1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (c) 1999-2001 Vojtech Pavlik 4 */ 5 6 /* 7 * XT keyboard driver for Linux 8 */ 9 10 #include <linux/slab.h> 11 #include <linux/module.h> 12 #include <linux/input.h> 13 #include <linux/serio.h> 14 15 #define DRIVER_DESC "XT keyboard driver" 16 17 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); 18 MODULE_DESCRIPTION(DRIVER_DESC); 19 MODULE_LICENSE("GPL"); 20 21 #define XTKBD_EMUL0 0xe0 22 #define XTKBD_EMUL1 0xe1 23 #define XTKBD_KEY 0x7f 24 #define XTKBD_RELEASE 0x80 25 26 static unsigned char xtkbd_keycode[256] = { 27 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 28 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 29 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 30 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 31 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 32 80, 81, 82, 83, 0, 0, 0, 87, 88, 0, 0, 0, 0, 0, 0, 0, 33 0, 0, 0, 0, 0, 87, 88, 0, 0, 0, 0,110,111,103,108,105, 34 106 35 }; 36 37 struct xtkbd { 38 unsigned char keycode[256]; 39 struct input_dev *dev; 40 struct serio *serio; 41 char phys[32]; 42 }; 43 44 static irqreturn_t xtkbd_interrupt(struct serio *serio, 45 unsigned char data, unsigned int flags) 46 { 47 struct xtkbd *xtkbd = serio_get_drvdata(serio); 48 49 switch (data) { 50 case XTKBD_EMUL0: 51 case XTKBD_EMUL1: 52 break; 53 default: 54 55 if (xtkbd->keycode[data & XTKBD_KEY]) { 56 input_report_key(xtkbd->dev, xtkbd->keycode[data & XTKBD_KEY], !(data & XTKBD_RELEASE)); 57 input_sync(xtkbd->dev); 58 } else { 59 printk(KERN_WARNING "xtkbd.c: Unknown key (scancode %#x) %s.\n", 60 data & XTKBD_KEY, data & XTKBD_RELEASE ? "released" : "pressed"); 61 } 62 } 63 return IRQ_HANDLED; 64 } 65 66 static int xtkbd_connect(struct serio *serio, struct serio_driver *drv) 67 { 68 struct xtkbd *xtkbd; 69 struct input_dev *input_dev; 70 int err = -ENOMEM; 71 int i; 72 73 xtkbd = kmalloc(sizeof(struct xtkbd), GFP_KERNEL); 74 input_dev = input_allocate_device(); 75 if (!xtkbd || !input_dev) 76 goto fail1; 77 78 xtkbd->serio = serio; 79 xtkbd->dev = input_dev; 80 snprintf(xtkbd->phys, sizeof(xtkbd->phys), "%s/input0", serio->phys); 81 memcpy(xtkbd->keycode, xtkbd_keycode, sizeof(xtkbd->keycode)); 82 83 input_dev->name = "XT Keyboard"; 84 input_dev->phys = xtkbd->phys; 85 input_dev->id.bustype = BUS_XTKBD; 86 input_dev->id.vendor = 0x0001; 87 input_dev->id.product = 0x0001; 88 input_dev->id.version = 0x0100; 89 input_dev->dev.parent = &serio->dev; 90 91 input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); 92 input_dev->keycode = xtkbd->keycode; 93 input_dev->keycodesize = sizeof(unsigned char); 94 input_dev->keycodemax = ARRAY_SIZE(xtkbd_keycode); 95 96 for (i = 0; i < 255; i++) 97 set_bit(xtkbd->keycode[i], input_dev->keybit); 98 clear_bit(0, input_dev->keybit); 99 100 serio_set_drvdata(serio, xtkbd); 101 102 err = serio_open(serio, drv); 103 if (err) 104 goto fail2; 105 106 err = input_register_device(xtkbd->dev); 107 if (err) 108 goto fail3; 109 110 return 0; 111 112 fail3: serio_close(serio); 113 fail2: serio_set_drvdata(serio, NULL); 114 fail1: input_free_device(input_dev); 115 kfree(xtkbd); 116 return err; 117 } 118 119 static void xtkbd_disconnect(struct serio *serio) 120 { 121 struct xtkbd *xtkbd = serio_get_drvdata(serio); 122 123 serio_close(serio); 124 serio_set_drvdata(serio, NULL); 125 input_unregister_device(xtkbd->dev); 126 kfree(xtkbd); 127 } 128 129 static const struct serio_device_id xtkbd_serio_ids[] = { 130 { 131 .type = SERIO_XT, 132 .proto = SERIO_ANY, 133 .id = SERIO_ANY, 134 .extra = SERIO_ANY, 135 }, 136 { 0 } 137 }; 138 139 MODULE_DEVICE_TABLE(serio, xtkbd_serio_ids); 140 141 static struct serio_driver xtkbd_drv = { 142 .driver = { 143 .name = "xtkbd", 144 }, 145 .description = DRIVER_DESC, 146 .id_table = xtkbd_serio_ids, 147 .interrupt = xtkbd_interrupt, 148 .connect = xtkbd_connect, 149 .disconnect = xtkbd_disconnect, 150 }; 151 152 module_serio_driver(xtkbd_drv); 153