Path: blob/master/drivers/input/keyboard/stowaway.c
15109 views
/*1* Stowaway keyboard driver for Linux2*/34/*5* Copyright (c) 2006 Marek Vasut6*7* Based on Newton keyboard driver for Linux8* by Justin Cormack9*/1011/*12* This program is free software; you can redistribute it and/or modify13* it under the terms of the GNU General Public License as published by14* the Free Software Foundation; either version 2 of the License, or15* (at your option) any later version.16*17* This program is distributed in the hope that it will be useful,18* but WITHOUT ANY WARRANTY; without even the implied warranty of19* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the20* GNU General Public License for more details.21*22* You should have received a copy of the GNU General Public License23* along with this program; if not, write to the Free Software24* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA25*26* Should you need to contact me, the author, you can do so either by27* e-mail - mail your message to <[email protected]>, or by paper mail:28* Marek Vasut, Liskovecka 559, Frydek-Mistek, 738 01 Czech Republic29*/3031#include <linux/slab.h>32#include <linux/module.h>33#include <linux/input.h>34#include <linux/init.h>35#include <linux/serio.h>3637#define DRIVER_DESC "Stowaway keyboard driver"3839MODULE_AUTHOR("Marek Vasut <[email protected]>");40MODULE_DESCRIPTION(DRIVER_DESC);41MODULE_LICENSE("GPL");4243#define SKBD_KEY_MASK 0x7f44#define SKBD_RELEASE 0x804546static unsigned char skbd_keycode[128] = {47KEY_1, KEY_2, KEY_3, KEY_Z, KEY_4, KEY_5, KEY_6, KEY_7,480, KEY_Q, KEY_W, KEY_E, KEY_R, KEY_T, KEY_Y, KEY_GRAVE,49KEY_X, KEY_A, KEY_S, KEY_D, KEY_F, KEY_G, KEY_H, KEY_SPACE,50KEY_CAPSLOCK, KEY_TAB, KEY_LEFTCTRL, 0, 0, 0, 0, 0,510, 0, 0, KEY_LEFTALT, 0, 0, 0, 0,520, 0, 0, 0, KEY_C, KEY_V, KEY_B, KEY_N,53KEY_MINUS, KEY_EQUAL, KEY_BACKSPACE, KEY_HOME, KEY_8, KEY_9, KEY_0, KEY_ESC,54KEY_LEFTBRACE, KEY_RIGHTBRACE, KEY_BACKSLASH, KEY_END, KEY_U, KEY_I, KEY_O, KEY_P,55KEY_APOSTROPHE, KEY_ENTER, KEY_PAGEUP,0, KEY_J, KEY_K, KEY_L, KEY_SEMICOLON,56KEY_SLASH, KEY_UP, KEY_PAGEDOWN, 0,KEY_M, KEY_COMMA, KEY_DOT, KEY_INSERT,57KEY_DELETE, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0,58KEY_LEFTSHIFT, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0,590, 0, 0, 0, 0, 0, 0, 0,600, 0, 0, 0, 0, 0, 0, 0,610, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_F7,62KEY_F8, KEY_F9, KEY_F10, KEY_F11, KEY_F12, 0, 0, 063};6465struct skbd {66unsigned char keycode[128];67struct input_dev *dev;68struct serio *serio;69char phys[32];70};7172static irqreturn_t skbd_interrupt(struct serio *serio, unsigned char data,73unsigned int flags)74{75struct skbd *skbd = serio_get_drvdata(serio);76struct input_dev *dev = skbd->dev;7778if (skbd->keycode[data & SKBD_KEY_MASK]) {79input_report_key(dev, skbd->keycode[data & SKBD_KEY_MASK],80!(data & SKBD_RELEASE));81input_sync(dev);82}8384return IRQ_HANDLED;85}8687static int skbd_connect(struct serio *serio, struct serio_driver *drv)88{89struct skbd *skbd;90struct input_dev *input_dev;91int err = -ENOMEM;92int i;9394skbd = kzalloc(sizeof(struct skbd), GFP_KERNEL);95input_dev = input_allocate_device();96if (!skbd || !input_dev)97goto fail1;9899skbd->serio = serio;100skbd->dev = input_dev;101snprintf(skbd->phys, sizeof(skbd->phys), "%s/input0", serio->phys);102memcpy(skbd->keycode, skbd_keycode, sizeof(skbd->keycode));103104input_dev->name = "Stowaway Keyboard";105input_dev->phys = skbd->phys;106input_dev->id.bustype = BUS_RS232;107input_dev->id.vendor = SERIO_STOWAWAY;108input_dev->id.product = 0x0001;109input_dev->id.version = 0x0100;110input_dev->dev.parent = &serio->dev;111112input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);113input_dev->keycode = skbd->keycode;114input_dev->keycodesize = sizeof(unsigned char);115input_dev->keycodemax = ARRAY_SIZE(skbd_keycode);116for (i = 0; i < ARRAY_SIZE(skbd_keycode); i++)117set_bit(skbd_keycode[i], input_dev->keybit);118clear_bit(0, input_dev->keybit);119120serio_set_drvdata(serio, skbd);121122err = serio_open(serio, drv);123if (err)124goto fail2;125126err = input_register_device(skbd->dev);127if (err)128goto fail3;129130return 0;131132fail3: serio_close(serio);133fail2: serio_set_drvdata(serio, NULL);134fail1: input_free_device(input_dev);135kfree(skbd);136return err;137}138139static void skbd_disconnect(struct serio *serio)140{141struct skbd *skbd = serio_get_drvdata(serio);142143serio_close(serio);144serio_set_drvdata(serio, NULL);145input_unregister_device(skbd->dev);146kfree(skbd);147}148149static struct serio_device_id skbd_serio_ids[] = {150{151.type = SERIO_RS232,152.proto = SERIO_STOWAWAY,153.id = SERIO_ANY,154.extra = SERIO_ANY,155},156{ 0 }157};158159MODULE_DEVICE_TABLE(serio, skbd_serio_ids);160161static struct serio_driver skbd_drv = {162.driver = {163.name = "stowaway",164},165.description = DRIVER_DESC,166.id_table = skbd_serio_ids,167.interrupt = skbd_interrupt,168.connect = skbd_connect,169.disconnect = skbd_disconnect,170};171172static int __init skbd_init(void)173{174return serio_register_driver(&skbd_drv);175}176177static void __exit skbd_exit(void)178{179serio_unregister_driver(&skbd_drv);180}181182module_init(skbd_init);183module_exit(skbd_exit);184185186