aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/usb/uvc/uvc_v4l2.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/usb/uvc/uvc_v4l2.c')
-rw-r--r--drivers/media/usb/uvc/uvc_v4l2.c141
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 */
108static __u32 uvc_try_frame_interval(struct uvc_frame *frame, __u32 interval) 108static 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
140static __u32 uvc_v4l2_get_bytesperline(const struct uvc_format *format, 140static 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:
336static int uvc_v4l2_get_streamparm(struct uvc_streaming *stream, 336static 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
1263struct uvc_xu_control_mapping32 { 1302struct 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
1280static int uvc_v4l2_get_xu_mapping(struct uvc_xu_control_mapping *kp, 1319static 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
1312struct uvc_xu_control_query32 { 1351struct 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