Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: UsbHostMAX3421E_Hello
Usb.cpp
00001 /* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. 00002 00003 This software may be distributed and modified under the terms of the GNU 00004 General Public License version 2 (GPL2) as published by the Free Software 00005 Foundation and appearing in the file GPL2.TXT included in the packaging of 00006 this file. Please note that GPL2 Section 2[b] requires that all works based 00007 on this software must also be made publicly available under the terms of 00008 the GPL2 ("Copyleft"). 00009 00010 Contact information 00011 ------------------- 00012 00013 Circuits At Home, LTD 00014 Web : http://www.circuitsathome.com 00015 e-mail : support@circuitsathome.com 00016 */ 00017 /* USB functions */ 00018 #include "Usb.h" 00019 00020 static uint8_t usb_error = 0; 00021 static uint8_t usb_task_state; 00022 00023 /* constructor */ 00024 Usb::Usb(PinName mosi, PinName miso, PinName sck, PinName ss, PinName intr) : 00025 MAX3421E(mosi, miso, sck, ss, intr), 00026 bmHubPre(0) 00027 { 00028 usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE; //set up state machine 00029 //init(); 00030 } 00031 00032 /* Initialize data structures */ 00033 int8_t Usb::init() 00034 { 00035 //devConfigIndex = 0; 00036 bmHubPre = 0; 00037 return MAX3421E::init(); 00038 } 00039 00040 /** 00041 * @brief 00042 * @note 00043 * @param 00044 * @retval 00045 */ 00046 uint8_t Usb::getUsbTaskState(void) 00047 { 00048 return(usb_task_state); 00049 } 00050 00051 /** 00052 * @brief 00053 * @note 00054 * @param 00055 * @retval 00056 */ 00057 void Usb::setUsbTaskState(uint8_t state) 00058 { 00059 usb_task_state = state; 00060 } 00061 00062 /** 00063 * @brief 00064 * @note 00065 * @param 00066 * @retval 00067 */ 00068 EpInfo* Usb::getEpInfoEntry(uint8_t addr, uint8_t ep) 00069 { 00070 UsbDevice* p = addrPool.GetUsbDevicePtr(addr); 00071 00072 if (!p || !p->epinfo) 00073 return NULL; 00074 00075 EpInfo* pep = p->epinfo; 00076 00077 for (uint8_t i = 0; i < p->epcount; i++) { 00078 if ((pep)->epAddr == ep) 00079 return pep; 00080 00081 pep++; 00082 } 00083 00084 return NULL; 00085 } 00086 00087 /* set device table entry */ 00088 00089 /* each device is different and has different number of endpoints. This function plugs endpoint record structure, defined in application, to devtable */ 00090 uint8_t Usb::setEpInfoEntry(uint8_t addr, uint8_t epcount, EpInfo* eprecord_ptr) 00091 { 00092 if (!eprecord_ptr) 00093 return USB_ERROR_INVALID_ARGUMENT; 00094 00095 UsbDevice* p = addrPool.GetUsbDevicePtr(addr); 00096 00097 if (!p) 00098 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; 00099 00100 p->address.devAddress = addr; 00101 p->epinfo = eprecord_ptr; 00102 p->epcount = epcount; 00103 00104 return 0; 00105 } 00106 00107 /** 00108 * @brief 00109 * @note 00110 * @param 00111 * @retval 00112 */ 00113 uint8_t Usb::setAddress(uint8_t addr, uint8_t ep, EpInfo ** ppep, uint16_t* nak_limit) 00114 { 00115 UsbDevice* p = addrPool.GetUsbDevicePtr(addr); 00116 00117 if (!p) 00118 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; 00119 00120 if (!p->epinfo) 00121 return USB_ERROR_EPINFO_IS_NULL; 00122 00123 *ppep = getEpInfoEntry(addr, ep); 00124 00125 if (!*ppep) 00126 return USB_ERROR_EP_NOT_FOUND_IN_TBL; 00127 00128 *nak_limit = (0x0001UL << (((*ppep)->bmNakPower > USB_NAK_MAX_POWER) ? USB_NAK_MAX_POWER : (*ppep)->bmNakPower)); 00129 (*nak_limit)--; 00130 00131 /* 00132 USBTRACE2("\r\nAddress: ", addr); 00133 USBTRACE2(" EP: ", ep); 00134 USBTRACE2(" NAK Power: ",(*ppep)->bmNakPower); 00135 USBTRACE2(" NAK Limit: ", nak_limit); 00136 USBTRACE("\r\n"); 00137 */ 00138 regWr(rPERADDR, addr); //set peripheral address 00139 uint8_t mode = regRd(rMODE); 00140 00141 //Serial.print("\r\nMode: "); 00142 00143 //Serial.println( mode, HEX); 00144 //Serial.print("\r\nLS: "); 00145 //Serial.println(p->lowspeed, HEX); 00146 // Set bmLOWSPEED and bmHUBPRE in case of low-speed device, reset them otherwise 00147 regWr(rMODE, (p->lowspeed) ? mode | bmLOWSPEED | bmHubPre : mode &~(bmHUBPRE | bmLOWSPEED)); 00148 00149 return 0; 00150 } 00151 00152 /* Control transfer. Sets address, endpoint, fills control packet with necessary data, dispatches control packet, and initiates bulk IN transfer, */ 00153 /* depending on request. Actual requests are defined as inlines */ 00154 /* return codes: */ 00155 /* 00 = success */ 00156 00157 /* 01-0f = non-zero HRSLT */ 00158 uint8_t Usb::ctrlReq 00159 ( 00160 uint8_t addr, 00161 uint8_t ep, 00162 uint8_t bmReqType, 00163 uint8_t bRequest, 00164 uint8_t wValLo, 00165 uint8_t wValHi, 00166 uint16_t wInd, 00167 uint16_t total, 00168 uint16_t nbytes, 00169 uint8_t* dataptr, 00170 USBReadParser* p 00171 ) 00172 { 00173 bool direction = false; //request direction, IN or OUT 00174 uint8_t rcode; 00175 SETUP_PKT setup_pkt; 00176 00177 EpInfo* pep = NULL; 00178 uint16_t nak_limit = 0; 00179 00180 rcode = setAddress(addr, ep, &pep, &nak_limit); 00181 00182 if (rcode) 00183 return rcode; 00184 00185 direction = ((bmReqType & 0x80) > 0); 00186 00187 /* fill in setup packet */ 00188 setup_pkt.ReqType_u.bmRequestType = bmReqType; 00189 setup_pkt.bRequest = bRequest; 00190 setup_pkt.wVal_u.wValueLo = wValLo; 00191 setup_pkt.wVal_u.wValueHi = wValHi; 00192 setup_pkt.wIndex = wInd; 00193 setup_pkt.wLength = total; 00194 00195 bytesWr(rSUDFIFO, 8, (uint8_t*) &setup_pkt); //transfer to setup packet FIFO 00196 rcode = dispatchPkt(tokSETUP, ep, nak_limit); //dispatch packet 00197 if (rcode) //return HRSLT if not zero 00198 return(rcode); 00199 00200 if (dataptr != NULL) { 00201 00202 //data stage, if present 00203 if (direction) { 00204 00205 //IN transfer 00206 uint16_t left = total; 00207 00208 pep->bmRcvToggle = 1; //bmRCVTOG1; 00209 while (left) 00210 { 00211 // Bytes read into buffer 00212 #if defined(ESP8266) || defined(ESP32) 00213 yield(); // needed in order to reset the watchdog timer on the ESP8266 00214 #endif 00215 00216 uint16_t read = nbytes; 00217 //uint16_t read = (left<nbytes) ? left : nbytes; 00218 00219 rcode = inTransfer(pep, nak_limit, &read, dataptr); 00220 if (rcode == hrTOGERR) { 00221 00222 // yes, we flip it wrong here so that next time it is actually correct! 00223 pep->bmRcvToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1; 00224 continue; 00225 } 00226 00227 if (rcode) 00228 return rcode; 00229 00230 // Invoke callback function if inTransfer completed successfully and callback function pointer is specified 00231 if (!rcode && p) 00232 ((USBReadParser*)p)->Parse(read, dataptr, total - left); 00233 00234 left -= read; 00235 00236 if (read < nbytes) 00237 break; 00238 } 00239 } 00240 else { 00241 00242 //OUT transfer 00243 pep->bmSndToggle = 1; //bmSNDTOG1; 00244 rcode = outTransfer(pep, nak_limit, nbytes, dataptr); 00245 } 00246 00247 if (rcode) //return error 00248 return(rcode); 00249 } 00250 00251 // Status stage 00252 return dispatchPkt((direction) ? tokOUTHS : tokINHS, ep, nak_limit); //GET if direction 00253 } 00254 00255 /* IN transfer to arbitrary endpoint. Assumes PERADDR is set. Handles multiple packets if necessary. Transfers 'nbytes' bytes. */ 00256 /* Keep sending INs and writes data to memory area pointed by 'data' */ 00257 00258 /* rcode 0 if no errors. rcode 01-0f is relayed from dispatchPkt(). Rcode f0 means RCVDAVIRQ error, 00259 fe USB xfer timeout */ 00260 uint8_t Usb::inTransfer(uint8_t addr, uint8_t ep, uint16_t* nbytesptr, uint8_t* data, uint8_t bInterval /*= 0*/ ) 00261 { 00262 EpInfo* pep = NULL; 00263 uint16_t nak_limit = 0; 00264 00265 uint8_t rcode = setAddress(addr, ep, &pep, &nak_limit); 00266 00267 if (rcode) { 00268 USBTRACE3("(USB::InTransfer) SetAddress Failed ", rcode, 0x81); 00269 USBTRACE3("(USB::InTransfer) addr requested ", addr, 0x81); 00270 USBTRACE3("(USB::InTransfer) ep requested ", ep, 0x81); 00271 return rcode; 00272 } 00273 00274 return inTransfer(pep, nak_limit, nbytesptr, data, bInterval); 00275 } 00276 00277 /** 00278 * @brief 00279 * @note 00280 * @param 00281 * @retval 00282 */ 00283 uint8_t Usb::inTransfer(EpInfo* pep, uint16_t nak_limit, uint16_t* nbytesptr, uint8_t* data, uint8_t bInterval /*= 0*/ ) 00284 { 00285 uint8_t rcode = 0; 00286 uint8_t pktsize; 00287 00288 uint16_t nbytes = *nbytesptr; 00289 00290 //printf("Requesting %i bytes ", nbytes); 00291 uint8_t maxpktsize = pep->maxPktSize; 00292 00293 *nbytesptr = 0; 00294 regWr(rHCTL, (pep->bmRcvToggle) ? bmRCVTOG1 : bmRCVTOG0); //set toggle value 00295 00296 // use a 'break' to exit this loop 00297 while (1) 00298 { 00299 #if defined(ESP8266) || defined(ESP32) 00300 yield(); // needed in order to reset the watchdog timer on the ESP8266 00301 #endif 00302 rcode = dispatchPkt(tokIN, pep->epAddr, nak_limit); //IN packet to EP-'endpoint'. Function takes care of NAKS. 00303 if (rcode == hrTOGERR) { 00304 00305 // yes, we flip it wrong here so that next time it is actually correct! 00306 pep->bmRcvToggle = (regRd(rHRSL) & bmRCVTOGRD) ? 0 : 1; 00307 regWr(rHCTL, (pep->bmRcvToggle) ? bmRCVTOG1 : bmRCVTOG0); //set toggle value 00308 continue; 00309 } 00310 00311 if (rcode) { 00312 00313 //printf(">>>>>>>> Problem! dispatchPkt %2.2x\r\n", rcode); 00314 break; //should be 0, indicating ACK. Else return error code. 00315 } 00316 00317 /* check for RCVDAVIRQ and generate error if not present 00318 * the only case when absence of RCVDAVIRQ makes sense is when toggle error occurred. 00319 * Need to add handling for that 00320 * 00321 * NOTE: I've seen this happen with SPI corruption -- xxxajk 00322 */ 00323 if ((regRd(rHIRQ) & bmRCVDAVIRQ) == 0) { 00324 00325 //printf(">>>>>>>> Problem! NO RCVDAVIRQ!\r\n"); 00326 rcode = 0xf0; //receive error 00327 break; 00328 } 00329 00330 pktsize = regRd(rRCVBC); //number of received bytes 00331 00332 //printf("Got %i bytes \r\n", pktsize); 00333 // This would be OK, but... 00334 //assert(pktsize <= nbytes); 00335 if (pktsize > nbytes) { 00336 00337 // This can happen. Use of assert on Arduino locks up the Arduino. 00338 // So I will trim the value, and hope for the best. 00339 //printf(">>>>>>>> Problem! Wanted %i bytes but got %i.\r\n", nbytes, pktsize); 00340 pktsize = nbytes; 00341 } 00342 00343 int16_t mem_left = (int16_t) nbytes -*((int16_t*)nbytesptr); 00344 00345 if (mem_left < 0) 00346 mem_left = 0; 00347 00348 data = bytesRd(rRCVFIFO, ((pktsize > mem_left) ? mem_left : pktsize), data); 00349 00350 regWr(rHIRQ, bmRCVDAVIRQ); // Clear the IRQ & free the buffer 00351 *nbytesptr += pktsize; // add this packet's byte count to total transfer length 00352 00353 /* The transfer is complete under two conditions: */ 00354 /* 1. The device sent a short packet (L.T. maxPacketSize) */ 00355 /* 2. 'nbytes' have been transferred. */ 00356 if ((pktsize < maxpktsize) || (*nbytesptr >= nbytes)) { 00357 00358 // have we transferred 'nbytes' bytes? 00359 // Save toggle value 00360 pep->bmRcvToggle = ((regRd(rHRSL) & bmRCVTOGRD)) ? 1 : 0; 00361 00362 //printf("\r\n"); 00363 rcode = 0; 00364 break; 00365 } 00366 else 00367 if (bInterval > 0) 00368 wait_ms(bInterval); // Delay according to polling interval 00369 } //while( 1 ) 00370 00371 return(rcode); 00372 } 00373 00374 /* OUT transfer to arbitrary endpoint. Handles multiple packets if necessary. Transfers 'nbytes' bytes. */ 00375 /* Handles NAK bug per Maxim Application Note 4000 for single buffer transfer */ 00376 00377 /* rcode 0 if no errors. rcode 01-0f is relayed from HRSL */ 00378 uint8_t Usb::outTransfer(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* data) 00379 { 00380 EpInfo* pep = NULL; 00381 uint16_t nak_limit = 0; 00382 00383 uint8_t rcode = setAddress(addr, ep, &pep, &nak_limit); 00384 00385 if (rcode) 00386 return rcode; 00387 00388 return outTransfer(pep, nak_limit, nbytes, data); 00389 } 00390 00391 /** 00392 * @brief 00393 * @note 00394 * @param 00395 * @retval 00396 */ 00397 uint8_t Usb::outTransfer(EpInfo* pep, uint16_t nak_limit, uint16_t nbytes, uint8_t* data) 00398 { 00399 uint8_t rcode = hrSUCCESS, retry_count; 00400 uint8_t* data_p = data; //local copy of the data pointer 00401 uint16_t bytes_tosend, nak_count; 00402 uint16_t bytes_left = nbytes; 00403 00404 uint8_t maxpktsize = pep->maxPktSize; 00405 00406 if (maxpktsize < 1 || maxpktsize > 64) 00407 return USB_ERROR_INVALID_MAX_PKT_SIZE; 00408 00409 uint32_t timeout = (uint32_t)millis() + USB_XFER_TIMEOUT; 00410 00411 regWr(rHCTL, (pep->bmSndToggle) ? bmSNDTOG1 : bmSNDTOG0); //set toggle value 00412 while (bytes_left) 00413 { 00414 #if defined(ESP8266) || defined(ESP32) 00415 yield(); // needed in order to reset the watchdog timer on the ESP8266 00416 #endif 00417 retry_count = 0; 00418 nak_count = 0; 00419 bytes_tosend = (bytes_left >= maxpktsize) ? maxpktsize : bytes_left; 00420 bytesWr(rSNDFIFO, bytes_tosend, data_p); //filling output FIFO 00421 regWr(rSNDBC, bytes_tosend); //set number of bytes 00422 regWr(rHXFR, (tokOUT | pep->epAddr)); //dispatch packet 00423 while (!(regRd(rHIRQ) & bmHXFRDNIRQ)) 00424 { 00425 #if defined(ESP8266) || defined(ESP32) 00426 yield(); // needed in order to reset the watchdog timer on the ESP8266 00427 #endif 00428 } //wait for the completion IRQ 00429 00430 regWr(rHIRQ, bmHXFRDNIRQ); //clear IRQ 00431 rcode = (regRd(rHRSL) & 0x0f); 00432 00433 while (rcode && ((int32_t) ((uint32_t)millis() - timeout) < 0L)) 00434 { 00435 #if defined(ESP8266) || defined(ESP32) 00436 yield(); // needed in order to reset the watchdog timer on the ESP8266 00437 #endif 00438 switch (rcode) { 00439 case hrNAK: 00440 nak_count++; 00441 if (nak_limit && (nak_count == nak_limit)) 00442 goto breakout; 00443 00444 //return ( rcode); 00445 break; 00446 00447 case hrTIMEOUT: 00448 retry_count++; 00449 if (retry_count == USB_RETRY_LIMIT) 00450 goto breakout; 00451 00452 //return ( rcode); 00453 break; 00454 00455 case hrTOGERR: 00456 // yes, we flip it wrong here so that next time it is actually correct! 00457 pep->bmSndToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1; 00458 regWr(rHCTL, (pep->bmSndToggle) ? bmSNDTOG1 : bmSNDTOG0); //set toggle value 00459 break; 00460 00461 default: 00462 goto breakout; 00463 } //switch( rcode 00464 00465 /* process NAK according to Host out NAK bug */ 00466 regWr(rSNDBC, 0); 00467 regWr(rSNDFIFO, *data_p); 00468 regWr(rSNDBC, bytes_tosend); 00469 regWr(rHXFR, (tokOUT | pep->epAddr)); //dispatch packet 00470 while (!(regRd(rHIRQ) & bmHXFRDNIRQ)) 00471 { 00472 #if defined(ESP8266) || defined(ESP32) 00473 yield(); // needed in order to reset the watchdog timer on the ESP8266 00474 #endif 00475 } //wait for the completion IRQ 00476 00477 regWr(rHIRQ, bmHXFRDNIRQ); //clear IRQ 00478 rcode = (regRd(rHRSL) & 0x0f); 00479 } //while( rcode && .... 00480 00481 bytes_left -= bytes_tosend; 00482 data_p += bytes_tosend; 00483 } //while( bytes_left... 00484 00485 breakout: 00486 pep->bmSndToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 1 : 0; //bmSNDTOG1 : bmSNDTOG0; //update toggle 00487 return(rcode); //should be 0 in all cases 00488 } 00489 00490 /* dispatch USB packet. Assumes peripheral address is set and relevant buffer is loaded/empty */ 00491 /* If NAK, tries to re-send up to nak_limit times */ 00492 /* If nak_limit == 0, do not count NAKs, exit after timeout */ 00493 /* If bus timeout, re-sends up to USB_RETRY_LIMIT times */ 00494 00495 /* return codes 0x00-0x0f are HRSLT( 0x00 being success ), 0xff means timeout */ 00496 uint8_t Usb::dispatchPkt(uint8_t token, uint8_t ep, uint16_t nak_limit) 00497 { 00498 uint32_t timeout = (uint32_t)millis() + USB_XFER_TIMEOUT; 00499 uint8_t tmpdata; 00500 uint8_t rcode = hrSUCCESS; 00501 uint8_t retry_count = 0; 00502 uint16_t nak_count = 0; 00503 00504 while ((int32_t) ((uint32_t)millis() - timeout) < 0L) 00505 { 00506 #if defined(ESP8266) || defined(ESP32) 00507 yield(); // needed in order to reset the watchdog timer on the ESP8266 00508 #endif 00509 regWr(rHXFR, (token | ep)); //launch the transfer 00510 rcode = USB_ERROR_TRANSFER_TIMEOUT; 00511 00512 while ((int32_t) ((uint32_t)millis() - timeout) < 0L) //wait for transfer completion 00513 { 00514 #if defined(ESP8266) || defined(ESP32) 00515 yield(); // needed in order to reset the watchdog timer on the ESP8266 00516 #endif 00517 tmpdata = regRd(rHIRQ); 00518 00519 if (tmpdata & bmHXFRDNIRQ) { 00520 regWr(rHIRQ, bmHXFRDNIRQ); //clear the interrupt 00521 rcode = 0x00; 00522 break; 00523 } //if( tmpdata & bmHXFRDNIRQ 00524 } //while ( millis() < timeout 00525 00526 //if (rcode != 0x00) //exit if timeout 00527 // return ( rcode); 00528 rcode = (regRd(rHRSL) & 0x0f); //analyze transfer result 00529 switch (rcode) { 00530 case hrNAK: 00531 nak_count++; 00532 if (nak_limit && (nak_count == nak_limit)) 00533 return(rcode); 00534 break; 00535 00536 case hrTIMEOUT: 00537 retry_count++; 00538 if (retry_count == USB_RETRY_LIMIT) 00539 return(rcode); 00540 break; 00541 00542 default: 00543 return(rcode); 00544 } //switch( rcode 00545 } //while( timeout > millis() 00546 00547 return(rcode); 00548 } 00549 00550 /* USB main task. Performs enumeration/cleanup */ 00551 void Usb::task(void) //USB state machine 00552 { 00553 uint8_t rcode; 00554 uint8_t tmpdata; 00555 static uint32_t delay = 0; 00556 00557 //USB_DEVICE_DESCRIPTOR buf; 00558 bool lowspeed = false; 00559 00560 MAX3421E::task(); 00561 00562 tmpdata = getVbusState(); 00563 00564 /* modify USB task state if Vbus changed */ 00565 switch (tmpdata) { 00566 case SE1: //illegal state 00567 usb_task_state = USB_DETACHED_SUBSTATE_ILLEGAL; 00568 lowspeed = false; 00569 break; 00570 00571 case SE0: //disconnected 00572 if ((usb_task_state & USB_STATE_MASK) != USB_STATE_DETACHED) 00573 usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE; 00574 lowspeed = false; 00575 break; 00576 00577 case LSHOST: 00578 lowspeed = true; 00579 00580 //intentional fallthrough 00581 case FSHOST: //attached 00582 if ((usb_task_state & USB_STATE_MASK) == USB_STATE_DETACHED) { 00583 delay = (uint32_t)millis() + USB_SETTLE_DELAY; 00584 usb_task_state = USB_ATTACHED_SUBSTATE_SETTLE; 00585 } 00586 break; 00587 } // switch( tmpdata 00588 00589 for (uint8_t i = 0; i < USB_NUMDEVICES; i++) 00590 if (devConfig[i]) 00591 rcode = devConfig[i]->Poll(); 00592 00593 switch (usb_task_state) { 00594 case USB_DETACHED_SUBSTATE_INITIALIZE: 00595 init(); 00596 00597 for (uint8_t i = 0; i < USB_NUMDEVICES; i++) 00598 if (devConfig[i]) 00599 rcode = devConfig[i]->Release(); 00600 00601 usb_task_state = USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE; 00602 break; 00603 00604 case USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE: //just sit here 00605 break; 00606 00607 case USB_DETACHED_SUBSTATE_ILLEGAL: //just sit here 00608 break; 00609 00610 case USB_ATTACHED_SUBSTATE_SETTLE: //settle time for just attached device 00611 if ((int32_t) ((uint32_t)millis() - delay) >= 0L) 00612 usb_task_state = USB_ATTACHED_SUBSTATE_RESET_DEVICE; 00613 else 00614 break; // don't fall through 00615 00616 case USB_ATTACHED_SUBSTATE_RESET_DEVICE: 00617 regWr(rHCTL, bmBUSRST); //issue bus reset 00618 usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE; 00619 break; 00620 00621 case USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE: 00622 if ((regRd(rHCTL) & bmBUSRST) == 0) { 00623 tmpdata = regRd(rMODE) | bmSOFKAENAB; //start SOF generation 00624 regWr(rMODE, tmpdata); 00625 usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_SOF; 00626 00627 //delay = (uint32_t)millis() + 20; //20ms wait after reset per USB spec 00628 } 00629 break; 00630 00631 case USB_ATTACHED_SUBSTATE_WAIT_SOF: //todo: change check order 00632 if (regRd(rHIRQ) & bmFRAMEIRQ) { 00633 00634 //when first SOF received _and_ 20ms has passed we can continue 00635 /* 00636 if (delay < (uint32_t)millis()) //20ms passed 00637 usb_task_state = USB_STATE_CONFIGURING; 00638 */ 00639 usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET; 00640 delay = (uint32_t)millis() + 20; 00641 } 00642 break; 00643 00644 case USB_ATTACHED_SUBSTATE_WAIT_RESET: 00645 if ((int32_t) ((uint32_t)millis() - delay) >= 0L) 00646 usb_task_state = USB_STATE_CONFIGURING; 00647 else 00648 break; // don't fall through 00649 00650 case USB_STATE_CONFIGURING: 00651 //Serial.print("\r\nConf.LS: "); 00652 //Serial.println(lowspeed, HEX); 00653 rcode = configuring(0, 0, lowspeed); 00654 00655 if (rcode) { 00656 if (rcode != USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE) { 00657 usb_error = rcode; 00658 usb_task_state = USB_STATE_ERROR; 00659 } 00660 } 00661 else 00662 usb_task_state = USB_STATE_RUNNING; 00663 break; 00664 00665 case USB_STATE_RUNNING: 00666 break; 00667 00668 case USB_STATE_ERROR: 00669 //MAX3421E::Init(); 00670 break; 00671 } // switch( usb_task_state ) 00672 } 00673 00674 /** 00675 * @brief 00676 * @note 00677 * @param 00678 * @retval 00679 */ 00680 uint8_t Usb::defaultAddressing(uint8_t parent, uint8_t port, bool lowspeed) 00681 { 00682 //uint8_t buf[12]; 00683 uint8_t rcode; 00684 UsbDevice* p0 = NULL, *p = NULL; 00685 00686 // Get pointer to pseudo device with address 0 assigned 00687 00688 p0 = addrPool.GetUsbDevicePtr(0); 00689 00690 if (!p0) 00691 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; 00692 00693 if (!p0->epinfo) 00694 return USB_ERROR_EPINFO_IS_NULL; 00695 00696 p0->lowspeed = (lowspeed) ? true : false; 00697 00698 // Allocate new address according to device class 00699 uint8_t bAddress = addrPool.AllocAddress(parent, false, port); 00700 00701 if (!bAddress) 00702 return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; 00703 00704 p = addrPool.GetUsbDevicePtr(bAddress); 00705 00706 if (!p) 00707 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; 00708 00709 p->lowspeed = lowspeed; 00710 00711 // Assign new address to the device 00712 rcode = setAddr(0, 0, bAddress); 00713 00714 if (rcode) { 00715 addrPool.FreeAddress(bAddress); 00716 bAddress = 0; 00717 return rcode; 00718 } 00719 00720 return 0; 00721 } 00722 00723 /** 00724 * @brief 00725 * @note 00726 * @param 00727 * @retval 00728 */ 00729 uint8_t Usb::attemptConfig(uint8_t driver, uint8_t parent, uint8_t port, bool lowspeed) 00730 { 00731 //printf("AttemptConfig: parent = %i, port = %i\r\n", parent, port); 00732 uint8_t retries = 0; 00733 00734 again: 00735 uint8_t rcode = devConfig[driver]->ConfigureDevice(parent, port, lowspeed); 00736 if (rcode == USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET) { 00737 if (parent == 0) { 00738 00739 // Send a bus reset on the root interface. 00740 regWr(rHCTL, bmBUSRST); //issue bus reset 00741 wait_ms(102); // delay 102ms, compensate for clock inaccuracy. 00742 } 00743 else { 00744 00745 // reset parent port 00746 devConfig[parent]->ResetHubPort(port); 00747 } 00748 } 00749 else 00750 if (rcode == hrJERR && retries < 3) { 00751 00752 // Some devices returns this when plugged in - trying to initialize the device again usually works 00753 wait_ms(100); 00754 retries++; 00755 goto again; 00756 } 00757 else 00758 if (rcode) 00759 return rcode; 00760 00761 rcode = devConfig[driver]->Init(parent, port, lowspeed); 00762 if (rcode == hrJERR && retries < 3) { 00763 00764 // Some devices returns this when plugged in - trying to initialize the device again usually works 00765 wait_ms(100); 00766 retries++; 00767 goto again; 00768 } 00769 00770 if (rcode) { 00771 00772 // Issue a bus reset, because the device may be in a limbo state 00773 if (parent == 0) { 00774 00775 // Send a bus reset on the root interface. 00776 regWr(rHCTL, bmBUSRST); //issue bus reset 00777 wait_ms(102); // delay 102ms, compensate for clock inaccuracy. 00778 } 00779 else { 00780 00781 // reset parent port 00782 devConfig[parent]->ResetHubPort(port); 00783 } 00784 } 00785 00786 return rcode; 00787 } 00788 00789 /* 00790 * This is broken. We need to enumerate differently. 00791 * It causes major problems with several devices if detected in an unexpected order. 00792 * 00793 * 00794 * Oleg - I wouldn't do anything before the newly connected device is considered sane. 00795 * i.e.(delays are not indicated for brevity): 00796 * 1. reset 00797 * 2. GetDevDescr(); 00798 * 3a. If ACK, continue with allocating address, addressing, etc. 00799 * 3b. Else reset again, count resets, stop at some number (5?). 00800 * 4. When max.number of resets is reached, toggle power/fail 00801 * 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() 00802 * it doesn't need to be reset again 00803 * New steps proposal: 00804 * 1: get address pool instance. exit on fail 00805 * 2: pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf). exit on fail. 00806 * 3: bus reset, 100ms delay 00807 * 4: set address 00808 * 5: pUsb->setEpInfoEntry(bAddress, 1, epInfo), exit on fail 00809 * 6: while (configurations) { 00810 * for(each configuration) { 00811 * for (each driver) { 00812 * 6a: Ask device if it likes configuration. Returns 0 on OK. 00813 * If successful, the driver configured device. 00814 * The driver now owns the endpoints, and takes over managing them. 00815 * The following will need codes: 00816 * Everything went well, instance consumed, exit with success. 00817 * Instance already in use, ignore it, try next driver. 00818 * Not a supported device, ignore it, try next driver. 00819 * Not a supported configuration for this device, ignore it, try next driver. 00820 * Could not configure device, fatal, exit with fail. 00821 * } 00822 * } 00823 * } 00824 * 7: for(each driver) { 00825 * 7a: Ask device if it knows this VID/PID. Acts exactly like 6a, but using VID/PID 00826 * 8: if we get here, no driver likes the device plugged in, so exit failure. 00827 * 00828 */ 00829 uint8_t Usb::configuring(uint8_t parent, uint8_t port, bool lowspeed) 00830 { 00831 //uint8_t bAddress = 0; 00832 00833 //printf("Configuring: parent = %i, port = %i\r\n", parent, port); 00834 uint8_t devConfigIndex; 00835 uint8_t rcode = 0; 00836 uint8_t buf[sizeof(USB_DEVICE_DESCRIPTOR)]; 00837 USB_DEVICE_DESCRIPTOR* udd = reinterpret_cast < USB_DEVICE_DESCRIPTOR * > (buf); 00838 UsbDevice* p = NULL; 00839 EpInfo* oldep_ptr = NULL; 00840 EpInfo epInfo; 00841 00842 epInfo.epAddr = 0; 00843 epInfo.maxPktSize = 8; 00844 epInfo.bmSndToggle = 0; 00845 epInfo.bmRcvToggle = 0; 00846 epInfo.bmNakPower = USB_NAK_MAX_POWER; 00847 00848 //wait_ms(2000); 00849 AddressPool& addrPool = GetAddressPool(); 00850 // Get pointer to pseudo device with address 0 assigned 00851 00852 p = addrPool.GetUsbDevicePtr(0); 00853 if (!p) { 00854 00855 //printf("Configuring error: USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL\r\n"); 00856 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; 00857 } 00858 00859 // Save old pointer to EP_RECORD of address 0 00860 oldep_ptr = p->epinfo; 00861 00862 // Temporary assign new pointer to epInfo to p->epinfo in order to 00863 // avoid toggle inconsistence 00864 p->epinfo = &epInfo; 00865 00866 p->lowspeed = lowspeed; 00867 00868 // Get device descriptor 00869 rcode = getDevDescr(0, 0, sizeof(USB_DEVICE_DESCRIPTOR), (uint8_t*)buf); 00870 00871 // Restore p->epinfo 00872 p->epinfo = oldep_ptr; 00873 00874 if (rcode) { 00875 00876 //printf("Configuring error: Can't get USB_DEVICE_DESCRIPTOR\r\n"); 00877 return rcode; 00878 } 00879 00880 // to-do? 00881 // Allocate new address according to device class 00882 //bAddress = addrPool.AllocAddress(parent, false, port); 00883 uint16_t vid = udd->idVendor; 00884 uint16_t pid = udd->idProduct; 00885 uint8_t klass = udd->bDeviceClass; 00886 uint8_t subklass = udd->bDeviceSubClass; 00887 // Attempt to configure if VID/PID or device class matches with a driver 00888 00889 // Qualify with subclass too. 00890 // 00891 // VID/PID & class tests default to false for drivers not yet ported 00892 // subclass defaults to true, so you don't have to define it if you don't have to. 00893 // 00894 for (devConfigIndex = 0; devConfigIndex < USB_NUMDEVICES; devConfigIndex++) { 00895 if (!devConfig[devConfigIndex]) 00896 continue; // no driver 00897 if (devConfig[devConfigIndex]->GetAddress()) 00898 continue; // consumed 00899 if 00900 ( 00901 devConfig[devConfigIndex]->DEVSUBCLASSOK(subklass) && 00902 (devConfig[devConfigIndex]->VIDPIDOK(vid, pid) || devConfig[devConfigIndex]->DEVCLASSOK(klass)) 00903 ) { 00904 rcode = attemptConfig(devConfigIndex, parent, port, lowspeed); 00905 if (rcode != USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED) 00906 break; 00907 } 00908 } 00909 00910 if (devConfigIndex < USB_NUMDEVICES) { 00911 return rcode; 00912 } 00913 00914 // blindly attempt to configure 00915 for (devConfigIndex = 0; devConfigIndex < USB_NUMDEVICES; devConfigIndex++) { 00916 if (!devConfig[devConfigIndex]) 00917 continue; 00918 if (devConfig[devConfigIndex]->GetAddress()) 00919 continue; // consumed 00920 if 00921 ( 00922 devConfig[devConfigIndex]->DEVSUBCLASSOK(subklass) && 00923 (devConfig[devConfigIndex]->VIDPIDOK(vid, pid) || devConfig[devConfigIndex]->DEVCLASSOK(klass)) 00924 ) continue; // If this is true it means it must have returned USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED above 00925 rcode = attemptConfig(devConfigIndex, parent, port, lowspeed); 00926 00927 //printf("ERROR ENUMERATING %2.2x\r\n", rcode); 00928 if (!(rcode == USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED || rcode == USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE)) { 00929 00930 // in case of an error dev_index should be reset to 0 00931 // in order to start from the very beginning the 00932 // next time the program gets here 00933 //if (rcode != USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE) 00934 // devConfigIndex = 0; 00935 return rcode; 00936 } 00937 } 00938 00939 // if we get here that means that the device class is not supported by any of registered classes 00940 rcode = defaultAddressing(parent, port, lowspeed); 00941 00942 return rcode; 00943 } 00944 00945 /** 00946 * @brief 00947 * @note 00948 * @param 00949 * @retval 00950 */ 00951 uint8_t Usb::releaseDevice(uint8_t addr) 00952 { 00953 if (!addr) 00954 return 0; 00955 00956 for (uint8_t i = 0; i < USB_NUMDEVICES; i++) { 00957 if (!devConfig[i]) 00958 continue; 00959 if (devConfig[i]->GetAddress() == addr) 00960 return devConfig[i]->Release(); 00961 } 00962 00963 return 0; 00964 } 00965 00966 #if 1 //!defined(USB_METHODS_INLINE) 00967 00968 //get device descriptor 00969 uint8_t Usb::getDevDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr) 00970 { 00971 return 00972 ( 00973 ctrlReq 00974 ( 00975 addr, 00976 ep, 00977 bmREQ_GET_DESCR, 00978 USB_REQUEST_GET_DESCRIPTOR, 00979 0x00, 00980 USB_DESCRIPTOR_DEVICE, 00981 0x0000, 00982 nbytes, 00983 nbytes, 00984 dataptr, 00985 NULL 00986 ) 00987 ); 00988 } 00989 00990 //get configuration descriptor 00991 uint8_t Usb::getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t* dataptr) 00992 { 00993 return 00994 ( 00995 ctrlReq 00996 ( 00997 addr, 00998 ep, 00999 bmREQ_GET_DESCR, 01000 USB_REQUEST_GET_DESCRIPTOR, 01001 conf, 01002 USB_DESCRIPTOR_CONFIGURATION, 01003 0x0000, 01004 nbytes, 01005 nbytes, 01006 dataptr, 01007 NULL 01008 ) 01009 ); 01010 } 01011 01012 /* 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 01013 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 */ 01014 uint8_t Usb::getConfDescr(uint8_t addr, uint8_t ep, uint8_t conf, USBReadParser* p) 01015 { 01016 const uint8_t bufSize = 64; 01017 uint8_t buf[bufSize]; 01018 USB_CONFIGURATION_DESCRIPTOR* ucd = reinterpret_cast < USB_CONFIGURATION_DESCRIPTOR * > (buf); 01019 01020 uint8_t ret = getConfDescr(addr, ep, 9, conf, buf); 01021 01022 if (ret) 01023 return ret; 01024 01025 uint16_t total = ucd->wTotalLength; 01026 01027 //USBTRACE2("\r\ntotal conf.size:", total); 01028 01029 return 01030 ( 01031 ctrlReq 01032 ( 01033 addr, 01034 ep, 01035 bmREQ_GET_DESCR, 01036 USB_REQUEST_GET_DESCRIPTOR, 01037 conf, 01038 USB_DESCRIPTOR_CONFIGURATION, 01039 0x0000, 01040 total, 01041 bufSize, 01042 buf, 01043 p 01044 ) 01045 ); 01046 } 01047 01048 //get string descriptor 01049 uint8_t Usb::getStrDescr(uint8_t addr, uint8_t ep, uint16_t ns, uint8_t index, uint16_t langid, uint8_t* dataptr) 01050 { 01051 return 01052 ( 01053 ctrlReq 01054 ( 01055 addr, 01056 ep, 01057 bmREQ_GET_DESCR, 01058 USB_REQUEST_GET_DESCRIPTOR, 01059 index, 01060 USB_DESCRIPTOR_STRING, 01061 langid, 01062 ns, 01063 ns, 01064 dataptr, 01065 NULL 01066 ) 01067 ); 01068 } 01069 01070 //set address 01071 uint8_t Usb::setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr) 01072 { 01073 uint8_t rcode = ctrlReq 01074 ( 01075 oldaddr, 01076 ep, 01077 bmREQ_SET, 01078 USB_REQUEST_SET_ADDRESS, 01079 newaddr, 01080 0x00, 01081 0x0000, 01082 0x0000, 01083 0x0000, 01084 NULL, 01085 NULL 01086 ); 01087 //wait_ms(2); //per USB 2.0 sect.9.2.6.3 01088 01089 wait_ms(300); // Older spec says you should wait at least 200ms 01090 return rcode; 01091 01092 //return ( ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL)); 01093 } 01094 01095 //set configuration 01096 uint8_t Usb::setConf(uint8_t addr, uint8_t ep, uint8_t conf_value) 01097 { 01098 return 01099 ( 01100 ctrlReq 01101 ( 01102 addr, 01103 ep, 01104 bmREQ_SET, 01105 USB_REQUEST_SET_CONFIGURATION, 01106 conf_value, 01107 0x00, 01108 0x0000, 01109 0x0000, 01110 0x0000, 01111 NULL, 01112 NULL 01113 ) 01114 ); 01115 } 01116 #endif // defined(USB_METHODS_INLINE)
Generated on Tue Jul 12 2022 18:12:05 by
1.7.2