f_loopback.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  1. /*
  2. * f_loopback.c - USB peripheral loopback configuration driver
  3. *
  4. * Copyright (C) 2003-2008 David Brownell
  5. * Copyright (C) 2008 by Nokia Corporation
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20. */
  21. /* #define VERBOSE_DEBUG */
  22. #include <linux/kernel.h>
  23. #include <linux/device.h>
  24. #include "g_zero.h"
  25. #include "gadget_chips.h"
  26. /*
  27. * LOOPBACK FUNCTION ... a testing vehicle for USB peripherals,
  28. *
  29. * This takes messages of various sizes written OUT to a device, and loops
  30. * them back so they can be read IN from it. It has been used by certain
  31. * test applications. It supports limited testing of data queueing logic.
  32. *
  33. *
  34. * This is currently packaged as a configuration driver, which can't be
  35. * combined with other functions to make composite devices. However, it
  36. * can be combined with other independent configurations.
  37. */
  38. struct f_loopback {
  39. struct usb_function function;
  40. struct usb_ep *in_ep;
  41. struct usb_ep *out_ep;
  42. };
  43. static inline struct f_loopback *func_to_loop(struct usb_function *f)
  44. {
  45. return container_of(f, struct f_loopback, function);
  46. }
  47. static unsigned qlen = 32;
  48. module_param(qlen, uint, 0);
  49. MODULE_PARM_DESC(qlenn, "depth of loopback queue");
  50. /*-------------------------------------------------------------------------*/
  51. static struct usb_interface_descriptor loopback_intf = {
  52. .bLength = sizeof loopback_intf,
  53. .bDescriptorType = USB_DT_INTERFACE,
  54. .bNumEndpoints = 2,
  55. .bInterfaceClass = USB_CLASS_VENDOR_SPEC,
  56. /* .iInterface = DYNAMIC */
  57. };
  58. /* full speed support: */
  59. static struct usb_endpoint_descriptor fs_loop_source_desc = {
  60. .bLength = USB_DT_ENDPOINT_SIZE,
  61. .bDescriptorType = USB_DT_ENDPOINT,
  62. .bEndpointAddress = USB_DIR_IN,
  63. .bmAttributes = USB_ENDPOINT_XFER_BULK,
  64. };
  65. static struct usb_endpoint_descriptor fs_loop_sink_desc = {
  66. .bLength = USB_DT_ENDPOINT_SIZE,
  67. .bDescriptorType = USB_DT_ENDPOINT,
  68. .bEndpointAddress = USB_DIR_OUT,
  69. .bmAttributes = USB_ENDPOINT_XFER_BULK,
  70. };
  71. static struct usb_descriptor_header *fs_loopback_descs[] = {
  72. (struct usb_descriptor_header *) &loopback_intf,
  73. (struct usb_descriptor_header *) &fs_loop_sink_desc,
  74. (struct usb_descriptor_header *) &fs_loop_source_desc,
  75. NULL,
  76. };
  77. /* high speed support: */
  78. static struct usb_endpoint_descriptor hs_loop_source_desc = {
  79. .bLength = USB_DT_ENDPOINT_SIZE,
  80. .bDescriptorType = USB_DT_ENDPOINT,
  81. .bmAttributes = USB_ENDPOINT_XFER_BULK,
  82. .wMaxPacketSize = cpu_to_le16(512),
  83. };
  84. static struct usb_endpoint_descriptor hs_loop_sink_desc = {
  85. .bLength = USB_DT_ENDPOINT_SIZE,
  86. .bDescriptorType = USB_DT_ENDPOINT,
  87. .bmAttributes = USB_ENDPOINT_XFER_BULK,
  88. .wMaxPacketSize = cpu_to_le16(512),
  89. };
  90. static struct usb_descriptor_header *hs_loopback_descs[] = {
  91. (struct usb_descriptor_header *) &loopback_intf,
  92. (struct usb_descriptor_header *) &hs_loop_source_desc,
  93. (struct usb_descriptor_header *) &hs_loop_sink_desc,
  94. NULL,
  95. };
  96. /* function-specific strings: */
  97. static struct usb_string strings_loopback[] = {
  98. [0].s = "loop input to output",
  99. { } /* end of list */
  100. };
  101. static struct usb_gadget_strings stringtab_loop = {
  102. .language = 0x0409, /* en-us */
  103. .strings = strings_loopback,
  104. };
  105. static struct usb_gadget_strings *loopback_strings[] = {
  106. &stringtab_loop,
  107. NULL,
  108. };
  109. /*-------------------------------------------------------------------------*/
  110. static int __init
  111. loopback_bind(struct usb_configuration *c, struct usb_function *f)
  112. {
  113. struct usb_composite_dev *cdev = c->cdev;
  114. struct f_loopback *loop = func_to_loop(f);
  115. int id;
  116. /* allocate interface ID(s) */
  117. id = usb_interface_id(c, f);
  118. if (id < 0)
  119. return id;
  120. loopback_intf.bInterfaceNumber = id;
  121. /* allocate endpoints */
  122. loop->in_ep = usb_ep_autoconfig(cdev->gadget, &fs_loop_source_desc);
  123. if (!loop->in_ep) {
  124. autoconf_fail:
  125. ERROR(cdev, "%s: can't autoconfigure on %s\n",
  126. f->name, cdev->gadget->name);
  127. return -ENODEV;
  128. }
  129. loop->in_ep->driver_data = cdev; /* claim */
  130. loop->out_ep = usb_ep_autoconfig(cdev->gadget, &fs_loop_sink_desc);
  131. if (!loop->out_ep)
  132. goto autoconf_fail;
  133. loop->out_ep->driver_data = cdev; /* claim */
  134. /* support high speed hardware */
  135. if (gadget_is_dualspeed(c->cdev->gadget)) {
  136. hs_loop_source_desc.bEndpointAddress =
  137. fs_loop_source_desc.bEndpointAddress;
  138. hs_loop_sink_desc.bEndpointAddress =
  139. fs_loop_sink_desc.bEndpointAddress;
  140. f->hs_descriptors = hs_loopback_descs;
  141. }
  142. DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n",
  143. gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
  144. f->name, loop->in_ep->name, loop->out_ep->name);
  145. return 0;
  146. }
  147. static void
  148. loopback_unbind(struct usb_configuration *c, struct usb_function *f)
  149. {
  150. kfree(func_to_loop(f));
  151. }
  152. static void loopback_complete(struct usb_ep *ep, struct usb_request *req)
  153. {
  154. struct f_loopback *loop = ep->driver_data;
  155. struct usb_composite_dev *cdev = loop->function.config->cdev;
  156. int status = req->status;
  157. switch (status) {
  158. case 0: /* normal completion? */
  159. if (ep == loop->out_ep) {
  160. /* loop this OUT packet back IN to the host */
  161. req->zero = (req->actual < req->length);
  162. req->length = req->actual;
  163. status = usb_ep_queue(loop->in_ep, req, GFP_ATOMIC);
  164. if (status == 0)
  165. return;
  166. /* "should never get here" */
  167. ERROR(cdev, "can't loop %s to %s: %d\n",
  168. ep->name, loop->in_ep->name,
  169. status);
  170. }
  171. /* queue the buffer for some later OUT packet */
  172. req->length = buflen;
  173. status = usb_ep_queue(loop->out_ep, req, GFP_ATOMIC);
  174. if (status == 0)
  175. return;
  176. /* "should never get here" */
  177. /* FALLTHROUGH */
  178. default:
  179. ERROR(cdev, "%s loop complete --> %d, %d/%d\n", ep->name,
  180. status, req->actual, req->length);
  181. /* FALLTHROUGH */
  182. /* NOTE: since this driver doesn't maintain an explicit record
  183. * of requests it submitted (just maintains qlen count), we
  184. * rely on the hardware driver to clean up on disconnect or
  185. * endpoint disable.
  186. */
  187. case -ECONNABORTED: /* hardware forced ep reset */
  188. case -ECONNRESET: /* request dequeued */
  189. case -ESHUTDOWN: /* disconnect from host */
  190. free_ep_req(ep, req);
  191. return;
  192. }
  193. }
  194. static void disable_loopback(struct f_loopback *loop)
  195. {
  196. struct usb_composite_dev *cdev;
  197. cdev = loop->function.config->cdev;
  198. disable_endpoints(cdev, loop->in_ep, loop->out_ep);
  199. VDBG(cdev, "%s disabled\n", loop->function.name);
  200. }
  201. static int
  202. enable_loopback(struct usb_composite_dev *cdev, struct f_loopback *loop)
  203. {
  204. int result = 0;
  205. const struct usb_endpoint_descriptor *src, *sink;
  206. struct usb_ep *ep;
  207. struct usb_request *req;
  208. unsigned i;
  209. src = ep_choose(cdev->gadget,
  210. &hs_loop_source_desc, &fs_loop_source_desc);
  211. sink = ep_choose(cdev->gadget,
  212. &hs_loop_sink_desc, &fs_loop_sink_desc);
  213. /* one endpoint writes data back IN to the host */
  214. ep = loop->in_ep;
  215. result = usb_ep_enable(ep, src);
  216. if (result < 0)
  217. return result;
  218. ep->driver_data = loop;
  219. /* one endpoint just reads OUT packets */
  220. ep = loop->out_ep;
  221. result = usb_ep_enable(ep, sink);
  222. if (result < 0) {
  223. fail0:
  224. ep = loop->in_ep;
  225. usb_ep_disable(ep);
  226. ep->driver_data = NULL;
  227. return result;
  228. }
  229. ep->driver_data = loop;
  230. /* allocate a bunch of read buffers and queue them all at once.
  231. * we buffer at most 'qlen' transfers; fewer if any need more
  232. * than 'buflen' bytes each.
  233. */
  234. for (i = 0; i < qlen && result == 0; i++) {
  235. req = alloc_ep_req(ep);
  236. if (req) {
  237. req->complete = loopback_complete;
  238. result = usb_ep_queue(ep, req, GFP_ATOMIC);
  239. if (result)
  240. ERROR(cdev, "%s queue req --> %d\n",
  241. ep->name, result);
  242. } else {
  243. usb_ep_disable(ep);
  244. ep->driver_data = NULL;
  245. result = -ENOMEM;
  246. goto fail0;
  247. }
  248. }
  249. DBG(cdev, "%s enabled\n", loop->function.name);
  250. return result;
  251. }
  252. static int loopback_set_alt(struct usb_function *f,
  253. unsigned intf, unsigned alt)
  254. {
  255. struct f_loopback *loop = func_to_loop(f);
  256. struct usb_composite_dev *cdev = f->config->cdev;
  257. /* we know alt is zero */
  258. if (loop->in_ep->driver_data)
  259. disable_loopback(loop);
  260. return enable_loopback(cdev, loop);
  261. }
  262. static void loopback_disable(struct usb_function *f)
  263. {
  264. struct f_loopback *loop = func_to_loop(f);
  265. disable_loopback(loop);
  266. }
  267. /*-------------------------------------------------------------------------*/
  268. static int __init loopback_bind_config(struct usb_configuration *c)
  269. {
  270. struct f_loopback *loop;
  271. int status;
  272. loop = kzalloc(sizeof *loop, GFP_KERNEL);
  273. if (!loop)
  274. return -ENOMEM;
  275. loop->function.name = "loopback";
  276. loop->function.descriptors = fs_loopback_descs;
  277. loop->function.bind = loopback_bind;
  278. loop->function.unbind = loopback_unbind;
  279. loop->function.set_alt = loopback_set_alt;
  280. loop->function.disable = loopback_disable;
  281. status = usb_add_function(c, &loop->function);
  282. if (status)
  283. kfree(loop);
  284. return status;
  285. }
  286. static struct usb_configuration loopback_driver = {
  287. .label = "loopback",
  288. .strings = loopback_strings,
  289. .bind = loopback_bind_config,
  290. .bConfigurationValue = 2,
  291. .bmAttributes = USB_CONFIG_ATT_SELFPOWER,
  292. /* .iConfiguration = DYNAMIC */
  293. };
  294. /**
  295. * loopback_add - add a loopback testing configuration to a device
  296. * @cdev: the device to support the loopback configuration
  297. */
  298. int __init loopback_add(struct usb_composite_dev *cdev, bool autoresume)
  299. {
  300. int id;
  301. /* allocate string ID(s) */
  302. id = usb_string_id(cdev);
  303. if (id < 0)
  304. return id;
  305. strings_loopback[0].id = id;
  306. loopback_intf.iInterface = id;
  307. loopback_driver.iConfiguration = id;
  308. /* support autoresume for remote wakeup testing */
  309. if (autoresume)
  310. sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
  311. /* support OTG systems */
  312. if (gadget_is_otg(cdev->gadget)) {
  313. loopback_driver.descriptors = otg_desc;
  314. loopback_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
  315. }
  316. return usb_add_config(cdev, &loopback_driver);
  317. }