aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget/f_acm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/gadget/f_acm.c')
-rw-r--r--drivers/usb/gadget/f_acm.c39
1 files changed, 30 insertions, 9 deletions
diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c
index 7953948bfe4a..400e1ebe6976 100644
--- a/drivers/usb/gadget/f_acm.c
+++ b/drivers/usb/gadget/f_acm.c
@@ -4,6 +4,8 @@
4 * Copyright (C) 2003 Al Borchers (alborchers@steinerpoint.com) 4 * Copyright (C) 2003 Al Borchers (alborchers@steinerpoint.com)
5 * Copyright (C) 2008 by David Brownell 5 * Copyright (C) 2008 by David Brownell
6 * Copyright (C) 2008 by Nokia Corporation 6 * Copyright (C) 2008 by Nokia Corporation
7 * Copyright (C) 2009 by Samsung Electronics
8 * Author: Michal Nazarewicz (m.nazarewicz@samsung.com)
7 * 9 *
8 * This software is distributed under the terms of the GNU General 10 * This software is distributed under the terms of the GNU General
9 * Public License ("GPL") as published by the Free Software Foundation, 11 * Public License ("GPL") as published by the Free Software Foundation,
@@ -12,6 +14,7 @@
12 14
13/* #define VERBOSE_DEBUG */ 15/* #define VERBOSE_DEBUG */
14 16
17#include <linux/slab.h>
15#include <linux/kernel.h> 18#include <linux/kernel.h>
16#include <linux/device.h> 19#include <linux/device.h>
17 20
@@ -99,6 +102,20 @@ static inline struct f_acm *port_to_acm(struct gserial *p)
99 102
100/* interface and class descriptors: */ 103/* interface and class descriptors: */
101 104
105static struct usb_interface_assoc_descriptor
106acm_iad_descriptor = {
107 .bLength = sizeof acm_iad_descriptor,
108 .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION,
109
110 /* .bFirstInterface = DYNAMIC, */
111 .bInterfaceCount = 2, // control + data
112 .bFunctionClass = USB_CLASS_COMM,
113 .bFunctionSubClass = USB_CDC_SUBCLASS_ACM,
114 .bFunctionProtocol = USB_CDC_PROTO_NONE,
115 /* .iFunction = DYNAMIC */
116};
117
118
102static struct usb_interface_descriptor acm_control_interface_desc __initdata = { 119static struct usb_interface_descriptor acm_control_interface_desc __initdata = {
103 .bLength = USB_DT_INTERFACE_SIZE, 120 .bLength = USB_DT_INTERFACE_SIZE,
104 .bDescriptorType = USB_DT_INTERFACE, 121 .bDescriptorType = USB_DT_INTERFACE,
@@ -178,6 +195,7 @@ static struct usb_endpoint_descriptor acm_fs_out_desc __initdata = {
178}; 195};
179 196
180static struct usb_descriptor_header *acm_fs_function[] __initdata = { 197static struct usb_descriptor_header *acm_fs_function[] __initdata = {
198 (struct usb_descriptor_header *) &acm_iad_descriptor,
181 (struct usb_descriptor_header *) &acm_control_interface_desc, 199 (struct usb_descriptor_header *) &acm_control_interface_desc,
182 (struct usb_descriptor_header *) &acm_header_desc, 200 (struct usb_descriptor_header *) &acm_header_desc,
183 (struct usb_descriptor_header *) &acm_call_mgmt_descriptor, 201 (struct usb_descriptor_header *) &acm_call_mgmt_descriptor,
@@ -216,6 +234,7 @@ static struct usb_endpoint_descriptor acm_hs_out_desc __initdata = {
216}; 234};
217 235
218static struct usb_descriptor_header *acm_hs_function[] __initdata = { 236static struct usb_descriptor_header *acm_hs_function[] __initdata = {
237 (struct usb_descriptor_header *) &acm_iad_descriptor,
219 (struct usb_descriptor_header *) &acm_control_interface_desc, 238 (struct usb_descriptor_header *) &acm_control_interface_desc,
220 (struct usb_descriptor_header *) &acm_header_desc, 239 (struct usb_descriptor_header *) &acm_header_desc,
221 (struct usb_descriptor_header *) &acm_call_mgmt_descriptor, 240 (struct usb_descriptor_header *) &acm_call_mgmt_descriptor,
@@ -232,11 +251,13 @@ static struct usb_descriptor_header *acm_hs_function[] __initdata = {
232 251
233#define ACM_CTRL_IDX 0 252#define ACM_CTRL_IDX 0
234#define ACM_DATA_IDX 1 253#define ACM_DATA_IDX 1
254#define ACM_IAD_IDX 2
235 255
236/* static strings, in UTF-8 */ 256/* static strings, in UTF-8 */
237static struct usb_string acm_string_defs[] = { 257static struct usb_string acm_string_defs[] = {
238 [ACM_CTRL_IDX].s = "CDC Abstract Control Model (ACM)", 258 [ACM_CTRL_IDX].s = "CDC Abstract Control Model (ACM)",
239 [ACM_DATA_IDX].s = "CDC ACM Data", 259 [ACM_DATA_IDX].s = "CDC ACM Data",
260 [ACM_IAD_IDX ].s = "CDC Serial",
240 { /* ZEROES END LIST */ }, 261 { /* ZEROES END LIST */ },
241}; 262};
242 263
@@ -432,7 +453,7 @@ static void acm_disable(struct usb_function *f)
432 * @length: size of data 453 * @length: size of data
433 * Context: irqs blocked, acm->lock held, acm_notify_req non-null 454 * Context: irqs blocked, acm->lock held, acm_notify_req non-null
434 * 455 *
435 * Returns zero on sucess or a negative errno. 456 * Returns zero on success or a negative errno.
436 * 457 *
437 * See section 6.3.5 of the CDC 1.1 specification for information 458 * See section 6.3.5 of the CDC 1.1 specification for information
438 * about the only notification we issue: SerialState change. 459 * about the only notification we issue: SerialState change.
@@ -563,6 +584,7 @@ acm_bind(struct usb_configuration *c, struct usb_function *f)
563 if (status < 0) 584 if (status < 0)
564 goto fail; 585 goto fail;
565 acm->ctrl_id = status; 586 acm->ctrl_id = status;
587 acm_iad_descriptor.bFirstInterface = status;
566 588
567 acm_control_interface_desc.bInterfaceNumber = status; 589 acm_control_interface_desc.bInterfaceNumber = status;
568 acm_union_desc .bMasterInterface0 = status; 590 acm_union_desc .bMasterInterface0 = status;
@@ -681,14 +703,6 @@ acm_unbind(struct usb_configuration *c, struct usb_function *f)
681/* Some controllers can't support CDC ACM ... */ 703/* Some controllers can't support CDC ACM ... */
682static inline bool can_support_cdc(struct usb_configuration *c) 704static inline bool can_support_cdc(struct usb_configuration *c)
683{ 705{
684 /* SH3 doesn't support multiple interfaces */
685 if (gadget_is_sh(c->cdev->gadget))
686 return false;
687
688 /* sa1100 doesn't have a third interrupt endpoint */
689 if (gadget_is_sa1100(c->cdev->gadget))
690 return false;
691
692 /* everything else is *probably* fine ... */ 706 /* everything else is *probably* fine ... */
693 return true; 707 return true;
694} 708}
@@ -732,6 +746,13 @@ int __init acm_bind_config(struct usb_configuration *c, u8 port_num)
732 acm_string_defs[ACM_DATA_IDX].id = status; 746 acm_string_defs[ACM_DATA_IDX].id = status;
733 747
734 acm_data_interface_desc.iInterface = status; 748 acm_data_interface_desc.iInterface = status;
749
750 status = usb_string_id(c->cdev);
751 if (status < 0)
752 return status;
753 acm_string_defs[ACM_IAD_IDX].id = status;
754
755 acm_iad_descriptor.iFunction = status;
735 } 756 }
736 757
737 /* allocate and initialize one new instance */ 758 /* allocate and initialize one new instance */