root/drivers/usb/gadget/function/f_loopback.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. func_to_loop
  2. loopback_bind
  3. lb_free_func
  4. loopback_complete
  5. disable_loopback
  6. lb_alloc_ep_req
  7. alloc_requests
  8. enable_endpoint
  9. enable_loopback
  10. loopback_set_alt
  11. loopback_disable
  12. loopback_alloc
  13. to_f_lb_opts
  14. lb_attr_release
  15. f_lb_opts_qlen_show
  16. f_lb_opts_qlen_store
  17. f_lb_opts_bulk_buflen_show
  18. f_lb_opts_bulk_buflen_store
  19. lb_free_instance
  20. loopback_alloc_instance
  21. lb_modinit
  22. lb_modexit

   1 // SPDX-License-Identifier: GPL-2.0+
   2 /*
   3  * f_loopback.c - USB peripheral loopback configuration driver
   4  *
   5  * Copyright (C) 2003-2008 David Brownell
   6  * Copyright (C) 2008 by Nokia Corporation
   7  */
   8 
   9 /* #define VERBOSE_DEBUG */
  10 
  11 #include <linux/slab.h>
  12 #include <linux/kernel.h>
  13 #include <linux/device.h>
  14 #include <linux/module.h>
  15 #include <linux/err.h>
  16 #include <linux/usb/composite.h>
  17 
  18 #include "g_zero.h"
  19 #include "u_f.h"
  20 
  21 /*
  22  * LOOPBACK FUNCTION ... a testing vehicle for USB peripherals,
  23  *
  24  * This takes messages of various sizes written OUT to a device, and loops
  25  * them back so they can be read IN from it.  It has been used by certain
  26  * test applications.  It supports limited testing of data queueing logic.
  27  */
  28 struct f_loopback {
  29         struct usb_function     function;
  30 
  31         struct usb_ep           *in_ep;
  32         struct usb_ep           *out_ep;
  33 
  34         unsigned                qlen;
  35         unsigned                buflen;
  36 };
  37 
  38 static inline struct f_loopback *func_to_loop(struct usb_function *f)
  39 {
  40         return container_of(f, struct f_loopback, function);
  41 }
  42 
  43 /*-------------------------------------------------------------------------*/
  44 
  45 static struct usb_interface_descriptor loopback_intf = {
  46         .bLength =              sizeof(loopback_intf),
  47         .bDescriptorType =      USB_DT_INTERFACE,
  48 
  49         .bNumEndpoints =        2,
  50         .bInterfaceClass =      USB_CLASS_VENDOR_SPEC,
  51         /* .iInterface = DYNAMIC */
  52 };
  53 
  54 /* full speed support: */
  55 
  56 static struct usb_endpoint_descriptor fs_loop_source_desc = {
  57         .bLength =              USB_DT_ENDPOINT_SIZE,
  58         .bDescriptorType =      USB_DT_ENDPOINT,
  59 
  60         .bEndpointAddress =     USB_DIR_IN,
  61         .bmAttributes =         USB_ENDPOINT_XFER_BULK,
  62 };
  63 
  64 static struct usb_endpoint_descriptor fs_loop_sink_desc = {
  65         .bLength =              USB_DT_ENDPOINT_SIZE,
  66         .bDescriptorType =      USB_DT_ENDPOINT,
  67 
  68         .bEndpointAddress =     USB_DIR_OUT,
  69         .bmAttributes =         USB_ENDPOINT_XFER_BULK,
  70 };
  71 
  72 static struct usb_descriptor_header *fs_loopback_descs[] = {
  73         (struct usb_descriptor_header *) &loopback_intf,
  74         (struct usb_descriptor_header *) &fs_loop_sink_desc,
  75         (struct usb_descriptor_header *) &fs_loop_source_desc,
  76         NULL,
  77 };
  78 
  79 /* high speed support: */
  80 
  81 static struct usb_endpoint_descriptor hs_loop_source_desc = {
  82         .bLength =              USB_DT_ENDPOINT_SIZE,
  83         .bDescriptorType =      USB_DT_ENDPOINT,
  84 
  85         .bmAttributes =         USB_ENDPOINT_XFER_BULK,
  86         .wMaxPacketSize =       cpu_to_le16(512),
  87 };
  88 
  89 static struct usb_endpoint_descriptor hs_loop_sink_desc = {
  90         .bLength =              USB_DT_ENDPOINT_SIZE,
  91         .bDescriptorType =      USB_DT_ENDPOINT,
  92 
  93         .bmAttributes =         USB_ENDPOINT_XFER_BULK,
  94         .wMaxPacketSize =       cpu_to_le16(512),
  95 };
  96 
  97 static struct usb_descriptor_header *hs_loopback_descs[] = {
  98         (struct usb_descriptor_header *) &loopback_intf,
  99         (struct usb_descriptor_header *) &hs_loop_source_desc,
 100         (struct usb_descriptor_header *) &hs_loop_sink_desc,
 101         NULL,
 102 };
 103 
 104 /* super speed support: */
 105 
 106 static struct usb_endpoint_descriptor ss_loop_source_desc = {
 107         .bLength =              USB_DT_ENDPOINT_SIZE,
 108         .bDescriptorType =      USB_DT_ENDPOINT,
 109 
 110         .bmAttributes =         USB_ENDPOINT_XFER_BULK,
 111         .wMaxPacketSize =       cpu_to_le16(1024),
 112 };
 113 
 114 static struct usb_ss_ep_comp_descriptor ss_loop_source_comp_desc = {
 115         .bLength =              USB_DT_SS_EP_COMP_SIZE,
 116         .bDescriptorType =      USB_DT_SS_ENDPOINT_COMP,
 117         .bMaxBurst =            0,
 118         .bmAttributes =         0,
 119         .wBytesPerInterval =    0,
 120 };
 121 
 122 static struct usb_endpoint_descriptor ss_loop_sink_desc = {
 123         .bLength =              USB_DT_ENDPOINT_SIZE,
 124         .bDescriptorType =      USB_DT_ENDPOINT,
 125 
 126         .bmAttributes =         USB_ENDPOINT_XFER_BULK,
 127         .wMaxPacketSize =       cpu_to_le16(1024),
 128 };
 129 
 130 static struct usb_ss_ep_comp_descriptor ss_loop_sink_comp_desc = {
 131         .bLength =              USB_DT_SS_EP_COMP_SIZE,
 132         .bDescriptorType =      USB_DT_SS_ENDPOINT_COMP,
 133         .bMaxBurst =            0,
 134         .bmAttributes =         0,
 135         .wBytesPerInterval =    0,
 136 };
 137 
 138 static struct usb_descriptor_header *ss_loopback_descs[] = {
 139         (struct usb_descriptor_header *) &loopback_intf,
 140         (struct usb_descriptor_header *) &ss_loop_source_desc,
 141         (struct usb_descriptor_header *) &ss_loop_source_comp_desc,
 142         (struct usb_descriptor_header *) &ss_loop_sink_desc,
 143         (struct usb_descriptor_header *) &ss_loop_sink_comp_desc,
 144         NULL,
 145 };
 146 
 147 /* function-specific strings: */
 148 
 149 static struct usb_string strings_loopback[] = {
 150         [0].s = "loop input to output",
 151         {  }                    /* end of list */
 152 };
 153 
 154 static struct usb_gadget_strings stringtab_loop = {
 155         .language       = 0x0409,       /* en-us */
 156         .strings        = strings_loopback,
 157 };
 158 
 159 static struct usb_gadget_strings *loopback_strings[] = {
 160         &stringtab_loop,
 161         NULL,
 162 };
 163 
 164 /*-------------------------------------------------------------------------*/
 165 
 166 static int loopback_bind(struct usb_configuration *c, struct usb_function *f)
 167 {
 168         struct usb_composite_dev *cdev = c->cdev;
 169         struct f_loopback       *loop = func_to_loop(f);
 170         int                     id;
 171         int ret;
 172 
 173         /* allocate interface ID(s) */
 174         id = usb_interface_id(c, f);
 175         if (id < 0)
 176                 return id;
 177         loopback_intf.bInterfaceNumber = id;
 178 
 179         id = usb_string_id(cdev);
 180         if (id < 0)
 181                 return id;
 182         strings_loopback[0].id = id;
 183         loopback_intf.iInterface = id;
 184 
 185         /* allocate endpoints */
 186 
 187         loop->in_ep = usb_ep_autoconfig(cdev->gadget, &fs_loop_source_desc);
 188         if (!loop->in_ep) {
 189 autoconf_fail:
 190                 ERROR(cdev, "%s: can't autoconfigure on %s\n",
 191                         f->name, cdev->gadget->name);
 192                 return -ENODEV;
 193         }
 194 
 195         loop->out_ep = usb_ep_autoconfig(cdev->gadget, &fs_loop_sink_desc);
 196         if (!loop->out_ep)
 197                 goto autoconf_fail;
 198 
 199         /* support high speed hardware */
 200         hs_loop_source_desc.bEndpointAddress =
 201                 fs_loop_source_desc.bEndpointAddress;
 202         hs_loop_sink_desc.bEndpointAddress = fs_loop_sink_desc.bEndpointAddress;
 203 
 204         /* support super speed hardware */
 205         ss_loop_source_desc.bEndpointAddress =
 206                 fs_loop_source_desc.bEndpointAddress;
 207         ss_loop_sink_desc.bEndpointAddress = fs_loop_sink_desc.bEndpointAddress;
 208 
 209         ret = usb_assign_descriptors(f, fs_loopback_descs, hs_loopback_descs,
 210                         ss_loopback_descs, NULL);
 211         if (ret)
 212                 return ret;
 213 
 214         DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n",
 215             (gadget_is_superspeed(c->cdev->gadget) ? "super" :
 216              (gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full")),
 217                         f->name, loop->in_ep->name, loop->out_ep->name);
 218         return 0;
 219 }
 220 
 221 static void lb_free_func(struct usb_function *f)
 222 {
 223         struct f_lb_opts *opts;
 224 
 225         opts = container_of(f->fi, struct f_lb_opts, func_inst);
 226 
 227         mutex_lock(&opts->lock);
 228         opts->refcnt--;
 229         mutex_unlock(&opts->lock);
 230 
 231         usb_free_all_descriptors(f);
 232         kfree(func_to_loop(f));
 233 }
 234 
 235 static void loopback_complete(struct usb_ep *ep, struct usb_request *req)
 236 {
 237         struct f_loopback       *loop = ep->driver_data;
 238         struct usb_composite_dev *cdev = loop->function.config->cdev;
 239         int                     status = req->status;
 240 
 241         switch (status) {
 242         case 0:                         /* normal completion? */
 243                 if (ep == loop->out_ep) {
 244                         /*
 245                          * We received some data from the host so let's
 246                          * queue it so host can read the from our in ep
 247                          */
 248                         struct usb_request *in_req = req->context;
 249 
 250                         in_req->zero = (req->actual < req->length);
 251                         in_req->length = req->actual;
 252                         ep = loop->in_ep;
 253                         req = in_req;
 254                 } else {
 255                         /*
 256                          * We have just looped back a bunch of data
 257                          * to host. Now let's wait for some more data.
 258                          */
 259                         req = req->context;
 260                         ep = loop->out_ep;
 261                 }
 262 
 263                 /* queue the buffer back to host or for next bunch of data */
 264                 status = usb_ep_queue(ep, req, GFP_ATOMIC);
 265                 if (status == 0) {
 266                         return;
 267                 } else {
 268                         ERROR(cdev, "Unable to loop back buffer to %s: %d\n",
 269                               ep->name, status);
 270                         goto free_req;
 271                 }
 272 
 273                 /* "should never get here" */
 274         default:
 275                 ERROR(cdev, "%s loop complete --> %d, %d/%d\n", ep->name,
 276                                 status, req->actual, req->length);
 277                 /* FALLTHROUGH */
 278 
 279         /* NOTE:  since this driver doesn't maintain an explicit record
 280          * of requests it submitted (just maintains qlen count), we
 281          * rely on the hardware driver to clean up on disconnect or
 282          * endpoint disable.
 283          */
 284         case -ECONNABORTED:             /* hardware forced ep reset */
 285         case -ECONNRESET:               /* request dequeued */
 286         case -ESHUTDOWN:                /* disconnect from host */
 287 free_req:
 288                 usb_ep_free_request(ep == loop->in_ep ?
 289                                     loop->out_ep : loop->in_ep,
 290                                     req->context);
 291                 free_ep_req(ep, req);
 292                 return;
 293         }
 294 }
 295 
 296 static void disable_loopback(struct f_loopback *loop)
 297 {
 298         struct usb_composite_dev        *cdev;
 299 
 300         cdev = loop->function.config->cdev;
 301         disable_endpoints(cdev, loop->in_ep, loop->out_ep, NULL, NULL);
 302         VDBG(cdev, "%s disabled\n", loop->function.name);
 303 }
 304 
 305 static inline struct usb_request *lb_alloc_ep_req(struct usb_ep *ep, int len)
 306 {
 307         return alloc_ep_req(ep, len);
 308 }
 309 
 310 static int alloc_requests(struct usb_composite_dev *cdev,
 311                           struct f_loopback *loop)
 312 {
 313         struct usb_request *in_req, *out_req;
 314         int i;
 315         int result = 0;
 316 
 317         /*
 318          * allocate a bunch of read buffers and queue them all at once.
 319          * we buffer at most 'qlen' transfers; We allocate buffers only
 320          * for out transfer and reuse them in IN transfers to implement
 321          * our loopback functionality
 322          */
 323         for (i = 0; i < loop->qlen && result == 0; i++) {
 324                 result = -ENOMEM;
 325 
 326                 in_req = usb_ep_alloc_request(loop->in_ep, GFP_ATOMIC);
 327                 if (!in_req)
 328                         goto fail;
 329 
 330                 out_req = lb_alloc_ep_req(loop->out_ep, loop->buflen);
 331                 if (!out_req)
 332                         goto fail_in;
 333 
 334                 in_req->complete = loopback_complete;
 335                 out_req->complete = loopback_complete;
 336 
 337                 in_req->buf = out_req->buf;
 338                 /* length will be set in complete routine */
 339                 in_req->context = out_req;
 340                 out_req->context = in_req;
 341 
 342                 result = usb_ep_queue(loop->out_ep, out_req, GFP_ATOMIC);
 343                 if (result) {
 344                         ERROR(cdev, "%s queue req --> %d\n",
 345                                         loop->out_ep->name, result);
 346                         goto fail_out;
 347                 }
 348         }
 349 
 350         return 0;
 351 
 352 fail_out:
 353         free_ep_req(loop->out_ep, out_req);
 354 fail_in:
 355         usb_ep_free_request(loop->in_ep, in_req);
 356 fail:
 357         return result;
 358 }
 359 
 360 static int enable_endpoint(struct usb_composite_dev *cdev,
 361                            struct f_loopback *loop, struct usb_ep *ep)
 362 {
 363         int                                     result;
 364 
 365         result = config_ep_by_speed(cdev->gadget, &(loop->function), ep);
 366         if (result)
 367                 goto out;
 368 
 369         result = usb_ep_enable(ep);
 370         if (result < 0)
 371                 goto out;
 372         ep->driver_data = loop;
 373         result = 0;
 374 
 375 out:
 376         return result;
 377 }
 378 
 379 static int
 380 enable_loopback(struct usb_composite_dev *cdev, struct f_loopback *loop)
 381 {
 382         int                                     result = 0;
 383 
 384         result = enable_endpoint(cdev, loop, loop->in_ep);
 385         if (result)
 386                 goto out;
 387 
 388         result = enable_endpoint(cdev, loop, loop->out_ep);
 389         if (result)
 390                 goto disable_in;
 391 
 392         result = alloc_requests(cdev, loop);
 393         if (result)
 394                 goto disable_out;
 395 
 396         DBG(cdev, "%s enabled\n", loop->function.name);
 397         return 0;
 398 
 399 disable_out:
 400         usb_ep_disable(loop->out_ep);
 401 disable_in:
 402         usb_ep_disable(loop->in_ep);
 403 out:
 404         return result;
 405 }
 406 
 407 static int loopback_set_alt(struct usb_function *f,
 408                 unsigned intf, unsigned alt)
 409 {
 410         struct f_loopback       *loop = func_to_loop(f);
 411         struct usb_composite_dev *cdev = f->config->cdev;
 412 
 413         /* we know alt is zero */
 414         disable_loopback(loop);
 415         return enable_loopback(cdev, loop);
 416 }
 417 
 418 static void loopback_disable(struct usb_function *f)
 419 {
 420         struct f_loopback       *loop = func_to_loop(f);
 421 
 422         disable_loopback(loop);
 423 }
 424 
 425 static struct usb_function *loopback_alloc(struct usb_function_instance *fi)
 426 {
 427         struct f_loopback       *loop;
 428         struct f_lb_opts        *lb_opts;
 429 
 430         loop = kzalloc(sizeof *loop, GFP_KERNEL);
 431         if (!loop)
 432                 return ERR_PTR(-ENOMEM);
 433 
 434         lb_opts = container_of(fi, struct f_lb_opts, func_inst);
 435 
 436         mutex_lock(&lb_opts->lock);
 437         lb_opts->refcnt++;
 438         mutex_unlock(&lb_opts->lock);
 439 
 440         loop->buflen = lb_opts->bulk_buflen;
 441         loop->qlen = lb_opts->qlen;
 442         if (!loop->qlen)
 443                 loop->qlen = 32;
 444 
 445         loop->function.name = "loopback";
 446         loop->function.bind = loopback_bind;
 447         loop->function.set_alt = loopback_set_alt;
 448         loop->function.disable = loopback_disable;
 449         loop->function.strings = loopback_strings;
 450 
 451         loop->function.free_func = lb_free_func;
 452 
 453         return &loop->function;
 454 }
 455 
 456 static inline struct f_lb_opts *to_f_lb_opts(struct config_item *item)
 457 {
 458         return container_of(to_config_group(item), struct f_lb_opts,
 459                             func_inst.group);
 460 }
 461 
 462 static void lb_attr_release(struct config_item *item)
 463 {
 464         struct f_lb_opts *lb_opts = to_f_lb_opts(item);
 465 
 466         usb_put_function_instance(&lb_opts->func_inst);
 467 }
 468 
 469 static struct configfs_item_operations lb_item_ops = {
 470         .release                = lb_attr_release,
 471 };
 472 
 473 static ssize_t f_lb_opts_qlen_show(struct config_item *item, char *page)
 474 {
 475         struct f_lb_opts *opts = to_f_lb_opts(item);
 476         int result;
 477 
 478         mutex_lock(&opts->lock);
 479         result = sprintf(page, "%d\n", opts->qlen);
 480         mutex_unlock(&opts->lock);
 481 
 482         return result;
 483 }
 484 
 485 static ssize_t f_lb_opts_qlen_store(struct config_item *item,
 486                                     const char *page, size_t len)
 487 {
 488         struct f_lb_opts *opts = to_f_lb_opts(item);
 489         int ret;
 490         u32 num;
 491 
 492         mutex_lock(&opts->lock);
 493         if (opts->refcnt) {
 494                 ret = -EBUSY;
 495                 goto end;
 496         }
 497 
 498         ret = kstrtou32(page, 0, &num);
 499         if (ret)
 500                 goto end;
 501 
 502         opts->qlen = num;
 503         ret = len;
 504 end:
 505         mutex_unlock(&opts->lock);
 506         return ret;
 507 }
 508 
 509 CONFIGFS_ATTR(f_lb_opts_, qlen);
 510 
 511 static ssize_t f_lb_opts_bulk_buflen_show(struct config_item *item, char *page)
 512 {
 513         struct f_lb_opts *opts = to_f_lb_opts(item);
 514         int result;
 515 
 516         mutex_lock(&opts->lock);
 517         result = sprintf(page, "%d\n", opts->bulk_buflen);
 518         mutex_unlock(&opts->lock);
 519 
 520         return result;
 521 }
 522 
 523 static ssize_t f_lb_opts_bulk_buflen_store(struct config_item *item,
 524                                     const char *page, size_t len)
 525 {
 526         struct f_lb_opts *opts = to_f_lb_opts(item);
 527         int ret;
 528         u32 num;
 529 
 530         mutex_lock(&opts->lock);
 531         if (opts->refcnt) {
 532                 ret = -EBUSY;
 533                 goto end;
 534         }
 535 
 536         ret = kstrtou32(page, 0, &num);
 537         if (ret)
 538                 goto end;
 539 
 540         opts->bulk_buflen = num;
 541         ret = len;
 542 end:
 543         mutex_unlock(&opts->lock);
 544         return ret;
 545 }
 546 
 547 CONFIGFS_ATTR(f_lb_opts_, bulk_buflen);
 548 
 549 static struct configfs_attribute *lb_attrs[] = {
 550         &f_lb_opts_attr_qlen,
 551         &f_lb_opts_attr_bulk_buflen,
 552         NULL,
 553 };
 554 
 555 static const struct config_item_type lb_func_type = {
 556         .ct_item_ops    = &lb_item_ops,
 557         .ct_attrs       = lb_attrs,
 558         .ct_owner       = THIS_MODULE,
 559 };
 560 
 561 static void lb_free_instance(struct usb_function_instance *fi)
 562 {
 563         struct f_lb_opts *lb_opts;
 564 
 565         lb_opts = container_of(fi, struct f_lb_opts, func_inst);
 566         kfree(lb_opts);
 567 }
 568 
 569 static struct usb_function_instance *loopback_alloc_instance(void)
 570 {
 571         struct f_lb_opts *lb_opts;
 572 
 573         lb_opts = kzalloc(sizeof(*lb_opts), GFP_KERNEL);
 574         if (!lb_opts)
 575                 return ERR_PTR(-ENOMEM);
 576         mutex_init(&lb_opts->lock);
 577         lb_opts->func_inst.free_func_inst = lb_free_instance;
 578         lb_opts->bulk_buflen = GZERO_BULK_BUFLEN;
 579         lb_opts->qlen = GZERO_QLEN;
 580 
 581         config_group_init_type_name(&lb_opts->func_inst.group, "",
 582                                     &lb_func_type);
 583 
 584         return  &lb_opts->func_inst;
 585 }
 586 DECLARE_USB_FUNCTION(Loopback, loopback_alloc_instance, loopback_alloc);
 587 
 588 int __init lb_modinit(void)
 589 {
 590         return usb_function_register(&Loopbackusb_func);
 591 }
 592 
 593 void __exit lb_modexit(void)
 594 {
 595         usb_function_unregister(&Loopbackusb_func);
 596 }
 597 
 598 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */