1 /* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
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
14 Web : http://www.circuitsathome.com
15 e-mail : support@circuitsathome.com
21 static uint8_t usb_error = 0;
22 static uint8_t usb_task_state;
25 USB::USB() : bmHubPre(0) {
26 usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE; //set up state machine
30 /* Initialize data structures */
36 uint8_t USB::getUsbTaskState(void) {
37 return ( usb_task_state);
40 void USB::setUsbTaskState(uint8_t state) {
41 usb_task_state = state;
44 EpInfo* USB::getEpInfoEntry(uint8_t addr, uint8_t ep) {
45 UsbDevice *p = addrPool.GetUsbDevicePtr(addr);
50 EpInfo *pep = p->epinfo;
52 for(uint8_t i = 0; i < p->epcount; i++) {
53 if((pep)->epAddr == ep)
61 /* set device table entry */
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) {
66 return USB_ERROR_INVALID_ARGUMENT;
68 UsbDevice *p = addrPool.GetUsbDevicePtr(addr);
71 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
73 p->address.devAddress = addr;
74 p->epinfo = eprecord_ptr;
80 uint8_t USB::SetAddress(uint8_t addr, uint8_t ep, EpInfo **ppep, uint16_t *nak_limit) {
81 UsbDevice *p = addrPool.GetUsbDevicePtr(addr);
84 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
87 return USB_ERROR_EPINFO_IS_NULL;
89 *ppep = getEpInfoEntry(addr, ep);
92 return USB_ERROR_EP_NOT_FOUND_IN_TBL;
94 *nak_limit = (0x0001UL << (((*ppep)->bmNakPower > USB_NAK_MAX_POWER) ? USB_NAK_MAX_POWER : (*ppep)->bmNakPower));
97 USBTRACE2("\r\nAddress: ", addr);
98 USBTRACE2(" EP: ", ep);
99 USBTRACE2(" NAK Power: ",(*ppep)->bmNakPower);
100 USBTRACE2(" NAK Limit: ", nak_limit);
103 regWr(rPERADDR, addr); //set peripheral address
105 uint8_t mode = regRd(rMODE);
107 //Serial.print("\r\nMode: ");
108 //Serial.println( mode, HEX);
109 //Serial.print("\r\nLS: ");
110 //Serial.println(p->lowspeed, HEX);
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));
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 */
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
133 uint16_t nak_limit = 0;
135 rcode = SetAddress(addr, ep, &pep, &nak_limit);
140 direction = ((bmReqType & 0x80) > 0);
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;
150 bytesWr(rSUDFIFO, 8, (uint8_t*) & setup_pkt); //transfer to setup packet FIFO
152 rcode = dispatchPkt(tokSETUP, ep, nak_limit); //dispatch packet
154 if(rcode) //return HRSLT if not zero
157 if(dataptr != NULL) //data stage, if present
159 if(direction) //IN transfer
161 uint16_t left = total;
163 pep->bmRcvToggle = 1; //bmRCVTOG1;
166 // Bytes read into buffer
167 uint16_t read = nbytes;
168 //uint16_t read = (left<nbytes) ? left : nbytes;
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;
180 // Invoke callback function if inTransfer completed successfully and callback function pointer is specified
182 ((USBReadParser*)p)->Parse(read, dataptr, total - left);
189 } else //OUT transfer
191 pep->bmSndToggle = 1; //bmSNDTOG1;
192 rcode = OutTransfer(pep, nak_limit, nbytes, dataptr);
194 if(rcode) //return error
198 return dispatchPkt((direction) ? tokOUTHS : tokINHS, ep, nak_limit); //GET if direction
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' */
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) {
208 uint16_t nak_limit = 0;
210 uint8_t rcode = SetAddress(addr, ep, &pep, &nak_limit);
213 USBTRACE3("(USB::InTransfer) SetAddress Failed ", rcode, 0x81);
214 USBTRACE3("(USB::InTransfer) addr requested ", addr, 0x81);
215 USBTRACE3("(USB::InTransfer) ep requested ", ep, 0x81);
218 return InTransfer(pep, nak_limit, nbytesptr, data);
221 uint8_t USB::InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, uint8_t* data) {
225 uint16_t nbytes = *nbytesptr;
226 //printf("Requesting %i bytes ", nbytes);
227 uint8_t maxpktsize = pep->maxPktSize;
230 regWr(rHCTL, (pep->bmRcvToggle) ? bmRCVTOG1 : bmRCVTOG0); //set toggle value
232 // use a 'break' to exit this loop
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
242 //printf(">>>>>>>> Problem! dispatchPkt %2.2x\r\n", rcode);
243 break; //should be 0, indicating ACK. Else return error code.
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
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);
263 int16_t mem_left = (int16_t)nbytes - *((int16_t*)nbytesptr);
268 data = bytesRd(rRCVFIFO, ((pktsize > mem_left) ? mem_left : pktsize), data);
270 regWr(rHIRQ, bmRCVDAVIRQ); // Clear the IRQ & free the buffer
271 *nbytesptr += pktsize; // add this packet's byte count to total transfer length
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?
279 pep->bmRcvToggle = ((regRd(rHRSL) & bmRCVTOGRD)) ? 1 : 0;
288 /* OUT transfer to arbitrary endpoint. Handles multiple packets if necessary. Transfers 'nbytes' bytes. */
289 /* Handles NAK bug per Maxim Application Note 4000 for single buffer transfer */
291 /* rcode 0 if no errors. rcode 01-0f is relayed from HRSL */
292 uint8_t USB::outTransfer(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* data) {
294 uint16_t nak_limit = 0;
296 uint8_t rcode = SetAddress(addr, ep, &pep, &nak_limit);
301 return OutTransfer(pep, nak_limit, nbytes, data);
304 uint8_t USB::OutTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t nbytes, uint8_t *data) {
305 uint8_t rcode = hrSUCCESS, retry_count;
306 uint8_t *data_p = data; //local copy of the data pointer
307 uint16_t bytes_tosend, nak_count;
308 uint16_t bytes_left = nbytes;
310 uint8_t maxpktsize = pep->maxPktSize;
312 if(maxpktsize < 1 || maxpktsize > 64)
313 return USB_ERROR_INVALID_MAX_PKT_SIZE;
315 unsigned long timeout = millis() + USB_XFER_TIMEOUT;
317 regWr(rHCTL, (pep->bmSndToggle) ? bmSNDTOG1 : bmSNDTOG0); //set toggle value
322 bytes_tosend = (bytes_left >= maxpktsize) ? maxpktsize : bytes_left;
323 bytesWr(rSNDFIFO, bytes_tosend, data_p); //filling output FIFO
324 regWr(rSNDBC, bytes_tosend); //set number of bytes
325 regWr(rHXFR, (tokOUT | pep->epAddr)); //dispatch packet
326 while(!(regRd(rHIRQ) & bmHXFRDNIRQ)); //wait for the completion IRQ
327 regWr(rHIRQ, bmHXFRDNIRQ); //clear IRQ
328 rcode = (regRd(rHRSL) & 0x0f);
330 while(rcode && ((long)(millis() - timeout) < 0L)) {
334 if(nak_limit && (nak_count == nak_limit))
340 if(retry_count == USB_RETRY_LIMIT)
345 // yes, we flip it wrong here so that next time it is actually correct!
346 pep->bmSndToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1;
347 regWr(rHCTL, (pep->bmSndToggle) ? bmSNDTOG1 : bmSNDTOG0); //set toggle value
353 /* process NAK according to Host out NAK bug */
355 regWr(rSNDFIFO, *data_p);
356 regWr(rSNDBC, bytes_tosend);
357 regWr(rHXFR, (tokOUT | pep->epAddr)); //dispatch packet
358 while(!(regRd(rHIRQ) & bmHXFRDNIRQ)); //wait for the completion IRQ
359 regWr(rHIRQ, bmHXFRDNIRQ); //clear IRQ
360 rcode = (regRd(rHRSL) & 0x0f);
361 }//while( rcode && ....
362 bytes_left -= bytes_tosend;
363 data_p += bytes_tosend;
364 }//while( bytes_left...
367 pep->bmSndToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 1 : 0; //bmSNDTOG1 : bmSNDTOG0; //update toggle
368 return ( rcode); //should be 0 in all cases
370 /* dispatch USB packet. Assumes peripheral address is set and relevant buffer is loaded/empty */
371 /* If NAK, tries to re-send up to nak_limit times */
372 /* If nak_limit == 0, do not count NAKs, exit after timeout */
373 /* If bus timeout, re-sends up to USB_RETRY_LIMIT times */
375 /* return codes 0x00-0x0f are HRSLT( 0x00 being success ), 0xff means timeout */
376 uint8_t USB::dispatchPkt(uint8_t token, uint8_t ep, uint16_t nak_limit) {
377 unsigned long timeout = millis() + USB_XFER_TIMEOUT;
379 uint8_t rcode = hrSUCCESS;
380 uint8_t retry_count = 0;
381 uint16_t nak_count = 0;
383 while((long)(millis() - timeout) < 0L) {
384 regWr(rHXFR, (token | ep)); //launch the transfer
385 rcode = USB_ERROR_TRANSFER_TIMEOUT;
387 while((long)(millis() - timeout) < 0L) //wait for transfer completion
389 tmpdata = regRd(rHIRQ);
391 if(tmpdata & bmHXFRDNIRQ) {
392 regWr(rHIRQ, bmHXFRDNIRQ); //clear the interrupt
395 }//if( tmpdata & bmHXFRDNIRQ
397 }//while ( millis() < timeout
399 //if (rcode != 0x00) //exit if timeout
402 rcode = (regRd(rHRSL) & 0x0f); //analyze transfer result
407 if(nak_limit && (nak_count == nak_limit))
412 if(retry_count == USB_RETRY_LIMIT)
419 }//while( timeout > millis()
423 /* USB main task. Performs enumeration/cleanup */
424 void USB::Task(void) //USB state machine
428 static unsigned long delay = 0;
429 //USB_DEVICE_DESCRIPTOR buf;
430 bool lowspeed = false;
434 tmpdata = getVbusState();
436 /* modify USB task state if Vbus changed */
438 case SE1: //illegal state
439 usb_task_state = USB_DETACHED_SUBSTATE_ILLEGAL;
442 case SE0: //disconnected
443 if((usb_task_state & USB_STATE_MASK) != USB_STATE_DETACHED)
444 usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE;
450 //intentional fallthrough
451 case FSHOST: //attached
452 if((usb_task_state & USB_STATE_MASK) == USB_STATE_DETACHED) {
453 delay = millis() + USB_SETTLE_DELAY;
454 usb_task_state = USB_ATTACHED_SUBSTATE_SETTLE;
459 for(uint8_t i = 0; i < USB_NUMDEVICES; i++)
461 rcode = devConfig[i]->Poll();
463 switch(usb_task_state) {
464 case USB_DETACHED_SUBSTATE_INITIALIZE:
467 for(uint8_t i = 0; i < USB_NUMDEVICES; i++)
469 rcode = devConfig[i]->Release();
471 usb_task_state = USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE;
473 case USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE: //just sit here
475 case USB_DETACHED_SUBSTATE_ILLEGAL: //just sit here
477 case USB_ATTACHED_SUBSTATE_SETTLE: //settle time for just attached device
478 if((long)(millis() - delay) >= 0L)
479 usb_task_state = USB_ATTACHED_SUBSTATE_RESET_DEVICE;
480 else break; // don't fall through
481 case USB_ATTACHED_SUBSTATE_RESET_DEVICE:
482 regWr(rHCTL, bmBUSRST); //issue bus reset
483 usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE;
485 case USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE:
486 if((regRd(rHCTL) & bmBUSRST) == 0) {
487 tmpdata = regRd(rMODE) | bmSOFKAENAB; //start SOF generation
488 regWr(rMODE, tmpdata);
489 usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_SOF;
490 //delay = millis() + 20; //20ms wait after reset per USB spec
493 case USB_ATTACHED_SUBSTATE_WAIT_SOF: //todo: change check order
494 if(regRd(rHIRQ) & bmFRAMEIRQ) {
495 //when first SOF received _and_ 20ms has passed we can continue
497 if (delay < millis()) //20ms passed
498 usb_task_state = USB_STATE_CONFIGURING;
500 usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET;
501 delay = millis() + 20;
504 case USB_ATTACHED_SUBSTATE_WAIT_RESET:
505 if((long)(millis() - delay) >= 0L) usb_task_state = USB_STATE_CONFIGURING;
506 else break; // don't fall through
507 case USB_STATE_CONFIGURING:
509 //Serial.print("\r\nConf.LS: ");
510 //Serial.println(lowspeed, HEX);
512 rcode = Configuring(0, 0, lowspeed);
515 if(rcode != USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE) {
517 usb_task_state = USB_STATE_ERROR;
520 usb_task_state = USB_STATE_RUNNING;
522 case USB_STATE_RUNNING:
524 case USB_STATE_ERROR:
527 } // switch( usb_task_state )
530 uint8_t USB::DefaultAddressing(uint8_t parent, uint8_t port, bool lowspeed) {
533 UsbDevice *p0 = NULL, *p = NULL;
535 // Get pointer to pseudo device with address 0 assigned
536 p0 = addrPool.GetUsbDevicePtr(0);
539 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
542 return USB_ERROR_EPINFO_IS_NULL;
544 p0->lowspeed = (lowspeed) ? true : false;
546 // Allocate new address according to device class
547 uint8_t bAddress = addrPool.AllocAddress(parent, false, port);
550 return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
552 p = addrPool.GetUsbDevicePtr(bAddress);
555 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
557 p->lowspeed = lowspeed;
559 // Assign new address to the device
560 rcode = setAddr(0, 0, bAddress);
563 addrPool.FreeAddress(bAddress);
570 uint8_t USB::AttemptConfig(uint8_t driver, uint8_t parent, uint8_t port, bool lowspeed) {
571 //printf("AttemptConfig: parent = %i, port = %i\r\n", parent, port);
575 uint8_t rcode = devConfig[driver]->ConfigureDevice(parent, port, lowspeed);
576 if(rcode == USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET) {
578 // Send a bus reset on the root interface.
579 regWr(rHCTL, bmBUSRST); //issue bus reset
580 delay(102); // delay 102ms, compensate for clock inaccuracy.
583 devConfig[parent]->ResetHubPort(port);
585 } else if(rcode == hrJERR && retries < 3) { // Some devices returns this when plugged in - trying to initialize the device again usually works
592 rcode = devConfig[driver]->Init(parent, port, lowspeed);
593 if(rcode == hrJERR && retries < 3) { // Some devices returns this when plugged in - trying to initialize the device again usually works
599 // Issue a bus reset, because the device may be in a limbo state
601 // Send a bus reset on the root interface.
602 regWr(rHCTL, bmBUSRST); //issue bus reset
603 delay(102); // delay 102ms, compensate for clock inaccuracy.
606 devConfig[parent]->ResetHubPort(port);
613 * This is broken. We need to enumerate differently.
614 * It causes major problems with several devices if detected in an unexpected order.
617 * Oleg - I wouldn't do anything before the newly connected device is considered sane.
618 * i.e.(delays are not indicated for brevity):
621 * 3a. If ACK, continue with allocating address, addressing, etc.
622 * 3b. Else reset again, count resets, stop at some number (5?).
623 * 4. When max.number of resets is reached, toggle power/fail
624 * If desired, this could be modified by performing two resets with GetDevDescr() in the middle - however, from my experience, if a device answers to GDD()
625 * it doesn't need to be reset again
626 * New steps proposal:
627 * 1: get address pool instance. exit on fail
628 * 2: pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf). exit on fail.
629 * 3: bus reset, 100ms delay
631 * 5: pUsb->setEpInfoEntry(bAddress, 1, epInfo), exit on fail
632 * 6: while (configurations) {
633 * for(each configuration) {
634 * for (each driver) {
635 * 6a: Ask device if it likes configuration. Returns 0 on OK.
636 * If successful, the driver configured device.
637 * The driver now owns the endpoints, and takes over managing them.
638 * The following will need codes:
639 * Everything went well, instance consumed, exit with success.
640 * Instance already in use, ignore it, try next driver.
641 * Not a supported device, ignore it, try next driver.
642 * Not a supported configuration for this device, ignore it, try next driver.
643 * Could not configure device, fatal, exit with fail.
647 * 7: for(each driver) {
648 * 7a: Ask device if it knows this VID/PID. Acts exactly like 6a, but using VID/PID
649 * 8: if we get here, no driver likes the device plugged in, so exit failure.
652 uint8_t USB::Configuring(uint8_t parent, uint8_t port, bool lowspeed) {
653 //uint8_t bAddress = 0;
654 //printf("Configuring: parent = %i, port = %i\r\n", parent, port);
655 uint8_t devConfigIndex;
657 uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)];
658 USB_DEVICE_DESCRIPTOR *udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR *>(buf);
660 EpInfo *oldep_ptr = NULL;
664 epInfo.maxPktSize = 8;
665 epInfo.epAttribs = 0;
666 epInfo.bmNakPower = USB_NAK_MAX_POWER;
669 AddressPool &addrPool = GetAddressPool();
670 // Get pointer to pseudo device with address 0 assigned
671 p = addrPool.GetUsbDevicePtr(0);
673 //printf("Configuring error: USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL\r\n");
674 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
677 // Save old pointer to EP_RECORD of address 0
678 oldep_ptr = p->epinfo;
680 // Temporary assign new pointer to epInfo to p->epinfo in order to
681 // avoid toggle inconsistence
685 p->lowspeed = lowspeed;
686 // Get device descriptor
687 rcode = getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf);
690 p->epinfo = oldep_ptr;
693 //printf("Configuring error: Can't get USB_DEVICE_DESCRIPTOR\r\n");
698 // Allocate new address according to device class
699 //bAddress = addrPool.AllocAddress(parent, false, port);
701 uint16_t vid = udd->idVendor;
702 uint16_t pid = udd->idProduct;
703 uint8_t klass = udd->bDeviceClass;
704 uint8_t subklass = udd->bDeviceSubClass;
705 // Attempt to configure if VID/PID or device class matches with a driver
706 // Qualify with subclass too.
708 // VID/PID & class tests default to false for drivers not yet ported
709 // subclass defaults to true, so you don't have to define it if you don't have to.
711 for(devConfigIndex = 0; devConfigIndex < USB_NUMDEVICES; devConfigIndex++) {
712 if(!devConfig[devConfigIndex]) continue; // no driver
713 if(devConfig[devConfigIndex]->GetAddress()) continue; // consumed
714 if(devConfig[devConfigIndex]->DEVSUBCLASSOK(subklass) && (devConfig[devConfigIndex]->VIDPIDOK(vid, pid) || devConfig[devConfigIndex]->DEVCLASSOK(klass))) {
715 rcode = AttemptConfig(devConfigIndex, parent, port, lowspeed);
716 if(rcode != USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED)
721 if(devConfigIndex < USB_NUMDEVICES) {
726 // blindly attempt to configure
727 for(devConfigIndex = 0; devConfigIndex < USB_NUMDEVICES; devConfigIndex++) {
728 if(!devConfig[devConfigIndex]) continue;
729 if(devConfig[devConfigIndex]->GetAddress()) continue; // consumed
730 if(devConfig[devConfigIndex]->DEVSUBCLASSOK(subklass) && (devConfig[devConfigIndex]->VIDPIDOK(vid, pid) || devConfig[devConfigIndex]->DEVCLASSOK(klass))) continue; // If this is true it means it must have returned USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED above
731 rcode = AttemptConfig(devConfigIndex, parent, port, lowspeed);
733 //printf("ERROR ENUMERATING %2.2x\r\n", rcode);
734 if(!(rcode == USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED || rcode == USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE)) {
735 // in case of an error dev_index should be reset to 0
736 // in order to start from the very beginning the
737 // next time the program gets here
738 //if (rcode != USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE)
739 // devConfigIndex = 0;
743 // if we get here that means that the device class is not supported by any of registered classes
744 rcode = DefaultAddressing(parent, port, lowspeed);
749 uint8_t USB::ReleaseDevice(uint8_t addr) {
753 for(uint8_t i = 0; i < USB_NUMDEVICES; i++) {
754 if(!devConfig[i]) continue;
755 if(devConfig[i]->GetAddress() == addr)
756 return devConfig[i]->Release();
761 #if 1 //!defined(USB_METHODS_INLINE)
762 //get device descriptor
764 uint8_t USB::getDevDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr) {
765 return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, nbytes, dataptr, NULL));
767 //get configuration descriptor
769 uint8_t USB::getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t* dataptr) {
770 return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, nbytes, dataptr, NULL));
773 /* Requests Configuration Descriptor. Sends two Get Conf Descr requests. The first one gets the total length of all descriptors, then the second one requests this
774 total length. The length of the first request can be shorter ( 4 bytes ), however, there are devices which won't work unless this length is set to 9 */
775 uint8_t USB::getConfDescr(uint8_t addr, uint8_t ep, uint8_t conf, USBReadParser *p) {
776 const uint8_t bufSize = 64;
777 uint8_t buf[bufSize];
778 USB_CONFIGURATION_DESCRIPTOR *ucd = reinterpret_cast<USB_CONFIGURATION_DESCRIPTOR *>(buf);
780 uint8_t ret = getConfDescr(addr, ep, 9, conf, buf);
785 uint16_t total = ucd->wTotalLength;
787 //USBTRACE2("\r\ntotal conf.size:", total);
789 return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, total, bufSize, buf, p));
792 //get string descriptor
794 uint8_t USB::getStrDescr(uint8_t addr, uint8_t ep, uint16_t ns, uint8_t index, uint16_t langid, uint8_t* dataptr) {
795 return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, ns, ns, dataptr, NULL));
799 uint8_t USB::setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr) {
800 uint8_t rcode = ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL);
801 //delay(2); //per USB 2.0 sect.9.2.6.3
802 delay(300); // Older spec says you should wait at least 200ms
804 //return ( ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL));
808 uint8_t USB::setConf(uint8_t addr, uint8_t ep, uint8_t conf_value) {
809 return ( ctrlReq(addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL));
812 #endif // defined(USB_METHODS_INLINE)