2.15. V4L2 控制

2.15.1. 簡介

V4L2 控制 API 看起來很簡單,但在驅動程式中正確實現很快就會變得非常困難。但是,處理控制元件所需的許多程式碼實際上並不是特定於驅動程式的,可以轉移到 V4L 核心框架。

畢竟,驅動程式開發人員唯一感興趣的部分是

  1. 如何新增控制元件?

  2. 如何設定控制元件的值?(即 s_ctrl)

偶爾

  1. 如何獲取控制元件的值?(即 g_volatile_ctrl)

  2. 如何驗證使用者建議的控制元件值?(即 try_ctrl)

其餘的都可以集中處理。

建立控制框架是為了在中心位置實現 V4L2 規範中關於控制的所有規則。並儘可能地方便驅動程式開發人員。

請注意,控制框架依賴於 V4L2 驅動程式的 v4l2_device 結構和子裝置驅動程式的 struct v4l2_subdev 的存在。

2.15.2. 框架中的物件

有兩個主要物件

v4l2_ctrl 物件描述了控制元件的屬性並跟蹤控制元件的值(包括當前值和建議的新值)。

v4l2_ctrl_handler 是跟蹤控制元件的物件。它維護一個它擁有的 v4l2_ctrl 物件列表,以及一個對控制元件的引用列表,可能引用其他處理程式擁有的控制元件。

2.15.3. V4L2 和子裝置驅動程式的基本用法

  1. 準備驅動程式

#include <media/v4l2-ctrls.h>

1.1) 將處理程式新增到驅動程式的頂層結構

對於 V4L2 驅動程式

struct foo_dev {
        ...
        struct v4l2_device v4l2_dev;
        ...
        struct v4l2_ctrl_handler ctrl_handler;
        ...
};

對於子裝置驅動程式

struct foo_dev {
        ...
        struct v4l2_subdev sd;
        ...
        struct v4l2_ctrl_handler ctrl_handler;
        ...
};

1.2) 初始化處理程式

v4l2_ctrl_handler_init(&foo->ctrl_handler, nr_of_controls);

第二個引數是一個提示,告訴函式期望此處理程式處理多少個控制元件。它將基於此資訊分配一個雜湊表。這只是一個提示。

1.3) 將控制元件處理程式掛鉤到驅動程式中

對於 V4L2 驅動程式

foo->v4l2_dev.ctrl_handler = &foo->ctrl_handler;

對於子裝置驅動程式

foo->sd.ctrl_handler = &foo->ctrl_handler;

1.4) 在最後清理處理程式

v4l2_ctrl_handler_free(&foo->ctrl_handler);
  1. 新增控制元件

您可以透過呼叫 v4l2_ctrl_new_std() 新增非選單控制元件

struct v4l2_ctrl *v4l2_ctrl_new_std(struct v4l2_ctrl_handler *hdl,
                const struct v4l2_ctrl_ops *ops,
                u32 id, s32 min, s32 max, u32 step, s32 def);

選單和整數選單控制元件透過呼叫 v4l2_ctrl_new_std_menu() 新增

struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl,
                const struct v4l2_ctrl_ops *ops,
                u32 id, s32 max, s32 skip_mask, s32 def);

帶有特定於驅動程式的選單的選單控制元件透過呼叫 v4l2_ctrl_new_std_menu_items() 新增

struct v4l2_ctrl *v4l2_ctrl_new_std_menu_items(
                struct v4l2_ctrl_handler *hdl,
                const struct v4l2_ctrl_ops *ops, u32 id, s32 max,
                s32 skip_mask, s32 def, const char * const *qmenu);

標準複合控制元件可以透過呼叫 v4l2_ctrl_new_std_compound() 新增

struct v4l2_ctrl *v4l2_ctrl_new_std_compound(struct v4l2_ctrl_handler *hdl,
                const struct v4l2_ctrl_ops *ops, u32 id,
                const union v4l2_ctrl_ptr p_def);

帶有特定於驅動程式的選單的整數選單控制元件可以透過呼叫 v4l2_ctrl_new_int_menu() 新增

struct v4l2_ctrl *v4l2_ctrl_new_int_menu(struct v4l2_ctrl_handler *hdl,
                const struct v4l2_ctrl_ops *ops,
                u32 id, s32 max, s32 def, const s64 *qmenu_int);

這些函式通常在 v4l2_ctrl_handler_init() 之後立即呼叫

static const s64 exp_bias_qmenu[] = {
       -2, -1, 0, 1, 2
};
static const char * const test_pattern[] = {
        "Disabled",
        "Vertical Bars",
        "Solid Black",
        "Solid White",
};

v4l2_ctrl_handler_init(&foo->ctrl_handler, nr_of_controls);
v4l2_ctrl_new_std(&foo->ctrl_handler, &foo_ctrl_ops,
                V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
v4l2_ctrl_new_std(&foo->ctrl_handler, &foo_ctrl_ops,
                V4L2_CID_CONTRAST, 0, 255, 1, 128);
v4l2_ctrl_new_std_menu(&foo->ctrl_handler, &foo_ctrl_ops,
                V4L2_CID_POWER_LINE_FREQUENCY,
                V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0,
                V4L2_CID_POWER_LINE_FREQUENCY_DISABLED);
v4l2_ctrl_new_int_menu(&foo->ctrl_handler, &foo_ctrl_ops,
                V4L2_CID_EXPOSURE_BIAS,
                ARRAY_SIZE(exp_bias_qmenu) - 1,
                ARRAY_SIZE(exp_bias_qmenu) / 2 - 1,
                exp_bias_qmenu);
v4l2_ctrl_new_std_menu_items(&foo->ctrl_handler, &foo_ctrl_ops,
                V4L2_CID_TEST_PATTERN, ARRAY_SIZE(test_pattern) - 1, 0,
                0, test_pattern);
...
if (foo->ctrl_handler.error) {
        int err = foo->ctrl_handler.error;

        v4l2_ctrl_handler_free(&foo->ctrl_handler);
        return err;
}

v4l2_ctrl_new_std() 函式返回指向新控制元件的 v4l2_ctrl 指標,但如果不需要在控制元件操作之外訪問該指標,則無需儲存它。

v4l2_ctrl_new_std() 函式將根據控制元件 ID 填充大多數字段,但最小值、最大值、步長和預設值除外。這些值在最後四個引數中傳遞。這些值是特定於驅動程式的,而控制元件屬性(如型別、名稱、標誌)都是全域性的。控制元件的當前值將設定為預設值。

v4l2_ctrl_new_std_menu() 函式非常相似,但它用於選單控制元件。由於選單控制元件的最小值始終為 0,因此沒有 min 引數,並且沒有步長,而是一個 skip_mask 引數:如果位 X 為 1,則跳過選單項 X。

v4l2_ctrl_new_int_menu() 函式建立一個新的標準整數選單控制元件,其中選單中包含特定於驅動程式的項。它與 v4l2_ctrl_new_std_menu 的不同之處在於,它沒有掩碼引數,而是將有符號 64 位整數陣列作為最後一個引數,該陣列構成精確的選單項列表。

v4l2_ctrl_new_std_menu_items() 函式與 v4l2_ctrl_new_std_menu 非常相似,但採用了一個額外的引數 qmenu,它是特定於驅動程式的選單,用於其他標準的選單控制元件。此控制元件的一個很好的示例是捕獲/顯示/感測器裝置的測試模式控制元件,該控制元件具有生成測試模式的功能。這些測試模式是特定於硬體的,因此選單的內容會因裝置而異。

請注意,如果出現問題,該函式將返回 NULL 或錯誤,並將 ctrl_handler->error 設定為錯誤程式碼。如果 ctrl_handler->error 已設定,則它只會返回並且不執行任何操作。如果 v4l2_ctrl_handler_init 無法分配內部資料結構,則也是如此。

這使得初始化處理程式並新增所有控制元件,並在最後僅檢查錯誤程式碼變得容易。節省了大量重複的錯誤檢查。

建議按升序控制元件 ID 順序新增控制元件:這樣會稍微快一些。

  1. (可選)強制初始控制元件設定

v4l2_ctrl_handler_setup(&foo->ctrl_handler);

這將無條件地為所有控制元件呼叫 s_ctrl。實際上,這會將硬體初始化為預設控制元件值。建議這樣做,因為這可以確保內部資料結構和硬體都同步。

  1. 最後:實現 v4l2_ctrl_ops

static const struct v4l2_ctrl_ops foo_ctrl_ops = {
        .s_ctrl = foo_s_ctrl,
};

通常您只需要 s_ctrl

static int foo_s_ctrl(struct v4l2_ctrl *ctrl)
{
        struct foo *state = container_of(ctrl->handler, struct foo, ctrl_handler);

        switch (ctrl->id) {
        case V4L2_CID_BRIGHTNESS:
                write_reg(0x123, ctrl->val);
                break;
        case V4L2_CID_CONTRAST:
                write_reg(0x456, ctrl->val);
                break;
        }
        return 0;
}

呼叫控制元件操作時,v4l2_ctrl 指標作為引數。新的控制元件值已經過驗證,因此您需要做的就是實際更新硬體暫存器。

你完成了!這對於我們擁有的大多數驅動程式來說已經足夠了。無需驗證控制元件值,或實現 QUERYCTRL、QUERY_EXT_CTRL 和 QUERYMENU。並且自動支援 G/S_CTRL 以及 G/TRY/S_EXT_CTRLS。

注意

其餘部分處理更高階的控制元件主題和場景。實際上,上述基本用法對於大多數驅動程式來說已經足夠了。

2.15.4. 繼承子裝置控制元件

當透過呼叫 v4l2_device_register_subdev() 向 V4L2 驅動程式註冊子裝置,並且設定了 v4l2_subdev 和 v4l2_device 的 ctrl_handler 欄位時,子裝置的控制元件也會自動在 V4L2 驅動程式中可用。如果子裝置驅動程式包含 V4L2 驅動程式中已存在的控制元件,則會跳過這些控制元件(因此 V4L2 驅動程式始終可以覆蓋子裝置控制元件)。

這裡發生的是 v4l2_device_register_subdev() 呼叫 v4l2_ctrl_add_handler(),將子裝置的控制元件新增到 v4l2_device 的控制元件中。

2.15.5. 訪問控制元件值

以下聯合在控制框架內部用於訪問控制元件值

union v4l2_ctrl_ptr {
        s32 *p_s32;
        s64 *p_s64;
        char *p_char;
        void *p;
};

v4l2_ctrl 結構包含以下欄位,可用於訪問當前值和新值

s32 val;
struct {
        s32 val;
} cur;


union v4l2_ctrl_ptr p_new;
union v4l2_ctrl_ptr p_cur;

如果控制元件具有簡單的 s32 型別,則

&ctrl->val == ctrl->p_new.p_s32
&ctrl->cur.val == ctrl->p_cur.p_s32

對於所有其他型別,請使用 ctrl->p_cur.p<something>。基本上,val 和 cur.val 欄位可以被視為別名,因為它們經常被使用。

在控制元件操作中,您可以自由使用這些。val 和 cur.val 不言自明。p_char 指標指向長度為 ctrl->maximum + 1 的字元緩衝區,並且始終以 0 結尾。

除非控制元件被標記為 volatile,否則 p_cur 欄位指向當前快取的控制元件值。當您建立新控制元件時,此值與預設值相同。呼叫 v4l2_ctrl_handler_setup() 後,此值將傳遞到硬體。通常,呼叫此函式是一個好主意。

每當設定新值時,該新值都會自動快取。這意味著大多數驅動程式不需要實現 g_volatile_ctrl() 操作。例外情況是對於返回易失性暫存器的控制元件,例如訊號強度讀數,該讀數會持續變化。在這種情況下,您將需要像這樣實現 g_volatile_ctrl

static int foo_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
{
        switch (ctrl->id) {
        case V4L2_CID_BRIGHTNESS:
                ctrl->val = read_reg(0x123);
                break;
        }
}

請注意,您也在 g_volatile_ctrl 中使用“新值”聯合。通常,需要實現 g_volatile_ctrl 的控制元件是隻讀控制元件。如果它們不是,則當控制元件更改時,不會生成 V4L2_EVENT_CTRL_CH_VALUE。

要將控制元件標記為 volatile,您必須設定 V4L2_CTRL_FLAG_VOLATILE

ctrl = v4l2_ctrl_new_std(&sd->ctrl_handler, ...);
if (ctrl)
        ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;

對於 try/s_ctrl,將填充新值(即使用者傳遞的值),您可以在 try_ctrl 中修改它們或在 s_ctrl 中設定它們。“cur”聯合包含當前值,您也可以使用它(但不能更改!)。

如果 s_ctrl 返回 0 (OK),則控制框架會將新的最終值複製到“cur”聯合中。

在 g_volatile/s/try_ctrl 中,您可以訪問同一處理程式擁有的所有控制元件的值,因為持有處理程式的鎖。如果您需要訪問其他處理程式擁有的控制元件的值,則必須非常小心,不要引入死鎖。

在控制元件操作之外,您必須透過輔助函式來安全地獲取或設定驅動程式中的單個控制元件值

s32 v4l2_ctrl_g_ctrl(struct v4l2_ctrl *ctrl);
int v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val);

這些函式像 VIDIOC_G/S_CTRL ioctl 一樣透過控制框架。但是,不要在控制元件操作 g_volatile/s/try_ctrl 中使用它們,因為這將導致死鎖,因為這些輔助函式也會鎖定處理程式。

您也可以自己獲取處理程式鎖

mutex_lock(&state->ctrl_handler.lock);
pr_info("String value is '%s'\n", ctrl1->p_cur.p_char);
pr_info("Integer value is '%s'\n", ctrl2->cur.val);
mutex_unlock(&state->ctrl_handler.lock);

2.15.7. 自定義控制元件

可以使用 v4l2_ctrl_new_custom() 建立特定於驅動程式的控制元件

static const struct v4l2_ctrl_config ctrl_filter = {
        .ops = &ctrl_custom_ops,
        .id = V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER,
        .name = "Spatial Filter",
        .type = V4L2_CTRL_TYPE_INTEGER,
        .flags = V4L2_CTRL_FLAG_SLIDER,
        .max = 15,
        .step = 1,
};

ctrl = v4l2_ctrl_new_custom(&foo->ctrl_handler, &ctrl_filter, NULL);

最後一個引數是 priv 指標,可以設定為特定於驅動程式的私有資料。

v4l2_ctrl_config 結構還有一個用於設定 is_private 標誌的欄位。

如果未設定 name 欄位,則框架將假定這是一個標準控制元件,並將相應地填充 name、type 和 flags 欄位。

2.15.8. 活動和抓取的控制元件

如果控制元件之間存在更復雜的關係,則可能需要啟用和停用控制元件。例如,如果 Chroma AGC 控制元件已開啟,則 Chroma Gain 控制元件處於非活動狀態。也就是說,您可以設定它,但只要自動增益控制處於開啟狀態,硬體就不會使用該值。通常,使用者介面可以停用此類輸入欄位。

您可以使用 v4l2_ctrl_activate() 設定“active”狀態。預設情況下,所有控制元件都是活動的。請注意,框架不檢查此標誌。它純粹是為了 GUI。該函式通常從 s_ctrl 中呼叫。

另一個標誌是“grabbed”標誌。抓取的控制元件意味著您無法更改它,因為它正在被某些資源使用。典型的例子是 MPEG 位元率控制元件,在捕獲正在進行時無法更改。

如果使用 v4l2_ctrl_grab() 將控制元件設定為“grabbed”,則如果嘗試設定此控制元件,框架將返回 -EBUSY。v4l2_ctrl_grab() 函式通常在驅動程式啟動或停止流式傳輸時呼叫。

2.15.9. 控制元件叢集

預設情況下,所有控制元件都與其他控制元件無關。但在更復雜的場景中,您可以獲得從一個控制元件到另一個控制元件的依賴關係。在這種情況下,您需要“叢集”它們

struct foo {
        struct v4l2_ctrl_handler ctrl_handler;
#define AUDIO_CL_VOLUME (0)
#define AUDIO_CL_MUTE   (1)
        struct v4l2_ctrl *audio_cluster[2];
        ...
};

state->audio_cluster[AUDIO_CL_VOLUME] =
        v4l2_ctrl_new_std(&state->ctrl_handler, ...);
state->audio_cluster[AUDIO_CL_MUTE] =
        v4l2_ctrl_new_std(&state->ctrl_handler, ...);
v4l2_ctrl_cluster(ARRAY_SIZE(state->audio_cluster), state->audio_cluster);

從現在開始,只要設定(或“獲取”或“嘗試”)屬於同一叢集的一個或多個控制元件,只會呼叫第一個控制元件(在本例中為“volume”)的控制元件操作。您有效地建立了一個新的複合控制元件。類似於 C 中“struct”的工作方式。

因此,當使用 V4L2_CID_AUDIO_VOLUME 作為引數呼叫 s_ctrl 時,您應該設定屬於 audio_cluster 的所有兩個控制元件

static int foo_s_ctrl(struct v4l2_ctrl *ctrl)
{
        struct foo *state = container_of(ctrl->handler, struct foo, ctrl_handler);

        switch (ctrl->id) {
        case V4L2_CID_AUDIO_VOLUME: {
                struct v4l2_ctrl *mute = ctrl->cluster[AUDIO_CL_MUTE];

                write_reg(0x123, mute->val ? 0 : ctrl->val);
                break;
        }
        case V4L2_CID_CONTRAST:
                write_reg(0x456, ctrl->val);
                break;
        }
        return 0;
}

在上面的示例中,對於 VOLUME 的情況,以下內容是等效的

ctrl == ctrl->cluster[AUDIO_CL_VOLUME] == state->audio_cluster[AUDIO_CL_VOLUME]
ctrl->cluster[AUDIO_CL_MUTE] == state->audio_cluster[AUDIO_CL_MUTE]

實際上,像這樣使用叢集陣列會變得非常麻煩。因此,改為使用以下等效方法

struct {
        /* audio cluster */
        struct v4l2_ctrl *volume;
        struct v4l2_ctrl *mute;
};

匿名結構用於清楚地“叢集”這兩個控制元件指標,但它沒有其他用途。效果與建立具有兩個控制元件指標的陣列相同。因此,您可以只做

state->volume = v4l2_ctrl_new_std(&state->ctrl_handler, ...);
state->mute = v4l2_ctrl_new_std(&state->ctrl_handler, ...);
v4l2_ctrl_cluster(2, &state->volume);

在 foo_s_ctrl 中,您可以直接使用這些指標:state->mute->val。

請注意,叢集中的控制元件可能為 NULL。例如,如果由於某種原因從未新增靜音(因為硬體不支援該特定功能),則靜音將為 NULL。因此,在這種情況下,我們有一個包含 2 個控制元件的叢集,其中實際上只例項化了 1 個控制元件。唯一的限制是叢集的第一個控制元件必須始終存在,因為它是叢集的“主”控制元件。主控制元件是識別叢集並提供指向用於該叢集的 v4l2_ctrl_ops 結構的指標的控制元件。

顯然,叢集陣列中的所有控制元件都必須初始化為有效控制元件或 NULL。

在極少數情況下,您可能想知道叢集的哪些控制元件實際上是由使用者顯式設定的。為此,您可以檢查每個控制元件的“is_new”標誌。例如,在音量/靜音叢集的情況下,如果使用者僅為靜音呼叫 VIDIOC_S_CTRL,則會設定靜音控制元件的“is_new”標誌。如果使用者為靜音和音量控制元件呼叫 VIDIOC_S_EXT_CTRLS,則兩個控制元件的“is_new”標誌都將為 1。

v4l2_ctrl_handler_setup() 呼叫時,“is_new”標誌始終為 1。

2.15.10. 使用自動叢集處理自動增益/增益型別控制元件

一種常見的控制元件叢集型別是處理“auto-foo/foo”型別的控制元件。典型的例子是自動增益/增益、自動曝光/曝光、自動白平衡/紅色平衡/藍色平衡。在所有情況下,您都有一個控制元件,用於確定另一個控制元件是由硬體自動處理,還是在使用者的手動控制下。

如果叢集處於自動模式,則應將手動控制元件標記為非活動和易失性。讀取易失性控制元件時,g_volatile_ctrl 操作應返回硬體的自動模式自動設定的值。

如果叢集設定為手動模式,則手動控制元件應再次變為活動狀態,並且清除易失性標誌(因此在手動模式下不再呼叫 g_volatile_ctrl)。此外,在切換到手動模式之前,會將自動模式確定的當前值複製為新的手動值。

最後,應為自動控制元件設定 V4L2_CTRL_FLAG_UPDATE,因為更改該控制元件會影響手動控制元件的控制元件標誌。

為了簡化此操作,引入了 v4l2_ctrl_cluster 的特殊變體

void v4l2_ctrl_auto_cluster(unsigned ncontrols, struct v4l2_ctrl **controls,
                            u8 manual_val, bool set_volatile);

前兩個引數與 v4l2_ctrl_cluster 相同。第三個引數告訴框架哪個值將叢集切換到手動模式。最後一個引數將可選地為非自動控制元件設定 V4L2_CTRL_FLAG_VOLATILE。如果為 false,則手動控制元件永遠不會易失性。如果硬體不為您提供讀回自動模式確定的值的選項,您通常會使用它(例如,如果自動增益開啟,則硬體不允許您獲取當前增益值)。

假定叢集的第一個控制元件是“自動”控制元件。

使用此函式將確保您無需處理所有複雜的標誌和 volatile 處理。

2.15.11. VIDIOC_LOG_STATUS 支援

此ioctl允許您將驅動程式的當前狀態轉儲到核心日誌中。 v4l2_ctrl_handler_log_status(ctrl_handler, prefix) 可用於將給定處理程式擁有的控制元件的值轉儲到日誌中。您也可以提供字首。如果字首未以空格結尾,則將為您新增“: ”。

2.15.12. 不同影片節點的不同的處理程式

通常,V4L2驅動程式只有一個控制處理程式,該處理程式對於所有影片節點都是全域性的。但是您也可以為不同的影片節點指定不同的控制處理程式。您可以透過手動設定 struct video_device 的 ctrl_handler 欄位來實現。

如果沒有涉及子裝置,則沒有問題,但是如果存在子裝置,則需要阻止子裝置控制元件自動合併到全域性控制處理程式。您只需將 struct v4l2_device 中的 ctrl_handler 欄位設定為 NULL 來實現這一點。現在 v4l2_device_register_subdev() 將不再合併子裝置控制元件。

新增每個子裝置後,您將必須手動呼叫 v4l2_ctrl_add_handler 以將子裝置的控制處理程式 (sd->ctrl_handler) 新增到所需的控制處理程式。此控制處理程式可能特定於 video_device 或 video_device 的子集。例如:無線電裝置節點只有音訊控制元件,而影片和 vbi 裝置節點共享音訊和影片控制元件的相同控制處理程式。

如果您希望一個處理程式(例如,用於無線電裝置節點)具有另一個處理程式的子集(例如,用於影片裝置節點),則應首先將控制元件新增到第一個處理程式,將其他控制元件新增到第二個處理程式,最後將第一個處理程式新增到第二個。例如

v4l2_ctrl_new_std(&radio_ctrl_handler, &radio_ops, V4L2_CID_AUDIO_VOLUME, ...);
v4l2_ctrl_new_std(&radio_ctrl_handler, &radio_ops, V4L2_CID_AUDIO_MUTE, ...);
v4l2_ctrl_new_std(&video_ctrl_handler, &video_ops, V4L2_CID_BRIGHTNESS, ...);
v4l2_ctrl_new_std(&video_ctrl_handler, &video_ops, V4L2_CID_CONTRAST, ...);
v4l2_ctrl_add_handler(&video_ctrl_handler, &radio_ctrl_handler, NULL);

v4l2_ctrl_add_handler() 的最後一個引數是一個篩選函式,允許您篩選要新增哪些控制元件。如果要新增所有控制元件,請將其設定為 NULL。

或者,您可以將特定控制元件新增到處理程式

volume = v4l2_ctrl_new_std(&video_ctrl_handler, &ops, V4L2_CID_AUDIO_VOLUME, ...);
v4l2_ctrl_new_std(&video_ctrl_handler, &ops, V4L2_CID_BRIGHTNESS, ...);
v4l2_ctrl_new_std(&video_ctrl_handler, &ops, V4L2_CID_CONTRAST, ...);

您不應該做的是為兩個處理程式製作兩個相同的控制元件。例如

v4l2_ctrl_new_std(&radio_ctrl_handler, &radio_ops, V4L2_CID_AUDIO_MUTE, ...);
v4l2_ctrl_new_std(&video_ctrl_handler, &video_ops, V4L2_CID_AUDIO_MUTE, ...);

這將是不好的,因為使無線電靜音不會更改影片靜音控制元件。規則是為您可以轉動的每個硬體“旋鈕”設定一個控制元件。

2.15.13. 查詢控制元件

通常,您自己建立了控制元件,並且可以將 struct v4l2_ctrl 指標儲存到您自己的結構中。

但是有時您需要從您不擁有的另一個處理程式中找到一個控制元件。例如,如果您必須從子裝置找到音量控制。

您可以透過呼叫 v4l2_ctrl_find 來實現這一點

struct v4l2_ctrl *volume;

volume = v4l2_ctrl_find(sd->ctrl_handler, V4L2_CID_AUDIO_VOLUME);

由於 v4l2_ctrl_find 會鎖定處理程式,因此您必須小心在哪裡使用它。例如,這不是一個好主意

struct v4l2_ctrl_handler ctrl_handler;

v4l2_ctrl_new_std(&ctrl_handler, &video_ops, V4L2_CID_BRIGHTNESS, ...);
v4l2_ctrl_new_std(&ctrl_handler, &video_ops, V4L2_CID_CONTRAST, ...);

...以及在 video_ops.s_ctrl 中

case V4L2_CID_BRIGHTNESS:
        contrast = v4l2_find_ctrl(&ctrl_handler, V4L2_CID_CONTRAST);
        ...

當框架呼叫 s_ctrl 時,ctrl_handler.lock 已經被佔用,因此嘗試從同一處理程式中找到另一個控制元件將導致死鎖。

建議不要從控制元件操作內部使用此函式。

2.15.14. 防止控制元件繼承

當使用 v4l2_ctrl_add_handler 將一個控制處理程式新增到另一個時,預設情況下,一個處理程式中的所有控制元件都會合併到另一個。但是,子裝置可能具有對於某些高階嵌入式系統有意義的低階控制元件,但在消費級硬體中使用時沒有意義。在這種情況下,您希望將這些低階控制元件保留在子裝置本地。您可以透過簡單地將控制元件的“is_private”標誌設定為 1 來實現這一點

static const struct v4l2_ctrl_config ctrl_private = {
        .ops = &ctrl_custom_ops,
        .id = V4L2_CID_...,
        .name = "Some Private Control",
        .type = V4L2_CTRL_TYPE_INTEGER,
        .max = 15,
        .step = 1,
        .is_private = 1,
};

ctrl = v4l2_ctrl_new_custom(&foo->ctrl_handler, &ctrl_private, NULL);

現在,當呼叫 v4l2_ctrl_add_handler 時,將跳過這些控制元件。

2.15.15. V4L2_CTRL_TYPE_CTRL_CLASS 控制元件

GUI 可以使用此型別的控制元件來獲取控制元件類的名稱。功能齊全的 GUI 可以建立一個帶有多個選項卡的對話方塊,每個選項卡包含屬於特定控制元件類的控制元件。可以透過查詢 ID 為 <control class | 1> 的特殊控制元件來找到每個選項卡的名稱。

驅動程式不必關心這一點。每當新增屬於新控制元件類的第一個控制元件時,框架將自動新增此型別的控制元件。

2.15.16. 新增通知回撥

有時,當子裝置驅動程式中的控制元件發生更改時,平臺或橋接驅動程式需要收到通知。您可以透過呼叫此函式來設定通知回撥

void v4l2_ctrl_notify(struct v4l2_ctrl *ctrl,
        void (*notify)(struct v4l2_ctrl *ctrl, void *priv), void *priv);

每當給定的控制元件更改值時,將呼叫通知回撥,其中包含指向控制元件的指標和與 v4l2_ctrl_notify 一起傳遞的 priv 指標。請注意,呼叫通知函式時會保持控制元件的處理程式鎖。

每個控制處理程式只能有一個通知函式。任何嘗試設定另一個通知函式的嘗試都會導致 WARN_ON。

2.15.17. v4l2_ctrl 函式和資料結構

union v4l2_ctrl_ptr

指向控制元件值的指標。

定義:

union v4l2_ctrl_ptr {
    s32 *p_s32;
    s64 *p_s64;
    u8 *p_u8;
    u16 *p_u16;
    u32 *p_u32;
    char *p_char;
    struct v4l2_ctrl_mpeg2_sequence *p_mpeg2_sequence;
    struct v4l2_ctrl_mpeg2_picture *p_mpeg2_picture;
    struct v4l2_ctrl_mpeg2_quantisation *p_mpeg2_quantisation;
    struct v4l2_ctrl_fwht_params *p_fwht_params;
    struct v4l2_ctrl_h264_sps *p_h264_sps;
    struct v4l2_ctrl_h264_pps *p_h264_pps;
    struct v4l2_ctrl_h264_scaling_matrix *p_h264_scaling_matrix;
    struct v4l2_ctrl_h264_slice_params *p_h264_slice_params;
    struct v4l2_ctrl_h264_decode_params *p_h264_decode_params;
    struct v4l2_ctrl_h264_pred_weights *p_h264_pred_weights;
    struct v4l2_ctrl_vp8_frame *p_vp8_frame;
    struct v4l2_ctrl_hevc_sps *p_hevc_sps;
    struct v4l2_ctrl_hevc_pps *p_hevc_pps;
    struct v4l2_ctrl_hevc_slice_params *p_hevc_slice_params;
    struct v4l2_ctrl_vp9_compressed_hdr *p_vp9_compressed_hdr_probs;
    struct v4l2_ctrl_vp9_frame *p_vp9_frame;
    struct v4l2_ctrl_hdr10_cll_info *p_hdr10_cll;
    struct v4l2_ctrl_hdr10_mastering_display *p_hdr10_mastering;
    struct v4l2_area *p_area;
    struct v4l2_ctrl_av1_sequence *p_av1_sequence;
    struct v4l2_ctrl_av1_tile_group_entry *p_av1_tile_group_entry;
    struct v4l2_ctrl_av1_frame *p_av1_frame;
    struct v4l2_ctrl_av1_film_grain *p_av1_film_grain;
    struct v4l2_rect *p_rect;
    void *p;
    const void *p_const;
};

成員

p_s32

指向 32 位有符號值的指標。

p_s64

指向 64 位有符號值的指標。

p_u8

指向 8 位無符號值的指標。

p_u16

指向 16 位無符號值的指標。

p_u32

指向 32 位無符號值的指標。

p_char

指向字串的指標。

p_mpeg2_sequence

指向 MPEG2 序列結構的指標。

p_mpeg2_picture

指向 MPEG2 圖片結構的指標。

p_mpeg2_quantisation

指向 MPEG2 量化資料結構的指標。

p_fwht_params

指向 FWHT 無狀態引數結構的指標。

p_h264_sps

指向 struct v4l2_ctrl_h264_sps 的指標。

p_h264_pps

指向 struct v4l2_ctrl_h264_pps 的指標。

p_h264_scaling_matrix

指向 struct v4l2_ctrl_h264_scaling_matrix 的指標。

p_h264_slice_params

指向 struct v4l2_ctrl_h264_slice_params 的指標。

p_h264_decode_params

指向 struct v4l2_ctrl_h264_decode_params 的指標。

p_h264_pred_weights

指向 struct v4l2_ctrl_h264_pred_weights 的指標。

p_vp8_frame

指向 VP8 幀引數結構的指標。

p_hevc_sps

指向 HEVC 序列引數集結構的指標。

p_hevc_pps

指向 HEVC 圖片引數集結構的指標。

p_hevc_slice_params

指向 HEVC 切片引數結構的指標。

p_vp9_compressed_hdr_probs

指向 VP9 幀壓縮標頭機率結構的指標。

p_vp9_frame

指向 VP9 幀引數結構的指標。

p_hdr10_cll

指向 HDR10 內容亮度級別結構的指標。

p_hdr10_mastering

指向 HDR10 母版顯示結構的指標。

p_area

指向區域的指標。

p_av1_sequence

指向 AV1 序列結構的指標。

p_av1_tile_group_entry

指向 AV1 圖塊組條目結構的指標。

p_av1_frame

指向 AV1 幀結構的指標。

p_av1_film_grain

指向 AV1 膠片顆粒結構的指標。

p_rect

指向矩形的指標。

p

指向複合值的指標。

p_const

指向常量複合值的指標。

union v4l2_ctrl_ptr v4l2_ctrl_ptr_create(void *ptr)

從 void 指標返回 v4l2_ctrl_ptr 的幫助函式

引數

void *ptr

void 指標

struct v4l2_ctrl_ops

驅動程式必須提供的控制元件操作。

定義:

struct v4l2_ctrl_ops {
    int (*g_volatile_ctrl)(struct v4l2_ctrl *ctrl);
    int (*try_ctrl)(struct v4l2_ctrl *ctrl);
    int (*s_ctrl)(struct v4l2_ctrl *ctrl);
};

成員

g_volatile_ctrl

獲取此控制元件的新值。通常僅與 volatile(並且通常是隻讀的)控制元件相關,例如返回當前訊號強度的控制元件,該控制元件會不斷變化。如果未設定,則將返回當前快取的值。

try_ctrl

測試控制元件的值是否有效。僅當通常的 min/max/step 檢查不足時才相關。

s_ctrl

實際設定新的控制元件值。s_ctrl 是強制性的。呼叫這些操作時,ctrl->handler->lock 處於保持狀態,因此沒有其他人可以訪問該處理程式擁有的控制元件。

struct v4l2_ctrl_type_ops

驅動程式必須提供的控制元件型別操作。

定義:

struct v4l2_ctrl_type_ops {
    bool (*equal)(const struct v4l2_ctrl *ctrl, union v4l2_ctrl_ptr ptr1, union v4l2_ctrl_ptr ptr2);
    void (*init)(const struct v4l2_ctrl *ctrl, u32 from_idx, union v4l2_ctrl_ptr ptr);
    void (*minimum)(const struct v4l2_ctrl *ctrl, u32 idx, union v4l2_ctrl_ptr ptr);
    void (*maximum)(const struct v4l2_ctrl *ctrl, u32 idx, union v4l2_ctrl_ptr ptr);
    void (*log)(const struct v4l2_ctrl *ctrl);
    int (*validate)(const struct v4l2_ctrl *ctrl, union v4l2_ctrl_ptr ptr);
};

成員

equal

如果所有 ctrl->elems 陣列元素都相等,則返回 true。

init

從 from_idx 初始化陣列元素的值到 ctrl->elems。

minimum

將值設定為控制元件的最小值。

maximum

將值設定為控制元件的最大值。

log

記錄該值。

validate

驗證 ctrl->new_elems 陣列元素的值。成功時返回 0,否則返回負值。

v4l2_ctrl_notify_fnc

Typedef:用於帶有當控制元件值發生更改時應呼叫的函式的通知引數的 typedef。

語法

void v4l2_ctrl_notify_fnc (struct v4l2_ctrl *ctrl, void *priv)

引數

struct v4l2_ctrl *ctrl

指向 struct v4l2_ctrl 的指標

void *priv

控制元件私有資料

說明

此 typedef 定義用作 v4l2_ctrl_notify() 的引數,並作為 struct v4l2_ctrl_handler 的引數。

struct v4l2_ctrl

控制元件結構。

定義:

struct v4l2_ctrl {
    struct list_head node;
    struct list_head ev_subs;
    struct v4l2_ctrl_handler *handler;
    struct v4l2_ctrl **cluster;
    unsigned int ncontrols;
    unsigned int done:1;
    unsigned int is_new:1;
    unsigned int has_changed:1;
    unsigned int is_private:1;
    unsigned int is_auto:1;
    unsigned int is_int:1;
    unsigned int is_string:1;
    unsigned int is_ptr:1;
    unsigned int is_array:1;
    unsigned int is_dyn_array:1;
    unsigned int has_volatiles:1;
    unsigned int call_notify:1;
    unsigned int manual_mode_value:8;
    const struct v4l2_ctrl_ops *ops;
    const struct v4l2_ctrl_type_ops *type_ops;
    u32 id;
    const char *name;
    enum v4l2_ctrl_type type;
    s64 minimum, maximum, default_value;
    u32 elems;
    u32 elem_size;
    u32 new_elems;
    u32 dims[V4L2_CTRL_MAX_DIMS];
    u32 nr_of_dims;
    union {
        u64 step;
        u64 menu_skip_mask;
    };
    union {
        const char * const *qmenu;
        const s64 *qmenu_int;
    };
    unsigned long flags;
    void *priv;
    void *p_array;
    u32 p_array_alloc_elems;
    s32 val;
    struct {
        s32 val;
    } cur;
    union v4l2_ctrl_ptr p_def;
    union v4l2_ctrl_ptr p_min;
    union v4l2_ctrl_ptr p_max;
    union v4l2_ctrl_ptr p_new;
    union v4l2_ctrl_ptr p_cur;
};

成員

node

列表節點。

ev_subs

控制元件事件訂閱列表。

handler

擁有該控制元件的處理程式。

cluster

指向群集陣列的開頭。

ncontrols

群集陣列中的控制元件數量。

done

內部標誌:為每個已處理的控制元件設定。

is_new

當用戶為此控制元件指定新值時設定。從 v4l2_ctrl_handler_setup() 呼叫時也會設定。驅動程式不應設定此標誌。

has_changed

噹噹前值與新值不同時設定。驅動程式不應使用此標誌。

is_private

如果設定,則此控制元件對其處理程式是私有的,並且不會新增到任何其他處理程式。驅動程式可以設定此標誌。

is_auto

如果設定,則此控制元件選擇其他群整合員是處於“自動”模式還是“手動”模式。這用於自動增益/增益型別群集。驅動程式不應直接設定此標誌。

is_int

如果設定,則此控制元件具有簡單的整數值(即,它使用 ctrl->val)。

is_string

如果設定,則此控制元件的型別為 V4L2_CTRL_TYPE_STRING

is_ptr

如果設定,則此控制元件是一個數組和/或型別 >= V4L2_CTRL_COMPOUND_TYPES 和/或型別 V4L2_CTRL_TYPE_STRING。換句話說,struct v4l2_ext_control 使用欄位 p 來指向資料。

is_array

如果設定,則此控制元件包含 N 維陣列。

is_dyn_array

如果設定,則此控制元件包含動態大小的 1 維陣列。如果設定了此項,則也會設定 is_array

has_volatiles

如果設定,則群集的一個或多個成員是 volatile 的。驅動程式不應觸控此標誌。

call_notify

如果設定,則每當控制元件的值更改時,呼叫處理程式的通知函式。

manual_mode_value

如果設定了 is_auto 標誌,則這是 auto 控制元件的值,用於確定該控制元件是否處於手動模式。因此,如果 auto 控制元件的值等於此值,則整個群集都處於手動模式。驅動程式不應直接設定此標誌。

ops

控制元件操作。

type_ops

控制元件型別操作。

id

控制元件 ID。

name

控制元件名稱。

type

控制元件型別。

minimum

控制元件的最小值。

maximum

控制元件的最大值。

default_value

控制元件的預設值。

elems

N 維陣列中的元素數。

elem_size

控制元件的大小(以位元組為單位)。

new_elems

p_new 中的元素數。除了動態陣列之外,這與 elems 相同。在動態陣列中,它在 1 到 p_array_alloc_elems 的範圍內。

dims

每個維度的大小。

nr_of_dims

dims 中的維度數。

{unnamed_union}

anonymous

step

非選單控制元件的控制元件步長值。

menu_skip_mask

選單控制元件的控制元件跳過掩碼。這使得跳過無效的選單項變得容易。如果設定了位 X,則跳過選單項 X。當然,這僅適用於 <= 32 個選單項的選單。沒有選單接近該數字,因此這沒問題。如果我們需要更多,則必須將其擴充套件到 u64 或位陣列。

{unnamed_union}

anonymous

qmenu

所有選單項的 const char * 陣列。空字串 (“”) 的陣列條目對應於不存在的選單項(這是對上述 menu_skip_mask 的補充)。最後一個條目必須為 NULL。僅當 typeV4L2_CTRL_TYPE_MENU 時使用。

qmenu_int

帶有整數選單項的 64 位整數陣列。陣列的大小必須等於選單大小,例如: ceil(\frac{maximum - minimum}{step}) + 1。僅當 typeV4L2_CTRL_TYPE_INTEGER_MENU 時使用。

flags

控制元件的標誌。

priv

控制元件的私有指標。供驅動程式使用。控制元件框架不會觸及它。請注意,刪除控制元件時不會釋放此指標。如果需要這樣做,則可以新增一個新的內部位欄位來告訴框架釋放此指標。

p_array

指向已分配陣列的指標。僅當 is_array 為 true 時才有效。

p_array_alloc_elems

當前值和新值的已分配陣列中的元素數。因此,p_array 實際上針對 2 * p_array_alloc_elems * elem_size 進行了大小調整。僅當 is_array 為 true 時才有效。

val

控制元件的新 s32 值。

cur

用於儲存當前值的結構。

cur.val

控制元件的當前值,如果 type 透過 u32 整數表示(請參閱 enum v4l2_ctrl_type)。

p_def

控制元件的預設值透過聯合表示,該聯合提供了透過指標訪問控制元件型別的標準方法(僅適用於複合控制元件)。

p_min

控制元件的最小值透過聯合表示,該聯合提供了透過指標訪問控制元件型別的標準方法(僅適用於複合控制元件)。

p_max

控制元件的最大值透過聯合表示,該聯合提供了透過指標訪問控制元件型別的標準方法(僅適用於複合控制元件)。

p_new

控制元件的新值透過聯合表示,該聯合提供了透過指標訪問控制元件型別的標準方法。

p_cur

控制元件的當前值透過聯合表示,該聯合提供了透過指標訪問控制元件型別的標準方法。

struct v4l2_ctrl_ref

控制元件引用。

定義:

struct v4l2_ctrl_ref {
    struct list_head node;
    struct v4l2_ctrl_ref *next;
    struct v4l2_ctrl *ctrl;
    struct v4l2_ctrl_helper *helper;
    bool from_other_dev;
    bool req_done;
    bool p_req_valid;
    bool p_req_array_enomem;
    u32 p_req_array_alloc_elems;
    u32 p_req_elems;
    union v4l2_ctrl_ptr p_req;
};

成員

node

排序列表的列表節點。

next

雜湊的單鏈接列表節點。

ctrl

實際的控制元件資訊。

helper

指向輔助結構的指標。在 v4l2-ctrl.cprepare_ext_ctrls 函式中內部使用。

from_other_dev

如果為真,則表示 ctrl 是在struct v4l2_ctrl_handler之外的另一個裝置中定義的。

req_done

內部標誌:如果包含此控制元件引用的控制元件處理程式繫結到媒體請求,則在應用該控制元件時設定此標誌。這可以防止從具有多個控制元件的叢集中應用控制元件兩次(當應用叢集的第一個控制元件時,它們都會被應用)。

p_req_valid

如果設定,則 p_req 包含請求的控制元件值。

p_req_array_enomem

如果設定,則 p_req 無效,因為分配陣列空間失敗。嘗試讀取此值將導致 ENOMEM。僅當 ctrl->is_array 為 true 時有效。

p_req_array_alloc_elems

為陣列分配的元素數量。僅當 p_req_valid 和 ctrl->is_array 為 true 時有效。

p_req_elems

p_req 中的元素數量。 這與 ctrl->elems 相同,除了動態陣列。 在這種情況下,它在 1 到 p_req_array_alloc_elems 的範圍內。 僅當 p_req_valid 為 true 時有效。

p_req

如果包含此控制元件引用的控制元件處理程式繫結到媒體請求,則此指標指向在執行請求時必須應用的控制元件的值,或者指向請求完成時的控制元件的值。 如果 p_req_valid 為 false,則表示從未為此請求設定過此控制元件,並且在此請求應用時控制元件不會更新。

說明

每個控制元件處理程式都有一個這些引用的列表。 list_head 用於儲存按控制元件 ID 排序的所有控制元件的列表,而 next 指標用於將控制元件連結到雜湊桶中。

struct v4l2_ctrl_handler

控制元件處理程式跟蹤所有控制元件:包括處理程式擁有的控制元件和從其他處理程式繼承的控制元件。

定義:

struct v4l2_ctrl_handler {
    struct mutex _lock;
    struct mutex *lock;
    struct list_head ctrls;
    struct list_head ctrl_refs;
    struct v4l2_ctrl_ref *cached;
    struct v4l2_ctrl_ref **buckets;
    v4l2_ctrl_notify_fnc notify;
    void *notify_priv;
    u16 nr_of_buckets;
    int error;
    bool request_is_queued;
    struct list_head requests;
    struct list_head requests_queued;
    struct media_request_object req_obj;
};

成員

_lock

“lock” 的預設值。

lock

用於控制對此處理程式及其控制元件的訪問的鎖。 可能在初始化後立即被使用者替換。

ctrls

此處理程式擁有的控制元件列表。

ctrl_refs

控制元件引用列表。

cached

上次找到的控制元件引用。 通常需要多次使用相同的控制元件,因此這是一個簡單的最佳化。

buckets

用於雜湊的桶。 允許快速查詢控制元件。

notify

每當控制元件值更改時呼叫的通知回撥。 請注意,呼叫通知函式時,將持有處理程式的鎖!

notify_priv

作為引數傳遞給 v4l2_ctrl 通知回撥。

nr_of_buckets

陣列中的桶總數。

error

第一次控制元件新增失敗的錯誤程式碼。

request_is_queued

如果請求已排隊,則為 True。

requests

用於跟蹤開啟的控制元件處理程式請求物件的列表。 對於父控制元件處理程式 (req_obj.ops == NULL),這是列表頭。 刪除父控制元件處理程式時,必須取消繫結並放置所有這些請求,因為它們引用了父控制元件處理程式。

requests_queued

已排隊請求的列表。 這決定了應用這些控制元件的順序。 請求完成後,將從該列表中刪除。

req_obj

struct media_request_object,用於連結到 struct media_request。 此請求物件具有引用計數。

struct v4l2_ctrl_config

控制元件配置結構。

定義:

struct v4l2_ctrl_config {
    const struct v4l2_ctrl_ops *ops;
    const struct v4l2_ctrl_type_ops *type_ops;
    u32 id;
    const char *name;
    enum v4l2_ctrl_type type;
    s64 min;
    s64 max;
    u64 step;
    s64 def;
    union v4l2_ctrl_ptr p_def;
    union v4l2_ctrl_ptr p_min;
    union v4l2_ctrl_ptr p_max;
    u32 dims[V4L2_CTRL_MAX_DIMS];
    u32 elem_size;
    u32 flags;
    u64 menu_skip_mask;
    const char * const *qmenu;
    const s64 *qmenu_int;
    unsigned int is_private:1;
};

成員

ops

控制元件操作。

type_ops

控制元件型別 ops。 僅複合控制元件需要。

id

控制元件 ID。

name

控制元件名稱。

type

控制元件型別。

min

控制元件的最小值。

max

控制元件的最大值。

step

非選單控制元件的控制元件步長值。

def

控制元件的預設值。

p_def

複合控制元件的控制元件預設值。

p_min

複合控制元件的控制元件最小值。

p_max

複合控制元件的控制元件最大值。

dims

每個維度的大小。

elem_size

控制元件的大小(以位元組為單位)。

flags

控制元件的標誌。

menu_skip_mask

選單控制元件的控制元件跳過掩碼。 這使得跳過無效的選單項變得容易。 如果設定了位 X,則跳過選單項 X。 當然,這僅適用於具有 <= 64 個選單項的選單。 沒有接近該數量的選單,所以這沒問題。 如果我們確實需要更多,那麼必須將其擴充套件到位陣列。

qmenu

所有選單項的 const char * 陣列。 空字串 (“”) 的陣列條目對應於不存在的選單項(這是對上面 menu_skip_mask 的補充)。 最後一個條目必須為 NULL。

qmenu_int

V4L2_CTRL_TYPE_INTEGER_MENU 型別的所有選單項的 const s64 整數陣列。

is_private

如果設定,則此控制元件是其處理程式私有的,並且不會新增到任何其他處理程式。

void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, s64 *min, s64 *max, u64 *step, s64 *def, u32 *flags)

根據控制元件 ID 填充控制元件欄位。

引數

u32 id

控制元件的 ID

const char **name

要用控制元件名稱的字串填充的指標

enum v4l2_ctrl_type *type

用於儲存控制元件型別的指標

s64 *min

用於儲存控制元件最小值的指標

s64 *max

用於儲存控制元件最大值的指標

u64 *step

用於儲存控制元件步長的指標

s64 *def

用於儲存控制元件預設值的指標

u32 *flags

用於儲存要在控制元件上使用的標誌的指標

說明

這適用於所有標準 V4L2 控制元件。 對於非標準控制元件,它只會填充給定的引數,並且 name 內容將設定為 NULL

此函式將覆蓋 nametypeflags 的內容。 minmaxstepdef 的內容可能會根據型別進行修改。

注意

不要在驅動程式中使用! 它僅在內部用於向後相容的控制元件處理。 一旦所有驅動程式都轉換為使用新的控制元件框架,該函式將不再匯出。

int v4l2_ctrl_handler_init_class(struct v4l2_ctrl_handler *hdl, unsigned int nr_of_controls_hint, struct lock_class_key *key, const char *name)

初始化控制元件處理程式。

引數

struct v4l2_ctrl_handler *hdl

控制元件處理程式。

unsigned int nr_of_controls_hint

提示此處理程式預計引用的控制元件數量。 這是總數,因此包括任何繼承的控制元件。 它不必精確,但如果它偏離太遠,那麼你要麼浪費記憶體(分配了太多的桶),要麼控制元件查詢變得更慢(分配的桶不夠,因此有更多的慢速列表查詢)。 不過,它總是會工作。

struct lock_class_key *key

如果設定了 CONFIG_LOCKDEP,則由鎖驗證器使用。

const char *name

如果設定了 CONFIG_LOCKDEP,則由鎖驗證器使用。

說明

注意

永遠不要直接使用此呼叫,始終使用隱藏 keyname 引數的 v4l2_ctrl_handler_init() 宏。

返回值

如果無法分配桶,則返回錯誤。 此錯誤也將儲存在 hdl->error 中。

v4l2_ctrl_handler_init

v4l2_ctrl_handler_init (hdl, nr_of_controls_hint)

輔助函式,用於建立靜態 struct lock_class_key 並呼叫 v4l2_ctrl_handler_init_class()

引數

hdl

控制元件處理程式。

nr_of_controls_hint

提示此處理程式預計引用的控制元件數量。 這是總數,因此包括任何繼承的控制元件。 它不必精確,但如果它偏離太遠,那麼你要麼浪費記憶體(分配了太多的桶),要麼控制元件查詢變得更慢(分配的桶不夠,因此有更多的慢速列表查詢)。 不過,它總是會工作。

說明

此輔助函式建立靜態 struct lock_class_key 並呼叫 v4l2_ctrl_handler_init_class(),為鎖驗證器提供適當的名稱。

使用此輔助函式來初始化控制元件處理程式。

void v4l2_ctrl_handler_free(struct v4l2_ctrl_handler *hdl)

釋放處理程式擁有的所有控制元件並釋放控制元件列表。

引數

struct v4l2_ctrl_handler *hdl

控制元件處理程式。

說明

如果 hdl == NULL,則不執行任何操作。

void v4l2_ctrl_lock(struct v4l2_ctrl *ctrl)

用於鎖定與控制元件關聯的處理程式的輔助函式。

引數

struct v4l2_ctrl *ctrl

要鎖定的控制元件。

void v4l2_ctrl_unlock(struct v4l2_ctrl *ctrl)

用於解鎖與控制元件關聯的處理程式的輔助函式。

引數

struct v4l2_ctrl *ctrl

要解鎖的控制元件。

int __v4l2_ctrl_handler_setup(struct v4l2_ctrl_handler *hdl)

為屬於處理程式的所有控制元件呼叫 s_ctrl op,以將硬體初始化為當前的控制元件值。 呼叫者負責代表 __v4l2_ctrl_handler_setup() 獲取控制元件處理程式互斥鎖。

引數

struct v4l2_ctrl_handler *hdl

控制元件處理程式。

說明

按鈕控制元件將被跳過,只讀控制元件也是如此。

如果 hdl == NULL,則這隻會返回 0。

int v4l2_ctrl_handler_setup(struct v4l2_ctrl_handler *hdl)

為屬於處理程式的所有控制元件呼叫 s_ctrl op,以將硬體初始化為當前的控制元件值。

引數

struct v4l2_ctrl_handler *hdl

控制元件處理程式。

說明

按鈕控制元件將被跳過,只讀控制元件也是如此。

如果 hdl == NULL,則這隻會返回 0。

void v4l2_ctrl_handler_log_status(struct v4l2_ctrl_handler *hdl, const char *prefix)

記錄處理程式擁有的所有控制元件。

引數

struct v4l2_ctrl_handler *hdl

控制元件處理程式。

const char *prefix

記錄控制元件值時要使用的字首。 如果字首不以空格結尾,則將在字首後新增“: ”。 如果 prefix == NULL,則不使用字首。

說明

與 VIDIOC_LOG_STATUS 一起使用。

如果 hdl == NULL,則不執行任何操作。

struct v4l2_ctrl *v4l2_ctrl_new_custom(struct v4l2_ctrl_handler *hdl, const struct v4l2_ctrl_config *cfg, void *priv)

分配並初始化新的自定義 V4L2 控制元件。

引數

struct v4l2_ctrl_handler *hdl

控制元件處理程式。

const struct v4l2_ctrl_config *cfg

控制元件的配置資料。

void *priv

控制元件的特定於驅動程式的私有資料。

說明

如果無法分配 v4l2_ctrl 結構,則返回 NULL,並將 hdl->error 設定為錯誤程式碼(如果尚未設定)。

struct v4l2_ctrl *v4l2_ctrl_new_std(struct v4l2_ctrl_handler *hdl, const struct v4l2_ctrl_ops *ops, u32 id, s64 min, s64 max, u64 step, s64 def)

分配並初始化新的標準 V4L2 非選單控制元件。

引數

struct v4l2_ctrl_handler *hdl

控制元件處理程式。

const struct v4l2_ctrl_ops *ops

控制元件操作。

u32 id

控制元件 ID。

s64 min

控制元件的最小值。

s64 max

控制元件的最大值。

u64 step

控制元件的步長值

s64 def

控制元件的預設值。

說明

如果無法分配 v4l2_ctrl 結構,或者控制元件 ID 未知,則返回 NULL,並將 hdl->error 設定為適當的錯誤程式碼(如果尚未設定)。

如果 id 引用選單控制元件,則此函式將返回 NULL。

新增選單控制元件時,請使用 v4l2_ctrl_new_std_menu()

struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl, const struct v4l2_ctrl_ops *ops, u32 id, u8 max, u64 mask, u8 def)

分配並初始化一個新的標準 V4L2 選單控制元件。

引數

struct v4l2_ctrl_handler *hdl

控制元件處理程式。

const struct v4l2_ctrl_ops *ops

控制元件操作。

u32 id

控制元件 ID。

u8 max

控制元件的最大值。

u64 mask

選單控制元件的控制元件跳過掩碼。 這使得跳過無效的選單項變得容易。 如果設定了位 X,則跳過選單項 X。 當然,這僅適用於具有 <= 64 個選單項的選單。 沒有接近該數量的選單,所以這沒問題。 如果我們確實需要更多,那麼必須將其擴充套件到位陣列。

u8 def

控制元件的預設值。

說明

v4l2_ctrl_new_std() 相同,但 min 設定為 0,並且 mask 值決定了要跳過哪些選單項。

如果 id 指的是非選單控制元件,則此函式將返回 NULL。

struct v4l2_ctrl *v4l2_ctrl_new_std_menu_items(struct v4l2_ctrl_handler *hdl, const struct v4l2_ctrl_ops *ops, u32 id, u8 max, u64 mask, u8 def, const char *const *qmenu)

使用特定於驅動程式的選單建立一個新的標準 V4L2 選單控制元件。

引數

struct v4l2_ctrl_handler *hdl

控制元件處理程式。

const struct v4l2_ctrl_ops *ops

控制元件操作。

u32 id

控制元件 ID。

u8 max

控制元件的最大值。

u64 mask

選單控制元件的控制元件跳過掩碼。 這使得跳過無效的選單項變得容易。 如果設定了位 X,則跳過選單項 X。 當然,這僅適用於具有 <= 64 個選單項的選單。 沒有接近該數量的選單,所以這沒問題。 如果我們確實需要更多,那麼必須將其擴充套件到位陣列。

u8 def

控制元件的預設值。

const char * const *qmenu

新的選單。

說明

v4l2_ctrl_new_std_menu() 相同,但 qmenu 將是此控制元件的特定於驅動程式的選單。

struct v4l2_ctrl *v4l2_ctrl_new_std_compound(struct v4l2_ctrl_handler *hdl, const struct v4l2_ctrl_ops *ops, u32 id, const union v4l2_ctrl_ptr p_def, const union v4l2_ctrl_ptr p_min, const union v4l2_ctrl_ptr p_max)

分配並初始化一個新的標準 V4L2 複合控制元件。

引數

struct v4l2_ctrl_handler *hdl

控制元件處理程式。

const struct v4l2_ctrl_ops *ops

控制元件操作。

u32 id

控制元件 ID。

const union v4l2_ctrl_ptr p_def

控制元件的預設值。

const union v4l2_ctrl_ptr p_min

控制元件的最小值。

const union v4l2_ctrl_ptr p_max

控制元件的最大值。

說明

v4l2_ctrl_new_std() 相同,但支援複合控制元件。要填充 p_defp_minp_max 欄位,請使用 v4l2_ctrl_ptr_create() 將指標轉換為 const union v4l2_ctrl_ptr。如果您希望複合控制元件的預設值、最小值或最大值全為零,請使用 v4l2_ctrl_ptr_create(NULL)。如果複合控制元件未設定 V4L2_CTRL_FLAG_HAS_WHICH_MIN_MAX 標誌,則它沒有最小值和最大值。在這種情況下,只需對 p_minp_max 引數使用 v4l2_ctrl_ptr_create(NULL)。

struct v4l2_ctrl *v4l2_ctrl_new_int_menu(struct v4l2_ctrl_handler *hdl, const struct v4l2_ctrl_ops *ops, u32 id, u8 max, u8 def, const s64 *qmenu_int)

建立一個新的標準 V4L2 整數選單控制元件。

引數

struct v4l2_ctrl_handler *hdl

控制元件處理程式。

const struct v4l2_ctrl_ops *ops

控制元件操作。

u32 id

控制元件 ID。

u8 max

控制元件的最大值。

u8 def

控制元件的預設值。

const s64 *qmenu_int

控制元件的選單項。

說明

v4l2_ctrl_new_std_menu() 相同,但 mask 設定為 0,並且它額外接受一個整數陣列作為引數,用於確定選單項。

如果 id 指的是非整數選單控制元件,則此函式將返回 NULL

v4l2_ctrl_filter

Typedef:用於定義新增控制元件處理程式時要使用的篩選器函式的 Typedef。

語法

bool v4l2_ctrl_filter (const struct v4l2_ctrl *ctrl)

引數

const struct v4l2_ctrl *ctrl

指向 struct v4l2_ctrl 的指標。

int v4l2_ctrl_add_handler(struct v4l2_ctrl_handler *hdl, struct v4l2_ctrl_handler *add, v4l2_ctrl_filter filter, bool from_other_dev)

將處理程式 add 中的所有控制元件新增到處理程式 hdl

引數

struct v4l2_ctrl_handler *hdl

控制元件處理程式。

struct v4l2_ctrl_handler *add

您想要將其控制元件新增到 hdl 控制元件處理程式的控制元件處理程式。

v4l2_ctrl_filter filter

此函式將篩選應新增哪些控制元件。

bool from_other_dev

如果為 true,則 add 中的控制元件是在與 hdl 不同的裝置中定義的。

說明

如果兩個處理程式中的任何一個是指標,則不執行任何操作。如果 filter 為 NULL,則新增所有控制元件。否則,僅新增 filter 返回 true 的那些控制元件。如果發生錯誤,hdl->error 將設定為錯誤程式碼(如果尚未設定)。

bool v4l2_ctrl_radio_filter(const struct v4l2_ctrl *ctrl)

用於無線電控制元件的標準篩選器。

引數

const struct v4l2_ctrl *ctrl

要篩選的控制元件。

說明

這將為任何對無線電裝置節點有效的控制元件返回 true。這些控制元件是所有的 V4L2_CID_AUDIO_* 使用者控制元件和所有的 FM 發射器類控制元件。

此函式要與 v4l2_ctrl_add_handler() 一起使用。

void v4l2_ctrl_cluster(unsigned int ncontrols, struct v4l2_ctrl **controls)

將叢集中的所有控制元件標記為屬於該叢集。

引數

unsigned int ncontrols

此叢集中控制元件的數量。

struct v4l2_ctrl **controls

大小為 ncontrols 的叢集控制元件陣列。

void v4l2_ctrl_auto_cluster(unsigned int ncontrols, struct v4l2_ctrl **controls, u8 manual_val, bool set_volatile)

將叢集中的所有控制元件標記為屬於該叢集,並將其設定為進行 autofoo/foo 型別處理。

引數

unsigned int ncontrols

此叢集中控制元件的數量。

struct v4l2_ctrl **controls

大小為 ncontrols 的叢集控制元件陣列。第一個控制元件必須是“自動”控制元件(例如,自動增益、自動曝光等)。

u8 manual_val

叢集中第一個控制元件的值,該值等於手動設定。

bool set_volatile

如果為 true,則除第一個自動控制元件之外的所有控制元件都將是易失的。

說明

用於控制元件組,其中一個控制元件選擇某個自動功能,而其他控制元件僅在自動功能關閉(手動模式)時才處於活動狀態。典型示例:自動增益與增益、自動白平衡與紅色和藍色平衡等。

此類控制元件的行為如下

當 autofoo 控制元件設定為自動時,任何手動控制元件都將設定為不活動狀態,並且任何讀取都將呼叫 g_volatile_ctrl(如果控制元件標記為易失)。

當 autofoo 控制元件設定為手動時,任何手動控制元件都將標記為活動狀態,並且任何讀取都將只返回當前值,而無需透過 g_volatile_ctrl。

此外,如果 autofoo 處於自動模式,此函式將在 autofoo 控制元件上設定 V4L2_CTRL_FLAG_UPDATE 標誌,並在 foo 控制元件上設定 V4L2_CTRL_FLAG_INACTIVE

struct v4l2_ctrl *v4l2_ctrl_find(struct v4l2_ctrl_handler *hdl, u32 id)

查詢具有給定 ID 的控制元件。

引數

struct v4l2_ctrl_handler *hdl

控制元件處理程式。

u32 id

要查詢的控制元件 ID。

說明

如果 hdl == NULL,則它也將返回 NULL。將鎖定處理程式,因此請勿從 v4l2_ctrl_ops 內部使用。

void v4l2_ctrl_activate(struct v4l2_ctrl *ctrl, bool active)

啟用或停用控制元件。

引數

struct v4l2_ctrl *ctrl

要(取消)啟用的控制元件。

bool active

如果控制元件應變為活動狀態,則為 True。

說明

這將自動設定或清除 V4L2_CTRL_FLAG_INACTIVE 標誌。如果 ctrl == NULL,則不執行任何操作。這通常會從 s_ctrl op 中呼叫。之後將生成 V4L2_EVENT_CTRL 事件。

此函式假定控制元件處理程式已鎖定。

void __v4l2_ctrl_grab(struct v4l2_ctrl *ctrl, bool grabbed)

v4l2_ctrl_grab 的解鎖變體。

引數

struct v4l2_ctrl *ctrl

要(取消)啟用的控制元件。

bool grabbed

如果控制元件應變為已抓取狀態,則為 True。

說明

這將自動設定或清除 V4L2_CTRL_FLAG_GRABBED 標誌。如果 ctrl == NULL,則不執行任何操作。之後將生成 V4L2_EVENT_CTRL 事件。這通常會在驅動程式中啟動或停止流式傳輸時呼叫。

此函式假定控制元件處理程式已由呼叫方鎖定。

void v4l2_ctrl_grab(struct v4l2_ctrl *ctrl, bool grabbed)

將控制元件標記為已抓取或未抓取。

引數

struct v4l2_ctrl *ctrl

要(取消)啟用的控制元件。

bool grabbed

如果控制元件應變為已抓取狀態,則為 True。

說明

這將自動設定或清除 V4L2_CTRL_FLAG_GRABBED 標誌。如果 ctrl == NULL,則不執行任何操作。之後將生成 V4L2_EVENT_CTRL 事件。這通常會在驅動程式中啟動或停止流式傳輸時呼叫。

此函式假定控制元件處理程式未鎖定,並將自行獲取鎖定。

int __v4l2_ctrl_modify_range(struct v4l2_ctrl *ctrl, s64 min, s64 max, u64 step, s64 def)

v4l2_ctrl_modify_range() 的未鎖定變體

引數

struct v4l2_ctrl *ctrl

要更新的控制元件。

s64 min

控制元件的最小值。

s64 max

控制元件的最大值。

u64 step

控制元件的步長值

s64 def

控制元件的預設值。

說明

動態更新控制元件的範圍。 這適用於控制元件型別 INTEGER、BOOLEAN、MENU、INTEGER MENU 和 BITMASK。 對於選單控制元件,step 值被解釋為 menu_skip_mask。

如果某個範圍引數對於此控制元件型別無效,則返回錯誤。

呼叫者負責代表 __v4l2_ctrl_modify_range() 獲取控制元件處理程式互斥鎖。

int v4l2_ctrl_modify_range(struct v4l2_ctrl *ctrl, s64 min, s64 max, u64 step, s64 def)

更新控制元件的範圍。

引數

struct v4l2_ctrl *ctrl

要更新的控制元件。

s64 min

控制元件的最小值。

s64 max

控制元件的最大值。

u64 step

控制元件的步長值

s64 def

控制元件的預設值。

說明

動態更新控制元件的範圍。 這適用於控制元件型別 INTEGER、BOOLEAN、MENU、INTEGER MENU 和 BITMASK。 對於選單控制元件,step 值被解釋為 menu_skip_mask。

如果某個範圍引數對於此控制元件型別無效,則返回錯誤。

此函式假定控制元件處理程式未鎖定,並將自行獲取鎖定。

int __v4l2_ctrl_modify_dimensions(struct v4l2_ctrl *ctrl, u32 dims[V4L2_CTRL_MAX_DIMS])

v4l2_ctrl_modify_dimensions() 的未鎖定變體

引數

struct v4l2_ctrl *ctrl

要更新的控制元件。

u32 dims[V4L2_CTRL_MAX_DIMS]

控制元件的新尺寸。

說明

動態更新陣列控制元件的尺寸。 陣列的元素將重置為其預設值,即使尺寸未更改也是如此。

如果 dims 對此控制元件無效,則返回錯誤。

呼叫者負責代表 __v4l2_ctrl_modify_dimensions() 獲取控制元件處理程式互斥鎖。

注意

在掛起的請求中使用同一控制元件時呼叫此函式未經測試。 它應該可以工作(具有錯誤控制元件大小的請求將靜默刪除該控制元件),但這會非常令人困惑。

int v4l2_ctrl_modify_dimensions(struct v4l2_ctrl *ctrl, u32 dims[V4L2_CTRL_MAX_DIMS])

更新陣列控制元件的尺寸。

引數

struct v4l2_ctrl *ctrl

要更新的控制元件。

u32 dims[V4L2_CTRL_MAX_DIMS]

控制元件的新尺寸。

說明

動態更新陣列控制元件的尺寸。 陣列的元素將重置為其預設值,即使尺寸未更改也是如此。

如果 dims 對此控制元件型別無效,則返回錯誤。

此函式假定控制元件處理程式未鎖定,並將自行獲取鎖定。

注意

在掛起的請求中使用同一控制元件時呼叫此函式未經測試。 它應該可以工作(具有錯誤控制元件大小的請求將靜默刪除該控制元件),但這會非常令人困惑。

void v4l2_ctrl_notify(struct v4l2_ctrl *ctrl, v4l2_ctrl_notify_fnc notify, void *priv)

用於設定控制元件的通知回撥的函式。

引數

struct v4l2_ctrl *ctrl

控制元件。

v4l2_ctrl_notify_fnc notify

回撥函式。

void *priv

回撥私有控制代碼,作為引數傳遞給回撥。

說明

此函式為控制元件設定回撥函式。 如果 ctrl 為 NULL,則它將不執行任何操作。 如果 notify 為 NULL,則將刪除通知回撥。

只能有一個通知。 如果已經存在另一個通知,則會發出 WARN_ON 並且該函式將不執行任何操作。

const char *v4l2_ctrl_get_name(u32 id)

獲取控制元件的名稱

引數

u32 id

控制元件 ID。

說明

此函式返回給定控制元件 ID 的名稱;如果它不是已知的控制元件,則返回 NULL。

const char *const *v4l2_ctrl_get_menu(u32 id)

獲取控制元件的選單字串陣列

引數

u32 id

控制元件 ID。

說明

此函式返回給定控制元件 ID 的以 NULL 結尾的選單字串陣列名稱;如果它不是已知的選單控制元件,則返回 NULL。

const s64 *v4l2_ctrl_get_int_menu(u32 id, u32 *len)

獲取控制元件的整數選單陣列

引數

u32 id

控制元件 ID。

u32 *len

整數陣列的大小。

說明

此函式返回給定控制元件 ID 的整數陣列;如果它不是已知的整數選單控制元件,則返回 NULL。

s32 v4l2_ctrl_g_ctrl(struct v4l2_ctrl *ctrl)

用於從驅動程式中獲取控制元件的值的輔助函式。

引數

struct v4l2_ctrl *ctrl

控制元件。

說明

這透過控制框架安全地返回控制元件的值。 此函式將鎖定控制元件的處理程式,因此無法從 v4l2_ctrl_ops 函式中使用它。

此函式僅適用於整數型別控制元件。

int __v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val)

v4l2_ctrl_s_ctrl() 的未鎖定變體。

引數

struct v4l2_ctrl *ctrl

控制元件。

s32 val

新值。

說明

這透過控制框架安全地設定控制元件的新值。 此函式假定控制元件的處理程式已鎖定,允許從 v4l2_ctrl_ops 函式中使用它。

此函式僅適用於整數型別控制元件。

int v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val)

用於從驅動程式中設定控制元件的值的輔助函式。

引數

struct v4l2_ctrl *ctrl

控制元件。

s32 val

新值。

說明

這透過控制框架安全地設定控制元件的新值。 此函式將鎖定控制元件的處理程式,因此無法從 v4l2_ctrl_ops 函式中使用它。

此函式僅適用於整數型別控制元件。

s64 v4l2_ctrl_g_ctrl_int64(struct v4l2_ctrl *ctrl)

用於從驅動程式中獲取 64 位控制元件的值的輔助函式。

引數

struct v4l2_ctrl *ctrl

控制元件。

說明

這透過控制框架安全地返回控制元件的值。 此函式將鎖定控制元件的處理程式,因此無法從 v4l2_ctrl_ops 函式中使用它。

此函式僅適用於 64 位整數型別控制元件。

int __v4l2_ctrl_s_ctrl_int64(struct v4l2_ctrl *ctrl, s64 val)

v4l2_ctrl_s_ctrl_int64() 的未鎖定變體。

引數

struct v4l2_ctrl *ctrl

控制元件。

s64 val

新值。

說明

這透過控制框架安全地設定控制元件的新值。 此函式假定控制元件的處理程式已鎖定,允許從 v4l2_ctrl_ops 函式中使用它。

此函式僅適用於 64 位整數型別控制元件。

int v4l2_ctrl_s_ctrl_int64(struct v4l2_ctrl *ctrl, s64 val)

用於從驅動程式中設定 64 位控制元件的值的輔助函式。

引數

struct v4l2_ctrl *ctrl

控制元件。

s64 val

新值。

說明

這透過控制框架安全地設定控制元件的新值。 此函式將鎖定控制元件的處理程式,因此無法從 v4l2_ctrl_ops 函式中使用它。

此函式僅適用於 64 位整數型別控制元件。

int __v4l2_ctrl_s_ctrl_string(struct v4l2_ctrl *ctrl, const char *s)

v4l2_ctrl_s_ctrl_string() 的未鎖定變體。

引數

struct v4l2_ctrl *ctrl

控制元件。

const char *s

新字串。

說明

這透過控制框架安全地設定控制元件的新字串。 此函式假定控制元件的處理程式已鎖定,允許從 v4l2_ctrl_ops 函式中使用它。

此函式僅適用於字串型別控制元件。

int v4l2_ctrl_s_ctrl_string(struct v4l2_ctrl *ctrl, const char *s)

用於從驅動程式中設定控制元件的字串值的輔助函式。

引數

struct v4l2_ctrl *ctrl

控制元件。

const char *s

新字串。

說明

這透過控制框架安全地設定控制元件的新字串。 此函式將鎖定控制元件的處理程式,因此無法從 v4l2_ctrl_ops 函式中使用它。

此函式僅適用於字串型別控制元件。

int __v4l2_ctrl_s_ctrl_compound(struct v4l2_ctrl *ctrl, enum v4l2_ctrl_type type, const void *p)

用於設定複合控制元件的未鎖定變體

引數

struct v4l2_ctrl *ctrl

控制元件。

enum v4l2_ctrl_type type

資料的型別。

const void *p

新的複合有效負載。

說明

這透過控制框架安全地設定控制元件的新複合有效負載。 此函式假定控制元件的處理程式已鎖定,允許從 v4l2_ctrl_ops 函式中使用它。

此函式僅適用於複合型別控制元件。

int v4l2_ctrl_s_ctrl_compound(struct v4l2_ctrl *ctrl, enum v4l2_ctrl_type type, const void *p)

用於從驅動程式中設定複合控制元件的輔助函式。

引數

struct v4l2_ctrl *ctrl

控制元件。

enum v4l2_ctrl_type type

資料的型別。

const void *p

新的複合有效負載。

說明

這透過控制框架安全地設定控制元件的新複合有效負載。 此函式將鎖定控制元件的處理程式,因此無法從 v4l2_ctrl_ops 函式中使用它。

此函式僅適用於複合型別控制元件。

void v4l2_ctrl_replace(struct v4l2_event *old, const struct v4l2_event *new)

要用作 struct v4l2_subscribed_event_ops replace() 的回撥的函式

引數

struct v4l2_event *old

指向具有報告事件的 v4l2_event 結構的指標;

const struct v4l2_event *new

指向具有已修改事件的v4l2_event結構體的指標;

void v4l2_ctrl_merge(const struct v4l2_event *old, struct v4l2_event *new)

用作struct v4l2_subscribed_event_ops merge()的回撥函式

引數

const struct v4l2_event *old

指向具有報告事件的 v4l2_event 結構的指標;

struct v4l2_event *new

指向具有已合併事件的v4l2_event結構體的指標;

int v4l2_ctrl_log_status(struct file *file, void *fh)

用於實現VIDIOC_LOG_STATUS ioctl 的輔助函式

引數

struct file *file

指向struct file的指標

void *fh

未使用。保留它只是為了與struct v4l2_ioctl_ops.vidioc_log_status 期望的引數相容。

說明

可用作僅轉儲與檔案控制代碼關聯的所有控制元件的 vidioc_log_status 函式。

int v4l2_ctrl_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub)

訂閱事件

引數

struct v4l2_fh *fh

指向struct v4l2_fh的指標

const struct v4l2_event_subscription *sub

指向struct v4l2_event_subscription的指標

說明

可用作僅訂閱控制事件的 vidioc_subscribe_event 函式。

__poll_t v4l2_ctrl_poll(struct file *file, struct poll_table_struct *wait)

用作 poll() 回撥的函式,它只輪詢控制事件。

引數

struct file *file

指向struct file的指標

struct poll_table_struct *wait

指向 struct poll_table_struct 的指標

int v4l2_ctrl_request_setup(struct media_request *req, struct v4l2_ctrl_handler *parent)

用於在請求中應用控制值的輔助函式

引數

struct media_request *req

請求

struct v4l2_ctrl_handler *parent

父控制元件處理程式(media_request_object_find()中的'priv')

說明

這是一個輔助函式,用於使用請求中包含的控制元件值呼叫控制元件處理程式的 s_ctrl 回撥。請注意,這種在請求中應用控制元件值的方法僅適用於記憶體到記憶體裝置。

void v4l2_ctrl_request_complete(struct media_request *req, struct v4l2_ctrl_handler *parent)

完成控制元件處理程式請求物件

引數

struct media_request *req

請求

struct v4l2_ctrl_handler *parent

父控制元件處理程式(media_request_object_find()中的'priv')

說明

該函式應在每個可能具有與之關聯的請求物件的控制元件處理程式上呼叫,即支援請求的驅動程式的控制元件處理程式。

該函式首先獲取控制元件處理程式中任何易失性控制元件的值,並將它們附加到請求。然後,該函式完成請求物件。

struct v4l2_ctrl_handler *v4l2_ctrl_request_hdl_find(struct media_request *req, struct v4l2_ctrl_handler *parent)

在請求中查詢控制元件處理程式

引數

struct media_request *req

請求

struct v4l2_ctrl_handler *parent

父控制元件處理程式(media_request_object_find()中的'priv')

說明

該函式在請求中查詢控制元件處理程式。如果未找到,則可能返回 NULL。完成後,您必須使用返回的處理程式指標呼叫v4l2_ctrl_request_hdl_put()

如果請求不處於 VALIDATING 或 QUEUED 狀態,則此函式將始終返回 NULL。

請注意,在 VALIDATING 狀態下,req_queue_mutex 被持有,因此無法從請求中新增或刪除物件。

在 QUEUED 狀態下,將由驅動程式來確保這一點。

void v4l2_ctrl_request_hdl_put(struct v4l2_ctrl_handler *hdl)

放置控制元件處理程式

引數

struct v4l2_ctrl_handler *hdl

放置此控制元件處理程式

說明

此函式釋放先前從'v4l2_ctrl_request_hdl_find()'獲得的控制元件處理程式。

struct v4l2_ctrl *v4l2_ctrl_request_hdl_ctrl_find(struct v4l2_ctrl_handler *hdl, u32 id)

查詢具有給定 ID 的控制元件。

引數

struct v4l2_ctrl_handler *hdl

請求中的控制元件處理程式。

u32 id

要查詢的控制元件的 ID。

說明

如果此控制元件是請求的一部分,則此函式返回指向該控制元件的指標,否則返回 NULL。

int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc)

用於實現VIDIOC_QUERYCTRL ioctl 的輔助函式

引數

struct v4l2_ctrl_handler *hdl

指向struct v4l2_ctrl_handler的指標

struct v4l2_queryctrl *qc

指向struct v4l2_queryctrl的指標

說明

如果 hdl == NULL,則它們都將返回 -EINVAL。

void v4l2_query_ext_ctrl_to_v4l2_queryctrl(struct v4l2_queryctrl *to, const struct v4l2_query_ext_ctrl *from)

將 qec 轉換為 qe。

引數

struct v4l2_queryctrl *to

要寫入的 v4l2_queryctrl。

const struct v4l2_query_ext_ctrl *from

要從中讀取的 v4l2_query_ext_ctrl。

說明

此函式是一個輔助函式,用於將 v4l2_query_ext_ctrl 轉換為 v4l2_queryctrl。

int v4l2_query_ext_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_query_ext_ctrl *qc)

用於實現VIDIOC_QUERY_EXT_CTRL ioctl 的輔助函式

引數

struct v4l2_ctrl_handler *hdl

指向struct v4l2_ctrl_handler的指標

struct v4l2_query_ext_ctrl *qc

指向struct v4l2_query_ext_ctrl的指標

說明

如果 hdl == NULL,則它們都將返回 -EINVAL。

int v4l2_querymenu(struct v4l2_ctrl_handler *hdl, struct v4l2_querymenu *qm)

用於實現VIDIOC_QUERYMENU ioctl 的輔助函式

引數

struct v4l2_ctrl_handler *hdl

指向struct v4l2_ctrl_handler的指標

struct v4l2_querymenu *qm

指向struct v4l2_querymenu的指標

說明

如果 hdl == NULL,則它們都將返回 -EINVAL。

int v4l2_g_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_control *ctrl)

用於實現VIDIOC_G_CTRL ioctl 的輔助函式

引數

struct v4l2_ctrl_handler *hdl

指向struct v4l2_ctrl_handler的指標

struct v4l2_control *ctrl

指向struct v4l2_control的指標

說明

如果 hdl == NULL,則它們都將返回 -EINVAL。

int v4l2_s_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl, struct v4l2_control *ctrl)

用於實現VIDIOC_S_CTRL ioctl 的輔助函式

引數

struct v4l2_fh *fh

指向struct v4l2_fh的指標

struct v4l2_ctrl_handler *hdl

指向struct v4l2_ctrl_handler的指標

struct v4l2_control *ctrl

指向struct v4l2_control的指標

說明

如果 hdl == NULL,則它們都將返回 -EINVAL。

int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct video_device *vdev, struct media_device *mdev, struct v4l2_ext_controls *c)

用於實現 VIDIOC_G_EXT_CTRLS ioctl 的輔助函式

引數

struct v4l2_ctrl_handler *hdl

指向struct v4l2_ctrl_handler的指標

struct video_device *vdev

指向 struct video_device 的指標

struct media_device *mdev

指向 struct media_device 的指標

struct v4l2_ext_controls *c

指向 struct v4l2_ext_controls 的指標

說明

如果 hdl == NULL,則它們都將返回 -EINVAL。

int v4l2_try_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct video_device *vdev, struct media_device *mdev, struct v4l2_ext_controls *c)

用於實現 VIDIOC_TRY_EXT_CTRLS ioctl 的輔助函式

引數

struct v4l2_ctrl_handler *hdl

指向struct v4l2_ctrl_handler的指標

struct video_device *vdev

指向 struct video_device 的指標

struct media_device *mdev

指向 struct media_device 的指標

struct v4l2_ext_controls *c

指向 struct v4l2_ext_controls 的指標

說明

如果 hdl == NULL,則它們都將返回 -EINVAL。

int v4l2_s_ext_ctrls(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl, struct video_device *vdev, struct media_device *mdev, struct v4l2_ext_controls *c)

用於實現 VIDIOC_S_EXT_CTRLS ioctl 的輔助函式

引數

struct v4l2_fh *fh

指向struct v4l2_fh的指標

struct v4l2_ctrl_handler *hdl

指向struct v4l2_ctrl_handler的指標

struct video_device *vdev

指向 struct video_device 的指標

struct media_device *mdev

指向 struct media_device 的指標

struct v4l2_ext_controls *c

指向 struct v4l2_ext_controls 的指標

說明

如果 hdl == NULL,則它們都將返回 -EINVAL。

int v4l2_ctrl_subdev_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh, struct v4l2_event_subscription *sub)

用作 struct v4l2_subdev_core_ops subscribe_event 函式的輔助函式,該函式僅訂閱控制事件。

引數

struct v4l2_subdev *sd

指向 struct v4l2_subdev 的指標

struct v4l2_fh *fh

指向struct v4l2_fh的指標

struct v4l2_event_subscription *sub

指向struct v4l2_event_subscription的指標

int v4l2_ctrl_subdev_log_status(struct v4l2_subdev *sd)

記錄子裝置控制控制代碼擁有的所有控制元件。

引數

struct v4l2_subdev *sd

指向 struct v4l2_subdev 的指標

int v4l2_ctrl_new_fwnode_properties(struct v4l2_ctrl_handler *hdl, const struct v4l2_ctrl_ops *ctrl_ops, const struct v4l2_fwnode_device_properties *p)

註冊裝置屬性的控制元件

引數

struct v4l2_ctrl_handler *hdl

指向要在其上註冊控制元件的 struct v4l2_ctrl_handler 的指標

const struct v4l2_ctrl_ops *ctrl_ops

指向用於註冊控制元件的 struct v4l2_ctrl_ops 的指標

const struct v4l2_fwnode_device_properties *p

指向 struct v4l2_fwnode_device_properties 的指標

說明

如果屬性已設定為某個值,則此函式使用 p 引數中包含的屬性值註冊與裝置屬性關聯的控制元件。

當前解析並註冊以下 v4l2 控制元件: - V4L2_CID_CAMERA_ORIENTATION - V4L2_CID_CAMERA_SENSOR_ROTATION;

呼叫方已使用 hdl 控制控制代碼註冊的控制元件不會被覆蓋。呼叫方應先註冊他們想要自己處理的控制元件,然後再呼叫此函式。

返回值

成功時返回 0,失敗時返回負錯誤程式碼。

bool v4l2_ctrl_type_op_equal(const struct v4l2_ctrl *ctrl, union v4l2_ctrl_ptr ptr1, union v4l2_ctrl_ptr ptr2)

預設的 v4l2_ctrl_type_ops equal 回撥。

引數

const struct v4l2_ctrl *ctrl

v4l2_ctrl 指標。

union v4l2_ctrl_ptr ptr1

一個 v4l2 控制值。

union v4l2_ctrl_ptr ptr2

一個 v4l2 控制值。

返回值

如果值相等,則為 true;否則為 false。

void v4l2_ctrl_type_op_init(const struct v4l2_ctrl *ctrl, u32 from_idx, union v4l2_ctrl_ptr ptr)

預設的 v4l2_ctrl_type_ops init 回撥。

引數

const struct v4l2_ctrl *ctrl

v4l2_ctrl 指標。

u32 from_idx

起始元素索引。

union v4l2_ctrl_ptr ptr

v4l2 控制值。

返回值

void

void v4l2_ctrl_type_op_log(const struct v4l2_ctrl *ctrl)

預設的 v4l2_ctrl_type_ops log 回撥。

引數

const struct v4l2_ctrl *ctrl

v4l2_ctrl 指標。

返回值

void

int v4l2_ctrl_type_op_validate(const struct v4l2_ctrl *ctrl, union v4l2_ctrl_ptr ptr)

預設的 v4l2_ctrl_type_ops validate 回撥。

引數

const struct v4l2_ctrl *ctrl

v4l2_ctrl 指標。

union v4l2_ctrl_ptr ptr

v4l2 控制值。

返回值

成功時返回 0,失敗時返回負錯誤程式碼。