diff options
Diffstat (limited to 'drivers/input/keyboard/maple_keyb.c')
-rw-r--r-- | drivers/input/keyboard/maple_keyb.c | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/drivers/input/keyboard/maple_keyb.c b/drivers/input/keyboard/maple_keyb.c new file mode 100644 index 000000000000..859ed771ee0a --- /dev/null +++ b/drivers/input/keyboard/maple_keyb.c | |||
@@ -0,0 +1,190 @@ | |||
1 | /* | ||
2 | * $Id: maple_keyb.c,v 1.4 2004/03/22 01:18:15 lethal Exp $ | ||
3 | * SEGA Dreamcast keyboard driver | ||
4 | * Based on drivers/usb/usbkbd.c | ||
5 | */ | ||
6 | |||
7 | #include <linux/kernel.h> | ||
8 | #include <linux/slab.h> | ||
9 | #include <linux/input.h> | ||
10 | #include <linux/module.h> | ||
11 | #include <linux/init.h> | ||
12 | #include <linux/timer.h> | ||
13 | #include <linux/maple.h> | ||
14 | |||
15 | MODULE_AUTHOR("YAEGASHI Takeshi <t@keshi.org>"); | ||
16 | MODULE_DESCRIPTION("SEGA Dreamcast keyboard driver"); | ||
17 | MODULE_LICENSE("GPL"); | ||
18 | |||
19 | static unsigned char dc_kbd_keycode[256] = { | ||
20 | 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, | ||
21 | 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3, | ||
22 | 4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26, | ||
23 | 27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64, | ||
24 | 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106, | ||
25 | 105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71, | ||
26 | 72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190, | ||
27 | 191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113, | ||
28 | 115,114, 0, 0, 0,121, 0, 89, 93,124, 92, 94, 95, 0, 0, 0, | ||
29 | 122,123, 90, 91, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
30 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
31 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
32 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
33 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
34 | 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113, | ||
35 | 150,158,159,128,136,177,178,176,142,152,173,140 | ||
36 | }; | ||
37 | |||
38 | |||
39 | struct dc_kbd { | ||
40 | struct input_dev dev; | ||
41 | unsigned char new[8]; | ||
42 | unsigned char old[8]; | ||
43 | int open; | ||
44 | }; | ||
45 | |||
46 | |||
47 | static void dc_scan_kbd(struct dc_kbd *kbd) | ||
48 | { | ||
49 | int i; | ||
50 | struct input_dev *dev = &kbd->dev; | ||
51 | |||
52 | for(i=0; i<8; i++) | ||
53 | input_report_key(dev, | ||
54 | dc_kbd_keycode[i+224], | ||
55 | (kbd->new[0]>>i)&1); | ||
56 | |||
57 | for(i=2; i<8; i++) { | ||
58 | |||
59 | if(kbd->old[i]>3&&memscan(kbd->new+2, kbd->old[i], 6)==NULL) { | ||
60 | if(dc_kbd_keycode[kbd->old[i]]) | ||
61 | input_report_key(dev, | ||
62 | dc_kbd_keycode[kbd->old[i]], | ||
63 | 0); | ||
64 | else | ||
65 | printk("Unknown key (scancode %#x) released.", | ||
66 | kbd->old[i]); | ||
67 | } | ||
68 | |||
69 | if(kbd->new[i]>3&&memscan(kbd->old+2, kbd->new[i], 6)!=NULL) { | ||
70 | if(dc_kbd_keycode[kbd->new[i]]) | ||
71 | input_report_key(dev, | ||
72 | dc_kbd_keycode[kbd->new[i]], | ||
73 | 1); | ||
74 | else | ||
75 | printk("Unknown key (scancode %#x) pressed.", | ||
76 | kbd->new[i]); | ||
77 | } | ||
78 | } | ||
79 | |||
80 | input_sync(dev); | ||
81 | |||
82 | memcpy(kbd->old, kbd->new, 8); | ||
83 | } | ||
84 | |||
85 | |||
86 | static void dc_kbd_callback(struct mapleq *mq) | ||
87 | { | ||
88 | struct maple_device *mapledev = mq->dev; | ||
89 | struct dc_kbd *kbd = mapledev->private_data; | ||
90 | unsigned long *buf = mq->recvbuf; | ||
91 | |||
92 | if (buf[1] == mapledev->function) { | ||
93 | memcpy(kbd->new, buf+2, 8); | ||
94 | dc_scan_kbd(kbd); | ||
95 | } | ||
96 | } | ||
97 | |||
98 | |||
99 | static int dc_kbd_open(struct input_dev *dev) | ||
100 | { | ||
101 | struct dc_kbd *kbd = dev->private; | ||
102 | kbd->open++; | ||
103 | return 0; | ||
104 | } | ||
105 | |||
106 | |||
107 | static void dc_kbd_close(struct input_dev *dev) | ||
108 | { | ||
109 | struct dc_kbd *kbd = dev->private; | ||
110 | kbd->open--; | ||
111 | } | ||
112 | |||
113 | |||
114 | static int dc_kbd_connect(struct maple_device *dev) | ||
115 | { | ||
116 | int i; | ||
117 | unsigned long data = be32_to_cpu(dev->devinfo.function_data[0]); | ||
118 | struct dc_kbd *kbd; | ||
119 | |||
120 | if (!(kbd = kmalloc(sizeof(struct dc_kbd), GFP_KERNEL))) | ||
121 | return -1; | ||
122 | memset(kbd, 0, sizeof(struct dc_kbd)); | ||
123 | |||
124 | dev->private_data = kbd; | ||
125 | |||
126 | kbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP); | ||
127 | |||
128 | init_input_dev(&kbd->dev); | ||
129 | |||
130 | for (i=0; i<255; i++) | ||
131 | set_bit(dc_kbd_keycode[i], kbd->dev.keybit); | ||
132 | |||
133 | clear_bit(0, kbd->dev.keybit); | ||
134 | |||
135 | kbd->dev.private = kbd; | ||
136 | kbd->dev.open = dc_kbd_open; | ||
137 | kbd->dev.close = dc_kbd_close; | ||
138 | kbd->dev.event = NULL; | ||
139 | |||
140 | kbd->dev.name = dev->product_name; | ||
141 | kbd->dev.id.bustype = BUS_MAPLE; | ||
142 | |||
143 | input_register_device(&kbd->dev); | ||
144 | |||
145 | maple_getcond_callback(dev, dc_kbd_callback, 1, MAPLE_FUNC_KEYBOARD); | ||
146 | |||
147 | printk(KERN_INFO "input: keyboard(0x%lx): %s\n", data, kbd->dev.name); | ||
148 | |||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | |||
153 | static void dc_kbd_disconnect(struct maple_device *dev) | ||
154 | { | ||
155 | struct dc_kbd *kbd = dev->private_data; | ||
156 | |||
157 | input_unregister_device(&kbd->dev); | ||
158 | kfree(kbd); | ||
159 | } | ||
160 | |||
161 | |||
162 | static struct maple_driver dc_kbd_driver = { | ||
163 | .function = MAPLE_FUNC_KEYBOARD, | ||
164 | .name = "Dreamcast keyboard", | ||
165 | .connect = dc_kbd_connect, | ||
166 | .disconnect = dc_kbd_disconnect, | ||
167 | }; | ||
168 | |||
169 | |||
170 | static int __init dc_kbd_init(void) | ||
171 | { | ||
172 | maple_register_driver(&dc_kbd_driver); | ||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | |||
177 | static void __exit dc_kbd_exit(void) | ||
178 | { | ||
179 | maple_unregister_driver(&dc_kbd_driver); | ||
180 | } | ||
181 | |||
182 | |||
183 | module_init(dc_kbd_init); | ||
184 | module_exit(dc_kbd_exit); | ||
185 | |||
186 | /* | ||
187 | * Local variables: | ||
188 | * c-basic-offset: 8 | ||
189 | * End: | ||
190 | */ | ||