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, uint8_t bInterval /*= 0*/) {
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, bInterval);
219 }
220 
221 uint8_t USB::InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, uint8_t* data, uint8_t bInterval /*= 0*/) {
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) & bmRCVTOGRD) ? 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  } else if(bInterval > 0)
284  delay(bInterval); // Delay according to polling interval
285  } //while( 1 )
286  return ( rcode);
287 }
288 
289 /* OUT transfer to arbitrary endpoint. Handles multiple packets if necessary. Transfers 'nbytes' bytes. */
290 /* Handles NAK bug per Maxim Application Note 4000 for single buffer transfer */
291 
292 /* rcode 0 if no errors. rcode 01-0f is relayed from HRSL */
293 uint8_t USB::outTransfer(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* data) {
294  EpInfo *pep = NULL;
295  uint16_t nak_limit = 0;
296 
297  uint8_t rcode = SetAddress(addr, ep, &pep, &nak_limit);
298 
299  if(rcode)
300  return rcode;
301 
302  return OutTransfer(pep, nak_limit, nbytes, data);
303 }
304 
305 uint8_t USB::OutTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t nbytes, uint8_t *data) {
306  uint8_t rcode = hrSUCCESS, retry_count;
307  uint8_t *data_p = data; //local copy of the data pointer
308  uint16_t bytes_tosend, nak_count;
309  uint16_t bytes_left = nbytes;
310 
311  uint8_t maxpktsize = pep->maxPktSize;
312 
313  if(maxpktsize < 1 || maxpktsize > 64)
315 
316  unsigned long timeout = millis() + USB_XFER_TIMEOUT;
317 
318  regWr(rHCTL, (pep->bmSndToggle) ? bmSNDTOG1 : bmSNDTOG0); //set toggle value
319 
320  while(bytes_left) {
321  retry_count = 0;
322  nak_count = 0;
323  bytes_tosend = (bytes_left >= maxpktsize) ? maxpktsize : bytes_left;
324  bytesWr(rSNDFIFO, bytes_tosend, data_p); //filling output FIFO
325  regWr(rSNDBC, bytes_tosend); //set number of bytes
326  regWr(rHXFR, (tokOUT | pep->epAddr)); //dispatch packet
327  while(!(regRd(rHIRQ) & bmHXFRDNIRQ)); //wait for the completion IRQ
328  regWr(rHIRQ, bmHXFRDNIRQ); //clear IRQ
329  rcode = (regRd(rHRSL) & 0x0f);
330 
331  while(rcode && ((long)(millis() - timeout) < 0L)) {
332  switch(rcode) {
333  case hrNAK:
334  nak_count++;
335  if(nak_limit && (nak_count == nak_limit))
336  goto breakout;
337  //return ( rcode);
338  break;
339  case hrTIMEOUT:
340  retry_count++;
341  if(retry_count == USB_RETRY_LIMIT)
342  goto breakout;
343  //return ( rcode);
344  break;
345  case hrTOGERR:
346  // yes, we flip it wrong here so that next time it is actually correct!
347  pep->bmSndToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1;
348  regWr(rHCTL, (pep->bmSndToggle) ? bmSNDTOG1 : bmSNDTOG0); //set toggle value
349  break;
350  default:
351  goto breakout;
352  }//switch( rcode
353 
354  /* process NAK according to Host out NAK bug */
355  regWr(rSNDBC, 0);
356  regWr(rSNDFIFO, *data_p);
357  regWr(rSNDBC, bytes_tosend);
358  regWr(rHXFR, (tokOUT | pep->epAddr)); //dispatch packet
359  while(!(regRd(rHIRQ) & bmHXFRDNIRQ)); //wait for the completion IRQ
360  regWr(rHIRQ, bmHXFRDNIRQ); //clear IRQ
361  rcode = (regRd(rHRSL) & 0x0f);
362  }//while( rcode && ....
363  bytes_left -= bytes_tosend;
364  data_p += bytes_tosend;
365  }//while( bytes_left...
366 breakout:
367 
368  pep->bmSndToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 1 : 0; //bmSNDTOG1 : bmSNDTOG0; //update toggle
369  return ( rcode); //should be 0 in all cases
370 }
371 /* dispatch USB packet. Assumes peripheral address is set and relevant buffer is loaded/empty */
372 /* If NAK, tries to re-send up to nak_limit times */
373 /* If nak_limit == 0, do not count NAKs, exit after timeout */
374 /* If bus timeout, re-sends up to USB_RETRY_LIMIT times */
375 
376 /* return codes 0x00-0x0f are HRSLT( 0x00 being success ), 0xff means timeout */
377 uint8_t USB::dispatchPkt(uint8_t token, uint8_t ep, uint16_t nak_limit) {
378  unsigned long timeout = millis() + USB_XFER_TIMEOUT;
379  uint8_t tmpdata;
380  uint8_t rcode = hrSUCCESS;
381  uint8_t retry_count = 0;
382  uint16_t nak_count = 0;
383 
384  while((long)(millis() - timeout) < 0L) {
385  regWr(rHXFR, (token | ep)); //launch the transfer
387 
388  while((long)(millis() - timeout) < 0L) //wait for transfer completion
389  {
390  tmpdata = regRd(rHIRQ);
391 
392  if(tmpdata & bmHXFRDNIRQ) {
393  regWr(rHIRQ, bmHXFRDNIRQ); //clear the interrupt
394  rcode = 0x00;
395  break;
396  }//if( tmpdata & bmHXFRDNIRQ
397 
398  }//while ( millis() < timeout
399 
400  //if (rcode != 0x00) //exit if timeout
401  // return ( rcode);
402 
403  rcode = (regRd(rHRSL) & 0x0f); //analyze transfer result
404 
405  switch(rcode) {
406  case hrNAK:
407  nak_count++;
408  if(nak_limit && (nak_count == nak_limit))
409  return (rcode);
410  break;
411  case hrTIMEOUT:
412  retry_count++;
413  if(retry_count == USB_RETRY_LIMIT)
414  return (rcode);
415  break;
416  default:
417  return (rcode);
418  }//switch( rcode
419 
420  }//while( timeout > millis()
421  return ( rcode);
422 }
423 
424 /* USB main task. Performs enumeration/cleanup */
425 void USB::Task(void) //USB state machine
426 {
427  uint8_t rcode;
428  uint8_t tmpdata;
429  static unsigned long delay = 0;
430  //USB_DEVICE_DESCRIPTOR buf;
431  bool lowspeed = false;
432 
433  MAX3421E::Task();
434 
435  tmpdata = getVbusState();
436 
437  /* modify USB task state if Vbus changed */
438  switch(tmpdata) {
439  case SE1: //illegal state
440  usb_task_state = USB_DETACHED_SUBSTATE_ILLEGAL;
441  lowspeed = false;
442  break;
443  case SE0: //disconnected
444  if((usb_task_state & USB_STATE_MASK) != USB_STATE_DETACHED)
445  usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE;
446  lowspeed = false;
447  break;
448  case LSHOST:
449 
450  lowspeed = true;
451  //intentional fallthrough
452  case FSHOST: //attached
453  if((usb_task_state & USB_STATE_MASK) == USB_STATE_DETACHED) {
454  delay = millis() + USB_SETTLE_DELAY;
455  usb_task_state = USB_ATTACHED_SUBSTATE_SETTLE;
456  }
457  break;
458  }// switch( tmpdata
459 
460  for(uint8_t i = 0; i < USB_NUMDEVICES; i++)
461  if(devConfig[i])
462  rcode = devConfig[i]->Poll();
463 
464  switch(usb_task_state) {
466  init();
467 
468  for(uint8_t i = 0; i < USB_NUMDEVICES; i++)
469  if(devConfig[i])
470  rcode = devConfig[i]->Release();
471 
472  usb_task_state = USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE;
473  break;
474  case USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE: //just sit here
475  break;
476  case USB_DETACHED_SUBSTATE_ILLEGAL: //just sit here
477  break;
478  case USB_ATTACHED_SUBSTATE_SETTLE: //settle time for just attached device
479  if((long)(millis() - delay) >= 0L)
480  usb_task_state = USB_ATTACHED_SUBSTATE_RESET_DEVICE;
481  else break; // don't fall through
483  regWr(rHCTL, bmBUSRST); //issue bus reset
485  break;
487  if((regRd(rHCTL) & bmBUSRST) == 0) {
488  tmpdata = regRd(rMODE) | bmSOFKAENAB; //start SOF generation
489  regWr(rMODE, tmpdata);
490  usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_SOF;
491  //delay = millis() + 20; //20ms wait after reset per USB spec
492  }
493  break;
494  case USB_ATTACHED_SUBSTATE_WAIT_SOF: //todo: change check order
495  if(regRd(rHIRQ) & bmFRAMEIRQ) {
496  //when first SOF received _and_ 20ms has passed we can continue
497  /*
498  if (delay < millis()) //20ms passed
499  usb_task_state = USB_STATE_CONFIGURING;
500  */
501  usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET;
502  delay = millis() + 20;
503  }
504  break;
506  if((long)(millis() - delay) >= 0L) usb_task_state = USB_STATE_CONFIGURING;
507  else break; // don't fall through
509 
510  //Serial.print("\r\nConf.LS: ");
511  //Serial.println(lowspeed, HEX);
512 
513  rcode = Configuring(0, 0, lowspeed);
514 
515  if(rcode) {
517  usb_error = rcode;
518  usb_task_state = USB_STATE_ERROR;
519  }
520  } else
521  usb_task_state = USB_STATE_RUNNING;
522  break;
523  case USB_STATE_RUNNING:
524  break;
525  case USB_STATE_ERROR:
526  //MAX3421E::Init();
527  break;
528  } // switch( usb_task_state )
529 }
530 
531 uint8_t USB::DefaultAddressing(uint8_t parent, uint8_t port, bool lowspeed) {
532  //uint8_t buf[12];
533  uint8_t rcode;
534  UsbDevice *p0 = NULL, *p = NULL;
535 
536  // Get pointer to pseudo device with address 0 assigned
537  p0 = addrPool.GetUsbDevicePtr(0);
538 
539  if(!p0)
541 
542  if(!p0->epinfo)
544 
545  p0->lowspeed = (lowspeed) ? true : false;
546 
547  // Allocate new address according to device class
548  uint8_t bAddress = addrPool.AllocAddress(parent, false, port);
549 
550  if(!bAddress)
552 
553  p = addrPool.GetUsbDevicePtr(bAddress);
554 
555  if(!p)
557 
558  p->lowspeed = lowspeed;
559 
560  // Assign new address to the device
561  rcode = setAddr(0, 0, bAddress);
562 
563  if(rcode) {
564  addrPool.FreeAddress(bAddress);
565  bAddress = 0;
566  return rcode;
567  }
568  return 0;
569 };
570 
571 uint8_t USB::AttemptConfig(uint8_t driver, uint8_t parent, uint8_t port, bool lowspeed) {
572  //printf("AttemptConfig: parent = %i, port = %i\r\n", parent, port);
573  uint8_t retries = 0;
574 
575 again:
576  uint8_t rcode = devConfig[driver]->ConfigureDevice(parent, port, lowspeed);
578  if(parent == 0) {
579  // Send a bus reset on the root interface.
580  regWr(rHCTL, bmBUSRST); //issue bus reset
581  delay(102); // delay 102ms, compensate for clock inaccuracy.
582  } else {
583  // reset parent port
584  devConfig[parent]->ResetHubPort(port);
585  }
586  } else if(rcode == hrJERR && retries < 3) { // Some devices returns this when plugged in - trying to initialize the device again usually works
587  delay(100);
588  retries++;
589  goto again;
590  } else if(rcode)
591  return rcode;
592 
593  rcode = devConfig[driver]->Init(parent, port, lowspeed);
594  if(rcode == hrJERR && retries < 3) { // Some devices returns this when plugged in - trying to initialize the device again usually works
595  delay(100);
596  retries++;
597  goto again;
598  }
599  if(rcode) {
600  // Issue a bus reset, because the device may be in a limbo state
601  if(parent == 0) {
602  // Send a bus reset on the root interface.
603  regWr(rHCTL, bmBUSRST); //issue bus reset
604  delay(102); // delay 102ms, compensate for clock inaccuracy.
605  } else {
606  // reset parent port
607  devConfig[parent]->ResetHubPort(port);
608  }
609  }
610  return rcode;
611 }
612 
613 /*
614  * This is broken. We need to enumerate differently.
615  * It causes major problems with several devices if detected in an unexpected order.
616  *
617  *
618  * Oleg - I wouldn't do anything before the newly connected device is considered sane.
619  * i.e.(delays are not indicated for brevity):
620  * 1. reset
621  * 2. GetDevDescr();
622  * 3a. If ACK, continue with allocating address, addressing, etc.
623  * 3b. Else reset again, count resets, stop at some number (5?).
624  * 4. When max.number of resets is reached, toggle power/fail
625  * 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()
626  * it doesn't need to be reset again
627  * New steps proposal:
628  * 1: get address pool instance. exit on fail
629  * 2: pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf). exit on fail.
630  * 3: bus reset, 100ms delay
631  * 4: set address
632  * 5: pUsb->setEpInfoEntry(bAddress, 1, epInfo), exit on fail
633  * 6: while (configurations) {
634  * for(each configuration) {
635  * for (each driver) {
636  * 6a: Ask device if it likes configuration. Returns 0 on OK.
637  * If successful, the driver configured device.
638  * The driver now owns the endpoints, and takes over managing them.
639  * The following will need codes:
640  * Everything went well, instance consumed, exit with success.
641  * Instance already in use, ignore it, try next driver.
642  * Not a supported device, ignore it, try next driver.
643  * Not a supported configuration for this device, ignore it, try next driver.
644  * Could not configure device, fatal, exit with fail.
645  * }
646  * }
647  * }
648  * 7: for(each driver) {
649  * 7a: Ask device if it knows this VID/PID. Acts exactly like 6a, but using VID/PID
650  * 8: if we get here, no driver likes the device plugged in, so exit failure.
651  *
652  */
653 uint8_t USB::Configuring(uint8_t parent, uint8_t port, bool lowspeed) {
654  //uint8_t bAddress = 0;
655  //printf("Configuring: parent = %i, port = %i\r\n", parent, port);
656  uint8_t devConfigIndex;
657  uint8_t rcode = 0;
658  uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)];
659  USB_DEVICE_DESCRIPTOR *udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR *>(buf);
660  UsbDevice *p = NULL;
661  EpInfo *oldep_ptr = NULL;
662  EpInfo epInfo;
663 
664  epInfo.epAddr = 0;
665  epInfo.maxPktSize = 8;
666  epInfo.bmSndToggle = 0;
667  epInfo.bmRcvToggle = 0;
668  epInfo.bmNakPower = USB_NAK_MAX_POWER;
669 
670  //delay(2000);
671  AddressPool &addrPool = GetAddressPool();
672  // Get pointer to pseudo device with address 0 assigned
673  p = addrPool.GetUsbDevicePtr(0);
674  if(!p) {
675  //printf("Configuring error: USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL\r\n");
677  }
678 
679  // Save old pointer to EP_RECORD of address 0
680  oldep_ptr = p->epinfo;
681 
682  // Temporary assign new pointer to epInfo to p->epinfo in order to
683  // avoid toggle inconsistence
684 
685  p->epinfo = &epInfo;
686 
687  p->lowspeed = lowspeed;
688  // Get device descriptor
689  rcode = getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf);
690 
691  // Restore p->epinfo
692  p->epinfo = oldep_ptr;
693 
694  if(rcode) {
695  //printf("Configuring error: Can't get USB_DEVICE_DESCRIPTOR\r\n");
696  return rcode;
697  }
698 
699  // to-do?
700  // Allocate new address according to device class
701  //bAddress = addrPool.AllocAddress(parent, false, port);
702 
703  uint16_t vid = udd->idVendor;
704  uint16_t pid = udd->idProduct;
705  uint8_t klass = udd->bDeviceClass;
706  uint8_t subklass = udd->bDeviceSubClass;
707  // Attempt to configure if VID/PID or device class matches with a driver
708  // Qualify with subclass too.
709  //
710  // VID/PID & class tests default to false for drivers not yet ported
711  // subclass defaults to true, so you don't have to define it if you don't have to.
712  //
713  for(devConfigIndex = 0; devConfigIndex < USB_NUMDEVICES; devConfigIndex++) {
714  if(!devConfig[devConfigIndex]) continue; // no driver
715  if(devConfig[devConfigIndex]->GetAddress()) continue; // consumed
716  if(devConfig[devConfigIndex]->DEVSUBCLASSOK(subklass) && (devConfig[devConfigIndex]->VIDPIDOK(vid, pid) || devConfig[devConfigIndex]->DEVCLASSOK(klass))) {
717  rcode = AttemptConfig(devConfigIndex, parent, port, lowspeed);
719  break;
720  }
721  }
722 
723  if(devConfigIndex < USB_NUMDEVICES) {
724  return rcode;
725  }
726 
727 
728  // blindly attempt to configure
729  for(devConfigIndex = 0; devConfigIndex < USB_NUMDEVICES; devConfigIndex++) {
730  if(!devConfig[devConfigIndex]) continue;
731  if(devConfig[devConfigIndex]->GetAddress()) continue; // consumed
732  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
733  rcode = AttemptConfig(devConfigIndex, parent, port, lowspeed);
734 
735  //printf("ERROR ENUMERATING %2.2x\r\n", rcode);
737  // in case of an error dev_index should be reset to 0
738  // in order to start from the very beginning the
739  // next time the program gets here
740  //if (rcode != USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE)
741  // devConfigIndex = 0;
742  return rcode;
743  }
744  }
745  // if we get here that means that the device class is not supported by any of registered classes
746  rcode = DefaultAddressing(parent, port, lowspeed);
747 
748  return rcode;
749 }
750 
751 uint8_t USB::ReleaseDevice(uint8_t addr) {
752  if(!addr)
753  return 0;
754 
755  for(uint8_t i = 0; i < USB_NUMDEVICES; i++) {
756  if(!devConfig[i]) continue;
757  if(devConfig[i]->GetAddress() == addr)
758  return devConfig[i]->Release();
759  }
760  return 0;
761 }
762 
763 #if 1
764 //get device descriptor
765 
766 uint8_t USB::getDevDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr) {
767  return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, nbytes, dataptr, NULL));
768 }
769 //get configuration descriptor
770 
771 uint8_t USB::getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t* dataptr) {
772  return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, nbytes, dataptr, NULL));
773 }
774 
775 /* 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
776  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 */
777 uint8_t USB::getConfDescr(uint8_t addr, uint8_t ep, uint8_t conf, USBReadParser *p) {
778  const uint8_t bufSize = 64;
779  uint8_t buf[bufSize];
780  USB_CONFIGURATION_DESCRIPTOR *ucd = reinterpret_cast<USB_CONFIGURATION_DESCRIPTOR *>(buf);
781 
782  uint8_t ret = getConfDescr(addr, ep, 9, conf, buf);
783 
784  if(ret)
785  return ret;
786 
787  uint16_t total = ucd->wTotalLength;
788 
789  //USBTRACE2("\r\ntotal conf.size:", total);
790 
791  return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, total, bufSize, buf, p));
792 }
793 
794 //get string descriptor
795 
796 uint8_t USB::getStrDescr(uint8_t addr, uint8_t ep, uint16_t ns, uint8_t index, uint16_t langid, uint8_t* dataptr) {
797  return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, ns, ns, dataptr, NULL));
798 }
799 //set address
800 
801 uint8_t USB::setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr) {
802  uint8_t rcode = ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL);
803  //delay(2); //per USB 2.0 sect.9.2.6.3
804  delay(300); // Older spec says you should wait at least 200ms
805  return rcode;
806  //return ( ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL));
807 }
808 //set configuration
809 
810 uint8_t USB::setConf(uint8_t addr, uint8_t ep, uint8_t conf_value) {
811  return ( ctrlReq(addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL));
812 }
813 
814 #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:771
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
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:810
#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:502
#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 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:801
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:181
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
union SETUP_PKT::@33 wVal_u
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:293
#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:298
#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:196
uint8_t getStrDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t index, uint16_t langid, uint8_t *dataptr)
Definition: Usb.cpp:796
#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
#define USB_STATE_MASK
Definition: UsbCore.h:104
#define USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED
Definition: UsbCore.h:77
void Task(void)
Definition: Usb.cpp:425
#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
uint8_t inTransfer(uint8_t addr, uint8_t ep, uint16_t *nbytesptr, uint8_t *data, uint8_t bInterval=0)
Definition: Usb.cpp:206
#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:377
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:259
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:653
union SETUP_PKT::@32 ReqType_u
#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:255
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:203
#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:531
#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:766
#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:751
#define USB_ERROR_TRANSFER_TIMEOUT
Definition: UsbCore.h:92
#define USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET
Definition: UsbCore.h:88