Blame view
common/usb_kbd.c
13.2 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> |
9a8c72a6c USB: Rework usb_k... |
11 |
#include <malloc.h> |
52cb4d4fb stdio/device: rew... |
12 |
#include <stdio_dev.h> |
c918261c6 USB: replace old ... |
13 |
#include <asm/byteorder.h> |
affae2bff Initial revision |
14 |
|
affae2bff Initial revision |
15 |
#include <usb.h> |
affae2bff Initial revision |
16 |
/* |
00b7d6ecc USB: Squash check... |
17 |
* If overwrite_console returns 1, the stdin, stderr and stdout |
affae2bff Initial revision |
18 19 20 |
* are switched to the serial port, else the settings in the * environment are used */ |
6d0f6bcf3 rename CFG_ macro... |
21 |
#ifdef CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE |
00b7d6ecc USB: Squash check... |
22 |
extern int overwrite_console(void); |
affae2bff Initial revision |
23 |
#else |
00b7d6ecc USB: Squash check... |
24 |
int overwrite_console(void) |
affae2bff Initial revision |
25 |
{ |
00b7d6ecc USB: Squash check... |
26 |
return 0; |
affae2bff Initial revision |
27 28 |
} #endif |
9a8c72a6c USB: Rework usb_k... |
29 30 31 |
/* Keyboard sampling rate */ #define REPEAT_RATE (40 / 4) /* 40msec -> 25cps */ #define REPEAT_DELAY 10 /* 10 x REPEAT_RATE = 400msec */ |
affae2bff Initial revision |
32 33 |
#define NUM_LOCK 0x53 |
00b7d6ecc USB: Squash check... |
34 35 |
#define CAPS_LOCK 0x39 #define SCROLL_LOCK 0x47 |
affae2bff Initial revision |
36 |
|
affae2bff Initial revision |
37 |
/* Modifier bits */ |
9a8c72a6c USB: Rework usb_k... |
38 39 40 41 42 43 44 45 46 47 48 49 50 |
#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... |
51 |
#define DEVNAME "usbkbd" |
affae2bff Initial revision |
52 |
|
9a8c72a6c USB: Rework usb_k... |
53 54 |
/* Keyboard maps */ static const unsigned char usb_kbd_numkey[] = { |
00b7d6ecc USB: Squash check... |
55 56 57 |
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '\r', 0x1b, '\b', '\t', ' ', '-', '=', '[', ']', '\\', '#', ';', '\'', '`', ',', '.', '/' |
affae2bff Initial revision |
58 |
}; |
9a8c72a6c USB: Rework usb_k... |
59 |
static const unsigned char usb_kbd_numkey_shifted[] = { |
00b7d6ecc USB: Squash check... |
60 61 62 |
'!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '\r', 0x1b, '\b', '\t', ' ', '_', '+', '{', '}', '|', '~', ':', '"', '~', '<', '>', '?' |
affae2bff Initial revision |
63 |
}; |
d53da847c usb: add numeric ... |
64 65 66 67 68 |
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... |
69 |
/* |
4151a400c USB: add arrow ke... |
70 71 72 73 74 75 76 77 78 |
* 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... |
79 80 81 82 83 84 85 |
* 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... |
86 |
|
9a8c72a6c USB: Rework usb_k... |
87 88 |
#define USB_KBD_LEDMASK \ (USB_KBD_NUMLOCK | USB_KBD_CAPSLOCK | USB_KBD_SCROLLLOCK) |
48c8073ec USB: Add function... |
89 |
|
9a8c72a6c USB: Rework usb_k... |
90 91 |
struct usb_kbd_pdata { uint32_t repeat_delay; |
affae2bff Initial revision |
92 |
|
9a8c72a6c USB: Rework usb_k... |
93 94 95 |
uint32_t usb_in_pointer; uint32_t usb_out_pointer; uint8_t usb_kbd_buffer[USB_KBD_BUFFER_LEN]; |
48c8073ec USB: Add function... |
96 |
|
d7475386b USB: make usb_kbd... |
97 |
uint8_t *new; |
9a8c72a6c USB: Rework usb_k... |
98 |
uint8_t old[8]; |
48c8073ec USB: Add function... |
99 |
|
9a8c72a6c USB: Rework usb_k... |
100 101 |
uint8_t flags; }; |
48c8073ec USB: Add function... |
102 |
|
07551f234 console: usb: kbd... |
103 104 105 106 |
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... |
107 108 |
/* Generic keyboard event polling. */ void usb_kbd_generic_poll(void) |
affae2bff Initial revision |
109 |
{ |
48c8073ec USB: Add function... |
110 111 |
struct stdio_dev *dev; struct usb_device *usb_kbd_dev; |
9a8c72a6c USB: Rework usb_k... |
112 113 114 115 116 |
struct usb_kbd_pdata *data; struct usb_interface *iface; struct usb_endpoint_descriptor *ep; int pipe; int maxp; |
48c8073ec USB: Add function... |
117 |
|
9a8c72a6c USB: Rework usb_k... |
118 119 |
/* Get the pointer to USB Keyboard device pointer */ dev = stdio_get_by_name(DEVNAME); |
48c8073ec USB: Add function... |
120 |
usb_kbd_dev = (struct usb_device *)dev->priv; |
9a8c72a6c USB: Rework usb_k... |
121 122 123 124 |
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... |
125 |
|
9a8c72a6c USB: Rework usb_k... |
126 127 128 129 |
/* Submit a interrupt transfer request */ maxp = usb_maxpacket(usb_kbd_dev, pipe); usb_submit_int_msg(usb_kbd_dev, pipe, data->new, maxp > 8 ? 8 : maxp, ep->bInterval); |
affae2bff Initial revision |
130 |
} |
9a8c72a6c USB: Rework usb_k... |
131 132 |
/* 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 |
133 |
{ |
9a8c72a6c USB: Rework usb_k... |
134 135 136 137 |
if (data->usb_in_pointer == USB_KBD_BUFFER_LEN - 1) { /* Check for buffer full. */ if (data->usb_out_pointer == 0) return; |
affae2bff Initial revision |
138 |
|
9a8c72a6c USB: Rework usb_k... |
139 140 141 142 143 |
data->usb_in_pointer = 0; } else { /* Check for buffer full. */ if (data->usb_in_pointer == data->usb_out_pointer - 1) return; |
affae2bff Initial revision |
144 |
|
9a8c72a6c USB: Rework usb_k... |
145 146 |
data->usb_in_pointer++; } |
affae2bff Initial revision |
147 |
|
9a8c72a6c USB: Rework usb_k... |
148 |
data->usb_kbd_buffer[data->usb_in_pointer] = c; |
affae2bff Initial revision |
149 |
} |
9a8c72a6c USB: Rework usb_k... |
150 151 152 153 |
/* * 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 |
154 |
*/ |
affae2bff Initial revision |
155 156 |
static void usb_kbd_setled(struct usb_device *dev) { |
9a8c72a6c USB: Rework usb_k... |
157 158 159 |
struct usb_interface *iface = &dev->config.if_desc[0]; struct usb_kbd_pdata *data = dev->privptr; uint32_t leds = data->flags & USB_KBD_LEDMASK; |
affae2bff Initial revision |
160 161 |
usb_control_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE, |
8f8bd565f USB Consolidate d... |
162 |
0x200, iface->desc.bInterfaceNumber, (void *)&leds, 1, 0); |
affae2bff Initial revision |
163 |
} |
9a8c72a6c USB: Rework usb_k... |
164 |
#define CAPITAL_MASK 0x20 |
affae2bff Initial revision |
165 |
/* Translate the scancode in ASCII */ |
9a8c72a6c USB: Rework usb_k... |
166 167 |
static int usb_kbd_translate(struct usb_kbd_pdata *data, unsigned char scancode, unsigned char modifier, int pressed) |
affae2bff Initial revision |
168 |
{ |
9a8c72a6c USB: Rework usb_k... |
169 |
uint8_t keycode = 0; |
affae2bff Initial revision |
170 |
|
9a8c72a6c USB: Rework usb_k... |
171 |
/* Key released */ |
00b7d6ecc USB: Squash check... |
172 |
if (pressed == 0) { |
9a8c72a6c USB: Rework usb_k... |
173 |
data->repeat_delay = 0; |
affae2bff Initial revision |
174 175 |
return 0; } |
9a8c72a6c USB: Rework usb_k... |
176 |
|
00b7d6ecc USB: Squash check... |
177 |
if (pressed == 2) { |
9a8c72a6c USB: Rework usb_k... |
178 179 |
data->repeat_delay++; if (data->repeat_delay < REPEAT_DELAY) |
affae2bff Initial revision |
180 |
return 0; |
9a8c72a6c USB: Rework usb_k... |
181 182 |
data->repeat_delay = REPEAT_DELAY; |
affae2bff Initial revision |
183 |
} |
9a8c72a6c USB: Rework usb_k... |
184 185 186 187 188 189 |
/* Alphanumeric values */ if ((scancode > 3) && (scancode <= 0x1d)) { keycode = scancode - 4 + 'a'; if (data->flags & USB_KBD_CAPSLOCK) |
00b7d6ecc USB: Squash check... |
190 |
keycode &= ~CAPITAL_MASK; |
9a8c72a6c USB: Rework usb_k... |
191 192 193 |
if (modifier & (LEFT_SHIFT | RIGHT_SHIFT)) { /* Handle CAPSLock + Shift pressed simultaneously */ |
00b7d6ecc USB: Squash check... |
194 |
if (keycode & CAPITAL_MASK) |
00b7d6ecc USB: Squash check... |
195 |
keycode &= ~CAPITAL_MASK; |
affae2bff Initial revision |
196 |
else |
00b7d6ecc USB: Squash check... |
197 |
keycode |= CAPITAL_MASK; |
affae2bff Initial revision |
198 199 |
} } |
9a8c72a6c USB: Rework usb_k... |
200 201 202 203 204 205 206 |
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 |
207 |
} |
4785a694c Add Ctrl combo ke... |
208 |
|
4151a400c USB: add arrow ke... |
209 210 211 |
/* Arrow keys */ if ((scancode >= 0x4f) && (scancode <= 0x52)) keycode = usb_kbd_arrow[scancode - 0x4f]; |
d53da847c usb: add numeric ... |
212 213 214 |
/* Numeric keypad */ if ((scancode >= 0x54) && (scancode <= 0x67)) keycode = usb_kbd_num_keypad[scancode - 0x54]; |
9a8c72a6c USB: Rework usb_k... |
215 |
if (data->flags & USB_KBD_CTRL) |
4785a694c Add Ctrl combo ke... |
216 |
keycode = scancode - 0x3; |
00b7d6ecc USB: Squash check... |
217 218 |
if (pressed == 1) { if (scancode == NUM_LOCK) { |
9a8c72a6c USB: Rework usb_k... |
219 |
data->flags ^= USB_KBD_NUMLOCK; |
affae2bff Initial revision |
220 221 |
return 1; } |
9a8c72a6c USB: Rework usb_k... |
222 |
|
00b7d6ecc USB: Squash check... |
223 |
if (scancode == CAPS_LOCK) { |
9a8c72a6c USB: Rework usb_k... |
224 |
data->flags ^= USB_KBD_CAPSLOCK; |
affae2bff Initial revision |
225 226 |
return 1; } |
00b7d6ecc USB: Squash check... |
227 |
if (scancode == SCROLL_LOCK) { |
9a8c72a6c USB: Rework usb_k... |
228 |
data->flags ^= USB_KBD_SCROLLLOCK; |
affae2bff Initial revision |
229 230 231 |
return 1; } } |
9a8c72a6c USB: Rework usb_k... |
232 233 234 |
/* Report keycode if any */ if (keycode) { |
ceb4972a8 usb: common: Weed... |
235 |
debug("%c", keycode); |
9a8c72a6c USB: Rework usb_k... |
236 |
usb_kbd_put_queue(data, keycode); |
affae2bff Initial revision |
237 |
} |
9a8c72a6c USB: Rework usb_k... |
238 |
|
affae2bff Initial revision |
239 240 |
return 0; } |
9a8c72a6c USB: Rework usb_k... |
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 |
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; } if ((old[i] > 3) && (memscan(new + 2, old[i], 6) == new + 8)) res |= usb_kbd_translate(data, old[i], data->new[0], up); return res; } |
affae2bff Initial revision |
261 |
/* Interrupt service routine */ |
48c8073ec USB: Add function... |
262 |
static int usb_kbd_irq_worker(struct usb_device *dev) |
affae2bff Initial revision |
263 |
{ |
9a8c72a6c USB: Rework usb_k... |
264 265 |
struct usb_kbd_pdata *data = dev->privptr; int i, res = 0; |
4785a694c Add Ctrl combo ke... |
266 |
|
9a8c72a6c USB: Rework usb_k... |
267 268 269 270 271 272 |
/* 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... |
273 |
|
9a8c72a6c USB: Rework usb_k... |
274 275 276 |
for (i = 2; i < 8; i++) { res |= usb_kbd_service_key(dev, i, 0); res |= usb_kbd_service_key(dev, i, 1); |
affae2bff Initial revision |
277 |
} |
00b7d6ecc USB: Squash check... |
278 |
|
9a8c72a6c USB: Rework usb_k... |
279 280 281 |
/* 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... |
282 |
if (res == 1) |
affae2bff Initial revision |
283 |
usb_kbd_setled(dev); |
00b7d6ecc USB: Squash check... |
284 |
|
9a8c72a6c USB: Rework usb_k... |
285 |
memcpy(data->old, data->new, 8); |
00b7d6ecc USB: Squash check... |
286 |
|
9a8c72a6c USB: Rework usb_k... |
287 |
return 1; |
affae2bff Initial revision |
288 |
} |
9a8c72a6c USB: Rework usb_k... |
289 |
/* Keyboard interrupt handler */ |
48c8073ec USB: Add function... |
290 291 292 |
static int usb_kbd_irq(struct usb_device *dev) { if ((dev->irq_status != 0) || (dev->irq_act_len != 8)) { |
ceb4972a8 usb: common: Weed... |
293 294 295 |
debug("USB KBD: Error %lX, len %d ", dev->irq_status, dev->irq_act_len); |
48c8073ec USB: Add function... |
296 297 298 299 300 |
return 1; } return usb_kbd_irq_worker(dev); } |
9a8c72a6c USB: Rework usb_k... |
301 302 303 304 |
/* 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... |
305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 |
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], maxp > 8 ? 8 : maxp, ep->bInterval); |
9a8c72a6c USB: Rework usb_k... |
321 322 323 324 325 326 |
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, |
3d17308e4 USB: fix USB keyb... |
327 |
1, 0, data->new, sizeof(data->new)); |
9a8c72a6c USB: Rework usb_k... |
328 329 330 331 332 333 334 335 336 337 338 |
if (memcmp(data->old, data->new, sizeof(data->new))) usb_kbd_irq_worker(dev); #endif } /* test if a character is in the queue */ static int usb_kbd_testc(void) { struct stdio_dev *dev; struct usb_device *usb_kbd_dev; struct usb_kbd_pdata *data; |
c95e2b9ea console: usb: kbd... |
339 340 341 342 343 344 345 346 347 348 |
#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... |
349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 |
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 */ static int usb_kbd_getc(void) { 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 |
381 382 |
static int usb_kbd_probe(struct usb_device *dev, unsigned int ifnum) { |
8f8bd565f USB Consolidate d... |
383 |
struct usb_interface *iface; |
affae2bff Initial revision |
384 |
struct usb_endpoint_descriptor *ep; |
9a8c72a6c USB: Rework usb_k... |
385 |
struct usb_kbd_pdata *data; |
00b7d6ecc USB: Squash check... |
386 |
int pipe, maxp; |
affae2bff Initial revision |
387 |
|
00b7d6ecc USB: Squash check... |
388 389 |
if (dev->descriptor.bNumConfigurations != 1) return 0; |
9a8c72a6c USB: Rework usb_k... |
390 |
|
affae2bff Initial revision |
391 |
iface = &dev->config.if_desc[ifnum]; |
8f8bd565f USB Consolidate d... |
392 393 |
if (iface->desc.bInterfaceClass != 3) return 0; |
9a8c72a6c USB: Rework usb_k... |
394 |
|
8f8bd565f USB Consolidate d... |
395 396 |
if (iface->desc.bInterfaceSubClass != 1) return 0; |
9a8c72a6c USB: Rework usb_k... |
397 |
|
8f8bd565f USB Consolidate d... |
398 399 |
if (iface->desc.bInterfaceProtocol != 1) return 0; |
9a8c72a6c USB: Rework usb_k... |
400 |
|
8f8bd565f USB Consolidate d... |
401 402 |
if (iface->desc.bNumEndpoints != 1) return 0; |
affae2bff Initial revision |
403 404 |
ep = &iface->ep_desc[0]; |
9a8c72a6c USB: Rework usb_k... |
405 |
/* Check if endpoint 1 is interrupt endpoint */ |
00b7d6ecc USB: Squash check... |
406 407 |
if (!(ep->bEndpointAddress & 0x80)) return 0; |
9a8c72a6c USB: Rework usb_k... |
408 |
|
00b7d6ecc USB: Squash check... |
409 410 |
if ((ep->bmAttributes & 3) != 3) return 0; |
9a8c72a6c USB: Rework usb_k... |
411 |
|
ceb4972a8 usb: common: Weed... |
412 413 |
debug("USB KBD: found set protocol... "); |
9a8c72a6c USB: Rework usb_k... |
414 415 416 417 418 419 420 421 422 423 |
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... |
424 425 |
/* allocate input buffer aligned and sized to USB DMA alignment */ data->new = memalign(USB_DMA_MINALIGN, roundup(8, USB_DMA_MINALIGN)); |
9a8c72a6c USB: Rework usb_k... |
426 427 428 429 430 |
/* Insert private data into USB device structure */ dev->privptr = data; /* Set IRQ handler */ dev->irq_handle = usb_kbd_irq; |
affae2bff Initial revision |
431 432 |
pipe = usb_rcvintpipe(dev, ep->bEndpointAddress); maxp = usb_maxpacket(dev, pipe); |
9a8c72a6c USB: Rework usb_k... |
433 434 435 |
/* We found a USB Keyboard, install it. */ usb_set_protocol(dev, iface->desc.bInterfaceNumber, 0); |
ceb4972a8 usb: common: Weed... |
436 437 |
debug("USB KBD: found set idle... "); |
9a8c72a6c USB: Rework usb_k... |
438 |
usb_set_idle(dev, iface->desc.bInterfaceNumber, REPEAT_RATE, 0); |
ceb4972a8 usb: common: Weed... |
439 440 |
debug("USB KBD: enable interrupt pipe... "); |
5da2dc978 usb: workaround n... |
441 442 443 444 445 446 447 448 |
if (usb_submit_int_msg(dev, pipe, data->new, maxp > 8 ? 8 : maxp, 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... |
449 450 |
/* Success. */ |
affae2bff Initial revision |
451 452 |
return 1; } |
9a8c72a6c USB: Rework usb_k... |
453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 |
/* Search for keyboard and register it if found. */ int drv_usb_kbd_init(void) { struct stdio_dev usb_kbd_dev, *old_dev; 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; /* We found a keyboard, check if it is already registered. */ |
ceb4972a8 usb: common: Weed... |
476 477 |
debug("USB KBD: found set up device. "); |
9a8c72a6c USB: Rework usb_k... |
478 479 480 |
old_dev = stdio_get_by_name(DEVNAME); if (old_dev) { /* Already registered, just return ok. */ |
ceb4972a8 usb: common: Weed... |
481 482 |
debug("USB KBD: is already registered. "); |
09defbc75 usb: properly re-... |
483 |
usb_kbd_deregister(); |
9a8c72a6c USB: Rework usb_k... |
484 485 486 487 |
return 1; } /* Register the keyboard */ |
ceb4972a8 usb: common: Weed... |
488 489 |
debug("USB KBD: register. "); |
9a8c72a6c USB: Rework usb_k... |
490 491 492 493 494 495 496 497 498 499 500 |
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; usb_kbd_dev.putc = NULL; usb_kbd_dev.puts = NULL; 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... |
501 502 503 504 505 |
#ifdef CONFIG_CONSOLE_MUX error = iomux_doenv(stdin, stdinname); if (error) return error; #else |
9a8c72a6c USB: Rework usb_k... |
506 507 508 509 510 511 512 513 514 515 516 |
/* 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... |
517 |
#endif |
9a8c72a6c USB: Rework usb_k... |
518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 |
return 1; } /* No USB Keyboard found */ return -1; } /* Deregister the keyboard. */ int usb_kbd_deregister(void) { #ifdef CONFIG_SYS_STDIO_DEREGISTER return stdio_deregister(DEVNAME); #else return 1; #endif } |