diff options
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | configure.ac | 3 | ||||
-rw-r--r-- | hdmi_in_test/Makefile.am | 9 | ||||
-rw-r--r-- | hdmi_in_test/src/edid.h | 183 | ||||
-rw-r--r-- | hdmi_in_test/src/hdmi_in_event_test.c | 237 |
5 files changed, 432 insertions, 2 deletions
diff --git a/Makefile.am b/Makefile.am index ebde009d..bd082117 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,7 +1,7 @@ SUBDIRS = hal post_proc if QAHW_SUPPORT -SUBDIRS += qahw_api qahw_api/test +SUBDIRS += qahw_api qahw_api/test hdmi_in_test endif ACLOCAL_AMFLAGS = -I m4 diff --git a/configure.ac b/configure.ac index ffa5f8c9..da395273 100644 --- a/configure.ac +++ b/configure.ac @@ -120,7 +120,8 @@ AC_CONFIG_FILES([ \ hal/Makefile \ post_proc/Makefile \ qahw_api/Makefile \ - qahw_api/test/Makefile + qahw_api/test/Makefile \ + hdmi_in_test/Makefile ]) AC_OUTPUT diff --git a/hdmi_in_test/Makefile.am b/hdmi_in_test/Makefile.am new file mode 100644 index 00000000..34e4ff5f --- /dev/null +++ b/hdmi_in_test/Makefile.am @@ -0,0 +1,9 @@ + +ACLOCAL_AMFLAGS = -I m4 +bin_PROGRAMS = hdmi_in_test +pkgconfigdir = $(libdir)/pkgconfig + +hdmi_in_test_SOURCES = src/hdmi_in_event_test.c +hdmi_in_test_CFLAGS = $(CFLAGS) -Wno-sign-compare -Werror +hdmi_in_test_LDADD = -llog -lpthread + diff --git a/hdmi_in_test/src/edid.h b/hdmi_in_test/src/edid.h new file mode 100644 index 00000000..8dc6b84e --- /dev/null +++ b/hdmi_in_test/src/edid.h @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +uint8_t default_edid[] = { +/* Block 0 (EDID Base Block) */ +0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, +/* Vendor Identification */ +0x45, 0x23, 0xDD, 0xDD, 0x01, 0x01, 0x01, 0x01, 0x01, 0x16, +/* EDID Structure Version and Revision */ +0x01, 0x03, +/* Display Parameters */ +0x80, 0x90, 0x51, 0x78, 0x0A, +/* Color characteristics */ +0x0D, 0xC9, 0xA0, 0x57, 0x47, 0x98, 0x27, 0x12, 0x48, 0x4C, +/* Established Timings */ +0x21, 0x08, 0x00, +/* Standard Timings */ +0x81, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +/* Detailed Descriptors */ +0x02, 0x3A, 0x80, 0x18, 0x71, 0x38, 0x2D, 0x40, +0x58, 0x2C, +0x45, 0x00, 0xA0, 0x2A, 0x53, 0x00, 0x00, 0x1E, +/* Detailed Descriptors */ +0x01, 0x1D, 0x00, 0x72, 0x51, 0xD0, 0x1E, 0x20, +0x6E, 0x28, 0x55, 0x00, 0xA0, 0x2A, 0x53, 0x00, +0x00, 0x1E, +/* Monitor Descriptor */ +0x00, 0x00, 0x00, 0xFD, 0x00, 0x3A, 0x3E, 0x0F, +0x46, 0x0F, 0x00, 0x0A, 0x20, 0x20, 0x20, 0x20, +0x20, 0x20, +/* Monitor Descriptor */ +0x00, 0x00, 0x00, 0xFC, 0x00, 0x54, 0x56, 0x0A, +0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +0x20, 0x20, +/* Extension Flag */ +0x01, +/*checksum */ +0x9A, + +/* Block 1 (Extension Block) */ +/* Extension Header */ +0x02, 0x03, 0x37, +/* Display supports */ +0xF0, +/* Video Data Bock */ +0x4A, 0x10, 0x04, 0x05, 0x03, 0x02, 0x07, 0x06, +0x20, 0x01, 0x3C, +/* Audio Data Block */ +0x29, +0x09, 0x07, 0x07, /* LPCM, max 2 ch, 48k, 44.1k, 32k */ +0x15, 0x07, 0x50, /* AC-3, max 6 ch, 48k, 44.1k, 32k, max bitrate 640*/ +0x3D, 0x07, 0x50, /* DTS, max 6ch, 48,44.1,32k, max br 640*/ +/* Speaker Allocation Data Block */ +0x83, 0x01, 0x00, 0x00, +/* HDMI VSDB */ +/* no deep color, Max_TMDS_Clock = 165 MHz*/ +0x76, 0x03, 0x0C, 0x00, 0x30, 0x00, 0x80, 0x21, +/* hdmi_video_present=1, 3d_present=1, 3d_multi_present=0, +hdmi_vic_len=0, hdmi_3d_len=0xC*/ +0x2F, 0x88, 0x0C, 0x20, 0x90, 0x08, 0x10, 0x18, +0x10, 0x28, 0x10, 0x78, 0x10, 0x06, 0x26, +/* VCDB */ +0xE2, 0x00, 0x7B, +/* Detailed Descriptor */ +0x01, 0x1D, 0x80, 0x18, 0x71, 0x1C, 0x16, 0x20, +0x58, 0x2C, 0x25, 0x00, 0xA0, 0x2A, 0x53, 0x00, +0x00, 0x9E, +/* Detailed Descriptor */ +0x8C, 0x0A, 0xD0, 0x8A, 0x20, 0xE0, 0x2D, 0x10, +0x10, 0x3E, 0x96, 0x00, 0xA0, 0x2A, 0x53, 0x00, +0x00, 0x18, +/* Detailed Descriptor */ +0x8C, 0x0A, 0xD0, 0x8A, 0x20, 0xE0, 0x2D, 0x10, +0x10, 0x3E, 0x96, 0x00, 0x38, 0x2A, 0x43, 0x00, +0x00, 0x18, +/* Detailed Descriptor */ +0x8C, 0x0A, 0xA0, 0x14, 0x51, 0xF0, 0x16, 0x00, +0x26, 0x7C, 0x43, 0x00, 0x38, 0x2A, 0x43, 0x00, +0x00, 0x98, +/* checksum */ +0x38 +}; + +uint8_t edid_with_addtnl_snd_formats[] = { +/* Block 0 (EDID Base Block) */ +0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, +/* Vendor Identification */ +0x1E, 0x6D, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x17, +/* EDID Structure Version and Revision */ +0x01, 0x03, +/* Display Parameters */ +0x80, 0xa0, 0x5A, 0x78, 0x0A, +/* Color characteristics */ +0xEE, 0x91, 0xa3, 0x54, 0x4c, 0x99, 0x26, 0x0f, 0x50, 0x54, +/* Established Timings */ +0xa1, 0x08, 0x00, + +0x31, 0x40, 0x45, 0x40, 0x61, 0x40, 0x71, 0x40, +0x81, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + +0x02, 0x3a, 0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, +0x58, 0x2c, +0x45, 0x00, 0xa0, 0x5a, 0x00, 0x00, 0x00, 0x1e, + +0x66, 0x21, 0x50, 0xb0, 0x51, 0x00, 0x1b, 0x30, +0x40, 0x70, 0x36, 0x00, 0xa0, 0x5a, 0x00, 0x00, +0x00, 0x1e, + +0x00, 0x00, 0x00, 0xfd, 0x00, 0x3a, 0x3e, 0x1e, +0x53, 0x10, 0x00, 0x0a, 0x20, 0x20, 0x20, 0x20, +0x20, 0x20, + +0x00, 0x00, 0x00, 0xfc, 0x00, 0x4c, 0x47, 0x20, +0x54, 0x56, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, +0x20, 0x20, + +/* Extension Flag */ +0x01, +/*checksum */ +0x42, + +/* Block 1 (Extension Block) */ +/* Extension Header */ +0x02, 0x03, 0x37, +/* Display supports */ +0xF0, +/* Video Data Bock */ +0x4E, 0x10, 0x9F, 0x04, 0x13, 0x05, 0x14, 0x03, 0x02, 0x12, 0x20, 0x21, +0x22, 0x15, 0x01, + +/* Audio Data Block */ +0x2F, +0x3D, 0x06, 0xC0, +0x15, 0x07, 0x50, +0x0F, 0x57, 0x07, +0x57, 0x06, 0x00, +0x5F, 0x7E, 0x01, + +/* Speaker Allocation Data Block */ +0x67, 0x03, 0x0C, 0x00, + +0x30, 0x00, 0x80, 0x1E, 0xE3, 0x05, 0x00, 0x00, 0x01, + +0x1D, 0x80, 0x18, 0x71, 0x1C, 0x16, 0x20, 0x58, 0x2C, 0x25, 0x00, +0xA0, 0x5A, 0x00, 0x00, 0x00, +0x9E, 0x01, 0x1D, 0x00, 0x80, 0x51, 0xD0, 0x1A, 0x20, 0x6E, 0x88, +0x55, 0x00, 0xA0, 0x5A, 0x00, +0x00, 0x00, 0x1A, 0x02, 0x3A, 0x80, 0x18, 0x71, 0x38, 0x2D, 0x40, +0x58, 0x2C, 0x45, 0x00, 0xA0, +0x5A, 0x00, 0x00, 0x00, 0x1E, 0x66, 0x21, 0x50, 0xB0, 0x51, 0x00, +0x1B, 0x30, 0x40, 0x70, 0x36, +0x00, 0xA0, 0x5A, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, +/* checksum */ +0xFB +}; diff --git a/hdmi_in_test/src/hdmi_in_event_test.c b/hdmi_in_test/src/hdmi_in_event_test.c new file mode 100644 index 00000000..4dd75680 --- /dev/null +++ b/hdmi_in_test/src/hdmi_in_event_test.c @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Test app to capture event updates from kernel */ +/*#define LOG_NDEBUG 0*/ +#include <fcntl.h> +#include <linux/netlink.h> +#include <pthread.h> +#include <poll.h> +#include <stdio.h> +#include <string.h> +#include <sys/prctl.h> +#include <sys/stat.h> +#include <sys/socket.h> +#include <sys/types.h> +#include <utils/Log.h> +#include "edid.h" + +static int sock_event_fd = -1; + +int hdmi_conn_state = 0; +int hdmi_audio_state = 0; +int hdmi_audio_format = 0; +int hdmi_sample_rate = 0; +int hdmi_num_channels = 0; + +const char hdmi_in_audio_sys_path[] = + "/sys/devices/virtual/switch/hpd_state/state"; +const char hdmi_in_audio_dev_path[] = "/devices/virtual/switch/hpd_state"; +const char hdmi_in_audio_state_sys_path[] = + "/sys/devices/virtual/switch/audio_state/state"; +const char hdmi_in_audio_state_dev_path[] = + "/devices/virtual/switch/audio_state"; +const char hdmi_in_audio_format_sys_path[] = + "/sys/devices/virtual/switch/audio_format/state"; +const char hdmi_in_audio_format_dev_path[] = + "/devices/virtual/switch/audio_format"; +const char hdmi_in_audio_sample_rate_sys_path[] = + "/sys/devices/virtual/switch/sample_rate/state"; +const char hdmi_in_audio_sample_rate_dev_path[] = + "/devices/virtual/switch/sample_rate"; +const char hdmi_in_audio_channel_sys_path[] = + "/sys/devices/virtual/switch/channels/state"; +const char hdmi_in_audio_channel_dev_path[] = + "/devices/virtual/switch/channels"; + +pthread_t poll_event_th; +pthread_attr_t poll_event_attr; + +void send_edid_data() +{ + int fd = -1; + int ret; + char path[] = +"/sys/devices/soc/ca0c000.qcom,cci/ca0c000.qcom,cci:toshiba,tc358840@0/tc358840_audio_data"; + + fd = open(path, O_WRONLY, 0); + if (fd < 0) { + ALOGE("Unable open fd for file %s", path); + return; + } + + ret = write(fd, default_edid, sizeof(default_edid)); + + close(fd); +} + +void read_data_from_fd(const char* path, int *value) +{ + int fd = -1; + char buf[16]; + int ret; + + fd = open(path, O_RDONLY, 0); + if (fd < 0) { + ALOGE("Unable open fd for file %s", path); + return; + } + + ret = read(fd, buf, 15); + if (ret < 0) { + ALOGE("File %s Data is empty", path); + close(fd); + return; + } + + buf[ret] = '\0'; + *value = atoi(buf); + close(fd); +} + +void get_hdmi_status() +{ + read_data_from_fd(hdmi_in_audio_sys_path, &hdmi_conn_state); + read_data_from_fd(hdmi_in_audio_state_sys_path, &hdmi_audio_state); + read_data_from_fd(hdmi_in_audio_format_sys_path, &hdmi_audio_format); + read_data_from_fd(hdmi_in_audio_sample_rate_sys_path, &hdmi_sample_rate); + read_data_from_fd(hdmi_in_audio_channel_sys_path, &hdmi_num_channels); + + ALOGI("HDMI In state: %d, audio_state: %d, audio_format: %d,", + hdmi_conn_state, hdmi_audio_state, hdmi_audio_format); + ALOGI(" hdmi_sample_rate: %d, hdmi_num_channels: %d\n", + hdmi_sample_rate, hdmi_num_channels); +} + +int poll_event_init() +{ + struct sockaddr_nl sock_addr; + int sz = (64*1024); + int soc; + + memset(&sock_addr, 0, sizeof(sock_addr)); + sock_addr.nl_family = AF_NETLINK; + sock_addr.nl_pid = getpid(); + sock_addr.nl_groups = 0xffffffff; + + soc = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT); + if (soc < 0) { + return 0; + } + + setsockopt(soc, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz)); + + if (bind(soc, (struct sockaddr*) &sock_addr, sizeof(sock_addr)) < 0) { + close(soc); + return 0; + } + + sock_event_fd = soc; + + return (soc > 0); +} + +void listen_uevent(void *ptr) +{ + char buffer[64*1024]; + struct pollfd fds; + int i, count; + int j; + char *dev_path = NULL; + char *switch_state = NULL; + char *switch_name = NULL; + + while(1) { + + fds.fd = sock_event_fd; + fds.events = POLLIN; + fds.revents = 0; + i = poll(&fds, 1, -1); + + if (i > 0 && (fds.revents & POLLIN)) { + count = recv(sock_event_fd, buffer, (64*1024), 0 ); + if (count > 0) { + buffer[count] = '\0'; + j = 0; + while(j < count) { + if (strncmp(&buffer[j], "DEVPATH=", 8) == 0) { + dev_path = &buffer[j+8]; + j += 8; + continue; + } else if (strncmp(&buffer[j], "SWITCH_NAME=", 12) == 0) { + switch_name = &buffer[j+12]; + j += 12; + continue; + } else if (strncmp(&buffer[j], "SWITCH_STATE=", 13) == 0) { + switch_state = &buffer[j+13]; + j += 13; + continue; + } + j++; + } + ALOGI("devpath = %s, switch_name = %s \n", + dev_path, switch_name); + + if (strncmp(hdmi_in_audio_dev_path, dev_path, + strlen(hdmi_in_audio_dev_path)) == 0) { + get_hdmi_status(); + } else if (strncmp(hdmi_in_audio_sample_rate_dev_path, dev_path, + strlen(hdmi_in_audio_sample_rate_dev_path)) == 0) { + get_hdmi_status(); + } else if (strncmp(hdmi_in_audio_state_dev_path, dev_path, + strlen(hdmi_in_audio_state_dev_path)) == 0) { + get_hdmi_status(); + } else if (strncmp(hdmi_in_audio_channel_dev_path, dev_path, + strlen(hdmi_in_audio_channel_dev_path)) == 0) { + get_hdmi_status(); + } + } + } else { + ALOGD("NO Data\n"); + } + } +} + +int main() +{ + ALOGI("hdmi-in event test\n"); + + pthread_attr_init(&poll_event_attr); + pthread_attr_setdetachstate(&poll_event_attr, PTHREAD_CREATE_JOINABLE); + poll_event_init(); + pthread_create(&poll_event_th, &poll_event_attr, + (void *) listen_uevent, NULL); + get_hdmi_status(); + + /* Enable once kernel side write is proper + send_edid_data();*/ + pthread_join(poll_event_th, NULL); + ALOGI("hdmi-in event test exit\n"); + return 0; +} |