Also handle {GET,SET}_INTERFACE in common code (usb-desc.c).
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
USBDevice dev;
struct HCIInfo *hci;
- int altsetting;
int config;
#define CFIFO_LEN_MASK 255
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,
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,
}
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");
/* ------------------------------------------------------------------ */
+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;
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;
}
}
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;
}
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) {
}
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;
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. */
#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: "
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;
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);
QLIST_ENTRY(USBDescString) next;
};
+#define USB_MAX_ENDPOINTS 15
+#define USB_MAX_INTERFACES 16
+
/* definition of a USB device */
struct USBDevice {
DeviceState qdev;
int configuration;
int ninterfaces;
+ int altsetting[USB_MAX_INTERFACES];
const USBDescConfig *config;
+ const USBDescIface *ifaces[USB_MAX_INTERFACES];
};
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;
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"
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;
}
}
+ if (iface >= USB_MAX_INTERFACES) {
+ return USB_RET_STALL;
+ }
+
si.interface = iface;
si.altsetting = alt;
ret = ioctl(s->fd, USBDEVFS_SETINTERFACE, &si);
if (ret < 0) {
return ctrl_error();
}
+
+ s->dev.altsetting[iface] = alt;
usb_linux_update_endp_table(s);
return 0;
}