|
前面一篇介绍了如何获得USB Descriptor,更麻烦的是这个数据的解读。在【参考1】给出了一个直接解析 Descriptor的例子。美中不足的是,这个例子只能在老版本的Arduino上工作(我估计是 0.22),在新版本 1.6.x 的IDE上会出现很多报错。
经过努力修改,终于可以编译通过(需要选择 Arduno Uno),程序如下:
- /* MAX3421E USB Host controller configuration descriptor parser */
- //#include "Spi.h"
- #include "Max3421e.h"
- #include "Usb.h"
- #include "descriptor_parser.h"
-
- #define LOBYTE(x) ((char*)(&(x)))[0]
- #define HIBYTE(x) ((char*)(&(x)))[1]
- #define BUFSIZE 256 //buffer size
- #define DEVADDR 1
- #define getReportDescr( addr, ep, nbytes, parse_func, nak_limit ) ctrlXfer( addr, ep, bmREQ_HIDREPORT, USB_REQUEST_GET_DESCRIPTOR, 0x00, HID_DESCRIPTOR_REPORT, 0x0000, nbytes, parse_func, nak_limit )
- #define getReport( addr, ep, nbytes, interface, report_type, report_id, parse_func, nak_limit ) ctrlXfer( addr, ep, bmREQ_HIDIN, HID_REQUEST_GET_REPORT, report_id, report_type, interface, nbytes, parse_func, nak_limit )
- /* Foeward declarations */
- void setup();
- void loop();
- byte ctrlXfer( byte addr, byte ep, byte bmReqType, byte bRequest, byte wValLo, byte wValHi, unsigned int wInd, uint16_t nbytes, PARSE parse_func, uint16_t nak_limit );
- void HIDreport_parse( uint8_t* buf, uint8_t* head, uint8_t* tail);
- typedef struct {
- uint8_t bDescriptorType;
- uint16_t wDescriptorLength;
- } HID_CLASS_DESCRIPTOR;
- //typedef void (*PARSE)( int8_t*, int8_t*, int8_t );
- MAX3421E Max;
- USB Usb;
-
- void setup()
- {
- Serial.begin( 115200 );
- printProgStr(PSTR("\r\nStart"));
- Max.powerOn();
- delay( 200 );
- }
-
- void loop()
- {
- uint8_t rcode;
- uint8_t tmpbyte = 0;
- //PARSE pf = &HIDreport_parse;
- /**/
- Max.Task();
- Usb.Task();
- if( Usb.getUsbTaskState() >= USB_STATE_CONFIGURING ) { //state configuring or higher
- /* printing device descriptor */
- printProgStr(PSTR("\r\nDevice addressed... "));
- printProgStr(PSTR("Requesting device descriptor."));
- tmpbyte = getdevdescr( DEVADDR ); //number of configurations, 0 if error
- if( tmpbyte == 0 ) {
- printProgStr(PSTR("\r\nDevice descriptor cannot be retrieved. Program Halted\r\n"));
- while( 1 ); //stop
- }//if( tmpbyte
- /* print configuration descriptors for all configurations */
- for( uint8_t i = 0; i < tmpbyte; i++ ) {
- getconfdescr( DEVADDR, i );
- }
- /* Stop */
- while( 1 ); //stop
- }
- }
- /* Prints device descriptor. Returns number of configurations or zero if request error occured */
- byte getdevdescr( byte addr )
- {
- USB_DEVICE_DESCRIPTOR buf;
- byte rcode;
- //Max.toggle( BPNT_0 );
- rcode = Usb.getDevDescr( addr, 0, 0x12, ( char *)&buf );
- if( rcode ) {
- printProgStr( rcode_error_msg );
- print_hex( rcode, 8 );
- return( 0 );
- }
- printProgStr(PSTR("\r\nDevice descriptor: \r\n"));
- //Descriptor length
- printProgStr( descr_len );
- print_hex( buf.bLength, 8 );
- //Descriptor type
- // printProgStr( descr_type );
- // print_hex( buf.bDescriptorType, 8 );
- // printProgStr( descrtype_parse( buf.bDescriptorType ));
- //USB Version
- printProgStr(PSTR("\r\nUSB version:\t\t"));
- Serial.print(( HIBYTE( buf.bcdUSB )), HEX );
- Serial.print(".");
- Serial.print(( LOBYTE( buf.bcdUSB )), HEX );
- //Device class
- printProgStr( class_str );
- print_hex( buf.bDeviceClass, 8 );
- printProgStr( classname_parse( buf.bDeviceClass ));
- //Device Subclass
- printProgStr( subclass_str );
- print_hex( buf.bDeviceSubClass, 8 );
- //Device Protocol
- printProgStr( protocol_str );
- print_hex( buf.bDeviceProtocol, 8 );
- //Max.packet size
- printProgStr( maxpktsize_str );
- print_hex( buf.bMaxPacketSize0, 8 );
- //VID
- printProgStr(PSTR("\r\nVendor ID:\t\t"));
- print_hex( buf.idVendor, 16 );
- //PID
- printProgStr(PSTR("\r\nProduct ID:\t\t"));
- print_hex( buf.idProduct, 16 );
- //Revision
- printProgStr(PSTR("\r\nRevision ID:\t\t"));
- print_hex( buf.bcdDevice, 16 );
- //Mfg.string
- printProgStr (PSTR("\r\nMfg.string index:\t"));
- print_hex( buf.iManufacturer, 8 );
- getstrdescr( addr, buf.iManufacturer );
- //Prod.string
- printProgStr(PSTR("\r\nProd.string index:\t"));
- print_hex( buf.iProduct, 8 );
- //printProgStr( str_cont );
- getstrdescr( addr, buf.iProduct );
- //Serial number string
- printProgStr(PSTR("\r\nSerial number index:\t"));
- print_hex( buf.iSerialNumber, 8 );
- //printProgStr( str_cont );
- getstrdescr( addr, buf.iSerialNumber );
- //Number of configurations
- printProgStr(PSTR("\r\nNumber of conf.:\t"));
- print_hex( buf.bNumConfigurations, 8 );
- return( buf.bNumConfigurations );
- }
- /* Get string descriptor. Takes device address and string index */
- byte getstrdescr( byte addr, byte idx )
- {
- char buf[ BUFSIZE ];
- byte rcode;
- byte length;
- byte i;
- unsigned int langid;
- if( idx == 0 ) { //don't try to get index zero
- return( 0 );
- }
- rcode = Usb.getStrDescr( addr, 0, 1, 0, 0, buf ); //get language table length
- if( rcode ) {
- printProgStr(PSTR("\r\nError retrieving LangID table length"));
- return( rcode );
- }
- length = buf[ 0 ]; //length is the first byte
- rcode = Usb.getStrDescr( addr, 0, length, 0, 0, buf ); //get language table
- if( rcode ) {
- printProgStr(PSTR("\r\nError retrieving LangID table"));
- return( rcode );
- }
- HIBYTE( langid ) = buf[ 3 ]; //get first langid
- LOBYTE( langid ) = buf[ 2 ]; //bytes are swapped to account for endiannes
- //printProgStr(PSTR("\r\nLanguage ID: "));
- //print_hex( langid, 16 );
- rcode = Usb.getStrDescr( addr, 0, 1, idx, langid, buf );
- if( rcode ) {
- printProgStr(PSTR("\r\nError retrieving string length"));
- return( rcode );
- }
- length = ( buf[ 0 ] < 254 ? buf[ 0 ] : 254 );
- printProgStr(PSTR(" Length: "));
- Serial.print( length, DEC );
- rcode = Usb.getStrDescr( addr, 0, length, idx, langid, buf );
- if( rcode ) {
- printProgStr(PSTR("\r\nError retrieveing string"));
- return( rcode );
- }
- printProgStr(PSTR(" Contents: "));
- for( i = 2; i < length; i+=2 ) {
- Serial.print( buf[ i ] );
- }
- return( idx );
- }
- /* Returns string to class name */
- const char* classname_parse( byte class_number )
- {
- switch( class_number ) {
- case 0x00:
- return PSTR(" Use class information in the Interface Descriptor");
- case 0x01:
- return PSTR(" Audio");
- case 0x02:
- return PSTR(" Communications and CDC Control");
- case 0x03:
- return PSTR(" HID (Human Interface Device)");
- case 0x05:
- return PSTR(" Physical");
- case 0x06:
- return PSTR(" Image");
- case 0x07:
- return PSTR(" Printer");
- case 0x08:
- return PSTR(" Mass Storage");
- case 0x09:
- return PSTR(" Hub");
- case 0x0a:
- return PSTR(" CDC-Data");
- case 0x0b:
- return PSTR(" Smart Card");
- case 0x0d:
- return PSTR(" Content Security");
- case 0x0e:
- return PSTR(" Video");
- case 0x0f:
- return PSTR(" Personal Healthcare");
- case 0xdc:
- return PSTR("Diagnostic Device");
- case 0xe0:
- return PSTR(" Wireless Controller");
- case 0xef:
- return PSTR(" Miscellaneous");
- case 0xfe:
- return PSTR(" Application Specific");
- case 0xff:
- return PSTR(" Vendor Specific");
- default:
- return unk_msg;
- }//switch( class_number
- }
- /* Getting configuration descriptor */
- byte getconfdescr( byte addr, byte conf )
- {
- char buf[ BUFSIZE ];
- char* buf_ptr = buf;
- byte rcode;
- byte descr_length;
- byte descr_type;
- unsigned int total_length;
- printProgStr(PSTR("\r\n\nConfiguration number "));
- Serial.print( conf, HEX );
- rcode = Usb.getConfDescr( addr, 0, 4, conf, buf ); //get total length
- if( rcode ) {
- printProgStr(PSTR("Error retrieving configuration length. Error code "));
- Serial.println( rcode, HEX );
- return( 0 );
- }//if( rcode
- LOBYTE( total_length ) = buf[ 2 ];
- HIBYTE( total_length ) = buf[ 3 ];
- printProgStr(PSTR("\r\nTotal configuration length: "));
- Serial.print( total_length, DEC );
- printProgStr(PSTR(" bytes"));
- if( total_length > BUFSIZE ) { //check if total length is larger than buffer
- printProgStr(PSTR("Total length truncated to "));
- Serial.print( BUFSIZE, DEC);
- printProgStr(PSTR("bytes"));
- total_length = BUFSIZE;
- }
- rcode = Usb.getConfDescr( addr, 0, total_length, conf, buf ); //get the whole descriptor
- while( buf_ptr < buf + total_length ) { //parsing descriptors
- descr_length = *( buf_ptr );
- descr_type = *( buf_ptr + 1 );
- switch( descr_type ) {
- case( USB_DESCRIPTOR_CONFIGURATION ):
- printconfdescr( buf_ptr );
- break;
- case( USB_DESCRIPTOR_INTERFACE ):
- printintfdescr( buf_ptr );
- break;
- case( USB_DESCRIPTOR_ENDPOINT ):
- printepdescr( buf_ptr );
- break;
- case( HID_DESCRIPTOR_HID ):
- printhid_descr( buf_ptr );
- break;
- default:
- printunkdescr( buf_ptr );
- break;
- }//switch( descr_type
- Serial.println("");
- buf_ptr = ( buf_ptr + descr_length ); //advance buffer pointer
- }//while( buf_ptr <=...
- return( 0 );
- }
- /* function to print configuration descriptor */
- void printconfdescr( char* descr_ptr )
- {
- USB_CONFIGURATION_DESCRIPTOR* conf_ptr = ( USB_CONFIGURATION_DESCRIPTOR* )descr_ptr;
- uint8_t tmpbyte;
- printProgStr(PSTR("\r\n\nConfiguration descriptor:"));
- printProgStr(PSTR("\r\nTotal length:\t\t"));
- print_hex( conf_ptr->wTotalLength, 16 );
- printProgStr(PSTR("\r\nNumber of interfaces:\t"));
- print_hex( conf_ptr->bNumInterfaces, 8 );
- printProgStr(PSTR("\r\nConfiguration value:\t"));
- print_hex( conf_ptr->bConfigurationValue, 8 );
- printProgStr(PSTR("\r\nConfiguration string:\t"));
- tmpbyte = conf_ptr->iConfiguration;
- print_hex( tmpbyte, 8 );
- getstrdescr( DEVADDR, tmpbyte );
- printProgStr(PSTR("\r\nAttributes:\t\t"));
- tmpbyte = conf_ptr->bmAttributes;
- print_hex( tmpbyte, 8 );
- if( tmpbyte & 0x40 ) { //D6
- printProgStr(PSTR(" Self-powered"));
- }
- if( tmpbyte & 0x20 ) { //D5
- printProgStr(PSTR(" Remote Wakeup"));
- }
- printProgStr(PSTR("\r\nMax.power:\t\t"));
- tmpbyte = conf_ptr->bMaxPower;
- print_hex( tmpbyte, 8 );
- printProgStr(PSTR(" "));
- Serial.print(( tmpbyte * 2 ), DEC);
- printProgStr(PSTR("ma"));
- return;
- }
- /* function to print interface descriptor */
- void printintfdescr( char* descr_ptr )
- {
- USB_INTERFACE_DESCRIPTOR* intf_ptr = ( USB_INTERFACE_DESCRIPTOR* )descr_ptr;
- uint8_t tmpbyte;
- printProgStr(PSTR("\r\nInterface descriptor:"));
- printProgStr(PSTR("\r\nInterface number:\t"));
- print_hex( intf_ptr->bInterfaceNumber, 8 );
- printProgStr(PSTR("\r\nAlternate setting:\t"));
- print_hex( intf_ptr->bAlternateSetting, 8 );
- printProgStr(PSTR("\r\nEndpoints:\t\t"));
- print_hex( intf_ptr->bNumEndpoints, 8 );
- printProgStr( class_str );
- tmpbyte = intf_ptr->bInterfaceClass;
- print_hex( tmpbyte, 8 );
- printProgStr(classname_parse( tmpbyte ));
- printProgStr( subclass_str );
- print_hex( intf_ptr->bInterfaceSubClass, 8 );
- printProgStr( protocol_str );
- print_hex( intf_ptr->bInterfaceProtocol, 8 );
- printProgStr(PSTR("\r\nInterface string:\t"));
- tmpbyte = intf_ptr->iInterface;
- print_hex( tmpbyte, 8 );
- getstrdescr( DEVADDR, tmpbyte );
- return;
- }
- /* function to print endpoint descriptor */
- void printepdescr( char* descr_ptr )
- {
- USB_ENDPOINT_DESCRIPTOR* ep_ptr = ( USB_ENDPOINT_DESCRIPTOR* )descr_ptr;
- uint8_t tmpbyte;
- printProgStr(PSTR("\r\nEndpoint descriptor:"));
- printProgStr(PSTR("\r\nEndpoint address:\t"));
- tmpbyte = ep_ptr->bEndpointAddress;
- print_hex( tmpbyte & 0x0f, 8 );
- printProgStr(PSTR(" Direction: "));
- ( tmpbyte & 0x80 ) ? printProgStr(PSTR("IN")) : printProgStr(PSTR("OUT"));
- printProgStr(PSTR("\r\nAttributes:\t\t"));
- tmpbyte = ep_ptr->bmAttributes;
- print_hex( tmpbyte, 8 );
- printProgStr(PSTR(" Transfer type: "));
- printProgStr((char*)pgm_read_word(&transfer_types[(tmpbyte & 0x03)]));
- if(( tmpbyte & 0x03 ) == 1 ) { //Isochronous Transfer
- printProgStr(PSTR(", Sync Type: "));
- printProgStr((char*)pgm_read_word(&sync_types[(tmpbyte & 0x0c)]));
- printProgStr(PSTR(", Usage Type: "));
- printProgStr((char*)pgm_read_word(&usage_types[(tmpbyte & 0x30)]));
- }//if( tmpbyte & 0x01
- printProgStr( maxpktsize_str );
- print_hex( ep_ptr->wMaxPacketSize, 16 );
- printProgStr(PSTR("\r\nPolling interval:\t"));
- tmpbyte = ep_ptr->bInterval;
- print_hex( tmpbyte, 8 );
- printProgStr(PSTR(" "));
- Serial.print( tmpbyte, DEC );
- printProgStr(PSTR(" ms"));
- return;
- }
- /* function to print HID descriptor */
- void printhid_descr( char* descr_ptr )
- {
- PARSE pf = &HIDreport_parse;
- USB_HID_DESCRIPTOR* hid_ptr = ( USB_HID_DESCRIPTOR* )descr_ptr;
- uint8_t tmpbyte;
- /**/
- printProgStr(PSTR("\r\nHID descriptor:"));
- printProgStr(PSTR("\r\nDescriptor length:\t"));
- tmpbyte = hid_ptr->bLength;
- print_hex( tmpbyte, 8 );
- printProgStr(PSTR(" "));
- Serial.print( tmpbyte, DEC );
- printProgStr(PSTR(" bytes"));
- printProgStr(PSTR("\r\nHID version:\t\t"));
- Serial.print(( HIBYTE( hid_ptr->bcdHID )), HEX );
- Serial.print(".");
- Serial.print(( LOBYTE( hid_ptr->bcdHID )), HEX );
- tmpbyte = hid_ptr->bCountryCode;
- printProgStr(PSTR("\r\nCountry Code:\t\t"));
- Serial.print( tmpbyte, DEC );
- printProgStr(PSTR(" "));
- ( tmpbyte > 35 ) ? printProgStr(PSTR("Reserved")) : printProgStr((char*)pgm_read_word(&HID_Country_Codes[ tmpbyte ]));
- tmpbyte = hid_ptr->bNumDescriptors;
- printProgStr(PSTR("\r\nClass Descriptors:\t"));
- Serial.print( tmpbyte, DEC );
- //Printing class descriptors
- descr_ptr += 6; //advance buffer pointer
- for( uint8_t i = 0; i < tmpbyte; i++ ) {
- uint8_t tmpdata;
- HID_CLASS_DESCRIPTOR* hidclass_ptr = ( HID_CLASS_DESCRIPTOR* )descr_ptr;
- tmpdata = hidclass_ptr->bDescriptorType;
- printProgStr(PSTR("\r\nClass Descriptor Type:\t"));
- Serial.print( tmpdata, HEX );
- if(( tmpdata < 0x21 ) || ( tmpdata > 0x2f )) {
- printProgStr(PSTR(" Invalid"));
- }
- switch( tmpdata ) {
- case 0x21:
- printProgStr(PSTR(" HID"));
- break;
- case 0x22:
- printProgStr(PSTR(" Report"));
- break;
- case 0x23:
- printProgStr(PSTR(" Physical"));
- break;
- default:
- printProgStr(PSTR(" Reserved"));
- break;
- }//switch( tmpdata
- printProgStr(PSTR("\r\nClass Descriptor Length:"));
- Serial.print( hidclass_ptr->wDescriptorLength );
- printProgStr(PSTR(" bytes"));
- printProgStr(PSTR("\r\n\nHID report descriptor:\r\n"));
- getReportDescr( DEVADDR, 0 , hidclass_ptr->wDescriptorLength, pf, USB_NAK_LIMIT );
- descr_ptr += 3; //advance to the next record
- }//for( uint8_t i=...
- return;
- }
- /*function to print unknown descriptor */
- void printunkdescr( char* descr_ptr )
- {
- byte length = *descr_ptr;
- byte i;
- printProgStr(PSTR("\r\nUnknown descriptor:"));
- printProgStr(PSTR("Length:\t\t"));
- print_hex( *descr_ptr, 8 );
- printProgStr(PSTR("\r\nType:\t\t"));
- print_hex( *(descr_ptr + 1 ), 8 );
- printProgStr(PSTR("\r\nContents:\t"));
- descr_ptr += 2;
- for( i = 0; i < length; i++ ) {
- print_hex( *descr_ptr, 8 );
- descr_ptr++;
- }
- }
- /* Control-IN transfer with callback. Sets address, endpoint, fills control packet with necessary data, dispatches control packet, and initiates bulk IN transfer */
- /* Control, data, and setup stages combined from standard USB library to be able to read large data blocks. Restricted to control-IN transfers with data stage */
- /* data read and MAX3421E RECV FIFO buffer release shall be performed by parse_func callback */
- /* return codes: */
- /* 00 = success */
- /* 01-0f = non-zero HRSLT */
- byte ctrlXfer( byte addr, byte ep, byte bmReqType, byte bRequest, byte wValLo, byte wValHi, unsigned int wInd, uint16_t nbytes, PARSE parse_func, uint16_t nak_limit = USB_NAK_LIMIT )
- {
- byte rcode;
- SETUP_PKT sp;
- EP_RECORD* ep_rec = Usb.getDevTableEntry( addr, ep );
- byte pktsize;
- byte maxpktsize = ep_rec->MaxPktSize;
- unsigned int xfrlen = 0;
- /**/
- Max.regWr( rPERADDR, addr ); //set peripheral address
- /* fill in setup packet */
- sp.ReqType_u.bmRequestType = bmReqType;
- sp.bRequest = bRequest;
- sp.wVal_u.wValueLo = wValLo;
- sp.wVal_u.wValueHi = wValHi;
- sp.wIndex = wInd;
- sp.wLength = nbytes;
- Max.bytesWr( rSUDFIFO, 8, ( char *)&sp ); //transfer to setup packet FIFO
- rcode = Usb.dispatchPkt( tokSETUP, ep, nak_limit ); //dispatch packet
- //Serial.println("Setup packet"); //DEBUG
- if( rcode ) { //return HRSLT if not zero
- printProgStr(PSTR("\r\nSetup packet error: "));
- Serial.print( rcode, HEX );
- return( rcode );
- }
- /* Data stage */
- //ep_rec->rcvToggle = bmRCVTOG1;
- Max.regWr( rHCTL, bmRCVTOG1 ); //set toggle
- while( 1 ) { //exited by break
- /* request data */
- rcode = Usb.dispatchPkt( tokIN, ep, nak_limit );
- if( rcode ) {
- printProgStr(PSTR("\r\nData Stage Error: "));
- Serial.print( rcode, HEX );
- return( rcode );
- }
- /* check for RCVDAVIRQ and generate error if not present */
- /* the only case when absense of RCVDAVIRQ makes sense is when toggle error occured. Need to add handling for that */
- if(( Max.regRd( rHIRQ ) & bmRCVDAVIRQ ) == 0 ) {
- printProgStr(PSTR("\r\nData Toggle error."));
- return ( 0xf0 );
- }
- pktsize = Max.regRd( rRCVBC ); //get received bytes count
- parse_func( pktsize ); //call parse function. Parse is expected to read the FIFO completely
- Max.regWr( rHIRQ, bmRCVDAVIRQ ); // Clear the IRQ & free the buffer
- xfrlen += pktsize; // add this packet's byte count to total transfer length
- /* The transfer is complete under two conditions: */
- /* 1. The device sent a short packet (L.T. maxPacketSize) */
- /* 2. 'nbytes' have been transferred. */
- if (( pktsize < maxpktsize ) || (xfrlen >= nbytes )) { // have we transferred 'nbytes' bytes?
- break;
- }
- }//while( 1 )
- rcode = Usb.dispatchPkt( tokOUTHS, ep, nak_limit );
- if( rcode ) { //return error
- printProgStr(PSTR("Status packet error: "));
- Serial.print( rcode, HEX );
- }
- return( rcode );
- }
- /* Parses bitfields in main items */
- void print_mainbitfield( uint8_t byte_toparse )
- {
- ( byte_toparse & 0x01 ) ? printProgStr(PSTR("Constant,")) : printProgStr(PSTR("Data,")); //bit 0
- ( byte_toparse & 0x02 ) ? printProgStr(PSTR("Variable,")) : printProgStr(PSTR("Array,")); //bit 1
- ( byte_toparse & 0x04 ) ? printProgStr(PSTR("Relative,")) : printProgStr(PSTR("Absolute,")); //...
- ( byte_toparse & 0x08 ) ? printProgStr(PSTR("Wrap,")) : printProgStr(PSTR("No Wrap,"));
- ( byte_toparse & 0x10 ) ? printProgStr(PSTR("Non Linear,")) : printProgStr(PSTR("Linear,"));
- ( byte_toparse & 0x20 ) ? printProgStr(PSTR("No preferred,")) : printProgStr(PSTR("Preferred State,"));
- ( byte_toparse & 0x40 ) ? printProgStr(PSTR("Null State,")) : printProgStr(PSTR("No Null Position,")); //bit 6
- ( byte_toparse & 0x40 ) ? printProgStr(PSTR("Volatile( ignore for Input),")) : printProgStr(PSTR("Non-volatile(Ignore for Input),")); //bit 7
- }
- /* HID Report Desriptor Parser Callback */
- /* called repeatedly from Control transfer function */
- void HIDreport_parse( uint8_t pkt_size )
- {
- #define B_SIZE 0x03 //bSize bitmask
- #define B_TYPE 0x0c //bType bitmask
- #define B_TAG 0xf0 //bTag bitmask
- /* parser states */
- enum STATE { ITEM_START, DATA_PARSE };
- static STATE state = ITEM_START;
- static uint8_t databytes_left = 0;
- static uint8_t prefix; //item prefix - type and tag
- uint8_t byte_toparse;
- uint8_t bType;
- uint8_t tmpbyte;
- /**/
- while( 1 ) {
- if( pkt_size ) {
- byte_toparse = Max.regRd( rRCVFIFO ); //read a byte from FIFO
- pkt_size--;
- }
- else {
- return; //all bytes read
- }
- switch( state ) {
- case ITEM_START: //start of the record
- prefix = byte_toparse >>2; //store prefix for databyte parsing
- tmpbyte = byte_toparse & B_SIZE;
- /* get item length */
- ( tmpbyte == 0x03 ) ? databytes_left = 4 : databytes_left = tmpbyte;
- if( databytes_left ) {
- state = DATA_PARSE; //read bytes after prefix
- }
- printProgStr(PSTR("\r\nLength: "));
- Serial.print( databytes_left, DEC );
- /* get item type */
- bType = ( byte_toparse & B_TYPE ) >>2;
- printProgStr(PSTR(" Type: "));
- printProgStr((char*)pgm_read_word(&btypes[ bType ]));
- /* get item tag */
- printProgStr(PSTR("\t\tTag: "));
- tmpbyte = ( byte_toparse & B_TAG ) >>4 ;
- switch( bType ) {
- case 0: //Main
- if( tmpbyte < 0x08 ) {
- printProgStr(PSTR("Invalid Tag"));
- }
- else if( tmpbyte > 0x0c ) {
- printProgStr( reserved_msg );
- }
- else {
- printProgStr((char*)pgm_read_word(&maintags[ tmpbyte - 8 /* & 0x03 */]));
- //Serial.print("Byte: ");
- //Serial.println( tmpbyte, HEX );
- }
- break;//case 0 Main
- case 1: //Global
- ( tmpbyte > 0x0b ) ? printProgStr( reserved_msg ) : printProgStr((char*)pgm_read_word(&globaltags[ tmpbyte ]));
- break;//case 1 Global
- case 2: //Local
- ( tmpbyte > 0x0a ) ? printProgStr( reserved_msg ) : printProgStr((char*)pgm_read_word(&localtags[ tmpbyte ]));
- break;//case 2 Local
- default:
- break;
- }//switch( bType...
- break;//case ITEM_START
- case DATA_PARSE:
- switch( prefix ) {
- case 0x20: //Main Input
- case 0x24: //Main Output
- case 0x2c: //Main Feature
- /* todo: add parsing 8th bit */
- print_mainbitfield( byte_toparse );
- break;
- case 0x28: //Main Collection
- if(( byte_toparse > 0x06 ) && ( byte_toparse < 0x80 )) {
- printProgStr( reserved_msg );
- }
- else if(( byte_toparse > 0x7f ) && ( byte_toparse <= 0xff )) {
- printProgStr(PSTR("Vendor-defined"));
- }
- else {
- printProgStr((char*)pgm_read_word(&collections[ byte_toparse ]));
- }
- break;//case 0x28 Main Collection
- //case 0x30: //Main End Collection
- case 0x01: //Global Usage Page
- switch( byte_toparse ) { //see HID Usage Tables doc v.1.12 page 14
- case 0x00:
- case 0x01:
- case 0x02:
- case 0x03:
- case 0x04:
- case 0x05:
- case 0x06:
- case 0x07:
- case 0x08:
- case 0x09:
- case 0x0a:
- case 0x0b:
- case 0x0c:
- case 0x0d:
- case 0x0e:
- case 0x0f:
- case 0x10:
- printProgStr((char*)pgm_read_word(&usage_pages[ byte_toparse ]));
- break;
- case 0x14:
- printProgStr(PSTR("Alphanumeric Display"));
- break;
- case 0x40:
- printProgStr(PSTR("Medical Instruments"));
- break;
- case 0x80:
- case 0x81:
- case 0x82:
- case 0x83:
- printProgStr(PSTR("Monitor page"));
- break;
- case 0x84:
- case 0x85:
- case 0x86:
- case 0x87:
- printProgStr(PSTR("Power page"));
- break;
- case 0x8c:
- printProgStr(PSTR("Bar Code Scanner page"));
- break;
- case 0x8d:
- printProgStr(PSTR("Scale page"));
- break;
- case 0x8e:
- printProgStr(PSTR("Magnetic Stripe Reading (MSR) Devices"));
- break;
- case 0x8f:
- printProgStr(PSTR("Reserved Point of Sale pages"));
- break;
- case 0x90:
- printProgStr(PSTR("Camera Control Page"));
- break;
- case 0x91:
- printProgStr(PSTR("Arcade Page"));
- break;
- default:
- // printProgStr(PSTR("Data: "));
- // print_hex( byte_toparse, 8 );
- //databytes_left--;
- break;
- }//switch case 0x01: //Global Usage Page
- }//switch( prefix ...
- printProgStr(PSTR(" Data: "));
- print_hex( byte_toparse, 8 );
- databytes_left--;
- if( !databytes_left ) {
- state = ITEM_START;
- }
- break;
- }//switch( state...
- }//while( 1 ...
- }
- /* prints hex numbers with leading zeroes */
- // copyright, Peter H Anderson, Baltimore, MD, Nov, '07
- // source: [url]http://www.phanderson.com/arduino/arduino_display.html[/url]
- void print_hex(int v, int num_places)
- {
- int mask=0, n, num_nibbles, digit;
-
- for (n=1; n<=num_places; n++) {
- mask = (mask << 1) | 0x0001;
- }
- v = v & mask; // truncate v to specified number of places
-
- num_nibbles = num_places / 4;
- if ((num_places % 4) != 0) {
- ++num_nibbles;
- }
- do {
- digit = ((v >> (num_nibbles-1) * 4)) & 0x0f;
- Serial.print(digit, HEX);
- }
- while(--num_nibbles);
- }
- /* given a PROGMEM string, use Serial.print() to send it out */
- /* Some non-intuitive casting necessary: */
- /* printProgStr(PSTR("Func.Mode:\t0x")); */
- /* printProgStr((char*)pgm_read_word(&mtpopNames[(op & 0xFF)])); */
- void printProgStr(const char* str)
- {
- if(!str) {
- return;
- }
- char c;
- while((c = pgm_read_byte(str++))) {
- Serial.write(c);
- }
- return;
- }
复制代码
工作的照片:
我用USB Shield挂接了一个USB小键盘,获得的结果如下:
Start
Device addressed... Requesting device descriptor.
Device descriptor:
Descriptor Length: 12
USB version: 1.10
Class: 00 Use class information in the Interface Descriptor
Subclass: 00
Protocol: 00
Max.packet size: 08
Vendor ID: 13BA
Product ID: 0001
Revision ID: 0100
Mfg.string index: 00
Prod.string index: 00
Serial number index: 00
Number of conf.: 01
Configuration number 0
Total configuration length: 34 bytes
Configuration descriptor:
Total length: 0022
Number of interfaces: 01
Configuration value: 01
Configuration string: 00
Attributes: A0 Remote Wakeup
Max.power: 32 100ma
Interface descriptor:
Interface number: 00
Alternate setting: 00
Endpoints: 01
Class: 03 HID (Human Interface Device)
Subclass: 01
Protocol: 01
Interface string: 00
HID descriptor:
Descriptor length: 09 9 bytes
HID version: 1.10
Country Code: 0 Not Supported
Class Descriptors: 1
Class Descriptor Type: 22 Report
Class Descriptor Length:54 bytes
HID report descriptor:
Length: 1 Type: Global Tag: Usage Page Generic Desktop Controls Data: 01
Length: 1 Type: Local Tag: Usage Data: 06
Length: 1 Type: Main Tag: Collection Application (mouse, keyboard) Data: 01
Length: 1 Type: Global Tag: Usage Page LEDs Data: 08
Length: 1 Type: Local Tag: Usage Minimum Data: 01
Length: 1 Type: Local Tag: Usage Maximum Data: 03
Length: 1 Type: Global Tag: Logical Minimum Data: 00
Length: 1 Type: Global Tag: Logical Maximum Data: 01
Length: 1 Type: Global Tag: Report Size Data: 01
Length: 1 Type: Global Tag: Report Count Data: 03
Length: 1 Type: Main Tag: Output Data,Variable,Absolute,No Wrap,Linear,Preferred State,No Null Position,Non-volatile(Ignore for Input), Data: 02
Length: 1 Type: Global Tag: Report Count Data: 05
Length: 1 Type: Main Tag: Output Constant,Array,Absolute,No Wrap,Linear,Preferred State,No Null Position,Non-volatile(Ignore for Input), Data: 01
Length: 1 Type: Global Tag: Usage Page Keyboard/Keypad Data: 07
Length: 1 Type: Local Tag: Usage Minimum Data: E0
Length: 1 Type: Local Tag: Usage Maximum Data: E7
Length: 1 Type: Global Tag: Report Count Data: 08
Length: 1 Type: Main Tag: Input Data,Variable,Absolute,No Wrap,Linear,Preferred State,No Null Position,Non-volatile(Ignore for Input), Data: 02
Length: 1 Type: Global Tag: Report Size Data: 08
Length: 1 Type: Global Tag: Report Count Data: 01
Length: 1 Type: Main Tag: Input Constant,Array,Absolute,No Wrap,Linear,Preferred State,No Null Position,Non-volatile(Ignore for Input), Data: 01
Length: 1 Type: Local Tag: Usage Minimum Data: 00
Length: 1 Type: Local Tag: Usage Maximum Data: 91
Length: 2 Type: Global Tag: Logical Maximum Data: FF Data: 00
Length: 1 Type: Global Tag: Report Count Data: 06
Length: 1 Type: Main Tag: Input Data,Array,Absolute,No Wrap,Linear,Preferred State,No Null Position,Non-volatile(Ignore for Input), Data: 00
Length: 0 Type: Main Tag: End Collection
Endpoint descriptor:
Endpoint address: 01 Direction: IN
Attributes: 03 Transfer type: Interrupt
Max.packet size: 0008
Polling interval: 0A 10 ms
修改后的可以正常编译的代码下载
参考:
1. https://github.com/felis/USB_Hos ... s/descriptor_parser USB_Host_Shield/examples/descriptor_parser/ |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?注册
x
|