Blame view
common/usb_kbd.c
13.4 KB
affae2bff Initial revision |
1 2 3 4 5 6 7 |
/* * (C) Copyright 2001 * Denis Peter, MPL AG Switzerland * * Part of this source has been derived from the Linux USB * project. * |
1a4596601 Add GPL-2.0+ SPDX... |
8 |
* SPDX-License-Identifier: GPL-2.0+ |
affae2bff Initial revision |
9 10 |
*/ #include <common.h> |
0ea09dfe8 usb: kbd: Do not ... |
11 |
#include <errno.h> |
9a8c72a6c USB: Rework usb_k... |
12 |
#include <malloc.h> |
52cb4d4fb stdio/device: rew... |
13 |
#include <stdio_dev.h> |
c918261c6 USB: replace old ... |
14 |
#include <asm/byteorder.h> |
affae2bff Initial revision |
15 |
|
affae2bff Initial revision |
16 |
#include <usb.h> |
affae2bff Initial revision |
17 |
/* |
00b7d6ecc USB: Squash check... |
18 |
* If overwrite_console returns 1, the stdin, stderr and stdout |
affae2bff Initial revision |
19 20 21 |
* are switched to the serial port, else the settings in the * environment are used */ |
6d0f6bcf3 rename CFG_ macro... |
22 |
#ifdef CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE |
00b7d6ecc USB: Squash check... |
23 |
extern int overwrite_console(void); |
affae2bff Initial revision |
24 |
#else |
00b7d6ecc USB: Squash check... |
25 |
int overwrite_console(void) |
affae2bff Initial revision |
26 |
{ |
00b7d6ecc USB: Squash check... |
27 |
return 0; |
affae2bff Initial revision |
28 29 |
} #endif |
9a8c72a6c USB: Rework usb_k... |
30 31 32 |
/* Keyboard sampling rate */ #define REPEAT_RATE (40 / 4) /* 40msec -> 25cps */ #define REPEAT_DELAY 10 /* 10 x REPEAT_RATE = 400msec */ |
affae2bff Initial revision |
33 34 |
#define NUM_LOCK 0x53 |
00b7d6ecc USB: Squash check... |
35 36 |
#define CAPS_LOCK 0x39 #define SCROLL_LOCK 0x47 |
affae2bff Initial revision |
37 |
|
affae2bff Initial revision |
38 |
/* Modifier bits */ |
9a8c72a6c USB: Rework usb_k... |
39 40 41 42 43 44 45 46 47 48 49 50 51 |
#define LEFT_CNTR (1 << 0) #define LEFT_SHIFT (1 << 1) #define LEFT_ALT (1 << 2) #define LEFT_GUI (1 << 3) #define RIGHT_CNTR (1 << 4) #define RIGHT_SHIFT (1 << 5) #define RIGHT_ALT (1 << 6) #define RIGHT_GUI (1 << 7) /* Size of the keyboard buffer */ #define USB_KBD_BUFFER_LEN 0x20 /* Device name */ |
00b7d6ecc USB: Squash check... |
52 |
#define DEVNAME "usbkbd" |
affae2bff Initial revision |
53 |
|
9a8c72a6c USB: Rework usb_k... |
54 55 |
/* Keyboard maps */ static const unsigned char usb_kbd_numkey[] = { |
00b7d6ecc USB: Squash check... |
56 57 58 |
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '\r', 0x1b, '\b', '\t', ' ', '-', '=', '[', ']', '\\', '#', ';', '\'', '`', ',', '.', '/' |
affae2bff Initial revision |
59 |
}; |
9a8c72a6c USB: Rework usb_k... |
60 |
static const unsigned char usb_kbd_numkey_shifted[] = { |
00b7d6ecc USB: Squash check... |
61 62 63 |
'!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '\r', 0x1b, '\b', '\t', ' ', '_', '+', '{', '}', '|', '~', ':', '"', '~', '<', '>', '?' |
affae2bff Initial revision |
64 |
}; |
d53da847c usb: add numeric ... |
65 66 67 68 69 |
static const unsigned char usb_kbd_num_keypad[] = { '/', '*', '-', '+', '\r', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '.', 0, 0, 0, '=' }; |
9a8c72a6c USB: Rework usb_k... |
70 |
/* |
4151a400c USB: add arrow ke... |
71 72 73 74 75 76 77 78 79 |
* map arrow keys to ^F/^B ^N/^P, can't really use the proper * ANSI sequence for arrow keys because the queuing code breaks * when a single keypress expands to 3 queue elements */ static const unsigned char usb_kbd_arrow[] = { 0x6, 0x2, 0xe, 0x10 }; /* |
9a8c72a6c USB: Rework usb_k... |
80 81 82 83 84 85 86 |
* NOTE: It's important for the NUM, CAPS, SCROLL-lock bits to be in this * order. See usb_kbd_setled() function! */ #define USB_KBD_NUMLOCK (1 << 0) #define USB_KBD_CAPSLOCK (1 << 1) #define USB_KBD_SCROLLLOCK (1 << 2) #define USB_KBD_CTRL (1 << 3) |
48c8073ec USB: Add function... |
87 |
|
9a8c72a6c USB: Rework usb_k... |
88 89 |
#define USB_KBD_LEDMASK \ (USB_KBD_NUMLOCK | USB_KBD_CAPSLOCK | USB_KBD_SCROLLLOCK) |
48c8073ec USB: Add function... |
90 |
|
08a98b89d usb: Fix USB keyb... |
91 92 93 94 95 |
/* * USB Keyboard reports are 8 bytes in boot protocol. * Appendix B of HID Device Class Definition 1.11 */ #define USB_KBD_BOOT_REPORT_SIZE 8 |
9a8c72a6c USB: Rework usb_k... |
96 97 |
struct usb_kbd_pdata { uint32_t repeat_delay; |
affae2bff Initial revision |
98 |
|
9a8c72a6c USB: Rework usb_k... |
99 100 101 |
uint32_t usb_in_pointer; uint32_t usb_out_pointer; uint8_t usb_kbd_buffer[USB_KBD_BUFFER_LEN]; |
48c8073ec USB: Add function... |
102 |
|
d7475386b USB: make usb_kbd... |
103 |
uint8_t *new; |
08a98b89d usb: Fix USB keyb... |
104 |
uint8_t old[USB_KBD_BOOT_REPORT_SIZE]; |
48c8073ec USB: Add function... |
105 |
|
9a8c72a6c USB: Rework usb_k... |
106 107 |
uint8_t flags; }; |
48c8073ec USB: Add function... |
108 |
|
07551f234 console: usb: kbd... |
109 110 111 112 |
extern int __maybe_unused net_busy_flag; /* The period of time between two calls of usb_kbd_testc(). */ static unsigned long __maybe_unused kbd_testc_tms; |
9a8c72a6c USB: Rework usb_k... |
113 114 |
/* Generic keyboard event polling. */ void usb_kbd_generic_poll(void) |
affae2bff Initial revision |
115 |
{ |
48c8073ec USB: Add function... |
116 117 |
struct stdio_dev *dev; struct usb_device *usb_kbd_dev; |
9a8c72a6c USB: Rework usb_k... |
118 119 120 121 122 |
struct usb_kbd_pdata *data; struct usb_interface *iface; struct usb_endpoint_descriptor *ep; int pipe; int maxp; |
48c8073ec USB: Add function... |
123 |
|
9a8c72a6c USB: Rework usb_k... |
124 125 |
/* Get the pointer to USB Keyboard device pointer */ dev = stdio_get_by_name(DEVNAME); |
48c8073ec USB: Add function... |
126 |
usb_kbd_dev = (struct usb_device *)dev->priv; |
9a8c72a6c USB: Rework usb_k... |
127 128 129 130 |
data = usb_kbd_dev->privptr; iface = &usb_kbd_dev->config.if_desc[0]; ep = &iface->ep_desc[0]; pipe = usb_rcvintpipe(usb_kbd_dev, ep->bEndpointAddress); |
48c8073ec USB: Add function... |
131 |
|
9a8c72a6c USB: Rework usb_k... |
132 133 134 |
/* Submit a interrupt transfer request */ maxp = usb_maxpacket(usb_kbd_dev, pipe); usb_submit_int_msg(usb_kbd_dev, pipe, data->new, |
08a98b89d usb: Fix USB keyb... |
135 136 |
min(maxp, USB_KBD_BOOT_REPORT_SIZE), ep->bInterval); |
affae2bff Initial revision |
137 |
} |
9a8c72a6c USB: Rework usb_k... |
138 139 |
/* Puts character in the queue and sets up the in and out pointer. */ static void usb_kbd_put_queue(struct usb_kbd_pdata *data, char c) |
affae2bff Initial revision |
140 |
{ |
9a8c72a6c USB: Rework usb_k... |
141 142 143 144 |
if (data->usb_in_pointer == USB_KBD_BUFFER_LEN - 1) { /* Check for buffer full. */ if (data->usb_out_pointer == 0) return; |
affae2bff Initial revision |
145 |
|
9a8c72a6c USB: Rework usb_k... |
146 147 148 149 150 |
data->usb_in_pointer = 0; } else { /* Check for buffer full. */ if (data->usb_in_pointer == data->usb_out_pointer - 1) return; |
affae2bff Initial revision |
151 |
|
9a8c72a6c USB: Rework usb_k... |
152 153 |
data->usb_in_pointer++; } |
affae2bff Initial revision |
154 |
|
9a8c72a6c USB: Rework usb_k... |
155 |
data->usb_kbd_buffer[data->usb_in_pointer] = c; |
affae2bff Initial revision |
156 |
} |
9a8c72a6c USB: Rework usb_k... |
157 158 159 160 |
/* * Set the LEDs. Since this is used in the irq routine, the control job is * issued with a timeout of 0. This means, that the job is queued without * waiting for job completion. |
affae2bff Initial revision |
161 |
*/ |
affae2bff Initial revision |
162 163 |
static void usb_kbd_setled(struct usb_device *dev) { |
9a8c72a6c USB: Rework usb_k... |
164 165 |
struct usb_interface *iface = &dev->config.if_desc[0]; struct usb_kbd_pdata *data = dev->privptr; |
9b2393812 usb: kbd: Fix una... |
166 |
ALLOC_ALIGN_BUFFER(uint32_t, leds, 1, USB_DMA_MINALIGN); |
9a8c72a6c USB: Rework usb_k... |
167 |
|
9b2393812 usb: kbd: Fix una... |
168 |
*leds = data->flags & USB_KBD_LEDMASK; |
affae2bff Initial revision |
169 170 |
usb_control_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE, |
9b2393812 usb: kbd: Fix una... |
171 |
0x200, iface->desc.bInterfaceNumber, leds, 1, 0); |
affae2bff Initial revision |
172 |
} |
9a8c72a6c USB: Rework usb_k... |
173 |
#define CAPITAL_MASK 0x20 |
affae2bff Initial revision |
174 |
/* Translate the scancode in ASCII */ |
9a8c72a6c USB: Rework usb_k... |
175 176 |
static int usb_kbd_translate(struct usb_kbd_pdata *data, unsigned char scancode, unsigned char modifier, int pressed) |
affae2bff Initial revision |
177 |
{ |
9a8c72a6c USB: Rework usb_k... |
178 |
uint8_t keycode = 0; |
affae2bff Initial revision |
179 |
|
9a8c72a6c USB: Rework usb_k... |
180 |
/* Key released */ |
00b7d6ecc USB: Squash check... |
181 |
if (pressed == 0) { |
9a8c72a6c USB: Rework usb_k... |
182 |
data->repeat_delay = 0; |
affae2bff Initial revision |
183 184 |
return 0; } |
9a8c72a6c USB: Rework usb_k... |
185 |
|
00b7d6ecc USB: Squash check... |
186 |
if (pressed == 2) { |
9a8c72a6c USB: Rework usb_k... |
187 188 |
data->repeat_delay++; if (data->repeat_delay < REPEAT_DELAY) |
affae2bff Initial revision |
189 |
return 0; |
9a8c72a6c USB: Rework usb_k... |
190 191 |
data->repeat_delay = REPEAT_DELAY; |
affae2bff Initial revision |
192 |
} |
9a8c72a6c USB: Rework usb_k... |
193 194 195 196 197 198 |
/* Alphanumeric values */ if ((scancode > 3) && (scancode <= 0x1d)) { keycode = scancode - 4 + 'a'; if (data->flags & USB_KBD_CAPSLOCK) |
00b7d6ecc USB: Squash check... |
199 |
keycode &= ~CAPITAL_MASK; |
9a8c72a6c USB: Rework usb_k... |
200 201 202 |
if (modifier & (LEFT_SHIFT | RIGHT_SHIFT)) { /* Handle CAPSLock + Shift pressed simultaneously */ |
00b7d6ecc USB: Squash check... |
203 |
if (keycode & CAPITAL_MASK) |
00b7d6ecc USB: Squash check... |
204 |
keycode &= ~CAPITAL_MASK; |
affae2bff Initial revision |
205 |
else |
00b7d6ecc USB: Squash check... |
206 |
keycode |= CAPITAL_MASK; |
affae2bff Initial revision |
207 208 |
} } |
9a8c72a6c USB: Rework usb_k... |
209 210 211 212 213 214 215 |
if ((scancode > 0x1d) && (scancode < 0x3a)) { /* Shift pressed */ if (modifier & (LEFT_SHIFT | RIGHT_SHIFT)) keycode = usb_kbd_numkey_shifted[scancode - 0x1e]; else keycode = usb_kbd_numkey[scancode - 0x1e]; |
affae2bff Initial revision |
216 |
} |
4785a694c Add Ctrl combo ke... |
217 |
|
4151a400c USB: add arrow ke... |
218 219 220 |
/* Arrow keys */ if ((scancode >= 0x4f) && (scancode <= 0x52)) keycode = usb_kbd_arrow[scancode - 0x4f]; |
d53da847c usb: add numeric ... |
221 222 223 |
/* Numeric keypad */ if ((scancode >= 0x54) && (scancode <= 0x67)) keycode = usb_kbd_num_keypad[scancode - 0x54]; |
9a8c72a6c USB: Rework usb_k... |
224 |
if (data->flags & USB_KBD_CTRL) |
4785a694c Add Ctrl combo ke... |
225 |
keycode = scancode - 0x3; |
00b7d6ecc USB: Squash check... |
226 227 |
if (pressed == 1) { if (scancode == NUM_LOCK) { |
9a8c72a6c USB: Rework usb_k... |
228 |
data->flags ^= USB_KBD_NUMLOCK; |
affae2bff Initial revision |
229 230 |
return 1; } |
9a8c72a6c USB: Rework usb_k... |
231 |
|
00b7d6ecc USB: Squash check... |
232 |
if (scancode == CAPS_LOCK) { |
9a8c72a6c USB: Rework usb_k... |
233 |
data->flags ^= USB_KBD_CAPSLOCK; |
affae2bff Initial revision |
234 235 |
return 1; } |
00b7d6ecc USB: Squash check... |
236 |
if (scancode == SCROLL_LOCK) { |
9a8c72a6c USB: Rework usb_k... |
237 |
data->flags ^= USB_KBD_SCROLLLOCK; |
affae2bff Initial revision |
238 239 240 |
return 1; } } |
9a8c72a6c USB: Rework usb_k... |
241 242 243 |
/* Report keycode if any */ if (keycode) { |
ceb4972a8 usb: common: Weed... |
244 |
debug("%c", keycode); |
9a8c72a6c USB: Rework usb_k... |
245 |
usb_kbd_put_queue(data, keycode); |
affae2bff Initial revision |
246 |
} |
9a8c72a6c USB: Rework usb_k... |
247 |
|
affae2bff Initial revision |
248 249 |
return 0; } |
9a8c72a6c USB: Rework usb_k... |
250 251 252 253 254 255 256 257 258 259 260 261 262 263 |
static uint32_t usb_kbd_service_key(struct usb_device *dev, int i, int up) { uint32_t res = 0; struct usb_kbd_pdata *data = dev->privptr; uint8_t *new; uint8_t *old; if (up) { new = data->old; old = data->new; } else { new = data->new; old = data->old; } |
08a98b89d usb: Fix USB keyb... |
264 265 266 |
if ((old[i] > 3) && (memscan(new + 2, old[i], USB_KBD_BOOT_REPORT_SIZE - 2) == new + USB_KBD_BOOT_REPORT_SIZE)) { |
9a8c72a6c USB: Rework usb_k... |
267 |
res |= usb_kbd_translate(data, old[i], data->new[0], up); |
08a98b89d usb: Fix USB keyb... |
268 |
} |
9a8c72a6c USB: Rework usb_k... |
269 270 271 |
return res; } |
affae2bff Initial revision |
272 |
/* Interrupt service routine */ |
48c8073ec USB: Add function... |
273 |
static int usb_kbd_irq_worker(struct usb_device *dev) |
affae2bff Initial revision |
274 |
{ |
9a8c72a6c USB: Rework usb_k... |
275 276 |
struct usb_kbd_pdata *data = dev->privptr; int i, res = 0; |
4785a694c Add Ctrl combo ke... |
277 |
|
9a8c72a6c USB: Rework usb_k... |
278 279 280 281 282 283 |
/* No combo key pressed */ if (data->new[0] == 0x00) data->flags &= ~USB_KBD_CTRL; /* Left or Right Ctrl pressed */ else if ((data->new[0] == LEFT_CNTR) || (data->new[0] == RIGHT_CNTR)) data->flags |= USB_KBD_CTRL; |
00b7d6ecc USB: Squash check... |
284 |
|
08a98b89d usb: Fix USB keyb... |
285 |
for (i = 2; i < USB_KBD_BOOT_REPORT_SIZE; i++) { |
9a8c72a6c USB: Rework usb_k... |
286 287 |
res |= usb_kbd_service_key(dev, i, 0); res |= usb_kbd_service_key(dev, i, 1); |
affae2bff Initial revision |
288 |
} |
00b7d6ecc USB: Squash check... |
289 |
|
9a8c72a6c USB: Rework usb_k... |
290 291 292 |
/* Key is still pressed */ if ((data->new[2] > 3) && (data->old[2] == data->new[2])) res |= usb_kbd_translate(data, data->new[2], data->new[0], 2); |
00b7d6ecc USB: Squash check... |
293 |
if (res == 1) |
affae2bff Initial revision |
294 |
usb_kbd_setled(dev); |
00b7d6ecc USB: Squash check... |
295 |
|
08a98b89d usb: Fix USB keyb... |
296 |
memcpy(data->old, data->new, USB_KBD_BOOT_REPORT_SIZE); |
00b7d6ecc USB: Squash check... |
297 |
|
9a8c72a6c USB: Rework usb_k... |
298 |
return 1; |
affae2bff Initial revision |
299 |
} |
9a8c72a6c USB: Rework usb_k... |
300 |
/* Keyboard interrupt handler */ |
48c8073ec USB: Add function... |
301 302 |
static int usb_kbd_irq(struct usb_device *dev) { |
08a98b89d usb: Fix USB keyb... |
303 304 |
if ((dev->irq_status != 0) || (dev->irq_act_len != USB_KBD_BOOT_REPORT_SIZE)) { |
ceb4972a8 usb: common: Weed... |
305 306 307 |
debug("USB KBD: Error %lX, len %d ", dev->irq_status, dev->irq_act_len); |
48c8073ec USB: Add function... |
308 309 310 311 312 |
return 1; } return usb_kbd_irq_worker(dev); } |
9a8c72a6c USB: Rework usb_k... |
313 314 315 316 |
/* Interrupt polling */ static inline void usb_kbd_poll_for_event(struct usb_device *dev) { #if defined(CONFIG_SYS_USB_EVENT_POLL) |
f9636e8d3 USB: move keyboar... |
317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 |
struct usb_interface *iface; struct usb_endpoint_descriptor *ep; struct usb_kbd_pdata *data; int pipe; int maxp; /* Get the pointer to USB Keyboard device pointer */ data = dev->privptr; iface = &dev->config.if_desc[0]; ep = &iface->ep_desc[0]; pipe = usb_rcvintpipe(dev, ep->bEndpointAddress); /* Submit a interrupt transfer request */ maxp = usb_maxpacket(dev, pipe); usb_submit_int_msg(dev, pipe, &data->new[0], |
08a98b89d usb: Fix USB keyb... |
332 333 |
min(maxp, USB_KBD_BOOT_REPORT_SIZE), ep->bInterval); |
f9636e8d3 USB: move keyboar... |
334 |
|
9a8c72a6c USB: Rework usb_k... |
335 336 337 338 339 340 |
usb_kbd_irq_worker(dev); #elif defined(CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP) struct usb_interface *iface; struct usb_kbd_pdata *data = dev->privptr; iface = &dev->config.if_desc[0]; usb_get_report(dev, iface->desc.bInterfaceNumber, |
08a98b89d usb: Fix USB keyb... |
341 342 |
1, 0, data->new, USB_KBD_BOOT_REPORT_SIZE); if (memcmp(data->old, data->new, USB_KBD_BOOT_REPORT_SIZE)) |
9a8c72a6c USB: Rework usb_k... |
343 344 345 346 347 |
usb_kbd_irq_worker(dev); #endif } /* test if a character is in the queue */ |
709ea543b stdio: Pass devic... |
348 |
static int usb_kbd_testc(struct stdio_dev *sdev) |
9a8c72a6c USB: Rework usb_k... |
349 350 351 352 |
{ struct stdio_dev *dev; struct usb_device *usb_kbd_dev; struct usb_kbd_pdata *data; |
c95e2b9ea console: usb: kbd... |
353 354 355 356 357 358 359 360 361 362 |
#ifdef CONFIG_CMD_NET /* * If net_busy_flag is 1, NET transfer is running, * then we check key-pressed every second (first check may be * less than 1 second) to improve TFTP booting performance. */ if (net_busy_flag && (get_timer(kbd_testc_tms) < CONFIG_SYS_HZ)) return 0; kbd_testc_tms = get_timer(0); #endif |
9a8c72a6c USB: Rework usb_k... |
363 364 365 366 367 368 369 370 371 372 |
dev = stdio_get_by_name(DEVNAME); usb_kbd_dev = (struct usb_device *)dev->priv; data = usb_kbd_dev->privptr; usb_kbd_poll_for_event(usb_kbd_dev); return !(data->usb_in_pointer == data->usb_out_pointer); } /* gets the character from the queue */ |
709ea543b stdio: Pass devic... |
373 |
static int usb_kbd_getc(struct stdio_dev *sdev) |
9a8c72a6c USB: Rework usb_k... |
374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 |
{ struct stdio_dev *dev; struct usb_device *usb_kbd_dev; struct usb_kbd_pdata *data; dev = stdio_get_by_name(DEVNAME); usb_kbd_dev = (struct usb_device *)dev->priv; data = usb_kbd_dev->privptr; while (data->usb_in_pointer == data->usb_out_pointer) usb_kbd_poll_for_event(usb_kbd_dev); if (data->usb_out_pointer == USB_KBD_BUFFER_LEN - 1) data->usb_out_pointer = 0; else data->usb_out_pointer++; return data->usb_kbd_buffer[data->usb_out_pointer]; } /* probes the USB device dev for keyboard type. */ |
affae2bff Initial revision |
395 396 |
static int usb_kbd_probe(struct usb_device *dev, unsigned int ifnum) { |
8f8bd565f USB Consolidate d... |
397 |
struct usb_interface *iface; |
affae2bff Initial revision |
398 |
struct usb_endpoint_descriptor *ep; |
9a8c72a6c USB: Rework usb_k... |
399 |
struct usb_kbd_pdata *data; |
00b7d6ecc USB: Squash check... |
400 |
int pipe, maxp; |
affae2bff Initial revision |
401 |
|
00b7d6ecc USB: Squash check... |
402 403 |
if (dev->descriptor.bNumConfigurations != 1) return 0; |
9a8c72a6c USB: Rework usb_k... |
404 |
|
affae2bff Initial revision |
405 |
iface = &dev->config.if_desc[ifnum]; |
8f8bd565f USB Consolidate d... |
406 407 |
if (iface->desc.bInterfaceClass != 3) return 0; |
9a8c72a6c USB: Rework usb_k... |
408 |
|
8f8bd565f USB Consolidate d... |
409 410 |
if (iface->desc.bInterfaceSubClass != 1) return 0; |
9a8c72a6c USB: Rework usb_k... |
411 |
|
8f8bd565f USB Consolidate d... |
412 413 |
if (iface->desc.bInterfaceProtocol != 1) return 0; |
9a8c72a6c USB: Rework usb_k... |
414 |
|
8f8bd565f USB Consolidate d... |
415 416 |
if (iface->desc.bNumEndpoints != 1) return 0; |
affae2bff Initial revision |
417 418 |
ep = &iface->ep_desc[0]; |
9a8c72a6c USB: Rework usb_k... |
419 |
/* Check if endpoint 1 is interrupt endpoint */ |
00b7d6ecc USB: Squash check... |
420 421 |
if (!(ep->bEndpointAddress & 0x80)) return 0; |
9a8c72a6c USB: Rework usb_k... |
422 |
|
00b7d6ecc USB: Squash check... |
423 424 |
if ((ep->bmAttributes & 3) != 3) return 0; |
9a8c72a6c USB: Rework usb_k... |
425 |
|
ceb4972a8 usb: common: Weed... |
426 427 |
debug("USB KBD: found set protocol... "); |
9a8c72a6c USB: Rework usb_k... |
428 429 430 431 432 433 434 435 436 437 |
data = malloc(sizeof(struct usb_kbd_pdata)); if (!data) { printf("USB KBD: Error allocating private data "); return 0; } /* Clear private data */ memset(data, 0, sizeof(struct usb_kbd_pdata)); |
d7475386b USB: make usb_kbd... |
438 |
/* allocate input buffer aligned and sized to USB DMA alignment */ |
08a98b89d usb: Fix USB keyb... |
439 440 |
data->new = memalign(USB_DMA_MINALIGN, roundup(USB_KBD_BOOT_REPORT_SIZE, USB_DMA_MINALIGN)); |
d7475386b USB: make usb_kbd... |
441 |
|
9a8c72a6c USB: Rework usb_k... |
442 443 444 445 446 |
/* Insert private data into USB device structure */ dev->privptr = data; /* Set IRQ handler */ dev->irq_handle = usb_kbd_irq; |
affae2bff Initial revision |
447 448 |
pipe = usb_rcvintpipe(dev, ep->bEndpointAddress); maxp = usb_maxpacket(dev, pipe); |
9a8c72a6c USB: Rework usb_k... |
449 450 451 |
/* We found a USB Keyboard, install it. */ usb_set_protocol(dev, iface->desc.bInterfaceNumber, 0); |
ceb4972a8 usb: common: Weed... |
452 453 |
debug("USB KBD: found set idle... "); |
9a8c72a6c USB: Rework usb_k... |
454 |
usb_set_idle(dev, iface->desc.bInterfaceNumber, REPEAT_RATE, 0); |
ceb4972a8 usb: common: Weed... |
455 456 |
debug("USB KBD: enable interrupt pipe... "); |
08a98b89d usb: Fix USB keyb... |
457 458 |
if (usb_submit_int_msg(dev, pipe, data->new, min(maxp, USB_KBD_BOOT_REPORT_SIZE), |
5da2dc978 usb: workaround n... |
459 460 461 462 463 464 465 |
ep->bInterval) < 0) { printf("Failed to get keyboard state from device %04x:%04x ", dev->descriptor.idVendor, dev->descriptor.idProduct); /* Abort, we don't want to use that non-functional keyboard. */ return 0; } |
9a8c72a6c USB: Rework usb_k... |
466 467 |
/* Success. */ |
affae2bff Initial revision |
468 469 |
return 1; } |
9a8c72a6c USB: Rework usb_k... |
470 471 472 |
/* Search for keyboard and register it if found. */ int drv_usb_kbd_init(void) { |
3f78a2803 usb: kbd: Remove ... |
473 |
struct stdio_dev usb_kbd_dev; |
9a8c72a6c USB: Rework usb_k... |
474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 |
struct usb_device *dev; char *stdinname = getenv("stdin"); int error, i; /* Scan all USB Devices */ for (i = 0; i < USB_MAX_DEVICE; i++) { /* Get USB device. */ dev = usb_get_dev_index(i); if (!dev) return -1; if (dev->devnum == -1) continue; /* Try probing the keyboard */ if (usb_kbd_probe(dev, 0) != 1) continue; |
9a8c72a6c USB: Rework usb_k... |
491 |
/* Register the keyboard */ |
ceb4972a8 usb: common: Weed... |
492 493 |
debug("USB KBD: register. "); |
9a8c72a6c USB: Rework usb_k... |
494 495 496 |
memset(&usb_kbd_dev, 0, sizeof(struct stdio_dev)); strcpy(usb_kbd_dev.name, DEVNAME); usb_kbd_dev.flags = DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM; |
9a8c72a6c USB: Rework usb_k... |
497 498 499 500 501 502 |
usb_kbd_dev.getc = usb_kbd_getc; usb_kbd_dev.tstc = usb_kbd_testc; usb_kbd_dev.priv = (void *)dev; error = stdio_register(&usb_kbd_dev); if (error) return error; |
fb3ef649e USB: reevaluate i... |
503 504 505 506 507 |
#ifdef CONFIG_CONSOLE_MUX error = iomux_doenv(stdin, stdinname); if (error) return error; #else |
9a8c72a6c USB: Rework usb_k... |
508 509 510 511 512 513 514 515 516 517 518 |
/* Check if this is the standard input device. */ if (strcmp(stdinname, DEVNAME)) return 1; /* Reassign the console */ if (overwrite_console()) return 1; error = console_assign(stdin, DEVNAME); if (error) return error; |
fb3ef649e USB: reevaluate i... |
519 |
#endif |
9a8c72a6c USB: Rework usb_k... |
520 521 522 523 524 525 526 527 528 |
return 1; } /* No USB Keyboard found */ return -1; } /* Deregister the keyboard. */ |
8a8a2257e usb: kbd: Allow "... |
529 |
int usb_kbd_deregister(int force) |
9a8c72a6c USB: Rework usb_k... |
530 531 |
{ #ifdef CONFIG_SYS_STDIO_DEREGISTER |
8a8a2257e usb: kbd: Allow "... |
532 |
int ret = stdio_deregister(DEVNAME, force); |
0ea09dfe8 usb: kbd: Do not ... |
533 534 535 536 |
if (ret && ret != -ENODEV) return ret; return 0; |
9a8c72a6c USB: Rework usb_k... |
537 538 539 540 |
#else return 1; #endif } |