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