aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/usb-bus.c9
-rw-r--r--hw/usb.c13
-rw-r--r--hw/usb.h10
3 files changed, 32 insertions, 0 deletions
diff --git a/hw/usb-bus.c b/hw/usb-bus.c
index b753834584..5c05ed5806 100644
--- a/hw/usb-bus.c
+++ b/hw/usb-bus.c
@@ -74,6 +74,15 @@ static int usb_device_init(USBDevice *dev)
return 0;
}
+USBDevice *usb_device_find_device(USBDevice *dev, uint8_t addr)
+{
+ USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
+ if (klass->find_device) {
+ return klass->find_device(dev, addr);
+ }
+ return NULL;
+}
+
static void usb_device_handle_destroy(USBDevice *dev)
{
USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
diff --git a/hw/usb.c b/hw/usb.c
index 0c261644ec..bacdc81bfc 100644
--- a/hw/usb.c
+++ b/hw/usb.c
@@ -295,6 +295,19 @@ int set_usb_string(uint8_t *buf, const char *str)
return q - buf;
}
+USBDevice *usb_find_device(USBPort *port, uint8_t addr)
+{
+ USBDevice *dev = port->dev;
+
+ if (dev == NULL || !dev->attached || dev->state != USB_STATE_DEFAULT) {
+ return NULL;
+ }
+ if (dev->addr == addr) {
+ return dev;
+ }
+ return usb_device_find_device(dev, addr);
+}
+
/* Hand over a packet to a device for processing. Return value
USB_RET_ASYNC indicates the processing isn't finished yet, the
driver will call usb_packet_complete() when done processing it. */
diff --git a/hw/usb.h b/hw/usb.h
index 61271768bc..1beb4b32a9 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -229,6 +229,12 @@ typedef struct USBDeviceClass {
int (*init)(USBDevice *dev);
/*
+ * Walk (enabled) downstream ports, check for a matching device.
+ * Only hubs implement this.
+ */
+ USBDevice *(*find_device)(USBDevice *dev, uint8_t addr);
+
+ /*
* Process USB packet.
* Called by the HC (Host Controller).
*
@@ -332,6 +338,8 @@ void usb_packet_copy(USBPacket *p, void *ptr, size_t bytes);
void usb_packet_skip(USBPacket *p, size_t bytes);
void usb_packet_cleanup(USBPacket *p);
+USBDevice *usb_find_device(USBPort *port, uint8_t addr);
+
int usb_handle_packet(USBDevice *dev, USBPacket *p);
void usb_packet_complete(USBDevice *dev, USBPacket *p);
void usb_cancel_packet(USBPacket * p);
@@ -446,6 +454,8 @@ extern const VMStateDescription vmstate_usb_device;
.offset = vmstate_offset_value(_state, _field, USBDevice), \
}
+USBDevice *usb_device_find_device(USBDevice *dev, uint8_t addr);
+
int usb_device_handle_packet(USBDevice *dev, USBPacket *p);
void usb_device_cancel_packet(USBDevice *dev, USBPacket *p);