USB Host Shield 2.0
Usb.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
2 
3 This software may be distributed and modified under the terms of the GNU
4 General Public License version 2 (GPL2) as published by the Free Software
5 Foundation and appearing in the file GPL2.TXT included in the packaging of
6 this file. Please note that GPL2 Section 2[b] requires that all works based
7 on this software must also be made publicly available under the terms of
8 the GPL2 ("Copyleft").
9 
10 Contact information
11 -------------------
12 
13 Circuits At Home, LTD
14 Web : http://www.circuitsathome.com
15 e-mail : support@circuitsathome.com
16  */
17 /* USB functions */
18 
19 #include "Usb.h"
20 
21 static uint8_t usb_error = 0;
22 static uint8_t usb_task_state;
23 
24 /* constructor */
25 USB::USB() : bmHubPre(0) {
26  usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE; //set up state machine
27  init();
28 }
29 
30 /* Initialize data structures */
31 void USB::init() {
32  //devConfigIndex = 0;
33  bmHubPre = 0;
34 }
35 
36 uint8_t USB::getUsbTaskState(void) {
37  return ( usb_task_state);
38 }
39 
40 void USB::setUsbTaskState(uint8_t state) {
41  usb_task_state = state;
42 }
43 
44 EpInfo* USB::getEpInfoEntry(uint8_t addr, uint8_t ep) {
45  UsbDevice *p = addrPool.GetUsbDevicePtr(addr);
46 
47  if(!p || !p->epinfo)
48  return NULL;
49 
50  EpInfo *pep = p->epinfo;
51 
52  for(uint8_t i = 0; i < p->epcount; i++) {
53  if((pep)->epAddr == ep)
54  return pep;
55 
56  pep++;
57  }
58  return NULL;
59 }
60 
61 /* set device table entry */
62 
63 /* each device is different and has different number of endpoints. This function plugs endpoint record structure, defined in application, to devtable */
64 uint8_t USB::setEpInfoEntry(uint8_t addr, uint8_t epcount, EpInfo* eprecord_ptr) {
65  if(!eprecord_ptr)
67 
68  UsbDevice *p = addrPool.GetUsbDevicePtr(addr);
69 
70  if(!p)
72 
73  p->address.devAddress = addr;
74  p->epinfo = eprecord_ptr;
75  p->epcount = epcount;
76 
77  return 0;
78 }
79 
80 uint8_t USB::SetAddress(uint8_t addr, uint8_t ep, EpInfo **ppep, uint16_t *nak_limit) {
81  UsbDevice *p = addrPool.GetUsbDevicePtr(addr);
82 
83  if(!p)
85 
86  if(!p->epinfo)
88 
89  *ppep = getEpInfoEntry(addr, ep);
90 
91  if(!*ppep)
93 
94  *nak_limit = (0x0001UL << (((*ppep)->bmNakPower > USB_NAK_MAX_POWER) ? USB_NAK_MAX_POWER : (*ppep)->bmNakPower));
95  *nak_limit--;
96  /*
97  USBTRACE2("\r\nAddress: ", addr);
98  USBTRACE2(" EP: ", ep);
99  USBTRACE2(" NAK Power: ",(*ppep)->bmNakPower);
100  USBTRACE2(" NAK Limit: ", nak_limit);
101  USBTRACE("\r\n");
102  */
103  regWr(rPERADDR, addr); //set peripheral address
104 
105  uint8_t mode = regRd(rMODE);
106 
107  //Serial.print("\r\nMode: ");
108  //Serial.println( mode, HEX);
109  //Serial.print("\r\nLS: ");
110  //Serial.println(p->lowspeed, HEX);
111 
112 
113 
114  // Set bmLOWSPEED and bmHUBPRE in case of low-speed device, reset them otherwise
115  regWr(rMODE, (p->lowspeed) ? mode | bmLOWSPEED | bmHubPre : mode & ~(bmHUBPRE | bmLOWSPEED));
116 
117  return 0;
118 }
119 
120 /* Control transfer. Sets address, endpoint, fills control packet with necessary data, dispatches control packet, and initiates bulk IN transfer, */
121 /* depending on request. Actual requests are defined as inlines */
122 /* return codes: */
123 /* 00 = success */
124 
125 /* 01-0f = non-zero HRSLT */
126 uint8_t USB::ctrlReq(uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi,
127  uint16_t wInd, uint16_t total, uint16_t nbytes, uint8_t* dataptr, USBReadParser *p) {
128  bool direction = false; //request direction, IN or OUT
129  uint8_t rcode;
130  SETUP_PKT setup_pkt;
131 
132  EpInfo *pep = NULL;
133  uint16_t nak_limit = 0;
134 
135  rcode = SetAddress(addr, ep, &pep, &nak_limit);
136 
137  if(rcode)
138  return rcode;
139 
140  direction = ((bmReqType & 0x80) > 0);
141 
142  /* fill in setup packet */
143  setup_pkt.ReqType_u.bmRequestType = bmReqType;
144  setup_pkt.bRequest = bRequest;
145  setup_pkt.wVal_u.wValueLo = wValLo;
146  setup_pkt.wVal_u.wValueHi = wValHi;
147  setup_pkt.wIndex = wInd;
148  setup_pkt.wLength = total;
149 
150  bytesWr(rSUDFIFO, 8, (uint8_t*) & setup_pkt); //transfer to setup packet FIFO
151 
152  rcode = dispatchPkt(tokSETUP, ep, nak_limit); //dispatch packet
153 
154  if(rcode) //return HRSLT if not zero
155  return ( rcode);
156 
157  if(dataptr != NULL) //data stage, if present
158  {
159  if(direction) //IN transfer
160  {
161  uint16_t left = total;
162 
163  pep->bmRcvToggle = 1; //bmRCVTOG1;
164 
165  while(left) {
166  // Bytes read into buffer
167  uint16_t read = nbytes;
168  //uint16_t read = (left<nbytes) ? left : nbytes;
169 
170  rcode = InTransfer(pep, nak_limit, &read, dataptr);
171  if(rcode == hrTOGERR) {
172  // yes, we flip it wrong here so that next time it is actually correct!
173  pep->bmRcvToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1;
174  continue;
175  }
176 
177  if(rcode)
178  return rcode;
179 
180  // Invoke callback function if inTransfer completed successfully and callback function pointer is specified
181  if(!rcode && p)
182  ((USBReadParser*)p)->Parse(read, dataptr, total - left);
183 
184  left -= read;
185 
186  if(read < nbytes)
187  break;
188  }
189  } else //OUT transfer
190  {
191  pep->bmSndToggle = 1; //bmSNDTOG1;
192  rcode = OutTransfer(pep, nak_limit, nbytes, dataptr);
193  }
194  if(rcode) //return error
195  return ( rcode);
196  }
197  // Status stage
198  return dispatchPkt((direction) ? tokOUTHS : tokINHS, ep, nak_limit); //GET if direction
199 }
200 
201 /* IN transfer to arbitrary endpoint. Assumes PERADDR is set. Handles multiple packets if necessary. Transfers 'nbytes' bytes. */
202 /* Keep sending INs and writes data to memory area pointed by 'data' */
203 
204 /* rcode 0 if no errors. rcode 01-0f is relayed from dispatchPkt(). Rcode f0 means RCVDAVIRQ error,
205  fe USB xfer timeout */
206 uint8_t USB::inTransfer(uint8_t addr, uint8_t ep, uint16_t *nbytesptr, uint8_t* data) {
207  EpInfo *pep = NULL;
208  uint16_t nak_limit = 0;
209 
210  uint8_t rcode = SetAddress(addr, ep, &pep, &nak_limit);
211 
212  if(rcode) {
213  USBTRACE3("(USB::InTransfer) SetAddress Failed ", rcode, 0x81);
214  USBTRACE3("(USB::InTransfer) addr requested ", addr, 0x81);
215  USBTRACE3("(USB::InTransfer) ep requested ", ep, 0x81);
216  return rcode;
217  }
218  return InTransfer(pep, nak_limit, nbytesptr, data);
219 }
220 
221 uint8_t USB::InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, uint8_t* data) {
222  uint8_t rcode = 0;
223  uint8_t pktsize;
224 
225  uint16_t nbytes = *nbytesptr;
226  //printf("Requesting %i bytes ", nbytes);
227  uint8_t maxpktsize = pep->maxPktSize;
228 
229  *nbytesptr = 0;
230  regWr(rHCTL, (pep->bmRcvToggle) ? bmRCVTOG1 : bmRCVTOG0); //set toggle value
231 
232  // use a 'break' to exit this loop
233  while(1) {
234  rcode = dispatchPkt(tokIN, pep->epAddr, nak_limit); //IN packet to EP-'endpoint'. Function takes care of NAKS.
235  if(rcode == hrTOGERR) {
236  // yes, we flip it wrong here so that next time it is actually correct!
237  pep->bmRcvToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1;
238  regWr(rHCTL, (pep->bmRcvToggle) ? bmRCVTOG1 : bmRCVTOG0); //set toggle value
239  continue;
240  }
241  if(rcode) {
242  //printf(">>>>>>>> Problem! dispatchPkt %2.2x\r\n", rcode);
243  break; //should be 0, indicating ACK. Else return error code.
244  }
245  /* check for RCVDAVIRQ and generate error if not present */
246  /* the only case when absence of RCVDAVIRQ makes sense is when toggle error occurred. Need to add handling for that */
247  if((regRd(rHIRQ) & bmRCVDAVIRQ) == 0) {
248  //printf(">>>>>>>> Problem! NO RCVDAVIRQ!\r\n");
249  rcode = 0xf0; //receive error
250  break;
251  }
252  pktsize = regRd(rRCVBC); //number of received bytes
253  //printf("Got %i bytes \r\n", pktsize);
254  // This would be OK, but...
255  //assert(pktsize <= nbytes);
256  if(pktsize > nbytes) {
257  // This can happen. Use of assert on Arduino locks up the Arduino.
258  // So I will trim the value, and hope for the best.
259  //printf(">>>>>>>> Problem! Wanted %i bytes but got %i.\r\n", nbytes, pktsize);
260  pktsize = nbytes;
261  }
262 
263  int16_t mem_left = (int16_t)nbytes - *((int16_t*)nbytesptr);
264 
265  if(mem_left < 0)
266  mem_left = 0;
267 
268  data = bytesRd(rRCVFIFO, ((pktsize > mem_left) ? mem_left : pktsize), data);
269 
270  regWr(rHIRQ, bmRCVDAVIRQ); // Clear the IRQ & free the buffer
271  *nbytesptr += pktsize; // add this packet's byte count to total transfer length
272 
273  /* The transfer is complete under two conditions: */
274  /* 1. The device sent a short packet (L.T. maxPacketSize) */
275  /* 2. 'nbytes' have been transferred. */
276  if((pktsize < maxpktsize) || (*nbytesptr >= nbytes)) // have we transferred 'nbytes' bytes?
277  {
278  // Save toggle value
279  pep->bmRcvToggle = ((regRd(rHRSL) & bmRCVTOGRD)) ? 1 : 0;
280  //printf("\r\n");
281  rcode = 0;
282  break;
283  } // if
284  } //while( 1 )
285  return ( rcode);
286 }
287 
288 /* OUT transfer to arbitrary endpoint. Handles multiple packets if necessary. Transfers 'nbytes' bytes. */
289 /* Handles NAK bug per Maxim Application Note 4000 for single buffer transfer */
290 
291 /* rcode 0 if no errors. rcode 01-0f is relayed from HRSL */
292 uint8_t USB::outTransfer(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* data) {
293  EpInfo *pep = NULL;
294  uint16_t nak_limit = 0;
295 
296  uint8_t rcode = SetAddress(addr, ep, &pep, &nak_limit);
297 
298  if(rcode)
299  return rcode;
300 
301  return OutTransfer(pep, nak_limit, nbytes, data);
302 }
303 
304 uint8_t USB::OutTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t nbytes, uint8_t *data) {
305  uint8_t rcode = hrSUCCESS, retry_count;
306  uint8_t *data_p = data; //local copy of the data pointer
307  uint16_t bytes_tosend, nak_count;
308  uint16_t bytes_left = nbytes;
309 
310  uint8_t maxpktsize = pep->maxPktSize;
311 
312  if(maxpktsize < 1 || maxpktsize > 64)
314 
315  unsigned long timeout = millis() + USB_XFER_TIMEOUT;
316 
317  regWr(rHCTL, (pep->bmSndToggle) ? bmSNDTOG1 : bmSNDTOG0); //set toggle value
318 
319  while(bytes_left) {
320  retry_count = 0;
321  nak_count = 0;
322  bytes_tosend = (bytes_left >= maxpktsize) ? maxpktsize : bytes_left;
323  bytesWr(rSNDFIFO, bytes_tosend, data_p); //filling output FIFO
324  regWr(rSNDBC, bytes_tosend); //set number of bytes
325  regWr(rHXFR, (tokOUT | pep->epAddr)); //dispatch packet
326  while(!(regRd(rHIRQ) & bmHXFRDNIRQ)); //wait for the completion IRQ
327  regWr(rHIRQ, bmHXFRDNIRQ); //clear IRQ
328  rcode = (regRd(rHRSL) & 0x0f);
329 
330  while(rcode && ((long)(millis() - timeout) < 0L)) {
331  switch(rcode) {
332  case hrNAK:
333  nak_count++;
334  if(nak_limit && (nak_count == nak_limit))
335  goto breakout;
336  //return ( rcode);
337  break;
338  case hrTIMEOUT:
339  retry_count++;
340  if(retry_count == USB_RETRY_LIMIT)
341  goto breakout;
342  //return ( rcode);
343  break;
344  case hrTOGERR:
345  // yes, we flip it wrong here so that next time it is actually correct!
346  pep->bmSndToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1;
347  regWr(rHCTL, (pep->bmSndToggle) ? bmSNDTOG1 : bmSNDTOG0); //set toggle value
348  break;
349  default:
350  goto breakout;
351  }//switch( rcode
352 
353  /* process NAK according to Host out NAK bug */
354  regWr(rSNDBC, 0);
355  regWr(rSNDFIFO, *data_p);
356  regWr(rSNDBC, bytes_tosend);
357  regWr(rHXFR, (tokOUT | pep->epAddr)); //dispatch packet
358  while(!(regRd(rHIRQ) & bmHXFRDNIRQ)); //wait for the completion IRQ
359  regWr(rHIRQ, bmHXFRDNIRQ); //clear IRQ
360  rcode = (regRd(rHRSL) & 0x0f);
361  }//while( rcode && ....
362  bytes_left -= bytes_tosend;
363  data_p += bytes_tosend;
364  }//while( bytes_left...
365 breakout:
366 
367  pep->bmSndToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 1 : 0; //bmSNDTOG1 : bmSNDTOG0; //update toggle
368  return ( rcode); //should be 0 in all cases
369 }
370 /* dispatch USB packet. Assumes peripheral address is set and relevant buffer is loaded/empty */
371 /* If NAK, tries to re-send up to nak_limit times */
372 /* If nak_limit == 0, do not count NAKs, exit after timeout */
373 /* If bus timeout, re-sends up to USB_RETRY_LIMIT times */
374 
375 /* return codes 0x00-0x0f are HRSLT( 0x00 being success ), 0xff means timeout */
376 uint8_t USB::dispatchPkt(uint8_t token, uint8_t ep, uint16_t nak_limit) {
377  unsigned long timeout = millis() + USB_XFER_TIMEOUT;
378  uint8_t tmpdata;
379  uint8_t rcode = hrSUCCESS;
380  uint8_t retry_count = 0;
381  uint16_t nak_count = 0;
382 
383  while((long)(millis() - timeout) < 0L) {
384  regWr(rHXFR, (token | ep)); //launch the transfer
386 
387  while((long)(millis() - timeout) < 0L) //wait for transfer completion
388  {
389  tmpdata = regRd(rHIRQ);
390 
391  if(tmpdata & bmHXFRDNIRQ) {
392  regWr(rHIRQ, bmHXFRDNIRQ); //clear the interrupt
393  rcode = 0x00;
394  break;
395  }//if( tmpdata & bmHXFRDNIRQ
396 
397  }//while ( millis() < timeout
398 
399  //if (rcode != 0x00) //exit if timeout
400  // return ( rcode);
401 
402  rcode = (regRd(rHRSL) & 0x0f); //analyze transfer result
403 
404  switch(rcode) {
405  case hrNAK:
406  nak_count++;
407  if(nak_limit && (nak_count == nak_limit))
408  return (rcode);
409  break;
410  case hrTIMEOUT:
411  retry_count++;
412  if(retry_count == USB_RETRY_LIMIT)
413  return (rcode);
414  break;
415  default:
416  return (rcode);
417  }//switch( rcode
418 
419  }//while( timeout > millis()
420  return ( rcode);
421 }
422 
423 /* USB main task. Performs enumeration/cleanup */
424 void USB::Task(void) //USB state machine
425 {
426  uint8_t rcode;
427  uint8_t tmpdata;
428  static unsigned long delay = 0;
429  //USB_DEVICE_DESCRIPTOR buf;
430  bool lowspeed = false;
431 
432  MAX3421E::Task();
433 
434  tmpdata = getVbusState();
435 
436  /* modify USB task state if Vbus changed */
437  switch(tmpdata) {
438  case SE1: //illegal state
439  usb_task_state = USB_DETACHED_SUBSTATE_ILLEGAL;
440  lowspeed = false;
441  break;
442  case SE0: //disconnected
443  if((usb_task_state & USB_STATE_MASK) != USB_STATE_DETACHED)
444  usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE;
445  lowspeed = false;
446  break;
447  case LSHOST:
448 
449  lowspeed = true;
450  //intentional fallthrough
451  case FSHOST: //attached
452  if((usb_task_state & USB_STATE_MASK) == USB_STATE_DETACHED) {
453  delay = millis() + USB_SETTLE_DELAY;
454  usb_task_state = USB_ATTACHED_SUBSTATE_SETTLE;
455  }
456  break;
457  }// switch( tmpdata
458 
459  for(uint8_t i = 0; i < USB_NUMDEVICES; i++)
460  if(devConfig[i])
461  rcode = devConfig[i]->Poll();
462 
463  switch(usb_task_state) {
465  init();
466 
467  for(uint8_t i = 0; i < USB_NUMDEVICES; i++)
468  if(devConfig[i])
469  rcode = devConfig[i]->Release();
470 
471  usb_task_state = USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE;
472  break;
473  case USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE: //just sit here
474  break;
475  case USB_DETACHED_SUBSTATE_ILLEGAL: //just sit here
476  break;
477  case USB_ATTACHED_SUBSTATE_SETTLE: //settle time for just attached device
478  if((long)(millis() - delay) >= 0L)
479  usb_task_state = USB_ATTACHED_SUBSTATE_RESET_DEVICE;
480  else break; // don't fall through
482  regWr(rHCTL, bmBUSRST); //issue bus reset
484  break;
486  if((regRd(rHCTL) & bmBUSRST) == 0) {
487  tmpdata = regRd(rMODE) | bmSOFKAENAB; //start SOF generation
488  regWr(rMODE, tmpdata);
489  usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_SOF;
490  //delay = millis() + 20; //20ms wait after reset per USB spec
491  }
492  break;
493  case USB_ATTACHED_SUBSTATE_WAIT_SOF: //todo: change check order
494  if(regRd(rHIRQ) & bmFRAMEIRQ) {
495  //when first SOF received _and_ 20ms has passed we can continue
496  /*
497  if (delay < millis()) //20ms passed
498  usb_task_state = USB_STATE_CONFIGURING;
499  */
500  usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET;
501  delay = millis() + 20;
502  }
503  break;
505  if((long)(millis() - delay) >= 0L) usb_task_state = USB_STATE_CONFIGURING;
506  else break; // don't fall through
508 
509  //Serial.print("\r\nConf.LS: ");
510  //Serial.println(lowspeed, HEX);
511 
512  rcode = Configuring(0, 0, lowspeed);
513 
514  if(rcode) {
516  usb_error = rcode;
517  usb_task_state = USB_STATE_ERROR;
518  }
519  } else
520  usb_task_state = USB_STATE_RUNNING;
521  break;
522  case USB_STATE_RUNNING:
523  break;
524  case USB_STATE_ERROR:
525  //MAX3421E::Init();
526  break;
527  } // switch( usb_task_state )
528 }
529 
530 uint8_t USB::DefaultAddressing(uint8_t parent, uint8_t port, bool lowspeed) {
531  //uint8_t buf[12];
532  uint8_t rcode;
533  UsbDevice *p0 = NULL, *p = NULL;
534 
535  // Get pointer to pseudo device with address 0 assigned
536  p0 = addrPool.GetUsbDevicePtr(0);
537 
538  if(!p0)
540 
541  if(!p0->epinfo)
543 
544  p0->lowspeed = (lowspeed) ? true : false;
545 
546  // Allocate new address according to device class
547  uint8_t bAddress = addrPool.AllocAddress(parent, false, port);
548 
549  if(!bAddress)
551 
552  p = addrPool.GetUsbDevicePtr(bAddress);
553 
554  if(!p)
556 
557  p->lowspeed = lowspeed;
558 
559  // Assign new address to the device
560  rcode = setAddr(0, 0, bAddress);
561 
562  if(rcode) {
563  addrPool.FreeAddress(bAddress);
564  bAddress = 0;
565  return rcode;
566  }
567  return 0;
568 };
569 
570 uint8_t USB::AttemptConfig(uint8_t driver, uint8_t parent, uint8_t port, bool lowspeed) {
571  //printf("AttemptConfig: parent = %i, port = %i\r\n", parent, port);
572  uint8_t retries = 0;
573 
574 again:
575  uint8_t rcode = devConfig[driver]->ConfigureDevice(parent, port, lowspeed);
577  if(parent == 0) {
578  // Send a bus reset on the root interface.
579  regWr(rHCTL, bmBUSRST); //issue bus reset
580  delay(102); // delay 102ms, compensate for clock inaccuracy.
581  } else {
582  // reset parent port
583  devConfig[parent]->ResetHubPort(port);
584  }
585  } else if(rcode == hrJERR && retries < 3) { // Some devices returns this when plugged in - trying to initialize the device again usually works
586  delay(100);
587  retries++;
588  goto again;
589  } else if(rcode)
590  return rcode;
591 
592  rcode = devConfig[driver]->Init(parent, port, lowspeed);
593  if(rcode == hrJERR && retries < 3) { // Some devices returns this when plugged in - trying to initialize the device again usually works
594  delay(100);
595  retries++;
596  goto again;
597  }
598  if(rcode) {
599  // Issue a bus reset, because the device may be in a limbo state
600  if(parent == 0) {
601  // Send a bus reset on the root interface.
602  regWr(rHCTL, bmBUSRST); //issue bus reset
603  delay(102); // delay 102ms, compensate for clock inaccuracy.
604  } else {
605  // reset parent port
606  devConfig[parent]->ResetHubPort(port);
607  }
608  }
609  return rcode;
610 }
611 
612 /*
613  * This is broken. We need to enumerate differently.
614  * It causes major problems with several devices if detected in an unexpected order.
615  *
616  *
617  * Oleg - I wouldn't do anything before the newly connected device is considered sane.
618  * i.e.(delays are not indicated for brevity):
619  * 1. reset
620  * 2. GetDevDescr();
621  * 3a. If ACK, continue with allocating address, addressing, etc.
622  * 3b. Else reset again, count resets, stop at some number (5?).
623  * 4. When max.number of resets is reached, toggle power/fail
624  * If desired, this could be modified by performing two resets with GetDevDescr() in the middle - however, from my experience, if a device answers to GDD()
625  * it doesn't need to be reset again
626  * New steps proposal:
627  * 1: get address pool instance. exit on fail
628  * 2: pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf). exit on fail.
629  * 3: bus reset, 100ms delay
630  * 4: set address
631  * 5: pUsb->setEpInfoEntry(bAddress, 1, epInfo), exit on fail
632  * 6: while (configurations) {
633  * for(each configuration) {
634  * for (each driver) {
635  * 6a: Ask device if it likes configuration. Returns 0 on OK.
636  * If successful, the driver configured device.
637  * The driver now owns the endpoints, and takes over managing them.
638  * The following will need codes:
639  * Everything went well, instance consumed, exit with success.
640  * Instance already in use, ignore it, try next driver.
641  * Not a supported device, ignore it, try next driver.
642  * Not a supported configuration for this device, ignore it, try next driver.
643  * Could not configure device, fatal, exit with fail.
644  * }
645  * }
646  * }
647  * 7: for(each driver) {
648  * 7a: Ask device if it knows this VID/PID. Acts exactly like 6a, but using VID/PID
649  * 8: if we get here, no driver likes the device plugged in, so exit failure.
650  *
651  */
652 uint8_t USB::Configuring(uint8_t parent, uint8_t port, bool lowspeed) {
653  //uint8_t bAddress = 0;
654  //printf("Configuring: parent = %i, port = %i\r\n", parent, port);
655  uint8_t devConfigIndex;
656  uint8_t rcode = 0;
657  uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)];
658  USB_DEVICE_DESCRIPTOR *udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR *>(buf);
659  UsbDevice *p = NULL;
660  EpInfo *oldep_ptr = NULL;
661  EpInfo epInfo;
662 
663  epInfo.epAddr = 0;
664  epInfo.maxPktSize = 8;
665  epInfo.epAttribs = 0;
666  epInfo.bmNakPower = USB_NAK_MAX_POWER;
667 
668  //delay(2000);
669  AddressPool &addrPool = GetAddressPool();
670  // Get pointer to pseudo device with address 0 assigned
671  p = addrPool.GetUsbDevicePtr(0);
672  if(!p) {
673  //printf("Configuring error: USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL\r\n");
675  }
676 
677  // Save old pointer to EP_RECORD of address 0
678  oldep_ptr = p->epinfo;
679 
680  // Temporary assign new pointer to epInfo to p->epinfo in order to
681  // avoid toggle inconsistence
682 
683  p->epinfo = &epInfo;
684 
685  p->lowspeed = lowspeed;
686  // Get device descriptor
687  rcode = getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf);
688 
689  // Restore p->epinfo
690  p->epinfo = oldep_ptr;
691 
692  if(rcode) {
693  //printf("Configuring error: Can't get USB_DEVICE_DESCRIPTOR\r\n");
694  return rcode;
695  }
696 
697  // to-do?
698  // Allocate new address according to device class
699  //bAddress = addrPool.AllocAddress(parent, false, port);
700 
701  uint16_t vid = udd->idVendor;
702  uint16_t pid = udd->idProduct;
703  uint8_t klass = udd->bDeviceClass;
704  uint8_t subklass = udd->bDeviceSubClass;
705  // Attempt to configure if VID/PID or device class matches with a driver
706  // Qualify with subclass too.
707  //
708  // VID/PID & class tests default to false for drivers not yet ported
709  // subclass defaults to true, so you don't have to define it if you don't have to.
710  //
711  for(devConfigIndex = 0; devConfigIndex < USB_NUMDEVICES; devConfigIndex++) {
712  if(!devConfig[devConfigIndex]) continue; // no driver
713  if(devConfig[devConfigIndex]->GetAddress()) continue; // consumed
714  if(devConfig[devConfigIndex]->DEVSUBCLASSOK(subklass) && (devConfig[devConfigIndex]->VIDPIDOK(vid, pid) || devConfig[devConfigIndex]->DEVCLASSOK(klass))) {
715  rcode = AttemptConfig(devConfigIndex, parent, port, lowspeed);
717  break;
718  }
719  }
720 
721  if(devConfigIndex < USB_NUMDEVICES) {
722  return rcode;
723  }
724 
725 
726  // blindly attempt to configure
727  for(devConfigIndex = 0; devConfigIndex < USB_NUMDEVICES; devConfigIndex++) {
728  if(!devConfig[devConfigIndex]) continue;
729  if(devConfig[devConfigIndex]->GetAddress()) continue; // consumed
730  if(devConfig[devConfigIndex]->DEVSUBCLASSOK(subklass) && (devConfig[devConfigIndex]->VIDPIDOK(vid, pid) || devConfig[devConfigIndex]->DEVCLASSOK(klass))) continue; // If this is true it means it must have returned USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED above
731  rcode = AttemptConfig(devConfigIndex, parent, port, lowspeed);
732 
733  //printf("ERROR ENUMERATING %2.2x\r\n", rcode);
735  // in case of an error dev_index should be reset to 0
736  // in order to start from the very beginning the
737  // next time the program gets here
738  //if (rcode != USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE)
739  // devConfigIndex = 0;
740  return rcode;
741  }
742  }
743  // if we get here that means that the device class is not supported by any of registered classes
744  rcode = DefaultAddressing(parent, port, lowspeed);
745 
746  return rcode;
747 }
748 
749 uint8_t USB::ReleaseDevice(uint8_t addr) {
750  if(!addr)
751  return 0;
752 
753  for(uint8_t i = 0; i < USB_NUMDEVICES; i++) {
754  if(!devConfig[i]) continue;
755  if(devConfig[i]->GetAddress() == addr)
756  return devConfig[i]->Release();
757  }
758  return 0;
759 }
760 
761 #if 1
762 //get device descriptor
763 
764 uint8_t USB::getDevDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr) {
765  return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, nbytes, dataptr, NULL));
766 }
767 //get configuration descriptor
768 
769 uint8_t USB::getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t* dataptr) {
770  return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, nbytes, dataptr, NULL));
771 }
772 
773 /* Requests Configuration Descriptor. Sends two Get Conf Descr requests. The first one gets the total length of all descriptors, then the second one requests this
774  total length. The length of the first request can be shorter ( 4 bytes ), however, there are devices which won't work unless this length is set to 9 */
775 uint8_t USB::getConfDescr(uint8_t addr, uint8_t ep, uint8_t conf, USBReadParser *p) {
776  const uint8_t bufSize = 64;
777  uint8_t buf[bufSize];
778  USB_CONFIGURATION_DESCRIPTOR *ucd = reinterpret_cast<USB_CONFIGURATION_DESCRIPTOR *>(buf);
779 
780  uint8_t ret = getConfDescr(addr, ep, 9, conf, buf);
781 
782  if(ret)
783  return ret;
784 
785  uint16_t total = ucd->wTotalLength;
786 
787  //USBTRACE2("\r\ntotal conf.size:", total);
788 
789  return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, total, bufSize, buf, p));
790 }
791 
792 //get string descriptor
793 
794 uint8_t USB::getStrDescr(uint8_t addr, uint8_t ep, uint16_t ns, uint8_t index, uint16_t langid, uint8_t* dataptr) {
795  return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, ns, ns, dataptr, NULL));
796 }
797 //set address
798 
799 uint8_t USB::setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr) {
800  uint8_t rcode = ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL);
801  //delay(2); //per USB 2.0 sect.9.2.6.3
802  delay(300); // Older spec says you should wait at least 200ms
803  return rcode;
804  //return ( ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL));
805 }
806 //set configuration
807 
808 uint8_t USB::setConf(uint8_t addr, uint8_t ep, uint8_t conf_value) {
809  return ( ctrlReq(addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL));
810 }
811 
812 #endif // defined(USB_METHODS_INLINE)
uint8_t getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t *dataptr)
Definition: Usb.cpp:769
uint8_t bmRcvToggle
Definition: address.h:41
virtual uint8_t Poll()
Definition: UsbCore.h:136
#define USB_ERROR_EP_NOT_FOUND_IN_TBL
Definition: UsbCore.h:87
#define bmHUBPRE
Definition: max3421e.h:165
#define USB_ATTACHED_SUBSTATE_WAIT_RESET
Definition: UsbCore.h:114
#define FSHOST
Definition: max3421e.h:30
#define rHCTL
Definition: max3421e.h:174
union SETUP_PKT::@31 wVal_u
EpInfo * epinfo
Definition: address.h:76
bool lowspeed
Definition: address.h:79
#define USB_ERROR_EPINFO_IS_NULL
Definition: UsbCore.h:83
uint8_t bmNakPower
Definition: address.h:42
EpInfo * getEpInfoEntry(uint8_t addr, uint8_t ep)
Definition: Usb.cpp:44
#define bmSOFKAENAB
Definition: max3421e.h:166
#define USB_DESCRIPTOR_STRING
Definition: usb_ch9.h:65
uint16_t wLength
Definition: UsbCore.h:185
#define USB_SETTLE_DELAY
Definition: UsbCore.h:97
#define USB_ATTACHED_SUBSTATE_SETTLE
Definition: UsbCore.h:110
uint8_t getVbusState(void)
Definition: usbhost.h:128
#define bmRCVTOGRD
Definition: max3421e.h:199
#define USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE
Definition: UsbCore.h:78
#define USB_RETRY_LIMIT
Definition: UsbCore.h:96
#define USB_REQUEST_GET_DESCRIPTOR
Definition: usb_ch9.h:37
#define USB_DESCRIPTOR_DEVICE
Definition: usb_ch9.h:63
#define bmRCVTOG1
Definition: max3421e.h:181
#define USB_ERROR_INVALID_MAX_PKT_SIZE
Definition: UsbCore.h:86
uint8_t setConf(uint8_t addr, uint8_t ep, uint8_t conf_value)
Definition: Usb.cpp:808
#define USB_STATE_DETACHED
Definition: UsbCore.h:106
#define USB_NUMDEVICES
Definition: UsbCore.h:99
#define rRCVBC
Definition: max3421e.h:40
#define hrJERR
Definition: max3421e.h:220
uint8_t setEpInfoEntry(uint8_t addr, uint8_t epcount, EpInfo *eprecord_ptr)
Definition: Usb.cpp:64
virtual uint8_t ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed)
Definition: UsbCore.h:128
uint8_t Task()
Definition: usbhost.h:482
#define hrSUCCESS
Definition: max3421e.h:207
#define USB_STATE_ERROR
Definition: UsbCore.h:119
uint8_t bmRequestType
Definition: UsbCore.h:166
#define bmSNDTOGRD
Definition: max3421e.h:200
uint8_t epAttribs
Definition: address.h:37
uint8_t ctrlReq(uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi, uint16_t wInd, uint16_t total, uint16_t nbytes, uint8_t *dataptr, USBReadParser *p)
Definition: Usb.cpp:126
#define USB_DESCRIPTOR_CONFIGURATION
Definition: usb_ch9.h:64
virtual UsbDevice * GetUsbDevicePtr(uint8_t addr)=0
#define bmHXFRDNIRQ
Definition: max3421e.h:146
uint8_t setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr)
Definition: Usb.cpp:799
USB(void)
Definition: Usb.cpp:25
#define USB_STATE_RUNNING
Definition: UsbCore.h:118
uint8_t epAddr
Definition: address.h:33
#define rRCVFIFO
Definition: max3421e.h:37
#define USB_NAK_MAX_POWER
Definition: address.h:27
virtual UsbDevice * GetUsbDevicePtr(uint8_t addr)
Definition: address.h:180
uint16_t wIndex
Definition: UsbCore.h:184
#define bmBUSRST
Definition: max3421e.h:176
#define tokOUT
Definition: max3421e.h:190
#define tokIN
Definition: max3421e.h:189
#define LSHOST
Definition: max3421e.h:31
#define USB_XFER_TIMEOUT
Definition: UsbCore.h:94
Definition: address.h:32
#define rMODE
Definition: max3421e.h:160
void setUsbTaskState(uint8_t state)
Definition: Usb.cpp:40
uint8_t outTransfer(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t *data)
Definition: Usb.cpp:292
#define hrNAK
Definition: max3421e.h:211
#define bmREQ_GET_DESCR
Definition: UsbCore.h:47
#define rSNDBC
Definition: max3421e.h:41
#define rHRSL
Definition: max3421e.h:196
#define USB_ATTACHED_SUBSTATE_RESET_DEVICE
Definition: UsbCore.h:111
uint8_t * bytesRd(uint8_t reg, uint8_t nbytes, uint8_t *data_p)
Definition: usbhost.h:283
#define tokINHS
Definition: max3421e.h:191
#define bmLOWSPEED
Definition: max3421e.h:164
virtual void ResetHubPort(uint8_t port)
Definition: UsbCore.h:144
uint8_t * bytesWr(uint8_t reg, uint8_t nbytes, uint8_t *data_p)
Definition: usbhost.h:191
uint8_t getStrDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t index, uint16_t langid, uint8_t *dataptr)
Definition: Usb.cpp:794
#define USB_REQUEST_SET_ADDRESS
Definition: usb_ch9.h:36
#define tokSETUP
Definition: max3421e.h:188
#define rHXFR
Definition: max3421e.h:185
#define rHIRQ
Definition: max3421e.h:137
uint8_t bmSndToggle
Definition: address.h:40
#define rSNDFIFO
Definition: max3421e.h:38
#define USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE
Definition: UsbCore.h:85
uint8_t devAddress
Definition: address.h:67
#define tokOUTHS
Definition: max3421e.h:192
uint8_t getUsbTaskState(void)
Definition: Usb.cpp:36
#define USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL
Definition: UsbCore.h:82
uint8_t inTransfer(uint8_t addr, uint8_t ep, uint16_t *nbytesptr, uint8_t *data)
Definition: Usb.cpp:206
#define USB_STATE_MASK
Definition: UsbCore.h:104
#define USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED
Definition: UsbCore.h:77
union SETUP_PKT::@30 ReqType_u
void Task(void)
Definition: Usb.cpp:424
#define USB_DETACHED_SUBSTATE_ILLEGAL
Definition: UsbCore.h:109
#define hrTIMEOUT
Definition: max3421e.h:221
#define rPERADDR
Definition: max3421e.h:172
#define bmRCVDAVIRQ
Definition: max3421e.h:141
#define USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE
Definition: UsbCore.h:112
void regWr(uint8_t reg, uint8_t data)
Definition: usbhost.h:153
#define bmRCVTOG0
Definition: max3421e.h:180
uint8_t epcount
Definition: address.h:78
#define USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL
Definition: UsbCore.h:80
#define USB_STATE_CONFIGURING
Definition: UsbCore.h:117
uint8_t dispatchPkt(uint8_t token, uint8_t ep, uint16_t nak_limit)
Definition: Usb.cpp:376
virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed)
Definition: UsbCore.h:124
#define bmSNDTOG0
Definition: max3421e.h:182
uint8_t regRd(uint8_t reg)
Definition: usbhost.h:249
uint8_t maxPktSize
Definition: address.h:34
AddressPool & GetAddressPool()
Definition: UsbCore.h:213
#define USB_ERROR_INVALID_ARGUMENT
Definition: UsbCore.h:84
uint8_t Configuring(uint8_t parent, uint8_t port, bool lowspeed)
Definition: Usb.cpp:652
#define USBTRACE3(s, r, l)
Definition: macros.h:78
uint8_t bRequest
Definition: UsbCore.h:174
#define SE0
Definition: max3421e.h:28
virtual void FreeAddress(uint8_t addr)
Definition: address.h:254
virtual uint8_t Release()
Definition: UsbCore.h:132
#define bmFRAMEIRQ
Definition: max3421e.h:145
#define hrTOGERR
Definition: max3421e.h:213
#define SE1
Definition: max3421e.h:29
#define rSUDFIFO
Definition: max3421e.h:39
virtual uint8_t AllocAddress(uint8_t parent, bool is_hub=false, uint8_t port=0)
Definition: address.h:202
#define bmREQ_SET
Definition: UsbCore.h:48
UsbDeviceAddress address
Definition: address.h:77
#define USB_REQUEST_SET_CONFIGURATION
Definition: usb_ch9.h:40
#define USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE
Definition: UsbCore.h:108
uint8_t wValueHi
Definition: UsbCore.h:181
uint8_t DefaultAddressing(uint8_t parent, uint8_t port, bool lowspeed)
Definition: Usb.cpp:530
#define USB_DETACHED_SUBSTATE_INITIALIZE
Definition: UsbCore.h:107
uint8_t getDevDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t *dataptr)
defined(USB_METHODS_INLINE)
Definition: Usb.cpp:764
#define USB_ATTACHED_SUBSTATE_WAIT_SOF
Definition: UsbCore.h:113
uint8_t wValueLo
Definition: UsbCore.h:180
#define bmSNDTOG1
Definition: max3421e.h:183
uint8_t ReleaseDevice(uint8_t addr)
Definition: Usb.cpp:749
#define USB_ERROR_TRANSFER_TIMEOUT
Definition: UsbCore.h:92
#define USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET
Definition: UsbCore.h:88