linux/Documentation/video4linux/v4l2-controls.txt
<<
v2.6.16... value="v2.6.12" >opttion> 2">opttion2">ptti class="lxr_search">2" < 2" >input typ hidden" nam navtarget" 2" >input typ text" nam search" id search">2" >butt> typ submit">Search on> opttion2">ptti class="lxr_p6.3s"ption va.6.35.+p6.3s?return=Documenta16../video4 > /v4l2-controls.txt"lue="v2onclick="return ajax_p6.3s();">2" P6.3sn> a>2">opttione="v2 divone="v2 2">input typ hidden" nam ajax_lookup" id ajax_lookup" 2e="v2 one="v2 divon div id content"on div id file_contents"p /v4l2-controls.txt#L1" id L1" class="line" nam L1">v2 1 a>Introduc16.. /v4l2-controls.txt#L2" id L2" class="line" nam L2">v2 2 a>============ /v4l2-controls.txt#L3" id L3" class="line" nam L3">v2 3 a>2 /v4l2-controls.txt#L4" id L4" class="line" nam L4">v2 4 a>The V4L2 control API seems simple enough, but quickly becomes very hard to2 /v4l2-controls.txt#L5" id L5" class="line" nam L5">v2 5 a>implement corr2.6ly in drivers. But much of the code needed to handle controls2 /v4l2-controls.txt#L6" id L6" class="line" nam L6">v2 6 a>is ac1ually not driver specific and cti be moved to the V4L core fram work.2 /v4l2-controls.txt#L7" id L7" class="line" nam L7">v2 7 a>2 /v4l2-controls.txt#L8" id L8" class="line" nam L8">v2 8 a>After all, the only part that a driver developer is interested in is:2 /v4l2-controls.txt#L9" id L9" class="line" nam L9">v2 9 a>2 /v4l2-controls.txt#L10" id L10" class="line" nam L10">v2on va>1) How do I add a control?2 /v4l2-controls.txt#L11" id L11" class="line" nam L11">v211 a>2) How do I set the control's /v4l2-controls.txt#L12" id L12" class="line" nam L12">v212 a>2 /v4l2-controls.txt#L13" id L13" class="line" nam L13">v213 a>And occas6..ally:2 /v4l2-controls.txt#L14" id L14" class="line" nam L14">v214 a>2 /v4l2-controls.txt#L15" id L15" class="line" nam L15">v215 a>3) How do I get the control's /v4l2-controls.txt#L16" id L16" class="line" nam L16">v216 a>4) How do I /v4l2-controls.txt#L17" id L17" class="line" nam L17">v217 a>2 /v4l2-controls.txt#L18" id L18" class="line" nam L18">v218 a>All the rest is something that cti be done centrally.2 /v4l2-controls.txt#L19" id L19" class="line" nam L19">v219 a>2 /v4l2-controls.txt#L20" id L20" class="line" nam L20">v220 a>The control fram work was created in order to implement all the rules of the2 /v4l2-controls.txt#L21" id L21" class="line" nam L21">v221 a>V4L2 specifica16.. with respect to controls in a central place. And to make2 /v4l2-controls.txt#L22" id L22" class="line" nam L22">v222 a>life as easy as possible < the driver developer.2 /v4l2-controls.txt#L23" id L23" class="line" nam L23">v223 a>2 /v4l2-controls.txt#L24" id L24" class="line" nam L24">v224 a>Note that the control fram work relies on the p6.sence of a struc1 v4l2_device2 /v4l2-controls.txt#L25" id L25" class="line" nam L25">v225 a> < V4L2 drivers and struc1 v4l2_subdev < sub-device drivers.2 /v4l2-controls.txt#L26" id L26" class="line" nam L26">v226 a>2 /v4l2-controls.txt#L27" id L27" class="line" nam L27">v227 a>2 /v4l2-controls.txt#L28" id L28" class="line" nam L28">v228 a>Objects in the fram work2 /v4l2-controls.txt#L29" id L29" class="line" nam L29">v229 a>======================== /v4l2-controls.txt#L30" id L30" class="line" nam L30">v230 a>2 /v4l2-controls.txt#L31" id L31" class="line" nam L31">v231 a>There are two main objects:2 /v4l2-controls.txt#L32" id L32" class="line" nam L32">v232 a>2 /v4l2-controls.txt#L33" id L33" class="line" nam L33">v233 a>The v4l2_ctrl object describes the control properties and keeps track of the2 /v4l2-controls.txt#L34" id L34" class="line" nam L34">v234 a>control's /v4l2-controls.txt#L35" id L35" class="line" nam L35">v235 a>2 /v4l2-controls.txt#L36" id L36" class="line" nam L36">v236 a>v4l2_ctrl_handler is the object that keeps track of controls. It maintains a2 /v4l2-controls.txt#L37" id L37" class="line" nam L37">v237 a>list of v4l2_ctrl objects that it owns and another list of 6.3erences to2 /v4l2-controls.txt#L38" id L38" class="line" nam L38">v238 a>controls, possibly to controls owned by other handlers.2 /v4l2-controls.txt#L39" id L39" class="line" nam L39">v239 a>2 /v4l2-controls.txt#L40" id L40" class="line" nam L40">v240 a>2 /v4l2-controls.txt#L41" id L41" class="line" nam L41">v241 a>Bas6c usage < V4L2 and sub-device drivers2 /v4l2-controls.txt#L42" id L42" class="line" nam L42">v242 a>===========================================2 /v4l2-controls.txt#L43" id L43" class="line" nam L43">v243 a>2 /v4l2-controls.txt#L44" id L44" class="line" nam L44">v244 va>1) Prepare the driver:2 /v4l2-controls.txt#L45" id L45" class="line" nam L45">v245 a>2 /v4l2-controls.txt#L46" id L46" class="line" nam L46">v246 a>1.1) Add the handler to your driver's top-level struc1:2 /v4l2-controls.txt#L47" id L47" class="line" nam L47">v247 a>2 /v4l2-controls.txt#L48" id L48" class="line" nam L48">v248 a> struc1 foo_dev {2 /v4l2-controls.txt#L49" id L49" class="line" nam L49">v249 a> ...2 /v4l2-controls.txt#L50" id L50" class="line" nam L50">v250 a> struc1 v4l2_ctrl_handler ctrl_handler;2 /v4l2-controls.txt#L51" id L51" class="line" nam L51">v251 a> ...2 /v4l2-controls.txt#L52" id L52" class="line" nam L52">v252 a> };2 /v4l2-controls.txt#L53" id L53" class="line" nam L53">v253 a>2 /v4l2-controls.txt#L54" id L54" class="line" nam L54">v254 a> struc1 foo_dev *foo;2 /v4l2-controls.txt#L55" id L55" class="line" nam L55">v255 a>2 /v4l2-controls.txt#L56" id L56" class="line" nam L56">v256 a>1.2) Initialize the handler:2 /v4l2-controls.txt#L57" id L57" class="line" nam L57">v257 a>2 /v4l2-controls.txt#L58" id L58" class="line" nam L58">v258 a> v4l2_ctrl_handler_init(&foo->ctrl_handler, nr_of_controls);2 /v4l2-controls.txt#L59" id L59" class="line" nam L59">v259 a>2 /v4l2-controls.txt#L60" id L60" class="line" nam L60">v260 a> The second argument is va.int telling the unc16.. how many controls this2 /v4l2-controls.txt#L61" id L61" class="line" nam L61">v261 a> handler is expected to handle. It will allocate va.ashtable based on this2 /v4l2-controls.txt#L62" id L62" class="line" nam L62">v262 a> in /v4l2-controls.txt#L63" id L63" class="line" nam L63">v263 a>2 /v4l2-controls.txt#L64" id L64" class="line" nam L64">v264 va>1.3) Hook the control handler into the driver:2 /v4l2-controls.txt#L65" id L65" class="line" nam L65">v265 a>2 /v4l2-controls.txt#L66" id L66" class="line" nam L66">v266 a>1.3.1) F < V4L2 drivers do this:2 /v4l2-controls.txt#L67" id L67" class="line" nam L67">v267 a>2 /v4l2-controls.txt#L68" id L68" class="line" nam L68">v268 a> struc1 foo_dev {2 /v4l2-controls.txt#L69" id L69" class="line" nam L69">v269 a> ...2 /v4l2-controls.txt#L70" id L70" class="line" nam L70">v270 a> struc1 v4l2_device v4l2_dev;2 /v4l2-controls.txt#L71" id L71" class="line" nam L71">v271 a> ...2 /v4l2-controls.txt#L72" id L72" class="line" nam L72">v272 a> struc1 v4l2_ctrl_handler ctrl_handler;2 /v4l2-controls.txt#L73" id L73" class="line" nam L73">v273 a> ...2 /v4l2-controls.txt#L74" id L74" class="line" nam L74">v274 a> };2 /v4l2-controls.txt#L75" id L75" class="line" nam L75">v275 a>2 /v4l2-controls.txt#L76" id L76" class="line" nam L76">v276 a> foo->v4l2_dev.ctrl_handler = &foo->ctrl_handler;2 /v4l2-controls.txt#L77" id L77" class="line" nam L77">v277 a>2 /v4l2-controls.txt#L78" id L78" class="line" nam L78">v278 a> Where foo->v4l2_dev is of type struc1 v4l2_device.2 /v4l2-controls.txt#L79" id L79" class="line" nam L79">v279 a>2 /v4l2-controls.txt#L80" id L80" class="line" nam L80">v280 a> Fi.ally, remove all control func16..s from your v4l2_ioctl_ops:2 /v4l2-controls.txt#L81" id L81" class="line" nam L81">v281 a> vidioc_queryctrl, vidioc_querymenu, vidioc_g_ctrl, vidioc_s_ctrl,2 /v4l2-controls.txt#L82" id L82" class="line" nam L82">v282 a> vidioc_g_ext_ctrls, vidioc_try_ext_ctrls and vidioc_s_ext_ctrls.2 /v4l2-controls.txt#L83" id L83" class="line" nam L83">v283 a> Those are now no longer needed.2 /v4l2-controls.txt#L84" id L84" class="line" nam L84">v284 a>2 /v4l2-controls.txt#L85" id L85" class="line" nam L85">v285 a>1.3.2) F < sub-device drivers do this:2 /v4l2-controls.txt#L86" id L86" class="line" nam L86">v286 a>2 /v4l2-controls.txt#L87" id L87" class="line" nam L87">v287 a> struc1 foo_dev {2 /v4l2-controls.txt#L88" id L88" class="line" nam L88">v288 a> ...2 /v4l2-controls.txt#L89" id L89" class="line" nam L89">v289 a> struc1 v4l2_subdev sd;2 /v4l2-controls.txt#L90" id L90" class="line" nam L90">v290 a> ...2 /v4l2-controls.txt#L91" id L91" class="line" nam L91">v291 a> struc1 v4l2_ctrl_handler ctrl_handler;2 /v4l2-controls.txt#L92" id L92" class="line" nam L92">v292 a> ...2 /v4l2-controls.txt#L93" id L93" class="line" nam L93">v293 a> };2 /v4l2-controls.txt#L94" id L94" class="line" nam L94">v294 a>2 /v4l2-controls.txt#L95" id L95" class="line" nam L95">v295 a> foo->sd.ctrl_handler = &foo->ctrl_handler;2 /v4l2-controls.txt#L96" id L96" class="line" nam L96">v296 a>2 /v4l2-controls.txt#L97" id L97" class="line" nam L97">v297 a> Where foo->sd is of type struc1 v4l2_subdev.2 /v4l2-controls.txt#L98" id L98" class="line" nam L98">v298 a>2 /v4l2-controls.txt#L99" id L99" class="line" nam L99">v299 a> And set all core control ops in your struc1 v4l2_subdev_core_ops to these2 /v4l2-controls.txt#L100" id L100" class="line" nam L100">v100 a> helpers:2 /v4l2-controls.txt#L101" id L101" class="line" nam L101">v101 a>2 /v4l2-controls.txt#L102" id L102" class="line" nam L102">v102 a> .queryctrl = v4l2_subdev_queryctrl,2 /v4l2-controls.txt#L103" id L103" class="line" nam L103">v103 a> .querymenu = v4l2_subdev_querymenu,2 /v4l2-controls.txt#L104" id L104" class="line" nam L104">v104 a> .g_ctrl = v4l2_subdev_g_ctrl,2 /v4l2-controls.txt#L105" id L105" class="line" nam L105">v105 a> .s_ctrl = v4l2_subdev_s_ctrl,2 /v4l2-controls.txt#L106" id L106" class="line" nam L106">v106 a> .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,2 /v4l2-controls.txt#L107" id L107" class="line" nam L107">v107 a> .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,2 /v4l2-controls.txt#L108" id L108" class="line" nam L108">v108 a> .s_ext_ctrls = v4l2_subdev_s_ext_ctrls,2 /v4l2-controls.txt#L109" id L109" class="line" nam L109">v109 a>2 /v4l2-controls.txt#L110" id L110" class="line" nam L110">v110 a> Note: this is vatemporary solu16.. only. Once all V4L2 drivers that depend2 /v4l2-controls.txt#L111" id L111" class="line" nam L111">v111 a> .. subdev drivers are converted to the control fram work these helpers will2 /v4l2-controls.txt#L112" id L112" class="line" nam L112">v112 a> no longer be needed.2 /v4l2-controls.txt#L113" id L113" class="line" nam L113">v113 a>2 /v4l2-controls.txt#L114" id L114" class="line" nam L114">v114 va>1.4) Clean up the handler at the end:2 /v4l2-controls.txt#L115" id L115" class="line" nam L115">v115 a>2 /v4l2-controls.txt#L116" id L116" class="line" nam L116">v116 a> v4l2_ctrl_handler_free(&foo->ctrl_handler);2 /v4l2-controls.txt#L117" id L117" class="line" nam L117">v117 a>2 /v4l2-controls.txt#L118" id L118" class="line" nam L118">v118 a>2 /v4l2-controls.txt#L119" id L119" class="line" nam L119">v119 a>2) Add controls:2 /v4l2-controls.txt#L120" id L120" class="line" nam L120">v120 a>2 /v4l2-controls.txt#L121" id L121" class="line" nam L121">v121 a>You add non-menu controls by calling v4l2_ctrl_new_std:2 /v4l2-controls.txt#L122" id L122" class="line" nam L122">v122 a>2 /v4l2-controls.txt#L123" id L123" class="line" nam L123">v123 a> struc1 v4l2_ctrl *v4l2_ctrl_new_std(struc1 v4l2_ctrl_handler *hdl,2 /v4l2-controls.txt#L124" id L124" class="line" nam L124">v124 a> const struc1 v4l2_ctrl_ops *ops,2 /v4l2-controls.txt#L125" id L125" class="line" nam L125">v125 a> u32 id, s32 min, s32 max, u32 step, s32 def);2 /v4l2-controls.txt#L126" id L126" class="line" nam L126">v126 a>2 /v4l2-controls.txt#L127" id L127" class="line" nam L127">v127 a>Menu controls are added by calling v4l2_ctrl_new_std_menu:2 /v4l2-controls.txt#L128" id L128" class="line" nam L128">v128 a>2 /v4l2-controls.txt#L129" id L129" class="line" nam L129">v129 a> struc1 v4l2_ctrl *v4l2_ctrl_new_std_menu(struc1 v4l2_ctrl_handler *hdl,2 /v4l2-controls.txt#L130" id L130" class="line" nam L130">v130 a> const struc1 v4l2_ctrl_ops *ops,2 /v4l2-controls.txt#L131" id L131" class="line" nam L131">v131 a> u32 id, s32 max, s32 skip_mask, s32 def);2 /v4l2-controls.txt#L132" id L132" class="line" nam L132">v132 a>2 /v4l2-controls.txt#L133" id L133" class="line" nam L133">v133 a>Or alterna16vely < integer menu controls, by calling v4l2_ctrl_new_int_menu:2 /v4l2-controls.txt#L134" id L134" class="line" nam L134">v134 a>2 /v4l2-controls.txt#L135" id L135" class="line" nam L135">v135 a> struc1 v4l2_ctrl *v4l2_ctrl_new_int_menu(struc1 v4l2_ctrl_handler *hdl,2 /v4l2-controls.txt#L136" id L136" class="line" nam L136">v136 a> const struc1 v4l2_ctrl_ops *ops,2 /v4l2-controls.txt#L137" id L137" class="line" nam L137">v137 a> u32 id, s32 max, s32 def, const s64 *qmenu_int);2 /v4l2-controls.txt#L138" id L138" class="line" nam L138">v138 a>2 /v4l2-controls.txt#L139" id L139" class="line" nam L139">v139 a>These func16..s are typically called right after the v4l2_ctrl_handler_init:2 /v4l2-controls.txt#L140" id L140" class="line" nam L140">v140 a>2 /v4l2-controls.txt#L141" id L141" class="line" nam L141">v141 a> sta16c const s64 exp_bias_qmenu[] = {2 /v4l2-controls.txt#L142" id L142" class="line" nam L142">v142 a> -2, -1, 0, 1, 22 /v4l2-controls.txt#L143" id L143" class="line" nam L143">v143 a> };2 /v4l2-controls.txt#L144" id L144" class="line" nam L144">v144 a>2 /v4l2-controls.txt#L145" id L145" class="line" nam L145">v145 a> v4l2_ctrl_handler_init(&foo->ctrl_handler, nr_of_controls);2 /v4l2-controls.txt#L146" id L146" class="line" nam L146">v146 a> v4l2_ctrl_new_std(&foo->ctrl_handler, &foo_ctrl_ops,2 /v4l2-controls.txt#L147" id L147" class="line" nam L147">v147 a> V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);2 /v4l2-controls.txt#L148" id L148" class="line" nam L148">v148 a> v4l2_ctrl_new_std(&foo->ctrl_handler, &foo_ctrl_ops,2 /v4l2-controls.txt#L149" id L149" class="line" nam L149">v149 a> V4L2_CID_CONTRAST, 0, 255, 1, 128);2 /v4l2-controls.txt#L150" id L150" class="line" nam L150">v150 a> v4l2_ctrl_new_std_menu(&foo->ctrl_handler, &foo_ctrl_ops,2 /v4l2-controls.txt#L151" id L151" class="line" nam L151">v151 a> V4L2_CID_POWER_LINE_FREQUENCY,2 /v4l2-controls.txt#L152" id L152" class="line" nam L152">v152 a> V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0,2 /v4l2-controls.txt#L153" id L153" class="line" nam L153">v153 a> V4L2_CID_POWER_LINE_FREQUENCY_DISABLED);2 /v4l2-controls.txt#L154" id L154" class="line" nam L154">v154 a> v4l2_ctrl_new_int_menu(&foo->ctrl_handler, &foo_ctrl_ops,2 /v4l2-controls.txt#L155" id L155" class="line" nam L155">v155 a> V4L2_CID_EXPOSURE_BIAS,2 /v4l2-controls.txt#L156" id L156" class="line" nam L156">v156 a> ARRAY_SIZE(exp_bias_qmenu) - 1,2 /v4l2-controls.txt#L157" id L157" class="line" nam L157">v157 a> ARRAY_SIZE(exp_bias_qmenu) / 2 - 1,2 /v4l2-controls.txt#L158" id L158" class="line" nam L158">v158 a> exp_bias_qmenu);2 /v4l2-controls.txt#L159" id L159" class="line" nam L159">v159 a> ...2 /v4l2-controls.txt#L160" id L160" class="line" nam L160">v160 a> if (foo->ctrl_handler.error) {2 /v4l2-controls.txt#L161" id L161" class="line" nam L161">v161 a> int err = foo->ctrl_handler.error;2 /v4l2-controls.txt#L162" id L162" class="line" nam L162">v162 a>2 /v4l2-controls.txt#L163" id L163" class="line" nam L163">v163 a> v4l2_ctrl_handler_free(&foo->ctrl_handler);2 /v4l2-controls.txt#L164" id L164" class="line" nam L164">v164 a> return err;2 /v4l2-controls.txt#L165" id L165" class="line" nam L165">v165 a> }2 /v4l2-controls.txt#L166" id L166" class="line" nam L166">v166 a>2 /v4l2-controls.txt#L167" id L167" class="line" nam L167">v167 a>The v4l2_ctrl_new_std unc16.. returns the v4l2_ctrl pointer to the new2 /v4l2-controls.txt#L168" id L168" class="line" nam L168">v168 a>control, but if you do not need to access the pointer outside the control ops,2 /v4l2-controls.txt#L169" id L169" class="line" nam L169">v169 a>then there is no need to store it.2 /v4l2-controls.txt#L170" id L170" class="line" nam L170">v170 a>2 /v4l2-controls.txt#L171" id L171" class="line" nam L171">v171 a>The v4l2_ctrl_new_std unc16.. will fill in most fields based on the control2 /v4l2-controls.txt#L172" id L172" class="line" nam L172">v172 a>ID except < the min, max, step and default /v4l2-controls.txt#L173" id L173" class="line" nam L173">v173 a>last ur arguments. These /v4l2-controls.txt#L174" id L174" class="line" nam L174">v174 a>like type, nam , flags are all global. The control's curr2nt /v4l2-controls.txt#L175" id L175" class="line" nam L175">v175 a>to the default /v4l2-controls.txt#L176" id L176" class="line" nam L176">v176 a>2 /v4l2-controls.txt#L177" id L177" class="line" nam L177">v177 a>The v4l2_ctrl_new_std_menu unc16.. is very similar but it is used < menu2 /v4l2-controls.txt#L178" id L178" class="line" nam L178">v178 a>controls. There is no min argument since that is always 0 < menu controls,2 /v4l2-controls.txt#L179" id L179" class="line" nam L179">v179 a>and instead of a step there is a skip_mask argument: if bit X is 1, then menu2 /v4l2-controls.txt#L180" id L180" class="line" nam L180">v180 a>item X is skipped.2 /v4l2-controls.txt#L181" id L181" class="line" nam L181">v181 a>2 /v4l2-controls.txt#L182" id L182" class="line" nam L182">v182 a>The v4l2_ctrl_new_int_menu unc16.. creates a new standard integer menu2 /v4l2-controls.txt#L183" id L183" class="line" nam L183">v183 a>control with driver-specific items in the menu. It differs from2 /v4l2-controls.txt#L184" id L184" class="line" nam L184">v184 a>v4l2_ctrl_new_std_menu in that it doesn't have the mask argument and takes2 /v4l2-controls.txt#L185" id L185" class="line" nam L185">v185 a>as the last argument an array of signed 64-bit integers that /v4l2-controls.txt#L186" id L186" class="line" nam L186">v186 a>menu item list.2 /v4l2-controls.txt#L187" id L187" class="line" nam L187">v187 a>2 /v4l2-controls.txt#L188" id L188" class="line" nam L188">v188 a>Note that if something fails, the unc16.. will return NULL < an err < and2 /v4l2-controls.txt#L189" id L189" class="line" nam L189">v189 a>set ctrl_handler->err < to the err < code. If ctrl_handler->err < was already2 /v4l2-controls.txt#L190" id L190" class="line" nam L190">v190 a>set, then it will just return and do nothing. This is vlso true <2 /v4l2-controls.txt#L191" id L191" class="line" nam L191">v191 a>v4l2_ctrl_handler_init if it ctinot allocate the internal data struc1ur .2 /v4l2-controls.txt#L192" id L192" class="line" nam L192">v192 a>2 /v4l2-controls.txt#L193" id L193" class="line" nam L193">v193 a>This makes it easy to init the handler and just add all controls and only check2 /v4l2-controls.txt#L194" id L194" class="line" nam L194">v194 a>the err < code at the end. Saves a lot of 6.peti16ve err < checking.2 /v4l2-controls.txt#L195" id L195" class="line" nam L195">v195 a>2 /v4l2-controls.txt#L196" id L196" class="line" nam L196">v196 a>It is recommended to add controls in ascending control ID order: it will be2 /v4l2-controls.txt#L197" id L197" class="line" nam L197">v197 a>a bit faster that way.2 /v4l2-controls.txt#L198" id L198" class="line" nam L198">v198 a>2 /v4l2-controls.txt#L199" id L199" class="line" nam L199">v199 a>3) O.16..ally /v4l2-controls.txt#L200" id L200" class="line" nam L200">v200 a>2 /v4l2-controls.txt#L201" id L201" class="line" nam L201">v201 a> v4l2_ctrl_handler_setup(&foo->ctrl_handler);2 /v4l2-controls.txt#L202" id L202" class="line" nam L202">v202 a>2 /v4l2-controls.txt#L203" id L203" class="line" nam L203">v203 a>This will call s_ctrl < all controls uncondi16..ally. Effec16vely this2 /v4l2-controls.txt#L204" id L204" class="line" nam L204">v204 a>initializes the hardware to the default control /v4l2-controls.txt#L205" id L205" class="line" nam L205">v205 a>that you do this as this ensur s that both the internal data struc1ur s and2 /v4l2-controls.txt#L206" id L206" class="line" nam L206">v206 a>the hardware are in sync.2 /v4l2-controls.txt#L207" id L207" class="line" nam L207">v207 a>2 /v4l2-controls.txt#L208" id L208" class="line" nam L208">v208 a>4) Fi.ally: implement the v4l2_ctrl_ops2 /v4l2-controls.txt#L209" id L209" class="line" nam L209">v209 a>2 /v4l2-controls.txt#L210" id L210" class="line" nam L210">v210 a> sta16c const struc1 v4l2_ctrl_ops foo_ctrl_ops = {2 /v4l2-controls.txt#L211" id L211" class="line" nam L211">v211 a> .s_ctrl = foo_s_ctrl,2 /v4l2-controls.txt#L212" id L212" class="line" nam L212">v212 a> };2 /v4l2-controls.txt#L213" id L213" class="line" nam L213">v213 a>2 /v4l2-controls.txt#L214" id L214" class="line" nam L214">v214 va>Usually all you need is s_ctrl:2 /v4l2-controls.txt#L215" id L215" class="line" nam L215">v215 a>2 /v4l2-controls.txt#L216" id L216" class="line" nam L216">v216 a> sta16c int foo_s_ctrl(struc1 v4l2_ctrl *ctrl)2 /v4l2-controls.txt#L217" id L217" class="line" nam L217">v217 a> {2 /v4l2-controls.txt#L218" id L218" class="line" nam L218">v218 a> struc1 foo *sta1e = container_of(ctrl->handler, struc1 foo, ctrl_handler);2 /v4l2-controls.txt#L219" id L219" class="line" nam L219">v219 a>2 /v4l2-controls.txt#L220" id L220" class="line" nam L220">v220 a> switch (ctrl->id) {2 /v4l2-controls.txt#L221" id L221" class="line" nam L221">v221 a> case V4L2_CID_BRIGHTNESS:2 /v4l2-controls.txt#L222" id L222" class="line" nam L222">v222 a> write_reg(0x123, ctrl->val);2 /v4l2-controls.txt#L223" id L223" class="line" nam L223">v223 a> break;2 /v4l2-controls.txt#L224" id L224" class="line" nam L224">v224 a> case V4L2_CID_CONTRAST:2 /v4l2-controls.txt#L225" id L225" class="line" nam L225">v225 a> write_reg(0x456, ctrl->val);2 /v4l2-controls.txt#L226" id L226" class="line" nam L226">v226 a> break;2 /v4l2-controls.txt#L227" id L227" class="line" nam L227">v227 a> }2 /v4l2-controls.txt#L228" id L228" class="line" nam L228">v228 a> return 0;2 /v4l2-controls.txt#L229" id L229" class="line" nam L229">v229 a> }2 /v4l2-controls.txt#L230" id L230" class="line" nam L230">v230 a>2 /v4l2-controls.txt#L231" id L231" class="line" nam L231">v231 a>The control ops are called with the v4l2_ctrl pointer as argument.2 /v4l2-controls.txt#L232" id L232" class="line" nam L232">v232 a>The new control /v4l2-controls.txt#L233" id L233" class="line" nam L233">v233 a>to ac1ually update the hardware registers.2 /v4l2-controls.txt#L234" id L234" class="line" nam L234">v234 a>2 /v4l2-controls.txt#L235" id L235" class="line" nam L235">v235 a>You're done! And this is sufficient < most of the drivers we have. No need2 /v4l2-controls.txt#L236" id L236" class="line" nam L236">v236 a>to do any /v4l2-controls.txt#L237" id L237" class="line" nam L237">v237 a>G/S_CTRL as well as G/TRY/S_EXT_CTRLS are autooa16cally supported.2 /v4l2-controls.txt#L238" id L238" class="line" nam L238">v238 a>2 /v4l2-controls.txt#L239" id L239" class="line" nam L239">v239 a>2 /v4l2-controls.txt#L240" id L240" class="line" nam L240">v240 a>==============================================================================2 /v4l2-controls.txt#L241" id L241" class="line" nam L241">v241 a>2 /v4l2-controls.txt#L242" id L242" class="line" nam L242">v242 a>The remainder of this document deals with more advanced topics and scenarios.2 /v4l2-controls.txt#L243" id L243" class="line" nam L243">v243 a>In prac1ice the bas6c usage as described above is sufficient < most drivers.2 /v4l2-controls.txt#L244" id L244" class="line" nam L244">v244 a>2 /v4l2-controls.txt#L245" id L245" class="line" nam L245">v245 a>===============================================================================2 /v4l2-controls.txt#L246" id L246" class="line" nam L246">v246 a>2 /v4l2-controls.txt#L247" id L247" class="line" nam L247">v247 a>2 /v4l2-controls.txt#L248" id L248" class="line" nam L248">v248 a>Inheriting Controls2 /v4l2-controls.txt#L249" id L249" class="line" nam L249">v249 a>===================2 /v4l2-controls.txt#L250" id L250" class="line" nam L250">v250 a>2 /v4l2-controls.txt#L251" id L251" class="line" nam L251">v251 a>When a sub-device is registered with a V4L2 driver by calling2 /v4l2-controls.txt#L252" id L252" class="line" nam L252">v252 a>v4l2_device_register_subdev() and the ctrl_handler fields of both v4l2_subdev2 /v4l2-controls.txt#L253" id L253" class="line" nam L253">v253 a>and v4l2_device are set, then the controls of the subdev will become2 /v4l2-controls.txt#L254" id L254" class="line" nam L254">v254 a>autooa16cally available in the V4L2 driver as well. If the subdev driver2 /v4l2-controls.txt#L255" id L255" class="line" nam L255">v255 a>contains controls that already exist in the V4L2 driver, then those will be2 /v4l2-controls.txt#L256" id L256" class="line" nam L256">v256 a>skipped (so a V4L2 driver can always override a subdev control).2 /v4l2-controls.txt#L257" id L257" class="line" nam L257">v257 a>2 /v4l2-controls.txt#L258" id L258" class="line" nam L258">v258 a>What happens here is that v4l2_device_register_subdev() calls2 /v4l2-controls.txt#L259" id L259" class="line" nam L259">v259 a>v4l2_ctrl_add_handler() adding the controls of the subdev to the controls2 /v4l2-controls.txt#L260" id L260" class="line" nam L260">v260 a>of v4l2_device.2 /v4l2-controls.txt#L261" id L261" class="line" nam L261">v261 a>2 /v4l2-controls.txt#L262" id L262" class="line" nam L262">v262 a>2 /v4l2-controls.txt#L263" id L263" class="line" nam L263">v263 a>Accessing Control V /v4l2-controls.txt#L264" id L264" class="line" nam L264">v264 a>========================2 /v4l2-controls.txt#L265" id L265" class="line" nam L265">v265 a>2 /v4l2-controls.txt#L266" id L266" class="line" nam L266">v266 a>The v4l2_ctrl struc1 contains these two un6..s:2 /v4l2-controls.txt#L267" id L267" class="line" nam L267">v267 a>2 /v4l2-controls.txt#L268" id L268" class="line" nam L268">v268 a> /* The curr2nt control /v4l2-controls.txt#L269" id L269" class="line" nam L269">v269 a> un6.. {2 /v4l2-controls.txt#L270" id L270" class="line" nam L270">v270 a> s32 <;2 /v4l2-controls.txt#L271" id L271" class="line" nam L271">v271 a> s64 <64;2 /v4l2-controls.txt#L272" id L272" class="line" nam L272">v272 a> char *string;2 /v4l2-controls.txt#L273" id L273" class="line" nam L273">v273 a> } cur;2 /v4l2-controls.txt#L274" id L274" class="line" nam L274">v274 a>2 /v4l2-controls.txt#L275" id L275" class="line" nam L275">v275 a> /* The new control /v4l2-controls.txt#L276" id L276" class="line" nam L276">v276 a> un6.. {2 /v4l2-controls.txt#L277" id L277" class="line" nam L277">v277 a> s32 <;2 /v4l2-controls.txt#L278" id L278" class="line" nam L278">v278 a> s64 <64;2 /v4l2-controls.txt#L279" id L279" class="line" nam L279">v279 a> char *string;2 /v4l2-controls.txt#L280" id L280" class="line" nam L280">v280 a> };2 /v4l2-controls.txt#L281" id L281" class="line" nam L281">v281 a>2 /v4l2-controls.txt#L282" id L282" class="line" nam L282">v282 a>Within the control ops you can freely use these. The < and v <64 speak <2 /v4l2-controls.txt#L283" id L283" class="line" nam L283">v283 a>themselv s. The string pointers point to character buffers of length2 /v4l2-controls.txt#L284" id L284" class="line" nam L284">v284 a>ctrl->maximum + 1, and are always 0-terminated.2 /v4l2-controls.txt#L285" id L285" class="line" nam L285">v285 a>2 /v4l2-controls.txt#L286" id L286" class="line" nam L286">v286 a>In most cases 'cur' contains the curr2nt cached control /v4l2-controls.txt#L287" id L287" class="line" nam L287">v287 a>a new control this /v4l2-controls.txt#L288" id L288" class="line" nam L288">v288 a>v4l2_ctrl_handler_setup() this /v4l2-controls.txt#L289" id L289" class="line" nam L289">v289 a>a good idea to call this unc16...2 /v4l2-controls.txt#L290" id L290" class="line" nam L290">v290 a>2 /v4l2-controls.txt#L291" id L291" class="line" nam L291">v291 a>Whenever a new /v4l2-controls.txt#L292" id L292" class="line" nam L292">v292 a>that most drivers do not need to implement the g_vola16le_ctrl() op. The2 /v4l2-controls.txt#L293" id L293" class="line" nam L293">v293 a>except6.. is f < controls that return a vola16le register such as a signal2 /v4l2-controls.txt#L294" id L294" class="line" nam L294">v294 a>strength read-out that changes cont >ously. In that case you will need to2 /v4l2-controls.txt#L295" id L295" class="line" nam L295">v295 a>implement g_vola16le_ctrl like this:2 /v4l2-controls.txt#L296" id L296" class="line" nam L296">v296 a>2 /v4l2-controls.txt#L297" id L297" class="line" nam L297">v297 a> sta16c int foo_g_vola16le_ctrl(struc1 v4l2_ctrl *ctrl)2 /v4l2-controls.txt#L298" id L298" class="line" nam L298">v298 a> {2 /v4l2-controls.txt#L299" id L299" class="line" nam L299">v299 a> switch (ctrl->id) {2 /v4l2-controls.txt#L300" id L300" class="line" nam L300">v300 a> case V4L2_CID_BRIGHTNESS:2 /v4l2-controls.txt#L301" id L301" class="line" nam L301">v301 a> ctrl->val = read_reg(0x123);2 /v4l2-controls.txt#L302" id L302" class="line" nam L302">v302 a> break;2 /v4l2-controls.txt#L303" id L303" class="line" nam L303">v303 a> }2 /v4l2-controls.txt#L304" id L304" class="line" nam L304">v304 a> }2 /v4l2-controls.txt#L305" id L305" class="line" nam L305">v305 a>2 /v4l2-controls.txt#L306" id L306" class="line" nam L306">v306 a>Note that you use the 'new /v4l2-controls.txt#L307" id L307" class="line" nam L307">v307 a>controls that need to implement g_vola16le_ctrl are read-only controls.2 /v4l2-controls.txt#L308" id L308" class="line" nam L308">v308 a>2 /v4l2-controls.txt#L309" id L309" class="line" nam L309">v309 a>To mark a control as vola16le you have to set V4L2_CTRL_FLAG_VOLATILE:2 /v4l2-controls.txt#L310" id L310" class="line" nam L310">v310 a>2 /v4l2-controls.txt#L311" id L311" class="line" nam L311">v311 a> ctrl = v4l2_ctrl_new_std(&sd->ctrl_handler, ...);2 /v4l2-controls.txt#L312" id L312" class="line" nam L312">v312 a> if (ctrl)2 /v4l2-controls.txt#L313" id L313" class="line" nam L313">v313 a> ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;2 /v4l2-controls.txt#L314" id L314" class="line" nam L314">v314 a>2 /v4l2-controls.txt#L315" id L315" class="line" nam L315">v315 a>F < try/s_ctrl the new /v4l2-controls.txt#L316" id L316" class="line" nam L316">v316 a>you can modify them in try_ctrl < set them in s_ctrl. The 'cur' un6..2 /v4l2-controls.txt#L317" id L317" class="line" nam L317">v317 a>contains the curr2nt /v4l2-controls.txt#L318" id L318" class="line" nam L318">v318 a>2 /v4l2-controls.txt#L319" id L319" class="line" nam L319">v319 a>If s_ctrl returns 0 (OK), then the control fram work will copy the new final2 /v4l2-controls.txt#L320" id L320" class="line" nam L320">v320 a> /v4l2-controls.txt#L321" id L321" class="line" nam L321">v321 a>2 /v4l2-controls.txt#L322" id L322" class="line" nam L322">v322 a>While in g_vola16le/s/try_ctrl you can access the /v4l2-controls.txt#L323" id L323" class="line" nam L323">v323 a>by the sam handler since th handler's lock is held. If you need to access2 /v4l2-controls.txt#L324" id L324" class="line" nam L324">v324 a>the /v4l2-controls.txt#L325" id L325" class="line" nam L325">v325 a>not to introduce deadlocks.2 /v4l2-controls.txt#L326" id L326" class="line" nam L326">v326 a>2 /v4l2-controls.txt#L327" id L327" class="line" nam L327">v327 a>Outside of the control ops you have to go through to helper func16..s to get2 /v4l2-controls.txt#L328" id L328" class="line" nam L328">v328 a> < set a single control /v4l2-controls.txt#L329" id L329" class="line" nam L329">v329 a>2 /v4l2-controls.txt#L330" id L330" class="line" nam L330">v330 a> s32 4l2_ctrl_g_ctrl(struc1 v4l2_ctrl *ctrl);2 /v4l2-controls.txt#L331" id L331" class="line" nam L331">v331 a> int 4l2_ctrl_s_ctrl(struc1 v4l2_ctrl *ctrl, s32 <);2 /v4l2-controls.txt#L332" id L332" class="line" nam L332">v332 a>2 /v4l2-controls.txt#L333" id L333" class="line" nam L333">v333 a>These func16..s go through the control fram work just as VIDIOC_G/S_CTRL ioctls2 /v4l2-controls.txt#L334" id L334" class="line" nam L334">v334 a>do. Don't use these inside the control ops g_vola16le/s/try_ctrl, though, that2 /v4l2-controls.txt#L335" id L335" class="line" nam L335">v335 a>will result in a deadlock since th se helpers lock the handler as well.2 /v4l2-controls.txt#L336" id L336" class="line" nam L336">v336 a>2 /v4l2-controls.txt#L337" id L337" class="line" nam L337">v337 a>You can also take th handler lock yourself:2 /v4l2-controls.txt#L338" id L338" class="line" nam L338">v338 a>2 /v4l2-controls.txt#L339" id L339" class="line" nam L339">v339 a> mutex_lock(&sta1e->ctrl_handler.lock);2 /v4l2-controls.txt#L340" id L340" class="line" nam L340">v340 a> printk(KERN_INFO "String /v4l2-controls.txt#L341" id L341" class="line" nam L341">v341 a> printk(KERN_INFO "Integer /v4l2-controls.txt#L342" id L342" class="line" nam L342">v342 a> mutex_unlock(&sta1e->ctrl_handler.lock);2 /v4l2-controls.txt#L343" id L343" class="line" nam L343">v343 a>2 /v4l2-controls.txt#L344" id L344" class="line" nam L344">v344 a>2 /v4l2-controls.txt#L345" id L345" class="line" nam L345">v345 a>Menu Controls2 /v4l2-controls.txt#L346" id L346" class="line" nam L346">v346 a>=============2 /v4l2-controls.txt#L347" id L347" class="line" nam L347">v347 a>2 /v4l2-controls.txt#L348" id L348" class="line" nam L348">v348 a>The v4l2_ctrl struc1 contains this un6..:2 /v4l2-controls.txt#L349" id L349" class="line" nam L349">v349 a>2 /v4l2-controls.txt#L350" id L350" class="line" nam L350">v350 a> un6.. {2 /v4l2-controls.txt#L351" id L351" class="line" nam L351">v351 a> u32 step;2 /v4l2-controls.txt#L352" id L352" class="line" nam L352">v352 a> u32 menu_skip_mask;2 /v4l2-controls.txt#L353" id L353" class="line" nam L353">v353 a> };2 /v4l2-controls.txt#L354" id L354" class="line" nam L354">v354 a>2 /v4l2-controls.txt#L355" id L355" class="line" nam L355">v355 a>F < menu controls menu_skip_mask is used. What it does is that it allows you2 /v4l2-controls.txt#L356" id L356" class="line" nam L356">v356 a>to easily exclude certain menu items. This is used in the VIDIOC_QUERYMENU2 /v4l2-controls.txt#L357" id L357" class="line" nam L357">v357 a>implementa16.. where you can return -EINVAL if a certain menu item is not2 /v4l2-controls.txt#L358" id L358" class="line" nam L358">v358 a>present. Note that VIDIOC_QUERYCTRL always returns a step /v4l2-controls.txt#L359" id L359" class="line" nam L359">v359 a>menu controls.2 /v4l2-controls.txt#L360" id L360" class="line" nam L360">v360 a>2 /v4l2-controls.txt#L361" id L361" class="line" nam L361">v361 a>A good example is the MPEG Audio Layer II Bitrate menu control where the2 /v4l2-controls.txt#L362" id L362" class="line" nam L362">v362 a>menu is a list of standardized possible bitrates. But in prac1ice hardware2 /v4l2-controls.txt#L363" id L363" class="line" nam L363">v363 a>implementa16..s will only support a subset of those. By setting the skip2 /v4l2-controls.txt#L364" id L364" class="line" nam L364">v364 a>mask you can tell the fram work which menu items should be skipped. Setting2 /v4l2-controls.txt#L365" id L365" class="line" nam L365">v365 a>it to 0 means that all menu items are supported.2 /v4l2-controls.txt#L366" id L366" class="line" nam L366">v366 a>2 /v4l2-controls.txt#L367" id L367" class="line" nam L367">v367 a>You set this mask either through the 4l2_ctrl_config struc1 for a custom2 /v4l2-controls.txt#L368" id L368" class="line" nam L368">v368 a>control, or by calling v4l2_ctrl_new_std_menu().2 /v4l2-controls.txt#L369" id L369" class="line" nam L369">v369 a>2 /v4l2-controls.txt#L370" id L370" class="line" nam L370">v370 a>2 /v4l2-controls.txt#L371" id L371" class="line" nam L371">v371 a>Custom Controls2 /v4l2-controls.txt#L372" id L372" class="line" nam L372">v372 a>===============2 /v4l2-controls.txt#L373" id L373" class="line" nam L373">v373 a>2 /v4l2-controls.txt#L374" id L374" class="line" nam L374">v374 a>Driver specific controls can be created using v4l2_ctrl_new_custom():2 /v4l2-controls.txt#L375" id L375" class="line" nam L375">v375 a>2 /v4l2-controls.txt#L376" id L376" class="line" nam L376">v376 a> sta16c const struc1 v4l2_ctrl_config ctrl_filter = {2 /v4l2-controls.txt#L377" id L377" class="line" nam L377">v377 a> .ops = &ctrl_custom_ops,2 /v4l2-controls.txt#L378" id L378" class="line" nam L378">v378 a> .id = V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER,2 /v4l2-controls.txt#L379" id L379" class="line" nam L379">v379 a> .nam = "Spatial Filter",2 /v4l2-controls.txt#L380" id L380" class="line" nam L380">v380 a> .type = V4L2_CTRL_TYPE_INTEGER,2 /v4l2-controls.txt#L381" id L381" class="line" nam L381">v381 a> .flags = V4L2_CTRL_FLAG_SLIDER,2 /v4l2-controls.txt#L382" id L382" class="line" nam L382">v382 a> .max = 15,2 /v4l2-controls.txt#L383" id L383" class="line" nam L383">v383 a> .step = 1,2 /v4l2-controls.txt#L384" id L384" class="line" nam L384">v384 a> };2 /v4l2-controls.txt#L385" id L385" class="line" nam L385">v385 a>2 /v4l2-controls.txt#L386" id L386" class="line" nam L386">v386 a> ctrl = v4l2_ctrl_new_custom(&foo->ctrl_handler, &ctrl_filter, NULL);2 /v4l2-controls.txt#L387" id L387" class="line" nam L387">v387 a>2 /v4l2-controls.txt#L388" id L388" class="line" nam L388">v388 a>The last argument is the priv pointer which can be set to driver-specific2 /v4l2-controls.txt#L389" id L389" class="line" nam L389">v389 a>private data.2 /v4l2-controls.txt#L390" id L390" class="line" nam L390">v390 a>2 /v4l2-controls.txt#L391" id L391" class="line" nam L391">v391 a>The v4l2_ctrl_config struc1 also .as a field to set the is_private flag.2 /v4l2-controls.txt#L392" id L392" class="line" nam L392">v392 a>2 /v4l2-controls.txt#L393" id L393" class="line" nam L393">v393 a>If the nam field is not set, then the fram work will assume this is a standard2 /v4l2-controls.txt#L394" id L394" class="line" nam L394">v394 a>control and will fill in the nam , type and flags fields accordingly.2 /v4l2-controls.txt#L395" id L395" class="line" nam L395">v395 a>2 /v4l2-controls.txt#L396" id L396" class="line" nam L396">v396 a>2 /v4l2-controls.txt#L397" id L397" class="line" nam L397">v397 a>Ac16ve and Grabbed Controls2 /v4l2-controls.txt#L398" id L398" class="line" nam L398">v398 a>===========================2 /v4l2-controls.txt#L399" id L399" class="line" nam L399">v399 a>2 /v4l2-controls.txt#L400" id L400" class="line" nam L400">v400 a>If you get more complex rela16..ships between controls, then you may have to2 /v4l2-controls.txt#L401" id L401" class="line" nam L401">v401 a>ac1ivate and deac1ivate controls. F < example, if the Chroma AGC control is2 /v4l2-controls.txt#L402" id L402" class="line" nam L402">v402 a>on, then the Chroma Gain control is inac1ive. That is, you may set it, but2 /v4l2-controls.txt#L403" id L403" class="line" nam L403">v403 a>the /v4l2-controls.txt#L404" id L404" class="line" nam L404">v404 a>control is on. Typ6cally user interfaces can disable such input fields.2 /v4l2-controls.txt#L405" id L405" class="line" nam L405">v405 a>2 /v4l2-controls.txt#L406" id L406" class="line" nam L406">v406 a>You can set the 'ac1ive' sta1us using v4l2_ctrl_ac1ivate(). By default all2 /v4l2-controls.txt#L407" id L407" class="line" nam L407">v407 a>controls are ac1ive. Note that the fram work does not check < this lag.2 /v4l2-controls.txt#L408" id L408" class="line" nam L408">v408 a>It is meant purely < GUIs. The unc16.. is typ6cally called from within2 /v4l2-controls.txt#L409" id L409" class="line" nam L409">v409 a>s_ctrl.2 /v4l2-controls.txt#L410" id L410" class="line" nam L410">v410 a>2 /v4l2-controls.txt#L411" id L411" class="line" nam L411">v411 a>The other lag is the 'grabbed' lag. A grabbed control means that you cannot2 /v4l2-controls.txt#L412" id L412" class="line" nam L412">v412 a>change it because it is in use by some resource. Typ6cal examples are MPEG2 /v4l2-controls.txt#L413" id L413" class="line" nam L413">v413 a>bitrate controls that ctinot be changed while capturing is in progress.2 /v4l2-controls.txt#L414" id L414" class="line" nam L414">v414 a>2 /v4l2-controls.txt#L415" id L415" class="line" nam L415">v415 a>If a control is set to 'grabbed' using v4l2_ctrl_grab(), then the fram work2 /v4l2-controls.txt#L416" id L416" class="line" nam L416">v416 a>will return -EBUSY if an attemptais made to set this control. The2 /v4l2-controls.txt#L417" id L417" class="line" nam L417">v417 a>v4l2_ctrl_grab() unc16.. is typ6cally called from the driver when it2 /v4l2-controls.txt#L418" id L418" class="line" nam L418">v418 a>starts < stops streaming.2 /v4l2-controls.txt#L419" id L419" class="line" nam L419">v419 a>2 /v4l2-controls.txt#L420" id L420" class="line" nam L420">v420 a>2 /v4l2-controls.txt#L421" id L421" class="line" nam L421">v421 a>Control Clusters2 /v4l2-controls.txt#L422" id L422" class="line" nam L422">v422 a>================2 /v4l2-controls.txt#L423" id L423" class="line" nam L423">v423 a>2 /v4l2-controls.txt#L424" id L424" class="line" nam L424">v424 a>By default all controls are independent from the others. But in more2 /v4l2-controls.txt#L425" id L425" class="line" nam L425">v425 a>complex scenarios you can get dependencies from one control to another.2 /v4l2-controls.txt#L426" id L426" class="line" nam L426">v426 a>In that case you need to 'cluster' them:2 /v4l2-controls.txt#L427" id L427" class="line" nam L427">v427 a>2 /v4l2-controls.txt#L428" id L428" class="line" nam L428">v428 a> struc1 foo {2 /v4l2-controls.txt#L429" id L429" class="line" nam L429">v429 a> struc1 v4l2_ctrl_handler ctrl_handler;2 /v4l2-controls.txt#L430" id L430" class="line" nam L430">v430 a>#define AUDIO_CL_VOLUME (0)2 /v4l2-controls.txt#L431" id L431" class="line" nam L431">v431 a>#define AUDIO_CL_MUTE (1)2 /v4l2-controls.txt#L432" id L432" class="line" nam L432">v432 a> struc1 v4l2_ctrl *audio_cluster[2];2 /v4l2-controls.txt#L433" id L433" class="line" nam L433">v433 a> ...2 /v4l2-controls.txt#L434" id L434" class="line" nam L434">v434 a> };2 /v4l2-controls.txt#L435" id L435" class="line" nam L435">v435 a>2 /v4l2-controls.txt#L436" id L436" class="line" nam L436">v436 a> sta1e->audio_cluster[AUDIO_CL_VOLUME] =2 /v4l2-controls.txt#L437" id L437" class="line" nam L437">v437 a> v4l2_ctrl_new_std(&sta1e->ctrl_handler, ...);2 /v4l2-controls.txt#L438" id L438" class="line" nam L438">v438 a> sta1e->audio_cluster[AUDIO_CL_MUTE] =2 /v4l2-controls.txt#L439" id L439" class="line" nam L439">v439 a> v4l2_ctrl_new_std(&sta1e->ctrl_handler, ...);2 /v4l2-controls.txt#L440" id L440" class="line" nam L440">v440 a> v4l2_ctrl_cluster(ARRAY_SIZE(sta1e->audio_cluster), sta1e->audio_cluster);2 /v4l2-controls.txt#L441" id L441" class="line" nam L441">v441 a>2 /v4l2-controls.txt#L442" id L442" class="line" nam L442">v442 a>From now .. whenever one < more of the controls belonging to the sam 2 /v4l2-controls.txt#L443" id L443" class="line" nam L443">v443 a>cluster is set ( < 'gotten', or 'tried'), only the control ops of the first2 /v4l2-controls.txt#L444" id L444" class="line" nam L444">v444 a>control ('volume' in this example) is called. You effec1ively create a new2 /v4l2-controls.txt#L445" id L445" class="line" nam L445">v445 a>composite control. Similar to how a 'struc1' works in C.2 /v4l2-controls.txt#L446" id L446" class="line" nam L446">v446 a>2 /v4l2-controls.txt#L447" id L447" class="line" nam L447">v447 a>So when s_ctrl is called with V4L2_CID_AUDIO_VOLUME as argument, you should set2 /v4l2-controls.txt#L448" id L448" class="line" nam L448">v448 a>all two controls belonging to the audio_cluster:2 /v4l2-controls.txt#L449" id L449" class="line" nam L449">v449 a>2 /v4l2-controls.txt#L450" id L450" class="line" nam L450">v450 a> sta16c int foo_s_ctrl(struc1 v4l2_ctrl *ctrl)2 /v4l2-controls.txt#L451" id L451" class="line" nam L451">v451 a> {2 /v4l2-controls.txt#L452" id L452" class="line" nam L452">v452 a> struc1 foo *sta1e = container_of(ctrl->handler, struc1 foo, ctrl_handler);2 /v4l2-controls.txt#L453" id L453" class="line" nam L453">v453 a>2 /v4l2-controls.txt#L454" id L454" class="line" nam L454">v454 a> switch (ctrl->id) {2 /v4l2-controls.txt#L455" id L455" class="line" nam L455">v455 a> case V4L2_CID_AUDIO_VOLUME: {2 /v4l2-controls.txt#L456" id L456" class="line" nam L456">v456 a> struc1 v4l2_ctrl *mute = ctrl->cluster[AUDIO_CL_MUTE];2 /v4l2-controls.txt#L457" id L457" class="line" nam L457">v457 a>2 /v4l2-controls.txt#L458" id L458" class="line" nam L458">v458 a> write_reg(0x123, mute->val ? 0 : ctrl->val);2 /v4l2-controls.txt#L459" id L459" class="line" nam L459">v459 a> break;2 /v4l2-controls.txt#L460" id L460" class="line" nam L460">v460 a> }2 /v4l2-controls.txt#L461" id L461" class="line" nam L461">v461 a> case V4L2_CID_CONTRAST:2 /v4l2-controls.txt#L462" id L462" class="line" nam L462">v462 a> write_reg(0x456, ctrl->val);2 /v4l2-controls.txt#L463" id L463" class="line" nam L463">v463 a> break;2 /v4l2-controls.txt#L464" id L464" class="line" nam L464">v464 a> }2 /v4l2-controls.txt#L465" id L465" class="line" nam L465">v465 a> return 0;2 /v4l2-controls.txt#L466" id L466" class="line" nam L466">v466 a> }2 /v4l2-controls.txt#L467" id L467" class="line" nam L467">v467 a>2 /v4l2-controls.txt#L468" id L468" class="line" nam L468">v468 a>In the example above the following are equivalent < the VOLUME case:2 /v4l2-controls.txt#L469" id L469" class="line" nam L469">v469 a>2 /v4l2-controls.txt#L470" id L470" class="line" nam L470">v470 a> ctrl == ctrl->cluster[AUDIO_CL_VOLUME] == sta1e->audio_cluster[AUDIO_CL_VOLUME]2 /v4l2-controls.txt#L471" id L471" class="line" nam L471">v471 a> ctrl->cluster[AUDIO_CL_MUTE] == sta1e->audio_cluster[AUDIO_CL_MUTE]2 /v4l2-controls.txt#L472" id L472" class="line" nam L472">v472 a>2 /v4l2-controls.txt#L473" id L473" class="line" nam L473">v473 a>In prac1ice using cluster arrays like this becomes very tiresome. So instead2 /v4l2-controls.txt#L474" id L474" class="line" nam L474">v474 a>the following equivalent method is used:2 /v4l2-controls.txt#L475" id L475" class="line" nam L475">v475 a>2 /v4l2-controls.txt#L476" id L476" class="line" nam L476">v476 a> struc1 {2 /v4l2-controls.txt#L477" id L477" class="line" nam L477">v477 a> /* audio cluster */2 /v4l2-controls.txt#L478" id L478" class="line" nam L478">v478 a> struc1 v4l2_ctrl *volume;2 /v4l2-controls.txt#L479" id L479" class="line" nam L479">v479 a> struc1 v4l2_ctrl *mute;2 /v4l2-controls.txt#L480" id L480" class="line" nam L480">v480 a> };2 /v4l2-controls.txt#L481" id L481" class="line" nam L481">v481 a>2 /v4l2-controls.txt#L482" id L482" class="line" nam L482">v482 a>The anonymous struc1 is used to clearly 'cluster' these two control pointers,2 /v4l2-controls.txt#L483" id L483" class="line" nam L483">v483 a>but it serves no other purpose. The effec1 is the sam as creating an2 /v4l2-controls.txt#L484" id L484" class="line" nam L484">v484 a>array with two control pointers. So you can just do:2 /v4l2-controls.txt#L485" id L485" class="line" nam L485">v485 a>2 /v4l2-controls.txt#L486" id L486" class="line" nam L486">v486 a> sta1e->volume = v4l2_ctrl_new_std(&sta1e->ctrl_handler, ...);2 /v4l2-controls.txt#L487" id L487" class="line" nam L487">v487 a> sta1e->mute = v4l2_ctrl_new_std(&sta1e->ctrl_handler, ...);2 /v4l2-controls.txt#L488" id L488" class="line" nam L488">v488 a> v4l2_ctrl_cluster(2, &sta1e->volume);2 /v4l2-controls.txt#L489" id L489" class="line" nam L489">v489 a>2 /v4l2-controls.txt#L490" id L490" class="line" nam L490">v490 a>And in foo_s_ctrl you can use these pointers directly: sta1e->mute->val.2 /v4l2-controls.txt#L491" id L491" class="line" nam L491">v491 a>2 /v4l2-controls.txt#L492" id L492" class="line" nam L492">v492 a>Note that controls in a cluster may be NULL. F < example, if < some2 /v4l2-controls.txt#L493" id L493" class="line" nam L493">v493 a>reason mute was never added (because the hardware doesn't support that2 /v4l2-controls.txt#L494" id L494" class="line" nam L494">v494 a>par1icular feature), then mute will be NULL. So in that case we have a2 /v4l2-controls.txt#L495" id L495" class="line" nam L495">v495 a>cluster of 2 controls, of which only 1 is actually instantiated. The2 /v4l2-controls.txt#L496" id L496" class="line" nam L496">v496 a>only restric16.. is that the first control of the cluster must always be2 /v4l2-controls.txt#L497" id L497" class="line" nam L497">v497 a>present, since that is the 'master' control of the cluster. The master2 /v4l2-controls.txt#L498" id L498" class="line" nam L498">v498 a>control is the one that iden16fies the cluster and that provides the2 /v4l2-controls.txt#L499" id L499" class="line" nam L499">v499 a>pointer to the v4l2_ctrl_ops struc1 that is used < that cluster.2 /v4l2-controls.txt#L500" id L500" class="line" nam L500">v500 a>2 /v4l2-controls.txt#L501" id L501" class="line" nam L501">v501 a>Obviously, all controls in the cluster array must be initialized to either2 /v4l2-controls.txt#L502" id L502" class="line" nam L502">v502 a>a /v4l2-controls.txt#L503" id L503" class="line" nam L503">v503 a>2 /v4l2-controls.txt#L504" id L504" class="line" nam L504">v504 a>In rare cases you might want to know which controls of a cluster actually2 /v4l2-controls.txt#L505" id L505" class="line" nam L505">v505 a>were set explicitly by the user. F < this you can check the 'is_new' lag of2 /v4l2-controls.txt#L506" id L506" class="line" nam L506">v506 a>each control. F < example, in the case of a volume/mute cluster the 'is_new'2 /v4l2-controls.txt#L507" id L507" class="line" nam L507">v507 a> lag of the mute control would be set if the user called VIDIOC_S_CTRL <2 /v4l2-controls.txt#L508" id L508" class="line" nam L508">v508 a>mute only. If the user would call VIDIOC_S_EXT_CTRLS < both mute and volume2 /v4l2-controls.txt#L509" id L509" class="line" nam L509">v509 a>controls, then the 'is_new' lag would be 1 < both controls.2 /v4l2-controls.txt#L510" id L510" class="line" nam L510">v510 a>2 /v4l2-controls.txt#L511" id L511" class="line" nam L511">v511 a>The 'is_new' lag is always 1 when called from v4l2_ctrl_handler_setup().2 /v4l2-controls.txt#L512" id L512" class="line" nam L512">v512 a>2 /v4l2-controls.txt#L513" id L513" class="line" nam L513">v513 a>2 /v4l2-controls.txt#L514" id L514" class="line" nam L514">v514 a>Handling autogain/gain-type Controls with Auto Clusters2 /v4l2-controls.txt#L515" id L515" class="line" nam L515">v515 a>=======================================================2 /v4l2-controls.txt#L516" id L516" class="line" nam L516">v516 a>2 /v4l2-controls.txt#L517" id L517" class="line" nam L517">v517 a>A comm.. type of control cluster is one that handles 'auto-foo/foo'-type2 /v4l2-controls.txt#L518" id L518" class="line" nam L518">v518 a>controls. Typ6cal examples are autogain/gain, autoexposure/exposure,2 /v4l2-controls.txt#L519" id L519" class="line" nam L519">v519 a>autowhitebalance/red balance/b /v4l2-controls.txt#L520" id L520" class="line" nam L520">v520 a>that determines whether another control is handled autooa16cally by the hardware,2 /v4l2-controls.txt#L521" id L521" class="line" nam L521">v521 a>or whether it is under manual control from the user.2 /v4l2-controls.txt#L522" id L522" class="line" nam L522">v522 a>2 /v4l2-controls.txt#L523" id L523" class="line" nam L523">v523 a>If the cluster is in autooa16c mode, then the manual controls should be2 /v4l2-controls.txt#L524" id L524" class="line" nam L524">v524 a>marked inac16ve and vola16le. When the vola16le controls are read the2 /v4l2-controls.txt#L525" id L525" class="line" nam L525">v525 a>g_vola16le_ctrl opera16.. should return the /v4l2-controls.txt#L526" id L526" class="line" nam L526">v526 a>mode set up autooa16cally.2 /v4l2-controls.txt#L527" id L527" class="line" nam L527">v527 a>2 /v4l2-controls.txt#L528" id L528" class="line" nam L528">v528 a>If the cluster is put in manual mode, then the manual controls should become2 /v4l2-controls.txt#L529" id L529" class="line" nam L529">v529 a>ac16ve again and the vola16le lag is cleared (so g_vola16le_ctrl is no longer2 /v4l2-controls.txt#L530" id L530" class="line" nam L530">v530 a>called while in manual mode). In addi16.. just before switching to manual mode2 /v4l2-controls.txt#L531" id L531" class="line" nam L531">v531 a>the curr2nt /v4l2-controls.txt#L532" id L532" class="line" nam L532">v532 a> /v4l2-controls.txt#L533" id L533" class="line" nam L533">v533 a>2 /v4l2-controls.txt#L534" id L534" class="line" nam L534">v534 a>Finally the V4L2_CTRL_FLAG_UPDATE should be set < the auto control since2 /v4l2-controls.txt#L535" id L535" class="line" nam L535">v535 a>changing that control affec1s the control flags of the manual controls.2 /v4l2-controls.txt#L536" id L536" class="line" nam L536">v536 a>2 /v4l2-controls.txt#L537" id L537" class="line" nam L537">v537 a>In order to simplify this a special ria16.. of v4l2_ctrl_cluster was2 /v4l2-controls.txt#L538" id L538" class="line" nam L538">v538 a>introduced:2 /v4l2-controls.txt#L539" id L539" class="line" nam L539">v539 a>2 /v4l2-controls.txt#L540" id L540" class="line" nam L540">v540 a>void v4l2_ctrl_auto_cluster(unsigned ncontrols, struc1 v4l2_ctrl **controls,2 /v4l2-controls.txt#L541" id L541" class="line" nam L541">v541 a> u8 manual_ <, bool set_vola16le);2 /v4l2-controls.txt#L542" id L542" class="line" nam L542">v542 a>2 /v4l2-controls.txt#L543" id L543" class="line" nam L543">v543 a>The first two arguments are iden16cal to v4l2_ctrl_cluster. The third argument2 /v4l2-controls.txt#L544" id L544" class="line" nam L544">v544 a>tells the fram work which /v4l2-controls.txt#L545" id L545" class="line" nam L545">v545 a>last argument will op16..ally set V4L2_CTRL_FLAG_VOLATILE < the non-auto controls.2 /v4l2-controls.txt#L546" id L546" class="line" nam L546">v546 a>If it is false, then the manual controls are never vola16le. You would typ6cally2 /v4l2-controls.txt#L547" id L547" class="line" nam L547">v547 a>use that if the hardware does not g6ve you the op16.. to read back to /v4l2-controls.txt#L548" id L548" class="line" nam L548">v548 a>determined by the auto mode (e.g. if autogain is on, the hardware doesn't allow2 /v4l2-controls.txt#L549" id L549" class="line" nam L549">v549 a>you to obtain the curr2nt gain /v4l2-controls.txt#L550" id L550" class="line" nam L550">v550 a>2 /v4l2-controls.txt#L551" id L551" class="line" nam L551">v551 a>The first control of the cluster is assumed to be the 'auto' control.2 /v4l2-controls.txt#L552" id L552" class="line" nam L552">v552 a>2 /v4l2-controls.txt#L553" id L553" class="line" nam L553">v553 a>Using this func16.. will ensure that you don't need to handle all the complex2 /v4l2-controls.txt#L554" id L554" class="line" nam L554">v554 a> lag and vola16le handling.2 /v4l2-controls.txt#L555" id L555" class="line" nam L555">v555 a>2 /v4l2-controls.txt#L556" id L556" class="line" nam L556">v556 a>2 /v4l2-controls.txt#L557" id L557" class="line" nam L557">v557 a>VIDIOC_LOG_STATUS Support2 /v4l2-controls.txt#L558" id L558" class="line" nam L558">v558 a>=========================2 /v4l2-controls.txt#L559" id L559" class="line" nam L559">v559 a>2 /v4l2-controls.txt#L560" id L560" class="line" nam L560">v560 a>This ioctl allow you to dump the curr2nt sta1us of a driver to the kernel log.2 /v4l2-controls.txt#L561" id L561" class="line" nam L561">v561 a>The v4l2_ctrl_handler_log_sta1us(ctrl_handler, p6.3ix) can be used to dump the2 /v4l2-controls.txt#L562" id L562" class="line" nam L562">v562 a> /v4l2-controls.txt#L563" id L563" class="line" nam L563">v563 a>p6.3ix as well. If the p6.3ix didn't end with a space, then ': ' will be added2 /v4l2-controls.txt#L564" id L564" class="line" nam L564">v564 a> < you.2 /v4l2-controls.txt#L565" id L565" class="line" nam L565">v565 a>2 /v4l2-controls.txt#L566" id L566" class="line" nam L566">v566 a>2 /v4l2-controls.txt#L567" id L567" class="line" nam L567">v567 a>Differ2nt Handlers < Differ2nt Video Nodes2 /v4l2-controls.txt#L568" id L568" class="line" nam L568">v568 a>============================================2 /v4l2-controls.txt#L569" id L569" class="line" nam L569">v569 a>2 /v4l2-controls.txt#L570" id L570" class="line" nam L570">v570 a>Usually the V4L2 driver .as just one control handler that is global <2 /v4l2-controls.txt#L571" id L571" class="line" nam L571">v571 a>all video nodes. But you can also specify differ2nt control handlers <2 /v4l2-controls.txt#L572" id L572" class="line" nam L572">v572 a>differ2nt video nodes. You can do that by manually setting the ctrl_handler2 /v4l2-controls.txt#L573" id L573" class="line" nam L573">v573 a>field of struc1 video_device.2 /v4l2-controls.txt#L574" id L574" class="line" nam L574">v574 a>2 /v4l2-controls.txt#L575" id L575" class="line" nam L575">v575 a>That is no problem if there are no subdevs involved but if there are, then2 /v4l2-controls.txt#L576" id L576" class="line" nam L576">v576 a>you need to block the autooa16c merging of subdev controls to the global2 /v4l2-controls.txt#L577" id L577" class="line" nam L577">v577 a>control handler. You do that by simply setting the ctrl_handler field in2 /v4l2-controls.txt#L578" id L578" class="line" nam L578">v578 a>struc1 v4l2_device to NULL. Now v4l2_device_register_subdev() will no longer2 /v4l2-controls.txt#L579" id L579" class="line" nam L579">v579 a>merge subdev controls.2 /v4l2-controls.txt#L580" id L580" class="line" nam L580">v580 a>2 /v4l2-controls.txt#L581" id L581" class="line" nam L581">v581 a>After each subdev was added, you will then have to call v4l2_ctrl_add_handler2 /v4l2-controls.txt#L582" id L582" class="line" nam L582">v582 a>manually to add the subdev's control handler (sd->ctrl_handler) to the desired2 /v4l2-controls.txt#L583" id L583" class="line" nam L583">v583 a>control handler. This control handler may be specific to the video_device <2 /v4l2-controls.txt#L584" id L584" class="line" nam L584">v584 a> < a subset of video_device's. F < example: the radio device nodes only have2 /v4l2-controls.txt#L585" id L585" class="line" nam L585">v585 a>audio controls, while the video and vbi device nodes share the sam control2 /v4l2-controls.txt#L586" id L586" class="line" nam L586">v586 a>handler f < the audio and video controls.2 /v4l2-controls.txt#L587" id L587" class="line" nam L587">v587 a>2 /v4l2-controls.txt#L588" id L588" class="line" nam L588">v588 a>If you want to have one handler (e.g. < a radio device node) have a subset2 /v4l2-controls.txt#L589" id L589" class="line" nam L589">v589 a>of another handler (e.g. < a video device node), then you should first add2 /v4l2-controls.txt#L590" id L590" class="line" nam L590">v590 a>the controls to the first handler, add the other controls to the second2 /v4l2-controls.txt#L591" id L591" class="line" nam L591">v591 a>handler and finally add the first handler to the second. F < example:2 /v4l2-controls.txt#L592" id L592" class="line" nam L592">v592 a>2 /v4l2-controls.txt#L593" id L593" class="line" nam L593">v593 a> v4l2_ctrl_new_std(&radio_ctrl_handler, &radio_ops, V4L2_CID_AUDIO_VOLUME, ...);2 /v4l2-controls.txt#L594" id L594" class="line" nam L594">v594 a> v4l2_ctrl_new_std(&radio_ctrl_handler, &radio_ops, V4L2_CID_AUDIO_MUTE, ...);2 /v4l2-controls.txt#L595" id L595" class="line" nam L595">v595 a> v4l2_ctrl_new_std(&video_ctrl_handler, &video_ops, V4L2_CID_BRIGHTNESS, ...);2 /v4l2-controls.txt#L596" id L596" class="line" nam L596">v596 a> v4l2_ctrl_new_std(&video_ctrl_handler, &video_ops, V4L2_CID_CONTRAST, ...);2 /v4l2-controls.txt#L597" id L597" class="line" nam L597">v597 a> v4l2_ctrl_add_handler(&video_ctrl_handler, &radio_ctrl_handler);2 /v4l2-controls.txt#L598" id L598" class="line" nam L598">v598 a>2 /v4l2-controls.txt#L599" id L599" class="line" nam L599">v599 a>Or you can add specific controls to a handler:2 /v4l2-controls.txt#L600" id L600" class="line" nam L600">v600 a>2 /v4l2-controls.txt#L601" id L601" class="line" nam L601">v601 a> volume = v4l2_ctrl_new_std(&video_ctrl_handler, &ops, V4L2_CID_AUDIO_VOLUME, ...);2 /v4l2-controls.txt#L602" id L602" class="line" nam L602">v602 a> v4l2_ctrl_new_std(&video_ctrl_handler, &ops, V4L2_CID_BRIGHTNESS, ...);2 /v4l2-controls.txt#L603" id L603" class="line" nam L603">v603 a> v4l2_ctrl_new_std(&video_ctrl_handler, &ops, V4L2_CID_CONTRAST, ...);2 /v4l2-controls.txt#L604" id L604" class="line" nam L604">v604 a> v4l2_ctrl_add_ctrl(&radio_ctrl_handler, volume);2 /v4l2-controls.txt#L605" id L605" class="line" nam L605">v605 a>2 /v4l2-controls.txt#L606" id L606" class="line" nam L606">v606 a>What you should not doais make two iden16cal controls f < two handlers.2 /v4l2-controls.txt#L607" id L607" class="line" nam L607">v607 a>F < example:2 /v4l2-controls.txt#L608" id L608" class="line" nam L608">v608 a>2 /v4l2-controls.txt#L609" id L609" class="line" nam L609">v609 a> v4l2_ctrl_new_std(&radio_ctrl_handler, &radio_ops, V4L2_CID_AUDIO_MUTE, ...);2 /v4l2-controls.txt#L610" id L610" class="line" nam L610">v610 a> v4l2_ctrl_new_std(&video_ctrl_handler, &video_ops, V4L2_CID_AUDIO_MUTE, ...);2 /v4l2-controls.txt#L611" id L611" class="line" nam L611">v611 a>2 /v4l2-controls.txt#L612" id L612" class="line" nam L612">v612 a>This would be bad since muting the radio would not change the video mute2 /v4l2-controls.txt#L613" id L613" class="line" nam L613">v613 a>control. The rule is to have one control for each hardware 'knob' that you2 /v4l2-controls.txt#L614" id L614" class="line" nam L614">v614 a>can twiddle.2 /v4l2-controls.txt#L615" id L615" class="line" nam L615">v615 a>2 /v4l2-controls.txt#L616" id L616" class="line" nam L616">v616 a>2 /v4l2-controls.txt#L617" id L617" class="line" nam L617">v617 a>Finding Controls2 /v4l2-controls.txt#L618" id L618" class="line" nam L618">v618 a>================2 /v4l2-controls.txt#L619" id L619" class="line" nam L619">v619 a>2 /v4l2-controls.txt#L620" id L620" class="line" nam L620">v620 a>Normally you have created the controls yourself and you can store the struc12 /v4l2-controls.txt#L621" id L621" class="line" nam L621">v621 a>v4l2_ctrl pointer into your own struc1.2 /v4l2-controls.txt#L622" id L622" class="line" nam L622">v622 a>2 /v4l2-controls.txt#L623" id L623" class="line" nam L623">v623 a>But sometimes you need to find a control from another handler that you do2 /v4l2-controls.txt#L624" id L624" class="line" nam L624">v624 a>not own. F < example, if you have to find a volume control from a subdev.2 /v4l2-controls.txt#L625" id L625" class="line" nam L625">v625 a>2 /v4l2-controls.txt#L626" id L626" class="line" nam L626">v626 a>You can do that by calling v4l2_ctrl_find:2 /v4l2-controls.txt#L627" id L627" class="line" nam L627">v627 a>2 /v4l2-controls.txt#L628" id L628" class="line" nam L628">v628 a> struc1 v4l2_ctrl *volume;2 /v4l2-controls.txt#L629" id L629" class="line" nam L629">v629 a>2 /v4l2-controls.txt#L630" id L630" class="line" nam L630">v630 a> volume = v4l2_ctrl_find(sd->ctrl_handler, V4L2_CID_AUDIO_VOLUME);2 /v4l2-controls.txt#L631" id L631" class="line" nam L631">v631 a>2 /v4l2-controls.txt#L632" id L632" class="line" nam L632">v632 a>Since v4l2_ctrl_find will lock the handler you have to be careful where you2 /v4l2-controls.txt#L633" id L633" class="line" nam L633">v633 a>use it. F < example, this is not a good idea:2 /v4l2-controls.txt#L634" id L634" class="line" nam L634">v634 a>2 /v4l2-controls.txt#L635" id L635" class="line" nam L635">v635 a> struc1 v4l2_ctrl_handler ctrl_handler;2 /v4l2-controls.txt#L636" id L636" class="line" nam L636">v636 a>2 /v4l2-controls.txt#L637" id L637" class="line" nam L637">v637 a> v4l2_ctrl_new_std(&ctrl_handler, &video_ops, V4L2_CID_BRIGHTNESS, ...);2 /v4l2-controls.txt#L638" id L638" class="line" nam L638">v638 a> v4l2_ctrl_new_std(&ctrl_handler, &video_ops, V4L2_CID_CONTRAST, ...);2 /v4l2-controls.txt#L639" id L639" class="line" nam L639">v639 a>2 /v4l2-controls.txt#L640" id L640" class="line" nam L640">v640 a>...and in video_ops.s_ctrl:2 /v4l2-controls.txt#L641" id L641" class="line" nam L641">v641 a>2 /v4l2-controls.txt#L642" id L642" class="line" nam L642">v642 a> case V4L2_CID_BRIGHTNESS:2 /v4l2-controls.txt#L643" id L643" class="line" nam L643">v643 a> contrast = v4l2_find_ctrl(&ctrl_handler, V4L2_CID_CONTRAST);2 /v4l2-controls.txt#L644" id L644" class="line" nam L644">v644 a> ...2 /v4l2-controls.txt#L645" id L645" class="line" nam L645">v645 a>2 /v4l2-controls.txt#L646" id L646" class="line" nam L646">v646 a>When s_ctrl is called by the fram work the ctrl_handler.lock is already taken, so2 /v4l2-controls.txt#L647" id L647" class="line" nam L647">v647 a>attempting to find another control from the sam handler will deadlock.2 /v4l2-controls.txt#L648" id L648" class="line" nam L648">v648 a>2 /v4l2-controls.txt#L649" id L649" class="line" nam L649">v649 a>It is recommended not to use this func16.. from inside the control ops.2 /v4l2-controls.txt#L650" id L650" class="line" nam L650">v650 a>2 /v4l2-controls.txt#L651" id L651" class="line" nam L651">v651 a>2 /v4l2-controls.txt#L652" id L652" class="line" nam L652">v652 a>Inheriting Controls2 /v4l2-controls.txt#L653" id L653" class="line" nam L653">v653 a>===================2 /v4l2-controls.txt#L654" id L654" class="line" nam L654">v654 a>2 /v4l2-controls.txt#L655" id L655" class="line" nam L655">v655 a>When one control handler is added to another using v4l2_ctrl_add_handler, then2 /v4l2-controls.txt#L656" id L656" class="line" nam L656">v656 a>by default all controls from one are merged to the other. But a subdev might2 /v4l2-controls.txt#L657" id L657" class="line" nam L657">v657 a>have low-level controls that make sense < some advanced embedded system, but2 /v4l2-controls.txt#L658" id L658" class="line" nam L658">v658 a>not when it is used in consumer-level hardware. In that case you want to keep2 /v4l2-controls.txt#L659" id L659" class="line" nam L659">v659 a>those low-level controls local to the subdev. You can do this by simply2 /v4l2-controls.txt#L660" id L660" class="line" nam L660">v660 a>setting the 'is_private' lag of the control to 1:2 /v4l2-controls.txt#L661" id L661" class="line" nam L661">v661 a>2 /v4l2-controls.txt#L662" id L662" class="line" nam L662">v662 a> sta16c const struc1 v4l2_ctrl_config ctrl_private = {2 /v4l2-controls.txt#L663" id L663" class="line" nam L663">v663 a> .ops = &ctrl_custom_ops,2 /v4l2-controls.txt#L664" id L664" class="line" nam L664">v664 a> .id = V4L2_CID_...,2 /v4l2-controls.txt#L665" id L665" class="line" nam L665">v665 a> .nam = "Some Private Control",2 /v4l2-controls.txt#L666" id L666" class="line" nam L666">v666 a> .type = V4L2_CTRL_TYPE_INTEGER,2 /v4l2-controls.txt#L667" id L667" class="line" nam L667">v667 a> .max = 15,2 /v4l2-controls.txt#L668" id L668" class="line" nam L668">v668 a> .step = 1,2 /v4l2-controls.txt#L669" id L669" class="line" nam L669">v669 a> .is_private = 1,2 /v4l2-controls.txt#L670" id L670" class="line" nam L670">v670 a> };2 /v4l2-controls.txt#L671" id L671" class="line" nam L671">v671 a>2 /v4l2-controls.txt#L672" id L672" class="line" nam L672">v672 a> ctrl = v4l2_ctrl_new_custom(&foo->ctrl_handler, &ctrl_private, NULL);2 /v4l2-controls.txt#L673" id L673" class="line" nam L673">v673 a>2 /v4l2-controls.txt#L674" id L674" class="line" nam L674">v674 a>These controls will now be skipped when v4l2_ctrl_add_handler is called.2 /v4l2-controls.txt#L675" id L675" class="line" nam L675">v675 a>2 /v4l2-controls.txt#L676" id L676" class="line" nam L676">v676 a>2 /v4l2-controls.txt#L677" id L677" class="line" nam L677">v677 a>V4L2_CTRL_TYPE_CTRL_CLASS Controls2 /v4l2-controls.txt#L678" id L678" class="line" nam L678">v678 a>==================================2 /v4l2-controls.txt#L679" id L679" class="line" nam L679">v679 a>2 /v4l2-controls.txt#L680" id L680" class="line" nam L680">v680 a>Controls of this type can be used by GUIs to get the nam of the control class.2 /v4l2-controls.txt#L681" id L681" class="line" nam L681">v681 a>A fully featured GUI can make a dialog with multiple tabs with each tab2 /v4l2-controls.txt#L682" id L682" class="line" nam L682">v682 a>containing the controls belonging to a par1icular control class. The nam of2 /v4l2-controls.txt#L683" id L683" class="line" nam L683">v683 a>each tab can be found by querying a special control with ID <control class | 1>.2 /v4l2-controls.txt#L684" id L684" class="line" nam L684">v684 a>2 /v4l2-controls.txt#L685" id L685" class="line" nam L685">v685 a>Drivers do not have to care about this. The fram work will autooa16cally add2 /v4l2-controls.txt#L686" id L686" class="line" nam L686">v686 a>a control of this type whenever the first control belonging to a new control2 /v4l2-controls.txt#L687" id L687" class="line" nam L687">v687 a>class is added.2 /v4l2-controls.txt#L688" id L688" class="line" nam L688">v688 a>2 /v4l2-controls.txt#L689" id L689" class="line" nam L689">v689 a>2 /v4l2-controls.txt#L690" id L690" class="line" nam Ldeo_ctrl_handlerbelonging to a ...);2v665 a> .nam = "Some Private Control",7Documenta16../vcontrols.2 /v4l2-controls.txt#L679" id L679" clas2-control6.txt#L592" id L592" cla6s="li6e" namo4 > /v4l2-controls.txt#L680" id L680" class="line" nam L680">v680 a>Contr v4l2_c6rl_new_std(&radio_ct6l_han6ler, &radio_ops, V4L2_CID_AUDIO_VOLUME, ...);2 /v4l2-contro6s.txt6L594" 4L2_Cls.tta16..fuv682 evtens t 'is_a.6xt#L662" id L662" class="line" nam L662">v662 a> enta16../6ideo4 > /v4l2-controls6txt#L69m work will autooa16cally add2 /v4l2-controls6txt#L696" id1) Ad16.. it is false, tHEX">v614 ain is oshcontttahexad.6.m35.contg. il with ID <control class | 1>.2 /v4l2-controls.t6t#L596" id d.6.m35. Usd ide.2t/v4l2-h ha_yutxt#L626" id L626" class="line" nam L626">v626 a>You co4 > /v6l2-controls.txt#L598" id6 L59869menta16../video4 > /v4l2-controls.txt#L629" id L629" classu can add6specific controls to a h6ndler622v600 a62v647fnta16../virr2nt a>2tel"line" nene5.Doontrolne5 theoughxt#L626" id L626" class="line" nam L626">v626 a>You 7Documenta76../video4 > /v4l2-con7rols.7xt#L60
s tyorig a> LXR softcumen647 a>#L626" idhttp://sourcdetege.net/proj.35./lxr">LXR 0">vunity#L60deo4 experi26" cl nam6../647#L626" idmai7to:lxr@ nam .no">lxr@ nam .no../vi
lxr. nam .no kiv4ly host">v647#L626" idhttp://www.82 p th- napro.no">R2 p th Lnapro AS#L60de is use">v49Lnam a>thol a>2v5 oser thes a>cont1995.