usb: track altsetting in USBDevice
Also handle {GET,SET}_INTERFACE in common code (usb-desc.c). Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
This commit is contained in:
parent
65360511a2
commit
1de14d43e2
22
hw/usb-bt.c
22
hw/usb-bt.c
@ -28,7 +28,6 @@ struct USBBtState {
|
||||
USBDevice dev;
|
||||
struct HCIInfo *hci;
|
||||
|
||||
int altsetting;
|
||||
int config;
|
||||
|
||||
#define CFIFO_LEN_MASK 255
|
||||
@ -362,7 +361,6 @@ static void usb_bt_handle_reset(USBDevice *dev)
|
||||
s->outcmd.len = 0;
|
||||
s->outacl.len = 0;
|
||||
s->outsco.len = 0;
|
||||
s->altsetting = 0;
|
||||
}
|
||||
|
||||
static int usb_bt_handle_control(USBDevice *dev, USBPacket *p,
|
||||
@ -402,26 +400,6 @@ static int usb_bt_handle_control(USBDevice *dev, USBPacket *p,
|
||||
case EndpointOutRequest | USB_REQ_SET_FEATURE:
|
||||
goto fail;
|
||||
break;
|
||||
case InterfaceRequest | USB_REQ_GET_INTERFACE:
|
||||
if (value != 0 || (index & ~1) || length != 1)
|
||||
goto fail;
|
||||
if (index == 1)
|
||||
data[0] = s->altsetting;
|
||||
else
|
||||
data[0] = 0;
|
||||
ret = 1;
|
||||
break;
|
||||
case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
|
||||
if ((index & ~1) || length != 0 ||
|
||||
(index == 1 && (value < 0 || value > 4)) ||
|
||||
(index == 0 && value != 0)) {
|
||||
printf("%s: Wrong SET_INTERFACE request (%i, %i)\n",
|
||||
__FUNCTION__, index, value);
|
||||
goto fail;
|
||||
}
|
||||
s->altsetting = value;
|
||||
ret = 0;
|
||||
break;
|
||||
case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_DEVICE) << 8):
|
||||
if (s->config)
|
||||
usb_bt_fifo_out_enqueue(s, &s->outcmd, s->hci->cmd_send,
|
||||
|
@ -611,14 +611,6 @@ static int ccid_handle_control(USBDevice *dev, USBPacket *p, int request,
|
||||
}
|
||||
|
||||
switch (request) {
|
||||
case DeviceRequest | USB_REQ_GET_INTERFACE:
|
||||
data[0] = 0;
|
||||
ret = 1;
|
||||
break;
|
||||
case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
/* Class specific requests. */
|
||||
case InterfaceOutClass | CCID_CONTROL_ABORT:
|
||||
DPRINTF(s, 1, "ccid_control abort UNIMPLEMENTED\n");
|
||||
|
@ -223,6 +223,54 @@ int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len)
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
static const USBDescIface *usb_desc_find_interface(USBDevice *dev,
|
||||
int nif, int alt)
|
||||
{
|
||||
const USBDescIface *iface;
|
||||
int g, i;
|
||||
|
||||
if (!dev->config) {
|
||||
return NULL;
|
||||
}
|
||||
for (g = 0; g < dev->config->nif_groups; g++) {
|
||||
for (i = 0; i < dev->config->if_groups[g].nif; i++) {
|
||||
iface = &dev->config->if_groups[g].ifs[i];
|
||||
if (iface->bInterfaceNumber == nif &&
|
||||
iface->bAlternateSetting == alt) {
|
||||
return iface;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i = 0; i < dev->config->nif; i++) {
|
||||
iface = &dev->config->ifs[i];
|
||||
if (iface->bInterfaceNumber == nif &&
|
||||
iface->bAlternateSetting == alt) {
|
||||
return iface;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int usb_desc_set_interface(USBDevice *dev, int index, int value)
|
||||
{
|
||||
const USBDescIface *iface;
|
||||
int old;
|
||||
|
||||
iface = usb_desc_find_interface(dev, index, value);
|
||||
if (iface == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
old = dev->altsetting[index];
|
||||
dev->altsetting[index] = value;
|
||||
dev->ifaces[index] = iface;
|
||||
|
||||
if (dev->info->set_interface && old != value) {
|
||||
dev->info->set_interface(dev, index, old, value);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usb_desc_set_config(USBDevice *dev, int value)
|
||||
{
|
||||
int i;
|
||||
@ -237,12 +285,22 @@ static int usb_desc_set_config(USBDevice *dev, int value)
|
||||
dev->configuration = value;
|
||||
dev->ninterfaces = dev->device->confs[i].bNumInterfaces;
|
||||
dev->config = dev->device->confs + i;
|
||||
assert(dev->ninterfaces <= USB_MAX_INTERFACES);
|
||||
}
|
||||
}
|
||||
if (i < dev->device->bNumConfigurations) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < dev->ninterfaces; i++) {
|
||||
usb_desc_set_interface(dev, i, 0);
|
||||
}
|
||||
for (; i < USB_MAX_INTERFACES; i++) {
|
||||
dev->altsetting[i] = 0;
|
||||
dev->ifaces[i] = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -479,6 +537,19 @@ int usb_desc_handle_control(USBDevice *dev, USBPacket *p,
|
||||
}
|
||||
trace_usb_set_device_feature(dev->addr, value, ret);
|
||||
break;
|
||||
|
||||
case InterfaceRequest | USB_REQ_GET_INTERFACE:
|
||||
if (index < 0 || index >= dev->ninterfaces) {
|
||||
break;
|
||||
}
|
||||
data[0] = dev->altsetting[index];
|
||||
ret = 1;
|
||||
break;
|
||||
case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
|
||||
ret = usb_desc_set_interface(dev, index, value);
|
||||
trace_usb_set_interface(dev->addr, index, value, ret);
|
||||
break;
|
||||
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -384,13 +384,6 @@ static int usb_hid_handle_control(USBDevice *dev, USBPacket *p,
|
||||
|
||||
ret = 0;
|
||||
switch (request) {
|
||||
case DeviceRequest | USB_REQ_GET_INTERFACE:
|
||||
data[0] = 0;
|
||||
ret = 1;
|
||||
break;
|
||||
case DeviceOutRequest | USB_REQ_SET_INTERFACE:
|
||||
ret = 0;
|
||||
break;
|
||||
/* hid specific requests */
|
||||
case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
|
||||
switch (value >> 8) {
|
||||
|
@ -258,13 +258,6 @@ static int usb_hub_handle_control(USBDevice *dev, USBPacket *p,
|
||||
}
|
||||
ret = 0;
|
||||
break;
|
||||
case DeviceRequest | USB_REQ_GET_INTERFACE:
|
||||
data[0] = 0;
|
||||
ret = 1;
|
||||
break;
|
||||
case DeviceOutRequest | USB_REQ_SET_INTERFACE:
|
||||
ret = 0;
|
||||
break;
|
||||
/* usb specific requests */
|
||||
case GetHubStatus:
|
||||
data[0] = 0;
|
||||
|
10
hw/usb-msd.c
10
hw/usb-msd.c
@ -306,19 +306,9 @@ static int usb_msd_handle_control(USBDevice *dev, USBPacket *p,
|
||||
|
||||
ret = 0;
|
||||
switch (request) {
|
||||
case DeviceRequest | USB_REQ_GET_INTERFACE:
|
||||
data[0] = 0;
|
||||
ret = 1;
|
||||
break;
|
||||
case DeviceOutRequest | USB_REQ_SET_INTERFACE:
|
||||
ret = 0;
|
||||
break;
|
||||
case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
|
||||
ret = 0;
|
||||
break;
|
||||
case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
|
||||
ret = 0;
|
||||
break;
|
||||
/* Class specific requests. */
|
||||
case ClassInterfaceOutRequest | MassStorageReset:
|
||||
/* Reset state ready for the next CBW. */
|
||||
|
11
hw/usb-net.c
11
hw/usb-net.c
@ -1098,17 +1098,6 @@ static int usb_net_handle_control(USBDevice *dev, USBPacket *p,
|
||||
#endif
|
||||
break;
|
||||
|
||||
case DeviceRequest | USB_REQ_GET_INTERFACE:
|
||||
case InterfaceRequest | USB_REQ_GET_INTERFACE:
|
||||
data[0] = 0;
|
||||
ret = 1;
|
||||
break;
|
||||
|
||||
case DeviceOutRequest | USB_REQ_SET_INTERFACE:
|
||||
case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
fail:
|
||||
fprintf(stderr, "usbnet: failed control transaction: "
|
||||
|
@ -233,13 +233,6 @@ static int usb_serial_handle_control(USBDevice *dev, USBPacket *p,
|
||||
|
||||
ret = 0;
|
||||
switch (request) {
|
||||
case DeviceRequest | USB_REQ_GET_INTERFACE:
|
||||
data[0] = 0;
|
||||
ret = 1;
|
||||
break;
|
||||
case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
|
||||
ret = 0;
|
||||
break;
|
||||
case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
|
||||
ret = 0;
|
||||
break;
|
||||
|
@ -263,13 +263,6 @@ static int usb_wacom_handle_control(USBDevice *dev, USBPacket *p,
|
||||
|
||||
ret = 0;
|
||||
switch (request) {
|
||||
case DeviceRequest | USB_REQ_GET_INTERFACE:
|
||||
data[0] = 0;
|
||||
ret = 1;
|
||||
break;
|
||||
case DeviceOutRequest | USB_REQ_SET_INTERFACE:
|
||||
ret = 0;
|
||||
break;
|
||||
case WACOM_SET_REPORT:
|
||||
if (s->mouse_grabbed) {
|
||||
qemu_remove_mouse_event_handler(s->eh_entry);
|
||||
|
8
hw/usb.h
8
hw/usb.h
@ -161,6 +161,9 @@ struct USBDescString {
|
||||
QLIST_ENTRY(USBDescString) next;
|
||||
};
|
||||
|
||||
#define USB_MAX_ENDPOINTS 15
|
||||
#define USB_MAX_INTERFACES 16
|
||||
|
||||
/* definition of a USB device */
|
||||
struct USBDevice {
|
||||
DeviceState qdev;
|
||||
@ -191,7 +194,9 @@ struct USBDevice {
|
||||
|
||||
int configuration;
|
||||
int ninterfaces;
|
||||
int altsetting[USB_MAX_INTERFACES];
|
||||
const USBDescConfig *config;
|
||||
const USBDescIface *ifaces[USB_MAX_INTERFACES];
|
||||
};
|
||||
|
||||
struct USBDeviceInfo {
|
||||
@ -244,6 +249,9 @@ struct USBDeviceInfo {
|
||||
*/
|
||||
int (*handle_data)(USBDevice *dev, USBPacket *p);
|
||||
|
||||
void (*set_interface)(USBDevice *dev, int interface,
|
||||
int alt_old, int alt_new);
|
||||
|
||||
const char *product_desc;
|
||||
const USBDesc *usb_desc;
|
||||
|
||||
|
@ -246,6 +246,7 @@ usb_desc_other_speed_config(int addr, int index, int len, int ret) "dev %d query
|
||||
usb_desc_string(int addr, int index, int len, int ret) "dev %d query string %d, len %d, ret %d"
|
||||
usb_set_addr(int addr) "dev %d"
|
||||
usb_set_config(int addr, int config, int ret) "dev %d, config %d, ret %d"
|
||||
usb_set_interface(int addr, int iface, int alt, int ret) "dev %d, interface %d, altsetting %d, ret %d"
|
||||
usb_clear_device_feature(int addr, int feature, int ret) "dev %d, feature %d, ret %d"
|
||||
usb_set_device_feature(int addr, int feature, int ret) "dev %d, feature %d, ret %d"
|
||||
|
||||
|
10
usb-linux.c
10
usb-linux.c
@ -544,6 +544,10 @@ static int usb_host_claim_interfaces(USBHostDevice *dev, int configuration)
|
||||
int interface, nb_interfaces;
|
||||
int ret, i;
|
||||
|
||||
for (i = 0; i < USB_MAX_INTERFACES; i++) {
|
||||
dev->dev.altsetting[i] = 0;
|
||||
}
|
||||
|
||||
if (configuration == 0) { /* address state - ignore */
|
||||
dev->dev.ninterfaces = 0;
|
||||
dev->dev.configuration = 0;
|
||||
@ -997,6 +1001,10 @@ static int usb_host_set_interface(USBHostDevice *s, int iface, int alt)
|
||||
}
|
||||
}
|
||||
|
||||
if (iface >= USB_MAX_INTERFACES) {
|
||||
return USB_RET_STALL;
|
||||
}
|
||||
|
||||
si.interface = iface;
|
||||
si.altsetting = alt;
|
||||
ret = ioctl(s->fd, USBDEVFS_SETINTERFACE, &si);
|
||||
@ -1007,6 +1015,8 @@ static int usb_host_set_interface(USBHostDevice *s, int iface, int alt)
|
||||
if (ret < 0) {
|
||||
return ctrl_error();
|
||||
}
|
||||
|
||||
s->dev.altsetting[iface] = alt;
|
||||
usb_linux_update_endp_table(s);
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user