aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/uvc
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@skynet.be>2008-12-16 04:46:32 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2008-12-30 06:39:11 -0500
commit9768352ac1f9cc3aae675adb299452bd28a54734 (patch)
treeeac3d5caefbcccae4b6cdb877aa86b581ea1e7ba /drivers/media/video/uvc
parent6df126f834c7f6972528cba43604ce0c97329886 (diff)
V4L/DVB (9903): uvcvideo: V4L2 zoom controls support
Add support for absolute and continuous zoom controls (mapped to absolute and relative UVC zoom controls). Signed-off-by: Laurent Pinchart <laurent.pinchart@skynet.be> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/uvc')
-rw-r--r--drivers/media/video/uvc/uvc_ctrl.c76
-rw-r--r--drivers/media/video/uvc/uvc_v4l2.c4
-rw-r--r--drivers/media/video/uvc/uvcvideo.h5
3 files changed, 71 insertions, 14 deletions
diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c
index 335cb00e595b..2208165aa6f0 100644
--- a/drivers/media/video/uvc/uvc_ctrl.c
+++ b/drivers/media/video/uvc/uvc_ctrl.c
@@ -327,6 +327,31 @@ static struct uvc_menu_info exposure_auto_controls[] = {
327 { 8, "Aperture Priority Mode" }, 327 { 8, "Aperture Priority Mode" },
328}; 328};
329 329
330static __s32 uvc_ctrl_get_zoom(struct uvc_control_mapping *mapping,
331 __u8 query, const __u8 *data)
332{
333 __s8 zoom = (__s8)data[0];
334
335 switch (query) {
336 case GET_CUR:
337 return (zoom == 0) ? 0 : (zoom > 0 ? data[2] : -data[2]);
338
339 case GET_MIN:
340 case GET_MAX:
341 case GET_RES:
342 case GET_DEF:
343 default:
344 return data[2];
345 }
346}
347
348static void uvc_ctrl_set_zoom(struct uvc_control_mapping *mapping,
349 __s32 value, __u8 *data)
350{
351 data[0] = value == 0 ? 0 : (value > 0) ? 1 : 0xff;
352 data[2] = min(abs(value), 0xff);
353}
354
330static struct uvc_control_mapping uvc_ctrl_mappings[] = { 355static struct uvc_control_mapping uvc_ctrl_mappings[] = {
331 { 356 {
332 .id = V4L2_CID_BRIGHTNESS, 357 .id = V4L2_CID_BRIGHTNESS,
@@ -533,6 +558,28 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = {
533 .data_type = UVC_CTRL_DATA_TYPE_BOOLEAN, 558 .data_type = UVC_CTRL_DATA_TYPE_BOOLEAN,
534 }, 559 },
535 { 560 {
561 .id = V4L2_CID_ZOOM_ABSOLUTE,
562 .name = "Zoom, Absolute",
563 .entity = UVC_GUID_UVC_CAMERA,
564 .selector = CT_ZOOM_ABSOLUTE_CONTROL,
565 .size = 16,
566 .offset = 0,
567 .v4l2_type = V4L2_CTRL_TYPE_INTEGER,
568 .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED,
569 },
570 {
571 .id = V4L2_CID_ZOOM_CONTINUOUS,
572 .name = "Zoom, Continuous",
573 .entity = UVC_GUID_UVC_CAMERA,
574 .selector = CT_ZOOM_RELATIVE_CONTROL,
575 .size = 0,
576 .offset = 0,
577 .v4l2_type = V4L2_CTRL_TYPE_INTEGER,
578 .data_type = UVC_CTRL_DATA_TYPE_SIGNED,
579 .get = uvc_ctrl_get_zoom,
580 .set = uvc_ctrl_set_zoom,
581 },
582 {
536 .id = V4L2_CID_PRIVACY, 583 .id = V4L2_CID_PRIVACY,
537 .name = "Privacy", 584 .name = "Privacy",
538 .entity = UVC_GUID_UVC_CAMERA, 585 .entity = UVC_GUID_UVC_CAMERA,
@@ -568,8 +615,8 @@ static inline void uvc_clear_bit(__u8 *data, int bit)
568 * a signed 32bit integer. Sign extension will be performed if the mapping 615 * a signed 32bit integer. Sign extension will be performed if the mapping
569 * references a signed data type. 616 * references a signed data type.
570 */ 617 */
571static __s32 uvc_get_le_value(const __u8 *data, 618static __s32 uvc_get_le_value(struct uvc_control_mapping *mapping,
572 struct uvc_control_mapping *mapping) 619 __u8 query, const __u8 *data)
573{ 620{
574 int bits = mapping->size; 621 int bits = mapping->size;
575 int offset = mapping->offset; 622 int offset = mapping->offset;
@@ -598,8 +645,8 @@ static __s32 uvc_get_le_value(const __u8 *data,
598/* Set the bit string specified by mapping->offset and mapping->size 645/* Set the bit string specified by mapping->offset and mapping->size
599 * in the little-endian data stored at 'data' to the value 'value'. 646 * in the little-endian data stored at 'data' to the value 'value'.
600 */ 647 */
601static void uvc_set_le_value(__s32 value, __u8 *data, 648static void uvc_set_le_value(struct uvc_control_mapping *mapping,
602 struct uvc_control_mapping *mapping) 649 __s32 value, __u8 *data)
603{ 650{
604 int bits = mapping->size; 651 int bits = mapping->size;
605 int offset = mapping->offset; 652 int offset = mapping->offset;
@@ -751,7 +798,7 @@ int uvc_query_v4l2_ctrl(struct uvc_video_device *video,
751 video->dev->intfnum, ctrl->info->selector, 798 video->dev->intfnum, ctrl->info->selector,
752 data, ctrl->info->size)) < 0) 799 data, ctrl->info->size)) < 0)
753 goto out; 800 goto out;
754 v4l2_ctrl->default_value = uvc_get_le_value(data, mapping); 801 v4l2_ctrl->default_value = mapping->get(mapping, GET_DEF, data);
755 } 802 }
756 803
757 switch (mapping->v4l2_type) { 804 switch (mapping->v4l2_type) {
@@ -787,21 +834,21 @@ int uvc_query_v4l2_ctrl(struct uvc_video_device *video,
787 video->dev->intfnum, ctrl->info->selector, 834 video->dev->intfnum, ctrl->info->selector,
788 data, ctrl->info->size)) < 0) 835 data, ctrl->info->size)) < 0)
789 goto out; 836 goto out;
790 v4l2_ctrl->minimum = uvc_get_le_value(data, mapping); 837 v4l2_ctrl->minimum = mapping->get(mapping, GET_MIN, data);
791 } 838 }
792 if (ctrl->info->flags & UVC_CONTROL_GET_MAX) { 839 if (ctrl->info->flags & UVC_CONTROL_GET_MAX) {
793 if ((ret = uvc_query_ctrl(video->dev, GET_MAX, ctrl->entity->id, 840 if ((ret = uvc_query_ctrl(video->dev, GET_MAX, ctrl->entity->id,
794 video->dev->intfnum, ctrl->info->selector, 841 video->dev->intfnum, ctrl->info->selector,
795 data, ctrl->info->size)) < 0) 842 data, ctrl->info->size)) < 0)
796 goto out; 843 goto out;
797 v4l2_ctrl->maximum = uvc_get_le_value(data, mapping); 844 v4l2_ctrl->maximum = mapping->get(mapping, GET_MAX, data);
798 } 845 }
799 if (ctrl->info->flags & UVC_CONTROL_GET_RES) { 846 if (ctrl->info->flags & UVC_CONTROL_GET_RES) {
800 if ((ret = uvc_query_ctrl(video->dev, GET_RES, ctrl->entity->id, 847 if ((ret = uvc_query_ctrl(video->dev, GET_RES, ctrl->entity->id,
801 video->dev->intfnum, ctrl->info->selector, 848 video->dev->intfnum, ctrl->info->selector,
802 data, ctrl->info->size)) < 0) 849 data, ctrl->info->size)) < 0)
803 goto out; 850 goto out;
804 v4l2_ctrl->step = uvc_get_le_value(data, mapping); 851 v4l2_ctrl->step = mapping->get(mapping, GET_RES, data);
805 } 852 }
806 853
807 ret = 0; 854 ret = 0;
@@ -938,8 +985,8 @@ int uvc_ctrl_get(struct uvc_video_device *video,
938 ctrl->loaded = 1; 985 ctrl->loaded = 1;
939 } 986 }
940 987
941 xctrl->value = uvc_get_le_value( 988 xctrl->value = mapping->get(mapping, GET_CUR,
942 uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), mapping); 989 uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT));
943 990
944 if (mapping->v4l2_type == V4L2_CTRL_TYPE_MENU) { 991 if (mapping->v4l2_type == V4L2_CTRL_TYPE_MENU) {
945 menu = mapping->menu_info; 992 menu = mapping->menu_info;
@@ -995,8 +1042,8 @@ int uvc_ctrl_set(struct uvc_video_device *video,
995 ctrl->info->size); 1042 ctrl->info->size);
996 } 1043 }
997 1044
998 uvc_set_le_value(value, 1045 mapping->set(mapping, value,
999 uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), mapping); 1046 uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT));
1000 1047
1001 ctrl->dirty = 1; 1048 ctrl->dirty = 1;
1002 ctrl->modified = 1; 1049 ctrl->modified = 1;
@@ -1272,6 +1319,11 @@ int uvc_ctrl_add_mapping(struct uvc_control_mapping *mapping)
1272 struct uvc_control_mapping *map; 1319 struct uvc_control_mapping *map;
1273 int ret = -EINVAL; 1320 int ret = -EINVAL;
1274 1321
1322 if (mapping->get == NULL)
1323 mapping->get = uvc_get_le_value;
1324 if (mapping->set == NULL)
1325 mapping->set = uvc_set_le_value;
1326
1275 if (mapping->id & ~V4L2_CTRL_ID_MASK) { 1327 if (mapping->id & ~V4L2_CTRL_ID_MASK) {
1276 uvc_trace(UVC_TRACE_CONTROL, "Can't add mapping '%s' with " 1328 uvc_trace(UVC_TRACE_CONTROL, "Can't add mapping '%s' with "
1277 "invalid control id 0x%08x\n", mapping->name, 1329 "invalid control id 0x%08x\n", mapping->name,
diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c
index 7b1c1363583c..2e1fd1b2a619 100644
--- a/drivers/media/video/uvc/uvc_v4l2.c
+++ b/drivers/media/video/uvc/uvc_v4l2.c
@@ -914,7 +914,7 @@ static int uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
914 if (!capable(CAP_SYS_ADMIN)) 914 if (!capable(CAP_SYS_ADMIN))
915 return -EPERM; 915 return -EPERM;
916 916
917 info = kmalloc(sizeof *info, GFP_KERNEL); 917 info = kzalloc(sizeof *info, GFP_KERNEL);
918 if (info == NULL) 918 if (info == NULL)
919 return -ENOMEM; 919 return -ENOMEM;
920 920
@@ -941,7 +941,7 @@ static int uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
941 if (!capable(CAP_SYS_ADMIN)) 941 if (!capable(CAP_SYS_ADMIN))
942 return -EPERM; 942 return -EPERM;
943 943
944 map = kmalloc(sizeof *map, GFP_KERNEL); 944 map = kzalloc(sizeof *map, GFP_KERNEL);
945 if (map == NULL) 945 if (map == NULL)
946 return -ENOMEM; 946 return -ENOMEM;
947 947
diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h
index 00d593776b86..2a5bdacbaf27 100644
--- a/drivers/media/video/uvc/uvcvideo.h
+++ b/drivers/media/video/uvc/uvcvideo.h
@@ -384,6 +384,11 @@ struct uvc_control_mapping {
384 384
385 struct uvc_menu_info *menu_info; 385 struct uvc_menu_info *menu_info;
386 __u32 menu_count; 386 __u32 menu_count;
387
388 __s32 (*get) (struct uvc_control_mapping *mapping, __u8 query,
389 const __u8 *data);
390 void (*set) (struct uvc_control_mapping *mapping, __s32 value,
391 __u8 *data);
387}; 392};
388 393
389struct uvc_control { 394struct uvc_control {