ps2_keyboard.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507
  1. #include "ps2_keyboard.h"
  2. #include "../interrupt/apic/apic.h"
  3. #include "../../mm/mm.h"
  4. #include "../../mm/slab.h"
  5. #include "../../common/printk.h"
  6. #include <filesystem/VFS/VFS.h>
  7. #include <process/wait_queue.h>
  8. // 键盘输入缓冲区
  9. static struct ps2_keyboard_input_buffer *kb_buf_ptr = NULL;
  10. // 缓冲区等待队列
  11. static wait_queue_node_t ps2_keyboard_wait_queue;
  12. // 功能键标志变量
  13. static bool shift_l, shift_r, ctrl_l, ctrl_r, alt_l, alt_r;
  14. static bool gui_l, gui_r, apps, insert, home, pgup, del, end, pgdn, arrow_u, arrow_l, arrow_d, arrow_r;
  15. static bool kp_forward_slash, kp_en;
  16. /**
  17. * @brief 重置ps2键盘输入缓冲区
  18. *
  19. * @param kbp 缓冲区对象指针
  20. */
  21. static void ps2_keyboard_reset_buffer(struct ps2_keyboard_input_buffer *kbp)
  22. {
  23. kbp->ptr_head = kb_buf_ptr->buffer;
  24. kbp->ptr_tail = kb_buf_ptr->buffer;
  25. kbp->count = 0;
  26. // 清空输入缓冲区
  27. memset(kbp->buffer, 0, ps2_keyboard_buffer_size);
  28. }
  29. struct apic_IO_APIC_RTE_entry entry;
  30. hardware_intr_controller ps2_keyboard_intr_controller =
  31. {
  32. .enable = apic_ioapic_enable,
  33. .disable = apic_ioapic_disable,
  34. .install = apic_ioapic_install,
  35. .uninstall = apic_ioapic_uninstall,
  36. .ack = apic_ioapic_edge_ack,
  37. };
  38. /**
  39. * @brief 打开键盘文件
  40. *
  41. * @param inode 所在的inode
  42. * @param filp 文件指针
  43. * @return long
  44. */
  45. long ps2_keyboard_open(struct vfs_index_node_t *inode, struct vfs_file_t *filp)
  46. {
  47. filp->private_data = (void *)kb_buf_ptr;
  48. ps2_keyboard_reset_buffer(kb_buf_ptr);
  49. return 0;
  50. }
  51. /**
  52. * @brief 关闭键盘文件
  53. *
  54. * @param inode 所在的inode
  55. * @param filp 文件指针
  56. * @return long
  57. */
  58. long ps2_keyboard_close(struct vfs_index_node_t *inode, struct vfs_file_t *filp)
  59. {
  60. filp->private_data = NULL;
  61. ps2_keyboard_reset_buffer(kb_buf_ptr);
  62. return 0;
  63. }
  64. /**
  65. * @brief 键盘io控制接口
  66. *
  67. * @param inode 所在的inode
  68. * @param filp 键盘文件指针
  69. * @param cmd 命令
  70. * @param arg 参数
  71. * @return long
  72. */
  73. long ps2_keyboard_ioctl(struct vfs_index_node_t *inode, struct vfs_file_t *filp, uint64_t cmd, uint64_t arg)
  74. {
  75. switch (cmd)
  76. {
  77. case KEYBOARD_CMD_RESET_BUFFER:
  78. ps2_keyboard_reset_buffer(kb_buf_ptr);
  79. break;
  80. default:
  81. break;
  82. }
  83. return 0;
  84. }
  85. /**
  86. * @brief 读取键盘文件的操作接口
  87. *
  88. * @param filp 文件指针
  89. * @param buf 输出缓冲区
  90. * @param count 要读取的字节数
  91. * @param position 读取的位置
  92. * @return long 读取的字节数
  93. */
  94. long ps2_keyboard_read(struct vfs_file_t *filp, char *buf, int64_t count, long *position)
  95. {
  96. // 缓冲区为空则等待
  97. if (kb_buf_ptr->count == 0)
  98. wait_queue_sleep_on(&ps2_keyboard_wait_queue);
  99. long counter = kb_buf_ptr->count >= count ? count : kb_buf_ptr->count;
  100. uint8_t *tail = kb_buf_ptr->ptr_tail;
  101. // 要读取的部分没有越过缓冲区末尾
  102. if (counter <= (kb_buf_ptr->buffer + ps2_keyboard_buffer_size - tail))
  103. {
  104. copy_to_user(buf, tail, counter);
  105. kb_buf_ptr->ptr_tail += counter;
  106. }
  107. else // 要读取的部分越过了缓冲区的末尾,进行循环
  108. {
  109. uint64_t tmp = (kb_buf_ptr->buffer + ps2_keyboard_buffer_size - tail);
  110. copy_to_user(buf, tail, tmp);
  111. copy_to_user(buf, kb_buf_ptr->ptr_head, counter - tmp);
  112. kb_buf_ptr->ptr_tail = kb_buf_ptr->ptr_head + (counter - tmp);
  113. }
  114. kb_buf_ptr->count -= counter;
  115. return counter;
  116. }
  117. /**
  118. * @brief 键盘文件写入接口(无作用,空)
  119. *
  120. * @param filp
  121. * @param buf
  122. * @param count
  123. * @param position
  124. * @return long
  125. */
  126. long ps2_keyboard_write(struct vfs_file_t *filp, char *buf, int64_t count, long *position)
  127. {
  128. return 0;
  129. }
  130. /**
  131. * @brief ps2键盘驱动的虚拟文件接口
  132. *
  133. */
  134. struct vfs_file_operations_t ps2_keyboard_fops =
  135. {
  136. .open = ps2_keyboard_open,
  137. .close = ps2_keyboard_close,
  138. .ioctl = ps2_keyboard_ioctl,
  139. .read = ps2_keyboard_read,
  140. .write = ps2_keyboard_write,
  141. };
  142. /**
  143. * @brief 键盘中断处理函数(中断上半部)
  144. * 将数据存入缓冲区
  145. * @param irq_num 中断向量号
  146. * @param param 参数
  147. * @param regs 寄存器信息
  148. */
  149. void ps2_keyboard_handler(ul irq_num, ul param, struct pt_regs *regs)
  150. {
  151. // 读取键盘输入的信息
  152. unsigned char x = io_in8(PORT_PS2_KEYBOARD_DATA);
  153. // printk_color(ORANGE, BLACK, "key_pressed:%02x\n", x);
  154. // 当头指针越过界时,恢复指向数组头部
  155. if (kb_buf_ptr->ptr_head == kb_buf_ptr->buffer + ps2_keyboard_buffer_size)
  156. kb_buf_ptr->ptr_head = kb_buf_ptr->buffer;
  157. if (kb_buf_ptr->count >= ps2_keyboard_buffer_size)
  158. {
  159. kwarn("ps2_keyboard input buffer is full.");
  160. return;
  161. }
  162. *kb_buf_ptr->ptr_head = x;
  163. ++(kb_buf_ptr->count);
  164. ++(kb_buf_ptr->ptr_head);
  165. wait_queue_wakeup(&ps2_keyboard_wait_queue, PROC_UNINTERRUPTIBLE);
  166. }
  167. /**
  168. * @brief 初始化键盘驱动程序的函数
  169. *
  170. */
  171. void ps2_keyboard_init()
  172. {
  173. // ======= 初始化键盘循环队列缓冲区 ===========
  174. // 申请键盘循环队列缓冲区的内存
  175. kb_buf_ptr = (struct ps2_keyboard_input_buffer *)kmalloc(sizeof(struct ps2_keyboard_input_buffer), 0);
  176. kb_buf_ptr->ptr_head = kb_buf_ptr->buffer;
  177. kb_buf_ptr->ptr_tail = kb_buf_ptr->buffer;
  178. kb_buf_ptr->count = 0;
  179. memset(kb_buf_ptr->buffer, 0, ps2_keyboard_buffer_size);
  180. // ======== 初始化中断RTE entry ==========
  181. entry.vector = PS2_KEYBOARD_INTR_VECTOR; // 设置中断向量号
  182. entry.deliver_mode = IO_APIC_FIXED; // 投递模式:混合
  183. entry.dest_mode = DEST_PHYSICAL; // 物理模式投递中断
  184. entry.deliver_status = IDLE;
  185. entry.trigger_mode = EDGE_TRIGGER; // 设置边沿触发
  186. entry.polarity = POLARITY_HIGH; // 高电平触发
  187. entry.remote_IRR = IRR_RESET;
  188. entry.mask = MASKED;
  189. entry.reserved = 0;
  190. entry.destination.physical.reserved1 = 0;
  191. entry.destination.physical.reserved2 = 0;
  192. entry.destination.physical.phy_dest = 0; // 设置投递到BSP处理器
  193. // ======== 初始化键盘控制器,写入配置值 =========
  194. wait_ps2_keyboard_write();
  195. io_out8(PORT_PS2_KEYBOARD_CONTROL, PS2_KEYBOARD_COMMAND_WRITE);
  196. wait_ps2_keyboard_write();
  197. io_out8(PORT_PS2_KEYBOARD_DATA, PS2_KEYBOARD_PARAM_INIT);
  198. wait_ps2_keyboard_write();
  199. // 执行一百万次nop,等待键盘控制器把命令执行完毕
  200. for (int i = 0; i < 1000; ++i)
  201. for (int j = 0; j < 1000; ++j)
  202. nop();
  203. shift_l = false;
  204. shift_r = false;
  205. ctrl_l = false;
  206. ctrl_r = false;
  207. alt_l = false;
  208. alt_r = false;
  209. wait_queue_init(&ps2_keyboard_wait_queue, NULL);
  210. // 注册中断处理程序
  211. irq_register(PS2_KEYBOARD_INTR_VECTOR, &entry, &ps2_keyboard_handler, (ul)kb_buf_ptr, &ps2_keyboard_intr_controller, "ps/2 keyboard");
  212. kdebug("kb registered.");
  213. }
  214. /**
  215. * @brief 键盘驱动卸载函数
  216. *
  217. */
  218. void ps2_keyboard_exit()
  219. {
  220. irq_unregister(PS2_KEYBOARD_INTR_VECTOR);
  221. kfree((ul *)kb_buf_ptr);
  222. }
  223. /**
  224. * @brief 解析键盘扫描码
  225. *
  226. */
  227. void ps2_keyboard_analyze_keycode()
  228. {
  229. bool flag_make = false;
  230. int c = ps2_keyboard_get_scancode();
  231. // 循环队列为空
  232. if (c == -1)
  233. return;
  234. unsigned char scancode = (unsigned char)c;
  235. int key = 0;
  236. if (scancode == 0xE1) // Pause Break
  237. {
  238. key = PAUSE_BREAK;
  239. // 清除缓冲区中剩下的扫描码
  240. for (int i = 1; i < 6; ++i)
  241. if (ps2_keyboard_get_scancode() != pause_break_scan_code[i])
  242. {
  243. key = 0;
  244. break;
  245. }
  246. }
  247. else if (scancode == 0xE0) // 功能键, 有多个扫描码
  248. {
  249. // 获取下一个扫描码
  250. scancode = ps2_keyboard_get_scancode();
  251. switch (scancode)
  252. {
  253. case 0x2a: // print screen 按键被按下
  254. if (ps2_keyboard_get_scancode() == 0xe0)
  255. if (ps2_keyboard_get_scancode() == 0x37)
  256. {
  257. key = PRINT_SCREEN;
  258. flag_make = true;
  259. }
  260. break;
  261. case 0xb7: // print screen 按键被松开
  262. if (ps2_keyboard_get_scancode() == 0xe0)
  263. if (ps2_keyboard_get_scancode() == 0xaa)
  264. {
  265. key = PRINT_SCREEN;
  266. flag_make = false;
  267. }
  268. break;
  269. case 0x1d: // 按下右边的ctrl
  270. ctrl_r = true;
  271. key = OTHER_KEY;
  272. break;
  273. case 0x9d: // 松开右边的ctrl
  274. ctrl_r = false;
  275. key = OTHER_KEY;
  276. break;
  277. case 0x38: // 按下右边的alt
  278. alt_r = true;
  279. key = OTHER_KEY;
  280. break;
  281. case 0xb8: // 松开右边的alt
  282. alt_r = false;
  283. key = OTHER_KEY;
  284. break;
  285. case 0x5b:
  286. gui_l = true;
  287. key = OTHER_KEY;
  288. break;
  289. case 0xdb:
  290. gui_l = false;
  291. key = OTHER_KEY;
  292. break;
  293. case 0x5c:
  294. gui_r = true;
  295. key = OTHER_KEY;
  296. break;
  297. case 0xdc:
  298. gui_r = false;
  299. key = OTHER_KEY;
  300. break;
  301. case 0x5d:
  302. apps = true;
  303. key = OTHER_KEY;
  304. break;
  305. case 0xdd:
  306. apps = false;
  307. key = OTHER_KEY;
  308. break;
  309. case 0x52:
  310. insert = true;
  311. key = OTHER_KEY;
  312. break;
  313. case 0xd2:
  314. insert = false;
  315. key = OTHER_KEY;
  316. break;
  317. case 0x47:
  318. home = true;
  319. key = OTHER_KEY;
  320. break;
  321. case 0xc7:
  322. home = false;
  323. key = OTHER_KEY;
  324. break;
  325. case 0x49:
  326. pgup = true;
  327. key = OTHER_KEY;
  328. break;
  329. case 0xc9:
  330. pgup = false;
  331. key = OTHER_KEY;
  332. break;
  333. case 0x53:
  334. del = true;
  335. key = OTHER_KEY;
  336. break;
  337. case 0xd3:
  338. del = false;
  339. key = OTHER_KEY;
  340. break;
  341. case 0x4f:
  342. end = true;
  343. key = OTHER_KEY;
  344. break;
  345. case 0xcf:
  346. end = false;
  347. key = OTHER_KEY;
  348. break;
  349. case 0x51:
  350. pgdn = true;
  351. key = OTHER_KEY;
  352. break;
  353. case 0xd1:
  354. pgdn = false;
  355. key = OTHER_KEY;
  356. break;
  357. case 0x48:
  358. arrow_u = true;
  359. key = OTHER_KEY;
  360. break;
  361. case 0xc8:
  362. arrow_u = false;
  363. key = OTHER_KEY;
  364. break;
  365. case 0x4b:
  366. arrow_l = true;
  367. key = OTHER_KEY;
  368. break;
  369. case 0xcb:
  370. arrow_l = false;
  371. key = OTHER_KEY;
  372. break;
  373. case 0x50:
  374. arrow_d = true;
  375. key = OTHER_KEY;
  376. break;
  377. case 0xd0:
  378. arrow_d = false;
  379. key = OTHER_KEY;
  380. break;
  381. case 0x4d:
  382. arrow_r = true;
  383. key = OTHER_KEY;
  384. break;
  385. case 0xcd:
  386. arrow_r = false;
  387. key = OTHER_KEY;
  388. break;
  389. case 0x35: // 数字小键盘的 / 符号
  390. kp_forward_slash = true;
  391. key = OTHER_KEY;
  392. break;
  393. case 0xb5:
  394. kp_forward_slash = false;
  395. key = OTHER_KEY;
  396. break;
  397. case 0x1c:
  398. kp_en = true;
  399. key = OTHER_KEY;
  400. break;
  401. case 0x9c:
  402. kp_en = false;
  403. key = OTHER_KEY;
  404. break;
  405. default:
  406. key = OTHER_KEY;
  407. break;
  408. }
  409. }
  410. if (key == 0) // 属于第三类扫描码
  411. {
  412. // 判断按键是被按下还是抬起
  413. flag_make = ((scancode & FLAG_BREAK) ? 0 : 1);
  414. // 计算扫描码位于码表的第几行
  415. uint *key_row = &keycode_map_normal[(scancode & 0x7f) * MAP_COLS];
  416. unsigned char col = 0;
  417. // shift被按下
  418. if (shift_l || shift_r)
  419. col = 1;
  420. key = key_row[col];
  421. switch (scancode & 0x7f)
  422. {
  423. case 0x2a:
  424. shift_l = flag_make;
  425. key = 0;
  426. break;
  427. case 0x36:
  428. shift_r = flag_make;
  429. key = 0;
  430. break;
  431. case 0x1d:
  432. ctrl_l = flag_make;
  433. key = 0;
  434. break;
  435. case 0x38:
  436. ctrl_r = flag_make;
  437. key = 0;
  438. break;
  439. default:
  440. if (!flag_make)
  441. key = 0;
  442. break;
  443. }
  444. if (key)
  445. printk_color(ORANGE, BLACK, "%c", key);
  446. }
  447. }
  448. /**
  449. * @brief 从缓冲队列中获取键盘扫描码
  450. *
  451. */
  452. int ps2_keyboard_get_scancode()
  453. {
  454. // 缓冲队列为空
  455. if (kb_buf_ptr->count == 0)
  456. return -1;
  457. if (kb_buf_ptr->ptr_tail == kb_buf_ptr->buffer + ps2_keyboard_buffer_size)
  458. kb_buf_ptr->ptr_tail = kb_buf_ptr->buffer;
  459. int ret = (int)(*(kb_buf_ptr->ptr_tail));
  460. --(kb_buf_ptr->count);
  461. ++(kb_buf_ptr->ptr_tail);
  462. return ret;
  463. }