usb: move USB_REQ_{GET,SET}_CONFIGURATION handling to common code

This patch adds fields to the USBDevice struct for the current
speed (hard-wired to full speed for now) and current device
configuration.  Also a init function is added which inializes
these fields.  This allows USB_REQ_{GET,SET}_CONFIGURATION
handling to be moved to common code.

For most drivers the conversion is trivial ad they support a single
configuration only anyway.  One exception is bluetooth where some
device-specific setup code runs after get/set configuration.  The
other is usb-net which actually has two configurations so the
the code to check for the active configuration has been adapted.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
This commit is contained in:
Gerd Hoffmann 2010-11-26 20:20:41 +01:00
parent 41c6abbdeb
commit a980a065fb
11 changed files with 66 additions and 93 deletions

View File

@ -380,6 +380,17 @@ static int usb_bt_handle_control(USBDevice *dev, int request, int value,
ret = usb_desc_handle_control(dev, request, value, index, length, data);
if (ret >= 0) {
switch (request) {
case DeviceRequest | USB_REQ_GET_CONFIGURATION:
s->config = 0;
break;
case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
s->config = 1;
usb_bt_fifo_reset(&s->evt);
usb_bt_fifo_reset(&s->acl);
usb_bt_fifo_reset(&s->sco);
break;
}
return ret;
}
@ -413,23 +424,6 @@ static int usb_bt_handle_control(USBDevice *dev, int request, int value,
}
ret = 0;
break;
case DeviceRequest | USB_REQ_GET_CONFIGURATION:
data[0] = 1;
ret = 1;
s->config = 0;
break;
case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
ret = 0;
if (value != 1 && value != 0) {
printf("%s: Wrong SET_CONFIGURATION request (%i)\n",
__FUNCTION__, value);
goto fail;
}
s->config = 1;
usb_bt_fifo_reset(&s->evt);
usb_bt_fifo_reset(&s->acl);
usb_bt_fifo_reset(&s->sco);
break;
case InterfaceRequest | USB_REQ_GET_INTERFACE:
if (value != 0 || (index & ~1) || length != 1)
goto fail;
@ -544,8 +538,7 @@ static void usb_bt_handle_destroy(USBDevice *dev)
static int usb_bt_initfn(USBDevice *dev)
{
struct USBBtState *s = DO_UPCAST(struct USBBtState, dev, dev);
s->dev.speed = USB_SPEED_HIGH;
usb_desc_init(dev);
return 0;
}

View File

@ -153,6 +153,16 @@ int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len)
/* ------------------------------------------------------------------ */
void usb_desc_init(USBDevice *dev)
{
const USBDesc *desc = dev->info->usb_desc;
assert(desc != NULL);
dev->speed = USB_SPEED_FULL;
dev->device = desc->full;
dev->config = dev->device->confs;
}
void usb_desc_set_string(USBDevice *dev, uint8_t index, const char *str)
{
USBDescString *s;
@ -230,12 +240,12 @@ int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len
switch(type) {
case USB_DT_DEVICE:
ret = usb_desc_device(&desc->id, desc->full, buf, sizeof(buf));
ret = usb_desc_device(&desc->id, dev->device, buf, sizeof(buf));
trace_usb_desc_device(dev->addr, len, ret);
break;
case USB_DT_CONFIG:
if (index < desc->full->bNumConfigurations) {
ret = usb_desc_config(desc->full->confs + index, buf, sizeof(buf));
if (index < dev->device->bNumConfigurations) {
ret = usb_desc_config(dev->device->confs + index, buf, sizeof(buf));
}
trace_usb_desc_config(dev->addr, index, len, ret);
break;
@ -262,7 +272,7 @@ int usb_desc_handle_control(USBDevice *dev, int request, int value,
int index, int length, uint8_t *data)
{
const USBDesc *desc = dev->info->usb_desc;
int ret = -1;
int i, ret = -1;
assert(desc != NULL);
switch(request) {
@ -275,6 +285,20 @@ int usb_desc_handle_control(USBDevice *dev, int request, int value,
case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
ret = usb_desc_get_descriptor(dev, value, data, length);
break;
case DeviceRequest | USB_REQ_GET_CONFIGURATION:
data[0] = dev->config->bConfigurationValue;
ret = 1;
break;
case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
for (i = 0; i < dev->device->bNumConfigurations; i++) {
if (dev->device->confs[i].bConfigurationValue == value) {
dev->config = dev->device->confs + i;
ret = 0;
}
}
trace_usb_set_config(dev->addr, value, ret);
break;
}
return ret;
}

View File

@ -78,6 +78,7 @@ 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);
/* control message emulation helpers */
void usb_desc_init(USBDevice *dev);
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);

View File

@ -695,13 +695,6 @@ static int usb_hid_handle_control(USBDevice *dev, int request, int value,
}
ret = 0;
break;
case DeviceRequest | USB_REQ_GET_CONFIGURATION:
data[0] = 1;
ret = 1;
break;
case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
ret = 0;
break;
case DeviceRequest | USB_REQ_GET_INTERFACE:
data[0] = 0;
ret = 1;
@ -822,7 +815,8 @@ static void usb_hid_handle_destroy(USBDevice *dev)
static int usb_hid_initfn(USBDevice *dev, int kind)
{
USBHIDState *s = DO_UPCAST(USBHIDState, dev, dev);
s->dev.speed = USB_SPEED_FULL;
usb_desc_init(dev);
s->kind = kind;
if (s->kind == USB_MOUSE) {

View File

@ -297,13 +297,6 @@ static int usb_hub_handle_control(USBDevice *dev, int request, int value,
}
ret = 0;
break;
case DeviceRequest | USB_REQ_GET_CONFIGURATION:
data[0] = 1;
ret = 1;
break;
case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
ret = 0;
break;
case DeviceRequest | USB_REQ_GET_INTERFACE:
data[0] = 0;
ret = 1;
@ -541,7 +534,7 @@ static int usb_hub_initfn(USBDevice *dev)
USBHubPort *port;
int i;
s->dev.speed = USB_SPEED_FULL;
usb_desc_init(dev);
for (i = 0; i < NUM_PORTS; i++) {
port = &s->ports[i];
usb_register_port(usb_bus_from_device(dev),

View File

@ -261,13 +261,6 @@ static int usb_msd_handle_control(USBDevice *dev, int request, int value,
}
ret = 0;
break;
case DeviceRequest | USB_REQ_GET_CONFIGURATION:
data[0] = 1;
ret = 1;
break;
case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
ret = 0;
break;
case DeviceRequest | USB_REQ_GET_INTERFACE:
data[0] = 0;
ret = 1;
@ -502,7 +495,7 @@ static int usb_msd_initfn(USBDevice *dev)
usb_desc_set_string(dev, STR_SERIALNUMBER, dinfo->serial);
}
s->dev.speed = USB_SPEED_FULL;
usb_desc_init(dev);
scsi_bus_new(&s->bus, &s->dev.qdev, 0, 1, usb_msd_command_complete);
s->scsi_dev = scsi_bus_legacy_add_drive(&s->bus, bs, 0);
if (!s->scsi_dev) {

View File

@ -627,7 +627,6 @@ struct rndis_response {
typedef struct USBNetState {
USBDevice dev;
unsigned int rndis;
enum rndis_state rndis_state;
uint32_t medium;
uint32_t speed;
@ -648,6 +647,11 @@ typedef struct USBNetState {
QTAILQ_HEAD(rndis_resp_head, rndis_response) rndis_resp;
} USBNetState;
static int is_rndis(USBNetState *s)
{
return s->dev.config->bConfigurationValue == DEV_RNDIS_CONFIG_VALUE;
}
static int ndis_query(USBNetState *s, uint32_t oid,
uint8_t *inbuf, unsigned int inlen, uint8_t *outbuf,
size_t outlen)
@ -1077,8 +1081,9 @@ static int usb_net_handle_control(USBDevice *dev, int request, int value,
break;
case ClassInterfaceOutRequest | USB_CDC_SEND_ENCAPSULATED_COMMAND:
if (!s->rndis || value || index != 0)
if (!is_rndis(s) || value || index != 0) {
goto fail;
}
#ifdef TRAFFIC_DEBUG
{
unsigned int i;
@ -1095,8 +1100,9 @@ static int usb_net_handle_control(USBDevice *dev, int request, int value,
break;
case ClassInterfaceRequest | USB_CDC_GET_ENCAPSULATED_RESPONSE:
if (!s->rndis || value || index != 0)
if (!is_rndis(s) || value || index != 0) {
goto fail;
}
ret = rndis_get_response(s, data);
if (!ret) {
data[0] = 0;
@ -1116,27 +1122,6 @@ static int usb_net_handle_control(USBDevice *dev, int request, int value,
#endif
break;
case DeviceRequest | USB_REQ_GET_CONFIGURATION:
data[0] = s->rndis ? DEV_RNDIS_CONFIG_VALUE : DEV_CONFIG_VALUE;
ret = 1;
break;
case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
switch (value & 0xff) {
case DEV_CONFIG_VALUE:
s->rndis = 0;
break;
case DEV_RNDIS_CONFIG_VALUE:
s->rndis = 1;
break;
default:
goto fail;
}
ret = 0;
break;
case DeviceRequest | USB_REQ_GET_INTERFACE:
case InterfaceRequest | USB_REQ_GET_INTERFACE:
data[0] = 0;
@ -1207,7 +1192,7 @@ static int usb_net_handle_datain(USBNetState *s, USBPacket *p)
memcpy(p->data, &s->in_buf[s->in_ptr], ret);
s->in_ptr += ret;
if (s->in_ptr >= s->in_len &&
(s->rndis || (s->in_len & (64 - 1)) || !ret)) {
(is_rndis(s) || (s->in_len & (64 - 1)) || !ret)) {
/* no short packet necessary */
s->in_ptr = s->in_len = 0;
}
@ -1256,7 +1241,7 @@ static int usb_net_handle_dataout(USBNetState *s, USBPacket *p)
memcpy(&s->out_buf[s->out_ptr], p->data, sz);
s->out_ptr += sz;
if (!s->rndis) {
if (!is_rndis(s)) {
if (ret < 64) {
qemu_send_packet(&s->nic->nc, s->out_buf, s->out_ptr);
s->out_ptr = 0;
@ -1327,7 +1312,7 @@ static ssize_t usbnet_receive(VLANClientState *nc, const uint8_t *buf, size_t si
USBNetState *s = DO_UPCAST(NICState, nc, nc)->opaque;
struct rndis_packet_msg_type *msg;
if (s->rndis) {
if (is_rndis(s)) {
msg = (struct rndis_packet_msg_type *) s->in_buf;
if (!s->rndis_state == RNDIS_DATA_INITIALIZED)
return -1;
@ -1363,8 +1348,9 @@ static int usbnet_can_receive(VLANClientState *nc)
{
USBNetState *s = DO_UPCAST(NICState, nc, nc)->opaque;
if (s->rndis && !s->rndis_state == RNDIS_DATA_INITIALIZED)
if (is_rndis(s) && !s->rndis_state == RNDIS_DATA_INITIALIZED) {
return 1;
}
return !s->in_len;
}
@ -1397,9 +1383,8 @@ static int usb_net_initfn(USBDevice *dev)
{
USBNetState *s = DO_UPCAST(USBNetState, dev, dev);
s->dev.speed = USB_SPEED_FULL;
usb_desc_init(dev);
s->rndis = 1;
s->rndis_state = RNDIS_UNINITIALIZED;
QTAILQ_INIT(&s->rndis_resp);

View File

@ -254,13 +254,6 @@ static int usb_serial_handle_control(USBDevice *dev, int request, int value,
}
ret = 0;
break;
case DeviceRequest | USB_REQ_GET_CONFIGURATION:
data[0] = 1;
ret = 1;
break;
case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
ret = 0;
break;
case DeviceRequest | USB_REQ_GET_INTERFACE:
data[0] = 0;
ret = 1;
@ -507,7 +500,8 @@ static void usb_serial_event(void *opaque, int event)
static int usb_serial_initfn(USBDevice *dev)
{
USBSerialState *s = DO_UPCAST(USBSerialState, dev, dev);
s->dev.speed = USB_SPEED_FULL;
usb_desc_init(dev);
if (!s->cs) {
error_report("Property chardev is required");

View File

@ -284,13 +284,6 @@ static int usb_wacom_handle_control(USBDevice *dev, int request, int value,
}
ret = 0;
break;
case DeviceRequest | USB_REQ_GET_CONFIGURATION:
data[0] = 1;
ret = 1;
break;
case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
ret = 0;
break;
case DeviceRequest | USB_REQ_GET_INTERFACE:
data[0] = 0;
ret = 1;
@ -373,7 +366,7 @@ static void usb_wacom_handle_destroy(USBDevice *dev)
static int usb_wacom_initfn(USBDevice *dev)
{
USBWacomState *s = DO_UPCAST(USBWacomState, dev, dev);
s->dev.speed = USB_SPEED_FULL;
usb_desc_init(dev);
s->changed = 1;
return 0;
}

View File

@ -164,6 +164,8 @@ struct USBDevice {
int setup_index;
QLIST_HEAD(, USBDescString) strings;
const USBDescDevice *device;
const USBDescConfig *config;
};
struct USBDeviceInfo {

View File

@ -195,6 +195,7 @@ disable usb_desc_device(int addr, int len, int ret) "dev %d query device, len %d
disable usb_desc_config(int addr, int index, int len, int ret) "dev %d query config %d, len %d, ret %d"
disable usb_desc_string(int addr, int index, int len, int ret) "dev %d query string %d, len %d, ret %d"
disable usb_set_addr(int addr) "dev %d"
disable usb_set_config(int addr, int config, int ret) "dev %d, config %d, ret %d"
# vl.c
disable vm_state_notify(int running, int reason) "running %d reason %d"