21 #include <linux/ctype.h>
22 #include <linux/slab.h>
23 #include <linux/export.h>
30 #define has_op(master, op) \
31 (master->ops && master->ops->op)
32 #define call_op(master, op) \
33 (has_op(master, op) ? master->ops->op(master) : 0)
48 static bool is_cur_manual(
const struct v4l2_ctrl *master)
55 static bool is_new_manual(
const struct v4l2_ctrl *master)
66 static const char *
const mpeg_audio_sampling_freq[] = {
72 static const char *
const mpeg_audio_encoding[] = {
80 static const char *
const mpeg_audio_l1_bitrate[] = {
97 static const char *
const mpeg_audio_l2_bitrate[] = {
114 static const char *
const mpeg_audio_l3_bitrate[] = {
131 static const char *
const mpeg_audio_ac3_bitrate[] = {
153 static const char *
const mpeg_audio_mode[] = {
160 static const char *
const mpeg_audio_mode_extension[] = {
167 static const char *
const mpeg_audio_emphasis[] = {
173 static const char *
const mpeg_audio_crc[] = {
178 static const char *
const mpeg_audio_dec_playback[] = {
187 static const char *
const mpeg_video_encoding[] = {
193 static const char *
const mpeg_video_aspect[] = {
200 static const char *
const mpeg_video_bitrate_mode[] = {
205 static const char *
const mpeg_stream_type[] = {
206 "MPEG-2 Program Stream",
207 "MPEG-2 Transport Stream",
208 "MPEG-1 System Stream",
209 "MPEG-2 DVD-compatible Stream",
210 "MPEG-1 VCD-compatible Stream",
211 "MPEG-2 SVCD-compatible Stream",
214 static const char *
const mpeg_stream_vbi_fmt[] = {
216 "Private Packet, IVTV Format",
219 static const char *
const camera_power_line_frequency[] = {
226 static const char *
const camera_exposure_auto[] = {
229 "Shutter Priority Mode",
230 "Aperture Priority Mode",
233 static const char *
const camera_exposure_metering[] = {
239 static const char *
const camera_auto_focus_range[] = {
246 static const char *
const colorfx[] = {
265 static const char *
const auto_n_preset_white_balance[] = {
278 static const char *
const camera_iso_sensitivity_auto[] = {
283 static const char *
const scene_mode[] = {
300 static const char *
const tune_preemphasis[] = {
306 static const char *
const header_mode[] = {
308 "Joined With 1st Frame",
311 static const char *
const multi_slice[] = {
317 static const char *
const entropy_mode[] = {
322 static const char *
const mpeg_h264_level[] = {
341 static const char *
const h264_loop_filter[] = {
344 "Disabled at Slice Boundary",
347 static const char *
const h264_profile[] = {
349 "Constrained Baseline",
355 "High 444 Predictive",
362 "Scalable High Intra",
366 static const char *
const vui_sar_idc[] = {
387 static const char *
const h264_fp_arrangement_type[] = {
396 static const char *
const h264_fmo_map_type[] = {
397 "Interleaved Slices",
399 "Foreground with Leftover",
406 static const char *
const mpeg_mpeg4_level[] = {
417 static const char *
const mpeg4_profile[] = {
422 "Advanced Coding Efficency",
426 static const char *
const flash_led_mode[] = {
432 static const char *
const flash_strobe_source[] = {
438 static const char *
const jpeg_chroma_subsampling[] = {
447 static const char *
const dv_tx_mode[] = {
452 static const char *
const dv_rgb_range[] = {
454 "RGB limited range (16-235)",
455 "RGB full range (0-255)",
462 return mpeg_audio_sampling_freq;
464 return mpeg_audio_encoding;
466 return mpeg_audio_l1_bitrate;
468 return mpeg_audio_l2_bitrate;
470 return mpeg_audio_l3_bitrate;
472 return mpeg_audio_ac3_bitrate;
474 return mpeg_audio_mode;
476 return mpeg_audio_mode_extension;
478 return mpeg_audio_emphasis;
480 return mpeg_audio_crc;
483 return mpeg_audio_dec_playback;
485 return mpeg_video_encoding;
487 return mpeg_video_aspect;
489 return mpeg_video_bitrate_mode;
491 return mpeg_stream_type;
493 return mpeg_stream_vbi_fmt;
495 return camera_power_line_frequency;
497 return camera_exposure_auto;
499 return camera_exposure_metering;
501 return camera_auto_focus_range;
505 return auto_n_preset_white_balance;
507 return camera_iso_sensitivity_auto;
511 return tune_preemphasis;
513 return flash_led_mode;
515 return flash_strobe_source;
523 return mpeg_h264_level;
525 return h264_loop_filter;
531 return h264_fp_arrangement_type;
533 return h264_fmo_map_type;
535 return mpeg_mpeg4_level;
537 return mpeg4_profile;
539 return jpeg_chroma_subsampling;
684 return "H264 Set QP Value for HC Layers";
863 *min = *max = *step = *def = 0;
934 *min = *max = *step = *def = 0;
965 *min = *max = *step = *def = 0;
1029 switch (ctrl->
type) {
1044 ev->
u.
ctrl.changes = changes;
1048 ev->
u.
ctrl.value64 = 0;
1055 ev->
u.
ctrl.step = 1;
1066 if (list_empty(&ctrl->
ev_subs))
1068 fill_event(&ev, ctrl, changes);
1071 if (sev->fh != fh ||
1082 switch (ctrl->type) {
1084 len =
strlen(ctrl->cur.string);
1085 if (c->size < len + 1) {
1092 c->value64 = ctrl->cur.val64;
1095 c->value = ctrl->cur.val;
1109 switch (ctrl->
type) {
1123 ctrl->
string[size - 1] = 0;
1129 return ret ? -
EFAULT : 0;
1143 switch (ctrl->
type) {
1146 if (c->
size < len + 1) {
1164 bool update_inactive)
1170 switch (ctrl->
type) {
1188 if (update_inactive) {
1192 if (!is_cur_manual(ctrl->
cluster[0])) {
1194 if (ctrl->
cluster[0]->has_volatiles)
1199 if (changed || update_inactive) {
1204 send_event(fh, ctrl,
1211 static void cur_to_new(
struct v4l2_ctrl *ctrl)
1215 switch (ctrl->
type) {
1231 static int cluster_changed(
struct v4l2_ctrl *master)
1236 for (i = 0; !diff && i < master->
ncontrols; i++) {
1241 switch (ctrl->
type) {
1261 static int validate_new(
const struct v4l2_ctrl *ctrl,
1268 switch (ctrl->
type) {
1274 offset = ctrl->
step * (offset / ctrl->
step);
1326 if (hdl->
error == 0)
1333 unsigned nr_of_controls_hint)
1337 INIT_LIST_HEAD(&hdl->
ctrls);
1395 if (!type_is_int(ref->
ctrl))
1415 return find_private_ref(hdl,
id);
1424 while (ref && ref->
ctrl->id !=
id)
1440 ref = find_ref(hdl,
id);
1466 if (
id != class_ctrl && find_ref_lock(hdl, class_ctrl) ==
NULL)
1473 new_ref = kzalloc(
sizeof(*new_ref),
GFP_KERNEL);
1475 return handler_set_err(hdl, -
ENOMEM);
1486 INIT_LIST_HEAD(&new_ref->
node);
1496 goto insert_in_hash;
1501 if (ref->
ctrl->id <
id)
1504 if (ref->
ctrl->id ==
id) {
1508 list_add(&new_ref->
node, ref->
node.prev);
1515 hdl->
buckets[bucket] = new_ref;
1531 unsigned sz_extra = 0;
1543 handler_set_err(hdl, -
ERANGE);
1547 handler_set_err(hdl, -
ERANGE);
1554 (def < min || def > max)) {
1555 handler_set_err(hdl, -
ERANGE);
1559 handler_set_err(hdl, -
ERANGE);
1568 sz_extra += 2 * (max + 1);
1570 ctrl = kzalloc(
sizeof(*ctrl) + sz_extra,
GFP_KERNEL);
1572 handler_set_err(hdl, -
ENOMEM);
1576 INIT_LIST_HEAD(&ctrl->
node);
1577 INIT_LIST_HEAD(&ctrl->
ev_subs);
1595 ctrl->
cur.
string = (
char *)&ctrl[1] + sz_extra - (max + 1);
1596 ctrl->
string = (
char *)&ctrl[1] + sz_extra - 2 * (max + 1);
1600 if (handler_new_ref(hdl, ctrl)) {
1615 const char *name = cfg->
name;
1616 const char *
const *qmenu = cfg->
qmenu;
1638 qmenu_int ==
NULL) {
1639 handler_set_err(hdl, -
EINVAL);
1643 ctrl = v4l2_ctrl_new(hdl, cfg->
ops, cfg->
id, name,
1646 def, flags, qmenu, qmenu_int, priv);
1662 v4l2_ctrl_fill(
id, &name, &type, &min, &max, &step, &def, &flags);
1665 handler_set_err(hdl, -
EINVAL);
1668 return v4l2_ctrl_new(hdl, ops,
id, name, type,
1685 v4l2_ctrl_fill(
id, &name, &type, &min, &max, &step, &def, &flags);
1687 handler_set_err(hdl, -
EINVAL);
1690 return v4l2_ctrl_new(hdl, ops,
id, name, type,
1691 0, max, mask, def, flags, qmenu,
NULL,
NULL);
1698 s32 mask,
s32 def,
const char *
const *qmenu)
1710 handler_set_err(hdl, -
EINVAL);
1714 v4l2_ctrl_fill(
id, &name, &type, &min, &max, &step, &def, &flags);
1716 handler_set_err(hdl, -
EINVAL);
1719 return v4l2_ctrl_new(hdl, ops,
id, name, type, 0, max, mask, def,
1736 v4l2_ctrl_fill(
id, &name, &type, &min, &max, &step, &def, &flags);
1738 handler_set_err(hdl, -
EINVAL);
1741 return v4l2_ctrl_new(hdl, ops,
id, name, type,
1742 0, max, 0, def, flags,
NULL, qmenu_int,
NULL);
1753 handler_set_err(hdl, -
EINVAL);
1758 return handler_new_ref(hdl, ctrl) ?
NULL :
ctrl;
1771 if (!hdl || !add || hdl == add)
1788 ret = handler_new_ref(hdl, ctrl);
1823 BUG_ON(ncontrols == 0 || controls[0] ==
NULL);
1830 has_volatiles =
true;
1838 u8 manual_val,
bool set_volatile)
1846 WARN_ON(manual_val < master->minimum || manual_val > master->
maximum);
1853 if (!is_cur_manual(master))
1879 if (old != inactive)
1897 v4l2_ctrl_lock(ctrl);
1906 v4l2_ctrl_unlock(ctrl);
1911 static void log_ctrl(
const struct v4l2_ctrl *ctrl,
1912 const char *
prefix,
const char *colon)
1921 switch (ctrl->
type) {
1965 const char *colon =
"";
1973 if (len && prefix[len - 1] !=
' ')
1978 log_ctrl(ctrl, prefix, colon);
2005 for (i = 0; i < master->
ncontrols; i++) {
2007 cur_to_new(master->
cluster[i]);
2012 ret =
call_op(master, s_ctrl);
2034 ref = find_ref(hdl,
id);
2040 if (
id >= node2id(hdl->
ctrl_refs.prev)) {
2061 memset(qc, 0,
sizeof(*qc));
2101 switch (ctrl->
type) {
2114 if (i < ctrl->minimum || i > ctrl->
maximum)
2186 bool have_clusters =
false;
2189 for (i = 0, h = helpers; i < cs->
count; i++, h++) {
2204 ref = find_ref_lock(hdl,
id);
2211 if (ctrl->
cluster[0]->ncontrols > 1)
2212 have_clusters =
true;
2214 ref = find_ref_lock(hdl, ctrl->
cluster[0]->id);
2236 for (i = 0; i < cs->
count; i++)
2237 helpers[i].mref->helper =
NULL;
2238 for (i = 0, h = helpers; i < cs->
count; i++, h++) {
2264 if (ctrl_class == 0)
2266 return find_ref_lock(hdl, ctrl_class | 1) ? 0 : -
EINVAL;
2289 helpers = kmalloc_array(cs->
count,
sizeof(helper[0]),
2291 if (helpers ==
NULL)
2295 ret = prepare_ext_ctrls(hdl, cs, helpers);
2298 for (i = 0; !ret && i < cs->
count; i++)
2302 for (i = 0; !ret && i < cs->
count; i++) {
2307 if (helpers[i].mref ==
NULL)
2310 master = helpers[
i].
mref->ctrl;
2313 v4l2_ctrl_lock(master);
2319 cur_to_new(master->
cluster[j]);
2320 ret =
call_op(master, g_volatile_ctrl);
2321 ctrl_to_user = new_to_user;
2330 ret = ctrl_to_user(cs->
controls + idx,
2333 }
while (!ret && idx);
2335 v4l2_ctrl_unlock(master);
2367 v4l2_ctrl_lock(master);
2371 cur_to_new(master->
cluster[i]);
2372 ret =
call_op(master, g_volatile_ctrl);
2373 new_to_user(c, ctrl);
2375 cur_to_user(c, ctrl);
2377 v4l2_ctrl_unlock(master);
2387 if (ctrl ==
NULL || !type_is_int(ctrl))
2429 static int try_or_set_cluster(
struct v4l2_fh *fh,
2440 for (i = 0; i < master->
ncontrols; i++) {
2456 ret =
call_op(master, try_ctrl);
2459 if (ret || !
set || !cluster_changed(master))
2461 ret =
call_op(master, s_ctrl);
2466 update_flag = is_cur_manual(master) != is_new_manual(master);
2468 new_to_cur(fh, master->
cluster[i], update_flag && i > 0);
2480 for (i = 0; i < cs->
count; i++) {
2495 ret = validate_new(ctrl, &cs->
controls[i]);
2504 static void update_from_auto_cluster(
struct v4l2_ctrl *master)
2509 cur_to_new(master->
cluster[i]);
2510 if (!
call_op(master, g_volatile_ctrl))
2536 helpers = kmalloc_array(cs->
count,
sizeof(helper[0]),
2541 ret = prepare_ext_ctrls(hdl, cs, helpers);
2543 ret = validate_ctrls(cs, helpers,
set);
2546 for (i = 0; !ret && i < cs->
count; i++) {
2550 if (helpers[i].mref ==
NULL)
2554 master = helpers[
i].
mref->ctrl;
2555 v4l2_ctrl_lock(master);
2569 !is_cur_manual(master)) {
2577 if (helpers[tmp_idx].ctrl == master)
2578 new_auto_val = cs->
controls[tmp_idx].value;
2579 tmp_idx = helpers[tmp_idx].
next;
2584 update_from_auto_cluster(master);
2590 ret = user_to_new(cs->
controls + idx, helpers[idx].
ctrl);
2592 }
while (!ret && idx);
2595 ret = try_or_set_cluster(fh, master,
set);
2601 ret = new_to_user(cs->
controls + idx,
2604 }
while (!ret && idx);
2606 v4l2_ctrl_unlock(master);
2616 return try_set_ext_ctrls(
NULL, hdl, cs,
false);
2623 return try_set_ext_ctrls(fh, hdl, cs,
true);
2654 ret = validate_new(ctrl, c);
2658 v4l2_ctrl_lock(ctrl);
2670 update_from_auto_cluster(master);
2672 user_to_new(c, ctrl);
2673 ret = try_or_set_cluster(fh, master,
true);
2674 cur_to_user(c, ctrl);
2676 v4l2_ctrl_unlock(ctrl);
2687 if (ctrl ==
NULL || !type_is_int(ctrl))
2735 v4l2_ctrl_lock(ctrl);
2744 fill_event(&ev, ctrl, changes);
2750 v4l2_ctrl_unlock(ctrl);
2758 v4l2_ctrl_lock(ctrl);
2760 v4l2_ctrl_unlock(ctrl);
2765 u32 old_changes = old->
u.
ctrl.changes;
2767 old->
u.
ctrl =
new->u.ctrl;
2768 old->
u.
ctrl.changes |= old_changes;
2774 new->u.ctrl.changes |= old->
u.
ctrl.changes;
2779 .add = v4l2_ctrl_add_event,
2780 .del = v4l2_ctrl_del_event,
2813 poll_wait(file, &fh->
wait, wait);