📄 usb_kbd.c
字号:
unsigned short wDescriptorLength;} __attribute__ ((packed));/* * We parse each description item into this structure. Short items data * values are expanded to 32-bit signed int, long items contain a pointer * into the data area. */struct hid_item { unsigned char format; unsigned char size; unsigned char type; unsigned char tag; union { unsigned char u8; char s8; unsigned short u16; short s16; unsigned long u32; long s32; unsigned char *longdata; } data;};/* * HID report item format */#define HID_ITEM_FORMAT_SHORT 0#define HID_ITEM_FORMAT_LONG 1/* * Special tag indicating long items */#define HID_ITEM_TAG_LONG 15static struct usb_hid_descriptor usb_kbd_hid_desc;void usb_kbd_display_hid(struct usb_hid_descriptor *hid){ printf("USB_HID_DESC:\n"); printf(" bLenght 0x%x\n",hid->bLength); printf(" bcdHID 0x%x\n",hid->bcdHID); printf(" bCountryCode %d\n",hid->bCountryCode); printf(" bNumDescriptors 0x%x\n",hid->bNumDescriptors); printf(" bReportDescriptorType 0x%x\n",hid->bReportDescriptorType); printf(" wDescriptorLength 0x%x\n",hid->wDescriptorLength);}/* * Fetch a report description item from the data stream. We support long * items, though they are not used yet. */static int fetch_item(unsigned char *start,unsigned char *end, struct hid_item *item){ if((end - start) > 0) { unsigned char b = *start++; item->type = (b >> 2) & 3; item->tag = (b >> 4) & 15; if (item->tag == HID_ITEM_TAG_LONG) { item->format = HID_ITEM_FORMAT_LONG; if ((end - start) >= 2) { item->size = *start++; item->tag = *start++; if ((end - start) >= item->size) { item->data.longdata = start; start += item->size; return item->size; } } } else { item->format = HID_ITEM_FORMAT_SHORT; item->size = b & 3; switch (item->size) { case 0: return item->size; case 1: if ((end - start) >= 1) { item->data.u8 = *start++; return item->size; } break; case 2: if ((end - start) >= 2) { item->data.u16 = swap_16((unsigned short *)start); start+=2; return item->size; } case 3: item->size++; if ((end - start) >= 4) { item->data.u32 = swap_32((unsigned long *)start); start+=4; return item->size; } } } } return -1;}/* * HID report descriptor item type (prefix bit 2,3) */#define HID_ITEM_TYPE_MAIN 0#define HID_ITEM_TYPE_GLOBAL 1#define HID_ITEM_TYPE_LOCAL 2#define HID_ITEM_TYPE_RESERVED 3/* * HID report descriptor main item tags */#define HID_MAIN_ITEM_TAG_INPUT 8#define HID_MAIN_ITEM_TAG_OUTPUT 9#define HID_MAIN_ITEM_TAG_FEATURE 11#define HID_MAIN_ITEM_TAG_BEGIN_COLLECTION 10#define HID_MAIN_ITEM_TAG_END_COLLECTION 12/* * HID report descriptor main item contents */#define HID_MAIN_ITEM_CONSTANT 0x001#define HID_MAIN_ITEM_VARIABLE 0x002#define HID_MAIN_ITEM_RELATIVE 0x004#define HID_MAIN_ITEM_WRAP 0x008#define HID_MAIN_ITEM_NONLINEAR 0x010#define HID_MAIN_ITEM_NO_PREFERRED 0x020#define HID_MAIN_ITEM_NULL_STATE 0x040#define HID_MAIN_ITEM_VOLATILE 0x080#define HID_MAIN_ITEM_BUFFERED_BYTE 0x100/* * HID report descriptor collection item types */#define HID_COLLECTION_PHYSICAL 0#define HID_COLLECTION_APPLICATION 1#define HID_COLLECTION_LOGICAL 2/* * HID report descriptor global item tags */#define HID_GLOBAL_ITEM_TAG_USAGE_PAGE 0#define HID_GLOBAL_ITEM_TAG_LOGICAL_MINIMUM 1#define HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM 2#define HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM 3#define HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM 4#define HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT 5#define HID_GLOBAL_ITEM_TAG_UNIT 6#define HID_GLOBAL_ITEM_TAG_REPORT_SIZE 7#define HID_GLOBAL_ITEM_TAG_REPORT_ID 8#define HID_GLOBAL_ITEM_TAG_REPORT_COUNT 9#define HID_GLOBAL_ITEM_TAG_PUSH 10#define HID_GLOBAL_ITEM_TAG_POP 11/* * HID report descriptor local item tags */#define HID_LOCAL_ITEM_TAG_USAGE 0#define HID_LOCAL_ITEM_TAG_USAGE_MINIMUM 1#define HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM 2#define HID_LOCAL_ITEM_TAG_DESIGNATOR_INDEX 3#define HID_LOCAL_ITEM_TAG_DESIGNATOR_MINIMUM 4#define HID_LOCAL_ITEM_TAG_DESIGNATOR_MAXIMUM 5#define HID_LOCAL_ITEM_TAG_STRING_INDEX 7#define HID_LOCAL_ITEM_TAG_STRING_MINIMUM 8#define HID_LOCAL_ITEM_TAG_STRING_MAXIMUM 9#define HID_LOCAL_ITEM_TAG_DELIMITER 10static void usb_kbd_show_item(struct hid_item *item){ switch(item->type) { case HID_ITEM_TYPE_MAIN: switch(item->tag) { case HID_MAIN_ITEM_TAG_INPUT: printf("Main Input"); break; case HID_MAIN_ITEM_TAG_OUTPUT: printf("Main Output"); break; case HID_MAIN_ITEM_TAG_FEATURE: printf("Main Feature"); break; case HID_MAIN_ITEM_TAG_BEGIN_COLLECTION: printf("Main Begin Collection"); break; case HID_MAIN_ITEM_TAG_END_COLLECTION: printf("Main End Collection"); break; default: printf("Main reserved %d",item->tag); break; } break; case HID_ITEM_TYPE_GLOBAL: switch(item->tag) { case HID_GLOBAL_ITEM_TAG_USAGE_PAGE: printf("- Global Usage Page"); break; case HID_GLOBAL_ITEM_TAG_LOGICAL_MINIMUM: printf("- Global Logical Minimum"); break; case HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM: printf("- Global Logical Maximum"); break; case HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM: printf("- Global physical Minimum"); break; case HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM: printf("- Global physical Maximum"); break; case HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT: printf("- Global Unit Exponent"); break; case HID_GLOBAL_ITEM_TAG_UNIT: printf("- Global Unit"); break; case HID_GLOBAL_ITEM_TAG_REPORT_SIZE: printf("- Global Report Size"); break; case HID_GLOBAL_ITEM_TAG_REPORT_ID: printf("- Global Report ID"); break; case HID_GLOBAL_ITEM_TAG_REPORT_COUNT: printf("- Global Report Count"); break; case HID_GLOBAL_ITEM_TAG_PUSH: printf("- Global Push"); break; case HID_GLOBAL_ITEM_TAG_POP: printf("- Global Pop"); break; default: printf("- Global reserved %d",item->tag); break; } break; case HID_ITEM_TYPE_LOCAL: switch(item->tag) { case HID_LOCAL_ITEM_TAG_USAGE: printf("-- Local Usage"); break; case HID_LOCAL_ITEM_TAG_USAGE_MINIMUM: printf("-- Local Usage Minimum"); break; case HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM: printf("-- Local Usage Maximum"); break; case HID_LOCAL_ITEM_TAG_DESIGNATOR_INDEX: printf("-- Local Designator Index"); break; case HID_LOCAL_ITEM_TAG_DESIGNATOR_MINIMUM: printf("-- Local Designator Minimum"); break; case HID_LOCAL_ITEM_TAG_DESIGNATOR_MAXIMUM: printf("-- Local Designator Maximum"); break; case HID_LOCAL_ITEM_TAG_STRING_INDEX: printf("-- Local String Index"); break; case HID_LOCAL_ITEM_TAG_STRING_MINIMUM: printf("-- Local String Minimum"); break; case HID_LOCAL_ITEM_TAG_STRING_MAXIMUM: printf("-- Local String Maximum"); break; case HID_LOCAL_ITEM_TAG_DELIMITER: printf("-- Local Delimiter"); break; default: printf("-- Local reserved %d",item->tag); break; } break; default: printf("--- reserved %d",item->type); break; } switch(item->size) { case 1: printf(" %d",item->data.u8); break; case 2: printf(" %d",item->data.u16); break; case 4: printf(" %ld",item->data.u32); break; } printf("\n");}static int usb_kbd_get_hid_desc(struct usb_device *dev){ unsigned char buffer[256]; struct usb_descriptor_header *head; struct usb_config_descriptor *config; int index,len,i; unsigned char *start, *end; struct hid_item item; if(usb_get_configuration_no(dev,&buffer[0],0)==-1) return -1; head =(struct usb_descriptor_header *)&buffer[0]; if(head->bDescriptorType!=USB_DT_CONFIG) { printf(" ERROR: NOT USB_CONFIG_DESC %x\n",head->bDescriptorType); return -1; } index=head->bLength; config=(struct usb_config_descriptor *)&buffer[0]; len=swap_16(config->wTotalLength); /* Ok the first entry must be a configuration entry, now process the others */ head=(struct usb_descriptor_header *)&buffer[index]; while(index+1 < len) { if(head->bDescriptorType==USB_DT_HID) { printf("HID desc found\n"); memcpy(&usb_kbd_hid_desc,&buffer[index],buffer[index]); usb_kbd_hid_desc.bcdHID=swap_16(usb_kbd_hid_desc.bcdHID); usb_kbd_hid_desc.wDescriptorLength=swap_16(usb_kbd_hid_desc.wDescriptorLength); usb_kbd_display_hid(&usb_kbd_hid_desc); len=0; break; } index+=head->bLength; head=(struct usb_descriptor_header *)&buffer[index]; } if(len>0) return -1; len=usb_kbd_hid_desc.wDescriptorLength; if((index = usb_get_class_descriptor(dev, 0, USB_DT_REPORT, 0, &buffer[0], len)) < 0) { printf("reading report descriptor failed\n"); return -1; } printf(" report descriptor (size %u, read %d)\n", len, index); start=&buffer[0]; end=&buffer[len]; i=0; do { index=fetch_item(start,end,&item); i+=index; i++; if(index>=0) usb_kbd_show_item(&item); start+=index; start++; } while(index>=0);}#endif#endif /* CONFIG_USB_KEYBOARD */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -