mouse.c 9.6 KB

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