diff options
author | Michal Nazarewicz <m.nazarewicz@samsung.com> | 2009-10-28 18:57:30 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-12-11 22:55:19 +0300 |
commit | b97503ffa79f0a4aa13c7cd8b449b98d3077c78f (patch) | |
tree | 41a87deca5a6baa0f91af2f9016b9ae320ea4a58 /drivers/usb/gadget/f_acm.c | |
parent | 9c610213370ad2e58a892f890a11a90615edf020 (diff) | |
download | linux-b97503ffa79f0a4aa13c7cd8b449b98d3077c78f.tar.xz |
USB: Interface Association Descriptors added to CDC & RNDIS
Without Interface Association Descriptor, the CDC serial and
RNDIS functions did not work correctly when added to a
composite gadget with other functions. This is because, it
defined two interfaces and some hosts tried to treat each
interface separatelly.
Signed-off-by: Michal Nazarewicz <m.nazarewicz@samsung.com>
Cc: David Brownell <dbrownell@users.sourceforge.net>
Cc: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/gadget/f_acm.c')
-rw-r--r-- | drivers/usb/gadget/f_acm.c | 28 |
1 files changed, 28 insertions, 0 deletions
diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c index 4e3657808b0f..d10353d46b86 100644 --- a/drivers/usb/gadget/f_acm.c +++ b/drivers/usb/gadget/f_acm.c @@ -4,6 +4,8 @@ * Copyright (C) 2003 Al Borchers (alborchers@steinerpoint.com) * Copyright (C) 2008 by David Brownell * Copyright (C) 2008 by Nokia Corporation + * Copyright (C) 2009 by Samsung Electronics + * Author: Michal Nazarewicz (m.nazarewicz@samsung.com) * * This software is distributed under the terms of the GNU General * Public License ("GPL") as published by the Free Software Foundation, @@ -99,6 +101,20 @@ static inline struct f_acm *port_to_acm(struct gserial *p) /* interface and class descriptors: */ +static struct usb_interface_assoc_descriptor +acm_iad_descriptor = { + .bLength = sizeof acm_iad_descriptor, + .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, + + /* .bFirstInterface = DYNAMIC, */ + .bInterfaceCount = 2, // control + data + .bFunctionClass = USB_CLASS_COMM, + .bFunctionSubClass = USB_CDC_SUBCLASS_ACM, + .bFunctionProtocol = USB_CDC_PROTO_NONE, + /* .iFunction = DYNAMIC */ +}; + + static struct usb_interface_descriptor acm_control_interface_desc __initdata = { .bLength = USB_DT_INTERFACE_SIZE, .bDescriptorType = USB_DT_INTERFACE, @@ -178,6 +194,7 @@ static struct usb_endpoint_descriptor acm_fs_out_desc __initdata = { }; static struct usb_descriptor_header *acm_fs_function[] __initdata = { + (struct usb_descriptor_header *) &acm_iad_descriptor, (struct usb_descriptor_header *) &acm_control_interface_desc, (struct usb_descriptor_header *) &acm_header_desc, (struct usb_descriptor_header *) &acm_call_mgmt_descriptor, @@ -216,6 +233,7 @@ static struct usb_endpoint_descriptor acm_hs_out_desc __initdata = { }; static struct usb_descriptor_header *acm_hs_function[] __initdata = { + (struct usb_descriptor_header *) &acm_iad_descriptor, (struct usb_descriptor_header *) &acm_control_interface_desc, (struct usb_descriptor_header *) &acm_header_desc, (struct usb_descriptor_header *) &acm_call_mgmt_descriptor, @@ -232,11 +250,13 @@ static struct usb_descriptor_header *acm_hs_function[] __initdata = { #define ACM_CTRL_IDX 0 #define ACM_DATA_IDX 1 +#define ACM_IAD_IDX 2 /* static strings, in UTF-8 */ static struct usb_string acm_string_defs[] = { [ACM_CTRL_IDX].s = "CDC Abstract Control Model (ACM)", [ACM_DATA_IDX].s = "CDC ACM Data", + [ACM_IAD_IDX ].s = "CDC Serial", { /* ZEROES END LIST */ }, }; @@ -563,6 +583,7 @@ acm_bind(struct usb_configuration *c, struct usb_function *f) if (status < 0) goto fail; acm->ctrl_id = status; + acm_iad_descriptor.bFirstInterface = status; acm_control_interface_desc.bInterfaceNumber = status; acm_union_desc .bMasterInterface0 = status; @@ -732,6 +753,13 @@ int __init acm_bind_config(struct usb_configuration *c, u8 port_num) acm_string_defs[ACM_DATA_IDX].id = status; acm_data_interface_desc.iInterface = status; + + status = usb_string_id(c->cdev); + if (status < 0) + return status; + acm_string_defs[ACM_IAD_IDX].id = status; + + acm_iad_descriptor.iFunction = status; } /* allocate and initialize one new instance */ |