LibXenon
Bare-metal Xbox 360 homebrew library
Loading...
Searching...
No Matches
usbd.c
Go to the documentation of this file.
1/* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
3 *
4 * USB device layer File: usbd.c
5 *
6 * This module deals with devices (things connected to USB buses)
7 *
8 * Author: Mitch Lichtenberg
9 *
10 *********************************************************************
11 *
12 * Copyright 2000,2001,2002,2003,2005
13 * Broadcom Corporation. All rights reserved.
14 *
15 * This software is furnished under license and may be used and
16 * copied only in accordance with the following terms and
17 * conditions. Subject to these conditions, you may download,
18 * copy, install, use, modify and distribute modified or unmodified
19 * copies of this software in source and/or binary form. No title
20 * or ownership is transferred hereby.
21 *
22 * 1) Any source code used, modified or distributed must reproduce
23 * and retain this copyright notice and list of conditions
24 * as they appear in the source file.
25 *
26 * 2) No right is granted to use any trade name, trademark, or
27 * logo of Broadcom Corporation. The "Broadcom Corporation"
28 * name may not be used to endorse or promote products derived
29 * from this software without the prior written permission of
30 * Broadcom Corporation.
31 *
32 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
33 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
34 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
35 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
36 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
37 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
38 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
39 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
40 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
41 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
42 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
43 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
44 * THE POSSIBILITY OF SUCH DAMAGE.
45 ********************************************************************* */
46
47
48#include "cfe.h"
49
50#include "usbchap9.h"
51#include "usbd.h"
52
53
54/* For systems with non-coherent DMA, allocate all buffers to be
55 cache-aligned and multiples of a cache line in size, so that they
56 can be safely flushed or invalidated. */
57
58#define CACHE_ALIGN 32 /* XXX place holder, big enough to now. */
59#define ALIGN(n,align) (((n)+((align)-1)) & ~((align)-1))
60
61#define usb_dma_alloc(n) (KMALLOC(ALIGN((n),CACHE_ALIGN),CACHE_ALIGN))
62
63
64/* *********************************************************************
65 * Globals
66 ********************************************************************* */
67
68int usb_noisy = 0;
69
70//#define _USBREQTRACE_
71#ifdef _USBREQTRACE_
72#define REQTRACE(x) x
73
74static char *devname(usbreq_t *ur)
75{
76 if (ur->ur_dev == NULL) return "unkdev";
77 if (ur->ur_dev->ud_drv == NULL) return "unkdrv";
78 return ur->ur_dev->ud_drv->udrv_name;
79}
80static char *eptname(usbreq_t *ur)
81{
82 static char buf[16];
83
84 if (ur->ur_pipe == NULL) return "unkpipe";
85 sprintf(buf,"pipe%02X/%02X",ur->ur_pipe->up_flags,ur->ur_pipe->up_num);
86 return buf;
87}
88
89#else
90#define REQTRACE(x)
91#endif
92
94
95
96/* *********************************************************************
97 * usb_create_pipe(dev,epaddr,mps,flags)
98 *
99 * Create a pipe, causing the corresponding endpoint to
100 * be created in the host controller driver. Pipes form the
101 * basic "handle" for unidirectional communications with a
102 * USB device.
103 *
104 * Input parameters:
105 * dev - device we're talking about
106 * epaddr - endpoint address open, usually from the endpoint
107 * descriptor
108 * mps - maximum packet size understood by the device
109 * flags - flags for this pipe (UP_xxx flags)
110 *
111 * Return value:
112 * <0 if error
113 * 0 if ok
114 ********************************************************************* */
115
116int usb_create_pipe(usbdev_t *dev,int epaddr,int mps,int flags)
117{
118 usbpipe_t *pipe;
119 int pipeidx;
120
121 pipeidx = USB_EPADDR_TO_IDX(epaddr);
122
123 if (dev->ud_pipes[pipeidx] != NULL) {
124 printf("Trying to create a pipe that was already created!\n");
125 return 0;
126 }
127
128 pipe = KMALLOC(sizeof(usbpipe_t),0);
129
130 if (!pipe) return -1;
131
132 pipe->up_flags = flags;
133 pipe->up_num = pipeidx;
134 pipe->up_mps = mps;
135 pipe->up_dev = dev;
136 if (dev->ud_flags & UD_FLAG_LOWSPEED) flags |= UP_TYPE_LOWSPEED;
137 pipe->up_hwendpoint = UBEPTCREATE(dev->ud_bus,
138 dev->ud_address,
139 USB_ENDPOINT_ADDRESS(epaddr),
140 mps,
141 flags);
142
143 dev->ud_pipes[pipeidx] = pipe;
144
145 return 0;
146}
147
148/* *********************************************************************
149 * usb_open_pipe(dev,epdesc)
150 *
151 * Open a pipe given an endpoint descriptor - this is the
152 * normal way pipes get open, since you've just selected a
153 * configuration and have the descriptors handy with all
154 * the information you need.
155 *
156 * Input parameters:
157 * dev - device we're talking to
158 * epdesc - endpoint descriptor
159 *
160 * Return value:
161 * <0 if error
162 * else endpoint/pipe number (from descriptor)
163 ********************************************************************* */
164
166{
167 int res;
168 int flags = 0;
169
170 if (USB_ENDPOINT_DIR_IN(epdesc->bEndpointAddress)) flags |= UP_TYPE_IN;
171 else flags |= UP_TYPE_OUT;
172
173 switch (epdesc->bmAttributes & USB_ENDPOINT_TYPE_MASK) {
175 flags |= UP_TYPE_CONTROL;
176 break;
178 flags |= UP_TYPE_ISOC;
179 break;
181 flags |= UP_TYPE_BULK;
182 break;
184 flags |= UP_TYPE_INTR;
185 break;
186 }
187
188 res = usb_create_pipe(dev,
189 epdesc->bEndpointAddress,
190 GETUSBFIELD(epdesc,wMaxPacketSize),
191 flags);
192
193 if (res < 0) return res;
194
195 return epdesc->bEndpointAddress;
196}
197
198
199/* *********************************************************************
200 * usb_destroy_pipe(dev,epaddr)
201 *
202 * Close(destroy) an open pipe and remove endpoint descriptor
203 *
204 * Input parameters:
205 * dev - device we're talking to
206 * epaddr - pipe to close
207 *
208 * Return value:
209 * nothing
210 ********************************************************************* */
211
212void usb_destroy_pipe(usbdev_t *dev,int epaddr)
213{
214 usbpipe_t *pipe;
215 int pipeidx;
216
217 pipeidx = USB_EPADDR_TO_IDX(epaddr);
218
219 pipe = dev->ud_pipes[pipeidx];
220 if (!pipe) return;
221
222 if (dev->ud_pipes[pipeidx]) {
223 UBEPTDELETE(dev->ud_bus,
224 dev->ud_pipes[pipeidx]->up_hwendpoint);
225 }
226
227 KFREE(dev->ud_pipes[pipeidx]);
228 dev->ud_pipes[pipeidx] = NULL;
229}
230
231
232/* *********************************************************************
233 * usb_destroy_all_pipes(dev)
234 *
235 * Destroy all pipes related to this device.
236 *
237 * Input parameters:
238 * dev - device we're clearing out
239 *
240 * Return value:
241 * nothing
242 ********************************************************************* */
243
245{
246 int idx;
247
248 for (idx = 0; idx < UD_MAX_PIPES; idx++) {
249 if (dev->ud_pipes[idx]) {
250 UBEPTDELETE(dev->ud_bus,
251 dev->ud_pipes[idx]->up_hwendpoint);
252 KFREE(dev->ud_pipes[idx]);
253 dev->ud_pipes[idx] = NULL;
254 }
255 }
256}
257
258/* *********************************************************************
259 * usb_destroy_device(dev)
260 *
261 * Delete an entire USB device, closing its pipes and freeing
262 * the device data structure
263 *
264 * Input parameters:
265 * dev - device to destroy
266 *
267 * Return value:
268 * nothing
269 ********************************************************************* */
270
272{
274
275 dev->ud_bus->ub_devices[dev->ud_address] = NULL;
276
277 KFREE(dev);
278}
279
280
281/* *********************************************************************
282 * usb_create_device(bus,lowspeed)
283 *
284 * Create a new USB device. This device will be set to
285 * communicate on address zero (default address) and will be
286 * ready for basic stuff so we can figure out what it is.
287 * The control pipe will be open, so you can start requesting
288 * descriptors right away.
289 *
290 * Input parameters:
291 * bus - bus to create device on
292 * lowspeed - true if it's a lowspeed device (the hubs tell
293 * us these things)
294 *
295 * Return value:
296 * usb device structure, or NULL
297 ********************************************************************* */
298
300{
301 usbdev_t *dev;
302 int pipeflags;
303
304 /*
305 * Create the device structure.
306 */
307
308 dev = KMALLOC(sizeof(usbdev_t),0);
309 memset(dev,0,sizeof(usbdev_t));
310
311 dev->ud_bus = bus;
312 dev->ud_address = 0; /* default address */
313 dev->ud_parent = NULL;
314 dev->ud_flags = 0;
315
316 /*
317 * Adjust things based on the target device speed
318 */
319
320 pipeflags = UP_TYPE_CONTROL;
321 if (lowspeed) {
322 pipeflags |= UP_TYPE_LOWSPEED;
324 }
325
326 /*
327 * Create the control pipe.
328 */
329
330 usb_create_pipe(dev,0,
332 pipeflags);
333
334 return dev;
335}
336
337/* *********************************************************************
338 * usb_make_request(dev,epaddr,buf,len,flags)
339 *
340 * Create a template request structure with basic fields
341 * ready to go. A shorthand routine.
342 *
343 * Input parameters:
344 * dev- device we're talking to
345 * epaddr - endpoint address, from usb_open_pipe()
346 * buf,length - user buffer and buffer length
347 * flags - transfer direction, etc. (UR_xxx flags)
348 *
349 * Return value:
350 * usbreq_t pointer, or NULL
351 ********************************************************************* */
352
353usbreq_t *usb_make_request(usbdev_t *dev,int epaddr,uint8_t *buf,int length,int flags)
354{
355 usbreq_t *ur;
356 usbpipe_t *pipe;
357 int pipeidx;
358
359 pipeidx = USB_EPADDR_TO_IDX(epaddr);
360
361 pipe = dev->ud_pipes[pipeidx];
362
363 if (pipe == NULL) return NULL;
364
365 ur = KMALLOC(sizeof(usbreq_t),0);
366 memset(ur,0,sizeof(usbreq_t));
367
368 ur->ur_dev = dev;
369 ur->ur_pipe = pipe;
370 ur->ur_buffer = buf;
371 ur->ur_length = length;
372 ur->ur_flags = flags;
373 ur->ur_callback = NULL;
374
375 return ur;
376
377}
378
379/* *********************************************************************
380 * usb_poll(bus)
381 *
382 * Handle device-driver polling - simply vectors to host controller
383 * driver.
384 *
385 * Input parameters:
386 * bus - bus structure
387 *
388 * Return value:
389 * nothing
390 ********************************************************************* */
391
393{
394 UBINTR(bus);
395}
396
397/* *********************************************************************
398 * usb_daemon(bus)
399 *
400 * Polls for topology changes and initiates a bus scan if
401 * necessary.
402 *
403 * Input parameters:
404 * bus - bus to watch
405 *
406 * Return value:
407 * nothing
408 ********************************************************************* */
409
411{
412 /*
413 * Just see if someone flagged a need for a scan here
414 * and start the bus scan if necessary.
415 *
416 * The actual scanning is a hub function, starting at the
417 * root hub, so the code for that is over there.
418 */
419
421 bus->ub_flags &= ~UB_FLG_NEEDSCAN;
422 usb_scan(bus);
423 }
424}
425
426/* *********************************************************************
427 * usb_cancel_request(ur)
428 *
429 * Cancel a pending usb transfer request.
430 *
431 * Input parameters:
432 * ur - request to cancel
433 *
434 * Return value:
435 * 0 if ok
436 * else error (could not find request)
437 ********************************************************************* */
438
440{
441 printf("usb_cancel_request is not implemented.\n");
442 return 0;
443}
444
445/* *********************************************************************
446 * usb_free_request(ur)
447 *
448 * Return a transfer request to the free pool.
449 *
450 * Input parameters:
451 * ur - request to return
452 *
453 * Return value:
454 * nothing
455 ********************************************************************* */
456
458{
459 REQTRACE(printf("Free %p (%s,%s)\n",ur,eptname(ur),devname(ur)));
460
461 if (ur->ur_inprogress) {
462 printf("Yow! Tried to free a request that was in progress!\n");
463 return;
464 }
465 KFREE(ur);
466}
467
468/* *********************************************************************
469 * usb_delay_ms(bus,ms)
470 *
471 * Wait a while, calling the polling routine as we go.
472 *
473 * Input parameters:
474 * bus - bus we're talking to
475 * ms - how long to wait
476 *
477 * Return value:
478 * nothing
479 ********************************************************************* */
480
481
483{
484 mdelay(ms);
485}
486
487/* *********************************************************************
488 * usb_queue_request(ur)
489 *
490 * Call the transfer handler in the host controller driver to
491 * set up a transfer descriptor
492 *
493 * Input parameters:
494 * ur - request to queue
495 *
496 * Return value:
497 * 0 if ok
498 * else error
499 ********************************************************************* */
500
501
503{
504 int res;
505
506 REQTRACE(printf("Queue %p (%s,%s)\n",ur,eptname(ur),devname(ur)));
507
508 ur->ur_inprogress = 1;
509 ur->ur_xferred = 0;
510 res = UBXFER(ur->ur_dev->ud_bus,
512 ur);
513 return res;
514}
515
516/* *********************************************************************
517 * usb_wait_request(ur)
518 *
519 * Wait until a request completes, calling the polling routine
520 * as we wait.
521 *
522 * Input parameters:
523 * ur - request to wait for
524 *
525 * Return value:
526 * request status
527 ********************************************************************* */
528
530{
531 while ((volatile int) (ur->ur_inprogress)) {
532 usb_poll(ur->ur_dev->ud_bus);
533 }
534
535 return ur->ur_status;
536}
537
538/* *********************************************************************
539 * usb_sync_request(ur)
540 *
541 * Synchronous request - call usb_queue and then usb_wait
542 *
543 * Input parameters:
544 * ur - request to submit
545 *
546 * Return value:
547 * status of request
548 ********************************************************************* */
549
551{
553 return usb_wait_request(ur);
554}
555
556/* *********************************************************************
557 * usb_make_sync_request(dev,epaddr,buf,len,flags)
558 *
559 * Create a request, wait for it to complete, and delete
560 * the request. A shorthand**2 routine.
561 *
562 * Input parameters:
563 * dev- device we're talking to
564 * epaddr - endpoint address, from usb_open_pipe()
565 * buf,length - user buffer and buffer length
566 * flags - transfer direction, etc. (UR_xxx flags)
567 *
568 * Return value:
569 * status of request
570 ********************************************************************* */
571
572int usb_make_sync_request(usbdev_t *dev,int epaddr,uint8_t *buf,int length,int flags)
573{
574 usbreq_t *ur;
575 int res;
576
577 ur = usb_make_request(dev,epaddr,buf,length,flags);
578 res = usb_sync_request(ur);
580 return res;
581}
582
583/* *********************************************************************
584 * usb_simple_request(dev,reqtype,bRequest,wValue,wIndex)
585 *
586 * Handle a simple USB control pipe request. These are OUT
587 * requests with no data phase.
588 *
589 * Input parameters:
590 * dev - device we're talking to
591 * reqtype - request type (bmRequestType) for descriptor
592 * wValue - wValue for descriptor
593 * wIndex - wIndex for descriptor
594 *
595 * Return value:
596 * 0 if ok
597 * else error
598 ********************************************************************* */
599
600int usb_simple_request(usbdev_t *dev,uint8_t reqtype,int bRequest,int wValue,int wIndex)
601{
602 return usb_std_request(dev,reqtype,bRequest,wValue,wIndex,NULL,0);
603}
604
605
606/* *********************************************************************
607 * usb_set_configuration(dev,config)
608 *
609 * Set the current configuration for a USB device.
610 *
611 * Input parameters:
612 * dev - device we're talking to
613 * config - bConfigValue for the device
614 *
615 * Return value:
616 * request status
617 ********************************************************************* */
618
619int usb_set_configuration(usbdev_t *dev,int config)
620{
621 int res;
622
623 res = usb_simple_request(dev,0x00,USB_REQUEST_SET_CONFIGURATION,config,0);
624
625 return res;
626}
627
628
629/* *********************************************************************
630 * usb_new_address(bus)
631 *
632 * Return the next available address for the specified bus
633 *
634 * Input parameters:
635 * bus - bus to assign an address for
636 *
637 * Return value:
638 * new address, <0 if error
639 ********************************************************************* */
640
642{
643 int idx;
644
645 for (idx = 1; idx < USB_MAX_DEVICES; idx++) {
646 if (bus->ub_devices[idx] == NULL) return idx;
647 }
648
649 return -1;
650}
651
652/* *********************************************************************
653 * usb_set_address(dev,address)
654 *
655 * Set the address of a device. This also puts the device
656 * in the master device table for the bus and reconfigures the
657 * address of the control pipe.
658 *
659 * Input parameters:
660 * dev - device we're talking to
661 * address - new address (1..127)
662 *
663 * Return value:
664 * request status
665 ********************************************************************* */
666
668{
669 int res;
670 int idx;
671 usbpipe_t *pipe;
672
674
675 if (res == 0) {
676 dev->ud_bus->ub_devices[address] = dev;
677 dev->ud_address = address;
678 for (idx = 0; idx < UD_MAX_PIPES; idx++) {
679 pipe = dev->ud_pipes[idx];
680 if (pipe && pipe->up_hwendpoint) {
682 }
683 }
684 }
685
686 return res;
687}
688
689/* *********************************************************************
690 * usb_set_ep0mps(dev,mps)
691 *
692 * Set the maximum packet size of endpoint zero (mucks with the
693 * endpoint in the host controller)
694 *
695 * Input parameters:
696 * dev - device we're talking to
697 * mps - max packet size for endpoint zero
698 *
699 * Return value:
700 * request status
701 ********************************************************************* */
702
703int usb_set_ep0mps(usbdev_t *dev,int mps)
704{
705 usbpipe_t *pipe;
706
707 pipe = dev->ud_pipes[0];
708 if (pipe && pipe->up_hwendpoint) {
709 UBEPTSETMPS(dev->ud_bus,pipe->up_hwendpoint,mps);
710 }
711 if (pipe) {
712 pipe->up_mps = mps;
713 }
714
715 return 0;
716}
717
718/* *********************************************************************
719 * usb_clear_stall(dev,epaddr)
720 *
721 * Clear a stall condition on the specified pipe
722 *
723 * Input parameters:
724 * dev - device we're talking to
725 * epaddr - endpoint address
726 *
727 * Return value:
728 * 0 if ok
729 * else error
730 ********************************************************************* */
731int usb_clear_stall(usbdev_t *dev,int epaddr)
732{
733 uint8_t *requestbuf;
735 usbreq_t *ur;
736// int res;
737 int pipeidx;
738
739 /*
740 * Clear the stall in the hardware.
741 */
742
743 pipeidx = USB_EPADDR_TO_IDX(epaddr);
744
745 UBEPTCLEARTOGGLE(dev->ud_bus,dev->ud_pipes[pipeidx]->up_hwendpoint);
746
747 /*
748 * Do the "clear stall" request. Note that we should do this
749 * without calling usb_simple_request, since usb_simple_request
750 * may itself stall.
751 */
752
753 requestbuf = usb_dma_alloc(32);
754 req = (usb_device_request_t *) requestbuf;
755
756 req->bmRequestType = 0x02;
758 PUTUSBFIELD(req,wValue,0); /* ENDPOINT_HALT */
759 PUTUSBFIELD(req,wIndex,epaddr);
760 PUTUSBFIELD(req,wLength,0);
761
762 ur = usb_make_request(dev,0,requestbuf,
763 sizeof(usb_device_request_t),
765 /*res =*/ usb_sync_request(ur);
767 ur = usb_make_request(dev,0,requestbuf,0,UR_FLAG_STATUS_IN);
768 /*res =*/ usb_sync_request(ur);
770
771 KFREE(requestbuf);
772
773 return 0;
774}
775
776
777
778/* *********************************************************************
779 * usb_std_request(dev,bmRequestType,bRequest,wValue,
780 * wIndex,buffer,length)
781 *
782 * Do a standard control request on the control pipe,
783 * with the appropriate setup, data, and status phases.
784 *
785 * Input parameters:
786 * dev - dev we're talking to
787 * bmRequestType,bRequest,wValue,wIndex - fields for the
788 * USB request structure
789 * buffer - user buffer
790 * length - length of user buffer
791 *
792 * Return value:
793 * number of bytes transferred
794 ********************************************************************* */
795
796int usb_std_request(usbdev_t *dev,uint8_t bmRequestType,
797 uint8_t bRequest,uint16_t wValue,
798 uint16_t wIndex,uint8_t *buffer,int length)
799{
800 usbpipe_t *pipe = dev->ud_pipes[0];
801 usbreq_t *ur;
802 int res;
804 uint8_t *databuf = NULL;
805
806 req = usb_dma_alloc(32);
807
808 if ((buffer != NULL) && (length !=0)) {
809 databuf = usb_dma_alloc(length);
810 if (!(bmRequestType & USBREQ_DIR_IN)) {
811 memcpy(databuf,buffer,length);
812 }
813 else {
814 memset(databuf,0,length);
815 }
816 }
817
818 req->bmRequestType = bmRequestType;
819 req->bRequest = bRequest;
820 PUTUSBFIELD(req,wValue,wValue);
821 PUTUSBFIELD(req,wIndex,wIndex);
822 PUTUSBFIELD(req,wLength,length);
823
825 res = usb_sync_request(ur);
827
828 if (length != 0) {
829 if (bmRequestType & USBREQ_DIR_IN) {
830 ur = usb_make_request(dev,0,databuf,length,UR_FLAG_IN);
831 }
832 else {
833 ur = usb_make_request(dev,0,databuf,length,UR_FLAG_OUT);
834 }
835
836 res = usb_sync_request(ur);
837
838 if (res == 4) { /* STALL */
839 usb_clear_stall(dev,pipe->up_num);
841 if (databuf) KFREE(databuf);
842 KFREE(req);
843 return 0;
844 }
845
846 length = ur->ur_xferred;
848 }
849
850 if ((length != 0) && (databuf != NULL) && (bmRequestType & USBREQ_DIR_IN)) {
851 memcpy(buffer,databuf,length);
852 }
853
854 if (bmRequestType & USBREQ_DIR_IN) {
855 ur = usb_make_request(dev,0,(uint8_t *)req,0,UR_FLAG_STATUS_OUT);
856 }
857 else {
858 ur = usb_make_request(dev,0,(uint8_t *)req,0,UR_FLAG_STATUS_IN);
859 }
860
861 res = usb_sync_request(ur);
863
864 if (res == 4) { /* STALL */
865 usb_clear_stall(dev,pipe->up_num);
866 if (databuf) KFREE(databuf);
867 KFREE(req);
868 return 0;
869 }
870
871 if (databuf) KFREE(databuf);
872 KFREE(req);
873
874 return length;
875}
876
877
878
879
880/* *********************************************************************
881 * usb_get_descriptor(dev,reqtype,dsctype,dscidx,respbuf,buflen)
882 *
883 * Request a descriptor from the device.
884 *
885 * Input parameters:
886 * dev - device we're talking to
887 * reqtype - bmRequestType field for descriptor we want
888 * dsctype - descriptor type we want
889 * dscidx - index of descriptor we want (often zero)
890 * respbuf - response buffer
891 * buflen - length of response buffer
892 *
893 * Return value:
894 * number of bytes transferred
895 ********************************************************************* */
896
897int usb_get_descriptor(usbdev_t *dev,uint8_t reqtype,int dsctype,int dscidx,
898 uint8_t *respbuf,int buflen)
899{
900 return usb_std_request(dev,
902 USB_DESCRIPTOR_TYPEINDEX(dsctype,dscidx),
903 0,
904 respbuf,buflen);
905}
906
907/* *********************************************************************
908 * usb_get_string_descriptor(dev,reqtype,dsctype,dscidx,respbuf,buflen)
909 *
910 * Request a descriptor from the device.
911 *
912 * Input parameters:
913 * dev - device we're talking to
914 * dscidx - index of descriptor we want
915 * respbuf - response buffer
916 * buflen - length of response buffer
917 *
918 * Return value:
919 * number of bytes transferred
920 ********************************************************************* */
921
922static int usb_get_string_descriptor(usbdev_t *dev,int dscidx,
923 uint8_t *respbuf,int buflen)
924{
925 return usb_std_request(dev,
928 0x0409, /* Microsoft lang code for English */
929 respbuf,buflen);
930}
931
932/* *********************************************************************
933 * usb_get_string(dev,id,buf,maxlen)
934 *
935 * Request a string from the device, converting it from
936 * unicode to ascii (brutally).
937 *
938 * Input parameters:
939 * dev - device we're talking to
940 * id - string ID
941 * buf - buffer to receive string (null terminated)
942 * maxlen - length of buffer
943 *
944 * Return value:
945 * number of characters in returned string
946 ********************************************************************* */
947
948int usb_get_string(usbdev_t *dev,int id,char *buf,int maxlen)
949{
950 int amtcopy;
951 uint8_t *respbuf;
952 int idx;
953 usb_string_descr_t *sdscr;
954
955 respbuf = usb_dma_alloc(maxlen*2+2);
956 sdscr = (usb_string_descr_t *) respbuf;
957
958 /*
959 * First time just get the header of the descriptor so we can
960 * get the string length
961 */
962
963 amtcopy = usb_get_string_descriptor(dev,id,respbuf,2);
964
965 /*
966 * now do it again to get the whole string.
967 */
968
969 if (maxlen > sdscr->bLength) maxlen = sdscr->bLength;
970
971 amtcopy = usb_get_string_descriptor(dev,id,respbuf,maxlen);
972
973 *buf = '\0';
974 amtcopy = sdscr->bLength - 2;
975 if (amtcopy <= 0) return amtcopy;
976
977 for (idx = 0; idx < amtcopy; idx+=2) {
978 *buf++ = sdscr->bString[idx];
979 }
980
981 *buf = '\0';
982
983 KFREE(respbuf);
984
985 return amtcopy;
986}
987
988
989
990/* *********************************************************************
991 * usb_get_device_descriptor(dev,dscr,smallflg)
992 *
993 * Request the device descriptor for the device. This is often
994 * the first descriptor requested, so it needs to be done in
995 * stages so we can find out how big the control pipe is.
996 *
997 * Input parameters:
998 * dev - device we're talking to
999 * dscr - pointer to buffer to receive descriptor
1000 * smallflg - TRUE to request just 8 bytes.
1001 *
1002 * Return value:
1003 * number of bytes copied
1004 ********************************************************************* */
1005
1007{
1008 int res;
1009 uint8_t *respbuf;
1010 int amtcopy;
1011
1012 /*
1013 * Smallflg truncates the request 8 bytes. We need to do this for
1014 * the very first transaction to a USB device in order to determine
1015 * the size of its control pipe. Bad things will happen if you
1016 * try to retrieve more data than the control pipe will hold.
1017 *
1018 * So, be conservative at first and get the first 8 bytes of the
1019 * descriptor. Byte 7 is bMaxPacketSize0, the size of the control
1020 * pipe. Then you can go back and submit a bigger request for
1021 * everything else.
1022 */
1023
1024 amtcopy = smallflg ? USB_CONTROL_ENDPOINT_MIN_SIZE : sizeof(usb_device_descr_t);
1025
1026 respbuf = usb_dma_alloc(64);
1027 res = usb_get_descriptor(dev,USBREQ_DIR_IN,USB_DEVICE_DESCRIPTOR_TYPE,0,respbuf,amtcopy);
1028 memcpy(dscr,respbuf,amtcopy);
1029 KFREE(respbuf);
1030 return res;
1031
1032}
1033
1034/* *********************************************************************
1035 * usb_get_config_descriptor(dev,dscr,idx,maxlen)
1036 *
1037 * Request the configuration descriptor from the device.
1038 *
1039 * Input parameters:
1040 * dev - device we're talking to
1041 * dscr - descriptor buffer (receives data from device)
1042 * idx - index of config we want (usually zero)
1043 * maxlen - total size of buffer to receive descriptor
1044 *
1045 * Return value:
1046 * number of bytes copied
1047 ********************************************************************* */
1048
1050{
1051 int res;
1052 uint8_t *respbuf;
1053
1054 respbuf = usb_dma_alloc(maxlen);
1057 respbuf,maxlen);
1058 memcpy(dscr,respbuf,maxlen);
1059 KFREE(respbuf);
1060 return res;
1061
1062}
1063
1064
1065
1066/* *********************************************************************
1067 * usb_get_device_status(dev,status)
1068 *
1069 * Request status from the device (status descriptor)
1070 *
1071 * Input parameters:
1072 * dev - device we're talking to
1073 * status - receives device_status structure
1074 *
1075 * Return value:
1076 * number of bytes returned
1077 ********************************************************************* */
1078
1080{
1081 return usb_std_request(dev,
1083 0,
1084 0,
1085 0,
1086 (uint8_t *) status,
1087 sizeof(usb_device_status_t));
1088}
1089
1090
1091/* *********************************************************************
1092 * usb_complete_request(ur,status)
1093 *
1094 * Called when a usb request completes - pass status to
1095 * caller and call the callback if there is one.
1096 *
1097 * Input parameters:
1098 * ur - usbreq_t to complete
1099 * status - completion status
1100 *
1101 * Return value:
1102 * nothing
1103 ********************************************************************* */
1104
1106{
1107 REQTRACE(printf("Complete %p (%s,%s) Status=%d\n",ur,eptname(ur),devname(ur),status));
1108
1109 ur->ur_status = status;
1110 ur->ur_inprogress = 0;
1111 if (ur->ur_callback) (*(ur->ur_callback))(ur);
1112}
1113
1114
1115/* *********************************************************************
1116 * usb_initroot(bus)
1117 *
1118 * Initialize the root hub for the bus - we need to do this
1119 * each time a bus is configured.
1120 *
1121 * Input parameters:
1122 * bus - bus to initialize
1123 *
1124 * Return value:
1125 * nothing
1126 ********************************************************************* */
1127
1129{
1130 usbdev_t *dev;
1131 usb_driver_t *drv;
1132 int addr;
1133 int res;
1134 uint8_t *buf;
1135 int len;
1136 usb_config_descr_t cfgdescr;
1137
1138 /*
1139 * Create a device for the root hub.
1140 */
1141
1142 dev = usb_create_device(bus,0);
1143 bus->ub_roothub = dev;
1144 dev->ud_drv = &usbroothub_driver;
1145
1146 /*
1147 * Get the device descriptor. Make sure it's a hub.
1148 */
1149
1150 res = usb_get_device_descriptor(dev,&(dev->ud_devdescr),TRUE);
1151
1153 printf("Error! Root device is not a hub!\n");
1154 return;
1155 }
1156
1157 /*
1158 * Set up the max packet size for the control endpoint,
1159 * then get the rest of the descriptor.
1160 */
1161
1163 res = usb_get_device_descriptor(dev,&(dev->ud_devdescr),FALSE);
1164
1165 /*
1166 * Obtain a new address and set the address of the
1167 * root hub to this address.
1168 */
1169
1170 addr = usb_new_address(dev->ud_bus);
1171 res = usb_set_address(dev,addr);
1172
1173 /*
1174 * Get the configuration descriptor and all the
1175 * associated interface and endpoint descriptors.
1176 */
1177
1178 res = usb_get_config_descriptor(dev,&cfgdescr,0,
1179 sizeof(usb_config_descr_t));
1180 if (res != sizeof(usb_config_descr_t)) {
1181 printf("[a]usb_get_config_descriptor returns %d\n",res);
1182 }
1183
1184 len = GETUSBFIELD(&cfgdescr,wTotalLength);
1185 buf = usb_dma_alloc(len);
1186
1187 res = usb_get_config_descriptor(dev,(usb_config_descr_t *)buf,0,len);
1188 if (res != len) {
1189 printf("[b]usb_get_config_descriptor returns %d\n",res);
1190 }
1191
1192 dev->ud_cfgdescr = (usb_config_descr_t *) buf;
1193
1194 /*
1195 * Select the configuration. Not really needed for our poor
1196 * imitation root hub, but it's the right thing to do.
1197 */
1198
1200
1201 /*
1202 * Find the driver for this. It had better be the hub
1203 * driver.
1204 */
1205
1206 drv = usb_find_driver(dev);
1207
1208 /*
1209 * Call the attach method.
1210 */
1211
1212 (*(drv->udrv_attach))(dev,drv);
1213
1214 /*
1215 * Hub should now be operational.
1216 */
1217
1218}
1219
1220
1221/* *********************************************************************
1222 * usb_find_cfg_descr(dev,dtype,idx)
1223 *
1224 * Find a configuration descriptor - we retrieved all the config
1225 * descriptors during discovery, this lets us dig out the one
1226 * we want.
1227 *
1228 * Input parameters:
1229 * dev - device we are talking to
1230 * dtype - descriptor type to find
1231 * idx - index of descriptor if there's more than one
1232 *
1233 * Return value:
1234 * pointer to descriptor or NULL if not found
1235 ********************************************************************* */
1236
1237void *usb_find_cfg_descr(usbdev_t *dev,int dtype,int idx)
1238{
1239 uint8_t *endptr;
1240 uint8_t *ptr;
1241 usb_config_descr_t *cfgdscr;
1242
1243 if (dev->ud_cfgdescr == NULL) return NULL;
1244
1245 ptr = (uint8_t *) dev->ud_cfgdescr;
1246 endptr = ptr + GETUSBFIELD((dev->ud_cfgdescr),wTotalLength);
1247
1248 while (ptr < endptr) {
1249
1250 cfgdscr = (usb_config_descr_t *) ptr;
1251
1252 if (cfgdscr->bDescriptorType == dtype) {
1253 if (idx == 0) return (void *) ptr;
1254 else idx--;
1255 }
1256
1257 ptr += cfgdscr->bLength;
1258
1259 }
1260
1261 return NULL;
1262}
uint16_t length
Definition: ata.h:4
uint32_t address
Definition: ata.h:0
#define NULL
Definition: def.h:47
u32 status
Definition: ehci_defs.h:15
u32 ptr
Definition: iso9660.c:536
#define KMALLOC(size, align)
Definition: lib_malloc.h:92
#define KFREE(ptr)
Definition: lib_malloc.h:93
u16 uint16_t
Definition: libfdt_env.h:10
u8 uint8_t
Definition: libfdt_env.h:9
uint8_t bConfigurationValue
Definition: usbchap9.h:216
uint8_t bDescriptorType
Definition: usbchap9.h:213
uint8_t bDeviceClass
Definition: usbchap9.h:180
uint8_t bMaxPacketSize0
Definition: usbchap9.h:183
uint8_t bmRequestType
Definition: usbchap9.h:352
int(* udrv_attach)(usbdev_t *, usb_driver_t *)
Definition: usbd.h:292
char * udrv_name
Definition: usbd.h:291
uint8_t bmAttributes
Definition: usbchap9.h:197
uint8_t bEndpointAddress
Definition: usbchap9.h:196
uint8_t bString[1]
Definition: usbchap9.h:239
Definition: usbd.h:92
usbdev_t * ub_roothub
Definition: usbd.h:96
usbdev_t * ub_devices[USB_MAX_DEVICES]
Definition: usbd.h:97
unsigned int ub_flags
Definition: usbd.h:98
Definition: usbd.h:141
usbpipe_t * ud_pipes[UD_MAX_PIPES]
Definition: usbd.h:145
int ud_flags
Definition: usbd.h:147
usb_config_descr_t * ud_cfgdescr
Definition: usbd.h:150
int ud_address
Definition: usbd.h:144
usbbus_t * ud_bus
Definition: usbd.h:143
usb_device_descr_t ud_devdescr
Definition: usbd.h:149
usb_driver_t * ud_drv
Definition: usbd.h:142
struct usbdev_s * ud_parent
Definition: usbd.h:146
int up_mps
Definition: usbd.h:123
int up_flags
Definition: usbd.h:124
usb_ept_t * up_hwendpoint
Definition: usbd.h:120
usbdev_t * up_dev
Definition: usbd.h:121
int up_num
Definition: usbd.h:122
Definition: usbd.h:171
int(* ur_callback)(struct usbreq_s *req)
Definition: usbd.h:196
int ur_inprogress
Definition: usbd.h:195
int ur_status
Definition: usbd.h:188
uint8_t * ur_buffer
Definition: usbd.h:185
int ur_xferred
Definition: usbd.h:187
int ur_flags
Definition: usbd.h:189
usbdev_t * ur_dev
Definition: usbd.h:178
int ur_length
Definition: usbd.h:186
usbpipe_t * ur_pipe
Definition: usbd.h:179
void mdelay(int u)
Definition: time.c:17
#define GETUSBFIELD(s, f)
Definition: usbchap9.h:347
#define USB_ENDPOINT_TYPE_INTERRUPT
Definition: usbchap9.h:83
#define PUTUSBFIELD(s, f, v)
Definition: usbchap9.h:348
#define USB_DESCRIPTOR_TYPEINDEX(d, i)
Definition: usbchap9.h:71
#define USB_REQUEST_GET_DESCRIPTOR
Definition: usbchap9.h:129
#define USB_CONFIGURATION_DESCRIPTOR_TYPE
Definition: usbchap9.h:63
#define USB_ENDPOINT_DIR_IN(addr)
Definition: usbchap9.h:108
#define USB_ENDPOINT_ADDRESS(addr)
Definition: usbchap9.h:110
struct usb_device_descr_s usb_device_descr_t
#define USB_ENDPOINT_TYPE_CONTROL
Definition: usbchap9.h:80
#define USB_DEVICE_DESCRIPTOR_TYPE
Definition: usbchap9.h:62
#define USB_CONTROL_ENDPOINT_MIN_SIZE
Definition: usbchap9.h:174
#define USB_REQUEST_SET_CONFIGURATION
Definition: usbchap9.h:132
#define USB_STRING_DESCRIPTOR_TYPE
Definition: usbchap9.h:64
#define USB_ENDPOINT_TYPE_ISOCHRONOUS
Definition: usbchap9.h:81
#define USB_DEVICE_CLASS_HUB
Definition: usbchap9.h:152
#define USB_REQUEST_CLEAR_FEATURE
Definition: usbchap9.h:124
#define USB_REQUEST_SET_ADDRESS
Definition: usbchap9.h:128
#define USB_ENDPOINT_TYPE_MASK
Definition: usbchap9.h:78
#define USBREQ_DIR_IN
Definition: usbchap9.h:362
#define USB_ENDPOINT_TYPE_BULK
Definition: usbchap9.h:82
void * usb_find_cfg_descr(usbdev_t *dev, int dtype, int idx)
Definition: usbd.c:1237
int usb_simple_request(usbdev_t *dev, uint8_t reqtype, int bRequest, int wValue, int wIndex)
Definition: usbd.c:600
int usb_std_request(usbdev_t *dev, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, uint8_t *buffer, int length)
Definition: usbd.c:796
int usb_new_address(usbbus_t *bus)
Definition: usbd.c:641
void usb_destroy_pipe(usbdev_t *dev, int epaddr)
Definition: usbd.c:212
void usb_complete_request(usbreq_t *ur, int status)
Definition: usbd.c:1105
int usb_noisy
Definition: usbd.c:68
int usb_create_pipe(usbdev_t *dev, int epaddr, int mps, int flags)
Definition: usbd.c:116
int usb_wait_request(usbreq_t *ur)
Definition: usbd.c:529
int usb_sync_request(usbreq_t *ur)
Definition: usbd.c:550
usb_driver_t usbroothub_driver
Definition: usbhub.c:120
int usb_get_descriptor(usbdev_t *dev, uint8_t reqtype, int dsctype, int dscidx, uint8_t *respbuf, int buflen)
Definition: usbd.c:897
usbreq_t * usb_make_request(usbdev_t *dev, int epaddr, uint8_t *buf, int length, int flags)
Definition: usbd.c:353
#define REQTRACE(x)
Definition: usbd.c:90
void usb_free_request(usbreq_t *ur)
Definition: usbd.c:457
#define usb_dma_alloc(n)
Definition: usbd.c:61
int usb_get_device_status(usbdev_t *dev, usb_device_status_t *status)
Definition: usbd.c:1079
void usb_daemon(usbbus_t *bus)
Definition: usbd.c:410
void usb_poll(usbbus_t *bus)
Definition: usbd.c:392
int usb_clear_stall(usbdev_t *dev, int epaddr)
Definition: usbd.c:731
usbdev_t * usb_create_device(usbbus_t *bus, int lowspeed)
Definition: usbd.c:299
int usb_queue_request(usbreq_t *ur)
Definition: usbd.c:502
int usb_set_address(usbdev_t *dev, int address)
Definition: usbd.c:667
int usb_get_config_descriptor(usbdev_t *dev, usb_config_descr_t *dscr, int idx, int maxlen)
Definition: usbd.c:1049
int usb_get_string(usbdev_t *dev, int id, char *buf, int maxlen)
Definition: usbd.c:948
void usb_initroot(usbbus_t *bus)
Definition: usbd.c:1128
int usb_cancel_request(usbreq_t *ur)
Definition: usbd.c:439
int usb_get_device_descriptor(usbdev_t *dev, usb_device_descr_t *dscr, int smallflg)
Definition: usbd.c:1006
void usb_delay_ms(usbbus_t *bus, int ms)
Definition: usbd.c:482
void usb_destroy_all_pipes(usbdev_t *dev)
Definition: usbd.c:244
int usb_set_configuration(usbdev_t *dev, int config)
Definition: usbd.c:619
int usb_set_ep0mps(usbdev_t *dev, int mps)
Definition: usbd.c:703
int usb_make_sync_request(usbdev_t *dev, int epaddr, uint8_t *buf, int length, int flags)
Definition: usbd.c:572
int usb_open_pipe(usbdev_t *dev, usb_endpoint_descr_t *epdesc)
Definition: usbd.c:165
void usb_destroy_device(usbdev_t *dev)
Definition: usbd.c:271
#define UP_TYPE_OUT
Definition: usbd.h:115
#define UP_TYPE_IN
Definition: usbd.h:114
#define UBEPTDELETE(bus, ept)
Definition: usbd.h:277
#define UBEPTSETMPS(bus, ept, mps)
Definition: usbd.h:278
#define UR_FLAG_SETUP
Definition: usbd.h:163
#define UP_TYPE_INTR
Definition: usbd.h:111
#define UR_FLAG_OUT
Definition: usbd.h:165
#define UD_MAX_PIPES
Definition: usbd.h:138
#define UR_FLAG_STATUS_IN
Definition: usbd.h:166
#define UBINTR(bus)
Definition: usbd.h:275
#define UP_TYPE_LOWSPEED
Definition: usbd.h:117
#define UR_FLAG_IN
Definition: usbd.h:164
#define UP_TYPE_BULK
Definition: usbd.h:110
#define USB_MAX_DEVICES
Definition: usbd.h:90
#define USB_EPADDR_TO_IDX(addr)
Definition: usbd.h:139
#define UBEPTSETADDR(bus, ept, addr)
Definition: usbd.h:279
usb_driver_t * usb_find_driver(usbdev_t *dev)
Definition: usbdevs.c:158
#define UD_FLAG_LOWSPEED
Definition: usbd.h:135
#define UB_FLG_NEEDSCAN
Definition: usbd.h:102
#define UR_FLAG_STATUS_OUT
Definition: usbd.h:167
#define UP_TYPE_CONTROL
Definition: usbd.h:109
#define UBXFER(bus, ept, xfer)
Definition: usbd.h:281
#define UBEPTCREATE(bus, addr, num, mps, flags)
Definition: usbd.h:276
void usb_scan(usbbus_t *bus)
Definition: usbhub.c:981
#define UBEPTCLEARTOGGLE(bus, ept)
Definition: usbd.h:280
#define UP_TYPE_ISOC
Definition: usbd.h:112
usbbus_t * bus
Definition: usbhack.c:153
#define FALSE
Definition: usbhack.h:58
#define TRUE
True.
Definition: xetypes.h:52