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 "Newton keyboard driver"
0019
0020 MODULE_AUTHOR("Justin Cormack <j.cormack@doc.ic.ac.uk>");
0021 MODULE_DESCRIPTION(DRIVER_DESC);
0022 MODULE_LICENSE("GPL");
0023
0024 #define NKBD_KEY 0x7f
0025 #define NKBD_PRESS 0x80
0026
0027 static unsigned char nkbd_keycode[128] = {
0028 KEY_A, KEY_S, KEY_D, KEY_F, KEY_H, KEY_G, KEY_Z, KEY_X,
0029 KEY_C, KEY_V, 0, KEY_B, KEY_Q, KEY_W, KEY_E, KEY_R,
0030 KEY_Y, KEY_T, KEY_1, KEY_2, KEY_3, KEY_4, KEY_6, KEY_5,
0031 KEY_EQUAL, KEY_9, KEY_7, KEY_MINUS, KEY_8, KEY_0, KEY_RIGHTBRACE, KEY_O,
0032 KEY_U, KEY_LEFTBRACE, KEY_I, KEY_P, KEY_ENTER, KEY_L, KEY_J, KEY_APOSTROPHE,
0033 KEY_K, KEY_SEMICOLON, KEY_BACKSLASH, KEY_COMMA, KEY_SLASH, KEY_N, KEY_M, KEY_DOT,
0034 KEY_TAB, KEY_SPACE, KEY_GRAVE, KEY_DELETE, 0, 0, 0, KEY_LEFTMETA,
0035 KEY_LEFTSHIFT, KEY_CAPSLOCK, KEY_LEFTALT, KEY_LEFTCTRL, KEY_RIGHTSHIFT, 0, 0, 0,
0036 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0037 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0038 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0039 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0040 KEY_LEFT, KEY_RIGHT, KEY_DOWN, KEY_UP, 0
0041 };
0042
0043 struct nkbd {
0044 unsigned char keycode[128];
0045 struct input_dev *dev;
0046 struct serio *serio;
0047 char phys[32];
0048 };
0049
0050 static irqreturn_t nkbd_interrupt(struct serio *serio,
0051 unsigned char data, unsigned int flags)
0052 {
0053 struct nkbd *nkbd = serio_get_drvdata(serio);
0054
0055
0056 if (nkbd->keycode[data & NKBD_KEY]) {
0057 input_report_key(nkbd->dev, nkbd->keycode[data & NKBD_KEY], data & NKBD_PRESS);
0058 input_sync(nkbd->dev);
0059 }
0060
0061 else if (data == 0xe7)
0062 printk(KERN_INFO "input: %s on %s\n", nkbd->dev->name, serio->phys);
0063 return IRQ_HANDLED;
0064
0065 }
0066
0067 static int nkbd_connect(struct serio *serio, struct serio_driver *drv)
0068 {
0069 struct nkbd *nkbd;
0070 struct input_dev *input_dev;
0071 int err = -ENOMEM;
0072 int i;
0073
0074 nkbd = kzalloc(sizeof(struct nkbd), GFP_KERNEL);
0075 input_dev = input_allocate_device();
0076 if (!nkbd || !input_dev)
0077 goto fail1;
0078
0079 nkbd->serio = serio;
0080 nkbd->dev = input_dev;
0081 snprintf(nkbd->phys, sizeof(nkbd->phys), "%s/input0", serio->phys);
0082 memcpy(nkbd->keycode, nkbd_keycode, sizeof(nkbd->keycode));
0083
0084 input_dev->name = "Newton Keyboard";
0085 input_dev->phys = nkbd->phys;
0086 input_dev->id.bustype = BUS_RS232;
0087 input_dev->id.vendor = SERIO_NEWTON;
0088 input_dev->id.product = 0x0001;
0089 input_dev->id.version = 0x0100;
0090 input_dev->dev.parent = &serio->dev;
0091
0092 input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
0093 input_dev->keycode = nkbd->keycode;
0094 input_dev->keycodesize = sizeof(unsigned char);
0095 input_dev->keycodemax = ARRAY_SIZE(nkbd_keycode);
0096 for (i = 0; i < 128; i++)
0097 set_bit(nkbd->keycode[i], input_dev->keybit);
0098 clear_bit(0, input_dev->keybit);
0099
0100 serio_set_drvdata(serio, nkbd);
0101
0102 err = serio_open(serio, drv);
0103 if (err)
0104 goto fail2;
0105
0106 err = input_register_device(nkbd->dev);
0107 if (err)
0108 goto fail3;
0109
0110 return 0;
0111
0112 fail3: serio_close(serio);
0113 fail2: serio_set_drvdata(serio, NULL);
0114 fail1: input_free_device(input_dev);
0115 kfree(nkbd);
0116 return err;
0117 }
0118
0119 static void nkbd_disconnect(struct serio *serio)
0120 {
0121 struct nkbd *nkbd = serio_get_drvdata(serio);
0122
0123 serio_close(serio);
0124 serio_set_drvdata(serio, NULL);
0125 input_unregister_device(nkbd->dev);
0126 kfree(nkbd);
0127 }
0128
0129 static const struct serio_device_id nkbd_serio_ids[] = {
0130 {
0131 .type = SERIO_RS232,
0132 .proto = SERIO_NEWTON,
0133 .id = SERIO_ANY,
0134 .extra = SERIO_ANY,
0135 },
0136 { 0 }
0137 };
0138
0139 MODULE_DEVICE_TABLE(serio, nkbd_serio_ids);
0140
0141 static struct serio_driver nkbd_drv = {
0142 .driver = {
0143 .name = "newtonkbd",
0144 },
0145 .description = DRIVER_DESC,
0146 .id_table = nkbd_serio_ids,
0147 .interrupt = nkbd_interrupt,
0148 .connect = nkbd_connect,
0149 .disconnect = nkbd_disconnect,
0150 };
0151
0152 module_serio_driver(nkbd_drv);