0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <linux/slab.h>
0014 #include <linux/module.h>
0015 #include <linux/input.h>
0016 #include <linux/serio.h>
0017
0018 #define DRIVER_DESC "XT keyboard driver"
0019
0020 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
0021 MODULE_DESCRIPTION(DRIVER_DESC);
0022 MODULE_LICENSE("GPL");
0023
0024 #define XTKBD_EMUL0 0xe0
0025 #define XTKBD_EMUL1 0xe1
0026 #define XTKBD_KEY 0x7f
0027 #define XTKBD_RELEASE 0x80
0028
0029 static unsigned char xtkbd_keycode[256] = {
0030 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
0031 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
0032 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
0033 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
0034 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
0035 80, 81, 82, 83, 0, 0, 0, 87, 88, 0, 0, 0, 0, 0, 0, 0,
0036 0, 0, 0, 0, 0, 87, 88, 0, 0, 0, 0,110,111,103,108,105,
0037 106
0038 };
0039
0040 struct xtkbd {
0041 unsigned char keycode[256];
0042 struct input_dev *dev;
0043 struct serio *serio;
0044 char phys[32];
0045 };
0046
0047 static irqreturn_t xtkbd_interrupt(struct serio *serio,
0048 unsigned char data, unsigned int flags)
0049 {
0050 struct xtkbd *xtkbd = serio_get_drvdata(serio);
0051
0052 switch (data) {
0053 case XTKBD_EMUL0:
0054 case XTKBD_EMUL1:
0055 break;
0056 default:
0057
0058 if (xtkbd->keycode[data & XTKBD_KEY]) {
0059 input_report_key(xtkbd->dev, xtkbd->keycode[data & XTKBD_KEY], !(data & XTKBD_RELEASE));
0060 input_sync(xtkbd->dev);
0061 } else {
0062 printk(KERN_WARNING "xtkbd.c: Unknown key (scancode %#x) %s.\n",
0063 data & XTKBD_KEY, data & XTKBD_RELEASE ? "released" : "pressed");
0064 }
0065 }
0066 return IRQ_HANDLED;
0067 }
0068
0069 static int xtkbd_connect(struct serio *serio, struct serio_driver *drv)
0070 {
0071 struct xtkbd *xtkbd;
0072 struct input_dev *input_dev;
0073 int err = -ENOMEM;
0074 int i;
0075
0076 xtkbd = kmalloc(sizeof(struct xtkbd), GFP_KERNEL);
0077 input_dev = input_allocate_device();
0078 if (!xtkbd || !input_dev)
0079 goto fail1;
0080
0081 xtkbd->serio = serio;
0082 xtkbd->dev = input_dev;
0083 snprintf(xtkbd->phys, sizeof(xtkbd->phys), "%s/input0", serio->phys);
0084 memcpy(xtkbd->keycode, xtkbd_keycode, sizeof(xtkbd->keycode));
0085
0086 input_dev->name = "XT Keyboard";
0087 input_dev->phys = xtkbd->phys;
0088 input_dev->id.bustype = BUS_XTKBD;
0089 input_dev->id.vendor = 0x0001;
0090 input_dev->id.product = 0x0001;
0091 input_dev->id.version = 0x0100;
0092 input_dev->dev.parent = &serio->dev;
0093
0094 input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
0095 input_dev->keycode = xtkbd->keycode;
0096 input_dev->keycodesize = sizeof(unsigned char);
0097 input_dev->keycodemax = ARRAY_SIZE(xtkbd_keycode);
0098
0099 for (i = 0; i < 255; i++)
0100 set_bit(xtkbd->keycode[i], input_dev->keybit);
0101 clear_bit(0, input_dev->keybit);
0102
0103 serio_set_drvdata(serio, xtkbd);
0104
0105 err = serio_open(serio, drv);
0106 if (err)
0107 goto fail2;
0108
0109 err = input_register_device(xtkbd->dev);
0110 if (err)
0111 goto fail3;
0112
0113 return 0;
0114
0115 fail3: serio_close(serio);
0116 fail2: serio_set_drvdata(serio, NULL);
0117 fail1: input_free_device(input_dev);
0118 kfree(xtkbd);
0119 return err;
0120 }
0121
0122 static void xtkbd_disconnect(struct serio *serio)
0123 {
0124 struct xtkbd *xtkbd = serio_get_drvdata(serio);
0125
0126 serio_close(serio);
0127 serio_set_drvdata(serio, NULL);
0128 input_unregister_device(xtkbd->dev);
0129 kfree(xtkbd);
0130 }
0131
0132 static const struct serio_device_id xtkbd_serio_ids[] = {
0133 {
0134 .type = SERIO_XT,
0135 .proto = SERIO_ANY,
0136 .id = SERIO_ANY,
0137 .extra = SERIO_ANY,
0138 },
0139 { 0 }
0140 };
0141
0142 MODULE_DEVICE_TABLE(serio, xtkbd_serio_ids);
0143
0144 static struct serio_driver xtkbd_drv = {
0145 .driver = {
0146 .name = "xtkbd",
0147 },
0148 .description = DRIVER_DESC,
0149 .id_table = xtkbd_serio_ids,
0150 .interrupt = xtkbd_interrupt,
0151 .connect = xtkbd_connect,
0152 .disconnect = xtkbd_disconnect,
0153 };
0154
0155 module_serio_driver(xtkbd_drv);