2 * f_serial.c - generic USB serial function driver
4 * Copyright (C) 2003 Al Borchers (alborchers@steinerpoint.com)
5 * Copyright (C) 2008 by David Brownell
6 * Copyright (C) 2008 by Nokia Corporation
8 * This software is distributed under the terms of the GNU General
9 * Public License ("GPL") as published by the Free Software Foundation,
10 * either version 2 of that License or (at your option) any later version.
13 #include <linux/kernel.h>
14 #include <linux/device.h>
17 #include "gadget_chips.h"
21 * This function packages a simple "generic serial" port with no real
22 * control mechanisms, just raw data transfer over two bulk endpoints.
24 * Because it's not standardized, this isn't as interoperable as the
25 * CDC ACM driver. However, for many purposes it's just as functional
26 * if you can arrange appropriate host side drivers.
30 struct usb_endpoint_descriptor
*in
;
31 struct usb_endpoint_descriptor
*out
;
39 struct usb_descriptor_header
**fs_function
;
41 struct usb_descriptor_header
**hs_function
;
45 static inline struct f_gser
*func_to_gser(struct usb_function
*f
)
47 return container_of(f
, struct f_gser
, port
.func
);
50 /*-------------------------------------------------------------------------*/
52 /* interface descriptor: */
54 static struct usb_interface_descriptor gser_interface_desc __initdata
= {
55 .bLength
= USB_DT_INTERFACE_SIZE
,
56 .bDescriptorType
= USB_DT_INTERFACE
,
57 /* .bInterfaceNumber = DYNAMIC */
59 .bInterfaceClass
= USB_CLASS_VENDOR_SPEC
,
60 .bInterfaceSubClass
= 0,
61 .bInterfaceProtocol
= 0,
62 /* .iInterface = DYNAMIC */
65 /* full speed support: */
67 static struct usb_endpoint_descriptor gser_fs_in_desc __initdata
= {
68 .bLength
= USB_DT_ENDPOINT_SIZE
,
69 .bDescriptorType
= USB_DT_ENDPOINT
,
70 .bEndpointAddress
= USB_DIR_IN
,
71 .bmAttributes
= USB_ENDPOINT_XFER_BULK
,
74 static struct usb_endpoint_descriptor gser_fs_out_desc __initdata
= {
75 .bLength
= USB_DT_ENDPOINT_SIZE
,
76 .bDescriptorType
= USB_DT_ENDPOINT
,
77 .bEndpointAddress
= USB_DIR_OUT
,
78 .bmAttributes
= USB_ENDPOINT_XFER_BULK
,
81 static struct usb_descriptor_header
*gser_fs_function
[] __initdata
= {
82 (struct usb_descriptor_header
*) &gser_interface_desc
,
83 (struct usb_descriptor_header
*) &gser_fs_in_desc
,
84 (struct usb_descriptor_header
*) &gser_fs_out_desc
,
88 /* high speed support: */
90 static struct usb_endpoint_descriptor gser_hs_in_desc __initdata
= {
91 .bLength
= USB_DT_ENDPOINT_SIZE
,
92 .bDescriptorType
= USB_DT_ENDPOINT
,
93 .bmAttributes
= USB_ENDPOINT_XFER_BULK
,
94 .wMaxPacketSize
= __constant_cpu_to_le16(512),
97 static struct usb_endpoint_descriptor gser_hs_out_desc __initdata
= {
98 .bLength
= USB_DT_ENDPOINT_SIZE
,
99 .bDescriptorType
= USB_DT_ENDPOINT
,
100 .bmAttributes
= USB_ENDPOINT_XFER_BULK
,
101 .wMaxPacketSize
= __constant_cpu_to_le16(512),
104 static struct usb_descriptor_header
*gser_hs_function
[] __initdata
= {
105 (struct usb_descriptor_header
*) &gser_interface_desc
,
106 (struct usb_descriptor_header
*) &gser_hs_in_desc
,
107 (struct usb_descriptor_header
*) &gser_hs_out_desc
,
111 /* string descriptors: */
113 static struct usb_string gser_string_defs
[] = {
114 [0].s
= "Generic Serial",
115 { } /* end of list */
118 static struct usb_gadget_strings gser_string_table
= {
119 .language
= 0x0409, /* en-us */
120 .strings
= gser_string_defs
,
123 static struct usb_gadget_strings
*gser_strings
[] = {
128 /*-------------------------------------------------------------------------*/
130 static int gser_set_alt(struct usb_function
*f
, unsigned intf
, unsigned alt
)
132 struct f_gser
*gser
= func_to_gser(f
);
133 struct usb_composite_dev
*cdev
= f
->config
->cdev
;
135 /* we know alt == 0, so this is an activation or a reset */
137 if (gser
->port
.in
->driver_data
) {
138 DBG(cdev
, "reset generic ttyGS%d\n", gser
->port_num
);
139 gserial_disconnect(&gser
->port
);
141 DBG(cdev
, "activate generic ttyGS%d\n", gser
->port_num
);
142 gser
->port
.in_desc
= ep_choose(cdev
->gadget
,
143 gser
->hs
.in
, gser
->fs
.in
);
144 gser
->port
.out_desc
= ep_choose(cdev
->gadget
,
145 gser
->hs
.out
, gser
->fs
.out
);
147 gserial_connect(&gser
->port
, gser
->port_num
);
151 static void gser_disable(struct usb_function
*f
)
153 struct f_gser
*gser
= func_to_gser(f
);
154 struct usb_composite_dev
*cdev
= f
->config
->cdev
;
156 DBG(cdev
, "generic ttyGS%d deactivated\n", gser
->port_num
);
157 gserial_disconnect(&gser
->port
);
160 /*-------------------------------------------------------------------------*/
162 /* serial function driver setup/binding */
165 gser_bind(struct usb_configuration
*c
, struct usb_function
*f
)
167 struct usb_composite_dev
*cdev
= c
->cdev
;
168 struct f_gser
*gser
= func_to_gser(f
);
172 /* allocate instance-specific interface IDs */
173 status
= usb_interface_id(c
, f
);
176 gser
->data_id
= status
;
177 gser_interface_desc
.bInterfaceNumber
= status
;
181 /* allocate instance-specific endpoints */
182 ep
= usb_ep_autoconfig(cdev
->gadget
, &gser_fs_in_desc
);
186 ep
->driver_data
= cdev
; /* claim */
188 ep
= usb_ep_autoconfig(cdev
->gadget
, &gser_fs_out_desc
);
192 ep
->driver_data
= cdev
; /* claim */
194 /* copy descriptors, and track endpoint copies */
195 f
->descriptors
= usb_copy_descriptors(gser_fs_function
);
197 gser
->fs
.in
= usb_find_endpoint(gser_fs_function
,
198 f
->descriptors
, &gser_fs_in_desc
);
199 gser
->fs
.out
= usb_find_endpoint(gser_fs_function
,
200 f
->descriptors
, &gser_fs_out_desc
);
203 /* support all relevant hardware speeds... we expect that when
204 * hardware is dual speed, all bulk-capable endpoints work at
207 if (gadget_is_dualspeed(c
->cdev
->gadget
)) {
208 gser_hs_in_desc
.bEndpointAddress
=
209 gser_fs_in_desc
.bEndpointAddress
;
210 gser_hs_out_desc
.bEndpointAddress
=
211 gser_fs_out_desc
.bEndpointAddress
;
213 /* copy descriptors, and track endpoint copies */
214 f
->hs_descriptors
= usb_copy_descriptors(gser_hs_function
);
216 gser
->hs
.in
= usb_find_endpoint(gser_hs_function
,
217 f
->hs_descriptors
, &gser_hs_in_desc
);
218 gser
->hs
.out
= usb_find_endpoint(gser_hs_function
,
219 f
->hs_descriptors
, &gser_hs_out_desc
);
222 DBG(cdev
, "generic ttyGS%d: %s speed IN/%s OUT/%s\n",
224 gadget_is_dualspeed(c
->cdev
->gadget
) ? "dual" : "full",
225 gser
->port
.in
->name
, gser
->port
.out
->name
);
229 /* we might as well release our claims on endpoints */
231 gser
->port
.out
->driver_data
= NULL
;
233 gser
->port
.in
->driver_data
= NULL
;
235 ERROR(cdev
, "%s: can't bind, err %d\n", f
->name
, status
);
241 gser_unbind(struct usb_configuration
*c
, struct usb_function
*f
)
243 if (gadget_is_dualspeed(c
->cdev
->gadget
))
244 usb_free_descriptors(f
->hs_descriptors
);
245 usb_free_descriptors(f
->descriptors
);
246 kfree(func_to_gser(f
));
250 * gser_bind_config - add a generic serial function to a configuration
251 * @c: the configuration to support the serial instance
252 * @port_num: /dev/ttyGS* port this interface will use
253 * Context: single threaded during gadget setup
255 * Returns zero on success, else negative errno.
257 * Caller must have called @gserial_setup() with enough ports to
258 * handle all the ones it binds. Caller is also responsible
259 * for calling @gserial_cleanup() before module unload.
261 int __init
gser_bind_config(struct usb_configuration
*c
, u8 port_num
)
266 /* REVISIT might want instance-specific strings to help
267 * distinguish instances ...
270 /* maybe allocate device-global string ID */
271 if (gser_string_defs
[0].id
== 0) {
272 status
= usb_string_id(c
->cdev
);
275 gser_string_defs
[0].id
= status
;
278 /* allocate and initialize one new instance */
279 gser
= kzalloc(sizeof *gser
, GFP_KERNEL
);
283 gser
->port_num
= port_num
;
285 gser
->port
.func
.name
= "gser";
286 gser
->port
.func
.strings
= gser_strings
;
287 gser
->port
.func
.bind
= gser_bind
;
288 gser
->port
.func
.unbind
= gser_unbind
;
289 gser
->port
.func
.set_alt
= gser_set_alt
;
290 gser
->port
.func
.disable
= gser_disable
;
292 status
= usb_add_function(c
, &gser
->port
.func
);