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 ' 仅在接收到活动源消息时才会 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>

在此位位置强制执行低驱动条件。如果 <op> 指定特定的 CEC 操作码,则位位置必须至少为 18,否则尚未接收到该操作码。这将测试发送器是否可以正确处理低驱动条件并正确报告错误。请注意,发送器也可能将前 4 位中的低驱动解释为仲裁丢失条件。这取决于具体实现。

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

将一个虚假的 0x55 字节添加到接收到的 CEC 消息中,前提是该消息的长度为 15 个字节或更短。这有助于测试高层协议,因为应该忽略虚假字节。

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

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

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

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

此命令可用于测试远程 CEC 发送器中的仲裁丢失条件。当两个 CEC 适配器同时开始发送消息时会发生仲裁。在这种情况下,具有最多前导零的启动器获胜,而另一个发送器必须停止发送(“仲裁丢失”)。除了使用此错误注入命令外,很难对此进行测试。

如果远程 CEC 发送器的逻辑地址为 0(“电视”),则此方法不起作用,因为它始终会获胜。

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) 个虚假字节附加到消息。额外的字节具有消息中字节位置的值。因此,如果发送两个字节的消息(例如,获取 CEC 版本消息)并添加 2 个字节,则远程 CEC 适配器接收到的完整消息为 0x40 0x9f 0x02 0x03

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

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

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

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

使该位周期比允许的短。该位的位置不能是应答位。如果 <op> 指定了特定的 CEC 操作码,则该位的位置必须至少为 18,否则尚未收到操作码。通常,数据位的周期在 2.05 到 2.75 毫秒之间。使用此命令,该位的周期为 1.8 毫秒,这是通过减少 CEC 总线保持高电平的时间来实现的。此位周期小于允许值,接收器应以低驱动条件响应。

对于位位置 0 到 3 中的 0 位,此命令将被忽略。这是因为接收器也会在前四个位中寻找仲裁丢失条件,并且如果它看到一个太短的 0 位,则会发生什么是不确定的。

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

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

即使此位周期比有效值长,接收器将执行什么操作也是不确定的。它可能只是接受它,也可能超时并返回到空闲状态。不幸的是,CEC 规范对此保持沉默。

对于位位置 0 到 3 中的 0 位,此命令将被忽略。这是因为接收器也会在前四个位中寻找仲裁丢失条件,并且如果它看到一个太长的 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>

在此位位置强制执行低驱动条件。如果 <op> 指定了特定的 CEC 操作码,则该位的位置必须至少为 18,否则尚未收到操作码。这可用于测试接收器如何处理低驱动条件。请注意,如果这种情况发生在位位置 0-3,则接收器可以将其解释为仲裁丢失条件。这取决于具体实现。

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>

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

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

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

tx-custom-pulse

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