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 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 = 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  //printf("SetAddress Failed");
214  return rcode;
215  }
216  return InTransfer(pep, nak_limit, nbytesptr, data);
217 }
218 
219 uint8_t USB::InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, uint8_t* data) {
220  uint8_t rcode = 0;
221  uint8_t pktsize;
222 
223  uint16_t nbytes = *nbytesptr;
224  //printf("Requesting %i bytes ", nbytes);
225  uint8_t maxpktsize = pep->maxPktSize;
226 
227  *nbytesptr = 0;
228  regWr(rHCTL, (pep->bmRcvToggle) ? bmRCVTOG1 : bmRCVTOG0); //set toggle value
229 
230  while (1) // use a 'return' to exit this loop
231  {
232  rcode = dispatchPkt(tokIN, pep->epAddr, nak_limit); //IN packet to EP-'endpoint'. Function takes care of NAKS.
233  if (rcode == hrTOGERR) {
234  // yes, we flip it wrong here so that next time it is actually correct!
235  pep->bmRcvToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1;
236  regWr(rHCTL, (pep->bmRcvToggle) ? bmRCVTOG1 : bmRCVTOG0); //set toggle value
237  continue;
238  }
239  if (rcode) {
240  //printf(">>>>>>>> Problem! dispatchPkt %2.2x\r\n", rcode);
241  break; //should be 0, indicating ACK. Else return error code.
242  }
243  /* check for RCVDAVIRQ and generate error if not present */
244  /* the only case when absence of RCVDAVIRQ makes sense is when toggle error occurred. Need to add handling for that */
245  if ((regRd(rHIRQ) & bmRCVDAVIRQ) == 0) {
246  //printf(">>>>>>>> Problem! NO RCVDAVIRQ!\r\n");
247  rcode = 0xf0; //receive error
248  break;
249  }
250  pktsize = regRd(rRCVBC); //number of received bytes
251  //printf("Got %i bytes \r\n", pktsize);
252  // This would be OK, but...
253  //assert(pktsize <= nbytes);
254  if (pktsize > nbytes) {
255  // This can happen. Use of assert on Arduino locks up the Arduino.
256  // So I will trim the value, and hope for the best.
257  //printf(">>>>>>>> Problem! Wanted %i bytes but got %i.\r\n", nbytes, pktsize);
258  pktsize = nbytes;
259  }
260 
261  int16_t mem_left = (int16_t)nbytes - *((int16_t*)nbytesptr);
262 
263  if (mem_left < 0)
264  mem_left = 0;
265 
266  data = bytesRd(rRCVFIFO, ((pktsize > mem_left) ? mem_left : pktsize), data);
267 
268  regWr(rHIRQ, bmRCVDAVIRQ); // Clear the IRQ & free the buffer
269  *nbytesptr += pktsize; // add this packet's byte count to total transfer length
270 
271  /* The transfer is complete under two conditions: */
272  /* 1. The device sent a short packet (L.T. maxPacketSize) */
273  /* 2. 'nbytes' have been transferred. */
274  if ((pktsize < maxpktsize) || (*nbytesptr >= nbytes)) // have we transferred 'nbytes' bytes?
275  {
276  // Save toggle value
277  pep->bmRcvToggle = ((regRd(rHRSL) & bmRCVTOGRD)) ? 1 : 0;
278  //printf("\r\n");
279  rcode = 0;
280  break;
281  } // if
282  } //while( 1 )
283  return ( rcode);
284 }
285 
286 /* OUT transfer to arbitrary endpoint. Handles multiple packets if necessary. Transfers 'nbytes' bytes. */
287 /* Handles NAK bug per Maxim Application Note 4000 for single buffer transfer */
288 
289 /* rcode 0 if no errors. rcode 01-0f is relayed from HRSL */
290 uint8_t USB::outTransfer(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* data) {
291  EpInfo *pep = NULL;
292  uint16_t nak_limit = 0;
293 
294  uint8_t rcode = SetAddress(addr, ep, &pep, nak_limit);
295 
296  if (rcode)
297  return rcode;
298 
299  return OutTransfer(pep, nak_limit, nbytes, data);
300 }
301 
302 uint8_t USB::OutTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t nbytes, uint8_t *data) {
303  uint8_t rcode = hrSUCCESS, retry_count;
304  uint8_t *data_p = data; //local copy of the data pointer
305  uint16_t bytes_tosend, nak_count;
306  uint16_t bytes_left = nbytes;
307 
308  uint8_t maxpktsize = pep->maxPktSize;
309 
310  if (maxpktsize < 1 || maxpktsize > 64)
312 
313  unsigned long timeout = millis() + USB_XFER_TIMEOUT;
314 
315  regWr(rHCTL, (pep->bmSndToggle) ? bmSNDTOG1 : bmSNDTOG0); //set toggle value
316 
317  while (bytes_left) {
318  retry_count = 0;
319  nak_count = 0;
320  bytes_tosend = (bytes_left >= maxpktsize) ? maxpktsize : bytes_left;
321  bytesWr(rSNDFIFO, bytes_tosend, data_p); //filling output FIFO
322  regWr(rSNDBC, bytes_tosend); //set number of bytes
323  regWr(rHXFR, (tokOUT | pep->epAddr)); //dispatch packet
324  while (!(regRd(rHIRQ) & bmHXFRDNIRQ)); //wait for the completion IRQ
325  regWr(rHIRQ, bmHXFRDNIRQ); //clear IRQ
326  rcode = (regRd(rHRSL) & 0x0f);
327 
328  while (rcode && (timeout > millis())) {
329  switch (rcode) {
330  case hrNAK:
331  nak_count++;
332  if (nak_limit && (nak_count == nak_limit))
333  goto breakout;
334  //return ( rcode);
335  break;
336  case hrTIMEOUT:
337  retry_count++;
338  if (retry_count == USB_RETRY_LIMIT)
339  goto breakout;
340  //return ( rcode);
341  break;
342  case hrTOGERR:
343  // yes, we flip it wrong here so that next time it is actually correct!
344  pep->bmSndToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1;
345  regWr(rHCTL, (pep->bmSndToggle) ? bmSNDTOG1 : bmSNDTOG0); //set toggle value
346  break;
347  default:
348  goto breakout;
349  }//switch( rcode
350 
351  /* process NAK according to Host out NAK bug */
352  regWr(rSNDBC, 0);
353  regWr(rSNDFIFO, *data_p);
354  regWr(rSNDBC, bytes_tosend);
355  regWr(rHXFR, (tokOUT | pep->epAddr)); //dispatch packet
356  while (!(regRd(rHIRQ) & bmHXFRDNIRQ)); //wait for the completion IRQ
357  regWr(rHIRQ, bmHXFRDNIRQ); //clear IRQ
358  rcode = (regRd(rHRSL) & 0x0f);
359  }//while( rcode && ....
360  bytes_left -= bytes_tosend;
361  data_p += bytes_tosend;
362  }//while( bytes_left...
363 breakout:
364 
365  pep->bmSndToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 1 : 0; //bmSNDTOG1 : bmSNDTOG0; //update toggle
366  return ( rcode); //should be 0 in all cases
367 }
368 /* dispatch USB packet. Assumes peripheral address is set and relevant buffer is loaded/empty */
369 /* If NAK, tries to re-send up to nak_limit times */
370 /* If nak_limit == 0, do not count NAKs, exit after timeout */
371 /* If bus timeout, re-sends up to USB_RETRY_LIMIT times */
372 
373 /* return codes 0x00-0x0f are HRSLT( 0x00 being success ), 0xff means timeout */
374 uint8_t USB::dispatchPkt(uint8_t token, uint8_t ep, uint16_t nak_limit) {
375  unsigned long timeout = millis() + USB_XFER_TIMEOUT;
376  uint8_t tmpdata;
377  uint8_t rcode = hrSUCCESS;
378  uint8_t retry_count = 0;
379  uint16_t nak_count = 0;
380 
381  while (timeout > millis()) {
382  regWr(rHXFR, (token | ep)); //launch the transfer
384 
385  while (timeout > millis()) //wait for transfer completion
386  {
387  tmpdata = regRd(rHIRQ);
388 
389  if (tmpdata & bmHXFRDNIRQ) {
390  regWr(rHIRQ, bmHXFRDNIRQ); //clear the interrupt
391  rcode = 0x00;
392  break;
393  }//if( tmpdata & bmHXFRDNIRQ
394 
395  }//while ( millis() < timeout
396 
397  //if (rcode != 0x00) //exit if timeout
398  // return ( rcode);
399 
400  rcode = (regRd(rHRSL) & 0x0f); //analyze transfer result
401 
402  switch (rcode) {
403  case hrNAK:
404  nak_count++;
405  if (nak_limit && (nak_count == nak_limit))
406  return (rcode);
407  break;
408  case hrTIMEOUT:
409  retry_count++;
410  if (retry_count == USB_RETRY_LIMIT)
411  return (rcode);
412  break;
413  default:
414  return (rcode);
415  }//switch( rcode
416 
417  }//while( timeout > millis()
418  return ( rcode);
419 }
420 
421 /* USB main task. Performs enumeration/cleanup */
422 void USB::Task(void) //USB state machine
423 {
424  uint8_t rcode;
425  uint8_t tmpdata;
426  static unsigned long delay = 0;
427  //USB_DEVICE_DESCRIPTOR buf;
428  bool lowspeed = false;
429 
430  MAX3421E::Task();
431 
432  tmpdata = getVbusState();
433 
434  /* modify USB task state if Vbus changed */
435  switch (tmpdata) {
436  case SE1: //illegal state
437  usb_task_state = USB_DETACHED_SUBSTATE_ILLEGAL;
438  lowspeed = false;
439  break;
440  case SE0: //disconnected
441  if ((usb_task_state & USB_STATE_MASK) != USB_STATE_DETACHED)
442  usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE;
443  lowspeed = false;
444  break;
445  case LSHOST:
446 
447  lowspeed = true;
448  //intentional fallthrough
449  case FSHOST: //attached
450  if ((usb_task_state & USB_STATE_MASK) == USB_STATE_DETACHED) {
451  delay = millis() + USB_SETTLE_DELAY;
452  usb_task_state = USB_ATTACHED_SUBSTATE_SETTLE;
453  }
454  break;
455  }// switch( tmpdata
456 
457  for (uint8_t i = 0; i < USB_NUMDEVICES; i++)
458  if (devConfig[i])
459  rcode = devConfig[i]->Poll();
460 
461  switch (usb_task_state) {
463  init();
464 
465  for (uint8_t i = 0; i < USB_NUMDEVICES; i++)
466  if (devConfig[i])
467  rcode = devConfig[i]->Release();
468 
469  usb_task_state = USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE;
470  break;
471  case USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE: //just sit here
472  break;
473  case USB_DETACHED_SUBSTATE_ILLEGAL: //just sit here
474  break;
475  case USB_ATTACHED_SUBSTATE_SETTLE: //settle time for just attached device
476  if (delay < millis())
477  usb_task_state = USB_ATTACHED_SUBSTATE_RESET_DEVICE;
478  else break; // don't fall through
480  regWr(rHCTL, bmBUSRST); //issue bus reset
482  break;
484  if ((regRd(rHCTL) & bmBUSRST) == 0) {
485  tmpdata = regRd(rMODE) | bmSOFKAENAB; //start SOF generation
486  regWr(rMODE, tmpdata);
487  usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_SOF;
488  //delay = millis() + 20; //20ms wait after reset per USB spec
489  }
490  break;
491  case USB_ATTACHED_SUBSTATE_WAIT_SOF: //todo: change check order
492  if (regRd(rHIRQ) & bmFRAMEIRQ) {
493  //when first SOF received _and_ 20ms has passed we can continue
494  /*
495  if (delay < millis()) //20ms passed
496  usb_task_state = USB_STATE_CONFIGURING;
497  */
498  usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET;
499  delay = millis() + 20;
500  }
501  break;
503  if (delay < millis()) usb_task_state = USB_STATE_CONFIGURING;
504  else break; // don't fall through
506 
507  //Serial.print("\r\nConf.LS: ");
508  //Serial.println(lowspeed, HEX);
509 
510  rcode = Configuring(0, 0, lowspeed);
511 
512  if (rcode) {
514  usb_error = rcode;
515  usb_task_state = USB_STATE_ERROR;
516  }
517  } else
518  usb_task_state = USB_STATE_RUNNING;
519  break;
520  case USB_STATE_RUNNING:
521  break;
522  case USB_STATE_ERROR:
523  //MAX3421E::Init();
524  break;
525  } // switch( usb_task_state )
526 }
527 
528 uint8_t USB::DefaultAddressing(uint8_t parent, uint8_t port, bool lowspeed) {
529  //uint8_t buf[12];
530  uint8_t rcode;
531  UsbDevice *p0 = NULL, *p = NULL;
532 
533  // Get pointer to pseudo device with address 0 assigned
534  p0 = addrPool.GetUsbDevicePtr(0);
535 
536  if (!p0)
538 
539  if (!p0->epinfo)
541 
542  p0->lowspeed = (lowspeed) ? true : false;
543 
544  // Allocate new address according to device class
545  uint8_t bAddress = addrPool.AllocAddress(parent, false, port);
546 
547  if (!bAddress)
549 
550  p = addrPool.GetUsbDevicePtr(bAddress);
551 
552  if (!p)
554 
555  p->lowspeed = lowspeed;
556 
557  // Assign new address to the device
558  rcode = setAddr(0, 0, bAddress);
559 
560  if (rcode) {
561  addrPool.FreeAddress(bAddress);
562  bAddress = 0;
563  return rcode;
564  }
565  return 0;
566 };
567 
568 uint8_t USB::AttemptConfig(uint8_t driver, uint8_t parent, uint8_t port, bool lowspeed) {
569  //printf("AttemptConfig: parent = %i, port = %i\r\n", parent, port);
570 
571 again:
572  uint8_t rcode = devConfig[driver]->ConfigureDevice(parent, port, lowspeed);
574  if (parent == 0) {
575  // Send a bus reset on the root interface.
576  regWr(rHCTL, bmBUSRST); //issue bus reset
577  delay(102); // delay 102ms, compensate for clock inaccuracy.
578  } else {
579  // reset parent port
580  devConfig[parent]->ResetHubPort(port);
581  }
582  } else if (rcode == hrJERR) { // Some devices returns this when plugged in - trying to initialize the device again usually works
583  delay(100);
584  goto again;
585  } else if (rcode)
586  return rcode;
587 
588  rcode = devConfig[driver]->Init(parent, port, lowspeed);
589  if (rcode == hrJERR) { // Some devices returns this when plugged in - trying to initialize the device again usually works
590  delay(100);
591  goto again;
592  }
593  if (rcode) {
594  // Issue a bus reset, because the device may be in a limbo state
595  if (parent == 0) {
596  // Send a bus reset on the root interface.
597  regWr(rHCTL, bmBUSRST); //issue bus reset
598  delay(102); // delay 102ms, compensate for clock inaccuracy.
599  } else {
600  // reset parent port
601  devConfig[parent]->ResetHubPort(port);
602  }
603  }
604  return rcode;
605 }
606 
607 /*
608  * This is broken. We need to enumerate differently.
609  * It causes major problems with several devices if detected in an unexpected order.
610  *
611  *
612  * Oleg - I wouldn't do anything before the newly connected device is considered sane.
613  * i.e.(delays are not indicated for brevity):
614  * 1. reset
615  * 2. GetDevDescr();
616  * 3a. If ACK, continue with allocating address, addressing, etc.
617  * 3b. Else reset again, count resets, stop at some number (5?).
618  * 4. When max.number of resets is reached, toggle power/fail
619  * 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()
620  * it doesn't need to be reset again
621  * New steps proposal:
622  * 1: get address pool instance. exit on fail
623  * 2: pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf). exit on fail.
624  * 3: bus reset, 100ms delay
625  * 4: set address
626  * 5: pUsb->setEpInfoEntry(bAddress, 1, epInfo), exit on fail
627  * 6: while (configurations) {
628  * for(each configuration) {
629  * for (each driver) {
630  * 6a: Ask device if it likes configuration. Returns 0 on OK.
631  * If successful, the driver configured device.
632  * The driver now owns the endpoints, and takes over managing them.
633  * The following will need codes:
634  * Everything went well, instance consumed, exit with success.
635  * Instance already in use, ignore it, try next driver.
636  * Not a supported device, ignore it, try next driver.
637  * Not a supported configuration for this device, ignore it, try next driver.
638  * Could not configure device, fatal, exit with fail.
639  * }
640  * }
641  * }
642  * 7: for(each driver) {
643  * 7a: Ask device if it knows this VID/PID. Acts exactly like 6a, but using VID/PID
644  * 8: if we get here, no driver likes the device plugged in, so exit failure.
645  *
646  */
647 uint8_t USB::Configuring(uint8_t parent, uint8_t port, bool lowspeed) {
648  //uint8_t bAddress = 0;
649  //printf("Configuring: parent = %i, port = %i\r\n", parent, port);
650  uint8_t devConfigIndex;
651  uint8_t rcode = 0;
652  uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)];
653  UsbDevice *p = NULL;
654  EpInfo *oldep_ptr = NULL;
655  EpInfo epInfo;
656 
657  epInfo.epAddr = 0;
658  epInfo.maxPktSize = 8;
659  epInfo.epAttribs = 0;
660  epInfo.bmNakPower = USB_NAK_MAX_POWER;
661 
662  //delay(2000);
663  AddressPool &addrPool = GetAddressPool();
664  // Get pointer to pseudo device with address 0 assigned
665  p = addrPool.GetUsbDevicePtr(0);
666  if (!p) {
667  //printf("Configuring error: USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL\r\n");
669  }
670 
671  // Save old pointer to EP_RECORD of address 0
672  oldep_ptr = p->epinfo;
673 
674  // Temporary assign new pointer to epInfo to p->epinfo in order to
675  // avoid toggle inconsistence
676 
677  p->epinfo = &epInfo;
678 
679  p->lowspeed = lowspeed;
680  // Get device descriptor
681  rcode = getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf);
682 
683  // Restore p->epinfo
684  p->epinfo = oldep_ptr;
685 
686  if (rcode) {
687  //printf("Configuring error: Can't get USB_DEVICE_DESCRIPTOR\r\n");
688  return rcode;
689  }
690 
691  // to-do?
692  // Allocate new address according to device class
693  //bAddress = addrPool.AllocAddress(parent, false, port);
694 
695  //if (!bAddress)
696  // return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
697 
698  uint16_t vid = (uint16_t)((USB_DEVICE_DESCRIPTOR*)buf)->idVendor;
699  uint16_t pid = (uint16_t)((USB_DEVICE_DESCRIPTOR*)buf)->idProduct;
700  uint8_t klass = ((USB_DEVICE_DESCRIPTOR*)buf)->bDeviceClass;
701 
702  // Attempt to configure if VID/PID or device class matches with a driver
703  for (devConfigIndex = 0; devConfigIndex < USB_NUMDEVICES; devConfigIndex++) {
704  if (!devConfig[devConfigIndex]) continue; // no driver
705  if (devConfig[devConfigIndex]->GetAddress()) continue; // consumed
706  if (devConfig[devConfigIndex]->VIDPIDOK(vid, pid) || devConfig[devConfigIndex]->DEVCLASSOK(klass)) {
707  rcode = AttemptConfig(devConfigIndex, parent, port, lowspeed);
709  break;
710  }
711  }
712 
713  if (devConfigIndex < USB_NUMDEVICES) {
714  return rcode;
715  }
716 
717 
718  // blindly attempt to configure
719  for (devConfigIndex = 0; devConfigIndex < USB_NUMDEVICES; devConfigIndex++) {
720  if (!devConfig[devConfigIndex]) continue;
721  if (devConfig[devConfigIndex]->GetAddress()) continue; // consumed
722  if (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
723  rcode = AttemptConfig(devConfigIndex, parent, port, lowspeed);
724 
725  //printf("ERROR ENUMERATING %2.2x\r\n", rcode);
727  // in case of an error dev_index should be reset to 0
728  // in order to start from the very beginning the
729  // next time the program gets here
730  //if (rcode != USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE)
731  // devConfigIndex = 0;
732  return rcode;
733  }
734  }
735  // if we get here that means that the device class is not supported by any of registered classes
736  rcode = DefaultAddressing(parent, port, lowspeed);
737 
738  return rcode;
739 }
740 
741 uint8_t USB::ReleaseDevice(uint8_t addr) {
742  if (!addr)
743  return 0;
744 
745  for (uint8_t i = 0; i < USB_NUMDEVICES; i++) {
746  if(!devConfig[i]) continue;
747  if (devConfig[i]->GetAddress() == addr)
748  return devConfig[i]->Release();
749  }
750  return 0;
751 }
752 
753 #if 1
754 //get device descriptor
755 
756 uint8_t USB::getDevDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr) {
757  return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, nbytes, dataptr, NULL));
758 }
759 //get configuration descriptor
760 
761 uint8_t USB::getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t* dataptr) {
762  return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, nbytes, dataptr, NULL));
763 }
764 
765 /* 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
766  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 */
767 uint8_t USB::getConfDescr(uint8_t addr, uint8_t ep, uint8_t conf, USBReadParser *p) {
768  const uint8_t bufSize = 64;
769  uint8_t buf[bufSize];
770 
771  uint8_t ret = getConfDescr(addr, ep, 9, conf, buf);
772 
773  if (ret)
774  return ret;
775 
776  uint16_t total = ((USB_CONFIGURATION_DESCRIPTOR*)buf)->wTotalLength;
777 
778  //USBTRACE2("\r\ntotal conf.size:", total);
779 
780  return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, total, bufSize, buf, p));
781 }
782 
783 //get string descriptor
784 
785 uint8_t USB::getStrDescr(uint8_t addr, uint8_t ep, uint16_t ns, uint8_t index, uint16_t langid, uint8_t* dataptr) {
786  return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, ns, ns, dataptr, NULL));
787 }
788 //set address
789 
790 uint8_t USB::setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr) {
791  return ( ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL));
792 }
793 //set configuration
794 
795 uint8_t USB::setConf(uint8_t addr, uint8_t ep, uint8_t conf_value) {
796  return ( ctrlReq(addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL));
797 }
798 
799 #endif // defined(USB_METHODS_INLINE)
800 
uint8_t getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t *dataptr)
Definition: Usb.cpp:761
uint8_t bmRcvToggle
Definition: address.h:41
virtual uint8_t Poll()
Definition: UsbCore.h:110
#define USB_ERROR_EP_NOT_FOUND_IN_TBL
Definition: UsbCore.h:71
#define bmHUBPRE
Definition: max3421e.h:170
#define USB_ATTACHED_SUBSTATE_WAIT_RESET
Definition: UsbCore.h:98
#define FSHOST
Definition: max3421e.h:35
#define rHCTL
Definition: max3421e.h:179
EpInfo * epinfo
Definition: address.h:76
bool lowspeed
Definition: address.h:79
#define USB_ERROR_EPINFO_IS_NULL
Definition: UsbCore.h:67
uint8_t bmNakPower
Definition: address.h:42
EpInfo * getEpInfoEntry(uint8_t addr, uint8_t ep)
Definition: Usb.cpp:44
#define bmSOFKAENAB
Definition: max3421e.h:171
#define USB_DESCRIPTOR_STRING
Definition: usb_ch9.h:65
uint16_t wLength
Definition: UsbCore.h:140
#define USB_SETTLE_DELAY
Definition: UsbCore.h:81
#define USB_ATTACHED_SUBSTATE_SETTLE
Definition: UsbCore.h:94
void regWr(uint8_t reg, uint8_t data)
Definition: usbhost.h:106
#define bmRCVTOGRD
Definition: max3421e.h:204
#define USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE
Definition: UsbCore.h:62
#define USB_RETRY_LIMIT
Definition: UsbCore.h:80
#define USB_REQUEST_GET_DESCRIPTOR
Definition: usb_ch9.h:37
#define USB_DESCRIPTOR_DEVICE
Definition: usb_ch9.h:63
#define bmRCVTOG1
Definition: max3421e.h:186
#define USB_ERROR_INVALID_MAX_PKT_SIZE
Definition: UsbCore.h:70
uint8_t setConf(uint8_t addr, uint8_t ep, uint8_t conf_value)
Definition: Usb.cpp:795
#define USB_STATE_DETACHED
Definition: UsbCore.h:90
#define USB_NUMDEVICES
Definition: UsbCore.h:83
#define rRCVBC
Definition: max3421e.h:45
#define hrJERR
Definition: max3421e.h:225
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:108
#define hrSUCCESS
Definition: max3421e.h:212
#define USB_STATE_ERROR
Definition: UsbCore.h:103
uint8_t bmRequestType
Definition: UsbCore.h:121
#define bmSNDTOGRD
Definition: max3421e.h:205
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:151
uint8_t setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr)
Definition: Usb.cpp:790
USB(void)
Definition: Usb.cpp:25
#define USB_STATE_RUNNING
Definition: UsbCore.h:102
uint8_t epAddr
Definition: address.h:33
#define rRCVFIFO
Definition: max3421e.h:42
#define USB_NAK_MAX_POWER
Definition: address.h:27
virtual UsbDevice * GetUsbDevicePtr(uint8_t addr)
Definition: address.h:174
uint16_t wIndex
Definition: UsbCore.h:139
#define bmBUSRST
Definition: max3421e.h:181
#define tokOUT
Definition: max3421e.h:195
#define tokIN
Definition: max3421e.h:194
#define LSHOST
Definition: max3421e.h:36
#define USB_XFER_TIMEOUT
Definition: UsbCore.h:78
Definition: address.h:32
#define rMODE
Definition: max3421e.h:165
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:290
#define hrNAK
Definition: max3421e.h:216
#define bmREQ_GET_DESCR
Definition: UsbCore.h:31
#define rSNDBC
Definition: max3421e.h:46
#define rHRSL
Definition: max3421e.h:201
#define USB_ATTACHED_SUBSTATE_RESET_DEVICE
Definition: UsbCore.h:95
#define tokINHS
Definition: max3421e.h:196
#define bmLOWSPEED
Definition: max3421e.h:169
virtual void ResetHubPort(uint8_t port)
Definition: UsbCore.h:112
uint8_t getStrDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t index, uint16_t langid, uint8_t *dataptr)
Definition: Usb.cpp:785
#define USB_REQUEST_SET_ADDRESS
Definition: usb_ch9.h:36
union SETUP_PKT::@22 ReqType_u
#define tokSETUP
Definition: max3421e.h:193
uint8_t Task()
Definition: usbhost.h:335
#define rHXFR
Definition: max3421e.h:190
#define rHIRQ
Definition: max3421e.h:142
uint8_t bmSndToggle
Definition: address.h:40
#define rSNDFIFO
Definition: max3421e.h:43
#define USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE
Definition: UsbCore.h:69
uint8_t * bytesWr(uint8_t reg, uint8_t nbytes, uint8_t *data_p)
Definition: usbhost.h:121
#define tokOUTHS
Definition: max3421e.h:197
uint8_t getUsbTaskState(void)
Definition: Usb.cpp:36
#define USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL
Definition: UsbCore.h:66
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:88
#define USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED
Definition: UsbCore.h:61
void Task(void)
Definition: Usb.cpp:422
#define USB_DETACHED_SUBSTATE_ILLEGAL
Definition: UsbCore.h:93
#define hrTIMEOUT
Definition: max3421e.h:226
#define rPERADDR
Definition: max3421e.h:177
#define bmRCVDAVIRQ
Definition: max3421e.h:146
#define USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE
Definition: UsbCore.h:96
#define bmRCVTOG0
Definition: max3421e.h:185
virtual boolean DEVCLASSOK(uint8_t klass)
Definition: UsbCore.h:114
uint8_t epcount
Definition: address.h:78
#define USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL
Definition: UsbCore.h:64
#define USB_STATE_CONFIGURING
Definition: UsbCore.h:101
uint8_t dispatchPkt(uint8_t token, uint8_t ep, uint16_t nak_limit)
Definition: Usb.cpp:374
virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed)
Definition: UsbCore.h:107
#define bmSNDTOG0
Definition: max3421e.h:187
uint8_t maxPktSize
Definition: address.h:34
AddressPool & GetAddressPool()
Definition: UsbCore.h:168
#define USB_ERROR_INVALID_ARGUMENT
Definition: UsbCore.h:68
uint8_t Configuring(uint8_t parent, uint8_t port, bool lowspeed)
Definition: Usb.cpp:647
uint8_t address
Definition: address.h:77
uint8_t * bytesRd(uint8_t reg, uint8_t nbytes, uint8_t *data_p)
Definition: usbhost.h:165
uint8_t bRequest
Definition: UsbCore.h:129
#define SE0
Definition: max3421e.h:33
virtual void FreeAddress(uint8_t addr)
Definition: address.h:246
virtual uint8_t Release()
Definition: UsbCore.h:109
#define bmFRAMEIRQ
Definition: max3421e.h:150
#define hrTOGERR
Definition: max3421e.h:218
#define SE1
Definition: max3421e.h:34
#define rSUDFIFO
Definition: max3421e.h:44
virtual uint8_t AllocAddress(uint8_t parent, bool is_hub=false, uint8_t port=0)
Definition: address.h:195
#define bmREQ_SET
Definition: UsbCore.h:32
#define USB_REQUEST_SET_CONFIGURATION
Definition: usb_ch9.h:40
union SETUP_PKT::@23 wVal_u
#define USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE
Definition: UsbCore.h:92
uint8_t wValueHi
Definition: UsbCore.h:136
uint8_t DefaultAddressing(uint8_t parent, uint8_t port, bool lowspeed)
Definition: Usb.cpp:528
#define USB_DETACHED_SUBSTATE_INITIALIZE
Definition: UsbCore.h:91
uint8_t getDevDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t *dataptr)
defined(USB_METHODS_INLINE)
Definition: Usb.cpp:756
#define USB_ATTACHED_SUBSTATE_WAIT_SOF
Definition: UsbCore.h:97
uint8_t wValueLo
Definition: UsbCore.h:135
#define bmSNDTOG1
Definition: max3421e.h:188
uint8_t ReleaseDevice(uint8_t addr)
Definition: Usb.cpp:741
#define USB_ERROR_TRANSFER_TIMEOUT
Definition: UsbCore.h:76
#define USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET
Definition: UsbCore.h:72
uint8_t getVbusState(void)
Definition: usbhost.h:81
uint8_t regRd(uint8_t reg)
Definition: usbhost.h:149