330 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
			
		
		
	
	
			330 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
 | 
						|
 | 
						|
.. _cec_pin_error_inj:
 | 
						|
 | 
						|
CEC Pin Framework Error Injection
 | 
						|
=================================
 | 
						|
 | 
						|
The CEC Pin Framework is a core CEC framework for CEC hardware that only
 | 
						|
has low-level support for the CEC bus. Most hardware today will have
 | 
						|
high-level CEC support where the hardware deals with driving the CEC bus,
 | 
						|
but some older devices aren't that fancy. However, this framework also
 | 
						|
allows you to connect the CEC pin to a GPIO on e.g. a Raspberry Pi and
 | 
						|
you have now made a CEC adapter.
 | 
						|
 | 
						|
What makes doing this so interesting is that since we have full control
 | 
						|
over the bus it is easy to support error injection. This is ideal to
 | 
						|
test how well CEC adapters can handle error conditions.
 | 
						|
 | 
						|
Currently only the cec-gpio driver (when the CEC line is directly
 | 
						|
connected to a pull-up GPIO line) and the AllWinner A10/A20 drm driver
 | 
						|
support this framework.
 | 
						|
 | 
						|
If ``CONFIG_CEC_PIN_ERROR_INJ`` is enabled, then error injection is available
 | 
						|
through debugfs. Specifically, in ``/sys/kernel/debug/cec/cecX/`` there is
 | 
						|
now an ``error-inj`` file.
 | 
						|
 | 
						|
.. note::
 | 
						|
 | 
						|
    The error injection commands are not a stable ABI and may change in the
 | 
						|
    future.
 | 
						|
 | 
						|
With ``cat error-inj`` you can see both the possible commands and the current
 | 
						|
error injection status::
 | 
						|
 | 
						|
	$ 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
 | 
						|
 | 
						|
You can write error injection commands to ``error-inj`` using
 | 
						|
``echo 'cmd' >error-inj`` or ``cat cmd.txt >error-inj``. The ``cat error-inj``
 | 
						|
output contains the current error commands. You can save the output to a file
 | 
						|
and use it as an input to ``error-inj`` later.
 | 
						|
 | 
						|
Basic Syntax
 | 
						|
------------
 | 
						|
 | 
						|
Leading spaces/tabs are ignored. If the next character is a ``#`` or the end
 | 
						|
of the line was reached, then the whole line is ignored. Otherwise a command
 | 
						|
is expected.
 | 
						|
 | 
						|
The error injection commands fall in two main groups: those relating to
 | 
						|
receiving CEC messages and those relating to transmitting CEC messages. In
 | 
						|
addition, there are commands to clear existing error injection commands and
 | 
						|
to create custom pulses on the CEC bus.
 | 
						|
 | 
						|
Most error injection commands can be executed for specific CEC opcodes or for
 | 
						|
all opcodes (``any``). Each command also has a 'mode' which can be ``off``
 | 
						|
(can be used to turn off an existing error injection command), ``once``
 | 
						|
(the default) which will trigger the error injection only once for the next
 | 
						|
received or transmitted message, ``always`` to always trigger the error
 | 
						|
injection and ``toggle`` to toggle the error injection on or off for every
 | 
						|
transmit or receive.
 | 
						|
 | 
						|
So '``any rx-nack``' will NACK the next received CEC message,
 | 
						|
'``any,always rx-nack``' will NACK all received CEC messages and
 | 
						|
'``0x82,toggle rx-nack``' will only NACK if an Active Source message was
 | 
						|
received and do that only for every other received message.
 | 
						|
 | 
						|
After an error was injected with mode ``once`` the error injection command
 | 
						|
is cleared automatically, so ``once`` is a one-time deal.
 | 
						|
 | 
						|
All combinations of ``<op>`` and error injection commands can co-exist. So
 | 
						|
this is fine::
 | 
						|
 | 
						|
	0x9e tx-add-bytes 1
 | 
						|
	0x9e tx-early-eom
 | 
						|
	0x9f tx-add-bytes 2
 | 
						|
	any rx-nack
 | 
						|
 | 
						|
All four error injection commands will be active simultaneously.
 | 
						|
 | 
						|
However, if the same ``<op>`` and command combination is specified,
 | 
						|
but with different arguments::
 | 
						|
 | 
						|
	0x9e tx-add-bytes 1
 | 
						|
	0x9e tx-add-bytes 2
 | 
						|
 | 
						|
Then the second will overwrite the first.
 | 
						|
 | 
						|
Clear Error Injections
 | 
						|
----------------------
 | 
						|
 | 
						|
``clear``
 | 
						|
    Clear all error injections.
 | 
						|
 | 
						|
``rx-clear``
 | 
						|
    Clear all receive error injections
 | 
						|
 | 
						|
``tx-clear``
 | 
						|
    Clear all transmit error injections
 | 
						|
 | 
						|
``<op> clear``
 | 
						|
    Clear all error injections for the given opcode.
 | 
						|
 | 
						|
``<op> rx-clear``
 | 
						|
    Clear all receive error injections for the given opcode.
 | 
						|
 | 
						|
``<op> tx-clear``
 | 
						|
    Clear all transmit error injections for the given opcode.
 | 
						|
 | 
						|
Receive Messages
 | 
						|
----------------
 | 
						|
 | 
						|
``<op>[,<mode>] rx-nack``
 | 
						|
    NACK broadcast messages and messages directed to this CEC adapter.
 | 
						|
    Every byte of the message will be NACKed in case the transmitter
 | 
						|
    keeps transmitting after the first byte was NACKed.
 | 
						|
 | 
						|
``<op>[,<mode>] rx-low-drive <bit>``
 | 
						|
    Force a Low Drive condition at this bit position. If <op> specifies
 | 
						|
    a specific CEC opcode then the bit position must be at least 18,
 | 
						|
    otherwise the opcode hasn't been received yet. This tests if the
 | 
						|
    transmitter can handle the Low Drive condition correctly and reports
 | 
						|
    the error correctly. Note that a Low Drive in the first 4 bits can also
 | 
						|
    be interpreted as an Arbitration Lost condition by the transmitter.
 | 
						|
    This is implementation dependent.
 | 
						|
 | 
						|
``<op>[,<mode>] rx-add-byte``
 | 
						|
    Add a spurious 0x55 byte to the received CEC message, provided
 | 
						|
    the message was 15 bytes long or less. This is useful to test
 | 
						|
    the high-level protocol since spurious bytes should be ignored.
 | 
						|
 | 
						|
``<op>[,<mode>] rx-remove-byte``
 | 
						|
    Remove the last byte from the received CEC message, provided it
 | 
						|
    was at least 2 bytes long. This is useful to test the high-level
 | 
						|
    protocol since messages that are too short should be ignored.
 | 
						|
 | 
						|
``<op>[,<mode>] rx-arb-lost <poll>``
 | 
						|
    Generate a POLL message to trigger an Arbitration Lost condition.
 | 
						|
    This command is only allowed for ``<op>`` values of ``next`` or ``all``.
 | 
						|
    As soon as a start bit has been received the CEC adapter will switch
 | 
						|
    to transmit mode and it will transmit a POLL message. By default this is
 | 
						|
    0x0f, but it can also be specified explicitly via the ``<poll>`` argument.
 | 
						|
 | 
						|
    This command can be used to test the Arbitration Lost condition in
 | 
						|
    the remote CEC transmitter. Arbitration happens when two CEC adapters
 | 
						|
    start sending a message at the same time. In that case the initiator
 | 
						|
    with the most leading zeroes wins and the other transmitter has to
 | 
						|
    stop transmitting ('Arbitration Lost'). This is very hard to test,
 | 
						|
    except by using this error injection command.
 | 
						|
 | 
						|
    This does not work if the remote CEC transmitter has logical address
 | 
						|
    0 ('TV') since that will always win.
 | 
						|
 | 
						|
Transmit Messages
 | 
						|
-----------------
 | 
						|
 | 
						|
``tx-ignore-nack-until-eom``
 | 
						|
    This setting changes the behavior of transmitting CEC messages. Normally
 | 
						|
    as soon as the receiver NACKs a byte the transmit will stop, but the
 | 
						|
    specification also allows that the full message is transmitted and only
 | 
						|
    at the end will the transmitter look at the ACK bit. This is not
 | 
						|
    recommended behavior since there is no point in keeping the CEC bus busy
 | 
						|
    for longer than is strictly needed. Especially given how slow the bus is.
 | 
						|
 | 
						|
    This setting can be used to test how well a receiver deals with
 | 
						|
    transmitters that ignore NACKs until the very end of the message.
 | 
						|
 | 
						|
``<op>[,<mode>] tx-no-eom``
 | 
						|
    Don't set the EOM bit. Normally the last byte of the message has the EOM
 | 
						|
    (End-Of-Message) bit set. With this command the transmit will just stop
 | 
						|
    without ever sending an EOM. This can be used to test how a receiver
 | 
						|
    handles this case. Normally receivers have a time-out after which
 | 
						|
    they will go back to the Idle state.
 | 
						|
 | 
						|
``<op>[,<mode>] tx-early-eom``
 | 
						|
    Set the EOM bit one byte too soon. This obviously only works for messages
 | 
						|
    of two bytes or more. The EOM bit will be set for the second-to-last byte
 | 
						|
    and not for the final byte. The receiver should ignore the last byte in
 | 
						|
    this case. Since the resulting message is likely to be too short for this
 | 
						|
    same reason the whole message is typically ignored. The receiver should be
 | 
						|
    in Idle state after the last byte was transmitted.
 | 
						|
 | 
						|
``<op>[,<mode>] tx-add-bytes <num>``
 | 
						|
    Append ``<num>`` (1-255) spurious bytes to the message. The extra bytes
 | 
						|
    have the value of the byte position in the message. So if you transmit a
 | 
						|
    two byte message (e.g. a Get CEC Version message) and add 2 bytes, then
 | 
						|
    the full message received by the remote CEC adapter is
 | 
						|
    ``0x40 0x9f 0x02 0x03``.
 | 
						|
 | 
						|
    This command can be used to test buffer overflows in the receiver. E.g.
 | 
						|
    what does it do when it receives more than the maximum message size of 16
 | 
						|
    bytes.
 | 
						|
 | 
						|
``<op>[,<mode>] tx-remove-byte``
 | 
						|
    Drop the last byte from the message, provided the message is at least
 | 
						|
    two bytes long. The receiver should ignore messages that are too short.
 | 
						|
 | 
						|
``<op>[,<mode>] tx-short-bit <bit>``
 | 
						|
    Make this bit period shorter than allowed. The bit position cannot be
 | 
						|
    an Ack bit.  If <op> specifies a specific CEC opcode then the bit position
 | 
						|
    must be at least 18, otherwise the opcode hasn't been received yet.
 | 
						|
    Normally the period of a data bit is between 2.05 and 2.75 milliseconds.
 | 
						|
    With this command the period of this bit is 1.8 milliseconds, this is
 | 
						|
    done by reducing the time the CEC bus is high. This bit period is less
 | 
						|
    than is allowed and the receiver should respond with a Low Drive
 | 
						|
    condition.
 | 
						|
 | 
						|
    This command is ignored for 0 bits in bit positions 0 to 3. This is
 | 
						|
    because the receiver also looks for an Arbitration Lost condition in
 | 
						|
    those first four bits and it is undefined what will happen if it
 | 
						|
    sees a too-short 0 bit.
 | 
						|
 | 
						|
``<op>[,<mode>] tx-long-bit <bit>``
 | 
						|
    Make this bit period longer than is valid. The bit position cannot be
 | 
						|
    an Ack bit.  If <op> specifies a specific CEC opcode then the bit position
 | 
						|
    must be at least 18, otherwise the opcode hasn't been received yet.
 | 
						|
    Normally the period of a data bit is between 2.05 and 2.75 milliseconds.
 | 
						|
    With this command the period of this bit is 2.9 milliseconds, this is
 | 
						|
    done by increasing the time the CEC bus is high.
 | 
						|
 | 
						|
    Even though this bit period is longer than is valid it is undefined what
 | 
						|
    a receiver will do. It might just accept it, or it might time out and
 | 
						|
    return to Idle state. Unfortunately the CEC specification is silent about
 | 
						|
    this.
 | 
						|
 | 
						|
    This command is ignored for 0 bits in bit positions 0 to 3. This is
 | 
						|
    because the receiver also looks for an Arbitration Lost condition in
 | 
						|
    those first four bits and it is undefined what will happen if it
 | 
						|
    sees a too-long 0 bit.
 | 
						|
 | 
						|
``<op>[,<mode>] tx-short-start``
 | 
						|
    Make this start bit period shorter than allowed. Normally the period of
 | 
						|
    a start bit is between 4.3 and 4.7 milliseconds. With this command the
 | 
						|
    period of the start bit is 4.1 milliseconds, this is done by reducing
 | 
						|
    the time the CEC bus is high. This start bit period is less than is
 | 
						|
    allowed and the receiver should return to Idle state when this is detected.
 | 
						|
 | 
						|
``<op>[,<mode>] tx-long-start``
 | 
						|
    Make this start bit period longer than is valid. Normally the period of
 | 
						|
    a start bit is between 4.3 and 4.7 milliseconds. With this command the
 | 
						|
    period of the start bit is 5 milliseconds, this is done by increasing
 | 
						|
    the time the CEC bus is high. This start bit period is more than is
 | 
						|
    valid and the receiver should return to Idle state when this is detected.
 | 
						|
 | 
						|
    Even though this start bit period is longer than is valid it is undefined
 | 
						|
    what a receiver will do. It might just accept it, or it might time out and
 | 
						|
    return to Idle state. Unfortunately the CEC specification is silent about
 | 
						|
    this.
 | 
						|
 | 
						|
``<op>[,<mode>] tx-last-bit <bit>``
 | 
						|
    Just stop transmitting after this bit.  If <op> specifies a specific CEC
 | 
						|
    opcode then the bit position must be at least 18, otherwise the opcode
 | 
						|
    hasn't been received yet. This command can be used to test how the receiver
 | 
						|
    reacts when a message just suddenly stops. It should time out and go back
 | 
						|
    to Idle state.
 | 
						|
 | 
						|
``<op>[,<mode>] tx-low-drive <bit>``
 | 
						|
    Force a Low Drive condition at this bit position. If <op> specifies a
 | 
						|
    specific CEC opcode then the bit position must be at least 18, otherwise
 | 
						|
    the opcode hasn't been received yet. This can be used to test how the
 | 
						|
    receiver handles Low Drive conditions. Note that if this happens at bit
 | 
						|
    positions 0-3 the receiver can interpret this as an Arbitration Lost
 | 
						|
    condition. This is implementation dependent.
 | 
						|
 | 
						|
Custom Pulses
 | 
						|
-------------
 | 
						|
 | 
						|
``tx-custom-low-usecs <usecs>``
 | 
						|
    This defines the duration in microseconds that the custom pulse pulls
 | 
						|
    the CEC line low. The default is 1000 microseconds.
 | 
						|
 | 
						|
``tx-custom-high-usecs <usecs>``
 | 
						|
    This defines the duration in microseconds that the custom pulse keeps the
 | 
						|
    CEC line high (unless another CEC adapter pulls it low in that time).
 | 
						|
    The default is 1000 microseconds. The total period of the custom pulse is
 | 
						|
    ``tx-custom-low-usecs + tx-custom-high-usecs``.
 | 
						|
 | 
						|
``<op>[,<mode>] tx-custom-bit <bit>``
 | 
						|
    Send the custom bit instead of a regular data bit. The bit position cannot
 | 
						|
    be an Ack bit.  If <op> specifies a specific CEC opcode then the bit
 | 
						|
    position must be at least 18, otherwise the opcode hasn't been received yet.
 | 
						|
 | 
						|
``<op>[,<mode>] tx-custom-start``
 | 
						|
    Send the custom bit instead of a regular start bit.
 | 
						|
 | 
						|
``tx-custom-pulse``
 | 
						|
    Transmit a single custom pulse as soon as the CEC bus is idle.
 |