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