]> git.gir.st - tmk_keyboard.git/blob - tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/Usb.cpp
Merge branch 'ibm4704_fix_protocol'
[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)
Imprint / Impressum