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_descriptor *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->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_descriptor *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->bInterfaceClass != 3) return 0;
 359        if (iface->bInterfaceSubClass != 1) return 0;
 360        if (iface->bInterfaceProtocol != 1) return 0;
 361        if (iface->bNumEndpoints != 1) return 0;
 362
 363        ep = &iface->ep_desc[0];
 364
 365        if (!(ep->bEndpointAddress & 0x80)) return 0;
 366        if ((ep->bmAttributes & 3) != 3) return 0;
 367        USB_KBD_PRINTF("USB KBD found set protocol...\n");
 368        /* ok, we found a USB Keyboard, install it */
 369        /* usb_kbd_get_hid_desc(dev); */
 370        usb_set_protocol(dev, iface->bInterfaceNumber, 0);
 371        USB_KBD_PRINTF("USB KBD found set idle...\n");
 372        usb_set_idle(dev, iface->bInterfaceNumber, REPEAT_RATE, 0);
 373        memset(&new[0], 0, 8);
 374        memset(&old[0], 0, 8);
 375        repeat_delay=0;
 376        pipe = usb_rcvintpipe(dev, ep->bEndpointAddress);
 377        maxp = usb_maxpacket(dev, pipe);
 378        dev->irq_handle=usb_kbd_irq;
 379        USB_KBD_PRINTF("USB KBD enable interrupt pipe...\n");
 380        usb_submit_int_msg(dev,pipe,&new[0], maxp > 8 ? 8 : maxp,ep->bInterval);
 381        return 1;
 382}
 383
 384
 385#if 0
 386struct usb_hid_descriptor {
 387        unsigned char  bLength;
 388        unsigned char  bDescriptorType; /* 0x21 for HID */
 389        unsigned short bcdHID; /* release number */
 390        unsigned char  bCountryCode;
 391        unsigned char  bNumDescriptors;
 392        unsigned char  bReportDescriptorType;
 393        unsigned short wDescriptorLength;
 394} __attribute__ ((packed));
 395
 396/*
 397 * We parse each description item into this structure. Short items data
 398 * values are expanded to 32-bit signed int, long items contain a pointer
 399 * into the data area.
 400 */
 401
 402struct hid_item {
 403        unsigned char format;
 404        unsigned char size;
 405        unsigned char type;
 406        unsigned char tag;
 407        union {
 408            unsigned char   u8;
 409            char            s8;
 410            unsigned short  u16;
 411            short           s16;
 412            unsigned long   u32;
 413            long            s32;
 414            unsigned char  *longdata;
 415        } data;
 416};
 417
 418/*
 419 * HID report item format
 420 */
 421
 422#define HID_ITEM_FORMAT_SHORT   0
 423#define HID_ITEM_FORMAT_LONG    1
 424
 425/*
 426 * Special tag indicating long items
 427 */
 428
 429#define HID_ITEM_TAG_LONG       15
 430
 431
 432static struct usb_hid_descriptor usb_kbd_hid_desc;
 433
 434void usb_kbd_display_hid(struct usb_hid_descriptor *hid)
 435{
 436        printf("USB_HID_DESC:\n");
 437        printf("  bLenght               0x%x\n",hid->bLength);
 438        printf("  bcdHID                0x%x\n",hid->bcdHID);
 439        printf("  bCountryCode          %d\n",hid->bCountryCode);
 440        printf("  bNumDescriptors       0x%x\n",hid->bNumDescriptors);
 441        printf("  bReportDescriptorType 0x%x\n",hid->bReportDescriptorType);
 442        printf("  wDescriptorLength     0x%x\n",hid->wDescriptorLength);
 443}
 444
 445
 446/*
 447 * Fetch a report description item from the data stream. We support long
 448 * items, though they are not used yet.
 449 */
 450
 451static int fetch_item(unsigned char *start,unsigned char *end, struct hid_item *item)
 452{
 453        if((end - start) > 0) {
 454                unsigned char b = *start++;
 455                item->type = (b >> 2) & 3;
 456                item->tag  = (b >> 4) & 15;
 457                if (item->tag == HID_ITEM_TAG_LONG) {
 458                        item->format = HID_ITEM_FORMAT_LONG;
 459                        if ((end - start) >= 2) {
 460                                item->size = *start++;
 461                                item->tag  = *start++;
 462                                if ((end - start) >= item->size) {
 463                                        item->data.longdata = start;
 464                                        start += item->size;
 465                                        return item->size;
 466                                }
 467                        }
 468                } else {
 469                        item->format = HID_ITEM_FORMAT_SHORT;
 470                        item->size = b & 3;
 471                        switch (item->size) {
 472                                case 0:
 473                                        return item->size;
 474                                case 1:
 475                                        if ((end - start) >= 1) {
 476                                                item->data.u8 = *start++;
 477                                                return item->size;
 478                                        }
 479                                        break;
 480                                case 2:
 481                                        if ((end - start) >= 2) {
 482                                                item->data.u16 = le16_to_cpu((unsigned short *)start);
 483                                                start+=2;
 484                                                return item->size;
 485                                        }
 486                                case 3:
 487                                        item->size++;
 488                                        if ((end - start) >= 4) {
 489                                                item->data.u32 = le32_to_cpu((unsigned long *)start);
 490                                                start+=4;
 491                                                return item->size;
 492                                        }
 493                        }
 494                }
 495        }
 496        return -1;
 497}
 498
 499/*
 500 * HID report descriptor item type (prefix bit 2,3)
 501 */
 502
 503#define HID_ITEM_TYPE_MAIN              0
 504#define HID_ITEM_TYPE_GLOBAL            1
 505#define HID_ITEM_TYPE_LOCAL             2
 506#define HID_ITEM_TYPE_RESERVED          3
 507/*
 508 * HID report descriptor main item tags
 509 */
 510
 511#define HID_MAIN_ITEM_TAG_INPUT                 8
 512#define HID_MAIN_ITEM_TAG_OUTPUT                9
 513#define HID_MAIN_ITEM_TAG_FEATURE               11
 514#define HID_MAIN_ITEM_TAG_BEGIN_COLLECTION      10
 515#define HID_MAIN_ITEM_TAG_END_COLLECTION        12
 516/*
 517 * HID report descriptor main item contents
 518 */
 519
 520#define HID_MAIN_ITEM_CONSTANT          0x001
 521#define HID_MAIN_ITEM_VARIABLE          0x002
 522#define HID_MAIN_ITEM_RELATIVE          0x004
 523#define HID_MAIN_ITEM_WRAP              0x008
 524#define HID_MAIN_ITEM_NONLINEAR         0x010
 525#define HID_MAIN_ITEM_NO_PREFERRED      0x020
 526#define HID_MAIN_ITEM_NULL_STATE        0x040
 527#define HID_MAIN_ITEM_VOLATILE          0x080
 528#define HID_MAIN_ITEM_BUFFERED_BYTE     0x100
 529
 530/*
 531 * HID report descriptor collection item types
 532 */
 533
 534#define HID_COLLECTION_PHYSICAL         0
 535#define HID_COLLECTION_APPLICATION      1
 536#define HID_COLLECTION_LOGICAL          2
 537/*
 538 * HID report descriptor global item tags
 539 */
 540
 541#define HID_GLOBAL_ITEM_TAG_USAGE_PAGE          0
 542#define HID_GLOBAL_ITEM_TAG_LOGICAL_MINIMUM     1
 543#define HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM     2
 544#define HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM    3
 545#define HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM    4
 546#define HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT       5
 547#define HID_GLOBAL_ITEM_TAG_UNIT                6
 548#define HID_GLOBAL_ITEM_TAG_REPORT_SIZE         7
 549#define HID_GLOBAL_ITEM_TAG_REPORT_ID           8
 550#define HID_GLOBAL_ITEM_TAG_REPORT_COUNT        9
 551#define HID_GLOBAL_ITEM_TAG_PUSH                10
 552#define HID_GLOBAL_ITEM_TAG_POP                 11
 553
 554/*
 555 * HID report descriptor local item tags
 556 */
 557
 558#define HID_LOCAL_ITEM_TAG_USAGE                0
 559#define HID_LOCAL_ITEM_TAG_USAGE_MINIMUM        1
 560#define HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM        2
 561#define HID_LOCAL_ITEM_TAG_DESIGNATOR_INDEX     3
 562#define HID_LOCAL_ITEM_TAG_DESIGNATOR_MINIMUM   4
 563#define HID_LOCAL_ITEM_TAG_DESIGNATOR_MAXIMUM   5
 564#define HID_LOCAL_ITEM_TAG_STRING_INDEX         7
 565#define HID_LOCAL_ITEM_TAG_STRING_MINIMUM       8
 566#define HID_LOCAL_ITEM_TAG_STRING_MAXIMUM       9
 567#define HID_LOCAL_ITEM_TAG_DELIMITER            10
 568
 569
 570static void usb_kbd_show_item(struct hid_item *item)
 571{
 572        switch(item->type) {
 573                case HID_ITEM_TYPE_MAIN:
 574                        switch(item->tag) {
 575                                case HID_MAIN_ITEM_TAG_INPUT:
 576                                        printf("Main Input");
 577                                        break;
 578                                case HID_MAIN_ITEM_TAG_OUTPUT:
 579                                        printf("Main Output");
 580                                        break;
 581                                case HID_MAIN_ITEM_TAG_FEATURE:
 582                                        printf("Main Feature");
 583                                        break;
 584                                case HID_MAIN_ITEM_TAG_BEGIN_COLLECTION:
 585                                        printf("Main Begin Collection");
 586                                        break;
 587                                case HID_MAIN_ITEM_TAG_END_COLLECTION:
 588                                        printf("Main End Collection");
 589                                        break;
 590                                default:
 591                                        printf("Main reserved %d",item->tag);
 592                                        break;
 593                        }
 594                        break;
 595                case HID_ITEM_TYPE_GLOBAL:
 596                        switch(item->tag) {
 597                                case HID_GLOBAL_ITEM_TAG_USAGE_PAGE:
 598                                        printf("- Global Usage Page");
 599                                        break;
 600                                case HID_GLOBAL_ITEM_TAG_LOGICAL_MINIMUM:
 601                                        printf("- Global Logical Minimum");
 602                                        break;
 603                                case HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM:
 604                                        printf("- Global Logical Maximum");
 605                                        break;
 606                                case HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM:
 607                                        printf("- Global physical Minimum");
 608                                        break;
 609                                case HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM:
 610                                        printf("- Global physical Maximum");
 611                                        break;
 612                                case HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT:
 613                                        printf("- Global Unit Exponent");
 614                                        break;
 615                                case HID_GLOBAL_ITEM_TAG_UNIT:
 616                                        printf("- Global Unit");
 617                                        break;
 618                                case HID_GLOBAL_ITEM_TAG_REPORT_SIZE:
 619                                        printf("- Global Report Size");
 620                                        break;
 621                                case HID_GLOBAL_ITEM_TAG_REPORT_ID:
 622                                        printf("- Global Report ID");
 623                                        break;
 624                                case HID_GLOBAL_ITEM_TAG_REPORT_COUNT:
 625                                        printf("- Global Report Count");
 626                                        break;
 627                                case HID_GLOBAL_ITEM_TAG_PUSH:
 628                                        printf("- Global Push");
 629                                        break;
 630                                case HID_GLOBAL_ITEM_TAG_POP:
 631                                        printf("- Global Pop");
 632                                        break;
 633                                default:
 634                                        printf("- Global reserved %d",item->tag);
 635                                        break;
 636                        }
 637                        break;
 638                case HID_ITEM_TYPE_LOCAL:
 639                        switch(item->tag) {
 640                                case HID_LOCAL_ITEM_TAG_USAGE:
 641                                        printf("-- Local Usage");
 642                                        break;
 643                                case HID_LOCAL_ITEM_TAG_USAGE_MINIMUM:
 644                                        printf("-- Local Usage Minimum");
 645                                        break;
 646                                case HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM:
 647                                        printf("-- Local Usage Maximum");
 648                                        break;
 649                                case HID_LOCAL_ITEM_TAG_DESIGNATOR_INDEX:
 650                                        printf("-- Local Designator Index");
 651                                        break;
 652                                case HID_LOCAL_ITEM_TAG_DESIGNATOR_MINIMUM:
 653                                        printf("-- Local Designator Minimum");
 654                                        break;
 655                                case HID_LOCAL_ITEM_TAG_DESIGNATOR_MAXIMUM:
 656                                        printf("-- Local Designator Maximum");
 657                                        break;
 658                                case HID_LOCAL_ITEM_TAG_STRING_INDEX:
 659                                        printf("-- Local String Index");
 660                                        break;
 661                                case HID_LOCAL_ITEM_TAG_STRING_MINIMUM:
 662                                        printf("-- Local String Minimum");
 663                                        break;
 664                                case HID_LOCAL_ITEM_TAG_STRING_MAXIMUM:
 665                                        printf("-- Local String Maximum");
 666                                        break;
 667                                case HID_LOCAL_ITEM_TAG_DELIMITER:
 668                                        printf("-- Local Delimiter");
 669                                        break;
 670                                default:
 671                                        printf("-- Local reserved %d",item->tag);
 672                                        break;
 673                        }
 674                        break;
 675                default:
 676                        printf("--- reserved %d",item->type);
 677                        break;
 678        }
 679        switch(item->size) {
 680                case 1:
 681                        printf("  %d",item->data.u8);
 682                        break;
 683                case 2:
 684                        printf("  %d",item->data.u16);
 685                        break;
 686                case 4:
 687                        printf("  %ld",item->data.u32);
 688                        break;
 689        }
 690        printf("\n");
 691}
 692
 693
 694static int usb_kbd_get_hid_desc(struct usb_device *dev)
 695{
 696        unsigned char buffer[256];
 697        struct usb_descriptor_header *head;
 698        struct usb_config_descriptor *config;
 699        int index,len,i;
 700        unsigned char *start, *end;
 701        struct hid_item item;
 702
 703        if(usb_get_configuration_no(dev,&buffer[0],0)==-1)
 704                return -1;
 705        head =(struct usb_descriptor_header *)&buffer[0];
 706        if(head->bDescriptorType!=USB_DT_CONFIG) {
 707                printf(" ERROR: NOT USB_CONFIG_DESC %x\n",head->bDescriptorType);
 708                return -1;
 709        }
 710        index=head->bLength;
 711        config=(struct usb_config_descriptor *)&buffer[0];
 712        len=le16_to_cpu(config->wTotalLength);
 713        /* Ok the first entry must be a configuration entry, now process the others */
 714        head=(struct usb_descriptor_header *)&buffer[index];
 715        while(index+1 < len) {
 716                if(head->bDescriptorType==USB_DT_HID) {
 717                        printf("HID desc found\n");
 718                        memcpy(&usb_kbd_hid_desc,&buffer[index],buffer[index]);
 719                        le16_to_cpus(&usb_kbd_hid_desc.bcdHID);
 720                        le16_to_cpus(&usb_kbd_hid_desc.wDescriptorLength);
 721                        usb_kbd_display_hid(&usb_kbd_hid_desc);
 722                        len=0;
 723                        break;
 724                }
 725                index+=head->bLength;
 726                head=(struct usb_descriptor_header *)&buffer[index];
 727        }
 728        if(len>0)
 729                return -1;
 730        len=usb_kbd_hid_desc.wDescriptorLength;
 731        if((index = usb_get_class_descriptor(dev, 0, USB_DT_REPORT, 0, &buffer[0], len)) < 0) {
 732                printf("reading report descriptor failed\n");
 733                return -1;
 734        }
 735        printf(" report descriptor (size %u, read %d)\n", len, index);
 736        start = &buffer[0];
 737        end = &buffer[len];
 738        i=0;
 739        do {
 740                index=fetch_item(start,end,&item);
 741                i+=index;
 742                i++;
 743                if(index>=0)
 744                        usb_kbd_show_item(&item);
 745
 746                start+=index;
 747                start++;
 748        } while(index>=0);
 749
 750}
 751
 752#endif
 753