mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'kraxel/usb.14.pull' into staging
This commit is contained in:
@@ -193,6 +193,7 @@ hw-obj-$(CONFIG_PCSPK) += pcspk.o
|
||||
hw-obj-$(CONFIG_PCKBD) += pckbd.o
|
||||
hw-obj-$(CONFIG_USB_UHCI) += usb-uhci.o
|
||||
hw-obj-$(CONFIG_USB_OHCI) += usb-ohci.o
|
||||
hw-obj-$(CONFIG_USB_EHCI) += usb-ehci.o
|
||||
hw-obj-$(CONFIG_FDC) += fdc.o
|
||||
hw-obj-$(CONFIG_ACPI) += acpi.o acpi_piix4.o
|
||||
hw-obj-$(CONFIG_APM) += pm_smbus.o apm.o
|
||||
|
||||
@@ -3,6 +3,7 @@ CONFIG_VIRTIO_PCI=y
|
||||
CONFIG_VIRTIO=y
|
||||
CONFIG_USB_UHCI=y
|
||||
CONFIG_USB_OHCI=y
|
||||
CONFIG_USB_EHCI=y
|
||||
CONFIG_NE2000_PCI=y
|
||||
CONFIG_EEPRO100_PCI=y
|
||||
CONFIG_PCNET_PCI=y
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
|
||||
USB 2.0 Quick Start
|
||||
===================
|
||||
|
||||
The QEMU EHCI Adapter does *not* support companion controllers. That
|
||||
implies there are two completely separate USB busses: One USB 1.1 bus
|
||||
driven by the UHCI controller and one USB 2.0 bus driven by the EHCI
|
||||
controller. Devices must be attached to the correct controller
|
||||
manually.
|
||||
|
||||
The '-usb' switch will make qemu create the UHCI controller as part of
|
||||
the PIIX3 chipset. The USB 1.1 bus will carry the name "usb.0".
|
||||
|
||||
You can use the standard -device switch to add a EHCI controller to
|
||||
your virtual machine. It is strongly recommended to specify an ID for
|
||||
the controller so the USB 2.0 bus gets a individual name, for example
|
||||
'-device usb-ehci,id=ehci". This will give you a USB 2.0 bus named
|
||||
"ehci.0".
|
||||
|
||||
I strongly recomment to also use -device to attach usb devices because
|
||||
you can specify the bus they should be attached to this way. Here is
|
||||
a complete example:
|
||||
|
||||
qemu -M pc ${otheroptions} \
|
||||
-drive if=none,id=usbstick,file=/path/to/image \
|
||||
-usb \
|
||||
-device usb-ehci,id=ehci \
|
||||
-device usb-tablet,bus=usb.0 \
|
||||
-device usb-storage,bus=ehci.0,drive=usbstick
|
||||
|
||||
This attaches a usb tablet to the UHCI adapter and a usb mass storage
|
||||
device to the EHCI adapter.
|
||||
|
||||
enjoy,
|
||||
Gerd
|
||||
|
||||
--
|
||||
Gerd Hoffmann <kraxel@redhat.com>
|
||||
+3
-3
@@ -323,7 +323,7 @@ static void bt_hid_control_transaction(struct bt_hid_device_s *s,
|
||||
break;
|
||||
}
|
||||
s->proto = parameter;
|
||||
s->usbdev->info->handle_control(s->usbdev, SET_PROTOCOL, s->proto, 0, 0,
|
||||
s->usbdev->info->handle_control(s->usbdev, NULL, SET_PROTOCOL, s->proto, 0, 0,
|
||||
NULL);
|
||||
ret = BT_HS_SUCCESSFUL;
|
||||
break;
|
||||
@@ -333,7 +333,7 @@ static void bt_hid_control_transaction(struct bt_hid_device_s *s,
|
||||
ret = BT_HS_ERR_INVALID_PARAMETER;
|
||||
break;
|
||||
}
|
||||
s->usbdev->info->handle_control(s->usbdev, GET_IDLE, 0, 0, 1,
|
||||
s->usbdev->info->handle_control(s->usbdev, NULL, GET_IDLE, 0, 0, 1,
|
||||
s->control->sdu_out(s->control, 1));
|
||||
s->control->sdu_submit(s->control);
|
||||
break;
|
||||
@@ -346,7 +346,7 @@ static void bt_hid_control_transaction(struct bt_hid_device_s *s,
|
||||
|
||||
/* We don't need to know about the Idle Rate here really,
|
||||
* so just pass it on to the device. */
|
||||
ret = s->usbdev->info->handle_control(s->usbdev,
|
||||
ret = s->usbdev->info->handle_control(s->usbdev, NULL,
|
||||
SET_IDLE, data[1], 0, 0, NULL) ?
|
||||
BT_HS_SUCCESSFUL : BT_HS_ERR_INVALID_PARAMETER;
|
||||
/* XXX: Does this generate a handshake? */
|
||||
|
||||
@@ -100,6 +100,7 @@
|
||||
#define PCI_VENDOR_ID_INTEL 0x8086
|
||||
#define PCI_DEVICE_ID_INTEL_82441 0x1237
|
||||
#define PCI_DEVICE_ID_INTEL_82801AA_5 0x2415
|
||||
#define PCI_DEVICE_ID_INTEL_82801D 0x24CD
|
||||
#define PCI_DEVICE_ID_INTEL_ESB_9 0x25ab
|
||||
#define PCI_DEVICE_ID_INTEL_82371SB_0 0x7000
|
||||
#define PCI_DEVICE_ID_INTEL_82371SB_1 0x7010
|
||||
|
||||
+3
-3
@@ -372,13 +372,13 @@ static void usb_bt_handle_reset(USBDevice *dev)
|
||||
s->altsetting = 0;
|
||||
}
|
||||
|
||||
static int usb_bt_handle_control(USBDevice *dev, int request, int value,
|
||||
int index, int length, uint8_t *data)
|
||||
static int usb_bt_handle_control(USBDevice *dev, USBPacket *p,
|
||||
int request, int value, int index, int length, uint8_t *data)
|
||||
{
|
||||
struct USBBtState *s = (struct USBBtState *) dev->opaque;
|
||||
int ret;
|
||||
|
||||
ret = usb_desc_handle_control(dev, request, value, index, length, data);
|
||||
ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
|
||||
if (ret >= 0) {
|
||||
switch (request) {
|
||||
case DeviceRequest | USB_REQ_GET_CONFIGURATION:
|
||||
|
||||
+2
-2
@@ -602,8 +602,8 @@ static void ccid_handle_reset(USBDevice *dev)
|
||||
ccid_reset(s);
|
||||
}
|
||||
|
||||
static int ccid_handle_control(USBDevice *dev, int request, int value,
|
||||
int index, int length, uint8_t *data)
|
||||
static int ccid_handle_control(USBDevice *dev, USBPacket *p, int request,
|
||||
int value, int index, int length, uint8_t *data)
|
||||
{
|
||||
USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev);
|
||||
int ret = 0;
|
||||
|
||||
+51
-5
@@ -76,7 +76,7 @@ int usb_desc_config(const USBDescConfig *conf, uint8_t *dest, size_t len)
|
||||
{
|
||||
uint8_t bLength = 0x09;
|
||||
uint16_t wTotalLength = 0;
|
||||
int i, rc, count;
|
||||
int i, rc;
|
||||
|
||||
if (len < bLength) {
|
||||
return -1;
|
||||
@@ -91,8 +91,19 @@ int usb_desc_config(const USBDescConfig *conf, uint8_t *dest, size_t len)
|
||||
dest[0x08] = conf->bMaxPower;
|
||||
wTotalLength += bLength;
|
||||
|
||||
count = conf->nif ? conf->nif : conf->bNumInterfaces;
|
||||
for (i = 0; i < count; i++) {
|
||||
/* handle grouped interfaces if any*/
|
||||
for (i = 0; i < conf->nif_groups; i++) {
|
||||
rc = usb_desc_iface_group(&(conf->if_groups[i]),
|
||||
dest + wTotalLength,
|
||||
len - wTotalLength);
|
||||
if (rc < 0) {
|
||||
return rc;
|
||||
}
|
||||
wTotalLength += rc;
|
||||
}
|
||||
|
||||
/* handle normal (ungrouped / no IAD) interfaces if any */
|
||||
for (i = 0; i < conf->nif; i++) {
|
||||
rc = usb_desc_iface(conf->ifs + i, dest + wTotalLength, len - wTotalLength);
|
||||
if (rc < 0) {
|
||||
return rc;
|
||||
@@ -105,6 +116,41 @@ int usb_desc_config(const USBDescConfig *conf, uint8_t *dest, size_t len)
|
||||
return wTotalLength;
|
||||
}
|
||||
|
||||
int usb_desc_iface_group(const USBDescIfaceAssoc *iad, uint8_t *dest,
|
||||
size_t len)
|
||||
{
|
||||
int pos = 0;
|
||||
int i = 0;
|
||||
|
||||
/* handle interface association descriptor */
|
||||
uint8_t bLength = 0x08;
|
||||
|
||||
if (len < bLength) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
dest[0x00] = bLength;
|
||||
dest[0x01] = USB_DT_INTERFACE_ASSOC;
|
||||
dest[0x02] = iad->bFirstInterface;
|
||||
dest[0x03] = iad->bInterfaceCount;
|
||||
dest[0x04] = iad->bFunctionClass;
|
||||
dest[0x05] = iad->bFunctionSubClass;
|
||||
dest[0x06] = iad->bFunctionProtocol;
|
||||
dest[0x07] = iad->iFunction;
|
||||
pos += bLength;
|
||||
|
||||
/* handle associated interfaces in this group */
|
||||
for (i = 0; i < iad->nif; i++) {
|
||||
int rc = usb_desc_iface(&(iad->ifs[i]), dest + pos, len - pos);
|
||||
if (rc < 0) {
|
||||
return rc;
|
||||
}
|
||||
pos += rc;
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
int usb_desc_iface(const USBDescIface *iface, uint8_t *dest, size_t len)
|
||||
{
|
||||
uint8_t bLength = 0x09;
|
||||
@@ -344,8 +390,8 @@ int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usb_desc_handle_control(USBDevice *dev, int request, int value,
|
||||
int index, int length, uint8_t *data)
|
||||
int usb_desc_handle_control(USBDevice *dev, USBPacket *p,
|
||||
int request, int value, int index, int length, uint8_t *data)
|
||||
{
|
||||
const USBDesc *desc = dev->info->usb_desc;
|
||||
int i, ret = -1;
|
||||
|
||||
+22
-2
@@ -30,6 +30,24 @@ struct USBDescConfig {
|
||||
uint8_t bmAttributes;
|
||||
uint8_t bMaxPower;
|
||||
|
||||
/* grouped interfaces */
|
||||
uint8_t nif_groups;
|
||||
const USBDescIfaceAssoc *if_groups;
|
||||
|
||||
/* "normal" interfaces */
|
||||
uint8_t nif;
|
||||
const USBDescIface *ifs;
|
||||
};
|
||||
|
||||
/* conceptually an Interface Association Descriptor, and releated interfaces */
|
||||
struct USBDescIfaceAssoc {
|
||||
uint8_t bFirstInterface;
|
||||
uint8_t bInterfaceCount;
|
||||
uint8_t bFunctionClass;
|
||||
uint8_t bFunctionSubClass;
|
||||
uint8_t bFunctionProtocol;
|
||||
uint8_t iFunction;
|
||||
|
||||
uint8_t nif;
|
||||
const USBDescIface *ifs;
|
||||
};
|
||||
@@ -75,6 +93,8 @@ int usb_desc_device(const USBDescID *id, const USBDescDevice *dev,
|
||||
int usb_desc_device_qualifier(const USBDescDevice *dev,
|
||||
uint8_t *dest, size_t len);
|
||||
int usb_desc_config(const USBDescConfig *conf, uint8_t *dest, size_t len);
|
||||
int usb_desc_iface_group(const USBDescIfaceAssoc *iad, uint8_t *dest,
|
||||
size_t len);
|
||||
int usb_desc_iface(const USBDescIface *iface, uint8_t *dest, size_t len);
|
||||
int usb_desc_endpoint(const USBDescEndpoint *ep, uint8_t *dest, size_t len);
|
||||
int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len);
|
||||
@@ -86,7 +106,7 @@ void usb_desc_set_string(USBDevice *dev, uint8_t index, const char *str);
|
||||
const char *usb_desc_get_string(USBDevice *dev, uint8_t index);
|
||||
int usb_desc_string(USBDevice *dev, int index, uint8_t *dest, size_t len);
|
||||
int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len);
|
||||
int usb_desc_handle_control(USBDevice *dev, int request, int value,
|
||||
int index, int length, uint8_t *data);
|
||||
int usb_desc_handle_control(USBDevice *dev, USBPacket *p,
|
||||
int request, int value, int index, int length, uint8_t *data);
|
||||
|
||||
#endif /* QEMU_HW_USB_DESC_H */
|
||||
|
||||
+2037
File diff suppressed because it is too large
Load Diff
+6
-3
@@ -211,6 +211,7 @@ static const USBDescDevice desc_device_mouse = {
|
||||
.iConfiguration = STR_CONFIG_MOUSE,
|
||||
.bmAttributes = 0xa0,
|
||||
.bMaxPower = 50,
|
||||
.nif = 1,
|
||||
.ifs = &desc_iface_mouse,
|
||||
},
|
||||
},
|
||||
@@ -227,6 +228,7 @@ static const USBDescDevice desc_device_tablet = {
|
||||
.iConfiguration = STR_CONFIG_TABLET,
|
||||
.bmAttributes = 0xa0,
|
||||
.bMaxPower = 50,
|
||||
.nif = 1,
|
||||
.ifs = &desc_iface_tablet,
|
||||
},
|
||||
},
|
||||
@@ -243,6 +245,7 @@ static const USBDescDevice desc_device_keyboard = {
|
||||
.iConfiguration = STR_CONFIG_KEYBOARD,
|
||||
.bmAttributes = 0xa0,
|
||||
.bMaxPower = 50,
|
||||
.nif = 1,
|
||||
.ifs = &desc_iface_keyboard,
|
||||
},
|
||||
},
|
||||
@@ -724,13 +727,13 @@ static void usb_hid_set_next_idle(USBHIDState *s, int64_t curtime)
|
||||
s->next_idle_clock = curtime + (get_ticks_per_sec() * s->idle * 4) / 1000;
|
||||
}
|
||||
|
||||
static int usb_hid_handle_control(USBDevice *dev, int request, int value,
|
||||
int index, int length, uint8_t *data)
|
||||
static int usb_hid_handle_control(USBDevice *dev, USBPacket *p,
|
||||
int request, int value, int index, int length, uint8_t *data)
|
||||
{
|
||||
USBHIDState *s = (USBHIDState *)dev;
|
||||
int ret;
|
||||
|
||||
ret = usb_desc_handle_control(dev, request, value, index, length, data);
|
||||
ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
|
||||
if (ret >= 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
+5
-4
@@ -119,6 +119,7 @@ static const USBDescDevice desc_device_hub = {
|
||||
.bNumInterfaces = 1,
|
||||
.bConfigurationValue = 1,
|
||||
.bmAttributes = 0xe0,
|
||||
.nif = 1,
|
||||
.ifs = &desc_iface_hub,
|
||||
},
|
||||
},
|
||||
@@ -284,13 +285,13 @@ static void usb_hub_handle_reset(USBDevice *dev)
|
||||
/* XXX: do it */
|
||||
}
|
||||
|
||||
static int usb_hub_handle_control(USBDevice *dev, int request, int value,
|
||||
int index, int length, uint8_t *data)
|
||||
static int usb_hub_handle_control(USBDevice *dev, USBPacket *p,
|
||||
int request, int value, int index, int length, uint8_t *data)
|
||||
{
|
||||
USBHubState *s = (USBHubState *)dev;
|
||||
int ret;
|
||||
|
||||
ret = usb_desc_handle_control(dev, request, value, index, length, data);
|
||||
ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
|
||||
if (ret >= 0) {
|
||||
return ret;
|
||||
}
|
||||
@@ -494,7 +495,7 @@ static int usb_hub_broadcast_packet(USBHubState *s, USBPacket *p)
|
||||
port = &s->ports[i];
|
||||
dev = port->port.dev;
|
||||
if (dev && (port->wPortStatus & PORT_STAT_ENABLE)) {
|
||||
ret = dev->info->handle_packet(dev, p);
|
||||
ret = usb_handle_packet(dev, p);
|
||||
if (ret != USB_RET_NODEV) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
+9
-9
@@ -119,6 +119,7 @@ static const USBDescDevice desc_device_full = {
|
||||
.bConfigurationValue = 1,
|
||||
.iConfiguration = STR_CONFIG_FULL,
|
||||
.bmAttributes = 0xc0,
|
||||
.nif = 1,
|
||||
.ifs = &desc_iface_full,
|
||||
},
|
||||
},
|
||||
@@ -153,6 +154,7 @@ static const USBDescDevice desc_device_high = {
|
||||
.bConfigurationValue = 1,
|
||||
.iConfiguration = STR_CONFIG_HIGH,
|
||||
.bmAttributes = 0xc0,
|
||||
.nif = 1,
|
||||
.ifs = &desc_iface_high,
|
||||
},
|
||||
},
|
||||
@@ -251,7 +253,7 @@ static void usb_msd_command_complete(SCSIBus *bus, int reason, uint32_t tag,
|
||||
s->scsi_buf = s->scsi_dev->info->get_buf(s->scsi_dev, tag);
|
||||
if (p) {
|
||||
usb_msd_copy_data(s);
|
||||
if (s->usb_len == 0) {
|
||||
if (s->packet && s->usb_len == 0) {
|
||||
/* Set s->packet to NULL before calling usb_packet_complete
|
||||
because another request may be issued before
|
||||
usb_packet_complete returns. */
|
||||
@@ -270,13 +272,13 @@ static void usb_msd_handle_reset(USBDevice *dev)
|
||||
s->mode = USB_MSDM_CBW;
|
||||
}
|
||||
|
||||
static int usb_msd_handle_control(USBDevice *dev, int request, int value,
|
||||
int index, int length, uint8_t *data)
|
||||
static int usb_msd_handle_control(USBDevice *dev, USBPacket *p,
|
||||
int request, int value, int index, int length, uint8_t *data)
|
||||
{
|
||||
MSDState *s = (MSDState *)dev;
|
||||
int ret;
|
||||
|
||||
ret = usb_desc_handle_control(dev, request, value, index, length, data);
|
||||
ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
|
||||
if (ret >= 0) {
|
||||
return ret;
|
||||
}
|
||||
@@ -313,9 +315,9 @@ static int usb_msd_handle_control(USBDevice *dev, int request, int value,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void usb_msd_cancel_io(USBPacket *p, void *opaque)
|
||||
static void usb_msd_cancel_io(USBDevice *dev, USBPacket *p)
|
||||
{
|
||||
MSDState *s = opaque;
|
||||
MSDState *s = DO_UPCAST(MSDState, dev, dev);
|
||||
s->scsi_dev->info->cancel_io(s->scsi_dev, s->tag);
|
||||
s->packet = NULL;
|
||||
s->scsi_len = 0;
|
||||
@@ -396,7 +398,6 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
|
||||
}
|
||||
if (s->usb_len) {
|
||||
DPRINTF("Deferring packet %p\n", p);
|
||||
usb_defer_packet(p, usb_msd_cancel_io, s);
|
||||
s->packet = p;
|
||||
ret = USB_RET_ASYNC;
|
||||
} else {
|
||||
@@ -419,7 +420,6 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
|
||||
if (s->data_len != 0 || len < 13)
|
||||
goto fail;
|
||||
/* Waiting for SCSI write to complete. */
|
||||
usb_defer_packet(p, usb_msd_cancel_io, s);
|
||||
s->packet = p;
|
||||
ret = USB_RET_ASYNC;
|
||||
break;
|
||||
@@ -453,7 +453,6 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
|
||||
}
|
||||
if (s->usb_len) {
|
||||
DPRINTF("Deferring packet %p\n", p);
|
||||
usb_defer_packet(p, usb_msd_cancel_io, s);
|
||||
s->packet = p;
|
||||
ret = USB_RET_ASYNC;
|
||||
} else {
|
||||
@@ -602,6 +601,7 @@ static struct USBDeviceInfo msd_info = {
|
||||
.usb_desc = &desc,
|
||||
.init = usb_msd_initfn,
|
||||
.handle_packet = usb_generic_handle_packet,
|
||||
.cancel_packet = usb_msd_cancel_io,
|
||||
.handle_attach = usb_desc_attach,
|
||||
.handle_reset = usb_msd_handle_reset,
|
||||
.handle_control = usb_msd_handle_control,
|
||||
|
||||
+1
-1
@@ -601,7 +601,7 @@ static void musb_packet(MUSBState *s, MUSBEndPoint *ep,
|
||||
ep->packey[dir].dir = dir;
|
||||
|
||||
if (s->port.dev)
|
||||
ret = s->port.dev->info->handle_packet(s->port.dev, &ep->packey[dir].p);
|
||||
ret = usb_handle_packet(s->port.dev, &ep->packey[dir].p);
|
||||
else
|
||||
ret = USB_RET_NODEV;
|
||||
|
||||
|
||||
+3
-3
@@ -1042,13 +1042,13 @@ static void usb_net_handle_reset(USBDevice *dev)
|
||||
{
|
||||
}
|
||||
|
||||
static int usb_net_handle_control(USBDevice *dev, int request, int value,
|
||||
int index, int length, uint8_t *data)
|
||||
static int usb_net_handle_control(USBDevice *dev, USBPacket *p,
|
||||
int request, int value, int index, int length, uint8_t *data)
|
||||
{
|
||||
USBNetState *s = (USBNetState *) dev;
|
||||
int ret;
|
||||
|
||||
ret = usb_desc_handle_control(dev, request, value, index, length, data);
|
||||
ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
|
||||
if (ret >= 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
+2
-2
@@ -748,7 +748,7 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed,
|
||||
ohci->usb_packet.devep = OHCI_BM(ed->flags, ED_EN);
|
||||
ohci->usb_packet.data = ohci->usb_buf;
|
||||
ohci->usb_packet.len = len;
|
||||
ret = dev->info->handle_packet(dev, &ohci->usb_packet);
|
||||
ret = usb_handle_packet(dev, &ohci->usb_packet);
|
||||
if (ret != USB_RET_NODEV)
|
||||
break;
|
||||
}
|
||||
@@ -944,7 +944,7 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
|
||||
ohci->usb_packet.devep = OHCI_BM(ed->flags, ED_EN);
|
||||
ohci->usb_packet.data = ohci->usb_buf;
|
||||
ohci->usb_packet.len = len;
|
||||
ret = dev->info->handle_packet(dev, &ohci->usb_packet);
|
||||
ret = usb_handle_packet(dev, &ohci->usb_packet);
|
||||
if (ret != USB_RET_NODEV)
|
||||
break;
|
||||
}
|
||||
|
||||
+4
-3
@@ -146,6 +146,7 @@ static const USBDescDevice desc_device = {
|
||||
.bConfigurationValue = 1,
|
||||
.bmAttributes = 0x80,
|
||||
.bMaxPower = 50,
|
||||
.nif = 1,
|
||||
.ifs = &desc_iface0,
|
||||
},
|
||||
},
|
||||
@@ -218,14 +219,14 @@ static uint8_t usb_get_modem_lines(USBSerialState *s)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int usb_serial_handle_control(USBDevice *dev, int request, int value,
|
||||
int index, int length, uint8_t *data)
|
||||
static int usb_serial_handle_control(USBDevice *dev, USBPacket *p,
|
||||
int request, int value, int index, int length, uint8_t *data)
|
||||
{
|
||||
USBSerialState *s = (USBSerialState *)dev;
|
||||
int ret;
|
||||
|
||||
DPRINTF("got control %x, value %x\n",request, value);
|
||||
ret = usb_desc_handle_control(dev, request, value, index, length, data);
|
||||
ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
|
||||
if (ret >= 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
+5
-1
@@ -632,7 +632,7 @@ static int uhci_broadcast_packet(UHCIState *s, USBPacket *p)
|
||||
USBDevice *dev = port->port.dev;
|
||||
|
||||
if (dev && (port->ctrl & UHCI_PORT_EN))
|
||||
ret = dev->info->handle_packet(dev, p);
|
||||
ret = usb_handle_packet(dev, p);
|
||||
}
|
||||
|
||||
DPRINTF("uhci: packet exit. ret %d len %d\n", ret, p->len);
|
||||
@@ -702,11 +702,15 @@ out:
|
||||
case USB_RET_STALL:
|
||||
td->ctrl |= TD_CTRL_STALL;
|
||||
td->ctrl &= ~TD_CTRL_ACTIVE;
|
||||
s->status |= UHCI_STS_USBERR;
|
||||
uhci_update_irq(s);
|
||||
return 1;
|
||||
|
||||
case USB_RET_BABBLE:
|
||||
td->ctrl |= TD_CTRL_BABBLE | TD_CTRL_STALL;
|
||||
td->ctrl &= ~TD_CTRL_ACTIVE;
|
||||
s->status |= UHCI_STS_USBERR;
|
||||
uhci_update_irq(s);
|
||||
/* frame interrupted */
|
||||
return -1;
|
||||
|
||||
|
||||
+4
-3
@@ -108,6 +108,7 @@ static const USBDescDevice desc_device_wacom = {
|
||||
.bConfigurationValue = 1,
|
||||
.bmAttributes = 0x80,
|
||||
.bMaxPower = 40,
|
||||
.nif = 1,
|
||||
.ifs = &desc_iface_wacom,
|
||||
},
|
||||
},
|
||||
@@ -249,13 +250,13 @@ static void usb_wacom_handle_reset(USBDevice *dev)
|
||||
s->mode = WACOM_MODE_HID;
|
||||
}
|
||||
|
||||
static int usb_wacom_handle_control(USBDevice *dev, int request, int value,
|
||||
int index, int length, uint8_t *data)
|
||||
static int usb_wacom_handle_control(USBDevice *dev, USBPacket *p,
|
||||
int request, int value, int index, int length, uint8_t *data)
|
||||
{
|
||||
USBWacomState *s = (USBWacomState *) dev;
|
||||
int ret;
|
||||
|
||||
ret = usb_desc_handle_control(dev, request, value, index, length, data);
|
||||
ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
|
||||
if (ret >= 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -63,9 +63,10 @@ void usb_wakeup(USBDevice *dev)
|
||||
protocol)
|
||||
*/
|
||||
|
||||
#define SETUP_STATE_IDLE 0
|
||||
#define SETUP_STATE_DATA 1
|
||||
#define SETUP_STATE_ACK 2
|
||||
#define SETUP_STATE_IDLE 0
|
||||
#define SETUP_STATE_SETUP 1
|
||||
#define SETUP_STATE_DATA 2
|
||||
#define SETUP_STATE_ACK 3
|
||||
|
||||
static int do_token_setup(USBDevice *s, USBPacket *p)
|
||||
{
|
||||
@@ -82,10 +83,14 @@ static int do_token_setup(USBDevice *s, USBPacket *p)
|
||||
request = (s->setup_buf[0] << 8) | s->setup_buf[1];
|
||||
value = (s->setup_buf[3] << 8) | s->setup_buf[2];
|
||||
index = (s->setup_buf[5] << 8) | s->setup_buf[4];
|
||||
|
||||
|
||||
if (s->setup_buf[0] & USB_DIR_IN) {
|
||||
ret = s->info->handle_control(s, request, value, index,
|
||||
ret = s->info->handle_control(s, p, request, value, index,
|
||||
s->setup_len, s->data_buf);
|
||||
if (ret == USB_RET_ASYNC) {
|
||||
s->setup_state = SETUP_STATE_SETUP;
|
||||
return USB_RET_ASYNC;
|
||||
}
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@@ -123,9 +128,12 @@ static int do_token_in(USBDevice *s, USBPacket *p)
|
||||
switch(s->setup_state) {
|
||||
case SETUP_STATE_ACK:
|
||||
if (!(s->setup_buf[0] & USB_DIR_IN)) {
|
||||
s->setup_state = SETUP_STATE_IDLE;
|
||||
ret = s->info->handle_control(s, request, value, index,
|
||||
ret = s->info->handle_control(s, p, request, value, index,
|
||||
s->setup_len, s->data_buf);
|
||||
if (ret == USB_RET_ASYNC) {
|
||||
return USB_RET_ASYNC;
|
||||
}
|
||||
s->setup_state = SETUP_STATE_IDLE;
|
||||
if (ret > 0)
|
||||
return 0;
|
||||
return ret;
|
||||
@@ -238,6 +246,36 @@ int usb_generic_handle_packet(USBDevice *s, USBPacket *p)
|
||||
}
|
||||
}
|
||||
|
||||
/* ctrl complete function for devices which use usb_generic_handle_packet and
|
||||
may return USB_RET_ASYNC from their handle_control callback. Device code
|
||||
which does this *must* call this function instead of the normal
|
||||
usb_packet_complete to complete their async control packets. */
|
||||
void usb_generic_async_ctrl_complete(USBDevice *s, USBPacket *p)
|
||||
{
|
||||
if (p->len < 0) {
|
||||
s->setup_state = SETUP_STATE_IDLE;
|
||||
}
|
||||
|
||||
switch (s->setup_state) {
|
||||
case SETUP_STATE_SETUP:
|
||||
if (p->len < s->setup_len) {
|
||||
s->setup_len = p->len;
|
||||
}
|
||||
s->setup_state = SETUP_STATE_DATA;
|
||||
p->len = 8;
|
||||
break;
|
||||
|
||||
case SETUP_STATE_ACK:
|
||||
s->setup_state = SETUP_STATE_IDLE;
|
||||
p->len = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
usb_packet_complete(s, p);
|
||||
}
|
||||
|
||||
/* XXX: fix overflow */
|
||||
int set_usb_string(uint8_t *buf, const char *str)
|
||||
{
|
||||
@@ -259,9 +297,54 @@ int set_usb_string(uint8_t *buf, const char *str)
|
||||
void usb_send_msg(USBDevice *dev, int msg)
|
||||
{
|
||||
USBPacket p;
|
||||
int ret;
|
||||
|
||||
memset(&p, 0, sizeof(p));
|
||||
p.pid = msg;
|
||||
dev->info->handle_packet(dev, &p);
|
||||
|
||||
ret = usb_handle_packet(dev, &p);
|
||||
/* This _must_ be synchronous */
|
||||
assert(ret != USB_RET_ASYNC);
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
int usb_handle_packet(USBDevice *dev, USBPacket *p)
|
||||
{
|
||||
int ret;
|
||||
|
||||
assert(p->owner == NULL);
|
||||
ret = dev->info->handle_packet(dev, p);
|
||||
if (ret == USB_RET_ASYNC) {
|
||||
if (p->owner == NULL) {
|
||||
p->owner = dev;
|
||||
} else {
|
||||
/* We'll end up here when usb_handle_packet is called
|
||||
* recursively due to a hub being in the chain. Nothing
|
||||
* to do. Leave p->owner pointing to the device, not the
|
||||
* hub. */;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Notify the controller that an async packet is complete. This should only
|
||||
be called for packets previously deferred by returning USB_RET_ASYNC from
|
||||
handle_packet. */
|
||||
void usb_packet_complete(USBDevice *dev, USBPacket *p)
|
||||
{
|
||||
/* Note: p->owner != dev is possible in case dev is a hub */
|
||||
assert(p->owner != NULL);
|
||||
dev->port->ops->complete(dev, p);
|
||||
p->owner = NULL;
|
||||
}
|
||||
|
||||
/* Cancel an active packet. The packed must have been deferred by
|
||||
returning USB_RET_ASYNC from handle_packet, and not yet
|
||||
completed. */
|
||||
void usb_cancel_packet(USBPacket * p)
|
||||
{
|
||||
assert(p->owner != NULL);
|
||||
p->owner->info->cancel_packet(p->owner, p);
|
||||
p->owner = NULL;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user