aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget/f_uvc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/gadget/f_uvc.c')
-rw-r--r--drivers/usb/gadget/f_uvc.c138
1 files changed, 60 insertions, 78 deletions
diff --git a/drivers/usb/gadget/f_uvc.c b/drivers/usb/gadget/f_uvc.c
index 2a8bf0655c60..5b629876941b 100644
--- a/drivers/usb/gadget/f_uvc.c
+++ b/drivers/usb/gadget/f_uvc.c
@@ -417,7 +417,6 @@ uvc_register_video(struct uvc_device *uvc)
417 return -ENOMEM; 417 return -ENOMEM;
418 418
419 video->parent = &cdev->gadget->dev; 419 video->parent = &cdev->gadget->dev;
420 video->minor = -1;
421 video->fops = &uvc_v4l2_fops; 420 video->fops = &uvc_v4l2_fops;
422 video->release = video_device_release; 421 video->release = video_device_release;
423 strncpy(video->name, cdev->gadget->name, sizeof(video->name)); 422 strncpy(video->name, cdev->gadget->name, sizeof(video->name));
@@ -577,27 +576,15 @@ uvc_function_unbind(struct usb_configuration *c, struct usb_function *f)
577 576
578 INFO(cdev, "uvc_function_unbind\n"); 577 INFO(cdev, "uvc_function_unbind\n");
579 578
580 if (uvc->vdev) { 579 video_unregister_device(uvc->vdev);
581 if (uvc->vdev->minor == -1) 580 uvc->control_ep->driver_data = NULL;
582 video_device_release(uvc->vdev); 581 uvc->video.ep->driver_data = NULL;
583 else
584 video_unregister_device(uvc->vdev);
585 uvc->vdev = NULL;
586 }
587 582
588 if (uvc->control_ep) 583 uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id = 0;
589 uvc->control_ep->driver_data = NULL; 584 usb_ep_free_request(cdev->gadget->ep0, uvc->control_req);
590 if (uvc->video.ep) 585 kfree(uvc->control_buf);
591 uvc->video.ep->driver_data = NULL;
592
593 if (uvc->control_req) {
594 usb_ep_free_request(cdev->gadget->ep0, uvc->control_req);
595 kfree(uvc->control_buf);
596 }
597 586
598 kfree(f->descriptors); 587 usb_free_all_descriptors(f);
599 kfree(f->hs_descriptors);
600 kfree(f->ss_descriptors);
601 588
602 kfree(uvc); 589 kfree(uvc);
603} 590}
@@ -663,49 +650,40 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
663 /* sanity check the streaming endpoint module parameters */ 650 /* sanity check the streaming endpoint module parameters */
664 if (streaming_maxpacket > 1024) 651 if (streaming_maxpacket > 1024)
665 streaming_maxpacket = 1024; 652 streaming_maxpacket = 1024;
653 /*
654 * Fill in the HS descriptors from the module parameters for the Video
655 * Streaming endpoint.
656 * NOTE: We assume that the user knows what they are doing and won't
657 * give parameters that their UDC doesn't support.
658 */
659 uvc_hs_streaming_ep.wMaxPacketSize = streaming_maxpacket;
660 uvc_hs_streaming_ep.wMaxPacketSize |= streaming_mult << 11;
661 uvc_hs_streaming_ep.bInterval = streaming_interval;
662 uvc_hs_streaming_ep.bEndpointAddress =
663 uvc_fs_streaming_ep.bEndpointAddress;
666 664
667 /* Copy descriptors for FS. */ 665 /*
668 f->descriptors = uvc_copy_descriptors(uvc, USB_SPEED_FULL); 666 * Fill in the SS descriptors from the module parameters for the Video
669 667 * Streaming endpoint.
670 /* support high speed hardware */ 668 * NOTE: We assume that the user knows what they are doing and won't
671 if (gadget_is_dualspeed(cdev->gadget)) { 669 * give parameters that their UDC doesn't support.
672 /* 670 */
673 * Fill in the HS descriptors from the module parameters for the 671 uvc_ss_streaming_ep.wMaxPacketSize = streaming_maxpacket;
674 * Video Streaming endpoint. 672 uvc_ss_streaming_ep.bInterval = streaming_interval;
675 * NOTE: We assume that the user knows what they are doing and 673 uvc_ss_streaming_comp.bmAttributes = streaming_mult;
676 * won't give parameters that their UDC doesn't support. 674 uvc_ss_streaming_comp.bMaxBurst = streaming_maxburst;
677 */ 675 uvc_ss_streaming_comp.wBytesPerInterval =
678 uvc_hs_streaming_ep.wMaxPacketSize = streaming_maxpacket; 676 streaming_maxpacket * (streaming_mult + 1) *
679 uvc_hs_streaming_ep.wMaxPacketSize |= streaming_mult << 11; 677 (streaming_maxburst + 1);
680 uvc_hs_streaming_ep.bInterval = streaming_interval; 678 uvc_ss_streaming_ep.bEndpointAddress =
681 uvc_hs_streaming_ep.bEndpointAddress = 679 uvc_fs_streaming_ep.bEndpointAddress;
682 uvc_fs_streaming_ep.bEndpointAddress;
683
684 /* Copy descriptors. */
685 f->hs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_HIGH);
686 }
687 680
688 /* support super speed hardware */ 681 /* Copy descriptors */
689 if (gadget_is_superspeed(c->cdev->gadget)) { 682 f->fs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_FULL);
690 /* 683 if (gadget_is_dualspeed(cdev->gadget))
691 * Fill in the SS descriptors from the module parameters for the 684 f->hs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_HIGH);
692 * Video Streaming endpoint. 685 if (gadget_is_superspeed(c->cdev->gadget))
693 * NOTE: We assume that the user knows what they are doing and
694 * won't give parameters that their UDC doesn't support.
695 */
696 uvc_ss_streaming_ep.wMaxPacketSize = streaming_maxpacket;
697 uvc_ss_streaming_ep.bInterval = streaming_interval;
698 uvc_ss_streaming_comp.bmAttributes = streaming_mult;
699 uvc_ss_streaming_comp.bMaxBurst = streaming_maxburst;
700 uvc_ss_streaming_comp.wBytesPerInterval =
701 streaming_maxpacket * (streaming_mult + 1) *
702 (streaming_maxburst + 1);
703 uvc_ss_streaming_ep.bEndpointAddress =
704 uvc_fs_streaming_ep.bEndpointAddress;
705
706 /* Copy descriptors. */
707 f->ss_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_SUPER); 686 f->ss_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_SUPER);
708 }
709 687
710 /* Preallocate control endpoint request. */ 688 /* Preallocate control endpoint request. */
711 uvc->control_req = usb_ep_alloc_request(cdev->gadget->ep0, GFP_KERNEL); 689 uvc->control_req = usb_ep_alloc_request(cdev->gadget->ep0, GFP_KERNEL);
@@ -740,7 +718,20 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
740 return 0; 718 return 0;
741 719
742error: 720error:
743 uvc_function_unbind(c, f); 721 if (uvc->vdev)
722 video_device_release(uvc->vdev);
723
724 if (uvc->control_ep)
725 uvc->control_ep->driver_data = NULL;
726 if (uvc->video.ep)
727 uvc->video.ep->driver_data = NULL;
728
729 if (uvc->control_req) {
730 usb_ep_free_request(cdev->gadget->ep0, uvc->control_req);
731 kfree(uvc->control_buf);
732 }
733
734 usb_free_all_descriptors(f);
744 return ret; 735 return ret;
745} 736}
746 737
@@ -808,25 +799,16 @@ uvc_bind_config(struct usb_configuration *c,
808 uvc->desc.hs_streaming = hs_streaming; 799 uvc->desc.hs_streaming = hs_streaming;
809 uvc->desc.ss_streaming = ss_streaming; 800 uvc->desc.ss_streaming = ss_streaming;
810 801
811 /* maybe allocate device-global string IDs, and patch descriptors */ 802 /* Allocate string descriptor numbers. */
812 if (uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id == 0) { 803 if (uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id == 0) {
813 /* Allocate string descriptor numbers. */ 804 ret = usb_string_ids_tab(c->cdev, uvc_en_us_strings);
814 ret = usb_string_id(c->cdev); 805 if (ret)
815 if (ret < 0)
816 goto error;
817 uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id = ret;
818 uvc_iad.iFunction = ret;
819
820 ret = usb_string_id(c->cdev);
821 if (ret < 0)
822 goto error;
823 uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id = ret;
824 uvc_control_intf.iInterface = ret;
825
826 ret = usb_string_id(c->cdev);
827 if (ret < 0)
828 goto error; 806 goto error;
829 uvc_en_us_strings[UVC_STRING_STREAMING_IDX].id = ret; 807 uvc_iad.iFunction =
808 uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id;
809 uvc_control_intf.iInterface =
810 uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id;
811 ret = uvc_en_us_strings[UVC_STRING_STREAMING_IDX].id;
830 uvc_streaming_intf_alt0.iInterface = ret; 812 uvc_streaming_intf_alt0.iInterface = ret;
831 uvc_streaming_intf_alt1.iInterface = ret; 813 uvc_streaming_intf_alt1.iInterface = ret;
832 } 814 }