From: Justin C. <jp...@do...> - 2001-01-14 17:49:00
|
ok, here's a ruby patch to add a Newton keyboard driver. It is a nice portable serial keyboard that Apple sold may years back. If noone has any suggestions for changes I'll submit it to 2.4 as well. The only thing about 2.4 is that serio.c is in drivers/char/joystick and this will go into drivers/char: serio really ought to move to char, as it is not joystick specific. Justin diff -u -r -N ruby-orig/linux/drivers/input/Config.in ruby/linux/drivers/input/Config.in --- ruby-orig/linux/drivers/input/Config.in Sat Nov 11 12:37:01 2000 +++ ruby/linux/drivers/input/Config.in Sun Jan 14 17:09:14 2001 @@ -37,6 +37,7 @@ tristate ' Gravis Stinger gamepad' CONFIG_INPUT_STINGER tristate ' I-Force joysticks/wheels' CONFIG_INPUT_IFORCE_232 tristate ' Gunze AHL-51S touchscreen' CONFIG_INPUT_GUNZE + tristate ' Newton keyboard' CONFIG_INPUT_NEWTON fi bool 'Standard Game port support' CONFIG_INPUT_GAMEPORT diff -u -r -N ruby-orig/linux/drivers/input/Makefile ruby/linux/drivers/input/Makefile --- ruby-orig/linux/drivers/input/Makefile Sat Nov 11 12:37:01 2000 +++ ruby/linux/drivers/input/Makefile Sun Jan 14 17:09:14 2001 @@ -50,6 +50,7 @@ obj-$(CONFIG_INPUT_ATKBD) += atkbd.o serio.o obj-$(CONFIG_INPUT_XTKBD) += xtkbd.o serio.o obj-$(CONFIG_INPUT_PSMOUSE) += psmouse.o serio.o +obj-$(CONFIG_INPUT_NEWTON) += newtonkbd.o serio.o obj-$(CONFIG_INPUT_SERMOUSE) += sermouse.o serio.o obj-$(CONFIG_INPUT_SUNKBD) += sunkbd.o serio.o diff -u -r -N ruby-orig/linux/drivers/input/newtonkbd.c ruby/linux/drivers/input/newtonkbd.c --- ruby-orig/linux/drivers/input/newtonkbd.c Thu Jan 1 01:00:00 1970 +++ ruby/linux/drivers/input/newtonkbd.c Sun Jan 14 17:32:20 2001 @@ -0,0 +1,152 @@ +/* + * + * + * Copyright (c) 2000 Justin Cormack + * + * + */ + +/* + * Newton keyboard driver for Linux + */ + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Should you need to contact me, the author, you can do so either by + * e-mail - mail your message to <j.c...@do...>, or by paper mail: + * Justin Cormack, 68 Dartmouth Park Road, London NW5 1SN, UK. + */ + +#include <linux/malloc.h> +#include <linux/module.h> +#include <linux/input.h> +#include <linux/init.h> +#include <linux/serio.h> + +MODULE_AUTHOR("Justin Cormack <j.c...@do...>"); + +#define NKBD_KEY 0x7f +#define NKBD_PRESS 0x80 + +static unsigned char nkbd_keycode[128] = { + KEY_A, KEY_S, KEY_D, KEY_F, KEY_H, KEY_G, KEY_Z, KEY_X, + KEY_C, KEY_V, 0, KEY_B, KEY_Q, KEY_W, KEY_E, KEY_R, + KEY_Y, KEY_T, KEY_1, KEY_2, KEY_3, KEY_4, KEY_6, KEY_5, + KEY_EQUAL, KEY_9, KEY_7, KEY_MINUS, KEY_8, KEY_0, KEY_RIGHTBRACE, KEY_O, + KEY_U, KEY_LEFTBRACE, KEY_I, KEY_P, KEY_ENTER, KEY_L, KEY_J, KEY_APOSTROPHE, + KEY_K, KEY_SEMICOLON, KEY_BACKSLASH, KEY_COMMA, KEY_SLASH, KEY_N, KEY_M, KEY_DOT, + KEY_TAB, KEY_SPACE, KEY_GRAVE, KEY_DELETE, 0, 0, 0, KEY_LEFTMETA, + KEY_LEFTSHIFT, KEY_CAPSLOCK, KEY_LEFTALT, KEY_LEFTCTRL, KEY_RIGHTSHIFT, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, KEY_LEFT, KEY_RIGHT, KEY_DOWN, KEY_UP, 0 +}; + +static char *nkbd_name = "Newton Keyboard"; + +struct nkbd { + unsigned char keycode[128]; + struct input_dev dev; + struct serio *serio; +}; + +void nkbd_interrupt(struct serio *serio, unsigned char data, unsigned int flags) +{ + struct nkbd *nkbd = serio->private; + + /* invalid scan codes are probably the init sequence, so we ignore them */ + if (nkbd->keycode[data & NKBD_KEY]) + input_report_key(&nkbd->dev, nkbd->keycode[data & NKBD_KEY], data & NKBD_PRESS); + else if (data == 0xe7) /* end of init sequence */ + printk(KERN_INFO "input%d: %s on serio%d\n", nkbd->dev.number, nkbd_name, serio->number); + +} + +void nkbd_connect(struct serio *serio, struct serio_dev *dev) +{ + struct nkbd *nkbd; + int i; + + if (serio->type != (SERIO_RS232 | SERIO_NEWTON)) + return; + + if (!(nkbd = kmalloc(sizeof(struct nkbd), GFP_KERNEL))) + return; + + memset(nkbd, 0, sizeof(struct nkbd)); + + nkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP); + + nkbd->serio = serio; + + nkbd->dev.keycode = nkbd->keycode; + nkbd->dev.private = nkbd; + + serio->private = nkbd; + + if (serio_open(serio, dev)) { + kfree(nkbd); + return; + } + + memcpy(nkbd->keycode, nkbd_keycode, sizeof(nkbd->keycode)); + for (i = 0; i < 128; i++) + set_bit(nkbd->keycode[i], nkbd->dev.keybit); + clear_bit(0, nkbd->dev.keybit); + + nkbd->dev.name = nkbd_name; + nkbd->dev.idbus = BUS_RS232; + nkbd->dev.idvendor = SERIO_NEWTON; + nkbd->dev.idproduct = 0x0001; + nkbd->dev.idversion = 0x0100; + + input_register_device(&nkbd->dev); + + printk(KERN_INFO "input%d: %s on serio%d\n", nkbd->dev.number, nkbd_name, serio->number); +} + +void nkbd_disconnect(struct serio *serio) +{ + struct nkbd *nkbd = serio->private; + input_unregister_device(&nkbd->dev); + serio_close(serio); + kfree(nkbd); +} + +struct serio_dev nkbd_dev = { + interrupt: nkbd_interrupt, + connect: nkbd_connect, + disconnect: nkbd_disconnect +}; + +int __init nkbd_init(void) +{ + serio_register_device(&nkbd_dev); + return 0; +} + +void __exit nkbd_exit(void) +{ + serio_unregister_device(&nkbd_dev); +} + +module_init(nkbd_init); +module_exit(nkbd_exit); diff -u -r -N ruby-orig/linux/include/linux/serio.h ruby/linux/include/linux/serio.h --- ruby-orig/linux/include/linux/serio.h Mon Jul 17 11:42:14 2000 +++ ruby/linux/include/linux/serio.h Sun Jan 14 17:09:14 2001 @@ -104,6 +104,7 @@ #define SERIO_GUNZE 0x1c #define SERIO_IFORCE 0x1d #define SERIO_STINGER 0x1e +#define SERIO_NEWTON 0x1f #define SERIO_ID 0xff00UL #define SERIO_EXTRA 0xff0000UL diff -u -r -N ruby-orig/utils/inputattach.c ruby/utils/inputattach.c --- ruby-orig/utils/inputattach.c Mon Jul 17 11:42:15 2000 +++ ruby/utils/inputattach.c Sun Jan 14 17:09:14 2001 @@ -147,6 +147,24 @@ return 0; } +int newton_init(int fd) +{ + int i; + unsigned char c; + unsigned char response[35] = + { 0x16, 0x10, 0x02, 0x64, 0x5f, 0x69, 0x64, 0x00, + 0x00, 0x00, 0x0c, 0x6b, 0x79, 0x62, 0x64, 0x61, + 0x70, 0x70, 0x6c, 0x00, 0x00, 0x00, 0x01, 0x6e, + 0x6f, 0x66, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x03, 0xdd, 0xe7 }; + + for (i = 0; i < 35; i++) + if (readchar(fd, &c, 400) || (c != response[i])) + return -1; + + return 0; +} + int dump_init(int fd) { unsigned char c, o = 0; @@ -190,6 +208,7 @@ { "--intellimouse", "-ms3", B1200, CS7, SERIO_MZ, 0x11, 1, NULL }, + for (i = 0; i < 35; i++) + if (readchar(fd, &c, 400) || (c != response[i])) + return -1; + + return 0; +} + int dump_init(int fd) { unsigned char c, o = 0; @@ -190,6 +208,7 @@ { "--intellimouse", "-ms3", B1200, CS7, SERIO_MZ, 0x11, 1, NULL }, { "--mmwheel", "-mmw", B1200, CS7 | CSTOPB, SERIO_MZP, 0x13, 1, mzp_init }, { "--iforce", "-ifor", B38400, CS8 | CRTSCTS, SERIO_IFORCE, 0x00, 0, NULL }, +{ "--newtonkbd", "-newt", B9600, CS8, SERIO_NEWTON, 0x00, 0, newton_init }, { "--dump", "-dump", B1200, CS7, 0, 0x00, 0, dump_init }, { "", "", 0, 0 } |