Path: blob/master/drivers/input/keyboard/newtonkbd.c
15111 views
/*1* Copyright (c) 2000 Justin Cormack2*/34/*5* Newton keyboard driver for Linux6*/78/*9* This program is free software; you can redistribute it and/or modify10* it under the terms of the GNU General Public License as published by11* the Free Software Foundation; either version 2 of the License, or12* (at your option) any later version.13*14* This program is distributed in the hope that it will be useful,15* but WITHOUT ANY WARRANTY; without even the implied warranty of16* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the17* GNU General Public License for more details.18*19* You should have received a copy of the GNU General Public License20* along with this program; if not, write to the Free Software21* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA22*23* Should you need to contact me, the author, you can do so either by24* e-mail - mail your message to <[email protected]>, or by paper mail:25* Justin Cormack, 68 Dartmouth Park Road, London NW5 1SN, UK.26*/2728#include <linux/slab.h>29#include <linux/module.h>30#include <linux/input.h>31#include <linux/init.h>32#include <linux/serio.h>3334#define DRIVER_DESC "Newton keyboard driver"3536MODULE_AUTHOR("Justin Cormack <[email protected]>");37MODULE_DESCRIPTION(DRIVER_DESC);38MODULE_LICENSE("GPL");3940#define NKBD_KEY 0x7f41#define NKBD_PRESS 0x804243static unsigned char nkbd_keycode[128] = {44KEY_A, KEY_S, KEY_D, KEY_F, KEY_H, KEY_G, KEY_Z, KEY_X,45KEY_C, KEY_V, 0, KEY_B, KEY_Q, KEY_W, KEY_E, KEY_R,46KEY_Y, KEY_T, KEY_1, KEY_2, KEY_3, KEY_4, KEY_6, KEY_5,47KEY_EQUAL, KEY_9, KEY_7, KEY_MINUS, KEY_8, KEY_0, KEY_RIGHTBRACE, KEY_O,48KEY_U, KEY_LEFTBRACE, KEY_I, KEY_P, KEY_ENTER, KEY_L, KEY_J, KEY_APOSTROPHE,49KEY_K, KEY_SEMICOLON, KEY_BACKSLASH, KEY_COMMA, KEY_SLASH, KEY_N, KEY_M, KEY_DOT,50KEY_TAB, KEY_SPACE, KEY_GRAVE, KEY_DELETE, 0, 0, 0, KEY_LEFTMETA,51KEY_LEFTSHIFT, KEY_CAPSLOCK, KEY_LEFTALT, KEY_LEFTCTRL, KEY_RIGHTSHIFT, 0, 0, 0,520, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,530, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,540, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,550, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,56KEY_LEFT, KEY_RIGHT, KEY_DOWN, KEY_UP, 057};5859struct nkbd {60unsigned char keycode[128];61struct input_dev *dev;62struct serio *serio;63char phys[32];64};6566static irqreturn_t nkbd_interrupt(struct serio *serio,67unsigned char data, unsigned int flags)68{69struct nkbd *nkbd = serio_get_drvdata(serio);7071/* invalid scan codes are probably the init sequence, so we ignore them */72if (nkbd->keycode[data & NKBD_KEY]) {73input_report_key(nkbd->dev, nkbd->keycode[data & NKBD_KEY], data & NKBD_PRESS);74input_sync(nkbd->dev);75}7677else if (data == 0xe7) /* end of init sequence */78printk(KERN_INFO "input: %s on %s\n", nkbd->dev->name, serio->phys);79return IRQ_HANDLED;8081}8283static int nkbd_connect(struct serio *serio, struct serio_driver *drv)84{85struct nkbd *nkbd;86struct input_dev *input_dev;87int err = -ENOMEM;88int i;8990nkbd = kzalloc(sizeof(struct nkbd), GFP_KERNEL);91input_dev = input_allocate_device();92if (!nkbd || !input_dev)93goto fail1;9495nkbd->serio = serio;96nkbd->dev = input_dev;97snprintf(nkbd->phys, sizeof(nkbd->phys), "%s/input0", serio->phys);98memcpy(nkbd->keycode, nkbd_keycode, sizeof(nkbd->keycode));99100input_dev->name = "Newton Keyboard";101input_dev->phys = nkbd->phys;102input_dev->id.bustype = BUS_RS232;103input_dev->id.vendor = SERIO_NEWTON;104input_dev->id.product = 0x0001;105input_dev->id.version = 0x0100;106input_dev->dev.parent = &serio->dev;107108input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);109input_dev->keycode = nkbd->keycode;110input_dev->keycodesize = sizeof(unsigned char);111input_dev->keycodemax = ARRAY_SIZE(nkbd_keycode);112for (i = 0; i < 128; i++)113set_bit(nkbd->keycode[i], input_dev->keybit);114clear_bit(0, input_dev->keybit);115116serio_set_drvdata(serio, nkbd);117118err = serio_open(serio, drv);119if (err)120goto fail2;121122err = input_register_device(nkbd->dev);123if (err)124goto fail3;125126return 0;127128fail3: serio_close(serio);129fail2: serio_set_drvdata(serio, NULL);130fail1: input_free_device(input_dev);131kfree(nkbd);132return err;133}134135static void nkbd_disconnect(struct serio *serio)136{137struct nkbd *nkbd = serio_get_drvdata(serio);138139serio_close(serio);140serio_set_drvdata(serio, NULL);141input_unregister_device(nkbd->dev);142kfree(nkbd);143}144145static struct serio_device_id nkbd_serio_ids[] = {146{147.type = SERIO_RS232,148.proto = SERIO_NEWTON,149.id = SERIO_ANY,150.extra = SERIO_ANY,151},152{ 0 }153};154155MODULE_DEVICE_TABLE(serio, nkbd_serio_ids);156157static struct serio_driver nkbd_drv = {158.driver = {159.name = "newtonkbd",160},161.description = DRIVER_DESC,162.id_table = nkbd_serio_ids,163.interrupt = nkbd_interrupt,164.connect = nkbd_connect,165.disconnect = nkbd_disconnect,166};167168static int __init nkbd_init(void)169{170return serio_register_driver(&nkbd_drv);171}172173static void __exit nkbd_exit(void)174{175serio_unregister_driver(&nkbd_drv);176}177178module_init(nkbd_init);179module_exit(nkbd_exit);180181182