diff options
Diffstat (limited to 'drivers/usb/gadget/f_uvc.c')
-rw-r--r-- | drivers/usb/gadget/f_uvc.c | 138 |
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 | ||
742 | error: | 720 | error: |
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 | } |