Subversion Repositories Projects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1702 - 1
/* MAX3421E USB Host controller configuration descriptor parser */
2
#include <Spi.h>
3
#include <Max3421e.h>
4
#include <Usb.h>
5
#include "descriptor_parser.h"
6
 
7
#define LOBYTE(x) ((char*)(&(x)))[0]
8
#define HIBYTE(x) ((char*)(&(x)))[1]
9
#define BUFSIZE 256    //buffer size
10
#define DEVADDR 1
11
 
12
#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 )
13
#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 )
14
 
15
/* Foeward declarations */
16
void setup();
17
void loop();
18
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 );
19
void HIDreport_parse( uint8_t* buf, uint8_t* head, uint8_t* tail);
20
 
21
typedef struct {
22
  uint8_t bDescriptorType;
23
  uint16_t wDescriptorLength;
24
} HID_CLASS_DESCRIPTOR;
25
 
26
 
27
//typedef void (*PARSE)( int8_t*, int8_t*, int8_t );
28
 
29
MAX3421E Max;
30
USB Usb;
31
 
32
void setup()
33
{
34
  Serial.begin( 115200 );
35
  printProgStr(PSTR("\r\nStart"));
36
  Max.powerOn();
37
  delay( 200 );
38
}
39
 
40
void loop()
41
{
42
  uint8_t rcode;
43
  uint8_t tmpbyte = 0;
44
  //PARSE pf = &HIDreport_parse;
45
  /**/
46
  Max.Task();
47
  Usb.Task();
48
  if( Usb.getUsbTaskState() >= USB_STATE_CONFIGURING ) {  //state configuring or higher
49
  /* printing device descriptor */
50
    printProgStr(PSTR("\r\nDevice addressed... "));
51
    printProgStr(PSTR("Requesting device descriptor."));
52
    tmpbyte = getdevdescr( DEVADDR );                           //number of configurations, 0 if error
53
    if( tmpbyte == 0 ) {
54
      printProgStr(PSTR("\r\nDevice descriptor cannot be retrieved. Program Halted\r\n"));
55
      while( 1 );           //stop
56
     }//if( tmpbyte
57
     /* print configuration descriptors for all configurations */
58
     for( uint8_t i = 0; i < tmpbyte; i++ ) {
59
       getconfdescr( DEVADDR, i );
60
     }
61
  /* Stop */
62
      while( 1 );                          //stop
63
  }
64
}
65
 
66
/* Prints device descriptor. Returns number of configurations or zero if request error occured */
67
byte getdevdescr( byte addr )
68
{
69
  USB_DEVICE_DESCRIPTOR buf;
70
  byte rcode;
71
  //Max.toggle( BPNT_0 );
72
  rcode = Usb.getDevDescr( addr, 0, 0x12, ( char *)&buf );
73
  if( rcode ) {
74
    printProgStr( rcode_error_msg );
75
    print_hex( rcode, 8 );
76
    return( 0 );
77
  }
78
  printProgStr(PSTR("\r\nDevice descriptor: \r\n"));
79
  //Descriptor length
80
  printProgStr( descr_len );
81
  print_hex( buf.bLength, 8 );
82
  //Descriptor type
83
//  printProgStr( descr_type );
84
//  print_hex( buf.bDescriptorType, 8 );
85
//  printProgStr( descrtype_parse( buf.bDescriptorType ));
86
  //USB Version
87
  printProgStr(PSTR("\r\nUSB version:\t\t"));
88
  Serial.print(( HIBYTE( buf.bcdUSB )), HEX );
89
  Serial.print(".");
90
  Serial.print(( LOBYTE( buf.bcdUSB )), HEX );
91
  //Device class
92
  printProgStr( class_str );
93
  print_hex( buf.bDeviceClass, 8 );
94
  printProgStr( classname_parse( buf.bDeviceClass ));
95
  //Device Subclass
96
  printProgStr( subclass_str );
97
  print_hex( buf.bDeviceSubClass, 8 );
98
  //Device Protocol
99
  printProgStr( protocol_str );
100
  print_hex( buf.bDeviceProtocol, 8 );
101
  //Max.packet size
102
  printProgStr( maxpktsize_str );
103
  print_hex( buf.bMaxPacketSize0, 8 );
104
  //VID
105
  printProgStr(PSTR("\r\nVendor  ID:\t\t"));
106
  print_hex( buf.idVendor, 16 );
107
  //PID
108
  printProgStr(PSTR("\r\nProduct ID:\t\t"));
109
  print_hex( buf.idProduct, 16 );
110
  //Revision
111
  printProgStr(PSTR("\r\nRevision ID:\t\t"));
112
  print_hex( buf.bcdDevice, 16 );
113
  //Mfg.string
114
  printProgStr (PSTR("\r\nMfg.string index:\t"));
115
  print_hex( buf.iManufacturer, 8 );
116
  getstrdescr( addr, buf.iManufacturer );
117
  //Prod.string
118
  printProgStr(PSTR("\r\nProd.string index:\t"));
119
  print_hex( buf.iProduct, 8 );
120
  //printProgStr( str_cont );
121
  getstrdescr( addr, buf.iProduct );
122
  //Serial number string
123
  printProgStr(PSTR("\r\nSerial number index:\t"));
124
  print_hex( buf.iSerialNumber, 8 );
125
  //printProgStr( str_cont );
126
  getstrdescr( addr, buf.iSerialNumber );
127
  //Number of configurations
128
  printProgStr(PSTR("\r\nNumber of conf.:\t"));
129
  print_hex( buf.bNumConfigurations, 8 );
130
  return( buf.bNumConfigurations );
131
}
132
/* Get string descriptor. Takes device address and string index */
133
byte getstrdescr( byte addr, byte idx )
134
{
135
  char buf[ BUFSIZE ];
136
  byte rcode;
137
  byte length;
138
  byte i;
139
  unsigned int langid;
140
  if( idx == 0 ) {  //don't try to get index zero
141
    return( 0 );
142
  }
143
  rcode = Usb.getStrDescr( addr, 0, 1, 0, 0, buf );  //get language table length
144
  if( rcode ) {
145
    printProgStr(PSTR("\r\nError retrieving LangID table length"));
146
    return( rcode );
147
  }
148
  length = buf[ 0 ];      //length is the first byte
149
  rcode = Usb.getStrDescr( addr, 0, length, 0, 0, buf );  //get language table
150
  if( rcode ) {
151
    printProgStr(PSTR("\r\nError retrieving LangID table"));
152
    return( rcode );
153
  }
154
  HIBYTE( langid ) = buf[ 3 ];                            //get first langid
155
  LOBYTE( langid ) = buf[ 2 ];                            //bytes are swapped to account for endiannes
156
  //printProgStr(PSTR("\r\nLanguage ID: "));
157
  //print_hex( langid, 16 );
158
  rcode = Usb.getStrDescr( addr, 0, 1, idx, langid, buf );
159
  if( rcode ) {
160
    printProgStr(PSTR("\r\nError retrieving string length"));
161
    return( rcode );
162
  }
163
  length = ( buf[ 0 ] < 254 ? buf[ 0 ] : 254 );
164
  printProgStr(PSTR(" Length: "));
165
  Serial.print( length, DEC );
166
  rcode = Usb.getStrDescr( addr, 0, length, idx, langid, buf );
167
  if( rcode ) {
168
    printProgStr(PSTR("\r\nError retrieveing string"));
169
    return( rcode );
170
  }
171
  printProgStr(PSTR(" Contents: "));
172
  for( i = 2; i < length; i+=2 ) {
173
    Serial.print( buf[ i ] );
174
  }
175
  return( idx );
176
}
177
/* Returns string to class name */
178
const char* classname_parse( byte class_number )
179
{
180
  switch( class_number ) {
181
    case 0x00:
182
      return PSTR(" Use class information in the Interface Descriptor");
183
    case 0x01:
184
      return PSTR(" Audio");
185
    case 0x02:
186
      return PSTR(" Communications and CDC Control");
187
    case 0x03:
188
      return PSTR(" HID (Human Interface Device)");
189
    case 0x05:
190
      return PSTR(" Physical");
191
    case 0x06:
192
      return PSTR(" Image");
193
    case 0x07:
194
      return PSTR(" Printer");
195
    case 0x08:
196
      return PSTR(" Mass Storage");
197
    case 0x09:
198
      return PSTR(" Hub");
199
    case 0x0a:
200
      return PSTR(" CDC-Data");
201
    case 0x0b:
202
      return PSTR(" Smart Card");
203
    case 0x0d:
204
      return PSTR(" Content Security");
205
    case 0x0e:
206
      return PSTR(" Video");
207
    case 0x0f:
208
      return PSTR(" Personal Healthcare");
209
    case 0xdc:
210
      return PSTR("Diagnostic Device");
211
    case 0xe0:
212
      return PSTR(" Wireless Controller");
213
    case 0xef:
214
      return PSTR(" Miscellaneous");
215
    case 0xfe:
216
      return PSTR(" Application Specific");
217
    case 0xff:
218
      return PSTR(" Vendor Specific");
219
    default:
220
      return unk_msg;
221
  }//switch( class_number
222
}
223
/* Getting configuration descriptor */
224
byte getconfdescr( byte addr, byte conf )
225
{
226
  char buf[ BUFSIZE ];
227
  char* buf_ptr = buf;
228
  byte rcode;
229
  byte descr_length;
230
  byte descr_type;
231
  unsigned int total_length;
232
  printProgStr(PSTR("\r\n\nConfiguration number "));
233
  Serial.print( conf, HEX );
234
  rcode = Usb.getConfDescr( addr, 0, 4, conf, buf );  //get total length
235
  if( rcode ) {
236
    printProgStr(PSTR("Error retrieving configuration length. Error code "));
237
    Serial.println( rcode, HEX );
238
    return( 0 );
239
  }//if( rcode
240
  LOBYTE( total_length ) = buf[ 2 ];
241
  HIBYTE( total_length ) = buf[ 3 ];
242
  printProgStr(PSTR("\r\nTotal configuration length: "));
243
  Serial.print( total_length, DEC );
244
  printProgStr(PSTR(" bytes"));
245
  if( total_length > BUFSIZE ) {    //check if total length is larger than buffer
246
    printProgStr(PSTR("Total length truncated to "));
247
    Serial.print( BUFSIZE, DEC);
248
    printProgStr(PSTR("bytes"));
249
    total_length = BUFSIZE;
250
  }
251
  rcode = Usb.getConfDescr( addr, 0, total_length, conf, buf ); //get the whole descriptor
252
  while( buf_ptr < buf + total_length ) {  //parsing descriptors
253
    descr_length = *( buf_ptr );
254
    descr_type = *( buf_ptr + 1 );
255
    switch( descr_type ) {
256
      case( USB_DESCRIPTOR_CONFIGURATION ):
257
        printconfdescr( buf_ptr );
258
        break;
259
      case( USB_DESCRIPTOR_INTERFACE ):
260
        printintfdescr( buf_ptr );
261
        break;
262
      case( USB_DESCRIPTOR_ENDPOINT ):
263
        printepdescr( buf_ptr );
264
        break;
265
      case( HID_DESCRIPTOR_HID ):
266
        printhid_descr( buf_ptr );
267
        break;
268
      default:
269
        printunkdescr( buf_ptr );
270
        break;
271
        }//switch( descr_type
272
    Serial.println("");
273
    buf_ptr = ( buf_ptr + descr_length );    //advance buffer pointer
274
  }//while( buf_ptr <=...
275
  return( 0 );
276
}
277
/* function to print configuration descriptor */
278
void printconfdescr( char* descr_ptr )
279
{
280
 USB_CONFIGURATION_DESCRIPTOR* conf_ptr = ( USB_CONFIGURATION_DESCRIPTOR* )descr_ptr;
281
 uint8_t tmpbyte;
282
  printProgStr(PSTR("\r\n\nConfiguration descriptor:"));
283
  printProgStr(PSTR("\r\nTotal length:\t\t"));
284
  print_hex( conf_ptr->wTotalLength, 16 );
285
  printProgStr(PSTR("\r\nNumber of interfaces:\t"));
286
  print_hex( conf_ptr->bNumInterfaces, 8 );
287
  printProgStr(PSTR("\r\nConfiguration value:\t"));
288
  print_hex( conf_ptr->bConfigurationValue, 8 );
289
  printProgStr(PSTR("\r\nConfiguration string:\t"));
290
  tmpbyte = conf_ptr->iConfiguration;
291
  print_hex( tmpbyte, 8 );
292
  getstrdescr( DEVADDR, tmpbyte );
293
  printProgStr(PSTR("\r\nAttributes:\t\t"));
294
  tmpbyte = conf_ptr->bmAttributes;
295
  print_hex( tmpbyte, 8 );
296
  if( tmpbyte & 0x40 ) {  //D6
297
    printProgStr(PSTR(" Self-powered"));
298
  }
299
  if( tmpbyte & 0x20 ) { //D5
300
    printProgStr(PSTR(" Remote Wakeup"));
301
  }
302
  printProgStr(PSTR("\r\nMax.power:\t\t"));
303
  tmpbyte = conf_ptr->bMaxPower;
304
  print_hex( tmpbyte, 8 );
305
  printProgStr(PSTR(" "));
306
  Serial.print(( tmpbyte * 2 ), DEC);
307
  printProgStr(PSTR("ma"));
308
  return;
309
}
310
/* function to print interface descriptor */
311
void printintfdescr( char* descr_ptr )
312
{
313
 USB_INTERFACE_DESCRIPTOR* intf_ptr = ( USB_INTERFACE_DESCRIPTOR* )descr_ptr;
314
 uint8_t tmpbyte;
315
  printProgStr(PSTR("\r\nInterface descriptor:"));
316
  printProgStr(PSTR("\r\nInterface number:\t"));
317
  print_hex( intf_ptr->bInterfaceNumber, 8 );
318
  printProgStr(PSTR("\r\nAlternate setting:\t"));
319
  print_hex( intf_ptr->bAlternateSetting, 8 );
320
  printProgStr(PSTR("\r\nEndpoints:\t\t"));
321
  print_hex( intf_ptr->bNumEndpoints, 8 );
322
  printProgStr( class_str );
323
  tmpbyte = intf_ptr->bInterfaceClass;
324
  print_hex( tmpbyte, 8 );
325
  printProgStr(classname_parse( tmpbyte ));
326
  printProgStr( subclass_str );
327
  print_hex( intf_ptr->bInterfaceSubClass, 8 );
328
  printProgStr( protocol_str );
329
  print_hex( intf_ptr->bInterfaceProtocol, 8 );
330
  printProgStr(PSTR("\r\nInterface string:\t"));
331
  tmpbyte = intf_ptr->iInterface;
332
  print_hex( tmpbyte, 8 );
333
  getstrdescr( DEVADDR, tmpbyte );
334
  return;
335
}
336
/* function to print endpoint descriptor */
337
void printepdescr( char* descr_ptr )
338
{
339
 USB_ENDPOINT_DESCRIPTOR* ep_ptr = ( USB_ENDPOINT_DESCRIPTOR* )descr_ptr;
340
 uint8_t tmpbyte;
341
  printProgStr(PSTR("\r\nEndpoint descriptor:"));
342
  printProgStr(PSTR("\r\nEndpoint address:\t"));
343
  tmpbyte = ep_ptr->bEndpointAddress;
344
  print_hex( tmpbyte & 0x0f, 8 );
345
  printProgStr(PSTR(" Direction: "));
346
  ( tmpbyte & 0x80 ) ? printProgStr(PSTR("IN")) : printProgStr(PSTR("OUT"));
347
  printProgStr(PSTR("\r\nAttributes:\t\t"));
348
  tmpbyte = ep_ptr->bmAttributes;
349
  print_hex( tmpbyte, 8 );
350
  printProgStr(PSTR(" Transfer type: "));
351
  printProgStr((char*)pgm_read_word(&transfer_types[(tmpbyte & 0x03)]));
352
  if(( tmpbyte & 0x03 ) == 1 ) {  //Isochronous Transfer
353
    printProgStr(PSTR(", Sync Type: "));
354
    printProgStr((char*)pgm_read_word(&sync_types[(tmpbyte & 0x0c)]));
355
    printProgStr(PSTR(", Usage Type: "));
356
    printProgStr((char*)pgm_read_word(&usage_types[(tmpbyte & 0x30)]));
357
  }//if( tmpbyte & 0x01
358
  printProgStr( maxpktsize_str );
359
  print_hex( ep_ptr->wMaxPacketSize, 16 );
360
  printProgStr(PSTR("\r\nPolling interval:\t"));
361
  tmpbyte = ep_ptr->bInterval;
362
  print_hex( tmpbyte, 8 );
363
  printProgStr(PSTR(" "));
364
  Serial.print( tmpbyte, DEC );
365
  printProgStr(PSTR(" ms"));
366
  return;
367
}
368
/* function to print HID descriptor */
369
void printhid_descr( char* descr_ptr )
370
{
371
 PARSE pf = &HIDreport_parse;
372
 USB_HID_DESCRIPTOR* hid_ptr = ( USB_HID_DESCRIPTOR* )descr_ptr;
373
 uint8_t tmpbyte;
374
  /**/
375
  printProgStr(PSTR("\r\nHID descriptor:"));
376
  printProgStr(PSTR("\r\nDescriptor length:\t"));
377
  tmpbyte = hid_ptr->bLength;
378
  print_hex( tmpbyte, 8 );
379
  printProgStr(PSTR(" "));
380
  Serial.print( tmpbyte, DEC );
381
  printProgStr(PSTR(" bytes"));
382
  printProgStr(PSTR("\r\nHID version:\t\t"));
383
  Serial.print(( HIBYTE( hid_ptr->bcdHID )), HEX );
384
  Serial.print(".");
385
  Serial.print(( LOBYTE( hid_ptr->bcdHID )), HEX );
386
  tmpbyte = hid_ptr->bCountryCode;
387
  printProgStr(PSTR("\r\nCountry Code:\t\t"));
388
  Serial.print( tmpbyte, DEC );
389
  printProgStr(PSTR(" "));
390
  ( tmpbyte > 35 ) ? printProgStr(PSTR("Reserved")) : printProgStr((char*)pgm_read_word(&HID_Country_Codes[ tmpbyte ]));
391
  tmpbyte = hid_ptr->bNumDescriptors;
392
  printProgStr(PSTR("\r\nClass Descriptors:\t"));
393
  Serial.print( tmpbyte, DEC );
394
  //Printing class descriptors
395
  descr_ptr += 6; //advance buffer pointer
396
  for( uint8_t i = 0; i < tmpbyte; i++ ) {
397
    uint8_t tmpdata;
398
    HID_CLASS_DESCRIPTOR* hidclass_ptr = ( HID_CLASS_DESCRIPTOR* )descr_ptr;
399
    tmpdata = hidclass_ptr->bDescriptorType;
400
    printProgStr(PSTR("\r\nClass Descriptor Type:\t"));
401
    Serial.print( tmpdata, HEX );
402
    if(( tmpdata < 0x21 ) || ( tmpdata > 0x2f )) {
403
     printProgStr(PSTR(" Invalid"));
404
    }
405
    switch( tmpdata ) {
406
      case 0x21:
407
        printProgStr(PSTR(" HID"));
408
        break;
409
      case 0x22:
410
        printProgStr(PSTR(" Report"));
411
        break;
412
      case 0x23:
413
        printProgStr(PSTR(" Physical"));
414
        break;
415
      default:
416
        printProgStr(PSTR(" Reserved"));
417
        break;
418
    }//switch( tmpdata
419
    printProgStr(PSTR("\r\nClass Descriptor Length:"));
420
    Serial.print( hidclass_ptr->wDescriptorLength );
421
    printProgStr(PSTR(" bytes"));
422
    printProgStr(PSTR("\r\n\nHID report descriptor:\r\n"));
423
    getReportDescr( DEVADDR, 0 , hidclass_ptr->wDescriptorLength, pf, USB_NAK_LIMIT );
424
    descr_ptr += 3; //advance to the next record
425
  }//for( uint8_t i=...
426
  return;
427
}
428
/*function to print unknown descriptor */
429
void printunkdescr( char* descr_ptr )
430
{
431
  byte length = *descr_ptr;
432
  byte i;
433
  printProgStr(PSTR("\r\nUnknown descriptor:"));
434
  printProgStr(PSTR("Length:\t\t"));
435
  print_hex( *descr_ptr, 8 );
436
  printProgStr(PSTR("\r\nType:\t\t"));
437
  print_hex( *(descr_ptr + 1 ), 8 );
438
  printProgStr(PSTR("\r\nContents:\t"));
439
  descr_ptr += 2;
440
  for( i = 0; i < length; i++ ) {
441
    print_hex( *descr_ptr, 8 );
442
    descr_ptr++;
443
  }
444
}
445
/* Control-IN transfer with callback. Sets address, endpoint, fills control packet with necessary data, dispatches control packet, and initiates bulk IN transfer   */
446
/* 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   */
447
/* data read and MAX3421E RECV FIFO buffer release shall be performed by parse_func callback */
448
/* return codes:                */
449
/* 00       =   success         */
450
/* 01-0f    =   non-zero HRSLT  */
451
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 )
452
{
453
 byte rcode;
454
 SETUP_PKT sp;
455
 EP_RECORD* ep_rec = Usb.getDevTableEntry( addr, ep );
456
 byte pktsize;
457
 byte maxpktsize = ep_rec->MaxPktSize;
458
 unsigned int xfrlen = 0;
459
  /**/
460
  Max.regWr( rPERADDR, addr );                    //set peripheral address
461
  /* fill in setup packet */
462
  sp.ReqType_u.bmRequestType = bmReqType;
463
  sp.bRequest = bRequest;
464
  sp.wVal_u.wValueLo = wValLo;
465
  sp.wVal_u.wValueHi = wValHi;
466
  sp.wIndex = wInd;
467
  sp.wLength = nbytes;
468
  Max.bytesWr( rSUDFIFO, 8, ( char *)&sp );    //transfer to setup packet FIFO
469
  rcode = Usb.dispatchPkt( tokSETUP, ep, nak_limit );            //dispatch packet
470
  //Serial.println("Setup packet");   //DEBUG
471
  if( rcode ) {                                   //return HRSLT if not zero
472
      printProgStr(PSTR("\r\nSetup packet error: "));
473
      Serial.print( rcode, HEX );
474
      return( rcode );
475
  }
476
  /* Data stage */
477
  //ep_rec->rcvToggle = bmRCVTOG1;
478
  Max.regWr( rHCTL, bmRCVTOG1 );  //set toggle
479
  while( 1 ) {                    //exited by break
480
    /* request data */
481
    rcode = Usb.dispatchPkt( tokIN, ep, nak_limit );
482
    if( rcode ) {
483
      printProgStr(PSTR("\r\nData Stage Error: "));
484
      Serial.print( rcode, HEX );
485
      return( rcode );
486
    }
487
    /* check for RCVDAVIRQ and generate error if not present */
488
    /* the only case when absense of RCVDAVIRQ makes sense is when toggle error occured. Need to add handling for that */
489
    if(( Max.regRd( rHIRQ ) & bmRCVDAVIRQ ) == 0 ) {
490
      printProgStr(PSTR("\r\nData Toggle error."));
491
      return ( 0xf0 );
492
    }
493
    pktsize = Max.regRd( rRCVBC );  //get received bytes count
494
    parse_func( pktsize );          //call parse function. Parse is expected to read the FIFO completely
495
    Max.regWr( rHIRQ, bmRCVDAVIRQ );                    // Clear the IRQ & free the buffer
496
    xfrlen += pktsize;                              // add this packet's byte count to total transfer length
497
    /* The transfer is complete under two conditions:           */
498
    /* 1. The device sent a short packet (L.T. maxPacketSize)   */
499
    /* 2. 'nbytes' have been transferred.                       */
500
    if (( pktsize < maxpktsize ) || (xfrlen >= nbytes )) {      // have we transferred 'nbytes' bytes?
501
      break;
502
    }
503
  }//while( 1 )
504
  rcode = Usb.dispatchPkt( tokOUTHS, ep, nak_limit );
505
  if( rcode ) {   //return error
506
    printProgStr(PSTR("Status packet error: "));
507
    Serial.print( rcode, HEX );
508
  }
509
  return( rcode );
510
}
511
/* Parses bitfields in main items */
512
void print_mainbitfield( uint8_t byte_toparse )
513
{
514
  ( byte_toparse & 0x01 ) ? printProgStr(PSTR("Constant,")) : printProgStr(PSTR("Data,"));  //bit 0
515
  ( byte_toparse & 0x02 ) ? printProgStr(PSTR("Variable,")) : printProgStr(PSTR("Array,"));  //bit 1
516
  ( byte_toparse & 0x04 ) ? printProgStr(PSTR("Relative,")) : printProgStr(PSTR("Absolute,"));  //...
517
  ( byte_toparse & 0x08 ) ? printProgStr(PSTR("Wrap,")) : printProgStr(PSTR("No Wrap,"));
518
  ( byte_toparse & 0x10 ) ? printProgStr(PSTR("Non Linear,")) : printProgStr(PSTR("Linear,"));
519
  ( byte_toparse & 0x20 ) ? printProgStr(PSTR("No preferred,")) : printProgStr(PSTR("Preferred State,"));
520
  ( byte_toparse & 0x40 ) ? printProgStr(PSTR("Null State,")) : printProgStr(PSTR("No Null Position,"));  //bit 6
521
  ( byte_toparse & 0x40 ) ? printProgStr(PSTR("Volatile( ignore for Input),")) : printProgStr(PSTR("Non-volatile(Ignore for Input),"));  //bit 7
522
}
523
/* HID Report Desriptor Parser Callback             */
524
/* called repeatedly from Control transfer function */
525
void HIDreport_parse( uint8_t pkt_size )
526
{
527
#define B_SIZE 0x03        //bSize bitmask
528
#define B_TYPE 0x0c        //bType bitmask
529
#define B_TAG  0xf0        //bTag bitmask
530
 /* parser states */
531
 enum STATE { ITEM_START, DATA_PARSE };
532
 static STATE state = ITEM_START;
533
 static uint8_t databytes_left = 0;
534
 static uint8_t prefix;              //item prefix - type and tag
535
 uint8_t byte_toparse;
536
 uint8_t bType;
537
 uint8_t tmpbyte;
538
 /**/
539
  while( 1 ) {
540
     if( pkt_size ) {
541
       byte_toparse = Max.regRd( rRCVFIFO );  //read a byte from FIFO
542
       pkt_size--;
543
     }
544
     else {
545
       return;                                //all bytes read
546
     }
547
     switch( state ) {
548
      case ITEM_START:  //start of the record
549
        prefix = byte_toparse >>2;        //store prefix for databyte parsing
550
        tmpbyte = byte_toparse & B_SIZE;
551
        /* get item length */
552
        ( tmpbyte == 0x03 ) ? databytes_left = 4 : databytes_left = tmpbyte;
553
         if( databytes_left ) {
554
           state = DATA_PARSE;    //read bytes after prefix
555
         }
556
         printProgStr(PSTR("\r\nLength: "));
557
         Serial.print( databytes_left, DEC );
558
         /* get item type */
559
         bType = ( byte_toparse & B_TYPE ) >>2;
560
         printProgStr(PSTR("  Type: "));
561
         printProgStr((char*)pgm_read_word(&btypes[ bType ]));
562
         /* get item tag */
563
         printProgStr(PSTR("\t\tTag: "));
564
         tmpbyte = ( byte_toparse & B_TAG ) >>4 ;
565
         switch( bType ) {
566
           case 0:  //Main
567
             if( tmpbyte < 0x08 ) {
568
               printProgStr(PSTR("Invalid Tag"));
569
             }
570
             else if( tmpbyte > 0x0c ) {
571
               printProgStr( reserved_msg );
572
             }
573
             else {
574
               printProgStr((char*)pgm_read_word(&maintags[ tmpbyte - 8 /* & 0x03 */]));
575
               //Serial.print("Byte: ");
576
               //Serial.println( tmpbyte, HEX );
577
             }
578
             break;//case 0 Main
579
           case 1:  //Global
580
             ( tmpbyte > 0x0b ) ? printProgStr( reserved_msg ) : printProgStr((char*)pgm_read_word(&globaltags[ tmpbyte ]));
581
             break;//case 1 Global
582
           case 2:  //Local
583
             ( tmpbyte > 0x0a ) ? printProgStr( reserved_msg ) : printProgStr((char*)pgm_read_word(&localtags[ tmpbyte ]));
584
             break;//case 2 Local
585
           default:
586
             break;
587
         }//switch( bType...
588
         break;//case ITEM_START
589
       case DATA_PARSE:
590
         switch( prefix ) {
591
           case 0x20:  //Main Input
592
           case 0x24:  //Main Output
593
           case 0x2c:  //Main Feature
594
             /* todo: add parsing 8th bit */
595
             print_mainbitfield( byte_toparse );
596
             break;
597
           case 0x28:    //Main Collection
598
             if(( byte_toparse > 0x06 ) && ( byte_toparse < 0x80 )) {
599
               printProgStr( reserved_msg );
600
             }
601
             else if(( byte_toparse > 0x7f ) && ( byte_toparse <= 0xff )) {
602
               printProgStr(PSTR("Vendor-defined"));
603
             }
604
             else {
605
               printProgStr((char*)pgm_read_word(&collections[ byte_toparse ]));
606
             }
607
             break;//case 0x28 Main Collection
608
           //case 0x30: //Main End Collection
609
           case 0x01:    //Global Usage Page
610
             switch( byte_toparse ) {  //see HID Usage Tables doc v.1.12 page 14
611
               case 0x00:
612
               case 0x01:
613
               case 0x02:
614
               case 0x03:
615
               case 0x04:
616
               case 0x05:
617
               case 0x06:
618
               case 0x07:
619
               case 0x08:
620
               case 0x09:
621
               case 0x0a:
622
               case 0x0b:
623
               case 0x0c:
624
               case 0x0d:
625
               case 0x0e:
626
               case 0x0f:
627
               case 0x10:
628
                 printProgStr((char*)pgm_read_word(&usage_pages[ byte_toparse ]));
629
                 break;
630
               case 0x14:
631
                 printProgStr(PSTR("Alphanumeric Display"));
632
                 break;
633
               case 0x40:
634
                 printProgStr(PSTR("Medical Instruments"));
635
                 break;
636
               case 0x80:
637
               case 0x81:
638
               case 0x82:
639
               case 0x83:
640
                 printProgStr(PSTR("Monitor page"));
641
                 break;
642
               case 0x84:
643
               case 0x85:
644
               case 0x86:
645
               case 0x87:
646
                 printProgStr(PSTR("Power page"));
647
                 break;
648
               case 0x8c:
649
                 printProgStr(PSTR("Bar Code Scanner page"));
650
                 break;
651
               case 0x8d:
652
                 printProgStr(PSTR("Scale page"));
653
                 break;
654
               case 0x8e:
655
                 printProgStr(PSTR("Magnetic Stripe Reading (MSR) Devices"));
656
                 break;
657
               case 0x8f:
658
                 printProgStr(PSTR("Reserved Point of Sale pages"));
659
                 break;
660
               case 0x90:
661
                 printProgStr(PSTR("Camera Control Page"));
662
                 break;
663
               case 0x91:
664
                 printProgStr(PSTR("Arcade Page"));
665
                 break;
666
             default:
667
//               printProgStr(PSTR("Data: "));
668
//               print_hex( byte_toparse, 8 );
669
               //databytes_left--;
670
               break;
671
             }//switch case 0x01:    //Global Usage Page
672
         }//switch( prefix ...
673
         printProgStr(PSTR("  Data: "));
674
         print_hex( byte_toparse, 8 );
675
         databytes_left--;
676
         if( !databytes_left ) {
677
           state = ITEM_START;
678
         }
679
         break;
680
     }//switch( state...
681
   }//while( 1 ...
682
}
683
/* prints hex numbers with leading zeroes */
684
// copyright, Peter H Anderson, Baltimore, MD, Nov, '07
685
// source: http://www.phanderson.com/arduino/arduino_display.html
686
void print_hex(int v, int num_places)
687
{
688
  int mask=0, n, num_nibbles, digit;
689
 
690
  for (n=1; n<=num_places; n++) {
691
    mask = (mask << 1) | 0x0001;
692
  }
693
  v = v & mask; // truncate v to specified number of places
694
 
695
  num_nibbles = num_places / 4;
696
  if ((num_places % 4) != 0) {
697
    ++num_nibbles;
698
  }
699
  do {
700
    digit = ((v >> (num_nibbles-1) * 4)) & 0x0f;
701
    Serial.print(digit, HEX);
702
  }
703
  while(--num_nibbles);
704
}
705
 
706
/* given a PROGMEM string, use Serial.print() to send it out       */
707
/* Some non-intuitive casting necessary:                           */
708
/* printProgStr(PSTR("Func.Mode:\t0x"));                           */
709
/* printProgStr((char*)pgm_read_word(&mtpopNames[(op & 0xFF)]));   */
710
void printProgStr(const char* str)
711
{
712
  if(!str) {
713
    return;
714
  }
715
  char c;
716
  while((c = pgm_read_byte(str++))) {
717
    Serial.print(c,BYTE);
718
  }
719
  return;
720
}