1 /* 2 * ebcdic keycode functions for s390 console drivers 3 * 4 * S390 version 5 * Copyright IBM Corp. 2003 6 * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), 7 */ 8 9 #include <linux/module.h> 10 #include <linux/sched.h> 11 #include <linux/slab.h> 12 #include <linux/sysrq.h> 13 14 #include <linux/consolemap.h> 15 #include <linux/kbd_kern.h> 16 #include <linux/kbd_diacr.h> 17 #include <asm/uaccess.h> 18 19 #include "keyboard.h" 20 21 /* 22 * Handler Tables. 23 */ 24 #define K_HANDLERS\ 25 k_self, k_fn, k_spec, k_ignore,\ 26 k_dead, k_ignore, k_ignore, k_ignore,\ 27 k_ignore, k_ignore, k_ignore, k_ignore,\ 28 k_ignore, k_ignore, k_ignore, k_ignore 29 30 typedef void (k_handler_fn)(struct kbd_data *, unsigned char); 31 static k_handler_fn K_HANDLERS; 32 static k_handler_fn *k_handler[16] = { K_HANDLERS }; 33 34 /* maximum values each key_handler can handle */ 35 static const int kbd_max_vals[] = { 36 255, ARRAY_SIZE(func_table) - 1, NR_FN_HANDLER - 1, 0, 37 NR_DEAD - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 38 }; 39 static const int KBD_NR_TYPES = ARRAY_SIZE(kbd_max_vals); 40 41 static unsigned char ret_diacr[NR_DEAD] = { 42 '`', '\'', '^', '~', '"', ',' 43 }; 44 45 /* 46 * Alloc/free of kbd_data structures. 47 */ 48 struct kbd_data * 49 kbd_alloc(void) { 50 struct kbd_data *kbd; 51 int i; 52 53 kbd = kzalloc(sizeof(struct kbd_data), GFP_KERNEL); 54 if (!kbd) 55 goto out; 56 kbd->key_maps = kzalloc(sizeof(key_maps), GFP_KERNEL); 57 if (!kbd->key_maps) 58 goto out_kbd; 59 for (i = 0; i < ARRAY_SIZE(key_maps); i++) { 60 if (key_maps[i]) { 61 kbd->key_maps[i] = kmemdup(key_maps[i], 62 sizeof(u_short) * NR_KEYS, 63 GFP_KERNEL); 64 if (!kbd->key_maps[i]) 65 goto out_maps; 66 } 67 } 68 kbd->func_table = kzalloc(sizeof(func_table), GFP_KERNEL); 69 if (!kbd->func_table) 70 goto out_maps; 71 for (i = 0; i < ARRAY_SIZE(func_table); i++) { 72 if (func_table[i]) { 73 kbd->func_table[i] = kstrdup(func_table[i], 74 GFP_KERNEL); 75 if (!kbd->func_table[i]) 76 goto out_func; 77 } 78 } 79 kbd->fn_handler = 80 kzalloc(sizeof(fn_handler_fn *) * NR_FN_HANDLER, GFP_KERNEL); 81 if (!kbd->fn_handler) 82 goto out_func; 83 kbd->accent_table = kmemdup(accent_table, 84 sizeof(struct kbdiacruc) * MAX_DIACR, 85 GFP_KERNEL); 86 if (!kbd->accent_table) 87 goto out_fn_handler; 88 kbd->accent_table_size = accent_table_size; 89 return kbd; 90 91 out_fn_handler: 92 kfree(kbd->fn_handler); 93 out_func: 94 for (i = 0; i < ARRAY_SIZE(func_table); i++) 95 kfree(kbd->func_table[i]); 96 kfree(kbd->func_table); 97 out_maps: 98 for (i = 0; i < ARRAY_SIZE(key_maps); i++) 99 kfree(kbd->key_maps[i]); 100 kfree(kbd->key_maps); 101 out_kbd: 102 kfree(kbd); 103 out: 104 return NULL; 105 } 106 107 void 108 kbd_free(struct kbd_data *kbd) 109 { 110 int i; 111 112 kfree(kbd->accent_table); 113 kfree(kbd->fn_handler); 114 for (i = 0; i < ARRAY_SIZE(func_table); i++) 115 kfree(kbd->func_table[i]); 116 kfree(kbd->func_table); 117 for (i = 0; i < ARRAY_SIZE(key_maps); i++) 118 kfree(kbd->key_maps[i]); 119 kfree(kbd->key_maps); 120 kfree(kbd); 121 } 122 123 /* 124 * Generate ascii -> ebcdic translation table from kbd_data. 125 */ 126 void 127 kbd_ascebc(struct kbd_data *kbd, unsigned char *ascebc) 128 { 129 unsigned short *keymap, keysym; 130 int i, j, k; 131 132 memset(ascebc, 0x40, 256); 133 for (i = 0; i < ARRAY_SIZE(key_maps); i++) { 134 keymap = kbd->key_maps[i]; 135 if (!keymap) 136 continue; 137 for (j = 0; j < NR_KEYS; j++) { 138 k = ((i & 1) << 7) + j; 139 keysym = keymap[j]; 140 if (KTYP(keysym) == (KT_LATIN | 0xf0) || 141 KTYP(keysym) == (KT_LETTER | 0xf0)) 142 ascebc[KVAL(keysym)] = k; 143 else if (KTYP(keysym) == (KT_DEAD | 0xf0)) 144 ascebc[ret_diacr[KVAL(keysym)]] = k; 145 } 146 } 147 } 148 149 #if 0 150 /* 151 * Generate ebcdic -> ascii translation table from kbd_data. 152 */ 153 void 154 kbd_ebcasc(struct kbd_data *kbd, unsigned char *ebcasc) 155 { 156 unsigned short *keymap, keysym; 157 int i, j, k; 158 159 memset(ebcasc, ' ', 256); 160 for (i = 0; i < ARRAY_SIZE(key_maps); i++) { 161 keymap = kbd->key_maps[i]; 162 if (!keymap) 163 continue; 164 for (j = 0; j < NR_KEYS; j++) { 165 keysym = keymap[j]; 166 k = ((i & 1) << 7) + j; 167 if (KTYP(keysym) == (KT_LATIN | 0xf0) || 168 KTYP(keysym) == (KT_LETTER | 0xf0)) 169 ebcasc[k] = KVAL(keysym); 170 else if (KTYP(keysym) == (KT_DEAD | 0xf0)) 171 ebcasc[k] = ret_diacr[KVAL(keysym)]; 172 } 173 } 174 } 175 #endif 176 177 /* 178 * We have a combining character DIACR here, followed by the character CH. 179 * If the combination occurs in the table, return the corresponding value. 180 * Otherwise, if CH is a space or equals DIACR, return DIACR. 181 * Otherwise, conclude that DIACR was not combining after all, 182 * queue it and return CH. 183 */ 184 static unsigned int 185 handle_diacr(struct kbd_data *kbd, unsigned int ch) 186 { 187 int i, d; 188 189 d = kbd->diacr; 190 kbd->diacr = 0; 191 192 for (i = 0; i < kbd->accent_table_size; i++) { 193 if (kbd->accent_table[i].diacr == d && 194 kbd->accent_table[i].base == ch) 195 return kbd->accent_table[i].result; 196 } 197 198 if (ch == ' ' || ch == d) 199 return d; 200 201 kbd_put_queue(kbd->port, d); 202 return ch; 203 } 204 205 /* 206 * Handle dead key. 207 */ 208 static void 209 k_dead(struct kbd_data *kbd, unsigned char value) 210 { 211 value = ret_diacr[value]; 212 kbd->diacr = (kbd->diacr ? handle_diacr(kbd, value) : value); 213 } 214 215 /* 216 * Normal character handler. 217 */ 218 static void 219 k_self(struct kbd_data *kbd, unsigned char value) 220 { 221 if (kbd->diacr) 222 value = handle_diacr(kbd, value); 223 kbd_put_queue(kbd->port, value); 224 } 225 226 /* 227 * Special key handlers 228 */ 229 static void 230 k_ignore(struct kbd_data *kbd, unsigned char value) 231 { 232 } 233 234 /* 235 * Function key handler. 236 */ 237 static void 238 k_fn(struct kbd_data *kbd, unsigned char value) 239 { 240 if (kbd->func_table[value]) 241 kbd_puts_queue(kbd->port, kbd->func_table[value]); 242 } 243 244 static void 245 k_spec(struct kbd_data *kbd, unsigned char value) 246 { 247 if (value >= NR_FN_HANDLER) 248 return; 249 if (kbd->fn_handler[value]) 250 kbd->fn_handler[value](kbd); 251 } 252 253 /* 254 * Put utf8 character to tty flip buffer. 255 * UTF-8 is defined for words of up to 31 bits, 256 * but we need only 16 bits here 257 */ 258 static void 259 to_utf8(struct tty_port *port, ushort c) 260 { 261 if (c < 0x80) 262 /* 0******* */ 263 kbd_put_queue(port, c); 264 else if (c < 0x800) { 265 /* 110***** 10****** */ 266 kbd_put_queue(port, 0xc0 | (c >> 6)); 267 kbd_put_queue(port, 0x80 | (c & 0x3f)); 268 } else { 269 /* 1110**** 10****** 10****** */ 270 kbd_put_queue(port, 0xe0 | (c >> 12)); 271 kbd_put_queue(port, 0x80 | ((c >> 6) & 0x3f)); 272 kbd_put_queue(port, 0x80 | (c & 0x3f)); 273 } 274 } 275 276 /* 277 * Process keycode. 278 */ 279 void 280 kbd_keycode(struct kbd_data *kbd, unsigned int keycode) 281 { 282 unsigned short keysym; 283 unsigned char type, value; 284 285 if (!kbd) 286 return; 287 288 if (keycode >= 384) 289 keysym = kbd->key_maps[5][keycode - 384]; 290 else if (keycode >= 256) 291 keysym = kbd->key_maps[4][keycode - 256]; 292 else if (keycode >= 128) 293 keysym = kbd->key_maps[1][keycode - 128]; 294 else 295 keysym = kbd->key_maps[0][keycode]; 296 297 type = KTYP(keysym); 298 if (type >= 0xf0) { 299 type -= 0xf0; 300 if (type == KT_LETTER) 301 type = KT_LATIN; 302 value = KVAL(keysym); 303 #ifdef CONFIG_MAGIC_SYSRQ /* Handle the SysRq Hack */ 304 if (kbd->sysrq) { 305 if (kbd->sysrq == K(KT_LATIN, '-')) { 306 kbd->sysrq = 0; 307 handle_sysrq(value); 308 return; 309 } 310 if (value == '-') { 311 kbd->sysrq = K(KT_LATIN, '-'); 312 return; 313 } 314 /* Incomplete sysrq sequence. */ 315 (*k_handler[KTYP(kbd->sysrq)])(kbd, KVAL(kbd->sysrq)); 316 kbd->sysrq = 0; 317 } else if ((type == KT_LATIN && value == '^') || 318 (type == KT_DEAD && ret_diacr[value] == '^')) { 319 kbd->sysrq = K(type, value); 320 return; 321 } 322 #endif 323 (*k_handler[type])(kbd, value); 324 } else 325 to_utf8(kbd->port, keysym); 326 } 327 328 /* 329 * Ioctl stuff. 330 */ 331 static int 332 do_kdsk_ioctl(struct kbd_data *kbd, struct kbentry __user *user_kbe, 333 int cmd, int perm) 334 { 335 struct kbentry tmp; 336 ushort *key_map, val, ov; 337 338 if (copy_from_user(&tmp, user_kbe, sizeof(struct kbentry))) 339 return -EFAULT; 340 #if NR_KEYS < 256 341 if (tmp.kb_index >= NR_KEYS) 342 return -EINVAL; 343 #endif 344 #if MAX_NR_KEYMAPS < 256 345 if (tmp.kb_table >= MAX_NR_KEYMAPS) 346 return -EINVAL; 347 #endif 348 349 switch (cmd) { 350 case KDGKBENT: 351 key_map = kbd->key_maps[tmp.kb_table]; 352 if (key_map) { 353 val = U(key_map[tmp.kb_index]); 354 if (KTYP(val) >= KBD_NR_TYPES) 355 val = K_HOLE; 356 } else 357 val = (tmp.kb_index ? K_HOLE : K_NOSUCHMAP); 358 return put_user(val, &user_kbe->kb_value); 359 case KDSKBENT: 360 if (!perm) 361 return -EPERM; 362 if (!tmp.kb_index && tmp.kb_value == K_NOSUCHMAP) { 363 /* disallocate map */ 364 key_map = kbd->key_maps[tmp.kb_table]; 365 if (key_map) { 366 kbd->key_maps[tmp.kb_table] = NULL; 367 kfree(key_map); 368 } 369 break; 370 } 371 372 if (KTYP(tmp.kb_value) >= KBD_NR_TYPES) 373 return -EINVAL; 374 if (KVAL(tmp.kb_value) > kbd_max_vals[KTYP(tmp.kb_value)]) 375 return -EINVAL; 376 377 if (!(key_map = kbd->key_maps[tmp.kb_table])) { 378 int j; 379 380 key_map = kmalloc(sizeof(plain_map), 381 GFP_KERNEL); 382 if (!key_map) 383 return -ENOMEM; 384 kbd->key_maps[tmp.kb_table] = key_map; 385 for (j = 0; j < NR_KEYS; j++) 386 key_map[j] = U(K_HOLE); 387 } 388 ov = U(key_map[tmp.kb_index]); 389 if (tmp.kb_value == ov) 390 break; /* nothing to do */ 391 /* 392 * Attention Key. 393 */ 394 if (((ov == K_SAK) || (tmp.kb_value == K_SAK)) && 395 !capable(CAP_SYS_ADMIN)) 396 return -EPERM; 397 key_map[tmp.kb_index] = U(tmp.kb_value); 398 break; 399 } 400 return 0; 401 } 402 403 static int 404 do_kdgkb_ioctl(struct kbd_data *kbd, struct kbsentry __user *u_kbs, 405 int cmd, int perm) 406 { 407 unsigned char kb_func; 408 char *p; 409 int len; 410 411 /* Get u_kbs->kb_func. */ 412 if (get_user(kb_func, &u_kbs->kb_func)) 413 return -EFAULT; 414 #if MAX_NR_FUNC < 256 415 if (kb_func >= MAX_NR_FUNC) 416 return -EINVAL; 417 #endif 418 419 switch (cmd) { 420 case KDGKBSENT: 421 p = kbd->func_table[kb_func]; 422 if (p) { 423 len = strlen(p); 424 if (len >= sizeof(u_kbs->kb_string)) 425 len = sizeof(u_kbs->kb_string) - 1; 426 if (copy_to_user(u_kbs->kb_string, p, len)) 427 return -EFAULT; 428 } else 429 len = 0; 430 if (put_user('\0', u_kbs->kb_string + len)) 431 return -EFAULT; 432 break; 433 case KDSKBSENT: 434 if (!perm) 435 return -EPERM; 436 len = strnlen_user(u_kbs->kb_string, sizeof(u_kbs->kb_string)); 437 if (!len) 438 return -EFAULT; 439 if (len > sizeof(u_kbs->kb_string)) 440 return -EINVAL; 441 p = memdup_user_nul(u_kbs->kb_string, len); 442 if (IS_ERR(p)) 443 return PTR_ERR(p); 444 kfree(kbd->func_table[kb_func]); 445 kbd->func_table[kb_func] = p; 446 break; 447 } 448 return 0; 449 } 450 451 int kbd_ioctl(struct kbd_data *kbd, unsigned int cmd, unsigned long arg) 452 { 453 struct tty_struct *tty; 454 void __user *argp; 455 unsigned int ct; 456 int perm; 457 458 argp = (void __user *)arg; 459 460 /* 461 * To have permissions to do most of the vt ioctls, we either have 462 * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG. 463 */ 464 tty = tty_port_tty_get(kbd->port); 465 /* FIXME this test is pretty racy */ 466 perm = current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG); 467 tty_kref_put(tty); 468 switch (cmd) { 469 case KDGKBTYPE: 470 return put_user(KB_101, (char __user *)argp); 471 case KDGKBENT: 472 case KDSKBENT: 473 return do_kdsk_ioctl(kbd, argp, cmd, perm); 474 case KDGKBSENT: 475 case KDSKBSENT: 476 return do_kdgkb_ioctl(kbd, argp, cmd, perm); 477 case KDGKBDIACR: 478 { 479 struct kbdiacrs __user *a = argp; 480 struct kbdiacr diacr; 481 int i; 482 483 if (put_user(kbd->accent_table_size, &a->kb_cnt)) 484 return -EFAULT; 485 for (i = 0; i < kbd->accent_table_size; i++) { 486 diacr.diacr = kbd->accent_table[i].diacr; 487 diacr.base = kbd->accent_table[i].base; 488 diacr.result = kbd->accent_table[i].result; 489 if (copy_to_user(a->kbdiacr + i, &diacr, sizeof(struct kbdiacr))) 490 return -EFAULT; 491 } 492 return 0; 493 } 494 case KDGKBDIACRUC: 495 { 496 struct kbdiacrsuc __user *a = argp; 497 498 ct = kbd->accent_table_size; 499 if (put_user(ct, &a->kb_cnt)) 500 return -EFAULT; 501 if (copy_to_user(a->kbdiacruc, kbd->accent_table, 502 ct * sizeof(struct kbdiacruc))) 503 return -EFAULT; 504 return 0; 505 } 506 case KDSKBDIACR: 507 { 508 struct kbdiacrs __user *a = argp; 509 struct kbdiacr diacr; 510 int i; 511 512 if (!perm) 513 return -EPERM; 514 if (get_user(ct, &a->kb_cnt)) 515 return -EFAULT; 516 if (ct >= MAX_DIACR) 517 return -EINVAL; 518 kbd->accent_table_size = ct; 519 for (i = 0; i < ct; i++) { 520 if (copy_from_user(&diacr, a->kbdiacr + i, sizeof(struct kbdiacr))) 521 return -EFAULT; 522 kbd->accent_table[i].diacr = diacr.diacr; 523 kbd->accent_table[i].base = diacr.base; 524 kbd->accent_table[i].result = diacr.result; 525 } 526 return 0; 527 } 528 case KDSKBDIACRUC: 529 { 530 struct kbdiacrsuc __user *a = argp; 531 532 if (!perm) 533 return -EPERM; 534 if (get_user(ct, &a->kb_cnt)) 535 return -EFAULT; 536 if (ct >= MAX_DIACR) 537 return -EINVAL; 538 kbd->accent_table_size = ct; 539 if (copy_from_user(kbd->accent_table, a->kbdiacruc, 540 ct * sizeof(struct kbdiacruc))) 541 return -EFAULT; 542 return 0; 543 } 544 default: 545 return -ENOIOCTLCMD; 546 } 547 } 548 549 EXPORT_SYMBOL(kbd_ioctl); 550 EXPORT_SYMBOL(kbd_ascebc); 551 EXPORT_SYMBOL(kbd_free); 552 EXPORT_SYMBOL(kbd_alloc); 553 EXPORT_SYMBOL(kbd_keycode); 554