feat(input): PS/2 鼠标启用 IntelliMouse 滚轮
- init 发送 200/100/80 魔数并读取设备 ID;ID=3/4 时切到 4 字节包 - IRQ 的 4 字节模式解析第 4 字节低 4 位为有符号 Z 增量; 标准 3 字节模式 wheel 恒 0 - mouse_packet 增加 wheel:int8 - /dev/input/mouse 布局扩展:[9] = wheel(int8),read 返回 10; 调用方缓冲不足 10 字节时仍返回旧的 9 字节布局
This commit is contained in:
1 parent
5e2598a992
commit
5405a34a24
2 files changed
+48
-3
No files matched your search
@@ -466,6 +466,11 @@ virtual class mouse_device(devfs_file):
|
||||
dy = 0 - dy
|
||||
int32*(buf)[0] = int32(dx)
|
||||
int32*(buf)[1] = int32(dy)
|
||||
# [9] = 滚轮增量(int8,IntelliMouse;标准 3 字节鼠标恒 0)
|
||||
if size >= 10:
|
||||
wbuf: int8* = int8*(uint64(buffer) + 9)
|
||||
wbuf[0] = pkt.wheel
|
||||
return 10
|
||||
return 9
|
||||
return 1
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ class mouse_packet:
|
||||
dx: uint8 # 原始幅值字节(符号在 flags.bit4)
|
||||
dy: uint8 # 原始幅值字节(符号在 flags.bit5)
|
||||
buttons: uint8
|
||||
wheel: int8 # IntelliMouse 第 4 字节低 4 位的 Z 增量(3 字节模式恒 0)
|
||||
|
||||
packets: [MOUSE_BUF_SIZE]mouse_packet
|
||||
static pack_head: uint32 = 0
|
||||
@@ -29,6 +30,9 @@ static cycle: uint8 = 0
|
||||
static byte1: uint8 = 0
|
||||
static byte2: uint8 = 0
|
||||
static byte3: uint8 = 0
|
||||
static byte4: uint8 = 0
|
||||
# 0 = 标准 3 字节 PS/2 包;1 = IntelliMouse 4 字节包(第 4 字节带滚轮)
|
||||
static wheel_mode: int = 0
|
||||
|
||||
static mouse_x: int32 = 0
|
||||
static mouse_y: int32 = 0
|
||||
@@ -52,8 +56,12 @@ def _write_cmd(cmd: uint8):
|
||||
_wait_read()
|
||||
asm.inb(MOUSE_DATA)
|
||||
|
||||
def _read_data() -> uint8:
|
||||
_wait_read()
|
||||
return asm.inb(MOUSE_DATA)
|
||||
|
||||
def irq_handler() -> int:
|
||||
global cycle, byte1, byte2, byte3, pack_tail, pack_count, mse_irq_cnt
|
||||
global cycle, byte1, byte2, byte3, byte4, pack_tail, pack_count, mse_irq_cnt
|
||||
mse_irq_cnt += 1
|
||||
status: uint8 = asm.inb(MOUSE_STATUS)
|
||||
if (status & 0x20) == 0: return 0
|
||||
@@ -67,17 +75,30 @@ def irq_handler() -> int:
|
||||
byte2 = data
|
||||
cycle = 2
|
||||
return 0
|
||||
byte3 = data
|
||||
cycle = 0
|
||||
if cycle == 2:
|
||||
byte3 = data
|
||||
if wheel_mode != 0:
|
||||
cycle = 3
|
||||
return 0
|
||||
cycle = 0
|
||||
else:
|
||||
byte4 = data
|
||||
cycle = 0
|
||||
# 丢弃带溢出位的包(bit6/bit7 = X/Y overflow):此时设备给的是饱和值,
|
||||
# 直接采用会产生 ±127 级跳变(表现为光标“飞”)。
|
||||
if (byte1 & 0xC0) != 0:
|
||||
return 0
|
||||
# IntelliMouse 第 4 字节低 4 位是有符号 Z 增量(4-bit two's complement)。
|
||||
w: int = 0
|
||||
if wheel_mode != 0:
|
||||
w = int(byte4 & uint8(0x0F))
|
||||
if w >= 8: w = w - 16
|
||||
if pack_count < MOUSE_BUF_SIZE:
|
||||
packets[pack_tail].flags = byte1
|
||||
packets[pack_tail].dx = byte2
|
||||
packets[pack_tail].dy = byte3
|
||||
packets[pack_tail].buttons = byte1 & uint8(0x07)
|
||||
packets[pack_tail].wheel = int8(w)
|
||||
pack_tail = pack_tail + 1
|
||||
if pack_tail >= MOUSE_BUF_SIZE:
|
||||
pack_tail = 0
|
||||
@@ -93,11 +114,13 @@ def read_packet(out: mouse_packet*) -> int:
|
||||
out.dx = 0
|
||||
out.dy = 0
|
||||
out.buttons = 0
|
||||
out.wheel = 0
|
||||
return -1
|
||||
out.flags = packets[pack_head].flags
|
||||
out.dx = packets[pack_head].dx
|
||||
out.dy = packets[pack_head].dy
|
||||
out.buttons = packets[pack_head].buttons
|
||||
out.wheel = packets[pack_head].wheel
|
||||
pack_head = pack_head + 1
|
||||
if pack_head >= MOUSE_BUF_SIZE:
|
||||
pack_head = 0
|
||||
@@ -118,6 +141,8 @@ def get_buttons() -> uint8:
|
||||
return mouse_buttons
|
||||
|
||||
def init():
|
||||
global wheel_mode
|
||||
wheel_mode = 0
|
||||
_wait_write()
|
||||
asm.outb(MOUSE_COMMAND, 0xA8)
|
||||
# 读-改-写 CCB 期间屏蔽 IRQ1:与 keyboard.init 同理 —— 0x20 读 CCB 会把 CCB 值放进
|
||||
@@ -136,6 +161,21 @@ def init():
|
||||
asm.outb(MOUSE_DATA, status)
|
||||
pic.clearMask(1)
|
||||
_write_cmd(0xF6)
|
||||
# IntelliMouse 魔数:采样率 200 → 100 → 80。成功后设备 ID 变成 3(滚轮)
|
||||
# 或 4(滚轮 + 侧键),之后每个包变成 4 字节(第 4 字节低 4 位是 Z 增量)。
|
||||
_write_cmd(0xF3)
|
||||
_write_cmd(200)
|
||||
_write_cmd(0xF3)
|
||||
_write_cmd(100)
|
||||
_write_cmd(0xF3)
|
||||
_write_cmd(80)
|
||||
_write_cmd(0xF2)
|
||||
dev_id: uint8 = _read_data()
|
||||
if dev_id == uint8(3) or dev_id == uint8(4):
|
||||
wheel_mode = 1
|
||||
# 魔数序列会把采样率停在 80;恢复正常采样率 100 后再设分辨率/使能。
|
||||
_write_cmd(0xF3)
|
||||
_write_cmd(100)
|
||||
# 分辨率设为 8 counts/mm:0xF6(Set Defaults) 会把它重置为最粗的 4 counts/mm,
|
||||
# 于是每个计数对应的位移偏大。设细一档后光标更稳、不易“飞”。
|
||||
_write_cmd(0xE8)
|
||||
|
||||
Reference in new issue
Block a user