keyboard.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. /*
  2. * Copyright (c) 2006-2018, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2006-09-15 QiuYi the first version
  9. * 2017-08-16 Parai the 2nd version
  10. */
  11. #include <rtthread.h>
  12. #include <rthw.h>
  13. #include <bsp.h>
  14. #include "keyboard.h"
  15. #include "keymap.h"
  16. #define FALSE RT_FALSE
  17. #define TRUE RT_TRUE
  18. #define PRIVATE static
  19. #define PUBLIC
  20. #define t_bool rt_bool_t
  21. #define t_8 rt_uint8_t
  22. #define t_32 rt_uint32_t
  23. PRIVATE KB_INPUT kb_in;
  24. PRIVATE t_bool code_with_E0 = FALSE;
  25. PRIVATE t_bool shift_l; /* l shift state */
  26. PRIVATE t_bool shift_r; /* r shift state */
  27. PRIVATE t_bool alt_l; /* l alt state */
  28. PRIVATE t_bool alt_r; /* r left state */
  29. PRIVATE t_bool ctrl_l; /* l ctrl state */
  30. PRIVATE t_bool ctrl_r; /* l ctrl state */
  31. PRIVATE t_bool caps_lock; /* Caps Lock */
  32. PRIVATE t_bool num_lock; /* Num Lock */
  33. PRIVATE t_bool scroll_lock; /* Scroll Lock */
  34. PRIVATE int column = 0; /* keyrow[column] is one value of keymap */
  35. PRIVATE t_8 get_byte_from_kb_buf();
  36. PRIVATE void set_leds();
  37. PRIVATE void kb_wait();
  38. PRIVATE void kb_ack();
  39. PUBLIC void init_keyboard()
  40. {
  41. kb_in.count = 0;
  42. kb_in.p_head = kb_in.p_tail = kb_in.buf;
  43. caps_lock = 0;
  44. num_lock = 1;
  45. scroll_lock = 0;
  46. set_leds();
  47. }
  48. PUBLIC rt_bool_t keyboard_read(rt_uint32_t *pkey)
  49. {
  50. t_8 scan_code;
  51. t_bool make; /* TRUE : make */
  52. /* FALSE: break */
  53. t_32 key = 0;
  54. t_32* keyrow;
  55. if(kb_in.count > 0){
  56. code_with_E0 = FALSE;
  57. scan_code = get_byte_from_kb_buf();
  58. /* start scan */
  59. if (scan_code == 0xE1) {
  60. int i;
  61. static const t_8 pausebreak_scan_code[] = {0xE1, 0x1D, 0x45, 0xE1, 0x9D, 0xC5};
  62. t_bool is_pausebreak = TRUE;
  63. for(i=1;i<6;i++){
  64. if (get_byte_from_kb_buf() != pausebreak_scan_code[i]) {
  65. is_pausebreak = FALSE;
  66. break;
  67. }
  68. }
  69. if (is_pausebreak) {
  70. key = PAUSEBREAK;
  71. }
  72. }
  73. else if (scan_code == 0xE0) {
  74. code_with_E0 = TRUE;
  75. scan_code = get_byte_from_kb_buf();
  76. /* PrintScreen pressed */
  77. if (scan_code == 0x2A) {
  78. code_with_E0 = FALSE;
  79. if ((scan_code = get_byte_from_kb_buf()) == 0xE0) {
  80. code_with_E0 = TRUE;
  81. if ((scan_code = get_byte_from_kb_buf()) == 0x37) {
  82. key = PRINTSCREEN;
  83. make = TRUE;
  84. }
  85. }
  86. }
  87. /* PrintScreen released */
  88. else if (scan_code == 0xB7) {
  89. code_with_E0 = FALSE;
  90. if ((scan_code = get_byte_from_kb_buf()) == 0xE0) {
  91. code_with_E0 = TRUE;
  92. if ((scan_code = get_byte_from_kb_buf()) == 0xAA) {
  93. key = PRINTSCREEN;
  94. make = FALSE;
  95. }
  96. }
  97. }
  98. } /* if is not PrintScreen, scan_code is the one after 0xE0 */
  99. if ((key != PAUSEBREAK) && (key != PRINTSCREEN)) {
  100. /* is Make Code or Break Code */
  101. make = (scan_code & FLAG_BREAK ? FALSE : TRUE);
  102. keyrow = &keymap[(scan_code & 0x7F) * MAP_COLS];
  103. column = 0;
  104. t_bool caps = shift_l || shift_r;
  105. if (caps_lock) {
  106. if ((keyrow[0] >= 'a') && (keyrow[0] <= 'z')){
  107. caps = !caps;
  108. }
  109. }
  110. if (caps) {
  111. column = 1;
  112. }
  113. if (code_with_E0) {
  114. column = 2;
  115. }
  116. key = keyrow[column];
  117. switch(key) {
  118. case SHIFT_L:
  119. shift_l = make;
  120. break;
  121. case SHIFT_R:
  122. shift_r = make;
  123. break;
  124. case CTRL_L:
  125. ctrl_l = make;
  126. break;
  127. case CTRL_R:
  128. ctrl_r = make;
  129. break;
  130. case ALT_L:
  131. alt_l = make;
  132. break;
  133. case ALT_R:
  134. alt_l = make;
  135. break;
  136. case CAPS_LOCK:
  137. if (make) {
  138. caps_lock = !caps_lock;
  139. set_leds();
  140. }
  141. break;
  142. case NUM_LOCK:
  143. if (make) {
  144. num_lock = !num_lock;
  145. set_leds();
  146. }
  147. break;
  148. case SCROLL_LOCK:
  149. if (make) {
  150. scroll_lock = !scroll_lock;
  151. set_leds();
  152. }
  153. break;
  154. default:
  155. break;
  156. }
  157. }
  158. if(make){ /* ignore Break Code */
  159. t_bool pad = FALSE;
  160. /* handle the small pad first */
  161. if ((key >= PAD_SLASH) && (key <= PAD_9)) {
  162. pad = TRUE;
  163. switch(key) { /* '/', '*', '-', '+', and 'Enter' in num pad */
  164. case PAD_SLASH:
  165. key = '/';
  166. break;
  167. case PAD_STAR:
  168. key = '*';
  169. break;
  170. case PAD_MINUS:
  171. key = '-';
  172. break;
  173. case PAD_PLUS:
  174. key = '+';
  175. break;
  176. case PAD_ENTER:
  177. key = ENTER;
  178. break;
  179. default: /* keys whose value depends on the NumLock */
  180. if (num_lock) { /* '0' ~ '9' and '.' in num pad */
  181. if ((key >= PAD_0) && (key <= PAD_9)) {
  182. key = key - PAD_0 + '0';
  183. }
  184. else if (key == PAD_DOT) {
  185. key = '.';
  186. }
  187. }
  188. else{
  189. switch(key) {
  190. case PAD_HOME:
  191. key = HOME;
  192. break;
  193. case PAD_END:
  194. key = END;
  195. break;
  196. case PAD_PAGEUP:
  197. key = PAGEUP;
  198. break;
  199. case PAD_PAGEDOWN:
  200. key = PAGEDOWN;
  201. break;
  202. case PAD_INS:
  203. key = INSERT;
  204. break;
  205. case PAD_UP:
  206. key = UP;
  207. break;
  208. case PAD_DOWN:
  209. key = DOWN;
  210. break;
  211. case PAD_LEFT:
  212. key = LEFT;
  213. break;
  214. case PAD_RIGHT:
  215. key = RIGHT;
  216. break;
  217. case PAD_DOT:
  218. key = DELETE;
  219. break;
  220. default:
  221. break;
  222. }
  223. }
  224. break;
  225. }
  226. }
  227. key |= shift_l ? FLAG_SHIFT_L : 0;
  228. key |= shift_r ? FLAG_SHIFT_R : 0;
  229. key |= ctrl_l ? FLAG_CTRL_L : 0;
  230. key |= ctrl_r ? FLAG_CTRL_R : 0;
  231. key |= alt_l ? FLAG_ALT_L : 0;
  232. key |= alt_r ? FLAG_ALT_R : 0;
  233. key |= pad ? FLAG_PAD : 0;
  234. *pkey = key;
  235. return TRUE;
  236. }
  237. }
  238. return FALSE;
  239. }
  240. PRIVATE t_8 get_byte_from_kb_buf()
  241. {
  242. t_8 scan_code;
  243. RT_ASSERT(kb_in.count>0);
  244. scan_code = *(kb_in.p_tail);
  245. kb_in.p_tail++;
  246. if (kb_in.p_tail == kb_in.buf + KB_IN_BYTES) {
  247. kb_in.p_tail = kb_in.buf;
  248. }
  249. kb_in.count--;
  250. return scan_code;
  251. }
  252. PRIVATE void kb_wait() /* wait inpit cache of 8042 */
  253. {
  254. t_8 kb_stat;
  255. do {
  256. kb_stat = inb(KB_CMD);
  257. } while (kb_stat & 0x02);
  258. }
  259. PRIVATE void kb_ack()
  260. {
  261. t_8 kb_read;
  262. do {
  263. kb_read = inb(KB_DATA);
  264. } while (kb_read != KB_ACK);
  265. }
  266. PRIVATE void set_leds()
  267. {
  268. t_8 leds = (caps_lock << 2) | (num_lock << 1) | scroll_lock;
  269. kb_wait();
  270. outb(KB_DATA, LED_CODE);
  271. kb_ack();
  272. kb_wait();
  273. outb(KB_DATA, leds);
  274. kb_ack();
  275. }
  276. /**
  277. * @addtogroup QEMU
  278. */
  279. /*@{*/
  280. void rt_keyboard_isr(void)
  281. {
  282. rt_uint8_t data;
  283. if ((inb(KBSTATP) & KBS_DIB) == 0)
  284. return ;
  285. data = inb(KBDATAP);
  286. if (kb_in.count < KB_IN_BYTES) {
  287. *(kb_in.p_head) = data;
  288. kb_in.p_head++;
  289. if (kb_in.p_head == kb_in.buf + KB_IN_BYTES) {
  290. kb_in.p_head = kb_in.buf;
  291. }
  292. kb_in.count++;
  293. }
  294. }
  295. /* generally, this should be called in task level for all key inpit support,
  296. but here only support a key that is composed of 2 bytes */
  297. rt_bool_t rt_keyboard_getc(char* c)
  298. {
  299. if(kb_in.count>=2)
  300. {
  301. rt_uint32_t key = 0;
  302. rt_bool_t rv=keyboard_read(&key);
  303. switch(key)
  304. {
  305. case TAB:
  306. *c = '\t';
  307. break;
  308. case ENTER:
  309. *c = '\n';
  310. break;
  311. case BACKSPACE:
  312. *c = '\b';
  313. break;
  314. default:
  315. *c = key;
  316. break;
  317. }
  318. return rv;
  319. }
  320. return RT_FALSE;
  321. }
  322. /*@}*/