Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d0ec32ef authored by Varun Balaraj's avatar Varun Balaraj Committed by Garmond Leung
Browse files

hal : Test to receive events from kernel

 - Test app to wait for events of Hdmi-in connection state, audio present state,
   sample rate changes.
 - Added code to send edid data by using sysfs exposed by kernel.

Change-Id: Ia68df476397e8aed2aba299337377fe948ff9434
parent 2fab6895
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
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
+2 −1
Original line number Diff line number Diff line
@@ -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
+9 −0
Original line number Diff line number Diff line

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
+183 −0
Original line number Diff line number Diff line
/*
 * 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
};
+237 −0
Original line number Diff line number Diff line
/*
 * 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;
}