]> git.friedersdorff.com Git - max/tmk_keyboard.git/blob - tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/Usb.cpp
lufa: usb-usb: Use LUFA startup instead of cusotom
[max/tmk_keyboard.git] / tmk_core / protocol / usb_hid / USB_Host_Shield_2.0 / Usb.cpp
1 /* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
2
3 This software may be distributed and modified under the terms of the GNU
4 General Public License version 2 (GPL2) as published by the Free Software
5 Foundation and appearing in the file GPL2.TXT included in the packaging of
6 this file. Please note that GPL2 Section 2[b] requires that all works based
7 on this software must also be made publicly available under the terms of
8 the GPL2 ("Copyleft").
9
10 Contact information
11 -------------------
12
13 Circuits At Home, LTD
14 Web      :  http://www.circuitsathome.com
15 e-mail   :  support@circuitsathome.com
16  */
17 /* USB functions */
18
19 #include "Usb.h"
20
21 static uint8_t usb_error = 0;
22 static uint8_t usb_task_state;
23
24 /* constructor */
25 USB::USB() : bmHubPre(0) {
26         usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE; //set up state machine
27         init();
28 }
29
30 /* Initialize data structures */
31 void USB::init() {
32         //devConfigIndex = 0;
33         bmHubPre = 0;
34 }
35
36 uint8_t USB::getUsbTaskState(void) {
37         return ( usb_task_state);
38 }
39
40 void USB::setUsbTaskState(uint8_t state) {
41         usb_task_state = state;
42 }
43
44 EpInfo* USB::getEpInfoEntry(uint8_t addr, uint8_t ep) {
45         UsbDevice *p = addrPool.GetUsbDevicePtr(addr);
46
47         if(!p || !p->epinfo)
48                 return NULL;
49
50         EpInfo *pep = p->epinfo;
51
52         for(uint8_t i = 0; i < p->epcount; i++) {
53                 if((pep)->epAddr == ep)
54                         return pep;
55
56                 pep++;
57         }
58         return NULL;
59 }
60
61 /* set device table entry */
62
63 /* each device is different and has different number of endpoints. This function plugs endpoint record structure, defined in application, to devtable */
64 uint8_t USB::setEpInfoEntry(uint8_t addr, uint8_t epcount, EpInfo* eprecord_ptr) {
65         if(!eprecord_ptr)
66                 return USB_ERROR_INVALID_ARGUMENT;
67
68         UsbDevice *p = addrPool.GetUsbDevicePtr(addr);
69
70         if(!p)
71                 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
72
73         p->address.devAddress = addr;
74         p->epinfo = eprecord_ptr;
75         p->epcount = epcount;
76
77         return 0;
78 }
79
80 uint8_t USB::SetAddress(uint8_t addr, uint8_t ep, EpInfo **ppep, uint16_t *nak_limit) {
81         UsbDevice *p = addrPool.GetUsbDevicePtr(addr);
82
83         if(!p)
84                 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
85
86         if(!p->epinfo)
87                 return USB_ERROR_EPINFO_IS_NULL;
88
89         *ppep = getEpInfoEntry(addr, ep);
90
91         if(!*ppep)
92                 return USB_ERROR_EP_NOT_FOUND_IN_TBL;
93
94         *nak_limit = (0x0001UL << (((*ppep)->bmNakPower > USB_NAK_MAX_POWER) ? USB_NAK_MAX_POWER : (*ppep)->bmNakPower));
95         (*nak_limit)--;
96         /*
97           USBTRACE2("\r\nAddress: ", addr);
98           USBTRACE2(" EP: ", ep);
99           USBTRACE2(" NAK Power: ",(*ppep)->bmNakPower);
100           USBTRACE2(" NAK Limit: ", nak_limit);
101           USBTRACE("\r\n");
102          */
103         regWr(rPERADDR, addr); //set peripheral address
104
105         uint8_t mode = regRd(rMODE);
106
107         //Serial.print("\r\nMode: ");
108         //Serial.println( mode, HEX);
109         //Serial.print("\r\nLS: ");
110         //Serial.println(p->lowspeed, HEX);
111
112
113
114         // Set bmLOWSPEED and bmHUBPRE in case of low-speed device, reset them otherwise
115         regWr(rMODE, (p->lowspeed) ? mode | bmLOWSPEED | bmHubPre : mode & ~(bmHUBPRE | bmLOWSPEED));
116
117         return 0;
118 }
119
120 /* Control transfer. Sets address, endpoint, fills control packet with necessary data, dispatches control packet, and initiates bulk IN transfer,   */
121 /* depending on request. Actual requests are defined as inlines                                                                                      */
122 /* return codes:                */
123 /* 00       =   success         */
124
125 /* 01-0f    =   non-zero HRSLT  */
126 uint8_t USB::ctrlReq(uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi,
127         uint16_t wInd, uint16_t total, uint16_t nbytes, uint8_t* dataptr, USBReadParser *p) {
128         bool direction = false; //request direction, IN or OUT
129         uint8_t rcode;
130         SETUP_PKT setup_pkt;
131
132         EpInfo *pep = NULL;
133         uint16_t nak_limit = 0;
134
135         rcode = SetAddress(addr, ep, &pep, &nak_limit);
136
137         if(rcode)
138                 return rcode;
139
140         direction = ((bmReqType & 0x80) > 0);
141
142         /* fill in setup packet */
143         setup_pkt.ReqType_u.bmRequestType = bmReqType;
144         setup_pkt.bRequest = bRequest;
145         setup_pkt.wVal_u.wValueLo = wValLo;
146         setup_pkt.wVal_u.wValueHi = wValHi;
147         setup_pkt.wIndex = wInd;
148         setup_pkt.wLength = total;
149
150         bytesWr(rSUDFIFO, 8, (uint8_t*) & setup_pkt); //transfer to setup packet FIFO
151
152         rcode = dispatchPkt(tokSETUP, ep, nak_limit); //dispatch packet
153
154         if(rcode) //return HRSLT if not zero
155                 return ( rcode);
156
157         if(dataptr != NULL) //data stage, if present
158         {
159                 if(direction) //IN transfer
160                 {
161                         uint16_t left = total;
162
163                         pep->bmRcvToggle = 1; //bmRCVTOG1;
164
165                         while(left) {
166                                 // Bytes read into buffer
167                                 uint16_t read = nbytes;
168                                 //uint16_t read = (left<nbytes) ? left : nbytes;
169
170                                 rcode = InTransfer(pep, nak_limit, &read, dataptr);
171                                 if(rcode == hrTOGERR) {
172                                         // yes, we flip it wrong here so that next time it is actually correct!
173                                         pep->bmRcvToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1;
174                                         continue;
175                                 }
176
177                                 if(rcode)
178                                         return rcode;
179
180                                 // Invoke callback function if inTransfer completed successfully and callback function pointer is specified
181                                 if(!rcode && p)
182                                         ((USBReadParser*)p)->Parse(read, dataptr, total - left);
183
184                                 left -= read;
185
186                                 if(read < nbytes)
187                                         break;
188                         }
189                 } else //OUT transfer
190                 {
191                         pep->bmSndToggle = 1; //bmSNDTOG1;
192                         rcode = OutTransfer(pep, nak_limit, nbytes, dataptr);
193                 }
194                 if(rcode) //return error
195                         return ( rcode);
196         }
197         // Status stage
198         return dispatchPkt((direction) ? tokOUTHS : tokINHS, ep, nak_limit); //GET if direction
199 }
200
201 /* IN transfer to arbitrary endpoint. Assumes PERADDR is set. Handles multiple packets if necessary. Transfers 'nbytes' bytes. */
202 /* Keep sending INs and writes data to memory area pointed by 'data'                                                           */
203
204 /* rcode 0 if no errors. rcode 01-0f is relayed from dispatchPkt(). Rcode f0 means RCVDAVIRQ error,
205             fe USB xfer timeout */
206 uint8_t USB::inTransfer(uint8_t addr, uint8_t ep, uint16_t *nbytesptr, uint8_t* data) {
207         EpInfo *pep = NULL;
208         uint16_t nak_limit = 0;
209
210         uint8_t rcode = SetAddress(addr, ep, &pep, &nak_limit);
211
212         if(rcode) {
213                 USBTRACE3("(USB::InTransfer) SetAddress Failed ", rcode, 0x81);
214                 USBTRACE3("(USB::InTransfer) addr requested ", addr, 0x81);
215                 USBTRACE3("(USB::InTransfer) ep requested ", ep, 0x81);
216                 return rcode;
217         }
218         return InTransfer(pep, nak_limit, nbytesptr, data);
219 }
220
221 uint8_t USB::InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, uint8_t* data) {
222         uint8_t rcode = 0;
223         uint8_t pktsize;
224
225         uint16_t nbytes = *nbytesptr;
226         //printf("Requesting %i bytes ", nbytes);
227         uint8_t maxpktsize = pep->maxPktSize;
228
229         *nbytesptr = 0;
230         regWr(rHCTL, (pep->bmRcvToggle) ? bmRCVTOG1 : bmRCVTOG0); //set toggle value
231
232         // use a 'break' to exit this loop
233         while(1) {
234                 rcode = dispatchPkt(tokIN, pep->epAddr, nak_limit); //IN packet to EP-'endpoint'. Function takes care of NAKS.
235                 if(rcode == hrTOGERR) {
236                         // yes, we flip it wrong here so that next time it is actually correct!
237                         pep->bmRcvToggle = (regRd(rHRSL) & bmRCVTOGRD) ? 0 : 1;
238                         regWr(rHCTL, (pep->bmRcvToggle) ? bmRCVTOG1 : bmRCVTOG0); //set toggle value
239                         continue;
240                 }
241                 if(rcode) {
242                         //printf(">>>>>>>> Problem! dispatchPkt %2.2x\r\n", rcode);
243                         break; //should be 0, indicating ACK. Else return error code.
244                 }
245                 /* check for RCVDAVIRQ and generate error if not present */
246                 /* the only case when absence of RCVDAVIRQ makes sense is when toggle error occurred. Need to add handling for that */
247                 if((regRd(rHIRQ) & bmRCVDAVIRQ) == 0) {
248                         //printf(">>>>>>>> Problem! NO RCVDAVIRQ!\r\n");
249                         rcode = 0xf0; //receive error
250                         break;
251                 }
252                 pktsize = regRd(rRCVBC); //number of received bytes
253                 //printf("Got %i bytes \r\n", pktsize);
254                 // This would be OK, but...
255                 //assert(pktsize <= nbytes);
256                 if(pktsize > nbytes) {
257                         // This can happen. Use of assert on Arduino locks up the Arduino.
258                         // So I will trim the value, and hope for the best.
259                         //printf(">>>>>>>> Problem! Wanted %i bytes but got %i.\r\n", nbytes, pktsize);
260                         pktsize = nbytes;
261                 }
262
263                 int16_t mem_left = (int16_t)nbytes - *((int16_t*)nbytesptr);
264
265                 if(mem_left < 0)
266                         mem_left = 0;
267
268                 data = bytesRd(rRCVFIFO, ((pktsize > mem_left) ? mem_left : pktsize), data);
269
270                 regWr(rHIRQ, bmRCVDAVIRQ); // Clear the IRQ & free the buffer
271                 *nbytesptr += pktsize; // add this packet's byte count to total transfer length
272
273                 /* The transfer is complete under two conditions:           */
274                 /* 1. The device sent a short packet (L.T. maxPacketSize)   */
275                 /* 2. 'nbytes' have been transferred.                       */
276                 if((pktsize < maxpktsize) || (*nbytesptr >= nbytes)) // have we transferred 'nbytes' bytes?
277                 {
278                         // Save toggle value
279                         pep->bmRcvToggle = ((regRd(rHRSL) & bmRCVTOGRD)) ? 1 : 0;
280                         //printf("\r\n");
281                         rcode = 0;
282                         break;
283                 } // if
284         } //while( 1 )
285         return ( rcode);
286 }
287
288 /* OUT transfer to arbitrary endpoint. Handles multiple packets if necessary. Transfers 'nbytes' bytes. */
289 /* Handles NAK bug per Maxim Application Note 4000 for single buffer transfer   */
290
291 /* rcode 0 if no errors. rcode 01-0f is relayed from HRSL                       */
292 uint8_t USB::outTransfer(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* data) {
293         EpInfo *pep = NULL;
294         uint16_t nak_limit = 0;
295
296         uint8_t rcode = SetAddress(addr, ep, &pep, &nak_limit);
297
298         if(rcode)
299                 return rcode;
300
301         return OutTransfer(pep, nak_limit, nbytes, data);
302 }
303
304 uint8_t USB::OutTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t nbytes, uint8_t *data) {
305         uint8_t rcode = hrSUCCESS, retry_count;
306         uint8_t *data_p = data; //local copy of the data pointer
307         uint16_t bytes_tosend, nak_count;
308         uint16_t bytes_left = nbytes;
309
310         uint8_t maxpktsize = pep->maxPktSize;
311
312         if(maxpktsize < 1 || maxpktsize > 64)
313                 return USB_ERROR_INVALID_MAX_PKT_SIZE;
314
315         unsigned long timeout = millis() + USB_XFER_TIMEOUT;
316
317         regWr(rHCTL, (pep->bmSndToggle) ? bmSNDTOG1 : bmSNDTOG0); //set toggle value
318
319         while(bytes_left) {
320                 retry_count = 0;
321                 nak_count = 0;
322                 bytes_tosend = (bytes_left >= maxpktsize) ? maxpktsize : bytes_left;
323                 bytesWr(rSNDFIFO, bytes_tosend, data_p); //filling output FIFO
324                 regWr(rSNDBC, bytes_tosend); //set number of bytes
325                 regWr(rHXFR, (tokOUT | pep->epAddr)); //dispatch packet
326                 while(!(regRd(rHIRQ) & bmHXFRDNIRQ)); //wait for the completion IRQ
327                 regWr(rHIRQ, bmHXFRDNIRQ); //clear IRQ
328                 rcode = (regRd(rHRSL) & 0x0f);
329
330                 while(rcode && ((long)(millis() - timeout) < 0L)) {
331                         switch(rcode) {
332                                 case hrNAK:
333                                         nak_count++;
334                                         if(nak_limit && (nak_count == nak_limit))
335                                                 goto breakout;
336                                         //return ( rcode);
337                                         break;
338                                 case hrTIMEOUT:
339                                         retry_count++;
340                                         if(retry_count == USB_RETRY_LIMIT)
341                                                 goto breakout;
342                                         //return ( rcode);
343                                         break;
344                                 case hrTOGERR:
345                                         // yes, we flip it wrong here so that next time it is actually correct!
346                                         pep->bmSndToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1;
347                                         regWr(rHCTL, (pep->bmSndToggle) ? bmSNDTOG1 : bmSNDTOG0); //set toggle value
348                                         break;
349                                 default:
350                                         goto breakout;
351                         }//switch( rcode
352
353                         /* process NAK according to Host out NAK bug */
354                         regWr(rSNDBC, 0);
355                         regWr(rSNDFIFO, *data_p);
356                         regWr(rSNDBC, bytes_tosend);
357                         regWr(rHXFR, (tokOUT | pep->epAddr)); //dispatch packet
358                         while(!(regRd(rHIRQ) & bmHXFRDNIRQ)); //wait for the completion IRQ
359                         regWr(rHIRQ, bmHXFRDNIRQ); //clear IRQ
360                         rcode = (regRd(rHRSL) & 0x0f);
361                 }//while( rcode && ....
362                 bytes_left -= bytes_tosend;
363                 data_p += bytes_tosend;
364         }//while( bytes_left...
365 breakout:
366
367         pep->bmSndToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 1 : 0; //bmSNDTOG1 : bmSNDTOG0;  //update toggle
368         return ( rcode); //should be 0 in all cases
369 }
370 /* dispatch USB packet. Assumes peripheral address is set and relevant buffer is loaded/empty       */
371 /* If NAK, tries to re-send up to nak_limit times                                                   */
372 /* If nak_limit == 0, do not count NAKs, exit after timeout                                         */
373 /* If bus timeout, re-sends up to USB_RETRY_LIMIT times                                             */
374
375 /* return codes 0x00-0x0f are HRSLT( 0x00 being success ), 0xff means timeout                       */
376 uint8_t USB::dispatchPkt(uint8_t token, uint8_t ep, uint16_t nak_limit) {
377         unsigned long timeout = millis() + USB_XFER_TIMEOUT;
378         uint8_t tmpdata;
379         uint8_t rcode = hrSUCCESS;
380         uint8_t retry_count = 0;
381         uint16_t nak_count = 0;
382
383         while((long)(millis() - timeout) < 0L) {
384                 regWr(rHXFR, (token | ep)); //launch the transfer
385                 rcode = USB_ERROR_TRANSFER_TIMEOUT;
386
387                 while((long)(millis() - timeout) < 0L) //wait for transfer completion
388                 {
389                         tmpdata = regRd(rHIRQ);
390
391                         if(tmpdata & bmHXFRDNIRQ) {
392                                 regWr(rHIRQ, bmHXFRDNIRQ); //clear the interrupt
393                                 rcode = 0x00;
394                                 break;
395                         }//if( tmpdata & bmHXFRDNIRQ
396
397                 }//while ( millis() < timeout
398
399                 //if (rcode != 0x00) //exit if timeout
400                 //        return ( rcode);
401
402                 rcode = (regRd(rHRSL) & 0x0f); //analyze transfer result
403
404                 switch(rcode) {
405                         case hrNAK:
406                                 nak_count++;
407                                 if(nak_limit && (nak_count == nak_limit))
408                                         return (rcode);
409                                 break;
410                         case hrTIMEOUT:
411                                 retry_count++;
412                                 if(retry_count == USB_RETRY_LIMIT)
413                                         return (rcode);
414                                 break;
415                         default:
416                                 return (rcode);
417                 }//switch( rcode
418
419         }//while( timeout > millis()
420         return ( rcode);
421 }
422
423 /* USB main task. Performs enumeration/cleanup */
424 void USB::Task(void) //USB state machine
425 {
426         uint8_t rcode;
427         uint8_t tmpdata;
428         static unsigned long delay = 0;
429         //USB_DEVICE_DESCRIPTOR buf;
430         bool lowspeed = false;
431
432         MAX3421E::Task();
433
434         tmpdata = getVbusState();
435
436         /* modify USB task state if Vbus changed */
437         switch(tmpdata) {
438                 case SE1: //illegal state
439                         usb_task_state = USB_DETACHED_SUBSTATE_ILLEGAL;
440                         lowspeed = false;
441                         break;
442                 case SE0: //disconnected
443                         if((usb_task_state & USB_STATE_MASK) != USB_STATE_DETACHED)
444                                 usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE;
445                         lowspeed = false;
446                         break;
447                 case LSHOST:
448
449                         lowspeed = true;
450                         //intentional fallthrough
451                 case FSHOST: //attached
452                         if((usb_task_state & USB_STATE_MASK) == USB_STATE_DETACHED) {
453                                 delay = millis() + USB_SETTLE_DELAY;
454                                 usb_task_state = USB_ATTACHED_SUBSTATE_SETTLE;
455                         }
456                         break;
457         }// switch( tmpdata
458
459         for(uint8_t i = 0; i < USB_NUMDEVICES; i++)
460                 if(devConfig[i])
461                         rcode = devConfig[i]->Poll();
462
463         switch(usb_task_state) {
464                 case USB_DETACHED_SUBSTATE_INITIALIZE:
465                         init();
466
467                         for(uint8_t i = 0; i < USB_NUMDEVICES; i++)
468                                 if(devConfig[i])
469                                         rcode = devConfig[i]->Release();
470
471                         usb_task_state = USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE;
472                         break;
473                 case USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE: //just sit here
474                         break;
475                 case USB_DETACHED_SUBSTATE_ILLEGAL: //just sit here
476                         break;
477                 case USB_ATTACHED_SUBSTATE_SETTLE: //settle time for just attached device
478                         if((long)(millis() - delay) >= 0L)
479                                 usb_task_state = USB_ATTACHED_SUBSTATE_RESET_DEVICE;
480                         else break; // don't fall through
481                 case USB_ATTACHED_SUBSTATE_RESET_DEVICE:
482                         regWr(rHCTL, bmBUSRST); //issue bus reset
483                         usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE;
484                         break;
485                 case USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE:
486                         if((regRd(rHCTL) & bmBUSRST) == 0) {
487                                 tmpdata = regRd(rMODE) | bmSOFKAENAB; //start SOF generation
488                                 regWr(rMODE, tmpdata);
489                                 usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_SOF;
490                                 //delay = millis() + 20; //20ms wait after reset per USB spec
491                         }
492                         break;
493                 case USB_ATTACHED_SUBSTATE_WAIT_SOF: //todo: change check order
494                         if(regRd(rHIRQ) & bmFRAMEIRQ) {
495                                 //when first SOF received _and_ 20ms has passed we can continue
496                                 /*
497                                 if (delay < millis()) //20ms passed
498                                         usb_task_state = USB_STATE_CONFIGURING;
499                                  */
500                                 usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET;
501                                 delay = millis() + 20;
502                         }
503                         break;
504                 case USB_ATTACHED_SUBSTATE_WAIT_RESET:
505                         if((long)(millis() - delay) >= 0L) usb_task_state = USB_STATE_CONFIGURING;
506                         else break; // don't fall through
507                 case USB_STATE_CONFIGURING:
508
509                         //Serial.print("\r\nConf.LS: ");
510                         //Serial.println(lowspeed, HEX);
511
512                         rcode = Configuring(0, 0, lowspeed);
513
514                         if(rcode) {
515                                 if(rcode != USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE) {
516                                         usb_error = rcode;
517                                         usb_task_state = USB_STATE_ERROR;
518                                 }
519                         } else
520                                 usb_task_state = USB_STATE_RUNNING;
521                         break;
522                 case USB_STATE_RUNNING:
523                         break;
524                 case USB_STATE_ERROR:
525                         //MAX3421E::Init();
526                         break;
527         } // switch( usb_task_state )
528 }
529
530 uint8_t USB::DefaultAddressing(uint8_t parent, uint8_t port, bool lowspeed) {
531         //uint8_t                buf[12];
532         uint8_t rcode;
533         UsbDevice *p0 = NULL, *p = NULL;
534
535         // Get pointer to pseudo device with address 0 assigned
536         p0 = addrPool.GetUsbDevicePtr(0);
537
538         if(!p0)
539                 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
540
541         if(!p0->epinfo)
542                 return USB_ERROR_EPINFO_IS_NULL;
543
544         p0->lowspeed = (lowspeed) ? true : false;
545
546         // Allocate new address according to device class
547         uint8_t bAddress = addrPool.AllocAddress(parent, false, port);
548
549         if(!bAddress)
550                 return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
551
552         p = addrPool.GetUsbDevicePtr(bAddress);
553
554         if(!p)
555                 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
556
557         p->lowspeed = lowspeed;
558
559         // Assign new address to the device
560         rcode = setAddr(0, 0, bAddress);
561
562         if(rcode) {
563                 addrPool.FreeAddress(bAddress);
564                 bAddress = 0;
565                 return rcode;
566         }
567         return 0;
568 };
569
570 uint8_t USB::AttemptConfig(uint8_t driver, uint8_t parent, uint8_t port, bool lowspeed) {
571         //printf("AttemptConfig: parent = %i, port = %i\r\n", parent, port);
572         uint8_t retries = 0;
573
574 again:
575         uint8_t rcode = devConfig[driver]->ConfigureDevice(parent, port, lowspeed);
576         if(rcode == USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET) {
577                 if(parent == 0) {
578                         // Send a bus reset on the root interface.
579                         regWr(rHCTL, bmBUSRST); //issue bus reset
580                         delay(102); // delay 102ms, compensate for clock inaccuracy.
581                 } else {
582                         // reset parent port
583                         devConfig[parent]->ResetHubPort(port);
584                 }
585         } else if(rcode == hrJERR && retries < 3) { // Some devices returns this when plugged in - trying to initialize the device again usually works
586                 delay(100);
587                 retries++;
588                 goto again;
589         } else if(rcode)
590                 return rcode;
591
592         rcode = devConfig[driver]->Init(parent, port, lowspeed);
593         if(rcode == hrJERR && retries < 3) { // Some devices returns this when plugged in - trying to initialize the device again usually works
594                 delay(100);
595                 retries++;
596                 goto again;
597         }
598         if(rcode) {
599                 // Issue a bus reset, because the device may be in a limbo state
600                 if(parent == 0) {
601                         // Send a bus reset on the root interface.
602                         regWr(rHCTL, bmBUSRST); //issue bus reset
603                         delay(102); // delay 102ms, compensate for clock inaccuracy.
604                 } else {
605                         // reset parent port
606                         devConfig[parent]->ResetHubPort(port);
607                 }
608         }
609         return rcode;
610 }
611
612 /*
613  * This is broken. We need to enumerate differently.
614  * It causes major problems with several devices if detected in an unexpected order.
615  *
616  *
617  * Oleg - I wouldn't do anything before the newly connected device is considered sane.
618  * i.e.(delays are not indicated for brevity):
619  * 1. reset
620  * 2. GetDevDescr();
621  * 3a. If ACK, continue with allocating address, addressing, etc.
622  * 3b. Else reset again, count resets, stop at some number (5?).
623  * 4. When max.number of resets is reached, toggle power/fail
624  * 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()
625  * it doesn't need to be reset again
626  * New steps proposal:
627  * 1: get address pool instance. exit on fail
628  * 2: pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf). exit on fail.
629  * 3: bus reset, 100ms delay
630  * 4: set address
631  * 5: pUsb->setEpInfoEntry(bAddress, 1, epInfo), exit on fail
632  * 6: while (configurations) {
633  *              for(each configuration) {
634  *                      for (each driver) {
635  *                              6a: Ask device if it likes configuration. Returns 0 on OK.
636  *                                      If successful, the driver configured device.
637  *                                      The driver now owns the endpoints, and takes over managing them.
638  *                                      The following will need codes:
639  *                                          Everything went well, instance consumed, exit with success.
640  *                                          Instance already in use, ignore it, try next driver.
641  *                                          Not a supported device, ignore it, try next driver.
642  *                                          Not a supported configuration for this device, ignore it, try next driver.
643  *                                          Could not configure device, fatal, exit with fail.
644  *                      }
645  *              }
646  *    }
647  * 7: for(each driver) {
648  *      7a: Ask device if it knows this VID/PID. Acts exactly like 6a, but using VID/PID
649  * 8: if we get here, no driver likes the device plugged in, so exit failure.
650  *
651  */
652 uint8_t USB::Configuring(uint8_t parent, uint8_t port, bool lowspeed) {
653         //uint8_t bAddress = 0;
654         //printf("Configuring: parent = %i, port = %i\r\n", parent, port);
655         uint8_t devConfigIndex;
656         uint8_t rcode = 0;
657         uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)];
658         USB_DEVICE_DESCRIPTOR *udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR *>(buf);
659         UsbDevice *p = NULL;
660         EpInfo *oldep_ptr = NULL;
661         EpInfo epInfo;
662
663         epInfo.epAddr = 0;
664         epInfo.maxPktSize = 8;
665         epInfo.epAttribs = 0;
666         epInfo.bmNakPower = USB_NAK_MAX_POWER;
667
668         //delay(2000);
669         AddressPool &addrPool = GetAddressPool();
670         // Get pointer to pseudo device with address 0 assigned
671         p = addrPool.GetUsbDevicePtr(0);
672         if(!p) {
673                 //printf("Configuring error: USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL\r\n");
674                 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
675         }
676
677         // Save old pointer to EP_RECORD of address 0
678         oldep_ptr = p->epinfo;
679
680         // Temporary assign new pointer to epInfo to p->epinfo in order to
681         // avoid toggle inconsistence
682
683         p->epinfo = &epInfo;
684
685         p->lowspeed = lowspeed;
686         // Get device descriptor
687         rcode = getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf);
688
689         // Restore p->epinfo
690         p->epinfo = oldep_ptr;
691
692         if(rcode) {
693                 //printf("Configuring error: Can't get USB_DEVICE_DESCRIPTOR\r\n");
694                 return rcode;
695         }
696
697         // to-do?
698         // Allocate new address according to device class
699         //bAddress = addrPool.AllocAddress(parent, false, port);
700
701         uint16_t vid = udd->idVendor;
702         uint16_t pid = udd->idProduct;
703         uint8_t klass = udd->bDeviceClass;
704         uint8_t subklass = udd->bDeviceSubClass;
705         // Attempt to configure if VID/PID or device class matches with a driver
706         // Qualify with subclass too.
707         //
708         // VID/PID & class tests default to false for drivers not yet ported
709         // subclass defaults to true, so you don't have to define it if you don't have to.
710         //
711         for(devConfigIndex = 0; devConfigIndex < USB_NUMDEVICES; devConfigIndex++) {
712                 if(!devConfig[devConfigIndex]) continue; // no driver
713                 if(devConfig[devConfigIndex]->GetAddress()) continue; // consumed
714                 if(devConfig[devConfigIndex]->DEVSUBCLASSOK(subklass) && (devConfig[devConfigIndex]->VIDPIDOK(vid, pid) || devConfig[devConfigIndex]->DEVCLASSOK(klass))) {
715                         rcode = AttemptConfig(devConfigIndex, parent, port, lowspeed);
716                         if(rcode != USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED)
717                                 break;
718                 }
719         }
720
721         if(devConfigIndex < USB_NUMDEVICES) {
722                 return rcode;
723         }
724
725
726         // blindly attempt to configure
727         for(devConfigIndex = 0; devConfigIndex < USB_NUMDEVICES; devConfigIndex++) {
728                 if(!devConfig[devConfigIndex]) continue;
729                 if(devConfig[devConfigIndex]->GetAddress()) continue; // consumed
730                 if(devConfig[devConfigIndex]->DEVSUBCLASSOK(subklass) && (devConfig[devConfigIndex]->VIDPIDOK(vid, pid) || devConfig[devConfigIndex]->DEVCLASSOK(klass))) continue; // If this is true it means it must have returned USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED above
731                 rcode = AttemptConfig(devConfigIndex, parent, port, lowspeed);
732
733                 //printf("ERROR ENUMERATING %2.2x\r\n", rcode);
734                 if(!(rcode == USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED || rcode == USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE)) {
735                         // in case of an error dev_index should be reset to 0
736                         //                in order to start from the very beginning the
737                         //                next time the program gets here
738                         //if (rcode != USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE)
739                         //        devConfigIndex = 0;
740                         return rcode;
741                 }
742         }
743         // if we get here that means that the device class is not supported by any of registered classes
744         rcode = DefaultAddressing(parent, port, lowspeed);
745
746         return rcode;
747 }
748
749 uint8_t USB::ReleaseDevice(uint8_t addr) {
750         if(!addr)
751                 return 0;
752
753         for(uint8_t i = 0; i < USB_NUMDEVICES; i++) {
754                 if(!devConfig[i]) continue;
755                 if(devConfig[i]->GetAddress() == addr)
756                         return devConfig[i]->Release();
757         }
758         return 0;
759 }
760
761 #if 1 //!defined(USB_METHODS_INLINE)
762 //get device descriptor
763
764 uint8_t USB::getDevDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr) {
765         return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, nbytes, dataptr, NULL));
766 }
767 //get configuration descriptor
768
769 uint8_t USB::getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t* dataptr) {
770         return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, nbytes, dataptr, NULL));
771 }
772
773 /* 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
774  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 */
775 uint8_t USB::getConfDescr(uint8_t addr, uint8_t ep, uint8_t conf, USBReadParser *p) {
776         const uint8_t bufSize = 64;
777         uint8_t buf[bufSize];
778         USB_CONFIGURATION_DESCRIPTOR *ucd = reinterpret_cast<USB_CONFIGURATION_DESCRIPTOR *>(buf);
779
780         uint8_t ret = getConfDescr(addr, ep, 9, conf, buf);
781
782         if(ret)
783                 return ret;
784
785         uint16_t total = ucd->wTotalLength;
786
787         //USBTRACE2("\r\ntotal conf.size:", total);
788
789         return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, total, bufSize, buf, p));
790 }
791
792 //get string descriptor
793
794 uint8_t USB::getStrDescr(uint8_t addr, uint8_t ep, uint16_t ns, uint8_t index, uint16_t langid, uint8_t* dataptr) {
795         return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, ns, ns, dataptr, NULL));
796 }
797 //set address
798
799 uint8_t USB::setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr) {
800         uint8_t rcode = ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL);
801         //delay(2); //per USB 2.0 sect.9.2.6.3
802         delay(300); // Older spec says you should wait at least 200ms
803         return rcode;
804         //return ( ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL));
805 }
806 //set configuration
807
808 uint8_t USB::setConf(uint8_t addr, uint8_t ep, uint8_t conf_value) {
809         return ( ctrlReq(addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL));
810 }
811
812 #endif // defined(USB_METHODS_INLINE)