1 /* 2 * simulated keyboard input for omap35 with no keyboard (except via uart or usb) 3 * 4 * gutted version of ps2 version from ../pc 5 */ 6 #include "u.h" 7 #include "../port/lib.h" 8 #include "mem.h" 9 #include "dat.h" 10 #include "fns.h" 11 #include "io.h" 12 #include "../port/error.h" 13 14 enum { 15 Spec= 0xF800, /* Unicode private space */ 16 PF= Spec|0x20, /* num pad function key */ 17 View= Spec|0x00, /* view (shift window up) */ 18 KF= 0xF000, /* function key (begin Unicode private space) */ 19 Shift= Spec|0x60, 20 Break= Spec|0x61, 21 Ctrl= Spec|0x62, 22 Latin= Spec|0x63, 23 Caps= Spec|0x64, 24 Num= Spec|0x65, 25 Middle= Spec|0x66, 26 Altgr= Spec|0x67, 27 Kmouse= Spec|0x100, 28 No= 0x00, /* peter */ 29 30 Home= KF|13, 31 Up= KF|14, 32 Pgup= KF|15, 33 Print= KF|16, 34 Left= KF|17, 35 Right= KF|18, 36 End= KF|24, 37 Down= View, 38 Pgdown= KF|19, 39 Ins= KF|20, 40 Del= 0x7F, 41 Scroll= KF|21, 42 43 Nscan= 128, 44 45 Int= 0, /* kbscans indices */ 46 Ext, 47 Nscans, 48 }; 49 50 /* 51 * The codes at 0x79 and 0x7b are produced by the PFU Happy Hacking keyboard. 52 * A 'standard' keyboard doesn't produce anything above 0x58. 53 */ 54 Rune kbtab[Nscan] = 55 { 56 [0x00] No, 0x1b, '1', '2', '3', '4', '5', '6', 57 [0x08] '7', '8', '9', '0', '-', '=', '\b', '\t', 58 [0x10] 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 59 [0x18] 'o', 'p', '[', ']', '\n', Ctrl, 'a', 's', 60 [0x20] 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', 61 [0x28] '\'', '`', Shift, '\\', 'z', 'x', 'c', 'v', 62 [0x30] 'b', 'n', 'm', ',', '.', '/', Shift, '*', 63 [0x38] Latin, ' ', Ctrl, KF|1, KF|2, KF|3, KF|4, KF|5, 64 [0x40] KF|6, KF|7, KF|8, KF|9, KF|10, Num, Scroll, '7', 65 [0x48] '8', '9', '-', '4', '5', '6', '+', '1', 66 [0x50] '2', '3', '0', '.', No, No, No, KF|11, 67 [0x58] KF|12, No, No, No, No, No, No, No, 68 [0x60] No, No, No, No, No, No, No, No, 69 [0x68] No, No, No, No, No, No, No, No, 70 [0x70] No, No, No, No, No, No, No, No, 71 [0x78] No, View, No, Up, No, No, No, No, 72 }; 73 74 Rune kbtabshift[Nscan] = 75 { 76 [0x00] No, 0x1b, '!', '@', '#', '$', '%', '^', 77 [0x08] '&', '*', '(', ')', '_', '+', '\b', '\t', 78 [0x10] 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 79 [0x18] 'O', 'P', '{', '}', '\n', Ctrl, 'A', 'S', 80 [0x20] 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', 81 [0x28] '"', '~', Shift, '|', 'Z', 'X', 'C', 'V', 82 [0x30] 'B', 'N', 'M', '<', '>', '?', Shift, '*', 83 [0x38] Latin, ' ', Ctrl, KF|1, KF|2, KF|3, KF|4, KF|5, 84 [0x40] KF|6, KF|7, KF|8, KF|9, KF|10, Num, Scroll, '7', 85 [0x48] '8', '9', '-', '4', '5', '6', '+', '1', 86 [0x50] '2', '3', '0', '.', No, No, No, KF|11, 87 [0x58] KF|12, No, No, No, No, No, No, No, 88 [0x60] No, No, No, No, No, No, No, No, 89 [0x68] No, No, No, No, No, No, No, No, 90 [0x70] No, No, No, No, No, No, No, No, 91 [0x78] No, Up, No, Up, No, No, No, No, 92 }; 93 94 Rune kbtabesc1[Nscan] = 95 { 96 [0x00] No, No, No, No, No, No, No, No, 97 [0x08] No, No, No, No, No, No, No, No, 98 [0x10] No, No, No, No, No, No, No, No, 99 [0x18] No, No, No, No, '\n', Ctrl, No, No, 100 [0x20] No, No, No, No, No, No, No, No, 101 [0x28] No, No, Shift, No, No, No, No, No, 102 [0x30] No, No, No, No, No, '/', No, Print, 103 [0x38] Altgr, No, No, No, No, No, No, No, 104 [0x40] No, No, No, No, No, No, Break, Home, 105 [0x48] Up, Pgup, No, Left, No, Right, No, End, 106 [0x50] Down, Pgdown, Ins, Del, No, No, No, No, 107 [0x58] No, No, No, No, No, No, No, No, 108 [0x60] No, No, No, No, No, No, No, No, 109 [0x68] No, No, No, No, No, No, No, No, 110 [0x70] No, No, No, No, No, No, No, No, 111 [0x78] No, Up, No, No, No, No, No, No, 112 }; 113 114 Rune kbtabaltgr[Nscan] = 115 { 116 [0x00] No, No, No, No, No, No, No, No, 117 [0x08] No, No, No, No, No, No, No, No, 118 [0x10] No, No, No, No, No, No, No, No, 119 [0x18] No, No, No, No, '\n', Ctrl, No, No, 120 [0x20] No, No, No, No, No, No, No, No, 121 [0x28] No, No, Shift, No, No, No, No, No, 122 [0x30] No, No, No, No, No, '/', No, Print, 123 [0x38] Altgr, No, No, No, No, No, No, No, 124 [0x40] No, No, No, No, No, No, Break, Home, 125 [0x48] Up, Pgup, No, Left, No, Right, No, End, 126 [0x50] Down, Pgdown, Ins, Del, No, No, No, No, 127 [0x58] No, No, No, No, No, No, No, No, 128 [0x60] No, No, No, No, No, No, No, No, 129 [0x68] No, No, No, No, No, No, No, No, 130 [0x70] No, No, No, No, No, No, No, No, 131 [0x78] No, Up, No, No, No, No, No, No, 132 }; 133 134 Rune kbtabctrl[Nscan] = 135 { 136 [0x00] No, '', '', '', '', '', '', '', 137 [0x08] '', '', '', '', ' 138 ', '', '\b', '\t', 139 [0x10] '', '', '', '', '', '', '', '\t', 140 [0x18] '', '', '', '', '\n', Ctrl, '', '', 141 [0x20] '', '', '', '\b', '\n', '', '', '', 142 [0x28] '', No, Shift, '', '', '', '', '', 143 [0x30] '', '', ' 144 ', '', '', '', Shift, '\n', 145 [0x38] Latin, No, Ctrl, '', '', '', '', '', 146 [0x40] '', '', '', ' 147 ', '', '', '', '', 148 [0x48] '', '', ' 149 ', '', '', '', '', '', 150 [0x50] '', '', '', '', No, No, No, '', 151 [0x58] '', No, No, No, No, No, No, No, 152 [0x60] No, No, No, No, No, No, No, No, 153 [0x68] No, No, No, No, No, No, No, No, 154 [0x70] No, No, No, No, No, No, No, No, 155 [0x78] No, '', No, '\b', No, No, No, No, 156 }; 157 158 int mouseshifted; 159 void (*kbdmouse)(int); 160 161 static int kdebug; 162 163 typedef struct Kbscan Kbscan; 164 struct Kbscan { 165 int esc1; 166 int esc2; 167 int alt; 168 int altgr; 169 int caps; 170 int ctl; 171 int num; 172 int shift; 173 int collecting; 174 int nk; 175 Rune kc[5]; 176 int buttons; 177 }; 178 179 Kbscan kbscans[Nscans]; /* kernel and external scan code state */ 180 181 /* 182 * Scan code processing 183 */ 184 void 185 kbdputsc(int c, int external) 186 { 187 int i, keyup; 188 Kbscan *kbscan; 189 190 if(external) 191 kbscan = &kbscans[Ext]; 192 else 193 kbscan = &kbscans[Int]; 194 195 if(kdebug) 196 print("sc %x ms %d\n", c, mouseshifted); 197 /* 198 * e0's is the first of a 2 character sequence, e1 the first 199 * of a 3 character sequence (on the safari) 200 */ 201 if(c == 0xe0){ 202 kbscan->esc1 = 1; 203 return; 204 } else if(c == 0xe1){ 205 kbscan->esc2 = 2; 206 return; 207 } 208 209 keyup = c & 0x80; 210 c &= 0x7f; 211 if(c > sizeof kbtab){ 212 c |= keyup; 213 if(c != 0xFF) /* these come fairly often: CAPSLOCK U Y */ 214 print("unknown key %ux\n", c); 215 return; 216 } 217 218 if(kbscan->esc1){ 219 c = kbtabesc1[c]; 220 kbscan->esc1 = 0; 221 } else if(kbscan->esc2){ 222 kbscan->esc2--; 223 return; 224 } else if(kbscan->shift) 225 c = kbtabshift[c]; 226 else if(kbscan->altgr) 227 c = kbtabaltgr[c]; 228 else if(kbscan->ctl) 229 c = kbtabctrl[c]; 230 else 231 c = kbtab[c]; 232 233 if(kbscan->caps && c<='z' && c>='a') 234 c += 'A' - 'a'; 235 236 /* 237 * keyup only important for shifts 238 */ 239 if(keyup){ 240 switch(c){ 241 case Latin: 242 kbscan->alt = 0; 243 break; 244 case Shift: 245 kbscan->shift = 0; 246 mouseshifted = 0; 247 if(kdebug) 248 print("shiftclr\n"); 249 break; 250 case Ctrl: 251 kbscan->ctl = 0; 252 break; 253 case Altgr: 254 kbscan->altgr = 0; 255 break; 256 case Kmouse|1: 257 case Kmouse|2: 258 case Kmouse|3: 259 case Kmouse|4: 260 case Kmouse|5: 261 kbscan->buttons &= ~(1<<(c-Kmouse-1)); 262 if(kbdmouse) 263 kbdmouse(kbscan->buttons); 264 break; 265 } 266 return; 267 } 268 269 /* 270 * normal character 271 */ 272 if(!(c & (Spec|KF))){ 273 if(kbscan->ctl) 274 if(kbscan->alt && c == Del) 275 exit(0); 276 if(!kbscan->collecting){ 277 kbdputc(kbdq, c); 278 return; 279 } 280 kbscan->kc[kbscan->nk++] = c; 281 c = latin1(kbscan->kc, kbscan->nk); 282 if(c < -1) /* need more keystrokes */ 283 return; 284 if(c != -1) /* valid sequence */ 285 kbdputc(kbdq, c); 286 else /* dump characters */ 287 for(i=0; i<kbscan->nk; i++) 288 kbdputc(kbdq, kbscan->kc[i]); 289 kbscan->nk = 0; 290 kbscan->collecting = 0; 291 return; 292 } else { 293 switch(c){ 294 case Caps: 295 kbscan->caps ^= 1; 296 return; 297 case Num: 298 kbscan->num ^= 1; 299 return; 300 case Shift: 301 kbscan->shift = 1; 302 if(kdebug) 303 print("shift\n"); 304 mouseshifted = 1; 305 return; 306 case Latin: 307 kbscan->alt = 1; 308 /* 309 * VMware and Qemu use Ctl-Alt as the key combination 310 * to make the VM give up keyboard and mouse focus. 311 * This has the unfortunate side effect that when you 312 * come back into focus, Plan 9 thinks you want to type 313 * a compose sequence (you just typed alt). 314 * 315 * As a clumsy hack around this, we look for ctl-alt 316 * and don't treat it as the start of a compose sequence. 317 */ 318 if(!kbscan->ctl){ 319 kbscan->collecting = 1; 320 kbscan->nk = 0; 321 } 322 return; 323 case Ctrl: 324 kbscan->ctl = 1; 325 return; 326 case Altgr: 327 kbscan->altgr = 1; 328 return; 329 case Kmouse|1: 330 case Kmouse|2: 331 case Kmouse|3: 332 case Kmouse|4: 333 case Kmouse|5: 334 kbscan->buttons |= 1<<(c-Kmouse-1); 335 if(kbdmouse) 336 kbdmouse(kbscan->buttons); 337 return; 338 case KF|11: 339 print("kbd debug on, F12 turns it off\n"); 340 kdebug = 1; 341 break; 342 case KF|12: 343 kdebug = 0; 344 break; 345 } 346 } 347 kbdputc(kbdq, c); 348 } 349 350 void 351 kbdenable(void) 352 { 353 #ifdef notdef 354 kbdq = qopen(4*1024, 0, 0, 0); 355 if(kbdq == nil) 356 panic("kbdinit"); 357 qnoblock(kbdq, 1); 358 #endif 359 kbscans[Int].num = 0; 360 } 361 362 void 363 kbdputmap(ushort m, ushort scanc, Rune r) 364 { 365 if(scanc >= Nscan) 366 error(Ebadarg); 367 switch(m) { 368 default: 369 error(Ebadarg); 370 case 0: 371 kbtab[scanc] = r; 372 break; 373 case 1: 374 kbtabshift[scanc] = r; 375 break; 376 case 2: 377 kbtabesc1[scanc] = r; 378 break; 379 case 3: 380 kbtabaltgr[scanc] = r; 381 break; 382 case 4: 383 kbtabctrl[scanc] = r; 384 break; 385 } 386 } 387 388 int 389 kbdgetmap(uint offset, int *t, int *sc, Rune *r) 390 { 391 if ((int)offset < 0) 392 error(Ebadarg); 393 *t = offset/Nscan; 394 *sc = offset%Nscan; 395 switch(*t) { 396 default: 397 return 0; 398 case 0: 399 *r = kbtab[*sc]; 400 return 1; 401 case 1: 402 *r = kbtabshift[*sc]; 403 return 1; 404 case 2: 405 *r = kbtabesc1[*sc]; 406 return 1; 407 case 3: 408 *r = kbtabaltgr[*sc]; 409 return 1; 410 case 4: 411 *r = kbtabctrl[*sc]; 412 return 1; 413 } 414 } 415