3. CEC 引脚框架错误注入

CEC 引脚框架是核心 CEC 框架,适用于仅对 CEC 总线具有底层支持的 CEC 硬件。如今,大多数硬件都将具有高级 CEC 支持,硬件负责驱动 CEC 总线,但一些较旧的设备没有那么高级。但是,此框架还允许您将 CEC 引脚连接到例如 Raspberry Pi 上的 GPIO,并且您现在已经制作了一个 CEC 适配器。

这样做如此有趣的原因是,由于我们可以完全控制总线,因此很容易支持错误注入。这非常适合测试 CEC 适配器处理错误情况的能力。

目前只有 cec-gpio 驱动程序(当 CEC 线直接连接到上拉 GPIO 线时)和 AllWinner A10/A20 drm 驱动程序支持此框架。

如果启用了 CONFIG_CEC_PIN_ERROR_INJ,则可以通过 debugfs 进行错误注入。具体来说,在 /sys/kernel/debug/cec/cecX/ 中现在有一个 error-inj 文件。

注意

错误注入命令不是稳定的 ABI,将来可能会发生变化。

使用 cat error-inj,您可以查看可能的命令和当前的错误注入状态

$ cat /sys/kernel/debug/cec/cec0/error-inj
# Clear error injections:
#   clear          clear all rx and tx error injections
#   rx-clear       clear all rx error injections
#   tx-clear       clear all tx error injections
#   <op> clear     clear all rx and tx error injections for <op>
#   <op> rx-clear  clear all rx error injections for <op>
#   <op> tx-clear  clear all tx error injections for <op>
#
# RX error injection:
#   <op>[,<mode>] rx-nack              NACK the message instead of sending an ACK
#   <op>[,<mode>] rx-low-drive <bit>   force a low-drive condition at this bit position
#   <op>[,<mode>] rx-add-byte          add a spurious byte to the received CEC message
#   <op>[,<mode>] rx-remove-byte       remove the last byte from the received CEC message
#    any[,<mode>] rx-arb-lost [<poll>] generate a POLL message to trigger an arbitration lost
#
# TX error injection settings:
#   tx-ignore-nack-until-eom           ignore early NACKs until EOM
#   tx-custom-low-usecs <usecs>        define the 'low' time for the custom pulse
#   tx-custom-high-usecs <usecs>       define the 'high' time for the custom pulse
#   tx-custom-pulse                    transmit the custom pulse once the bus is idle
#
# TX error injection:
#   <op>[,<mode>] tx-no-eom            don't set the EOM bit
#   <op>[,<mode>] tx-early-eom         set the EOM bit one byte too soon
#   <op>[,<mode>] tx-add-bytes <num>   append <num> (1-255) spurious bytes to the message
#   <op>[,<mode>] tx-remove-byte       drop the last byte from the message
#   <op>[,<mode>] tx-short-bit <bit>   make this bit shorter than allowed
#   <op>[,<mode>] tx-long-bit <bit>    make this bit longer than allowed
#   <op>[,<mode>] tx-custom-bit <bit>  send the custom pulse instead of this bit
#   <op>[,<mode>] tx-short-start       send a start pulse that's too short
#   <op>[,<mode>] tx-long-start        send a start pulse that's too long
#   <op>[,<mode>] tx-custom-start      send the custom pulse instead of the start pulse
#   <op>[,<mode>] tx-last-bit <bit>    stop sending after this bit
#   <op>[,<mode>] tx-low-drive <bit>   force a low-drive condition at this bit position
#
# <op>       CEC message opcode (0-255) or 'any'
# <mode>     'once' (default), 'always', 'toggle' or 'off'
# <bit>      CEC message bit (0-159)
#            10 bits per 'byte': bits 0-7: data, bit 8: EOM, bit 9: ACK
# <poll>     CEC poll message used to test arbitration lost (0x00-0xff, default 0x0f)
# <usecs>    microseconds (0-10000000, default 1000)

clear

您可以使用 echo 'cmd' >error-injcat cmd.txt >error-inj 将错误注入命令写入 error-injcat error-inj 输出包含当前的错误命令。您可以将输出保存到文件中,稍后将其用作 error-inj 的输入。

3.1. 基本语法

前导空格/制表符将被忽略。如果下一个字符是 # 或到达行尾,则将忽略整行。否则,将需要一个命令。

错误注入命令分为两个主要组:与接收 CEC 消息相关的命令和与发送 CEC 消息相关的命令。此外,还有一些命令可以清除现有的错误注入命令,并在 CEC 总线上创建自定义脉冲。

大多数错误注入命令可以针对特定的 CEC 操作码或所有操作码 (any) 执行。每个命令还具有一个“模式”,可以是 off(可用于关闭现有的错误注入命令)、once(默认值),它将仅针对下一个接收或发送的消息触发一次错误注入,always 将始终触发错误注入,toggle 将为每次发送或接收打开或关闭错误注入。

因此,'any rx-nack' 将 NACK 下一个接收到的 CEC 消息,'any,always rx-nack' 将 NACK 所有接收到的 CEC 消息,'0x82,toggle rx-nack' 仅当收到 Active Source 消息时才会 NACK,并且仅对每隔一个接收到的消息执行此操作。

在以 once 模式注入错误后,错误注入命令将自动清除,因此 once 是一次性交易。

<op> 和错误注入命令的所有组合都可以共存。所以这是没问题的

0x9e tx-add-bytes 1
0x9e tx-early-eom
0x9f tx-add-bytes 2
any rx-nack

所有四个错误注入命令将同时处于活动状态。

但是,如果指定了相同的 <op> 和命令组合,但具有不同的参数

0x9e tx-add-bytes 1
0x9e tx-add-bytes 2

那么第二个将覆盖第一个。

3.2. 清除错误注入

clear

清除所有错误注入。

rx-clear

清除所有接收错误注入

tx-clear

清除所有发送错误注入

<op> clear

清除给定操作码的所有错误注入。

<op> rx-clear

清除给定操作码的所有接收错误注入。

<op> tx-clear

清除给定操作码的所有发送错误注入。

3.3. 接收消息

<op>[,<mode>] rx-nack

NACK 广播消息和定向到此 CEC 适配器的消息。如果发送器在第一个字节被 NACK 后继续发送,则消息的每个字节都将被 NACK。

<op>[,<mode>] rx-low-drive <bit>

在此位位置强制执行 Low Drive 条件。如果 <op> 指定特定的 CEC 操作码,则该位位置必须至少为 18,否则尚未收到该操作码。这将测试发送器是否可以正确处理 Low Drive 条件并正确报告错误。请注意,发送器也可以将前 4 位中的 Low Drive 解释为 Arbitration Lost 条件。这是与实现相关的。

<op>[,<mode>] rx-add-byte

向接收到的 CEC 消息添加一个伪造的 0x55 字节,前提是消息长度为 15 个字节或更少。这对于测试高级协议很有用,因为应该忽略伪造字节。

<op>[,<mode>] rx-remove-byte

从接收到的 CEC 消息中删除最后一个字节,前提是该消息至少为 2 个字节长。这对于测试高级协议很有用,因为应忽略太短的消息。

<op>[,<mode>] rx-arb-lost <poll>

生成 POLL 消息以触发 Arbitration Lost 条件。此命令仅允许用于 <op> 值为 nextall。一旦收到起始位,CEC 适配器将切换到发送模式,并发送一个 POLL 消息。默认情况下,这是 0x0f,但也可以通过 <poll> 参数显式指定。

此命令可用于测试远程 CEC 发送器中的 Arbitration Lost 条件。当两个 CEC 适配器同时开始发送消息时,会发生仲裁。在这种情况下,前导零最多的发起者获胜,另一个发送器必须停止发送(“Arbitration Lost”)。这很难测试,除非使用此错误注入命令。

如果远程 CEC 发送器的逻辑地址为 0 (“TV”),则此命令不起作用,因为它将始终获胜。

3.4. 发送消息

tx-ignore-nack-until-eom

此设置更改了发送 CEC 消息的行为。通常,一旦接收器 NACK 一个字节,发送就会停止,但规范也允许发送完整的消息,并且只有在最后,发送器才会查看 ACK 位。不建议这样做,因为没有必要使 CEC 总线占用时间超过严格所需的长度。尤其是考虑到总线的速度有多慢。

此设置可用于测试接收器如何处理忽略 NACK 直到消息结尾的发送器。

<op>[,<mode>] tx-no-eom

不要设置 EOM 位。通常,消息的最后一个字节设置了 EOM(消息结束)位。使用此命令,发送将停止,而不会发送 EOM。这可用于测试接收器如何处理这种情况。通常,接收器有一个超时时间,在此之后它们将返回到空闲状态。

<op>[,<mode>] tx-early-eom

提前一个字节设置 EOM 位。这显然仅适用于两个或多个字节的消息。EOM 位将为倒数第二个字节设置,而不是为最后一个字节设置。在这种情况下,接收器应忽略最后一个字节。由于生成的消息可能由于同样的理由而太短,因此通常会忽略整个消息。接收器在发送最后一个字节后应处于空闲状态。

<op>[,<mode>] tx-add-bytes <num>

<num> (1-255) 个伪造字节附加到消息。额外的字节的值是消息中的字节位置。因此,如果您发送一个两字节的消息(例如,一个 Get CEC Version 消息)并添加 2 个字节,则远程 CEC 适配器接收到的完整消息是 0x40 0x9f 0x02 0x03

此命令可用于测试接收器中的缓冲区溢出。例如,当它收到超过最大消息大小 16 个字节时,它会做什么。

<op>[,<mode>] tx-remove-byte

从消息中删除最后一个字节,前提是该消息至少为两个字节长。接收器应忽略太短的消息。

<op>[,<mode>] tx-short-bit <bit>

使此位周期短于允许的长度。位位置不能是 Ack 位。如果 <op> 指定特定的 CEC 操作码,则该位位置必须至少为 18,否则尚未收到该操作码。通常,数据位的周期在 2.05 到 2.75 毫秒之间。使用此命令,此位的周期为 1.8 毫秒,这是通过减少 CEC 总线处于高电平的时间来完成的。此位周期小于允许的长度,接收器应以 Low Drive 条件响应。

对于位位置 0 到 3 中的 0 位,此命令将被忽略。这是因为接收器还在前四位中查找 Arbitration Lost 条件,并且如果它看到一个太短的 0 位,会发生什么情况是未定义的。

<op>[,<mode>] tx-long-bit <bit>

使此位周期长于有效周期。位位置不能是 Ack 位。如果 <op> 指定特定的 CEC 操作码,则该位位置必须至少为 18,否则尚未收到该操作码。通常,数据位的周期在 2.05 到 2.75 毫秒之间。使用此命令,此位的周期为 2.9 毫秒,这是通过增加 CEC 总线处于高电平的时间来完成的。

即使此位周期长于有效周期,接收器会做什么也是未定义的。它可能只是接受它,或者它可能会超时并返回到空闲状态。不幸的是,CEC 规范对此保持沉默。

对于位位置 0 到 3 中的 0 位,此命令将被忽略。这是因为接收器还在前四位中查找 Arbitration Lost 条件,并且如果它看到一个太长的 0 位,会发生什么情况是未定义的。

<op>[,<mode>] tx-short-start

使此起始位周期短于允许的长度。通常,起始位的周期在 4.3 到 4.7 毫秒之间。使用此命令,起始位的周期为 4.1 毫秒,这是通过减少 CEC 总线处于高电平的时间来完成的。此起始位周期小于允许的长度,当检测到此情况时,接收器应返回到空闲状态。

<op>[,<mode>] tx-long-start

使此起始位周期长于有效周期。通常,起始位的周期在 4.3 到 4.7 毫秒之间。使用此命令,起始位的周期为 5 毫秒,这是通过增加 CEC 总线处于高电平的时间来完成的。此起始位周期大于有效周期,当检测到此情况时,接收器应返回到空闲状态。

即使此起始位周期长于有效周期,接收器会做什么也是未定义的。它可能只是接受它,或者它可能会超时并返回到空闲状态。不幸的是,CEC 规范对此保持沉默。

<op>[,<mode>] tx-last-bit <bit>

在此位之后停止发送。如果 <op> 指定特定的 CEC 操作码,则该位位置必须至少为 18,否则尚未收到该操作码。此命令可用于测试当消息突然停止时接收器如何反应。它应该超时并返回到空闲状态。

<op>[,<mode>] tx-low-drive <bit>

在此位位置强制执行 Low Drive 条件。如果 <op> 指定特定的 CEC 操作码,则该位位置必须至少为 18,否则尚未收到该操作码。这可用于测试接收器如何处理 Low Drive 条件。请注意,如果这发生在位位置 0-3 处,则接收器可以将此解释为 Arbitration Lost 条件。这是与实现相关的。

3.5. 自定义脉冲

tx-custom-low-usecs <usecs>

这定义了自定义脉冲将 CEC 线拉低的持续时间,以微秒为单位。默认值为 1000 微秒。

tx-custom-high-usecs <usecs>

这定义了自定义脉冲保持 CEC 线高电平的持续时间,以微秒为单位(除非另一个 CEC 适配器在该时间内将其拉低)。默认值为 1000 微秒。自定义脉冲的总周期为 tx-custom-low-usecs + tx-custom-high-usecs

<op>[,<mode>] tx-custom-bit <bit>

发送自定义位而不是常规数据位。位位置不能是 Ack 位。如果 <op> 指定特定的 CEC 操作码,则该位位置必须至少为 18,否则尚未收到该操作码。

<op>[,<mode>] tx-custom-start

发送自定义位而不是常规起始位。

tx-custom-pulse

一旦 CEC 总线空闲,就发送一个自定义脉冲。