From 18df7b4d4579a1a340e1213577cedec195886b17 Mon Sep 17 00:00:00 2001 From: srinivasgtl <71806084+srinivasgtl@users.noreply.github.com> Date: Fri, 19 Jul 2024 19:31:32 +0100 Subject: [PATCH 01/40] gh #44 Initial L3 Low level desig document for the hdmi cec sink device --- .../hdmi-cec-sink-L3-Low-Level_TestSpec.md | 239 ++++++++++++++++++ 1 file changed, 239 insertions(+) create mode 100644 docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md diff --git a/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md b/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md new file mode 100644 index 0000000..ee9cf2e --- /dev/null +++ b/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md @@ -0,0 +1,239 @@ +# HDMI CEC L3 Test Document for Sink Devices. + +## Table of Contents +- [Acronyms, Terms and Abbreviations](#acronyms-terms-and-abbreviations) +- [Description](#description) +- [Component Runtime Execution Requirements](#component-runtime-execution-requirements) + - [Initialization and Startup] + +## Overview +This document provides an overview of the L3 testing requirements for the module `HDMI CEC` source device. It outlines the scope of testing, objectives, External devices, specific test requirements, expected deliverables and approaches to satisfy the L3 Test requirement. + +## Acronyms, Terms and Abbreviations +- `CEC` - Consumer Electronics Control +- `HAL` - Hardware Abstraction layer +- `HDMI` - High Definition Multimedia Interface +- `API` - Application Program Interface +- `SoC` - System on Chip +- `DUT` - Device Under Test. + + +## References +CEC Adaptor: https://www.pulse-eight.com/p/104/usb-hdmi-cec-adapter# +`HAL` interface file: https://github.com/rdkcentral/rdk-halif-hdmi_cec/blob/main/include/hdmi_cec_driver.h + + +## Module Description +Consumer Electronics Control (`CEC`) is a one-wire bidirectional bus within an HDMI system that enables interconnected products to communicate with each other. This module outlines a set of `HAL` `APIs` designed to support `HDMI` `CEC` functionality. The current document details the L3 test definitions and descriptions used to validate these `HDMI` `CEC` `APIs`, including the prerequisites that must be managed before testing and the external stimuli that need to be applied during the test. + +The present document describes the test scope for the Sink Device activities only. + +### HDMI-CEC L3 Test Functionality +The below pic depicts the HDMI CEC L3 Test Functionality Setup. TV 2 marked as `DUT` is the Sink device under test. + +Note: All the devices used in the test setup should be supporting CEC feature during the entire duration of the test. + +```mermaid +graph TB +A[STB] -->|HDMI| B[CEC Adaptor] +B --> |HDMI| C[ TV] +B -->|USB| C3[PC] +``` + +#### Logical Address Test +1. Setting the logical address for the `DUT` with the same logical address of already existing device on the network (STB) + +#### Message Transmission and Reception Test +2. Transmitting HDMI CEC Command to receive a reply. +3. Broadcasting a HDMI CEC Command to put the STB into Standby state. +4. Recieve a standby broadcasting command send by the CEC Adaptor +5. Receving a simple HDMI CEC standby command from the CEC Adaptor +6. Receiving a HDMI OSD Command with a string of max length (14 bytes ) from CEC Adaptor. + +#### Stress Test +6. Receiving a HDMI OSD Command repeatedly for 10 times with a string of max length from CEC Adaptor. + +#### Hardware Fault Test +7. Introducing a Fault on the HDMI line to test the Transmit functionality. + + +# Test 1 : Logical Address Test + +### Functionality: +1. The `DUT` should attempt to acquire logical address which is already in use. + +### Pre-requisites: +1. First, set the STB to ON state to enable it to acquire a Logical address. +2. HDMI CEC Adaptor should able to help in getting the STB logical address for further activities. + +|Title|Details| +|--|--| +|Function Name|`test_l3_hdmi_cec_sink_hal_AcquireLogicalAddress`| +|Description|This functions performs to acquire a Logical address which is already acquired by the STB. This should prove the capability of the HAL API HdmiCecAddLogicalAddress() where it shall fail to acquire a Logical address that is already been taken | +|Test Group|03| +|Test Case ID|001| +|Priority|High| + +**Pre-Conditions:** +1. A STB device should be present in the network which is already acquired the Logical address before the test is performed. +2. HMDI CEC Adaptor should provide a way to read the acquired STB logical address. + +**Dependencies:** +Pre requisites should be met before starting this test. + +**User Interaction:** +User should able to get the STB logical address and feed it for the test. + +#### Test Procedure +| Variation / Steps | Description | Test Data | Expected Result | Notes| +| -- | --------- | ---------- | -------------- | ----- | +| 01 | Open HDMI CEC HAL using HdmiCecOpen API | handle = valid pointer | HDMI_CEC_IO_SUCCESS | Should be successful | +| 02 | Wait to enter the STB logical address | NA | NA | Feed the logical Address of the STB manually | +| 03 | Try acquiring the STB logical address using HdmiCecAddLogicalAddress()| handle = valid handle, logicalAddress = STB logical address | HDMI_CEC_IO_LOGICALADDRESS_UNAVAILABLE | Should be successful | +| 04 | Close HDMI CEC HAL using HdmiCecClose API | handle = valid handle | HDMI_CEC_IO_SUCCESS | Should be successful | + + +# Test 2: Request, Receive and Respond for the basic CEC Commands + +Functionality: +1. `DUT` shall request a CEC Version from the Source Device (STB). It should receive a valid version and evaluated. +2. `DUT` shall receive a standby command as a unicast command from the CEC Adaptor. +3. `DUT` shall receive a OSD Command with max buffer size from the CEC Adaptor and respond to this command. + + +| Title | Details | +|-------------------------------|--------------------------------------------------| +| Function Name | `test_l3_hdmi_cec_sink_tx_rx_test` | +| Description | This test shall validate the Tx, and Rx CEC Commands between the `DUT`, STB and CEC Adaptor connected on a network | +| Test Group | 03 | +| Test Case ID | 002 | +| Priority | High | + +**Pre-Conditions:** +The platforms are connected as shown in the picture above and STB and the CEC Adaptor are kept ready before start of the test. + +**Dependencies:** +Pre requisites should be met before starting this test. + +**User Interaction:** +If the user chooses to run the test in interactive mode, then the test case has to be selected via the console. + +#### Test Procedure + +| Variation / Steps | Description | Test Data | Expected Result | Notes | +| -- | --------- | ---------- | -------------- | ----- | +| 01 | Open HDMI CEC HAL using `HdmiCecOpen` API | `handle` = valid pointer | `HDMI_CEC_IO_SUCCESS` | Should be successful | +| 02 | Acquire a valid logical address `0x00` using `HdmiCecAddLogicalAddress` | `handle` = valid handle, `logicalAddress` = 0 | `HDMI_CEC_IO_SUCCESS` | Should be successful | +| 03 | Set the receive callback function using `HdmiCecSetRxCallback` | `handle` = valid handle, `cbfunc` = RxCallback, `data` = buffer pointer | `HDMI_CEC_IO_SUCCESS` | Should be successful | +| 04 | Get the connected device (STB) logical address manually. Wait until this data is entered | N/A | N/A | Enter the logical address of the STB as read on the CEC adapter | +| 05 | Frame a command to transmit CEC frames to get the CEC version of the connected STB using `HdmiCecTx` | `handle` = valid handle, `buf` = {0x47, 0x9F}, `len` = sizeof(buf), `result` = valid pointer | `HDMI_CEC_IO_SUCCESS` | Should be successful | +| 06 | Wait for a second and validate a response from the STB on the RxCallback and set the `dataRx` flag to True. Validate the received data and set the `dataRx` flag to False | Test data received from STB | Read and validate this data. Rx data should be a valid CEC version | Should be successful | +| 12 | Frame and send a CEC OSD command with full buffer data with `DUT` logical address from CEC adapter | `buffer` = {0x02, 0x64, "Hello, World!"} | N/A | User to set this data through CEC adapter | +| 13 | Wait for the user to signal when the CEC command is sent in step 12 | User to press `y` to move | N/A | User to signal once the CEC command is sent | +| 14 | Wait for a second to receive data from the CEC adapter on the RxCallback and set the `dataRx` flag to True. Validate the received data with "Hello, World!" and set the `dataRx` flag to False | Test data received should be `0x0F` | Read and validate this data. Data received should be "Hello, World!" | Should be successful | +| 15 | Close HDMI CEC HAL using `HdmiCecClose` API | `handle` = valid handle | `HDMI_CEC_IO_SUCCESS` | Should be successful | + +# Test 3: Request, Receive and Respond for the basic CEC Commands + +Functionality: +1. `DUT` shall broadcast a standby command to the connected devices and STB should receive and act upon the command. +2. `DUT` shall receive a standby command as a broadcast command from the CEC Adaptor. + +| Title | Details | +|-------------------------------|--------------------------------------------------| +| Function Name | `test_l3_hdmi_cec_sink_broadcast_test` | +| Description | This test shall validate the broadcast CEC Commands between the `DUT`, STB and CEC Adaptor connected on a network | +| Test Group | 03 | +| Test Case ID | 003 | +| Priority | High | + +**Pre-Conditions:** +The platforms are connected as shown in the picture above and STB and the CEC Adaptor are kept ready before start of the test. + +**Dependencies:** +Pre requisites should be met before starting this test. + +**User Interaction:** +If the user chooses to run the test in interactive mode, then the test case has to be selected via the console. + +#### Test Procedure +## New Test Plan (Broadcast Commands) + +| Variation / Steps | Description | Test Data | Expected Result | Notes | +| -- | --------- | ---------- | -------------- | ----- | +| 01 | Open HDMI CEC HAL using `HdmiCecOpen` API | `handle` = valid pointer | `HDMI_CEC_IO_SUCCESS` | Should be successful | +| 02 | Acquire a valid logical address `0x00` using `HdmiCecAddLogicalAddress` | `handle` = valid handle, `logicalAddress` = 0 | `HDMI_CEC_IO_SUCCESS` | Should be successful | +| 03 | Set the receive callback function using `HdmiCecSetRxCallback` | `handle` = valid handle, `cbfunc` = RxCallback, `data` = buffer pointer | `HDMI_CEC_IO_SUCCESS` | Should be successful | +| 04 | Frame a command to broadcast CEC frames to put the connected STB into standby state using `HdmiCecTx` | `handle` = valid handle, `buf` = {0x0F, 0x36}, `len` = sizeof(buf), `result` = valid pointer | `HDMI_CEC_IO_SUCCESS` | Should be successful.
Buffer data may change based on STB logical address | +| 05 | Wait for the user to respond indicating test pass or fail | `1` for pass and `0` for fail | N/A | User to enter the result | +| 06 | Frame and send a CEC command to broadcast standby command from CEC adapter | `buffer` = {0x2F, 0x36} | N/A | User to set this data through CEC adapter | +| 07 | Wait for the user to signal when the CEC broadcast is sent in step 6 | User to press `y` to move | N/A | User to signal once the CEC broadcast is set | +| 08 | Wait for a second to receive data from the CEC adapter on the RxCallback and set the `dataRx` flag to True. Validate the received data with `0x36` and set the `dataRx` flag to False | Test data received should be `0x0F` | Read and validate this data. Data received should be `0x36` (standby data) | Should be successful | +| 09 | Close HDMI CEC HAL using `HdmiCecClose` API | `handle` = valid handle | `HDMI_CEC_IO_SUCCESS` | Should be successful | + + +# Test 4: Stress Test + +Functionality: +1. `DUT` shall respond to a CEC OSD command received from the CEC Adaptor repeatedly for 10 times. Adaptor will be used for a better control from the automation tool. + +| Title | Details | +|-------------------------------|--------------------------------------------------| +| Function Name | `test_l3_hdmi_cec_sink_respond_osd_command_from_adaptor_repeatedly` | +| Description | Receive and respond for the CEC OSD Command with buffer data continesouly for 10 time to prove the robustness of this API. | +| Test Group | 03 | +| Test Case ID | 004 | +| Priority | High | + +**Pre-Conditions:** +TV 1 and the STB are already ON before the start of the Test and they have acquired the physical and logical addresses. TV1 and STB should be good enough to support the basic CEC Commands like get CEC Version. + +**Dependencies:** +Pre requisites should be met before starting this test. + +**User Interaction:** +If the user chooses to run the test in interactive mode, then the test case has to be selected via the console. + +#### Test Procedure +| Variation / Steps | Description | Test Data | Expected Result | Notes | +|-------------------|-------------|-----------|------------------|-------| +| 01 | Open HDMI CEC HAL using `HdmiCecOpen` API | `handle` = valid pointer | `HDMI_CEC_IO_SUCCESS` | Should be successful | +| 02 | Acquire a valid logical address `0x00` using `HdmiCecAddLogicalAddress` | `handle` = valid handle, `logicalAddress` = 0 | `HDMI_CEC_IO_SUCCESS` | Should be successful | +| 03 | Set the receive callback function using `HdmiCecSetRxCallback` | `handle` = valid handle, `cbfunc` = valid callback function pointer, `data` = pointer to the valid data buffer | `HDMI_CEC_IO_SUCCESS` | Should be successful | +| 04 | Wait for a manual command so that CEC Adaptor can send a CEC OSD Command continuously for 10 times | N/A | N/A | Should be successful | +| 05 | Frame a command to Tx Test OSD CEC command with full buffer size from the HDMI CEC adaptor continuously for 10 times | `buf` = {0x05, 0x64, 0x00, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x21} | N/A | Should be successful | +| 06 | Validate the data received from the DUT when the `dataRx` flag in RxCall back function is set to true for 10 times | Compare the received data with predefined buffer | `buf` = {0x05, 0x64, 0x00, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x21} | Should be successful | +| 07 | Close HDMI CEC HAL using `HdmiCecClose` API | `handle` = valid handle | `HDMI_CEC_IO_SUCCESS` | Should be successful | + + +# Test 5: Hardware Fault Test + +Functionality: +1. `DUT` shall respond with the correct error code when a Fault (pulling the HDMI line to high) is introduced into the HDMI CEC line. + +| Title | Details | +|-------------------------------|--------------------------------------------------| +| Function Name | `test_l3_hdmi_cec_sink_hw_fault_test` | +| Description | Test for the return of proper error code when an hardware fault is introduced into the cec line and trying to Tx the CEC data. | +| Test Group | 03 | +| Test Case ID | 005 | +| Priority | High | + +**Pre-Conditions:** +Conntect a HW fault inducer which can pull the HDMI CEC line to high and to normal through a switch. + +**Dependencies:** +Pre requisites should be met before starting this test. + +**User Interaction:** +If the user chooses to run the test in interactive mode, then the test case has to be selected via the console. + +#### Test Procedure +| Variation / Steps | Description | Test Data | Expected Result | Notes | +|-------------------|-------------|-----------|------------------|-------| +| 01 | Open HDMI CEC HAL using `HdmiCecOpen` API | `handle` = valid pointer | `HDMI_CEC_IO_SUCCESS` | Should be successful | +| 02 | Acquire a valid logical address `0x00` using `HdmiCecAddLogicalAddress` | `handle` = valid handle, `logicalAddress` = 0 | `HDMI_CEC_IO_SUCCESS` | Should be successful | +| 03 | Set the receive callback function using `HdmiCecSetRxCallback` | `handle` = valid handle, `cbfunc` = valid callback function pointer, `data` = pointer to the valid data buffer | `HDMI_CEC_IO_SUCCESS` | Should be successful | +| 04 | Wait for a manual command so that the user is ready to pull the hdmi CEC high high with the help of the fault inducer switch | N/A | N/A | Should be successful | +| 05 | Frame a command to Tx Test OSD CEC command with full buffer size from the `DUT` continuously for 10 times | handle= valid handle, `buf` = {0x05, 0x64, 0x00, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x21} |HDMI_CEC_STATUS and HDMI_CEC_IO_SENT_FAILED | Should be successful | +| 06 | Close HDMI CEC HAL using `HdmiCecClose` API | `handle` = valid handle | `HDMI_CEC_IO_SUCCESS` | Should be successful | From 178e1bf960681510eacd8870b074ae932b943c23 Mon Sep 17 00:00:00 2001 From: srinivasgtl <71806084+srinivasgtl@users.noreply.github.com> Date: Mon, 22 Jul 2024 06:33:16 +0100 Subject: [PATCH 02/40] gh#44 Update hdmi-cec-sink-L3-Low-Level_TestSpec.md Correcting the typo mistakes. --- .../hdmi-cec-sink-L3-Low-Level_TestSpec.md | 69 +++++++++---------- 1 file changed, 34 insertions(+), 35 deletions(-) diff --git a/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md b/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md index ee9cf2e..246c457 100644 --- a/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md +++ b/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md @@ -31,7 +31,7 @@ The present document describes the test scope for the Sink Device activities onl ### HDMI-CEC L3 Test Functionality The below pic depicts the HDMI CEC L3 Test Functionality Setup. TV 2 marked as `DUT` is the Sink device under test. -Note: All the devices used in the test setup should be supporting CEC feature during the entire duration of the test. +Note: All the devices used in the test setup should support `HDMI` `CEC` feature during the entire duration of the test. ```mermaid graph TB @@ -41,48 +41,47 @@ B -->|USB| C3[PC] ``` #### Logical Address Test -1. Setting the logical address for the `DUT` with the same logical address of already existing device on the network (STB) +1. Setting the logical address for the `DUT` with the same logical address of the already existing device on the network (STB) #### Message Transmission and Reception Test 2. Transmitting HDMI CEC Command to receive a reply. 3. Broadcasting a HDMI CEC Command to put the STB into Standby state. -4. Recieve a standby broadcasting command send by the CEC Adaptor -5. Receving a simple HDMI CEC standby command from the CEC Adaptor -6. Receiving a HDMI OSD Command with a string of max length (14 bytes ) from CEC Adaptor. +4. Recieve a standby broadcasting command sent by the CEC Adaptor +5. Receiving an HDMI OSD Command with a string of max length (14 bytes ) from CEC Adaptor. #### Stress Test -6. Receiving a HDMI OSD Command repeatedly for 10 times with a string of max length from CEC Adaptor. +6. Receiving an HDMI OSD Command repeatedly for 10 times with a string of max length from CEC Adaptor. #### Hardware Fault Test 7. Introducing a Fault on the HDMI line to test the Transmit functionality. -# Test 1 : Logical Address Test +# Test 1: Logical Address Test ### Functionality: -1. The `DUT` should attempt to acquire logical address which is already in use. +1. The `DUT` should attempt to acquire a logical address that is already in use. ### Pre-requisites: 1. First, set the STB to ON state to enable it to acquire a Logical address. -2. HDMI CEC Adaptor should able to help in getting the STB logical address for further activities. +2. HDMI CEC Adaptor should be able to help in getting the STB logical address for further activities. |Title|Details| |--|--| |Function Name|`test_l3_hdmi_cec_sink_hal_AcquireLogicalAddress`| -|Description|This functions performs to acquire a Logical address which is already acquired by the STB. This should prove the capability of the HAL API HdmiCecAddLogicalAddress() where it shall fail to acquire a Logical address that is already been taken | +|Description|This function performs to acquire a Logical address that is already acquired by the STB. This should prove the capability of the HAL API HdmiCecAddLogicalAddress() where it shall fail to acquire a Logical address that is already been taken | |Test Group|03| |Test Case ID|001| |Priority|High| **Pre-Conditions:** -1. A STB device should be present in the network which is already acquired the Logical address before the test is performed. -2. HMDI CEC Adaptor should provide a way to read the acquired STB logical address. +1. An STB device should be present in the network which is already acquired the Logical address before the test is performed. +2. The HMDI CEC Adaptor should provide a way to read the acquired STB logical address. **Dependencies:** -Pre requisites should be met before starting this test. +Prerequisites should be met before starting this test. **User Interaction:** -User should able to get the STB logical address and feed it for the test. +The user should be able to get the STB logical address and feed it for the test. #### Test Procedure | Variation / Steps | Description | Test Data | Expected Result | Notes| @@ -93,27 +92,27 @@ User should able to get the STB logical address and feed it for the test. | 04 | Close HDMI CEC HAL using HdmiCecClose API | handle = valid handle | HDMI_CEC_IO_SUCCESS | Should be successful | -# Test 2: Request, Receive and Respond for the basic CEC Commands +# Test 2: Request, Receive, and Respond to the basic CEC Commands Functionality: -1. `DUT` shall request a CEC Version from the Source Device (STB). It should receive a valid version and evaluated. +1. `DUT` shall request a CEC Version from the Source Device (STB). It should receive a valid version and be evaluated. 2. `DUT` shall receive a standby command as a unicast command from the CEC Adaptor. -3. `DUT` shall receive a OSD Command with max buffer size from the CEC Adaptor and respond to this command. +3. `DUT` shall receive an OSD Command with max buffer size from the CEC Adaptor and respond to this command. | Title | Details | |-------------------------------|--------------------------------------------------| | Function Name | `test_l3_hdmi_cec_sink_tx_rx_test` | -| Description | This test shall validate the Tx, and Rx CEC Commands between the `DUT`, STB and CEC Adaptor connected on a network | +| Description | This test shall validate the Tx, and Rx CEC Commands between the `DUT`, STB, and CEC Adaptor connected on a network | | Test Group | 03 | | Test Case ID | 002 | | Priority | High | **Pre-Conditions:** -The platforms are connected as shown in the picture above and STB and the CEC Adaptor are kept ready before start of the test. +The platforms are connected as shown in the picture above and STB and the CEC Adaptor are kept ready before the start of the test. **Dependencies:** -Pre requisites should be met before starting this test. +Prerequisites should be met before starting this test. **User Interaction:** If the user chooses to run the test in interactive mode, then the test case has to be selected via the console. @@ -133,7 +132,7 @@ If the user chooses to run the test in interactive mode, then the test case has | 14 | Wait for a second to receive data from the CEC adapter on the RxCallback and set the `dataRx` flag to True. Validate the received data with "Hello, World!" and set the `dataRx` flag to False | Test data received should be `0x0F` | Read and validate this data. Data received should be "Hello, World!" | Should be successful | | 15 | Close HDMI CEC HAL using `HdmiCecClose` API | `handle` = valid handle | `HDMI_CEC_IO_SUCCESS` | Should be successful | -# Test 3: Request, Receive and Respond for the basic CEC Commands +# Test 3: Transmit and Receive CEC broadcast Commands Functionality: 1. `DUT` shall broadcast a standby command to the connected devices and STB should receive and act upon the command. @@ -142,16 +141,16 @@ Functionality: | Title | Details | |-------------------------------|--------------------------------------------------| | Function Name | `test_l3_hdmi_cec_sink_broadcast_test` | -| Description | This test shall validate the broadcast CEC Commands between the `DUT`, STB and CEC Adaptor connected on a network | +| Description | This test shall validate the broadcast CEC Commands between the `DUT`, STB, and CEC Adaptor connected on a network | | Test Group | 03 | | Test Case ID | 003 | | Priority | High | **Pre-Conditions:** -The platforms are connected as shown in the picture above and STB and the CEC Adaptor are kept ready before start of the test. +The platforms are connected as shown in the picture above and STB and the CEC Adaptor are kept ready before the start of the test. **Dependencies:** -Pre requisites should be met before starting this test. +Prerequisites should be met before starting this test. **User Interaction:** If the user chooses to run the test in interactive mode, then the test case has to be selected via the console. @@ -175,21 +174,21 @@ If the user chooses to run the test in interactive mode, then the test case has # Test 4: Stress Test Functionality: -1. `DUT` shall respond to a CEC OSD command received from the CEC Adaptor repeatedly for 10 times. Adaptor will be used for a better control from the automation tool. +1. `DUT` shall respond to a CEC OSD command received from the CEC Adaptor repeatedly for 10 times. The adaptor will be used for better control from the automation tool. | Title | Details | |-------------------------------|--------------------------------------------------| | Function Name | `test_l3_hdmi_cec_sink_respond_osd_command_from_adaptor_repeatedly` | -| Description | Receive and respond for the CEC OSD Command with buffer data continesouly for 10 time to prove the robustness of this API. | +| Description | Receive and respond to the CEC OSD Command with buffer data continuously for 10 times to prove the robustness of this API. | | Test Group | 03 | | Test Case ID | 004 | | Priority | High | **Pre-Conditions:** -TV 1 and the STB are already ON before the start of the Test and they have acquired the physical and logical addresses. TV1 and STB should be good enough to support the basic CEC Commands like get CEC Version. +TV 1 and the STB are already ON before the start of the Test and they have acquired the physical and logical addresses. TV1 and STB should be good enough to support the basic CEC Commands like getting the `CEC` Version. **Dependencies:** -Pre requisites should be met before starting this test. +Prerequisites should be met before starting this test. **User Interaction:** If the user chooses to run the test in interactive mode, then the test case has to be selected via the console. @@ -200,8 +199,8 @@ If the user chooses to run the test in interactive mode, then the test case has | 01 | Open HDMI CEC HAL using `HdmiCecOpen` API | `handle` = valid pointer | `HDMI_CEC_IO_SUCCESS` | Should be successful | | 02 | Acquire a valid logical address `0x00` using `HdmiCecAddLogicalAddress` | `handle` = valid handle, `logicalAddress` = 0 | `HDMI_CEC_IO_SUCCESS` | Should be successful | | 03 | Set the receive callback function using `HdmiCecSetRxCallback` | `handle` = valid handle, `cbfunc` = valid callback function pointer, `data` = pointer to the valid data buffer | `HDMI_CEC_IO_SUCCESS` | Should be successful | -| 04 | Wait for a manual command so that CEC Adaptor can send a CEC OSD Command continuously for 10 times | N/A | N/A | Should be successful | -| 05 | Frame a command to Tx Test OSD CEC command with full buffer size from the HDMI CEC adaptor continuously for 10 times | `buf` = {0x05, 0x64, 0x00, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x21} | N/A | Should be successful | +| 04 | Wait for a manual command so that CEC Adaptor can send a CEC OSD Command continuously 10 times | N/A | N/A | Should be successful | +| 05 | Frame command to Tx Test OSD CEC command with full buffer size from the HDMI CEC adaptor continuously for 10 times | `buf` = {0x05, 0x64, 0x00, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x21} | N/A | Should be successful | | 06 | Validate the data received from the DUT when the `dataRx` flag in RxCall back function is set to true for 10 times | Compare the received data with predefined buffer | `buf` = {0x05, 0x64, 0x00, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x21} | Should be successful | | 07 | Close HDMI CEC HAL using `HdmiCecClose` API | `handle` = valid handle | `HDMI_CEC_IO_SUCCESS` | Should be successful | @@ -214,16 +213,16 @@ Functionality: | Title | Details | |-------------------------------|--------------------------------------------------| | Function Name | `test_l3_hdmi_cec_sink_hw_fault_test` | -| Description | Test for the return of proper error code when an hardware fault is introduced into the cec line and trying to Tx the CEC data. | +| Description | Test for the return of proper error code when a hardware fault is introduced into the CEC line and trying to Tx the CEC data. | | Test Group | 03 | | Test Case ID | 005 | | Priority | High | **Pre-Conditions:** -Conntect a HW fault inducer which can pull the HDMI CEC line to high and to normal through a switch. +Connect an HW fault inducer which can pull the HDMI CEC line to high and to normal through a switch. **Dependencies:** -Pre requisites should be met before starting this test. +Prerequisites should be met before starting this test. **User Interaction:** If the user chooses to run the test in interactive mode, then the test case has to be selected via the console. @@ -234,6 +233,6 @@ If the user chooses to run the test in interactive mode, then the test case has | 01 | Open HDMI CEC HAL using `HdmiCecOpen` API | `handle` = valid pointer | `HDMI_CEC_IO_SUCCESS` | Should be successful | | 02 | Acquire a valid logical address `0x00` using `HdmiCecAddLogicalAddress` | `handle` = valid handle, `logicalAddress` = 0 | `HDMI_CEC_IO_SUCCESS` | Should be successful | | 03 | Set the receive callback function using `HdmiCecSetRxCallback` | `handle` = valid handle, `cbfunc` = valid callback function pointer, `data` = pointer to the valid data buffer | `HDMI_CEC_IO_SUCCESS` | Should be successful | -| 04 | Wait for a manual command so that the user is ready to pull the hdmi CEC high high with the help of the fault inducer switch | N/A | N/A | Should be successful | -| 05 | Frame a command to Tx Test OSD CEC command with full buffer size from the `DUT` continuously for 10 times | handle= valid handle, `buf` = {0x05, 0x64, 0x00, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x21} |HDMI_CEC_STATUS and HDMI_CEC_IO_SENT_FAILED | Should be successful | +| 04 | Wait for a manual command so that the user is ready to pull the `HDMI` `CEC` high high with the help of the fault inducer switch | N/A | N/A | Should be successful | +| 05 | Frame command to Tx Test OSD CEC command with full buffer size from the `DUT` continuously for 10 times | handle= valid handle, `buf` = {0x05, 0x64, 0x00, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x21} |HDMI_CEC_STATUS and HDMI_CEC_IO_SENT_FAILED | Should be successful | | 06 | Close HDMI CEC HAL using `HdmiCecClose` API | `handle` = valid handle | `HDMI_CEC_IO_SUCCESS` | Should be successful | From 8c06c4c52d0b643bc69c57fe678f19564ccd96ec Mon Sep 17 00:00:00 2001 From: srinivasgtl <71806084+srinivasgtl@users.noreply.github.com> Date: Mon, 22 Jul 2024 06:57:40 +0100 Subject: [PATCH 03/40] gh #44 Update hdmi-cec-sink-L3-Low-Level_TestSpec.md Updated with lib cec commands. --- .../hdmi-cec-sink-L3-Low-Level_TestSpec.md | 29 +++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md b/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md index 246c457..d62aa23 100644 --- a/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md +++ b/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md @@ -24,14 +24,14 @@ CEC Adaptor: https://www.pulse-eight.com/p/104/usb-hdmi-cec-adapter# ## Module Description -Consumer Electronics Control (`CEC`) is a one-wire bidirectional bus within an HDMI system that enables interconnected products to communicate with each other. This module outlines a set of `HAL` `APIs` designed to support `HDMI` `CEC` functionality. The current document details the L3 test definitions and descriptions used to validate these `HDMI` `CEC` `APIs`, including the prerequisites that must be managed before testing and the external stimuli that need to be applied during the test. +Consumer Electronics Control (`CEC`) is a one-wire bidirectional bus within an HDMI system that enables interconnected products to communicate. This module outlines a set of `HAL` `APIs` designed to support `HDMI` `CEC` functionality. The current document details the L3 test definitions and descriptions used to validate these `HDMI` `CEC` `APIs`, including the prerequisites that must be managed before testing and the external stimuli that need to be applied during the test. The present document describes the test scope for the Sink Device activities only. ### HDMI-CEC L3 Test Functionality The below pic depicts the HDMI CEC L3 Test Functionality Setup. TV 2 marked as `DUT` is the Sink device under test. -Note: All the devices used in the test setup should support `HDMI` `CEC` feature during the entire duration of the test. +Note: All the devices used in the test setup should support `HDMI` `CEC` feature during the entire test duration. ```mermaid graph TB @@ -40,6 +40,17 @@ B --> |HDMI| C[ TV] B -->|USB| C3[PC] ``` +### Pulse-8 CEC Adaptor tool: +The Pulse-8 CEC Adapter will be utilized to frame and send commands to the DUT. This tool leverages libcec, which can be installed to facilitate CEC activities during testing. The cec-client tool will be employed extensively throughout the test. Additionally, RAFT can use this tool to automate the test cases. + +Reference to the tool: https://www.pulse-eight.com/p/104/usb-hdmi-cec-adapter +libcec tools: https://www.pulse-eight.com/Download/Get/51 + +**Commands used during the test:** +To get the COM port of the `CEC` Tool adaptor: cec-client -l +To find the devices connected (with their logical and physical address): echo scan | cec-client -s -d 1 +To Tx and Broadcast: echo tx | cec-client -s -d 1 + #### Logical Address Test 1. Setting the logical address for the `DUT` with the same logical address of the already existing device on the network (STB) @@ -74,7 +85,7 @@ B -->|USB| C3[PC] |Priority|High| **Pre-Conditions:** -1. An STB device should be present in the network which is already acquired the Logical address before the test is performed. +1. An STB device should be present in the network which is already acquired the Logical A before the test is performed. 2. The HMDI CEC Adaptor should provide a way to read the acquired STB logical address. **Dependencies:** @@ -82,6 +93,8 @@ Prerequisites should be met before starting this test. **User Interaction:** The user should be able to get the STB logical address and feed it for the test. +`echo scan | cec-client -s -d 1` shall be used to get the logical address of all the devices connected on the network. + #### Test Procedure | Variation / Steps | Description | Test Data | Expected Result | Notes| @@ -116,6 +129,8 @@ Prerequisites should be met before starting this test. **User Interaction:** If the user chooses to run the test in interactive mode, then the test case has to be selected via the console. +`echo tx | cec-client -s -d 1` shall be used to Transmit the CEC Frames from `HDMI` `CEC` Adaptor. +RAFT can also use these commands or the Andriod libraries. #### Test Procedure @@ -154,6 +169,8 @@ Prerequisites should be met before starting this test. **User Interaction:** If the user chooses to run the test in interactive mode, then the test case has to be selected via the console. +`echo tx | cec-client -s -d 1` shall be used to Broadcast the CEC Frames from `HDMI` `CEC` Adaptor. +RAFT can also use these commands or the Andriod libraries. #### Test Procedure ## New Test Plan (Broadcast Commands) @@ -192,6 +209,8 @@ Prerequisites should be met before starting this test. **User Interaction:** If the user chooses to run the test in interactive mode, then the test case has to be selected via the console. +`echo tx | cec-client -s -d 1` shall be used to Broadcast the CEC Frames from `HDMI` `CEC` Adaptor. +RAFT can also use these commands or the Andriod libraries. #### Test Procedure | Variation / Steps | Description | Test Data | Expected Result | Notes | @@ -213,7 +232,7 @@ Functionality: | Title | Details | |-------------------------------|--------------------------------------------------| | Function Name | `test_l3_hdmi_cec_sink_hw_fault_test` | -| Description | Test for the return of proper error code when a hardware fault is introduced into the CEC line and trying to Tx the CEC data. | +| Description | Test for the return of proper error code when a hardware fault is introduced into the CEC line and try to Tx the CEC data. | | Test Group | 03 | | Test Case ID | 005 | | Priority | High | @@ -233,6 +252,6 @@ If the user chooses to run the test in interactive mode, then the test case has | 01 | Open HDMI CEC HAL using `HdmiCecOpen` API | `handle` = valid pointer | `HDMI_CEC_IO_SUCCESS` | Should be successful | | 02 | Acquire a valid logical address `0x00` using `HdmiCecAddLogicalAddress` | `handle` = valid handle, `logicalAddress` = 0 | `HDMI_CEC_IO_SUCCESS` | Should be successful | | 03 | Set the receive callback function using `HdmiCecSetRxCallback` | `handle` = valid handle, `cbfunc` = valid callback function pointer, `data` = pointer to the valid data buffer | `HDMI_CEC_IO_SUCCESS` | Should be successful | -| 04 | Wait for a manual command so that the user is ready to pull the `HDMI` `CEC` high high with the help of the fault inducer switch | N/A | N/A | Should be successful | +| 04 | Wait for a manual command so that the user is ready to pull the `HDMI` `CEC` high with the help of the fault inducer switch | N/A | N/A | Should be successful | | 05 | Frame command to Tx Test OSD CEC command with full buffer size from the `DUT` continuously for 10 times | handle= valid handle, `buf` = {0x05, 0x64, 0x00, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x21} |HDMI_CEC_STATUS and HDMI_CEC_IO_SENT_FAILED | Should be successful | | 06 | Close HDMI CEC HAL using `HdmiCecClose` API | `handle` = valid handle | `HDMI_CEC_IO_SUCCESS` | Should be successful | From e3240dda3da389859c03c53f9f971e4ec3d39eff Mon Sep 17 00:00:00 2001 From: srinivasgtl <71806084+srinivasgtl@users.noreply.github.com> Date: Mon, 22 Jul 2024 11:27:27 +0100 Subject: [PATCH 04/40] gh #44 Update hdmi-cec-sink-L3-Low-Level_TestSpec.md Typo mistakes --- .../hdmi-cec-sink-L3-Low-Level_TestSpec.md | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md b/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md index d62aa23..86f1951 100644 --- a/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md +++ b/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md @@ -35,7 +35,7 @@ Note: All the devices used in the test setup should support `HDMI` `CEC` feature ```mermaid graph TB -A[STB] -->|HDMI| B[CEC Adaptor] +A[STB] -->|HDMI| B[Pulse-8 CEC Adaptor] B --> |HDMI| C[ TV] B -->|USB| C3[PC] ``` @@ -47,18 +47,19 @@ Reference to the tool: https://www.pulse-eight.com/p/104/usb-hdmi-cec-adapter libcec tools: https://www.pulse-eight.com/Download/Get/51 **Commands used during the test:** -To get the COM port of the `CEC` Tool adaptor: cec-client -l -To find the devices connected (with their logical and physical address): echo scan | cec-client -s -d 1 -To Tx and Broadcast: echo tx | cec-client -s -d 1 +- To get the COM port of the `CEC` Tool adaptor: ```cec-client -l``` +- To find the devices connected (with their logical and physical address): ```echo scan | cec-client -s -d 1``` +- To Tx and Broadcast: ```echo tx | cec-client -s -d 1``` +## Test Functionalities #### Logical Address Test 1. Setting the logical address for the `DUT` with the same logical address of the already existing device on the network (STB) #### Message Transmission and Reception Test -2. Transmitting HDMI CEC Command to receive a reply. -3. Broadcasting a HDMI CEC Command to put the STB into Standby state. -4. Recieve a standby broadcasting command sent by the CEC Adaptor -5. Receiving an HDMI OSD Command with a string of max length (14 bytes ) from CEC Adaptor. +2. Transmitting HDMI CEC basic command (GetCECVersion) from the `DUT` to receive a reply from the connected device +3. Broadcasting an HDMI CEC Command from the `DUT` to put the STB into the standby state +4. Recieve a standby broadcasting command on the `DUT` sent by the CEC Adaptor +5. Receiving an HDMI OSD Command with a string of max length (14 bytes ) from the CEC Adaptor #### Stress Test 6. Receiving an HDMI OSD Command repeatedly for 10 times with a string of max length from CEC Adaptor. @@ -92,8 +93,8 @@ To Tx and Broadcast: echo tx | cec-client -s -d 1 Prerequisites should be met before starting this test. **User Interaction:** -The user should be able to get the STB logical address and feed it for the test. -`echo scan | cec-client -s -d 1` shall be used to get the logical address of all the devices connected on the network. +- The user should be able to get the STB logical address and feed it for the test. +- `echo scan | cec-client -s -d 1` shall be used to get the logical address of all the devices connected to the network. #### Test Procedure @@ -109,8 +110,7 @@ The user should be able to get the STB logical address and feed it for the test. Functionality: 1. `DUT` shall request a CEC Version from the Source Device (STB). It should receive a valid version and be evaluated. -2. `DUT` shall receive a standby command as a unicast command from the CEC Adaptor. -3. `DUT` shall receive an OSD Command with max buffer size from the CEC Adaptor and respond to this command. +2. `DUT` shall receive an OSD Command with max buffer size from the CEC Adaptor and respond to this command. | Title | Details | @@ -128,8 +128,8 @@ The platforms are connected as shown in the picture above and STB and the CEC Ad Prerequisites should be met before starting this test. **User Interaction:** -If the user chooses to run the test in interactive mode, then the test case has to be selected via the console. -`echo tx | cec-client -s -d 1` shall be used to Transmit the CEC Frames from `HDMI` `CEC` Adaptor. +- If the user chooses to run the test in interactive mode, then the test case has to be selected via the console. +- `echo tx | cec-client -s -d 1` shall be used to Transmit the CEC Frames from `HDMI` `CEC` Adaptor. RAFT can also use these commands or the Andriod libraries. #### Test Procedure @@ -142,10 +142,10 @@ RAFT can also use these commands or the Andriod libraries. | 04 | Get the connected device (STB) logical address manually. Wait until this data is entered | N/A | N/A | Enter the logical address of the STB as read on the CEC adapter | | 05 | Frame a command to transmit CEC frames to get the CEC version of the connected STB using `HdmiCecTx` | `handle` = valid handle, `buf` = {0x47, 0x9F}, `len` = sizeof(buf), `result` = valid pointer | `HDMI_CEC_IO_SUCCESS` | Should be successful | | 06 | Wait for a second and validate a response from the STB on the RxCallback and set the `dataRx` flag to True. Validate the received data and set the `dataRx` flag to False | Test data received from STB | Read and validate this data. Rx data should be a valid CEC version | Should be successful | -| 12 | Frame and send a CEC OSD command with full buffer data with `DUT` logical address from CEC adapter | `buffer` = {0x02, 0x64, "Hello, World!"} | N/A | User to set this data through CEC adapter | -| 13 | Wait for the user to signal when the CEC command is sent in step 12 | User to press `y` to move | N/A | User to signal once the CEC command is sent | -| 14 | Wait for a second to receive data from the CEC adapter on the RxCallback and set the `dataRx` flag to True. Validate the received data with "Hello, World!" and set the `dataRx` flag to False | Test data received should be `0x0F` | Read and validate this data. Data received should be "Hello, World!" | Should be successful | -| 15 | Close HDMI CEC HAL using `HdmiCecClose` API | `handle` = valid handle | `HDMI_CEC_IO_SUCCESS` | Should be successful | +| 07 | Frame and send a CEC OSD command with full buffer data with `DUT` logical address from CEC adapter | `buffer` = {0x02, 0x64, "Hello, World!"} | N/A | User to set this data through CEC adapter | +| 08 | Wait for the user to signal when the CEC command is sent in step 12 | User to press `y` to move | N/A | User to signal once the CEC command is sent | +| 09 | Wait for a second to receive data from the CEC adapter on the RxCallback and set the `dataRx` flag to True. Validate the received data with "Hello, World!" and set the `dataRx` flag to False | Test data received should be `0x0F` | Read and validate this data. Data received should be "Hello, World!" | Should be successful | +| 10 | Close HDMI CEC HAL using `HdmiCecClose` API | `handle` = valid handle | `HDMI_CEC_IO_SUCCESS` | Should be successful | # Test 3: Transmit and Receive CEC broadcast Commands @@ -168,8 +168,8 @@ The platforms are connected as shown in the picture above and STB and the CEC Ad Prerequisites should be met before starting this test. **User Interaction:** -If the user chooses to run the test in interactive mode, then the test case has to be selected via the console. -`echo tx | cec-client -s -d 1` shall be used to Broadcast the CEC Frames from `HDMI` `CEC` Adaptor. +- If the user chooses to run the test in interactive mode, then the test case has to be selected via the console. +- `echo tx | cec-client -s -d 1` shall be used to Broadcast the CEC Frames from `HDMI` `CEC` Adaptor. RAFT can also use these commands or the Andriod libraries. #### Test Procedure @@ -208,8 +208,8 @@ TV 1 and the STB are already ON before the start of the Test and they have acqui Prerequisites should be met before starting this test. **User Interaction:** -If the user chooses to run the test in interactive mode, then the test case has to be selected via the console. -`echo tx | cec-client -s -d 1` shall be used to Broadcast the CEC Frames from `HDMI` `CEC` Adaptor. +- If the user chooses to run the test in interactive mode, then the test case has to be selected via the console. +- `echo tx | cec-client -s -d 1` shall be used to Broadcast the CEC Frames from `HDMI` `CEC` Adaptor. RAFT can also use these commands or the Andriod libraries. #### Test Procedure From 5eb801bf1b57977f1fb285085891f84ea86c1e94 Mon Sep 17 00:00:00 2001 From: srinivasgtl <71806084+srinivasgtl@users.noreply.github.com> Date: Tue, 23 Jul 2024 21:22:26 +0100 Subject: [PATCH 05/40] gh #44 Update hdmi-cec-sink-L3-Low-Level_TestSpec.md Updated with some basic RAFT requirements. Modified the design to use only a single Adaptor which can send, receive, and respond to the commands. --- .../hdmi-cec-sink-L3-Low-Level_TestSpec.md | 79 ++++++------------- 1 file changed, 24 insertions(+), 55 deletions(-) diff --git a/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md b/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md index 86f1951..f2c3ce4 100644 --- a/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md +++ b/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md @@ -31,13 +31,14 @@ The present document describes the test scope for the Sink Device activities onl ### HDMI-CEC L3 Test Functionality The below pic depicts the HDMI CEC L3 Test Functionality Setup. TV 2 marked as `DUT` is the Sink device under test. -Note: All the devices used in the test setup should support `HDMI` `CEC` feature during the entire test duration. +Note: The below-shown prerequisites should be met before starting the test on the platforms. +- All the devices used in the test setup should support the `HDMI` `CEC` feature during the entire test duration. +- HDMI drivers should be up and running on the platform before running this test. ```mermaid graph TB -A[STB] -->|HDMI| B[Pulse-8 CEC Adaptor] -B --> |HDMI| C[ TV] -B -->|USB| C3[PC] +C[PC] <--> A +A[Pulse-8 - 1] <--> |HDMI| B[TV] ``` ### Pulse-8 CEC Adaptor tool: @@ -51,72 +52,40 @@ libcec tools: https://www.pulse-eight.com/Download/Get/51 - To find the devices connected (with their logical and physical address): ```echo scan | cec-client -s -d 1``` - To Tx and Broadcast: ```echo tx | cec-client -s -d 1``` +**Libraries and tools required for RAFT** +- python-cec will be used to control the `CEC` adaptor. +- https://pypi.org/project/cec/ will provide more information on how to use this library. + +**Prerequisite Test to make sure all the CEC Adaptors are connected** +1. Make sure to read the physical address of the CEC Adaptor allocated based on the port it has been connected to, using libCEC on RAFT. +2. The physical and logical addresses allocated to the CEC adaptor shall be read and validated on RAFT. + ## Test Functionalities -#### Logical Address Test -1. Setting the logical address for the `DUT` with the same logical address of the already existing device on the network (STB) #### Message Transmission and Reception Test -2. Transmitting HDMI CEC basic command (GetCECVersion) from the `DUT` to receive a reply from the connected device -3. Broadcasting an HDMI CEC Command from the `DUT` to put the STB into the standby state -4. Recieve a standby broadcasting command on the `DUT` sent by the CEC Adaptor -5. Receiving an HDMI OSD Command with a string of max length (14 bytes ) from the CEC Adaptor +- Transmit an HDMI CEC basic command (GetCECVersion) from the DUT to receive a reply from the connected CEC Adaptor. +- Broadcast an HDMI CEC Command from the DUT and verify that this command has been received on the CEC Adaptor. +- Receive a standby broadcasting command on the DUT sent by the CEC Adaptor and validate it. +- Receive an HDMI OSD Command with a string of maximum length (14 bytes) from the CEC Adaptor. +- The CEC Adaptor sends a standby command to a device with a logical address other than the DUT logical address and ensures no callback is received. #### Stress Test -6. Receiving an HDMI OSD Command repeatedly for 10 times with a string of max length from CEC Adaptor. +- Receiving an HDMI OSD Command repeatedly for 10 times with a different string of max length from CEC Adaptor. #### Hardware Fault Test -7. Introducing a Fault on the HDMI line to test the Transmit functionality. - - -# Test 1: Logical Address Test - -### Functionality: -1. The `DUT` should attempt to acquire a logical address that is already in use. +- Introducing a Fault on the HDMI line to test the Transmit functionality. -### Pre-requisites: -1. First, set the STB to ON state to enable it to acquire a Logical address. -2. HDMI CEC Adaptor should be able to help in getting the STB logical address for further activities. -|Title|Details| -|--|--| -|Function Name|`test_l3_hdmi_cec_sink_hal_AcquireLogicalAddress`| -|Description|This function performs to acquire a Logical address that is already acquired by the STB. This should prove the capability of the HAL API HdmiCecAddLogicalAddress() where it shall fail to acquire a Logical address that is already been taken | -|Test Group|03| -|Test Case ID|001| -|Priority|High| - -**Pre-Conditions:** -1. An STB device should be present in the network which is already acquired the Logical A before the test is performed. -2. The HMDI CEC Adaptor should provide a way to read the acquired STB logical address. - -**Dependencies:** -Prerequisites should be met before starting this test. - -**User Interaction:** -- The user should be able to get the STB logical address and feed it for the test. -- `echo scan | cec-client -s -d 1` shall be used to get the logical address of all the devices connected to the network. - - -#### Test Procedure -| Variation / Steps | Description | Test Data | Expected Result | Notes| -| -- | --------- | ---------- | -------------- | ----- | -| 01 | Open HDMI CEC HAL using HdmiCecOpen API | handle = valid pointer | HDMI_CEC_IO_SUCCESS | Should be successful | -| 02 | Wait to enter the STB logical address | NA | NA | Feed the logical Address of the STB manually | -| 03 | Try acquiring the STB logical address using HdmiCecAddLogicalAddress()| handle = valid handle, logicalAddress = STB logical address | HDMI_CEC_IO_LOGICALADDRESS_UNAVAILABLE | Should be successful | -| 04 | Close HDMI CEC HAL using HdmiCecClose API | handle = valid handle | HDMI_CEC_IO_SUCCESS | Should be successful | - - -# Test 2: Request, Receive, and Respond to the basic CEC Commands +# Test 1: Message Transmission and Reception Test - Unicast messages Functionality: -1. `DUT` shall request a CEC Version from the Source Device (STB). It should receive a valid version and be evaluated. -2. `DUT` shall receive an OSD Command with max buffer size from the CEC Adaptor and respond to this command. - +1. `DUT` shall request a CEC Version from the CEC adaptor connected. It should receive a valid version and be evaluated. +2. `DUT` shall receive an OSD Command with max buffer size from the CEC Adaptor and respond to this command. | Title | Details | |-------------------------------|--------------------------------------------------| | Function Name | `test_l3_hdmi_cec_sink_tx_rx_test` | -| Description | This test shall validate the Tx, and Rx CEC Commands between the `DUT`, STB, and CEC Adaptor connected on a network | +| Description | This test shall validate the Tx, and Rx CEC Commands between the `DUT`and CEC Adaptor connected on a network | | Test Group | 03 | | Test Case ID | 002 | | Priority | High | From c68bf775b6aca7e83d7184ef022b0dedc26ce2ca Mon Sep 17 00:00:00 2001 From: srinivasgtl <71806084+srinivasgtl@users.noreply.github.com> Date: Wed, 24 Jul 2024 07:28:18 +0100 Subject: [PATCH 06/40] gh #44 Update hdmi-cec-sink-L3-Low-Level_TestSpec.md Updating RAFT info. --- docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md b/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md index f2c3ce4..0e909d9 100644 --- a/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md +++ b/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md @@ -41,8 +41,8 @@ C[PC] <--> A A[Pulse-8 - 1] <--> |HDMI| B[TV] ``` -### Pulse-8 CEC Adaptor tool: -The Pulse-8 CEC Adapter will be utilized to frame and send commands to the DUT. This tool leverages libcec, which can be installed to facilitate CEC activities during testing. The cec-client tool will be employed extensively throughout the test. Additionally, RAFT can use this tool to automate the test cases. +### Pulse Eight CEC Adaptor tool: +The Pulse-Eight CEC Adapter will be utilized to frame and send commands to the DUT. This tool leverages libcec, which can be installed to facilitate CEC activities during testing. The cec-client tool will be employed extensively throughout the test. Additionally, RAFT can use this tool to automate the test cases. Reference to the tool: https://www.pulse-eight.com/p/104/usb-hdmi-cec-adapter libcec tools: https://www.pulse-eight.com/Download/Get/51 @@ -53,6 +53,7 @@ libcec tools: https://www.pulse-eight.com/Download/Get/51 - To Tx and Broadcast: ```echo tx | cec-client -s -d 1``` **Libraries and tools required for RAFT** +- libcec should be installed on the PC where the Pulse-Eight CEC Adaptor is connected. - python-cec will be used to control the `CEC` adaptor. - https://pypi.org/project/cec/ will provide more information on how to use this library. @@ -63,7 +64,9 @@ libcec tools: https://www.pulse-eight.com/Download/Get/51 ## Test Functionalities #### Message Transmission and Reception Test -- Transmit an HDMI CEC basic command (GetCECVersion) from the DUT to receive a reply from the connected CEC Adaptor. +Note: All the below tests should be carried out on all the available HMDI ports. + +- Transmit an HDMI CEC basic command (GetCECVersion) from the DUT to receive a reply from the connected CEC Adaptor. - Broadcast an HDMI CEC Command from the DUT and verify that this command has been received on the CEC Adaptor. - Receive a standby broadcasting command on the DUT sent by the CEC Adaptor and validate it. - Receive an HDMI OSD Command with a string of maximum length (14 bytes) from the CEC Adaptor. @@ -91,7 +94,8 @@ Functionality: | Priority | High | **Pre-Conditions:** -The platforms are connected as shown in the picture above and STB and the CEC Adaptor are kept ready before the start of the test. +- The platforms are connected as shown in the picture above and STB and the CEC Adaptor are kept ready before the start of the test. +- libcec is installed on the PC where the PulseEight tool is connected. libcec will respond to all the basic CEC Commands received from `DUT` **Dependencies:** Prerequisites should be met before starting this test. @@ -99,7 +103,7 @@ Prerequisites should be met before starting this test. **User Interaction:** - If the user chooses to run the test in interactive mode, then the test case has to be selected via the console. - `echo tx | cec-client -s -d 1` shall be used to Transmit the CEC Frames from `HDMI` `CEC` Adaptor. -RAFT can also use these commands or the Andriod libraries. + #### Test Procedure From ab6c14b5e422e1e48b401bdb848f23d7999e6d88 Mon Sep 17 00:00:00 2001 From: srinivasgtl <71806084+srinivasgtl@users.noreply.github.com> Date: Wed, 24 Jul 2024 16:32:29 +0100 Subject: [PATCH 07/40] gh #44 Update hdmi-cec-sink-L3-Low-Level_TestSpec.md RAFT updates. --- .../hdmi-cec-sink-L3-Low-Level_TestSpec.md | 130 +++++++++++++----- 1 file changed, 99 insertions(+), 31 deletions(-) diff --git a/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md b/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md index 0e909d9..f585c62 100644 --- a/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md +++ b/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md @@ -12,10 +12,12 @@ This document provides an overview of the L3 testing requirements for the module ## Acronyms, Terms and Abbreviations - `CEC` - Consumer Electronics Control - `HAL` - Hardware Abstraction layer -- `HDMI` - High Definition Multimedia Interface +- `HDMI` - High Definition Multimedia Interface - `API` - Application Program Interface - `SoC` - System on Chip -- `DUT` - Device Under Test. +- `DUT` - Device Under Test +- `LA` - Logical Address +- `PA` - Physical Address ## References @@ -70,7 +72,7 @@ Note: All the below tests should be carried out on all the available HMDI ports. - Broadcast an HDMI CEC Command from the DUT and verify that this command has been received on the CEC Adaptor. - Receive a standby broadcasting command on the DUT sent by the CEC Adaptor and validate it. - Receive an HDMI OSD Command with a string of maximum length (14 bytes) from the CEC Adaptor. -- The CEC Adaptor sends a standby command to a device with a logical address other than the DUT logical address and ensures no callback is received. +- The CEC Adaptor sends a standby command to a device with a logical address other than the DUT logical address, ensuring no callback is received. #### Stress Test - Receiving an HDMI OSD Command repeatedly for 10 times with a different string of max length from CEC Adaptor. @@ -83,7 +85,8 @@ Note: All the below tests should be carried out on all the available HMDI ports. Functionality: 1. `DUT` shall request a CEC Version from the CEC adaptor connected. It should receive a valid version and be evaluated. -2. `DUT` shall receive an OSD Command with max buffer size from the CEC Adaptor and respond to this command. +2. `DUT` shall receive an OSD Command with max buffer size from the CEC Adaptor and respond to this command. +3. `DUT` shall receive a "getCECVersion" command with a different `LA` which should not generate any callback. | Title | Details | |-------------------------------|--------------------------------------------------| @@ -102,8 +105,32 @@ Prerequisites should be met before starting this test. **User Interaction:** - If the user chooses to run the test in interactive mode, then the test case has to be selected via the console. -- `echo tx | cec-client -s -d 1` shall be used to Transmit the CEC Frames from `HDMI` `CEC` Adaptor. - +- RAFT will replace the human to run the test, but still, the RAFT should provide an option for the user to change the HMDI ports and start the test again. + +**RAFT Requirements:** +- RAFT shall initiate the test by reading and validating the LA and PA. +- RAFT shall initiate the commands to send the CEC OSD command with the string data as read from the hdmicec_sinktest.yml file. +- RAFT shall provide a means to enter the LA for the test and any other data required during the test. + +**Sequence Diagram** +```mermaid +sequenceDiagram + participant DUT + participant CEC Adaptor + participant RAFT + RAFT->>CEC Adaptor: Read and validate LA and PA + RAFT->>DUT: Start the HAL test + DUT->>DUT: Add Logical Address + DUT->>DUT: Set receive Callback + DUT->>CEC Adaptor: Send "GetCECVersion" + CEC Adaptor->>DUT: Send the "CEC Version" + DUT->>DUT: Validate CEC Version + RAFT->>CEC Adaptor: Command to send CEC OSD Command + CEC Adaptor->>DUT: Send CEC OSD Command + DUT-->>DUT: Validate the received command + CEC Adaptor->>DUT: Send "GetCECVersion" to a LA other than `DUT` + DUT-->>DUT: No RxCallaback is received. +``` #### Test Procedure @@ -112,24 +139,27 @@ Prerequisites should be met before starting this test. | 01 | Open HDMI CEC HAL using `HdmiCecOpen` API | `handle` = valid pointer | `HDMI_CEC_IO_SUCCESS` | Should be successful | | 02 | Acquire a valid logical address `0x00` using `HdmiCecAddLogicalAddress` | `handle` = valid handle, `logicalAddress` = 0 | `HDMI_CEC_IO_SUCCESS` | Should be successful | | 03 | Set the receive callback function using `HdmiCecSetRxCallback` | `handle` = valid handle, `cbfunc` = RxCallback, `data` = buffer pointer | `HDMI_CEC_IO_SUCCESS` | Should be successful | -| 04 | Get the connected device (STB) logical address manually. Wait until this data is entered | N/A | N/A | Enter the logical address of the STB as read on the CEC adapter | -| 05 | Frame a command to transmit CEC frames to get the CEC version of the connected STB using `HdmiCecTx` | `handle` = valid handle, `buf` = {0x47, 0x9F}, `len` = sizeof(buf), `result` = valid pointer | `HDMI_CEC_IO_SUCCESS` | Should be successful | -| 06 | Wait for a second and validate a response from the STB on the RxCallback and set the `dataRx` flag to True. Validate the received data and set the `dataRx` flag to False | Test data received from STB | Read and validate this data. Rx data should be a valid CEC version | Should be successful | -| 07 | Frame and send a CEC OSD command with full buffer data with `DUT` logical address from CEC adapter | `buffer` = {0x02, 0x64, "Hello, World!"} | N/A | User to set this data through CEC adapter | -| 08 | Wait for the user to signal when the CEC command is sent in step 12 | User to press `y` to move | N/A | User to signal once the CEC command is sent | -| 09 | Wait for a second to receive data from the CEC adapter on the RxCallback and set the `dataRx` flag to True. Validate the received data with "Hello, World!" and set the `dataRx` flag to False | Test data received should be `0x0F` | Read and validate this data. Data received should be "Hello, World!" | Should be successful | -| 10 | Close HDMI CEC HAL using `HdmiCecClose` API | `handle` = valid handle | `HDMI_CEC_IO_SUCCESS` | Should be successful | +| 04 | Wait to get the connected device (CEC Adaptor) logical address from RAFT.| N/A | N/A | RAFT to enter the LA address of the CEC Adaptor | +| 05 | Frame a getCECVersion command using the "getcecVersion" command from the test yaml file and send it using using `HdmiCecTx` | `handle` = valid handle, `buf` = cec buffer with LA and command, `len` = sizeof(buf), `result` = valid pointer | `HDMI_CEC_IO_SUCCESS` | Should be successful | +| 06 | Wait for a second and validate a response from the CEC Adaptor on the RxCallback and validate | Test data received from CEC Adaptor | Read and validate this data. Rx data should be a valid CEC version | Should be successful | +| 07 | Frame and send a CEC OSD command based on "setosd" on the test yaml file and transmit this data to `DUT`. | `buffer` = LA, Command and data from test yaml | N/A | RAFT to set this data through CEC adapter | +| 08 | Wait for the RAFT to signal when the CEC command is sent in step 7 | NA | N/A | RAFT to signal once the CEC command is sent | +| 09 | Validate the data received on `DUT` with the "setosd" command data on the test yaml file| Test data received shall match with the data in yaml | Read and validate this data| Should be successful | +| 10 | Frame and send a CEC command based on "getcecVersion" on the test yaml file and transmit this data to the LA address other than `DUT`. | `buffer` = LA of non existing device and
data read from test yaml | N/A | RAFT to set this data through CEC adapter | +| 11 | Wait for the RAFT to signal when the CEC command is sent in step 11 | NA | N/A | RAFT to signal once the CEC command is sent | +| 12 | Validate the data received on CEC with the "setosd" command on the test yaml file| Test data received should match with the data in yaml | Read and validate this data| Should be successful | +| 13 | Close HDMI CEC HAL using `HdmiCecClose` API | `handle` = valid handle | `HDMI_CEC_IO_SUCCESS` | Should be successful | # Test 3: Transmit and Receive CEC broadcast Commands Functionality: -1. `DUT` shall broadcast a standby command to the connected devices and STB should receive and act upon the command. -2. `DUT` shall receive a standby command as a broadcast command from the CEC Adaptor. +1. `DUT` shall broadcast a standby command to the connected devices and RAFT should validate this received command on the CEC Adaptor. +2. `DUT` shall receive a standby command as a broadcast command from the CEC Adaptor. RAFT to initiate and command the Test. | Title | Details | |-------------------------------|--------------------------------------------------| | Function Name | `test_l3_hdmi_cec_sink_broadcast_test` | -| Description | This test shall validate the broadcast CEC Commands between the `DUT`, STB, and CEC Adaptor connected on a network | +| Description | This test shall validate the broadcast CEC Commands between the `DUT`, and the CEC Adaptor connected on a network | | Test Group | 03 | | Test Case ID | 003 | | Priority | High | @@ -142,8 +172,28 @@ Prerequisites should be met before starting this test. **User Interaction:** - If the user chooses to run the test in interactive mode, then the test case has to be selected via the console. -- `echo tx | cec-client -s -d 1` shall be used to Broadcast the CEC Frames from `HDMI` `CEC` Adaptor. -RAFT can also use these commands or the Andriod libraries. +- RAFT will replace the human to run the test, but still, the RAFT should provide an option for the user to change the HMDI ports and start the test again. + +**RAFT Requirements:** +- RAFT shall initiate the commands to broadcast the standby CEC command with the string data as read from the hdmicec_sinktest.yml file. +- RAFT provides an interface for the user to change the HMDI port and start the test again. + +**Sequence Diagram** +```mermaid +sequenceDiagram + participant DUT + participant CEC Adaptor + participant RAFT + RAFT->>CEC Adaptor: Read and validate LA and PA + RAFT->>DUT: Start the HAL test + DUT->>DUT: Add Logical Address + DUT->>DUT: Set receive Callback + DUT->>CEC Adaptor: Broadcast "standby" + RAFT->>CEC Adaptor: Validate the CEC Command received on the `CEC` adaptor + RAFT->>CEC Adaptor: Board "standby" command" + CEC Adaptor->> DUT: Receive the standby command + DUT-->>DUT: Validate the received command +``` #### Test Procedure ## New Test Plan (Broadcast Commands) @@ -153,37 +203,56 @@ RAFT can also use these commands or the Andriod libraries. | 01 | Open HDMI CEC HAL using `HdmiCecOpen` API | `handle` = valid pointer | `HDMI_CEC_IO_SUCCESS` | Should be successful | | 02 | Acquire a valid logical address `0x00` using `HdmiCecAddLogicalAddress` | `handle` = valid handle, `logicalAddress` = 0 | `HDMI_CEC_IO_SUCCESS` | Should be successful | | 03 | Set the receive callback function using `HdmiCecSetRxCallback` | `handle` = valid handle, `cbfunc` = RxCallback, `data` = buffer pointer | `HDMI_CEC_IO_SUCCESS` | Should be successful | -| 04 | Frame a command to broadcast CEC frames to put the connected STB into standby state using `HdmiCecTx` | `handle` = valid handle, `buf` = {0x0F, 0x36}, `len` = sizeof(buf), `result` = valid pointer | `HDMI_CEC_IO_SUCCESS` | Should be successful.
Buffer data may change based on STB logical address | -| 05 | Wait for the user to respond indicating test pass or fail | `1` for pass and `0` for fail | N/A | User to enter the result | -| 06 | Frame and send a CEC command to broadcast standby command from CEC adapter | `buffer` = {0x2F, 0x36} | N/A | User to set this data through CEC adapter | -| 07 | Wait for the user to signal when the CEC broadcast is sent in step 6 | User to press `y` to move | N/A | User to signal once the CEC broadcast is set | -| 08 | Wait for a second to receive data from the CEC adapter on the RxCallback and set the `dataRx` flag to True. Validate the received data with `0x36` and set the `dataRx` flag to False | Test data received should be `0x0F` | Read and validate this data. Data received should be `0x36` (standby data) | Should be successful | +| 04 | Frame a standby command to broadcast from `DUT` to all the connected devices using `HdmiCecTx`. Test command and data shall be read from test yaml | `handle` = valid handle, `buf` = as read from yaml file, `len` = sizeof(buf), `result` = valid pointer | `HDMI_CEC_IO_SUCCESS` | Should be successful| +| 05 | RAFT should receive this data and validate the command received. The test should wait for the RAFT to enter the test result based on the validation | NA| N/A | RAFT to provide the result | +| 06 | RAFT to command CEC adaptor to frame and broadcast the standby CEC command. Test data should be read from test yaml file | `buffer` = test yaml file data | N/A | RAFT to set this data through CEC adapter | +| 07 | Wait for the RAFT to signal when the CEC broadcast is sent in step 6 | RAFT to provide `y` to move | N/A | RAFT to signal once the CEC broadcast is set | +| 08 | Received data from the CEC adapter on the RxCallback shall be validated. Received data shall be validated against the test yaml file | Test data received should be as mentioned in the test yaml file | Read and validate this data | Should be successful | | 09 | Close HDMI CEC HAL using `HdmiCecClose` API | `handle` = valid handle | `HDMI_CEC_IO_SUCCESS` | Should be successful | # Test 4: Stress Test Functionality: -1. `DUT` shall respond to a CEC OSD command received from the CEC Adaptor repeatedly for 10 times. The adaptor will be used for better control from the automation tool. +1. `DUT` shall respond to a CEC OSD command received from the CEC Adaptor continuously 10 times with different strings and validate. | Title | Details | |-------------------------------|--------------------------------------------------| | Function Name | `test_l3_hdmi_cec_sink_respond_osd_command_from_adaptor_repeatedly` | -| Description | Receive and respond to the CEC OSD Command with buffer data continuously for 10 times to prove the robustness of this API. | +| Description | Receive and respond to the CEC OSD Command with buffer data continuously 10 times to prove the robustness of this API. | | Test Group | 03 | | Test Case ID | 004 | | Priority | High | **Pre-Conditions:** -TV 1 and the STB are already ON before the start of the Test and they have acquired the physical and logical addresses. TV1 and STB should be good enough to support the basic CEC Commands like getting the `CEC` Version. +- The platforms are connected as shown in the picture above and STB and the CEC Adaptor are kept ready before the start of the test. +- libcec is installed on the PC where the PulseEight tool is connected. libcec will respond to all the basic CEC Commands received from `DUT` **Dependencies:** Prerequisites should be met before starting this test. **User Interaction:** - If the user chooses to run the test in interactive mode, then the test case has to be selected via the console. -- `echo tx | cec-client -s -d 1` shall be used to Broadcast the CEC Frames from `HDMI` `CEC` Adaptor. -RAFT can also use these commands or the Andriod libraries. +- RAFT will replace the human to run the test, but still, the RAFT should provide an option for the user to change the HMDI ports and start the test again. + +**RAFT Requirements:** +- RAFT shall initiate the test by reading and validating the LA and PA. +- RAFT shall initiate the commands to send the CEC OSD command with the string data as read from the hdmicec_sinktest.yml file. + +**Sequence Diagram** +```mermaid +sequenceDiagram + participant DUT + participant CEC Adaptor + participant RAFT + RAFT->>CEC Adaptor: Read and validate LA and PA + RAFT->>DUT: Start the HAL test + DUT->>DUT: Add Logical Address + DUT->>DUT: Set receive Callback + RAFT->>CEC Adaptor: Command to send CEC OSD Command for 10 times + CEC Adaptor->>DUT: Send CEC OSD Command for 10 times + DUT-->>DUT: Validate the received command for 10 times +``` #### Test Procedure | Variation / Steps | Description | Test Data | Expected Result | Notes | @@ -191,9 +260,8 @@ RAFT can also use these commands or the Andriod libraries. | 01 | Open HDMI CEC HAL using `HdmiCecOpen` API | `handle` = valid pointer | `HDMI_CEC_IO_SUCCESS` | Should be successful | | 02 | Acquire a valid logical address `0x00` using `HdmiCecAddLogicalAddress` | `handle` = valid handle, `logicalAddress` = 0 | `HDMI_CEC_IO_SUCCESS` | Should be successful | | 03 | Set the receive callback function using `HdmiCecSetRxCallback` | `handle` = valid handle, `cbfunc` = valid callback function pointer, `data` = pointer to the valid data buffer | `HDMI_CEC_IO_SUCCESS` | Should be successful | -| 04 | Wait for a manual command so that CEC Adaptor can send a CEC OSD Command continuously 10 times | N/A | N/A | Should be successful | -| 05 | Frame command to Tx Test OSD CEC command with full buffer size from the HDMI CEC adaptor continuously for 10 times | `buf` = {0x05, 0x64, 0x00, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x21} | N/A | Should be successful | -| 06 | Validate the data received from the DUT when the `dataRx` flag in RxCall back function is set to true for 10 times | Compare the received data with predefined buffer | `buf` = {0x05, 0x64, 0x00, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x21} | Should be successful | +| 04 | RAFT shall wait for a signal from `DUT`so that it can signal the CEC Adaptor to send a CEC OSD Command continuously 10 times with different data available in test yaml file | N/A | N/A | Should be successful | +| 05 | Validate the data received on the DUT and compare the data with the data from "setosd/data" on test yaml file | Compare the received data with "setosd/data" on test yaml | NA | Should be successful | | 07 | Close HDMI CEC HAL using `HdmiCecClose` API | `handle` = valid handle | `HDMI_CEC_IO_SUCCESS` | Should be successful | From 967267a5e6689b1d0e3aa0d8ba9e5bbde21feb01 Mon Sep 17 00:00:00 2001 From: srinivasgtl <71806084+srinivasgtl@users.noreply.github.com> Date: Wed, 24 Jul 2024 16:35:13 +0100 Subject: [PATCH 08/40] gh #44 Update hdmi-cec-sink-L3-Low-Level_TestSpec.md removed unwanted data. --- .../hdmi-cec-sink-L3-Low-Level_TestSpec.md | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md b/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md index f585c62..5650bc2 100644 --- a/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md +++ b/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md @@ -7,7 +7,7 @@ - [Initialization and Startup] ## Overview -This document provides an overview of the L3 testing requirements for the module `HDMI CEC` source device. It outlines the scope of testing, objectives, External devices, specific test requirements, expected deliverables and approaches to satisfy the L3 Test requirement. +This document provides an overview of the L3 testing requirements for the module `HDMI CEC` source device. It outlines the scope of testing, objectives, External devices, specific test requirements, expected deliverables, and approaches to satisfy the L3 Test requirement. ## Acronyms, Terms and Abbreviations - `CEC` - Consumer Electronics Control @@ -21,8 +21,8 @@ This document provides an overview of the L3 testing requirements for the module ## References -CEC Adaptor: https://www.pulse-eight.com/p/104/usb-hdmi-cec-adapter# -`HAL` interface file: https://github.com/rdkcentral/rdk-halif-hdmi_cec/blob/main/include/hdmi_cec_driver.h +- CEC Adaptor: https://www.pulse-eight.com/p/104/usb-hdmi-cec-adapter# +- `HAL` interface file: https://github.com/rdkcentral/rdk-halif-hdmi_cec/blob/main/include/hdmi_cec_driver.h ## Module Description @@ -43,16 +43,11 @@ C[PC] <--> A A[Pulse-8 - 1] <--> |HDMI| B[TV] ``` -### Pulse Eight CEC Adaptor tool: +### Pulse-Eight CEC Adaptor tool: The Pulse-Eight CEC Adapter will be utilized to frame and send commands to the DUT. This tool leverages libcec, which can be installed to facilitate CEC activities during testing. The cec-client tool will be employed extensively throughout the test. Additionally, RAFT can use this tool to automate the test cases. -Reference to the tool: https://www.pulse-eight.com/p/104/usb-hdmi-cec-adapter -libcec tools: https://www.pulse-eight.com/Download/Get/51 - -**Commands used during the test:** -- To get the COM port of the `CEC` Tool adaptor: ```cec-client -l``` -- To find the devices connected (with their logical and physical address): ```echo scan | cec-client -s -d 1``` -- To Tx and Broadcast: ```echo tx | cec-client -s -d 1``` +- Reference to the tool: https://www.pulse-eight.com/p/104/usb-hdmi-cec-adapter +- libcec tools: https://www.pulse-eight.com/Download/Get/51 **Libraries and tools required for RAFT** - libcec should be installed on the PC where the Pulse-Eight CEC Adaptor is connected. From a96f61ad9acaa21c6f3da83777245f093cda7ecd Mon Sep 17 00:00:00 2001 From: srinivasgtl <71806084+srinivasgtl@users.noreply.github.com> Date: Wed, 24 Jul 2024 16:47:21 +0100 Subject: [PATCH 09/40] gh #44 Initial Test data profile --- profiles/sink/sink_hdmiCEC_test.yml | 48 +++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 profiles/sink/sink_hdmiCEC_test.yml diff --git a/profiles/sink/sink_hdmiCEC_test.yml b/profiles/sink/sink_hdmiCEC_test.yml new file mode 100644 index 0000000..28237e8 --- /dev/null +++ b/profiles/sink/sink_hdmiCEC_test.yml @@ -0,0 +1,48 @@ +hdmicec: + config: + number_ports: 3 + ports: + - id: 1 + type: in + cec_supported: true + cec_version: 02 + - id: 2 + type: in + cec_supported: true + cec_version: 02 + - id: 3 + type: in + cec_supported: true + cec_version: 02 + + test: + tx: + #CEC GET Version command + - command: + getcecVersion: + sinkla:0 + sourcela:1 + command:9F + expectedreply:02 + #CEC Standby command: + standby: + sinkla:0 + sourcela:1 + command:36 + setosd: + sinkla:0 + sourcela:1 + command:64 + data: + [80,48,65,6C,6C,6F,20,57,6F,72,6C,64,31,21], + [81,49,65,6D,6C,6F,20,57,6F,73,6C,64,32,22], + [82,50,65,6E,6C,6F,20,57,6F,74,6C,64,33,23], + [83,51,65,6F,6C,6F,20,57,6F,75,6C,64,34,24], + [84,52,65,6C,6C,6F,20,57,6F,76,6C,64,35,25], + [85,53,65,6C,6C,6F,20,57,6F,77,6C,64,36,26], + [86,54,65,6C,6C,6F,20,57,6F,78,6C,64,37,27], + [87,55,65,6C,6C,6F,20,57,6F,79,6C,64,38,28], + [88,56,65,6C,6C,6F,20,57,6F,7A,6C,64,39,29], + [89,57,65,6C,6C,6F,20,57,6F,7B,6C,64,40,30] + + From aa82cb56119231786bb552cbbbcc7489f6420d69 Mon Sep 17 00:00:00 2001 From: srinivasgtl <71806084+srinivasgtl@users.noreply.github.com> Date: Wed, 24 Jul 2024 16:50:49 +0100 Subject: [PATCH 10/40] gh #44 updating the yaml file --- profiles/sink/sink_hdmiCEC_test.yml | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/profiles/sink/sink_hdmiCEC_test.yml b/profiles/sink/sink_hdmiCEC_test.yml index 28237e8..da5fb1b 100644 --- a/profiles/sink/sink_hdmiCEC_test.yml +++ b/profiles/sink/sink_hdmiCEC_test.yml @@ -1,20 +1,6 @@ hdmicec: config: number_ports: 3 - ports: - - id: 1 - type: in - cec_supported: true - cec_version: 02 - - id: 2 - type: in - cec_supported: true - cec_version: 02 - - id: 3 - type: in - cec_supported: true - cec_version: 02 - test: tx: #CEC GET Version command From b844a146e77417d7bdf1ae04192dd73fb396fbe6 Mon Sep 17 00:00:00 2001 From: srinivasgtl <71806084+srinivasgtl@users.noreply.github.com> Date: Thu, 25 Jul 2024 15:19:19 +0100 Subject: [PATCH 11/40] gh#44 Update hdmi-cec-sink-L3-Low-Level_TestSpec.md Updating with review comments. --- .../hdmi-cec-sink-L3-Low-Level_TestSpec.md | 74 +++++++++++-------- 1 file changed, 45 insertions(+), 29 deletions(-) diff --git a/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md b/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md index 5650bc2..c6b37b6 100644 --- a/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md +++ b/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md @@ -31,11 +31,12 @@ Consumer Electronics Control (`CEC`) is a one-wire bidirectional bus within an H The present document describes the test scope for the Sink Device activities only. ### HDMI-CEC L3 Test Functionality -The below pic depicts the HDMI CEC L3 Test Functionality Setup. TV 2 marked as `DUT` is the Sink device under test. +The picture below depicts the HDMI CEC L3 Test Functionality Setup. This simple setup has an HDMI CEC Pulse-eight USB adaptor, which acts as a source device and can send the required commands (using libcec tool commands) and respond to the received CEC Commands. Note: The below-shown prerequisites should be met before starting the test on the platforms. - All the devices used in the test setup should support the `HDMI` `CEC` feature during the entire test duration. - HDMI drivers should be up and running on the platform before running this test. +- For now, it is suggested not to connect multiple CEC Adaptors onto a single PC as there is no proper support on libcec for multiple devices. ```mermaid graph TB @@ -44,7 +45,7 @@ A[Pulse-8 - 1] <--> |HDMI| B[TV] ``` ### Pulse-Eight CEC Adaptor tool: -The Pulse-Eight CEC Adapter will be utilized to frame and send commands to the DUT. This tool leverages libcec, which can be installed to facilitate CEC activities during testing. The cec-client tool will be employed extensively throughout the test. Additionally, RAFT can use this tool to automate the test cases. +The Pulse-Eight CEC Adapter will be used to frame and send commands to the DUT. This tool leverages libcec, which can be installed to facilitate CEC activities during testing. The cec-client tool will be employed extensively throughout the test. Additionally, RAFT can use this tool to automate the test cases. - Reference to the tool: https://www.pulse-eight.com/p/104/usb-hdmi-cec-adapter - libcec tools: https://www.pulse-eight.com/Download/Get/51 @@ -53,35 +54,41 @@ The Pulse-Eight CEC Adapter will be utilized to frame and send commands to the D - libcec should be installed on the PC where the Pulse-Eight CEC Adaptor is connected. - python-cec will be used to control the `CEC` adaptor. - https://pypi.org/project/cec/ will provide more information on how to use this library. - + +**cec-ctrl Commands used in Manual Mode** +- To get the logical and physical address: cec-client -s -d 4 +- To Tx data: `cec-client -s -t 1 --data ` or `echo "tx " | cec-client -s` Eg:`echo "tx 10:36" | cec-client -s` +- To check the last received data use `cec-client -m | grep '>>' | tail -n 1`. `cec-client -m` shall monitor the data continuously + **Prerequisite Test to make sure all the CEC Adaptors are connected** -1. Make sure to read the physical address of the CEC Adaptor allocated based on the port it has been connected to, using libCEC on RAFT. +1. Make sure to read the physical address of the CEC Adaptor allocated based on the port it has been connected to, using libCEC on PC. 2. The physical and logical addresses allocated to the CEC adaptor shall be read and validated on RAFT. ## Test Functionalities #### Message Transmission and Reception Test Note: All the below tests should be carried out on all the available HMDI ports. +- Transmit an HDMI CEC basic command (GetCECVersion) from the DUT to receive a reply from the connected CEC Adaptor. +- Receive an HDMI OSD Command with a string of maximum length (14 bytes) from the CEC Adaptor and acknowledge it. +- The CEC Adaptor sends a standby command to a device to all the logical addresses other than 0x00 and 0x0f. `DUT` should not respond to any of these commands. -- Transmit an HDMI CEC basic command (GetCECVersion) from the DUT to receive a reply from the connected CEC Adaptor. +#### Message Broadcast and Receive broadcast +Note: All the below tests should be carried out on all the available HMDI ports. - Broadcast an HDMI CEC Command from the DUT and verify that this command has been received on the CEC Adaptor. - Receive a standby broadcasting command on the DUT sent by the CEC Adaptor and validate it. -- Receive an HDMI OSD Command with a string of maximum length (14 bytes) from the CEC Adaptor. -- The CEC Adaptor sends a standby command to a device with a logical address other than the DUT logical address, ensuring no callback is received. - + #### Stress Test - Receiving an HDMI OSD Command repeatedly for 10 times with a different string of max length from CEC Adaptor. #### Hardware Fault Test - Introducing a Fault on the HDMI line to test the Transmit functionality. - # Test 1: Message Transmission and Reception Test - Unicast messages Functionality: -1. `DUT` shall request a CEC Version from the CEC adaptor connected. It should receive a valid version and be evaluated. -2. `DUT` shall receive an OSD Command with max buffer size from the CEC Adaptor and respond to this command. -3. `DUT` shall receive a "getCECVersion" command with a different `LA` which should not generate any callback. +1. `DUT` shall request a CEC Version from the CEC adaptor connected. `DUT` should receive a valid CEC version. +2. `DUT` shall receive an OSD Command with max buffer size from the CEC Adaptor and acknowledge to this command. +3. `DUT` shall receive a "getCECVersion" command with a different `LA` from 0x01 to 0x0E and should not receive any acknowledgment. | Title | Details | |-------------------------------|--------------------------------------------------| @@ -92,15 +99,17 @@ Functionality: | Priority | High | **Pre-Conditions:** -- The platforms are connected as shown in the picture above and STB and the CEC Adaptor are kept ready before the start of the test. -- libcec is installed on the PC where the PulseEight tool is connected. libcec will respond to all the basic CEC Commands received from `DUT` +- The platforms are connected as shown in the picture where the CEC Adaptor is considered to be connected and detected correctly. +- libcec is installed on the PC where the CEC Adaptor tool is connected. libcec shall respond to all the basic CEC Commands received from `DUT` **Dependencies:** Prerequisites should be met before starting this test. **User Interaction:** - If the user chooses to run the test in interactive mode, then the test case has to be selected via the console. -- RAFT will replace the human to run the test, but still, the RAFT should provide an option for the user to change the HMDI ports and start the test again. +- If the user chooses to run manually, he should use the cec-client commands as shown above. +- RAFT will replace the human to run the test if required, but still, the RAFT should provide an option for the user to change the HMDI ports and start the test again. +- The user should choose either to run manually or choose the RAFT. **RAFT Requirements:** - RAFT shall initiate the test by reading and validating the LA and PA. @@ -112,19 +121,25 @@ Prerequisites should be met before starting this test. sequenceDiagram participant DUT participant CEC Adaptor - participant RAFT - RAFT->>CEC Adaptor: Read and validate LA and PA - RAFT->>DUT: Start the HAL test + participant RAFT/user + RAFT/user->>CEC Adaptor: Read and validate LA and PA + RAFT/user->>DUT: Start the HAL test DUT->>DUT: Add Logical Address DUT->>DUT: Set receive Callback + DUT->>DUT: Wait for User/RAFT to enter the logical address DUT->>CEC Adaptor: Send "GetCECVersion" CEC Adaptor->>DUT: Send the "CEC Version" DUT->>DUT: Validate CEC Version - RAFT->>CEC Adaptor: Command to send CEC OSD Command + DUT->>DUT: Wait for User/RAFT to signal the start of the next test + RAFT/user->>CEC Adaptor: Command to send CEC OSD Command CEC Adaptor->>DUT: Send CEC OSD Command - DUT-->>DUT: Validate the received command - CEC Adaptor->>DUT: Send "GetCECVersion" to a LA other than `DUT` - DUT-->>DUT: No RxCallaback is received. + DUT->>DUT: Validate the received command + RAFT/user->>RAFT/user: Read the CEC acknowledgment received and validate + DUT->>DUT: Wait for User/RAFT to enter the acknowledgment confirmation and decide Test Pass/Fail + CEC Adaptor->>DUT: Send "GetCECVersion" to an LA other than `DUT`(0x01 to 0x0E). Repeat these 4 steps for all the addresses sent. + DUT->>DUT: Wait for User/RAFT to signal when the CEC adaptor has sent a CEC message. + DUT->>DUT: Test fails if it has received any message. + RAFT/user->>RAFT/user: No CEC acknowledgment is received after CEC Frames are sent. ``` #### Test Procedure @@ -134,16 +149,17 @@ sequenceDiagram | 01 | Open HDMI CEC HAL using `HdmiCecOpen` API | `handle` = valid pointer | `HDMI_CEC_IO_SUCCESS` | Should be successful | | 02 | Acquire a valid logical address `0x00` using `HdmiCecAddLogicalAddress` | `handle` = valid handle, `logicalAddress` = 0 | `HDMI_CEC_IO_SUCCESS` | Should be successful | | 03 | Set the receive callback function using `HdmiCecSetRxCallback` | `handle` = valid handle, `cbfunc` = RxCallback, `data` = buffer pointer | `HDMI_CEC_IO_SUCCESS` | Should be successful | -| 04 | Wait to get the connected device (CEC Adaptor) logical address from RAFT.| N/A | N/A | RAFT to enter the LA address of the CEC Adaptor | +| 04 | Wait to get the connected device (CEC Adaptor) logical address from RAFT/user.| N/A | N/A | RAFT/user to enter the LA address of the CEC Adaptor | | 05 | Frame a getCECVersion command using the "getcecVersion" command from the test yaml file and send it using using `HdmiCecTx` | `handle` = valid handle, `buf` = cec buffer with LA and command, `len` = sizeof(buf), `result` = valid pointer | `HDMI_CEC_IO_SUCCESS` | Should be successful | | 06 | Wait for a second and validate a response from the CEC Adaptor on the RxCallback and validate | Test data received from CEC Adaptor | Read and validate this data. Rx data should be a valid CEC version | Should be successful | -| 07 | Frame and send a CEC OSD command based on "setosd" on the test yaml file and transmit this data to `DUT`. | `buffer` = LA, Command and data from test yaml | N/A | RAFT to set this data through CEC adapter | -| 08 | Wait for the RAFT to signal when the CEC command is sent in step 7 | NA | N/A | RAFT to signal once the CEC command is sent | +| 07 | Frame and send a CEC OSD command based on "setosd" on the test yaml file and transmit this data to `DUT`. | `buffer` = LA, Command and data from test yaml | N/A | RAFT/user to set this data through CEC adapter | +| 08 | Wait for the RAFT/user to signal when the CEC command is sent in step 7 | NA | N/A | RAFT/user to signal once the CEC command is sent | | 09 | Validate the data received on `DUT` with the "setosd" command data on the test yaml file| Test data received shall match with the data in yaml | Read and validate this data| Should be successful | -| 10 | Frame and send a CEC command based on "getcecVersion" on the test yaml file and transmit this data to the LA address other than `DUT`. | `buffer` = LA of non existing device and
data read from test yaml | N/A | RAFT to set this data through CEC adapter | -| 11 | Wait for the RAFT to signal when the CEC command is sent in step 11 | NA | N/A | RAFT to signal once the CEC command is sent | -| 12 | Validate the data received on CEC with the "setosd" command on the test yaml file| Test data received should match with the data in yaml | Read and validate this data| Should be successful | -| 13 | Close HDMI CEC HAL using `HdmiCecClose` API | `handle` = valid handle | `HDMI_CEC_IO_SUCCESS` | Should be successful | +| 10 | RAFT/user shall validate for the acknowledgment received from the `DUT` while the test will wait for the result| Press "Y"/"N" based on ack | Test to consume this input to decide overall test pass or fail| Should be successful | +| 11 | RAFT/user to frame and send a CEC command to all LA addresses from 0x01 to 0x0E through CEC adaptor | "getCECVersion" command | N/A | RAFT to set this data through CEC adapter | +| 12 | RAFT/user should not receive any ack after sending this data| NA | NA | Should be successful | +| 13 | Test to wait for the RAFT/user to signal about its test result with steps 11 and 12 | Press "Y"/"N" based on test result | N/A | RAFT/user to provide this test result | +| 14 | Close HDMI CEC HAL using `HdmiCecClose` API | `handle` = valid handle | `HDMI_CEC_IO_SUCCESS` | Should be successful | # Test 3: Transmit and Receive CEC broadcast Commands From fa9b96646ad5059513b7bc64988fde468e91f9bd Mon Sep 17 00:00:00 2001 From: srinivasgtl <71806084+srinivasgtl@users.noreply.github.com> Date: Thu, 25 Jul 2024 17:35:36 +0100 Subject: [PATCH 12/40] gh #44 Update hdmi-cec-sink-L3-Low-Level_TestSpec.md Updated with review comments --- .../hdmi-cec-sink-L3-Low-Level_TestSpec.md | 143 +++++++++++------- 1 file changed, 86 insertions(+), 57 deletions(-) diff --git a/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md b/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md index c6b37b6..d5c8447 100644 --- a/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md +++ b/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md @@ -79,6 +79,7 @@ Note: All the below tests should be carried out on all the available HMDI ports. #### Stress Test - Receiving an HDMI OSD Command repeatedly for 10 times with a different string of max length from CEC Adaptor. +- Transmit an HDMI OSD Command repeatedly for 10 times with a different string of max length to the CEC Adaptor. #### Hardware Fault Test - Introducing a Fault on the HDMI line to test the Transmit functionality. @@ -86,9 +87,10 @@ Note: All the below tests should be carried out on all the available HMDI ports. # Test 1: Message Transmission and Reception Test - Unicast messages Functionality: -1. `DUT` shall request a CEC Version from the CEC adaptor connected. `DUT` should receive a valid CEC version. -2. `DUT` shall receive an OSD Command with max buffer size from the CEC Adaptor and acknowledge to this command. -3. `DUT` shall receive a "getCECVersion" command with a different `LA` from 0x01 to 0x0E and should not receive any acknowledgment. +1. RAFT/user to send a simple "getCECVersion" command to the `DUT` before setting the logical address. +2. `DUT` shall request a CEC Version from the CEC adaptor connected. `DUT` should receive a valid CEC version. +3. `DUT` shall receive an OSD Command with max buffer size from the CEC Adaptor and acknowledge to this command. +4. `DUT` shall receive a "getCECVersion" command with a different `LA` from 0x01 to 0x0E and should not receive any acknowledgment. | Title | Details | |-------------------------------|--------------------------------------------------| @@ -103,7 +105,7 @@ Functionality: - libcec is installed on the PC where the CEC Adaptor tool is connected. libcec shall respond to all the basic CEC Commands received from `DUT` **Dependencies:** -Prerequisites should be met before starting this test. +- Prerequisites should be met before starting this test. **User Interaction:** - If the user chooses to run the test in interactive mode, then the test case has to be selected via the console. @@ -114,7 +116,8 @@ Prerequisites should be met before starting this test. **RAFT Requirements:** - RAFT shall initiate the test by reading and validating the LA and PA. - RAFT shall initiate the commands to send the CEC OSD command with the string data as read from the hdmicec_sinktest.yml file. -- RAFT shall provide a means to enter the LA for the test and any other data required during the test. +- RAFT shall provide a means to enter the LA for the test and any other data required during the test. +- RAFT shall consider reading and give input to the test wherever required. **Sequence Diagram** ```mermaid @@ -124,8 +127,12 @@ sequenceDiagram participant RAFT/user RAFT/user->>CEC Adaptor: Read and validate LA and PA RAFT/user->>DUT: Start the HAL test - DUT->>DUT: Add Logical Address DUT->>DUT: Set receive Callback + CEC Adaptor->>DUT: Send "GetCECVersion" before adding the logical address + RAFT/user->>RAFT/user: No response or ack should be received. + DUT->>DUT: Wait for the RAFT/user to signal to provide ack received or not. + DUT->>DUT: Check no RxCallback has been received and decide whether the test passes or fails + DUT->>DUT: Add Logical Address DUT->>DUT: Wait for User/RAFT to enter the logical address DUT->>CEC Adaptor: Send "GetCECVersion" CEC Adaptor->>DUT: Send the "CEC Version" @@ -145,27 +152,29 @@ sequenceDiagram #### Test Procedure | Variation / Steps | Description | Test Data | Expected Result | Notes | -| -- | --------- | ---------- | -------------- | ----- | +|-------------------|-------------|-----------|------------------|-------| | 01 | Open HDMI CEC HAL using `HdmiCecOpen` API | `handle` = valid pointer | `HDMI_CEC_IO_SUCCESS` | Should be successful | -| 02 | Acquire a valid logical address `0x00` using `HdmiCecAddLogicalAddress` | `handle` = valid handle, `logicalAddress` = 0 | `HDMI_CEC_IO_SUCCESS` | Should be successful | -| 03 | Set the receive callback function using `HdmiCecSetRxCallback` | `handle` = valid handle, `cbfunc` = RxCallback, `data` = buffer pointer | `HDMI_CEC_IO_SUCCESS` | Should be successful | -| 04 | Wait to get the connected device (CEC Adaptor) logical address from RAFT/user.| N/A | N/A | RAFT/user to enter the LA address of the CEC Adaptor | -| 05 | Frame a getCECVersion command using the "getcecVersion" command from the test yaml file and send it using using `HdmiCecTx` | `handle` = valid handle, `buf` = cec buffer with LA and command, `len` = sizeof(buf), `result` = valid pointer | `HDMI_CEC_IO_SUCCESS` | Should be successful | -| 06 | Wait for a second and validate a response from the CEC Adaptor on the RxCallback and validate | Test data received from CEC Adaptor | Read and validate this data. Rx data should be a valid CEC version | Should be successful | -| 07 | Frame and send a CEC OSD command based on "setosd" on the test yaml file and transmit this data to `DUT`. | `buffer` = LA, Command and data from test yaml | N/A | RAFT/user to set this data through CEC adapter | -| 08 | Wait for the RAFT/user to signal when the CEC command is sent in step 7 | NA | N/A | RAFT/user to signal once the CEC command is sent | -| 09 | Validate the data received on `DUT` with the "setosd" command data on the test yaml file| Test data received shall match with the data in yaml | Read and validate this data| Should be successful | -| 10 | RAFT/user shall validate for the acknowledgment received from the `DUT` while the test will wait for the result| Press "Y"/"N" based on ack | Test to consume this input to decide overall test pass or fail| Should be successful | -| 11 | RAFT/user to frame and send a CEC command to all LA addresses from 0x01 to 0x0E through CEC adaptor | "getCECVersion" command | N/A | RAFT to set this data through CEC adapter | -| 12 | RAFT/user should not receive any ack after sending this data| NA | NA | Should be successful | -| 13 | Test to wait for the RAFT/user to signal about its test result with steps 11 and 12 | Press "Y"/"N" based on test result | N/A | RAFT/user to provide this test result | -| 14 | Close HDMI CEC HAL using `HdmiCecClose` API | `handle` = valid handle | `HDMI_CEC_IO_SUCCESS` | Should be successful | - -# Test 3: Transmit and Receive CEC broadcast Commands +| 02 | Set the receive callback function using `HdmiCecSetRxCallback` | `handle` = valid handle, `cbfunc` = RxCallback, `data` = buffer pointer | `HDMI_CEC_IO_SUCCESS` | Should be successful | +| 03 | RAFT/user to send a "getCECVersion" command to the Device Under Test (DUT) and should not receive any response or acknowledgment | CEC command = read from "getCECVersion" in YAML file, LA = 0 | N/A | Should be successful | +| 04 | DUT to wait for a signal from RAFT/user and then validate whether it has received any data. The test fails if it has received any data. | Data received on the Rx callback | No Rx Callback is made | Should be successful | +| 05 | Acquire a valid logical address `0x00` using `HdmiCecAddLogicalAddress` | `handle` = valid handle, `logicalAddress` = 0 | `HDMI_CEC_IO_SUCCESS` | Should be successful | +| 06 | Wait to get the connected device (CEC Adaptor) logical address from RAFT/user | N/A | N/A | RAFT/user to enter the logical address of the CEC Adaptor | +| 07 | Frame a "getCECVersion" command using the "getCECVersion" command from the test YAML file and send it using `HdmiCecTx` | `handle` = valid handle, `buf` = CEC buffer with LA and command, `len` = sizeof(buf), `result` = valid pointer | `HDMI_CEC_IO_SUCCESS` | Should be successful | +| 08 | Wait for a second and validate a response from the CEC Adaptor on the RxCallback and validate | Test data received from CEC Adaptor | Read and validate this data. Rx data should be a valid CEC version | Should be successful | +| 09 | Frame and send a CEC OSD command based on "setosd" from the test YAML file and transmit this data to DUT | `buffer` = LA, command and data from test YAML | N/A | RAFT/user to set this data through CEC adaptor | +| 10 | Wait for the RAFT/user to signal when the CEC command is sent in step 09 | N/A | N/A | RAFT/user to signal once the CEC command is sent | +| 11 | Validate the data received on DUT with the "setosd" command data from the test YAML file | Test data received should match the data in YAML | Read and validate this data | Should be successful | +| 12 | RAFT/user to validate the acknowledgment received from the DUT while the test waits for the result | Press "Y"/"N" based on acknowledgment | Test to consume this input to decide overall test pass or fail | Should be successful | +| 13 | RAFT/user to frame and send a CEC command to all logical addresses from 0x01 to 0x0E through the CEC adaptor | "getCECVersion" command | N/A | RAFT/user to set this data through the CEC adaptor | +| 14 | RAFT/user should not receive any acknowledgment after sending this data | N/A | N/A | Should be successful | +| 15 | Test to wait for the RAFT/user to signal about its test result for steps 13 and 14 | Press "Y"/"N" based on test result | N/A | RAFT/user to provide this test result | +| 16 | Close HDMI CEC HAL using `HdmiCecClose` API | `handle` = valid handle | `HDMI_CEC_IO_SUCCESS` | Should be successful | + +# Test 2: Transmit and Receive CEC broadcast Commands Functionality: -1. `DUT` shall broadcast a standby command to the connected devices and RAFT should validate this received command on the CEC Adaptor. -2. `DUT` shall receive a standby command as a broadcast command from the CEC Adaptor. RAFT to initiate and command the Test. +1. `DUT` shall broadcast a standby command to the connected devices and RAFT/user should validate this received command on the CEC Adaptor. +2. `DUT` shall receive a standby command as a broadcast command from the CEC Adaptor. RAFT/user to initiate and command the Test. | Title | Details | |-------------------------------|--------------------------------------------------| @@ -176,33 +185,40 @@ Functionality: | Priority | High | **Pre-Conditions:** -The platforms are connected as shown in the picture above and STB and the CEC Adaptor are kept ready before the start of the test. +- The platforms are connected as shown in the picture where the CEC Adaptor is considered to be connected and detected correctly. +- libcec is installed on the PC where the CEC Adaptor tool is connected. libcec shall respond to all the basic CEC Commands received from `DUT` **Dependencies:** -Prerequisites should be met before starting this test. +- Prerequisites should be met before starting this test. **User Interaction:** - If the user chooses to run the test in interactive mode, then the test case has to be selected via the console. -- RAFT will replace the human to run the test, but still, the RAFT should provide an option for the user to change the HMDI ports and start the test again. +- If the user chooses to run manually, he should use the cec-client commands as shown above. +- RAFT will replace the human to run the test if required, but still, the RAFT should provide an option for the user to change the HMDI ports and start the test again. +- The user should choose either to run manually or choose the RAFT. **RAFT Requirements:** -- RAFT shall initiate the commands to broadcast the standby CEC command with the string data as read from the hdmicec_sinktest.yml file. -- RAFT provides an interface for the user to change the HMDI port and start the test again. - +- RAFT shall initiate the commands to send the standby command. +- RAFT shall consider reading and give input to the test wherever required. + **Sequence Diagram** ```mermaid sequenceDiagram participant DUT participant CEC Adaptor - participant RAFT - RAFT->>CEC Adaptor: Read and validate LA and PA - RAFT->>DUT: Start the HAL test + participant RAFT/user + RAFT/user->>CEC Adaptor: Read and validate LA and PA (device ready) + RAFT/user->>DUT: Start the HAL test DUT->>DUT: Add Logical Address DUT->>DUT: Set receive Callback DUT->>CEC Adaptor: Broadcast "standby" - RAFT->>CEC Adaptor: Validate the CEC Command received on the `CEC` adaptor - RAFT->>CEC Adaptor: Board "standby" command" - CEC Adaptor->> DUT: Receive the standby command + RAFT/user->>CEC Adaptor: Validate the CEC Command received on the `CEC` adaptor + DUT->>DUT: Wait for the input from RAFT/user to provide the test result + RAFT/user->>DUT: Provide the Test result of standby data received by it. + DUT->>DUT: Wait for the input from RAFT/user to send a broadcast command + RAFT->>CEC Adaptor: Broadcast "standby" command + RAFT/user->>DUT: Signal the command to validate the data RAFT/user broadcasted and received by DUT. + CEC Adaptor->> DUT: Broadcast the standby command DUT-->>DUT: Validate the received command ``` @@ -210,45 +226,47 @@ sequenceDiagram ## New Test Plan (Broadcast Commands) | Variation / Steps | Description | Test Data | Expected Result | Notes | -| -- | --------- | ---------- | -------------- | ----- | +|-------------------|-------------|-----------|------------------|-------| | 01 | Open HDMI CEC HAL using `HdmiCecOpen` API | `handle` = valid pointer | `HDMI_CEC_IO_SUCCESS` | Should be successful | | 02 | Acquire a valid logical address `0x00` using `HdmiCecAddLogicalAddress` | `handle` = valid handle, `logicalAddress` = 0 | `HDMI_CEC_IO_SUCCESS` | Should be successful | | 03 | Set the receive callback function using `HdmiCecSetRxCallback` | `handle` = valid handle, `cbfunc` = RxCallback, `data` = buffer pointer | `HDMI_CEC_IO_SUCCESS` | Should be successful | -| 04 | Frame a standby command to broadcast from `DUT` to all the connected devices using `HdmiCecTx`. Test command and data shall be read from test yaml | `handle` = valid handle, `buf` = as read from yaml file, `len` = sizeof(buf), `result` = valid pointer | `HDMI_CEC_IO_SUCCESS` | Should be successful| -| 05 | RAFT should receive this data and validate the command received. The test should wait for the RAFT to enter the test result based on the validation | NA| N/A | RAFT to provide the result | -| 06 | RAFT to command CEC adaptor to frame and broadcast the standby CEC command. Test data should be read from test yaml file | `buffer` = test yaml file data | N/A | RAFT to set this data through CEC adapter | -| 07 | Wait for the RAFT to signal when the CEC broadcast is sent in step 6 | RAFT to provide `y` to move | N/A | RAFT to signal once the CEC broadcast is set | -| 08 | Received data from the CEC adapter on the RxCallback shall be validated. Received data shall be validated against the test yaml file | Test data received should be as mentioned in the test yaml file | Read and validate this data | Should be successful | +| 04 | Frame a standby command to broadcast from `DUT` to all connected devices using `HdmiCecTx`. Test command and data shall be read from the test YAML file | `handle` = valid handle, `buf` = standby command as read from YAML file, `len` = sizeof(buf), `result` = valid pointer | `HDMI_CEC_IO_SUCCESS` | Should be successful | +| 05 | RAFT/user should receive this data and validate the command received. The test should wait for the RAFT to enter the test result based on the validation | N/A | N/A | RAFT to provide the result | +| 06 | RAFT/user to command CEC adaptor to frame and broadcast the standby CEC command. Test data should be read from the test YAML file | `buffer` = test YAML file data | N/A | RAFT to set this data through CEC adaptor | +| 07 | Wait for the RAFT to signal when the CEC broadcast is sent in step 6 | RAFT/user to provide `y` to move the test | N/A | RAFT to signal once the CEC broadcast is set | +| 08 | Validate the data received from the CEC adaptor on the test RxCallback against the test YAML file | Test data received should be as mentioned in the test YAML file | Read and validate this data | Should be successful | | 09 | Close HDMI CEC HAL using `HdmiCecClose` API | `handle` = valid handle | `HDMI_CEC_IO_SUCCESS` | Should be successful | - -# Test 4: Stress Test +# Test 3: Stress Test Functionality: -1. `DUT` shall respond to a CEC OSD command received from the CEC Adaptor continuously 10 times with different strings and validate. +1. `DUT` shall respond to a CEC OSD command received from the CEC Adaptor repeatedly for 10 times with different strings and validate. +2. `DUT` shall transmit the CEC OSD command to the CEC Adaptor repeatedly for 10 times. CEC Adaptor to read and validate | Title | Details | |-------------------------------|--------------------------------------------------| -| Function Name | `test_l3_hdmi_cec_sink_respond_osd_command_from_adaptor_repeatedly` | -| Description | Receive and respond to the CEC OSD Command with buffer data continuously 10 times to prove the robustness of this API. | +| Function Name | `test_l3_hdmi_cec_tx_rx_osd_cmd_repeatedly` | +| Description | Transmit and Receive CEC OSD Command with buffer data continuously 10 times to prove the robustness of these API. | | Test Group | 03 | | Test Case ID | 004 | | Priority | High | **Pre-Conditions:** -- The platforms are connected as shown in the picture above and STB and the CEC Adaptor are kept ready before the start of the test. -- libcec is installed on the PC where the PulseEight tool is connected. libcec will respond to all the basic CEC Commands received from `DUT` +- The platforms are connected as shown in the picture where the CEC Adaptor is considered to be connected and detected correctly. +- libcec is installed on the PC where the CEC Adaptor tool is connected. libcec shall respond to all the basic CEC Commands received from `DUT` **Dependencies:** -Prerequisites should be met before starting this test. +- Prerequisites should be met before starting this test. **User Interaction:** - If the user chooses to run the test in interactive mode, then the test case has to be selected via the console. -- RAFT will replace the human to run the test, but still, the RAFT should provide an option for the user to change the HMDI ports and start the test again. +- If the user chooses to run manually, he should use the cec-client commands as shown above. +- RAFT will replace the human to run the test if required, but still, the RAFT should provide an option for the user to change the HMDI ports and start the test again. +- The user should choose either to run manually or choose the RAFT. **RAFT Requirements:** -- RAFT shall initiate the test by reading and validating the LA and PA. -- RAFT shall initiate the commands to send the CEC OSD command with the string data as read from the hdmicec_sinktest.yml file. +- RAFT shall initiate the commands to send the OSD command and validate the acknowledgments +- RAFT shall consider reading and give input to the test wherever required. **Sequence Diagram** ```mermaid @@ -256,13 +274,20 @@ sequenceDiagram participant DUT participant CEC Adaptor participant RAFT - RAFT->>CEC Adaptor: Read and validate LA and PA - RAFT->>DUT: Start the HAL test + RAFT/user->>CEC Adaptor: Read and validate LA and PA + RAFT/user->>DUT: Start the HAL test DUT->>DUT: Add Logical Address DUT->>DUT: Set receive Callback - RAFT->>CEC Adaptor: Command to send CEC OSD Command for 10 times + RAFT/user->>CEC Adaptor: Command to send CEC OSD Command for 10 times CEC Adaptor->>DUT: Send CEC OSD Command for 10 times + RAFT/user->>DUT: To signal the Test to start receiving the OSD data. + RAFT/user->>RAFT/user: To validate the acknowledgment received each time when sent the CEC Frame. DUT-->>DUT: Validate the received command for 10 times + RAFT/user->>DUT: DUT to wait till the RAFT/user provides the data ack result + DUT->>CEC Adaptor: Send CEC OSD Command for 10 times + RAFT/user->>RAFT/user: To validate the OSD Command received on the CEC Adaptor + RAFT/user->>DUT: DUT to wait till the RAFT/user provides the data ack result + DUT->>DUT: To decide the final result based on the RAFT/user result and its own result. ``` #### Test Procedure @@ -272,7 +297,11 @@ sequenceDiagram | 02 | Acquire a valid logical address `0x00` using `HdmiCecAddLogicalAddress` | `handle` = valid handle, `logicalAddress` = 0 | `HDMI_CEC_IO_SUCCESS` | Should be successful | | 03 | Set the receive callback function using `HdmiCecSetRxCallback` | `handle` = valid handle, `cbfunc` = valid callback function pointer, `data` = pointer to the valid data buffer | `HDMI_CEC_IO_SUCCESS` | Should be successful | | 04 | RAFT shall wait for a signal from `DUT`so that it can signal the CEC Adaptor to send a CEC OSD Command continuously 10 times with different data available in test yaml file | N/A | N/A | Should be successful | -| 05 | Validate the data received on the DUT and compare the data with the data from "setosd/data" on test yaml file | Compare the received data with "setosd/data" on test yaml | NA | Should be successful | +| 05 | Validate the data received on the DUT and compare the data with the data from "setosd/data" on the test yaml file | Compare the received data with "setosd/data" on test yaml | NA | Should be successful | +| 06 | RAFT/User to check acknowledgment for each command sent. DUT to wait for RAFT result | RAFT/user to provide `y` or `n` to move the test | NA | Should be successful | +| 07 | `DUT` to send a CEC OSD command continuously 10 times with different data available in test yaml file. Tx command should pass every time it send data| `handle` = valid handle, `buf` = "setosd/data" command as read from YAML file with different data, `len` = sizeof(buf), `result` = valid pointer | NA | Should be successful +| 05 | Validate the data received on the RAFT and compare the data with the data from "setosd/data" on the test yaml file | Compare the received data with "setosd/data" on test yaml | NA | Should be successful | +| 06 | RAFT/User to check received OSD Data for each command sent. DUT to wait for RAFT result | RAFT/user to provide `y` or `n` to move the test | NA | Should be successful | | 07 | Close HDMI CEC HAL using `HdmiCecClose` API | `handle` = valid handle | `HDMI_CEC_IO_SUCCESS` | Should be successful | From eb5c5429ba726d330a7aa3e6b9e08838cbf38cdb Mon Sep 17 00:00:00 2001 From: srinivasgtl <71806084+srinivasgtl@users.noreply.github.com> Date: Thu, 25 Jul 2024 17:38:48 +0100 Subject: [PATCH 13/40] gh #44 Update hdmi-cec-sink-L3-Low-Level_TestSpec.md --- docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md b/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md index d5c8447..56c0889 100644 --- a/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md +++ b/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md @@ -41,7 +41,7 @@ Note: The below-shown prerequisites should be met before starting the test on th ```mermaid graph TB C[PC] <--> A -A[Pulse-8 - 1] <--> |HDMI| B[TV] +A[Pulse-Eight CEC Adaptor ] <--> |HDMI| B[TV] ``` ### Pulse-Eight CEC Adaptor tool: @@ -56,7 +56,8 @@ The Pulse-Eight CEC Adapter will be used to frame and send commands to the DUT. - https://pypi.org/project/cec/ will provide more information on how to use this library. **cec-ctrl Commands used in Manual Mode** -- To get the logical and physical address: cec-client -s -d 4 +- libcec should be installed on the PC where the Pulse-Eight CEC Adaptor is connected. +- To get the logical and physical address: `cec-client -s -d 4` - To Tx data: `cec-client -s -t 1 --data ` or `echo "tx " | cec-client -s` Eg:`echo "tx 10:36" | cec-client -s` - To check the last received data use `cec-client -m | grep '>>' | tail -n 1`. `cec-client -m` shall monitor the data continuously From a77a0b6ff5021defffc3e3270958c1d4374a1417 Mon Sep 17 00:00:00 2001 From: srinivasgtl <71806084+srinivasgtl@users.noreply.github.com> Date: Thu, 25 Jul 2024 17:48:05 +0100 Subject: [PATCH 14/40] gh #44 Update hdmi-cec-sink-L3-Low-Level_TestSpec.md enhancement to the sequence diagram --- docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md b/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md index 56c0889..3df11c1 100644 --- a/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md +++ b/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md @@ -132,20 +132,25 @@ sequenceDiagram CEC Adaptor->>DUT: Send "GetCECVersion" before adding the logical address RAFT/user->>RAFT/user: No response or ack should be received. DUT->>DUT: Wait for the RAFT/user to signal to provide ack received or not. + RAFT/user->>DUT: RAFT/user to signal the test to move ahead DUT->>DUT: Check no RxCallback has been received and decide whether the test passes or fails DUT->>DUT: Add Logical Address DUT->>DUT: Wait for User/RAFT to enter the logical address + RAFT/user->>DUT: RAFT/user to provide the logical address DUT->>CEC Adaptor: Send "GetCECVersion" CEC Adaptor->>DUT: Send the "CEC Version" DUT->>DUT: Validate CEC Version DUT->>DUT: Wait for User/RAFT to signal the start of the next test + RAFT/user->>DUT: RAFT/user to signal the test to move ahead RAFT/user->>CEC Adaptor: Command to send CEC OSD Command CEC Adaptor->>DUT: Send CEC OSD Command DUT->>DUT: Validate the received command RAFT/user->>RAFT/user: Read the CEC acknowledgment received and validate DUT->>DUT: Wait for User/RAFT to enter the acknowledgment confirmation and decide Test Pass/Fail + RAFT/user->>DUT: RAFT/user to provide the test result CEC Adaptor->>DUT: Send "GetCECVersion" to an LA other than `DUT`(0x01 to 0x0E). Repeat these 4 steps for all the addresses sent. DUT->>DUT: Wait for User/RAFT to signal when the CEC adaptor has sent a CEC message. + RAFT/user->>DUT: RAFT/user to signal the test to move ahead DUT->>DUT: Test fails if it has received any message. RAFT/user->>RAFT/user: No CEC acknowledgment is received after CEC Frames are sent. ``` @@ -217,6 +222,7 @@ sequenceDiagram DUT->>DUT: Wait for the input from RAFT/user to provide the test result RAFT/user->>DUT: Provide the Test result of standby data received by it. DUT->>DUT: Wait for the input from RAFT/user to send a broadcast command + RAFT/user->>DUT: RAFT/user to signal the test to move ahead RAFT->>CEC Adaptor: Broadcast "standby" command RAFT/user->>DUT: Signal the command to validate the data RAFT/user broadcasted and received by DUT. CEC Adaptor->> DUT: Broadcast the standby command @@ -285,9 +291,11 @@ sequenceDiagram RAFT/user->>RAFT/user: To validate the acknowledgment received each time when sent the CEC Frame. DUT-->>DUT: Validate the received command for 10 times RAFT/user->>DUT: DUT to wait till the RAFT/user provides the data ack result + RAFT/user->>DUT: RAFT/user to signal the test to move ahead with the ack result DUT->>CEC Adaptor: Send CEC OSD Command for 10 times RAFT/user->>RAFT/user: To validate the OSD Command received on the CEC Adaptor RAFT/user->>DUT: DUT to wait till the RAFT/user provides the data ack result + RAFT/user->>DUT: RAFT/user to signal the test with result DUT->>DUT: To decide the final result based on the RAFT/user result and its own result. ``` From b4197d2bae88ecd4a35d002c0f0d3131ae50e323 Mon Sep 17 00:00:00 2001 From: srinivasgtl <71806084+srinivasgtl@users.noreply.github.com> Date: Thu, 25 Jul 2024 17:50:02 +0100 Subject: [PATCH 15/40] gh #44 Update hdmi-cec-sink-L3-Low-Level_TestSpec.md --- docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md b/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md index 3df11c1..5635d76 100644 --- a/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md +++ b/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md @@ -230,7 +230,6 @@ sequenceDiagram ``` #### Test Procedure -## New Test Plan (Broadcast Commands) | Variation / Steps | Description | Test Data | Expected Result | Notes | |-------------------|-------------|-----------|------------------|-------| From 69271b6d86ef971d638d4cc5ad3b13cebaadbf46 Mon Sep 17 00:00:00 2001 From: srinivasgtl <71806084+srinivasgtl@users.noreply.github.com> Date: Tue, 6 Aug 2024 18:10:59 +0100 Subject: [PATCH 16/40] gh #44 Initial version of L3 Test interfaces --- src/main.c | 3 + src/test_l3_hdmi_cec_sink_driver.c | 405 +++++++++++++++++++++++++++++ src/test_register.c | 12 +- 3 files changed, 419 insertions(+), 1 deletion(-) create mode 100644 src/test_l3_hdmi_cec_sink_driver.c diff --git a/src/main.c b/src/main.c index 7170e87..f2eb0ba 100644 --- a/src/main.c +++ b/src/main.c @@ -70,6 +70,8 @@ extern int register_hdmicec_hal_source_l1_tests( void ); extern int register_hdmicec_hal_sink_l1_tests( void ); extern int register_hdmicec_hal_source_l2_tests( void ); extern int register_hdmicec_hal_sink_l2_tests( void ); +extern int register_hdmicec_hal_sink_l3_tests( void ); + #ifdef VCOMPONENT extern int register_vcomponent_tests ( char* profile ); @@ -138,6 +140,7 @@ int main(int argc, char** argv) if(strncmp(szReturnedString,"sink",UT_KVP_MAX_ELEMENT_SIZE) == 0) { register_hdmicec_hal_sink_l1_tests (); register_hdmicec_hal_sink_l2_tests (); + register_hdmicec_hal_sink_l3_tests (); } UT_run_tests(); diff --git a/src/test_l3_hdmi_cec_sink_driver.c b/src/test_l3_hdmi_cec_sink_driver.c new file mode 100644 index 0000000..827aca8 --- /dev/null +++ b/src/test_l3_hdmi_cec_sink_driver.c @@ -0,0 +1,405 @@ +/* +* If not stated otherwise in this file or this component's LICENSE file the +* following copyright and licenses apply:* +* Copyright 2024 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +/** + * @addtogroup HPK Hardware Porting Kit + * @{ + * + */ + +/** + * @addtogroup HDMI_CEC HDMI CEC Module + * @{ + * + */ + +/** + * @defgroup HDMI_CEC_HALTESTS HDMI CEC HAL Tests + * @{ + * + */ + + +/** + * @defgroup HDMI_CEC_HALTESTS_L2 HDMI CEC HAL Tests L2 File + * @{ + * @parblock + * + * ### L2 Test Cases for HDMI CEC HAL : + * + * + * ## Module's Role + * This module includes Level 2 functional tests (success and failure scenarios). + * This is to ensure that the hdmi_cec_driver APIs meet the requirements across all vendors. + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * + * Refer to API Definition specification documentation : [hdmi-cec_halSpec.md](../../docs/pages/hdmi-cec_halSpec.md) + * + * @endparblock + */ + +/** + * @file test_l2_hdmi_cec_sink_driver.c + * + */ + +#include +#include +#include "hdmi_cec_driver.h" + +#define TIMEOUT 5 +#define REPLY_TIMEOUT 5 + +static int gTestGroup = 3; +static int gTestID = 1; +static int gHandle = 0; +static int cbFlag = 0; + +/* Callback function */ +void onRxDataReceived(int handle, void *callbackData, unsigned char *buf, int len) +{ + UT_LOG ("\nBuffer generated: %x length: %d\n",buf, len); + if((handle!=0) && (callbackData !=NULL) && (len>0)) { + UT_LOG("\nCall back data generated is \n"); + for (int index=0; index < len; index++) { + UT_LOG("buf at index : %d is %x \n", index, buf[index]); + } + + memset(buf, 0, len); + } + else { + if (handle == 0) { + UT_FAIL("Error: Invalid handle.\n"); + } + if (callbackData == NULL) { + UT_FAIL("Error: Null callback data.\n"); + } + if (len <= 0) { + UT_FAIL("Error: Invalid length.\n"); + } + } + cbFlag = 1; +} + + +/** +* @brief Initialization of the HAL CEC Module +* +* This test provides a scope to open the HAL CEC module and preserve the handle. + +* +* **Test Group ID:** 03@n +* **Test Case ID:** 001@n +* +* **Test Procedure:** +* Refer to UT specification documentation +*/ + +void test_l3_hdmi_cec_sink_hal_Init(void) +{ + gTestID = 1; + HDMI_CEC_STATUS status; + + UT_LOG_INFO("In %s [%02d%03d]\n", __FUNCTION__, gTestGroup, gTestID); + + // Step 1: Call HdmiCecOpen() + UT_LOG_DEBUG("Invoking HdmiCecOpen with valid handle"); + status = HdmiCecOpen(&gHandle); + //UT_ASSERT_EQUAL_FATAL(status, HDMI_CEC_IO_SUCCESS); + //UT_ASSERT_NOT_EQUAL_FATAL(gHandle, 0); + if ((status != HDMI_CEC_IO_SUCCESS) || (gHandle == NULL)) + UT_LOG_ERROR("Invoking HdmiCecOpen failed"); + + // Step 2: Register the call back + status = HdmiCecSetRxCallback(gHandle, onRxDataReceived,(void*)0xABABABAB); + //UT_ASSERT_EQUAL_FATAL(status, HDMI_CEC_IO_SUCCESS); + + UT_LOG_INFO("Out %s\n", __FUNCTION__); +} + +/** +* @brief This test provides a scope to add the logical address +* +* This test case provides a scope to add the available logical address +* to a Device under test. +* Note: +* This applies only for the Sink Devices. +* Source devices will get the logical address during CEC open. +* +* **Test Group ID:** 02@n +* **Test Case ID:** 002@n +* +*/ +void test_l3_hdmi_cec_sink_hal_AddLogicalAddress(void) +{ + gTestID = 2; + UT_LOG_INFO("In %s [%02d%03d]\n", __FUNCTION__, gTestGroup, gTestID); + + + HDMI_CEC_STATUS status; + int logicalAddress; + + UT_LOG_DEBUG("Enter Logical Address to add: "); + scanf("Logical Address: %d", &logicalAddress); + + /* Check that logical address should be valid one */ + + status = HdmiCecAddLogicalAddress(gHandle,logicalAddress ); + UT_LOG_DEBUG("Invoking HdmiCecAddLogicalAddress with handle: %d and logicalAddress: %d", gHandle, logicalAddress); + //UT_ASSERT_EQUAL(status, HDMI_CEC_IO_SUCCESS); + if (status != HDMI_CEC_IO_SUCCESS) + { + UT_LOG_ERROR("HdmiCecAddLogicalAddress failed with status: %d\n", status); + } + + UT_LOG_INFO("Out %s\n", __FUNCTION__); +} + + +/** +* @brief Test to get the logical address +* +* +* **Test Group ID:** 02@n +* **Test Case ID:** 003@n +* +*/ + +void test_l3_hdmi_cec_sink_hal_GetLogicalAddress(void) +{ + gTestID = 3; + UT_LOG_INFO("In %s [%02d%03d]\n", __FUNCTION__, gTestGroup, gTestID); + + HDMI_CEC_STATUS status; + int logicalAddress = -1; + + status = HdmiCecGetLogicalAddress(gHandle, &logicalAddress); + UT_LOG_DEBUG("Invoking HdmiCecGetLogicalAddress with handle: %d and logicalAddress: %d", gHandle, logicalAddress); + //UT_ASSERT_EQUAL(status, HDMI_CEC_IO_SUCCESS); + if (status != HDMI_CEC_IO_SUCCESS) + { + UT_LOG_ERROR("HdmiCecAddLogicalAddress failed with status: %d\n", status); + } + + UT_LOG_INFO("Out %s\n", __FUNCTION__); +} + + +/** +* @brief Test to Transmit the CEC Command +* +* +* **Test Group ID:** 02@n +* **Test Case ID:** 003@n +* +*/ + + +void test_l3_hdmi_cec_sink_hal_TransmitHdmiCecCommand(void) +{ + gTestID = 4; + UT_LOG_INFO("In %s [%02d%03d]\n", __FUNCTION__, gTestGroup, gTestID); + + int sourceLogicalAddress = -1; // Example source logical address + int destinationLogicalAddress = -1; // Example destination logical address + unsigned char buf[16] = {0}; // Example CEC message buffer + int len = 0, cecCommand = 0, cecCommandDataLength = 0; + int result; + + // Reading inputs from the user or test framework + UT_LOG_DEBUG("Source Logical Address:"); + scanf("%d",&sourceLogicalAddress); + + UT_LOG_DEBUG("Destination Logical Address: "); + scanf("%d",&destinationLogicalAddress); + + UT_LOG_DEBUG("Enter CEC Command: "); + scanf("%x", &cecCommand); + printf("CEC Command:%x \n",cecCommand); + UT_LOG_DEBUG("Length of CEC Command data: "); + scanf("%d",&cecCommandDataLength); + + // Reading CEC Command data + for (int i = 0; i < cecCommandDataLength; i++) { + UT_LOG_DEBUG("Databyte[%d]=",i); + scanf("%x", &buf[i + 2]); // +2 to account for the first two bytes + } + + // Building the CEC message + buf[0] = (unsigned char)((sourceLogicalAddress << 4) | (destinationLogicalAddress & 0x0F)); + buf[1] = (unsigned char)cecCommand; + + len = cecCommandDataLength + 2; // 1 byte for logical addresses, 1 byte for CEC Command + + // Assume HdmiCecTx is a function to send the CEC command + int status = HdmiCecTx(gHandle, buf, len, &result); + + UT_LOG_DEBUG("Invoking HdmiCecTx with handle: %d status:%d result:%d \n", gHandle, status, result); + //UT_ASSERT_EQUAL(status, HDMI_CEC_IO_SUCCESS); + //UT_ASSERT_EQUAL(result, HDMI_CEC_IO_SENT_BUT_NOT_ACKD); + + if ((result != HDMI_CEC_IO_SENT_BUT_NOT_ACKD) && (status != HDMI_CEC_IO_SUCCESS)) { + UT_LOG_ERROR("HdmiCecTx failed with status: %d result:%d\n", status, result); + } + + sleep(5); + + UT_LOG_INFO("Out %s\n", __FUNCTION__); +} + + + + + +/** +* @brief Test to Receive the CEC Command +* +* +* **Test Group ID:** 02@n +* **Test Case ID:** 005@n +* +*/ + + +void test_l3_hdmi_cec_sink_hal_ReceiveHdmiCecCommand(void) +{ + gTestID = 5; + UT_LOG_INFO("In %s [%02d%03d]\n", __FUNCTION__, gTestGroup, gTestID); + + sleep(REPLY_TIMEOUT); // Wait for a reply + + if (cbFlag != 1) + { + UT_LOG_ERROR("HdmiCecRx failed to receive data"); + } + + cbFlag = 0; + + UT_LOG_INFO("Out %s\n", __FUNCTION__); +} + +/** +* @brief Test to get the physical address +* +* +* **Test Group ID:** 02@n +* **Test Case ID:** 006@n +* +*/ +void test_l3_hdmi_cec_sink_hal_GetPhysicalAddress(void) +{ + gTestID = 6; + UT_LOG_INFO("In %s [%02d%03d]\n", __FUNCTION__, gTestGroup, gTestID); + + HDMI_CEC_STATUS status; + int physicalAddress = -1; + + status = HdmiCecGetPhysicalAddress(gHandle, &physicalAddress); + UT_LOG_DEBUG("Invoking HdmiCecGetPhysicalAddress with handle: %d and physical Address: %d", gHandle, physicalAddress); + //UT_ASSERT_EQUAL(status, HDMI_CEC_IO_SUCCESS); + if (status != HDMI_CEC_IO_SUCCESS) + { + UT_LOG_ERROR("HdmiCecgetPhysicalAddress failed with status: %d\n", status); + } + + UT_LOG_INFO("Out %s\n", __FUNCTION__); +} + +/** +* @brief Test to Remove logical address +* +* +* **Test Group ID:** 02@n +* **Test Case ID:** 006@n +* +*/ +void test_l3_hdmi_cec_sink_hal_RemoveLogicalAddress(void) +{ + gTestID = 7; + UT_LOG_INFO("In %s [%02d%03d]\n", __FUNCTION__, gTestGroup, gTestID); + + HDMI_CEC_STATUS status; + int logicalAddress; + + UT_LOG_DEBUG("Enter Logical Address to Remove: "); + scanf("Logical Address: %d", &logicalAddress); + + // Invoke the API HdmiCecRemoveLogicalAddress + status = HdmiCecRemoveLogicalAddress(gHandle, logicalAddress); + UT_LOG_DEBUG("Invoking HdmiCecRemoveLogicalAddress with handle: %d and logicalAddress: %d", gHandle, logicalAddress); + // UT_ASSERT_EQUAL(status, HDMI_CEC_IO_SUCCESS); + if (status != HDMI_CEC_IO_SUCCESS) + { + UT_LOG_ERROR("HdmiCecRemoveLogicalAddress failed with status: %d\n", status); + } + + UT_LOG_INFO("Out %s\n", __FUNCTION__); +} + +void test_l2_hdmi_cec_sink_hal_Close(void) +{ + gTestID = 8; + HDMI_CEC_STATUS status; + + UT_LOG_INFO("In %s [%02d%03d]\n", __FUNCTION__, gTestGroup, gTestID); + + // Step 1: Call the pre-requisite API HdmiCecOpen() + UT_LOG_DEBUG("Invoking HdmiCecOpen with valid handle"); + status = HdmiCecClose(gHandle); + //UT_ASSERT_EQUAL_FATAL(status, HDMI_CEC_IO_SUCCESS); + //UT_ASSERT_NOT_EQUAL_FATAL(gHandle, 0); + + UT_LOG_INFO("Out %s\n", __FUNCTION__); +} + + +static UT_test_suite_t * pSuite = NULL; + +/** + * @brief Register the main tests for this module + * + * @return int - 0 on success, otherwise failure + */ +int test_register_hdmicec_hal_sink_l3_tests(void) +{ + // Create the test suite + pSuite = UT_add_suite("[L3 HDMICEC Sink Functions] ", NULL, NULL); + if (pSuite == NULL) + { + return -1; + } + // List of test function names and strings + + UT_add_test( pSuite, "L3_Init_HdmiCec", test_l3_hdmi_cec_sink_hal_Init); + UT_add_test( pSuite, "L3_AddLogicalAddress", test_l3_hdmi_cec_sink_hal_AddLogicalAddress); + UT_add_test( pSuite, "L3_GetLogicalAddress", test_l3_hdmi_cec_sink_hal_GetLogicalAddress); + UT_add_test( pSuite, "L3_TransmitCecCommand", test_l3_hdmi_cec_sink_hal_TransmitHdmiCecCommand); + UT_add_test( pSuite, "L3_ReceiveCecCommand", test_l3_hdmi_cec_sink_hal_ReceiveHdmiCecCommand); + UT_add_test( pSuite, "L3_GetPhyiscalAddress", test_l3_hdmi_cec_sink_hal_GetPhysicalAddress); + UT_add_test( pSuite, "L3_RemoveLogicalAddressHdmiCec_Sink", test_l3_hdmi_cec_sink_hal_RemoveLogicalAddress); + UT_add_test( pSuite, "L3_Close_HdmiCec_Sink", test_l2_hdmi_cec_sink_hal_Close); + + return 0; +} + +/** @} */ // End of HDMI CEC HAL Tests L1 File +/** @} */ // End of HDMI CEC HAL Tests +/** @} */ // End of HDMI CEC Module +/** @} */ // End of HPK diff --git a/src/test_register.c b/src/test_register.c index fbdf048..7722b05 100644 --- a/src/test_register.c +++ b/src/test_register.c @@ -66,7 +66,7 @@ extern int test_hdmidec_hal_l1_register_sink_tests( void ); extern int test_hdmidec_hal_l1_register_source_tests( void ); extern int test_register_hdmicec_hal_source_l2_tests( void ); extern int test_register_hdmicec_hal_sink_l2_tests( void ); - +extern int test_register_hdmicec_hal_sink_l3_tests(void); int register_hdmicec_hal_common_l1_tests( void ) { @@ -110,6 +110,16 @@ int register_hdmicec_hal_sink_l2_tests( void ) return registerFailed; } +int register_hdmicec_hal_sink_l3_tests( void ) +{ + int registerFailed=0; + + registerFailed |= test_register_hdmicec_hal_sink_l3_tests(); + + return registerFailed; +} + + /** @} */ // End of HDMI CEC HAL Tests Register File /** @} */ // End of HDMI CEC HAL Tests /** @} */ // End of HDMI CEC Module From a7ad1365eeb1cf0d18816027a8ff4bbb1b982ca2 Mon Sep 17 00:00:00 2001 From: srinivasgtl <71806084+srinivasgtl@users.noreply.github.com> Date: Tue, 6 Aug 2024 19:02:42 +0100 Subject: [PATCH 17/40] gh #44 - Updated the documentation part. --- src/test_l3_hdmi_cec_sink_driver.c | 134 ++++++++++++++++++++++++----- 1 file changed, 114 insertions(+), 20 deletions(-) diff --git a/src/test_l3_hdmi_cec_sink_driver.c b/src/test_l3_hdmi_cec_sink_driver.c index 827aca8..9892193 100644 --- a/src/test_l3_hdmi_cec_sink_driver.c +++ b/src/test_l3_hdmi_cec_sink_driver.c @@ -36,7 +36,7 @@ /** - * @defgroup HDMI_CEC_HALTESTS_L2 HDMI CEC HAL Tests L2 File + * @defgroup HDMI_CEC_HALTESTS_L3 HDMI CEC HAL Tests L2 File * @{ * @parblock * @@ -44,8 +44,8 @@ * * * ## Module's Role - * This module includes Level 2 functional tests (success and failure scenarios). - * This is to ensure that the hdmi_cec_driver APIs meet the requirements across all vendors. + * This module includes Level 3 functional test interfaces. + * This Test Interfaces provides a scope to create a User Test cases for HDMI CEC Sink modules that can be either Manual or automated scripts. * * **Pre-Conditions:** None@n * **Dependencies:** None@n @@ -56,7 +56,7 @@ */ /** - * @file test_l2_hdmi_cec_sink_driver.c + * @file test_l3_hdmi_cec_sink_driver.c * */ @@ -72,6 +72,18 @@ static int gTestID = 1; static int gHandle = 0; static int cbFlag = 0; + +/** +* @brief Rx Callback function +* +* This function is a Receive Call back function called when data is received from a connected device. +* This function should be registered through HdmiCecSetRxCallback(). +* +* **Test Group ID:** 03@n +* **Test Case ID:** 000@n +* +*/ + /* Callback function */ void onRxDataReceived(int handle, void *callbackData, unsigned char *buf, int len) { @@ -106,10 +118,16 @@ void onRxDataReceived(int handle, void *callbackData, unsigned char *buf, int le * * **Test Group ID:** 03@n +* * **Test Case ID:** 001@n * -* **Test Procedure:** -* Refer to UT specification documentation +* **Pre-Conditions:** None@n +* +* **Dependencies:** None@n +* +* **User Interaction:** @n +* User or Automation tool should select the Test 1 to before running any test. +* */ void test_l3_hdmi_cec_sink_hal_Init(void) @@ -135,17 +153,27 @@ void test_l3_hdmi_cec_sink_hal_Init(void) } /** -* @brief This test provides a scope to add the logical address +* @brief This test provides a scope to add the sink logical address. Usually it shall be zero. * -* This test case provides a scope to add the available logical address +* This test case provides a scope to add the available sink logical address * to a Device under test. +* * Note: * This applies only for the Sink Devices. * Source devices will get the logical address during CEC open. * * **Test Group ID:** 02@n +* * **Test Case ID:** 002@n * +* **Pre-Conditions:** @n +* HDMI-CEC Module should be intialized through Test 1 before calling this test. +* +* **Dependencies:** None@n +* +* **User Interaction:** @n +* User or Automation tool should select the Test 2 and provide the logical address. +* */ void test_l3_hdmi_cec_sink_hal_AddLogicalAddress(void) { @@ -176,12 +204,22 @@ void test_l3_hdmi_cec_sink_hal_AddLogicalAddress(void) /** * @brief Test to get the logical address * +* This test provides a scope to check the assigned logical address of the device. * * **Test Group ID:** 02@n +* * **Test Case ID:** 003@n * -*/ +* **Pre-Conditions:** @n +* HDMI-CEC Module should be intialized through Test 1 before calling this test. +* +* **Dependencies:** None@n +* +* **User Interaction:** @n +* User or Automation tool should select the Test 3 and shall read the Logical address displayed on the console. +* +*/ void test_l3_hdmi_cec_sink_hal_GetLogicalAddress(void) { gTestID = 3; @@ -203,15 +241,25 @@ void test_l3_hdmi_cec_sink_hal_GetLogicalAddress(void) /** -* @brief Test to Transmit the CEC Command +* @brief Test provides a scope to Transmit the CEC Command * +* This test provides an interface to user/automation tool to transmit a CEC Command. +* Necessary input should be provided to the test. * * **Test Group ID:** 02@n -* **Test Case ID:** 003@n +* +* **Test Case ID:** 004@n +* +* **Pre-Conditions:** @n +* HDMI-CEC Module should be intialized through Test 1 before calling this test. +* +* **Dependencies:** None@n +* +* **User Interaction:** @n +* User or Automation tool should select the Test 4 and shall provide the necessary source and destination logical address, +* CEC command, data lenght and data. * */ - - void test_l3_hdmi_cec_sink_hal_TransmitHdmiCecCommand(void) { gTestID = 4; @@ -264,20 +312,26 @@ void test_l3_hdmi_cec_sink_hal_TransmitHdmiCecCommand(void) UT_LOG_INFO("Out %s\n", __FUNCTION__); } - - - - /** * @brief Test to Receive the CEC Command * +* This test provides an interface to check whether the CEC has received any frames or not. * * **Test Group ID:** 02@n +* * **Test Case ID:** 005@n * +* **Pre-Conditions:** @n +* HDMI-CEC Module should be intialized through Test 1 before calling this test. +* +* **Dependencies:** @n +* Depends on the external device to send a CEC Frames with necessary command and data. +* +* **User Interaction:** @n +* User or Automation tool should select the Test 5 and make sure that the CEC Frames has been sent from an external +* device connected in the network. +* */ - - void test_l3_hdmi_cec_sink_hal_ReceiveHdmiCecCommand(void) { gTestID = 5; @@ -298,10 +352,21 @@ void test_l3_hdmi_cec_sink_hal_ReceiveHdmiCecCommand(void) /** * @brief Test to get the physical address * +* This test provides a scope to read the physical address of the device. * * **Test Group ID:** 02@n +* * **Test Case ID:** 006@n * +* **Pre-Conditions:** @n +* HDMI-CEC Module should be intialized through Test 1 before calling this test. +* +* **Dependencies:** None@n +* +* **User Interaction:** @n +* User or Automation tool should select the Test 6 to read the physical address of the device +* device connected in the network. +* */ void test_l3_hdmi_cec_sink_hal_GetPhysicalAddress(void) { @@ -325,9 +390,20 @@ void test_l3_hdmi_cec_sink_hal_GetPhysicalAddress(void) /** * @brief Test to Remove logical address * +* This test provides a scope to remove the logical address of the device. HAL API to set +* to default logical addres 0xF once the logical address is removed. * * **Test Group ID:** 02@n -* **Test Case ID:** 006@n +* +* **Test Case ID:** 07@n +* +* **Pre-Conditions:** @n +* HDMI-CEC Module should be intialized through Test 1 before calling this test. +* +* **Dependencies:** None@n +* +* **User Interaction:** @n +* User or Automation tool should select the Test 7 to delete the logical address. * */ void test_l3_hdmi_cec_sink_hal_RemoveLogicalAddress(void) @@ -353,6 +429,24 @@ void test_l3_hdmi_cec_sink_hal_RemoveLogicalAddress(void) UT_LOG_INFO("Out %s\n", __FUNCTION__); } +/** +* @brief Test to close the HDMI CEC device. +* +* This test provides a scope to close the created HDMI CEC handle. +* +* **Test Group ID:** 02@n +* +* **Test Case ID:** 08@n +* +* **Pre-Conditions:** @n +* HDMI-CEC Module should be intialized through Test 1 before calling this test. +* +* **Dependencies:** None@n +* +* **User Interaction:** @n +* User or Automation tool should select the Test 8 to close the created HDMI CEC handle. +* +*/ void test_l2_hdmi_cec_sink_hal_Close(void) { gTestID = 8; From 44f08d75e4fc49d333a1d61dd6a36d4aeb584bac Mon Sep 17 00:00:00 2001 From: srinivasgtl <71806084+srinivasgtl@users.noreply.github.com> Date: Thu, 22 Aug 2024 16:31:12 +0100 Subject: [PATCH 18/40] gh #44 Updated with proper logging --- src/test_l3_hdmi_cec_sink_driver.c | 356 ++++++++++++++++++++--------- 1 file changed, 244 insertions(+), 112 deletions(-) diff --git a/src/test_l3_hdmi_cec_sink_driver.c b/src/test_l3_hdmi_cec_sink_driver.c index 9892193..8cf77e3 100644 --- a/src/test_l3_hdmi_cec_sink_driver.c +++ b/src/test_l3_hdmi_cec_sink_driver.c @@ -72,11 +72,81 @@ static int gTestID = 1; static int gHandle = 0; static int cbFlag = 0; +// CEC command map table and supporting function +typedef struct { + unsigned char cecCommand; // CEC command code + const char* commandName; // Human-readable command name + int dataLength; // Number of data bytes required for the command +} CecCommandMap; + +CecCommandMap cecCommandTable[] = { + {0x00, "Feature Abort", 2}, + {0x04, "Image View On", 0}, + {0x0D, "Text View On", 0}, + {0x20, "Active Source", 2}, + {0x32, "Inactive Source", 2}, + {0x36, "Request Active Source", 0}, + {0x41, "Standby", 0}, + {0x44, "User Control Pressed", 1}, + {0x45, "User Control Released", 0}, + {0x46, "Give OSD Name", 0}, + {0x47, "Set OSD Name", 15}, + {0x82, "Routing Change", 4}, + {0x83, "Routing Information", 2}, + {0x86, "Report Physical Address", 3}, + {0x87, "Request Active Source", 0}, + {0x8C, "Give Device Vendor ID", 0}, + {0x89, "Device Vendor ID", 3}, + {0x90, "Vendor Command", 16}, + {0x91, "Vendor Command with ID", 16}, + {0x92, "Give Device Power Status", 0}, + {0x93, "Report Power Status", 1}, + {0x9E, "CEC Version", 1}, + {0x9F, "Get CEC Version", 0}, + {0xA0, "Get Menu Language", 0}, + {0xA1, "Set Menu Language", 3}, + {0xA5, "Report Physical Address", 3}, + {0xA6, "Request Short Audio Descriptor", 1}, + {0xC0, "Report Audio Status", 1}, + {0xC1, "Give Audio Status", 0}, + {0xC2, "Set System Audio Mode", 1}, + {0xC3, "Report Audio Descriptor", 1}, + {0xC4, "Set Audio Rate", 1}, + // Add more commands as needed +}; + +/** +* @brief CEC Command with data size mapping function. +* +* This function maps the provided CEC command with the data length required for the CEC Command. +* This will help the test to consider the correct size of the data required for the CEC Command. +* +* **Test Group ID:** 03@n +* **Test Case ID:** 000@n +* +*/ +int getCecCommandInfo(unsigned char cecCommand, const char** commandName, int* dataLength) { + UT_LOG_INFO("In %s(IN: cecCommand: [0x%02X])\n", __FUNCTION__, cecCommand); + + int tableSize = sizeof(cecCommandTable) / sizeof(CecCommandMap); + + for (int i = 0; i < tableSize; i++) { + if (cecCommandTable[i].cecCommand == cecCommand) { + *commandName = cecCommandTable[i].commandName; + *dataLength = cecCommandTable[i].dataLength; + UT_LOG_INFO("Out %s(OUT: commandName: [%s], OUT: dataLength: [%d])\n", __FUNCTION__, *commandName, *dataLength); + return 0; // Command found + } + } + + UT_LOG_INFO("Out %s(OUT: Command not found)\n", __FUNCTION__); + return -1; // Command not found +} /** * @brief Rx Callback function * -* This function is a Receive Call back function called when data is received from a connected device. +* This function is a Receive Call back function called when data is received from a connected device. * This function should be registered through HdmiCecSetRxCallback(). * * **Test Group ID:** 03@n @@ -85,31 +155,37 @@ static int cbFlag = 0; */ /* Callback function */ -void onRxDataReceived(int handle, void *callbackData, unsigned char *buf, int len) -{ - UT_LOG ("\nBuffer generated: %x length: %d\n",buf, len); - if((handle!=0) && (callbackData !=NULL) && (len>0)) { - UT_LOG("\nCall back data generated is \n"); - for (int index=0; index < len; index++) { - UT_LOG("buf at index : %d is %x \n", index, buf[index]); - } - - memset(buf, 0, len); - } - else { +void onRxDataReceived(int handle, void *callbackData, unsigned char *buf, int len) { + UT_LOG_INFO("In %s(IN: handle: [%d], IN: callbackData: [%p], IN: buf: [%p], IN: len: [%d])\n", __FUNCTION__, handle, callbackData, buf, len); + + if ((handle != 0) && (callbackData != NULL) && (len > 0)) { + UT_LOG_INFO("CEC Data Received\n"); + + // Log each byte received in the buffer + for (int index = 0; index < len; index++) { + UT_LOG_INFO("Buffer at index [%d]: [0x%02X]\n", index, buf[index]); + } + + // Clear the buffer after processing + memset(buf, 0, len); + UT_LOG_INFO("Buffer cleared after processing.\n"); + + } else { + // Log specific errors based on failed conditions if (handle == 0) { - UT_FAIL("Error: Invalid handle.\n"); + UT_LOG_ERROR("Error: Invalid handle.\n"); } if (callbackData == NULL) { - UT_FAIL("Error: Null callback data.\n"); + UT_LOG_ERROR("Error: Null callback data.\n"); } if (len <= 0) { - UT_FAIL("Error: Invalid length.\n"); + UT_LOG_ERROR("Error: Invalid length.\n"); } } - cbFlag = 1; -} + cbFlag = 1; + UT_LOG_INFO("Out %s(OUT: cbFlag set to [1])\n", __FUNCTION__); +} /** * @brief Initialization of the HAL CEC Module @@ -132,24 +208,28 @@ void onRxDataReceived(int handle, void *callbackData, unsigned char *buf, int le void test_l3_hdmi_cec_sink_hal_Init(void) { - gTestID = 1; - HDMI_CEC_STATUS status; - - UT_LOG_INFO("In %s [%02d%03d]\n", __FUNCTION__, gTestGroup, gTestID); - - // Step 1: Call HdmiCecOpen() - UT_LOG_DEBUG("Invoking HdmiCecOpen with valid handle"); - status = HdmiCecOpen(&gHandle); - //UT_ASSERT_EQUAL_FATAL(status, HDMI_CEC_IO_SUCCESS); - //UT_ASSERT_NOT_EQUAL_FATAL(gHandle, 0); - if ((status != HDMI_CEC_IO_SUCCESS) || (gHandle == NULL)) - UT_LOG_ERROR("Invoking HdmiCecOpen failed"); - - // Step 2: Register the call back - status = HdmiCecSetRxCallback(gHandle, onRxDataReceived,(void*)0xABABABAB); - //UT_ASSERT_EQUAL_FATAL(status, HDMI_CEC_IO_SUCCESS); - - UT_LOG_INFO("Out %s\n", __FUNCTION__); + gTestID = 1; + HDMI_CEC_STATUS status = HDMI_CEC_IO_SUCCESS; + + UT_LOG_INFO("In %s [%02d%03d]\n", __FUNCTION__, gTestGroup, gTestID); + + // Step 1: Call HdmiCecOpen() + UT_LOG_INFO("Calling HdmiCecOpen(IN:gHandle[0x%0X])",&gHandle); + status = HdmiCecOpen(&gHandle); + if ((status != HDMI_CEC_IO_SUCCESS) || (gHandle == NULL)) + { + UT_LOG_ERROR("Failed to Invoke HdmiCecOpen()"); + } + + // Step 2: Register the call back + UT_LOG_INFO("Calling HdmiCecSetRxCallback(IN:handle[0x%0X],IN:cbfunc[0x%0X]",gHandle,onRxDataReceived); + status = HdmiCecSetRxCallback(gHandle, onRxDataReceived,(void*)0xABABABAB); + if(status != HDMI_CEC_IO_SUCCESS) + { + UT_LOG_ERROR("Failed HdmiCecSetRxCallback(IN:handle[0x%0X],IN:cbfunc[0x%0X]) status:%d",gHandle,onRxDataReceived),status; + } + + UT_LOG_INFO("Out %s\n", __FUNCTION__); } /** @@ -158,7 +238,7 @@ void test_l3_hdmi_cec_sink_hal_Init(void) * This test case provides a scope to add the available sink logical address * to a Device under test. * -* Note: +* Note: * This applies only for the Sink Devices. * Source devices will get the logical address during CEC open. * @@ -168,7 +248,7 @@ void test_l3_hdmi_cec_sink_hal_Init(void) * * **Pre-Conditions:** @n * HDMI-CEC Module should be intialized through Test 1 before calling this test. -* +* * **Dependencies:** None@n * * **User Interaction:** @n @@ -180,22 +260,21 @@ void test_l3_hdmi_cec_sink_hal_AddLogicalAddress(void) gTestID = 2; UT_LOG_INFO("In %s [%02d%03d]\n", __FUNCTION__, gTestGroup, gTestID); - - HDMI_CEC_STATUS status; - int logicalAddress; - - UT_LOG_DEBUG("Enter Logical Address to add: "); - scanf("Logical Address: %d", &logicalAddress); + HDMI_CEC_STATUS status = HDMI_CEC_IO_SUCCESS; + int logicalAddress = -1; - /* Check that logical address should be valid one */ + UT_LOG_MENU_INFO("----------------------------------------------------------"); + UT_LOG_MENU_INFO("Enter Logical Address: "); + scanf("%d", &logicalAddress); + /* Check that logical address should be valid one */ + UT_LOG_INFO("Calling HdmiCecAddLogicalAddress(IN:handle:[0x%0X], IN:logicalAddress:[%d]",gHandle,logicalAddress); status = HdmiCecAddLogicalAddress(gHandle,logicalAddress ); - UT_LOG_DEBUG("Invoking HdmiCecAddLogicalAddress with handle: %d and logicalAddress: %d", gHandle, logicalAddress); - //UT_ASSERT_EQUAL(status, HDMI_CEC_IO_SUCCESS); + if (status != HDMI_CEC_IO_SUCCESS) { - UT_LOG_ERROR("HdmiCecAddLogicalAddress failed with status: %d\n", status); - } + UT_LOG_ERROR("Failed HdmiCecAddLogicalAddress (IN:handle:[0x%0X], IN:logicalAddress:[%d]), status[%d]",gHandle,logicalAddress,status); + } UT_LOG_INFO("Out %s\n", __FUNCTION__); } @@ -225,26 +304,32 @@ void test_l3_hdmi_cec_sink_hal_GetLogicalAddress(void) gTestID = 3; UT_LOG_INFO("In %s [%02d%03d]\n", __FUNCTION__, gTestGroup, gTestID); - HDMI_CEC_STATUS status; - int logicalAddress = -1; + HDMI_CEC_STATUS status = HDMI_CEC_IO_SUCCESS; + int logicalAddress = -1; + UT_LOG_INFO("Calling HdmiCecGetLogicalAddress(IN: handle: [0x%0X], OUT: logicalAddress: [])", gHandle); status = HdmiCecGetLogicalAddress(gHandle, &logicalAddress); - UT_LOG_DEBUG("Invoking HdmiCecGetLogicalAddress with handle: %d and logicalAddress: %d", gHandle, logicalAddress); - //UT_ASSERT_EQUAL(status, HDMI_CEC_IO_SUCCESS); - if (status != HDMI_CEC_IO_SUCCESS) + + if (status == HDMI_CEC_IO_SUCCESS) + { + UT_LOG_INFO("HdmiCecGetLogicalAddress successful (OUT: logicalAddress: [%d])", logicalAddress); + } + else { - UT_LOG_ERROR("HdmiCecAddLogicalAddress failed with status: %d\n", status); - } + UT_LOG_ERROR("HdmiCecGetLogicalAddress failed (IN: handle: [0x%0X], OUT: logicalAddress: [%d]), status: [%d])", gHandle, logicalAddress, status); + // Additional error handling can be added here if necessary + } UT_LOG_INFO("Out %s\n", __FUNCTION__); } + /** * @brief Test provides a scope to Transmit the CEC Command * * This test provides an interface to user/automation tool to transmit a CEC Command. -* Necessary input should be provided to the test. +* Necessary input should be provided to the test. * * **Test Group ID:** 02@n * @@ -257,56 +342,75 @@ void test_l3_hdmi_cec_sink_hal_GetLogicalAddress(void) * * **User Interaction:** @n * User or Automation tool should select the Test 4 and shall provide the necessary source and destination logical address, -* CEC command, data lenght and data. +* CEC command, data lenght and data. * */ -void test_l3_hdmi_cec_sink_hal_TransmitHdmiCecCommand(void) -{ +void test_l3_hdmi_cec_sink_hal_TransmitHdmiCecCommand(void) { gTestID = 4; UT_LOG_INFO("In %s [%02d%03d]\n", __FUNCTION__, gTestGroup, gTestID); - int sourceLogicalAddress = -1; // Example source logical address - int destinationLogicalAddress = -1; // Example destination logical address - unsigned char buf[16] = {0}; // Example CEC message buffer - int len = 0, cecCommand = 0, cecCommandDataLength = 0; + int sourceLogicalAddress = -1; + int destinationLogicalAddress = -1; + unsigned char buf[16] = {0}; + int len = 0, cecCommand = 0; int result; + const char* commandName; + int expectedDataLength; // Reading inputs from the user or test framework - UT_LOG_DEBUG("Source Logical Address:"); - scanf("%d",&sourceLogicalAddress); + UT_LOG_MENU_INFO("Enter a valid Source Logical Address:"); + scanf("%d", &sourceLogicalAddress); - UT_LOG_DEBUG("Destination Logical Address: "); - scanf("%d",&destinationLogicalAddress); + UT_LOG_MENU_INFO("Enter a valid Destination Logical Address: "); + scanf("%d", &destinationLogicalAddress); - UT_LOG_DEBUG("Enter CEC Command: "); + UT_LOG_MENU_INFO("Enter CEC Command (in hex): "); scanf("%x", &cecCommand); - printf("CEC Command:%x \n",cecCommand); - UT_LOG_DEBUG("Length of CEC Command data: "); - scanf("%d",&cecCommandDataLength); - - // Reading CEC Command data - for (int i = 0; i < cecCommandDataLength; i++) { - UT_LOG_DEBUG("Databyte[%d]=",i); - scanf("%x", &buf[i + 2]); // +2 to account for the first two bytes + + // Validate the CEC command and get the expected data length + if (getCecCommandInfo(cecCommand, &commandName, &expectedDataLength) != 0) { + // Command not found in the map, prompt the user for additional information + UT_LOG_WARNING("CEC command 0x%02X is not recognized. It might be a vendor-specific command.", cecCommand); + + UT_LOG_MENU_INFO("Please enter the number of data bytes for the CEC command: "); + scanf("%d", &expectedDataLength); + + commandName = "Vendor Specific Command"; + } else { + UT_LOG_INFO("CEC Command: %s (0x%02X), expects %d data byte(s)", commandName, cecCommand, expectedDataLength); + } + + // If the command has data bytes, prompt for them + if (expectedDataLength > 0) { + for (int i = 0; i < expectedDataLength; i++) { + UT_LOG_MENU_INFO("Enter Databyte[%d] (in hex):", i); + scanf("%x", &buf[i + 2]); // +2 to account for the first two bytes + } } // Building the CEC message buf[0] = (unsigned char)((sourceLogicalAddress << 4) | (destinationLogicalAddress & 0x0F)); buf[1] = (unsigned char)cecCommand; + len = expectedDataLength + 2; // 1 byte for logical addresses, 1 byte for CEC Command - len = cecCommandDataLength + 2; // 1 byte for logical addresses, 1 byte for CEC Command + // Logging the transmission attempt + UT_LOG_INFO("Calling HdmiCecTx(IN: handle: [0x%0X], IN: message length: [%d], IN: message data: [", gHandle, len); + for (int i = 0; i < len; i++) { + printf(" %02X", buf[i]); + } + printf(" ])"); // Assume HdmiCecTx is a function to send the CEC command int status = HdmiCecTx(gHandle, buf, len, &result); - UT_LOG_DEBUG("Invoking HdmiCecTx with handle: %d status:%d result:%d \n", gHandle, status, result); - //UT_ASSERT_EQUAL(status, HDMI_CEC_IO_SUCCESS); - //UT_ASSERT_EQUAL(result, HDMI_CEC_IO_SENT_BUT_NOT_ACKD); - - if ((result != HDMI_CEC_IO_SENT_BUT_NOT_ACKD) && (status != HDMI_CEC_IO_SUCCESS)) { - UT_LOG_ERROR("HdmiCecTx failed with status: %d result:%d\n", status, result); + // Logging the result of the transmission + if ((result == HDMI_CEC_IO_SENT_BUT_NOT_ACKD) && (status == HDMI_CEC_IO_SUCCESS)) { + UT_LOG_INFO("HdmiCecTx successful (OUT: result: [%d])", result); + } else { + UT_LOG_ERROR("HdmiCecTx failed (IN: handle: [0x%0X], IN: length: [%d], result: [%d], status:[%d])", gHandle, len, result, status); } + // Optional delay after sending the command sleep(5); UT_LOG_INFO("Out %s\n", __FUNCTION__); @@ -337,18 +441,26 @@ void test_l3_hdmi_cec_sink_hal_ReceiveHdmiCecCommand(void) gTestID = 5; UT_LOG_INFO("In %s [%02d%03d]\n", __FUNCTION__, gTestGroup, gTestID); - sleep(REPLY_TIMEOUT); // Wait for a reply + UT_LOG_INFO("Waiting for HDMI CEC command (timeout: %d seconds)", REPLY_TIMEOUT); - if (cbFlag != 1) - { - UT_LOG_ERROR("HdmiCecRx failed to receive data"); - } + sleep(REPLY_TIMEOUT); // Wait for a reply + + if (cbFlag != 1) + { + UT_LOG_ERROR("HdmiCecRx failed to receive data (IN: expected callback flag: [1], OUT: actual callback flag: [%d])", cbFlag); + } + else + { + UT_LOG_INFO("HdmiCecRx successfully received data (OUT: callback flag: [%d])", cbFlag); + } + + // Resetting callback flag for future tests + cbFlag = 0; - cbFlag = 0; - UT_LOG_INFO("Out %s\n", __FUNCTION__); } + /** * @brief Test to get the physical address * @@ -373,20 +485,26 @@ void test_l3_hdmi_cec_sink_hal_GetPhysicalAddress(void) gTestID = 6; UT_LOG_INFO("In %s [%02d%03d]\n", __FUNCTION__, gTestGroup, gTestID); - HDMI_CEC_STATUS status; - int physicalAddress = -1; + HDMI_CEC_STATUS status = HDMI_CEC_IO_SUCCESS; + int physicalAddress = -1; + + UT_LOG_INFO("Calling HdmiCecGetPhysicalAddress(IN: handle: [0x%0X], OUT: physicalAddress: [uninitialized])", gHandle); status = HdmiCecGetPhysicalAddress(gHandle, &physicalAddress); - UT_LOG_DEBUG("Invoking HdmiCecGetPhysicalAddress with handle: %d and physical Address: %d", gHandle, physicalAddress); - //UT_ASSERT_EQUAL(status, HDMI_CEC_IO_SUCCESS); - if (status != HDMI_CEC_IO_SUCCESS) + + if (status == HDMI_CEC_IO_SUCCESS) + { + UT_LOG_INFO("HdmiCecGetPhysicalAddress successful (OUT: physicalAddress: [0x%04X])", physicalAddress); + } + else { - UT_LOG_ERROR("HdmiCecgetPhysicalAddress failed with status: %d\n", status); + UT_LOG_ERROR("HdmiCecGetPhysicalAddress failed (IN: handle: [0x%0X], physicalAddress: [%d]), status:[%d]", gHandle, physicalAddress, status); } UT_LOG_INFO("Out %s\n", __FUNCTION__); } + /** * @brief Test to Remove logical address * @@ -411,31 +529,35 @@ void test_l3_hdmi_cec_sink_hal_RemoveLogicalAddress(void) gTestID = 7; UT_LOG_INFO("In %s [%02d%03d]\n", __FUNCTION__, gTestGroup, gTestID); - HDMI_CEC_STATUS status; - int logicalAddress; + HDMI_CEC_STATUS status = HDMI_CEC_IO_SUCCESS; + int logicalAddress = -1; - UT_LOG_DEBUG("Enter Logical Address to Remove: "); - scanf("Logical Address: %d", &logicalAddress); + UT_LOG_MENU_INFO("Enter Logical Address to Remove: "); + scanf("%d", &logicalAddress); + + UT_LOG_INFO("Calling HdmiCecRemoveLogicalAddress(IN: handle: [0x%0X], IN: logicalAddress: [%d])", gHandle, logicalAddress); // Invoke the API HdmiCecRemoveLogicalAddress status = HdmiCecRemoveLogicalAddress(gHandle, logicalAddress); - UT_LOG_DEBUG("Invoking HdmiCecRemoveLogicalAddress with handle: %d and logicalAddress: %d", gHandle, logicalAddress); - // UT_ASSERT_EQUAL(status, HDMI_CEC_IO_SUCCESS); - if (status != HDMI_CEC_IO_SUCCESS) + + if (status == HDMI_CEC_IO_SUCCESS) + { + UT_LOG_INFO("HdmiCecRemoveLogicalAddress successful logicalAddress: [%d]", logicalAddress); + } + else { - UT_LOG_ERROR("HdmiCecRemoveLogicalAddress failed with status: %d\n", status); + UT_LOG_ERROR("HdmiCecRemoveLogicalAddress failed (IN: handle: [0x%0X], IN: logicalAddress: [%d], OUT: status: [%d])", gHandle, logicalAddress, status); } UT_LOG_INFO("Out %s\n", __FUNCTION__); } - /** * @brief Test to close the HDMI CEC device. * * This test provides a scope to close the created HDMI CEC handle. * * **Test Group ID:** 02@n -* +* * **Test Case ID:** 08@n * * **Pre-Conditions:** @n @@ -454,16 +576,26 @@ void test_l2_hdmi_cec_sink_hal_Close(void) UT_LOG_INFO("In %s [%02d%03d]\n", __FUNCTION__, gTestGroup, gTestID); - // Step 1: Call the pre-requisite API HdmiCecOpen() - UT_LOG_DEBUG("Invoking HdmiCecOpen with valid handle"); + // Step 1: Log the pre-requisite action + UT_LOG_INFO("Calling HdmiCecClose(IN: handle: [0x%0X])", gHandle); + + // Step 2: Call the API to close the HDMI CEC handle status = HdmiCecClose(gHandle); - //UT_ASSERT_EQUAL_FATAL(status, HDMI_CEC_IO_SUCCESS); - //UT_ASSERT_NOT_EQUAL_FATAL(gHandle, 0); + // Step 3: Check if the close operation was successful + if (status == HDMI_CEC_IO_SUCCESS) + { + UT_LOG_INFO("HdmiCecClose successful (OUT: status: [%d])", status); + } + else + { + UT_LOG_ERROR("HdmiCecClose failed (IN: handle: [0x%0X]) status: [%d]", gHandle, status); + } + + // Step 4: Log the end of the function UT_LOG_INFO("Out %s\n", __FUNCTION__); } - static UT_test_suite_t * pSuite = NULL; /** From da92d35bc3b9f9914cbd32ca38b27d7e29f71f7e Mon Sep 17 00:00:00 2001 From: srinivasgtl <71806084+srinivasgtl@users.noreply.github.com> Date: Wed, 18 Sep 2024 20:17:21 +0100 Subject: [PATCH 19/40] gh #44 updated with assert and other logging mechanism changes --- src/test_l3_hdmi_cec_sink_driver.c | 128 ++++++++++++++--------------- 1 file changed, 62 insertions(+), 66 deletions(-) diff --git a/src/test_l3_hdmi_cec_sink_driver.c b/src/test_l3_hdmi_cec_sink_driver.c index 8cf77e3..b995637 100644 --- a/src/test_l3_hdmi_cec_sink_driver.c +++ b/src/test_l3_hdmi_cec_sink_driver.c @@ -115,6 +115,27 @@ CecCommandMap cecCommandTable[] = { // Add more commands as needed }; +/* cecError_t */ +const static ut_control_keyStringMapping_t cecError_mapTable [] = { + {"HDMI_CEC_IO_SUCCESS", (int32_t)HDMI_CEC_IO_SUCCESS} + {"HDMI_CEC_IO_SENT_AND_ACKD", (int32_t)HDMI_CEC_IO_SENT_AND_ACKD}, + {"HDMI_CEC_IO_SENT_BUT_NOT_ACKD", (int32_t)HDMI_CEC_IO_SENT_BUT_NOT_ACKD}, + {"HDMI_CEC_IO_SENT_FAILED", (int32_t)HDMI_CEC_IO_SENT_FAILED}, + {"HDMI_CEC_IO_NOT_OPENED", (int32_t)HDMI_CEC_IO_NOT_OPENED}, + {"HDMI_CEC_IO_INVALID_ARGUMENT", (int32_t)HDMI_CEC_IO_INVALID_ARGUMENT}, + {"HDMI_CEC_IO_LOGICALADDRESS_UNAVAILABLE", (int32_t)HDMI_CEC_IO_LOGICALADDRESS_UNAVAILABLE}, + {"HDMI_CEC_IO_GENERAL_ERROR", (int32_t)HDMI_CEC_IO_GENERAL_ERROR}, + {"HDMI_CEC_IO_ALREADY_OPEN", (int32_t)HDMI_CEC_IO_ALREADY_OPEN}, + {"HDMI_CEC_IO_ALREADY_REMOVED", (int32_t)HDMI_CEC_IO_ALREADY_REMOVED}, + {"HDMI_CEC_IO_INVALID_OUTPUT", (int32_t)HDMI_CEC_IO_INVALID_OUTPUT}, + {"HDMI_CEC_IO_INVALID_HANDLE", (int32_t)HDMI_CEC_IO_INVALID_HANDLE}, + {"HDMI_CEC_IO_OPERATION_NOT_SUPPORTED", (int32_t)HDMI_CEC_IO_OPERATION_NOT_SUPPORTED}, + {"HDMI_CEC_IO_NOT_ADDED", (int32_t)HDMI_CEC_IO_NOT_ADDED}, + {"HDMI_CEC_IO_MAX", (int32_t)HDMI_CEC_IO_MAX} + { NULL, -1 } +}; + + /** * @brief CEC Command with data size mapping function. * @@ -216,18 +237,14 @@ void test_l3_hdmi_cec_sink_hal_Init(void) // Step 1: Call HdmiCecOpen() UT_LOG_INFO("Calling HdmiCecOpen(IN:gHandle[0x%0X])",&gHandle); status = HdmiCecOpen(&gHandle); - if ((status != HDMI_CEC_IO_SUCCESS) || (gHandle == NULL)) - { - UT_LOG_ERROR("Failed to Invoke HdmiCecOpen()"); - } + UT_LOG_INFO("Result HdmiCecSetRxCallback() cecError:[%s]",UT_ControlGetMapString(cecError_mapTable,status)); + assert(status == HDMI_CEC_IO_SUCCESS); // Step 2: Register the call back UT_LOG_INFO("Calling HdmiCecSetRxCallback(IN:handle[0x%0X],IN:cbfunc[0x%0X]",gHandle,onRxDataReceived); status = HdmiCecSetRxCallback(gHandle, onRxDataReceived,(void*)0xABABABAB); - if(status != HDMI_CEC_IO_SUCCESS) - { - UT_LOG_ERROR("Failed HdmiCecSetRxCallback(IN:handle[0x%0X],IN:cbfunc[0x%0X]) status:%d",gHandle,onRxDataReceived),status; - } + UT_LOG_INFO("Result HdmiCecSetRxCallback() cecError:[%s]",UT_ControlGetMapString(cecError_mapTable,status)); + assert(status == HDMI_CEC_IO_SUCCESS); UT_LOG_INFO("Out %s\n", __FUNCTION__); } @@ -261,20 +278,19 @@ void test_l3_hdmi_cec_sink_hal_AddLogicalAddress(void) UT_LOG_INFO("In %s [%02d%03d]\n", __FUNCTION__, gTestGroup, gTestID); HDMI_CEC_STATUS status = HDMI_CEC_IO_SUCCESS; + int logicalAddress = -1; UT_LOG_MENU_INFO("----------------------------------------------------------"); - UT_LOG_MENU_INFO("Enter Logical Address: "); + UT_LOG_MENU_INFO("\t \tEnter Logical Address: "); + UT_LOG_MENU_INFO("----------------------------------------------------------"); scanf("%d", &logicalAddress); /* Check that logical address should be valid one */ UT_LOG_INFO("Calling HdmiCecAddLogicalAddress(IN:handle:[0x%0X], IN:logicalAddress:[%d]",gHandle,logicalAddress); status = HdmiCecAddLogicalAddress(gHandle,logicalAddress ); - - if (status != HDMI_CEC_IO_SUCCESS) - { - UT_LOG_ERROR("Failed HdmiCecAddLogicalAddress (IN:handle:[0x%0X], IN:logicalAddress:[%d]), status[%d]",gHandle,logicalAddress,status); - } + UT_LOG_INFO("Failed HdmiCecAddLogicalAddress (IN:handle:[0x%0X], IN:logicalAddress:[%d]), status[%d]",gHandle,logicalAddress,UT_ControlGetMapString(cecError_mapTable,status)); + assert(status == HDMI_CEC_IO_SUCCESS); UT_LOG_INFO("Out %s\n", __FUNCTION__); } @@ -310,16 +326,9 @@ void test_l3_hdmi_cec_sink_hal_GetLogicalAddress(void) UT_LOG_INFO("Calling HdmiCecGetLogicalAddress(IN: handle: [0x%0X], OUT: logicalAddress: [])", gHandle); status = HdmiCecGetLogicalAddress(gHandle, &logicalAddress); - if (status == HDMI_CEC_IO_SUCCESS) - { - UT_LOG_INFO("HdmiCecGetLogicalAddress successful (OUT: logicalAddress: [%d])", logicalAddress); - } - else - { - UT_LOG_ERROR("HdmiCecGetLogicalAddress failed (IN: handle: [0x%0X], OUT: logicalAddress: [%d]), status: [%d])", gHandle, logicalAddress, status); - // Additional error handling can be added here if necessary - } - + UT_LOG_INFO("HdmiCecGetLogicalAddress failed (IN: handle: [0x%0X], OUT: logicalAddress: [%d]), status: [%d])", gHandle, logicalAddress, UT_ControlGetMapString(cecError_mapTable,status)); + assert(status == HDMI_CEC_IO_SUCCESS); +UT_ControlGetMapString(cecError_mapTable,status) UT_LOG_INFO("Out %s\n", __FUNCTION__); } @@ -358,13 +367,20 @@ void test_l3_hdmi_cec_sink_hal_TransmitHdmiCecCommand(void) { int expectedDataLength; // Reading inputs from the user or test framework - UT_LOG_MENU_INFO("Enter a valid Source Logical Address:"); + UT_LOG_MENU_INFO("----------------------------------------------------------"); + UT_LOG_MENU_INFO("\t \tEnter a valid Source Logical Address:"); + UT_LOG_MENU_INFO("----------------------------------------------------------"); scanf("%d", &sourceLogicalAddress); - UT_LOG_MENU_INFO("Enter a valid Destination Logical Address: "); + UT_LOG_MENU_INFO("----------------------------------------------------------"); + UT_LOG_MENU_INFO("\t \tEnter a valid Destination Logical Address: "); scanf("%d", &destinationLogicalAddress); + UT_LOG_MENU_INFO("----------------------------------------------------------"); - UT_LOG_MENU_INFO("Enter CEC Command (in hex): "); + + UT_LOG_MENU_INFO("----------------------------------------------------------"); + UT_LOG_MENU_INFO("\t \tEnter CEC Command (in hex): "); + UT_LOG_MENU_INFO("----------------------------------------------------------"); scanf("%x", &cecCommand); // Validate the CEC command and get the expected data length @@ -372,7 +388,9 @@ void test_l3_hdmi_cec_sink_hal_TransmitHdmiCecCommand(void) { // Command not found in the map, prompt the user for additional information UT_LOG_WARNING("CEC command 0x%02X is not recognized. It might be a vendor-specific command.", cecCommand); - UT_LOG_MENU_INFO("Please enter the number of data bytes for the CEC command: "); + UT_LOG_MENU_INFO("----------------------------------------------------------"); + UT_LOG_MENU_INFO("\t \tPlease enter the number of data bytes for the CEC command: "); + UT_LOG_MENU_INFO("----------------------------------------------------------"); scanf("%d", &expectedDataLength); commandName = "Vendor Specific Command"; @@ -383,7 +401,7 @@ void test_l3_hdmi_cec_sink_hal_TransmitHdmiCecCommand(void) { // If the command has data bytes, prompt for them if (expectedDataLength > 0) { for (int i = 0; i < expectedDataLength; i++) { - UT_LOG_MENU_INFO("Enter Databyte[%d] (in hex):", i); + UT_LOG_MENU_INFO("\t \tEnter Databyte[%d] (in hex):", i); scanf("%x", &buf[i + 2]); // +2 to account for the first two bytes } } @@ -402,13 +420,9 @@ void test_l3_hdmi_cec_sink_hal_TransmitHdmiCecCommand(void) { // Assume HdmiCecTx is a function to send the CEC command int status = HdmiCecTx(gHandle, buf, len, &result); + UT_LOG_INFO("HdmiCecTx failed (IN: handle: [0x%0X], IN: length: [%d], result: [%d], status:[%d])", gHandle, len, result, UT_ControlGetMapString(cecError_mapTable,status)); - // Logging the result of the transmission - if ((result == HDMI_CEC_IO_SENT_BUT_NOT_ACKD) && (status == HDMI_CEC_IO_SUCCESS)) { - UT_LOG_INFO("HdmiCecTx successful (OUT: result: [%d])", result); - } else { - UT_LOG_ERROR("HdmiCecTx failed (IN: handle: [0x%0X], IN: length: [%d], result: [%d], status:[%d])", gHandle, len, result, status); - } + assert((result == HDMI_CEC_IO_SENT_BUT_NOT_ACKD) && (status == HDMI_CEC_IO_SUCCESS)) // Optional delay after sending the command sleep(5); @@ -448,6 +462,7 @@ void test_l3_hdmi_cec_sink_hal_ReceiveHdmiCecCommand(void) if (cbFlag != 1) { UT_LOG_ERROR("HdmiCecRx failed to receive data (IN: expected callback flag: [1], OUT: actual callback flag: [%d])", cbFlag); + assert(cbFlag == 1); } else { @@ -490,16 +505,9 @@ void test_l3_hdmi_cec_sink_hal_GetPhysicalAddress(void) UT_LOG_INFO("Calling HdmiCecGetPhysicalAddress(IN: handle: [0x%0X], OUT: physicalAddress: [uninitialized])", gHandle); - status = HdmiCecGetPhysicalAddress(gHandle, &physicalAddress); - - if (status == HDMI_CEC_IO_SUCCESS) - { - UT_LOG_INFO("HdmiCecGetPhysicalAddress successful (OUT: physicalAddress: [0x%04X])", physicalAddress); - } - else - { - UT_LOG_ERROR("HdmiCecGetPhysicalAddress failed (IN: handle: [0x%0X], physicalAddress: [%d]), status:[%d]", gHandle, physicalAddress, status); - } + status = HdmiCecGetPhysiicalAddress(gHandle, &physicalAddress); + UT_LOG_INFO("HdmiCecGetPhysicalAddress failed (IN: handle: [0x%0X], physicalAddress: [%d]), status:[%d]", gHandle, physicalAddress,UT_ControlGetMapString(cecError_mapTable,status)); + assert(status == HDMI_CEC_IO_SUCCESS); UT_LOG_INFO("Out %s\n", __FUNCTION__); } @@ -532,23 +540,19 @@ void test_l3_hdmi_cec_sink_hal_RemoveLogicalAddress(void) HDMI_CEC_STATUS status = HDMI_CEC_IO_SUCCESS; int logicalAddress = -1; - UT_LOG_MENU_INFO("Enter Logical Address to Remove: "); + UT_LOG_MENU_INFO("----------------------------------------------------------"); + UT_LOG_MENU_INFO("\t \tEnter Logical Address to Remove: "); + UT_LOG_MENU_INFO("----------------------------------------------------------"); + scanf("%d", &logicalAddress); UT_LOG_INFO("Calling HdmiCecRemoveLogicalAddress(IN: handle: [0x%0X], IN: logicalAddress: [%d])", gHandle, logicalAddress); // Invoke the API HdmiCecRemoveLogicalAddress status = HdmiCecRemoveLogicalAddress(gHandle, logicalAddress); - - if (status == HDMI_CEC_IO_SUCCESS) - { - UT_LOG_INFO("HdmiCecRemoveLogicalAddress successful logicalAddress: [%d]", logicalAddress); - } - else - { - UT_LOG_ERROR("HdmiCecRemoveLogicalAddress failed (IN: handle: [0x%0X], IN: logicalAddress: [%d], OUT: status: [%d])", gHandle, logicalAddress, status); - } - + UT_LOG_INFO("HdmiCecRemoveLogicalAddress failed (IN: handle: [0x%0X], IN: logicalAddress: [%d], OUT: status: [%d])", gHandle, logicalAddress, UT_ControlGetMapString(cecError_mapTable,status)); + assert(status == HDMI_CEC_IO_SUCCESS); + UT_LOG_INFO("Out %s\n", __FUNCTION__); } /** @@ -581,16 +585,8 @@ void test_l2_hdmi_cec_sink_hal_Close(void) // Step 2: Call the API to close the HDMI CEC handle status = HdmiCecClose(gHandle); - - // Step 3: Check if the close operation was successful - if (status == HDMI_CEC_IO_SUCCESS) - { - UT_LOG_INFO("HdmiCecClose successful (OUT: status: [%d])", status); - } - else - { - UT_LOG_ERROR("HdmiCecClose failed (IN: handle: [0x%0X]) status: [%d]", gHandle, status); - } + UT_LOG_INFO("HdmiCecClose failed (IN: handle: [0x%0X]) status: [%d]", gHandle, status); + assert(status == HDMI_CEC_IO_SUCCESS); // Step 4: Log the end of the function UT_LOG_INFO("Out %s\n", __FUNCTION__); From a839f6cf28329ac15eb6de375ba1b49f90c3ab38 Mon Sep 17 00:00:00 2001 From: srinivasgtl <71806084+srinivasgtl@users.noreply.github.com> Date: Thu, 21 Nov 2024 16:50:24 +0000 Subject: [PATCH 20/40] gh #44 Updates to hdmicec to fix compilation issues --- build.sh | 2 +- src/test_l3_hdmi_cec_sink_driver.c | 29 ++++++++++++++++------------- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/build.sh b/build.sh index 6b77cee..fa44309 100755 --- a/build.sh +++ b/build.sh @@ -28,7 +28,7 @@ NC="\e[39m" # When the major version changes in the ut-core, what that signals is that the testings will have to be upgraded to support that version # Therefore in that case it warns you but doesnt' chnage to that version, which could cause your tests to break. # Change this to upgrade your UT-Core Major versions. Non ABI Changes 1.x.x are supported, between major revisions -UT_PROJECT_MAJOR_VERSION="3." +UT_PROJECT_MAJOR_VERSION="4." # Clone the Unit Test Requirements TEST_REPO=git@github.com:rdkcentral/ut-core.git diff --git a/src/test_l3_hdmi_cec_sink_driver.c b/src/test_l3_hdmi_cec_sink_driver.c index b995637..bd825be 100644 --- a/src/test_l3_hdmi_cec_sink_driver.c +++ b/src/test_l3_hdmi_cec_sink_driver.c @@ -62,11 +62,15 @@ #include #include +#include +#include #include "hdmi_cec_driver.h" #define TIMEOUT 5 #define REPLY_TIMEOUT 5 +#define UT_LOG_MENU_INFO UT_LOG_INFO + static int gTestGroup = 3; static int gTestID = 1; static int gHandle = 0; @@ -117,7 +121,7 @@ CecCommandMap cecCommandTable[] = { /* cecError_t */ const static ut_control_keyStringMapping_t cecError_mapTable [] = { - {"HDMI_CEC_IO_SUCCESS", (int32_t)HDMI_CEC_IO_SUCCESS} + {"HDMI_CEC_IO_SUCCESS", (int32_t)HDMI_CEC_IO_SUCCESS}, {"HDMI_CEC_IO_SENT_AND_ACKD", (int32_t)HDMI_CEC_IO_SENT_AND_ACKD}, {"HDMI_CEC_IO_SENT_BUT_NOT_ACKD", (int32_t)HDMI_CEC_IO_SENT_BUT_NOT_ACKD}, {"HDMI_CEC_IO_SENT_FAILED", (int32_t)HDMI_CEC_IO_SENT_FAILED}, @@ -131,7 +135,7 @@ const static ut_control_keyStringMapping_t cecError_mapTable [] = { {"HDMI_CEC_IO_INVALID_HANDLE", (int32_t)HDMI_CEC_IO_INVALID_HANDLE}, {"HDMI_CEC_IO_OPERATION_NOT_SUPPORTED", (int32_t)HDMI_CEC_IO_OPERATION_NOT_SUPPORTED}, {"HDMI_CEC_IO_NOT_ADDED", (int32_t)HDMI_CEC_IO_NOT_ADDED}, - {"HDMI_CEC_IO_MAX", (int32_t)HDMI_CEC_IO_MAX} + {"HDMI_CEC_IO_MAX", (int32_t)HDMI_CEC_IO_MAX}, { NULL, -1 } }; @@ -237,13 +241,13 @@ void test_l3_hdmi_cec_sink_hal_Init(void) // Step 1: Call HdmiCecOpen() UT_LOG_INFO("Calling HdmiCecOpen(IN:gHandle[0x%0X])",&gHandle); status = HdmiCecOpen(&gHandle); - UT_LOG_INFO("Result HdmiCecSetRxCallback() cecError:[%s]",UT_ControlGetMapString(cecError_mapTable,status)); + UT_LOG_INFO("Result HdmiCecSetRxCallback() cecError:[%s]",UT_Control_GetMapString(cecError_mapTable,status)); assert(status == HDMI_CEC_IO_SUCCESS); // Step 2: Register the call back UT_LOG_INFO("Calling HdmiCecSetRxCallback(IN:handle[0x%0X],IN:cbfunc[0x%0X]",gHandle,onRxDataReceived); status = HdmiCecSetRxCallback(gHandle, onRxDataReceived,(void*)0xABABABAB); - UT_LOG_INFO("Result HdmiCecSetRxCallback() cecError:[%s]",UT_ControlGetMapString(cecError_mapTable,status)); + UT_LOG_INFO("Result HdmiCecSetRxCallback() cecError:[%s]",UT_Control_GetMapString(cecError_mapTable,status)); assert(status == HDMI_CEC_IO_SUCCESS); UT_LOG_INFO("Out %s\n", __FUNCTION__); @@ -289,7 +293,7 @@ void test_l3_hdmi_cec_sink_hal_AddLogicalAddress(void) /* Check that logical address should be valid one */ UT_LOG_INFO("Calling HdmiCecAddLogicalAddress(IN:handle:[0x%0X], IN:logicalAddress:[%d]",gHandle,logicalAddress); status = HdmiCecAddLogicalAddress(gHandle,logicalAddress ); - UT_LOG_INFO("Failed HdmiCecAddLogicalAddress (IN:handle:[0x%0X], IN:logicalAddress:[%d]), status[%d]",gHandle,logicalAddress,UT_ControlGetMapString(cecError_mapTable,status)); + UT_LOG_INFO("Failed HdmiCecAddLogicalAddress (IN:handle:[0x%0X], IN:logicalAddress:[%d]), status[%d]",gHandle,logicalAddress,UT_Control_GetMapString(cecError_mapTable,status)); assert(status == HDMI_CEC_IO_SUCCESS); UT_LOG_INFO("Out %s\n", __FUNCTION__); @@ -326,9 +330,8 @@ void test_l3_hdmi_cec_sink_hal_GetLogicalAddress(void) UT_LOG_INFO("Calling HdmiCecGetLogicalAddress(IN: handle: [0x%0X], OUT: logicalAddress: [])", gHandle); status = HdmiCecGetLogicalAddress(gHandle, &logicalAddress); - UT_LOG_INFO("HdmiCecGetLogicalAddress failed (IN: handle: [0x%0X], OUT: logicalAddress: [%d]), status: [%d])", gHandle, logicalAddress, UT_ControlGetMapString(cecError_mapTable,status)); + UT_LOG_INFO("HdmiCecGetLogicalAddress(IN: handle: [0x%0X], OUT: logicalAddress: [%d]), status: [%d])", gHandle, logicalAddress, UT_Control_GetMapString(cecError_mapTable,status)); assert(status == HDMI_CEC_IO_SUCCESS); -UT_ControlGetMapString(cecError_mapTable,status) UT_LOG_INFO("Out %s\n", __FUNCTION__); } @@ -420,9 +423,9 @@ void test_l3_hdmi_cec_sink_hal_TransmitHdmiCecCommand(void) { // Assume HdmiCecTx is a function to send the CEC command int status = HdmiCecTx(gHandle, buf, len, &result); - UT_LOG_INFO("HdmiCecTx failed (IN: handle: [0x%0X], IN: length: [%d], result: [%d], status:[%d])", gHandle, len, result, UT_ControlGetMapString(cecError_mapTable,status)); + UT_LOG_INFO("HdmiCecTx(IN: handle: [0x%0X], IN: length: [%d], result: [%d], status:[%d])", gHandle, len, result, UT_Control_GetMapString(cecError_mapTable,status)); - assert((result == HDMI_CEC_IO_SENT_BUT_NOT_ACKD) && (status == HDMI_CEC_IO_SUCCESS)) + assert((result == HDMI_CEC_IO_SENT_BUT_NOT_ACKD) && (status == HDMI_CEC_IO_SUCCESS)); // Optional delay after sending the command sleep(5); @@ -505,8 +508,8 @@ void test_l3_hdmi_cec_sink_hal_GetPhysicalAddress(void) UT_LOG_INFO("Calling HdmiCecGetPhysicalAddress(IN: handle: [0x%0X], OUT: physicalAddress: [uninitialized])", gHandle); - status = HdmiCecGetPhysiicalAddress(gHandle, &physicalAddress); - UT_LOG_INFO("HdmiCecGetPhysicalAddress failed (IN: handle: [0x%0X], physicalAddress: [%d]), status:[%d]", gHandle, physicalAddress,UT_ControlGetMapString(cecError_mapTable,status)); + status = HdmiCecGetPhysicalAddress(gHandle, &physicalAddress); + UT_LOG_INFO("HdmiCecGetPhysicalAddress(IN: handle: [0x%0X], physicalAddress: [%d]), status:[%d]", gHandle, physicalAddress,UT_Control_GetMapString(cecError_mapTable,status)); assert(status == HDMI_CEC_IO_SUCCESS); UT_LOG_INFO("Out %s\n", __FUNCTION__); @@ -550,7 +553,7 @@ void test_l3_hdmi_cec_sink_hal_RemoveLogicalAddress(void) // Invoke the API HdmiCecRemoveLogicalAddress status = HdmiCecRemoveLogicalAddress(gHandle, logicalAddress); - UT_LOG_INFO("HdmiCecRemoveLogicalAddress failed (IN: handle: [0x%0X], IN: logicalAddress: [%d], OUT: status: [%d])", gHandle, logicalAddress, UT_ControlGetMapString(cecError_mapTable,status)); + UT_LOG_INFO("HdmiCecRemoveLogicalAddress(IN: handle: [0x%0X], IN: logicalAddress: [%d], OUT: status: [%d])", gHandle, logicalAddress, UT_Control_GetMapString(cecError_mapTable,status)); assert(status == HDMI_CEC_IO_SUCCESS); UT_LOG_INFO("Out %s\n", __FUNCTION__); @@ -585,7 +588,7 @@ void test_l2_hdmi_cec_sink_hal_Close(void) // Step 2: Call the API to close the HDMI CEC handle status = HdmiCecClose(gHandle); - UT_LOG_INFO("HdmiCecClose failed (IN: handle: [0x%0X]) status: [%d]", gHandle, status); + UT_LOG_INFO("HdmiCecClose(IN: handle: [0x%0X]) status: [%d]", gHandle, status); assert(status == HDMI_CEC_IO_SUCCESS); // Step 4: Log the end of the function From 797aca3ec9a3c3eb75e1f24ab0e3b5467ec5d2a4 Mon Sep 17 00:00:00 2001 From: srinivasgtl <71806084+srinivasgtl@users.noreply.github.com> Date: Sun, 24 Nov 2024 18:26:47 +0000 Subject: [PATCH 21/40] gh #44 adding cec commands and responses --- host/.lastlogin | 0 host/activate_venv.sh | 35 +++ host/install.sh | 170 +++++++++++ host/tests/classes/hdmiCEC.py | 272 ++++++++++++++++++ host/tests/classes/hdmiCEC_testConfig.yml | 66 +++++ host/tests/configs/deviceConfig.yml | 42 +++ host/tests/configs/example_rack_config.yml | 96 +++++++ .../hdmiCEC_L3_Tests/hdmiCECHelperClass.py | 149 ++++++++++ .../hdmiCEC_L3_Tests/hdmiCEC_L3_testSetup.yml | 35 +++ ...nsmitSingleStandbyCommandandValidateAck.py | 113 ++++++++ src/test_l3_hdmi_cec_sink_driver.c | 226 ++++++++++++++- 11 files changed, 1193 insertions(+), 11 deletions(-) create mode 100644 host/.lastlogin create mode 100644 host/activate_venv.sh create mode 100755 host/install.sh create mode 100644 host/tests/classes/hdmiCEC.py create mode 100644 host/tests/classes/hdmiCEC_testConfig.yml create mode 100644 host/tests/configs/deviceConfig.yml create mode 100644 host/tests/configs/example_rack_config.yml create mode 100755 host/tests/hdmiCEC_L3_Tests/hdmiCECHelperClass.py create mode 100755 host/tests/hdmiCEC_L3_Tests/hdmiCEC_L3_testSetup.yml create mode 100755 host/tests/hdmiCEC_L3_Tests/hdmiCEC_test01_TransmitSingleStandbyCommandandValidateAck.py diff --git a/host/.lastlogin b/host/.lastlogin new file mode 100644 index 0000000..e69de29 diff --git a/host/activate_venv.sh b/host/activate_venv.sh new file mode 100644 index 0000000..d911224 --- /dev/null +++ b/host/activate_venv.sh @@ -0,0 +1,35 @@ +#!/usr/bin/env bash +#** ***************************************************************************** +# * +# * If not stated otherwise in this file or this component's LICENSE file the +# * following copyright and licenses apply: +# * +# * Copyright 2023 RDK Management +# * +# * Licensed under the Apache License, Version 2.0 (the "License"); +# * you may not use this file except in compliance with the License. +# * You may obtain a copy of the License at +# * +# * +# http://www.apache.org/licenses/LICENSE-2.0 +# * +# * Unless required by applicable law or agreed to in writing, software +# * distributed under the License is distributed on an "AS IS" BASIS, +# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# * See the License for the specific language governing permissions and +# * limitations under the License. +# * +#* ****************************************************************************** +MY_PATH="$(realpath ${BASH_SOURCE[0]})" +MY_DIR="$(dirname ${MY_PATH})" +VENV_DIR="${MY_DIR}/python_venv" # Default virtual environment directory name + +# Check if the script is sourced +if [[ "${BASH_SOURCE[0]}" != "${0}" ]]; then + source "$VENV_DIR"/bin/activate + echo "Virtual environment '$VENV_DIR' activated." +else + echo "The script must be sourced. 'source ./activate_venv.sh' or '. ./activate_venv.sh'" + echo "Once activated you can deactivate with 'deactivate' command" +fi + diff --git a/host/install.sh b/host/install.sh new file mode 100755 index 0000000..9a5ff8a --- /dev/null +++ b/host/install.sh @@ -0,0 +1,170 @@ +#!/usr/bin/env bash +#** ***************************************************************************** +# * +# * If not stated otherwise in this file or this component's LICENSE file the +# * following copyright and licenses apply: +# * +# * Copyright 2023 RDK Management +# * +# * Licensed under the Apache License, Version 2.0 (the "License"); +# * you may not use this file except in compliance with the License. +# * You may obtain a copy of the License at +# * +# * +# http://www.apache.org/licenses/LICENSE-2.0 +# * +# * Unless required by applicable law or agreed to in writing, software +# * distributed under the License is distributed on an "AS IS" BASIS, +# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# * See the License for the specific language governing permissions and +# * limitations under the License. +# * +#* ****************************************************************************** +MY_PATH="$(realpath ${BASH_SOURCE[0]})" +MY_DIR="$(dirname ${MY_PATH})" +TESTS_DIR="${MY_DIR}/tests" +RAFT_DIR="${TESTS_DIR}/raft" +PLUGINS_FRAMEWORK_DIR="${RAFT_DIR}/framework/plugins" +VENV_NAME="python_venv" +VENV_DIR="${MY_DIR}/${VENV_NAME}" # Default virtual environment directory name + +mkdir -p ${TESTS_DIR} + +NO_COLOR="\e[0m" +RED="\e[0;31m" +CYAN="\e[0;36m" +YELLOW="\e[1;33m" +GREEN="\e[0;32m" +RED_BOLD="\e[1;31m" +BLUE_BOLD="\e[1;34m" +YELLOW_BOLD="\e[1;33m" + +set -e # return on errors + +function DUMP_VAR() +{ + local var_name="$1" + local var_content="${!var_name}" + echo -e ${CYAN}$var_name:[${var_content}]${NO_COLOR} +} +function ECHO() +{ + echo -e "$*" +} + +function DEBUG() +{ + # if set -x is in use debug messages are useless as whole stript will be shown + if [[ "$-" =~ "x" ]]; then + return + fi + if [[ "${DEBUG_FLAG}" == "1" ]];then + ECHO "${BLUE_BOLD}DEBUG: ${CYAN}$*${NO_COLOR}" > /dev/stderr + fi +} + +function INFO() +{ + ECHO "${GREEN}$*${NO_COLOR}" +} + +function WARNING() +{ + ECHO "${YELLOW_BOLD}Warning: ${YELLOW}$*${NO_COLOR}" > /dev/stderr +} + +function ERROR() +{ + ECHO "${RED_BOLD}ERROR: ${RED}$*${NO_COLOR}" + exit 1 +} + +function install_pip_requirements() +{ + local requirements_file="$1" + + if [ ! -f ${requirements_file} ]; then + WARNING "No ${requirements_file} found" + return # Exit the function if the file exists + fi + + INFO "install_pip_requirements( ${requirements_file} ):" + if pip install -r "$requirements_file" >/dev/null 2>&1; then + INFO "pip install completed" + else + ERROR "process_and_update_sha(): pip install failed." + return 1 # Exit the function with error code + fi +} + +function clone_repo() +{ + # Requirment it to clone only if not present. + local repo_url="$1" + local path="$2" + local version="$3" + local message="$4" + + if [[ -z "${repo_url}" ]]; then + ERROR "clone_repo:A url for a repository must be passed to the clone repo function" + fi + if [[ -z "${version}" ]]; then + ERROR "clone_repo:Version not specified" + fi + if [[ ! -z "${path}" ]]; then + if [[ ! -d "${path}" ]]; then + INFO "git clone ${repo_url} @ ${version} ${CYAN}${message}${NO_COLOR}" + git clone ${repo_url} "${path}" > /dev/null 2>&1 + cd ${path} + #INFO "git checkout ${version}" + git checkout ${version} > /dev/null 2>&1 + cd - > /dev/null + fi + fi +} + +function setup_and_enable_venv() +{ + # Check if virtual environment directory exists, create if not + if [[ ! -d "$VENV_DIR" ]]; then + ECHO "Creating Virtual environment ${YELLOW}'$VENV_NAME'${NO_COLOR}" + python3 -m venv "$VENV_DIR" + ECHO "Virtual environment created." + fi + + # Request that the user re-run this script from the vendor + # Check if already inside a virtual environment + if [[ ! -n "$VIRTUAL_ENV" ]]; then + # Activate virtual environment + ECHO "please source & re-run ${YELLOW}install.sh${NO_COLOR} to ensure setup:" + ECHO ${YELLOW}"source ./activate_venv.sh"${NO_COLOR} + exit 1 # Exit the function if already in a venv + fi + + if [ -f "${VENV_DIR}/.installed" ]; then + return + fi + + # Upgrade pip + #python3 -m pip install --upgrade pip + #echo "pip upgraded within the virtual environment." + + touch ${VENV_DIR}/.installed +} + + +## Setup and start venv +setup_and_enable_venv + +### Clone required repos ### +# Setup raft +clone_repo git@github.com:rdkcentral/python_raft.git "${RAFT_DIR}" "1.1.1" "in ./raft" +install_pip_requirements "${RAFT_DIR}"/requirements.txt + +# Setup ut-raft +clone_repo git@github.com:rdkcentral/ut-raft.git "${PLUGINS_FRAMEWORK_DIR}/ut_raft" 2.0.0 "in ./raft/framework/plugins" +install_pip_requirements "${PLUGINS_FRAMEWORK_DIR}"/ut_raft/requirements.txt + +## Install your own sub git repo's in here as required +# +INFO "Install Complete" diff --git a/host/tests/classes/hdmiCEC.py b/host/tests/classes/hdmiCEC.py new file mode 100644 index 0000000..b61f3ee --- /dev/null +++ b/host/tests/classes/hdmiCEC.py @@ -0,0 +1,272 @@ +#!/usr/bin/env python3 +#** ***************************************************************************** +# * +# * If not stated otherwise in this file or this component's LICENSE file the +# * following copyright and licenses apply: +# * +# * Copyright 2024 RDK Management +# * +# * Licensed under the Apache License, Version 2.0 (the "License"); +# * you may not use this file except in compliance with the License. +# * You may obtain a copy of the License at +# * +# * +# http://www.apache.org/licenses/LICENSE-2.0 +# * +# * Unless required by applicable law or agreed to in writing, software +# * distributed under the License is distributed on an "AS IS" BASIS, +# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# * See the License for the specific language governing permissions and +# * limitations under the License. +# * +#* ****************************************************************************** + +import subprocess +import os +import sys +from enum import Enum, auto +import re +import yaml + +# Add parent directory to the system path for module imports +dir_path = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(dir_path, "../")) + +from raft.framework.plugins.ut_raft.configRead import ConfigRead +from raft.framework.plugins.ut_raft.utSuiteNavigator import UTSuiteNavigatorClass +from raft.framework.plugins.ut_raft.interactiveShell import InteractiveShell +from raft.framework.plugins.ut_raft.utBaseUtils import utBaseUtils + +class hdmiCECClass(): + """ + HDMI CEC Class. + + This module provides common functionalities and extensions for the HDMI CEC Module. + """ + + def __init__(self, moduleConfigProfileFile :str, session=None, targetWorkspace="/tmp"): + """ + Initializes the HDMI CEC Class instance with configuration settings. + + Args: + moduleConfigProfileFile (str): Path to the device profile configuration file. + session: Optional; session object for the user interface. + + Returns: + None + """ + self.moduleName = "hdmiCEC" + self.testConfigFile = os:.path.join(dir_path, "hdmiCEC_testConfig.yml") + self.testSuite = "L3 hdmicec - Sink" + + # Load configurations for device profile and menu + self.moduleConfigProfile = ConfigRead( moduleConfigProfileFile , self.moduleName) + self.testConfig = ConfigRead(self.testConfigFile, self.moduleName) + self.testConfig.test.execute = os.path.join(targetWorkspace, self.testConfig.test.execute) + self.utMenu = UTSuiteNavigatorClass(self.testConfig, None, session) + self.testSession = session + self.utils = utBaseUtils() + self.ports = self.moduleConfigProfile.fields.get("Ports") + + for artifact in self.testConfig.test.artifacts: + filesPath = os.path.join(dir_path, artifact) + self.utils.rsync(self.testSession, filesPath, targetWorkspace) + + # Start the user interface menu + self.utMenu.start() + + def searchPattern(self, haystack, pattern): + """ + Searches for the first occurrence of a specified pattern in the provided string. + + Args: + haystack (str): The string to be searched. + pattern (str): The regular expression pattern to search for. + + Returns: + str: The first capturing group of the match if found; otherwise, None. + + Notes: + - The pattern should contain at least one capturing group (parentheses). + - If no match is found, None is returned. + """ + match = re.search(pattern, haystack) + if match: + return match.group(1) + return None + + def initialise(self): + """ + Initializes the HDMI CEC module for sink. + + Args: + None. + + Returns: + None + """ + result = self.utMenu.select( self.testSuite, "L3_Init_HdmiCec") + + def terminate(self): + """ + Terminates the hdmi cec module + + Args: + None + + Returns: + None + """ + result = self.utMenu.select(self.testSuite, "L3_Close_HdmiCec_Sink") + + def addLogicalAddress(self, logicalAddress:int): + """ + Adding the logical address of a specific device. + For now Sink to support only the logical address 0. + + Args: + logicalAddress (int): The Logical address of the DUT. This will be fixed to zero for a sink device for now. + + Returns: + None + """ + promptWithAnswers = [ + { + "query_type": "direct", + "query": "Enter Logical Address:", + "input": str(logicalAddress) + } + ] + + + result = self.utMenu.select(self.testSuite, "L3_AddLogicalAddress", promptWithAnswers) + + def removeLogicalAddress(self, logicalAddress:int): + """ + Remove logical address. + + Args: + logicalAddress (int): The Logical address of the DUT that should be removed. + + Returns: + None + """ + promptWithAnswers = [ + { + "query_type": "direct", + "query": "Enter Logical Address to Remove:", + "input": str(logicalAddress) + } + ] + + result = self.utMenu.select(self.testSuite, "L3_RemoveLogicalAddressHdmiCec_Sink", promptWithAnswers) + + + + def getLogicalAddress(self): + """ + Retrieves the Logical Address of the DUT. + + Args: + None. + + Returns: + int: Logical address of the device. + """ + result = self.utMenu.select( self.testSuite, "L3_GetLogicalAddress") + connectionStatusPattern = r"HdmiCecGetLogicalAddress\(IN: handle: [.*\], OUT: logicalAddress: [.*\]), status: [.*\])" + logicalAddress = self.searchPattern(result, connectionStatusPattern) + + return logicalAddress + + + def getPhysicalAddress(self): + """ + Retrieve the Physical Address of the DUT. + + Args: + None. + + Returns: + int: Physical Address of the DUT. + """ + + + result = self.utMenu.select( self.testSuite, "L3_GetPhyiscalAddress") + typeStatusPattern = r"HdmiCecGetPhysicalAddress\(IN: handle: [.*\], physicalAddress: [.*\]), status:[.*\]" + physicalAddress = self.searchPattern(result, typeStatusPattern) + + return physicalAddress + + def cecTransmitCmd(self, sourceLogicalAddress:int, destLogicalAddress:int, cecCommand:int, cecData:list=None): + """ + Transmit/Broadcast the CEC command and data to the respective destination. + + Args: + None. + + Returns: + None + """ + + promptWithAnswers = [ + { + "query_type": "direct", + "query": "Enter a valid Source Logical Address:", + "input": str(sourceLogicalAddress) + }, + { + "query_type": "direct", + "query": "Enter a valid Destination Logical Address:", + "input": str(destLogicalAddress) + }, + { + "query_type": "direct", + "query": "Enter CEC Command:", + "input": str(cecCommand) + }, + ] + + if cecData: + for byte in cecData: + promptWithAnswers.append( + { + "query_type": "direct", + "query": "Enter Databyte", + "input": str(byte) + }) + + result = self.utMenu.select( self.testSuite, "L3_TransmitCecCommand",promptWithAnswers) + + + def __del__(self): + """ + Cleans up and de-initializes the hdmi cec helper by stopping the test menu. + + Args: + None. + + Returns: + None + """ + self.utMenu.stop() + +# Test and example usage code +if __name__ == '__main__': + + shell = InteractiveShell() + shell.open() + + platformProfile = dir_path + "/../../../profiles/sink/Sink_AudioSettings.yaml" + # test the class assuming that it's optional + test = dsAudioClass(platformProfile, shell) + + test.initialise() + ports = test.getSupportedPorts() + + test.enablePort(ports[0][0], ports[0][1]) + test.disablePort(ports[0][0], ports[0][1]) + + test.terminate() + + shell.close() diff --git a/host/tests/classes/hdmiCEC_testConfig.yml b/host/tests/classes/hdmiCEC_testConfig.yml new file mode 100644 index 0000000..baa8d23 --- /dev/null +++ b/host/tests/classes/hdmiCEC_testConfig.yml @@ -0,0 +1,66 @@ +#** ***************************************************************************** +# * +# * If not stated otherwise in this file or this component's LICENSE file the +# * following copyright and licenses apply: +# * +# * Copyright 2024 RDK Management +# * +# * Licensed under the Apache License, Version 2.0 (the "License"); +# * you may not use this file except in compliance with the License. +# * You may obtain a copy of the License at +# * +# * +# http://www.apache.org/licenses/LICENSE-2.0 +# * +# * Unless required by applicable law or agreed to in writing, software +# * distributed under the License is distributed on an "AS IS" BASIS, +# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# * See the License for the specific language governing permissions and +# * limitations under the License. +# * +#* ****************************************************************************** +hdmiCEC: + description: "hdmi CEC testing profile / menu system for UT" + test: + artifacts: + #List of artifacts folders, test class copies the content of folder to the target device workspace + - "../../../bin/" + # exectute command, this will appended with the target device workspace path + execute: "run.sh" + type: UT-C # C (UT-C Cunit) / C++ (UT-G (g++ ut-core gtest backend)) + suites: + 0: + name: "L1 hdmicec" + tests: + - "open_Positive" + - "open_negative" + - "close_Positive" + - "close_negative" + - "getPhysicalAddress_Positive" + - "getPhysicalAddress_negative" + - "setRxCallback_Positive" + - "setRxCallback_negative" + - "addLogicalAddress_Positive" + - "addLogicalAddress_negative" + - "removeLogicalAddress_Positive" + - "removeLogicalAddress_negative" + 1: + name: "L2 hdmicec - Sink" + tests: + - "L2_GetDefaultLogicalAddress_Sink" + - "L2_AddAndGetLogicalAddress_Sink" + - "L2_RemoveLogicalAddress_Sink" + - "L2_BroadcastHdmiCecCommand_Sink" + - "L2_VerifyPhysicalAddress_Sink" + - "L2_TransmitCECCommand_Sink" + 2: + name: "L3 hdmicec - Sink" + tests: + - "L3_Init_HdmiCec" + - "L3_AddLogicalAddress" + - "L3_GetLogicalAddress" + - "L3_TransmitCecCommand" + - "L3_ReceiveCecCommand" + - "L3_GetPhyiscalAddress" + - "L3_RemoveLogicalAddressHdmiCec_Sink" + - "L3_Close_HdmiCec_Sink" diff --git a/host/tests/configs/deviceConfig.yml b/host/tests/configs/deviceConfig.yml new file mode 100644 index 0000000..b7dafee --- /dev/null +++ b/host/tests/configs/deviceConfig.yml @@ -0,0 +1,42 @@ +#** ***************************************************************************** +# * +# * If not stated otherwise in this file or this component's LICENSE file the +# * following copyright and licenses apply: +# * +# * Copyright 2023 RDK Management +# * +# * Licensed under the Apache License, Version 2.0 (the "License"); +# * you may not use this file except in compliance with the License. +# * You may obtain a copy of the License at +# * +# * +# http://www.apache.org/licenses/LICENSE-2.0 +# * +# * Unless required by applicable law or agreed to in writing, software +# * distributed under the License is distributed on an "AS IS" BASIS, +# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# * See the License for the specific language governing permissions and +# * limitations under the License. +# * +#* ****************************************************************************** + +# The information defined in this config is consistent across all devices of a type. + +deviceConfig: + cpe1: + platform: "element" + model: "uk" + soc_vendor: "amlogic" + target_directory: "/tmp/" # Target Directory on device + prompt: "" # Prompt string on console + test: + #TODO: Use the single profile file which contains all details (ds, hdmi, etc) + profile: "../../../../profiles/sink/sink_hdmiCEC_test.yaml" + streams_download_url: "" #URL path from which the streams are downloaded to the device + cpe2: + platform: "test" + model: "test" + vendor: "test" + target_directory: "/tmp" + profile: "" + test: diff --git a/host/tests/configs/example_rack_config.yml b/host/tests/configs/example_rack_config.yml new file mode 100644 index 0000000..815a440 --- /dev/null +++ b/host/tests/configs/example_rack_config.yml @@ -0,0 +1,96 @@ +#** ***************************************************************************** +# * +# * If not stated otherwise in this file or this component's LICENSE file the +# * following copyright and licenses apply: +# * +# * Copyright 2023 RDK Management +# * +# * Licensed under the Apache License, Version 2.0 (the "License"); +# * you may not use this file except in compliance with the License. +# * You may obtain a copy of the License at +# * +# * +# http://www.apache.org/licenses/LICENSE-2.0 +# * +# * Unless required by applicable law or agreed to in writing, software +# * distributed under the License is distributed on an "AS IS" BASIS, +# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# * See the License for the specific language governing permissions and +# * limitations under the License. +# * +#* ****************************************************************************** + +# This config file creates your environment, defaults are setup internally unless otherwise overridden. +# you will need at least 1 rack and 1 slot to operate. +# each module e.g. console options, will be off by default unless otherwise stated + +# Depreciated +# slotx: address: IP of device while running locally, replaced with slotx: ip +# slotx: deviceConsole: IP of device while running locally, replaced with slotx: devices + +# This example is taken from https://github.com/rdkcentral/python_raft/blob/master/examples/configs/example_rack_config.yml +# For information on python_raft please refer to : https://github.com/rdkcentral/python_raft/blob/master/README.md + +# Data that is global to all tests. +globalConfig: + includes: + # [ includes: ] + # [ deviceConfig: "required.yml file" ] + deviceConfig: "example_device_config.yml" + capture: + # [capture: optional] + # [ocrEnginePath: "/usr/bin/tesseract"] # "C:\\Program Files\\Tesseract-OCR\\tesseract.exe" (For Windows) - tesseract binary + # [resolution: "1080p"] - Capture resolution + # [input: 0] - which input is connected to the video path + # Note: Video capture will not be installed unless screenRegions: is defined in deviceConfig: + ocrEnginePath: "/usr/bin/tesseract" # "C:\\Program Files\\Tesseract-OCR\\tesseract.exe" (For Windows) + resolution: "1080p" + input: 0 + cec-adaptor: + type: cec-client + adaptor: /dev/ttyACM0 + local: + log: # log for each slot + directory: "./logs" + delimiter: "/" + +# Define racks, their slots and the devices in them. These are not always physical racks and slots. +rackConfig: + rack1: + name: "rack1" + description: "example config at my desk" + slot1: + # [ name: "required", description: "optional"] + name: "slot1" + devices: + # [ devices: ] + # [ type: "serial": port: "COM7" baudRate: "(default)115200" dataBits: "optional(8)" stopBits: "optional(1)" parity: "optional(None)" FlowControl: "optional(None)" ] + # [ type: "ssh": port: 22 username: "test" password: "test" ] + # [ type: "telnet": port: 23 username: "test" password: "test" ] + - dut: + ip: "127.0.0.1" # IP Address of the ADA Hub + description: "local PC" + platform: "PC" + consoles: + - default: + type: "ssh" + port: 22 + username: "srr07" + ip: "127.0.0.1" #IP address + password: '1234' + - ssh_player: + type: "ssh" + port: 22 + username: "srr07" + ip: "127.0.0.1" #IP address + password: '1234' + - ssh_hal_test: + type: "ssh" + port: 22 + username: "srr07" + ip: "127.0.0.1" #IP address + password: '1234' + outbound: + download_url: "http://localhost:8000/" # download location for the CPE device + httpProxy: # Local Proxy if required + workspaceDirectory: './logs/workspace' # Local working directory diff --git a/host/tests/hdmiCEC_L3_Tests/hdmiCECHelperClass.py b/host/tests/hdmiCEC_L3_Tests/hdmiCECHelperClass.py new file mode 100755 index 0000000..a95ded8 --- /dev/null +++ b/host/tests/hdmiCEC_L3_Tests/hdmiCECHelperClass.py @@ -0,0 +1,149 @@ +#!/usr/bin/env python3 +#** ***************************************************************************** +# * +# * If not stated otherwise in this file or this component's LICENSE file the +# * following copyright and licenses apply: +# * +# * Copyright 2024 RDK Management +# * +# * Licensed under the Apache License, Version 2.0 (the "License"); +# * you may not use this file except in compliance with the License. +# * You may obtain a copy of the License at +# * +# * +# http://www.apache.org/licenses/LICENSE-2.0 +# * +# * Unless required by applicable law or agreed to in writing, software +# * distributed under the License is distributed on an "AS IS" BASIS, +# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# * See the License for the specific language governing permissions and +# * limitations under the License. +# * +#* ****************************************************************************** + +import os +import sys + +dir_path = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(dir_path, "../../")) + +from raft.framework.plugins.ut_raft.configRead import ConfigRead +from raft.framework.plugins.ut_raft.utUserResponse import utUserResponse +from raft.framework.plugins.ut_raft import utHelperClass +from raft.framework.core.logModule import logModule +from classes.hdmCEC import hdmiCECClass + +class hdmiCECHelperClass(utHelperClass): + + def __init__(self, testName:str, qcId:str, log:logModule=None ): + """ + Initializes the test class with test name, setup configuration, and sessions for the device. + + Args: + testName (str) : name of the test + qcId (str): QC ID of the test. + log (class, optional): Parent log class. Defaults to None. + """ + self.testName = "" + self.testSetupPath = os.path.join(dir_path, "hdmiCEC__L3_testSetup.yml") + self.moduleName = "hdmiCEC" + self.rackDevice = "dut" + + super().__init__(testName, qcId, log) + + # Load test setup configuration + self.testSetup = ConfigRead(self.testSetupPath, self.moduleName) + + # Open Sessions hal test + self.hal_session = self.dut.getConsoleSession("ssh_hal_test") + + deviceTestSetup = self.cpe.get("test") + + # Create user response Class + self.testUserResponse = utUserResponse() + + # Get path to device profile file + self.moduleConfigProfileFile = os.path.join(dir_path, deviceTestSetup.get("profile")) + + self.targetWorkspace = self.cpe.get("target_directory") + self.targetWorkspace = os.path.join(self.targetWorkspace, self.moduleName) + +# def testDownloadAssets(self): +# """ +# Downloads the test artifacts listed in the test setup configuration. +# +# This function retrieves the necessary files and saves them on the DUT. +# +# Args: +# None +# """ +# +# # List of streams with path +# self.testStreams = [] +# url = [] +# +# streamPaths = self.testSetup.get("assets").get("device").get(self.testName).get("streams") +# +# # Download test streams to device +# if streamPaths and self.streamDownloadURL: +# for streamPath in streamPaths: +# url.append(os.path.join(self.streamDownloadURL, streamPath)) +# self.testStreams.append(os.path.join(self.targetWorkspace, os.path.basename(streamPath))) +# self.downloadToDevice(url, self.targetWorkspace, self.rackDevice) + +# def testCleanAssets(self): +# """ +# Removes the downloaded assets and test streams from the DUT after test execution. +# +# Args: +# None +# """ +# self.deleteFromDevice(self.testStreams) +# + def testRunPrerequisites(self): + """ + Executes prerequisite commands listed in the test setup configuration file on the DUT. + + Args: + None + """ + + # Run commands as part of test prerequisites + test = self.testSetup.get("assets").get("device").get(self.testName) + cmds = test.get("execute") + if cmds is not None: + for cmd in cmds: + self.writeCommands(cmd) + + def testPrepareFunction(self): + """ + Prepares the environment and assets required for the test. + + This function: + - Downloads the required assets. + - Runs the prerequisite commands. + - Creates hdmiCEC + + Returns: + bool + """ + + + # Run Prerequisites listed in the test setup configuration file + self.testRunPrerequisites() + + # Create the hdmiCEC class + self.testhdmiCEC = hdmiCECClass(self.moduleConfigProfileFile, self.hal_session, self.targetWorkspace) + + return True + + def testEndFunction(self, powerOff=True): + # Clean the assets downloaded to the device + self.testCleanAssets() + + # Clean up the hdmiCEC instance + del self.testhdmiCEC + + def testExceptionCleanUp (self): + # Clean the assets downloaded to the device + self.testCleanAssets() diff --git a/host/tests/hdmiCEC_L3_Tests/hdmiCEC_L3_testSetup.yml b/host/tests/hdmiCEC_L3_Tests/hdmiCEC_L3_testSetup.yml new file mode 100755 index 0000000..bf903d3 --- /dev/null +++ b/host/tests/hdmiCEC_L3_Tests/hdmiCEC_L3_testSetup.yml @@ -0,0 +1,35 @@ +#** ***************************************************************************** +# * +# * If not stated otherwise in this file or this component's LICENSE file the +# * following copyright and licenses apply: +# * +# * Copyright 2024 RDK Management +# * +# * Licensed under the Apache License, Version 2.0 (the "License"); +# * you may not use this file except in compliance with the License. +# * You may obtain a copy of the License at +# * +# * +# http://www.apache.org/licenses/LICENSE-2.0 +# * +# * Unless required by applicable law or agreed to in writing, software +# * distributed under the License is distributed on an "AS IS" BASIS, +# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# * See the License for the specific language governing permissions and +# * limitations under the License. +# * +#* ****************************************************************************** + + +hdmiCEC: # Prefix must always exist + description: "hdmiCEC test setup" + assets: + device: + test01_TransmitSingleStandbyCommandandValidateAck: + <<: *defaults + test02_BroadcastStandbyCommand: + <<: *defaults + test03_TransmitOSDCommandandValidateAck: + <<: *defaults + test04_TransmitLargerOSDCommandRepeatedlyandValidate: + <<: *defaults diff --git a/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test01_TransmitSingleStandbyCommandandValidateAck.py b/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test01_TransmitSingleStandbyCommandandValidateAck.py new file mode 100755 index 0000000..ae2a09d --- /dev/null +++ b/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test01_TransmitSingleStandbyCommandandValidateAck.py @@ -0,0 +1,113 @@ +#!/usr/bin/env python3 +#** ***************************************************************************** +# * +# * If not stated otherwise in this file or this component's LICENSE file the +# * following copyright and licenses apply: +# * +# * Copyright 2024 RDK Management +# * +# * Licensed under the Apache License, Version 2.0 (the "License"); +# * you may not use this file except in compliance with the License. +# * You may obtain a copy of the License at +# * +# * +# http://www.apache.org/licenses/LICENSE-2.0 +# * +# * Unless required by applicable law or agreed to in writing, software +# * distributed under the License is distributed on an "AS IS" BASIS, +# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# * See the License for the specific language governing permissions and +# * limitations under the License. +# * +#* ****************************************************************************** + +import os +import sys + +dir_path = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(dir_path)) +sys.path.append(os.path.join(dir_path, "../")) + +from hdmiCECHelperClass import hdmiCECHelperClass +from raft.framework.core.logModule import logModule + +class hdmiCEC_test01_TransmitSingleStandbyCommandandValidateAck(hdmiCECHelperClass): + """ + Test class to enable, disable, and verify the status of audio ports on a device. + + This class uses the `dsAudioClass` to interact with the device's audio ports, + downloading necessary test assets, playing audio streams, enabling and disabling + audio ports, and performing verification of audio output. + """ + def __init__(self, log:logModule=None): + """ + Initializes the test class with test name, setup configuration, and sessions for the device. + + Args: + None + """ + # Class variables + self.testName = "test01_TransmitSingleStanbyCommandandValidateAck" + self.qcID = '1' + + super().__init__(self.testName, self.qcID, log) + + #TODO: Current version supports only manual verification. + def testVerifyStanbyStatus(self, ack, manual=False): + """ + Verifies the CEC Transmit Status through the result and also through the manual input. + + For manual verification, it prompts the user to confirm if CEC data is received by the destination + device and the action has been performed. + + Args: + ack(str): Ack result as printed on the test. Need to check that proper ACK is received. + (bool, optional): Flag to indicate if manual verification should be used. + Defaults to False for automation, True for manual. + + Returns: + bool: True if ACK verification succeeds, False otherwise.Also True if Manual test is Y and Flase if N + """ + if manual == True: + return self.testUserResponse.getUserYN(f"Is Stanby Command honored {port}? (Y/N):") + else : + #TODO: Add automation verification methods + return False + + def testFunction(self): + """ + The main test function that Transmits the Stanby Command and checks the ACK and validates it. + + This function: + - Send a standby command to a device that is connected on the CEC network and get the ack. + - User to confirm whether the targetted device had recieved this command or not. + + Returns: + bool: Final result of the test. + """ + + # Initialize the hdmiCEC module + self.testhdmiCEC.initialise() + + # Add the logical Address + self.testhdmiCEC.addLogicalAddress(0) + + # Transmit Standby command to a specific destination address + self.testhdmiCEC.cecTransmitCmd(0,3,65,[0]) + + #Verify the test result + result = self.testVerifyStandbyStatus(ack, True) + + # Remove the Logical Address + self.testhdmiCEC.removeLogicalAddress(0) + + # Terminate dsAudio Module + self.testdsAudio.terminate() + + return result + +if __name__ == '__main__': + summerLogName = os.path.splitext(os.path.basename(__file__))[0] + "_summery" + summeryLog = logModule(summerLogName, level=logModule.INFO) + test = hdmiCEC_test01_TransmitSingleStandbyCommandandValidateAck(summeryLog) + test.run(False) diff --git a/src/test_l3_hdmi_cec_sink_driver.c b/src/test_l3_hdmi_cec_sink_driver.c index bd825be..50ee614 100644 --- a/src/test_l3_hdmi_cec_sink_driver.c +++ b/src/test_l3_hdmi_cec_sink_driver.c @@ -180,6 +180,7 @@ int getCecCommandInfo(unsigned char cecCommand, const char** commandName, int* d */ /* Callback function */ +#if 0 void onRxDataReceived(int handle, void *callbackData, unsigned char *buf, int len) { UT_LOG_INFO("In %s(IN: handle: [%d], IN: callbackData: [%p], IN: buf: [%p], IN: len: [%d])\n", __FUNCTION__, handle, callbackData, buf, len); @@ -211,6 +212,211 @@ void onRxDataReceived(int handle, void *callbackData, unsigned char *buf, int le cbFlag = 1; UT_LOG_INFO("Out %s(OUT: cbFlag set to [1])\n", __FUNCTION__); } +#endif + +void displayOsdMessage(const char *message) { + UT_LOG_INFO("Displaying OSD message: \"%s\" on the device.\n", message); + + // Implement device-specific logic here, e.g., + // - Update a graphical display + // - Notify the user via LEDs or indicators + // - Trigger an external display mechanism + + // For example: + printf("OSD Message: %s\n", message); + + UT_LOG_INFO("OSD message display completed.\n"); +} + +void handleImageViewOn(int handle, unsigned char initiator, unsigned char destination) { + UT_LOG_INFO("Image View On command received.\n"); + // Perform any device-specific action for "Image View On" if needed. + UT_LOG_INFO("Image View On processed.\n"); +} + +void handleActiveSource(int handle, unsigned char initiator, unsigned char destination, unsigned char *buf, int len) { + if (len >= 4) { + unsigned short physicalAddress = (buf[2] << 8) | buf[3]; // Combine bytes to form the physical address + UT_LOG_INFO("Active Source command received. Physical Address: [0x%04X]\n", physicalAddress); + + // Process Active Source as needed. + } else { + UT_LOG_ERROR("Active Source command received with insufficient data.\n"); + } +} + +void handleGivePhysicalAddress(int handle, unsigned char initiator, unsigned char destination) { + unsigned char response[5] = { (destination << 4) | initiator, 0x84, 0x10, 0x00, 0x02 }; // Physical Address = 1.0.0.0, Device Type = TV + int result; + HdmiCecTx(handle, response, sizeof(response), &result); + UT_LOG_INFO("Reported Physical Address response sent with result: %d\n", result); +} + +void handleDeviceVendorID(int handle, unsigned char initiator, unsigned char destination) { + unsigned char response[4] = { (destination << 4) | initiator, 0x87, 0x00, 0x00, 0x01 }; // Example Vendor ID: 0x000001 + int result; + HdmiCecTx(handle, response, sizeof(response), &result); + UT_LOG_INFO("Device Vendor ID response sent with result: %d\n", result); +} + +void handleReportPhysicalAddress(int handle, unsigned char initiator, unsigned char destination) { + unsigned char response[5] = { (destination << 4) | initiator, 0x84, 0x10, 0x00, 0x02 }; // Physical Address = 1.0.0.0, Device Type = TV + int result; + HdmiCecTx(handle, response, sizeof(response), &result); + UT_LOG_INFO("Reported Physical Address response sent with result: %d\n", result); +} + +void handleReportPowerStatus(int handle, unsigned char initiator, unsigned char destination) { + unsigned char response[3] = { (destination << 4) | initiator, 0x90, 0x00 }; // Power Status: On (0x00) + int result; + HdmiCecTx(handle, response, sizeof(response), &result); + UT_LOG_INFO("Reported Power Status response sent with result: %d\n", result); +} + +void handleGiveCECVersion(int handle, unsigned char initiator, unsigned char destination) { + unsigned char response[3] = { (destination << 4) | initiator, 0x9E, 0x05 }; // CEC Version: 1.4 (0x05) + int result; + HdmiCecTx(handle, response, sizeof(response), &result); + UT_LOG_INFO("CEC Version response sent with result: %d\n", result); +} + +void handleGiveDeviceVendorID(int handle, unsigned char initiator, unsigned char destination) { + unsigned char response[4] = { (destination << 4) | initiator, 0x87, 0x00, 0x00, 0x01 }; // Vendor ID: 0x000001 + int result; + HdmiCecTx(handle, response, sizeof(response), &result); + UT_LOG_INFO("Device Vendor ID response sent with result: %d\n", result); +} + +void handleStandby(int handle) { + UT_LOG_INFO("Standby command received. Initiating standby actions.\n"); + // Implement device-specific standby actions here, such as turning off the display. +} + +void handleGiveDeviceInfo(int handle, unsigned char initiator, unsigned char destination) { + unsigned char response[12] = { (destination << 4) | initiator, 0xA1, 'V', 'T', 'S', ' ', 'D', 'e', 'v', 'i', 'c', 'e' }; // Device Info: "VTS Device" + int result; + HdmiCecTx(handle, response, sizeof(response), &result); + UT_LOG_INFO("Device Info response sent with result: %d\n", result); +} + +void handleOsdDisplay(int handle, unsigned char initiator, unsigned char destination, unsigned char *buf, int len) { + if (len > 2) { + UT_LOG_INFO("OSD Display message received: "); + for (int i = 2; i < len; i++) { + UT_LOG_INFO("%c", buf[i]); + } + UT_LOG_INFO("\n"); + } else { + UT_LOG_ERROR("OSD Display message received with insufficient data.\n"); + } +} + +void handleGetOsdName(int handle, unsigned char initiator, unsigned char destination) { + unsigned char response[11] = { (destination << 4) | initiator, 0x47, 'V', 'T', 'S', ' ', 'D', 'e', 'v', 'i', 'c', 'e' }; // OSD Name: "VTS Device" + int result; + HdmiCecTx(handle, response, sizeof(response), &result); + UT_LOG_INFO("OSD Name response sent with result: %d sourc/destination:0x%2x\n", result,response[0]); +} + +void handleGetPowerStatus(int handle, unsigned char initiator, unsigned char destination) { + unsigned char response[3] = { (destination << 4) | initiator, 0x90, 0x00 }; // Power Status: On (0x00) + int result; + HdmiCecTx(handle, response, sizeof(response), &result); + UT_LOG_INFO("Power Status response sent with result: %d\n", result); +} + +void handleFeatureAbort(int handle, unsigned char initiator, unsigned char destination, unsigned char opcode, unsigned char reason) { + unsigned char response[4] = { (destination << 4) | initiator, 0x00, opcode, reason }; // Abort with reason + int result; + HdmiCecTx(handle, response, sizeof(response), &result); + UT_LOG_WARNING("Feature Abort sent for opcode: 0x%02X with reason: 0x%02X, result: %d\n", opcode, reason, result); +} + + +/** + * @brief This function clears the stdin buffer. + * + * This function clears the stdin buffer. + */ +static void readAndDiscardRestOfLine(FILE *in) +{ + int c; + while ((c = fgetc(in)) != EOF && c != '\n'); +} + +static void readInt(int32_t *value) +{ + scanf("%d", value); + readAndDiscardRestOfLine(stdin); +} + +static void readHex(int32_t *value) +{ + scanf("%x", value); + readAndDiscardRestOfLine(stdin); +} +void onRxDataReceived(int handle, void *callbackData, unsigned char *buf, int len) { + UT_LOG_INFO("In %s(IN: handle: [%d], IN: callbackData: [%p], IN: buf: [%p], IN: len: [%d])\n", __FUNCTION__, handle, callbackData, buf, len); + + if ((handle != 0) && (callbackData != NULL) && (len > 0)) { + UT_LOG_INFO("CEC Data Received\n"); + + // Log each byte received in the buffer + for (int index = 0; index < len; index++) { + UT_LOG_INFO("Buffer at index [%d]: [0x%02X]\n", index, buf[index]); + } + + // Parse the command + unsigned char initiator = (buf[0] >> 4) & 0xF; // Extract initiator address + unsigned char destination = buf[0] & 0xF; // Extract destination address + unsigned char opcode = buf[1]; // Command opcode + + UT_LOG_INFO("Initiator: [0x%X], Destination: [0x%X], Opcode: [0x%02X]\n", initiator, destination, opcode); + + // Handle each opcode with its corresponding function + switch (opcode) { + case 0x04: handleImageViewOn(handle, initiator, destination); break; + case 0x82: handleActiveSource(handle, initiator, destination, buf, len); break; + case 0x8E: handleGivePhysicalAddress(handle, initiator, destination); break; + case 0x87: handleDeviceVendorID(handle, initiator, destination); break; + case 0x84: handleReportPhysicalAddress(handle, initiator, destination); break; + case 0x90: handleReportPowerStatus(handle, initiator, destination); break; + case 0x9F: handleGiveCECVersion(handle, initiator, destination); break; + case 0x8C: handleGiveDeviceVendorID(handle, initiator, destination); break; + case 0x36: handleStandby(handle); break; + case 0xA0: handleGiveDeviceInfo(handle, initiator, destination); break; + case 0x64: handleOsdDisplay(handle, initiator, destination, buf, len); break; + case 0x46: handleGetOsdName(handle, initiator, destination); break; + case 0x8F: handleGetPowerStatus(handle, initiator, destination); break; + case 0x00: handleFeatureAbort(handle, initiator, destination, opcode, 0x04); break; + default: + UT_LOG_WARNING("Unhandled opcode: [0x%02X]\n", opcode); + //handleFeatureAbort(handle, initiator, destination, opcode, 0x04); // Feature Abort: Unrecognized opcode + break; + } + + // Clear the buffer after processing + memset(buf, 0, len); + UT_LOG_INFO("Buffer cleared after processing.\n"); + + } else { + // Log specific errors based on failed conditions + if (handle == 0) { + UT_LOG_ERROR("Error: Invalid handle.\n"); + } + if (callbackData == NULL) { + UT_LOG_ERROR("Error: Null callback data.\n"); + } + if (len <= 0) { + UT_LOG_ERROR("Error: Invalid length.\n"); + } + } + + cbFlag = 1; + UT_LOG_INFO("Out %s(OUT: cbFlag set to [1])\n", __FUNCTION__); +} + + /** * @brief Initialization of the HAL CEC Module @@ -287,13 +493,13 @@ void test_l3_hdmi_cec_sink_hal_AddLogicalAddress(void) UT_LOG_MENU_INFO("----------------------------------------------------------"); UT_LOG_MENU_INFO("\t \tEnter Logical Address: "); + readHex(&logicalAddress;) UT_LOG_MENU_INFO("----------------------------------------------------------"); - scanf("%d", &logicalAddress); /* Check that logical address should be valid one */ UT_LOG_INFO("Calling HdmiCecAddLogicalAddress(IN:handle:[0x%0X], IN:logicalAddress:[%d]",gHandle,logicalAddress); status = HdmiCecAddLogicalAddress(gHandle,logicalAddress ); - UT_LOG_INFO("Failed HdmiCecAddLogicalAddress (IN:handle:[0x%0X], IN:logicalAddress:[%d]), status[%d]",gHandle,logicalAddress,UT_Control_GetMapString(cecError_mapTable,status)); + UT_LOG_INFO("HdmiCecAddLogicalAddress (IN:handle:[0x%0X], IN:logicalAddress:[%d]), status[%d]",gHandle,logicalAddress,UT_Control_GetMapString(cecError_mapTable,status)); assert(status == HDMI_CEC_IO_SUCCESS); UT_LOG_INFO("Out %s\n", __FUNCTION__); @@ -372,19 +578,19 @@ void test_l3_hdmi_cec_sink_hal_TransmitHdmiCecCommand(void) { // Reading inputs from the user or test framework UT_LOG_MENU_INFO("----------------------------------------------------------"); UT_LOG_MENU_INFO("\t \tEnter a valid Source Logical Address:"); + readHex(&sourceLogicalAddress); UT_LOG_MENU_INFO("----------------------------------------------------------"); - scanf("%d", &sourceLogicalAddress); UT_LOG_MENU_INFO("----------------------------------------------------------"); UT_LOG_MENU_INFO("\t \tEnter a valid Destination Logical Address: "); - scanf("%d", &destinationLogicalAddress); + readHex(&destinationLogicalAddress); UT_LOG_MENU_INFO("----------------------------------------------------------"); UT_LOG_MENU_INFO("----------------------------------------------------------"); UT_LOG_MENU_INFO("\t \tEnter CEC Command (in hex): "); + readHex(&cecCommand); UT_LOG_MENU_INFO("----------------------------------------------------------"); - scanf("%x", &cecCommand); // Validate the CEC command and get the expected data length if (getCecCommandInfo(cecCommand, &commandName, &expectedDataLength) != 0) { @@ -393,9 +599,8 @@ void test_l3_hdmi_cec_sink_hal_TransmitHdmiCecCommand(void) { UT_LOG_MENU_INFO("----------------------------------------------------------"); UT_LOG_MENU_INFO("\t \tPlease enter the number of data bytes for the CEC command: "); + readInt(&expectedDataLength); UT_LOG_MENU_INFO("----------------------------------------------------------"); - scanf("%d", &expectedDataLength); - commandName = "Vendor Specific Command"; } else { UT_LOG_INFO("CEC Command: %s (0x%02X), expects %d data byte(s)", commandName, cecCommand, expectedDataLength); @@ -405,7 +610,7 @@ void test_l3_hdmi_cec_sink_hal_TransmitHdmiCecCommand(void) { if (expectedDataLength > 0) { for (int i = 0; i < expectedDataLength; i++) { UT_LOG_MENU_INFO("\t \tEnter Databyte[%d] (in hex):", i); - scanf("%x", &buf[i + 2]); // +2 to account for the first two bytes + readHex(&buf[i + 2]); // +2 to account for the first two bytes } } @@ -425,7 +630,7 @@ void test_l3_hdmi_cec_sink_hal_TransmitHdmiCecCommand(void) { int status = HdmiCecTx(gHandle, buf, len, &result); UT_LOG_INFO("HdmiCecTx(IN: handle: [0x%0X], IN: length: [%d], result: [%d], status:[%d])", gHandle, len, result, UT_Control_GetMapString(cecError_mapTable,status)); - assert((result == HDMI_CEC_IO_SENT_BUT_NOT_ACKD) && (status == HDMI_CEC_IO_SUCCESS)); + //assert((result == HDMI_CEC_IO_SENT_BUT_NOT_ACKD) && (status == HDMI_CEC_IO_SUCCESS)); // Optional delay after sending the command sleep(5); @@ -545,10 +750,9 @@ void test_l3_hdmi_cec_sink_hal_RemoveLogicalAddress(void) UT_LOG_MENU_INFO("----------------------------------------------------------"); UT_LOG_MENU_INFO("\t \tEnter Logical Address to Remove: "); + readHex(&logicalAddress); UT_LOG_MENU_INFO("----------------------------------------------------------"); - scanf("%d", &logicalAddress); - UT_LOG_INFO("Calling HdmiCecRemoveLogicalAddress(IN: handle: [0x%0X], IN: logicalAddress: [%d])", gHandle, logicalAddress); // Invoke the API HdmiCecRemoveLogicalAddress From 329c86fb779d08b89329be12e89e390165e95f36 Mon Sep 17 00:00:00 2001 From: srinivasgtl <71806084+srinivasgtl@users.noreply.github.com> Date: Thu, 5 Dec 2024 11:39:20 +0000 Subject: [PATCH 22/40] gh #44 Updated test cases to use cec adaptor --- .vscode/launch.json | 35 ++++++++++++++ host/tests/classes/hdmiCEC.py | 29 +++++++----- .../hdmiCEC_L3_Tests/hdmiCECHelperClass.py | 9 ++-- .../hdmiCEC_L3_Tests/hdmiCECTestCommands.yml | 14 ++++++ .../hdmiCEC_L3_Tests/hdmiCEC_L3_testSetup.yml | 4 -- ...nsmitSingleStandbyCommandandValidateAck.py | 47 +++++++++++++++---- src/main.c | 26 ++-------- 7 files changed, 112 insertions(+), 52 deletions(-) create mode 100644 .vscode/launch.json create mode 100644 host/tests/hdmiCEC_L3_Tests/hdmiCECTestCommands.yml diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..51fc070 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,35 @@ +{ + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Python Debugger: Current File", + "type": "debugpy", + "request": "launch", + "program": "${file}", + "args": [ "--config", "example_rack_config.yml", + "--deviceConfig", "deviceConfig.yml"], + "console": "integratedTerminal" + }, + { + "name": "C/C++ Runner: Debug Session", + "type": "cppdbg", + "request": "launch", + "stopAtEntry": false, + "externalConsole": false, + "cwd": "${workspaceFolder}", + "program": "${workspaceFolder}/bin/hal_test", + "environment": [ {"name": "LD_LIBRARY_PATH", "value":"${workspaceFolder}/bin/"} ], + "args": [ "-l", "${workspaceFolder}/logs/", "-p", "${workspaceFolder}/profiles/sink/Sink_AudioSettings.yaml" ], + "MIMode": "gdb", + "miDebuggerPath": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ] + } + ] +} diff --git a/host/tests/classes/hdmiCEC.py b/host/tests/classes/hdmiCEC.py index b61f3ee..9a1ecfb 100644 --- a/host/tests/classes/hdmiCEC.py +++ b/host/tests/classes/hdmiCEC.py @@ -56,8 +56,8 @@ def __init__(self, moduleConfigProfileFile :str, session=None, targetWorkspace=" None """ self.moduleName = "hdmiCEC" - self.testConfigFile = os:.path.join(dir_path, "hdmiCEC_testConfig.yml") - self.testSuite = "L3 hdmicec - Sink" + self.testConfigFile = os.path.join(dir_path, "hdmiCEC_testConfig.yml") + self.testSuite = "L3 HDMICEC Sink Functions" # Load configurations for device profile and menu self.moduleConfigProfile = ConfigRead( moduleConfigProfileFile , self.moduleName) @@ -146,7 +146,7 @@ def removeLogicalAddress(self, logicalAddress:int): Remove logical address. Args: - logicalAddress (int): The Logical address of the DUT that should be removed. + logicalAddress (int): The Logical address of the DUT that should be removed. Returns: None @@ -190,8 +190,6 @@ def getPhysicalAddress(self): Returns: int: Physical Address of the DUT. """ - - result = self.utMenu.select( self.testSuite, "L3_GetPhyiscalAddress") typeStatusPattern = r"HdmiCecGetPhysicalAddress\(IN: handle: [.*\], physicalAddress: [.*\]), status:[.*\]" physicalAddress = self.searchPattern(result, typeStatusPattern) @@ -200,7 +198,7 @@ def getPhysicalAddress(self): def cecTransmitCmd(self, sourceLogicalAddress:int, destLogicalAddress:int, cecCommand:int, cecData:list=None): """ - Transmit/Broadcast the CEC command and data to the respective destination. + Transmit/Broadcast the CEC command and data to the respective destination. Args: None. @@ -233,8 +231,8 @@ def cecTransmitCmd(self, sourceLogicalAddress:int, destLogicalAddress:int, cecCo { "query_type": "direct", "query": "Enter Databyte", - "input": str(byte) - }) + "input": str(byte) + }) result = self.utMenu.select( self.testSuite, "L3_TransmitCecCommand",promptWithAnswers) @@ -257,16 +255,21 @@ def __del__(self): shell = InteractiveShell() shell.open() - platformProfile = dir_path + "/../../../profiles/sink/Sink_AudioSettings.yaml" + platformProfile = dir_path + "/../../../profiles/sink/sink_hdmiCEC.yaml" + # test the class assuming that it's optional - test = dsAudioClass(platformProfile, shell) + test = hdmiCECClass(platformProfile, shell) + # Initialize the hdmiCEC module test.initialise() - ports = test.getSupportedPorts() - test.enablePort(ports[0][0], ports[0][1]) - test.disablePort(ports[0][0], ports[0][1]) + # Add the logical Address. For now 0 only. + test.addLogicalAddress(0) + + # Get Physical Address + physicalAddress = test.getPhysicalAddress() + # Close the device test.terminate() shell.close() diff --git a/host/tests/hdmiCEC_L3_Tests/hdmiCECHelperClass.py b/host/tests/hdmiCEC_L3_Tests/hdmiCECHelperClass.py index a95ded8..dcabad0 100755 --- a/host/tests/hdmiCEC_L3_Tests/hdmiCECHelperClass.py +++ b/host/tests/hdmiCEC_L3_Tests/hdmiCECHelperClass.py @@ -26,12 +26,13 @@ dir_path = os.path.dirname(os.path.realpath(__file__)) sys.path.append(os.path.join(dir_path, "../../")) +sys.path.append(os.path.join(dir_path, "../")) from raft.framework.plugins.ut_raft.configRead import ConfigRead from raft.framework.plugins.ut_raft.utUserResponse import utUserResponse from raft.framework.plugins.ut_raft import utHelperClass from raft.framework.core.logModule import logModule -from classes.hdmCEC import hdmiCECClass +from classes.hdmiCEC import hdmiCECClass class hdmiCECHelperClass(utHelperClass): @@ -45,7 +46,7 @@ def __init__(self, testName:str, qcId:str, log:logModule=None ): log (class, optional): Parent log class. Defaults to None. """ self.testName = "" - self.testSetupPath = os.path.join(dir_path, "hdmiCEC__L3_testSetup.yml") + self.testSetupPath = os.path.join(dir_path, "hdmiCEC_L3_testSetup.yml") self.moduleName = "hdmiCEC" self.rackDevice = "dut" @@ -130,7 +131,7 @@ def testPrepareFunction(self): # Run Prerequisites listed in the test setup configuration file - self.testRunPrerequisites() + #self.testRunPrerequisites() # Create the hdmiCEC class self.testhdmiCEC = hdmiCECClass(self.moduleConfigProfileFile, self.hal_session, self.targetWorkspace) @@ -139,7 +140,7 @@ def testPrepareFunction(self): def testEndFunction(self, powerOff=True): # Clean the assets downloaded to the device - self.testCleanAssets() + #self.testCleanAssets() # Clean up the hdmiCEC instance del self.testhdmiCEC diff --git a/host/tests/hdmiCEC_L3_Tests/hdmiCECTestCommands.yml b/host/tests/hdmiCEC_L3_Tests/hdmiCECTestCommands.yml new file mode 100644 index 0000000..e3ae591 --- /dev/null +++ b/host/tests/hdmiCEC_L3_Tests/hdmiCECTestCommands.yml @@ -0,0 +1,14 @@ +hdmiCEC: + test01_TransmitSingleStandbyCommandandValidateAck: + - command: "0x36" # Standby + responses: + - type: "power_status" + loop_devices: true # Apply this response to all devices in the device map + payload: "[:sender]:90:[:power_status]" # Response pattern with placeholders + description: "Devices report their power status" + - command: "0x8F" # Request Power Status + responses: + - type: "power_status_response" + loop_devices: true # Apply this response to all devices in the device map + payload: "[:sender]:90:[:power_status]" # Response pattern with placeholders + description: "Devices respond with their current power status" \ No newline at end of file diff --git a/host/tests/hdmiCEC_L3_Tests/hdmiCEC_L3_testSetup.yml b/host/tests/hdmiCEC_L3_Tests/hdmiCEC_L3_testSetup.yml index bf903d3..9abc501 100755 --- a/host/tests/hdmiCEC_L3_Tests/hdmiCEC_L3_testSetup.yml +++ b/host/tests/hdmiCEC_L3_Tests/hdmiCEC_L3_testSetup.yml @@ -26,10 +26,6 @@ hdmiCEC: # Prefix must always exist assets: device: test01_TransmitSingleStandbyCommandandValidateAck: - <<: *defaults test02_BroadcastStandbyCommand: - <<: *defaults test03_TransmitOSDCommandandValidateAck: - <<: *defaults test04_TransmitLargerOSDCommandRepeatedlyandValidate: - <<: *defaults diff --git a/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test01_TransmitSingleStandbyCommandandValidateAck.py b/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test01_TransmitSingleStandbyCommandandValidateAck.py index ae2a09d..bd21665 100755 --- a/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test01_TransmitSingleStandbyCommandandValidateAck.py +++ b/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test01_TransmitSingleStandbyCommandandValidateAck.py @@ -30,6 +30,7 @@ from hdmiCECHelperClass import hdmiCECHelperClass from raft.framework.core.logModule import logModule +from raft.framework.plugins.ut_raft.configRead import ConfigRead class hdmiCEC_test01_TransmitSingleStandbyCommandandValidateAck(hdmiCECHelperClass): """ @@ -50,6 +51,13 @@ def __init__(self, log:logModule=None): self.testName = "test01_TransmitSingleStanbyCommandandValidateAck" self.qcID = '1' + self.testCECCommands = os.path.join(dir_path, "hdmiCECTestCommands.yml") + hdmicec = ConfigRead(self.testCECCommands, "hdmiCEC") + self.cecCommands = hdmicec.fields.get("test01_TransmitSingleStandbyCommandandValidateAck") + for command in self.cecCommands: + cec = command.get("command") + payload = command.get("payload") + print(cec, payload) super().__init__(self.testName, self.qcID, log) #TODO: Current version supports only manual verification. @@ -57,7 +65,7 @@ def testVerifyStanbyStatus(self, ack, manual=False): """ Verifies the CEC Transmit Status through the result and also through the manual input. - For manual verification, it prompts the user to confirm if CEC data is received by the destination + For manual verification, it prompts the user to confirm if CEC data is received by the destination device and the action has been performed. Args: @@ -69,7 +77,7 @@ def testVerifyStanbyStatus(self, ack, manual=False): bool: True if ACK verification succeeds, False otherwise.Also True if Manual test is Y and Flase if N """ if manual == True: - return self.testUserResponse.getUserYN(f"Is Stanby Command honored {port}? (Y/N):") + return self.testUserResponse.getUserYN(f"Is Stanby Command honored? (Y/N):") else : #TODO: Add automation verification methods return False @@ -79,7 +87,7 @@ def testFunction(self): The main test function that Transmits the Stanby Command and checks the ACK and validates it. This function: - - Send a standby command to a device that is connected on the CEC network and get the ack. + - Send a standby command to a device that is connected on the CEC network and get the ack. - User to confirm whether the targetted device had recieved this command or not. Returns: @@ -89,17 +97,36 @@ def testFunction(self): # Initialize the hdmiCEC module self.testhdmiCEC.initialise() - # Add the logical Address + # Add the logical Address. For now 0 only. self.testhdmiCEC.addLogicalAddress(0) - # Transmit Standby command to a specific destination address - self.testhdmiCEC.cecTransmitCmd(0,3,65,[0]) + self.cecDevices = [1,2,3]#self.cecAdapter.listDevices() - #Verify the test result - result = self.testVerifyStandbyStatus(ack, True) + for device in self.cecDevices: + logicalAddress = 1#int(device["address"].split('.')[0]) - # Remove the Logical Address - self.testhdmiCEC.removeLogicalAddress(0) + # To bypass sending the message to TV + if logicalAddress == 0 or logicalAddress == 14: + continue + + # self.log.stepStart(f'HdmiCecTx(IN: handle: [0x%0X], IN: length: [%d], result: [%d], status:[%d]') + + for command in self.cecCommands: + cec = command.get("command") + payload = command.get("payload") + #result = self.cecAdapter.startMonitoring() + #print(result) + # Transmit Standby command to a specific destination address + self.testhdmiCEC.cecTransmitCmd(0, logicalAddress,cec,payload) + #self.cecAdapter.stopMonitoring() + + #Verify the test result + result = self.testVerifyStanbyStatus(logicalAddress, True) + + self.log.stepResult() + + # Remove the Logical Address + self.testhdmiCEC.removeLogicalAddress(0) # Terminate dsAudio Module self.testdsAudio.terminate() diff --git a/src/main.c b/src/main.c index f2eb0ba..5c18bb2 100644 --- a/src/main.c +++ b/src/main.c @@ -113,36 +113,20 @@ int main(int argc, char** argv) } optind = 1; //Reset argv[] element pointer for further processing #endif - + /* Register tests as required, then call the UT-main to support switches and triggering */ UT_init( argc, argv ); - status = ut_kvp_getStringField(ut_kvp_profile_getInstance(), "hdmicec/type", szReturnedString, UT_KVP_MAX_ELEMENT_SIZE); - if (status == UT_KVP_STATUS_SUCCESS ) { - UT_LOG_DEBUG("Device Type: %s", szReturnedString); - } - else { - UT_LOG_ERROR("Failed to get the platform Device Type"); - return -1; - } - register_hdmicec_hal_common_l1_tests(); #ifdef VCOMPONENT register_vcomponent_tests(pProfilePath); test_l3_hdmi_cec_driver_register (pValidationProfilePath); #endif - - if(strncmp(szReturnedString,"source",UT_KVP_MAX_ELEMENT_SIZE) == 0) { - register_hdmicec_hal_source_l1_tests (); - register_hdmicec_hal_source_l2_tests (); - } - - if(strncmp(szReturnedString,"sink",UT_KVP_MAX_ELEMENT_SIZE) == 0) { - register_hdmicec_hal_sink_l1_tests (); - register_hdmicec_hal_sink_l2_tests (); + register_hdmicec_hal_source_l1_tests (); + register_hdmicec_hal_source_l2_tests (); + register_hdmicec_hal_sink_l1_tests (); + register_hdmicec_hal_sink_l2_tests (); register_hdmicec_hal_sink_l3_tests (); - } - UT_run_tests(); #ifdef VCOMPONENT From e65b3067948f37eadba963b0d1648a23c0e111e8 Mon Sep 17 00:00:00 2001 From: bhanucbp <141142298+bhanucbp@users.noreply.github.com> Date: Mon, 9 Dec 2024 20:16:29 +0000 Subject: [PATCH 23/40] gh #44 Updated test cases to use cec adaptor --- Makefile | 6 +- host/tests/classes/hdmiCEC.py | 45 +- host/tests/classes/hdmiCEC_testConfig.yml | 17 +- .../hdmiCEC_L3_Tests/hdmiCECHelperClass.py | 2 +- .../hdmiCEC_L3_Tests/hdmiCECTestCommands.yml | 21 +- .../hdmiCEC_L3_Tests/hdmiCEC_L3_testSetup.yml | 2 +- ... => hdmiCEC_test01_TransmitCECCommands.py} | 65 +- .../hdmiCEC_test02_ReceiveCECCommands.py | 113 +++ src/test_l3_hdmi_cec_sink_driver.c | 758 ++++++++++-------- 9 files changed, 599 insertions(+), 430 deletions(-) rename host/tests/hdmiCEC_L3_Tests/{hdmiCEC_test01_TransmitSingleStandbyCommandandValidateAck.py => hdmiCEC_test01_TransmitCECCommands.py} (57%) create mode 100644 host/tests/hdmiCEC_L3_Tests/hdmiCEC_test02_ReceiveCECCommands.py diff --git a/Makefile b/Makefile index 3bf2882..4b2fd2e 100644 --- a/Makefile +++ b/Makefile @@ -81,9 +81,9 @@ export HAL_LIB_DIR build: $(SETUP_SKELETON_LIBS) echo "SETUP_SKELETON_LIBS $(SETUP_SKELETON_LIBS)" @echo UT [$@] - make -C ./ut-core framework - make -C ./ut-core test - + make -C ./ut-core TARGET=${TARGET} + rm -rf $(BIN_DIR)/lib$(HAL_LIB).so + rm -rf $(ROOT_DIR)/libs/lib$(HAL_LIB).so #Build against the real library leads to the SOC library dependency also.SOC lib dependency cannot be specified in the ut Makefile, since it is supposed to be common across may platforms. So in order to over come this situation, creating a template skelton library with empty templates so that the template library wont have any other Soc dependency. And in the real platform mount copy bind with the actual library will work fine. skeleton: echo $(CC) diff --git a/host/tests/classes/hdmiCEC.py b/host/tests/classes/hdmiCEC.py index 9a1ecfb..a7c3ab4 100644 --- a/host/tests/classes/hdmiCEC.py +++ b/host/tests/classes/hdmiCEC.py @@ -55,7 +55,7 @@ def __init__(self, moduleConfigProfileFile :str, session=None, targetWorkspace=" Returns: None """ - self.moduleName = "hdmiCEC" + self.moduleName = "hdmicec" self.testConfigFile = os.path.join(dir_path, "hdmiCEC_testConfig.yml") self.testSuite = "L3 HDMICEC Sink Functions" @@ -105,7 +105,7 @@ def initialise(self): Returns: None """ - result = self.utMenu.select( self.testSuite, "L3_Init_HdmiCec") + result = self.utMenu.select( self.testSuite, "Init HDMI CEC") def terminate(self): """ @@ -117,7 +117,7 @@ def terminate(self): Returns: None """ - result = self.utMenu.select(self.testSuite, "L3_Close_HdmiCec_Sink") + result = self.utMenu.select(self.testSuite, "Close HDMI CEC") def addLogicalAddress(self, logicalAddress:int): """ @@ -137,11 +137,9 @@ def addLogicalAddress(self, logicalAddress:int): "input": str(logicalAddress) } ] + result = self.utMenu.select(self.testSuite, "Add Logical Address", promptWithAnswers) - - result = self.utMenu.select(self.testSuite, "L3_AddLogicalAddress", promptWithAnswers) - - def removeLogicalAddress(self, logicalAddress:int): + def removeLogicalAddress(self): """ Remove logical address. @@ -151,17 +149,7 @@ def removeLogicalAddress(self, logicalAddress:int): Returns: None """ - promptWithAnswers = [ - { - "query_type": "direct", - "query": "Enter Logical Address to Remove:", - "input": str(logicalAddress) - } - ] - - result = self.utMenu.select(self.testSuite, "L3_RemoveLogicalAddressHdmiCec_Sink", promptWithAnswers) - - + result = self.utMenu.select(self.testSuite, "Remove Logical Address") def getLogicalAddress(self): """ @@ -173,13 +161,12 @@ def getLogicalAddress(self): Returns: int: Logical address of the device. """ - result = self.utMenu.select( self.testSuite, "L3_GetLogicalAddress") - connectionStatusPattern = r"HdmiCecGetLogicalAddress\(IN: handle: [.*\], OUT: logicalAddress: [.*\]), status: [.*\])" + result = self.utMenu.select( self.testSuite, "Get Logical Address") + connectionStatusPattern = r"Result HdmiCecGetLogicalAddress\(IN:handle:[.*\], OUT:logicalAddress:[.*\]) HDMI_CEC_STATUS:[.*\])" logicalAddress = self.searchPattern(result, connectionStatusPattern) return logicalAddress - def getPhysicalAddress(self): """ Retrieve the Physical Address of the DUT. @@ -190,13 +177,13 @@ def getPhysicalAddress(self): Returns: int: Physical Address of the DUT. """ - result = self.utMenu.select( self.testSuite, "L3_GetPhyiscalAddress") - typeStatusPattern = r"HdmiCecGetPhysicalAddress\(IN: handle: [.*\], physicalAddress: [.*\]), status:[.*\]" + result = self.utMenu.select( self.testSuite, "Get Phyiscal Address") + typeStatusPattern = r"Result HdmiCecGetPhysicalAddress\(IN:handle:[.*\], OUT:physicalAddress:[.*\]) HDMI_CEC_STATUS:[.*\]" physicalAddress = self.searchPattern(result, typeStatusPattern) return physicalAddress - def cecTransmitCmd(self, sourceLogicalAddress:int, destLogicalAddress:int, cecCommand:int, cecData:list=None): + def cecTransmitCmd(self, destLogicalAddress:int, cecCommand:int, cecData:list=None): """ Transmit/Broadcast the CEC command and data to the respective destination. @@ -208,11 +195,6 @@ def cecTransmitCmd(self, sourceLogicalAddress:int, destLogicalAddress:int, cecCo """ promptWithAnswers = [ - { - "query_type": "direct", - "query": "Enter a valid Source Logical Address:", - "input": str(sourceLogicalAddress) - }, { "query_type": "direct", "query": "Enter a valid Destination Logical Address:", @@ -220,7 +202,7 @@ def cecTransmitCmd(self, sourceLogicalAddress:int, destLogicalAddress:int, cecCo }, { "query_type": "direct", - "query": "Enter CEC Command:", + "query": "Enter CEC Command (in hex):", "input": str(cecCommand) }, ] @@ -234,8 +216,7 @@ def cecTransmitCmd(self, sourceLogicalAddress:int, destLogicalAddress:int, cecCo "input": str(byte) }) - result = self.utMenu.select( self.testSuite, "L3_TransmitCecCommand",promptWithAnswers) - + result = self.utMenu.select( self.testSuite, "Transmit CEC Command",promptWithAnswers) def __del__(self): """ diff --git a/host/tests/classes/hdmiCEC_testConfig.yml b/host/tests/classes/hdmiCEC_testConfig.yml index baa8d23..40ac032 100644 --- a/host/tests/classes/hdmiCEC_testConfig.yml +++ b/host/tests/classes/hdmiCEC_testConfig.yml @@ -19,7 +19,7 @@ # * limitations under the License. # * #* ****************************************************************************** -hdmiCEC: +hdmicec: description: "hdmi CEC testing profile / menu system for UT" test: artifacts: @@ -56,11 +56,10 @@ hdmiCEC: 2: name: "L3 hdmicec - Sink" tests: - - "L3_Init_HdmiCec" - - "L3_AddLogicalAddress" - - "L3_GetLogicalAddress" - - "L3_TransmitCecCommand" - - "L3_ReceiveCecCommand" - - "L3_GetPhyiscalAddress" - - "L3_RemoveLogicalAddressHdmiCec_Sink" - - "L3_Close_HdmiCec_Sink" + - "Init HDMI CEC" + - "Add Logical Address" + - "Get Logical Address" + - "Transmit CEC Command" + - "Get Phyiscal Address" + - "Remove Logical Address" + - "Close HDMI CEC" diff --git a/host/tests/hdmiCEC_L3_Tests/hdmiCECHelperClass.py b/host/tests/hdmiCEC_L3_Tests/hdmiCECHelperClass.py index dcabad0..478f421 100755 --- a/host/tests/hdmiCEC_L3_Tests/hdmiCECHelperClass.py +++ b/host/tests/hdmiCEC_L3_Tests/hdmiCECHelperClass.py @@ -47,7 +47,7 @@ def __init__(self, testName:str, qcId:str, log:logModule=None ): """ self.testName = "" self.testSetupPath = os.path.join(dir_path, "hdmiCEC_L3_testSetup.yml") - self.moduleName = "hdmiCEC" + self.moduleName = "hdmicec" self.rackDevice = "dut" super().__init__(testName, qcId, log) diff --git a/host/tests/hdmiCEC_L3_Tests/hdmiCECTestCommands.yml b/host/tests/hdmiCEC_L3_Tests/hdmiCECTestCommands.yml index e3ae591..ecf469e 100644 --- a/host/tests/hdmiCEC_L3_Tests/hdmiCECTestCommands.yml +++ b/host/tests/hdmiCEC_L3_Tests/hdmiCECTestCommands.yml @@ -1,14 +1,15 @@ hdmiCEC: - test01_TransmitSingleStandbyCommandandValidateAck: + test01_TransmitCECCommands: + - command: "0x04" # Image View on + payload: + responses: - command: "0x36" # Standby + payload: responses: - - type: "power_status" - loop_devices: true # Apply this response to all devices in the device map - payload: "[:sender]:90:[:power_status]" # Response pattern with placeholders - description: "Devices report their power status" - - command: "0x8F" # Request Power Status + - command: "0x9F" # Get CEC version + payload: responses: - - type: "power_status_response" - loop_devices: true # Apply this response to all devices in the device map - payload: "[:sender]:90:[:power_status]" # Response pattern with placeholders - description: "Devices respond with their current power status" \ No newline at end of file + - type: "Get CEC Version" + loop_devices: false # Apply this response to all devices in the device map + payload: "" # Response pattern with placeholders + description: "Device request for CEC version" \ No newline at end of file diff --git a/host/tests/hdmiCEC_L3_Tests/hdmiCEC_L3_testSetup.yml b/host/tests/hdmiCEC_L3_Tests/hdmiCEC_L3_testSetup.yml index 9abc501..fcddfe7 100755 --- a/host/tests/hdmiCEC_L3_Tests/hdmiCEC_L3_testSetup.yml +++ b/host/tests/hdmiCEC_L3_Tests/hdmiCEC_L3_testSetup.yml @@ -21,7 +21,7 @@ #* ****************************************************************************** -hdmiCEC: # Prefix must always exist +hdmicec: # Prefix must always exist description: "hdmiCEC test setup" assets: device: diff --git a/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test01_TransmitSingleStandbyCommandandValidateAck.py b/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test01_TransmitCECCommands.py similarity index 57% rename from host/tests/hdmiCEC_L3_Tests/hdmiCEC_test01_TransmitSingleStandbyCommandandValidateAck.py rename to host/tests/hdmiCEC_L3_Tests/hdmiCEC_test01_TransmitCECCommands.py index bd21665..fb4c648 100755 --- a/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test01_TransmitSingleStandbyCommandandValidateAck.py +++ b/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test01_TransmitCECCommands.py @@ -32,7 +32,7 @@ from raft.framework.core.logModule import logModule from raft.framework.plugins.ut_raft.configRead import ConfigRead -class hdmiCEC_test01_TransmitSingleStandbyCommandandValidateAck(hdmiCECHelperClass): +class hdmiCEC_test01_TransmitCECCommands(hdmiCECHelperClass): """ Test class to enable, disable, and verify the status of audio ports on a device. @@ -48,39 +48,15 @@ def __init__(self, log:logModule=None): None """ # Class variables - self.testName = "test01_TransmitSingleStanbyCommandandValidateAck" + self.testName = "test01_TransmitCECCommands" self.qcID = '1' + self.sourceLogicalAddress = 0 self.testCECCommands = os.path.join(dir_path, "hdmiCECTestCommands.yml") hdmicec = ConfigRead(self.testCECCommands, "hdmiCEC") - self.cecCommands = hdmicec.fields.get("test01_TransmitSingleStandbyCommandandValidateAck") - for command in self.cecCommands: - cec = command.get("command") - payload = command.get("payload") - print(cec, payload) - super().__init__(self.testName, self.qcID, log) - - #TODO: Current version supports only manual verification. - def testVerifyStanbyStatus(self, ack, manual=False): - """ - Verifies the CEC Transmit Status through the result and also through the manual input. - - For manual verification, it prompts the user to confirm if CEC data is received by the destination - device and the action has been performed. - - Args: - ack(str): Ack result as printed on the test. Need to check that proper ACK is received. - (bool, optional): Flag to indicate if manual verification should be used. - Defaults to False for automation, True for manual. + self.cecCommands = hdmicec.fields.get(self.testName) - Returns: - bool: True if ACK verification succeeds, False otherwise.Also True if Manual test is Y and Flase if N - """ - if manual == True: - return self.testUserResponse.getUserYN(f"Is Stanby Command honored? (Y/N):") - else : - #TODO: Add automation verification methods - return False + super().__init__(self.testName, self.qcID, log) def testFunction(self): """ @@ -97,44 +73,41 @@ def testFunction(self): # Initialize the hdmiCEC module self.testhdmiCEC.initialise() - # Add the logical Address. For now 0 only. - self.testhdmiCEC.addLogicalAddress(0) + # Add the logical Address. + self.testhdmiCEC.addLogicalAddress(self.sourceLogicalAddress) - self.cecDevices = [1,2,3]#self.cecAdapter.listDevices() + self.cecDevices = self.cecAdapter.listDevices() for device in self.cecDevices: - logicalAddress = 1#int(device["address"].split('.')[0]) + logicalAddress = device["logical address"] # To bypass sending the message to TV if logicalAddress == 0 or logicalAddress == 14: continue - # self.log.stepStart(f'HdmiCecTx(IN: handle: [0x%0X], IN: length: [%d], result: [%d], status:[%d]') - for command in self.cecCommands: cec = command.get("command") payload = command.get("payload") - #result = self.cecAdapter.startMonitoring() - #print(result) + # Transmit Standby command to a specific destination address - self.testhdmiCEC.cecTransmitCmd(0, logicalAddress,cec,payload) - #self.cecAdapter.stopMonitoring() + self.testhdmiCEC.cecTransmitCmd(logicalAddress, cec, payload) + + self.log.stepStart(f'HdmiCecTx Source: {self.sourceLogicalAddress} Destination: {logicalAddress} CEC OPCode: {cec} Payload: {payload}') - #Verify the test result - result = self.testVerifyStanbyStatus(logicalAddress, True) + result = self.cecAdapter.checkTransmitStatus(self.sourceLogicalAddress, logicalAddress, cec, payload) - self.log.stepResult() + self.log.stepResult(result, f'HdmiCecTx Source: {self.sourceLogicalAddress} Destination: {logicalAddress} CEC OPCode: {cec} Payload: {payload}') - # Remove the Logical Address - self.testhdmiCEC.removeLogicalAddress(0) + # Remove the Logical Address + self.testhdmiCEC.removeLogicalAddress() # Terminate dsAudio Module - self.testdsAudio.terminate() + self.testhdmiCEC.terminate() return result if __name__ == '__main__': summerLogName = os.path.splitext(os.path.basename(__file__))[0] + "_summery" summeryLog = logModule(summerLogName, level=logModule.INFO) - test = hdmiCEC_test01_TransmitSingleStandbyCommandandValidateAck(summeryLog) + test = hdmiCEC_test01_TransmitCECCommands(summeryLog) test.run(False) diff --git a/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test02_ReceiveCECCommands.py b/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test02_ReceiveCECCommands.py new file mode 100644 index 0000000..cec862b --- /dev/null +++ b/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test02_ReceiveCECCommands.py @@ -0,0 +1,113 @@ +#!/usr/bin/env python3 +#** ***************************************************************************** +# * +# * If not stated otherwise in this file or this component's LICENSE file the +# * following copyright and licenses apply: +# * +# * Copyright 2024 RDK Management +# * +# * Licensed under the Apache License, Version 2.0 (the "License"); +# * you may not use this file except in compliance with the License. +# * You may obtain a copy of the License at +# * +# * +# http://www.apache.org/licenses/LICENSE-2.0 +# * +# * Unless required by applicable law or agreed to in writing, software +# * distributed under the License is distributed on an "AS IS" BASIS, +# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# * See the License for the specific language governing permissions and +# * limitations under the License. +# * +#* ****************************************************************************** + +import os +import sys + +dir_path = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(dir_path)) +sys.path.append(os.path.join(dir_path, "../")) + +from hdmiCECHelperClass import hdmiCECHelperClass +from raft.framework.core.logModule import logModule +from raft.framework.plugins.ut_raft.configRead import ConfigRead + +class hdmiCEC_test02_ReceiveCECCommands(hdmiCECHelperClass): + """ + Test class to enable, disable, and verify the status of audio ports on a device. + + This class uses the `dsAudioClass` to interact with the device's audio ports, + downloading necessary test assets, playing audio streams, enabling and disabling + audio ports, and performing verification of audio output. + """ + def __init__(self, log:logModule=None): + """ + Initializes the test class with test name, setup configuration, and sessions for the device. + + Args: + None + """ + # Class variables + self.testName = "test02_ReceiveCECCommands" + self.qcID = '2' + self.sourceLogicalAddress = 0 + + self.testCECCommands = os.path.join(dir_path, "hdmiCECTestCommands.yml") + hdmicec = ConfigRead(self.testCECCommands, "hdmiCEC") + self.cecCommands = hdmicec.fields.get(self.testName) + + super().__init__(self.testName, self.qcID, log) + + def testFunction(self): + """ + The main test function that Transmits the Stanby Command and checks the ACK and validates it. + + This function: + - Send a standby command to a device that is connected on the CEC network and get the ack. + - User to confirm whether the targetted device had recieved this command or not. + + Returns: + bool: Final result of the test. + """ + + # Initialize the hdmiCEC module + self.testhdmiCEC.initialise() + + # Add the logical Address. + self.testhdmiCEC.addLogicalAddress(self.sourceLogicalAddress) + + self.cecDevices = self.cecAdapter.listDevices() + + for device in self.cecDevices: + logicalAddress = device["logical address"] + + # To bypass sending the message to TV + if logicalAddress == 0 or logicalAddress == 14: + continue + + for command in self.cecCommands: + cec = command.get("command") + payload = command.get("payload") + + # Transmit Standby command to a specific destination address + self.testhdmiCEC.cecTransmitCmd(logicalAddress, cec, payload) + + self.log.stepStart(f'HdmiCecTx Source: {self.sourceLogicalAddress} Destination: {logicalAddress} CEC OPCode: {cec} Payload: {payload}') + + result = self.cecAdapter.checkTransmitStatus(self.sourceLogicalAddress, logicalAddress, cec, payload) + + self.log.stepResult(result, f'HdmiCecTx Source: {self.sourceLogicalAddress} Destination: {logicalAddress} CEC OPCode: {cec} Payload: {payload}') + + # Remove the Logical Address + self.testhdmiCEC.removeLogicalAddress() + + # Terminate dsAudio Module + self.testhdmiCEC.terminate() + + return result + +if __name__ == '__main__': + summerLogName = os.path.splitext(os.path.basename(__file__))[0] + "_summery" + summeryLog = logModule(summerLogName, level=logModule.INFO) + test = hdmiCEC_test02_ReceiveCECCommands(summeryLog) + test.run(False) diff --git a/src/test_l3_hdmi_cec_sink_driver.c b/src/test_l3_hdmi_cec_sink_driver.c index 50ee614..799dcf4 100644 --- a/src/test_l3_hdmi_cec_sink_driver.c +++ b/src/test_l3_hdmi_cec_sink_driver.c @@ -15,26 +15,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - /** * @addtogroup HPK Hardware Porting Kit * @{ * */ - /** * @addtogroup HDMI_CEC HDMI CEC Module * @{ * */ - /** * @defgroup HDMI_CEC_HALTESTS HDMI CEC HAL Tests * @{ * */ - /** * @defgroup HDMI_CEC_HALTESTS_L3 HDMI CEC HAL Tests L2 File * @{ @@ -60,6 +56,7 @@ * */ +#include #include #include #include @@ -69,21 +66,21 @@ #define TIMEOUT 5 #define REPLY_TIMEOUT 5 -#define UT_LOG_MENU_INFO UT_LOG_INFO +#define HDMI_CEC_MAX_PAYLOAD 128 +#define HDMI_CEC_MAX_OSDNAME 15 -static int gTestGroup = 3; -static int gTestID = 1; -static int gHandle = 0; -static int cbFlag = 0; +#define UT_LOG_MENU_INFO UT_LOG_INFO // CEC command map table and supporting function -typedef struct { - unsigned char cecCommand; // CEC command code +typedef struct +{ + uint8_t cecCommand; // CEC command code const char* commandName; // Human-readable command name - int dataLength; // Number of data bytes required for the command + int32_t dataLength; // Number of data bytes required for the command } CecCommandMap; -CecCommandMap cecCommandTable[] = { +CecCommandMap cecCommandTable[] = +{ {0x00, "Feature Abort", 2}, {0x04, "Image View On", 0}, {0x0D, "Text View On", 0}, @@ -119,8 +116,66 @@ CecCommandMap cecCommandTable[] = { // Add more commands as needed }; +typedef enum HDMI_CEC_DEVICE_TYPE_T +{ + HDMI_CEC_RECORDER = 1, + HDMI_CEC_AMPLIFIER, + HDMI_CEC_TUNER, + HDMI_CEC_PLAYBACK, + HDMI_CEC_AUDIO, + HDMI_CEC_TV, + HDMI_CEC_RESERVED +} HDMI_CEC_DEVICE_TYPE; + +const static ut_control_keyStringMapping_t cecDeviceType_mapTable[] = +{ + {"Recorder", (int32_t)HDMI_CEC_RECORDER}, + {"Amplifier", (int32_t)HDMI_CEC_AMPLIFIER}, + {"Tuner", (int32_t)HDMI_CEC_TUNER}, + {"Playback Device", (int32_t)HDMI_CEC_PLAYBACK}, + {"Audio System", (int32_t)HDMI_CEC_AUDIO}, + {"TV", (int32_t)HDMI_CEC_TV}, + {"Reserved", (int32_t)HDMI_CEC_RESERVED} +}; + +typedef enum HDMI_CEC_POWER_STATUS_T +{ + HDMI_CEC_ON = 0, + HDMI_CEC_STANDBY, + HDMI_CEC_TRANSIT_STANDBY, + HDMI_CEC_TRANSIT_ON +} HDMI_CEC_POWER_STATUS; + +const static ut_control_keyStringMapping_t cecPowerStatus_mapTable[] = +{ + {"On", (int32_t)HDMI_CEC_ON}, + {"Standby", (int32_t)HDMI_CEC_STANDBY}, + {"Transition to Standby", (int32_t)HDMI_CEC_TRANSIT_STANDBY}, + {"Transition to On", (int32_t)HDMI_CEC_TRANSIT_ON} +}; + +typedef enum HDMI_CEC_FEATURE_ABORT_REASON_T +{ + HDMI_CEC_UNRECOGNIZE = 0, + HDMI_CEC_NOTCORRECTMODE, + HDMI_CEC_CANNOTPROVIDE, + HDMI_CEC_INVALID, + HDMI_CEC_REFUSED, + HDMI_CEC_UNABLE +} HDMI_CEC_FEATURE_ABORT_REASON; + +const static ut_control_keyStringMapping_t cecFeatureAbortReason_mapTable[] = +{ + {"Unrecognized opcode", (int32_t)HDMI_CEC_UNRECOGNIZE}, + {"Not in Correct mode to respond", (int32_t)HDMI_CEC_NOTCORRECTMODE}, + {"Cannot provide source", (int32_t)HDMI_CEC_CANNOTPROVIDE}, + {"Invalid operand", (int32_t)HDMI_CEC_INVALID}, + {"Refused", (int32_t)HDMI_CEC_REFUSED}, + {"Unable to determine", (int32_t)HDMI_CEC_UNABLE} +}; /* cecError_t */ -const static ut_control_keyStringMapping_t cecError_mapTable [] = { +const static ut_control_keyStringMapping_t cecError_mapTable [] = +{ {"HDMI_CEC_IO_SUCCESS", (int32_t)HDMI_CEC_IO_SUCCESS}, {"HDMI_CEC_IO_SENT_AND_ACKD", (int32_t)HDMI_CEC_IO_SENT_AND_ACKD}, {"HDMI_CEC_IO_SENT_BUT_NOT_ACKD", (int32_t)HDMI_CEC_IO_SENT_BUT_NOT_ACKD}, @@ -139,6 +194,24 @@ const static ut_control_keyStringMapping_t cecError_mapTable [] = { { NULL, -1 } }; +static int32_t gTestGroup = 3; +static int32_t gTestID = 1; +static int32_t gHandle = 0; +static int32_t gLogicalAddress = -1; +static uint32_t gPhysicalAddress = -1; +static uint8_t *gPhysicalAddressBytes; +static HDMI_CEC_DEVICE_TYPE gDeviceType = HDMI_CEC_TV; +static HDMI_CEC_POWER_STATUS gPowerStatus = HDMI_CEC_ON; +static uint8_t gDeviceVendorID[] = {0x00, 0x00, 0x01}; // Example Vendor ID: 0x000001 +static uint8_t gCECVersion = 0x05; // CEC Version: 1.4 (0x05) +static uint8_t gAudioDelay = (100/2) + 1; //100msec audio delay ((number of milliseconds/2) + 1) +static uint8_t gVideoDelay = (200/2) + 1; //100msec video delay ((number of milliseconds/2) + 1) +static uint8_t gBroadcastAddress = 0xF; + +//(Bits 1-0) : Audio Ouput Compensated (0 - N/A, 1 - TV audio output is delay compensated, 2 - TV audio output is NOT delay compensated, 3 - TV audio output is Par delay compensated) +//(Bit 2) : 0 - normal latency, 1 - low latency +//Bit(7-3) : Reserved +uint8_t gLatencyFlag = 0x00; /** * @brief CEC Command with data size mapping function. @@ -146,17 +219,17 @@ const static ut_control_keyStringMapping_t cecError_mapTable [] = { * This function maps the provided CEC command with the data length required for the CEC Command. * This will help the test to consider the correct size of the data required for the CEC Command. * -* **Test Group ID:** 03@n -* **Test Case ID:** 000@n -* */ -int getCecCommandInfo(unsigned char cecCommand, const char** commandName, int* dataLength) { +static int32_t getCecCommandInfo(uint8_t cecCommand, const char** commandName, int32_t* dataLength) +{ UT_LOG_INFO("In %s(IN: cecCommand: [0x%02X])\n", __FUNCTION__, cecCommand); - int tableSize = sizeof(cecCommandTable) / sizeof(CecCommandMap); + int32_t tableSize = sizeof(cecCommandTable) / sizeof(CecCommandMap); - for (int i = 0; i < tableSize; i++) { - if (cecCommandTable[i].cecCommand == cecCommand) { + for (int32_t i = 0; i < tableSize; i++) + { + if (cecCommandTable[i].cecCommand == cecCommand) + { *commandName = cecCommandTable[i].commandName; *dataLength = cecCommandTable[i].dataLength; UT_LOG_INFO("Out %s(OUT: commandName: [%s], OUT: dataLength: [%d])\n", __FUNCTION__, *commandName, *dataLength); @@ -168,170 +241,222 @@ int getCecCommandInfo(unsigned char cecCommand, const char** commandName, int* d return -1; // Command not found } -/** -* @brief Rx Callback function -* -* This function is a Receive Call back function called when data is received from a connected device. -* This function should be registered through HdmiCecSetRxCallback(). -* -* **Test Group ID:** 03@n -* **Test Case ID:** 000@n -* -*/ - -/* Callback function */ -#if 0 -void onRxDataReceived(int handle, void *callbackData, unsigned char *buf, int len) { - UT_LOG_INFO("In %s(IN: handle: [%d], IN: callbackData: [%p], IN: buf: [%p], IN: len: [%d])\n", __FUNCTION__, handle, callbackData, buf, len); - - if ((handle != 0) && (callbackData != NULL) && (len > 0)) { - UT_LOG_INFO("CEC Data Received\n"); - - // Log each byte received in the buffer - for (int index = 0; index < len; index++) { - UT_LOG_INFO("Buffer at index [%d]: [0x%02X]\n", index, buf[index]); - } - - // Clear the buffer after processing - memset(buf, 0, len); - UT_LOG_INFO("Buffer cleared after processing.\n"); - - } else { - // Log specific errors based on failed conditions - if (handle == 0) { - UT_LOG_ERROR("Error: Invalid handle.\n"); - } - if (callbackData == NULL) { - UT_LOG_ERROR("Error: Null callback data.\n"); - } - if (len <= 0) { - UT_LOG_ERROR("Error: Invalid length.\n"); - } - } - - cbFlag = 1; - UT_LOG_INFO("Out %s(OUT: cbFlag set to [1])\n", __FUNCTION__); -} -#endif - -void displayOsdMessage(const char *message) { - UT_LOG_INFO("Displaying OSD message: \"%s\" on the device.\n", message); - - // Implement device-specific logic here, e.g., - // - Update a graphical display - // - Notify the user via LEDs or indicators - // - Trigger an external display mechanism - - // For example: - printf("OSD Message: %s\n", message); - - UT_LOG_INFO("OSD message display completed.\n"); -} - -void handleImageViewOn(int handle, unsigned char initiator, unsigned char destination) { +static void handleImageViewOn() +{ UT_LOG_INFO("Image View On command received.\n"); // Perform any device-specific action for "Image View On" if needed. UT_LOG_INFO("Image View On processed.\n"); } -void handleActiveSource(int handle, unsigned char initiator, unsigned char destination, unsigned char *buf, int len) { - if (len >= 4) { - unsigned short physicalAddress = (buf[2] << 8) | buf[3]; // Combine bytes to form the physical address +static void handleActiveSource(uint8_t *buf, int32_t len) +{ + if (len >= 4) + { + uint16_t physicalAddress = (buf[2] << 8) | buf[3]; // Combine bytes to form the physical address UT_LOG_INFO("Active Source command received. Physical Address: [0x%04X]\n", physicalAddress); - // Process Active Source as needed. - } else { + } + else + { UT_LOG_ERROR("Active Source command received with insufficient data.\n"); } } -void handleGivePhysicalAddress(int handle, unsigned char initiator, unsigned char destination) { - unsigned char response[5] = { (destination << 4) | initiator, 0x84, 0x10, 0x00, 0x02 }; // Physical Address = 1.0.0.0, Device Type = TV - int result; +static void handleGivePhysicalAddress(int32_t handle, uint8_t initiator, uint8_t destination, uint8_t *pPhysicalAddress, HDMI_CEC_DEVICE_TYPE deviceType) +{ + uint8_t response[] = { (destination << 4) | initiator, 0x84, (pPhysicalAddress[3] << 4) | pPhysicalAddress[2], (pPhysicalAddress[1] << 4 ) | pPhysicalAddress[0], deviceType}; + int32_t result; HdmiCecTx(handle, response, sizeof(response), &result); UT_LOG_INFO("Reported Physical Address response sent with result: %d\n", result); } -void handleDeviceVendorID(int handle, unsigned char initiator, unsigned char destination) { - unsigned char response[4] = { (destination << 4) | initiator, 0x87, 0x00, 0x00, 0x01 }; // Example Vendor ID: 0x000001 - int result; - HdmiCecTx(handle, response, sizeof(response), &result); - UT_LOG_INFO("Device Vendor ID response sent with result: %d\n", result); +static void handleReportPhysicalAddress(uint8_t *buf, int32_t len) +{ + if (len >= 5) + UT_LOG_INFO("Reported Physical Address: 0x%02X:0x%02X:0x%02X:0x%02X, Type: %s\n", (buf[2] >> 4) & 0x0F, buf[2] & 0x0F, (buf[3] >> 4) & 0x0F, buf[3] & 0x0F, UT_Control_GetMapString(cecDeviceType_mapTable, buf[4])); + else + UT_LOG_ERROR("Reported Physical command received with insufficient data.\n"); } -void handleReportPhysicalAddress(int handle, unsigned char initiator, unsigned char destination) { - unsigned char response[5] = { (destination << 4) | initiator, 0x84, 0x10, 0x00, 0x02 }; // Physical Address = 1.0.0.0, Device Type = TV - int result; +static void handleGetCECVersion(int32_t handle, uint8_t initiator, uint8_t destination, uint8_t version) +{ + uint8_t response[] = { (destination << 4) | initiator, 0x9E, version }; + int32_t result; HdmiCecTx(handle, response, sizeof(response), &result); - UT_LOG_INFO("Reported Physical Address response sent with result: %d\n", result); + UT_LOG_INFO("CEC Version response sent with result: %d\n", result); } -void handleReportPowerStatus(int handle, unsigned char initiator, unsigned char destination) { - unsigned char response[3] = { (destination << 4) | initiator, 0x90, 0x00 }; // Power Status: On (0x00) - int result; - HdmiCecTx(handle, response, sizeof(response), &result); - UT_LOG_INFO("Reported Power Status response sent with result: %d\n", result); +static void handleCECVersion(uint8_t *buf, int32_t len) +{ + if (len >= 3) + UT_LOG_INFO("Received CEC Version: %x\n", buf[2]); + else + UT_LOG_ERROR("CEC Version command received with insufficient data.\n"); } -void handleGiveCECVersion(int handle, unsigned char initiator, unsigned char destination) { - unsigned char response[3] = { (destination << 4) | initiator, 0x9E, 0x05 }; // CEC Version: 1.4 (0x05) - int result; +static void handleGiveDeviceVendorID(int32_t handle, uint8_t initiator, uint8_t destination, uint8_t *pDeviceVendorId) +{ + uint8_t response[] = { (destination << 4) | initiator, 0x87, pDeviceVendorId[0], pDeviceVendorId[1], pDeviceVendorId[2]}; + int32_t result; HdmiCecTx(handle, response, sizeof(response), &result); - UT_LOG_INFO("CEC Version response sent with result: %d\n", result); + UT_LOG_INFO("Device Vendor ID response sent with result: %d\n", result); } -void handleGiveDeviceVendorID(int handle, unsigned char initiator, unsigned char destination) { - unsigned char response[4] = { (destination << 4) | initiator, 0x87, 0x00, 0x00, 0x01 }; // Vendor ID: 0x000001 - int result; - HdmiCecTx(handle, response, sizeof(response), &result); - UT_LOG_INFO("Device Vendor ID response sent with result: %d\n", result); +static void handleDeviceVendorID(uint8_t *buf, int32_t len) +{ + if (len >= 5) + UT_LOG_INFO("Received Device Vendor ID: %x%x%x\n", buf[2], buf[3], buf[4]); + else + UT_LOG_ERROR("Give Device vendor ID command received with insufficient data.\n"); } -void handleStandby(int handle) { +static void handleStandby() +{ UT_LOG_INFO("Standby command received. Initiating standby actions.\n"); // Implement device-specific standby actions here, such as turning off the display. } -void handleGiveDeviceInfo(int handle, unsigned char initiator, unsigned char destination) { - unsigned char response[12] = { (destination << 4) | initiator, 0xA1, 'V', 'T', 'S', ' ', 'D', 'e', 'v', 'i', 'c', 'e' }; // Device Info: "VTS Device" - int result; +static void handleGiveDeviceInfo(int32_t handle, uint8_t initiator, uint8_t destination) +{ + uint8_t response[] = { (destination << 4) | initiator, 0xA1, 'V', 'T', 'S', ' ', 'D', 'e', 'v', 'i', 'c', 'e' }; // Device Info: "VTS Device" + int32_t result; HdmiCecTx(handle, response, sizeof(response), &result); UT_LOG_INFO("Device Info response sent with result: %d\n", result); } -void handleOsdDisplay(int handle, unsigned char initiator, unsigned char destination, unsigned char *buf, int len) { - if (len > 2) { - UT_LOG_INFO("OSD Display message received: "); - for (int i = 2; i < len; i++) { - UT_LOG_INFO("%c", buf[i]); +static void handleOsdDisplay(uint8_t *buf, int32_t len) +{ + if (len > 3) + { + uint8_t buffer[HDMI_CEC_MAX_OSDNAME] = {0}; + uint8_t *temp = buffer; + UT_LOG_INFO("OSD Display Control: %d", buf[2]); + for (int32_t i = 3; i < len; i++) + { + int32_t len = 0; + len = snprintf(temp, HDMI_CEC_MAX_OSDNAME, "%c", buf[i]); + temp += len; } - UT_LOG_INFO("\n"); - } else { + UT_LOG_INFO("OSD Display message received: %s", buffer); + } + else + { UT_LOG_ERROR("OSD Display message received with insufficient data.\n"); } } -void handleGetOsdName(int handle, unsigned char initiator, unsigned char destination) { - unsigned char response[11] = { (destination << 4) | initiator, 0x47, 'V', 'T', 'S', ' ', 'D', 'e', 'v', 'i', 'c', 'e' }; // OSD Name: "VTS Device" - int result; +static void handleGiveOSDName(int32_t handle, uint8_t initiator, uint8_t destination) +{ + uint8_t response[] = { (destination << 4) | initiator, 0x47, 'V', 'T', 'S', ' ', 'D', 'e', 'v', 'i', 'c', 'e' }; // OSD Name: "VTS Device" + int32_t result; HdmiCecTx(handle, response, sizeof(response), &result); UT_LOG_INFO("OSD Name response sent with result: %d sourc/destination:0x%2x\n", result,response[0]); } -void handleGetPowerStatus(int handle, unsigned char initiator, unsigned char destination) { - unsigned char response[3] = { (destination << 4) | initiator, 0x90, 0x00 }; // Power Status: On (0x00) - int result; +static void handleSetOSDName(uint8_t *buf, int32_t len) +{ + if (len > 2) + { + uint8_t buffer[HDMI_CEC_MAX_OSDNAME] = {0}; + uint8_t *temp = buffer; + for (int32_t i = 2; i < len; i++) + { + int32_t len = 0; + len = snprintf(temp, HDMI_CEC_MAX_OSDNAME, "%c", buf[i]); + temp += len; + } + UT_LOG_INFO("OSD Name received: %s", buffer); + } + else + { + UT_LOG_ERROR("OSD Name message received with insufficient data.\n"); + } +} + +static void handleGivePowerStatus(int32_t handle, uint8_t initiator, uint8_t destination, HDMI_CEC_POWER_STATUS powerStatus) +{ + uint8_t response[] = { (destination << 4) | initiator, 0x90, powerStatus }; + int32_t result; HdmiCecTx(handle, response, sizeof(response), &result); UT_LOG_INFO("Power Status response sent with result: %d\n", result); } -void handleFeatureAbort(int handle, unsigned char initiator, unsigned char destination, unsigned char opcode, unsigned char reason) { - unsigned char response[4] = { (destination << 4) | initiator, 0x00, opcode, reason }; // Abort with reason - int result; +static void handleReportPowerStatus(uint8_t *buf, int32_t len) +{ + if (len >= 3) + { + UT_LOG_INFO("Power Status: %s\n", UT_Control_GetMapString(cecPowerStatus_mapTable, buf[2])); + } + else + { + UT_LOG_ERROR("Power Status received with insufficient data.\n"); + } +} + +static void handleFeatureAbort(uint8_t *buf, int32_t len) +{ + if (len >= 4) + { + UT_LOG_INFO("Feature Abort: Opcode: 0x%02X, Reason: %s\n", buf[2], UT_Control_GetMapString(cecFeatureAbortReason_mapTable, buf[3])); + } + else + { + UT_LOG_ERROR("Feature Abort received with insufficient data.\n"); + } +} + +static void sendFeatureAbort(int32_t handle, uint8_t initiator, uint8_t destination, uint8_t opcode, uint8_t reason) +{ + uint8_t response[] = { (destination << 4) | initiator, 0x00, opcode, reason }; // Abort with reason + int32_t result; HdmiCecTx(handle, response, sizeof(response), &result); UT_LOG_WARNING("Feature Abort sent for opcode: 0x%02X with reason: 0x%02X, result: %d\n", opcode, reason, result); } +static void handleSetMenuLanguage(uint8_t *buf, int32_t len) +{ + if (len >= 5) + { + UT_LOG_INFO("OSD Menu Language received: %c%c%c", buf[2], buf[2], buf[3]); + } + else + { + UT_LOG_ERROR("OSD Menu Language received with insufficient data"); + } +} + +static void handleCurrentLatency(int32_t handle, uint8_t *buf, int32_t len, uint8_t *pPhysicalAddress, uint8_t videoDelay, uint8_t audioDelay, uint8_t latency) +{ + uint8_t response[] = {(gLogicalAddress << 4) | gBroadcastAddress, 0xA8, buf[2], buf[3], videoDelay, latency, audioDelay}; + + int32_t result; + + if (len >= 4) + { + if (buf[2] == (pPhysicalAddress[3] << 4) | pPhysicalAddress[2] && + buf[3] == (pPhysicalAddress[1] << 4) | pPhysicalAddress[0]) + { + response[4] = videoDelay; + response[5] = latency; + response[6] = audioDelay; + + HdmiCecTx(handle, response, sizeof(response), &result); + } + + } + else + { + UT_LOG_ERROR("Latency query received with insufficient data.\n"); + } +} + +static void handleRequestActiveSource(int32_t handle, uint8_t *pPhysicalAddress) +{ + uint8_t response[] = { (gLogicalAddress << 4) | gBroadcastAddress, 0x82, (pPhysicalAddress[3] << 4) | pPhysicalAddress[2], (pPhysicalAddress[1] << 4 ) | pPhysicalAddress[0]}; + int32_t result; + HdmiCecTx(handle, response, sizeof(response), &result); + UT_LOG_INFO("Requested Active Sources response sent with result: %d\n", result); +} /** * @brief This function clears the stdin buffer. @@ -340,7 +465,7 @@ void handleFeatureAbort(int handle, unsigned char initiator, unsigned char desti */ static void readAndDiscardRestOfLine(FILE *in) { - int c; + int32_t c; while ((c = fgetc(in)) != EOF && c != '\n'); } @@ -355,69 +480,97 @@ static void readHex(int32_t *value) scanf("%x", value); readAndDiscardRestOfLine(stdin); } -void onRxDataReceived(int handle, void *callbackData, unsigned char *buf, int len) { - UT_LOG_INFO("In %s(IN: handle: [%d], IN: callbackData: [%p], IN: buf: [%p], IN: len: [%d])\n", __FUNCTION__, handle, callbackData, buf, len); - - if ((handle != 0) && (callbackData != NULL) && (len > 0)) { - UT_LOG_INFO("CEC Data Received\n"); - // Log each byte received in the buffer - for (int index = 0; index < len; index++) { - UT_LOG_INFO("Buffer at index [%d]: [0x%02X]\n", index, buf[index]); - } +static void onRxDataReceived(int32_t handle, void *callbackData, uint8_t *buf, int32_t len) +{ + UT_LOG_INFO("In %s(IN: handle: [%p], IN: callbackData: [%p], IN: buf: [%p], IN: len: [%d])\n", __FUNCTION__, handle, callbackData, buf, len); + if ((handle != 0) && (callbackData != NULL) && (len > 0)) + { // Parse the command - unsigned char initiator = (buf[0] >> 4) & 0xF; // Extract initiator address - unsigned char destination = buf[0] & 0xF; // Extract destination address - unsigned char opcode = buf[1]; // Command opcode + uint8_t initiator = (buf[0] >> 4) & 0xF; // Extract initiator address + uint8_t destination = buf[0] & 0xF; // Extract destination address + uint8_t opcode; // Command opcode + if( len == 1) + { + UT_LOG_INFO("Received Ping message Initiator: [0x%02X], Destination: [0x%02X]", initiator, destination); + UT_LOG_INFO("Out %s\n", __FUNCTION__); + return; + } - UT_LOG_INFO("Initiator: [0x%X], Destination: [0x%X], Opcode: [0x%02X]\n", initiator, destination, opcode); + opcode = buf[1]; + + UT_LOG_INFO("Initiator: [0x%02X], Destination: [0x%02X], Opcode: [0x%02X]", initiator, destination, opcode); + if (len > 2) + { + char buffer[HDMI_CEC_MAX_PAYLOAD] = {0}; + uint8_t *temp = buffer; + // Log each byte received in the buffer + for (int32_t index = 2; index < len; index++) + { + int32_t len = 0; + len = snprintf(temp, HDMI_CEC_MAX_PAYLOAD, "0x%02X, ", buf[index]); + temp += len; + } + buffer[strlen(buffer)-2] = '\0'; + UT_LOG_INFO("Payload: [%s]", buffer); + } // Handle each opcode with its corresponding function - switch (opcode) { - case 0x04: handleImageViewOn(handle, initiator, destination); break; - case 0x82: handleActiveSource(handle, initiator, destination, buf, len); break; - case 0x8E: handleGivePhysicalAddress(handle, initiator, destination); break; - case 0x87: handleDeviceVendorID(handle, initiator, destination); break; - case 0x84: handleReportPhysicalAddress(handle, initiator, destination); break; - case 0x90: handleReportPowerStatus(handle, initiator, destination); break; - case 0x9F: handleGiveCECVersion(handle, initiator, destination); break; - case 0x8C: handleGiveDeviceVendorID(handle, initiator, destination); break; - case 0x36: handleStandby(handle); break; - case 0xA0: handleGiveDeviceInfo(handle, initiator, destination); break; - case 0x64: handleOsdDisplay(handle, initiator, destination, buf, len); break; - case 0x46: handleGetOsdName(handle, initiator, destination); break; - case 0x8F: handleGetPowerStatus(handle, initiator, destination); break; - case 0x00: handleFeatureAbort(handle, initiator, destination, opcode, 0x04); break; + switch (opcode) + { + // CEC Commands no response sent + case 0x00: handleFeatureAbort(buf, len); break; + case 0x04: handleImageViewOn(); break; + case 0x32: handleSetMenuLanguage(buf, len); break; + case 0x82: handleActiveSource(buf, len); break; + case 0x84: handleReportPhysicalAddress(buf, len); break; + case 0x87: handleDeviceVendorID(buf, len); break; + case 0x36: handleStandby(); break; + case 0x64: handleOsdDisplay(buf, len); break; + case 0x90: handleReportPowerStatus(buf, len); break; + case 0x9E: handleCECVersion(buf, len); break; + case 0x47: handleSetOSDName(buf, len); break; + + // CEC commands with response + case 0x83: handleGivePhysicalAddress(handle, initiator, destination, gPhysicalAddressBytes, gDeviceType); break; + case 0x8F: handleGivePowerStatus(handle, initiator, destination, gPowerStatus); break; + case 0x8C: handleGiveDeviceVendorID(handle, initiator, destination, gDeviceVendorID); break; + case 0x9F: handleGetCECVersion(handle, initiator, destination, gCECVersion); break; + case 0x46: handleGiveOSDName(handle, initiator, destination); break; + + // Broadcasting CEC commands with response + case 0x85: handleRequestActiveSource(handle, gPhysicalAddressBytes); break; + case 0xA7: handleCurrentLatency(handle, buf, len, gPhysicalAddressBytes, gVideoDelay, gAudioDelay, gLatencyFlag); break; default: UT_LOG_WARNING("Unhandled opcode: [0x%02X]\n", opcode); - //handleFeatureAbort(handle, initiator, destination, opcode, 0x04); // Feature Abort: Unrecognized opcode + sendFeatureAbort(handle, initiator, destination, opcode, 0x04); // Feature Abort: Unrecognized opcode break; } // Clear the buffer after processing memset(buf, 0, len); - UT_LOG_INFO("Buffer cleared after processing.\n"); - - } else { + } + else + { // Log specific errors based on failed conditions - if (handle == 0) { + if (handle == 0) + { UT_LOG_ERROR("Error: Invalid handle.\n"); } - if (callbackData == NULL) { + if (callbackData == NULL) + { UT_LOG_ERROR("Error: Null callback data.\n"); } - if (len <= 0) { + if (len <= 0) + { UT_LOG_ERROR("Error: Invalid length.\n"); } } - cbFlag = 1; - UT_LOG_INFO("Out %s(OUT: cbFlag set to [1])\n", __FUNCTION__); + UT_LOG_INFO("Out %s\n", __FUNCTION__); } - - /** * @brief Initialization of the HAL CEC Module * @@ -436,27 +589,34 @@ void onRxDataReceived(int handle, void *callbackData, unsigned char *buf, int le * User or Automation tool should select the Test 1 to before running any test. * */ - void test_l3_hdmi_cec_sink_hal_Init(void) { - gTestID = 1; - HDMI_CEC_STATUS status = HDMI_CEC_IO_SUCCESS; + gTestID = 1; + HDMI_CEC_STATUS status = HDMI_CEC_IO_SUCCESS; - UT_LOG_INFO("In %s [%02d%03d]\n", __FUNCTION__, gTestGroup, gTestID); + UT_LOG_INFO("In %s [%02d%03d]\n", __FUNCTION__, gTestGroup, gTestID); - // Step 1: Call HdmiCecOpen() - UT_LOG_INFO("Calling HdmiCecOpen(IN:gHandle[0x%0X])",&gHandle); - status = HdmiCecOpen(&gHandle); - UT_LOG_INFO("Result HdmiCecSetRxCallback() cecError:[%s]",UT_Control_GetMapString(cecError_mapTable,status)); - assert(status == HDMI_CEC_IO_SUCCESS); + // Step 1: Call HdmiCecOpen() + UT_LOG_INFO("Calling HdmiCecOpen(OUT:handle:[])"); + status = HdmiCecOpen(&gHandle); + UT_LOG_INFO("Result HdmiCecOpen(OUT:handle:[0x%0X]) HDMI_CEC_STATUS:[%s]",gHandle, UT_Control_GetMapString(cecError_mapTable,status)); + assert(status == HDMI_CEC_IO_SUCCESS); + assert(gHandle != 0); - // Step 2: Register the call back - UT_LOG_INFO("Calling HdmiCecSetRxCallback(IN:handle[0x%0X],IN:cbfunc[0x%0X]",gHandle,onRxDataReceived); - status = HdmiCecSetRxCallback(gHandle, onRxDataReceived,(void*)0xABABABAB); - UT_LOG_INFO("Result HdmiCecSetRxCallback() cecError:[%s]",UT_Control_GetMapString(cecError_mapTable,status)); - assert(status == HDMI_CEC_IO_SUCCESS); + // Step 2: Register the call back + UT_LOG_INFO("Calling HdmiCecSetRxCallback(IN:handle:[0x%0X], IN:cbfunc:[0x%0X])",gHandle, onRxDataReceived); + status = HdmiCecSetRxCallback(gHandle, onRxDataReceived,(void*)0xABABABAB); + UT_LOG_INFO("Result HdmiCecSetRxCallback(IN:handle:[0x%0X], IN:cbfunc:[0x%0X]) HDMI_CEC_STATUS:[%s]",gHandle,onRxDataReceived, UT_Control_GetMapString(cecError_mapTable,status)); + assert(status == HDMI_CEC_IO_SUCCESS); + + UT_LOG_INFO("Calling HdmiCecGetPhysicalAddress(IN:handle:[0x%0X], OUT:physicalAddress:[])", gHandle); + status = HdmiCecGetPhysicalAddress(gHandle, &gPhysicalAddress); + UT_LOG_INFO("Result HdmiCecGetPhysicalAddress(IN:handle:[0x%0X], OUT:physicalAddress:[%d]) HDMI_CEC_STATUS:[%s]", gHandle, gPhysicalAddress, UT_Control_GetMapString(cecError_mapTable,status)); + assert(status == HDMI_CEC_IO_SUCCESS); - UT_LOG_INFO("Out %s\n", __FUNCTION__); + gPhysicalAddressBytes = (uint8_t*)&gPhysicalAddress; + + UT_LOG_INFO("Out %s\n", __FUNCTION__); } /** @@ -489,23 +649,29 @@ void test_l3_hdmi_cec_sink_hal_AddLogicalAddress(void) HDMI_CEC_STATUS status = HDMI_CEC_IO_SUCCESS; - int logicalAddress = -1; + int32_t logicalAddress = -1; + int32_t getLogicalAddress = -1; - UT_LOG_MENU_INFO("----------------------------------------------------------"); - UT_LOG_MENU_INFO("\t \tEnter Logical Address: "); - readHex(&logicalAddress;) - UT_LOG_MENU_INFO("----------------------------------------------------------"); + UT_LOG_MENU_INFO("Enter Logical Address:"); + readInt(&logicalAddress); /* Check that logical address should be valid one */ - UT_LOG_INFO("Calling HdmiCecAddLogicalAddress(IN:handle:[0x%0X], IN:logicalAddress:[%d]",gHandle,logicalAddress); - status = HdmiCecAddLogicalAddress(gHandle,logicalAddress ); - UT_LOG_INFO("HdmiCecAddLogicalAddress (IN:handle:[0x%0X], IN:logicalAddress:[%d]), status[%d]",gHandle,logicalAddress,UT_Control_GetMapString(cecError_mapTable,status)); + UT_LOG_INFO("Calling HdmiCecAddLogicalAddress(IN:handle:[0x%0X], IN:logicalAddress:[%d]", gHandle, logicalAddress); + status = HdmiCecAddLogicalAddress(gHandle, logicalAddress); + UT_LOG_INFO("Result HdmiCecAddLogicalAddress (IN:handle:[0x%0X], IN:logicalAddress:[%d]) HDMI_CEC_STATUS[%s]",gHandle,logicalAddress,UT_Control_GetMapString(cecError_mapTable,status)); + assert(status == HDMI_CEC_IO_SUCCESS); + + UT_LOG_INFO("Calling HdmiCecGetLogicalAddress(IN:handle:[0x%0X], OUT:logicalAddress:[])", gHandle); + status = HdmiCecGetLogicalAddress(gHandle, &getLogicalAddress); + UT_LOG_INFO("Result HdmiCecGetLogicalAddress(IN:handle:[0x%0X], OUT:logicalAddress:[%d]) HDMI_CEC_STATUS:[%s])", gHandle, getLogicalAddress, UT_Control_GetMapString(cecError_mapTable,status)); assert(status == HDMI_CEC_IO_SUCCESS); + assert(logicalAddress == getLogicalAddress); + + gLogicalAddress = getLogicalAddress; UT_LOG_INFO("Out %s\n", __FUNCTION__); } - /** * @brief Test to get the logical address * @@ -531,18 +697,16 @@ void test_l3_hdmi_cec_sink_hal_GetLogicalAddress(void) UT_LOG_INFO("In %s [%02d%03d]\n", __FUNCTION__, gTestGroup, gTestID); HDMI_CEC_STATUS status = HDMI_CEC_IO_SUCCESS; - int logicalAddress = -1; + int32_t logicalAddress = -1; - UT_LOG_INFO("Calling HdmiCecGetLogicalAddress(IN: handle: [0x%0X], OUT: logicalAddress: [])", gHandle); + UT_LOG_INFO("Calling HdmiCecGetLogicalAddress(IN:handle:[0x%0X], OUT:logicalAddress:[])", gHandle); status = HdmiCecGetLogicalAddress(gHandle, &logicalAddress); - - UT_LOG_INFO("HdmiCecGetLogicalAddress(IN: handle: [0x%0X], OUT: logicalAddress: [%d]), status: [%d])", gHandle, logicalAddress, UT_Control_GetMapString(cecError_mapTable,status)); + UT_LOG_INFO("Result HdmiCecGetLogicalAddress(IN:handle:[0x%0X], OUT:logicalAddress:[%d]) HDMI_CEC_STATUS:[%s])", gHandle, logicalAddress, UT_Control_GetMapString(cecError_mapTable,status)); assert(status == HDMI_CEC_IO_SUCCESS); + UT_LOG_INFO("Out %s\n", __FUNCTION__); } - - /** * @brief Test provides a scope to Transmit the CEC Command * @@ -559,7 +723,7 @@ void test_l3_hdmi_cec_sink_hal_GetLogicalAddress(void) * **Dependencies:** None@n * * **User Interaction:** @n -* User or Automation tool should select the Test 4 and shall provide the necessary source and destination logical address, +* User or Automation tool should select the Test 4 and shall provide the necessary source and destination logical address, * CEC command, data lenght and data. * */ @@ -567,123 +731,63 @@ void test_l3_hdmi_cec_sink_hal_TransmitHdmiCecCommand(void) { gTestID = 4; UT_LOG_INFO("In %s [%02d%03d]\n", __FUNCTION__, gTestGroup, gTestID); - int sourceLogicalAddress = -1; - int destinationLogicalAddress = -1; - unsigned char buf[16] = {0}; - int len = 0, cecCommand = 0; - int result; + int32_t sourceLogicalAddress = gLogicalAddress; + int32_t destinationLogicalAddress = -1; + uint8_t buf[16] = {0}; + int32_t len = 0, cecCommand = 0; + int32_t result; const char* commandName; - int expectedDataLength; + int32_t expectedDataLength; - // Reading inputs from the user or test framework - UT_LOG_MENU_INFO("----------------------------------------------------------"); - UT_LOG_MENU_INFO("\t \tEnter a valid Source Logical Address:"); - readHex(&sourceLogicalAddress); - UT_LOG_MENU_INFO("----------------------------------------------------------"); - - UT_LOG_MENU_INFO("----------------------------------------------------------"); - UT_LOG_MENU_INFO("\t \tEnter a valid Destination Logical Address: "); - readHex(&destinationLogicalAddress); - UT_LOG_MENU_INFO("----------------------------------------------------------"); + assert(sourceLogicalAddress != -1); + // Reading inputs from the user or test framework + UT_LOG_MENU_INFO("Enter a valid Destination Logical Address: "); + readInt(&destinationLogicalAddress); - UT_LOG_MENU_INFO("----------------------------------------------------------"); - UT_LOG_MENU_INFO("\t \tEnter CEC Command (in hex): "); + UT_LOG_MENU_INFO("Enter CEC Command (in hex): "); readHex(&cecCommand); - UT_LOG_MENU_INFO("----------------------------------------------------------"); // Validate the CEC command and get the expected data length - if (getCecCommandInfo(cecCommand, &commandName, &expectedDataLength) != 0) { + if (getCecCommandInfo(cecCommand, &commandName, &expectedDataLength) != 0) + { // Command not found in the map, prompt the user for additional information UT_LOG_WARNING("CEC command 0x%02X is not recognized. It might be a vendor-specific command.", cecCommand); - UT_LOG_MENU_INFO("----------------------------------------------------------"); - UT_LOG_MENU_INFO("\t \tPlease enter the number of data bytes for the CEC command: "); + UT_LOG_MENU_INFO("Enter the number of data bytes for the CEC command:"); readInt(&expectedDataLength); - UT_LOG_MENU_INFO("----------------------------------------------------------"); commandName = "Vendor Specific Command"; - } else { + } + else + { UT_LOG_INFO("CEC Command: %s (0x%02X), expects %d data byte(s)", commandName, cecCommand, expectedDataLength); } // If the command has data bytes, prompt for them - if (expectedDataLength > 0) { - for (int i = 0; i < expectedDataLength; i++) { - UT_LOG_MENU_INFO("\t \tEnter Databyte[%d] (in hex):", i); - readHex(&buf[i + 2]); // +2 to account for the first two bytes + if (expectedDataLength > 0) + { + for (int32_t i = 0; i < expectedDataLength; i++) + { + int32_t byte_data; + UT_LOG_MENU_INFO("Enter Databyte[%d] (in hex):", i); + readHex(&byte_data); + buf[i + 2] = (uint8_t)byte_data; // +2 to account for the first two bytes } } // Building the CEC message - buf[0] = (unsigned char)((sourceLogicalAddress << 4) | (destinationLogicalAddress & 0x0F)); - buf[1] = (unsigned char)cecCommand; + buf[0] = (uint8_t)((sourceLogicalAddress << 4) | (destinationLogicalAddress & 0x0F)); + buf[1] = (uint8_t)cecCommand; len = expectedDataLength + 2; // 1 byte for logical addresses, 1 byte for CEC Command // Logging the transmission attempt - UT_LOG_INFO("Calling HdmiCecTx(IN: handle: [0x%0X], IN: message length: [%d], IN: message data: [", gHandle, len); - for (int i = 0; i < len; i++) { - printf(" %02X", buf[i]); - } - printf(" ])"); - - // Assume HdmiCecTx is a function to send the CEC command - int status = HdmiCecTx(gHandle, buf, len, &result); - UT_LOG_INFO("HdmiCecTx(IN: handle: [0x%0X], IN: length: [%d], result: [%d], status:[%d])", gHandle, len, result, UT_Control_GetMapString(cecError_mapTable,status)); - - //assert((result == HDMI_CEC_IO_SENT_BUT_NOT_ACKD) && (status == HDMI_CEC_IO_SUCCESS)); - - // Optional delay after sending the command - sleep(5); - - UT_LOG_INFO("Out %s\n", __FUNCTION__); -} - -/** -* @brief Test to Receive the CEC Command -* -* This test provides an interface to check whether the CEC has received any frames or not. -* -* **Test Group ID:** 02@n -* -* **Test Case ID:** 005@n -* -* **Pre-Conditions:** @n -* HDMI-CEC Module should be intialized through Test 1 before calling this test. -* -* **Dependencies:** @n -* Depends on the external device to send a CEC Frames with necessary command and data. -* -* **User Interaction:** @n -* User or Automation tool should select the Test 5 and make sure that the CEC Frames has been sent from an external -* device connected in the network. -* -*/ -void test_l3_hdmi_cec_sink_hal_ReceiveHdmiCecCommand(void) -{ - gTestID = 5; - UT_LOG_INFO("In %s [%02d%03d]\n", __FUNCTION__, gTestGroup, gTestID); - - UT_LOG_INFO("Waiting for HDMI CEC command (timeout: %d seconds)", REPLY_TIMEOUT); - - sleep(REPLY_TIMEOUT); // Wait for a reply - - if (cbFlag != 1) - { - UT_LOG_ERROR("HdmiCecRx failed to receive data (IN: expected callback flag: [1], OUT: actual callback flag: [%d])", cbFlag); - assert(cbFlag == 1); - } - else - { - UT_LOG_INFO("HdmiCecRx successfully received data (OUT: callback flag: [%d])", cbFlag); - } - - // Resetting callback flag for future tests - cbFlag = 0; + UT_LOG_INFO("Calling HdmiCecTx(IN:handle:[0x%0X], IN:buf:[%p], IN:len:[%d], OUT:result:[])", gHandle, buf, len); + int32_t status = HdmiCecTx(gHandle, buf, len, &result); + UT_LOG_INFO("Result HdmiCecTx(IN:handle:[0x%0X], IN:buf:[%p], IN:len:[%d], OUT:result:[%d]) HDMI_CEC_STATUS:[%s]", gHandle, buf, len, result, UT_Control_GetMapString(cecError_mapTable,status)); UT_LOG_INFO("Out %s\n", __FUNCTION__); } - /** * @brief Test to get the physical address * @@ -699,7 +803,7 @@ void test_l3_hdmi_cec_sink_hal_ReceiveHdmiCecCommand(void) * **Dependencies:** None@n * * **User Interaction:** @n -* User or Automation tool should select the Test 6 to read the physical address of the device +* User or Automation tool should select the Test 6 to read the physical address of the device * device connected in the network. * */ @@ -709,22 +813,20 @@ void test_l3_hdmi_cec_sink_hal_GetPhysicalAddress(void) UT_LOG_INFO("In %s [%02d%03d]\n", __FUNCTION__, gTestGroup, gTestID); HDMI_CEC_STATUS status = HDMI_CEC_IO_SUCCESS; - int physicalAddress = -1; - - UT_LOG_INFO("Calling HdmiCecGetPhysicalAddress(IN: handle: [0x%0X], OUT: physicalAddress: [uninitialized])", gHandle); + uint32_t physicalAddress = -1; + UT_LOG_INFO("Calling HdmiCecGetPhysicalAddress(IN:handle:[0x%0X], OUT:physicalAddress:[])", gHandle); status = HdmiCecGetPhysicalAddress(gHandle, &physicalAddress); - UT_LOG_INFO("HdmiCecGetPhysicalAddress(IN: handle: [0x%0X], physicalAddress: [%d]), status:[%d]", gHandle, physicalAddress,UT_Control_GetMapString(cecError_mapTable,status)); + UT_LOG_INFO("Result HdmiCecGetPhysicalAddress(IN:handle:[0x%0X], OUT:physicalAddress:[%d]) HDMI_CEC_STATUS:[%s]", gHandle, physicalAddress, UT_Control_GetMapString(cecError_mapTable,status)); assert(status == HDMI_CEC_IO_SUCCESS); UT_LOG_INFO("Out %s\n", __FUNCTION__); } - /** * @brief Test to Remove logical address * -* This test provides a scope to remove the logical address of the device. HAL API to set +* This test provides a scope to remove the logical address of the device. HAL API to set * to default logical addres 0xF once the logical address is removed. * * **Test Group ID:** 02@n @@ -746,20 +848,24 @@ void test_l3_hdmi_cec_sink_hal_RemoveLogicalAddress(void) UT_LOG_INFO("In %s [%02d%03d]\n", __FUNCTION__, gTestGroup, gTestID); HDMI_CEC_STATUS status = HDMI_CEC_IO_SUCCESS; - int logicalAddress = -1; + int32_t logicalAddress = gLogicalAddress; + int32_t getLogicalAddress = 0; - UT_LOG_MENU_INFO("----------------------------------------------------------"); - UT_LOG_MENU_INFO("\t \tEnter Logical Address to Remove: "); - readHex(&logicalAddress); - UT_LOG_MENU_INFO("----------------------------------------------------------"); + assert(logicalAddress != -1); - UT_LOG_INFO("Calling HdmiCecRemoveLogicalAddress(IN: handle: [0x%0X], IN: logicalAddress: [%d])", gHandle, logicalAddress); - - // Invoke the API HdmiCecRemoveLogicalAddress + UT_LOG_INFO("Calling HdmiCecRemoveLogicalAddress(IN:handle:[0x%0X], IN:logicalAddress:[%d])", gHandle, logicalAddress); status = HdmiCecRemoveLogicalAddress(gHandle, logicalAddress); - UT_LOG_INFO("HdmiCecRemoveLogicalAddress(IN: handle: [0x%0X], IN: logicalAddress: [%d], OUT: status: [%d])", gHandle, logicalAddress, UT_Control_GetMapString(cecError_mapTable,status)); + UT_LOG_INFO("Result HdmiCecRemoveLogicalAddress(IN:handle:[0x%0X], IN:logicalAddress:[%d]) HDMI_CEC_STATUS:[%s])", gHandle, logicalAddress, UT_Control_GetMapString(cecError_mapTable,status)); + assert(status == HDMI_CEC_IO_SUCCESS); + + UT_LOG_INFO("Calling HdmiCecGetLogicalAddress(IN:handle:[0x%0X], OUT:logicalAddress:[])", gHandle); + status = HdmiCecGetLogicalAddress(gHandle, &getLogicalAddress); + UT_LOG_INFO("Result HdmiCecGetLogicalAddress(IN:handle:[0x%0X], OUT:logicalAddress:[%d]) HDMI_CEC_STATUS:[%s])", gHandle, getLogicalAddress, UT_Control_GetMapString(cecError_mapTable,status)); assert(status == HDMI_CEC_IO_SUCCESS); - + assert(getLogicalAddress == -1); + + gLogicalAddress = -1; + UT_LOG_INFO("Out %s\n", __FUNCTION__); } /** @@ -780,22 +886,19 @@ void test_l3_hdmi_cec_sink_hal_RemoveLogicalAddress(void) * User or Automation tool should select the Test 8 to close the created HDMI CEC handle. * */ -void test_l2_hdmi_cec_sink_hal_Close(void) +void test_l3_hdmi_cec_sink_hal_Close(void) { gTestID = 8; HDMI_CEC_STATUS status; UT_LOG_INFO("In %s [%02d%03d]\n", __FUNCTION__, gTestGroup, gTestID); - // Step 1: Log the pre-requisite action - UT_LOG_INFO("Calling HdmiCecClose(IN: handle: [0x%0X])", gHandle); - - // Step 2: Call the API to close the HDMI CEC handle + UT_LOG_INFO("Calling HdmiCecClose(IN:handle:[0x%0X])", gHandle); status = HdmiCecClose(gHandle); - UT_LOG_INFO("HdmiCecClose(IN: handle: [0x%0X]) status: [%d]", gHandle, status); + UT_LOG_INFO("Result HdmiCecClose(IN:handle:[0x%0X]) HDMI_CEC_STATUS:[%s]", gHandle, UT_Control_GetMapString(cecError_mapTable,status)); assert(status == HDMI_CEC_IO_SUCCESS); + gHandle = 0; - // Step 4: Log the end of the function UT_LOG_INFO("Out %s\n", __FUNCTION__); } @@ -804,9 +907,9 @@ static UT_test_suite_t * pSuite = NULL; /** * @brief Register the main tests for this module * - * @return int - 0 on success, otherwise failure + * @return int32_t - 0 on success, otherwise failure */ -int test_register_hdmicec_hal_sink_l3_tests(void) +int32_t test_register_hdmicec_hal_sink_l3_tests(void) { // Create the test suite pSuite = UT_add_suite("[L3 HDMICEC Sink Functions] ", NULL, NULL); @@ -816,14 +919,13 @@ int test_register_hdmicec_hal_sink_l3_tests(void) } // List of test function names and strings - UT_add_test( pSuite, "L3_Init_HdmiCec", test_l3_hdmi_cec_sink_hal_Init); - UT_add_test( pSuite, "L3_AddLogicalAddress", test_l3_hdmi_cec_sink_hal_AddLogicalAddress); - UT_add_test( pSuite, "L3_GetLogicalAddress", test_l3_hdmi_cec_sink_hal_GetLogicalAddress); - UT_add_test( pSuite, "L3_TransmitCecCommand", test_l3_hdmi_cec_sink_hal_TransmitHdmiCecCommand); - UT_add_test( pSuite, "L3_ReceiveCecCommand", test_l3_hdmi_cec_sink_hal_ReceiveHdmiCecCommand); - UT_add_test( pSuite, "L3_GetPhyiscalAddress", test_l3_hdmi_cec_sink_hal_GetPhysicalAddress); - UT_add_test( pSuite, "L3_RemoveLogicalAddressHdmiCec_Sink", test_l3_hdmi_cec_sink_hal_RemoveLogicalAddress); - UT_add_test( pSuite, "L3_Close_HdmiCec_Sink", test_l2_hdmi_cec_sink_hal_Close); + UT_add_test( pSuite, "Init HDMI CEC", test_l3_hdmi_cec_sink_hal_Init); + UT_add_test( pSuite, "Add Logical Address", test_l3_hdmi_cec_sink_hal_AddLogicalAddress); + UT_add_test( pSuite, "Get Logical Address", test_l3_hdmi_cec_sink_hal_GetLogicalAddress); + UT_add_test( pSuite, "Transmit CEC Command", test_l3_hdmi_cec_sink_hal_TransmitHdmiCecCommand); + UT_add_test( pSuite, "Get Phyiscal Address", test_l3_hdmi_cec_sink_hal_GetPhysicalAddress); + UT_add_test( pSuite, "Remove Logical Address", test_l3_hdmi_cec_sink_hal_RemoveLogicalAddress); + UT_add_test( pSuite, "Close HDMI CEC", test_l3_hdmi_cec_sink_hal_Close); return 0; } From 079741ed606aeb177ca63c59d2285c90600b57b9 Mon Sep 17 00:00:00 2001 From: bhanucbp <141142298+bhanucbp@users.noreply.github.com> Date: Wed, 11 Dec 2024 21:23:16 +0000 Subject: [PATCH 24/40] gh #44 L3 test case development Updated c test and python code to read the commands from yaml file --- host/tests/classes/hdmiCEC.py | 76 ++- host/tests/classes/hdmiCEC_testConfig.yml | 2 +- .../hdmiCEC_L3_Tests/hdmiCECHelperClass.py | 5 + .../hdmiCEC_L3_Tests/hdmiCECTestCommands.yml | 85 +++- .../hdmiCEC_test01_TransmitCECCommands.py | 35 +- .../hdmiCEC_test02_ReceiveCECCommands.py | 95 +++- profiles/sink/sink_hdmiCEC.yml | 135 +++++ src/test_l3_hdmi_cec_sink_driver.c | 480 +++++++----------- 8 files changed, 557 insertions(+), 356 deletions(-) diff --git a/host/tests/classes/hdmiCEC.py b/host/tests/classes/hdmiCEC.py index a7c3ab4..9cf3c24 100644 --- a/host/tests/classes/hdmiCEC.py +++ b/host/tests/classes/hdmiCEC.py @@ -21,12 +21,9 @@ # * #* ****************************************************************************** -import subprocess +import re import os import sys -from enum import Enum, auto -import re -import yaml # Add parent directory to the system path for module imports dir_path = os.path.dirname(os.path.realpath(__file__)) @@ -119,13 +116,13 @@ def terminate(self): """ result = self.utMenu.select(self.testSuite, "Close HDMI CEC") - def addLogicalAddress(self, logicalAddress:int): + def addLogicalAddress(self, logicalAddress:str='0'): """ Adding the logical address of a specific device. For now Sink to support only the logical address 0. Args: - logicalAddress (int): The Logical address of the DUT. This will be fixed to zero for a sink device for now. + logicalAddress (str): The Logical address of the DUT. This will be fixed to zero for a sink device for now. Returns: None @@ -134,7 +131,7 @@ def addLogicalAddress(self, logicalAddress:int): { "query_type": "direct", "query": "Enter Logical Address:", - "input": str(logicalAddress) + "input": logicalAddress } ] result = self.utMenu.select(self.testSuite, "Add Logical Address", promptWithAnswers) @@ -162,7 +159,7 @@ def getLogicalAddress(self): int: Logical address of the device. """ result = self.utMenu.select( self.testSuite, "Get Logical Address") - connectionStatusPattern = r"Result HdmiCecGetLogicalAddress\(IN:handle:[.*\], OUT:logicalAddress:[.*\]) HDMI_CEC_STATUS:[.*\])" + connectionStatusPattern = r"Result HdmiCecGetLogicalAddress\(IN:handle:\[0x[0-9A-F]+\], OUT:logicalAddress:\[([0-9A-Fa-f]+)\]\)" logicalAddress = self.searchPattern(result, connectionStatusPattern) return logicalAddress @@ -183,7 +180,7 @@ def getPhysicalAddress(self): return physicalAddress - def cecTransmitCmd(self, destLogicalAddress:int, cecCommand:int, cecData:list=None): + def cecTransmitCmd(self, destLogicalAddress:str, cecCommand:str, cecData:list=None): """ Transmit/Broadcast the CEC command and data to the respective destination. @@ -198,12 +195,12 @@ def cecTransmitCmd(self, destLogicalAddress:int, cecCommand:int, cecData:list=No { "query_type": "direct", "query": "Enter a valid Destination Logical Address:", - "input": str(destLogicalAddress) + "input": destLogicalAddress }, { "query_type": "direct", "query": "Enter CEC Command (in hex):", - "input": str(cecCommand) + "input": cecCommand }, ] @@ -218,6 +215,63 @@ def cecTransmitCmd(self, destLogicalAddress:int, cecCommand:int, cecData:list=No result = self.utMenu.select( self.testSuite, "Transmit CEC Command",promptWithAnswers) + def readCallbackDetails (self): + """ + Parses the callback logs from the device. + + Args: + None. + + Returns: + dict: A dictionary with two keys: + - "Received": A list of dictionaries containing details about received opcodes. + - "Response": A list of dictionaries containing details about sent response opcodes. + Each dictionary contains the following keys: + - "Opcode" (str): The opcode value in hexadecimal. + - "Description" (str): A textual description of the opcode. + - "Initiator" (str): The initiator address in hexadecimal. + - "Destination" (str): The destination address in hexadecimal. + - "Data" (list): The data associated with the opcode. + """ + result = { + "Received": [], + "Response": [] + } + callbackLogs = self.testSession.read_all() + + received_pattern = re.compile( + r"Received Opcode: \[([^\]]+)\] \[([^\]]+)\] Initiator: \[([^\]]+)\], Destination: \[([^\]]+)\] Data: \[(.*?)\]" + ) + sent_pattern = re.compile( + r"Sent Response Opcode: \[([^\]]+)\] \[([^\]]+)\] Initiator: \[([^\]]+)\], Destination: \[([^\]]+)\] Data: \[(.*?)\]" + ) + + def parse_data_field(data_field): + # Split the data field into an array of hex values + return ["0x" + value.strip() for value in data_field.split(":")] + + for match in received_pattern.finditer(callbackLogs): + opcode, description, initiator, destination, data = match.groups() + result["Received"].append({ + "Opcode": opcode, + "Description": description, + "Initiator": initiator, + "Destination": destination, + "Data": parse_data_field(data) + }) + + for match in sent_pattern.finditer(callbackLogs): + opcode, description, initiator, destination, data = match.groups() + result["Response"].append({ + "Opcode": opcode, + "Description": description, + "Initiator": initiator, + "Destination": destination, + "Data": parse_data_field(data) + }) + + return result + def __del__(self): """ Cleans up and de-initializes the hdmi cec helper by stopping the test menu. diff --git a/host/tests/classes/hdmiCEC_testConfig.yml b/host/tests/classes/hdmiCEC_testConfig.yml index 40ac032..00f7ba5 100644 --- a/host/tests/classes/hdmiCEC_testConfig.yml +++ b/host/tests/classes/hdmiCEC_testConfig.yml @@ -26,7 +26,7 @@ hdmicec: #List of artifacts folders, test class copies the content of folder to the target device workspace - "../../../bin/" # exectute command, this will appended with the target device workspace path - execute: "run.sh" + execute: "run.sh -p sink_hdmiCEC.yml" type: UT-C # C (UT-C Cunit) / C++ (UT-G (g++ ut-core gtest backend)) suites: 0: diff --git a/host/tests/hdmiCEC_L3_Tests/hdmiCECHelperClass.py b/host/tests/hdmiCEC_L3_Tests/hdmiCECHelperClass.py index 478f421..abba8d4 100755 --- a/host/tests/hdmiCEC_L3_Tests/hdmiCECHelperClass.py +++ b/host/tests/hdmiCEC_L3_Tests/hdmiCECHelperClass.py @@ -69,6 +69,11 @@ def __init__(self, testName:str, qcId:str, log:logModule=None ): self.targetWorkspace = self.cpe.get("target_directory") self.targetWorkspace = os.path.join(self.targetWorkspace, self.moduleName) + self.testCECCommands = os.path.join(dir_path, "hdmiCECTestCommands.yml") + hdmicec = ConfigRead(self.testCECCommands, self.moduleName) + self.cecCommands = hdmicec.fields.get(self.testName) + self.hdmiCECController = self.dut.hdmiCECController + # def testDownloadAssets(self): # """ # Downloads the test artifacts listed in the test setup configuration. diff --git a/host/tests/hdmiCEC_L3_Tests/hdmiCECTestCommands.yml b/host/tests/hdmiCEC_L3_Tests/hdmiCECTestCommands.yml index ecf469e..7b62b96 100644 --- a/host/tests/hdmiCEC_L3_Tests/hdmiCECTestCommands.yml +++ b/host/tests/hdmiCEC_L3_Tests/hdmiCECTestCommands.yml @@ -1,15 +1,72 @@ -hdmiCEC: +hdmicec: test01_TransmitCECCommands: - - command: "0x04" # Image View on - payload: - responses: - - command: "0x36" # Standby - payload: - responses: - - command: "0x9F" # Get CEC version - payload: - responses: - - type: "Get CEC Version" - loop_devices: false # Apply this response to all devices in the device map - payload: "" # Response pattern with placeholders - description: "Device request for CEC version" \ No newline at end of file + - command: "0x82" # Active Soruce + payload: ["0x00", "0x00"] + type: "Broadcast" + - command: "0x90" # "Report power status + payload: ["0x00"] + type: "Direct" + response: null + - command: "0x47" # Give OSD Name + payload: ['0x52', '0x44', '0x4b', '0x20', '0x56', '0x54', '0x53', '0x20', '0x44', '0x65', '0x76', '0x69', '0x63', '0x65'] + type: "Direct" + response: null + test02_ReceiveCECCommands: + - command: "0x04" # Image View on + payload: + type: "Direct" + response: null + - command: "0x85" # Request Active source + payload: + type: "Broadcast" + response: + type: "Broadcast" + command: "0x82" + update_payload: true + payload: ["0x00", "0x00"] + description: "Active Soruce" + - command: "0x91" # Get Menu Language + payload: + type: "Direct" + response: + type: "Broadcast" + command: "0x32" + update_payload: false + payload: ["0x65", "0x6E", "0x67"] + description: "Set Menu Language" + - command: "0x8C" # Give Vendor ID + payload: + type: "Direct" + response: + type: "Broadcast" + command: "0x87" + update_payload: false + payload: ["0x00", "0x00","0x01"] + description: "Device Vendor Id" + - command: "0x8F" # Give power status + payload: + type: "Direct" + response: + type: "Direct" + command: "0x90" + update_payload: false + payload: ["0x00"] + description: "Report power status" + - command: "0x9F" # Get CEC version + payload: + type: "Direct" + response: + type: "Direct" + command: "0x9E" + update_payload: false + payload: ["0x05"] + description: "Device request for CEC version" + - command: "0x46" # Give OSD Name + payload: + type: "Direct" + response: + type: "Direct" + command: "0x47" + update_payload: false + payload: ['0x52', '0x44', '0x4b', '0x20', '0x56', '0x54', '0x53', '0x20', '0x44', '0x65', '0x76', '0x69', '0x63', '0x65'] + description: "Device request OSD name" diff --git a/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test01_TransmitCECCommands.py b/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test01_TransmitCECCommands.py index fb4c648..12488c2 100755 --- a/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test01_TransmitCECCommands.py +++ b/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test01_TransmitCECCommands.py @@ -50,11 +50,8 @@ def __init__(self, log:logModule=None): # Class variables self.testName = "test01_TransmitCECCommands" self.qcID = '1' - self.sourceLogicalAddress = 0 - - self.testCECCommands = os.path.join(dir_path, "hdmiCECTestCommands.yml") - hdmicec = ConfigRead(self.testCECCommands, "hdmiCEC") - self.cecCommands = hdmicec.fields.get(self.testName) + self.tvLogicalAddress = '0' + self.broadcastAddress = 'f' super().__init__(self.testName, self.qcID, log) @@ -74,29 +71,41 @@ def testFunction(self): self.testhdmiCEC.initialise() # Add the logical Address. - self.testhdmiCEC.addLogicalAddress(self.sourceLogicalAddress) + self.testhdmiCEC.addLogicalAddress(self.tvLogicalAddress) + + # Get the logical Address. + deviceLogicalAddress = self.testhdmiCEC.getLogicalAddress() - self.cecDevices = self.cecAdapter.listDevices() + self.cecDevices = self.hdmiCECController.listDevices() + finalResult = True for device in self.cecDevices: logicalAddress = device["logical address"] # To bypass sending the message to TV - if logicalAddress == 0 or logicalAddress == 14: + if logicalAddress == '0' or logicalAddress == 'f': continue for command in self.cecCommands: + result = False cec = command.get("command") payload = command.get("payload") + type = command.get("type") + + destinationLogicalAddress = logicalAddress + if type == "Broadcast": + destinationLogicalAddress = self.broadcastAddress # Transmit Standby command to a specific destination address - self.testhdmiCEC.cecTransmitCmd(logicalAddress, cec, payload) + self.testhdmiCEC.cecTransmitCmd(destinationLogicalAddress, cec, payload) + + self.log.stepStart(f'HdmiCecTx Source: {deviceLogicalAddress} Destination: {destinationLogicalAddress} CEC OPCode: {cec} Payload: {payload}') - self.log.stepStart(f'HdmiCecTx Source: {self.sourceLogicalAddress} Destination: {logicalAddress} CEC OPCode: {cec} Payload: {payload}') + result = self.hdmiCECController.checkTransmitStatus(deviceLogicalAddress, destinationLogicalAddress, cec, payload) - result = self.cecAdapter.checkTransmitStatus(self.sourceLogicalAddress, logicalAddress, cec, payload) + self.log.stepResult(result, f'HdmiCecTx Source: {deviceLogicalAddress} Destination: {destinationLogicalAddress} CEC OPCode: {cec} Payload: {payload}') - self.log.stepResult(result, f'HdmiCecTx Source: {self.sourceLogicalAddress} Destination: {logicalAddress} CEC OPCode: {cec} Payload: {payload}') + finalResult &= result # Remove the Logical Address self.testhdmiCEC.removeLogicalAddress() @@ -104,7 +113,7 @@ def testFunction(self): # Terminate dsAudio Module self.testhdmiCEC.terminate() - return result + return finalResult if __name__ == '__main__': summerLogName = os.path.splitext(os.path.basename(__file__))[0] + "_summery" diff --git a/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test02_ReceiveCECCommands.py b/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test02_ReceiveCECCommands.py index cec862b..329e4de 100644 --- a/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test02_ReceiveCECCommands.py +++ b/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test02_ReceiveCECCommands.py @@ -50,14 +50,37 @@ def __init__(self, log:logModule=None): # Class variables self.testName = "test02_ReceiveCECCommands" self.qcID = '2' - self.sourceLogicalAddress = 0 - - self.testCECCommands = os.path.join(dir_path, "hdmiCECTestCommands.yml") - hdmicec = ConfigRead(self.testCECCommands, "hdmiCEC") - self.cecCommands = hdmicec.fields.get(self.testName) + self.tvLogicalAddress = '0' + self.broadcastAddress = 'f' super().__init__(self.testName, self.qcID, log) + def testVerifyReceivedData(self, callbackData:dict, initiatorLogicalAddress:int, destinationLogicalAddress:int, opCode:str, payload:list): + """ + Verifies the received callback data. + + Args: + callbackData(dict): callback data received + initiatorLogicalAddress(int): Initiator logical address + destinationLogicalAddress(int): Destination logical address + opCode (str): opcode sent + payload (str): Payload Sent + Returns: + bool: Final result of the test. + """ + result = False + for received in callbackData["Received"]: + if (received["Initiator"] == initiatorLogicalAddress and + received["Destination"] == destinationLogicalAddress and + received["Opcode"] == opCode): + result = True + if payload: + for rec, sent in zip(received["Data"][2:], payload): + if rec != sent: + result = False + break + return result + def testFunction(self): """ The main test function that Transmits the Stanby Command and checks the ACK and validates it. @@ -74,29 +97,59 @@ def testFunction(self): self.testhdmiCEC.initialise() # Add the logical Address. - self.testhdmiCEC.addLogicalAddress(self.sourceLogicalAddress) + self.testhdmiCEC.addLogicalAddress(self.tvLogicalAddress) + + # Get the logical Address. + deviceLogicalAddress = self.testhdmiCEC.getLogicalAddress() - self.cecDevices = self.cecAdapter.listDevices() + if deviceLogicalAddress is None: + self.log.error("Failed to get the device logical address") + return False - for device in self.cecDevices: - logicalAddress = device["logical address"] + self.cecAdaptor = self.hdmiCECController.adaptorDetails - # To bypass sending the message to TV - if logicalAddress == 0 or logicalAddress == 14: - continue + if self.cecAdaptor is None: + return False - for command in self.cecCommands: - cec = command.get("command") - payload = command.get("payload") + cecAdapterLogicalAddress = self.cecAdaptor["logical address"] - # Transmit Standby command to a specific destination address - self.testhdmiCEC.cecTransmitCmd(logicalAddress, cec, payload) + finalResult = True + for command in self.cecCommands: + result = False + cecOpcode = command.get("command") + payload = command.get("payload") + response = command.get("response") + type = command.get("type") - self.log.stepStart(f'HdmiCecTx Source: {self.sourceLogicalAddress} Destination: {logicalAddress} CEC OPCode: {cec} Payload: {payload}') + destinationLogicalAddress = deviceLogicalAddress + if type == "Broadcast": + destinationLogicalAddress = self.broadcastAddress - result = self.cecAdapter.checkTransmitStatus(self.sourceLogicalAddress, logicalAddress, cec, payload) + self.log.stepStart(f'Send Test: {cecAdapterLogicalAddress} Destination: {destinationLogicalAddress} CEC OPCode: {cecOpcode} Payload: {payload}') - self.log.stepResult(result, f'HdmiCecTx Source: {self.sourceLogicalAddress} Destination: {logicalAddress} CEC OPCode: {cec} Payload: {payload}') + self.hdmiCECController.sendMessage(cecAdapterLogicalAddress, destinationLogicalAddress, cecOpcode, payload) + + callbackData = self.testhdmiCEC.readCallbackDetails() + + result = self.testVerifyReceivedData(callbackData, cecAdapterLogicalAddress, destinationLogicalAddress, cecOpcode, payload) + + finalResult &= result + + self.log.stepResult(result, f'Send Test: {cecAdapterLogicalAddress} Destination: {destinationLogicalAddress} CEC OPCode: {cecOpcode} Payload: {payload}') + + if response: + destinationLogicalAddress = cecAdapterLogicalAddress + if response.get("type") == "Broadcast": + destinationLogicalAddress = self.broadcastAddress + + cecOpcode = response.get("command") + payload = response.get("payload") + + self.log.stepStart(f'Response Test: {deviceLogicalAddress} Destination: {destinationLogicalAddress} CEC OPCode: {cecOpcode} Payload: {payload}') + result = self.hdmiCECController.checkTransmitStatus(deviceLogicalAddress, destinationLogicalAddress, cecOpcode, payload) + self.log.stepResult(result, f'Response Test: {cecAdapterLogicalAddress} Destination: {destinationLogicalAddress} CEC OPCode: {cecOpcode} Payload: {payload}') + + finalResult &= result # Remove the Logical Address self.testhdmiCEC.removeLogicalAddress() @@ -104,7 +157,7 @@ def testFunction(self): # Terminate dsAudio Module self.testhdmiCEC.terminate() - return result + return finalResult if __name__ == '__main__': summerLogName = os.path.splitext(os.path.basename(__file__))[0] + "_summery" diff --git a/profiles/sink/sink_hdmiCEC.yml b/profiles/sink/sink_hdmiCEC.yml index 323bf59..b4a6d9a 100644 --- a/profiles/sink/sink_hdmiCEC.yml +++ b/profiles/sink/sink_hdmiCEC.yml @@ -4,3 +4,138 @@ hdmicec: features: extendedEnumsSupported: false + + cec_responses: + - command: "0x00" # Feature Abort + payload: + type: "Direct" + response: + type: "Direct" + command: "0x9E" + update_payload: true + payload: ["0x00", "0x00"] + description: "Feature Abort Reason" + - command: "0x04" # Image View on + payload: + type: "Direct" + response: null + - command: "0x0D" # Text View On + payload: + type: "Direct" + response: null + - command: "0x32" # Set Menu Language + payload: + type: "Broadcast" + response: null + - command: "0x36" # Standby + payload: + type: "Both" + response: null + - command: "0x46" # Give OSD Name + payload: + type: "Direct" + response: + type: "Direct" + command: "0x47" + update_payload: false + payload: ["0x52", "0x44", "0x4b", "0x20", "0x56", "0x54", "0x53", "0x20", "0x44", "0x65", "0x76", "0x69", "0x63", "0x65"] + description: "Device request OSD name" + - command: "0x47" # report OSD Name + payload: + type: "Direct" + response: null + - command: "0x64" # Set OSD String + payload: + type: "Direct" + response: null + - command: "0x82" # Active source + payload: + type: "Broadcast" + response: null + - command: "0x83" # Give Physical Address + payload: + type: "Direct" + response: + type: "Broadcast" + command: "0x84" + update_payload: true + payload: ["0x00", "0x00", "0x00"] + description: "Report Physical Address" + - command: "0x84" # Report Physical address + payload: + type: "Broadcast" + response: null + - command: "0x85" # Request Active source + payload: + type: "Broadcast" + response: + type: "Broadcast" + command: "0x82" + update_payload: true + payload: ["0x00", "0x00"] + description: "Active Soruce" + - command: "0x87" # Device Vendor ID + payload: + type: "Broadcast" + response: null + - command: "0x8C" # Give Vendor ID + payload: + type: "Direct" + response: + type: "Broadcast" + command: "0x87" + update_payload: false + payload: ["0x00", "0x00", "0x01"] + description: "Device Vendor Id" + - command: "0x8F" # Give power status + payload: + type: "Direct" + response: + type: "Direct" + command: "0x90" + update_payload: false + payload: ["0x00"] + description: "Report power status" + - command: "0x90" # Power Status + payload: + type: "Direct" + response: null + - command: "0x91" # Get Menu Language + payload: + type: "Direct" + response: + type: "Broadcast" + command: "0x32" + update_payload: false + payload: ["0x65", "0x6E", "0x67"] + description: "Set Menu Language" + - command: "0x9E" # CEC Version + response: null + - command: "0x9F" # Get CEC version + payload: + type: "Direct" + response: + type: "Direct" + command: "0x9E" + update_payload: false + payload: ["0x05"] + description: "Device request for CEC version" + - command: "0xA7" # Request Latency + payload: + type: "Broadcast" + response: + type: "Broadcast" + command: "0xA8" + update_payload: true + # 100msec video delay ((number of milliseconds/2) + 1) + # 200msec audio delay ((number of milliseconds/2) + 1) + # (Bits 1-0) : Audio Ouput Compensated (0 - N/A, 1 - TV audio output is delay compensated, 2 - TV audio output is NOT delay compensated, 3 - TV audio output is Par delay compensated) + # (Bit 2) : 0 - normal latency, 1 - low latency + # Bit(7-3) : Reserved + payload: ["0x00", "0x00", "0x65", "0x00", "0x33"] + description: "Report Physical Address" + - command: "0xA8" # Report Physical Address + payload: + type: "Broadcast" + response: null + diff --git a/src/test_l3_hdmi_cec_sink_driver.c b/src/test_l3_hdmi_cec_sink_driver.c index 799dcf4..c2f71c7 100644 --- a/src/test_l3_hdmi_cec_sink_driver.c +++ b/src/test_l3_hdmi_cec_sink_driver.c @@ -68,52 +68,97 @@ #define HDMI_CEC_MAX_PAYLOAD 128 #define HDMI_CEC_MAX_OSDNAME 15 +#define HDMI_CEC_KVP_SIZE 128 +#define HDMI_CEC_TYPE_SIZE 16 #define UT_LOG_MENU_INFO UT_LOG_INFO -// CEC command map table and supporting function typedef struct { - uint8_t cecCommand; // CEC command code - const char* commandName; // Human-readable command name - int32_t dataLength; // Number of data bytes required for the command + uint8_t cecCommand; // CEC command code + const char* commandName; // Human-readable command name + int32_t dataLength; // Number of data bytes required for the command } CecCommandMap; -CecCommandMap cecCommandTable[] = +typedef struct cecResponse { + uint8_t cecCommand; //CEC opcode + uint32_t payloadSize; //CEC payload size + uint8_t type[UT_KVP_MAX_ELEMENT_SIZE]; //Type of the opcode Broadcast/ Direct + uint8_t payload[HDMI_CEC_MAX_PAYLOAD]; //CEC Payload +} cecResponse_t; + +CecCommandMap cecCommandTable[] = { {0x00, "Feature Abort", 2}, {0x04, "Image View On", 0}, + {0x05, "Tuner Step Increment", 0}, + {0x06, "Tuner Step Decrement", 0}, + {0x07, "Tuner Device Status", 8}, + {0x08, "Give Tuner Device Status", 0}, + {0x09, "Record On", 8}, + {0x0A, "Record Status", 8}, + {0x0B, "Record Off", 0}, {0x0D, "Text View On", 0}, - {0x20, "Active Source", 2}, - {0x32, "Inactive Source", 2}, - {0x36, "Request Active Source", 0}, - {0x41, "Standby", 0}, + {0x0F, "Record TV Screen", 0}, + {0x1A, "Give Deck Status", 0}, + {0x1B, "Deck Status", 1}, + {0x32, "Set Menu Language", 3}, + {0x33, "Clear Analog Timer", 0}, + {0x34, "Set Analog Timer", 8}, + {0x35, "Timer Status", 3}, + {0x36, "Standby", 0}, + {0x41, "Play", 0}, + {0x42, "Deck Control", 1}, + {0x43, "Timer Cleared Status", 1}, {0x44, "User Control Pressed", 1}, {0x45, "User Control Released", 0}, {0x46, "Give OSD Name", 0}, - {0x47, "Set OSD Name", 15}, - {0x82, "Routing Change", 4}, - {0x83, "Routing Information", 2}, - {0x86, "Report Physical Address", 3}, - {0x87, "Request Active Source", 0}, + {0x47, "Set OSD Name", 14}, + {0x64, "Set OSD String", 14}, + {0x67, "Set Timer Program Title", 14}, + {0x70, "System Audio Mode Request", 2}, + {0x71, "Give Audio Status", 0}, + {0x72, "Set System Audio Mode", 1}, + {0x7A, "Report Audio Status", 1}, + {0x7D, "Give System Audio Mode Status", 0}, + {0x7E, "System Audio Mode Status", 1}, + {0x80, "Routing Change", 4}, + {0x81, "Routing Information", 2}, + {0x82, "Active Source", 2}, + {0x83, "Give Physical Address", 0}, + {0x84, "Report Physical Address", 3}, + {0x85, "Request Active Source", 0}, + {0x86, "Set Stream Path", 2}, + {0x87, "Device Vendor ID", 3}, + {0x89, "Vendor Command", 14}, + {0x8A, "Vendor Remote Button Down", 1}, + {0x8B, "Vendor Remote Button Up", 0}, {0x8C, "Give Device Vendor ID", 0}, - {0x89, "Device Vendor ID", 3}, - {0x90, "Vendor Command", 16}, - {0x91, "Vendor Command with ID", 16}, - {0x92, "Give Device Power Status", 0}, - {0x93, "Report Power Status", 1}, + {0x8D, "Menu Request", 1}, + {0x8E, "Menu Status", 1}, + {0x8F, "Give Device Power Status", 0}, + {0x90, "Report Power Status", 1}, + {0x91, "Get Menu Language", 0}, + {0x92, "Select Analog Service", 4}, + {0x93, "Select Digital Service", 4}, + {0x97, "Set Digital Timer", 6}, + {0x99, "Clear Digital Timer", 0}, + {0x9A, "Set Audio Rate", 1}, + {0x9D, "Inactive Source", 2}, {0x9E, "CEC Version", 1}, {0x9F, "Get CEC Version", 0}, - {0xA0, "Get Menu Language", 0}, - {0xA1, "Set Menu Language", 3}, - {0xA5, "Report Physical Address", 3}, - {0xA6, "Request Short Audio Descriptor", 1}, - {0xC0, "Report Audio Status", 1}, - {0xC1, "Give Audio Status", 0}, - {0xC2, "Set System Audio Mode", 1}, - {0xC3, "Report Audio Descriptor", 1}, - {0xC4, "Set Audio Rate", 1}, - // Add more commands as needed + {0xA0, "Vendor Command With ID", 17}, + {0xA1, "Clear External Timer", 0}, + {0xA2, "Set External Timer", 9}, + {0xA7, "Request Current Latency", 2}, + {0xA8, "Report Current Latency", 5}, + {0xC0, "Initiate ARC", 0}, + {0xC1, "Report ARC Initiated", 0}, + {0xC2, "Report ARC Terminated", 0}, + {0xC3, "Request ARC Initiation", 0}, + {0xC4, "Request ARC Termination", 0}, + {0xC5, "Terminate ARC", 0}, + {0xFF, "Abort", 0} }; typedef enum HDMI_CEC_DEVICE_TYPE_T @@ -200,19 +245,8 @@ static int32_t gHandle = 0; static int32_t gLogicalAddress = -1; static uint32_t gPhysicalAddress = -1; static uint8_t *gPhysicalAddressBytes; -static HDMI_CEC_DEVICE_TYPE gDeviceType = HDMI_CEC_TV; -static HDMI_CEC_POWER_STATUS gPowerStatus = HDMI_CEC_ON; -static uint8_t gDeviceVendorID[] = {0x00, 0x00, 0x01}; // Example Vendor ID: 0x000001 -static uint8_t gCECVersion = 0x05; // CEC Version: 1.4 (0x05) -static uint8_t gAudioDelay = (100/2) + 1; //100msec audio delay ((number of milliseconds/2) + 1) -static uint8_t gVideoDelay = (200/2) + 1; //100msec video delay ((number of milliseconds/2) + 1) static uint8_t gBroadcastAddress = 0xF; -//(Bits 1-0) : Audio Ouput Compensated (0 - N/A, 1 - TV audio output is delay compensated, 2 - TV audio output is NOT delay compensated, 3 - TV audio output is Par delay compensated) -//(Bit 2) : 0 - normal latency, 1 - low latency -//Bit(7-3) : Reserved -uint8_t gLatencyFlag = 0x00; - /** * @brief CEC Command with data size mapping function. * @@ -222,7 +256,6 @@ uint8_t gLatencyFlag = 0x00; */ static int32_t getCecCommandInfo(uint8_t cecCommand, const char** commandName, int32_t* dataLength) { - UT_LOG_INFO("In %s(IN: cecCommand: [0x%02X])\n", __FUNCTION__, cecCommand); int32_t tableSize = sizeof(cecCommandTable) / sizeof(CecCommandMap); @@ -232,324 +265,179 @@ static int32_t getCecCommandInfo(uint8_t cecCommand, const char** commandName, i { *commandName = cecCommandTable[i].commandName; *dataLength = cecCommandTable[i].dataLength; - UT_LOG_INFO("Out %s(OUT: commandName: [%s], OUT: dataLength: [%d])\n", __FUNCTION__, *commandName, *dataLength); return 0; // Command found } } - UT_LOG_INFO("Out %s(OUT: Command not found)\n", __FUNCTION__); return -1; // Command not found } -static void handleImageViewOn() -{ - UT_LOG_INFO("Image View On command received.\n"); - // Perform any device-specific action for "Image View On" if needed. - UT_LOG_INFO("Image View On processed.\n"); -} - -static void handleActiveSource(uint8_t *buf, int32_t len) -{ - if (len >= 4) - { - uint16_t physicalAddress = (buf[2] << 8) | buf[3]; // Combine bytes to form the physical address - UT_LOG_INFO("Active Source command received. Physical Address: [0x%04X]\n", physicalAddress); - // Process Active Source as needed. - } - else - { - UT_LOG_ERROR("Active Source command received with insufficient data.\n"); - } -} - -static void handleGivePhysicalAddress(int32_t handle, uint8_t initiator, uint8_t destination, uint8_t *pPhysicalAddress, HDMI_CEC_DEVICE_TYPE deviceType) +/** + * @brief This function clears the stdin buffer. + * + * This function clears the stdin buffer. + */ +static void readAndDiscardRestOfLine(FILE *in) { - uint8_t response[] = { (destination << 4) | initiator, 0x84, (pPhysicalAddress[3] << 4) | pPhysicalAddress[2], (pPhysicalAddress[1] << 4 ) | pPhysicalAddress[0], deviceType}; - int32_t result; - HdmiCecTx(handle, response, sizeof(response), &result); - UT_LOG_INFO("Reported Physical Address response sent with result: %d\n", result); + int32_t c; + while ((c = fgetc(in)) != EOF && c != '\n'); } -static void handleReportPhysicalAddress(uint8_t *buf, int32_t len) +static void readInt(int32_t *value) { - if (len >= 5) - UT_LOG_INFO("Reported Physical Address: 0x%02X:0x%02X:0x%02X:0x%02X, Type: %s\n", (buf[2] >> 4) & 0x0F, buf[2] & 0x0F, (buf[3] >> 4) & 0x0F, buf[3] & 0x0F, UT_Control_GetMapString(cecDeviceType_mapTable, buf[4])); - else - UT_LOG_ERROR("Reported Physical command received with insufficient data.\n"); + scanf("%d", value); + readAndDiscardRestOfLine(stdin); } -static void handleGetCECVersion(int32_t handle, uint8_t initiator, uint8_t destination, uint8_t version) +static void readHex(int32_t *value) { - uint8_t response[] = { (destination << 4) | initiator, 0x9E, version }; - int32_t result; - HdmiCecTx(handle, response, sizeof(response), &result); - UT_LOG_INFO("CEC Version response sent with result: %d\n", result); + scanf("%x", value); + readAndDiscardRestOfLine(stdin); } -static void handleCECVersion(uint8_t *buf, int32_t len) +static bool getCommandResponse(uint8_t opcode, cecResponse_t *pResponse) { - if (len >= 3) - UT_LOG_INFO("Received CEC Version: %x\n", buf[2]); - else - UT_LOG_ERROR("CEC Version command received with insufficient data.\n"); -} + uint32_t numCommands = 0; + char key_string[HDMI_CEC_KVP_SIZE] = {0}; -static void handleGiveDeviceVendorID(int32_t handle, uint8_t initiator, uint8_t destination, uint8_t *pDeviceVendorId) -{ - uint8_t response[] = { (destination << 4) | initiator, 0x87, pDeviceVendorId[0], pDeviceVendorId[1], pDeviceVendorId[2]}; - int32_t result; - HdmiCecTx(handle, response, sizeof(response), &result); - UT_LOG_INFO("Device Vendor ID response sent with result: %d\n", result); -} + memset(pResponse, 0, sizeof(cecResponse_t)); -static void handleDeviceVendorID(uint8_t *buf, int32_t len) -{ - if (len >= 5) - UT_LOG_INFO("Received Device Vendor ID: %x%x%x\n", buf[2], buf[3], buf[4]); - else - UT_LOG_ERROR("Give Device vendor ID command received with insufficient data.\n"); -} + numCommands = UT_KVP_PROFILE_GET_LIST_COUNT("hdmicec/cec_responses"); -static void handleStandby() -{ - UT_LOG_INFO("Standby command received. Initiating standby actions.\n"); - // Implement device-specific standby actions here, such as turning off the display. -} + for(uint32_t i = 0; i < numCommands; i++) + { + uint8_t command; + uint8_t found; -static void handleGiveDeviceInfo(int32_t handle, uint8_t initiator, uint8_t destination) -{ - uint8_t response[] = { (destination << 4) | initiator, 0xA1, 'V', 'T', 'S', ' ', 'D', 'e', 'v', 'i', 'c', 'e' }; // Device Info: "VTS Device" - int32_t result; - HdmiCecTx(handle, response, sizeof(response), &result); - UT_LOG_INFO("Device Info response sent with result: %d\n", result); -} + snprintf(key_string, HDMI_CEC_KVP_SIZE, "hdmicec/cec_responses/%d/command" , i); + command = UT_KVP_PROFILE_GET_UINT8(key_string); -static void handleOsdDisplay(uint8_t *buf, int32_t len) -{ - if (len > 3) - { - uint8_t buffer[HDMI_CEC_MAX_OSDNAME] = {0}; - uint8_t *temp = buffer; - UT_LOG_INFO("OSD Display Control: %d", buf[2]); - for (int32_t i = 3; i < len; i++) + if(command != opcode) { - int32_t len = 0; - len = snprintf(temp, HDMI_CEC_MAX_OSDNAME, "%c", buf[i]); - temp += len; + continue; } - UT_LOG_INFO("OSD Display message received: %s", buffer); - } - else - { - UT_LOG_ERROR("OSD Display message received with insufficient data.\n"); - } -} + snprintf(key_string, HDMI_CEC_KVP_SIZE, "hdmicec/cec_responses/%d/response/command" , i); + found = ut_kvp_fieldPresent(ut_kvp_profile_getInstance(), key_string); -static void handleGiveOSDName(int32_t handle, uint8_t initiator, uint8_t destination) -{ - uint8_t response[] = { (destination << 4) | initiator, 0x47, 'V', 'T', 'S', ' ', 'D', 'e', 'v', 'i', 'c', 'e' }; // OSD Name: "VTS Device" - int32_t result; - HdmiCecTx(handle, response, sizeof(response), &result); - UT_LOG_INFO("OSD Name response sent with result: %d sourc/destination:0x%2x\n", result,response[0]); -} - -static void handleSetOSDName(uint8_t *buf, int32_t len) -{ - if (len > 2) - { - uint8_t buffer[HDMI_CEC_MAX_OSDNAME] = {0}; - uint8_t *temp = buffer; - for (int32_t i = 2; i < len; i++) + if(found) { - int32_t len = 0; - len = snprintf(temp, HDMI_CEC_MAX_OSDNAME, "%c", buf[i]); - temp += len; - } - UT_LOG_INFO("OSD Name received: %s", buffer); - } - else - { - UT_LOG_ERROR("OSD Name message received with insufficient data.\n"); - } -} + pResponse->cecCommand = UT_KVP_PROFILE_GET_UINT8(key_string); -static void handleGivePowerStatus(int32_t handle, uint8_t initiator, uint8_t destination, HDMI_CEC_POWER_STATUS powerStatus) -{ - uint8_t response[] = { (destination << 4) | initiator, 0x90, powerStatus }; - int32_t result; - HdmiCecTx(handle, response, sizeof(response), &result); - UT_LOG_INFO("Power Status response sent with result: %d\n", result); -} + snprintf(key_string, HDMI_CEC_KVP_SIZE, "hdmicec/cec_responses/%d/response/type" , i); + UT_KVP_PROFILE_GET_STRING(key_string, pResponse->type); -static void handleReportPowerStatus(uint8_t *buf, int32_t len) -{ - if (len >= 3) - { - UT_LOG_INFO("Power Status: %s\n", UT_Control_GetMapString(cecPowerStatus_mapTable, buf[2])); - } - else - { - UT_LOG_ERROR("Power Status received with insufficient data.\n"); - } -} + snprintf(key_string, HDMI_CEC_KVP_SIZE, "hdmicec/cec_responses/%d/response/payload" , i); + pResponse->payloadSize = UT_KVP_PROFILE_GET_LIST_COUNT(key_string); -static void handleFeatureAbort(uint8_t *buf, int32_t len) -{ - if (len >= 4) - { - UT_LOG_INFO("Feature Abort: Opcode: 0x%02X, Reason: %s\n", buf[2], UT_Control_GetMapString(cecFeatureAbortReason_mapTable, buf[3])); - } - else - { - UT_LOG_ERROR("Feature Abort received with insufficient data.\n"); + for(uint8_t j = 0; j < pResponse->payloadSize; j++) + { + snprintf(key_string, HDMI_CEC_KVP_SIZE, "hdmicec/cec_responses/%d/response/payload/%d" , i, j); + pResponse->payload[j] = UT_KVP_PROFILE_GET_UINT8(key_string); + } + return true; + } } + return false; } -static void sendFeatureAbort(int32_t handle, uint8_t initiator, uint8_t destination, uint8_t opcode, uint8_t reason) +static void sendResponse(int32_t handle, uint8_t initiator, uint8_t destination, + uint8_t *buf, int32_t len, cecResponse_t *pCecResponse) { - uint8_t response[] = { (destination << 4) | initiator, 0x00, opcode, reason }; // Abort with reason - int32_t result; - HdmiCecTx(handle, response, sizeof(response), &result); - UT_LOG_WARNING("Feature Abort sent for opcode: 0x%02X with reason: 0x%02X, result: %d\n", opcode, reason, result); -} + uint8_t prBuffer[HDMI_CEC_MAX_PAYLOAD] = {0}; + uint8_t response[HDMI_CEC_MAX_PAYLOAD] = {0}; -static void handleSetMenuLanguage(uint8_t *buf, int32_t len) -{ - if (len >= 5) + if (pCecResponse->payloadSize) { - UT_LOG_INFO("OSD Menu Language received: %c%c%c", buf[2], buf[2], buf[3]); - } - else - { - UT_LOG_ERROR("OSD Menu Language received with insufficient data"); - } -} - -static void handleCurrentLatency(int32_t handle, uint8_t *buf, int32_t len, uint8_t *pPhysicalAddress, uint8_t videoDelay, uint8_t audioDelay, uint8_t latency) -{ - uint8_t response[] = {(gLogicalAddress << 4) | gBroadcastAddress, 0xA8, buf[2], buf[3], videoDelay, latency, audioDelay}; - - int32_t result; + int32_t result; + const char* commandName; + int32_t expectedDataLength; - if (len >= 4) - { - if (buf[2] == (pPhysicalAddress[3] << 4) | pPhysicalAddress[2] && - buf[3] == (pPhysicalAddress[1] << 4) | pPhysicalAddress[0]) + if (!strcmp(pCecResponse->type, "Direct")) + { + response[0] = (destination << 4) | initiator; + } + else { - response[4] = videoDelay; - response[5] = latency; - response[6] = audioDelay; + //Send braodcast message + response[0] = (gLogicalAddress << 4) | gBroadcastAddress; + } + response[1] = pCecResponse->cecCommand; - HdmiCecTx(handle, response, sizeof(response), &result); + for (int32_t index = 0; index < pCecResponse->payloadSize; index++) + { + response[index + 2] = pCecResponse->payload[index]; } - } - else - { - UT_LOG_ERROR("Latency query received with insufficient data.\n"); - } -} + { + uint8_t *temp = prBuffer; + // Log each byte received in the buffer + for (int32_t index = 0; index < pCecResponse->payloadSize + 2; index++) + { + int32_t len = 0; + len = snprintf(temp, HDMI_CEC_MAX_PAYLOAD, "%02X:", response[index]); + temp += len; + } + prBuffer[strlen(prBuffer)-1] = '\0'; -static void handleRequestActiveSource(int32_t handle, uint8_t *pPhysicalAddress) -{ - uint8_t response[] = { (gLogicalAddress << 4) | gBroadcastAddress, 0x82, (pPhysicalAddress[3] << 4) | pPhysicalAddress[2], (pPhysicalAddress[1] << 4 ) | pPhysicalAddress[0]}; - int32_t result; - HdmiCecTx(handle, response, sizeof(response), &result); - UT_LOG_INFO("Requested Active Sources response sent with result: %d\n", result); -} + } -/** - * @brief This function clears the stdin buffer. - * - * This function clears the stdin buffer. - */ -static void readAndDiscardRestOfLine(FILE *in) -{ - int32_t c; - while ((c = fgetc(in)) != EOF && c != '\n'); -} + HdmiCecTx(handle, response, pCecResponse->payloadSize + 2, &result); -static void readInt(int32_t *value) -{ - scanf("%d", value); - readAndDiscardRestOfLine(stdin); -} + getCecCommandInfo(pCecResponse->cecCommand, &commandName, &expectedDataLength); -static void readHex(int32_t *value) -{ - scanf("%x", value); - readAndDiscardRestOfLine(stdin); + UT_LOG_INFO("Sent Response Opcode: [0x%02X] [%s] Initiator: [%x], Destination: [%x] Data: [%s]\n", + pCecResponse->cecCommand, commandName, destination, initiator, prBuffer); + } } static void onRxDataReceived(int32_t handle, void *callbackData, uint8_t *buf, int32_t len) { UT_LOG_INFO("In %s(IN: handle: [%p], IN: callbackData: [%p], IN: buf: [%p], IN: len: [%d])\n", __FUNCTION__, handle, callbackData, buf, len); + const char* commandName; + int32_t expectedDataLength; + if ((handle != 0) && (callbackData != NULL) && (len > 0)) { // Parse the command uint8_t initiator = (buf[0] >> 4) & 0xF; // Extract initiator address uint8_t destination = buf[0] & 0xF; // Extract destination address uint8_t opcode; // Command opcode + cecResponse_t cecResponse = {0}; // cec response + uint8_t prBuffer[HDMI_CEC_MAX_PAYLOAD] = {0}; + bool result = false; + if( len == 1) { - UT_LOG_INFO("Received Ping message Initiator: [0x%02X], Destination: [0x%02X]", initiator, destination); - UT_LOG_INFO("Out %s\n", __FUNCTION__); - return; + UT_LOG_INFO("Received Ping message Initiator: [%x], Destination: [%x]", initiator, destination); + goto exit; } opcode = buf[1]; - UT_LOG_INFO("Initiator: [0x%02X], Destination: [0x%02X], Opcode: [0x%02X]", initiator, destination, opcode); - if (len > 2) + if(getCecCommandInfo(opcode, &commandName, &expectedDataLength) != 0) + { + UT_LOG_WARNING("CEC command 0x%02X is not recognized", opcode); + goto exit; + } + { - char buffer[HDMI_CEC_MAX_PAYLOAD] = {0}; - uint8_t *temp = buffer; + uint8_t *temp = prBuffer; // Log each byte received in the buffer - for (int32_t index = 2; index < len; index++) + for (int32_t index = 0; index < len; index++) { int32_t len = 0; - len = snprintf(temp, HDMI_CEC_MAX_PAYLOAD, "0x%02X, ", buf[index]); + len = snprintf(temp, HDMI_CEC_MAX_PAYLOAD, "%02X:", buf[index]); temp += len; } - buffer[strlen(buffer)-2] = '\0'; - UT_LOG_INFO("Payload: [%s]", buffer); + prBuffer[strlen(prBuffer)-1] = '\0'; } - // Handle each opcode with its corresponding function - switch (opcode) - { - // CEC Commands no response sent - case 0x00: handleFeatureAbort(buf, len); break; - case 0x04: handleImageViewOn(); break; - case 0x32: handleSetMenuLanguage(buf, len); break; - case 0x82: handleActiveSource(buf, len); break; - case 0x84: handleReportPhysicalAddress(buf, len); break; - case 0x87: handleDeviceVendorID(buf, len); break; - case 0x36: handleStandby(); break; - case 0x64: handleOsdDisplay(buf, len); break; - case 0x90: handleReportPowerStatus(buf, len); break; - case 0x9E: handleCECVersion(buf, len); break; - case 0x47: handleSetOSDName(buf, len); break; - - // CEC commands with response - case 0x83: handleGivePhysicalAddress(handle, initiator, destination, gPhysicalAddressBytes, gDeviceType); break; - case 0x8F: handleGivePowerStatus(handle, initiator, destination, gPowerStatus); break; - case 0x8C: handleGiveDeviceVendorID(handle, initiator, destination, gDeviceVendorID); break; - case 0x9F: handleGetCECVersion(handle, initiator, destination, gCECVersion); break; - case 0x46: handleGiveOSDName(handle, initiator, destination); break; - - // Broadcasting CEC commands with response - case 0x85: handleRequestActiveSource(handle, gPhysicalAddressBytes); break; - case 0xA7: handleCurrentLatency(handle, buf, len, gPhysicalAddressBytes, gVideoDelay, gAudioDelay, gLatencyFlag); break; - default: - UT_LOG_WARNING("Unhandled opcode: [0x%02X]\n", opcode); - sendFeatureAbort(handle, initiator, destination, opcode, 0x04); // Feature Abort: Unrecognized opcode - break; - } + UT_LOG_INFO("Received Opcode: [0x%02X] [%s] Initiator: [%x], Destination: [%x] Data: [%s]\n", opcode, commandName, initiator, destination, prBuffer); + + result = getCommandResponse(opcode, &cecResponse); - // Clear the buffer after processing - memset(buf, 0, len); + sendResponse(handle, initiator, destination, buf, len, &cecResponse); } else { @@ -567,7 +455,7 @@ static void onRxDataReceived(int32_t handle, void *callbackData, uint8_t *buf, i UT_LOG_ERROR("Error: Invalid length.\n"); } } - +exit: UT_LOG_INFO("Out %s\n", __FUNCTION__); } @@ -653,17 +541,17 @@ void test_l3_hdmi_cec_sink_hal_AddLogicalAddress(void) int32_t getLogicalAddress = -1; UT_LOG_MENU_INFO("Enter Logical Address:"); - readInt(&logicalAddress); + readHex(&logicalAddress); /* Check that logical address should be valid one */ - UT_LOG_INFO("Calling HdmiCecAddLogicalAddress(IN:handle:[0x%0X], IN:logicalAddress:[%d]", gHandle, logicalAddress); + UT_LOG_INFO("Calling HdmiCecAddLogicalAddress(IN:handle:[0x%0X], IN:logicalAddress:[%x]", gHandle, logicalAddress); status = HdmiCecAddLogicalAddress(gHandle, logicalAddress); - UT_LOG_INFO("Result HdmiCecAddLogicalAddress (IN:handle:[0x%0X], IN:logicalAddress:[%d]) HDMI_CEC_STATUS[%s]",gHandle,logicalAddress,UT_Control_GetMapString(cecError_mapTable,status)); + UT_LOG_INFO("Result HdmiCecAddLogicalAddress (IN:handle:[0x%0X], IN:logicalAddress:[%x]) HDMI_CEC_STATUS[%s]",gHandle,logicalAddress,UT_Control_GetMapString(cecError_mapTable,status)); assert(status == HDMI_CEC_IO_SUCCESS); UT_LOG_INFO("Calling HdmiCecGetLogicalAddress(IN:handle:[0x%0X], OUT:logicalAddress:[])", gHandle); status = HdmiCecGetLogicalAddress(gHandle, &getLogicalAddress); - UT_LOG_INFO("Result HdmiCecGetLogicalAddress(IN:handle:[0x%0X], OUT:logicalAddress:[%d]) HDMI_CEC_STATUS:[%s])", gHandle, getLogicalAddress, UT_Control_GetMapString(cecError_mapTable,status)); + UT_LOG_INFO("Result HdmiCecGetLogicalAddress(IN:handle:[0x%0X], OUT:logicalAddress:[%x]) HDMI_CEC_STATUS:[%s])", gHandle, getLogicalAddress, UT_Control_GetMapString(cecError_mapTable,status)); assert(status == HDMI_CEC_IO_SUCCESS); assert(logicalAddress == getLogicalAddress); @@ -701,7 +589,7 @@ void test_l3_hdmi_cec_sink_hal_GetLogicalAddress(void) UT_LOG_INFO("Calling HdmiCecGetLogicalAddress(IN:handle:[0x%0X], OUT:logicalAddress:[])", gHandle); status = HdmiCecGetLogicalAddress(gHandle, &logicalAddress); - UT_LOG_INFO("Result HdmiCecGetLogicalAddress(IN:handle:[0x%0X], OUT:logicalAddress:[%d]) HDMI_CEC_STATUS:[%s])", gHandle, logicalAddress, UT_Control_GetMapString(cecError_mapTable,status)); + UT_LOG_INFO("Result HdmiCecGetLogicalAddress(IN:handle:[0x%0X], OUT:logicalAddress:[%x]) HDMI_CEC_STATUS:[%s])", gHandle, logicalAddress, UT_Control_GetMapString(cecError_mapTable,status)); assert(status == HDMI_CEC_IO_SUCCESS); UT_LOG_INFO("Out %s\n", __FUNCTION__); @@ -743,7 +631,7 @@ void test_l3_hdmi_cec_sink_hal_TransmitHdmiCecCommand(void) { // Reading inputs from the user or test framework UT_LOG_MENU_INFO("Enter a valid Destination Logical Address: "); - readInt(&destinationLogicalAddress); + readHex(&destinationLogicalAddress); UT_LOG_MENU_INFO("Enter CEC Command (in hex): "); readHex(&cecCommand); @@ -917,8 +805,8 @@ int32_t test_register_hdmicec_hal_sink_l3_tests(void) { return -1; } - // List of test function names and strings + // List of test function names and strings UT_add_test( pSuite, "Init HDMI CEC", test_l3_hdmi_cec_sink_hal_Init); UT_add_test( pSuite, "Add Logical Address", test_l3_hdmi_cec_sink_hal_AddLogicalAddress); UT_add_test( pSuite, "Get Logical Address", test_l3_hdmi_cec_sink_hal_GetLogicalAddress); From 3e943a3626571108f425582d424cd9872dbb2e18 Mon Sep 17 00:00:00 2001 From: bhanucbp <141142298+bhanucbp@users.noreply.github.com> Date: Thu, 12 Dec 2024 12:19:19 +0000 Subject: [PATCH 25/40] gh #44 L3 test case development Updated the code with comments and cleanup --- host/tests/classes/hdmiCEC.py | 63 +++++++++------ host/tests/classes/hdmiCEC_testConfig.yml | 2 +- host/tests/configs/deviceConfig.yml | 4 +- host/tests/configs/example_rack_config.yml | 43 +++++----- .../hdmiCEC_L3_Tests/hdmiCECHelperClass.py | 81 ++++--------------- .../hdmiCEC_L3_Tests/hdmiCECTestCommands.yml | 22 +++++ .../hdmiCEC_L3_Tests/hdmiCEC_L3_testSetup.yml | 10 +-- .../hdmiCEC_test01_TransmitCECCommands.py | 44 ++++++---- .../hdmiCEC_test02_ReceiveCECCommands.py | 40 +++++---- profiles/sink/sink_hdmiCEC_test.yml | 34 -------- 10 files changed, 154 insertions(+), 189 deletions(-) delete mode 100644 profiles/sink/sink_hdmiCEC_test.yml diff --git a/host/tests/classes/hdmiCEC.py b/host/tests/classes/hdmiCEC.py index 9cf3c24..c85a544 100644 --- a/host/tests/classes/hdmiCEC.py +++ b/host/tests/classes/hdmiCEC.py @@ -36,18 +36,20 @@ class hdmiCECClass(): """ - HDMI CEC Class. + HDMI CEC Class. - This module provides common functionalities and extensions for the HDMI CEC Module. + Provides functionalities for initializing, configuring, and controlling + HDMI CEC (Consumer Electronics Control) operations in the test environment. """ - def __init__(self, moduleConfigProfileFile :str, session=None, targetWorkspace="/tmp"): + def __init__(self, moduleConfigProfileFile:str, session=None, targetWorkspace:str="/tmp"): """ - Initializes the HDMI CEC Class instance with configuration settings. + Initialize the HDMI CEC Class with configuration settings. Args: - moduleConfigProfileFile (str): Path to the device profile configuration file. - session: Optional; session object for the user interface. + moduleConfigProfileFile (str): Path to the profile configuration file for the HDMI CEC module. + session: Optional session object for managing interactions with the device. + targetWorkspace (str, optional): Target workspace directory on the device. Defaults to "/tmp". Returns: None @@ -56,19 +58,22 @@ def __init__(self, moduleConfigProfileFile :str, session=None, targetWorkspace=" self.testConfigFile = os.path.join(dir_path, "hdmiCEC_testConfig.yml") self.testSuite = "L3 HDMICEC Sink Functions" - # Load configurations for device profile and menu - self.moduleConfigProfile = ConfigRead( moduleConfigProfileFile , self.moduleName) + # Prepare the profile file on the target workspace + profileOnTarget = os.path.join(targetWorkspace, os.path.basename(moduleConfigProfileFile)) self.testConfig = ConfigRead(self.testConfigFile, self.moduleName) - self.testConfig.test.execute = os.path.join(targetWorkspace, self.testConfig.test.execute) + self.testConfig.test.execute = os.path.join(targetWorkspace, self.testConfig.test.execute) + f" -p {profileOnTarget}" self.utMenu = UTSuiteNavigatorClass(self.testConfig, None, session) self.testSession = session self.utils = utBaseUtils() - self.ports = self.moduleConfigProfile.fields.get("Ports") + # Copy required artifacts to the target workspace for artifact in self.testConfig.test.artifacts: filesPath = os.path.join(dir_path, artifact) self.utils.rsync(self.testSession, filesPath, targetWorkspace) + # Copy the profile configuration to the target workspace + self.utils.scpCopy(self.testSession, moduleConfigProfileFile, targetWorkspace) + # Start the user interface menu self.utMenu.start() @@ -118,11 +123,10 @@ def terminate(self): def addLogicalAddress(self, logicalAddress:str='0'): """ - Adding the logical address of a specific device. - For now Sink to support only the logical address 0. + Add a logical address for the device. Args: - logicalAddress (str): The Logical address of the DUT. This will be fixed to zero for a sink device for now. + logicalAddress (str, optional): Logical address of the device. Defaults to '0'. Value ranges from '0' - 'f' Returns: None @@ -138,10 +142,10 @@ def addLogicalAddress(self, logicalAddress:str='0'): def removeLogicalAddress(self): """ - Remove logical address. + Remove the logical address of the device. Args: - logicalAddress (int): The Logical address of the DUT that should be removed. + None Returns: None @@ -150,13 +154,13 @@ def removeLogicalAddress(self): def getLogicalAddress(self): """ - Retrieves the Logical Address of the DUT. + Get the logical address of the device. Args: None. Returns: - int: Logical address of the device. + str: Logical address of the device. Value ranges from '0' - 'f' """ result = self.utMenu.select( self.testSuite, "Get Logical Address") connectionStatusPattern = r"Result HdmiCecGetLogicalAddress\(IN:handle:\[0x[0-9A-F]+\], OUT:logicalAddress:\[([0-9A-Fa-f]+)\]\)" @@ -166,13 +170,13 @@ def getLogicalAddress(self): def getPhysicalAddress(self): """ - Retrieve the Physical Address of the DUT. + Get the physical address of the device. Args: None. Returns: - int: Physical Address of the DUT. + str: Physical Address of the DUT. """ result = self.utMenu.select( self.testSuite, "Get Phyiscal Address") typeStatusPattern = r"Result HdmiCecGetPhysicalAddress\(IN:handle:[.*\], OUT:physicalAddress:[.*\]) HDMI_CEC_STATUS:[.*\]" @@ -182,10 +186,12 @@ def getPhysicalAddress(self): def cecTransmitCmd(self, destLogicalAddress:str, cecCommand:str, cecData:list=None): """ - Transmit/Broadcast the CEC command and data to the respective destination. + Transmit or broadcast a CEC command to a specified destination. Args: - None. + destLogicalAddress (str): Destination logical address. + cecCommand (str): CEC command in hexadecimal. + cecData (list, optional): List of data bytes to include in the transmission. Returns: None @@ -233,10 +239,8 @@ def readCallbackDetails (self): - "Destination" (str): The destination address in hexadecimal. - "Data" (list): The data associated with the opcode. """ - result = { - "Received": [], - "Response": [] - } + result = {"Received": [], "Response": []} + callbackLogs = self.testSession.read_all() received_pattern = re.compile( @@ -304,6 +308,15 @@ def __del__(self): # Get Physical Address physicalAddress = test.getPhysicalAddress() + # Broadcast 0x85 cec command + test.cecTransmitCmd('f', '0x85') + + # Transmitt 0x04 cec command to '1' + test.cecTransmitCmd('1', '0x85') + + # Read the callback details + result = test.readCallbackDetails() + # Close the device test.terminate() diff --git a/host/tests/classes/hdmiCEC_testConfig.yml b/host/tests/classes/hdmiCEC_testConfig.yml index 00f7ba5..40ac032 100644 --- a/host/tests/classes/hdmiCEC_testConfig.yml +++ b/host/tests/classes/hdmiCEC_testConfig.yml @@ -26,7 +26,7 @@ hdmicec: #List of artifacts folders, test class copies the content of folder to the target device workspace - "../../../bin/" # exectute command, this will appended with the target device workspace path - execute: "run.sh -p sink_hdmiCEC.yml" + execute: "run.sh" type: UT-C # C (UT-C Cunit) / C++ (UT-G (g++ ut-core gtest backend)) suites: 0: diff --git a/host/tests/configs/deviceConfig.yml b/host/tests/configs/deviceConfig.yml index b7dafee..91046a1 100644 --- a/host/tests/configs/deviceConfig.yml +++ b/host/tests/configs/deviceConfig.yml @@ -30,9 +30,7 @@ deviceConfig: target_directory: "/tmp/" # Target Directory on device prompt: "" # Prompt string on console test: - #TODO: Use the single profile file which contains all details (ds, hdmi, etc) - profile: "../../../../profiles/sink/sink_hdmiCEC_test.yaml" - streams_download_url: "" #URL path from which the streams are downloaded to the device + profile: "../../../profiles/sink/sink_hdmiCEC.yml" cpe2: platform: "test" model: "test" diff --git a/host/tests/configs/example_rack_config.yml b/host/tests/configs/example_rack_config.yml index 815a440..910b483 100644 --- a/host/tests/configs/example_rack_config.yml +++ b/host/tests/configs/example_rack_config.yml @@ -37,18 +37,6 @@ globalConfig: # [ includes: ] # [ deviceConfig: "required.yml file" ] deviceConfig: "example_device_config.yml" - capture: - # [capture: optional] - # [ocrEnginePath: "/usr/bin/tesseract"] # "C:\\Program Files\\Tesseract-OCR\\tesseract.exe" (For Windows) - tesseract binary - # [resolution: "1080p"] - Capture resolution - # [input: 0] - which input is connected to the video path - # Note: Video capture will not be installed unless screenRegions: is defined in deviceConfig: - ocrEnginePath: "/usr/bin/tesseract" # "C:\\Program Files\\Tesseract-OCR\\tesseract.exe" (For Windows) - resolution: "1080p" - input: 0 - cec-adaptor: - type: cec-client - adaptor: /dev/ttyACM0 local: log: # log for each slot directory: "./logs" @@ -68,29 +56,36 @@ rackConfig: # [ type: "ssh": port: 22 username: "test" password: "test" ] # [ type: "telnet": port: 23 username: "test" password: "test" ] - dut: - ip: "127.0.0.1" # IP Address of the ADA Hub - description: "local PC" - platform: "PC" + ip: "127.0.0.1" + description: "element" + platform: "element" consoles: - default: type: "ssh" port: 22 - username: "srr07" - ip: "127.0.0.1" #IP address - password: '1234' + username: "root" + ip: "127.0.0.1" + password: ' ' - ssh_player: type: "ssh" port: 22 - username: "srr07" - ip: "127.0.0.1" #IP address - password: '1234' + username: "root" + ip: "127.0.0.1" + password: ' ' - ssh_hal_test: type: "ssh" port: 22 - username: "srr07" - ip: "127.0.0.1" #IP address - password: '1234' + username: "root" + ip: "127.0.0.1" + password: ' ' outbound: download_url: "http://localhost:8000/" # download location for the CPE device httpProxy: # Local Proxy if required workspaceDirectory: './logs/workspace' # Local working directory + hdmiCECController: + type: remote-cec-client + vendor: "Pulse Eight" + adaptor: /dev/ttyACM0 # Adaptor device entry + address: "127.0.0.1" # Needs to be be filled out with IP address + username: "root" # Needs to be filled out with login username + password: ' ' # Needs to be filled out with login password diff --git a/host/tests/hdmiCEC_L3_Tests/hdmiCECHelperClass.py b/host/tests/hdmiCEC_L3_Tests/hdmiCECHelperClass.py index abba8d4..d6d113d 100755 --- a/host/tests/hdmiCEC_L3_Tests/hdmiCECHelperClass.py +++ b/host/tests/hdmiCEC_L3_Tests/hdmiCECHelperClass.py @@ -36,20 +36,28 @@ class hdmiCECHelperClass(utHelperClass): + """ + Helper class for managing HDMI CEC tests. + + This class extends the `utHelperClass` and provides functionality for preparing + and cleaning up HDMI CEC tests. + """ + def __init__(self, testName:str, qcId:str, log:logModule=None ): """ - Initializes the test class with test name, setup configuration, and sessions for the device. + Initializes the test helper class with test name, setup configuration, and session management. Args: - testName (str) : name of the test - qcId (str): QC ID of the test. - log (class, optional): Parent log class. Defaults to None. + testName (str): Name of the test. + qcId (str): Quality Control (QC) ID of the test. + log (logModule, optional): Parent log module instance for logging. Defaults to None. """ self.testName = "" self.testSetupPath = os.path.join(dir_path, "hdmiCEC_L3_testSetup.yml") self.moduleName = "hdmicec" self.rackDevice = "dut" + # Initialize the base helper class super().__init__(testName, qcId, log) # Load test setup configuration @@ -74,82 +82,23 @@ def __init__(self, testName:str, qcId:str, log:logModule=None ): self.cecCommands = hdmicec.fields.get(self.testName) self.hdmiCECController = self.dut.hdmiCECController -# def testDownloadAssets(self): -# """ -# Downloads the test artifacts listed in the test setup configuration. -# -# This function retrieves the necessary files and saves them on the DUT. -# -# Args: -# None -# """ -# -# # List of streams with path -# self.testStreams = [] -# url = [] -# -# streamPaths = self.testSetup.get("assets").get("device").get(self.testName).get("streams") -# -# # Download test streams to device -# if streamPaths and self.streamDownloadURL: -# for streamPath in streamPaths: -# url.append(os.path.join(self.streamDownloadURL, streamPath)) -# self.testStreams.append(os.path.join(self.targetWorkspace, os.path.basename(streamPath))) -# self.downloadToDevice(url, self.targetWorkspace, self.rackDevice) - -# def testCleanAssets(self): -# """ -# Removes the downloaded assets and test streams from the DUT after test execution. -# -# Args: -# None -# """ -# self.deleteFromDevice(self.testStreams) -# - def testRunPrerequisites(self): - """ - Executes prerequisite commands listed in the test setup configuration file on the DUT. - - Args: - None - """ - - # Run commands as part of test prerequisites - test = self.testSetup.get("assets").get("device").get(self.testName) - cmds = test.get("execute") - if cmds is not None: - for cmd in cmds: - self.writeCommands(cmd) - def testPrepareFunction(self): """ - Prepares the environment and assets required for the test. + Cleans up the test environment by deinitializing the HDMI CEC instance. - This function: - - Downloads the required assets. - - Runs the prerequisite commands. - - Creates hdmiCEC + Args: + powerOff (bool, optional): Flag to indicate whether to power off the device. Defaults to True. Returns: bool """ - - # Run Prerequisites listed in the test setup configuration file - #self.testRunPrerequisites() - # Create the hdmiCEC class self.testhdmiCEC = hdmiCECClass(self.moduleConfigProfileFile, self.hal_session, self.targetWorkspace) return True def testEndFunction(self, powerOff=True): - # Clean the assets downloaded to the device - #self.testCleanAssets() # Clean up the hdmiCEC instance del self.testhdmiCEC - - def testExceptionCleanUp (self): - # Clean the assets downloaded to the device - self.testCleanAssets() diff --git a/host/tests/hdmiCEC_L3_Tests/hdmiCECTestCommands.yml b/host/tests/hdmiCEC_L3_Tests/hdmiCECTestCommands.yml index 7b62b96..65c6f2e 100644 --- a/host/tests/hdmiCEC_L3_Tests/hdmiCECTestCommands.yml +++ b/host/tests/hdmiCEC_L3_Tests/hdmiCECTestCommands.yml @@ -1,3 +1,25 @@ +#** ***************************************************************************** +# * +# * If not stated otherwise in this file or this component's LICENSE file the +# * following copyright and licenses apply: +# * +# * Copyright 2024 RDK Management +# * +# * Licensed under the Apache License, Version 2.0 (the "License"); +# * you may not use this file except in compliance with the License. +# * You may obtain a copy of the License at +# * +# * +# http://www.apache.org/licenses/LICENSE-2.0 +# * +# * Unless required by applicable law or agreed to in writing, software +# * distributed under the License is distributed on an "AS IS" BASIS, +# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# * See the License for the specific language governing permissions and +# * limitations under the License. +# * +#* ****************************************************************************** + hdmicec: test01_TransmitCECCommands: - command: "0x82" # Active Soruce diff --git a/host/tests/hdmiCEC_L3_Tests/hdmiCEC_L3_testSetup.yml b/host/tests/hdmiCEC_L3_Tests/hdmiCEC_L3_testSetup.yml index fcddfe7..8da1aa5 100755 --- a/host/tests/hdmiCEC_L3_Tests/hdmiCEC_L3_testSetup.yml +++ b/host/tests/hdmiCEC_L3_Tests/hdmiCEC_L3_testSetup.yml @@ -20,12 +20,10 @@ # * #* ****************************************************************************** - -hdmicec: # Prefix must always exist +hdmicec: description: "hdmiCEC test setup" assets: device: - test01_TransmitSingleStandbyCommandandValidateAck: - test02_BroadcastStandbyCommand: - test03_TransmitOSDCommandandValidateAck: - test04_TransmitLargerOSDCommandRepeatedlyandValidate: + test01_TransmitCECCommands: + test02_ReceiveCECCommands: + diff --git a/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test01_TransmitCECCommands.py b/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test01_TransmitCECCommands.py index 12488c2..8f3919c 100755 --- a/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test01_TransmitCECCommands.py +++ b/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test01_TransmitCECCommands.py @@ -24,28 +24,26 @@ import os import sys +# Append the current and parent directory paths to sys.path for module imports dir_path = os.path.dirname(os.path.realpath(__file__)) sys.path.append(os.path.join(dir_path)) sys.path.append(os.path.join(dir_path, "../")) +# Importing helper classes and modules for HDMI-CEC testing and logging from hdmiCECHelperClass import hdmiCECHelperClass from raft.framework.core.logModule import logModule from raft.framework.plugins.ut_raft.configRead import ConfigRead class hdmiCEC_test01_TransmitCECCommands(hdmiCECHelperClass): """ - Test class to enable, disable, and verify the status of audio ports on a device. - - This class uses the `dsAudioClass` to interact with the device's audio ports, - downloading necessary test assets, playing audio streams, enabling and disabling - audio ports, and performing verification of audio output. + A class for testing HDMI-CEC functionality by transmitting and verifying CEC commands. """ def __init__(self, log:logModule=None): """ - Initializes the test class with test name, setup configuration, and sessions for the device. + Initializes the test class with test-specific configurations. Args: - None + log (logModule): Logging module instance to record test execution. """ # Class variables self.testName = "test01_TransmitCECCommands" @@ -53,18 +51,24 @@ def __init__(self, log:logModule=None): self.tvLogicalAddress = '0' self.broadcastAddress = 'f' + # Initialize the parent class super().__init__(self.testName, self.qcID, log) def testFunction(self): """ - The main test function that Transmits the Stanby Command and checks the ACK and validates it. + Main test function for transmitting HDMI-CEC commands and validating responses. - This function: - - Send a standby command to a device that is connected on the CEC network and get the ack. - - User to confirm whether the targetted device had recieved this command or not. + Steps: + 1. Initialize HDMI-CEC module. + 2. Add a logical address to the test device. + 3. Get the logical address of the device. + 4. List all connected CEC devices. + 5. Iterate through devices and send commands to appropriate logical addresses. + 6. Validate transmission and record results. + 7. Clean up by removing logical addresses and terminating the HDMI-CEC module. Returns: - bool: Final result of the test. + bool: Final result of the test execution. """ # Initialize the hdmiCEC module @@ -76,14 +80,17 @@ def testFunction(self): # Get the logical Address. deviceLogicalAddress = self.testhdmiCEC.getLogicalAddress() + # List all connected CEC devices self.cecDevices = self.hdmiCECController.listDevices() + # Final test result finalResult = True + for device in self.cecDevices: logicalAddress = device["logical address"] - # To bypass sending the message to TV - if logicalAddress == '0' or logicalAddress == 'f': + # Skip sending messages to TV + if logicalAddress == '0' or logicalAddress == 'e': continue for command in self.cecCommands: @@ -92,15 +99,17 @@ def testFunction(self): payload = command.get("payload") type = command.get("type") + # Determine the destination logical address destinationLogicalAddress = logicalAddress if type == "Broadcast": destinationLogicalAddress = self.broadcastAddress - # Transmit Standby command to a specific destination address + # Transmit the CEC command self.testhdmiCEC.cecTransmitCmd(destinationLogicalAddress, cec, payload) self.log.stepStart(f'HdmiCecTx Source: {deviceLogicalAddress} Destination: {destinationLogicalAddress} CEC OPCode: {cec} Payload: {payload}') + # Validate the transmission result = self.hdmiCECController.checkTransmitStatus(deviceLogicalAddress, destinationLogicalAddress, cec, payload) self.log.stepResult(result, f'HdmiCecTx Source: {deviceLogicalAddress} Destination: {destinationLogicalAddress} CEC OPCode: {cec} Payload: {payload}') @@ -110,13 +119,16 @@ def testFunction(self): # Remove the Logical Address self.testhdmiCEC.removeLogicalAddress() - # Terminate dsAudio Module + # Terminate the hdmiCEC Module self.testhdmiCEC.terminate() return finalResult if __name__ == '__main__': + # Configure the summary log file summerLogName = os.path.splitext(os.path.basename(__file__))[0] + "_summery" summeryLog = logModule(summerLogName, level=logModule.INFO) + + # Create an instance of the test class and execute the test test = hdmiCEC_test01_TransmitCECCommands(summeryLog) test.run(False) diff --git a/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test02_ReceiveCECCommands.py b/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test02_ReceiveCECCommands.py index 329e4de..b433ae0 100644 --- a/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test02_ReceiveCECCommands.py +++ b/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test02_ReceiveCECCommands.py @@ -24,6 +24,7 @@ import os import sys +# Append the current and parent directory paths to sys.path for module imports dir_path = os.path.dirname(os.path.realpath(__file__)) sys.path.append(os.path.join(dir_path)) sys.path.append(os.path.join(dir_path, "../")) @@ -34,18 +35,15 @@ class hdmiCEC_test02_ReceiveCECCommands(hdmiCECHelperClass): """ - Test class to enable, disable, and verify the status of audio ports on a device. - - This class uses the `dsAudioClass` to interact with the device's audio ports, - downloading necessary test assets, playing audio streams, enabling and disabling - audio ports, and performing verification of audio output. + A class for testing HDMI-CEC functionality by sending CEC commands + and verifying the received callback data. """ def __init__(self, log:logModule=None): """ - Initializes the test class with test name, setup configuration, and sessions for the device. + Initializes the test class with test-specific configurations. Args: - None + log (logModule): Logging module instance to record test execution. """ # Class variables self.testName = "test02_ReceiveCECCommands" @@ -53,6 +51,7 @@ def __init__(self, log:logModule=None): self.tvLogicalAddress = '0' self.broadcastAddress = 'f' + # Initialize the parent class super().__init__(self.testName, self.qcID, log) def testVerifyReceivedData(self, callbackData:dict, initiatorLogicalAddress:int, destinationLogicalAddress:int, opCode:str, payload:list): @@ -70,10 +69,12 @@ def testVerifyReceivedData(self, callbackData:dict, initiatorLogicalAddress:int, """ result = False for received in callbackData["Received"]: + # Check if initiator, destination, and opcode match the expected values if (received["Initiator"] == initiatorLogicalAddress and received["Destination"] == destinationLogicalAddress and received["Opcode"] == opCode): result = True + # Verify payload if provided if payload: for rec, sent in zip(received["Data"][2:], payload): if rec != sent: @@ -83,14 +84,17 @@ def testVerifyReceivedData(self, callbackData:dict, initiatorLogicalAddress:int, def testFunction(self): """ - The main test function that Transmits the Stanby Command and checks the ACK and validates it. + Main test function to send CEC commands and validate received callback data. - This function: - - Send a standby command to a device that is connected on the CEC network and get the ack. - - User to confirm whether the targetted device had recieved this command or not. + Steps: + 1. Initialize HDMI-CEC module. + 2. Add and retrieve logical address of the device. + 3. Send commands to other devices and validate responses using callback data. + 4. Validate response commands if specified. + 5. Clean up by removing logical addresses and terminating the module. Returns: - bool: Final result of the test. + bool: Final result of the test execution. """ # Initialize the hdmiCEC module @@ -102,15 +106,18 @@ def testFunction(self): # Get the logical Address. deviceLogicalAddress = self.testhdmiCEC.getLogicalAddress() + # Ensure the logical address is retrieved successfully if deviceLogicalAddress is None: self.log.error("Failed to get the device logical address") return False + # Retrieve details of the HDMI-CEC adapter self.cecAdaptor = self.hdmiCECController.adaptorDetails if self.cecAdaptor is None: return False + # Get the logical address of the HDMI-CEC adapter cecAdapterLogicalAddress = self.cecAdaptor["logical address"] finalResult = True @@ -121,6 +128,7 @@ def testFunction(self): response = command.get("response") type = command.get("type") + # Determine the destination logical address destinationLogicalAddress = deviceLogicalAddress if type == "Broadcast": destinationLogicalAddress = self.broadcastAddress @@ -129,14 +137,15 @@ def testFunction(self): self.hdmiCECController.sendMessage(cecAdapterLogicalAddress, destinationLogicalAddress, cecOpcode, payload) + # Read the callback details and verify the received data callbackData = self.testhdmiCEC.readCallbackDetails() - result = self.testVerifyReceivedData(callbackData, cecAdapterLogicalAddress, destinationLogicalAddress, cecOpcode, payload) finalResult &= result self.log.stepResult(result, f'Send Test: {cecAdapterLogicalAddress} Destination: {destinationLogicalAddress} CEC OPCode: {cecOpcode} Payload: {payload}') + # If a response is expected, validate the response if response: destinationLogicalAddress = cecAdapterLogicalAddress if response.get("type") == "Broadcast": @@ -154,13 +163,16 @@ def testFunction(self): # Remove the Logical Address self.testhdmiCEC.removeLogicalAddress() - # Terminate dsAudio Module + # Terminate the hdmiCEC module self.testhdmiCEC.terminate() return finalResult if __name__ == '__main__': + # Configure the summary log file summerLogName = os.path.splitext(os.path.basename(__file__))[0] + "_summery" summeryLog = logModule(summerLogName, level=logModule.INFO) + + # Create an instance of the test class and execute the test test = hdmiCEC_test02_ReceiveCECCommands(summeryLog) test.run(False) diff --git a/profiles/sink/sink_hdmiCEC_test.yml b/profiles/sink/sink_hdmiCEC_test.yml deleted file mode 100644 index da5fb1b..0000000 --- a/profiles/sink/sink_hdmiCEC_test.yml +++ /dev/null @@ -1,34 +0,0 @@ -hdmicec: - config: - number_ports: 3 - test: - tx: - #CEC GET Version command - - command: - getcecVersion: - sinkla:0 - sourcela:1 - command:9F - expectedreply:02 - #CEC Standby command: - standby: - sinkla:0 - sourcela:1 - command:36 - setosd: - sinkla:0 - sourcela:1 - command:64 - data: - [80,48,65,6C,6C,6F,20,57,6F,72,6C,64,31,21], - [81,49,65,6D,6C,6F,20,57,6F,73,6C,64,32,22], - [82,50,65,6E,6C,6F,20,57,6F,74,6C,64,33,23], - [83,51,65,6F,6C,6F,20,57,6F,75,6C,64,34,24], - [84,52,65,6C,6C,6F,20,57,6F,76,6C,64,35,25], - [85,53,65,6C,6C,6F,20,57,6F,77,6C,64,36,26], - [86,54,65,6C,6C,6F,20,57,6F,78,6C,64,37,27], - [87,55,65,6C,6C,6F,20,57,6F,79,6C,64,38,28], - [88,56,65,6C,6C,6F,20,57,6F,7A,6C,64,39,29], - [89,57,65,6C,6C,6F,20,57,6F,7B,6C,64,40,30] - - From 9b498c534f054b3bb0945f9ce2a9b1863bad0a8e Mon Sep 17 00:00:00 2001 From: bhanucbp <141142298+bhanucbp@users.noreply.github.com> Date: Thu, 12 Dec 2024 19:56:55 +0000 Subject: [PATCH 26/40] gh #44 L3 test case development Added python file to run all tests Used monitor function to get the adaptor logs --- .../hdmiCEC_L3_Tests/hdmiCECHelperClass.py | 7 +- .../hdmiCEC_L3_Tests/hdmiCEC_L3_Runall.py | 73 +++++++++++++++++++ .../hdmiCEC_L3_Tests/hdmiCEC_L3_testSetup.yml | 29 -------- .../hdmiCEC_test01_TransmitCECCommands.py | 8 +- .../hdmiCEC_test02_ReceiveCECCommands.py | 3 + 5 files changed, 85 insertions(+), 35 deletions(-) create mode 100644 host/tests/hdmiCEC_L3_Tests/hdmiCEC_L3_Runall.py delete mode 100755 host/tests/hdmiCEC_L3_Tests/hdmiCEC_L3_testSetup.yml diff --git a/host/tests/hdmiCEC_L3_Tests/hdmiCECHelperClass.py b/host/tests/hdmiCEC_L3_Tests/hdmiCECHelperClass.py index d6d113d..f75eb56 100755 --- a/host/tests/hdmiCEC_L3_Tests/hdmiCECHelperClass.py +++ b/host/tests/hdmiCEC_L3_Tests/hdmiCECHelperClass.py @@ -53,16 +53,12 @@ def __init__(self, testName:str, qcId:str, log:logModule=None ): log (logModule, optional): Parent log module instance for logging. Defaults to None. """ self.testName = "" - self.testSetupPath = os.path.join(dir_path, "hdmiCEC_L3_testSetup.yml") self.moduleName = "hdmicec" self.rackDevice = "dut" # Initialize the base helper class super().__init__(testName, qcId, log) - # Load test setup configuration - self.testSetup = ConfigRead(self.testSetupPath, self.moduleName) - # Open Sessions hal test self.hal_session = self.dut.getConsoleSession("ssh_hal_test") @@ -80,7 +76,6 @@ def __init__(self, testName:str, qcId:str, log:logModule=None ): self.testCECCommands = os.path.join(dir_path, "hdmiCECTestCommands.yml") hdmicec = ConfigRead(self.testCECCommands, self.moduleName) self.cecCommands = hdmicec.fields.get(self.testName) - self.hdmiCECController = self.dut.hdmiCECController def testPrepareFunction(self): """ @@ -100,5 +95,7 @@ def testPrepareFunction(self): def testEndFunction(self, powerOff=True): + super().testEndFunction(powerOff) # Clean up the hdmiCEC instance del self.testhdmiCEC + diff --git a/host/tests/hdmiCEC_L3_Tests/hdmiCEC_L3_Runall.py b/host/tests/hdmiCEC_L3_Tests/hdmiCEC_L3_Runall.py new file mode 100644 index 0000000..05748ec --- /dev/null +++ b/host/tests/hdmiCEC_L3_Tests/hdmiCEC_L3_Runall.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python3 +#** ***************************************************************************** +# * +# * If not stated otherwise in this file or this component's LICENSE file the +# * following copyright and licenses apply: +# * +# * Copyright 2024 RDK Management +# * +# * Licensed under the Apache License, Version 2.0 (the "License"); +# * you may not use this file except in compliance with the License. +# * You may obtain a copy of the License at +# * +# * +# http://www.apache.org/licenses/LICENSE-2.0 +# * +# * Unless required by applicable law or agreed to in writing, software +# * distributed under the License is distributed on an "AS IS" BASIS, +# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# * See the License for the specific language governing permissions and +# * limitations under the License. +# * +#* ****************************************************************************** + +import os +import sys +import importlib +from pathlib import Path + +dir_path = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(dir_path)) +sys.path.append(os.path.join(dir_path, "../")) +sys.path.append(os.path.join(dir_path, "../raft")) + +from raft.framework.core.logModule import logModule + +def Runall_L3(): + skipTests = [] + # Summery log for all the tests + hdmiCECSummerLog = logModule("hdmiCEC_Sink", level=logModule.INFO) + + testDirectory = Path(dir_path) + + # Find all test modules in the directory + test_modules = sorted(testDirectory.glob("hdmiCEC_test*.py")) + + # Run each test by dynamically importing and instantiating + for test_module_path in test_modules: + # Construct module name from file name, excluding .py extension + module_name = test_module_path.stem + skip = False + for skipTest in skipTests: + if skipTest in module_name: + skip = True + break + if skip: + continue + try: + # Dynamically import the module + module = importlib.import_module(module_name) + + # Dynamically access the test class from the module + # Assuming each test file has only one class named the same as the module + test_class = getattr(module, module_name) + + # Instantiate and run the test + test_instance = test_class(hdmiCECSummerLog) + test_instance.run(False) + + except (ImportError, AttributeError) as e: + hdmiCECSummerLog.error(f"Failed to import {module_name}: {e}") + +if __name__ == '__main__': + Runall_L3() \ No newline at end of file diff --git a/host/tests/hdmiCEC_L3_Tests/hdmiCEC_L3_testSetup.yml b/host/tests/hdmiCEC_L3_Tests/hdmiCEC_L3_testSetup.yml deleted file mode 100755 index 8da1aa5..0000000 --- a/host/tests/hdmiCEC_L3_Tests/hdmiCEC_L3_testSetup.yml +++ /dev/null @@ -1,29 +0,0 @@ -#** ***************************************************************************** -# * -# * If not stated otherwise in this file or this component's LICENSE file the -# * following copyright and licenses apply: -# * -# * Copyright 2024 RDK Management -# * -# * Licensed under the Apache License, Version 2.0 (the "License"); -# * you may not use this file except in compliance with the License. -# * You may obtain a copy of the License at -# * -# * -# http://www.apache.org/licenses/LICENSE-2.0 -# * -# * Unless required by applicable law or agreed to in writing, software -# * distributed under the License is distributed on an "AS IS" BASIS, -# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# * See the License for the specific language governing permissions and -# * limitations under the License. -# * -#* ****************************************************************************** - -hdmicec: - description: "hdmiCEC test setup" - assets: - device: - test01_TransmitCECCommands: - test02_ReceiveCECCommands: - diff --git a/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test01_TransmitCECCommands.py b/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test01_TransmitCECCommands.py index 8f3919c..f45a26f 100755 --- a/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test01_TransmitCECCommands.py +++ b/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test01_TransmitCECCommands.py @@ -23,6 +23,7 @@ import os import sys +import time # Append the current and parent directory paths to sys.path for module imports dir_path = os.path.dirname(os.path.realpath(__file__)) @@ -32,7 +33,6 @@ # Importing helper classes and modules for HDMI-CEC testing and logging from hdmiCECHelperClass import hdmiCECHelperClass from raft.framework.core.logModule import logModule -from raft.framework.plugins.ut_raft.configRead import ConfigRead class hdmiCEC_test01_TransmitCECCommands(hdmiCECHelperClass): """ @@ -86,6 +86,8 @@ def testFunction(self): # Final test result finalResult = True + self.hdmiCECController.startMonitoring() + for device in self.cecDevices: logicalAddress = device["logical address"] @@ -107,6 +109,8 @@ def testFunction(self): # Transmit the CEC command self.testhdmiCEC.cecTransmitCmd(destinationLogicalAddress, cec, payload) + time.sleep(2) + self.log.stepStart(f'HdmiCecTx Source: {deviceLogicalAddress} Destination: {destinationLogicalAddress} CEC OPCode: {cec} Payload: {payload}') # Validate the transmission @@ -116,6 +120,8 @@ def testFunction(self): finalResult &= result + self.hdmiCECController.stopMonitoring() + # Remove the Logical Address self.testhdmiCEC.removeLogicalAddress() diff --git a/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test02_ReceiveCECCommands.py b/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test02_ReceiveCECCommands.py index b433ae0..5151309 100644 --- a/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test02_ReceiveCECCommands.py +++ b/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test02_ReceiveCECCommands.py @@ -120,6 +120,7 @@ def testFunction(self): # Get the logical address of the HDMI-CEC adapter cecAdapterLogicalAddress = self.cecAdaptor["logical address"] + self.hdmiCECController.startMonitoring() finalResult = True for command in self.cecCommands: result = False @@ -160,6 +161,8 @@ def testFunction(self): finalResult &= result + self.hdmiCECController.stopMonitoring() + # Remove the Logical Address self.testhdmiCEC.removeLogicalAddress() From 2ce8ce155b4022371672757c75e0749464e5055f Mon Sep 17 00:00:00 2001 From: bhanucbp <141142298+bhanucbp@users.noreply.github.com> Date: Tue, 17 Dec 2024 14:18:24 +0000 Subject: [PATCH 27/40] gh #44 L3 test case development Updated with review comments --- host/tests/classes/hdmiCEC.py | 10 ++ .../hdmiCEC_L3_Tests/hdmiCECHelperClass.py | 1 + .../hdmiCEC_L3_Tests/hdmiCECTestCommands.yml | 1 + .../hdmiCEC_test01_TransmitCECCommands.py | 34 +++-- .../hdmiCEC_test02_ReceiveCECCommands.py | 3 +- src/test_l3_hdmi_cec_sink_driver.c | 119 +++--------------- 6 files changed, 54 insertions(+), 114 deletions(-) diff --git a/host/tests/classes/hdmiCEC.py b/host/tests/classes/hdmiCEC.py index c85a544..c39d79e 100644 --- a/host/tests/classes/hdmiCEC.py +++ b/host/tests/classes/hdmiCEC.py @@ -221,6 +221,16 @@ def cecTransmitCmd(self, destLogicalAddress:str, cecCommand:str, cecData:list=No result = self.utMenu.select( self.testSuite, "Transmit CEC Command",promptWithAnswers) + pattern = r"Result HdmiCecTx\(.*OUT:result:\[(.*?)\]\).*HDMI_CEC_STATUS:\[(.*?)\]" + + txStatus = self.searchPattern(result, pattern) + + status = False + if txStatus == "HDMI_CEC_IO_SENT_AND_ACKD" or txStatus == "HDMI_CEC_IO_SENT_BUT_NOT_ACKD": + status = True + + return status + def readCallbackDetails (self): """ Parses the callback logs from the device. diff --git a/host/tests/hdmiCEC_L3_Tests/hdmiCECHelperClass.py b/host/tests/hdmiCEC_L3_Tests/hdmiCECHelperClass.py index f75eb56..5aa5123 100755 --- a/host/tests/hdmiCEC_L3_Tests/hdmiCECHelperClass.py +++ b/host/tests/hdmiCEC_L3_Tests/hdmiCECHelperClass.py @@ -76,6 +76,7 @@ def __init__(self, testName:str, qcId:str, log:logModule=None ): self.testCECCommands = os.path.join(dir_path, "hdmiCECTestCommands.yml") hdmicec = ConfigRead(self.testCECCommands, self.moduleName) self.cecCommands = hdmicec.fields.get(self.testName) + self.testLogicalAddress = hdmicec.logicalAddress def testPrepareFunction(self): """ diff --git a/host/tests/hdmiCEC_L3_Tests/hdmiCECTestCommands.yml b/host/tests/hdmiCEC_L3_Tests/hdmiCECTestCommands.yml index 65c6f2e..ba480e4 100644 --- a/host/tests/hdmiCEC_L3_Tests/hdmiCECTestCommands.yml +++ b/host/tests/hdmiCEC_L3_Tests/hdmiCECTestCommands.yml @@ -21,6 +21,7 @@ #* ****************************************************************************** hdmicec: + logicalAddress: '0' test01_TransmitCECCommands: - command: "0x82" # Active Soruce payload: ["0x00", "0x00"] diff --git a/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test01_TransmitCECCommands.py b/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test01_TransmitCECCommands.py index f45a26f..920e3a2 100755 --- a/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test01_TransmitCECCommands.py +++ b/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test01_TransmitCECCommands.py @@ -48,12 +48,24 @@ def __init__(self, log:logModule=None): # Class variables self.testName = "test01_TransmitCECCommands" self.qcID = '1' - self.tvLogicalAddress = '0' self.broadcastAddress = 'f' # Initialize the parent class super().__init__(self.testName, self.qcID, log) + def testVerifyTxResults(self, txResult:str, rxResult:bool): + """ + Verifies the tx and rx results. + + Args: + txResult(str): tx result + rxResult(bool): rx result + Returns: + bool: Final result of the test. + """ + + return rxResult + def testFunction(self): """ Main test function for transmitting HDMI-CEC commands and validating responses. @@ -75,7 +87,7 @@ def testFunction(self): self.testhdmiCEC.initialise() # Add the logical Address. - self.testhdmiCEC.addLogicalAddress(self.tvLogicalAddress) + self.testhdmiCEC.addLogicalAddress(self.testLogicalAddress) # Get the logical Address. deviceLogicalAddress = self.testhdmiCEC.getLogicalAddress() @@ -96,7 +108,6 @@ def testFunction(self): continue for command in self.cecCommands: - result = False cec = command.get("command") payload = command.get("payload") type = command.get("type") @@ -106,19 +117,24 @@ def testFunction(self): if type == "Broadcast": destinationLogicalAddress = self.broadcastAddress + self.log.stepStart(f'HdmiCecTx Source: {deviceLogicalAddress} Destination: {destinationLogicalAddress} CEC OPCode: {cec} Payload: {payload}') + # Transmit the CEC command - self.testhdmiCEC.cecTransmitCmd(destinationLogicalAddress, cec, payload) + txResults = self.testhdmiCEC.cecTransmitCmd(destinationLogicalAddress, cec, payload) - time.sleep(2) + self.log.stepResult(txResults, f'HdmiCecTx Source: {deviceLogicalAddress} Destination: {destinationLogicalAddress} CEC OPCode: {cec} Payload: {payload}') - self.log.stepStart(f'HdmiCecTx Source: {deviceLogicalAddress} Destination: {destinationLogicalAddress} CEC OPCode: {cec} Payload: {payload}') + finalResult &= txResults + + time.sleep(2) + self.log.stepStart(f'HdmiCecTx Receive Source: {deviceLogicalAddress} Destination: {destinationLogicalAddress} CEC OPCode: {cec} Payload: {payload}') # Validate the transmission - result = self.hdmiCECController.checkTransmitStatus(deviceLogicalAddress, destinationLogicalAddress, cec, payload) + rxResult = self.hdmiCECController.checkTransmitStatus(deviceLogicalAddress, destinationLogicalAddress, cec, payload) - self.log.stepResult(result, f'HdmiCecTx Source: {deviceLogicalAddress} Destination: {destinationLogicalAddress} CEC OPCode: {cec} Payload: {payload}') + self.log.stepResult(rxResult, f'HdmiCecTx Receive Source: {deviceLogicalAddress} Destination: {destinationLogicalAddress} CEC OPCode: {cec} Payload: {payload}') - finalResult &= result + finalResult &= rxResult self.hdmiCECController.stopMonitoring() diff --git a/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test02_ReceiveCECCommands.py b/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test02_ReceiveCECCommands.py index 5151309..18c1c45 100644 --- a/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test02_ReceiveCECCommands.py +++ b/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test02_ReceiveCECCommands.py @@ -48,7 +48,6 @@ def __init__(self, log:logModule=None): # Class variables self.testName = "test02_ReceiveCECCommands" self.qcID = '2' - self.tvLogicalAddress = '0' self.broadcastAddress = 'f' # Initialize the parent class @@ -101,7 +100,7 @@ def testFunction(self): self.testhdmiCEC.initialise() # Add the logical Address. - self.testhdmiCEC.addLogicalAddress(self.tvLogicalAddress) + self.testhdmiCEC.addLogicalAddress(self.testLogicalAddress) # Get the logical Address. deviceLogicalAddress = self.testhdmiCEC.getLogicalAddress() diff --git a/src/test_l3_hdmi_cec_sink_driver.c b/src/test_l3_hdmi_cec_sink_driver.c index c2f71c7..b8dd206 100644 --- a/src/test_l3_hdmi_cec_sink_driver.c +++ b/src/test_l3_hdmi_cec_sink_driver.c @@ -161,63 +161,6 @@ CecCommandMap cecCommandTable[] = { {0xFF, "Abort", 0} }; -typedef enum HDMI_CEC_DEVICE_TYPE_T -{ - HDMI_CEC_RECORDER = 1, - HDMI_CEC_AMPLIFIER, - HDMI_CEC_TUNER, - HDMI_CEC_PLAYBACK, - HDMI_CEC_AUDIO, - HDMI_CEC_TV, - HDMI_CEC_RESERVED -} HDMI_CEC_DEVICE_TYPE; - -const static ut_control_keyStringMapping_t cecDeviceType_mapTable[] = -{ - {"Recorder", (int32_t)HDMI_CEC_RECORDER}, - {"Amplifier", (int32_t)HDMI_CEC_AMPLIFIER}, - {"Tuner", (int32_t)HDMI_CEC_TUNER}, - {"Playback Device", (int32_t)HDMI_CEC_PLAYBACK}, - {"Audio System", (int32_t)HDMI_CEC_AUDIO}, - {"TV", (int32_t)HDMI_CEC_TV}, - {"Reserved", (int32_t)HDMI_CEC_RESERVED} -}; - -typedef enum HDMI_CEC_POWER_STATUS_T -{ - HDMI_CEC_ON = 0, - HDMI_CEC_STANDBY, - HDMI_CEC_TRANSIT_STANDBY, - HDMI_CEC_TRANSIT_ON -} HDMI_CEC_POWER_STATUS; - -const static ut_control_keyStringMapping_t cecPowerStatus_mapTable[] = -{ - {"On", (int32_t)HDMI_CEC_ON}, - {"Standby", (int32_t)HDMI_CEC_STANDBY}, - {"Transition to Standby", (int32_t)HDMI_CEC_TRANSIT_STANDBY}, - {"Transition to On", (int32_t)HDMI_CEC_TRANSIT_ON} -}; - -typedef enum HDMI_CEC_FEATURE_ABORT_REASON_T -{ - HDMI_CEC_UNRECOGNIZE = 0, - HDMI_CEC_NOTCORRECTMODE, - HDMI_CEC_CANNOTPROVIDE, - HDMI_CEC_INVALID, - HDMI_CEC_REFUSED, - HDMI_CEC_UNABLE -} HDMI_CEC_FEATURE_ABORT_REASON; - -const static ut_control_keyStringMapping_t cecFeatureAbortReason_mapTable[] = -{ - {"Unrecognized opcode", (int32_t)HDMI_CEC_UNRECOGNIZE}, - {"Not in Correct mode to respond", (int32_t)HDMI_CEC_NOTCORRECTMODE}, - {"Cannot provide source", (int32_t)HDMI_CEC_CANNOTPROVIDE}, - {"Invalid operand", (int32_t)HDMI_CEC_INVALID}, - {"Refused", (int32_t)HDMI_CEC_REFUSED}, - {"Unable to determine", (int32_t)HDMI_CEC_UNABLE} -}; /* cecError_t */ const static ut_control_keyStringMapping_t cecError_mapTable [] = { @@ -463,7 +406,6 @@ static void onRxDataReceived(int32_t handle, void *callbackData, uint8_t *buf, i * @brief Initialization of the HAL CEC Module * * This test provides a scope to open the HAL CEC module and preserve the handle. - * * **Test Group ID:** 03@n * @@ -473,9 +415,6 @@ static void onRxDataReceived(int32_t handle, void *callbackData, uint8_t *buf, i * * **Dependencies:** None@n * -* **User Interaction:** @n -* User or Automation tool should select the Test 1 to before running any test. -* */ void test_l3_hdmi_cec_sink_hal_Init(void) { @@ -517,7 +456,7 @@ void test_l3_hdmi_cec_sink_hal_Init(void) * This applies only for the Sink Devices. * Source devices will get the logical address during CEC open. * -* **Test Group ID:** 02@n +* **Test Group ID:** 03@n * * **Test Case ID:** 002@n * @@ -526,9 +465,6 @@ void test_l3_hdmi_cec_sink_hal_Init(void) * * **Dependencies:** None@n * -* **User Interaction:** @n -* User or Automation tool should select the Test 2 and provide the logical address. -* */ void test_l3_hdmi_cec_sink_hal_AddLogicalAddress(void) { @@ -565,7 +501,7 @@ void test_l3_hdmi_cec_sink_hal_AddLogicalAddress(void) * * This test provides a scope to check the assigned logical address of the device. * -* **Test Group ID:** 02@n +* **Test Group ID:** 03@n * * **Test Case ID:** 003@n * @@ -573,10 +509,6 @@ void test_l3_hdmi_cec_sink_hal_AddLogicalAddress(void) * HDMI-CEC Module should be intialized through Test 1 before calling this test. * * **Dependencies:** None@n -* -* **User Interaction:** @n -* User or Automation tool should select the Test 3 and shall read the Logical address displayed on the console. - * */ void test_l3_hdmi_cec_sink_hal_GetLogicalAddress(void) @@ -591,6 +523,7 @@ void test_l3_hdmi_cec_sink_hal_GetLogicalAddress(void) status = HdmiCecGetLogicalAddress(gHandle, &logicalAddress); UT_LOG_INFO("Result HdmiCecGetLogicalAddress(IN:handle:[0x%0X], OUT:logicalAddress:[%x]) HDMI_CEC_STATUS:[%s])", gHandle, logicalAddress, UT_Control_GetMapString(cecError_mapTable,status)); assert(status == HDMI_CEC_IO_SUCCESS); + assert(logicalAddress >= 0 && logicalAddress <= 15); UT_LOG_INFO("Out %s\n", __FUNCTION__); } @@ -601,19 +534,16 @@ void test_l3_hdmi_cec_sink_hal_GetLogicalAddress(void) * This test provides an interface to user/automation tool to transmit a CEC Command. * Necessary input should be provided to the test. * -* **Test Group ID:** 02@n +* **Test Group ID:** 03@n * * **Test Case ID:** 004@n * * **Pre-Conditions:** @n * HDMI-CEC Module should be intialized through Test 1 before calling this test. +* Logical Address should be added through Test 2 before calling this test. * * **Dependencies:** None@n * -* **User Interaction:** @n -* User or Automation tool should select the Test 4 and shall provide the necessary source and destination logical address, -* CEC command, data lenght and data. -* */ void test_l3_hdmi_cec_sink_hal_TransmitHdmiCecCommand(void) { gTestID = 4; @@ -671,7 +601,8 @@ void test_l3_hdmi_cec_sink_hal_TransmitHdmiCecCommand(void) { // Logging the transmission attempt UT_LOG_INFO("Calling HdmiCecTx(IN:handle:[0x%0X], IN:buf:[%p], IN:len:[%d], OUT:result:[])", gHandle, buf, len); int32_t status = HdmiCecTx(gHandle, buf, len, &result); - UT_LOG_INFO("Result HdmiCecTx(IN:handle:[0x%0X], IN:buf:[%p], IN:len:[%d], OUT:result:[%d]) HDMI_CEC_STATUS:[%s]", gHandle, buf, len, result, UT_Control_GetMapString(cecError_mapTable,status)); + UT_LOG_INFO("Result HdmiCecTx(IN:handle:[0x%0X], IN:buf:[%p], IN:len:[%d], OUT:result:[%s]) HDMI_CEC_STATUS:[%s]", gHandle, buf, len, UT_Control_GetMapString(cecError_mapTable, result)? UT_Control_GetMapString(cecError_mapTable, result):"HDMI_CEC_IO_SENT_FAILED", UT_Control_GetMapString(cecError_mapTable,status)); + assert(status == HDMI_CEC_IO_SUCCESS); UT_LOG_INFO("Out %s\n", __FUNCTION__); } @@ -681,23 +612,19 @@ void test_l3_hdmi_cec_sink_hal_TransmitHdmiCecCommand(void) { * * This test provides a scope to read the physical address of the device. * -* **Test Group ID:** 02@n +* **Test Group ID:** 03@n * -* **Test Case ID:** 006@n +* **Test Case ID:** 005@n * * **Pre-Conditions:** @n * HDMI-CEC Module should be intialized through Test 1 before calling this test. * * **Dependencies:** None@n * -* **User Interaction:** @n -* User or Automation tool should select the Test 6 to read the physical address of the device -* device connected in the network. -* */ void test_l3_hdmi_cec_sink_hal_GetPhysicalAddress(void) { - gTestID = 6; + gTestID = 5; UT_LOG_INFO("In %s [%02d%03d]\n", __FUNCTION__, gTestGroup, gTestID); HDMI_CEC_STATUS status = HDMI_CEC_IO_SUCCESS; @@ -717,22 +644,18 @@ void test_l3_hdmi_cec_sink_hal_GetPhysicalAddress(void) * This test provides a scope to remove the logical address of the device. HAL API to set * to default logical addres 0xF once the logical address is removed. * -* **Test Group ID:** 02@n +* **Test Group ID:** 03@n * -* **Test Case ID:** 07@n +* **Test Case ID:** 006@n * * **Pre-Conditions:** @n * HDMI-CEC Module should be intialized through Test 1 before calling this test. * * **Dependencies:** None@n -* -* **User Interaction:** @n -* User or Automation tool should select the Test 7 to delete the logical address. -* */ void test_l3_hdmi_cec_sink_hal_RemoveLogicalAddress(void) { - gTestID = 7; + gTestID = 6; UT_LOG_INFO("In %s [%02d%03d]\n", __FUNCTION__, gTestGroup, gTestID); HDMI_CEC_STATUS status = HDMI_CEC_IO_SUCCESS; @@ -746,12 +669,6 @@ void test_l3_hdmi_cec_sink_hal_RemoveLogicalAddress(void) UT_LOG_INFO("Result HdmiCecRemoveLogicalAddress(IN:handle:[0x%0X], IN:logicalAddress:[%d]) HDMI_CEC_STATUS:[%s])", gHandle, logicalAddress, UT_Control_GetMapString(cecError_mapTable,status)); assert(status == HDMI_CEC_IO_SUCCESS); - UT_LOG_INFO("Calling HdmiCecGetLogicalAddress(IN:handle:[0x%0X], OUT:logicalAddress:[])", gHandle); - status = HdmiCecGetLogicalAddress(gHandle, &getLogicalAddress); - UT_LOG_INFO("Result HdmiCecGetLogicalAddress(IN:handle:[0x%0X], OUT:logicalAddress:[%d]) HDMI_CEC_STATUS:[%s])", gHandle, getLogicalAddress, UT_Control_GetMapString(cecError_mapTable,status)); - assert(status == HDMI_CEC_IO_SUCCESS); - assert(getLogicalAddress == -1); - gLogicalAddress = -1; UT_LOG_INFO("Out %s\n", __FUNCTION__); @@ -761,22 +678,18 @@ void test_l3_hdmi_cec_sink_hal_RemoveLogicalAddress(void) * * This test provides a scope to close the created HDMI CEC handle. * -* **Test Group ID:** 02@n +* **Test Group ID:** 03@n * -* **Test Case ID:** 08@n +* **Test Case ID:** 007@n * * **Pre-Conditions:** @n * HDMI-CEC Module should be intialized through Test 1 before calling this test. * * **Dependencies:** None@n -* -* **User Interaction:** @n -* User or Automation tool should select the Test 8 to close the created HDMI CEC handle. -* */ void test_l3_hdmi_cec_sink_hal_Close(void) { - gTestID = 8; + gTestID = 7; HDMI_CEC_STATUS status; UT_LOG_INFO("In %s [%02d%03d]\n", __FUNCTION__, gTestGroup, gTestID); From 39dfa92ff6df159dbcf63b0464860a6a9d84aec9 Mon Sep 17 00:00:00 2001 From: bhanucbp <141142298+bhanucbp@users.noreply.github.com> Date: Tue, 17 Dec 2024 17:38:33 +0000 Subject: [PATCH 28/40] gh #44 L3 test case development Updated test for source devices --- host/tests/classes/hdmiCEC.py | 18 + host/tests/classes/hdmiCEC_testConfig.yml | 2 +- .../hdmiCEC_L3_Tests/hdmiCECHelperClass.py | 1 + .../hdmiCEC_test01_TransmitCECCommands.py | 2 +- profiles/source/source_hdmiCEC.yml | 135 +++ src/test_l3_hdmi_cec_driver.c | 1063 ++++++++++------- src/test_l3_hdmi_cec_sink_driver.c | 737 ------------ 7 files changed, 817 insertions(+), 1141 deletions(-) delete mode 100644 src/test_l3_hdmi_cec_sink_driver.c diff --git a/host/tests/classes/hdmiCEC.py b/host/tests/classes/hdmiCEC.py index c39d79e..b4ce310 100644 --- a/host/tests/classes/hdmiCEC.py +++ b/host/tests/classes/hdmiCEC.py @@ -59,6 +59,7 @@ def __init__(self, moduleConfigProfileFile:str, session=None, targetWorkspace:st self.testSuite = "L3 HDMICEC Sink Functions" # Prepare the profile file on the target workspace + self.moduleConfigProfile = ConfigRead( moduleConfigProfileFile , self.moduleName) profileOnTarget = os.path.join(targetWorkspace, os.path.basename(moduleConfigProfileFile)) self.testConfig = ConfigRead(self.testConfigFile, self.moduleName) self.testConfig.test.execute = os.path.join(targetWorkspace, self.testConfig.test.execute) + f" -p {profileOnTarget}" @@ -286,6 +287,23 @@ def parse_data_field(data_field): return result + def getDeviceType(self): + """ + Retrieves the type of the audio device. + + Args: + None. + + Returns: + str: The type of device: + - "sink" - sink device. + - "source" - source device. + - None if the device type is unknown or unsupported. + """ + type = self.moduleConfigProfile.fields.get("type") + + return type + def __del__(self): """ Cleans up and de-initializes the hdmi cec helper by stopping the test menu. diff --git a/host/tests/classes/hdmiCEC_testConfig.yml b/host/tests/classes/hdmiCEC_testConfig.yml index 40ac032..18ed34e 100644 --- a/host/tests/classes/hdmiCEC_testConfig.yml +++ b/host/tests/classes/hdmiCEC_testConfig.yml @@ -54,7 +54,7 @@ hdmicec: - "L2_VerifyPhysicalAddress_Sink" - "L2_TransmitCECCommand_Sink" 2: - name: "L3 hdmicec - Sink" + name: "L3 HDMICEC Functions" tests: - "Init HDMI CEC" - "Add Logical Address" diff --git a/host/tests/hdmiCEC_L3_Tests/hdmiCECHelperClass.py b/host/tests/hdmiCEC_L3_Tests/hdmiCECHelperClass.py index 5aa5123..db1fc0d 100755 --- a/host/tests/hdmiCEC_L3_Tests/hdmiCECHelperClass.py +++ b/host/tests/hdmiCEC_L3_Tests/hdmiCECHelperClass.py @@ -91,6 +91,7 @@ def testPrepareFunction(self): # Create the hdmiCEC class self.testhdmiCEC = hdmiCECClass(self.moduleConfigProfileFile, self.hal_session, self.targetWorkspace) + self.deviceType = self.testhdmiCEC.getDeviceType() return True diff --git a/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test01_TransmitCECCommands.py b/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test01_TransmitCECCommands.py index 920e3a2..fc993e7 100755 --- a/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test01_TransmitCECCommands.py +++ b/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test01_TransmitCECCommands.py @@ -104,7 +104,7 @@ def testFunction(self): logicalAddress = device["logical address"] # Skip sending messages to TV - if logicalAddress == '0' or logicalAddress == 'e': + if logicalAddress == deviceLogicalAddress: continue for command in self.cecCommands: diff --git a/profiles/source/source_hdmiCEC.yml b/profiles/source/source_hdmiCEC.yml index 7b8fff6..67b4790 100644 --- a/profiles/source/source_hdmiCEC.yml +++ b/profiles/source/source_hdmiCEC.yml @@ -4,3 +4,138 @@ hdmicec: features: extendedEnumsSupported: false + + cec_responses: + - command: "0x00" # Feature Abort + payload: + type: "Direct" + response: + type: "Direct" + command: "0x9E" + update_payload: true + payload: ["0x00", "0x00"] + description: "Feature Abort Reason" + - command: "0x04" # Image View on + payload: + type: "Direct" + response: null + - command: "0x0D" # Text View On + payload: + type: "Direct" + response: null + - command: "0x32" # Set Menu Language + payload: + type: "Broadcast" + response: null + - command: "0x36" # Standby + payload: + type: "Both" + response: null + - command: "0x46" # Give OSD Name + payload: + type: "Direct" + response: + type: "Direct" + command: "0x47" + update_payload: false + payload: ["0x52", "0x44", "0x4b", "0x20", "0x56", "0x54", "0x53", "0x20", "0x44", "0x65", "0x76", "0x69", "0x63", "0x65"] + description: "Device request OSD name" + - command: "0x47" # report OSD Name + payload: + type: "Direct" + response: null + - command: "0x64" # Set OSD String + payload: + type: "Direct" + response: null + - command: "0x82" # Active source + payload: + type: "Broadcast" + response: null + - command: "0x83" # Give Physical Address + payload: + type: "Direct" + response: + type: "Broadcast" + command: "0x84" + update_payload: true + payload: ["0x00", "0x00", "0x00"] + description: "Report Physical Address" + - command: "0x84" # Report Physical address + payload: + type: "Broadcast" + response: null + - command: "0x85" # Request Active source + payload: + type: "Broadcast" + response: + type: "Broadcast" + command: "0x82" + update_payload: true + payload: ["0x00", "0x00"] + description: "Active Soruce" + - command: "0x87" # Device Vendor ID + payload: + type: "Broadcast" + response: null + - command: "0x8C" # Give Vendor ID + payload: + type: "Direct" + response: + type: "Broadcast" + command: "0x87" + update_payload: false + payload: ["0x00", "0x00", "0x01"] + description: "Device Vendor Id" + - command: "0x8F" # Give power status + payload: + type: "Direct" + response: + type: "Direct" + command: "0x90" + update_payload: false + payload: ["0x00"] + description: "Report power status" + - command: "0x90" # Power Status + payload: + type: "Direct" + response: null + - command: "0x91" # Get Menu Language + payload: + type: "Direct" + response: + type: "Broadcast" + command: "0x32" + update_payload: false + payload: ["0x65", "0x6E", "0x67"] + description: "Set Menu Language" + - command: "0x9E" # CEC Version + response: null + - command: "0x9F" # Get CEC version + payload: + type: "Direct" + response: + type: "Direct" + command: "0x9E" + update_payload: false + payload: ["0x05"] + description: "Device request for CEC version" + - command: "0xA7" # Request Latency + payload: + type: "Broadcast" + response: + type: "Broadcast" + command: "0xA8" + update_payload: true + # 100msec video delay ((number of milliseconds/2) + 1) + # 200msec audio delay ((number of milliseconds/2) + 1) + # (Bits 1-0) : Audio Ouput Compensated (0 - N/A, 1 - TV audio output is delay compensated, 2 - TV audio output is NOT delay compensated, 3 - TV audio output is Par delay compensated) + # (Bit 2) : 0 - normal latency, 1 - low latency + # Bit(7-3) : Reserved + payload: ["0x00", "0x00", "0x65", "0x00", "0x33"] + description: "Report Physical Address" + - command: "0xA8" # Report Physical Address + payload: + type: "Broadcast" + response: null + diff --git a/src/test_l3_hdmi_cec_driver.c b/src/test_l3_hdmi_cec_driver.c index 51a7bcb..13fb827 100644 --- a/src/test_l3_hdmi_cec_driver.c +++ b/src/test_l3_hdmi_cec_driver.c @@ -1,536 +1,795 @@ -/** -* If not stated otherwise in this file or this component's LICENSE -* file the following copyright and licenses apply: -* -* Copyright 2023 RDK Management +/* +* If not stated otherwise in this file or this component's LICENSE file the +* following copyright and licenses apply:* +* Copyright 2024 RDK Management * -* Licensed under the Apache License, Version 2.0 (the License); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at * -* http://www.apache.org/licenses/LICENSE-2.0 +* http://www.apache.org/licenses/LICENSE-2.0 * -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an AS IS BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. */ +/** + * @addtogroup HPK Hardware Porting Kit + * @{ + * + */ +/** + * @addtogroup HDMI_CEC HDMI CEC Module + * @{ + * + */ +/** + * @defgroup HDMI_CEC_HALTESTS HDMI CEC HAL Tests + * @{ + * + */ /** -* @file TODO: test_l3_hdmi_cec_driver.c -* @page module_name TODO: Required field, name of the main module -* @subpage sub_page_name TODO: Add a function group if relevant -* -* ## Module's Role -* TODO: Explain the module's role in the system in general -* This is to ensure that the API meets the operational requirements of the module across all vendors. -* -* **Pre-Conditions:** TODO: Add pre-conditions if any@n -* **Dependencies:** TODO: Add dependencies if any@n -* -* Ref to API Definition specification documentation :[hdmi-cec_halSpec.md](../../docs/pages/hdmi-cec_halSpec.md) -*/ + * @defgroup HDMI_CEC_HALTESTS_L3 HDMI CEC HAL Tests L2 File + * @{ + * @parblock + * + * ### L2 Test Cases for HDMI CEC HAL : + * + * + * ## Module's Role + * This module includes Level 3 functional test interfaces. + * This Test Interfaces provides a scope to create a User Test cases for HDMI CEC Sink modules that can be either Manual or automated scripts. + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * + * Refer to API Definition specification documentation : [hdmi-cec_halSpec.md](../../docs/pages/hdmi-cec_halSpec.md) + * + * @endparblock + */ -#include -#include -#include -#include -#include -#include +/** + * @file test_l3_hdmi_cec_driver.c + * + */ +#include #include #include #include +#include #include "hdmi_cec_driver.h" -#define DEFAULT_LOGICAL_ADDRESS_PANEL 0 - -#define MAX_WAIT_TIME_SECS 30 -#define MAX_DATA_SIZE 64 - -#define CEC_IMAGE_VIEW_ON 0x04 -#define CEC_TEXT_VIEW_ON 0x0D -#define CEC_STANDBY 0x36 -#define CEC_SET_OSD_NAME 0x49 -#define CEC_ACTIVE_SOURCE 0x82 -#define CEC_REQUEST_ACTIVE_SOURCE 0x85 -#define CEC_INACTIVE_SOURCE 0x9D -#define CEC_COMMAND_UNKNOWN 0x00 - -#define CMD_IMAGE_VIEW_ON "ImageViewOn" -#define CMD_TEXT_VIEW_ON "TextViewOn" -#define CMD_STANDBY "StandBy" -#define CMD_ACTIVE_SOURCE "ActiveSource" -#define CMD_REQUEST_ACTIVE_SOURCE "RequestActiveSource" -#define CMD_INACTIVE_SOURCE "InactiveSource" -#define CMD_SET_OSD_NAME "SetOSDName" - -#define VP_PREFIX "hdmicec/" -#define CMD_DATA_OSD_NAME "/osd_name" -#define VP_RESULT_INITIATOR "/result/initiator" -#define VP_RESULT_DESTINATION "/result/destination" -#define VP_RESULT_OPCODE "/result/opcode" -#define VP_RESULT_PARAMETER_SIZE "/result/parameters/size" -#define VP_RESULT_PARAMETER_DATA "/result/parameters/data/" - -#define COUNT(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x]))))) +#define TIMEOUT 5 +#define REPLY_TIMEOUT 5 + +#define HDMI_CEC_MAX_PAYLOAD 128 +#define HDMI_CEC_MAX_OSDNAME 15 +#define HDMI_CEC_KVP_SIZE 128 +#define HDMI_CEC_TYPE_SIZE 16 +#define HDMI_CEC_DEVICE_TYPE_SIZE 8 + +#define UT_LOG_MENU_INFO UT_LOG_INFO typedef struct { - char* str; - int val; -} strVal_t; - -const static strVal_t gOpCode [] = { - { CMD_IMAGE_VIEW_ON, CEC_IMAGE_VIEW_ON }, - { CMD_TEXT_VIEW_ON, CEC_TEXT_VIEW_ON }, - { CMD_SET_OSD_NAME, CEC_SET_OSD_NAME }, - { CMD_STANDBY , CEC_STANDBY }, - { CMD_ACTIVE_SOURCE, CEC_ACTIVE_SOURCE }, - { CMD_REQUEST_ACTIVE_SOURCE, CEC_REQUEST_ACTIVE_SOURCE }, - { CMD_INACTIVE_SOURCE, CEC_INACTIVE_SOURCE } -}; + uint8_t cecCommand; // CEC command code + const char* commandName; // Human-readable command name + int32_t dataLength; // Number of data bytes required for the command +} CecCommandMap; +typedef struct cecResponse +{ + uint8_t cecCommand; //CEC opcode + uint32_t payloadSize; //CEC payload size + uint8_t type[UT_KVP_MAX_ELEMENT_SIZE]; //Type of the opcode Broadcast/ Direct + uint8_t payload[HDMI_CEC_MAX_PAYLOAD]; //CEC Payload + bool updatePhysicalAddress; +} cecResponse_t; + +CecCommandMap cecCommandTable[] = { + {0x00, "Feature Abort", 2}, + {0x04, "Image View On", 0}, + {0x05, "Tuner Step Increment", 0}, + {0x06, "Tuner Step Decrement", 0}, + {0x07, "Tuner Device Status", 8}, + {0x08, "Give Tuner Device Status", 0}, + {0x09, "Record On", 8}, + {0x0A, "Record Status", 8}, + {0x0B, "Record Off", 0}, + {0x0D, "Text View On", 0}, + {0x0F, "Record TV Screen", 0}, + {0x1A, "Give Deck Status", 0}, + {0x1B, "Deck Status", 1}, + {0x32, "Set Menu Language", 3}, + {0x33, "Clear Analog Timer", 0}, + {0x34, "Set Analog Timer", 8}, + {0x35, "Timer Status", 3}, + {0x36, "Standby", 0}, + {0x41, "Play", 0}, + {0x42, "Deck Control", 1}, + {0x43, "Timer Cleared Status", 1}, + {0x44, "User Control Pressed", 1}, + {0x45, "User Control Released", 0}, + {0x46, "Give OSD Name", 0}, + {0x47, "Set OSD Name", 14}, + {0x64, "Set OSD String", 14}, + {0x67, "Set Timer Program Title", 14}, + {0x70, "System Audio Mode Request", 2}, + {0x71, "Give Audio Status", 0}, + {0x72, "Set System Audio Mode", 1}, + {0x7A, "Report Audio Status", 1}, + {0x7D, "Give System Audio Mode Status", 0}, + {0x7E, "System Audio Mode Status", 1}, + {0x80, "Routing Change", 4}, + {0x81, "Routing Information", 2}, + {0x82, "Active Source", 2}, + {0x83, "Give Physical Address", 0}, + {0x84, "Report Physical Address", 3}, + {0x85, "Request Active Source", 0}, + {0x86, "Set Stream Path", 2}, + {0x87, "Device Vendor ID", 3}, + {0x89, "Vendor Command", 14}, + {0x8A, "Vendor Remote Button Down", 1}, + {0x8B, "Vendor Remote Button Up", 0}, + {0x8C, "Give Device Vendor ID", 0}, + {0x8D, "Menu Request", 1}, + {0x8E, "Menu Status", 1}, + {0x8F, "Give Device Power Status", 0}, + {0x90, "Report Power Status", 1}, + {0x91, "Get Menu Language", 0}, + {0x92, "Select Analog Service", 4}, + {0x93, "Select Digital Service", 4}, + {0x97, "Set Digital Timer", 6}, + {0x99, "Clear Digital Timer", 0}, + {0x9A, "Set Audio Rate", 1}, + {0x9D, "Inactive Source", 2}, + {0x9E, "CEC Version", 1}, + {0x9F, "Get CEC Version", 0}, + {0xA0, "Vendor Command With ID", 17}, + {0xA1, "Clear External Timer", 0}, + {0xA2, "Set External Timer", 9}, + {0xA7, "Request Current Latency", 2}, + {0xA8, "Report Current Latency", 5}, + {0xC0, "Initiate ARC", 0}, + {0xC1, "Report ARC Initiated", 0}, + {0xC2, "Report ARC Terminated", 0}, + {0xC3, "Request ARC Initiation", 0}, + {0xC4, "Request ARC Termination", 0}, + {0xC5, "Terminate ARC", 0}, + {0xFF, "Abort", 0} +}; -static UT_test_suite_t * pSuite = NULL; -static int gTestGroup = 1; -static int gTestID = 1; +/* cecError_t */ +const static ut_control_keyStringMapping_t cecError_mapTable [] = +{ + {"HDMI_CEC_IO_SUCCESS", (int32_t)HDMI_CEC_IO_SUCCESS}, + {"HDMI_CEC_IO_SENT_AND_ACKD", (int32_t)HDMI_CEC_IO_SENT_AND_ACKD}, + {"HDMI_CEC_IO_SENT_BUT_NOT_ACKD", (int32_t)HDMI_CEC_IO_SENT_BUT_NOT_ACKD}, + {"HDMI_CEC_IO_SENT_FAILED", (int32_t)HDMI_CEC_IO_SENT_FAILED}, + {"HDMI_CEC_IO_NOT_OPENED", (int32_t)HDMI_CEC_IO_NOT_OPENED}, + {"HDMI_CEC_IO_INVALID_ARGUMENT", (int32_t)HDMI_CEC_IO_INVALID_ARGUMENT}, + {"HDMI_CEC_IO_LOGICALADDRESS_UNAVAILABLE", (int32_t)HDMI_CEC_IO_LOGICALADDRESS_UNAVAILABLE}, + {"HDMI_CEC_IO_GENERAL_ERROR", (int32_t)HDMI_CEC_IO_GENERAL_ERROR}, + {"HDMI_CEC_IO_ALREADY_OPEN", (int32_t)HDMI_CEC_IO_ALREADY_OPEN}, + {"HDMI_CEC_IO_ALREADY_REMOVED", (int32_t)HDMI_CEC_IO_ALREADY_REMOVED}, + {"HDMI_CEC_IO_INVALID_OUTPUT", (int32_t)HDMI_CEC_IO_INVALID_OUTPUT}, + {"HDMI_CEC_IO_INVALID_HANDLE", (int32_t)HDMI_CEC_IO_INVALID_HANDLE}, + {"HDMI_CEC_IO_OPERATION_NOT_SUPPORTED", (int32_t)HDMI_CEC_IO_OPERATION_NOT_SUPPORTED}, + {"HDMI_CEC_IO_NOT_ADDED", (int32_t)HDMI_CEC_IO_NOT_ADDED}, + {"HDMI_CEC_IO_MAX", (int32_t)HDMI_CEC_IO_MAX}, + { NULL, -1 } +}; -static uint8_t gExpectedCecCommand = CEC_COMMAND_UNKNOWN; //Set teach test before waiting for trigger -static sem_t gSemCallbackReceived; -static uint8_t gCommandValidated = CEC_COMMAND_UNKNOWN; //Set by receive callback after test validation is successful +typedef enum HDMI_CEC_DEVICE_TYPE_t +{ + SINK = 0, + SOURCE = 1 +}HDMI_CEC_DEVICE_TYPE; + +static int32_t gTestGroup = 3; +static int32_t gTestID = 1; +static int32_t gHandle = 1; +static int32_t gLogicalAddress = -1; +static uint32_t gPhysicalAddress = -1; +static uint8_t *gPhysicalAddressBytes; +static uint8_t gBroadcastAddress = 0xF; +static HDMI_CEC_DEVICE_TYPE gDeviceType = SINK; +/** +* @brief CEC Command with data size mapping function. +* +* This function maps the provided CEC command with the data length required for the CEC Command. +* This will help the test to consider the correct size of the data required for the CEC Command. +* +*/ +static int32_t getCecCommandInfo(uint8_t cecCommand, const char** commandName, int32_t* dataLength) +{ -static ut_kvp_instance_t *gValidationProfileInstance = NULL; + int32_t tableSize = sizeof(cecCommandTable) / sizeof(CecCommandMap); -int GetOpCode(const strVal_t *map, int length, char* str) -{ - int result = -1; - - if(map == NULL || length <= 0 || str == NULL) - { - return result; - } - - for (int i = 0; i < length; ++i) - { - if (!strcmp(str, map[i].str)) + for (int32_t i = 0; i < tableSize; i++) { - result = map[i].val; - break; + if (cecCommandTable[i].cecCommand == cecCommand) + { + *commandName = cecCommandTable[i].commandName; + *dataLength = cecCommandTable[i].dataLength; + return 0; // Command found + } } - } - return result; -} -char* GetOpCodeString(const strVal_t *map, int length, int val) -{ - char* result = NULL; - - if(map == NULL || length <= 0) - { - return NULL; - } - - for (int i = 0; i < length; ++i) - { - if (val == (int)map[i].val) - { - result = map[i].str; - break; - } - } - return result; + return -1; // Command not found } - /** - * @brief hdmicec receive message callback - * - * @param handle Hdmi device handle - * @param callbackData callback data passed - * @param buf receive message buffer passed - * @param len receive message buffer length + * @brief This function clears the stdin buffer. + * + * This function clears the stdin buffer. */ -void ReceiveCallback(int handle, void *callbackData, unsigned char *buf, int len) +static void readAndDiscardRestOfLine(FILE *in) { - uint8_t src, dest, opcode; - uint8_t expected_src, expected_dest, expected_opcode; - uint8_t physical_address[4]; - char* expected_command = NULL; - ut_kvp_instance_t *vp_instance; - char szReturnedString[UT_KVP_MAX_ELEMENT_SIZE]; - char field_name[UT_KVP_MAX_ELEMENT_SIZE]; - uint8_t parameter_data[UT_KVP_MAX_ELEMENT_SIZE]; - uint8_t parameter_size = 0; - int length = 0, field_len = 0; - - UT_LOG ("\nBuffer generated: %x length: %d\n",buf, len); - if((handle!=0) && (callbackData !=NULL) && (len>0)) - { - vp_instance = (ut_kvp_instance_t *)callbackData; + int32_t c; + while ((c = fgetc(in)) != EOF && c != '\n'); +} - UT_LOG("\nCall back data generated is \n"); - for (int index=0; index < len; index++) - { - UT_LOG("buf at index : %d is %x", index, buf[index]); - } +static void readInt(int32_t *value) +{ + scanf("%d", value); + readAndDiscardRestOfLine(stdin); +} - src = (buf[0] & 0xF0) >> 4; - dest = buf[0] & 0x0F; - opcode = buf[1]; +static void readHex(int32_t *value) +{ + scanf("%x", value); + readAndDiscardRestOfLine(stdin); +} - expected_command = GetOpCodeString(gOpCode, COUNT(gOpCode), gExpectedCecCommand); - strcpy(field_name, VP_PREFIX); - strcpy(field_name + strlen(VP_PREFIX), expected_command); - length = strlen(field_name); +static bool getCommandResponse(uint8_t opcode, cecResponse_t *pResponse) +{ + uint32_t numCommands = 0; + char key_string[HDMI_CEC_KVP_SIZE] = {0}; - strcpy(field_name + length, VP_RESULT_INITIATOR); - expected_src = ut_kvp_getUInt8Field (vp_instance, field_name); + memset(pResponse, 0, sizeof(cecResponse_t)); - strcpy(field_name + length, VP_RESULT_DESTINATION); - expected_dest = ut_kvp_getUInt8Field (vp_instance, field_name); + numCommands = UT_KVP_PROFILE_GET_LIST_COUNT("hdmicec/cec_responses"); - strcpy(field_name + length, VP_RESULT_OPCODE); - expected_opcode = ut_kvp_getUInt8Field (vp_instance, field_name); + for(uint32_t i = 0; i < numCommands; i++) + { + uint8_t command; + uint8_t found; - strcpy(field_name + length, VP_RESULT_PARAMETER_SIZE); - parameter_size = ut_kvp_getUInt8Field (vp_instance, field_name); - field_len = strlen(field_name); - strcpy(field_name + length, VP_RESULT_PARAMETER_DATA); + snprintf(key_string, HDMI_CEC_KVP_SIZE, "hdmicec/cec_responses/%d/command" , i); + command = UT_KVP_PROFILE_GET_UINT8(key_string); - for (int i = 0; i < parameter_size; ++i) + if(command != opcode) { - int num_len = snprintf( NULL, 0, "%d", i ); - snprintf( field_name + field_len + 1 , num_len + 1, "%d", i ); - parameter_data[i] = ut_kvp_getUInt8Field (vp_instance, field_name); - UT_LOG("Expected Parameter data at [%d]: 0x%02x",i,parameter_data[i]); + continue; } + snprintf(key_string, HDMI_CEC_KVP_SIZE, "hdmicec/cec_responses/%d/response/command" , i); + found = ut_kvp_fieldPresent(ut_kvp_profile_getInstance(), key_string); - UT_LOG("\nExpected Command[%s] Src[%d] Dest[%d] \n", (GetOpCodeString(gOpCode, COUNT(gOpCode), gExpectedCecCommand)),expected_src, expected_dest); - UT_LOG("\nCommand[%s] triggered Src[%d] Dest[%d] \n", (GetOpCodeString(gOpCode, COUNT(gOpCode), opcode)),src, dest); - - switch (opcode) + if(found) { - case CEC_ACTIVE_SOURCE: - case CEC_INACTIVE_SOURCE: - { - UT_LOG("\nPhysicalAddress[%d.%d.%d.%d]\n",(buf[2] >> 4) & 0x0F, buf[2] & 0x0F, (buf[3] >> 4) & 0xF0, buf[3] & 0x0F); - } - break; - case CEC_SET_OSD_NAME: + pResponse->cecCommand = UT_KVP_PROFILE_GET_UINT8(key_string); + + snprintf(key_string, HDMI_CEC_KVP_SIZE, "hdmicec/cec_responses/%d/response/type" , i); + UT_KVP_PROFILE_GET_STRING(key_string, pResponse->type); + + snprintf(key_string, HDMI_CEC_KVP_SIZE, "hdmicec/cec_responses/%d/response/payload" , i); + pResponse->payloadSize = UT_KVP_PROFILE_GET_LIST_COUNT(key_string); + + for(uint8_t j = 0; j < pResponse->payloadSize; j++) { - char str[len - 1]; - memcpy(str, &buf[2], len-2); - str[len-2] = '\0'; - UT_LOG("\nosd_name[%s]\n", str); + snprintf(key_string, HDMI_CEC_KVP_SIZE, "hdmicec/cec_responses/%d/response/payload/%d" , i, j); + pResponse->payload[j] = UT_KVP_PROFILE_GET_UINT8(key_string); } - break; - } - //Lets see if this the opcode that was expected. If it is not test will timeout - if(gExpectedCecCommand == opcode) - { - //Lets validate the addresses and opcode - if(src == expected_src && dest == expected_dest && opcode == expected_opcode) + + snprintf(key_string, HDMI_CEC_KVP_SIZE, "hdmicec/cec_responses/%d/response/update_payload" , i); + pResponse->updatePhysicalAddress = UT_KVP_PROFILE_GET_BOOL(key_string); + + if (pResponse->updatePhysicalAddress) { - UT_LOG("\nParameter size[%d] received size[%d]\n", parameter_size, len - 2); - //Expected parameter size should be equal to length of cec buffer received minus 2 (Address, opcode bytes) - gCommandValidated = gExpectedCecCommand; - if(parameter_size > 0) - { - if((parameter_size != (len - 2)) || (memcmp(parameter_data, &buf[2], parameter_size) != 0)) - { - gCommandValidated = CEC_COMMAND_UNKNOWN; - } - } + pResponse->payload[0] = (((uint8_t)gPhysicalAddressBytes[3] << 4) & 0xF0) | (gPhysicalAddressBytes[2] & 0x0F); + pResponse->payload[1] = (((uint8_t)gPhysicalAddressBytes[1] << 4) & 0xF0) | (gPhysicalAddressBytes[0] & 0x0F); } - //Even if the validation fails, signal the test as the opcode is same. - sem_post(&gSemCallbackReceived); + + return true; } } - else + return false; +} + +static void sendResponse(int32_t handle, uint8_t initiator, uint8_t destination, + uint8_t *buf, int32_t len, cecResponse_t *pCecResponse) +{ + uint8_t prBuffer[HDMI_CEC_MAX_PAYLOAD] = {0}; + uint8_t response[HDMI_CEC_MAX_PAYLOAD] = {0}; + + if (pCecResponse->payloadSize) { - if (handle == 0) { - UT_FAIL("Error: Invalid handle.\n"); + int32_t result; + const char* commandName; + int32_t expectedDataLength; + + if (!strcmp(pCecResponse->type, "Direct")) + { + response[0] = (destination << 4) | initiator; } - if (callbackData == NULL) { - UT_FAIL("Error: Null callback data.\n"); + else + { + //Send braodcast message + response[0] = (gLogicalAddress << 4) | gBroadcastAddress; } - if (len <= 0) { - UT_FAIL("Error: Invalid length.\n"); + response[1] = pCecResponse->cecCommand; + + for (int32_t index = 0; index < pCecResponse->payloadSize; index++) + { + response[index + 2] = pCecResponse->payload[index]; } + + { + uint8_t *temp = prBuffer; + // Log each byte received in the buffer + for (int32_t index = 0; index < pCecResponse->payloadSize + 2; index++) + { + int32_t len = 0; + len = snprintf(temp, HDMI_CEC_MAX_PAYLOAD, "%02X:", response[index]); + temp += len; + } + prBuffer[strlen(prBuffer)-1] = '\0'; + + } + + HdmiCecTx(handle, response, pCecResponse->payloadSize + 2, &result); + + getCecCommandInfo(pCecResponse->cecCommand, &commandName, &expectedDataLength); + + UT_LOG_INFO("Sent Response Opcode: [0x%02X] [%s] Initiator: [%x], Destination: [%x] Data: [%s]\n", + pCecResponse->cecCommand, commandName, destination, initiator, prBuffer); } } -/** - * @brief callback to get the async send message status - * - * @param handle Hdmi device handle - * @param callbackData callback data passed - * @param result async send status - */ -void TransmitCallback(int handle, void *callbackData, int result) +static void onRxDataReceived(int32_t handle, void *callbackData, uint8_t *buf, int32_t len) { - if((handle!=0) && (callbackData !=NULL)) { - //UT_ASSERT_TRUE_FATAL( (unsigned long long)callbackData== (unsigned long long)0xDEADBEEF); - UT_LOG ("\ncallbackData returned: %x result: %d\n",callbackData, result); - } -} + UT_LOG_INFO("In %s(IN: handle: [%p], IN: callbackData: [%p], IN: buf: [%p], IN: len: [%d])\n", __FUNCTION__, handle, callbackData, buf, len); + const char* commandName; + int32_t expectedDataLength; -int TimedWaitForCallback(uint32_t timeOutSeconds) -{ - int s, result = -1; - struct timespec ts; - clock_gettime(CLOCK_REALTIME, &ts); - ts.tv_sec += timeOutSeconds; - while ((s = sem_timedwait(&gSemCallbackReceived, &ts)) == -1 && errno == EINTR) + if ((handle != 0) && (callbackData != NULL) && (len > 0)) { - continue; /* Restart if interrupted by handler */ - } + // Parse the command + uint8_t initiator = (buf[0] >> 4) & 0xF; // Extract initiator address + uint8_t destination = buf[0] & 0xF; // Extract destination address + uint8_t opcode; // Command opcode + cecResponse_t cecResponse = {0}; // cec response + uint8_t prBuffer[HDMI_CEC_MAX_PAYLOAD] = {0}; + bool result = false; + + if( len == 1) + { + UT_LOG_INFO("Received Ping message Initiator: [%x], Destination: [%x]", initiator, destination); + goto exit; + } - /* Check what happened */ - if (s == -1) - { - if (errno == ETIMEDOUT) + opcode = buf[1]; + + if(getCecCommandInfo(opcode, &commandName, &expectedDataLength) != 0) { - result = 1; + UT_LOG_WARNING("CEC command 0x%02X is not recognized", opcode); + goto exit; } + + { + uint8_t *temp = prBuffer; + // Log each byte received in the buffer + for (int32_t index = 0; index < len; index++) + { + int32_t len = 0; + len = snprintf(temp, HDMI_CEC_MAX_PAYLOAD, "%02X:", buf[index]); + temp += len; + } + prBuffer[strlen(prBuffer)-1] = '\0'; + } + + UT_LOG_INFO("Received Opcode: [0x%02X] [%s] Initiator: [%x], Destination: [%x] Data: [%s]\n", opcode, commandName, initiator, destination, prBuffer); + + result = getCommandResponse(opcode, &cecResponse); + + sendResponse(handle, initiator, destination, buf, len, &cecResponse); } else { - result = 0; + // Log specific errors based on failed conditions + if (handle == 0) + { + UT_LOG_ERROR("Error: Invalid handle.\n"); + } + if (callbackData == NULL) + { + UT_LOG_ERROR("Error: Null callback data.\n"); + } + if (len <= 0) + { + UT_LOG_ERROR("Error: Invalid length.\n"); + } } - return result; +exit: + UT_LOG_INFO("Out %s\n", __FUNCTION__); } - /** -* HdmiCecOpen() Positive -* HdmiCec -* +* @brief Initialization of the HAL CEC Module +* +* This test provides a scope to open the HAL CEC module and preserve the handle. +* +* **Test Group ID:** 03@n +* +* **Test Case ID:** 001@n +* +* **Pre-Conditions:** None@n +* +* **Dependencies:** None@n +* */ -void test_l3_sink_image_view_on (void) +void test_l3_hdmi_cec_hal_Init(void) { - int result; - int handle = 0; gTestID = 1; + HDMI_CEC_STATUS status = HDMI_CEC_IO_SUCCESS; - UT_LOG("\n In %s [%02d%03d]\n", __FUNCTION__, gTestGroup, gTestID); - result = HdmiCecOpen( &handle ); - if (HDMI_CEC_IO_SUCCESS != result) { UT_FAIL_FATAL("open failed"); } + UT_LOG_INFO("In %s [%02d%03d]\n", __FUNCTION__, gTestGroup, gTestID); - result = HdmiCecSetRxCallback(handle, ReceiveCallback, (void*)gValidationProfileInstance); - if (HDMI_CEC_IO_SUCCESS != result) { UT_FAIL("HdmiCecSetRxCallback failed"); } + // Step 1: Call HdmiCecOpen() + UT_LOG_INFO("Calling HdmiCecOpen(OUT:handle:[])"); + status = HdmiCecOpen(&gHandle); + UT_LOG_INFO("Result HdmiCecOpen(OUT:handle:[0x%0X]) HDMI_CEC_STATUS:[%s]",gHandle, UT_Control_GetMapString(cecError_mapTable,status)); + assert(status == HDMI_CEC_IO_SUCCESS); + assert(gHandle != 0); - result = HdmiCecSetTxCallback( handle, TransmitCallback, (void*)0xDEADBEEF ); - if (HDMI_CEC_IO_SUCCESS != result) { UT_FAIL("HdmiCecSetTxCallback failed"); } + // Step 2: Register the call back + UT_LOG_INFO("Calling HdmiCecSetRxCallback(IN:handle:[0x%0X], IN:cbfunc:[0x%0X])",gHandle, onRxDataReceived); + status = HdmiCecSetRxCallback(gHandle, onRxDataReceived,(void*)0xABABABAB); + UT_LOG_INFO("Result HdmiCecSetRxCallback(IN:handle:[0x%0X], IN:cbfunc:[0x%0X]) HDMI_CEC_STATUS:[%s]",gHandle,onRxDataReceived, UT_Control_GetMapString(cecError_mapTable,status)); + assert(status == HDMI_CEC_IO_SUCCESS); - result = HdmiCecAddLogicalAddress( handle, DEFAULT_LOGICAL_ADDRESS_PANEL ); - if (HDMI_CEC_IO_SUCCESS != result) { UT_FAIL("HdmiCecAddLogicalAddress failed"); } + UT_LOG_INFO("Calling HdmiCecGetPhysicalAddress(IN:handle:[0x%0X], OUT:physicalAddress:[])", gHandle); + status = HdmiCecGetPhysicalAddress(gHandle, &gPhysicalAddress); + UT_LOG_INFO("Result HdmiCecGetPhysicalAddress(IN:handle:[0x%0X], OUT:physicalAddress:[%x]) HDMI_CEC_STATUS:[%s]", gHandle, gPhysicalAddress, UT_Control_GetMapString(cecError_mapTable,status)); + assert(status == HDMI_CEC_IO_SUCCESS); - gExpectedCecCommand = CEC_IMAGE_VIEW_ON; - gCommandValidated = CEC_COMMAND_UNKNOWN; - - UT_LOG ("\nTrigger ImageViewOn\n"); - result = TimedWaitForCallback(MAX_WAIT_TIME_SECS); - if(result != 0) - { - UT_FAIL("Failed to receive ImageViewOn"); - } - if(gCommandValidated != gExpectedCecCommand) - { - UT_FAIL("Test Validation of ImageViewOn failed"); - } - result = HdmiCecClose( handle ); - if (HDMI_CEC_IO_SUCCESS != result) { UT_FAIL_FATAL("close failed"); } + gPhysicalAddressBytes = (uint8_t*)&gPhysicalAddress; + UT_LOG_INFO("Out %s\n", __FUNCTION__); } -void test_l3_sink_text_view_on (void) +/** +* @brief This test provides a scope to add the sink logical address. Usually it shall be zero. +* +* This test case provides a scope to add the available sink logical address +* to a Device under test. +* +* Note: +* This applies only for the Sink Devices. +* Source devices will get the logical address during CEC open. +* +* **Test Group ID:** 03@n +* +* **Test Case ID:** 002@n +* +* **Pre-Conditions:** @n +* HDMI-CEC Module should be intialized through Test 1 before calling this test. +* +* **Dependencies:** None@n +* +*/ +void test_l3_hdmi_cec_hal_AddLogicalAddress(void) { - int result; - int handle = 0; - gTestID = 1; + gTestID = 2; + UT_LOG_INFO("In %s [%02d%03d]\n", __FUNCTION__, gTestGroup, gTestID); - UT_LOG("\n In %s [%02d%03d]\n", __FUNCTION__, gTestGroup, gTestID); - result = HdmiCecOpen( &handle ); - if (HDMI_CEC_IO_SUCCESS != result) { UT_FAIL_FATAL("open failed"); } + HDMI_CEC_STATUS status = HDMI_CEC_IO_SUCCESS; - result = HdmiCecSetRxCallback(handle, ReceiveCallback, (void*)gValidationProfileInstance); - if (HDMI_CEC_IO_SUCCESS != result) { UT_FAIL("HdmiCecSetRxCallback failed"); } + int32_t logicalAddress = -1; + int32_t getLogicalAddress = -1; - result = HdmiCecSetTxCallback( handle, TransmitCallback, (void*)0xDEADBEEF ); - if (HDMI_CEC_IO_SUCCESS != result) { UT_FAIL("HdmiCecSetTxCallback failed"); } + if (gDeviceType == SOURCE) + { + UT_LOG_ERROR("Source Device doesn't support add logical Address"); + UT_LOG_INFO("Out %s\n", __FUNCTION__); + return; + } - result = HdmiCecAddLogicalAddress( handle, DEFAULT_LOGICAL_ADDRESS_PANEL ); - if (HDMI_CEC_IO_SUCCESS != result) { UT_FAIL("HdmiCecAddLogicalAddress failed"); } + UT_LOG_MENU_INFO("Enter Logical Address:"); + readHex(&logicalAddress); - gExpectedCecCommand = CEC_TEXT_VIEW_ON; - gCommandValidated = CEC_COMMAND_UNKNOWN; + /* Check that logical address should be valid one */ + UT_LOG_INFO("Calling HdmiCecAddLogicalAddress(IN:handle:[0x%0X], IN:logicalAddress:[%x]", gHandle, logicalAddress); + status = HdmiCecAddLogicalAddress(gHandle, logicalAddress); + UT_LOG_INFO("Result HdmiCecAddLogicalAddress (IN:handle:[0x%0X], IN:logicalAddress:[%x]) HDMI_CEC_STATUS[%s]",gHandle,logicalAddress,UT_Control_GetMapString(cecError_mapTable,status)); + assert(status == HDMI_CEC_IO_SUCCESS); - UT_LOG ("\nTrigger TextViewOn\n"); - result = TimedWaitForCallback(MAX_WAIT_TIME_SECS); - if(result != 0) - { - UT_FAIL("Failed to receive TextViewOn"); - } - if(gCommandValidated != gExpectedCecCommand) - { - UT_FAIL("Test Validation of TextViewOn failed"); - } - result = HdmiCecClose( handle ); - if (HDMI_CEC_IO_SUCCESS != result) { UT_FAIL_FATAL("close failed"); } + UT_LOG_INFO("Calling HdmiCecGetLogicalAddress(IN:handle:[0x%0X], OUT:logicalAddress:[])", gHandle); + status = HdmiCecGetLogicalAddress(gHandle, &getLogicalAddress); + UT_LOG_INFO("Result HdmiCecGetLogicalAddress(IN:handle:[0x%0X], OUT:logicalAddress:[%x]) HDMI_CEC_STATUS:[%s])", gHandle, getLogicalAddress, UT_Control_GetMapString(cecError_mapTable,status)); + assert(status == HDMI_CEC_IO_SUCCESS); + assert(logicalAddress == getLogicalAddress); + + gLogicalAddress = getLogicalAddress; + UT_LOG_INFO("Out %s\n", __FUNCTION__); } -void test_l3_sink_active_source (void) +/** +* @brief Test to get the logical address +* +* This test provides a scope to check the assigned logical address of the device. +* +* **Test Group ID:** 03@n +* +* **Test Case ID:** 003@n +* +* **Pre-Conditions:** @n +* HDMI-CEC Module should be intialized through Test 1 before calling this test. +* +* **Dependencies:** None@n +* +*/ +void test_l3_hdmi_cec_hal_GetLogicalAddress(void) { - int result; - int handle = 0; - gTestID = 1; + gTestID = 3; + UT_LOG_INFO("In %s [%02d%03d]\n", __FUNCTION__, gTestGroup, gTestID); + + HDMI_CEC_STATUS status = HDMI_CEC_IO_SUCCESS; + int32_t logicalAddress = -1; + + UT_LOG_INFO("Calling HdmiCecGetLogicalAddress(IN:handle:[0x%0X], OUT:logicalAddress:[])", gHandle); + status = HdmiCecGetLogicalAddress(gHandle, &logicalAddress); + UT_LOG_INFO("Result HdmiCecGetLogicalAddress(IN:handle:[0x%0X], OUT:logicalAddress:[%x]) HDMI_CEC_STATUS:[%s])", gHandle, logicalAddress, UT_Control_GetMapString(cecError_mapTable,status)); + assert(status == HDMI_CEC_IO_SUCCESS); + assert(logicalAddress >= 0 && logicalAddress <= 15); + + UT_LOG_INFO("Out %s\n", __FUNCTION__); +} - UT_LOG("\n In %s [%02d%03d]\n", __FUNCTION__, gTestGroup, gTestID); - result = HdmiCecOpen( &handle ); - if (HDMI_CEC_IO_SUCCESS != result) { UT_FAIL_FATAL("open failed"); } +/** +* @brief Test provides a scope to Transmit the CEC Command +* +* This test provides an interface to user/automation tool to transmit a CEC Command. +* Necessary input should be provided to the test. +* +* **Test Group ID:** 03@n +* +* **Test Case ID:** 004@n +* +* **Pre-Conditions:** @n +* HDMI-CEC Module should be intialized through Test 1 before calling this test. +* Logical Address should be added through Test 2 before calling this test. +* +* **Dependencies:** None@n +* +*/ +void test_l3_hdmi_cec_hal_TransmitHdmiCecCommand(void) { + gTestID = 4; + UT_LOG_INFO("In %s [%02d%03d]\n", __FUNCTION__, gTestGroup, gTestID); - result = HdmiCecSetRxCallback(handle, ReceiveCallback, (void*)gValidationProfileInstance); - if (HDMI_CEC_IO_SUCCESS != result) { UT_FAIL("HdmiCecSetRxCallback failed"); } + int32_t sourceLogicalAddress = gLogicalAddress; + int32_t destinationLogicalAddress = -1; + uint8_t buf[16] = {0}; + int32_t len = 0, cecCommand = 0; + int32_t result; + const char* commandName; + int32_t expectedDataLength; - result = HdmiCecSetTxCallback( handle, TransmitCallback, (void*)0xDEADBEEF ); - if (HDMI_CEC_IO_SUCCESS != result) { UT_FAIL("HdmiCecSetTxCallback failed"); } + assert(sourceLogicalAddress != -1); - result = HdmiCecAddLogicalAddress( handle, DEFAULT_LOGICAL_ADDRESS_PANEL ); - if (HDMI_CEC_IO_SUCCESS != result) { UT_FAIL("HdmiCecAddLogicalAddress failed"); } + // Reading inputs from the user or test framework + UT_LOG_MENU_INFO("Enter a valid Destination Logical Address: "); + readHex(&destinationLogicalAddress); - gExpectedCecCommand = CEC_ACTIVE_SOURCE; - gCommandValidated = CEC_COMMAND_UNKNOWN; + UT_LOG_MENU_INFO("Enter CEC Command (in hex): "); + readHex(&cecCommand); - UT_LOG ("\nTrigger ActiveSource\n"); - result = TimedWaitForCallback(MAX_WAIT_TIME_SECS); - if(result != 0) + // Validate the CEC command and get the expected data length + if (getCecCommandInfo(cecCommand, &commandName, &expectedDataLength) != 0) { - UT_FAIL("Failed to receive ActiveSource"); + // Command not found in the map, prompt the user for additional information + UT_LOG_WARNING("CEC command 0x%02X is not recognized. It might be a vendor-specific command.", cecCommand); + + UT_LOG_MENU_INFO("Enter the number of data bytes for the CEC command:"); + readInt(&expectedDataLength); + commandName = "Vendor Specific Command"; } - if(gCommandValidated != gExpectedCecCommand) + else { - UT_FAIL("Test Validation of ActiveSource failed"); + UT_LOG_INFO("CEC Command: %s (0x%02X), expects %d data byte(s)", commandName, cecCommand, expectedDataLength); } - result = HdmiCecClose( handle ); - if (HDMI_CEC_IO_SUCCESS != result) { UT_FAIL_FATAL("close failed"); } + // If the command has data bytes, prompt for them + if (expectedDataLength > 0) + { + for (int32_t i = 0; i < expectedDataLength; i++) + { + int32_t byte_data; + UT_LOG_MENU_INFO("Enter Databyte[%d] (in hex):", i); + readHex(&byte_data); + buf[i + 2] = (uint8_t)byte_data; // +2 to account for the first two bytes + } + } + + // Building the CEC message + buf[0] = (uint8_t)((sourceLogicalAddress << 4) | (destinationLogicalAddress & 0x0F)); + buf[1] = (uint8_t)cecCommand; + len = expectedDataLength + 2; // 1 byte for logical addresses, 1 byte for CEC Command + + // Logging the transmission attempt + UT_LOG_INFO("Calling HdmiCecTx(IN:handle:[0x%0X], IN:buf:[%p], IN:len:[%d], OUT:result:[])", gHandle, buf, len); + int32_t status = HdmiCecTx(gHandle, buf, len, &result); + UT_LOG_INFO("Result HdmiCecTx(IN:handle:[0x%0X], IN:buf:[%p], IN:len:[%d], OUT:result:[%s]) HDMI_CEC_STATUS:[%s]", gHandle, buf, len, UT_Control_GetMapString(cecError_mapTable, result)? UT_Control_GetMapString(cecError_mapTable, result):"HDMI_CEC_IO_SENT_FAILED", UT_Control_GetMapString(cecError_mapTable,status)); + assert(status == HDMI_CEC_IO_SUCCESS); + + UT_LOG_INFO("Out %s\n", __FUNCTION__); } -void test_l3_sink_inactive_source (void) +/** +* @brief Test to get the physical address +* +* This test provides a scope to read the physical address of the device. +* +* **Test Group ID:** 03@n +* +* **Test Case ID:** 005@n +* +* **Pre-Conditions:** @n +* HDMI-CEC Module should be intialized through Test 1 before calling this test. +* +* **Dependencies:** None@n +* +*/ +void test_l3_hdmi_cec_hal_GetPhysicalAddress(void) { - int result; - int handle = 0; - gTestID = 1; + gTestID = 5; + UT_LOG_INFO("In %s [%02d%03d]\n", __FUNCTION__, gTestGroup, gTestID); - UT_LOG("\n In %s [%02d%03d]\n", __FUNCTION__, gTestGroup, gTestID); - result = HdmiCecOpen( &handle ); - if (HDMI_CEC_IO_SUCCESS != result) { UT_FAIL_FATAL("open failed"); } + HDMI_CEC_STATUS status = HDMI_CEC_IO_SUCCESS; + uint32_t physicalAddress = -1; - result = HdmiCecSetRxCallback(handle, ReceiveCallback, (void*)gValidationProfileInstance); - if (HDMI_CEC_IO_SUCCESS != result) { UT_FAIL("HdmiCecSetRxCallback failed"); } + UT_LOG_INFO("Calling HdmiCecGetPhysicalAddress(IN:handle:[0x%0X], OUT:physicalAddress:[])", gHandle); + status = HdmiCecGetPhysicalAddress(gHandle, &physicalAddress); + UT_LOG_INFO("Result HdmiCecGetPhysicalAddress(IN:handle:[0x%0X], OUT:physicalAddress:[%x]) HDMI_CEC_STATUS:[%s]", gHandle, physicalAddress, UT_Control_GetMapString(cecError_mapTable,status)); + assert(status == HDMI_CEC_IO_SUCCESS); - result = HdmiCecSetTxCallback( handle, TransmitCallback, (void*)0xDEADBEEF ); - if (HDMI_CEC_IO_SUCCESS != result) { UT_FAIL("HdmiCecSetTxCallback failed"); } + UT_LOG_INFO("Out %s\n", __FUNCTION__); +} - result = HdmiCecAddLogicalAddress( handle, DEFAULT_LOGICAL_ADDRESS_PANEL ); - if (HDMI_CEC_IO_SUCCESS != result) { UT_FAIL("HdmiCecAddLogicalAddress failed"); } +/** +* @brief Test to Remove logical address +* +* This test provides a scope to remove the logical address of the device. HAL API to set +* to default logical addres 0xF once the logical address is removed. +* +* **Test Group ID:** 03@n +* +* **Test Case ID:** 006@n +* +* **Pre-Conditions:** @n +* HDMI-CEC Module should be intialized through Test 1 before calling this test. +* +* **Dependencies:** None@n +*/ +void test_l3_hdmi_cec_hal_RemoveLogicalAddress(void) +{ + gTestID = 6; + UT_LOG_INFO("In %s [%02d%03d]\n", __FUNCTION__, gTestGroup, gTestID); - gExpectedCecCommand = CEC_INACTIVE_SOURCE; - gCommandValidated = CEC_COMMAND_UNKNOWN; + HDMI_CEC_STATUS status = HDMI_CEC_IO_SUCCESS; + int32_t logicalAddress = gLogicalAddress; + int32_t getLogicalAddress = 0; - UT_LOG ("\nTrigger InactiveSource\n"); - result = TimedWaitForCallback(MAX_WAIT_TIME_SECS); - if(result != 0) - { - UT_FAIL("Failed to receive InactiveSource"); - } - if(gCommandValidated != gExpectedCecCommand) + if (gDeviceType == SOURCE) { - UT_FAIL("Test Validation of InactiveSource failed"); + UT_LOG_ERROR("Source Device doesn't support remove logical Address"); + UT_LOG_INFO("Out %s\n", __FUNCTION__); + return; } - result = HdmiCecClose( handle ); - if (HDMI_CEC_IO_SUCCESS != result) { UT_FAIL_FATAL("close failed"); } -} + assert(logicalAddress != -1); -void test_l3_sink_set_osd_name (void) -{ - int result; - int handle = 0; - gTestID = 1; + UT_LOG_INFO("Calling HdmiCecRemoveLogicalAddress(IN:handle:[0x%0X], IN:logicalAddress:[%d])", gHandle, logicalAddress); + status = HdmiCecRemoveLogicalAddress(gHandle, logicalAddress); + UT_LOG_INFO("Result HdmiCecRemoveLogicalAddress(IN:handle:[0x%0X], IN:logicalAddress:[%d]) HDMI_CEC_STATUS:[%s])", gHandle, logicalAddress, UT_Control_GetMapString(cecError_mapTable,status)); + assert(status == HDMI_CEC_IO_SUCCESS); - UT_LOG("\n In %s [%02d%03d]\n", __FUNCTION__, gTestGroup, gTestID); - result = HdmiCecOpen( &handle ); - if (HDMI_CEC_IO_SUCCESS != result) { UT_FAIL_FATAL("open failed"); } + gLogicalAddress = -1; - result = HdmiCecSetRxCallback(handle, ReceiveCallback, (void*)gValidationProfileInstance); - if (HDMI_CEC_IO_SUCCESS != result) { UT_FAIL("HdmiCecSetRxCallback failed"); } + UT_LOG_INFO("Out %s\n", __FUNCTION__); +} +/** +* @brief Test to close the HDMI CEC device. +* +* This test provides a scope to close the created HDMI CEC handle. +* +* **Test Group ID:** 03@n +* +* **Test Case ID:** 007@n +* +* **Pre-Conditions:** @n +* HDMI-CEC Module should be intialized through Test 1 before calling this test. +* +* **Dependencies:** None@n +*/ +void test_l3_hdmi_cec_hal_Close(void) +{ + gTestID = 7; + HDMI_CEC_STATUS status; - result = HdmiCecSetTxCallback( handle, TransmitCallback, (void*)0xDEADBEEF ); - if (HDMI_CEC_IO_SUCCESS != result) { UT_FAIL("HdmiCecSetTxCallback failed"); } + UT_LOG_INFO("In %s [%02d%03d]\n", __FUNCTION__, gTestGroup, gTestID); - result = HdmiCecAddLogicalAddress( handle, DEFAULT_LOGICAL_ADDRESS_PANEL ); - if (HDMI_CEC_IO_SUCCESS != result) { UT_FAIL("HdmiCecAddLogicalAddress failed"); } + UT_LOG_INFO("Calling HdmiCecClose(IN:handle:[0x%0X])", gHandle); + status = HdmiCecClose(gHandle); + UT_LOG_INFO("Result HdmiCecClose(IN:handle:[0x%0X]) HDMI_CEC_STATUS:[%s]", gHandle, UT_Control_GetMapString(cecError_mapTable,status)); + assert(status == HDMI_CEC_IO_SUCCESS); + gHandle = 0; - gExpectedCecCommand = CEC_SET_OSD_NAME; - gCommandValidated = CEC_COMMAND_UNKNOWN; + UT_LOG_INFO("Out %s\n", __FUNCTION__); +} - UT_LOG ("\nTrigger SetOSDName\n"); - result = TimedWaitForCallback(MAX_WAIT_TIME_SECS); - if(result != 0) - { - UT_FAIL("Failed to receive SetOSDName"); - } - if(gCommandValidated != gExpectedCecCommand) - { - UT_FAIL("Test Validation of SetOSDName failed"); - } - result = HdmiCecClose( handle ); - if (HDMI_CEC_IO_SUCCESS != result) { UT_FAIL_FATAL("close failed"); } +static UT_test_suite_t * pSuite = NULL; -} /** - * @brief Register the main test(s) for this module + * @brief Register the main tests for this module * - * @return int - 0 on success, otherwise failure + * @return int32_t - 0 on success, otherwise failure */ -int test_l3_hdmi_cec_driver_register ( char* validation_profile ) +int32_t test_register_hdmicec_hal_sink_l3_tests(void) { ut_kvp_status_t status; - if(validation_profile == NULL) + char deviceType[HDMI_CEC_DEVICE_TYPE_SIZE] = {0}; + + // Create the test suite + pSuite = UT_add_suite("[L3 HDMICEC Functions] ", NULL, NULL); + if (pSuite == NULL) { - UT_FAIL("validation_profile NULL"); return -1; } - gValidationProfileInstance = ut_kvp_createInstance(); - assert(gValidationProfileInstance != NULL); - status = ut_kvp_open(gValidationProfileInstance, validation_profile); - if(status != UT_KVP_STATUS_SUCCESS) + status = ut_kvp_getStringField(ut_kvp_profile_getInstance(), "hdmicec/type", deviceType, HDMI_CEC_DEVICE_TYPE_SIZE); + + if (status == UT_KVP_STATUS_SUCCESS ) { - UT_LOG_ERROR("ut_kvp_open: status: %d", status); - assert(status == UT_KVP_STATUS_SUCCESS); + if (!strncmp(deviceType, "source", HDMI_CEC_DEVICE_TYPE_SIZE)) + { + gDeviceType = SOURCE; + } + else if(!strncmp(deviceType, "sink", HDMI_CEC_DEVICE_TYPE_SIZE)) + { + gDeviceType = SINK; + } + else + { + UT_LOG_ERROR("Invalid platform type: %s", deviceType); + return -1; + } + } + else { + UT_LOG_ERROR("Failed to get the platform type"); return -1; } - /* add a suite to the registry */ - pSuite = UT_add_suite( "[L3 hdmi_cec_driver]", NULL, NULL ); - if ( NULL == pSuite ) - { - return -1; - } - - sem_init(&gSemCallbackReceived, 0, 0); - UT_add_test( pSuite, "test_l3_sink_image_view_on" ,test_l3_sink_image_view_on ); - UT_add_test( pSuite, "test_l3_sink_text_view_on" ,test_l3_sink_text_view_on ); - UT_add_test( pSuite, "test_l3_sink_active_source" ,test_l3_sink_active_source); - UT_add_test( pSuite, "test_l3_sink_inactive_source" ,test_l3_sink_inactive_source ); - UT_add_test( pSuite, "test_l3_sink_set_osd_name" ,test_l3_sink_set_osd_name ); - - return 0; -} + // List of test function names and strings + UT_add_test( pSuite, "Init HDMI CEC", test_l3_hdmi_cec_hal_Init); + UT_add_test( pSuite, "Add Logical Address", test_l3_hdmi_cec_hal_AddLogicalAddress); + UT_add_test( pSuite, "Get Logical Address", test_l3_hdmi_cec_hal_GetLogicalAddress); + UT_add_test( pSuite, "Transmit CEC Command", test_l3_hdmi_cec_hal_TransmitHdmiCecCommand); + UT_add_test( pSuite, "Get Phyiscal Address", test_l3_hdmi_cec_hal_GetPhysicalAddress); + UT_add_test( pSuite, "Remove Logical Address", test_l3_hdmi_cec_hal_RemoveLogicalAddress); + UT_add_test( pSuite, "Close HDMI CEC", test_l3_hdmi_cec_hal_Close); + + return 0; +} + +/** @} */ // End of HDMI CEC HAL Tests L1 File +/** @} */ // End of HDMI CEC HAL Tests +/** @} */ // End of HDMI CEC Module +/** @} */ // End of HPK diff --git a/src/test_l3_hdmi_cec_sink_driver.c b/src/test_l3_hdmi_cec_sink_driver.c deleted file mode 100644 index b8dd206..0000000 --- a/src/test_l3_hdmi_cec_sink_driver.c +++ /dev/null @@ -1,737 +0,0 @@ -/* -* If not stated otherwise in this file or this component's LICENSE file the -* following copyright and licenses apply:* -* Copyright 2024 RDK Management -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -/** - * @addtogroup HPK Hardware Porting Kit - * @{ - * - */ -/** - * @addtogroup HDMI_CEC HDMI CEC Module - * @{ - * - */ -/** - * @defgroup HDMI_CEC_HALTESTS HDMI CEC HAL Tests - * @{ - * - */ - -/** - * @defgroup HDMI_CEC_HALTESTS_L3 HDMI CEC HAL Tests L2 File - * @{ - * @parblock - * - * ### L2 Test Cases for HDMI CEC HAL : - * - * - * ## Module's Role - * This module includes Level 3 functional test interfaces. - * This Test Interfaces provides a scope to create a User Test cases for HDMI CEC Sink modules that can be either Manual or automated scripts. - * - * **Pre-Conditions:** None@n - * **Dependencies:** None@n - * - * Refer to API Definition specification documentation : [hdmi-cec_halSpec.md](../../docs/pages/hdmi-cec_halSpec.md) - * - * @endparblock - */ - -/** - * @file test_l3_hdmi_cec_sink_driver.c - * - */ - -#include -#include -#include -#include -#include -#include "hdmi_cec_driver.h" - -#define TIMEOUT 5 -#define REPLY_TIMEOUT 5 - -#define HDMI_CEC_MAX_PAYLOAD 128 -#define HDMI_CEC_MAX_OSDNAME 15 -#define HDMI_CEC_KVP_SIZE 128 -#define HDMI_CEC_TYPE_SIZE 16 - -#define UT_LOG_MENU_INFO UT_LOG_INFO - -typedef struct -{ - uint8_t cecCommand; // CEC command code - const char* commandName; // Human-readable command name - int32_t dataLength; // Number of data bytes required for the command -} CecCommandMap; - -typedef struct cecResponse -{ - uint8_t cecCommand; //CEC opcode - uint32_t payloadSize; //CEC payload size - uint8_t type[UT_KVP_MAX_ELEMENT_SIZE]; //Type of the opcode Broadcast/ Direct - uint8_t payload[HDMI_CEC_MAX_PAYLOAD]; //CEC Payload -} cecResponse_t; - -CecCommandMap cecCommandTable[] = { - {0x00, "Feature Abort", 2}, - {0x04, "Image View On", 0}, - {0x05, "Tuner Step Increment", 0}, - {0x06, "Tuner Step Decrement", 0}, - {0x07, "Tuner Device Status", 8}, - {0x08, "Give Tuner Device Status", 0}, - {0x09, "Record On", 8}, - {0x0A, "Record Status", 8}, - {0x0B, "Record Off", 0}, - {0x0D, "Text View On", 0}, - {0x0F, "Record TV Screen", 0}, - {0x1A, "Give Deck Status", 0}, - {0x1B, "Deck Status", 1}, - {0x32, "Set Menu Language", 3}, - {0x33, "Clear Analog Timer", 0}, - {0x34, "Set Analog Timer", 8}, - {0x35, "Timer Status", 3}, - {0x36, "Standby", 0}, - {0x41, "Play", 0}, - {0x42, "Deck Control", 1}, - {0x43, "Timer Cleared Status", 1}, - {0x44, "User Control Pressed", 1}, - {0x45, "User Control Released", 0}, - {0x46, "Give OSD Name", 0}, - {0x47, "Set OSD Name", 14}, - {0x64, "Set OSD String", 14}, - {0x67, "Set Timer Program Title", 14}, - {0x70, "System Audio Mode Request", 2}, - {0x71, "Give Audio Status", 0}, - {0x72, "Set System Audio Mode", 1}, - {0x7A, "Report Audio Status", 1}, - {0x7D, "Give System Audio Mode Status", 0}, - {0x7E, "System Audio Mode Status", 1}, - {0x80, "Routing Change", 4}, - {0x81, "Routing Information", 2}, - {0x82, "Active Source", 2}, - {0x83, "Give Physical Address", 0}, - {0x84, "Report Physical Address", 3}, - {0x85, "Request Active Source", 0}, - {0x86, "Set Stream Path", 2}, - {0x87, "Device Vendor ID", 3}, - {0x89, "Vendor Command", 14}, - {0x8A, "Vendor Remote Button Down", 1}, - {0x8B, "Vendor Remote Button Up", 0}, - {0x8C, "Give Device Vendor ID", 0}, - {0x8D, "Menu Request", 1}, - {0x8E, "Menu Status", 1}, - {0x8F, "Give Device Power Status", 0}, - {0x90, "Report Power Status", 1}, - {0x91, "Get Menu Language", 0}, - {0x92, "Select Analog Service", 4}, - {0x93, "Select Digital Service", 4}, - {0x97, "Set Digital Timer", 6}, - {0x99, "Clear Digital Timer", 0}, - {0x9A, "Set Audio Rate", 1}, - {0x9D, "Inactive Source", 2}, - {0x9E, "CEC Version", 1}, - {0x9F, "Get CEC Version", 0}, - {0xA0, "Vendor Command With ID", 17}, - {0xA1, "Clear External Timer", 0}, - {0xA2, "Set External Timer", 9}, - {0xA7, "Request Current Latency", 2}, - {0xA8, "Report Current Latency", 5}, - {0xC0, "Initiate ARC", 0}, - {0xC1, "Report ARC Initiated", 0}, - {0xC2, "Report ARC Terminated", 0}, - {0xC3, "Request ARC Initiation", 0}, - {0xC4, "Request ARC Termination", 0}, - {0xC5, "Terminate ARC", 0}, - {0xFF, "Abort", 0} -}; - -/* cecError_t */ -const static ut_control_keyStringMapping_t cecError_mapTable [] = -{ - {"HDMI_CEC_IO_SUCCESS", (int32_t)HDMI_CEC_IO_SUCCESS}, - {"HDMI_CEC_IO_SENT_AND_ACKD", (int32_t)HDMI_CEC_IO_SENT_AND_ACKD}, - {"HDMI_CEC_IO_SENT_BUT_NOT_ACKD", (int32_t)HDMI_CEC_IO_SENT_BUT_NOT_ACKD}, - {"HDMI_CEC_IO_SENT_FAILED", (int32_t)HDMI_CEC_IO_SENT_FAILED}, - {"HDMI_CEC_IO_NOT_OPENED", (int32_t)HDMI_CEC_IO_NOT_OPENED}, - {"HDMI_CEC_IO_INVALID_ARGUMENT", (int32_t)HDMI_CEC_IO_INVALID_ARGUMENT}, - {"HDMI_CEC_IO_LOGICALADDRESS_UNAVAILABLE", (int32_t)HDMI_CEC_IO_LOGICALADDRESS_UNAVAILABLE}, - {"HDMI_CEC_IO_GENERAL_ERROR", (int32_t)HDMI_CEC_IO_GENERAL_ERROR}, - {"HDMI_CEC_IO_ALREADY_OPEN", (int32_t)HDMI_CEC_IO_ALREADY_OPEN}, - {"HDMI_CEC_IO_ALREADY_REMOVED", (int32_t)HDMI_CEC_IO_ALREADY_REMOVED}, - {"HDMI_CEC_IO_INVALID_OUTPUT", (int32_t)HDMI_CEC_IO_INVALID_OUTPUT}, - {"HDMI_CEC_IO_INVALID_HANDLE", (int32_t)HDMI_CEC_IO_INVALID_HANDLE}, - {"HDMI_CEC_IO_OPERATION_NOT_SUPPORTED", (int32_t)HDMI_CEC_IO_OPERATION_NOT_SUPPORTED}, - {"HDMI_CEC_IO_NOT_ADDED", (int32_t)HDMI_CEC_IO_NOT_ADDED}, - {"HDMI_CEC_IO_MAX", (int32_t)HDMI_CEC_IO_MAX}, - { NULL, -1 } -}; - -static int32_t gTestGroup = 3; -static int32_t gTestID = 1; -static int32_t gHandle = 0; -static int32_t gLogicalAddress = -1; -static uint32_t gPhysicalAddress = -1; -static uint8_t *gPhysicalAddressBytes; -static uint8_t gBroadcastAddress = 0xF; - -/** -* @brief CEC Command with data size mapping function. -* -* This function maps the provided CEC command with the data length required for the CEC Command. -* This will help the test to consider the correct size of the data required for the CEC Command. -* -*/ -static int32_t getCecCommandInfo(uint8_t cecCommand, const char** commandName, int32_t* dataLength) -{ - - int32_t tableSize = sizeof(cecCommandTable) / sizeof(CecCommandMap); - - for (int32_t i = 0; i < tableSize; i++) - { - if (cecCommandTable[i].cecCommand == cecCommand) - { - *commandName = cecCommandTable[i].commandName; - *dataLength = cecCommandTable[i].dataLength; - return 0; // Command found - } - } - - return -1; // Command not found -} - -/** - * @brief This function clears the stdin buffer. - * - * This function clears the stdin buffer. - */ -static void readAndDiscardRestOfLine(FILE *in) -{ - int32_t c; - while ((c = fgetc(in)) != EOF && c != '\n'); -} - -static void readInt(int32_t *value) -{ - scanf("%d", value); - readAndDiscardRestOfLine(stdin); -} - -static void readHex(int32_t *value) -{ - scanf("%x", value); - readAndDiscardRestOfLine(stdin); -} - -static bool getCommandResponse(uint8_t opcode, cecResponse_t *pResponse) -{ - uint32_t numCommands = 0; - char key_string[HDMI_CEC_KVP_SIZE] = {0}; - - memset(pResponse, 0, sizeof(cecResponse_t)); - - numCommands = UT_KVP_PROFILE_GET_LIST_COUNT("hdmicec/cec_responses"); - - for(uint32_t i = 0; i < numCommands; i++) - { - uint8_t command; - uint8_t found; - - snprintf(key_string, HDMI_CEC_KVP_SIZE, "hdmicec/cec_responses/%d/command" , i); - command = UT_KVP_PROFILE_GET_UINT8(key_string); - - if(command != opcode) - { - continue; - } - snprintf(key_string, HDMI_CEC_KVP_SIZE, "hdmicec/cec_responses/%d/response/command" , i); - found = ut_kvp_fieldPresent(ut_kvp_profile_getInstance(), key_string); - - if(found) - { - pResponse->cecCommand = UT_KVP_PROFILE_GET_UINT8(key_string); - - snprintf(key_string, HDMI_CEC_KVP_SIZE, "hdmicec/cec_responses/%d/response/type" , i); - UT_KVP_PROFILE_GET_STRING(key_string, pResponse->type); - - snprintf(key_string, HDMI_CEC_KVP_SIZE, "hdmicec/cec_responses/%d/response/payload" , i); - pResponse->payloadSize = UT_KVP_PROFILE_GET_LIST_COUNT(key_string); - - for(uint8_t j = 0; j < pResponse->payloadSize; j++) - { - snprintf(key_string, HDMI_CEC_KVP_SIZE, "hdmicec/cec_responses/%d/response/payload/%d" , i, j); - pResponse->payload[j] = UT_KVP_PROFILE_GET_UINT8(key_string); - } - return true; - } - } - return false; -} - -static void sendResponse(int32_t handle, uint8_t initiator, uint8_t destination, - uint8_t *buf, int32_t len, cecResponse_t *pCecResponse) -{ - uint8_t prBuffer[HDMI_CEC_MAX_PAYLOAD] = {0}; - uint8_t response[HDMI_CEC_MAX_PAYLOAD] = {0}; - - if (pCecResponse->payloadSize) - { - int32_t result; - const char* commandName; - int32_t expectedDataLength; - - if (!strcmp(pCecResponse->type, "Direct")) - { - response[0] = (destination << 4) | initiator; - } - else - { - //Send braodcast message - response[0] = (gLogicalAddress << 4) | gBroadcastAddress; - } - response[1] = pCecResponse->cecCommand; - - for (int32_t index = 0; index < pCecResponse->payloadSize; index++) - { - response[index + 2] = pCecResponse->payload[index]; - } - - { - uint8_t *temp = prBuffer; - // Log each byte received in the buffer - for (int32_t index = 0; index < pCecResponse->payloadSize + 2; index++) - { - int32_t len = 0; - len = snprintf(temp, HDMI_CEC_MAX_PAYLOAD, "%02X:", response[index]); - temp += len; - } - prBuffer[strlen(prBuffer)-1] = '\0'; - - } - - HdmiCecTx(handle, response, pCecResponse->payloadSize + 2, &result); - - getCecCommandInfo(pCecResponse->cecCommand, &commandName, &expectedDataLength); - - UT_LOG_INFO("Sent Response Opcode: [0x%02X] [%s] Initiator: [%x], Destination: [%x] Data: [%s]\n", - pCecResponse->cecCommand, commandName, destination, initiator, prBuffer); - } -} - -static void onRxDataReceived(int32_t handle, void *callbackData, uint8_t *buf, int32_t len) -{ - UT_LOG_INFO("In %s(IN: handle: [%p], IN: callbackData: [%p], IN: buf: [%p], IN: len: [%d])\n", __FUNCTION__, handle, callbackData, buf, len); - - const char* commandName; - int32_t expectedDataLength; - - if ((handle != 0) && (callbackData != NULL) && (len > 0)) - { - // Parse the command - uint8_t initiator = (buf[0] >> 4) & 0xF; // Extract initiator address - uint8_t destination = buf[0] & 0xF; // Extract destination address - uint8_t opcode; // Command opcode - cecResponse_t cecResponse = {0}; // cec response - uint8_t prBuffer[HDMI_CEC_MAX_PAYLOAD] = {0}; - bool result = false; - - if( len == 1) - { - UT_LOG_INFO("Received Ping message Initiator: [%x], Destination: [%x]", initiator, destination); - goto exit; - } - - opcode = buf[1]; - - if(getCecCommandInfo(opcode, &commandName, &expectedDataLength) != 0) - { - UT_LOG_WARNING("CEC command 0x%02X is not recognized", opcode); - goto exit; - } - - { - uint8_t *temp = prBuffer; - // Log each byte received in the buffer - for (int32_t index = 0; index < len; index++) - { - int32_t len = 0; - len = snprintf(temp, HDMI_CEC_MAX_PAYLOAD, "%02X:", buf[index]); - temp += len; - } - prBuffer[strlen(prBuffer)-1] = '\0'; - } - - UT_LOG_INFO("Received Opcode: [0x%02X] [%s] Initiator: [%x], Destination: [%x] Data: [%s]\n", opcode, commandName, initiator, destination, prBuffer); - - result = getCommandResponse(opcode, &cecResponse); - - sendResponse(handle, initiator, destination, buf, len, &cecResponse); - } - else - { - // Log specific errors based on failed conditions - if (handle == 0) - { - UT_LOG_ERROR("Error: Invalid handle.\n"); - } - if (callbackData == NULL) - { - UT_LOG_ERROR("Error: Null callback data.\n"); - } - if (len <= 0) - { - UT_LOG_ERROR("Error: Invalid length.\n"); - } - } -exit: - UT_LOG_INFO("Out %s\n", __FUNCTION__); -} - -/** -* @brief Initialization of the HAL CEC Module -* -* This test provides a scope to open the HAL CEC module and preserve the handle. -* -* **Test Group ID:** 03@n -* -* **Test Case ID:** 001@n -* -* **Pre-Conditions:** None@n -* -* **Dependencies:** None@n -* -*/ -void test_l3_hdmi_cec_sink_hal_Init(void) -{ - gTestID = 1; - HDMI_CEC_STATUS status = HDMI_CEC_IO_SUCCESS; - - UT_LOG_INFO("In %s [%02d%03d]\n", __FUNCTION__, gTestGroup, gTestID); - - // Step 1: Call HdmiCecOpen() - UT_LOG_INFO("Calling HdmiCecOpen(OUT:handle:[])"); - status = HdmiCecOpen(&gHandle); - UT_LOG_INFO("Result HdmiCecOpen(OUT:handle:[0x%0X]) HDMI_CEC_STATUS:[%s]",gHandle, UT_Control_GetMapString(cecError_mapTable,status)); - assert(status == HDMI_CEC_IO_SUCCESS); - assert(gHandle != 0); - - // Step 2: Register the call back - UT_LOG_INFO("Calling HdmiCecSetRxCallback(IN:handle:[0x%0X], IN:cbfunc:[0x%0X])",gHandle, onRxDataReceived); - status = HdmiCecSetRxCallback(gHandle, onRxDataReceived,(void*)0xABABABAB); - UT_LOG_INFO("Result HdmiCecSetRxCallback(IN:handle:[0x%0X], IN:cbfunc:[0x%0X]) HDMI_CEC_STATUS:[%s]",gHandle,onRxDataReceived, UT_Control_GetMapString(cecError_mapTable,status)); - assert(status == HDMI_CEC_IO_SUCCESS); - - UT_LOG_INFO("Calling HdmiCecGetPhysicalAddress(IN:handle:[0x%0X], OUT:physicalAddress:[])", gHandle); - status = HdmiCecGetPhysicalAddress(gHandle, &gPhysicalAddress); - UT_LOG_INFO("Result HdmiCecGetPhysicalAddress(IN:handle:[0x%0X], OUT:physicalAddress:[%d]) HDMI_CEC_STATUS:[%s]", gHandle, gPhysicalAddress, UT_Control_GetMapString(cecError_mapTable,status)); - assert(status == HDMI_CEC_IO_SUCCESS); - - gPhysicalAddressBytes = (uint8_t*)&gPhysicalAddress; - - UT_LOG_INFO("Out %s\n", __FUNCTION__); -} - -/** -* @brief This test provides a scope to add the sink logical address. Usually it shall be zero. -* -* This test case provides a scope to add the available sink logical address -* to a Device under test. -* -* Note: -* This applies only for the Sink Devices. -* Source devices will get the logical address during CEC open. -* -* **Test Group ID:** 03@n -* -* **Test Case ID:** 002@n -* -* **Pre-Conditions:** @n -* HDMI-CEC Module should be intialized through Test 1 before calling this test. -* -* **Dependencies:** None@n -* -*/ -void test_l3_hdmi_cec_sink_hal_AddLogicalAddress(void) -{ - gTestID = 2; - UT_LOG_INFO("In %s [%02d%03d]\n", __FUNCTION__, gTestGroup, gTestID); - - HDMI_CEC_STATUS status = HDMI_CEC_IO_SUCCESS; - - int32_t logicalAddress = -1; - int32_t getLogicalAddress = -1; - - UT_LOG_MENU_INFO("Enter Logical Address:"); - readHex(&logicalAddress); - - /* Check that logical address should be valid one */ - UT_LOG_INFO("Calling HdmiCecAddLogicalAddress(IN:handle:[0x%0X], IN:logicalAddress:[%x]", gHandle, logicalAddress); - status = HdmiCecAddLogicalAddress(gHandle, logicalAddress); - UT_LOG_INFO("Result HdmiCecAddLogicalAddress (IN:handle:[0x%0X], IN:logicalAddress:[%x]) HDMI_CEC_STATUS[%s]",gHandle,logicalAddress,UT_Control_GetMapString(cecError_mapTable,status)); - assert(status == HDMI_CEC_IO_SUCCESS); - - UT_LOG_INFO("Calling HdmiCecGetLogicalAddress(IN:handle:[0x%0X], OUT:logicalAddress:[])", gHandle); - status = HdmiCecGetLogicalAddress(gHandle, &getLogicalAddress); - UT_LOG_INFO("Result HdmiCecGetLogicalAddress(IN:handle:[0x%0X], OUT:logicalAddress:[%x]) HDMI_CEC_STATUS:[%s])", gHandle, getLogicalAddress, UT_Control_GetMapString(cecError_mapTable,status)); - assert(status == HDMI_CEC_IO_SUCCESS); - assert(logicalAddress == getLogicalAddress); - - gLogicalAddress = getLogicalAddress; - - UT_LOG_INFO("Out %s\n", __FUNCTION__); -} - -/** -* @brief Test to get the logical address -* -* This test provides a scope to check the assigned logical address of the device. -* -* **Test Group ID:** 03@n -* -* **Test Case ID:** 003@n -* -* **Pre-Conditions:** @n -* HDMI-CEC Module should be intialized through Test 1 before calling this test. -* -* **Dependencies:** None@n -* -*/ -void test_l3_hdmi_cec_sink_hal_GetLogicalAddress(void) -{ - gTestID = 3; - UT_LOG_INFO("In %s [%02d%03d]\n", __FUNCTION__, gTestGroup, gTestID); - - HDMI_CEC_STATUS status = HDMI_CEC_IO_SUCCESS; - int32_t logicalAddress = -1; - - UT_LOG_INFO("Calling HdmiCecGetLogicalAddress(IN:handle:[0x%0X], OUT:logicalAddress:[])", gHandle); - status = HdmiCecGetLogicalAddress(gHandle, &logicalAddress); - UT_LOG_INFO("Result HdmiCecGetLogicalAddress(IN:handle:[0x%0X], OUT:logicalAddress:[%x]) HDMI_CEC_STATUS:[%s])", gHandle, logicalAddress, UT_Control_GetMapString(cecError_mapTable,status)); - assert(status == HDMI_CEC_IO_SUCCESS); - assert(logicalAddress >= 0 && logicalAddress <= 15); - - UT_LOG_INFO("Out %s\n", __FUNCTION__); -} - -/** -* @brief Test provides a scope to Transmit the CEC Command -* -* This test provides an interface to user/automation tool to transmit a CEC Command. -* Necessary input should be provided to the test. -* -* **Test Group ID:** 03@n -* -* **Test Case ID:** 004@n -* -* **Pre-Conditions:** @n -* HDMI-CEC Module should be intialized through Test 1 before calling this test. -* Logical Address should be added through Test 2 before calling this test. -* -* **Dependencies:** None@n -* -*/ -void test_l3_hdmi_cec_sink_hal_TransmitHdmiCecCommand(void) { - gTestID = 4; - UT_LOG_INFO("In %s [%02d%03d]\n", __FUNCTION__, gTestGroup, gTestID); - - int32_t sourceLogicalAddress = gLogicalAddress; - int32_t destinationLogicalAddress = -1; - uint8_t buf[16] = {0}; - int32_t len = 0, cecCommand = 0; - int32_t result; - const char* commandName; - int32_t expectedDataLength; - - assert(sourceLogicalAddress != -1); - - // Reading inputs from the user or test framework - UT_LOG_MENU_INFO("Enter a valid Destination Logical Address: "); - readHex(&destinationLogicalAddress); - - UT_LOG_MENU_INFO("Enter CEC Command (in hex): "); - readHex(&cecCommand); - - // Validate the CEC command and get the expected data length - if (getCecCommandInfo(cecCommand, &commandName, &expectedDataLength) != 0) - { - // Command not found in the map, prompt the user for additional information - UT_LOG_WARNING("CEC command 0x%02X is not recognized. It might be a vendor-specific command.", cecCommand); - - UT_LOG_MENU_INFO("Enter the number of data bytes for the CEC command:"); - readInt(&expectedDataLength); - commandName = "Vendor Specific Command"; - } - else - { - UT_LOG_INFO("CEC Command: %s (0x%02X), expects %d data byte(s)", commandName, cecCommand, expectedDataLength); - } - - // If the command has data bytes, prompt for them - if (expectedDataLength > 0) - { - for (int32_t i = 0; i < expectedDataLength; i++) - { - int32_t byte_data; - UT_LOG_MENU_INFO("Enter Databyte[%d] (in hex):", i); - readHex(&byte_data); - buf[i + 2] = (uint8_t)byte_data; // +2 to account for the first two bytes - } - } - - // Building the CEC message - buf[0] = (uint8_t)((sourceLogicalAddress << 4) | (destinationLogicalAddress & 0x0F)); - buf[1] = (uint8_t)cecCommand; - len = expectedDataLength + 2; // 1 byte for logical addresses, 1 byte for CEC Command - - // Logging the transmission attempt - UT_LOG_INFO("Calling HdmiCecTx(IN:handle:[0x%0X], IN:buf:[%p], IN:len:[%d], OUT:result:[])", gHandle, buf, len); - int32_t status = HdmiCecTx(gHandle, buf, len, &result); - UT_LOG_INFO("Result HdmiCecTx(IN:handle:[0x%0X], IN:buf:[%p], IN:len:[%d], OUT:result:[%s]) HDMI_CEC_STATUS:[%s]", gHandle, buf, len, UT_Control_GetMapString(cecError_mapTable, result)? UT_Control_GetMapString(cecError_mapTable, result):"HDMI_CEC_IO_SENT_FAILED", UT_Control_GetMapString(cecError_mapTable,status)); - assert(status == HDMI_CEC_IO_SUCCESS); - - UT_LOG_INFO("Out %s\n", __FUNCTION__); -} - -/** -* @brief Test to get the physical address -* -* This test provides a scope to read the physical address of the device. -* -* **Test Group ID:** 03@n -* -* **Test Case ID:** 005@n -* -* **Pre-Conditions:** @n -* HDMI-CEC Module should be intialized through Test 1 before calling this test. -* -* **Dependencies:** None@n -* -*/ -void test_l3_hdmi_cec_sink_hal_GetPhysicalAddress(void) -{ - gTestID = 5; - UT_LOG_INFO("In %s [%02d%03d]\n", __FUNCTION__, gTestGroup, gTestID); - - HDMI_CEC_STATUS status = HDMI_CEC_IO_SUCCESS; - uint32_t physicalAddress = -1; - - UT_LOG_INFO("Calling HdmiCecGetPhysicalAddress(IN:handle:[0x%0X], OUT:physicalAddress:[])", gHandle); - status = HdmiCecGetPhysicalAddress(gHandle, &physicalAddress); - UT_LOG_INFO("Result HdmiCecGetPhysicalAddress(IN:handle:[0x%0X], OUT:physicalAddress:[%d]) HDMI_CEC_STATUS:[%s]", gHandle, physicalAddress, UT_Control_GetMapString(cecError_mapTable,status)); - assert(status == HDMI_CEC_IO_SUCCESS); - - UT_LOG_INFO("Out %s\n", __FUNCTION__); -} - -/** -* @brief Test to Remove logical address -* -* This test provides a scope to remove the logical address of the device. HAL API to set -* to default logical addres 0xF once the logical address is removed. -* -* **Test Group ID:** 03@n -* -* **Test Case ID:** 006@n -* -* **Pre-Conditions:** @n -* HDMI-CEC Module should be intialized through Test 1 before calling this test. -* -* **Dependencies:** None@n -*/ -void test_l3_hdmi_cec_sink_hal_RemoveLogicalAddress(void) -{ - gTestID = 6; - UT_LOG_INFO("In %s [%02d%03d]\n", __FUNCTION__, gTestGroup, gTestID); - - HDMI_CEC_STATUS status = HDMI_CEC_IO_SUCCESS; - int32_t logicalAddress = gLogicalAddress; - int32_t getLogicalAddress = 0; - - assert(logicalAddress != -1); - - UT_LOG_INFO("Calling HdmiCecRemoveLogicalAddress(IN:handle:[0x%0X], IN:logicalAddress:[%d])", gHandle, logicalAddress); - status = HdmiCecRemoveLogicalAddress(gHandle, logicalAddress); - UT_LOG_INFO("Result HdmiCecRemoveLogicalAddress(IN:handle:[0x%0X], IN:logicalAddress:[%d]) HDMI_CEC_STATUS:[%s])", gHandle, logicalAddress, UT_Control_GetMapString(cecError_mapTable,status)); - assert(status == HDMI_CEC_IO_SUCCESS); - - gLogicalAddress = -1; - - UT_LOG_INFO("Out %s\n", __FUNCTION__); -} -/** -* @brief Test to close the HDMI CEC device. -* -* This test provides a scope to close the created HDMI CEC handle. -* -* **Test Group ID:** 03@n -* -* **Test Case ID:** 007@n -* -* **Pre-Conditions:** @n -* HDMI-CEC Module should be intialized through Test 1 before calling this test. -* -* **Dependencies:** None@n -*/ -void test_l3_hdmi_cec_sink_hal_Close(void) -{ - gTestID = 7; - HDMI_CEC_STATUS status; - - UT_LOG_INFO("In %s [%02d%03d]\n", __FUNCTION__, gTestGroup, gTestID); - - UT_LOG_INFO("Calling HdmiCecClose(IN:handle:[0x%0X])", gHandle); - status = HdmiCecClose(gHandle); - UT_LOG_INFO("Result HdmiCecClose(IN:handle:[0x%0X]) HDMI_CEC_STATUS:[%s]", gHandle, UT_Control_GetMapString(cecError_mapTable,status)); - assert(status == HDMI_CEC_IO_SUCCESS); - gHandle = 0; - - UT_LOG_INFO("Out %s\n", __FUNCTION__); -} - -static UT_test_suite_t * pSuite = NULL; - -/** - * @brief Register the main tests for this module - * - * @return int32_t - 0 on success, otherwise failure - */ -int32_t test_register_hdmicec_hal_sink_l3_tests(void) -{ - // Create the test suite - pSuite = UT_add_suite("[L3 HDMICEC Sink Functions] ", NULL, NULL); - if (pSuite == NULL) - { - return -1; - } - - // List of test function names and strings - UT_add_test( pSuite, "Init HDMI CEC", test_l3_hdmi_cec_sink_hal_Init); - UT_add_test( pSuite, "Add Logical Address", test_l3_hdmi_cec_sink_hal_AddLogicalAddress); - UT_add_test( pSuite, "Get Logical Address", test_l3_hdmi_cec_sink_hal_GetLogicalAddress); - UT_add_test( pSuite, "Transmit CEC Command", test_l3_hdmi_cec_sink_hal_TransmitHdmiCecCommand); - UT_add_test( pSuite, "Get Phyiscal Address", test_l3_hdmi_cec_sink_hal_GetPhysicalAddress); - UT_add_test( pSuite, "Remove Logical Address", test_l3_hdmi_cec_sink_hal_RemoveLogicalAddress); - UT_add_test( pSuite, "Close HDMI CEC", test_l3_hdmi_cec_sink_hal_Close); - - return 0; -} - -/** @} */ // End of HDMI CEC HAL Tests L1 File -/** @} */ // End of HDMI CEC HAL Tests -/** @} */ // End of HDMI CEC Module -/** @} */ // End of HPK From 3c90fa1b489d968c98a7b0b16aea4e385c48ed79 Mon Sep 17 00:00:00 2001 From: bhanucbp <141142298+bhanucbp@users.noreply.github.com> Date: Thu, 19 Dec 2024 19:35:11 +0000 Subject: [PATCH 29/40] gh #44 L3 test case development Updated tests with new raft implementation --- docs/pages/hdmi-cec-L3_TestProcedure.md | 193 ++++++++++++++++++ host/tests/classes/hdmiCEC.py | 15 +- .../hdmiCEC_L3_Tests/hdmiCEC_L3_Runall.py | 2 +- .../hdmiCEC_test01_TransmitCECCommands.py | 6 +- .../hdmiCEC_test02_ReceiveCECCommands.py | 82 ++++---- src/test_l3_hdmi_cec_driver.c | 32 ++- 6 files changed, 274 insertions(+), 56 deletions(-) create mode 100644 docs/pages/hdmi-cec-L3_TestProcedure.md diff --git a/docs/pages/hdmi-cec-L3_TestProcedure.md b/docs/pages/hdmi-cec-L3_TestProcedure.md new file mode 100644 index 0000000..4139937 --- /dev/null +++ b/docs/pages/hdmi-cec-L3_TestProcedure.md @@ -0,0 +1,193 @@ +# dsAudio HAL L3 Python Test Procedure + +## Table of Contents + +- [Acronyms, Terms and Abbreviations](#acronyms-terms-and-abbreviations) +- [Setting Up Test Environment](#setting-up-test-environment) +- [Streams Required](#streams-required) +- [Test Cases](#test-cases) + - [dsAudio_L3_Runall_Sink.py](#dsaudio_l3_runall_sinkpy) + - [dsAudio_L3_Runall_Source.py](#dsaudio_l3_runall_sourcepy) + - [dsaudio_test01_enabledisableandverifyaudioportstatus.py](#dsaudio_test01_enabledisableandverifyaudioportstatuspy) + +## Acronyms, Terms and Abbreviations + +- `HAL` - Hardware Abstraction Layer +- `L3` - Level 3 Testing +- `DUT` - Device Under Test +- `RAFT` - Rapid Automation Framework for Testing +- `YAML` - YAML Ain't Markup Language +- `HDMI` - High Definition Multimedia Interface +- `API` - Application Program Interface +- `SoC` - System on Chip +- `DUT` - Device Under Test +- `LA` - Logical Address +- `PA` - Physical Address + +## Setting Up Test Environment + +To execute `HAL` `L3` Python test cases, need a Python environment. Follow these steps mentioned in [HPK Public Documentation](https://github.com/rdkcentral/rdk-hpk-documentation/blob/main/README.md) + +### Update Configuration Files + +#### Rack Configuration File + +Example Rack configuration File: [example_rack_config.yml](../../../ut/host/tests/configs/example_rack_config.yml) + +For more details refer [RAFT](https://github.com/rdkcentral/python_raft/blob/1.0.0/README.md) and [example_rack_config.yml](https://github.com/rdkcentral/python_raft/blob/1.0.0/examples/configs/example_rack_config.yml) + +In this file, update the configuration to define the console sessions for the `DUT` and the outbound settings: + +|Console Session|Description| +|---------------|-----------| +|default|Downloads the streams required for test cases| +|ssh_hal_test|Executes the `HAL` binary for the test case| + +```yaml +rackConfig: + - dut: + ip: "XXX.XXX.XXX.XXX" # IP Address of the device + description: "stb device under test" + platform: "stb" + consoles: + - default: + type: "ssh" + port: 10022 + username: "root" + ip: "XXX.XXX.XXX" # IP address of the device + password: ' ' + - ssh_hal_test: + type: "ssh" + port: 10022 + username: "root" + ip: "XXX.XXX.XXX" # IP address of the device + password: ' ' + outbound: + download_url: "http://localhost:8000/" # download location for the CPE device + httpProxy: # Local Proxy if required + workspaceDirectory: './logs/workspace' # Local working directory +``` + +#### Device Configuration File + +Example Device configuration File: [deviceConfig.yml](../../../ut/host/tests/configs/deviceConfig.yml) + +For more details refer [RAFT](https://github.com/rdkcentral/python_raft/blob/1.0.0/README.md) and [example_device_config.yml](https://github.com/rdkcentral/python_raft/blob/1.0.0/examples/configs/example_device_config.yml) + +Update below fileds in the device configuration file: + +- Set the path for `target_directory` where `HAL` binaries will be copied onto the device. +- Specify the device profile path in `test/profile` +- Ensure the `platform` should match with the `DUT` `platform` in [Rack Configuration](#rack-configuration-file) + +```yaml +deviceConfig: + cpe1: + platform: "tv" + model: "uk" + soc_vendor: "soc" + target_directory: "/tmp/" # Target Directory on device + prompt: "" + test: + profile: "../../../profiles/sink/sink_hdmiCEC.yml" +``` + +#### Test Configuration + +Example Test Setup configuration File: [hdmiCEC_testConfig.yml](../../../ut/host/tests/classes/hdmiCEC_testConfig.yml) + +Execute command to run te HAL binary was provided in this file. + +```yaml +hdmicec: + description: "hdmi CEC testing profile / menu system for UT" + test: + artifacts: + #List of artifacts folders, test class copies the content of folder to the target device workspace + - "../../../bin/" + # exectute command, this will appended with the target device workspace path + execute: "run.sh" + type: UT-C # C (UT-C Cunit) / C++ (UT-G (g++ ut-core gtest backend)) +``` + +## Run Test Cases + +Once the environment is set up, you can execute the test cases with the following command + +```bash +python --config /ut/host/tests/configs/example_rack_config.yml --deviceConfig /ut/host/tests/configs/deviceConfig.yml +``` + +## Test Cases + +### dsAudio_L3_Runall_Sink.py + +This python file runs all the tests supported by `sink` devices + +```bash +python dsAudio_L3_Runall_Sink.py --config /ut/host/tests/configs/example_rack_config.yml --deviceConfig /ut/host/tests/configs/deviceConfig.yml +``` + +### dsAudio_L3_Runall_Source.py + +This python file runs all the tests supported by `source` devices + +```bash +python dsAudio_L3_Runall_Source.py --config /ut/host/tests/configs/example_rack_config.yml --deviceConfig /ut/host/tests/configs/deviceConfig.yml +``` + +### dsAudio_test01_EnableDisableAndVerifyAudioPortStatus.py + +#### Platform Support - test01 + +- Source +- Sink + +#### User Input Required - test01 + +**Yes**: User interaction is necessary to confirm audio playback status (This will be automated later). + +#### Acceptance Criteria - test01 + +Play **Stream #1** and confirm that audio is heard through the supported ports. + +#### Expected Results - test01 + +The test enables the specified audio ports, plays the audio stream, and subsequently disables the ports + +Success Criteria + +- User should hear audio through the enabled port during playback +- User should not hear any audio when the port is disabled. + +#### Test Steps - test01 + +- Initiate the Test: + + - Select and execute the Python file: **`dsAudio_test01_EnableDisableAndVerifyAudioPortStatus.py`** + - The test will automatically download all required artifacts and streams, copying them to the designated target directory before commencing execution. + +- Audio Playback Verification: + + The test will play the designated audio stream and prompt the user with the following: + + - Question: "Is audio playing on the enabled audio port? (Y/N)" + - Press **Y** if audio is heard (this will mark the step as PASS). + - Press **N** if no audio is heard (this will mark the step as FAIL). + +- Audio Status Confirmation (Port Disabled): + + After confirming audio playback, the test will disable the audio port and prompt the user again: + + - Question: "Is audio playing when the port is disabled? (Y/N)" + - Press **N** if no audio is heard (this will mark the step as PASS). + - Press **Y** if audio is heard (this will mark the step as FAIL). + +- Repeat for All Ports: + + The test will iterate through all available audio ports, enabling/disabling each one and collecting user feedback accordingly. + +- Test Conclusion: + + Upon receiving user responses for all ports, the test will conclude and present a final result: PASS or FAIL based on the user inputs throughout the test execution. + diff --git a/host/tests/classes/hdmiCEC.py b/host/tests/classes/hdmiCEC.py index b4ce310..4ee318d 100644 --- a/host/tests/classes/hdmiCEC.py +++ b/host/tests/classes/hdmiCEC.py @@ -56,7 +56,7 @@ def __init__(self, moduleConfigProfileFile:str, session=None, targetWorkspace:st """ self.moduleName = "hdmicec" self.testConfigFile = os.path.join(dir_path, "hdmiCEC_testConfig.yml") - self.testSuite = "L3 HDMICEC Sink Functions" + self.testSuite = "L3 HDMICEC Functions" # Prepare the profile file on the target workspace self.moduleConfigProfile = ConfigRead( moduleConfigProfileFile , self.moduleName) @@ -180,10 +180,17 @@ def getPhysicalAddress(self): str: Physical Address of the DUT. """ result = self.utMenu.select( self.testSuite, "Get Phyiscal Address") - typeStatusPattern = r"Result HdmiCecGetPhysicalAddress\(IN:handle:[.*\], OUT:physicalAddress:[.*\]) HDMI_CEC_STATUS:[.*\]" - physicalAddress = self.searchPattern(result, typeStatusPattern) - return physicalAddress + addressBytes = None + pattern = r"Result HdmiCecGetPhysicalAddress\(IN:handle:.*OUT:physicalAddress:\[([\da-fA-F]\.[\da-fA-F]\.[\da-fA-F]\.[\da-fA-F])\]" + physicalAddress = self.searchPattern(result, pattern) + if physicalAddress: + parts = physicalAddress.split(".") + high_byte = hex(int(parts[0], 16) << 4 | int(parts[1], 16)) + low_byte = hex(int(parts[2], 16) << 4 | int(parts[3], 16)) + addressBytes = [high_byte, low_byte] + + return addressBytes def cecTransmitCmd(self, destLogicalAddress:str, cecCommand:str, cecData:list=None): """ diff --git a/host/tests/hdmiCEC_L3_Tests/hdmiCEC_L3_Runall.py b/host/tests/hdmiCEC_L3_Tests/hdmiCEC_L3_Runall.py index 05748ec..6fc77e7 100644 --- a/host/tests/hdmiCEC_L3_Tests/hdmiCEC_L3_Runall.py +++ b/host/tests/hdmiCEC_L3_Tests/hdmiCEC_L3_Runall.py @@ -36,7 +36,7 @@ def Runall_L3(): skipTests = [] # Summery log for all the tests - hdmiCECSummerLog = logModule("hdmiCEC_Sink", level=logModule.INFO) + hdmiCECSummerLog = logModule("hdmiCEC", level=logModule.INFO) testDirectory = Path(dir_path) diff --git a/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test01_TransmitCECCommands.py b/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test01_TransmitCECCommands.py index fc993e7..262d546 100755 --- a/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test01_TransmitCECCommands.py +++ b/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test01_TransmitCECCommands.py @@ -98,8 +98,6 @@ def testFunction(self): # Final test result finalResult = True - self.hdmiCECController.startMonitoring() - for device in self.cecDevices: logicalAddress = device["logical address"] @@ -130,14 +128,12 @@ def testFunction(self): self.log.stepStart(f'HdmiCecTx Receive Source: {deviceLogicalAddress} Destination: {destinationLogicalAddress} CEC OPCode: {cec} Payload: {payload}') # Validate the transmission - rxResult = self.hdmiCECController.checkTransmitStatus(deviceLogicalAddress, destinationLogicalAddress, cec, payload) + rxResult = self.hdmiCECController.receiveMessage(deviceLogicalAddress, destinationLogicalAddress, cec, payload) self.log.stepResult(rxResult, f'HdmiCecTx Receive Source: {deviceLogicalAddress} Destination: {destinationLogicalAddress} CEC OPCode: {cec} Payload: {payload}') finalResult &= rxResult - self.hdmiCECController.stopMonitoring() - # Remove the Logical Address self.testhdmiCEC.removeLogicalAddress() diff --git a/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test02_ReceiveCECCommands.py b/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test02_ReceiveCECCommands.py index 18c1c45..357200b 100644 --- a/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test02_ReceiveCECCommands.py +++ b/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test02_ReceiveCECCommands.py @@ -23,6 +23,7 @@ import os import sys +import time # Append the current and parent directory paths to sys.path for module imports dir_path = os.path.dirname(os.path.realpath(__file__)) @@ -105,62 +106,69 @@ def testFunction(self): # Get the logical Address. deviceLogicalAddress = self.testhdmiCEC.getLogicalAddress() + # Get Physical Address + devicePhysicalAddress = self.testhdmiCEC.getPhysicalAddress() + # Ensure the logical address is retrieved successfully if deviceLogicalAddress is None: self.log.error("Failed to get the device logical address") return False - # Retrieve details of the HDMI-CEC adapter - self.cecAdaptor = self.hdmiCECController.adaptorDetails + # List all connected CEC devices + self.cecDevices = self.hdmiCECController.listDevices() - if self.cecAdaptor is None: - return False + finalResult = True - # Get the logical address of the HDMI-CEC adapter - cecAdapterLogicalAddress = self.cecAdaptor["logical address"] + for device in self.cecDevices: + logicalAddress = device["logical address"] - self.hdmiCECController.startMonitoring() - finalResult = True - for command in self.cecCommands: - result = False - cecOpcode = command.get("command") - payload = command.get("payload") - response = command.get("response") - type = command.get("type") + # Skip sending messages to TV + if logicalAddress == deviceLogicalAddress: + continue - # Determine the destination logical address - destinationLogicalAddress = deviceLogicalAddress - if type == "Broadcast": - destinationLogicalAddress = self.broadcastAddress + cecAdapterLogicalAddress = logicalAddress - self.log.stepStart(f'Send Test: {cecAdapterLogicalAddress} Destination: {destinationLogicalAddress} CEC OPCode: {cecOpcode} Payload: {payload}') + for command in self.cecCommands: + result = False + cecOpcode = command.get("command") + payload = command.get("payload") + response = command.get("response") + type = command.get("type") - self.hdmiCECController.sendMessage(cecAdapterLogicalAddress, destinationLogicalAddress, cecOpcode, payload) + # Determine the destination logical address + destinationLogicalAddress = deviceLogicalAddress + if type == "Broadcast": + destinationLogicalAddress = self.broadcastAddress - # Read the callback details and verify the received data - callbackData = self.testhdmiCEC.readCallbackDetails() - result = self.testVerifyReceivedData(callbackData, cecAdapterLogicalAddress, destinationLogicalAddress, cecOpcode, payload) + self.log.stepStart(f'Send Test: Source: {cecAdapterLogicalAddress} Destination: {destinationLogicalAddress} CEC OPCode: {cecOpcode} Payload: {payload}') - finalResult &= result + self.hdmiCECController.sendMessage(cecAdapterLogicalAddress, destinationLogicalAddress, cecOpcode, payload) - self.log.stepResult(result, f'Send Test: {cecAdapterLogicalAddress} Destination: {destinationLogicalAddress} CEC OPCode: {cecOpcode} Payload: {payload}') + # Read the callback details and verify the received data + callbackData = self.testhdmiCEC.readCallbackDetails() + result = self.testVerifyReceivedData(callbackData, cecAdapterLogicalAddress, destinationLogicalAddress, cecOpcode, payload) - # If a response is expected, validate the response - if response: - destinationLogicalAddress = cecAdapterLogicalAddress - if response.get("type") == "Broadcast": - destinationLogicalAddress = self.broadcastAddress + finalResult &= result - cecOpcode = response.get("command") - payload = response.get("payload") + self.log.stepResult(result, f'Send Test: Source: {cecAdapterLogicalAddress} Destination: {destinationLogicalAddress} CEC OPCode: {cecOpcode} Payload: {payload}') - self.log.stepStart(f'Response Test: {deviceLogicalAddress} Destination: {destinationLogicalAddress} CEC OPCode: {cecOpcode} Payload: {payload}') - result = self.hdmiCECController.checkTransmitStatus(deviceLogicalAddress, destinationLogicalAddress, cecOpcode, payload) - self.log.stepResult(result, f'Response Test: {cecAdapterLogicalAddress} Destination: {destinationLogicalAddress} CEC OPCode: {cecOpcode} Payload: {payload}') + # If a response is expected, validate the response + if response: + destinationLogicalAddress = cecAdapterLogicalAddress + if response.get("type") == "Broadcast": + destinationLogicalAddress = self.broadcastAddress - finalResult &= result + cecOpcode = response.get("command") + payload = response.get("payload") + if response.get("update_payload"): + payload[0] = devicePhysicalAddress[0] + payload[1] = devicePhysicalAddress[1] + + self.log.stepStart(f'Response Test: Source: {deviceLogicalAddress} Destination: {destinationLogicalAddress} CEC OPCode: {cecOpcode} Payload: {payload}') + result = self.hdmiCECController.receiveMessage(deviceLogicalAddress, destinationLogicalAddress, cecOpcode, payload) + self.log.stepResult(result, f'Response Test: Source: {deviceLogicalAddress} Destination: {destinationLogicalAddress} CEC OPCode: {cecOpcode} Payload: {payload}') - self.hdmiCECController.stopMonitoring() + finalResult &= result # Remove the Logical Address self.testhdmiCEC.removeLogicalAddress() diff --git a/src/test_l3_hdmi_cec_driver.c b/src/test_l3_hdmi_cec_driver.c index 13fb827..27799c3 100644 --- a/src/test_l3_hdmi_cec_driver.c +++ b/src/test_l3_hdmi_cec_driver.c @@ -438,6 +438,7 @@ void test_l3_hdmi_cec_hal_Init(void) { gTestID = 1; HDMI_CEC_STATUS status = HDMI_CEC_IO_SUCCESS; + int32_t getLogicalAddress = -1; UT_LOG_INFO("In %s [%02d%03d]\n", __FUNCTION__, gTestGroup, gTestID); @@ -454,12 +455,23 @@ void test_l3_hdmi_cec_hal_Init(void) UT_LOG_INFO("Result HdmiCecSetRxCallback(IN:handle:[0x%0X], IN:cbfunc:[0x%0X]) HDMI_CEC_STATUS:[%s]",gHandle,onRxDataReceived, UT_Control_GetMapString(cecError_mapTable,status)); assert(status == HDMI_CEC_IO_SUCCESS); + gPhysicalAddressBytes = (uint8_t*)&gPhysicalAddress; + UT_LOG_INFO("Calling HdmiCecGetPhysicalAddress(IN:handle:[0x%0X], OUT:physicalAddress:[])", gHandle); status = HdmiCecGetPhysicalAddress(gHandle, &gPhysicalAddress); - UT_LOG_INFO("Result HdmiCecGetPhysicalAddress(IN:handle:[0x%0X], OUT:physicalAddress:[%x]) HDMI_CEC_STATUS:[%s]", gHandle, gPhysicalAddress, UT_Control_GetMapString(cecError_mapTable,status)); + UT_LOG_INFO("Result HdmiCecGetPhysicalAddress(IN:handle:[0x%0X], OUT:physicalAddress:[%01x.%01x.%01x.%01x]) HDMI_CEC_STATUS:[%s]", gHandle, + gPhysicalAddressBytes[3], gPhysicalAddressBytes[2], gPhysicalAddressBytes[1], gPhysicalAddressBytes[0], + UT_Control_GetMapString(cecError_mapTable,status)); assert(status == HDMI_CEC_IO_SUCCESS); - gPhysicalAddressBytes = (uint8_t*)&gPhysicalAddress; + if (gDeviceType == SOURCE) + { + UT_LOG_INFO("Calling HdmiCecGetLogicalAddress(IN:handle:[0x%0X], OUT:logicalAddress:[])", gHandle); + status = HdmiCecGetLogicalAddress(gHandle, &getLogicalAddress); + UT_LOG_INFO("Result HdmiCecGetLogicalAddress(IN:handle:[0x%0X], OUT:logicalAddress:[%x]) HDMI_CEC_STATUS:[%s])", gHandle, getLogicalAddress, UT_Control_GetMapString(cecError_mapTable,status)); + + gLogicalAddress = getLogicalAddress; + } UT_LOG_INFO("Out %s\n", __FUNCTION__); } @@ -494,6 +506,9 @@ void test_l3_hdmi_cec_hal_AddLogicalAddress(void) int32_t logicalAddress = -1; int32_t getLogicalAddress = -1; + UT_LOG_MENU_INFO("Enter Logical Address:"); + readHex(&logicalAddress); + if (gDeviceType == SOURCE) { UT_LOG_ERROR("Source Device doesn't support add logical Address"); @@ -501,9 +516,6 @@ void test_l3_hdmi_cec_hal_AddLogicalAddress(void) return; } - UT_LOG_MENU_INFO("Enter Logical Address:"); - readHex(&logicalAddress); - /* Check that logical address should be valid one */ UT_LOG_INFO("Calling HdmiCecAddLogicalAddress(IN:handle:[0x%0X], IN:logicalAddress:[%x]", gHandle, logicalAddress); status = HdmiCecAddLogicalAddress(gHandle, logicalAddress); @@ -550,6 +562,7 @@ void test_l3_hdmi_cec_hal_GetLogicalAddress(void) assert(status == HDMI_CEC_IO_SUCCESS); assert(logicalAddress >= 0 && logicalAddress <= 15); + gLogicalAddress = logicalAddress; UT_LOG_INFO("Out %s\n", __FUNCTION__); } @@ -627,7 +640,7 @@ void test_l3_hdmi_cec_hal_TransmitHdmiCecCommand(void) { UT_LOG_INFO("Calling HdmiCecTx(IN:handle:[0x%0X], IN:buf:[%p], IN:len:[%d], OUT:result:[])", gHandle, buf, len); int32_t status = HdmiCecTx(gHandle, buf, len, &result); UT_LOG_INFO("Result HdmiCecTx(IN:handle:[0x%0X], IN:buf:[%p], IN:len:[%d], OUT:result:[%s]) HDMI_CEC_STATUS:[%s]", gHandle, buf, len, UT_Control_GetMapString(cecError_mapTable, result)? UT_Control_GetMapString(cecError_mapTable, result):"HDMI_CEC_IO_SENT_FAILED", UT_Control_GetMapString(cecError_mapTable,status)); - assert(status == HDMI_CEC_IO_SUCCESS); + assert(status == HDMI_CEC_IO_SUCCESS || status == HDMI_CEC_IO_SENT_AND_ACKD || status == HDMI_CEC_IO_SENT_BUT_NOT_ACKD ); UT_LOG_INFO("Out %s\n", __FUNCTION__); } @@ -653,11 +666,12 @@ void test_l3_hdmi_cec_hal_GetPhysicalAddress(void) UT_LOG_INFO("In %s [%02d%03d]\n", __FUNCTION__, gTestGroup, gTestID); HDMI_CEC_STATUS status = HDMI_CEC_IO_SUCCESS; - uint32_t physicalAddress = -1; UT_LOG_INFO("Calling HdmiCecGetPhysicalAddress(IN:handle:[0x%0X], OUT:physicalAddress:[])", gHandle); - status = HdmiCecGetPhysicalAddress(gHandle, &physicalAddress); - UT_LOG_INFO("Result HdmiCecGetPhysicalAddress(IN:handle:[0x%0X], OUT:physicalAddress:[%x]) HDMI_CEC_STATUS:[%s]", gHandle, physicalAddress, UT_Control_GetMapString(cecError_mapTable,status)); + status = HdmiCecGetPhysicalAddress(gHandle, &gPhysicalAddress); + UT_LOG_INFO("Result HdmiCecGetPhysicalAddress(IN:handle:[0x%0X], OUT:physicalAddress:[%01x.%01x.%01x.%01x]) HDMI_CEC_STATUS:[%s]", gHandle, + gPhysicalAddressBytes[3], gPhysicalAddressBytes[2], gPhysicalAddressBytes[1], gPhysicalAddressBytes[0], + UT_Control_GetMapString(cecError_mapTable,status)); assert(status == HDMI_CEC_IO_SUCCESS); UT_LOG_INFO("Out %s\n", __FUNCTION__); From 69eb512cf543134766bb9979ba98d412509b998a Mon Sep 17 00:00:00 2001 From: bhanucbp <141142298+bhanucbp@users.noreply.github.com> Date: Fri, 20 Dec 2024 12:21:13 +0000 Subject: [PATCH 30/40] gh #44 L3 test case development Initialized global handle with correct value --- src/test_l3_hdmi_cec_driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test_l3_hdmi_cec_driver.c b/src/test_l3_hdmi_cec_driver.c index 27799c3..68105f2 100644 --- a/src/test_l3_hdmi_cec_driver.c +++ b/src/test_l3_hdmi_cec_driver.c @@ -192,7 +192,7 @@ typedef enum HDMI_CEC_DEVICE_TYPE_t static int32_t gTestGroup = 3; static int32_t gTestID = 1; -static int32_t gHandle = 1; +static int32_t gHandle = 0; static int32_t gLogicalAddress = -1; static uint32_t gPhysicalAddress = -1; static uint8_t *gPhysicalAddressBytes; From 87dca6206ef04ca9950717aabce6a220d45be2c9 Mon Sep 17 00:00:00 2001 From: bhanucbp <141142298+bhanucbp@users.noreply.github.com> Date: Mon, 23 Dec 2024 13:21:28 +0000 Subject: [PATCH 31/40] gh #44 L3 test case development Updated raft tag --- host/install.sh | 2 +- .../hdmiCEC_L3_Tests/hdmiCEC_test01_TransmitCECCommands.py | 2 +- .../tests/hdmiCEC_L3_Tests/hdmiCEC_test02_ReceiveCECCommands.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/host/install.sh b/host/install.sh index 9a5ff8a..fefb72d 100755 --- a/host/install.sh +++ b/host/install.sh @@ -158,7 +158,7 @@ setup_and_enable_venv ### Clone required repos ### # Setup raft -clone_repo git@github.com:rdkcentral/python_raft.git "${RAFT_DIR}" "1.1.1" "in ./raft" +clone_repo git@github.com:rdkcentral/python_raft.git "${RAFT_DIR}" "1.2.0" "in ./raft" install_pip_requirements "${RAFT_DIR}"/requirements.txt # Setup ut-raft diff --git a/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test01_TransmitCECCommands.py b/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test01_TransmitCECCommands.py index 262d546..4bbb2f7 100755 --- a/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test01_TransmitCECCommands.py +++ b/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test01_TransmitCECCommands.py @@ -128,7 +128,7 @@ def testFunction(self): self.log.stepStart(f'HdmiCecTx Receive Source: {deviceLogicalAddress} Destination: {destinationLogicalAddress} CEC OPCode: {cec} Payload: {payload}') # Validate the transmission - rxResult = self.hdmiCECController.receiveMessage(deviceLogicalAddress, destinationLogicalAddress, cec, payload) + rxResult = self.hdmiCECController.checkMessageReceived(deviceLogicalAddress, destinationLogicalAddress, cec, payload=payload) self.log.stepResult(rxResult, f'HdmiCecTx Receive Source: {deviceLogicalAddress} Destination: {destinationLogicalAddress} CEC OPCode: {cec} Payload: {payload}') diff --git a/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test02_ReceiveCECCommands.py b/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test02_ReceiveCECCommands.py index 357200b..7566811 100644 --- a/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test02_ReceiveCECCommands.py +++ b/host/tests/hdmiCEC_L3_Tests/hdmiCEC_test02_ReceiveCECCommands.py @@ -165,7 +165,7 @@ def testFunction(self): payload[1] = devicePhysicalAddress[1] self.log.stepStart(f'Response Test: Source: {deviceLogicalAddress} Destination: {destinationLogicalAddress} CEC OPCode: {cecOpcode} Payload: {payload}') - result = self.hdmiCECController.receiveMessage(deviceLogicalAddress, destinationLogicalAddress, cecOpcode, payload) + result = self.hdmiCECController.checkMessageReceived(deviceLogicalAddress, destinationLogicalAddress, cecOpcode, payload=payload) self.log.stepResult(result, f'Response Test: Source: {deviceLogicalAddress} Destination: {destinationLogicalAddress} CEC OPCode: {cecOpcode} Payload: {payload}') finalResult &= result From c920a0438d346badd11d97170200ab557f3ff79b Mon Sep 17 00:00:00 2001 From: bhanucbp <141142298+bhanucbp@users.noreply.github.com> Date: Mon, 23 Dec 2024 16:56:24 +0000 Subject: [PATCH 32/40] gh #44 L3 test case development Updated specification document --- docs/pages/hdmi-cec-L3-Low-Level_TestSpec.md | 97 +++++ .../hdmi-cec-sink-L3-Low-Level_TestSpec.md | 346 ------------------ 2 files changed, 97 insertions(+), 346 deletions(-) create mode 100644 docs/pages/hdmi-cec-L3-Low-Level_TestSpec.md delete mode 100644 docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md diff --git a/docs/pages/hdmi-cec-L3-Low-Level_TestSpec.md b/docs/pages/hdmi-cec-L3-Low-Level_TestSpec.md new file mode 100644 index 0000000..df6d41d --- /dev/null +++ b/docs/pages/hdmi-cec-L3-Low-Level_TestSpec.md @@ -0,0 +1,97 @@ +# HDMI CEC L3 Test Document + +## Table of Contents + +- [Acronyms, Terms and Abbreviations](#acronyms-terms-and-abbreviations) +- [Overview](#overview) +- [References](#references) +- [Level 3 Test Procedure](#level-3-test-cases-high-level-overview) +- [Level 3 Python Test](#level-3-python-test-cases-high-level-overview) + +## Overview + +This document describes the L3 Test Procedure for the HDMI CEC module. + +## Acronyms, Terms and Abbreviations + +- `CEC` - Consumer Electronics Control +- `HAL` - Hardware Abstraction layer +- `HDMI` - High Definition Multimedia Interface +- `API` - Application Program Interface +- `SoC` - System on Chip +- `DUT` - Device Under Test +- `LA` - Logical Address +- `PA` - Physical Address + +## References + +- CEC Adaptor: [Pulse Eight](https://www.pulse-eight.com/p/104/usb-hdmi-cec-adapter) +- `HAL` interface file: [hdmi_cec_driver.h](https://github.com/rdkcentral/rdk-halif-hdmi_cec/blob/1.3.9/include/hdmi_cec_driver.h) + +## Level 3 Test Cases High Level Overview + +|#|Test-case|Description|HAL APIs|Source|Sink| +|-|---------|-----------|--------|------|----| +|1|Transmit CEC Commands|Send predefined `CEC` commands from the DUT and verify if the command is successfully transmitted using the CEC adapter| `HdmiCecTx()`|`Y`|`Y`| +|2|Receive CEC commands|Send predefined `CEC` commands from the CEC adapter, verify if the `DUT` successfully receives the command, and check the response through call-backs.| `HdmiCecTx()`|`Y`|`Y`| + +## Level 3 Python Test Cases High Level Overview + +The class diagram below illustrates the flow of HDMI CEC Python test cases: + +```mermaid +--- +title: HDMI-CEC - Python Class Flow +--- +classDiagram + testControl <|-- ut_raft : inherits + class ut_raft{ + } + ut_raft <|-- hdmiCECHelperClass : inherits + hdmiCECHelperClass <|-- L3_TestClasses : inherits + L3_TestClasses ..> hdmiCEC : uses + note for testControl "uses rackConfig.yml and deviceConfig.yml" + note for hdmiCEC "uses platformProfile.yml" + note for L3_TestClasses "uses hdmiCECTestCommands.yml" + note for ut_raft "suite Navigator uses testSuite.yml" +``` + +- **testControl** + - Test Control Module for running rack Testing. This module configures the `DUT` based on the rack configuration file provided to the test. + - This class is defined in `RAFT` framework. For more details refer [RAFT](https://github.com/rdkcentral/python_raft/blob/1.2.0/README.md) +- **ut_raft** + - Python based testing framework for writing engineering tests. + - It provides common functionalities like menu navigation, configuration reader, reading user response etc. + - For more details [ut-raft](https://github.com/rdkcentral/ut-raft/tree/2.0.0) +- **hdmiCEC** + - This is test helper class which communicates with the `L3` C/C++ test running on the `DUT` through menu +- **L3_TestClasses** + - These are the L3 test case classes + - Each class covers the each test use-case defined in [L3 Test use-cases](#level-3-test-cases-high-level-overview) table + +### YAML File Inputs + +- **rackConfig.yaml** + - Identifies the rack configuration and platform used + - References platform-specific config from `deviceConfig.yaml` + - For more details refer [RAFT](https://github.com/rdkcentral/python_raft/blob/1.2.0/README.md) and [example_rack_config.yml](https://github.com/rdkcentral/python_raft/blob/1.2.0/examples/configs/example_rack_config.yml) + +- **deviceConfig.yaml** + - Specifies overall configuration for the platform + - Can be overridden by: + - Changing locally .yaml file directory + - Using --deviceConfig command line switch + - For more details refer [RAFT](https://github.com/rdkcentral/python_raft/blob/1.2.0/README.md) and [example_device_config.yml](https://github.com/rdkcentral/python_raft/blob/1.2.0/examples/configs/example_device_config.yml) + +- **componentProfile.yaml/platformProfile.yaml** + - Contains component-specific configurations + - Contains platform wide configuration broken down into separate components + - Example configuration file [sink_hdmiCEC](../../profiles/sink/sink_hdmiCEC.yml) + +- **hdmiCECTestCommands.yaml** + - This configuration file contains the list of `CEC` commands. + - Example configuration file [hdmiCECTestCommands.yml](../../host/tests/hdmiCEC_L3_Tests/hdmiCECTestCommands.yml) + +- **testConfig.yaml** + - This configuration file contains the list of menu items for C/C++ L3 test running on `DUT` + - Example configuration file [hdmiCEC_testConfig.yml](../../host/tests/classes/hdmiCEC_testConfig.yml) diff --git a/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md b/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md deleted file mode 100644 index 5635d76..0000000 --- a/docs/pages/hdmi-cec-sink-L3-Low-Level_TestSpec.md +++ /dev/null @@ -1,346 +0,0 @@ -# HDMI CEC L3 Test Document for Sink Devices. - -## Table of Contents -- [Acronyms, Terms and Abbreviations](#acronyms-terms-and-abbreviations) -- [Description](#description) -- [Component Runtime Execution Requirements](#component-runtime-execution-requirements) - - [Initialization and Startup] - -## Overview -This document provides an overview of the L3 testing requirements for the module `HDMI CEC` source device. It outlines the scope of testing, objectives, External devices, specific test requirements, expected deliverables, and approaches to satisfy the L3 Test requirement. - -## Acronyms, Terms and Abbreviations -- `CEC` - Consumer Electronics Control -- `HAL` - Hardware Abstraction layer -- `HDMI` - High Definition Multimedia Interface -- `API` - Application Program Interface -- `SoC` - System on Chip -- `DUT` - Device Under Test -- `LA` - Logical Address -- `PA` - Physical Address - - -## References -- CEC Adaptor: https://www.pulse-eight.com/p/104/usb-hdmi-cec-adapter# -- `HAL` interface file: https://github.com/rdkcentral/rdk-halif-hdmi_cec/blob/main/include/hdmi_cec_driver.h - - -## Module Description -Consumer Electronics Control (`CEC`) is a one-wire bidirectional bus within an HDMI system that enables interconnected products to communicate. This module outlines a set of `HAL` `APIs` designed to support `HDMI` `CEC` functionality. The current document details the L3 test definitions and descriptions used to validate these `HDMI` `CEC` `APIs`, including the prerequisites that must be managed before testing and the external stimuli that need to be applied during the test. - -The present document describes the test scope for the Sink Device activities only. - -### HDMI-CEC L3 Test Functionality -The picture below depicts the HDMI CEC L3 Test Functionality Setup. This simple setup has an HDMI CEC Pulse-eight USB adaptor, which acts as a source device and can send the required commands (using libcec tool commands) and respond to the received CEC Commands. - -Note: The below-shown prerequisites should be met before starting the test on the platforms. -- All the devices used in the test setup should support the `HDMI` `CEC` feature during the entire test duration. -- HDMI drivers should be up and running on the platform before running this test. -- For now, it is suggested not to connect multiple CEC Adaptors onto a single PC as there is no proper support on libcec for multiple devices. - -```mermaid -graph TB -C[PC] <--> A -A[Pulse-Eight CEC Adaptor ] <--> |HDMI| B[TV] -``` - -### Pulse-Eight CEC Adaptor tool: -The Pulse-Eight CEC Adapter will be used to frame and send commands to the DUT. This tool leverages libcec, which can be installed to facilitate CEC activities during testing. The cec-client tool will be employed extensively throughout the test. Additionally, RAFT can use this tool to automate the test cases. - -- Reference to the tool: https://www.pulse-eight.com/p/104/usb-hdmi-cec-adapter -- libcec tools: https://www.pulse-eight.com/Download/Get/51 - -**Libraries and tools required for RAFT** -- libcec should be installed on the PC where the Pulse-Eight CEC Adaptor is connected. -- python-cec will be used to control the `CEC` adaptor. -- https://pypi.org/project/cec/ will provide more information on how to use this library. - -**cec-ctrl Commands used in Manual Mode** -- libcec should be installed on the PC where the Pulse-Eight CEC Adaptor is connected. -- To get the logical and physical address: `cec-client -s -d 4` -- To Tx data: `cec-client -s -t 1 --data ` or `echo "tx " | cec-client -s` Eg:`echo "tx 10:36" | cec-client -s` -- To check the last received data use `cec-client -m | grep '>>' | tail -n 1`. `cec-client -m` shall monitor the data continuously - -**Prerequisite Test to make sure all the CEC Adaptors are connected** -1. Make sure to read the physical address of the CEC Adaptor allocated based on the port it has been connected to, using libCEC on PC. -2. The physical and logical addresses allocated to the CEC adaptor shall be read and validated on RAFT. - -## Test Functionalities - -#### Message Transmission and Reception Test -Note: All the below tests should be carried out on all the available HMDI ports. -- Transmit an HDMI CEC basic command (GetCECVersion) from the DUT to receive a reply from the connected CEC Adaptor. -- Receive an HDMI OSD Command with a string of maximum length (14 bytes) from the CEC Adaptor and acknowledge it. -- The CEC Adaptor sends a standby command to a device to all the logical addresses other than 0x00 and 0x0f. `DUT` should not respond to any of these commands. - -#### Message Broadcast and Receive broadcast -Note: All the below tests should be carried out on all the available HMDI ports. -- Broadcast an HDMI CEC Command from the DUT and verify that this command has been received on the CEC Adaptor. -- Receive a standby broadcasting command on the DUT sent by the CEC Adaptor and validate it. - -#### Stress Test -- Receiving an HDMI OSD Command repeatedly for 10 times with a different string of max length from CEC Adaptor. -- Transmit an HDMI OSD Command repeatedly for 10 times with a different string of max length to the CEC Adaptor. - -#### Hardware Fault Test -- Introducing a Fault on the HDMI line to test the Transmit functionality. - -# Test 1: Message Transmission and Reception Test - Unicast messages - -Functionality: -1. RAFT/user to send a simple "getCECVersion" command to the `DUT` before setting the logical address. -2. `DUT` shall request a CEC Version from the CEC adaptor connected. `DUT` should receive a valid CEC version. -3. `DUT` shall receive an OSD Command with max buffer size from the CEC Adaptor and acknowledge to this command. -4. `DUT` shall receive a "getCECVersion" command with a different `LA` from 0x01 to 0x0E and should not receive any acknowledgment. - -| Title | Details | -|-------------------------------|--------------------------------------------------| -| Function Name | `test_l3_hdmi_cec_sink_tx_rx_test` | -| Description | This test shall validate the Tx, and Rx CEC Commands between the `DUT`and CEC Adaptor connected on a network | -| Test Group | 03 | -| Test Case ID | 002 | -| Priority | High | - -**Pre-Conditions:** -- The platforms are connected as shown in the picture where the CEC Adaptor is considered to be connected and detected correctly. -- libcec is installed on the PC where the CEC Adaptor tool is connected. libcec shall respond to all the basic CEC Commands received from `DUT` - -**Dependencies:** -- Prerequisites should be met before starting this test. - -**User Interaction:** -- If the user chooses to run the test in interactive mode, then the test case has to be selected via the console. -- If the user chooses to run manually, he should use the cec-client commands as shown above. -- RAFT will replace the human to run the test if required, but still, the RAFT should provide an option for the user to change the HMDI ports and start the test again. -- The user should choose either to run manually or choose the RAFT. - -**RAFT Requirements:** -- RAFT shall initiate the test by reading and validating the LA and PA. -- RAFT shall initiate the commands to send the CEC OSD command with the string data as read from the hdmicec_sinktest.yml file. -- RAFT shall provide a means to enter the LA for the test and any other data required during the test. -- RAFT shall consider reading and give input to the test wherever required. - -**Sequence Diagram** -```mermaid -sequenceDiagram - participant DUT - participant CEC Adaptor - participant RAFT/user - RAFT/user->>CEC Adaptor: Read and validate LA and PA - RAFT/user->>DUT: Start the HAL test - DUT->>DUT: Set receive Callback - CEC Adaptor->>DUT: Send "GetCECVersion" before adding the logical address - RAFT/user->>RAFT/user: No response or ack should be received. - DUT->>DUT: Wait for the RAFT/user to signal to provide ack received or not. - RAFT/user->>DUT: RAFT/user to signal the test to move ahead - DUT->>DUT: Check no RxCallback has been received and decide whether the test passes or fails - DUT->>DUT: Add Logical Address - DUT->>DUT: Wait for User/RAFT to enter the logical address - RAFT/user->>DUT: RAFT/user to provide the logical address - DUT->>CEC Adaptor: Send "GetCECVersion" - CEC Adaptor->>DUT: Send the "CEC Version" - DUT->>DUT: Validate CEC Version - DUT->>DUT: Wait for User/RAFT to signal the start of the next test - RAFT/user->>DUT: RAFT/user to signal the test to move ahead - RAFT/user->>CEC Adaptor: Command to send CEC OSD Command - CEC Adaptor->>DUT: Send CEC OSD Command - DUT->>DUT: Validate the received command - RAFT/user->>RAFT/user: Read the CEC acknowledgment received and validate - DUT->>DUT: Wait for User/RAFT to enter the acknowledgment confirmation and decide Test Pass/Fail - RAFT/user->>DUT: RAFT/user to provide the test result - CEC Adaptor->>DUT: Send "GetCECVersion" to an LA other than `DUT`(0x01 to 0x0E). Repeat these 4 steps for all the addresses sent. - DUT->>DUT: Wait for User/RAFT to signal when the CEC adaptor has sent a CEC message. - RAFT/user->>DUT: RAFT/user to signal the test to move ahead - DUT->>DUT: Test fails if it has received any message. - RAFT/user->>RAFT/user: No CEC acknowledgment is received after CEC Frames are sent. -``` - -#### Test Procedure - -| Variation / Steps | Description | Test Data | Expected Result | Notes | -|-------------------|-------------|-----------|------------------|-------| -| 01 | Open HDMI CEC HAL using `HdmiCecOpen` API | `handle` = valid pointer | `HDMI_CEC_IO_SUCCESS` | Should be successful | -| 02 | Set the receive callback function using `HdmiCecSetRxCallback` | `handle` = valid handle, `cbfunc` = RxCallback, `data` = buffer pointer | `HDMI_CEC_IO_SUCCESS` | Should be successful | -| 03 | RAFT/user to send a "getCECVersion" command to the Device Under Test (DUT) and should not receive any response or acknowledgment | CEC command = read from "getCECVersion" in YAML file, LA = 0 | N/A | Should be successful | -| 04 | DUT to wait for a signal from RAFT/user and then validate whether it has received any data. The test fails if it has received any data. | Data received on the Rx callback | No Rx Callback is made | Should be successful | -| 05 | Acquire a valid logical address `0x00` using `HdmiCecAddLogicalAddress` | `handle` = valid handle, `logicalAddress` = 0 | `HDMI_CEC_IO_SUCCESS` | Should be successful | -| 06 | Wait to get the connected device (CEC Adaptor) logical address from RAFT/user | N/A | N/A | RAFT/user to enter the logical address of the CEC Adaptor | -| 07 | Frame a "getCECVersion" command using the "getCECVersion" command from the test YAML file and send it using `HdmiCecTx` | `handle` = valid handle, `buf` = CEC buffer with LA and command, `len` = sizeof(buf), `result` = valid pointer | `HDMI_CEC_IO_SUCCESS` | Should be successful | -| 08 | Wait for a second and validate a response from the CEC Adaptor on the RxCallback and validate | Test data received from CEC Adaptor | Read and validate this data. Rx data should be a valid CEC version | Should be successful | -| 09 | Frame and send a CEC OSD command based on "setosd" from the test YAML file and transmit this data to DUT | `buffer` = LA, command and data from test YAML | N/A | RAFT/user to set this data through CEC adaptor | -| 10 | Wait for the RAFT/user to signal when the CEC command is sent in step 09 | N/A | N/A | RAFT/user to signal once the CEC command is sent | -| 11 | Validate the data received on DUT with the "setosd" command data from the test YAML file | Test data received should match the data in YAML | Read and validate this data | Should be successful | -| 12 | RAFT/user to validate the acknowledgment received from the DUT while the test waits for the result | Press "Y"/"N" based on acknowledgment | Test to consume this input to decide overall test pass or fail | Should be successful | -| 13 | RAFT/user to frame and send a CEC command to all logical addresses from 0x01 to 0x0E through the CEC adaptor | "getCECVersion" command | N/A | RAFT/user to set this data through the CEC adaptor | -| 14 | RAFT/user should not receive any acknowledgment after sending this data | N/A | N/A | Should be successful | -| 15 | Test to wait for the RAFT/user to signal about its test result for steps 13 and 14 | Press "Y"/"N" based on test result | N/A | RAFT/user to provide this test result | -| 16 | Close HDMI CEC HAL using `HdmiCecClose` API | `handle` = valid handle | `HDMI_CEC_IO_SUCCESS` | Should be successful | - -# Test 2: Transmit and Receive CEC broadcast Commands - -Functionality: -1. `DUT` shall broadcast a standby command to the connected devices and RAFT/user should validate this received command on the CEC Adaptor. -2. `DUT` shall receive a standby command as a broadcast command from the CEC Adaptor. RAFT/user to initiate and command the Test. - -| Title | Details | -|-------------------------------|--------------------------------------------------| -| Function Name | `test_l3_hdmi_cec_sink_broadcast_test` | -| Description | This test shall validate the broadcast CEC Commands between the `DUT`, and the CEC Adaptor connected on a network | -| Test Group | 03 | -| Test Case ID | 003 | -| Priority | High | - -**Pre-Conditions:** -- The platforms are connected as shown in the picture where the CEC Adaptor is considered to be connected and detected correctly. -- libcec is installed on the PC where the CEC Adaptor tool is connected. libcec shall respond to all the basic CEC Commands received from `DUT` - -**Dependencies:** -- Prerequisites should be met before starting this test. - -**User Interaction:** -- If the user chooses to run the test in interactive mode, then the test case has to be selected via the console. -- If the user chooses to run manually, he should use the cec-client commands as shown above. -- RAFT will replace the human to run the test if required, but still, the RAFT should provide an option for the user to change the HMDI ports and start the test again. -- The user should choose either to run manually or choose the RAFT. - -**RAFT Requirements:** -- RAFT shall initiate the commands to send the standby command. -- RAFT shall consider reading and give input to the test wherever required. - -**Sequence Diagram** -```mermaid -sequenceDiagram - participant DUT - participant CEC Adaptor - participant RAFT/user - RAFT/user->>CEC Adaptor: Read and validate LA and PA (device ready) - RAFT/user->>DUT: Start the HAL test - DUT->>DUT: Add Logical Address - DUT->>DUT: Set receive Callback - DUT->>CEC Adaptor: Broadcast "standby" - RAFT/user->>CEC Adaptor: Validate the CEC Command received on the `CEC` adaptor - DUT->>DUT: Wait for the input from RAFT/user to provide the test result - RAFT/user->>DUT: Provide the Test result of standby data received by it. - DUT->>DUT: Wait for the input from RAFT/user to send a broadcast command - RAFT/user->>DUT: RAFT/user to signal the test to move ahead - RAFT->>CEC Adaptor: Broadcast "standby" command - RAFT/user->>DUT: Signal the command to validate the data RAFT/user broadcasted and received by DUT. - CEC Adaptor->> DUT: Broadcast the standby command - DUT-->>DUT: Validate the received command -``` - -#### Test Procedure - -| Variation / Steps | Description | Test Data | Expected Result | Notes | -|-------------------|-------------|-----------|------------------|-------| -| 01 | Open HDMI CEC HAL using `HdmiCecOpen` API | `handle` = valid pointer | `HDMI_CEC_IO_SUCCESS` | Should be successful | -| 02 | Acquire a valid logical address `0x00` using `HdmiCecAddLogicalAddress` | `handle` = valid handle, `logicalAddress` = 0 | `HDMI_CEC_IO_SUCCESS` | Should be successful | -| 03 | Set the receive callback function using `HdmiCecSetRxCallback` | `handle` = valid handle, `cbfunc` = RxCallback, `data` = buffer pointer | `HDMI_CEC_IO_SUCCESS` | Should be successful | -| 04 | Frame a standby command to broadcast from `DUT` to all connected devices using `HdmiCecTx`. Test command and data shall be read from the test YAML file | `handle` = valid handle, `buf` = standby command as read from YAML file, `len` = sizeof(buf), `result` = valid pointer | `HDMI_CEC_IO_SUCCESS` | Should be successful | -| 05 | RAFT/user should receive this data and validate the command received. The test should wait for the RAFT to enter the test result based on the validation | N/A | N/A | RAFT to provide the result | -| 06 | RAFT/user to command CEC adaptor to frame and broadcast the standby CEC command. Test data should be read from the test YAML file | `buffer` = test YAML file data | N/A | RAFT to set this data through CEC adaptor | -| 07 | Wait for the RAFT to signal when the CEC broadcast is sent in step 6 | RAFT/user to provide `y` to move the test | N/A | RAFT to signal once the CEC broadcast is set | -| 08 | Validate the data received from the CEC adaptor on the test RxCallback against the test YAML file | Test data received should be as mentioned in the test YAML file | Read and validate this data | Should be successful | -| 09 | Close HDMI CEC HAL using `HdmiCecClose` API | `handle` = valid handle | `HDMI_CEC_IO_SUCCESS` | Should be successful | - -# Test 3: Stress Test - -Functionality: -1. `DUT` shall respond to a CEC OSD command received from the CEC Adaptor repeatedly for 10 times with different strings and validate. -2. `DUT` shall transmit the CEC OSD command to the CEC Adaptor repeatedly for 10 times. CEC Adaptor to read and validate - -| Title | Details | -|-------------------------------|--------------------------------------------------| -| Function Name | `test_l3_hdmi_cec_tx_rx_osd_cmd_repeatedly` | -| Description | Transmit and Receive CEC OSD Command with buffer data continuously 10 times to prove the robustness of these API. | -| Test Group | 03 | -| Test Case ID | 004 | -| Priority | High | - -**Pre-Conditions:** -- The platforms are connected as shown in the picture where the CEC Adaptor is considered to be connected and detected correctly. -- libcec is installed on the PC where the CEC Adaptor tool is connected. libcec shall respond to all the basic CEC Commands received from `DUT` - -**Dependencies:** -- Prerequisites should be met before starting this test. - -**User Interaction:** -- If the user chooses to run the test in interactive mode, then the test case has to be selected via the console. -- If the user chooses to run manually, he should use the cec-client commands as shown above. -- RAFT will replace the human to run the test if required, but still, the RAFT should provide an option for the user to change the HMDI ports and start the test again. -- The user should choose either to run manually or choose the RAFT. - -**RAFT Requirements:** -- RAFT shall initiate the commands to send the OSD command and validate the acknowledgments -- RAFT shall consider reading and give input to the test wherever required. - -**Sequence Diagram** -```mermaid -sequenceDiagram - participant DUT - participant CEC Adaptor - participant RAFT - RAFT/user->>CEC Adaptor: Read and validate LA and PA - RAFT/user->>DUT: Start the HAL test - DUT->>DUT: Add Logical Address - DUT->>DUT: Set receive Callback - RAFT/user->>CEC Adaptor: Command to send CEC OSD Command for 10 times - CEC Adaptor->>DUT: Send CEC OSD Command for 10 times - RAFT/user->>DUT: To signal the Test to start receiving the OSD data. - RAFT/user->>RAFT/user: To validate the acknowledgment received each time when sent the CEC Frame. - DUT-->>DUT: Validate the received command for 10 times - RAFT/user->>DUT: DUT to wait till the RAFT/user provides the data ack result - RAFT/user->>DUT: RAFT/user to signal the test to move ahead with the ack result - DUT->>CEC Adaptor: Send CEC OSD Command for 10 times - RAFT/user->>RAFT/user: To validate the OSD Command received on the CEC Adaptor - RAFT/user->>DUT: DUT to wait till the RAFT/user provides the data ack result - RAFT/user->>DUT: RAFT/user to signal the test with result - DUT->>DUT: To decide the final result based on the RAFT/user result and its own result. -``` - -#### Test Procedure -| Variation / Steps | Description | Test Data | Expected Result | Notes | -|-------------------|-------------|-----------|------------------|-------| -| 01 | Open HDMI CEC HAL using `HdmiCecOpen` API | `handle` = valid pointer | `HDMI_CEC_IO_SUCCESS` | Should be successful | -| 02 | Acquire a valid logical address `0x00` using `HdmiCecAddLogicalAddress` | `handle` = valid handle, `logicalAddress` = 0 | `HDMI_CEC_IO_SUCCESS` | Should be successful | -| 03 | Set the receive callback function using `HdmiCecSetRxCallback` | `handle` = valid handle, `cbfunc` = valid callback function pointer, `data` = pointer to the valid data buffer | `HDMI_CEC_IO_SUCCESS` | Should be successful | -| 04 | RAFT shall wait for a signal from `DUT`so that it can signal the CEC Adaptor to send a CEC OSD Command continuously 10 times with different data available in test yaml file | N/A | N/A | Should be successful | -| 05 | Validate the data received on the DUT and compare the data with the data from "setosd/data" on the test yaml file | Compare the received data with "setosd/data" on test yaml | NA | Should be successful | -| 06 | RAFT/User to check acknowledgment for each command sent. DUT to wait for RAFT result | RAFT/user to provide `y` or `n` to move the test | NA | Should be successful | -| 07 | `DUT` to send a CEC OSD command continuously 10 times with different data available in test yaml file. Tx command should pass every time it send data| `handle` = valid handle, `buf` = "setosd/data" command as read from YAML file with different data, `len` = sizeof(buf), `result` = valid pointer | NA | Should be successful -| 05 | Validate the data received on the RAFT and compare the data with the data from "setosd/data" on the test yaml file | Compare the received data with "setosd/data" on test yaml | NA | Should be successful | -| 06 | RAFT/User to check received OSD Data for each command sent. DUT to wait for RAFT result | RAFT/user to provide `y` or `n` to move the test | NA | Should be successful | -| 07 | Close HDMI CEC HAL using `HdmiCecClose` API | `handle` = valid handle | `HDMI_CEC_IO_SUCCESS` | Should be successful | - - -# Test 5: Hardware Fault Test - -Functionality: -1. `DUT` shall respond with the correct error code when a Fault (pulling the HDMI line to high) is introduced into the HDMI CEC line. - -| Title | Details | -|-------------------------------|--------------------------------------------------| -| Function Name | `test_l3_hdmi_cec_sink_hw_fault_test` | -| Description | Test for the return of proper error code when a hardware fault is introduced into the CEC line and try to Tx the CEC data. | -| Test Group | 03 | -| Test Case ID | 005 | -| Priority | High | - -**Pre-Conditions:** -Connect an HW fault inducer which can pull the HDMI CEC line to high and to normal through a switch. - -**Dependencies:** -Prerequisites should be met before starting this test. - -**User Interaction:** -If the user chooses to run the test in interactive mode, then the test case has to be selected via the console. - -#### Test Procedure -| Variation / Steps | Description | Test Data | Expected Result | Notes | -|-------------------|-------------|-----------|------------------|-------| -| 01 | Open HDMI CEC HAL using `HdmiCecOpen` API | `handle` = valid pointer | `HDMI_CEC_IO_SUCCESS` | Should be successful | -| 02 | Acquire a valid logical address `0x00` using `HdmiCecAddLogicalAddress` | `handle` = valid handle, `logicalAddress` = 0 | `HDMI_CEC_IO_SUCCESS` | Should be successful | -| 03 | Set the receive callback function using `HdmiCecSetRxCallback` | `handle` = valid handle, `cbfunc` = valid callback function pointer, `data` = pointer to the valid data buffer | `HDMI_CEC_IO_SUCCESS` | Should be successful | -| 04 | Wait for a manual command so that the user is ready to pull the `HDMI` `CEC` high with the help of the fault inducer switch | N/A | N/A | Should be successful | -| 05 | Frame command to Tx Test OSD CEC command with full buffer size from the `DUT` continuously for 10 times | handle= valid handle, `buf` = {0x05, 0x64, 0x00, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x21} |HDMI_CEC_STATUS and HDMI_CEC_IO_SENT_FAILED | Should be successful | -| 06 | Close HDMI CEC HAL using `HdmiCecClose` API | `handle` = valid handle | `HDMI_CEC_IO_SUCCESS` | Should be successful | From 5b1501c2eda70c5c98050aa95f9e0c1acc2e6c81 Mon Sep 17 00:00:00 2001 From: bhanucbp <141142298+bhanucbp@users.noreply.github.com> Date: Tue, 24 Dec 2024 11:03:47 +0000 Subject: [PATCH 33/40] gh #44 L3 test case development Updated the test procedure document --- docs/pages/hdmi-cec-L3_TestProcedure.md | 183 +++++++++++++++++------- 1 file changed, 128 insertions(+), 55 deletions(-) diff --git a/docs/pages/hdmi-cec-L3_TestProcedure.md b/docs/pages/hdmi-cec-L3_TestProcedure.md index 4139937..fac7135 100644 --- a/docs/pages/hdmi-cec-L3_TestProcedure.md +++ b/docs/pages/hdmi-cec-L3_TestProcedure.md @@ -4,11 +4,10 @@ - [Acronyms, Terms and Abbreviations](#acronyms-terms-and-abbreviations) - [Setting Up Test Environment](#setting-up-test-environment) -- [Streams Required](#streams-required) - [Test Cases](#test-cases) - - [dsAudio_L3_Runall_Sink.py](#dsaudio_l3_runall_sinkpy) - - [dsAudio_L3_Runall_Source.py](#dsaudio_l3_runall_sourcepy) - - [dsaudio_test01_enabledisableandverifyaudioportstatus.py](#dsaudio_test01_enabledisableandverifyaudioportstatuspy) + - [hdmiCEC_L3_Runall.py](#hdmicec_l3_runallpy) + - [hdmiCEC_test01_TransmitCECCommands.py](#hdmicec_test01_transmitceccommandspy) + - [hdmiCEC_test02_ReceiveCECCommands.py](#hdmicec_test02_receivececcommandspy) ## Acronyms, Terms and Abbreviations @@ -26,6 +25,64 @@ ## Setting Up Test Environment +The picture below depicts the HDMI CEC L3 Test Functionality Setup. This simple setup has an HDMI CEC Pulse-eight USB adaptor, which acts as a source device and can send the required commands (using libcec tool commands) and respond to the received CEC Commands. + +### Prerequisites + +- Ensure all devices in the test setup support the `HDMI` `CEC` feature for the test duration. +- HDMI drivers must be properly installed and active on the platform before initiating the test. + +```mermaid +graph TB +C[PC] <--> A +A[Pulse-Eight CEC Adaptor ] <--> |HDMI| B[DUT] +``` + +### Pulse-Eight CEC Adaptor tool + +The Pulse-Eight CEC adaptor is used to frame and send commands to the DUT. It utilizes the libCEC library for HDMI CEC activities, and the cec-client tool plays a key role in test automation within RAFT. + +- Adaptor Details: [Pulse Eight](https://www.pulse-eight.com/p/104/usb-hdmi-cec-adapter) + +#### Installation Instructions + +- Linux + +```bash +sudo apt update +sudo apt upgrade +sudo apt install cec-utils +``` + +- Windows + +Download the [libcec Tool](https://www.pulse-eight.com/Download/Get/51) and follow installation steps. + +#### Example `cec-client` Commands + +- List Device Details: + +```bash +cec-client -l +``` + +- Scan for Connected Devices: + +```bash +echo 'scan' | cec-client -s -d 1 +``` + +- Send CEC Commands: + +```bash +echo 'tx 10:8F' | cec-client -s -d 1 + +Command Format: +tx :: +``` + +### Python Environment + To execute `HAL` `L3` Python test cases, need a Python environment. Follow these steps mentioned in [HPK Public Documentation](https://github.com/rdkcentral/rdk-hpk-documentation/blob/main/README.md) ### Update Configuration Files @@ -34,15 +91,49 @@ To execute `HAL` `L3` Python test cases, need a Python environment. Follow these Example Rack configuration File: [example_rack_config.yml](../../../ut/host/tests/configs/example_rack_config.yml) -For more details refer [RAFT](https://github.com/rdkcentral/python_raft/blob/1.0.0/README.md) and [example_rack_config.yml](https://github.com/rdkcentral/python_raft/blob/1.0.0/examples/configs/example_rack_config.yml) +Refer to the following resources for more details: + +- [RAFT](https://github.com/rdkcentral/python_raft/blob/1.0.0/README.md) +- [example_rack_config.yml](https://github.com/rdkcentral/python_raft/blob/1.0.0/examples/configs/example_rack_config.yml) -In this file, update the configuration to define the console sessions for the `DUT` and the outbound settings: +Update the configuration to define the console sessions for the DUT, cec-client details, and outbound settings. + +##### Console Sessions |Console Session|Description| |---------------|-----------| -|default|Downloads the streams required for test cases| +|default|Downloads the bins required for test cases| |ssh_hal_test|Executes the `HAL` binary for the test case| +##### CEC Controller + +`RAFT` supports two types of cec controllers: + +###### Remote controller + +For adaptors connected to a remote server, use the configuration below: + +```yaml + hdmiCECController: + type: remote-cec-client # Use remote cec controller + adaptor: /dev/ttyACM0 # Adaptor port + address: XXX.XXX.XXX.XXX # IP address of the server + username: root # Login username + password: ' ' # Login password +``` + +###### Local controller + +For adaptors connected directly to the server running the tests, use the configuration below: + +```yaml + hdmiCECController: + type: cec-client # Use local cec controller + adaptor: /dev/ttyACM0 # adaptor port +``` + +##### Example Rack Configuration + ```yaml rackConfig: - dut: @@ -66,19 +157,27 @@ rackConfig: download_url: "http://localhost:8000/" # download location for the CPE device httpProxy: # Local Proxy if required workspaceDirectory: './logs/workspace' # Local working directory + hdmiCECController: + type: remote-cec-client + adaptor: /dev/ttyACM0 + address: XXX.XXX.XXX.XXX + username: root + password: ' ' ``` #### Device Configuration File Example Device configuration File: [deviceConfig.yml](../../../ut/host/tests/configs/deviceConfig.yml) -For more details refer [RAFT](https://github.com/rdkcentral/python_raft/blob/1.0.0/README.md) and [example_device_config.yml](https://github.com/rdkcentral/python_raft/blob/1.0.0/examples/configs/example_device_config.yml) +Refer to the following resources for more details: +- [RAFT](https://github.com/rdkcentral/python_raft/blob/1.0.0/README.md) +- [example_device_config.yml](https://github.com/rdkcentral/python_raft/blob/1.0.0/examples/configs/example_device_config.yml) -Update below fileds in the device configuration file: +Update the following fields: -- Set the path for `target_directory` where `HAL` binaries will be copied onto the device. -- Specify the device profile path in `test/profile` -- Ensure the `platform` should match with the `DUT` `platform` in [Rack Configuration](#rack-configuration-file) +- **Target Directory**: Specify the `target_directory` path where HAL binaries will be copied. +- **Device Profile**: Provide the path and profile file for the `test/profile`. +- **Platform**: Ensure the platform matches the `dut` platform in the [Rack Configuration](#rack-configuration-file) ```yaml deviceConfig: @@ -96,7 +195,7 @@ deviceConfig: Example Test Setup configuration File: [hdmiCEC_testConfig.yml](../../../ut/host/tests/classes/hdmiCEC_testConfig.yml) -Execute command to run te HAL binary was provided in this file. +Specify the command to run the HAL binary within this file. ```yaml hdmicec: @@ -120,74 +219,48 @@ python --config /ut/host/tests/configs/example_rack_con ## Test Cases -### dsAudio_L3_Runall_Sink.py +### hdmiCEC_L3_Runall.py -This python file runs all the tests supported by `sink` devices +This python file runs all the tests ```bash -python dsAudio_L3_Runall_Sink.py --config /ut/host/tests/configs/example_rack_config.yml --deviceConfig /ut/host/tests/configs/deviceConfig.yml +python hdmiCEC_L3_Runall.py --config /ut/host/tests/configs/example_rack_config.yml --deviceConfig /ut/host/tests/configs/deviceConfig.yml ``` -### dsAudio_L3_Runall_Source.py - -This python file runs all the tests supported by `source` devices - -```bash -python dsAudio_L3_Runall_Source.py --config /ut/host/tests/configs/example_rack_config.yml --deviceConfig /ut/host/tests/configs/deviceConfig.yml -``` - -### dsAudio_test01_EnableDisableAndVerifyAudioPortStatus.py +### hdmiCEC_test01_TransmitCECCommands.py #### Platform Support - test01 - Source - Sink -#### User Input Required - test01 - -**Yes**: User interaction is necessary to confirm audio playback status (This will be automated later). - #### Acceptance Criteria - test01 -Play **Stream #1** and confirm that audio is heard through the supported ports. - #### Expected Results - test01 -The test enables the specified audio ports, plays the audio stream, and subsequently disables the ports - -Success Criteria - -- User should hear audio through the enabled port during playback -- User should not hear any audio when the port is disabled. - #### Test Steps - test01 - Initiate the Test: - - Select and execute the Python file: **`dsAudio_test01_EnableDisableAndVerifyAudioPortStatus.py`** - - The test will automatically download all required artifacts and streams, copying them to the designated target directory before commencing execution. - -- Audio Playback Verification: + - Select and execute the Python file: **`hdmiCEC_test01_TransmitCECCommands.py`** - The test will play the designated audio stream and prompt the user with the following: +- Test Conclusion: - - Question: "Is audio playing on the enabled audio port? (Y/N)" - - Press **Y** if audio is heard (this will mark the step as PASS). - - Press **N** if no audio is heard (this will mark the step as FAIL). +### hdmiCEC_test02_ReceiveCECCommands.py -- Audio Status Confirmation (Port Disabled): +#### Platform Support - test02 - After confirming audio playback, the test will disable the audio port and prompt the user again: +- Source +- Sink - - Question: "Is audio playing when the port is disabled? (Y/N)" - - Press **N** if no audio is heard (this will mark the step as PASS). - - Press **Y** if audio is heard (this will mark the step as FAIL). +#### Acceptance Criteria - test02 -- Repeat for All Ports: +#### Expected Results - test02 - The test will iterate through all available audio ports, enabling/disabling each one and collecting user feedback accordingly. +#### Test Steps - test02 -- Test Conclusion: +- Initiate the Test: - Upon receiving user responses for all ports, the test will conclude and present a final result: PASS or FAIL based on the user inputs throughout the test execution. + - Select and execute the Python file: **`hdmiCEC_test02_ReceiveCECCommands.py`** +- Test Conclusion: \ No newline at end of file From 052a67515d52f822855bb55730e44305df5aeb5e Mon Sep 17 00:00:00 2001 From: bhanucbp <141142298+bhanucbp@users.noreply.github.com> Date: Tue, 24 Dec 2024 15:15:46 +0000 Subject: [PATCH 34/40] gh #44 L3 test case development Corrected the physical address format --- host/tests/classes/hdmiCEC.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/host/tests/classes/hdmiCEC.py b/host/tests/classes/hdmiCEC.py index 4ee318d..6bbc857 100644 --- a/host/tests/classes/hdmiCEC.py +++ b/host/tests/classes/hdmiCEC.py @@ -188,7 +188,7 @@ def getPhysicalAddress(self): parts = physicalAddress.split(".") high_byte = hex(int(parts[0], 16) << 4 | int(parts[1], 16)) low_byte = hex(int(parts[2], 16) << 4 | int(parts[3], 16)) - addressBytes = [high_byte, low_byte] + addressBytes = [f"0x{int(high_byte, 16):02X}",f"0x{int(low_byte, 16):02X}"] return addressBytes From 5a2e5544f2067191f5cad4fc39c8e61a1b69a172 Mon Sep 17 00:00:00 2001 From: bhanucbp <141142298+bhanucbp@users.noreply.github.com> Date: Fri, 27 Dec 2024 16:35:29 +0000 Subject: [PATCH 35/40] gh #44 L3 test case development Updated test procedure document --- docs/pages/hdmi-cec-L3_TestProcedure.md | 114 ++++++++++++++++++++++-- 1 file changed, 107 insertions(+), 7 deletions(-) diff --git a/docs/pages/hdmi-cec-L3_TestProcedure.md b/docs/pages/hdmi-cec-L3_TestProcedure.md index fac7135..60cbeae 100644 --- a/docs/pages/hdmi-cec-L3_TestProcedure.md +++ b/docs/pages/hdmi-cec-L3_TestProcedure.md @@ -34,8 +34,9 @@ The picture below depicts the HDMI CEC L3 Test Functionality Setup. This simple ```mermaid graph TB -C[PC] <--> A +C[PC] <--> |USB| A A[Pulse-Eight CEC Adaptor ] <--> |HDMI| B[DUT] +A[Pulse-Eight CEC Adaptor ] <--> |HDMI| D[Other Test Device] ``` ### Pulse-Eight CEC Adaptor tool @@ -170,6 +171,7 @@ rackConfig: Example Device configuration File: [deviceConfig.yml](../../../ut/host/tests/configs/deviceConfig.yml) Refer to the following resources for more details: + - [RAFT](https://github.com/rdkcentral/python_raft/blob/1.0.0/README.md) - [example_device_config.yml](https://github.com/rdkcentral/python_raft/blob/1.0.0/examples/configs/example_device_config.yml) @@ -234,17 +236,65 @@ python hdmiCEC_L3_Runall.py --config /ut/host/tests/configs/example_rack_ - Source - Sink +#### User Input Required - test01 + +No - (This is a automated case) + #### Acceptance Criteria - test01 +- The test verifies that the device under test (DUT) can successfully transmit HDMI-CEC commands to connected devices as defined in the test profile. +- Transmission should be correctly initiated and logged by the HDMI-CEC controller. + #### Expected Results - test01 +The test is considered successful if: + +- All HDMI-CEC commands listed in the `YAML` profile are transmitted without errors. +- The test script validates that the transmission is initiated and logged correctly by the HDMI-CEC controller. + #### Test Steps - test01 -- Initiate the Test: +Preparation: + +- Ensure the `DUT` is connected to the HDMI-CEC controller devices via HDMI cables. +- Verify that configuration files for the test environment are correctly set up. + +Execution: + +Run the Python script with the following command: + +```bash +python hdmiCEC_test01_TransmitCECCommands.py --config /ut/host/tests/configs/example_rack_config.yml --deviceConfig /ut/host/tests/configs/deviceConfig.yml +``` + +Functionality: + +- The script initializes the HDMI-CEC controller session. +- It transmits HDMI-CEC commands from the DUT to the connected devices. + +Validation: + +- The script checks if the HDMI-CEC controller logs confirm the transmission of each command. +- Transmission status is logged with details such as source, destination, opcode, and payload. + +#### Test Logs and Artifacts - test01 + +Summary Logs: + +- A comprehensive log file is generated, detailing the execution status of each command. +- Log file path: <"PATH">/ut/logs/rack<#>/slot<#>/<"DATE-TIME">/test_summary.log. + +- Transmission Status: + - Logs include information about the success or failure of each transmitted command. + +#### Test Conclusion - test01 - - Select and execute the Python file: **`hdmiCEC_test01_TransmitCECCommands.py`** +The test script will display a final PASS/FAIL result based on the following conditions: -- Test Conclusion: +- PASS: All CEC commands are successfully transmitted as listed in the YAML profile, and transmission logs confirm initiation by the HDMI-CEC controller. +- FAIL: Any transmission error or failure to initiate commands. + +Summary logs are saved for further review and debugging. ### hdmiCEC_test02_ReceiveCECCommands.py @@ -253,14 +303,64 @@ python hdmiCEC_L3_Runall.py --config /ut/host/tests/configs/example_rack_ - Source - Sink +#### User Input Required - test02 + +No - (This is a automated case) + #### Acceptance Criteria - test02 +- The test verifies whether the device under test (DUT) can reliably receive HDMI-CEC commands. +- The received callback data must match the expected values, including: + - Source logical address + - Destination logical address + - Opcode + - Payload + #### Expected Results - test02 +The test is considered successful if: + +- All transmitted HDMI-CEC commands are successfully received by the DUT. +- The callback data accurately reflects the transmitted command parameters (source, destination, opcode, and payload). + #### Test Steps - test02 -- Initiate the Test: +Preparation: + +- Ensure the DUT is powered on and connected to the HDMI-CEC controller. +- Verify the configuration files for the test environment are properly set up. + +Execution: + +Run the Python script with the following command: + +```bash +python hdmiCEC_test02_ReceiveCECCommands.py --config /ut/host/tests/configs/example_rack_config.yml --deviceConfig /ut/host/tests/configs/deviceConfig.yml +``` + +Functionality: + +- The script initializes the HDMI-CEC controller. +- It sends HDMI-CEC commands to the DUT's logical address, including directed and broadcast messages. +- The DUT processes these commands, and the script reads the callback data. + +Verification: + +- The script validates the callback data received by the DUT against the transmitted parameters (source, destination, opcode, payload). + +#### Test Logs and Artifacts - test02 + +Summary Logs: + +- The script generates a detailed log file summarizing the test execution. +- Log file path: <"PATH">/ut/logs/rack<#>/slot<#>/<"DATE-TIME">/test_summary.log +- Logs include information on received commands, validation results, and any discrepancies. + +#### Test Conclusion - test02 + +The test script will display a final PASS/FAIL result based on the following conditions: - - Select and execute the Python file: **`hdmiCEC_test02_ReceiveCECCommands.py`** +- PASS: All received HDMI-CEC commands and callback data match the expected values. +- FAIL: Any mismatch in the callback data or failure to receive commands. -- Test Conclusion: \ No newline at end of file +Summary logs are saved for review and troubleshooting From f70ba59dd14f442a674a100b1ae88c1f8ce0aabf Mon Sep 17 00:00:00 2001 From: bhanucbp <141142298+bhanucbp@users.noreply.github.com> Date: Fri, 27 Dec 2024 17:49:04 +0000 Subject: [PATCH 36/40] gh #44 L3 test case development Corrected merge conflicts --- src/main.c | 35 +++++++++++++++++++++++++++-------- src/test_register.c | 2 +- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/src/main.c b/src/main.c index f582079..45c4d5a 100644 --- a/src/main.c +++ b/src/main.c @@ -68,8 +68,7 @@ extern int register_hdmicec_hal_l1_tests( void ); extern int register_hdmicec_hal_source_l2_tests( void ); extern int register_hdmicec_hal_sink_l2_tests( void ); -extern int register_hdmicec_hal_sink_l3_tests( void ); - +extern int register_hdmicec_hal_l3_tests( void ); #ifdef VCOMPONENT extern int register_vcomponent_tests ( char* profile ); @@ -116,16 +115,36 @@ int main(int argc, char** argv) /* Register tests as required, then call the UT-main to support switches and triggering */ UT_init( argc, argv ); - register_hdmicec_hal_common_l1_tests(); + status = ut_kvp_getStringField(ut_kvp_profile_getInstance(), "hdmicec/type", szReturnedString, UT_KVP_MAX_ELEMENT_SIZE); + if (status == UT_KVP_STATUS_SUCCESS ) { + UT_LOG_DEBUG("Device Type: %s", szReturnedString); + } + else { + UT_LOG_ERROR("Failed to get the platform Device Type"); + return -1; + } + + registerReturn = register_hdmicec_hal_l1_tests(); + if ( registerReturn == -1 ) + { + UT_LOG_ERROR("\n register_hdmicec_hal_l1_tests() returned failure"); + return -1; + } #ifdef VCOMPONENT register_vcomponent_tests(pProfilePath); test_l3_hdmi_cec_driver_register (pValidationProfilePath); #endif - register_hdmicec_hal_source_l1_tests (); - register_hdmicec_hal_source_l2_tests (); - register_hdmicec_hal_sink_l1_tests (); - register_hdmicec_hal_sink_l2_tests (); - register_hdmicec_hal_sink_l3_tests (); + + if(strncmp(szReturnedString,"source",UT_KVP_MAX_ELEMENT_SIZE) == 0) { + register_hdmicec_hal_source_l2_tests (); + } + + if(strncmp(szReturnedString,"sink",UT_KVP_MAX_ELEMENT_SIZE) == 0) { + register_hdmicec_hal_sink_l2_tests (); + } + + register_hdmicec_hal_l3_tests (); + UT_run_tests(); #ifdef VCOMPONENT diff --git a/src/test_register.c b/src/test_register.c index 9765f57..3da40ea 100644 --- a/src/test_register.c +++ b/src/test_register.c @@ -96,7 +96,7 @@ int register_hdmicec_hal_sink_l2_tests( void ) return registerFailed; } -int register_hdmicec_hal_sink_l3_tests( void ) +int register_hdmicec_hal_l3_tests( void ) { int registerFailed=0; From 190c126646f07d0167ea878d576ad94b2964f742 Mon Sep 17 00:00:00 2001 From: bhanucbp <141142298+bhanucbp@users.noreply.github.com> Date: Mon, 30 Dec 2024 10:19:14 +0000 Subject: [PATCH 37/40] gh #44 L3 test case development Added virtual device code --- src/main.c | 2 +- src/test_vcomponent.c | 8 +- src/test_vd_hdmi_cec_driver.c | 409 ++++++++++++++++++++++++++++++++++ 3 files changed, 414 insertions(+), 5 deletions(-) create mode 100644 src/test_vd_hdmi_cec_driver.c diff --git a/src/main.c b/src/main.c index 45c4d5a..e1c359b 100644 --- a/src/main.c +++ b/src/main.c @@ -132,7 +132,7 @@ int main(int argc, char** argv) } #ifdef VCOMPONENT register_vcomponent_tests(pProfilePath); - test_l3_hdmi_cec_driver_register (pValidationProfilePath); + test_vd_hdmi_cec_driver_register (pValidationProfilePath); #endif if(strncmp(szReturnedString,"source",UT_KVP_MAX_ELEMENT_SIZE) == 0) { diff --git a/src/test_vcomponent.c b/src/test_vcomponent.c index bdd1c25..6f60be3 100644 --- a/src/test_vcomponent.c +++ b/src/test_vcomponent.c @@ -56,7 +56,7 @@ /** * @file test_vcomponent.c - * + * */ @@ -85,7 +85,7 @@ struct vcomponent_info gVCInfo = {NULL, NULL}; void start_virtual_component (void) { vcHdmiCec_Status_t status; - + if(gVCInfo.pProfilePath == NULL) { assert(gVCInfo.pProfilePath != NULL); @@ -121,7 +121,7 @@ void stop_virtual_component(void) } gVCInfo.handle = NULL; UT_LOG("Virtual Component stopped\n"); - + } static UT_test_suite_t * pSuite = NULL; @@ -133,7 +133,7 @@ static UT_test_suite_t * pSuite = NULL; */ int register_vcomponent_tests ( char* profile) { - if(profile == NULL) + if(profile == NULL) { return -1; } diff --git a/src/test_vd_hdmi_cec_driver.c b/src/test_vd_hdmi_cec_driver.c new file mode 100644 index 0000000..ccfaa66 --- /dev/null +++ b/src/test_vd_hdmi_cec_driver.c @@ -0,0 +1,409 @@ +/** +* If not stated otherwise in this file or this component's LICENSE +* file the following copyright and licenses apply: +* +* Copyright 2023 RDK Management +* +* Licensed under the Apache License, Version 2.0 (the License); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an AS IS BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +/** +* @file TODO: test_vd_hdmi_cec_driver.c +* @page module_name TODO: Required field, name of the main module +* @subpage sub_page_name TODO: Add a function group if relevant +* +* ## Module's Role +* TODO: Explain the module's role in the system in general +* This is to ensure that the API meets the operational requirements of the module across all vendors. +* +* **Pre-Conditions:** TODO: Add pre-conditions if any@n +* **Dependencies:** TODO: Add dependencies if any@n +* +* Ref to API Definition specification documentation :[hdmi-cec_halSpec.md](../../docs/pages/hdmi-cec_halSpec.md) +*/ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include "hdmi_cec_driver.h" + +#define DEFAULT_LOGICAL_ADDRESS_PANEL 0 + +#define MAX_WAIT_TIME_SECS 30 +#define MAX_DATA_SIZE 64 + +#define CEC_IMAGE_VIEW_ON 0x04 +#define CEC_TEXT_VIEW_ON 0x0D +#define CEC_STANDBY 0x36 +#define CEC_SET_OSD_NAME 0x47 +#define CEC_ACTIVE_SOURCE 0x82 +#define CEC_REPORT_PHYSICAL_ADDRESS 0x84 +#define CEC_REQUEST_ACTIVE_SOURCE 0x85 +#define CEC_INACTIVE_SOURCE 0x9D +#define CEC_COMMAND_UNKNOWN 0x00 + +#define CMD_IMAGE_VIEW_ON "ImageViewOn" +#define CMD_TEXT_VIEW_ON "TextViewOn" +#define CMD_STANDBY "StandBy" +#define CMD_ACTIVE_SOURCE "ActiveSource" +#define CMD_REQUEST_ACTIVE_SOURCE "RequestActiveSource" +#define CMD_INACTIVE_SOURCE "InactiveSource" +#define CMD_SET_OSD_NAME "SetOsdName" +#define CMD_REPORT_PHYSICAL_ADDRESS "ReportPhysicalAddress" + +#define VP_PREFIX "hdmicec/" +#define CMD_DATA_OSD_NAME "/osd_name" +#define VP_RESULT_INITIATOR "/result/initiator" +#define VP_RESULT_DESTINATION "/result/destination" +#define VP_RESULT_OPCODE "/result/opcode" +#define VP_RESULT_PARAMETER_SIZE "/result/parameters/size" +#define VP_RESULT_PARAMETER_DATA "/result/parameters/data/" + +#define COUNT(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x]))))) + +typedef struct +{ + char* str; + int val; +} strVal_t; + +const static strVal_t gOpCode [] = { + { CMD_IMAGE_VIEW_ON, CEC_IMAGE_VIEW_ON }, + { CMD_TEXT_VIEW_ON, CEC_TEXT_VIEW_ON }, + { CMD_SET_OSD_NAME, CEC_SET_OSD_NAME }, + { CMD_STANDBY , CEC_STANDBY }, + { CMD_ACTIVE_SOURCE, CEC_ACTIVE_SOURCE }, + { CMD_REQUEST_ACTIVE_SOURCE, CEC_REQUEST_ACTIVE_SOURCE }, + { CMD_INACTIVE_SOURCE, CEC_INACTIVE_SOURCE }, + { CMD_REPORT_PHYSICAL_ADDRESS, CEC_REPORT_PHYSICAL_ADDRESS} +}; + + +static UT_test_suite_t * pSuite = NULL; +static int gTestGroup = 1; +static int gTestID = 1; + +static uint8_t gExpectedCecCommand = CEC_COMMAND_UNKNOWN; //Set teach test before waiting for trigger +static sem_t gSemCallbackReceived; +static uint8_t gCommandValidated = CEC_COMMAND_UNKNOWN; //Set by receive callback after test validation is successful + +static ut_kvp_instance_t *gValidationProfileInstance = NULL; + +int GetOpCode(const strVal_t *map, int length, char* str) +{ + int result = -1; + + if(map == NULL || length <= 0 || str == NULL) + { + return result; + } + + for (int i = 0; i < length; ++i) + { + if (!strcmp(str, map[i].str)) + { + result = map[i].val; + break; + } + } + return result; +} + +char* GetOpCodeString(const strVal_t *map, int length, int val) +{ + char* result = NULL; + + if(map == NULL || length <= 0) + { + return NULL; + } + + for (int i = 0; i < length; ++i) + { + if (val == (int)map[i].val) + { + result = map[i].str; + break; + } + } + return result; +} + + +/** + * @brief hdmicec receive message callback + * + * @param handle Hdmi device handle + * @param callbackData callback data passed + * @param buf receive message buffer passed + * @param len receive message buffer length + */ +void ReceiveCallback(int handle, void *callbackData, unsigned char *buf, int len) +{ + uint8_t src, dest, opcode; + uint8_t expected_src, expected_dest, expected_opcode; + uint8_t physical_address[4]; + char* expected_command = NULL; + ut_kvp_instance_t *vp_instance; + char szReturnedString[UT_KVP_MAX_ELEMENT_SIZE]; + char field_name[UT_KVP_MAX_ELEMENT_SIZE]; + uint8_t parameter_data[UT_KVP_MAX_ELEMENT_SIZE]; + uint8_t parameter_size = 0; + int length = 0, field_len = 0; + + UT_LOG ("\nBuffer generated: %x length: %d\n",buf, len); + + UT_ASSERT_MSG( handle != 0, "Error: Invalid handle."); + UT_ASSERT_MSG( callbackData != NULL, "Error: Null callback data."); + UT_ASSERT_MSG( len > 0, "Error: Invalid length."); + + vp_instance = (ut_kvp_instance_t *)callbackData; + + UT_LOG("\nCall back data generated is \n"); + for (int index=0; index < len; index++) + { + UT_LOG("buf at index : %d is %x", index, buf[index]); + } + + src = (buf[0] & 0xF0) >> 4; + dest = buf[0] & 0x0F; + opcode = buf[1]; + + expected_command = GetOpCodeString(gOpCode, COUNT(gOpCode), gExpectedCecCommand); + strcpy(field_name, VP_PREFIX); + strcpy(field_name + strlen(VP_PREFIX), expected_command); + length = strlen(field_name); + + strcpy(field_name + length, VP_RESULT_INITIATOR); + expected_src = ut_kvp_getUInt8Field (vp_instance, field_name); + + strcpy(field_name + length, VP_RESULT_DESTINATION); + expected_dest = ut_kvp_getUInt8Field (vp_instance, field_name); + + strcpy(field_name + length, VP_RESULT_OPCODE); + expected_opcode = ut_kvp_getUInt8Field (vp_instance, field_name); + + strcpy(field_name + length, VP_RESULT_PARAMETER_SIZE); + parameter_size = ut_kvp_getUInt8Field (vp_instance, field_name); + field_len = strlen(field_name); + strcpy(field_name + length, VP_RESULT_PARAMETER_DATA); + + for (int i = 0; i < parameter_size; ++i) + { + int num_len = snprintf( NULL, 0, "%d", i ); + snprintf( field_name + field_len + 1 , num_len + 1, "%d", i ); + parameter_data[i] = ut_kvp_getUInt8Field (vp_instance, field_name); + UT_LOG("Expected Parameter data at [%d]: 0x%02x",i,parameter_data[i]); + } + + UT_LOG("\nExpected Command[%s] Src[%d] Dest[%d] \n", (GetOpCodeString(gOpCode, COUNT(gOpCode), gExpectedCecCommand)),expected_src, expected_dest); + UT_LOG("\nCommand[%s] triggered Src[%d] Dest[%d] \n", (GetOpCodeString(gOpCode, COUNT(gOpCode), opcode)),src, dest); + + switch (opcode) + { + case CEC_ACTIVE_SOURCE: + case CEC_INACTIVE_SOURCE: + { + UT_LOG("\nPhysicalAddress[%d.%d.%d.%d]\n",(buf[2] >> 4) & 0x0F, buf[2] & 0x0F, (buf[3] >> 4) & 0xF0, buf[3] & 0x0F); + } + break; + case CEC_SET_OSD_NAME: + { + char str[len - 1]; + memcpy(str, &buf[2], len-2); + str[len-2] = '\0'; + UT_LOG("\nosd_name[%s]\n", str); + } + break; + } + //Lets see if this the opcode that was expected. If it is not test will timeout + if(gExpectedCecCommand == opcode) + { + //Lets validate the addresses and opcode + if(src == expected_src && dest == expected_dest && opcode == expected_opcode) + { + UT_LOG("\nParameter size[%d] received size[%d]\n", parameter_size, len - 2); + //Expected parameter size should be equal to length of cec buffer received minus 2 (Address, opcode bytes) + gCommandValidated = gExpectedCecCommand; + if(parameter_size > 0) + { + if((parameter_size != (len - 2)) || (memcmp(parameter_data, &buf[2], parameter_size) != 0)) + { + gCommandValidated = CEC_COMMAND_UNKNOWN; + } + } + } + //Even if the validation fails, signal the test as the opcode is same. + sem_post(&gSemCallbackReceived); + } +} + +/** + * @brief callback to get the async send message status + * + * @param handle Hdmi device handle + * @param callbackData callback data passed + * @param result async send status + */ +void TransmitCallback(int handle, void *callbackData, int result) +{ + if((handle!=0) && (callbackData !=NULL)) { + //UT_ASSERT_TRUE_FATAL( (unsigned long long)callbackData== (unsigned long long)0xDEADBEEF); + UT_LOG ("\ncallbackData returned: %x result: %d\n",callbackData, result); + } +} + + +int TimedWaitForCallback(uint32_t timeOutSeconds) +{ + int s, result = -1; + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += timeOutSeconds; + while ((s = sem_timedwait(&gSemCallbackReceived, &ts)) == -1 && errno == EINTR) + { + continue; /* Restart if interrupted by handler */ + } + + /* Check what happened */ + if (s == -1) + { + if (errno == ETIMEDOUT) + { + result = 1; + } + } + else + { + result = 0; + } + return result; +} + +static void validate_receive_callback_data(uint8_t expected_cmd, const char *cmd_str, const char *func, uint32_t timeOutSecs) +{ + int result; + int handle = 0; + gTestID = 1; + + UT_LOG("\n In %s [%02d%03d]\n", func, gTestGroup, gTestID); + result = HdmiCecOpen( &handle ); + if (HDMI_CEC_IO_SUCCESS != result) { UT_FAIL_FATAL("open failed"); } + + result = HdmiCecSetRxCallback(handle, ReceiveCallback, (void*)gValidationProfileInstance); + if (HDMI_CEC_IO_SUCCESS != result) { UT_FAIL("HdmiCecSetRxCallback failed"); } + + result = HdmiCecSetTxCallback( handle, TransmitCallback, (void*)0xDEADBEEF ); + if (HDMI_CEC_IO_SUCCESS != result) { UT_FAIL("HdmiCecSetTxCallback failed"); } + + result = HdmiCecAddLogicalAddress( handle, DEFAULT_LOGICAL_ADDRESS_PANEL ); + if (HDMI_CEC_IO_SUCCESS != result) { UT_FAIL("HdmiCecAddLogicalAddress failed"); } + + gExpectedCecCommand = expected_cmd; + gCommandValidated = CEC_COMMAND_UNKNOWN; + + UT_LOG ("\nTrigger %s\n", cmd_str); + result = TimedWaitForCallback(timeOutSecs); + if(result != 0) + { + UT_FAIL("Failed to receive expected command in callback"); + } + if(gCommandValidated != gExpectedCecCommand) + { + UT_FAIL("Test Validation failed"); + } + result = HdmiCecClose( handle ); + if (HDMI_CEC_IO_SUCCESS != result) { UT_FAIL_FATAL("close failed"); } +} + + +/** +* Positive cases that receive callback data +*/ +void test_vd_sink_image_view_on (void) +{ + validate_receive_callback_data(CEC_IMAGE_VIEW_ON, CMD_IMAGE_VIEW_ON, __FUNCTION__, MAX_WAIT_TIME_SECS); +} + +void test_vd_sink_text_view_on (void) +{ + validate_receive_callback_data(CEC_TEXT_VIEW_ON, CMD_TEXT_VIEW_ON, __FUNCTION__, MAX_WAIT_TIME_SECS); +} + +void test_vd_sink_active_source (void) +{ + validate_receive_callback_data(CEC_ACTIVE_SOURCE, CMD_ACTIVE_SOURCE, __FUNCTION__, MAX_WAIT_TIME_SECS); +} + +void test_vd_sink_inactive_source (void) +{ + validate_receive_callback_data(CEC_INACTIVE_SOURCE, CMD_INACTIVE_SOURCE, __FUNCTION__, MAX_WAIT_TIME_SECS); +} + +void test_vd_sink_set_osd_name (void) +{ + validate_receive_callback_data(CEC_SET_OSD_NAME, CMD_SET_OSD_NAME, __FUNCTION__, MAX_WAIT_TIME_SECS); +} + +void test_vd_sink_add_device (void) +{ + validate_receive_callback_data(CEC_REPORT_PHYSICAL_ADDRESS, CMD_REPORT_PHYSICAL_ADDRESS, __FUNCTION__, MAX_WAIT_TIME_SECS); +} +/** + * @brief Register the main test(s) for this module + * + * @return int - 0 on success, otherwise failure + */ +int test_vd_hdmi_cec_driver_register ( char* validation_profile ) +{ + ut_kvp_status_t status; + if(validation_profile == NULL) + { + UT_FAIL("validation_profile NULL"); + return -1; + } + + gValidationProfileInstance = ut_kvp_createInstance(); + assert(gValidationProfileInstance != NULL); + status = ut_kvp_open(gValidationProfileInstance, validation_profile); + if(status != UT_KVP_STATUS_SUCCESS) + { + UT_LOG_ERROR("ut_kvp_open: status: %d", status); + assert(status == UT_KVP_STATUS_SUCCESS); + return -1; + } + + /* add a suite to the registry */ + pSuite = UT_add_suite( "[L3 hdmi_cec_driver]", NULL, NULL ); + if ( NULL == pSuite ) + { + return -1; + } + + sem_init(&gSemCallbackReceived, 0, 0); + UT_add_test( pSuite, "test_vd_sink_image_view_on" ,test_vd_sink_image_view_on ); + UT_add_test( pSuite, "test_vd_sink_text_view_on" ,test_vd_sink_text_view_on ); + UT_add_test( pSuite, "test_vd_sink_active_source" ,test_vd_sink_active_source); + UT_add_test( pSuite, "test_vd_sink_inactive_source" ,test_vd_sink_inactive_source ); + UT_add_test( pSuite, "test_vd_sink_set_osd_name" ,test_vd_sink_set_osd_name ); + UT_add_test( pSuite, "test_vd_sink_add_device" ,test_vd_sink_add_device ); + + return 0; +} From c1b133407782c8e091350e2ae165ff364b9921a6 Mon Sep 17 00:00:00 2001 From: bhanucbp <141142298+bhanucbp@users.noreply.github.com> Date: Mon, 30 Dec 2024 11:08:02 +0000 Subject: [PATCH 38/40] gh #44 L3 test case development Addressed review comments --- host/tests/classes/hdmiCEC.py | 8 ++++++-- host/tests/configs/example_rack_config.yml | 4 ++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/host/tests/classes/hdmiCEC.py b/host/tests/classes/hdmiCEC.py index 6bbc857..8775374 100644 --- a/host/tests/classes/hdmiCEC.py +++ b/host/tests/classes/hdmiCEC.py @@ -234,8 +234,12 @@ def cecTransmitCmd(self, destLogicalAddress:str, cecCommand:str, cecData:list=No txStatus = self.searchPattern(result, pattern) status = False - if txStatus == "HDMI_CEC_IO_SENT_AND_ACKD" or txStatus == "HDMI_CEC_IO_SENT_BUT_NOT_ACKD": - status = True + if destLogicalAddress == 'f': + if txStatus == "HDMI_CEC_IO_SENT_BUT_NOT_ACKD": + status = True + else: + if txStatus == "HDMI_CEC_IO_SENT_AND_ACKD": + status = True return status diff --git a/host/tests/configs/example_rack_config.yml b/host/tests/configs/example_rack_config.yml index 78c83ed..e3b3c07 100644 --- a/host/tests/configs/example_rack_config.yml +++ b/host/tests/configs/example_rack_config.yml @@ -57,8 +57,8 @@ rackConfig: # [ type: "telnet": port: 23 username: "test" password: "test" ] - dut: ip: "127.0.0.1" - description: "element" - platform: "element" + description: "tv" + platform: "tv" consoles: - default: type: "ssh" From 8120dfce15faaff7ee736b4ad378e20f98220f14 Mon Sep 17 00:00:00 2001 From: bhanucbp <141142298+bhanucbp@users.noreply.github.com> Date: Mon, 30 Dec 2024 18:10:44 +0000 Subject: [PATCH 39/40] gh #44 L3 test case development Addressed review comments --- README.md | 9 +++++-- docs/pages/hdmi-cec-L3_TestProcedure.md | 2 +- host/tests/classes/hdmiCEC.py | 4 +-- host/tests/configs/deviceConfig.yml | 2 +- .../hdmiCEC_L3_Tests/hdmiCECTestCommands.yml | 27 ++++++++++++------- src/main.c | 2 +- 6 files changed, 29 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 2f709b7..3857a90 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,9 @@ - `HDMI` - High Definition Multimedia Interface - `CEC` - Consumer Electronics Control - `L1` - Functional Tests -- `L2` - Functional Tests +- `L2` - Module functional Testing +- `L3` - Module testing with External Stimulus is required to validate and control device +- `API` - Application Programming Interface ## Description @@ -23,11 +25,13 @@ This repository contains the Unit Test Suites(L1 & L2) for HDMI CEC `HAL`. |SNo|Document Name|Document Description|Document Link| |---|-------------|--------------------|-------------| -|1|`HAL` Specification Document|This document provides specific information on the APIs for which tests are written in this module|[hdmi-cec_halSpec.md](https://github.com/rdkcentral/rdk-halif-hdmi_cec/blob/main/docs/pages/hdmi-cec_halSpec.md)| +|1|`HAL` Specification Document|This document provides specific information on the APIs for which tests are written in this module|[hdmi-cec_halSpec.md](https://github.com/rdkcentral/rdk-halif-hdmi_cec/blob/1.3.9/docs/pages/hdmi-cec_halSpec.md)| |2|High Level Test Spec for sink device|High Level Test Specification Documentation for the `HDMI` `CEC` Sink device|[hdmi-cec-sink_High-Level_TestSpec.md](docs/pages/hdmi-cec-sink_High-Level_TestSpec.md )| |3|`L2` Low Level Test Spec for sink device|`L2` Low Level Test Specification and Procedure Documentation for the `HDMI` `CEC` Sink device|[hdmi-cec-sink_L2_Low-Level_TestSpec.md](docs/pages/hdmi-cec-sink_L2_Low-Level_TestSpec.md)| |4|High Level Test Spec for Source device|High Level Test Specification Documentation for the `HDMI` `CEC` Source device|[hdmi-cec-source_High-Level_TestSpec.md](docs/pages/hdmi-cec-source_High-Level_TestSpec.md)| |5|`L2` Low Level Test Spec for Source device|`L2` Low Level Test Specification and Procedure Documentation for the `HDMI` `CEC` Source device|[hdmi-cec-source_L2_Low-Level_TestSpec.md](docs/pages/hdmi-cec-source_L2_Low-Level_TestSpec.md)| +|6|`L3` Low Level Test Specification|`L3` Low Level Test Specification for the `HDMI` `CEC`|[hdmi-cec-L3-Low-Level_TestSpec.md](docs/pages/hdmi-cec-L3-Low-Level_TestSpec.md)| +|7|`L3` Test procedure document|`L3` Test procedure document for the `HDMI` `CEC`|[hdmi-cec-L3_TestProcedure.md](docs/pages/hdmi-cec-L3_TestProcedure.md)| ## Notes @@ -47,3 +51,4 @@ Alternatively, use the run.sh script with the profile file: - Profiles file available in [profile yaml file](./profiles/) - vcomponent is an alpha release. +- Install Python Environment and Activation Scripts please check the[HPK Documentation](https://github.com/rdkcentral/rdk-hpk-documentation/blob/main/README.md) diff --git a/docs/pages/hdmi-cec-L3_TestProcedure.md b/docs/pages/hdmi-cec-L3_TestProcedure.md index 60cbeae..4ff93f9 100644 --- a/docs/pages/hdmi-cec-L3_TestProcedure.md +++ b/docs/pages/hdmi-cec-L3_TestProcedure.md @@ -1,4 +1,4 @@ -# dsAudio HAL L3 Python Test Procedure +# HDMI CEC HAL L3 Python Test Procedure ## Table of Contents diff --git a/host/tests/classes/hdmiCEC.py b/host/tests/classes/hdmiCEC.py index 8775374..3415777 100644 --- a/host/tests/classes/hdmiCEC.py +++ b/host/tests/classes/hdmiCEC.py @@ -100,7 +100,7 @@ def searchPattern(self, haystack, pattern): def initialise(self): """ - Initializes the HDMI CEC module for sink. + Initializes the HDMI CEC module. Args: None. @@ -300,7 +300,7 @@ def parse_data_field(data_field): def getDeviceType(self): """ - Retrieves the type of the audio device. + Retrieves the type of dut. Args: None. diff --git a/host/tests/configs/deviceConfig.yml b/host/tests/configs/deviceConfig.yml index 91046a1..2813b82 100644 --- a/host/tests/configs/deviceConfig.yml +++ b/host/tests/configs/deviceConfig.yml @@ -24,7 +24,7 @@ deviceConfig: cpe1: - platform: "element" + platform: "tv" model: "uk" soc_vendor: "amlogic" target_directory: "/tmp/" # Target Directory on device diff --git a/host/tests/hdmiCEC_L3_Tests/hdmiCECTestCommands.yml b/host/tests/hdmiCEC_L3_Tests/hdmiCECTestCommands.yml index ba480e4..aad88fc 100644 --- a/host/tests/hdmiCEC_L3_Tests/hdmiCECTestCommands.yml +++ b/host/tests/hdmiCEC_L3_Tests/hdmiCECTestCommands.yml @@ -24,13 +24,14 @@ hdmicec: logicalAddress: '0' test01_TransmitCECCommands: - command: "0x82" # Active Soruce - payload: ["0x00", "0x00"] + payload: ["0x00", "0x00"] # Physical address of the device type: "Broadcast" - - command: "0x90" # "Report power status + - command: "0x90" # Report power status payload: ["0x00"] type: "Direct" response: null - - command: "0x47" # Give OSD Name + - command: "0x47" # Set OSD Name + # Paylod contain ascii values of osd name "RDK VTS Device" payload: ['0x52', '0x44', '0x4b', '0x20', '0x56', '0x54', '0x53', '0x20', '0x44', '0x65', '0x76', '0x69', '0x63', '0x65'] type: "Direct" response: null @@ -44,17 +45,18 @@ hdmicec: type: "Broadcast" response: type: "Broadcast" - command: "0x82" + command: "0x82" # Active Soruce update_payload: true - payload: ["0x00", "0x00"] + payload: ["0x00", "0x00"] # Physical address of the device description: "Active Soruce" - command: "0x91" # Get Menu Language payload: type: "Direct" response: type: "Broadcast" - command: "0x32" + command: "0x32" # Set menu language update_payload: false + # payload contains the menu lanaguage 'eng' in ascii payload: ["0x65", "0x6E", "0x67"] description: "Set Menu Language" - command: "0x8C" # Give Vendor ID @@ -62,8 +64,9 @@ hdmicec: type: "Direct" response: type: "Broadcast" - command: "0x87" + command: "0x87" # Report vendor ID update_payload: false + # Payload contains the example vendor id 0x0000001 payload: ["0x00", "0x00","0x01"] description: "Device Vendor Id" - command: "0x8F" # Give power status @@ -71,8 +74,10 @@ hdmicec: type: "Direct" response: type: "Direct" - command: "0x90" + command: "0x90" # Report power status update_payload: false + # Payload contains the power status of the device + # 0x00 - on, 0x01 - Standby, 0x02 - in transition Standby to On, 0x03 - in transition On to Standby payload: ["0x00"] description: "Report power status" - command: "0x9F" # Get CEC version @@ -80,8 +85,9 @@ hdmicec: type: "Direct" response: type: "Direct" - command: "0x9E" + command: "0x9E" # Report CEC Version update_payload: false + # CEC Version 0x05 - "version 1.4" payload: ["0x05"] description: "Device request for CEC version" - command: "0x46" # Give OSD Name @@ -89,7 +95,8 @@ hdmicec: type: "Direct" response: type: "Direct" - command: "0x47" + command: "0x47" # Set OSD Name update_payload: false + # Paylod contain ascii values of osd name "RDK VTS Device" payload: ['0x52', '0x44', '0x4b', '0x20', '0x56', '0x54', '0x53', '0x20', '0x44', '0x65', '0x76', '0x69', '0x63', '0x65'] description: "Device request OSD name" diff --git a/src/main.c b/src/main.c index e1c359b..b2104ac 100644 --- a/src/main.c +++ b/src/main.c @@ -72,7 +72,7 @@ extern int register_hdmicec_hal_l3_tests( void ); #ifdef VCOMPONENT extern int register_vcomponent_tests ( char* profile ); -extern int test_l3_hdmi_cec_driver_register ( char* pValidationProfilePath ); +extern int test_vd_hdmi_cec_driver_register ( char* pValidationProfilePath ); #endif int main(int argc, char** argv) From fe8db615d176caabea29fa17ab775baed9d4116a Mon Sep 17 00:00:00 2001 From: bhanucbp <141142298+bhanucbp@users.noreply.github.com> Date: Tue, 31 Dec 2024 14:29:42 +0000 Subject: [PATCH 40/40] gh #44 L3 test case development - Addressed review comments - Moved cec responses to different yml file under assets folder - Updated the exectute command to take the cec response file --- Makefile | 4 + assets/cec_responses/cec_responses.yml | 131 ++++++++++++++++++++++++ host/tests/classes/hdmiCEC.py | 4 +- profiles/sink/sink_hdmiCEC.yml | 135 ------------------------- profiles/source/source_hdmiCEC.yml | 135 ------------------------- src/test_l3_hdmi_cec_driver.c | 14 ++- 6 files changed, 149 insertions(+), 274 deletions(-) create mode 100644 assets/cec_responses/cec_responses.yml diff --git a/Makefile b/Makefile index b961f7b..1e837f1 100644 --- a/Makefile +++ b/Makefile @@ -33,6 +33,8 @@ TOP_DIR := $(ROOT_DIR) SRC_DIRS = $(ROOT_DIR)/src INC_DIRS := $(ROOT_DIR)/../include +ASSETS_DIR := $(ROOT_DIR)/assets +CEC_RESP_DIR := $(ASSETS_DIR)/cec_responses HAL_LIB := RCECHal SKELTON_SRCS := $(ROOT_DIR)/skeletons/src/hdmi_cec_driver.c VCOMPONENT_SRCS := $(wildcard $(ROOT_DIR)/vcomponent/src/*.c) @@ -84,6 +86,8 @@ build: $(SETUP_SKELETON_LIBS) make -C ./ut-core TARGET=${TARGET} rm -rf $(BIN_DIR)/lib$(HAL_LIB).so rm -rf $(ROOT_DIR)/libs/lib$(HAL_LIB).so + cp -r $(CEC_RESP_DIR)/* $(BIN_DIR)/ + #Build against the real library leads to the SOC library dependency also.SOC lib dependency cannot be specified in the ut Makefile, since it is supposed to be common across may platforms. So in order to over come this situation, creating a template skelton library with empty templates so that the template library wont have any other Soc dependency. And in the real platform mount copy bind with the actual library will work fine. skeleton: echo $(CC) diff --git a/assets/cec_responses/cec_responses.yml b/assets/cec_responses/cec_responses.yml new file mode 100644 index 0000000..fb691f9 --- /dev/null +++ b/assets/cec_responses/cec_responses.yml @@ -0,0 +1,131 @@ +hdmicec: + cec_responses: + - command: "0x04" # Image View on + payload: + type: "Direct" + response: null + - command: "0x0D" # Text View On + payload: + type: "Direct" + response: null + - command: "0x32" # Set Menu Language + payload: + type: "Broadcast" + response: null + - command: "0x36" # Standby + payload: + type: "Both" + response: null + - command: "0x46" # Give OSD Name + payload: + type: "Direct" + response: + type: "Direct" + command: "0x47" # Set OSD Name + update_payload: false + # Paylod contain ascii values of osd name "RDK VTS Device" + payload: ["0x52", "0x44", "0x4b", "0x20", "0x56", "0x54", "0x53", "0x20", "0x44", "0x65", "0x76", "0x69", "0x63", "0x65"] + description: "Device request OSD name" + - command: "0x47" # report OSD Name + payload: + type: "Direct" + response: null + - command: "0x64" # Set OSD String + payload: + type: "Direct" + response: null + - command: "0x82" # Active source + payload: + type: "Broadcast" + response: null + - command: "0x83" # Give Physical Address + payload: + type: "Direct" + response: + type: "Broadcast" + command: "0x84" # Report Physical address + update_payload: true + # Payload with phycical address + payload: ["0x00", "0x00", "0x00"] + description: "Report Physical Address" + - command: "0x84" # Report Physical address + payload: + type: "Broadcast" + response: null + - command: "0x85" # Request Active source + payload: + type: "Broadcast" + response: + type: "Broadcast" + command: "0x82" # Report Active source + update_payload: true + # Payload with physical address + payload: ["0x00", "0x00"] + description: "Active Soruce" + - command: "0x87" # Device Vendor ID + payload: + type: "Broadcast" + response: null + - command: "0x8C" # Give Vendor ID + payload: + type: "Direct" + response: + type: "Broadcast" + command: "0x87" # Report Vendor ID + update_payload: false + # Payload with example vendor ID 0x000001 + payload: ["0x00", "0x00", "0x01"] + description: "Device Vendor Id" + - command: "0x8F" # Give power status + payload: + type: "Direct" + response: + type: "Direct" + command: "0x90" # Report power Status + update_payload: false + payload: ["0x00"] # Power Status on + description: "Report power status" + - command: "0x90" # Power Status + payload: + type: "Direct" + response: null + - command: "0x91" # Get Menu Language + payload: + type: "Direct" + response: + type: "Broadcast" + command: "0x32" # Report Menu language + update_payload: false + # 'eng' language in ascii value + payload: ["0x65", "0x6E", "0x67"] + description: "Set Menu Language" + - command: "0x9E" # CEC Version + response: null + - command: "0x9F" # Get CEC version + payload: + type: "Direct" + response: + type: "Direct" + command: "0x9E" # Report CEC Version + update_payload: false + # CEC Version 0x05 - "version 1.4" + payload: ["0x05"] + description: "Device request for CEC version" + - command: "0xA7" # Request Latency + payload: + type: "Broadcast" + response: + type: "Broadcast" + command: "0xA8" # Report Latency + update_payload: true + # 100msec video delay ((number of milliseconds/2) + 1) + # 200msec audio delay ((number of milliseconds/2) + 1) + # (Bits 1-0) : Audio Ouput Compensated (0 - N/A, 1 - TV audio output is delay compensated, 2 - TV audio output is NOT delay compensated, 3 - TV audio output is Par delay compensated) + # (Bit 2) : 0 - normal latency, 1 - low latency + # Bit(7-3) : Reserved + payload: ["0x00", "0x00", "0x65", "0x00", "0x33"] + description: "Report Physical Address" + - command: "0xA8" # Report Physical Address + payload: + type: "Broadcast" + response: null diff --git a/host/tests/classes/hdmiCEC.py b/host/tests/classes/hdmiCEC.py index 3415777..e185e2f 100644 --- a/host/tests/classes/hdmiCEC.py +++ b/host/tests/classes/hdmiCEC.py @@ -57,12 +57,14 @@ def __init__(self, moduleConfigProfileFile:str, session=None, targetWorkspace:st self.moduleName = "hdmicec" self.testConfigFile = os.path.join(dir_path, "hdmiCEC_testConfig.yml") self.testSuite = "L3 HDMICEC Functions" + cecResponseFile = "cec_responses.yml" # Prepare the profile file on the target workspace self.moduleConfigProfile = ConfigRead( moduleConfigProfileFile , self.moduleName) profileOnTarget = os.path.join(targetWorkspace, os.path.basename(moduleConfigProfileFile)) + cecResponseFileOnTarget = os.path.join(targetWorkspace, cecResponseFile) self.testConfig = ConfigRead(self.testConfigFile, self.moduleName) - self.testConfig.test.execute = os.path.join(targetWorkspace, self.testConfig.test.execute) + f" -p {profileOnTarget}" + self.testConfig.test.execute = os.path.join(targetWorkspace, self.testConfig.test.execute) + f" -p {profileOnTarget}" + f" -p {cecResponseFileOnTarget}" self.utMenu = UTSuiteNavigatorClass(self.testConfig, None, session) self.testSession = session self.utils = utBaseUtils() diff --git a/profiles/sink/sink_hdmiCEC.yml b/profiles/sink/sink_hdmiCEC.yml index b4a6d9a..323bf59 100644 --- a/profiles/sink/sink_hdmiCEC.yml +++ b/profiles/sink/sink_hdmiCEC.yml @@ -4,138 +4,3 @@ hdmicec: features: extendedEnumsSupported: false - - cec_responses: - - command: "0x00" # Feature Abort - payload: - type: "Direct" - response: - type: "Direct" - command: "0x9E" - update_payload: true - payload: ["0x00", "0x00"] - description: "Feature Abort Reason" - - command: "0x04" # Image View on - payload: - type: "Direct" - response: null - - command: "0x0D" # Text View On - payload: - type: "Direct" - response: null - - command: "0x32" # Set Menu Language - payload: - type: "Broadcast" - response: null - - command: "0x36" # Standby - payload: - type: "Both" - response: null - - command: "0x46" # Give OSD Name - payload: - type: "Direct" - response: - type: "Direct" - command: "0x47" - update_payload: false - payload: ["0x52", "0x44", "0x4b", "0x20", "0x56", "0x54", "0x53", "0x20", "0x44", "0x65", "0x76", "0x69", "0x63", "0x65"] - description: "Device request OSD name" - - command: "0x47" # report OSD Name - payload: - type: "Direct" - response: null - - command: "0x64" # Set OSD String - payload: - type: "Direct" - response: null - - command: "0x82" # Active source - payload: - type: "Broadcast" - response: null - - command: "0x83" # Give Physical Address - payload: - type: "Direct" - response: - type: "Broadcast" - command: "0x84" - update_payload: true - payload: ["0x00", "0x00", "0x00"] - description: "Report Physical Address" - - command: "0x84" # Report Physical address - payload: - type: "Broadcast" - response: null - - command: "0x85" # Request Active source - payload: - type: "Broadcast" - response: - type: "Broadcast" - command: "0x82" - update_payload: true - payload: ["0x00", "0x00"] - description: "Active Soruce" - - command: "0x87" # Device Vendor ID - payload: - type: "Broadcast" - response: null - - command: "0x8C" # Give Vendor ID - payload: - type: "Direct" - response: - type: "Broadcast" - command: "0x87" - update_payload: false - payload: ["0x00", "0x00", "0x01"] - description: "Device Vendor Id" - - command: "0x8F" # Give power status - payload: - type: "Direct" - response: - type: "Direct" - command: "0x90" - update_payload: false - payload: ["0x00"] - description: "Report power status" - - command: "0x90" # Power Status - payload: - type: "Direct" - response: null - - command: "0x91" # Get Menu Language - payload: - type: "Direct" - response: - type: "Broadcast" - command: "0x32" - update_payload: false - payload: ["0x65", "0x6E", "0x67"] - description: "Set Menu Language" - - command: "0x9E" # CEC Version - response: null - - command: "0x9F" # Get CEC version - payload: - type: "Direct" - response: - type: "Direct" - command: "0x9E" - update_payload: false - payload: ["0x05"] - description: "Device request for CEC version" - - command: "0xA7" # Request Latency - payload: - type: "Broadcast" - response: - type: "Broadcast" - command: "0xA8" - update_payload: true - # 100msec video delay ((number of milliseconds/2) + 1) - # 200msec audio delay ((number of milliseconds/2) + 1) - # (Bits 1-0) : Audio Ouput Compensated (0 - N/A, 1 - TV audio output is delay compensated, 2 - TV audio output is NOT delay compensated, 3 - TV audio output is Par delay compensated) - # (Bit 2) : 0 - normal latency, 1 - low latency - # Bit(7-3) : Reserved - payload: ["0x00", "0x00", "0x65", "0x00", "0x33"] - description: "Report Physical Address" - - command: "0xA8" # Report Physical Address - payload: - type: "Broadcast" - response: null - diff --git a/profiles/source/source_hdmiCEC.yml b/profiles/source/source_hdmiCEC.yml index 67b4790..7b8fff6 100644 --- a/profiles/source/source_hdmiCEC.yml +++ b/profiles/source/source_hdmiCEC.yml @@ -4,138 +4,3 @@ hdmicec: features: extendedEnumsSupported: false - - cec_responses: - - command: "0x00" # Feature Abort - payload: - type: "Direct" - response: - type: "Direct" - command: "0x9E" - update_payload: true - payload: ["0x00", "0x00"] - description: "Feature Abort Reason" - - command: "0x04" # Image View on - payload: - type: "Direct" - response: null - - command: "0x0D" # Text View On - payload: - type: "Direct" - response: null - - command: "0x32" # Set Menu Language - payload: - type: "Broadcast" - response: null - - command: "0x36" # Standby - payload: - type: "Both" - response: null - - command: "0x46" # Give OSD Name - payload: - type: "Direct" - response: - type: "Direct" - command: "0x47" - update_payload: false - payload: ["0x52", "0x44", "0x4b", "0x20", "0x56", "0x54", "0x53", "0x20", "0x44", "0x65", "0x76", "0x69", "0x63", "0x65"] - description: "Device request OSD name" - - command: "0x47" # report OSD Name - payload: - type: "Direct" - response: null - - command: "0x64" # Set OSD String - payload: - type: "Direct" - response: null - - command: "0x82" # Active source - payload: - type: "Broadcast" - response: null - - command: "0x83" # Give Physical Address - payload: - type: "Direct" - response: - type: "Broadcast" - command: "0x84" - update_payload: true - payload: ["0x00", "0x00", "0x00"] - description: "Report Physical Address" - - command: "0x84" # Report Physical address - payload: - type: "Broadcast" - response: null - - command: "0x85" # Request Active source - payload: - type: "Broadcast" - response: - type: "Broadcast" - command: "0x82" - update_payload: true - payload: ["0x00", "0x00"] - description: "Active Soruce" - - command: "0x87" # Device Vendor ID - payload: - type: "Broadcast" - response: null - - command: "0x8C" # Give Vendor ID - payload: - type: "Direct" - response: - type: "Broadcast" - command: "0x87" - update_payload: false - payload: ["0x00", "0x00", "0x01"] - description: "Device Vendor Id" - - command: "0x8F" # Give power status - payload: - type: "Direct" - response: - type: "Direct" - command: "0x90" - update_payload: false - payload: ["0x00"] - description: "Report power status" - - command: "0x90" # Power Status - payload: - type: "Direct" - response: null - - command: "0x91" # Get Menu Language - payload: - type: "Direct" - response: - type: "Broadcast" - command: "0x32" - update_payload: false - payload: ["0x65", "0x6E", "0x67"] - description: "Set Menu Language" - - command: "0x9E" # CEC Version - response: null - - command: "0x9F" # Get CEC version - payload: - type: "Direct" - response: - type: "Direct" - command: "0x9E" - update_payload: false - payload: ["0x05"] - description: "Device request for CEC version" - - command: "0xA7" # Request Latency - payload: - type: "Broadcast" - response: - type: "Broadcast" - command: "0xA8" - update_payload: true - # 100msec video delay ((number of milliseconds/2) + 1) - # 200msec audio delay ((number of milliseconds/2) + 1) - # (Bits 1-0) : Audio Ouput Compensated (0 - N/A, 1 - TV audio output is delay compensated, 2 - TV audio output is NOT delay compensated, 3 - TV audio output is Par delay compensated) - # (Bit 2) : 0 - normal latency, 1 - low latency - # Bit(7-3) : Reserved - payload: ["0x00", "0x00", "0x65", "0x00", "0x33"] - description: "Report Physical Address" - - command: "0xA8" # Report Physical Address - payload: - type: "Broadcast" - response: null - diff --git a/src/test_l3_hdmi_cec_driver.c b/src/test_l3_hdmi_cec_driver.c index 79b75b2..d24ff11 100644 --- a/src/test_l3_hdmi_cec_driver.c +++ b/src/test_l3_hdmi_cec_driver.c @@ -32,11 +32,11 @@ */ /** - * @defgroup HDMI_CEC_HALTESTS_L3 HDMI CEC HAL Tests L2 File + * @defgroup HDMI_CEC_HALTESTS_L3 HDMI CEC HAL Tests L3 File * @{ * @parblock * - * ### L2 Test Cases for HDMI CEC HAL : + * ### L3 Test Cases for HDMI CEC HAL : * * * ## Module's Role @@ -298,6 +298,14 @@ static bool getCommandResponse(uint8_t opcode, cecResponse_t *pResponse) return true; } } + + /* If the received opcode is not found in the supported list send feature abort response */ + pResponse->cecCommand = 0x00; //Feature abort + pResponse->payloadSize = 2; + pResponse->payload[0] = opcode; + pResponse->payload[1] = 0x01; //Unsupported opcode + strncpy(pResponse->type, "Direct", UT_KVP_MAX_ELEMENT_SIZE); + return false; } @@ -803,7 +811,7 @@ int32_t test_register_hdmicec_hal_l3_tests(void) return 0; } -/** @} */ // End of HDMI CEC HAL Tests L1 File +/** @} */ // End of HDMI CEC HAL Tests L3 File /** @} */ // End of HDMI CEC HAL Tests /** @} */ // End of HDMI CEC Module /** @} */ // End of HPK