diff options
author | Hans de Goede <hdegoede@redhat.com> | 2012-04-08 11:59:53 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-05-07 15:41:35 -0400 |
commit | 805e9b4a06bf874c56e0811e9cca5e25cf465e42 (patch) | |
tree | 4a45d1fbbe4aa3c66774a9fc441aa3536d395a14 /drivers/media/video/uvc | |
parent | 55afeb8a4d3ffdf8de546d5de37aca5b229ca9a4 (diff) |
[media] uvcvideo: Send control change events for slave ctrls when the master changes
This allows v4l2 control UI-s to update the inactive state (ie grey-ing
out of controls) for slave controls when the master control changes.
[Use __uvc_find_control() to find slave controls, as they're always
located in the same entity as the corresponding master control]
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
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.c | 58 |
1 files changed, 56 insertions, 2 deletions
diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c index ae7371f3a39..03212c70333 100644 --- a/drivers/media/video/uvc/uvc_ctrl.c +++ b/drivers/media/video/uvc/uvc_ctrl.c | |||
@@ -1177,22 +1177,76 @@ static void uvc_ctrl_send_event(struct uvc_fh *handle, | |||
1177 | 1177 | ||
1178 | list_for_each_entry(sev, &mapping->ev_subs, node) { | 1178 | list_for_each_entry(sev, &mapping->ev_subs, node) { |
1179 | if (sev->fh && (sev->fh != &handle->vfh || | 1179 | if (sev->fh && (sev->fh != &handle->vfh || |
1180 | (sev->flags & V4L2_EVENT_SUB_FL_ALLOW_FEEDBACK))) | 1180 | (sev->flags & V4L2_EVENT_SUB_FL_ALLOW_FEEDBACK) || |
1181 | (changes & V4L2_EVENT_CTRL_CH_FLAGS))) | ||
1181 | v4l2_event_queue_fh(sev->fh, &ev); | 1182 | v4l2_event_queue_fh(sev->fh, &ev); |
1182 | } | 1183 | } |
1183 | } | 1184 | } |
1184 | 1185 | ||
1186 | static void uvc_ctrl_send_slave_event(struct uvc_fh *handle, | ||
1187 | struct uvc_control *master, u32 slave_id, | ||
1188 | const struct v4l2_ext_control *xctrls, unsigned int xctrls_count) | ||
1189 | { | ||
1190 | struct uvc_control_mapping *mapping = NULL; | ||
1191 | struct uvc_control *ctrl = NULL; | ||
1192 | u32 changes = V4L2_EVENT_CTRL_CH_FLAGS; | ||
1193 | unsigned int i; | ||
1194 | s32 val = 0; | ||
1195 | |||
1196 | /* | ||
1197 | * We can skip sending an event for the slave if the slave | ||
1198 | * is being modified in the same transaction. | ||
1199 | */ | ||
1200 | for (i = 0; i < xctrls_count; i++) { | ||
1201 | if (xctrls[i].id == slave_id) | ||
1202 | return; | ||
1203 | } | ||
1204 | |||
1205 | __uvc_find_control(master->entity, slave_id, &mapping, &ctrl, 0); | ||
1206 | if (ctrl == NULL) | ||
1207 | return; | ||
1208 | |||
1209 | if (__uvc_ctrl_get(handle->chain, ctrl, mapping, &val) == 0) | ||
1210 | changes |= V4L2_EVENT_CTRL_CH_VALUE; | ||
1211 | |||
1212 | uvc_ctrl_send_event(handle, ctrl, mapping, val, changes); | ||
1213 | } | ||
1214 | |||
1185 | static void uvc_ctrl_send_events(struct uvc_fh *handle, | 1215 | static void uvc_ctrl_send_events(struct uvc_fh *handle, |
1186 | const struct v4l2_ext_control *xctrls, unsigned int xctrls_count) | 1216 | const struct v4l2_ext_control *xctrls, unsigned int xctrls_count) |
1187 | { | 1217 | { |
1188 | struct uvc_control_mapping *mapping; | 1218 | struct uvc_control_mapping *mapping; |
1189 | struct uvc_control *ctrl; | 1219 | struct uvc_control *ctrl; |
1220 | u32 changes = V4L2_EVENT_CTRL_CH_VALUE; | ||
1190 | unsigned int i; | 1221 | unsigned int i; |
1222 | unsigned int j; | ||
1191 | 1223 | ||
1192 | for (i = 0; i < xctrls_count; ++i) { | 1224 | for (i = 0; i < xctrls_count; ++i) { |
1193 | ctrl = uvc_find_control(handle->chain, xctrls[i].id, &mapping); | 1225 | ctrl = uvc_find_control(handle->chain, xctrls[i].id, &mapping); |
1226 | |||
1227 | for (j = 0; j < ARRAY_SIZE(mapping->slave_ids); ++j) { | ||
1228 | if (!mapping->slave_ids[j]) | ||
1229 | break; | ||
1230 | uvc_ctrl_send_slave_event(handle, ctrl, | ||
1231 | mapping->slave_ids[j], | ||
1232 | xctrls, xctrls_count); | ||
1233 | } | ||
1234 | |||
1235 | /* | ||
1236 | * If the master is being modified in the same transaction | ||
1237 | * flags may change too. | ||
1238 | */ | ||
1239 | if (mapping->master_id) { | ||
1240 | for (j = 0; j < xctrls_count; j++) { | ||
1241 | if (xctrls[j].id == mapping->master_id) { | ||
1242 | changes |= V4L2_EVENT_CTRL_CH_FLAGS; | ||
1243 | break; | ||
1244 | } | ||
1245 | } | ||
1246 | } | ||
1247 | |||
1194 | uvc_ctrl_send_event(handle, ctrl, mapping, xctrls[i].value, | 1248 | uvc_ctrl_send_event(handle, ctrl, mapping, xctrls[i].value, |
1195 | V4L2_EVENT_CTRL_CH_VALUE); | 1249 | changes); |
1196 | } | 1250 | } |
1197 | } | 1251 | } |
1198 | 1252 | ||