1/* ********************************************************************* 2 * Broadcom Common Firmware Environment (CFE) 3 * 4 * USB Human Interface Driver File: usbhid.c 5 * 6 * This module deals with keyboards, mice, etc. It's very simple, 7 * and only the "boot protocol" is supported. 8 * 9 * Author: Mitch Lichtenberg (mpl@broadcom.com) 10 * 11 ********************************************************************* 12 * 13 * Copyright 2000,2001,2002,2003 14 * Broadcom Corporation. All rights reserved. 15 * 16 * This software is furnished under license and may be used and 17 * copied only in accordance with the following terms and 18 * conditions. Subject to these conditions, you may download, 19 * copy, install, use, modify and distribute modified or unmodified 20 * copies of this software in source and/or binary form. No title 21 * or ownership is transferred hereby. 22 * 23 * 1) Any source code used, modified or distributed must reproduce 24 * and retain this copyright notice and list of conditions 25 * as they appear in the source file. 26 * 27 * 2) No right is granted to use any trade name, trademark, or 28 * logo of Broadcom Corporation. The "Broadcom Corporation" 29 * name may not be used to endorse or promote products derived 30 * from this software without the prior written permission of 31 * Broadcom Corporation. 32 * 33 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR 34 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED 35 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 36 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT 37 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN 38 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, 39 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 40 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 41 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 42 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 43 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 44 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF 45 * THE POSSIBILITY OF SUCH DAMAGE. 46 ********************************************************************* */ 47 48 49#ifndef _CFE_ 50#include <stdio.h> 51#include <time.h> 52#include <memory.h> 53#include <stdint.h> 54#include "usbhack.h" 55#else 56#include "lib_types.h" 57#include "lib_string.h" 58#include "lib_printf.h" 59#include "cfe_console.h" 60#endif 61 62#include "lib_malloc.h" 63#include "lib_queue.h" 64#include "usbchap9.h" 65#include "usbd.h" 66 67/* ********************************************************************* 68 * Constants 69 ********************************************************************* */ 70 71#define HID_BOOT_PROTOCOL 0 72#define HID_REPORT_PROTOCOL 1 73 74#define HID_DEVTYPE_UNKNOWN 0 75#define HID_DEVTYPE_KBD 1 76#define HID_DEVTYPE_MOUSE 2 77#define HID_DEVTYPE_MAX 2 78 79#define UBR_KBD_MODS 0 80#define UBR_KBD_RSVD 1 81#define UBR_KBD_KEYS 2 82#define UBR_KBD_NUMKEYS 6 83#define UBR_KBD_MAX 8 84 85#define KBD_MOD_LCTRL 0x01 86#define KBD_MOD_LSHIFT 0x02 87#define KBD_MOD_LALT 0x04 88#define KBD_MOD_LWIN 0x08 89 90#define KBD_MOD_RCTRL 0x10 91#define KBD_MOD_RSHIFT 0x20 92#define KBD_MOD_RALT 0x40 93#define KBD_MOD_RWIN 0x80 94 95/* ********************************************************************* 96 * Macros 97 ********************************************************************* */ 98 99#define usbhid_set_protocol(dev,protocol,ifc) \ 100 usb_simple_request(dev,0x21,0x0B,0,ifc) 101 102 103/* ********************************************************************* 104 * Forward Definitions 105 ********************************************************************* */ 106 107static int usbhid_attach(usbdev_t *dev,usb_driver_t *drv); 108static int usbhid_detach(usbdev_t *dev); 109 110/* ********************************************************************* 111 * Structures 112 ********************************************************************* */ 113 114typedef struct usbhid_softc_s { 115 int uhid_ipipe; 116 int uhid_ipipemps; 117 int uhid_devtype; 118 uint8_t uhid_imsg[UBR_KBD_MAX]; 119 uint8_t uhid_lastmsg[UBR_KBD_MAX]; 120 uint32_t uhid_shiftflags; 121} usbhid_softc_t; 122 123usb_driver_t usbhid_driver = { 124 "Human-Interface Device", 125 usbhid_attach, 126 usbhid_detach 127}; 128 129static char *usbhid_devtypes[3] = { 130 "Unknown", 131 "Keyboard", 132 "Mouse"}; 133 134#ifdef CFG_VGACONSOLE 135extern int pcconsole_enqueue(uint8_t ch); 136#endif 137 138 139/* ********************************************************************* 140 * Constants for keyboard table 141 ********************************************************************* */ 142 143#define FLG_NUM 0x0001 /* Toggles: same as bits for LEDs */ 144#define FLG_CAPS 0x0002 145#define FLG_SCROLL 0x0004 146#define FLG_SHIFT 0x0008 /* Shifts */ 147#define FLG_CTRL 0x0100 148#define FLG_ALT 0x0200 149#define FLG_FKEY 0x0400 /* function keys */ 150#define FLG_NKPD 0x0800 /* numeric keypad */ 151#define FLG_ASCII 0x1000 /* regular ASCII character */ 152#define FLG_NONE 0x2000 153 154 155/* ********************************************************************* 156 * Structures for keyboard table 157 ********************************************************************* */ 158 159#define KC_RESPLEN 4 160typedef struct keycode_s { 161 int kc_type; 162 char kc_normal[KC_RESPLEN]; 163 char kc_shifted[KC_RESPLEN]; 164 char kc_ctrl[KC_RESPLEN]; 165} keycode_t; 166 167 168/* ********************************************************************* 169 * Scan code conversion table 170 ********************************************************************* */ 171 172static keycode_t usbhid_scantable[] = { 173 { FLG_NONE, "", "", "" }, /* 0 */ 174 { FLG_NONE, "", "", "" }, /* 1 */ 175 { FLG_NONE, "", "", "" }, /* 2 */ 176 { FLG_NONE, "", "", "" }, /* 3 */ 177 { FLG_ASCII, "a", "A", "\001" }, /* 4 a */ 178 { FLG_ASCII, "b", "B", "\002" }, /* 5 b */ 179 { FLG_ASCII, "c", "C", "\003" }, /* 6 c */ 180 { FLG_ASCII, "d", "D", "\004" }, /* 7 d */ 181 { FLG_ASCII, "e", "E", "\005" }, /* 8 e */ 182 { FLG_ASCII, "f", "F", "\006" }, /* 9 f */ 183 { FLG_ASCII, "g", "G", "\007" }, /* 10 g */ 184 { FLG_ASCII, "h", "H", "\010" }, /* 11 h */ 185 { FLG_ASCII, "i", "I", "\011" }, /* 12 i */ 186 { FLG_ASCII, "j", "J", "\n" }, /* 13 j */ 187 { FLG_ASCII, "k", "K", "\013" }, /* 14 k */ 188 { FLG_ASCII, "l", "L", "\014" }, /* 15 l */ 189 { FLG_ASCII, "m", "M", "\r" }, /* 16 m */ 190 { FLG_ASCII, "n", "N", "\016" }, /* 17 n */ 191 { FLG_ASCII, "o", "O", "\017" }, /* 18 o */ 192 { FLG_ASCII, "p", "P", "\020" }, /* 19 p */ 193 { FLG_ASCII, "q", "Q", "\021" }, /* 20 q */ 194 { FLG_ASCII, "r", "R", "\022" }, /* 21 r */ 195 { FLG_ASCII, "s", "S", "\023" }, /* 22 s */ 196 { FLG_ASCII, "t", "T", "\024" }, /* 23 t */ 197 { FLG_ASCII, "u", "U", "\025" }, /* 24 u */ 198 { FLG_ASCII, "v", "V", "\026" }, /* 25 v */ 199 { FLG_ASCII, "w", "W", "\027" }, /* 26 w */ 200 { FLG_ASCII, "x", "X", "\030" }, /* 27 x */ 201 { FLG_ASCII, "y", "Y", "\031" }, /* 28 y */ 202 { FLG_ASCII, "z", "Z", "\032" }, /* 29 z */ 203 204 { FLG_ASCII, "1", "!", "!" }, /* 30 1 */ 205 { FLG_ASCII, "2", "@", "\000" }, /* 31 2 */ 206 { FLG_ASCII, "3", "#", "#" }, /* 32 3 */ 207 { FLG_ASCII, "4", "$", "$" }, /* 33 4 */ 208 { FLG_ASCII, "5", "%", "%" }, /* 34 5 */ 209 { FLG_ASCII, "6", "^", "\036" }, /* 35 6 */ 210 { FLG_ASCII, "7", "&", "&" }, /* 36 7 */ 211 { FLG_ASCII, "8", "*", "\010" }, /* 37 8 */ 212 { FLG_ASCII, "9", "(", "(" }, /* 38 9 */ 213 { FLG_ASCII, "0", ")", ")" }, /* 39 0 */ 214 215 { FLG_ASCII, "\r", "\r", "\n" }, /* 40 ENT */ 216 { FLG_ASCII, "\033", "\033", "\033" }, /* 41 ESC */ 217 { FLG_ASCII, "\177", "\177", "\010" }, /* 42 <- */ 218 { FLG_ASCII, "\t", "\177\t", "\t" }, /* 43 ->| */ 219 { FLG_ASCII, " ", " ", "\000" }, /* 44 SPC */ 220 221 { FLG_ASCII, "-", "_", "\037" }, /* 45 - */ 222 { FLG_ASCII, "=", "+", "+" }, /* 46 = */ 223 { FLG_ASCII, "[", "{", "\033" }, /* 47 [ */ 224 { FLG_ASCII, "]", "}", "\035" }, /* 48 ] */ 225 { FLG_ASCII, "\\", "|", "\034" }, /* 49 \ */ 226 227 { FLG_NONE, "", "", "" }, /* 50 pound */ 228 229 { FLG_ASCII, ";", ":", ";" }, /* 51 ; */ 230 { FLG_ASCII, "'", "\"", "'" }, /* 52 ' */ 231 { FLG_ASCII, "`", "~", "`" }, /* 53 ` */ 232 { FLG_ASCII, ",", "<", "<" }, /* 54 , */ 233 { FLG_ASCII, ".", ">", ">" }, /* 55 . */ 234 { FLG_ASCII, "/", "?", "\037" }, /* 56 / */ 235 { FLG_CAPS, "", "", "" }, /* 57 CAPS */ 236 237 { FLG_FKEY, "\033[M", "\033[Y", "\033[k" }, /* 58 f1 */ 238 { FLG_FKEY, "\033[N", "\033[Z", "\033[l" }, /* 59 f2 */ 239 { FLG_FKEY, "\033[O", "\033[a", "\033[m" }, /* 60 f3 */ 240 { FLG_FKEY, "\033[P", "\033[b", "\033[n" }, /* 61 f4 */ 241 { FLG_FKEY, "\033[Q", "\033[c", "\033[o" }, /* 62 f5 */ 242 { FLG_FKEY, "\033[R", "\033[d", "\033[p" }, /* 63 f6 */ 243 { FLG_FKEY, "\033[S", "\033[e", "\033[q" }, /* 64 f7 */ 244 { FLG_FKEY, "\033[T", "\033[f", "\033[r" }, /* 65 f8 */ 245 { FLG_FKEY, "\033[U", "\033[g", "\033[s" }, /* 66 f9 */ 246 { FLG_FKEY, "\033[V", "\033[h", "\033[t" }, /* 67 f10 */ 247 { FLG_FKEY, "\033[W", "\033[i", "\033[u" }, /* 68 f11 */ 248 { FLG_FKEY, "\033[X", "\033[j", "\033[v" }, /* 69 f12 */ 249 250 { FLG_NONE, "", "", "" }, /* 70 prtsc */ 251 { FLG_SCROLL, "", "", "" }, /* 71 SCRLK */ 252 { FLG_NONE, "", "", "" }, /* 72 pause */ 253 { FLG_NONE, "", "", "" }, /* 73 KPins */ 254 { FLG_NONE, "", "", "" }, /* 74 KPhome */ 255 { FLG_NONE, "", "", "" }, /* 75 KPpgup */ 256 { FLG_NONE, "", "", "" }, /* 76 KPdel */ 257 { FLG_NONE, "", "", "" }, /* 77 KPend */ 258 { FLG_NONE, "", "", "" }, /* 78 KPpgdn */ 259 260 { FLG_FKEY, "\033[C", "", "" }, /* 79 KPright */ 261 { FLG_FKEY, "\033[D", "", "" }, /* 80 KPleft */ 262 { FLG_FKEY, "\033[B", "", "" }, /* 81 KPdown */ 263 { FLG_FKEY, "\033[A", "", "" }, /* 82 KPup */ 264 265 { FLG_NUM, "", "", "" }, /* 83 NUMLK */ 266 { FLG_NKPD, "/", "/", "/" }, /* 84 KP/ */ 267 { FLG_NKPD, "*", "*", "*" }, /* 85 KP* */ 268 { FLG_NKPD, "-", "-", "-" }, /* 86 KP- */ 269 { FLG_NKPD, "+", "+", "+" }, /* 87 KP+ */ 270 { FLG_NKPD, "\r", "\r", "\n" }, /* 88 KPent */ 271 272 { FLG_NKPD, "1", "\033[F", "1" }, /* 89 KP1 */ 273 { FLG_NKPD, "2", "\033[B", "2" }, /* 90 KP2 */ 274 { FLG_NKPD, "3", "\033[G", "3" }, /* 91 KP3 */ 275 { FLG_NKPD, "4", "\033[D", "4" }, /* 92 KP4 */ 276 { FLG_NKPD, "5", "\033[E", "5" }, /* 93 KP5 */ 277 { FLG_NKPD, "6", "\033[C", "6" }, /* 94 KP6 */ 278 { FLG_NKPD, "7", "\033[H", "7" }, /* 95 KP7 */ 279 { FLG_NKPD, "8", "\033[A", "8" }, /* 96 KP8 */ 280 { FLG_NKPD, "9", "\033[I", "9" }, /* 97 KP9 */ 281 { FLG_NKPD, "0", "\033[L", "0" }, /* 98 KP0 */ 282 283 { FLG_NKPD, ".", "\177", "." }, /* 99 KP. */ 284 285 { FLG_NONE, "", "", "" }, /* 100 non\ */ 286 287}; 288 289#define usbhid_scantablesize (sizeof(usbhid_scantable)/sizeof(keycode_t)) 290 291 292/* ********************************************************************* 293 * usbhid_kbd_mod1(uhid) 294 * 295 * Process modifier key changes for the current USB event, 296 * which was stored in uhid_imsg. Basically all this does 297 * is update uhid_shiftflags, converting the bits into the ones 298 * we use in our keyboard table. 299 * 300 * Input parameters: 301 * uhid - the hid softc. 302 * 303 * Return value: 304 * nothing 305 ********************************************************************* */ 306 307static void usbhid_kbd_mod1(usbhid_softc_t *uhid) 308{ 309 uint8_t changed; 310 uint8_t mod; 311 312 /* 313 * See if anything changed. 314 */ 315 316 changed = (uhid->uhid_imsg[UBR_KBD_MODS] ^ uhid->uhid_lastmsg[UBR_KBD_MODS]); 317 if (changed == 0) return; 318 319 /* 320 * Something changed. Reflect changes in our local copy of the 321 * shift state. 322 */ 323 324 mod = uhid->uhid_imsg[UBR_KBD_MODS]; 325 326 uhid->uhid_shiftflags &= ~(FLG_SHIFT|FLG_ALT|FLG_CTRL); 327 328 if (mod & (KBD_MOD_LCTRL|KBD_MOD_RCTRL)) uhid->uhid_shiftflags |= FLG_CTRL; 329 if (mod & (KBD_MOD_LSHIFT|KBD_MOD_RSHIFT)) uhid->uhid_shiftflags |= FLG_SHIFT; 330 if (mod & (KBD_MOD_LALT|KBD_MOD_RALT)) uhid->uhid_shiftflags |= FLG_ALT; 331} 332 333/* ********************************************************************* 334 * usbhid_kbd_scan1(uhid,scan,breakflg) 335 * 336 * Handle a single keyboard event. Using the scan code, look up 337 * the key in the table and convert it to one or more characters 338 * for the keyboard event queue. 339 * 340 * Input parameters: 341 * uhid - the hid softc 342 * scan - scan code from keyboard report 343 * breakflg - true if key is being released, false if pressed 344 * 345 * Return value: 346 * nothing 347 ********************************************************************* */ 348 349static void usbhid_kbd_scan1(usbhid_softc_t *uhid,uint8_t scan,int breakflg) 350{ 351 keycode_t *code = 0; 352 char *str; 353 354 /* 355 * Check scan code for reality. 356 */ 357 358 if (scan >= usbhid_scantablesize) return; 359 code = &usbhid_scantable[scan]; 360 361 /* 362 * If the change is a toggle, handle the toggle. These 363 * keys also deal with the LEDs on the keyboard. 364 */ 365 366 if (code->kc_type & (FLG_CAPS|FLG_SCROLL|FLG_NUM)) { 367 if (!breakflg) uhid->uhid_shiftflags ^= code->kc_type; 368// if (ks->ks_setleds) { 369// (*(ks->ks_setleds))(ks,ks->ks_shiftflags & (FLG_CAPS|FLG_SCROLL|FLG_NUM)); 370// } 371 } 372 373 /* 374 * Regular keys - just look up in table and 375 * queue the characters to the upper layers. 376 */ 377 378 if (code->kc_type & (FLG_ASCII | FLG_FKEY | FLG_NKPD)) { 379 if (uhid->uhid_shiftflags & (FLG_SHIFT|FLG_CAPS)) str = code->kc_shifted; 380 else if (uhid->uhid_shiftflags & FLG_CTRL) str = code->kc_ctrl; 381 else str = code->kc_normal; 382 if (!breakflg) { 383#if CFG_VGACONSOLE 384 while (*str) { 385 pcconsole_enqueue(*str++); 386 } 387#else 388 printf("%s",str); 389#endif 390#ifndef _CFE_ 391 fflush(stdout); 392#endif 393 } 394 } 395 396} 397 398 399/* ********************************************************************* 400 * usbhid_kbd_scan(uhid) 401 * 402 * Main processing routine for keyboard report messages. Once 403 * we've determined that it is a keyboard mesage, we end up 404 * here. The work involves seeing what new keys have arrived 405 * in the list (presses), and which ones are no longer there 406 * (releases). To do this, we us the current and previous 407 * report structure. 408 * 409 * Input parameters: 410 * uhid - the hid softc 411 * 412 * Return value: 413 * nothing 414 ********************************************************************* */ 415 416static void usbhid_kbd_scan(usbhid_softc_t *uhid) 417{ 418 int n,o; 419 420 /* 421 * Modifier keys (shift, alt, control) 422 */ 423 424 if (uhid->uhid_imsg[UBR_KBD_MODS] ^ uhid->uhid_lastmsg[UBR_KBD_MODS]) { 425 usbhid_kbd_mod1(uhid); 426 } 427 428 /* 429 * "Make" codes (keys pressed down) 430 * Look for keys in 'uhid_imsg' that are not in 'uhid_lastmsg' 431 */ 432 433 for (n = UBR_KBD_KEYS; n < (UBR_KBD_KEYS + UBR_KBD_NUMKEYS); n++) { 434 if (uhid->uhid_imsg[n] == 0) break; /* no more keys */ 435 for (o = UBR_KBD_KEYS; o < (UBR_KBD_KEYS + UBR_KBD_NUMKEYS); o++) { 436 if (uhid->uhid_imsg[n] == uhid->uhid_lastmsg[o]) break; 437 } 438 if (o == (UBR_KBD_KEYS + UBR_KBD_NUMKEYS)) { /* key not found, must be pressed */ 439 usbhid_kbd_scan1(uhid,uhid->uhid_imsg[n],0); 440 } 441 } 442 443 /* 444 * "Break" codes (keys released) 445 * Look for keys in 'uhid_lastmsg' that are not in 'uhid_imsg' 446 */ 447 448 449 for (n = UBR_KBD_KEYS; n < (UBR_KBD_KEYS + UBR_KBD_NUMKEYS); n++) { 450 if (uhid->uhid_lastmsg[n] == 0) break; /* no more keys */ 451 for (o = UBR_KBD_KEYS; o < (UBR_KBD_KEYS + UBR_KBD_NUMKEYS); o++) { 452 if (uhid->uhid_lastmsg[n] == uhid->uhid_imsg[o]) break; 453 } 454 if (o == (UBR_KBD_KEYS + UBR_KBD_NUMKEYS)) { /* key not found, must be released */ 455 usbhid_kbd_scan1(uhid,uhid->uhid_lastmsg[n],1); 456 } 457 } 458} 459 460 461/* ********************************************************************* 462 * usbhid_ireq_callback(ur) 463 * 464 * This routine is called when our interrupt transfer completes 465 * and there is report data to be processed. 466 * 467 * Input parameters: 468 * ur - usb request 469 * 470 * Return value: 471 * 0 472 ********************************************************************* */ 473 474static int usbhid_ireq_callback(usbreq_t *ur) 475{ 476 usbhid_softc_t *uhid = (ur->ur_dev->ud_private); 477 478 /* 479 * If the driver is unloaded, the request will be cancelled. 480 */ 481 482 if (ur->ur_status == 0xFF) { 483 usb_free_request(ur); 484 return 0; 485 } 486 487 /* 488 * What we do now depends on the type of device. 489 */ 490 491 switch (uhid->uhid_devtype) { 492 case HID_DEVTYPE_KBD: 493 /* 494 * Handle keyboard event 495 */ 496 usbhid_kbd_scan(uhid); 497 498 /* 499 * Save old event to compare for next time. 500 */ 501 memcpy(uhid->uhid_lastmsg,uhid->uhid_imsg,8); 502 break; 503 504 case HID_DEVTYPE_MOUSE: 505 break; 506 } 507 508 /* 509 * Re-queue request to get next keyboard event. 510 */ 511 512 usb_queue_request(ur); 513 514 return 0; 515} 516 517 518/* ********************************************************************* 519 * usbhid_queue_intreq(dev,softc) 520 * 521 * Queue an interrupt request for this usb device. The 522 * driver will place this request on the queue that corresponds 523 * to the endpoint, and will call the callback routine when 524 * something happens. 525 * 526 * Input parameters: 527 * dev - usb device 528 * softc - the usb hid softc 529 * 530 * Return value: 531 * nothing 532 ********************************************************************* */ 533 534static void usbhid_queue_intreq(usbdev_t *dev,usbhid_softc_t *softc) 535{ 536 usbreq_t *ur; 537 538 ur = usb_make_request(dev, 539 softc->uhid_ipipe, 540 softc->uhid_imsg,softc->uhid_ipipemps, 541 UR_FLAG_IN); 542 543 ur->ur_callback = usbhid_ireq_callback; 544 545 usb_queue_request(ur); 546} 547 548 549/* ********************************************************************* 550 * usbhid_attach(dev,drv) 551 * 552 * This routine is called when the bus scan stuff finds a HID 553 * device. We finish up the initialization by configuring the 554 * device and allocating our softc here. 555 * 556 * Input parameters: 557 * dev - usb device, in the "addressed" state. 558 * drv - the driver table entry that matched 559 * 560 * Return value: 561 * 0 562 ********************************************************************* */ 563 564static int usbhid_attach(usbdev_t *dev,usb_driver_t *drv) 565{ 566 usb_config_descr_t *cfgdscr = dev->ud_cfgdescr; 567 usb_endpoint_descr_t *epdscr; 568 usb_interface_descr_t *ifdscr; 569 usbhid_softc_t *softc; 570 571 dev->ud_drv = drv; 572 573 softc = KMALLOC(sizeof(usbhid_softc_t),0); 574 memset(softc,0,sizeof(usbhid_softc_t)); 575 dev->ud_private = softc; 576 577 epdscr = usb_find_cfg_descr(dev,USB_ENDPOINT_DESCRIPTOR_TYPE,0); 578 ifdscr = usb_find_cfg_descr(dev,USB_INTERFACE_DESCRIPTOR_TYPE,0); 579 580 if (!epdscr || !ifdscr) { 581 /* 582 * Could not get descriptors, something is very wrong. 583 * Leave device addressed but not configured. 584 */ 585 return 0; 586 } 587 588 /* 589 * Choose the standard configuration. 590 */ 591 592 usb_set_configuration(dev,cfgdscr->bConfigurationValue); 593 594 /* 595 * Set the protocol to the "boot" protocol, so we don't 596 * have to deal with fancy HID stuff. 597 */ 598 599 usbhid_set_protocol(dev,HID_BOOT_PROTOCOL,ifdscr->bInterfaceNumber); 600 601 /* 602 * Open the interrupt pipe. 603 */ 604 605 softc->uhid_ipipe = usb_open_pipe(dev,epdscr); 606 softc->uhid_ipipemps = GETUSBFIELD(epdscr,wMaxPacketSize); 607 608 /* 609 * Figure out the device type from the protocol. Keyboards, 610 * mice use this field to distinguish themselves. 611 */ 612 613 softc->uhid_devtype = ifdscr->bInterfaceProtocol; 614 if (softc->uhid_devtype > HID_DEVTYPE_MAX) { 615 softc->uhid_devtype = HID_DEVTYPE_UNKNOWN; 616 } 617 618 console_log("USBHID: %s Configured.\n", 619 usbhid_devtypes[softc->uhid_devtype]); 620 621 /* 622 * Queue a transfer on the interrupt endpoint to catch 623 * our first characters. 624 */ 625 626 usbhid_queue_intreq(dev,softc); 627 628 return 0; 629} 630 631/* ********************************************************************* 632 * usbhid_detach(dev) 633 * 634 * This routine is called when the bus scanner notices that 635 * this device has been removed from the system. We should 636 * do any cleanup that is required. The pending requests 637 * will be cancelled automagically. 638 * 639 * Input parameters: 640 * dev - usb device 641 * 642 * Return value: 643 * 0 644 ********************************************************************* */ 645 646static int usbhid_detach(usbdev_t *dev) 647{ 648 return 0; 649} 650 651 652 653