Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *  Copyright (c) 1999-2001 Vojtech Pavlik
0004  */
0005 
0006 /*
0007  * XT 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 "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);