1 #include "ps2_mouse.h"
2 #include <driver/interrupt/apic/apic.h>
3 #include <mm/mm.h>
4 #include <mm/slab.h>
5 #include <common/printk.h>
6 #include <common/kprint.h>
7
8 static struct ps2_mouse_input_buffer *ps2_mouse_buf_ptr = NULL;
9 static int c = 0;
10 struct apic_IO_APIC_RTE_entry ps2_mouse_entry;
11 static unsigned char ps2_mouse_id = 0;
12 struct ps2_mouse_packet_3bytes pak;
13 static int ps2_mouse_count = 0;
14 /**
15 * @brief 清空缓冲区
16 *
17 */
ps2_mouse_clear_buf()18 static void ps2_mouse_clear_buf()
19 {
20 ps2_mouse_buf_ptr->ptr_head = ps2_mouse_buf_ptr->buffer;
21 ps2_mouse_buf_ptr->ptr_tail = ps2_mouse_buf_ptr->buffer;
22 ps2_mouse_buf_ptr->count = 0;
23 memset(ps2_mouse_buf_ptr->buffer, 0, ps2_mouse_buffer_size);
24 }
25
26 /**
27 * @brief 从缓冲队列中获取鼠标数据字节
28 * @return 鼠标数据包的字节
29 * 若缓冲队列为空则返回-1024
30 */
ps2_mouse_get_scancode()31 static int ps2_mouse_get_scancode()
32 {
33 // 缓冲队列为空
34 if (ps2_mouse_buf_ptr->count == 0)
35 while (!ps2_mouse_buf_ptr->count)
36 nop();
37
38 if (ps2_mouse_buf_ptr->ptr_tail == ps2_mouse_buf_ptr->buffer + ps2_mouse_buffer_size)
39 ps2_mouse_buf_ptr->ptr_tail = ps2_mouse_buf_ptr->buffer;
40
41 int ret = (int)((char)(*(ps2_mouse_buf_ptr->ptr_tail)));
42 --(ps2_mouse_buf_ptr->count);
43 ++(ps2_mouse_buf_ptr->ptr_tail);
44 // printk("count=%d", ps2_mouse_buf_ptr->count);
45
46 return ret;
47 }
48
49 /**
50 * @brief 鼠标中断处理函数(中断上半部)
51 * 将数据存入缓冲区
52 * @param irq_num 中断向量号
53 * @param param 参数
54 * @param regs 寄存器信息
55 */
ps2_mouse_handler(ul irq_num,ul param,struct pt_regs * regs)56 void ps2_mouse_handler(ul irq_num, ul param, struct pt_regs *regs)
57 {
58 // 读取鼠标输入的信息
59 unsigned char x = io_in8(PORT_KEYBOARD_DATA);
60
61 // 当头指针越过界时,恢复指向数组头部
62 if (ps2_mouse_buf_ptr->ptr_head == ps2_mouse_buf_ptr->buffer + ps2_mouse_buffer_size)
63 ps2_mouse_buf_ptr->ptr_head = ps2_mouse_buf_ptr->buffer;
64
65 if (ps2_mouse_buf_ptr->count >= ps2_mouse_buffer_size)
66 {
67 kwarn("ps2_mouse input buffer is full.");
68 return;
69 }
70
71 *ps2_mouse_buf_ptr->ptr_head = x;
72 ++(ps2_mouse_buf_ptr->count);
73 ++(ps2_mouse_buf_ptr->ptr_head);
74 printk("c=%d\tval = %d\n", ++c, x);
75 }
76
77 hardware_intr_controller ps2_mouse_intr_controller =
78 {
79 .enable = apic_ioapic_enable,
80 .disable = apic_ioapic_disable,
81 .install = apic_ioapic_install,
82 .uninstall = apic_ioapic_uninstall,
83 .ack = apic_ioapic_edge_ack,
84
85 };
86
87 /**
88 * @brief 从键盘控制器读取ps2_mouse id
89 *
90 * @return unsigned char 鼠标id
91 */
ps2_mouse_get_mouse_ID()92 static unsigned char ps2_mouse_get_mouse_ID()
93 {
94 // 读取鼠标的ID
95 io_out8(PORT_KEYBOARD_CONTROL, KEYBOARD_COMMAND_SEND_TO_PS2_MOUSE);
96 wait_keyboard_write();
97 io_out8(PORT_KEYBOARD_DATA, PS2_MOUSE_GET_ID);
98 wait_keyboard_write();
99 ps2_mouse_id = io_in8(PORT_KEYBOARD_DATA);
100 wait_keyboard_write();
101 io_in8(PORT_KEYBOARD_DATA);
102 for (int i = 0; i < 1000; i++)
103 for (int j = 0; j < 1000; j++)
104 nop();
105 return ps2_mouse_id;
106 }
107
108 /**
109 * @brief 设置鼠标采样率
110 *
111 * @param hz 采样率
112 */
ps2_mouse_set_sample_rate(unsigned int hz)113 int ps2_mouse_set_sample_rate(unsigned int hz)
114 {
115 switch (hz)
116 {
117 case 10:
118 case 20:
119 case 40:
120 case 60:
121 case 80:
122 case 100:
123 case 200:
124 wait_keyboard_write();
125 io_out8(PORT_KEYBOARD_CONTROL, KEYBOARD_COMMAND_SEND_TO_PS2_MOUSE);
126 wait_keyboard_write();
127 io_out8(PORT_KEYBOARD_DATA, PS2_MOUSE_SET_SAMPLING_RATE);
128 wait_keyboard_write();
129 io_in8(PORT_KEYBOARD_DATA);
130
131 for (int i = 0; i < 1000; i++)
132 for (int j = 0; j < 1000; j++)
133 nop();
134
135 io_out8(PORT_KEYBOARD_CONTROL, KEYBOARD_COMMAND_SEND_TO_PS2_MOUSE);
136 wait_keyboard_write();
137 io_out8(PORT_KEYBOARD_DATA, hz);
138 for (int i = 0; i < 1000; i++)
139 for (int j = 0; j < 1000; j++)
140 nop();
141 wait_keyboard_write();
142 io_in8(PORT_KEYBOARD_DATA);
143
144 break;
145
146 default:
147 return EINVALID_ARGUMENT;
148 break;
149 }
150 return SUCCESS;
151 }
152 /**
153 * @brief 使鼠标支持滚轮
154 * 该模式下,鼠标ID=3
155 */
ps2_mouse_enable_scroll_wheel()156 static int ps2_mouse_enable_scroll_wheel()
157 {
158 if (ps2_mouse_id == 3)
159 return SUCCESS;
160
161 ps2_mouse_set_sample_rate(200);
162 ps2_mouse_set_sample_rate(100);
163 ps2_mouse_set_sample_rate(80);
164 if (ps2_mouse_get_mouse_ID() != 3)
165 {
166 kerror("Cannot set mouse ID to 3");
167 return EFAIL;
168 }
169 // 清空缓冲区,防止解析时产生错误
170 ps2_mouse_clear_buf();
171 return SUCCESS;
172 }
173 /**
174 * @brief 使鼠标支持5键
175 * 该模式下ID=4
176 */
ps2_mouse_enable_5keys()177 static int ps2_mouse_enable_5keys()
178 {
179 if (ps2_mouse_id == 4)
180 return SUCCESS;
181 // 根据规范,应当先启用ID=3
182 ps2_mouse_enable_scroll_wheel();
183
184 ps2_mouse_set_sample_rate(200);
185 ps2_mouse_set_sample_rate(200);
186 ps2_mouse_set_sample_rate(80);
187 if (ps2_mouse_get_mouse_ID() != 4)
188 {
189 kerror("Cannot set ps2_mouse ID to 4");
190 return EFAIL;
191 }
192 // 清空缓冲区,防止解析时产生错误
193 ps2_mouse_clear_buf();
194
195 return SUCCESS;
196 }
197 /**
198 * @brief 初始化鼠标驱动程序
199 *
200 */
ps2_mouse_init()201 void ps2_mouse_init()
202 {
203 // 初始化鼠标读入队列缓冲区
204 ps2_mouse_buf_ptr = (struct ps2_mouse_input_buffer *)kzalloc(sizeof(struct ps2_mouse_input_buffer), 0);
205 ps2_mouse_buf_ptr->ptr_head = ps2_mouse_buf_ptr->buffer;
206 ps2_mouse_buf_ptr->ptr_tail = ps2_mouse_buf_ptr->buffer;
207 ps2_mouse_buf_ptr->count = 0;
208 memset(ps2_mouse_buf_ptr->buffer, 0, ps2_mouse_buffer_size);
209
210 // ======== 初始化中断RTE entry ==========
211
212 ps2_mouse_entry.vector = PS2_MOUSE_INTR_VECTOR; // 设置中断向量号
213 ps2_mouse_entry.deliver_mode = IO_APIC_FIXED; // 投递模式:混合
214 ps2_mouse_entry.dest_mode = DEST_PHYSICAL; // 物理模式投递中断
215 ps2_mouse_entry.deliver_status = IDLE;
216 ps2_mouse_entry.trigger_mode = EDGE_TRIGGER; // 设置边沿触发
217 ps2_mouse_entry.polarity = POLARITY_HIGH; // 高电平触发
218 ps2_mouse_entry.remote_IRR = IRR_RESET;
219 ps2_mouse_entry.mask = MASKED;
220 ps2_mouse_entry.reserved = 0;
221
222 ps2_mouse_entry.destination.physical.reserved1 = 0;
223 ps2_mouse_entry.destination.physical.reserved2 = 0;
224 ps2_mouse_entry.destination.physical.phy_dest = 0; // 设置投递到BSP处理器
225
226 // 注册中断处理程序
227 irq_register(PS2_MOUSE_INTR_VECTOR, &ps2_mouse_entry, &ps2_mouse_handler, (ul)ps2_mouse_buf_ptr, &ps2_mouse_intr_controller, "ps/2 mouse");
228
229 wait_keyboard_write();
230 io_out8(PORT_KEYBOARD_CONTROL, KEYBOARD_COMMAND_ENABLE_PS2_MOUSE_PORT); // 开启鼠标端口
231 for (int i = 0; i < 1000; i++)
232 for (int j = 0; j < 1000; j++)
233 nop();
234 wait_keyboard_write();
235 io_in8(PORT_KEYBOARD_DATA);
236
237 io_out8(PORT_KEYBOARD_CONTROL, KEYBOARD_COMMAND_SEND_TO_PS2_MOUSE);
238 wait_keyboard_write();
239 io_out8(PORT_KEYBOARD_DATA, PS2_MOUSE_ENABLE); // 允许鼠标设备发送数据包
240 wait_keyboard_write();
241 io_in8(PORT_KEYBOARD_DATA);
242
243 for (int i = 0; i < 1000; i++)
244 for (int j = 0; j < 1000; j++)
245 nop();
246 wait_keyboard_write();
247 io_out8(PORT_KEYBOARD_CONTROL, KEYBOARD_COMMAND_WRITE);
248 wait_keyboard_write();
249 io_out8(PORT_KEYBOARD_DATA, KEYBOARD_PARAM_INIT); // 设置键盘控制器
250 wait_keyboard_write();
251 io_in8(PORT_KEYBOARD_DATA);
252 for (int i = 0; i < 1000; i++)
253 for (int j = 0; j < 1000; j++)
254 nop();
255 wait_keyboard_write();
256 //ps2_mouse_enable_5keys();
257 ps2_mouse_get_mouse_ID();
258 ps2_mouse_set_sample_rate(30);
259 ps2_mouse_clear_buf();
260 kdebug("ps2_mouse ID:%d", ps2_mouse_id);
261 c = 0;
262 //ps2_mouse_count = 1;
263 }
264
265 /**
266 * @brief 卸载鼠标驱动程序
267 *
268 */
ps2_mouse_exit()269 void ps2_mouse_exit()
270 {
271 irq_unregister(PS2_MOUSE_INTR_VECTOR);
272 kfree((ul *)ps2_mouse_buf_ptr);
273 }
274
275 /**
276 * @brief 获取鼠标数据包
277 *
278 * @param packet 数据包的返回值
279 * @return int 错误码
280 */
ps2_mouse_get_packet(void * packet)281 int ps2_mouse_get_packet(void *packet)
282 {
283 // if (ps2_mouse_buf_ptr->count != 0)
284 // kdebug("at get packet: count=%d", ps2_mouse_buf_ptr->count);
285 int code = 0;
286 switch (ps2_mouse_id)
287 {
288 case 0: // 3bytes 数据包
289 if (ps2_mouse_buf_ptr->count < 4)
290 return EFAIL;
291 do
292 {
293 code = ps2_mouse_get_scancode();
294 ((struct ps2_mouse_packet_3bytes *)packet)->byte0 = (unsigned char)code;
295 } while (code == -1024);
296
297 do
298 {
299 code = ps2_mouse_get_scancode();
300 ((struct ps2_mouse_packet_3bytes *)packet)->movement_x = (char)code;
301 } while (code == -1024);
302
303 do
304 {
305 code = ps2_mouse_get_scancode();
306 ((struct ps2_mouse_packet_3bytes *)packet)->movement_y = (char)code;
307 } while (code == -1024);
308
309 return SUCCESS;
310 break;
311
312 case 3: // 4bytes数据包
313 case 4:
314 if (ps2_mouse_buf_ptr->count < 5)
315 return EFAIL;
316 do
317 {
318 code = ps2_mouse_get_scancode();
319 ((struct ps2_mouse_packet_4bytes *)packet)->byte0 = (unsigned char)code;
320 } while (code == -1024);
321
322 do
323 {
324 code = ps2_mouse_get_scancode();
325 ((struct ps2_mouse_packet_4bytes *)packet)->movement_x = (char)code;
326 } while (code == -1024);
327
328 do
329 {
330 code = ps2_mouse_get_scancode();
331 ((struct ps2_mouse_packet_4bytes *)packet)->movement_y = (char)code;
332 } while (code == -1024);
333
334 do
335 {
336 code = ps2_mouse_get_scancode();
337 ((struct ps2_mouse_packet_4bytes *)packet)->byte3 = (char)code;
338 } while (code == -1024);
339
340 return SUCCESS;
341 break;
342
343 default: // Should not reach here
344 kBUG("ps2_mouse_get_packet(): Invalid ps2_mouse_id!");
345 return EFAIL;
346 break;
347 }
348 return SUCCESS;
349 }
350
analyze_mousecode()351 void analyze_mousecode()
352 {
353 if(!ps2_mouse_buf_ptr->count)
354 return;
355 else printk_color(ORANGE, BLACK, "COUNT=%d\n", ps2_mouse_buf_ptr->count);
356 unsigned char x = ps2_mouse_get_scancode();
357
358 switch (ps2_mouse_count)
359 {
360 case 0:
361 ps2_mouse_count++;
362 break;
363
364 case 1:
365 pak.byte0 = x;
366 ps2_mouse_count++;
367 break;
368
369 case 2:
370 pak.movement_x = (char)x;
371 ps2_mouse_count++;
372 break;
373
374 case 3:
375 pak.movement_y = (char)x;
376 ps2_mouse_count = 1;
377
378 printk_color(RED, GREEN, "(M:%02x,X:%3d,Y:%3d)\tcount=%d\n", pak.byte0, pak.movement_x, pak.movement_y, ps2_mouse_buf_ptr->count);
379 break;
380
381 default:
382 break;
383 }
384 }