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