diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/input/keyboard/newtonkbd.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/input/keyboard/newtonkbd.c')
-rw-r--r-- | drivers/input/keyboard/newtonkbd.c | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/drivers/input/keyboard/newtonkbd.c b/drivers/input/keyboard/newtonkbd.c new file mode 100644 index 000000000000..2e8ce1613eec --- /dev/null +++ b/drivers/input/keyboard/newtonkbd.c | |||
@@ -0,0 +1,184 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000 Justin Cormack | ||
3 | */ | ||
4 | |||
5 | /* | ||
6 | * Newton keyboard driver for Linux | ||
7 | */ | ||
8 | |||
9 | /* | ||
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. | ||
14 | * | ||
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. | ||
19 | * | ||
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 | ||
23 | * | ||
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. | ||
27 | */ | ||
28 | |||
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> | ||
34 | |||
35 | #define DRIVER_DESC "Newton keyboard driver" | ||
36 | |||
37 | MODULE_AUTHOR("Justin Cormack <j.cormack@doc.ic.ac.uk>"); | ||
38 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
39 | MODULE_LICENSE("GPL"); | ||
40 | |||
41 | #define NKBD_KEY 0x7f | ||
42 | #define NKBD_PRESS 0x80 | ||
43 | |||
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 | ||
58 | }; | ||
59 | |||
60 | static char *nkbd_name = "Newton Keyboard"; | ||
61 | |||
62 | struct nkbd { | ||
63 | unsigned char keycode[128]; | ||
64 | struct input_dev dev; | ||
65 | struct serio *serio; | ||
66 | char phys[32]; | ||
67 | }; | ||
68 | |||
69 | static irqreturn_t nkbd_interrupt(struct serio *serio, | ||
70 | unsigned char data, unsigned int flags, struct pt_regs *regs) | ||
71 | { | ||
72 | struct nkbd *nkbd = serio_get_drvdata(serio); | ||
73 | |||
74 | /* invalid scan codes are probably the init sequence, so we ignore them */ | ||
75 | if (nkbd->keycode[data & NKBD_KEY]) { | ||
76 | input_regs(&nkbd->dev, regs); | ||
77 | input_report_key(&nkbd->dev, nkbd->keycode[data & NKBD_KEY], data & NKBD_PRESS); | ||
78 | input_sync(&nkbd->dev); | ||
79 | } | ||
80 | |||
81 | else if (data == 0xe7) /* end of init sequence */ | ||
82 | printk(KERN_INFO "input: %s on %s\n", nkbd_name, serio->phys); | ||
83 | return IRQ_HANDLED; | ||
84 | |||
85 | } | ||
86 | |||
87 | static int nkbd_connect(struct serio *serio, struct serio_driver *drv) | ||
88 | { | ||
89 | struct nkbd *nkbd; | ||
90 | int i; | ||
91 | int err; | ||
92 | |||
93 | if (!(nkbd = kmalloc(sizeof(struct nkbd), GFP_KERNEL))) | ||
94 | return -ENOMEM; | ||
95 | |||
96 | memset(nkbd, 0, sizeof(struct nkbd)); | ||
97 | |||
98 | nkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP); | ||
99 | |||
100 | nkbd->serio = serio; | ||
101 | |||
102 | init_input_dev(&nkbd->dev); | ||
103 | nkbd->dev.keycode = nkbd->keycode; | ||
104 | nkbd->dev.keycodesize = sizeof(unsigned char); | ||
105 | nkbd->dev.keycodemax = ARRAY_SIZE(nkbd_keycode); | ||
106 | nkbd->dev.private = nkbd; | ||
107 | |||
108 | serio_set_drvdata(serio, nkbd); | ||
109 | |||
110 | err = serio_open(serio, drv); | ||
111 | if (err) { | ||
112 | serio_set_drvdata(serio, NULL); | ||
113 | kfree(nkbd); | ||
114 | return err; | ||
115 | } | ||
116 | |||
117 | memcpy(nkbd->keycode, nkbd_keycode, sizeof(nkbd->keycode)); | ||
118 | for (i = 0; i < 128; i++) | ||
119 | set_bit(nkbd->keycode[i], nkbd->dev.keybit); | ||
120 | clear_bit(0, nkbd->dev.keybit); | ||
121 | |||
122 | sprintf(nkbd->phys, "%s/input0", serio->phys); | ||
123 | |||
124 | nkbd->dev.name = nkbd_name; | ||
125 | nkbd->dev.phys = nkbd->phys; | ||
126 | nkbd->dev.id.bustype = BUS_RS232; | ||
127 | nkbd->dev.id.vendor = SERIO_NEWTON; | ||
128 | nkbd->dev.id.product = 0x0001; | ||
129 | nkbd->dev.id.version = 0x0100; | ||
130 | nkbd->dev.dev = &serio->dev; | ||
131 | |||
132 | input_register_device(&nkbd->dev); | ||
133 | |||
134 | printk(KERN_INFO "input: %s on %s\n", nkbd_name, serio->phys); | ||
135 | |||
136 | return 0; | ||
137 | } | ||
138 | |||
139 | static void nkbd_disconnect(struct serio *serio) | ||
140 | { | ||
141 | struct nkbd *nkbd = serio_get_drvdata(serio); | ||
142 | |||
143 | input_unregister_device(&nkbd->dev); | ||
144 | serio_close(serio); | ||
145 | serio_set_drvdata(serio, NULL); | ||
146 | kfree(nkbd); | ||
147 | } | ||
148 | |||
149 | static struct serio_device_id nkbd_serio_ids[] = { | ||
150 | { | ||
151 | .type = SERIO_RS232, | ||
152 | .proto = SERIO_NEWTON, | ||
153 | .id = SERIO_ANY, | ||
154 | .extra = SERIO_ANY, | ||
155 | }, | ||
156 | { 0 } | ||
157 | }; | ||
158 | |||
159 | MODULE_DEVICE_TABLE(serio, nkbd_serio_ids); | ||
160 | |||
161 | static struct serio_driver nkbd_drv = { | ||
162 | .driver = { | ||
163 | .name = "newtonkbd", | ||
164 | }, | ||
165 | .description = DRIVER_DESC, | ||
166 | .id_table = nkbd_serio_ids, | ||
167 | .interrupt = nkbd_interrupt, | ||
168 | .connect = nkbd_connect, | ||
169 | .disconnect = nkbd_disconnect, | ||
170 | }; | ||
171 | |||
172 | static int __init nkbd_init(void) | ||
173 | { | ||
174 | serio_register_driver(&nkbd_drv); | ||
175 | return 0; | ||
176 | } | ||
177 | |||
178 | static void __exit nkbd_exit(void) | ||
179 | { | ||
180 | serio_unregister_driver(&nkbd_drv); | ||
181 | } | ||
182 | |||
183 | module_init(nkbd_init); | ||
184 | module_exit(nkbd_exit); | ||