7.29. ioctl VIDIOC_G_EXT_CTRLS, VIDIOC_S_EXT_CTRLS, VIDIOC_TRY_EXT_CTRLS

7.29.1. 名稱

VIDIOC_G_EXT_CTRLS - VIDIOC_S_EXT_CTRLS - VIDIOC_TRY_EXT_CTRLS - 獲取或設定多個控制元件的值,嘗試控制元件值

7.29.2. 概要

VIDIOC_G_EXT_CTRLS

int ioctl(int fd, VIDIOC_G_EXT_CTRLS, struct v4l2_ext_controls *argp)

VIDIOC_S_EXT_CTRLS

int ioctl(int fd, VIDIOC_S_EXT_CTRLS, struct v4l2_ext_controls *argp)

VIDIOC_TRY_EXT_CTRLS

int ioctl(int fd, VIDIOC_TRY_EXT_CTRLS, struct v4l2_ext_controls *argp)

7.29.3. 引數

fd

open() 返回的檔案描述符。

argp

指向 struct v4l2_ext_controls 的指標。

7.29.4. 描述

這些 ioctl 允許呼叫者以原子方式獲取或設定多個控制元件。控制元件 ID 被分組到控制元件類中(參見 控制元件類),並且控制元件陣列中的所有控制元件必須屬於同一個控制元件類。

應用程式必須始終填寫 struct v4l2_ext_controlscountwhichcontrolsreserved 欄位,並初始化 controls 欄位指向的 struct v4l2_ext_control 陣列。

要獲取一組控制元件的當前值,應用程式需要初始化每個 struct v4l2_ext_controlidsizereserved2 欄位,並呼叫 VIDIOC_G_EXT_CTRLS ioctl。字串控制元件還必須設定 string 欄位。複合型別的控制元件(設定了 V4L2_CTRL_FLAG_HAS_PAYLOAD)必須設定 ptr 欄位。

如果 size 太小,無法接收控制元件結果(僅與指標型別控制元件(如字串)相關),則驅動程式會將 size 設定為有效值並返回 ENOSPC 錯誤程式碼。您應該將記憶體重新分配到這個新的大小並重試。對於字串型別,如果字串在這段時間內增長了,則可能再次出現相同的問題。建議先呼叫 ioctls VIDIOC_QUERYCTRL、VIDIOC_QUERY_EXT_CTRL 和 VIDIOC_QUERYMENU,並使用 maximum+1 作為新的 size 值。這保證了足夠的記憶體。

N 維陣列是逐行設定和檢索的。您不能設定部分陣列,必須設定或檢索所有元素。總大小計算為 elems * elem_size。這些值可以透過呼叫 VIDIOC_QUERY_EXT_CTRL 來獲取。

要更改一組控制元件的值,應用程式需要初始化每個 struct v4l2_ext_controlidsizereserved2value/value64/string/ptr 欄位,並呼叫 VIDIOC_S_EXT_CTRLS ioctl。只有在所有控制元件值都有效時,才會設定這些控制元件。

要檢查一組控制元件是否具有正確的值,應用程式需要初始化每個 struct v4l2_ext_controlidsizereserved2value/value64/string/ptr 欄位,並呼叫 VIDIOC_TRY_EXT_CTRLS ioctl。驅動程式可以自動將錯誤的值調整為有效值,也可以返回錯誤,具體取決於驅動程式。

idwhich 無效時,驅動程式會返回 EINVAL 錯誤程式碼。當值超出範圍時,驅動程式可以選擇採用最接近的有效值或返回 ERANGE 錯誤程式碼,無論哪種方式看起來更合適。在第一種情況下,新值將在 struct v4l2_ext_control 中設定。如果新的控制元件值不合適(例如,給定的選單索引不受選單控制元件支援),那麼這將導致 EINVAL 錯誤程式碼錯誤。

如果 request_fd 設定為尚未排隊的 請求 檔案描述符,並且 which 設定為 V4L2_CTRL_WHICH_REQUEST_VAL,那麼控制元件不會在呼叫 VIDIOC_S_EXT_CTRLS 時立即應用,而是由驅動程式為與同一請求關聯的緩衝區應用。如果裝置不支援請求,則將返回 EACCES。如果支援請求,但給出了無效的請求檔案描述符,則將返回 EINVAL

嘗試為已排隊的請求呼叫 VIDIOC_S_EXT_CTRLS 將導致 EBUSY 錯誤。

如果在呼叫 VIDIOC_G_EXT_CTRLS 期間指定了 request_fd 並且 which 設定為 V4L2_CTRL_WHICH_REQUEST_VAL,那麼它將返回請求完成時的控制元件值。如果請求尚未完成,那麼這將導致 EACCES 錯誤。

只有在所有控制元件值都正確時,驅動程式才會設定/獲取這些控制元件。這可以防止僅設定/獲取部分控制元件的情況。只有低階錯誤(例如,i2c 命令失敗)仍然會導致這種情況。

型別 v4l2_ext_control
struct v4l2_ext_control

__u32

id

標識控制元件,由應用程式設定。

__u32

size

此控制元件的有效負載的總大小(以位元組為單位)。

size 欄位通常為 0,但對於指標控制元件,應將其設定為包含有效負載或將接收有效負載的記憶體大小。如果 VIDIOC_G_EXT_CTRLS 發現此值小於儲存有效負載結果所需的值,那麼它將被設定為足夠大以儲存有效負載結果的值,並且返回 ENOSPC

注意

對於字串控制元件,不應將此 size 欄位與字串的長度混淆。此欄位指的是包含字串的記憶體的大小。字串的實際長度可能小得多。

__u32

reserved2[1]

保留供將來擴充套件使用。驅動程式和應用程式必須將陣列設定為零。

union {

(anonymous)

__s32

value

新值或當前值。如果此控制元件的型別不是 V4L2_CTRL_TYPE_INTEGER64 且未設定 V4L2_CTRL_FLAG_HAS_PAYLOAD,則有效。

__s64

value64

新值或當前值。如果此控制元件的型別為 V4L2_CTRL_TYPE_INTEGER64 且未設定 V4L2_CTRL_FLAG_HAS_PAYLOAD,則有效。

char *

string

指向字串的指標。如果此控制元件的型別為 V4L2_CTRL_TYPE_STRING,則有效。

__u8 *

p_u8

指向無符號 8 位值的矩陣控制元件的指標。如果此控制元件的型別為 V4L2_CTRL_TYPE_U8,則有效。

__u16 *

p_u16

指向無符號 16 位值的矩陣控制元件的指標。如果此控制元件的型別為 V4L2_CTRL_TYPE_U16,則有效。

__u32 *

p_u32

指向無符號 32 位值的矩陣控制元件的指標。如果此控制元件的型別為 V4L2_CTRL_TYPE_U32,則有效。

__s32 *

p_s32

指向有符號 32 位值的矩陣控制元件的指標。如果此控制元件的型別為 V4L2_CTRL_TYPE_INTEGER 且設定了 V4L2_CTRL_FLAG_HAS_PAYLOAD,則有效。

__s64 *

p_s64

指向有符號 64 位值的矩陣控制元件的指標。如果此控制元件的型別為 V4L2_CTRL_TYPE_INTEGER64 且設定了 V4L2_CTRL_FLAG_HAS_PAYLOAD,則有效。

struct v4l2_area *

p_area

指向 struct v4l2_area 的指標。如果此控制元件的型別為 V4L2_CTRL_TYPE_AREA,則有效。

struct v4l2_rect *

p_rect

指向 struct v4l2_rect 的指標。如果此控制元件的型別為 V4L2_CTRL_TYPE_RECT,則有效。

struct v4l2_ctrl_h264_sps *

p_h264_sps

指向 struct v4l2_ctrl_h264_sps 的指標。如果此控制元件的型別為 V4L2_CTRL_TYPE_H264_SPS,則有效。

struct v4l2_ctrl_h264_pps *

p_h264_pps

指向 struct v4l2_ctrl_h264_pps 的指標。如果此控制元件的型別為 V4L2_CTRL_TYPE_H264_PPS,則有效。

struct v4l2_ctrl_h264_scaling_matrix *

p_h264_scaling_matrix

指向 struct v4l2_ctrl_h264_scaling_matrix 的指標。如果此控制元件的型別為 V4L2_CTRL_TYPE_H264_SCALING_MATRIX,則有效。

struct v4l2_ctrl_h264_pred_weights *

p_h264_pred_weights

指向 struct v4l2_ctrl_h264_pred_weights 的指標。如果此控制元件的型別為 V4L2_CTRL_TYPE_H264_PRED_WEIGHTS,則有效。

struct v4l2_ctrl_h264_slice_params *

p_h264_slice_params

指向 struct v4l2_ctrl_h264_slice_params 的指標。如果此控制元件的型別為 V4L2_CTRL_TYPE_H264_SLICE_PARAMS,則有效。

struct v4l2_ctrl_h264_decode_params *

p_h264_decode_params

指向 struct v4l2_ctrl_h264_decode_params 的指標。如果此控制元件的型別為 V4L2_CTRL_TYPE_H264_DECODE_PARAMS,則有效。

struct v4l2_ctrl_fwht_params *

p_fwht_params

指向 struct v4l2_ctrl_fwht_params 的指標。如果此控制元件的型別為 V4L2_CTRL_TYPE_FWHT_PARAMS,則有效。

struct v4l2_ctrl_vp8_frame *

p_vp8_frame

指向 struct v4l2_ctrl_vp8_frame 的指標。如果此控制元件的型別為 V4L2_CTRL_TYPE_VP8_FRAME,則有效。

struct v4l2_ctrl_mpeg2_sequence *

p_mpeg2_sequence

指向 struct v4l2_ctrl_mpeg2_sequence 的指標。如果此控制元件的型別為 V4L2_CTRL_TYPE_MPEG2_SEQUENCE,則有效。

struct v4l2_ctrl_mpeg2_picture *

p_mpeg2_picture

指向 struct v4l2_ctrl_mpeg2_picture 的指標。如果此控制元件的型別為 V4L2_CTRL_TYPE_MPEG2_PICTURE,則有效。

struct v4l2_ctrl_mpeg2_quantisation *

p_mpeg2_quantisation

指向 struct v4l2_ctrl_mpeg2_quantisation 的指標。如果此控制元件的型別為 V4L2_CTRL_TYPE_MPEG2_QUANTISATION,則有效。

struct v4l2_ctrl_vp9_compressed_hdr *

p_vp9_compressed_hdr_probs

指向 struct v4l2_ctrl_vp9_compressed_hdr 的指標。如果此控制元件的型別為 V4L2_CTRL_TYPE_VP9_COMPRESSED_HDR,則有效。

struct v4l2_ctrl_vp9_frame *

p_vp9_frame

指向 struct v4l2_ctrl_vp9_frame 的指標。如果此控制元件的型別為 V4L2_CTRL_TYPE_VP9_FRAME,則有效。

struct v4l2_ctrl_hdr10_cll_info *

p_hdr10_cll

指向 struct v4l2_ctrl_hdr10_cll_info 的指標。如果此控制元件的型別為 V4L2_CTRL_TYPE_HDR10_CLL_INFO,則有效。

struct v4l2_ctrl_hdr10_mastering_display *

p_hdr10_mastering

指向 struct v4l2_ctrl_hdr10_mastering_display 的指標。如果此控制元件的型別為 V4L2_CTRL_TYPE_HDR10_MASTERING_DISPLAY,則有效。

struct v4l2_ctrl_hevc_sps *

p_hevc_sps

指向 struct v4l2_ctrl_hevc_sps 的指標。如果此控制元件的型別為 V4L2_CTRL_TYPE_HEVC_SPS,則有效。

struct v4l2_ctrl_hevc_pps *

p_hevc_pps

指向 struct v4l2_ctrl_hevc_pps 的指標。如果此控制元件的型別為 V4L2_CTRL_TYPE_HEVC_PPS,則有效。

struct v4l2_ctrl_hevc_slice_params *

p_hevc_slice_params

指向 struct v4l2_ctrl_hevc_slice_params 的指標。如果此控制元件的型別為 V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS,則有效。

struct v4l2_ctrl_hevc_scaling_matrix *

p_hevc_scaling_matrix

指向 struct v4l2_ctrl_hevc_scaling_matrix 的指標。如果此控制元件的型別為 V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX,則有效。

struct v4l2_ctrl_hevc_decode_params *

p_hevc_decode_params

指向 struct v4l2_ctrl_hevc_decode_params 的指標。如果此控制元件的型別為 V4L2_CTRL_TYPE_HEVC_DECODE_PARAMS,則有效。

struct v4l2_ctrl_av1_sequence *

p_av1_sequence

指向 struct v4l2_ctrl_av1_sequence 的指標。如果此控制元件的型別為 V4L2_CTRL_TYPE_AV1_SEQUENCE,則有效。

struct v4l2_ctrl_av1_tile_group_entry *

p_av1_tile_group_entry

指向 struct v4l2_ctrl_av1_tile_group_entry 的指標。如果此控制元件的型別為 V4L2_CTRL_TYPE_AV1_TILE_GROUP_ENTRY,則有效。

struct v4l2_ctrl_av1_frame *

p_av1_frame

指向 struct v4l2_ctrl_av1_frame 的指標。如果此控制元件的型別為 V4L2_CTRL_TYPE_AV1_FRAME,則有效。

struct v4l2_ctrl_av1_film_grain *

p_av1_film_grain

指向 struct v4l2_ctrl_av1_film_grain 的指標。如果此控制元件的型別為 V4L2_CTRL_TYPE_AV1_FILM_GRAIN,則有效。

struct v4l2_ctrl_hdr10_cll_info *

p_hdr10_cll_info

指向 struct v4l2_ctrl_hdr10_cll_info 的指標。如果此控制元件的型別為 V4L2_CTRL_TYPE_HDR10_CLL_INFO,則有效。

struct v4l2_ctrl_hdr10_mastering_display *

p_hdr10_mastering_display

指向 struct v4l2_ctrl_hdr10_mastering_display 的指標。如果此控制元件的型別為 V4L2_CTRL_TYPE_HDR10_MASTERING_DISPLAY,則有效。

void *

ptr

指向複合型別的指標,該複合型別可以是 N 維陣列和/或複合型別(控制元件的型別 >= V4L2_CTRL_COMPOUND_TYPES)。如果為此控制元件設定了 V4L2_CTRL_FLAG_HAS_PAYLOAD,則有效。

}

型別 v4l2_ext_controls
struct v4l2_ext_controls

union {

(anonymous)

__u32

which

要獲取/設定/嘗試的控制元件的值。

V4L2_CTRL_WHICH_CUR_VAL 將返回控制元件的當前值,V4L2_CTRL_WHICH_DEF_VAL 將返回控制元件的預設值,V4L2_CTRL_WHICH_MIN_VAL 將返回控制元件的最小值,V4L2_CTRL_WHICH_MAX_VAL 將返回控制元件的最大值。V4L2_CTRL_WHICH_REQUEST_VAL 指示必須從請求中檢索控制元件值,或者為請求嘗試/設定控制元件值。在這種情況下,request_fd 欄位包含應使用的請求的檔案描述符。如果裝置不支援請求,則將返回 EACCES

使用 V4L2_CTRL_WHICH_DEF_VALV4L2_CTRL_WHICH_MIN_VALV4L2_CTRL_WHICH_MAX_VAL 時,請注意您只能獲取控制元件的預設值/最小值/最大值,而不能設定或嘗試它。

是否控制元件支援使用 V4L2_CTRL_WHICH_MIN_VALV4L2_CTRL_WHICH_MAX_VAL 查詢最小值和最大值由 V4L2_CTRL_FLAG_HAS_WHICH_MIN_MAX 標誌指示。大多數非複合控制元件型別都支援這一點。對於具有複合型別的控制元件,最小值/最大值的定義由控制元件文件提供。如果複合控制元件沒有記錄最小值/最大值的含義,那麼查詢最小值或最大值將導致錯誤程式碼 -EINVAL。

為了向後相容,您也可以在此處使用控制元件類(參見 控制元件類)。在這種情況下,所有控制元件都必須屬於該控制元件類。此用法已棄用,請改用 V4L2_CTRL_WHICH_CUR_VAL。有一些非常舊的驅動程式尚不支援 V4L2_CTRL_WHICH_CUR_VAL,並且需要在此處使用控制元件類。您可以透過將 which 設定為 V4L2_CTRL_WHICH_CUR_VAL 並使用計數 0 呼叫 VIDIOC_TRY_EXT_CTRLS 來測試此類驅動程式。如果這失敗了,那麼驅動程式不支援 V4L2_CTRL_WHICH_CUR_VAL

__u32

ctrl_class

為了向後相容而保留的已棄用名稱。請改用 which

}

__u32

count

控制元件陣列中控制元件的數量。也可以為零。

__u32

error_idx

失敗控制元件的索引。在發生錯誤時由驅動程式設定。

如果錯誤與特定控制元件相關聯,則 error_idx 將設定為該控制元件的索引。如果錯誤與特定控制元件無關,或者驗證步驟失敗(請參見下文),則 error_idx 將設定為 count。如果 ioctl 返回 0(成功),則該值未定義。

在從硬體讀取控制元件或寫入硬體之前,會進行驗證步驟:這會檢查列表中的所有控制元件是否都是有效的控制元件,是否沒有嘗試寫入只讀控制元件或從只寫控制元件讀取,以及任何其他可以在不訪問硬體的情況下進行的預先檢查。在此步驟中完成的確切驗證取決於驅動程式,因為某些檢查可能需要硬體訪問才能用於某些裝置,因此無法進行預先檢查。但是,驅動程式應盡最大努力進行儘可能多的預先檢查。

進行此檢查是為了避免由於容易避免的問題而使硬體處於不一致的狀態。但這會導致另一個問題:應用程式需要知道錯誤是來自驗證步驟(意味著未觸及硬體)還是來自實際讀取硬體或寫入硬體期間的錯誤。

為此,事後看來很糟糕的解決方案是,如果驗證失敗,則將 error_idx 設定為 count。這會產生一個不幸的副作用,即無法看到哪個控制元件驗證失敗。如果驗證成功並且在訪問硬體時發生了錯誤,那麼 error_idx 小於 count,並且只有到 error_idx-1 的控制元件被正確讀取或寫入,其餘控制元件的狀態未定義。

由於 VIDIOC_TRY_EXT_CTRLS 不訪問硬體,因此也不需要以這種特殊方式處理驗證步驟,所以 error_idx 將被設定為驗證失敗的控制元件,而不是 count。這意味著,如果 VIDIOC_S_EXT_CTRLS 失敗,並且 error_idx 被設定為 count,那麼您可以呼叫 VIDIOC_TRY_EXT_CTRLS 來嘗試發現實際驗證失敗的控制元件。不幸的是,對於 VIDIOC_G_EXT_CTRLS,沒有等效的 TRY 操作。

__s32

request_fd

用於此操作的請求的檔案描述符。僅當 which 設定為 V4L2_CTRL_WHICH_REQUEST_VAL 時有效。如果裝置不支援請求,則將返回 EACCES。如果支援請求,但給出了無效的請求檔案描述符,則將返回 EINVAL

__u32

保留[1]

為將來的擴充套件保留。

驅動程式和應用程式必須將陣列設定為零。

struct v4l2_ext_control *

控制元件

指向 count 個 v4l2_ext_control 結構體的陣列的指標。

如果 count 等於零,則忽略。

控制類

V4L2_CTRL_CLASS_USER

0x980000

包含使用者控制元件的類。這些控制元件在 使用者控制元件 中描述。可以使用 VIDIOC_S_CTRLVIDIOC_G_CTRL ioctl 設定的所有控制元件都屬於此類。

V4L2_CTRL_CLASS_CODEC

0x990000

包含有狀態編解碼器控制元件的類。這些控制元件在 編解碼器控制元件參考 中描述。

V4L2_CTRL_CLASS_CAMERA

0x9a0000

包含相機控制元件的類。這些控制元件在 相機控制元件參考 中描述。

V4L2_CTRL_CLASS_FM_TX

0x9b0000

包含 FM 發射器 (FM TX) 控制元件的類。這些控制元件在 FM 發射器控制元件參考 中描述。

V4L2_CTRL_CLASS_FLASH

0x9c0000

包含閃光燈裝置控制元件的類。這些控制元件在 閃光燈控制元件參考 中描述。

V4L2_CTRL_CLASS_JPEG

0x9d0000

包含 JPEG 壓縮控制元件的類。這些控制元件在 JPEG 控制元件參考 中描述。

V4L2_CTRL_CLASS_IMAGE_SOURCE

0x9e0000

包含影像源控制元件的類。這些控制元件在 影像源控制元件參考 中描述。

V4L2_CTRL_CLASS_IMAGE_PROC

0x9f0000

包含影像處理控制元件的類。這些控制元件在 影像處理控制元件參考 中描述。

V4L2_CTRL_CLASS_FM_RX

0xa10000

包含 FM 接收器 (FM RX) 控制元件的類。這些控制元件在 FM 接收器控制元件參考 中描述。

V4L2_CTRL_CLASS_RF_TUNER

0xa20000

包含 RF 調諧器控制元件的類。這些控制元件在 RF 調諧器控制元件參考 中描述。

V4L2_CTRL_CLASS_DETECT

0xa30000

包含運動或物體檢測控制元件的類。這些控制元件在 檢測控制元件參考 中描述。

V4L2_CTRL_CLASS_CODEC_STATELESS

0xa40000

包含無狀態編解碼器控制元件的類。這些控制元件在 無狀態編解碼器控制元件參考 中描述。

V4L2_CTRL_CLASS_COLORIMETRY

0xa50000

包含色彩控制元件的類。這些控制元件在 色彩控制元件參考 中描述。

7.29.5. 返回值

成功時返回 0,出錯時返回 -1,並且會適當地設定 errno 變數。通用錯誤程式碼在 通用錯誤程式碼 章節中描述。

EINVAL

struct v4l2_ext_control id 無效,或者 struct v4l2_ext_controls which 無效,或者 struct v4l2_ext_control value 不合適(例如,給定的選單索引不受驅動程式支援),或者 which 欄位設定為 V4L2_CTRL_WHICH_REQUEST_VAL,但給定的 request_fd 無效或核心不支援 V4L2_CTRL_WHICH_REQUEST_VAL。如果兩個或多個控制元件值衝突,則 VIDIOC_S_EXT_CTRLSVIDIOC_TRY_EXT_CTRLS ioctl 也會返回此錯誤程式碼。

ERANGE

struct v4l2_ext_control value 超出範圍。

EBUSY

控制元件暫時無法更改,可能是因為另一個應用程式接管了此控制元件所屬的裝置功能的控制,或者(如果 which 欄位設定為 V4L2_CTRL_WHICH_REQUEST_VAL)請求已排隊但尚未完成。

ENOSPC

為控制元件的有效載荷保留的空間不足。欄位 size 設定為足以儲存有效載荷的值,並返回此錯誤程式碼。

EACCES

嘗試嘗試或設定只讀控制元件,或獲取只寫控制元件,或從尚未完成的請求中獲取控制元件。

或者 which 欄位設定為 V4L2_CTRL_WHICH_REQUEST_VAL,但裝置不支援請求。

或者,如果嘗試設定非活動控制元件,並且驅動程式無法快取新值,直到控制元件再次啟用。