keyboard.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. /***********************************************************************
  2. *
  3. * (C) Copyright 2004
  4. * DENX Software Engineering
  5. * Wolfgang Denk, wd@denx.de
  6. * All rights reserved.
  7. *
  8. * Keyboard driver
  9. *
  10. ***********************************************************************/
  11. #include <common.h>
  12. #ifdef CONFIG_PS2KBD
  13. #include <devices.h>
  14. #include <keyboard.h>
  15. #undef KBG_DEBUG
  16. #ifdef KBG_DEBUG
  17. #define PRINTF(fmt,args...) printf (fmt ,##args)
  18. #else
  19. #define PRINTF(fmt,args...)
  20. #endif
  21. #define DEVNAME "kbd"
  22. #define LED_SCR 0x01 /* scroll lock led */
  23. #define LED_CAP 0x04 /* caps lock led */
  24. #define LED_NUM 0x02 /* num lock led */
  25. #define KBD_BUFFER_LEN 0x20 /* size of the keyboardbuffer */
  26. #if defined(CONFIG_MPC5xxx) || defined(CONFIG_MPC85xx)
  27. int ps2ser_check(void);
  28. #endif
  29. static volatile char kbd_buffer[KBD_BUFFER_LEN];
  30. static volatile int in_pointer = 0;
  31. static volatile int out_pointer = 0;
  32. static unsigned char leds = 0;
  33. static unsigned char num_lock = 0;
  34. static unsigned char caps_lock = 0;
  35. static unsigned char scroll_lock = 0;
  36. static unsigned char shift = 0;
  37. static unsigned char ctrl = 0;
  38. static unsigned char alt = 0;
  39. static unsigned char e0 = 0;
  40. /******************************************************************
  41. * Queue handling
  42. ******************************************************************/
  43. /* puts character in the queue and sets up the in and out pointer */
  44. static void kbd_put_queue(char data)
  45. {
  46. if((in_pointer+1)==KBD_BUFFER_LEN) {
  47. if(out_pointer==0) {
  48. return; /* buffer full */
  49. } else{
  50. in_pointer=0;
  51. }
  52. } else {
  53. if((in_pointer+1)==out_pointer)
  54. return; /* buffer full */
  55. in_pointer++;
  56. }
  57. kbd_buffer[in_pointer]=data;
  58. return;
  59. }
  60. /* test if a character is in the queue */
  61. static int kbd_testc(void)
  62. {
  63. #if defined(CONFIG_MPC5xxx) || defined(CONFIG_MPC85xx)
  64. /* no ISR is used, so received chars must be polled */
  65. ps2ser_check();
  66. #endif
  67. if(in_pointer==out_pointer)
  68. return(0); /* no data */
  69. else
  70. return(1);
  71. }
  72. /* gets the character from the queue */
  73. static int kbd_getc(void)
  74. {
  75. char c;
  76. while(in_pointer==out_pointer) {
  77. #if defined(CONFIG_MPC5xxx) || defined(CONFIG_MPC85xx)
  78. /* no ISR is used, so received chars must be polled */
  79. ps2ser_check();
  80. #endif
  81. ;}
  82. if((out_pointer+1)==KBD_BUFFER_LEN)
  83. out_pointer=0;
  84. else
  85. out_pointer++;
  86. c=kbd_buffer[out_pointer];
  87. return (int)c;
  88. }
  89. /* Simple translation table for the keys */
  90. static unsigned char kbd_plain_xlate[] = {
  91. 0xff,0x1b, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=','\b','\t', /* 0x00 - 0x0f */
  92. 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']','\r',0xff, 'a', 's', /* 0x10 - 0x1f */
  93. 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';','\'', '`',0xff,'\\', 'z', 'x', 'c', 'v', /* 0x20 - 0x2f */
  94. 'b', 'n', 'm', ',', '.', '/',0xff,0xff,0xff, ' ',0xff,0xff,0xff,0xff,0xff,0xff, /* 0x30 - 0x3f */
  95. 0xff,0xff,0xff,0xff,0xff,0xff,0xff, '7', '8', '9', '-', '4', '5', '6', '+', '1', /* 0x40 - 0x4f */
  96. '2', '3', '0', '.',0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 0x50 - 0x5F */
  97. '\r',0xff,0xff
  98. };
  99. static unsigned char kbd_shift_xlate[] = {
  100. 0xff,0x1b, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+','\b','\t', /* 0x00 - 0x0f */
  101. 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}','\r',0xff, 'A', 'S', /* 0x10 - 0x1f */
  102. 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~',0xff, '|', 'Z', 'X', 'C', 'V', /* 0x20 - 0x2f */
  103. 'B', 'N', 'M', '<', '>', '?',0xff,0xff,0xff, ' ',0xff,0xff,0xff,0xff,0xff,0xff, /* 0x30 - 0x3f */
  104. 0xff,0xff,0xff,0xff,0xff,0xff,0xff, '7', '8', '9', '-', '4', '5', '6', '+', '1', /* 0x40 - 0x4f */
  105. '2', '3', '0', '.',0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 0x50 - 0x5F */
  106. '\r',0xff,0xff
  107. };
  108. static unsigned char kbd_ctrl_xlate[] = {
  109. 0xff,0x1b, '1',0x00, '3', '4', '5',0x1E, '7', '8', '9', '0',0x1F, '=','\b','\t', /* 0x00 - 0x0f */
  110. 0x11,0x17,0x05,0x12,0x14,0x18,0x15,0x09,0x0f,0x10,0x1b,0x1d,'\n',0xff,0x01,0x13, /* 0x10 - 0x1f */
  111. 0x04,0x06,0x08,0x09,0x0a,0x0b,0x0c, ';','\'', '~',0x00,0x1c,0x1a,0x18,0x03,0x16, /* 0x20 - 0x2f */
  112. 0x02,0x0e,0x0d, '<', '>', '?',0xff,0xff,0xff,0x00,0xff,0xff,0xff,0xff,0xff,0xff, /* 0x30 - 0x3f */
  113. 0xff,0xff,0xff,0xff,0xff,0xff,0xff, '7', '8', '9', '-', '4', '5', '6', '+', '1', /* 0x40 - 0x4f */
  114. '2', '3', '0', '.',0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 0x50 - 0x5F */
  115. '\r',0xff,0xff
  116. };
  117. void handle_scancode(unsigned char scancode)
  118. {
  119. unsigned char keycode;
  120. /* Convert scancode to keycode */
  121. PRINTF("scancode %x\n",scancode);
  122. if(scancode==0xe0) {
  123. e0=1; /* special charakters */
  124. return;
  125. }
  126. if(e0==1) {
  127. e0=0; /* delete flag */
  128. if(!( ((scancode&0x7F)==0x38)|| /* the right ctrl key */
  129. ((scancode&0x7F)==0x1D)|| /* the right alt key */
  130. ((scancode&0x7F)==0x35)|| /* the right '/' key */
  131. ((scancode&0x7F)==0x1C) )) /* the right enter key */
  132. /* we swallow unknown e0 codes */
  133. return;
  134. }
  135. /* special cntrl keys */
  136. switch(scancode) {
  137. case 0x2A:
  138. case 0x36: /* shift pressed */
  139. shift=1;
  140. return; /* do nothing else */
  141. case 0xAA:
  142. case 0xB6: /* shift released */
  143. shift=0;
  144. return; /* do nothing else */
  145. case 0x38: /* alt pressed */
  146. alt=1;
  147. return; /* do nothing else */
  148. case 0xB8: /* alt released */
  149. alt=0;
  150. return; /* do nothing else */
  151. case 0x1d: /* ctrl pressed */
  152. ctrl=1;
  153. return; /* do nothing else */
  154. case 0x9d: /* ctrl released */
  155. ctrl=0;
  156. return; /* do nothing else */
  157. case 0x46: /* scrollock pressed */
  158. scroll_lock=~scroll_lock;
  159. if(scroll_lock==0)
  160. leds&=~LED_SCR; /* switch LED off */
  161. else
  162. leds|=LED_SCR; /* switch on LED */
  163. pckbd_leds(leds);
  164. return; /* do nothing else */
  165. case 0x3A: /* capslock pressed */
  166. caps_lock=~caps_lock;
  167. if(caps_lock==0)
  168. leds&=~LED_CAP; /* switch caps_lock off */
  169. else
  170. leds|=LED_CAP; /* switch on LED */
  171. pckbd_leds(leds);
  172. return;
  173. case 0x45: /* numlock pressed */
  174. num_lock=~num_lock;
  175. if(num_lock==0)
  176. leds&=~LED_NUM; /* switch LED off */
  177. else
  178. leds|=LED_NUM; /* switch on LED */
  179. pckbd_leds(leds);
  180. return;
  181. case 0xC6: /* scroll lock released */
  182. case 0xC5: /* num lock released */
  183. case 0xBA: /* caps lock released */
  184. return; /* just swallow */
  185. }
  186. #if 1
  187. if((scancode&0x80)==0x80) /* key released */
  188. return;
  189. #else
  190. if((scancode&0x80)==0x00) /* key pressed */
  191. return;
  192. scancode &= ~0x80;
  193. #endif
  194. /* now, decide which table we need */
  195. if(scancode > (sizeof(kbd_plain_xlate)/sizeof(kbd_plain_xlate[0]))) { /* scancode not in list */
  196. PRINTF("unkown scancode %X\n",scancode);
  197. return; /* swallow it */
  198. }
  199. /* setup plain code first */
  200. keycode=kbd_plain_xlate[scancode];
  201. if(caps_lock==1) { /* caps_lock is pressed, overwrite plain code */
  202. if(scancode > (sizeof(kbd_shift_xlate)/sizeof(kbd_shift_xlate[0]))) { /* scancode not in list */
  203. PRINTF("unkown caps-locked scancode %X\n",scancode);
  204. return; /* swallow it */
  205. }
  206. keycode=kbd_shift_xlate[scancode];
  207. if(keycode<'A') { /* we only want the alphas capital */
  208. keycode=kbd_plain_xlate[scancode];
  209. }
  210. }
  211. if(shift==1) { /* shift overwrites caps_lock */
  212. if(scancode > (sizeof(kbd_shift_xlate)/sizeof(kbd_shift_xlate[0]))) { /* scancode not in list */
  213. PRINTF("unkown shifted scancode %X\n",scancode);
  214. return; /* swallow it */
  215. }
  216. keycode=kbd_shift_xlate[scancode];
  217. }
  218. if(ctrl==1) { /* ctrl overwrites caps_lock and shift */
  219. if(scancode > (sizeof(kbd_ctrl_xlate)/sizeof(kbd_ctrl_xlate[0]))) { /* scancode not in list */
  220. PRINTF("unkown ctrl scancode %X\n",scancode);
  221. return; /* swallow it */
  222. }
  223. keycode=kbd_ctrl_xlate[scancode];
  224. }
  225. /* check if valid keycode */
  226. if(keycode==0xff) {
  227. PRINTF("unkown scancode %X\n",scancode);
  228. return; /* swallow unknown codes */
  229. }
  230. kbd_put_queue(keycode);
  231. PRINTF("%x\n",keycode);
  232. }
  233. /******************************************************************
  234. * Init
  235. ******************************************************************/
  236. #ifdef CFG_CONSOLE_OVERWRITE_ROUTINE
  237. extern int overwrite_console (void);
  238. #define OVERWRITE_CONSOLE overwrite_console ()
  239. #else
  240. #define OVERWRITE_CONSOLE 0
  241. #endif /* CFG_CONSOLE_OVERWRITE_ROUTINE */
  242. int kbd_init (void)
  243. {
  244. int error;
  245. device_t kbddev ;
  246. char *stdinname = getenv ("stdin");
  247. if(kbd_init_hw()==-1)
  248. return -1;
  249. memset (&kbddev, 0, sizeof(kbddev));
  250. strcpy(kbddev.name, DEVNAME);
  251. kbddev.flags = DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM;
  252. kbddev.putc = NULL ;
  253. kbddev.puts = NULL ;
  254. kbddev.getc = kbd_getc ;
  255. kbddev.tstc = kbd_testc ;
  256. error = device_register (&kbddev);
  257. if(error==0) {
  258. /* check if this is the standard input device */
  259. if(strcmp(stdinname,DEVNAME)==0) {
  260. /* reassign the console */
  261. if(OVERWRITE_CONSOLE) {
  262. return 1;
  263. }
  264. error=console_assign(stdin,DEVNAME);
  265. if(error==0)
  266. return 1;
  267. else
  268. return error;
  269. }
  270. return 1;
  271. }
  272. return error;
  273. }
  274. #endif /* CONFIG_PS2KBD */