.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | V4L2 controls framework implementation. |
---|
3 | 4 | |
---|
4 | 5 | Copyright (C) 2010 Hans Verkuil <hverkuil@xs4all.nl> |
---|
5 | 6 | |
---|
6 | | - This program is free software; you can redistribute it and/or modify |
---|
7 | | - it under the terms of the GNU General Public License as published by |
---|
8 | | - the Free Software Foundation; either version 2 of the License, or |
---|
9 | | - (at your option) any later version. |
---|
10 | | - |
---|
11 | | - This program is distributed in the hope that it will be useful, |
---|
12 | | - but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
13 | | - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
14 | | - GNU General Public License for more details. |
---|
15 | | - |
---|
16 | | - You should have received a copy of the GNU General Public License |
---|
17 | | - along with this program; if not, write to the Free Software |
---|
18 | | - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
---|
19 | 7 | */ |
---|
20 | 8 | |
---|
| 9 | +#define pr_fmt(fmt) "v4l2-ctrls: " fmt |
---|
| 10 | + |
---|
21 | 11 | #include <linux/ctype.h> |
---|
| 12 | +#include <linux/export.h> |
---|
22 | 13 | #include <linux/mm.h> |
---|
23 | 14 | #include <linux/slab.h> |
---|
24 | | -#include <linux/export.h> |
---|
25 | | -#include <media/v4l2-ioctl.h> |
---|
26 | | -#include <media/v4l2-device.h> |
---|
27 | 15 | #include <media/v4l2-ctrls.h> |
---|
28 | | -#include <media/v4l2-event.h> |
---|
29 | 16 | #include <media/v4l2-dev.h> |
---|
| 17 | +#include <media/v4l2-device.h> |
---|
| 18 | +#include <media/v4l2-event.h> |
---|
| 19 | +#include <media/v4l2-fwnode.h> |
---|
| 20 | +#include <media/v4l2-ioctl.h> |
---|
| 21 | + |
---|
| 22 | +#define dprintk(vdev, fmt, arg...) do { \ |
---|
| 23 | + if (!WARN_ON(!(vdev)) && ((vdev)->dev_debug & V4L2_DEV_DEBUG_CTRL)) \ |
---|
| 24 | + printk(KERN_DEBUG pr_fmt("%s: %s: " fmt), \ |
---|
| 25 | + __func__, video_device_node_name(vdev), ##arg); \ |
---|
| 26 | +} while (0) |
---|
30 | 27 | |
---|
31 | 28 | #define has_op(master, op) \ |
---|
32 | 29 | (master->ops && master->ops->op) |
---|
33 | 30 | #define call_op(master, op) \ |
---|
34 | 31 | (has_op(master, op) ? master->ops->op(master) : 0) |
---|
35 | 32 | |
---|
| 33 | +static const union v4l2_ctrl_ptr ptr_null; |
---|
| 34 | + |
---|
36 | 35 | /* Internal temporary helper struct, one for each v4l2_ext_control */ |
---|
37 | 36 | struct v4l2_ctrl_helper { |
---|
38 | 37 | /* Pointer to the control reference of the master control */ |
---|
39 | 38 | struct v4l2_ctrl_ref *mref; |
---|
40 | | - /* The control corresponding to the v4l2_ext_control ID field. */ |
---|
41 | | - struct v4l2_ctrl *ctrl; |
---|
| 39 | + /* The control ref corresponding to the v4l2_ext_control ID field. */ |
---|
| 40 | + struct v4l2_ctrl_ref *ref; |
---|
42 | 41 | /* v4l2_ext_control index of the next control belonging to the |
---|
43 | 42 | same cluster, or 0 if there isn't any. */ |
---|
44 | 43 | u32 next; |
---|
.. | .. |
---|
201 | 200 | static const char * const mpeg_video_bitrate_mode[] = { |
---|
202 | 201 | "Variable Bitrate", |
---|
203 | 202 | "Constant Bitrate", |
---|
| 203 | + "Constant Quality", |
---|
204 | 204 | NULL |
---|
205 | 205 | }; |
---|
206 | 206 | static const char * const mpeg_stream_type[] = { |
---|
.. | .. |
---|
411 | 411 | "Explicit", |
---|
412 | 412 | NULL, |
---|
413 | 413 | }; |
---|
| 414 | + static const char * const h264_decode_mode[] = { |
---|
| 415 | + "Slice-Based", |
---|
| 416 | + "Frame-Based", |
---|
| 417 | + NULL, |
---|
| 418 | + }; |
---|
| 419 | + static const char * const h264_start_code[] = { |
---|
| 420 | + "No Start Code", |
---|
| 421 | + "Annex B Start Code", |
---|
| 422 | + NULL, |
---|
| 423 | + }; |
---|
| 424 | + static const char * const h264_hierarchical_coding_type[] = { |
---|
| 425 | + "Hier Coding B", |
---|
| 426 | + "Hier Coding P", |
---|
| 427 | + NULL, |
---|
| 428 | + }; |
---|
| 429 | + static const char * const mpeg_mpeg2_level[] = { |
---|
| 430 | + "Low", |
---|
| 431 | + "Main", |
---|
| 432 | + "High 1440", |
---|
| 433 | + "High", |
---|
| 434 | + NULL, |
---|
| 435 | + }; |
---|
| 436 | + static const char * const mpeg2_profile[] = { |
---|
| 437 | + "Simple", |
---|
| 438 | + "Main", |
---|
| 439 | + "SNR Scalable", |
---|
| 440 | + "Spatially Scalable", |
---|
| 441 | + "High", |
---|
| 442 | + NULL, |
---|
| 443 | + }; |
---|
414 | 444 | static const char * const mpeg_mpeg4_level[] = { |
---|
415 | 445 | "0", |
---|
416 | 446 | "0b", |
---|
.. | .. |
---|
448 | 478 | "1", |
---|
449 | 479 | "2", |
---|
450 | 480 | "3", |
---|
| 481 | + NULL, |
---|
| 482 | + }; |
---|
| 483 | + static const char * const vp9_level[] = { |
---|
| 484 | + "1", |
---|
| 485 | + "1.1", |
---|
| 486 | + "2", |
---|
| 487 | + "2.1", |
---|
| 488 | + "3", |
---|
| 489 | + "3.1", |
---|
| 490 | + "4", |
---|
| 491 | + "4.1", |
---|
| 492 | + "5", |
---|
| 493 | + "5.1", |
---|
| 494 | + "5.2", |
---|
| 495 | + "6", |
---|
| 496 | + "6.1", |
---|
| 497 | + "6.2", |
---|
451 | 498 | NULL, |
---|
452 | 499 | }; |
---|
453 | 500 | |
---|
.. | .. |
---|
550 | 597 | "Disabled at slice boundary", |
---|
551 | 598 | "NULL", |
---|
552 | 599 | }; |
---|
| 600 | + static const char * const hevc_decode_mode[] = { |
---|
| 601 | + "Slice-Based", |
---|
| 602 | + "Frame-Based", |
---|
| 603 | + NULL, |
---|
| 604 | + }; |
---|
| 605 | + static const char * const hevc_start_code[] = { |
---|
| 606 | + "No Start Code", |
---|
| 607 | + "Annex B Start Code", |
---|
| 608 | + NULL, |
---|
| 609 | + }; |
---|
| 610 | + static const char * const camera_orientation[] = { |
---|
| 611 | + "Front", |
---|
| 612 | + "Back", |
---|
| 613 | + "External", |
---|
| 614 | + NULL, |
---|
| 615 | + }; |
---|
| 616 | + static const char * const mpeg_video_frame_skip[] = { |
---|
| 617 | + "Disabled", |
---|
| 618 | + "Level Limit", |
---|
| 619 | + "VBV/CPB Limit", |
---|
| 620 | + NULL, |
---|
| 621 | + }; |
---|
553 | 622 | |
---|
554 | 623 | switch (id) { |
---|
555 | 624 | case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: |
---|
.. | .. |
---|
611 | 680 | return flash_strobe_source; |
---|
612 | 681 | case V4L2_CID_MPEG_VIDEO_HEADER_MODE: |
---|
613 | 682 | return header_mode; |
---|
| 683 | + case V4L2_CID_MPEG_VIDEO_FRAME_SKIP_MODE: |
---|
| 684 | + return mpeg_video_frame_skip; |
---|
614 | 685 | case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE: |
---|
615 | 686 | return multi_slice; |
---|
616 | 687 | case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE: |
---|
.. | .. |
---|
627 | 698 | return h264_fp_arrangement_type; |
---|
628 | 699 | case V4L2_CID_MPEG_VIDEO_H264_FMO_MAP_TYPE: |
---|
629 | 700 | return h264_fmo_map_type; |
---|
| 701 | + case V4L2_CID_MPEG_VIDEO_H264_DECODE_MODE: |
---|
| 702 | + return h264_decode_mode; |
---|
| 703 | + case V4L2_CID_MPEG_VIDEO_H264_START_CODE: |
---|
| 704 | + return h264_start_code; |
---|
| 705 | + case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_TYPE: |
---|
| 706 | + return h264_hierarchical_coding_type; |
---|
| 707 | + case V4L2_CID_MPEG_VIDEO_MPEG2_LEVEL: |
---|
| 708 | + return mpeg_mpeg2_level; |
---|
| 709 | + case V4L2_CID_MPEG_VIDEO_MPEG2_PROFILE: |
---|
| 710 | + return mpeg2_profile; |
---|
630 | 711 | case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL: |
---|
631 | 712 | return mpeg_mpeg4_level; |
---|
632 | 713 | case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE: |
---|
.. | .. |
---|
637 | 718 | return vp8_profile; |
---|
638 | 719 | case V4L2_CID_MPEG_VIDEO_VP9_PROFILE: |
---|
639 | 720 | return vp9_profile; |
---|
| 721 | + case V4L2_CID_MPEG_VIDEO_VP9_LEVEL: |
---|
| 722 | + return vp9_level; |
---|
640 | 723 | case V4L2_CID_JPEG_CHROMA_SUBSAMPLING: |
---|
641 | 724 | return jpeg_chroma_subsampling; |
---|
642 | 725 | case V4L2_CID_DV_TX_MODE: |
---|
.. | .. |
---|
663 | 746 | return hevc_tier; |
---|
664 | 747 | case V4L2_CID_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE: |
---|
665 | 748 | return hevc_loop_filter_mode; |
---|
666 | | - |
---|
| 749 | + case V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE: |
---|
| 750 | + return hevc_decode_mode; |
---|
| 751 | + case V4L2_CID_MPEG_VIDEO_HEVC_START_CODE: |
---|
| 752 | + return hevc_start_code; |
---|
| 753 | + case V4L2_CID_CAMERA_ORIENTATION: |
---|
| 754 | + return camera_orientation; |
---|
667 | 755 | default: |
---|
668 | 756 | return NULL; |
---|
669 | 757 | } |
---|
.. | .. |
---|
779 | 867 | case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: return "Video GOP Closure"; |
---|
780 | 868 | case V4L2_CID_MPEG_VIDEO_PULLDOWN: return "Video Pulldown"; |
---|
781 | 869 | case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: return "Video Bitrate Mode"; |
---|
| 870 | + case V4L2_CID_MPEG_VIDEO_CONSTANT_QUALITY: return "Constant Quality"; |
---|
782 | 871 | case V4L2_CID_MPEG_VIDEO_BITRATE: return "Video Bitrate"; |
---|
783 | 872 | case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: return "Video Peak Bitrate"; |
---|
784 | 873 | case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION: return "Video Temporal Decimation"; |
---|
.. | .. |
---|
791 | 880 | case V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE: return "H264 MB Level Rate Control"; |
---|
792 | 881 | case V4L2_CID_MPEG_VIDEO_HEADER_MODE: return "Sequence Header Mode"; |
---|
793 | 882 | case V4L2_CID_MPEG_VIDEO_MAX_REF_PIC: return "Max Number of Reference Pics"; |
---|
| 883 | + case V4L2_CID_MPEG_VIDEO_FRAME_SKIP_MODE: return "Frame Skip Mode"; |
---|
| 884 | + case V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY: return "Display Delay"; |
---|
| 885 | + case V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY_ENABLE: return "Display Delay Enable"; |
---|
| 886 | + case V4L2_CID_MPEG_VIDEO_AU_DELIMITER: return "Generate Access Unit Delimiters"; |
---|
794 | 887 | case V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP: return "H263 I-Frame QP Value"; |
---|
795 | 888 | case V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP: return "H263 P-Frame QP Value"; |
---|
796 | 889 | case V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP: return "H263 B-Frame QP Value"; |
---|
.. | .. |
---|
830 | 923 | case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER:return "H264 Number of HC Layers"; |
---|
831 | 924 | case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_QP: |
---|
832 | 925 | return "H264 Set QP Value for HC Layers"; |
---|
| 926 | + case V4L2_CID_MPEG_VIDEO_H264_CONSTRAINED_INTRA_PREDICTION: |
---|
| 927 | + return "H264 Constrained Intra Pred"; |
---|
833 | 928 | case V4L2_CID_MPEG_VIDEO_H264_CHROMA_QP_INDEX_OFFSET: return "H264 Chroma QP Index Offset"; |
---|
| 929 | + case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MIN_QP: return "H264 I-Frame Minimum QP Value"; |
---|
| 930 | + case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MAX_QP: return "H264 I-Frame Maximum QP Value"; |
---|
| 931 | + case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MIN_QP: return "H264 P-Frame Minimum QP Value"; |
---|
| 932 | + case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MAX_QP: return "H264 P-Frame Maximum QP Value"; |
---|
| 933 | + case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_MIN_QP: return "H264 B-Frame Minimum QP Value"; |
---|
| 934 | + case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_MAX_QP: return "H264 B-Frame Maximum QP Value"; |
---|
| 935 | + case V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L0_BR: return "H264 Hierarchical Lay 0 Bitrate"; |
---|
| 936 | + case V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L1_BR: return "H264 Hierarchical Lay 1 Bitrate"; |
---|
| 937 | + case V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L2_BR: return "H264 Hierarchical Lay 2 Bitrate"; |
---|
| 938 | + case V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L3_BR: return "H264 Hierarchical Lay 3 Bitrate"; |
---|
| 939 | + case V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L4_BR: return "H264 Hierarchical Lay 4 Bitrate"; |
---|
| 940 | + case V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L5_BR: return "H264 Hierarchical Lay 5 Bitrate"; |
---|
| 941 | + case V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L6_BR: return "H264 Hierarchical Lay 6 Bitrate"; |
---|
| 942 | + case V4L2_CID_MPEG_VIDEO_H264_SPS: return "H264 Sequence Parameter Set"; |
---|
| 943 | + case V4L2_CID_MPEG_VIDEO_H264_PPS: return "H264 Picture Parameter Set"; |
---|
| 944 | + case V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX: return "H264 Scaling Matrix"; |
---|
| 945 | + case V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAMS: return "H264 Slice Parameters"; |
---|
| 946 | + case V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS: return "H264 Decode Parameters"; |
---|
| 947 | + case V4L2_CID_MPEG_VIDEO_H264_DECODE_MODE: return "H264 Decode Mode"; |
---|
| 948 | + case V4L2_CID_MPEG_VIDEO_H264_START_CODE: return "H264 Start Code"; |
---|
| 949 | + case V4L2_CID_MPEG_VIDEO_H264_PRED_WEIGHTS: return "H264 Prediction Weight Table"; |
---|
| 950 | + case V4L2_CID_MPEG_VIDEO_MPEG2_LEVEL: return "MPEG2 Level"; |
---|
| 951 | + case V4L2_CID_MPEG_VIDEO_MPEG2_PROFILE: return "MPEG2 Profile"; |
---|
834 | 952 | case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP: return "MPEG4 I-Frame QP Value"; |
---|
835 | 953 | case V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP: return "MPEG4 P-Frame QP Value"; |
---|
836 | 954 | case V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP: return "MPEG4 B-Frame QP Value"; |
---|
.. | .. |
---|
845 | 963 | case V4L2_CID_MPEG_VIDEO_VBV_SIZE: return "VBV Buffer Size"; |
---|
846 | 964 | case V4L2_CID_MPEG_VIDEO_DEC_PTS: return "Video Decoder PTS"; |
---|
847 | 965 | case V4L2_CID_MPEG_VIDEO_DEC_FRAME: return "Video Decoder Frame Count"; |
---|
| 966 | + case V4L2_CID_MPEG_VIDEO_DEC_CONCEAL_COLOR: return "Video Decoder Conceal Color"; |
---|
848 | 967 | case V4L2_CID_MPEG_VIDEO_VBV_DELAY: return "Initial Delay for VBV Control"; |
---|
849 | 968 | case V4L2_CID_MPEG_VIDEO_MV_H_SEARCH_RANGE: return "Horizontal MV Search Range"; |
---|
850 | 969 | case V4L2_CID_MPEG_VIDEO_MV_V_SEARCH_RANGE: return "Vertical MV Search Range"; |
---|
851 | 970 | case V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER: return "Repeat Sequence Header"; |
---|
852 | 971 | case V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME: return "Force Key Frame"; |
---|
| 972 | + case V4L2_CID_MPEG_VIDEO_BASELAYER_PRIORITY_ID: return "Base Layer Priority ID"; |
---|
| 973 | + case V4L2_CID_MPEG_VIDEO_LTR_COUNT: return "LTR Count"; |
---|
| 974 | + case V4L2_CID_MPEG_VIDEO_FRAME_LTR_INDEX: return "Frame LTR Index"; |
---|
| 975 | + case V4L2_CID_MPEG_VIDEO_USE_LTR_FRAMES: return "Use LTR Frames"; |
---|
| 976 | + case V4L2_CID_MPEG_VIDEO_MPEG2_SLICE_PARAMS: return "MPEG-2 Slice Parameters"; |
---|
| 977 | + case V4L2_CID_MPEG_VIDEO_MPEG2_QUANTIZATION: return "MPEG-2 Quantization Matrices"; |
---|
| 978 | + case V4L2_CID_MPEG_VIDEO_FWHT_PARAMS: return "FWHT Stateless Parameters"; |
---|
| 979 | + case V4L2_CID_FWHT_I_FRAME_QP: return "FWHT I-Frame QP Value"; |
---|
| 980 | + case V4L2_CID_FWHT_P_FRAME_QP: return "FWHT P-Frame QP Value"; |
---|
853 | 981 | |
---|
854 | 982 | /* VPX controls */ |
---|
855 | 983 | case V4L2_CID_MPEG_VIDEO_VPX_NUM_PARTITIONS: return "VPX Number of Partitions"; |
---|
.. | .. |
---|
865 | 993 | case V4L2_CID_MPEG_VIDEO_VPX_P_FRAME_QP: return "VPX P-Frame QP Value"; |
---|
866 | 994 | case V4L2_CID_MPEG_VIDEO_VP8_PROFILE: return "VP8 Profile"; |
---|
867 | 995 | case V4L2_CID_MPEG_VIDEO_VP9_PROFILE: return "VP9 Profile"; |
---|
| 996 | + case V4L2_CID_MPEG_VIDEO_VP9_LEVEL: return "VP9 Level"; |
---|
| 997 | + case V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER: return "VP8 Frame Header"; |
---|
868 | 998 | |
---|
869 | 999 | /* HEVC controls */ |
---|
870 | 1000 | case V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP: return "HEVC I-Frame QP Value"; |
---|
.. | .. |
---|
872 | 1002 | case V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_QP: return "HEVC B-Frame QP Value"; |
---|
873 | 1003 | case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP: return "HEVC Minimum QP Value"; |
---|
874 | 1004 | case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP: return "HEVC Maximum QP Value"; |
---|
| 1005 | + case V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_MIN_QP: return "HEVC I-Frame Minimum QP Value"; |
---|
| 1006 | + case V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_MAX_QP: return "HEVC I-Frame Maximum QP Value"; |
---|
| 1007 | + case V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_MIN_QP: return "HEVC P-Frame Minimum QP Value"; |
---|
| 1008 | + case V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_MAX_QP: return "HEVC P-Frame Maximum QP Value"; |
---|
| 1009 | + case V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_MIN_QP: return "HEVC B-Frame Minimum QP Value"; |
---|
| 1010 | + case V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_MAX_QP: return "HEVC B-Frame Maximum QP Value"; |
---|
875 | 1011 | case V4L2_CID_MPEG_VIDEO_HEVC_PROFILE: return "HEVC Profile"; |
---|
876 | 1012 | case V4L2_CID_MPEG_VIDEO_HEVC_LEVEL: return "HEVC Level"; |
---|
877 | 1013 | case V4L2_CID_MPEG_VIDEO_HEVC_TIER: return "HEVC Tier"; |
---|
.. | .. |
---|
912 | 1048 | case V4L2_CID_MPEG_VIDEO_HEVC_SIZE_OF_LENGTH_FIELD: return "HEVC Size of Length Field"; |
---|
913 | 1049 | case V4L2_CID_MPEG_VIDEO_REF_NUMBER_FOR_PFRAMES: return "Reference Frames for a P-Frame"; |
---|
914 | 1050 | case V4L2_CID_MPEG_VIDEO_PREPEND_SPSPPS_TO_IDR: return "Prepend SPS and PPS to IDR"; |
---|
| 1051 | + case V4L2_CID_MPEG_VIDEO_HEVC_SPS: return "HEVC Sequence Parameter Set"; |
---|
| 1052 | + case V4L2_CID_MPEG_VIDEO_HEVC_PPS: return "HEVC Picture Parameter Set"; |
---|
| 1053 | + case V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS: return "HEVC Slice Parameters"; |
---|
| 1054 | + case V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE: return "HEVC Decode Mode"; |
---|
| 1055 | + case V4L2_CID_MPEG_VIDEO_HEVC_START_CODE: return "HEVC Start Code"; |
---|
915 | 1056 | |
---|
916 | 1057 | /* CAMERA controls */ |
---|
917 | 1058 | /* Keep the order of the 'case's the same as in v4l2-controls.h! */ |
---|
.. | .. |
---|
949 | 1090 | case V4L2_CID_AUTO_FOCUS_RANGE: return "Auto Focus, Range"; |
---|
950 | 1091 | case V4L2_CID_PAN_SPEED: return "Pan, Speed"; |
---|
951 | 1092 | case V4L2_CID_TILT_SPEED: return "Tilt, Speed"; |
---|
| 1093 | + case V4L2_CID_UNIT_CELL_SIZE: return "Unit Cell Size"; |
---|
| 1094 | + case V4L2_CID_CAMERA_ORIENTATION: return "Camera Orientation"; |
---|
| 1095 | + case V4L2_CID_CAMERA_SENSOR_ROTATION: return "Camera Sensor Rotation"; |
---|
952 | 1096 | |
---|
953 | 1097 | /* FM Radio Modulator controls */ |
---|
954 | 1098 | /* Keep the order of the 'case's the same as in v4l2-controls.h! */ |
---|
.. | .. |
---|
1067 | 1211 | case V4L2_CID_DETECT_MD_GLOBAL_THRESHOLD: return "MD Global Threshold"; |
---|
1068 | 1212 | case V4L2_CID_DETECT_MD_THRESHOLD_GRID: return "MD Threshold Grid"; |
---|
1069 | 1213 | case V4L2_CID_DETECT_MD_REGION_GRID: return "MD Region Grid"; |
---|
| 1214 | + |
---|
| 1215 | + /* Colorimetry controls */ |
---|
| 1216 | + /* Keep the order of the 'case's the same as in v4l2-controls.h! */ |
---|
| 1217 | + case V4L2_CID_COLORIMETRY_CLASS: return "Colorimetry Controls"; |
---|
| 1218 | + case V4L2_CID_COLORIMETRY_HDR10_CLL_INFO: return "HDR10 Content Light Info"; |
---|
| 1219 | + case V4L2_CID_COLORIMETRY_HDR10_MASTERING_DISPLAY: return "HDR10 Mastering Display"; |
---|
1070 | 1220 | default: |
---|
1071 | 1221 | return NULL; |
---|
1072 | 1222 | } |
---|
.. | .. |
---|
1107 | 1257 | case V4L2_CID_FLASH_READY: |
---|
1108 | 1258 | case V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER: |
---|
1109 | 1259 | case V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE: |
---|
| 1260 | + case V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY_ENABLE: |
---|
1110 | 1261 | case V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE: |
---|
1111 | 1262 | case V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE: |
---|
1112 | 1263 | case V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM: |
---|
1113 | 1264 | case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE: |
---|
1114 | 1265 | case V4L2_CID_MPEG_VIDEO_MPEG4_QPEL: |
---|
1115 | 1266 | case V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER: |
---|
| 1267 | + case V4L2_CID_MPEG_VIDEO_AU_DELIMITER: |
---|
1116 | 1268 | case V4L2_CID_WIDE_DYNAMIC_RANGE: |
---|
1117 | 1269 | case V4L2_CID_IMAGE_STABILIZATION: |
---|
1118 | 1270 | case V4L2_CID_RDS_RECEPTION: |
---|
.. | .. |
---|
1142 | 1294 | break; |
---|
1143 | 1295 | case V4L2_CID_MPEG_VIDEO_MV_H_SEARCH_RANGE: |
---|
1144 | 1296 | case V4L2_CID_MPEG_VIDEO_MV_V_SEARCH_RANGE: |
---|
| 1297 | + case V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY: |
---|
1145 | 1298 | *type = V4L2_CTRL_TYPE_INTEGER; |
---|
| 1299 | + break; |
---|
| 1300 | + case V4L2_CID_MPEG_VIDEO_LTR_COUNT: |
---|
| 1301 | + *type = V4L2_CTRL_TYPE_INTEGER; |
---|
| 1302 | + break; |
---|
| 1303 | + case V4L2_CID_MPEG_VIDEO_FRAME_LTR_INDEX: |
---|
| 1304 | + *type = V4L2_CTRL_TYPE_INTEGER; |
---|
| 1305 | + *flags |= V4L2_CTRL_FLAG_EXECUTE_ON_WRITE; |
---|
| 1306 | + break; |
---|
| 1307 | + case V4L2_CID_MPEG_VIDEO_USE_LTR_FRAMES: |
---|
| 1308 | + *type = V4L2_CTRL_TYPE_BITMASK; |
---|
| 1309 | + *flags |= V4L2_CTRL_FLAG_EXECUTE_ON_WRITE; |
---|
1146 | 1310 | break; |
---|
1147 | 1311 | case V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME: |
---|
1148 | 1312 | case V4L2_CID_PAN_RESET: |
---|
.. | .. |
---|
1183 | 1347 | case V4L2_CID_FLASH_LED_MODE: |
---|
1184 | 1348 | case V4L2_CID_FLASH_STROBE_SOURCE: |
---|
1185 | 1349 | case V4L2_CID_MPEG_VIDEO_HEADER_MODE: |
---|
| 1350 | + case V4L2_CID_MPEG_VIDEO_FRAME_SKIP_MODE: |
---|
1186 | 1351 | case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE: |
---|
1187 | 1352 | case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE: |
---|
1188 | 1353 | case V4L2_CID_MPEG_VIDEO_H264_LEVEL: |
---|
.. | .. |
---|
1191 | 1356 | case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC: |
---|
1192 | 1357 | case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE: |
---|
1193 | 1358 | case V4L2_CID_MPEG_VIDEO_H264_FMO_MAP_TYPE: |
---|
| 1359 | + case V4L2_CID_MPEG_VIDEO_H264_DECODE_MODE: |
---|
| 1360 | + case V4L2_CID_MPEG_VIDEO_H264_START_CODE: |
---|
| 1361 | + case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_TYPE: |
---|
| 1362 | + case V4L2_CID_MPEG_VIDEO_MPEG2_LEVEL: |
---|
| 1363 | + case V4L2_CID_MPEG_VIDEO_MPEG2_PROFILE: |
---|
1194 | 1364 | case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL: |
---|
1195 | 1365 | case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE: |
---|
1196 | 1366 | case V4L2_CID_JPEG_CHROMA_SUBSAMPLING: |
---|
.. | .. |
---|
1208 | 1378 | case V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_SEL: |
---|
1209 | 1379 | case V4L2_CID_MPEG_VIDEO_VP8_PROFILE: |
---|
1210 | 1380 | case V4L2_CID_MPEG_VIDEO_VP9_PROFILE: |
---|
| 1381 | + case V4L2_CID_MPEG_VIDEO_VP9_LEVEL: |
---|
1211 | 1382 | case V4L2_CID_DETECT_MD_MODE: |
---|
1212 | 1383 | case V4L2_CID_MPEG_VIDEO_HEVC_PROFILE: |
---|
1213 | 1384 | case V4L2_CID_MPEG_VIDEO_HEVC_LEVEL: |
---|
.. | .. |
---|
1216 | 1387 | case V4L2_CID_MPEG_VIDEO_HEVC_SIZE_OF_LENGTH_FIELD: |
---|
1217 | 1388 | case V4L2_CID_MPEG_VIDEO_HEVC_TIER: |
---|
1218 | 1389 | case V4L2_CID_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE: |
---|
| 1390 | + case V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE: |
---|
| 1391 | + case V4L2_CID_MPEG_VIDEO_HEVC_START_CODE: |
---|
| 1392 | + case V4L2_CID_CAMERA_ORIENTATION: |
---|
1219 | 1393 | *type = V4L2_CTRL_TYPE_MENU; |
---|
1220 | 1394 | break; |
---|
1221 | 1395 | case V4L2_CID_LINK_FREQ: |
---|
.. | .. |
---|
1245 | 1419 | case V4L2_CID_FM_RX_CLASS: |
---|
1246 | 1420 | case V4L2_CID_RF_TUNER_CLASS: |
---|
1247 | 1421 | case V4L2_CID_DETECT_CLASS: |
---|
| 1422 | + case V4L2_CID_COLORIMETRY_CLASS: |
---|
1248 | 1423 | *type = V4L2_CTRL_TYPE_CTRL_CLASS; |
---|
1249 | | - /* You can neither read not write these */ |
---|
| 1424 | + /* You can neither read nor write these */ |
---|
1250 | 1425 | *flags |= V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_WRITE_ONLY; |
---|
1251 | 1426 | *min = *max = *step = *def = 0; |
---|
1252 | 1427 | break; |
---|
.. | .. |
---|
1286 | 1461 | *max = 0x7fffffffffffffffLL; |
---|
1287 | 1462 | *step = 1; |
---|
1288 | 1463 | break; |
---|
| 1464 | + case V4L2_CID_MPEG_VIDEO_DEC_CONCEAL_COLOR: |
---|
| 1465 | + *type = V4L2_CTRL_TYPE_INTEGER64; |
---|
| 1466 | + *min = 0; |
---|
| 1467 | + /* default for 8 bit black, luma is 16, chroma is 128 */ |
---|
| 1468 | + *def = 0x8000800010LL; |
---|
| 1469 | + *max = 0xffffffffffffLL; |
---|
| 1470 | + *step = 1; |
---|
| 1471 | + break; |
---|
1289 | 1472 | case V4L2_CID_PIXEL_RATE: |
---|
1290 | 1473 | *type = V4L2_CTRL_TYPE_INTEGER64; |
---|
1291 | 1474 | *flags |= V4L2_CTRL_FLAG_READ_ONLY; |
---|
.. | .. |
---|
1298 | 1481 | break; |
---|
1299 | 1482 | case V4L2_CID_RDS_TX_ALT_FREQS: |
---|
1300 | 1483 | *type = V4L2_CTRL_TYPE_U32; |
---|
| 1484 | + break; |
---|
| 1485 | + case V4L2_CID_MPEG_VIDEO_MPEG2_SLICE_PARAMS: |
---|
| 1486 | + *type = V4L2_CTRL_TYPE_MPEG2_SLICE_PARAMS; |
---|
| 1487 | + break; |
---|
| 1488 | + case V4L2_CID_MPEG_VIDEO_MPEG2_QUANTIZATION: |
---|
| 1489 | + *type = V4L2_CTRL_TYPE_MPEG2_QUANTIZATION; |
---|
| 1490 | + break; |
---|
| 1491 | + case V4L2_CID_MPEG_VIDEO_FWHT_PARAMS: |
---|
| 1492 | + *type = V4L2_CTRL_TYPE_FWHT_PARAMS; |
---|
| 1493 | + break; |
---|
| 1494 | + case V4L2_CID_MPEG_VIDEO_H264_SPS: |
---|
| 1495 | + *type = V4L2_CTRL_TYPE_H264_SPS; |
---|
| 1496 | + break; |
---|
| 1497 | + case V4L2_CID_MPEG_VIDEO_H264_PPS: |
---|
| 1498 | + *type = V4L2_CTRL_TYPE_H264_PPS; |
---|
| 1499 | + break; |
---|
| 1500 | + case V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX: |
---|
| 1501 | + *type = V4L2_CTRL_TYPE_H264_SCALING_MATRIX; |
---|
| 1502 | + break; |
---|
| 1503 | + case V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAMS: |
---|
| 1504 | + *type = V4L2_CTRL_TYPE_H264_SLICE_PARAMS; |
---|
| 1505 | + break; |
---|
| 1506 | + case V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS: |
---|
| 1507 | + *type = V4L2_CTRL_TYPE_H264_DECODE_PARAMS; |
---|
| 1508 | + break; |
---|
| 1509 | + case V4L2_CID_MPEG_VIDEO_H264_PRED_WEIGHTS: |
---|
| 1510 | + *type = V4L2_CTRL_TYPE_H264_PRED_WEIGHTS; |
---|
| 1511 | + break; |
---|
| 1512 | + case V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER: |
---|
| 1513 | + *type = V4L2_CTRL_TYPE_VP8_FRAME_HEADER; |
---|
| 1514 | + break; |
---|
| 1515 | + case V4L2_CID_MPEG_VIDEO_HEVC_SPS: |
---|
| 1516 | + *type = V4L2_CTRL_TYPE_HEVC_SPS; |
---|
| 1517 | + break; |
---|
| 1518 | + case V4L2_CID_MPEG_VIDEO_HEVC_PPS: |
---|
| 1519 | + *type = V4L2_CTRL_TYPE_HEVC_PPS; |
---|
| 1520 | + break; |
---|
| 1521 | + case V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS: |
---|
| 1522 | + *type = V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS; |
---|
| 1523 | + break; |
---|
| 1524 | + case V4L2_CID_UNIT_CELL_SIZE: |
---|
| 1525 | + *type = V4L2_CTRL_TYPE_AREA; |
---|
| 1526 | + *flags |= V4L2_CTRL_FLAG_READ_ONLY; |
---|
| 1527 | + break; |
---|
| 1528 | + case V4L2_CID_COLORIMETRY_HDR10_CLL_INFO: |
---|
| 1529 | + *type = V4L2_CTRL_TYPE_HDR10_CLL_INFO; |
---|
| 1530 | + break; |
---|
| 1531 | + case V4L2_CID_COLORIMETRY_HDR10_MASTERING_DISPLAY: |
---|
| 1532 | + *type = V4L2_CTRL_TYPE_HDR10_MASTERING_DISPLAY; |
---|
1301 | 1533 | break; |
---|
1302 | 1534 | default: |
---|
1303 | 1535 | *type = V4L2_CTRL_TYPE_INTEGER; |
---|
.. | .. |
---|
1365 | 1597 | case V4L2_CID_RDS_RX_TRAFFIC_ANNOUNCEMENT: |
---|
1366 | 1598 | case V4L2_CID_RDS_RX_TRAFFIC_PROGRAM: |
---|
1367 | 1599 | case V4L2_CID_RDS_RX_MUSIC_SPEECH: |
---|
| 1600 | + case V4L2_CID_CAMERA_ORIENTATION: |
---|
| 1601 | + case V4L2_CID_CAMERA_SENSOR_ROTATION: |
---|
1368 | 1602 | *flags |= V4L2_CTRL_FLAG_READ_ONLY; |
---|
1369 | 1603 | break; |
---|
1370 | 1604 | case V4L2_CID_RF_TUNER_PLL_LOCK: |
---|
.. | .. |
---|
1444 | 1678 | if (ctrl->is_int) |
---|
1445 | 1679 | return ptr1.p_s32[idx] == ptr2.p_s32[idx]; |
---|
1446 | 1680 | idx *= ctrl->elem_size; |
---|
1447 | | - return !memcmp(ptr1.p + idx, ptr2.p + idx, ctrl->elem_size); |
---|
| 1681 | + return !memcmp(ptr1.p_const + idx, ptr2.p_const + idx, |
---|
| 1682 | + ctrl->elem_size); |
---|
| 1683 | + } |
---|
| 1684 | +} |
---|
| 1685 | + |
---|
| 1686 | +static void std_init_compound(const struct v4l2_ctrl *ctrl, u32 idx, |
---|
| 1687 | + union v4l2_ctrl_ptr ptr) |
---|
| 1688 | +{ |
---|
| 1689 | + struct v4l2_ctrl_mpeg2_slice_params *p_mpeg2_slice_params; |
---|
| 1690 | + void *p = ptr.p + idx * ctrl->elem_size; |
---|
| 1691 | + |
---|
| 1692 | + if (ctrl->p_def.p_const) |
---|
| 1693 | + memcpy(p, ctrl->p_def.p_const, ctrl->elem_size); |
---|
| 1694 | + else |
---|
| 1695 | + memset(p, 0, ctrl->elem_size); |
---|
| 1696 | + |
---|
| 1697 | + /* |
---|
| 1698 | + * The cast is needed to get rid of a gcc warning complaining that |
---|
| 1699 | + * V4L2_CTRL_TYPE_MPEG2_SLICE_PARAMS is not part of the |
---|
| 1700 | + * v4l2_ctrl_type enum. |
---|
| 1701 | + */ |
---|
| 1702 | + switch ((u32)ctrl->type) { |
---|
| 1703 | + case V4L2_CTRL_TYPE_MPEG2_SLICE_PARAMS: |
---|
| 1704 | + p_mpeg2_slice_params = p; |
---|
| 1705 | + /* 4:2:0 */ |
---|
| 1706 | + p_mpeg2_slice_params->sequence.chroma_format = 1; |
---|
| 1707 | + /* interlaced top field */ |
---|
| 1708 | + p_mpeg2_slice_params->picture.picture_structure = 1; |
---|
| 1709 | + p_mpeg2_slice_params->picture.picture_coding_type = |
---|
| 1710 | + V4L2_MPEG2_PICTURE_CODING_TYPE_I; |
---|
| 1711 | + break; |
---|
1448 | 1712 | } |
---|
1449 | 1713 | } |
---|
1450 | 1714 | |
---|
.. | .. |
---|
1467 | 1731 | case V4L2_CTRL_TYPE_BOOLEAN: |
---|
1468 | 1732 | ptr.p_s32[idx] = ctrl->default_value; |
---|
1469 | 1733 | break; |
---|
| 1734 | + case V4L2_CTRL_TYPE_BUTTON: |
---|
| 1735 | + case V4L2_CTRL_TYPE_CTRL_CLASS: |
---|
| 1736 | + ptr.p_s32[idx] = 0; |
---|
| 1737 | + break; |
---|
1470 | 1738 | case V4L2_CTRL_TYPE_U8: |
---|
1471 | 1739 | ptr.p_u8[idx] = ctrl->default_value; |
---|
1472 | 1740 | break; |
---|
.. | .. |
---|
1477 | 1745 | ptr.p_u32[idx] = ctrl->default_value; |
---|
1478 | 1746 | break; |
---|
1479 | 1747 | default: |
---|
1480 | | - idx *= ctrl->elem_size; |
---|
1481 | | - memset(ptr.p + idx, 0, ctrl->elem_size); |
---|
| 1748 | + std_init_compound(ctrl, idx, ptr); |
---|
1482 | 1749 | break; |
---|
1483 | 1750 | } |
---|
1484 | 1751 | } |
---|
.. | .. |
---|
1526 | 1793 | case V4L2_CTRL_TYPE_U32: |
---|
1527 | 1794 | pr_cont("%u", (unsigned)*ptr.p_u32); |
---|
1528 | 1795 | break; |
---|
| 1796 | + case V4L2_CTRL_TYPE_HDR10_CLL_INFO: |
---|
| 1797 | + pr_cont("HDR10_CLL_INFO"); |
---|
| 1798 | + break; |
---|
| 1799 | + case V4L2_CTRL_TYPE_HDR10_MASTERING_DISPLAY: |
---|
| 1800 | + pr_cont("HDR10_MASTERING_DISPLAY"); |
---|
| 1801 | + break; |
---|
1529 | 1802 | default: |
---|
1530 | 1803 | pr_cont("unknown type %d", ctrl->type); |
---|
1531 | 1804 | break; |
---|
.. | .. |
---|
1554 | 1827 | }) |
---|
1555 | 1828 | |
---|
1556 | 1829 | /* Validate a new control */ |
---|
| 1830 | + |
---|
| 1831 | +#define zero_padding(s) \ |
---|
| 1832 | + memset(&(s).padding, 0, sizeof((s).padding)) |
---|
| 1833 | +#define zero_reserved(s) \ |
---|
| 1834 | + memset(&(s).reserved, 0, sizeof((s).reserved)) |
---|
| 1835 | + |
---|
| 1836 | +/* |
---|
| 1837 | + * Compound controls validation requires setting unused fields/flags to zero |
---|
| 1838 | + * in order to properly detect unchanged controls with std_equal's memcmp. |
---|
| 1839 | + */ |
---|
| 1840 | +static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx, |
---|
| 1841 | + union v4l2_ctrl_ptr ptr) |
---|
| 1842 | +{ |
---|
| 1843 | + struct v4l2_ctrl_mpeg2_slice_params *p_mpeg2_slice_params; |
---|
| 1844 | + struct v4l2_ctrl_vp8_frame_header *p_vp8_frame_header; |
---|
| 1845 | + struct v4l2_ctrl_h264_slice_params *p_h264_slice_params; |
---|
| 1846 | + struct v4l2_ctrl_h264_decode_params *p_h264_dec_params; |
---|
| 1847 | + struct v4l2_ctrl_hevc_sps *p_hevc_sps; |
---|
| 1848 | + struct v4l2_ctrl_hevc_pps *p_hevc_pps; |
---|
| 1849 | + struct v4l2_ctrl_hevc_slice_params *p_hevc_slice_params; |
---|
| 1850 | + struct v4l2_ctrl_hdr10_mastering_display *p_hdr10_mastering; |
---|
| 1851 | + struct v4l2_area *area; |
---|
| 1852 | + void *p = ptr.p + idx * ctrl->elem_size; |
---|
| 1853 | + unsigned int i; |
---|
| 1854 | + |
---|
| 1855 | + switch ((u32)ctrl->type) { |
---|
| 1856 | + case V4L2_CTRL_TYPE_MPEG2_SLICE_PARAMS: |
---|
| 1857 | + p_mpeg2_slice_params = p; |
---|
| 1858 | + |
---|
| 1859 | + switch (p_mpeg2_slice_params->sequence.chroma_format) { |
---|
| 1860 | + case 1: /* 4:2:0 */ |
---|
| 1861 | + case 2: /* 4:2:2 */ |
---|
| 1862 | + case 3: /* 4:4:4 */ |
---|
| 1863 | + break; |
---|
| 1864 | + default: |
---|
| 1865 | + return -EINVAL; |
---|
| 1866 | + } |
---|
| 1867 | + |
---|
| 1868 | + switch (p_mpeg2_slice_params->picture.intra_dc_precision) { |
---|
| 1869 | + case 0: /* 8 bits */ |
---|
| 1870 | + case 1: /* 9 bits */ |
---|
| 1871 | + case 2: /* 10 bits */ |
---|
| 1872 | + case 3: /* 11 bits */ |
---|
| 1873 | + break; |
---|
| 1874 | + default: |
---|
| 1875 | + return -EINVAL; |
---|
| 1876 | + } |
---|
| 1877 | + |
---|
| 1878 | + switch (p_mpeg2_slice_params->picture.picture_structure) { |
---|
| 1879 | + case 1: /* interlaced top field */ |
---|
| 1880 | + case 2: /* interlaced bottom field */ |
---|
| 1881 | + case 3: /* progressive */ |
---|
| 1882 | + break; |
---|
| 1883 | + default: |
---|
| 1884 | + return -EINVAL; |
---|
| 1885 | + } |
---|
| 1886 | + |
---|
| 1887 | + switch (p_mpeg2_slice_params->picture.picture_coding_type) { |
---|
| 1888 | + case V4L2_MPEG2_PICTURE_CODING_TYPE_I: |
---|
| 1889 | + case V4L2_MPEG2_PICTURE_CODING_TYPE_P: |
---|
| 1890 | + case V4L2_MPEG2_PICTURE_CODING_TYPE_B: |
---|
| 1891 | + break; |
---|
| 1892 | + default: |
---|
| 1893 | + return -EINVAL; |
---|
| 1894 | + } |
---|
| 1895 | + |
---|
| 1896 | + break; |
---|
| 1897 | + |
---|
| 1898 | + case V4L2_CTRL_TYPE_MPEG2_QUANTIZATION: |
---|
| 1899 | + break; |
---|
| 1900 | + |
---|
| 1901 | + case V4L2_CTRL_TYPE_FWHT_PARAMS: |
---|
| 1902 | + break; |
---|
| 1903 | + |
---|
| 1904 | + case V4L2_CTRL_TYPE_H264_SPS: |
---|
| 1905 | + case V4L2_CTRL_TYPE_H264_PPS: |
---|
| 1906 | + case V4L2_CTRL_TYPE_H264_SCALING_MATRIX: |
---|
| 1907 | + case V4L2_CTRL_TYPE_H264_PRED_WEIGHTS: |
---|
| 1908 | + break; |
---|
| 1909 | + |
---|
| 1910 | + case V4L2_CTRL_TYPE_H264_SLICE_PARAMS: |
---|
| 1911 | + p_h264_slice_params = p; |
---|
| 1912 | + |
---|
| 1913 | + zero_reserved(*p_h264_slice_params); |
---|
| 1914 | + break; |
---|
| 1915 | + |
---|
| 1916 | + case V4L2_CTRL_TYPE_H264_DECODE_PARAMS: |
---|
| 1917 | + p_h264_dec_params = p; |
---|
| 1918 | + |
---|
| 1919 | + for (i = 0; i < V4L2_H264_NUM_DPB_ENTRIES; i++) { |
---|
| 1920 | + struct v4l2_h264_dpb_entry *dpb_entry = |
---|
| 1921 | + &p_h264_dec_params->dpb[i]; |
---|
| 1922 | + |
---|
| 1923 | + zero_reserved(*dpb_entry); |
---|
| 1924 | + } |
---|
| 1925 | + zero_reserved(*p_h264_dec_params); |
---|
| 1926 | + break; |
---|
| 1927 | + |
---|
| 1928 | + case V4L2_CTRL_TYPE_VP8_FRAME_HEADER: |
---|
| 1929 | + p_vp8_frame_header = p; |
---|
| 1930 | + |
---|
| 1931 | + switch (p_vp8_frame_header->num_dct_parts) { |
---|
| 1932 | + case 1: |
---|
| 1933 | + case 2: |
---|
| 1934 | + case 4: |
---|
| 1935 | + case 8: |
---|
| 1936 | + break; |
---|
| 1937 | + default: |
---|
| 1938 | + return -EINVAL; |
---|
| 1939 | + } |
---|
| 1940 | + zero_padding(p_vp8_frame_header->segment_header); |
---|
| 1941 | + zero_padding(p_vp8_frame_header->lf_header); |
---|
| 1942 | + zero_padding(p_vp8_frame_header->quant_header); |
---|
| 1943 | + zero_padding(p_vp8_frame_header->entropy_header); |
---|
| 1944 | + zero_padding(p_vp8_frame_header->coder_state); |
---|
| 1945 | + break; |
---|
| 1946 | + |
---|
| 1947 | + case V4L2_CTRL_TYPE_HEVC_SPS: |
---|
| 1948 | + p_hevc_sps = p; |
---|
| 1949 | + |
---|
| 1950 | + if (!(p_hevc_sps->flags & V4L2_HEVC_SPS_FLAG_PCM_ENABLED)) { |
---|
| 1951 | + p_hevc_sps->pcm_sample_bit_depth_luma_minus1 = 0; |
---|
| 1952 | + p_hevc_sps->pcm_sample_bit_depth_chroma_minus1 = 0; |
---|
| 1953 | + p_hevc_sps->log2_min_pcm_luma_coding_block_size_minus3 = 0; |
---|
| 1954 | + p_hevc_sps->log2_diff_max_min_pcm_luma_coding_block_size = 0; |
---|
| 1955 | + } |
---|
| 1956 | + |
---|
| 1957 | + if (!(p_hevc_sps->flags & |
---|
| 1958 | + V4L2_HEVC_SPS_FLAG_LONG_TERM_REF_PICS_PRESENT)) |
---|
| 1959 | + p_hevc_sps->num_long_term_ref_pics_sps = 0; |
---|
| 1960 | + break; |
---|
| 1961 | + |
---|
| 1962 | + case V4L2_CTRL_TYPE_HEVC_PPS: |
---|
| 1963 | + p_hevc_pps = p; |
---|
| 1964 | + |
---|
| 1965 | + if (!(p_hevc_pps->flags & |
---|
| 1966 | + V4L2_HEVC_PPS_FLAG_CU_QP_DELTA_ENABLED)) |
---|
| 1967 | + p_hevc_pps->diff_cu_qp_delta_depth = 0; |
---|
| 1968 | + |
---|
| 1969 | + if (!(p_hevc_pps->flags & V4L2_HEVC_PPS_FLAG_TILES_ENABLED)) { |
---|
| 1970 | + p_hevc_pps->num_tile_columns_minus1 = 0; |
---|
| 1971 | + p_hevc_pps->num_tile_rows_minus1 = 0; |
---|
| 1972 | + memset(&p_hevc_pps->column_width_minus1, 0, |
---|
| 1973 | + sizeof(p_hevc_pps->column_width_minus1)); |
---|
| 1974 | + memset(&p_hevc_pps->row_height_minus1, 0, |
---|
| 1975 | + sizeof(p_hevc_pps->row_height_minus1)); |
---|
| 1976 | + |
---|
| 1977 | + p_hevc_pps->flags &= |
---|
| 1978 | + ~V4L2_HEVC_PPS_FLAG_LOOP_FILTER_ACROSS_TILES_ENABLED; |
---|
| 1979 | + } |
---|
| 1980 | + |
---|
| 1981 | + if (p_hevc_pps->flags & |
---|
| 1982 | + V4L2_HEVC_PPS_FLAG_PPS_DISABLE_DEBLOCKING_FILTER) { |
---|
| 1983 | + p_hevc_pps->pps_beta_offset_div2 = 0; |
---|
| 1984 | + p_hevc_pps->pps_tc_offset_div2 = 0; |
---|
| 1985 | + } |
---|
| 1986 | + |
---|
| 1987 | + zero_padding(*p_hevc_pps); |
---|
| 1988 | + break; |
---|
| 1989 | + |
---|
| 1990 | + case V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS: |
---|
| 1991 | + p_hevc_slice_params = p; |
---|
| 1992 | + |
---|
| 1993 | + if (p_hevc_slice_params->num_active_dpb_entries > |
---|
| 1994 | + V4L2_HEVC_DPB_ENTRIES_NUM_MAX) |
---|
| 1995 | + return -EINVAL; |
---|
| 1996 | + |
---|
| 1997 | + zero_padding(p_hevc_slice_params->pred_weight_table); |
---|
| 1998 | + |
---|
| 1999 | + for (i = 0; i < p_hevc_slice_params->num_active_dpb_entries; |
---|
| 2000 | + i++) { |
---|
| 2001 | + struct v4l2_hevc_dpb_entry *dpb_entry = |
---|
| 2002 | + &p_hevc_slice_params->dpb[i]; |
---|
| 2003 | + |
---|
| 2004 | + zero_padding(*dpb_entry); |
---|
| 2005 | + } |
---|
| 2006 | + |
---|
| 2007 | + zero_padding(*p_hevc_slice_params); |
---|
| 2008 | + break; |
---|
| 2009 | + |
---|
| 2010 | + case V4L2_CTRL_TYPE_HDR10_CLL_INFO: |
---|
| 2011 | + break; |
---|
| 2012 | + |
---|
| 2013 | + case V4L2_CTRL_TYPE_HDR10_MASTERING_DISPLAY: |
---|
| 2014 | + p_hdr10_mastering = p; |
---|
| 2015 | + |
---|
| 2016 | + for (i = 0; i < 3; ++i) { |
---|
| 2017 | + if (p_hdr10_mastering->display_primaries_x[i] < |
---|
| 2018 | + V4L2_HDR10_MASTERING_PRIMARIES_X_LOW || |
---|
| 2019 | + p_hdr10_mastering->display_primaries_x[i] > |
---|
| 2020 | + V4L2_HDR10_MASTERING_PRIMARIES_X_HIGH || |
---|
| 2021 | + p_hdr10_mastering->display_primaries_y[i] < |
---|
| 2022 | + V4L2_HDR10_MASTERING_PRIMARIES_Y_LOW || |
---|
| 2023 | + p_hdr10_mastering->display_primaries_y[i] > |
---|
| 2024 | + V4L2_HDR10_MASTERING_PRIMARIES_Y_HIGH) |
---|
| 2025 | + return -EINVAL; |
---|
| 2026 | + } |
---|
| 2027 | + |
---|
| 2028 | + if (p_hdr10_mastering->white_point_x < |
---|
| 2029 | + V4L2_HDR10_MASTERING_WHITE_POINT_X_LOW || |
---|
| 2030 | + p_hdr10_mastering->white_point_x > |
---|
| 2031 | + V4L2_HDR10_MASTERING_WHITE_POINT_X_HIGH || |
---|
| 2032 | + p_hdr10_mastering->white_point_y < |
---|
| 2033 | + V4L2_HDR10_MASTERING_WHITE_POINT_Y_LOW || |
---|
| 2034 | + p_hdr10_mastering->white_point_y > |
---|
| 2035 | + V4L2_HDR10_MASTERING_WHITE_POINT_Y_HIGH) |
---|
| 2036 | + return -EINVAL; |
---|
| 2037 | + |
---|
| 2038 | + if (p_hdr10_mastering->max_display_mastering_luminance < |
---|
| 2039 | + V4L2_HDR10_MASTERING_MAX_LUMA_LOW || |
---|
| 2040 | + p_hdr10_mastering->max_display_mastering_luminance > |
---|
| 2041 | + V4L2_HDR10_MASTERING_MAX_LUMA_HIGH || |
---|
| 2042 | + p_hdr10_mastering->min_display_mastering_luminance < |
---|
| 2043 | + V4L2_HDR10_MASTERING_MIN_LUMA_LOW || |
---|
| 2044 | + p_hdr10_mastering->min_display_mastering_luminance > |
---|
| 2045 | + V4L2_HDR10_MASTERING_MIN_LUMA_HIGH) |
---|
| 2046 | + return -EINVAL; |
---|
| 2047 | + |
---|
| 2048 | + /* The following restriction comes from ITU-T Rec. H.265 spec */ |
---|
| 2049 | + if (p_hdr10_mastering->max_display_mastering_luminance == |
---|
| 2050 | + V4L2_HDR10_MASTERING_MAX_LUMA_LOW && |
---|
| 2051 | + p_hdr10_mastering->min_display_mastering_luminance == |
---|
| 2052 | + V4L2_HDR10_MASTERING_MIN_LUMA_HIGH) |
---|
| 2053 | + return -EINVAL; |
---|
| 2054 | + |
---|
| 2055 | + break; |
---|
| 2056 | + |
---|
| 2057 | + case V4L2_CTRL_TYPE_AREA: |
---|
| 2058 | + area = p; |
---|
| 2059 | + if (!area->width || !area->height) |
---|
| 2060 | + return -EINVAL; |
---|
| 2061 | + break; |
---|
| 2062 | + |
---|
| 2063 | + default: |
---|
| 2064 | + return -EINVAL; |
---|
| 2065 | + } |
---|
| 2066 | + |
---|
| 2067 | + return 0; |
---|
| 2068 | +} |
---|
| 2069 | + |
---|
1557 | 2070 | static int std_validate(const struct v4l2_ctrl *ctrl, u32 idx, |
---|
1558 | 2071 | union v4l2_ctrl_ptr ptr) |
---|
1559 | 2072 | { |
---|
.. | .. |
---|
1561 | 2074 | u64 offset; |
---|
1562 | 2075 | s64 val; |
---|
1563 | 2076 | |
---|
1564 | | - switch (ctrl->type) { |
---|
| 2077 | + switch ((u32)ctrl->type) { |
---|
1565 | 2078 | case V4L2_CTRL_TYPE_INTEGER: |
---|
1566 | 2079 | return ROUND_TO_RANGE(ptr.p_s32[idx], u32, ctrl); |
---|
1567 | 2080 | case V4L2_CTRL_TYPE_INTEGER64: |
---|
.. | .. |
---|
1594 | 2107 | case V4L2_CTRL_TYPE_INTEGER_MENU: |
---|
1595 | 2108 | if (ptr.p_s32[idx] < ctrl->minimum || ptr.p_s32[idx] > ctrl->maximum) |
---|
1596 | 2109 | return -ERANGE; |
---|
1597 | | - if (ctrl->menu_skip_mask & (1 << ptr.p_s32[idx])) |
---|
| 2110 | + if (ptr.p_s32[idx] < BITS_PER_LONG_LONG && |
---|
| 2111 | + (ctrl->menu_skip_mask & BIT_ULL(ptr.p_s32[idx]))) |
---|
1598 | 2112 | return -EINVAL; |
---|
1599 | 2113 | if (ctrl->type == V4L2_CTRL_TYPE_MENU && |
---|
1600 | 2114 | ctrl->qmenu[ptr.p_s32[idx]][0] == '\0') |
---|
.. | .. |
---|
1620 | 2134 | return 0; |
---|
1621 | 2135 | |
---|
1622 | 2136 | default: |
---|
1623 | | - return -EINVAL; |
---|
| 2137 | + return std_validate_compound(ctrl, idx, ptr); |
---|
1624 | 2138 | } |
---|
1625 | 2139 | } |
---|
1626 | 2140 | |
---|
.. | .. |
---|
1639 | 2153 | u32 len; |
---|
1640 | 2154 | |
---|
1641 | 2155 | if (ctrl->is_ptr && !ctrl->is_string) |
---|
1642 | | - return copy_to_user(c->ptr, ptr.p, c->size) ? |
---|
| 2156 | + return copy_to_user(c->ptr, ptr.p_const, c->size) ? |
---|
1643 | 2157 | -EFAULT : 0; |
---|
1644 | 2158 | |
---|
1645 | 2159 | switch (ctrl->type) { |
---|
.. | .. |
---|
1673 | 2187 | struct v4l2_ctrl *ctrl) |
---|
1674 | 2188 | { |
---|
1675 | 2189 | return ptr_to_user(c, ctrl, ctrl->p_new); |
---|
| 2190 | +} |
---|
| 2191 | + |
---|
| 2192 | +/* Helper function: copy the request value back to the caller */ |
---|
| 2193 | +static int req_to_user(struct v4l2_ext_control *c, |
---|
| 2194 | + struct v4l2_ctrl_ref *ref) |
---|
| 2195 | +{ |
---|
| 2196 | + return ptr_to_user(c, ref->ctrl, ref->p_req); |
---|
1676 | 2197 | } |
---|
1677 | 2198 | |
---|
1678 | 2199 | /* Helper function: copy the initial control value back to the caller */ |
---|
.. | .. |
---|
1747 | 2268 | { |
---|
1748 | 2269 | if (ctrl == NULL) |
---|
1749 | 2270 | return; |
---|
1750 | | - memcpy(to.p, from.p, ctrl->elems * ctrl->elem_size); |
---|
| 2271 | + memcpy(to.p, from.p_const, ctrl->elems * ctrl->elem_size); |
---|
1751 | 2272 | } |
---|
1752 | 2273 | |
---|
1753 | 2274 | /* Copy the new value to the current value. */ |
---|
.. | .. |
---|
1794 | 2315 | ptr_to_ptr(ctrl, ctrl->p_cur, ctrl->p_new); |
---|
1795 | 2316 | } |
---|
1796 | 2317 | |
---|
| 2318 | +/* Copy the new value to the request value */ |
---|
| 2319 | +static void new_to_req(struct v4l2_ctrl_ref *ref) |
---|
| 2320 | +{ |
---|
| 2321 | + if (!ref) |
---|
| 2322 | + return; |
---|
| 2323 | + ptr_to_ptr(ref->ctrl, ref->ctrl->p_new, ref->p_req); |
---|
| 2324 | + ref->valid_p_req = true; |
---|
| 2325 | +} |
---|
| 2326 | + |
---|
| 2327 | +/* Copy the current value to the request value */ |
---|
| 2328 | +static void cur_to_req(struct v4l2_ctrl_ref *ref) |
---|
| 2329 | +{ |
---|
| 2330 | + if (!ref) |
---|
| 2331 | + return; |
---|
| 2332 | + ptr_to_ptr(ref->ctrl, ref->ctrl->p_cur, ref->p_req); |
---|
| 2333 | + ref->valid_p_req = true; |
---|
| 2334 | +} |
---|
| 2335 | + |
---|
| 2336 | +/* Copy the request value to the new value */ |
---|
| 2337 | +static void req_to_new(struct v4l2_ctrl_ref *ref) |
---|
| 2338 | +{ |
---|
| 2339 | + if (!ref) |
---|
| 2340 | + return; |
---|
| 2341 | + if (ref->valid_p_req) |
---|
| 2342 | + ptr_to_ptr(ref->ctrl, ref->p_req, ref->ctrl->p_new); |
---|
| 2343 | + else |
---|
| 2344 | + ptr_to_ptr(ref->ctrl, ref->ctrl->p_cur, ref->ctrl->p_new); |
---|
| 2345 | +} |
---|
| 2346 | + |
---|
1797 | 2347 | /* Return non-zero if one or more of the controls in the cluster has a new |
---|
1798 | 2348 | value that differs from the current value. */ |
---|
1799 | 2349 | static int cluster_changed(struct v4l2_ctrl *master) |
---|
.. | .. |
---|
1838 | 2388 | case V4L2_CTRL_TYPE_BOOLEAN: |
---|
1839 | 2389 | if (step != 1 || max > 1 || min < 0) |
---|
1840 | 2390 | return -ERANGE; |
---|
1841 | | - /* fall through */ |
---|
| 2391 | + fallthrough; |
---|
1842 | 2392 | case V4L2_CTRL_TYPE_U8: |
---|
1843 | 2393 | case V4L2_CTRL_TYPE_U16: |
---|
1844 | 2394 | case V4L2_CTRL_TYPE_U32: |
---|
.. | .. |
---|
1903 | 2453 | lockdep_set_class_and_name(hdl->lock, key, name); |
---|
1904 | 2454 | INIT_LIST_HEAD(&hdl->ctrls); |
---|
1905 | 2455 | INIT_LIST_HEAD(&hdl->ctrl_refs); |
---|
| 2456 | + INIT_LIST_HEAD(&hdl->requests); |
---|
| 2457 | + INIT_LIST_HEAD(&hdl->requests_queued); |
---|
| 2458 | + hdl->request_is_queued = false; |
---|
1906 | 2459 | hdl->nr_of_buckets = 1 + nr_of_controls_hint / 8; |
---|
1907 | 2460 | hdl->buckets = kvmalloc_array(hdl->nr_of_buckets, |
---|
1908 | 2461 | sizeof(hdl->buckets[0]), |
---|
1909 | 2462 | GFP_KERNEL | __GFP_ZERO); |
---|
1910 | 2463 | hdl->error = hdl->buckets ? 0 : -ENOMEM; |
---|
| 2464 | + media_request_object_init(&hdl->req_obj); |
---|
1911 | 2465 | return hdl->error; |
---|
1912 | 2466 | } |
---|
1913 | 2467 | EXPORT_SYMBOL(v4l2_ctrl_handler_init_class); |
---|
.. | .. |
---|
1922 | 2476 | if (hdl == NULL || hdl->buckets == NULL) |
---|
1923 | 2477 | return; |
---|
1924 | 2478 | |
---|
| 2479 | + /* |
---|
| 2480 | + * If the main handler is freed and it is used by handler objects in |
---|
| 2481 | + * outstanding requests, then unbind and put those objects before |
---|
| 2482 | + * freeing the main handler. |
---|
| 2483 | + * |
---|
| 2484 | + * The main handler can be identified by having a NULL ops pointer in |
---|
| 2485 | + * the request object. |
---|
| 2486 | + */ |
---|
| 2487 | + if (!hdl->req_obj.ops && !list_empty(&hdl->requests)) { |
---|
| 2488 | + struct v4l2_ctrl_handler *req, *next_req; |
---|
| 2489 | + |
---|
| 2490 | + list_for_each_entry_safe(req, next_req, &hdl->requests, requests) { |
---|
| 2491 | + media_request_object_unbind(&req->req_obj); |
---|
| 2492 | + media_request_object_put(&req->req_obj); |
---|
| 2493 | + } |
---|
| 2494 | + } |
---|
1925 | 2495 | mutex_lock(hdl->lock); |
---|
1926 | 2496 | /* Free all nodes */ |
---|
1927 | 2497 | list_for_each_entry_safe(ref, next_ref, &hdl->ctrl_refs, node) { |
---|
.. | .. |
---|
2023 | 2593 | |
---|
2024 | 2594 | /* Allocate a new v4l2_ctrl_ref and hook it into the handler. */ |
---|
2025 | 2595 | static int handler_new_ref(struct v4l2_ctrl_handler *hdl, |
---|
2026 | | - struct v4l2_ctrl *ctrl) |
---|
| 2596 | + struct v4l2_ctrl *ctrl, |
---|
| 2597 | + struct v4l2_ctrl_ref **ctrl_ref, |
---|
| 2598 | + bool from_other_dev, bool allocate_req) |
---|
2027 | 2599 | { |
---|
2028 | 2600 | struct v4l2_ctrl_ref *ref; |
---|
2029 | 2601 | struct v4l2_ctrl_ref *new_ref; |
---|
2030 | 2602 | u32 id = ctrl->id; |
---|
2031 | 2603 | u32 class_ctrl = V4L2_CTRL_ID2WHICH(id) | 1; |
---|
2032 | 2604 | int bucket = id % hdl->nr_of_buckets; /* which bucket to use */ |
---|
| 2605 | + unsigned int size_extra_req = 0; |
---|
| 2606 | + |
---|
| 2607 | + if (ctrl_ref) |
---|
| 2608 | + *ctrl_ref = NULL; |
---|
2033 | 2609 | |
---|
2034 | 2610 | /* |
---|
2035 | 2611 | * Automatically add the control class if it is not yet present and |
---|
.. | .. |
---|
2043 | 2619 | if (hdl->error) |
---|
2044 | 2620 | return hdl->error; |
---|
2045 | 2621 | |
---|
2046 | | - new_ref = kzalloc(sizeof(*new_ref), GFP_KERNEL); |
---|
| 2622 | + if (allocate_req) |
---|
| 2623 | + size_extra_req = ctrl->elems * ctrl->elem_size; |
---|
| 2624 | + new_ref = kzalloc(sizeof(*new_ref) + size_extra_req, GFP_KERNEL); |
---|
2047 | 2625 | if (!new_ref) |
---|
2048 | 2626 | return handler_set_err(hdl, -ENOMEM); |
---|
2049 | 2627 | new_ref->ctrl = ctrl; |
---|
2050 | | - if (ctrl->handler == hdl) { |
---|
2051 | | - /* By default each control starts in a cluster of its own. |
---|
2052 | | - new_ref->ctrl is basically a cluster array with one |
---|
2053 | | - element, so that's perfect to use as the cluster pointer. |
---|
2054 | | - But only do this for the handler that owns the control. */ |
---|
2055 | | - ctrl->cluster = &new_ref->ctrl; |
---|
2056 | | - ctrl->ncontrols = 1; |
---|
2057 | | - } |
---|
| 2628 | + new_ref->from_other_dev = from_other_dev; |
---|
| 2629 | + if (size_extra_req) |
---|
| 2630 | + new_ref->p_req.p = &new_ref[1]; |
---|
2058 | 2631 | |
---|
2059 | 2632 | INIT_LIST_HEAD(&new_ref->node); |
---|
2060 | 2633 | |
---|
.. | .. |
---|
2086 | 2659 | /* Insert the control node in the hash */ |
---|
2087 | 2660 | new_ref->next = hdl->buckets[bucket]; |
---|
2088 | 2661 | hdl->buckets[bucket] = new_ref; |
---|
| 2662 | + if (ctrl_ref) |
---|
| 2663 | + *ctrl_ref = new_ref; |
---|
| 2664 | + if (ctrl->handler == hdl) { |
---|
| 2665 | + /* By default each control starts in a cluster of its own. |
---|
| 2666 | + * new_ref->ctrl is basically a cluster array with one |
---|
| 2667 | + * element, so that's perfect to use as the cluster pointer. |
---|
| 2668 | + * But only do this for the handler that owns the control. |
---|
| 2669 | + */ |
---|
| 2670 | + ctrl->cluster = &new_ref->ctrl; |
---|
| 2671 | + ctrl->ncontrols = 1; |
---|
| 2672 | + } |
---|
2089 | 2673 | |
---|
2090 | 2674 | unlock: |
---|
2091 | 2675 | mutex_unlock(hdl->lock); |
---|
.. | .. |
---|
2100 | 2684 | s64 min, s64 max, u64 step, s64 def, |
---|
2101 | 2685 | const u32 dims[V4L2_CTRL_MAX_DIMS], u32 elem_size, |
---|
2102 | 2686 | u32 flags, const char * const *qmenu, |
---|
2103 | | - const s64 *qmenu_int, void *priv) |
---|
| 2687 | + const s64 *qmenu_int, const union v4l2_ctrl_ptr p_def, |
---|
| 2688 | + void *priv) |
---|
2104 | 2689 | { |
---|
2105 | 2690 | struct v4l2_ctrl *ctrl; |
---|
2106 | 2691 | unsigned sz_extra; |
---|
.. | .. |
---|
2124 | 2709 | is_array = nr_of_dims > 0; |
---|
2125 | 2710 | |
---|
2126 | 2711 | /* Prefill elem_size for all types handled by std_type_ops */ |
---|
2127 | | - switch (type) { |
---|
| 2712 | + switch ((u32)type) { |
---|
2128 | 2713 | case V4L2_CTRL_TYPE_INTEGER64: |
---|
2129 | 2714 | elem_size = sizeof(s64); |
---|
2130 | 2715 | break; |
---|
.. | .. |
---|
2139 | 2724 | break; |
---|
2140 | 2725 | case V4L2_CTRL_TYPE_U32: |
---|
2141 | 2726 | elem_size = sizeof(u32); |
---|
| 2727 | + break; |
---|
| 2728 | + case V4L2_CTRL_TYPE_MPEG2_SLICE_PARAMS: |
---|
| 2729 | + elem_size = sizeof(struct v4l2_ctrl_mpeg2_slice_params); |
---|
| 2730 | + break; |
---|
| 2731 | + case V4L2_CTRL_TYPE_MPEG2_QUANTIZATION: |
---|
| 2732 | + elem_size = sizeof(struct v4l2_ctrl_mpeg2_quantization); |
---|
| 2733 | + break; |
---|
| 2734 | + case V4L2_CTRL_TYPE_FWHT_PARAMS: |
---|
| 2735 | + elem_size = sizeof(struct v4l2_ctrl_fwht_params); |
---|
| 2736 | + break; |
---|
| 2737 | + case V4L2_CTRL_TYPE_H264_SPS: |
---|
| 2738 | + elem_size = sizeof(struct v4l2_ctrl_h264_sps); |
---|
| 2739 | + break; |
---|
| 2740 | + case V4L2_CTRL_TYPE_H264_PPS: |
---|
| 2741 | + elem_size = sizeof(struct v4l2_ctrl_h264_pps); |
---|
| 2742 | + break; |
---|
| 2743 | + case V4L2_CTRL_TYPE_H264_SCALING_MATRIX: |
---|
| 2744 | + elem_size = sizeof(struct v4l2_ctrl_h264_scaling_matrix); |
---|
| 2745 | + break; |
---|
| 2746 | + case V4L2_CTRL_TYPE_H264_SLICE_PARAMS: |
---|
| 2747 | + elem_size = sizeof(struct v4l2_ctrl_h264_slice_params); |
---|
| 2748 | + break; |
---|
| 2749 | + case V4L2_CTRL_TYPE_H264_DECODE_PARAMS: |
---|
| 2750 | + elem_size = sizeof(struct v4l2_ctrl_h264_decode_params); |
---|
| 2751 | + break; |
---|
| 2752 | + case V4L2_CTRL_TYPE_H264_PRED_WEIGHTS: |
---|
| 2753 | + elem_size = sizeof(struct v4l2_ctrl_h264_pred_weights); |
---|
| 2754 | + break; |
---|
| 2755 | + case V4L2_CTRL_TYPE_VP8_FRAME_HEADER: |
---|
| 2756 | + elem_size = sizeof(struct v4l2_ctrl_vp8_frame_header); |
---|
| 2757 | + break; |
---|
| 2758 | + case V4L2_CTRL_TYPE_HEVC_SPS: |
---|
| 2759 | + elem_size = sizeof(struct v4l2_ctrl_hevc_sps); |
---|
| 2760 | + break; |
---|
| 2761 | + case V4L2_CTRL_TYPE_HEVC_PPS: |
---|
| 2762 | + elem_size = sizeof(struct v4l2_ctrl_hevc_pps); |
---|
| 2763 | + break; |
---|
| 2764 | + case V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS: |
---|
| 2765 | + elem_size = sizeof(struct v4l2_ctrl_hevc_slice_params); |
---|
| 2766 | + break; |
---|
| 2767 | + case V4L2_CTRL_TYPE_HDR10_CLL_INFO: |
---|
| 2768 | + elem_size = sizeof(struct v4l2_ctrl_hdr10_cll_info); |
---|
| 2769 | + break; |
---|
| 2770 | + case V4L2_CTRL_TYPE_HDR10_MASTERING_DISPLAY: |
---|
| 2771 | + elem_size = sizeof(struct v4l2_ctrl_hdr10_mastering_display); |
---|
| 2772 | + break; |
---|
| 2773 | + case V4L2_CTRL_TYPE_AREA: |
---|
| 2774 | + elem_size = sizeof(struct v4l2_area); |
---|
2142 | 2775 | break; |
---|
2143 | 2776 | default: |
---|
2144 | 2777 | if (type < V4L2_CTRL_COMPOUND_TYPES) |
---|
.. | .. |
---|
2178 | 2811 | type >= V4L2_CTRL_COMPOUND_TYPES || |
---|
2179 | 2812 | is_array) |
---|
2180 | 2813 | sz_extra += 2 * tot_ctrl_size; |
---|
| 2814 | + |
---|
| 2815 | + if (type >= V4L2_CTRL_COMPOUND_TYPES && p_def.p_const) |
---|
| 2816 | + sz_extra += elem_size; |
---|
2181 | 2817 | |
---|
2182 | 2818 | ctrl = kvzalloc(sizeof(*ctrl) + sz_extra, GFP_KERNEL); |
---|
2183 | 2819 | if (ctrl == NULL) { |
---|
.. | .. |
---|
2222 | 2858 | ctrl->p_new.p = &ctrl->val; |
---|
2223 | 2859 | ctrl->p_cur.p = &ctrl->cur.val; |
---|
2224 | 2860 | } |
---|
| 2861 | + |
---|
| 2862 | + if (type >= V4L2_CTRL_COMPOUND_TYPES && p_def.p_const) { |
---|
| 2863 | + ctrl->p_def.p = ctrl->p_cur.p + tot_ctrl_size; |
---|
| 2864 | + memcpy(ctrl->p_def.p, p_def.p_const, elem_size); |
---|
| 2865 | + } |
---|
| 2866 | + |
---|
2225 | 2867 | for (idx = 0; idx < elems; idx++) { |
---|
2226 | 2868 | ctrl->type_ops->init(ctrl, idx, ctrl->p_cur); |
---|
2227 | 2869 | ctrl->type_ops->init(ctrl, idx, ctrl->p_new); |
---|
2228 | 2870 | } |
---|
2229 | 2871 | |
---|
2230 | | - if (handler_new_ref(hdl, ctrl)) { |
---|
| 2872 | + if (handler_new_ref(hdl, ctrl, NULL, false, false)) { |
---|
2231 | 2873 | kvfree(ctrl); |
---|
2232 | 2874 | return NULL; |
---|
2233 | 2875 | } |
---|
.. | .. |
---|
2273 | 2915 | type, min, max, |
---|
2274 | 2916 | is_menu ? cfg->menu_skip_mask : step, def, |
---|
2275 | 2917 | cfg->dims, cfg->elem_size, |
---|
2276 | | - flags, qmenu, qmenu_int, priv); |
---|
| 2918 | + flags, qmenu, qmenu_int, cfg->p_def, priv); |
---|
2277 | 2919 | if (ctrl) |
---|
2278 | 2920 | ctrl->is_private = cfg->is_private; |
---|
2279 | 2921 | return ctrl; |
---|
.. | .. |
---|
2298 | 2940 | } |
---|
2299 | 2941 | return v4l2_ctrl_new(hdl, ops, NULL, id, name, type, |
---|
2300 | 2942 | min, max, step, def, NULL, 0, |
---|
2301 | | - flags, NULL, NULL, NULL); |
---|
| 2943 | + flags, NULL, NULL, ptr_null, NULL); |
---|
2302 | 2944 | } |
---|
2303 | 2945 | EXPORT_SYMBOL(v4l2_ctrl_new_std); |
---|
2304 | 2946 | |
---|
.. | .. |
---|
2331 | 2973 | } |
---|
2332 | 2974 | return v4l2_ctrl_new(hdl, ops, NULL, id, name, type, |
---|
2333 | 2975 | 0, max, mask, def, NULL, 0, |
---|
2334 | | - flags, qmenu, qmenu_int, NULL); |
---|
| 2976 | + flags, qmenu, qmenu_int, ptr_null, NULL); |
---|
2335 | 2977 | } |
---|
2336 | 2978 | EXPORT_SYMBOL(v4l2_ctrl_new_std_menu); |
---|
2337 | 2979 | |
---|
.. | .. |
---|
2363 | 3005 | } |
---|
2364 | 3006 | return v4l2_ctrl_new(hdl, ops, NULL, id, name, type, |
---|
2365 | 3007 | 0, max, mask, def, NULL, 0, |
---|
2366 | | - flags, qmenu, NULL, NULL); |
---|
| 3008 | + flags, qmenu, NULL, ptr_null, NULL); |
---|
2367 | 3009 | |
---|
2368 | 3010 | } |
---|
2369 | 3011 | EXPORT_SYMBOL(v4l2_ctrl_new_std_menu_items); |
---|
| 3012 | + |
---|
| 3013 | +/* Helper function for standard compound controls */ |
---|
| 3014 | +struct v4l2_ctrl *v4l2_ctrl_new_std_compound(struct v4l2_ctrl_handler *hdl, |
---|
| 3015 | + const struct v4l2_ctrl_ops *ops, u32 id, |
---|
| 3016 | + const union v4l2_ctrl_ptr p_def) |
---|
| 3017 | +{ |
---|
| 3018 | + const char *name; |
---|
| 3019 | + enum v4l2_ctrl_type type; |
---|
| 3020 | + u32 flags; |
---|
| 3021 | + s64 min, max, step, def; |
---|
| 3022 | + |
---|
| 3023 | + v4l2_ctrl_fill(id, &name, &type, &min, &max, &step, &def, &flags); |
---|
| 3024 | + if (type < V4L2_CTRL_COMPOUND_TYPES) { |
---|
| 3025 | + handler_set_err(hdl, -EINVAL); |
---|
| 3026 | + return NULL; |
---|
| 3027 | + } |
---|
| 3028 | + return v4l2_ctrl_new(hdl, ops, NULL, id, name, type, |
---|
| 3029 | + min, max, step, def, NULL, 0, |
---|
| 3030 | + flags, NULL, NULL, p_def, NULL); |
---|
| 3031 | +} |
---|
| 3032 | +EXPORT_SYMBOL(v4l2_ctrl_new_std_compound); |
---|
2370 | 3033 | |
---|
2371 | 3034 | /* Helper function for standard integer menu controls */ |
---|
2372 | 3035 | struct v4l2_ctrl *v4l2_ctrl_new_int_menu(struct v4l2_ctrl_handler *hdl, |
---|
.. | .. |
---|
2388 | 3051 | } |
---|
2389 | 3052 | return v4l2_ctrl_new(hdl, ops, NULL, id, name, type, |
---|
2390 | 3053 | 0, max, 0, def, NULL, 0, |
---|
2391 | | - flags, NULL, qmenu_int, NULL); |
---|
| 3054 | + flags, NULL, qmenu_int, ptr_null, NULL); |
---|
2392 | 3055 | } |
---|
2393 | 3056 | EXPORT_SYMBOL(v4l2_ctrl_new_int_menu); |
---|
2394 | 3057 | |
---|
2395 | 3058 | /* Add the controls from another handler to our own. */ |
---|
2396 | 3059 | int v4l2_ctrl_add_handler(struct v4l2_ctrl_handler *hdl, |
---|
2397 | 3060 | struct v4l2_ctrl_handler *add, |
---|
2398 | | - bool (*filter)(const struct v4l2_ctrl *ctrl)) |
---|
| 3061 | + bool (*filter)(const struct v4l2_ctrl *ctrl), |
---|
| 3062 | + bool from_other_dev) |
---|
2399 | 3063 | { |
---|
2400 | 3064 | struct v4l2_ctrl_ref *ref; |
---|
2401 | 3065 | int ret = 0; |
---|
.. | .. |
---|
2418 | 3082 | /* Filter any unwanted controls */ |
---|
2419 | 3083 | if (filter && !filter(ctrl)) |
---|
2420 | 3084 | continue; |
---|
2421 | | - ret = handler_new_ref(hdl, ctrl); |
---|
| 3085 | + ret = handler_new_ref(hdl, ctrl, NULL, from_other_dev, false); |
---|
2422 | 3086 | if (ret) |
---|
2423 | 3087 | break; |
---|
2424 | 3088 | } |
---|
.. | .. |
---|
2517 | 3181 | } |
---|
2518 | 3182 | EXPORT_SYMBOL(v4l2_ctrl_activate); |
---|
2519 | 3183 | |
---|
2520 | | -/* Grab/ungrab a control. |
---|
2521 | | - Typically used when streaming starts and you want to grab controls, |
---|
2522 | | - preventing the user from changing them. |
---|
2523 | | - |
---|
2524 | | - Just call this and the framework will block any attempts to change |
---|
2525 | | - these controls. */ |
---|
2526 | | -void v4l2_ctrl_grab(struct v4l2_ctrl *ctrl, bool grabbed) |
---|
| 3184 | +void __v4l2_ctrl_grab(struct v4l2_ctrl *ctrl, bool grabbed) |
---|
2527 | 3185 | { |
---|
2528 | 3186 | bool old; |
---|
2529 | 3187 | |
---|
2530 | 3188 | if (ctrl == NULL) |
---|
2531 | 3189 | return; |
---|
2532 | 3190 | |
---|
2533 | | - v4l2_ctrl_lock(ctrl); |
---|
| 3191 | + lockdep_assert_held(ctrl->handler->lock); |
---|
| 3192 | + |
---|
2534 | 3193 | if (grabbed) |
---|
2535 | 3194 | /* set V4L2_CTRL_FLAG_GRABBED */ |
---|
2536 | 3195 | old = test_and_set_bit(1, &ctrl->flags); |
---|
.. | .. |
---|
2539 | 3198 | old = test_and_clear_bit(1, &ctrl->flags); |
---|
2540 | 3199 | if (old != grabbed) |
---|
2541 | 3200 | send_event(NULL, ctrl, V4L2_EVENT_CTRL_CH_FLAGS); |
---|
2542 | | - v4l2_ctrl_unlock(ctrl); |
---|
2543 | 3201 | } |
---|
2544 | | -EXPORT_SYMBOL(v4l2_ctrl_grab); |
---|
| 3202 | +EXPORT_SYMBOL(__v4l2_ctrl_grab); |
---|
2545 | 3203 | |
---|
2546 | 3204 | /* Log the control name and value */ |
---|
2547 | 3205 | static void log_ctrl(const struct v4l2_ctrl *ctrl, |
---|
.. | .. |
---|
2728 | 3386 | qc->id = id; |
---|
2729 | 3387 | else |
---|
2730 | 3388 | qc->id = ctrl->id; |
---|
2731 | | - strlcpy(qc->name, ctrl->name, sizeof(qc->name)); |
---|
| 3389 | + strscpy(qc->name, ctrl->name, sizeof(qc->name)); |
---|
2732 | 3390 | qc->flags = user_flags(ctrl); |
---|
2733 | 3391 | qc->type = ctrl->type; |
---|
2734 | 3392 | qc->elem_size = ctrl->elem_size; |
---|
.. | .. |
---|
2760 | 3418 | qc->id = qec.id; |
---|
2761 | 3419 | qc->type = qec.type; |
---|
2762 | 3420 | qc->flags = qec.flags; |
---|
2763 | | - strlcpy(qc->name, qec.name, sizeof(qc->name)); |
---|
| 3421 | + strscpy(qc->name, qec.name, sizeof(qc->name)); |
---|
2764 | 3422 | switch (qc->type) { |
---|
2765 | 3423 | case V4L2_CTRL_TYPE_INTEGER: |
---|
2766 | 3424 | case V4L2_CTRL_TYPE_BOOLEAN: |
---|
.. | .. |
---|
2813 | 3471 | return -EINVAL; |
---|
2814 | 3472 | |
---|
2815 | 3473 | /* Use mask to see if this menu item should be skipped */ |
---|
2816 | | - if (ctrl->menu_skip_mask & (1 << i)) |
---|
| 3474 | + if (ctrl->menu_skip_mask & (1ULL << i)) |
---|
2817 | 3475 | return -EINVAL; |
---|
2818 | 3476 | /* Empty menu items should also be skipped */ |
---|
2819 | 3477 | if (ctrl->type == V4L2_CTRL_TYPE_MENU) { |
---|
2820 | 3478 | if (ctrl->qmenu[i] == NULL || ctrl->qmenu[i][0] == '\0') |
---|
2821 | 3479 | return -EINVAL; |
---|
2822 | | - strlcpy(qm->name, ctrl->qmenu[i], sizeof(qm->name)); |
---|
| 3480 | + strscpy(qm->name, ctrl->qmenu[i], sizeof(qm->name)); |
---|
2823 | 3481 | } else { |
---|
2824 | 3482 | qm->value = ctrl->qmenu_int[i]; |
---|
2825 | 3483 | } |
---|
.. | .. |
---|
2827 | 3485 | } |
---|
2828 | 3486 | EXPORT_SYMBOL(v4l2_querymenu); |
---|
2829 | 3487 | |
---|
| 3488 | +static int v4l2_ctrl_request_clone(struct v4l2_ctrl_handler *hdl, |
---|
| 3489 | + const struct v4l2_ctrl_handler *from) |
---|
| 3490 | +{ |
---|
| 3491 | + struct v4l2_ctrl_ref *ref; |
---|
| 3492 | + int err = 0; |
---|
| 3493 | + |
---|
| 3494 | + if (WARN_ON(!hdl || hdl == from)) |
---|
| 3495 | + return -EINVAL; |
---|
| 3496 | + |
---|
| 3497 | + if (hdl->error) |
---|
| 3498 | + return hdl->error; |
---|
| 3499 | + |
---|
| 3500 | + WARN_ON(hdl->lock != &hdl->_lock); |
---|
| 3501 | + |
---|
| 3502 | + mutex_lock(from->lock); |
---|
| 3503 | + list_for_each_entry(ref, &from->ctrl_refs, node) { |
---|
| 3504 | + struct v4l2_ctrl *ctrl = ref->ctrl; |
---|
| 3505 | + struct v4l2_ctrl_ref *new_ref; |
---|
| 3506 | + |
---|
| 3507 | + /* Skip refs inherited from other devices */ |
---|
| 3508 | + if (ref->from_other_dev) |
---|
| 3509 | + continue; |
---|
| 3510 | + /* And buttons */ |
---|
| 3511 | + if (ctrl->type == V4L2_CTRL_TYPE_BUTTON) |
---|
| 3512 | + continue; |
---|
| 3513 | + err = handler_new_ref(hdl, ctrl, &new_ref, false, true); |
---|
| 3514 | + if (err) |
---|
| 3515 | + break; |
---|
| 3516 | + } |
---|
| 3517 | + mutex_unlock(from->lock); |
---|
| 3518 | + return err; |
---|
| 3519 | +} |
---|
| 3520 | + |
---|
| 3521 | +static void v4l2_ctrl_request_queue(struct media_request_object *obj) |
---|
| 3522 | +{ |
---|
| 3523 | + struct v4l2_ctrl_handler *hdl = |
---|
| 3524 | + container_of(obj, struct v4l2_ctrl_handler, req_obj); |
---|
| 3525 | + struct v4l2_ctrl_handler *main_hdl = obj->priv; |
---|
| 3526 | + |
---|
| 3527 | + mutex_lock(main_hdl->lock); |
---|
| 3528 | + list_add_tail(&hdl->requests_queued, &main_hdl->requests_queued); |
---|
| 3529 | + hdl->request_is_queued = true; |
---|
| 3530 | + mutex_unlock(main_hdl->lock); |
---|
| 3531 | +} |
---|
| 3532 | + |
---|
| 3533 | +static void v4l2_ctrl_request_unbind(struct media_request_object *obj) |
---|
| 3534 | +{ |
---|
| 3535 | + struct v4l2_ctrl_handler *hdl = |
---|
| 3536 | + container_of(obj, struct v4l2_ctrl_handler, req_obj); |
---|
| 3537 | + struct v4l2_ctrl_handler *main_hdl = obj->priv; |
---|
| 3538 | + |
---|
| 3539 | + mutex_lock(main_hdl->lock); |
---|
| 3540 | + list_del_init(&hdl->requests); |
---|
| 3541 | + if (hdl->request_is_queued) { |
---|
| 3542 | + list_del_init(&hdl->requests_queued); |
---|
| 3543 | + hdl->request_is_queued = false; |
---|
| 3544 | + } |
---|
| 3545 | + mutex_unlock(main_hdl->lock); |
---|
| 3546 | +} |
---|
| 3547 | + |
---|
| 3548 | +static void v4l2_ctrl_request_release(struct media_request_object *obj) |
---|
| 3549 | +{ |
---|
| 3550 | + struct v4l2_ctrl_handler *hdl = |
---|
| 3551 | + container_of(obj, struct v4l2_ctrl_handler, req_obj); |
---|
| 3552 | + |
---|
| 3553 | + v4l2_ctrl_handler_free(hdl); |
---|
| 3554 | + kfree(hdl); |
---|
| 3555 | +} |
---|
| 3556 | + |
---|
| 3557 | +static const struct media_request_object_ops req_ops = { |
---|
| 3558 | + .queue = v4l2_ctrl_request_queue, |
---|
| 3559 | + .unbind = v4l2_ctrl_request_unbind, |
---|
| 3560 | + .release = v4l2_ctrl_request_release, |
---|
| 3561 | +}; |
---|
| 3562 | + |
---|
| 3563 | +struct v4l2_ctrl_handler *v4l2_ctrl_request_hdl_find(struct media_request *req, |
---|
| 3564 | + struct v4l2_ctrl_handler *parent) |
---|
| 3565 | +{ |
---|
| 3566 | + struct media_request_object *obj; |
---|
| 3567 | + |
---|
| 3568 | + if (WARN_ON(req->state != MEDIA_REQUEST_STATE_VALIDATING && |
---|
| 3569 | + req->state != MEDIA_REQUEST_STATE_QUEUED)) |
---|
| 3570 | + return NULL; |
---|
| 3571 | + |
---|
| 3572 | + obj = media_request_object_find(req, &req_ops, parent); |
---|
| 3573 | + if (obj) |
---|
| 3574 | + return container_of(obj, struct v4l2_ctrl_handler, req_obj); |
---|
| 3575 | + return NULL; |
---|
| 3576 | +} |
---|
| 3577 | +EXPORT_SYMBOL_GPL(v4l2_ctrl_request_hdl_find); |
---|
| 3578 | + |
---|
| 3579 | +struct v4l2_ctrl * |
---|
| 3580 | +v4l2_ctrl_request_hdl_ctrl_find(struct v4l2_ctrl_handler *hdl, u32 id) |
---|
| 3581 | +{ |
---|
| 3582 | + struct v4l2_ctrl_ref *ref = find_ref_lock(hdl, id); |
---|
| 3583 | + |
---|
| 3584 | + return (ref && ref->valid_p_req) ? ref->ctrl : NULL; |
---|
| 3585 | +} |
---|
| 3586 | +EXPORT_SYMBOL_GPL(v4l2_ctrl_request_hdl_ctrl_find); |
---|
| 3587 | + |
---|
| 3588 | +static int v4l2_ctrl_request_bind(struct media_request *req, |
---|
| 3589 | + struct v4l2_ctrl_handler *hdl, |
---|
| 3590 | + struct v4l2_ctrl_handler *from) |
---|
| 3591 | +{ |
---|
| 3592 | + int ret; |
---|
| 3593 | + |
---|
| 3594 | + ret = v4l2_ctrl_request_clone(hdl, from); |
---|
| 3595 | + |
---|
| 3596 | + if (!ret) { |
---|
| 3597 | + ret = media_request_object_bind(req, &req_ops, |
---|
| 3598 | + from, false, &hdl->req_obj); |
---|
| 3599 | + if (!ret) { |
---|
| 3600 | + mutex_lock(from->lock); |
---|
| 3601 | + list_add_tail(&hdl->requests, &from->requests); |
---|
| 3602 | + mutex_unlock(from->lock); |
---|
| 3603 | + } |
---|
| 3604 | + } |
---|
| 3605 | + return ret; |
---|
| 3606 | +} |
---|
2830 | 3607 | |
---|
2831 | 3608 | /* Some general notes on the atomic requirements of VIDIOC_G/TRY/S_EXT_CTRLS: |
---|
2832 | 3609 | |
---|
.. | .. |
---|
2872 | 3649 | static int prepare_ext_ctrls(struct v4l2_ctrl_handler *hdl, |
---|
2873 | 3650 | struct v4l2_ext_controls *cs, |
---|
2874 | 3651 | struct v4l2_ctrl_helper *helpers, |
---|
| 3652 | + struct video_device *vdev, |
---|
2875 | 3653 | bool get) |
---|
2876 | 3654 | { |
---|
2877 | 3655 | struct v4l2_ctrl_helper *h; |
---|
.. | .. |
---|
2888 | 3666 | |
---|
2889 | 3667 | if (cs->which && |
---|
2890 | 3668 | cs->which != V4L2_CTRL_WHICH_DEF_VAL && |
---|
2891 | | - V4L2_CTRL_ID2WHICH(id) != cs->which) |
---|
| 3669 | + cs->which != V4L2_CTRL_WHICH_REQUEST_VAL && |
---|
| 3670 | + V4L2_CTRL_ID2WHICH(id) != cs->which) { |
---|
| 3671 | + dprintk(vdev, |
---|
| 3672 | + "invalid which 0x%x or control id 0x%x\n", |
---|
| 3673 | + cs->which, id); |
---|
2892 | 3674 | return -EINVAL; |
---|
| 3675 | + } |
---|
2893 | 3676 | |
---|
2894 | 3677 | /* Old-style private controls are not allowed for |
---|
2895 | 3678 | extended controls */ |
---|
2896 | | - if (id >= V4L2_CID_PRIVATE_BASE) |
---|
| 3679 | + if (id >= V4L2_CID_PRIVATE_BASE) { |
---|
| 3680 | + dprintk(vdev, |
---|
| 3681 | + "old-style private controls not allowed\n"); |
---|
2897 | 3682 | return -EINVAL; |
---|
| 3683 | + } |
---|
2898 | 3684 | ref = find_ref_lock(hdl, id); |
---|
2899 | | - if (ref == NULL) |
---|
| 3685 | + if (ref == NULL) { |
---|
| 3686 | + dprintk(vdev, "cannot find control id 0x%x\n", id); |
---|
2900 | 3687 | return -EINVAL; |
---|
| 3688 | + } |
---|
| 3689 | + h->ref = ref; |
---|
2901 | 3690 | ctrl = ref->ctrl; |
---|
2902 | | - if (ctrl->flags & V4L2_CTRL_FLAG_DISABLED) |
---|
| 3691 | + if (ctrl->flags & V4L2_CTRL_FLAG_DISABLED) { |
---|
| 3692 | + dprintk(vdev, "control id 0x%x is disabled\n", id); |
---|
2903 | 3693 | return -EINVAL; |
---|
| 3694 | + } |
---|
2904 | 3695 | |
---|
2905 | 3696 | if (ctrl->cluster[0]->ncontrols > 1) |
---|
2906 | 3697 | have_clusters = true; |
---|
.. | .. |
---|
2910 | 3701 | unsigned tot_size = ctrl->elems * ctrl->elem_size; |
---|
2911 | 3702 | |
---|
2912 | 3703 | if (c->size < tot_size) { |
---|
| 3704 | + /* |
---|
| 3705 | + * In the get case the application first |
---|
| 3706 | + * queries to obtain the size of the control. |
---|
| 3707 | + */ |
---|
2913 | 3708 | if (get) { |
---|
2914 | 3709 | c->size = tot_size; |
---|
2915 | 3710 | return -ENOSPC; |
---|
2916 | 3711 | } |
---|
| 3712 | + dprintk(vdev, |
---|
| 3713 | + "pointer control id 0x%x size too small, %d bytes but %d bytes needed\n", |
---|
| 3714 | + id, c->size, tot_size); |
---|
2917 | 3715 | return -EFAULT; |
---|
2918 | 3716 | } |
---|
2919 | 3717 | c->size = tot_size; |
---|
2920 | 3718 | } |
---|
2921 | 3719 | /* Store the ref to the master control of the cluster */ |
---|
2922 | 3720 | h->mref = ref; |
---|
2923 | | - h->ctrl = ctrl; |
---|
2924 | 3721 | /* Initially set next to 0, meaning that there is no other |
---|
2925 | 3722 | control in this helper array belonging to the same |
---|
2926 | 3723 | cluster */ |
---|
.. | .. |
---|
2967 | 3764 | whether there are any controls at all. */ |
---|
2968 | 3765 | static int class_check(struct v4l2_ctrl_handler *hdl, u32 which) |
---|
2969 | 3766 | { |
---|
2970 | | - if (which == 0 || which == V4L2_CTRL_WHICH_DEF_VAL) |
---|
| 3767 | + if (which == 0 || which == V4L2_CTRL_WHICH_DEF_VAL || |
---|
| 3768 | + which == V4L2_CTRL_WHICH_REQUEST_VAL) |
---|
2971 | 3769 | return 0; |
---|
2972 | 3770 | return find_ref_lock(hdl, which | 1) ? 0 : -EINVAL; |
---|
2973 | 3771 | } |
---|
2974 | 3772 | |
---|
2975 | | - |
---|
2976 | | - |
---|
2977 | | -/* Get extended controls. Allocates the helpers array if needed. */ |
---|
2978 | | -int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls *cs) |
---|
| 3773 | +/* |
---|
| 3774 | + * Get extended controls. Allocates the helpers array if needed. |
---|
| 3775 | + * |
---|
| 3776 | + * Note that v4l2_g_ext_ctrls_common() with 'which' set to |
---|
| 3777 | + * V4L2_CTRL_WHICH_REQUEST_VAL is only called if the request was |
---|
| 3778 | + * completed, and in that case valid_p_req is true for all controls. |
---|
| 3779 | + */ |
---|
| 3780 | +static int v4l2_g_ext_ctrls_common(struct v4l2_ctrl_handler *hdl, |
---|
| 3781 | + struct v4l2_ext_controls *cs, |
---|
| 3782 | + struct video_device *vdev) |
---|
2979 | 3783 | { |
---|
2980 | 3784 | struct v4l2_ctrl_helper helper[4]; |
---|
2981 | 3785 | struct v4l2_ctrl_helper *helpers = helper; |
---|
2982 | 3786 | int ret; |
---|
2983 | 3787 | int i, j; |
---|
2984 | | - bool def_value; |
---|
| 3788 | + bool is_default, is_request; |
---|
2985 | 3789 | |
---|
2986 | | - def_value = (cs->which == V4L2_CTRL_WHICH_DEF_VAL); |
---|
| 3790 | + is_default = (cs->which == V4L2_CTRL_WHICH_DEF_VAL); |
---|
| 3791 | + is_request = (cs->which == V4L2_CTRL_WHICH_REQUEST_VAL); |
---|
2987 | 3792 | |
---|
2988 | 3793 | cs->error_idx = cs->count; |
---|
2989 | 3794 | cs->which = V4L2_CTRL_ID2WHICH(cs->which); |
---|
.. | .. |
---|
3001 | 3806 | return -ENOMEM; |
---|
3002 | 3807 | } |
---|
3003 | 3808 | |
---|
3004 | | - ret = prepare_ext_ctrls(hdl, cs, helpers, true); |
---|
| 3809 | + ret = prepare_ext_ctrls(hdl, cs, helpers, vdev, true); |
---|
3005 | 3810 | cs->error_idx = cs->count; |
---|
3006 | 3811 | |
---|
3007 | 3812 | for (i = 0; !ret && i < cs->count; i++) |
---|
3008 | | - if (helpers[i].ctrl->flags & V4L2_CTRL_FLAG_WRITE_ONLY) |
---|
| 3813 | + if (helpers[i].ref->ctrl->flags & V4L2_CTRL_FLAG_WRITE_ONLY) |
---|
3009 | 3814 | ret = -EACCES; |
---|
3010 | 3815 | |
---|
3011 | 3816 | for (i = 0; !ret && i < cs->count; i++) { |
---|
3012 | | - int (*ctrl_to_user)(struct v4l2_ext_control *c, |
---|
3013 | | - struct v4l2_ctrl *ctrl); |
---|
3014 | 3817 | struct v4l2_ctrl *master; |
---|
3015 | | - |
---|
3016 | | - ctrl_to_user = def_value ? def_to_user : cur_to_user; |
---|
| 3818 | + bool is_volatile = false; |
---|
| 3819 | + u32 idx = i; |
---|
3017 | 3820 | |
---|
3018 | 3821 | if (helpers[i].mref == NULL) |
---|
3019 | 3822 | continue; |
---|
.. | .. |
---|
3023 | 3826 | |
---|
3024 | 3827 | v4l2_ctrl_lock(master); |
---|
3025 | 3828 | |
---|
3026 | | - /* g_volatile_ctrl will update the new control values */ |
---|
3027 | | - if (!def_value && |
---|
| 3829 | + /* |
---|
| 3830 | + * g_volatile_ctrl will update the new control values. |
---|
| 3831 | + * This makes no sense for V4L2_CTRL_WHICH_DEF_VAL and |
---|
| 3832 | + * V4L2_CTRL_WHICH_REQUEST_VAL. In the case of requests |
---|
| 3833 | + * it is v4l2_ctrl_request_complete() that copies the |
---|
| 3834 | + * volatile controls at the time of request completion |
---|
| 3835 | + * to the request, so you don't want to do that again. |
---|
| 3836 | + */ |
---|
| 3837 | + if (!is_default && !is_request && |
---|
3028 | 3838 | ((master->flags & V4L2_CTRL_FLAG_VOLATILE) || |
---|
3029 | 3839 | (master->has_volatiles && !is_cur_manual(master)))) { |
---|
3030 | 3840 | for (j = 0; j < master->ncontrols; j++) |
---|
3031 | 3841 | cur_to_new(master->cluster[j]); |
---|
3032 | 3842 | ret = call_op(master, g_volatile_ctrl); |
---|
3033 | | - ctrl_to_user = new_to_user; |
---|
| 3843 | + is_volatile = true; |
---|
3034 | 3844 | } |
---|
3035 | | - /* If OK, then copy the current (for non-volatile controls) |
---|
3036 | | - or the new (for volatile controls) control values to the |
---|
3037 | | - caller */ |
---|
3038 | | - if (!ret) { |
---|
3039 | | - u32 idx = i; |
---|
3040 | 3845 | |
---|
3041 | | - do { |
---|
3042 | | - ret = ctrl_to_user(cs->controls + idx, |
---|
3043 | | - helpers[idx].ctrl); |
---|
3044 | | - idx = helpers[idx].next; |
---|
3045 | | - } while (!ret && idx); |
---|
| 3846 | + if (ret) { |
---|
| 3847 | + v4l2_ctrl_unlock(master); |
---|
| 3848 | + break; |
---|
3046 | 3849 | } |
---|
| 3850 | + |
---|
| 3851 | + /* |
---|
| 3852 | + * Copy the default value (if is_default is true), the |
---|
| 3853 | + * request value (if is_request is true and p_req is valid), |
---|
| 3854 | + * the new volatile value (if is_volatile is true) or the |
---|
| 3855 | + * current value. |
---|
| 3856 | + */ |
---|
| 3857 | + do { |
---|
| 3858 | + struct v4l2_ctrl_ref *ref = helpers[idx].ref; |
---|
| 3859 | + |
---|
| 3860 | + if (is_default) |
---|
| 3861 | + ret = def_to_user(cs->controls + idx, ref->ctrl); |
---|
| 3862 | + else if (is_request && ref->valid_p_req) |
---|
| 3863 | + ret = req_to_user(cs->controls + idx, ref); |
---|
| 3864 | + else if (is_volatile) |
---|
| 3865 | + ret = new_to_user(cs->controls + idx, ref->ctrl); |
---|
| 3866 | + else |
---|
| 3867 | + ret = cur_to_user(cs->controls + idx, ref->ctrl); |
---|
| 3868 | + idx = helpers[idx].next; |
---|
| 3869 | + } while (!ret && idx); |
---|
| 3870 | + |
---|
3047 | 3871 | v4l2_ctrl_unlock(master); |
---|
3048 | 3872 | } |
---|
3049 | 3873 | |
---|
3050 | 3874 | if (cs->count > ARRAY_SIZE(helper)) |
---|
3051 | 3875 | kvfree(helpers); |
---|
| 3876 | + return ret; |
---|
| 3877 | +} |
---|
| 3878 | + |
---|
| 3879 | +static struct media_request_object * |
---|
| 3880 | +v4l2_ctrls_find_req_obj(struct v4l2_ctrl_handler *hdl, |
---|
| 3881 | + struct media_request *req, bool set) |
---|
| 3882 | +{ |
---|
| 3883 | + struct media_request_object *obj; |
---|
| 3884 | + struct v4l2_ctrl_handler *new_hdl; |
---|
| 3885 | + int ret; |
---|
| 3886 | + |
---|
| 3887 | + if (IS_ERR(req)) |
---|
| 3888 | + return ERR_CAST(req); |
---|
| 3889 | + |
---|
| 3890 | + if (set && WARN_ON(req->state != MEDIA_REQUEST_STATE_UPDATING)) |
---|
| 3891 | + return ERR_PTR(-EBUSY); |
---|
| 3892 | + |
---|
| 3893 | + obj = media_request_object_find(req, &req_ops, hdl); |
---|
| 3894 | + if (obj) |
---|
| 3895 | + return obj; |
---|
| 3896 | + if (!set) |
---|
| 3897 | + return ERR_PTR(-ENOENT); |
---|
| 3898 | + |
---|
| 3899 | + new_hdl = kzalloc(sizeof(*new_hdl), GFP_KERNEL); |
---|
| 3900 | + if (!new_hdl) |
---|
| 3901 | + return ERR_PTR(-ENOMEM); |
---|
| 3902 | + |
---|
| 3903 | + obj = &new_hdl->req_obj; |
---|
| 3904 | + ret = v4l2_ctrl_handler_init(new_hdl, (hdl->nr_of_buckets - 1) * 8); |
---|
| 3905 | + if (!ret) |
---|
| 3906 | + ret = v4l2_ctrl_request_bind(req, new_hdl, hdl); |
---|
| 3907 | + if (ret) { |
---|
| 3908 | + kfree(new_hdl); |
---|
| 3909 | + |
---|
| 3910 | + return ERR_PTR(ret); |
---|
| 3911 | + } |
---|
| 3912 | + |
---|
| 3913 | + media_request_object_get(obj); |
---|
| 3914 | + return obj; |
---|
| 3915 | +} |
---|
| 3916 | + |
---|
| 3917 | +int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct video_device *vdev, |
---|
| 3918 | + struct media_device *mdev, struct v4l2_ext_controls *cs) |
---|
| 3919 | +{ |
---|
| 3920 | + struct media_request_object *obj = NULL; |
---|
| 3921 | + struct media_request *req = NULL; |
---|
| 3922 | + int ret; |
---|
| 3923 | + |
---|
| 3924 | + if (cs->which == V4L2_CTRL_WHICH_REQUEST_VAL) { |
---|
| 3925 | + if (!mdev || cs->request_fd < 0) |
---|
| 3926 | + return -EINVAL; |
---|
| 3927 | + |
---|
| 3928 | + req = media_request_get_by_fd(mdev, cs->request_fd); |
---|
| 3929 | + if (IS_ERR(req)) |
---|
| 3930 | + return PTR_ERR(req); |
---|
| 3931 | + |
---|
| 3932 | + if (req->state != MEDIA_REQUEST_STATE_COMPLETE) { |
---|
| 3933 | + media_request_put(req); |
---|
| 3934 | + return -EACCES; |
---|
| 3935 | + } |
---|
| 3936 | + |
---|
| 3937 | + ret = media_request_lock_for_access(req); |
---|
| 3938 | + if (ret) { |
---|
| 3939 | + media_request_put(req); |
---|
| 3940 | + return ret; |
---|
| 3941 | + } |
---|
| 3942 | + |
---|
| 3943 | + obj = v4l2_ctrls_find_req_obj(hdl, req, false); |
---|
| 3944 | + if (IS_ERR(obj)) { |
---|
| 3945 | + media_request_unlock_for_access(req); |
---|
| 3946 | + media_request_put(req); |
---|
| 3947 | + return PTR_ERR(obj); |
---|
| 3948 | + } |
---|
| 3949 | + |
---|
| 3950 | + hdl = container_of(obj, struct v4l2_ctrl_handler, |
---|
| 3951 | + req_obj); |
---|
| 3952 | + } |
---|
| 3953 | + |
---|
| 3954 | + ret = v4l2_g_ext_ctrls_common(hdl, cs, vdev); |
---|
| 3955 | + |
---|
| 3956 | + if (obj) { |
---|
| 3957 | + media_request_unlock_for_access(req); |
---|
| 3958 | + media_request_object_put(obj); |
---|
| 3959 | + media_request_put(req); |
---|
| 3960 | + } |
---|
3052 | 3961 | return ret; |
---|
3053 | 3962 | } |
---|
3054 | 3963 | EXPORT_SYMBOL(v4l2_g_ext_ctrls); |
---|
.. | .. |
---|
3103 | 4012 | struct v4l2_ext_control c; |
---|
3104 | 4013 | |
---|
3105 | 4014 | /* It's a driver bug if this happens. */ |
---|
3106 | | - WARN_ON(!ctrl->is_int); |
---|
| 4015 | + if (WARN_ON(!ctrl->is_int)) |
---|
| 4016 | + return 0; |
---|
3107 | 4017 | c.value = 0; |
---|
3108 | 4018 | get_ctrl(ctrl, &c); |
---|
3109 | 4019 | return c.value; |
---|
.. | .. |
---|
3115 | 4025 | struct v4l2_ext_control c; |
---|
3116 | 4026 | |
---|
3117 | 4027 | /* It's a driver bug if this happens. */ |
---|
3118 | | - WARN_ON(ctrl->is_ptr || ctrl->type != V4L2_CTRL_TYPE_INTEGER64); |
---|
| 4028 | + if (WARN_ON(ctrl->is_ptr || ctrl->type != V4L2_CTRL_TYPE_INTEGER64)) |
---|
| 4029 | + return 0; |
---|
3119 | 4030 | c.value64 = 0; |
---|
3120 | 4031 | get_ctrl(ctrl, &c); |
---|
3121 | 4032 | return c.value64; |
---|
.. | .. |
---|
3185 | 4096 | |
---|
3186 | 4097 | /* Validate controls. */ |
---|
3187 | 4098 | static int validate_ctrls(struct v4l2_ext_controls *cs, |
---|
3188 | | - struct v4l2_ctrl_helper *helpers, bool set) |
---|
| 4099 | + struct v4l2_ctrl_helper *helpers, |
---|
| 4100 | + struct video_device *vdev, |
---|
| 4101 | + bool set) |
---|
3189 | 4102 | { |
---|
3190 | 4103 | unsigned i; |
---|
3191 | 4104 | int ret = 0; |
---|
3192 | 4105 | |
---|
3193 | 4106 | cs->error_idx = cs->count; |
---|
3194 | 4107 | for (i = 0; i < cs->count; i++) { |
---|
3195 | | - struct v4l2_ctrl *ctrl = helpers[i].ctrl; |
---|
| 4108 | + struct v4l2_ctrl *ctrl = helpers[i].ref->ctrl; |
---|
3196 | 4109 | union v4l2_ctrl_ptr p_new; |
---|
3197 | 4110 | |
---|
3198 | 4111 | cs->error_idx = i; |
---|
3199 | 4112 | |
---|
3200 | | - if (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY) |
---|
| 4113 | + if (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY) { |
---|
| 4114 | + dprintk(vdev, |
---|
| 4115 | + "control id 0x%x is read-only\n", |
---|
| 4116 | + ctrl->id); |
---|
3201 | 4117 | return -EACCES; |
---|
| 4118 | + } |
---|
3202 | 4119 | /* This test is also done in try_set_control_cluster() which |
---|
3203 | 4120 | is called in atomic context, so that has the final say, |
---|
3204 | 4121 | but it makes sense to do an up-front check as well. Once |
---|
3205 | 4122 | an error occurs in try_set_control_cluster() some other |
---|
3206 | 4123 | controls may have been set already and we want to do a |
---|
3207 | 4124 | best-effort to avoid that. */ |
---|
3208 | | - if (set && (ctrl->flags & V4L2_CTRL_FLAG_GRABBED)) |
---|
| 4125 | + if (set && (ctrl->flags & V4L2_CTRL_FLAG_GRABBED)) { |
---|
| 4126 | + dprintk(vdev, |
---|
| 4127 | + "control id 0x%x is grabbed, cannot set\n", |
---|
| 4128 | + ctrl->id); |
---|
3209 | 4129 | return -EBUSY; |
---|
| 4130 | + } |
---|
3210 | 4131 | /* |
---|
3211 | 4132 | * Skip validation for now if the payload needs to be copied |
---|
3212 | 4133 | * from userspace into kernelspace. We'll validate those later. |
---|
.. | .. |
---|
3239 | 4160 | } |
---|
3240 | 4161 | |
---|
3241 | 4162 | /* Try or try-and-set controls */ |
---|
3242 | | -static int try_set_ext_ctrls(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl, |
---|
3243 | | - struct v4l2_ext_controls *cs, |
---|
3244 | | - bool set) |
---|
| 4163 | +static int try_set_ext_ctrls_common(struct v4l2_fh *fh, |
---|
| 4164 | + struct v4l2_ctrl_handler *hdl, |
---|
| 4165 | + struct v4l2_ext_controls *cs, |
---|
| 4166 | + struct video_device *vdev, bool set) |
---|
3245 | 4167 | { |
---|
3246 | 4168 | struct v4l2_ctrl_helper helper[4]; |
---|
3247 | 4169 | struct v4l2_ctrl_helper *helpers = helper; |
---|
.. | .. |
---|
3251 | 4173 | cs->error_idx = cs->count; |
---|
3252 | 4174 | |
---|
3253 | 4175 | /* Default value cannot be changed */ |
---|
3254 | | - if (cs->which == V4L2_CTRL_WHICH_DEF_VAL) |
---|
| 4176 | + if (cs->which == V4L2_CTRL_WHICH_DEF_VAL) { |
---|
| 4177 | + dprintk(vdev, "%s: cannot change default value\n", |
---|
| 4178 | + video_device_node_name(vdev)); |
---|
3255 | 4179 | return -EINVAL; |
---|
| 4180 | + } |
---|
3256 | 4181 | |
---|
3257 | 4182 | cs->which = V4L2_CTRL_ID2WHICH(cs->which); |
---|
3258 | 4183 | |
---|
3259 | | - if (hdl == NULL) |
---|
| 4184 | + if (hdl == NULL) { |
---|
| 4185 | + dprintk(vdev, "%s: invalid null control handler\n", |
---|
| 4186 | + video_device_node_name(vdev)); |
---|
3260 | 4187 | return -EINVAL; |
---|
| 4188 | + } |
---|
3261 | 4189 | |
---|
3262 | 4190 | if (cs->count == 0) |
---|
3263 | 4191 | return class_check(hdl, cs->which); |
---|
.. | .. |
---|
3268 | 4196 | if (!helpers) |
---|
3269 | 4197 | return -ENOMEM; |
---|
3270 | 4198 | } |
---|
3271 | | - ret = prepare_ext_ctrls(hdl, cs, helpers, false); |
---|
| 4199 | + ret = prepare_ext_ctrls(hdl, cs, helpers, vdev, false); |
---|
3272 | 4200 | if (!ret) |
---|
3273 | | - ret = validate_ctrls(cs, helpers, set); |
---|
| 4201 | + ret = validate_ctrls(cs, helpers, vdev, set); |
---|
3274 | 4202 | if (ret && set) |
---|
3275 | 4203 | cs->error_idx = cs->count; |
---|
3276 | 4204 | for (i = 0; !ret && i < cs->count; i++) { |
---|
.. | .. |
---|
3304 | 4232 | do { |
---|
3305 | 4233 | /* Check if the auto control is part of the |
---|
3306 | 4234 | list, and remember the new value. */ |
---|
3307 | | - if (helpers[tmp_idx].ctrl == master) |
---|
| 4235 | + if (helpers[tmp_idx].ref->ctrl == master) |
---|
3308 | 4236 | new_auto_val = cs->controls[tmp_idx].value; |
---|
3309 | 4237 | tmp_idx = helpers[tmp_idx].next; |
---|
3310 | 4238 | } while (tmp_idx); |
---|
.. | .. |
---|
3317 | 4245 | /* Copy the new caller-supplied control values. |
---|
3318 | 4246 | user_to_new() sets 'is_new' to 1. */ |
---|
3319 | 4247 | do { |
---|
3320 | | - struct v4l2_ctrl *ctrl = helpers[idx].ctrl; |
---|
| 4248 | + struct v4l2_ctrl *ctrl = helpers[idx].ref->ctrl; |
---|
3321 | 4249 | |
---|
3322 | 4250 | ret = user_to_new(cs->controls + idx, ctrl); |
---|
3323 | 4251 | if (!ret && ctrl->is_ptr) |
---|
.. | .. |
---|
3326 | 4254 | } while (!ret && idx); |
---|
3327 | 4255 | |
---|
3328 | 4256 | if (!ret) |
---|
3329 | | - ret = try_or_set_cluster(fh, master, set, 0); |
---|
| 4257 | + ret = try_or_set_cluster(fh, master, |
---|
| 4258 | + !hdl->req_obj.req && set, 0); |
---|
| 4259 | + if (!ret && hdl->req_obj.req && set) { |
---|
| 4260 | + for (j = 0; j < master->ncontrols; j++) { |
---|
| 4261 | + struct v4l2_ctrl_ref *ref = |
---|
| 4262 | + find_ref(hdl, master->cluster[j]->id); |
---|
| 4263 | + |
---|
| 4264 | + new_to_req(ref); |
---|
| 4265 | + } |
---|
| 4266 | + } |
---|
3330 | 4267 | |
---|
3331 | 4268 | /* Copy the new values back to userspace. */ |
---|
3332 | 4269 | if (!ret) { |
---|
3333 | 4270 | idx = i; |
---|
3334 | 4271 | do { |
---|
3335 | 4272 | ret = new_to_user(cs->controls + idx, |
---|
3336 | | - helpers[idx].ctrl); |
---|
| 4273 | + helpers[idx].ref->ctrl); |
---|
3337 | 4274 | idx = helpers[idx].next; |
---|
3338 | 4275 | } while (!ret && idx); |
---|
3339 | 4276 | } |
---|
.. | .. |
---|
3345 | 4282 | return ret; |
---|
3346 | 4283 | } |
---|
3347 | 4284 | |
---|
3348 | | -int v4l2_try_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls *cs) |
---|
| 4285 | +static int try_set_ext_ctrls(struct v4l2_fh *fh, |
---|
| 4286 | + struct v4l2_ctrl_handler *hdl, |
---|
| 4287 | + struct video_device *vdev, |
---|
| 4288 | + struct media_device *mdev, |
---|
| 4289 | + struct v4l2_ext_controls *cs, bool set) |
---|
3349 | 4290 | { |
---|
3350 | | - return try_set_ext_ctrls(NULL, hdl, cs, false); |
---|
| 4291 | + struct media_request_object *obj = NULL; |
---|
| 4292 | + struct media_request *req = NULL; |
---|
| 4293 | + int ret; |
---|
| 4294 | + |
---|
| 4295 | + if (cs->which == V4L2_CTRL_WHICH_REQUEST_VAL) { |
---|
| 4296 | + if (!mdev) { |
---|
| 4297 | + dprintk(vdev, "%s: missing media device\n", |
---|
| 4298 | + video_device_node_name(vdev)); |
---|
| 4299 | + return -EINVAL; |
---|
| 4300 | + } |
---|
| 4301 | + |
---|
| 4302 | + if (cs->request_fd < 0) { |
---|
| 4303 | + dprintk(vdev, "%s: invalid request fd %d\n", |
---|
| 4304 | + video_device_node_name(vdev), cs->request_fd); |
---|
| 4305 | + return -EINVAL; |
---|
| 4306 | + } |
---|
| 4307 | + |
---|
| 4308 | + req = media_request_get_by_fd(mdev, cs->request_fd); |
---|
| 4309 | + if (IS_ERR(req)) { |
---|
| 4310 | + dprintk(vdev, "%s: cannot find request fd %d\n", |
---|
| 4311 | + video_device_node_name(vdev), cs->request_fd); |
---|
| 4312 | + return PTR_ERR(req); |
---|
| 4313 | + } |
---|
| 4314 | + |
---|
| 4315 | + ret = media_request_lock_for_update(req); |
---|
| 4316 | + if (ret) { |
---|
| 4317 | + dprintk(vdev, "%s: cannot lock request fd %d\n", |
---|
| 4318 | + video_device_node_name(vdev), cs->request_fd); |
---|
| 4319 | + media_request_put(req); |
---|
| 4320 | + return ret; |
---|
| 4321 | + } |
---|
| 4322 | + |
---|
| 4323 | + obj = v4l2_ctrls_find_req_obj(hdl, req, set); |
---|
| 4324 | + if (IS_ERR(obj)) { |
---|
| 4325 | + dprintk(vdev, |
---|
| 4326 | + "%s: cannot find request object for request fd %d\n", |
---|
| 4327 | + video_device_node_name(vdev), |
---|
| 4328 | + cs->request_fd); |
---|
| 4329 | + media_request_unlock_for_update(req); |
---|
| 4330 | + media_request_put(req); |
---|
| 4331 | + return PTR_ERR(obj); |
---|
| 4332 | + } |
---|
| 4333 | + hdl = container_of(obj, struct v4l2_ctrl_handler, |
---|
| 4334 | + req_obj); |
---|
| 4335 | + } |
---|
| 4336 | + |
---|
| 4337 | + ret = try_set_ext_ctrls_common(fh, hdl, cs, vdev, set); |
---|
| 4338 | + if (ret) |
---|
| 4339 | + dprintk(vdev, |
---|
| 4340 | + "%s: try_set_ext_ctrls_common failed (%d)\n", |
---|
| 4341 | + video_device_node_name(vdev), ret); |
---|
| 4342 | + |
---|
| 4343 | + if (obj) { |
---|
| 4344 | + media_request_unlock_for_update(req); |
---|
| 4345 | + media_request_object_put(obj); |
---|
| 4346 | + media_request_put(req); |
---|
| 4347 | + } |
---|
| 4348 | + |
---|
| 4349 | + return ret; |
---|
| 4350 | +} |
---|
| 4351 | + |
---|
| 4352 | +int v4l2_try_ext_ctrls(struct v4l2_ctrl_handler *hdl, |
---|
| 4353 | + struct video_device *vdev, |
---|
| 4354 | + struct media_device *mdev, |
---|
| 4355 | + struct v4l2_ext_controls *cs) |
---|
| 4356 | +{ |
---|
| 4357 | + return try_set_ext_ctrls(NULL, hdl, vdev, mdev, cs, false); |
---|
3351 | 4358 | } |
---|
3352 | 4359 | EXPORT_SYMBOL(v4l2_try_ext_ctrls); |
---|
3353 | 4360 | |
---|
3354 | | -int v4l2_s_ext_ctrls(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl, |
---|
3355 | | - struct v4l2_ext_controls *cs) |
---|
| 4361 | +int v4l2_s_ext_ctrls(struct v4l2_fh *fh, |
---|
| 4362 | + struct v4l2_ctrl_handler *hdl, |
---|
| 4363 | + struct video_device *vdev, |
---|
| 4364 | + struct media_device *mdev, |
---|
| 4365 | + struct v4l2_ext_controls *cs) |
---|
3356 | 4366 | { |
---|
3357 | | - return try_set_ext_ctrls(fh, hdl, cs, true); |
---|
| 4367 | + return try_set_ext_ctrls(fh, hdl, vdev, mdev, cs, true); |
---|
3358 | 4368 | } |
---|
3359 | 4369 | EXPORT_SYMBOL(v4l2_s_ext_ctrls); |
---|
3360 | 4370 | |
---|
.. | .. |
---|
3425 | 4435 | lockdep_assert_held(ctrl->handler->lock); |
---|
3426 | 4436 | |
---|
3427 | 4437 | /* It's a driver bug if this happens. */ |
---|
3428 | | - WARN_ON(!ctrl->is_int); |
---|
| 4438 | + if (WARN_ON(!ctrl->is_int)) |
---|
| 4439 | + return -EINVAL; |
---|
3429 | 4440 | ctrl->val = val; |
---|
3430 | 4441 | return set_ctrl(NULL, ctrl, 0); |
---|
3431 | 4442 | } |
---|
.. | .. |
---|
3436 | 4447 | lockdep_assert_held(ctrl->handler->lock); |
---|
3437 | 4448 | |
---|
3438 | 4449 | /* It's a driver bug if this happens. */ |
---|
3439 | | - WARN_ON(ctrl->is_ptr || ctrl->type != V4L2_CTRL_TYPE_INTEGER64); |
---|
| 4450 | + if (WARN_ON(ctrl->is_ptr || ctrl->type != V4L2_CTRL_TYPE_INTEGER64)) |
---|
| 4451 | + return -EINVAL; |
---|
3440 | 4452 | *ctrl->p_new.p_s64 = val; |
---|
3441 | 4453 | return set_ctrl(NULL, ctrl, 0); |
---|
3442 | 4454 | } |
---|
.. | .. |
---|
3447 | 4459 | lockdep_assert_held(ctrl->handler->lock); |
---|
3448 | 4460 | |
---|
3449 | 4461 | /* It's a driver bug if this happens. */ |
---|
3450 | | - WARN_ON(ctrl->type != V4L2_CTRL_TYPE_STRING); |
---|
3451 | | - strlcpy(ctrl->p_new.p_char, s, ctrl->maximum + 1); |
---|
| 4462 | + if (WARN_ON(ctrl->type != V4L2_CTRL_TYPE_STRING)) |
---|
| 4463 | + return -EINVAL; |
---|
| 4464 | + strscpy(ctrl->p_new.p_char, s, ctrl->maximum + 1); |
---|
3452 | 4465 | return set_ctrl(NULL, ctrl, 0); |
---|
3453 | 4466 | } |
---|
3454 | 4467 | EXPORT_SYMBOL(__v4l2_ctrl_s_ctrl_string); |
---|
| 4468 | + |
---|
| 4469 | +int __v4l2_ctrl_s_ctrl_compound(struct v4l2_ctrl *ctrl, |
---|
| 4470 | + enum v4l2_ctrl_type type, const void *p) |
---|
| 4471 | +{ |
---|
| 4472 | + lockdep_assert_held(ctrl->handler->lock); |
---|
| 4473 | + |
---|
| 4474 | + /* It's a driver bug if this happens. */ |
---|
| 4475 | + if (WARN_ON(ctrl->type != type)) |
---|
| 4476 | + return -EINVAL; |
---|
| 4477 | + memcpy(ctrl->p_new.p, p, ctrl->elems * ctrl->elem_size); |
---|
| 4478 | + return set_ctrl(NULL, ctrl, 0); |
---|
| 4479 | +} |
---|
| 4480 | +EXPORT_SYMBOL(__v4l2_ctrl_s_ctrl_compound); |
---|
| 4481 | + |
---|
| 4482 | +void v4l2_ctrl_request_complete(struct media_request *req, |
---|
| 4483 | + struct v4l2_ctrl_handler *main_hdl) |
---|
| 4484 | +{ |
---|
| 4485 | + struct media_request_object *obj; |
---|
| 4486 | + struct v4l2_ctrl_handler *hdl; |
---|
| 4487 | + struct v4l2_ctrl_ref *ref; |
---|
| 4488 | + |
---|
| 4489 | + if (!req || !main_hdl) |
---|
| 4490 | + return; |
---|
| 4491 | + |
---|
| 4492 | + /* |
---|
| 4493 | + * Note that it is valid if nothing was found. It means |
---|
| 4494 | + * that this request doesn't have any controls and so just |
---|
| 4495 | + * wants to leave the controls unchanged. |
---|
| 4496 | + */ |
---|
| 4497 | + obj = media_request_object_find(req, &req_ops, main_hdl); |
---|
| 4498 | + if (!obj) |
---|
| 4499 | + return; |
---|
| 4500 | + hdl = container_of(obj, struct v4l2_ctrl_handler, req_obj); |
---|
| 4501 | + |
---|
| 4502 | + list_for_each_entry(ref, &hdl->ctrl_refs, node) { |
---|
| 4503 | + struct v4l2_ctrl *ctrl = ref->ctrl; |
---|
| 4504 | + struct v4l2_ctrl *master = ctrl->cluster[0]; |
---|
| 4505 | + unsigned int i; |
---|
| 4506 | + |
---|
| 4507 | + if (ctrl->flags & V4L2_CTRL_FLAG_VOLATILE) { |
---|
| 4508 | + v4l2_ctrl_lock(master); |
---|
| 4509 | + /* g_volatile_ctrl will update the current control values */ |
---|
| 4510 | + for (i = 0; i < master->ncontrols; i++) |
---|
| 4511 | + cur_to_new(master->cluster[i]); |
---|
| 4512 | + call_op(master, g_volatile_ctrl); |
---|
| 4513 | + new_to_req(ref); |
---|
| 4514 | + v4l2_ctrl_unlock(master); |
---|
| 4515 | + continue; |
---|
| 4516 | + } |
---|
| 4517 | + if (ref->valid_p_req) |
---|
| 4518 | + continue; |
---|
| 4519 | + |
---|
| 4520 | + /* Copy the current control value into the request */ |
---|
| 4521 | + v4l2_ctrl_lock(ctrl); |
---|
| 4522 | + cur_to_req(ref); |
---|
| 4523 | + v4l2_ctrl_unlock(ctrl); |
---|
| 4524 | + } |
---|
| 4525 | + |
---|
| 4526 | + mutex_lock(main_hdl->lock); |
---|
| 4527 | + WARN_ON(!hdl->request_is_queued); |
---|
| 4528 | + list_del_init(&hdl->requests_queued); |
---|
| 4529 | + hdl->request_is_queued = false; |
---|
| 4530 | + mutex_unlock(main_hdl->lock); |
---|
| 4531 | + media_request_object_complete(obj); |
---|
| 4532 | + media_request_object_put(obj); |
---|
| 4533 | +} |
---|
| 4534 | +EXPORT_SYMBOL(v4l2_ctrl_request_complete); |
---|
| 4535 | + |
---|
| 4536 | +int v4l2_ctrl_request_setup(struct media_request *req, |
---|
| 4537 | + struct v4l2_ctrl_handler *main_hdl) |
---|
| 4538 | +{ |
---|
| 4539 | + struct media_request_object *obj; |
---|
| 4540 | + struct v4l2_ctrl_handler *hdl; |
---|
| 4541 | + struct v4l2_ctrl_ref *ref; |
---|
| 4542 | + int ret = 0; |
---|
| 4543 | + |
---|
| 4544 | + if (!req || !main_hdl) |
---|
| 4545 | + return 0; |
---|
| 4546 | + |
---|
| 4547 | + if (WARN_ON(req->state != MEDIA_REQUEST_STATE_QUEUED)) |
---|
| 4548 | + return -EBUSY; |
---|
| 4549 | + |
---|
| 4550 | + /* |
---|
| 4551 | + * Note that it is valid if nothing was found. It means |
---|
| 4552 | + * that this request doesn't have any controls and so just |
---|
| 4553 | + * wants to leave the controls unchanged. |
---|
| 4554 | + */ |
---|
| 4555 | + obj = media_request_object_find(req, &req_ops, main_hdl); |
---|
| 4556 | + if (!obj) |
---|
| 4557 | + return 0; |
---|
| 4558 | + if (obj->completed) { |
---|
| 4559 | + media_request_object_put(obj); |
---|
| 4560 | + return -EBUSY; |
---|
| 4561 | + } |
---|
| 4562 | + hdl = container_of(obj, struct v4l2_ctrl_handler, req_obj); |
---|
| 4563 | + |
---|
| 4564 | + list_for_each_entry(ref, &hdl->ctrl_refs, node) |
---|
| 4565 | + ref->req_done = false; |
---|
| 4566 | + |
---|
| 4567 | + list_for_each_entry(ref, &hdl->ctrl_refs, node) { |
---|
| 4568 | + struct v4l2_ctrl *ctrl = ref->ctrl; |
---|
| 4569 | + struct v4l2_ctrl *master = ctrl->cluster[0]; |
---|
| 4570 | + bool have_new_data = false; |
---|
| 4571 | + int i; |
---|
| 4572 | + |
---|
| 4573 | + /* |
---|
| 4574 | + * Skip if this control was already handled by a cluster. |
---|
| 4575 | + * Skip button controls and read-only controls. |
---|
| 4576 | + */ |
---|
| 4577 | + if (ref->req_done || ctrl->type == V4L2_CTRL_TYPE_BUTTON || |
---|
| 4578 | + (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY)) |
---|
| 4579 | + continue; |
---|
| 4580 | + |
---|
| 4581 | + v4l2_ctrl_lock(master); |
---|
| 4582 | + for (i = 0; i < master->ncontrols; i++) { |
---|
| 4583 | + if (master->cluster[i]) { |
---|
| 4584 | + struct v4l2_ctrl_ref *r = |
---|
| 4585 | + find_ref(hdl, master->cluster[i]->id); |
---|
| 4586 | + |
---|
| 4587 | + if (r->valid_p_req) { |
---|
| 4588 | + have_new_data = true; |
---|
| 4589 | + break; |
---|
| 4590 | + } |
---|
| 4591 | + } |
---|
| 4592 | + } |
---|
| 4593 | + if (!have_new_data) { |
---|
| 4594 | + v4l2_ctrl_unlock(master); |
---|
| 4595 | + continue; |
---|
| 4596 | + } |
---|
| 4597 | + |
---|
| 4598 | + for (i = 0; i < master->ncontrols; i++) { |
---|
| 4599 | + if (master->cluster[i]) { |
---|
| 4600 | + struct v4l2_ctrl_ref *r = |
---|
| 4601 | + find_ref(hdl, master->cluster[i]->id); |
---|
| 4602 | + |
---|
| 4603 | + req_to_new(r); |
---|
| 4604 | + master->cluster[i]->is_new = 1; |
---|
| 4605 | + r->req_done = true; |
---|
| 4606 | + } |
---|
| 4607 | + } |
---|
| 4608 | + /* |
---|
| 4609 | + * For volatile autoclusters that are currently in auto mode |
---|
| 4610 | + * we need to discover if it will be set to manual mode. |
---|
| 4611 | + * If so, then we have to copy the current volatile values |
---|
| 4612 | + * first since those will become the new manual values (which |
---|
| 4613 | + * may be overwritten by explicit new values from this set |
---|
| 4614 | + * of controls). |
---|
| 4615 | + */ |
---|
| 4616 | + if (master->is_auto && master->has_volatiles && |
---|
| 4617 | + !is_cur_manual(master)) { |
---|
| 4618 | + s32 new_auto_val = *master->p_new.p_s32; |
---|
| 4619 | + |
---|
| 4620 | + /* |
---|
| 4621 | + * If the new value == the manual value, then copy |
---|
| 4622 | + * the current volatile values. |
---|
| 4623 | + */ |
---|
| 4624 | + if (new_auto_val == master->manual_mode_value) |
---|
| 4625 | + update_from_auto_cluster(master); |
---|
| 4626 | + } |
---|
| 4627 | + |
---|
| 4628 | + ret = try_or_set_cluster(NULL, master, true, 0); |
---|
| 4629 | + v4l2_ctrl_unlock(master); |
---|
| 4630 | + |
---|
| 4631 | + if (ret) |
---|
| 4632 | + break; |
---|
| 4633 | + } |
---|
| 4634 | + |
---|
| 4635 | + media_request_object_put(obj); |
---|
| 4636 | + return ret; |
---|
| 4637 | +} |
---|
| 4638 | +EXPORT_SYMBOL(v4l2_ctrl_request_setup); |
---|
3455 | 4639 | |
---|
3456 | 4640 | void v4l2_ctrl_notify(struct v4l2_ctrl *ctrl, v4l2_ctrl_notify_fnc notify, void *priv) |
---|
3457 | 4641 | { |
---|
.. | .. |
---|
3620 | 4804 | { |
---|
3621 | 4805 | struct v4l2_fh *fh = file->private_data; |
---|
3622 | 4806 | |
---|
| 4807 | + poll_wait(file, &fh->wait, wait); |
---|
3623 | 4808 | if (v4l2_event_pending(fh)) |
---|
3624 | 4809 | return EPOLLPRI; |
---|
3625 | | - poll_wait(file, &fh->wait, wait); |
---|
3626 | 4810 | return 0; |
---|
3627 | 4811 | } |
---|
3628 | 4812 | EXPORT_SYMBOL(v4l2_ctrl_poll); |
---|
| 4813 | + |
---|
| 4814 | +int v4l2_ctrl_new_fwnode_properties(struct v4l2_ctrl_handler *hdl, |
---|
| 4815 | + const struct v4l2_ctrl_ops *ctrl_ops, |
---|
| 4816 | + const struct v4l2_fwnode_device_properties *p) |
---|
| 4817 | +{ |
---|
| 4818 | + if (p->orientation != V4L2_FWNODE_PROPERTY_UNSET) { |
---|
| 4819 | + u32 orientation_ctrl; |
---|
| 4820 | + |
---|
| 4821 | + switch (p->orientation) { |
---|
| 4822 | + case V4L2_FWNODE_ORIENTATION_FRONT: |
---|
| 4823 | + orientation_ctrl = V4L2_CAMERA_ORIENTATION_FRONT; |
---|
| 4824 | + break; |
---|
| 4825 | + case V4L2_FWNODE_ORIENTATION_BACK: |
---|
| 4826 | + orientation_ctrl = V4L2_CAMERA_ORIENTATION_BACK; |
---|
| 4827 | + break; |
---|
| 4828 | + case V4L2_FWNODE_ORIENTATION_EXTERNAL: |
---|
| 4829 | + orientation_ctrl = V4L2_CAMERA_ORIENTATION_EXTERNAL; |
---|
| 4830 | + break; |
---|
| 4831 | + default: |
---|
| 4832 | + return -EINVAL; |
---|
| 4833 | + } |
---|
| 4834 | + if (!v4l2_ctrl_new_std_menu(hdl, ctrl_ops, |
---|
| 4835 | + V4L2_CID_CAMERA_ORIENTATION, |
---|
| 4836 | + V4L2_CAMERA_ORIENTATION_EXTERNAL, 0, |
---|
| 4837 | + orientation_ctrl)) |
---|
| 4838 | + return hdl->error; |
---|
| 4839 | + } |
---|
| 4840 | + |
---|
| 4841 | + if (p->rotation != V4L2_FWNODE_PROPERTY_UNSET) { |
---|
| 4842 | + if (!v4l2_ctrl_new_std(hdl, ctrl_ops, |
---|
| 4843 | + V4L2_CID_CAMERA_SENSOR_ROTATION, |
---|
| 4844 | + p->rotation, p->rotation, 1, |
---|
| 4845 | + p->rotation)) |
---|
| 4846 | + return hdl->error; |
---|
| 4847 | + } |
---|
| 4848 | + |
---|
| 4849 | + return hdl->error; |
---|
| 4850 | +} |
---|
| 4851 | +EXPORT_SYMBOL(v4l2_ctrl_new_fwnode_properties); |
---|