aboutsummaryrefslogtreecommitdiff
path: root/payloads/libpayload/drivers/usb/usb.c
diff options
context:
space:
mode:
Diffstat (limited to 'payloads/libpayload/drivers/usb/usb.c')
-rw-r--r--payloads/libpayload/drivers/usb/usb.c36
1 files changed, 30 insertions, 6 deletions
diff --git a/payloads/libpayload/drivers/usb/usb.c b/payloads/libpayload/drivers/usb/usb.c
index 6dafd076c4..54a5935c1a 100644
--- a/payloads/libpayload/drivers/usb/usb.c
+++ b/payloads/libpayload/drivers/usb/usb.c
@@ -242,13 +242,11 @@ get_free_address (hci_t *controller)
return -1; // no free address
}
-static int
-set_address (hci_t *controller, int speed, int hubport, int hubaddr)
+int
+generic_set_address (hci_t *controller, int speed, int hubport, int hubaddr)
{
int adr = get_free_address (controller); // address to set
dev_req_t dr;
- configuration_descriptor_t *cd;
- device_descriptor_t *dd;
memset (&dr, 0, sizeof (dr));
dr.data_dir = host_to_device;
@@ -273,11 +271,29 @@ set_address (hci_t *controller, int speed, int hubport, int hubaddr)
dev->endpoints[0].direction = SETUP;
mdelay (50);
if (dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0)) {
- usb_debug ("set_address failed\n");
return -1;
}
mdelay (50);
+
+ return adr;
+}
+
+static int
+set_address (hci_t *controller, int speed, int hubport, int hubaddr)
+{
+ int adr = controller->set_address(controller, speed, hubport, hubaddr);
+ if (adr < 0 || !controller->devices[adr]) {
+ usb_debug ("set_address failed\n");
+ return -1;
+ }
+ configuration_descriptor_t *cd;
+ device_descriptor_t *dd;
+
+ usbdev_t *dev = controller->devices[adr];
dev->address = adr;
+ dev->hub = hubaddr;
+ dev->port = hubport;
+ dev->speed = speed;
dev->descriptor = get_descriptor (dev, gen_bmRequestType
(device_to_host, standard_type, dev_recp), 1, 0, 0);
dd = (device_descriptor_t *) dev->descriptor;
@@ -298,7 +314,6 @@ set_address (hci_t *controller, int speed, int hubport, int hubaddr)
dev->configuration = get_descriptor (dev, gen_bmRequestType
(device_to_host, standard_type, dev_recp), 2, 0, 0);
cd = (configuration_descriptor_t *) dev->configuration;
- set_configuration (dev);
interface_descriptor_t *interface =
(interface_descriptor_t *) (((char *) cd) + cd->bLength);
{
@@ -366,6 +381,13 @@ set_address (hci_t *controller, int speed, int hubport, int hubaddr)
}
}
+ if (controller->finish_device_config &&
+ controller->finish_device_config(dev))
+ return adr; /* Device isn't configured correctly,
+ only control transfers may work. */
+
+ set_configuration(dev);
+
int class = dd->bDeviceClass;
if (class == 0)
class = interface->bInterfaceClass;
@@ -475,6 +497,8 @@ usb_detach_device(hci_t *controller, int devno)
controller->devices[devno]->destroy (controller->devices[devno]);
free(controller->devices[devno]);
controller->devices[devno] = NULL;
+ if (controller->destroy_device)
+ controller->destroy_device(controller, devno);
}
}