18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci V4L2 controls framework implementation. 48c2ecf20Sopenharmony_ci 58c2ecf20Sopenharmony_ci Copyright (C) 2010 Hans Verkuil <hverkuil@xs4all.nl> 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#define pr_fmt(fmt) "v4l2-ctrls: " fmt 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <linux/ctype.h> 128c2ecf20Sopenharmony_ci#include <linux/export.h> 138c2ecf20Sopenharmony_ci#include <linux/mm.h> 148c2ecf20Sopenharmony_ci#include <linux/slab.h> 158c2ecf20Sopenharmony_ci#include <media/v4l2-ctrls.h> 168c2ecf20Sopenharmony_ci#include <media/v4l2-dev.h> 178c2ecf20Sopenharmony_ci#include <media/v4l2-device.h> 188c2ecf20Sopenharmony_ci#include <media/v4l2-event.h> 198c2ecf20Sopenharmony_ci#include <media/v4l2-fwnode.h> 208c2ecf20Sopenharmony_ci#include <media/v4l2-ioctl.h> 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci#define dprintk(vdev, fmt, arg...) do { \ 238c2ecf20Sopenharmony_ci if (!WARN_ON(!(vdev)) && ((vdev)->dev_debug & V4L2_DEV_DEBUG_CTRL)) \ 248c2ecf20Sopenharmony_ci printk(KERN_DEBUG pr_fmt("%s: %s: " fmt), \ 258c2ecf20Sopenharmony_ci __func__, video_device_node_name(vdev), ##arg); \ 268c2ecf20Sopenharmony_ci} while (0) 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci#define has_op(master, op) \ 298c2ecf20Sopenharmony_ci (master->ops && master->ops->op) 308c2ecf20Sopenharmony_ci#define call_op(master, op) \ 318c2ecf20Sopenharmony_ci (has_op(master, op) ? master->ops->op(master) : 0) 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_cistatic const union v4l2_ctrl_ptr ptr_null; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci/* Internal temporary helper struct, one for each v4l2_ext_control */ 368c2ecf20Sopenharmony_cistruct v4l2_ctrl_helper { 378c2ecf20Sopenharmony_ci /* Pointer to the control reference of the master control */ 388c2ecf20Sopenharmony_ci struct v4l2_ctrl_ref *mref; 398c2ecf20Sopenharmony_ci /* The control ref corresponding to the v4l2_ext_control ID field. */ 408c2ecf20Sopenharmony_ci struct v4l2_ctrl_ref *ref; 418c2ecf20Sopenharmony_ci /* v4l2_ext_control index of the next control belonging to the 428c2ecf20Sopenharmony_ci same cluster, or 0 if there isn't any. */ 438c2ecf20Sopenharmony_ci u32 next; 448c2ecf20Sopenharmony_ci}; 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci/* Small helper function to determine if the autocluster is set to manual 478c2ecf20Sopenharmony_ci mode. */ 488c2ecf20Sopenharmony_cistatic bool is_cur_manual(const struct v4l2_ctrl *master) 498c2ecf20Sopenharmony_ci{ 508c2ecf20Sopenharmony_ci return master->is_auto && master->cur.val == master->manual_mode_value; 518c2ecf20Sopenharmony_ci} 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci/* Same as above, but this checks the against the new value instead of the 548c2ecf20Sopenharmony_ci current value. */ 558c2ecf20Sopenharmony_cistatic bool is_new_manual(const struct v4l2_ctrl *master) 568c2ecf20Sopenharmony_ci{ 578c2ecf20Sopenharmony_ci return master->is_auto && master->val == master->manual_mode_value; 588c2ecf20Sopenharmony_ci} 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci/* Returns NULL or a character pointer array containing the menu for 618c2ecf20Sopenharmony_ci the given control ID. The pointer array ends with a NULL pointer. 628c2ecf20Sopenharmony_ci An empty string signifies a menu entry that is invalid. This allows 638c2ecf20Sopenharmony_ci drivers to disable certain options if it is not supported. */ 648c2ecf20Sopenharmony_ciconst char * const *v4l2_ctrl_get_menu(u32 id) 658c2ecf20Sopenharmony_ci{ 668c2ecf20Sopenharmony_ci static const char * const mpeg_audio_sampling_freq[] = { 678c2ecf20Sopenharmony_ci "44.1 kHz", 688c2ecf20Sopenharmony_ci "48 kHz", 698c2ecf20Sopenharmony_ci "32 kHz", 708c2ecf20Sopenharmony_ci NULL 718c2ecf20Sopenharmony_ci }; 728c2ecf20Sopenharmony_ci static const char * const mpeg_audio_encoding[] = { 738c2ecf20Sopenharmony_ci "MPEG-1/2 Layer I", 748c2ecf20Sopenharmony_ci "MPEG-1/2 Layer II", 758c2ecf20Sopenharmony_ci "MPEG-1/2 Layer III", 768c2ecf20Sopenharmony_ci "MPEG-2/4 AAC", 778c2ecf20Sopenharmony_ci "AC-3", 788c2ecf20Sopenharmony_ci NULL 798c2ecf20Sopenharmony_ci }; 808c2ecf20Sopenharmony_ci static const char * const mpeg_audio_l1_bitrate[] = { 818c2ecf20Sopenharmony_ci "32 kbps", 828c2ecf20Sopenharmony_ci "64 kbps", 838c2ecf20Sopenharmony_ci "96 kbps", 848c2ecf20Sopenharmony_ci "128 kbps", 858c2ecf20Sopenharmony_ci "160 kbps", 868c2ecf20Sopenharmony_ci "192 kbps", 878c2ecf20Sopenharmony_ci "224 kbps", 888c2ecf20Sopenharmony_ci "256 kbps", 898c2ecf20Sopenharmony_ci "288 kbps", 908c2ecf20Sopenharmony_ci "320 kbps", 918c2ecf20Sopenharmony_ci "352 kbps", 928c2ecf20Sopenharmony_ci "384 kbps", 938c2ecf20Sopenharmony_ci "416 kbps", 948c2ecf20Sopenharmony_ci "448 kbps", 958c2ecf20Sopenharmony_ci NULL 968c2ecf20Sopenharmony_ci }; 978c2ecf20Sopenharmony_ci static const char * const mpeg_audio_l2_bitrate[] = { 988c2ecf20Sopenharmony_ci "32 kbps", 998c2ecf20Sopenharmony_ci "48 kbps", 1008c2ecf20Sopenharmony_ci "56 kbps", 1018c2ecf20Sopenharmony_ci "64 kbps", 1028c2ecf20Sopenharmony_ci "80 kbps", 1038c2ecf20Sopenharmony_ci "96 kbps", 1048c2ecf20Sopenharmony_ci "112 kbps", 1058c2ecf20Sopenharmony_ci "128 kbps", 1068c2ecf20Sopenharmony_ci "160 kbps", 1078c2ecf20Sopenharmony_ci "192 kbps", 1088c2ecf20Sopenharmony_ci "224 kbps", 1098c2ecf20Sopenharmony_ci "256 kbps", 1108c2ecf20Sopenharmony_ci "320 kbps", 1118c2ecf20Sopenharmony_ci "384 kbps", 1128c2ecf20Sopenharmony_ci NULL 1138c2ecf20Sopenharmony_ci }; 1148c2ecf20Sopenharmony_ci static const char * const mpeg_audio_l3_bitrate[] = { 1158c2ecf20Sopenharmony_ci "32 kbps", 1168c2ecf20Sopenharmony_ci "40 kbps", 1178c2ecf20Sopenharmony_ci "48 kbps", 1188c2ecf20Sopenharmony_ci "56 kbps", 1198c2ecf20Sopenharmony_ci "64 kbps", 1208c2ecf20Sopenharmony_ci "80 kbps", 1218c2ecf20Sopenharmony_ci "96 kbps", 1228c2ecf20Sopenharmony_ci "112 kbps", 1238c2ecf20Sopenharmony_ci "128 kbps", 1248c2ecf20Sopenharmony_ci "160 kbps", 1258c2ecf20Sopenharmony_ci "192 kbps", 1268c2ecf20Sopenharmony_ci "224 kbps", 1278c2ecf20Sopenharmony_ci "256 kbps", 1288c2ecf20Sopenharmony_ci "320 kbps", 1298c2ecf20Sopenharmony_ci NULL 1308c2ecf20Sopenharmony_ci }; 1318c2ecf20Sopenharmony_ci static const char * const mpeg_audio_ac3_bitrate[] = { 1328c2ecf20Sopenharmony_ci "32 kbps", 1338c2ecf20Sopenharmony_ci "40 kbps", 1348c2ecf20Sopenharmony_ci "48 kbps", 1358c2ecf20Sopenharmony_ci "56 kbps", 1368c2ecf20Sopenharmony_ci "64 kbps", 1378c2ecf20Sopenharmony_ci "80 kbps", 1388c2ecf20Sopenharmony_ci "96 kbps", 1398c2ecf20Sopenharmony_ci "112 kbps", 1408c2ecf20Sopenharmony_ci "128 kbps", 1418c2ecf20Sopenharmony_ci "160 kbps", 1428c2ecf20Sopenharmony_ci "192 kbps", 1438c2ecf20Sopenharmony_ci "224 kbps", 1448c2ecf20Sopenharmony_ci "256 kbps", 1458c2ecf20Sopenharmony_ci "320 kbps", 1468c2ecf20Sopenharmony_ci "384 kbps", 1478c2ecf20Sopenharmony_ci "448 kbps", 1488c2ecf20Sopenharmony_ci "512 kbps", 1498c2ecf20Sopenharmony_ci "576 kbps", 1508c2ecf20Sopenharmony_ci "640 kbps", 1518c2ecf20Sopenharmony_ci NULL 1528c2ecf20Sopenharmony_ci }; 1538c2ecf20Sopenharmony_ci static const char * const mpeg_audio_mode[] = { 1548c2ecf20Sopenharmony_ci "Stereo", 1558c2ecf20Sopenharmony_ci "Joint Stereo", 1568c2ecf20Sopenharmony_ci "Dual", 1578c2ecf20Sopenharmony_ci "Mono", 1588c2ecf20Sopenharmony_ci NULL 1598c2ecf20Sopenharmony_ci }; 1608c2ecf20Sopenharmony_ci static const char * const mpeg_audio_mode_extension[] = { 1618c2ecf20Sopenharmony_ci "Bound 4", 1628c2ecf20Sopenharmony_ci "Bound 8", 1638c2ecf20Sopenharmony_ci "Bound 12", 1648c2ecf20Sopenharmony_ci "Bound 16", 1658c2ecf20Sopenharmony_ci NULL 1668c2ecf20Sopenharmony_ci }; 1678c2ecf20Sopenharmony_ci static const char * const mpeg_audio_emphasis[] = { 1688c2ecf20Sopenharmony_ci "No Emphasis", 1698c2ecf20Sopenharmony_ci "50/15 us", 1708c2ecf20Sopenharmony_ci "CCITT J17", 1718c2ecf20Sopenharmony_ci NULL 1728c2ecf20Sopenharmony_ci }; 1738c2ecf20Sopenharmony_ci static const char * const mpeg_audio_crc[] = { 1748c2ecf20Sopenharmony_ci "No CRC", 1758c2ecf20Sopenharmony_ci "16-bit CRC", 1768c2ecf20Sopenharmony_ci NULL 1778c2ecf20Sopenharmony_ci }; 1788c2ecf20Sopenharmony_ci static const char * const mpeg_audio_dec_playback[] = { 1798c2ecf20Sopenharmony_ci "Auto", 1808c2ecf20Sopenharmony_ci "Stereo", 1818c2ecf20Sopenharmony_ci "Left", 1828c2ecf20Sopenharmony_ci "Right", 1838c2ecf20Sopenharmony_ci "Mono", 1848c2ecf20Sopenharmony_ci "Swapped Stereo", 1858c2ecf20Sopenharmony_ci NULL 1868c2ecf20Sopenharmony_ci }; 1878c2ecf20Sopenharmony_ci static const char * const mpeg_video_encoding[] = { 1888c2ecf20Sopenharmony_ci "MPEG-1", 1898c2ecf20Sopenharmony_ci "MPEG-2", 1908c2ecf20Sopenharmony_ci "MPEG-4 AVC", 1918c2ecf20Sopenharmony_ci NULL 1928c2ecf20Sopenharmony_ci }; 1938c2ecf20Sopenharmony_ci static const char * const mpeg_video_aspect[] = { 1948c2ecf20Sopenharmony_ci "1x1", 1958c2ecf20Sopenharmony_ci "4x3", 1968c2ecf20Sopenharmony_ci "16x9", 1978c2ecf20Sopenharmony_ci "2.21x1", 1988c2ecf20Sopenharmony_ci NULL 1998c2ecf20Sopenharmony_ci }; 2008c2ecf20Sopenharmony_ci static const char * const mpeg_video_bitrate_mode[] = { 2018c2ecf20Sopenharmony_ci "Variable Bitrate", 2028c2ecf20Sopenharmony_ci "Constant Bitrate", 2038c2ecf20Sopenharmony_ci "Constant Quality", 2048c2ecf20Sopenharmony_ci NULL 2058c2ecf20Sopenharmony_ci }; 2068c2ecf20Sopenharmony_ci static const char * const mpeg_stream_type[] = { 2078c2ecf20Sopenharmony_ci "MPEG-2 Program Stream", 2088c2ecf20Sopenharmony_ci "MPEG-2 Transport Stream", 2098c2ecf20Sopenharmony_ci "MPEG-1 System Stream", 2108c2ecf20Sopenharmony_ci "MPEG-2 DVD-compatible Stream", 2118c2ecf20Sopenharmony_ci "MPEG-1 VCD-compatible Stream", 2128c2ecf20Sopenharmony_ci "MPEG-2 SVCD-compatible Stream", 2138c2ecf20Sopenharmony_ci NULL 2148c2ecf20Sopenharmony_ci }; 2158c2ecf20Sopenharmony_ci static const char * const mpeg_stream_vbi_fmt[] = { 2168c2ecf20Sopenharmony_ci "No VBI", 2178c2ecf20Sopenharmony_ci "Private Packet, IVTV Format", 2188c2ecf20Sopenharmony_ci NULL 2198c2ecf20Sopenharmony_ci }; 2208c2ecf20Sopenharmony_ci static const char * const camera_power_line_frequency[] = { 2218c2ecf20Sopenharmony_ci "Disabled", 2228c2ecf20Sopenharmony_ci "50 Hz", 2238c2ecf20Sopenharmony_ci "60 Hz", 2248c2ecf20Sopenharmony_ci "Auto", 2258c2ecf20Sopenharmony_ci NULL 2268c2ecf20Sopenharmony_ci }; 2278c2ecf20Sopenharmony_ci static const char * const camera_exposure_auto[] = { 2288c2ecf20Sopenharmony_ci "Auto Mode", 2298c2ecf20Sopenharmony_ci "Manual Mode", 2308c2ecf20Sopenharmony_ci "Shutter Priority Mode", 2318c2ecf20Sopenharmony_ci "Aperture Priority Mode", 2328c2ecf20Sopenharmony_ci NULL 2338c2ecf20Sopenharmony_ci }; 2348c2ecf20Sopenharmony_ci static const char * const camera_exposure_metering[] = { 2358c2ecf20Sopenharmony_ci "Average", 2368c2ecf20Sopenharmony_ci "Center Weighted", 2378c2ecf20Sopenharmony_ci "Spot", 2388c2ecf20Sopenharmony_ci "Matrix", 2398c2ecf20Sopenharmony_ci NULL 2408c2ecf20Sopenharmony_ci }; 2418c2ecf20Sopenharmony_ci static const char * const camera_auto_focus_range[] = { 2428c2ecf20Sopenharmony_ci "Auto", 2438c2ecf20Sopenharmony_ci "Normal", 2448c2ecf20Sopenharmony_ci "Macro", 2458c2ecf20Sopenharmony_ci "Infinity", 2468c2ecf20Sopenharmony_ci NULL 2478c2ecf20Sopenharmony_ci }; 2488c2ecf20Sopenharmony_ci static const char * const colorfx[] = { 2498c2ecf20Sopenharmony_ci "None", 2508c2ecf20Sopenharmony_ci "Black & White", 2518c2ecf20Sopenharmony_ci "Sepia", 2528c2ecf20Sopenharmony_ci "Negative", 2538c2ecf20Sopenharmony_ci "Emboss", 2548c2ecf20Sopenharmony_ci "Sketch", 2558c2ecf20Sopenharmony_ci "Sky Blue", 2568c2ecf20Sopenharmony_ci "Grass Green", 2578c2ecf20Sopenharmony_ci "Skin Whiten", 2588c2ecf20Sopenharmony_ci "Vivid", 2598c2ecf20Sopenharmony_ci "Aqua", 2608c2ecf20Sopenharmony_ci "Art Freeze", 2618c2ecf20Sopenharmony_ci "Silhouette", 2628c2ecf20Sopenharmony_ci "Solarization", 2638c2ecf20Sopenharmony_ci "Antique", 2648c2ecf20Sopenharmony_ci "Set Cb/Cr", 2658c2ecf20Sopenharmony_ci NULL 2668c2ecf20Sopenharmony_ci }; 2678c2ecf20Sopenharmony_ci static const char * const auto_n_preset_white_balance[] = { 2688c2ecf20Sopenharmony_ci "Manual", 2698c2ecf20Sopenharmony_ci "Auto", 2708c2ecf20Sopenharmony_ci "Incandescent", 2718c2ecf20Sopenharmony_ci "Fluorescent", 2728c2ecf20Sopenharmony_ci "Fluorescent H", 2738c2ecf20Sopenharmony_ci "Horizon", 2748c2ecf20Sopenharmony_ci "Daylight", 2758c2ecf20Sopenharmony_ci "Flash", 2768c2ecf20Sopenharmony_ci "Cloudy", 2778c2ecf20Sopenharmony_ci "Shade", 2788c2ecf20Sopenharmony_ci NULL, 2798c2ecf20Sopenharmony_ci }; 2808c2ecf20Sopenharmony_ci static const char * const camera_iso_sensitivity_auto[] = { 2818c2ecf20Sopenharmony_ci "Manual", 2828c2ecf20Sopenharmony_ci "Auto", 2838c2ecf20Sopenharmony_ci NULL 2848c2ecf20Sopenharmony_ci }; 2858c2ecf20Sopenharmony_ci static const char * const scene_mode[] = { 2868c2ecf20Sopenharmony_ci "None", 2878c2ecf20Sopenharmony_ci "Backlight", 2888c2ecf20Sopenharmony_ci "Beach/Snow", 2898c2ecf20Sopenharmony_ci "Candle Light", 2908c2ecf20Sopenharmony_ci "Dusk/Dawn", 2918c2ecf20Sopenharmony_ci "Fall Colors", 2928c2ecf20Sopenharmony_ci "Fireworks", 2938c2ecf20Sopenharmony_ci "Landscape", 2948c2ecf20Sopenharmony_ci "Night", 2958c2ecf20Sopenharmony_ci "Party/Indoor", 2968c2ecf20Sopenharmony_ci "Portrait", 2978c2ecf20Sopenharmony_ci "Sports", 2988c2ecf20Sopenharmony_ci "Sunset", 2998c2ecf20Sopenharmony_ci "Text", 3008c2ecf20Sopenharmony_ci NULL 3018c2ecf20Sopenharmony_ci }; 3028c2ecf20Sopenharmony_ci static const char * const tune_emphasis[] = { 3038c2ecf20Sopenharmony_ci "None", 3048c2ecf20Sopenharmony_ci "50 Microseconds", 3058c2ecf20Sopenharmony_ci "75 Microseconds", 3068c2ecf20Sopenharmony_ci NULL, 3078c2ecf20Sopenharmony_ci }; 3088c2ecf20Sopenharmony_ci static const char * const header_mode[] = { 3098c2ecf20Sopenharmony_ci "Separate Buffer", 3108c2ecf20Sopenharmony_ci "Joined With 1st Frame", 3118c2ecf20Sopenharmony_ci NULL, 3128c2ecf20Sopenharmony_ci }; 3138c2ecf20Sopenharmony_ci static const char * const multi_slice[] = { 3148c2ecf20Sopenharmony_ci "Single", 3158c2ecf20Sopenharmony_ci "Max Macroblocks", 3168c2ecf20Sopenharmony_ci "Max Bytes", 3178c2ecf20Sopenharmony_ci NULL, 3188c2ecf20Sopenharmony_ci }; 3198c2ecf20Sopenharmony_ci static const char * const entropy_mode[] = { 3208c2ecf20Sopenharmony_ci "CAVLC", 3218c2ecf20Sopenharmony_ci "CABAC", 3228c2ecf20Sopenharmony_ci NULL, 3238c2ecf20Sopenharmony_ci }; 3248c2ecf20Sopenharmony_ci static const char * const mpeg_h264_level[] = { 3258c2ecf20Sopenharmony_ci "1", 3268c2ecf20Sopenharmony_ci "1b", 3278c2ecf20Sopenharmony_ci "1.1", 3288c2ecf20Sopenharmony_ci "1.2", 3298c2ecf20Sopenharmony_ci "1.3", 3308c2ecf20Sopenharmony_ci "2", 3318c2ecf20Sopenharmony_ci "2.1", 3328c2ecf20Sopenharmony_ci "2.2", 3338c2ecf20Sopenharmony_ci "3", 3348c2ecf20Sopenharmony_ci "3.1", 3358c2ecf20Sopenharmony_ci "3.2", 3368c2ecf20Sopenharmony_ci "4", 3378c2ecf20Sopenharmony_ci "4.1", 3388c2ecf20Sopenharmony_ci "4.2", 3398c2ecf20Sopenharmony_ci "5", 3408c2ecf20Sopenharmony_ci "5.1", 3418c2ecf20Sopenharmony_ci "5.2", 3428c2ecf20Sopenharmony_ci "6.0", 3438c2ecf20Sopenharmony_ci "6.1", 3448c2ecf20Sopenharmony_ci "6.2", 3458c2ecf20Sopenharmony_ci NULL, 3468c2ecf20Sopenharmony_ci }; 3478c2ecf20Sopenharmony_ci static const char * const h264_loop_filter[] = { 3488c2ecf20Sopenharmony_ci "Enabled", 3498c2ecf20Sopenharmony_ci "Disabled", 3508c2ecf20Sopenharmony_ci "Disabled at Slice Boundary", 3518c2ecf20Sopenharmony_ci NULL, 3528c2ecf20Sopenharmony_ci }; 3538c2ecf20Sopenharmony_ci static const char * const h264_profile[] = { 3548c2ecf20Sopenharmony_ci "Baseline", 3558c2ecf20Sopenharmony_ci "Constrained Baseline", 3568c2ecf20Sopenharmony_ci "Main", 3578c2ecf20Sopenharmony_ci "Extended", 3588c2ecf20Sopenharmony_ci "High", 3598c2ecf20Sopenharmony_ci "High 10", 3608c2ecf20Sopenharmony_ci "High 422", 3618c2ecf20Sopenharmony_ci "High 444 Predictive", 3628c2ecf20Sopenharmony_ci "High 10 Intra", 3638c2ecf20Sopenharmony_ci "High 422 Intra", 3648c2ecf20Sopenharmony_ci "High 444 Intra", 3658c2ecf20Sopenharmony_ci "CAVLC 444 Intra", 3668c2ecf20Sopenharmony_ci "Scalable Baseline", 3678c2ecf20Sopenharmony_ci "Scalable High", 3688c2ecf20Sopenharmony_ci "Scalable High Intra", 3698c2ecf20Sopenharmony_ci "Stereo High", 3708c2ecf20Sopenharmony_ci "Multiview High", 3718c2ecf20Sopenharmony_ci "Constrained High", 3728c2ecf20Sopenharmony_ci NULL, 3738c2ecf20Sopenharmony_ci }; 3748c2ecf20Sopenharmony_ci static const char * const vui_sar_idc[] = { 3758c2ecf20Sopenharmony_ci "Unspecified", 3768c2ecf20Sopenharmony_ci "1:1", 3778c2ecf20Sopenharmony_ci "12:11", 3788c2ecf20Sopenharmony_ci "10:11", 3798c2ecf20Sopenharmony_ci "16:11", 3808c2ecf20Sopenharmony_ci "40:33", 3818c2ecf20Sopenharmony_ci "24:11", 3828c2ecf20Sopenharmony_ci "20:11", 3838c2ecf20Sopenharmony_ci "32:11", 3848c2ecf20Sopenharmony_ci "80:33", 3858c2ecf20Sopenharmony_ci "18:11", 3868c2ecf20Sopenharmony_ci "15:11", 3878c2ecf20Sopenharmony_ci "64:33", 3888c2ecf20Sopenharmony_ci "160:99", 3898c2ecf20Sopenharmony_ci "4:3", 3908c2ecf20Sopenharmony_ci "3:2", 3918c2ecf20Sopenharmony_ci "2:1", 3928c2ecf20Sopenharmony_ci "Extended SAR", 3938c2ecf20Sopenharmony_ci NULL, 3948c2ecf20Sopenharmony_ci }; 3958c2ecf20Sopenharmony_ci static const char * const h264_fp_arrangement_type[] = { 3968c2ecf20Sopenharmony_ci "Checkerboard", 3978c2ecf20Sopenharmony_ci "Column", 3988c2ecf20Sopenharmony_ci "Row", 3998c2ecf20Sopenharmony_ci "Side by Side", 4008c2ecf20Sopenharmony_ci "Top Bottom", 4018c2ecf20Sopenharmony_ci "Temporal", 4028c2ecf20Sopenharmony_ci NULL, 4038c2ecf20Sopenharmony_ci }; 4048c2ecf20Sopenharmony_ci static const char * const h264_fmo_map_type[] = { 4058c2ecf20Sopenharmony_ci "Interleaved Slices", 4068c2ecf20Sopenharmony_ci "Scattered Slices", 4078c2ecf20Sopenharmony_ci "Foreground with Leftover", 4088c2ecf20Sopenharmony_ci "Box Out", 4098c2ecf20Sopenharmony_ci "Raster Scan", 4108c2ecf20Sopenharmony_ci "Wipe Scan", 4118c2ecf20Sopenharmony_ci "Explicit", 4128c2ecf20Sopenharmony_ci NULL, 4138c2ecf20Sopenharmony_ci }; 4148c2ecf20Sopenharmony_ci static const char * const h264_decode_mode[] = { 4158c2ecf20Sopenharmony_ci "Slice-Based", 4168c2ecf20Sopenharmony_ci "Frame-Based", 4178c2ecf20Sopenharmony_ci NULL, 4188c2ecf20Sopenharmony_ci }; 4198c2ecf20Sopenharmony_ci static const char * const h264_start_code[] = { 4208c2ecf20Sopenharmony_ci "No Start Code", 4218c2ecf20Sopenharmony_ci "Annex B Start Code", 4228c2ecf20Sopenharmony_ci NULL, 4238c2ecf20Sopenharmony_ci }; 4248c2ecf20Sopenharmony_ci static const char * const mpeg_mpeg2_level[] = { 4258c2ecf20Sopenharmony_ci "Low", 4268c2ecf20Sopenharmony_ci "Main", 4278c2ecf20Sopenharmony_ci "High 1440", 4288c2ecf20Sopenharmony_ci "High", 4298c2ecf20Sopenharmony_ci NULL, 4308c2ecf20Sopenharmony_ci }; 4318c2ecf20Sopenharmony_ci static const char * const mpeg2_profile[] = { 4328c2ecf20Sopenharmony_ci "Simple", 4338c2ecf20Sopenharmony_ci "Main", 4348c2ecf20Sopenharmony_ci "SNR Scalable", 4358c2ecf20Sopenharmony_ci "Spatially Scalable", 4368c2ecf20Sopenharmony_ci "High", 4378c2ecf20Sopenharmony_ci NULL, 4388c2ecf20Sopenharmony_ci }; 4398c2ecf20Sopenharmony_ci static const char * const mpeg_mpeg4_level[] = { 4408c2ecf20Sopenharmony_ci "0", 4418c2ecf20Sopenharmony_ci "0b", 4428c2ecf20Sopenharmony_ci "1", 4438c2ecf20Sopenharmony_ci "2", 4448c2ecf20Sopenharmony_ci "3", 4458c2ecf20Sopenharmony_ci "3b", 4468c2ecf20Sopenharmony_ci "4", 4478c2ecf20Sopenharmony_ci "5", 4488c2ecf20Sopenharmony_ci NULL, 4498c2ecf20Sopenharmony_ci }; 4508c2ecf20Sopenharmony_ci static const char * const mpeg4_profile[] = { 4518c2ecf20Sopenharmony_ci "Simple", 4528c2ecf20Sopenharmony_ci "Advanced Simple", 4538c2ecf20Sopenharmony_ci "Core", 4548c2ecf20Sopenharmony_ci "Simple Scalable", 4558c2ecf20Sopenharmony_ci "Advanced Coding Efficiency", 4568c2ecf20Sopenharmony_ci NULL, 4578c2ecf20Sopenharmony_ci }; 4588c2ecf20Sopenharmony_ci 4598c2ecf20Sopenharmony_ci static const char * const vpx_golden_frame_sel[] = { 4608c2ecf20Sopenharmony_ci "Use Previous Frame", 4618c2ecf20Sopenharmony_ci "Use Previous Specific Frame", 4628c2ecf20Sopenharmony_ci NULL, 4638c2ecf20Sopenharmony_ci }; 4648c2ecf20Sopenharmony_ci static const char * const vp8_profile[] = { 4658c2ecf20Sopenharmony_ci "0", 4668c2ecf20Sopenharmony_ci "1", 4678c2ecf20Sopenharmony_ci "2", 4688c2ecf20Sopenharmony_ci "3", 4698c2ecf20Sopenharmony_ci NULL, 4708c2ecf20Sopenharmony_ci }; 4718c2ecf20Sopenharmony_ci static const char * const vp9_profile[] = { 4728c2ecf20Sopenharmony_ci "0", 4738c2ecf20Sopenharmony_ci "1", 4748c2ecf20Sopenharmony_ci "2", 4758c2ecf20Sopenharmony_ci "3", 4768c2ecf20Sopenharmony_ci NULL, 4778c2ecf20Sopenharmony_ci }; 4788c2ecf20Sopenharmony_ci static const char * const vp9_level[] = { 4798c2ecf20Sopenharmony_ci "1", 4808c2ecf20Sopenharmony_ci "1.1", 4818c2ecf20Sopenharmony_ci "2", 4828c2ecf20Sopenharmony_ci "2.1", 4838c2ecf20Sopenharmony_ci "3", 4848c2ecf20Sopenharmony_ci "3.1", 4858c2ecf20Sopenharmony_ci "4", 4868c2ecf20Sopenharmony_ci "4.1", 4878c2ecf20Sopenharmony_ci "5", 4888c2ecf20Sopenharmony_ci "5.1", 4898c2ecf20Sopenharmony_ci "5.2", 4908c2ecf20Sopenharmony_ci "6", 4918c2ecf20Sopenharmony_ci "6.1", 4928c2ecf20Sopenharmony_ci "6.2", 4938c2ecf20Sopenharmony_ci NULL, 4948c2ecf20Sopenharmony_ci }; 4958c2ecf20Sopenharmony_ci 4968c2ecf20Sopenharmony_ci static const char * const flash_led_mode[] = { 4978c2ecf20Sopenharmony_ci "Off", 4988c2ecf20Sopenharmony_ci "Flash", 4998c2ecf20Sopenharmony_ci "Torch", 5008c2ecf20Sopenharmony_ci NULL, 5018c2ecf20Sopenharmony_ci }; 5028c2ecf20Sopenharmony_ci static const char * const flash_strobe_source[] = { 5038c2ecf20Sopenharmony_ci "Software", 5048c2ecf20Sopenharmony_ci "External", 5058c2ecf20Sopenharmony_ci NULL, 5068c2ecf20Sopenharmony_ci }; 5078c2ecf20Sopenharmony_ci 5088c2ecf20Sopenharmony_ci static const char * const jpeg_chroma_subsampling[] = { 5098c2ecf20Sopenharmony_ci "4:4:4", 5108c2ecf20Sopenharmony_ci "4:2:2", 5118c2ecf20Sopenharmony_ci "4:2:0", 5128c2ecf20Sopenharmony_ci "4:1:1", 5138c2ecf20Sopenharmony_ci "4:1:0", 5148c2ecf20Sopenharmony_ci "Gray", 5158c2ecf20Sopenharmony_ci NULL, 5168c2ecf20Sopenharmony_ci }; 5178c2ecf20Sopenharmony_ci static const char * const dv_tx_mode[] = { 5188c2ecf20Sopenharmony_ci "DVI-D", 5198c2ecf20Sopenharmony_ci "HDMI", 5208c2ecf20Sopenharmony_ci NULL, 5218c2ecf20Sopenharmony_ci }; 5228c2ecf20Sopenharmony_ci static const char * const dv_rgb_range[] = { 5238c2ecf20Sopenharmony_ci "Automatic", 5248c2ecf20Sopenharmony_ci "RGB Limited Range (16-235)", 5258c2ecf20Sopenharmony_ci "RGB Full Range (0-255)", 5268c2ecf20Sopenharmony_ci NULL, 5278c2ecf20Sopenharmony_ci }; 5288c2ecf20Sopenharmony_ci static const char * const dv_it_content_type[] = { 5298c2ecf20Sopenharmony_ci "Graphics", 5308c2ecf20Sopenharmony_ci "Photo", 5318c2ecf20Sopenharmony_ci "Cinema", 5328c2ecf20Sopenharmony_ci "Game", 5338c2ecf20Sopenharmony_ci "No IT Content", 5348c2ecf20Sopenharmony_ci NULL, 5358c2ecf20Sopenharmony_ci }; 5368c2ecf20Sopenharmony_ci static const char * const detect_md_mode[] = { 5378c2ecf20Sopenharmony_ci "Disabled", 5388c2ecf20Sopenharmony_ci "Global", 5398c2ecf20Sopenharmony_ci "Threshold Grid", 5408c2ecf20Sopenharmony_ci "Region Grid", 5418c2ecf20Sopenharmony_ci NULL, 5428c2ecf20Sopenharmony_ci }; 5438c2ecf20Sopenharmony_ci 5448c2ecf20Sopenharmony_ci static const char * const hevc_profile[] = { 5458c2ecf20Sopenharmony_ci "Main", 5468c2ecf20Sopenharmony_ci "Main Still Picture", 5478c2ecf20Sopenharmony_ci "Main 10", 5488c2ecf20Sopenharmony_ci NULL, 5498c2ecf20Sopenharmony_ci }; 5508c2ecf20Sopenharmony_ci static const char * const hevc_level[] = { 5518c2ecf20Sopenharmony_ci "1", 5528c2ecf20Sopenharmony_ci "2", 5538c2ecf20Sopenharmony_ci "2.1", 5548c2ecf20Sopenharmony_ci "3", 5558c2ecf20Sopenharmony_ci "3.1", 5568c2ecf20Sopenharmony_ci "4", 5578c2ecf20Sopenharmony_ci "4.1", 5588c2ecf20Sopenharmony_ci "5", 5598c2ecf20Sopenharmony_ci "5.1", 5608c2ecf20Sopenharmony_ci "5.2", 5618c2ecf20Sopenharmony_ci "6", 5628c2ecf20Sopenharmony_ci "6.1", 5638c2ecf20Sopenharmony_ci "6.2", 5648c2ecf20Sopenharmony_ci NULL, 5658c2ecf20Sopenharmony_ci }; 5668c2ecf20Sopenharmony_ci static const char * const hevc_hierarchial_coding_type[] = { 5678c2ecf20Sopenharmony_ci "B", 5688c2ecf20Sopenharmony_ci "P", 5698c2ecf20Sopenharmony_ci NULL, 5708c2ecf20Sopenharmony_ci }; 5718c2ecf20Sopenharmony_ci static const char * const hevc_refresh_type[] = { 5728c2ecf20Sopenharmony_ci "None", 5738c2ecf20Sopenharmony_ci "CRA", 5748c2ecf20Sopenharmony_ci "IDR", 5758c2ecf20Sopenharmony_ci NULL, 5768c2ecf20Sopenharmony_ci }; 5778c2ecf20Sopenharmony_ci static const char * const hevc_size_of_length_field[] = { 5788c2ecf20Sopenharmony_ci "0", 5798c2ecf20Sopenharmony_ci "1", 5808c2ecf20Sopenharmony_ci "2", 5818c2ecf20Sopenharmony_ci "4", 5828c2ecf20Sopenharmony_ci NULL, 5838c2ecf20Sopenharmony_ci }; 5848c2ecf20Sopenharmony_ci static const char * const hevc_tier[] = { 5858c2ecf20Sopenharmony_ci "Main", 5868c2ecf20Sopenharmony_ci "High", 5878c2ecf20Sopenharmony_ci NULL, 5888c2ecf20Sopenharmony_ci }; 5898c2ecf20Sopenharmony_ci static const char * const hevc_loop_filter_mode[] = { 5908c2ecf20Sopenharmony_ci "Disabled", 5918c2ecf20Sopenharmony_ci "Enabled", 5928c2ecf20Sopenharmony_ci "Disabled at slice boundary", 5938c2ecf20Sopenharmony_ci "NULL", 5948c2ecf20Sopenharmony_ci }; 5958c2ecf20Sopenharmony_ci static const char * const hevc_decode_mode[] = { 5968c2ecf20Sopenharmony_ci "Slice-Based", 5978c2ecf20Sopenharmony_ci "Frame-Based", 5988c2ecf20Sopenharmony_ci NULL, 5998c2ecf20Sopenharmony_ci }; 6008c2ecf20Sopenharmony_ci static const char * const hevc_start_code[] = { 6018c2ecf20Sopenharmony_ci "No Start Code", 6028c2ecf20Sopenharmony_ci "Annex B Start Code", 6038c2ecf20Sopenharmony_ci NULL, 6048c2ecf20Sopenharmony_ci }; 6058c2ecf20Sopenharmony_ci static const char * const camera_orientation[] = { 6068c2ecf20Sopenharmony_ci "Front", 6078c2ecf20Sopenharmony_ci "Back", 6088c2ecf20Sopenharmony_ci "External", 6098c2ecf20Sopenharmony_ci NULL, 6108c2ecf20Sopenharmony_ci }; 6118c2ecf20Sopenharmony_ci static const char * const mpeg_video_frame_skip[] = { 6128c2ecf20Sopenharmony_ci "Disabled", 6138c2ecf20Sopenharmony_ci "Level Limit", 6148c2ecf20Sopenharmony_ci "VBV/CPB Limit", 6158c2ecf20Sopenharmony_ci NULL, 6168c2ecf20Sopenharmony_ci }; 6178c2ecf20Sopenharmony_ci 6188c2ecf20Sopenharmony_ci switch (id) { 6198c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: 6208c2ecf20Sopenharmony_ci return mpeg_audio_sampling_freq; 6218c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_AUDIO_ENCODING: 6228c2ecf20Sopenharmony_ci return mpeg_audio_encoding; 6238c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_AUDIO_L1_BITRATE: 6248c2ecf20Sopenharmony_ci return mpeg_audio_l1_bitrate; 6258c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_AUDIO_L2_BITRATE: 6268c2ecf20Sopenharmony_ci return mpeg_audio_l2_bitrate; 6278c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_AUDIO_L3_BITRATE: 6288c2ecf20Sopenharmony_ci return mpeg_audio_l3_bitrate; 6298c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: 6308c2ecf20Sopenharmony_ci return mpeg_audio_ac3_bitrate; 6318c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_AUDIO_MODE: 6328c2ecf20Sopenharmony_ci return mpeg_audio_mode; 6338c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: 6348c2ecf20Sopenharmony_ci return mpeg_audio_mode_extension; 6358c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_AUDIO_EMPHASIS: 6368c2ecf20Sopenharmony_ci return mpeg_audio_emphasis; 6378c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_AUDIO_CRC: 6388c2ecf20Sopenharmony_ci return mpeg_audio_crc; 6398c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK: 6408c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_AUDIO_DEC_MULTILINGUAL_PLAYBACK: 6418c2ecf20Sopenharmony_ci return mpeg_audio_dec_playback; 6428c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_ENCODING: 6438c2ecf20Sopenharmony_ci return mpeg_video_encoding; 6448c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_ASPECT: 6458c2ecf20Sopenharmony_ci return mpeg_video_aspect; 6468c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: 6478c2ecf20Sopenharmony_ci return mpeg_video_bitrate_mode; 6488c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_STREAM_TYPE: 6498c2ecf20Sopenharmony_ci return mpeg_stream_type; 6508c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_STREAM_VBI_FMT: 6518c2ecf20Sopenharmony_ci return mpeg_stream_vbi_fmt; 6528c2ecf20Sopenharmony_ci case V4L2_CID_POWER_LINE_FREQUENCY: 6538c2ecf20Sopenharmony_ci return camera_power_line_frequency; 6548c2ecf20Sopenharmony_ci case V4L2_CID_EXPOSURE_AUTO: 6558c2ecf20Sopenharmony_ci return camera_exposure_auto; 6568c2ecf20Sopenharmony_ci case V4L2_CID_EXPOSURE_METERING: 6578c2ecf20Sopenharmony_ci return camera_exposure_metering; 6588c2ecf20Sopenharmony_ci case V4L2_CID_AUTO_FOCUS_RANGE: 6598c2ecf20Sopenharmony_ci return camera_auto_focus_range; 6608c2ecf20Sopenharmony_ci case V4L2_CID_COLORFX: 6618c2ecf20Sopenharmony_ci return colorfx; 6628c2ecf20Sopenharmony_ci case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE: 6638c2ecf20Sopenharmony_ci return auto_n_preset_white_balance; 6648c2ecf20Sopenharmony_ci case V4L2_CID_ISO_SENSITIVITY_AUTO: 6658c2ecf20Sopenharmony_ci return camera_iso_sensitivity_auto; 6668c2ecf20Sopenharmony_ci case V4L2_CID_SCENE_MODE: 6678c2ecf20Sopenharmony_ci return scene_mode; 6688c2ecf20Sopenharmony_ci case V4L2_CID_TUNE_PREEMPHASIS: 6698c2ecf20Sopenharmony_ci return tune_emphasis; 6708c2ecf20Sopenharmony_ci case V4L2_CID_TUNE_DEEMPHASIS: 6718c2ecf20Sopenharmony_ci return tune_emphasis; 6728c2ecf20Sopenharmony_ci case V4L2_CID_FLASH_LED_MODE: 6738c2ecf20Sopenharmony_ci return flash_led_mode; 6748c2ecf20Sopenharmony_ci case V4L2_CID_FLASH_STROBE_SOURCE: 6758c2ecf20Sopenharmony_ci return flash_strobe_source; 6768c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEADER_MODE: 6778c2ecf20Sopenharmony_ci return header_mode; 6788c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_FRAME_SKIP_MODE: 6798c2ecf20Sopenharmony_ci return mpeg_video_frame_skip; 6808c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE: 6818c2ecf20Sopenharmony_ci return multi_slice; 6828c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE: 6838c2ecf20Sopenharmony_ci return entropy_mode; 6848c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_LEVEL: 6858c2ecf20Sopenharmony_ci return mpeg_h264_level; 6868c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE: 6878c2ecf20Sopenharmony_ci return h264_loop_filter; 6888c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_PROFILE: 6898c2ecf20Sopenharmony_ci return h264_profile; 6908c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC: 6918c2ecf20Sopenharmony_ci return vui_sar_idc; 6928c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE: 6938c2ecf20Sopenharmony_ci return h264_fp_arrangement_type; 6948c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_FMO_MAP_TYPE: 6958c2ecf20Sopenharmony_ci return h264_fmo_map_type; 6968c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_DECODE_MODE: 6978c2ecf20Sopenharmony_ci return h264_decode_mode; 6988c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_START_CODE: 6998c2ecf20Sopenharmony_ci return h264_start_code; 7008c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_MPEG2_LEVEL: 7018c2ecf20Sopenharmony_ci return mpeg_mpeg2_level; 7028c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_MPEG2_PROFILE: 7038c2ecf20Sopenharmony_ci return mpeg2_profile; 7048c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL: 7058c2ecf20Sopenharmony_ci return mpeg_mpeg4_level; 7068c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE: 7078c2ecf20Sopenharmony_ci return mpeg4_profile; 7088c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_SEL: 7098c2ecf20Sopenharmony_ci return vpx_golden_frame_sel; 7108c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_VP8_PROFILE: 7118c2ecf20Sopenharmony_ci return vp8_profile; 7128c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_VP9_PROFILE: 7138c2ecf20Sopenharmony_ci return vp9_profile; 7148c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_VP9_LEVEL: 7158c2ecf20Sopenharmony_ci return vp9_level; 7168c2ecf20Sopenharmony_ci case V4L2_CID_JPEG_CHROMA_SUBSAMPLING: 7178c2ecf20Sopenharmony_ci return jpeg_chroma_subsampling; 7188c2ecf20Sopenharmony_ci case V4L2_CID_DV_TX_MODE: 7198c2ecf20Sopenharmony_ci return dv_tx_mode; 7208c2ecf20Sopenharmony_ci case V4L2_CID_DV_TX_RGB_RANGE: 7218c2ecf20Sopenharmony_ci case V4L2_CID_DV_RX_RGB_RANGE: 7228c2ecf20Sopenharmony_ci return dv_rgb_range; 7238c2ecf20Sopenharmony_ci case V4L2_CID_DV_TX_IT_CONTENT_TYPE: 7248c2ecf20Sopenharmony_ci case V4L2_CID_DV_RX_IT_CONTENT_TYPE: 7258c2ecf20Sopenharmony_ci return dv_it_content_type; 7268c2ecf20Sopenharmony_ci case V4L2_CID_DETECT_MD_MODE: 7278c2ecf20Sopenharmony_ci return detect_md_mode; 7288c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_PROFILE: 7298c2ecf20Sopenharmony_ci return hevc_profile; 7308c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_LEVEL: 7318c2ecf20Sopenharmony_ci return hevc_level; 7328c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_TYPE: 7338c2ecf20Sopenharmony_ci return hevc_hierarchial_coding_type; 7348c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_REFRESH_TYPE: 7358c2ecf20Sopenharmony_ci return hevc_refresh_type; 7368c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_SIZE_OF_LENGTH_FIELD: 7378c2ecf20Sopenharmony_ci return hevc_size_of_length_field; 7388c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_TIER: 7398c2ecf20Sopenharmony_ci return hevc_tier; 7408c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE: 7418c2ecf20Sopenharmony_ci return hevc_loop_filter_mode; 7428c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE: 7438c2ecf20Sopenharmony_ci return hevc_decode_mode; 7448c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_START_CODE: 7458c2ecf20Sopenharmony_ci return hevc_start_code; 7468c2ecf20Sopenharmony_ci case V4L2_CID_CAMERA_ORIENTATION: 7478c2ecf20Sopenharmony_ci return camera_orientation; 7488c2ecf20Sopenharmony_ci default: 7498c2ecf20Sopenharmony_ci return NULL; 7508c2ecf20Sopenharmony_ci } 7518c2ecf20Sopenharmony_ci} 7528c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_get_menu); 7538c2ecf20Sopenharmony_ci 7548c2ecf20Sopenharmony_ci#define __v4l2_qmenu_int_len(arr, len) ({ *(len) = ARRAY_SIZE(arr); arr; }) 7558c2ecf20Sopenharmony_ci/* 7568c2ecf20Sopenharmony_ci * Returns NULL or an s64 type array containing the menu for given 7578c2ecf20Sopenharmony_ci * control ID. The total number of the menu items is returned in @len. 7588c2ecf20Sopenharmony_ci */ 7598c2ecf20Sopenharmony_ciconst s64 *v4l2_ctrl_get_int_menu(u32 id, u32 *len) 7608c2ecf20Sopenharmony_ci{ 7618c2ecf20Sopenharmony_ci static const s64 qmenu_int_vpx_num_partitions[] = { 7628c2ecf20Sopenharmony_ci 1, 2, 4, 8, 7638c2ecf20Sopenharmony_ci }; 7648c2ecf20Sopenharmony_ci 7658c2ecf20Sopenharmony_ci static const s64 qmenu_int_vpx_num_ref_frames[] = { 7668c2ecf20Sopenharmony_ci 1, 2, 3, 7678c2ecf20Sopenharmony_ci }; 7688c2ecf20Sopenharmony_ci 7698c2ecf20Sopenharmony_ci switch (id) { 7708c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_VPX_NUM_PARTITIONS: 7718c2ecf20Sopenharmony_ci return __v4l2_qmenu_int_len(qmenu_int_vpx_num_partitions, len); 7728c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_VPX_NUM_REF_FRAMES: 7738c2ecf20Sopenharmony_ci return __v4l2_qmenu_int_len(qmenu_int_vpx_num_ref_frames, len); 7748c2ecf20Sopenharmony_ci default: 7758c2ecf20Sopenharmony_ci *len = 0; 7768c2ecf20Sopenharmony_ci return NULL; 7778c2ecf20Sopenharmony_ci } 7788c2ecf20Sopenharmony_ci} 7798c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_get_int_menu); 7808c2ecf20Sopenharmony_ci 7818c2ecf20Sopenharmony_ci/* Return the control name. */ 7828c2ecf20Sopenharmony_ciconst char *v4l2_ctrl_get_name(u32 id) 7838c2ecf20Sopenharmony_ci{ 7848c2ecf20Sopenharmony_ci switch (id) { 7858c2ecf20Sopenharmony_ci /* USER controls */ 7868c2ecf20Sopenharmony_ci /* Keep the order of the 'case's the same as in v4l2-controls.h! */ 7878c2ecf20Sopenharmony_ci case V4L2_CID_USER_CLASS: return "User Controls"; 7888c2ecf20Sopenharmony_ci case V4L2_CID_BRIGHTNESS: return "Brightness"; 7898c2ecf20Sopenharmony_ci case V4L2_CID_CONTRAST: return "Contrast"; 7908c2ecf20Sopenharmony_ci case V4L2_CID_SATURATION: return "Saturation"; 7918c2ecf20Sopenharmony_ci case V4L2_CID_HUE: return "Hue"; 7928c2ecf20Sopenharmony_ci case V4L2_CID_AUDIO_VOLUME: return "Volume"; 7938c2ecf20Sopenharmony_ci case V4L2_CID_AUDIO_BALANCE: return "Balance"; 7948c2ecf20Sopenharmony_ci case V4L2_CID_AUDIO_BASS: return "Bass"; 7958c2ecf20Sopenharmony_ci case V4L2_CID_AUDIO_TREBLE: return "Treble"; 7968c2ecf20Sopenharmony_ci case V4L2_CID_AUDIO_MUTE: return "Mute"; 7978c2ecf20Sopenharmony_ci case V4L2_CID_AUDIO_LOUDNESS: return "Loudness"; 7988c2ecf20Sopenharmony_ci case V4L2_CID_BLACK_LEVEL: return "Black Level"; 7998c2ecf20Sopenharmony_ci case V4L2_CID_AUTO_WHITE_BALANCE: return "White Balance, Automatic"; 8008c2ecf20Sopenharmony_ci case V4L2_CID_DO_WHITE_BALANCE: return "Do White Balance"; 8018c2ecf20Sopenharmony_ci case V4L2_CID_RED_BALANCE: return "Red Balance"; 8028c2ecf20Sopenharmony_ci case V4L2_CID_BLUE_BALANCE: return "Blue Balance"; 8038c2ecf20Sopenharmony_ci case V4L2_CID_GAMMA: return "Gamma"; 8048c2ecf20Sopenharmony_ci case V4L2_CID_EXPOSURE: return "Exposure"; 8058c2ecf20Sopenharmony_ci case V4L2_CID_AUTOGAIN: return "Gain, Automatic"; 8068c2ecf20Sopenharmony_ci case V4L2_CID_GAIN: return "Gain"; 8078c2ecf20Sopenharmony_ci case V4L2_CID_HFLIP: return "Horizontal Flip"; 8088c2ecf20Sopenharmony_ci case V4L2_CID_VFLIP: return "Vertical Flip"; 8098c2ecf20Sopenharmony_ci case V4L2_CID_POWER_LINE_FREQUENCY: return "Power Line Frequency"; 8108c2ecf20Sopenharmony_ci case V4L2_CID_HUE_AUTO: return "Hue, Automatic"; 8118c2ecf20Sopenharmony_ci case V4L2_CID_WHITE_BALANCE_TEMPERATURE: return "White Balance Temperature"; 8128c2ecf20Sopenharmony_ci case V4L2_CID_SHARPNESS: return "Sharpness"; 8138c2ecf20Sopenharmony_ci case V4L2_CID_BACKLIGHT_COMPENSATION: return "Backlight Compensation"; 8148c2ecf20Sopenharmony_ci case V4L2_CID_CHROMA_AGC: return "Chroma AGC"; 8158c2ecf20Sopenharmony_ci case V4L2_CID_COLOR_KILLER: return "Color Killer"; 8168c2ecf20Sopenharmony_ci case V4L2_CID_COLORFX: return "Color Effects"; 8178c2ecf20Sopenharmony_ci case V4L2_CID_AUTOBRIGHTNESS: return "Brightness, Automatic"; 8188c2ecf20Sopenharmony_ci case V4L2_CID_BAND_STOP_FILTER: return "Band-Stop Filter"; 8198c2ecf20Sopenharmony_ci case V4L2_CID_ROTATE: return "Rotate"; 8208c2ecf20Sopenharmony_ci case V4L2_CID_BG_COLOR: return "Background Color"; 8218c2ecf20Sopenharmony_ci case V4L2_CID_CHROMA_GAIN: return "Chroma Gain"; 8228c2ecf20Sopenharmony_ci case V4L2_CID_ILLUMINATORS_1: return "Illuminator 1"; 8238c2ecf20Sopenharmony_ci case V4L2_CID_ILLUMINATORS_2: return "Illuminator 2"; 8248c2ecf20Sopenharmony_ci case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: return "Min Number of Capture Buffers"; 8258c2ecf20Sopenharmony_ci case V4L2_CID_MIN_BUFFERS_FOR_OUTPUT: return "Min Number of Output Buffers"; 8268c2ecf20Sopenharmony_ci case V4L2_CID_ALPHA_COMPONENT: return "Alpha Component"; 8278c2ecf20Sopenharmony_ci case V4L2_CID_COLORFX_CBCR: return "Color Effects, CbCr"; 8288c2ecf20Sopenharmony_ci 8298c2ecf20Sopenharmony_ci /* Codec controls */ 8308c2ecf20Sopenharmony_ci /* The MPEG controls are applicable to all codec controls 8318c2ecf20Sopenharmony_ci * and the 'MPEG' part of the define is historical */ 8328c2ecf20Sopenharmony_ci /* Keep the order of the 'case's the same as in videodev2.h! */ 8338c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_CLASS: return "Codec Controls"; 8348c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_STREAM_TYPE: return "Stream Type"; 8358c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_STREAM_PID_PMT: return "Stream PMT Program ID"; 8368c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_STREAM_PID_AUDIO: return "Stream Audio Program ID"; 8378c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_STREAM_PID_VIDEO: return "Stream Video Program ID"; 8388c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_STREAM_PID_PCR: return "Stream PCR Program ID"; 8398c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_STREAM_PES_ID_AUDIO: return "Stream PES Audio ID"; 8408c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_STREAM_PES_ID_VIDEO: return "Stream PES Video ID"; 8418c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_STREAM_VBI_FMT: return "Stream VBI Format"; 8428c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: return "Audio Sampling Frequency"; 8438c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_AUDIO_ENCODING: return "Audio Encoding"; 8448c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_AUDIO_L1_BITRATE: return "Audio Layer I Bitrate"; 8458c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_AUDIO_L2_BITRATE: return "Audio Layer II Bitrate"; 8468c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_AUDIO_L3_BITRATE: return "Audio Layer III Bitrate"; 8478c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_AUDIO_MODE: return "Audio Stereo Mode"; 8488c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: return "Audio Stereo Mode Extension"; 8498c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_AUDIO_EMPHASIS: return "Audio Emphasis"; 8508c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_AUDIO_CRC: return "Audio CRC"; 8518c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_AUDIO_MUTE: return "Audio Mute"; 8528c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_AUDIO_AAC_BITRATE: return "Audio AAC Bitrate"; 8538c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: return "Audio AC-3 Bitrate"; 8548c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK: return "Audio Playback"; 8558c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_AUDIO_DEC_MULTILINGUAL_PLAYBACK: return "Audio Multilingual Playback"; 8568c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_ENCODING: return "Video Encoding"; 8578c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_ASPECT: return "Video Aspect"; 8588c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_B_FRAMES: return "Video B Frames"; 8598c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_GOP_SIZE: return "Video GOP Size"; 8608c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: return "Video GOP Closure"; 8618c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_PULLDOWN: return "Video Pulldown"; 8628c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: return "Video Bitrate Mode"; 8638c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_CONSTANT_QUALITY: return "Constant Quality"; 8648c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_BITRATE: return "Video Bitrate"; 8658c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: return "Video Peak Bitrate"; 8668c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION: return "Video Temporal Decimation"; 8678c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_MUTE: return "Video Mute"; 8688c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_MUTE_YUV: return "Video Mute YUV"; 8698c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE: return "Decoder Slice Interface"; 8708c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER: return "MPEG4 Loop Filter Enable"; 8718c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB: return "Number of Intra Refresh MBs"; 8728c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE: return "Frame Level Rate Control Enable"; 8738c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE: return "H264 MB Level Rate Control"; 8748c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEADER_MODE: return "Sequence Header Mode"; 8758c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_MAX_REF_PIC: return "Max Number of Reference Pics"; 8768c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_FRAME_SKIP_MODE: return "Frame Skip Mode"; 8778c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP: return "H263 I-Frame QP Value"; 8788c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP: return "H263 P-Frame QP Value"; 8798c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP: return "H263 B-Frame QP Value"; 8808c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H263_MIN_QP: return "H263 Minimum QP Value"; 8818c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H263_MAX_QP: return "H263 Maximum QP Value"; 8828c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP: return "H264 I-Frame QP Value"; 8838c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP: return "H264 P-Frame QP Value"; 8848c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP: return "H264 B-Frame QP Value"; 8858c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_MAX_QP: return "H264 Maximum QP Value"; 8868c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_MIN_QP: return "H264 Minimum QP Value"; 8878c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM: return "H264 8x8 Transform Enable"; 8888c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_CPB_SIZE: return "H264 CPB Buffer Size"; 8898c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE: return "H264 Entropy Mode"; 8908c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_I_PERIOD: return "H264 I-Frame Period"; 8918c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_LEVEL: return "H264 Level"; 8928c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA: return "H264 Loop Filter Alpha Offset"; 8938c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA: return "H264 Loop Filter Beta Offset"; 8948c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE: return "H264 Loop Filter Mode"; 8958c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_PROFILE: return "H264 Profile"; 8968c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_HEIGHT: return "Vertical Size of SAR"; 8978c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH: return "Horizontal Size of SAR"; 8988c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE: return "Aspect Ratio VUI Enable"; 8998c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC: return "VUI Aspect Ratio IDC"; 9008c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING: return "H264 Enable Frame Packing SEI"; 9018c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_CURRENT_FRAME_0: return "H264 Set Curr. Frame as Frame0"; 9028c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE: return "H264 FP Arrangement Type"; 9038c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_FMO: return "H264 Flexible MB Ordering"; 9048c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_FMO_MAP_TYPE: return "H264 Map Type for FMO"; 9058c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_FMO_SLICE_GROUP: return "H264 FMO Number of Slice Groups"; 9068c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_DIRECTION: return "H264 FMO Direction of Change"; 9078c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_RATE: return "H264 FMO Size of 1st Slice Grp"; 9088c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_FMO_RUN_LENGTH: return "H264 FMO No. of Consecutive MBs"; 9098c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_ASO: return "H264 Arbitrary Slice Ordering"; 9108c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_ASO_SLICE_ORDER: return "H264 ASO Slice Order"; 9118c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING: return "Enable H264 Hierarchical Coding"; 9128c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_TYPE: return "H264 Hierarchical Coding Type"; 9138c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER:return "H264 Number of HC Layers"; 9148c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_QP: 9158c2ecf20Sopenharmony_ci return "H264 Set QP Value for HC Layers"; 9168c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_CONSTRAINED_INTRA_PREDICTION: 9178c2ecf20Sopenharmony_ci return "H264 Constrained Intra Pred"; 9188c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_CHROMA_QP_INDEX_OFFSET: return "H264 Chroma QP Index Offset"; 9198c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MIN_QP: return "H264 I-Frame Minimum QP Value"; 9208c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MAX_QP: return "H264 I-Frame Maximum QP Value"; 9218c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MIN_QP: return "H264 P-Frame Minimum QP Value"; 9228c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MAX_QP: return "H264 P-Frame Maximum QP Value"; 9238c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_SPS: return "H264 Sequence Parameter Set"; 9248c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_PPS: return "H264 Picture Parameter Set"; 9258c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX: return "H264 Scaling Matrix"; 9268c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAMS: return "H264 Slice Parameters"; 9278c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS: return "H264 Decode Parameters"; 9288c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_DECODE_MODE: return "H264 Decode Mode"; 9298c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_START_CODE: return "H264 Start Code"; 9308c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_PRED_WEIGHTS: return "H264 Prediction Weight Table"; 9318c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_MPEG2_LEVEL: return "MPEG2 Level"; 9328c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_MPEG2_PROFILE: return "MPEG2 Profile"; 9338c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP: return "MPEG4 I-Frame QP Value"; 9348c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP: return "MPEG4 P-Frame QP Value"; 9358c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP: return "MPEG4 B-Frame QP Value"; 9368c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP: return "MPEG4 Minimum QP Value"; 9378c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP: return "MPEG4 Maximum QP Value"; 9388c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL: return "MPEG4 Level"; 9398c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE: return "MPEG4 Profile"; 9408c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_MPEG4_QPEL: return "Quarter Pixel Search Enable"; 9418c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES: return "Maximum Bytes in a Slice"; 9428c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB: return "Number of MBs in a Slice"; 9438c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE: return "Slice Partitioning Method"; 9448c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_VBV_SIZE: return "VBV Buffer Size"; 9458c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_DEC_PTS: return "Video Decoder PTS"; 9468c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_DEC_FRAME: return "Video Decoder Frame Count"; 9478c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_VBV_DELAY: return "Initial Delay for VBV Control"; 9488c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_MV_H_SEARCH_RANGE: return "Horizontal MV Search Range"; 9498c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_MV_V_SEARCH_RANGE: return "Vertical MV Search Range"; 9508c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER: return "Repeat Sequence Header"; 9518c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME: return "Force Key Frame"; 9528c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_MPEG2_SLICE_PARAMS: return "MPEG-2 Slice Parameters"; 9538c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_MPEG2_QUANTIZATION: return "MPEG-2 Quantization Matrices"; 9548c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_FWHT_PARAMS: return "FWHT Stateless Parameters"; 9558c2ecf20Sopenharmony_ci case V4L2_CID_FWHT_I_FRAME_QP: return "FWHT I-Frame QP Value"; 9568c2ecf20Sopenharmony_ci case V4L2_CID_FWHT_P_FRAME_QP: return "FWHT P-Frame QP Value"; 9578c2ecf20Sopenharmony_ci 9588c2ecf20Sopenharmony_ci /* VPX controls */ 9598c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_VPX_NUM_PARTITIONS: return "VPX Number of Partitions"; 9608c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_VPX_IMD_DISABLE_4X4: return "VPX Intra Mode Decision Disable"; 9618c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_VPX_NUM_REF_FRAMES: return "VPX No. of Refs for P Frame"; 9628c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_VPX_FILTER_LEVEL: return "VPX Loop Filter Level Range"; 9638c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_VPX_FILTER_SHARPNESS: return "VPX Deblocking Effect Control"; 9648c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_REF_PERIOD: return "VPX Golden Frame Refresh Period"; 9658c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_SEL: return "VPX Golden Frame Indicator"; 9668c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_VPX_MIN_QP: return "VPX Minimum QP Value"; 9678c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_VPX_MAX_QP: return "VPX Maximum QP Value"; 9688c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_VPX_I_FRAME_QP: return "VPX I-Frame QP Value"; 9698c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_VPX_P_FRAME_QP: return "VPX P-Frame QP Value"; 9708c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_VP8_PROFILE: return "VP8 Profile"; 9718c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_VP9_PROFILE: return "VP9 Profile"; 9728c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_VP9_LEVEL: return "VP9 Level"; 9738c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER: return "VP8 Frame Header"; 9748c2ecf20Sopenharmony_ci 9758c2ecf20Sopenharmony_ci /* HEVC controls */ 9768c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP: return "HEVC I-Frame QP Value"; 9778c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_QP: return "HEVC P-Frame QP Value"; 9788c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_QP: return "HEVC B-Frame QP Value"; 9798c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP: return "HEVC Minimum QP Value"; 9808c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP: return "HEVC Maximum QP Value"; 9818c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_PROFILE: return "HEVC Profile"; 9828c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_LEVEL: return "HEVC Level"; 9838c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_TIER: return "HEVC Tier"; 9848c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_FRAME_RATE_RESOLUTION: return "HEVC Frame Rate Resolution"; 9858c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_MAX_PARTITION_DEPTH: return "HEVC Maximum Coding Unit Depth"; 9868c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_REFRESH_TYPE: return "HEVC Refresh Type"; 9878c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_CONST_INTRA_PRED: return "HEVC Constant Intra Prediction"; 9888c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_LOSSLESS_CU: return "HEVC Lossless Encoding"; 9898c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_WAVEFRONT: return "HEVC Wavefront"; 9908c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE: return "HEVC Loop Filter"; 9918c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_HIER_QP: return "HEVC QP Values"; 9928c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_TYPE: return "HEVC Hierarchical Coding Type"; 9938c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_LAYER: return "HEVC Hierarchical Coding Layer"; 9948c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L0_QP: return "HEVC Hierarchical Layer 0 QP"; 9958c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L1_QP: return "HEVC Hierarchical Layer 1 QP"; 9968c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L2_QP: return "HEVC Hierarchical Layer 2 QP"; 9978c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L3_QP: return "HEVC Hierarchical Layer 3 QP"; 9988c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L4_QP: return "HEVC Hierarchical Layer 4 QP"; 9998c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L5_QP: return "HEVC Hierarchical Layer 5 QP"; 10008c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L6_QP: return "HEVC Hierarchical Layer 6 QP"; 10018c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L0_BR: return "HEVC Hierarchical Lay 0 BitRate"; 10028c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L1_BR: return "HEVC Hierarchical Lay 1 BitRate"; 10038c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L2_BR: return "HEVC Hierarchical Lay 2 BitRate"; 10048c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L3_BR: return "HEVC Hierarchical Lay 3 BitRate"; 10058c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L4_BR: return "HEVC Hierarchical Lay 4 BitRate"; 10068c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L5_BR: return "HEVC Hierarchical Lay 5 BitRate"; 10078c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L6_BR: return "HEVC Hierarchical Lay 6 BitRate"; 10088c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_GENERAL_PB: return "HEVC General PB"; 10098c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_TEMPORAL_ID: return "HEVC Temporal ID"; 10108c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_STRONG_SMOOTHING: return "HEVC Strong Intra Smoothing"; 10118c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_INTRA_PU_SPLIT: return "HEVC Intra PU Split"; 10128c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_TMV_PREDICTION: return "HEVC TMV Prediction"; 10138c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_MAX_NUM_MERGE_MV_MINUS1: return "HEVC Max Num of Candidate MVs"; 10148c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_WITHOUT_STARTCODE: return "HEVC ENC Without Startcode"; 10158c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_REFRESH_PERIOD: return "HEVC Num of I-Frame b/w 2 IDR"; 10168c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_LF_BETA_OFFSET_DIV2: return "HEVC Loop Filter Beta Offset"; 10178c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_LF_TC_OFFSET_DIV2: return "HEVC Loop Filter TC Offset"; 10188c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_SIZE_OF_LENGTH_FIELD: return "HEVC Size of Length Field"; 10198c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_REF_NUMBER_FOR_PFRAMES: return "Reference Frames for a P-Frame"; 10208c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_PREPEND_SPSPPS_TO_IDR: return "Prepend SPS and PPS to IDR"; 10218c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_SPS: return "HEVC Sequence Parameter Set"; 10228c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_PPS: return "HEVC Picture Parameter Set"; 10238c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS: return "HEVC Slice Parameters"; 10248c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE: return "HEVC Decode Mode"; 10258c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_START_CODE: return "HEVC Start Code"; 10268c2ecf20Sopenharmony_ci 10278c2ecf20Sopenharmony_ci /* CAMERA controls */ 10288c2ecf20Sopenharmony_ci /* Keep the order of the 'case's the same as in v4l2-controls.h! */ 10298c2ecf20Sopenharmony_ci case V4L2_CID_CAMERA_CLASS: return "Camera Controls"; 10308c2ecf20Sopenharmony_ci case V4L2_CID_EXPOSURE_AUTO: return "Auto Exposure"; 10318c2ecf20Sopenharmony_ci case V4L2_CID_EXPOSURE_ABSOLUTE: return "Exposure Time, Absolute"; 10328c2ecf20Sopenharmony_ci case V4L2_CID_EXPOSURE_AUTO_PRIORITY: return "Exposure, Dynamic Framerate"; 10338c2ecf20Sopenharmony_ci case V4L2_CID_PAN_RELATIVE: return "Pan, Relative"; 10348c2ecf20Sopenharmony_ci case V4L2_CID_TILT_RELATIVE: return "Tilt, Relative"; 10358c2ecf20Sopenharmony_ci case V4L2_CID_PAN_RESET: return "Pan, Reset"; 10368c2ecf20Sopenharmony_ci case V4L2_CID_TILT_RESET: return "Tilt, Reset"; 10378c2ecf20Sopenharmony_ci case V4L2_CID_PAN_ABSOLUTE: return "Pan, Absolute"; 10388c2ecf20Sopenharmony_ci case V4L2_CID_TILT_ABSOLUTE: return "Tilt, Absolute"; 10398c2ecf20Sopenharmony_ci case V4L2_CID_FOCUS_ABSOLUTE: return "Focus, Absolute"; 10408c2ecf20Sopenharmony_ci case V4L2_CID_FOCUS_RELATIVE: return "Focus, Relative"; 10418c2ecf20Sopenharmony_ci case V4L2_CID_FOCUS_AUTO: return "Focus, Automatic Continuous"; 10428c2ecf20Sopenharmony_ci case V4L2_CID_ZOOM_ABSOLUTE: return "Zoom, Absolute"; 10438c2ecf20Sopenharmony_ci case V4L2_CID_ZOOM_RELATIVE: return "Zoom, Relative"; 10448c2ecf20Sopenharmony_ci case V4L2_CID_ZOOM_CONTINUOUS: return "Zoom, Continuous"; 10458c2ecf20Sopenharmony_ci case V4L2_CID_PRIVACY: return "Privacy"; 10468c2ecf20Sopenharmony_ci case V4L2_CID_IRIS_ABSOLUTE: return "Iris, Absolute"; 10478c2ecf20Sopenharmony_ci case V4L2_CID_IRIS_RELATIVE: return "Iris, Relative"; 10488c2ecf20Sopenharmony_ci case V4L2_CID_AUTO_EXPOSURE_BIAS: return "Auto Exposure, Bias"; 10498c2ecf20Sopenharmony_ci case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE: return "White Balance, Auto & Preset"; 10508c2ecf20Sopenharmony_ci case V4L2_CID_WIDE_DYNAMIC_RANGE: return "Wide Dynamic Range"; 10518c2ecf20Sopenharmony_ci case V4L2_CID_IMAGE_STABILIZATION: return "Image Stabilization"; 10528c2ecf20Sopenharmony_ci case V4L2_CID_ISO_SENSITIVITY: return "ISO Sensitivity"; 10538c2ecf20Sopenharmony_ci case V4L2_CID_ISO_SENSITIVITY_AUTO: return "ISO Sensitivity, Auto"; 10548c2ecf20Sopenharmony_ci case V4L2_CID_EXPOSURE_METERING: return "Exposure, Metering Mode"; 10558c2ecf20Sopenharmony_ci case V4L2_CID_SCENE_MODE: return "Scene Mode"; 10568c2ecf20Sopenharmony_ci case V4L2_CID_3A_LOCK: return "3A Lock"; 10578c2ecf20Sopenharmony_ci case V4L2_CID_AUTO_FOCUS_START: return "Auto Focus, Start"; 10588c2ecf20Sopenharmony_ci case V4L2_CID_AUTO_FOCUS_STOP: return "Auto Focus, Stop"; 10598c2ecf20Sopenharmony_ci case V4L2_CID_AUTO_FOCUS_STATUS: return "Auto Focus, Status"; 10608c2ecf20Sopenharmony_ci case V4L2_CID_AUTO_FOCUS_RANGE: return "Auto Focus, Range"; 10618c2ecf20Sopenharmony_ci case V4L2_CID_PAN_SPEED: return "Pan, Speed"; 10628c2ecf20Sopenharmony_ci case V4L2_CID_TILT_SPEED: return "Tilt, Speed"; 10638c2ecf20Sopenharmony_ci case V4L2_CID_UNIT_CELL_SIZE: return "Unit Cell Size"; 10648c2ecf20Sopenharmony_ci case V4L2_CID_CAMERA_ORIENTATION: return "Camera Orientation"; 10658c2ecf20Sopenharmony_ci case V4L2_CID_CAMERA_SENSOR_ROTATION: return "Camera Sensor Rotation"; 10668c2ecf20Sopenharmony_ci 10678c2ecf20Sopenharmony_ci /* FM Radio Modulator controls */ 10688c2ecf20Sopenharmony_ci /* Keep the order of the 'case's the same as in v4l2-controls.h! */ 10698c2ecf20Sopenharmony_ci case V4L2_CID_FM_TX_CLASS: return "FM Radio Modulator Controls"; 10708c2ecf20Sopenharmony_ci case V4L2_CID_RDS_TX_DEVIATION: return "RDS Signal Deviation"; 10718c2ecf20Sopenharmony_ci case V4L2_CID_RDS_TX_PI: return "RDS Program ID"; 10728c2ecf20Sopenharmony_ci case V4L2_CID_RDS_TX_PTY: return "RDS Program Type"; 10738c2ecf20Sopenharmony_ci case V4L2_CID_RDS_TX_PS_NAME: return "RDS PS Name"; 10748c2ecf20Sopenharmony_ci case V4L2_CID_RDS_TX_RADIO_TEXT: return "RDS Radio Text"; 10758c2ecf20Sopenharmony_ci case V4L2_CID_RDS_TX_MONO_STEREO: return "RDS Stereo"; 10768c2ecf20Sopenharmony_ci case V4L2_CID_RDS_TX_ARTIFICIAL_HEAD: return "RDS Artificial Head"; 10778c2ecf20Sopenharmony_ci case V4L2_CID_RDS_TX_COMPRESSED: return "RDS Compressed"; 10788c2ecf20Sopenharmony_ci case V4L2_CID_RDS_TX_DYNAMIC_PTY: return "RDS Dynamic PTY"; 10798c2ecf20Sopenharmony_ci case V4L2_CID_RDS_TX_TRAFFIC_ANNOUNCEMENT: return "RDS Traffic Announcement"; 10808c2ecf20Sopenharmony_ci case V4L2_CID_RDS_TX_TRAFFIC_PROGRAM: return "RDS Traffic Program"; 10818c2ecf20Sopenharmony_ci case V4L2_CID_RDS_TX_MUSIC_SPEECH: return "RDS Music"; 10828c2ecf20Sopenharmony_ci case V4L2_CID_RDS_TX_ALT_FREQS_ENABLE: return "RDS Enable Alt Frequencies"; 10838c2ecf20Sopenharmony_ci case V4L2_CID_RDS_TX_ALT_FREQS: return "RDS Alternate Frequencies"; 10848c2ecf20Sopenharmony_ci case V4L2_CID_AUDIO_LIMITER_ENABLED: return "Audio Limiter Feature Enabled"; 10858c2ecf20Sopenharmony_ci case V4L2_CID_AUDIO_LIMITER_RELEASE_TIME: return "Audio Limiter Release Time"; 10868c2ecf20Sopenharmony_ci case V4L2_CID_AUDIO_LIMITER_DEVIATION: return "Audio Limiter Deviation"; 10878c2ecf20Sopenharmony_ci case V4L2_CID_AUDIO_COMPRESSION_ENABLED: return "Audio Compression Enabled"; 10888c2ecf20Sopenharmony_ci case V4L2_CID_AUDIO_COMPRESSION_GAIN: return "Audio Compression Gain"; 10898c2ecf20Sopenharmony_ci case V4L2_CID_AUDIO_COMPRESSION_THRESHOLD: return "Audio Compression Threshold"; 10908c2ecf20Sopenharmony_ci case V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME: return "Audio Compression Attack Time"; 10918c2ecf20Sopenharmony_ci case V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME: return "Audio Compression Release Time"; 10928c2ecf20Sopenharmony_ci case V4L2_CID_PILOT_TONE_ENABLED: return "Pilot Tone Feature Enabled"; 10938c2ecf20Sopenharmony_ci case V4L2_CID_PILOT_TONE_DEVIATION: return "Pilot Tone Deviation"; 10948c2ecf20Sopenharmony_ci case V4L2_CID_PILOT_TONE_FREQUENCY: return "Pilot Tone Frequency"; 10958c2ecf20Sopenharmony_ci case V4L2_CID_TUNE_PREEMPHASIS: return "Pre-Emphasis"; 10968c2ecf20Sopenharmony_ci case V4L2_CID_TUNE_POWER_LEVEL: return "Tune Power Level"; 10978c2ecf20Sopenharmony_ci case V4L2_CID_TUNE_ANTENNA_CAPACITOR: return "Tune Antenna Capacitor"; 10988c2ecf20Sopenharmony_ci 10998c2ecf20Sopenharmony_ci /* Flash controls */ 11008c2ecf20Sopenharmony_ci /* Keep the order of the 'case's the same as in v4l2-controls.h! */ 11018c2ecf20Sopenharmony_ci case V4L2_CID_FLASH_CLASS: return "Flash Controls"; 11028c2ecf20Sopenharmony_ci case V4L2_CID_FLASH_LED_MODE: return "LED Mode"; 11038c2ecf20Sopenharmony_ci case V4L2_CID_FLASH_STROBE_SOURCE: return "Strobe Source"; 11048c2ecf20Sopenharmony_ci case V4L2_CID_FLASH_STROBE: return "Strobe"; 11058c2ecf20Sopenharmony_ci case V4L2_CID_FLASH_STROBE_STOP: return "Stop Strobe"; 11068c2ecf20Sopenharmony_ci case V4L2_CID_FLASH_STROBE_STATUS: return "Strobe Status"; 11078c2ecf20Sopenharmony_ci case V4L2_CID_FLASH_TIMEOUT: return "Strobe Timeout"; 11088c2ecf20Sopenharmony_ci case V4L2_CID_FLASH_INTENSITY: return "Intensity, Flash Mode"; 11098c2ecf20Sopenharmony_ci case V4L2_CID_FLASH_TORCH_INTENSITY: return "Intensity, Torch Mode"; 11108c2ecf20Sopenharmony_ci case V4L2_CID_FLASH_INDICATOR_INTENSITY: return "Intensity, Indicator"; 11118c2ecf20Sopenharmony_ci case V4L2_CID_FLASH_FAULT: return "Faults"; 11128c2ecf20Sopenharmony_ci case V4L2_CID_FLASH_CHARGE: return "Charge"; 11138c2ecf20Sopenharmony_ci case V4L2_CID_FLASH_READY: return "Ready to Strobe"; 11148c2ecf20Sopenharmony_ci 11158c2ecf20Sopenharmony_ci /* JPEG encoder controls */ 11168c2ecf20Sopenharmony_ci /* Keep the order of the 'case's the same as in v4l2-controls.h! */ 11178c2ecf20Sopenharmony_ci case V4L2_CID_JPEG_CLASS: return "JPEG Compression Controls"; 11188c2ecf20Sopenharmony_ci case V4L2_CID_JPEG_CHROMA_SUBSAMPLING: return "Chroma Subsampling"; 11198c2ecf20Sopenharmony_ci case V4L2_CID_JPEG_RESTART_INTERVAL: return "Restart Interval"; 11208c2ecf20Sopenharmony_ci case V4L2_CID_JPEG_COMPRESSION_QUALITY: return "Compression Quality"; 11218c2ecf20Sopenharmony_ci case V4L2_CID_JPEG_ACTIVE_MARKER: return "Active Markers"; 11228c2ecf20Sopenharmony_ci 11238c2ecf20Sopenharmony_ci /* Image source controls */ 11248c2ecf20Sopenharmony_ci /* Keep the order of the 'case's the same as in v4l2-controls.h! */ 11258c2ecf20Sopenharmony_ci case V4L2_CID_IMAGE_SOURCE_CLASS: return "Image Source Controls"; 11268c2ecf20Sopenharmony_ci case V4L2_CID_VBLANK: return "Vertical Blanking"; 11278c2ecf20Sopenharmony_ci case V4L2_CID_HBLANK: return "Horizontal Blanking"; 11288c2ecf20Sopenharmony_ci case V4L2_CID_ANALOGUE_GAIN: return "Analogue Gain"; 11298c2ecf20Sopenharmony_ci case V4L2_CID_TEST_PATTERN_RED: return "Red Pixel Value"; 11308c2ecf20Sopenharmony_ci case V4L2_CID_TEST_PATTERN_GREENR: return "Green (Red) Pixel Value"; 11318c2ecf20Sopenharmony_ci case V4L2_CID_TEST_PATTERN_BLUE: return "Blue Pixel Value"; 11328c2ecf20Sopenharmony_ci case V4L2_CID_TEST_PATTERN_GREENB: return "Green (Blue) Pixel Value"; 11338c2ecf20Sopenharmony_ci 11348c2ecf20Sopenharmony_ci /* Image processing controls */ 11358c2ecf20Sopenharmony_ci /* Keep the order of the 'case's the same as in v4l2-controls.h! */ 11368c2ecf20Sopenharmony_ci case V4L2_CID_IMAGE_PROC_CLASS: return "Image Processing Controls"; 11378c2ecf20Sopenharmony_ci case V4L2_CID_LINK_FREQ: return "Link Frequency"; 11388c2ecf20Sopenharmony_ci case V4L2_CID_PIXEL_RATE: return "Pixel Rate"; 11398c2ecf20Sopenharmony_ci case V4L2_CID_TEST_PATTERN: return "Test Pattern"; 11408c2ecf20Sopenharmony_ci case V4L2_CID_DEINTERLACING_MODE: return "Deinterlacing Mode"; 11418c2ecf20Sopenharmony_ci case V4L2_CID_DIGITAL_GAIN: return "Digital Gain"; 11428c2ecf20Sopenharmony_ci 11438c2ecf20Sopenharmony_ci /* DV controls */ 11448c2ecf20Sopenharmony_ci /* Keep the order of the 'case's the same as in v4l2-controls.h! */ 11458c2ecf20Sopenharmony_ci case V4L2_CID_DV_CLASS: return "Digital Video Controls"; 11468c2ecf20Sopenharmony_ci case V4L2_CID_DV_TX_HOTPLUG: return "Hotplug Present"; 11478c2ecf20Sopenharmony_ci case V4L2_CID_DV_TX_RXSENSE: return "RxSense Present"; 11488c2ecf20Sopenharmony_ci case V4L2_CID_DV_TX_EDID_PRESENT: return "EDID Present"; 11498c2ecf20Sopenharmony_ci case V4L2_CID_DV_TX_MODE: return "Transmit Mode"; 11508c2ecf20Sopenharmony_ci case V4L2_CID_DV_TX_RGB_RANGE: return "Tx RGB Quantization Range"; 11518c2ecf20Sopenharmony_ci case V4L2_CID_DV_TX_IT_CONTENT_TYPE: return "Tx IT Content Type"; 11528c2ecf20Sopenharmony_ci case V4L2_CID_DV_RX_POWER_PRESENT: return "Power Present"; 11538c2ecf20Sopenharmony_ci case V4L2_CID_DV_RX_RGB_RANGE: return "Rx RGB Quantization Range"; 11548c2ecf20Sopenharmony_ci case V4L2_CID_DV_RX_IT_CONTENT_TYPE: return "Rx IT Content Type"; 11558c2ecf20Sopenharmony_ci 11568c2ecf20Sopenharmony_ci case V4L2_CID_FM_RX_CLASS: return "FM Radio Receiver Controls"; 11578c2ecf20Sopenharmony_ci case V4L2_CID_TUNE_DEEMPHASIS: return "De-Emphasis"; 11588c2ecf20Sopenharmony_ci case V4L2_CID_RDS_RECEPTION: return "RDS Reception"; 11598c2ecf20Sopenharmony_ci case V4L2_CID_RF_TUNER_CLASS: return "RF Tuner Controls"; 11608c2ecf20Sopenharmony_ci case V4L2_CID_RF_TUNER_RF_GAIN: return "RF Gain"; 11618c2ecf20Sopenharmony_ci case V4L2_CID_RF_TUNER_LNA_GAIN_AUTO: return "LNA Gain, Auto"; 11628c2ecf20Sopenharmony_ci case V4L2_CID_RF_TUNER_LNA_GAIN: return "LNA Gain"; 11638c2ecf20Sopenharmony_ci case V4L2_CID_RF_TUNER_MIXER_GAIN_AUTO: return "Mixer Gain, Auto"; 11648c2ecf20Sopenharmony_ci case V4L2_CID_RF_TUNER_MIXER_GAIN: return "Mixer Gain"; 11658c2ecf20Sopenharmony_ci case V4L2_CID_RF_TUNER_IF_GAIN_AUTO: return "IF Gain, Auto"; 11668c2ecf20Sopenharmony_ci case V4L2_CID_RF_TUNER_IF_GAIN: return "IF Gain"; 11678c2ecf20Sopenharmony_ci case V4L2_CID_RF_TUNER_BANDWIDTH_AUTO: return "Bandwidth, Auto"; 11688c2ecf20Sopenharmony_ci case V4L2_CID_RF_TUNER_BANDWIDTH: return "Bandwidth"; 11698c2ecf20Sopenharmony_ci case V4L2_CID_RF_TUNER_PLL_LOCK: return "PLL Lock"; 11708c2ecf20Sopenharmony_ci case V4L2_CID_RDS_RX_PTY: return "RDS Program Type"; 11718c2ecf20Sopenharmony_ci case V4L2_CID_RDS_RX_PS_NAME: return "RDS PS Name"; 11728c2ecf20Sopenharmony_ci case V4L2_CID_RDS_RX_RADIO_TEXT: return "RDS Radio Text"; 11738c2ecf20Sopenharmony_ci case V4L2_CID_RDS_RX_TRAFFIC_ANNOUNCEMENT: return "RDS Traffic Announcement"; 11748c2ecf20Sopenharmony_ci case V4L2_CID_RDS_RX_TRAFFIC_PROGRAM: return "RDS Traffic Program"; 11758c2ecf20Sopenharmony_ci case V4L2_CID_RDS_RX_MUSIC_SPEECH: return "RDS Music"; 11768c2ecf20Sopenharmony_ci 11778c2ecf20Sopenharmony_ci /* Detection controls */ 11788c2ecf20Sopenharmony_ci /* Keep the order of the 'case's the same as in v4l2-controls.h! */ 11798c2ecf20Sopenharmony_ci case V4L2_CID_DETECT_CLASS: return "Detection Controls"; 11808c2ecf20Sopenharmony_ci case V4L2_CID_DETECT_MD_MODE: return "Motion Detection Mode"; 11818c2ecf20Sopenharmony_ci case V4L2_CID_DETECT_MD_GLOBAL_THRESHOLD: return "MD Global Threshold"; 11828c2ecf20Sopenharmony_ci case V4L2_CID_DETECT_MD_THRESHOLD_GRID: return "MD Threshold Grid"; 11838c2ecf20Sopenharmony_ci case V4L2_CID_DETECT_MD_REGION_GRID: return "MD Region Grid"; 11848c2ecf20Sopenharmony_ci default: 11858c2ecf20Sopenharmony_ci return NULL; 11868c2ecf20Sopenharmony_ci } 11878c2ecf20Sopenharmony_ci} 11888c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_get_name); 11898c2ecf20Sopenharmony_ci 11908c2ecf20Sopenharmony_civoid v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, 11918c2ecf20Sopenharmony_ci s64 *min, s64 *max, u64 *step, s64 *def, u32 *flags) 11928c2ecf20Sopenharmony_ci{ 11938c2ecf20Sopenharmony_ci *name = v4l2_ctrl_get_name(id); 11948c2ecf20Sopenharmony_ci *flags = 0; 11958c2ecf20Sopenharmony_ci 11968c2ecf20Sopenharmony_ci switch (id) { 11978c2ecf20Sopenharmony_ci case V4L2_CID_AUDIO_MUTE: 11988c2ecf20Sopenharmony_ci case V4L2_CID_AUDIO_LOUDNESS: 11998c2ecf20Sopenharmony_ci case V4L2_CID_AUTO_WHITE_BALANCE: 12008c2ecf20Sopenharmony_ci case V4L2_CID_AUTOGAIN: 12018c2ecf20Sopenharmony_ci case V4L2_CID_HFLIP: 12028c2ecf20Sopenharmony_ci case V4L2_CID_VFLIP: 12038c2ecf20Sopenharmony_ci case V4L2_CID_HUE_AUTO: 12048c2ecf20Sopenharmony_ci case V4L2_CID_CHROMA_AGC: 12058c2ecf20Sopenharmony_ci case V4L2_CID_COLOR_KILLER: 12068c2ecf20Sopenharmony_ci case V4L2_CID_AUTOBRIGHTNESS: 12078c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_AUDIO_MUTE: 12088c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_MUTE: 12098c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: 12108c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_PULLDOWN: 12118c2ecf20Sopenharmony_ci case V4L2_CID_EXPOSURE_AUTO_PRIORITY: 12128c2ecf20Sopenharmony_ci case V4L2_CID_FOCUS_AUTO: 12138c2ecf20Sopenharmony_ci case V4L2_CID_PRIVACY: 12148c2ecf20Sopenharmony_ci case V4L2_CID_AUDIO_LIMITER_ENABLED: 12158c2ecf20Sopenharmony_ci case V4L2_CID_AUDIO_COMPRESSION_ENABLED: 12168c2ecf20Sopenharmony_ci case V4L2_CID_PILOT_TONE_ENABLED: 12178c2ecf20Sopenharmony_ci case V4L2_CID_ILLUMINATORS_1: 12188c2ecf20Sopenharmony_ci case V4L2_CID_ILLUMINATORS_2: 12198c2ecf20Sopenharmony_ci case V4L2_CID_FLASH_STROBE_STATUS: 12208c2ecf20Sopenharmony_ci case V4L2_CID_FLASH_CHARGE: 12218c2ecf20Sopenharmony_ci case V4L2_CID_FLASH_READY: 12228c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER: 12238c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE: 12248c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE: 12258c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE: 12268c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM: 12278c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE: 12288c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_MPEG4_QPEL: 12298c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER: 12308c2ecf20Sopenharmony_ci case V4L2_CID_WIDE_DYNAMIC_RANGE: 12318c2ecf20Sopenharmony_ci case V4L2_CID_IMAGE_STABILIZATION: 12328c2ecf20Sopenharmony_ci case V4L2_CID_RDS_RECEPTION: 12338c2ecf20Sopenharmony_ci case V4L2_CID_RF_TUNER_LNA_GAIN_AUTO: 12348c2ecf20Sopenharmony_ci case V4L2_CID_RF_TUNER_MIXER_GAIN_AUTO: 12358c2ecf20Sopenharmony_ci case V4L2_CID_RF_TUNER_IF_GAIN_AUTO: 12368c2ecf20Sopenharmony_ci case V4L2_CID_RF_TUNER_BANDWIDTH_AUTO: 12378c2ecf20Sopenharmony_ci case V4L2_CID_RF_TUNER_PLL_LOCK: 12388c2ecf20Sopenharmony_ci case V4L2_CID_RDS_TX_MONO_STEREO: 12398c2ecf20Sopenharmony_ci case V4L2_CID_RDS_TX_ARTIFICIAL_HEAD: 12408c2ecf20Sopenharmony_ci case V4L2_CID_RDS_TX_COMPRESSED: 12418c2ecf20Sopenharmony_ci case V4L2_CID_RDS_TX_DYNAMIC_PTY: 12428c2ecf20Sopenharmony_ci case V4L2_CID_RDS_TX_TRAFFIC_ANNOUNCEMENT: 12438c2ecf20Sopenharmony_ci case V4L2_CID_RDS_TX_TRAFFIC_PROGRAM: 12448c2ecf20Sopenharmony_ci case V4L2_CID_RDS_TX_MUSIC_SPEECH: 12458c2ecf20Sopenharmony_ci case V4L2_CID_RDS_TX_ALT_FREQS_ENABLE: 12468c2ecf20Sopenharmony_ci case V4L2_CID_RDS_RX_TRAFFIC_ANNOUNCEMENT: 12478c2ecf20Sopenharmony_ci case V4L2_CID_RDS_RX_TRAFFIC_PROGRAM: 12488c2ecf20Sopenharmony_ci case V4L2_CID_RDS_RX_MUSIC_SPEECH: 12498c2ecf20Sopenharmony_ci *type = V4L2_CTRL_TYPE_BOOLEAN; 12508c2ecf20Sopenharmony_ci *min = 0; 12518c2ecf20Sopenharmony_ci *max = *step = 1; 12528c2ecf20Sopenharmony_ci break; 12538c2ecf20Sopenharmony_ci case V4L2_CID_ROTATE: 12548c2ecf20Sopenharmony_ci *type = V4L2_CTRL_TYPE_INTEGER; 12558c2ecf20Sopenharmony_ci *flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT; 12568c2ecf20Sopenharmony_ci break; 12578c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_MV_H_SEARCH_RANGE: 12588c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_MV_V_SEARCH_RANGE: 12598c2ecf20Sopenharmony_ci *type = V4L2_CTRL_TYPE_INTEGER; 12608c2ecf20Sopenharmony_ci break; 12618c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME: 12628c2ecf20Sopenharmony_ci case V4L2_CID_PAN_RESET: 12638c2ecf20Sopenharmony_ci case V4L2_CID_TILT_RESET: 12648c2ecf20Sopenharmony_ci case V4L2_CID_FLASH_STROBE: 12658c2ecf20Sopenharmony_ci case V4L2_CID_FLASH_STROBE_STOP: 12668c2ecf20Sopenharmony_ci case V4L2_CID_AUTO_FOCUS_START: 12678c2ecf20Sopenharmony_ci case V4L2_CID_AUTO_FOCUS_STOP: 12688c2ecf20Sopenharmony_ci case V4L2_CID_DO_WHITE_BALANCE: 12698c2ecf20Sopenharmony_ci *type = V4L2_CTRL_TYPE_BUTTON; 12708c2ecf20Sopenharmony_ci *flags |= V4L2_CTRL_FLAG_WRITE_ONLY | 12718c2ecf20Sopenharmony_ci V4L2_CTRL_FLAG_EXECUTE_ON_WRITE; 12728c2ecf20Sopenharmony_ci *min = *max = *step = *def = 0; 12738c2ecf20Sopenharmony_ci break; 12748c2ecf20Sopenharmony_ci case V4L2_CID_POWER_LINE_FREQUENCY: 12758c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: 12768c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_AUDIO_ENCODING: 12778c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_AUDIO_L1_BITRATE: 12788c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_AUDIO_L2_BITRATE: 12798c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_AUDIO_L3_BITRATE: 12808c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: 12818c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_AUDIO_MODE: 12828c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: 12838c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_AUDIO_EMPHASIS: 12848c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_AUDIO_CRC: 12858c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK: 12868c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_AUDIO_DEC_MULTILINGUAL_PLAYBACK: 12878c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_ENCODING: 12888c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_ASPECT: 12898c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: 12908c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_STREAM_TYPE: 12918c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_STREAM_VBI_FMT: 12928c2ecf20Sopenharmony_ci case V4L2_CID_EXPOSURE_AUTO: 12938c2ecf20Sopenharmony_ci case V4L2_CID_AUTO_FOCUS_RANGE: 12948c2ecf20Sopenharmony_ci case V4L2_CID_COLORFX: 12958c2ecf20Sopenharmony_ci case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE: 12968c2ecf20Sopenharmony_ci case V4L2_CID_TUNE_PREEMPHASIS: 12978c2ecf20Sopenharmony_ci case V4L2_CID_FLASH_LED_MODE: 12988c2ecf20Sopenharmony_ci case V4L2_CID_FLASH_STROBE_SOURCE: 12998c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEADER_MODE: 13008c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_FRAME_SKIP_MODE: 13018c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE: 13028c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE: 13038c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_LEVEL: 13048c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE: 13058c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_PROFILE: 13068c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC: 13078c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE: 13088c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_FMO_MAP_TYPE: 13098c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_DECODE_MODE: 13108c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_START_CODE: 13118c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_MPEG2_LEVEL: 13128c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_MPEG2_PROFILE: 13138c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL: 13148c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE: 13158c2ecf20Sopenharmony_ci case V4L2_CID_JPEG_CHROMA_SUBSAMPLING: 13168c2ecf20Sopenharmony_ci case V4L2_CID_ISO_SENSITIVITY_AUTO: 13178c2ecf20Sopenharmony_ci case V4L2_CID_EXPOSURE_METERING: 13188c2ecf20Sopenharmony_ci case V4L2_CID_SCENE_MODE: 13198c2ecf20Sopenharmony_ci case V4L2_CID_DV_TX_MODE: 13208c2ecf20Sopenharmony_ci case V4L2_CID_DV_TX_RGB_RANGE: 13218c2ecf20Sopenharmony_ci case V4L2_CID_DV_TX_IT_CONTENT_TYPE: 13228c2ecf20Sopenharmony_ci case V4L2_CID_DV_RX_RGB_RANGE: 13238c2ecf20Sopenharmony_ci case V4L2_CID_DV_RX_IT_CONTENT_TYPE: 13248c2ecf20Sopenharmony_ci case V4L2_CID_TEST_PATTERN: 13258c2ecf20Sopenharmony_ci case V4L2_CID_DEINTERLACING_MODE: 13268c2ecf20Sopenharmony_ci case V4L2_CID_TUNE_DEEMPHASIS: 13278c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_SEL: 13288c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_VP8_PROFILE: 13298c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_VP9_PROFILE: 13308c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_VP9_LEVEL: 13318c2ecf20Sopenharmony_ci case V4L2_CID_DETECT_MD_MODE: 13328c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_PROFILE: 13338c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_LEVEL: 13348c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_TYPE: 13358c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_REFRESH_TYPE: 13368c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_SIZE_OF_LENGTH_FIELD: 13378c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_TIER: 13388c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE: 13398c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE: 13408c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_START_CODE: 13418c2ecf20Sopenharmony_ci case V4L2_CID_CAMERA_ORIENTATION: 13428c2ecf20Sopenharmony_ci *type = V4L2_CTRL_TYPE_MENU; 13438c2ecf20Sopenharmony_ci break; 13448c2ecf20Sopenharmony_ci case V4L2_CID_LINK_FREQ: 13458c2ecf20Sopenharmony_ci *type = V4L2_CTRL_TYPE_INTEGER_MENU; 13468c2ecf20Sopenharmony_ci break; 13478c2ecf20Sopenharmony_ci case V4L2_CID_RDS_TX_PS_NAME: 13488c2ecf20Sopenharmony_ci case V4L2_CID_RDS_TX_RADIO_TEXT: 13498c2ecf20Sopenharmony_ci case V4L2_CID_RDS_RX_PS_NAME: 13508c2ecf20Sopenharmony_ci case V4L2_CID_RDS_RX_RADIO_TEXT: 13518c2ecf20Sopenharmony_ci *type = V4L2_CTRL_TYPE_STRING; 13528c2ecf20Sopenharmony_ci break; 13538c2ecf20Sopenharmony_ci case V4L2_CID_ISO_SENSITIVITY: 13548c2ecf20Sopenharmony_ci case V4L2_CID_AUTO_EXPOSURE_BIAS: 13558c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_VPX_NUM_PARTITIONS: 13568c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_VPX_NUM_REF_FRAMES: 13578c2ecf20Sopenharmony_ci *type = V4L2_CTRL_TYPE_INTEGER_MENU; 13588c2ecf20Sopenharmony_ci break; 13598c2ecf20Sopenharmony_ci case V4L2_CID_USER_CLASS: 13608c2ecf20Sopenharmony_ci case V4L2_CID_CAMERA_CLASS: 13618c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_CLASS: 13628c2ecf20Sopenharmony_ci case V4L2_CID_FM_TX_CLASS: 13638c2ecf20Sopenharmony_ci case V4L2_CID_FLASH_CLASS: 13648c2ecf20Sopenharmony_ci case V4L2_CID_JPEG_CLASS: 13658c2ecf20Sopenharmony_ci case V4L2_CID_IMAGE_SOURCE_CLASS: 13668c2ecf20Sopenharmony_ci case V4L2_CID_IMAGE_PROC_CLASS: 13678c2ecf20Sopenharmony_ci case V4L2_CID_DV_CLASS: 13688c2ecf20Sopenharmony_ci case V4L2_CID_FM_RX_CLASS: 13698c2ecf20Sopenharmony_ci case V4L2_CID_RF_TUNER_CLASS: 13708c2ecf20Sopenharmony_ci case V4L2_CID_DETECT_CLASS: 13718c2ecf20Sopenharmony_ci *type = V4L2_CTRL_TYPE_CTRL_CLASS; 13728c2ecf20Sopenharmony_ci /* You can neither read not write these */ 13738c2ecf20Sopenharmony_ci *flags |= V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_WRITE_ONLY; 13748c2ecf20Sopenharmony_ci *min = *max = *step = *def = 0; 13758c2ecf20Sopenharmony_ci break; 13768c2ecf20Sopenharmony_ci case V4L2_CID_BG_COLOR: 13778c2ecf20Sopenharmony_ci *type = V4L2_CTRL_TYPE_INTEGER; 13788c2ecf20Sopenharmony_ci *step = 1; 13798c2ecf20Sopenharmony_ci *min = 0; 13808c2ecf20Sopenharmony_ci /* Max is calculated as RGB888 that is 2^24 */ 13818c2ecf20Sopenharmony_ci *max = 0xFFFFFF; 13828c2ecf20Sopenharmony_ci break; 13838c2ecf20Sopenharmony_ci case V4L2_CID_FLASH_FAULT: 13848c2ecf20Sopenharmony_ci case V4L2_CID_JPEG_ACTIVE_MARKER: 13858c2ecf20Sopenharmony_ci case V4L2_CID_3A_LOCK: 13868c2ecf20Sopenharmony_ci case V4L2_CID_AUTO_FOCUS_STATUS: 13878c2ecf20Sopenharmony_ci case V4L2_CID_DV_TX_HOTPLUG: 13888c2ecf20Sopenharmony_ci case V4L2_CID_DV_TX_RXSENSE: 13898c2ecf20Sopenharmony_ci case V4L2_CID_DV_TX_EDID_PRESENT: 13908c2ecf20Sopenharmony_ci case V4L2_CID_DV_RX_POWER_PRESENT: 13918c2ecf20Sopenharmony_ci *type = V4L2_CTRL_TYPE_BITMASK; 13928c2ecf20Sopenharmony_ci break; 13938c2ecf20Sopenharmony_ci case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: 13948c2ecf20Sopenharmony_ci case V4L2_CID_MIN_BUFFERS_FOR_OUTPUT: 13958c2ecf20Sopenharmony_ci *type = V4L2_CTRL_TYPE_INTEGER; 13968c2ecf20Sopenharmony_ci *flags |= V4L2_CTRL_FLAG_READ_ONLY; 13978c2ecf20Sopenharmony_ci break; 13988c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_DEC_PTS: 13998c2ecf20Sopenharmony_ci *type = V4L2_CTRL_TYPE_INTEGER64; 14008c2ecf20Sopenharmony_ci *flags |= V4L2_CTRL_FLAG_VOLATILE | V4L2_CTRL_FLAG_READ_ONLY; 14018c2ecf20Sopenharmony_ci *min = *def = 0; 14028c2ecf20Sopenharmony_ci *max = 0x1ffffffffLL; 14038c2ecf20Sopenharmony_ci *step = 1; 14048c2ecf20Sopenharmony_ci break; 14058c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_DEC_FRAME: 14068c2ecf20Sopenharmony_ci *type = V4L2_CTRL_TYPE_INTEGER64; 14078c2ecf20Sopenharmony_ci *flags |= V4L2_CTRL_FLAG_VOLATILE | V4L2_CTRL_FLAG_READ_ONLY; 14088c2ecf20Sopenharmony_ci *min = *def = 0; 14098c2ecf20Sopenharmony_ci *max = 0x7fffffffffffffffLL; 14108c2ecf20Sopenharmony_ci *step = 1; 14118c2ecf20Sopenharmony_ci break; 14128c2ecf20Sopenharmony_ci case V4L2_CID_PIXEL_RATE: 14138c2ecf20Sopenharmony_ci *type = V4L2_CTRL_TYPE_INTEGER64; 14148c2ecf20Sopenharmony_ci *flags |= V4L2_CTRL_FLAG_READ_ONLY; 14158c2ecf20Sopenharmony_ci break; 14168c2ecf20Sopenharmony_ci case V4L2_CID_DETECT_MD_REGION_GRID: 14178c2ecf20Sopenharmony_ci *type = V4L2_CTRL_TYPE_U8; 14188c2ecf20Sopenharmony_ci break; 14198c2ecf20Sopenharmony_ci case V4L2_CID_DETECT_MD_THRESHOLD_GRID: 14208c2ecf20Sopenharmony_ci *type = V4L2_CTRL_TYPE_U16; 14218c2ecf20Sopenharmony_ci break; 14228c2ecf20Sopenharmony_ci case V4L2_CID_RDS_TX_ALT_FREQS: 14238c2ecf20Sopenharmony_ci *type = V4L2_CTRL_TYPE_U32; 14248c2ecf20Sopenharmony_ci break; 14258c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_MPEG2_SLICE_PARAMS: 14268c2ecf20Sopenharmony_ci *type = V4L2_CTRL_TYPE_MPEG2_SLICE_PARAMS; 14278c2ecf20Sopenharmony_ci break; 14288c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_MPEG2_QUANTIZATION: 14298c2ecf20Sopenharmony_ci *type = V4L2_CTRL_TYPE_MPEG2_QUANTIZATION; 14308c2ecf20Sopenharmony_ci break; 14318c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_FWHT_PARAMS: 14328c2ecf20Sopenharmony_ci *type = V4L2_CTRL_TYPE_FWHT_PARAMS; 14338c2ecf20Sopenharmony_ci break; 14348c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_SPS: 14358c2ecf20Sopenharmony_ci *type = V4L2_CTRL_TYPE_H264_SPS; 14368c2ecf20Sopenharmony_ci break; 14378c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_PPS: 14388c2ecf20Sopenharmony_ci *type = V4L2_CTRL_TYPE_H264_PPS; 14398c2ecf20Sopenharmony_ci break; 14408c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX: 14418c2ecf20Sopenharmony_ci *type = V4L2_CTRL_TYPE_H264_SCALING_MATRIX; 14428c2ecf20Sopenharmony_ci break; 14438c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAMS: 14448c2ecf20Sopenharmony_ci *type = V4L2_CTRL_TYPE_H264_SLICE_PARAMS; 14458c2ecf20Sopenharmony_ci break; 14468c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS: 14478c2ecf20Sopenharmony_ci *type = V4L2_CTRL_TYPE_H264_DECODE_PARAMS; 14488c2ecf20Sopenharmony_ci break; 14498c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_H264_PRED_WEIGHTS: 14508c2ecf20Sopenharmony_ci *type = V4L2_CTRL_TYPE_H264_PRED_WEIGHTS; 14518c2ecf20Sopenharmony_ci break; 14528c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER: 14538c2ecf20Sopenharmony_ci *type = V4L2_CTRL_TYPE_VP8_FRAME_HEADER; 14548c2ecf20Sopenharmony_ci break; 14558c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_SPS: 14568c2ecf20Sopenharmony_ci *type = V4L2_CTRL_TYPE_HEVC_SPS; 14578c2ecf20Sopenharmony_ci break; 14588c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_PPS: 14598c2ecf20Sopenharmony_ci *type = V4L2_CTRL_TYPE_HEVC_PPS; 14608c2ecf20Sopenharmony_ci break; 14618c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS: 14628c2ecf20Sopenharmony_ci *type = V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS; 14638c2ecf20Sopenharmony_ci break; 14648c2ecf20Sopenharmony_ci case V4L2_CID_UNIT_CELL_SIZE: 14658c2ecf20Sopenharmony_ci *type = V4L2_CTRL_TYPE_AREA; 14668c2ecf20Sopenharmony_ci *flags |= V4L2_CTRL_FLAG_READ_ONLY; 14678c2ecf20Sopenharmony_ci break; 14688c2ecf20Sopenharmony_ci default: 14698c2ecf20Sopenharmony_ci *type = V4L2_CTRL_TYPE_INTEGER; 14708c2ecf20Sopenharmony_ci break; 14718c2ecf20Sopenharmony_ci } 14728c2ecf20Sopenharmony_ci switch (id) { 14738c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_AUDIO_ENCODING: 14748c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_AUDIO_MODE: 14758c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: 14768c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_VIDEO_B_FRAMES: 14778c2ecf20Sopenharmony_ci case V4L2_CID_MPEG_STREAM_TYPE: 14788c2ecf20Sopenharmony_ci *flags |= V4L2_CTRL_FLAG_UPDATE; 14798c2ecf20Sopenharmony_ci break; 14808c2ecf20Sopenharmony_ci case V4L2_CID_AUDIO_VOLUME: 14818c2ecf20Sopenharmony_ci case V4L2_CID_AUDIO_BALANCE: 14828c2ecf20Sopenharmony_ci case V4L2_CID_AUDIO_BASS: 14838c2ecf20Sopenharmony_ci case V4L2_CID_AUDIO_TREBLE: 14848c2ecf20Sopenharmony_ci case V4L2_CID_BRIGHTNESS: 14858c2ecf20Sopenharmony_ci case V4L2_CID_CONTRAST: 14868c2ecf20Sopenharmony_ci case V4L2_CID_SATURATION: 14878c2ecf20Sopenharmony_ci case V4L2_CID_HUE: 14888c2ecf20Sopenharmony_ci case V4L2_CID_RED_BALANCE: 14898c2ecf20Sopenharmony_ci case V4L2_CID_BLUE_BALANCE: 14908c2ecf20Sopenharmony_ci case V4L2_CID_GAMMA: 14918c2ecf20Sopenharmony_ci case V4L2_CID_SHARPNESS: 14928c2ecf20Sopenharmony_ci case V4L2_CID_CHROMA_GAIN: 14938c2ecf20Sopenharmony_ci case V4L2_CID_RDS_TX_DEVIATION: 14948c2ecf20Sopenharmony_ci case V4L2_CID_AUDIO_LIMITER_RELEASE_TIME: 14958c2ecf20Sopenharmony_ci case V4L2_CID_AUDIO_LIMITER_DEVIATION: 14968c2ecf20Sopenharmony_ci case V4L2_CID_AUDIO_COMPRESSION_GAIN: 14978c2ecf20Sopenharmony_ci case V4L2_CID_AUDIO_COMPRESSION_THRESHOLD: 14988c2ecf20Sopenharmony_ci case V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME: 14998c2ecf20Sopenharmony_ci case V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME: 15008c2ecf20Sopenharmony_ci case V4L2_CID_PILOT_TONE_DEVIATION: 15018c2ecf20Sopenharmony_ci case V4L2_CID_PILOT_TONE_FREQUENCY: 15028c2ecf20Sopenharmony_ci case V4L2_CID_TUNE_POWER_LEVEL: 15038c2ecf20Sopenharmony_ci case V4L2_CID_TUNE_ANTENNA_CAPACITOR: 15048c2ecf20Sopenharmony_ci case V4L2_CID_RF_TUNER_RF_GAIN: 15058c2ecf20Sopenharmony_ci case V4L2_CID_RF_TUNER_LNA_GAIN: 15068c2ecf20Sopenharmony_ci case V4L2_CID_RF_TUNER_MIXER_GAIN: 15078c2ecf20Sopenharmony_ci case V4L2_CID_RF_TUNER_IF_GAIN: 15088c2ecf20Sopenharmony_ci case V4L2_CID_RF_TUNER_BANDWIDTH: 15098c2ecf20Sopenharmony_ci case V4L2_CID_DETECT_MD_GLOBAL_THRESHOLD: 15108c2ecf20Sopenharmony_ci *flags |= V4L2_CTRL_FLAG_SLIDER; 15118c2ecf20Sopenharmony_ci break; 15128c2ecf20Sopenharmony_ci case V4L2_CID_PAN_RELATIVE: 15138c2ecf20Sopenharmony_ci case V4L2_CID_TILT_RELATIVE: 15148c2ecf20Sopenharmony_ci case V4L2_CID_FOCUS_RELATIVE: 15158c2ecf20Sopenharmony_ci case V4L2_CID_IRIS_RELATIVE: 15168c2ecf20Sopenharmony_ci case V4L2_CID_ZOOM_RELATIVE: 15178c2ecf20Sopenharmony_ci *flags |= V4L2_CTRL_FLAG_WRITE_ONLY | 15188c2ecf20Sopenharmony_ci V4L2_CTRL_FLAG_EXECUTE_ON_WRITE; 15198c2ecf20Sopenharmony_ci break; 15208c2ecf20Sopenharmony_ci case V4L2_CID_FLASH_STROBE_STATUS: 15218c2ecf20Sopenharmony_ci case V4L2_CID_AUTO_FOCUS_STATUS: 15228c2ecf20Sopenharmony_ci case V4L2_CID_FLASH_READY: 15238c2ecf20Sopenharmony_ci case V4L2_CID_DV_TX_HOTPLUG: 15248c2ecf20Sopenharmony_ci case V4L2_CID_DV_TX_RXSENSE: 15258c2ecf20Sopenharmony_ci case V4L2_CID_DV_TX_EDID_PRESENT: 15268c2ecf20Sopenharmony_ci case V4L2_CID_DV_RX_POWER_PRESENT: 15278c2ecf20Sopenharmony_ci case V4L2_CID_DV_RX_IT_CONTENT_TYPE: 15288c2ecf20Sopenharmony_ci case V4L2_CID_RDS_RX_PTY: 15298c2ecf20Sopenharmony_ci case V4L2_CID_RDS_RX_PS_NAME: 15308c2ecf20Sopenharmony_ci case V4L2_CID_RDS_RX_RADIO_TEXT: 15318c2ecf20Sopenharmony_ci case V4L2_CID_RDS_RX_TRAFFIC_ANNOUNCEMENT: 15328c2ecf20Sopenharmony_ci case V4L2_CID_RDS_RX_TRAFFIC_PROGRAM: 15338c2ecf20Sopenharmony_ci case V4L2_CID_RDS_RX_MUSIC_SPEECH: 15348c2ecf20Sopenharmony_ci case V4L2_CID_CAMERA_ORIENTATION: 15358c2ecf20Sopenharmony_ci case V4L2_CID_CAMERA_SENSOR_ROTATION: 15368c2ecf20Sopenharmony_ci *flags |= V4L2_CTRL_FLAG_READ_ONLY; 15378c2ecf20Sopenharmony_ci break; 15388c2ecf20Sopenharmony_ci case V4L2_CID_RF_TUNER_PLL_LOCK: 15398c2ecf20Sopenharmony_ci *flags |= V4L2_CTRL_FLAG_VOLATILE; 15408c2ecf20Sopenharmony_ci break; 15418c2ecf20Sopenharmony_ci } 15428c2ecf20Sopenharmony_ci} 15438c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_fill); 15448c2ecf20Sopenharmony_ci 15458c2ecf20Sopenharmony_cistatic u32 user_flags(const struct v4l2_ctrl *ctrl) 15468c2ecf20Sopenharmony_ci{ 15478c2ecf20Sopenharmony_ci u32 flags = ctrl->flags; 15488c2ecf20Sopenharmony_ci 15498c2ecf20Sopenharmony_ci if (ctrl->is_ptr) 15508c2ecf20Sopenharmony_ci flags |= V4L2_CTRL_FLAG_HAS_PAYLOAD; 15518c2ecf20Sopenharmony_ci 15528c2ecf20Sopenharmony_ci return flags; 15538c2ecf20Sopenharmony_ci} 15548c2ecf20Sopenharmony_ci 15558c2ecf20Sopenharmony_cistatic void fill_event(struct v4l2_event *ev, struct v4l2_ctrl *ctrl, u32 changes) 15568c2ecf20Sopenharmony_ci{ 15578c2ecf20Sopenharmony_ci memset(ev, 0, sizeof(*ev)); 15588c2ecf20Sopenharmony_ci ev->type = V4L2_EVENT_CTRL; 15598c2ecf20Sopenharmony_ci ev->id = ctrl->id; 15608c2ecf20Sopenharmony_ci ev->u.ctrl.changes = changes; 15618c2ecf20Sopenharmony_ci ev->u.ctrl.type = ctrl->type; 15628c2ecf20Sopenharmony_ci ev->u.ctrl.flags = user_flags(ctrl); 15638c2ecf20Sopenharmony_ci if (ctrl->is_ptr) 15648c2ecf20Sopenharmony_ci ev->u.ctrl.value64 = 0; 15658c2ecf20Sopenharmony_ci else 15668c2ecf20Sopenharmony_ci ev->u.ctrl.value64 = *ctrl->p_cur.p_s64; 15678c2ecf20Sopenharmony_ci ev->u.ctrl.minimum = ctrl->minimum; 15688c2ecf20Sopenharmony_ci ev->u.ctrl.maximum = ctrl->maximum; 15698c2ecf20Sopenharmony_ci if (ctrl->type == V4L2_CTRL_TYPE_MENU 15708c2ecf20Sopenharmony_ci || ctrl->type == V4L2_CTRL_TYPE_INTEGER_MENU) 15718c2ecf20Sopenharmony_ci ev->u.ctrl.step = 1; 15728c2ecf20Sopenharmony_ci else 15738c2ecf20Sopenharmony_ci ev->u.ctrl.step = ctrl->step; 15748c2ecf20Sopenharmony_ci ev->u.ctrl.default_value = ctrl->default_value; 15758c2ecf20Sopenharmony_ci} 15768c2ecf20Sopenharmony_ci 15778c2ecf20Sopenharmony_cistatic void send_event(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, u32 changes) 15788c2ecf20Sopenharmony_ci{ 15798c2ecf20Sopenharmony_ci struct v4l2_event ev; 15808c2ecf20Sopenharmony_ci struct v4l2_subscribed_event *sev; 15818c2ecf20Sopenharmony_ci 15828c2ecf20Sopenharmony_ci if (list_empty(&ctrl->ev_subs)) 15838c2ecf20Sopenharmony_ci return; 15848c2ecf20Sopenharmony_ci fill_event(&ev, ctrl, changes); 15858c2ecf20Sopenharmony_ci 15868c2ecf20Sopenharmony_ci list_for_each_entry(sev, &ctrl->ev_subs, node) 15878c2ecf20Sopenharmony_ci if (sev->fh != fh || 15888c2ecf20Sopenharmony_ci (sev->flags & V4L2_EVENT_SUB_FL_ALLOW_FEEDBACK)) 15898c2ecf20Sopenharmony_ci v4l2_event_queue_fh(sev->fh, &ev); 15908c2ecf20Sopenharmony_ci} 15918c2ecf20Sopenharmony_ci 15928c2ecf20Sopenharmony_cistatic bool std_equal(const struct v4l2_ctrl *ctrl, u32 idx, 15938c2ecf20Sopenharmony_ci union v4l2_ctrl_ptr ptr1, 15948c2ecf20Sopenharmony_ci union v4l2_ctrl_ptr ptr2) 15958c2ecf20Sopenharmony_ci{ 15968c2ecf20Sopenharmony_ci switch (ctrl->type) { 15978c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_BUTTON: 15988c2ecf20Sopenharmony_ci return false; 15998c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_STRING: 16008c2ecf20Sopenharmony_ci idx *= ctrl->elem_size; 16018c2ecf20Sopenharmony_ci /* strings are always 0-terminated */ 16028c2ecf20Sopenharmony_ci return !strcmp(ptr1.p_char + idx, ptr2.p_char + idx); 16038c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_INTEGER64: 16048c2ecf20Sopenharmony_ci return ptr1.p_s64[idx] == ptr2.p_s64[idx]; 16058c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_U8: 16068c2ecf20Sopenharmony_ci return ptr1.p_u8[idx] == ptr2.p_u8[idx]; 16078c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_U16: 16088c2ecf20Sopenharmony_ci return ptr1.p_u16[idx] == ptr2.p_u16[idx]; 16098c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_U32: 16108c2ecf20Sopenharmony_ci return ptr1.p_u32[idx] == ptr2.p_u32[idx]; 16118c2ecf20Sopenharmony_ci default: 16128c2ecf20Sopenharmony_ci if (ctrl->is_int) 16138c2ecf20Sopenharmony_ci return ptr1.p_s32[idx] == ptr2.p_s32[idx]; 16148c2ecf20Sopenharmony_ci idx *= ctrl->elem_size; 16158c2ecf20Sopenharmony_ci return !memcmp(ptr1.p_const + idx, ptr2.p_const + idx, 16168c2ecf20Sopenharmony_ci ctrl->elem_size); 16178c2ecf20Sopenharmony_ci } 16188c2ecf20Sopenharmony_ci} 16198c2ecf20Sopenharmony_ci 16208c2ecf20Sopenharmony_cistatic void std_init_compound(const struct v4l2_ctrl *ctrl, u32 idx, 16218c2ecf20Sopenharmony_ci union v4l2_ctrl_ptr ptr) 16228c2ecf20Sopenharmony_ci{ 16238c2ecf20Sopenharmony_ci struct v4l2_ctrl_mpeg2_slice_params *p_mpeg2_slice_params; 16248c2ecf20Sopenharmony_ci void *p = ptr.p + idx * ctrl->elem_size; 16258c2ecf20Sopenharmony_ci 16268c2ecf20Sopenharmony_ci if (ctrl->p_def.p_const) 16278c2ecf20Sopenharmony_ci memcpy(p, ctrl->p_def.p_const, ctrl->elem_size); 16288c2ecf20Sopenharmony_ci else 16298c2ecf20Sopenharmony_ci memset(p, 0, ctrl->elem_size); 16308c2ecf20Sopenharmony_ci 16318c2ecf20Sopenharmony_ci /* 16328c2ecf20Sopenharmony_ci * The cast is needed to get rid of a gcc warning complaining that 16338c2ecf20Sopenharmony_ci * V4L2_CTRL_TYPE_MPEG2_SLICE_PARAMS is not part of the 16348c2ecf20Sopenharmony_ci * v4l2_ctrl_type enum. 16358c2ecf20Sopenharmony_ci */ 16368c2ecf20Sopenharmony_ci switch ((u32)ctrl->type) { 16378c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_MPEG2_SLICE_PARAMS: 16388c2ecf20Sopenharmony_ci p_mpeg2_slice_params = p; 16398c2ecf20Sopenharmony_ci /* 4:2:0 */ 16408c2ecf20Sopenharmony_ci p_mpeg2_slice_params->sequence.chroma_format = 1; 16418c2ecf20Sopenharmony_ci /* interlaced top field */ 16428c2ecf20Sopenharmony_ci p_mpeg2_slice_params->picture.picture_structure = 1; 16438c2ecf20Sopenharmony_ci p_mpeg2_slice_params->picture.picture_coding_type = 16448c2ecf20Sopenharmony_ci V4L2_MPEG2_PICTURE_CODING_TYPE_I; 16458c2ecf20Sopenharmony_ci break; 16468c2ecf20Sopenharmony_ci } 16478c2ecf20Sopenharmony_ci} 16488c2ecf20Sopenharmony_ci 16498c2ecf20Sopenharmony_cistatic void std_init(const struct v4l2_ctrl *ctrl, u32 idx, 16508c2ecf20Sopenharmony_ci union v4l2_ctrl_ptr ptr) 16518c2ecf20Sopenharmony_ci{ 16528c2ecf20Sopenharmony_ci switch (ctrl->type) { 16538c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_STRING: 16548c2ecf20Sopenharmony_ci idx *= ctrl->elem_size; 16558c2ecf20Sopenharmony_ci memset(ptr.p_char + idx, ' ', ctrl->minimum); 16568c2ecf20Sopenharmony_ci ptr.p_char[idx + ctrl->minimum] = '\0'; 16578c2ecf20Sopenharmony_ci break; 16588c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_INTEGER64: 16598c2ecf20Sopenharmony_ci ptr.p_s64[idx] = ctrl->default_value; 16608c2ecf20Sopenharmony_ci break; 16618c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_INTEGER: 16628c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_INTEGER_MENU: 16638c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_MENU: 16648c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_BITMASK: 16658c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_BOOLEAN: 16668c2ecf20Sopenharmony_ci ptr.p_s32[idx] = ctrl->default_value; 16678c2ecf20Sopenharmony_ci break; 16688c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_BUTTON: 16698c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_CTRL_CLASS: 16708c2ecf20Sopenharmony_ci ptr.p_s32[idx] = 0; 16718c2ecf20Sopenharmony_ci break; 16728c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_U8: 16738c2ecf20Sopenharmony_ci ptr.p_u8[idx] = ctrl->default_value; 16748c2ecf20Sopenharmony_ci break; 16758c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_U16: 16768c2ecf20Sopenharmony_ci ptr.p_u16[idx] = ctrl->default_value; 16778c2ecf20Sopenharmony_ci break; 16788c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_U32: 16798c2ecf20Sopenharmony_ci ptr.p_u32[idx] = ctrl->default_value; 16808c2ecf20Sopenharmony_ci break; 16818c2ecf20Sopenharmony_ci default: 16828c2ecf20Sopenharmony_ci std_init_compound(ctrl, idx, ptr); 16838c2ecf20Sopenharmony_ci break; 16848c2ecf20Sopenharmony_ci } 16858c2ecf20Sopenharmony_ci} 16868c2ecf20Sopenharmony_ci 16878c2ecf20Sopenharmony_cistatic void std_log(const struct v4l2_ctrl *ctrl) 16888c2ecf20Sopenharmony_ci{ 16898c2ecf20Sopenharmony_ci union v4l2_ctrl_ptr ptr = ctrl->p_cur; 16908c2ecf20Sopenharmony_ci 16918c2ecf20Sopenharmony_ci if (ctrl->is_array) { 16928c2ecf20Sopenharmony_ci unsigned i; 16938c2ecf20Sopenharmony_ci 16948c2ecf20Sopenharmony_ci for (i = 0; i < ctrl->nr_of_dims; i++) 16958c2ecf20Sopenharmony_ci pr_cont("[%u]", ctrl->dims[i]); 16968c2ecf20Sopenharmony_ci pr_cont(" "); 16978c2ecf20Sopenharmony_ci } 16988c2ecf20Sopenharmony_ci 16998c2ecf20Sopenharmony_ci switch (ctrl->type) { 17008c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_INTEGER: 17018c2ecf20Sopenharmony_ci pr_cont("%d", *ptr.p_s32); 17028c2ecf20Sopenharmony_ci break; 17038c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_BOOLEAN: 17048c2ecf20Sopenharmony_ci pr_cont("%s", *ptr.p_s32 ? "true" : "false"); 17058c2ecf20Sopenharmony_ci break; 17068c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_MENU: 17078c2ecf20Sopenharmony_ci pr_cont("%s", ctrl->qmenu[*ptr.p_s32]); 17088c2ecf20Sopenharmony_ci break; 17098c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_INTEGER_MENU: 17108c2ecf20Sopenharmony_ci pr_cont("%lld", ctrl->qmenu_int[*ptr.p_s32]); 17118c2ecf20Sopenharmony_ci break; 17128c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_BITMASK: 17138c2ecf20Sopenharmony_ci pr_cont("0x%08x", *ptr.p_s32); 17148c2ecf20Sopenharmony_ci break; 17158c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_INTEGER64: 17168c2ecf20Sopenharmony_ci pr_cont("%lld", *ptr.p_s64); 17178c2ecf20Sopenharmony_ci break; 17188c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_STRING: 17198c2ecf20Sopenharmony_ci pr_cont("%s", ptr.p_char); 17208c2ecf20Sopenharmony_ci break; 17218c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_U8: 17228c2ecf20Sopenharmony_ci pr_cont("%u", (unsigned)*ptr.p_u8); 17238c2ecf20Sopenharmony_ci break; 17248c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_U16: 17258c2ecf20Sopenharmony_ci pr_cont("%u", (unsigned)*ptr.p_u16); 17268c2ecf20Sopenharmony_ci break; 17278c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_U32: 17288c2ecf20Sopenharmony_ci pr_cont("%u", (unsigned)*ptr.p_u32); 17298c2ecf20Sopenharmony_ci break; 17308c2ecf20Sopenharmony_ci default: 17318c2ecf20Sopenharmony_ci pr_cont("unknown type %d", ctrl->type); 17328c2ecf20Sopenharmony_ci break; 17338c2ecf20Sopenharmony_ci } 17348c2ecf20Sopenharmony_ci} 17358c2ecf20Sopenharmony_ci 17368c2ecf20Sopenharmony_ci/* 17378c2ecf20Sopenharmony_ci * Round towards the closest legal value. Be careful when we are 17388c2ecf20Sopenharmony_ci * close to the maximum range of the control type to prevent 17398c2ecf20Sopenharmony_ci * wrap-arounds. 17408c2ecf20Sopenharmony_ci */ 17418c2ecf20Sopenharmony_ci#define ROUND_TO_RANGE(val, offset_type, ctrl) \ 17428c2ecf20Sopenharmony_ci({ \ 17438c2ecf20Sopenharmony_ci offset_type offset; \ 17448c2ecf20Sopenharmony_ci if ((ctrl)->maximum >= 0 && \ 17458c2ecf20Sopenharmony_ci val >= (ctrl)->maximum - (s32)((ctrl)->step / 2)) \ 17468c2ecf20Sopenharmony_ci val = (ctrl)->maximum; \ 17478c2ecf20Sopenharmony_ci else \ 17488c2ecf20Sopenharmony_ci val += (s32)((ctrl)->step / 2); \ 17498c2ecf20Sopenharmony_ci val = clamp_t(typeof(val), val, \ 17508c2ecf20Sopenharmony_ci (ctrl)->minimum, (ctrl)->maximum); \ 17518c2ecf20Sopenharmony_ci offset = (val) - (ctrl)->minimum; \ 17528c2ecf20Sopenharmony_ci offset = (ctrl)->step * (offset / (u32)(ctrl)->step); \ 17538c2ecf20Sopenharmony_ci val = (ctrl)->minimum + offset; \ 17548c2ecf20Sopenharmony_ci 0; \ 17558c2ecf20Sopenharmony_ci}) 17568c2ecf20Sopenharmony_ci 17578c2ecf20Sopenharmony_ci/* Validate a new control */ 17588c2ecf20Sopenharmony_ci 17598c2ecf20Sopenharmony_ci#define zero_padding(s) \ 17608c2ecf20Sopenharmony_ci memset(&(s).padding, 0, sizeof((s).padding)) 17618c2ecf20Sopenharmony_ci#define zero_reserved(s) \ 17628c2ecf20Sopenharmony_ci memset(&(s).reserved, 0, sizeof((s).reserved)) 17638c2ecf20Sopenharmony_ci 17648c2ecf20Sopenharmony_ci/* 17658c2ecf20Sopenharmony_ci * Compound controls validation requires setting unused fields/flags to zero 17668c2ecf20Sopenharmony_ci * in order to properly detect unchanged controls with std_equal's memcmp. 17678c2ecf20Sopenharmony_ci */ 17688c2ecf20Sopenharmony_cistatic int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx, 17698c2ecf20Sopenharmony_ci union v4l2_ctrl_ptr ptr) 17708c2ecf20Sopenharmony_ci{ 17718c2ecf20Sopenharmony_ci struct v4l2_ctrl_mpeg2_slice_params *p_mpeg2_slice_params; 17728c2ecf20Sopenharmony_ci struct v4l2_ctrl_vp8_frame_header *p_vp8_frame_header; 17738c2ecf20Sopenharmony_ci struct v4l2_ctrl_h264_slice_params *p_h264_slice_params; 17748c2ecf20Sopenharmony_ci struct v4l2_ctrl_h264_decode_params *p_h264_dec_params; 17758c2ecf20Sopenharmony_ci struct v4l2_ctrl_hevc_sps *p_hevc_sps; 17768c2ecf20Sopenharmony_ci struct v4l2_ctrl_hevc_pps *p_hevc_pps; 17778c2ecf20Sopenharmony_ci struct v4l2_ctrl_hevc_slice_params *p_hevc_slice_params; 17788c2ecf20Sopenharmony_ci struct v4l2_area *area; 17798c2ecf20Sopenharmony_ci void *p = ptr.p + idx * ctrl->elem_size; 17808c2ecf20Sopenharmony_ci unsigned int i; 17818c2ecf20Sopenharmony_ci 17828c2ecf20Sopenharmony_ci switch ((u32)ctrl->type) { 17838c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_MPEG2_SLICE_PARAMS: 17848c2ecf20Sopenharmony_ci p_mpeg2_slice_params = p; 17858c2ecf20Sopenharmony_ci 17868c2ecf20Sopenharmony_ci switch (p_mpeg2_slice_params->sequence.chroma_format) { 17878c2ecf20Sopenharmony_ci case 1: /* 4:2:0 */ 17888c2ecf20Sopenharmony_ci case 2: /* 4:2:2 */ 17898c2ecf20Sopenharmony_ci case 3: /* 4:4:4 */ 17908c2ecf20Sopenharmony_ci break; 17918c2ecf20Sopenharmony_ci default: 17928c2ecf20Sopenharmony_ci return -EINVAL; 17938c2ecf20Sopenharmony_ci } 17948c2ecf20Sopenharmony_ci 17958c2ecf20Sopenharmony_ci switch (p_mpeg2_slice_params->picture.intra_dc_precision) { 17968c2ecf20Sopenharmony_ci case 0: /* 8 bits */ 17978c2ecf20Sopenharmony_ci case 1: /* 9 bits */ 17988c2ecf20Sopenharmony_ci case 2: /* 10 bits */ 17998c2ecf20Sopenharmony_ci case 3: /* 11 bits */ 18008c2ecf20Sopenharmony_ci break; 18018c2ecf20Sopenharmony_ci default: 18028c2ecf20Sopenharmony_ci return -EINVAL; 18038c2ecf20Sopenharmony_ci } 18048c2ecf20Sopenharmony_ci 18058c2ecf20Sopenharmony_ci switch (p_mpeg2_slice_params->picture.picture_structure) { 18068c2ecf20Sopenharmony_ci case 1: /* interlaced top field */ 18078c2ecf20Sopenharmony_ci case 2: /* interlaced bottom field */ 18088c2ecf20Sopenharmony_ci case 3: /* progressive */ 18098c2ecf20Sopenharmony_ci break; 18108c2ecf20Sopenharmony_ci default: 18118c2ecf20Sopenharmony_ci return -EINVAL; 18128c2ecf20Sopenharmony_ci } 18138c2ecf20Sopenharmony_ci 18148c2ecf20Sopenharmony_ci switch (p_mpeg2_slice_params->picture.picture_coding_type) { 18158c2ecf20Sopenharmony_ci case V4L2_MPEG2_PICTURE_CODING_TYPE_I: 18168c2ecf20Sopenharmony_ci case V4L2_MPEG2_PICTURE_CODING_TYPE_P: 18178c2ecf20Sopenharmony_ci case V4L2_MPEG2_PICTURE_CODING_TYPE_B: 18188c2ecf20Sopenharmony_ci break; 18198c2ecf20Sopenharmony_ci default: 18208c2ecf20Sopenharmony_ci return -EINVAL; 18218c2ecf20Sopenharmony_ci } 18228c2ecf20Sopenharmony_ci 18238c2ecf20Sopenharmony_ci break; 18248c2ecf20Sopenharmony_ci 18258c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_MPEG2_QUANTIZATION: 18268c2ecf20Sopenharmony_ci break; 18278c2ecf20Sopenharmony_ci 18288c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_FWHT_PARAMS: 18298c2ecf20Sopenharmony_ci break; 18308c2ecf20Sopenharmony_ci 18318c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_H264_SPS: 18328c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_H264_PPS: 18338c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_H264_SCALING_MATRIX: 18348c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_H264_PRED_WEIGHTS: 18358c2ecf20Sopenharmony_ci break; 18368c2ecf20Sopenharmony_ci 18378c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_H264_SLICE_PARAMS: 18388c2ecf20Sopenharmony_ci p_h264_slice_params = p; 18398c2ecf20Sopenharmony_ci 18408c2ecf20Sopenharmony_ci zero_reserved(*p_h264_slice_params); 18418c2ecf20Sopenharmony_ci break; 18428c2ecf20Sopenharmony_ci 18438c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_H264_DECODE_PARAMS: 18448c2ecf20Sopenharmony_ci p_h264_dec_params = p; 18458c2ecf20Sopenharmony_ci 18468c2ecf20Sopenharmony_ci for (i = 0; i < V4L2_H264_NUM_DPB_ENTRIES; i++) { 18478c2ecf20Sopenharmony_ci struct v4l2_h264_dpb_entry *dpb_entry = 18488c2ecf20Sopenharmony_ci &p_h264_dec_params->dpb[i]; 18498c2ecf20Sopenharmony_ci 18508c2ecf20Sopenharmony_ci zero_reserved(*dpb_entry); 18518c2ecf20Sopenharmony_ci } 18528c2ecf20Sopenharmony_ci zero_reserved(*p_h264_dec_params); 18538c2ecf20Sopenharmony_ci break; 18548c2ecf20Sopenharmony_ci 18558c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_VP8_FRAME_HEADER: 18568c2ecf20Sopenharmony_ci p_vp8_frame_header = p; 18578c2ecf20Sopenharmony_ci 18588c2ecf20Sopenharmony_ci switch (p_vp8_frame_header->num_dct_parts) { 18598c2ecf20Sopenharmony_ci case 1: 18608c2ecf20Sopenharmony_ci case 2: 18618c2ecf20Sopenharmony_ci case 4: 18628c2ecf20Sopenharmony_ci case 8: 18638c2ecf20Sopenharmony_ci break; 18648c2ecf20Sopenharmony_ci default: 18658c2ecf20Sopenharmony_ci return -EINVAL; 18668c2ecf20Sopenharmony_ci } 18678c2ecf20Sopenharmony_ci zero_padding(p_vp8_frame_header->segment_header); 18688c2ecf20Sopenharmony_ci zero_padding(p_vp8_frame_header->lf_header); 18698c2ecf20Sopenharmony_ci zero_padding(p_vp8_frame_header->quant_header); 18708c2ecf20Sopenharmony_ci zero_padding(p_vp8_frame_header->entropy_header); 18718c2ecf20Sopenharmony_ci zero_padding(p_vp8_frame_header->coder_state); 18728c2ecf20Sopenharmony_ci break; 18738c2ecf20Sopenharmony_ci 18748c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_HEVC_SPS: 18758c2ecf20Sopenharmony_ci p_hevc_sps = p; 18768c2ecf20Sopenharmony_ci 18778c2ecf20Sopenharmony_ci if (!(p_hevc_sps->flags & V4L2_HEVC_SPS_FLAG_PCM_ENABLED)) { 18788c2ecf20Sopenharmony_ci p_hevc_sps->pcm_sample_bit_depth_luma_minus1 = 0; 18798c2ecf20Sopenharmony_ci p_hevc_sps->pcm_sample_bit_depth_chroma_minus1 = 0; 18808c2ecf20Sopenharmony_ci p_hevc_sps->log2_min_pcm_luma_coding_block_size_minus3 = 0; 18818c2ecf20Sopenharmony_ci p_hevc_sps->log2_diff_max_min_pcm_luma_coding_block_size = 0; 18828c2ecf20Sopenharmony_ci } 18838c2ecf20Sopenharmony_ci 18848c2ecf20Sopenharmony_ci if (!(p_hevc_sps->flags & 18858c2ecf20Sopenharmony_ci V4L2_HEVC_SPS_FLAG_LONG_TERM_REF_PICS_PRESENT)) 18868c2ecf20Sopenharmony_ci p_hevc_sps->num_long_term_ref_pics_sps = 0; 18878c2ecf20Sopenharmony_ci break; 18888c2ecf20Sopenharmony_ci 18898c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_HEVC_PPS: 18908c2ecf20Sopenharmony_ci p_hevc_pps = p; 18918c2ecf20Sopenharmony_ci 18928c2ecf20Sopenharmony_ci if (!(p_hevc_pps->flags & 18938c2ecf20Sopenharmony_ci V4L2_HEVC_PPS_FLAG_CU_QP_DELTA_ENABLED)) 18948c2ecf20Sopenharmony_ci p_hevc_pps->diff_cu_qp_delta_depth = 0; 18958c2ecf20Sopenharmony_ci 18968c2ecf20Sopenharmony_ci if (!(p_hevc_pps->flags & V4L2_HEVC_PPS_FLAG_TILES_ENABLED)) { 18978c2ecf20Sopenharmony_ci p_hevc_pps->num_tile_columns_minus1 = 0; 18988c2ecf20Sopenharmony_ci p_hevc_pps->num_tile_rows_minus1 = 0; 18998c2ecf20Sopenharmony_ci memset(&p_hevc_pps->column_width_minus1, 0, 19008c2ecf20Sopenharmony_ci sizeof(p_hevc_pps->column_width_minus1)); 19018c2ecf20Sopenharmony_ci memset(&p_hevc_pps->row_height_minus1, 0, 19028c2ecf20Sopenharmony_ci sizeof(p_hevc_pps->row_height_minus1)); 19038c2ecf20Sopenharmony_ci 19048c2ecf20Sopenharmony_ci p_hevc_pps->flags &= 19058c2ecf20Sopenharmony_ci ~V4L2_HEVC_PPS_FLAG_LOOP_FILTER_ACROSS_TILES_ENABLED; 19068c2ecf20Sopenharmony_ci } 19078c2ecf20Sopenharmony_ci 19088c2ecf20Sopenharmony_ci if (p_hevc_pps->flags & 19098c2ecf20Sopenharmony_ci V4L2_HEVC_PPS_FLAG_PPS_DISABLE_DEBLOCKING_FILTER) { 19108c2ecf20Sopenharmony_ci p_hevc_pps->pps_beta_offset_div2 = 0; 19118c2ecf20Sopenharmony_ci p_hevc_pps->pps_tc_offset_div2 = 0; 19128c2ecf20Sopenharmony_ci } 19138c2ecf20Sopenharmony_ci 19148c2ecf20Sopenharmony_ci zero_padding(*p_hevc_pps); 19158c2ecf20Sopenharmony_ci break; 19168c2ecf20Sopenharmony_ci 19178c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS: 19188c2ecf20Sopenharmony_ci p_hevc_slice_params = p; 19198c2ecf20Sopenharmony_ci 19208c2ecf20Sopenharmony_ci if (p_hevc_slice_params->num_active_dpb_entries > 19218c2ecf20Sopenharmony_ci V4L2_HEVC_DPB_ENTRIES_NUM_MAX) 19228c2ecf20Sopenharmony_ci return -EINVAL; 19238c2ecf20Sopenharmony_ci 19248c2ecf20Sopenharmony_ci zero_padding(p_hevc_slice_params->pred_weight_table); 19258c2ecf20Sopenharmony_ci 19268c2ecf20Sopenharmony_ci for (i = 0; i < p_hevc_slice_params->num_active_dpb_entries; 19278c2ecf20Sopenharmony_ci i++) { 19288c2ecf20Sopenharmony_ci struct v4l2_hevc_dpb_entry *dpb_entry = 19298c2ecf20Sopenharmony_ci &p_hevc_slice_params->dpb[i]; 19308c2ecf20Sopenharmony_ci 19318c2ecf20Sopenharmony_ci zero_padding(*dpb_entry); 19328c2ecf20Sopenharmony_ci } 19338c2ecf20Sopenharmony_ci 19348c2ecf20Sopenharmony_ci zero_padding(*p_hevc_slice_params); 19358c2ecf20Sopenharmony_ci break; 19368c2ecf20Sopenharmony_ci 19378c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_AREA: 19388c2ecf20Sopenharmony_ci area = p; 19398c2ecf20Sopenharmony_ci if (!area->width || !area->height) 19408c2ecf20Sopenharmony_ci return -EINVAL; 19418c2ecf20Sopenharmony_ci break; 19428c2ecf20Sopenharmony_ci 19438c2ecf20Sopenharmony_ci default: 19448c2ecf20Sopenharmony_ci return -EINVAL; 19458c2ecf20Sopenharmony_ci } 19468c2ecf20Sopenharmony_ci 19478c2ecf20Sopenharmony_ci return 0; 19488c2ecf20Sopenharmony_ci} 19498c2ecf20Sopenharmony_ci 19508c2ecf20Sopenharmony_cistatic int std_validate(const struct v4l2_ctrl *ctrl, u32 idx, 19518c2ecf20Sopenharmony_ci union v4l2_ctrl_ptr ptr) 19528c2ecf20Sopenharmony_ci{ 19538c2ecf20Sopenharmony_ci size_t len; 19548c2ecf20Sopenharmony_ci u64 offset; 19558c2ecf20Sopenharmony_ci s64 val; 19568c2ecf20Sopenharmony_ci 19578c2ecf20Sopenharmony_ci switch ((u32)ctrl->type) { 19588c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_INTEGER: 19598c2ecf20Sopenharmony_ci return ROUND_TO_RANGE(ptr.p_s32[idx], u32, ctrl); 19608c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_INTEGER64: 19618c2ecf20Sopenharmony_ci /* 19628c2ecf20Sopenharmony_ci * We can't use the ROUND_TO_RANGE define here due to 19638c2ecf20Sopenharmony_ci * the u64 divide that needs special care. 19648c2ecf20Sopenharmony_ci */ 19658c2ecf20Sopenharmony_ci val = ptr.p_s64[idx]; 19668c2ecf20Sopenharmony_ci if (ctrl->maximum >= 0 && val >= ctrl->maximum - (s64)(ctrl->step / 2)) 19678c2ecf20Sopenharmony_ci val = ctrl->maximum; 19688c2ecf20Sopenharmony_ci else 19698c2ecf20Sopenharmony_ci val += (s64)(ctrl->step / 2); 19708c2ecf20Sopenharmony_ci val = clamp_t(s64, val, ctrl->minimum, ctrl->maximum); 19718c2ecf20Sopenharmony_ci offset = val - ctrl->minimum; 19728c2ecf20Sopenharmony_ci do_div(offset, ctrl->step); 19738c2ecf20Sopenharmony_ci ptr.p_s64[idx] = ctrl->minimum + offset * ctrl->step; 19748c2ecf20Sopenharmony_ci return 0; 19758c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_U8: 19768c2ecf20Sopenharmony_ci return ROUND_TO_RANGE(ptr.p_u8[idx], u8, ctrl); 19778c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_U16: 19788c2ecf20Sopenharmony_ci return ROUND_TO_RANGE(ptr.p_u16[idx], u16, ctrl); 19798c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_U32: 19808c2ecf20Sopenharmony_ci return ROUND_TO_RANGE(ptr.p_u32[idx], u32, ctrl); 19818c2ecf20Sopenharmony_ci 19828c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_BOOLEAN: 19838c2ecf20Sopenharmony_ci ptr.p_s32[idx] = !!ptr.p_s32[idx]; 19848c2ecf20Sopenharmony_ci return 0; 19858c2ecf20Sopenharmony_ci 19868c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_MENU: 19878c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_INTEGER_MENU: 19888c2ecf20Sopenharmony_ci if (ptr.p_s32[idx] < ctrl->minimum || ptr.p_s32[idx] > ctrl->maximum) 19898c2ecf20Sopenharmony_ci return -ERANGE; 19908c2ecf20Sopenharmony_ci if (ptr.p_s32[idx] < BITS_PER_LONG_LONG && 19918c2ecf20Sopenharmony_ci (ctrl->menu_skip_mask & BIT_ULL(ptr.p_s32[idx]))) 19928c2ecf20Sopenharmony_ci return -EINVAL; 19938c2ecf20Sopenharmony_ci if (ctrl->type == V4L2_CTRL_TYPE_MENU && 19948c2ecf20Sopenharmony_ci ctrl->qmenu[ptr.p_s32[idx]][0] == '\0') 19958c2ecf20Sopenharmony_ci return -EINVAL; 19968c2ecf20Sopenharmony_ci return 0; 19978c2ecf20Sopenharmony_ci 19988c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_BITMASK: 19998c2ecf20Sopenharmony_ci ptr.p_s32[idx] &= ctrl->maximum; 20008c2ecf20Sopenharmony_ci return 0; 20018c2ecf20Sopenharmony_ci 20028c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_BUTTON: 20038c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_CTRL_CLASS: 20048c2ecf20Sopenharmony_ci ptr.p_s32[idx] = 0; 20058c2ecf20Sopenharmony_ci return 0; 20068c2ecf20Sopenharmony_ci 20078c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_STRING: 20088c2ecf20Sopenharmony_ci idx *= ctrl->elem_size; 20098c2ecf20Sopenharmony_ci len = strlen(ptr.p_char + idx); 20108c2ecf20Sopenharmony_ci if (len < ctrl->minimum) 20118c2ecf20Sopenharmony_ci return -ERANGE; 20128c2ecf20Sopenharmony_ci if ((len - (u32)ctrl->minimum) % (u32)ctrl->step) 20138c2ecf20Sopenharmony_ci return -ERANGE; 20148c2ecf20Sopenharmony_ci return 0; 20158c2ecf20Sopenharmony_ci 20168c2ecf20Sopenharmony_ci default: 20178c2ecf20Sopenharmony_ci return std_validate_compound(ctrl, idx, ptr); 20188c2ecf20Sopenharmony_ci } 20198c2ecf20Sopenharmony_ci} 20208c2ecf20Sopenharmony_ci 20218c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_type_ops std_type_ops = { 20228c2ecf20Sopenharmony_ci .equal = std_equal, 20238c2ecf20Sopenharmony_ci .init = std_init, 20248c2ecf20Sopenharmony_ci .log = std_log, 20258c2ecf20Sopenharmony_ci .validate = std_validate, 20268c2ecf20Sopenharmony_ci}; 20278c2ecf20Sopenharmony_ci 20288c2ecf20Sopenharmony_ci/* Helper function: copy the given control value back to the caller */ 20298c2ecf20Sopenharmony_cistatic int ptr_to_user(struct v4l2_ext_control *c, 20308c2ecf20Sopenharmony_ci struct v4l2_ctrl *ctrl, 20318c2ecf20Sopenharmony_ci union v4l2_ctrl_ptr ptr) 20328c2ecf20Sopenharmony_ci{ 20338c2ecf20Sopenharmony_ci u32 len; 20348c2ecf20Sopenharmony_ci 20358c2ecf20Sopenharmony_ci if (ctrl->is_ptr && !ctrl->is_string) 20368c2ecf20Sopenharmony_ci return copy_to_user(c->ptr, ptr.p_const, c->size) ? 20378c2ecf20Sopenharmony_ci -EFAULT : 0; 20388c2ecf20Sopenharmony_ci 20398c2ecf20Sopenharmony_ci switch (ctrl->type) { 20408c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_STRING: 20418c2ecf20Sopenharmony_ci len = strlen(ptr.p_char); 20428c2ecf20Sopenharmony_ci if (c->size < len + 1) { 20438c2ecf20Sopenharmony_ci c->size = ctrl->elem_size; 20448c2ecf20Sopenharmony_ci return -ENOSPC; 20458c2ecf20Sopenharmony_ci } 20468c2ecf20Sopenharmony_ci return copy_to_user(c->string, ptr.p_char, len + 1) ? 20478c2ecf20Sopenharmony_ci -EFAULT : 0; 20488c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_INTEGER64: 20498c2ecf20Sopenharmony_ci c->value64 = *ptr.p_s64; 20508c2ecf20Sopenharmony_ci break; 20518c2ecf20Sopenharmony_ci default: 20528c2ecf20Sopenharmony_ci c->value = *ptr.p_s32; 20538c2ecf20Sopenharmony_ci break; 20548c2ecf20Sopenharmony_ci } 20558c2ecf20Sopenharmony_ci return 0; 20568c2ecf20Sopenharmony_ci} 20578c2ecf20Sopenharmony_ci 20588c2ecf20Sopenharmony_ci/* Helper function: copy the current control value back to the caller */ 20598c2ecf20Sopenharmony_cistatic int cur_to_user(struct v4l2_ext_control *c, 20608c2ecf20Sopenharmony_ci struct v4l2_ctrl *ctrl) 20618c2ecf20Sopenharmony_ci{ 20628c2ecf20Sopenharmony_ci return ptr_to_user(c, ctrl, ctrl->p_cur); 20638c2ecf20Sopenharmony_ci} 20648c2ecf20Sopenharmony_ci 20658c2ecf20Sopenharmony_ci/* Helper function: copy the new control value back to the caller */ 20668c2ecf20Sopenharmony_cistatic int new_to_user(struct v4l2_ext_control *c, 20678c2ecf20Sopenharmony_ci struct v4l2_ctrl *ctrl) 20688c2ecf20Sopenharmony_ci{ 20698c2ecf20Sopenharmony_ci return ptr_to_user(c, ctrl, ctrl->p_new); 20708c2ecf20Sopenharmony_ci} 20718c2ecf20Sopenharmony_ci 20728c2ecf20Sopenharmony_ci/* Helper function: copy the request value back to the caller */ 20738c2ecf20Sopenharmony_cistatic int req_to_user(struct v4l2_ext_control *c, 20748c2ecf20Sopenharmony_ci struct v4l2_ctrl_ref *ref) 20758c2ecf20Sopenharmony_ci{ 20768c2ecf20Sopenharmony_ci return ptr_to_user(c, ref->ctrl, ref->p_req); 20778c2ecf20Sopenharmony_ci} 20788c2ecf20Sopenharmony_ci 20798c2ecf20Sopenharmony_ci/* Helper function: copy the initial control value back to the caller */ 20808c2ecf20Sopenharmony_cistatic int def_to_user(struct v4l2_ext_control *c, struct v4l2_ctrl *ctrl) 20818c2ecf20Sopenharmony_ci{ 20828c2ecf20Sopenharmony_ci int idx; 20838c2ecf20Sopenharmony_ci 20848c2ecf20Sopenharmony_ci for (idx = 0; idx < ctrl->elems; idx++) 20858c2ecf20Sopenharmony_ci ctrl->type_ops->init(ctrl, idx, ctrl->p_new); 20868c2ecf20Sopenharmony_ci 20878c2ecf20Sopenharmony_ci return ptr_to_user(c, ctrl, ctrl->p_new); 20888c2ecf20Sopenharmony_ci} 20898c2ecf20Sopenharmony_ci 20908c2ecf20Sopenharmony_ci/* Helper function: copy the caller-provider value to the given control value */ 20918c2ecf20Sopenharmony_cistatic int user_to_ptr(struct v4l2_ext_control *c, 20928c2ecf20Sopenharmony_ci struct v4l2_ctrl *ctrl, 20938c2ecf20Sopenharmony_ci union v4l2_ctrl_ptr ptr) 20948c2ecf20Sopenharmony_ci{ 20958c2ecf20Sopenharmony_ci int ret; 20968c2ecf20Sopenharmony_ci u32 size; 20978c2ecf20Sopenharmony_ci 20988c2ecf20Sopenharmony_ci ctrl->is_new = 1; 20998c2ecf20Sopenharmony_ci if (ctrl->is_ptr && !ctrl->is_string) { 21008c2ecf20Sopenharmony_ci unsigned idx; 21018c2ecf20Sopenharmony_ci 21028c2ecf20Sopenharmony_ci ret = copy_from_user(ptr.p, c->ptr, c->size) ? -EFAULT : 0; 21038c2ecf20Sopenharmony_ci if (ret || !ctrl->is_array) 21048c2ecf20Sopenharmony_ci return ret; 21058c2ecf20Sopenharmony_ci for (idx = c->size / ctrl->elem_size; idx < ctrl->elems; idx++) 21068c2ecf20Sopenharmony_ci ctrl->type_ops->init(ctrl, idx, ptr); 21078c2ecf20Sopenharmony_ci return 0; 21088c2ecf20Sopenharmony_ci } 21098c2ecf20Sopenharmony_ci 21108c2ecf20Sopenharmony_ci switch (ctrl->type) { 21118c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_INTEGER64: 21128c2ecf20Sopenharmony_ci *ptr.p_s64 = c->value64; 21138c2ecf20Sopenharmony_ci break; 21148c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_STRING: 21158c2ecf20Sopenharmony_ci size = c->size; 21168c2ecf20Sopenharmony_ci if (size == 0) 21178c2ecf20Sopenharmony_ci return -ERANGE; 21188c2ecf20Sopenharmony_ci if (size > ctrl->maximum + 1) 21198c2ecf20Sopenharmony_ci size = ctrl->maximum + 1; 21208c2ecf20Sopenharmony_ci ret = copy_from_user(ptr.p_char, c->string, size) ? -EFAULT : 0; 21218c2ecf20Sopenharmony_ci if (!ret) { 21228c2ecf20Sopenharmony_ci char last = ptr.p_char[size - 1]; 21238c2ecf20Sopenharmony_ci 21248c2ecf20Sopenharmony_ci ptr.p_char[size - 1] = 0; 21258c2ecf20Sopenharmony_ci /* If the string was longer than ctrl->maximum, 21268c2ecf20Sopenharmony_ci then return an error. */ 21278c2ecf20Sopenharmony_ci if (strlen(ptr.p_char) == ctrl->maximum && last) 21288c2ecf20Sopenharmony_ci return -ERANGE; 21298c2ecf20Sopenharmony_ci } 21308c2ecf20Sopenharmony_ci return ret; 21318c2ecf20Sopenharmony_ci default: 21328c2ecf20Sopenharmony_ci *ptr.p_s32 = c->value; 21338c2ecf20Sopenharmony_ci break; 21348c2ecf20Sopenharmony_ci } 21358c2ecf20Sopenharmony_ci return 0; 21368c2ecf20Sopenharmony_ci} 21378c2ecf20Sopenharmony_ci 21388c2ecf20Sopenharmony_ci/* Helper function: copy the caller-provider value as the new control value */ 21398c2ecf20Sopenharmony_cistatic int user_to_new(struct v4l2_ext_control *c, 21408c2ecf20Sopenharmony_ci struct v4l2_ctrl *ctrl) 21418c2ecf20Sopenharmony_ci{ 21428c2ecf20Sopenharmony_ci return user_to_ptr(c, ctrl, ctrl->p_new); 21438c2ecf20Sopenharmony_ci} 21448c2ecf20Sopenharmony_ci 21458c2ecf20Sopenharmony_ci/* Copy the one value to another. */ 21468c2ecf20Sopenharmony_cistatic void ptr_to_ptr(struct v4l2_ctrl *ctrl, 21478c2ecf20Sopenharmony_ci union v4l2_ctrl_ptr from, union v4l2_ctrl_ptr to) 21488c2ecf20Sopenharmony_ci{ 21498c2ecf20Sopenharmony_ci if (ctrl == NULL) 21508c2ecf20Sopenharmony_ci return; 21518c2ecf20Sopenharmony_ci memcpy(to.p, from.p_const, ctrl->elems * ctrl->elem_size); 21528c2ecf20Sopenharmony_ci} 21538c2ecf20Sopenharmony_ci 21548c2ecf20Sopenharmony_ci/* Copy the new value to the current value. */ 21558c2ecf20Sopenharmony_cistatic void new_to_cur(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, u32 ch_flags) 21568c2ecf20Sopenharmony_ci{ 21578c2ecf20Sopenharmony_ci bool changed; 21588c2ecf20Sopenharmony_ci 21598c2ecf20Sopenharmony_ci if (ctrl == NULL) 21608c2ecf20Sopenharmony_ci return; 21618c2ecf20Sopenharmony_ci 21628c2ecf20Sopenharmony_ci /* has_changed is set by cluster_changed */ 21638c2ecf20Sopenharmony_ci changed = ctrl->has_changed; 21648c2ecf20Sopenharmony_ci if (changed) 21658c2ecf20Sopenharmony_ci ptr_to_ptr(ctrl, ctrl->p_new, ctrl->p_cur); 21668c2ecf20Sopenharmony_ci 21678c2ecf20Sopenharmony_ci if (ch_flags & V4L2_EVENT_CTRL_CH_FLAGS) { 21688c2ecf20Sopenharmony_ci /* Note: CH_FLAGS is only set for auto clusters. */ 21698c2ecf20Sopenharmony_ci ctrl->flags &= 21708c2ecf20Sopenharmony_ci ~(V4L2_CTRL_FLAG_INACTIVE | V4L2_CTRL_FLAG_VOLATILE); 21718c2ecf20Sopenharmony_ci if (!is_cur_manual(ctrl->cluster[0])) { 21728c2ecf20Sopenharmony_ci ctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; 21738c2ecf20Sopenharmony_ci if (ctrl->cluster[0]->has_volatiles) 21748c2ecf20Sopenharmony_ci ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE; 21758c2ecf20Sopenharmony_ci } 21768c2ecf20Sopenharmony_ci fh = NULL; 21778c2ecf20Sopenharmony_ci } 21788c2ecf20Sopenharmony_ci if (changed || ch_flags) { 21798c2ecf20Sopenharmony_ci /* If a control was changed that was not one of the controls 21808c2ecf20Sopenharmony_ci modified by the application, then send the event to all. */ 21818c2ecf20Sopenharmony_ci if (!ctrl->is_new) 21828c2ecf20Sopenharmony_ci fh = NULL; 21838c2ecf20Sopenharmony_ci send_event(fh, ctrl, 21848c2ecf20Sopenharmony_ci (changed ? V4L2_EVENT_CTRL_CH_VALUE : 0) | ch_flags); 21858c2ecf20Sopenharmony_ci if (ctrl->call_notify && changed && ctrl->handler->notify) 21868c2ecf20Sopenharmony_ci ctrl->handler->notify(ctrl, ctrl->handler->notify_priv); 21878c2ecf20Sopenharmony_ci } 21888c2ecf20Sopenharmony_ci} 21898c2ecf20Sopenharmony_ci 21908c2ecf20Sopenharmony_ci/* Copy the current value to the new value */ 21918c2ecf20Sopenharmony_cistatic void cur_to_new(struct v4l2_ctrl *ctrl) 21928c2ecf20Sopenharmony_ci{ 21938c2ecf20Sopenharmony_ci if (ctrl == NULL) 21948c2ecf20Sopenharmony_ci return; 21958c2ecf20Sopenharmony_ci ptr_to_ptr(ctrl, ctrl->p_cur, ctrl->p_new); 21968c2ecf20Sopenharmony_ci} 21978c2ecf20Sopenharmony_ci 21988c2ecf20Sopenharmony_ci/* Copy the new value to the request value */ 21998c2ecf20Sopenharmony_cistatic void new_to_req(struct v4l2_ctrl_ref *ref) 22008c2ecf20Sopenharmony_ci{ 22018c2ecf20Sopenharmony_ci if (!ref) 22028c2ecf20Sopenharmony_ci return; 22038c2ecf20Sopenharmony_ci ptr_to_ptr(ref->ctrl, ref->ctrl->p_new, ref->p_req); 22048c2ecf20Sopenharmony_ci ref->valid_p_req = true; 22058c2ecf20Sopenharmony_ci} 22068c2ecf20Sopenharmony_ci 22078c2ecf20Sopenharmony_ci/* Copy the current value to the request value */ 22088c2ecf20Sopenharmony_cistatic void cur_to_req(struct v4l2_ctrl_ref *ref) 22098c2ecf20Sopenharmony_ci{ 22108c2ecf20Sopenharmony_ci if (!ref) 22118c2ecf20Sopenharmony_ci return; 22128c2ecf20Sopenharmony_ci ptr_to_ptr(ref->ctrl, ref->ctrl->p_cur, ref->p_req); 22138c2ecf20Sopenharmony_ci ref->valid_p_req = true; 22148c2ecf20Sopenharmony_ci} 22158c2ecf20Sopenharmony_ci 22168c2ecf20Sopenharmony_ci/* Copy the request value to the new value */ 22178c2ecf20Sopenharmony_cistatic void req_to_new(struct v4l2_ctrl_ref *ref) 22188c2ecf20Sopenharmony_ci{ 22198c2ecf20Sopenharmony_ci if (!ref) 22208c2ecf20Sopenharmony_ci return; 22218c2ecf20Sopenharmony_ci if (ref->valid_p_req) 22228c2ecf20Sopenharmony_ci ptr_to_ptr(ref->ctrl, ref->p_req, ref->ctrl->p_new); 22238c2ecf20Sopenharmony_ci else 22248c2ecf20Sopenharmony_ci ptr_to_ptr(ref->ctrl, ref->ctrl->p_cur, ref->ctrl->p_new); 22258c2ecf20Sopenharmony_ci} 22268c2ecf20Sopenharmony_ci 22278c2ecf20Sopenharmony_ci/* Return non-zero if one or more of the controls in the cluster has a new 22288c2ecf20Sopenharmony_ci value that differs from the current value. */ 22298c2ecf20Sopenharmony_cistatic int cluster_changed(struct v4l2_ctrl *master) 22308c2ecf20Sopenharmony_ci{ 22318c2ecf20Sopenharmony_ci bool changed = false; 22328c2ecf20Sopenharmony_ci unsigned idx; 22338c2ecf20Sopenharmony_ci int i; 22348c2ecf20Sopenharmony_ci 22358c2ecf20Sopenharmony_ci for (i = 0; i < master->ncontrols; i++) { 22368c2ecf20Sopenharmony_ci struct v4l2_ctrl *ctrl = master->cluster[i]; 22378c2ecf20Sopenharmony_ci bool ctrl_changed = false; 22388c2ecf20Sopenharmony_ci 22398c2ecf20Sopenharmony_ci if (ctrl == NULL) 22408c2ecf20Sopenharmony_ci continue; 22418c2ecf20Sopenharmony_ci 22428c2ecf20Sopenharmony_ci if (ctrl->flags & V4L2_CTRL_FLAG_EXECUTE_ON_WRITE) 22438c2ecf20Sopenharmony_ci changed = ctrl_changed = true; 22448c2ecf20Sopenharmony_ci 22458c2ecf20Sopenharmony_ci /* 22468c2ecf20Sopenharmony_ci * Set has_changed to false to avoid generating 22478c2ecf20Sopenharmony_ci * the event V4L2_EVENT_CTRL_CH_VALUE 22488c2ecf20Sopenharmony_ci */ 22498c2ecf20Sopenharmony_ci if (ctrl->flags & V4L2_CTRL_FLAG_VOLATILE) { 22508c2ecf20Sopenharmony_ci ctrl->has_changed = false; 22518c2ecf20Sopenharmony_ci continue; 22528c2ecf20Sopenharmony_ci } 22538c2ecf20Sopenharmony_ci 22548c2ecf20Sopenharmony_ci for (idx = 0; !ctrl_changed && idx < ctrl->elems; idx++) 22558c2ecf20Sopenharmony_ci ctrl_changed = !ctrl->type_ops->equal(ctrl, idx, 22568c2ecf20Sopenharmony_ci ctrl->p_cur, ctrl->p_new); 22578c2ecf20Sopenharmony_ci ctrl->has_changed = ctrl_changed; 22588c2ecf20Sopenharmony_ci changed |= ctrl->has_changed; 22598c2ecf20Sopenharmony_ci } 22608c2ecf20Sopenharmony_ci return changed; 22618c2ecf20Sopenharmony_ci} 22628c2ecf20Sopenharmony_ci 22638c2ecf20Sopenharmony_ci/* Control range checking */ 22648c2ecf20Sopenharmony_cistatic int check_range(enum v4l2_ctrl_type type, 22658c2ecf20Sopenharmony_ci s64 min, s64 max, u64 step, s64 def) 22668c2ecf20Sopenharmony_ci{ 22678c2ecf20Sopenharmony_ci switch (type) { 22688c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_BOOLEAN: 22698c2ecf20Sopenharmony_ci if (step != 1 || max > 1 || min < 0) 22708c2ecf20Sopenharmony_ci return -ERANGE; 22718c2ecf20Sopenharmony_ci fallthrough; 22728c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_U8: 22738c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_U16: 22748c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_U32: 22758c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_INTEGER: 22768c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_INTEGER64: 22778c2ecf20Sopenharmony_ci if (step == 0 || min > max || def < min || def > max) 22788c2ecf20Sopenharmony_ci return -ERANGE; 22798c2ecf20Sopenharmony_ci return 0; 22808c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_BITMASK: 22818c2ecf20Sopenharmony_ci if (step || min || !max || (def & ~max)) 22828c2ecf20Sopenharmony_ci return -ERANGE; 22838c2ecf20Sopenharmony_ci return 0; 22848c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_MENU: 22858c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_INTEGER_MENU: 22868c2ecf20Sopenharmony_ci if (min > max || def < min || def > max) 22878c2ecf20Sopenharmony_ci return -ERANGE; 22888c2ecf20Sopenharmony_ci /* Note: step == menu_skip_mask for menu controls. 22898c2ecf20Sopenharmony_ci So here we check if the default value is masked out. */ 22908c2ecf20Sopenharmony_ci if (step && ((1 << def) & step)) 22918c2ecf20Sopenharmony_ci return -EINVAL; 22928c2ecf20Sopenharmony_ci return 0; 22938c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_STRING: 22948c2ecf20Sopenharmony_ci if (min > max || min < 0 || step < 1 || def) 22958c2ecf20Sopenharmony_ci return -ERANGE; 22968c2ecf20Sopenharmony_ci return 0; 22978c2ecf20Sopenharmony_ci default: 22988c2ecf20Sopenharmony_ci return 0; 22998c2ecf20Sopenharmony_ci } 23008c2ecf20Sopenharmony_ci} 23018c2ecf20Sopenharmony_ci 23028c2ecf20Sopenharmony_ci/* Validate a new control */ 23038c2ecf20Sopenharmony_cistatic int validate_new(const struct v4l2_ctrl *ctrl, union v4l2_ctrl_ptr p_new) 23048c2ecf20Sopenharmony_ci{ 23058c2ecf20Sopenharmony_ci unsigned idx; 23068c2ecf20Sopenharmony_ci int err = 0; 23078c2ecf20Sopenharmony_ci 23088c2ecf20Sopenharmony_ci for (idx = 0; !err && idx < ctrl->elems; idx++) 23098c2ecf20Sopenharmony_ci err = ctrl->type_ops->validate(ctrl, idx, p_new); 23108c2ecf20Sopenharmony_ci return err; 23118c2ecf20Sopenharmony_ci} 23128c2ecf20Sopenharmony_ci 23138c2ecf20Sopenharmony_cistatic inline u32 node2id(struct list_head *node) 23148c2ecf20Sopenharmony_ci{ 23158c2ecf20Sopenharmony_ci return list_entry(node, struct v4l2_ctrl_ref, node)->ctrl->id; 23168c2ecf20Sopenharmony_ci} 23178c2ecf20Sopenharmony_ci 23188c2ecf20Sopenharmony_ci/* Set the handler's error code if it wasn't set earlier already */ 23198c2ecf20Sopenharmony_cistatic inline int handler_set_err(struct v4l2_ctrl_handler *hdl, int err) 23208c2ecf20Sopenharmony_ci{ 23218c2ecf20Sopenharmony_ci if (hdl->error == 0) 23228c2ecf20Sopenharmony_ci hdl->error = err; 23238c2ecf20Sopenharmony_ci return err; 23248c2ecf20Sopenharmony_ci} 23258c2ecf20Sopenharmony_ci 23268c2ecf20Sopenharmony_ci/* Initialize the handler */ 23278c2ecf20Sopenharmony_ciint v4l2_ctrl_handler_init_class(struct v4l2_ctrl_handler *hdl, 23288c2ecf20Sopenharmony_ci unsigned nr_of_controls_hint, 23298c2ecf20Sopenharmony_ci struct lock_class_key *key, const char *name) 23308c2ecf20Sopenharmony_ci{ 23318c2ecf20Sopenharmony_ci mutex_init(&hdl->_lock); 23328c2ecf20Sopenharmony_ci hdl->lock = &hdl->_lock; 23338c2ecf20Sopenharmony_ci lockdep_set_class_and_name(hdl->lock, key, name); 23348c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&hdl->ctrls); 23358c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&hdl->ctrl_refs); 23368c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&hdl->requests); 23378c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&hdl->requests_queued); 23388c2ecf20Sopenharmony_ci hdl->request_is_queued = false; 23398c2ecf20Sopenharmony_ci hdl->nr_of_buckets = 1 + nr_of_controls_hint / 8; 23408c2ecf20Sopenharmony_ci hdl->buckets = kvmalloc_array(hdl->nr_of_buckets, 23418c2ecf20Sopenharmony_ci sizeof(hdl->buckets[0]), 23428c2ecf20Sopenharmony_ci GFP_KERNEL | __GFP_ZERO); 23438c2ecf20Sopenharmony_ci hdl->error = hdl->buckets ? 0 : -ENOMEM; 23448c2ecf20Sopenharmony_ci media_request_object_init(&hdl->req_obj); 23458c2ecf20Sopenharmony_ci return hdl->error; 23468c2ecf20Sopenharmony_ci} 23478c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_handler_init_class); 23488c2ecf20Sopenharmony_ci 23498c2ecf20Sopenharmony_ci/* Free all controls and control refs */ 23508c2ecf20Sopenharmony_civoid v4l2_ctrl_handler_free(struct v4l2_ctrl_handler *hdl) 23518c2ecf20Sopenharmony_ci{ 23528c2ecf20Sopenharmony_ci struct v4l2_ctrl_ref *ref, *next_ref; 23538c2ecf20Sopenharmony_ci struct v4l2_ctrl *ctrl, *next_ctrl; 23548c2ecf20Sopenharmony_ci struct v4l2_subscribed_event *sev, *next_sev; 23558c2ecf20Sopenharmony_ci 23568c2ecf20Sopenharmony_ci if (hdl == NULL || hdl->buckets == NULL) 23578c2ecf20Sopenharmony_ci return; 23588c2ecf20Sopenharmony_ci 23598c2ecf20Sopenharmony_ci /* 23608c2ecf20Sopenharmony_ci * If the main handler is freed and it is used by handler objects in 23618c2ecf20Sopenharmony_ci * outstanding requests, then unbind and put those objects before 23628c2ecf20Sopenharmony_ci * freeing the main handler. 23638c2ecf20Sopenharmony_ci * 23648c2ecf20Sopenharmony_ci * The main handler can be identified by having a NULL ops pointer in 23658c2ecf20Sopenharmony_ci * the request object. 23668c2ecf20Sopenharmony_ci */ 23678c2ecf20Sopenharmony_ci if (!hdl->req_obj.ops && !list_empty(&hdl->requests)) { 23688c2ecf20Sopenharmony_ci struct v4l2_ctrl_handler *req, *next_req; 23698c2ecf20Sopenharmony_ci 23708c2ecf20Sopenharmony_ci list_for_each_entry_safe(req, next_req, &hdl->requests, requests) { 23718c2ecf20Sopenharmony_ci media_request_object_unbind(&req->req_obj); 23728c2ecf20Sopenharmony_ci media_request_object_put(&req->req_obj); 23738c2ecf20Sopenharmony_ci } 23748c2ecf20Sopenharmony_ci } 23758c2ecf20Sopenharmony_ci mutex_lock(hdl->lock); 23768c2ecf20Sopenharmony_ci /* Free all nodes */ 23778c2ecf20Sopenharmony_ci list_for_each_entry_safe(ref, next_ref, &hdl->ctrl_refs, node) { 23788c2ecf20Sopenharmony_ci list_del(&ref->node); 23798c2ecf20Sopenharmony_ci kfree(ref); 23808c2ecf20Sopenharmony_ci } 23818c2ecf20Sopenharmony_ci /* Free all controls owned by the handler */ 23828c2ecf20Sopenharmony_ci list_for_each_entry_safe(ctrl, next_ctrl, &hdl->ctrls, node) { 23838c2ecf20Sopenharmony_ci list_del(&ctrl->node); 23848c2ecf20Sopenharmony_ci list_for_each_entry_safe(sev, next_sev, &ctrl->ev_subs, node) 23858c2ecf20Sopenharmony_ci list_del(&sev->node); 23868c2ecf20Sopenharmony_ci kvfree(ctrl); 23878c2ecf20Sopenharmony_ci } 23888c2ecf20Sopenharmony_ci kvfree(hdl->buckets); 23898c2ecf20Sopenharmony_ci hdl->buckets = NULL; 23908c2ecf20Sopenharmony_ci hdl->cached = NULL; 23918c2ecf20Sopenharmony_ci hdl->error = 0; 23928c2ecf20Sopenharmony_ci mutex_unlock(hdl->lock); 23938c2ecf20Sopenharmony_ci mutex_destroy(&hdl->_lock); 23948c2ecf20Sopenharmony_ci} 23958c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_handler_free); 23968c2ecf20Sopenharmony_ci 23978c2ecf20Sopenharmony_ci/* For backwards compatibility: V4L2_CID_PRIVATE_BASE should no longer 23988c2ecf20Sopenharmony_ci be used except in G_CTRL, S_CTRL, QUERYCTRL and QUERYMENU when dealing 23998c2ecf20Sopenharmony_ci with applications that do not use the NEXT_CTRL flag. 24008c2ecf20Sopenharmony_ci 24018c2ecf20Sopenharmony_ci We just find the n-th private user control. It's O(N), but that should not 24028c2ecf20Sopenharmony_ci be an issue in this particular case. */ 24038c2ecf20Sopenharmony_cistatic struct v4l2_ctrl_ref *find_private_ref( 24048c2ecf20Sopenharmony_ci struct v4l2_ctrl_handler *hdl, u32 id) 24058c2ecf20Sopenharmony_ci{ 24068c2ecf20Sopenharmony_ci struct v4l2_ctrl_ref *ref; 24078c2ecf20Sopenharmony_ci 24088c2ecf20Sopenharmony_ci id -= V4L2_CID_PRIVATE_BASE; 24098c2ecf20Sopenharmony_ci list_for_each_entry(ref, &hdl->ctrl_refs, node) { 24108c2ecf20Sopenharmony_ci /* Search for private user controls that are compatible with 24118c2ecf20Sopenharmony_ci VIDIOC_G/S_CTRL. */ 24128c2ecf20Sopenharmony_ci if (V4L2_CTRL_ID2WHICH(ref->ctrl->id) == V4L2_CTRL_CLASS_USER && 24138c2ecf20Sopenharmony_ci V4L2_CTRL_DRIVER_PRIV(ref->ctrl->id)) { 24148c2ecf20Sopenharmony_ci if (!ref->ctrl->is_int) 24158c2ecf20Sopenharmony_ci continue; 24168c2ecf20Sopenharmony_ci if (id == 0) 24178c2ecf20Sopenharmony_ci return ref; 24188c2ecf20Sopenharmony_ci id--; 24198c2ecf20Sopenharmony_ci } 24208c2ecf20Sopenharmony_ci } 24218c2ecf20Sopenharmony_ci return NULL; 24228c2ecf20Sopenharmony_ci} 24238c2ecf20Sopenharmony_ci 24248c2ecf20Sopenharmony_ci/* Find a control with the given ID. */ 24258c2ecf20Sopenharmony_cistatic struct v4l2_ctrl_ref *find_ref(struct v4l2_ctrl_handler *hdl, u32 id) 24268c2ecf20Sopenharmony_ci{ 24278c2ecf20Sopenharmony_ci struct v4l2_ctrl_ref *ref; 24288c2ecf20Sopenharmony_ci int bucket; 24298c2ecf20Sopenharmony_ci 24308c2ecf20Sopenharmony_ci id &= V4L2_CTRL_ID_MASK; 24318c2ecf20Sopenharmony_ci 24328c2ecf20Sopenharmony_ci /* Old-style private controls need special handling */ 24338c2ecf20Sopenharmony_ci if (id >= V4L2_CID_PRIVATE_BASE) 24348c2ecf20Sopenharmony_ci return find_private_ref(hdl, id); 24358c2ecf20Sopenharmony_ci bucket = id % hdl->nr_of_buckets; 24368c2ecf20Sopenharmony_ci 24378c2ecf20Sopenharmony_ci /* Simple optimization: cache the last control found */ 24388c2ecf20Sopenharmony_ci if (hdl->cached && hdl->cached->ctrl->id == id) 24398c2ecf20Sopenharmony_ci return hdl->cached; 24408c2ecf20Sopenharmony_ci 24418c2ecf20Sopenharmony_ci /* Not in cache, search the hash */ 24428c2ecf20Sopenharmony_ci ref = hdl->buckets ? hdl->buckets[bucket] : NULL; 24438c2ecf20Sopenharmony_ci while (ref && ref->ctrl->id != id) 24448c2ecf20Sopenharmony_ci ref = ref->next; 24458c2ecf20Sopenharmony_ci 24468c2ecf20Sopenharmony_ci if (ref) 24478c2ecf20Sopenharmony_ci hdl->cached = ref; /* cache it! */ 24488c2ecf20Sopenharmony_ci return ref; 24498c2ecf20Sopenharmony_ci} 24508c2ecf20Sopenharmony_ci 24518c2ecf20Sopenharmony_ci/* Find a control with the given ID. Take the handler's lock first. */ 24528c2ecf20Sopenharmony_cistatic struct v4l2_ctrl_ref *find_ref_lock( 24538c2ecf20Sopenharmony_ci struct v4l2_ctrl_handler *hdl, u32 id) 24548c2ecf20Sopenharmony_ci{ 24558c2ecf20Sopenharmony_ci struct v4l2_ctrl_ref *ref = NULL; 24568c2ecf20Sopenharmony_ci 24578c2ecf20Sopenharmony_ci if (hdl) { 24588c2ecf20Sopenharmony_ci mutex_lock(hdl->lock); 24598c2ecf20Sopenharmony_ci ref = find_ref(hdl, id); 24608c2ecf20Sopenharmony_ci mutex_unlock(hdl->lock); 24618c2ecf20Sopenharmony_ci } 24628c2ecf20Sopenharmony_ci return ref; 24638c2ecf20Sopenharmony_ci} 24648c2ecf20Sopenharmony_ci 24658c2ecf20Sopenharmony_ci/* Find a control with the given ID. */ 24668c2ecf20Sopenharmony_cistruct v4l2_ctrl *v4l2_ctrl_find(struct v4l2_ctrl_handler *hdl, u32 id) 24678c2ecf20Sopenharmony_ci{ 24688c2ecf20Sopenharmony_ci struct v4l2_ctrl_ref *ref = find_ref_lock(hdl, id); 24698c2ecf20Sopenharmony_ci 24708c2ecf20Sopenharmony_ci return ref ? ref->ctrl : NULL; 24718c2ecf20Sopenharmony_ci} 24728c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_find); 24738c2ecf20Sopenharmony_ci 24748c2ecf20Sopenharmony_ci/* Allocate a new v4l2_ctrl_ref and hook it into the handler. */ 24758c2ecf20Sopenharmony_cistatic int handler_new_ref(struct v4l2_ctrl_handler *hdl, 24768c2ecf20Sopenharmony_ci struct v4l2_ctrl *ctrl, 24778c2ecf20Sopenharmony_ci struct v4l2_ctrl_ref **ctrl_ref, 24788c2ecf20Sopenharmony_ci bool from_other_dev, bool allocate_req) 24798c2ecf20Sopenharmony_ci{ 24808c2ecf20Sopenharmony_ci struct v4l2_ctrl_ref *ref; 24818c2ecf20Sopenharmony_ci struct v4l2_ctrl_ref *new_ref; 24828c2ecf20Sopenharmony_ci u32 id = ctrl->id; 24838c2ecf20Sopenharmony_ci u32 class_ctrl = V4L2_CTRL_ID2WHICH(id) | 1; 24848c2ecf20Sopenharmony_ci int bucket = id % hdl->nr_of_buckets; /* which bucket to use */ 24858c2ecf20Sopenharmony_ci unsigned int size_extra_req = 0; 24868c2ecf20Sopenharmony_ci 24878c2ecf20Sopenharmony_ci if (ctrl_ref) 24888c2ecf20Sopenharmony_ci *ctrl_ref = NULL; 24898c2ecf20Sopenharmony_ci 24908c2ecf20Sopenharmony_ci /* 24918c2ecf20Sopenharmony_ci * Automatically add the control class if it is not yet present and 24928c2ecf20Sopenharmony_ci * the new control is not a compound control. 24938c2ecf20Sopenharmony_ci */ 24948c2ecf20Sopenharmony_ci if (ctrl->type < V4L2_CTRL_COMPOUND_TYPES && 24958c2ecf20Sopenharmony_ci id != class_ctrl && find_ref_lock(hdl, class_ctrl) == NULL) 24968c2ecf20Sopenharmony_ci if (!v4l2_ctrl_new_std(hdl, NULL, class_ctrl, 0, 0, 0, 0)) 24978c2ecf20Sopenharmony_ci return hdl->error; 24988c2ecf20Sopenharmony_ci 24998c2ecf20Sopenharmony_ci if (hdl->error) 25008c2ecf20Sopenharmony_ci return hdl->error; 25018c2ecf20Sopenharmony_ci 25028c2ecf20Sopenharmony_ci if (allocate_req) 25038c2ecf20Sopenharmony_ci size_extra_req = ctrl->elems * ctrl->elem_size; 25048c2ecf20Sopenharmony_ci new_ref = kzalloc(sizeof(*new_ref) + size_extra_req, GFP_KERNEL); 25058c2ecf20Sopenharmony_ci if (!new_ref) 25068c2ecf20Sopenharmony_ci return handler_set_err(hdl, -ENOMEM); 25078c2ecf20Sopenharmony_ci new_ref->ctrl = ctrl; 25088c2ecf20Sopenharmony_ci new_ref->from_other_dev = from_other_dev; 25098c2ecf20Sopenharmony_ci if (size_extra_req) 25108c2ecf20Sopenharmony_ci new_ref->p_req.p = &new_ref[1]; 25118c2ecf20Sopenharmony_ci 25128c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&new_ref->node); 25138c2ecf20Sopenharmony_ci 25148c2ecf20Sopenharmony_ci mutex_lock(hdl->lock); 25158c2ecf20Sopenharmony_ci 25168c2ecf20Sopenharmony_ci /* Add immediately at the end of the list if the list is empty, or if 25178c2ecf20Sopenharmony_ci the last element in the list has a lower ID. 25188c2ecf20Sopenharmony_ci This ensures that when elements are added in ascending order the 25198c2ecf20Sopenharmony_ci insertion is an O(1) operation. */ 25208c2ecf20Sopenharmony_ci if (list_empty(&hdl->ctrl_refs) || id > node2id(hdl->ctrl_refs.prev)) { 25218c2ecf20Sopenharmony_ci list_add_tail(&new_ref->node, &hdl->ctrl_refs); 25228c2ecf20Sopenharmony_ci goto insert_in_hash; 25238c2ecf20Sopenharmony_ci } 25248c2ecf20Sopenharmony_ci 25258c2ecf20Sopenharmony_ci /* Find insert position in sorted list */ 25268c2ecf20Sopenharmony_ci list_for_each_entry(ref, &hdl->ctrl_refs, node) { 25278c2ecf20Sopenharmony_ci if (ref->ctrl->id < id) 25288c2ecf20Sopenharmony_ci continue; 25298c2ecf20Sopenharmony_ci /* Don't add duplicates */ 25308c2ecf20Sopenharmony_ci if (ref->ctrl->id == id) { 25318c2ecf20Sopenharmony_ci kfree(new_ref); 25328c2ecf20Sopenharmony_ci goto unlock; 25338c2ecf20Sopenharmony_ci } 25348c2ecf20Sopenharmony_ci list_add(&new_ref->node, ref->node.prev); 25358c2ecf20Sopenharmony_ci break; 25368c2ecf20Sopenharmony_ci } 25378c2ecf20Sopenharmony_ci 25388c2ecf20Sopenharmony_ciinsert_in_hash: 25398c2ecf20Sopenharmony_ci /* Insert the control node in the hash */ 25408c2ecf20Sopenharmony_ci new_ref->next = hdl->buckets[bucket]; 25418c2ecf20Sopenharmony_ci hdl->buckets[bucket] = new_ref; 25428c2ecf20Sopenharmony_ci if (ctrl_ref) 25438c2ecf20Sopenharmony_ci *ctrl_ref = new_ref; 25448c2ecf20Sopenharmony_ci if (ctrl->handler == hdl) { 25458c2ecf20Sopenharmony_ci /* By default each control starts in a cluster of its own. 25468c2ecf20Sopenharmony_ci * new_ref->ctrl is basically a cluster array with one 25478c2ecf20Sopenharmony_ci * element, so that's perfect to use as the cluster pointer. 25488c2ecf20Sopenharmony_ci * But only do this for the handler that owns the control. 25498c2ecf20Sopenharmony_ci */ 25508c2ecf20Sopenharmony_ci ctrl->cluster = &new_ref->ctrl; 25518c2ecf20Sopenharmony_ci ctrl->ncontrols = 1; 25528c2ecf20Sopenharmony_ci } 25538c2ecf20Sopenharmony_ci 25548c2ecf20Sopenharmony_ciunlock: 25558c2ecf20Sopenharmony_ci mutex_unlock(hdl->lock); 25568c2ecf20Sopenharmony_ci return 0; 25578c2ecf20Sopenharmony_ci} 25588c2ecf20Sopenharmony_ci 25598c2ecf20Sopenharmony_ci/* Add a new control */ 25608c2ecf20Sopenharmony_cistatic struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, 25618c2ecf20Sopenharmony_ci const struct v4l2_ctrl_ops *ops, 25628c2ecf20Sopenharmony_ci const struct v4l2_ctrl_type_ops *type_ops, 25638c2ecf20Sopenharmony_ci u32 id, const char *name, enum v4l2_ctrl_type type, 25648c2ecf20Sopenharmony_ci s64 min, s64 max, u64 step, s64 def, 25658c2ecf20Sopenharmony_ci const u32 dims[V4L2_CTRL_MAX_DIMS], u32 elem_size, 25668c2ecf20Sopenharmony_ci u32 flags, const char * const *qmenu, 25678c2ecf20Sopenharmony_ci const s64 *qmenu_int, const union v4l2_ctrl_ptr p_def, 25688c2ecf20Sopenharmony_ci void *priv) 25698c2ecf20Sopenharmony_ci{ 25708c2ecf20Sopenharmony_ci struct v4l2_ctrl *ctrl; 25718c2ecf20Sopenharmony_ci unsigned sz_extra; 25728c2ecf20Sopenharmony_ci unsigned nr_of_dims = 0; 25738c2ecf20Sopenharmony_ci unsigned elems = 1; 25748c2ecf20Sopenharmony_ci bool is_array; 25758c2ecf20Sopenharmony_ci unsigned tot_ctrl_size; 25768c2ecf20Sopenharmony_ci unsigned idx; 25778c2ecf20Sopenharmony_ci void *data; 25788c2ecf20Sopenharmony_ci int err; 25798c2ecf20Sopenharmony_ci 25808c2ecf20Sopenharmony_ci if (hdl->error) 25818c2ecf20Sopenharmony_ci return NULL; 25828c2ecf20Sopenharmony_ci 25838c2ecf20Sopenharmony_ci while (dims && dims[nr_of_dims]) { 25848c2ecf20Sopenharmony_ci elems *= dims[nr_of_dims]; 25858c2ecf20Sopenharmony_ci nr_of_dims++; 25868c2ecf20Sopenharmony_ci if (nr_of_dims == V4L2_CTRL_MAX_DIMS) 25878c2ecf20Sopenharmony_ci break; 25888c2ecf20Sopenharmony_ci } 25898c2ecf20Sopenharmony_ci is_array = nr_of_dims > 0; 25908c2ecf20Sopenharmony_ci 25918c2ecf20Sopenharmony_ci /* Prefill elem_size for all types handled by std_type_ops */ 25928c2ecf20Sopenharmony_ci switch ((u32)type) { 25938c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_INTEGER64: 25948c2ecf20Sopenharmony_ci elem_size = sizeof(s64); 25958c2ecf20Sopenharmony_ci break; 25968c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_STRING: 25978c2ecf20Sopenharmony_ci elem_size = max + 1; 25988c2ecf20Sopenharmony_ci break; 25998c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_U8: 26008c2ecf20Sopenharmony_ci elem_size = sizeof(u8); 26018c2ecf20Sopenharmony_ci break; 26028c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_U16: 26038c2ecf20Sopenharmony_ci elem_size = sizeof(u16); 26048c2ecf20Sopenharmony_ci break; 26058c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_U32: 26068c2ecf20Sopenharmony_ci elem_size = sizeof(u32); 26078c2ecf20Sopenharmony_ci break; 26088c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_MPEG2_SLICE_PARAMS: 26098c2ecf20Sopenharmony_ci elem_size = sizeof(struct v4l2_ctrl_mpeg2_slice_params); 26108c2ecf20Sopenharmony_ci break; 26118c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_MPEG2_QUANTIZATION: 26128c2ecf20Sopenharmony_ci elem_size = sizeof(struct v4l2_ctrl_mpeg2_quantization); 26138c2ecf20Sopenharmony_ci break; 26148c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_FWHT_PARAMS: 26158c2ecf20Sopenharmony_ci elem_size = sizeof(struct v4l2_ctrl_fwht_params); 26168c2ecf20Sopenharmony_ci break; 26178c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_H264_SPS: 26188c2ecf20Sopenharmony_ci elem_size = sizeof(struct v4l2_ctrl_h264_sps); 26198c2ecf20Sopenharmony_ci break; 26208c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_H264_PPS: 26218c2ecf20Sopenharmony_ci elem_size = sizeof(struct v4l2_ctrl_h264_pps); 26228c2ecf20Sopenharmony_ci break; 26238c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_H264_SCALING_MATRIX: 26248c2ecf20Sopenharmony_ci elem_size = sizeof(struct v4l2_ctrl_h264_scaling_matrix); 26258c2ecf20Sopenharmony_ci break; 26268c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_H264_SLICE_PARAMS: 26278c2ecf20Sopenharmony_ci elem_size = sizeof(struct v4l2_ctrl_h264_slice_params); 26288c2ecf20Sopenharmony_ci break; 26298c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_H264_DECODE_PARAMS: 26308c2ecf20Sopenharmony_ci elem_size = sizeof(struct v4l2_ctrl_h264_decode_params); 26318c2ecf20Sopenharmony_ci break; 26328c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_H264_PRED_WEIGHTS: 26338c2ecf20Sopenharmony_ci elem_size = sizeof(struct v4l2_ctrl_h264_pred_weights); 26348c2ecf20Sopenharmony_ci break; 26358c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_VP8_FRAME_HEADER: 26368c2ecf20Sopenharmony_ci elem_size = sizeof(struct v4l2_ctrl_vp8_frame_header); 26378c2ecf20Sopenharmony_ci break; 26388c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_HEVC_SPS: 26398c2ecf20Sopenharmony_ci elem_size = sizeof(struct v4l2_ctrl_hevc_sps); 26408c2ecf20Sopenharmony_ci break; 26418c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_HEVC_PPS: 26428c2ecf20Sopenharmony_ci elem_size = sizeof(struct v4l2_ctrl_hevc_pps); 26438c2ecf20Sopenharmony_ci break; 26448c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS: 26458c2ecf20Sopenharmony_ci elem_size = sizeof(struct v4l2_ctrl_hevc_slice_params); 26468c2ecf20Sopenharmony_ci break; 26478c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_AREA: 26488c2ecf20Sopenharmony_ci elem_size = sizeof(struct v4l2_area); 26498c2ecf20Sopenharmony_ci break; 26508c2ecf20Sopenharmony_ci default: 26518c2ecf20Sopenharmony_ci if (type < V4L2_CTRL_COMPOUND_TYPES) 26528c2ecf20Sopenharmony_ci elem_size = sizeof(s32); 26538c2ecf20Sopenharmony_ci break; 26548c2ecf20Sopenharmony_ci } 26558c2ecf20Sopenharmony_ci tot_ctrl_size = elem_size * elems; 26568c2ecf20Sopenharmony_ci 26578c2ecf20Sopenharmony_ci /* Sanity checks */ 26588c2ecf20Sopenharmony_ci if (id == 0 || name == NULL || !elem_size || 26598c2ecf20Sopenharmony_ci id >= V4L2_CID_PRIVATE_BASE || 26608c2ecf20Sopenharmony_ci (type == V4L2_CTRL_TYPE_MENU && qmenu == NULL) || 26618c2ecf20Sopenharmony_ci (type == V4L2_CTRL_TYPE_INTEGER_MENU && qmenu_int == NULL)) { 26628c2ecf20Sopenharmony_ci handler_set_err(hdl, -ERANGE); 26638c2ecf20Sopenharmony_ci return NULL; 26648c2ecf20Sopenharmony_ci } 26658c2ecf20Sopenharmony_ci err = check_range(type, min, max, step, def); 26668c2ecf20Sopenharmony_ci if (err) { 26678c2ecf20Sopenharmony_ci handler_set_err(hdl, err); 26688c2ecf20Sopenharmony_ci return NULL; 26698c2ecf20Sopenharmony_ci } 26708c2ecf20Sopenharmony_ci if (is_array && 26718c2ecf20Sopenharmony_ci (type == V4L2_CTRL_TYPE_BUTTON || 26728c2ecf20Sopenharmony_ci type == V4L2_CTRL_TYPE_CTRL_CLASS)) { 26738c2ecf20Sopenharmony_ci handler_set_err(hdl, -EINVAL); 26748c2ecf20Sopenharmony_ci return NULL; 26758c2ecf20Sopenharmony_ci } 26768c2ecf20Sopenharmony_ci 26778c2ecf20Sopenharmony_ci sz_extra = 0; 26788c2ecf20Sopenharmony_ci if (type == V4L2_CTRL_TYPE_BUTTON) 26798c2ecf20Sopenharmony_ci flags |= V4L2_CTRL_FLAG_WRITE_ONLY | 26808c2ecf20Sopenharmony_ci V4L2_CTRL_FLAG_EXECUTE_ON_WRITE; 26818c2ecf20Sopenharmony_ci else if (type == V4L2_CTRL_TYPE_CTRL_CLASS) 26828c2ecf20Sopenharmony_ci flags |= V4L2_CTRL_FLAG_READ_ONLY; 26838c2ecf20Sopenharmony_ci else if (type == V4L2_CTRL_TYPE_INTEGER64 || 26848c2ecf20Sopenharmony_ci type == V4L2_CTRL_TYPE_STRING || 26858c2ecf20Sopenharmony_ci type >= V4L2_CTRL_COMPOUND_TYPES || 26868c2ecf20Sopenharmony_ci is_array) 26878c2ecf20Sopenharmony_ci sz_extra += 2 * tot_ctrl_size; 26888c2ecf20Sopenharmony_ci 26898c2ecf20Sopenharmony_ci if (type >= V4L2_CTRL_COMPOUND_TYPES && p_def.p_const) 26908c2ecf20Sopenharmony_ci sz_extra += elem_size; 26918c2ecf20Sopenharmony_ci 26928c2ecf20Sopenharmony_ci ctrl = kvzalloc(sizeof(*ctrl) + sz_extra, GFP_KERNEL); 26938c2ecf20Sopenharmony_ci if (ctrl == NULL) { 26948c2ecf20Sopenharmony_ci handler_set_err(hdl, -ENOMEM); 26958c2ecf20Sopenharmony_ci return NULL; 26968c2ecf20Sopenharmony_ci } 26978c2ecf20Sopenharmony_ci 26988c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&ctrl->node); 26998c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&ctrl->ev_subs); 27008c2ecf20Sopenharmony_ci ctrl->handler = hdl; 27018c2ecf20Sopenharmony_ci ctrl->ops = ops; 27028c2ecf20Sopenharmony_ci ctrl->type_ops = type_ops ? type_ops : &std_type_ops; 27038c2ecf20Sopenharmony_ci ctrl->id = id; 27048c2ecf20Sopenharmony_ci ctrl->name = name; 27058c2ecf20Sopenharmony_ci ctrl->type = type; 27068c2ecf20Sopenharmony_ci ctrl->flags = flags; 27078c2ecf20Sopenharmony_ci ctrl->minimum = min; 27088c2ecf20Sopenharmony_ci ctrl->maximum = max; 27098c2ecf20Sopenharmony_ci ctrl->step = step; 27108c2ecf20Sopenharmony_ci ctrl->default_value = def; 27118c2ecf20Sopenharmony_ci ctrl->is_string = !is_array && type == V4L2_CTRL_TYPE_STRING; 27128c2ecf20Sopenharmony_ci ctrl->is_ptr = is_array || type >= V4L2_CTRL_COMPOUND_TYPES || ctrl->is_string; 27138c2ecf20Sopenharmony_ci ctrl->is_int = !ctrl->is_ptr && type != V4L2_CTRL_TYPE_INTEGER64; 27148c2ecf20Sopenharmony_ci ctrl->is_array = is_array; 27158c2ecf20Sopenharmony_ci ctrl->elems = elems; 27168c2ecf20Sopenharmony_ci ctrl->nr_of_dims = nr_of_dims; 27178c2ecf20Sopenharmony_ci if (nr_of_dims) 27188c2ecf20Sopenharmony_ci memcpy(ctrl->dims, dims, nr_of_dims * sizeof(dims[0])); 27198c2ecf20Sopenharmony_ci ctrl->elem_size = elem_size; 27208c2ecf20Sopenharmony_ci if (type == V4L2_CTRL_TYPE_MENU) 27218c2ecf20Sopenharmony_ci ctrl->qmenu = qmenu; 27228c2ecf20Sopenharmony_ci else if (type == V4L2_CTRL_TYPE_INTEGER_MENU) 27238c2ecf20Sopenharmony_ci ctrl->qmenu_int = qmenu_int; 27248c2ecf20Sopenharmony_ci ctrl->priv = priv; 27258c2ecf20Sopenharmony_ci ctrl->cur.val = ctrl->val = def; 27268c2ecf20Sopenharmony_ci data = &ctrl[1]; 27278c2ecf20Sopenharmony_ci 27288c2ecf20Sopenharmony_ci if (!ctrl->is_int) { 27298c2ecf20Sopenharmony_ci ctrl->p_new.p = data; 27308c2ecf20Sopenharmony_ci ctrl->p_cur.p = data + tot_ctrl_size; 27318c2ecf20Sopenharmony_ci } else { 27328c2ecf20Sopenharmony_ci ctrl->p_new.p = &ctrl->val; 27338c2ecf20Sopenharmony_ci ctrl->p_cur.p = &ctrl->cur.val; 27348c2ecf20Sopenharmony_ci } 27358c2ecf20Sopenharmony_ci 27368c2ecf20Sopenharmony_ci if (type >= V4L2_CTRL_COMPOUND_TYPES && p_def.p_const) { 27378c2ecf20Sopenharmony_ci ctrl->p_def.p = ctrl->p_cur.p + tot_ctrl_size; 27388c2ecf20Sopenharmony_ci memcpy(ctrl->p_def.p, p_def.p_const, elem_size); 27398c2ecf20Sopenharmony_ci } 27408c2ecf20Sopenharmony_ci 27418c2ecf20Sopenharmony_ci for (idx = 0; idx < elems; idx++) { 27428c2ecf20Sopenharmony_ci ctrl->type_ops->init(ctrl, idx, ctrl->p_cur); 27438c2ecf20Sopenharmony_ci ctrl->type_ops->init(ctrl, idx, ctrl->p_new); 27448c2ecf20Sopenharmony_ci } 27458c2ecf20Sopenharmony_ci 27468c2ecf20Sopenharmony_ci if (handler_new_ref(hdl, ctrl, NULL, false, false)) { 27478c2ecf20Sopenharmony_ci kvfree(ctrl); 27488c2ecf20Sopenharmony_ci return NULL; 27498c2ecf20Sopenharmony_ci } 27508c2ecf20Sopenharmony_ci mutex_lock(hdl->lock); 27518c2ecf20Sopenharmony_ci list_add_tail(&ctrl->node, &hdl->ctrls); 27528c2ecf20Sopenharmony_ci mutex_unlock(hdl->lock); 27538c2ecf20Sopenharmony_ci return ctrl; 27548c2ecf20Sopenharmony_ci} 27558c2ecf20Sopenharmony_ci 27568c2ecf20Sopenharmony_cistruct v4l2_ctrl *v4l2_ctrl_new_custom(struct v4l2_ctrl_handler *hdl, 27578c2ecf20Sopenharmony_ci const struct v4l2_ctrl_config *cfg, void *priv) 27588c2ecf20Sopenharmony_ci{ 27598c2ecf20Sopenharmony_ci bool is_menu; 27608c2ecf20Sopenharmony_ci struct v4l2_ctrl *ctrl; 27618c2ecf20Sopenharmony_ci const char *name = cfg->name; 27628c2ecf20Sopenharmony_ci const char * const *qmenu = cfg->qmenu; 27638c2ecf20Sopenharmony_ci const s64 *qmenu_int = cfg->qmenu_int; 27648c2ecf20Sopenharmony_ci enum v4l2_ctrl_type type = cfg->type; 27658c2ecf20Sopenharmony_ci u32 flags = cfg->flags; 27668c2ecf20Sopenharmony_ci s64 min = cfg->min; 27678c2ecf20Sopenharmony_ci s64 max = cfg->max; 27688c2ecf20Sopenharmony_ci u64 step = cfg->step; 27698c2ecf20Sopenharmony_ci s64 def = cfg->def; 27708c2ecf20Sopenharmony_ci 27718c2ecf20Sopenharmony_ci if (name == NULL) 27728c2ecf20Sopenharmony_ci v4l2_ctrl_fill(cfg->id, &name, &type, &min, &max, &step, 27738c2ecf20Sopenharmony_ci &def, &flags); 27748c2ecf20Sopenharmony_ci 27758c2ecf20Sopenharmony_ci is_menu = (type == V4L2_CTRL_TYPE_MENU || 27768c2ecf20Sopenharmony_ci type == V4L2_CTRL_TYPE_INTEGER_MENU); 27778c2ecf20Sopenharmony_ci if (is_menu) 27788c2ecf20Sopenharmony_ci WARN_ON(step); 27798c2ecf20Sopenharmony_ci else 27808c2ecf20Sopenharmony_ci WARN_ON(cfg->menu_skip_mask); 27818c2ecf20Sopenharmony_ci if (type == V4L2_CTRL_TYPE_MENU && !qmenu) { 27828c2ecf20Sopenharmony_ci qmenu = v4l2_ctrl_get_menu(cfg->id); 27838c2ecf20Sopenharmony_ci } else if (type == V4L2_CTRL_TYPE_INTEGER_MENU && !qmenu_int) { 27848c2ecf20Sopenharmony_ci handler_set_err(hdl, -EINVAL); 27858c2ecf20Sopenharmony_ci return NULL; 27868c2ecf20Sopenharmony_ci } 27878c2ecf20Sopenharmony_ci 27888c2ecf20Sopenharmony_ci ctrl = v4l2_ctrl_new(hdl, cfg->ops, cfg->type_ops, cfg->id, name, 27898c2ecf20Sopenharmony_ci type, min, max, 27908c2ecf20Sopenharmony_ci is_menu ? cfg->menu_skip_mask : step, def, 27918c2ecf20Sopenharmony_ci cfg->dims, cfg->elem_size, 27928c2ecf20Sopenharmony_ci flags, qmenu, qmenu_int, cfg->p_def, priv); 27938c2ecf20Sopenharmony_ci if (ctrl) 27948c2ecf20Sopenharmony_ci ctrl->is_private = cfg->is_private; 27958c2ecf20Sopenharmony_ci return ctrl; 27968c2ecf20Sopenharmony_ci} 27978c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_new_custom); 27988c2ecf20Sopenharmony_ci 27998c2ecf20Sopenharmony_ci/* Helper function for standard non-menu controls */ 28008c2ecf20Sopenharmony_cistruct v4l2_ctrl *v4l2_ctrl_new_std(struct v4l2_ctrl_handler *hdl, 28018c2ecf20Sopenharmony_ci const struct v4l2_ctrl_ops *ops, 28028c2ecf20Sopenharmony_ci u32 id, s64 min, s64 max, u64 step, s64 def) 28038c2ecf20Sopenharmony_ci{ 28048c2ecf20Sopenharmony_ci const char *name; 28058c2ecf20Sopenharmony_ci enum v4l2_ctrl_type type; 28068c2ecf20Sopenharmony_ci u32 flags; 28078c2ecf20Sopenharmony_ci 28088c2ecf20Sopenharmony_ci v4l2_ctrl_fill(id, &name, &type, &min, &max, &step, &def, &flags); 28098c2ecf20Sopenharmony_ci if (type == V4L2_CTRL_TYPE_MENU || 28108c2ecf20Sopenharmony_ci type == V4L2_CTRL_TYPE_INTEGER_MENU || 28118c2ecf20Sopenharmony_ci type >= V4L2_CTRL_COMPOUND_TYPES) { 28128c2ecf20Sopenharmony_ci handler_set_err(hdl, -EINVAL); 28138c2ecf20Sopenharmony_ci return NULL; 28148c2ecf20Sopenharmony_ci } 28158c2ecf20Sopenharmony_ci return v4l2_ctrl_new(hdl, ops, NULL, id, name, type, 28168c2ecf20Sopenharmony_ci min, max, step, def, NULL, 0, 28178c2ecf20Sopenharmony_ci flags, NULL, NULL, ptr_null, NULL); 28188c2ecf20Sopenharmony_ci} 28198c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_new_std); 28208c2ecf20Sopenharmony_ci 28218c2ecf20Sopenharmony_ci/* Helper function for standard menu controls */ 28228c2ecf20Sopenharmony_cistruct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl, 28238c2ecf20Sopenharmony_ci const struct v4l2_ctrl_ops *ops, 28248c2ecf20Sopenharmony_ci u32 id, u8 _max, u64 mask, u8 _def) 28258c2ecf20Sopenharmony_ci{ 28268c2ecf20Sopenharmony_ci const char * const *qmenu = NULL; 28278c2ecf20Sopenharmony_ci const s64 *qmenu_int = NULL; 28288c2ecf20Sopenharmony_ci unsigned int qmenu_int_len = 0; 28298c2ecf20Sopenharmony_ci const char *name; 28308c2ecf20Sopenharmony_ci enum v4l2_ctrl_type type; 28318c2ecf20Sopenharmony_ci s64 min; 28328c2ecf20Sopenharmony_ci s64 max = _max; 28338c2ecf20Sopenharmony_ci s64 def = _def; 28348c2ecf20Sopenharmony_ci u64 step; 28358c2ecf20Sopenharmony_ci u32 flags; 28368c2ecf20Sopenharmony_ci 28378c2ecf20Sopenharmony_ci v4l2_ctrl_fill(id, &name, &type, &min, &max, &step, &def, &flags); 28388c2ecf20Sopenharmony_ci 28398c2ecf20Sopenharmony_ci if (type == V4L2_CTRL_TYPE_MENU) 28408c2ecf20Sopenharmony_ci qmenu = v4l2_ctrl_get_menu(id); 28418c2ecf20Sopenharmony_ci else if (type == V4L2_CTRL_TYPE_INTEGER_MENU) 28428c2ecf20Sopenharmony_ci qmenu_int = v4l2_ctrl_get_int_menu(id, &qmenu_int_len); 28438c2ecf20Sopenharmony_ci 28448c2ecf20Sopenharmony_ci if ((!qmenu && !qmenu_int) || (qmenu_int && max > qmenu_int_len)) { 28458c2ecf20Sopenharmony_ci handler_set_err(hdl, -EINVAL); 28468c2ecf20Sopenharmony_ci return NULL; 28478c2ecf20Sopenharmony_ci } 28488c2ecf20Sopenharmony_ci return v4l2_ctrl_new(hdl, ops, NULL, id, name, type, 28498c2ecf20Sopenharmony_ci 0, max, mask, def, NULL, 0, 28508c2ecf20Sopenharmony_ci flags, qmenu, qmenu_int, ptr_null, NULL); 28518c2ecf20Sopenharmony_ci} 28528c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_new_std_menu); 28538c2ecf20Sopenharmony_ci 28548c2ecf20Sopenharmony_ci/* Helper function for standard menu controls with driver defined menu */ 28558c2ecf20Sopenharmony_cistruct v4l2_ctrl *v4l2_ctrl_new_std_menu_items(struct v4l2_ctrl_handler *hdl, 28568c2ecf20Sopenharmony_ci const struct v4l2_ctrl_ops *ops, u32 id, u8 _max, 28578c2ecf20Sopenharmony_ci u64 mask, u8 _def, const char * const *qmenu) 28588c2ecf20Sopenharmony_ci{ 28598c2ecf20Sopenharmony_ci enum v4l2_ctrl_type type; 28608c2ecf20Sopenharmony_ci const char *name; 28618c2ecf20Sopenharmony_ci u32 flags; 28628c2ecf20Sopenharmony_ci u64 step; 28638c2ecf20Sopenharmony_ci s64 min; 28648c2ecf20Sopenharmony_ci s64 max = _max; 28658c2ecf20Sopenharmony_ci s64 def = _def; 28668c2ecf20Sopenharmony_ci 28678c2ecf20Sopenharmony_ci /* v4l2_ctrl_new_std_menu_items() should only be called for 28688c2ecf20Sopenharmony_ci * standard controls without a standard menu. 28698c2ecf20Sopenharmony_ci */ 28708c2ecf20Sopenharmony_ci if (v4l2_ctrl_get_menu(id)) { 28718c2ecf20Sopenharmony_ci handler_set_err(hdl, -EINVAL); 28728c2ecf20Sopenharmony_ci return NULL; 28738c2ecf20Sopenharmony_ci } 28748c2ecf20Sopenharmony_ci 28758c2ecf20Sopenharmony_ci v4l2_ctrl_fill(id, &name, &type, &min, &max, &step, &def, &flags); 28768c2ecf20Sopenharmony_ci if (type != V4L2_CTRL_TYPE_MENU || qmenu == NULL) { 28778c2ecf20Sopenharmony_ci handler_set_err(hdl, -EINVAL); 28788c2ecf20Sopenharmony_ci return NULL; 28798c2ecf20Sopenharmony_ci } 28808c2ecf20Sopenharmony_ci return v4l2_ctrl_new(hdl, ops, NULL, id, name, type, 28818c2ecf20Sopenharmony_ci 0, max, mask, def, NULL, 0, 28828c2ecf20Sopenharmony_ci flags, qmenu, NULL, ptr_null, NULL); 28838c2ecf20Sopenharmony_ci 28848c2ecf20Sopenharmony_ci} 28858c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_new_std_menu_items); 28868c2ecf20Sopenharmony_ci 28878c2ecf20Sopenharmony_ci/* Helper function for standard compound controls */ 28888c2ecf20Sopenharmony_cistruct v4l2_ctrl *v4l2_ctrl_new_std_compound(struct v4l2_ctrl_handler *hdl, 28898c2ecf20Sopenharmony_ci const struct v4l2_ctrl_ops *ops, u32 id, 28908c2ecf20Sopenharmony_ci const union v4l2_ctrl_ptr p_def) 28918c2ecf20Sopenharmony_ci{ 28928c2ecf20Sopenharmony_ci const char *name; 28938c2ecf20Sopenharmony_ci enum v4l2_ctrl_type type; 28948c2ecf20Sopenharmony_ci u32 flags; 28958c2ecf20Sopenharmony_ci s64 min, max, step, def; 28968c2ecf20Sopenharmony_ci 28978c2ecf20Sopenharmony_ci v4l2_ctrl_fill(id, &name, &type, &min, &max, &step, &def, &flags); 28988c2ecf20Sopenharmony_ci if (type < V4L2_CTRL_COMPOUND_TYPES) { 28998c2ecf20Sopenharmony_ci handler_set_err(hdl, -EINVAL); 29008c2ecf20Sopenharmony_ci return NULL; 29018c2ecf20Sopenharmony_ci } 29028c2ecf20Sopenharmony_ci return v4l2_ctrl_new(hdl, ops, NULL, id, name, type, 29038c2ecf20Sopenharmony_ci min, max, step, def, NULL, 0, 29048c2ecf20Sopenharmony_ci flags, NULL, NULL, p_def, NULL); 29058c2ecf20Sopenharmony_ci} 29068c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_new_std_compound); 29078c2ecf20Sopenharmony_ci 29088c2ecf20Sopenharmony_ci/* Helper function for standard integer menu controls */ 29098c2ecf20Sopenharmony_cistruct v4l2_ctrl *v4l2_ctrl_new_int_menu(struct v4l2_ctrl_handler *hdl, 29108c2ecf20Sopenharmony_ci const struct v4l2_ctrl_ops *ops, 29118c2ecf20Sopenharmony_ci u32 id, u8 _max, u8 _def, const s64 *qmenu_int) 29128c2ecf20Sopenharmony_ci{ 29138c2ecf20Sopenharmony_ci const char *name; 29148c2ecf20Sopenharmony_ci enum v4l2_ctrl_type type; 29158c2ecf20Sopenharmony_ci s64 min; 29168c2ecf20Sopenharmony_ci u64 step; 29178c2ecf20Sopenharmony_ci s64 max = _max; 29188c2ecf20Sopenharmony_ci s64 def = _def; 29198c2ecf20Sopenharmony_ci u32 flags; 29208c2ecf20Sopenharmony_ci 29218c2ecf20Sopenharmony_ci v4l2_ctrl_fill(id, &name, &type, &min, &max, &step, &def, &flags); 29228c2ecf20Sopenharmony_ci if (type != V4L2_CTRL_TYPE_INTEGER_MENU) { 29238c2ecf20Sopenharmony_ci handler_set_err(hdl, -EINVAL); 29248c2ecf20Sopenharmony_ci return NULL; 29258c2ecf20Sopenharmony_ci } 29268c2ecf20Sopenharmony_ci return v4l2_ctrl_new(hdl, ops, NULL, id, name, type, 29278c2ecf20Sopenharmony_ci 0, max, 0, def, NULL, 0, 29288c2ecf20Sopenharmony_ci flags, NULL, qmenu_int, ptr_null, NULL); 29298c2ecf20Sopenharmony_ci} 29308c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_new_int_menu); 29318c2ecf20Sopenharmony_ci 29328c2ecf20Sopenharmony_ci/* Add the controls from another handler to our own. */ 29338c2ecf20Sopenharmony_ciint v4l2_ctrl_add_handler(struct v4l2_ctrl_handler *hdl, 29348c2ecf20Sopenharmony_ci struct v4l2_ctrl_handler *add, 29358c2ecf20Sopenharmony_ci bool (*filter)(const struct v4l2_ctrl *ctrl), 29368c2ecf20Sopenharmony_ci bool from_other_dev) 29378c2ecf20Sopenharmony_ci{ 29388c2ecf20Sopenharmony_ci struct v4l2_ctrl_ref *ref; 29398c2ecf20Sopenharmony_ci int ret = 0; 29408c2ecf20Sopenharmony_ci 29418c2ecf20Sopenharmony_ci /* Do nothing if either handler is NULL or if they are the same */ 29428c2ecf20Sopenharmony_ci if (!hdl || !add || hdl == add) 29438c2ecf20Sopenharmony_ci return 0; 29448c2ecf20Sopenharmony_ci if (hdl->error) 29458c2ecf20Sopenharmony_ci return hdl->error; 29468c2ecf20Sopenharmony_ci mutex_lock(add->lock); 29478c2ecf20Sopenharmony_ci list_for_each_entry(ref, &add->ctrl_refs, node) { 29488c2ecf20Sopenharmony_ci struct v4l2_ctrl *ctrl = ref->ctrl; 29498c2ecf20Sopenharmony_ci 29508c2ecf20Sopenharmony_ci /* Skip handler-private controls. */ 29518c2ecf20Sopenharmony_ci if (ctrl->is_private) 29528c2ecf20Sopenharmony_ci continue; 29538c2ecf20Sopenharmony_ci /* And control classes */ 29548c2ecf20Sopenharmony_ci if (ctrl->type == V4L2_CTRL_TYPE_CTRL_CLASS) 29558c2ecf20Sopenharmony_ci continue; 29568c2ecf20Sopenharmony_ci /* Filter any unwanted controls */ 29578c2ecf20Sopenharmony_ci if (filter && !filter(ctrl)) 29588c2ecf20Sopenharmony_ci continue; 29598c2ecf20Sopenharmony_ci ret = handler_new_ref(hdl, ctrl, NULL, from_other_dev, false); 29608c2ecf20Sopenharmony_ci if (ret) 29618c2ecf20Sopenharmony_ci break; 29628c2ecf20Sopenharmony_ci } 29638c2ecf20Sopenharmony_ci mutex_unlock(add->lock); 29648c2ecf20Sopenharmony_ci return ret; 29658c2ecf20Sopenharmony_ci} 29668c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_add_handler); 29678c2ecf20Sopenharmony_ci 29688c2ecf20Sopenharmony_cibool v4l2_ctrl_radio_filter(const struct v4l2_ctrl *ctrl) 29698c2ecf20Sopenharmony_ci{ 29708c2ecf20Sopenharmony_ci if (V4L2_CTRL_ID2WHICH(ctrl->id) == V4L2_CTRL_CLASS_FM_TX) 29718c2ecf20Sopenharmony_ci return true; 29728c2ecf20Sopenharmony_ci if (V4L2_CTRL_ID2WHICH(ctrl->id) == V4L2_CTRL_CLASS_FM_RX) 29738c2ecf20Sopenharmony_ci return true; 29748c2ecf20Sopenharmony_ci switch (ctrl->id) { 29758c2ecf20Sopenharmony_ci case V4L2_CID_AUDIO_MUTE: 29768c2ecf20Sopenharmony_ci case V4L2_CID_AUDIO_VOLUME: 29778c2ecf20Sopenharmony_ci case V4L2_CID_AUDIO_BALANCE: 29788c2ecf20Sopenharmony_ci case V4L2_CID_AUDIO_BASS: 29798c2ecf20Sopenharmony_ci case V4L2_CID_AUDIO_TREBLE: 29808c2ecf20Sopenharmony_ci case V4L2_CID_AUDIO_LOUDNESS: 29818c2ecf20Sopenharmony_ci return true; 29828c2ecf20Sopenharmony_ci default: 29838c2ecf20Sopenharmony_ci break; 29848c2ecf20Sopenharmony_ci } 29858c2ecf20Sopenharmony_ci return false; 29868c2ecf20Sopenharmony_ci} 29878c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_radio_filter); 29888c2ecf20Sopenharmony_ci 29898c2ecf20Sopenharmony_ci/* Cluster controls */ 29908c2ecf20Sopenharmony_civoid v4l2_ctrl_cluster(unsigned ncontrols, struct v4l2_ctrl **controls) 29918c2ecf20Sopenharmony_ci{ 29928c2ecf20Sopenharmony_ci bool has_volatiles = false; 29938c2ecf20Sopenharmony_ci int i; 29948c2ecf20Sopenharmony_ci 29958c2ecf20Sopenharmony_ci /* The first control is the master control and it must not be NULL */ 29968c2ecf20Sopenharmony_ci if (WARN_ON(ncontrols == 0 || controls[0] == NULL)) 29978c2ecf20Sopenharmony_ci return; 29988c2ecf20Sopenharmony_ci 29998c2ecf20Sopenharmony_ci for (i = 0; i < ncontrols; i++) { 30008c2ecf20Sopenharmony_ci if (controls[i]) { 30018c2ecf20Sopenharmony_ci controls[i]->cluster = controls; 30028c2ecf20Sopenharmony_ci controls[i]->ncontrols = ncontrols; 30038c2ecf20Sopenharmony_ci if (controls[i]->flags & V4L2_CTRL_FLAG_VOLATILE) 30048c2ecf20Sopenharmony_ci has_volatiles = true; 30058c2ecf20Sopenharmony_ci } 30068c2ecf20Sopenharmony_ci } 30078c2ecf20Sopenharmony_ci controls[0]->has_volatiles = has_volatiles; 30088c2ecf20Sopenharmony_ci} 30098c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_cluster); 30108c2ecf20Sopenharmony_ci 30118c2ecf20Sopenharmony_civoid v4l2_ctrl_auto_cluster(unsigned ncontrols, struct v4l2_ctrl **controls, 30128c2ecf20Sopenharmony_ci u8 manual_val, bool set_volatile) 30138c2ecf20Sopenharmony_ci{ 30148c2ecf20Sopenharmony_ci struct v4l2_ctrl *master = controls[0]; 30158c2ecf20Sopenharmony_ci u32 flag = 0; 30168c2ecf20Sopenharmony_ci int i; 30178c2ecf20Sopenharmony_ci 30188c2ecf20Sopenharmony_ci v4l2_ctrl_cluster(ncontrols, controls); 30198c2ecf20Sopenharmony_ci WARN_ON(ncontrols <= 1); 30208c2ecf20Sopenharmony_ci WARN_ON(manual_val < master->minimum || manual_val > master->maximum); 30218c2ecf20Sopenharmony_ci WARN_ON(set_volatile && !has_op(master, g_volatile_ctrl)); 30228c2ecf20Sopenharmony_ci master->is_auto = true; 30238c2ecf20Sopenharmony_ci master->has_volatiles = set_volatile; 30248c2ecf20Sopenharmony_ci master->manual_mode_value = manual_val; 30258c2ecf20Sopenharmony_ci master->flags |= V4L2_CTRL_FLAG_UPDATE; 30268c2ecf20Sopenharmony_ci 30278c2ecf20Sopenharmony_ci if (!is_cur_manual(master)) 30288c2ecf20Sopenharmony_ci flag = V4L2_CTRL_FLAG_INACTIVE | 30298c2ecf20Sopenharmony_ci (set_volatile ? V4L2_CTRL_FLAG_VOLATILE : 0); 30308c2ecf20Sopenharmony_ci 30318c2ecf20Sopenharmony_ci for (i = 1; i < ncontrols; i++) 30328c2ecf20Sopenharmony_ci if (controls[i]) 30338c2ecf20Sopenharmony_ci controls[i]->flags |= flag; 30348c2ecf20Sopenharmony_ci} 30358c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_auto_cluster); 30368c2ecf20Sopenharmony_ci 30378c2ecf20Sopenharmony_ci/* Activate/deactivate a control. */ 30388c2ecf20Sopenharmony_civoid v4l2_ctrl_activate(struct v4l2_ctrl *ctrl, bool active) 30398c2ecf20Sopenharmony_ci{ 30408c2ecf20Sopenharmony_ci /* invert since the actual flag is called 'inactive' */ 30418c2ecf20Sopenharmony_ci bool inactive = !active; 30428c2ecf20Sopenharmony_ci bool old; 30438c2ecf20Sopenharmony_ci 30448c2ecf20Sopenharmony_ci if (ctrl == NULL) 30458c2ecf20Sopenharmony_ci return; 30468c2ecf20Sopenharmony_ci 30478c2ecf20Sopenharmony_ci if (inactive) 30488c2ecf20Sopenharmony_ci /* set V4L2_CTRL_FLAG_INACTIVE */ 30498c2ecf20Sopenharmony_ci old = test_and_set_bit(4, &ctrl->flags); 30508c2ecf20Sopenharmony_ci else 30518c2ecf20Sopenharmony_ci /* clear V4L2_CTRL_FLAG_INACTIVE */ 30528c2ecf20Sopenharmony_ci old = test_and_clear_bit(4, &ctrl->flags); 30538c2ecf20Sopenharmony_ci if (old != inactive) 30548c2ecf20Sopenharmony_ci send_event(NULL, ctrl, V4L2_EVENT_CTRL_CH_FLAGS); 30558c2ecf20Sopenharmony_ci} 30568c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_activate); 30578c2ecf20Sopenharmony_ci 30588c2ecf20Sopenharmony_civoid __v4l2_ctrl_grab(struct v4l2_ctrl *ctrl, bool grabbed) 30598c2ecf20Sopenharmony_ci{ 30608c2ecf20Sopenharmony_ci bool old; 30618c2ecf20Sopenharmony_ci 30628c2ecf20Sopenharmony_ci if (ctrl == NULL) 30638c2ecf20Sopenharmony_ci return; 30648c2ecf20Sopenharmony_ci 30658c2ecf20Sopenharmony_ci lockdep_assert_held(ctrl->handler->lock); 30668c2ecf20Sopenharmony_ci 30678c2ecf20Sopenharmony_ci if (grabbed) 30688c2ecf20Sopenharmony_ci /* set V4L2_CTRL_FLAG_GRABBED */ 30698c2ecf20Sopenharmony_ci old = test_and_set_bit(1, &ctrl->flags); 30708c2ecf20Sopenharmony_ci else 30718c2ecf20Sopenharmony_ci /* clear V4L2_CTRL_FLAG_GRABBED */ 30728c2ecf20Sopenharmony_ci old = test_and_clear_bit(1, &ctrl->flags); 30738c2ecf20Sopenharmony_ci if (old != grabbed) 30748c2ecf20Sopenharmony_ci send_event(NULL, ctrl, V4L2_EVENT_CTRL_CH_FLAGS); 30758c2ecf20Sopenharmony_ci} 30768c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__v4l2_ctrl_grab); 30778c2ecf20Sopenharmony_ci 30788c2ecf20Sopenharmony_ci/* Log the control name and value */ 30798c2ecf20Sopenharmony_cistatic void log_ctrl(const struct v4l2_ctrl *ctrl, 30808c2ecf20Sopenharmony_ci const char *prefix, const char *colon) 30818c2ecf20Sopenharmony_ci{ 30828c2ecf20Sopenharmony_ci if (ctrl->flags & (V4L2_CTRL_FLAG_DISABLED | V4L2_CTRL_FLAG_WRITE_ONLY)) 30838c2ecf20Sopenharmony_ci return; 30848c2ecf20Sopenharmony_ci if (ctrl->type == V4L2_CTRL_TYPE_CTRL_CLASS) 30858c2ecf20Sopenharmony_ci return; 30868c2ecf20Sopenharmony_ci 30878c2ecf20Sopenharmony_ci pr_info("%s%s%s: ", prefix, colon, ctrl->name); 30888c2ecf20Sopenharmony_ci 30898c2ecf20Sopenharmony_ci ctrl->type_ops->log(ctrl); 30908c2ecf20Sopenharmony_ci 30918c2ecf20Sopenharmony_ci if (ctrl->flags & (V4L2_CTRL_FLAG_INACTIVE | 30928c2ecf20Sopenharmony_ci V4L2_CTRL_FLAG_GRABBED | 30938c2ecf20Sopenharmony_ci V4L2_CTRL_FLAG_VOLATILE)) { 30948c2ecf20Sopenharmony_ci if (ctrl->flags & V4L2_CTRL_FLAG_INACTIVE) 30958c2ecf20Sopenharmony_ci pr_cont(" inactive"); 30968c2ecf20Sopenharmony_ci if (ctrl->flags & V4L2_CTRL_FLAG_GRABBED) 30978c2ecf20Sopenharmony_ci pr_cont(" grabbed"); 30988c2ecf20Sopenharmony_ci if (ctrl->flags & V4L2_CTRL_FLAG_VOLATILE) 30998c2ecf20Sopenharmony_ci pr_cont(" volatile"); 31008c2ecf20Sopenharmony_ci } 31018c2ecf20Sopenharmony_ci pr_cont("\n"); 31028c2ecf20Sopenharmony_ci} 31038c2ecf20Sopenharmony_ci 31048c2ecf20Sopenharmony_ci/* Log all controls owned by the handler */ 31058c2ecf20Sopenharmony_civoid v4l2_ctrl_handler_log_status(struct v4l2_ctrl_handler *hdl, 31068c2ecf20Sopenharmony_ci const char *prefix) 31078c2ecf20Sopenharmony_ci{ 31088c2ecf20Sopenharmony_ci struct v4l2_ctrl *ctrl; 31098c2ecf20Sopenharmony_ci const char *colon = ""; 31108c2ecf20Sopenharmony_ci int len; 31118c2ecf20Sopenharmony_ci 31128c2ecf20Sopenharmony_ci if (hdl == NULL) 31138c2ecf20Sopenharmony_ci return; 31148c2ecf20Sopenharmony_ci if (prefix == NULL) 31158c2ecf20Sopenharmony_ci prefix = ""; 31168c2ecf20Sopenharmony_ci len = strlen(prefix); 31178c2ecf20Sopenharmony_ci if (len && prefix[len - 1] != ' ') 31188c2ecf20Sopenharmony_ci colon = ": "; 31198c2ecf20Sopenharmony_ci mutex_lock(hdl->lock); 31208c2ecf20Sopenharmony_ci list_for_each_entry(ctrl, &hdl->ctrls, node) 31218c2ecf20Sopenharmony_ci if (!(ctrl->flags & V4L2_CTRL_FLAG_DISABLED)) 31228c2ecf20Sopenharmony_ci log_ctrl(ctrl, prefix, colon); 31238c2ecf20Sopenharmony_ci mutex_unlock(hdl->lock); 31248c2ecf20Sopenharmony_ci} 31258c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_handler_log_status); 31268c2ecf20Sopenharmony_ci 31278c2ecf20Sopenharmony_ciint v4l2_ctrl_subdev_log_status(struct v4l2_subdev *sd) 31288c2ecf20Sopenharmony_ci{ 31298c2ecf20Sopenharmony_ci v4l2_ctrl_handler_log_status(sd->ctrl_handler, sd->name); 31308c2ecf20Sopenharmony_ci return 0; 31318c2ecf20Sopenharmony_ci} 31328c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_subdev_log_status); 31338c2ecf20Sopenharmony_ci 31348c2ecf20Sopenharmony_ci/* Call s_ctrl for all controls owned by the handler */ 31358c2ecf20Sopenharmony_ciint __v4l2_ctrl_handler_setup(struct v4l2_ctrl_handler *hdl) 31368c2ecf20Sopenharmony_ci{ 31378c2ecf20Sopenharmony_ci struct v4l2_ctrl *ctrl; 31388c2ecf20Sopenharmony_ci int ret = 0; 31398c2ecf20Sopenharmony_ci 31408c2ecf20Sopenharmony_ci if (hdl == NULL) 31418c2ecf20Sopenharmony_ci return 0; 31428c2ecf20Sopenharmony_ci 31438c2ecf20Sopenharmony_ci lockdep_assert_held(hdl->lock); 31448c2ecf20Sopenharmony_ci 31458c2ecf20Sopenharmony_ci list_for_each_entry(ctrl, &hdl->ctrls, node) 31468c2ecf20Sopenharmony_ci ctrl->done = false; 31478c2ecf20Sopenharmony_ci 31488c2ecf20Sopenharmony_ci list_for_each_entry(ctrl, &hdl->ctrls, node) { 31498c2ecf20Sopenharmony_ci struct v4l2_ctrl *master = ctrl->cluster[0]; 31508c2ecf20Sopenharmony_ci int i; 31518c2ecf20Sopenharmony_ci 31528c2ecf20Sopenharmony_ci /* Skip if this control was already handled by a cluster. */ 31538c2ecf20Sopenharmony_ci /* Skip button controls and read-only controls. */ 31548c2ecf20Sopenharmony_ci if (ctrl->done || ctrl->type == V4L2_CTRL_TYPE_BUTTON || 31558c2ecf20Sopenharmony_ci (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY)) 31568c2ecf20Sopenharmony_ci continue; 31578c2ecf20Sopenharmony_ci 31588c2ecf20Sopenharmony_ci for (i = 0; i < master->ncontrols; i++) { 31598c2ecf20Sopenharmony_ci if (master->cluster[i]) { 31608c2ecf20Sopenharmony_ci cur_to_new(master->cluster[i]); 31618c2ecf20Sopenharmony_ci master->cluster[i]->is_new = 1; 31628c2ecf20Sopenharmony_ci master->cluster[i]->done = true; 31638c2ecf20Sopenharmony_ci } 31648c2ecf20Sopenharmony_ci } 31658c2ecf20Sopenharmony_ci ret = call_op(master, s_ctrl); 31668c2ecf20Sopenharmony_ci if (ret) 31678c2ecf20Sopenharmony_ci break; 31688c2ecf20Sopenharmony_ci } 31698c2ecf20Sopenharmony_ci 31708c2ecf20Sopenharmony_ci return ret; 31718c2ecf20Sopenharmony_ci} 31728c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(__v4l2_ctrl_handler_setup); 31738c2ecf20Sopenharmony_ci 31748c2ecf20Sopenharmony_ciint v4l2_ctrl_handler_setup(struct v4l2_ctrl_handler *hdl) 31758c2ecf20Sopenharmony_ci{ 31768c2ecf20Sopenharmony_ci int ret; 31778c2ecf20Sopenharmony_ci 31788c2ecf20Sopenharmony_ci if (hdl == NULL) 31798c2ecf20Sopenharmony_ci return 0; 31808c2ecf20Sopenharmony_ci 31818c2ecf20Sopenharmony_ci mutex_lock(hdl->lock); 31828c2ecf20Sopenharmony_ci ret = __v4l2_ctrl_handler_setup(hdl); 31838c2ecf20Sopenharmony_ci mutex_unlock(hdl->lock); 31848c2ecf20Sopenharmony_ci 31858c2ecf20Sopenharmony_ci return ret; 31868c2ecf20Sopenharmony_ci} 31878c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_handler_setup); 31888c2ecf20Sopenharmony_ci 31898c2ecf20Sopenharmony_ci/* Implement VIDIOC_QUERY_EXT_CTRL */ 31908c2ecf20Sopenharmony_ciint v4l2_query_ext_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_query_ext_ctrl *qc) 31918c2ecf20Sopenharmony_ci{ 31928c2ecf20Sopenharmony_ci const unsigned next_flags = V4L2_CTRL_FLAG_NEXT_CTRL | V4L2_CTRL_FLAG_NEXT_COMPOUND; 31938c2ecf20Sopenharmony_ci u32 id = qc->id & V4L2_CTRL_ID_MASK; 31948c2ecf20Sopenharmony_ci struct v4l2_ctrl_ref *ref; 31958c2ecf20Sopenharmony_ci struct v4l2_ctrl *ctrl; 31968c2ecf20Sopenharmony_ci 31978c2ecf20Sopenharmony_ci if (hdl == NULL) 31988c2ecf20Sopenharmony_ci return -EINVAL; 31998c2ecf20Sopenharmony_ci 32008c2ecf20Sopenharmony_ci mutex_lock(hdl->lock); 32018c2ecf20Sopenharmony_ci 32028c2ecf20Sopenharmony_ci /* Try to find it */ 32038c2ecf20Sopenharmony_ci ref = find_ref(hdl, id); 32048c2ecf20Sopenharmony_ci 32058c2ecf20Sopenharmony_ci if ((qc->id & next_flags) && !list_empty(&hdl->ctrl_refs)) { 32068c2ecf20Sopenharmony_ci bool is_compound; 32078c2ecf20Sopenharmony_ci /* Match any control that is not hidden */ 32088c2ecf20Sopenharmony_ci unsigned mask = 1; 32098c2ecf20Sopenharmony_ci bool match = false; 32108c2ecf20Sopenharmony_ci 32118c2ecf20Sopenharmony_ci if ((qc->id & next_flags) == V4L2_CTRL_FLAG_NEXT_COMPOUND) { 32128c2ecf20Sopenharmony_ci /* Match any hidden control */ 32138c2ecf20Sopenharmony_ci match = true; 32148c2ecf20Sopenharmony_ci } else if ((qc->id & next_flags) == next_flags) { 32158c2ecf20Sopenharmony_ci /* Match any control, compound or not */ 32168c2ecf20Sopenharmony_ci mask = 0; 32178c2ecf20Sopenharmony_ci } 32188c2ecf20Sopenharmony_ci 32198c2ecf20Sopenharmony_ci /* Find the next control with ID > qc->id */ 32208c2ecf20Sopenharmony_ci 32218c2ecf20Sopenharmony_ci /* Did we reach the end of the control list? */ 32228c2ecf20Sopenharmony_ci if (id >= node2id(hdl->ctrl_refs.prev)) { 32238c2ecf20Sopenharmony_ci ref = NULL; /* Yes, so there is no next control */ 32248c2ecf20Sopenharmony_ci } else if (ref) { 32258c2ecf20Sopenharmony_ci /* We found a control with the given ID, so just get 32268c2ecf20Sopenharmony_ci the next valid one in the list. */ 32278c2ecf20Sopenharmony_ci list_for_each_entry_continue(ref, &hdl->ctrl_refs, node) { 32288c2ecf20Sopenharmony_ci is_compound = ref->ctrl->is_array || 32298c2ecf20Sopenharmony_ci ref->ctrl->type >= V4L2_CTRL_COMPOUND_TYPES; 32308c2ecf20Sopenharmony_ci if (id < ref->ctrl->id && 32318c2ecf20Sopenharmony_ci (is_compound & mask) == match) 32328c2ecf20Sopenharmony_ci break; 32338c2ecf20Sopenharmony_ci } 32348c2ecf20Sopenharmony_ci if (&ref->node == &hdl->ctrl_refs) 32358c2ecf20Sopenharmony_ci ref = NULL; 32368c2ecf20Sopenharmony_ci } else { 32378c2ecf20Sopenharmony_ci /* No control with the given ID exists, so start 32388c2ecf20Sopenharmony_ci searching for the next largest ID. We know there 32398c2ecf20Sopenharmony_ci is one, otherwise the first 'if' above would have 32408c2ecf20Sopenharmony_ci been true. */ 32418c2ecf20Sopenharmony_ci list_for_each_entry(ref, &hdl->ctrl_refs, node) { 32428c2ecf20Sopenharmony_ci is_compound = ref->ctrl->is_array || 32438c2ecf20Sopenharmony_ci ref->ctrl->type >= V4L2_CTRL_COMPOUND_TYPES; 32448c2ecf20Sopenharmony_ci if (id < ref->ctrl->id && 32458c2ecf20Sopenharmony_ci (is_compound & mask) == match) 32468c2ecf20Sopenharmony_ci break; 32478c2ecf20Sopenharmony_ci } 32488c2ecf20Sopenharmony_ci if (&ref->node == &hdl->ctrl_refs) 32498c2ecf20Sopenharmony_ci ref = NULL; 32508c2ecf20Sopenharmony_ci } 32518c2ecf20Sopenharmony_ci } 32528c2ecf20Sopenharmony_ci mutex_unlock(hdl->lock); 32538c2ecf20Sopenharmony_ci 32548c2ecf20Sopenharmony_ci if (!ref) 32558c2ecf20Sopenharmony_ci return -EINVAL; 32568c2ecf20Sopenharmony_ci 32578c2ecf20Sopenharmony_ci ctrl = ref->ctrl; 32588c2ecf20Sopenharmony_ci memset(qc, 0, sizeof(*qc)); 32598c2ecf20Sopenharmony_ci if (id >= V4L2_CID_PRIVATE_BASE) 32608c2ecf20Sopenharmony_ci qc->id = id; 32618c2ecf20Sopenharmony_ci else 32628c2ecf20Sopenharmony_ci qc->id = ctrl->id; 32638c2ecf20Sopenharmony_ci strscpy(qc->name, ctrl->name, sizeof(qc->name)); 32648c2ecf20Sopenharmony_ci qc->flags = user_flags(ctrl); 32658c2ecf20Sopenharmony_ci qc->type = ctrl->type; 32668c2ecf20Sopenharmony_ci qc->elem_size = ctrl->elem_size; 32678c2ecf20Sopenharmony_ci qc->elems = ctrl->elems; 32688c2ecf20Sopenharmony_ci qc->nr_of_dims = ctrl->nr_of_dims; 32698c2ecf20Sopenharmony_ci memcpy(qc->dims, ctrl->dims, qc->nr_of_dims * sizeof(qc->dims[0])); 32708c2ecf20Sopenharmony_ci qc->minimum = ctrl->minimum; 32718c2ecf20Sopenharmony_ci qc->maximum = ctrl->maximum; 32728c2ecf20Sopenharmony_ci qc->default_value = ctrl->default_value; 32738c2ecf20Sopenharmony_ci if (ctrl->type == V4L2_CTRL_TYPE_MENU 32748c2ecf20Sopenharmony_ci || ctrl->type == V4L2_CTRL_TYPE_INTEGER_MENU) 32758c2ecf20Sopenharmony_ci qc->step = 1; 32768c2ecf20Sopenharmony_ci else 32778c2ecf20Sopenharmony_ci qc->step = ctrl->step; 32788c2ecf20Sopenharmony_ci return 0; 32798c2ecf20Sopenharmony_ci} 32808c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_query_ext_ctrl); 32818c2ecf20Sopenharmony_ci 32828c2ecf20Sopenharmony_ci/* Implement VIDIOC_QUERYCTRL */ 32838c2ecf20Sopenharmony_ciint v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc) 32848c2ecf20Sopenharmony_ci{ 32858c2ecf20Sopenharmony_ci struct v4l2_query_ext_ctrl qec = { qc->id }; 32868c2ecf20Sopenharmony_ci int rc; 32878c2ecf20Sopenharmony_ci 32888c2ecf20Sopenharmony_ci rc = v4l2_query_ext_ctrl(hdl, &qec); 32898c2ecf20Sopenharmony_ci if (rc) 32908c2ecf20Sopenharmony_ci return rc; 32918c2ecf20Sopenharmony_ci 32928c2ecf20Sopenharmony_ci qc->id = qec.id; 32938c2ecf20Sopenharmony_ci qc->type = qec.type; 32948c2ecf20Sopenharmony_ci qc->flags = qec.flags; 32958c2ecf20Sopenharmony_ci strscpy(qc->name, qec.name, sizeof(qc->name)); 32968c2ecf20Sopenharmony_ci switch (qc->type) { 32978c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_INTEGER: 32988c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_BOOLEAN: 32998c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_MENU: 33008c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_INTEGER_MENU: 33018c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_STRING: 33028c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_BITMASK: 33038c2ecf20Sopenharmony_ci qc->minimum = qec.minimum; 33048c2ecf20Sopenharmony_ci qc->maximum = qec.maximum; 33058c2ecf20Sopenharmony_ci qc->step = qec.step; 33068c2ecf20Sopenharmony_ci qc->default_value = qec.default_value; 33078c2ecf20Sopenharmony_ci break; 33088c2ecf20Sopenharmony_ci default: 33098c2ecf20Sopenharmony_ci qc->minimum = 0; 33108c2ecf20Sopenharmony_ci qc->maximum = 0; 33118c2ecf20Sopenharmony_ci qc->step = 0; 33128c2ecf20Sopenharmony_ci qc->default_value = 0; 33138c2ecf20Sopenharmony_ci break; 33148c2ecf20Sopenharmony_ci } 33158c2ecf20Sopenharmony_ci return 0; 33168c2ecf20Sopenharmony_ci} 33178c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_queryctrl); 33188c2ecf20Sopenharmony_ci 33198c2ecf20Sopenharmony_ci/* Implement VIDIOC_QUERYMENU */ 33208c2ecf20Sopenharmony_ciint v4l2_querymenu(struct v4l2_ctrl_handler *hdl, struct v4l2_querymenu *qm) 33218c2ecf20Sopenharmony_ci{ 33228c2ecf20Sopenharmony_ci struct v4l2_ctrl *ctrl; 33238c2ecf20Sopenharmony_ci u32 i = qm->index; 33248c2ecf20Sopenharmony_ci 33258c2ecf20Sopenharmony_ci ctrl = v4l2_ctrl_find(hdl, qm->id); 33268c2ecf20Sopenharmony_ci if (!ctrl) 33278c2ecf20Sopenharmony_ci return -EINVAL; 33288c2ecf20Sopenharmony_ci 33298c2ecf20Sopenharmony_ci qm->reserved = 0; 33308c2ecf20Sopenharmony_ci /* Sanity checks */ 33318c2ecf20Sopenharmony_ci switch (ctrl->type) { 33328c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_MENU: 33338c2ecf20Sopenharmony_ci if (ctrl->qmenu == NULL) 33348c2ecf20Sopenharmony_ci return -EINVAL; 33358c2ecf20Sopenharmony_ci break; 33368c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_INTEGER_MENU: 33378c2ecf20Sopenharmony_ci if (ctrl->qmenu_int == NULL) 33388c2ecf20Sopenharmony_ci return -EINVAL; 33398c2ecf20Sopenharmony_ci break; 33408c2ecf20Sopenharmony_ci default: 33418c2ecf20Sopenharmony_ci return -EINVAL; 33428c2ecf20Sopenharmony_ci } 33438c2ecf20Sopenharmony_ci 33448c2ecf20Sopenharmony_ci if (i < ctrl->minimum || i > ctrl->maximum) 33458c2ecf20Sopenharmony_ci return -EINVAL; 33468c2ecf20Sopenharmony_ci 33478c2ecf20Sopenharmony_ci /* Use mask to see if this menu item should be skipped */ 33488c2ecf20Sopenharmony_ci if (ctrl->menu_skip_mask & (1ULL << i)) 33498c2ecf20Sopenharmony_ci return -EINVAL; 33508c2ecf20Sopenharmony_ci /* Empty menu items should also be skipped */ 33518c2ecf20Sopenharmony_ci if (ctrl->type == V4L2_CTRL_TYPE_MENU) { 33528c2ecf20Sopenharmony_ci if (ctrl->qmenu[i] == NULL || ctrl->qmenu[i][0] == '\0') 33538c2ecf20Sopenharmony_ci return -EINVAL; 33548c2ecf20Sopenharmony_ci strscpy(qm->name, ctrl->qmenu[i], sizeof(qm->name)); 33558c2ecf20Sopenharmony_ci } else { 33568c2ecf20Sopenharmony_ci qm->value = ctrl->qmenu_int[i]; 33578c2ecf20Sopenharmony_ci } 33588c2ecf20Sopenharmony_ci return 0; 33598c2ecf20Sopenharmony_ci} 33608c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_querymenu); 33618c2ecf20Sopenharmony_ci 33628c2ecf20Sopenharmony_cistatic int v4l2_ctrl_request_clone(struct v4l2_ctrl_handler *hdl, 33638c2ecf20Sopenharmony_ci const struct v4l2_ctrl_handler *from) 33648c2ecf20Sopenharmony_ci{ 33658c2ecf20Sopenharmony_ci struct v4l2_ctrl_ref *ref; 33668c2ecf20Sopenharmony_ci int err = 0; 33678c2ecf20Sopenharmony_ci 33688c2ecf20Sopenharmony_ci if (WARN_ON(!hdl || hdl == from)) 33698c2ecf20Sopenharmony_ci return -EINVAL; 33708c2ecf20Sopenharmony_ci 33718c2ecf20Sopenharmony_ci if (hdl->error) 33728c2ecf20Sopenharmony_ci return hdl->error; 33738c2ecf20Sopenharmony_ci 33748c2ecf20Sopenharmony_ci WARN_ON(hdl->lock != &hdl->_lock); 33758c2ecf20Sopenharmony_ci 33768c2ecf20Sopenharmony_ci mutex_lock(from->lock); 33778c2ecf20Sopenharmony_ci list_for_each_entry(ref, &from->ctrl_refs, node) { 33788c2ecf20Sopenharmony_ci struct v4l2_ctrl *ctrl = ref->ctrl; 33798c2ecf20Sopenharmony_ci struct v4l2_ctrl_ref *new_ref; 33808c2ecf20Sopenharmony_ci 33818c2ecf20Sopenharmony_ci /* Skip refs inherited from other devices */ 33828c2ecf20Sopenharmony_ci if (ref->from_other_dev) 33838c2ecf20Sopenharmony_ci continue; 33848c2ecf20Sopenharmony_ci /* And buttons */ 33858c2ecf20Sopenharmony_ci if (ctrl->type == V4L2_CTRL_TYPE_BUTTON) 33868c2ecf20Sopenharmony_ci continue; 33878c2ecf20Sopenharmony_ci err = handler_new_ref(hdl, ctrl, &new_ref, false, true); 33888c2ecf20Sopenharmony_ci if (err) 33898c2ecf20Sopenharmony_ci break; 33908c2ecf20Sopenharmony_ci } 33918c2ecf20Sopenharmony_ci mutex_unlock(from->lock); 33928c2ecf20Sopenharmony_ci return err; 33938c2ecf20Sopenharmony_ci} 33948c2ecf20Sopenharmony_ci 33958c2ecf20Sopenharmony_cistatic void v4l2_ctrl_request_queue(struct media_request_object *obj) 33968c2ecf20Sopenharmony_ci{ 33978c2ecf20Sopenharmony_ci struct v4l2_ctrl_handler *hdl = 33988c2ecf20Sopenharmony_ci container_of(obj, struct v4l2_ctrl_handler, req_obj); 33998c2ecf20Sopenharmony_ci struct v4l2_ctrl_handler *main_hdl = obj->priv; 34008c2ecf20Sopenharmony_ci 34018c2ecf20Sopenharmony_ci mutex_lock(main_hdl->lock); 34028c2ecf20Sopenharmony_ci list_add_tail(&hdl->requests_queued, &main_hdl->requests_queued); 34038c2ecf20Sopenharmony_ci hdl->request_is_queued = true; 34048c2ecf20Sopenharmony_ci mutex_unlock(main_hdl->lock); 34058c2ecf20Sopenharmony_ci} 34068c2ecf20Sopenharmony_ci 34078c2ecf20Sopenharmony_cistatic void v4l2_ctrl_request_unbind(struct media_request_object *obj) 34088c2ecf20Sopenharmony_ci{ 34098c2ecf20Sopenharmony_ci struct v4l2_ctrl_handler *hdl = 34108c2ecf20Sopenharmony_ci container_of(obj, struct v4l2_ctrl_handler, req_obj); 34118c2ecf20Sopenharmony_ci struct v4l2_ctrl_handler *main_hdl = obj->priv; 34128c2ecf20Sopenharmony_ci 34138c2ecf20Sopenharmony_ci mutex_lock(main_hdl->lock); 34148c2ecf20Sopenharmony_ci list_del_init(&hdl->requests); 34158c2ecf20Sopenharmony_ci if (hdl->request_is_queued) { 34168c2ecf20Sopenharmony_ci list_del_init(&hdl->requests_queued); 34178c2ecf20Sopenharmony_ci hdl->request_is_queued = false; 34188c2ecf20Sopenharmony_ci } 34198c2ecf20Sopenharmony_ci mutex_unlock(main_hdl->lock); 34208c2ecf20Sopenharmony_ci} 34218c2ecf20Sopenharmony_ci 34228c2ecf20Sopenharmony_cistatic void v4l2_ctrl_request_release(struct media_request_object *obj) 34238c2ecf20Sopenharmony_ci{ 34248c2ecf20Sopenharmony_ci struct v4l2_ctrl_handler *hdl = 34258c2ecf20Sopenharmony_ci container_of(obj, struct v4l2_ctrl_handler, req_obj); 34268c2ecf20Sopenharmony_ci 34278c2ecf20Sopenharmony_ci v4l2_ctrl_handler_free(hdl); 34288c2ecf20Sopenharmony_ci kfree(hdl); 34298c2ecf20Sopenharmony_ci} 34308c2ecf20Sopenharmony_ci 34318c2ecf20Sopenharmony_cistatic const struct media_request_object_ops req_ops = { 34328c2ecf20Sopenharmony_ci .queue = v4l2_ctrl_request_queue, 34338c2ecf20Sopenharmony_ci .unbind = v4l2_ctrl_request_unbind, 34348c2ecf20Sopenharmony_ci .release = v4l2_ctrl_request_release, 34358c2ecf20Sopenharmony_ci}; 34368c2ecf20Sopenharmony_ci 34378c2ecf20Sopenharmony_cistruct v4l2_ctrl_handler *v4l2_ctrl_request_hdl_find(struct media_request *req, 34388c2ecf20Sopenharmony_ci struct v4l2_ctrl_handler *parent) 34398c2ecf20Sopenharmony_ci{ 34408c2ecf20Sopenharmony_ci struct media_request_object *obj; 34418c2ecf20Sopenharmony_ci 34428c2ecf20Sopenharmony_ci if (WARN_ON(req->state != MEDIA_REQUEST_STATE_VALIDATING && 34438c2ecf20Sopenharmony_ci req->state != MEDIA_REQUEST_STATE_QUEUED)) 34448c2ecf20Sopenharmony_ci return NULL; 34458c2ecf20Sopenharmony_ci 34468c2ecf20Sopenharmony_ci obj = media_request_object_find(req, &req_ops, parent); 34478c2ecf20Sopenharmony_ci if (obj) 34488c2ecf20Sopenharmony_ci return container_of(obj, struct v4l2_ctrl_handler, req_obj); 34498c2ecf20Sopenharmony_ci return NULL; 34508c2ecf20Sopenharmony_ci} 34518c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(v4l2_ctrl_request_hdl_find); 34528c2ecf20Sopenharmony_ci 34538c2ecf20Sopenharmony_cistruct v4l2_ctrl * 34548c2ecf20Sopenharmony_civ4l2_ctrl_request_hdl_ctrl_find(struct v4l2_ctrl_handler *hdl, u32 id) 34558c2ecf20Sopenharmony_ci{ 34568c2ecf20Sopenharmony_ci struct v4l2_ctrl_ref *ref = find_ref_lock(hdl, id); 34578c2ecf20Sopenharmony_ci 34588c2ecf20Sopenharmony_ci return (ref && ref->valid_p_req) ? ref->ctrl : NULL; 34598c2ecf20Sopenharmony_ci} 34608c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(v4l2_ctrl_request_hdl_ctrl_find); 34618c2ecf20Sopenharmony_ci 34628c2ecf20Sopenharmony_cistatic int v4l2_ctrl_request_bind(struct media_request *req, 34638c2ecf20Sopenharmony_ci struct v4l2_ctrl_handler *hdl, 34648c2ecf20Sopenharmony_ci struct v4l2_ctrl_handler *from) 34658c2ecf20Sopenharmony_ci{ 34668c2ecf20Sopenharmony_ci int ret; 34678c2ecf20Sopenharmony_ci 34688c2ecf20Sopenharmony_ci ret = v4l2_ctrl_request_clone(hdl, from); 34698c2ecf20Sopenharmony_ci 34708c2ecf20Sopenharmony_ci if (!ret) { 34718c2ecf20Sopenharmony_ci ret = media_request_object_bind(req, &req_ops, 34728c2ecf20Sopenharmony_ci from, false, &hdl->req_obj); 34738c2ecf20Sopenharmony_ci if (!ret) { 34748c2ecf20Sopenharmony_ci mutex_lock(from->lock); 34758c2ecf20Sopenharmony_ci list_add_tail(&hdl->requests, &from->requests); 34768c2ecf20Sopenharmony_ci mutex_unlock(from->lock); 34778c2ecf20Sopenharmony_ci } 34788c2ecf20Sopenharmony_ci } 34798c2ecf20Sopenharmony_ci return ret; 34808c2ecf20Sopenharmony_ci} 34818c2ecf20Sopenharmony_ci 34828c2ecf20Sopenharmony_ci/* Some general notes on the atomic requirements of VIDIOC_G/TRY/S_EXT_CTRLS: 34838c2ecf20Sopenharmony_ci 34848c2ecf20Sopenharmony_ci It is not a fully atomic operation, just best-effort only. After all, if 34858c2ecf20Sopenharmony_ci multiple controls have to be set through multiple i2c writes (for example) 34868c2ecf20Sopenharmony_ci then some initial writes may succeed while others fail. Thus leaving the 34878c2ecf20Sopenharmony_ci system in an inconsistent state. The question is how much effort you are 34888c2ecf20Sopenharmony_ci willing to spend on trying to make something atomic that really isn't. 34898c2ecf20Sopenharmony_ci 34908c2ecf20Sopenharmony_ci From the point of view of an application the main requirement is that 34918c2ecf20Sopenharmony_ci when you call VIDIOC_S_EXT_CTRLS and some values are invalid then an 34928c2ecf20Sopenharmony_ci error should be returned without actually affecting any controls. 34938c2ecf20Sopenharmony_ci 34948c2ecf20Sopenharmony_ci If all the values are correct, then it is acceptable to just give up 34958c2ecf20Sopenharmony_ci in case of low-level errors. 34968c2ecf20Sopenharmony_ci 34978c2ecf20Sopenharmony_ci It is important though that the application can tell when only a partial 34988c2ecf20Sopenharmony_ci configuration was done. The way we do that is through the error_idx field 34998c2ecf20Sopenharmony_ci of struct v4l2_ext_controls: if that is equal to the count field then no 35008c2ecf20Sopenharmony_ci controls were affected. Otherwise all controls before that index were 35018c2ecf20Sopenharmony_ci successful in performing their 'get' or 'set' operation, the control at 35028c2ecf20Sopenharmony_ci the given index failed, and you don't know what happened with the controls 35038c2ecf20Sopenharmony_ci after the failed one. Since if they were part of a control cluster they 35048c2ecf20Sopenharmony_ci could have been successfully processed (if a cluster member was encountered 35058c2ecf20Sopenharmony_ci at index < error_idx), they could have failed (if a cluster member was at 35068c2ecf20Sopenharmony_ci error_idx), or they may not have been processed yet (if the first cluster 35078c2ecf20Sopenharmony_ci member appeared after error_idx). 35088c2ecf20Sopenharmony_ci 35098c2ecf20Sopenharmony_ci It is all fairly theoretical, though. In practice all you can do is to 35108c2ecf20Sopenharmony_ci bail out. If error_idx == count, then it is an application bug. If 35118c2ecf20Sopenharmony_ci error_idx < count then it is only an application bug if the error code was 35128c2ecf20Sopenharmony_ci EBUSY. That usually means that something started streaming just when you 35138c2ecf20Sopenharmony_ci tried to set the controls. In all other cases it is a driver/hardware 35148c2ecf20Sopenharmony_ci problem and all you can do is to retry or bail out. 35158c2ecf20Sopenharmony_ci 35168c2ecf20Sopenharmony_ci Note that these rules do not apply to VIDIOC_TRY_EXT_CTRLS: since that 35178c2ecf20Sopenharmony_ci never modifies controls the error_idx is just set to whatever control 35188c2ecf20Sopenharmony_ci has an invalid value. 35198c2ecf20Sopenharmony_ci */ 35208c2ecf20Sopenharmony_ci 35218c2ecf20Sopenharmony_ci/* Prepare for the extended g/s/try functions. 35228c2ecf20Sopenharmony_ci Find the controls in the control array and do some basic checks. */ 35238c2ecf20Sopenharmony_cistatic int prepare_ext_ctrls(struct v4l2_ctrl_handler *hdl, 35248c2ecf20Sopenharmony_ci struct v4l2_ext_controls *cs, 35258c2ecf20Sopenharmony_ci struct v4l2_ctrl_helper *helpers, 35268c2ecf20Sopenharmony_ci struct video_device *vdev, 35278c2ecf20Sopenharmony_ci bool get) 35288c2ecf20Sopenharmony_ci{ 35298c2ecf20Sopenharmony_ci struct v4l2_ctrl_helper *h; 35308c2ecf20Sopenharmony_ci bool have_clusters = false; 35318c2ecf20Sopenharmony_ci u32 i; 35328c2ecf20Sopenharmony_ci 35338c2ecf20Sopenharmony_ci for (i = 0, h = helpers; i < cs->count; i++, h++) { 35348c2ecf20Sopenharmony_ci struct v4l2_ext_control *c = &cs->controls[i]; 35358c2ecf20Sopenharmony_ci struct v4l2_ctrl_ref *ref; 35368c2ecf20Sopenharmony_ci struct v4l2_ctrl *ctrl; 35378c2ecf20Sopenharmony_ci u32 id = c->id & V4L2_CTRL_ID_MASK; 35388c2ecf20Sopenharmony_ci 35398c2ecf20Sopenharmony_ci cs->error_idx = i; 35408c2ecf20Sopenharmony_ci 35418c2ecf20Sopenharmony_ci if (cs->which && 35428c2ecf20Sopenharmony_ci cs->which != V4L2_CTRL_WHICH_DEF_VAL && 35438c2ecf20Sopenharmony_ci cs->which != V4L2_CTRL_WHICH_REQUEST_VAL && 35448c2ecf20Sopenharmony_ci V4L2_CTRL_ID2WHICH(id) != cs->which) { 35458c2ecf20Sopenharmony_ci dprintk(vdev, 35468c2ecf20Sopenharmony_ci "invalid which 0x%x or control id 0x%x\n", 35478c2ecf20Sopenharmony_ci cs->which, id); 35488c2ecf20Sopenharmony_ci return -EINVAL; 35498c2ecf20Sopenharmony_ci } 35508c2ecf20Sopenharmony_ci 35518c2ecf20Sopenharmony_ci /* Old-style private controls are not allowed for 35528c2ecf20Sopenharmony_ci extended controls */ 35538c2ecf20Sopenharmony_ci if (id >= V4L2_CID_PRIVATE_BASE) { 35548c2ecf20Sopenharmony_ci dprintk(vdev, 35558c2ecf20Sopenharmony_ci "old-style private controls not allowed\n"); 35568c2ecf20Sopenharmony_ci return -EINVAL; 35578c2ecf20Sopenharmony_ci } 35588c2ecf20Sopenharmony_ci ref = find_ref_lock(hdl, id); 35598c2ecf20Sopenharmony_ci if (ref == NULL) { 35608c2ecf20Sopenharmony_ci dprintk(vdev, "cannot find control id 0x%x\n", id); 35618c2ecf20Sopenharmony_ci return -EINVAL; 35628c2ecf20Sopenharmony_ci } 35638c2ecf20Sopenharmony_ci h->ref = ref; 35648c2ecf20Sopenharmony_ci ctrl = ref->ctrl; 35658c2ecf20Sopenharmony_ci if (ctrl->flags & V4L2_CTRL_FLAG_DISABLED) { 35668c2ecf20Sopenharmony_ci dprintk(vdev, "control id 0x%x is disabled\n", id); 35678c2ecf20Sopenharmony_ci return -EINVAL; 35688c2ecf20Sopenharmony_ci } 35698c2ecf20Sopenharmony_ci 35708c2ecf20Sopenharmony_ci if (ctrl->cluster[0]->ncontrols > 1) 35718c2ecf20Sopenharmony_ci have_clusters = true; 35728c2ecf20Sopenharmony_ci if (ctrl->cluster[0] != ctrl) 35738c2ecf20Sopenharmony_ci ref = find_ref_lock(hdl, ctrl->cluster[0]->id); 35748c2ecf20Sopenharmony_ci if (ctrl->is_ptr && !ctrl->is_string) { 35758c2ecf20Sopenharmony_ci unsigned tot_size = ctrl->elems * ctrl->elem_size; 35768c2ecf20Sopenharmony_ci 35778c2ecf20Sopenharmony_ci if (c->size < tot_size) { 35788c2ecf20Sopenharmony_ci /* 35798c2ecf20Sopenharmony_ci * In the get case the application first 35808c2ecf20Sopenharmony_ci * queries to obtain the size of the control. 35818c2ecf20Sopenharmony_ci */ 35828c2ecf20Sopenharmony_ci if (get) { 35838c2ecf20Sopenharmony_ci c->size = tot_size; 35848c2ecf20Sopenharmony_ci return -ENOSPC; 35858c2ecf20Sopenharmony_ci } 35868c2ecf20Sopenharmony_ci dprintk(vdev, 35878c2ecf20Sopenharmony_ci "pointer control id 0x%x size too small, %d bytes but %d bytes needed\n", 35888c2ecf20Sopenharmony_ci id, c->size, tot_size); 35898c2ecf20Sopenharmony_ci return -EFAULT; 35908c2ecf20Sopenharmony_ci } 35918c2ecf20Sopenharmony_ci c->size = tot_size; 35928c2ecf20Sopenharmony_ci } 35938c2ecf20Sopenharmony_ci /* Store the ref to the master control of the cluster */ 35948c2ecf20Sopenharmony_ci h->mref = ref; 35958c2ecf20Sopenharmony_ci /* Initially set next to 0, meaning that there is no other 35968c2ecf20Sopenharmony_ci control in this helper array belonging to the same 35978c2ecf20Sopenharmony_ci cluster */ 35988c2ecf20Sopenharmony_ci h->next = 0; 35998c2ecf20Sopenharmony_ci } 36008c2ecf20Sopenharmony_ci 36018c2ecf20Sopenharmony_ci /* We are done if there were no controls that belong to a multi- 36028c2ecf20Sopenharmony_ci control cluster. */ 36038c2ecf20Sopenharmony_ci if (!have_clusters) 36048c2ecf20Sopenharmony_ci return 0; 36058c2ecf20Sopenharmony_ci 36068c2ecf20Sopenharmony_ci /* The code below figures out in O(n) time which controls in the list 36078c2ecf20Sopenharmony_ci belong to the same cluster. */ 36088c2ecf20Sopenharmony_ci 36098c2ecf20Sopenharmony_ci /* This has to be done with the handler lock taken. */ 36108c2ecf20Sopenharmony_ci mutex_lock(hdl->lock); 36118c2ecf20Sopenharmony_ci 36128c2ecf20Sopenharmony_ci /* First zero the helper field in the master control references */ 36138c2ecf20Sopenharmony_ci for (i = 0; i < cs->count; i++) 36148c2ecf20Sopenharmony_ci helpers[i].mref->helper = NULL; 36158c2ecf20Sopenharmony_ci for (i = 0, h = helpers; i < cs->count; i++, h++) { 36168c2ecf20Sopenharmony_ci struct v4l2_ctrl_ref *mref = h->mref; 36178c2ecf20Sopenharmony_ci 36188c2ecf20Sopenharmony_ci /* If the mref->helper is set, then it points to an earlier 36198c2ecf20Sopenharmony_ci helper that belongs to the same cluster. */ 36208c2ecf20Sopenharmony_ci if (mref->helper) { 36218c2ecf20Sopenharmony_ci /* Set the next field of mref->helper to the current 36228c2ecf20Sopenharmony_ci index: this means that that earlier helper now 36238c2ecf20Sopenharmony_ci points to the next helper in the same cluster. */ 36248c2ecf20Sopenharmony_ci mref->helper->next = i; 36258c2ecf20Sopenharmony_ci /* mref should be set only for the first helper in the 36268c2ecf20Sopenharmony_ci cluster, clear the others. */ 36278c2ecf20Sopenharmony_ci h->mref = NULL; 36288c2ecf20Sopenharmony_ci } 36298c2ecf20Sopenharmony_ci /* Point the mref helper to the current helper struct. */ 36308c2ecf20Sopenharmony_ci mref->helper = h; 36318c2ecf20Sopenharmony_ci } 36328c2ecf20Sopenharmony_ci mutex_unlock(hdl->lock); 36338c2ecf20Sopenharmony_ci return 0; 36348c2ecf20Sopenharmony_ci} 36358c2ecf20Sopenharmony_ci 36368c2ecf20Sopenharmony_ci/* Handles the corner case where cs->count == 0. It checks whether the 36378c2ecf20Sopenharmony_ci specified control class exists. If that class ID is 0, then it checks 36388c2ecf20Sopenharmony_ci whether there are any controls at all. */ 36398c2ecf20Sopenharmony_cistatic int class_check(struct v4l2_ctrl_handler *hdl, u32 which) 36408c2ecf20Sopenharmony_ci{ 36418c2ecf20Sopenharmony_ci if (which == 0 || which == V4L2_CTRL_WHICH_DEF_VAL || 36428c2ecf20Sopenharmony_ci which == V4L2_CTRL_WHICH_REQUEST_VAL) 36438c2ecf20Sopenharmony_ci return 0; 36448c2ecf20Sopenharmony_ci return find_ref_lock(hdl, which | 1) ? 0 : -EINVAL; 36458c2ecf20Sopenharmony_ci} 36468c2ecf20Sopenharmony_ci 36478c2ecf20Sopenharmony_ci/* 36488c2ecf20Sopenharmony_ci * Get extended controls. Allocates the helpers array if needed. 36498c2ecf20Sopenharmony_ci * 36508c2ecf20Sopenharmony_ci * Note that v4l2_g_ext_ctrls_common() with 'which' set to 36518c2ecf20Sopenharmony_ci * V4L2_CTRL_WHICH_REQUEST_VAL is only called if the request was 36528c2ecf20Sopenharmony_ci * completed, and in that case valid_p_req is true for all controls. 36538c2ecf20Sopenharmony_ci */ 36548c2ecf20Sopenharmony_cistatic int v4l2_g_ext_ctrls_common(struct v4l2_ctrl_handler *hdl, 36558c2ecf20Sopenharmony_ci struct v4l2_ext_controls *cs, 36568c2ecf20Sopenharmony_ci struct video_device *vdev) 36578c2ecf20Sopenharmony_ci{ 36588c2ecf20Sopenharmony_ci struct v4l2_ctrl_helper helper[4]; 36598c2ecf20Sopenharmony_ci struct v4l2_ctrl_helper *helpers = helper; 36608c2ecf20Sopenharmony_ci int ret; 36618c2ecf20Sopenharmony_ci int i, j; 36628c2ecf20Sopenharmony_ci bool is_default, is_request; 36638c2ecf20Sopenharmony_ci 36648c2ecf20Sopenharmony_ci is_default = (cs->which == V4L2_CTRL_WHICH_DEF_VAL); 36658c2ecf20Sopenharmony_ci is_request = (cs->which == V4L2_CTRL_WHICH_REQUEST_VAL); 36668c2ecf20Sopenharmony_ci 36678c2ecf20Sopenharmony_ci cs->error_idx = cs->count; 36688c2ecf20Sopenharmony_ci cs->which = V4L2_CTRL_ID2WHICH(cs->which); 36698c2ecf20Sopenharmony_ci 36708c2ecf20Sopenharmony_ci if (hdl == NULL) 36718c2ecf20Sopenharmony_ci return -EINVAL; 36728c2ecf20Sopenharmony_ci 36738c2ecf20Sopenharmony_ci if (cs->count == 0) 36748c2ecf20Sopenharmony_ci return class_check(hdl, cs->which); 36758c2ecf20Sopenharmony_ci 36768c2ecf20Sopenharmony_ci if (cs->count > ARRAY_SIZE(helper)) { 36778c2ecf20Sopenharmony_ci helpers = kvmalloc_array(cs->count, sizeof(helper[0]), 36788c2ecf20Sopenharmony_ci GFP_KERNEL); 36798c2ecf20Sopenharmony_ci if (helpers == NULL) 36808c2ecf20Sopenharmony_ci return -ENOMEM; 36818c2ecf20Sopenharmony_ci } 36828c2ecf20Sopenharmony_ci 36838c2ecf20Sopenharmony_ci ret = prepare_ext_ctrls(hdl, cs, helpers, vdev, true); 36848c2ecf20Sopenharmony_ci cs->error_idx = cs->count; 36858c2ecf20Sopenharmony_ci 36868c2ecf20Sopenharmony_ci for (i = 0; !ret && i < cs->count; i++) 36878c2ecf20Sopenharmony_ci if (helpers[i].ref->ctrl->flags & V4L2_CTRL_FLAG_WRITE_ONLY) 36888c2ecf20Sopenharmony_ci ret = -EACCES; 36898c2ecf20Sopenharmony_ci 36908c2ecf20Sopenharmony_ci for (i = 0; !ret && i < cs->count; i++) { 36918c2ecf20Sopenharmony_ci struct v4l2_ctrl *master; 36928c2ecf20Sopenharmony_ci bool is_volatile = false; 36938c2ecf20Sopenharmony_ci u32 idx = i; 36948c2ecf20Sopenharmony_ci 36958c2ecf20Sopenharmony_ci if (helpers[i].mref == NULL) 36968c2ecf20Sopenharmony_ci continue; 36978c2ecf20Sopenharmony_ci 36988c2ecf20Sopenharmony_ci master = helpers[i].mref->ctrl; 36998c2ecf20Sopenharmony_ci cs->error_idx = i; 37008c2ecf20Sopenharmony_ci 37018c2ecf20Sopenharmony_ci v4l2_ctrl_lock(master); 37028c2ecf20Sopenharmony_ci 37038c2ecf20Sopenharmony_ci /* 37048c2ecf20Sopenharmony_ci * g_volatile_ctrl will update the new control values. 37058c2ecf20Sopenharmony_ci * This makes no sense for V4L2_CTRL_WHICH_DEF_VAL and 37068c2ecf20Sopenharmony_ci * V4L2_CTRL_WHICH_REQUEST_VAL. In the case of requests 37078c2ecf20Sopenharmony_ci * it is v4l2_ctrl_request_complete() that copies the 37088c2ecf20Sopenharmony_ci * volatile controls at the time of request completion 37098c2ecf20Sopenharmony_ci * to the request, so you don't want to do that again. 37108c2ecf20Sopenharmony_ci */ 37118c2ecf20Sopenharmony_ci if (!is_default && !is_request && 37128c2ecf20Sopenharmony_ci ((master->flags & V4L2_CTRL_FLAG_VOLATILE) || 37138c2ecf20Sopenharmony_ci (master->has_volatiles && !is_cur_manual(master)))) { 37148c2ecf20Sopenharmony_ci for (j = 0; j < master->ncontrols; j++) 37158c2ecf20Sopenharmony_ci cur_to_new(master->cluster[j]); 37168c2ecf20Sopenharmony_ci ret = call_op(master, g_volatile_ctrl); 37178c2ecf20Sopenharmony_ci is_volatile = true; 37188c2ecf20Sopenharmony_ci } 37198c2ecf20Sopenharmony_ci 37208c2ecf20Sopenharmony_ci if (ret) { 37218c2ecf20Sopenharmony_ci v4l2_ctrl_unlock(master); 37228c2ecf20Sopenharmony_ci break; 37238c2ecf20Sopenharmony_ci } 37248c2ecf20Sopenharmony_ci 37258c2ecf20Sopenharmony_ci /* 37268c2ecf20Sopenharmony_ci * Copy the default value (if is_default is true), the 37278c2ecf20Sopenharmony_ci * request value (if is_request is true and p_req is valid), 37288c2ecf20Sopenharmony_ci * the new volatile value (if is_volatile is true) or the 37298c2ecf20Sopenharmony_ci * current value. 37308c2ecf20Sopenharmony_ci */ 37318c2ecf20Sopenharmony_ci do { 37328c2ecf20Sopenharmony_ci struct v4l2_ctrl_ref *ref = helpers[idx].ref; 37338c2ecf20Sopenharmony_ci 37348c2ecf20Sopenharmony_ci if (is_default) 37358c2ecf20Sopenharmony_ci ret = def_to_user(cs->controls + idx, ref->ctrl); 37368c2ecf20Sopenharmony_ci else if (is_request && ref->valid_p_req) 37378c2ecf20Sopenharmony_ci ret = req_to_user(cs->controls + idx, ref); 37388c2ecf20Sopenharmony_ci else if (is_volatile) 37398c2ecf20Sopenharmony_ci ret = new_to_user(cs->controls + idx, ref->ctrl); 37408c2ecf20Sopenharmony_ci else 37418c2ecf20Sopenharmony_ci ret = cur_to_user(cs->controls + idx, ref->ctrl); 37428c2ecf20Sopenharmony_ci idx = helpers[idx].next; 37438c2ecf20Sopenharmony_ci } while (!ret && idx); 37448c2ecf20Sopenharmony_ci 37458c2ecf20Sopenharmony_ci v4l2_ctrl_unlock(master); 37468c2ecf20Sopenharmony_ci } 37478c2ecf20Sopenharmony_ci 37488c2ecf20Sopenharmony_ci if (cs->count > ARRAY_SIZE(helper)) 37498c2ecf20Sopenharmony_ci kvfree(helpers); 37508c2ecf20Sopenharmony_ci return ret; 37518c2ecf20Sopenharmony_ci} 37528c2ecf20Sopenharmony_ci 37538c2ecf20Sopenharmony_cistatic struct media_request_object * 37548c2ecf20Sopenharmony_civ4l2_ctrls_find_req_obj(struct v4l2_ctrl_handler *hdl, 37558c2ecf20Sopenharmony_ci struct media_request *req, bool set) 37568c2ecf20Sopenharmony_ci{ 37578c2ecf20Sopenharmony_ci struct media_request_object *obj; 37588c2ecf20Sopenharmony_ci struct v4l2_ctrl_handler *new_hdl; 37598c2ecf20Sopenharmony_ci int ret; 37608c2ecf20Sopenharmony_ci 37618c2ecf20Sopenharmony_ci if (IS_ERR(req)) 37628c2ecf20Sopenharmony_ci return ERR_CAST(req); 37638c2ecf20Sopenharmony_ci 37648c2ecf20Sopenharmony_ci if (set && WARN_ON(req->state != MEDIA_REQUEST_STATE_UPDATING)) 37658c2ecf20Sopenharmony_ci return ERR_PTR(-EBUSY); 37668c2ecf20Sopenharmony_ci 37678c2ecf20Sopenharmony_ci obj = media_request_object_find(req, &req_ops, hdl); 37688c2ecf20Sopenharmony_ci if (obj) 37698c2ecf20Sopenharmony_ci return obj; 37708c2ecf20Sopenharmony_ci if (!set) 37718c2ecf20Sopenharmony_ci return ERR_PTR(-ENOENT); 37728c2ecf20Sopenharmony_ci 37738c2ecf20Sopenharmony_ci new_hdl = kzalloc(sizeof(*new_hdl), GFP_KERNEL); 37748c2ecf20Sopenharmony_ci if (!new_hdl) 37758c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 37768c2ecf20Sopenharmony_ci 37778c2ecf20Sopenharmony_ci obj = &new_hdl->req_obj; 37788c2ecf20Sopenharmony_ci ret = v4l2_ctrl_handler_init(new_hdl, (hdl->nr_of_buckets - 1) * 8); 37798c2ecf20Sopenharmony_ci if (!ret) 37808c2ecf20Sopenharmony_ci ret = v4l2_ctrl_request_bind(req, new_hdl, hdl); 37818c2ecf20Sopenharmony_ci if (ret) { 37828c2ecf20Sopenharmony_ci kfree(new_hdl); 37838c2ecf20Sopenharmony_ci 37848c2ecf20Sopenharmony_ci return ERR_PTR(ret); 37858c2ecf20Sopenharmony_ci } 37868c2ecf20Sopenharmony_ci 37878c2ecf20Sopenharmony_ci media_request_object_get(obj); 37888c2ecf20Sopenharmony_ci return obj; 37898c2ecf20Sopenharmony_ci} 37908c2ecf20Sopenharmony_ci 37918c2ecf20Sopenharmony_ciint v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct video_device *vdev, 37928c2ecf20Sopenharmony_ci struct media_device *mdev, struct v4l2_ext_controls *cs) 37938c2ecf20Sopenharmony_ci{ 37948c2ecf20Sopenharmony_ci struct media_request_object *obj = NULL; 37958c2ecf20Sopenharmony_ci struct media_request *req = NULL; 37968c2ecf20Sopenharmony_ci int ret; 37978c2ecf20Sopenharmony_ci 37988c2ecf20Sopenharmony_ci if (cs->which == V4L2_CTRL_WHICH_REQUEST_VAL) { 37998c2ecf20Sopenharmony_ci if (!mdev || cs->request_fd < 0) 38008c2ecf20Sopenharmony_ci return -EINVAL; 38018c2ecf20Sopenharmony_ci 38028c2ecf20Sopenharmony_ci req = media_request_get_by_fd(mdev, cs->request_fd); 38038c2ecf20Sopenharmony_ci if (IS_ERR(req)) 38048c2ecf20Sopenharmony_ci return PTR_ERR(req); 38058c2ecf20Sopenharmony_ci 38068c2ecf20Sopenharmony_ci if (req->state != MEDIA_REQUEST_STATE_COMPLETE) { 38078c2ecf20Sopenharmony_ci media_request_put(req); 38088c2ecf20Sopenharmony_ci return -EACCES; 38098c2ecf20Sopenharmony_ci } 38108c2ecf20Sopenharmony_ci 38118c2ecf20Sopenharmony_ci ret = media_request_lock_for_access(req); 38128c2ecf20Sopenharmony_ci if (ret) { 38138c2ecf20Sopenharmony_ci media_request_put(req); 38148c2ecf20Sopenharmony_ci return ret; 38158c2ecf20Sopenharmony_ci } 38168c2ecf20Sopenharmony_ci 38178c2ecf20Sopenharmony_ci obj = v4l2_ctrls_find_req_obj(hdl, req, false); 38188c2ecf20Sopenharmony_ci if (IS_ERR(obj)) { 38198c2ecf20Sopenharmony_ci media_request_unlock_for_access(req); 38208c2ecf20Sopenharmony_ci media_request_put(req); 38218c2ecf20Sopenharmony_ci return PTR_ERR(obj); 38228c2ecf20Sopenharmony_ci } 38238c2ecf20Sopenharmony_ci 38248c2ecf20Sopenharmony_ci hdl = container_of(obj, struct v4l2_ctrl_handler, 38258c2ecf20Sopenharmony_ci req_obj); 38268c2ecf20Sopenharmony_ci } 38278c2ecf20Sopenharmony_ci 38288c2ecf20Sopenharmony_ci ret = v4l2_g_ext_ctrls_common(hdl, cs, vdev); 38298c2ecf20Sopenharmony_ci 38308c2ecf20Sopenharmony_ci if (obj) { 38318c2ecf20Sopenharmony_ci media_request_unlock_for_access(req); 38328c2ecf20Sopenharmony_ci media_request_object_put(obj); 38338c2ecf20Sopenharmony_ci media_request_put(req); 38348c2ecf20Sopenharmony_ci } 38358c2ecf20Sopenharmony_ci return ret; 38368c2ecf20Sopenharmony_ci} 38378c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_g_ext_ctrls); 38388c2ecf20Sopenharmony_ci 38398c2ecf20Sopenharmony_ci/* Helper function to get a single control */ 38408c2ecf20Sopenharmony_cistatic int get_ctrl(struct v4l2_ctrl *ctrl, struct v4l2_ext_control *c) 38418c2ecf20Sopenharmony_ci{ 38428c2ecf20Sopenharmony_ci struct v4l2_ctrl *master = ctrl->cluster[0]; 38438c2ecf20Sopenharmony_ci int ret = 0; 38448c2ecf20Sopenharmony_ci int i; 38458c2ecf20Sopenharmony_ci 38468c2ecf20Sopenharmony_ci /* Compound controls are not supported. The new_to_user() and 38478c2ecf20Sopenharmony_ci * cur_to_user() calls below would need to be modified not to access 38488c2ecf20Sopenharmony_ci * userspace memory when called from get_ctrl(). 38498c2ecf20Sopenharmony_ci */ 38508c2ecf20Sopenharmony_ci if (!ctrl->is_int && ctrl->type != V4L2_CTRL_TYPE_INTEGER64) 38518c2ecf20Sopenharmony_ci return -EINVAL; 38528c2ecf20Sopenharmony_ci 38538c2ecf20Sopenharmony_ci if (ctrl->flags & V4L2_CTRL_FLAG_WRITE_ONLY) 38548c2ecf20Sopenharmony_ci return -EACCES; 38558c2ecf20Sopenharmony_ci 38568c2ecf20Sopenharmony_ci v4l2_ctrl_lock(master); 38578c2ecf20Sopenharmony_ci /* g_volatile_ctrl will update the current control values */ 38588c2ecf20Sopenharmony_ci if (ctrl->flags & V4L2_CTRL_FLAG_VOLATILE) { 38598c2ecf20Sopenharmony_ci for (i = 0; i < master->ncontrols; i++) 38608c2ecf20Sopenharmony_ci cur_to_new(master->cluster[i]); 38618c2ecf20Sopenharmony_ci ret = call_op(master, g_volatile_ctrl); 38628c2ecf20Sopenharmony_ci new_to_user(c, ctrl); 38638c2ecf20Sopenharmony_ci } else { 38648c2ecf20Sopenharmony_ci cur_to_user(c, ctrl); 38658c2ecf20Sopenharmony_ci } 38668c2ecf20Sopenharmony_ci v4l2_ctrl_unlock(master); 38678c2ecf20Sopenharmony_ci return ret; 38688c2ecf20Sopenharmony_ci} 38698c2ecf20Sopenharmony_ci 38708c2ecf20Sopenharmony_ciint v4l2_g_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_control *control) 38718c2ecf20Sopenharmony_ci{ 38728c2ecf20Sopenharmony_ci struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, control->id); 38738c2ecf20Sopenharmony_ci struct v4l2_ext_control c; 38748c2ecf20Sopenharmony_ci int ret; 38758c2ecf20Sopenharmony_ci 38768c2ecf20Sopenharmony_ci if (ctrl == NULL || !ctrl->is_int) 38778c2ecf20Sopenharmony_ci return -EINVAL; 38788c2ecf20Sopenharmony_ci ret = get_ctrl(ctrl, &c); 38798c2ecf20Sopenharmony_ci control->value = c.value; 38808c2ecf20Sopenharmony_ci return ret; 38818c2ecf20Sopenharmony_ci} 38828c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_g_ctrl); 38838c2ecf20Sopenharmony_ci 38848c2ecf20Sopenharmony_cis32 v4l2_ctrl_g_ctrl(struct v4l2_ctrl *ctrl) 38858c2ecf20Sopenharmony_ci{ 38868c2ecf20Sopenharmony_ci struct v4l2_ext_control c; 38878c2ecf20Sopenharmony_ci 38888c2ecf20Sopenharmony_ci /* It's a driver bug if this happens. */ 38898c2ecf20Sopenharmony_ci if (WARN_ON(!ctrl->is_int)) 38908c2ecf20Sopenharmony_ci return 0; 38918c2ecf20Sopenharmony_ci c.value = 0; 38928c2ecf20Sopenharmony_ci get_ctrl(ctrl, &c); 38938c2ecf20Sopenharmony_ci return c.value; 38948c2ecf20Sopenharmony_ci} 38958c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_g_ctrl); 38968c2ecf20Sopenharmony_ci 38978c2ecf20Sopenharmony_cis64 v4l2_ctrl_g_ctrl_int64(struct v4l2_ctrl *ctrl) 38988c2ecf20Sopenharmony_ci{ 38998c2ecf20Sopenharmony_ci struct v4l2_ext_control c; 39008c2ecf20Sopenharmony_ci 39018c2ecf20Sopenharmony_ci /* It's a driver bug if this happens. */ 39028c2ecf20Sopenharmony_ci if (WARN_ON(ctrl->is_ptr || ctrl->type != V4L2_CTRL_TYPE_INTEGER64)) 39038c2ecf20Sopenharmony_ci return 0; 39048c2ecf20Sopenharmony_ci c.value64 = 0; 39058c2ecf20Sopenharmony_ci get_ctrl(ctrl, &c); 39068c2ecf20Sopenharmony_ci return c.value64; 39078c2ecf20Sopenharmony_ci} 39088c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_g_ctrl_int64); 39098c2ecf20Sopenharmony_ci 39108c2ecf20Sopenharmony_ci 39118c2ecf20Sopenharmony_ci/* Core function that calls try/s_ctrl and ensures that the new value is 39128c2ecf20Sopenharmony_ci copied to the current value on a set. 39138c2ecf20Sopenharmony_ci Must be called with ctrl->handler->lock held. */ 39148c2ecf20Sopenharmony_cistatic int try_or_set_cluster(struct v4l2_fh *fh, struct v4l2_ctrl *master, 39158c2ecf20Sopenharmony_ci bool set, u32 ch_flags) 39168c2ecf20Sopenharmony_ci{ 39178c2ecf20Sopenharmony_ci bool update_flag; 39188c2ecf20Sopenharmony_ci int ret; 39198c2ecf20Sopenharmony_ci int i; 39208c2ecf20Sopenharmony_ci 39218c2ecf20Sopenharmony_ci /* Go through the cluster and either validate the new value or 39228c2ecf20Sopenharmony_ci (if no new value was set), copy the current value to the new 39238c2ecf20Sopenharmony_ci value, ensuring a consistent view for the control ops when 39248c2ecf20Sopenharmony_ci called. */ 39258c2ecf20Sopenharmony_ci for (i = 0; i < master->ncontrols; i++) { 39268c2ecf20Sopenharmony_ci struct v4l2_ctrl *ctrl = master->cluster[i]; 39278c2ecf20Sopenharmony_ci 39288c2ecf20Sopenharmony_ci if (ctrl == NULL) 39298c2ecf20Sopenharmony_ci continue; 39308c2ecf20Sopenharmony_ci 39318c2ecf20Sopenharmony_ci if (!ctrl->is_new) { 39328c2ecf20Sopenharmony_ci cur_to_new(ctrl); 39338c2ecf20Sopenharmony_ci continue; 39348c2ecf20Sopenharmony_ci } 39358c2ecf20Sopenharmony_ci /* Check again: it may have changed since the 39368c2ecf20Sopenharmony_ci previous check in try_or_set_ext_ctrls(). */ 39378c2ecf20Sopenharmony_ci if (set && (ctrl->flags & V4L2_CTRL_FLAG_GRABBED)) 39388c2ecf20Sopenharmony_ci return -EBUSY; 39398c2ecf20Sopenharmony_ci } 39408c2ecf20Sopenharmony_ci 39418c2ecf20Sopenharmony_ci ret = call_op(master, try_ctrl); 39428c2ecf20Sopenharmony_ci 39438c2ecf20Sopenharmony_ci /* Don't set if there is no change */ 39448c2ecf20Sopenharmony_ci if (ret || !set || !cluster_changed(master)) 39458c2ecf20Sopenharmony_ci return ret; 39468c2ecf20Sopenharmony_ci ret = call_op(master, s_ctrl); 39478c2ecf20Sopenharmony_ci if (ret) 39488c2ecf20Sopenharmony_ci return ret; 39498c2ecf20Sopenharmony_ci 39508c2ecf20Sopenharmony_ci /* If OK, then make the new values permanent. */ 39518c2ecf20Sopenharmony_ci update_flag = is_cur_manual(master) != is_new_manual(master); 39528c2ecf20Sopenharmony_ci 39538c2ecf20Sopenharmony_ci for (i = 0; i < master->ncontrols; i++) { 39548c2ecf20Sopenharmony_ci /* 39558c2ecf20Sopenharmony_ci * If we switch from auto to manual mode, and this cluster 39568c2ecf20Sopenharmony_ci * contains volatile controls, then all non-master controls 39578c2ecf20Sopenharmony_ci * have to be marked as changed. The 'new' value contains 39588c2ecf20Sopenharmony_ci * the volatile value (obtained by update_from_auto_cluster), 39598c2ecf20Sopenharmony_ci * which now has to become the current value. 39608c2ecf20Sopenharmony_ci */ 39618c2ecf20Sopenharmony_ci if (i && update_flag && is_new_manual(master) && 39628c2ecf20Sopenharmony_ci master->has_volatiles && master->cluster[i]) 39638c2ecf20Sopenharmony_ci master->cluster[i]->has_changed = true; 39648c2ecf20Sopenharmony_ci 39658c2ecf20Sopenharmony_ci new_to_cur(fh, master->cluster[i], ch_flags | 39668c2ecf20Sopenharmony_ci ((update_flag && i > 0) ? V4L2_EVENT_CTRL_CH_FLAGS : 0)); 39678c2ecf20Sopenharmony_ci } 39688c2ecf20Sopenharmony_ci return 0; 39698c2ecf20Sopenharmony_ci} 39708c2ecf20Sopenharmony_ci 39718c2ecf20Sopenharmony_ci/* Validate controls. */ 39728c2ecf20Sopenharmony_cistatic int validate_ctrls(struct v4l2_ext_controls *cs, 39738c2ecf20Sopenharmony_ci struct v4l2_ctrl_helper *helpers, 39748c2ecf20Sopenharmony_ci struct video_device *vdev, 39758c2ecf20Sopenharmony_ci bool set) 39768c2ecf20Sopenharmony_ci{ 39778c2ecf20Sopenharmony_ci unsigned i; 39788c2ecf20Sopenharmony_ci int ret = 0; 39798c2ecf20Sopenharmony_ci 39808c2ecf20Sopenharmony_ci cs->error_idx = cs->count; 39818c2ecf20Sopenharmony_ci for (i = 0; i < cs->count; i++) { 39828c2ecf20Sopenharmony_ci struct v4l2_ctrl *ctrl = helpers[i].ref->ctrl; 39838c2ecf20Sopenharmony_ci union v4l2_ctrl_ptr p_new; 39848c2ecf20Sopenharmony_ci 39858c2ecf20Sopenharmony_ci cs->error_idx = i; 39868c2ecf20Sopenharmony_ci 39878c2ecf20Sopenharmony_ci if (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY) { 39888c2ecf20Sopenharmony_ci dprintk(vdev, 39898c2ecf20Sopenharmony_ci "control id 0x%x is read-only\n", 39908c2ecf20Sopenharmony_ci ctrl->id); 39918c2ecf20Sopenharmony_ci return -EACCES; 39928c2ecf20Sopenharmony_ci } 39938c2ecf20Sopenharmony_ci /* This test is also done in try_set_control_cluster() which 39948c2ecf20Sopenharmony_ci is called in atomic context, so that has the final say, 39958c2ecf20Sopenharmony_ci but it makes sense to do an up-front check as well. Once 39968c2ecf20Sopenharmony_ci an error occurs in try_set_control_cluster() some other 39978c2ecf20Sopenharmony_ci controls may have been set already and we want to do a 39988c2ecf20Sopenharmony_ci best-effort to avoid that. */ 39998c2ecf20Sopenharmony_ci if (set && (ctrl->flags & V4L2_CTRL_FLAG_GRABBED)) { 40008c2ecf20Sopenharmony_ci dprintk(vdev, 40018c2ecf20Sopenharmony_ci "control id 0x%x is grabbed, cannot set\n", 40028c2ecf20Sopenharmony_ci ctrl->id); 40038c2ecf20Sopenharmony_ci return -EBUSY; 40048c2ecf20Sopenharmony_ci } 40058c2ecf20Sopenharmony_ci /* 40068c2ecf20Sopenharmony_ci * Skip validation for now if the payload needs to be copied 40078c2ecf20Sopenharmony_ci * from userspace into kernelspace. We'll validate those later. 40088c2ecf20Sopenharmony_ci */ 40098c2ecf20Sopenharmony_ci if (ctrl->is_ptr) 40108c2ecf20Sopenharmony_ci continue; 40118c2ecf20Sopenharmony_ci if (ctrl->type == V4L2_CTRL_TYPE_INTEGER64) 40128c2ecf20Sopenharmony_ci p_new.p_s64 = &cs->controls[i].value64; 40138c2ecf20Sopenharmony_ci else 40148c2ecf20Sopenharmony_ci p_new.p_s32 = &cs->controls[i].value; 40158c2ecf20Sopenharmony_ci ret = validate_new(ctrl, p_new); 40168c2ecf20Sopenharmony_ci if (ret) 40178c2ecf20Sopenharmony_ci return ret; 40188c2ecf20Sopenharmony_ci } 40198c2ecf20Sopenharmony_ci return 0; 40208c2ecf20Sopenharmony_ci} 40218c2ecf20Sopenharmony_ci 40228c2ecf20Sopenharmony_ci/* Obtain the current volatile values of an autocluster and mark them 40238c2ecf20Sopenharmony_ci as new. */ 40248c2ecf20Sopenharmony_cistatic void update_from_auto_cluster(struct v4l2_ctrl *master) 40258c2ecf20Sopenharmony_ci{ 40268c2ecf20Sopenharmony_ci int i; 40278c2ecf20Sopenharmony_ci 40288c2ecf20Sopenharmony_ci for (i = 1; i < master->ncontrols; i++) 40298c2ecf20Sopenharmony_ci cur_to_new(master->cluster[i]); 40308c2ecf20Sopenharmony_ci if (!call_op(master, g_volatile_ctrl)) 40318c2ecf20Sopenharmony_ci for (i = 1; i < master->ncontrols; i++) 40328c2ecf20Sopenharmony_ci if (master->cluster[i]) 40338c2ecf20Sopenharmony_ci master->cluster[i]->is_new = 1; 40348c2ecf20Sopenharmony_ci} 40358c2ecf20Sopenharmony_ci 40368c2ecf20Sopenharmony_ci/* Try or try-and-set controls */ 40378c2ecf20Sopenharmony_cistatic int try_set_ext_ctrls_common(struct v4l2_fh *fh, 40388c2ecf20Sopenharmony_ci struct v4l2_ctrl_handler *hdl, 40398c2ecf20Sopenharmony_ci struct v4l2_ext_controls *cs, 40408c2ecf20Sopenharmony_ci struct video_device *vdev, bool set) 40418c2ecf20Sopenharmony_ci{ 40428c2ecf20Sopenharmony_ci struct v4l2_ctrl_helper helper[4]; 40438c2ecf20Sopenharmony_ci struct v4l2_ctrl_helper *helpers = helper; 40448c2ecf20Sopenharmony_ci unsigned i, j; 40458c2ecf20Sopenharmony_ci int ret; 40468c2ecf20Sopenharmony_ci 40478c2ecf20Sopenharmony_ci cs->error_idx = cs->count; 40488c2ecf20Sopenharmony_ci 40498c2ecf20Sopenharmony_ci /* Default value cannot be changed */ 40508c2ecf20Sopenharmony_ci if (cs->which == V4L2_CTRL_WHICH_DEF_VAL) { 40518c2ecf20Sopenharmony_ci dprintk(vdev, "%s: cannot change default value\n", 40528c2ecf20Sopenharmony_ci video_device_node_name(vdev)); 40538c2ecf20Sopenharmony_ci return -EINVAL; 40548c2ecf20Sopenharmony_ci } 40558c2ecf20Sopenharmony_ci 40568c2ecf20Sopenharmony_ci cs->which = V4L2_CTRL_ID2WHICH(cs->which); 40578c2ecf20Sopenharmony_ci 40588c2ecf20Sopenharmony_ci if (hdl == NULL) { 40598c2ecf20Sopenharmony_ci dprintk(vdev, "%s: invalid null control handler\n", 40608c2ecf20Sopenharmony_ci video_device_node_name(vdev)); 40618c2ecf20Sopenharmony_ci return -EINVAL; 40628c2ecf20Sopenharmony_ci } 40638c2ecf20Sopenharmony_ci 40648c2ecf20Sopenharmony_ci if (cs->count == 0) 40658c2ecf20Sopenharmony_ci return class_check(hdl, cs->which); 40668c2ecf20Sopenharmony_ci 40678c2ecf20Sopenharmony_ci if (cs->count > ARRAY_SIZE(helper)) { 40688c2ecf20Sopenharmony_ci helpers = kvmalloc_array(cs->count, sizeof(helper[0]), 40698c2ecf20Sopenharmony_ci GFP_KERNEL); 40708c2ecf20Sopenharmony_ci if (!helpers) 40718c2ecf20Sopenharmony_ci return -ENOMEM; 40728c2ecf20Sopenharmony_ci } 40738c2ecf20Sopenharmony_ci ret = prepare_ext_ctrls(hdl, cs, helpers, vdev, false); 40748c2ecf20Sopenharmony_ci if (!ret) 40758c2ecf20Sopenharmony_ci ret = validate_ctrls(cs, helpers, vdev, set); 40768c2ecf20Sopenharmony_ci if (ret && set) 40778c2ecf20Sopenharmony_ci cs->error_idx = cs->count; 40788c2ecf20Sopenharmony_ci for (i = 0; !ret && i < cs->count; i++) { 40798c2ecf20Sopenharmony_ci struct v4l2_ctrl *master; 40808c2ecf20Sopenharmony_ci u32 idx = i; 40818c2ecf20Sopenharmony_ci 40828c2ecf20Sopenharmony_ci if (helpers[i].mref == NULL) 40838c2ecf20Sopenharmony_ci continue; 40848c2ecf20Sopenharmony_ci 40858c2ecf20Sopenharmony_ci cs->error_idx = i; 40868c2ecf20Sopenharmony_ci master = helpers[i].mref->ctrl; 40878c2ecf20Sopenharmony_ci v4l2_ctrl_lock(master); 40888c2ecf20Sopenharmony_ci 40898c2ecf20Sopenharmony_ci /* Reset the 'is_new' flags of the cluster */ 40908c2ecf20Sopenharmony_ci for (j = 0; j < master->ncontrols; j++) 40918c2ecf20Sopenharmony_ci if (master->cluster[j]) 40928c2ecf20Sopenharmony_ci master->cluster[j]->is_new = 0; 40938c2ecf20Sopenharmony_ci 40948c2ecf20Sopenharmony_ci /* For volatile autoclusters that are currently in auto mode 40958c2ecf20Sopenharmony_ci we need to discover if it will be set to manual mode. 40968c2ecf20Sopenharmony_ci If so, then we have to copy the current volatile values 40978c2ecf20Sopenharmony_ci first since those will become the new manual values (which 40988c2ecf20Sopenharmony_ci may be overwritten by explicit new values from this set 40998c2ecf20Sopenharmony_ci of controls). */ 41008c2ecf20Sopenharmony_ci if (master->is_auto && master->has_volatiles && 41018c2ecf20Sopenharmony_ci !is_cur_manual(master)) { 41028c2ecf20Sopenharmony_ci /* Pick an initial non-manual value */ 41038c2ecf20Sopenharmony_ci s32 new_auto_val = master->manual_mode_value + 1; 41048c2ecf20Sopenharmony_ci u32 tmp_idx = idx; 41058c2ecf20Sopenharmony_ci 41068c2ecf20Sopenharmony_ci do { 41078c2ecf20Sopenharmony_ci /* Check if the auto control is part of the 41088c2ecf20Sopenharmony_ci list, and remember the new value. */ 41098c2ecf20Sopenharmony_ci if (helpers[tmp_idx].ref->ctrl == master) 41108c2ecf20Sopenharmony_ci new_auto_val = cs->controls[tmp_idx].value; 41118c2ecf20Sopenharmony_ci tmp_idx = helpers[tmp_idx].next; 41128c2ecf20Sopenharmony_ci } while (tmp_idx); 41138c2ecf20Sopenharmony_ci /* If the new value == the manual value, then copy 41148c2ecf20Sopenharmony_ci the current volatile values. */ 41158c2ecf20Sopenharmony_ci if (new_auto_val == master->manual_mode_value) 41168c2ecf20Sopenharmony_ci update_from_auto_cluster(master); 41178c2ecf20Sopenharmony_ci } 41188c2ecf20Sopenharmony_ci 41198c2ecf20Sopenharmony_ci /* Copy the new caller-supplied control values. 41208c2ecf20Sopenharmony_ci user_to_new() sets 'is_new' to 1. */ 41218c2ecf20Sopenharmony_ci do { 41228c2ecf20Sopenharmony_ci struct v4l2_ctrl *ctrl = helpers[idx].ref->ctrl; 41238c2ecf20Sopenharmony_ci 41248c2ecf20Sopenharmony_ci ret = user_to_new(cs->controls + idx, ctrl); 41258c2ecf20Sopenharmony_ci if (!ret && ctrl->is_ptr) 41268c2ecf20Sopenharmony_ci ret = validate_new(ctrl, ctrl->p_new); 41278c2ecf20Sopenharmony_ci idx = helpers[idx].next; 41288c2ecf20Sopenharmony_ci } while (!ret && idx); 41298c2ecf20Sopenharmony_ci 41308c2ecf20Sopenharmony_ci if (!ret) 41318c2ecf20Sopenharmony_ci ret = try_or_set_cluster(fh, master, 41328c2ecf20Sopenharmony_ci !hdl->req_obj.req && set, 0); 41338c2ecf20Sopenharmony_ci if (!ret && hdl->req_obj.req && set) { 41348c2ecf20Sopenharmony_ci for (j = 0; j < master->ncontrols; j++) { 41358c2ecf20Sopenharmony_ci struct v4l2_ctrl_ref *ref = 41368c2ecf20Sopenharmony_ci find_ref(hdl, master->cluster[j]->id); 41378c2ecf20Sopenharmony_ci 41388c2ecf20Sopenharmony_ci new_to_req(ref); 41398c2ecf20Sopenharmony_ci } 41408c2ecf20Sopenharmony_ci } 41418c2ecf20Sopenharmony_ci 41428c2ecf20Sopenharmony_ci /* Copy the new values back to userspace. */ 41438c2ecf20Sopenharmony_ci if (!ret) { 41448c2ecf20Sopenharmony_ci idx = i; 41458c2ecf20Sopenharmony_ci do { 41468c2ecf20Sopenharmony_ci ret = new_to_user(cs->controls + idx, 41478c2ecf20Sopenharmony_ci helpers[idx].ref->ctrl); 41488c2ecf20Sopenharmony_ci idx = helpers[idx].next; 41498c2ecf20Sopenharmony_ci } while (!ret && idx); 41508c2ecf20Sopenharmony_ci } 41518c2ecf20Sopenharmony_ci v4l2_ctrl_unlock(master); 41528c2ecf20Sopenharmony_ci } 41538c2ecf20Sopenharmony_ci 41548c2ecf20Sopenharmony_ci if (cs->count > ARRAY_SIZE(helper)) 41558c2ecf20Sopenharmony_ci kvfree(helpers); 41568c2ecf20Sopenharmony_ci return ret; 41578c2ecf20Sopenharmony_ci} 41588c2ecf20Sopenharmony_ci 41598c2ecf20Sopenharmony_cistatic int try_set_ext_ctrls(struct v4l2_fh *fh, 41608c2ecf20Sopenharmony_ci struct v4l2_ctrl_handler *hdl, 41618c2ecf20Sopenharmony_ci struct video_device *vdev, 41628c2ecf20Sopenharmony_ci struct media_device *mdev, 41638c2ecf20Sopenharmony_ci struct v4l2_ext_controls *cs, bool set) 41648c2ecf20Sopenharmony_ci{ 41658c2ecf20Sopenharmony_ci struct media_request_object *obj = NULL; 41668c2ecf20Sopenharmony_ci struct media_request *req = NULL; 41678c2ecf20Sopenharmony_ci int ret; 41688c2ecf20Sopenharmony_ci 41698c2ecf20Sopenharmony_ci if (cs->which == V4L2_CTRL_WHICH_REQUEST_VAL) { 41708c2ecf20Sopenharmony_ci if (!mdev) { 41718c2ecf20Sopenharmony_ci dprintk(vdev, "%s: missing media device\n", 41728c2ecf20Sopenharmony_ci video_device_node_name(vdev)); 41738c2ecf20Sopenharmony_ci return -EINVAL; 41748c2ecf20Sopenharmony_ci } 41758c2ecf20Sopenharmony_ci 41768c2ecf20Sopenharmony_ci if (cs->request_fd < 0) { 41778c2ecf20Sopenharmony_ci dprintk(vdev, "%s: invalid request fd %d\n", 41788c2ecf20Sopenharmony_ci video_device_node_name(vdev), cs->request_fd); 41798c2ecf20Sopenharmony_ci return -EINVAL; 41808c2ecf20Sopenharmony_ci } 41818c2ecf20Sopenharmony_ci 41828c2ecf20Sopenharmony_ci req = media_request_get_by_fd(mdev, cs->request_fd); 41838c2ecf20Sopenharmony_ci if (IS_ERR(req)) { 41848c2ecf20Sopenharmony_ci dprintk(vdev, "%s: cannot find request fd %d\n", 41858c2ecf20Sopenharmony_ci video_device_node_name(vdev), cs->request_fd); 41868c2ecf20Sopenharmony_ci return PTR_ERR(req); 41878c2ecf20Sopenharmony_ci } 41888c2ecf20Sopenharmony_ci 41898c2ecf20Sopenharmony_ci ret = media_request_lock_for_update(req); 41908c2ecf20Sopenharmony_ci if (ret) { 41918c2ecf20Sopenharmony_ci dprintk(vdev, "%s: cannot lock request fd %d\n", 41928c2ecf20Sopenharmony_ci video_device_node_name(vdev), cs->request_fd); 41938c2ecf20Sopenharmony_ci media_request_put(req); 41948c2ecf20Sopenharmony_ci return ret; 41958c2ecf20Sopenharmony_ci } 41968c2ecf20Sopenharmony_ci 41978c2ecf20Sopenharmony_ci obj = v4l2_ctrls_find_req_obj(hdl, req, set); 41988c2ecf20Sopenharmony_ci if (IS_ERR(obj)) { 41998c2ecf20Sopenharmony_ci dprintk(vdev, 42008c2ecf20Sopenharmony_ci "%s: cannot find request object for request fd %d\n", 42018c2ecf20Sopenharmony_ci video_device_node_name(vdev), 42028c2ecf20Sopenharmony_ci cs->request_fd); 42038c2ecf20Sopenharmony_ci media_request_unlock_for_update(req); 42048c2ecf20Sopenharmony_ci media_request_put(req); 42058c2ecf20Sopenharmony_ci return PTR_ERR(obj); 42068c2ecf20Sopenharmony_ci } 42078c2ecf20Sopenharmony_ci hdl = container_of(obj, struct v4l2_ctrl_handler, 42088c2ecf20Sopenharmony_ci req_obj); 42098c2ecf20Sopenharmony_ci } 42108c2ecf20Sopenharmony_ci 42118c2ecf20Sopenharmony_ci ret = try_set_ext_ctrls_common(fh, hdl, cs, vdev, set); 42128c2ecf20Sopenharmony_ci if (ret) 42138c2ecf20Sopenharmony_ci dprintk(vdev, 42148c2ecf20Sopenharmony_ci "%s: try_set_ext_ctrls_common failed (%d)\n", 42158c2ecf20Sopenharmony_ci video_device_node_name(vdev), ret); 42168c2ecf20Sopenharmony_ci 42178c2ecf20Sopenharmony_ci if (obj) { 42188c2ecf20Sopenharmony_ci media_request_unlock_for_update(req); 42198c2ecf20Sopenharmony_ci media_request_object_put(obj); 42208c2ecf20Sopenharmony_ci media_request_put(req); 42218c2ecf20Sopenharmony_ci } 42228c2ecf20Sopenharmony_ci 42238c2ecf20Sopenharmony_ci return ret; 42248c2ecf20Sopenharmony_ci} 42258c2ecf20Sopenharmony_ci 42268c2ecf20Sopenharmony_ciint v4l2_try_ext_ctrls(struct v4l2_ctrl_handler *hdl, 42278c2ecf20Sopenharmony_ci struct video_device *vdev, 42288c2ecf20Sopenharmony_ci struct media_device *mdev, 42298c2ecf20Sopenharmony_ci struct v4l2_ext_controls *cs) 42308c2ecf20Sopenharmony_ci{ 42318c2ecf20Sopenharmony_ci return try_set_ext_ctrls(NULL, hdl, vdev, mdev, cs, false); 42328c2ecf20Sopenharmony_ci} 42338c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_try_ext_ctrls); 42348c2ecf20Sopenharmony_ci 42358c2ecf20Sopenharmony_ciint v4l2_s_ext_ctrls(struct v4l2_fh *fh, 42368c2ecf20Sopenharmony_ci struct v4l2_ctrl_handler *hdl, 42378c2ecf20Sopenharmony_ci struct video_device *vdev, 42388c2ecf20Sopenharmony_ci struct media_device *mdev, 42398c2ecf20Sopenharmony_ci struct v4l2_ext_controls *cs) 42408c2ecf20Sopenharmony_ci{ 42418c2ecf20Sopenharmony_ci return try_set_ext_ctrls(fh, hdl, vdev, mdev, cs, true); 42428c2ecf20Sopenharmony_ci} 42438c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_s_ext_ctrls); 42448c2ecf20Sopenharmony_ci 42458c2ecf20Sopenharmony_ci/* Helper function for VIDIOC_S_CTRL compatibility */ 42468c2ecf20Sopenharmony_cistatic int set_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, u32 ch_flags) 42478c2ecf20Sopenharmony_ci{ 42488c2ecf20Sopenharmony_ci struct v4l2_ctrl *master = ctrl->cluster[0]; 42498c2ecf20Sopenharmony_ci int ret; 42508c2ecf20Sopenharmony_ci int i; 42518c2ecf20Sopenharmony_ci 42528c2ecf20Sopenharmony_ci /* Reset the 'is_new' flags of the cluster */ 42538c2ecf20Sopenharmony_ci for (i = 0; i < master->ncontrols; i++) 42548c2ecf20Sopenharmony_ci if (master->cluster[i]) 42558c2ecf20Sopenharmony_ci master->cluster[i]->is_new = 0; 42568c2ecf20Sopenharmony_ci 42578c2ecf20Sopenharmony_ci ret = validate_new(ctrl, ctrl->p_new); 42588c2ecf20Sopenharmony_ci if (ret) 42598c2ecf20Sopenharmony_ci return ret; 42608c2ecf20Sopenharmony_ci 42618c2ecf20Sopenharmony_ci /* For autoclusters with volatiles that are switched from auto to 42628c2ecf20Sopenharmony_ci manual mode we have to update the current volatile values since 42638c2ecf20Sopenharmony_ci those will become the initial manual values after such a switch. */ 42648c2ecf20Sopenharmony_ci if (master->is_auto && master->has_volatiles && ctrl == master && 42658c2ecf20Sopenharmony_ci !is_cur_manual(master) && ctrl->val == master->manual_mode_value) 42668c2ecf20Sopenharmony_ci update_from_auto_cluster(master); 42678c2ecf20Sopenharmony_ci 42688c2ecf20Sopenharmony_ci ctrl->is_new = 1; 42698c2ecf20Sopenharmony_ci return try_or_set_cluster(fh, master, true, ch_flags); 42708c2ecf20Sopenharmony_ci} 42718c2ecf20Sopenharmony_ci 42728c2ecf20Sopenharmony_ci/* Helper function for VIDIOC_S_CTRL compatibility */ 42738c2ecf20Sopenharmony_cistatic int set_ctrl_lock(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, 42748c2ecf20Sopenharmony_ci struct v4l2_ext_control *c) 42758c2ecf20Sopenharmony_ci{ 42768c2ecf20Sopenharmony_ci int ret; 42778c2ecf20Sopenharmony_ci 42788c2ecf20Sopenharmony_ci v4l2_ctrl_lock(ctrl); 42798c2ecf20Sopenharmony_ci user_to_new(c, ctrl); 42808c2ecf20Sopenharmony_ci ret = set_ctrl(fh, ctrl, 0); 42818c2ecf20Sopenharmony_ci if (!ret) 42828c2ecf20Sopenharmony_ci cur_to_user(c, ctrl); 42838c2ecf20Sopenharmony_ci v4l2_ctrl_unlock(ctrl); 42848c2ecf20Sopenharmony_ci return ret; 42858c2ecf20Sopenharmony_ci} 42868c2ecf20Sopenharmony_ci 42878c2ecf20Sopenharmony_ciint v4l2_s_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl, 42888c2ecf20Sopenharmony_ci struct v4l2_control *control) 42898c2ecf20Sopenharmony_ci{ 42908c2ecf20Sopenharmony_ci struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, control->id); 42918c2ecf20Sopenharmony_ci struct v4l2_ext_control c = { control->id }; 42928c2ecf20Sopenharmony_ci int ret; 42938c2ecf20Sopenharmony_ci 42948c2ecf20Sopenharmony_ci if (ctrl == NULL || !ctrl->is_int) 42958c2ecf20Sopenharmony_ci return -EINVAL; 42968c2ecf20Sopenharmony_ci 42978c2ecf20Sopenharmony_ci if (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY) 42988c2ecf20Sopenharmony_ci return -EACCES; 42998c2ecf20Sopenharmony_ci 43008c2ecf20Sopenharmony_ci c.value = control->value; 43018c2ecf20Sopenharmony_ci ret = set_ctrl_lock(fh, ctrl, &c); 43028c2ecf20Sopenharmony_ci control->value = c.value; 43038c2ecf20Sopenharmony_ci return ret; 43048c2ecf20Sopenharmony_ci} 43058c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_s_ctrl); 43068c2ecf20Sopenharmony_ci 43078c2ecf20Sopenharmony_ciint __v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val) 43088c2ecf20Sopenharmony_ci{ 43098c2ecf20Sopenharmony_ci lockdep_assert_held(ctrl->handler->lock); 43108c2ecf20Sopenharmony_ci 43118c2ecf20Sopenharmony_ci /* It's a driver bug if this happens. */ 43128c2ecf20Sopenharmony_ci if (WARN_ON(!ctrl->is_int)) 43138c2ecf20Sopenharmony_ci return -EINVAL; 43148c2ecf20Sopenharmony_ci ctrl->val = val; 43158c2ecf20Sopenharmony_ci return set_ctrl(NULL, ctrl, 0); 43168c2ecf20Sopenharmony_ci} 43178c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__v4l2_ctrl_s_ctrl); 43188c2ecf20Sopenharmony_ci 43198c2ecf20Sopenharmony_ciint __v4l2_ctrl_s_ctrl_int64(struct v4l2_ctrl *ctrl, s64 val) 43208c2ecf20Sopenharmony_ci{ 43218c2ecf20Sopenharmony_ci lockdep_assert_held(ctrl->handler->lock); 43228c2ecf20Sopenharmony_ci 43238c2ecf20Sopenharmony_ci /* It's a driver bug if this happens. */ 43248c2ecf20Sopenharmony_ci if (WARN_ON(ctrl->is_ptr || ctrl->type != V4L2_CTRL_TYPE_INTEGER64)) 43258c2ecf20Sopenharmony_ci return -EINVAL; 43268c2ecf20Sopenharmony_ci *ctrl->p_new.p_s64 = val; 43278c2ecf20Sopenharmony_ci return set_ctrl(NULL, ctrl, 0); 43288c2ecf20Sopenharmony_ci} 43298c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__v4l2_ctrl_s_ctrl_int64); 43308c2ecf20Sopenharmony_ci 43318c2ecf20Sopenharmony_ciint __v4l2_ctrl_s_ctrl_string(struct v4l2_ctrl *ctrl, const char *s) 43328c2ecf20Sopenharmony_ci{ 43338c2ecf20Sopenharmony_ci lockdep_assert_held(ctrl->handler->lock); 43348c2ecf20Sopenharmony_ci 43358c2ecf20Sopenharmony_ci /* It's a driver bug if this happens. */ 43368c2ecf20Sopenharmony_ci if (WARN_ON(ctrl->type != V4L2_CTRL_TYPE_STRING)) 43378c2ecf20Sopenharmony_ci return -EINVAL; 43388c2ecf20Sopenharmony_ci strscpy(ctrl->p_new.p_char, s, ctrl->maximum + 1); 43398c2ecf20Sopenharmony_ci return set_ctrl(NULL, ctrl, 0); 43408c2ecf20Sopenharmony_ci} 43418c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__v4l2_ctrl_s_ctrl_string); 43428c2ecf20Sopenharmony_ci 43438c2ecf20Sopenharmony_ciint __v4l2_ctrl_s_ctrl_compound(struct v4l2_ctrl *ctrl, 43448c2ecf20Sopenharmony_ci enum v4l2_ctrl_type type, const void *p) 43458c2ecf20Sopenharmony_ci{ 43468c2ecf20Sopenharmony_ci lockdep_assert_held(ctrl->handler->lock); 43478c2ecf20Sopenharmony_ci 43488c2ecf20Sopenharmony_ci /* It's a driver bug if this happens. */ 43498c2ecf20Sopenharmony_ci if (WARN_ON(ctrl->type != type)) 43508c2ecf20Sopenharmony_ci return -EINVAL; 43518c2ecf20Sopenharmony_ci memcpy(ctrl->p_new.p, p, ctrl->elems * ctrl->elem_size); 43528c2ecf20Sopenharmony_ci return set_ctrl(NULL, ctrl, 0); 43538c2ecf20Sopenharmony_ci} 43548c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__v4l2_ctrl_s_ctrl_compound); 43558c2ecf20Sopenharmony_ci 43568c2ecf20Sopenharmony_civoid v4l2_ctrl_request_complete(struct media_request *req, 43578c2ecf20Sopenharmony_ci struct v4l2_ctrl_handler *main_hdl) 43588c2ecf20Sopenharmony_ci{ 43598c2ecf20Sopenharmony_ci struct media_request_object *obj; 43608c2ecf20Sopenharmony_ci struct v4l2_ctrl_handler *hdl; 43618c2ecf20Sopenharmony_ci struct v4l2_ctrl_ref *ref; 43628c2ecf20Sopenharmony_ci 43638c2ecf20Sopenharmony_ci if (!req || !main_hdl) 43648c2ecf20Sopenharmony_ci return; 43658c2ecf20Sopenharmony_ci 43668c2ecf20Sopenharmony_ci /* 43678c2ecf20Sopenharmony_ci * Note that it is valid if nothing was found. It means 43688c2ecf20Sopenharmony_ci * that this request doesn't have any controls and so just 43698c2ecf20Sopenharmony_ci * wants to leave the controls unchanged. 43708c2ecf20Sopenharmony_ci */ 43718c2ecf20Sopenharmony_ci obj = media_request_object_find(req, &req_ops, main_hdl); 43728c2ecf20Sopenharmony_ci if (!obj) 43738c2ecf20Sopenharmony_ci return; 43748c2ecf20Sopenharmony_ci hdl = container_of(obj, struct v4l2_ctrl_handler, req_obj); 43758c2ecf20Sopenharmony_ci 43768c2ecf20Sopenharmony_ci list_for_each_entry(ref, &hdl->ctrl_refs, node) { 43778c2ecf20Sopenharmony_ci struct v4l2_ctrl *ctrl = ref->ctrl; 43788c2ecf20Sopenharmony_ci struct v4l2_ctrl *master = ctrl->cluster[0]; 43798c2ecf20Sopenharmony_ci unsigned int i; 43808c2ecf20Sopenharmony_ci 43818c2ecf20Sopenharmony_ci if (ctrl->flags & V4L2_CTRL_FLAG_VOLATILE) { 43828c2ecf20Sopenharmony_ci v4l2_ctrl_lock(master); 43838c2ecf20Sopenharmony_ci /* g_volatile_ctrl will update the current control values */ 43848c2ecf20Sopenharmony_ci for (i = 0; i < master->ncontrols; i++) 43858c2ecf20Sopenharmony_ci cur_to_new(master->cluster[i]); 43868c2ecf20Sopenharmony_ci call_op(master, g_volatile_ctrl); 43878c2ecf20Sopenharmony_ci new_to_req(ref); 43888c2ecf20Sopenharmony_ci v4l2_ctrl_unlock(master); 43898c2ecf20Sopenharmony_ci continue; 43908c2ecf20Sopenharmony_ci } 43918c2ecf20Sopenharmony_ci if (ref->valid_p_req) 43928c2ecf20Sopenharmony_ci continue; 43938c2ecf20Sopenharmony_ci 43948c2ecf20Sopenharmony_ci /* Copy the current control value into the request */ 43958c2ecf20Sopenharmony_ci v4l2_ctrl_lock(ctrl); 43968c2ecf20Sopenharmony_ci cur_to_req(ref); 43978c2ecf20Sopenharmony_ci v4l2_ctrl_unlock(ctrl); 43988c2ecf20Sopenharmony_ci } 43998c2ecf20Sopenharmony_ci 44008c2ecf20Sopenharmony_ci mutex_lock(main_hdl->lock); 44018c2ecf20Sopenharmony_ci WARN_ON(!hdl->request_is_queued); 44028c2ecf20Sopenharmony_ci list_del_init(&hdl->requests_queued); 44038c2ecf20Sopenharmony_ci hdl->request_is_queued = false; 44048c2ecf20Sopenharmony_ci mutex_unlock(main_hdl->lock); 44058c2ecf20Sopenharmony_ci media_request_object_complete(obj); 44068c2ecf20Sopenharmony_ci media_request_object_put(obj); 44078c2ecf20Sopenharmony_ci} 44088c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_request_complete); 44098c2ecf20Sopenharmony_ci 44108c2ecf20Sopenharmony_ciint v4l2_ctrl_request_setup(struct media_request *req, 44118c2ecf20Sopenharmony_ci struct v4l2_ctrl_handler *main_hdl) 44128c2ecf20Sopenharmony_ci{ 44138c2ecf20Sopenharmony_ci struct media_request_object *obj; 44148c2ecf20Sopenharmony_ci struct v4l2_ctrl_handler *hdl; 44158c2ecf20Sopenharmony_ci struct v4l2_ctrl_ref *ref; 44168c2ecf20Sopenharmony_ci int ret = 0; 44178c2ecf20Sopenharmony_ci 44188c2ecf20Sopenharmony_ci if (!req || !main_hdl) 44198c2ecf20Sopenharmony_ci return 0; 44208c2ecf20Sopenharmony_ci 44218c2ecf20Sopenharmony_ci if (WARN_ON(req->state != MEDIA_REQUEST_STATE_QUEUED)) 44228c2ecf20Sopenharmony_ci return -EBUSY; 44238c2ecf20Sopenharmony_ci 44248c2ecf20Sopenharmony_ci /* 44258c2ecf20Sopenharmony_ci * Note that it is valid if nothing was found. It means 44268c2ecf20Sopenharmony_ci * that this request doesn't have any controls and so just 44278c2ecf20Sopenharmony_ci * wants to leave the controls unchanged. 44288c2ecf20Sopenharmony_ci */ 44298c2ecf20Sopenharmony_ci obj = media_request_object_find(req, &req_ops, main_hdl); 44308c2ecf20Sopenharmony_ci if (!obj) 44318c2ecf20Sopenharmony_ci return 0; 44328c2ecf20Sopenharmony_ci if (obj->completed) { 44338c2ecf20Sopenharmony_ci media_request_object_put(obj); 44348c2ecf20Sopenharmony_ci return -EBUSY; 44358c2ecf20Sopenharmony_ci } 44368c2ecf20Sopenharmony_ci hdl = container_of(obj, struct v4l2_ctrl_handler, req_obj); 44378c2ecf20Sopenharmony_ci 44388c2ecf20Sopenharmony_ci list_for_each_entry(ref, &hdl->ctrl_refs, node) 44398c2ecf20Sopenharmony_ci ref->req_done = false; 44408c2ecf20Sopenharmony_ci 44418c2ecf20Sopenharmony_ci list_for_each_entry(ref, &hdl->ctrl_refs, node) { 44428c2ecf20Sopenharmony_ci struct v4l2_ctrl *ctrl = ref->ctrl; 44438c2ecf20Sopenharmony_ci struct v4l2_ctrl *master = ctrl->cluster[0]; 44448c2ecf20Sopenharmony_ci bool have_new_data = false; 44458c2ecf20Sopenharmony_ci int i; 44468c2ecf20Sopenharmony_ci 44478c2ecf20Sopenharmony_ci /* 44488c2ecf20Sopenharmony_ci * Skip if this control was already handled by a cluster. 44498c2ecf20Sopenharmony_ci * Skip button controls and read-only controls. 44508c2ecf20Sopenharmony_ci */ 44518c2ecf20Sopenharmony_ci if (ref->req_done || ctrl->type == V4L2_CTRL_TYPE_BUTTON || 44528c2ecf20Sopenharmony_ci (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY)) 44538c2ecf20Sopenharmony_ci continue; 44548c2ecf20Sopenharmony_ci 44558c2ecf20Sopenharmony_ci v4l2_ctrl_lock(master); 44568c2ecf20Sopenharmony_ci for (i = 0; i < master->ncontrols; i++) { 44578c2ecf20Sopenharmony_ci if (master->cluster[i]) { 44588c2ecf20Sopenharmony_ci struct v4l2_ctrl_ref *r = 44598c2ecf20Sopenharmony_ci find_ref(hdl, master->cluster[i]->id); 44608c2ecf20Sopenharmony_ci 44618c2ecf20Sopenharmony_ci if (r->valid_p_req) { 44628c2ecf20Sopenharmony_ci have_new_data = true; 44638c2ecf20Sopenharmony_ci break; 44648c2ecf20Sopenharmony_ci } 44658c2ecf20Sopenharmony_ci } 44668c2ecf20Sopenharmony_ci } 44678c2ecf20Sopenharmony_ci if (!have_new_data) { 44688c2ecf20Sopenharmony_ci v4l2_ctrl_unlock(master); 44698c2ecf20Sopenharmony_ci continue; 44708c2ecf20Sopenharmony_ci } 44718c2ecf20Sopenharmony_ci 44728c2ecf20Sopenharmony_ci for (i = 0; i < master->ncontrols; i++) { 44738c2ecf20Sopenharmony_ci if (master->cluster[i]) { 44748c2ecf20Sopenharmony_ci struct v4l2_ctrl_ref *r = 44758c2ecf20Sopenharmony_ci find_ref(hdl, master->cluster[i]->id); 44768c2ecf20Sopenharmony_ci 44778c2ecf20Sopenharmony_ci req_to_new(r); 44788c2ecf20Sopenharmony_ci master->cluster[i]->is_new = 1; 44798c2ecf20Sopenharmony_ci r->req_done = true; 44808c2ecf20Sopenharmony_ci } 44818c2ecf20Sopenharmony_ci } 44828c2ecf20Sopenharmony_ci /* 44838c2ecf20Sopenharmony_ci * For volatile autoclusters that are currently in auto mode 44848c2ecf20Sopenharmony_ci * we need to discover if it will be set to manual mode. 44858c2ecf20Sopenharmony_ci * If so, then we have to copy the current volatile values 44868c2ecf20Sopenharmony_ci * first since those will become the new manual values (which 44878c2ecf20Sopenharmony_ci * may be overwritten by explicit new values from this set 44888c2ecf20Sopenharmony_ci * of controls). 44898c2ecf20Sopenharmony_ci */ 44908c2ecf20Sopenharmony_ci if (master->is_auto && master->has_volatiles && 44918c2ecf20Sopenharmony_ci !is_cur_manual(master)) { 44928c2ecf20Sopenharmony_ci s32 new_auto_val = *master->p_new.p_s32; 44938c2ecf20Sopenharmony_ci 44948c2ecf20Sopenharmony_ci /* 44958c2ecf20Sopenharmony_ci * If the new value == the manual value, then copy 44968c2ecf20Sopenharmony_ci * the current volatile values. 44978c2ecf20Sopenharmony_ci */ 44988c2ecf20Sopenharmony_ci if (new_auto_val == master->manual_mode_value) 44998c2ecf20Sopenharmony_ci update_from_auto_cluster(master); 45008c2ecf20Sopenharmony_ci } 45018c2ecf20Sopenharmony_ci 45028c2ecf20Sopenharmony_ci ret = try_or_set_cluster(NULL, master, true, 0); 45038c2ecf20Sopenharmony_ci v4l2_ctrl_unlock(master); 45048c2ecf20Sopenharmony_ci 45058c2ecf20Sopenharmony_ci if (ret) 45068c2ecf20Sopenharmony_ci break; 45078c2ecf20Sopenharmony_ci } 45088c2ecf20Sopenharmony_ci 45098c2ecf20Sopenharmony_ci media_request_object_put(obj); 45108c2ecf20Sopenharmony_ci return ret; 45118c2ecf20Sopenharmony_ci} 45128c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_request_setup); 45138c2ecf20Sopenharmony_ci 45148c2ecf20Sopenharmony_civoid v4l2_ctrl_notify(struct v4l2_ctrl *ctrl, v4l2_ctrl_notify_fnc notify, void *priv) 45158c2ecf20Sopenharmony_ci{ 45168c2ecf20Sopenharmony_ci if (ctrl == NULL) 45178c2ecf20Sopenharmony_ci return; 45188c2ecf20Sopenharmony_ci if (notify == NULL) { 45198c2ecf20Sopenharmony_ci ctrl->call_notify = 0; 45208c2ecf20Sopenharmony_ci return; 45218c2ecf20Sopenharmony_ci } 45228c2ecf20Sopenharmony_ci if (WARN_ON(ctrl->handler->notify && ctrl->handler->notify != notify)) 45238c2ecf20Sopenharmony_ci return; 45248c2ecf20Sopenharmony_ci ctrl->handler->notify = notify; 45258c2ecf20Sopenharmony_ci ctrl->handler->notify_priv = priv; 45268c2ecf20Sopenharmony_ci ctrl->call_notify = 1; 45278c2ecf20Sopenharmony_ci} 45288c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_notify); 45298c2ecf20Sopenharmony_ci 45308c2ecf20Sopenharmony_ciint __v4l2_ctrl_modify_range(struct v4l2_ctrl *ctrl, 45318c2ecf20Sopenharmony_ci s64 min, s64 max, u64 step, s64 def) 45328c2ecf20Sopenharmony_ci{ 45338c2ecf20Sopenharmony_ci bool value_changed; 45348c2ecf20Sopenharmony_ci bool range_changed = false; 45358c2ecf20Sopenharmony_ci int ret; 45368c2ecf20Sopenharmony_ci 45378c2ecf20Sopenharmony_ci lockdep_assert_held(ctrl->handler->lock); 45388c2ecf20Sopenharmony_ci 45398c2ecf20Sopenharmony_ci switch (ctrl->type) { 45408c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_INTEGER: 45418c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_INTEGER64: 45428c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_BOOLEAN: 45438c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_MENU: 45448c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_INTEGER_MENU: 45458c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_BITMASK: 45468c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_U8: 45478c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_U16: 45488c2ecf20Sopenharmony_ci case V4L2_CTRL_TYPE_U32: 45498c2ecf20Sopenharmony_ci if (ctrl->is_array) 45508c2ecf20Sopenharmony_ci return -EINVAL; 45518c2ecf20Sopenharmony_ci ret = check_range(ctrl->type, min, max, step, def); 45528c2ecf20Sopenharmony_ci if (ret) 45538c2ecf20Sopenharmony_ci return ret; 45548c2ecf20Sopenharmony_ci break; 45558c2ecf20Sopenharmony_ci default: 45568c2ecf20Sopenharmony_ci return -EINVAL; 45578c2ecf20Sopenharmony_ci } 45588c2ecf20Sopenharmony_ci if ((ctrl->minimum != min) || (ctrl->maximum != max) || 45598c2ecf20Sopenharmony_ci (ctrl->step != step) || ctrl->default_value != def) { 45608c2ecf20Sopenharmony_ci range_changed = true; 45618c2ecf20Sopenharmony_ci ctrl->minimum = min; 45628c2ecf20Sopenharmony_ci ctrl->maximum = max; 45638c2ecf20Sopenharmony_ci ctrl->step = step; 45648c2ecf20Sopenharmony_ci ctrl->default_value = def; 45658c2ecf20Sopenharmony_ci } 45668c2ecf20Sopenharmony_ci cur_to_new(ctrl); 45678c2ecf20Sopenharmony_ci if (validate_new(ctrl, ctrl->p_new)) { 45688c2ecf20Sopenharmony_ci if (ctrl->type == V4L2_CTRL_TYPE_INTEGER64) 45698c2ecf20Sopenharmony_ci *ctrl->p_new.p_s64 = def; 45708c2ecf20Sopenharmony_ci else 45718c2ecf20Sopenharmony_ci *ctrl->p_new.p_s32 = def; 45728c2ecf20Sopenharmony_ci } 45738c2ecf20Sopenharmony_ci 45748c2ecf20Sopenharmony_ci if (ctrl->type == V4L2_CTRL_TYPE_INTEGER64) 45758c2ecf20Sopenharmony_ci value_changed = *ctrl->p_new.p_s64 != *ctrl->p_cur.p_s64; 45768c2ecf20Sopenharmony_ci else 45778c2ecf20Sopenharmony_ci value_changed = *ctrl->p_new.p_s32 != *ctrl->p_cur.p_s32; 45788c2ecf20Sopenharmony_ci if (value_changed) 45798c2ecf20Sopenharmony_ci ret = set_ctrl(NULL, ctrl, V4L2_EVENT_CTRL_CH_RANGE); 45808c2ecf20Sopenharmony_ci else if (range_changed) 45818c2ecf20Sopenharmony_ci send_event(NULL, ctrl, V4L2_EVENT_CTRL_CH_RANGE); 45828c2ecf20Sopenharmony_ci return ret; 45838c2ecf20Sopenharmony_ci} 45848c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__v4l2_ctrl_modify_range); 45858c2ecf20Sopenharmony_ci 45868c2ecf20Sopenharmony_cistatic int v4l2_ctrl_add_event(struct v4l2_subscribed_event *sev, unsigned elems) 45878c2ecf20Sopenharmony_ci{ 45888c2ecf20Sopenharmony_ci struct v4l2_ctrl *ctrl = v4l2_ctrl_find(sev->fh->ctrl_handler, sev->id); 45898c2ecf20Sopenharmony_ci 45908c2ecf20Sopenharmony_ci if (ctrl == NULL) 45918c2ecf20Sopenharmony_ci return -EINVAL; 45928c2ecf20Sopenharmony_ci 45938c2ecf20Sopenharmony_ci v4l2_ctrl_lock(ctrl); 45948c2ecf20Sopenharmony_ci list_add_tail(&sev->node, &ctrl->ev_subs); 45958c2ecf20Sopenharmony_ci if (ctrl->type != V4L2_CTRL_TYPE_CTRL_CLASS && 45968c2ecf20Sopenharmony_ci (sev->flags & V4L2_EVENT_SUB_FL_SEND_INITIAL)) { 45978c2ecf20Sopenharmony_ci struct v4l2_event ev; 45988c2ecf20Sopenharmony_ci u32 changes = V4L2_EVENT_CTRL_CH_FLAGS; 45998c2ecf20Sopenharmony_ci 46008c2ecf20Sopenharmony_ci if (!(ctrl->flags & V4L2_CTRL_FLAG_WRITE_ONLY)) 46018c2ecf20Sopenharmony_ci changes |= V4L2_EVENT_CTRL_CH_VALUE; 46028c2ecf20Sopenharmony_ci fill_event(&ev, ctrl, changes); 46038c2ecf20Sopenharmony_ci /* Mark the queue as active, allowing this initial 46048c2ecf20Sopenharmony_ci event to be accepted. */ 46058c2ecf20Sopenharmony_ci sev->elems = elems; 46068c2ecf20Sopenharmony_ci v4l2_event_queue_fh(sev->fh, &ev); 46078c2ecf20Sopenharmony_ci } 46088c2ecf20Sopenharmony_ci v4l2_ctrl_unlock(ctrl); 46098c2ecf20Sopenharmony_ci return 0; 46108c2ecf20Sopenharmony_ci} 46118c2ecf20Sopenharmony_ci 46128c2ecf20Sopenharmony_cistatic void v4l2_ctrl_del_event(struct v4l2_subscribed_event *sev) 46138c2ecf20Sopenharmony_ci{ 46148c2ecf20Sopenharmony_ci struct v4l2_ctrl *ctrl = v4l2_ctrl_find(sev->fh->ctrl_handler, sev->id); 46158c2ecf20Sopenharmony_ci 46168c2ecf20Sopenharmony_ci if (ctrl == NULL) 46178c2ecf20Sopenharmony_ci return; 46188c2ecf20Sopenharmony_ci 46198c2ecf20Sopenharmony_ci v4l2_ctrl_lock(ctrl); 46208c2ecf20Sopenharmony_ci list_del(&sev->node); 46218c2ecf20Sopenharmony_ci v4l2_ctrl_unlock(ctrl); 46228c2ecf20Sopenharmony_ci} 46238c2ecf20Sopenharmony_ci 46248c2ecf20Sopenharmony_civoid v4l2_ctrl_replace(struct v4l2_event *old, const struct v4l2_event *new) 46258c2ecf20Sopenharmony_ci{ 46268c2ecf20Sopenharmony_ci u32 old_changes = old->u.ctrl.changes; 46278c2ecf20Sopenharmony_ci 46288c2ecf20Sopenharmony_ci old->u.ctrl = new->u.ctrl; 46298c2ecf20Sopenharmony_ci old->u.ctrl.changes |= old_changes; 46308c2ecf20Sopenharmony_ci} 46318c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_replace); 46328c2ecf20Sopenharmony_ci 46338c2ecf20Sopenharmony_civoid v4l2_ctrl_merge(const struct v4l2_event *old, struct v4l2_event *new) 46348c2ecf20Sopenharmony_ci{ 46358c2ecf20Sopenharmony_ci new->u.ctrl.changes |= old->u.ctrl.changes; 46368c2ecf20Sopenharmony_ci} 46378c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_merge); 46388c2ecf20Sopenharmony_ci 46398c2ecf20Sopenharmony_ciconst struct v4l2_subscribed_event_ops v4l2_ctrl_sub_ev_ops = { 46408c2ecf20Sopenharmony_ci .add = v4l2_ctrl_add_event, 46418c2ecf20Sopenharmony_ci .del = v4l2_ctrl_del_event, 46428c2ecf20Sopenharmony_ci .replace = v4l2_ctrl_replace, 46438c2ecf20Sopenharmony_ci .merge = v4l2_ctrl_merge, 46448c2ecf20Sopenharmony_ci}; 46458c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_sub_ev_ops); 46468c2ecf20Sopenharmony_ci 46478c2ecf20Sopenharmony_ciint v4l2_ctrl_log_status(struct file *file, void *fh) 46488c2ecf20Sopenharmony_ci{ 46498c2ecf20Sopenharmony_ci struct video_device *vfd = video_devdata(file); 46508c2ecf20Sopenharmony_ci struct v4l2_fh *vfh = file->private_data; 46518c2ecf20Sopenharmony_ci 46528c2ecf20Sopenharmony_ci if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) && vfd->v4l2_dev) 46538c2ecf20Sopenharmony_ci v4l2_ctrl_handler_log_status(vfh->ctrl_handler, 46548c2ecf20Sopenharmony_ci vfd->v4l2_dev->name); 46558c2ecf20Sopenharmony_ci return 0; 46568c2ecf20Sopenharmony_ci} 46578c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_log_status); 46588c2ecf20Sopenharmony_ci 46598c2ecf20Sopenharmony_ciint v4l2_ctrl_subscribe_event(struct v4l2_fh *fh, 46608c2ecf20Sopenharmony_ci const struct v4l2_event_subscription *sub) 46618c2ecf20Sopenharmony_ci{ 46628c2ecf20Sopenharmony_ci if (sub->type == V4L2_EVENT_CTRL) 46638c2ecf20Sopenharmony_ci return v4l2_event_subscribe(fh, sub, 0, &v4l2_ctrl_sub_ev_ops); 46648c2ecf20Sopenharmony_ci return -EINVAL; 46658c2ecf20Sopenharmony_ci} 46668c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_subscribe_event); 46678c2ecf20Sopenharmony_ci 46688c2ecf20Sopenharmony_ciint v4l2_ctrl_subdev_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh, 46698c2ecf20Sopenharmony_ci struct v4l2_event_subscription *sub) 46708c2ecf20Sopenharmony_ci{ 46718c2ecf20Sopenharmony_ci if (!sd->ctrl_handler) 46728c2ecf20Sopenharmony_ci return -EINVAL; 46738c2ecf20Sopenharmony_ci return v4l2_ctrl_subscribe_event(fh, sub); 46748c2ecf20Sopenharmony_ci} 46758c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_subdev_subscribe_event); 46768c2ecf20Sopenharmony_ci 46778c2ecf20Sopenharmony_ci__poll_t v4l2_ctrl_poll(struct file *file, struct poll_table_struct *wait) 46788c2ecf20Sopenharmony_ci{ 46798c2ecf20Sopenharmony_ci struct v4l2_fh *fh = file->private_data; 46808c2ecf20Sopenharmony_ci 46818c2ecf20Sopenharmony_ci poll_wait(file, &fh->wait, wait); 46828c2ecf20Sopenharmony_ci if (v4l2_event_pending(fh)) 46838c2ecf20Sopenharmony_ci return EPOLLPRI; 46848c2ecf20Sopenharmony_ci return 0; 46858c2ecf20Sopenharmony_ci} 46868c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_poll); 46878c2ecf20Sopenharmony_ci 46888c2ecf20Sopenharmony_ciint v4l2_ctrl_new_fwnode_properties(struct v4l2_ctrl_handler *hdl, 46898c2ecf20Sopenharmony_ci const struct v4l2_ctrl_ops *ctrl_ops, 46908c2ecf20Sopenharmony_ci const struct v4l2_fwnode_device_properties *p) 46918c2ecf20Sopenharmony_ci{ 46928c2ecf20Sopenharmony_ci if (p->orientation != V4L2_FWNODE_PROPERTY_UNSET) { 46938c2ecf20Sopenharmony_ci u32 orientation_ctrl; 46948c2ecf20Sopenharmony_ci 46958c2ecf20Sopenharmony_ci switch (p->orientation) { 46968c2ecf20Sopenharmony_ci case V4L2_FWNODE_ORIENTATION_FRONT: 46978c2ecf20Sopenharmony_ci orientation_ctrl = V4L2_CAMERA_ORIENTATION_FRONT; 46988c2ecf20Sopenharmony_ci break; 46998c2ecf20Sopenharmony_ci case V4L2_FWNODE_ORIENTATION_BACK: 47008c2ecf20Sopenharmony_ci orientation_ctrl = V4L2_CAMERA_ORIENTATION_BACK; 47018c2ecf20Sopenharmony_ci break; 47028c2ecf20Sopenharmony_ci case V4L2_FWNODE_ORIENTATION_EXTERNAL: 47038c2ecf20Sopenharmony_ci orientation_ctrl = V4L2_CAMERA_ORIENTATION_EXTERNAL; 47048c2ecf20Sopenharmony_ci break; 47058c2ecf20Sopenharmony_ci default: 47068c2ecf20Sopenharmony_ci return -EINVAL; 47078c2ecf20Sopenharmony_ci } 47088c2ecf20Sopenharmony_ci if (!v4l2_ctrl_new_std_menu(hdl, ctrl_ops, 47098c2ecf20Sopenharmony_ci V4L2_CID_CAMERA_ORIENTATION, 47108c2ecf20Sopenharmony_ci V4L2_CAMERA_ORIENTATION_EXTERNAL, 0, 47118c2ecf20Sopenharmony_ci orientation_ctrl)) 47128c2ecf20Sopenharmony_ci return hdl->error; 47138c2ecf20Sopenharmony_ci } 47148c2ecf20Sopenharmony_ci 47158c2ecf20Sopenharmony_ci if (p->rotation != V4L2_FWNODE_PROPERTY_UNSET) { 47168c2ecf20Sopenharmony_ci if (!v4l2_ctrl_new_std(hdl, ctrl_ops, 47178c2ecf20Sopenharmony_ci V4L2_CID_CAMERA_SENSOR_ROTATION, 47188c2ecf20Sopenharmony_ci p->rotation, p->rotation, 1, 47198c2ecf20Sopenharmony_ci p->rotation)) 47208c2ecf20Sopenharmony_ci return hdl->error; 47218c2ecf20Sopenharmony_ci } 47228c2ecf20Sopenharmony_ci 47238c2ecf20Sopenharmony_ci return hdl->error; 47248c2ecf20Sopenharmony_ci} 47258c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_new_fwnode_properties); 4726