diff options
author | Hans Verkuil <hverkuil@xs4all.nl> | 2011-01-23 09:33:16 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-03-21 19:31:50 -0400 |
commit | 7e996afa81f71ade7870eb26b1b17350b4395646 (patch) | |
tree | e3e953b08e91f5805cd8d3e5acb646af84e7b75d | |
parent | 0eb73de019da80facad559c8a5ef21a4b357d8d5 (diff) |
[media] vivi: convert to the control framework and add test controls
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | drivers/media/video/vivi.c | 228 |
1 files changed, 139 insertions, 89 deletions
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 9ed3831b34bd..66ce69e2833b 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <media/videobuf2-vmalloc.h> | 30 | #include <media/videobuf2-vmalloc.h> |
31 | #include <media/v4l2-device.h> | 31 | #include <media/v4l2-device.h> |
32 | #include <media/v4l2-ioctl.h> | 32 | #include <media/v4l2-ioctl.h> |
33 | #include <media/v4l2-ctrls.h> | ||
33 | #include <media/v4l2-common.h> | 34 | #include <media/v4l2-common.h> |
34 | 35 | ||
35 | #define VIVI_MODULE_NAME "vivi" | 36 | #define VIVI_MODULE_NAME "vivi" |
@@ -158,13 +159,20 @@ static LIST_HEAD(vivi_devlist); | |||
158 | struct vivi_dev { | 159 | struct vivi_dev { |
159 | struct list_head vivi_devlist; | 160 | struct list_head vivi_devlist; |
160 | struct v4l2_device v4l2_dev; | 161 | struct v4l2_device v4l2_dev; |
162 | struct v4l2_ctrl_handler ctrl_handler; | ||
161 | 163 | ||
162 | /* controls */ | 164 | /* controls */ |
163 | int brightness; | 165 | struct v4l2_ctrl *brightness; |
164 | int contrast; | 166 | struct v4l2_ctrl *contrast; |
165 | int saturation; | 167 | struct v4l2_ctrl *saturation; |
166 | int hue; | 168 | struct v4l2_ctrl *hue; |
167 | int volume; | 169 | struct v4l2_ctrl *volume; |
170 | struct v4l2_ctrl *button; | ||
171 | struct v4l2_ctrl *boolean; | ||
172 | struct v4l2_ctrl *int32; | ||
173 | struct v4l2_ctrl *int64; | ||
174 | struct v4l2_ctrl *menu; | ||
175 | struct v4l2_ctrl *string; | ||
168 | 176 | ||
169 | spinlock_t slock; | 177 | spinlock_t slock; |
170 | struct mutex mutex; | 178 | struct mutex mutex; |
@@ -177,6 +185,7 @@ struct vivi_dev { | |||
177 | /* Several counters */ | 185 | /* Several counters */ |
178 | unsigned ms; | 186 | unsigned ms; |
179 | unsigned long jiffies; | 187 | unsigned long jiffies; |
188 | unsigned button_pressed; | ||
180 | 189 | ||
181 | int mv_count; /* Controls bars movement */ | 190 | int mv_count; /* Controls bars movement */ |
182 | 191 | ||
@@ -470,14 +479,30 @@ static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf) | |||
470 | dev->width, dev->height, dev->input); | 479 | dev->width, dev->height, dev->input); |
471 | gen_text(dev, vbuf, line++ * 16, 16, str); | 480 | gen_text(dev, vbuf, line++ * 16, 16, str); |
472 | 481 | ||
482 | mutex_lock(&dev->ctrl_handler.lock); | ||
473 | snprintf(str, sizeof(str), " brightness %3d, contrast %3d, saturation %3d, hue %d ", | 483 | snprintf(str, sizeof(str), " brightness %3d, contrast %3d, saturation %3d, hue %d ", |
474 | dev->brightness, | 484 | dev->brightness->cur.val, |
475 | dev->contrast, | 485 | dev->contrast->cur.val, |
476 | dev->saturation, | 486 | dev->saturation->cur.val, |
477 | dev->hue); | 487 | dev->hue->cur.val); |
478 | gen_text(dev, vbuf, line++ * 16, 16, str); | 488 | gen_text(dev, vbuf, line++ * 16, 16, str); |
479 | snprintf(str, sizeof(str), " volume %3d ", dev->volume); | 489 | snprintf(str, sizeof(str), " volume %3d ", dev->volume->cur.val); |
480 | gen_text(dev, vbuf, line++ * 16, 16, str); | 490 | gen_text(dev, vbuf, line++ * 16, 16, str); |
491 | snprintf(str, sizeof(str), " int32 %d, int64 %lld ", | ||
492 | dev->int32->cur.val, | ||
493 | dev->int64->cur.val64); | ||
494 | gen_text(dev, vbuf, line++ * 16, 16, str); | ||
495 | snprintf(str, sizeof(str), " boolean %d, menu %s, string \"%s\" ", | ||
496 | dev->boolean->cur.val, | ||
497 | dev->menu->qmenu[dev->menu->cur.val], | ||
498 | dev->string->cur.string); | ||
499 | mutex_unlock(&dev->ctrl_handler.lock); | ||
500 | gen_text(dev, vbuf, line++ * 16, 16, str); | ||
501 | if (dev->button_pressed) { | ||
502 | dev->button_pressed--; | ||
503 | snprintf(str, sizeof(str), " button pressed!"); | ||
504 | gen_text(dev, vbuf, line++ * 16, 16, str); | ||
505 | } | ||
481 | 506 | ||
482 | dev->mv_count += 2; | 507 | dev->mv_count += 2; |
483 | 508 | ||
@@ -957,80 +982,14 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i) | |||
957 | } | 982 | } |
958 | 983 | ||
959 | /* --- controls ---------------------------------------------- */ | 984 | /* --- controls ---------------------------------------------- */ |
960 | static int vidioc_queryctrl(struct file *file, void *priv, | ||
961 | struct v4l2_queryctrl *qc) | ||
962 | { | ||
963 | switch (qc->id) { | ||
964 | case V4L2_CID_AUDIO_VOLUME: | ||
965 | return v4l2_ctrl_query_fill(qc, 0, 255, 1, 200); | ||
966 | case V4L2_CID_BRIGHTNESS: | ||
967 | return v4l2_ctrl_query_fill(qc, 0, 255, 1, 127); | ||
968 | case V4L2_CID_CONTRAST: | ||
969 | return v4l2_ctrl_query_fill(qc, 0, 255, 1, 16); | ||
970 | case V4L2_CID_SATURATION: | ||
971 | return v4l2_ctrl_query_fill(qc, 0, 255, 1, 127); | ||
972 | case V4L2_CID_HUE: | ||
973 | return v4l2_ctrl_query_fill(qc, -128, 127, 1, 0); | ||
974 | } | ||
975 | return -EINVAL; | ||
976 | } | ||
977 | 985 | ||
978 | static int vidioc_g_ctrl(struct file *file, void *priv, | 986 | static int vivi_s_ctrl(struct v4l2_ctrl *ctrl) |
979 | struct v4l2_control *ctrl) | ||
980 | { | 987 | { |
981 | struct vivi_dev *dev = video_drvdata(file); | 988 | struct vivi_dev *dev = container_of(ctrl->handler, struct vivi_dev, ctrl_handler); |
982 | 989 | ||
983 | switch (ctrl->id) { | 990 | if (ctrl == dev->button) |
984 | case V4L2_CID_AUDIO_VOLUME: | 991 | dev->button_pressed = 30; |
985 | ctrl->value = dev->volume; | 992 | return 0; |
986 | return 0; | ||
987 | case V4L2_CID_BRIGHTNESS: | ||
988 | ctrl->value = dev->brightness; | ||
989 | return 0; | ||
990 | case V4L2_CID_CONTRAST: | ||
991 | ctrl->value = dev->contrast; | ||
992 | return 0; | ||
993 | case V4L2_CID_SATURATION: | ||
994 | ctrl->value = dev->saturation; | ||
995 | return 0; | ||
996 | case V4L2_CID_HUE: | ||
997 | ctrl->value = dev->hue; | ||
998 | return 0; | ||
999 | } | ||
1000 | return -EINVAL; | ||
1001 | } | ||
1002 | |||
1003 | static int vidioc_s_ctrl(struct file *file, void *priv, | ||
1004 | struct v4l2_control *ctrl) | ||
1005 | { | ||
1006 | struct vivi_dev *dev = video_drvdata(file); | ||
1007 | struct v4l2_queryctrl qc; | ||
1008 | int err; | ||
1009 | |||
1010 | qc.id = ctrl->id; | ||
1011 | err = vidioc_queryctrl(file, priv, &qc); | ||
1012 | if (err < 0) | ||
1013 | return err; | ||
1014 | if (ctrl->value < qc.minimum || ctrl->value > qc.maximum) | ||
1015 | return -ERANGE; | ||
1016 | switch (ctrl->id) { | ||
1017 | case V4L2_CID_AUDIO_VOLUME: | ||
1018 | dev->volume = ctrl->value; | ||
1019 | return 0; | ||
1020 | case V4L2_CID_BRIGHTNESS: | ||
1021 | dev->brightness = ctrl->value; | ||
1022 | return 0; | ||
1023 | case V4L2_CID_CONTRAST: | ||
1024 | dev->contrast = ctrl->value; | ||
1025 | return 0; | ||
1026 | case V4L2_CID_SATURATION: | ||
1027 | dev->saturation = ctrl->value; | ||
1028 | return 0; | ||
1029 | case V4L2_CID_HUE: | ||
1030 | dev->hue = ctrl->value; | ||
1031 | return 0; | ||
1032 | } | ||
1033 | return -EINVAL; | ||
1034 | } | 993 | } |
1035 | 994 | ||
1036 | /* ------------------------------------------------------------------ | 995 | /* ------------------------------------------------------------------ |
@@ -1094,6 +1053,79 @@ static int vivi_mmap(struct file *file, struct vm_area_struct *vma) | |||
1094 | return ret; | 1053 | return ret; |
1095 | } | 1054 | } |
1096 | 1055 | ||
1056 | static const struct v4l2_ctrl_ops vivi_ctrl_ops = { | ||
1057 | .s_ctrl = vivi_s_ctrl, | ||
1058 | }; | ||
1059 | |||
1060 | #define VIVI_CID_CUSTOM_BASE (V4L2_CID_USER_BASE | 0xf000) | ||
1061 | |||
1062 | static const struct v4l2_ctrl_config vivi_ctrl_button = { | ||
1063 | .ops = &vivi_ctrl_ops, | ||
1064 | .id = VIVI_CID_CUSTOM_BASE + 0, | ||
1065 | .name = "Button", | ||
1066 | .type = V4L2_CTRL_TYPE_BUTTON, | ||
1067 | }; | ||
1068 | |||
1069 | static const struct v4l2_ctrl_config vivi_ctrl_boolean = { | ||
1070 | .ops = &vivi_ctrl_ops, | ||
1071 | .id = VIVI_CID_CUSTOM_BASE + 1, | ||
1072 | .name = "Boolean", | ||
1073 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
1074 | .min = 0, | ||
1075 | .max = 1, | ||
1076 | .step = 1, | ||
1077 | .def = 1, | ||
1078 | }; | ||
1079 | |||
1080 | static const struct v4l2_ctrl_config vivi_ctrl_int32 = { | ||
1081 | .ops = &vivi_ctrl_ops, | ||
1082 | .id = VIVI_CID_CUSTOM_BASE + 2, | ||
1083 | .name = "Integer 32 Bits", | ||
1084 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
1085 | .min = -2147483648, | ||
1086 | .max = 2147483647, | ||
1087 | .step = 1, | ||
1088 | }; | ||
1089 | |||
1090 | static const struct v4l2_ctrl_config vivi_ctrl_int64 = { | ||
1091 | .ops = &vivi_ctrl_ops, | ||
1092 | .id = VIVI_CID_CUSTOM_BASE + 3, | ||
1093 | .name = "Integer 64 Bits", | ||
1094 | .type = V4L2_CTRL_TYPE_INTEGER64, | ||
1095 | }; | ||
1096 | |||
1097 | static const char * const vivi_ctrl_menu_strings[] = { | ||
1098 | "Menu Item 0 (Skipped)", | ||
1099 | "Menu Item 1", | ||
1100 | "Menu Item 2 (Skipped)", | ||
1101 | "Menu Item 3", | ||
1102 | "Menu Item 4", | ||
1103 | "Menu Item 5 (Skipped)", | ||
1104 | NULL, | ||
1105 | }; | ||
1106 | |||
1107 | static const struct v4l2_ctrl_config vivi_ctrl_menu = { | ||
1108 | .ops = &vivi_ctrl_ops, | ||
1109 | .id = VIVI_CID_CUSTOM_BASE + 4, | ||
1110 | .name = "Menu", | ||
1111 | .type = V4L2_CTRL_TYPE_MENU, | ||
1112 | .min = 1, | ||
1113 | .max = 4, | ||
1114 | .def = 3, | ||
1115 | .menu_skip_mask = 0x04, | ||
1116 | .qmenu = vivi_ctrl_menu_strings, | ||
1117 | }; | ||
1118 | |||
1119 | static const struct v4l2_ctrl_config vivi_ctrl_string = { | ||
1120 | .ops = &vivi_ctrl_ops, | ||
1121 | .id = VIVI_CID_CUSTOM_BASE + 5, | ||
1122 | .name = "String", | ||
1123 | .type = V4L2_CTRL_TYPE_STRING, | ||
1124 | .min = 2, | ||
1125 | .max = 4, | ||
1126 | .step = 1, | ||
1127 | }; | ||
1128 | |||
1097 | static const struct v4l2_file_operations vivi_fops = { | 1129 | static const struct v4l2_file_operations vivi_fops = { |
1098 | .owner = THIS_MODULE, | 1130 | .owner = THIS_MODULE, |
1099 | .open = vivi_open, | 1131 | .open = vivi_open, |
@@ -1120,9 +1152,6 @@ static const struct v4l2_ioctl_ops vivi_ioctl_ops = { | |||
1120 | .vidioc_s_input = vidioc_s_input, | 1152 | .vidioc_s_input = vidioc_s_input, |
1121 | .vidioc_streamon = vidioc_streamon, | 1153 | .vidioc_streamon = vidioc_streamon, |
1122 | .vidioc_streamoff = vidioc_streamoff, | 1154 | .vidioc_streamoff = vidioc_streamoff, |
1123 | .vidioc_queryctrl = vidioc_queryctrl, | ||
1124 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
1125 | .vidioc_s_ctrl = vidioc_s_ctrl, | ||
1126 | }; | 1155 | }; |
1127 | 1156 | ||
1128 | static struct video_device vivi_template = { | 1157 | static struct video_device vivi_template = { |
@@ -1153,6 +1182,7 @@ static int vivi_release(void) | |||
1153 | video_device_node_name(dev->vfd)); | 1182 | video_device_node_name(dev->vfd)); |
1154 | video_unregister_device(dev->vfd); | 1183 | video_unregister_device(dev->vfd); |
1155 | v4l2_device_unregister(&dev->v4l2_dev); | 1184 | v4l2_device_unregister(&dev->v4l2_dev); |
1185 | v4l2_ctrl_handler_free(&dev->ctrl_handler); | ||
1156 | kfree(dev); | 1186 | kfree(dev); |
1157 | } | 1187 | } |
1158 | 1188 | ||
@@ -1163,6 +1193,7 @@ static int __init vivi_create_instance(int inst) | |||
1163 | { | 1193 | { |
1164 | struct vivi_dev *dev; | 1194 | struct vivi_dev *dev; |
1165 | struct video_device *vfd; | 1195 | struct video_device *vfd; |
1196 | struct v4l2_ctrl_handler *hdl; | ||
1166 | struct vb2_queue *q; | 1197 | struct vb2_queue *q; |
1167 | int ret; | 1198 | int ret; |
1168 | 1199 | ||
@@ -1179,11 +1210,29 @@ static int __init vivi_create_instance(int inst) | |||
1179 | dev->fmt = &formats[0]; | 1210 | dev->fmt = &formats[0]; |
1180 | dev->width = 640; | 1211 | dev->width = 640; |
1181 | dev->height = 480; | 1212 | dev->height = 480; |
1182 | dev->volume = 200; | 1213 | hdl = &dev->ctrl_handler; |
1183 | dev->brightness = 127; | 1214 | v4l2_ctrl_handler_init(hdl, 11); |
1184 | dev->contrast = 16; | 1215 | dev->volume = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops, |
1185 | dev->saturation = 127; | 1216 | V4L2_CID_AUDIO_VOLUME, 0, 255, 1, 200); |
1186 | dev->hue = 0; | 1217 | dev->brightness = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops, |
1218 | V4L2_CID_BRIGHTNESS, 0, 255, 1, 127); | ||
1219 | dev->contrast = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops, | ||
1220 | V4L2_CID_CONTRAST, 0, 255, 1, 16); | ||
1221 | dev->saturation = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops, | ||
1222 | V4L2_CID_SATURATION, 0, 255, 1, 127); | ||
1223 | dev->hue = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops, | ||
1224 | V4L2_CID_HUE, -128, 127, 1, 0); | ||
1225 | dev->button = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_button, NULL); | ||
1226 | dev->int32 = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_int32, NULL); | ||
1227 | dev->int64 = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_int64, NULL); | ||
1228 | dev->boolean = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_boolean, NULL); | ||
1229 | dev->menu = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_menu, NULL); | ||
1230 | dev->string = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_string, NULL); | ||
1231 | if (hdl->error) { | ||
1232 | ret = hdl->error; | ||
1233 | goto unreg_dev; | ||
1234 | } | ||
1235 | dev->v4l2_dev.ctrl_handler = hdl; | ||
1187 | 1236 | ||
1188 | /* initialize locks */ | 1237 | /* initialize locks */ |
1189 | spin_lock_init(&dev->slock); | 1238 | spin_lock_init(&dev->slock); |
@@ -1241,6 +1290,7 @@ static int __init vivi_create_instance(int inst) | |||
1241 | rel_vdev: | 1290 | rel_vdev: |
1242 | video_device_release(vfd); | 1291 | video_device_release(vfd); |
1243 | unreg_dev: | 1292 | unreg_dev: |
1293 | v4l2_ctrl_handler_free(hdl); | ||
1244 | v4l2_device_unregister(&dev->v4l2_dev); | 1294 | v4l2_device_unregister(&dev->v4l2_dev); |
1245 | free_dev: | 1295 | free_dev: |
1246 | kfree(dev); | 1296 | kfree(dev); |