diff options
Diffstat (limited to 'drivers/media/usb/uvc/uvc_v4l2.c')
-rw-r--r-- | drivers/media/usb/uvc/uvc_v4l2.c | 141 |
1 files changed, 90 insertions, 51 deletions
diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c index a13ad4e178be..bd32914259ae 100644 --- a/drivers/media/usb/uvc/uvc_v4l2.c +++ b/drivers/media/usb/uvc/uvc_v4l2.c | |||
@@ -40,13 +40,13 @@ static int uvc_ioctl_ctrl_map(struct uvc_video_chain *chain, | |||
40 | unsigned int size; | 40 | unsigned int size; |
41 | int ret; | 41 | int ret; |
42 | 42 | ||
43 | map = kzalloc(sizeof *map, GFP_KERNEL); | 43 | map = kzalloc(sizeof(*map), GFP_KERNEL); |
44 | if (map == NULL) | 44 | if (map == NULL) |
45 | return -ENOMEM; | 45 | return -ENOMEM; |
46 | 46 | ||
47 | map->id = xmap->id; | 47 | map->id = xmap->id; |
48 | memcpy(map->name, xmap->name, sizeof map->name); | 48 | memcpy(map->name, xmap->name, sizeof(map->name)); |
49 | memcpy(map->entity, xmap->entity, sizeof map->entity); | 49 | memcpy(map->entity, xmap->entity, sizeof(map->entity)); |
50 | map->selector = xmap->selector; | 50 | map->selector = xmap->selector; |
51 | map->size = xmap->size; | 51 | map->size = xmap->size; |
52 | map->offset = xmap->offset; | 52 | map->offset = xmap->offset; |
@@ -105,12 +105,12 @@ free_map: | |||
105 | * the Video Probe and Commit negotiation, but some hardware don't implement | 105 | * the Video Probe and Commit negotiation, but some hardware don't implement |
106 | * that feature. | 106 | * that feature. |
107 | */ | 107 | */ |
108 | static __u32 uvc_try_frame_interval(struct uvc_frame *frame, __u32 interval) | 108 | static u32 uvc_try_frame_interval(struct uvc_frame *frame, u32 interval) |
109 | { | 109 | { |
110 | unsigned int i; | 110 | unsigned int i; |
111 | 111 | ||
112 | if (frame->bFrameIntervalType) { | 112 | if (frame->bFrameIntervalType) { |
113 | __u32 best = -1, dist; | 113 | u32 best = -1, dist; |
114 | 114 | ||
115 | for (i = 0; i < frame->bFrameIntervalType; ++i) { | 115 | for (i = 0; i < frame->bFrameIntervalType; ++i) { |
116 | dist = interval > frame->dwFrameInterval[i] | 116 | dist = interval > frame->dwFrameInterval[i] |
@@ -125,9 +125,9 @@ static __u32 uvc_try_frame_interval(struct uvc_frame *frame, __u32 interval) | |||
125 | 125 | ||
126 | interval = frame->dwFrameInterval[i-1]; | 126 | interval = frame->dwFrameInterval[i-1]; |
127 | } else { | 127 | } else { |
128 | const __u32 min = frame->dwFrameInterval[0]; | 128 | const u32 min = frame->dwFrameInterval[0]; |
129 | const __u32 max = frame->dwFrameInterval[1]; | 129 | const u32 max = frame->dwFrameInterval[1]; |
130 | const __u32 step = frame->dwFrameInterval[2]; | 130 | const u32 step = frame->dwFrameInterval[2]; |
131 | 131 | ||
132 | interval = min + (interval - min + step/2) / step * step; | 132 | interval = min + (interval - min + step/2) / step * step; |
133 | if (interval > max) | 133 | if (interval > max) |
@@ -137,7 +137,7 @@ static __u32 uvc_try_frame_interval(struct uvc_frame *frame, __u32 interval) | |||
137 | return interval; | 137 | return interval; |
138 | } | 138 | } |
139 | 139 | ||
140 | static __u32 uvc_v4l2_get_bytesperline(const struct uvc_format *format, | 140 | static u32 uvc_v4l2_get_bytesperline(const struct uvc_format *format, |
141 | const struct uvc_frame *frame) | 141 | const struct uvc_frame *frame) |
142 | { | 142 | { |
143 | switch (format->fcc) { | 143 | switch (format->fcc) { |
@@ -158,17 +158,17 @@ static int uvc_v4l2_try_format(struct uvc_streaming *stream, | |||
158 | { | 158 | { |
159 | struct uvc_format *format = NULL; | 159 | struct uvc_format *format = NULL; |
160 | struct uvc_frame *frame = NULL; | 160 | struct uvc_frame *frame = NULL; |
161 | __u16 rw, rh; | 161 | u16 rw, rh; |
162 | unsigned int d, maxd; | 162 | unsigned int d, maxd; |
163 | unsigned int i; | 163 | unsigned int i; |
164 | __u32 interval; | 164 | u32 interval; |
165 | int ret = 0; | 165 | int ret = 0; |
166 | __u8 *fcc; | 166 | u8 *fcc; |
167 | 167 | ||
168 | if (fmt->type != stream->type) | 168 | if (fmt->type != stream->type) |
169 | return -EINVAL; | 169 | return -EINVAL; |
170 | 170 | ||
171 | fcc = (__u8 *)&fmt->fmt.pix.pixelformat; | 171 | fcc = (u8 *)&fmt->fmt.pix.pixelformat; |
172 | uvc_trace(UVC_TRACE_FORMAT, "Trying format 0x%08x (%c%c%c%c): %ux%u.\n", | 172 | uvc_trace(UVC_TRACE_FORMAT, "Trying format 0x%08x (%c%c%c%c): %ux%u.\n", |
173 | fmt->fmt.pix.pixelformat, | 173 | fmt->fmt.pix.pixelformat, |
174 | fcc[0], fcc[1], fcc[2], fcc[3], | 174 | fcc[0], fcc[1], fcc[2], fcc[3], |
@@ -197,8 +197,8 @@ static int uvc_v4l2_try_format(struct uvc_streaming *stream, | |||
197 | maxd = (unsigned int)-1; | 197 | maxd = (unsigned int)-1; |
198 | 198 | ||
199 | for (i = 0; i < format->nframes; ++i) { | 199 | for (i = 0; i < format->nframes; ++i) { |
200 | __u16 w = format->frame[i].wWidth; | 200 | u16 w = format->frame[i].wWidth; |
201 | __u16 h = format->frame[i].wHeight; | 201 | u16 h = format->frame[i].wHeight; |
202 | 202 | ||
203 | d = min(w, rw) * min(h, rh); | 203 | d = min(w, rw) * min(h, rh); |
204 | d = w*h + rw*rh - 2*d; | 204 | d = w*h + rw*rh - 2*d; |
@@ -224,7 +224,7 @@ static int uvc_v4l2_try_format(struct uvc_streaming *stream, | |||
224 | (100000000/interval)%10); | 224 | (100000000/interval)%10); |
225 | 225 | ||
226 | /* Set the format index, frame index and frame interval. */ | 226 | /* Set the format index, frame index and frame interval. */ |
227 | memset(probe, 0, sizeof *probe); | 227 | memset(probe, 0, sizeof(*probe)); |
228 | probe->bmHint = 1; /* dwFrameInterval */ | 228 | probe->bmHint = 1; /* dwFrameInterval */ |
229 | probe->bFormatIndex = format->index; | 229 | probe->bFormatIndex = format->index; |
230 | probe->bFrameIndex = frame->bFrameIndex; | 230 | probe->bFrameIndex = frame->bFrameIndex; |
@@ -336,7 +336,7 @@ done: | |||
336 | static int uvc_v4l2_get_streamparm(struct uvc_streaming *stream, | 336 | static int uvc_v4l2_get_streamparm(struct uvc_streaming *stream, |
337 | struct v4l2_streamparm *parm) | 337 | struct v4l2_streamparm *parm) |
338 | { | 338 | { |
339 | uint32_t numerator, denominator; | 339 | u32 numerator, denominator; |
340 | 340 | ||
341 | if (parm->type != stream->type) | 341 | if (parm->type != stream->type) |
342 | return -EINVAL; | 342 | return -EINVAL; |
@@ -348,7 +348,7 @@ static int uvc_v4l2_get_streamparm(struct uvc_streaming *stream, | |||
348 | denominator = 10000000; | 348 | denominator = 10000000; |
349 | uvc_simplify_fraction(&numerator, &denominator, 8, 333); | 349 | uvc_simplify_fraction(&numerator, &denominator, 8, 333); |
350 | 350 | ||
351 | memset(parm, 0, sizeof *parm); | 351 | memset(parm, 0, sizeof(*parm)); |
352 | parm->type = stream->type; | 352 | parm->type = stream->type; |
353 | 353 | ||
354 | if (stream->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { | 354 | if (stream->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { |
@@ -373,7 +373,10 @@ static int uvc_v4l2_set_streamparm(struct uvc_streaming *stream, | |||
373 | { | 373 | { |
374 | struct uvc_streaming_control probe; | 374 | struct uvc_streaming_control probe; |
375 | struct v4l2_fract timeperframe; | 375 | struct v4l2_fract timeperframe; |
376 | uint32_t interval; | 376 | struct uvc_format *format; |
377 | struct uvc_frame *frame; | ||
378 | u32 interval, maxd; | ||
379 | unsigned int i; | ||
377 | int ret; | 380 | int ret; |
378 | 381 | ||
379 | if (parm->type != stream->type) | 382 | if (parm->type != stream->type) |
@@ -396,9 +399,33 @@ static int uvc_v4l2_set_streamparm(struct uvc_streaming *stream, | |||
396 | return -EBUSY; | 399 | return -EBUSY; |
397 | } | 400 | } |
398 | 401 | ||
402 | format = stream->cur_format; | ||
403 | frame = stream->cur_frame; | ||
399 | probe = stream->ctrl; | 404 | probe = stream->ctrl; |
400 | probe.dwFrameInterval = | 405 | probe.dwFrameInterval = uvc_try_frame_interval(frame, interval); |
401 | uvc_try_frame_interval(stream->cur_frame, interval); | 406 | maxd = abs((s32)probe.dwFrameInterval - interval); |
407 | |||
408 | /* Try frames with matching size to find the best frame interval. */ | ||
409 | for (i = 0; i < format->nframes && maxd != 0; i++) { | ||
410 | u32 d, ival; | ||
411 | |||
412 | if (&format->frame[i] == stream->cur_frame) | ||
413 | continue; | ||
414 | |||
415 | if (format->frame[i].wWidth != stream->cur_frame->wWidth || | ||
416 | format->frame[i].wHeight != stream->cur_frame->wHeight) | ||
417 | continue; | ||
418 | |||
419 | ival = uvc_try_frame_interval(&format->frame[i], interval); | ||
420 | d = abs((s32)ival - interval); | ||
421 | if (d >= maxd) | ||
422 | continue; | ||
423 | |||
424 | frame = &format->frame[i]; | ||
425 | probe.bFrameIndex = frame->bFrameIndex; | ||
426 | probe.dwFrameInterval = ival; | ||
427 | maxd = d; | ||
428 | } | ||
402 | 429 | ||
403 | /* Probe the device with the new settings. */ | 430 | /* Probe the device with the new settings. */ |
404 | ret = uvc_probe_video(stream, &probe); | 431 | ret = uvc_probe_video(stream, &probe); |
@@ -408,6 +435,7 @@ static int uvc_v4l2_set_streamparm(struct uvc_streaming *stream, | |||
408 | } | 435 | } |
409 | 436 | ||
410 | stream->ctrl = probe; | 437 | stream->ctrl = probe; |
438 | stream->cur_frame = frame; | ||
411 | mutex_unlock(&stream->mutex); | 439 | mutex_unlock(&stream->mutex); |
412 | 440 | ||
413 | /* Return the actual frame period. */ | 441 | /* Return the actual frame period. */ |
@@ -498,7 +526,7 @@ static int uvc_v4l2_open(struct file *file) | |||
498 | return ret; | 526 | return ret; |
499 | 527 | ||
500 | /* Create the device handle. */ | 528 | /* Create the device handle. */ |
501 | handle = kzalloc(sizeof *handle, GFP_KERNEL); | 529 | handle = kzalloc(sizeof(*handle), GFP_KERNEL); |
502 | if (handle == NULL) { | 530 | if (handle == NULL) { |
503 | usb_autopm_put_interface(stream->dev->intf); | 531 | usb_autopm_put_interface(stream->dev->intf); |
504 | return -ENOMEM; | 532 | return -ENOMEM; |
@@ -577,7 +605,7 @@ static int uvc_ioctl_enum_fmt(struct uvc_streaming *stream, | |||
577 | { | 605 | { |
578 | struct uvc_format *format; | 606 | struct uvc_format *format; |
579 | enum v4l2_buf_type type = fmt->type; | 607 | enum v4l2_buf_type type = fmt->type; |
580 | __u32 index = fmt->index; | 608 | u32 index = fmt->index; |
581 | 609 | ||
582 | if (fmt->type != stream->type || fmt->index >= stream->nformats) | 610 | if (fmt->type != stream->type || fmt->index >= stream->nformats) |
583 | return -EINVAL; | 611 | return -EINVAL; |
@@ -1145,8 +1173,9 @@ static int uvc_ioctl_enum_framesizes(struct file *file, void *fh, | |||
1145 | struct uvc_fh *handle = fh; | 1173 | struct uvc_fh *handle = fh; |
1146 | struct uvc_streaming *stream = handle->stream; | 1174 | struct uvc_streaming *stream = handle->stream; |
1147 | struct uvc_format *format = NULL; | 1175 | struct uvc_format *format = NULL; |
1148 | struct uvc_frame *frame; | 1176 | struct uvc_frame *frame = NULL; |
1149 | int i; | 1177 | unsigned int index; |
1178 | unsigned int i; | ||
1150 | 1179 | ||
1151 | /* Look for the given pixel format */ | 1180 | /* Look for the given pixel format */ |
1152 | for (i = 0; i < stream->nformats; i++) { | 1181 | for (i = 0; i < stream->nformats; i++) { |
@@ -1158,10 +1187,20 @@ static int uvc_ioctl_enum_framesizes(struct file *file, void *fh, | |||
1158 | if (format == NULL) | 1187 | if (format == NULL) |
1159 | return -EINVAL; | 1188 | return -EINVAL; |
1160 | 1189 | ||
1161 | if (fsize->index >= format->nframes) | 1190 | /* Skip duplicate frame sizes */ |
1191 | for (i = 0, index = 0; i < format->nframes; i++) { | ||
1192 | if (frame && frame->wWidth == format->frame[i].wWidth && | ||
1193 | frame->wHeight == format->frame[i].wHeight) | ||
1194 | continue; | ||
1195 | frame = &format->frame[i]; | ||
1196 | if (index == fsize->index) | ||
1197 | break; | ||
1198 | index++; | ||
1199 | } | ||
1200 | |||
1201 | if (i == format->nframes) | ||
1162 | return -EINVAL; | 1202 | return -EINVAL; |
1163 | 1203 | ||
1164 | frame = &format->frame[fsize->index]; | ||
1165 | fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; | 1204 | fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; |
1166 | fsize->discrete.width = frame->wWidth; | 1205 | fsize->discrete.width = frame->wWidth; |
1167 | fsize->discrete.height = frame->wHeight; | 1206 | fsize->discrete.height = frame->wHeight; |
@@ -1175,7 +1214,9 @@ static int uvc_ioctl_enum_frameintervals(struct file *file, void *fh, | |||
1175 | struct uvc_streaming *stream = handle->stream; | 1214 | struct uvc_streaming *stream = handle->stream; |
1176 | struct uvc_format *format = NULL; | 1215 | struct uvc_format *format = NULL; |
1177 | struct uvc_frame *frame = NULL; | 1216 | struct uvc_frame *frame = NULL; |
1178 | int i; | 1217 | unsigned int nintervals; |
1218 | unsigned int index; | ||
1219 | unsigned int i; | ||
1179 | 1220 | ||
1180 | /* Look for the given pixel format and frame size */ | 1221 | /* Look for the given pixel format and frame size */ |
1181 | for (i = 0; i < stream->nformats; i++) { | 1222 | for (i = 0; i < stream->nformats; i++) { |
@@ -1187,30 +1228,28 @@ static int uvc_ioctl_enum_frameintervals(struct file *file, void *fh, | |||
1187 | if (format == NULL) | 1228 | if (format == NULL) |
1188 | return -EINVAL; | 1229 | return -EINVAL; |
1189 | 1230 | ||
1231 | index = fival->index; | ||
1190 | for (i = 0; i < format->nframes; i++) { | 1232 | for (i = 0; i < format->nframes; i++) { |
1191 | if (format->frame[i].wWidth == fival->width && | 1233 | if (format->frame[i].wWidth == fival->width && |
1192 | format->frame[i].wHeight == fival->height) { | 1234 | format->frame[i].wHeight == fival->height) { |
1193 | frame = &format->frame[i]; | 1235 | frame = &format->frame[i]; |
1194 | break; | 1236 | nintervals = frame->bFrameIntervalType ?: 1; |
1237 | if (index < nintervals) | ||
1238 | break; | ||
1239 | index -= nintervals; | ||
1195 | } | 1240 | } |
1196 | } | 1241 | } |
1197 | if (frame == NULL) | 1242 | if (i == format->nframes) |
1198 | return -EINVAL; | 1243 | return -EINVAL; |
1199 | 1244 | ||
1200 | if (frame->bFrameIntervalType) { | 1245 | if (frame->bFrameIntervalType) { |
1201 | if (fival->index >= frame->bFrameIntervalType) | ||
1202 | return -EINVAL; | ||
1203 | |||
1204 | fival->type = V4L2_FRMIVAL_TYPE_DISCRETE; | 1246 | fival->type = V4L2_FRMIVAL_TYPE_DISCRETE; |
1205 | fival->discrete.numerator = | 1247 | fival->discrete.numerator = |
1206 | frame->dwFrameInterval[fival->index]; | 1248 | frame->dwFrameInterval[index]; |
1207 | fival->discrete.denominator = 10000000; | 1249 | fival->discrete.denominator = 10000000; |
1208 | uvc_simplify_fraction(&fival->discrete.numerator, | 1250 | uvc_simplify_fraction(&fival->discrete.numerator, |
1209 | &fival->discrete.denominator, 8, 333); | 1251 | &fival->discrete.denominator, 8, 333); |
1210 | } else { | 1252 | } else { |
1211 | if (fival->index) | ||
1212 | return -EINVAL; | ||
1213 | |||
1214 | fival->type = V4L2_FRMIVAL_TYPE_STEPWISE; | 1253 | fival->type = V4L2_FRMIVAL_TYPE_STEPWISE; |
1215 | fival->stepwise.min.numerator = frame->dwFrameInterval[0]; | 1254 | fival->stepwise.min.numerator = frame->dwFrameInterval[0]; |
1216 | fival->stepwise.min.denominator = 10000000; | 1255 | fival->stepwise.min.denominator = 10000000; |
@@ -1261,20 +1300,20 @@ static long uvc_ioctl_default(struct file *file, void *fh, bool valid_prio, | |||
1261 | 1300 | ||
1262 | #ifdef CONFIG_COMPAT | 1301 | #ifdef CONFIG_COMPAT |
1263 | struct uvc_xu_control_mapping32 { | 1302 | struct uvc_xu_control_mapping32 { |
1264 | __u32 id; | 1303 | u32 id; |
1265 | __u8 name[32]; | 1304 | u8 name[32]; |
1266 | __u8 entity[16]; | 1305 | u8 entity[16]; |
1267 | __u8 selector; | 1306 | u8 selector; |
1268 | 1307 | ||
1269 | __u8 size; | 1308 | u8 size; |
1270 | __u8 offset; | 1309 | u8 offset; |
1271 | __u32 v4l2_type; | 1310 | u32 v4l2_type; |
1272 | __u32 data_type; | 1311 | u32 data_type; |
1273 | 1312 | ||
1274 | compat_caddr_t menu_info; | 1313 | compat_caddr_t menu_info; |
1275 | __u32 menu_count; | 1314 | u32 menu_count; |
1276 | 1315 | ||
1277 | __u32 reserved[4]; | 1316 | u32 reserved[4]; |
1278 | }; | 1317 | }; |
1279 | 1318 | ||
1280 | static int uvc_v4l2_get_xu_mapping(struct uvc_xu_control_mapping *kp, | 1319 | static int uvc_v4l2_get_xu_mapping(struct uvc_xu_control_mapping *kp, |
@@ -1310,10 +1349,10 @@ static int uvc_v4l2_put_xu_mapping(const struct uvc_xu_control_mapping *kp, | |||
1310 | } | 1349 | } |
1311 | 1350 | ||
1312 | struct uvc_xu_control_query32 { | 1351 | struct uvc_xu_control_query32 { |
1313 | __u8 unit; | 1352 | u8 unit; |
1314 | __u8 selector; | 1353 | u8 selector; |
1315 | __u8 query; | 1354 | u8 query; |
1316 | __u16 size; | 1355 | u16 size; |
1317 | compat_caddr_t data; | 1356 | compat_caddr_t data; |
1318 | }; | 1357 | }; |
1319 | 1358 | ||