Usb.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright 2009-2011 Oleg Mazurov, Circuits At Home, http://www.circuitsathome.com
00003  * MAX3421E USB host controller support
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the authors nor the names of its contributors
00014  *    may be used to endorse or promote products derived from this software
00015  *    without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00018  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00021  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00023  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00024  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00025  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00026  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00027  * SUCH DAMAGE.
00028  */
00029 
00030 /* USB functions */
00031 
00032 #include "Usb.h"
00033 
00034 static byte usb_error = 0;
00035 static byte usb_task_state;
00036 DEV_RECORD devtable[ USB_NUMDEVICES + 1 ];
00037 EP_RECORD dev0ep;           //Endpoint data structure used during enumeration for uninitialized device
00038 
00039 
00040 /* constructor */
00041 
00042 USB::USB () {
00043     usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE;  //set up state machine
00044     init(); 
00045 }
00046 /* Initialize data structures */
00047 void USB::init()
00048 {
00049   byte i;
00050     for( i = 0; i < ( USB_NUMDEVICES + 1 ); i++ ) {
00051         devtable[ i ].epinfo = NULL;       //clear device table
00052         devtable[ i ].devclass = 0;
00053     }
00054     devtable[ 0 ].epinfo = &dev0ep; //set single ep for uninitialized device  
00055     // not necessary dev0ep.MaxPktSize = 8;          //minimum possible                         
00056     dev0ep.sndToggle = bmSNDTOG0;   //set DATA0/1 toggles to 0
00057     dev0ep.rcvToggle = bmRCVTOG0;
00058 }
00059 byte USB::getUsbTaskState( void )
00060 {
00061     return( usb_task_state );
00062 }
00063 void USB::setUsbTaskState( byte state )
00064 {
00065     usb_task_state = state;
00066 }     
00067 EP_RECORD* USB::getDevTableEntry( byte addr, byte ep )
00068 {
00069   EP_RECORD* ptr;
00070     ptr = devtable[ addr ].epinfo;
00071     ptr += ep;
00072     return( ptr );
00073 }
00074 /* set device table entry */
00075 /* each device is different and has different number of endpoints. This function plugs endpoint record structure, defined in application, to devtable */
00076 void USB::setDevTableEntry( byte addr, EP_RECORD* eprecord_ptr )
00077 {
00078     devtable[ addr ].epinfo = eprecord_ptr;
00079     //return();
00080 }
00081 /* Control transfer. Sets address, endpoint, fills control packet with necessary data, dispatches control packet, and initiates bulk IN transfer,   */
00082 /* depending on request. Actual requests are defined as inlines                                                                                      */
00083 /* return codes:                */
00084 /* 00       =   success         */
00085 /* 01-0f    =   non-zero HRSLT  */
00086 byte USB::ctrlReq( byte addr, byte ep, byte bmReqType, byte bRequest, byte wValLo, byte wValHi, unsigned int wInd, unsigned int nbytes, char* dataptr, unsigned int nak_limit )
00087 {
00088  boolean direction = false;     //request direction, IN or OUT
00089  byte rcode;   
00090  SETUP_PKT setup_pkt;
00091 
00092   regWr( rPERADDR, addr );                    //set peripheral address
00093   if( bmReqType & 0x80 ) {
00094     direction = true;                       //determine request direction
00095   }
00096     /* fill in setup packet */
00097     setup_pkt.ReqType_u.bmRequestType = bmReqType;
00098     setup_pkt.bRequest = bRequest;
00099     setup_pkt.wVal_u.wValueLo = wValLo;
00100     setup_pkt.wVal_u.wValueHi = wValHi;
00101     setup_pkt.wIndex = wInd;
00102     setup_pkt.wLength = nbytes;
00103     bytesWr( rSUDFIFO, 8, ( char *)&setup_pkt );    //transfer to setup packet FIFO
00104     rcode = dispatchPkt( tokSETUP, ep, nak_limit );            //dispatch packet
00105     //Serial.println("Setup packet");   //DEBUG
00106     if( rcode ) {                                   //return HRSLT if not zero
00107         Serial.print("Setup packet error: ");
00108         Serial.print( rcode, HEX );                                          
00109         return( rcode );
00110     }
00111     //Serial.println( direction, HEX ); 
00112     if( dataptr != NULL ) {                         //data stage, if present
00113         rcode = ctrlData( addr, ep, nbytes, dataptr, direction );
00114     }
00115     if( rcode ) {   //return error
00116         Serial.print("Data packet error: ");
00117         Serial.print( rcode, HEX );                                          
00118         return( rcode );
00119     }
00120     rcode = ctrlStatus( ep, direction );                //status stage
00121     return( rcode );
00122 }
00123 /* Control transfer with status stage and no data stage */
00124 /* Assumed peripheral address is already set */
00125 byte USB::ctrlStatus( byte ep, boolean direction, unsigned int nak_limit )
00126 {
00127   byte rcode;
00128     if( direction ) { //GET
00129         rcode = dispatchPkt( tokOUTHS, ep, nak_limit );
00130     }
00131     else {
00132         rcode = dispatchPkt( tokINHS, ep, nak_limit );
00133     }
00134     return( rcode );
00135 }
00136 /* Control transfer with data stage. Stages 2 and 3 of control transfer. Assumes preipheral address is set and setup packet has been sent */
00137 byte USB::ctrlData( byte addr, byte ep, unsigned int nbytes, char* dataptr, boolean direction, unsigned int nak_limit )
00138 {
00139  byte rcode;
00140   if( direction ) {                      //IN transfer
00141     devtable[ addr ].epinfo[ ep ].rcvToggle = bmRCVTOG1;
00142     rcode = inTransfer( addr, ep, nbytes, dataptr, nak_limit );
00143     return( rcode );
00144   }
00145   else {              //OUT transfer
00146     devtable[ addr ].epinfo[ ep ].sndToggle = bmSNDTOG1;
00147     rcode = outTransfer( addr, ep, nbytes, dataptr, nak_limit );
00148     return( rcode );
00149   }    
00150 }
00151 /* IN transfer to arbitrary endpoint. Assumes PERADDR is set. Handles multiple packets if necessary. Transfers 'nbytes' bytes. */
00152 /* Keep sending INs and writes data to memory area pointed by 'data'                                                           */
00153 /* rcode 0 if no errors. rcode 01-0f is relayed from dispatchPkt(). Rcode f0 means RCVDAVIRQ error,
00154             fe USB xfer timeout */
00155 byte USB::inTransfer( byte addr, byte ep, unsigned int nbytes, char* data, unsigned int nak_limit )
00156 {
00157  byte rcode;
00158  byte pktsize;
00159  byte maxpktsize = devtable[ addr ].epinfo[ ep ].MaxPktSize; 
00160  unsigned int xfrlen = 0;
00161     regWr( rHCTL, devtable[ addr ].epinfo[ ep ].rcvToggle );    //set toggle value
00162     while( 1 ) { // use a 'return' to exit this loop
00163         rcode = dispatchPkt( tokIN, ep, nak_limit );           //IN packet to EP-'endpoint'. Function takes care of NAKS.
00164         if( rcode ) {
00165             return( rcode );                            //should be 0, indicating ACK. Else return error code.
00166         }
00167         /* check for RCVDAVIRQ and generate error if not present */ 
00168         /* the only case when absense of RCVDAVIRQ makes sense is when toggle error occured. Need to add handling for that */
00169         if(( regRd( rHIRQ ) & bmRCVDAVIRQ ) == 0 ) {
00170             return ( 0xf0 );                            //receive error
00171         }
00172         pktsize = regRd( rRCVBC );                      //number of received bytes
00173         data = bytesRd( rRCVFIFO, pktsize, data );
00174         regWr( rHIRQ, bmRCVDAVIRQ );                    // Clear the IRQ & free the buffer
00175         xfrlen += pktsize;                              // add this packet's byte count to total transfer length
00176         /* The transfer is complete under two conditions:           */
00177         /* 1. The device sent a short packet (L.T. maxPacketSize)   */
00178         /* 2. 'nbytes' have been transferred.                       */
00179         if (( pktsize < maxpktsize ) || (xfrlen >= nbytes )) {      // have we transferred 'nbytes' bytes?
00180             if( regRd( rHRSL ) & bmRCVTOGRD ) {                     //save toggle value
00181                 devtable[ addr ].epinfo[ ep ].rcvToggle = bmRCVTOG1;
00182             }
00183             else {
00184                 devtable[ addr ].epinfo[ ep ].rcvToggle = bmRCVTOG0;
00185             }
00186             return( 0 );
00187         }
00188   }//while( 1 )
00189 }
00190 
00191 int USB::newInTransfer( byte addr, byte ep, unsigned int nbytes, char* data, unsigned int nak_limit )
00192 {
00193  byte rcode;
00194  byte pktsize;
00195  byte maxpktsize = devtable[ addr ].epinfo[ ep ].MaxPktSize; 
00196  unsigned int xfrlen = 0;
00197     regWr( rHCTL, devtable[ addr ].epinfo[ ep ].rcvToggle );    //set toggle value
00198     while( 1 ) { // use a 'return' to exit this loop
00199         rcode = dispatchPkt( tokIN, ep, nak_limit );           //IN packet to EP-'endpoint'. Function takes care of NAKS.
00200         if( rcode ) {
00201                 return -1;                            //should be 0, indicating ACK. Else return error code.
00202         }
00203         /* check for RCVDAVIRQ and generate error if not present */ 
00204         /* the only case when absense of RCVDAVIRQ makes sense is when toggle error occured. Need to add handling for that */
00205         if(( regRd( rHIRQ ) & bmRCVDAVIRQ ) == 0 ) {
00206             return -1;                            //receive error
00207         }
00208         pktsize = regRd( rRCVBC );                      //number of received bytes
00209         data = bytesRd( rRCVFIFO, pktsize, data );
00210         regWr( rHIRQ, bmRCVDAVIRQ );                    // Clear the IRQ & free the buffer
00211         xfrlen += pktsize;                              // add this packet's byte count to total transfer length
00212         /* The transfer is complete under two conditions:           */
00213         /* 1. The device sent a short packet (L.T. maxPacketSize)   */
00214         /* 2. 'nbytes' have been transferred.                       */
00215         if (( pktsize < maxpktsize ) || (xfrlen >= nbytes )) {      // have we transferred 'nbytes' bytes?
00216             if( regRd( rHRSL ) & bmRCVTOGRD ) {                     //save toggle value
00217                 devtable[ addr ].epinfo[ ep ].rcvToggle = bmRCVTOG1;
00218             }
00219             else {
00220                 devtable[ addr ].epinfo[ ep ].rcvToggle = bmRCVTOG0;
00221             }
00222             return xfrlen;
00223         }
00224   }//while( 1 )
00225 }
00226 
00227 /* OUT transfer to arbitrary endpoint. Assumes PERADDR is set. Handles multiple packets if necessary. Transfers 'nbytes' bytes. */
00228 /* Handles NAK bug per Maxim Application Note 4000 for single buffer transfer   */
00229 /* rcode 0 if no errors. rcode 01-0f is relayed from HRSL                       */
00230 /* major part of this function borrowed from code shared by Richard Ibbotson    */
00231 byte USB::outTransfer( byte addr, byte ep, unsigned int nbytes, char* data, unsigned int nak_limit )
00232 {
00233  byte rcode, retry_count;
00234  char* data_p = data;   //local copy of the data pointer
00235  unsigned int bytes_tosend, nak_count;
00236  unsigned int bytes_left = nbytes;
00237  byte maxpktsize = devtable[ addr ].epinfo[ ep ].MaxPktSize; 
00238  unsigned long timeout = millis() + USB_XFER_TIMEOUT;
00239  
00240   if (!maxpktsize) { //todo: move this check close to epinfo init. Make it 1< pktsize <64
00241     return 0xFE;
00242   }
00243  
00244   regWr( rHCTL, devtable[ addr ].epinfo[ ep ].sndToggle );    //set toggle value
00245   while( bytes_left ) {
00246     retry_count = 0;
00247     nak_count = 0;
00248     bytes_tosend = ( bytes_left >= maxpktsize ) ? maxpktsize : bytes_left;
00249     bytesWr( rSNDFIFO, bytes_tosend, data_p );      //filling output FIFO
00250     regWr( rSNDBC, bytes_tosend );                  //set number of bytes    
00251     regWr( rHXFR, ( tokOUT | ep ));                 //dispatch packet
00252     while(!(regRd( rHIRQ ) & bmHXFRDNIRQ ));        //wait for the completion IRQ
00253     regWr( rHIRQ, bmHXFRDNIRQ );                    //clear IRQ
00254     rcode = ( regRd( rHRSL ) & 0x0f );
00255     while( rcode && ( timeout > millis())) {
00256       switch( rcode ) {
00257         case hrNAK:
00258           nak_count++;
00259           if( nak_limit && ( nak_count == USB_NAK_LIMIT )) {
00260             return( rcode);                                   //return NAK
00261           }
00262           break;
00263         case hrTIMEOUT:
00264           retry_count++;
00265           if( retry_count == USB_RETRY_LIMIT ) {
00266             return( rcode );    //return TIMEOUT
00267           }
00268           break;
00269         default:  
00270           return( rcode );
00271       }//switch( rcode...
00272       /* process NAK according to Host out NAK bug */
00273       regWr( rSNDBC, 0 );
00274       regWr( rSNDFIFO, *data_p );
00275       regWr( rSNDBC, bytes_tosend );
00276       regWr( rHXFR, ( tokOUT | ep ));                 //dispatch packet
00277       while(!(regRd( rHIRQ ) & bmHXFRDNIRQ ));        //wait for the completion IRQ
00278       regWr( rHIRQ, bmHXFRDNIRQ );                    //clear IRQ
00279       rcode = ( regRd( rHRSL ) & 0x0f );
00280     }//while( rcode && ....
00281     bytes_left -= bytes_tosend;
00282     data_p += bytes_tosend;
00283   }//while( bytes_left...
00284   devtable[ addr ].epinfo[ ep ].sndToggle = ( regRd( rHRSL ) & bmSNDTOGRD ) ? bmSNDTOG1 : bmSNDTOG0;  //update toggle
00285   return( rcode );    //should be 0 in all cases
00286 }
00287 /* dispatch usb packet. Assumes peripheral address is set and relevant buffer is loaded/empty       */
00288 /* If NAK, tries to re-send up to nak_limit times                                                   */
00289 /* If nak_limit == 0, do not count NAKs, exit after timeout                                         */
00290 /* If bus timeout, re-sends up to USB_RETRY_LIMIT times                                             */
00291 /* return codes 0x00-0x0f are HRSLT( 0x00 being success ), 0xff means timeout                       */
00292 byte USB::dispatchPkt( byte token, byte ep, unsigned int nak_limit )
00293 {
00294  unsigned long timeout = millis() + USB_XFER_TIMEOUT;
00295  byte tmpdata;   
00296  byte rcode;
00297  unsigned int nak_count = 0;
00298  char retry_count = 0;
00299 
00300   while( timeout > millis() ) {
00301     regWr( rHXFR, ( token|ep ));            //launch the transfer
00302     rcode = 0xff;   
00303     while( millis() < timeout ) {           //wait for transfer completion
00304       tmpdata = regRd( rHIRQ );
00305       if( tmpdata & bmHXFRDNIRQ ) {
00306         regWr( rHIRQ, bmHXFRDNIRQ );    //clear the interrupt
00307         rcode = 0x00;
00308         break;
00309       }//if( tmpdata & bmHXFRDNIRQ
00310     }//while ( millis() < timeout
00311     if( rcode != 0x00 ) {                //exit if timeout
00312       return( rcode );
00313     }
00314     rcode = ( regRd( rHRSL ) & 0x0f );  //analyze transfer result
00315     switch( rcode ) {
00316       case hrNAK:
00317         nak_count ++;
00318         if( nak_limit && ( nak_count == nak_limit )) {
00319           return( rcode );
00320         }
00321         break;
00322       case hrTIMEOUT:
00323         retry_count ++;
00324         if( retry_count == USB_RETRY_LIMIT ) {
00325           return( rcode );
00326         }
00327         break;
00328       default:
00329         return( rcode );
00330     }//switch( rcode
00331   }//while( timeout > millis() 
00332   return( rcode );
00333 }
00334 /* USB main task. Performs enumeration/cleanup */
00335 void USB::Task( void )      //USB state machine
00336 {
00337   byte i;   
00338   byte rcode;
00339   static byte tmpaddr; 
00340   byte tmpdata;
00341   static unsigned long delay = 0;
00342   USB_DEVICE_DESCRIPTOR buf;
00343     tmpdata = getVbusState();
00344     /* modify USB task state if Vbus changed */
00345 
00346     switch( tmpdata ) {
00347         case SE1:   //illegal state
00348             usb_task_state = USB_DETACHED_SUBSTATE_ILLEGAL;
00349             break;
00350         case SE0:   //disconnected
00351             if(( usb_task_state & USB_STATE_MASK ) != USB_STATE_DETACHED ) {
00352                 usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE;
00353             }
00354             break;
00355         case FSHOST:    //attached
00356         case LSHOST:
00357             if(( usb_task_state & USB_STATE_MASK ) == USB_STATE_DETACHED ) {
00358                 delay = millis() + USB_SETTLE_DELAY;
00359                 usb_task_state = USB_ATTACHED_SUBSTATE_SETTLE;
00360             }
00361             break;
00362         }// switch( tmpdata
00363     //Serial.print("USB task state: ");
00364     //Serial.println( usb_task_state, HEX );
00365     switch( usb_task_state ) {
00366         case USB_DETACHED_SUBSTATE_INITIALIZE:
00367             init();
00368             usb_task_state = USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE;
00369             break;
00370         case USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE:     //just sit here
00371             break;
00372         case USB_DETACHED_SUBSTATE_ILLEGAL:             //just sit here
00373             break;
00374         case USB_ATTACHED_SUBSTATE_SETTLE:              //setlle time for just attached device                  
00375             if( delay < millis() ) {
00376                 usb_task_state = USB_ATTACHED_SUBSTATE_RESET_DEVICE;
00377             }
00378             break;
00379         case USB_ATTACHED_SUBSTATE_RESET_DEVICE:
00380             regWr( rHCTL, bmBUSRST );                   //issue bus reset
00381             usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE;
00382             break;
00383         case USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE:
00384             if(( regRd( rHCTL ) & bmBUSRST ) == 0 ) {
00385                 tmpdata = regRd( rMODE ) | bmSOFKAENAB;                 //start SOF generation
00386                 regWr( rMODE, tmpdata );
00387 //                  regWr( rMODE, bmSOFKAENAB );
00388                 usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_SOF;
00389                 delay = millis() + 20; //20ms wait after reset per USB spec
00390             }
00391             break;
00392         case USB_ATTACHED_SUBSTATE_WAIT_SOF:  //todo: change check order
00393             if( regRd( rHIRQ ) & bmFRAMEIRQ ) {                         //when first SOF received we can continue
00394               if( delay < millis() ) {                                    //20ms passed
00395                 usb_task_state = USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE;
00396               }
00397             }
00398             break;
00399         case USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE:
00400             // toggle( BPNT_0 );
00401             devtable[ 0 ].epinfo->MaxPktSize = 8;   //set max.packet size to min.allowed
00402             rcode = getDevDescr( 0, 0, 8, ( char* )&buf );
00403             if( rcode == 0 ) {
00404                 devtable[ 0 ].epinfo->MaxPktSize = buf.bMaxPacketSize0;
00405                 usb_task_state = USB_STATE_ADDRESSING;
00406             }
00407             else {
00408                 usb_error = USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE;
00409                 usb_task_state = USB_STATE_ERROR;
00410             }
00411             break;
00412         case USB_STATE_ADDRESSING:
00413             for( i = 1; i < USB_NUMDEVICES; i++ ) {
00414                 if( devtable[ i ].epinfo == NULL ) {
00415                     devtable[ i ].epinfo = devtable[ 0 ].epinfo;        //set correct MaxPktSize
00416                                                                         //temporary record
00417                                                                         //until plugged with real device endpoint structure
00418                     rcode = setAddr( 0, 0, i );
00419                     if( rcode == 0 ) {
00420                         tmpaddr = i;
00421                         usb_task_state = USB_STATE_CONFIGURING;
00422                     }
00423                     else {
00424                         usb_error = USB_STATE_ADDRESSING;          //set address error
00425                         usb_task_state = USB_STATE_ERROR;
00426                     }
00427                     break;  //break if address assigned or error occured during address assignment attempt                      
00428                 }
00429             }//for( i = 1; i < USB_NUMDEVICES; i++
00430             if( usb_task_state == USB_STATE_ADDRESSING ) {     //no vacant place in devtable
00431                 usb_error = 0xfe;
00432                 usb_task_state = USB_STATE_ERROR;
00433             }
00434             break;
00435         case USB_STATE_CONFIGURING:
00436             break;
00437         case USB_STATE_RUNNING:
00438             break;
00439         case USB_STATE_ERROR:
00440             break;
00441     }// switch( usb_task_state
00442 }    
00443   


rosserial_adk_demo
Author(s): Adam Stambler
autogenerated on Mon Dec 2 2013 12:02:02