Blame view
common/usb_kbd.c
17 KB
83d290c56 SPDX: Convert all... |
1 |
// SPDX-License-Identifier: GPL-2.0+ |
affae2bff Initial revision |
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. |
affae2bff Initial revision |
8 9 |
*/ #include <common.h> |
24b852a7a Move console defi... |
10 |
#include <console.h> |
697033cbf dm: usb: Support ... |
11 |
#include <dm.h> |
7b51b576d env: Move env_get... |
12 |
#include <env.h> |
0ea09dfe8 usb: kbd: Do not ... |
13 |
#include <errno.h> |
9a8c72a6c USB: Rework usb_k... |
14 |
#include <malloc.h> |
cf92e05c0 Move ALLOC_CACHE_... |
15 |
#include <memalign.h> |
52cb4d4fb stdio/device: rew... |
16 |
#include <stdio_dev.h> |
f8f3e0e53 usb_kbd: Add supp... |
17 |
#include <watchdog.h> |
c918261c6 USB: replace old ... |
18 |
#include <asm/byteorder.h> |
affae2bff Initial revision |
19 |
|
affae2bff Initial revision |
20 |
#include <usb.h> |
affae2bff Initial revision |
21 |
/* |
00b7d6ecc USB: Squash check... |
22 |
* If overwrite_console returns 1, the stdin, stderr and stdout |
affae2bff Initial revision |
23 24 25 |
* are switched to the serial port, else the settings in the * environment are used */ |
6d0f6bcf3 rename CFG_ macro... |
26 |
#ifdef CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE |
00b7d6ecc USB: Squash check... |
27 |
extern int overwrite_console(void); |
affae2bff Initial revision |
28 |
#else |
00b7d6ecc USB: Squash check... |
29 |
int overwrite_console(void) |
affae2bff Initial revision |
30 |
{ |
00b7d6ecc USB: Squash check... |
31 |
return 0; |
affae2bff Initial revision |
32 33 |
} #endif |
9a8c72a6c USB: Rework usb_k... |
34 |
/* Keyboard sampling rate */ |
8454c84af usb: kbd: Fix key... |
35 |
#define REPEAT_RATE 40 /* 40msec -> 25cps */ |
9a8c72a6c USB: Rework usb_k... |
36 |
#define REPEAT_DELAY 10 /* 10 x REPEAT_RATE = 400msec */ |
affae2bff Initial revision |
37 38 |
#define NUM_LOCK 0x53 |
00b7d6ecc USB: Squash check... |
39 40 |
#define CAPS_LOCK 0x39 #define SCROLL_LOCK 0x47 |
affae2bff Initial revision |
41 |
|
affae2bff Initial revision |
42 |
/* Modifier bits */ |
9a8c72a6c USB: Rework usb_k... |
43 44 45 46 47 48 49 50 51 52 53 54 55 |
#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... |
56 |
#define DEVNAME "usbkbd" |
affae2bff Initial revision |
57 |
|
9a8c72a6c USB: Rework usb_k... |
58 59 |
/* Keyboard maps */ static const unsigned char usb_kbd_numkey[] = { |
00b7d6ecc USB: Squash check... |
60 61 62 |
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '\r', 0x1b, '\b', '\t', ' ', '-', '=', '[', ']', '\\', '#', ';', '\'', '`', ',', '.', '/' |
affae2bff Initial revision |
63 |
}; |
9a8c72a6c USB: Rework usb_k... |
64 |
static const unsigned char usb_kbd_numkey_shifted[] = { |
00b7d6ecc USB: Squash check... |
65 66 67 |
'!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '\r', 0x1b, '\b', '\t', ' ', '_', '+', '{', '}', '|', '~', ':', '"', '~', '<', '>', '?' |
affae2bff Initial revision |
68 |
}; |
d53da847c usb: add numeric ... |
69 70 71 72 73 |
static const unsigned char usb_kbd_num_keypad[] = { '/', '*', '-', '+', '\r', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '.', 0, 0, 0, '=' }; |
3352c2114 usb: kbd: simplif... |
74 |
static const u8 usb_special_keys[] = { |
87e91bcca usb: kbd: impleme... |
75 76 77 |
#ifdef CONFIG_USB_KEYBOARD_FN_KEYS '2', 'H', '5', '3', 'F', '6', 'C', 'D', 'B', 'A' #else |
3352c2114 usb: kbd: simplif... |
78 |
'C', 'D', 'B', 'A' |
87e91bcca usb: kbd: impleme... |
79 |
#endif |
4151a400c USB: add arrow ke... |
80 81 82 |
}; /* |
9a8c72a6c USB: Rework usb_k... |
83 84 85 86 87 88 89 |
* 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... |
90 |
|
9a8c72a6c USB: Rework usb_k... |
91 92 |
#define USB_KBD_LEDMASK \ (USB_KBD_NUMLOCK | USB_KBD_CAPSLOCK | USB_KBD_SCROLLLOCK) |
48c8073ec USB: Add function... |
93 |
|
9a8c72a6c USB: Rework usb_k... |
94 |
struct usb_kbd_pdata { |
8f8d7d245 usb: kbd: Cache p... |
95 96 97 |
unsigned long intpipe; int intpktsize; int intinterval; |
8454c84af usb: kbd: Fix key... |
98 |
unsigned long last_report; |
8e5531198 usb: kbd: Add (op... |
99 |
struct int_queue *intq; |
8f8d7d245 usb: kbd: Cache p... |
100 |
|
9a8c72a6c USB: Rework usb_k... |
101 |
uint32_t repeat_delay; |
affae2bff Initial revision |
102 |
|
9a8c72a6c USB: Rework usb_k... |
103 104 105 |
uint32_t usb_in_pointer; uint32_t usb_out_pointer; uint8_t usb_kbd_buffer[USB_KBD_BUFFER_LEN]; |
48c8073ec USB: Add function... |
106 |
|
d7475386b USB: make usb_kbd... |
107 |
uint8_t *new; |
08a98b89d usb: Fix USB keyb... |
108 |
uint8_t old[USB_KBD_BOOT_REPORT_SIZE]; |
48c8073ec USB: Add function... |
109 |
|
9a8c72a6c USB: Rework usb_k... |
110 111 |
uint8_t flags; }; |
48c8073ec USB: Add function... |
112 |
|
07551f234 console: usb: kbd... |
113 114 115 116 |
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... |
117 |
/* Puts character in the queue and sets up the in and out pointer. */ |
28dfa7d80 usb: kbd: signatu... |
118 |
static void usb_kbd_put_queue(struct usb_kbd_pdata *data, u8 c) |
affae2bff Initial revision |
119 |
{ |
9a8c72a6c USB: Rework usb_k... |
120 121 122 123 |
if (data->usb_in_pointer == USB_KBD_BUFFER_LEN - 1) { /* Check for buffer full. */ if (data->usb_out_pointer == 0) return; |
affae2bff Initial revision |
124 |
|
9a8c72a6c USB: Rework usb_k... |
125 126 127 128 129 |
data->usb_in_pointer = 0; } else { /* Check for buffer full. */ if (data->usb_in_pointer == data->usb_out_pointer - 1) return; |
affae2bff Initial revision |
130 |
|
9a8c72a6c USB: Rework usb_k... |
131 132 |
data->usb_in_pointer++; } |
affae2bff Initial revision |
133 |
|
9a8c72a6c USB: Rework usb_k... |
134 |
data->usb_kbd_buffer[data->usb_in_pointer] = c; |
affae2bff Initial revision |
135 |
} |
9a8c72a6c USB: Rework usb_k... |
136 137 138 139 |
/* * 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 |
140 |
*/ |
affae2bff Initial revision |
141 142 |
static void usb_kbd_setled(struct usb_device *dev) { |
9a8c72a6c USB: Rework usb_k... |
143 144 |
struct usb_interface *iface = &dev->config.if_desc[0]; struct usb_kbd_pdata *data = dev->privptr; |
9b2393812 usb: kbd: Fix una... |
145 |
ALLOC_ALIGN_BUFFER(uint32_t, leds, 1, USB_DMA_MINALIGN); |
9a8c72a6c USB: Rework usb_k... |
146 |
|
9b2393812 usb: kbd: Fix una... |
147 |
*leds = data->flags & USB_KBD_LEDMASK; |
affae2bff Initial revision |
148 149 |
usb_control_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE, |
9b2393812 usb: kbd: Fix una... |
150 |
0x200, iface->desc.bInterfaceNumber, leds, 1, 0); |
affae2bff Initial revision |
151 |
} |
9a8c72a6c USB: Rework usb_k... |
152 |
#define CAPITAL_MASK 0x20 |
affae2bff Initial revision |
153 |
/* Translate the scancode in ASCII */ |
9a8c72a6c USB: Rework usb_k... |
154 155 |
static int usb_kbd_translate(struct usb_kbd_pdata *data, unsigned char scancode, unsigned char modifier, int pressed) |
affae2bff Initial revision |
156 |
{ |
9a8c72a6c USB: Rework usb_k... |
157 |
uint8_t keycode = 0; |
affae2bff Initial revision |
158 |
|
9a8c72a6c USB: Rework usb_k... |
159 |
/* Key released */ |
00b7d6ecc USB: Squash check... |
160 |
if (pressed == 0) { |
9a8c72a6c USB: Rework usb_k... |
161 |
data->repeat_delay = 0; |
affae2bff Initial revision |
162 163 |
return 0; } |
9a8c72a6c USB: Rework usb_k... |
164 |
|
00b7d6ecc USB: Squash check... |
165 |
if (pressed == 2) { |
9a8c72a6c USB: Rework usb_k... |
166 167 |
data->repeat_delay++; if (data->repeat_delay < REPEAT_DELAY) |
affae2bff Initial revision |
168 |
return 0; |
9a8c72a6c USB: Rework usb_k... |
169 170 |
data->repeat_delay = REPEAT_DELAY; |
affae2bff Initial revision |
171 |
} |
9a8c72a6c USB: Rework usb_k... |
172 173 174 175 176 177 |
/* Alphanumeric values */ if ((scancode > 3) && (scancode <= 0x1d)) { keycode = scancode - 4 + 'a'; if (data->flags & USB_KBD_CAPSLOCK) |
00b7d6ecc USB: Squash check... |
178 |
keycode &= ~CAPITAL_MASK; |
9a8c72a6c USB: Rework usb_k... |
179 180 181 |
if (modifier & (LEFT_SHIFT | RIGHT_SHIFT)) { /* Handle CAPSLock + Shift pressed simultaneously */ |
00b7d6ecc USB: Squash check... |
182 |
if (keycode & CAPITAL_MASK) |
00b7d6ecc USB: Squash check... |
183 |
keycode &= ~CAPITAL_MASK; |
affae2bff Initial revision |
184 |
else |
00b7d6ecc USB: Squash check... |
185 |
keycode |= CAPITAL_MASK; |
affae2bff Initial revision |
186 187 |
} } |
9a8c72a6c USB: Rework usb_k... |
188 |
|
bdbcbe752 usb: kbd: Prevent... |
189 |
if ((scancode > 0x1d) && (scancode < 0x39)) { |
9a8c72a6c USB: Rework usb_k... |
190 191 192 193 194 |
/* 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 |
195 |
} |
4785a694c Add Ctrl combo ke... |
196 |
|
d53da847c usb: add numeric ... |
197 198 199 |
/* Numeric keypad */ if ((scancode >= 0x54) && (scancode <= 0x67)) keycode = usb_kbd_num_keypad[scancode - 0x54]; |
9a8c72a6c USB: Rework usb_k... |
200 |
if (data->flags & USB_KBD_CTRL) |
4785a694c Add Ctrl combo ke... |
201 |
keycode = scancode - 0x3; |
00b7d6ecc USB: Squash check... |
202 203 |
if (pressed == 1) { if (scancode == NUM_LOCK) { |
9a8c72a6c USB: Rework usb_k... |
204 |
data->flags ^= USB_KBD_NUMLOCK; |
affae2bff Initial revision |
205 206 |
return 1; } |
9a8c72a6c USB: Rework usb_k... |
207 |
|
00b7d6ecc USB: Squash check... |
208 |
if (scancode == CAPS_LOCK) { |
9a8c72a6c USB: Rework usb_k... |
209 |
data->flags ^= USB_KBD_CAPSLOCK; |
affae2bff Initial revision |
210 211 |
return 1; } |
00b7d6ecc USB: Squash check... |
212 |
if (scancode == SCROLL_LOCK) { |
9a8c72a6c USB: Rework usb_k... |
213 |
data->flags ^= USB_KBD_SCROLLLOCK; |
affae2bff Initial revision |
214 215 216 |
return 1; } } |
9a8c72a6c USB: Rework usb_k... |
217 218 |
/* Report keycode if any */ |
3352c2114 usb: kbd: simplif... |
219 |
if (keycode) { |
ceb4972a8 usb: common: Weed... |
220 |
debug("%c", keycode); |
9a8c72a6c USB: Rework usb_k... |
221 |
usb_kbd_put_queue(data, keycode); |
3352c2114 usb: kbd: simplif... |
222 |
return 0; |
affae2bff Initial revision |
223 |
} |
9a8c72a6c USB: Rework usb_k... |
224 |
|
87e91bcca usb: kbd: impleme... |
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 |
#ifdef CONFIG_USB_KEYBOARD_FN_KEYS if (scancode < 0x3a || scancode > 0x52 || scancode == 0x46 || scancode == 0x47) return 1; usb_kbd_put_queue(data, 0x1b); if (scancode < 0x3e) { /* F1 - F4 */ usb_kbd_put_queue(data, 0x4f); usb_kbd_put_queue(data, scancode - 0x3a + 'P'); return 0; } usb_kbd_put_queue(data, '['); if (scancode < 0x42) { /* F5 - F8 */ usb_kbd_put_queue(data, '1'); if (scancode == 0x3e) --scancode; keycode = scancode - 0x3f + '7'; } else if (scancode < 0x49) { /* F9 - F12 */ usb_kbd_put_queue(data, '2'); if (scancode > 0x43) ++scancode; keycode = scancode - 0x42 + '0'; } else { /* * INSERT, HOME, PAGE UP, DELETE, END, PAGE DOWN, * RIGHT, LEFT, DOWN, UP */ keycode = usb_special_keys[scancode - 0x49]; } usb_kbd_put_queue(data, keycode); if (scancode < 0x4f && scancode != 0x4a && scancode != 0x4d) usb_kbd_put_queue(data, '~'); return 0; #else |
3352c2114 usb: kbd: simplif... |
262 263 264 265 266 267 268 269 |
/* Left, Right, Up, Down */ if (scancode > 0x4e && scancode < 0x53) { usb_kbd_put_queue(data, 0x1b); usb_kbd_put_queue(data, '['); usb_kbd_put_queue(data, usb_special_keys[scancode - 0x4f]); return 0; } return 1; |
87e91bcca usb: kbd: impleme... |
270 |
#endif /* CONFIG_USB_KEYBOARD_FN_KEYS */ |
affae2bff Initial revision |
271 |
} |
9a8c72a6c USB: Rework usb_k... |
272 273 274 275 276 277 278 279 280 281 282 283 284 285 |
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... |
286 287 288 |
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... |
289 |
res |= usb_kbd_translate(data, old[i], data->new[0], up); |
08a98b89d usb: Fix USB keyb... |
290 |
} |
9a8c72a6c USB: Rework usb_k... |
291 292 293 |
return res; } |
affae2bff Initial revision |
294 |
/* Interrupt service routine */ |
48c8073ec USB: Add function... |
295 |
static int usb_kbd_irq_worker(struct usb_device *dev) |
affae2bff Initial revision |
296 |
{ |
9a8c72a6c USB: Rework usb_k... |
297 298 |
struct usb_kbd_pdata *data = dev->privptr; int i, res = 0; |
4785a694c Add Ctrl combo ke... |
299 |
|
9a8c72a6c USB: Rework usb_k... |
300 301 302 303 304 305 |
/* 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... |
306 |
|
08a98b89d usb: Fix USB keyb... |
307 |
for (i = 2; i < USB_KBD_BOOT_REPORT_SIZE; i++) { |
9a8c72a6c USB: Rework usb_k... |
308 309 |
res |= usb_kbd_service_key(dev, i, 0); res |= usb_kbd_service_key(dev, i, 1); |
affae2bff Initial revision |
310 |
} |
00b7d6ecc USB: Squash check... |
311 |
|
9a8c72a6c USB: Rework usb_k... |
312 313 314 |
/* 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... |
315 |
if (res == 1) |
affae2bff Initial revision |
316 |
usb_kbd_setled(dev); |
00b7d6ecc USB: Squash check... |
317 |
|
08a98b89d usb: Fix USB keyb... |
318 |
memcpy(data->old, data->new, USB_KBD_BOOT_REPORT_SIZE); |
00b7d6ecc USB: Squash check... |
319 |
|
9a8c72a6c USB: Rework usb_k... |
320 |
return 1; |
affae2bff Initial revision |
321 |
} |
9a8c72a6c USB: Rework usb_k... |
322 |
/* Keyboard interrupt handler */ |
48c8073ec USB: Add function... |
323 324 |
static int usb_kbd_irq(struct usb_device *dev) { |
08a98b89d usb: Fix USB keyb... |
325 326 |
if ((dev->irq_status != 0) || (dev->irq_act_len != USB_KBD_BOOT_REPORT_SIZE)) { |
ceb4972a8 usb: common: Weed... |
327 328 329 |
debug("USB KBD: Error %lX, len %d ", dev->irq_status, dev->irq_act_len); |
48c8073ec USB: Add function... |
330 331 332 333 334 |
return 1; } return usb_kbd_irq_worker(dev); } |
9a8c72a6c USB: Rework usb_k... |
335 336 337 |
/* Interrupt polling */ static inline void usb_kbd_poll_for_event(struct usb_device *dev) { |
8454c84af usb: kbd: Fix key... |
338 |
#if defined(CONFIG_SYS_USB_EVENT_POLL) |
8f8d7d245 usb: kbd: Cache p... |
339 |
struct usb_kbd_pdata *data = dev->privptr; |
f9636e8d3 USB: move keyboar... |
340 |
|
216db3af2 usb: kbd: fix typo |
341 |
/* Submit an interrupt transfer request */ |
fdd135bf8 usb: usb_submit_i... |
342 |
if (usb_int_msg(dev, data->intpipe, &data->new[0], |
3437121c0 usb: Add nonblock... |
343 |
data->intpktsize, data->intinterval, true) >= 0) |
3e816a242 usb_kdb: only pro... |
344 |
usb_kbd_irq_worker(dev); |
8454c84af usb: kbd: Fix key... |
345 346 347 |
#elif defined(CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP) || \ defined(CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE) #if defined(CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP) |
9a8c72a6c USB: Rework usb_k... |
348 349 350 351 |
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... |
352 |
1, 0, data->new, USB_KBD_BOOT_REPORT_SIZE); |
8454c84af usb: kbd: Fix key... |
353 |
if (memcmp(data->old, data->new, USB_KBD_BOOT_REPORT_SIZE)) { |
9a8c72a6c USB: Rework usb_k... |
354 |
usb_kbd_irq_worker(dev); |
8454c84af usb: kbd: Fix key... |
355 |
#else |
8e5531198 usb: kbd: Add (op... |
356 357 358 359 360 361 |
struct usb_kbd_pdata *data = dev->privptr; if (poll_int_queue(dev, data->intq)) { usb_kbd_irq_worker(dev); /* We've consumed all queued int packets, create new */ destroy_int_queue(dev, data->intq); data->intq = create_int_queue(dev, data->intpipe, 1, |
8bb6c1d1e usb: Add an inter... |
362 363 |
USB_KBD_BOOT_REPORT_SIZE, data->new, data->intinterval); |
8454c84af usb: kbd: Fix key... |
364 365 366 367 368 369 370 |
#endif data->last_report = get_timer(0); /* Repeat last usb hid report every REPEAT_RATE ms for keyrepeat */ } else if (data->last_report != -1 && get_timer(data->last_report) > REPEAT_RATE) { usb_kbd_irq_worker(dev); data->last_report = get_timer(0); |
8e5531198 usb: kbd: Add (op... |
371 |
} |
9a8c72a6c USB: Rework usb_k... |
372 373 374 375 |
#endif } /* test if a character is in the queue */ |
709ea543b stdio: Pass devic... |
376 |
static int usb_kbd_testc(struct stdio_dev *sdev) |
9a8c72a6c USB: Rework usb_k... |
377 378 379 380 |
{ struct stdio_dev *dev; struct usb_device *usb_kbd_dev; struct usb_kbd_pdata *data; |
c95e2b9ea console: usb: kbd... |
381 382 383 384 385 386 387 388 389 390 |
#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 |
4fb67f47f usb_kdb: Get stdi... |
391 |
dev = stdio_get_by_name(sdev->name); |
9a8c72a6c USB: Rework usb_k... |
392 393 394 395 396 397 398 399 400 |
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... |
401 |
static int usb_kbd_getc(struct stdio_dev *sdev) |
9a8c72a6c USB: Rework usb_k... |
402 403 404 405 |
{ struct stdio_dev *dev; struct usb_device *usb_kbd_dev; struct usb_kbd_pdata *data; |
4fb67f47f usb_kdb: Get stdi... |
406 |
dev = stdio_get_by_name(sdev->name); |
9a8c72a6c USB: Rework usb_k... |
407 408 |
usb_kbd_dev = (struct usb_device *)dev->priv; data = usb_kbd_dev->privptr; |
f8f3e0e53 usb_kbd: Add supp... |
409 410 |
while (data->usb_in_pointer == data->usb_out_pointer) { WATCHDOG_RESET(); |
9a8c72a6c USB: Rework usb_k... |
411 |
usb_kbd_poll_for_event(usb_kbd_dev); |
f8f3e0e53 usb_kbd: Add supp... |
412 |
} |
9a8c72a6c USB: Rework usb_k... |
413 414 415 416 417 418 419 420 421 422 |
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. */ |
34ab37eef dm: usb: Add supp... |
423 |
static int usb_kbd_probe_dev(struct usb_device *dev, unsigned int ifnum) |
affae2bff Initial revision |
424 |
{ |
8f8bd565f USB Consolidate d... |
425 |
struct usb_interface *iface; |
affae2bff Initial revision |
426 |
struct usb_endpoint_descriptor *ep; |
9a8c72a6c USB: Rework usb_k... |
427 |
struct usb_kbd_pdata *data; |
affae2bff Initial revision |
428 |
|
00b7d6ecc USB: Squash check... |
429 430 |
if (dev->descriptor.bNumConfigurations != 1) return 0; |
9a8c72a6c USB: Rework usb_k... |
431 |
|
affae2bff Initial revision |
432 |
iface = &dev->config.if_desc[ifnum]; |
2cdb58ebd usb: Avoid open-c... |
433 |
if (iface->desc.bInterfaceClass != USB_CLASS_HID) |
8f8bd565f USB Consolidate d... |
434 |
return 0; |
9a8c72a6c USB: Rework usb_k... |
435 |
|
2cdb58ebd usb: Avoid open-c... |
436 |
if (iface->desc.bInterfaceSubClass != USB_SUB_HID_BOOT) |
8f8bd565f USB Consolidate d... |
437 |
return 0; |
9a8c72a6c USB: Rework usb_k... |
438 |
|
2cdb58ebd usb: Avoid open-c... |
439 |
if (iface->desc.bInterfaceProtocol != USB_PROT_HID_KEYBOARD) |
8f8bd565f USB Consolidate d... |
440 |
return 0; |
9a8c72a6c USB: Rework usb_k... |
441 |
|
8f8bd565f USB Consolidate d... |
442 443 |
if (iface->desc.bNumEndpoints != 1) return 0; |
affae2bff Initial revision |
444 445 |
ep = &iface->ep_desc[0]; |
9a8c72a6c USB: Rework usb_k... |
446 |
/* Check if endpoint 1 is interrupt endpoint */ |
00b7d6ecc USB: Squash check... |
447 448 |
if (!(ep->bEndpointAddress & 0x80)) return 0; |
9a8c72a6c USB: Rework usb_k... |
449 |
|
00b7d6ecc USB: Squash check... |
450 451 |
if ((ep->bmAttributes & 3) != 3) return 0; |
9a8c72a6c USB: Rework usb_k... |
452 |
|
ceb4972a8 usb: common: Weed... |
453 454 |
debug("USB KBD: found set protocol... "); |
9a8c72a6c USB: Rework usb_k... |
455 456 457 458 459 460 461 462 463 464 |
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... |
465 |
/* allocate input buffer aligned and sized to USB DMA alignment */ |
08a98b89d usb: Fix USB keyb... |
466 467 |
data->new = memalign(USB_DMA_MINALIGN, roundup(USB_KBD_BOOT_REPORT_SIZE, USB_DMA_MINALIGN)); |
d7475386b USB: make usb_kbd... |
468 |
|
9a8c72a6c USB: Rework usb_k... |
469 470 471 472 473 |
/* Insert private data into USB device structure */ dev->privptr = data; /* Set IRQ handler */ dev->irq_handle = usb_kbd_irq; |
8f8d7d245 usb: kbd: Cache p... |
474 475 476 477 |
data->intpipe = usb_rcvintpipe(dev, ep->bEndpointAddress); data->intpktsize = min(usb_maxpacket(dev, data->intpipe), USB_KBD_BOOT_REPORT_SIZE); data->intinterval = ep->bInterval; |
8454c84af usb: kbd: Fix key... |
478 |
data->last_report = -1; |
9a8c72a6c USB: Rework usb_k... |
479 480 481 |
/* We found a USB Keyboard, install it. */ usb_set_protocol(dev, iface->desc.bInterfaceNumber, 0); |
de451493f usb: kbd: Disable... |
482 483 |
debug("USB KBD: found set idle... "); |
8454c84af usb: kbd: Fix key... |
484 485 |
#if !defined(CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP) && \ !defined(CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE) |
8454c84af usb: kbd: Fix key... |
486 |
usb_set_idle(dev, iface->desc.bInterfaceNumber, REPEAT_RATE / 4, 0); |
de451493f usb: kbd: Disable... |
487 488 |
#else usb_set_idle(dev, iface->desc.bInterfaceNumber, 0, 0); |
8454c84af usb: kbd: Fix key... |
489 |
#endif |
9a8c72a6c USB: Rework usb_k... |
490 |
|
ceb4972a8 usb: common: Weed... |
491 492 |
debug("USB KBD: enable interrupt pipe... "); |
8e5531198 usb: kbd: Add (op... |
493 494 |
#ifdef CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE data->intq = create_int_queue(dev, data->intpipe, 1, |
8bb6c1d1e usb: Add an inter... |
495 496 |
USB_KBD_BOOT_REPORT_SIZE, data->new, data->intinterval); |
8e5531198 usb: kbd: Add (op... |
497 |
if (!data->intq) { |
e4b70d803 usb: kbd: don't u... |
498 499 500 |
#elif defined(CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP) if (usb_get_report(dev, iface->desc.bInterfaceNumber, 1, 0, data->new, USB_KBD_BOOT_REPORT_SIZE) < 0) { |
8e5531198 usb: kbd: Add (op... |
501 |
#else |
fdd135bf8 usb: usb_submit_i... |
502 |
if (usb_int_msg(dev, data->intpipe, data->new, data->intpktsize, |
3437121c0 usb: Add nonblock... |
503 |
data->intinterval, false) < 0) { |
8e5531198 usb: kbd: Add (op... |
504 |
#endif |
5da2dc978 usb: workaround n... |
505 506 507 508 509 510 |
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... |
511 512 |
/* Success. */ |
affae2bff Initial revision |
513 514 |
return 1; } |
603afaf0e dm: usb: Split ou... |
515 516 517 518 519 520 521 |
static int probe_usb_keyboard(struct usb_device *dev) { char *stdinname; struct stdio_dev usb_kbd_dev; int error; /* Try probing the keyboard */ |
34ab37eef dm: usb: Add supp... |
522 |
if (usb_kbd_probe_dev(dev, 0) != 1) |
603afaf0e dm: usb: Split ou... |
523 524 525 526 527 528 529 |
return -ENOENT; /* Register the keyboard */ debug("USB KBD: register. "); memset(&usb_kbd_dev, 0, sizeof(struct stdio_dev)); strcpy(usb_kbd_dev.name, DEVNAME); |
1caf934a0 video: Drop DEV_F... |
530 |
usb_kbd_dev.flags = DEV_FLAGS_INPUT; |
603afaf0e dm: usb: Split ou... |
531 532 533 534 535 536 |
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; |
00caae6d4 env: Rename geten... |
537 |
stdinname = env_get("stdin"); |
b02654294 console: Don't en... |
538 |
#if CONFIG_IS_ENABLED(CONSOLE_MUX) |
603afaf0e dm: usb: Split ou... |
539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 |
error = iomux_doenv(stdin, stdinname); if (error) return error; #else /* 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; #endif return 0; } |
fd09c205f usb: s/CONFIG_DM_... |
558 |
#if !CONFIG_IS_ENABLED(DM_USB) |
9a8c72a6c USB: Rework usb_k... |
559 560 561 |
/* Search for keyboard and register it if found. */ int drv_usb_kbd_init(void) { |
9a8c72a6c USB: Rework usb_k... |
562 |
int error, i; |
697033cbf dm: usb: Support ... |
563 564 |
debug("%s: Probing for keyboard ", __func__); |
697033cbf dm: usb: Support ... |
565 |
/* Scan all USB Devices */ |
9a8c72a6c USB: Rework usb_k... |
566 |
for (i = 0; i < USB_MAX_DEVICE; i++) { |
603afaf0e dm: usb: Split ou... |
567 |
struct usb_device *dev; |
9a8c72a6c USB: Rework usb_k... |
568 569 570 |
/* Get USB device. */ dev = usb_get_dev_index(i); if (!dev) |
603afaf0e dm: usb: Split ou... |
571 |
break; |
9a8c72a6c USB: Rework usb_k... |
572 573 574 |
if (dev->devnum == -1) continue; |
603afaf0e dm: usb: Split ou... |
575 576 |
error = probe_usb_keyboard(dev); if (!error) |
9a8c72a6c USB: Rework usb_k... |
577 |
return 1; |
603afaf0e dm: usb: Split ou... |
578 |
if (error && error != -ENOENT) |
9a8c72a6c USB: Rework usb_k... |
579 |
return error; |
9a8c72a6c USB: Rework usb_k... |
580 581 582 583 584 585 586 |
} /* No USB Keyboard found */ return -1; } /* Deregister the keyboard. */ |
8a8a2257e usb: kbd: Allow "... |
587 |
int usb_kbd_deregister(int force) |
9a8c72a6c USB: Rework usb_k... |
588 |
{ |
869588dec Convert CONFIG_SY... |
589 |
#if CONFIG_IS_ENABLED(SYS_STDIO_DEREGISTER) |
dfe5b1c86 usb: kbd: Fix mem... |
590 591 592 593 594 595 596 597 598 599 |
struct stdio_dev *dev; struct usb_device *usb_kbd_dev; struct usb_kbd_pdata *data; dev = stdio_get_by_name(DEVNAME); if (dev) { usb_kbd_dev = (struct usb_device *)dev->priv; data = usb_kbd_dev->privptr; if (stdio_deregister_dev(dev, force) != 0) return 1; |
b02654294 console: Don't en... |
600 |
#if CONFIG_IS_ENABLED(CONSOLE_MUX) |
00caae6d4 env: Rename geten... |
601 |
if (iomux_doenv(stdin, env_get("stdin")) != 0) |
3cbcb2892 usb: Fix usb_kbd_... |
602 603 |
return 1; #endif |
8e5531198 usb: kbd: Add (op... |
604 605 606 |
#ifdef CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE destroy_int_queue(usb_kbd_dev, data->intq); #endif |
dfe5b1c86 usb: kbd: Fix mem... |
607 608 609 |
free(data->new); free(data); } |
0ea09dfe8 usb: kbd: Do not ... |
610 611 |
return 0; |
9a8c72a6c USB: Rework usb_k... |
612 613 614 615 |
#else return 1; #endif } |
34ab37eef dm: usb: Add supp... |
616 |
|
9a80e7143 usb: kbd: Do not ... |
617 |
#endif |
fd09c205f usb: s/CONFIG_DM_... |
618 |
#if CONFIG_IS_ENABLED(DM_USB) |
34ab37eef dm: usb: Add supp... |
619 620 621 622 |
static int usb_kbd_probe(struct udevice *dev) { struct usb_device *udev = dev_get_parent_priv(dev); |
34ab37eef dm: usb: Add supp... |
623 |
|
8319aeb1d usb: squash lines... |
624 |
return probe_usb_keyboard(udev); |
34ab37eef dm: usb: Add supp... |
625 |
} |
8a8348703 dm: usb: Add a re... |
626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 |
static int usb_kbd_remove(struct udevice *dev) { struct usb_device *udev = dev_get_parent_priv(dev); struct usb_kbd_pdata *data; struct stdio_dev *sdev; int ret; sdev = stdio_get_by_name(DEVNAME); if (!sdev) { ret = -ENXIO; goto err; } data = udev->privptr; if (stdio_deregister_dev(sdev, true)) { ret = -EPERM; goto err; } |
b02654294 console: Don't en... |
643 |
#if CONFIG_IS_ENABLED(CONSOLE_MUX) |
00caae6d4 env: Rename geten... |
644 |
if (iomux_doenv(stdin, env_get("stdin"))) { |
8a8348703 dm: usb: Add a re... |
645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 |
ret = -ENOLINK; goto err; } #endif #ifdef CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE destroy_int_queue(udev, data->intq); #endif free(data->new); free(data); return 0; err: printf("%s: warning, ret=%d", __func__, ret); return ret; } |
34ab37eef dm: usb: Add supp... |
660 661 662 663 664 665 666 667 668 669 |
static const struct udevice_id usb_kbd_ids[] = { { .compatible = "usb-keyboard" }, { } }; U_BOOT_DRIVER(usb_kbd) = { .name = "usb_kbd", .id = UCLASS_KEYBOARD, .of_match = usb_kbd_ids, .probe = usb_kbd_probe, |
8a8348703 dm: usb: Add a re... |
670 |
.remove = usb_kbd_remove, |
34ab37eef dm: usb: Add supp... |
671 |
}; |
34ab37eef dm: usb: Add supp... |
672 673 674 675 676 677 |
static const struct usb_device_id kbd_id_table[] = { { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS | USB_DEVICE_ID_MATCH_INT_PROTOCOL, .bInterfaceClass = USB_CLASS_HID, |
2cdb58ebd usb: Avoid open-c... |
678 679 |
.bInterfaceSubClass = USB_SUB_HID_BOOT, .bInterfaceProtocol = USB_PROT_HID_KEYBOARD, |
34ab37eef dm: usb: Add supp... |
680 681 682 683 684 685 686 |
}, { } /* Terminating entry */ }; U_BOOT_USB_DEVICE(usb_kbd, kbd_id_table); #endif |