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 }