aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/char/keyboard.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/char/keyboard.c')
-rw-r--r--drivers/s390/char/keyboard.c66
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 */
186static unsigned char 187static unsigned int
187handle_diacr(struct kbd_data *kbd, unsigned char ch) 188handle_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
460kbd_ioctl(struct kbd_data *kbd, struct file *file, 461kbd_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 }