mirror of
https://github.com/xemu-project/xemu.git
synced 2024-11-23 19:49:43 +00:00
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:
parent
41c6abbdeb
commit
a980a065fb
31
hw/usb-bt.c
31
hw/usb-bt.c
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
10
hw/usb-hid.c
10
hw/usb-hid.c
@ -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) {
|
||||
|
@ -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),
|
||||
|
@ -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) {
|
||||
|
45
hw/usb-net.c
45
hw/usb-net.c
@ -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);
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
}
|
||||
|
2
hw/usb.h
2
hw/usb.h
@ -164,6 +164,8 @@ struct USBDevice {
|
||||
int setup_index;
|
||||
|
||||
QLIST_HEAD(, USBDescString) strings;
|
||||
const USBDescDevice *device;
|
||||
const USBDescConfig *config;
|
||||
};
|
||||
|
||||
struct USBDeviceInfo {
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user