| 1 | |
| 2 | |
| 3 | * uvc_gadget.c -- USB Video Class Gadget driver
|
| 4 | *
|
| 5 | * Copyright (C) 2009-2010
|
| 6 | * Laurent Pinchart ([email protected])
|
| 7 |
|
| 8 |
|
| 9 | #include <linux/device.h>
|
| 10 | #include <linux/errno.h>
|
| 11 | #include <linux/fs.h>
|
| 12 | #include <linux/kernel.h>
|
| 13 | #include <linux/list.h>
|
| 14 | #include <linux/module.h>
|
| 15 | #include <linux/mutex.h>
|
| 16 | #include <linux/string.h>
|
| 17 | #include <linux/usb/ch9.h>
|
| 18 | #include <linux/usb/gadget.h>
|
| 19 | #include <linux/usb/g_uvc.h>
|
| 20 | #include <linux/usb/video.h>
|
| 21 | #include <linux/vmalloc.h>
|
| 22 | #include <linux/wait.h>
|
| 23 |
|
| 24 | #include <media/v4l2-dev.h>
|
| 25 | #include <media/v4l2-event.h>
|
| 26 |
|
| 27 | #include "uvc.h"
|
| 28 | #include "uvc_configfs.h"
|
| 29 | #include "uvc_v4l2.h"
|
| 30 | #include "uvc_video.h"
|
| 31 |
|
| 32 | unsigned int uvc_gadget_trace_param;
|
| 33 | module_param_named(trace, uvc_gadget_trace_param, uint, 0644);
|
| 34 | MODULE_PARM_DESC(trace, "Trace level bitmask");
|
| 35 |
|
| 36 | |
| 37 | * Function descriptors
|
| 38 |
|
| 39 |
|
| 40 |
|
| 41 |
|
| 42 | static struct usb_string uvc_en_us_strings[] = {
|
| 43 |
|
| 44 | [UVC_STRING_STREAMING_IDX].s = "Video Streaming",
|
| 45 | { }
|
| 46 | };
|
| 47 |
|
| 48 | static struct usb_gadget_strings uvc_stringtab = {
|
| 49 | .language = 0x0409,
|
| 50 | .strings = uvc_en_us_strings,
|
| 51 | };
|
| 52 |
|
| 53 | static struct usb_gadget_strings *uvc_function_strings[] = {
|
| 54 | &uvc_stringtab,
|
| 55 | NULL,
|
| 56 | };
|
| 57 |
|
| 58 | #define UVC_INTF_VIDEO_CONTROL 0
|
| 59 | #define UVC_INTF_VIDEO_STREAMING 1
|
| 60 |
|
| 61 | #define UVC_STATUS_MAX_PACKET_SIZE 16
|
| 62 |
|
| 63 | static struct usb_interface_assoc_descriptor uvc_iad = {
|
| 64 | .bLength = sizeof(uvc_iad),
|
| 65 | .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION,
|
| 66 | .bFirstInterface = 0,
|
| 67 | .bInterfaceCount = 2,
|
| 68 | .bFunctionClass = USB_CLASS_VIDEO,
|
| 69 | .bFunctionSubClass = UVC_SC_VIDEO_INTERFACE_COLLECTION,
|
| 70 | .bFunctionProtocol = 0x00,
|
| 71 | .iFunction = 0,
|
| 72 | };
|
| 73 |
|
| 74 | static struct usb_interface_descriptor uvc_control_intf = {
|
| 75 | .bLength = USB_DT_INTERFACE_SIZE,
|
| 76 | .bDescriptorType = USB_DT_INTERFACE,
|
| 77 | .bInterfaceNumber = UVC_INTF_VIDEO_CONTROL,
|
| 78 | .bAlternateSetting = 0,
|
| 79 | .bNumEndpoints = 0,
|
| 80 | .bInterfaceClass = USB_CLASS_VIDEO,
|
| 81 | .bInterfaceSubClass = UVC_SC_VIDEOCONTROL,
|
| 82 | .bInterfaceProtocol = 0x00,
|
| 83 | .iInterface = 0,
|
| 84 | };
|
| 85 |
|
| 86 | static struct usb_endpoint_descriptor uvc_interrupt_ep = {
|
| 87 | .bLength = USB_DT_ENDPOINT_SIZE,
|
| 88 | .bDescriptorType = USB_DT_ENDPOINT,
|
| 89 | .bEndpointAddress = USB_DIR_IN,
|
| 90 | .bmAttributes = USB_ENDPOINT_XFER_INT,
|
| 91 | .wMaxPacketSize = cpu_to_le16(UVC_STATUS_MAX_PACKET_SIZE),
|
| 92 | .bInterval = 8,
|
| 93 | };
|
| 94 |
|
| 95 | static struct usb_ss_ep_comp_descriptor uvc_ss_interrupt_comp = {
|
| 96 | .bLength = sizeof(uvc_ss_interrupt_comp),
|
| 97 | .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
|
| 98 |
|
| 99 | .bMaxBurst = 0,
|
| 100 | .bmAttributes = 0,
|
| 101 | .wBytesPerInterval = cpu_to_le16(UVC_STATUS_MAX_PACKET_SIZE),
|
| 102 | };
|
| 103 |
|
| 104 | static struct uvc_control_endpoint_descriptor uvc_interrupt_cs_ep = {
|
| 105 | .bLength = UVC_DT_CONTROL_ENDPOINT_SIZE,
|
| 106 | .bDescriptorType = USB_DT_CS_ENDPOINT,
|
| 107 | .bDescriptorSubType = UVC_EP_INTERRUPT,
|
| 108 | .wMaxTransferSize = cpu_to_le16(UVC_STATUS_MAX_PACKET_SIZE),
|
| 109 | };
|
| 110 |
|
| 111 | static struct usb_interface_descriptor uvc_streaming_intf_alt0 = {
|
| 112 | .bLength = USB_DT_INTERFACE_SIZE,
|
| 113 | .bDescriptorType = USB_DT_INTERFACE,
|
| 114 | .bInterfaceNumber = UVC_INTF_VIDEO_STREAMING,
|
| 115 | .bAlternateSetting = 0,
|
| 116 | .bNumEndpoints = 0,
|
| 117 | .bInterfaceClass = USB_CLASS_VIDEO,
|
| 118 | .bInterfaceSubClass = UVC_SC_VIDEOSTREAMING,
|
| 119 | .bInterfaceProtocol = 0x00,
|
| 120 | .iInterface = 0,
|
| 121 | };
|
| 122 |
|
| 123 | static struct usb_interface_descriptor uvc_streaming_intf_alt1 = {
|
| 124 | .bLength = USB_DT_INTERFACE_SIZE,
|
| 125 | .bDescriptorType = USB_DT_INTERFACE,
|
| 126 | .bInterfaceNumber = UVC_INTF_VIDEO_STREAMING,
|
| 127 | .bAlternateSetting = 1,
|
| 128 | .bNumEndpoints = 1,
|
| 129 | .bInterfaceClass = USB_CLASS_VIDEO,
|
| 130 | .bInterfaceSubClass = UVC_SC_VIDEOSTREAMING,
|
| 131 | .bInterfaceProtocol = 0x00,
|
| 132 | .iInterface = 0,
|
| 133 | };
|
| 134 |
|
| 135 | static struct usb_endpoint_descriptor uvc_fs_streaming_ep = {
|
| 136 | .bLength = USB_DT_ENDPOINT_SIZE,
|
| 137 | .bDescriptorType = USB_DT_ENDPOINT,
|
| 138 | .bEndpointAddress = USB_DIR_IN,
|
| 139 | .bmAttributes = USB_ENDPOINT_SYNC_ASYNC
|
| 140 | | USB_ENDPOINT_XFER_ISOC,
|
| 141 | |
| 142 | * The wMaxPacketSize and bInterval values will be initialized from
|
| 143 | * module parameters.
|
| 144 |
|
| 145 | };
|
| 146 |
|
| 147 | static struct usb_endpoint_descriptor uvc_hs_streaming_ep = {
|
| 148 | .bLength = USB_DT_ENDPOINT_SIZE,
|
| 149 | .bDescriptorType = USB_DT_ENDPOINT,
|
| 150 | .bEndpointAddress = USB_DIR_IN,
|
| 151 | .bmAttributes = USB_ENDPOINT_SYNC_ASYNC
|
| 152 | | USB_ENDPOINT_XFER_ISOC,
|
| 153 | |
| 154 | * The wMaxPacketSize and bInterval values will be initialized from
|
| 155 | * module parameters.
|
| 156 |
|
| 157 | };
|
| 158 |
|
| 159 | static struct usb_endpoint_descriptor uvc_ss_streaming_ep = {
|
| 160 | .bLength = USB_DT_ENDPOINT_SIZE,
|
| 161 | .bDescriptorType = USB_DT_ENDPOINT,
|
| 162 |
|
| 163 | .bEndpointAddress = USB_DIR_IN,
|
| 164 | .bmAttributes = USB_ENDPOINT_SYNC_ASYNC
|
| 165 | | USB_ENDPOINT_XFER_ISOC,
|
| 166 | |
| 167 | * The wMaxPacketSize and bInterval values will be initialized from
|
| 168 | * module parameters.
|
| 169 |
|
| 170 | };
|
| 171 |
|
| 172 | static struct usb_ss_ep_comp_descriptor uvc_ss_streaming_comp = {
|
| 173 | .bLength = sizeof(uvc_ss_streaming_comp),
|
| 174 | .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
|
| 175 | |
| 176 | * The bMaxBurst, bmAttributes and wBytesPerInterval values will be
|
| 177 | * initialized from module parameters.
|
| 178 |
|
| 179 | };
|
| 180 |
|
| 181 | static const struct usb_descriptor_header * const uvc_fs_streaming[] = {
|
| 182 | (struct usb_descriptor_header *) &uvc_streaming_intf_alt1,
|
| 183 | (struct usb_descriptor_header *) &uvc_fs_streaming_ep,
|
| 184 | NULL,
|
| 185 | };
|
| 186 |
|
| 187 | static const struct usb_descriptor_header * const uvc_hs_streaming[] = {
|
| 188 | (struct usb_descriptor_header *) &uvc_streaming_intf_alt1,
|
| 189 | (struct usb_descriptor_header *) &uvc_hs_streaming_ep,
|
| 190 | NULL,
|
| 191 | };
|
| 192 |
|
| 193 | static const struct usb_descriptor_header * const uvc_ss_streaming[] = {
|
| 194 | (struct usb_descriptor_header *) &uvc_streaming_intf_alt1,
|
| 195 | (struct usb_descriptor_header *) &uvc_ss_streaming_ep,
|
| 196 | (struct usb_descriptor_header *) &uvc_ss_streaming_comp,
|
| 197 | NULL,
|
| 198 | };
|
| 199 |
|
| 200 | |
| 201 | * Control requests
|
| 202 |
|
| 203 |
|
| 204 | static void
|
| 205 | uvc_function_ep0_complete(struct usb_ep *ep, struct usb_request *req)
|
| 206 | {
|
| 207 | struct uvc_device *uvc = req->context;
|
| 208 | struct v4l2_event v4l2_event;
|
| 209 | struct uvc_event *uvc_event = (void *)&v4l2_event.u.data;
|
| 210 |
|
| 211 | if (uvc->event_setup_out) {
|
| 212 | uvc->event_setup_out = 0;
|
| 213 |
|
| 214 | memset(&v4l2_event, 0, sizeof(v4l2_event));
|
| 215 | v4l2_event.type = UVC_EVENT_DATA;
|
| 216 | uvc_event->data.length = min_t(unsigned int, req->actual,
|
| 217 | sizeof(uvc_event->data.data));
|
| 218 | memcpy(&uvc_event->data.data, req->buf, uvc_event->data.length);
|
| 219 | v4l2_event_queue(&uvc->vdev, &v4l2_event);
|
| 220 | }
|
| 221 | }
|
| 222 |
|
| 223 | static int
|
| 224 | uvc_function_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
|
| 225 | {
|
| 226 | struct uvc_device *uvc = to_uvc(f);
|
| 227 | struct v4l2_event v4l2_event;
|
| 228 | struct uvc_event *uvc_event = (void *)&v4l2_event.u.data;
|
| 229 | unsigned int interface = le16_to_cpu(ctrl->wIndex) & 0xff;
|
| 230 | struct usb_ctrlrequest *mctrl;
|
| 231 |
|
| 232 | if ((ctrl->bRequestType & USB_TYPE_MASK) != USB_TYPE_CLASS) {
|
| 233 | uvcg_info(f, "invalid request type\n");
|
| 234 | return -EINVAL;
|
| 235 | }
|
| 236 |
|
| 237 |
|
| 238 | if (le16_to_cpu(ctrl->wLength) > UVC_MAX_REQUEST_SIZE)
|
| 239 | return -EINVAL;
|
| 240 |
|
| 241 | |
| 242 | * Tell the complete callback to generate an event for the next request
|
| 243 | * that will be enqueued by UVCIOC_SEND_RESPONSE.
|
| 244 |
|
| 245 | uvc->event_setup_out = !(ctrl->bRequestType & USB_DIR_IN);
|
| 246 | uvc->event_length = le16_to_cpu(ctrl->wLength);
|
| 247 |
|
| 248 | memset(&v4l2_event, 0, sizeof(v4l2_event));
|
| 249 | v4l2_event.type = UVC_EVENT_SETUP;
|
| 250 | memcpy(&uvc_event->req, ctrl, sizeof(uvc_event->req));
|
| 251 |
|
| 252 | |
| 253 | * the ctrl request so the userspace doesn't have to bother with
|
| 254 | * offset and configfs parsing
|
| 255 |
|
| 256 | mctrl = &uvc_event->req;
|
| 257 | mctrl->wIndex &= ~cpu_to_le16(0xff);
|
| 258 | if (interface == uvc->streaming_intf)
|
| 259 | mctrl->wIndex = cpu_to_le16(UVC_STRING_STREAMING_IDX);
|
| 260 |
|
| 261 | v4l2_event_queue(&uvc->vdev, &v4l2_event);
|
| 262 |
|
| 263 | return 0;
|
| 264 | }
|
| 265 |
|
| 266 | void uvc_function_setup_continue(struct uvc_device *uvc, int disable_ep)
|
| 267 | {
|
| 268 | struct usb_composite_dev *cdev = uvc->func.config->cdev;
|
| 269 |
|
| 270 | if (disable_ep && uvc->video.ep)
|
| 271 | usb_ep_disable(uvc->video.ep);
|
| 272 |
|
| 273 | usb_composite_setup_continue(cdev);
|
| 274 | }
|
| 275 |
|
| 276 | static int
|
| 277 | uvc_function_get_alt(struct usb_function *f, unsigned interface)
|
| 278 | {
|
| 279 | struct uvc_device *uvc = to_uvc(f);
|
| 280 |
|
| 281 | uvcg_info(f, "%s(%u)\n", __func__, interface);
|
| 282 |
|
| 283 | if (interface == uvc->control_intf)
|
| 284 | return 0;
|
| 285 | else if (interface != uvc->streaming_intf)
|
| 286 | return -EINVAL;
|
| 287 | else
|
| 288 | return uvc->video.ep->enabled ? 1 : 0;
|
| 289 | }
|
| 290 |
|
| 291 | static int
|
| 292 | uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
|
| 293 | {
|
| 294 | struct uvc_device *uvc = to_uvc(f);
|
| 295 | struct usb_composite_dev *cdev = f->config->cdev;
|
| 296 | struct v4l2_event v4l2_event;
|
| 297 | struct uvc_event *uvc_event = (void *)&v4l2_event.u.data;
|
| 298 | int ret;
|
| 299 |
|
| 300 | uvcg_info(f, "%s(%u, %u)\n", __func__, interface, alt);
|
| 301 |
|
| 302 | if (interface == uvc->control_intf) {
|
| 303 | if (alt)
|
| 304 | return -EINVAL;
|
| 305 |
|
| 306 | if (uvc->enable_interrupt_ep) {
|
| 307 | uvcg_info(f, "reset UVC interrupt endpoint\n");
|
| 308 | usb_ep_disable(uvc->interrupt_ep);
|
| 309 |
|
| 310 | if (!uvc->interrupt_ep->desc)
|
| 311 | if (config_ep_by_speed(cdev->gadget, f,
|
| 312 | uvc->interrupt_ep))
|
| 313 | return -EINVAL;
|
| 314 |
|
| 315 | usb_ep_enable(uvc->interrupt_ep);
|
| 316 | }
|
| 317 |
|
| 318 | if (uvc->state == UVC_STATE_DISCONNECTED) {
|
| 319 | memset(&v4l2_event, 0, sizeof(v4l2_event));
|
| 320 | v4l2_event.type = UVC_EVENT_CONNECT;
|
| 321 | uvc_event->speed = cdev->gadget->speed;
|
| 322 | v4l2_event_queue(&uvc->vdev, &v4l2_event);
|
| 323 |
|
| 324 | uvc->state = UVC_STATE_CONNECTED;
|
| 325 | }
|
| 326 |
|
| 327 | return 0;
|
| 328 | }
|
| 329 |
|
| 330 | if (interface != uvc->streaming_intf)
|
| 331 | return -EINVAL;
|
| 332 |
|
| 333 | |
| 334 | if (usb_endpoint_xfer_bulk(&uvc->desc.vs_ep))
|
| 335 | return alt ? -EINVAL : 0;
|
| 336 |
|
| 337 |
|
| 338 | switch (alt) {
|
| 339 | case 0:
|
| 340 | if (uvc->state != UVC_STATE_STREAMING)
|
| 341 | return 0;
|
| 342 |
|
| 343 | memset(&v4l2_event, 0, sizeof(v4l2_event));
|
| 344 | v4l2_event.type = UVC_EVENT_STREAMOFF;
|
| 345 | v4l2_event_queue(&uvc->vdev, &v4l2_event);
|
| 346 |
|
| 347 | return USB_GADGET_DELAYED_STATUS;
|
| 348 |
|
| 349 | case 1:
|
| 350 | if (uvc->state != UVC_STATE_CONNECTED)
|
| 351 | return 0;
|
| 352 |
|
| 353 | if (!uvc->video.ep)
|
| 354 | return -EINVAL;
|
| 355 |
|
| 356 | uvcg_info(f, "reset UVC\n");
|
| 357 | usb_ep_disable(uvc->video.ep);
|
| 358 |
|
| 359 | ret = config_ep_by_speed(f->config->cdev->gadget,
|
| 360 | &(uvc->func), uvc->video.ep);
|
| 361 | if (ret)
|
| 362 | return ret;
|
| 363 | usb_ep_enable(uvc->video.ep);
|
| 364 |
|
| 365 | uvc->video.max_req_size = uvc->video.ep->maxpacket
|
| 366 | * max_t(unsigned int, uvc->video.ep->maxburst, 1)
|
| 367 | * (uvc->video.ep->mult);
|
| 368 |
|
| 369 | memset(&v4l2_event, 0, sizeof(v4l2_event));
|
| 370 | v4l2_event.type = UVC_EVENT_STREAMON;
|
| 371 | v4l2_event_queue(&uvc->vdev, &v4l2_event);
|
| 372 | return USB_GADGET_DELAYED_STATUS;
|
| 373 |
|
| 374 | default:
|
| 375 | return -EINVAL;
|
| 376 | }
|
| 377 | }
|
| 378 |
|
| 379 | static void
|
| 380 | uvc_function_disable(struct usb_function *f)
|
| 381 | {
|
| 382 | struct uvc_device *uvc = to_uvc(f);
|
| 383 | struct v4l2_event v4l2_event;
|
| 384 |
|
| 385 | uvcg_info(f, "%s()\n", __func__);
|
| 386 |
|
| 387 | memset(&v4l2_event, 0, sizeof(v4l2_event));
|
| 388 | v4l2_event.type = UVC_EVENT_DISCONNECT;
|
| 389 | v4l2_event_queue(&uvc->vdev, &v4l2_event);
|
| 390 |
|
| 391 | uvc->state = UVC_STATE_DISCONNECTED;
|
| 392 |
|
| 393 | usb_ep_disable(uvc->video.ep);
|
| 394 | if (uvc->enable_interrupt_ep)
|
| 395 | usb_ep_disable(uvc->interrupt_ep);
|
| 396 | }
|
| 397 |
|
| 398 | |
| 399 | * Connection / disconnection
|
| 400 |
|
| 401 |
|
| 402 | void
|
| 403 | uvc_function_connect(struct uvc_device *uvc)
|
| 404 | {
|
| 405 | int ret;
|
| 406 |
|
| 407 | if ((ret = usb_function_activate(&uvc->func)) < 0)
|
| 408 | uvcg_info(&uvc->func, "UVC connect failed with %d\n", ret);
|
| 409 | }
|
| 410 |
|
| 411 | void
|
| 412 | uvc_function_disconnect(struct uvc_device *uvc)
|
| 413 | {
|
| 414 | int ret;
|
| 415 |
|
| 416 | guard(mutex)(&uvc->lock);
|
| 417 | if (uvc->func_unbound) {
|
| 418 | dev_dbg(&uvc->vdev.dev, "skipping function deactivate (unbound)\n");
|
| 419 | return;
|
| 420 | }
|
| 421 |
|
| 422 | if ((ret = usb_function_deactivate(&uvc->func)) < 0)
|
| 423 | uvcg_info(&uvc->func, "UVC disconnect failed with %d\n", ret);
|
| 424 | }
|
| 425 |
|
| 426 | |
| 427 | * USB probe and disconnect
|
| 428 |
|
| 429 |
|
| 430 | static ssize_t function_name_show(struct device *dev,
|
| 431 | struct device_attribute *attr, char *buf)
|
| 432 | {
|
| 433 | struct uvc_device *uvc = dev_get_drvdata(dev);
|
| 434 |
|
| 435 | return sprintf(buf, "%s\n", uvc->func.fi->group.cg_item.ci_name);
|
| 436 | }
|
| 437 |
|
| 438 | static DEVICE_ATTR_RO(function_name);
|
| 439 |
|
| 440 | static void uvc_vdev_release(struct video_device *vdev)
|
| 441 | {
|
| 442 | struct uvc_device *uvc = video_get_drvdata(vdev);
|
| 443 |
|
| 444 |
|
| 445 | if (uvc->vdev_release_done)
|
| 446 | complete(uvc->vdev_release_done);
|
| 447 | }
|
| 448 |
|
| 449 | static int
|
| 450 | uvc_register_video(struct uvc_device *uvc)
|
| 451 | {
|
| 452 | struct usb_composite_dev *cdev = uvc->func.config->cdev;
|
| 453 | int ret;
|
| 454 |
|
| 455 |
|
| 456 | memset(&uvc->vdev, 0, sizeof(uvc->vdev));
|
| 457 | uvc->vdev.v4l2_dev = &uvc->v4l2_dev;
|
| 458 | uvc->vdev.v4l2_dev->dev = &cdev->gadget->dev;
|
| 459 | uvc->vdev.fops = &uvc_v4l2_fops;
|
| 460 | uvc->vdev.ioctl_ops = &uvc_v4l2_ioctl_ops;
|
| 461 | uvc->vdev.release = uvc_vdev_release;
|
| 462 | uvc->vdev.vfl_dir = VFL_DIR_TX;
|
| 463 | uvc->vdev.lock = &uvc->video.mutex;
|
| 464 | uvc->vdev.device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
|
| 465 | strscpy(uvc->vdev.name, cdev->gadget->name, sizeof(uvc->vdev.name));
|
| 466 |
|
| 467 | video_set_drvdata(&uvc->vdev, uvc);
|
| 468 |
|
| 469 | ret = video_register_device(&uvc->vdev, VFL_TYPE_VIDEO, -1);
|
| 470 | if (ret < 0)
|
| 471 | return ret;
|
| 472 |
|
| 473 | ret = device_create_file(&uvc->vdev.dev, &dev_attr_function_name);
|
| 474 | if (ret < 0) {
|
| 475 | video_unregister_device(&uvc->vdev);
|
| 476 | return ret;
|
| 477 | }
|
| 478 |
|
| 479 | return 0;
|
| 480 | }
|
| 481 |
|
| 482 | #define UVC_COPY_DESCRIPTOR(mem, dst, desc) \
|
| 483 | do { \
|
| 484 | memcpy(mem, desc, (desc)->bLength); \
|
| 485 | *(dst)++ = mem; \
|
| 486 | mem += (desc)->bLength; \
|
| 487 | } while (0)
|
| 488 |
|
| 489 | #define UVC_COPY_DESCRIPTORS(mem, dst, src) \
|
| 490 | do { \
|
| 491 | const struct usb_descriptor_header * const *__src; \
|
| 492 | for (__src = src; *__src; ++__src) { \
|
| 493 | memcpy(mem, *__src, (*__src)->bLength); \
|
| 494 | *dst++ = mem; \
|
| 495 | mem += (*__src)->bLength; \
|
| 496 | } \
|
| 497 | } while (0)
|
| 498 |
|
| 499 | #define UVC_COPY_XU_DESCRIPTOR(mem, dst, desc) \
|
| 500 | do { \
|
| 501 | *(dst)++ = mem; \
|
| 502 | memcpy(mem, desc, 22); \
|
| 503 | mem += 22; \
|
| 504 | \
|
| 505 | memcpy(mem, (desc)->baSourceID, (desc)->bNrInPins); \
|
| 506 | mem += (desc)->bNrInPins; \
|
| 507 | \
|
| 508 | memcpy(mem, &(desc)->bControlSize, 1); \
|
| 509 | mem++; \
|
| 510 | \
|
| 511 | memcpy(mem, (desc)->bmControls, (desc)->bControlSize); \
|
| 512 | mem += (desc)->bControlSize; \
|
| 513 | \
|
| 514 | memcpy(mem, &(desc)->iExtension, 1); \
|
| 515 | mem++; \
|
| 516 | } while (0)
|
| 517 |
|
| 518 | static struct usb_descriptor_header **
|
| 519 | uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
|
| 520 | {
|
| 521 | struct uvc_input_header_descriptor *uvc_streaming_header;
|
| 522 | struct uvc_header_descriptor *uvc_control_header;
|
| 523 | const struct uvc_descriptor_header * const *uvc_control_desc;
|
| 524 | const struct uvc_descriptor_header * const *uvc_streaming_cls;
|
| 525 | const struct usb_descriptor_header * const *uvc_streaming_std;
|
| 526 | const struct usb_descriptor_header * const *src;
|
| 527 | struct usb_descriptor_header **dst;
|
| 528 | struct usb_descriptor_header **hdr;
|
| 529 | struct uvcg_extension *xu;
|
| 530 | unsigned int control_size;
|
| 531 | unsigned int streaming_size;
|
| 532 | unsigned int n_desc;
|
| 533 | unsigned int bytes;
|
| 534 | void *mem;
|
| 535 |
|
| 536 | switch (speed) {
|
| 537 | case USB_SPEED_SUPER_PLUS:
|
| 538 | case USB_SPEED_SUPER:
|
| 539 | uvc_control_desc = uvc->desc.ss_control;
|
| 540 | uvc_streaming_cls = uvc->desc.ss_streaming;
|
| 541 | uvc_streaming_std = uvc_ss_streaming;
|
| 542 | break;
|
| 543 |
|
| 544 | case USB_SPEED_HIGH:
|
| 545 | uvc_control_desc = uvc->desc.fs_control;
|
| 546 | uvc_streaming_cls = uvc->desc.hs_streaming;
|
| 547 | uvc_streaming_std = uvc_hs_streaming;
|
| 548 | break;
|
| 549 |
|
| 550 | case USB_SPEED_FULL:
|
| 551 | default:
|
| 552 | uvc_control_desc = uvc->desc.fs_control;
|
| 553 | uvc_streaming_cls = uvc->desc.fs_streaming;
|
| 554 | uvc_streaming_std = uvc_fs_streaming;
|
| 555 | break;
|
| 556 | }
|
| 557 |
|
| 558 | if (!uvc_control_desc || !uvc_streaming_cls)
|
| 559 | return ERR_PTR(-ENODEV);
|
| 560 |
|
| 561 | |
| 562 | * Descriptors layout
|
| 563 | *
|
| 564 | * uvc_iad
|
| 565 | * uvc_control_intf
|
| 566 | * Class-specific UVC control descriptors
|
| 567 | * uvc_interrupt_ep
|
| 568 | * uvc_interrupt_cs_ep
|
| 569 | * uvc_ss_interrupt_comp (for SS only)
|
| 570 | * uvc_streaming_intf_alt0
|
| 571 | * Class-specific UVC streaming descriptors
|
| 572 | * uvc_{fs|hs}_streaming
|
| 573 |
|
| 574 |
|
| 575 |
|
| 576 | control_size = 0;
|
| 577 | streaming_size = 0;
|
| 578 | bytes = uvc_iad.bLength + uvc_control_intf.bLength
|
| 579 | + uvc_streaming_intf_alt0.bLength;
|
| 580 |
|
| 581 | n_desc = 3;
|
| 582 | if (uvc->enable_interrupt_ep) {
|
| 583 | bytes += uvc_interrupt_ep.bLength + uvc_interrupt_cs_ep.bLength;
|
| 584 | n_desc += 2;
|
| 585 |
|
| 586 | if (speed == USB_SPEED_SUPER ||
|
| 587 | speed == USB_SPEED_SUPER_PLUS) {
|
| 588 | bytes += uvc_ss_interrupt_comp.bLength;
|
| 589 | n_desc += 1;
|
| 590 | }
|
| 591 | }
|
| 592 |
|
| 593 | for (src = (const struct usb_descriptor_header **)uvc_control_desc;
|
| 594 | *src; ++src) {
|
| 595 | control_size += (*src)->bLength;
|
| 596 | bytes += (*src)->bLength;
|
| 597 | n_desc++;
|
| 598 | }
|
| 599 |
|
| 600 | list_for_each_entry(xu, uvc->desc.extension_units, list) {
|
| 601 | control_size += xu->desc.bLength;
|
| 602 | bytes += xu->desc.bLength;
|
| 603 | n_desc++;
|
| 604 | }
|
| 605 |
|
| 606 | for (src = (const struct usb_descriptor_header **)uvc_streaming_cls;
|
| 607 | *src; ++src) {
|
| 608 | streaming_size += (*src)->bLength;
|
| 609 | bytes += (*src)->bLength;
|
| 610 | n_desc++;
|
| 611 | }
|
| 612 | for (src = uvc_streaming_std; *src; ++src) {
|
| 613 | bytes += (*src)->bLength;
|
| 614 | n_desc++;
|
| 615 | }
|
| 616 |
|
| 617 | mem = kmalloc((n_desc + 1) * sizeof(*src) + bytes, GFP_KERNEL);
|
| 618 | if (mem == NULL)
|
| 619 | return NULL;
|
| 620 |
|
| 621 | hdr = mem;
|
| 622 | dst = mem;
|
| 623 | mem += (n_desc + 1) * sizeof(*src);
|
| 624 |
|
| 625 |
|
| 626 | UVC_COPY_DESCRIPTOR(mem, dst, &uvc_iad);
|
| 627 | UVC_COPY_DESCRIPTOR(mem, dst, &uvc_control_intf);
|
| 628 |
|
| 629 | uvc_control_header = mem;
|
| 630 | UVC_COPY_DESCRIPTORS(mem, dst,
|
| 631 | (const struct usb_descriptor_header **)uvc_control_desc);
|
| 632 |
|
| 633 | list_for_each_entry(xu, uvc->desc.extension_units, list)
|
| 634 | UVC_COPY_XU_DESCRIPTOR(mem, dst, &xu->desc);
|
| 635 |
|
| 636 | uvc_control_header->wTotalLength = cpu_to_le16(control_size);
|
| 637 | uvc_control_header->bInCollection = 1;
|
| 638 | uvc_control_header->baInterfaceNr[0] = uvc->streaming_intf;
|
| 639 |
|
| 640 | if (uvc->enable_interrupt_ep) {
|
| 641 | UVC_COPY_DESCRIPTOR(mem, dst, &uvc_interrupt_ep);
|
| 642 | if (speed == USB_SPEED_SUPER ||
|
| 643 | speed == USB_SPEED_SUPER_PLUS)
|
| 644 | UVC_COPY_DESCRIPTOR(mem, dst, &uvc_ss_interrupt_comp);
|
| 645 |
|
| 646 | UVC_COPY_DESCRIPTOR(mem, dst, &uvc_interrupt_cs_ep);
|
| 647 | }
|
| 648 |
|
| 649 | UVC_COPY_DESCRIPTOR(mem, dst, &uvc_streaming_intf_alt0);
|
| 650 |
|
| 651 | uvc_streaming_header = mem;
|
| 652 | UVC_COPY_DESCRIPTORS(mem, dst,
|
| 653 | (const struct usb_descriptor_header**)uvc_streaming_cls);
|
| 654 | uvc_streaming_header->wTotalLength = cpu_to_le16(streaming_size);
|
| 655 | uvc_streaming_header->bEndpointAddress = uvc->video.ep->address;
|
| 656 |
|
| 657 | UVC_COPY_DESCRIPTORS(mem, dst, uvc_streaming_std);
|
| 658 |
|
| 659 | *dst = NULL;
|
| 660 | return hdr;
|
| 661 | }
|
| 662 |
|
| 663 | static int
|
| 664 | uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
|
| 665 | {
|
| 666 | struct usb_composite_dev *cdev = c->cdev;
|
| 667 | struct uvc_device *uvc = to_uvc(f);
|
| 668 | struct uvcg_extension *xu;
|
| 669 | struct usb_string *us;
|
| 670 | unsigned int max_packet_mult;
|
| 671 | unsigned int max_packet_size;
|
| 672 | struct usb_ep *ep;
|
| 673 | struct f_uvc_opts *opts;
|
| 674 | int ret = -EINVAL;
|
| 675 |
|
| 676 | uvcg_info(f, "%s()\n", __func__);
|
| 677 | scoped_guard(mutex, &uvc->lock)
|
| 678 | uvc->func_unbound = false;
|
| 679 |
|
| 680 | opts = fi_to_f_uvc_opts(f->fi);
|
| 681 |
|
| 682 | opts->streaming_interval = clamp(opts->streaming_interval, 1U, 16U);
|
| 683 | opts->streaming_maxpacket = clamp(opts->streaming_maxpacket, 1U, 3072U);
|
| 684 | opts->streaming_maxburst = min(opts->streaming_maxburst, 15U);
|
| 685 |
|
| 686 |
|
| 687 | if (opts->streaming_maxburst &&
|
| 688 | (opts->streaming_maxpacket % 1024) != 0) {
|
| 689 | opts->streaming_maxpacket = roundup(opts->streaming_maxpacket, 1024);
|
| 690 | uvcg_info(f, "overriding streaming_maxpacket to %d\n",
|
| 691 | opts->streaming_maxpacket);
|
| 692 | }
|
| 693 |
|
| 694 | |
| 695 | * Fill in the FS/HS/SS Video Streaming specific descriptors from the
|
| 696 | * module parameters.
|
| 697 | *
|
| 698 | * NOTE: We assume that the user knows what they are doing and won't
|
| 699 | * give parameters that their UDC doesn't support.
|
| 700 |
|
| 701 | if (opts->streaming_maxpacket <= 1024) {
|
| 702 | max_packet_mult = 1;
|
| 703 | max_packet_size = opts->streaming_maxpacket;
|
| 704 | } else if (opts->streaming_maxpacket <= 2048) {
|
| 705 | max_packet_mult = 2;
|
| 706 | max_packet_size = opts->streaming_maxpacket / 2;
|
| 707 | } else {
|
| 708 | max_packet_mult = 3;
|
| 709 | max_packet_size = opts->streaming_maxpacket / 3;
|
| 710 | }
|
| 711 |
|
| 712 | uvc_fs_streaming_ep.wMaxPacketSize =
|
| 713 | cpu_to_le16(min(opts->streaming_maxpacket, 1023U));
|
| 714 | uvc_fs_streaming_ep.bInterval = opts->streaming_interval;
|
| 715 |
|
| 716 | uvc_hs_streaming_ep.wMaxPacketSize =
|
| 717 | cpu_to_le16(max_packet_size | ((max_packet_mult - 1) << 11));
|
| 718 |
|
| 719 |
|
| 720 | if (max_packet_mult > 1)
|
| 721 | uvc_hs_streaming_ep.bInterval = 1;
|
| 722 | else
|
| 723 | uvc_hs_streaming_ep.bInterval = opts->streaming_interval;
|
| 724 |
|
| 725 | uvc_ss_streaming_ep.wMaxPacketSize = cpu_to_le16(max_packet_size);
|
| 726 | uvc_ss_streaming_ep.bInterval = opts->streaming_interval;
|
| 727 | uvc_ss_streaming_comp.bmAttributes = max_packet_mult - 1;
|
| 728 | uvc_ss_streaming_comp.bMaxBurst = opts->streaming_maxburst;
|
| 729 | uvc_ss_streaming_comp.wBytesPerInterval =
|
| 730 | cpu_to_le16(max_packet_size * max_packet_mult *
|
| 731 | (opts->streaming_maxburst + 1));
|
| 732 |
|
| 733 |
|
| 734 | if (opts->enable_interrupt_ep) {
|
| 735 | ep = usb_ep_autoconfig(cdev->gadget, &uvc_interrupt_ep);
|
| 736 | if (!ep) {
|
| 737 | uvcg_info(f, "Unable to allocate interrupt EP\n");
|
| 738 | goto error;
|
| 739 | }
|
| 740 | uvc->interrupt_ep = ep;
|
| 741 | uvc_control_intf.bNumEndpoints = 1;
|
| 742 | }
|
| 743 | uvc->enable_interrupt_ep = opts->enable_interrupt_ep;
|
| 744 |
|
| 745 | |
| 746 | * gadget_is_{super|dual}speed() API check UDC controller capitblity. It should pass down
|
| 747 | * highest speed endpoint descriptor to UDC controller. So UDC controller driver can reserve
|
| 748 | * enough resource at check_config(), especially mult and maxburst. So UDC driver (such as
|
| 749 | * cdns3) can know need at least (mult + 1) * (maxburst + 1) * wMaxPacketSize internal
|
| 750 | * memory for this uvc functions. This is the only straightforward method to resolve the UDC
|
| 751 | * resource allocation issue in the current gadget framework.
|
| 752 |
|
| 753 | if (gadget_is_superspeed(c->cdev->gadget))
|
| 754 | ep = usb_ep_autoconfig_ss(cdev->gadget, &uvc_ss_streaming_ep,
|
| 755 | &uvc_ss_streaming_comp);
|
| 756 | else if (gadget_is_dualspeed(cdev->gadget))
|
| 757 | ep = usb_ep_autoconfig(cdev->gadget, &uvc_hs_streaming_ep);
|
| 758 | else
|
| 759 | ep = usb_ep_autoconfig(cdev->gadget, &uvc_fs_streaming_ep);
|
| 760 |
|
| 761 | if (!ep) {
|
| 762 | uvcg_info(f, "Unable to allocate streaming EP\n");
|
| 763 | goto error;
|
| 764 | }
|
| 765 | uvc->video.ep = ep;
|
| 766 |
|
| 767 | uvc_fs_streaming_ep.bEndpointAddress = uvc->video.ep->address;
|
| 768 | uvc_hs_streaming_ep.bEndpointAddress = uvc->video.ep->address;
|
| 769 | uvc_ss_streaming_ep.bEndpointAddress = uvc->video.ep->address;
|
| 770 |
|
| 771 | |
| 772 | * Hold opts->lock across both the XU string-descriptor fixup below and
|
| 773 | * the descriptor-copy block further down. Without this, configfs
|
| 774 | * uvcg_extension_drop() (which takes opts->lock) can race with the
|
| 775 | * list_for_each_entry() walks here and inside uvc_copy_descriptors(),
|
| 776 | * leading to a UAF on a freed struct uvcg_extension. See
|
| 777 | * drivers/usb/gadget/function/uvc_configfs.c::uvcg_extension_drop().
|
| 778 |
|
| 779 | mutex_lock(&opts->lock);
|
| 780 |
|
| 781 | |
| 782 | * XUs can have an arbitrary string descriptor describing them. If they
|
| 783 | * have one pick up the ID.
|
| 784 |
|
| 785 | list_for_each_entry(xu, &opts->extension_units, list)
|
| 786 | if (xu->string_descriptor_index)
|
| 787 | xu->desc.iExtension = cdev->usb_strings[xu->string_descriptor_index].id;
|
| 788 |
|
| 789 | |
| 790 | * We attach the hard-coded defaults incase the user does not provide
|
| 791 | * any more appropriate strings through configfs.
|
| 792 |
|
| 793 | uvc_en_us_strings[UVC_STRING_CONTROL_IDX].s = opts->function_name;
|
| 794 | us = usb_gstrings_attach(cdev, uvc_function_strings,
|
| 795 | ARRAY_SIZE(uvc_en_us_strings));
|
| 796 | if (IS_ERR(us)) {
|
| 797 | ret = PTR_ERR(us);
|
| 798 | goto error_unlock;
|
| 799 | }
|
| 800 |
|
| 801 | uvc_iad.iFunction = opts->iad_index ? cdev->usb_strings[opts->iad_index].id :
|
| 802 | us[UVC_STRING_CONTROL_IDX].id;
|
| 803 | uvc_streaming_intf_alt0.iInterface = opts->vs0_index ?
|
| 804 | cdev->usb_strings[opts->vs0_index].id :
|
| 805 | us[UVC_STRING_STREAMING_IDX].id;
|
| 806 | uvc_streaming_intf_alt1.iInterface = opts->vs1_index ?
|
| 807 | cdev->usb_strings[opts->vs1_index].id :
|
| 808 | us[UVC_STRING_STREAMING_IDX].id;
|
| 809 |
|
| 810 |
|
| 811 | if ((ret = usb_interface_id(c, f)) < 0)
|
| 812 | goto error_unlock;
|
| 813 | uvc_iad.bFirstInterface = ret;
|
| 814 | uvc_control_intf.bInterfaceNumber = ret;
|
| 815 | uvc->control_intf = ret;
|
| 816 | opts->control_interface = ret;
|
| 817 |
|
| 818 | if ((ret = usb_interface_id(c, f)) < 0)
|
| 819 | goto error_unlock;
|
| 820 | uvc_streaming_intf_alt0.bInterfaceNumber = ret;
|
| 821 | uvc_streaming_intf_alt1.bInterfaceNumber = ret;
|
| 822 | uvc->streaming_intf = ret;
|
| 823 | opts->streaming_interface = ret;
|
| 824 |
|
| 825 |
|
| 826 | f->fs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_FULL);
|
| 827 | if (IS_ERR(f->fs_descriptors)) {
|
| 828 | ret = PTR_ERR(f->fs_descriptors);
|
| 829 | f->fs_descriptors = NULL;
|
| 830 | goto error_unlock;
|
| 831 | }
|
| 832 |
|
| 833 | f->hs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_HIGH);
|
| 834 | if (IS_ERR(f->hs_descriptors)) {
|
| 835 | ret = PTR_ERR(f->hs_descriptors);
|
| 836 | f->hs_descriptors = NULL;
|
| 837 | goto error_unlock;
|
| 838 | }
|
| 839 |
|
| 840 | f->ss_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_SUPER);
|
| 841 | if (IS_ERR(f->ss_descriptors)) {
|
| 842 | ret = PTR_ERR(f->ss_descriptors);
|
| 843 | f->ss_descriptors = NULL;
|
| 844 | goto error_unlock;
|
| 845 | }
|
| 846 |
|
| 847 | f->ssp_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_SUPER_PLUS);
|
| 848 | if (IS_ERR(f->ssp_descriptors)) {
|
| 849 | ret = PTR_ERR(f->ssp_descriptors);
|
| 850 | f->ssp_descriptors = NULL;
|
| 851 | goto error_unlock;
|
| 852 | }
|
| 853 |
|
| 854 | mutex_unlock(&opts->lock);
|
| 855 |
|
| 856 |
|
| 857 | uvc->control_req = usb_ep_alloc_request(cdev->gadget->ep0, GFP_KERNEL);
|
| 858 | uvc->control_buf = kmalloc(UVC_MAX_REQUEST_SIZE, GFP_KERNEL);
|
| 859 | if (uvc->control_req == NULL || uvc->control_buf == NULL) {
|
| 860 | ret = -ENOMEM;
|
| 861 | goto error;
|
| 862 | }
|
| 863 |
|
| 864 | uvc->control_req->buf = uvc->control_buf;
|
| 865 | uvc->control_req->complete = uvc_function_ep0_complete;
|
| 866 | uvc->control_req->context = uvc;
|
| 867 |
|
| 868 | if (v4l2_device_register(&cdev->gadget->dev, &uvc->v4l2_dev)) {
|
| 869 | uvcg_err(f, "failed to register V4L2 device\n");
|
| 870 | goto error;
|
| 871 | }
|
| 872 |
|
| 873 |
|
| 874 | ret = uvcg_video_init(&uvc->video, uvc);
|
| 875 | if (ret < 0)
|
| 876 | goto v4l2_error;
|
| 877 |
|
| 878 |
|
| 879 | ret = uvc_register_video(uvc);
|
| 880 | if (ret < 0) {
|
| 881 | uvcg_err(f, "failed to register video device\n");
|
| 882 | goto v4l2_error;
|
| 883 | }
|
| 884 |
|
| 885 | return 0;
|
| 886 |
|
| 887 | error_unlock:
|
| 888 | mutex_unlock(&opts->lock);
|
| 889 | v4l2_error:
|
| 890 | v4l2_device_unregister(&uvc->v4l2_dev);
|
| 891 | error:
|
| 892 | if (uvc->control_req) {
|
| 893 | usb_ep_free_request(cdev->gadget->ep0, uvc->control_req);
|
| 894 | uvc->control_req = NULL;
|
| 895 | }
|
| 896 | kfree(uvc->control_buf);
|
| 897 | uvc->control_buf = NULL;
|
| 898 |
|
| 899 | usb_free_all_descriptors(f);
|
| 900 | return ret;
|
| 901 | }
|
| 902 |
|
| 903 | |
| 904 | * USB gadget function
|
| 905 |
|
| 906 |
|
| 907 | static void uvc_free_inst(struct usb_function_instance *f)
|
| 908 | {
|
| 909 | struct f_uvc_opts *opts = fi_to_f_uvc_opts(f);
|
| 910 |
|
| 911 | mutex_destroy(&opts->lock);
|
| 912 | kfree(opts);
|
| 913 | }
|
| 914 |
|
| 915 | static struct usb_function_instance *uvc_alloc_inst(void)
|
| 916 | {
|
| 917 | struct f_uvc_opts *opts;
|
| 918 | struct uvc_camera_terminal_descriptor *cd;
|
| 919 | struct uvc_processing_unit_descriptor *pd;
|
| 920 | struct uvc_output_terminal_descriptor *od;
|
| 921 | struct uvc_descriptor_header **ctl_cls;
|
| 922 | int ret;
|
| 923 |
|
| 924 | opts = kzalloc_obj(*opts);
|
| 925 | if (!opts)
|
| 926 | return ERR_PTR(-ENOMEM);
|
| 927 | opts->func_inst.free_func_inst = uvc_free_inst;
|
| 928 | mutex_init(&opts->lock);
|
| 929 |
|
| 930 | cd = &opts->uvc_camera_terminal;
|
| 931 | cd->bLength = UVC_DT_CAMERA_TERMINAL_SIZE(3);
|
| 932 | cd->bDescriptorType = USB_DT_CS_INTERFACE;
|
| 933 | cd->bDescriptorSubType = UVC_VC_INPUT_TERMINAL;
|
| 934 | cd->bTerminalID = 1;
|
| 935 | cd->wTerminalType = cpu_to_le16(0x0201);
|
| 936 | cd->bAssocTerminal = 0;
|
| 937 | cd->iTerminal = 0;
|
| 938 | cd->wObjectiveFocalLengthMin = cpu_to_le16(0);
|
| 939 | cd->wObjectiveFocalLengthMax = cpu_to_le16(0);
|
| 940 | cd->wOcularFocalLength = cpu_to_le16(0);
|
| 941 | cd->bControlSize = 3;
|
| 942 | cd->bmControls[0] = 2;
|
| 943 | cd->bmControls[1] = 0;
|
| 944 | cd->bmControls[2] = 0;
|
| 945 |
|
| 946 | pd = &opts->uvc_processing;
|
| 947 | pd->bLength = UVC_DT_PROCESSING_UNIT_SIZE(2);
|
| 948 | pd->bDescriptorType = USB_DT_CS_INTERFACE;
|
| 949 | pd->bDescriptorSubType = UVC_VC_PROCESSING_UNIT;
|
| 950 | pd->bUnitID = 2;
|
| 951 | pd->bSourceID = 1;
|
| 952 | pd->wMaxMultiplier = cpu_to_le16(16*1024);
|
| 953 | pd->bControlSize = 2;
|
| 954 | pd->bmControls[0] = 1;
|
| 955 | pd->bmControls[1] = 0;
|
| 956 | pd->iProcessing = 0;
|
| 957 | pd->bmVideoStandards = 0;
|
| 958 |
|
| 959 | od = &opts->uvc_output_terminal;
|
| 960 | od->bLength = UVC_DT_OUTPUT_TERMINAL_SIZE;
|
| 961 | od->bDescriptorType = USB_DT_CS_INTERFACE;
|
| 962 | od->bDescriptorSubType = UVC_VC_OUTPUT_TERMINAL;
|
| 963 | od->bTerminalID = 3;
|
| 964 | od->wTerminalType = cpu_to_le16(0x0101);
|
| 965 | od->bAssocTerminal = 0;
|
| 966 | od->bSourceID = 2;
|
| 967 | od->iTerminal = 0;
|
| 968 |
|
| 969 | |
| 970 | * With the ability to add XUs to the UVC function graph, we need to be
|
| 971 | * able to allocate unique unit IDs to them. The IDs are 1-based, with
|
| 972 | * the CT, PU and OT above consuming the first 3.
|
| 973 |
|
| 974 | opts->last_unit_id = 3;
|
| 975 |
|
| 976 |
|
| 977 | ctl_cls = opts->uvc_fs_control_cls;
|
| 978 | ctl_cls[0] = NULL;
|
| 979 | ctl_cls[1] = (struct uvc_descriptor_header *)cd;
|
| 980 | ctl_cls[2] = (struct uvc_descriptor_header *)pd;
|
| 981 | ctl_cls[3] = (struct uvc_descriptor_header *)od;
|
| 982 | ctl_cls[4] = NULL;
|
| 983 | opts->fs_control =
|
| 984 | (const struct uvc_descriptor_header * const *)ctl_cls;
|
| 985 |
|
| 986 |
|
| 987 | ctl_cls = opts->uvc_ss_control_cls;
|
| 988 | ctl_cls[0] = NULL;
|
| 989 | ctl_cls[1] = (struct uvc_descriptor_header *)cd;
|
| 990 | ctl_cls[2] = (struct uvc_descriptor_header *)pd;
|
| 991 | ctl_cls[3] = (struct uvc_descriptor_header *)od;
|
| 992 | ctl_cls[4] = NULL;
|
| 993 | opts->ss_control =
|
| 994 | (const struct uvc_descriptor_header * const *)ctl_cls;
|
| 995 |
|
| 996 | INIT_LIST_HEAD(&opts->extension_units);
|
| 997 |
|
| 998 | opts->streaming_interval = 1;
|
| 999 | opts->streaming_maxpacket = 1024;
|
| 1000 | snprintf(opts->function_name, sizeof(opts->function_name), "UVC Camera");
|
| 1001 |
|
| 1002 | ret = uvcg_attach_configfs(opts);
|
| 1003 | if (ret < 0) {
|
| 1004 | kfree(opts);
|
| 1005 | return ERR_PTR(ret);
|
| 1006 | }
|
| 1007 |
|
| 1008 | return &opts->func_inst;
|
| 1009 | }
|
| 1010 |
|
| 1011 | static void uvc_free(struct usb_function *f)
|
| 1012 | {
|
| 1013 | struct uvc_device *uvc = to_uvc(f);
|
| 1014 | struct f_uvc_opts *opts = container_of(f->fi, struct f_uvc_opts,
|
| 1015 | func_inst);
|
| 1016 | if (!opts->header)
|
| 1017 | config_item_put(&uvc->header->item);
|
| 1018 | --opts->refcnt;
|
| 1019 | kfree(uvc);
|
| 1020 | }
|
| 1021 |
|
| 1022 | static void uvc_function_unbind(struct usb_configuration *c,
|
| 1023 | struct usb_function *f)
|
| 1024 | {
|
| 1025 | DECLARE_COMPLETION_ONSTACK(vdev_release_done);
|
| 1026 | struct usb_composite_dev *cdev = c->cdev;
|
| 1027 | struct uvc_device *uvc = to_uvc(f);
|
| 1028 | struct uvc_video *video = &uvc->video;
|
| 1029 | long wait_ret = 1;
|
| 1030 | bool connected;
|
| 1031 |
|
| 1032 | uvcg_info(f, "%s()\n", __func__);
|
| 1033 | scoped_guard(mutex, &uvc->lock) {
|
| 1034 | uvc->func_unbound = true;
|
| 1035 | uvc->vdev_release_done = &vdev_release_done;
|
| 1036 | connected = uvc->func_connected;
|
| 1037 | }
|
| 1038 |
|
| 1039 | kthread_cancel_work_sync(&video->hw_submit);
|
| 1040 |
|
| 1041 | if (video->async_wq)
|
| 1042 | destroy_workqueue(video->async_wq);
|
| 1043 |
|
| 1044 | |
| 1045 | * If we know we're connected via v4l2, then there should be a cleanup
|
| 1046 | * of the device from userspace either via UVC_EVENT_DISCONNECT or
|
| 1047 | * though the video device removal uevent. Allow some time for the
|
| 1048 | * application to close out before things get deleted.
|
| 1049 |
|
| 1050 | if (connected) {
|
| 1051 | uvcg_dbg(f, "waiting for clean disconnect\n");
|
| 1052 | wait_ret = wait_event_interruptible_timeout(uvc->func_connected_queue,
|
| 1053 | uvc->func_connected == false, msecs_to_jiffies(500));
|
| 1054 | uvcg_dbg(f, "done waiting with ret: %ld\n", wait_ret);
|
| 1055 | }
|
| 1056 |
|
| 1057 | device_remove_file(&uvc->vdev.dev, &dev_attr_function_name);
|
| 1058 | video_unregister_device(&uvc->vdev);
|
| 1059 | v4l2_device_unregister(&uvc->v4l2_dev);
|
| 1060 |
|
| 1061 | scoped_guard(mutex, &uvc->lock)
|
| 1062 | connected = uvc->func_connected;
|
| 1063 |
|
| 1064 | if (connected) {
|
| 1065 | |
| 1066 | * Wait for the release to occur to ensure there are no longer any
|
| 1067 | * pending operations that may cause panics when resources are cleaned
|
| 1068 | * up.
|
| 1069 |
|
| 1070 | uvcg_warn(f, "%s no clean disconnect, wait for release\n", __func__);
|
| 1071 | wait_ret = wait_event_interruptible_timeout(uvc->func_connected_queue,
|
| 1072 | uvc->func_connected == false, msecs_to_jiffies(1000));
|
| 1073 | uvcg_dbg(f, "done waiting for release with ret: %ld\n", wait_ret);
|
| 1074 | }
|
| 1075 |
|
| 1076 |
|
| 1077 | wait_for_completion(&vdev_release_done);
|
| 1078 | uvc->vdev_release_done = NULL;
|
| 1079 |
|
| 1080 | usb_ep_free_request(cdev->gadget->ep0, uvc->control_req);
|
| 1081 | uvc->control_req = NULL;
|
| 1082 | kfree(uvc->control_buf);
|
| 1083 | uvc->control_buf = NULL;
|
| 1084 |
|
| 1085 | usb_free_all_descriptors(f);
|
| 1086 | }
|
| 1087 |
|
| 1088 | static struct usb_function *uvc_alloc(struct usb_function_instance *fi)
|
| 1089 | {
|
| 1090 | struct uvc_device *uvc;
|
| 1091 | struct f_uvc_opts *opts;
|
| 1092 | struct uvc_descriptor_header **strm_cls;
|
| 1093 | struct config_item *streaming, *header, *h;
|
| 1094 |
|
| 1095 | uvc = kzalloc_obj(*uvc);
|
| 1096 | if (uvc == NULL)
|
| 1097 | return ERR_PTR(-ENOMEM);
|
| 1098 |
|
| 1099 | mutex_init(&uvc->video.mutex);
|
| 1100 | mutex_init(&uvc->lock);
|
| 1101 | uvc->func_unbound = true;
|
| 1102 | uvc->state = UVC_STATE_DISCONNECTED;
|
| 1103 | init_waitqueue_head(&uvc->func_connected_queue);
|
| 1104 | opts = fi_to_f_uvc_opts(fi);
|
| 1105 |
|
| 1106 | mutex_lock(&opts->lock);
|
| 1107 | if (opts->uvc_fs_streaming_cls) {
|
| 1108 | strm_cls = opts->uvc_fs_streaming_cls;
|
| 1109 | opts->fs_streaming =
|
| 1110 | (const struct uvc_descriptor_header * const *)strm_cls;
|
| 1111 | }
|
| 1112 | if (opts->uvc_hs_streaming_cls) {
|
| 1113 | strm_cls = opts->uvc_hs_streaming_cls;
|
| 1114 | opts->hs_streaming =
|
| 1115 | (const struct uvc_descriptor_header * const *)strm_cls;
|
| 1116 | }
|
| 1117 | if (opts->uvc_ss_streaming_cls) {
|
| 1118 | strm_cls = opts->uvc_ss_streaming_cls;
|
| 1119 | opts->ss_streaming =
|
| 1120 | (const struct uvc_descriptor_header * const *)strm_cls;
|
| 1121 | }
|
| 1122 |
|
| 1123 | uvc->desc.fs_control = opts->fs_control;
|
| 1124 | uvc->desc.ss_control = opts->ss_control;
|
| 1125 | uvc->desc.fs_streaming = opts->fs_streaming;
|
| 1126 | uvc->desc.hs_streaming = opts->hs_streaming;
|
| 1127 | uvc->desc.ss_streaming = opts->ss_streaming;
|
| 1128 |
|
| 1129 | if (opts->header) {
|
| 1130 | uvc->header = opts->header;
|
| 1131 | } else {
|
| 1132 | streaming = config_group_find_item(&opts->func_inst.group, "streaming");
|
| 1133 | if (!streaming)
|
| 1134 | goto err_config;
|
| 1135 |
|
| 1136 | header = config_group_find_item(to_config_group(streaming), "header");
|
| 1137 | config_item_put(streaming);
|
| 1138 | if (!header)
|
| 1139 | goto err_config;
|
| 1140 |
|
| 1141 | h = config_group_find_item(to_config_group(header), "h");
|
| 1142 | config_item_put(header);
|
| 1143 | if (!h)
|
| 1144 | goto err_config;
|
| 1145 |
|
| 1146 | uvc->header = to_uvcg_streaming_header(h);
|
| 1147 | if (!uvc->header->linked) {
|
| 1148 | mutex_unlock(&opts->lock);
|
| 1149 | kfree(uvc);
|
| 1150 | return ERR_PTR(-EBUSY);
|
| 1151 | }
|
| 1152 | }
|
| 1153 |
|
| 1154 | uvc->desc.extension_units = &opts->extension_units;
|
| 1155 |
|
| 1156 | ++opts->refcnt;
|
| 1157 | mutex_unlock(&opts->lock);
|
| 1158 |
|
| 1159 |
|
| 1160 | uvc->func.name = "uvc";
|
| 1161 | uvc->func.bind = uvc_function_bind;
|
| 1162 | uvc->func.unbind = uvc_function_unbind;
|
| 1163 | uvc->func.get_alt = uvc_function_get_alt;
|
| 1164 | uvc->func.set_alt = uvc_function_set_alt;
|
| 1165 | uvc->func.disable = uvc_function_disable;
|
| 1166 | uvc->func.setup = uvc_function_setup;
|
| 1167 | uvc->func.free_func = uvc_free;
|
| 1168 | uvc->func.bind_deactivated = true;
|
| 1169 |
|
| 1170 | return &uvc->func;
|
| 1171 |
|
| 1172 | err_config:
|
| 1173 | mutex_unlock(&opts->lock);
|
| 1174 | kfree(uvc);
|
| 1175 | return ERR_PTR(-ENOENT);
|
| 1176 | }
|
| 1177 |
|
| 1178 | DECLARE_USB_FUNCTION_INIT(uvc, uvc_alloc_inst, uvc_alloc);
|
| 1179 | MODULE_DESCRIPTION("USB Video Class Gadget driver");
|
| 1180 | MODULE_LICENSE("GPL");
|
| 1181 | MODULE_AUTHOR("Laurent Pinchart");
|