aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>2012-12-23 15:10:06 -0500
committerFelipe Balbi <balbi@ti.com>2013-01-21 13:52:43 -0500
commit19b10a8828a6cdd5a4e7e37babd5084d35641f87 (patch)
tree636a228ed32d975a8214639b17b4d7a595fdf7b4
parentb473577854fea63055ff9ab84f0f52a3e8aed15e (diff)
usb: gadget: allocate & giveback serial ports instead hard code them
This patch removes gserial_setup() and gserial_cleanup() and adds gserial_alloc_line() and gserial_free_line() to replace them. The initial setup of u_serial happens now on module load time. A maximum of four TTY ports can be requested which is the current limit. In theory we could extend this limit, the hard limit is the number of available endpoints. alloc_tty_driver() is now called at module init time with the max available ports. The per-line footprint here is on 32bit is 3 * size of pointer + 60 bytes (for cdevs). The remaining memory (struct gs_port) is allocated once a port is requested. With this change it is possible to load g_multi and g_serial at the same time. GS0 receives the module that is loaded first, GS1 is received by the next module and so on. With the configfs interface the port number can be exported and the device node is more predictable. Nothing changes for g_serial and friends as long as one module is used. Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Signed-off-by: Felipe Balbi <balbi@ti.com>
-rw-r--r--drivers/usb/gadget/acm_ms.c10
-rw-r--r--drivers/usb/gadget/cdc2.c9
-rw-r--r--drivers/usb/gadget/dbgp.c10
-rw-r--r--drivers/usb/gadget/f_acm.c3
-rw-r--r--drivers/usb/gadget/f_obex.c4
-rw-r--r--drivers/usb/gadget/f_serial.c4
-rw-r--r--drivers/usb/gadget/multi.c12
-rw-r--r--drivers/usb/gadget/nokia.c37
-rw-r--r--drivers/usb/gadget/serial.c31
-rw-r--r--drivers/usb/gadget/u_serial.c310
-rw-r--r--drivers/usb/gadget/u_serial.h8
11 files changed, 229 insertions, 209 deletions
diff --git a/drivers/usb/gadget/acm_ms.c b/drivers/usb/gadget/acm_ms.c
index 35cbe7283514..eb0fbdae5ccb 100644
--- a/drivers/usb/gadget/acm_ms.c
+++ b/drivers/usb/gadget/acm_ms.c
@@ -111,6 +111,7 @@ FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data);
111static struct fsg_common fsg_common; 111static struct fsg_common fsg_common;
112 112
113/*-------------------------------------------------------------------------*/ 113/*-------------------------------------------------------------------------*/
114static unsigned char tty_line;
114 115
115/* 116/*
116 * We _always_ have both ACM and mass storage functions. 117 * We _always_ have both ACM and mass storage functions.
@@ -125,7 +126,7 @@ static int __init acm_ms_do_config(struct usb_configuration *c)
125 } 126 }
126 127
127 128
128 status = acm_bind_config(c, 0); 129 status = acm_bind_config(c, tty_line);
129 if (status < 0) 130 if (status < 0)
130 return status; 131 return status;
131 132
@@ -152,7 +153,7 @@ static int __init acm_ms_bind(struct usb_composite_dev *cdev)
152 void *retp; 153 void *retp;
153 154
154 /* set up serial link layer */ 155 /* set up serial link layer */
155 status = gserial_setup(cdev->gadget, 1); 156 status = gserial_alloc_line(&tty_line);
156 if (status < 0) 157 if (status < 0)
157 return status; 158 return status;
158 159
@@ -188,14 +189,13 @@ static int __init acm_ms_bind(struct usb_composite_dev *cdev)
188fail1: 189fail1:
189 fsg_common_put(&fsg_common); 190 fsg_common_put(&fsg_common);
190fail0: 191fail0:
191 gserial_cleanup(); 192 gserial_free_line(tty_line);
192 return status; 193 return status;
193} 194}
194 195
195static int __exit acm_ms_unbind(struct usb_composite_dev *cdev) 196static int __exit acm_ms_unbind(struct usb_composite_dev *cdev)
196{ 197{
197 gserial_cleanup(); 198 gserial_free_line(tty_line);
198
199 return 0; 199 return 0;
200} 200}
201 201
diff --git a/drivers/usb/gadget/cdc2.c b/drivers/usb/gadget/cdc2.c
index 379df679ef30..16911a5aeb03 100644
--- a/drivers/usb/gadget/cdc2.c
+++ b/drivers/usb/gadget/cdc2.c
@@ -108,6 +108,7 @@ static u8 hostaddr[ETH_ALEN];
108 108
109/*-------------------------------------------------------------------------*/ 109/*-------------------------------------------------------------------------*/
110 110
111static unsigned char tty_line;
111/* 112/*
112 * We _always_ have both CDC ECM and CDC ACM functions. 113 * We _always_ have both CDC ECM and CDC ACM functions.
113 */ 114 */
@@ -124,7 +125,7 @@ static int __init cdc_do_config(struct usb_configuration *c)
124 if (status < 0) 125 if (status < 0)
125 return status; 126 return status;
126 127
127 status = acm_bind_config(c, 0); 128 status = acm_bind_config(c, tty_line);
128 if (status < 0) 129 if (status < 0)
129 return status; 130 return status;
130 131
@@ -157,7 +158,7 @@ static int __init cdc_bind(struct usb_composite_dev *cdev)
157 return status; 158 return status;
158 159
159 /* set up serial link layer */ 160 /* set up serial link layer */
160 status = gserial_setup(cdev->gadget, 1); 161 status = gserial_alloc_line(&tty_line);
161 if (status < 0) 162 if (status < 0)
162 goto fail0; 163 goto fail0;
163 164
@@ -183,7 +184,7 @@ static int __init cdc_bind(struct usb_composite_dev *cdev)
183 return 0; 184 return 0;
184 185
185fail1: 186fail1:
186 gserial_cleanup(); 187 gserial_free_line(tty_line);
187fail0: 188fail0:
188 gether_cleanup(); 189 gether_cleanup();
189 return status; 190 return status;
@@ -191,7 +192,7 @@ fail0:
191 192
192static int __exit cdc_unbind(struct usb_composite_dev *cdev) 193static int __exit cdc_unbind(struct usb_composite_dev *cdev)
193{ 194{
194 gserial_cleanup(); 195 gserial_free_line(tty_line);
195 gether_cleanup(); 196 gether_cleanup();
196 return 0; 197 return 0;
197} 198}
diff --git a/drivers/usb/gadget/dbgp.c b/drivers/usb/gadget/dbgp.c
index 41eb98df5644..986fc511a2ed 100644
--- a/drivers/usb/gadget/dbgp.c
+++ b/drivers/usb/gadget/dbgp.c
@@ -231,6 +231,10 @@ static void dbgp_unbind(struct usb_gadget *gadget)
231 gadget->ep0->driver_data = NULL; 231 gadget->ep0->driver_data = NULL;
232} 232}
233 233
234#ifdef CONFIG_USB_G_DBGP_SERIAL
235static unsigned char tty_line;
236#endif
237
234static int __init dbgp_configure_endpoints(struct usb_gadget *gadget) 238static int __init dbgp_configure_endpoints(struct usb_gadget *gadget)
235{ 239{
236 int stp; 240 int stp;
@@ -268,7 +272,7 @@ static int __init dbgp_configure_endpoints(struct usb_gadget *gadget)
268 dbgp.serial->in->desc = &i_desc; 272 dbgp.serial->in->desc = &i_desc;
269 dbgp.serial->out->desc = &o_desc; 273 dbgp.serial->out->desc = &o_desc;
270 274
271 if (gserial_setup(gadget, 1) < 0) { 275 if (gserial_alloc_line(&tty_line)) {
272 stp = 3; 276 stp = 3;
273 goto fail_3; 277 goto fail_3;
274 } 278 }
@@ -377,7 +381,7 @@ static int dbgp_setup(struct usb_gadget *gadget,
377#ifdef CONFIG_USB_G_DBGP_PRINTK 381#ifdef CONFIG_USB_G_DBGP_PRINTK
378 err = dbgp_enable_ep(); 382 err = dbgp_enable_ep();
379#else 383#else
380 err = gserial_connect(dbgp.serial, 0); 384 err = gserial_connect(dbgp.serial, tty_line);
381#endif 385#endif
382 if (err < 0) 386 if (err < 0)
383 goto fail; 387 goto fail;
@@ -420,7 +424,7 @@ static void __exit dbgp_exit(void)
420{ 424{
421 usb_gadget_unregister_driver(&dbgp_driver); 425 usb_gadget_unregister_driver(&dbgp_driver);
422#ifdef CONFIG_USB_G_DBGP_SERIAL 426#ifdef CONFIG_USB_G_DBGP_SERIAL
423 gserial_cleanup(); 427 gserial_free_line(tty_line);
424#endif 428#endif
425} 429}
426 430
diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c
index d4a7c1912105..3178fa70916e 100644
--- a/drivers/usb/gadget/f_acm.c
+++ b/drivers/usb/gadget/f_acm.c
@@ -719,9 +719,6 @@ acm_unbind(struct usb_configuration *c, struct usb_function *f)
719 * 719 *
720 * Returns zero on success, else negative errno. 720 * Returns zero on success, else negative errno.
721 * 721 *
722 * Caller must have called @gserial_setup() with enough ports to
723 * handle all the ones it binds. Caller is also responsible
724 * for calling @gserial_cleanup() before module unload.
725 */ 722 */
726int acm_bind_config(struct usb_configuration *c, u8 port_num) 723int acm_bind_config(struct usb_configuration *c, u8 port_num)
727{ 724{
diff --git a/drivers/usb/gadget/f_obex.c b/drivers/usb/gadget/f_obex.c
index d8dd8782768c..36a004563b82 100644
--- a/drivers/usb/gadget/f_obex.c
+++ b/drivers/usb/gadget/f_obex.c
@@ -406,10 +406,6 @@ static inline bool can_support_obex(struct usb_configuration *c)
406 * Context: single threaded during gadget setup 406 * Context: single threaded during gadget setup
407 * 407 *
408 * Returns zero on success, else negative errno. 408 * Returns zero on success, else negative errno.
409 *
410 * Caller must have called @gserial_setup() with enough ports to
411 * handle all the ones it binds. Caller is also responsible
412 * for calling @gserial_cleanup() before module unload.
413 */ 409 */
414int __init obex_bind_config(struct usb_configuration *c, u8 port_num) 410int __init obex_bind_config(struct usb_configuration *c, u8 port_num)
415{ 411{
diff --git a/drivers/usb/gadget/f_serial.c b/drivers/usb/gadget/f_serial.c
index 98fa7795df5f..da33cfb3031d 100644
--- a/drivers/usb/gadget/f_serial.c
+++ b/drivers/usb/gadget/f_serial.c
@@ -260,10 +260,6 @@ gser_unbind(struct usb_configuration *c, struct usb_function *f)
260 * Context: single threaded during gadget setup 260 * Context: single threaded during gadget setup
261 * 261 *
262 * Returns zero on success, else negative errno. 262 * Returns zero on success, else negative errno.
263 *
264 * Caller must have called @gserial_setup() with enough ports to
265 * handle all the ones it binds. Caller is also responsible
266 * for calling @gserial_cleanup() before module unload.
267 */ 263 */
268int __init gser_bind_config(struct usb_configuration *c, u8 port_num) 264int __init gser_bind_config(struct usb_configuration *c, u8 port_num)
269{ 265{
diff --git a/drivers/usb/gadget/multi.c b/drivers/usb/gadget/multi.c
index 00667911100d..9ca0ac0334e7 100644
--- a/drivers/usb/gadget/multi.c
+++ b/drivers/usb/gadget/multi.c
@@ -136,6 +136,7 @@ static struct fsg_common fsg_common;
136 136
137static u8 hostaddr[ETH_ALEN]; 137static u8 hostaddr[ETH_ALEN];
138 138
139static unsigned char tty_line;
139 140
140/********** RNDIS **********/ 141/********** RNDIS **********/
141 142
@@ -154,7 +155,7 @@ static __init int rndis_do_config(struct usb_configuration *c)
154 if (ret < 0) 155 if (ret < 0)
155 return ret; 156 return ret;
156 157
157 ret = acm_bind_config(c, 0); 158 ret = acm_bind_config(c, tty_line);
158 if (ret < 0) 159 if (ret < 0)
159 return ret; 160 return ret;
160 161
@@ -205,7 +206,7 @@ static __init int cdc_do_config(struct usb_configuration *c)
205 if (ret < 0) 206 if (ret < 0)
206 return ret; 207 return ret;
207 208
208 ret = acm_bind_config(c, 0); 209 ret = acm_bind_config(c, tty_line);
209 if (ret < 0) 210 if (ret < 0)
210 return ret; 211 return ret;
211 212
@@ -242,7 +243,6 @@ static int cdc_config_register(struct usb_composite_dev *cdev)
242 243
243/****************************** Gadget Bind ******************************/ 244/****************************** Gadget Bind ******************************/
244 245
245
246static int __ref multi_bind(struct usb_composite_dev *cdev) 246static int __ref multi_bind(struct usb_composite_dev *cdev)
247{ 247{
248 struct usb_gadget *gadget = cdev->gadget; 248 struct usb_gadget *gadget = cdev->gadget;
@@ -260,7 +260,7 @@ static int __ref multi_bind(struct usb_composite_dev *cdev)
260 return status; 260 return status;
261 261
262 /* set up serial link layer */ 262 /* set up serial link layer */
263 status = gserial_setup(cdev->gadget, 1); 263 status = gserial_alloc_line(&tty_line);
264 if (status < 0) 264 if (status < 0)
265 goto fail0; 265 goto fail0;
266 266
@@ -300,7 +300,7 @@ static int __ref multi_bind(struct usb_composite_dev *cdev)
300fail2: 300fail2:
301 fsg_common_put(&fsg_common); 301 fsg_common_put(&fsg_common);
302fail1: 302fail1:
303 gserial_cleanup(); 303 gserial_free_line(tty_line);
304fail0: 304fail0:
305 gether_cleanup(); 305 gether_cleanup();
306 return status; 306 return status;
@@ -308,7 +308,7 @@ fail0:
308 308
309static int __exit multi_unbind(struct usb_composite_dev *cdev) 309static int __exit multi_unbind(struct usb_composite_dev *cdev)
310{ 310{
311 gserial_cleanup(); 311 gserial_free_line(tty_line);
312 gether_cleanup(); 312 gether_cleanup();
313 return 0; 313 return 0;
314} 314}
diff --git a/drivers/usb/gadget/nokia.c b/drivers/usb/gadget/nokia.c
index 48f0d5c372a8..084d0d7cb8fa 100644
--- a/drivers/usb/gadget/nokia.c
+++ b/drivers/usb/gadget/nokia.c
@@ -100,6 +100,15 @@ MODULE_LICENSE("GPL");
100 100
101static u8 hostaddr[ETH_ALEN]; 101static u8 hostaddr[ETH_ALEN];
102 102
103enum {
104 TTY_PORT_OBEX0,
105 TTY_PORT_OBEX1,
106 TTY_PORT_ACM,
107 TTY_PORTS_MAX,
108};
109
110static unsigned char tty_lines[TTY_PORTS_MAX];
111
103static int __init nokia_bind_config(struct usb_configuration *c) 112static int __init nokia_bind_config(struct usb_configuration *c)
104{ 113{
105 int status = 0; 114 int status = 0;
@@ -108,15 +117,15 @@ static int __init nokia_bind_config(struct usb_configuration *c)
108 if (status) 117 if (status)
109 printk(KERN_DEBUG "could not bind phonet config\n"); 118 printk(KERN_DEBUG "could not bind phonet config\n");
110 119
111 status = obex_bind_config(c, 0); 120 status = obex_bind_config(c, tty_lines[TTY_PORT_OBEX0]);
112 if (status) 121 if (status)
113 printk(KERN_DEBUG "could not bind obex config %d\n", 0); 122 printk(KERN_DEBUG "could not bind obex config %d\n", 0);
114 123
115 status = obex_bind_config(c, 1); 124 status = obex_bind_config(c, tty_lines[TTY_PORT_OBEX1]);
116 if (status) 125 if (status)
117 printk(KERN_DEBUG "could not bind obex config %d\n", 0); 126 printk(KERN_DEBUG "could not bind obex config %d\n", 0);
118 127
119 status = acm_bind_config(c, 2); 128 status = acm_bind_config(c, tty_lines[TTY_PORT_ACM]);
120 if (status) 129 if (status)
121 printk(KERN_DEBUG "could not bind acm config\n"); 130 printk(KERN_DEBUG "could not bind acm config\n");
122 131
@@ -147,14 +156,17 @@ static int __init nokia_bind(struct usb_composite_dev *cdev)
147{ 156{
148 struct usb_gadget *gadget = cdev->gadget; 157 struct usb_gadget *gadget = cdev->gadget;
149 int status; 158 int status;
159 int cur_line;
150 160
151 status = gphonet_setup(cdev->gadget); 161 status = gphonet_setup(cdev->gadget);
152 if (status < 0) 162 if (status < 0)
153 goto err_phonet; 163 goto err_phonet;
154 164
155 status = gserial_setup(cdev->gadget, 3); 165 for (cur_line = 0; cur_line < TTY_PORTS_MAX; cur_line++) {
156 if (status < 0) 166 status = gserial_alloc_line(&tty_lines[cur_line]);
157 goto err_serial; 167 if (status)
168 goto err_ether;
169 }
158 170
159 status = gether_setup(cdev->gadget, hostaddr); 171 status = gether_setup(cdev->gadget, hostaddr);
160 if (status < 0) 172 if (status < 0)
@@ -191,8 +203,10 @@ static int __init nokia_bind(struct usb_composite_dev *cdev)
191err_usb: 203err_usb:
192 gether_cleanup(); 204 gether_cleanup();
193err_ether: 205err_ether:
194 gserial_cleanup(); 206 cur_line--;
195err_serial: 207 while (cur_line >= 0)
208 gserial_free_line(tty_lines[cur_line--]);
209
196 gphonet_cleanup(); 210 gphonet_cleanup();
197err_phonet: 211err_phonet:
198 return status; 212 return status;
@@ -200,8 +214,13 @@ err_phonet:
200 214
201static int __exit nokia_unbind(struct usb_composite_dev *cdev) 215static int __exit nokia_unbind(struct usb_composite_dev *cdev)
202{ 216{
217 int i;
218
203 gphonet_cleanup(); 219 gphonet_cleanup();
204 gserial_cleanup(); 220
221 for (i = 0; i < TTY_PORTS_MAX; i++)
222 gserial_free_line(tty_lines[i]);
223
205 gether_cleanup(); 224 gether_cleanup();
206 225
207 return 0; 226 return 0;
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
index 4816f494fc4d..a883562f6a89 100644
--- a/drivers/usb/gadget/serial.c
+++ b/drivers/usb/gadget/serial.c
@@ -127,6 +127,7 @@ module_param(n_ports, uint, 0);
127MODULE_PARM_DESC(n_ports, "number of ports to create, default=1"); 127MODULE_PARM_DESC(n_ports, "number of ports to create, default=1");
128 128
129/*-------------------------------------------------------------------------*/ 129/*-------------------------------------------------------------------------*/
130static unsigned char tty_lines[MAX_U_SERIAL_PORTS];
130 131
131static int __init serial_bind_acm_config(struct usb_configuration *c) 132static int __init serial_bind_acm_config(struct usb_configuration *c)
132{ 133{
@@ -134,7 +135,7 @@ static int __init serial_bind_acm_config(struct usb_configuration *c)
134 int status = 0; 135 int status = 0;
135 136
136 for (i = 0; i < n_ports && status == 0; i++) 137 for (i = 0; i < n_ports && status == 0; i++)
137 status = acm_bind_config(c, i); 138 status = acm_bind_config(c, tty_lines[i]);
138 return status; 139 return status;
139} 140}
140 141
@@ -144,7 +145,7 @@ static int __init serial_bind_obex_config(struct usb_configuration *c)
144 int status = 0; 145 int status = 0;
145 146
146 for (i = 0; i < n_ports && status == 0; i++) 147 for (i = 0; i < n_ports && status == 0; i++)
147 status = obex_bind_config(c, i); 148 status = obex_bind_config(c, tty_lines[i]);
148 return status; 149 return status;
149} 150}
150 151
@@ -154,7 +155,7 @@ static int __init serial_bind_gser_config(struct usb_configuration *c)
154 int status = 0; 155 int status = 0;
155 156
156 for (i = 0; i < n_ports && status == 0; i++) 157 for (i = 0; i < n_ports && status == 0; i++)
157 status = gser_bind_config(c, i); 158 status = gser_bind_config(c, tty_lines[i]);
158 return status; 159 return status;
159} 160}
160 161
@@ -165,13 +166,25 @@ static struct usb_configuration serial_config_driver = {
165 .bmAttributes = USB_CONFIG_ATT_SELFPOWER, 166 .bmAttributes = USB_CONFIG_ATT_SELFPOWER,
166}; 167};
167 168
169static int gs_unbind(struct usb_composite_dev *cdev)
170{
171 int i;
172
173 for (i = 0; i < n_ports; i++)
174 gserial_free_line(tty_lines[i]);
175 return 0;
176}
177
168static int __init gs_bind(struct usb_composite_dev *cdev) 178static int __init gs_bind(struct usb_composite_dev *cdev)
169{ 179{
170 int status; 180 int status;
181 int cur_line;
171 182
172 status = gserial_setup(cdev->gadget, n_ports); 183 for (cur_line = 0; cur_line < n_ports; cur_line++) {
173 if (status < 0) 184 status = gserial_alloc_line(&tty_lines[cur_line]);
174 return status; 185 if (status)
186 goto fail;
187 }
175 188
176 /* Allocate string descriptor numbers ... note that string 189 /* Allocate string descriptor numbers ... note that string
177 * contents can be overridden by the composite_dev glue. 190 * contents can be overridden by the composite_dev glue.
@@ -209,7 +222,9 @@ static int __init gs_bind(struct usb_composite_dev *cdev)
209 return 0; 222 return 0;
210 223
211fail: 224fail:
212 gserial_cleanup(); 225 cur_line--;
226 while (cur_line >= 0)
227 gserial_free_line(tty_lines[cur_line--]);
213 return status; 228 return status;
214} 229}
215 230
@@ -219,6 +234,7 @@ static __refdata struct usb_composite_driver gserial_driver = {
219 .strings = dev_strings, 234 .strings = dev_strings,
220 .max_speed = USB_SPEED_SUPER, 235 .max_speed = USB_SPEED_SUPER,
221 .bind = gs_bind, 236 .bind = gs_bind,
237 .unbind = gs_unbind,
222}; 238};
223 239
224static int __init init(void) 240static int __init init(void)
@@ -254,6 +270,5 @@ module_init(init);
254static void __exit cleanup(void) 270static void __exit cleanup(void)
255{ 271{
256 usb_composite_unregister(&gserial_driver); 272 usb_composite_unregister(&gserial_driver);
257 gserial_cleanup();
258} 273}
259module_exit(cleanup); 274module_exit(cleanup);
diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c
index 1662d839a1d6..ea360fda2e14 100644
--- a/drivers/usb/gadget/u_serial.c
+++ b/drivers/usb/gadget/u_serial.c
@@ -36,11 +36,12 @@
36 * "serial port" functionality through the USB gadget stack. Each such 36 * "serial port" functionality through the USB gadget stack. Each such
37 * port is exposed through a /dev/ttyGS* node. 37 * port is exposed through a /dev/ttyGS* node.
38 * 38 *
39 * After initialization (gserial_setup), these TTY port devices stay 39 * After this module has been loaded, the individual TTY port can be requested
40 * available until they are removed (gserial_cleanup). Each one may be 40 * (gserial_alloc_line()) and it will stay available until they are removed
41 * connected to a USB function (gserial_connect), or disconnected (with 41 * (gserial_free_line()). Each one may be connected to a USB function
42 * gserial_disconnect) when the USB host issues a config change event. 42 * (gserial_connect), or disconnected (with gserial_disconnect) when the USB
43 * Data can only flow when the port is connected to the host. 43 * host issues a config change event. Data can only flow when the port is
44 * connected to the host.
44 * 45 *
45 * A given TTY port can be made available in multiple configurations. 46 * A given TTY port can be made available in multiple configurations.
46 * For example, each one might expose a ttyGS0 node which provides a 47 * For example, each one might expose a ttyGS0 node which provides a
@@ -120,13 +121,10 @@ struct gs_port {
120 struct usb_cdc_line_coding port_line_coding; /* 8-N-1 etc */ 121 struct usb_cdc_line_coding port_line_coding; /* 8-N-1 etc */
121}; 122};
122 123
123/* increase N_PORTS if you need more */
124#define N_PORTS 4
125static struct portmaster { 124static struct portmaster {
126 struct mutex lock; /* protect open/close */ 125 struct mutex lock; /* protect open/close */
127 struct gs_port *port; 126 struct gs_port *port;
128} ports[N_PORTS]; 127} ports[MAX_U_SERIAL_PORTS];
129static unsigned n_ports;
130 128
131#define GS_CLOSE_TIMEOUT 15 /* seconds */ 129#define GS_CLOSE_TIMEOUT 15 /* seconds */
132 130
@@ -1033,10 +1031,19 @@ static int
1033gs_port_alloc(unsigned port_num, struct usb_cdc_line_coding *coding) 1031gs_port_alloc(unsigned port_num, struct usb_cdc_line_coding *coding)
1034{ 1032{
1035 struct gs_port *port; 1033 struct gs_port *port;
1034 int ret = 0;
1035
1036 mutex_lock(&ports[port_num].lock);
1037 if (ports[port_num].port) {
1038 ret = -EBUSY;
1039 goto out;
1040 }
1036 1041
1037 port = kzalloc(sizeof(struct gs_port), GFP_KERNEL); 1042 port = kzalloc(sizeof(struct gs_port), GFP_KERNEL);
1038 if (port == NULL) 1043 if (port == NULL) {
1039 return -ENOMEM; 1044 ret = -ENOMEM;
1045 goto out;
1046 }
1040 1047
1041 tty_port_init(&port->port); 1048 tty_port_init(&port->port);
1042 spin_lock_init(&port->port_lock); 1049 spin_lock_init(&port->port_lock);
@@ -1052,114 +1059,10 @@ gs_port_alloc(unsigned port_num, struct usb_cdc_line_coding *coding)
1052 port->port_line_coding = *coding; 1059 port->port_line_coding = *coding;
1053 1060
1054 ports[port_num].port = port; 1061 ports[port_num].port = port;
1055 1062out:
1056 return 0; 1063 mutex_unlock(&ports[port_num].lock);
1057} 1064 return ret;
1058
1059/**
1060 * gserial_setup - initialize TTY driver for one or more ports
1061 * @g: gadget to associate with these ports
1062 * @count: how many ports to support
1063 * Context: may sleep
1064 *
1065 * The TTY stack needs to know in advance how many devices it should
1066 * plan to manage. Use this call to set up the ports you will be
1067 * exporting through USB. Later, connect them to functions based
1068 * on what configuration is activated by the USB host; and disconnect
1069 * them as appropriate.
1070 *
1071 * An example would be a two-configuration device in which both
1072 * configurations expose port 0, but through different functions.
1073 * One configuration could even expose port 1 while the other
1074 * one doesn't.
1075 *
1076 * Returns negative errno or zero.
1077 */
1078int gserial_setup(struct usb_gadget *g, unsigned count)
1079{
1080 unsigned i;
1081 struct usb_cdc_line_coding coding;
1082 int status;
1083
1084 if (count == 0 || count > N_PORTS)
1085 return -EINVAL;
1086
1087 if (gs_tty_driver)
1088 return -EBUSY;
1089
1090 gs_tty_driver = alloc_tty_driver(count);
1091 if (!gs_tty_driver)
1092 return -ENOMEM;
1093
1094 gs_tty_driver->driver_name = "g_serial";
1095 gs_tty_driver->name = PREFIX;
1096 /* uses dynamically assigned dev_t values */
1097
1098 gs_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
1099 gs_tty_driver->subtype = SERIAL_TYPE_NORMAL;
1100 gs_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
1101 gs_tty_driver->init_termios = tty_std_termios;
1102
1103 /* 9600-8-N-1 ... matches defaults expected by "usbser.sys" on
1104 * MS-Windows. Otherwise, most of these flags shouldn't affect
1105 * anything unless we were to actually hook up to a serial line.
1106 */
1107 gs_tty_driver->init_termios.c_cflag =
1108 B9600 | CS8 | CREAD | HUPCL | CLOCAL;
1109 gs_tty_driver->init_termios.c_ispeed = 9600;
1110 gs_tty_driver->init_termios.c_ospeed = 9600;
1111
1112 coding.dwDTERate = cpu_to_le32(9600);
1113 coding.bCharFormat = 8;
1114 coding.bParityType = USB_CDC_NO_PARITY;
1115 coding.bDataBits = USB_CDC_1_STOP_BITS;
1116
1117 tty_set_operations(gs_tty_driver, &gs_tty_ops);
1118
1119 /* make devices be openable */
1120 for (i = 0; i < count; i++) {
1121 mutex_init(&ports[i].lock);
1122 status = gs_port_alloc(i, &coding);
1123 if (status) {
1124 count = i;
1125 goto fail;
1126 }
1127 }
1128 n_ports = count;
1129
1130 /* export the driver ... */
1131 status = tty_register_driver(gs_tty_driver);
1132 if (status) {
1133 pr_err("%s: cannot register, err %d\n",
1134 __func__, status);
1135 goto fail;
1136 }
1137
1138 /* ... and sysfs class devices, so mdev/udev make /dev/ttyGS* */
1139 for (i = 0; i < count; i++) {
1140 struct device *tty_dev;
1141
1142 tty_dev = tty_port_register_device(&ports[i].port->port,
1143 gs_tty_driver, i, &g->dev);
1144 if (IS_ERR(tty_dev))
1145 pr_warning("%s: no classdev for port %d, err %ld\n",
1146 __func__, i, PTR_ERR(tty_dev));
1147 }
1148
1149 pr_debug("%s: registered %d ttyGS* device%s\n", __func__,
1150 count, (count == 1) ? "" : "s");
1151
1152 return status;
1153fail:
1154 while (count--) {
1155 tty_port_destroy(&ports[count].port->port);
1156 kfree(ports[count].port);
1157 }
1158 put_tty_driver(gs_tty_driver);
1159 gs_tty_driver = NULL;
1160 return status;
1161} 1065}
1162EXPORT_SYMBOL_GPL(gserial_setup);
1163 1066
1164static int gs_closed(struct gs_port *port) 1067static int gs_closed(struct gs_port *port)
1165{ 1068{
@@ -1171,56 +1074,77 @@ static int gs_closed(struct gs_port *port)
1171 return cond; 1074 return cond;
1172} 1075}
1173 1076
1174/** 1077static void gserial_free_port(struct gs_port *port)
1175 * gserial_cleanup - remove TTY-over-USB driver and devices 1078{
1176 * Context: may sleep 1079 tasklet_kill(&port->push);
1177 * 1080 /* wait for old opens to finish */
1178 * This is called to free all resources allocated by @gserial_setup(). 1081 wait_event(port->port.close_wait, gs_closed(port));
1179 * Accordingly, it may need to wait until some open /dev/ files have 1082 WARN_ON(port->port_usb != NULL);
1180 * closed. 1083 tty_port_destroy(&port->port);
1181 * 1084 kfree(port);
1182 * The caller must have issued @gserial_disconnect() for any ports 1085}
1183 * that had previously been connected, so that there is never any 1086
1184 * I/O pending when it's called. 1087void gserial_free_line(unsigned char port_num)
1185 */
1186void gserial_cleanup(void)
1187{ 1088{
1188 unsigned i;
1189 struct gs_port *port; 1089 struct gs_port *port;
1190 1090
1191 if (!gs_tty_driver) 1091 mutex_lock(&ports[port_num].lock);
1092 if (WARN_ON(!ports[port_num].port)) {
1093 mutex_unlock(&ports[port_num].lock);
1192 return; 1094 return;
1095 }
1096 port = ports[port_num].port;
1097 ports[port_num].port = NULL;
1098 mutex_unlock(&ports[port_num].lock);
1193 1099
1194 /* start sysfs and /dev/ttyGS* node removal */ 1100 gserial_free_port(port);
1195 for (i = 0; i < n_ports; i++) 1101 tty_unregister_device(gs_tty_driver, port_num);
1196 tty_unregister_device(gs_tty_driver, i); 1102}
1197 1103EXPORT_SYMBOL_GPL(gserial_free_line);
1198 for (i = 0; i < n_ports; i++) {
1199 /* prevent new opens */
1200 mutex_lock(&ports[i].lock);
1201 port = ports[i].port;
1202 ports[i].port = NULL;
1203 mutex_unlock(&ports[i].lock);
1204
1205 tasklet_kill(&port->push);
1206 1104
1207 /* wait for old opens to finish */ 1105int gserial_alloc_line(unsigned char *line_num)
1208 wait_event(port->port.close_wait, gs_closed(port)); 1106{
1107 struct usb_cdc_line_coding coding;
1108 struct device *tty_dev;
1109 int ret;
1110 int port_num;
1209 1111
1210 WARN_ON(port->port_usb != NULL); 1112 coding.dwDTERate = cpu_to_le32(9600);
1113 coding.bCharFormat = 8;
1114 coding.bParityType = USB_CDC_NO_PARITY;
1115 coding.bDataBits = USB_CDC_1_STOP_BITS;
1211 1116
1212 tty_port_destroy(&port->port); 1117 for (port_num = 0; port_num < MAX_U_SERIAL_PORTS; port_num++) {
1213 kfree(port); 1118 ret = gs_port_alloc(port_num, &coding);
1119 if (ret == -EBUSY)
1120 continue;
1121 if (ret)
1122 return ret;
1123 break;
1214 } 1124 }
1215 n_ports = 0; 1125 if (ret)
1126 return ret;
1216 1127
1217 tty_unregister_driver(gs_tty_driver); 1128 /* ... and sysfs class devices, so mdev/udev make /dev/ttyGS* */
1218 put_tty_driver(gs_tty_driver);
1219 gs_tty_driver = NULL;
1220 1129
1221 pr_debug("%s: cleaned up ttyGS* support\n", __func__); 1130 tty_dev = tty_port_register_device(&ports[port_num].port->port,
1131 gs_tty_driver, port_num, NULL);
1132 if (IS_ERR(tty_dev)) {
1133 struct gs_port *port;
1134 pr_err("%s: failed to register tty for port %d, err %ld\n",
1135 __func__, port_num, PTR_ERR(tty_dev));
1136
1137 ret = PTR_ERR(tty_dev);
1138 port = ports[port_num].port;
1139 ports[port_num].port = NULL;
1140 gserial_free_port(port);
1141 goto err;
1142 }
1143 *line_num = port_num;
1144err:
1145 return ret;
1222} 1146}
1223EXPORT_SYMBOL_GPL(gserial_cleanup); 1147EXPORT_SYMBOL_GPL(gserial_alloc_line);
1224 1148
1225/** 1149/**
1226 * gserial_connect - notify TTY I/O glue that USB link is active 1150 * gserial_connect - notify TTY I/O glue that USB link is active
@@ -1237,8 +1161,8 @@ EXPORT_SYMBOL_GPL(gserial_cleanup);
1237 * 1161 *
1238 * Caller needs to have set up the endpoints and USB function in @dev 1162 * Caller needs to have set up the endpoints and USB function in @dev
1239 * before calling this, as well as the appropriate (speed-specific) 1163 * before calling this, as well as the appropriate (speed-specific)
1240 * endpoint descriptors, and also have set up the TTY driver by calling 1164 * endpoint descriptors, and also have allocate @port_num by calling
1241 * @gserial_setup(). 1165 * @gserial_alloc_line().
1242 * 1166 *
1243 * Returns negative errno or zero. 1167 * Returns negative errno or zero.
1244 * On success, ep->driver_data will be overwritten. 1168 * On success, ep->driver_data will be overwritten.
@@ -1249,11 +1173,18 @@ int gserial_connect(struct gserial *gser, u8 port_num)
1249 unsigned long flags; 1173 unsigned long flags;
1250 int status; 1174 int status;
1251 1175
1252 if (!gs_tty_driver || port_num >= n_ports) 1176 if (port_num >= MAX_U_SERIAL_PORTS)
1253 return -ENXIO; 1177 return -ENXIO;
1254 1178
1255 /* we "know" gserial_cleanup() hasn't been called */
1256 port = ports[port_num].port; 1179 port = ports[port_num].port;
1180 if (!port) {
1181 pr_err("serial line %d not allocated.\n", port_num);
1182 return -EINVAL;
1183 }
1184 if (port->port_usb) {
1185 pr_err("serial line %d is in use.\n", port_num);
1186 return -EBUSY;
1187 }
1257 1188
1258 /* activate the endpoints */ 1189 /* activate the endpoints */
1259 status = usb_ep_enable(gser->in); 1190 status = usb_ep_enable(gser->in);
@@ -1357,4 +1288,63 @@ void gserial_disconnect(struct gserial *gser)
1357} 1288}
1358EXPORT_SYMBOL_GPL(gserial_disconnect); 1289EXPORT_SYMBOL_GPL(gserial_disconnect);
1359 1290
1291int userial_init(void)
1292{
1293 unsigned i;
1294 int status;
1295
1296 gs_tty_driver = alloc_tty_driver(MAX_U_SERIAL_PORTS);
1297 if (!gs_tty_driver)
1298 return -ENOMEM;
1299
1300 gs_tty_driver->driver_name = "g_serial";
1301 gs_tty_driver->name = PREFIX;
1302 /* uses dynamically assigned dev_t values */
1303
1304 gs_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
1305 gs_tty_driver->subtype = SERIAL_TYPE_NORMAL;
1306 gs_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
1307 gs_tty_driver->init_termios = tty_std_termios;
1308
1309 /* 9600-8-N-1 ... matches defaults expected by "usbser.sys" on
1310 * MS-Windows. Otherwise, most of these flags shouldn't affect
1311 * anything unless we were to actually hook up to a serial line.
1312 */
1313 gs_tty_driver->init_termios.c_cflag =
1314 B9600 | CS8 | CREAD | HUPCL | CLOCAL;
1315 gs_tty_driver->init_termios.c_ispeed = 9600;
1316 gs_tty_driver->init_termios.c_ospeed = 9600;
1317
1318 tty_set_operations(gs_tty_driver, &gs_tty_ops);
1319 for (i = 0; i < MAX_U_SERIAL_PORTS; i++)
1320 mutex_init(&ports[i].lock);
1321
1322 /* export the driver ... */
1323 status = tty_register_driver(gs_tty_driver);
1324 if (status) {
1325 pr_err("%s: cannot register, err %d\n",
1326 __func__, status);
1327 goto fail;
1328 }
1329
1330 pr_debug("%s: registered %d ttyGS* device%s\n", __func__,
1331 MAX_U_SERIAL_PORTS,
1332 (MAX_U_SERIAL_PORTS == 1) ? "" : "s");
1333
1334 return status;
1335fail:
1336 put_tty_driver(gs_tty_driver);
1337 gs_tty_driver = NULL;
1338 return status;
1339}
1340module_init(userial_init);
1341
1342static void userial_cleanup(void)
1343{
1344 tty_unregister_driver(gs_tty_driver);
1345 put_tty_driver(gs_tty_driver);
1346 gs_tty_driver = NULL;
1347}
1348module_exit(userial_cleanup);
1349
1360MODULE_LICENSE("GPL"); 1350MODULE_LICENSE("GPL");
diff --git a/drivers/usb/gadget/u_serial.h b/drivers/usb/gadget/u_serial.h
index 9b0fe6450fbf..f06ee9a5db51 100644
--- a/drivers/usb/gadget/u_serial.h
+++ b/drivers/usb/gadget/u_serial.h
@@ -15,6 +15,8 @@
15#include <linux/usb/composite.h> 15#include <linux/usb/composite.h>
16#include <linux/usb/cdc.h> 16#include <linux/usb/cdc.h>
17 17
18#define MAX_U_SERIAL_PORTS 4
19
18/* 20/*
19 * One non-multiplexed "serial" I/O port ... there can be several of these 21 * One non-multiplexed "serial" I/O port ... there can be several of these
20 * on any given USB peripheral device, if it provides enough endpoints. 22 * on any given USB peripheral device, if it provides enough endpoints.
@@ -49,9 +51,9 @@ struct gserial {
49struct usb_request *gs_alloc_req(struct usb_ep *ep, unsigned len, gfp_t flags); 51struct usb_request *gs_alloc_req(struct usb_ep *ep, unsigned len, gfp_t flags);
50void gs_free_req(struct usb_ep *, struct usb_request *req); 52void gs_free_req(struct usb_ep *, struct usb_request *req);
51 53
52/* port setup/teardown is handled by gadget driver */ 54/* management of individual TTY ports */
53int gserial_setup(struct usb_gadget *g, unsigned n_ports); 55int gserial_alloc_line(unsigned char *port_line);
54void gserial_cleanup(void); 56void gserial_free_line(unsigned char port_line);
55 57
56/* connect/disconnect is handled by individual functions */ 58/* connect/disconnect is handled by individual functions */
57int gserial_connect(struct gserial *, u8 port_num); 59int gserial_connect(struct gserial *, u8 port_num);