Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *  Copyright (c) 2000 Justin Cormack
0004  */
0005 
0006 /*
0007  * Newton keyboard driver for Linux
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     /* invalid scan codes are probably the init sequence, so we ignore them */
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) /* end of init sequence */
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);