요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
.. c:namespace:: CEC
.. _CEC_TRANSMIT:
.. _CEC_RECEIVE:
***********************************
ioctls CEC_RECEIVE and CEC_TRANSMIT
***********************************
Name
====
CEC_RECEIVE, CEC_TRANSMIT - Receive or transmit a CEC message
Synopsis
========
.. c:macro:: CEC_RECEIVE
``int ioctl(int fd, CEC_RECEIVE, struct cec_msg *argp)``
.. c:macro:: CEC_TRANSMIT
``int ioctl(int fd, CEC_TRANSMIT, struct cec_msg *argp)``
Arguments
=========
``fd``
File descriptor returned by :c:func:`open()`.
``argp``
Pointer to struct cec_msg.
Description
===========
To receive a CEC message the application has to fill in the
``timeout`` field of struct :c:type:`cec_msg` and pass it to
:ref:`ioctl CEC_RECEIVE <CEC_RECEIVE>`.
If the file descriptor is in non-blocking mode and there are no received
messages pending, then it will return -1 and set errno to the ``EAGAIN``
error code. If the file descriptor is in blocking mode and ``timeout``
is non-zero and no message arrived within ``timeout`` milliseconds, then
it will return -1 and set errno to the ``ETIMEDOUT`` error code.
A received message can be:
1. a message received from another CEC device (the ``sequence`` field will
be 0, ``tx_status`` will be 0 and ``rx_status`` will be non-zero).
2. the transmit result of an earlier non-blocking transmit (the ``sequence``
field will be non-zero, ``tx_status`` will be non-zero and ``rx_status``
will be 0).
3. the reply to an earlier non-blocking transmit (the ``sequence`` field will
be non-zero, ``tx_status`` will be 0 and ``rx_status`` will be non-zero).
To send a CEC message the application has to fill in the struct
:c:type:`cec_msg` and pass it to :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>`.
The :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>` is only available if
``CEC_CAP_TRANSMIT`` is set. If there is no more room in the transmit
queue, then it will return -1 and set errno to the ``EBUSY`` error code.
The transmit queue has enough room for 18 messages (about 1 second worth
of 2-byte messages). Note that the CEC kernel framework will also reply
to core messages (see :ref:`cec-core-processing`), so it is not a good
idea to fully fill up the transmit queue.
If the file descriptor is in non-blocking mode then the transmit will
return 0 and the result of the transmit will be available via
:ref:`ioctl CEC_RECEIVE <CEC_RECEIVE>` once the transmit has finished.
If a non-blocking transmit also specified waiting for a reply, then
the reply will arrive in a later message. The ``sequence`` field can
be used to associate both transmit results and replies with the original
transmit.
Normally calling :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>` when the physical
address is invalid (due to e.g. a disconnect) will return ``ENONET``.
However, the CEC specification allows sending messages from 'Unregistered' to
'TV' when the physical address is invalid since some TVs pull the hotplug detect
pin of the HDMI connector low when they go into standby, or when switching to
another input.
When the hotplug detect pin goes low the EDID disappears, and thus the
physical address, but the cable is still connected and CEC still works.
In order to detect/wake up the device it is allowed to send poll and 'Image/Text
View On' messages from initiator 0xf ('Unregistered') to destination 0 ('TV').
.. tabularcolumns:: |p{1.0cm}|p{3.5cm}|p{12.8cm}|
.. c:type:: cec_msg
.. cssclass:: longtable
.. flat-table:: struct cec_msg
:header-rows: 0
:stub-columns: 0
:widths: 1 1 16
* - __u64
- ``tx_ts``
- Timestamp in ns of when the last byte of the message was transmitted.
The timestamp has been taken from the ``CLOCK_MONOTONIC`` clock. To access
the same clock from userspace use :c:func:`clock_gettime`.
* - __u64
- ``rx_ts``
- Timestamp in ns of when the last byte of the message was received.
The timestamp has been taken from the ``CLOCK_MONOTONIC`` clock. To access
the same clock from userspace use :c:func:`clock_gettime`.
* - __u32
- ``len``
- The length of the message. For :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>` this is filled in
by the application. The driver will fill this in for
:ref:`ioctl CEC_RECEIVE <CEC_RECEIVE>`. For :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>` it will be
filled in by the driver with the length of the reply message if ``reply`` was set.
* - __u32
- ``timeout``
- The timeout in milliseconds. This is the time the device will wait
for a message to be received before timing out. If it is set to 0,
then it will wait indefinitely when it is called by :ref:`ioctl CEC_RECEIVE <CEC_RECEIVE>`.
If it is 0 and it is called by :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>`,
then it will be replaced by 1000 if the ``reply`` is non-zero or
ignored if ``reply`` is 0.
* - __u32
- ``sequence``
- A non-zero sequence number is automatically assigned by the CEC framework
for all transmitted messages. It is used by the CEC framework when it queues
the transmit result for a non-blocking transmit. This allows the application
to associate the received message with the original transmit.
In addition, if a non-blocking transmit will wait for a reply (ii.e. ``timeout``
was not 0), then the ``sequence`` field of the reply will be set to the sequence
value of the original transmit. This allows the application to associate the
received message with the original transmit.
* - __u32
- ``flags``
- Flags. See :ref:`cec-msg-flags` for a list of available flags.
* - __u8
- ``msg[16]``
- The message payload. For :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>` this is filled in by the
application. The driver will fill this in for :ref:`ioctl CEC_RECEIVE <CEC_RECEIVE>`.
For :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>` it will be filled in by the driver with
the payload of the reply message if ``timeout`` was set.
* - __u8
- ``reply``
- Wait until this message is replied. If ``reply`` is 0 and the
``timeout`` is 0, then don't wait for a reply but return after
transmitting the message. Ignored by :ref:`ioctl CEC_RECEIVE <CEC_RECEIVE>`.
The case where ``reply`` is 0 (this is the opcode for the Feature Abort
message) and ``timeout`` is non-zero is specifically allowed to make it
possible to send a message and wait up to ``timeout`` milliseconds for a
Feature Abort reply. In this case ``rx_status`` will either be set
to :ref:`CEC_RX_STATUS_TIMEOUT <CEC-RX-STATUS-TIMEOUT>` or
:ref:`CEC_RX_STATUS_FEATURE_ABORT <CEC-RX-STATUS-FEATURE-ABORT>`.
If the transmitter message is ``CEC_MSG_INITIATE_ARC`` then the ``reply``
values ``CEC_MSG_REPORT_ARC_INITIATED`` and ``CEC_MSG_REPORT_ARC_TERMINATED``
are processed differently: either value will match both possible replies.
The reason is that the ``CEC_MSG_INITIATE_ARC`` message is the only CEC
message that has two possible replies other than Feature Abort. The
``reply`` field will be updated with the actual reply so that it is
synchronized with the contents of the received message.
* - __u8
- ``rx_status``
- The status bits of the received message. See
:ref:`cec-rx-status` for the possible status values.
* - __u8
- ``tx_status``
- The status bits of the transmitted message. See
:ref:`cec-tx-status` for the possible status values.
When calling :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>` in non-blocking mode,
this field will be 0 if the transmit started, or non-0 if the transmit
result is known immediately. The latter would be the case when attempting
to transmit a Poll message to yourself. That results in a
:ref:`CEC_TX_STATUS_NACK <CEC-TX-STATUS-NACK>` without ever actually
transmitting the Poll message.
* - __u8
- ``tx_arb_lost_cnt``
- A counter of the number of transmit attempts that resulted in the
Arbitration Lost error. This is only set if the hardware supports
this, otherwise it is always 0. This counter is only valid if the
:ref:`CEC_TX_STATUS_ARB_LOST <CEC-TX-STATUS-ARB-LOST>` status bit is set.
* - __u8
- ``tx_nack_cnt``
- A counter of the number of transmit attempts that resulted in the
Not Acknowledged error. This is only set if the hardware supports
this, otherwise it is always 0. This counter is only valid if the
:ref:`CEC_TX_STATUS_NACK <CEC-TX-STATUS-NACK>` status bit is set.
* - __u8
- ``tx_low_drive_cnt``
- A counter of the number of transmit attempts that resulted in the
Arbitration Lost error. This is only set if the hardware supports
this, otherwise it is always 0. This counter is only valid if the
:ref:`CEC_TX_STATUS_LOW_DRIVE <CEC-TX-STATUS-LOW-DRIVE>` status bit is set.
* - __u8
- ``tx_error_cnt``
- A counter of the number of transmit errors other than Arbitration
Lost or Not Acknowledged. This is only set if the hardware
supports this, otherwise it is always 0. This counter is only
valid if the :ref:`CEC_TX_STATUS_ERROR <CEC-TX-STATUS-ERROR>` status bit is set.
.. tabularcolumns:: |p{6.2cm}|p{1.0cm}|p{10.1cm}|
.. _cec-msg-flags:
.. flat-table:: Flags for struct cec_msg
:header-rows: 0
:stub-columns: 0
:widths: 3 1 4
* .. _`CEC-MSG-FL-REPLY-TO-FOLLOWERS`:
- ``CEC_MSG_FL_REPLY_TO_FOLLOWERS``
- 1
- If a CEC transmit expects a reply, then by default that reply is only sent to
the filehandle that called :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>`. If this
flag is set, then the reply is also sent to all followers, if any. If the
filehandle that called :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>` is also a
follower, then that filehandle will receive the reply twice: once as the
result of the :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>`, and once via
:ref:`ioctl CEC_RECEIVE <CEC_RECEIVE>`.
* .. _`CEC-MSG-FL-RAW`:
- ``CEC_MSG_FL_RAW``
- 2
- Normally CEC messages are validated before transmitting them. If this
flag is set when :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>` is called,
then no validation takes place and the message is transmitted as-is.
This is useful when debugging CEC issues.
This flag is only allowed if the process has the ``CAP_SYS_RAWIO``
capability. If that is not set, then the ``EPERM`` error code is
returned.
* .. _`CEC-MSG-FL-REPLY-VENDOR-ID`:
- ``CEC_MSG_FL_REPLY_VENDOR_ID``
- 4
- This flag is only available if the ``CEC_CAP_REPLY_VENDOR_ID`` capability
is set. If this flag is set, then the reply is expected to consist of
the ``CEC_MSG_VENDOR_COMMAND_WITH_ID`` opcode followed by the Vendor ID
(in bytes 1-4 of the message), followed by the ``struct cec_msg``
``reply`` field.
Note that this assumes that the byte after the Vendor ID is a
vendor-specific opcode.
This flag makes it easier to wait for replies to vendor commands.
.. tabularcolumns:: |p{5.6cm}|p{0.9cm}|p{10.8cm}|
.. _cec-tx-status:
.. flat-table:: CEC Transmit Status
:header-rows: 0
:stub-columns: 0
:widths: 3 1 16
* .. _`CEC-TX-STATUS-OK`:
- ``CEC_TX_STATUS_OK``
- 0x01
- The message was transmitted successfully. This is mutually
exclusive with :ref:`CEC_TX_STATUS_MAX_RETRIES <CEC-TX-STATUS-MAX-RETRIES>`.
Other bits can still be set if earlier attempts met with failure before
the transmit was eventually successful.
* .. _`CEC-TX-STATUS-ARB-LOST`:
- ``CEC_TX_STATUS_ARB_LOST``
- 0x02
- CEC line arbitration was lost, i.e. another transmit started at the
same time with a higher priority. Optional status, not all hardware
can detect this error condition.
* .. _`CEC-TX-STATUS-NACK`:
- ``CEC_TX_STATUS_NACK``
- 0x04
- Message was not acknowledged. Note that some hardware cannot tell apart
a 'Not Acknowledged' status from other error conditions, i.e. the result
of a transmit is just OK or FAIL. In that case this status will be
returned when the transmit failed.
* .. _`CEC-TX-STATUS-LOW-DRIVE`:
- ``CEC_TX_STATUS_LOW_DRIVE``
- 0x08
- Low drive was detected on the CEC bus. This indicates that a
follower detected an error on the bus and requests a
retransmission. Optional status, not all hardware can detect this
error condition.
* .. _`CEC-TX-STATUS-ERROR`:
- ``CEC_TX_STATUS_ERROR``
- 0x10
- Some error occurred. This is used for any errors that do not fit
``CEC_TX_STATUS_ARB_LOST`` or ``CEC_TX_STATUS_LOW_DRIVE``, either because
the hardware could not tell which error occurred, or because the hardware
tested for other conditions besides those two. Optional status.
* .. _`CEC-TX-STATUS-MAX-RETRIES`:
- ``CEC_TX_STATUS_MAX_RETRIES``
- 0x20
- The transmit failed after one or more retries. This status bit is
mutually exclusive with :ref:`CEC_TX_STATUS_OK <CEC-TX-STATUS-OK>`.
Other bits can still be set to explain which failures were seen.
* .. _`CEC-TX-STATUS-ABORTED`:
- ``CEC_TX_STATUS_ABORTED``
- 0x40
- The transmit was aborted due to an HDMI disconnect, or the adapter
was unconfigured, or a transmit was interrupted, or the driver
returned an error when attempting to start a transmit.
* .. _`CEC-TX-STATUS-TIMEOUT`:
- ``CEC_TX_STATUS_TIMEOUT``
- 0x80
- The transmit timed out. This should not normally happen and this
indicates a driver problem.
.. tabularcolumns:: |p{5.6cm}|p{0.9cm}|p{10.8cm}|
.. _cec-rx-status:
.. flat-table:: CEC Receive Status
:header-rows: 0
:stub-columns: 0
:widths: 3 1 16
* .. _`CEC-RX-STATUS-OK`:
- ``CEC_RX_STATUS_OK``
- 0x01
- The message was received successfully.
* .. _`CEC-RX-STATUS-TIMEOUT`:
- ``CEC_RX_STATUS_TIMEOUT``
- 0x02
- The reply to an earlier transmitted message timed out.
* .. _`CEC-RX-STATUS-FEATURE-ABORT`:
- ``CEC_RX_STATUS_FEATURE_ABORT``
- 0x04
- The message was received successfully but the reply was
``CEC_MSG_FEATURE_ABORT``. This status is only set if this message
was the reply to an earlier transmitted message.
* .. _`CEC-RX-STATUS-ABORTED`:
- ``CEC_RX_STATUS_ABORTED``
- 0x08
- The wait for a reply to an earlier transmitted message was aborted
because the HDMI cable was disconnected, the adapter was unconfigured
or the :ref:`CEC_TRANSMIT <CEC_RECEIVE>` that waited for a
reply was interrupted.
Return Value
============
On success 0 is returned, on error -1 and the ``errno`` variable is set
appropriately. The generic error codes are described at the
:ref:`Generic Error Codes <gen-errors>` chapter.
The :ref:`ioctl CEC_RECEIVE <CEC_RECEIVE>` can return the following
error codes:
EAGAIN
No messages are in the receive queue, and the filehandle is in non-blocking mode.
ETIMEDOUT
The ``timeout`` was reached while waiting for a message.
ERESTARTSYS
The wait for a message was interrupted (e.g. by Ctrl-C).
The :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>` can return the following
error codes:
ENOTTY
The ``CEC_CAP_TRANSMIT`` capability wasn't set, so this ioctl is not supported.
EPERM
The CEC adapter is not configured, i.e. :ref:`ioctl CEC_ADAP_S_LOG_ADDRS <CEC_ADAP_S_LOG_ADDRS>`
has never been called, or ``CEC_MSG_FL_RAW`` was used from a process that
did not have the ``CAP_SYS_RAWIO`` capability.
ENONET
The CEC adapter is not configured, i.e. :ref:`ioctl CEC_ADAP_S_LOG_ADDRS <CEC_ADAP_S_LOG_ADDRS>`
was called, but the physical address is invalid so no logical address was claimed.
An exception is made in this case for transmits from initiator 0xf ('Unregistered')
to destination 0 ('TV'). In that case the transmit will proceed as usual.
EBUSY
Another filehandle is in exclusive follower or initiator mode, or the filehandle
is in mode ``CEC_MODE_NO_INITIATOR``. This is also returned if the transmit
queue is full.
EINVAL
The contents of struct :c:type:`cec_msg` is invalid.
ERESTARTSYS
The wait for a successful transmit was interrupted (e.g. by Ctrl-C).
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
이름, 선언과 인자
1-37`CEC_RECEIVE`와 `CEC_TRANSMIT`은 CEC message를 각각 수신하고 송신하는 ioctl입니다. 두 호출은 모두 `struct cec_msg` 하나로 message payload, timeout, reply 조건과 결과 status를 주고받습니다.
호출 형식은 `int ioctl(int fd, CEC_RECEIVE, struct cec_msg *argp)`와 `int ioctl(int fd, CEC_TRANSMIT, struct cec_msg *argp)`입니다.
`fd`는 `open()`이 반환한 file descriptor이고 `argp`는 `struct cec_msg`를 가리키는 pointer입니다.
동일한 구조체를 사용하지만 입력·출력 필드의 의미가 request에 따라 달라집니다.
.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
.. c:namespace:: CEC
.. _CEC_TRANSMIT:
.. _CEC_RECEIVE:
***********************************
ioctls CEC_RECEIVE and CEC_TRANSMIT
***********************************
Name
====
CEC_RECEIVE, CEC_TRANSMIT - Receive or transmit a CEC message
Synopsis
========
.. c:macro:: CEC_RECEIVE
``int ioctl(int fd, CEC_RECEIVE, struct cec_msg *argp)``
.. c:macro:: CEC_TRANSMIT
``int ioctl(int fd, CEC_TRANSMIT, struct cec_msg *argp)``
Arguments
=========
``fd``
File descriptor returned by :c:func:`open()`.
``argp``
Pointer to struct cec_msg.
Description
===========
수신·송신과 비동기 결과
38-74수신하려면 응용 프로그램이 `struct cec_msg.timeout`을 채워 `CEC_RECEIVE`에 전달합니다. nonblocking descriptor에 pending message가 없으면 -1과 `EAGAIN`을 반환합니다. blocking descriptor에서 `timeout`이 0이 아니고 지정한 millisecond 안에 message가 도착하지 않으면 -1과 `ETIMEDOUT`을 반환합니다.
수신 결과는 세 종류입니다. 다른 device에서 받은 message는 `sequence=0`, `tx_status=0`, `rx_status!=0`입니다. 이전 nonblocking transmit의 송신 결과는 `sequence!=0`, `tx_status!=0`, `rx_status=0`입니다. 그 transmit의 reply는 `sequence!=0`, `tx_status=0`, `rx_status!=0`입니다.
송신하려면 응용 프로그램이 `struct cec_msg`를 채워 `CEC_TRANSMIT`에 전달합니다. 이 ioctl은 `CEC_CAP_TRANSMIT` capability가 있을 때만 사용할 수 있습니다.
transmit queue가 가득 차면 `EBUSY`입니다. queue에는 2-byte message 약 1초 분량인 18개를 넣을 수 있지만 CEC kernel framework도 core message reply를 같은 경로로 보내므로 queue를 완전히 채우는 것은 좋지 않습니다.
nonblocking mode의 transmit은 시작 후 0을 반환하고, 완료된 송신 결과는 나중에 `CEC_RECEIVE`로 받습니다. reply까지 요청했다면 reply는 그보다 뒤의 별도 message로 도착하며, 두 결과의 `sequence`로 원래 transmit과 연결합니다.
sequence와 두 status 필드 조합으로 queue 항목의 종류를 구분합니다.
하나의 sequence가 제출, 송신 결과와 선택적 reply를 묶습니다.
To receive a CEC message the application has to fill in the
``timeout`` field of struct :c:type:`cec_msg` and pass it to
:ref:`ioctl CEC_RECEIVE <CEC_RECEIVE>`.
If the file descriptor is in non-blocking mode and there are no received
messages pending, then it will return -1 and set errno to the ``EAGAIN``
error code. If the file descriptor is in blocking mode and ``timeout``
is non-zero and no message arrived within ``timeout`` milliseconds, then
it will return -1 and set errno to the ``ETIMEDOUT`` error code.
A received message can be:
1. a message received from another CEC device (the ``sequence`` field will
be 0, ``tx_status`` will be 0 and ``rx_status`` will be non-zero).
2. the transmit result of an earlier non-blocking transmit (the ``sequence``
field will be non-zero, ``tx_status`` will be non-zero and ``rx_status``
will be 0).
3. the reply to an earlier non-blocking transmit (the ``sequence`` field will
be non-zero, ``tx_status`` will be 0 and ``rx_status`` will be non-zero).
To send a CEC message the application has to fill in the struct
:c:type:`cec_msg` and pass it to :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>`.
The :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>` is only available if
``CEC_CAP_TRANSMIT`` is set. If there is no more room in the transmit
queue, then it will return -1 and set errno to the ``EBUSY`` error code.
The transmit queue has enough room for 18 messages (about 1 second worth
of 2-byte messages). Note that the CEC kernel framework will also reply
to core messages (see :ref:`cec-core-processing`), so it is not a good
idea to fully fill up the transmit queue.
If the file descriptor is in non-blocking mode then the transmit will
return 0 and the result of the transmit will be available via
:ref:`ioctl CEC_RECEIVE <CEC_RECEIVE>` once the transmit has finished.
If a non-blocking transmit also specified waiting for a reply, then
the reply will arrive in a later message. The ``sequence`` field can
be used to associate both transmit results and replies with the original
transmit.
Physical address가 없을 때의 예외 송신
75-88physical address가 disconnect 등의 이유로 invalid이면 일반 `CEC_TRANSMIT`은 `ENONET`을 반환합니다.
다만 CEC specification은 physical address가 없어도 `Unregistered`에서 `TV`로 message를 보내는 예외를 허용합니다. 일부 TV는 standby에 들어가거나 다른 input으로 전환할 때 HDMI hotplug detect pin을 low로 내리기 때문입니다.
hotplug detect가 low가 되면 EDID와 physical address는 사라지지만 cable은 여전히 연결되어 CEC가 동작할 수 있습니다. device를 탐지하거나 깨우기 위해 initiator 0xf(`Unregistered`)에서 destination 0(`TV`)로 poll 및 `Image/Text View On` message를 보낼 수 있습니다.
EDID가 사라져도 CEC link가 살아 있는 TV를 깨울 수 있게 합니다.
Normally calling :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>` when the physical
address is invalid (due to e.g. a disconnect) will return ``ENONET``.
However, the CEC specification allows sending messages from 'Unregistered' to
'TV' when the physical address is invalid since some TVs pull the hotplug detect
pin of the HDMI connector low when they go into standby, or when switching to
another input.
When the hotplug detect pin goes low the EDID disappears, and thus the
physical address, but the cable is still connected and CEC still works.
In order to detect/wake up the device it is allowed to send poll and 'Image/Text
View On' messages from initiator 0xf ('Unregistered') to destination 0 ('TV').
struct cec_msg 기본 필드
89-137`tx_ts`는 message의 마지막 byte가 송신된 시각, `rx_ts`는 마지막 byte가 수신된 시각을 nanosecond로 기록합니다. 둘 다 `CLOCK_MONOTONIC`에서 얻으며 userspace에서는 `clock_gettime()`으로 같은 clock에 접근합니다.
`len`은 message 길이입니다. `CEC_TRANSMIT` 입력에서는 응용 프로그램이 채우고 `CEC_RECEIVE`에서는 driver가 채웁니다. transmit이 reply를 기다렸다면 driver가 reply message 길이로 다시 채웁니다.
`timeout`은 millisecond 단위 대기 시간입니다. `CEC_RECEIVE`에서 0이면 무기한 기다립니다. `CEC_TRANSMIT`에서 0이면 `reply`가 non-zero일 때 1000으로 바뀌고, `reply`도 0이면 무시됩니다.
모든 transmit에는 framework가 non-zero `sequence`를 자동 할당합니다. nonblocking transmit의 송신 결과를 queue에 넣을 때 이 값으로 원래 요청과 연결합니다. reply를 기다리는 nonblocking transmit에서도 reply의 `sequence`를 원 요청과 같은 값으로 설정합니다.
원문 131행의 `ii.e.` 표기는 오탈자 형태 그대로 원문 영역에 보존됩니다. 의미는 `timeout`이 0이 아니어서 reply를 기다리는 경우입니다.
`flags`는 뒤의 `cec-msg-flags` 목록에 정의된 message flag bitmask입니다.
timestamp, 길이, 대기 시간과 비동기 연결 정보를 담습니다.
.. tabularcolumns:: |p{1.0cm}|p{3.5cm}|p{12.8cm}|
.. c:type:: cec_msg
.. cssclass:: longtable
.. flat-table:: struct cec_msg
:header-rows: 0
:stub-columns: 0
:widths: 1 1 16
* - __u64
- ``tx_ts``
- Timestamp in ns of when the last byte of the message was transmitted.
The timestamp has been taken from the ``CLOCK_MONOTONIC`` clock. To access
the same clock from userspace use :c:func:`clock_gettime`.
* - __u64
- ``rx_ts``
- Timestamp in ns of when the last byte of the message was received.
The timestamp has been taken from the ``CLOCK_MONOTONIC`` clock. To access
the same clock from userspace use :c:func:`clock_gettime`.
* - __u32
- ``len``
- The length of the message. For :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>` this is filled in
by the application. The driver will fill this in for
:ref:`ioctl CEC_RECEIVE <CEC_RECEIVE>`. For :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>` it will be
filled in by the driver with the length of the reply message if ``reply`` was set.
* - __u32
- ``timeout``
- The timeout in milliseconds. This is the time the device will wait
for a message to be received before timing out. If it is set to 0,
then it will wait indefinitely when it is called by :ref:`ioctl CEC_RECEIVE <CEC_RECEIVE>`.
If it is 0 and it is called by :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>`,
then it will be replaced by 1000 if the ``reply`` is non-zero or
ignored if ``reply`` is 0.
* - __u32
- ``sequence``
- A non-zero sequence number is automatically assigned by the CEC framework
for all transmitted messages. It is used by the CEC framework when it queues
the transmit result for a non-blocking transmit. This allows the application
to associate the received message with the original transmit.
In addition, if a non-blocking transmit will wait for a reply (ii.e. ``timeout``
was not 0), then the ``sequence`` field of the reply will be set to the sequence
value of the original transmit. This allows the application to associate the
received message with the original transmit.
* - __u32
- ``flags``
- Flags. See :ref:`cec-msg-flags` for a list of available flags.
Payload, reply, status와 재시도 counter
138-200`msg[16]`은 message payload입니다. transmit 입력에서는 응용 프로그램이 채우고 receive에서는 driver가 채우며, reply를 기다린 transmit이면 driver가 reply payload로 갱신합니다.
`reply`는 기다릴 reply opcode입니다. `reply=0`이고 `timeout=0`이면 reply를 기다리지 않고 transmit 직후 반환합니다. `CEC_RECEIVE`에서는 이 필드를 무시합니다.
`reply=0`은 Feature Abort opcode이기도 하므로 `timeout`이 non-zero인 조합을 명시적으로 허용합니다. 이 경우 최대 timeout 동안 Feature Abort를 기다리며 `rx_status`는 `CEC_RX_STATUS_TIMEOUT` 또는 `CEC_RX_STATUS_FEATURE_ABORT`가 됩니다.
transmit message가 `CEC_MSG_INITIATE_ARC`이면 reply 값 `CEC_MSG_REPORT_ARC_INITIATED`와 `CEC_MSG_REPORT_ARC_TERMINATED` 중 어느 것을 지정해도 두 실제 reply에 모두 match합니다. 이 message만 Feature Abort 외에 가능한 reply가 두 개이기 때문입니다. 수신 후 `reply` 필드는 실제 opcode로 갱신되어 `msg` 내용과 동기화됩니다.
`rx_status`는 받은 message의 status bit이고 `tx_status`는 보낸 message의 status bit입니다. nonblocking `CEC_TRANSMIT` 직후 `tx_status=0`이면 송신이 시작된 것이고 non-zero이면 결과를 즉시 알 수 있는 경우입니다.
자기 자신에게 Poll을 보내면 실제 bus 송신 없이 즉시 `CEC_TX_STATUS_NACK`이 되므로 nonblocking 호출에서도 결과가 바로 알려질 수 있습니다.
`tx_arb_lost_cnt`, `tx_nack_cnt`, `tx_low_drive_cnt`, `tx_error_cnt`는 각각 해당 송신 실패를 겪은 시도 횟수입니다. hardware가 지원하지 않으면 0이며 각각 대응하는 `CEC_TX_STATUS_*` bit가 설정됐을 때만 유효합니다.
원문은 `tx_low_drive_cnt`를 Arbitration Lost 횟수라고 설명하지만 유효 조건은 `CEC_TX_STATUS_LOW_DRIVE`입니다. 원문 문구는 보존하고 이 불일치를 검토 메모로 남깁니다.
message 본문, 기대 reply와 양방향 status를 한 구조체에 담습니다.
hardware 지원과 대응 status bit가 모두 있어야 의미가 있습니다.
reply opcode와 timeout 조합이 완료 조건을 정합니다.
* - __u8
- ``msg[16]``
- The message payload. For :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>` this is filled in by the
application. The driver will fill this in for :ref:`ioctl CEC_RECEIVE <CEC_RECEIVE>`.
For :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>` it will be filled in by the driver with
the payload of the reply message if ``timeout`` was set.
* - __u8
- ``reply``
- Wait until this message is replied. If ``reply`` is 0 and the
``timeout`` is 0, then don't wait for a reply but return after
transmitting the message. Ignored by :ref:`ioctl CEC_RECEIVE <CEC_RECEIVE>`.
The case where ``reply`` is 0 (this is the opcode for the Feature Abort
message) and ``timeout`` is non-zero is specifically allowed to make it
possible to send a message and wait up to ``timeout`` milliseconds for a
Feature Abort reply. In this case ``rx_status`` will either be set
to :ref:`CEC_RX_STATUS_TIMEOUT <CEC-RX-STATUS-TIMEOUT>` or
:ref:`CEC_RX_STATUS_FEATURE_ABORT <CEC-RX-STATUS-FEATURE-ABORT>`.
If the transmitter message is ``CEC_MSG_INITIATE_ARC`` then the ``reply``
values ``CEC_MSG_REPORT_ARC_INITIATED`` and ``CEC_MSG_REPORT_ARC_TERMINATED``
are processed differently: either value will match both possible replies.
The reason is that the ``CEC_MSG_INITIATE_ARC`` message is the only CEC
message that has two possible replies other than Feature Abort. The
``reply`` field will be updated with the actual reply so that it is
synchronized with the contents of the received message.
* - __u8
- ``rx_status``
- The status bits of the received message. See
:ref:`cec-rx-status` for the possible status values.
* - __u8
- ``tx_status``
- The status bits of the transmitted message. See
:ref:`cec-tx-status` for the possible status values.
When calling :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>` in non-blocking mode,
this field will be 0 if the transmit started, or non-0 if the transmit
result is known immediately. The latter would be the case when attempting
to transmit a Poll message to yourself. That results in a
:ref:`CEC_TX_STATUS_NACK <CEC-TX-STATUS-NACK>` without ever actually
transmitting the Poll message.
* - __u8
- ``tx_arb_lost_cnt``
- A counter of the number of transmit attempts that resulted in the
Arbitration Lost error. This is only set if the hardware supports
this, otherwise it is always 0. This counter is only valid if the
:ref:`CEC_TX_STATUS_ARB_LOST <CEC-TX-STATUS-ARB-LOST>` status bit is set.
* - __u8
- ``tx_nack_cnt``
- A counter of the number of transmit attempts that resulted in the
Not Acknowledged error. This is only set if the hardware supports
this, otherwise it is always 0. This counter is only valid if the
:ref:`CEC_TX_STATUS_NACK <CEC-TX-STATUS-NACK>` status bit is set.
* - __u8
- ``tx_low_drive_cnt``
- A counter of the number of transmit attempts that resulted in the
Arbitration Lost error. This is only set if the hardware supports
this, otherwise it is always 0. This counter is only valid if the
:ref:`CEC_TX_STATUS_LOW_DRIVE <CEC-TX-STATUS-LOW-DRIVE>` status bit is set.
* - __u8
- ``tx_error_cnt``
- A counter of the number of transmit errors other than Arbitration
Lost or Not Acknowledged. This is only set if the hardware
supports this, otherwise it is always 0. This counter is only
valid if the :ref:`CEC_TX_STATUS_ERROR <CEC-TX-STATUS-ERROR>` status bit is set.
struct cec_msg flag
201-249`CEC_MSG_FL_REPLY_TO_FOLLOWERS`(1)는 기대한 reply를 transmit을 요청한 filehandle뿐 아니라 모든 follower에도 전달합니다.
요청 filehandle 자체도 follower라면 같은 reply를 두 번 받습니다. 하나는 `CEC_TRANSMIT` 결과이고 다른 하나는 `CEC_RECEIVE` queue를 통한 follower copy입니다.
`CEC_MSG_FL_RAW`(2)는 transmit 전 CEC message validation을 생략하고 원문 그대로 송신하므로 debugging에 유용합니다. process에 `CAP_SYS_RAWIO`가 있어야 하며 없으면 `EPERM`입니다.
`CEC_MSG_FL_REPLY_VENDOR_ID`(4)는 `CEC_CAP_REPLY_VENDOR_ID` capability가 있을 때만 사용할 수 있습니다. 기대 reply를 `CEC_MSG_VENDOR_COMMAND_WITH_ID`, message byte 1–4의 Vendor ID, 그 뒤의 `struct cec_msg.reply` opcode 조합으로 해석합니다.
Vendor ID 다음 byte를 vendor-specific opcode라고 가정하며, vendor command의 reply를 기다리는 절차를 단순하게 합니다.
reply 분배, raw 송신과 vendor reply matching을 제어합니다.
Vendor ID와 그 뒤 opcode까지 reply 조건에 포함합니다.
.. tabularcolumns:: |p{6.2cm}|p{1.0cm}|p{10.1cm}|
.. _cec-msg-flags:
.. flat-table:: Flags for struct cec_msg
:header-rows: 0
:stub-columns: 0
:widths: 3 1 4
* .. _`CEC-MSG-FL-REPLY-TO-FOLLOWERS`:
- ``CEC_MSG_FL_REPLY_TO_FOLLOWERS``
- 1
- If a CEC transmit expects a reply, then by default that reply is only sent to
the filehandle that called :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>`. If this
flag is set, then the reply is also sent to all followers, if any. If the
filehandle that called :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>` is also a
follower, then that filehandle will receive the reply twice: once as the
result of the :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>`, and once via
:ref:`ioctl CEC_RECEIVE <CEC_RECEIVE>`.
* .. _`CEC-MSG-FL-RAW`:
- ``CEC_MSG_FL_RAW``
- 2
- Normally CEC messages are validated before transmitting them. If this
flag is set when :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>` is called,
then no validation takes place and the message is transmitted as-is.
This is useful when debugging CEC issues.
This flag is only allowed if the process has the ``CAP_SYS_RAWIO``
capability. If that is not set, then the ``EPERM`` error code is
returned.
* .. _`CEC-MSG-FL-REPLY-VENDOR-ID`:
- ``CEC_MSG_FL_REPLY_VENDOR_ID``
- 4
- This flag is only available if the ``CEC_CAP_REPLY_VENDOR_ID`` capability
is set. If this flag is set, then the reply is expected to consist of
the ``CEC_MSG_VENDOR_COMMAND_WITH_ID`` opcode followed by the Vendor ID
(in bytes 1-4 of the message), followed by the ``struct cec_msg``
``reply`` field.
Note that this assumes that the byte after the Vendor ID is a
vendor-specific opcode.
This flag makes it easier to wait for replies to vendor commands.
CEC transmit status
250-318`CEC_TX_STATUS_OK`(0x01)은 최종 송신 성공입니다. `CEC_TX_STATUS_MAX_RETRIES`와 동시에 설정될 수 없지만, 이전 시도의 실패를 나타내는 다른 bit는 함께 남을 수 있습니다.
`CEC_TX_STATUS_ARB_LOST`(0x02)는 같은 시각에 더 높은 priority 송신이 시작돼 CEC line arbitration에서 진 것입니다. 선택적 status라 모든 hardware가 검출하지는 못합니다.
`CEC_TX_STATUS_NACK`(0x04)은 message가 acknowledge되지 않았음을 뜻합니다. 일부 hardware는 NACK과 다른 실패를 구분하지 못하고 OK 또는 FAIL만 보고하므로, 그런 장치에서는 모든 송신 실패에 이 status를 반환할 수 있습니다.
`CEC_TX_STATUS_LOW_DRIVE`(0x08)는 CEC bus에서 low drive를 검출했다는 뜻입니다. follower가 bus error를 감지해 재송신을 요청한 경우이며 선택적 status입니다.
`CEC_TX_STATUS_ERROR`(0x10)은 ARB_LOST나 LOW_DRIVE에 맞지 않는 오류입니다. hardware가 정확한 종류를 구분하지 못하거나 두 조건 외의 오류를 검사했을 때 사용하며 선택적입니다.
`CEC_TX_STATUS_MAX_RETRIES`(0x20)는 한 번 이상의 재시도 뒤 송신이 실패했음을 뜻합니다. OK와 상호 배타적이며 다른 failure bit가 원인을 함께 설명할 수 있습니다.
`CEC_TX_STATUS_ABORTED`(0x40)는 HDMI disconnect, adapter unconfigured, transmit interrupt 또는 driver의 송신 시작 오류로 중단됐음을 뜻합니다.
`CEC_TX_STATUS_TIMEOUT`(0x80)은 transmit timeout이며 정상적으로 발생해서는 안 되므로 driver 문제를 나타냅니다.
여러 실패 bit가 누적될 수 있지만 OK와 MAX_RETRIES는 상호 배타적입니다.
.. tabularcolumns:: |p{5.6cm}|p{0.9cm}|p{10.8cm}|
.. _cec-tx-status:
.. flat-table:: CEC Transmit Status
:header-rows: 0
:stub-columns: 0
:widths: 3 1 16
* .. _`CEC-TX-STATUS-OK`:
- ``CEC_TX_STATUS_OK``
- 0x01
- The message was transmitted successfully. This is mutually
exclusive with :ref:`CEC_TX_STATUS_MAX_RETRIES <CEC-TX-STATUS-MAX-RETRIES>`.
Other bits can still be set if earlier attempts met with failure before
the transmit was eventually successful.
* .. _`CEC-TX-STATUS-ARB-LOST`:
- ``CEC_TX_STATUS_ARB_LOST``
- 0x02
- CEC line arbitration was lost, i.e. another transmit started at the
same time with a higher priority. Optional status, not all hardware
can detect this error condition.
* .. _`CEC-TX-STATUS-NACK`:
- ``CEC_TX_STATUS_NACK``
- 0x04
- Message was not acknowledged. Note that some hardware cannot tell apart
a 'Not Acknowledged' status from other error conditions, i.e. the result
of a transmit is just OK or FAIL. In that case this status will be
returned when the transmit failed.
* .. _`CEC-TX-STATUS-LOW-DRIVE`:
- ``CEC_TX_STATUS_LOW_DRIVE``
- 0x08
- Low drive was detected on the CEC bus. This indicates that a
follower detected an error on the bus and requests a
retransmission. Optional status, not all hardware can detect this
error condition.
* .. _`CEC-TX-STATUS-ERROR`:
- ``CEC_TX_STATUS_ERROR``
- 0x10
- Some error occurred. This is used for any errors that do not fit
``CEC_TX_STATUS_ARB_LOST`` or ``CEC_TX_STATUS_LOW_DRIVE``, either because
the hardware could not tell which error occurred, or because the hardware
tested for other conditions besides those two. Optional status.
* .. _`CEC-TX-STATUS-MAX-RETRIES`:
- ``CEC_TX_STATUS_MAX_RETRIES``
- 0x20
- The transmit failed after one or more retries. This status bit is
mutually exclusive with :ref:`CEC_TX_STATUS_OK <CEC-TX-STATUS-OK>`.
Other bits can still be set to explain which failures were seen.
* .. _`CEC-TX-STATUS-ABORTED`:
- ``CEC_TX_STATUS_ABORTED``
- 0x40
- The transmit was aborted due to an HDMI disconnect, or the adapter
was unconfigured, or a transmit was interrupted, or the driver
returned an error when attempting to start a transmit.
* .. _`CEC-TX-STATUS-TIMEOUT`:
- ``CEC_TX_STATUS_TIMEOUT``
- 0x80
- The transmit timed out. This should not normally happen and this
indicates a driver problem.
CEC receive status
319-354`CEC_RX_STATUS_OK`(0x01)은 message가 성공적으로 수신됐음을 뜻합니다.
`CEC_RX_STATUS_TIMEOUT`(0x02)은 앞서 송신한 message의 reply가 timeout 안에 오지 않았음을 뜻합니다.
`CEC_RX_STATUS_FEATURE_ABORT`(0x04)는 message 수신에는 성공했지만 reply가 `CEC_MSG_FEATURE_ABORT`였음을 뜻합니다. 앞선 transmit에 대한 reply인 경우에만 설정됩니다.
`CEC_RX_STATUS_ABORTED`(0x08)는 HDMI cable disconnect, adapter unconfigured 또는 reply를 기다리던 작업의 interrupt 때문에 reply 대기가 중단됐음을 뜻합니다.
원문 351행의 `:ref:`CEC_TRANSMIT <CEC_RECEIVE>`` 표기는 표시 text와 target이 서로 다릅니다. 접을 수 있는 원문에는 그대로 보존하고, 의미상 reply를 기다리던 transmit 작업이 interrupt된 경우로 번역합니다.
실제 message 수신과 transmit reply 대기 결과를 함께 표현합니다.
.. tabularcolumns:: |p{5.6cm}|p{0.9cm}|p{10.8cm}|
.. _cec-rx-status:
.. flat-table:: CEC Receive Status
:header-rows: 0
:stub-columns: 0
:widths: 3 1 16
* .. _`CEC-RX-STATUS-OK`:
- ``CEC_RX_STATUS_OK``
- 0x01
- The message was received successfully.
* .. _`CEC-RX-STATUS-TIMEOUT`:
- ``CEC_RX_STATUS_TIMEOUT``
- 0x02
- The reply to an earlier transmitted message timed out.
* .. _`CEC-RX-STATUS-FEATURE-ABORT`:
- ``CEC_RX_STATUS_FEATURE_ABORT``
- 0x04
- The message was received successfully but the reply was
``CEC_MSG_FEATURE_ABORT``. This status is only set if this message
was the reply to an earlier transmitted message.
* .. _`CEC-RX-STATUS-ABORTED`:
- ``CEC_RX_STATUS_ABORTED``
- 0x08
- The wait for a reply to an earlier transmitted message was aborted
because the HDMI cable was disconnected, the adapter was unconfigured
or the :ref:`CEC_TRANSMIT <CEC_RECEIVE>` that waited for a
reply was interrupted.
CEC_RECEIVE 반환값과 오류
355-373성공하면 0, 오류이면 -1을 반환하고 `errno`를 설정합니다. 공통 오류는 Generic Error Codes 장을 따릅니다.
`EAGAIN`은 nonblocking filehandle의 receive queue가 비어 있을 때, `ETIMEDOUT`은 message를 기다리다 `timeout`에 도달했을 때 반환합니다.
`ERESTARTSYS`는 message 대기가 Ctrl-C 같은 interrupt로 중단됐음을 뜻합니다.
queue 상태, timeout과 signal interrupt를 구분합니다.
Return Value
============
On success 0 is returned, on error -1 and the ``errno`` variable is set
appropriately. The generic error codes are described at the
:ref:`Generic Error Codes <gen-errors>` chapter.
The :ref:`ioctl CEC_RECEIVE <CEC_RECEIVE>` can return the following
error codes:
EAGAIN
No messages are in the receive queue, and the filehandle is in non-blocking mode.
ETIMEDOUT
The ``timeout`` was reached while waiting for a message.
ERESTARTSYS
The wait for a message was interrupted (e.g. by Ctrl-C).
CEC_TRANSMIT 오류
374-400`ENOTTY`는 `CEC_CAP_TRANSMIT` capability가 없어 ioctl을 지원하지 않는 경우입니다.
`EPERM`은 `CEC_ADAP_S_LOG_ADDRS`를 한 번도 호출하지 않아 adapter가 configured되지 않았거나, `CAP_SYS_RAWIO`가 없는 process가 `CEC_MSG_FL_RAW`를 사용한 경우입니다.
`ENONET`은 `CEC_ADAP_S_LOG_ADDRS`는 호출했지만 physical address가 invalid여서 logical address를 claim하지 못한 경우입니다. initiator 0xf(`Unregistered`)에서 destination 0(`TV`)로 보내는 예외는 정상적으로 진행합니다.
`EBUSY`는 다른 filehandle이 exclusive follower·initiator mode이거나 현재 filehandle이 `CEC_MODE_NO_INITIATOR`인 경우, 또는 transmit queue가 가득 찬 경우입니다.
`EINVAL`은 `struct cec_msg` 내용이 유효하지 않을 때, `ERESTARTSYS`는 성공적인 transmit을 기다리는 동안 Ctrl-C 같은 interrupt가 발생했을 때 반환합니다.
capability, adapter 상태, mode, queue와 message 유효성을 구분합니다.
The :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>` can return the following
error codes:
ENOTTY
The ``CEC_CAP_TRANSMIT`` capability wasn't set, so this ioctl is not supported.
EPERM
The CEC adapter is not configured, i.e. :ref:`ioctl CEC_ADAP_S_LOG_ADDRS <CEC_ADAP_S_LOG_ADDRS>`
has never been called, or ``CEC_MSG_FL_RAW`` was used from a process that
did not have the ``CAP_SYS_RAWIO`` capability.
ENONET
The CEC adapter is not configured, i.e. :ref:`ioctl CEC_ADAP_S_LOG_ADDRS <CEC_ADAP_S_LOG_ADDRS>`
was called, but the physical address is invalid so no logical address was claimed.
An exception is made in this case for transmits from initiator 0xf ('Unregistered')
to destination 0 ('TV'). In that case the transmit will proceed as usual.
EBUSY
Another filehandle is in exclusive follower or initiator mode, or the filehandle
is in mode ``CEC_MODE_NO_INITIATOR``. This is also returned if the transmit
queue is full.
EINVAL
The contents of struct :c:type:`cec_msg` is invalid.
ERESTARTSYS
The wait for a successful transmit was interrupted (e.g. by Ctrl-C).
요약·해설
cec-ioc-receive.rst:1-400이 API는 동기·비동기 CEC 송수신을 하나의 `struct cec_msg`로 표현합니다. nonblocking transmit의 송신 결과와 reply는 `CEC_RECEIVE` queue에 별도 항목으로 들어오며 `sequence`로 원 요청과 연결됩니다. status는 누적 bit이므로 단일 값 비교보다 bitmask로 해석해야 합니다. 원문의 `tx_low_drive_cnt` 설명과 351행 교차참조에는 문맥 불일치가 있어 원문을 보존하고 해당 번역 구간에 검토 메모를 표시했습니다.