diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-10-08 06:47:31 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-10-08 06:47:31 -0400 |
commit | 463311960e9312245418af98dce8c0161fd6b827 (patch) | |
tree | 9529b6063b10f1b85408ef4757d1917dfdb8292d /drivers/usb/gadget/function | |
parent | 87d7bcee4f5973a593b0d50134364cfe5652ff33 (diff) | |
parent | 4ed9a3d455558406cad83d38764ee659de25851c (diff) |
Merge tag 'usb-3.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB updates from Greg KH:
"Here's the big USB patchset for 3.18-rc1. Also in here is the PHY
tree, as it seems to fit well with the USB tree for various reasons...
Anyway, lots of little changes in here, all over the place, full
details in the changelog
All have been in the linux-next tree for a while with no issues"
* tag 'usb-3.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (244 commits)
USB: host: st: fix typo 'CONFIG_USB_EHCI_HCD_ST'
uas: Reduce number of function arguments for uas_alloc_foo functions
xhci: Allow xHCI drivers to be built as separate modules
xhci: Export symbols used by host-controller drivers
xhci: Check for XHCI_COMP_MODE_QUIRK when disabling D3cold
xhci: Introduce xhci_init_driver()
usb: hcd: add generic PHY support
usb: rename phy to usb_phy in HCD
usb: gadget: uvc: fix up uvcg_v4l2_get_unmapped_area typo
USB: host: st: fix ehci/ohci driver selection
usb: host: ehci-exynos: Remove unnecessary usb-phy support
usb: core: return -ENOTSUPP for all targeted hosts
USB: Remove .owner field for driver
usb: core: log higher level message on malformed LANGID descriptor
usb: Add LED triggers for USB activity
usb: Rename usb-common.c
usb: gadget: Refactor request completion
usb: gadget: Introduce usb_gadget_giveback_request()
usb: dwc2/gadget: move phy bus legth initialization
phy: remove .owner field for drivers using module_platform_driver
...
Diffstat (limited to 'drivers/usb/gadget/function')
26 files changed, 1829 insertions, 715 deletions
diff --git a/drivers/usb/gadget/function/Makefile b/drivers/usb/gadget/function/Makefile index 83ae1065149d..90701aa5a826 100644 --- a/drivers/usb/gadget/function/Makefile +++ b/drivers/usb/gadget/function/Makefile | |||
@@ -2,8 +2,8 @@ | |||
2 | # USB peripheral controller drivers | 2 | # USB peripheral controller drivers |
3 | # | 3 | # |
4 | 4 | ||
5 | ccflags-y := -Idrivers/usb/gadget/ | 5 | ccflags-y := -I$(srctree)/drivers/usb/gadget/ |
6 | ccflags-y += -Idrivers/usb/gadget/udc/ | 6 | ccflags-y += -I$(srctree)/drivers/usb/gadget/udc/ |
7 | 7 | ||
8 | # USB Functions | 8 | # USB Functions |
9 | usb_f_acm-y := f_acm.o | 9 | usb_f_acm-y := f_acm.o |
@@ -32,3 +32,9 @@ usb_f_mass_storage-y := f_mass_storage.o storage_common.o | |||
32 | obj-$(CONFIG_USB_F_MASS_STORAGE)+= usb_f_mass_storage.o | 32 | obj-$(CONFIG_USB_F_MASS_STORAGE)+= usb_f_mass_storage.o |
33 | usb_f_fs-y := f_fs.o | 33 | usb_f_fs-y := f_fs.o |
34 | obj-$(CONFIG_USB_F_FS) += usb_f_fs.o | 34 | obj-$(CONFIG_USB_F_FS) += usb_f_fs.o |
35 | usb_f_uac1-y := f_uac1.o u_uac1.o | ||
36 | obj-$(CONFIG_USB_F_UAC1) += usb_f_uac1.o | ||
37 | usb_f_uac2-y := f_uac2.o | ||
38 | obj-$(CONFIG_USB_F_UAC2) += usb_f_uac2.o | ||
39 | usb_f_uvc-y := f_uvc.o uvc_queue.o uvc_v4l2.o uvc_video.o | ||
40 | obj-$(CONFIG_USB_F_UVC) += usb_f_uvc.o | ||
diff --git a/drivers/usb/gadget/function/f_acm.c b/drivers/usb/gadget/function/f_acm.c index ab1065afbbd0..6da4685490ef 100644 --- a/drivers/usb/gadget/function/f_acm.c +++ b/drivers/usb/gadget/function/f_acm.c | |||
@@ -313,15 +313,15 @@ static void acm_complete_set_line_coding(struct usb_ep *ep, | |||
313 | struct usb_composite_dev *cdev = acm->port.func.config->cdev; | 313 | struct usb_composite_dev *cdev = acm->port.func.config->cdev; |
314 | 314 | ||
315 | if (req->status != 0) { | 315 | if (req->status != 0) { |
316 | DBG(cdev, "acm ttyGS%d completion, err %d\n", | 316 | dev_dbg(&cdev->gadget->dev, "acm ttyGS%d completion, err %d\n", |
317 | acm->port_num, req->status); | 317 | acm->port_num, req->status); |
318 | return; | 318 | return; |
319 | } | 319 | } |
320 | 320 | ||
321 | /* normal completion */ | 321 | /* normal completion */ |
322 | if (req->actual != sizeof(acm->port_line_coding)) { | 322 | if (req->actual != sizeof(acm->port_line_coding)) { |
323 | DBG(cdev, "acm ttyGS%d short resp, len %d\n", | 323 | dev_dbg(&cdev->gadget->dev, "acm ttyGS%d short resp, len %d\n", |
324 | acm->port_num, req->actual); | 324 | acm->port_num, req->actual); |
325 | usb_ep_set_halt(ep); | 325 | usb_ep_set_halt(ep); |
326 | } else { | 326 | } else { |
327 | struct usb_cdc_line_coding *value = req->buf; | 327 | struct usb_cdc_line_coding *value = req->buf; |
@@ -397,14 +397,16 @@ static int acm_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) | |||
397 | 397 | ||
398 | default: | 398 | default: |
399 | invalid: | 399 | invalid: |
400 | VDBG(cdev, "invalid control req%02x.%02x v%04x i%04x l%d\n", | 400 | dev_vdbg(&cdev->gadget->dev, |
401 | ctrl->bRequestType, ctrl->bRequest, | 401 | "invalid control req%02x.%02x v%04x i%04x l%d\n", |
402 | w_value, w_index, w_length); | 402 | ctrl->bRequestType, ctrl->bRequest, |
403 | w_value, w_index, w_length); | ||
403 | } | 404 | } |
404 | 405 | ||
405 | /* respond with data transfer or status phase? */ | 406 | /* respond with data transfer or status phase? */ |
406 | if (value >= 0) { | 407 | if (value >= 0) { |
407 | DBG(cdev, "acm ttyGS%d req%02x.%02x v%04x i%04x l%d\n", | 408 | dev_dbg(&cdev->gadget->dev, |
409 | "acm ttyGS%d req%02x.%02x v%04x i%04x l%d\n", | ||
408 | acm->port_num, ctrl->bRequestType, ctrl->bRequest, | 410 | acm->port_num, ctrl->bRequestType, ctrl->bRequest, |
409 | w_value, w_index, w_length); | 411 | w_value, w_index, w_length); |
410 | req->zero = 0; | 412 | req->zero = 0; |
@@ -428,10 +430,12 @@ static int acm_set_alt(struct usb_function *f, unsigned intf, unsigned alt) | |||
428 | 430 | ||
429 | if (intf == acm->ctrl_id) { | 431 | if (intf == acm->ctrl_id) { |
430 | if (acm->notify->driver_data) { | 432 | if (acm->notify->driver_data) { |
431 | VDBG(cdev, "reset acm control interface %d\n", intf); | 433 | dev_vdbg(&cdev->gadget->dev, |
434 | "reset acm control interface %d\n", intf); | ||
432 | usb_ep_disable(acm->notify); | 435 | usb_ep_disable(acm->notify); |
433 | } else { | 436 | } else { |
434 | VDBG(cdev, "init acm ctrl interface %d\n", intf); | 437 | dev_vdbg(&cdev->gadget->dev, |
438 | "init acm ctrl interface %d\n", intf); | ||
435 | if (config_ep_by_speed(cdev->gadget, f, acm->notify)) | 439 | if (config_ep_by_speed(cdev->gadget, f, acm->notify)) |
436 | return -EINVAL; | 440 | return -EINVAL; |
437 | } | 441 | } |
@@ -440,11 +444,13 @@ static int acm_set_alt(struct usb_function *f, unsigned intf, unsigned alt) | |||
440 | 444 | ||
441 | } else if (intf == acm->data_id) { | 445 | } else if (intf == acm->data_id) { |
442 | if (acm->port.in->driver_data) { | 446 | if (acm->port.in->driver_data) { |
443 | DBG(cdev, "reset acm ttyGS%d\n", acm->port_num); | 447 | dev_dbg(&cdev->gadget->dev, |
448 | "reset acm ttyGS%d\n", acm->port_num); | ||
444 | gserial_disconnect(&acm->port); | 449 | gserial_disconnect(&acm->port); |
445 | } | 450 | } |
446 | if (!acm->port.in->desc || !acm->port.out->desc) { | 451 | if (!acm->port.in->desc || !acm->port.out->desc) { |
447 | DBG(cdev, "activate acm ttyGS%d\n", acm->port_num); | 452 | dev_dbg(&cdev->gadget->dev, |
453 | "activate acm ttyGS%d\n", acm->port_num); | ||
448 | if (config_ep_by_speed(cdev->gadget, f, | 454 | if (config_ep_by_speed(cdev->gadget, f, |
449 | acm->port.in) || | 455 | acm->port.in) || |
450 | config_ep_by_speed(cdev->gadget, f, | 456 | config_ep_by_speed(cdev->gadget, f, |
@@ -467,7 +473,7 @@ static void acm_disable(struct usb_function *f) | |||
467 | struct f_acm *acm = func_to_acm(f); | 473 | struct f_acm *acm = func_to_acm(f); |
468 | struct usb_composite_dev *cdev = f->config->cdev; | 474 | struct usb_composite_dev *cdev = f->config->cdev; |
469 | 475 | ||
470 | DBG(cdev, "acm ttyGS%d deactivated\n", acm->port_num); | 476 | dev_dbg(&cdev->gadget->dev, "acm ttyGS%d deactivated\n", acm->port_num); |
471 | gserial_disconnect(&acm->port); | 477 | gserial_disconnect(&acm->port); |
472 | usb_ep_disable(acm->notify); | 478 | usb_ep_disable(acm->notify); |
473 | acm->notify->driver_data = NULL; | 479 | acm->notify->driver_data = NULL; |
@@ -537,8 +543,8 @@ static int acm_notify_serial_state(struct f_acm *acm) | |||
537 | 543 | ||
538 | spin_lock(&acm->lock); | 544 | spin_lock(&acm->lock); |
539 | if (acm->notify_req) { | 545 | if (acm->notify_req) { |
540 | DBG(cdev, "acm ttyGS%d serial state %04x\n", | 546 | dev_dbg(&cdev->gadget->dev, "acm ttyGS%d serial state %04x\n", |
541 | acm->port_num, acm->serial_state); | 547 | acm->port_num, acm->serial_state); |
542 | status = acm_cdc_notify(acm, USB_CDC_NOTIFY_SERIAL_STATE, | 548 | status = acm_cdc_notify(acm, USB_CDC_NOTIFY_SERIAL_STATE, |
543 | 0, &acm->serial_state, sizeof(acm->serial_state)); | 549 | 0, &acm->serial_state, sizeof(acm->serial_state)); |
544 | } else { | 550 | } else { |
@@ -691,12 +697,13 @@ acm_bind(struct usb_configuration *c, struct usb_function *f) | |||
691 | if (status) | 697 | if (status) |
692 | goto fail; | 698 | goto fail; |
693 | 699 | ||
694 | DBG(cdev, "acm ttyGS%d: %s speed IN/%s OUT/%s NOTIFY/%s\n", | 700 | dev_dbg(&cdev->gadget->dev, |
695 | acm->port_num, | 701 | "acm ttyGS%d: %s speed IN/%s OUT/%s NOTIFY/%s\n", |
696 | gadget_is_superspeed(c->cdev->gadget) ? "super" : | 702 | acm->port_num, |
697 | gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", | 703 | gadget_is_superspeed(c->cdev->gadget) ? "super" : |
698 | acm->port.in->name, acm->port.out->name, | 704 | gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", |
699 | acm->notify->name); | 705 | acm->port.in->name, acm->port.out->name, |
706 | acm->notify->name); | ||
700 | return 0; | 707 | return 0; |
701 | 708 | ||
702 | fail: | 709 | fail: |
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 0dc3552d1360..4ad11e03cf54 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c | |||
@@ -1032,6 +1032,29 @@ static long ffs_epfile_ioctl(struct file *file, unsigned code, | |||
1032 | case FUNCTIONFS_ENDPOINT_REVMAP: | 1032 | case FUNCTIONFS_ENDPOINT_REVMAP: |
1033 | ret = epfile->ep->num; | 1033 | ret = epfile->ep->num; |
1034 | break; | 1034 | break; |
1035 | case FUNCTIONFS_ENDPOINT_DESC: | ||
1036 | { | ||
1037 | int desc_idx; | ||
1038 | struct usb_endpoint_descriptor *desc; | ||
1039 | |||
1040 | switch (epfile->ffs->gadget->speed) { | ||
1041 | case USB_SPEED_SUPER: | ||
1042 | desc_idx = 2; | ||
1043 | break; | ||
1044 | case USB_SPEED_HIGH: | ||
1045 | desc_idx = 1; | ||
1046 | break; | ||
1047 | default: | ||
1048 | desc_idx = 0; | ||
1049 | } | ||
1050 | desc = epfile->ep->descs[desc_idx]; | ||
1051 | |||
1052 | spin_unlock_irq(&epfile->ffs->eps_lock); | ||
1053 | ret = copy_to_user((void *)value, desc, sizeof(*desc)); | ||
1054 | if (ret) | ||
1055 | ret = -EFAULT; | ||
1056 | return ret; | ||
1057 | } | ||
1035 | default: | 1058 | default: |
1036 | ret = -ENOTTY; | 1059 | ret = -ENOTTY; |
1037 | } | 1060 | } |
@@ -1534,7 +1557,10 @@ static int ffs_epfiles_create(struct ffs_data *ffs) | |||
1534 | epfile->ffs = ffs; | 1557 | epfile->ffs = ffs; |
1535 | mutex_init(&epfile->mutex); | 1558 | mutex_init(&epfile->mutex); |
1536 | init_waitqueue_head(&epfile->wait); | 1559 | init_waitqueue_head(&epfile->wait); |
1537 | sprintf(epfiles->name, "ep%u", i); | 1560 | if (ffs->user_flags & FUNCTIONFS_VIRTUAL_ADDR) |
1561 | sprintf(epfiles->name, "ep%02x", ffs->eps_addrmap[i]); | ||
1562 | else | ||
1563 | sprintf(epfiles->name, "ep%u", i); | ||
1538 | if (!unlikely(ffs_sb_create_file(ffs->sb, epfiles->name, epfile, | 1564 | if (!unlikely(ffs_sb_create_file(ffs->sb, epfiles->name, epfile, |
1539 | &ffs_epfile_operations, | 1565 | &ffs_epfile_operations, |
1540 | &epfile->dentry))) { | 1566 | &epfile->dentry))) { |
@@ -2083,10 +2109,12 @@ static int __ffs_data_got_descs(struct ffs_data *ffs, | |||
2083 | break; | 2109 | break; |
2084 | case FUNCTIONFS_DESCRIPTORS_MAGIC_V2: | 2110 | case FUNCTIONFS_DESCRIPTORS_MAGIC_V2: |
2085 | flags = get_unaligned_le32(data + 8); | 2111 | flags = get_unaligned_le32(data + 8); |
2112 | ffs->user_flags = flags; | ||
2086 | if (flags & ~(FUNCTIONFS_HAS_FS_DESC | | 2113 | if (flags & ~(FUNCTIONFS_HAS_FS_DESC | |
2087 | FUNCTIONFS_HAS_HS_DESC | | 2114 | FUNCTIONFS_HAS_HS_DESC | |
2088 | FUNCTIONFS_HAS_SS_DESC | | 2115 | FUNCTIONFS_HAS_SS_DESC | |
2089 | FUNCTIONFS_HAS_MS_OS_DESC)) { | 2116 | FUNCTIONFS_HAS_MS_OS_DESC | |
2117 | FUNCTIONFS_VIRTUAL_ADDR)) { | ||
2090 | ret = -ENOSYS; | 2118 | ret = -ENOSYS; |
2091 | goto error; | 2119 | goto error; |
2092 | } | 2120 | } |
@@ -2346,7 +2374,8 @@ static void __ffs_event_add(struct ffs_data *ffs, | |||
2346 | break; | 2374 | break; |
2347 | 2375 | ||
2348 | default: | 2376 | default: |
2349 | BUG(); | 2377 | WARN(1, "%d: unknown event, this should not happen\n", type); |
2378 | return; | ||
2350 | } | 2379 | } |
2351 | 2380 | ||
2352 | { | 2381 | { |
@@ -2393,7 +2422,8 @@ static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep, | |||
2393 | struct usb_endpoint_descriptor *ds = (void *)desc; | 2422 | struct usb_endpoint_descriptor *ds = (void *)desc; |
2394 | struct ffs_function *func = priv; | 2423 | struct ffs_function *func = priv; |
2395 | struct ffs_ep *ffs_ep; | 2424 | struct ffs_ep *ffs_ep; |
2396 | unsigned ep_desc_id, idx; | 2425 | unsigned ep_desc_id; |
2426 | int idx; | ||
2397 | static const char *speed_names[] = { "full", "high", "super" }; | 2427 | static const char *speed_names[] = { "full", "high", "super" }; |
2398 | 2428 | ||
2399 | if (type != FFS_DESCRIPTOR) | 2429 | if (type != FFS_DESCRIPTOR) |
@@ -2441,7 +2471,13 @@ static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep, | |||
2441 | } else { | 2471 | } else { |
2442 | struct usb_request *req; | 2472 | struct usb_request *req; |
2443 | struct usb_ep *ep; | 2473 | struct usb_ep *ep; |
2474 | u8 bEndpointAddress; | ||
2444 | 2475 | ||
2476 | /* | ||
2477 | * We back up bEndpointAddress because autoconfig overwrites | ||
2478 | * it with physical endpoint address. | ||
2479 | */ | ||
2480 | bEndpointAddress = ds->bEndpointAddress; | ||
2445 | pr_vdebug("autoconfig\n"); | 2481 | pr_vdebug("autoconfig\n"); |
2446 | ep = usb_ep_autoconfig(func->gadget, ds); | 2482 | ep = usb_ep_autoconfig(func->gadget, ds); |
2447 | if (unlikely(!ep)) | 2483 | if (unlikely(!ep)) |
@@ -2456,6 +2492,12 @@ static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep, | |||
2456 | ffs_ep->req = req; | 2492 | ffs_ep->req = req; |
2457 | func->eps_revmap[ds->bEndpointAddress & | 2493 | func->eps_revmap[ds->bEndpointAddress & |
2458 | USB_ENDPOINT_NUMBER_MASK] = idx + 1; | 2494 | USB_ENDPOINT_NUMBER_MASK] = idx + 1; |
2495 | /* | ||
2496 | * If we use virtual address mapping, we restore | ||
2497 | * original bEndpointAddress value. | ||
2498 | */ | ||
2499 | if (func->ffs->user_flags & FUNCTIONFS_VIRTUAL_ADDR) | ||
2500 | ds->bEndpointAddress = bEndpointAddress; | ||
2459 | } | 2501 | } |
2460 | ffs_dump_mem(": Rewritten ep desc", ds, ds->bLength); | 2502 | ffs_dump_mem(": Rewritten ep desc", ds, ds->bLength); |
2461 | 2503 | ||
@@ -2900,6 +2942,8 @@ static int ffs_func_setup(struct usb_function *f, | |||
2900 | ret = ffs_func_revmap_ep(func, le16_to_cpu(creq->wIndex)); | 2942 | ret = ffs_func_revmap_ep(func, le16_to_cpu(creq->wIndex)); |
2901 | if (unlikely(ret < 0)) | 2943 | if (unlikely(ret < 0)) |
2902 | return ret; | 2944 | return ret; |
2945 | if (func->ffs->user_flags & FUNCTIONFS_VIRTUAL_ADDR) | ||
2946 | ret = func->ffs->eps_addrmap[ret]; | ||
2903 | break; | 2947 | break; |
2904 | 2948 | ||
2905 | default: | 2949 | default: |
diff --git a/drivers/usb/gadget/function/f_loopback.c b/drivers/usb/gadget/function/f_loopback.c index 4557cd03f0b1..bf04389137e6 100644 --- a/drivers/usb/gadget/function/f_loopback.c +++ b/drivers/usb/gadget/function/f_loopback.c | |||
@@ -298,7 +298,8 @@ static void disable_loopback(struct f_loopback *loop) | |||
298 | struct usb_composite_dev *cdev; | 298 | struct usb_composite_dev *cdev; |
299 | 299 | ||
300 | cdev = loop->function.config->cdev; | 300 | cdev = loop->function.config->cdev; |
301 | disable_endpoints(cdev, loop->in_ep, loop->out_ep, NULL, NULL); | 301 | disable_endpoints(cdev, loop->in_ep, loop->out_ep, NULL, NULL, NULL, |
302 | NULL); | ||
302 | VDBG(cdev, "%s disabled\n", loop->function.name); | 303 | VDBG(cdev, "%s disabled\n", loop->function.name); |
303 | } | 304 | } |
304 | 305 | ||
diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c index b96393908860..811929cd4c9e 100644 --- a/drivers/usb/gadget/function/f_mass_storage.c +++ b/drivers/usb/gadget/function/f_mass_storage.c | |||
@@ -566,22 +566,22 @@ static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep, | |||
566 | *pbusy = 1; | 566 | *pbusy = 1; |
567 | *state = BUF_STATE_BUSY; | 567 | *state = BUF_STATE_BUSY; |
568 | spin_unlock_irq(&fsg->common->lock); | 568 | spin_unlock_irq(&fsg->common->lock); |
569 | |||
569 | rc = usb_ep_queue(ep, req, GFP_KERNEL); | 570 | rc = usb_ep_queue(ep, req, GFP_KERNEL); |
570 | if (rc != 0) { | 571 | if (rc == 0) |
571 | *pbusy = 0; | 572 | return; /* All good, we're done */ |
572 | *state = BUF_STATE_EMPTY; | ||
573 | 573 | ||
574 | /* We can't do much more than wait for a reset */ | 574 | *pbusy = 0; |
575 | *state = BUF_STATE_EMPTY; | ||
575 | 576 | ||
576 | /* | 577 | /* We can't do much more than wait for a reset */ |
577 | * Note: currently the net2280 driver fails zero-length | 578 | |
578 | * submissions if DMA is enabled. | 579 | /* |
579 | */ | 580 | * Note: currently the net2280 driver fails zero-length |
580 | if (rc != -ESHUTDOWN && | 581 | * submissions if DMA is enabled. |
581 | !(rc == -EOPNOTSUPP && req->length == 0)) | 582 | */ |
582 | WARNING(fsg, "error in submission: %s --> %d\n", | 583 | if (rc != -ESHUTDOWN && !(rc == -EOPNOTSUPP && req->length == 0)) |
583 | ep->name, rc); | 584 | WARNING(fsg, "error in submission: %s --> %d\n", ep->name, rc); |
584 | } | ||
585 | } | 585 | } |
586 | 586 | ||
587 | static bool start_in_transfer(struct fsg_common *common, struct fsg_buffhd *bh) | 587 | static bool start_in_transfer(struct fsg_common *common, struct fsg_buffhd *bh) |
@@ -3665,4 +3665,3 @@ void fsg_config_from_params(struct fsg_config *cfg, | |||
3665 | cfg->fsg_num_buffers = fsg_num_buffers; | 3665 | cfg->fsg_num_buffers = fsg_num_buffers; |
3666 | } | 3666 | } |
3667 | EXPORT_SYMBOL_GPL(fsg_config_from_params); | 3667 | EXPORT_SYMBOL_GPL(fsg_config_from_params); |
3668 | |||
diff --git a/drivers/usb/gadget/function/f_obex.c b/drivers/usb/gadget/function/f_obex.c index aebae1853bce..5f40080c92cc 100644 --- a/drivers/usb/gadget/function/f_obex.c +++ b/drivers/usb/gadget/function/f_obex.c | |||
@@ -200,19 +200,22 @@ static int obex_set_alt(struct usb_function *f, unsigned intf, unsigned alt) | |||
200 | if (alt != 0) | 200 | if (alt != 0) |
201 | goto fail; | 201 | goto fail; |
202 | /* NOP */ | 202 | /* NOP */ |
203 | DBG(cdev, "reset obex ttyGS%d control\n", obex->port_num); | 203 | dev_dbg(&cdev->gadget->dev, |
204 | "reset obex ttyGS%d control\n", obex->port_num); | ||
204 | 205 | ||
205 | } else if (intf == obex->data_id) { | 206 | } else if (intf == obex->data_id) { |
206 | if (alt > 1) | 207 | if (alt > 1) |
207 | goto fail; | 208 | goto fail; |
208 | 209 | ||
209 | if (obex->port.in->driver_data) { | 210 | if (obex->port.in->driver_data) { |
210 | DBG(cdev, "reset obex ttyGS%d\n", obex->port_num); | 211 | dev_dbg(&cdev->gadget->dev, |
212 | "reset obex ttyGS%d\n", obex->port_num); | ||
211 | gserial_disconnect(&obex->port); | 213 | gserial_disconnect(&obex->port); |
212 | } | 214 | } |
213 | 215 | ||
214 | if (!obex->port.in->desc || !obex->port.out->desc) { | 216 | if (!obex->port.in->desc || !obex->port.out->desc) { |
215 | DBG(cdev, "init obex ttyGS%d\n", obex->port_num); | 217 | dev_dbg(&cdev->gadget->dev, |
218 | "init obex ttyGS%d\n", obex->port_num); | ||
216 | if (config_ep_by_speed(cdev->gadget, f, | 219 | if (config_ep_by_speed(cdev->gadget, f, |
217 | obex->port.in) || | 220 | obex->port.in) || |
218 | config_ep_by_speed(cdev->gadget, f, | 221 | config_ep_by_speed(cdev->gadget, f, |
@@ -224,7 +227,8 @@ static int obex_set_alt(struct usb_function *f, unsigned intf, unsigned alt) | |||
224 | } | 227 | } |
225 | 228 | ||
226 | if (alt == 1) { | 229 | if (alt == 1) { |
227 | DBG(cdev, "activate obex ttyGS%d\n", obex->port_num); | 230 | dev_dbg(&cdev->gadget->dev, |
231 | "activate obex ttyGS%d\n", obex->port_num); | ||
228 | gserial_connect(&obex->port, obex->port_num); | 232 | gserial_connect(&obex->port, obex->port_num); |
229 | } | 233 | } |
230 | 234 | ||
@@ -252,7 +256,7 @@ static void obex_disable(struct usb_function *f) | |||
252 | struct f_obex *obex = func_to_obex(f); | 256 | struct f_obex *obex = func_to_obex(f); |
253 | struct usb_composite_dev *cdev = f->config->cdev; | 257 | struct usb_composite_dev *cdev = f->config->cdev; |
254 | 258 | ||
255 | DBG(cdev, "obex ttyGS%d disable\n", obex->port_num); | 259 | dev_dbg(&cdev->gadget->dev, "obex ttyGS%d disable\n", obex->port_num); |
256 | gserial_disconnect(&obex->port); | 260 | gserial_disconnect(&obex->port); |
257 | } | 261 | } |
258 | 262 | ||
@@ -269,7 +273,8 @@ static void obex_connect(struct gserial *g) | |||
269 | 273 | ||
270 | status = usb_function_activate(&g->func); | 274 | status = usb_function_activate(&g->func); |
271 | if (status) | 275 | if (status) |
272 | DBG(cdev, "obex ttyGS%d function activate --> %d\n", | 276 | dev_dbg(&cdev->gadget->dev, |
277 | "obex ttyGS%d function activate --> %d\n", | ||
273 | obex->port_num, status); | 278 | obex->port_num, status); |
274 | } | 279 | } |
275 | 280 | ||
@@ -284,7 +289,8 @@ static void obex_disconnect(struct gserial *g) | |||
284 | 289 | ||
285 | status = usb_function_deactivate(&g->func); | 290 | status = usb_function_deactivate(&g->func); |
286 | if (status) | 291 | if (status) |
287 | DBG(cdev, "obex ttyGS%d function deactivate --> %d\n", | 292 | dev_dbg(&cdev->gadget->dev, |
293 | "obex ttyGS%d function deactivate --> %d\n", | ||
288 | obex->port_num, status); | 294 | obex->port_num, status); |
289 | } | 295 | } |
290 | 296 | ||
@@ -383,10 +389,10 @@ static int obex_bind(struct usb_configuration *c, struct usb_function *f) | |||
383 | obex->can_activate = true; | 389 | obex->can_activate = true; |
384 | 390 | ||
385 | 391 | ||
386 | DBG(cdev, "obex ttyGS%d: %s speed IN/%s OUT/%s\n", | 392 | dev_dbg(&cdev->gadget->dev, "obex ttyGS%d: %s speed IN/%s OUT/%s\n", |
387 | obex->port_num, | 393 | obex->port_num, |
388 | gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", | 394 | gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", |
389 | obex->port.in->name, obex->port.out->name); | 395 | obex->port.in->name, obex->port.out->name); |
390 | 396 | ||
391 | return 0; | 397 | return 0; |
392 | 398 | ||
diff --git a/drivers/usb/gadget/function/f_serial.c b/drivers/usb/gadget/function/f_serial.c index 9ecbcbf36a45..2e02dfabc7ae 100644 --- a/drivers/usb/gadget/function/f_serial.c +++ b/drivers/usb/gadget/function/f_serial.c | |||
@@ -155,11 +155,13 @@ static int gser_set_alt(struct usb_function *f, unsigned intf, unsigned alt) | |||
155 | /* we know alt == 0, so this is an activation or a reset */ | 155 | /* we know alt == 0, so this is an activation or a reset */ |
156 | 156 | ||
157 | if (gser->port.in->driver_data) { | 157 | if (gser->port.in->driver_data) { |
158 | DBG(cdev, "reset generic ttyGS%d\n", gser->port_num); | 158 | dev_dbg(&cdev->gadget->dev, |
159 | "reset generic ttyGS%d\n", gser->port_num); | ||
159 | gserial_disconnect(&gser->port); | 160 | gserial_disconnect(&gser->port); |
160 | } | 161 | } |
161 | if (!gser->port.in->desc || !gser->port.out->desc) { | 162 | if (!gser->port.in->desc || !gser->port.out->desc) { |
162 | DBG(cdev, "activate generic ttyGS%d\n", gser->port_num); | 163 | dev_dbg(&cdev->gadget->dev, |
164 | "activate generic ttyGS%d\n", gser->port_num); | ||
163 | if (config_ep_by_speed(cdev->gadget, f, gser->port.in) || | 165 | if (config_ep_by_speed(cdev->gadget, f, gser->port.in) || |
164 | config_ep_by_speed(cdev->gadget, f, gser->port.out)) { | 166 | config_ep_by_speed(cdev->gadget, f, gser->port.out)) { |
165 | gser->port.in->desc = NULL; | 167 | gser->port.in->desc = NULL; |
@@ -176,7 +178,8 @@ static void gser_disable(struct usb_function *f) | |||
176 | struct f_gser *gser = func_to_gser(f); | 178 | struct f_gser *gser = func_to_gser(f); |
177 | struct usb_composite_dev *cdev = f->config->cdev; | 179 | struct usb_composite_dev *cdev = f->config->cdev; |
178 | 180 | ||
179 | DBG(cdev, "generic ttyGS%d deactivated\n", gser->port_num); | 181 | dev_dbg(&cdev->gadget->dev, |
182 | "generic ttyGS%d deactivated\n", gser->port_num); | ||
180 | gserial_disconnect(&gser->port); | 183 | gserial_disconnect(&gser->port); |
181 | } | 184 | } |
182 | 185 | ||
@@ -239,11 +242,11 @@ static int gser_bind(struct usb_configuration *c, struct usb_function *f) | |||
239 | gser_ss_function); | 242 | gser_ss_function); |
240 | if (status) | 243 | if (status) |
241 | goto fail; | 244 | goto fail; |
242 | DBG(cdev, "generic ttyGS%d: %s speed IN/%s OUT/%s\n", | 245 | dev_dbg(&cdev->gadget->dev, "generic ttyGS%d: %s speed IN/%s OUT/%s\n", |
243 | gser->port_num, | 246 | gser->port_num, |
244 | gadget_is_superspeed(c->cdev->gadget) ? "super" : | 247 | gadget_is_superspeed(c->cdev->gadget) ? "super" : |
245 | gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", | 248 | gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", |
246 | gser->port.in->name, gser->port.out->name); | 249 | gser->port.in->name, gser->port.out->name); |
247 | return 0; | 250 | return 0; |
248 | 251 | ||
249 | fail: | 252 | fail: |
diff --git a/drivers/usb/gadget/function/f_sourcesink.c b/drivers/usb/gadget/function/f_sourcesink.c index d3cd52db78fe..80be25b32cd7 100644 --- a/drivers/usb/gadget/function/f_sourcesink.c +++ b/drivers/usb/gadget/function/f_sourcesink.c | |||
@@ -23,6 +23,15 @@ | |||
23 | #include "gadget_chips.h" | 23 | #include "gadget_chips.h" |
24 | #include "u_f.h" | 24 | #include "u_f.h" |
25 | 25 | ||
26 | #define USB_MS_TO_SS_INTERVAL(x) USB_MS_TO_HS_INTERVAL(x) | ||
27 | |||
28 | enum eptype { | ||
29 | EP_CONTROL = 0, | ||
30 | EP_BULK, | ||
31 | EP_ISOC, | ||
32 | EP_INTERRUPT, | ||
33 | }; | ||
34 | |||
26 | /* | 35 | /* |
27 | * SOURCE/SINK FUNCTION ... a primary testing vehicle for USB peripheral | 36 | * SOURCE/SINK FUNCTION ... a primary testing vehicle for USB peripheral |
28 | * controller drivers. | 37 | * controller drivers. |
@@ -55,6 +64,8 @@ struct f_sourcesink { | |||
55 | struct usb_ep *out_ep; | 64 | struct usb_ep *out_ep; |
56 | struct usb_ep *iso_in_ep; | 65 | struct usb_ep *iso_in_ep; |
57 | struct usb_ep *iso_out_ep; | 66 | struct usb_ep *iso_out_ep; |
67 | struct usb_ep *int_in_ep; | ||
68 | struct usb_ep *int_out_ep; | ||
58 | int cur_alt; | 69 | int cur_alt; |
59 | }; | 70 | }; |
60 | 71 | ||
@@ -68,6 +79,10 @@ static unsigned isoc_interval; | |||
68 | static unsigned isoc_maxpacket; | 79 | static unsigned isoc_maxpacket; |
69 | static unsigned isoc_mult; | 80 | static unsigned isoc_mult; |
70 | static unsigned isoc_maxburst; | 81 | static unsigned isoc_maxburst; |
82 | static unsigned int_interval; /* In ms */ | ||
83 | static unsigned int_maxpacket; | ||
84 | static unsigned int_mult; | ||
85 | static unsigned int_maxburst; | ||
71 | static unsigned buflen; | 86 | static unsigned buflen; |
72 | 87 | ||
73 | /*-------------------------------------------------------------------------*/ | 88 | /*-------------------------------------------------------------------------*/ |
@@ -92,6 +107,16 @@ static struct usb_interface_descriptor source_sink_intf_alt1 = { | |||
92 | /* .iInterface = DYNAMIC */ | 107 | /* .iInterface = DYNAMIC */ |
93 | }; | 108 | }; |
94 | 109 | ||
110 | static struct usb_interface_descriptor source_sink_intf_alt2 = { | ||
111 | .bLength = USB_DT_INTERFACE_SIZE, | ||
112 | .bDescriptorType = USB_DT_INTERFACE, | ||
113 | |||
114 | .bAlternateSetting = 2, | ||
115 | .bNumEndpoints = 2, | ||
116 | .bInterfaceClass = USB_CLASS_VENDOR_SPEC, | ||
117 | /* .iInterface = DYNAMIC */ | ||
118 | }; | ||
119 | |||
95 | /* full speed support: */ | 120 | /* full speed support: */ |
96 | 121 | ||
97 | static struct usb_endpoint_descriptor fs_source_desc = { | 122 | static struct usb_endpoint_descriptor fs_source_desc = { |
@@ -130,6 +155,26 @@ static struct usb_endpoint_descriptor fs_iso_sink_desc = { | |||
130 | .bInterval = 4, | 155 | .bInterval = 4, |
131 | }; | 156 | }; |
132 | 157 | ||
158 | static struct usb_endpoint_descriptor fs_int_source_desc = { | ||
159 | .bLength = USB_DT_ENDPOINT_SIZE, | ||
160 | .bDescriptorType = USB_DT_ENDPOINT, | ||
161 | |||
162 | .bEndpointAddress = USB_DIR_IN, | ||
163 | .bmAttributes = USB_ENDPOINT_XFER_INT, | ||
164 | .wMaxPacketSize = cpu_to_le16(64), | ||
165 | .bInterval = GZERO_INT_INTERVAL, | ||
166 | }; | ||
167 | |||
168 | static struct usb_endpoint_descriptor fs_int_sink_desc = { | ||
169 | .bLength = USB_DT_ENDPOINT_SIZE, | ||
170 | .bDescriptorType = USB_DT_ENDPOINT, | ||
171 | |||
172 | .bEndpointAddress = USB_DIR_OUT, | ||
173 | .bmAttributes = USB_ENDPOINT_XFER_INT, | ||
174 | .wMaxPacketSize = cpu_to_le16(64), | ||
175 | .bInterval = GZERO_INT_INTERVAL, | ||
176 | }; | ||
177 | |||
133 | static struct usb_descriptor_header *fs_source_sink_descs[] = { | 178 | static struct usb_descriptor_header *fs_source_sink_descs[] = { |
134 | (struct usb_descriptor_header *) &source_sink_intf_alt0, | 179 | (struct usb_descriptor_header *) &source_sink_intf_alt0, |
135 | (struct usb_descriptor_header *) &fs_sink_desc, | 180 | (struct usb_descriptor_header *) &fs_sink_desc, |
@@ -140,6 +185,10 @@ static struct usb_descriptor_header *fs_source_sink_descs[] = { | |||
140 | (struct usb_descriptor_header *) &fs_source_desc, | 185 | (struct usb_descriptor_header *) &fs_source_desc, |
141 | (struct usb_descriptor_header *) &fs_iso_sink_desc, | 186 | (struct usb_descriptor_header *) &fs_iso_sink_desc, |
142 | (struct usb_descriptor_header *) &fs_iso_source_desc, | 187 | (struct usb_descriptor_header *) &fs_iso_source_desc, |
188 | (struct usb_descriptor_header *) &source_sink_intf_alt2, | ||
189 | #define FS_ALT_IFC_2_OFFSET 8 | ||
190 | (struct usb_descriptor_header *) &fs_int_sink_desc, | ||
191 | (struct usb_descriptor_header *) &fs_int_source_desc, | ||
143 | NULL, | 192 | NULL, |
144 | }; | 193 | }; |
145 | 194 | ||
@@ -179,6 +228,24 @@ static struct usb_endpoint_descriptor hs_iso_sink_desc = { | |||
179 | .bInterval = 4, | 228 | .bInterval = 4, |
180 | }; | 229 | }; |
181 | 230 | ||
231 | static struct usb_endpoint_descriptor hs_int_source_desc = { | ||
232 | .bLength = USB_DT_ENDPOINT_SIZE, | ||
233 | .bDescriptorType = USB_DT_ENDPOINT, | ||
234 | |||
235 | .bmAttributes = USB_ENDPOINT_XFER_INT, | ||
236 | .wMaxPacketSize = cpu_to_le16(1024), | ||
237 | .bInterval = USB_MS_TO_HS_INTERVAL(GZERO_INT_INTERVAL), | ||
238 | }; | ||
239 | |||
240 | static struct usb_endpoint_descriptor hs_int_sink_desc = { | ||
241 | .bLength = USB_DT_ENDPOINT_SIZE, | ||
242 | .bDescriptorType = USB_DT_ENDPOINT, | ||
243 | |||
244 | .bmAttributes = USB_ENDPOINT_XFER_INT, | ||
245 | .wMaxPacketSize = cpu_to_le16(1024), | ||
246 | .bInterval = USB_MS_TO_HS_INTERVAL(GZERO_INT_INTERVAL), | ||
247 | }; | ||
248 | |||
182 | static struct usb_descriptor_header *hs_source_sink_descs[] = { | 249 | static struct usb_descriptor_header *hs_source_sink_descs[] = { |
183 | (struct usb_descriptor_header *) &source_sink_intf_alt0, | 250 | (struct usb_descriptor_header *) &source_sink_intf_alt0, |
184 | (struct usb_descriptor_header *) &hs_source_desc, | 251 | (struct usb_descriptor_header *) &hs_source_desc, |
@@ -189,6 +256,10 @@ static struct usb_descriptor_header *hs_source_sink_descs[] = { | |||
189 | (struct usb_descriptor_header *) &hs_sink_desc, | 256 | (struct usb_descriptor_header *) &hs_sink_desc, |
190 | (struct usb_descriptor_header *) &hs_iso_source_desc, | 257 | (struct usb_descriptor_header *) &hs_iso_source_desc, |
191 | (struct usb_descriptor_header *) &hs_iso_sink_desc, | 258 | (struct usb_descriptor_header *) &hs_iso_sink_desc, |
259 | (struct usb_descriptor_header *) &source_sink_intf_alt2, | ||
260 | #define HS_ALT_IFC_2_OFFSET 8 | ||
261 | (struct usb_descriptor_header *) &hs_int_source_desc, | ||
262 | (struct usb_descriptor_header *) &hs_int_sink_desc, | ||
192 | NULL, | 263 | NULL, |
193 | }; | 264 | }; |
194 | 265 | ||
@@ -264,6 +335,42 @@ static struct usb_ss_ep_comp_descriptor ss_iso_sink_comp_desc = { | |||
264 | .wBytesPerInterval = cpu_to_le16(1024), | 335 | .wBytesPerInterval = cpu_to_le16(1024), |
265 | }; | 336 | }; |
266 | 337 | ||
338 | static struct usb_endpoint_descriptor ss_int_source_desc = { | ||
339 | .bLength = USB_DT_ENDPOINT_SIZE, | ||
340 | .bDescriptorType = USB_DT_ENDPOINT, | ||
341 | |||
342 | .bmAttributes = USB_ENDPOINT_XFER_INT, | ||
343 | .wMaxPacketSize = cpu_to_le16(1024), | ||
344 | .bInterval = USB_MS_TO_SS_INTERVAL(GZERO_INT_INTERVAL), | ||
345 | }; | ||
346 | |||
347 | struct usb_ss_ep_comp_descriptor ss_int_source_comp_desc = { | ||
348 | .bLength = USB_DT_SS_EP_COMP_SIZE, | ||
349 | .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, | ||
350 | |||
351 | .bMaxBurst = 0, | ||
352 | .bmAttributes = 0, | ||
353 | .wBytesPerInterval = cpu_to_le16(1024), | ||
354 | }; | ||
355 | |||
356 | static struct usb_endpoint_descriptor ss_int_sink_desc = { | ||
357 | .bLength = USB_DT_ENDPOINT_SIZE, | ||
358 | .bDescriptorType = USB_DT_ENDPOINT, | ||
359 | |||
360 | .bmAttributes = USB_ENDPOINT_XFER_INT, | ||
361 | .wMaxPacketSize = cpu_to_le16(1024), | ||
362 | .bInterval = USB_MS_TO_SS_INTERVAL(GZERO_INT_INTERVAL), | ||
363 | }; | ||
364 | |||
365 | struct usb_ss_ep_comp_descriptor ss_int_sink_comp_desc = { | ||
366 | .bLength = USB_DT_SS_EP_COMP_SIZE, | ||
367 | .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, | ||
368 | |||
369 | .bMaxBurst = 0, | ||
370 | .bmAttributes = 0, | ||
371 | .wBytesPerInterval = cpu_to_le16(1024), | ||
372 | }; | ||
373 | |||
267 | static struct usb_descriptor_header *ss_source_sink_descs[] = { | 374 | static struct usb_descriptor_header *ss_source_sink_descs[] = { |
268 | (struct usb_descriptor_header *) &source_sink_intf_alt0, | 375 | (struct usb_descriptor_header *) &source_sink_intf_alt0, |
269 | (struct usb_descriptor_header *) &ss_source_desc, | 376 | (struct usb_descriptor_header *) &ss_source_desc, |
@@ -280,6 +387,12 @@ static struct usb_descriptor_header *ss_source_sink_descs[] = { | |||
280 | (struct usb_descriptor_header *) &ss_iso_source_comp_desc, | 387 | (struct usb_descriptor_header *) &ss_iso_source_comp_desc, |
281 | (struct usb_descriptor_header *) &ss_iso_sink_desc, | 388 | (struct usb_descriptor_header *) &ss_iso_sink_desc, |
282 | (struct usb_descriptor_header *) &ss_iso_sink_comp_desc, | 389 | (struct usb_descriptor_header *) &ss_iso_sink_comp_desc, |
390 | (struct usb_descriptor_header *) &source_sink_intf_alt2, | ||
391 | #define SS_ALT_IFC_2_OFFSET 14 | ||
392 | (struct usb_descriptor_header *) &ss_int_source_desc, | ||
393 | (struct usb_descriptor_header *) &ss_int_source_comp_desc, | ||
394 | (struct usb_descriptor_header *) &ss_int_sink_desc, | ||
395 | (struct usb_descriptor_header *) &ss_int_sink_comp_desc, | ||
283 | NULL, | 396 | NULL, |
284 | }; | 397 | }; |
285 | 398 | ||
@@ -301,6 +414,21 @@ static struct usb_gadget_strings *sourcesink_strings[] = { | |||
301 | }; | 414 | }; |
302 | 415 | ||
303 | /*-------------------------------------------------------------------------*/ | 416 | /*-------------------------------------------------------------------------*/ |
417 | static const char *get_ep_string(enum eptype ep_type) | ||
418 | { | ||
419 | switch (ep_type) { | ||
420 | case EP_ISOC: | ||
421 | return "ISOC-"; | ||
422 | case EP_INTERRUPT: | ||
423 | return "INTERRUPT-"; | ||
424 | case EP_CONTROL: | ||
425 | return "CTRL-"; | ||
426 | case EP_BULK: | ||
427 | return "BULK-"; | ||
428 | default: | ||
429 | return "UNKNOWN-"; | ||
430 | } | ||
431 | } | ||
304 | 432 | ||
305 | static inline struct usb_request *ss_alloc_ep_req(struct usb_ep *ep, int len) | 433 | static inline struct usb_request *ss_alloc_ep_req(struct usb_ep *ep, int len) |
306 | { | 434 | { |
@@ -328,7 +456,8 @@ static void disable_ep(struct usb_composite_dev *cdev, struct usb_ep *ep) | |||
328 | 456 | ||
329 | void disable_endpoints(struct usb_composite_dev *cdev, | 457 | void disable_endpoints(struct usb_composite_dev *cdev, |
330 | struct usb_ep *in, struct usb_ep *out, | 458 | struct usb_ep *in, struct usb_ep *out, |
331 | struct usb_ep *iso_in, struct usb_ep *iso_out) | 459 | struct usb_ep *iso_in, struct usb_ep *iso_out, |
460 | struct usb_ep *int_in, struct usb_ep *int_out) | ||
332 | { | 461 | { |
333 | disable_ep(cdev, in); | 462 | disable_ep(cdev, in); |
334 | disable_ep(cdev, out); | 463 | disable_ep(cdev, out); |
@@ -336,6 +465,10 @@ void disable_endpoints(struct usb_composite_dev *cdev, | |||
336 | disable_ep(cdev, iso_in); | 465 | disable_ep(cdev, iso_in); |
337 | if (iso_out) | 466 | if (iso_out) |
338 | disable_ep(cdev, iso_out); | 467 | disable_ep(cdev, iso_out); |
468 | if (int_in) | ||
469 | disable_ep(cdev, int_in); | ||
470 | if (int_out) | ||
471 | disable_ep(cdev, int_out); | ||
339 | } | 472 | } |
340 | 473 | ||
341 | static int | 474 | static int |
@@ -352,6 +485,7 @@ sourcesink_bind(struct usb_configuration *c, struct usb_function *f) | |||
352 | return id; | 485 | return id; |
353 | source_sink_intf_alt0.bInterfaceNumber = id; | 486 | source_sink_intf_alt0.bInterfaceNumber = id; |
354 | source_sink_intf_alt1.bInterfaceNumber = id; | 487 | source_sink_intf_alt1.bInterfaceNumber = id; |
488 | source_sink_intf_alt2.bInterfaceNumber = id; | ||
355 | 489 | ||
356 | /* allocate bulk endpoints */ | 490 | /* allocate bulk endpoints */ |
357 | ss->in_ep = usb_ep_autoconfig(cdev->gadget, &fs_source_desc); | 491 | ss->in_ep = usb_ep_autoconfig(cdev->gadget, &fs_source_desc); |
@@ -412,14 +546,55 @@ no_iso: | |||
412 | if (isoc_maxpacket > 1024) | 546 | if (isoc_maxpacket > 1024) |
413 | isoc_maxpacket = 1024; | 547 | isoc_maxpacket = 1024; |
414 | 548 | ||
549 | /* sanity check the interrupt module parameters */ | ||
550 | if (int_interval < 1) | ||
551 | int_interval = 1; | ||
552 | if (int_interval > 4096) | ||
553 | int_interval = 4096; | ||
554 | if (int_mult > 2) | ||
555 | int_mult = 2; | ||
556 | if (int_maxburst > 15) | ||
557 | int_maxburst = 15; | ||
558 | |||
559 | /* fill in the FS interrupt descriptors from the module parameters */ | ||
560 | fs_int_source_desc.wMaxPacketSize = int_maxpacket > 64 ? | ||
561 | 64 : int_maxpacket; | ||
562 | fs_int_source_desc.bInterval = int_interval > 255 ? | ||
563 | 255 : int_interval; | ||
564 | fs_int_sink_desc.wMaxPacketSize = int_maxpacket > 64 ? | ||
565 | 64 : int_maxpacket; | ||
566 | fs_int_sink_desc.bInterval = int_interval > 255 ? | ||
567 | 255 : int_interval; | ||
568 | |||
569 | /* allocate int endpoints */ | ||
570 | ss->int_in_ep = usb_ep_autoconfig(cdev->gadget, &fs_int_source_desc); | ||
571 | if (!ss->int_in_ep) | ||
572 | goto no_int; | ||
573 | ss->int_in_ep->driver_data = cdev; /* claim */ | ||
574 | |||
575 | ss->int_out_ep = usb_ep_autoconfig(cdev->gadget, &fs_int_sink_desc); | ||
576 | if (ss->int_out_ep) { | ||
577 | ss->int_out_ep->driver_data = cdev; /* claim */ | ||
578 | } else { | ||
579 | ss->int_in_ep->driver_data = NULL; | ||
580 | ss->int_in_ep = NULL; | ||
581 | no_int: | ||
582 | fs_source_sink_descs[FS_ALT_IFC_2_OFFSET] = NULL; | ||
583 | hs_source_sink_descs[HS_ALT_IFC_2_OFFSET] = NULL; | ||
584 | ss_source_sink_descs[SS_ALT_IFC_2_OFFSET] = NULL; | ||
585 | } | ||
586 | |||
587 | if (int_maxpacket > 1024) | ||
588 | int_maxpacket = 1024; | ||
589 | |||
415 | /* support high speed hardware */ | 590 | /* support high speed hardware */ |
416 | hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress; | 591 | hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress; |
417 | hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress; | 592 | hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress; |
418 | 593 | ||
419 | /* | 594 | /* |
420 | * Fill in the HS isoc descriptors from the module parameters. | 595 | * Fill in the HS isoc and interrupt descriptors from the module |
421 | * We assume that the user knows what they are doing and won't | 596 | * parameters. We assume that the user knows what they are doing and |
422 | * give parameters that their UDC doesn't support. | 597 | * won't give parameters that their UDC doesn't support. |
423 | */ | 598 | */ |
424 | hs_iso_source_desc.wMaxPacketSize = isoc_maxpacket; | 599 | hs_iso_source_desc.wMaxPacketSize = isoc_maxpacket; |
425 | hs_iso_source_desc.wMaxPacketSize |= isoc_mult << 11; | 600 | hs_iso_source_desc.wMaxPacketSize |= isoc_mult << 11; |
@@ -432,6 +607,17 @@ no_iso: | |||
432 | hs_iso_sink_desc.bInterval = isoc_interval; | 607 | hs_iso_sink_desc.bInterval = isoc_interval; |
433 | hs_iso_sink_desc.bEndpointAddress = fs_iso_sink_desc.bEndpointAddress; | 608 | hs_iso_sink_desc.bEndpointAddress = fs_iso_sink_desc.bEndpointAddress; |
434 | 609 | ||
610 | hs_int_source_desc.wMaxPacketSize = int_maxpacket; | ||
611 | hs_int_source_desc.wMaxPacketSize |= int_mult << 11; | ||
612 | hs_int_source_desc.bInterval = USB_MS_TO_HS_INTERVAL(int_interval); | ||
613 | hs_int_source_desc.bEndpointAddress = | ||
614 | fs_int_source_desc.bEndpointAddress; | ||
615 | |||
616 | hs_int_sink_desc.wMaxPacketSize = int_maxpacket; | ||
617 | hs_int_sink_desc.wMaxPacketSize |= int_mult << 11; | ||
618 | hs_int_sink_desc.bInterval = USB_MS_TO_HS_INTERVAL(int_interval); | ||
619 | hs_int_sink_desc.bEndpointAddress = fs_int_sink_desc.bEndpointAddress; | ||
620 | |||
435 | /* support super speed hardware */ | 621 | /* support super speed hardware */ |
436 | ss_source_desc.bEndpointAddress = | 622 | ss_source_desc.bEndpointAddress = |
437 | fs_source_desc.bEndpointAddress; | 623 | fs_source_desc.bEndpointAddress; |
@@ -439,9 +625,9 @@ no_iso: | |||
439 | fs_sink_desc.bEndpointAddress; | 625 | fs_sink_desc.bEndpointAddress; |
440 | 626 | ||
441 | /* | 627 | /* |
442 | * Fill in the SS isoc descriptors from the module parameters. | 628 | * Fill in the SS isoc and interrupt descriptors from the module |
443 | * We assume that the user knows what they are doing and won't | 629 | * parameters. We assume that the user knows what they are doing and |
444 | * give parameters that their UDC doesn't support. | 630 | * won't give parameters that their UDC doesn't support. |
445 | */ | 631 | */ |
446 | ss_iso_source_desc.wMaxPacketSize = isoc_maxpacket; | 632 | ss_iso_source_desc.wMaxPacketSize = isoc_maxpacket; |
447 | ss_iso_source_desc.bInterval = isoc_interval; | 633 | ss_iso_source_desc.bInterval = isoc_interval; |
@@ -460,17 +646,37 @@ no_iso: | |||
460 | isoc_maxpacket * (isoc_mult + 1) * (isoc_maxburst + 1); | 646 | isoc_maxpacket * (isoc_mult + 1) * (isoc_maxburst + 1); |
461 | ss_iso_sink_desc.bEndpointAddress = fs_iso_sink_desc.bEndpointAddress; | 647 | ss_iso_sink_desc.bEndpointAddress = fs_iso_sink_desc.bEndpointAddress; |
462 | 648 | ||
649 | ss_int_source_desc.wMaxPacketSize = int_maxpacket; | ||
650 | ss_int_source_desc.bInterval = USB_MS_TO_SS_INTERVAL(int_interval); | ||
651 | ss_int_source_comp_desc.bmAttributes = int_mult; | ||
652 | ss_int_source_comp_desc.bMaxBurst = int_maxburst; | ||
653 | ss_int_source_comp_desc.wBytesPerInterval = | ||
654 | int_maxpacket * (int_mult + 1) * (int_maxburst + 1); | ||
655 | ss_int_source_desc.bEndpointAddress = | ||
656 | fs_int_source_desc.bEndpointAddress; | ||
657 | |||
658 | ss_int_sink_desc.wMaxPacketSize = int_maxpacket; | ||
659 | ss_int_sink_desc.bInterval = USB_MS_TO_SS_INTERVAL(int_interval); | ||
660 | ss_int_sink_comp_desc.bmAttributes = int_mult; | ||
661 | ss_int_sink_comp_desc.bMaxBurst = int_maxburst; | ||
662 | ss_int_sink_comp_desc.wBytesPerInterval = | ||
663 | int_maxpacket * (int_mult + 1) * (int_maxburst + 1); | ||
664 | ss_int_sink_desc.bEndpointAddress = fs_int_sink_desc.bEndpointAddress; | ||
665 | |||
463 | ret = usb_assign_descriptors(f, fs_source_sink_descs, | 666 | ret = usb_assign_descriptors(f, fs_source_sink_descs, |
464 | hs_source_sink_descs, ss_source_sink_descs); | 667 | hs_source_sink_descs, ss_source_sink_descs); |
465 | if (ret) | 668 | if (ret) |
466 | return ret; | 669 | return ret; |
467 | 670 | ||
468 | DBG(cdev, "%s speed %s: IN/%s, OUT/%s, ISO-IN/%s, ISO-OUT/%s\n", | 671 | DBG(cdev, "%s speed %s: IN/%s, OUT/%s, ISO-IN/%s, ISO-OUT/%s, " |
672 | "INT-IN/%s, INT-OUT/%s\n", | ||
469 | (gadget_is_superspeed(c->cdev->gadget) ? "super" : | 673 | (gadget_is_superspeed(c->cdev->gadget) ? "super" : |
470 | (gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full")), | 674 | (gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full")), |
471 | f->name, ss->in_ep->name, ss->out_ep->name, | 675 | f->name, ss->in_ep->name, ss->out_ep->name, |
472 | ss->iso_in_ep ? ss->iso_in_ep->name : "<none>", | 676 | ss->iso_in_ep ? ss->iso_in_ep->name : "<none>", |
473 | ss->iso_out_ep ? ss->iso_out_ep->name : "<none>"); | 677 | ss->iso_out_ep ? ss->iso_out_ep->name : "<none>", |
678 | ss->int_in_ep ? ss->int_in_ep->name : "<none>", | ||
679 | ss->int_out_ep ? ss->int_out_ep->name : "<none>"); | ||
474 | return 0; | 680 | return 0; |
475 | } | 681 | } |
476 | 682 | ||
@@ -601,14 +807,15 @@ static void source_sink_complete(struct usb_ep *ep, struct usb_request *req) | |||
601 | } | 807 | } |
602 | 808 | ||
603 | static int source_sink_start_ep(struct f_sourcesink *ss, bool is_in, | 809 | static int source_sink_start_ep(struct f_sourcesink *ss, bool is_in, |
604 | bool is_iso, int speed) | 810 | enum eptype ep_type, int speed) |
605 | { | 811 | { |
606 | struct usb_ep *ep; | 812 | struct usb_ep *ep; |
607 | struct usb_request *req; | 813 | struct usb_request *req; |
608 | int i, size, status; | 814 | int i, size, status; |
609 | 815 | ||
610 | for (i = 0; i < 8; i++) { | 816 | for (i = 0; i < 8; i++) { |
611 | if (is_iso) { | 817 | switch (ep_type) { |
818 | case EP_ISOC: | ||
612 | switch (speed) { | 819 | switch (speed) { |
613 | case USB_SPEED_SUPER: | 820 | case USB_SPEED_SUPER: |
614 | size = isoc_maxpacket * (isoc_mult + 1) * | 821 | size = isoc_maxpacket * (isoc_mult + 1) * |
@@ -624,9 +831,28 @@ static int source_sink_start_ep(struct f_sourcesink *ss, bool is_in, | |||
624 | } | 831 | } |
625 | ep = is_in ? ss->iso_in_ep : ss->iso_out_ep; | 832 | ep = is_in ? ss->iso_in_ep : ss->iso_out_ep; |
626 | req = ss_alloc_ep_req(ep, size); | 833 | req = ss_alloc_ep_req(ep, size); |
627 | } else { | 834 | break; |
835 | case EP_INTERRUPT: | ||
836 | switch (speed) { | ||
837 | case USB_SPEED_SUPER: | ||
838 | size = int_maxpacket * (int_mult + 1) * | ||
839 | (int_maxburst + 1); | ||
840 | break; | ||
841 | case USB_SPEED_HIGH: | ||
842 | size = int_maxpacket * (int_mult + 1); | ||
843 | break; | ||
844 | default: | ||
845 | size = int_maxpacket > 1023 ? | ||
846 | 1023 : int_maxpacket; | ||
847 | break; | ||
848 | } | ||
849 | ep = is_in ? ss->int_in_ep : ss->int_out_ep; | ||
850 | req = ss_alloc_ep_req(ep, size); | ||
851 | break; | ||
852 | default: | ||
628 | ep = is_in ? ss->in_ep : ss->out_ep; | 853 | ep = is_in ? ss->in_ep : ss->out_ep; |
629 | req = ss_alloc_ep_req(ep, 0); | 854 | req = ss_alloc_ep_req(ep, 0); |
855 | break; | ||
630 | } | 856 | } |
631 | 857 | ||
632 | if (!req) | 858 | if (!req) |
@@ -644,12 +870,12 @@ static int source_sink_start_ep(struct f_sourcesink *ss, bool is_in, | |||
644 | 870 | ||
645 | cdev = ss->function.config->cdev; | 871 | cdev = ss->function.config->cdev; |
646 | ERROR(cdev, "start %s%s %s --> %d\n", | 872 | ERROR(cdev, "start %s%s %s --> %d\n", |
647 | is_iso ? "ISO-" : "", is_in ? "IN" : "OUT", | 873 | get_ep_string(ep_type), is_in ? "IN" : "OUT", |
648 | ep->name, status); | 874 | ep->name, status); |
649 | free_ep_req(ep, req); | 875 | free_ep_req(ep, req); |
650 | } | 876 | } |
651 | 877 | ||
652 | if (!is_iso) | 878 | if (!(ep_type == EP_ISOC)) |
653 | break; | 879 | break; |
654 | } | 880 | } |
655 | 881 | ||
@@ -662,7 +888,7 @@ static void disable_source_sink(struct f_sourcesink *ss) | |||
662 | 888 | ||
663 | cdev = ss->function.config->cdev; | 889 | cdev = ss->function.config->cdev; |
664 | disable_endpoints(cdev, ss->in_ep, ss->out_ep, ss->iso_in_ep, | 890 | disable_endpoints(cdev, ss->in_ep, ss->out_ep, ss->iso_in_ep, |
665 | ss->iso_out_ep); | 891 | ss->iso_out_ep, ss->int_in_ep, ss->int_out_ep); |
666 | VDBG(cdev, "%s disabled\n", ss->function.name); | 892 | VDBG(cdev, "%s disabled\n", ss->function.name); |
667 | } | 893 | } |
668 | 894 | ||
@@ -674,6 +900,62 @@ enable_source_sink(struct usb_composite_dev *cdev, struct f_sourcesink *ss, | |||
674 | int speed = cdev->gadget->speed; | 900 | int speed = cdev->gadget->speed; |
675 | struct usb_ep *ep; | 901 | struct usb_ep *ep; |
676 | 902 | ||
903 | if (alt == 2) { | ||
904 | /* Configure for periodic interrupt endpoint */ | ||
905 | ep = ss->int_in_ep; | ||
906 | if (ep) { | ||
907 | result = config_ep_by_speed(cdev->gadget, | ||
908 | &(ss->function), ep); | ||
909 | if (result) | ||
910 | return result; | ||
911 | |||
912 | result = usb_ep_enable(ep); | ||
913 | if (result < 0) | ||
914 | return result; | ||
915 | |||
916 | ep->driver_data = ss; | ||
917 | result = source_sink_start_ep(ss, true, EP_INTERRUPT, | ||
918 | speed); | ||
919 | if (result < 0) { | ||
920 | fail1: | ||
921 | ep = ss->int_in_ep; | ||
922 | if (ep) { | ||
923 | usb_ep_disable(ep); | ||
924 | ep->driver_data = NULL; | ||
925 | } | ||
926 | return result; | ||
927 | } | ||
928 | } | ||
929 | |||
930 | /* | ||
931 | * one interrupt endpoint reads (sinks) anything OUT (from the | ||
932 | * host) | ||
933 | */ | ||
934 | ep = ss->int_out_ep; | ||
935 | if (ep) { | ||
936 | result = config_ep_by_speed(cdev->gadget, | ||
937 | &(ss->function), ep); | ||
938 | if (result) | ||
939 | goto fail1; | ||
940 | |||
941 | result = usb_ep_enable(ep); | ||
942 | if (result < 0) | ||
943 | goto fail1; | ||
944 | |||
945 | ep->driver_data = ss; | ||
946 | result = source_sink_start_ep(ss, false, EP_INTERRUPT, | ||
947 | speed); | ||
948 | if (result < 0) { | ||
949 | ep = ss->int_out_ep; | ||
950 | usb_ep_disable(ep); | ||
951 | ep->driver_data = NULL; | ||
952 | goto fail1; | ||
953 | } | ||
954 | } | ||
955 | |||
956 | goto out; | ||
957 | } | ||
958 | |||
677 | /* one bulk endpoint writes (sources) zeroes IN (to the host) */ | 959 | /* one bulk endpoint writes (sources) zeroes IN (to the host) */ |
678 | ep = ss->in_ep; | 960 | ep = ss->in_ep; |
679 | result = config_ep_by_speed(cdev->gadget, &(ss->function), ep); | 961 | result = config_ep_by_speed(cdev->gadget, &(ss->function), ep); |
@@ -684,7 +966,7 @@ enable_source_sink(struct usb_composite_dev *cdev, struct f_sourcesink *ss, | |||
684 | return result; | 966 | return result; |
685 | ep->driver_data = ss; | 967 | ep->driver_data = ss; |
686 | 968 | ||
687 | result = source_sink_start_ep(ss, true, false, speed); | 969 | result = source_sink_start_ep(ss, true, EP_BULK, speed); |
688 | if (result < 0) { | 970 | if (result < 0) { |
689 | fail: | 971 | fail: |
690 | ep = ss->in_ep; | 972 | ep = ss->in_ep; |
@@ -703,7 +985,7 @@ fail: | |||
703 | goto fail; | 985 | goto fail; |
704 | ep->driver_data = ss; | 986 | ep->driver_data = ss; |
705 | 987 | ||
706 | result = source_sink_start_ep(ss, false, false, speed); | 988 | result = source_sink_start_ep(ss, false, EP_BULK, speed); |
707 | if (result < 0) { | 989 | if (result < 0) { |
708 | fail2: | 990 | fail2: |
709 | ep = ss->out_ep; | 991 | ep = ss->out_ep; |
@@ -726,7 +1008,7 @@ fail2: | |||
726 | goto fail2; | 1008 | goto fail2; |
727 | ep->driver_data = ss; | 1009 | ep->driver_data = ss; |
728 | 1010 | ||
729 | result = source_sink_start_ep(ss, true, true, speed); | 1011 | result = source_sink_start_ep(ss, true, EP_ISOC, speed); |
730 | if (result < 0) { | 1012 | if (result < 0) { |
731 | fail3: | 1013 | fail3: |
732 | ep = ss->iso_in_ep; | 1014 | ep = ss->iso_in_ep; |
@@ -749,13 +1031,14 @@ fail3: | |||
749 | goto fail3; | 1031 | goto fail3; |
750 | ep->driver_data = ss; | 1032 | ep->driver_data = ss; |
751 | 1033 | ||
752 | result = source_sink_start_ep(ss, false, true, speed); | 1034 | result = source_sink_start_ep(ss, false, EP_ISOC, speed); |
753 | if (result < 0) { | 1035 | if (result < 0) { |
754 | usb_ep_disable(ep); | 1036 | usb_ep_disable(ep); |
755 | ep->driver_data = NULL; | 1037 | ep->driver_data = NULL; |
756 | goto fail3; | 1038 | goto fail3; |
757 | } | 1039 | } |
758 | } | 1040 | } |
1041 | |||
759 | out: | 1042 | out: |
760 | ss->cur_alt = alt; | 1043 | ss->cur_alt = alt; |
761 | 1044 | ||
@@ -771,6 +1054,8 @@ static int sourcesink_set_alt(struct usb_function *f, | |||
771 | 1054 | ||
772 | if (ss->in_ep->driver_data) | 1055 | if (ss->in_ep->driver_data) |
773 | disable_source_sink(ss); | 1056 | disable_source_sink(ss); |
1057 | else if (alt == 2 && ss->int_in_ep->driver_data) | ||
1058 | disable_source_sink(ss); | ||
774 | return enable_source_sink(cdev, ss, alt); | 1059 | return enable_source_sink(cdev, ss, alt); |
775 | } | 1060 | } |
776 | 1061 | ||
@@ -883,6 +1168,10 @@ static struct usb_function *source_sink_alloc_func( | |||
883 | isoc_maxpacket = ss_opts->isoc_maxpacket; | 1168 | isoc_maxpacket = ss_opts->isoc_maxpacket; |
884 | isoc_mult = ss_opts->isoc_mult; | 1169 | isoc_mult = ss_opts->isoc_mult; |
885 | isoc_maxburst = ss_opts->isoc_maxburst; | 1170 | isoc_maxburst = ss_opts->isoc_maxburst; |
1171 | int_interval = ss_opts->int_interval; | ||
1172 | int_maxpacket = ss_opts->int_maxpacket; | ||
1173 | int_mult = ss_opts->int_mult; | ||
1174 | int_maxburst = ss_opts->int_maxburst; | ||
886 | buflen = ss_opts->bulk_buflen; | 1175 | buflen = ss_opts->bulk_buflen; |
887 | 1176 | ||
888 | ss->function.name = "source/sink"; | 1177 | ss->function.name = "source/sink"; |
@@ -1179,6 +1468,182 @@ static struct f_ss_opts_attribute f_ss_opts_bulk_buflen = | |||
1179 | f_ss_opts_bulk_buflen_show, | 1468 | f_ss_opts_bulk_buflen_show, |
1180 | f_ss_opts_bulk_buflen_store); | 1469 | f_ss_opts_bulk_buflen_store); |
1181 | 1470 | ||
1471 | static ssize_t f_ss_opts_int_interval_show(struct f_ss_opts *opts, char *page) | ||
1472 | { | ||
1473 | int result; | ||
1474 | |||
1475 | mutex_lock(&opts->lock); | ||
1476 | result = sprintf(page, "%d", opts->int_interval); | ||
1477 | mutex_unlock(&opts->lock); | ||
1478 | |||
1479 | return result; | ||
1480 | } | ||
1481 | |||
1482 | static ssize_t f_ss_opts_int_interval_store(struct f_ss_opts *opts, | ||
1483 | const char *page, size_t len) | ||
1484 | { | ||
1485 | int ret; | ||
1486 | u32 num; | ||
1487 | |||
1488 | mutex_lock(&opts->lock); | ||
1489 | if (opts->refcnt) { | ||
1490 | ret = -EBUSY; | ||
1491 | goto end; | ||
1492 | } | ||
1493 | |||
1494 | ret = kstrtou32(page, 0, &num); | ||
1495 | if (ret) | ||
1496 | goto end; | ||
1497 | |||
1498 | if (num > 4096) { | ||
1499 | ret = -EINVAL; | ||
1500 | goto end; | ||
1501 | } | ||
1502 | |||
1503 | opts->int_interval = num; | ||
1504 | ret = len; | ||
1505 | end: | ||
1506 | mutex_unlock(&opts->lock); | ||
1507 | return ret; | ||
1508 | } | ||
1509 | |||
1510 | static struct f_ss_opts_attribute f_ss_opts_int_interval = | ||
1511 | __CONFIGFS_ATTR(int_interval, S_IRUGO | S_IWUSR, | ||
1512 | f_ss_opts_int_interval_show, | ||
1513 | f_ss_opts_int_interval_store); | ||
1514 | |||
1515 | static ssize_t f_ss_opts_int_maxpacket_show(struct f_ss_opts *opts, char *page) | ||
1516 | { | ||
1517 | int result; | ||
1518 | |||
1519 | mutex_lock(&opts->lock); | ||
1520 | result = sprintf(page, "%d", opts->int_maxpacket); | ||
1521 | mutex_unlock(&opts->lock); | ||
1522 | |||
1523 | return result; | ||
1524 | } | ||
1525 | |||
1526 | static ssize_t f_ss_opts_int_maxpacket_store(struct f_ss_opts *opts, | ||
1527 | const char *page, size_t len) | ||
1528 | { | ||
1529 | int ret; | ||
1530 | u16 num; | ||
1531 | |||
1532 | mutex_lock(&opts->lock); | ||
1533 | if (opts->refcnt) { | ||
1534 | ret = -EBUSY; | ||
1535 | goto end; | ||
1536 | } | ||
1537 | |||
1538 | ret = kstrtou16(page, 0, &num); | ||
1539 | if (ret) | ||
1540 | goto end; | ||
1541 | |||
1542 | if (num > 1024) { | ||
1543 | ret = -EINVAL; | ||
1544 | goto end; | ||
1545 | } | ||
1546 | |||
1547 | opts->int_maxpacket = num; | ||
1548 | ret = len; | ||
1549 | end: | ||
1550 | mutex_unlock(&opts->lock); | ||
1551 | return ret; | ||
1552 | } | ||
1553 | |||
1554 | static struct f_ss_opts_attribute f_ss_opts_int_maxpacket = | ||
1555 | __CONFIGFS_ATTR(int_maxpacket, S_IRUGO | S_IWUSR, | ||
1556 | f_ss_opts_int_maxpacket_show, | ||
1557 | f_ss_opts_int_maxpacket_store); | ||
1558 | |||
1559 | static ssize_t f_ss_opts_int_mult_show(struct f_ss_opts *opts, char *page) | ||
1560 | { | ||
1561 | int result; | ||
1562 | |||
1563 | mutex_lock(&opts->lock); | ||
1564 | result = sprintf(page, "%d", opts->int_mult); | ||
1565 | mutex_unlock(&opts->lock); | ||
1566 | |||
1567 | return result; | ||
1568 | } | ||
1569 | |||
1570 | static ssize_t f_ss_opts_int_mult_store(struct f_ss_opts *opts, | ||
1571 | const char *page, size_t len) | ||
1572 | { | ||
1573 | int ret; | ||
1574 | u8 num; | ||
1575 | |||
1576 | mutex_lock(&opts->lock); | ||
1577 | if (opts->refcnt) { | ||
1578 | ret = -EBUSY; | ||
1579 | goto end; | ||
1580 | } | ||
1581 | |||
1582 | ret = kstrtou8(page, 0, &num); | ||
1583 | if (ret) | ||
1584 | goto end; | ||
1585 | |||
1586 | if (num > 2) { | ||
1587 | ret = -EINVAL; | ||
1588 | goto end; | ||
1589 | } | ||
1590 | |||
1591 | opts->int_mult = num; | ||
1592 | ret = len; | ||
1593 | end: | ||
1594 | mutex_unlock(&opts->lock); | ||
1595 | return ret; | ||
1596 | } | ||
1597 | |||
1598 | static struct f_ss_opts_attribute f_ss_opts_int_mult = | ||
1599 | __CONFIGFS_ATTR(int_mult, S_IRUGO | S_IWUSR, | ||
1600 | f_ss_opts_int_mult_show, | ||
1601 | f_ss_opts_int_mult_store); | ||
1602 | |||
1603 | static ssize_t f_ss_opts_int_maxburst_show(struct f_ss_opts *opts, char *page) | ||
1604 | { | ||
1605 | int result; | ||
1606 | |||
1607 | mutex_lock(&opts->lock); | ||
1608 | result = sprintf(page, "%d", opts->int_maxburst); | ||
1609 | mutex_unlock(&opts->lock); | ||
1610 | |||
1611 | return result; | ||
1612 | } | ||
1613 | |||
1614 | static ssize_t f_ss_opts_int_maxburst_store(struct f_ss_opts *opts, | ||
1615 | const char *page, size_t len) | ||
1616 | { | ||
1617 | int ret; | ||
1618 | u8 num; | ||
1619 | |||
1620 | mutex_lock(&opts->lock); | ||
1621 | if (opts->refcnt) { | ||
1622 | ret = -EBUSY; | ||
1623 | goto end; | ||
1624 | } | ||
1625 | |||
1626 | ret = kstrtou8(page, 0, &num); | ||
1627 | if (ret) | ||
1628 | goto end; | ||
1629 | |||
1630 | if (num > 15) { | ||
1631 | ret = -EINVAL; | ||
1632 | goto end; | ||
1633 | } | ||
1634 | |||
1635 | opts->int_maxburst = num; | ||
1636 | ret = len; | ||
1637 | end: | ||
1638 | mutex_unlock(&opts->lock); | ||
1639 | return ret; | ||
1640 | } | ||
1641 | |||
1642 | static struct f_ss_opts_attribute f_ss_opts_int_maxburst = | ||
1643 | __CONFIGFS_ATTR(int_maxburst, S_IRUGO | S_IWUSR, | ||
1644 | f_ss_opts_int_maxburst_show, | ||
1645 | f_ss_opts_int_maxburst_store); | ||
1646 | |||
1182 | static struct configfs_attribute *ss_attrs[] = { | 1647 | static struct configfs_attribute *ss_attrs[] = { |
1183 | &f_ss_opts_pattern.attr, | 1648 | &f_ss_opts_pattern.attr, |
1184 | &f_ss_opts_isoc_interval.attr, | 1649 | &f_ss_opts_isoc_interval.attr, |
@@ -1186,6 +1651,10 @@ static struct configfs_attribute *ss_attrs[] = { | |||
1186 | &f_ss_opts_isoc_mult.attr, | 1651 | &f_ss_opts_isoc_mult.attr, |
1187 | &f_ss_opts_isoc_maxburst.attr, | 1652 | &f_ss_opts_isoc_maxburst.attr, |
1188 | &f_ss_opts_bulk_buflen.attr, | 1653 | &f_ss_opts_bulk_buflen.attr, |
1654 | &f_ss_opts_int_interval.attr, | ||
1655 | &f_ss_opts_int_maxpacket.attr, | ||
1656 | &f_ss_opts_int_mult.attr, | ||
1657 | &f_ss_opts_int_maxburst.attr, | ||
1189 | NULL, | 1658 | NULL, |
1190 | }; | 1659 | }; |
1191 | 1660 | ||
@@ -1215,6 +1684,8 @@ static struct usb_function_instance *source_sink_alloc_inst(void) | |||
1215 | ss_opts->isoc_interval = GZERO_ISOC_INTERVAL; | 1684 | ss_opts->isoc_interval = GZERO_ISOC_INTERVAL; |
1216 | ss_opts->isoc_maxpacket = GZERO_ISOC_MAXPACKET; | 1685 | ss_opts->isoc_maxpacket = GZERO_ISOC_MAXPACKET; |
1217 | ss_opts->bulk_buflen = GZERO_BULK_BUFLEN; | 1686 | ss_opts->bulk_buflen = GZERO_BULK_BUFLEN; |
1687 | ss_opts->int_interval = GZERO_INT_INTERVAL; | ||
1688 | ss_opts->int_maxpacket = GZERO_INT_MAXPACKET; | ||
1218 | 1689 | ||
1219 | config_group_init_type_name(&ss_opts->func_inst.group, "", | 1690 | config_group_init_type_name(&ss_opts->func_inst.group, "", |
1220 | &ss_func_type); | 1691 | &ss_func_type); |
diff --git a/drivers/usb/gadget/function/f_uac1.c b/drivers/usb/gadget/function/f_uac1.c index 2b4c82d84bfc..f7b203293205 100644 --- a/drivers/usb/gadget/function/f_uac1.c +++ b/drivers/usb/gadget/function/f_uac1.c | |||
@@ -11,24 +11,12 @@ | |||
11 | 11 | ||
12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/module.h> | ||
14 | #include <linux/device.h> | 15 | #include <linux/device.h> |
15 | #include <linux/atomic.h> | 16 | #include <linux/atomic.h> |
16 | 17 | ||
17 | #include "u_uac1.h" | 18 | #include "u_uac1.h" |
18 | 19 | ||
19 | #define OUT_EP_MAX_PACKET_SIZE 200 | ||
20 | static int req_buf_size = OUT_EP_MAX_PACKET_SIZE; | ||
21 | module_param(req_buf_size, int, S_IRUGO); | ||
22 | MODULE_PARM_DESC(req_buf_size, "ISO OUT endpoint request buffer size"); | ||
23 | |||
24 | static int req_count = 256; | ||
25 | module_param(req_count, int, S_IRUGO); | ||
26 | MODULE_PARM_DESC(req_count, "ISO OUT endpoint request count"); | ||
27 | |||
28 | static int audio_buf_size = 48000; | ||
29 | module_param(audio_buf_size, int, S_IRUGO); | ||
30 | MODULE_PARM_DESC(audio_buf_size, "Audio buffer size"); | ||
31 | |||
32 | static int generic_set_cmd(struct usb_audio_control *con, u8 cmd, int value); | 20 | static int generic_set_cmd(struct usb_audio_control *con, u8 cmd, int value); |
33 | static int generic_get_cmd(struct usb_audio_control *con, u8 cmd); | 21 | static int generic_get_cmd(struct usb_audio_control *con, u8 cmd); |
34 | 22 | ||
@@ -46,7 +34,7 @@ static int generic_get_cmd(struct usb_audio_control *con, u8 cmd); | |||
46 | #define F_AUDIO_NUM_INTERFACES 2 | 34 | #define F_AUDIO_NUM_INTERFACES 2 |
47 | 35 | ||
48 | /* B.3.1 Standard AC Interface Descriptor */ | 36 | /* B.3.1 Standard AC Interface Descriptor */ |
49 | static struct usb_interface_descriptor ac_interface_desc __initdata = { | 37 | static struct usb_interface_descriptor ac_interface_desc = { |
50 | .bLength = USB_DT_INTERFACE_SIZE, | 38 | .bLength = USB_DT_INTERFACE_SIZE, |
51 | .bDescriptorType = USB_DT_INTERFACE, | 39 | .bDescriptorType = USB_DT_INTERFACE, |
52 | .bNumEndpoints = 0, | 40 | .bNumEndpoints = 0, |
@@ -183,12 +171,12 @@ static struct usb_endpoint_descriptor as_out_ep_desc = { | |||
183 | .bEndpointAddress = USB_DIR_OUT, | 171 | .bEndpointAddress = USB_DIR_OUT, |
184 | .bmAttributes = USB_ENDPOINT_SYNC_ADAPTIVE | 172 | .bmAttributes = USB_ENDPOINT_SYNC_ADAPTIVE |
185 | | USB_ENDPOINT_XFER_ISOC, | 173 | | USB_ENDPOINT_XFER_ISOC, |
186 | .wMaxPacketSize = __constant_cpu_to_le16(OUT_EP_MAX_PACKET_SIZE), | 174 | .wMaxPacketSize = cpu_to_le16(UAC1_OUT_EP_MAX_PACKET_SIZE), |
187 | .bInterval = 4, | 175 | .bInterval = 4, |
188 | }; | 176 | }; |
189 | 177 | ||
190 | /* Class-specific AS ISO OUT Endpoint Descriptor */ | 178 | /* Class-specific AS ISO OUT Endpoint Descriptor */ |
191 | static struct uac_iso_endpoint_descriptor as_iso_out_desc __initdata = { | 179 | static struct uac_iso_endpoint_descriptor as_iso_out_desc = { |
192 | .bLength = UAC_ISO_ENDPOINT_DESC_SIZE, | 180 | .bLength = UAC_ISO_ENDPOINT_DESC_SIZE, |
193 | .bDescriptorType = USB_DT_CS_ENDPOINT, | 181 | .bDescriptorType = USB_DT_CS_ENDPOINT, |
194 | .bDescriptorSubtype = UAC_EP_GENERAL, | 182 | .bDescriptorSubtype = UAC_EP_GENERAL, |
@@ -197,7 +185,7 @@ static struct uac_iso_endpoint_descriptor as_iso_out_desc __initdata = { | |||
197 | .wLockDelay = __constant_cpu_to_le16(1), | 185 | .wLockDelay = __constant_cpu_to_le16(1), |
198 | }; | 186 | }; |
199 | 187 | ||
200 | static struct usb_descriptor_header *f_audio_desc[] __initdata = { | 188 | static struct usb_descriptor_header *f_audio_desc[] = { |
201 | (struct usb_descriptor_header *)&ac_interface_desc, | 189 | (struct usb_descriptor_header *)&ac_interface_desc, |
202 | (struct usb_descriptor_header *)&ac_header_desc, | 190 | (struct usb_descriptor_header *)&ac_header_desc, |
203 | 191 | ||
@@ -216,6 +204,37 @@ static struct usb_descriptor_header *f_audio_desc[] __initdata = { | |||
216 | NULL, | 204 | NULL, |
217 | }; | 205 | }; |
218 | 206 | ||
207 | enum { | ||
208 | STR_AC_IF, | ||
209 | STR_INPUT_TERMINAL, | ||
210 | STR_INPUT_TERMINAL_CH_NAMES, | ||
211 | STR_FEAT_DESC_0, | ||
212 | STR_OUTPUT_TERMINAL, | ||
213 | STR_AS_IF_ALT0, | ||
214 | STR_AS_IF_ALT1, | ||
215 | }; | ||
216 | |||
217 | static struct usb_string strings_uac1[] = { | ||
218 | [STR_AC_IF].s = "AC Interface", | ||
219 | [STR_INPUT_TERMINAL].s = "Input terminal", | ||
220 | [STR_INPUT_TERMINAL_CH_NAMES].s = "Channels", | ||
221 | [STR_FEAT_DESC_0].s = "Volume control & mute", | ||
222 | [STR_OUTPUT_TERMINAL].s = "Output terminal", | ||
223 | [STR_AS_IF_ALT0].s = "AS Interface", | ||
224 | [STR_AS_IF_ALT1].s = "AS Interface", | ||
225 | { }, | ||
226 | }; | ||
227 | |||
228 | static struct usb_gadget_strings str_uac1 = { | ||
229 | .language = 0x0409, /* en-us */ | ||
230 | .strings = strings_uac1, | ||
231 | }; | ||
232 | |||
233 | static struct usb_gadget_strings *uac1_strings[] = { | ||
234 | &str_uac1, | ||
235 | NULL, | ||
236 | }; | ||
237 | |||
219 | /* | 238 | /* |
220 | * This function is an ALSA sound card following USB Audio Class Spec 1.0. | 239 | * This function is an ALSA sound card following USB Audio Class Spec 1.0. |
221 | */ | 240 | */ |
@@ -300,8 +319,14 @@ static int f_audio_out_ep_complete(struct usb_ep *ep, struct usb_request *req) | |||
300 | struct f_audio *audio = req->context; | 319 | struct f_audio *audio = req->context; |
301 | struct usb_composite_dev *cdev = audio->card.func.config->cdev; | 320 | struct usb_composite_dev *cdev = audio->card.func.config->cdev; |
302 | struct f_audio_buf *copy_buf = audio->copy_buf; | 321 | struct f_audio_buf *copy_buf = audio->copy_buf; |
322 | struct f_uac1_opts *opts; | ||
323 | int audio_buf_size; | ||
303 | int err; | 324 | int err; |
304 | 325 | ||
326 | opts = container_of(audio->card.func.fi, struct f_uac1_opts, | ||
327 | func_inst); | ||
328 | audio_buf_size = opts->audio_buf_size; | ||
329 | |||
305 | if (!copy_buf) | 330 | if (!copy_buf) |
306 | return -EINVAL; | 331 | return -EINVAL; |
307 | 332 | ||
@@ -546,10 +571,17 @@ static int f_audio_set_alt(struct usb_function *f, unsigned intf, unsigned alt) | |||
546 | struct usb_composite_dev *cdev = f->config->cdev; | 571 | struct usb_composite_dev *cdev = f->config->cdev; |
547 | struct usb_ep *out_ep = audio->out_ep; | 572 | struct usb_ep *out_ep = audio->out_ep; |
548 | struct usb_request *req; | 573 | struct usb_request *req; |
574 | struct f_uac1_opts *opts; | ||
575 | int req_buf_size, req_count, audio_buf_size; | ||
549 | int i = 0, err = 0; | 576 | int i = 0, err = 0; |
550 | 577 | ||
551 | DBG(cdev, "intf %d, alt %d\n", intf, alt); | 578 | DBG(cdev, "intf %d, alt %d\n", intf, alt); |
552 | 579 | ||
580 | opts = container_of(f->fi, struct f_uac1_opts, func_inst); | ||
581 | req_buf_size = opts->req_buf_size; | ||
582 | req_count = opts->req_count; | ||
583 | audio_buf_size = opts->audio_buf_size; | ||
584 | |||
553 | if (intf == 1) { | 585 | if (intf == 1) { |
554 | if (alt == 1) { | 586 | if (alt == 1) { |
555 | usb_ep_enable(out_ep); | 587 | usb_ep_enable(out_ep); |
@@ -625,13 +657,37 @@ static void f_audio_build_desc(struct f_audio *audio) | |||
625 | } | 657 | } |
626 | 658 | ||
627 | /* audio function driver setup/binding */ | 659 | /* audio function driver setup/binding */ |
628 | static int __init | 660 | static int |
629 | f_audio_bind(struct usb_configuration *c, struct usb_function *f) | 661 | f_audio_bind(struct usb_configuration *c, struct usb_function *f) |
630 | { | 662 | { |
631 | struct usb_composite_dev *cdev = c->cdev; | 663 | struct usb_composite_dev *cdev = c->cdev; |
632 | struct f_audio *audio = func_to_audio(f); | 664 | struct f_audio *audio = func_to_audio(f); |
665 | struct usb_string *us; | ||
633 | int status; | 666 | int status; |
634 | struct usb_ep *ep = NULL; | 667 | struct usb_ep *ep = NULL; |
668 | struct f_uac1_opts *audio_opts; | ||
669 | |||
670 | audio_opts = container_of(f->fi, struct f_uac1_opts, func_inst); | ||
671 | audio->card.gadget = c->cdev->gadget; | ||
672 | audio_opts->card = &audio->card; | ||
673 | /* set up ASLA audio devices */ | ||
674 | if (!audio_opts->bound) { | ||
675 | status = gaudio_setup(&audio->card); | ||
676 | if (status < 0) | ||
677 | return status; | ||
678 | audio_opts->bound = true; | ||
679 | } | ||
680 | us = usb_gstrings_attach(cdev, uac1_strings, ARRAY_SIZE(strings_uac1)); | ||
681 | if (IS_ERR(us)) | ||
682 | return PTR_ERR(us); | ||
683 | ac_interface_desc.iInterface = us[STR_AC_IF].id; | ||
684 | input_terminal_desc.iTerminal = us[STR_INPUT_TERMINAL].id; | ||
685 | input_terminal_desc.iChannelNames = us[STR_INPUT_TERMINAL_CH_NAMES].id; | ||
686 | feature_unit_desc.iFeature = us[STR_FEAT_DESC_0].id; | ||
687 | output_terminal_desc.iTerminal = us[STR_OUTPUT_TERMINAL].id; | ||
688 | as_interface_alt_0_desc.iInterface = us[STR_AS_IF_ALT0].id; | ||
689 | as_interface_alt_1_desc.iInterface = us[STR_AS_IF_ALT1].id; | ||
690 | |||
635 | 691 | ||
636 | f_audio_build_desc(audio); | 692 | f_audio_build_desc(audio); |
637 | 693 | ||
@@ -666,20 +722,12 @@ f_audio_bind(struct usb_configuration *c, struct usb_function *f) | |||
666 | return 0; | 722 | return 0; |
667 | 723 | ||
668 | fail: | 724 | fail: |
725 | gaudio_cleanup(&audio->card); | ||
669 | if (ep) | 726 | if (ep) |
670 | ep->driver_data = NULL; | 727 | ep->driver_data = NULL; |
671 | return status; | 728 | return status; |
672 | } | 729 | } |
673 | 730 | ||
674 | static void | ||
675 | f_audio_unbind(struct usb_configuration *c, struct usb_function *f) | ||
676 | { | ||
677 | struct f_audio *audio = func_to_audio(f); | ||
678 | |||
679 | usb_free_all_descriptors(f); | ||
680 | kfree(audio); | ||
681 | } | ||
682 | |||
683 | /*-------------------------------------------------------------------------*/ | 731 | /*-------------------------------------------------------------------------*/ |
684 | 732 | ||
685 | static int generic_set_cmd(struct usb_audio_control *con, u8 cmd, int value) | 733 | static int generic_set_cmd(struct usb_audio_control *con, u8 cmd, int value) |
@@ -695,7 +743,7 @@ static int generic_get_cmd(struct usb_audio_control *con, u8 cmd) | |||
695 | } | 743 | } |
696 | 744 | ||
697 | /* Todo: add more control selecotor dynamically */ | 745 | /* Todo: add more control selecotor dynamically */ |
698 | static int __init control_selector_init(struct f_audio *audio) | 746 | static int control_selector_init(struct f_audio *audio) |
699 | { | 747 | { |
700 | INIT_LIST_HEAD(&audio->cs); | 748 | INIT_LIST_HEAD(&audio->cs); |
701 | list_add(&feature_unit.list, &audio->cs); | 749 | list_add(&feature_unit.list, &audio->cs); |
@@ -712,57 +760,226 @@ static int __init control_selector_init(struct f_audio *audio) | |||
712 | return 0; | 760 | return 0; |
713 | } | 761 | } |
714 | 762 | ||
715 | /** | 763 | static inline struct f_uac1_opts *to_f_uac1_opts(struct config_item *item) |
716 | * audio_bind_config - add USB audio function to a configuration | 764 | { |
717 | * @c: the configuration to supcard the USB audio function | 765 | return container_of(to_config_group(item), struct f_uac1_opts, |
718 | * Context: single threaded during gadget setup | 766 | func_inst.group); |
719 | * | 767 | } |
720 | * Returns zero on success, else negative errno. | 768 | |
721 | */ | 769 | CONFIGFS_ATTR_STRUCT(f_uac1_opts); |
722 | static int __init audio_bind_config(struct usb_configuration *c) | 770 | CONFIGFS_ATTR_OPS(f_uac1_opts); |
771 | |||
772 | static void f_uac1_attr_release(struct config_item *item) | ||
773 | { | ||
774 | struct f_uac1_opts *opts = to_f_uac1_opts(item); | ||
775 | |||
776 | usb_put_function_instance(&opts->func_inst); | ||
777 | } | ||
778 | |||
779 | static struct configfs_item_operations f_uac1_item_ops = { | ||
780 | .release = f_uac1_attr_release, | ||
781 | .show_attribute = f_uac1_opts_attr_show, | ||
782 | .store_attribute = f_uac1_opts_attr_store, | ||
783 | }; | ||
784 | |||
785 | #define UAC1_INT_ATTRIBUTE(name) \ | ||
786 | static ssize_t f_uac1_opts_##name##_show(struct f_uac1_opts *opts, \ | ||
787 | char *page) \ | ||
788 | { \ | ||
789 | int result; \ | ||
790 | \ | ||
791 | mutex_lock(&opts->lock); \ | ||
792 | result = sprintf(page, "%u\n", opts->name); \ | ||
793 | mutex_unlock(&opts->lock); \ | ||
794 | \ | ||
795 | return result; \ | ||
796 | } \ | ||
797 | \ | ||
798 | static ssize_t f_uac1_opts_##name##_store(struct f_uac1_opts *opts, \ | ||
799 | const char *page, size_t len) \ | ||
800 | { \ | ||
801 | int ret; \ | ||
802 | u32 num; \ | ||
803 | \ | ||
804 | mutex_lock(&opts->lock); \ | ||
805 | if (opts->refcnt) { \ | ||
806 | ret = -EBUSY; \ | ||
807 | goto end; \ | ||
808 | } \ | ||
809 | \ | ||
810 | ret = kstrtou32(page, 0, &num); \ | ||
811 | if (ret) \ | ||
812 | goto end; \ | ||
813 | \ | ||
814 | opts->name = num; \ | ||
815 | ret = len; \ | ||
816 | \ | ||
817 | end: \ | ||
818 | mutex_unlock(&opts->lock); \ | ||
819 | return ret; \ | ||
820 | } \ | ||
821 | \ | ||
822 | static struct f_uac1_opts_attribute f_uac1_opts_##name = \ | ||
823 | __CONFIGFS_ATTR(name, S_IRUGO | S_IWUSR, \ | ||
824 | f_uac1_opts_##name##_show, \ | ||
825 | f_uac1_opts_##name##_store) | ||
826 | |||
827 | UAC1_INT_ATTRIBUTE(req_buf_size); | ||
828 | UAC1_INT_ATTRIBUTE(req_count); | ||
829 | UAC1_INT_ATTRIBUTE(audio_buf_size); | ||
830 | |||
831 | #define UAC1_STR_ATTRIBUTE(name) \ | ||
832 | static ssize_t f_uac1_opts_##name##_show(struct f_uac1_opts *opts, \ | ||
833 | char *page) \ | ||
834 | { \ | ||
835 | int result; \ | ||
836 | \ | ||
837 | mutex_lock(&opts->lock); \ | ||
838 | result = sprintf(page, "%s\n", opts->name); \ | ||
839 | mutex_unlock(&opts->lock); \ | ||
840 | \ | ||
841 | return result; \ | ||
842 | } \ | ||
843 | \ | ||
844 | static ssize_t f_uac1_opts_##name##_store(struct f_uac1_opts *opts, \ | ||
845 | const char *page, size_t len) \ | ||
846 | { \ | ||
847 | int ret = -EBUSY; \ | ||
848 | char *tmp; \ | ||
849 | \ | ||
850 | mutex_lock(&opts->lock); \ | ||
851 | if (opts->refcnt) \ | ||
852 | goto end; \ | ||
853 | \ | ||
854 | tmp = kstrndup(page, len, GFP_KERNEL); \ | ||
855 | if (tmp) { \ | ||
856 | ret = -ENOMEM; \ | ||
857 | goto end; \ | ||
858 | } \ | ||
859 | if (opts->name##_alloc) \ | ||
860 | kfree(opts->name); \ | ||
861 | opts->name##_alloc = true; \ | ||
862 | opts->name = tmp; \ | ||
863 | ret = len; \ | ||
864 | \ | ||
865 | end: \ | ||
866 | mutex_unlock(&opts->lock); \ | ||
867 | return ret; \ | ||
868 | } \ | ||
869 | \ | ||
870 | static struct f_uac1_opts_attribute f_uac1_opts_##name = \ | ||
871 | __CONFIGFS_ATTR(name, S_IRUGO | S_IWUSR, \ | ||
872 | f_uac1_opts_##name##_show, \ | ||
873 | f_uac1_opts_##name##_store) | ||
874 | |||
875 | UAC1_STR_ATTRIBUTE(fn_play); | ||
876 | UAC1_STR_ATTRIBUTE(fn_cap); | ||
877 | UAC1_STR_ATTRIBUTE(fn_cntl); | ||
878 | |||
879 | static struct configfs_attribute *f_uac1_attrs[] = { | ||
880 | &f_uac1_opts_req_buf_size.attr, | ||
881 | &f_uac1_opts_req_count.attr, | ||
882 | &f_uac1_opts_audio_buf_size.attr, | ||
883 | &f_uac1_opts_fn_play.attr, | ||
884 | &f_uac1_opts_fn_cap.attr, | ||
885 | &f_uac1_opts_fn_cntl.attr, | ||
886 | NULL, | ||
887 | }; | ||
888 | |||
889 | static struct config_item_type f_uac1_func_type = { | ||
890 | .ct_item_ops = &f_uac1_item_ops, | ||
891 | .ct_attrs = f_uac1_attrs, | ||
892 | .ct_owner = THIS_MODULE, | ||
893 | }; | ||
894 | |||
895 | static void f_audio_free_inst(struct usb_function_instance *f) | ||
896 | { | ||
897 | struct f_uac1_opts *opts; | ||
898 | |||
899 | opts = container_of(f, struct f_uac1_opts, func_inst); | ||
900 | gaudio_cleanup(opts->card); | ||
901 | if (opts->fn_play_alloc) | ||
902 | kfree(opts->fn_play); | ||
903 | if (opts->fn_cap_alloc) | ||
904 | kfree(opts->fn_cap); | ||
905 | if (opts->fn_cntl_alloc) | ||
906 | kfree(opts->fn_cntl); | ||
907 | kfree(opts); | ||
908 | } | ||
909 | |||
910 | static struct usb_function_instance *f_audio_alloc_inst(void) | ||
911 | { | ||
912 | struct f_uac1_opts *opts; | ||
913 | |||
914 | opts = kzalloc(sizeof(*opts), GFP_KERNEL); | ||
915 | if (!opts) | ||
916 | return ERR_PTR(-ENOMEM); | ||
917 | |||
918 | mutex_init(&opts->lock); | ||
919 | opts->func_inst.free_func_inst = f_audio_free_inst; | ||
920 | |||
921 | config_group_init_type_name(&opts->func_inst.group, "", | ||
922 | &f_uac1_func_type); | ||
923 | |||
924 | opts->req_buf_size = UAC1_OUT_EP_MAX_PACKET_SIZE; | ||
925 | opts->req_count = UAC1_REQ_COUNT; | ||
926 | opts->audio_buf_size = UAC1_AUDIO_BUF_SIZE; | ||
927 | opts->fn_play = FILE_PCM_PLAYBACK; | ||
928 | opts->fn_cap = FILE_PCM_CAPTURE; | ||
929 | opts->fn_cntl = FILE_CONTROL; | ||
930 | return &opts->func_inst; | ||
931 | } | ||
932 | |||
933 | static void f_audio_free(struct usb_function *f) | ||
934 | { | ||
935 | struct f_audio *audio = func_to_audio(f); | ||
936 | struct f_uac1_opts *opts; | ||
937 | |||
938 | opts = container_of(f->fi, struct f_uac1_opts, func_inst); | ||
939 | kfree(audio); | ||
940 | mutex_lock(&opts->lock); | ||
941 | --opts->refcnt; | ||
942 | mutex_unlock(&opts->lock); | ||
943 | } | ||
944 | |||
945 | static void f_audio_unbind(struct usb_configuration *c, struct usb_function *f) | ||
946 | { | ||
947 | usb_free_all_descriptors(f); | ||
948 | } | ||
949 | |||
950 | static struct usb_function *f_audio_alloc(struct usb_function_instance *fi) | ||
723 | { | 951 | { |
724 | struct f_audio *audio; | 952 | struct f_audio *audio; |
725 | int status; | 953 | struct f_uac1_opts *opts; |
726 | 954 | ||
727 | /* allocate and initialize one new instance */ | 955 | /* allocate and initialize one new instance */ |
728 | audio = kzalloc(sizeof *audio, GFP_KERNEL); | 956 | audio = kzalloc(sizeof(*audio), GFP_KERNEL); |
729 | if (!audio) | 957 | if (!audio) |
730 | return -ENOMEM; | 958 | return ERR_PTR(-ENOMEM); |
731 | 959 | ||
732 | audio->card.func.name = "g_audio"; | 960 | audio->card.func.name = "g_audio"; |
733 | audio->card.gadget = c->cdev->gadget; | ||
734 | 961 | ||
962 | opts = container_of(fi, struct f_uac1_opts, func_inst); | ||
963 | mutex_lock(&opts->lock); | ||
964 | ++opts->refcnt; | ||
965 | mutex_unlock(&opts->lock); | ||
735 | INIT_LIST_HEAD(&audio->play_queue); | 966 | INIT_LIST_HEAD(&audio->play_queue); |
736 | spin_lock_init(&audio->lock); | 967 | spin_lock_init(&audio->lock); |
737 | 968 | ||
738 | /* set up ASLA audio devices */ | ||
739 | status = gaudio_setup(&audio->card); | ||
740 | if (status < 0) | ||
741 | goto setup_fail; | ||
742 | |||
743 | audio->card.func.strings = audio_strings; | ||
744 | audio->card.func.bind = f_audio_bind; | 969 | audio->card.func.bind = f_audio_bind; |
745 | audio->card.func.unbind = f_audio_unbind; | 970 | audio->card.func.unbind = f_audio_unbind; |
746 | audio->card.func.set_alt = f_audio_set_alt; | 971 | audio->card.func.set_alt = f_audio_set_alt; |
747 | audio->card.func.setup = f_audio_setup; | 972 | audio->card.func.setup = f_audio_setup; |
748 | audio->card.func.disable = f_audio_disable; | 973 | audio->card.func.disable = f_audio_disable; |
974 | audio->card.func.free_func = f_audio_free; | ||
749 | 975 | ||
750 | control_selector_init(audio); | 976 | control_selector_init(audio); |
751 | 977 | ||
752 | INIT_WORK(&audio->playback_work, f_audio_playback_work); | 978 | INIT_WORK(&audio->playback_work, f_audio_playback_work); |
753 | 979 | ||
754 | status = usb_add_function(c, &audio->card.func); | 980 | return &audio->card.func; |
755 | if (status) | ||
756 | goto add_fail; | ||
757 | |||
758 | INFO(c->cdev, "audio_buf_size %d, req_buf_size %d, req_count %d\n", | ||
759 | audio_buf_size, req_buf_size, req_count); | ||
760 | |||
761 | return status; | ||
762 | |||
763 | add_fail: | ||
764 | gaudio_cleanup(); | ||
765 | setup_fail: | ||
766 | kfree(audio); | ||
767 | return status; | ||
768 | } | 981 | } |
982 | |||
983 | DECLARE_USB_FUNCTION_INIT(uac1, f_audio_alloc_inst, f_audio_alloc); | ||
984 | MODULE_LICENSE("GPL"); | ||
985 | MODULE_AUTHOR("Bryan Wu"); | ||
diff --git a/drivers/usb/gadget/function/f_uac2.c b/drivers/usb/gadget/function/f_uac2.c index 3ed89ecc8d6d..a5a27a504d67 100644 --- a/drivers/usb/gadget/function/f_uac2.c +++ b/drivers/usb/gadget/function/f_uac2.c | |||
@@ -20,35 +20,7 @@ | |||
20 | #include <sound/pcm.h> | 20 | #include <sound/pcm.h> |
21 | #include <sound/pcm_params.h> | 21 | #include <sound/pcm_params.h> |
22 | 22 | ||
23 | /* Playback(USB-IN) Default Stereo - Fl/Fr */ | 23 | #include "u_uac2.h" |
24 | static int p_chmask = 0x3; | ||
25 | module_param(p_chmask, uint, S_IRUGO); | ||
26 | MODULE_PARM_DESC(p_chmask, "Playback Channel Mask"); | ||
27 | |||
28 | /* Playback Default 48 KHz */ | ||
29 | static int p_srate = 48000; | ||
30 | module_param(p_srate, uint, S_IRUGO); | ||
31 | MODULE_PARM_DESC(p_srate, "Playback Sampling Rate"); | ||
32 | |||
33 | /* Playback Default 16bits/sample */ | ||
34 | static int p_ssize = 2; | ||
35 | module_param(p_ssize, uint, S_IRUGO); | ||
36 | MODULE_PARM_DESC(p_ssize, "Playback Sample Size(bytes)"); | ||
37 | |||
38 | /* Capture(USB-OUT) Default Stereo - Fl/Fr */ | ||
39 | static int c_chmask = 0x3; | ||
40 | module_param(c_chmask, uint, S_IRUGO); | ||
41 | MODULE_PARM_DESC(c_chmask, "Capture Channel Mask"); | ||
42 | |||
43 | /* Capture Default 64 KHz */ | ||
44 | static int c_srate = 64000; | ||
45 | module_param(c_srate, uint, S_IRUGO); | ||
46 | MODULE_PARM_DESC(c_srate, "Capture Sampling Rate"); | ||
47 | |||
48 | /* Capture Default 16bits/sample */ | ||
49 | static int c_ssize = 2; | ||
50 | module_param(c_ssize, uint, S_IRUGO); | ||
51 | MODULE_PARM_DESC(c_ssize, "Capture Sample Size(bytes)"); | ||
52 | 24 | ||
53 | /* Keep everyone on toes */ | 25 | /* Keep everyone on toes */ |
54 | #define USB_XFERS 2 | 26 | #define USB_XFERS 2 |
@@ -120,6 +92,15 @@ struct snd_uac2_chip { | |||
120 | 92 | ||
121 | struct snd_card *card; | 93 | struct snd_card *card; |
122 | struct snd_pcm *pcm; | 94 | struct snd_pcm *pcm; |
95 | |||
96 | /* timekeeping for the playback endpoint */ | ||
97 | unsigned int p_interval; | ||
98 | unsigned int p_residue; | ||
99 | |||
100 | /* pre-calculated values for playback iso completion */ | ||
101 | unsigned int p_pktsize; | ||
102 | unsigned int p_pktsize_residue; | ||
103 | unsigned int p_framesize; | ||
123 | }; | 104 | }; |
124 | 105 | ||
125 | #define BUFF_SIZE_MAX (PAGE_SIZE * 16) | 106 | #define BUFF_SIZE_MAX (PAGE_SIZE * 16) |
@@ -149,8 +130,6 @@ struct audio_dev { | |||
149 | struct snd_uac2_chip uac2; | 130 | struct snd_uac2_chip uac2; |
150 | }; | 131 | }; |
151 | 132 | ||
152 | static struct audio_dev *agdev_g; | ||
153 | |||
154 | static inline | 133 | static inline |
155 | struct audio_dev *func_to_agdev(struct usb_function *f) | 134 | struct audio_dev *func_to_agdev(struct usb_function *f) |
156 | { | 135 | { |
@@ -170,6 +149,12 @@ struct snd_uac2_chip *pdev_to_uac2(struct platform_device *p) | |||
170 | } | 149 | } |
171 | 150 | ||
172 | static inline | 151 | static inline |
152 | struct f_uac2_opts *agdev_to_uac2_opts(struct audio_dev *agdev) | ||
153 | { | ||
154 | return container_of(agdev->func.fi, struct f_uac2_opts, func_inst); | ||
155 | } | ||
156 | |||
157 | static inline | ||
173 | uint num_channels(uint chanmask) | 158 | uint num_channels(uint chanmask) |
174 | { | 159 | { |
175 | uint num = 0; | 160 | uint num = 0; |
@@ -187,8 +172,8 @@ agdev_iso_complete(struct usb_ep *ep, struct usb_request *req) | |||
187 | { | 172 | { |
188 | unsigned pending; | 173 | unsigned pending; |
189 | unsigned long flags; | 174 | unsigned long flags; |
175 | unsigned int hw_ptr; | ||
190 | bool update_alsa = false; | 176 | bool update_alsa = false; |
191 | unsigned char *src, *dst; | ||
192 | int status = req->status; | 177 | int status = req->status; |
193 | struct uac2_req *ur = req->context; | 178 | struct uac2_req *ur = req->context; |
194 | struct snd_pcm_substream *substream; | 179 | struct snd_pcm_substream *substream; |
@@ -216,12 +201,27 @@ agdev_iso_complete(struct usb_ep *ep, struct usb_request *req) | |||
216 | spin_lock_irqsave(&prm->lock, flags); | 201 | spin_lock_irqsave(&prm->lock, flags); |
217 | 202 | ||
218 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 203 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
219 | src = prm->dma_area + prm->hw_ptr; | 204 | /* |
205 | * For each IN packet, take the quotient of the current data | ||
206 | * rate and the endpoint's interval as the base packet size. | ||
207 | * If there is a residue from this division, add it to the | ||
208 | * residue accumulator. | ||
209 | */ | ||
210 | req->length = uac2->p_pktsize; | ||
211 | uac2->p_residue += uac2->p_pktsize_residue; | ||
212 | |||
213 | /* | ||
214 | * Whenever there are more bytes in the accumulator than we | ||
215 | * need to add one more sample frame, increase this packet's | ||
216 | * size and decrease the accumulator. | ||
217 | */ | ||
218 | if (uac2->p_residue / uac2->p_interval >= uac2->p_framesize) { | ||
219 | req->length += uac2->p_framesize; | ||
220 | uac2->p_residue -= uac2->p_framesize * | ||
221 | uac2->p_interval; | ||
222 | } | ||
223 | |||
220 | req->actual = req->length; | 224 | req->actual = req->length; |
221 | dst = req->buf; | ||
222 | } else { | ||
223 | dst = prm->dma_area + prm->hw_ptr; | ||
224 | src = req->buf; | ||
225 | } | 225 | } |
226 | 226 | ||
227 | pending = prm->hw_ptr % prm->period_size; | 227 | pending = prm->hw_ptr % prm->period_size; |
@@ -229,12 +229,32 @@ agdev_iso_complete(struct usb_ep *ep, struct usb_request *req) | |||
229 | if (pending >= prm->period_size) | 229 | if (pending >= prm->period_size) |
230 | update_alsa = true; | 230 | update_alsa = true; |
231 | 231 | ||
232 | hw_ptr = prm->hw_ptr; | ||
232 | prm->hw_ptr = (prm->hw_ptr + req->actual) % prm->dma_bytes; | 233 | prm->hw_ptr = (prm->hw_ptr + req->actual) % prm->dma_bytes; |
233 | 234 | ||
234 | spin_unlock_irqrestore(&prm->lock, flags); | 235 | spin_unlock_irqrestore(&prm->lock, flags); |
235 | 236 | ||
236 | /* Pack USB load in ALSA ring buffer */ | 237 | /* Pack USB load in ALSA ring buffer */ |
237 | memcpy(dst, src, req->actual); | 238 | pending = prm->dma_bytes - hw_ptr; |
239 | |||
240 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
241 | if (unlikely(pending < req->actual)) { | ||
242 | memcpy(req->buf, prm->dma_area + hw_ptr, pending); | ||
243 | memcpy(req->buf + pending, prm->dma_area, | ||
244 | req->actual - pending); | ||
245 | } else { | ||
246 | memcpy(req->buf, prm->dma_area + hw_ptr, req->actual); | ||
247 | } | ||
248 | } else { | ||
249 | if (unlikely(pending < req->actual)) { | ||
250 | memcpy(prm->dma_area + hw_ptr, req->buf, pending); | ||
251 | memcpy(prm->dma_area, req->buf + pending, | ||
252 | req->actual - pending); | ||
253 | } else { | ||
254 | memcpy(prm->dma_area + hw_ptr, req->buf, req->actual); | ||
255 | } | ||
256 | } | ||
257 | |||
238 | exit: | 258 | exit: |
239 | if (usb_ep_queue(ep, req, GFP_ATOMIC)) | 259 | if (usb_ep_queue(ep, req, GFP_ATOMIC)) |
240 | dev_err(&uac2->pdev.dev, "%d Error!\n", __LINE__); | 260 | dev_err(&uac2->pdev.dev, "%d Error!\n", __LINE__); |
@@ -342,6 +362,21 @@ static int uac2_pcm_open(struct snd_pcm_substream *substream) | |||
342 | { | 362 | { |
343 | struct snd_uac2_chip *uac2 = snd_pcm_substream_chip(substream); | 363 | struct snd_uac2_chip *uac2 = snd_pcm_substream_chip(substream); |
344 | struct snd_pcm_runtime *runtime = substream->runtime; | 364 | struct snd_pcm_runtime *runtime = substream->runtime; |
365 | struct audio_dev *audio_dev; | ||
366 | struct f_uac2_opts *opts; | ||
367 | int p_ssize, c_ssize; | ||
368 | int p_srate, c_srate; | ||
369 | int p_chmask, c_chmask; | ||
370 | |||
371 | audio_dev = uac2_to_agdev(uac2); | ||
372 | opts = container_of(audio_dev->func.fi, struct f_uac2_opts, func_inst); | ||
373 | p_ssize = opts->p_ssize; | ||
374 | c_ssize = opts->c_ssize; | ||
375 | p_srate = opts->p_srate; | ||
376 | c_srate = opts->c_srate; | ||
377 | p_chmask = opts->p_chmask; | ||
378 | c_chmask = opts->c_chmask; | ||
379 | uac2->p_residue = 0; | ||
345 | 380 | ||
346 | runtime->hw = uac2_pcm_hardware; | 381 | runtime->hw = uac2_pcm_hardware; |
347 | 382 | ||
@@ -411,7 +446,15 @@ static int snd_uac2_probe(struct platform_device *pdev) | |||
411 | struct snd_uac2_chip *uac2 = pdev_to_uac2(pdev); | 446 | struct snd_uac2_chip *uac2 = pdev_to_uac2(pdev); |
412 | struct snd_card *card; | 447 | struct snd_card *card; |
413 | struct snd_pcm *pcm; | 448 | struct snd_pcm *pcm; |
449 | struct audio_dev *audio_dev; | ||
450 | struct f_uac2_opts *opts; | ||
414 | int err; | 451 | int err; |
452 | int p_chmask, c_chmask; | ||
453 | |||
454 | audio_dev = uac2_to_agdev(uac2); | ||
455 | opts = container_of(audio_dev->func.fi, struct f_uac2_opts, func_inst); | ||
456 | p_chmask = opts->p_chmask; | ||
457 | c_chmask = opts->c_chmask; | ||
415 | 458 | ||
416 | /* Choose any slot, with no id */ | 459 | /* Choose any slot, with no id */ |
417 | err = snd_card_new(&pdev->dev, -1, NULL, THIS_MODULE, 0, &card); | 460 | err = snd_card_new(&pdev->dev, -1, NULL, THIS_MODULE, 0, &card); |
@@ -919,20 +962,58 @@ free_ep(struct uac2_rtd_params *prm, struct usb_ep *ep) | |||
919 | "%s:%d Error!\n", __func__, __LINE__); | 962 | "%s:%d Error!\n", __func__, __LINE__); |
920 | } | 963 | } |
921 | 964 | ||
922 | static int __init | 965 | static int |
923 | afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) | 966 | afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) |
924 | { | 967 | { |
925 | struct audio_dev *agdev = func_to_agdev(fn); | 968 | struct audio_dev *agdev = func_to_agdev(fn); |
926 | struct snd_uac2_chip *uac2 = &agdev->uac2; | 969 | struct snd_uac2_chip *uac2 = &agdev->uac2; |
927 | struct usb_composite_dev *cdev = cfg->cdev; | 970 | struct usb_composite_dev *cdev = cfg->cdev; |
928 | struct usb_gadget *gadget = cdev->gadget; | 971 | struct usb_gadget *gadget = cdev->gadget; |
972 | struct device *dev = &uac2->pdev.dev; | ||
929 | struct uac2_rtd_params *prm; | 973 | struct uac2_rtd_params *prm; |
974 | struct f_uac2_opts *uac2_opts; | ||
975 | struct usb_string *us; | ||
930 | int ret; | 976 | int ret; |
931 | 977 | ||
978 | uac2_opts = container_of(fn->fi, struct f_uac2_opts, func_inst); | ||
979 | |||
980 | us = usb_gstrings_attach(cdev, fn_strings, ARRAY_SIZE(strings_fn)); | ||
981 | if (IS_ERR(us)) | ||
982 | return PTR_ERR(us); | ||
983 | iad_desc.iFunction = us[STR_ASSOC].id; | ||
984 | std_ac_if_desc.iInterface = us[STR_IF_CTRL].id; | ||
985 | in_clk_src_desc.iClockSource = us[STR_CLKSRC_IN].id; | ||
986 | out_clk_src_desc.iClockSource = us[STR_CLKSRC_OUT].id; | ||
987 | usb_out_it_desc.iTerminal = us[STR_USB_IT].id; | ||
988 | io_in_it_desc.iTerminal = us[STR_IO_IT].id; | ||
989 | usb_in_ot_desc.iTerminal = us[STR_USB_OT].id; | ||
990 | io_out_ot_desc.iTerminal = us[STR_IO_OT].id; | ||
991 | std_as_out_if0_desc.iInterface = us[STR_AS_OUT_ALT0].id; | ||
992 | std_as_out_if1_desc.iInterface = us[STR_AS_OUT_ALT1].id; | ||
993 | std_as_in_if0_desc.iInterface = us[STR_AS_IN_ALT0].id; | ||
994 | std_as_in_if1_desc.iInterface = us[STR_AS_IN_ALT1].id; | ||
995 | |||
996 | |||
997 | /* Initialize the configurable parameters */ | ||
998 | usb_out_it_desc.bNrChannels = num_channels(uac2_opts->c_chmask); | ||
999 | usb_out_it_desc.bmChannelConfig = cpu_to_le32(uac2_opts->c_chmask); | ||
1000 | io_in_it_desc.bNrChannels = num_channels(uac2_opts->p_chmask); | ||
1001 | io_in_it_desc.bmChannelConfig = cpu_to_le32(uac2_opts->p_chmask); | ||
1002 | as_out_hdr_desc.bNrChannels = num_channels(uac2_opts->c_chmask); | ||
1003 | as_out_hdr_desc.bmChannelConfig = cpu_to_le32(uac2_opts->c_chmask); | ||
1004 | as_in_hdr_desc.bNrChannels = num_channels(uac2_opts->p_chmask); | ||
1005 | as_in_hdr_desc.bmChannelConfig = cpu_to_le32(uac2_opts->p_chmask); | ||
1006 | as_out_fmt1_desc.bSubslotSize = uac2_opts->c_ssize; | ||
1007 | as_out_fmt1_desc.bBitResolution = uac2_opts->c_ssize * 8; | ||
1008 | as_in_fmt1_desc.bSubslotSize = uac2_opts->p_ssize; | ||
1009 | as_in_fmt1_desc.bBitResolution = uac2_opts->p_ssize * 8; | ||
1010 | |||
1011 | snprintf(clksrc_in, sizeof(clksrc_in), "%uHz", uac2_opts->p_srate); | ||
1012 | snprintf(clksrc_out, sizeof(clksrc_out), "%uHz", uac2_opts->c_srate); | ||
1013 | |||
932 | ret = usb_interface_id(cfg, fn); | 1014 | ret = usb_interface_id(cfg, fn); |
933 | if (ret < 0) { | 1015 | if (ret < 0) { |
934 | dev_err(&uac2->pdev.dev, | 1016 | dev_err(dev, "%s:%d Error!\n", __func__, __LINE__); |
935 | "%s:%d Error!\n", __func__, __LINE__); | ||
936 | return ret; | 1017 | return ret; |
937 | } | 1018 | } |
938 | std_ac_if_desc.bInterfaceNumber = ret; | 1019 | std_ac_if_desc.bInterfaceNumber = ret; |
@@ -941,8 +1022,7 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) | |||
941 | 1022 | ||
942 | ret = usb_interface_id(cfg, fn); | 1023 | ret = usb_interface_id(cfg, fn); |
943 | if (ret < 0) { | 1024 | if (ret < 0) { |
944 | dev_err(&uac2->pdev.dev, | 1025 | dev_err(dev, "%s:%d Error!\n", __func__, __LINE__); |
945 | "%s:%d Error!\n", __func__, __LINE__); | ||
946 | return ret; | 1026 | return ret; |
947 | } | 1027 | } |
948 | std_as_out_if0_desc.bInterfaceNumber = ret; | 1028 | std_as_out_if0_desc.bInterfaceNumber = ret; |
@@ -952,8 +1032,7 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) | |||
952 | 1032 | ||
953 | ret = usb_interface_id(cfg, fn); | 1033 | ret = usb_interface_id(cfg, fn); |
954 | if (ret < 0) { | 1034 | if (ret < 0) { |
955 | dev_err(&uac2->pdev.dev, | 1035 | dev_err(dev, "%s:%d Error!\n", __func__, __LINE__); |
956 | "%s:%d Error!\n", __func__, __LINE__); | ||
957 | return ret; | 1036 | return ret; |
958 | } | 1037 | } |
959 | std_as_in_if0_desc.bInterfaceNumber = ret; | 1038 | std_as_in_if0_desc.bInterfaceNumber = ret; |
@@ -963,16 +1042,14 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) | |||
963 | 1042 | ||
964 | agdev->out_ep = usb_ep_autoconfig(gadget, &fs_epout_desc); | 1043 | agdev->out_ep = usb_ep_autoconfig(gadget, &fs_epout_desc); |
965 | if (!agdev->out_ep) { | 1044 | if (!agdev->out_ep) { |
966 | dev_err(&uac2->pdev.dev, | 1045 | dev_err(dev, "%s:%d Error!\n", __func__, __LINE__); |
967 | "%s:%d Error!\n", __func__, __LINE__); | ||
968 | goto err; | 1046 | goto err; |
969 | } | 1047 | } |
970 | agdev->out_ep->driver_data = agdev; | 1048 | agdev->out_ep->driver_data = agdev; |
971 | 1049 | ||
972 | agdev->in_ep = usb_ep_autoconfig(gadget, &fs_epin_desc); | 1050 | agdev->in_ep = usb_ep_autoconfig(gadget, &fs_epin_desc); |
973 | if (!agdev->in_ep) { | 1051 | if (!agdev->in_ep) { |
974 | dev_err(&uac2->pdev.dev, | 1052 | dev_err(dev, "%s:%d Error!\n", __func__, __LINE__); |
975 | "%s:%d Error!\n", __func__, __LINE__); | ||
976 | goto err; | 1053 | goto err; |
977 | } | 1054 | } |
978 | agdev->in_ep->driver_data = agdev; | 1055 | agdev->in_ep->driver_data = agdev; |
@@ -1020,27 +1097,6 @@ err: | |||
1020 | return -EINVAL; | 1097 | return -EINVAL; |
1021 | } | 1098 | } |
1022 | 1099 | ||
1023 | static void | ||
1024 | afunc_unbind(struct usb_configuration *cfg, struct usb_function *fn) | ||
1025 | { | ||
1026 | struct audio_dev *agdev = func_to_agdev(fn); | ||
1027 | struct uac2_rtd_params *prm; | ||
1028 | |||
1029 | alsa_uac2_exit(agdev); | ||
1030 | |||
1031 | prm = &agdev->uac2.p_prm; | ||
1032 | kfree(prm->rbuf); | ||
1033 | |||
1034 | prm = &agdev->uac2.c_prm; | ||
1035 | kfree(prm->rbuf); | ||
1036 | usb_free_all_descriptors(fn); | ||
1037 | |||
1038 | if (agdev->in_ep) | ||
1039 | agdev->in_ep->driver_data = NULL; | ||
1040 | if (agdev->out_ep) | ||
1041 | agdev->out_ep->driver_data = NULL; | ||
1042 | } | ||
1043 | |||
1044 | static int | 1100 | static int |
1045 | afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt) | 1101 | afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt) |
1046 | { | 1102 | { |
@@ -1048,23 +1104,22 @@ afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt) | |||
1048 | struct audio_dev *agdev = func_to_agdev(fn); | 1104 | struct audio_dev *agdev = func_to_agdev(fn); |
1049 | struct snd_uac2_chip *uac2 = &agdev->uac2; | 1105 | struct snd_uac2_chip *uac2 = &agdev->uac2; |
1050 | struct usb_gadget *gadget = cdev->gadget; | 1106 | struct usb_gadget *gadget = cdev->gadget; |
1107 | struct device *dev = &uac2->pdev.dev; | ||
1051 | struct usb_request *req; | 1108 | struct usb_request *req; |
1052 | struct usb_ep *ep; | 1109 | struct usb_ep *ep; |
1053 | struct uac2_rtd_params *prm; | 1110 | struct uac2_rtd_params *prm; |
1054 | int i; | 1111 | int req_len, i; |
1055 | 1112 | ||
1056 | /* No i/f has more than 2 alt settings */ | 1113 | /* No i/f has more than 2 alt settings */ |
1057 | if (alt > 1) { | 1114 | if (alt > 1) { |
1058 | dev_err(&uac2->pdev.dev, | 1115 | dev_err(dev, "%s:%d Error!\n", __func__, __LINE__); |
1059 | "%s:%d Error!\n", __func__, __LINE__); | ||
1060 | return -EINVAL; | 1116 | return -EINVAL; |
1061 | } | 1117 | } |
1062 | 1118 | ||
1063 | if (intf == agdev->ac_intf) { | 1119 | if (intf == agdev->ac_intf) { |
1064 | /* Control I/f has only 1 AltSetting - 0 */ | 1120 | /* Control I/f has only 1 AltSetting - 0 */ |
1065 | if (alt) { | 1121 | if (alt) { |
1066 | dev_err(&uac2->pdev.dev, | 1122 | dev_err(dev, "%s:%d Error!\n", __func__, __LINE__); |
1067 | "%s:%d Error!\n", __func__, __LINE__); | ||
1068 | return -EINVAL; | 1123 | return -EINVAL; |
1069 | } | 1124 | } |
1070 | return 0; | 1125 | return 0; |
@@ -1075,14 +1130,43 @@ afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt) | |||
1075 | prm = &uac2->c_prm; | 1130 | prm = &uac2->c_prm; |
1076 | config_ep_by_speed(gadget, fn, ep); | 1131 | config_ep_by_speed(gadget, fn, ep); |
1077 | agdev->as_out_alt = alt; | 1132 | agdev->as_out_alt = alt; |
1133 | req_len = prm->max_psize; | ||
1078 | } else if (intf == agdev->as_in_intf) { | 1134 | } else if (intf == agdev->as_in_intf) { |
1135 | struct f_uac2_opts *opts = agdev_to_uac2_opts(agdev); | ||
1136 | unsigned int factor, rate; | ||
1137 | struct usb_endpoint_descriptor *ep_desc; | ||
1138 | |||
1079 | ep = agdev->in_ep; | 1139 | ep = agdev->in_ep; |
1080 | prm = &uac2->p_prm; | 1140 | prm = &uac2->p_prm; |
1081 | config_ep_by_speed(gadget, fn, ep); | 1141 | config_ep_by_speed(gadget, fn, ep); |
1082 | agdev->as_in_alt = alt; | 1142 | agdev->as_in_alt = alt; |
1143 | |||
1144 | /* pre-calculate the playback endpoint's interval */ | ||
1145 | if (gadget->speed == USB_SPEED_FULL) { | ||
1146 | ep_desc = &fs_epin_desc; | ||
1147 | factor = 1000; | ||
1148 | } else { | ||
1149 | ep_desc = &hs_epin_desc; | ||
1150 | factor = 125; | ||
1151 | } | ||
1152 | |||
1153 | /* pre-compute some values for iso_complete() */ | ||
1154 | uac2->p_framesize = opts->p_ssize * | ||
1155 | num_channels(opts->p_chmask); | ||
1156 | rate = opts->p_srate * uac2->p_framesize; | ||
1157 | uac2->p_interval = (1 << (ep_desc->bInterval - 1)) * factor; | ||
1158 | uac2->p_pktsize = min_t(unsigned int, rate / uac2->p_interval, | ||
1159 | prm->max_psize); | ||
1160 | |||
1161 | if (uac2->p_pktsize < prm->max_psize) | ||
1162 | uac2->p_pktsize_residue = rate % uac2->p_interval; | ||
1163 | else | ||
1164 | uac2->p_pktsize_residue = 0; | ||
1165 | |||
1166 | req_len = uac2->p_pktsize; | ||
1167 | uac2->p_residue = 0; | ||
1083 | } else { | 1168 | } else { |
1084 | dev_err(&uac2->pdev.dev, | 1169 | dev_err(dev, "%s:%d Error!\n", __func__, __LINE__); |
1085 | "%s:%d Error!\n", __func__, __LINE__); | ||
1086 | return -EINVAL; | 1170 | return -EINVAL; |
1087 | } | 1171 | } |
1088 | 1172 | ||
@@ -1095,31 +1179,23 @@ afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt) | |||
1095 | usb_ep_enable(ep); | 1179 | usb_ep_enable(ep); |
1096 | 1180 | ||
1097 | for (i = 0; i < USB_XFERS; i++) { | 1181 | for (i = 0; i < USB_XFERS; i++) { |
1098 | if (prm->ureq[i].req) { | 1182 | if (!prm->ureq[i].req) { |
1099 | if (usb_ep_queue(ep, prm->ureq[i].req, GFP_ATOMIC)) | 1183 | req = usb_ep_alloc_request(ep, GFP_ATOMIC); |
1100 | dev_err(&uac2->pdev.dev, "%d Error!\n", | 1184 | if (req == NULL) |
1101 | __LINE__); | 1185 | return -ENOMEM; |
1102 | continue; | 1186 | |
1103 | } | 1187 | prm->ureq[i].req = req; |
1104 | 1188 | prm->ureq[i].pp = prm; | |
1105 | req = usb_ep_alloc_request(ep, GFP_ATOMIC); | 1189 | |
1106 | if (req == NULL) { | 1190 | req->zero = 0; |
1107 | dev_err(&uac2->pdev.dev, | 1191 | req->context = &prm->ureq[i]; |
1108 | "%s:%d Error!\n", __func__, __LINE__); | 1192 | req->length = req_len; |
1109 | return -EINVAL; | 1193 | req->complete = agdev_iso_complete; |
1194 | req->buf = prm->rbuf + i * prm->max_psize; | ||
1110 | } | 1195 | } |
1111 | 1196 | ||
1112 | prm->ureq[i].req = req; | 1197 | if (usb_ep_queue(ep, prm->ureq[i].req, GFP_ATOMIC)) |
1113 | prm->ureq[i].pp = prm; | 1198 | dev_err(dev, "%s:%d Error!\n", __func__, __LINE__); |
1114 | |||
1115 | req->zero = 0; | ||
1116 | req->context = &prm->ureq[i]; | ||
1117 | req->length = prm->max_psize; | ||
1118 | req->complete = agdev_iso_complete; | ||
1119 | req->buf = prm->rbuf + i * req->length; | ||
1120 | |||
1121 | if (usb_ep_queue(ep, req, GFP_ATOMIC)) | ||
1122 | dev_err(&uac2->pdev.dev, "%d Error!\n", __LINE__); | ||
1123 | } | 1199 | } |
1124 | 1200 | ||
1125 | return 0; | 1201 | return 0; |
@@ -1164,12 +1240,18 @@ in_rq_cur(struct usb_function *fn, const struct usb_ctrlrequest *cr) | |||
1164 | struct usb_request *req = fn->config->cdev->req; | 1240 | struct usb_request *req = fn->config->cdev->req; |
1165 | struct audio_dev *agdev = func_to_agdev(fn); | 1241 | struct audio_dev *agdev = func_to_agdev(fn); |
1166 | struct snd_uac2_chip *uac2 = &agdev->uac2; | 1242 | struct snd_uac2_chip *uac2 = &agdev->uac2; |
1243 | struct f_uac2_opts *opts; | ||
1167 | u16 w_length = le16_to_cpu(cr->wLength); | 1244 | u16 w_length = le16_to_cpu(cr->wLength); |
1168 | u16 w_index = le16_to_cpu(cr->wIndex); | 1245 | u16 w_index = le16_to_cpu(cr->wIndex); |
1169 | u16 w_value = le16_to_cpu(cr->wValue); | 1246 | u16 w_value = le16_to_cpu(cr->wValue); |
1170 | u8 entity_id = (w_index >> 8) & 0xff; | 1247 | u8 entity_id = (w_index >> 8) & 0xff; |
1171 | u8 control_selector = w_value >> 8; | 1248 | u8 control_selector = w_value >> 8; |
1172 | int value = -EOPNOTSUPP; | 1249 | int value = -EOPNOTSUPP; |
1250 | int p_srate, c_srate; | ||
1251 | |||
1252 | opts = agdev_to_uac2_opts(agdev); | ||
1253 | p_srate = opts->p_srate; | ||
1254 | c_srate = opts->c_srate; | ||
1173 | 1255 | ||
1174 | if (control_selector == UAC2_CS_CONTROL_SAM_FREQ) { | 1256 | if (control_selector == UAC2_CS_CONTROL_SAM_FREQ) { |
1175 | struct cntrl_cur_lay3 c; | 1257 | struct cntrl_cur_lay3 c; |
@@ -1199,6 +1281,7 @@ in_rq_range(struct usb_function *fn, const struct usb_ctrlrequest *cr) | |||
1199 | struct usb_request *req = fn->config->cdev->req; | 1281 | struct usb_request *req = fn->config->cdev->req; |
1200 | struct audio_dev *agdev = func_to_agdev(fn); | 1282 | struct audio_dev *agdev = func_to_agdev(fn); |
1201 | struct snd_uac2_chip *uac2 = &agdev->uac2; | 1283 | struct snd_uac2_chip *uac2 = &agdev->uac2; |
1284 | struct f_uac2_opts *opts; | ||
1202 | u16 w_length = le16_to_cpu(cr->wLength); | 1285 | u16 w_length = le16_to_cpu(cr->wLength); |
1203 | u16 w_index = le16_to_cpu(cr->wIndex); | 1286 | u16 w_index = le16_to_cpu(cr->wIndex); |
1204 | u16 w_value = le16_to_cpu(cr->wValue); | 1287 | u16 w_value = le16_to_cpu(cr->wValue); |
@@ -1206,6 +1289,11 @@ in_rq_range(struct usb_function *fn, const struct usb_ctrlrequest *cr) | |||
1206 | u8 control_selector = w_value >> 8; | 1289 | u8 control_selector = w_value >> 8; |
1207 | struct cntrl_range_lay3 r; | 1290 | struct cntrl_range_lay3 r; |
1208 | int value = -EOPNOTSUPP; | 1291 | int value = -EOPNOTSUPP; |
1292 | int p_srate, c_srate; | ||
1293 | |||
1294 | opts = agdev_to_uac2_opts(agdev); | ||
1295 | p_srate = opts->p_srate; | ||
1296 | c_srate = opts->c_srate; | ||
1209 | 1297 | ||
1210 | if (control_selector == UAC2_CS_CONTROL_SAM_FREQ) { | 1298 | if (control_selector == UAC2_CS_CONTROL_SAM_FREQ) { |
1211 | if (entity_id == USB_IN_CLK_ID) | 1299 | if (entity_id == USB_IN_CLK_ID) |
@@ -1309,66 +1397,184 @@ afunc_setup(struct usb_function *fn, const struct usb_ctrlrequest *cr) | |||
1309 | return value; | 1397 | return value; |
1310 | } | 1398 | } |
1311 | 1399 | ||
1312 | static int audio_bind_config(struct usb_configuration *cfg) | 1400 | static inline struct f_uac2_opts *to_f_uac2_opts(struct config_item *item) |
1313 | { | 1401 | { |
1314 | int res; | 1402 | return container_of(to_config_group(item), struct f_uac2_opts, |
1315 | 1403 | func_inst.group); | |
1316 | agdev_g = kzalloc(sizeof *agdev_g, GFP_KERNEL); | 1404 | } |
1317 | if (agdev_g == NULL) | ||
1318 | return -ENOMEM; | ||
1319 | |||
1320 | res = usb_string_ids_tab(cfg->cdev, strings_fn); | ||
1321 | if (res) | ||
1322 | return res; | ||
1323 | iad_desc.iFunction = strings_fn[STR_ASSOC].id; | ||
1324 | std_ac_if_desc.iInterface = strings_fn[STR_IF_CTRL].id; | ||
1325 | in_clk_src_desc.iClockSource = strings_fn[STR_CLKSRC_IN].id; | ||
1326 | out_clk_src_desc.iClockSource = strings_fn[STR_CLKSRC_OUT].id; | ||
1327 | usb_out_it_desc.iTerminal = strings_fn[STR_USB_IT].id; | ||
1328 | io_in_it_desc.iTerminal = strings_fn[STR_IO_IT].id; | ||
1329 | usb_in_ot_desc.iTerminal = strings_fn[STR_USB_OT].id; | ||
1330 | io_out_ot_desc.iTerminal = strings_fn[STR_IO_OT].id; | ||
1331 | std_as_out_if0_desc.iInterface = strings_fn[STR_AS_OUT_ALT0].id; | ||
1332 | std_as_out_if1_desc.iInterface = strings_fn[STR_AS_OUT_ALT1].id; | ||
1333 | std_as_in_if0_desc.iInterface = strings_fn[STR_AS_IN_ALT0].id; | ||
1334 | std_as_in_if1_desc.iInterface = strings_fn[STR_AS_IN_ALT1].id; | ||
1335 | |||
1336 | agdev_g->func.name = "uac2_func"; | ||
1337 | agdev_g->func.strings = fn_strings; | ||
1338 | agdev_g->func.bind = afunc_bind; | ||
1339 | agdev_g->func.unbind = afunc_unbind; | ||
1340 | agdev_g->func.set_alt = afunc_set_alt; | ||
1341 | agdev_g->func.get_alt = afunc_get_alt; | ||
1342 | agdev_g->func.disable = afunc_disable; | ||
1343 | agdev_g->func.setup = afunc_setup; | ||
1344 | 1405 | ||
1345 | /* Initialize the configurable parameters */ | 1406 | CONFIGFS_ATTR_STRUCT(f_uac2_opts); |
1346 | usb_out_it_desc.bNrChannels = num_channels(c_chmask); | 1407 | CONFIGFS_ATTR_OPS(f_uac2_opts); |
1347 | usb_out_it_desc.bmChannelConfig = cpu_to_le32(c_chmask); | 1408 | |
1348 | io_in_it_desc.bNrChannels = num_channels(p_chmask); | 1409 | static void f_uac2_attr_release(struct config_item *item) |
1349 | io_in_it_desc.bmChannelConfig = cpu_to_le32(p_chmask); | 1410 | { |
1350 | as_out_hdr_desc.bNrChannels = num_channels(c_chmask); | 1411 | struct f_uac2_opts *opts = to_f_uac2_opts(item); |
1351 | as_out_hdr_desc.bmChannelConfig = cpu_to_le32(c_chmask); | 1412 | |
1352 | as_in_hdr_desc.bNrChannels = num_channels(p_chmask); | 1413 | usb_put_function_instance(&opts->func_inst); |
1353 | as_in_hdr_desc.bmChannelConfig = cpu_to_le32(p_chmask); | ||
1354 | as_out_fmt1_desc.bSubslotSize = c_ssize; | ||
1355 | as_out_fmt1_desc.bBitResolution = c_ssize * 8; | ||
1356 | as_in_fmt1_desc.bSubslotSize = p_ssize; | ||
1357 | as_in_fmt1_desc.bBitResolution = p_ssize * 8; | ||
1358 | |||
1359 | snprintf(clksrc_in, sizeof(clksrc_in), "%uHz", p_srate); | ||
1360 | snprintf(clksrc_out, sizeof(clksrc_out), "%uHz", c_srate); | ||
1361 | |||
1362 | res = usb_add_function(cfg, &agdev_g->func); | ||
1363 | if (res < 0) | ||
1364 | kfree(agdev_g); | ||
1365 | |||
1366 | return res; | ||
1367 | } | 1414 | } |
1368 | 1415 | ||
1369 | static void | 1416 | static struct configfs_item_operations f_uac2_item_ops = { |
1370 | uac2_unbind_config(struct usb_configuration *cfg) | 1417 | .release = f_uac2_attr_release, |
1418 | .show_attribute = f_uac2_opts_attr_show, | ||
1419 | .store_attribute = f_uac2_opts_attr_store, | ||
1420 | }; | ||
1421 | |||
1422 | #define UAC2_ATTRIBUTE(name) \ | ||
1423 | static ssize_t f_uac2_opts_##name##_show(struct f_uac2_opts *opts, \ | ||
1424 | char *page) \ | ||
1425 | { \ | ||
1426 | int result; \ | ||
1427 | \ | ||
1428 | mutex_lock(&opts->lock); \ | ||
1429 | result = sprintf(page, "%u\n", opts->name); \ | ||
1430 | mutex_unlock(&opts->lock); \ | ||
1431 | \ | ||
1432 | return result; \ | ||
1433 | } \ | ||
1434 | \ | ||
1435 | static ssize_t f_uac2_opts_##name##_store(struct f_uac2_opts *opts, \ | ||
1436 | const char *page, size_t len) \ | ||
1437 | { \ | ||
1438 | int ret; \ | ||
1439 | u32 num; \ | ||
1440 | \ | ||
1441 | mutex_lock(&opts->lock); \ | ||
1442 | if (opts->refcnt) { \ | ||
1443 | ret = -EBUSY; \ | ||
1444 | goto end; \ | ||
1445 | } \ | ||
1446 | \ | ||
1447 | ret = kstrtou32(page, 0, &num); \ | ||
1448 | if (ret) \ | ||
1449 | goto end; \ | ||
1450 | \ | ||
1451 | opts->name = num; \ | ||
1452 | ret = len; \ | ||
1453 | \ | ||
1454 | end: \ | ||
1455 | mutex_unlock(&opts->lock); \ | ||
1456 | return ret; \ | ||
1457 | } \ | ||
1458 | \ | ||
1459 | static struct f_uac2_opts_attribute f_uac2_opts_##name = \ | ||
1460 | __CONFIGFS_ATTR(name, S_IRUGO | S_IWUSR, \ | ||
1461 | f_uac2_opts_##name##_show, \ | ||
1462 | f_uac2_opts_##name##_store) | ||
1463 | |||
1464 | UAC2_ATTRIBUTE(p_chmask); | ||
1465 | UAC2_ATTRIBUTE(p_srate); | ||
1466 | UAC2_ATTRIBUTE(p_ssize); | ||
1467 | UAC2_ATTRIBUTE(c_chmask); | ||
1468 | UAC2_ATTRIBUTE(c_srate); | ||
1469 | UAC2_ATTRIBUTE(c_ssize); | ||
1470 | |||
1471 | static struct configfs_attribute *f_uac2_attrs[] = { | ||
1472 | &f_uac2_opts_p_chmask.attr, | ||
1473 | &f_uac2_opts_p_srate.attr, | ||
1474 | &f_uac2_opts_p_ssize.attr, | ||
1475 | &f_uac2_opts_c_chmask.attr, | ||
1476 | &f_uac2_opts_c_srate.attr, | ||
1477 | &f_uac2_opts_c_ssize.attr, | ||
1478 | NULL, | ||
1479 | }; | ||
1480 | |||
1481 | static struct config_item_type f_uac2_func_type = { | ||
1482 | .ct_item_ops = &f_uac2_item_ops, | ||
1483 | .ct_attrs = f_uac2_attrs, | ||
1484 | .ct_owner = THIS_MODULE, | ||
1485 | }; | ||
1486 | |||
1487 | static void afunc_free_inst(struct usb_function_instance *f) | ||
1371 | { | 1488 | { |
1372 | kfree(agdev_g); | 1489 | struct f_uac2_opts *opts; |
1373 | agdev_g = NULL; | 1490 | |
1491 | opts = container_of(f, struct f_uac2_opts, func_inst); | ||
1492 | kfree(opts); | ||
1374 | } | 1493 | } |
1494 | |||
1495 | static struct usb_function_instance *afunc_alloc_inst(void) | ||
1496 | { | ||
1497 | struct f_uac2_opts *opts; | ||
1498 | |||
1499 | opts = kzalloc(sizeof(*opts), GFP_KERNEL); | ||
1500 | if (!opts) | ||
1501 | return ERR_PTR(-ENOMEM); | ||
1502 | |||
1503 | mutex_init(&opts->lock); | ||
1504 | opts->func_inst.free_func_inst = afunc_free_inst; | ||
1505 | |||
1506 | config_group_init_type_name(&opts->func_inst.group, "", | ||
1507 | &f_uac2_func_type); | ||
1508 | |||
1509 | opts->p_chmask = UAC2_DEF_PCHMASK; | ||
1510 | opts->p_srate = UAC2_DEF_PSRATE; | ||
1511 | opts->p_ssize = UAC2_DEF_PSSIZE; | ||
1512 | opts->c_chmask = UAC2_DEF_CCHMASK; | ||
1513 | opts->c_srate = UAC2_DEF_CSRATE; | ||
1514 | opts->c_ssize = UAC2_DEF_CSSIZE; | ||
1515 | return &opts->func_inst; | ||
1516 | } | ||
1517 | |||
1518 | static void afunc_free(struct usb_function *f) | ||
1519 | { | ||
1520 | struct audio_dev *agdev; | ||
1521 | struct f_uac2_opts *opts; | ||
1522 | |||
1523 | agdev = func_to_agdev(f); | ||
1524 | opts = container_of(f->fi, struct f_uac2_opts, func_inst); | ||
1525 | kfree(agdev); | ||
1526 | mutex_lock(&opts->lock); | ||
1527 | --opts->refcnt; | ||
1528 | mutex_unlock(&opts->lock); | ||
1529 | } | ||
1530 | |||
1531 | static void afunc_unbind(struct usb_configuration *c, struct usb_function *f) | ||
1532 | { | ||
1533 | struct audio_dev *agdev = func_to_agdev(f); | ||
1534 | struct uac2_rtd_params *prm; | ||
1535 | |||
1536 | alsa_uac2_exit(agdev); | ||
1537 | |||
1538 | prm = &agdev->uac2.p_prm; | ||
1539 | kfree(prm->rbuf); | ||
1540 | |||
1541 | prm = &agdev->uac2.c_prm; | ||
1542 | kfree(prm->rbuf); | ||
1543 | usb_free_all_descriptors(f); | ||
1544 | |||
1545 | if (agdev->in_ep) | ||
1546 | agdev->in_ep->driver_data = NULL; | ||
1547 | if (agdev->out_ep) | ||
1548 | agdev->out_ep->driver_data = NULL; | ||
1549 | } | ||
1550 | |||
1551 | struct usb_function *afunc_alloc(struct usb_function_instance *fi) | ||
1552 | { | ||
1553 | struct audio_dev *agdev; | ||
1554 | struct f_uac2_opts *opts; | ||
1555 | |||
1556 | agdev = kzalloc(sizeof(*agdev), GFP_KERNEL); | ||
1557 | if (agdev == NULL) | ||
1558 | return ERR_PTR(-ENOMEM); | ||
1559 | |||
1560 | opts = container_of(fi, struct f_uac2_opts, func_inst); | ||
1561 | mutex_lock(&opts->lock); | ||
1562 | ++opts->refcnt; | ||
1563 | mutex_unlock(&opts->lock); | ||
1564 | |||
1565 | agdev->func.name = "uac2_func"; | ||
1566 | agdev->func.bind = afunc_bind; | ||
1567 | agdev->func.unbind = afunc_unbind; | ||
1568 | agdev->func.set_alt = afunc_set_alt; | ||
1569 | agdev->func.get_alt = afunc_get_alt; | ||
1570 | agdev->func.disable = afunc_disable; | ||
1571 | agdev->func.setup = afunc_setup; | ||
1572 | agdev->func.free_func = afunc_free; | ||
1573 | |||
1574 | return &agdev->func; | ||
1575 | } | ||
1576 | |||
1577 | DECLARE_USB_FUNCTION_INIT(uac2, afunc_alloc_inst, afunc_alloc); | ||
1578 | MODULE_LICENSE("GPL"); | ||
1579 | MODULE_AUTHOR("Yadwinder Singh"); | ||
1580 | MODULE_AUTHOR("Jaswinder Singh"); | ||
diff --git a/drivers/usb/gadget/function/f_uvc.c b/drivers/usb/gadget/function/f_uvc.c index e2a1f50bd93c..e126439e4b65 100644 --- a/drivers/usb/gadget/function/f_uvc.c +++ b/drivers/usb/gadget/function/f_uvc.c | |||
@@ -11,6 +11,7 @@ | |||
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/module.h> | ||
14 | #include <linux/device.h> | 15 | #include <linux/device.h> |
15 | #include <linux/errno.h> | 16 | #include <linux/errno.h> |
16 | #include <linux/fs.h> | 17 | #include <linux/fs.h> |
@@ -27,24 +28,12 @@ | |||
27 | #include <media/v4l2-event.h> | 28 | #include <media/v4l2-event.h> |
28 | 29 | ||
29 | #include "uvc.h" | 30 | #include "uvc.h" |
31 | #include "uvc_v4l2.h" | ||
32 | #include "uvc_video.h" | ||
33 | #include "u_uvc.h" | ||
30 | 34 | ||
31 | unsigned int uvc_gadget_trace_param; | 35 | unsigned int uvc_gadget_trace_param; |
32 | 36 | ||
33 | /*-------------------------------------------------------------------------*/ | ||
34 | |||
35 | /* module parameters specific to the Video streaming endpoint */ | ||
36 | static unsigned int streaming_interval = 1; | ||
37 | module_param(streaming_interval, uint, S_IRUGO|S_IWUSR); | ||
38 | MODULE_PARM_DESC(streaming_interval, "1 - 16"); | ||
39 | |||
40 | static unsigned int streaming_maxpacket = 1024; | ||
41 | module_param(streaming_maxpacket, uint, S_IRUGO|S_IWUSR); | ||
42 | MODULE_PARM_DESC(streaming_maxpacket, "1 - 1023 (FS), 1 - 3072 (hs/ss)"); | ||
43 | |||
44 | static unsigned int streaming_maxburst; | ||
45 | module_param(streaming_maxburst, uint, S_IRUGO|S_IWUSR); | ||
46 | MODULE_PARM_DESC(streaming_maxburst, "0 - 15 (ss only)"); | ||
47 | |||
48 | /* -------------------------------------------------------------------------- | 37 | /* -------------------------------------------------------------------------- |
49 | * Function descriptors | 38 | * Function descriptors |
50 | */ | 39 | */ |
@@ -75,7 +64,7 @@ static struct usb_gadget_strings *uvc_function_strings[] = { | |||
75 | 64 | ||
76 | #define UVC_STATUS_MAX_PACKET_SIZE 16 /* 16 bytes status */ | 65 | #define UVC_STATUS_MAX_PACKET_SIZE 16 /* 16 bytes status */ |
77 | 66 | ||
78 | static struct usb_interface_assoc_descriptor uvc_iad __initdata = { | 67 | static struct usb_interface_assoc_descriptor uvc_iad = { |
79 | .bLength = sizeof(uvc_iad), | 68 | .bLength = sizeof(uvc_iad), |
80 | .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, | 69 | .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, |
81 | .bFirstInterface = 0, | 70 | .bFirstInterface = 0, |
@@ -86,7 +75,7 @@ static struct usb_interface_assoc_descriptor uvc_iad __initdata = { | |||
86 | .iFunction = 0, | 75 | .iFunction = 0, |
87 | }; | 76 | }; |
88 | 77 | ||
89 | static struct usb_interface_descriptor uvc_control_intf __initdata = { | 78 | static struct usb_interface_descriptor uvc_control_intf = { |
90 | .bLength = USB_DT_INTERFACE_SIZE, | 79 | .bLength = USB_DT_INTERFACE_SIZE, |
91 | .bDescriptorType = USB_DT_INTERFACE, | 80 | .bDescriptorType = USB_DT_INTERFACE, |
92 | .bInterfaceNumber = UVC_INTF_VIDEO_CONTROL, | 81 | .bInterfaceNumber = UVC_INTF_VIDEO_CONTROL, |
@@ -98,7 +87,7 @@ static struct usb_interface_descriptor uvc_control_intf __initdata = { | |||
98 | .iInterface = 0, | 87 | .iInterface = 0, |
99 | }; | 88 | }; |
100 | 89 | ||
101 | static struct usb_endpoint_descriptor uvc_control_ep __initdata = { | 90 | static struct usb_endpoint_descriptor uvc_control_ep = { |
102 | .bLength = USB_DT_ENDPOINT_SIZE, | 91 | .bLength = USB_DT_ENDPOINT_SIZE, |
103 | .bDescriptorType = USB_DT_ENDPOINT, | 92 | .bDescriptorType = USB_DT_ENDPOINT, |
104 | .bEndpointAddress = USB_DIR_IN, | 93 | .bEndpointAddress = USB_DIR_IN, |
@@ -107,7 +96,7 @@ static struct usb_endpoint_descriptor uvc_control_ep __initdata = { | |||
107 | .bInterval = 8, | 96 | .bInterval = 8, |
108 | }; | 97 | }; |
109 | 98 | ||
110 | static struct usb_ss_ep_comp_descriptor uvc_ss_control_comp __initdata = { | 99 | static struct usb_ss_ep_comp_descriptor uvc_ss_control_comp = { |
111 | .bLength = sizeof(uvc_ss_control_comp), | 100 | .bLength = sizeof(uvc_ss_control_comp), |
112 | .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, | 101 | .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, |
113 | /* The following 3 values can be tweaked if necessary. */ | 102 | /* The following 3 values can be tweaked if necessary. */ |
@@ -116,14 +105,14 @@ static struct usb_ss_ep_comp_descriptor uvc_ss_control_comp __initdata = { | |||
116 | .wBytesPerInterval = cpu_to_le16(UVC_STATUS_MAX_PACKET_SIZE), | 105 | .wBytesPerInterval = cpu_to_le16(UVC_STATUS_MAX_PACKET_SIZE), |
117 | }; | 106 | }; |
118 | 107 | ||
119 | static struct uvc_control_endpoint_descriptor uvc_control_cs_ep __initdata = { | 108 | static struct uvc_control_endpoint_descriptor uvc_control_cs_ep = { |
120 | .bLength = UVC_DT_CONTROL_ENDPOINT_SIZE, | 109 | .bLength = UVC_DT_CONTROL_ENDPOINT_SIZE, |
121 | .bDescriptorType = USB_DT_CS_ENDPOINT, | 110 | .bDescriptorType = USB_DT_CS_ENDPOINT, |
122 | .bDescriptorSubType = UVC_EP_INTERRUPT, | 111 | .bDescriptorSubType = UVC_EP_INTERRUPT, |
123 | .wMaxTransferSize = cpu_to_le16(UVC_STATUS_MAX_PACKET_SIZE), | 112 | .wMaxTransferSize = cpu_to_le16(UVC_STATUS_MAX_PACKET_SIZE), |
124 | }; | 113 | }; |
125 | 114 | ||
126 | static struct usb_interface_descriptor uvc_streaming_intf_alt0 __initdata = { | 115 | static struct usb_interface_descriptor uvc_streaming_intf_alt0 = { |
127 | .bLength = USB_DT_INTERFACE_SIZE, | 116 | .bLength = USB_DT_INTERFACE_SIZE, |
128 | .bDescriptorType = USB_DT_INTERFACE, | 117 | .bDescriptorType = USB_DT_INTERFACE, |
129 | .bInterfaceNumber = UVC_INTF_VIDEO_STREAMING, | 118 | .bInterfaceNumber = UVC_INTF_VIDEO_STREAMING, |
@@ -135,7 +124,7 @@ static struct usb_interface_descriptor uvc_streaming_intf_alt0 __initdata = { | |||
135 | .iInterface = 0, | 124 | .iInterface = 0, |
136 | }; | 125 | }; |
137 | 126 | ||
138 | static struct usb_interface_descriptor uvc_streaming_intf_alt1 __initdata = { | 127 | static struct usb_interface_descriptor uvc_streaming_intf_alt1 = { |
139 | .bLength = USB_DT_INTERFACE_SIZE, | 128 | .bLength = USB_DT_INTERFACE_SIZE, |
140 | .bDescriptorType = USB_DT_INTERFACE, | 129 | .bDescriptorType = USB_DT_INTERFACE, |
141 | .bInterfaceNumber = UVC_INTF_VIDEO_STREAMING, | 130 | .bInterfaceNumber = UVC_INTF_VIDEO_STREAMING, |
@@ -147,7 +136,7 @@ static struct usb_interface_descriptor uvc_streaming_intf_alt1 __initdata = { | |||
147 | .iInterface = 0, | 136 | .iInterface = 0, |
148 | }; | 137 | }; |
149 | 138 | ||
150 | static struct usb_endpoint_descriptor uvc_fs_streaming_ep __initdata = { | 139 | static struct usb_endpoint_descriptor uvc_fs_streaming_ep = { |
151 | .bLength = USB_DT_ENDPOINT_SIZE, | 140 | .bLength = USB_DT_ENDPOINT_SIZE, |
152 | .bDescriptorType = USB_DT_ENDPOINT, | 141 | .bDescriptorType = USB_DT_ENDPOINT, |
153 | .bEndpointAddress = USB_DIR_IN, | 142 | .bEndpointAddress = USB_DIR_IN, |
@@ -158,7 +147,7 @@ static struct usb_endpoint_descriptor uvc_fs_streaming_ep __initdata = { | |||
158 | */ | 147 | */ |
159 | }; | 148 | }; |
160 | 149 | ||
161 | static struct usb_endpoint_descriptor uvc_hs_streaming_ep __initdata = { | 150 | static struct usb_endpoint_descriptor uvc_hs_streaming_ep = { |
162 | .bLength = USB_DT_ENDPOINT_SIZE, | 151 | .bLength = USB_DT_ENDPOINT_SIZE, |
163 | .bDescriptorType = USB_DT_ENDPOINT, | 152 | .bDescriptorType = USB_DT_ENDPOINT, |
164 | .bEndpointAddress = USB_DIR_IN, | 153 | .bEndpointAddress = USB_DIR_IN, |
@@ -169,7 +158,7 @@ static struct usb_endpoint_descriptor uvc_hs_streaming_ep __initdata = { | |||
169 | */ | 158 | */ |
170 | }; | 159 | }; |
171 | 160 | ||
172 | static struct usb_endpoint_descriptor uvc_ss_streaming_ep __initdata = { | 161 | static struct usb_endpoint_descriptor uvc_ss_streaming_ep = { |
173 | .bLength = USB_DT_ENDPOINT_SIZE, | 162 | .bLength = USB_DT_ENDPOINT_SIZE, |
174 | .bDescriptorType = USB_DT_ENDPOINT, | 163 | .bDescriptorType = USB_DT_ENDPOINT, |
175 | 164 | ||
@@ -181,7 +170,7 @@ static struct usb_endpoint_descriptor uvc_ss_streaming_ep __initdata = { | |||
181 | */ | 170 | */ |
182 | }; | 171 | }; |
183 | 172 | ||
184 | static struct usb_ss_ep_comp_descriptor uvc_ss_streaming_comp __initdata = { | 173 | static struct usb_ss_ep_comp_descriptor uvc_ss_streaming_comp = { |
185 | .bLength = sizeof(uvc_ss_streaming_comp), | 174 | .bLength = sizeof(uvc_ss_streaming_comp), |
186 | .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, | 175 | .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, |
187 | /* The bMaxBurst, bmAttributes and wBytesPerInterval values will be | 176 | /* The bMaxBurst, bmAttributes and wBytesPerInterval values will be |
@@ -208,6 +197,12 @@ static const struct usb_descriptor_header * const uvc_ss_streaming[] = { | |||
208 | NULL, | 197 | NULL, |
209 | }; | 198 | }; |
210 | 199 | ||
200 | void uvc_set_trace_param(unsigned int trace) | ||
201 | { | ||
202 | uvc_gadget_trace_param = trace; | ||
203 | } | ||
204 | EXPORT_SYMBOL(uvc_set_trace_param); | ||
205 | |||
211 | /* -------------------------------------------------------------------------- | 206 | /* -------------------------------------------------------------------------- |
212 | * Control requests | 207 | * Control requests |
213 | */ | 208 | */ |
@@ -251,6 +246,12 @@ uvc_function_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) | |||
251 | if (le16_to_cpu(ctrl->wLength) > UVC_MAX_REQUEST_SIZE) | 246 | if (le16_to_cpu(ctrl->wLength) > UVC_MAX_REQUEST_SIZE) |
252 | return -EINVAL; | 247 | return -EINVAL; |
253 | 248 | ||
249 | /* Tell the complete callback to generate an event for the next request | ||
250 | * that will be enqueued by UVCIOC_SEND_RESPONSE. | ||
251 | */ | ||
252 | uvc->event_setup_out = !(ctrl->bRequestType & USB_DIR_IN); | ||
253 | uvc->event_length = le16_to_cpu(ctrl->wLength); | ||
254 | |||
254 | memset(&v4l2_event, 0, sizeof(v4l2_event)); | 255 | memset(&v4l2_event, 0, sizeof(v4l2_event)); |
255 | v4l2_event.type = UVC_EVENT_SETUP; | 256 | v4l2_event.type = UVC_EVENT_SETUP; |
256 | memcpy(&uvc_event->req, ctrl, sizeof(uvc_event->req)); | 257 | memcpy(&uvc_event->req, ctrl, sizeof(uvc_event->req)); |
@@ -408,7 +409,9 @@ uvc_register_video(struct uvc_device *uvc) | |||
408 | 409 | ||
409 | video->v4l2_dev = &uvc->v4l2_dev; | 410 | video->v4l2_dev = &uvc->v4l2_dev; |
410 | video->fops = &uvc_v4l2_fops; | 411 | video->fops = &uvc_v4l2_fops; |
412 | video->ioctl_ops = &uvc_v4l2_ioctl_ops; | ||
411 | video->release = video_device_release; | 413 | video->release = video_device_release; |
414 | video->vfl_dir = VFL_DIR_TX; | ||
412 | strlcpy(video->name, cdev->gadget->name, sizeof(video->name)); | 415 | strlcpy(video->name, cdev->gadget->name, sizeof(video->name)); |
413 | 416 | ||
414 | uvc->vdev = video; | 417 | uvc->vdev = video; |
@@ -434,7 +437,7 @@ uvc_register_video(struct uvc_device *uvc) | |||
434 | } \ | 437 | } \ |
435 | } while (0) | 438 | } while (0) |
436 | 439 | ||
437 | static struct usb_descriptor_header ** __init | 440 | static struct usb_descriptor_header ** |
438 | uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed) | 441 | uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed) |
439 | { | 442 | { |
440 | struct uvc_input_header_descriptor *uvc_streaming_header; | 443 | struct uvc_input_header_descriptor *uvc_streaming_header; |
@@ -554,45 +557,26 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed) | |||
554 | return hdr; | 557 | return hdr; |
555 | } | 558 | } |
556 | 559 | ||
557 | static void | 560 | static int |
558 | uvc_function_unbind(struct usb_configuration *c, struct usb_function *f) | ||
559 | { | ||
560 | struct usb_composite_dev *cdev = c->cdev; | ||
561 | struct uvc_device *uvc = to_uvc(f); | ||
562 | |||
563 | INFO(cdev, "uvc_function_unbind\n"); | ||
564 | |||
565 | video_unregister_device(uvc->vdev); | ||
566 | v4l2_device_unregister(&uvc->v4l2_dev); | ||
567 | uvc->control_ep->driver_data = NULL; | ||
568 | uvc->video.ep->driver_data = NULL; | ||
569 | |||
570 | uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id = 0; | ||
571 | usb_ep_free_request(cdev->gadget->ep0, uvc->control_req); | ||
572 | kfree(uvc->control_buf); | ||
573 | |||
574 | usb_free_all_descriptors(f); | ||
575 | |||
576 | kfree(uvc); | ||
577 | } | ||
578 | |||
579 | static int __init | ||
580 | uvc_function_bind(struct usb_configuration *c, struct usb_function *f) | 561 | uvc_function_bind(struct usb_configuration *c, struct usb_function *f) |
581 | { | 562 | { |
582 | struct usb_composite_dev *cdev = c->cdev; | 563 | struct usb_composite_dev *cdev = c->cdev; |
583 | struct uvc_device *uvc = to_uvc(f); | 564 | struct uvc_device *uvc = to_uvc(f); |
565 | struct usb_string *us; | ||
584 | unsigned int max_packet_mult; | 566 | unsigned int max_packet_mult; |
585 | unsigned int max_packet_size; | 567 | unsigned int max_packet_size; |
586 | struct usb_ep *ep; | 568 | struct usb_ep *ep; |
569 | struct f_uvc_opts *opts; | ||
587 | int ret = -EINVAL; | 570 | int ret = -EINVAL; |
588 | 571 | ||
589 | INFO(cdev, "uvc_function_bind\n"); | 572 | INFO(cdev, "uvc_function_bind\n"); |
590 | 573 | ||
574 | opts = to_f_uvc_opts(f->fi); | ||
591 | /* Sanity check the streaming endpoint module parameters. | 575 | /* Sanity check the streaming endpoint module parameters. |
592 | */ | 576 | */ |
593 | streaming_interval = clamp(streaming_interval, 1U, 16U); | 577 | opts->streaming_interval = clamp(opts->streaming_interval, 1U, 16U); |
594 | streaming_maxpacket = clamp(streaming_maxpacket, 1U, 3072U); | 578 | opts->streaming_maxpacket = clamp(opts->streaming_maxpacket, 1U, 3072U); |
595 | streaming_maxburst = min(streaming_maxburst, 15U); | 579 | opts->streaming_maxburst = min(opts->streaming_maxburst, 15U); |
596 | 580 | ||
597 | /* Fill in the FS/HS/SS Video Streaming specific descriptors from the | 581 | /* Fill in the FS/HS/SS Video Streaming specific descriptors from the |
598 | * module parameters. | 582 | * module parameters. |
@@ -600,30 +584,32 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) | |||
600 | * NOTE: We assume that the user knows what they are doing and won't | 584 | * NOTE: We assume that the user knows what they are doing and won't |
601 | * give parameters that their UDC doesn't support. | 585 | * give parameters that their UDC doesn't support. |
602 | */ | 586 | */ |
603 | if (streaming_maxpacket <= 1024) { | 587 | if (opts->streaming_maxpacket <= 1024) { |
604 | max_packet_mult = 1; | 588 | max_packet_mult = 1; |
605 | max_packet_size = streaming_maxpacket; | 589 | max_packet_size = opts->streaming_maxpacket; |
606 | } else if (streaming_maxpacket <= 2048) { | 590 | } else if (opts->streaming_maxpacket <= 2048) { |
607 | max_packet_mult = 2; | 591 | max_packet_mult = 2; |
608 | max_packet_size = streaming_maxpacket / 2; | 592 | max_packet_size = opts->streaming_maxpacket / 2; |
609 | } else { | 593 | } else { |
610 | max_packet_mult = 3; | 594 | max_packet_mult = 3; |
611 | max_packet_size = streaming_maxpacket / 3; | 595 | max_packet_size = opts->streaming_maxpacket / 3; |
612 | } | 596 | } |
613 | 597 | ||
614 | uvc_fs_streaming_ep.wMaxPacketSize = min(streaming_maxpacket, 1023U); | 598 | uvc_fs_streaming_ep.wMaxPacketSize = |
615 | uvc_fs_streaming_ep.bInterval = streaming_interval; | 599 | cpu_to_le16(min(opts->streaming_maxpacket, 1023U)); |
600 | uvc_fs_streaming_ep.bInterval = opts->streaming_interval; | ||
616 | 601 | ||
617 | uvc_hs_streaming_ep.wMaxPacketSize = max_packet_size; | 602 | uvc_hs_streaming_ep.wMaxPacketSize = |
618 | uvc_hs_streaming_ep.wMaxPacketSize |= ((max_packet_mult - 1) << 11); | 603 | cpu_to_le16(max_packet_size | ((max_packet_mult - 1) << 11)); |
619 | uvc_hs_streaming_ep.bInterval = streaming_interval; | 604 | uvc_hs_streaming_ep.bInterval = opts->streaming_interval; |
620 | 605 | ||
621 | uvc_ss_streaming_ep.wMaxPacketSize = max_packet_size; | 606 | uvc_ss_streaming_ep.wMaxPacketSize = cpu_to_le16(max_packet_size); |
622 | uvc_ss_streaming_ep.bInterval = streaming_interval; | 607 | uvc_ss_streaming_ep.bInterval = opts->streaming_interval; |
623 | uvc_ss_streaming_comp.bmAttributes = max_packet_mult - 1; | 608 | uvc_ss_streaming_comp.bmAttributes = max_packet_mult - 1; |
624 | uvc_ss_streaming_comp.bMaxBurst = streaming_maxburst; | 609 | uvc_ss_streaming_comp.bMaxBurst = opts->streaming_maxburst; |
625 | uvc_ss_streaming_comp.wBytesPerInterval = | 610 | uvc_ss_streaming_comp.wBytesPerInterval = |
626 | max_packet_size * max_packet_mult * streaming_maxburst; | 611 | cpu_to_le16(max_packet_size * max_packet_mult * |
612 | opts->streaming_maxburst); | ||
627 | 613 | ||
628 | /* Allocate endpoints. */ | 614 | /* Allocate endpoints. */ |
629 | ep = usb_ep_autoconfig(cdev->gadget, &uvc_control_ep); | 615 | ep = usb_ep_autoconfig(cdev->gadget, &uvc_control_ep); |
@@ -653,6 +639,18 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) | |||
653 | uvc_hs_streaming_ep.bEndpointAddress = uvc->video.ep->address; | 639 | uvc_hs_streaming_ep.bEndpointAddress = uvc->video.ep->address; |
654 | uvc_ss_streaming_ep.bEndpointAddress = uvc->video.ep->address; | 640 | uvc_ss_streaming_ep.bEndpointAddress = uvc->video.ep->address; |
655 | 641 | ||
642 | us = usb_gstrings_attach(cdev, uvc_function_strings, | ||
643 | ARRAY_SIZE(uvc_en_us_strings)); | ||
644 | if (IS_ERR(us)) { | ||
645 | ret = PTR_ERR(us); | ||
646 | goto error; | ||
647 | } | ||
648 | uvc_iad.iFunction = us[UVC_STRING_CONTROL_IDX].id; | ||
649 | uvc_control_intf.iInterface = us[UVC_STRING_CONTROL_IDX].id; | ||
650 | ret = us[UVC_STRING_STREAMING_IDX].id; | ||
651 | uvc_streaming_intf_alt0.iInterface = ret; | ||
652 | uvc_streaming_intf_alt1.iInterface = ret; | ||
653 | |||
656 | /* Allocate interface IDs. */ | 654 | /* Allocate interface IDs. */ |
657 | if ((ret = usb_interface_id(c, f)) < 0) | 655 | if ((ret = usb_interface_id(c, f)) < 0) |
658 | goto error; | 656 | goto error; |
@@ -697,7 +695,7 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) | |||
697 | } | 695 | } |
698 | 696 | ||
699 | /* Initialise video. */ | 697 | /* Initialise video. */ |
700 | ret = uvc_video_init(&uvc->video); | 698 | ret = uvcg_video_init(&uvc->video); |
701 | if (ret < 0) | 699 | if (ret < 0) |
702 | goto error; | 700 | goto error; |
703 | 701 | ||
@@ -720,10 +718,9 @@ error: | |||
720 | if (uvc->video.ep) | 718 | if (uvc->video.ep) |
721 | uvc->video.ep->driver_data = NULL; | 719 | uvc->video.ep->driver_data = NULL; |
722 | 720 | ||
723 | if (uvc->control_req) { | 721 | if (uvc->control_req) |
724 | usb_ep_free_request(cdev->gadget->ep0, uvc->control_req); | 722 | usb_ep_free_request(cdev->gadget->ep0, uvc->control_req); |
725 | kfree(uvc->control_buf); | 723 | kfree(uvc->control_buf); |
726 | } | ||
727 | 724 | ||
728 | usb_free_all_descriptors(f); | 725 | usb_free_all_descriptors(f); |
729 | return ret; | 726 | return ret; |
@@ -733,104 +730,81 @@ error: | |||
733 | * USB gadget function | 730 | * USB gadget function |
734 | */ | 731 | */ |
735 | 732 | ||
736 | /** | 733 | static void uvc_free_inst(struct usb_function_instance *f) |
737 | * uvc_bind_config - add a UVC function to a configuration | ||
738 | * @c: the configuration to support the UVC instance | ||
739 | * Context: single threaded during gadget setup | ||
740 | * | ||
741 | * Returns zero on success, else negative errno. | ||
742 | * | ||
743 | * Caller must have called @uvc_setup(). Caller is also responsible for | ||
744 | * calling @uvc_cleanup() before module unload. | ||
745 | */ | ||
746 | int __init | ||
747 | uvc_bind_config(struct usb_configuration *c, | ||
748 | const struct uvc_descriptor_header * const *fs_control, | ||
749 | const struct uvc_descriptor_header * const *ss_control, | ||
750 | const struct uvc_descriptor_header * const *fs_streaming, | ||
751 | const struct uvc_descriptor_header * const *hs_streaming, | ||
752 | const struct uvc_descriptor_header * const *ss_streaming) | ||
753 | { | 734 | { |
754 | struct uvc_device *uvc; | 735 | struct f_uvc_opts *opts = to_f_uvc_opts(f); |
755 | int ret = 0; | ||
756 | 736 | ||
757 | /* TODO Check if the USB device controller supports the required | 737 | kfree(opts); |
758 | * features. | 738 | } |
759 | */ | ||
760 | if (!gadget_is_dualspeed(c->cdev->gadget)) | ||
761 | return -EINVAL; | ||
762 | 739 | ||
763 | uvc = kzalloc(sizeof(*uvc), GFP_KERNEL); | 740 | static struct usb_function_instance *uvc_alloc_inst(void) |
764 | if (uvc == NULL) | 741 | { |
765 | return -ENOMEM; | 742 | struct f_uvc_opts *opts; |
766 | 743 | ||
767 | uvc->state = UVC_STATE_DISCONNECTED; | 744 | opts = kzalloc(sizeof(*opts), GFP_KERNEL); |
745 | if (!opts) | ||
746 | return ERR_PTR(-ENOMEM); | ||
747 | opts->func_inst.free_func_inst = uvc_free_inst; | ||
768 | 748 | ||
769 | /* Validate the descriptors. */ | 749 | return &opts->func_inst; |
770 | if (fs_control == NULL || fs_control[0] == NULL || | 750 | } |
771 | fs_control[0]->bDescriptorSubType != UVC_VC_HEADER) | ||
772 | goto error; | ||
773 | 751 | ||
774 | if (ss_control == NULL || ss_control[0] == NULL || | 752 | static void uvc_free(struct usb_function *f) |
775 | ss_control[0]->bDescriptorSubType != UVC_VC_HEADER) | 753 | { |
776 | goto error; | 754 | struct uvc_device *uvc = to_uvc(f); |
777 | 755 | ||
778 | if (fs_streaming == NULL || fs_streaming[0] == NULL || | 756 | kfree(uvc); |
779 | fs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER) | 757 | } |
780 | goto error; | ||
781 | 758 | ||
782 | if (hs_streaming == NULL || hs_streaming[0] == NULL || | 759 | static void uvc_unbind(struct usb_configuration *c, struct usb_function *f) |
783 | hs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER) | 760 | { |
784 | goto error; | 761 | struct usb_composite_dev *cdev = c->cdev; |
762 | struct uvc_device *uvc = to_uvc(f); | ||
785 | 763 | ||
786 | if (ss_streaming == NULL || ss_streaming[0] == NULL || | 764 | INFO(cdev, "%s\n", __func__); |
787 | ss_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER) | ||
788 | goto error; | ||
789 | 765 | ||
790 | uvc->desc.fs_control = fs_control; | 766 | video_unregister_device(uvc->vdev); |
791 | uvc->desc.ss_control = ss_control; | 767 | v4l2_device_unregister(&uvc->v4l2_dev); |
792 | uvc->desc.fs_streaming = fs_streaming; | 768 | uvc->control_ep->driver_data = NULL; |
793 | uvc->desc.hs_streaming = hs_streaming; | 769 | uvc->video.ep->driver_data = NULL; |
794 | uvc->desc.ss_streaming = ss_streaming; | ||
795 | 770 | ||
796 | /* String descriptors are global, we only need to allocate string IDs | 771 | usb_ep_free_request(cdev->gadget->ep0, uvc->control_req); |
797 | * for the first UVC function. UVC functions beyond the first (if any) | 772 | kfree(uvc->control_buf); |
798 | * will reuse the same IDs. | 773 | |
799 | */ | 774 | usb_free_all_descriptors(f); |
800 | if (uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id == 0) { | 775 | } |
801 | ret = usb_string_ids_tab(c->cdev, uvc_en_us_strings); | 776 | |
802 | if (ret) | 777 | static struct usb_function *uvc_alloc(struct usb_function_instance *fi) |
803 | goto error; | 778 | { |
804 | uvc_iad.iFunction = | 779 | struct uvc_device *uvc; |
805 | uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id; | 780 | struct f_uvc_opts *opts; |
806 | uvc_control_intf.iInterface = | 781 | |
807 | uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id; | 782 | uvc = kzalloc(sizeof(*uvc), GFP_KERNEL); |
808 | ret = uvc_en_us_strings[UVC_STRING_STREAMING_IDX].id; | 783 | if (uvc == NULL) |
809 | uvc_streaming_intf_alt0.iInterface = ret; | 784 | return ERR_PTR(-ENOMEM); |
810 | uvc_streaming_intf_alt1.iInterface = ret; | 785 | |
811 | } | 786 | uvc->state = UVC_STATE_DISCONNECTED; |
787 | opts = to_f_uvc_opts(fi); | ||
788 | |||
789 | uvc->desc.fs_control = opts->fs_control; | ||
790 | uvc->desc.ss_control = opts->ss_control; | ||
791 | uvc->desc.fs_streaming = opts->fs_streaming; | ||
792 | uvc->desc.hs_streaming = opts->hs_streaming; | ||
793 | uvc->desc.ss_streaming = opts->ss_streaming; | ||
812 | 794 | ||
813 | /* Register the function. */ | 795 | /* Register the function. */ |
814 | uvc->func.name = "uvc"; | 796 | uvc->func.name = "uvc"; |
815 | uvc->func.strings = uvc_function_strings; | ||
816 | uvc->func.bind = uvc_function_bind; | 797 | uvc->func.bind = uvc_function_bind; |
817 | uvc->func.unbind = uvc_function_unbind; | 798 | uvc->func.unbind = uvc_unbind; |
818 | uvc->func.get_alt = uvc_function_get_alt; | 799 | uvc->func.get_alt = uvc_function_get_alt; |
819 | uvc->func.set_alt = uvc_function_set_alt; | 800 | uvc->func.set_alt = uvc_function_set_alt; |
820 | uvc->func.disable = uvc_function_disable; | 801 | uvc->func.disable = uvc_function_disable; |
821 | uvc->func.setup = uvc_function_setup; | 802 | uvc->func.setup = uvc_function_setup; |
803 | uvc->func.free_func = uvc_free; | ||
822 | 804 | ||
823 | ret = usb_add_function(c, &uvc->func); | 805 | return &uvc->func; |
824 | if (ret) | ||
825 | kfree(uvc); | ||
826 | |||
827 | return ret; | ||
828 | |||
829 | error: | ||
830 | kfree(uvc); | ||
831 | return ret; | ||
832 | } | 806 | } |
833 | 807 | ||
834 | module_param_named(trace, uvc_gadget_trace_param, uint, S_IRUGO|S_IWUSR); | 808 | DECLARE_USB_FUNCTION_INIT(uvc, uvc_alloc_inst, uvc_alloc); |
835 | MODULE_PARM_DESC(trace, "Trace level bitmask"); | 809 | MODULE_LICENSE("GPL"); |
836 | 810 | MODULE_AUTHOR("Laurent Pinchart"); | |
diff --git a/drivers/usb/gadget/function/f_uvc.h b/drivers/usb/gadget/function/f_uvc.h index ec52752f7326..d0a73bdcbba1 100644 --- a/drivers/usb/gadget/function/f_uvc.h +++ b/drivers/usb/gadget/function/f_uvc.h | |||
@@ -16,12 +16,13 @@ | |||
16 | #include <linux/usb/composite.h> | 16 | #include <linux/usb/composite.h> |
17 | #include <linux/usb/video.h> | 17 | #include <linux/usb/video.h> |
18 | 18 | ||
19 | int uvc_bind_config(struct usb_configuration *c, | 19 | #include "uvc.h" |
20 | const struct uvc_descriptor_header * const *fs_control, | 20 | |
21 | const struct uvc_descriptor_header * const *hs_control, | 21 | void uvc_function_setup_continue(struct uvc_device *uvc); |
22 | const struct uvc_descriptor_header * const *fs_streaming, | 22 | |
23 | const struct uvc_descriptor_header * const *hs_streaming, | 23 | void uvc_function_connect(struct uvc_device *uvc); |
24 | const struct uvc_descriptor_header * const *ss_streaming); | 24 | |
25 | void uvc_function_disconnect(struct uvc_device *uvc); | ||
25 | 26 | ||
26 | #endif /* _F_UVC_H_ */ | 27 | #endif /* _F_UVC_H_ */ |
27 | 28 | ||
diff --git a/drivers/usb/gadget/function/g_zero.h b/drivers/usb/gadget/function/g_zero.h index 15f180904f8a..2ce28b9d97cc 100644 --- a/drivers/usb/gadget/function/g_zero.h +++ b/drivers/usb/gadget/function/g_zero.h | |||
@@ -10,6 +10,8 @@ | |||
10 | #define GZERO_QLEN 32 | 10 | #define GZERO_QLEN 32 |
11 | #define GZERO_ISOC_INTERVAL 4 | 11 | #define GZERO_ISOC_INTERVAL 4 |
12 | #define GZERO_ISOC_MAXPACKET 1024 | 12 | #define GZERO_ISOC_MAXPACKET 1024 |
13 | #define GZERO_INT_INTERVAL 1 /* Default interrupt interval = 1 ms */ | ||
14 | #define GZERO_INT_MAXPACKET 1024 | ||
13 | 15 | ||
14 | struct usb_zero_options { | 16 | struct usb_zero_options { |
15 | unsigned pattern; | 17 | unsigned pattern; |
@@ -17,6 +19,10 @@ struct usb_zero_options { | |||
17 | unsigned isoc_maxpacket; | 19 | unsigned isoc_maxpacket; |
18 | unsigned isoc_mult; | 20 | unsigned isoc_mult; |
19 | unsigned isoc_maxburst; | 21 | unsigned isoc_maxburst; |
22 | unsigned int_interval; /* In ms */ | ||
23 | unsigned int_maxpacket; | ||
24 | unsigned int_mult; | ||
25 | unsigned int_maxburst; | ||
20 | unsigned bulk_buflen; | 26 | unsigned bulk_buflen; |
21 | unsigned qlen; | 27 | unsigned qlen; |
22 | }; | 28 | }; |
@@ -28,6 +34,10 @@ struct f_ss_opts { | |||
28 | unsigned isoc_maxpacket; | 34 | unsigned isoc_maxpacket; |
29 | unsigned isoc_mult; | 35 | unsigned isoc_mult; |
30 | unsigned isoc_maxburst; | 36 | unsigned isoc_maxburst; |
37 | unsigned int_interval; /* In ms */ | ||
38 | unsigned int_maxpacket; | ||
39 | unsigned int_mult; | ||
40 | unsigned int_maxburst; | ||
31 | unsigned bulk_buflen; | 41 | unsigned bulk_buflen; |
32 | 42 | ||
33 | /* | 43 | /* |
@@ -62,6 +72,7 @@ int lb_modinit(void); | |||
62 | void free_ep_req(struct usb_ep *ep, struct usb_request *req); | 72 | void free_ep_req(struct usb_ep *ep, struct usb_request *req); |
63 | void disable_endpoints(struct usb_composite_dev *cdev, | 73 | void disable_endpoints(struct usb_composite_dev *cdev, |
64 | struct usb_ep *in, struct usb_ep *out, | 74 | struct usb_ep *in, struct usb_ep *out, |
65 | struct usb_ep *iso_in, struct usb_ep *iso_out); | 75 | struct usb_ep *iso_in, struct usb_ep *iso_out, |
76 | struct usb_ep *int_in, struct usb_ep *int_out); | ||
66 | 77 | ||
67 | #endif /* __G_ZERO_H */ | 78 | #endif /* __G_ZERO_H */ |
diff --git a/drivers/usb/gadget/function/u_fs.h b/drivers/usb/gadget/function/u_fs.h index d48897e8ffeb..cd128e31f808 100644 --- a/drivers/usb/gadget/function/u_fs.h +++ b/drivers/usb/gadget/function/u_fs.h | |||
@@ -224,6 +224,8 @@ struct ffs_data { | |||
224 | void *ms_os_descs_ext_prop_name_avail; | 224 | void *ms_os_descs_ext_prop_name_avail; |
225 | void *ms_os_descs_ext_prop_data_avail; | 225 | void *ms_os_descs_ext_prop_data_avail; |
226 | 226 | ||
227 | unsigned user_flags; | ||
228 | |||
227 | u8 eps_addrmap[15]; | 229 | u8 eps_addrmap[15]; |
228 | 230 | ||
229 | unsigned short strings_count; | 231 | unsigned short strings_count; |
diff --git a/drivers/usb/gadget/function/u_serial.c b/drivers/usb/gadget/function/u_serial.c index ad0aca812002..491082aaf103 100644 --- a/drivers/usb/gadget/function/u_serial.c +++ b/drivers/usb/gadget/function/u_serial.c | |||
@@ -55,11 +55,8 @@ | |||
55 | * for a telephone or fax link. And ttyGS2 might be something that just | 55 | * for a telephone or fax link. And ttyGS2 might be something that just |
56 | * needs a simple byte stream interface for some messaging protocol that | 56 | * needs a simple byte stream interface for some messaging protocol that |
57 | * is managed in userspace ... OBEX, PTP, and MTP have been mentioned. | 57 | * is managed in userspace ... OBEX, PTP, and MTP have been mentioned. |
58 | */ | 58 | * |
59 | 59 | * | |
60 | #define PREFIX "ttyGS" | ||
61 | |||
62 | /* | ||
63 | * gserial is the lifecycle interface, used by USB functions | 60 | * gserial is the lifecycle interface, used by USB functions |
64 | * gs_port is the I/O nexus, used by the tty driver | 61 | * gs_port is the I/O nexus, used by the tty driver |
65 | * tty_struct links to the tty/filesystem framework | 62 | * tty_struct links to the tty/filesystem framework |
@@ -385,9 +382,9 @@ __acquires(&port->port_lock) | |||
385 | list_del(&req->list); | 382 | list_del(&req->list); |
386 | req->zero = (gs_buf_data_avail(&port->port_write_buf) == 0); | 383 | req->zero = (gs_buf_data_avail(&port->port_write_buf) == 0); |
387 | 384 | ||
388 | pr_vdebug(PREFIX "%d: tx len=%d, 0x%02x 0x%02x 0x%02x ...\n", | 385 | pr_vdebug("ttyGS%d: tx len=%d, 0x%02x 0x%02x 0x%02x ...\n", |
389 | port->port_num, len, *((u8 *)req->buf), | 386 | port->port_num, len, *((u8 *)req->buf), |
390 | *((u8 *)req->buf+1), *((u8 *)req->buf+2)); | 387 | *((u8 *)req->buf+1), *((u8 *)req->buf+2)); |
391 | 388 | ||
392 | /* Drop lock while we call out of driver; completions | 389 | /* Drop lock while we call out of driver; completions |
393 | * could be issued while we do so. Disconnection may | 390 | * could be issued while we do so. Disconnection may |
@@ -503,13 +500,13 @@ static void gs_rx_push(unsigned long _port) | |||
503 | switch (req->status) { | 500 | switch (req->status) { |
504 | case -ESHUTDOWN: | 501 | case -ESHUTDOWN: |
505 | disconnect = true; | 502 | disconnect = true; |
506 | pr_vdebug(PREFIX "%d: shutdown\n", port->port_num); | 503 | pr_vdebug("ttyGS%d: shutdown\n", port->port_num); |
507 | break; | 504 | break; |
508 | 505 | ||
509 | default: | 506 | default: |
510 | /* presumably a transient fault */ | 507 | /* presumably a transient fault */ |
511 | pr_warning(PREFIX "%d: unexpected RX status %d\n", | 508 | pr_warn("ttyGS%d: unexpected RX status %d\n", |
512 | port->port_num, req->status); | 509 | port->port_num, req->status); |
513 | /* FALLTHROUGH */ | 510 | /* FALLTHROUGH */ |
514 | case 0: | 511 | case 0: |
515 | /* normal completion */ | 512 | /* normal completion */ |
@@ -537,9 +534,8 @@ static void gs_rx_push(unsigned long _port) | |||
537 | if (count != size) { | 534 | if (count != size) { |
538 | /* stop pushing; TTY layer can't handle more */ | 535 | /* stop pushing; TTY layer can't handle more */ |
539 | port->n_read += count; | 536 | port->n_read += count; |
540 | pr_vdebug(PREFIX "%d: rx block %d/%d\n", | 537 | pr_vdebug("ttyGS%d: rx block %d/%d\n", |
541 | port->port_num, | 538 | port->port_num, count, req->actual); |
542 | count, req->actual); | ||
543 | break; | 539 | break; |
544 | } | 540 | } |
545 | port->n_read = 0; | 541 | port->n_read = 0; |
@@ -569,7 +565,7 @@ static void gs_rx_push(unsigned long _port) | |||
569 | if (do_push) | 565 | if (do_push) |
570 | tasklet_schedule(&port->push); | 566 | tasklet_schedule(&port->push); |
571 | else | 567 | else |
572 | pr_warning(PREFIX "%d: RX not scheduled?\n", | 568 | pr_warn("ttyGS%d: RX not scheduled?\n", |
573 | port->port_num); | 569 | port->port_num); |
574 | } | 570 | } |
575 | } | 571 | } |
@@ -985,7 +981,7 @@ static void gs_unthrottle(struct tty_struct *tty) | |||
985 | * read queue backs up enough we'll be NAKing OUT packets. | 981 | * read queue backs up enough we'll be NAKing OUT packets. |
986 | */ | 982 | */ |
987 | tasklet_schedule(&port->push); | 983 | tasklet_schedule(&port->push); |
988 | pr_vdebug(PREFIX "%d: unthrottle\n", port->port_num); | 984 | pr_vdebug("ttyGS%d: unthrottle\n", port->port_num); |
989 | } | 985 | } |
990 | spin_unlock_irqrestore(&port->port_lock, flags); | 986 | spin_unlock_irqrestore(&port->port_lock, flags); |
991 | } | 987 | } |
@@ -1295,7 +1291,7 @@ static int userial_init(void) | |||
1295 | return -ENOMEM; | 1291 | return -ENOMEM; |
1296 | 1292 | ||
1297 | gs_tty_driver->driver_name = "g_serial"; | 1293 | gs_tty_driver->driver_name = "g_serial"; |
1298 | gs_tty_driver->name = PREFIX; | 1294 | gs_tty_driver->name = "ttyGS"; |
1299 | /* uses dynamically assigned dev_t values */ | 1295 | /* uses dynamically assigned dev_t values */ |
1300 | 1296 | ||
1301 | gs_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; | 1297 | gs_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; |
diff --git a/drivers/usb/gadget/function/u_uac1.c b/drivers/usb/gadget/function/u_uac1.c index 7a55fea43430..a44a07f30281 100644 --- a/drivers/usb/gadget/function/u_uac1.c +++ b/drivers/usb/gadget/function/u_uac1.c | |||
@@ -10,6 +10,7 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
13 | #include <linux/module.h> | ||
13 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
14 | #include <linux/device.h> | 15 | #include <linux/device.h> |
15 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
@@ -23,22 +24,6 @@ | |||
23 | * This component encapsulates the ALSA devices for USB audio gadget | 24 | * This component encapsulates the ALSA devices for USB audio gadget |
24 | */ | 25 | */ |
25 | 26 | ||
26 | #define FILE_PCM_PLAYBACK "/dev/snd/pcmC0D0p" | ||
27 | #define FILE_PCM_CAPTURE "/dev/snd/pcmC0D0c" | ||
28 | #define FILE_CONTROL "/dev/snd/controlC0" | ||
29 | |||
30 | static char *fn_play = FILE_PCM_PLAYBACK; | ||
31 | module_param(fn_play, charp, S_IRUGO); | ||
32 | MODULE_PARM_DESC(fn_play, "Playback PCM device file name"); | ||
33 | |||
34 | static char *fn_cap = FILE_PCM_CAPTURE; | ||
35 | module_param(fn_cap, charp, S_IRUGO); | ||
36 | MODULE_PARM_DESC(fn_cap, "Capture PCM device file name"); | ||
37 | |||
38 | static char *fn_cntl = FILE_CONTROL; | ||
39 | module_param(fn_cntl, charp, S_IRUGO); | ||
40 | MODULE_PARM_DESC(fn_cntl, "Control device file name"); | ||
41 | |||
42 | /*-------------------------------------------------------------------------*/ | 27 | /*-------------------------------------------------------------------------*/ |
43 | 28 | ||
44 | /** | 29 | /** |
@@ -167,7 +152,7 @@ static int playback_default_hw_params(struct gaudio_snd_dev *snd) | |||
167 | /** | 152 | /** |
168 | * Playback audio buffer data by ALSA PCM device | 153 | * Playback audio buffer data by ALSA PCM device |
169 | */ | 154 | */ |
170 | static size_t u_audio_playback(struct gaudio *card, void *buf, size_t count) | 155 | size_t u_audio_playback(struct gaudio *card, void *buf, size_t count) |
171 | { | 156 | { |
172 | struct gaudio_snd_dev *snd = &card->playback; | 157 | struct gaudio_snd_dev *snd = &card->playback; |
173 | struct snd_pcm_substream *substream = snd->substream; | 158 | struct snd_pcm_substream *substream = snd->substream; |
@@ -202,12 +187,12 @@ try_again: | |||
202 | return 0; | 187 | return 0; |
203 | } | 188 | } |
204 | 189 | ||
205 | static int u_audio_get_playback_channels(struct gaudio *card) | 190 | int u_audio_get_playback_channels(struct gaudio *card) |
206 | { | 191 | { |
207 | return card->playback.channels; | 192 | return card->playback.channels; |
208 | } | 193 | } |
209 | 194 | ||
210 | static int u_audio_get_playback_rate(struct gaudio *card) | 195 | int u_audio_get_playback_rate(struct gaudio *card) |
211 | { | 196 | { |
212 | return card->playback.rate; | 197 | return card->playback.rate; |
213 | } | 198 | } |
@@ -220,6 +205,13 @@ static int gaudio_open_snd_dev(struct gaudio *card) | |||
220 | { | 205 | { |
221 | struct snd_pcm_file *pcm_file; | 206 | struct snd_pcm_file *pcm_file; |
222 | struct gaudio_snd_dev *snd; | 207 | struct gaudio_snd_dev *snd; |
208 | struct f_uac1_opts *opts; | ||
209 | char *fn_play, *fn_cap, *fn_cntl; | ||
210 | |||
211 | opts = container_of(card->func.fi, struct f_uac1_opts, func_inst); | ||
212 | fn_play = opts->fn_play; | ||
213 | fn_cap = opts->fn_cap; | ||
214 | fn_cntl = opts->fn_cntl; | ||
223 | 215 | ||
224 | if (!card) | 216 | if (!card) |
225 | return -ENODEV; | 217 | return -ENODEV; |
@@ -293,7 +285,6 @@ static int gaudio_close_snd_dev(struct gaudio *gau) | |||
293 | return 0; | 285 | return 0; |
294 | } | 286 | } |
295 | 287 | ||
296 | static struct gaudio *the_card; | ||
297 | /** | 288 | /** |
298 | * gaudio_setup - setup ALSA interface and preparing for USB transfer | 289 | * gaudio_setup - setup ALSA interface and preparing for USB transfer |
299 | * | 290 | * |
@@ -301,15 +292,13 @@ static struct gaudio *the_card; | |||
301 | * | 292 | * |
302 | * Returns negative errno, or zero on success | 293 | * Returns negative errno, or zero on success |
303 | */ | 294 | */ |
304 | int __init gaudio_setup(struct gaudio *card) | 295 | int gaudio_setup(struct gaudio *card) |
305 | { | 296 | { |
306 | int ret; | 297 | int ret; |
307 | 298 | ||
308 | ret = gaudio_open_snd_dev(card); | 299 | ret = gaudio_open_snd_dev(card); |
309 | if (ret) | 300 | if (ret) |
310 | ERROR(card, "we need at least one control device\n"); | 301 | ERROR(card, "we need at least one control device\n"); |
311 | else if (!the_card) | ||
312 | the_card = card; | ||
313 | 302 | ||
314 | return ret; | 303 | return ret; |
315 | 304 | ||
@@ -320,11 +309,10 @@ int __init gaudio_setup(struct gaudio *card) | |||
320 | * | 309 | * |
321 | * This is called to free all resources allocated by @gaudio_setup(). | 310 | * This is called to free all resources allocated by @gaudio_setup(). |
322 | */ | 311 | */ |
323 | void gaudio_cleanup(void) | 312 | void gaudio_cleanup(struct gaudio *the_card) |
324 | { | 313 | { |
325 | if (the_card) { | 314 | if (the_card) { |
326 | gaudio_close_snd_dev(the_card); | 315 | gaudio_close_snd_dev(the_card); |
327 | the_card = NULL; | ||
328 | } | 316 | } |
329 | } | 317 | } |
330 | 318 | ||
diff --git a/drivers/usb/gadget/function/u_uac1.h b/drivers/usb/gadget/function/u_uac1.h index 18c2e729faf6..f8b17fe82efe 100644 --- a/drivers/usb/gadget/function/u_uac1.h +++ b/drivers/usb/gadget/function/u_uac1.h | |||
@@ -23,6 +23,14 @@ | |||
23 | 23 | ||
24 | #include "gadget_chips.h" | 24 | #include "gadget_chips.h" |
25 | 25 | ||
26 | #define FILE_PCM_PLAYBACK "/dev/snd/pcmC0D0p" | ||
27 | #define FILE_PCM_CAPTURE "/dev/snd/pcmC0D0c" | ||
28 | #define FILE_CONTROL "/dev/snd/controlC0" | ||
29 | |||
30 | #define UAC1_OUT_EP_MAX_PACKET_SIZE 200 | ||
31 | #define UAC1_REQ_COUNT 256 | ||
32 | #define UAC1_AUDIO_BUF_SIZE 48000 | ||
33 | |||
26 | /* | 34 | /* |
27 | * This represents the USB side of an audio card device, managed by a USB | 35 | * This represents the USB side of an audio card device, managed by a USB |
28 | * function which provides control and stream interfaces. | 36 | * function which provides control and stream interfaces. |
@@ -50,7 +58,28 @@ struct gaudio { | |||
50 | /* TODO */ | 58 | /* TODO */ |
51 | }; | 59 | }; |
52 | 60 | ||
61 | struct f_uac1_opts { | ||
62 | struct usb_function_instance func_inst; | ||
63 | int req_buf_size; | ||
64 | int req_count; | ||
65 | int audio_buf_size; | ||
66 | char *fn_play; | ||
67 | char *fn_cap; | ||
68 | char *fn_cntl; | ||
69 | unsigned bound:1; | ||
70 | unsigned fn_play_alloc:1; | ||
71 | unsigned fn_cap_alloc:1; | ||
72 | unsigned fn_cntl_alloc:1; | ||
73 | struct gaudio *card; | ||
74 | struct mutex lock; | ||
75 | int refcnt; | ||
76 | }; | ||
77 | |||
53 | int gaudio_setup(struct gaudio *card); | 78 | int gaudio_setup(struct gaudio *card); |
54 | void gaudio_cleanup(void); | 79 | void gaudio_cleanup(struct gaudio *the_card); |
80 | |||
81 | size_t u_audio_playback(struct gaudio *card, void *buf, size_t count); | ||
82 | int u_audio_get_playback_channels(struct gaudio *card); | ||
83 | int u_audio_get_playback_rate(struct gaudio *card); | ||
55 | 84 | ||
56 | #endif /* __U_AUDIO_H */ | 85 | #endif /* __U_AUDIO_H */ |
diff --git a/drivers/usb/gadget/function/u_uac2.h b/drivers/usb/gadget/function/u_uac2.h new file mode 100644 index 000000000000..78dd37279bd4 --- /dev/null +++ b/drivers/usb/gadget/function/u_uac2.h | |||
@@ -0,0 +1,42 @@ | |||
1 | /* | ||
2 | * u_uac2.h | ||
3 | * | ||
4 | * Utility definitions for UAC2 function | ||
5 | * | ||
6 | * Copyright (c) 2014 Samsung Electronics Co., Ltd. | ||
7 | * http://www.samsung.com | ||
8 | * | ||
9 | * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | */ | ||
15 | |||
16 | #ifndef U_UAC2_H | ||
17 | #define U_UAC2_H | ||
18 | |||
19 | #include <linux/usb/composite.h> | ||
20 | |||
21 | #define UAC2_DEF_PCHMASK 0x3 | ||
22 | #define UAC2_DEF_PSRATE 48000 | ||
23 | #define UAC2_DEF_PSSIZE 2 | ||
24 | #define UAC2_DEF_CCHMASK 0x3 | ||
25 | #define UAC2_DEF_CSRATE 64000 | ||
26 | #define UAC2_DEF_CSSIZE 2 | ||
27 | |||
28 | struct f_uac2_opts { | ||
29 | struct usb_function_instance func_inst; | ||
30 | int p_chmask; | ||
31 | int p_srate; | ||
32 | int p_ssize; | ||
33 | int c_chmask; | ||
34 | int c_srate; | ||
35 | int c_ssize; | ||
36 | bool bound; | ||
37 | |||
38 | struct mutex lock; | ||
39 | int refcnt; | ||
40 | }; | ||
41 | |||
42 | #endif | ||
diff --git a/drivers/usb/gadget/function/u_uvc.h b/drivers/usb/gadget/function/u_uvc.h new file mode 100644 index 000000000000..2a8dfdff0332 --- /dev/null +++ b/drivers/usb/gadget/function/u_uvc.h | |||
@@ -0,0 +1,39 @@ | |||
1 | /* | ||
2 | * u_uvc.h | ||
3 | * | ||
4 | * Utility definitions for the uvc function | ||
5 | * | ||
6 | * Copyright (c) 2013-2014 Samsung Electronics Co., Ltd. | ||
7 | * http://www.samsung.com | ||
8 | * | ||
9 | * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | */ | ||
15 | |||
16 | #ifndef U_UVC_H | ||
17 | #define U_UVC_H | ||
18 | |||
19 | #include <linux/usb/composite.h> | ||
20 | |||
21 | #define to_f_uvc_opts(f) container_of(f, struct f_uvc_opts, func_inst) | ||
22 | |||
23 | struct f_uvc_opts { | ||
24 | struct usb_function_instance func_inst; | ||
25 | unsigned int uvc_gadget_trace_param; | ||
26 | unsigned int streaming_interval; | ||
27 | unsigned int streaming_maxpacket; | ||
28 | unsigned int streaming_maxburst; | ||
29 | const struct uvc_descriptor_header * const *fs_control; | ||
30 | const struct uvc_descriptor_header * const *ss_control; | ||
31 | const struct uvc_descriptor_header * const *fs_streaming; | ||
32 | const struct uvc_descriptor_header * const *hs_streaming; | ||
33 | const struct uvc_descriptor_header * const *ss_streaming; | ||
34 | }; | ||
35 | |||
36 | void uvc_set_trace_param(unsigned int trace); | ||
37 | |||
38 | #endif /* U_UVC_H */ | ||
39 | |||
diff --git a/drivers/usb/gadget/function/uvc.h b/drivers/usb/gadget/function/uvc.h index 7a9111de8054..f67695cb28f8 100644 --- a/drivers/usb/gadget/function/uvc.h +++ b/drivers/usb/gadget/function/uvc.h | |||
@@ -53,6 +53,7 @@ struct uvc_event | |||
53 | #ifdef __KERNEL__ | 53 | #ifdef __KERNEL__ |
54 | 54 | ||
55 | #include <linux/usb.h> /* For usb_endpoint_* */ | 55 | #include <linux/usb.h> /* For usb_endpoint_* */ |
56 | #include <linux/usb/composite.h> | ||
56 | #include <linux/usb/gadget.h> | 57 | #include <linux/usb/gadget.h> |
57 | #include <linux/videodev2.h> | 58 | #include <linux/videodev2.h> |
58 | #include <linux/version.h> | 59 | #include <linux/version.h> |
@@ -96,9 +97,6 @@ extern unsigned int uvc_gadget_trace_param; | |||
96 | * Driver specific constants | 97 | * Driver specific constants |
97 | */ | 98 | */ |
98 | 99 | ||
99 | #define DRIVER_VERSION "0.1.0" | ||
100 | #define DRIVER_VERSION_NUMBER KERNEL_VERSION(0, 1, 0) | ||
101 | |||
102 | #define UVC_NUM_REQUESTS 4 | 100 | #define UVC_NUM_REQUESTS 4 |
103 | #define UVC_MAX_REQUEST_SIZE 64 | 101 | #define UVC_MAX_REQUEST_SIZE 64 |
104 | #define UVC_MAX_EVENTS 4 | 102 | #define UVC_MAX_EVENTS 4 |
diff --git a/drivers/usb/gadget/function/uvc_queue.c b/drivers/usb/gadget/function/uvc_queue.c index 1c29bc954db9..8ea8b3b227b4 100644 --- a/drivers/usb/gadget/function/uvc_queue.c +++ b/drivers/usb/gadget/function/uvc_queue.c | |||
@@ -28,7 +28,7 @@ | |||
28 | /* ------------------------------------------------------------------------ | 28 | /* ------------------------------------------------------------------------ |
29 | * Video buffers queue management. | 29 | * Video buffers queue management. |
30 | * | 30 | * |
31 | * Video queues is initialized by uvc_queue_init(). The function performs | 31 | * Video queues is initialized by uvcg_queue_init(). The function performs |
32 | * basic initialization of the uvc_video_queue struct and never fails. | 32 | * basic initialization of the uvc_video_queue struct and never fails. |
33 | * | 33 | * |
34 | * Video buffers are managed by videobuf2. The driver uses a mutex to protect | 34 | * Video buffers are managed by videobuf2. The driver uses a mutex to protect |
@@ -126,13 +126,12 @@ static struct vb2_ops uvc_queue_qops = { | |||
126 | .wait_finish = uvc_wait_finish, | 126 | .wait_finish = uvc_wait_finish, |
127 | }; | 127 | }; |
128 | 128 | ||
129 | static int uvc_queue_init(struct uvc_video_queue *queue, | 129 | int uvcg_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type) |
130 | enum v4l2_buf_type type) | ||
131 | { | 130 | { |
132 | int ret; | 131 | int ret; |
133 | 132 | ||
134 | queue->queue.type = type; | 133 | queue->queue.type = type; |
135 | queue->queue.io_modes = VB2_MMAP | VB2_USERPTR; | 134 | queue->queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; |
136 | queue->queue.drv_priv = queue; | 135 | queue->queue.drv_priv = queue; |
137 | queue->queue.buf_struct_size = sizeof(struct uvc_buffer); | 136 | queue->queue.buf_struct_size = sizeof(struct uvc_buffer); |
138 | queue->queue.ops = &uvc_queue_qops; | 137 | queue->queue.ops = &uvc_queue_qops; |
@@ -154,7 +153,7 @@ static int uvc_queue_init(struct uvc_video_queue *queue, | |||
154 | /* | 153 | /* |
155 | * Free the video buffers. | 154 | * Free the video buffers. |
156 | */ | 155 | */ |
157 | static void uvc_free_buffers(struct uvc_video_queue *queue) | 156 | void uvcg_free_buffers(struct uvc_video_queue *queue) |
158 | { | 157 | { |
159 | mutex_lock(&queue->mutex); | 158 | mutex_lock(&queue->mutex); |
160 | vb2_queue_release(&queue->queue); | 159 | vb2_queue_release(&queue->queue); |
@@ -164,8 +163,8 @@ static void uvc_free_buffers(struct uvc_video_queue *queue) | |||
164 | /* | 163 | /* |
165 | * Allocate the video buffers. | 164 | * Allocate the video buffers. |
166 | */ | 165 | */ |
167 | static int uvc_alloc_buffers(struct uvc_video_queue *queue, | 166 | int uvcg_alloc_buffers(struct uvc_video_queue *queue, |
168 | struct v4l2_requestbuffers *rb) | 167 | struct v4l2_requestbuffers *rb) |
169 | { | 168 | { |
170 | int ret; | 169 | int ret; |
171 | 170 | ||
@@ -176,8 +175,7 @@ static int uvc_alloc_buffers(struct uvc_video_queue *queue, | |||
176 | return ret ? ret : rb->count; | 175 | return ret ? ret : rb->count; |
177 | } | 176 | } |
178 | 177 | ||
179 | static int uvc_query_buffer(struct uvc_video_queue *queue, | 178 | int uvcg_query_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf) |
180 | struct v4l2_buffer *buf) | ||
181 | { | 179 | { |
182 | int ret; | 180 | int ret; |
183 | 181 | ||
@@ -188,8 +186,7 @@ static int uvc_query_buffer(struct uvc_video_queue *queue, | |||
188 | return ret; | 186 | return ret; |
189 | } | 187 | } |
190 | 188 | ||
191 | static int uvc_queue_buffer(struct uvc_video_queue *queue, | 189 | int uvcg_queue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf) |
192 | struct v4l2_buffer *buf) | ||
193 | { | 190 | { |
194 | unsigned long flags; | 191 | unsigned long flags; |
195 | int ret; | 192 | int ret; |
@@ -213,8 +210,8 @@ done: | |||
213 | * Dequeue a video buffer. If nonblocking is false, block until a buffer is | 210 | * Dequeue a video buffer. If nonblocking is false, block until a buffer is |
214 | * available. | 211 | * available. |
215 | */ | 212 | */ |
216 | static int uvc_dequeue_buffer(struct uvc_video_queue *queue, | 213 | int uvcg_dequeue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf, |
217 | struct v4l2_buffer *buf, int nonblocking) | 214 | int nonblocking) |
218 | { | 215 | { |
219 | int ret; | 216 | int ret; |
220 | 217 | ||
@@ -231,8 +228,8 @@ static int uvc_dequeue_buffer(struct uvc_video_queue *queue, | |||
231 | * This function implements video queue polling and is intended to be used by | 228 | * This function implements video queue polling and is intended to be used by |
232 | * the device poll handler. | 229 | * the device poll handler. |
233 | */ | 230 | */ |
234 | static unsigned int uvc_queue_poll(struct uvc_video_queue *queue, | 231 | unsigned int uvcg_queue_poll(struct uvc_video_queue *queue, struct file *file, |
235 | struct file *file, poll_table *wait) | 232 | poll_table *wait) |
236 | { | 233 | { |
237 | unsigned int ret; | 234 | unsigned int ret; |
238 | 235 | ||
@@ -243,8 +240,7 @@ static unsigned int uvc_queue_poll(struct uvc_video_queue *queue, | |||
243 | return ret; | 240 | return ret; |
244 | } | 241 | } |
245 | 242 | ||
246 | static int uvc_queue_mmap(struct uvc_video_queue *queue, | 243 | int uvcg_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma) |
247 | struct vm_area_struct *vma) | ||
248 | { | 244 | { |
249 | int ret; | 245 | int ret; |
250 | 246 | ||
@@ -261,8 +257,8 @@ static int uvc_queue_mmap(struct uvc_video_queue *queue, | |||
261 | * | 257 | * |
262 | * NO-MMU arch need this function to make mmap() work correctly. | 258 | * NO-MMU arch need this function to make mmap() work correctly. |
263 | */ | 259 | */ |
264 | static unsigned long uvc_queue_get_unmapped_area(struct uvc_video_queue *queue, | 260 | unsigned long uvcg_queue_get_unmapped_area(struct uvc_video_queue *queue, |
265 | unsigned long pgoff) | 261 | unsigned long pgoff) |
266 | { | 262 | { |
267 | unsigned long ret; | 263 | unsigned long ret; |
268 | 264 | ||
@@ -285,7 +281,7 @@ static unsigned long uvc_queue_get_unmapped_area(struct uvc_video_queue *queue, | |||
285 | * This function acquires the irq spinlock and can be called from interrupt | 281 | * This function acquires the irq spinlock and can be called from interrupt |
286 | * context. | 282 | * context. |
287 | */ | 283 | */ |
288 | static void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect) | 284 | void uvcg_queue_cancel(struct uvc_video_queue *queue, int disconnect) |
289 | { | 285 | { |
290 | struct uvc_buffer *buf; | 286 | struct uvc_buffer *buf; |
291 | unsigned long flags; | 287 | unsigned long flags; |
@@ -324,9 +320,9 @@ static void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect) | |||
324 | * the main queue. | 320 | * the main queue. |
325 | * | 321 | * |
326 | * This function can't be called from interrupt context. Use | 322 | * This function can't be called from interrupt context. Use |
327 | * uvc_queue_cancel() instead. | 323 | * uvcg_queue_cancel() instead. |
328 | */ | 324 | */ |
329 | static int uvc_queue_enable(struct uvc_video_queue *queue, int enable) | 325 | int uvcg_queue_enable(struct uvc_video_queue *queue, int enable) |
330 | { | 326 | { |
331 | unsigned long flags; | 327 | unsigned long flags; |
332 | int ret = 0; | 328 | int ret = 0; |
@@ -363,8 +359,8 @@ done: | |||
363 | } | 359 | } |
364 | 360 | ||
365 | /* called with &queue_irqlock held.. */ | 361 | /* called with &queue_irqlock held.. */ |
366 | static struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue, | 362 | struct uvc_buffer *uvcg_queue_next_buffer(struct uvc_video_queue *queue, |
367 | struct uvc_buffer *buf) | 363 | struct uvc_buffer *buf) |
368 | { | 364 | { |
369 | struct uvc_buffer *nextbuf; | 365 | struct uvc_buffer *nextbuf; |
370 | 366 | ||
@@ -392,7 +388,7 @@ static struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue, | |||
392 | return nextbuf; | 388 | return nextbuf; |
393 | } | 389 | } |
394 | 390 | ||
395 | static struct uvc_buffer *uvc_queue_head(struct uvc_video_queue *queue) | 391 | struct uvc_buffer *uvcg_queue_head(struct uvc_video_queue *queue) |
396 | { | 392 | { |
397 | struct uvc_buffer *buf = NULL; | 393 | struct uvc_buffer *buf = NULL; |
398 | 394 | ||
diff --git a/drivers/usb/gadget/function/uvc_queue.h b/drivers/usb/gadget/function/uvc_queue.h index 8e76ce982f1e..03919c724961 100644 --- a/drivers/usb/gadget/function/uvc_queue.h +++ b/drivers/usb/gadget/function/uvc_queue.h | |||
@@ -57,6 +57,39 @@ static inline int uvc_queue_streaming(struct uvc_video_queue *queue) | |||
57 | return vb2_is_streaming(&queue->queue); | 57 | return vb2_is_streaming(&queue->queue); |
58 | } | 58 | } |
59 | 59 | ||
60 | int uvcg_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type); | ||
61 | |||
62 | void uvcg_free_buffers(struct uvc_video_queue *queue); | ||
63 | |||
64 | int uvcg_alloc_buffers(struct uvc_video_queue *queue, | ||
65 | struct v4l2_requestbuffers *rb); | ||
66 | |||
67 | int uvcg_query_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf); | ||
68 | |||
69 | int uvcg_queue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf); | ||
70 | |||
71 | int uvcg_dequeue_buffer(struct uvc_video_queue *queue, | ||
72 | struct v4l2_buffer *buf, int nonblocking); | ||
73 | |||
74 | unsigned int uvcg_queue_poll(struct uvc_video_queue *queue, | ||
75 | struct file *file, poll_table *wait); | ||
76 | |||
77 | int uvcg_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma); | ||
78 | |||
79 | #ifndef CONFIG_MMU | ||
80 | unsigned long uvcg_queue_get_unmapped_area(struct uvc_video_queue *queue, | ||
81 | unsigned long pgoff); | ||
82 | #endif /* CONFIG_MMU */ | ||
83 | |||
84 | void uvcg_queue_cancel(struct uvc_video_queue *queue, int disconnect); | ||
85 | |||
86 | int uvcg_queue_enable(struct uvc_video_queue *queue, int enable); | ||
87 | |||
88 | struct uvc_buffer *uvcg_queue_next_buffer(struct uvc_video_queue *queue, | ||
89 | struct uvc_buffer *buf); | ||
90 | |||
91 | struct uvc_buffer *uvcg_queue_head(struct uvc_video_queue *queue); | ||
92 | |||
60 | #endif /* __KERNEL__ */ | 93 | #endif /* __KERNEL__ */ |
61 | 94 | ||
62 | #endif /* _UVC_QUEUE_H_ */ | 95 | #endif /* _UVC_QUEUE_H_ */ |
diff --git a/drivers/usb/gadget/function/uvc_v4l2.c b/drivers/usb/gadget/function/uvc_v4l2.c index ad48e81155e2..5aad7fededa5 100644 --- a/drivers/usb/gadget/function/uvc_v4l2.c +++ b/drivers/usb/gadget/function/uvc_v4l2.c | |||
@@ -23,8 +23,10 @@ | |||
23 | #include <media/v4l2-event.h> | 23 | #include <media/v4l2-event.h> |
24 | #include <media/v4l2-ioctl.h> | 24 | #include <media/v4l2-ioctl.h> |
25 | 25 | ||
26 | #include "f_uvc.h" | ||
26 | #include "uvc.h" | 27 | #include "uvc.h" |
27 | #include "uvc_queue.h" | 28 | #include "uvc_queue.h" |
29 | #include "uvc_video.h" | ||
28 | 30 | ||
29 | /* -------------------------------------------------------------------------- | 31 | /* -------------------------------------------------------------------------- |
30 | * Requests handling | 32 | * Requests handling |
@@ -48,7 +50,7 @@ uvc_send_response(struct uvc_device *uvc, struct uvc_request_data *data) | |||
48 | } | 50 | } |
49 | 51 | ||
50 | /* -------------------------------------------------------------------------- | 52 | /* -------------------------------------------------------------------------- |
51 | * V4L2 | 53 | * V4L2 ioctls |
52 | */ | 54 | */ |
53 | 55 | ||
54 | struct uvc_format | 56 | struct uvc_format |
@@ -63,8 +65,29 @@ static struct uvc_format uvc_formats[] = { | |||
63 | }; | 65 | }; |
64 | 66 | ||
65 | static int | 67 | static int |
66 | uvc_v4l2_get_format(struct uvc_video *video, struct v4l2_format *fmt) | 68 | uvc_v4l2_querycap(struct file *file, void *fh, struct v4l2_capability *cap) |
67 | { | 69 | { |
70 | struct video_device *vdev = video_devdata(file); | ||
71 | struct uvc_device *uvc = video_get_drvdata(vdev); | ||
72 | struct usb_composite_dev *cdev = uvc->func.config->cdev; | ||
73 | |||
74 | strlcpy(cap->driver, "g_uvc", sizeof(cap->driver)); | ||
75 | strlcpy(cap->card, cdev->gadget->name, sizeof(cap->card)); | ||
76 | strlcpy(cap->bus_info, dev_name(&cdev->gadget->dev), | ||
77 | sizeof(cap->bus_info)); | ||
78 | |||
79 | cap->capabilities = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING; | ||
80 | |||
81 | return 0; | ||
82 | } | ||
83 | |||
84 | static int | ||
85 | uvc_v4l2_get_format(struct file *file, void *fh, struct v4l2_format *fmt) | ||
86 | { | ||
87 | struct video_device *vdev = video_devdata(file); | ||
88 | struct uvc_device *uvc = video_get_drvdata(vdev); | ||
89 | struct uvc_video *video = &uvc->video; | ||
90 | |||
68 | fmt->fmt.pix.pixelformat = video->fcc; | 91 | fmt->fmt.pix.pixelformat = video->fcc; |
69 | fmt->fmt.pix.width = video->width; | 92 | fmt->fmt.pix.width = video->width; |
70 | fmt->fmt.pix.height = video->height; | 93 | fmt->fmt.pix.height = video->height; |
@@ -78,8 +101,11 @@ uvc_v4l2_get_format(struct uvc_video *video, struct v4l2_format *fmt) | |||
78 | } | 101 | } |
79 | 102 | ||
80 | static int | 103 | static int |
81 | uvc_v4l2_set_format(struct uvc_video *video, struct v4l2_format *fmt) | 104 | uvc_v4l2_set_format(struct file *file, void *fh, struct v4l2_format *fmt) |
82 | { | 105 | { |
106 | struct video_device *vdev = video_devdata(file); | ||
107 | struct uvc_device *uvc = video_get_drvdata(vdev); | ||
108 | struct uvc_video *video = &uvc->video; | ||
83 | struct uvc_format *format; | 109 | struct uvc_format *format; |
84 | unsigned int imagesize; | 110 | unsigned int imagesize; |
85 | unsigned int bpl; | 111 | unsigned int bpl; |
@@ -116,209 +142,184 @@ uvc_v4l2_set_format(struct uvc_video *video, struct v4l2_format *fmt) | |||
116 | } | 142 | } |
117 | 143 | ||
118 | static int | 144 | static int |
119 | uvc_v4l2_open(struct file *file) | 145 | uvc_v4l2_reqbufs(struct file *file, void *fh, struct v4l2_requestbuffers *b) |
120 | { | 146 | { |
121 | struct video_device *vdev = video_devdata(file); | 147 | struct video_device *vdev = video_devdata(file); |
122 | struct uvc_device *uvc = video_get_drvdata(vdev); | 148 | struct uvc_device *uvc = video_get_drvdata(vdev); |
123 | struct uvc_file_handle *handle; | 149 | struct uvc_video *video = &uvc->video; |
124 | |||
125 | handle = kzalloc(sizeof(*handle), GFP_KERNEL); | ||
126 | if (handle == NULL) | ||
127 | return -ENOMEM; | ||
128 | |||
129 | v4l2_fh_init(&handle->vfh, vdev); | ||
130 | v4l2_fh_add(&handle->vfh); | ||
131 | 150 | ||
132 | handle->device = &uvc->video; | 151 | if (b->type != video->queue.queue.type) |
133 | file->private_data = &handle->vfh; | 152 | return -EINVAL; |
134 | 153 | ||
135 | uvc_function_connect(uvc); | 154 | return uvcg_alloc_buffers(&video->queue, b); |
136 | return 0; | ||
137 | } | 155 | } |
138 | 156 | ||
139 | static int | 157 | static int |
140 | uvc_v4l2_release(struct file *file) | 158 | uvc_v4l2_querybuf(struct file *file, void *fh, struct v4l2_buffer *b) |
141 | { | 159 | { |
142 | struct video_device *vdev = video_devdata(file); | 160 | struct video_device *vdev = video_devdata(file); |
143 | struct uvc_device *uvc = video_get_drvdata(vdev); | 161 | struct uvc_device *uvc = video_get_drvdata(vdev); |
144 | struct uvc_file_handle *handle = to_uvc_file_handle(file->private_data); | 162 | struct uvc_video *video = &uvc->video; |
145 | struct uvc_video *video = handle->device; | ||
146 | |||
147 | uvc_function_disconnect(uvc); | ||
148 | |||
149 | uvc_video_enable(video, 0); | ||
150 | uvc_free_buffers(&video->queue); | ||
151 | |||
152 | file->private_data = NULL; | ||
153 | v4l2_fh_del(&handle->vfh); | ||
154 | v4l2_fh_exit(&handle->vfh); | ||
155 | kfree(handle); | ||
156 | 163 | ||
157 | return 0; | 164 | return uvcg_query_buffer(&video->queue, b); |
158 | } | 165 | } |
159 | 166 | ||
160 | static long | 167 | static int |
161 | uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) | 168 | uvc_v4l2_qbuf(struct file *file, void *fh, struct v4l2_buffer *b) |
162 | { | 169 | { |
163 | struct video_device *vdev = video_devdata(file); | 170 | struct video_device *vdev = video_devdata(file); |
164 | struct uvc_device *uvc = video_get_drvdata(vdev); | 171 | struct uvc_device *uvc = video_get_drvdata(vdev); |
165 | struct uvc_file_handle *handle = to_uvc_file_handle(file->private_data); | ||
166 | struct usb_composite_dev *cdev = uvc->func.config->cdev; | ||
167 | struct uvc_video *video = &uvc->video; | 172 | struct uvc_video *video = &uvc->video; |
168 | int ret = 0; | 173 | int ret; |
169 | |||
170 | switch (cmd) { | ||
171 | /* Query capabilities */ | ||
172 | case VIDIOC_QUERYCAP: | ||
173 | { | ||
174 | struct v4l2_capability *cap = arg; | ||
175 | |||
176 | memset(cap, 0, sizeof *cap); | ||
177 | strlcpy(cap->driver, "g_uvc", sizeof(cap->driver)); | ||
178 | strlcpy(cap->card, cdev->gadget->name, sizeof(cap->card)); | ||
179 | strlcpy(cap->bus_info, dev_name(&cdev->gadget->dev), | ||
180 | sizeof cap->bus_info); | ||
181 | cap->version = DRIVER_VERSION_NUMBER; | ||
182 | cap->capabilities = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING; | ||
183 | break; | ||
184 | } | ||
185 | |||
186 | /* Get & Set format */ | ||
187 | case VIDIOC_G_FMT: | ||
188 | { | ||
189 | struct v4l2_format *fmt = arg; | ||
190 | 174 | ||
191 | if (fmt->type != video->queue.queue.type) | 175 | ret = uvcg_queue_buffer(&video->queue, b); |
192 | return -EINVAL; | 176 | if (ret < 0) |
177 | return ret; | ||
193 | 178 | ||
194 | return uvc_v4l2_get_format(video, fmt); | 179 | return uvcg_video_pump(video); |
195 | } | 180 | } |
196 | 181 | ||
197 | case VIDIOC_S_FMT: | 182 | static int |
198 | { | 183 | uvc_v4l2_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b) |
199 | struct v4l2_format *fmt = arg; | 184 | { |
185 | struct video_device *vdev = video_devdata(file); | ||
186 | struct uvc_device *uvc = video_get_drvdata(vdev); | ||
187 | struct uvc_video *video = &uvc->video; | ||
200 | 188 | ||
201 | if (fmt->type != video->queue.queue.type) | 189 | return uvcg_dequeue_buffer(&video->queue, b, file->f_flags & O_NONBLOCK); |
202 | return -EINVAL; | 190 | } |
203 | 191 | ||
204 | return uvc_v4l2_set_format(video, fmt); | 192 | static int |
205 | } | 193 | uvc_v4l2_streamon(struct file *file, void *fh, enum v4l2_buf_type type) |
194 | { | ||
195 | struct video_device *vdev = video_devdata(file); | ||
196 | struct uvc_device *uvc = video_get_drvdata(vdev); | ||
197 | struct uvc_video *video = &uvc->video; | ||
198 | int ret; | ||
206 | 199 | ||
207 | /* Buffers & streaming */ | 200 | if (type != video->queue.queue.type) |
208 | case VIDIOC_REQBUFS: | 201 | return -EINVAL; |
209 | { | ||
210 | struct v4l2_requestbuffers *rb = arg; | ||
211 | 202 | ||
212 | if (rb->type != video->queue.queue.type) | 203 | /* Enable UVC video. */ |
213 | return -EINVAL; | 204 | ret = uvcg_video_enable(video, 1); |
205 | if (ret < 0) | ||
206 | return ret; | ||
214 | 207 | ||
215 | ret = uvc_alloc_buffers(&video->queue, rb); | 208 | /* |
216 | if (ret < 0) | 209 | * Complete the alternate setting selection setup phase now that |
217 | return ret; | 210 | * userspace is ready to provide video frames. |
211 | */ | ||
212 | uvc_function_setup_continue(uvc); | ||
213 | uvc->state = UVC_STATE_STREAMING; | ||
218 | 214 | ||
219 | ret = 0; | 215 | return 0; |
220 | break; | 216 | } |
221 | } | ||
222 | |||
223 | case VIDIOC_QUERYBUF: | ||
224 | { | ||
225 | struct v4l2_buffer *buf = arg; | ||
226 | 217 | ||
227 | return uvc_query_buffer(&video->queue, buf); | 218 | static int |
228 | } | 219 | uvc_v4l2_streamoff(struct file *file, void *fh, enum v4l2_buf_type type) |
220 | { | ||
221 | struct video_device *vdev = video_devdata(file); | ||
222 | struct uvc_device *uvc = video_get_drvdata(vdev); | ||
223 | struct uvc_video *video = &uvc->video; | ||
229 | 224 | ||
230 | case VIDIOC_QBUF: | 225 | if (type != video->queue.queue.type) |
231 | if ((ret = uvc_queue_buffer(&video->queue, arg)) < 0) | 226 | return -EINVAL; |
232 | return ret; | ||
233 | 227 | ||
234 | return uvc_video_pump(video); | 228 | return uvcg_video_enable(video, 0); |
229 | } | ||
235 | 230 | ||
236 | case VIDIOC_DQBUF: | 231 | static int |
237 | return uvc_dequeue_buffer(&video->queue, arg, | 232 | uvc_v4l2_subscribe_event(struct v4l2_fh *fh, |
238 | file->f_flags & O_NONBLOCK); | 233 | const struct v4l2_event_subscription *sub) |
234 | { | ||
235 | if (sub->type < UVC_EVENT_FIRST || sub->type > UVC_EVENT_LAST) | ||
236 | return -EINVAL; | ||
239 | 237 | ||
240 | case VIDIOC_STREAMON: | 238 | return v4l2_event_subscribe(fh, sub, 2, NULL); |
241 | { | 239 | } |
242 | int *type = arg; | ||
243 | 240 | ||
244 | if (*type != video->queue.queue.type) | 241 | static int |
245 | return -EINVAL; | 242 | uvc_v4l2_unsubscribe_event(struct v4l2_fh *fh, |
243 | const struct v4l2_event_subscription *sub) | ||
244 | { | ||
245 | return v4l2_event_unsubscribe(fh, sub); | ||
246 | } | ||
246 | 247 | ||
247 | /* Enable UVC video. */ | 248 | static long |
248 | ret = uvc_video_enable(video, 1); | 249 | uvc_v4l2_ioctl_default(struct file *file, void *fh, bool valid_prio, |
249 | if (ret < 0) | 250 | unsigned int cmd, void *arg) |
250 | return ret; | 251 | { |
252 | struct video_device *vdev = video_devdata(file); | ||
253 | struct uvc_device *uvc = video_get_drvdata(vdev); | ||
251 | 254 | ||
252 | /* | 255 | switch (cmd) { |
253 | * Complete the alternate setting selection setup phase now that | 256 | case UVCIOC_SEND_RESPONSE: |
254 | * userspace is ready to provide video frames. | 257 | return uvc_send_response(uvc, arg); |
255 | */ | ||
256 | uvc_function_setup_continue(uvc); | ||
257 | uvc->state = UVC_STATE_STREAMING; | ||
258 | 258 | ||
259 | return 0; | 259 | default: |
260 | return -ENOIOCTLCMD; | ||
260 | } | 261 | } |
262 | } | ||
261 | 263 | ||
262 | case VIDIOC_STREAMOFF: | 264 | const struct v4l2_ioctl_ops uvc_v4l2_ioctl_ops = { |
263 | { | 265 | .vidioc_querycap = uvc_v4l2_querycap, |
264 | int *type = arg; | 266 | .vidioc_g_fmt_vid_out = uvc_v4l2_get_format, |
265 | 267 | .vidioc_s_fmt_vid_out = uvc_v4l2_set_format, | |
266 | if (*type != video->queue.queue.type) | 268 | .vidioc_reqbufs = uvc_v4l2_reqbufs, |
267 | return -EINVAL; | 269 | .vidioc_querybuf = uvc_v4l2_querybuf, |
270 | .vidioc_qbuf = uvc_v4l2_qbuf, | ||
271 | .vidioc_dqbuf = uvc_v4l2_dqbuf, | ||
272 | .vidioc_streamon = uvc_v4l2_streamon, | ||
273 | .vidioc_streamoff = uvc_v4l2_streamoff, | ||
274 | .vidioc_subscribe_event = uvc_v4l2_subscribe_event, | ||
275 | .vidioc_unsubscribe_event = uvc_v4l2_unsubscribe_event, | ||
276 | .vidioc_default = uvc_v4l2_ioctl_default, | ||
277 | }; | ||
268 | 278 | ||
269 | return uvc_video_enable(video, 0); | 279 | /* -------------------------------------------------------------------------- |
270 | } | 280 | * V4L2 |
281 | */ | ||
271 | 282 | ||
272 | /* Events */ | 283 | static int |
273 | case VIDIOC_DQEVENT: | 284 | uvc_v4l2_open(struct file *file) |
274 | { | 285 | { |
275 | struct v4l2_event *event = arg; | 286 | struct video_device *vdev = video_devdata(file); |
276 | 287 | struct uvc_device *uvc = video_get_drvdata(vdev); | |
277 | ret = v4l2_event_dequeue(&handle->vfh, event, | 288 | struct uvc_file_handle *handle; |
278 | file->f_flags & O_NONBLOCK); | ||
279 | if (ret == 0 && event->type == UVC_EVENT_SETUP) { | ||
280 | struct uvc_event *uvc_event = (void *)&event->u.data; | ||
281 | |||
282 | /* Tell the complete callback to generate an event for | ||
283 | * the next request that will be enqueued by | ||
284 | * uvc_event_write. | ||
285 | */ | ||
286 | uvc->event_setup_out = | ||
287 | !(uvc_event->req.bRequestType & USB_DIR_IN); | ||
288 | uvc->event_length = uvc_event->req.wLength; | ||
289 | } | ||
290 | 289 | ||
291 | return ret; | 290 | handle = kzalloc(sizeof(*handle), GFP_KERNEL); |
292 | } | 291 | if (handle == NULL) |
292 | return -ENOMEM; | ||
293 | 293 | ||
294 | case VIDIOC_SUBSCRIBE_EVENT: | 294 | v4l2_fh_init(&handle->vfh, vdev); |
295 | { | 295 | v4l2_fh_add(&handle->vfh); |
296 | struct v4l2_event_subscription *sub = arg; | ||
297 | 296 | ||
298 | if (sub->type < UVC_EVENT_FIRST || sub->type > UVC_EVENT_LAST) | 297 | handle->device = &uvc->video; |
299 | return -EINVAL; | 298 | file->private_data = &handle->vfh; |
300 | 299 | ||
301 | return v4l2_event_subscribe(&handle->vfh, arg, 2, NULL); | 300 | uvc_function_connect(uvc); |
302 | } | 301 | return 0; |
302 | } | ||
303 | 303 | ||
304 | case VIDIOC_UNSUBSCRIBE_EVENT: | 304 | static int |
305 | return v4l2_event_unsubscribe(&handle->vfh, arg); | 305 | uvc_v4l2_release(struct file *file) |
306 | { | ||
307 | struct video_device *vdev = video_devdata(file); | ||
308 | struct uvc_device *uvc = video_get_drvdata(vdev); | ||
309 | struct uvc_file_handle *handle = to_uvc_file_handle(file->private_data); | ||
310 | struct uvc_video *video = handle->device; | ||
306 | 311 | ||
307 | case UVCIOC_SEND_RESPONSE: | 312 | uvc_function_disconnect(uvc); |
308 | ret = uvc_send_response(uvc, arg); | ||
309 | break; | ||
310 | 313 | ||
311 | default: | 314 | uvcg_video_enable(video, 0); |
312 | return -ENOIOCTLCMD; | 315 | uvcg_free_buffers(&video->queue); |
313 | } | ||
314 | 316 | ||
315 | return ret; | 317 | file->private_data = NULL; |
316 | } | 318 | v4l2_fh_del(&handle->vfh); |
319 | v4l2_fh_exit(&handle->vfh); | ||
320 | kfree(handle); | ||
317 | 321 | ||
318 | static long | 322 | return 0; |
319 | uvc_v4l2_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||
320 | { | ||
321 | return video_usercopy(file, cmd, arg, uvc_v4l2_do_ioctl); | ||
322 | } | 323 | } |
323 | 324 | ||
324 | static int | 325 | static int |
@@ -327,7 +328,7 @@ uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma) | |||
327 | struct video_device *vdev = video_devdata(file); | 328 | struct video_device *vdev = video_devdata(file); |
328 | struct uvc_device *uvc = video_get_drvdata(vdev); | 329 | struct uvc_device *uvc = video_get_drvdata(vdev); |
329 | 330 | ||
330 | return uvc_queue_mmap(&uvc->video.queue, vma); | 331 | return uvcg_queue_mmap(&uvc->video.queue, vma); |
331 | } | 332 | } |
332 | 333 | ||
333 | static unsigned int | 334 | static unsigned int |
@@ -336,30 +337,30 @@ uvc_v4l2_poll(struct file *file, poll_table *wait) | |||
336 | struct video_device *vdev = video_devdata(file); | 337 | struct video_device *vdev = video_devdata(file); |
337 | struct uvc_device *uvc = video_get_drvdata(vdev); | 338 | struct uvc_device *uvc = video_get_drvdata(vdev); |
338 | 339 | ||
339 | return uvc_queue_poll(&uvc->video.queue, file, wait); | 340 | return uvcg_queue_poll(&uvc->video.queue, file, wait); |
340 | } | 341 | } |
341 | 342 | ||
342 | #ifndef CONFIG_MMU | 343 | #ifndef CONFIG_MMU |
343 | static unsigned long uvc_v4l2_get_unmapped_area(struct file *file, | 344 | static unsigned long uvcg_v4l2_get_unmapped_area(struct file *file, |
344 | unsigned long addr, unsigned long len, unsigned long pgoff, | 345 | unsigned long addr, unsigned long len, unsigned long pgoff, |
345 | unsigned long flags) | 346 | unsigned long flags) |
346 | { | 347 | { |
347 | struct video_device *vdev = video_devdata(file); | 348 | struct video_device *vdev = video_devdata(file); |
348 | struct uvc_device *uvc = video_get_drvdata(vdev); | 349 | struct uvc_device *uvc = video_get_drvdata(vdev); |
349 | 350 | ||
350 | return uvc_queue_get_unmapped_area(&uvc->video.queue, pgoff); | 351 | return uvcg_queue_get_unmapped_area(&uvc->video.queue, pgoff); |
351 | } | 352 | } |
352 | #endif | 353 | #endif |
353 | 354 | ||
354 | static struct v4l2_file_operations uvc_v4l2_fops = { | 355 | struct v4l2_file_operations uvc_v4l2_fops = { |
355 | .owner = THIS_MODULE, | 356 | .owner = THIS_MODULE, |
356 | .open = uvc_v4l2_open, | 357 | .open = uvc_v4l2_open, |
357 | .release = uvc_v4l2_release, | 358 | .release = uvc_v4l2_release, |
358 | .ioctl = uvc_v4l2_ioctl, | 359 | .ioctl = video_ioctl2, |
359 | .mmap = uvc_v4l2_mmap, | 360 | .mmap = uvc_v4l2_mmap, |
360 | .poll = uvc_v4l2_poll, | 361 | .poll = uvc_v4l2_poll, |
361 | #ifndef CONFIG_MMU | 362 | #ifndef CONFIG_MMU |
362 | .get_unmapped_area = uvc_v4l2_get_unmapped_area, | 363 | .get_unmapped_area = uvcg_v4l2_get_unmapped_area, |
363 | #endif | 364 | #endif |
364 | }; | 365 | }; |
365 | 366 | ||
diff --git a/drivers/usb/gadget/function/uvc_v4l2.h b/drivers/usb/gadget/function/uvc_v4l2.h new file mode 100644 index 000000000000..2683b92fda65 --- /dev/null +++ b/drivers/usb/gadget/function/uvc_v4l2.h | |||
@@ -0,0 +1,22 @@ | |||
1 | /* | ||
2 | * uvc_v4l2.h -- USB Video Class Gadget driver | ||
3 | * | ||
4 | * Copyright (C) 2009-2010 | ||
5 | * Laurent Pinchart (laurent.pinchart@ideasonboard.com) | ||
6 | * | ||
7 | * Copyright (c) 2013 Samsung Electronics Co., Ltd. | ||
8 | * http://www.samsung.com | ||
9 | * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | */ | ||
15 | |||
16 | #ifndef __UVC_V4L2_H__ | ||
17 | #define __UVC_V4L2_H__ | ||
18 | |||
19 | extern const struct v4l2_ioctl_ops uvc_v4l2_ioctl_ops; | ||
20 | extern struct v4l2_file_operations uvc_v4l2_fops; | ||
21 | |||
22 | #endif /* __UVC_V4L2_H__ */ | ||
diff --git a/drivers/usb/gadget/function/uvc_video.c b/drivers/usb/gadget/function/uvc_video.c index a5eb9a3fbb7a..c3e1f27dbbef 100644 --- a/drivers/usb/gadget/function/uvc_video.c +++ b/drivers/usb/gadget/function/uvc_video.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/errno.h> | 15 | #include <linux/errno.h> |
16 | #include <linux/usb/ch9.h> | 16 | #include <linux/usb/ch9.h> |
17 | #include <linux/usb/gadget.h> | 17 | #include <linux/usb/gadget.h> |
18 | #include <linux/usb/video.h> | ||
18 | 19 | ||
19 | #include <media/v4l2-dev.h> | 20 | #include <media/v4l2-dev.h> |
20 | 21 | ||
@@ -85,7 +86,7 @@ uvc_video_encode_bulk(struct usb_request *req, struct uvc_video *video, | |||
85 | if (buf->bytesused == video->queue.buf_used) { | 86 | if (buf->bytesused == video->queue.buf_used) { |
86 | video->queue.buf_used = 0; | 87 | video->queue.buf_used = 0; |
87 | buf->state = UVC_BUF_STATE_DONE; | 88 | buf->state = UVC_BUF_STATE_DONE; |
88 | uvc_queue_next_buffer(&video->queue, buf); | 89 | uvcg_queue_next_buffer(&video->queue, buf); |
89 | video->fid ^= UVC_STREAM_FID; | 90 | video->fid ^= UVC_STREAM_FID; |
90 | 91 | ||
91 | video->payload_size = 0; | 92 | video->payload_size = 0; |
@@ -118,7 +119,7 @@ uvc_video_encode_isoc(struct usb_request *req, struct uvc_video *video, | |||
118 | if (buf->bytesused == video->queue.buf_used) { | 119 | if (buf->bytesused == video->queue.buf_used) { |
119 | video->queue.buf_used = 0; | 120 | video->queue.buf_used = 0; |
120 | buf->state = UVC_BUF_STATE_DONE; | 121 | buf->state = UVC_BUF_STATE_DONE; |
121 | uvc_queue_next_buffer(&video->queue, buf); | 122 | uvcg_queue_next_buffer(&video->queue, buf); |
122 | video->fid ^= UVC_STREAM_FID; | 123 | video->fid ^= UVC_STREAM_FID; |
123 | } | 124 | } |
124 | } | 125 | } |
@@ -171,19 +172,19 @@ uvc_video_complete(struct usb_ep *ep, struct usb_request *req) | |||
171 | break; | 172 | break; |
172 | 173 | ||
173 | case -ESHUTDOWN: /* disconnect from host. */ | 174 | case -ESHUTDOWN: /* disconnect from host. */ |
174 | printk(KERN_INFO "VS request cancelled.\n"); | 175 | printk(KERN_DEBUG "VS request cancelled.\n"); |
175 | uvc_queue_cancel(queue, 1); | 176 | uvcg_queue_cancel(queue, 1); |
176 | goto requeue; | 177 | goto requeue; |
177 | 178 | ||
178 | default: | 179 | default: |
179 | printk(KERN_INFO "VS request completed with status %d.\n", | 180 | printk(KERN_INFO "VS request completed with status %d.\n", |
180 | req->status); | 181 | req->status); |
181 | uvc_queue_cancel(queue, 0); | 182 | uvcg_queue_cancel(queue, 0); |
182 | goto requeue; | 183 | goto requeue; |
183 | } | 184 | } |
184 | 185 | ||
185 | spin_lock_irqsave(&video->queue.irqlock, flags); | 186 | spin_lock_irqsave(&video->queue.irqlock, flags); |
186 | buf = uvc_queue_head(&video->queue); | 187 | buf = uvcg_queue_head(&video->queue); |
187 | if (buf == NULL) { | 188 | if (buf == NULL) { |
188 | spin_unlock_irqrestore(&video->queue.irqlock, flags); | 189 | spin_unlock_irqrestore(&video->queue.irqlock, flags); |
189 | goto requeue; | 190 | goto requeue; |
@@ -195,7 +196,7 @@ uvc_video_complete(struct usb_ep *ep, struct usb_request *req) | |||
195 | printk(KERN_INFO "Failed to queue request (%d).\n", ret); | 196 | printk(KERN_INFO "Failed to queue request (%d).\n", ret); |
196 | usb_ep_set_halt(ep); | 197 | usb_ep_set_halt(ep); |
197 | spin_unlock_irqrestore(&video->queue.irqlock, flags); | 198 | spin_unlock_irqrestore(&video->queue.irqlock, flags); |
198 | uvc_queue_cancel(queue, 0); | 199 | uvcg_queue_cancel(queue, 0); |
199 | goto requeue; | 200 | goto requeue; |
200 | } | 201 | } |
201 | spin_unlock_irqrestore(&video->queue.irqlock, flags); | 202 | spin_unlock_irqrestore(&video->queue.irqlock, flags); |
@@ -274,13 +275,12 @@ error: | |||
274 | */ | 275 | */ |
275 | 276 | ||
276 | /* | 277 | /* |
277 | * uvc_video_pump - Pump video data into the USB requests | 278 | * uvcg_video_pump - Pump video data into the USB requests |
278 | * | 279 | * |
279 | * This function fills the available USB requests (listed in req_free) with | 280 | * This function fills the available USB requests (listed in req_free) with |
280 | * video data from the queued buffers. | 281 | * video data from the queued buffers. |
281 | */ | 282 | */ |
282 | static int | 283 | int uvcg_video_pump(struct uvc_video *video) |
283 | uvc_video_pump(struct uvc_video *video) | ||
284 | { | 284 | { |
285 | struct uvc_video_queue *queue = &video->queue; | 285 | struct uvc_video_queue *queue = &video->queue; |
286 | struct usb_request *req; | 286 | struct usb_request *req; |
@@ -288,7 +288,7 @@ uvc_video_pump(struct uvc_video *video) | |||
288 | unsigned long flags; | 288 | unsigned long flags; |
289 | int ret; | 289 | int ret; |
290 | 290 | ||
291 | /* FIXME TODO Race between uvc_video_pump and requests completion | 291 | /* FIXME TODO Race between uvcg_video_pump and requests completion |
292 | * handler ??? | 292 | * handler ??? |
293 | */ | 293 | */ |
294 | 294 | ||
@@ -309,10 +309,10 @@ uvc_video_pump(struct uvc_video *video) | |||
309 | /* Retrieve the first available video buffer and fill the | 309 | /* Retrieve the first available video buffer and fill the |
310 | * request, protected by the video queue irqlock. | 310 | * request, protected by the video queue irqlock. |
311 | */ | 311 | */ |
312 | spin_lock_irqsave(&video->queue.irqlock, flags); | 312 | spin_lock_irqsave(&queue->irqlock, flags); |
313 | buf = uvc_queue_head(&video->queue); | 313 | buf = uvcg_queue_head(queue); |
314 | if (buf == NULL) { | 314 | if (buf == NULL) { |
315 | spin_unlock_irqrestore(&video->queue.irqlock, flags); | 315 | spin_unlock_irqrestore(&queue->irqlock, flags); |
316 | break; | 316 | break; |
317 | } | 317 | } |
318 | 318 | ||
@@ -323,11 +323,11 @@ uvc_video_pump(struct uvc_video *video) | |||
323 | if (ret < 0) { | 323 | if (ret < 0) { |
324 | printk(KERN_INFO "Failed to queue request (%d)\n", ret); | 324 | printk(KERN_INFO "Failed to queue request (%d)\n", ret); |
325 | usb_ep_set_halt(video->ep); | 325 | usb_ep_set_halt(video->ep); |
326 | spin_unlock_irqrestore(&video->queue.irqlock, flags); | 326 | spin_unlock_irqrestore(&queue->irqlock, flags); |
327 | uvc_queue_cancel(queue, 0); | 327 | uvcg_queue_cancel(queue, 0); |
328 | break; | 328 | break; |
329 | } | 329 | } |
330 | spin_unlock_irqrestore(&video->queue.irqlock, flags); | 330 | spin_unlock_irqrestore(&queue->irqlock, flags); |
331 | } | 331 | } |
332 | 332 | ||
333 | spin_lock_irqsave(&video->req_lock, flags); | 333 | spin_lock_irqsave(&video->req_lock, flags); |
@@ -339,8 +339,7 @@ uvc_video_pump(struct uvc_video *video) | |||
339 | /* | 339 | /* |
340 | * Enable or disable the video stream. | 340 | * Enable or disable the video stream. |
341 | */ | 341 | */ |
342 | static int | 342 | int uvcg_video_enable(struct uvc_video *video, int enable) |
343 | uvc_video_enable(struct uvc_video *video, int enable) | ||
344 | { | 343 | { |
345 | unsigned int i; | 344 | unsigned int i; |
346 | int ret; | 345 | int ret; |
@@ -356,11 +355,11 @@ uvc_video_enable(struct uvc_video *video, int enable) | |||
356 | usb_ep_dequeue(video->ep, video->req[i]); | 355 | usb_ep_dequeue(video->ep, video->req[i]); |
357 | 356 | ||
358 | uvc_video_free_requests(video); | 357 | uvc_video_free_requests(video); |
359 | uvc_queue_enable(&video->queue, 0); | 358 | uvcg_queue_enable(&video->queue, 0); |
360 | return 0; | 359 | return 0; |
361 | } | 360 | } |
362 | 361 | ||
363 | if ((ret = uvc_queue_enable(&video->queue, 1)) < 0) | 362 | if ((ret = uvcg_queue_enable(&video->queue, 1)) < 0) |
364 | return ret; | 363 | return ret; |
365 | 364 | ||
366 | if ((ret = uvc_video_alloc_requests(video)) < 0) | 365 | if ((ret = uvc_video_alloc_requests(video)) < 0) |
@@ -372,14 +371,13 @@ uvc_video_enable(struct uvc_video *video, int enable) | |||
372 | } else | 371 | } else |
373 | video->encode = uvc_video_encode_isoc; | 372 | video->encode = uvc_video_encode_isoc; |
374 | 373 | ||
375 | return uvc_video_pump(video); | 374 | return uvcg_video_pump(video); |
376 | } | 375 | } |
377 | 376 | ||
378 | /* | 377 | /* |
379 | * Initialize the UVC video stream. | 378 | * Initialize the UVC video stream. |
380 | */ | 379 | */ |
381 | static int | 380 | int uvcg_video_init(struct uvc_video *video) |
382 | uvc_video_init(struct uvc_video *video) | ||
383 | { | 381 | { |
384 | INIT_LIST_HEAD(&video->req_free); | 382 | INIT_LIST_HEAD(&video->req_free); |
385 | spin_lock_init(&video->req_lock); | 383 | spin_lock_init(&video->req_lock); |
@@ -391,7 +389,7 @@ uvc_video_init(struct uvc_video *video) | |||
391 | video->imagesize = 320 * 240 * 2; | 389 | video->imagesize = 320 * 240 * 2; |
392 | 390 | ||
393 | /* Initialize the video buffers queue. */ | 391 | /* Initialize the video buffers queue. */ |
394 | uvc_queue_init(&video->queue, V4L2_BUF_TYPE_VIDEO_OUTPUT); | 392 | uvcg_queue_init(&video->queue, V4L2_BUF_TYPE_VIDEO_OUTPUT); |
395 | return 0; | 393 | return 0; |
396 | } | 394 | } |
397 | 395 | ||
diff --git a/drivers/usb/gadget/function/uvc_video.h b/drivers/usb/gadget/function/uvc_video.h new file mode 100644 index 000000000000..ef00f06fa00b --- /dev/null +++ b/drivers/usb/gadget/function/uvc_video.h | |||
@@ -0,0 +1,24 @@ | |||
1 | /* | ||
2 | * uvc_video.h -- USB Video Class Gadget driver | ||
3 | * | ||
4 | * Copyright (C) 2009-2010 | ||
5 | * Laurent Pinchart (laurent.pinchart@ideasonboard.com) | ||
6 | * | ||
7 | * Copyright (c) 2013 Samsung Electronics Co., Ltd. | ||
8 | * http://www.samsung.com | ||
9 | * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | */ | ||
15 | #ifndef __UVC_VIDEO_H__ | ||
16 | #define __UVC_VIDEO_H__ | ||
17 | |||
18 | int uvcg_video_pump(struct uvc_video *video); | ||
19 | |||
20 | int uvcg_video_enable(struct uvc_video *video, int enable); | ||
21 | |||
22 | int uvcg_video_init(struct uvc_video *video); | ||
23 | |||
24 | #endif /* __UVC_VIDEO_H__ */ | ||