aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/v4l2-core
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2012-07-23 08:15:21 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-09-13 15:23:36 -0400
commit03d5285b8b320994b57b610553cf2b019186b5ba (patch)
tree7f5554a5570b2125b2e6bb6f4f4db2cc11c7d306 /drivers/media/v4l2-core
parent117a55b69d36a19028d1c59a737ad1246a0a75ad (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.c135
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 */
1217static int validate_new_int(const struct v4l2_ctrl *ctrl, s32 *pval) 1217static 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 */
1266static 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
2274EXPORT_SYMBOL(v4l2_subdev_g_ext_ctrls); 2251EXPORT_SYMBOL(v4l2_subdev_g_ext_ctrls);
2275 2252
2276/* Helper function to get a single control */ 2253/* Helper function to get a single control */
2277static int get_ctrl(struct v4l2_ctrl *ctrl, s32 *val) 2254static 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)
2300int v4l2_g_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_control *control) 2284int 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}
2308EXPORT_SYMBOL(v4l2_g_ctrl); 2296EXPORT_SYMBOL(v4l2_g_ctrl);
2309 2297
@@ -2315,15 +2303,28 @@ EXPORT_SYMBOL(v4l2_subdev_g_ctrl);
2315 2303
2316s32 v4l2_ctrl_g_ctrl(struct v4l2_ctrl *ctrl) 2304s32 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}
2325EXPORT_SYMBOL(v4l2_ctrl_g_ctrl); 2314EXPORT_SYMBOL(v4l2_ctrl_g_ctrl);
2326 2315
2316s64 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}
2326EXPORT_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
2539EXPORT_SYMBOL(v4l2_subdev_s_ext_ctrls); 2540EXPORT_SYMBOL(v4l2_subdev_s_ext_ctrls);
2540 2541
2541/* Helper function for VIDIOC_S_CTRL compatibility */ 2542/* Helper function for VIDIOC_S_CTRL compatibility */
2542static int set_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, s32 *val) 2543static 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}
2586EXPORT_SYMBOL(v4l2_s_ctrl); 2601EXPORT_SYMBOL(v4l2_s_ctrl);
2587 2602
@@ -2593,12 +2608,26 @@ EXPORT_SYMBOL(v4l2_subdev_s_ctrl);
2593 2608
2594int v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val) 2609int 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}
2600EXPORT_SYMBOL(v4l2_ctrl_s_ctrl); 2618EXPORT_SYMBOL(v4l2_ctrl_s_ctrl);
2601 2619
2620int 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}
2629EXPORT_SYMBOL(v4l2_ctrl_s_ctrl_int64);
2630
2602static int v4l2_ctrl_add_event(struct v4l2_subscribed_event *sev, unsigned elems) 2631static 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);