diff options
-rw-r--r-- | drivers/usb/gadget/acm_ms.c | 10 | ||||
-rw-r--r-- | drivers/usb/gadget/cdc2.c | 9 | ||||
-rw-r--r-- | drivers/usb/gadget/dbgp.c | 10 | ||||
-rw-r--r-- | drivers/usb/gadget/f_acm.c | 3 | ||||
-rw-r--r-- | drivers/usb/gadget/f_obex.c | 4 | ||||
-rw-r--r-- | drivers/usb/gadget/f_serial.c | 4 | ||||
-rw-r--r-- | drivers/usb/gadget/multi.c | 12 | ||||
-rw-r--r-- | drivers/usb/gadget/nokia.c | 37 | ||||
-rw-r--r-- | drivers/usb/gadget/serial.c | 31 | ||||
-rw-r--r-- | drivers/usb/gadget/u_serial.c | 310 | ||||
-rw-r--r-- | drivers/usb/gadget/u_serial.h | 8 |
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); | |||
111 | static struct fsg_common fsg_common; | 111 | static struct fsg_common fsg_common; |
112 | 112 | ||
113 | /*-------------------------------------------------------------------------*/ | 113 | /*-------------------------------------------------------------------------*/ |
114 | static 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) | |||
188 | fail1: | 189 | fail1: |
189 | fsg_common_put(&fsg_common); | 190 | fsg_common_put(&fsg_common); |
190 | fail0: | 191 | fail0: |
191 | gserial_cleanup(); | 192 | gserial_free_line(tty_line); |
192 | return status; | 193 | return status; |
193 | } | 194 | } |
194 | 195 | ||
195 | static int __exit acm_ms_unbind(struct usb_composite_dev *cdev) | 196 | static 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 | ||
111 | static 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 | ||
185 | fail1: | 186 | fail1: |
186 | gserial_cleanup(); | 187 | gserial_free_line(tty_line); |
187 | fail0: | 188 | fail0: |
188 | gether_cleanup(); | 189 | gether_cleanup(); |
189 | return status; | 190 | return status; |
@@ -191,7 +192,7 @@ fail0: | |||
191 | 192 | ||
192 | static int __exit cdc_unbind(struct usb_composite_dev *cdev) | 193 | static 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 | ||
235 | static unsigned char tty_line; | ||
236 | #endif | ||
237 | |||
234 | static int __init dbgp_configure_endpoints(struct usb_gadget *gadget) | 238 | static 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 | */ |
726 | int acm_bind_config(struct usb_configuration *c, u8 port_num) | 723 | int 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 | */ |
414 | int __init obex_bind_config(struct usb_configuration *c, u8 port_num) | 410 | int __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 | */ |
268 | int __init gser_bind_config(struct usb_configuration *c, u8 port_num) | 264 | int __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 | ||
137 | static u8 hostaddr[ETH_ALEN]; | 137 | static u8 hostaddr[ETH_ALEN]; |
138 | 138 | ||
139 | static 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 | |||
246 | static int __ref multi_bind(struct usb_composite_dev *cdev) | 246 | static 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) | |||
300 | fail2: | 300 | fail2: |
301 | fsg_common_put(&fsg_common); | 301 | fsg_common_put(&fsg_common); |
302 | fail1: | 302 | fail1: |
303 | gserial_cleanup(); | 303 | gserial_free_line(tty_line); |
304 | fail0: | 304 | fail0: |
305 | gether_cleanup(); | 305 | gether_cleanup(); |
306 | return status; | 306 | return status; |
@@ -308,7 +308,7 @@ fail0: | |||
308 | 308 | ||
309 | static int __exit multi_unbind(struct usb_composite_dev *cdev) | 309 | static 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 | ||
101 | static u8 hostaddr[ETH_ALEN]; | 101 | static u8 hostaddr[ETH_ALEN]; |
102 | 102 | ||
103 | enum { | ||
104 | TTY_PORT_OBEX0, | ||
105 | TTY_PORT_OBEX1, | ||
106 | TTY_PORT_ACM, | ||
107 | TTY_PORTS_MAX, | ||
108 | }; | ||
109 | |||
110 | static unsigned char tty_lines[TTY_PORTS_MAX]; | ||
111 | |||
103 | static int __init nokia_bind_config(struct usb_configuration *c) | 112 | static 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) | |||
191 | err_usb: | 203 | err_usb: |
192 | gether_cleanup(); | 204 | gether_cleanup(); |
193 | err_ether: | 205 | err_ether: |
194 | gserial_cleanup(); | 206 | cur_line--; |
195 | err_serial: | 207 | while (cur_line >= 0) |
208 | gserial_free_line(tty_lines[cur_line--]); | ||
209 | |||
196 | gphonet_cleanup(); | 210 | gphonet_cleanup(); |
197 | err_phonet: | 211 | err_phonet: |
198 | return status; | 212 | return status; |
@@ -200,8 +214,13 @@ err_phonet: | |||
200 | 214 | ||
201 | static int __exit nokia_unbind(struct usb_composite_dev *cdev) | 215 | static 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); | |||
127 | MODULE_PARM_DESC(n_ports, "number of ports to create, default=1"); | 127 | MODULE_PARM_DESC(n_ports, "number of ports to create, default=1"); |
128 | 128 | ||
129 | /*-------------------------------------------------------------------------*/ | 129 | /*-------------------------------------------------------------------------*/ |
130 | static unsigned char tty_lines[MAX_U_SERIAL_PORTS]; | ||
130 | 131 | ||
131 | static int __init serial_bind_acm_config(struct usb_configuration *c) | 132 | static 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 | ||
169 | static 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 | |||
168 | static int __init gs_bind(struct usb_composite_dev *cdev) | 178 | static 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 | ||
211 | fail: | 224 | fail: |
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 | ||
224 | static int __init init(void) | 240 | static int __init init(void) |
@@ -254,6 +270,5 @@ module_init(init); | |||
254 | static void __exit cleanup(void) | 270 | static void __exit cleanup(void) |
255 | { | 271 | { |
256 | usb_composite_unregister(&gserial_driver); | 272 | usb_composite_unregister(&gserial_driver); |
257 | gserial_cleanup(); | ||
258 | } | 273 | } |
259 | module_exit(cleanup); | 274 | module_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 | ||
125 | static struct portmaster { | 124 | static 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]; |
129 | static 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 | |||
1033 | gs_port_alloc(unsigned port_num, struct usb_cdc_line_coding *coding) | 1031 | gs_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 | 1062 | out: | |
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 | */ | ||
1078 | int 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; | ||
1153 | fail: | ||
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 | } |
1162 | EXPORT_SYMBOL_GPL(gserial_setup); | ||
1163 | 1066 | ||
1164 | static int gs_closed(struct gs_port *port) | 1067 | static 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 | /** | 1077 | static 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. | 1087 | void gserial_free_line(unsigned char port_num) |
1185 | */ | ||
1186 | void 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 | 1103 | EXPORT_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 */ | 1105 | int 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; | ||
1144 | err: | ||
1145 | return ret; | ||
1222 | } | 1146 | } |
1223 | EXPORT_SYMBOL_GPL(gserial_cleanup); | 1147 | EXPORT_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 | } |
1358 | EXPORT_SYMBOL_GPL(gserial_disconnect); | 1289 | EXPORT_SYMBOL_GPL(gserial_disconnect); |
1359 | 1290 | ||
1291 | int 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; | ||
1335 | fail: | ||
1336 | put_tty_driver(gs_tty_driver); | ||
1337 | gs_tty_driver = NULL; | ||
1338 | return status; | ||
1339 | } | ||
1340 | module_init(userial_init); | ||
1341 | |||
1342 | static 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 | } | ||
1348 | module_exit(userial_cleanup); | ||
1349 | |||
1360 | MODULE_LICENSE("GPL"); | 1350 | MODULE_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 { | |||
49 | struct usb_request *gs_alloc_req(struct usb_ep *ep, unsigned len, gfp_t flags); | 51 | struct usb_request *gs_alloc_req(struct usb_ep *ep, unsigned len, gfp_t flags); |
50 | void gs_free_req(struct usb_ep *, struct usb_request *req); | 52 | void 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 */ |
53 | int gserial_setup(struct usb_gadget *g, unsigned n_ports); | 55 | int gserial_alloc_line(unsigned char *port_line); |
54 | void gserial_cleanup(void); | 56 | void 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 */ |
57 | int gserial_connect(struct gserial *, u8 port_num); | 59 | int gserial_connect(struct gserial *, u8 port_num); |