LibXenon
Bare-metal Xbox 360 homebrew library
Loading...
Searching...
No Matches
usbhub.c
Go to the documentation of this file.
1/* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
3 *
4 * USB Hub and device discovery code File: usbhub.c
5 *
6 * This module deals with hubs and device discovery.
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/* For systems with non-coherent DMA, allocate all buffers to be
54 cache-aligned and multiples of a cache line in size, so that they
55 can be safely flushed or invalidated. */
56
57#define CACHE_ALIGN 32 /* XXX place holder, big enough to now. */
58#define BUFF_ALIGN 16
59#define ALIGN(n,align) (((n)+((align)-1)) & ~((align)-1))
60
61#define usb_dma_alloc(n) (KMALLOC(ALIGN((n),CACHE_ALIGN),BUFF_ALIGN))
62#define usb_dma_free(p) (KFREE(p))
63
64/* *********************************************************************
65 * Macros for common hub requests
66 ********************************************************************* */
67
68#define usbhub_set_port_feature(dev,port,feature) \
69 usb_simple_request(dev,0x23,USB_HUBREQ_SET_FEATURE,feature,port)
70
71#define usbhub_set_hub_feature(dev,feature) \
72 usb_simple_request(dev,0x20,USB_HUBREQ_SET_FEATURE,feature,0)
73
74#define usbhub_clear_port_feature(dev,port,feature) \
75 usb_simple_request(dev,0x23,USB_HUBREQ_CLEAR_FEATURE,feature,port)
76
77#define usbhub_clear_hub_feature(dev,feature) \
78 usb_simple_request(dev,0x20,USB_HUBREQ_CLEAR_FEATURE,feature,0)
79
80
81/* *********************************************************************
82 * Externs
83 ********************************************************************* */
84
85extern int usb_noisy;
86
87/* *********************************************************************
88 * Forward declarations
89 ********************************************************************* */
90
91static int usbhub_attach(usbdev_t *dev,usb_driver_t *drv);
92static int usbhub_detach(usbdev_t *dev);
93static void usbhub_markdetached(usbdev_t *dev);
94
95/* *********************************************************************
96 * Hub-specific data structures
97 ********************************************************************* */
98
99#define UHUB_MAX_DEVICES 8
100
101#define UHUB_FLG_NEEDSCAN 1
102
103typedef struct usbhub_softc_s {
109 unsigned int uhub_flags;
113
115 "USB Hub",
116 usbhub_attach,
117 usbhub_detach
118};
119
121 "Root Hub",
122 usbhub_attach,
123 usbhub_detach
124};
125
126
127/* *********************************************************************
128 * usbhub_ireq_callback(ur)
129 *
130 * this routine is called when the transfer we queued to the
131 * interrupt endpoint on the hub completes. It means that
132 * *some* port on the hub needs attention. The data indicates
133 * which port, but for our purposes we don't really care - if
134 * we get this callback, we'll set a flag and re-probe the bus.
135 *
136 * Input parameters:
137 * ur - usbreq that completed
138 *
139 * Return value:
140 * 0
141 ********************************************************************* */
142
143static int usbhub_ireq_callback(usbreq_t *ur)
144{
145 int idx;
146 usbhub_softc_t *uhub = (ur->ur_dev->ud_private);
147
148 /*
149 * Check to see if the request was cancelled by someone
150 * deleting our endpoint. We also check for "device not responding"
151 * which typically happens when a device is removed.
152 *
153 * XXX this is not correct, it appears that hubs sometimes do
154 * return this error. We'll need to redo the whole way
155 * surprise detach works eventually...
156 */
157
158 if ((ur->ur_status == UR_ERR_CANCELLED) ||
161 return 0;
162 }
163
164 /*
165 * Check to see if any of our ports need attention
166 */
167
168 for (idx = 1; idx <= uhub->uhub_nports; idx++) {
169 if (ur->ur_buffer[0] & (1<<idx)) {
170
171 /*
172 * Mark the hub as needing a scan, and mark the bus as well
173 * so the top-level polling will notice.
174 */
175
178 }
179 }
180
181
182 /*
183 * Do NOT requeue the request here. We will do this
184 * during exploration.
185 */
186
188
189 return 0;
190}
191
192
193/* *********************************************************************
194 * usbhub_get_hub_descriptor(dev,dscr,idx,maxlen)
195 *
196 * Obtain the hub descriptor (special for hubs) from the
197 * device.
198 *
199 * Input parameters:
200 * dev - usb device
201 * dscr - place to put hub descriptor
202 * idx - which hub descriptor to get (usually zero)
203 * maxlen - max # of bytes to return
204 *
205 * Return value:
206 * result status
207 ********************************************************************* */
208
209static int usbhub_get_hub_descriptor(usbdev_t *dev,usb_hub_descr_t *dscr,int idx,int maxlen)
210{
211 int res;
212 uint8_t *respbuf;
213 int len;
214
215 /*
216 * Get the hub descriptor. Get the first 8 bytes first, then get
217 * the rest if there is more.
218 */
219
221 res = usb_std_request(dev,0xA0,
223 0, 0,
224 respbuf,
226 len = ((usb_hub_descr_t *)respbuf)->bDescriptorLength;
227 if (len > USB_HUB_DESCR_SIZE) {
228 usb_dma_free(respbuf);
230 res = usb_std_request(dev,0xA0,
232 0, 0,
233 respbuf,
234 len);
235 }
236 memcpy(dscr, respbuf, (len <= maxlen ? len : maxlen));
237 usb_dma_free(respbuf);
238 return res;
239}
240
241
242/* *********************************************************************
243 * usbhub_get_hub_status(dev,status)
244 *
245 * Obtain the hub status (special for hubs) from the
246 * device.
247 *
248 * Input parameters:
249 * dev - usb device
250 * status - where to put hub status structure
251 *
252 * Return value:
253 * # of bytes returned
254 ********************************************************************* */
255
256#if 0
257static int usbhub_get_hub_status(usbdev_t *dev,usb_hub_status_t *status)
258{
259 return usb_std_request(dev,
260 0xA0,
261 0x00,
262 0,
263 0,
264 (uint8_t *) status,
265 sizeof(usbhub_status_t));
266}
267#endif
268
269
270/* *********************************************************************
271 * usbhub_get_port_status(dev,port,status)
272 *
273 * Obtain the port status for a particular port from
274 * device.
275 *
276 * Input parameters:
277 * dev - usb device
278 * port - 1-based port number
279 * status - where to put port status structure
280 *
281 * Return value:
282 * # of bytes returned
283 ********************************************************************* */
284
285static int usbhub_get_port_status(usbdev_t *dev,int port,usb_port_status_t *status)
286{
287 return usb_std_request(dev,
288 0xA3,
289 0,
290 0,
291 port,
292 (uint8_t *) status,
293 sizeof(usb_port_status_t));
294}
295
296
297/* *********************************************************************
298 * usbhub_queue_intreq(dev,softc)
299 *
300 * Queue the transfer to the interrupt pipe that will catch
301 * the hub's port status changes
302 *
303 * Input parameters:
304 * dev - usb device
305 * softc - hub-specific data
306 *
307 * Return value:
308 * nothing
309 ********************************************************************* */
310
311static void usbhub_queue_intreq(usbdev_t *dev,usbhub_softc_t *softc)
312{
313 usbreq_t *ur;
314
315 ur = usb_make_request(dev,
316 softc->uhub_ipipe,
317 softc->uhub_imsg,softc->uhub_ipipemps,
319
320 ur->ur_callback = usbhub_ireq_callback;
321
323}
324
325
326/* *********************************************************************
327 * usbhub_attach(dev,drv)
328 *
329 * This routine is called when the hub attaches to the system.
330 * We complete initialization for the hub and set things up so
331 * that an explore will happen soon.
332 *
333 * Input parameters:
334 * dev - usb device
335 * drv - driver structure
336 *
337 * Return value:
338 * 0
339 ********************************************************************* */
340
341static int usbhub_attach(usbdev_t *dev,usb_driver_t *drv)
342{
343 usb_device_status_t devstatus;
344 usb_config_descr_t *cfgdscr;
345// usb_interface_descr_t *ifdscr;
346 usb_endpoint_descr_t *epdscr;
347 usbhub_softc_t *softc;
348
349 /*
350 * Remember the driver dispatch.
351 */
352
353 dev->ud_drv = drv;
354
355 softc = KMALLOC(sizeof(usbhub_softc_t),0);
356 memset(softc,0,sizeof(usbhub_softc_t));
357 softc->uhub_imsg = NULL;
358 dev->ud_private = softc;
359
360 /*
361 * Dig out the data from the configuration descriptor
362 * (we got this from the device before attach time)
363 */
364
365 cfgdscr = dev->ud_cfgdescr;
368
369 /*
370 * Get device status (is this really necessary?)
371 */
372
373 usb_get_device_status(dev,&devstatus);
374
375 /*
376 * Set us to configuration index 0
377 */
378
380
381 /*
382 * Get the hub descriptor.
383 */
384
385 usbhub_get_hub_descriptor(dev,&softc->uhub_descr,0,sizeof(usb_hub_descr_t));
386
387 /*
388 * remember stuff from the hub descriptor
389 */
390
391 softc->uhub_nports = softc->uhub_descr.bNumberOfPorts;
392
393 /*
394 * Open the interrupt pipe
395 */
396
397 softc->uhub_ipipemps = GETUSBFIELD(epdscr,wMaxPacketSize);
398 softc->uhub_imsg = usb_dma_alloc(softc->uhub_ipipemps);
399 softc->uhub_ipipe = usb_open_pipe(dev,epdscr);
400
401 /*
402 * Mark the bus and the hub as needing service.
403 */
404
407
408 /*
409 * Okay, that's it. The top-level USB daemon will notice
410 * that the bus needs service and will invoke the exploration code.
411 * This may in turn require additional explores until
412 * everything settles down.
413 */
414
415 return 0;
416}
417
418
419/* *********************************************************************
420 * usbhub_detach(dev)
421 *
422 * Called when a hub is removed from the system - we remove
423 * all subordinate devices.
424 *
425 * Input parameters:
426 * dev - device (hub) that was removed
427 *
428 * Return value:
429 * 0
430 ********************************************************************* */
431
432static int usbhub_detach(usbdev_t *dev)
433{
434 usbhub_softc_t *hub;
435 usbdev_t *deldev;
436 int idx;
437
438 if (!IS_HUB(dev)) return 0; /* should not happen */
439
440 hub = dev->ud_private;
441 for (idx = 0; idx < UHUB_MAX_DEVICES; idx++) {
442 deldev = hub->uhub_devices[idx];
443 if (deldev) {
444 if (usb_noisy > 0)
445 console_log("USB: Removing device attached to bus %d hub %d port %d",
446 dev->ud_bus->ub_num,
447 dev->ud_address,idx+1);
448 if (deldev->ud_drv) {
449 /* close open pipes, cancel reqs */
450 usb_destroy_all_pipes(deldev);
451 /*
452 * Try to process the done queue. This will complete any
453 * requests that made it out of the pipes while we were
454 * doing the stuff above.
455 */
456 usb_poll(deldev->ud_bus);
457 /* Call detach method, clean up device softc */
458 (*(deldev->ud_drv->udrv_detach))(deldev);
459 }
460 else {
461 if (usb_noisy > 0) {
462 console_log("USB: Detached device on bus %d hub %d port %d "
463 "has no methods",
464 dev->ud_bus->ub_num,
465 dev->ud_address,idx+1);
466 }
467 }
468 if (deldev->ud_cfgdescr) usb_dma_free(deldev->ud_cfgdescr);
469 usb_destroy_device(deldev);
470 }
471 }
472
473 if (hub->uhub_imsg != NULL) {
475 }
476 KFREE(hub); /* remove softc */
477
478 return 0;
479}
480
481
482
483/* *********************************************************************
484 * usbhub_map_tree1(dev,level,func,arg)
485 *
486 * This routine is used in recursive device tree exploration.
487 * We call 'func' for each device at this tree, and descend
488 * when we run into hubs
489 *
490 * Input parameters:
491 * dev - current device pointer
492 * level - current nesting level
493 * func - function to call
494 * arg - argument to pass to function
495 *
496 * Return value:
497 * nothing
498 ********************************************************************* */
499
500static void usbhub_map_tree1(usbdev_t *dev,int level,
501 int (*func)(usbdev_t *dev,void *arg),void *arg)
502{
503 usbhub_softc_t *hub;
504 int idx;
505
506 (*func)(dev,arg);
507
508 if (IS_HUB(dev)) {
509 hub = dev->ud_private;
510 for (idx = 0; idx < UHUB_MAX_DEVICES; idx++) {
511 if (hub->uhub_devices[idx]) {
512 usbhub_map_tree1(hub->uhub_devices[idx],level+1,func,arg);
513 }
514 }
515 }
516}
517
518/* *********************************************************************
519 * usbhub_map_tree(bus,func,arg)
520 *
521 * Call a function for each device in the tree
522 *
523 * Input parameters:
524 * bus - bus to scan
525 * func - function to call
526 * arg - argument to pass to function
527 *
528 * Return value:
529 * nothing
530 ********************************************************************* */
531
532void usbhub_map_tree(usbbus_t *bus,int (*func)(usbdev_t *dev,void *arg),void *arg)
533{
534 usbhub_map_tree1(bus->ub_roothub,0,func,arg);
535}
536
537void usbhub_map_from_device(usbdev_t *dev,int (*func)(usbdev_t *dev,void *arg),void *arg)
538{
539 usbhub_map_tree1(dev,0,func,arg);
540}
541
542
543/* *********************************************************************
544 * usbhub_dumpbus1(dev,arg)
545 *
546 * map function to dump devices in the device tree
547 *
548 * Input parameters:
549 * dev - device we're working on
550 * arg - argument from map_tree call
551 *
552 * Return value:
553 * 0
554 ********************************************************************* */
555
556static int usbhub_dumpbus1(usbdev_t *dev,void *arg)
557{
558 uint32_t *verbose = (uint32_t *) arg;
559
560 if ((*verbose & 0x00FF) && (dev->ud_address != (*verbose & 0x00FF))) return 0;
561
562 if (*verbose & 0x100) {
563 printf("============================================================================\n");
564 }
565
567
568 if (*verbose & 0x100) {
571 }
572
573 return 0;
574}
575
576
577/* *********************************************************************
578 * usbhub_dumpbus(bus,verbose)
579 *
580 * Dump information about devices on the USB bus.
581 *
582 * Input parameters:
583 * bus - bus to dump
584 * verbose - nonzero to display more info, like descriptors
585 *
586 * Return value:
587 * nothing
588 ********************************************************************* */
589
591{
592 usbhub_map_tree(bus,usbhub_dumpbus1,&verbose);
593}
594
595
596
597/* *********************************************************************
598 * usbhub_reset_devicee(dev,port,status)
599 *
600 * Reset a device on a hub port. This routine does a
601 * USB_PORT_FEATURE_RESET on the specified port, waits for the
602 * bit to clear, and returns. It is used to get a device into the
603 * DEFAULT state according to the spec.
604 *
605 * Input parameters:
606 * dev - hub device
607 * port - port number(1-based)
608 * status - place to return port_status structure after
609 * reset completes
610 *
611 * Return value:
612 * nothing
613 ********************************************************************* */
614
615static void usbhub_reset_device(usbdev_t *dev,int port,usb_port_status_t *portstatus)
616{
617 if (usb_noisy > 0)
618 console_log("USB: Resetting device on bus %d port %d",dev->ud_bus->ub_num,port);
619#ifndef _CFE_
620 fflush(stdout);
621#endif
622
624
625 usbhub_get_port_status(dev,port,portstatus);
626
627 for (;;) {
628 usbhub_get_port_status(dev,port,portstatus);
629 if ((GETUSBFIELD((portstatus),wPortStatus) & USB_PORT_STATUS_RESET) == 0) break;
630 usb_delay_ms(dev->ud_bus,250);
631 }
632 usb_delay_ms(dev->ud_bus,250);
633
635}
636
637
638
639/* *********************************************************************
640 * usbhub_scan_ports(dev,arg)
641 *
642 * Scan the ports on this hub for new or removed devices.
643 *
644 * Input parameters:
645 * dev - hub device
646 * arg - passed from bus scan main routines
647 *
648 * Return value:
649 * nothing
650 ********************************************************************* */
651
652static void usbhub_scan_ports(usbdev_t *dev,void *arg)
653{
654 uint16_t current;
655 uint16_t changed;
656 usbhub_softc_t *softc;
657 int idx;
658 int res;
659 int len;
660 uint8_t *buf;
661 usbdev_t *newdev;
662 usb_driver_t *newdrv;
663 int addr;
664 usb_port_status_t *portstatus;
665 usb_config_descr_t cfgdescr;
666 unsigned int powerondelay;
667
668 if (!IS_HUB(dev)) return; /* should not happen. */
669
670 portstatus = usb_dma_alloc(sizeof(usb_port_status_t));
671 if (portstatus == NULL) return;
672
673 /*
674 * We know this is a hub. Get the softc back.
675 */
676
677 softc = (usbhub_softc_t *) dev->ud_private;
678
679 powerondelay = ((unsigned int) softc->uhub_descr.bPowerOnToPowerGood)*2 + 20;
680
681 /*
682 * Turn on the power to the ports whose power is not yet on.
683 */
684
685 for (idx = 0; idx < softc->uhub_nports; idx++) {
686
687 usbhub_get_port_status(dev,idx+1,portstatus);
688
689 current = GETUSBFIELD(portstatus,wPortStatus);
690 changed = GETUSBFIELD(portstatus,wPortChange);
691 if (usb_noisy > 1) {
692 printf("BeforePowerup: port %d status %04X changed %04X\n",idx+1,current,changed);
693 }
694
695 if (!(current & USB_PORT_STATUS_POWER)) {
696 if (usb_noisy > 1) console_log("USB: Powering up bus %d port %d",
697 dev->ud_bus->ub_num,idx+1);
699 usb_delay_ms(dev->ud_bus,powerondelay);
700 }
701 }
702
703 /*
704 * Begin exploration at this level.
705 */
706
707 for (idx = 0; idx < softc->uhub_nports; idx++) {
708
709 usbhub_get_port_status(dev,idx+1,portstatus);
710
711 current = GETUSBFIELD(portstatus,wPortStatus);
712 changed = GETUSBFIELD(portstatus,wPortChange);
713
714 if (usb_noisy > 0) {
715 printf("USB: Explore: Bus %d Hub %d port %d status %04X changed %04X\n",
716 dev->ud_bus->ub_num,
717 dev->ud_address,idx+1,current,changed);
718 usb_dbg_dumpportstatus(idx+1,portstatus,1);
719 }
720
721
722// if (changed & USB_PORT_STATUS_RESET) {
723// usbhub_clear_port_feature(dev,idx+1,USB_PORT_FEATURE_C_PORT_RESET);
724// }
725
726 if (changed & USB_PORT_STATUS_ENABLED) {
728 }
729
730 if (changed & USB_PORT_STATUS_CONNECT) {
731 /*
732 * A device was either connected or disconnected.
733 * Clear the status change first.
734 */
735
737
738 if (current & USB_PORT_STATUS_CONNECT) {
739
740 /*
741 * The device has been CONNECTED.
742 */
743
744 console_log("USB: New device connected to bus %d hub %d port %d",
745 dev->ud_bus->ub_num,
746 dev->ud_address,idx+1);
747
748 /*
749 * Reset the device. Reuse our old port status structure
750 * so we get the latest status. Some devices do not report
751 * lowspeed until they are reset.
752 */
753
754 usbhub_reset_device(dev,idx+1,portstatus);
755 current = GETUSBFIELD(portstatus,wPortStatus);
756 changed = GETUSBFIELD(portstatus,wPortChange);
757
758 /*
759 * Create a device for this port.
760 */
761
762 newdev = usb_create_device(dev->ud_bus,(current & USB_PORT_STATUS_LOWSPD) ? 1 : 0);
763
764 /*
765 * Get the device descriptor.
766 */
767
768 res = usb_get_device_descriptor(newdev,&newdev->ud_devdescr,TRUE);
769
770 if (usb_noisy > 1) usb_dbg_dumpdescriptors(newdev,(uint8_t *) &(newdev->ud_devdescr),8);
771
772 /*
773 * Set up the max packet size for the control endpoint,
774 * then get the rest of the descriptor.
775 */
776
778 res = usb_get_device_descriptor(newdev,&newdev->ud_devdescr,FALSE);
779
780 /*
781 * Obtain a new address and set the address of the
782 * root hub to this address.
783 */
784
785 addr = usb_new_address(newdev->ud_bus);
786 res = usb_set_address(newdev,addr);
787
788 /*
789 * Get the configuration descriptor and all the
790 * associated interface and endpoint descriptors.
791 */
792
793 res = usb_get_config_descriptor(newdev,&cfgdescr,0,
794 sizeof(usb_config_descr_t));
795 if (res != sizeof(usb_config_descr_t)) {
796 printf("[a] usb_get_config_descriptor returns %d\n",res);
797 }
798
799 len = GETUSBFIELD(&cfgdescr,wTotalLength);
800 buf = usb_dma_alloc(len);
801
802 res = usb_get_config_descriptor(newdev,(usb_config_descr_t *)buf,0,len);
803 if (res != len) {
804 printf("[b] usb_get_config_descriptor returns %d\n",res);
805 }
806
807 newdev->ud_cfgdescr = (usb_config_descr_t *) buf;
808
809 if (usb_noisy > 1) usb_dbg_dumpdescriptors(newdev,buf,len);
810
811 /*
812 * Point the hub at the devices it owns
813 */
814
815 softc->uhub_devices[idx] = newdev;
816
817 /*
818 * Find the driver for this. It had better be the hub
819 * driver.
820 */
821
822 newdrv = usb_find_driver(newdev);
823
824 /*
825 * Call the attach method.
826 */
827
828 if (newdrv) {
829 newdev->ud_drv = newdrv; /* remember driver dispatch in device */
830 (*(newdrv->udrv_attach))(newdev,newdrv);
831 }
832 }
833
834 else {
835
836 /*
837 * The device has been DISCONNECTED.
838 */
839
840 console_log("USB: Device disconnected from bus %d hub %d port %d",
841 dev->ud_bus->ub_num,
842 dev->ud_address,idx+1);
843
844 /*
845 * Recover pointer to device below hub and clear
846 * this pointer.
847 */
848
849 newdev = softc->uhub_devices[idx]; /* Get device pointer */
850
851 if (newdev) usbhub_markdetached(newdev); /* mark device and all subordinate
852 devices as "removing" */
853
854 softc->uhub_devices[idx] = NULL; /* remove device from hub */
855
856 /*
857 * Deassign the USB device's address and then
858 * call detach method to free resources. Devices that
859 * do not have drivers will not have any methods.
860 */
861
862 if (newdev) {
863 if (newdev->ud_drv) {
864 /* close open pipes, cancel reqs */
865 usb_destroy_all_pipes(newdev);
866 /*
867 * Try to process the done queue. This will complete any
868 * requests that made it out of the pipes while we were
869 * doing the stuff above.
870 */
871 usb_poll(newdev->ud_bus);
872 /* Call detach method, clean up device softc */
873 (*(newdev->ud_drv->udrv_detach))(newdev);
874 }
875 else {
876 if (usb_noisy > 0) {
877 console_log("USB: Detached device on bus %d hub %d port %d "
878 "has no methods",
879 dev->ud_bus->ub_num,
880 dev->ud_address,idx+1);
881 }
882 }
883
884 if (newdev->ud_cfgdescr) usb_dma_free(newdev->ud_cfgdescr);
885
886 usb_destroy_device(newdev);
887 }
888
889 }
890 }
891
892 }
893
894 usb_dma_free(portstatus);
895
896 /*
897 * Queue up a request for the interrupt pipe. This will catch further
898 * changes at this port.
899 */
900
901 usbhub_queue_intreq(dev,softc);
902
903}
904
905/* *********************************************************************
906 * usbhub_markdetached(dev)
907 *
908 * Mark a device and all devices below it as "removing" so we
909 * will change the status of pending requests to cancelled.
910 *
911 * Input parameters:
912 * dev - device in the tree to start at
913 *
914 * Return value:
915 * nothing
916 ********************************************************************* */
917
918static int usbhub_markdetached1(usbdev_t *dev,void *arg)
919{
921 return 0;
922}
923
924static void usbhub_markdetached(usbdev_t *dev)
925{
926 usbhub_map_from_device(dev,usbhub_markdetached1,NULL);
927}
928
929/* *********************************************************************
930 * usbhub_scan1(dev,arg)
931 *
932 * Scan one device at this level, or descend if we run into a hub
933 * This is part of the device discovery code.
934 *
935 * Input parameters:
936 * dev - current device, maybe a hub
937 * arg - passed from main scan routine
938 *
939 * Return value:
940 * 0
941 ********************************************************************* */
942
943
944static int usbhub_scan1(usbdev_t *dev,void *arg)
945{
946 usbhub_softc_t *hub;
947
948 /*
949 * If the device is not a hub, we've reached the leaves of the
950 * tree.
951 */
952
953 if (!IS_HUB(dev)) return 0;
954
955 /*
956 * Otherwise, scan the ports on this hub.
957 */
958
959 hub = dev->ud_private;
960
961 if (hub->uhub_flags & UHUB_FLG_NEEDSCAN) {
962 hub->uhub_flags &= ~UHUB_FLG_NEEDSCAN;
963 usbhub_scan_ports(dev,arg);
964 }
965
966 return 0;
967}
968
969/* *********************************************************************
970 * usb_scan(bus)
971 *
972 * Scan the bus looking for new or removed devices
973 *
974 * Input parameters:
975 * bus - bus to scan
976 *
977 * Return value:
978 * nothing
979 ********************************************************************* */
980
982{
983 /*
984 * Call our tree walker with the scan function.
985 */
986
987 usbhub_map_tree(bus,usbhub_scan1,NULL);
988}
989
990
991
#define console_log(fmt, x...)
Definition: cfe.h:18
#define NULL
Definition: def.h:47
u32 status
Definition: ehci_defs.h:15
#define KMALLOC(size, align)
Definition: lib_malloc.h:92
#define KFREE(ptr)
Definition: lib_malloc.h:93
u32 uint32_t
Definition: libfdt_env.h:11
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 bMaxPacketSize0
Definition: usbchap9.h:183
int(* udrv_attach)(usbdev_t *, usb_driver_t *)
Definition: usbd.h:292
int(* udrv_detach)(usbdev_t *)
Definition: usbd.h:293
uint8_t bNumberOfPorts
Definition: usbchap9.h:291
uint8_t bPowerOnToPowerGood
Definition: usbchap9.h:294
Definition: usbd.h:92
usbdev_t * ub_roothub
Definition: usbd.h:96
int ub_num
Definition: usbd.h:99
unsigned int ub_flags
Definition: usbd.h:98
Definition: usbd.h:141
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
void * ud_private
Definition: usbd.h:148
usb_device_descr_t ud_devdescr
Definition: usbd.h:149
usb_driver_t * ud_drv
Definition: usbd.h:142
usb_hub_descr_t uhub_descr
Definition: usbhub.c:104
usbdev_t * uhub_devices[UHUB_MAX_DEVICES]
Definition: usbhub.c:111
usb_hub_status_t uhub_status
Definition: usbhub.c:105
unsigned int uhub_flags
Definition: usbhub.c:109
int uhub_ipipemps
Definition: usbhub.c:107
uint8_t * uhub_imsg
Definition: usbhub.c:110
int uhub_nports
Definition: usbhub.c:108
int uhub_ipipe
Definition: usbhub.c:106
Definition: usbd.h:171
int(* ur_callback)(struct usbreq_s *req)
Definition: usbd.h:196
int ur_status
Definition: usbd.h:188
uint8_t * ur_buffer
Definition: usbd.h:185
usbdev_t * ur_dev
Definition: usbd.h:178
#define GETUSBFIELD(s, f)
Definition: usbchap9.h:347
#define USB_PORT_FEATURE_C_PORT_CONNECTION
Definition: usbchap9.h:340
#define USB_PORT_STATUS_CONNECT
Definition: usbchap9.h:309
#define USB_PORT_STATUS_ENABLED
Definition: usbchap9.h:310
#define USB_ENDPOINT_DESCRIPTOR_TYPE
Definition: usbchap9.h:66
#define USB_PORT_STATUS_POWER
Definition: usbchap9.h:314
#define USB_HUB_DESCR_SIZE
Definition: usbchap9.h:287
#define USB_PORT_STATUS_RESET
Definition: usbchap9.h:313
#define USB_PORT_FEATURE_C_PORT_RESET
Definition: usbchap9.h:344
#define USB_PORT_FEATURE_RESET
Definition: usbchap9.h:337
#define USB_PORT_STATUS_LOWSPD
Definition: usbchap9.h:315
#define USB_PORT_FEATURE_POWER
Definition: usbchap9.h:338
#define USB_INTERFACE_DESCRIPTOR_TYPE
Definition: usbchap9.h:65
#define USB_PORT_FEATURE_C_PORT_ENABLE
Definition: usbchap9.h:341
#define USB_HUBREQ_GET_DESCRIPTOR
Definition: usbchap9.h:327
void * usb_find_cfg_descr(usbdev_t *dev, int dtype, int idx)
Definition: usbd.c:1237
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
usbreq_t * usb_make_request(usbdev_t *dev, int epaddr, uint8_t *buf, int length, int flags)
Definition: usbd.c:353
void usb_free_request(usbreq_t *ur)
Definition: usbd.c:457
int usb_get_device_status(usbdev_t *dev, usb_device_status_t *status)
Definition: usbd.c:1079
void usb_poll(usbbus_t *bus)
Definition: usbd.c:392
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_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_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
void usb_dbg_showdevice(usbdev_t *dev)
Definition: usbdebug.c:314
void usb_dbg_dumpdescriptors(usbdev_t *dev, uint8_t *ptr, int len)
Definition: usbdebug.c:110
#define UR_ERR_CANCELLED
Definition: usbd.h:84
void usb_dbg_dumpportstatus(int port, usb_port_status_t *portstatus, int level)
Definition: usbdebug.c:64
#define UR_FLAG_IN
Definition: usbd.h:164
#define UR_FLAG_SHORTOK
Definition: usbd.h:168
usb_driver_t * usb_find_driver(usbdev_t *dev)
Definition: usbdevs.c:158
#define UD_FLAG_REMOVING
Definition: usbd.h:136
#define UB_FLG_NEEDSCAN
Definition: usbd.h:102
#define IS_HUB(dev)
Definition: usbd.h:311
#define UR_ERR_DEVICENOTRESPONDING
Definition: usbd.h:76
void usb_dbg_dumpcfgdescr(usbdev_t *dev, unsigned int index)
Definition: usbdebug.c:266
usbbus_t * bus
Definition: usbhack.c:153
#define FALSE
Definition: usbhack.h:58
usb_driver_t usbhub_driver
Definition: usbhub.c:114
int usb_noisy
Definition: usbd.c:68
usb_driver_t usbroothub_driver
Definition: usbhub.c:120
struct usbhub_softc_s usbhub_softc_t
#define usb_dma_free(p)
Definition: usbhub.c:62
#define usbhub_clear_port_feature(dev, port, feature)
Definition: usbhub.c:74
#define UHUB_FLG_NEEDSCAN
Definition: usbhub.c:101
#define usb_dma_alloc(n)
Definition: usbhub.c:61
void usbhub_map_tree(usbbus_t *bus, int(*func)(usbdev_t *dev, void *arg), void *arg)
Definition: usbhub.c:532
#define UHUB_MAX_DEVICES
Definition: usbhub.c:99
void usbhub_map_from_device(usbdev_t *dev, int(*func)(usbdev_t *dev, void *arg), void *arg)
Definition: usbhub.c:537
void usb_scan(usbbus_t *bus)
Definition: usbhub.c:981
void usbhub_dumpbus(usbbus_t *bus, uint32_t verbose)
Definition: usbhub.c:590
#define usbhub_set_port_feature(dev, port, feature)
Definition: usbhub.c:68
#define TRUE
True.
Definition: xetypes.h:52