~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/net/9p/trans_usbg.c

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0+
  2 /*
  3  * trans_usbg.c - USB peripheral usb9pfs configuration driver and transport.
  4  *
  5  * Copyright (C) 2024 Michael Grzeschik <m.grzeschik@pengutronix.de>
  6  */
  7 
  8 /* Gadget usb9pfs only needs two bulk endpoints, and will use the usb9pfs
  9  * transport to mount host exported filesystem via usb gadget.
 10  */
 11 
 12 /*     +--------------------------+    |    +--------------------------+
 13  *     |  9PFS mounting client    |    |    |  9PFS exporting server   |
 14  *  SW |                          |    |    |                          |
 15  *     |   (this:trans_usbg)      |    |    |(e.g. diod or nfs-ganesha)|
 16  *     +-------------^------------+    |    +-------------^------------+
 17  *                   |                 |                  |
 18  * ------------------|------------------------------------|-------------
 19  *                   |                 |                  |
 20  *     +-------------v------------+    |    +-------------v------------+
 21  *     |                          |    |    |                          |
 22  *  HW |   USB Device Controller  <--------->   USB Host Controller    |
 23  *     |                          |    |    |                          |
 24  *     +--------------------------+    |    +--------------------------+
 25  */
 26 
 27 #include <linux/cleanup.h>
 28 #include <linux/kernel.h>
 29 #include <linux/module.h>
 30 #include <linux/usb/composite.h>
 31 #include <linux/usb/func_utils.h>
 32 
 33 #include <net/9p/9p.h>
 34 #include <net/9p/client.h>
 35 #include <net/9p/transport.h>
 36 
 37 #define DEFAULT_BUFLEN        16384
 38 
 39 struct f_usb9pfs {
 40         struct p9_client *client;
 41 
 42         /* 9p request lock for en/dequeue */
 43         spinlock_t lock;
 44 
 45         struct usb_request *in_req;
 46         struct usb_request *out_req;
 47 
 48         struct usb_ep *in_ep;
 49         struct usb_ep *out_ep;
 50 
 51         struct completion send;
 52         struct completion received;
 53 
 54         unsigned int buflen;
 55 
 56         struct usb_function function;
 57 };
 58 
 59 static inline struct f_usb9pfs *func_to_usb9pfs(struct usb_function *f)
 60 {
 61         return container_of(f, struct f_usb9pfs, function);
 62 }
 63 
 64 struct f_usb9pfs_opts {
 65         struct usb_function_instance func_inst;
 66         unsigned int buflen;
 67 
 68         struct f_usb9pfs_dev *dev;
 69 
 70         /* Read/write access to configfs attributes is handled by configfs.
 71          *
 72          * This is to protect the data from concurrent access by read/write
 73          * and create symlink/remove symlink.
 74          */
 75         struct mutex lock;
 76         int refcnt;
 77 };
 78 
 79 struct f_usb9pfs_dev {
 80         struct f_usb9pfs *usb9pfs;
 81         struct f_usb9pfs_opts *opts;
 82         char tag[41];
 83         bool inuse;
 84 
 85         struct list_head usb9pfs_instance;
 86 };
 87 
 88 static DEFINE_MUTEX(usb9pfs_lock);
 89 static struct list_head usbg_instance_list;
 90 
 91 static int usb9pfs_queue_tx(struct f_usb9pfs *usb9pfs, struct p9_req_t *p9_tx_req,
 92                             gfp_t gfp_flags)
 93 {
 94         struct usb_composite_dev *cdev = usb9pfs->function.config->cdev;
 95         struct usb_request *req = usb9pfs->in_req;
 96         int ret;
 97 
 98         if (!(p9_tx_req->tc.size % usb9pfs->in_ep->maxpacket))
 99                 req->zero = 1;
100 
101         req->buf = p9_tx_req->tc.sdata;
102         req->length = p9_tx_req->tc.size;
103         req->context = p9_tx_req;
104 
105         dev_dbg(&cdev->gadget->dev, "%s usb9pfs send --> %d/%d, zero: %d\n",
106                 usb9pfs->in_ep->name, req->actual, req->length, req->zero);
107 
108         ret = usb_ep_queue(usb9pfs->in_ep, req, gfp_flags);
109         if (ret)
110                 req->context = NULL;
111 
112         dev_dbg(&cdev->gadget->dev, "tx submit --> %d\n", ret);
113 
114         return ret;
115 }
116 
117 static int usb9pfs_queue_rx(struct f_usb9pfs *usb9pfs, struct usb_request *req,
118                             gfp_t gfp_flags)
119 {
120         struct usb_composite_dev *cdev = usb9pfs->function.config->cdev;
121         int ret;
122 
123         ret = usb_ep_queue(usb9pfs->out_ep, req, gfp_flags);
124 
125         dev_dbg(&cdev->gadget->dev, "rx submit --> %d\n", ret);
126 
127         return ret;
128 }
129 
130 static int usb9pfs_transmit(struct f_usb9pfs *usb9pfs, struct p9_req_t *p9_req)
131 {
132         int ret = 0;
133 
134         guard(spinlock_irqsave)(&usb9pfs->lock);
135 
136         ret = usb9pfs_queue_tx(usb9pfs, p9_req, GFP_ATOMIC);
137         if (ret)
138                 return ret;
139 
140         list_del(&p9_req->req_list);
141 
142         p9_req_get(p9_req);
143 
144         return ret;
145 }
146 
147 static void usb9pfs_tx_complete(struct usb_ep *ep, struct usb_request *req)
148 {
149         struct f_usb9pfs *usb9pfs = ep->driver_data;
150         struct usb_composite_dev *cdev = usb9pfs->function.config->cdev;
151         struct p9_req_t *p9_tx_req = req->context;
152         unsigned long flags;
153 
154         /* reset zero packages */
155         req->zero = 0;
156 
157         if (req->status) {
158                 dev_err(&cdev->gadget->dev, "%s usb9pfs complete --> %d, %d/%d\n",
159                         ep->name, req->status, req->actual, req->length);
160                 return;
161         }
162 
163         dev_dbg(&cdev->gadget->dev, "%s usb9pfs complete --> %d, %d/%d\n",
164                 ep->name, req->status, req->actual, req->length);
165 
166         spin_lock_irqsave(&usb9pfs->lock, flags);
167         WRITE_ONCE(p9_tx_req->status, REQ_STATUS_SENT);
168 
169         p9_req_put(usb9pfs->client, p9_tx_req);
170 
171         req->context = NULL;
172 
173         spin_unlock_irqrestore(&usb9pfs->lock, flags);
174 
175         complete(&usb9pfs->send);
176 }
177 
178 static struct p9_req_t *usb9pfs_rx_header(struct f_usb9pfs *usb9pfs, void *buf)
179 {
180         struct p9_req_t *p9_rx_req;
181         struct p9_fcall rc;
182         int ret;
183 
184         /* start by reading header */
185         rc.sdata = buf;
186         rc.offset = 0;
187         rc.capacity = P9_HDRSZ;
188         rc.size = P9_HDRSZ;
189 
190         p9_debug(P9_DEBUG_TRANS, "mux %p got %zu bytes\n", usb9pfs,
191                  rc.capacity - rc.offset);
192 
193         ret = p9_parse_header(&rc, &rc.size, NULL, NULL, 0);
194         if (ret) {
195                 p9_debug(P9_DEBUG_ERROR,
196                          "error parsing header: %d\n", ret);
197                 return NULL;
198         }
199 
200         p9_debug(P9_DEBUG_TRANS,
201                  "mux %p pkt: size: %d bytes tag: %d\n",
202                  usb9pfs, rc.size, rc.tag);
203 
204         p9_rx_req = p9_tag_lookup(usb9pfs->client, rc.tag);
205         if (!p9_rx_req || p9_rx_req->status != REQ_STATUS_SENT) {
206                 p9_debug(P9_DEBUG_ERROR, "Unexpected packet tag %d\n", rc.tag);
207                 return NULL;
208         }
209 
210         if (rc.size > p9_rx_req->rc.capacity) {
211                 p9_debug(P9_DEBUG_ERROR,
212                          "requested packet size too big: %d for tag %d with capacity %zd\n",
213                          rc.size, rc.tag, p9_rx_req->rc.capacity);
214                 p9_req_put(usb9pfs->client, p9_rx_req);
215                 return NULL;
216         }
217 
218         if (!p9_rx_req->rc.sdata) {
219                 p9_debug(P9_DEBUG_ERROR,
220                          "No recv fcall for tag %d (req %p), disconnecting!\n",
221                          rc.tag, p9_rx_req);
222                 p9_req_put(usb9pfs->client, p9_rx_req);
223                 return NULL;
224         }
225 
226         return p9_rx_req;
227 }
228 
229 static void usb9pfs_rx_complete(struct usb_ep *ep, struct usb_request *req)
230 {
231         struct f_usb9pfs *usb9pfs = ep->driver_data;
232         struct usb_composite_dev *cdev = usb9pfs->function.config->cdev;
233         struct p9_req_t *p9_rx_req;
234 
235         if (req->status) {
236                 dev_err(&cdev->gadget->dev, "%s usb9pfs complete --> %d, %d/%d\n",
237                         ep->name, req->status, req->actual, req->length);
238                 return;
239         }
240 
241         p9_rx_req = usb9pfs_rx_header(usb9pfs, req->buf);
242         if (!p9_rx_req)
243                 return;
244 
245         memcpy(p9_rx_req->rc.sdata, req->buf, req->actual);
246 
247         p9_rx_req->rc.size = req->actual;
248 
249         p9_client_cb(usb9pfs->client, p9_rx_req, REQ_STATUS_RCVD);
250         p9_req_put(usb9pfs->client, p9_rx_req);
251 
252         complete(&usb9pfs->received);
253 }
254 
255 static void disable_ep(struct usb_composite_dev *cdev, struct usb_ep *ep)
256 {
257         int value;
258 
259         value = usb_ep_disable(ep);
260         if (value < 0)
261                 dev_info(&cdev->gadget->dev,
262                          "disable %s --> %d\n", ep->name, value);
263 }
264 
265 static void disable_usb9pfs(struct f_usb9pfs *usb9pfs)
266 {
267         struct usb_composite_dev *cdev =
268                 usb9pfs->function.config->cdev;
269 
270         if (usb9pfs->in_req) {
271                 usb_ep_free_request(usb9pfs->in_ep, usb9pfs->in_req);
272                 usb9pfs->in_req = NULL;
273         }
274 
275         if (usb9pfs->out_req) {
276                 usb_ep_free_request(usb9pfs->out_ep, usb9pfs->out_req);
277                 usb9pfs->out_req = NULL;
278         }
279 
280         disable_ep(cdev, usb9pfs->in_ep);
281         disable_ep(cdev, usb9pfs->out_ep);
282         dev_dbg(&cdev->gadget->dev, "%s disabled\n",
283                 usb9pfs->function.name);
284 }
285 
286 static int alloc_requests(struct usb_composite_dev *cdev,
287                           struct f_usb9pfs *usb9pfs)
288 {
289         int ret;
290 
291         usb9pfs->in_req = usb_ep_alloc_request(usb9pfs->in_ep, GFP_ATOMIC);
292         if (!usb9pfs->in_req) {
293                 ret = -ENOENT;
294                 goto fail;
295         }
296 
297         usb9pfs->out_req = alloc_ep_req(usb9pfs->out_ep, usb9pfs->buflen);
298         if (!usb9pfs->out_req) {
299                 ret = -ENOENT;
300                 goto fail_in;
301         }
302 
303         usb9pfs->in_req->complete = usb9pfs_tx_complete;
304         usb9pfs->out_req->complete = usb9pfs_rx_complete;
305 
306         /* length will be set in complete routine */
307         usb9pfs->in_req->context = usb9pfs;
308         usb9pfs->out_req->context = usb9pfs;
309 
310         return 0;
311 
312 fail_in:
313         usb_ep_free_request(usb9pfs->in_ep, usb9pfs->in_req);
314 fail:
315         return ret;
316 }
317 
318 static int enable_endpoint(struct usb_composite_dev *cdev,
319                            struct f_usb9pfs *usb9pfs, struct usb_ep *ep)
320 {
321         int ret;
322 
323         ret = config_ep_by_speed(cdev->gadget, &usb9pfs->function, ep);
324         if (ret)
325                 return ret;
326 
327         ret = usb_ep_enable(ep);
328         if (ret < 0)
329                 return ret;
330 
331         ep->driver_data = usb9pfs;
332 
333         return 0;
334 }
335 
336 static int
337 enable_usb9pfs(struct usb_composite_dev *cdev, struct f_usb9pfs *usb9pfs)
338 {
339         struct p9_client *client;
340         int ret = 0;
341 
342         ret = enable_endpoint(cdev, usb9pfs, usb9pfs->in_ep);
343         if (ret)
344                 goto out;
345 
346         ret = enable_endpoint(cdev, usb9pfs, usb9pfs->out_ep);
347         if (ret)
348                 goto disable_in;
349 
350         ret = alloc_requests(cdev, usb9pfs);
351         if (ret)
352                 goto disable_out;
353 
354         client = usb9pfs->client;
355         if (client)
356                 client->status = Connected;
357 
358         dev_dbg(&cdev->gadget->dev, "%s enabled\n", usb9pfs->function.name);
359         return 0;
360 
361 disable_out:
362         usb_ep_disable(usb9pfs->out_ep);
363 disable_in:
364         usb_ep_disable(usb9pfs->in_ep);
365 out:
366         return ret;
367 }
368 
369 static int p9_usbg_create(struct p9_client *client, const char *devname, char *args)
370 {
371         struct f_usb9pfs_dev *dev;
372         struct f_usb9pfs *usb9pfs;
373         int ret = -ENOENT;
374         int found = 0;
375 
376         if (!devname)
377                 return -EINVAL;
378 
379         guard(mutex)(&usb9pfs_lock);
380 
381         list_for_each_entry(dev, &usbg_instance_list, usb9pfs_instance) {
382                 if (!strncmp(devname, dev->tag, strlen(devname))) {
383                         if (!dev->inuse) {
384                                 dev->inuse = true;
385                                 found = 1;
386                                 break;
387                         }
388                         ret = -EBUSY;
389                         break;
390                 }
391         }
392 
393         if (!found) {
394                 pr_err("no channels available for device %s\n", devname);
395                 return ret;
396         }
397 
398         usb9pfs = dev->usb9pfs;
399         if (!usb9pfs)
400                 return -EINVAL;
401 
402         client->trans = (void *)usb9pfs;
403         if (!usb9pfs->in_req)
404                 client->status = Disconnected;
405         else
406                 client->status = Connected;
407         usb9pfs->client = client;
408 
409         client->trans_mod->maxsize = usb9pfs->buflen;
410 
411         complete(&usb9pfs->received);
412 
413         return 0;
414 }
415 
416 static void usb9pfs_clear_tx(struct f_usb9pfs *usb9pfs)
417 {
418         struct p9_req_t *req;
419 
420         guard(spinlock_irqsave)(&usb9pfs->lock);
421 
422         req = usb9pfs->in_req->context;
423         if (!req)
424                 return;
425 
426         if (!req->t_err)
427                 req->t_err = -ECONNRESET;
428 
429         p9_client_cb(usb9pfs->client, req, REQ_STATUS_ERROR);
430 }
431 
432 static void p9_usbg_close(struct p9_client *client)
433 {
434         struct f_usb9pfs *usb9pfs;
435         struct f_usb9pfs_dev *dev;
436         struct f_usb9pfs_opts *opts;
437 
438         if (!client)
439                 return;
440 
441         usb9pfs = client->trans;
442         if (!usb9pfs)
443                 return;
444 
445         client->status = Disconnected;
446 
447         usb9pfs_clear_tx(usb9pfs);
448 
449         opts = container_of(usb9pfs->function.fi,
450                             struct f_usb9pfs_opts, func_inst);
451 
452         dev = opts->dev;
453 
454         mutex_lock(&usb9pfs_lock);
455         dev->inuse = false;
456         mutex_unlock(&usb9pfs_lock);
457 }
458 
459 static int p9_usbg_request(struct p9_client *client, struct p9_req_t *p9_req)
460 {
461         struct f_usb9pfs *usb9pfs = client->trans;
462         int ret;
463 
464         if (client->status != Connected)
465                 return -EBUSY;
466 
467         ret = wait_for_completion_killable(&usb9pfs->received);
468         if (ret)
469                 return ret;
470 
471         ret = usb9pfs_transmit(usb9pfs, p9_req);
472         if (ret)
473                 return ret;
474 
475         ret = wait_for_completion_killable(&usb9pfs->send);
476         if (ret)
477                 return ret;
478 
479         return usb9pfs_queue_rx(usb9pfs, usb9pfs->out_req, GFP_ATOMIC);
480 }
481 
482 static int p9_usbg_cancel(struct p9_client *client, struct p9_req_t *req)
483 {
484         struct f_usb9pfs *usb9pfs = client->trans;
485         int ret = 1;
486 
487         p9_debug(P9_DEBUG_TRANS, "client %p req %p\n", client, req);
488 
489         guard(spinlock_irqsave)(&usb9pfs->lock);
490 
491         if (req->status == REQ_STATUS_UNSENT) {
492                 list_del(&req->req_list);
493                 WRITE_ONCE(req->status, REQ_STATUS_FLSHD);
494                 p9_req_put(client, req);
495                 ret = 0;
496         }
497 
498         return ret;
499 }
500 
501 static struct p9_trans_module p9_usbg_trans = {
502         .name = "usbg",
503         .create = p9_usbg_create,
504         .close = p9_usbg_close,
505         .request = p9_usbg_request,
506         .cancel = p9_usbg_cancel,
507         .owner = THIS_MODULE,
508 };
509 
510 /*-------------------------------------------------------------------------*/
511 
512 #define USB_PROTOCOL_9PFS       0x09
513 
514 static struct usb_interface_descriptor usb9pfs_intf = {
515         .bLength =              sizeof(usb9pfs_intf),
516         .bDescriptorType =      USB_DT_INTERFACE,
517 
518         .bNumEndpoints =        2,
519         .bInterfaceClass =      USB_CLASS_VENDOR_SPEC,
520         .bInterfaceSubClass =   USB_SUBCLASS_VENDOR_SPEC,
521         .bInterfaceProtocol =   USB_PROTOCOL_9PFS,
522 
523         /* .iInterface = DYNAMIC */
524 };
525 
526 /* full speed support: */
527 
528 static struct usb_endpoint_descriptor fs_usb9pfs_source_desc = {
529         .bLength =              USB_DT_ENDPOINT_SIZE,
530         .bDescriptorType =      USB_DT_ENDPOINT,
531 
532         .bEndpointAddress =     USB_DIR_IN,
533         .bmAttributes =         USB_ENDPOINT_XFER_BULK,
534 };
535 
536 static struct usb_endpoint_descriptor fs_usb9pfs_sink_desc = {
537         .bLength =              USB_DT_ENDPOINT_SIZE,
538         .bDescriptorType =      USB_DT_ENDPOINT,
539 
540         .bEndpointAddress =     USB_DIR_OUT,
541         .bmAttributes =         USB_ENDPOINT_XFER_BULK,
542 };
543 
544 static struct usb_descriptor_header *fs_usb9pfs_descs[] = {
545         (struct usb_descriptor_header *)&usb9pfs_intf,
546         (struct usb_descriptor_header *)&fs_usb9pfs_sink_desc,
547         (struct usb_descriptor_header *)&fs_usb9pfs_source_desc,
548         NULL,
549 };
550 
551 /* high speed support: */
552 
553 static struct usb_endpoint_descriptor hs_usb9pfs_source_desc = {
554         .bLength =              USB_DT_ENDPOINT_SIZE,
555         .bDescriptorType =      USB_DT_ENDPOINT,
556 
557         .bmAttributes =         USB_ENDPOINT_XFER_BULK,
558         .wMaxPacketSize =       cpu_to_le16(512),
559 };
560 
561 static struct usb_endpoint_descriptor hs_usb9pfs_sink_desc = {
562         .bLength =              USB_DT_ENDPOINT_SIZE,
563         .bDescriptorType =      USB_DT_ENDPOINT,
564 
565         .bmAttributes =         USB_ENDPOINT_XFER_BULK,
566         .wMaxPacketSize =       cpu_to_le16(512),
567 };
568 
569 static struct usb_descriptor_header *hs_usb9pfs_descs[] = {
570         (struct usb_descriptor_header *)&usb9pfs_intf,
571         (struct usb_descriptor_header *)&hs_usb9pfs_source_desc,
572         (struct usb_descriptor_header *)&hs_usb9pfs_sink_desc,
573         NULL,
574 };
575 
576 /* super speed support: */
577 
578 static struct usb_endpoint_descriptor ss_usb9pfs_source_desc = {
579         .bLength =              USB_DT_ENDPOINT_SIZE,
580         .bDescriptorType =      USB_DT_ENDPOINT,
581 
582         .bmAttributes =         USB_ENDPOINT_XFER_BULK,
583         .wMaxPacketSize =       cpu_to_le16(1024),
584 };
585 
586 static struct usb_ss_ep_comp_descriptor ss_usb9pfs_source_comp_desc = {
587         .bLength =              USB_DT_SS_EP_COMP_SIZE,
588         .bDescriptorType =      USB_DT_SS_ENDPOINT_COMP,
589         .bMaxBurst =            0,
590         .bmAttributes =         0,
591         .wBytesPerInterval =    0,
592 };
593 
594 static struct usb_endpoint_descriptor ss_usb9pfs_sink_desc = {
595         .bLength =              USB_DT_ENDPOINT_SIZE,
596         .bDescriptorType =      USB_DT_ENDPOINT,
597 
598         .bmAttributes =         USB_ENDPOINT_XFER_BULK,
599         .wMaxPacketSize =       cpu_to_le16(1024),
600 };
601 
602 static struct usb_ss_ep_comp_descriptor ss_usb9pfs_sink_comp_desc = {
603         .bLength =              USB_DT_SS_EP_COMP_SIZE,
604         .bDescriptorType =      USB_DT_SS_ENDPOINT_COMP,
605         .bMaxBurst =            0,
606         .bmAttributes =         0,
607         .wBytesPerInterval =    0,
608 };
609 
610 static struct usb_descriptor_header *ss_usb9pfs_descs[] = {
611         (struct usb_descriptor_header *)&usb9pfs_intf,
612         (struct usb_descriptor_header *)&ss_usb9pfs_source_desc,
613         (struct usb_descriptor_header *)&ss_usb9pfs_source_comp_desc,
614         (struct usb_descriptor_header *)&ss_usb9pfs_sink_desc,
615         (struct usb_descriptor_header *)&ss_usb9pfs_sink_comp_desc,
616         NULL,
617 };
618 
619 /* function-specific strings: */
620 static struct usb_string strings_usb9pfs[] = {
621         [0].s = "usb9pfs input to output",
622         {  }                    /* end of list */
623 };
624 
625 static struct usb_gadget_strings stringtab_usb9pfs = {
626         .language       = 0x0409,       /* en-us */
627         .strings        = strings_usb9pfs,
628 };
629 
630 static struct usb_gadget_strings *usb9pfs_strings[] = {
631         &stringtab_usb9pfs,
632         NULL,
633 };
634 
635 /*-------------------------------------------------------------------------*/
636 
637 static int usb9pfs_func_bind(struct usb_configuration *c,
638                              struct usb_function *f)
639 {
640         struct f_usb9pfs *usb9pfs = func_to_usb9pfs(f);
641         struct f_usb9pfs_opts *opts;
642         struct usb_composite_dev *cdev = c->cdev;
643         int ret;
644         int id;
645 
646         /* allocate interface ID(s) */
647         id = usb_interface_id(c, f);
648         if (id < 0)
649                 return id;
650         usb9pfs_intf.bInterfaceNumber = id;
651 
652         id = usb_string_id(cdev);
653         if (id < 0)
654                 return id;
655         strings_usb9pfs[0].id = id;
656         usb9pfs_intf.iInterface = id;
657 
658         /* allocate endpoints */
659         usb9pfs->in_ep = usb_ep_autoconfig(cdev->gadget,
660                                            &fs_usb9pfs_source_desc);
661         if (!usb9pfs->in_ep)
662                 goto autoconf_fail;
663 
664         usb9pfs->out_ep = usb_ep_autoconfig(cdev->gadget,
665                                             &fs_usb9pfs_sink_desc);
666         if (!usb9pfs->out_ep)
667                 goto autoconf_fail;
668 
669         /* support high speed hardware */
670         hs_usb9pfs_source_desc.bEndpointAddress =
671                 fs_usb9pfs_source_desc.bEndpointAddress;
672         hs_usb9pfs_sink_desc.bEndpointAddress =
673                 fs_usb9pfs_sink_desc.bEndpointAddress;
674 
675         /* support super speed hardware */
676         ss_usb9pfs_source_desc.bEndpointAddress =
677                 fs_usb9pfs_source_desc.bEndpointAddress;
678         ss_usb9pfs_sink_desc.bEndpointAddress =
679                 fs_usb9pfs_sink_desc.bEndpointAddress;
680 
681         ret = usb_assign_descriptors(f, fs_usb9pfs_descs, hs_usb9pfs_descs,
682                                      ss_usb9pfs_descs, ss_usb9pfs_descs);
683         if (ret)
684                 return ret;
685 
686         opts = container_of(f->fi, struct f_usb9pfs_opts, func_inst);
687         opts->dev->usb9pfs = usb9pfs;
688 
689         dev_dbg(&cdev->gadget->dev, "%s speed %s: IN/%s, OUT/%s\n",
690                 (gadget_is_superspeed(c->cdev->gadget) ? "super" :
691                 (gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full")),
692                         f->name, usb9pfs->in_ep->name, usb9pfs->out_ep->name);
693 
694         return 0;
695 
696 autoconf_fail:
697         ERROR(cdev, "%s: can't autoconfigure on %s\n",
698               f->name, cdev->gadget->name);
699         return -ENODEV;
700 }
701 
702 static void usb9pfs_func_unbind(struct usb_configuration *c,
703                                 struct usb_function *f)
704 {
705         struct f_usb9pfs *usb9pfs = func_to_usb9pfs(f);
706 
707         disable_usb9pfs(usb9pfs);
708 }
709 
710 static void usb9pfs_free_func(struct usb_function *f)
711 {
712         struct f_usb9pfs *usb9pfs = func_to_usb9pfs(f);
713         struct f_usb9pfs_opts *opts;
714 
715         kfree(usb9pfs);
716 
717         opts = container_of(f->fi, struct f_usb9pfs_opts, func_inst);
718 
719         mutex_lock(&opts->lock);
720         opts->refcnt--;
721         mutex_unlock(&opts->lock);
722 
723         usb_free_all_descriptors(f);
724 }
725 
726 static int usb9pfs_set_alt(struct usb_function *f,
727                            unsigned int intf, unsigned int alt)
728 {
729         struct f_usb9pfs *usb9pfs = func_to_usb9pfs(f);
730         struct usb_composite_dev *cdev = f->config->cdev;
731 
732         return enable_usb9pfs(cdev, usb9pfs);
733 }
734 
735 static void usb9pfs_disable(struct usb_function *f)
736 {
737         struct f_usb9pfs *usb9pfs = func_to_usb9pfs(f);
738 
739         usb9pfs_clear_tx(usb9pfs);
740 }
741 
742 static struct usb_function *usb9pfs_alloc(struct usb_function_instance *fi)
743 {
744         struct f_usb9pfs_opts *usb9pfs_opts;
745         struct f_usb9pfs *usb9pfs;
746 
747         usb9pfs = kzalloc(sizeof(*usb9pfs), GFP_KERNEL);
748         if (!usb9pfs)
749                 return ERR_PTR(-ENOMEM);
750 
751         spin_lock_init(&usb9pfs->lock);
752 
753         init_completion(&usb9pfs->send);
754         init_completion(&usb9pfs->received);
755 
756         usb9pfs_opts = container_of(fi, struct f_usb9pfs_opts, func_inst);
757 
758         mutex_lock(&usb9pfs_opts->lock);
759         usb9pfs_opts->refcnt++;
760         mutex_unlock(&usb9pfs_opts->lock);
761 
762         usb9pfs->buflen = usb9pfs_opts->buflen;
763 
764         usb9pfs->function.name = "usb9pfs";
765         usb9pfs->function.bind = usb9pfs_func_bind;
766         usb9pfs->function.unbind = usb9pfs_func_unbind;
767         usb9pfs->function.set_alt = usb9pfs_set_alt;
768         usb9pfs->function.disable = usb9pfs_disable;
769         usb9pfs->function.strings = usb9pfs_strings;
770 
771         usb9pfs->function.free_func = usb9pfs_free_func;
772 
773         return &usb9pfs->function;
774 }
775 
776 static inline struct f_usb9pfs_opts *to_f_usb9pfs_opts(struct config_item *item)
777 {
778         return container_of(to_config_group(item), struct f_usb9pfs_opts,
779                             func_inst.group);
780 }
781 
782 static inline struct f_usb9pfs_opts *fi_to_f_usb9pfs_opts(struct usb_function_instance *fi)
783 {
784         return container_of(fi, struct f_usb9pfs_opts, func_inst);
785 }
786 
787 static void usb9pfs_attr_release(struct config_item *item)
788 {
789         struct f_usb9pfs_opts *usb9pfs_opts = to_f_usb9pfs_opts(item);
790 
791         usb_put_function_instance(&usb9pfs_opts->func_inst);
792 }
793 
794 static struct configfs_item_operations usb9pfs_item_ops = {
795         .release                = usb9pfs_attr_release,
796 };
797 
798 static ssize_t f_usb9pfs_opts_buflen_show(struct config_item *item, char *page)
799 {
800         struct f_usb9pfs_opts *opts = to_f_usb9pfs_opts(item);
801         int ret;
802 
803         mutex_lock(&opts->lock);
804         ret = sysfs_emit(page, "%d\n", opts->buflen);
805         mutex_unlock(&opts->lock);
806 
807         return ret;
808 }
809 
810 static ssize_t f_usb9pfs_opts_buflen_store(struct config_item *item,
811                                            const char *page, size_t len)
812 {
813         struct f_usb9pfs_opts *opts = to_f_usb9pfs_opts(item);
814         int ret;
815         u32 num;
816 
817         guard(mutex)(&opts->lock);
818 
819         if (opts->refcnt)
820                 return -EBUSY;
821 
822         ret = kstrtou32(page, 0, &num);
823         if (ret)
824                 return ret;
825 
826         opts->buflen = num;
827 
828         return len;
829 }
830 
831 CONFIGFS_ATTR(f_usb9pfs_opts_, buflen);
832 
833 static struct configfs_attribute *usb9pfs_attrs[] = {
834         &f_usb9pfs_opts_attr_buflen,
835         NULL,
836 };
837 
838 static const struct config_item_type usb9pfs_func_type = {
839         .ct_item_ops    = &usb9pfs_item_ops,
840         .ct_attrs       = usb9pfs_attrs,
841         .ct_owner       = THIS_MODULE,
842 };
843 
844 static struct f_usb9pfs_dev *_usb9pfs_do_find_dev(const char *tag)
845 {
846         struct f_usb9pfs_dev *usb9pfs_dev;
847 
848         if (!tag)
849                 return NULL;
850 
851         list_for_each_entry(usb9pfs_dev, &usbg_instance_list, usb9pfs_instance) {
852                 if (strcmp(usb9pfs_dev->tag, tag) == 0)
853                         return usb9pfs_dev;
854         }
855 
856         return NULL;
857 }
858 
859 static int usb9pfs_tag_instance(struct f_usb9pfs_dev *dev, const char *tag)
860 {
861         struct f_usb9pfs_dev *existing;
862         int ret = 0;
863 
864         guard(mutex)(&usb9pfs_lock);
865 
866         existing = _usb9pfs_do_find_dev(tag);
867         if (!existing)
868                 strscpy(dev->tag, tag, ARRAY_SIZE(dev->tag));
869         else if (existing != dev)
870                 ret = -EBUSY;
871 
872         return ret;
873 }
874 
875 static int usb9pfs_set_inst_tag(struct usb_function_instance *fi, const char *tag)
876 {
877         if (strlen(tag) >= sizeof_field(struct f_usb9pfs_dev, tag))
878                 return -ENAMETOOLONG;
879         return usb9pfs_tag_instance(fi_to_f_usb9pfs_opts(fi)->dev, tag);
880 }
881 
882 static void usb9pfs_free_instance(struct usb_function_instance *fi)
883 {
884         struct f_usb9pfs_opts *usb9pfs_opts =
885                 container_of(fi, struct f_usb9pfs_opts, func_inst);
886         struct f_usb9pfs_dev *dev = usb9pfs_opts->dev;
887 
888         mutex_lock(&usb9pfs_lock);
889         list_del(&dev->usb9pfs_instance);
890         mutex_unlock(&usb9pfs_lock);
891 
892         kfree(usb9pfs_opts);
893 }
894 
895 static struct usb_function_instance *usb9pfs_alloc_instance(void)
896 {
897         struct f_usb9pfs_opts *usb9pfs_opts;
898         struct f_usb9pfs_dev *dev;
899 
900         usb9pfs_opts = kzalloc(sizeof(*usb9pfs_opts), GFP_KERNEL);
901         if (!usb9pfs_opts)
902                 return ERR_PTR(-ENOMEM);
903 
904         mutex_init(&usb9pfs_opts->lock);
905 
906         usb9pfs_opts->func_inst.set_inst_name = usb9pfs_set_inst_tag;
907         usb9pfs_opts->func_inst.free_func_inst = usb9pfs_free_instance;
908 
909         usb9pfs_opts->buflen = DEFAULT_BUFLEN;
910 
911         dev = kzalloc(sizeof(*dev), GFP_KERNEL);
912         if (IS_ERR(dev)) {
913                 kfree(usb9pfs_opts);
914                 return ERR_CAST(dev);
915         }
916 
917         usb9pfs_opts->dev = dev;
918         dev->opts = usb9pfs_opts;
919 
920         config_group_init_type_name(&usb9pfs_opts->func_inst.group, "",
921                                     &usb9pfs_func_type);
922 
923         mutex_lock(&usb9pfs_lock);
924         list_add_tail(&dev->usb9pfs_instance, &usbg_instance_list);
925         mutex_unlock(&usb9pfs_lock);
926 
927         return &usb9pfs_opts->func_inst;
928 }
929 DECLARE_USB_FUNCTION(usb9pfs, usb9pfs_alloc_instance, usb9pfs_alloc);
930 
931 static int __init usb9pfs_modinit(void)
932 {
933         int ret;
934 
935         INIT_LIST_HEAD(&usbg_instance_list);
936 
937         ret = usb_function_register(&usb9pfsusb_func);
938         if (!ret)
939                 v9fs_register_trans(&p9_usbg_trans);
940 
941         return ret;
942 }
943 
944 static void __exit usb9pfs_modexit(void)
945 {
946         usb_function_unregister(&usb9pfsusb_func);
947         v9fs_unregister_trans(&p9_usbg_trans);
948 }
949 
950 module_init(usb9pfs_modinit);
951 module_exit(usb9pfs_modexit);
952 
953 MODULE_ALIAS_9P("usbg");
954 MODULE_LICENSE("GPL");
955 MODULE_DESCRIPTION("USB gadget 9pfs transport");
956 MODULE_AUTHOR("Michael Grzeschik");
957 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php