6.1. 簡介¶
LIRC 代表 Linux 紅外遙控。LIRC 裝置介面是一個雙向介面,用於在使用者空間和核心空間之間傳輸原始紅外資料和解碼後的掃描碼資料。從根本上說,它只是一個字元裝置 (/dev/lircX,其中 X = 0, 1, 2, ...),在其上定義了許多標準的 struct file_operations。關於來回傳輸原始紅外資料和解碼後的掃描碼,基本的 fops 是 read、write 和 ioctl。
也可以將 BPF 程式附加到 LIRC 裝置,用於將原始紅外資料解碼為掃描碼。
驅動程式向 LIRC 註冊後示例 dmesg 輸出
$ dmesg |grep lirc_dev
rc rc0: lirc_dev: driver mceusb registered at minor = 0, raw IR receiver, raw IR transmitter
您應該看到的字元裝置資訊
$ ls -l /dev/lirc*
crw-rw---- 1 root root 248, 0 Jul 2 22:20 /dev/lirc0
請注意,v4l-utils 軟體包包含用於使用 LIRC 裝置的工具
ir-ctl:可以接收原始紅外資料和傳輸紅外資料,以及查詢 LIRC 裝置功能。
ir-keytable:可以載入鍵對映;允許您設定紅外核心協議;載入 BPF 紅外解碼器和測試紅外解碼。還提供了一些 BPF 紅外解碼器。
6.2. LIRC 模式¶
LIRC 支援一些接收和傳送紅外程式碼的模式,如下表所示。
LIRC_MODE_SCANCODE
此模式用於傳送和接收紅外資料。
對於傳輸(又名傳送),建立一個
struct lirc_scancode,並在scancode成員中設定所需的掃描碼,將rc_proto設定為 紅外協議,並將所有其他成員設定為 0。將此結構寫入 lirc 裝置。對於接收,您可以從 LIRC 裝置讀取
struct lirc_scancode。scancode欄位設定為接收到的掃描碼,紅外協議在rc_proto中設定。如果掃描碼對映到有效的鍵程式碼,則將其設定在keycode欄位中,否則將其設定為KEY_RESERVED。如果切換位在支援它的協議(例如 rc-5 和 rc-6)中設定,則
flags可以設定LIRC_SCANCODE_FLAG_TOGGLE,或者如果接收到支援它的協議的重複(例如 nec),則可以設定LIRC_SCANCODE_FLAG_REPEAT。在 Sanyo 和 NEC 協議中,如果按住遙控器上的按鈕,而不是重複整個掃描碼,遙控器會發送一個更短的訊息,其中沒有掃描碼,這僅僅意味著按鈕被按住,即“重複”。當接收到此訊息時,將設定
LIRC_SCANCODE_FLAG_REPEAT,並且重複掃描碼和鍵程式碼。使用 nec,無法區分“按鈕按住”和“重複按下同一按鈕”。rc-5 和 rc-6 協議有一個切換位。當釋放一個按鈕並再次按下時,切換位會反轉。如果設定了切換位,則設定
LIRC_SCANCODE_FLAG_TOGGLE。
timestamp欄位使用掃描碼解碼時的時間納秒(在CLOCK_MONOTONIC中)填充。
LIRC_MODE_MODE2
驅動程式將脈衝和空間程式碼的序列作為一系列 u32 值返回給使用者空間。
此模式僅用於紅外接收。
高 8 位確定資料包型別,低 24 位確定有效負載。使用
LIRC_VALUE()宏來獲取有效負載,宏LIRC_MODE2()將為您提供型別,它是以下之一
LIRC_MODE2_PULSE表示以微秒為單位的紅外存在,也稱為閃光。
LIRC_MODE2_SPACE表示以微秒為單位的紅外不存在,也稱為間隙。
LIRC_MODE2_FREQUENCY如果使用 ioctl LIRC_SET_MEASURE_CARRIER_MODE 啟用了載波頻率的測量,則此資料包會為您提供以赫茲為單位的載波頻率。
LIRC_MODE2_TIMEOUT由於未檢測到紅外訊號,使用 ioctl LIRC_GET_REC_TIMEOUT 和 LIRC_SET_REC_TIMEOUT 設定的超時到期時,將傳送此資料包,其中包含未檢測到紅外訊號的微秒數。
LIRC_MODE2_OVERFLOW表示紅外接收器遇到溢位,並且丟失了一些紅外訊號。此後的紅外資料應再次正確。實際值並不重要,但核心將其設定為 0xffffff 以與 lircd 相容。
LIRC_MODE_PULSE
在脈衝模式下,一系列脈衝/空間整數值使用 LIRC write() 寫入 lirc 裝置。
這些值是以微秒為單位的脈衝和空間長度交替出現。第一個和最後一個條目必須是脈衝,因此必須有奇數個條目。
此模式僅用於紅外發送。
6.3. LIRC_MODE_SCANCODE 使用的資料型別¶
-
struct lirc_scancode¶
解碼後的掃描碼,帶有用於 LIRC_MODE_SCANCODE 的協議
定義:
struct lirc_scancode {
__u64 timestamp;
__u16 flags;
__u16 rc_proto;
__u32 keycode;
__u64 scancode;
};
成員
timestamp使用 CLOCK_MONOTONIC 解碼紅外訊號時的納秒時間戳。
flags對於傳輸應為 0。當接收掃描碼時,可以根據協議設定 LIRC_SCANCODE_FLAG_TOGGLE 或 LIRC_SCANCODE_FLAG_REPEAT
rc_proto請參閱
enum rc_protokeycode轉換後的鍵程式碼。對於傳輸設定為 0。
scancode接收或要傳送的掃描碼
-
enum rc_proto¶
遠端控制器協議
常量
RC_PROTO_UNKNOWN協議未知
RC_PROTO_OTHER協議已知但專有
RC_PROTO_RC5Philips RC5 協議
RC_PROTO_RC5X_20Philips RC5x 20 位協議
RC_PROTO_RC5_SZRC5 的 StreamZap 變體
RC_PROTO_JVCJVC 協議
RC_PROTO_SONY12Sony 12 位協議
RC_PROTO_SONY15Sony 15 位協議
RC_PROTO_SONY20Sony 20 位協議
RC_PROTO_NECNEC 協議
RC_PROTO_NECX擴充套件 NEC 協議
RC_PROTO_NEC32NEC 32 位協議
RC_PROTO_SANYOSanyo 協議
RC_PROTO_MCIR2_KBD類似 RC6 的 MCE 鍵盤
RC_PROTO_MCIR2_MSE類似 RC6 的 MCE 滑鼠
RC_PROTO_RC6_0Philips RC6-0-16 協議
RC_PROTO_RC6_6A_20Philips RC6-6A-20 協議
RC_PROTO_RC6_6A_24Philips RC6-6A-24 協議
RC_PROTO_RC6_6A_32Philips RC6-6A-32 協議
RC_PROTO_RC6_MCEMCE (Philips RC6-6A-32 子型別) 協議
RC_PROTO_SHARPSharp 協議
RC_PROTO_XMPXMP 協議
RC_PROTO_CECCEC 協議
RC_PROTO_IMONiMon Pad 協議
RC_PROTO_RCMM12RC-MM 協議 12 位
RC_PROTO_RCMM24RC-MM 協議 24 位
RC_PROTO_RCMM32RC-MM 協議 32 位
RC_PROTO_XBOX_DVDXbox DVD 電影播放套件協議
RC_PROTO_MAXenum rc_proto的最大值
6.4. 基於 BPF 的紅外解碼器¶
核心支援解碼最常見的 紅外協議,但有許多協議不受支援。為了支援這些協議,可以載入一個 BPF 程式來執行解碼。這隻能在支援讀取原始紅外訊號的 LIRC 裝置上完成。
首先,使用帶有 BPF_LOAD_PROG 引數的 bpf(2) 系統呼叫,必須載入 BPF_PROG_TYPE_LIRC_MODE2 型別的程式。一旦附加到 LIRC 裝置,就會在 LIRC 裝置上的每個脈衝、空間或超時事件中呼叫此程式。BPF 程式的上下文是指向無符號整數的指標,它是 LIRC_MODE_MODE2 值。當程式解碼掃描碼後,可以使用 BPF 函式 bpf_rc_keydown() 或 bpf_rc_repeat() 提交它。可以使用 bpf_rc_pointer_rel() 報告滑鼠或指標移動。
一旦您有了 BPF_PROG_TYPE_LIRC_MODE2 BPF 程式的檔案描述符,就可以使用 bpf(2) 系統呼叫將其附加到 LIRC 裝置。目標必須是 LIRC 裝置的檔案描述符,並且附加型別必須是 BPF_LIRC_MODE2。一次最多可以將 64 個 BPF 程式附加到單個 LIRC 裝置。