diff options
author | Hans de Goede <hdegoede@redhat.com> | 2012-02-22 13:11:53 +0100 |
---|---|---|
committer | Hans de Goede <hdegoede@redhat.com> | 2012-02-22 13:14:11 +0100 |
commit | df24fe116ea913dd1fa4b4725ad5764117943eba (patch) | |
tree | aea4b261f4157c74bf5e4309709a99a8c3220258 /usbredirhost | |
parent | 9bd3461acab257410ed38569ba93abc33059cd69 (diff) |
usbredirhost: Clear ep_info on set_interface
Now that we only re-parse the interface and not the entire config when changing
the alt setting, we must first clear the ep-info of the endpoints currently
belonging to the interface as a different alt setting may have less endpoints!
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Diffstat (limited to 'usbredirhost')
-rw-r--r-- | usbredirhost/usbredirhost.c | 49 |
1 files changed, 32 insertions, 17 deletions
diff --git a/usbredirhost/usbredirhost.c b/usbredirhost/usbredirhost.c index 2f4216e..4f3e8f1 100644 --- a/usbredirhost/usbredirhost.c +++ b/usbredirhost/usbredirhost.c @@ -81,6 +81,8 @@ struct usbredirtransfer { struct usbredirhost_ep { uint8_t type; + uint8_t interval; + uint8_t interface; uint8_t iso_started; uint8_t iso_pkts_per_transfer; uint8_t iso_transfer_count; @@ -302,17 +304,10 @@ static int usbredirhost_get_max_packetsize(uint16_t wMaxPacketSize) /* Called from open/close and parser read callbacks */ static void usbredirhost_send_interface_n_ep_info(struct usbredirhost *host) { - int i, j; + int i; const struct libusb_interface_descriptor *intf_desc; struct usb_redir_ep_info_header ep_info; struct usb_redir_interface_info_header interface_info; - uint8_t ep_address; - - for (i = 0; i < MAX_ENDPOINTS; i++) { - ep_info.type[i] = host->endpoint[i].type; - ep_info.interface[i] = 0; - ep_info.interval[i] = 0; - } interface_info.interface_count = host->config->bNumInterfaces; for (i = 0; i < host->config->bNumInterfaces; i++) { @@ -323,16 +318,14 @@ static void usbredirhost_send_interface_n_ep_info(struct usbredirhost *host) interface_info.interface_class[i] = intf_desc->bInterfaceClass; interface_info.interface_subclass[i] = intf_desc->bInterfaceSubClass; interface_info.interface_protocol[i] = intf_desc->bInterfaceProtocol; - - for (j = 0; j < intf_desc->bNumEndpoints; j++) { - ep_address = intf_desc->endpoint[j].bEndpointAddress; - ep_info.interval[EP2I(ep_address)] = - intf_desc->endpoint[j].bInterval; - ep_info.interface[EP2I(ep_address)] = - intf_desc->bInterfaceNumber; - } } usbredirparser_send_interface_info(host->parser, &interface_info); + + for (i = 0; i < MAX_ENDPOINTS; i++) { + ep_info.type[i] = host->endpoint[i].type; + ep_info.interval[i] = host->endpoint[i].interval; + ep_info.interface[i] = host->endpoint[i].interface; + } usbredirparser_send_ep_info(host->parser, &ep_info); } @@ -402,6 +395,10 @@ static void usbredirhost_parse_interface(struct usbredirhost *host, int i) host->endpoint[EP2I(ep_address)].type = intf_desc->endpoint[j].bmAttributes & LIBUSB_TRANSFER_TYPE_MASK; + host->endpoint[EP2I(ep_address)].interval = + intf_desc->endpoint[j].bInterval; + host->endpoint[EP2I(ep_address)].interface = + intf_desc->bInterfaceNumber; } } @@ -415,6 +412,8 @@ static void usbredirhost_parse_config(struct usbredirhost *host) } else { host->endpoint[i].type = usb_redir_type_invalid; } + host->endpoint[i].interval = 0; + host->endpoint[i].interface = 0; } for (i = 0; i < host->config->bNumInterfaces; i++) { @@ -1488,7 +1487,7 @@ static void usbredirhost_set_alt_setting(void *priv, uint32_t id, struct usb_redir_set_alt_setting_header *set_alt_setting) { struct usbredirhost *host = priv; - int i, r; + int i, j, r; struct usb_redir_alt_setting_status_header status = { .status = usb_redir_success, }; @@ -1518,6 +1517,22 @@ static void usbredirhost_set_alt_setting(void *priv, uint32_t id, status.status = libusb_status_or_error_to_redir_status(host, r); goto exit; } + + /* The new alt setting may have lost endpoints compared to the old! -> + Clear settings for all endpoints which used to be part of the intf. */ + for (j = 0; j < MAX_ENDPOINTS; j++) { + if (host->endpoint[j].interface != set_alt_setting->interface) + continue; + + if ((i & 0x0f) == 0) { + host->endpoint[j].type = usb_redir_type_control; + } else { + host->endpoint[j].type = usb_redir_type_invalid; + } + host->endpoint[j].interval = 0; + host->endpoint[j].interface = 0; + } + host->alt_setting[i] = set_alt_setting->alt; usbredirhost_parse_interface(host, i); usbredirhost_send_interface_n_ep_info(host); |