keyboard.c 7.0 KB

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