使用者空間 EC 介面 (cdev)

surface_aggregator_cdev 模組為 SSAM 控制器提供了一個 misc 裝置,允許使用者空間(或多或少)直接連線到 SAM EC。 它旨在用於開發和除錯,因此不應以任何其他方式使用或依賴。 請注意,此模組不會自動載入,而是必須手動載入。

提供的介面可以透過 /dev/surface/aggregator 裝置檔案訪問。 此介面的所有功能都透過 IOCTL 提供。 這些 IOCTL 及其各自的輸入/輸出引數結構在 include/uapi/linux/surface_aggregator/cdev.h 中定義。

可以在 https://github.com/linux-surface/surface-aggregator-module/tree/master/scripts/ssam 找到一個小型 python 庫和用於訪問此介面的指令碼。

接收事件

可以透過從裝置檔案讀取來接收事件。 它們由 struct ssam_cdev_event 資料型別表示。

但是,在事件可以被讀取之前,必須透過 SSAM_CDEV_NOTIF_REGISTER IOCTL 註冊所需的通知器。 從本質上講,通知器是回撥函式,當 EC 傳送事件時呼叫。 在此介面中,它們與特定的目標類別和裝置檔案例項相關聯。 它們將此類別的任何事件轉發到相應例項的緩衝區,然後可以從中讀取該事件。

通知器本身不會在 EC 上啟用事件。 因此,可能還需要透過 SSAM_CDEV_EVENT_ENABLE IOCTL 啟用事件。 雖然通知器按客戶端工作(即每個裝置檔案例項),但事件是全域性啟用的,適用於 EC 及其所有客戶端(無論使用者空間還是非使用者空間)。 SSAM_CDEV_EVENT_ENABLESSAM_CDEV_EVENT_DISABLE IOCTL 負責事件的引用計數,以便只要有客戶端請求該事件,該事件就會被啟用。

請注意,一旦客戶端例項關閉,已啟用的事件不會自動停用。 因此,任何客戶端程序(或程序組)都應平衡其事件啟用呼叫與相應的事件停用呼叫。 但是,在不同的客戶端例項上啟用和停用事件是完全有效的。 例如,可以在客戶端例項 A 上設定通知器並讀取事件,在例項 B 上啟用這些事件(請注意,由於事件是全域性啟用/停用的,因此 A 也會收到這些事件),並且在不再需要任何事件後,透過例項 C 停用先前啟用的事件,這是有效的。

控制器 IOCTL

提供以下 IOCTL

控制器 IOCTL

型別

編號

方向

名稱

描述

0xA5

1

WR

REQUEST

執行同步 SAM 請求。

0xA5

2

W

NOTIF_REGISTER

註冊事件通知器。

0xA5

3

W

NOTIF_UNREGISTER

取消註冊事件通知器。

0xA5

4

W

EVENT_ENABLE

啟用事件源。

0xA5

5

W

EVENT_DISABLE

停用事件源。

SSAM_CDEV_REQUEST

定義為 _IOWR(0xA5, 1, struct ssam_cdev_request)

執行同步 SAM 請求。 請求規範作為 struct ssam_cdev_request 型別的引數傳入,然後由 IOCTL 寫入/修改以返回請求的狀態和結果。

請求有效負載資料必須單獨分配,並透過 payload.datapayload.length 成員傳入。 如果需要響應,則響應緩衝區必須由呼叫者分配,並透過 response.data 成員傳入。 response.length 成員必須設定為此緩衝區的容量,如果不需要響應,則設定為零。 請求完成後,呼叫會將響應寫入響應緩衝區(如果其容量允許),並用響應的實際大小(以位元組為單位)覆蓋長度欄位。

此外,如果請求有響應,則必須透過請求標誌來指示,就像在核心請求中一樣。 可以透過 flags 成員設定請求標誌,並且這些值對應於在 enum ssam_cdev_request_flags 中找到的值。

最後,請求本身的狀態在 status 成員中返回(負 errno 值表示失敗)。 請注意,IOCTL 的失敗指示與請求的失敗指示是分開的:如果在請求設定過程中出現任何故障(-EFAULT)或者如果提供的引數或其任何欄位無效(-EINVAL),則 IOCTL 返回負狀態碼。 在這種情況下,可以設定請求引數的狀態值,從而提供有關出現問題的更多詳細資訊(例如,記憶體不足的 -ENOMEM),但此值也可能為零。 如果請求已成功地從 IOCTL 內部設定、提交和完成(即交回使用者空間),則 IOCTL 將返回零狀態碼,但如果請求在提交後實際執行失敗,則請求 status 成員可能仍然為負。

下面提供了引數結構的完整定義。

SSAM_CDEV_NOTIF_REGISTER

定義為 _IOW(0xA5, 2, struct ssam_cdev_notifier_desc)

使用指定的優先順序為給定通知器描述中指定的事件目標類別註冊通知器。 註冊通知器是接收事件所必需的,但本身不會啟用事件。 在為特定目標類別註冊通知器後,該類別的所有事件都將轉發到使用者空間客戶端,然後可以從裝置檔案例項中讀取。 請注意,在 EC 傳送事件之前,可能必須啟用事件,例如透過 SSAM_CDEV_EVENT_ENABLE IOCTL。

每個目標類別和客戶端例項只能註冊一個通知器。 如果已註冊通知器,則此 IOCTL 將失敗並顯示 -EEXIST

當裝置檔案例項關閉時,通知器將自動刪除。

SSAM_CDEV_NOTIF_UNREGISTER

定義為 _IOW(0xA5, 3, struct ssam_cdev_notifier_desc)

取消註冊與指定目標類別關聯的通知器。 此 IOCTL 將忽略優先順序欄位。 如果沒有為此客戶端例項和給定類別註冊通知器,則此 IOCTL 將失敗並顯示 -ENOENT

SSAM_CDEV_EVENT_ENABLE

定義為 _IOW(0xA5, 4, struct ssam_cdev_event_desc)

啟用與給定事件描述符關聯的事件。

請注意,此呼叫本身不會註冊通知器,它只會啟用控制器上的事件。 如果您想透過從裝置檔案讀取來接收事件,則需要在該例項上註冊相應的通知器。

關閉裝置檔案時,事件不會自動停用。 這必須手動完成,透過呼叫 SSAM_CDEV_EVENT_DISABLE IOCTL。

SSAM_CDEV_EVENT_DISABLE

定義為 _IOW(0xA5, 5, struct ssam_cdev_event_desc)

停用與給定事件描述符關聯的事件。

請注意,這不會取消註冊任何通知器。 在此呼叫之後,可能仍會收到事件並將其轉發到使用者空間。 停止接收事件的唯一安全方法是取消註冊所有先前註冊的通知器。

結構體和列舉

enum ssam_cdev_request_flags

SSAM cdev 請求 IOCTL 的請求標誌。

常量

SSAM_CDEV_REQUEST_HAS_RESPONSE

指定請求需要響應。 如果未設定,則請求將在其底層資料包傳輸後直接完成。 如果設定,則請求傳輸系統會等待請求的響應。

SSAM_CDEV_REQUEST_UNSEQUENCED

指定應透過未排序的資料包傳輸請求。 如果設定,則請求不得有響應,這意味著此標誌和 SSAM_CDEV_REQUEST_HAS_RESPONSE 標誌互斥。

struct ssam_cdev_request

控制器請求 IOCTL 引數。

定義:

struct ssam_cdev_request {
    __u8 target_category;
    __u8 target_id;
    __u8 command_id;
    __u8 instance_id;
    __u16 flags;
    __s16 status;
    struct {
        __u64 data;
        __u16 length;
        __u8 __pad[6];
    } payload;
    struct {
        __u64 data;
        __u16 length;
        __u8 __pad[6];
    } response;
};

成員

target_category

SAM 請求的目標類別。

target_id

SAM 請求的目標 ID。

command_id

SAM 請求的命令 ID。

instance_id

SAM 請求的例項 ID。

flags

請求標誌(請參閱 enum ssam_cdev_request_flags)。

status

請求狀態(輸出)。

payload

請求有效負載(輸入資料)。

payload.data

指向請求有效負載資料的指標。

payload.length

請求有效負載資料的長度(以位元組為單位)。

response

請求響應(輸出資料)。

response.data

指向響應緩衝區的指標。

response.length

輸入:響應緩衝區的容量(以位元組為單位)。 輸出:請求響應的長度(緩衝區中實際使用的位元組數)。

struct ssam_cdev_notifier_desc

通知器描述符。

定義:

struct ssam_cdev_notifier_desc {
    __s32 priority;
    __u8 target_category;
};

成員

priority

優先順序值,確定呼叫通知器回撥的順序。 值越高意味著優先順序越高,即關聯的回撥將比其他(較低優先順序)回撥更早執行。

target_category

此通知器應接收事件的事件目標類別。

描述

指定應註冊或取消註冊的通知器,特別是具有哪個優先順序以及用於哪個目標類別的事件。

struct ssam_cdev_event_desc

事件描述符。

定義:

struct ssam_cdev_event_desc {
    struct {
        __u8 target_category;
        __u8 target_id;
        __u8 cid_enable;
        __u8 cid_disable;
    } reg;
    struct {
        __u8 target_category;
        __u8 instance;
    } id;
    __u8 flags;
};

成員

reg

將透過其啟用/停用事件的登錄檔。

reg.target_category

事件登錄檔請求的目標類別。

reg.target_id

事件登錄檔請求的目標 ID。

reg.cid_enable

用於啟用事件請求的命令 ID。

reg.cid_disable

用於停用事件請求的命令 ID。

id

指定事件的 ID。

id.target_category

事件源的目標類別。

id.instance

事件源的例項 ID。

flags

用於啟用事件的標誌。

描述

指定應啟用/停用哪個事件以及如何執行此操作。

struct ssam_cdev_event

EC 傳送的 SSAM 事件。

定義:

struct ssam_cdev_event {
    __u8 target_category;
    __u8 target_id;
    __u8 command_id;
    __u8 instance_id;
    __u16 length;
    __u8 data[];
};

成員

target_category

事件源的目標類別。 請參閱 enum ssam_ssh_tc

target_id

事件源的目標 ID。

command_id

事件的命令 ID。

instance_id

事件源的例項 ID。

length

事件有效負載的長度,以位元組為單位。

data

事件有效負載資料。