Zoltan Hudak / UsbHostMAX3421E

Dependents:   UsbHostMAX3421E_Hello

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Usb.cpp Source File

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)