diff options
Diffstat (limited to 'drivers/s390/char/keyboard.c')
-rw-r--r-- | drivers/s390/char/keyboard.c | 66 |
1 files changed, 55 insertions, 11 deletions
diff --git a/drivers/s390/char/keyboard.c b/drivers/s390/char/keyboard.c index f62f9a4e8950..cee4d4e42429 100644 --- a/drivers/s390/char/keyboard.c +++ b/drivers/s390/char/keyboard.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/sched.h> | 11 | #include <linux/sched.h> |
12 | #include <linux/sysrq.h> | 12 | #include <linux/sysrq.h> |
13 | 13 | ||
14 | #include <linux/consolemap.h> | ||
14 | #include <linux/kbd_kern.h> | 15 | #include <linux/kbd_kern.h> |
15 | #include <linux/kbd_diacr.h> | 16 | #include <linux/kbd_diacr.h> |
16 | #include <asm/uaccess.h> | 17 | #include <asm/uaccess.h> |
@@ -82,11 +83,11 @@ kbd_alloc(void) { | |||
82 | if (!kbd->fn_handler) | 83 | if (!kbd->fn_handler) |
83 | goto out_func; | 84 | goto out_func; |
84 | kbd->accent_table = | 85 | kbd->accent_table = |
85 | kmalloc(sizeof(struct kbdiacr)*MAX_DIACR, GFP_KERNEL); | 86 | kmalloc(sizeof(struct kbdiacruc)*MAX_DIACR, GFP_KERNEL); |
86 | if (!kbd->accent_table) | 87 | if (!kbd->accent_table) |
87 | goto out_fn_handler; | 88 | goto out_fn_handler; |
88 | memcpy(kbd->accent_table, accent_table, | 89 | memcpy(kbd->accent_table, accent_table, |
89 | sizeof(struct kbdiacr)*MAX_DIACR); | 90 | sizeof(struct kbdiacruc)*MAX_DIACR); |
90 | kbd->accent_table_size = accent_table_size; | 91 | kbd->accent_table_size = accent_table_size; |
91 | return kbd; | 92 | return kbd; |
92 | 93 | ||
@@ -183,8 +184,8 @@ kbd_ebcasc(struct kbd_data *kbd, unsigned char *ebcasc) | |||
183 | * Otherwise, conclude that DIACR was not combining after all, | 184 | * Otherwise, conclude that DIACR was not combining after all, |
184 | * queue it and return CH. | 185 | * queue it and return CH. |
185 | */ | 186 | */ |
186 | static unsigned char | 187 | static unsigned int |
187 | handle_diacr(struct kbd_data *kbd, unsigned char ch) | 188 | handle_diacr(struct kbd_data *kbd, unsigned int ch) |
188 | { | 189 | { |
189 | int i, d; | 190 | int i, d; |
190 | 191 | ||
@@ -460,7 +461,6 @@ int | |||
460 | kbd_ioctl(struct kbd_data *kbd, struct file *file, | 461 | kbd_ioctl(struct kbd_data *kbd, struct file *file, |
461 | unsigned int cmd, unsigned long arg) | 462 | unsigned int cmd, unsigned long arg) |
462 | { | 463 | { |
463 | struct kbdiacrs __user *a; | ||
464 | void __user *argp; | 464 | void __user *argp; |
465 | int ct, perm; | 465 | int ct, perm; |
466 | 466 | ||
@@ -481,17 +481,40 @@ kbd_ioctl(struct kbd_data *kbd, struct file *file, | |||
481 | case KDSKBSENT: | 481 | case KDSKBSENT: |
482 | return do_kdgkb_ioctl(kbd, argp, cmd, perm); | 482 | return do_kdgkb_ioctl(kbd, argp, cmd, perm); |
483 | case KDGKBDIACR: | 483 | case KDGKBDIACR: |
484 | a = argp; | 484 | { |
485 | struct kbdiacrs __user *a = argp; | ||
486 | struct kbdiacr diacr; | ||
487 | int i; | ||
485 | 488 | ||
486 | if (put_user(kbd->accent_table_size, &a->kb_cnt)) | 489 | if (put_user(kbd->accent_table_size, &a->kb_cnt)) |
487 | return -EFAULT; | 490 | return -EFAULT; |
491 | for (i = 0; i < kbd->accent_table_size; i++) { | ||
492 | diacr.diacr = kbd->accent_table[i].diacr; | ||
493 | diacr.base = kbd->accent_table[i].base; | ||
494 | diacr.result = kbd->accent_table[i].result; | ||
495 | if (copy_to_user(a->kbdiacr + i, &diacr, sizeof(struct kbdiacr))) | ||
496 | return -EFAULT; | ||
497 | } | ||
498 | return 0; | ||
499 | } | ||
500 | case KDGKBDIACRUC: | ||
501 | { | ||
502 | struct kbdiacrsuc __user *a = argp; | ||
503 | |||
488 | ct = kbd->accent_table_size; | 504 | ct = kbd->accent_table_size; |
489 | if (copy_to_user(a->kbdiacr, kbd->accent_table, | 505 | if (put_user(ct, &a->kb_cnt)) |
490 | ct * sizeof(struct kbdiacr))) | 506 | return -EFAULT; |
507 | if (copy_to_user(a->kbdiacruc, kbd->accent_table, | ||
508 | ct * sizeof(struct kbdiacruc))) | ||
491 | return -EFAULT; | 509 | return -EFAULT; |
492 | return 0; | 510 | return 0; |
511 | } | ||
493 | case KDSKBDIACR: | 512 | case KDSKBDIACR: |
494 | a = argp; | 513 | { |
514 | struct kbdiacrs __user *a = argp; | ||
515 | struct kbdiacr diacr; | ||
516 | int i; | ||
517 | |||
495 | if (!perm) | 518 | if (!perm) |
496 | return -EPERM; | 519 | return -EPERM; |
497 | if (get_user(ct, &a->kb_cnt)) | 520 | if (get_user(ct, &a->kb_cnt)) |
@@ -499,10 +522,31 @@ kbd_ioctl(struct kbd_data *kbd, struct file *file, | |||
499 | if (ct >= MAX_DIACR) | 522 | if (ct >= MAX_DIACR) |
500 | return -EINVAL; | 523 | return -EINVAL; |
501 | kbd->accent_table_size = ct; | 524 | kbd->accent_table_size = ct; |
502 | if (copy_from_user(kbd->accent_table, a->kbdiacr, | 525 | for (i = 0; i < ct; i++) { |
503 | ct * sizeof(struct kbdiacr))) | 526 | if (copy_from_user(&diacr, a->kbdiacr + i, sizeof(struct kbdiacr))) |
527 | return -EFAULT; | ||
528 | kbd->accent_table[i].diacr = diacr.diacr; | ||
529 | kbd->accent_table[i].base = diacr.base; | ||
530 | kbd->accent_table[i].result = diacr.result; | ||
531 | } | ||
532 | return 0; | ||
533 | } | ||
534 | case KDSKBDIACRUC: | ||
535 | { | ||
536 | struct kbdiacrsuc __user *a = argp; | ||
537 | |||
538 | if (!perm) | ||
539 | return -EPERM; | ||
540 | if (get_user(ct, &a->kb_cnt)) | ||
541 | return -EFAULT; | ||
542 | if (ct >= MAX_DIACR) | ||
543 | return -EINVAL; | ||
544 | kbd->accent_table_size = ct; | ||
545 | if (copy_from_user(kbd->accent_table, a->kbdiacruc, | ||
546 | ct * sizeof(struct kbdiacruc))) | ||
504 | return -EFAULT; | 547 | return -EFAULT; |
505 | return 0; | 548 | return 0; |
549 | } | ||
506 | default: | 550 | default: |
507 | return -ENOIOCTLCMD; | 551 | return -ENOIOCTLCMD; |
508 | } | 552 | } |