1 /* 2 * (C) Copyright 2001 3 * Denis Peter, MPL AG Switzerland 4 * 5 * Part of this source has been derived from the Linux USB 6 * project. 7 * 8 * See file CREDITS for list of people who contributed to this 9 * project. 10 * 11 * This program is free software; you can redistribute it and/or 12 * modify it under the terms of the GNU General Public License as 13 * published by the Free Software Foundation; either version 2 of 14 * the License, or (at your option) any later version. 15 * 16 * This program is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this program; if not, write to the Free Software 23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 24 * MA 02111-1307 USA 25 * 26 */ 27 #include <common.h> 28 #include <devices.h> 29 30 #ifdef CONFIG_USB_KEYBOARD 31 32 #include <usb.h> 33 34 #undef USB_KBD_DEBUG 35 /* 36 * if overwrite_console returns 1, the stdin, stderr and stdout 37 * are switched to the serial port, else the settings in the 38 * environment are used 39 */ 40 #ifdef CFG_CONSOLE_OVERWRITE_ROUTINE 41 extern int overwrite_console (void); 42 #else 43 int overwrite_console (void) 44 { 45 return (0); 46 } 47 #endif 48 49 #ifdef USB_KBD_DEBUG 50 #define USB_KBD_PRINTF(fmt,args...) printf (fmt ,##args) 51 #else 52 #define USB_KBD_PRINTF(fmt,args...) 53 #endif 54 55 56 #define REPEAT_RATE 40/4 /* 40msec -> 25cps */ 57 #define REPEAT_DELAY 10 /* 10 x REAPEAT_RATE = 400msec */ 58 59 #define NUM_LOCK 0x53 60 #define CAPS_LOCK 0x39 61 #define SCROLL_LOCK 0x47 62 63 64 /* Modifier bits */ 65 #define LEFT_CNTR 0 66 #define LEFT_SHIFT 1 67 #define LEFT_ALT 2 68 #define LEFT_GUI 3 69 #define RIGHT_CNTR 4 70 #define RIGHT_SHIFT 5 71 #define RIGHT_ALT 6 72 #define RIGHT_GUI 7 73 74 #define USB_KBD_BUFFER_LEN 0x20 /* size of the keyboardbuffer */ 75 76 static volatile char usb_kbd_buffer[USB_KBD_BUFFER_LEN]; 77 static volatile int usb_in_pointer = 0; 78 static volatile int usb_out_pointer = 0; 79 80 unsigned char new[8]; 81 unsigned char old[8]; 82 int repeat_delay; 83 #define DEVNAME "usbkbd" 84 static unsigned char num_lock = 0; 85 static unsigned char caps_lock = 0; 86 static unsigned char scroll_lock = 0; 87 static unsigned char ctrl = 0; 88 89 static unsigned char leds __attribute__ ((aligned (0x4))); 90 91 static unsigned char usb_kbd_numkey[] = { 92 '1', '2', '3', '4', '5', '6', '7', '8', '9', '0','\r',0x1b,'\b','\t',' ', '-', 93 '=', '[', ']','\\', '#', ';', '\'', '`', ',', '.', '/' 94 }; 95 static unsigned char usb_kbd_numkey_shifted[] = { 96 '!', '@', '#', '$', '%', '^', '&', '*', '(', ')','\r',0x1b,'\b','\t',' ', '_', 97 '+', '{', '}', '|', '~', ':', '"', '~', '<', '>', '?' 98 }; 99 100 /****************************************************************** 101 * Queue handling 102 ******************************************************************/ 103 /* puts character in the queue and sets up the in and out pointer */ 104 static void usb_kbd_put_queue(char data) 105 { 106 if((usb_in_pointer+1)==USB_KBD_BUFFER_LEN) { 107 if(usb_out_pointer==0) { 108 return; /* buffer full */ 109 } else{ 110 usb_in_pointer=0; 111 } 112 } else { 113 if((usb_in_pointer+1)==usb_out_pointer) 114 return; /* buffer full */ 115 usb_in_pointer++; 116 } 117 usb_kbd_buffer[usb_in_pointer]=data; 118 return; 119 } 120 121 /* test if a character is in the queue */ 122 static int usb_kbd_testc(void) 123 { 124 #ifdef CFG_USB_EVENT_POLL 125 usb_event_poll(); 126 #endif 127 if(usb_in_pointer==usb_out_pointer) 128 return(0); /* no data */ 129 else 130 return(1); 131 } 132 /* gets the character from the queue */ 133 static int usb_kbd_getc(void) 134 { 135 char c; 136 while(usb_in_pointer==usb_out_pointer) { 137 #ifdef CFG_USB_EVENT_POLL 138 usb_event_poll(); 139 #endif 140 } 141 if((usb_out_pointer+1)==USB_KBD_BUFFER_LEN) 142 usb_out_pointer=0; 143 else 144 usb_out_pointer++; 145 c=usb_kbd_buffer[usb_out_pointer]; 146 return (int)c; 147 148 } 149 150 /* forward decleration */ 151 static int usb_kbd_probe(struct usb_device *dev, unsigned int ifnum); 152 153 /* search for keyboard and register it if found */ 154 int drv_usb_kbd_init(void) 155 { 156 int error,i,index; 157 device_t usb_kbd_dev,*old_dev; 158 struct usb_device *dev; 159 char *stdinname = getenv ("stdin"); 160 161 usb_in_pointer=0; 162 usb_out_pointer=0; 163 /* scan all USB Devices */ 164 for(i=0;i<USB_MAX_DEVICE;i++) { 165 dev=usb_get_dev_index(i); /* get device */ 166 if(dev->devnum!=-1) { 167 if(usb_kbd_probe(dev,0)==1) { /* Ok, we found a keyboard */ 168 /* check, if it is already registered */ 169 USB_KBD_PRINTF("USB KBD found set up device.\n"); 170 for (index=1; index<=ListNumItems(devlist); index++) { 171 old_dev = ListGetPtrToItem(devlist, index); 172 if(strcmp(old_dev->name,DEVNAME)==0) { 173 /* ok, already registered, just return ok */ 174 USB_KBD_PRINTF("USB KBD is already registered.\n"); 175 return 1; 176 } 177 } 178 /* register the keyboard */ 179 USB_KBD_PRINTF("USB KBD register.\n"); 180 memset (&usb_kbd_dev, 0, sizeof(device_t)); 181 strcpy(usb_kbd_dev.name, DEVNAME); 182 usb_kbd_dev.flags = DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM; 183 usb_kbd_dev.putc = NULL; 184 usb_kbd_dev.puts = NULL; 185 usb_kbd_dev.getc = usb_kbd_getc; 186 usb_kbd_dev.tstc = usb_kbd_testc; 187 error = device_register (&usb_kbd_dev); 188 if(error==0) { 189 /* check if this is the standard input device */ 190 if(strcmp(stdinname,DEVNAME)==0) { 191 /* reassign the console */ 192 if(overwrite_console()) { 193 return 1; 194 } 195 error=console_assign(stdin,DEVNAME); 196 if(error==0) 197 return 1; 198 else 199 return error; 200 } 201 return 1; 202 } 203 return error; 204 } 205 } 206 } 207 /* no USB Keyboard found */ 208 return -1; 209 } 210 211 212 /* deregistering the keyboard */ 213 int usb_kbd_deregister(void) 214 { 215 return device_deregister(DEVNAME); 216 } 217 218 /************************************************************************** 219 * Low Level drivers 220 */ 221 222 /* set the LEDs. Since this is used in the irq routine, the control job 223 is issued with a timeout of 0. This means, that the job is queued without 224 waiting for job completion */ 225 226 static void usb_kbd_setled(struct usb_device *dev) 227 { 228 struct usb_interface_descriptor *iface; 229 iface = &dev->config.if_desc[0]; 230 leds=0; 231 if(scroll_lock!=0) 232 leds|=1; 233 leds<<=1; 234 if(caps_lock!=0) 235 leds|=1; 236 leds<<=1; 237 if(num_lock!=0) 238 leds|=1; 239 usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 240 USB_REQ_SET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE, 241 0x200, iface->bInterfaceNumber,(void *)&leds, 1, 0); 242 243 } 244 245 246 #define CAPITAL_MASK 0x20 247 /* Translate the scancode in ASCII */ 248 static int usb_kbd_translate(unsigned char scancode,unsigned char modifier,int pressed) 249 { 250 unsigned char keycode; 251 252 if(pressed==0) { 253 /* key released */ 254 repeat_delay=0; 255 return 0; 256 } 257 if(pressed==2) { 258 repeat_delay++; 259 if(repeat_delay<REPEAT_DELAY) 260 return 0; 261 repeat_delay=REPEAT_DELAY; 262 } 263 keycode=0; 264 if((scancode>3) && (scancode<=0x1d)) { /* alpha numeric values */ 265 keycode=scancode-4 + 0x61; 266 if(caps_lock) 267 keycode&=~CAPITAL_MASK; /* switch to capital Letters */ 268 if(((modifier&(1<<LEFT_SHIFT))!=0)||((modifier&(1<<RIGHT_SHIFT))!=0)) { 269 if(keycode & CAPITAL_MASK) 270 keycode&=~CAPITAL_MASK; /* switch to capital Letters */ 271 else 272 keycode|=CAPITAL_MASK; /* switch to non capital Letters */ 273 } 274 } 275 if((scancode>0x1d) && (scancode<0x3A)) { 276 if(((modifier&(1<<LEFT_SHIFT))!=0)||((modifier&(1<<RIGHT_SHIFT))!=0)) /* shifted */ 277 keycode=usb_kbd_numkey_shifted[scancode-0x1e]; 278 else /* non shifted */ 279 keycode=usb_kbd_numkey[scancode-0x1e]; 280 } 281 282 if (ctrl) 283 keycode = scancode - 0x3; 284 285 if(pressed==1) { 286 if(scancode==NUM_LOCK) { 287 num_lock=~num_lock; 288 return 1; 289 } 290 if(scancode==CAPS_LOCK) { 291 caps_lock=~caps_lock; 292 return 1; 293 } 294 if(scancode==SCROLL_LOCK) { 295 scroll_lock=~scroll_lock; 296 return 1; 297 } 298 } 299 if(keycode!=0) { 300 USB_KBD_PRINTF("%c",keycode); 301 usb_kbd_put_queue(keycode); 302 } 303 return 0; 304 } 305 306 /* Interrupt service routine */ 307 static int usb_kbd_irq(struct usb_device *dev) 308 { 309 int i,res; 310 311 if((dev->irq_status!=0)||(dev->irq_act_len!=8)) 312 { 313 USB_KBD_PRINTF("usb_keyboard Error %lX, len %d\n",dev->irq_status,dev->irq_act_len); 314 return 1; 315 } 316 res=0; 317 318 switch (new[0]) { 319 case 0x0: /* No combo key pressed */ 320 ctrl = 0; 321 break; 322 case 0x01: /* Left Ctrl pressed */ 323 case 0x10: /* Right Ctrl pressed */ 324 ctrl = 1; 325 break; 326 } 327 328 for (i = 2; i < 8; i++) { 329 if (old[i] > 3 && memscan(&new[2], old[i], 6) == &new[8]) { 330 res|=usb_kbd_translate(old[i],new[0],0); 331 } 332 if (new[i] > 3 && memscan(&old[2], new[i], 6) == &old[8]) { 333 res|=usb_kbd_translate(new[i],new[0],1); 334 } 335 } 336 if((new[2]>3) && (old[2]==new[2])) /* still pressed */ 337 res|=usb_kbd_translate(new[2],new[0],2); 338 if(res==1) 339 usb_kbd_setled(dev); 340 memcpy(&old[0],&new[0], 8); 341 return 1; /* install IRQ Handler again */ 342 } 343 344 /* probes the USB device dev for keyboard type */ 345 static int usb_kbd_probe(struct usb_device *dev, unsigned int ifnum) 346 { 347 struct usb_interface_descriptor *iface; 348 struct usb_endpoint_descriptor *ep; 349 int pipe,maxp; 350 351 if (dev->descriptor.bNumConfigurations != 1) return 0; 352 iface = &dev->config.if_desc[ifnum]; 353 354 if (iface->bInterfaceClass != 3) return 0; 355 if (iface->bInterfaceSubClass != 1) return 0; 356 if (iface->bInterfaceProtocol != 1) return 0; 357 if (iface->bNumEndpoints != 1) return 0; 358 359 ep = &iface->ep_desc[0]; 360 361 if (!(ep->bEndpointAddress & 0x80)) return 0; 362 if ((ep->bmAttributes & 3) != 3) return 0; 363 USB_KBD_PRINTF("USB KBD found set protocol...\n"); 364 /* ok, we found a USB Keyboard, install it */ 365 /* usb_kbd_get_hid_desc(dev); */ 366 usb_set_protocol(dev, iface->bInterfaceNumber, 0); 367 USB_KBD_PRINTF("USB KBD found set idle...\n"); 368 usb_set_idle(dev, iface->bInterfaceNumber, REPEAT_RATE, 0); 369 memset(&new[0], 0, 8); 370 memset(&old[0], 0, 8); 371 repeat_delay=0; 372 pipe = usb_rcvintpipe(dev, ep->bEndpointAddress); 373 maxp = usb_maxpacket(dev, pipe); 374 dev->irq_handle=usb_kbd_irq; 375 USB_KBD_PRINTF("USB KBD enable interrupt pipe...\n"); 376 usb_submit_int_msg(dev,pipe,&new[0], maxp > 8 ? 8 : maxp,ep->bInterval); 377 return 1; 378 } 379 380 381 #if 0 382 struct usb_hid_descriptor { 383 unsigned char bLength; 384 unsigned char bDescriptorType; /* 0x21 for HID */ 385 unsigned short bcdHID; /* release number */ 386 unsigned char bCountryCode; 387 unsigned char bNumDescriptors; 388 unsigned char bReportDescriptorType; 389 unsigned short wDescriptorLength; 390 } __attribute__ ((packed)); 391 392 /* 393 * We parse each description item into this structure. Short items data 394 * values are expanded to 32-bit signed int, long items contain a pointer 395 * into the data area. 396 */ 397 398 struct hid_item { 399 unsigned char format; 400 unsigned char size; 401 unsigned char type; 402 unsigned char tag; 403 union { 404 unsigned char u8; 405 char s8; 406 unsigned short u16; 407 short s16; 408 unsigned long u32; 409 long s32; 410 unsigned char *longdata; 411 } data; 412 }; 413 414 /* 415 * HID report item format 416 */ 417 418 #define HID_ITEM_FORMAT_SHORT 0 419 #define HID_ITEM_FORMAT_LONG 1 420 421 /* 422 * Special tag indicating long items 423 */ 424 425 #define HID_ITEM_TAG_LONG 15 426 427 428 static struct usb_hid_descriptor usb_kbd_hid_desc; 429 430 void usb_kbd_display_hid(struct usb_hid_descriptor *hid) 431 { 432 printf("USB_HID_DESC:\n"); 433 printf(" bLenght 0x%x\n",hid->bLength); 434 printf(" bcdHID 0x%x\n",hid->bcdHID); 435 printf(" bCountryCode %d\n",hid->bCountryCode); 436 printf(" bNumDescriptors 0x%x\n",hid->bNumDescriptors); 437 printf(" bReportDescriptorType 0x%x\n",hid->bReportDescriptorType); 438 printf(" wDescriptorLength 0x%x\n",hid->wDescriptorLength); 439 } 440 441 442 /* 443 * Fetch a report description item from the data stream. We support long 444 * items, though they are not used yet. 445 */ 446 447 static int fetch_item(unsigned char *start,unsigned char *end, struct hid_item *item) 448 { 449 if((end - start) > 0) { 450 unsigned char b = *start++; 451 item->type = (b >> 2) & 3; 452 item->tag = (b >> 4) & 15; 453 if (item->tag == HID_ITEM_TAG_LONG) { 454 item->format = HID_ITEM_FORMAT_LONG; 455 if ((end - start) >= 2) { 456 item->size = *start++; 457 item->tag = *start++; 458 if ((end - start) >= item->size) { 459 item->data.longdata = start; 460 start += item->size; 461 return item->size; 462 } 463 } 464 } else { 465 item->format = HID_ITEM_FORMAT_SHORT; 466 item->size = b & 3; 467 switch (item->size) { 468 case 0: 469 return item->size; 470 case 1: 471 if ((end - start) >= 1) { 472 item->data.u8 = *start++; 473 return item->size; 474 } 475 break; 476 case 2: 477 if ((end - start) >= 2) { 478 item->data.u16 = swap_16((unsigned short *)start); 479 start+=2; 480 return item->size; 481 } 482 case 3: 483 item->size++; 484 if ((end - start) >= 4) { 485 item->data.u32 = swap_32((unsigned long *)start); 486 start+=4; 487 return item->size; 488 } 489 } 490 } 491 } 492 return -1; 493 } 494 495 /* 496 * HID report descriptor item type (prefix bit 2,3) 497 */ 498 499 #define HID_ITEM_TYPE_MAIN 0 500 #define HID_ITEM_TYPE_GLOBAL 1 501 #define HID_ITEM_TYPE_LOCAL 2 502 #define HID_ITEM_TYPE_RESERVED 3 503 /* 504 * HID report descriptor main item tags 505 */ 506 507 #define HID_MAIN_ITEM_TAG_INPUT 8 508 #define HID_MAIN_ITEM_TAG_OUTPUT 9 509 #define HID_MAIN_ITEM_TAG_FEATURE 11 510 #define HID_MAIN_ITEM_TAG_BEGIN_COLLECTION 10 511 #define HID_MAIN_ITEM_TAG_END_COLLECTION 12 512 /* 513 * HID report descriptor main item contents 514 */ 515 516 #define HID_MAIN_ITEM_CONSTANT 0x001 517 #define HID_MAIN_ITEM_VARIABLE 0x002 518 #define HID_MAIN_ITEM_RELATIVE 0x004 519 #define HID_MAIN_ITEM_WRAP 0x008 520 #define HID_MAIN_ITEM_NONLINEAR 0x010 521 #define HID_MAIN_ITEM_NO_PREFERRED 0x020 522 #define HID_MAIN_ITEM_NULL_STATE 0x040 523 #define HID_MAIN_ITEM_VOLATILE 0x080 524 #define HID_MAIN_ITEM_BUFFERED_BYTE 0x100 525 526 /* 527 * HID report descriptor collection item types 528 */ 529 530 #define HID_COLLECTION_PHYSICAL 0 531 #define HID_COLLECTION_APPLICATION 1 532 #define HID_COLLECTION_LOGICAL 2 533 /* 534 * HID report descriptor global item tags 535 */ 536 537 #define HID_GLOBAL_ITEM_TAG_USAGE_PAGE 0 538 #define HID_GLOBAL_ITEM_TAG_LOGICAL_MINIMUM 1 539 #define HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM 2 540 #define HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM 3 541 #define HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM 4 542 #define HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT 5 543 #define HID_GLOBAL_ITEM_TAG_UNIT 6 544 #define HID_GLOBAL_ITEM_TAG_REPORT_SIZE 7 545 #define HID_GLOBAL_ITEM_TAG_REPORT_ID 8 546 #define HID_GLOBAL_ITEM_TAG_REPORT_COUNT 9 547 #define HID_GLOBAL_ITEM_TAG_PUSH 10 548 #define HID_GLOBAL_ITEM_TAG_POP 11 549 550 /* 551 * HID report descriptor local item tags 552 */ 553 554 #define HID_LOCAL_ITEM_TAG_USAGE 0 555 #define HID_LOCAL_ITEM_TAG_USAGE_MINIMUM 1 556 #define HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM 2 557 #define HID_LOCAL_ITEM_TAG_DESIGNATOR_INDEX 3 558 #define HID_LOCAL_ITEM_TAG_DESIGNATOR_MINIMUM 4 559 #define HID_LOCAL_ITEM_TAG_DESIGNATOR_MAXIMUM 5 560 #define HID_LOCAL_ITEM_TAG_STRING_INDEX 7 561 #define HID_LOCAL_ITEM_TAG_STRING_MINIMUM 8 562 #define HID_LOCAL_ITEM_TAG_STRING_MAXIMUM 9 563 #define HID_LOCAL_ITEM_TAG_DELIMITER 10 564 565 566 static void usb_kbd_show_item(struct hid_item *item) 567 { 568 switch(item->type) { 569 case HID_ITEM_TYPE_MAIN: 570 switch(item->tag) { 571 case HID_MAIN_ITEM_TAG_INPUT: 572 printf("Main Input"); 573 break; 574 case HID_MAIN_ITEM_TAG_OUTPUT: 575 printf("Main Output"); 576 break; 577 case HID_MAIN_ITEM_TAG_FEATURE: 578 printf("Main Feature"); 579 break; 580 case HID_MAIN_ITEM_TAG_BEGIN_COLLECTION: 581 printf("Main Begin Collection"); 582 break; 583 case HID_MAIN_ITEM_TAG_END_COLLECTION: 584 printf("Main End Collection"); 585 break; 586 default: 587 printf("Main reserved %d",item->tag); 588 break; 589 } 590 break; 591 case HID_ITEM_TYPE_GLOBAL: 592 switch(item->tag) { 593 case HID_GLOBAL_ITEM_TAG_USAGE_PAGE: 594 printf("- Global Usage Page"); 595 break; 596 case HID_GLOBAL_ITEM_TAG_LOGICAL_MINIMUM: 597 printf("- Global Logical Minimum"); 598 break; 599 case HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM: 600 printf("- Global Logical Maximum"); 601 break; 602 case HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM: 603 printf("- Global physical Minimum"); 604 break; 605 case HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM: 606 printf("- Global physical Maximum"); 607 break; 608 case HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT: 609 printf("- Global Unit Exponent"); 610 break; 611 case HID_GLOBAL_ITEM_TAG_UNIT: 612 printf("- Global Unit"); 613 break; 614 case HID_GLOBAL_ITEM_TAG_REPORT_SIZE: 615 printf("- Global Report Size"); 616 break; 617 case HID_GLOBAL_ITEM_TAG_REPORT_ID: 618 printf("- Global Report ID"); 619 break; 620 case HID_GLOBAL_ITEM_TAG_REPORT_COUNT: 621 printf("- Global Report Count"); 622 break; 623 case HID_GLOBAL_ITEM_TAG_PUSH: 624 printf("- Global Push"); 625 break; 626 case HID_GLOBAL_ITEM_TAG_POP: 627 printf("- Global Pop"); 628 break; 629 default: 630 printf("- Global reserved %d",item->tag); 631 break; 632 } 633 break; 634 case HID_ITEM_TYPE_LOCAL: 635 switch(item->tag) { 636 case HID_LOCAL_ITEM_TAG_USAGE: 637 printf("-- Local Usage"); 638 break; 639 case HID_LOCAL_ITEM_TAG_USAGE_MINIMUM: 640 printf("-- Local Usage Minimum"); 641 break; 642 case HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM: 643 printf("-- Local Usage Maximum"); 644 break; 645 case HID_LOCAL_ITEM_TAG_DESIGNATOR_INDEX: 646 printf("-- Local Designator Index"); 647 break; 648 case HID_LOCAL_ITEM_TAG_DESIGNATOR_MINIMUM: 649 printf("-- Local Designator Minimum"); 650 break; 651 case HID_LOCAL_ITEM_TAG_DESIGNATOR_MAXIMUM: 652 printf("-- Local Designator Maximum"); 653 break; 654 case HID_LOCAL_ITEM_TAG_STRING_INDEX: 655 printf("-- Local String Index"); 656 break; 657 case HID_LOCAL_ITEM_TAG_STRING_MINIMUM: 658 printf("-- Local String Minimum"); 659 break; 660 case HID_LOCAL_ITEM_TAG_STRING_MAXIMUM: 661 printf("-- Local String Maximum"); 662 break; 663 case HID_LOCAL_ITEM_TAG_DELIMITER: 664 printf("-- Local Delimiter"); 665 break; 666 default: 667 printf("-- Local reserved %d",item->tag); 668 break; 669 } 670 break; 671 default: 672 printf("--- reserved %d",item->type); 673 break; 674 } 675 switch(item->size) { 676 case 1: 677 printf(" %d",item->data.u8); 678 break; 679 case 2: 680 printf(" %d",item->data.u16); 681 break; 682 case 4: 683 printf(" %ld",item->data.u32); 684 break; 685 } 686 printf("\n"); 687 } 688 689 690 static int usb_kbd_get_hid_desc(struct usb_device *dev) 691 { 692 unsigned char buffer[256]; 693 struct usb_descriptor_header *head; 694 struct usb_config_descriptor *config; 695 int index,len,i; 696 unsigned char *start, *end; 697 struct hid_item item; 698 699 if(usb_get_configuration_no(dev,&buffer[0],0)==-1) 700 return -1; 701 head =(struct usb_descriptor_header *)&buffer[0]; 702 if(head->bDescriptorType!=USB_DT_CONFIG) { 703 printf(" ERROR: NOT USB_CONFIG_DESC %x\n",head->bDescriptorType); 704 return -1; 705 } 706 index=head->bLength; 707 config=(struct usb_config_descriptor *)&buffer[0]; 708 len=swap_16(config->wTotalLength); 709 /* Ok the first entry must be a configuration entry, now process the others */ 710 head=(struct usb_descriptor_header *)&buffer[index]; 711 while(index+1 < len) { 712 if(head->bDescriptorType==USB_DT_HID) { 713 printf("HID desc found\n"); 714 memcpy(&usb_kbd_hid_desc,&buffer[index],buffer[index]); 715 usb_kbd_hid_desc.bcdHID=swap_16(usb_kbd_hid_desc.bcdHID); 716 usb_kbd_hid_desc.wDescriptorLength=swap_16(usb_kbd_hid_desc.wDescriptorLength); 717 usb_kbd_display_hid(&usb_kbd_hid_desc); 718 len=0; 719 break; 720 } 721 index+=head->bLength; 722 head=(struct usb_descriptor_header *)&buffer[index]; 723 } 724 if(len>0) 725 return -1; 726 len=usb_kbd_hid_desc.wDescriptorLength; 727 if((index = usb_get_class_descriptor(dev, 0, USB_DT_REPORT, 0, &buffer[0], len)) < 0) { 728 printf("reading report descriptor failed\n"); 729 return -1; 730 } 731 printf(" report descriptor (size %u, read %d)\n", len, index); 732 start=&buffer[0]; 733 end=&buffer[len]; 734 i=0; 735 do { 736 index=fetch_item(start,end,&item); 737 i+=index; 738 i++; 739 if(index>=0) 740 usb_kbd_show_item(&item); 741 742 start+=index; 743 start++; 744 } while(index>=0); 745 746 } 747 748 749 #endif 750 751 #endif /* CONFIG_USB_KEYBOARD */ 752