diff options
| -rw-r--r-- | drivers/media/video/uvc/uvc_v4l2.c | 78 | ||||
| -rw-r--r-- | drivers/media/video/uvc/uvc_video.c | 3 | ||||
| -rw-r--r-- | drivers/media/video/uvc/uvcvideo.h | 4 |
3 files changed, 58 insertions, 27 deletions
diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c index 07dd2357fbb..2f6dc6b9734 100644 --- a/drivers/media/video/uvc/uvc_v4l2.c +++ b/drivers/media/video/uvc/uvc_v4l2.c | |||
| @@ -226,12 +226,14 @@ static int uvc_v4l2_try_format(struct uvc_streaming *stream, | |||
| 226 | * developers test their webcams with the Linux driver as well as with | 226 | * developers test their webcams with the Linux driver as well as with |
| 227 | * the Windows driver). | 227 | * the Windows driver). |
| 228 | */ | 228 | */ |
| 229 | mutex_lock(&stream->mutex); | ||
| 229 | if (stream->dev->quirks & UVC_QUIRK_PROBE_EXTRAFIELDS) | 230 | if (stream->dev->quirks & UVC_QUIRK_PROBE_EXTRAFIELDS) |
| 230 | probe->dwMaxVideoFrameSize = | 231 | probe->dwMaxVideoFrameSize = |
| 231 | stream->ctrl.dwMaxVideoFrameSize; | 232 | stream->ctrl.dwMaxVideoFrameSize; |
| 232 | 233 | ||
| 233 | /* Probe the device. */ | 234 | /* Probe the device. */ |
| 234 | ret = uvc_probe_video(stream, probe); | 235 | ret = uvc_probe_video(stream, probe); |
| 236 | mutex_unlock(&stream->mutex); | ||
| 235 | if (ret < 0) | 237 | if (ret < 0) |
| 236 | goto done; | 238 | goto done; |
| 237 | 239 | ||
| @@ -255,14 +257,21 @@ done: | |||
| 255 | static int uvc_v4l2_get_format(struct uvc_streaming *stream, | 257 | static int uvc_v4l2_get_format(struct uvc_streaming *stream, |
| 256 | struct v4l2_format *fmt) | 258 | struct v4l2_format *fmt) |
| 257 | { | 259 | { |
| 258 | struct uvc_format *format = stream->cur_format; | 260 | struct uvc_format *format; |
| 259 | struct uvc_frame *frame = stream->cur_frame; | 261 | struct uvc_frame *frame; |
| 262 | int ret = 0; | ||
| 260 | 263 | ||
| 261 | if (fmt->type != stream->type) | 264 | if (fmt->type != stream->type) |
| 262 | return -EINVAL; | 265 | return -EINVAL; |
| 263 | 266 | ||
| 264 | if (format == NULL || frame == NULL) | 267 | mutex_lock(&stream->mutex); |
| 265 | return -EINVAL; | 268 | format = stream->cur_format; |
| 269 | frame = stream->cur_frame; | ||
| 270 | |||
| 271 | if (format == NULL || frame == NULL) { | ||
| 272 | ret = -EINVAL; | ||
| 273 | goto done; | ||
| 274 | } | ||
| 266 | 275 | ||
| 267 | fmt->fmt.pix.pixelformat = format->fcc; | 276 | fmt->fmt.pix.pixelformat = format->fcc; |
| 268 | fmt->fmt.pix.width = frame->wWidth; | 277 | fmt->fmt.pix.width = frame->wWidth; |
| @@ -273,7 +282,9 @@ static int uvc_v4l2_get_format(struct uvc_streaming *stream, | |||
| 273 | fmt->fmt.pix.colorspace = format->colorspace; | 282 | fmt->fmt.pix.colorspace = format->colorspace; |
| 274 | fmt->fmt.pix.priv = 0; | 283 | fmt->fmt.pix.priv = 0; |
| 275 | 284 | ||
| 276 | return 0; | 285 | done: |
| 286 | mutex_unlock(&stream->mutex); | ||
| 287 | return ret; | ||
| 277 | } | 288 | } |
| 278 | 289 | ||
| 279 | static int uvc_v4l2_set_format(struct uvc_streaming *stream, | 290 | static int uvc_v4l2_set_format(struct uvc_streaming *stream, |
| @@ -287,18 +298,24 @@ static int uvc_v4l2_set_format(struct uvc_streaming *stream, | |||
| 287 | if (fmt->type != stream->type) | 298 | if (fmt->type != stream->type) |
| 288 | return -EINVAL; | 299 | return -EINVAL; |
| 289 | 300 | ||
| 290 | if (uvc_queue_allocated(&stream->queue)) | ||
| 291 | return -EBUSY; | ||
| 292 | |||
| 293 | ret = uvc_v4l2_try_format(stream, fmt, &probe, &format, &frame); | 301 | ret = uvc_v4l2_try_format(stream, fmt, &probe, &format, &frame); |
| 294 | if (ret < 0) | 302 | if (ret < 0) |
| 295 | return ret; | 303 | return ret; |
| 296 | 304 | ||
| 305 | mutex_lock(&stream->mutex); | ||
| 306 | |||
| 307 | if (uvc_queue_allocated(&stream->queue)) { | ||
| 308 | ret = -EBUSY; | ||
| 309 | goto done; | ||
| 310 | } | ||
| 311 | |||
| 297 | memcpy(&stream->ctrl, &probe, sizeof probe); | 312 | memcpy(&stream->ctrl, &probe, sizeof probe); |
| 298 | stream->cur_format = format; | 313 | stream->cur_format = format; |
| 299 | stream->cur_frame = frame; | 314 | stream->cur_frame = frame; |
| 300 | 315 | ||
| 301 | return 0; | 316 | done: |
| 317 | mutex_unlock(&stream->mutex); | ||
| 318 | return ret; | ||
| 302 | } | 319 | } |
| 303 | 320 | ||
| 304 | static int uvc_v4l2_get_streamparm(struct uvc_streaming *stream, | 321 | static int uvc_v4l2_get_streamparm(struct uvc_streaming *stream, |
| @@ -309,7 +326,10 @@ static int uvc_v4l2_get_streamparm(struct uvc_streaming *stream, | |||
| 309 | if (parm->type != stream->type) | 326 | if (parm->type != stream->type) |
| 310 | return -EINVAL; | 327 | return -EINVAL; |
| 311 | 328 | ||
| 329 | mutex_lock(&stream->mutex); | ||
| 312 | numerator = stream->ctrl.dwFrameInterval; | 330 | numerator = stream->ctrl.dwFrameInterval; |
| 331 | mutex_unlock(&stream->mutex); | ||
| 332 | |||
| 313 | denominator = 10000000; | 333 | denominator = 10000000; |
| 314 | uvc_simplify_fraction(&numerator, &denominator, 8, 333); | 334 | uvc_simplify_fraction(&numerator, &denominator, 8, 333); |
| 315 | 335 | ||
| @@ -336,7 +356,6 @@ static int uvc_v4l2_get_streamparm(struct uvc_streaming *stream, | |||
| 336 | static int uvc_v4l2_set_streamparm(struct uvc_streaming *stream, | 356 | static int uvc_v4l2_set_streamparm(struct uvc_streaming *stream, |
| 337 | struct v4l2_streamparm *parm) | 357 | struct v4l2_streamparm *parm) |
| 338 | { | 358 | { |
| 339 | struct uvc_frame *frame = stream->cur_frame; | ||
| 340 | struct uvc_streaming_control probe; | 359 | struct uvc_streaming_control probe; |
| 341 | struct v4l2_fract timeperframe; | 360 | struct v4l2_fract timeperframe; |
| 342 | uint32_t interval; | 361 | uint32_t interval; |
| @@ -345,28 +364,36 @@ static int uvc_v4l2_set_streamparm(struct uvc_streaming *stream, | |||
| 345 | if (parm->type != stream->type) | 364 | if (parm->type != stream->type) |
| 346 | return -EINVAL; | 365 | return -EINVAL; |
| 347 | 366 | ||
| 348 | if (uvc_queue_streaming(&stream->queue)) | ||
| 349 | return -EBUSY; | ||
| 350 | |||
| 351 | if (parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) | 367 | if (parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) |
| 352 | timeperframe = parm->parm.capture.timeperframe; | 368 | timeperframe = parm->parm.capture.timeperframe; |
| 353 | else | 369 | else |
| 354 | timeperframe = parm->parm.output.timeperframe; | 370 | timeperframe = parm->parm.output.timeperframe; |
| 355 | 371 | ||
| 356 | memcpy(&probe, &stream->ctrl, sizeof probe); | ||
| 357 | interval = uvc_fraction_to_interval(timeperframe.numerator, | 372 | interval = uvc_fraction_to_interval(timeperframe.numerator, |
| 358 | timeperframe.denominator); | 373 | timeperframe.denominator); |
| 359 | |||
| 360 | uvc_trace(UVC_TRACE_FORMAT, "Setting frame interval to %u/%u (%u).\n", | 374 | uvc_trace(UVC_TRACE_FORMAT, "Setting frame interval to %u/%u (%u).\n", |
| 361 | timeperframe.numerator, timeperframe.denominator, interval); | 375 | timeperframe.numerator, timeperframe.denominator, interval); |
| 362 | probe.dwFrameInterval = uvc_try_frame_interval(frame, interval); | 376 | |
| 377 | mutex_lock(&stream->mutex); | ||
| 378 | |||
| 379 | if (uvc_queue_streaming(&stream->queue)) { | ||
| 380 | mutex_unlock(&stream->mutex); | ||
| 381 | return -EBUSY; | ||
| 382 | } | ||
| 383 | |||
| 384 | memcpy(&probe, &stream->ctrl, sizeof probe); | ||
| 385 | probe.dwFrameInterval = | ||
| 386 | uvc_try_frame_interval(stream->cur_frame, interval); | ||
| 363 | 387 | ||
| 364 | /* Probe the device with the new settings. */ | 388 | /* Probe the device with the new settings. */ |
| 365 | ret = uvc_probe_video(stream, &probe); | 389 | ret = uvc_probe_video(stream, &probe); |
| 366 | if (ret < 0) | 390 | if (ret < 0) { |
| 391 | mutex_unlock(&stream->mutex); | ||
| 367 | return ret; | 392 | return ret; |
| 393 | } | ||
| 368 | 394 | ||
| 369 | memcpy(&stream->ctrl, &probe, sizeof probe); | 395 | memcpy(&stream->ctrl, &probe, sizeof probe); |
| 396 | mutex_unlock(&stream->mutex); | ||
| 370 | 397 | ||
| 371 | /* Return the actual frame period. */ | 398 | /* Return the actual frame period. */ |
| 372 | timeperframe.numerator = probe.dwFrameInterval; | 399 | timeperframe.numerator = probe.dwFrameInterval; |
| @@ -869,15 +896,17 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) | |||
| 869 | case VIDIOC_CROPCAP: | 896 | case VIDIOC_CROPCAP: |
| 870 | { | 897 | { |
| 871 | struct v4l2_cropcap *ccap = arg; | 898 | struct v4l2_cropcap *ccap = arg; |
| 872 | struct uvc_frame *frame = stream->cur_frame; | ||
| 873 | 899 | ||
| 874 | if (ccap->type != stream->type) | 900 | if (ccap->type != stream->type) |
| 875 | return -EINVAL; | 901 | return -EINVAL; |
| 876 | 902 | ||
| 877 | ccap->bounds.left = 0; | 903 | ccap->bounds.left = 0; |
| 878 | ccap->bounds.top = 0; | 904 | ccap->bounds.top = 0; |
| 879 | ccap->bounds.width = frame->wWidth; | 905 | |
| 880 | ccap->bounds.height = frame->wHeight; | 906 | mutex_lock(&stream->mutex); |
| 907 | ccap->bounds.width = stream->cur_frame->wWidth; | ||
| 908 | ccap->bounds.height = stream->cur_frame->wHeight; | ||
| 909 | mutex_unlock(&stream->mutex); | ||
| 881 | 910 | ||
| 882 | ccap->defrect = ccap->bounds; | 911 | ccap->defrect = ccap->bounds; |
| 883 | 912 | ||
| @@ -894,8 +923,6 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) | |||
| 894 | case VIDIOC_REQBUFS: | 923 | case VIDIOC_REQBUFS: |
| 895 | { | 924 | { |
| 896 | struct v4l2_requestbuffers *rb = arg; | 925 | struct v4l2_requestbuffers *rb = arg; |
| 897 | unsigned int bufsize = | ||
| 898 | stream->ctrl.dwMaxVideoFrameSize; | ||
| 899 | 926 | ||
| 900 | if (rb->type != stream->type || | 927 | if (rb->type != stream->type || |
| 901 | rb->memory != V4L2_MEMORY_MMAP) | 928 | rb->memory != V4L2_MEMORY_MMAP) |
| @@ -904,7 +931,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) | |||
| 904 | if ((ret = uvc_acquire_privileges(handle)) < 0) | 931 | if ((ret = uvc_acquire_privileges(handle)) < 0) |
| 905 | return ret; | 932 | return ret; |
| 906 | 933 | ||
| 907 | ret = uvc_alloc_buffers(&stream->queue, rb->count, bufsize); | 934 | mutex_lock(&stream->mutex); |
| 935 | ret = uvc_alloc_buffers(&stream->queue, rb->count, | ||
| 936 | stream->ctrl.dwMaxVideoFrameSize); | ||
| 937 | mutex_unlock(&stream->mutex); | ||
| 908 | if (ret < 0) | 938 | if (ret < 0) |
| 909 | return ret; | 939 | return ret; |
| 910 | 940 | ||
| @@ -952,7 +982,9 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) | |||
| 952 | if (!uvc_has_privileges(handle)) | 982 | if (!uvc_has_privileges(handle)) |
| 953 | return -EBUSY; | 983 | return -EBUSY; |
| 954 | 984 | ||
| 985 | mutex_lock(&stream->mutex); | ||
| 955 | ret = uvc_video_enable(stream, 1); | 986 | ret = uvc_video_enable(stream, 1); |
| 987 | mutex_unlock(&stream->mutex); | ||
| 956 | if (ret < 0) | 988 | if (ret < 0) |
| 957 | return ret; | 989 | return ret; |
| 958 | break; | 990 | break; |
diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c index 5555f010283..5673d673504 100644 --- a/drivers/media/video/uvc/uvc_video.c +++ b/drivers/media/video/uvc/uvc_video.c | |||
| @@ -293,8 +293,6 @@ int uvc_probe_video(struct uvc_streaming *stream, | |||
| 293 | unsigned int i; | 293 | unsigned int i; |
| 294 | int ret; | 294 | int ret; |
| 295 | 295 | ||
| 296 | mutex_lock(&stream->mutex); | ||
| 297 | |||
| 298 | /* Perform probing. The device should adjust the requested values | 296 | /* Perform probing. The device should adjust the requested values |
| 299 | * according to its capabilities. However, some devices, namely the | 297 | * according to its capabilities. However, some devices, namely the |
| 300 | * first generation UVC Logitech webcams, don't implement the Video | 298 | * first generation UVC Logitech webcams, don't implement the Video |
| @@ -346,7 +344,6 @@ int uvc_probe_video(struct uvc_streaming *stream, | |||
| 346 | } | 344 | } |
| 347 | 345 | ||
| 348 | done: | 346 | done: |
| 349 | mutex_unlock(&stream->mutex); | ||
| 350 | return ret; | 347 | return ret; |
| 351 | } | 348 | } |
| 352 | 349 | ||
diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h index ea893bc0df0..45f01e7e13d 100644 --- a/drivers/media/video/uvc/uvcvideo.h +++ b/drivers/media/video/uvc/uvcvideo.h | |||
| @@ -436,7 +436,9 @@ struct uvc_streaming { | |||
| 436 | struct uvc_streaming_control ctrl; | 436 | struct uvc_streaming_control ctrl; |
| 437 | struct uvc_format *cur_format; | 437 | struct uvc_format *cur_format; |
| 438 | struct uvc_frame *cur_frame; | 438 | struct uvc_frame *cur_frame; |
| 439 | 439 | /* Protect access to ctrl, cur_format, cur_frame and hardware video | |
| 440 | * probe control. | ||
| 441 | */ | ||
| 440 | struct mutex mutex; | 442 | struct mutex mutex; |
| 441 | 443 | ||
| 442 | unsigned int frozen : 1; | 444 | unsigned int frozen : 1; |
