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