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 42 USB::USB () { 43 usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE; //set up state machine 44 init(); 45 } 46 /* Initialize data structures */ 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 } 59 byte USB::getUsbTaskState( void ) 60 { 61 return( usb_task_state ); 62 } 63 void USB::setUsbTaskState( byte state ) 64 { 65 usb_task_state = state; 66 } 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 */ 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 */ 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 */ 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