diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 4a91774..7853409 100644 Index: linux-dev/drivers/input/keyboard/Kconfig =================================================================== --- linux-dev.orig/drivers/input/keyboard/Kconfig 2005-12-28 14:22:26.000000000 -0800 +++ linux-dev/drivers/input/keyboard/Kconfig 2005-12-28 14:24:45.000000000 -0800 @@ -121,6 +121,12 @@ To compile this driver as a module, choose M here: the module will be called newtonkbd. +config KEYBOARD_SMTKBD + tristate "Smart Keyboard" + select SERIO + help + Say Y here to enable Smart Keyboard based + config KEYBOARD_CORGI tristate "Corgi keyboard" depends on PXA_SHARPSL Index: linux-dev/drivers/input/keyboard/Makefile =================================================================== --- linux-dev.orig/drivers/input/keyboard/Makefile 2005-12-28 14:22:26.000000000 -0800 +++ linux-dev/drivers/input/keyboard/Makefile 2005-12-29 06:35:59.000000000 -0800 @@ -12,6 +12,7 @@ obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o obj-$(CONFIG_KEYBOARD_LOCOMO) += locomokbd.o obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o +obj-$(CONFIG_KEYBOARD_SMTKBD) += smtkbd.o obj-$(CONFIG_KEYBOARD_98KBD) += 98kbd.o obj-$(CONFIG_KEYBOARD_CORGI) += corgikbd.o obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o Index: linux-dev/drivers/input/keyboard/smtkbd.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-dev/drivers/input/keyboard/smtkbd.c 2005-12-29 11:00:46.000000000 -0800 @@ -0,0 +1,235 @@ +/* + * Bluetooth Smart Keyboard driver for Linux + * by Maikichi + */ + +#include +#include +#include +#include +#include + +#define DRIVER_DESC "Smart keyboard driver" + +static char debug = 0; +MODULE_PARM(debug, "c"); + +#define SERIO_SMTKBD 0x23 + +/* + Use Standard keycode defined by + + HOME -> LEFT META + CIRCLE -> GRAVE + DEL -> ESC +*/ +static unsigned char smtkbd_keycode[128] = { + 0 , KEY_1 , KEY_2 , KEY_3 , + KEY_4 , KEY_5 , KEY_6 , KEY_Q , + KEY_W , KEY_E , KEY_R , KEY_T , + KEY_A , KEY_S , KEY_D , KEY_F , + + KEY_G , KEY_Z , KEY_X , KEY_C , + KEY_V , KEY_B , KEY_SPACE , KEY_TAB , + KEY_CAPSLOCK , KEY_LEFTMETA , KEY_7 , KEY_8 , + KEY_9 , KEY_0 , KEY_MINUS , KEY_EQUAL , + + KEY_BACKSPACE , KEY_Y , KEY_U , KEY_I , + KEY_O , KEY_P , KEY_LEFTBRACE , KEY_RIGHTBRACE , + KEY_H , KEY_J , KEY_K , KEY_L , + KEY_SEMICOLON , KEY_APOSTROPHE , KEY_ENTER , KEY_N , + + KEY_M , KEY_COMMA , KEY_DOT , KEY_SLASH , + KEY_UP , KEY_SPACE , KEY_GRAVE , KEY_LEFT , + KEY_DOWN , KEY_RIGHT , KEY_LEFTCTRL , KEY_RIGHTSHIFT , + KEY_LEFTSHIFT , KEY_ESC/*DEL*/ , 0/*FUNC*/ , KEY_LEFTALT , + + /* +Funk Key */ + 0 , KEY_F1 , KEY_F2 , KEY_F3 , + KEY_F4 , KEY_F5 , KEY_F6 , 0/*KEY_Q*/ , + 0/*KEY_W*/ , 0/*KEY_E*/ , 0/*KEY_R*/ , 0/*KEY_T*/ , + 0/*KEY_A*/ , 0/*KEY_S*/ , 0/*KEY_D*/ , 0/*KEY_F*/ , + + 0/*KEY_G*/ , 0/*KEY_Z*/ , 0/*KEY_X*/ , 0/*KEY_C*/ , + 0/*KEY_V*/ , 0/*KEY_B*/ , KEY_SPACE , KEY_TAB , + KEY_CAPSLOCK , KEY_RIGHTMETA , KEY_F7 , KEY_F8 , + KEY_F9 , KEY_F10 , KEY_F11 , KEY_F12 , + + KEY_DELETE , 0/*KEY_Y*/ , 0/*KEY_U*/ , KEY_SYSRQ , + KEY_SCROLLLOCK , KEY_PAUSE , KEY_UP , KEY_BACKSLASH , + KEY_KPASTERISK , KEY_KPSLASH , KEY_HOME , KEY_PAGEUP , + KEY_LEFT , KEY_RIGHT , KEY_ENTER , KEY_KPPLUS , + + KEY_KPMINUS , KEY_END , KEY_PAGEDOWN , KEY_DOWN , + KEY_UP , KEY_SPACE , KEY_GRAVE , KEY_LEFT , + KEY_DOWN , KEY_RIGHT , KEY_RIGHTCTRL , KEY_RIGHTSHIFT , + KEY_LEFTSHIFT , KEY_ESC/*DEL*/ , 0/*FUNC*/ , KEY_RIGHTALT +}; + +struct smart_keyboard { + unsigned char keycode[128]; + unsigned char press[32]; /* 256/8 */ + unsigned char func; + struct input_dev *dev; + struct serio *serio; + char phys[32]; +}; + +static irqreturn_t smtkbd_interrupt(struct serio *serio, unsigned char data, + unsigned int flags, struct pt_regs *regs) +{ + struct smart_keyboard *smtkbd = serio_get_drvdata(serio); + unsigned char keycode; + unsigned char release; + int i, j; + + if (data == 0x3e || data == 0x7d) { + + /* Press or release [Func] key */ + smtkbd->func = (data & 0x40) ? 0 : 1; + + /* Release all keys */ + for (i = 0; i < 32; i++) { + for (j = 0; j < 8; j++) + if (smtkbd->press[i] & (1 << j)) + input_report_key(smtkbd->dev, i * 8 + j, 0); + smtkbd->press[i] = 0; + } + + } else { + release = (data & 0x40) ? 1 : 0; + keycode = smtkbd->keycode[(data & 0x3f) + release + + (smtkbd->func * 64)]; + if (keycode) { + input_report_key(smtkbd->dev, keycode, + release ? 0 : 1); + if (release) + smtkbd->press[keycode / 8] &= ~(1 << (keycode % 8)); + else + smtkbd->press[keycode / 8] |= (1 << (keycode % 8)); + + if (debug) + printk(KERN_INFO "Smart Keyboard [%d] : %s\n", + keycode, release ? "Release" : "Press"); + } + } + + return IRQ_HANDLED; +} + +static int smtkbd_connect(struct serio *serio, struct serio_driver *drv) +{ + struct smart_keyboard *smtkbd; + struct input_dev *input_dev; + int err = -ENOMEM; + int i; + +#if 0 + if (serio->type != (SERIO_RS232 | SERIO_SMTKBD)) + return -ENODEV; +#endif + + smtkbd = kzalloc(sizeof(struct smart_keyboard), GFP_KERNEL); + input_dev = input_allocate_device(); + if (!smtkbd || !input_dev) + goto fail; + + smtkbd->serio = serio; + smtkbd->dev = input_dev; + sprintf(smtkbd->phys, "%s/input0", serio->phys); + memcpy(smtkbd->keycode, smtkbd_keycode, sizeof(smtkbd->keycode)); + + input_dev->name = "Smart Keyboard"; + input_dev->phys = smtkbd->phys; + input_dev->id.bustype = BUS_RS232; + input_dev->id.vendor = SERIO_SMTKBD; + input_dev->id.product = 0x0001; + input_dev->id.version = 0x0100; + input_dev->cdev.dev = &serio->dev; + input_dev->private = smtkbd; + + input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); + input_dev->keycode = smtkbd->keycode; + input_dev->keycodesize = sizeof(unsigned char); + input_dev->keycodemax = ARRAY_SIZE(smtkbd_keycode); + for (i = 0; i < 128; i++) + set_bit(smtkbd->keycode[i], input_dev->keybit); + clear_bit(0, input_dev->keybit); + + serio_set_drvdata(serio, smtkbd); + + err = serio_open(serio, drv); + if (err) + goto fail; + + input_register_device(smtkbd->dev); + return 0; + + fail: + serio_set_drvdata(serio, NULL); + input_free_device(input_dev); + kfree(smtkbd); + return err; +} + +void smtkbd_disconnect(struct serio *serio) +{ + struct smart_keyboard *smtkbd = serio_get_drvdata(serio); +#if 0 + int i, j; + + /* Release All Key */ + for (i = 0; i < 32; i++) { + for (j = 0; j < 8; j++) + if (smtkbd->press[i] & (1 << j)) + input_report_key(smtkbd->dev, i * 8 + j, 0); + smtkbd->press[i]=0; + } +#endif + + serio_close(serio); + serio_set_drvdata(serio, NULL); + input_unregister_device(smtkbd->dev); + kfree(smtkbd); +} + +static struct serio_device_id smtkbd_serio_ids[] = { + { + .type = SERIO_RS232, + .proto = SERIO_SMTKBD, + //.proto = SERIO_STOWAWAY, + .id = SERIO_ANY, + .extra = SERIO_ANY, + }, + { 0 } +}; +MODULE_DEVICE_TABLE(serio, smtkbd_serio_ids); + +static struct serio_driver smtkbd_drv = { + .driver = { + .name = "smtkbd", + }, + .description = DRIVER_DESC, + .id_table = smtkbd_serio_ids, + .interrupt = smtkbd_interrupt, + .connect = smtkbd_connect, + .disconnect = smtkbd_disconnect +}; + +static int __init smtkbd_init(void) +{ + serio_register_driver(&smtkbd_drv); + return 0; +} + +static void __exit smtkbd_exit(void) +{ + serio_unregister_driver(&smtkbd_drv); +} + +module_init(smtkbd_init); +module_exit(smtkbd_exit); + +MODULE_AUTHOR("maikichi "); +MODULE_DESCRIPTION("Bluetooth Smart Keyboard driver"); +MODULE_LICENSE("GPL");