2  *  Copyright (c) 2000 Justin Cormack
 
   6  * Newton keyboard driver for Linux
 
  10  * This program is free software; you can redistribute it and/or modify
 
  11  * it under the terms of the GNU General Public License as published by
 
  12  * the Free Software Foundation; either version 2 of the License, or
 
  13  * (at your option) any later version.
 
  15  * This program is distributed in the hope that it will be useful,
 
  16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
  17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 
  18  * GNU General Public License for more details.
 
  20  * You should have received a copy of the GNU General Public License
 
  21  * along with this program; if not, write to the Free Software
 
  22  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
  24  * Should you need to contact me, the author, you can do so either by
 
  25  * e-mail - mail your message to <j.cormack@doc.ic.ac.uk>, or by paper mail:
 
  26  * Justin Cormack, 68 Dartmouth Park Road, London NW5 1SN, UK.
 
  29 #include <linux/slab.h>
 
  30 #include <linux/module.h>
 
  31 #include <linux/input.h>
 
  32 #include <linux/init.h>
 
  33 #include <linux/serio.h>
 
  35 #define DRIVER_DESC     "Newton keyboard driver"
 
  37 MODULE_AUTHOR("Justin Cormack <j.cormack@doc.ic.ac.uk>");
 
  38 MODULE_DESCRIPTION(DRIVER_DESC);
 
  39 MODULE_LICENSE("GPL");
 
  42 #define NKBD_PRESS      0x80
 
  44 static unsigned char nkbd_keycode[128] = {
 
  45         KEY_A, KEY_S, KEY_D, KEY_F, KEY_H, KEY_G, KEY_Z, KEY_X,
 
  46         KEY_C, KEY_V, 0, KEY_B, KEY_Q, KEY_W, KEY_E, KEY_R,
 
  47         KEY_Y, KEY_T, KEY_1, KEY_2, KEY_3, KEY_4, KEY_6, KEY_5,
 
  48         KEY_EQUAL, KEY_9, KEY_7, KEY_MINUS, KEY_8, KEY_0, KEY_RIGHTBRACE, KEY_O,
 
  49         KEY_U, KEY_LEFTBRACE, KEY_I, KEY_P, KEY_ENTER, KEY_L, KEY_J, KEY_APOSTROPHE,
 
  50         KEY_K, KEY_SEMICOLON, KEY_BACKSLASH, KEY_COMMA, KEY_SLASH, KEY_N, KEY_M, KEY_DOT,
 
  51         KEY_TAB, KEY_SPACE, KEY_GRAVE, KEY_DELETE, 0, 0, 0, KEY_LEFTMETA,
 
  52         KEY_LEFTSHIFT, KEY_CAPSLOCK, KEY_LEFTALT, KEY_LEFTCTRL, KEY_RIGHTSHIFT, 0, 0, 0,
 
  53         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
  54         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
  55         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
  56         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
  57         KEY_LEFT, KEY_RIGHT, KEY_DOWN, KEY_UP, 0
 
  61         unsigned char keycode[128];
 
  62         struct input_dev *dev;
 
  67 static irqreturn_t nkbd_interrupt(struct serio *serio,
 
  68                 unsigned char data, unsigned int flags)
 
  70         struct nkbd *nkbd = serio_get_drvdata(serio);
 
  72         /* invalid scan codes are probably the init sequence, so we ignore them */
 
  73         if (nkbd->keycode[data & NKBD_KEY]) {
 
  74                 input_report_key(nkbd->dev, nkbd->keycode[data & NKBD_KEY], data & NKBD_PRESS);
 
  75                 input_sync(nkbd->dev);
 
  78         else if (data == 0xe7) /* end of init sequence */
 
  79                 printk(KERN_INFO "input: %s on %s\n", nkbd->dev->name, serio->phys);
 
  84 static int nkbd_connect(struct serio *serio, struct serio_driver *drv)
 
  87         struct input_dev *input_dev;
 
  91         nkbd = kzalloc(sizeof(struct nkbd), GFP_KERNEL);
 
  92         input_dev = input_allocate_device();
 
  93         if (!nkbd || !input_dev)
 
  97         nkbd->dev = input_dev;
 
  98         snprintf(nkbd->phys, sizeof(nkbd->phys), "%s/input0", serio->phys);
 
  99         memcpy(nkbd->keycode, nkbd_keycode, sizeof(nkbd->keycode));
 
 101         input_dev->name = "Newton Keyboard";
 
 102         input_dev->phys = nkbd->phys;
 
 103         input_dev->id.bustype = BUS_RS232;
 
 104         input_dev->id.vendor = SERIO_NEWTON;
 
 105         input_dev->id.product = 0x0001;
 
 106         input_dev->id.version = 0x0100;
 
 107         input_dev->cdev.dev = &serio->dev;
 
 108         input_dev->private = nkbd;
 
 110         input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
 
 111         input_dev->keycode = nkbd->keycode;
 
 112         input_dev->keycodesize = sizeof(unsigned char);
 
 113         input_dev->keycodemax = ARRAY_SIZE(nkbd_keycode);
 
 114         for (i = 0; i < 128; i++)
 
 115                 set_bit(nkbd->keycode[i], input_dev->keybit);
 
 116         clear_bit(0, input_dev->keybit);
 
 118         serio_set_drvdata(serio, nkbd);
 
 120         err = serio_open(serio, drv);
 
 124         err = input_register_device(nkbd->dev);
 
 130  fail3: serio_close(serio);
 
 131  fail2: serio_set_drvdata(serio, NULL);
 
 132  fail1: input_free_device(input_dev);
 
 137 static void nkbd_disconnect(struct serio *serio)
 
 139         struct nkbd *nkbd = serio_get_drvdata(serio);
 
 142         serio_set_drvdata(serio, NULL);
 
 143         input_unregister_device(nkbd->dev);
 
 147 static struct serio_device_id nkbd_serio_ids[] = {
 
 150                 .proto  = SERIO_NEWTON,
 
 157 MODULE_DEVICE_TABLE(serio, nkbd_serio_ids);
 
 159 static struct serio_driver nkbd_drv = {
 
 163         .description    = DRIVER_DESC,
 
 164         .id_table       = nkbd_serio_ids,
 
 165         .interrupt      = nkbd_interrupt,
 
 166         .connect        = nkbd_connect,
 
 167         .disconnect     = nkbd_disconnect,
 
 170 static int __init nkbd_init(void)
 
 172         return serio_register_driver(&nkbd_drv);
 
 175 static void __exit nkbd_exit(void)
 
 177         serio_unregister_driver(&nkbd_drv);
 
 180 module_init(nkbd_init);
 
 181 module_exit(nkbd_exit);