github.com/jspc/eggos@v0.5.1-0.20221028160421-556c75c878a5/drivers/ps2/mouse/mouse.go (about)

     1  package mouse
     2  
     3  import (
     4  	"github.com/jspc/eggos/drivers/pic"
     5  	"github.com/jspc/eggos/drivers/ps2"
     6  	"github.com/jspc/eggos/kernel/trap"
     7  )
     8  
     9  const (
    10  	_IRQ_MOUSE = pic.IRQ_BASE + pic.LINE_MOUSE
    11  )
    12  
    13  var (
    14  	mouseCnt int
    15  
    16  	packet     [3]byte
    17  	status     byte
    18  	xpos, ypos int
    19  
    20  	eventch chan Packet
    21  )
    22  
    23  type Packet struct {
    24  	X, Y        int
    25  	Left, Right bool
    26  }
    27  
    28  func Cursor() (int, int) {
    29  	return xpos, ypos
    30  }
    31  
    32  func LeftClick() bool {
    33  	return status&0x01 != 0
    34  }
    35  
    36  func RightClick() bool {
    37  	return status&0x02 != 0
    38  }
    39  
    40  func intr() {
    41  	pic.EOI(_IRQ_MOUSE)
    42  	for {
    43  		st := ps2.ReadCmd()
    44  		// log.Infof("status:%08b", st)
    45  		if st&0x01 == 0 {
    46  			break
    47  		}
    48  		x := ps2.ReadDataNoWait()
    49  		// log.Infof("data:%08b", x)
    50  		handlePacket(x)
    51  	}
    52  }
    53  
    54  func handlePacket(v byte) {
    55  	switch mouseCnt {
    56  	case 0:
    57  		packet[0] = v
    58  		if v&0x08 == 0 {
    59  			return
    60  		}
    61  		mouseCnt++
    62  	case 1:
    63  		packet[1] = v
    64  		mouseCnt++
    65  	case 2:
    66  		packet[2] = v
    67  		mouseCnt = 0
    68  		// x overflow or y overflow, discard packet
    69  		if packet[0]&0xC0 != 0 {
    70  			return
    71  		}
    72  		status = packet[0]
    73  		xpos += xrel(status, int(packet[1]))
    74  		ypos -= yrel(status, int(packet[2]))
    75  
    76  		p := Packet{
    77  			X:     xpos,
    78  			Y:     ypos,
    79  			Left:  LeftClick(),
    80  			Right: RightClick(),
    81  		}
    82  		select {
    83  		case eventch <- p:
    84  		default:
    85  		}
    86  	}
    87  	// log.Infof("x:%d y:%d packet:%v status:%8b", xpos, ypos, packet, status)
    88  }
    89  
    90  func xrel(status byte, value int) int {
    91  	var ret byte
    92  	if status&0x10 != 0 {
    93  		ret |= 0x80
    94  	}
    95  	ret |= byte(value)
    96  	return int(int8(ret))
    97  }
    98  
    99  func yrel(status byte, value int) int {
   100  	var ret byte
   101  	if status&0x20 != 0 {
   102  		ret |= 0x80
   103  	}
   104  	ret |= byte(value)
   105  	return int(int8(ret))
   106  }
   107  
   108  func EventQueue() chan Packet {
   109  	return eventch
   110  }
   111  
   112  func Init() {
   113  	status := ps2.ReadCmd()
   114  	// enable mouse IRQ and port clock
   115  	status |= 0x22
   116  	// enable keyboard IRQ and port clock
   117  	status |= 0x11
   118  	// enable keyboard translation
   119  	status |= 0x40
   120  	ps2.WriteCmd(0x60)
   121  	ps2.WriteData(status, false)
   122  
   123  	// enable ps2 mouse port
   124  	ps2.WriteCmd(0xA8)
   125  
   126  	// enable ps2 keyboard port
   127  	ps2.WriteCmd(0xAE)
   128  
   129  	// enable mouse send packet
   130  	ps2.WriteMouseData(0xF4)
   131  
   132  	trap.Register(_IRQ_MOUSE, intr)
   133  	pic.EnableIRQ(pic.LINE_MOUSE)
   134  
   135  	eventch = make(chan Packet, 10)
   136  }