1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Copyright (c) 1999-2001 Vojtech Pavlik |
4 | * |
5 | * USB HIDBP Keyboard support |
6 | */ |
7 | |
8 | /* |
9 | * |
10 | * Should you need to contact me, the author, you can do so either by |
11 | * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: |
12 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic |
13 | */ |
14 | |
15 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
16 | |
17 | #include <linux/kernel.h> |
18 | #include <linux/slab.h> |
19 | #include <linux/module.h> |
20 | #include <linux/init.h> |
21 | #include <linux/usb/input.h> |
22 | #include <linux/hid.h> |
23 | |
24 | /* |
25 | * Version Information |
26 | */ |
27 | #define DRIVER_VERSION "" |
28 | #define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>" |
29 | #define DRIVER_DESC "USB HID Boot Protocol keyboard driver" |
30 | |
31 | MODULE_AUTHOR(DRIVER_AUTHOR); |
32 | MODULE_DESCRIPTION(DRIVER_DESC); |
33 | MODULE_LICENSE("GPL" ); |
34 | |
35 | static const unsigned char usb_kbd_keycode[256] = { |
36 | 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, |
37 | 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3, |
38 | 4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26, |
39 | 27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64, |
40 | 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106, |
41 | 105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71, |
42 | 72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190, |
43 | 191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113, |
44 | 115,114, 0, 0, 0,121, 0, 89, 93,124, 92, 94, 95, 0, 0, 0, |
45 | 122,123, 90, 91, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
46 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
47 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
48 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
49 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
50 | 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113, |
51 | 150,158,159,128,136,177,178,176,142,152,173,140 |
52 | }; |
53 | |
54 | |
55 | /** |
56 | * struct usb_kbd - state of each attached keyboard |
57 | * @dev: input device associated with this keyboard |
58 | * @usbdev: usb device associated with this keyboard |
59 | * @old: data received in the past from the @irq URB representing which |
60 | * keys were pressed. By comparing with the current list of keys |
61 | * that are pressed, we are able to see key releases. |
62 | * @irq: URB for receiving a list of keys that are pressed when a |
63 | * new key is pressed or a key that was pressed is released. |
64 | * @led: URB for sending LEDs (e.g. numlock, ...) |
65 | * @newleds: data that will be sent with the @led URB representing which LEDs |
66 | * should be on |
67 | * @name: Name of the keyboard. @dev's name field points to this buffer |
68 | * @phys: Physical path of the keyboard. @dev's phys field points to this |
69 | * buffer |
70 | * @new: Buffer for the @irq URB |
71 | * @cr: Control request for @led URB |
72 | * @leds: Buffer for the @led URB |
73 | * @new_dma: DMA address for @irq URB |
74 | * @leds_dma: DMA address for @led URB |
75 | * @leds_lock: spinlock that protects @leds, @newleds, and @led_urb_submitted |
76 | * @led_urb_submitted: indicates whether @led is in progress, i.e. it has been |
77 | * submitted and its completion handler has not returned yet |
78 | * without resubmitting @led |
79 | */ |
80 | struct usb_kbd { |
81 | struct input_dev *dev; |
82 | struct usb_device *usbdev; |
83 | unsigned char old[8]; |
84 | struct urb *irq, *led; |
85 | unsigned char newleds; |
86 | char name[128]; |
87 | char phys[64]; |
88 | |
89 | unsigned char *new; |
90 | struct usb_ctrlrequest *cr; |
91 | unsigned char *leds; |
92 | dma_addr_t new_dma; |
93 | dma_addr_t leds_dma; |
94 | |
95 | spinlock_t leds_lock; |
96 | bool led_urb_submitted; |
97 | |
98 | }; |
99 | |
100 | static void usb_kbd_irq(struct urb *urb) |
101 | { |
102 | struct usb_kbd *kbd = urb->context; |
103 | int i; |
104 | |
105 | switch (urb->status) { |
106 | case 0: /* success */ |
107 | break; |
108 | case -ECONNRESET: /* unlink */ |
109 | case -ENOENT: |
110 | case -ESHUTDOWN: |
111 | return; |
112 | /* -EPIPE: should clear the halt */ |
113 | default: /* error */ |
114 | goto resubmit; |
115 | } |
116 | |
117 | for (i = 0; i < 8; i++) |
118 | input_report_key(dev: kbd->dev, code: usb_kbd_keycode[i + 224], value: (kbd->new[0] >> i) & 1); |
119 | |
120 | for (i = 2; i < 8; i++) { |
121 | |
122 | if (kbd->old[i] > 3 && memscan(p: kbd->new + 2, c: kbd->old[i], size: 6) == kbd->new + 8) { |
123 | if (usb_kbd_keycode[kbd->old[i]]) |
124 | input_report_key(dev: kbd->dev, code: usb_kbd_keycode[kbd->old[i]], value: 0); |
125 | else |
126 | hid_info(urb->dev, |
127 | "Unknown key (scancode %#x) released.\n" , |
128 | kbd->old[i]); |
129 | } |
130 | |
131 | if (kbd->new[i] > 3 && memscan(p: kbd->old + 2, c: kbd->new[i], size: 6) == kbd->old + 8) { |
132 | if (usb_kbd_keycode[kbd->new[i]]) |
133 | input_report_key(dev: kbd->dev, code: usb_kbd_keycode[kbd->new[i]], value: 1); |
134 | else |
135 | hid_info(urb->dev, |
136 | "Unknown key (scancode %#x) pressed.\n" , |
137 | kbd->new[i]); |
138 | } |
139 | } |
140 | |
141 | input_sync(dev: kbd->dev); |
142 | |
143 | memcpy(kbd->old, kbd->new, 8); |
144 | |
145 | resubmit: |
146 | i = usb_submit_urb (urb, GFP_ATOMIC); |
147 | if (i) |
148 | hid_err(urb->dev, "can't resubmit intr, %s-%s/input0, status %d" , |
149 | kbd->usbdev->bus->bus_name, |
150 | kbd->usbdev->devpath, i); |
151 | } |
152 | |
153 | static int usb_kbd_event(struct input_dev *dev, unsigned int type, |
154 | unsigned int code, int value) |
155 | { |
156 | unsigned long flags; |
157 | struct usb_kbd *kbd = input_get_drvdata(dev); |
158 | |
159 | if (type != EV_LED) |
160 | return -1; |
161 | |
162 | spin_lock_irqsave(&kbd->leds_lock, flags); |
163 | kbd->newleds = (!!test_bit(LED_KANA, dev->led) << 3) | (!!test_bit(LED_COMPOSE, dev->led) << 3) | |
164 | (!!test_bit(LED_SCROLLL, dev->led) << 2) | (!!test_bit(LED_CAPSL, dev->led) << 1) | |
165 | (!!test_bit(LED_NUML, dev->led)); |
166 | |
167 | if (kbd->led_urb_submitted){ |
168 | spin_unlock_irqrestore(lock: &kbd->leds_lock, flags); |
169 | return 0; |
170 | } |
171 | |
172 | if (*(kbd->leds) == kbd->newleds){ |
173 | spin_unlock_irqrestore(lock: &kbd->leds_lock, flags); |
174 | return 0; |
175 | } |
176 | |
177 | *(kbd->leds) = kbd->newleds; |
178 | |
179 | kbd->led->dev = kbd->usbdev; |
180 | if (usb_submit_urb(urb: kbd->led, GFP_ATOMIC)) |
181 | pr_err("usb_submit_urb(leds) failed\n" ); |
182 | else |
183 | kbd->led_urb_submitted = true; |
184 | |
185 | spin_unlock_irqrestore(lock: &kbd->leds_lock, flags); |
186 | |
187 | return 0; |
188 | } |
189 | |
190 | static void usb_kbd_led(struct urb *urb) |
191 | { |
192 | unsigned long flags; |
193 | struct usb_kbd *kbd = urb->context; |
194 | |
195 | if (urb->status) |
196 | hid_warn(urb->dev, "led urb status %d received\n" , |
197 | urb->status); |
198 | |
199 | spin_lock_irqsave(&kbd->leds_lock, flags); |
200 | |
201 | if (*(kbd->leds) == kbd->newleds){ |
202 | kbd->led_urb_submitted = false; |
203 | spin_unlock_irqrestore(lock: &kbd->leds_lock, flags); |
204 | return; |
205 | } |
206 | |
207 | *(kbd->leds) = kbd->newleds; |
208 | |
209 | kbd->led->dev = kbd->usbdev; |
210 | if (usb_submit_urb(urb: kbd->led, GFP_ATOMIC)){ |
211 | hid_err(urb->dev, "usb_submit_urb(leds) failed\n" ); |
212 | kbd->led_urb_submitted = false; |
213 | } |
214 | spin_unlock_irqrestore(lock: &kbd->leds_lock, flags); |
215 | |
216 | } |
217 | |
218 | static int usb_kbd_open(struct input_dev *dev) |
219 | { |
220 | struct usb_kbd *kbd = input_get_drvdata(dev); |
221 | |
222 | kbd->irq->dev = kbd->usbdev; |
223 | if (usb_submit_urb(urb: kbd->irq, GFP_KERNEL)) |
224 | return -EIO; |
225 | |
226 | return 0; |
227 | } |
228 | |
229 | static void usb_kbd_close(struct input_dev *dev) |
230 | { |
231 | struct usb_kbd *kbd = input_get_drvdata(dev); |
232 | |
233 | usb_kill_urb(urb: kbd->irq); |
234 | } |
235 | |
236 | static int usb_kbd_alloc_mem(struct usb_device *dev, struct usb_kbd *kbd) |
237 | { |
238 | if (!(kbd->irq = usb_alloc_urb(iso_packets: 0, GFP_KERNEL))) |
239 | return -1; |
240 | if (!(kbd->led = usb_alloc_urb(iso_packets: 0, GFP_KERNEL))) |
241 | return -1; |
242 | if (!(kbd->new = usb_alloc_coherent(dev, size: 8, GFP_KERNEL, dma: &kbd->new_dma))) |
243 | return -1; |
244 | if (!(kbd->cr = kmalloc(size: sizeof(struct usb_ctrlrequest), GFP_KERNEL))) |
245 | return -1; |
246 | if (!(kbd->leds = usb_alloc_coherent(dev, size: 1, GFP_KERNEL, dma: &kbd->leds_dma))) |
247 | return -1; |
248 | |
249 | return 0; |
250 | } |
251 | |
252 | static void usb_kbd_free_mem(struct usb_device *dev, struct usb_kbd *kbd) |
253 | { |
254 | usb_free_urb(urb: kbd->irq); |
255 | usb_free_urb(urb: kbd->led); |
256 | usb_free_coherent(dev, size: 8, addr: kbd->new, dma: kbd->new_dma); |
257 | kfree(objp: kbd->cr); |
258 | usb_free_coherent(dev, size: 1, addr: kbd->leds, dma: kbd->leds_dma); |
259 | } |
260 | |
261 | static int usb_kbd_probe(struct usb_interface *iface, |
262 | const struct usb_device_id *id) |
263 | { |
264 | struct usb_device *dev = interface_to_usbdev(iface); |
265 | struct usb_host_interface *interface; |
266 | struct usb_endpoint_descriptor *endpoint; |
267 | struct usb_kbd *kbd; |
268 | struct input_dev *input_dev; |
269 | int i, pipe, maxp; |
270 | int error = -ENOMEM; |
271 | |
272 | interface = iface->cur_altsetting; |
273 | |
274 | if (interface->desc.bNumEndpoints != 1) |
275 | return -ENODEV; |
276 | |
277 | endpoint = &interface->endpoint[0].desc; |
278 | if (!usb_endpoint_is_int_in(epd: endpoint)) |
279 | return -ENODEV; |
280 | |
281 | pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); |
282 | maxp = usb_maxpacket(udev: dev, pipe); |
283 | |
284 | kbd = kzalloc(size: sizeof(struct usb_kbd), GFP_KERNEL); |
285 | input_dev = input_allocate_device(); |
286 | if (!kbd || !input_dev) |
287 | goto fail1; |
288 | |
289 | if (usb_kbd_alloc_mem(dev, kbd)) |
290 | goto fail2; |
291 | |
292 | kbd->usbdev = dev; |
293 | kbd->dev = input_dev; |
294 | spin_lock_init(&kbd->leds_lock); |
295 | |
296 | if (dev->manufacturer) |
297 | strscpy(p: kbd->name, q: dev->manufacturer, size: sizeof(kbd->name)); |
298 | |
299 | if (dev->product) { |
300 | if (dev->manufacturer) |
301 | strlcat(p: kbd->name, q: " " , avail: sizeof(kbd->name)); |
302 | strlcat(p: kbd->name, q: dev->product, avail: sizeof(kbd->name)); |
303 | } |
304 | |
305 | if (!strlen(kbd->name)) |
306 | snprintf(buf: kbd->name, size: sizeof(kbd->name), |
307 | fmt: "USB HIDBP Keyboard %04x:%04x" , |
308 | le16_to_cpu(dev->descriptor.idVendor), |
309 | le16_to_cpu(dev->descriptor.idProduct)); |
310 | |
311 | usb_make_path(dev, buf: kbd->phys, size: sizeof(kbd->phys)); |
312 | strlcat(p: kbd->phys, q: "/input0" , avail: sizeof(kbd->phys)); |
313 | |
314 | input_dev->name = kbd->name; |
315 | input_dev->phys = kbd->phys; |
316 | usb_to_input_id(dev, id: &input_dev->id); |
317 | input_dev->dev.parent = &iface->dev; |
318 | |
319 | input_set_drvdata(dev: input_dev, data: kbd); |
320 | |
321 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_LED) | |
322 | BIT_MASK(EV_REP); |
323 | input_dev->ledbit[0] = BIT_MASK(LED_NUML) | BIT_MASK(LED_CAPSL) | |
324 | BIT_MASK(LED_SCROLLL) | BIT_MASK(LED_COMPOSE) | |
325 | BIT_MASK(LED_KANA); |
326 | |
327 | for (i = 0; i < 255; i++) |
328 | set_bit(nr: usb_kbd_keycode[i], addr: input_dev->keybit); |
329 | clear_bit(nr: 0, addr: input_dev->keybit); |
330 | |
331 | input_dev->event = usb_kbd_event; |
332 | input_dev->open = usb_kbd_open; |
333 | input_dev->close = usb_kbd_close; |
334 | |
335 | usb_fill_int_urb(urb: kbd->irq, dev, pipe, |
336 | transfer_buffer: kbd->new, buffer_length: (maxp > 8 ? 8 : maxp), |
337 | complete_fn: usb_kbd_irq, context: kbd, interval: endpoint->bInterval); |
338 | kbd->irq->transfer_dma = kbd->new_dma; |
339 | kbd->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
340 | |
341 | kbd->cr->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE; |
342 | kbd->cr->bRequest = 0x09; |
343 | kbd->cr->wValue = cpu_to_le16(0x200); |
344 | kbd->cr->wIndex = cpu_to_le16(interface->desc.bInterfaceNumber); |
345 | kbd->cr->wLength = cpu_to_le16(1); |
346 | |
347 | usb_fill_control_urb(urb: kbd->led, dev, usb_sndctrlpipe(dev, 0), |
348 | setup_packet: (void *) kbd->cr, transfer_buffer: kbd->leds, buffer_length: 1, |
349 | complete_fn: usb_kbd_led, context: kbd); |
350 | kbd->led->transfer_dma = kbd->leds_dma; |
351 | kbd->led->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
352 | |
353 | error = input_register_device(kbd->dev); |
354 | if (error) |
355 | goto fail2; |
356 | |
357 | usb_set_intfdata(intf: iface, data: kbd); |
358 | device_set_wakeup_enable(dev: &dev->dev, enable: 1); |
359 | return 0; |
360 | |
361 | fail2: |
362 | usb_kbd_free_mem(dev, kbd); |
363 | fail1: |
364 | input_free_device(dev: input_dev); |
365 | kfree(objp: kbd); |
366 | return error; |
367 | } |
368 | |
369 | static void usb_kbd_disconnect(struct usb_interface *intf) |
370 | { |
371 | struct usb_kbd *kbd = usb_get_intfdata (intf); |
372 | |
373 | usb_set_intfdata(intf, NULL); |
374 | if (kbd) { |
375 | usb_kill_urb(urb: kbd->irq); |
376 | input_unregister_device(kbd->dev); |
377 | usb_kill_urb(urb: kbd->led); |
378 | usb_kbd_free_mem(interface_to_usbdev(intf), kbd); |
379 | kfree(objp: kbd); |
380 | } |
381 | } |
382 | |
383 | static const struct usb_device_id usb_kbd_id_table[] = { |
384 | { USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT, |
385 | USB_INTERFACE_PROTOCOL_KEYBOARD) }, |
386 | { } /* Terminating entry */ |
387 | }; |
388 | |
389 | MODULE_DEVICE_TABLE (usb, usb_kbd_id_table); |
390 | |
391 | static struct usb_driver usb_kbd_driver = { |
392 | .name = "usbkbd" , |
393 | .probe = usb_kbd_probe, |
394 | .disconnect = usb_kbd_disconnect, |
395 | .id_table = usb_kbd_id_table, |
396 | }; |
397 | |
398 | module_usb_driver(usb_kbd_driver); |
399 | |