2.11. ioctls CEC_RECEIVE 和 CEC_TRANSMIT

2.11.1. 名稱

CEC_RECEIVE, CEC_TRANSMIT - 接收或傳送 CEC 訊息

2.11.2. 概要

CEC_RECEIVE

int ioctl(int fd, CEC_RECEIVE, struct cec_msg *argp)

CEC_TRANSMIT

int ioctl(int fd, CEC_TRANSMIT, struct cec_msg *argp)

2.11.3. 引數

fd

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

argp

指向 struct cec_msg 的指標。

2.11.4. 描述

要接收 CEC 訊息,應用程式必須填寫 struct cec_msgtimeout 欄位,並將其傳遞給 ioctl CEC_RECEIVE。如果檔案描述符處於非阻塞模式,並且沒有待處理的已接收訊息,則它將返回 -1 並將 errno 設定為 EAGAIN 錯誤程式碼。如果檔案描述符處於阻塞模式,並且 timeout 為非零,並且在 timeout 毫秒內沒有訊息到達,則它將返回 -1 並將 errno 設定為 ETIMEDOUT 錯誤程式碼。

接收到的訊息可以是

  1. 從另一個 CEC 裝置接收的訊息(sequence 欄位將為 0,tx_status 將為 0,rx_status 將為非零)。

  2. 先前非阻塞傳輸的傳輸結果(sequence 欄位將為非零,tx_status 將為非零,rx_status 將為 0)。

  3. 先前非阻塞傳輸的回覆(sequence 欄位將為非零,tx_status 將為 0,rx_status 將為非零)。

要傳送 CEC 訊息,應用程式必須填寫 struct cec_msg,並將其傳遞給 ioctl CEC_TRANSMIT。僅當設定了 CEC_CAP_TRANSMIT 時,ioctl CEC_TRANSMIT 才可用。如果傳輸佇列中沒有更多空間,則它將返回 -1 並將 errno 設定為 EBUSY 錯誤程式碼。傳輸佇列有足夠的空間容納 18 條訊息(大約 1 秒的 2 位元組訊息)。請注意,CEC 核心框架也會回覆核心訊息(請參閱 核心訊息處理),因此完全填滿傳輸佇列並不是一個好主意。

如果檔案描述符處於非阻塞模式,則傳輸將返回 0,並且一旦傳輸完成,就可以透過 ioctl CEC_RECEIVE 獲得傳輸結果。如果非阻塞傳輸還指定了等待回覆,則回覆將在稍後的訊息中到達。sequence 欄位可用於將傳輸結果和回覆與原始傳輸相關聯。

通常,當物理地址無效時(例如,由於斷開連線),呼叫 ioctl CEC_TRANSMIT 將返回 ENONET

但是,CEC 規範允許在物理地址無效時從“未註冊”向“電視”傳送訊息,因為某些電視在進入待機狀態或切換到另一個輸入時會將 HDMI 聯結器的熱插拔檢測引腳拉低。

當熱插拔檢測引腳變為低電平時,EDID 消失,因此物理地址也消失,但電纜仍然連線並且 CEC 仍然有效。為了檢測/喚醒裝置,允許從發起者 0xf(“未註冊”)向目標 0(“電視”)傳送輪詢和“影像/文字檢視開啟”訊息。

type cec_msg
struct cec_msg

__u64

tx_ts

訊息的最後一個位元組被傳輸時的納秒時間戳。時間戳取自 CLOCK_MONOTONIC 時鐘。要從使用者空間訪問同一時鐘,請使用 clock_gettime()

__u64

rx_ts

訊息的最後一個位元組被接收時的納秒時間戳。時間戳取自 CLOCK_MONOTONIC 時鐘。要從使用者空間訪問同一時鐘,請使用 clock_gettime()

__u32

len

訊息的長度。對於 ioctl CEC_TRANSMIT,這由應用程式填寫。驅動程式將為 ioctl CEC_RECEIVE 填寫此項。對於 ioctl CEC_TRANSMIT,如果設定了 reply,則驅動程式將使用回覆訊息的長度填寫此項。

__u32

timeout

以毫秒為單位的超時時間。這是裝置在超時之前等待接收訊息的時間。如果將其設定為 0,則當透過 ioctl CEC_RECEIVE 呼叫時,它將無限期地等待。如果它為 0 並且透過 ioctl CEC_TRANSMIT 呼叫,則如果 reply 為非零,則它將被替換為 1000,如果 reply 為 0,則將被忽略。

__u32

sequence

CEC 框架會自動為所有傳輸的訊息分配一個非零序列號。當 CEC 框架為非阻塞傳輸排隊傳輸結果時,會使用此序列號。這允許應用程式將接收到的訊息與原始傳輸相關聯。

此外,如果非阻塞傳輸將等待回覆(即 timeout 不為 0),則回覆的 sequence 欄位將設定為原始傳輸的序列值。這允許應用程式將接收到的訊息與原始傳輸相關聯。

__u32

flags

標誌。有關可用標誌的列表,請參閱 struct cec_msg 的標誌

__u8

msg[16]

訊息有效負載。對於 ioctl CEC_TRANSMIT,這由應用程式填寫。驅動程式將為 ioctl CEC_RECEIVE 填寫此項。對於 ioctl CEC_TRANSMIT,如果設定了 timeout,則驅動程式將使用回覆訊息的有效負載填寫此項。

__u8

reply

等待直到此訊息被回覆。如果 reply 為 0 且 timeout 為 0,則在傳輸訊息後不要等待回覆而返回。被 ioctl CEC_RECEIVE 忽略。特別允許 reply 為 0(這是 Feature Abort 訊息的操作碼)且 timeout 為非零的情況,以便可以傳送訊息並最多等待 timeout 毫秒以獲得 Feature Abort 回覆。在這種情況下,rx_status 將設定為 CEC_RX_STATUS_TIMEOUTCEC_RX_STATUS_FEATURE_ABORT

如果發射器訊息為 CEC_MSG_INITIATE_ARC,則 replyCEC_MSG_REPORT_ARC_INITIATEDCEC_MSG_REPORT_ARC_TERMINATED 的處理方式不同:任何值都將匹配所有可能的回覆。原因是 CEC_MSG_INITIATE_ARC 訊息是唯一具有除 Feature Abort 之外的兩種可能回覆的 CEC 訊息。reply 欄位將使用實際回覆進行更新,以便與接收到的訊息的內容同步。

__u8

rx_status

接收到的訊息的狀態位。有關可能的狀態值,請參閱 CEC 接收狀態

__u8

tx_status

傳輸的訊息的狀態位。有關可能的狀態值,請參閱 CEC 傳輸狀態。在非阻塞模式下呼叫 ioctl CEC_TRANSMIT 時,如果傳輸已啟動,則此欄位將為 0;如果立即知道傳輸結果,則此欄位將為非 0。嘗試向自己傳輸 Poll 訊息時就是後一種情況。這會導致 CEC_TX_STATUS_NACK,而無需實際傳輸 Poll 訊息。

__u8

tx_arb_lost_cnt

導致 Arbitration Lost 錯誤的傳輸嘗試次數的計數器。僅當硬體支援此功能時才會設定此值,否則始終為 0。僅當設定了 CEC_TX_STATUS_ARB_LOST 狀態位時,此計數器才有效。

__u8

tx_nack_cnt

導致 Not Acknowledged 錯誤的傳輸嘗試次數的計數器。僅當硬體支援此功能時才會設定此值,否則始終為 0。僅當設定了 CEC_TX_STATUS_NACK 狀態位時,此計數器才有效。

__u8

tx_low_drive_cnt

導致 Arbitration Lost 錯誤的傳輸嘗試次數的計數器。僅當硬體支援此功能時才會設定此值,否則始終為 0。僅當設定了 CEC_TX_STATUS_LOW_DRIVE 狀態位時,此計數器才有效。

__u8

tx_error_cnt

Arbitration Lost 或 Not Acknowledged 之外的傳輸錯誤數量的計數器。僅當硬體支援此功能時才會設定此值,否則始終為 0。僅當設定了 CEC_TX_STATUS_ERROR 狀態位時,此計數器才有效。

struct cec_msg 的標誌

CEC_MSG_FL_REPLY_TO_FOLLOWERS

1

如果 CEC 傳輸期望回覆,則預設情況下,該回復僅傳送到呼叫 ioctl CEC_TRANSMIT 的檔案控制代碼。如果設定了此標誌,則回覆也會發送到所有關注者(如果有)。如果呼叫 ioctl CEC_TRANSMIT 的檔案控制代碼也是關注者,則該檔案控制代碼將收到兩次回覆:一次作為 ioctl CEC_TRANSMIT 的結果,一次透過 ioctl CEC_RECEIVE

CEC_MSG_FL_RAW

2

通常,CEC 訊息在傳輸之前會進行驗證。如果在呼叫 ioctl CEC_TRANSMIT 時設定了此標誌,則不會進行驗證,並且訊息將按原樣傳輸。這在除錯 CEC 問題時很有用。只有程序具有 CAP_SYS_RAWIO 功能時,才允許使用此標誌。如果未設定該標誌,則返回 EPERM 錯誤程式碼。

CEC_MSG_FL_REPLY_VENDOR_ID

4

僅當設定了 CEC_CAP_REPLY_VENDOR_ID 功能時,此標誌才可用。如果設定了此標誌,則預期回覆由 CEC_MSG_VENDOR_COMMAND_WITH_ID 操作碼、Vendor ID(在訊息的位元組 1-4 中)以及 struct cec_msg reply 欄位組成。

請注意,這假設 Vendor ID 之後的位元組是供應商特定的操作碼。

此標誌使等待供應商命令的回覆變得更容易。

CEC 傳輸狀態

CEC_TX_STATUS_OK

0x01

訊息已成功傳輸。這與 CEC_TX_STATUS_MAX_RETRIES 互斥。如果在傳輸最終成功之前,先前的嘗試遇到失敗,則仍然可以設定其他位。

CEC_TX_STATUS_ARB_LOST

0x02

CEC 線仲裁丟失,即另一個傳輸以更高的優先順序同時啟動。可選狀態,並非所有硬體都可以檢測到此錯誤情況。

CEC_TX_STATUS_NACK

0x04

訊息未被確認。請注意,某些硬體無法區分“未確認”狀態與其他錯誤情況,即傳輸結果僅為 OK 或 FAIL。在這種情況下,當傳輸失敗時將返回此狀態。

CEC_TX_STATUS_LOW_DRIVE

0x08

在 CEC 總線上檢測到低驅動。這表明關注者檢測到總線上存在錯誤,並請求重新傳輸。可選狀態,並非所有硬體都可以檢測到此錯誤情況。

CEC_TX_STATUS_ERROR

0x10

發生了一些錯誤。這用於不適合 CEC_TX_STATUS_ARB_LOSTCEC_TX_STATUS_LOW_DRIVE 的任何錯誤,可能是因為硬體無法判斷髮生了哪個錯誤,或者因為硬體測試了除這兩種情況之外的其他情況。可選狀態。

CEC_TX_STATUS_MAX_RETRIES

0x20

一次或多次重試後傳輸失敗。此狀態位與 CEC_TX_STATUS_OK 互斥。仍然可以設定其他位來解釋看到了哪些失敗。

CEC_TX_STATUS_ABORTED

0x40

由於 HDMI 斷開連線,或者介面卡已取消配置,或者傳輸已中斷,或者驅動程式在嘗試啟動傳輸時返回了錯誤,因此傳輸已中止。

CEC_TX_STATUS_TIMEOUT

0x80

傳輸超時。這通常不應該發生,並且這表明驅動程式存在問題。

CEC 接收狀態

CEC_RX_STATUS_OK

0x01

訊息已成功接收。

CEC_RX_STATUS_TIMEOUT

0x02

先前傳輸的訊息的回覆超時。

CEC_RX_STATUS_FEATURE_ABORT

0x04

訊息已成功接收,但回覆為 CEC_MSG_FEATURE_ABORT。僅當此訊息是對先前傳輸的訊息的回覆時,才設定此狀態。

CEC_RX_STATUS_ABORTED

0x08

由於 HDMI 電纜已斷開連線,或者介面卡已取消配置,或者等待回覆的 CEC_TRANSMIT 已中斷,因此等待先前傳輸的訊息的回覆已中止。

2.11.5. 返回值

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

ioctl CEC_RECEIVE 可以返回以下錯誤程式碼

EAGAIN

接收佇列中沒有訊息,並且檔案控制代碼處於非阻塞模式。

ETIMEDOUT

在等待訊息時達到 timeout

ERESTARTSYS

等待訊息被中斷(例如,透過 Ctrl-C)。

ioctl CEC_TRANSMIT 可以返回以下錯誤程式碼

ENOTTY

未設定 CEC_CAP_TRANSMIT 功能,因此不支援此 ioctl。

EPERM

CEC 介面卡未配置,即從未呼叫 ioctl CEC_ADAP_S_LOG_ADDRS,或者從沒有 CAP_SYS_RAWIO 功能的程序使用了 CEC_MSG_FL_RAW

ENONET

CEC 介面卡未配置,即已呼叫 ioctl CEC_ADAP_S_LOG_ADDRS,但是物理地址無效,因此未宣告邏輯地址。在這種情況下,從發起者 0xf(“未註冊”)到目標 0(“電視”)的傳輸是一個例外。在這種情況下,傳輸將照常進行。

EBUSY

另一個檔案控制代碼處於獨佔關注者或發起者模式,或者檔案控制代碼處於模式 CEC_MODE_NO_INITIATOR。如果傳輸佇列已滿,也會返回此值。

EINVAL

struct cec_msg 的內容無效。

ERESTARTSYS

等待成功傳輸被中斷(例如,透過 Ctrl-C)。