1 /*
2  * Copyright 2009-2011 Oleg Mazurov, Circuits At Home, http://www.circuitsathome.com
3  * MAX3421E USB host controller support
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the authors nor the names of its contributors
14  *    may be used to endorse or promote products derived from this software
15  *    without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29 
30 /* USB functions */
31 
32 #include "Usb.h"
33 
34 static byte usb_error = 0;
35 static byte usb_task_state;
36 DEV_RECORD devtable[ USB_NUMDEVICES + 1 ];
37 EP_RECORD dev0ep;           //Endpoint data structure used during enumeration for uninitialized device
38 
39 
40 /* constructor */
41 
USB()42 USB::USB () {
43     usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE;  //set up state machine
44     init();
45 }
46 /* Initialize data structures */
init()47 void USB::init()
48 {
49   byte i;
50     for( i = 0; i < ( USB_NUMDEVICES + 1 ); i++ ) {
51         devtable[ i ].epinfo = NULL;       //clear device table
52         devtable[ i ].devclass = 0;
53     }
54     devtable[ 0 ].epinfo = &dev0ep; //set single ep for uninitialized device
55     // not necessary dev0ep.MaxPktSize = 8;          //minimum possible
56     dev0ep.sndToggle = bmSNDTOG0;   //set DATA0/1 toggles to 0
57     dev0ep.rcvToggle = bmRCVTOG0;
58 }
getUsbTaskState(void)59 byte USB::getUsbTaskState( void )
60 {
61     return( usb_task_state );
62 }
setUsbTaskState(byte state)63 void USB::setUsbTaskState( byte state )
64 {
65     usb_task_state = state;
66 }
getDevTableEntry(byte addr,byte ep)67 EP_RECORD* USB::getDevTableEntry( byte addr, byte ep )
68 {
69   EP_RECORD* ptr;
70     ptr = devtable[ addr ].epinfo;
71     ptr += ep;
72     return( ptr );
73 }
74 /* set device table entry */
75 /* each device is different and has different number of endpoints. This function plugs endpoint record structure, defined in application, to devtable */
setDevTableEntry(byte addr,EP_RECORD * eprecord_ptr)76 void USB::setDevTableEntry( byte addr, EP_RECORD* eprecord_ptr )
77 {
78     devtable[ addr ].epinfo = eprecord_ptr;
79     //return();
80 }
81 /* Control transfer. Sets address, endpoint, fills control packet with necessary data, dispatches control packet, and initiates bulk IN transfer,   */
82 /* depending on request. Actual requests are defined as inlines                                                                                      */
83 /* return codes:                */
84 /* 00       =   success         */
85 /* 01-0f    =   non-zero HRSLT  */
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)86 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 )
87 {
88  boolean direction = false;     //request direction, IN or OUT
89  byte rcode;
90  SETUP_PKT setup_pkt;
91 
92   regWr( rPERADDR, addr );                    //set peripheral address
93   if( bmReqType & 0x80 ) {
94     direction = true;                       //determine request direction
95   }
96     /* fill in setup packet */
97     setup_pkt.ReqType_u.bmRequestType = bmReqType;
98     setup_pkt.bRequest = bRequest;
99     setup_pkt.wVal_u.wValueLo = wValLo;
100     setup_pkt.wVal_u.wValueHi = wValHi;
101     setup_pkt.wIndex = wInd;
102     setup_pkt.wLength = nbytes;
103     bytesWr( rSUDFIFO, 8, ( char *)&setup_pkt );    //transfer to setup packet FIFO
104     rcode = dispatchPkt( tokSETUP, ep, nak_limit );            //dispatch packet
105     //Serial.println("Setup packet");   //DEBUG
106     if( rcode ) {                                   //return HRSLT if not zero
107         Serial.print("Setup packet error: ");
108         Serial.print( rcode, HEX );
109         return( rcode );
110     }
111     //Serial.println( direction, HEX );
112     if( dataptr != NULL ) {                         //data stage, if present
113         rcode = ctrlData( addr, ep, nbytes, dataptr, direction );
114     }
115     if( rcode ) {   //return error
116         Serial.print("Data packet error: ");
117         Serial.print( rcode, HEX );
118         return( rcode );
119     }
120     rcode = ctrlStatus( ep, direction );                //status stage
121     return( rcode );
122 }
123 /* Control transfer with status stage and no data stage */
124 /* Assumed peripheral address is already set */
ctrlStatus(byte ep,boolean direction,unsigned int nak_limit)125 byte USB::ctrlStatus( byte ep, boolean direction, unsigned int nak_limit )
126 {
127   byte rcode;
128     if( direction ) { //GET
129         rcode = dispatchPkt( tokOUTHS, ep, nak_limit );
130     }
131     else {
132         rcode = dispatchPkt( tokINHS, ep, nak_limit );
133     }
134     return( rcode );
135 }
136 /* Control transfer with data stage. Stages 2 and 3 of control transfer. Assumes preipheral address is set and setup packet has been sent */
ctrlData(byte addr,byte ep,unsigned int nbytes,char * dataptr,boolean direction,unsigned int nak_limit)137 byte USB::ctrlData( byte addr, byte ep, unsigned int nbytes, char* dataptr, boolean direction, unsigned int nak_limit )
138 {
139  byte rcode;
140   if( direction ) {                      //IN transfer
141     devtable[ addr ].epinfo[ ep ].rcvToggle = bmRCVTOG1;
142     rcode = inTransfer( addr, ep, nbytes, dataptr, nak_limit );
143     return( rcode );
144   }
145   else {              //OUT transfer
146     devtable[ addr ].epinfo[ ep ].sndToggle = bmSNDTOG1;
147     rcode = outTransfer( addr, ep, nbytes, dataptr, nak_limit );
148     return( rcode );
149   }
150 }
151 /* IN transfer to arbitrary endpoint. Assumes PERADDR is set. Handles multiple packets if necessary. Transfers 'nbytes' bytes. */
152 /* Keep sending INs and writes data to memory area pointed by 'data'                                                           */
153 /* rcode 0 if no errors. rcode 01-0f is relayed from dispatchPkt(). Rcode f0 means RCVDAVIRQ error,
154             fe USB xfer timeout */
inTransfer(byte addr,byte ep,unsigned int nbytes,char * data,unsigned int nak_limit)155 byte USB::inTransfer( byte addr, byte ep, unsigned int nbytes, char* data, unsigned int nak_limit )
156 {
157  byte rcode;
158  byte pktsize;
159  byte maxpktsize = devtable[ addr ].epinfo[ ep ].MaxPktSize;
160  unsigned int xfrlen = 0;
161     regWr( rHCTL, devtable[ addr ].epinfo[ ep ].rcvToggle );    //set toggle value
162     while( 1 ) { // use a 'return' to exit this loop
163         rcode = dispatchPkt( tokIN, ep, nak_limit );           //IN packet to EP-'endpoint'. Function takes care of NAKS.
164         if( rcode ) {
165             return( rcode );                            //should be 0, indicating ACK. Else return error code.
166         }
167         /* check for RCVDAVIRQ and generate error if not present */
168         /* the only case when absense of RCVDAVIRQ makes sense is when toggle error occured. Need to add handling for that */
169         if(( regRd( rHIRQ ) & bmRCVDAVIRQ ) == 0 ) {
170             return ( 0xf0 );                            //receive error
171         }
172         pktsize = regRd( rRCVBC );                      //number of received bytes
173         data = bytesRd( rRCVFIFO, pktsize, data );
174         regWr( rHIRQ, bmRCVDAVIRQ );                    // Clear the IRQ & free the buffer
175         xfrlen += pktsize;                              // add this packet's byte count to total transfer length
176         /* The transfer is complete under two conditions:           */
177         /* 1. The device sent a short packet (L.T. maxPacketSize)   */
178         /* 2. 'nbytes' have been transferred.                       */
179         if (( pktsize < maxpktsize ) || (xfrlen >= nbytes )) {      // have we transferred 'nbytes' bytes?
180             if( regRd( rHRSL ) & bmRCVTOGRD ) {                     //save toggle value
181                 devtable[ addr ].epinfo[ ep ].rcvToggle = bmRCVTOG1;
182             }
183             else {
184                 devtable[ addr ].epinfo[ ep ].rcvToggle = bmRCVTOG0;
185             }
186             return( 0 );
187         }
188   }//while( 1 )
189 }
190 
newInTransfer(byte addr,byte ep,unsigned int nbytes,char * data,unsigned int nak_limit)191 int USB::newInTransfer( byte addr, byte ep, unsigned int nbytes, char* data, unsigned int nak_limit )
192 {
193  byte rcode;
194  byte pktsize;
195  byte maxpktsize = devtable[ addr ].epinfo[ ep ].MaxPktSize;
196  unsigned int xfrlen = 0;
197     regWr( rHCTL, devtable[ addr ].epinfo[ ep ].rcvToggle );    //set toggle value
198     while( 1 ) { // use a 'return' to exit this loop
199         rcode = dispatchPkt( tokIN, ep, nak_limit );           //IN packet to EP-'endpoint'. Function takes care of NAKS.
200         if( rcode ) {
201 		return -1;                            //should be 0, indicating ACK. Else return error code.
202         }
203         /* check for RCVDAVIRQ and generate error if not present */
204         /* the only case when absense of RCVDAVIRQ makes sense is when toggle error occured. Need to add handling for that */
205         if(( regRd( rHIRQ ) & bmRCVDAVIRQ ) == 0 ) {
206             return -1;                            //receive error
207         }
208         pktsize = regRd( rRCVBC );                      //number of received bytes
209         data = bytesRd( rRCVFIFO, pktsize, data );
210         regWr( rHIRQ, bmRCVDAVIRQ );                    // Clear the IRQ & free the buffer
211         xfrlen += pktsize;                              // add this packet's byte count to total transfer length
212         /* The transfer is complete under two conditions:           */
213         /* 1. The device sent a short packet (L.T. maxPacketSize)   */
214         /* 2. 'nbytes' have been transferred.                       */
215         if (( pktsize < maxpktsize ) || (xfrlen >= nbytes )) {      // have we transferred 'nbytes' bytes?
216             if( regRd( rHRSL ) & bmRCVTOGRD ) {                     //save toggle value
217                 devtable[ addr ].epinfo[ ep ].rcvToggle = bmRCVTOG1;
218             }
219             else {
220                 devtable[ addr ].epinfo[ ep ].rcvToggle = bmRCVTOG0;
221             }
222             return xfrlen;
223         }
224   }//while( 1 )
225 }
226 
227 /* OUT transfer to arbitrary endpoint. Assumes PERADDR is set. Handles multiple packets if necessary. Transfers 'nbytes' bytes. */
228 /* Handles NAK bug per Maxim Application Note 4000 for single buffer transfer   */
229 /* rcode 0 if no errors. rcode 01-0f is relayed from HRSL                       */
230 /* major part of this function borrowed from code shared by Richard Ibbotson    */
outTransfer(byte addr,byte ep,unsigned int nbytes,char * data,unsigned int nak_limit)231 byte USB::outTransfer( byte addr, byte ep, unsigned int nbytes, char* data, unsigned int nak_limit )
232 {
233  byte rcode, retry_count;
234  char* data_p = data;   //local copy of the data pointer
235  unsigned int bytes_tosend, nak_count;
236  unsigned int bytes_left = nbytes;
237  byte maxpktsize = devtable[ addr ].epinfo[ ep ].MaxPktSize;
238  unsigned long timeout = millis() + USB_XFER_TIMEOUT;
239 
240   if (!maxpktsize) { //todo: move this check close to epinfo init. Make it 1< pktsize <64
241     return 0xFE;
242   }
243 
244   regWr( rHCTL, devtable[ addr ].epinfo[ ep ].sndToggle );    //set toggle value
245   while( bytes_left ) {
246     retry_count = 0;
247     nak_count = 0;
248     bytes_tosend = ( bytes_left >= maxpktsize ) ? maxpktsize : bytes_left;
249     bytesWr( rSNDFIFO, bytes_tosend, data_p );      //filling output FIFO
250     regWr( rSNDBC, bytes_tosend );                  //set number of bytes
251     regWr( rHXFR, ( tokOUT | ep ));                 //dispatch packet
252     while(!(regRd( rHIRQ ) & bmHXFRDNIRQ ));        //wait for the completion IRQ
253     regWr( rHIRQ, bmHXFRDNIRQ );                    //clear IRQ
254     rcode = ( regRd( rHRSL ) & 0x0f );
255     while( rcode && ( timeout > millis())) {
256       switch( rcode ) {
257         case hrNAK:
258           nak_count++;
259           if( nak_limit && ( nak_count == USB_NAK_LIMIT )) {
260             return( rcode);                                   //return NAK
261           }
262           break;
263         case hrTIMEOUT:
264           retry_count++;
265           if( retry_count == USB_RETRY_LIMIT ) {
266             return( rcode );    //return TIMEOUT
267           }
268           break;
269         default:
270           return( rcode );
271       }//switch( rcode...
272       /* process NAK according to Host out NAK bug */
273       regWr( rSNDBC, 0 );
274       regWr( rSNDFIFO, *data_p );
275       regWr( rSNDBC, bytes_tosend );
276       regWr( rHXFR, ( tokOUT | ep ));                 //dispatch packet
277       while(!(regRd( rHIRQ ) & bmHXFRDNIRQ ));        //wait for the completion IRQ
278       regWr( rHIRQ, bmHXFRDNIRQ );                    //clear IRQ
279       rcode = ( regRd( rHRSL ) & 0x0f );
280     }//while( rcode && ....
281     bytes_left -= bytes_tosend;
282     data_p += bytes_tosend;
283   }//while( bytes_left...
284   devtable[ addr ].epinfo[ ep ].sndToggle = ( regRd( rHRSL ) & bmSNDTOGRD ) ? bmSNDTOG1 : bmSNDTOG0;  //update toggle
285   return( rcode );    //should be 0 in all cases
286 }
287 /* dispatch usb packet. Assumes peripheral address is set and relevant buffer is loaded/empty       */
288 /* If NAK, tries to re-send up to nak_limit times                                                   */
289 /* If nak_limit == 0, do not count NAKs, exit after timeout                                         */
290 /* If bus timeout, re-sends up to USB_RETRY_LIMIT times                                             */
291 /* return codes 0x00-0x0f are HRSLT( 0x00 being success ), 0xff means timeout                       */
dispatchPkt(byte token,byte ep,unsigned int nak_limit)292 byte USB::dispatchPkt( byte token, byte ep, unsigned int nak_limit )
293 {
294  unsigned long timeout = millis() + USB_XFER_TIMEOUT;
295  byte tmpdata;
296  byte rcode;
297  unsigned int nak_count = 0;
298  char retry_count = 0;
299 
300   while( timeout > millis() ) {
301     regWr( rHXFR, ( token|ep ));            //launch the transfer
302     rcode = 0xff;
303     while( millis() < timeout ) {           //wait for transfer completion
304       tmpdata = regRd( rHIRQ );
305       if( tmpdata & bmHXFRDNIRQ ) {
306         regWr( rHIRQ, bmHXFRDNIRQ );    //clear the interrupt
307         rcode = 0x00;
308         break;
309       }//if( tmpdata & bmHXFRDNIRQ
310     }//while ( millis() < timeout
311     if( rcode != 0x00 ) {                //exit if timeout
312       return( rcode );
313     }
314     rcode = ( regRd( rHRSL ) & 0x0f );  //analyze transfer result
315     switch( rcode ) {
316       case hrNAK:
317         nak_count ++;
318         if( nak_limit && ( nak_count == nak_limit )) {
319           return( rcode );
320         }
321         break;
322       case hrTIMEOUT:
323         retry_count ++;
324         if( retry_count == USB_RETRY_LIMIT ) {
325           return( rcode );
326         }
327         break;
328       default:
329         return( rcode );
330     }//switch( rcode
331   }//while( timeout > millis()
332   return( rcode );
333 }
334 /* USB main task. Performs enumeration/cleanup */
Task(void)335 void USB::Task( void )      //USB state machine
336 {
337   byte i;
338   byte rcode;
339   static byte tmpaddr;
340   byte tmpdata;
341   static unsigned long delay = 0;
342   USB_DEVICE_DESCRIPTOR buf;
343     tmpdata = getVbusState();
344     /* modify USB task state if Vbus changed */
345 
346     switch( tmpdata ) {
347         case SE1:   //illegal state
348             usb_task_state = USB_DETACHED_SUBSTATE_ILLEGAL;
349             break;
350         case SE0:   //disconnected
351             if(( usb_task_state & USB_STATE_MASK ) != USB_STATE_DETACHED ) {
352                 usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE;
353             }
354             break;
355         case FSHOST:    //attached
356         case LSHOST:
357             if(( usb_task_state & USB_STATE_MASK ) == USB_STATE_DETACHED ) {
358                 delay = millis() + USB_SETTLE_DELAY;
359                 usb_task_state = USB_ATTACHED_SUBSTATE_SETTLE;
360             }
361             break;
362         }// switch( tmpdata
363     //Serial.print("USB task state: ");
364     //Serial.println( usb_task_state, HEX );
365     switch( usb_task_state ) {
366         case USB_DETACHED_SUBSTATE_INITIALIZE:
367             init();
368             usb_task_state = USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE;
369             break;
370         case USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE:     //just sit here
371             break;
372         case USB_DETACHED_SUBSTATE_ILLEGAL:             //just sit here
373             break;
374         case USB_ATTACHED_SUBSTATE_SETTLE:              //setlle time for just attached device
375             if( delay < millis() ) {
376                 usb_task_state = USB_ATTACHED_SUBSTATE_RESET_DEVICE;
377             }
378             break;
379         case USB_ATTACHED_SUBSTATE_RESET_DEVICE:
380             regWr( rHCTL, bmBUSRST );                   //issue bus reset
381             usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE;
382             break;
383         case USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE:
384             if(( regRd( rHCTL ) & bmBUSRST ) == 0 ) {
385                 tmpdata = regRd( rMODE ) | bmSOFKAENAB;                 //start SOF generation
386                 regWr( rMODE, tmpdata );
387 //                  regWr( rMODE, bmSOFKAENAB );
388                 usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_SOF;
389                 delay = millis() + 20; //20ms wait after reset per USB spec
390             }
391             break;
392         case USB_ATTACHED_SUBSTATE_WAIT_SOF:  //todo: change check order
393             if( regRd( rHIRQ ) & bmFRAMEIRQ ) {                         //when first SOF received we can continue
394               if( delay < millis() ) {                                    //20ms passed
395                 usb_task_state = USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE;
396               }
397             }
398             break;
399         case USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE:
400             // toggle( BPNT_0 );
401             devtable[ 0 ].epinfo->MaxPktSize = 8;   //set max.packet size to min.allowed
402             rcode = getDevDescr( 0, 0, 8, ( char* )&buf );
403             if( rcode == 0 ) {
404                 devtable[ 0 ].epinfo->MaxPktSize = buf.bMaxPacketSize0;
405                 usb_task_state = USB_STATE_ADDRESSING;
406             }
407             else {
408                 usb_error = USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE;
409                 usb_task_state = USB_STATE_ERROR;
410             }
411             break;
412         case USB_STATE_ADDRESSING:
413             for( i = 1; i < USB_NUMDEVICES; i++ ) {
414                 if( devtable[ i ].epinfo == NULL ) {
415                     devtable[ i ].epinfo = devtable[ 0 ].epinfo;        //set correct MaxPktSize
416                                                                         //temporary record
417                                                                         //until plugged with real device endpoint structure
418                     rcode = setAddr( 0, 0, i );
419                     if( rcode == 0 ) {
420                         tmpaddr = i;
421                         usb_task_state = USB_STATE_CONFIGURING;
422                     }
423                     else {
424                         usb_error = USB_STATE_ADDRESSING;          //set address error
425                         usb_task_state = USB_STATE_ERROR;
426                     }
427                     break;  //break if address assigned or error occured during address assignment attempt
428                 }
429             }//for( i = 1; i < USB_NUMDEVICES; i++
430             if( usb_task_state == USB_STATE_ADDRESSING ) {     //no vacant place in devtable
431                 usb_error = 0xfe;
432                 usb_task_state = USB_STATE_ERROR;
433             }
434             break;
435         case USB_STATE_CONFIGURING:
436             break;
437         case USB_STATE_RUNNING:
438             break;
439         case USB_STATE_ERROR:
440             break;
441     }// switch( usb_task_state
442 }
443 
444