aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget/zero.c
diff options
context:
space:
mode:
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>2012-12-23 15:10:01 -0500
committerFelipe Balbi <balbi@ti.com>2013-01-21 13:52:40 -0500
commitcf9a08ae5aece88987bbeee8eb0dd0ebb5015815 (patch)
treebbc7e204bd532b6ff84586653f57bc7ec6bf6380 /drivers/usb/gadget/zero.c
parentde53c25447117eae6b3f8952f663f08a09e0dbb7 (diff)
usb: gadget: convert source sink and loopback to new function interface
This patch converts the f_sourcesink and f_loopback file to the USB-function module. Both functions shares a few common utility functions which are currently implemented in g_zero.c itself. This patch moves the common code into the sourcesink file and creates one module out of the the two functions (source sink and loop back). The g_zero gadget is function specific to source sink and loop back to set a few options. This Symbol dependency enforces a modul load right now. Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/gadget/zero.c')
-rw-r--r--drivers/usb/gadget/zero.c196
1 files changed, 116 insertions, 80 deletions
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
index 8ba0bee4e6c0..a331ab13f1e5 100644
--- a/drivers/usb/gadget/zero.c
+++ b/drivers/usb/gadget/zero.c
@@ -10,7 +10,6 @@
10 * (at your option) any later version. 10 * (at your option) any later version.
11 */ 11 */
12 12
13
14/* 13/*
15 * Gadget Zero only needs two bulk endpoints, and is an example of how you 14 * Gadget Zero only needs two bulk endpoints, and is an example of how you
16 * can write a hardware-agnostic gadget driver running inside a USB device. 15 * can write a hardware-agnostic gadget driver running inside a USB device.
@@ -43,23 +42,11 @@
43#include <linux/kernel.h> 42#include <linux/kernel.h>
44#include <linux/slab.h> 43#include <linux/slab.h>
45#include <linux/device.h> 44#include <linux/device.h>
45#include <linux/module.h>
46#include <linux/err.h>
47#include <linux/usb/composite.h>
46 48
47#include "g_zero.h" 49#include "g_zero.h"
48#include "gadget_chips.h"
49
50
51/*-------------------------------------------------------------------------*/
52
53/*
54 * Kbuild is not very cooperative with respect to linking separately
55 * compiled library objects into one module. So for now we won't use
56 * separate compilation ... ensuring init/exit sections work to shrink
57 * the runtime footprint, and giving us at least some parts of what
58 * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
59 */
60#include "f_sourcesink.c"
61#include "f_loopback.c"
62
63/*-------------------------------------------------------------------------*/ 50/*-------------------------------------------------------------------------*/
64USB_GADGET_COMPOSITE_OPTIONS(); 51USB_GADGET_COMPOSITE_OPTIONS();
65 52
@@ -67,9 +54,6 @@ USB_GADGET_COMPOSITE_OPTIONS();
67 54
68static const char longname[] = "Gadget Zero"; 55static const char longname[] = "Gadget Zero";
69 56
70unsigned buflen = 4096; /* only used for bulk endpoints */
71module_param(buflen, uint, 0);
72
73/* 57/*
74 * Normally the "loopback" configuration is second (index 1) so 58 * Normally the "loopback" configuration is second (index 1) so
75 * it's not the default. Here's where to change that order, to 59 * it's not the default. Here's where to change that order, to
@@ -79,6 +63,13 @@ module_param(buflen, uint, 0);
79static bool loopdefault = 0; 63static bool loopdefault = 0;
80module_param(loopdefault, bool, S_IRUGO|S_IWUSR); 64module_param(loopdefault, bool, S_IRUGO|S_IWUSR);
81 65
66struct usb_zero_options gzero_options = {
67 .isoc_interval = 4,
68 .isoc_maxpacket = 1024,
69 .bulk_buflen = 4096,
70 .qlen = 32,
71};
72
82/*-------------------------------------------------------------------------*/ 73/*-------------------------------------------------------------------------*/
83 74
84/* Thanks to NetChip Technologies for donating this product ID. 75/* Thanks to NetChip Technologies for donating this product ID.
@@ -129,10 +120,12 @@ static struct usb_otg_descriptor otg_descriptor = {
129 .bmAttributes = USB_OTG_SRP | USB_OTG_HNP, 120 .bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
130}; 121};
131 122
132const struct usb_descriptor_header *otg_desc[] = { 123static const struct usb_descriptor_header *otg_desc[] = {
133 (struct usb_descriptor_header *) &otg_descriptor, 124 (struct usb_descriptor_header *) &otg_descriptor,
134 NULL, 125 NULL,
135}; 126};
127#else
128#define otg_desc NULL
136#endif 129#endif
137 130
138/* string IDs are assigned dynamically */ 131/* string IDs are assigned dynamically */
@@ -163,58 +156,6 @@ static struct usb_gadget_strings *dev_strings[] = {
163 156
164/*-------------------------------------------------------------------------*/ 157/*-------------------------------------------------------------------------*/
165 158
166struct usb_request *alloc_ep_req(struct usb_ep *ep, int len)
167{
168 struct usb_request *req;
169
170 req = usb_ep_alloc_request(ep, GFP_ATOMIC);
171 if (req) {
172 if (len)
173 req->length = len;
174 else
175 req->length = buflen;
176 req->buf = kmalloc(req->length, GFP_ATOMIC);
177 if (!req->buf) {
178 usb_ep_free_request(ep, req);
179 req = NULL;
180 }
181 }
182 return req;
183}
184
185void free_ep_req(struct usb_ep *ep, struct usb_request *req)
186{
187 kfree(req->buf);
188 usb_ep_free_request(ep, req);
189}
190
191static void disable_ep(struct usb_composite_dev *cdev, struct usb_ep *ep)
192{
193 int value;
194
195 if (ep->driver_data) {
196 value = usb_ep_disable(ep);
197 if (value < 0)
198 DBG(cdev, "disable %s --> %d\n",
199 ep->name, value);
200 ep->driver_data = NULL;
201 }
202}
203
204void disable_endpoints(struct usb_composite_dev *cdev,
205 struct usb_ep *in, struct usb_ep *out,
206 struct usb_ep *iso_in, struct usb_ep *iso_out)
207{
208 disable_ep(cdev, in);
209 disable_ep(cdev, out);
210 if (iso_in)
211 disable_ep(cdev, iso_in);
212 if (iso_out)
213 disable_ep(cdev, iso_out);
214}
215
216/*-------------------------------------------------------------------------*/
217
218static struct timer_list autoresume_timer; 159static struct timer_list autoresume_timer;
219 160
220static void zero_autoresume(unsigned long _c) 161static void zero_autoresume(unsigned long _c)
@@ -258,23 +199,63 @@ static void zero_resume(struct usb_composite_dev *cdev)
258 199
259static struct usb_configuration loopback_driver = { 200static struct usb_configuration loopback_driver = {
260 .label = "loopback", 201 .label = "loopback",
261 .strings = loopback_strings,
262 .bConfigurationValue = 2, 202 .bConfigurationValue = 2,
263 .bmAttributes = USB_CONFIG_ATT_SELFPOWER, 203 .bmAttributes = USB_CONFIG_ATT_SELFPOWER,
264 /* .iConfiguration = DYNAMIC */ 204 /* .iConfiguration = DYNAMIC */
265}; 205};
266 206
207static struct usb_function *func_ss;
208static struct usb_function_instance *func_inst_ss;
209
210static int ss_config_setup(struct usb_configuration *c,
211 const struct usb_ctrlrequest *ctrl)
212{
213 switch (ctrl->bRequest) {
214 case 0x5b:
215 case 0x5c:
216 return func_ss->setup(func_ss, ctrl);
217 default:
218 return -EOPNOTSUPP;
219 }
220}
221
267static struct usb_configuration sourcesink_driver = { 222static struct usb_configuration sourcesink_driver = {
268 .label = "source/sink", 223 .label = "source/sink",
269 .strings = sourcesink_strings,
270 .setup = ss_config_setup, 224 .setup = ss_config_setup,
271 .bConfigurationValue = 3, 225 .bConfigurationValue = 3,
272 .bmAttributes = USB_CONFIG_ATT_SELFPOWER, 226 .bmAttributes = USB_CONFIG_ATT_SELFPOWER,
273 /* .iConfiguration = DYNAMIC */ 227 /* .iConfiguration = DYNAMIC */
274}; 228};
275 229
230module_param_named(buflen, gzero_options.bulk_buflen, uint, 0);
231module_param_named(pattern, gzero_options.pattern, uint, S_IRUGO|S_IWUSR);
232MODULE_PARM_DESC(pattern, "0 = all zeroes, 1 = mod63, 2 = none");
233
234module_param_named(isoc_interval, gzero_options.isoc_interval, uint,
235 S_IRUGO|S_IWUSR);
236MODULE_PARM_DESC(isoc_interval, "1 - 16");
237
238module_param_named(isoc_maxpacket, gzero_options.isoc_maxpacket, uint,
239 S_IRUGO|S_IWUSR);
240MODULE_PARM_DESC(isoc_maxpacket, "0 - 1023 (fs), 0 - 1024 (hs/ss)");
241
242module_param_named(isoc_mult, gzero_options.isoc_mult, uint, S_IRUGO|S_IWUSR);
243MODULE_PARM_DESC(isoc_mult, "0 - 2 (hs/ss only)");
244
245module_param_named(isoc_maxburst, gzero_options.isoc_maxburst, uint,
246 S_IRUGO|S_IWUSR);
247MODULE_PARM_DESC(isoc_maxburst, "0 - 15 (ss only)");
248
249static struct usb_function *func_lb;
250static struct usb_function_instance *func_inst_lb;
251
252module_param_named(qlen, gzero_options.qlen, uint, S_IRUGO|S_IWUSR);
253MODULE_PARM_DESC(qlen, "depth of loopback queue");
254
276static int __init zero_bind(struct usb_composite_dev *cdev) 255static int __init zero_bind(struct usb_composite_dev *cdev)
277{ 256{
257 struct f_ss_opts *ss_opts;
258 struct f_lb_opts *lb_opts;
278 int status; 259 int status;
279 260
280 /* Allocate string descriptor numbers ... note that string 261 /* Allocate string descriptor numbers ... note that string
@@ -290,6 +271,36 @@ static int __init zero_bind(struct usb_composite_dev *cdev)
290 271
291 setup_timer(&autoresume_timer, zero_autoresume, (unsigned long) cdev); 272 setup_timer(&autoresume_timer, zero_autoresume, (unsigned long) cdev);
292 273
274 func_inst_ss = usb_get_function_instance("SourceSink");
275 if (IS_ERR(func_inst_ss))
276 return PTR_ERR(func_inst_ss);
277
278 ss_opts = container_of(func_inst_ss, struct f_ss_opts, func_inst);
279 ss_opts->pattern = gzero_options.pattern;
280 ss_opts->isoc_interval = gzero_options.isoc_interval;
281 ss_opts->isoc_maxpacket = gzero_options.isoc_maxpacket;
282 ss_opts->isoc_mult = gzero_options.isoc_mult;
283 ss_opts->isoc_maxburst = gzero_options.isoc_maxpacket;
284 ss_opts->bulk_buflen = gzero_options.bulk_buflen;
285
286 func_ss = usb_get_function(func_inst_ss);
287 if (IS_ERR(func_ss))
288 goto err_put_func_inst_ss;
289
290 func_inst_lb = usb_get_function_instance("Loopback");
291 if (IS_ERR(func_inst_lb))
292 goto err_put_func_ss;
293
294 lb_opts = container_of(func_inst_lb, struct f_lb_opts, func_inst);
295 lb_opts->bulk_buflen = gzero_options.bulk_buflen;
296 lb_opts->qlen = gzero_options.qlen;
297
298 func_lb = usb_get_function(func_inst_lb);
299 if (IS_ERR(func_lb)) {
300 status = PTR_ERR(func_lb);
301 goto err_put_func_inst_lb;
302 }
303
293 sourcesink_driver.iConfiguration = strings_dev[USB_GZERO_SS_DESC].id; 304 sourcesink_driver.iConfiguration = strings_dev[USB_GZERO_SS_DESC].id;
294 loopback_driver.iConfiguration = strings_dev[USB_GZERO_LB_DESC].id; 305 loopback_driver.iConfiguration = strings_dev[USB_GZERO_LB_DESC].id;
295 306
@@ -315,25 +326,50 @@ static int __init zero_bind(struct usb_composite_dev *cdev)
315 * SH3 only allows one config... 326 * SH3 only allows one config...
316 */ 327 */
317 if (loopdefault) { 328 if (loopdefault) {
318 usb_add_config(cdev, &loopback_driver, loopback_bind_config); 329 usb_add_config_only(cdev, &loopback_driver);
319 usb_add_config(cdev, &sourcesink_driver, 330 usb_add_config_only(cdev, &sourcesink_driver);
320 sourcesink_bind_config);
321 } else { 331 } else {
322 usb_add_config(cdev, &sourcesink_driver, 332 usb_add_config_only(cdev, &sourcesink_driver);
323 sourcesink_bind_config); 333 usb_add_config_only(cdev, &loopback_driver);
324 usb_add_config(cdev, &loopback_driver, loopback_bind_config);
325 } 334 }
335 status = usb_add_function(&sourcesink_driver, func_ss);
336 if (status)
337 goto err_conf_flb;
326 338
339 usb_ep_autoconfig_reset(cdev->gadget);
340 status = usb_add_function(&loopback_driver, func_lb);
341 if (status)
342 goto err_conf_flb;
343
344 usb_ep_autoconfig_reset(cdev->gadget);
327 usb_composite_overwrite_options(cdev, &coverwrite); 345 usb_composite_overwrite_options(cdev, &coverwrite);
328 346
329 INFO(cdev, "%s, version: " DRIVER_VERSION "\n", longname); 347 INFO(cdev, "%s, version: " DRIVER_VERSION "\n", longname);
330 348
331 return 0; 349 return 0;
350
351err_conf_flb:
352 usb_put_function(func_lb);
353 func_lb = NULL;
354err_put_func_inst_lb:
355 usb_put_function_instance(func_inst_lb);
356 func_inst_lb = NULL;
357err_put_func_ss:
358 usb_put_function(func_ss);
359 func_ss = NULL;
360err_put_func_inst_ss:
361 usb_put_function_instance(func_inst_ss);
362 func_inst_ss = NULL;
363 return status;
332} 364}
333 365
334static int zero_unbind(struct usb_composite_dev *cdev) 366static int zero_unbind(struct usb_composite_dev *cdev)
335{ 367{
336 del_timer_sync(&autoresume_timer); 368 del_timer_sync(&autoresume_timer);
369 if (!IS_ERR_OR_NULL(func_ss))
370 usb_put_function(func_ss);
371 if (!IS_ERR_OR_NULL(func_lb))
372 usb_put_function(func_lb);
337 return 0; 373 return 0;
338} 374}
339 375