usb: gadget: f_uvc: use usb_gstrings_attach
Attach strings to gadget with usb_strings_attach. It is required for correct instantiation of functions more than once: instead of modifying the local uvc_en_us_strings a function instance specific copy is created with usb_gstrings_attach. Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@samsung.com> Tested-by: Michael Grzeschik <m.grzeschik@pengutronix.de> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
This commit is contained in:
parent
cb47d889e6
commit
13443799b5
|
@ -562,6 +562,7 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
|
||||||
{
|
{
|
||||||
struct usb_composite_dev *cdev = c->cdev;
|
struct usb_composite_dev *cdev = c->cdev;
|
||||||
struct uvc_device *uvc = to_uvc(f);
|
struct uvc_device *uvc = to_uvc(f);
|
||||||
|
struct usb_string *us;
|
||||||
unsigned int max_packet_mult;
|
unsigned int max_packet_mult;
|
||||||
unsigned int max_packet_size;
|
unsigned int max_packet_size;
|
||||||
struct usb_ep *ep;
|
struct usb_ep *ep;
|
||||||
|
@ -637,22 +638,17 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
|
||||||
uvc_hs_streaming_ep.bEndpointAddress = uvc->video.ep->address;
|
uvc_hs_streaming_ep.bEndpointAddress = uvc->video.ep->address;
|
||||||
uvc_ss_streaming_ep.bEndpointAddress = uvc->video.ep->address;
|
uvc_ss_streaming_ep.bEndpointAddress = uvc->video.ep->address;
|
||||||
|
|
||||||
/* String descriptors are global, we only need to allocate string IDs
|
us = usb_gstrings_attach(cdev, uvc_function_strings,
|
||||||
* for the first UVC function. UVC functions beyond the first (if any)
|
ARRAY_SIZE(uvc_en_us_strings));
|
||||||
* will reuse the same IDs.
|
if (IS_ERR(us)) {
|
||||||
*/
|
ret = PTR_ERR(us);
|
||||||
if (uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id == 0) {
|
goto error;
|
||||||
ret = usb_string_ids_tab(c->cdev, uvc_en_us_strings);
|
|
||||||
if (ret)
|
|
||||||
goto error;
|
|
||||||
uvc_iad.iFunction =
|
|
||||||
uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id;
|
|
||||||
uvc_control_intf.iInterface =
|
|
||||||
uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id;
|
|
||||||
ret = uvc_en_us_strings[UVC_STRING_STREAMING_IDX].id;
|
|
||||||
uvc_streaming_intf_alt0.iInterface = ret;
|
|
||||||
uvc_streaming_intf_alt1.iInterface = ret;
|
|
||||||
}
|
}
|
||||||
|
uvc_iad.iFunction = us[UVC_STRING_CONTROL_IDX].id;
|
||||||
|
uvc_control_intf.iInterface = us[UVC_STRING_CONTROL_IDX].id;
|
||||||
|
ret = us[UVC_STRING_STREAMING_IDX].id;
|
||||||
|
uvc_streaming_intf_alt0.iInterface = ret;
|
||||||
|
uvc_streaming_intf_alt1.iInterface = ret;
|
||||||
|
|
||||||
/* Allocate interface IDs. */
|
/* Allocate interface IDs. */
|
||||||
if ((ret = usb_interface_id(c, f)) < 0)
|
if ((ret = usb_interface_id(c, f)) < 0)
|
||||||
|
@ -771,7 +767,6 @@ static void uvc_unbind(struct usb_configuration *c, struct usb_function *f)
|
||||||
uvc->control_ep->driver_data = NULL;
|
uvc->control_ep->driver_data = NULL;
|
||||||
uvc->video.ep->driver_data = NULL;
|
uvc->video.ep->driver_data = NULL;
|
||||||
|
|
||||||
uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id = 0;
|
|
||||||
usb_ep_free_request(cdev->gadget->ep0, uvc->control_req);
|
usb_ep_free_request(cdev->gadget->ep0, uvc->control_req);
|
||||||
kfree(uvc->control_buf);
|
kfree(uvc->control_buf);
|
||||||
|
|
||||||
|
@ -798,7 +793,6 @@ struct usb_function *uvc_alloc(struct usb_function_instance *fi)
|
||||||
|
|
||||||
/* Register the function. */
|
/* Register the function. */
|
||||||
uvc->func.name = "uvc";
|
uvc->func.name = "uvc";
|
||||||
uvc->func.strings = uvc_function_strings;
|
|
||||||
uvc->func.bind = uvc_function_bind;
|
uvc->func.bind = uvc_function_bind;
|
||||||
uvc->func.unbind = uvc_unbind;
|
uvc->func.unbind = uvc_unbind;
|
||||||
uvc->func.get_alt = uvc_function_get_alt;
|
uvc->func.get_alt = uvc_function_get_alt;
|
||||||
|
|
Loading…
Reference in New Issue