diff options
author | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2012-07-23 08:15:21 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-09-13 15:23:36 -0400 |
commit | 03d5285b8b320994b57b610553cf2b019186b5ba (patch) | |
tree | 7f5554a5570b2125b2e6bb6f4f4db2cc11c7d306 /drivers/media/v4l2-core | |
parent | 117a55b69d36a19028d1c59a737ad1246a0a75ad (diff) |
[media] v4l2-ctrls: Add v4l2_ctrl_[gs]_ctrl_int64()
These helper functions get and set a 64-bit control's value from within
a driver. They are similar to v4l2_ctrl_[gs]_ctrl() but operate on
64-bit integer controls instead of 32-bit controls.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Sakari Ailus <sakari.ailus@iki.fi>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/v4l2-core')
-rw-r--r-- | drivers/media/v4l2-core/v4l2-ctrls.c | 135 |
1 files changed, 82 insertions, 53 deletions
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index 6a34c30fff5b..ab287f236801 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c | |||
@@ -1213,76 +1213,53 @@ static int cluster_changed(struct v4l2_ctrl *master) | |||
1213 | return diff; | 1213 | return diff; |
1214 | } | 1214 | } |
1215 | 1215 | ||
1216 | /* Validate integer-type control */ | 1216 | /* Validate a new control */ |
1217 | static int validate_new_int(const struct v4l2_ctrl *ctrl, s32 *pval) | 1217 | static int validate_new(const struct v4l2_ctrl *ctrl, |
1218 | struct v4l2_ext_control *c) | ||
1218 | { | 1219 | { |
1219 | s32 val = *pval; | 1220 | size_t len; |
1220 | u32 offset; | 1221 | u32 offset; |
1222 | s32 val; | ||
1221 | 1223 | ||
1222 | switch (ctrl->type) { | 1224 | switch (ctrl->type) { |
1223 | case V4L2_CTRL_TYPE_INTEGER: | 1225 | case V4L2_CTRL_TYPE_INTEGER: |
1224 | /* Round towards the closest legal value */ | 1226 | /* Round towards the closest legal value */ |
1225 | val += ctrl->step / 2; | 1227 | val = c->value + ctrl->step / 2; |
1226 | if (val < ctrl->minimum) | 1228 | val = clamp(val, ctrl->minimum, ctrl->maximum); |
1227 | val = ctrl->minimum; | ||
1228 | if (val > ctrl->maximum) | ||
1229 | val = ctrl->maximum; | ||
1230 | offset = val - ctrl->minimum; | 1229 | offset = val - ctrl->minimum; |
1231 | offset = ctrl->step * (offset / ctrl->step); | 1230 | offset = ctrl->step * (offset / ctrl->step); |
1232 | val = ctrl->minimum + offset; | 1231 | c->value = ctrl->minimum + offset; |
1233 | *pval = val; | ||
1234 | return 0; | 1232 | return 0; |
1235 | 1233 | ||
1236 | case V4L2_CTRL_TYPE_BOOLEAN: | 1234 | case V4L2_CTRL_TYPE_BOOLEAN: |
1237 | *pval = !!val; | 1235 | c->value = !!c->value; |
1238 | return 0; | 1236 | return 0; |
1239 | 1237 | ||
1240 | case V4L2_CTRL_TYPE_MENU: | 1238 | case V4L2_CTRL_TYPE_MENU: |
1241 | case V4L2_CTRL_TYPE_INTEGER_MENU: | 1239 | case V4L2_CTRL_TYPE_INTEGER_MENU: |
1242 | if (val < ctrl->minimum || val > ctrl->maximum) | 1240 | if (c->value < ctrl->minimum || c->value > ctrl->maximum) |
1243 | return -ERANGE; | 1241 | return -ERANGE; |
1244 | if (ctrl->menu_skip_mask & (1 << val)) | 1242 | if (ctrl->menu_skip_mask & (1 << c->value)) |
1245 | return -EINVAL; | 1243 | return -EINVAL; |
1246 | if (ctrl->type == V4L2_CTRL_TYPE_MENU && | 1244 | if (ctrl->type == V4L2_CTRL_TYPE_MENU && |
1247 | ctrl->qmenu[val][0] == '\0') | 1245 | ctrl->qmenu[c->value][0] == '\0') |
1248 | return -EINVAL; | 1246 | return -EINVAL; |
1249 | return 0; | 1247 | return 0; |
1250 | 1248 | ||
1251 | case V4L2_CTRL_TYPE_BITMASK: | 1249 | case V4L2_CTRL_TYPE_BITMASK: |
1252 | *pval &= ctrl->maximum; | 1250 | c->value &= ctrl->maximum; |
1253 | return 0; | 1251 | return 0; |
1254 | 1252 | ||
1255 | case V4L2_CTRL_TYPE_BUTTON: | 1253 | case V4L2_CTRL_TYPE_BUTTON: |
1256 | case V4L2_CTRL_TYPE_CTRL_CLASS: | 1254 | case V4L2_CTRL_TYPE_CTRL_CLASS: |
1257 | *pval = 0; | 1255 | c->value = 0; |
1258 | return 0; | 1256 | return 0; |
1259 | 1257 | ||
1260 | default: | ||
1261 | return -EINVAL; | ||
1262 | } | ||
1263 | } | ||
1264 | |||
1265 | /* Validate a new control */ | ||
1266 | static int validate_new(const struct v4l2_ctrl *ctrl, struct v4l2_ext_control *c) | ||
1267 | { | ||
1268 | char *s = c->string; | ||
1269 | size_t len; | ||
1270 | |||
1271 | switch (ctrl->type) { | ||
1272 | case V4L2_CTRL_TYPE_INTEGER: | ||
1273 | case V4L2_CTRL_TYPE_BOOLEAN: | ||
1274 | case V4L2_CTRL_TYPE_MENU: | ||
1275 | case V4L2_CTRL_TYPE_INTEGER_MENU: | ||
1276 | case V4L2_CTRL_TYPE_BITMASK: | ||
1277 | case V4L2_CTRL_TYPE_BUTTON: | ||
1278 | case V4L2_CTRL_TYPE_CTRL_CLASS: | ||
1279 | return validate_new_int(ctrl, &c->value); | ||
1280 | |||
1281 | case V4L2_CTRL_TYPE_INTEGER64: | 1258 | case V4L2_CTRL_TYPE_INTEGER64: |
1282 | return 0; | 1259 | return 0; |
1283 | 1260 | ||
1284 | case V4L2_CTRL_TYPE_STRING: | 1261 | case V4L2_CTRL_TYPE_STRING: |
1285 | len = strlen(s); | 1262 | len = strlen(c->string); |
1286 | if (len < ctrl->minimum) | 1263 | if (len < ctrl->minimum) |
1287 | return -ERANGE; | 1264 | return -ERANGE; |
1288 | if ((len - ctrl->minimum) % ctrl->step) | 1265 | if ((len - ctrl->minimum) % ctrl->step) |
@@ -2274,12 +2251,19 @@ int v4l2_subdev_g_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *cs | |||
2274 | EXPORT_SYMBOL(v4l2_subdev_g_ext_ctrls); | 2251 | EXPORT_SYMBOL(v4l2_subdev_g_ext_ctrls); |
2275 | 2252 | ||
2276 | /* Helper function to get a single control */ | 2253 | /* Helper function to get a single control */ |
2277 | static int get_ctrl(struct v4l2_ctrl *ctrl, s32 *val) | 2254 | static int get_ctrl(struct v4l2_ctrl *ctrl, struct v4l2_ext_control *c) |
2278 | { | 2255 | { |
2279 | struct v4l2_ctrl *master = ctrl->cluster[0]; | 2256 | struct v4l2_ctrl *master = ctrl->cluster[0]; |
2280 | int ret = 0; | 2257 | int ret = 0; |
2281 | int i; | 2258 | int i; |
2282 | 2259 | ||
2260 | /* String controls are not supported. The new_to_user() and | ||
2261 | * cur_to_user() calls below would need to be modified not to access | ||
2262 | * userspace memory when called from get_ctrl(). | ||
2263 | */ | ||
2264 | if (ctrl->type == V4L2_CTRL_TYPE_STRING) | ||
2265 | return -EINVAL; | ||
2266 | |||
2283 | if (ctrl->flags & V4L2_CTRL_FLAG_WRITE_ONLY) | 2267 | if (ctrl->flags & V4L2_CTRL_FLAG_WRITE_ONLY) |
2284 | return -EACCES; | 2268 | return -EACCES; |
2285 | 2269 | ||
@@ -2289,9 +2273,9 @@ static int get_ctrl(struct v4l2_ctrl *ctrl, s32 *val) | |||
2289 | for (i = 0; i < master->ncontrols; i++) | 2273 | for (i = 0; i < master->ncontrols; i++) |
2290 | cur_to_new(master->cluster[i]); | 2274 | cur_to_new(master->cluster[i]); |
2291 | ret = call_op(master, g_volatile_ctrl); | 2275 | ret = call_op(master, g_volatile_ctrl); |
2292 | *val = ctrl->val; | 2276 | new_to_user(c, ctrl); |
2293 | } else { | 2277 | } else { |
2294 | *val = ctrl->cur.val; | 2278 | cur_to_user(c, ctrl); |
2295 | } | 2279 | } |
2296 | v4l2_ctrl_unlock(master); | 2280 | v4l2_ctrl_unlock(master); |
2297 | return ret; | 2281 | return ret; |
@@ -2300,10 +2284,14 @@ static int get_ctrl(struct v4l2_ctrl *ctrl, s32 *val) | |||
2300 | int v4l2_g_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_control *control) | 2284 | int v4l2_g_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_control *control) |
2301 | { | 2285 | { |
2302 | struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, control->id); | 2286 | struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, control->id); |
2287 | struct v4l2_ext_control c; | ||
2288 | int ret; | ||
2303 | 2289 | ||
2304 | if (ctrl == NULL || !type_is_int(ctrl)) | 2290 | if (ctrl == NULL || !type_is_int(ctrl)) |
2305 | return -EINVAL; | 2291 | return -EINVAL; |
2306 | return get_ctrl(ctrl, &control->value); | 2292 | ret = get_ctrl(ctrl, &c); |
2293 | control->value = c.value; | ||
2294 | return ret; | ||
2307 | } | 2295 | } |
2308 | EXPORT_SYMBOL(v4l2_g_ctrl); | 2296 | EXPORT_SYMBOL(v4l2_g_ctrl); |
2309 | 2297 | ||
@@ -2315,15 +2303,28 @@ EXPORT_SYMBOL(v4l2_subdev_g_ctrl); | |||
2315 | 2303 | ||
2316 | s32 v4l2_ctrl_g_ctrl(struct v4l2_ctrl *ctrl) | 2304 | s32 v4l2_ctrl_g_ctrl(struct v4l2_ctrl *ctrl) |
2317 | { | 2305 | { |
2318 | s32 val = 0; | 2306 | struct v4l2_ext_control c; |
2319 | 2307 | ||
2320 | /* It's a driver bug if this happens. */ | 2308 | /* It's a driver bug if this happens. */ |
2321 | WARN_ON(!type_is_int(ctrl)); | 2309 | WARN_ON(!type_is_int(ctrl)); |
2322 | get_ctrl(ctrl, &val); | 2310 | c.value = 0; |
2323 | return val; | 2311 | get_ctrl(ctrl, &c); |
2312 | return c.value; | ||
2324 | } | 2313 | } |
2325 | EXPORT_SYMBOL(v4l2_ctrl_g_ctrl); | 2314 | EXPORT_SYMBOL(v4l2_ctrl_g_ctrl); |
2326 | 2315 | ||
2316 | s64 v4l2_ctrl_g_ctrl_int64(struct v4l2_ctrl *ctrl) | ||
2317 | { | ||
2318 | struct v4l2_ext_control c; | ||
2319 | |||
2320 | /* It's a driver bug if this happens. */ | ||
2321 | WARN_ON(ctrl->type != V4L2_CTRL_TYPE_INTEGER64); | ||
2322 | c.value = 0; | ||
2323 | get_ctrl(ctrl, &c); | ||
2324 | return c.value; | ||
2325 | } | ||
2326 | EXPORT_SYMBOL(v4l2_ctrl_g_ctrl_int64); | ||
2327 | |||
2327 | 2328 | ||
2328 | /* Core function that calls try/s_ctrl and ensures that the new value is | 2329 | /* Core function that calls try/s_ctrl and ensures that the new value is |
2329 | copied to the current value on a set. | 2330 | copied to the current value on a set. |
@@ -2539,13 +2540,21 @@ int v4l2_subdev_s_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *cs | |||
2539 | EXPORT_SYMBOL(v4l2_subdev_s_ext_ctrls); | 2540 | EXPORT_SYMBOL(v4l2_subdev_s_ext_ctrls); |
2540 | 2541 | ||
2541 | /* Helper function for VIDIOC_S_CTRL compatibility */ | 2542 | /* Helper function for VIDIOC_S_CTRL compatibility */ |
2542 | static int set_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, s32 *val) | 2543 | static int set_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, |
2544 | struct v4l2_ext_control *c) | ||
2543 | { | 2545 | { |
2544 | struct v4l2_ctrl *master = ctrl->cluster[0]; | 2546 | struct v4l2_ctrl *master = ctrl->cluster[0]; |
2545 | int ret; | 2547 | int ret; |
2546 | int i; | 2548 | int i; |
2547 | 2549 | ||
2548 | ret = validate_new_int(ctrl, val); | 2550 | /* String controls are not supported. The user_to_new() and |
2551 | * cur_to_user() calls below would need to be modified not to access | ||
2552 | * userspace memory when called from set_ctrl(). | ||
2553 | */ | ||
2554 | if (ctrl->type == V4L2_CTRL_TYPE_STRING) | ||
2555 | return -EINVAL; | ||
2556 | |||
2557 | ret = validate_new(ctrl, c); | ||
2549 | if (ret) | 2558 | if (ret) |
2550 | return ret; | 2559 | return ret; |
2551 | 2560 | ||
@@ -2560,12 +2569,13 @@ static int set_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, s32 *val) | |||
2560 | manual mode we have to update the current volatile values since | 2569 | manual mode we have to update the current volatile values since |
2561 | those will become the initial manual values after such a switch. */ | 2570 | those will become the initial manual values after such a switch. */ |
2562 | if (master->is_auto && master->has_volatiles && ctrl == master && | 2571 | if (master->is_auto && master->has_volatiles && ctrl == master && |
2563 | !is_cur_manual(master) && *val == master->manual_mode_value) | 2572 | !is_cur_manual(master) && c->value == master->manual_mode_value) |
2564 | update_from_auto_cluster(master); | 2573 | update_from_auto_cluster(master); |
2565 | ctrl->val = *val; | 2574 | |
2566 | ctrl->is_new = 1; | 2575 | user_to_new(c, ctrl); |
2567 | ret = try_or_set_cluster(fh, master, true); | 2576 | ret = try_or_set_cluster(fh, master, true); |
2568 | *val = ctrl->cur.val; | 2577 | cur_to_user(c, ctrl); |
2578 | |||
2569 | v4l2_ctrl_unlock(ctrl); | 2579 | v4l2_ctrl_unlock(ctrl); |
2570 | return ret; | 2580 | return ret; |
2571 | } | 2581 | } |
@@ -2574,6 +2584,8 @@ int v4l2_s_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl, | |||
2574 | struct v4l2_control *control) | 2584 | struct v4l2_control *control) |
2575 | { | 2585 | { |
2576 | struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, control->id); | 2586 | struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, control->id); |
2587 | struct v4l2_ext_control c; | ||
2588 | int ret; | ||
2577 | 2589 | ||
2578 | if (ctrl == NULL || !type_is_int(ctrl)) | 2590 | if (ctrl == NULL || !type_is_int(ctrl)) |
2579 | return -EINVAL; | 2591 | return -EINVAL; |
@@ -2581,7 +2593,10 @@ int v4l2_s_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl, | |||
2581 | if (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY) | 2593 | if (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY) |
2582 | return -EACCES; | 2594 | return -EACCES; |
2583 | 2595 | ||
2584 | return set_ctrl(fh, ctrl, &control->value); | 2596 | c.value = control->value; |
2597 | ret = set_ctrl(fh, ctrl, &c); | ||
2598 | control->value = c.value; | ||
2599 | return ret; | ||
2585 | } | 2600 | } |
2586 | EXPORT_SYMBOL(v4l2_s_ctrl); | 2601 | EXPORT_SYMBOL(v4l2_s_ctrl); |
2587 | 2602 | ||
@@ -2593,12 +2608,26 @@ EXPORT_SYMBOL(v4l2_subdev_s_ctrl); | |||
2593 | 2608 | ||
2594 | int v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val) | 2609 | int v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val) |
2595 | { | 2610 | { |
2611 | struct v4l2_ext_control c; | ||
2612 | |||
2596 | /* It's a driver bug if this happens. */ | 2613 | /* It's a driver bug if this happens. */ |
2597 | WARN_ON(!type_is_int(ctrl)); | 2614 | WARN_ON(!type_is_int(ctrl)); |
2598 | return set_ctrl(NULL, ctrl, &val); | 2615 | c.value = val; |
2616 | return set_ctrl(NULL, ctrl, &c); | ||
2599 | } | 2617 | } |
2600 | EXPORT_SYMBOL(v4l2_ctrl_s_ctrl); | 2618 | EXPORT_SYMBOL(v4l2_ctrl_s_ctrl); |
2601 | 2619 | ||
2620 | int v4l2_ctrl_s_ctrl_int64(struct v4l2_ctrl *ctrl, s64 val) | ||
2621 | { | ||
2622 | struct v4l2_ext_control c; | ||
2623 | |||
2624 | /* It's a driver bug if this happens. */ | ||
2625 | WARN_ON(ctrl->type != V4L2_CTRL_TYPE_INTEGER64); | ||
2626 | c.value64 = val; | ||
2627 | return set_ctrl(NULL, ctrl, &c); | ||
2628 | } | ||
2629 | EXPORT_SYMBOL(v4l2_ctrl_s_ctrl_int64); | ||
2630 | |||
2602 | static int v4l2_ctrl_add_event(struct v4l2_subscribed_event *sev, unsigned elems) | 2631 | static int v4l2_ctrl_add_event(struct v4l2_subscribed_event *sev, unsigned elems) |
2603 | { | 2632 | { |
2604 | struct v4l2_ctrl *ctrl = v4l2_ctrl_find(sev->fh->ctrl_handler, sev->id); | 2633 | struct v4l2_ctrl *ctrl = v4l2_ctrl_find(sev->fh->ctrl_handler, sev->id); |