diff options
author | Shibata Makoto <shibata@mac.tec.toyota.co.jp> | 2013-04-26 20:39:06 +0900 |
---|---|---|
committer | Shibata Makoto <shibata@mac.tec.toyota.co.jp> | 2013-04-26 20:39:41 +0900 |
commit | 0f80d0012c6f40ebb02622e058911e9d581bc4f2 (patch) | |
tree | b184a9305d983642adfdc4855a49d714541033b9 | |
download | ico-uxf-device-input-controller-0f80d0012c6f40ebb02622e058911e9d581bc4f2.tar.gz ico-uxf-device-input-controller-0f80d0012c6f40ebb02622e058911e9d581bc4f2.tar.bz2 ico-uxf-device-input-controller-0f80d0012c6f40ebb02622e058911e9d581bc4f2.zip |
Updated package changelog.
Change-Id: I24b2c18efcc223a2abea06b317f0b54c976841d9
Signed-off-by: Shibata Makoto <shibata@mac.tec.toyota.co.jp>
27 files changed, 6000 insertions, 0 deletions
diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..a5ec0c8 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,6 @@ +SUBDIRS = joystick_gtforce touch_egalax tests + +DIST_SUBDIRS = joystick_gtforce touch_egalax tests + +DISTCHECK_CONFIGURE_FLAGS = --disable-setuid-install + diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..916169a --- /dev/null +++ b/autogen.sh @@ -0,0 +1,9 @@ +#! /bin/sh + +test -n "$srcdir" || srcdir=`dirname "$0"` +test -n "$srcdir" || srcdir=. +( + cd "$srcdir" && + autoreconf --force -v --install +) || exit +test -n "$NOCONFIGURE" || "$srcdir/configure" "$@" diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..61e9d3b --- /dev/null +++ b/configure.ac @@ -0,0 +1,57 @@ +AC_PREREQ([2.68]) +AC_INIT([ico-uxf-device-input-controller], + [0.4.91], + [https://BUG-REPORT-ADDRESS]) + +AC_CONFIG_HEADERS([config.h]) + +AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz]) + +AM_SILENT_RULES([yes]) + +# Check for programs +AC_PROG_CC +AC_PROG_CXX +AC_PROG_SED + +# Initialize libtool +LT_PREREQ([2.2]) +LT_INIT([disable-static]) + +PKG_PROG_PKG_CONFIG() + +AC_CHECK_HEADERS([execinfo.h]) + +AC_CHECK_FUNCS([mkostemp strchrnul]) + +AC_ARG_ENABLE(setuid-install, [ --enable-setuid-install],, + enable_setuid_install=yes) +AM_CONDITIONAL(ENABLE_SETUID_INSTALL, test x$enable_setuid_install = xyes) + +SHARED_LIBS= +SHARED_CFLAGS= +AC_SUBST(SHARED_LIBS) +AC_SUBST(SHARED_CFLAGS) + +COMPOSITOR_LIBS="$COMPOSITOR_LIBS" +COMPOSITOR_CFLAGS="$COMPOSITOR_CFLAGS" + +AM_CONDITIONAL(ENABLE_DESKTOP_SHELL, true) + +if test "x$GCC" = "xyes"; then + my_common_gcc_flags="-Wall -Wextra -Wno-unused-parameter \ + -Wno-missing-field-initializers -g -fvisibility=hidden" + GCC_CFLAGS="$my_common_gcc_flags \ + -Wstrict-prototypes -Wmissing-prototypes" + GCC_CXXFLAGS="$my_common_gcc_flags" +fi +AC_SUBST(GCC_CFLAGS) +AC_SUBST(GCC_CXXFLAGS) + +WAYLAND_SCANNER_RULES(['$(top_srcdir)/protocol']) + +AC_CONFIG_FILES([Makefile + joystick_gtforce/Makefile + touch_egalax/Makefile + tests/Makefile]) +AC_OUTPUT diff --git a/egalax_calibration.conf b/egalax_calibration.conf new file mode 100644 index 0000000..7fe61e2 --- /dev/null +++ b/egalax_calibration.conf @@ -0,0 +1,6 @@ +DWIDTH=1920 +DHEIGHT=1080 +POSITION1=1908*164 +POSITION2=127*175 +POSITION3=1874*1829 +POSITION4=149*1802 diff --git a/joystick_gtforce.conf b/joystick_gtforce.conf new file mode 100644 index 0000000..9537ad1 --- /dev/null +++ b/joystick_gtforce.conf @@ -0,0 +1,59 @@ +## Multi Input Controller Configurations for joystick_gtforce +## /opt/etc/ico-uxf-device-input-controller/joystick_gtforce.conf +## Feb-08-2013 + +## Device +[device] +# Device Name +name=DrivingForceGT +# Device Input Controller +ictl=ico_ictl-joystick +# Device type('8' is input switch) +type=8 +# ECU Id +ecu=0 + +## Input Switch +[input] +## UpDown key input +0=JS_UPDOWN +# input event from device(type;number) +0.event=2;3 +# event code to Multi Input Manager(Up;Down) +0.code=10:Up;11:Down + +## LeftRight key input +1=JS_LR +# input event from device(type;number) +1.event=2;2 +# event code to Multi Input Manager(Left;Right) +1.code=20:Left;21:Right + +## CROSS Button input +2=JS_CROSS +# input event from device(type;number) +2.event=1;0 +# event code to Multi Input Manager +2.code=30 + +## SQUARE Button input +3=JS_SQUARE +# input event from device(type;number) +3.event=1;1 +# event code to Multi Input Manager +3.code=40 + +## CIRCLE Button input +4=JS_CIRCLE +# input event from device(type;number) +4.event=1;2 +# event code to Multi Input Manager +4.code=50 + +## TRIANGLE Button input +5=JS_TRIANGLE +# input event from device(type;number) +5.event=1;3 +# event code to Multi Input Manager +5.code=60 + diff --git a/joystick_gtforce/Makefile.am b/joystick_gtforce/Makefile.am new file mode 100644 index 0000000..6f3f8ed --- /dev/null +++ b/joystick_gtforce/Makefile.am @@ -0,0 +1,26 @@ +export abs_builddir + +glib_inc = -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/lib/i386-linux-gnu/glib-2.0/include +glib_lib = -lgobject-2.0 -lgthread-2.0 -lrt -lglib-2.0 + +wayland_client_lib = -lwayland-client +wayland_ivi_client_lib = -lico-uxf-weston-plugin +wayland_ivi_client_inc = -I/usr/include/ico-uxf-weston-plugin + +AM_CFLAGS = $(GCC_CFLAGS) +AM_CPPFLAGS = -I$(top_srcdir)/src $(wayland_ivi_client_inc) $(glib_inc) $(COMPOSITOR_CFLAGS) + +bin_PROGRAMS = \ + ico_ictl-joystick_gtforce + +check_LTLIBRARIES = $(TESTS) +check_PROGRAMS = ico_ictl-joystick + +AM_LDFLAGS = -module -avoid-version -rpath $(libdir) $(glib_lib) + +ico_ictl_joystick_gtforce_SOURCES = \ + ico_ictl-joystick.c \ + ico_ictl-wayland.c \ + dbg_curtime.c +ico_ictl_joystick_gtforce_LDADD = $(SIMPLE_CLIENT_LIBS) $(wayland_ivi_client_lib) $(wayland_client_lib) + diff --git a/joystick_gtforce/dbg_curtime.c b/joystick_gtforce/dbg_curtime.c new file mode 100644 index 0000000..23063fb --- /dev/null +++ b/joystick_gtforce/dbg_curtime.c @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2013, TOYOTA MOTOR CORPORATION. + * + * This program is licensed under the terms and conditions of the + * Apache License, version 2.0. The full text of the Apache License is at + * http://www.apache.org/licenses/LICENSE-2.0 + * + */ +/** + * @brief Current date & time string for log output + * + * @date Feb-08-2013 + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <math.h> +#include <sys/time.h> +#include <time.h> + +const char *dbg_curtime(void); + +/*--------------------------------------------------------------------------*/ +/** + * @brief dbg_curtime: Current time for Debug Write + * + * @param None + * @return String pointer for current time + */ +/*--------------------------------------------------------------------------*/ +const char * +dbg_curtime(void) +{ + struct timeval NowTime; /* Current date & time */ + static int NowZone = (99*60*60);/* Local time */ + extern long timezone; /* System time zone */ + static char sBuf[28]; + + if (NowZone > (24*60*60)) { + tzset(); + NowZone = timezone; + } + gettimeofday(&NowTime, (struct timezone *)0); + NowTime.tv_sec -= NowZone; + + sprintf(sBuf, "[%02d:%02d:%02d.%03d]", + (int)((NowTime.tv_sec/3600) % 24), + (int)((NowTime.tv_sec/60) % 60), + (int)(NowTime.tv_sec % 60), + (int)NowTime.tv_usec/1000); + + return(sBuf); +} + diff --git a/joystick_gtforce/ico_ictl-joystick.c b/joystick_gtforce/ico_ictl-joystick.c new file mode 100644 index 0000000..3e10160 --- /dev/null +++ b/joystick_gtforce/ico_ictl-joystick.c @@ -0,0 +1,658 @@ +/* + * Copyright (c) 2013, TOYOTA MOTOR CORPORATION. + * + * This program is licensed under the terms and conditions of the + * Apache License, version 2.0. The full text of the Apache License is at + * http://www.apache.org/licenses/LICENSE-2.0 + * + */ +/** + * @brief Device Input Controller(GtForce joystick) + * @brief joystick input event to Input Manager + * + * @date Feb-08-2013 + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <strings.h> +#include <errno.h> +#include <pthread.h> +#include <sys/ioctl.h> +#include <linux/joystick.h> +#include <glib.h> + +#include "ico_ictl-local.h" + +/* type definition */ +typedef struct _Ico_ICtl_JS { + int fd; /* device file fd */ + char device[32]; /* device name */ + char ictl[32]; /* input controller name */ + int type; /* device type */ + int hostid; /* host Id(currently unused) */ +} Ico_ICtl_JS; + +typedef struct _Ico_Ictl_Code { + unsigned short code; /* code value */ + char name[20]; /* code name */ +} Ico_Ictl_Code; + +typedef struct _Ico_ICtl_JS_Input { + char name[20]; /* input switch name */ + int input; /* input number */ + int type; /* input event type */ + int number; /* input event number */ + Ico_Ictl_Code code[20]; /* key code */ + int last; /* last input code */ +} Ico_ICtl_JS_Input; + +/* prototype of static function */ +static void PrintUsage(const char *pName); + +/* table/variable */ +int mPseudo = 0; /* pseudo input device for test */ +int mDebug = 0; /* debug mode */ +int mEventLog = 0; /* event input log */ +struct timeval lastEvent = { 0, 0 }; /* last input event time */ +int gRunning = 1; /* run state(1:run, 0:finish) */ + +/* Input Contorller Table */ +Ico_ICtl_Mng gIco_ICtrl_Mng = { 0 }; +Ico_ICtl_JS gIco_ICtrl_JS = { 0 }; +int nIco_ICtrl_JS_Input = 0; +Ico_ICtl_JS_Input *gIco_ICtrl_JS_Input = NULL; + +/* static functions */ +/*--------------------------------------------------------------------------*/ +/** + * @brief ico_ictl_find_input_by_name: find Input Table by input switch name + * + * @param[in] name input switch name + * @return result + * @retval !=NULL success(Input Table address) + * @retval ==NULL failed + */ +/*--------------------------------------------------------------------------*/ +static Ico_ICtl_JS_Input * +ico_ictl_find_input_by_name(const char *name) +{ + Ico_ICtl_JS_Input *iMng = NULL; + int ii; + + for (ii = 0; ii < nIco_ICtrl_JS_Input; ii++) { + if (strncasecmp(name, gIco_ICtrl_JS_Input[ii].name, 16) == 0) { + iMng = &gIco_ICtrl_JS_Input[ii]; + break; + } + } + return iMng; +} + +/*--------------------------------------------------------------------------*/ +/** + * @brief ico_ictl_find_input_by_param: find Input Table by input switch type and number + * + * @param[in] type input event type (of Linux Input subsystem) + * @param[in] number input event number (of Linux Input subsystem) + * @return result + * @retval !=NULL success(Input Table address) + * @retval ==NULL failed + */ +/*--------------------------------------------------------------------------*/ +static Ico_ICtl_JS_Input * +ico_ictl_find_input_by_param(int type, int number) +{ + Ico_ICtl_JS_Input *iMng = NULL; + int ii; + + for (ii = 0; ii < nIco_ICtrl_JS_Input; ii++) { + if ((gIco_ICtrl_JS_Input[ii].type == type) + && (gIco_ICtrl_JS_Input[ii].number == number)) { + iMng = &gIco_ICtrl_JS_Input[ii]; + break; + } + } + return iMng; +} + +/*--------------------------------------------------------------------------*/ +/** + * @brief conf_getUint: convert integer string to value + * + * @param[in] str integer string + * @return result + * @retval >=0 success(converted vaule) + * @retval -1 failed + */ +/*--------------------------------------------------------------------------*/ +static int +conf_getUint(const char *str) +{ + int key = -1; + char *errpt; + + if (str != NULL) { + errpt = NULL; + key = strtol(str, &errpt, 0); + if ((errpt) && (*errpt != 0)) { + key = -1; + } + } + return key; +} + +/*--------------------------------------------------------------------------*/ +/** + * @brief conf_countNumericalKey: get configuration list + * + * @param[in] keyfile configuration file + * @param[in] group configuration key group name + * @return result + * @retval !=NULL success(configuration list) + * @retval ==NULL failed + */ +/*--------------------------------------------------------------------------*/ +static GList * +conf_countNumericalKey(GKeyFile *keyfile, const char *group) +{ + GList* list=NULL; + char **result; + gsize length; + int i; + + result = g_key_file_get_keys(keyfile, group, &length, NULL); + + for (i = 0; i < (int)length; i++) { + int id = conf_getUint(result[i]); + if (id >= 0) { + list=g_list_append(list, g_strdup(result[i])); + } + } + g_strfreev(result); + return list; +} + +/*--------------------------------------------------------------------------*/ +/** + * @brief conf_appendStr: connect strings + * + * @param[in] str1 string 1 + * @param[in] str2 string 2 + * @return connected string + */ +/*--------------------------------------------------------------------------*/ +static char * +conf_appendStr(const char *str1, const char *str2) +{ + static char buf[128]; + snprintf(buf, sizeof(buf)-1, "%s%s", str1, str2); + return buf; +} + +/*--------------------------------------------------------------------------*/ +/** + * @brief ico_ictl_read_conf: read configuration file + * + * @param[in] file configuration file path name + * @return result + * @retval ICO_ICTL_OK sccess + * @retval ICO_ICTL_ERR failed + */ +/*--------------------------------------------------------------------------*/ +static int +ico_ictl_read_conf(const char *file) +{ + DEBUG_PRINT("ico_ictl_read_conf: Enter(file=%s)", file); + + GKeyFile *keyfile; + GKeyFileFlags flags; + GString *filepath; + GList *idlist; + GError *error = NULL; + Ico_ICtl_JS_Input *iMng; + char *name; + gsize length; + int ii, jj; + + keyfile = g_key_file_new(); + flags = G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS; + + filepath = g_string_new(file); + + if (! g_key_file_load_from_file(keyfile, filepath->str, flags, &error)) { + ERROR_PRINT("ico_ictl_read_conf: Leave(can not open conf file)"); + g_string_free(filepath, TRUE); + return ICO_ICTL_ERR; + } + g_string_free(filepath, TRUE); + + /* count number of key in [device] section */ + memset((char *)&gIco_ICtrl_JS, 0, sizeof(gIco_ICtrl_JS)); + name = g_key_file_get_string(keyfile, "device", "name", &error); + if (name) { + strncpy(gIco_ICtrl_JS.device, name, sizeof(gIco_ICtrl_JS.device)-1); + } + name = g_key_file_get_string(keyfile, "device", "ictl", &error); + if (name) { + strncpy(gIco_ICtrl_JS.ictl, name, sizeof(gIco_ICtrl_JS.ictl)-1); + } + gIco_ICtrl_JS.type = g_key_file_get_integer(keyfile, "device", "type", &error); + gIco_ICtrl_JS.hostid = g_key_file_get_integer(keyfile, "device", "ecu", &error); + + /* count number of key in [input] section */ + idlist = conf_countNumericalKey(keyfile, "input"); + length = g_list_length(idlist); + if (length <= 0) { + length = 1; + } + nIco_ICtrl_JS_Input = 0; + gIco_ICtrl_JS_Input = (Ico_ICtl_JS_Input *)malloc(sizeof(Ico_ICtl_JS_Input) * length); + if (! gIco_ICtrl_JS_Input) { + ERROR_PRINT("joystick_gtforce: No Memory"); + exit(1); + } + memset((char *)gIco_ICtrl_JS_Input, 0, sizeof(Ico_ICtl_JS_Input) * length); + + for (ii = 0; ii < (int)length; ii++) { + const char *g = "input"; + char *key = (char *)g_list_nth_data(idlist, ii); + gsize listsize; + gint *attr; + gchar **code; + + name = g_key_file_get_string(keyfile, g, key, &error); + if (name == NULL) continue; + + iMng = ico_ictl_find_input_by_name(name); + if (iMng != NULL) { + /* multiple define */ + ERROR_PRINT("ico_ictl_read_conf: switch name(%s) re-define", name); + continue; + } + iMng = &gIco_ICtrl_JS_Input[nIco_ICtrl_JS_Input]; + + iMng->input = conf_getUint(key); + strncpy(iMng->name, name, sizeof(iMng->name)-1); + + /* event */ + attr = g_key_file_get_integer_list(keyfile, g, conf_appendStr(key, ".event"), + &listsize, &error); + if (listsize < 2) continue; + iMng->type = attr[0]; + iMng->number = attr[1]; + + /* code */ + code = g_key_file_get_string_list(keyfile, g, conf_appendStr(key, ".code"), + &listsize, &error); + if ((code == NULL) || (listsize <= 0)) { + strcpy(iMng->code[0].name, iMng->name); + } + else { + if ((int)listsize > 20) listsize = 20; + for (jj = 0; jj < (int)listsize; jj++) { + char *p = (char *)code[jj]; + while ((*p != 0) && (*p != ':')) { + iMng->code[jj].code = iMng->code[jj].code * 10 + *p - '0'; + p ++; + } + if (*p) { + p ++; + strncpy(iMng->code[jj].name, p, sizeof(iMng->code[jj].name)-1); + } + if (iMng->code[jj].name[0] == 0) { + strcpy(iMng->code[jj].name, iMng->name); + } + } + } + if (code) g_strfreev(code); + + nIco_ICtrl_JS_Input ++; + + DEBUG_PRINT("%s input:%d(type=%d,number=%d,code=%d[%s],%d[%s])", + iMng->name, iMng->input, iMng->type, iMng->number, + iMng->code[0].code, iMng->code[0].name, + iMng->code[1].code, iMng->code[1].name); + } + DEBUG_PRINT("ico_ictl_read_conf: Leave"); + + return ICO_ICTL_OK; +} + +/*--------------------------------------------------------------------------*/ +/** + * @brief ico_ictl_js_open: open input jyostick input device + * + * @param[in] ictlDevName device name + * @return result + * @retval >= 0 sccess(device file descriptor) + * @retval ICO_ICTL_ERR failed + */ +/*--------------------------------------------------------------------------*/ +static int +ico_ictl_js_open(const char *ictlDevName) +{ + DEBUG_PRINT("ico_ictl_js_open: Enter(device=%s)", ictlDevName) + + int fd = -1; + char devFile[64]; + char devName[64]; + int ii, jj, kk; + + if (ictlDevName == NULL) { + ERROR_PRINT("ico_ictl_js_open: Leave(failed devname NULL)"); + return ICO_ICTL_ERR; + } + + char *pdev = getenv(ICO_ICTL_INPUT_DEV); + if ((pdev != NULL) && (*pdev != 0)) { + DEBUG_PRINT("ico_ictl_js_open: Pseudo input device(%s)", pdev); + mPseudo = 1; + } + else { + pdev = (char *)ictlDevName; + } + for (ii = 0; ii < 16; ii++) { + if (mPseudo) { + snprintf(devFile, 64, "/dev/input/event%d", ii); + } + else { + snprintf(devFile, 64, "/dev/input/js%d", ii); + } + fd = open(devFile, O_RDONLY | O_NONBLOCK); + if (fd < 0) continue; + + memset(devName, 0, sizeof(devName)); + if (mPseudo) { + ioctl(fd, EVIOCGNAME(sizeof(devName)), devName); + } + else { + ioctl(fd, JSIOCGNAME(sizeof(devName)), devName); + } + kk = 0; + for (jj = 0; devName[jj]; jj++) { + if (devName[jj] != ' ') { + devName[kk++] = devName[jj]; + } + } + devName[kk] = 0; + DEBUG_PRINT("ico_ictl_js_open: %d.%s", ii+1, devName); + + if (strncasecmp(devName, pdev, sizeof(devName)) == 0) break; + /* not match, close */ + close(fd); + fd = -1; + } + + if (fd < 0) { + ERROR_PRINT("ico_ictl_js_open: Leave(not find device file)"); + return ICO_ICTL_ERR; + } + DEBUG_PRINT("ico_ictl_js_open: Leave(found %s[%s] as %s)", pdev, devFile, ictlDevName); + return fd; +} + +/*--------------------------------------------------------------------------*/ +/** + * @brief ico_ictl_js_read: read input jyostick input device + * + * @param[in] fd file descriptor + * @return nothing + */ +/*--------------------------------------------------------------------------*/ +static void +ico_ictl_js_read(int fd) +{ + DEBUG_PRINT("ico_ictl_js_read: Enter(fd=%d)", fd) + + struct js_event events[8]; + struct input_event pevents[8]; + int rSize; + int ii, jj; + int number, value, type, code, state; + + if (mPseudo) { + /* Pseudo event input for Debug */ + rSize = read(fd, pevents, sizeof(pevents)); + if (rSize > 0) { + for (ii = 0; ii < rSize/((int)sizeof(struct input_event)); ii++) { + events[ii].time = (pevents[ii].time.tv_sec % 1000) * 1000 + + pevents[ii].time.tv_usec / 1000; + events[ii].type = pevents[ii].type; + events[ii].number = pevents[ii].code; + events[ii].value = pevents[ii].value; + if ((events[ii].type == 2) && (events[ii].value == 9)) { + events[ii].value = 0; + } + else if ((events[ii].type == 1) && (events[ii].number == 9)) { + events[ii].number = 0; + } + DEBUG_PRINT("ico_ictl_js_read: pseude event.%d %d.%d.%d", + ii, events[ii].type, events[ii].number, events[ii].value); + } + rSize = ii * sizeof(struct js_event); + } + } + else { + rSize = read(fd, events, sizeof(events)); + } + if (rSize < 0) { + ii = errno; + if ((ii == EINTR) || (ii == EAGAIN)) { + return; + } + DEBUG_PRINT("ico_ictl_js_read: Leave(read error[%d])", ii) + exit(9); + } + for (ii = 0; ii < (rSize / (int)sizeof(struct js_event)); ii++) { + Ico_ICtl_JS_Input *iMng = NULL; + + type = events[ii].type; + number = events[ii].number; + value = events[ii].value; + DEBUG_PRINT("ico_ictl_js_read: Read(type=%d, number=%d, value=%d", + type, number, value); + + iMng = ico_ictl_find_input_by_param(type, number); + if (iMng == NULL) { + continue; + } + + if (mEventLog) { + struct timeval curtime; + gettimeofday(&curtime, NULL); + + if (lastEvent.tv_sec) { + int sec, usec; + + sec = curtime.tv_sec - lastEvent.tv_sec; + usec = curtime.tv_usec - lastEvent.tv_usec; + + if (usec < 0) { + sec -= 1; + usec += 1000000; + } + usec += 500; + if( usec >= 1000000 ) { + usec -= 1000000; + sec += 1; + } + if ((sec > 0) || ((sec == 0) && (usec >= 10000))) { + lastEvent.tv_sec = curtime.tv_sec; + lastEvent.tv_usec = curtime.tv_usec; + } + } + else { + lastEvent.tv_sec = curtime.tv_sec; + lastEvent.tv_usec = curtime.tv_usec; + } + for (jj = 0; + jj < (int)(sizeof(gIco_ICtrl_JS_Input)/sizeof(Ico_ICtl_JS_Input)); jj++) { + if ((type == gIco_ICtrl_JS_Input[jj].type) && + (number == gIco_ICtrl_JS_Input[jj].number)) { + break; + } + } + } + + if (iMng->code[1].code != 0) { + if (value < 0) { + code = iMng->code[0].code; + state = WL_KEYBOARD_KEY_STATE_PRESSED; + iMng->last = code; + } + else if (value > 0) { + code = iMng->code[1].code; + state = WL_KEYBOARD_KEY_STATE_PRESSED; + iMng->last = code; + } + else { + if (iMng->last != iMng->code[0].code && iMng->last != iMng->code[1].code) { + continue; + } + code = iMng->last; + state = WL_KEYBOARD_KEY_STATE_RELEASED; + iMng->last = -1; + } + } + else { + if (value == 0) { + code = iMng->code[0].code; + state = WL_KEYBOARD_KEY_STATE_RELEASED; + } + else if (value == 1) { + code = iMng->code[0].code; + state = WL_KEYBOARD_KEY_STATE_PRESSED; + } + else { + continue; + } + } + ico_input_mgr_device_input_event(gIco_ICtrl_Mng.Wayland_InputMgr, events[ii].time, + gIco_ICtrl_JS.device, iMng->input, code, state); + } +} + +/*--------------------------------------------------------------------------*/ +/** + * @brief signal_int: signal handler + * + * @param[in] signum signal number(unused) + * @return nothing + */ +/*--------------------------------------------------------------------------*/ +static void +signal_int(int signum) +{ + gRunning = 0; +} + +/*--------------------------------------------------------------------------*/ +/** + * @brief Device Input Controllers: For Joy Stick + * main routine + * + * @param main() finction's standard parameter (argc,argv) + * @return result + * @retval 0 success + * @retval 1 failed + */ +/*--------------------------------------------------------------------------*/ +int main(int argc, char *argv[]) +{ + struct epoll_event ev_ret[16]; + char *ictlDevName = "DrivingForceGT"; + int JSfd; + int ii, jj; + int ret; + struct sigaction sigint; + + /* get device name from parameter */ + for (ii = 1; ii < argc; ii++) { + if (strcasecmp( argv[ii], "-h") == 0) { + PrintUsage(argv[0]); + exit( 0 ); + } + else if (strcasecmp( argv[ii], "-d") == 0) { + /* debug */ + mDebug = 1; + } + else if (strcasecmp( argv[ii], "-l") == 0) { + /* event input log */ + mEventLog = 1; + } + else { + ictlDevName = argv[ii]; + } + } + + /* change to daemon */ + if (! mDebug) { + if (daemon(0, 1) < 0) { + fprintf(stderr, "%s: Can not Create Daemon\n", argv[0]); + exit(1); + } + } + + /* open joystick */ + JSfd = ico_ictl_js_open(ictlDevName); + if (JSfd < 0) { + ERROR_PRINT("main: Leave(Error device open)"); + exit(1); + } + gIco_ICtrl_JS.fd = JSfd; + + /* read conf file */ + char *confpath = getenv(ICO_ICTL_CONF_ENV); + if (!confpath) { + confpath = ICO_ICTL_CONF_FILE; + } + ico_ictl_read_conf(confpath); + + /* initialize wayland */ + ico_ictl_wayland_init(NULL, NULL); + ico_ictl_add_fd(JSfd); + + /* send configuration informations to Multi Input Manager */ + for (ii = 0; ii < nIco_ICtrl_JS_Input; ii++) { + ico_input_mgr_device_configure_input( + gIco_ICtrl_Mng.Wayland_InputMgr, gIco_ICtrl_JS.device, gIco_ICtrl_JS.type, + gIco_ICtrl_JS_Input[ii].name, gIco_ICtrl_JS_Input[ii].input, + gIco_ICtrl_JS_Input[ii].code[0].name, gIco_ICtrl_JS_Input[ii].code[0].code); + for (jj = 1; jj < 20; jj++) { + if (gIco_ICtrl_JS_Input[ii].code[jj].code == 0) break; + ico_input_mgr_device_configure_code( + gIco_ICtrl_Mng.Wayland_InputMgr, gIco_ICtrl_JS.device, + gIco_ICtrl_JS_Input[ii].input, gIco_ICtrl_JS_Input[ii].code[jj].name, + gIco_ICtrl_JS_Input[ii].code[jj].code); + } + } + + /* signal init */ + sigint.sa_handler = signal_int; + sigemptyset(&sigint.sa_mask); + sigint.sa_flags = SA_RESETHAND; + sigaction(SIGINT, &sigint, NULL); + + /* main loop */ + while (gRunning) { + ret = ico_ictl_wayland_iterate(ev_ret, 200); + for (ii = 0; ii < ret; ii++) { + if (ev_ret[ii].data.fd == JSfd) { + ico_ictl_js_read(JSfd); + } + } + } + ico_ictl_wayland_finish(); + + exit(0); +} + +static void PrintUsage(const char *pName) +{ + fprintf( stderr, "Usage: %s [-h] [-d] DeviceName\n", pName ); + fprintf( stderr, " ex)\n"); + fprintf( stderr, " %s \"Driving Force GT\"\n", pName); +} + diff --git a/joystick_gtforce/ico_ictl-local.h b/joystick_gtforce/ico_ictl-local.h new file mode 100644 index 0000000..cc6265b --- /dev/null +++ b/joystick_gtforce/ico_ictl-local.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2013, TOYOTA MOTOR CORPORATION. + * + * This program is licensed under the terms and conditions of the + * Apache License, version 2.0. The full text of the Apache License is at + * http://www.apache.org/licenses/LICENSE-2.0 + * + */ +/** + * @brief header file of Input Controllers + * + * @date Feb-20-2013 + */ + +#ifndef _ICO_ICTL_LOCAL_H_ +#define _ICO_ICTL_LOCAL_H_ + +#include <wayland-client-protocol.h> +#include <wayland-client.h> +#include <wayland-egl.h> +#include <wayland-util.h> +#include <sys/ioctl.h> +#include <sys/epoll.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#include <ico_input_mgr-client-protocol.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* call back function */ +typedef void (*Ico_ICtl_Wayland_Cb)( void ); + +/* Deafult config file */ +#define ICO_ICTL_CONF_FILE \ + "/opt/etc/ico-uxf-device-input-controller/joystick_gtforce.conf" +/* Environment valible name for config file */ +#define ICO_ICTL_CONF_ENV "ICTL_GTFORCE_CONF" +/* Environment valible name for input device*/ +#define ICO_ICTL_INPUT_DEV "ICTL_GTFORCE_DEV" + +#define ICO_ICTL_TOUCH_NONE 0 /* not exist touch event */ +#define ICO_ICTL_TOUCH_KEYIN 1 /* touch event is reserved */ +#define ICO_ICTL_TOUCH_PASSED 2 /* touch event is passed */ + +#define ICO_ICTL_EVENT_NUM (16) +/* return val */ +#define ICO_ICTL_OK 0 /* success */ +#define ICO_ICTL_ERR (-1) /* failedi */ + +/* management table */ +typedef struct _Ico_ICtl_Mng { + /* Multi Input Controller */ + int ICTL_ID; /* multi input controller ID */ + Ico_ICtl_Wayland_Cb ICtl_CallBack; /* call back function */ + + /* wayland interfaces */ + struct wl_display *Wayland_Display; /* Wayland Display */ + struct wl_registry *Wayland_Registry; /* Wayland Registory */ + struct ico_input_mgr_device *Wayland_InputMgr; /* Wayland multi input manager */ + + int WaylandFd; /* file descriptor of Wayland */ + int ICTL_EFD; /* descriptor of epoll */ + +} Ico_ICtl_Mng; + +/* function prototype */ + /* initialization to wayland */ +int ico_ictl_wayland_init(const char *display ,Ico_ICtl_Wayland_Cb callback); +void ico_ictl_wayland_finish(void); /* finish wayland connection */ + /* iterate wayland connection */ +int ico_ictl_wayland_iterate(struct epoll_event *ev_ret, int timeout); +int ico_ictl_add_fd(int fd); /* add file descriptor */ + +/* macro for debug */ +extern const char *dbg_curtime(void); +extern int mDebug; +#define DEBUG_PRINT(fmt, ...) \ + {if (mDebug) {fprintf(stderr, "%sDBG> "fmt" (%s:%d)\n",dbg_curtime(),##__VA_ARGS__,__FILE__,__LINE__); fflush(stderr);}} +#define ERROR_PRINT(fmt, ...) \ + {fprintf(stderr, "%sERR> "fmt" (%s:%d)\n",dbg_curtime(),##__VA_ARGS__,__FILE__,__LINE__); fflush(stderr);} + +#ifdef __cplusplus +} +#endif +#endif /* _ICO_ICTL_LOCAL_H_ */ + diff --git a/joystick_gtforce/ico_ictl-wayland.c b/joystick_gtforce/ico_ictl-wayland.c new file mode 100644 index 0000000..9665f2c --- /dev/null +++ b/joystick_gtforce/ico_ictl-wayland.c @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2013, TOYOTA MOTOR CORPORATION. + * + * This program is licensed under the terms and conditions of the + * Apache License, version 2.0. The full text of the Apache License is at + * http://www.apache.org/licenses/LICENSE-2.0 + * + */ +/** + * @brief Device Input Controllers(wayland processing) + * processing related wayland + * + * @date Feb-08-2013 + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <strings.h> +#include <errno.h> +#include <pthread.h> + +#include "ico_ictl-local.h" + +/* prototype of static function */ +/* callback function from wayland global */ +static void ico_ictl_wayland_globalcb(void *data, struct wl_registry *registry, + uint32_t wldispid, const char *event, + uint32_t version); + +/* table/variable */ +extern Ico_ICtl_Mng gIco_ICtrl_Mng; + +static const struct wl_registry_listener registry_listener = { + ico_ictl_wayland_globalcb +}; + +/*--------------------------------------------------------------------------*/ +/** + * @brief ico_ictl_wayland_init + * connect to wayland of specified Display. specified NULL to + * connected Display, connect to the default Display. + * + * @param[in] display display to connect + * @param[in] callback callback function + * @return result + * @retval ICO_ICTL_EOK Success + * @retval ICO_ICTL_ERR Failed + */ +/*--------------------------------------------------------------------------*/ +int +ico_ictl_wayland_init(const char *display, Ico_ICtl_Wayland_Cb callback) +{ + DEBUG_PRINT("ico_ictl_wayland_init: Enter"); + + int ret; + + /* regist callback funtion */ + gIco_ICtrl_Mng.ICtl_CallBack = callback; + + /* connect to wayland(retry max 3 sec) */ + for (ret = 0; ret < (3000/20); ret++) { + gIco_ICtrl_Mng.Wayland_Display = wl_display_connect(display); + if (gIco_ICtrl_Mng.Wayland_Display) { + break; + } + usleep(20*1000); + } + if (! gIco_ICtrl_Mng.Wayland_Display) { + ERROR_PRINT("ico_ictl_wayland_init: Leave(ERR), Wayland Connect Error"); + return ICO_ICTL_ERR; + } + + /* add listener of wayland registry */ + gIco_ICtrl_Mng.Wayland_Registry = + wl_display_get_registry(gIco_ICtrl_Mng.Wayland_Display); + wl_registry_add_listener(gIco_ICtrl_Mng.Wayland_Registry, + ®istry_listener, &gIco_ICtrl_Mng); + + /* display dispatch to wait */ + do { + wl_display_dispatch(gIco_ICtrl_Mng.Wayland_Display); + } while (gIco_ICtrl_Mng.Wayland_InputMgr == NULL); + + /* get the Wayland descriptor */ + gIco_ICtrl_Mng.WaylandFd = + wl_display_get_fd(gIco_ICtrl_Mng.Wayland_Display); + DEBUG_PRINT("ico_ictl_wayland_init: WFD = %d", gIco_ICtrl_Mng.WaylandFd); + + /* create epoll file descriptor */ + gIco_ICtrl_Mng.ICTL_EFD = epoll_create1(EPOLL_CLOEXEC); + if (gIco_ICtrl_Mng.ICTL_EFD < 0) { + ERROR_PRINT("ico_ictl_wayland_init: Leave(ERR), Epoll Create Error"); + return ICO_ICTL_ERR; + } + struct epoll_event ev; + memset(&ev, 0, sizeof(ev)); + ev.events = EPOLLIN; + ev.data.fd = gIco_ICtrl_Mng.WaylandFd; + if (epoll_ctl(gIco_ICtrl_Mng.ICTL_EFD, EPOLL_CTL_ADD, + gIco_ICtrl_Mng.WaylandFd, &ev) != 0) { + ERROR_PRINT("ico_ictl_wayland_init: Leave(ERR), Epoll ctl Error"); + return ICO_ICTL_ERR; + } + DEBUG_PRINT("ico_ictl_wayland_init: Leave(EOK)"); + return ICO_ICTL_OK; +} + +/*--------------------------------------------------------------------------*/ +/** + * @brief ico_ictl_wayland_globalcb + * + * @param[in] data the information that appointed at the time of + * callback registration + * @param[in] registry wayland registry + * @param[in] wldispid wayland displya id + * @param[in] event event name + * @param[in] version version of Wayland + * @return nothing + */ +/*--------------------------------------------------------------------------*/ +static void +ico_ictl_wayland_globalcb(void *data, struct wl_registry *registry, uint32_t wldispid, + const char *event, uint32_t version) +{ + DEBUG_PRINT("ico_ictl_wayland_globalcb: Event=%s DispId=%08x", event, wldispid); + + if (strcmp(event, "ico_input_mgr_device") == 0) { + /* connect ictl_master in multi input manager */ + gIco_ICtrl_Mng.Wayland_InputMgr = (struct ico_input_mgr_device *) + wl_registry_bind(gIco_ICtrl_Mng.Wayland_Registry, + wldispid, &ico_input_mgr_device_interface, 1); + + DEBUG_PRINT("ico_ictl_wayland_globalcb: wl_registry_bind(ico_input_mgr_device)"); + } +} + +/*--------------------------------------------------------------------------*/ +/** + * @brief ico_ictl_wayland_iterate + * iterate processing of wayland + * + * @param[in] timeout wait time miri-sec + * @return nothing + */ +/*--------------------------------------------------------------------------*/ +int +ico_ictl_wayland_iterate(struct epoll_event *ev_ret, int timeout) +{ + int nfds; + int ii = 0; + + memset(ev_ret, 0, sizeof(struct epoll_event) * ICO_ICTL_EVENT_NUM); + wl_display_flush(gIco_ICtrl_Mng.Wayland_Display); + + while (1) { + if ((nfds = epoll_wait( gIco_ICtrl_Mng.ICTL_EFD, ev_ret, + ICO_ICTL_EVENT_NUM, timeout)) > 0) { + for (ii = 0; ii < nfds; ii++) { + if (ev_ret[ii].data.fd == gIco_ICtrl_Mng.WaylandFd) { + wl_display_dispatch(gIco_ICtrl_Mng.Wayland_Display); + DEBUG_PRINT( "ico_ictl_wayland_iterate: Exit wayland fd"); + } + } + return nfds; + } + else if (nfds == 0) { + return nfds; + } + } +} + +/*--------------------------------------------------------------------------*/ +/** + * @brief ico_ictl_add_fd + * Add file descriptor to watch in pool. + * + * @param[in] fd File descriptor + * @return result + * @retval ICO_ICTL_EOK Success + * @retval ICO_ICTL_ERR Failed + */ +/*--------------------------------------------------------------------------*/ +int +ico_ictl_add_fd(int fd) +{ + DEBUG_PRINT("ico_ictl_add_fd: Enter(fd=%d)", fd); + + struct epoll_event ev; + + if (gIco_ICtrl_Mng.ICTL_EFD <= 0) { + ERROR_PRINT("ico_ictl_add_fd: Leave(ERR), Epoll Never Created"); + return ICO_ICTL_ERR; + } + + memset(&ev, 0, sizeof(ev)); + ev.events = EPOLLIN; + ev.data.fd = fd; + if (epoll_ctl(gIco_ICtrl_Mng.ICTL_EFD, EPOLL_CTL_ADD, fd, &ev) != 0) { + ERROR_PRINT("ico_ictl_add_fd: Leave(ERR), Epoll ctl Error"); + return ICO_ICTL_ERR; + } + DEBUG_PRINT("ico_ictl_add_fd: Leave(EOK)"); + + return ICO_ICTL_OK; +} + +/*--------------------------------------------------------------------------*/ +/** + * @brief ico_ictl_wayland_finish + * Finish wayland connection + * + * @param nothing + * @return nothing + */ +/*--------------------------------------------------------------------------*/ +void +ico_ictl_wayland_finish(void) +{ + DEBUG_PRINT("ico_ictl_wayland_finish: Enter"); + + wl_display_flush(gIco_ICtrl_Mng.Wayland_Display); + wl_display_disconnect(gIco_ICtrl_Mng.Wayland_Display); + + DEBUG_PRINT("ico_ictl_wayland_finish: Leave"); +} + diff --git a/packaging/ico-uxf-device-input-controller.changes b/packaging/ico-uxf-device-input-controller.changes new file mode 100644 index 0000000..35ba624 --- /dev/null +++ b/packaging/ico-uxf-device-input-controller.changes @@ -0,0 +1,3 @@ +* Fri Apr 26 2013 Shibata Makoto <shibata@mac.tec.toyota.co.jp> de524fc +- Import initial. + diff --git a/packaging/ico-uxf-device-input-controller.spec b/packaging/ico-uxf-device-input-controller.spec new file mode 100644 index 0000000..c125e30 --- /dev/null +++ b/packaging/ico-uxf-device-input-controller.spec @@ -0,0 +1,50 @@ +Name: ico-uxf-device-input-controller +Summary: Device Input Controller +Version: 0.5.01 +Release: 1.1 +Group: System/GUI +License: Apache License, Version 2.0 +URL: "" +Source0: %{name}-%{version}.tar.bz2 + +BuildRequires: pkgconfig(wayland-client) >= 1.0 +BuildRequires: pkgconfig(wayland-egl) +BuildRequires: pkgconfig(egl) +BuildRequires: pkgconfig(glesv2) +BuildRequires: pkgconfig(glib-2.0) +BuildRequires: ico-uxf-weston-plugin-devel >= 0.5.0 +Requires: weston >= 1.0 +Requires: ico-uxf-weston-plugin >= 0.5.0 + +%description +Device Input Controller for ico-uxf-weston-plugin(Multi Input Manager) + +%prep +%setup -q -n %{name}-%{version} + +%build +autoreconf --install + +%autogen --prefix=/usr + +%configure +make %{?_smp_mflags} + +%install +rm -rf %{buildroot} +%make_install + +# configurations +%define ictl_conf /opt/etc/ico-uxf-device-input-controller +mkdir -p %{buildroot}%{ictl_conf} +install -m 0644 joystick_gtforce.conf %{buildroot}%{ictl_conf} +install -m 0644 egalax_calibration.conf %{buildroot}%{ictl_conf} + +%files +%defattr(-,root,root,-) +%{_bindir}/ico_ictl-joystick_gtforce +%{_bindir}/ico_ictl-touch_egalax +%{_bindir}/ico_ictl-egalax_calibration +%{ictl_conf}/joystick_gtforce.conf +%{ictl_conf}/egalax_calibration.conf + diff --git a/tests/Makefile.am b/tests/Makefile.am new file mode 100644 index 0000000..eee4ee5 --- /dev/null +++ b/tests/Makefile.am @@ -0,0 +1,35 @@ +TESTS_ENVIRONMENT = $(SHELL) $(top_srcdir)/tests/weston-plugin-test + +export abs_builddir + +EFL_INCLUDE = `pkg-config --cflags ecore-evas ecore evas ecore-wayland elementary` +AM_CFLAGS = $(GCC_CFLAGS) $(EFL_INCLUDE) +AM_CPPFLAGS = -I$(top_srcdir)/src -DUNIT_TEST $(COMPOSITOR_CFLAGS) + +noinst_PROGRAMS = \ + test-send_event \ + test-homescreen \ + test-client + +check_LTLIBRARIES = $(TESTS) +check_PROGRAMS = test-homescreen test-client test-send_event + +AM_LDFLAGS = -module -avoid-version -rpath $(libdir) -lwayland-egl -lEGL -lGLESv2 +AM_CFLAGS = $(wayland_ivi_client_inc) $(GCC_CFLAGS) + +test_common_src = test-common.c test-common.h +test_wayland_client = -lwayland-client +wayland_ivi_client_lib = -lico-uxf-weston-plugin +wayland_ivi_client_inc = -I/usr/include/ico-uxf-weston-plugin + +test_send_event_SOURCES = test-send_event.c $(test_common_src) +test_send_event_LDADD = $(SIMPLE_CLIENT_LIBS) $(test_wayland_client) + +test_homescreen_SOURCES = test-homescreen.c $(test_common_src) +test_homescreen_LDADD = $(SIMPLE_CLIENT_LIBS) $(wayland_ivi_client_lib) $(test_wayland_client) + +test_client_SOURCES = test-client.c $(test_common_src) +test_client_LDADD = $(SIMPLE_CLIENT_LIBS) $(wayland_ivi_client_lib) $(test_wayland_client) + +EXTRA_DIST = input-controller-test + diff --git a/tests/input-controller-test b/tests/input-controller-test new file mode 100755 index 0000000..218335c --- /dev/null +++ b/tests/input-controller-test @@ -0,0 +1,85 @@ +#!/bin/sh +# +# Device Input Controller Test +# +# Remark: This examination premises that Weston does not run. + +# 1 Delete log file +rm -fr ../tests/testlog/* + +# 2 Start Pseudo event device (for Touch Panel and Jyostick) +../tests/test-send_event -device=ico_test_touch -d -mq=55551 2> ../tests/testlog/event_log_touch.log & +../tests/test-send_event -device=ico_test_joystick -d -J -mq=55552 2> ../tests/testlog/event_log_joystic.log & +sleep 1 + +# 3 Start Device Input Controllers +export CALIBRATOIN_CONF="../egalax_calibration.conf" +export ICTL_TOUCH_DEV="ico_test_touch" +#../touch_egalax/ico_ictl-touch_egalax -d -L ico_test_touch 2> ../tests/testlog/touch_egalax.log & +../touch_egalax/ico_ictl-touch_egalax -d -L > ../tests/testlog/touch_egalax.log 2>&1 & +sleep 0.5 +export ICTL_GTFORCE_CONF="../joystick_gtforce.conf" +export ICTL_GTFORCE_DEV="ico_test_joystick" +#../joystick_gtforce/ico_ictl-joystick_gtforce -d -l ico_test_joystick 2> ../tests/testlog/joystick_gtforce.log & +../joystick_gtforce/ico_ictl-joystick_gtforce -d -l > ../tests/testlog/joystick_gtforce.log 2>&1 & +sleep 1 + +# 4 Weston/Wayland Envionment +export XDG_RUNTIME_DIR=/tmp/run-root +export QT_QPA_PLATFORM=wayland +export ELM_ENGINE=wayland_egl +export ECORE_EVAS_ENGINE=wayland_egl +#export ELM_ENGINE=wayland_shm +#export ECORE_EVAS_ENGINE=wayland_shm +export EVAS_FONT_DPI=72 +export ECORE_IMF_MODULE=isf +export ELM_MODULES="ctxpopup_copypasteUI>entry/api:datetime_input_ctxpopup>datetime/api" +export ELM_SCALE="0.7" +export ELM_PROFILE=mobile + +# 5 Start Weston +export XDG_CONFIG_HOME="../tests" +/usr/bin/weston --backend=drm-backend.so --idle-time=0 --log=../tests/testlog/weston.log & +sleep 1 + +# 5 Start test-homescreen +../tests/test-homescreen < ../tests/testdata/hs_alltest.dat 2> ../tests/testlog/test-homescreen.log + +# 6 End of Test +sleep 1 +/usr/bin/killall weston +/usr/bin/killall test-send_event +/usr/bin/killall test-send_event +/usr/bin/killall ico_ictl-touch_egalax +/usr/bin/killall ico_ictl-joystick_gtforce +sleep 1 + +# 9 Check Error +FOUND_ERR=0 +/bin/grep "ERR>" testlog/* +if [ "$?" != "1" ] ; then + FOUND_ERR=1 +fi +/bin/grep "WRN>" testlog/* +if [ "$?" != "1" ] ; then + FOUND_ERR=1 +fi +/bin/grep "Error" testlog/* +if [ "$?" != "1" ] ; then + FOUND_ERR=1 +fi +/bin/grep "error" testlog/* | /bin/grep -v "error_but_no_problem_for_test" +if [ "$?" != "1" ] ; then + FOUND_ERR=1 +fi +/bin/grep "Fail" testlog/* | /bin/grep -v "error_but_no_problem_for_test" +if [ "$?" != "1" ] ; then + FOUND_ERR=1 +fi + +if [ $FOUND_ERR = 0 ] ; then + echo "Device Input Controller Test: OK" +else + echo "Device Input Controller Test: ERROR" +fi + diff --git a/tests/test-client.c b/tests/test-client.c new file mode 100644 index 0000000..f6b877e --- /dev/null +++ b/tests/test-client.c @@ -0,0 +1,634 @@ +/* + * Copyright (c) 2013, TOYOTA MOTOR CORPORATION. + * + * This program is licensed under the terms and conditions of the + * Apache License, version 2.0. The full text of the Apache License is at + * http://www.apache.org/licenses/LICENSE-2.0 + * + */ +/** + * @brief Wayland Application for uint test of Weston(Wayland) IVI plugins + * + * @date Feb-08-2013 + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <assert.h> +#include <poll.h> +#include <wayland-client.h> +#include <linux/input.h> +#include "ico_ivi_shell-client-protocol.h" +#include "ico_window_mgr-client-protocol.h" +#include "ico_input_mgr-client-protocol.h" +#include "test-common.h" + +#define MAX_CON_NAME 127 + +struct display { + struct wl_display *display; + struct wl_registry *registry; + struct wl_compositor *compositor; + struct wl_shell *shell; + struct ico_ivi_shell *ico_ivi_shell; + struct ico_window_mgr *ico_window_mgr; + struct ico_exinput *ico_exinput; + struct input *input; + struct output *output; + struct surface *surface; + int init_color; + int init_width; + int init_height; + int prompt; + char connect[MAX_CON_NAME+1]; +}; + +struct input { + struct display *display; + struct wl_seat *seat; + struct wl_pointer *pointer; + struct wl_keyboard *keyboard; + float x, y; + uint32_t button_mask; + struct surface *pointer_focus; + struct surface *keyboard_focus; + uint32_t last_key, last_key_state; +}; + +struct output { + struct display *display; + struct wl_output *output; + int x, y; + int width, height; +}; + +struct surface { + struct display *display; + struct wl_surface *surface; + struct wl_shell_surface *shell_surface; + struct output *output; + EGLDisplay dpy; + EGLConfig conf; + EGLContext ctx; + EGLSurface egl_surface; +}; + +static void clear_surface(struct display *display); + +static void +pointer_handle_enter(void *data, struct wl_pointer *pointer, + uint32_t serial, struct wl_surface *surface, + wl_fixed_t x, wl_fixed_t y) +{ + struct input *input = data; + + input->pointer_focus = wl_surface_get_user_data(surface); + input->x = wl_fixed_to_double(x); + input->y = wl_fixed_to_double(y); + print_log("CLIENT: got pointer enter (%d,%d), surface %p", + (int)input->x, (int)input->y, surface); +} + +static void +pointer_handle_leave(void *data, struct wl_pointer *pointer, + uint32_t serial, struct wl_surface *surface) +{ + struct input *input = data; + + input->pointer_focus = NULL; + + print_log("CLIENT: got pointer leave, surface %p", surface); +} + +static void +pointer_handle_motion(void *data, struct wl_pointer *pointer, + uint32_t time, wl_fixed_t x, wl_fixed_t y) +{ + struct input *input = data; + + input->x = wl_fixed_to_double(x); + input->y = wl_fixed_to_double(y); + + print_log("CLIENT: got pointer motion (%d,%d)", (int)input->x, (int)input->y); +} + +static void +pointer_handle_button(void *data, struct wl_pointer *pointer, + uint32_t serial, uint32_t time, uint32_t button, uint32_t state_w) +{ + struct input *input = data; + uint32_t bit; + enum wl_pointer_button_state state = state_w; + + bit = 1 << (button - BTN_LEFT); + if (state == WL_POINTER_BUTTON_STATE_PRESSED) + input->button_mask |= bit; + else + input->button_mask &= ~bit; + print_log("CLIENT: got pointer button %u %u", button, state_w); +} + +static void +pointer_handle_axis(void *data, struct wl_pointer *pointer, + uint32_t time, uint32_t axis, wl_fixed_t value) +{ + fprintf(stderr, "CLIENT: got pointer axis %u %d\n", axis, value); +} + +static void +keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard, + uint32_t format, int fd, uint32_t size) +{ + close(fd); + print_log("CLIENT: got keyboard keymap"); +} + +static void +keyboard_handle_enter(void *data, struct wl_keyboard *keyboard, + uint32_t serial, struct wl_surface *surface, struct wl_array *keys) +{ + struct input *input = data; + + input->keyboard_focus = wl_surface_get_user_data(surface); + print_log("CLIENT: got keyboard enter, surface %p", surface); +} + +static void +keyboard_handle_leave(void *data, struct wl_keyboard *keyboard, + uint32_t serial, struct wl_surface *surface) +{ + struct input *input = data; + + input->keyboard_focus = NULL; + print_log("CLIENT: got keyboard leave, surface %p", surface); +} + +static void +keyboard_handle_key(void *data, struct wl_keyboard *keyboard, + uint32_t serial, uint32_t time, uint32_t key, uint32_t state) +{ + struct input *input = data; + + input->last_key = key; + input->last_key_state = state; + + print_log("CLIENT: got keyboard key %u %u", key, state); +} + +static void +keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard, + uint32_t serial, uint32_t mods_depressed, + uint32_t mods_latched, uint32_t mods_locked, uint32_t group) +{ + print_log("CLIENT: got keyboard modifier"); +} + +static const struct wl_pointer_listener pointer_listener = { + pointer_handle_enter, + pointer_handle_leave, + pointer_handle_motion, + pointer_handle_button, + pointer_handle_axis, +}; + +static const struct wl_keyboard_listener keyboard_listener = { + keyboard_handle_keymap, + keyboard_handle_enter, + keyboard_handle_leave, + keyboard_handle_key, + keyboard_handle_modifiers, +}; + +static void +seat_handle_capabilities(void *data, struct wl_seat *seat, + enum wl_seat_capability caps) +{ + struct input *input = data; + + if ((caps & WL_SEAT_CAPABILITY_POINTER) && !input->pointer) { + input->pointer = wl_seat_get_pointer(seat); + wl_pointer_set_user_data(input->pointer, input); + wl_pointer_add_listener(input->pointer, &pointer_listener, + input); + } + else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && input->pointer) { + wl_pointer_destroy(input->pointer); + input->pointer = NULL; + } + + if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !input->keyboard) { + input->keyboard = wl_seat_get_keyboard(seat); + wl_keyboard_set_user_data(input->keyboard, input); + wl_keyboard_add_listener(input->keyboard, &keyboard_listener, + input); + } + else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && input->keyboard) { + wl_keyboard_destroy(input->keyboard); + input->keyboard = NULL; + } +} + +static const struct wl_seat_listener seat_listener = { + seat_handle_capabilities, +}; + +static void +output_handle_geometry(void *data, struct wl_output *wl_output, int x, int y, + int physical_width, int physical_height, int subpixel, + const char *make, const char *model, int32_t transform) +{ + struct output *output = data; + + output->x = x; + output->y = y; + + print_log("CLIENT: Output[geometry] x/y=%d/%d,trans=%d", x, y, transform); +} + +static void +output_handle_mode(void *data, struct wl_output *wl_output, uint32_t flags, + int width, int height, int refresh) +{ + struct output *output = data; + + if (flags & WL_OUTPUT_MODE_CURRENT) { + output->width = width; + output->height = height; + print_log("CLIENT: Output[mode] w/h=%d/%d", width, height); + } +} + +static const struct wl_output_listener output_listener = { + output_handle_geometry, + output_handle_mode +}; + +static void +cb_input_capabilities(void *data, struct ico_exinput *ico_exinput, + const char *device, int32_t type, const char *swname, int32_t input, + const char *codename, int32_t code) +{ + print_log("CLIENT: Event[input_capabilities] device=%s type=%d sw=%s input=%d " + "code=%s[%d]", device, type, swname, input, codename, code); +} + +static void +cb_input_code(void *data, struct ico_exinput *ico_exinput, + const char *device, int32_t input, const char *codename, int32_t code) +{ + print_log("CLIENT: Event[input_code] device=%s input=%d code=%s[%d]", + device, input, codename, code); +} + +static void +cb_input_input(void *data, struct ico_exinput *ico_exinput, uint32_t time, + const char *device, int32_t input, int32_t code, int32_t state) +{ + print_log("CLIENT: Event[input_input] device=%s input=%d code=%d state=%d", + device, input, code, state); +} + +static const struct ico_exinput_listener exinput_listener = { + cb_input_capabilities, + cb_input_code, + cb_input_input +}; + +static void +shell_surface_ping(void *data, struct wl_shell_surface *wl_shell_surface, uint32_t serial) +{ + print_log("CLIENT: shell_surface_ping: surface=%08x serial=%d", + (int)wl_shell_surface, serial); +} + +static void +shell_surface_configure(void *data, struct wl_shell_surface *wl_shell_surface, + uint32_t edges, int32_t width, int32_t height) +{ + print_log("CLIENT: shell_surface_configure: surface=%08x edg=%x, width=%d height=%d", + (int)wl_shell_surface, edges, width, height); +} + +static void +shell_surface_popup_done(void *data, struct wl_shell_surface *wl_shell_surface) +{ + print_log("CLIENT: shell_surface_popup_done: surface=%08x", (int)wl_shell_surface); +} + +static const struct wl_shell_surface_listener shell_surface_listener = { + shell_surface_ping, + shell_surface_configure, + shell_surface_popup_done +}; + +static void +handle_global(void *data, struct wl_registry *registry, uint32_t id, + const char *interface, uint32_t version) +{ + struct display *display = data; + struct input *input; + struct output *output; + + print_log("CLIENT: handle_global: interface=<%s> id=%d", interface, (int)id); + + if (strcmp(interface, "wl_compositor") == 0) { + display->compositor = + wl_registry_bind(display->registry, + id, &wl_compositor_interface, 1); + } + else if (strcmp(interface, "wl_seat") == 0) { + input = calloc(1, sizeof *input); + input->display = display; + input->seat = wl_registry_bind(display->registry, id, + &wl_seat_interface, 1); + input->pointer_focus = NULL; + input->keyboard_focus = NULL; + + wl_seat_add_listener(input->seat, &seat_listener, input); + display->input = input; + } + else if (strcmp(interface, "wl_output") == 0) { + output = malloc(sizeof *output); + output->display = display; + output->output = wl_registry_bind(display->registry, + id, &wl_output_interface, 1); + wl_output_add_listener(output->output, + &output_listener, output); + display->output = output; + + print_log("CLIENT: created output global %p", display->output); + } + else if (strcmp(interface, "wl_shell") == 0) { + display->shell = + wl_registry_bind(display->registry, + id, &wl_shell_interface, 1); + } + else if (strcmp(interface, "ico_ivi_shell") == 0) { + display->ico_ivi_shell = + wl_registry_bind(display->registry, + id, &ico_ivi_shell_interface, 1); + } + else if (strcmp(interface, "ico_window_mgr") == 0) { + display->ico_window_mgr = + wl_registry_bind(display->registry, + id, &ico_window_mgr_interface, 1); + print_log("CLIENT: created window_mgr global %p", display->ico_window_mgr); + } + else if (strcmp(interface, "ico_exinput") == 0) { + display->ico_exinput = + wl_registry_bind(display->registry, + id, &ico_exinput_interface, 1); + ico_exinput_add_listener(display->ico_exinput, + &exinput_listener, display); + print_log("CLIENT: created exinput global %p", display->ico_exinput); + } +} + +static const struct wl_registry_listener registry_listener = { + handle_global +}; + +static void +surface_enter(void *data, struct wl_surface *wl_surface, struct wl_output *output) +{ + struct surface *surface = data; + + surface->output = wl_output_get_user_data(output); + + print_log("CLIENT: got surface enter, output %p", surface->output); +} + +static void +surface_leave(void *data, struct wl_surface *wl_surface, struct wl_output *output) +{ + struct surface *surface = data; + + surface->output = NULL; + + print_log("CLIENT: got surface leave, output %p", wl_output_get_user_data(output)); +} + +static const struct wl_surface_listener surface_listener = { + surface_enter, + surface_leave +}; + +static void +send_keyboard_state(struct display *display) +{ + int focus = display->input->keyboard_focus != NULL; + + if (focus) { + assert(display->input->keyboard_focus == display->surface); + } + + wl_display_flush(display->display); + + print_log("CLIENT: keyboard_state %u %u %d", + display->input->last_key, display->input->last_key_state, focus); + + wl_display_roundtrip(display->display); +} + +static void +send_button_state(struct display *display) +{ + wl_display_roundtrip(display->display); + + print_log("CLIENT: button_state %u", display->input->button_mask); + + wl_display_roundtrip(display->display); +} + +static void +send_state(struct display* display) +{ + int visible = display->surface->output != NULL; + wl_fixed_t x = wl_fixed_from_int(-1); + wl_fixed_t y = wl_fixed_from_int(-1); + + if (display->input->pointer_focus != NULL) { + assert(display->input->pointer_focus == display->surface); + x = wl_fixed_from_double(display->input->x); + y = wl_fixed_from_double(display->input->y); + } + + if (visible) { + /* FIXME: this fails on multi-display setup */ + /* assert(display->surface->output == display->output); */ + } + + wl_display_flush(display->display); + + print_log("CLIENT: state %d %d %d", x, y, visible); + + wl_display_roundtrip(display->display); +} + +static void +create_surface(struct display *display) +{ + struct surface *surface; + + surface = malloc(sizeof *surface); + assert(surface); + surface->display = display; + display->surface = surface; + surface->surface = wl_compositor_create_surface(display->compositor); + wl_surface_add_listener(surface->surface, &surface_listener, surface); + + if (display->shell) { + surface->shell_surface = + wl_shell_get_shell_surface(display->shell, surface->surface); + if (surface->shell_surface) { + wl_shell_surface_add_listener(surface->shell_surface, + &shell_surface_listener, display); + wl_shell_surface_set_toplevel(surface->shell_surface); + } + } + wl_display_flush(display->display); + + print_log("CLIENT: create surface %d shell=%08x", + wl_proxy_get_id((struct wl_proxy *) surface->surface), + (int)surface->shell_surface); + + poll(NULL, 0, 100); /* Wait for next frame where we'll get events. */ + + wl_display_roundtrip(display->display); + + surface->dpy = opengl_init(display->display, &surface->conf, &surface->ctx); + if (surface->dpy) { + surface->egl_surface = opengl_create_window(display->display, surface->surface, + surface->dpy, surface->conf, + surface->ctx, display->init_width, + display->init_height, display->init_color); + clear_surface(display); + print_log("CLIENT: created egl_surface %08x", (int)surface->egl_surface); + } +} + +static void +clear_surface(struct display *display) +{ + if (! display->surface) { + create_surface(display); + } + else { + opengl_clear_window(display->init_color); + opengl_swap_buffer(display->display, + display->surface->dpy, display->surface->egl_surface); + } +} + +int main(int argc, char *argv[]) +{ + struct display *display; + char buf[256]; + int ret, fd; + int msec; + int postsec = 0; + + display = malloc(sizeof *display); + assert(display); + memset((char *)display, 0, sizeof *display); + + display->init_width = 640; + display->init_height = 480; + display->init_color = 0xA0A08020; + for (fd = 1; fd < argc; fd++ ) { + if (argv[fd][0] == '-') { + if (strncasecmp(argv[fd], "-color=", 7) == 0) { + display->init_color = strtoul(&argv[fd][7], (char **)0, 0); + } + else if (strncasecmp(argv[fd], "-width=", 7) == 0) { + display->init_width = strtol(&argv[fd][7], (char **)0, 0); + } + else if (strncasecmp(argv[fd], "-height=", 8) == 0) { + display->init_height = strtol(&argv[fd][8], (char **)0, 0); + } + else if (strncasecmp(argv[fd], "-display=", 9) == 0) { + strncpy(display->connect, &argv[fd][9], MAX_CON_NAME); + } + else if (strncasecmp(argv[fd], "-postsleep=", 11) == 0) { + postsec = sec_str_2_value(&argv[fd][11]); + } + else if (strncasecmp(argv[fd], "-prompt=", 8) == 0) { + if (argv[fd][8] == 0) { + display->prompt = argv[fd][8] & 1; + } + else { + display->prompt = 1; + } + } + } + } + + if (display->connect[0]) { + display->display = wl_display_connect(display->connect); + } + else { + display->display = wl_display_connect(NULL); + } + assert(display->display); + + display->registry = wl_display_get_registry(display->display); + wl_registry_add_listener(display->registry, + ®istry_listener, display); + wl_display_dispatch(display->display); + + fd = 0; + + while (1) { + sleep_with_wayland(display->display, 20); + if (display->prompt) { + printf("CLIENT: "); fflush(stdout); + } + ret = getdata(display->ico_window_mgr, "CLIENT: ", fd, buf, sizeof(buf)); + if (ret < 0) { + fprintf(stderr, "CLIENT: read error: fd %d, %m\n", + fd); + break; + } + if (ret == 0) continue; + wl_display_flush(display->display); + + if ((strncasecmp(buf, "bye", 3) == 0) || + (strncasecmp(buf, "quit", 4) == 0) || + (strncasecmp(buf, "end", 3) == 0)) { + /* Exit, end of test */ + break; + } + else if (strncasecmp(buf, "create-surface", ret) == 0) { + create_surface(display); + } + else if (strncasecmp(buf, "clear-surface", 13) == 0) { + display->init_color = strtoul(&buf[14], (char **)0, 0); + clear_surface(display); + } + else if (strncasecmp(buf, "send-state", ret) == 0) { + send_state(display); + } + else if (strncasecmp(buf, "send-button-state", ret) == 0) { + send_button_state(display); + } + else if (strncasecmp(buf, "send-keyboard-state", ret) == 0) { + send_keyboard_state(display); + } + else if (strncasecmp(buf, "sleep", 5) == 0) { + msec = sec_str_2_value(&buf[6]); + sleep_with_wayland(display->display, msec); + } + else { + print_log("CLIENT: unknown command[%s]", buf); + return(-1); + } + } + if (postsec > 0) { + sleep_with_wayland(display->display, postsec); + } + + exit(0); +} + diff --git a/tests/test-common.c b/tests/test-common.c new file mode 100644 index 0000000..5b83995 --- /dev/null +++ b/tests/test-common.c @@ -0,0 +1,411 @@ +/* + * Copyright (c) 2013, TOYOTA MOTOR CORPORATION. + * + * This program is licensed under the terms and conditions of the + * Apache License, version 2.0. The full text of the Apache License is at + * http://www.apache.org/licenses/LICENSE-2.0 + * + */ +/** + * @brief Uint test common routines + * + * @date Feb-08-2013 + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include <sys/types.h> +#include <time.h> +#include <errno.h> +#include <wayland-client.h> +#include <ico_window_mgr-client-protocol.h> +#include "test-common.h" + +/*--------------------------------------------------------------------------*/ +/** + * @brief getdata: Input data string + * + * @param[in] window_mgr ico_window_mgr, if Null, output to stderr + * @param[in] prompt Echoback printout header + * @param[in] fd Input file discriptor + * @param[in] buf Input buffer + * @param[in] size Buffer size + * @return Number of input characters + * @retval >= 0 Number of input characters + * @retval < 0 Input error + */ +/*--------------------------------------------------------------------------*/ +int +getdata(void *window_mgr, const char *prompt, int fd, char *buf, const int size) +{ + int ret; + int i, j; + + j = -1; + for (i = 0; i < (size-1); i++) { + ret = read(fd, &buf[i], 1); + + if (ret < 0) { + return(ret); + } + + if ((buf[i] == '\n') || (buf[i] == '\r')) break; + if (buf[i] == '\t') { + buf[i] = ' '; + } + if ((buf[i] == '#') && (j < 0)) { + j = i; + } + } + buf[i] = 0; + print_log("%s%s", prompt, buf); + + /* Delete trailing spaces */ + if (j >= 0) { + for (; j > 0; j--) { + if (buf[j-1] != ' ') break; + } + buf[j] = 0; + i = j; + } + + /* Delete header spaces */ + for (j = 0; buf[j]; j++) { + if (buf[j] != ' ') break; + } + if (j > 0) { + strcpy( buf, &buf[j] ); + i -= j; + } + return(i); +} + +/*--------------------------------------------------------------------------*/ +/** + * @brief print_log: Weston log output + * + * @param[in] fmt printf format + * @param[in] ... printf arguments + * @return None + */ +/*--------------------------------------------------------------------------*/ +void +print_log(const char *fmt, ...) +{ + va_list ap; + char log[128]; + struct timeval NowTime; + extern long timezone; + static int sTimeZone = (99*60*60); + + va_start(ap, fmt); + vsnprintf(log, sizeof(log)-2, fmt, ap); + va_end(ap); + + gettimeofday( &NowTime, (struct timezone *)0 ); + if( sTimeZone > (24*60*60) ) { + tzset(); + sTimeZone = timezone; + } + NowTime.tv_sec -= sTimeZone; + fprintf(stderr, "[%02d:%02d:%02d.%03d@%d] %s\n", + (int)((NowTime.tv_sec/3600) % 24), + (int)((NowTime.tv_sec/60) % 60), + (int)(NowTime.tv_sec % 60), + (int)NowTime.tv_usec/1000, getpid(), log); +} + +/*--------------------------------------------------------------------------*/ +/** + * @brief wayland_dispatch_nonblock: Read from wayland if receive data exist + * + * @param[in] display Wayland connection + * @return None + */ +/*--------------------------------------------------------------------------*/ +void +wayland_dispatch_nonblock(struct wl_display *display) +{ + int nread; + + /* Check wayland input */ + do { + /* Flush send data */ + wl_display_flush(display); + + nread = 0; + if (ioctl(wl_display_get_fd(display), FIONREAD, &nread) < 0) { + nread = 0; + } + if (nread >= 8) { + /* Read event from wayland */ + wl_display_dispatch(display); + } + } while (nread > 0); +} + +/*--------------------------------------------------------------------------*/ +/** + * @brief sleep_with_wayland: Sleep and receive wayland event + * + * @param[in] display Wayland connection + * @param[in] msec Sleep time (miri-sec) + * @return None + */ +/*--------------------------------------------------------------------------*/ +void +sleep_with_wayland(struct wl_display *display, int msec) +{ + int nread; + int fd; + + + fd = wl_display_get_fd(display); + + do { + /* Flush send data */ + wl_display_flush(display); + + /* Check wayland input */ + nread = 0; + if (ioctl(fd, FIONREAD, &nread) < 0) { + nread = 0; + } + if (nread >= 8) { + /* Read event from wayland */ + wl_display_dispatch(display); + } + msec -= 20; + if (msec >= 0) usleep(20*1000); + } while (msec > 0); +} + +/*--------------------------------------------------------------------------*/ +/** + * @brief wait_with_wayland: Wait for end and receive wayland event + * + * @param[in] display Wayland connection + * @param[in] msec Maximum wait time (miri-sec) + * @param[in] endflag End flag address + * @return None + */ +/*--------------------------------------------------------------------------*/ +void +wait_with_wayland(struct wl_display *display, int msec, int *endflag) +{ + int nread; + int fd; + + fd = wl_display_get_fd(display); + + do { + /* Flush send data */ + wl_display_flush(display); + + /* Check wayland input */ + nread = 0; + if (ioctl(fd, FIONREAD, &nread) < 0) { + nread = 0; + } + if (nread >= 8) { + /* Read event from wayland */ + wl_display_dispatch(display); + } + msec -= 20; + if (msec >= 0) usleep(20*1000); + } while ((*endflag == 0) && (msec > 0)); +} + +/*--------------------------------------------------------------------------*/ +/** + * @brief sec_str_2_value: Convert seconds string to value + * + * @param[in] ssec Time ("sec.msec") + * @return miri-second + */ +/*--------------------------------------------------------------------------*/ +int +sec_str_2_value(const char *ssec) +{ + int sec; + int msec; + int n; + char *errp = NULL; + + sec = strtol(ssec, &errp, 0) * 1000; + if ((errp != NULL) && (*errp == '.')) { + msec = 0; + n = 0; + for (errp++; *errp; errp++) { + if ((*errp < '0') || (*errp > '9')) break; + msec = msec * 10 + *errp - '0'; + n++; + if (n >= 3) break; + } + if (n == 1) msec *= 100; + if (n == 2) msec *= 10; + sec += msec; + } + return(sec); +} + +/*--------------------------------------------------------------------------*/ +/** + * @brief opengl_init: Initialize OpenGL ESv2/EGL + * + * @param[in] display Wayland connection + * @param[out] rconf EGL configuration + * @param[out] rctx EGL context + * @return EGL display + * @retval != NULL EGL display + * @retval == NULL OpenGL/EGL initialize error + */ +/*--------------------------------------------------------------------------*/ +EGLDisplay +opengl_init(struct wl_display *display, EGLConfig *rconf, EGLContext *rctx) +{ + EGLDisplay dpy; /* EGL dsplay id */ + EGLint major, minor; + EGLint num_configs; + EGLConfig conf = 0; + EGLContext ctx; + + static const EGLint config_attribs[] = { + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_RED_SIZE, 1, + EGL_GREEN_SIZE, 1, + EGL_BLUE_SIZE, 1, + EGL_ALPHA_SIZE, 1, + EGL_DEPTH_SIZE, 1, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL_NONE + }; + static const EGLint context_attribs[] = { + EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE + }; + + dpy = eglGetDisplay((EGLNativeDisplayType)display); + if (! dpy) { + fprintf(stderr, "eglGetDisplay Error\n"); + return NULL; + } + + if (eglInitialize(dpy, &major, &minor) == EGL_FALSE) { + fprintf(stderr, "eglInitialize Error\n"); + return NULL; + } + + if (eglBindAPI(EGL_OPENGL_ES_API) == EGL_FALSE) { + fprintf(stderr, "eglBindAPI Error\n"); + return NULL; + } + + if (eglChooseConfig(dpy, config_attribs, &conf, 1, &num_configs) == EGL_FALSE) { + fprintf(stderr, "eglChooseConfig Error\n"); + return NULL; + } + + ctx = eglCreateContext(dpy, conf, EGL_NO_CONTEXT, context_attribs); + if (! ctx) { + fprintf(stderr, "eglCreateContext Error\n"); + return NULL; + } + *rconf = conf; + *rctx = ctx; + + wayland_dispatch_nonblock(display); + + return(dpy); +} + +/*--------------------------------------------------------------------------*/ +/** + * @brief opengl_create_window: Create OpenGL/EGL window + * + * @param[in] display Wayland connection + * @param[in] surface Wayland surface + * @param[in] dpy EGL display + * @param[in] conf EGL configuration + * @param[in] ctx EGL context + * @param[in] width Widown width + * @param[in] height Window height + * @param[in] color Initiale color(A<<24|R<<16|G<<8|B) + * @return EGL surface + * @retval != NULL EGL surface + * @retval == NULL Create window error + */ +/*--------------------------------------------------------------------------*/ +EGLSurface +opengl_create_window(struct wl_display *display, struct wl_surface *surface, + EGLDisplay dpy, EGLConfig conf, EGLContext ctx, + const int width, const int height, const int color) +{ + struct wl_egl_window *egl_window; + EGLSurface egl_surface; + + static const EGLint surface_attribs[] = { + EGL_ALPHA_FORMAT, EGL_ALPHA_FORMAT_PRE, EGL_NONE + }; + + egl_window = wl_egl_window_create(surface, width, height); + egl_surface = eglCreateWindowSurface(dpy, conf, (EGLNativeWindowType)egl_window, + surface_attribs); + eglMakeCurrent(dpy, egl_surface, egl_surface, ctx); + glViewport(0, 0, width, height); + + wayland_dispatch_nonblock(display); + + opengl_clear_window(color); + + opengl_swap_buffer(display, dpy, egl_surface); + + return(egl_surface); +} + +/*--------------------------------------------------------------------------*/ +/** + * @brief opengl_clear_window: OpenGL window clear + * + * @param[in] color Initiale color(A<<24|R<<16|G<<8|B) + * @return None + */ +/*--------------------------------------------------------------------------*/ +void +opengl_clear_window(const unsigned int color) +{ + double r, g, b, a; + + r = (double)((color>>16) & 0x0ff); + r = r / 256.0; + g = (double)((color>>8) & 0x0ff); + g = g / 256.0; + b = (double)(color & 0x0ff); + b = b / 256.0; + a = (double)((color>>24) & 0x0ff); + a = (a + 1.0) / 256.0; + + glClearColor(r, g, b, a); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT| GL_STENCIL_BUFFER_BIT); +} + +/*--------------------------------------------------------------------------*/ +/** + * @brief opengl_create_window: Create OpenGL/EGL window + * + * @param[in] display Wayland connection + * @param[in] dpy EGL display + * @param[in] egl_surface EGL surface + * @return None + */ +/*--------------------------------------------------------------------------*/ +void +opengl_swap_buffer(struct wl_display *display, EGLDisplay dpy, EGLSurface egl_surface) +{ + eglSwapBuffers(dpy, egl_surface); + + wayland_dispatch_nonblock(display); +} diff --git a/tests/test-common.h b/tests/test-common.h new file mode 100644 index 0000000..a17e3ad --- /dev/null +++ b/tests/test-common.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2013, TOYOTA MOTOR CORPORATION. + * + * This program is licensed under the terms and conditions of the + * Apache License, version 2.0. The full text of the Apache License is at + * http://www.apache.org/licenses/LICENSE-2.0 + * + */ +/** + * @brief Header file for uint test common routines + * + * @date Feb-08-2013 + */ + +#ifndef _TEST_COMMON_H_ +#define _TEST_COMMON_H_ + +#include <GLES2/gl2.h> /* OpenGL ES 2.x */ +#include <EGL/egl.h> /* EGL */ +#include <wayland-client.h> /* Wayland client library */ +#include <wayland-egl.h> /* Wayland EGL library */ +#include <wayland-util.h> /* Wayland Misc library */ + +/* Function prototype */ +int getdata(void *window_mgr, const char *prompt, int fd, char *buf, const int size); +void print_log(const char *fmt, ...); +void wayland_dispatch_nonblock(struct wl_display *display); +void sleep_with_wayland(struct wl_display *display, int msec); +void wait_with_wayland(struct wl_display *display, int msec, int *endflag); +int sec_str_2_value(const char *ssec); +EGLDisplay opengl_init(struct wl_display *display, EGLConfig *rconf, EGLContext *rctx); +EGLSurface opengl_create_window(struct wl_display *display, struct wl_surface *surface, + EGLDisplay dpy, EGLConfig conf, EGLContext ctx, + const int width, const int height, const int color); +void opengl_clear_window(const unsigned int color); +void opengl_swap_buffer(struct wl_display *display, EGLDisplay dpy, EGLSurface egl_surface); + +#endif /*_TEST_COMMON_H_*/ diff --git a/tests/test-homescreen.c b/tests/test-homescreen.c new file mode 100644 index 0000000..9b7fc68 --- /dev/null +++ b/tests/test-homescreen.c @@ -0,0 +1,1464 @@ +/* + * Copyright (c) 2013, TOYOTA MOTOR CORPORATION. + * + * This program is licensed under the terms and conditions of the + * Apache License, version 2.0. The full text of the Apache License is at + * http://www.apache.org/licenses/LICENSE-2.0 + * + */ +/** + * @brief HomeScreen for uint test of Weston(Wayland) IVI plugins + * + * @date Feb-08-2013 + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <assert.h> +#include <poll.h> +#include <errno.h> +#include <sys/ioctl.h> +#include <sys/ipc.h> +#include <sys/msg.h> +#include <sys/time.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <signal.h> +#include <linux/input.h> +#include <wayland-client.h> +#include "ico_ivi_shell-client-protocol.h" +#include "ico_window_mgr-client-protocol.h" +#include "ico_input_mgr-client-protocol.h" +#include "test-common.h" + +#define MAX_APPID 128 +#define ICO_IVI_MAX_COORDINATE 16383 + +struct surface_name { + struct surface_name *next; + int surfaceid; + int pid; + char appid[MAX_APPID]; + int x; + int y; + int width; + int height; + int visible; +}; + +#define MAX_CON_NAME 127 + +struct display { + struct wl_display *display; + struct wl_registry *registry; + struct wl_compositor *compositor; + struct wl_shell *shell; + struct ico_ivi_shell *ico_ivi_shell; + struct ico_window_mgr *ico_window_mgr; + struct ico_input_mgr_control *ico_input_mgr; + struct ico_input_mgr_device *ico_input_device; + struct ico_exinput *ico_exinput; + struct input *input; + struct output *output; + struct surface *surface; + struct surface_name *surface_name; + struct surface_name *bgsurface_name; + int bg_created; + int init_color; + int init_width; + int init_height; + int surface_created; + int surface_destroyed; + int prompt; + int visible_on_create; + char connect[MAX_CON_NAME+1]; +}; + +struct input { + struct display *display; + struct wl_seat *seat; + struct wl_pointer *pointer; + struct wl_keyboard *keyboard; + float x, y; + uint32_t button_mask; + struct surface *pointer_focus; + struct surface *keyboard_focus; + uint32_t last_key, last_key_state; +}; + +struct output { + struct display *display; + struct wl_output *output; + int x, y; + int width, height; +}; + +struct surface { + struct display *display; + struct wl_surface *surface; + struct wl_shell_surface *shell_surface; + struct output *output; + EGLDisplay dpy; + EGLConfig conf; + EGLContext ctx; + EGLSurface egl_surface; +}; + +static void clear_surface(struct display *display); + +static void +pointer_handle_enter(void *data, struct wl_pointer *pointer, + uint32_t serial, struct wl_surface *surface, + wl_fixed_t x, wl_fixed_t y) +{ + struct input *input = data; + + input->pointer_focus = wl_surface_get_user_data(surface); + input->x = wl_fixed_to_double(x); + input->y = wl_fixed_to_double(y); + print_log("HOMESCREEN: got pointer enter (%d,%d), surface %p", + (int)input->x, (int)input->y, surface); +} + +static void +pointer_handle_leave(void *data, struct wl_pointer *pointer, + uint32_t serial, struct wl_surface *surface) +{ + struct input *input = data; + + input->pointer_focus = NULL; + + print_log("HOMESCREEN: got pointer leave, surface %p", surface); +} + +static void +pointer_handle_motion(void *data, struct wl_pointer *pointer, + uint32_t time, wl_fixed_t x, wl_fixed_t y) +{ + struct input *input = data; + + input->x = wl_fixed_to_double(x); + input->y = wl_fixed_to_double(y); + + print_log("HOMESCREEN: got pointer motion (%d,%d)", (int)input->x, (int)input->y); +} + +static void +pointer_handle_button(void *data, struct wl_pointer *pointer, + uint32_t serial, uint32_t time, uint32_t button, uint32_t state_w) +{ + struct input *input = data; + uint32_t bit; + enum wl_pointer_button_state state = state_w; + + bit = 1 << (button - BTN_LEFT); + if (state == WL_POINTER_BUTTON_STATE_PRESSED) + input->button_mask |= bit; + else + input->button_mask &= ~bit; + print_log("HOMESCREEN: got pointer button %u %u", button, state_w); +} + +static void +pointer_handle_axis(void *data, struct wl_pointer *pointer, + uint32_t time, uint32_t axis, wl_fixed_t value) +{ + print_log("HOMESCREEN: got pointer axis %u %d", axis, value); +} + +static void +keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard, + uint32_t format, int fd, uint32_t size) +{ + close(fd); + print_log("HOMESCREEN: got keyboard keymap"); +} + +static void +keyboard_handle_enter(void *data, struct wl_keyboard *keyboard, + uint32_t serial, struct wl_surface *surface, struct wl_array *keys) +{ + struct input *input = data; + + input->keyboard_focus = wl_surface_get_user_data(surface); + print_log("HOMESCREEN: got keyboard enter, surface %p", surface); +} + +static void +keyboard_handle_leave(void *data, struct wl_keyboard *keyboard, + uint32_t serial, struct wl_surface *surface) +{ + struct input *input = data; + + input->keyboard_focus = NULL; + print_log("HOMESCREEN: got keyboard leave, surface %p", surface); +} + +static void +keyboard_handle_key(void *data, struct wl_keyboard *keyboard, + uint32_t serial, uint32_t time, uint32_t key, uint32_t state) +{ + struct input *input = data; + + input->last_key = key; + input->last_key_state = state; + + print_log("HOMESCREEN: got keyboard key %u %u", key, state); +} + +static void +keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard, + uint32_t serial, uint32_t mods_depressed, + uint32_t mods_latched, uint32_t mods_locked, uint32_t group) +{ + print_log("HOMESCREEN: got keyboard modifier"); +} + +static const struct wl_pointer_listener pointer_listener = { + pointer_handle_enter, + pointer_handle_leave, + pointer_handle_motion, + pointer_handle_button, + pointer_handle_axis, +}; + +static const struct wl_keyboard_listener keyboard_listener = { + keyboard_handle_keymap, + keyboard_handle_enter, + keyboard_handle_leave, + keyboard_handle_key, + keyboard_handle_modifiers, +}; + +static void +seat_handle_capabilities(void *data, struct wl_seat *seat, + enum wl_seat_capability caps) +{ + struct input *input = data; + + if ((caps & WL_SEAT_CAPABILITY_POINTER) && !input->pointer) { + input->pointer = wl_seat_get_pointer(seat); + wl_pointer_set_user_data(input->pointer, input); + wl_pointer_add_listener(input->pointer, &pointer_listener, + input); + } + else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && input->pointer) { + wl_pointer_destroy(input->pointer); + input->pointer = NULL; + } + + if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !input->keyboard) { + input->keyboard = wl_seat_get_keyboard(seat); + wl_keyboard_set_user_data(input->keyboard, input); + wl_keyboard_add_listener(input->keyboard, &keyboard_listener, + input); + } + else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && input->keyboard) { + wl_keyboard_destroy(input->keyboard); + input->keyboard = NULL; + } +} + +static const struct wl_seat_listener seat_listener = { + seat_handle_capabilities, +}; + +static void +surface_enter(void *data, struct wl_surface *wl_surface, struct wl_output *output) +{ + struct surface *surface = data; + + surface->output = wl_output_get_user_data(output); + + print_log("HOMESCREEN: got surface enter, output %p", surface->output); +} + +static void +surface_leave(void *data, struct wl_surface *wl_surface, struct wl_output *output) +{ + struct surface *surface = data; + + surface->output = NULL; + + print_log("HOMESCREEN: got surface leave, output %p", + wl_output_get_user_data(output)); +} + +static const struct wl_surface_listener surface_listener = { + surface_enter, + surface_leave +}; + +static void +create_surface(struct display *display) +{ + struct surface *surface; + int id; + + surface = malloc(sizeof *surface); + assert(surface); + surface->display = display; + display->surface = surface; + surface->surface = wl_compositor_create_surface(display->compositor); + wl_surface_add_listener(surface->surface, &surface_listener, surface); + + if (display->shell) { + surface->shell_surface = + wl_shell_get_shell_surface(display->shell, surface->surface); + if (surface->shell_surface) { + wl_shell_surface_set_toplevel(surface->shell_surface); + } + } + wl_display_flush(display->display); + + id = wl_proxy_get_id((struct wl_proxy *) surface->surface); + print_log("HOMESCREEN: create surface = %d", id); + + poll(NULL, 0, 100); /* Wait for next frame where we'll get events. */ + + wl_display_roundtrip(display->display); + + surface->dpy = opengl_init(display->display, &surface->conf, &surface->ctx); + if (surface->dpy) { + surface->egl_surface = opengl_create_window(display->display, surface->surface, + surface->dpy, surface->conf, + surface->ctx, display->init_width, + display->init_height, display->init_color); + clear_surface(display); + print_log("HOMESCREEN: created egl_surface %08x", (int)surface->egl_surface); + } +} + +static void +clear_surface(struct display *display) +{ + if (! display->surface) { + create_surface(display); + } + else { + opengl_clear_window(display->init_color); + opengl_swap_buffer(display->display, + display->surface->dpy, display->surface->egl_surface); + } +} + +static void +output_handle_geometry(void *data, struct wl_output *wl_output, int x, int y, + int physical_width, int physical_height, int subpixel, + const char *make, const char *model, int32_t transform) +{ + struct output *output = data; + + output->x = x; + output->y = y; +} + +static void +output_handle_mode(void *data, struct wl_output *wl_output, uint32_t flags, + int width, int height, int refresh) +{ + struct output *output = data; + + if (flags & WL_OUTPUT_MODE_CURRENT) { + struct display *display = output->display; + + output->width = width; + output->height = height; + + print_log("HOMESCREEN: Event[handle_mode] x/y=%d/%d bgsurf=%08x", + width, height, (int)display->bgsurface_name); + + display->init_width = width; + display->init_height = height; + + if (display->bgsurface_name) { + ico_window_mgr_set_positionsize(display->ico_window_mgr, + display->bgsurface_name->surfaceid, + 0, 0, width, height); + } + else if (display->bg_created == 0) { + display->bg_created = 9; + create_surface(output->display); + } + } +} + +static const struct wl_output_listener output_listener = { + output_handle_geometry, + output_handle_mode +}; + +static int +search_surface(struct display *display, const char *surfname) +{ + struct surface_name *p; + + p = display->surface_name; + while (p) { + if (strcmp(p->appid, surfname) == 0) break; + p = p->next; + } + + if (p) { + return(p->surfaceid); + } + else { + return(-1); + } +} + +static struct surface_name * +search_surfacename(struct display *display, const char *surfname) +{ + struct surface_name *p; + + p = display->surface_name; + while (p) { + if (strcmp(p->appid, surfname) == 0) break; + p = p->next; + } + return(p); +} + +static struct surface_name * +search_surfaceid(struct display *display, const int surfaceid) +{ + struct surface_name *p; + + p = display->surface_name; + while (p) { + if (p->surfaceid == surfaceid) { + return(p); + } + p = p->next; + } + return(NULL); +} + +static void +window_created(void *data, struct ico_window_mgr *ico_window_mgr, + uint32_t surfaceid, int32_t pid, const char *appid) +{ + struct display *display = data; + struct surface_name *p; + struct surface_name *fp; + + display->surface_created = 1; + p = display->surface_name; + fp = NULL; + while (p) { + if (p->surfaceid == (int)surfaceid) break; + fp = p; + p = p->next; + } + if (p) { + print_log("HOMESCREEN: Event[window_created] surface=%08x(app=%s) exist", + (int)surfaceid, appid); + } + else { + print_log("HOMESCREEN: Event[window_created] new surface=%08x(app=%s)", + (int)surfaceid, appid); + p = malloc(sizeof(struct surface_name)); + if (! p) { + return; + } + memset(p, 0, sizeof(struct surface_name)); + if (fp) { + fp->next = p; + } + else { + display->surface_name = p; + } + } + p->surfaceid = surfaceid; + p->pid = pid; + strncpy(p->appid, appid, MAX_APPID-1); + + /* Set default size and show */ + if (p->width > 0) { + ico_window_mgr_set_positionsize(display->ico_window_mgr, surfaceid, + p->x, p->y, p->width, p->height); + } + + print_log("HOMESCREEN: Created window[%08x] (app=%s)", (int)surfaceid, appid); + + if (strncasecmp(appid, "test-homescreen", 15) == 0) { + display->bgsurface_name = p; + if (display->bg_created == 1) { + display->bg_created = 9; + ico_window_mgr_set_positionsize(display->ico_window_mgr, surfaceid, + 0, 0, display->init_width, display->init_height); + } + ico_window_mgr_set_visible(display->ico_window_mgr, surfaceid, 1, 0); + print_log("HOMESCREEN: Created window[%08x] (app=%s) Visible", + (int)surfaceid, appid); + p->visible = 1; + } +} + +static void +window_destroyed(void *data, struct ico_window_mgr *ico_window_mgr, uint32_t surfaceid) +{ + struct display *display = data; + struct surface_name *p; + struct surface_name *fp; + + display->surface_destroyed = 1; + p = search_surfaceid(display, (int)surfaceid); + if (! p) { + print_log("HOMESCREEN: Event[window_destroyed] surface=%08x dose not exist", + (int)surfaceid); + } + else { + print_log("HOMESCREEN: Event[window_destroyed] surface=%08x", (int)surfaceid); + if (p == display->surface_name) { + display->surface_name = p->next; + } + else { + fp = display->surface_name; + while (fp) { + if (fp->next == p) { + fp->next = p->next; + break; + } + fp = fp->next; + } + } + free(p); + } +} + +static void +window_visible(void *data, struct ico_window_mgr *ico_window_mgr, + uint32_t surfaceid, int32_t visible, int32_t raise, int32_t hint) +{ + struct display *display = data; + struct surface_name *p; + + p = search_surfaceid(display, (int)surfaceid); + if (! p) { + print_log("HOMESCREEN: Event[window_visible] surface=%08x dose not exist", + (int)surfaceid); + } + else { + print_log("HOMESCREEN: Event[window_visible] surface=%08x " + "visible=%d raise=%d hint=%d", + (int)surfaceid, visible, raise, hint); + p->visible = visible; + if (hint == 0) { + ico_window_mgr_set_visible(display->ico_window_mgr, surfaceid, visible, 9); + } + } +} + +static void +window_configure(void *data, struct ico_window_mgr *ico_window_mgr, + uint32_t surfaceid, const char *appid, int32_t layer, + int32_t x, int32_t y, int32_t width, int32_t height, int32_t hint) +{ + struct display *display = data; + struct surface_name *p; + + print_log("HOMESCREEN: Event[window_configure] surface=%08x " + "app=%s x/y=%d/%d w/h=%d/%d hint=%d", + (int)surfaceid, appid, x, y, width, height, hint); + + p = search_surfaceid(display, (int)surfaceid); + if (! p) { + print_log("HOMESCREEN: Event[window_configure] surface=%08x(app=%s) new create", + (int)surfaceid, appid); + window_created(data, ico_window_mgr, surfaceid, 0, appid); + p = search_surfaceid(display, (int)surfaceid); + if (! p) { + print_log("HOMESCREEN: Event[window_configure] can not make table"); + return; + } + } +} + +static void +window_active(void *data, struct ico_window_mgr *ico_window_mgr, + uint32_t surfaceid, const uint32_t active) +{ + print_log("HOMESCREEN: Event[window_active] surface=%08x acive=%d", + (int)surfaceid, (int)active); +} + +static const struct ico_window_mgr_listener window_mgr_listener = { + window_created, + window_destroyed, + window_visible, + window_configure, + window_active +}; + +static void +cb_input_capabilities(void *data, struct ico_exinput *ico_exinput, + const char *device, int32_t type, const char *swname, int32_t input, + const char *codename, int32_t code) +{ + print_log("HOMESCREEN: Event[input_capabilities] device=%s type=%d sw=%s input=%d " + "code=%s[%d]", device, type, swname, input, codename, code); +} + +static void +cb_input_code(void *data, struct ico_exinput *ico_exinput, + const char *device, int32_t input, const char *codename, int32_t code) +{ + print_log("HOMESCREEN: Event[input_code] device=%s input=%d code=%s[%d]", + device, input, codename, code); +} + +static void +cb_input_input(void *data, struct ico_exinput *ico_exinput, uint32_t time, + const char *device, int32_t input, int32_t code, int32_t state) +{ + print_log("HOMESCREEN: Event[input_input] device=%s input=%d code=%d state=%d", + device, input, code, state); +} + +static const struct ico_exinput_listener exinput_listener = { + cb_input_capabilities, + cb_input_code, + cb_input_input +}; + +static void +handle_global(void *data, struct wl_registry *registry, uint32_t id, + const char *interface, uint32_t version) +{ + struct display *display = data; + struct input *input; + struct output *output; + + print_log("HOMESCREEN: handle_global: interface=<%s> id=%d", interface, (int)id); + + if (strcmp(interface, "wl_compositor") == 0) { + display->compositor = + wl_registry_bind(display->registry, + id, &wl_compositor_interface, 1); + } + else if (strcmp(interface, "wl_seat") == 0) { + input = calloc(1, sizeof *input); + input->display = display; + input->seat = wl_registry_bind(display->registry, id, + &wl_seat_interface, 1); + input->pointer_focus = NULL; + input->keyboard_focus = NULL; + + wl_seat_add_listener(input->seat, &seat_listener, input); + display->input = input; + } + else if (strcmp(interface, "wl_output") == 0) { + output = malloc(sizeof *output); + output->display = display; + output->output = wl_registry_bind(display->registry, + id, &wl_output_interface, 1); + wl_output_add_listener(output->output, + &output_listener, output); + display->output = output; + + print_log("HOMESCREEN: created output global %p", display->output); + } + else if (strcmp(interface, "wl_shell") == 0) { + display->shell = + wl_registry_bind(display->registry, + id, &wl_shell_interface, 1); + } + else if (strcmp(interface, "ico_ivi_shell") == 0) { + display->ico_ivi_shell = + wl_registry_bind(display->registry, + id, &ico_ivi_shell_interface, 1); + } + else if (strcmp(interface, "ico_window_mgr") == 0) { + display->ico_window_mgr = + wl_registry_bind(display->registry, + id, &ico_window_mgr_interface, 1); + ico_window_mgr_add_listener(display->ico_window_mgr, + &window_mgr_listener, display); + print_log("HOMESCREEN: created window_mgr global %p", display->ico_window_mgr); + + ico_window_mgr_set_eventcb(display->ico_window_mgr, 1); + } + else if (strcmp(interface, "ico_input_mgr_control") == 0) { + display->ico_input_mgr = + wl_registry_bind(display->registry, + id, &ico_input_mgr_control_interface, 1); + print_log("HOMESCREEN: created input_mgr global %p", display->ico_input_mgr); + } + else if (strcmp(interface, "ico_input_mgr_device") == 0) { + display->ico_input_device = + wl_registry_bind(display->registry, + id, &ico_input_mgr_device_interface, 1); + print_log("HOMESCREEN: created input_device global %p", display->ico_input_device); + } + else if (strcmp(interface, "ico_exinput") == 0) { + display->ico_exinput = + wl_registry_bind(display->registry, + id, &ico_exinput_interface, 1); + ico_exinput_add_listener(display->ico_exinput, + &exinput_listener, display); + print_log("HOMESCREEN: created exinput global %p", display->ico_exinput); + + ico_window_mgr_set_eventcb(display->ico_window_mgr, 1); + + display->bg_created = 1; + create_surface(display); + } +} + +static const struct wl_registry_listener registry_listener = { + handle_global +}; + +static char * +skip_spaces(char *buf) +{ + while ((*buf == ' ') || (*buf == '\t')) { + buf++; + } + return(buf); +} + +static int +pars_command(char *buf, char *pt[], const int len) +{ + char *p; + int narg; + + memset(pt, 0, sizeof(int *)*10); + p = buf; + for (narg = 0; narg < len; narg++) { + p = skip_spaces(p); + if (*p == 0) break; + pt[narg] = p; + for (; *p; p++) { + if ((*p == ' ') || (*p == '\t') || + (*p == '=') || (*p == ',')) break; + } + if (*p == 0) { + narg++; + break; + } + *p = 0; + p++; + } + return (narg); +} + +static void +launch_app(struct display *display, char *buf) +{ + char sbuf[256]; + + display->surface_created = 0; + display->surface_destroyed = 0; + snprintf(sbuf, sizeof(sbuf)-1, "%s &", skip_spaces(buf)); + if (system(sbuf) < 0) { + print_log("HOMESCREEN: Can not launch application[%s]", sbuf); + } + else { + sleep_with_wayland(display->display, 500); + } +} + +static void +kill_app(struct display *display, char *buf) +{ + char *args[10]; + int narg; + struct surface_name *p; + struct surface_name *fp; + + narg = pars_command(buf, args, 10); + if (narg >= 1) { + p = search_surfacename(display, args[0]); + if (kill(p->pid, SIGINT) < 0) { + print_log("HOMESCREEN: kill[%s.%d] Application dose not exist", + p->appid, p->pid); + } + else { + sleep_with_wayland(display->display, 300); + p = search_surfacename(display, args[0]); + if ((p != NULL) && (kill(p->pid, SIGTERM) >= 0)) { + sleep_with_wayland(display->display, 200); + p = search_surfacename(display, args[0]); + if (p) { + kill(p->pid, SIGKILL); + sleep_with_wayland(display->display, 200); + } + } + } + p = search_surfacename(display, args[0]); + if (p) { + if (p == display->surface_name) { + display->surface_name = p->next; + } + else { + fp = display->surface_name; + while (fp) { + if (fp->next == p) { + fp->next = p->next; + break; + } + } + } + free(p); + } + } + else { + print_log("HOMESCREEN: kill command[kill appid] has no argument"); + } +} + +static void +layer_surface(struct display *display, char *buf) +{ + char *args[10]; + int narg; + int surfaceid; + int layerid; + + narg = pars_command(buf, args, 10); + if (narg >= 2) { + surfaceid = search_surface(display, args[0]); + layerid = strtol(args[1], (char **)0, 0); + if ((surfaceid >= 0) && (layerid >= 0)) { + print_log("HOMESCREEN: set_window_layer(%s,%08x)", + args[0], surfaceid, layerid); + ico_window_mgr_set_window_layer(display->ico_window_mgr, surfaceid, layerid); + } + else { + print_log("HOMESCREEN: Unknown surface(%s) at layer command", args[0]); + } + } + else { + print_log("HOMESCREEN: layer command[layer appid layerid] has no argument"); + } +} + +static void +positionsize_surface(struct display *display, char *buf) +{ + char *args[10]; + int narg; + int surfaceid; + int x, y, width, height; + + narg = pars_command(buf, args, 10); + if (narg >= 5) { + surfaceid = search_surface(display, args[0]); + x = strtol(args[1], (char **)0, 0); + y = strtol(args[2], (char **)0, 0); + width = strtol(args[3], (char **)0, 0); + height = strtol(args[4], (char **)0, 0); + if ((surfaceid >= 0) && (x >= 0) && (y >=0) && (width >= 0) && (height >=0)) { + print_log("HOMESCREEN: set_positionsize(%s,%08x,%d,%d,%d,%d)", + args[0], surfaceid, x, y, width, height); + ico_window_mgr_set_positionsize(display->ico_window_mgr, surfaceid, + x, y, width, height); + } + else { + print_log("HOMESCREEN: Unknown surface(%s) at positionsize command", + args[0]); + } + } + else { + print_log("HOMESCREEN: positionsize command" + "[positionsize appid x y width heigh] has no argument"); + } +} + +static void +move_surface(struct display *display, char *buf) +{ + char *args[10]; + int narg; + int surfaceid; + int x, y; + + narg = pars_command(buf, args, 10); + if (narg >= 3) { + surfaceid = search_surface(display, args[0]); + x = strtol(args[1], (char **)0, 0); + y = strtol(args[2], (char **)0, 0); + if ((surfaceid >= 0) && (x >= 0) && (y >=0)) { + print_log("HOMESCREEN: move(%s,%08x,%d,%d)", args[0], surfaceid, x, y); + ico_window_mgr_set_positionsize(display->ico_window_mgr, surfaceid, + x, y, + ICO_IVI_MAX_COORDINATE+1, ICO_IVI_MAX_COORDINATE+1); + } + else { + print_log("HOMESCREEN: Unknown surface(%s) at move command", args[0]); + } + } + else { + print_log("HOMESCREEN: move command[positionsize appid x y] has no argument"); + } +} + +static void +resize_surface(struct display *display, char *buf) +{ + char *args[10]; + int narg; + int surfaceid; + int width, height; + + narg = pars_command(buf, args, 10); + if (narg >= 3) { + surfaceid = search_surface(display, args[0]); + width = strtol(args[1], (char **)0, 0); + height = strtol(args[2], (char **)0, 0); + if ((surfaceid >= 0) && (width >= 0) && (height >=0)) { + print_log("HOMESCREEN: resize(%s,%08x,%d,%d)", args[0], surfaceid, width, height); + ico_window_mgr_set_positionsize(display->ico_window_mgr, surfaceid, + ICO_IVI_MAX_COORDINATE+1, ICO_IVI_MAX_COORDINATE+1, + width, height); + } + else { + print_log("HOMESCREEN: Unknown surface(%s) at resize command", args[0]); + } + } + else { + print_log("HOMESCREEN: positionsize command" + "[resize appid width heigh] has no argument"); + } +} + +static void +visible_surface(struct display *display, char *buf) +{ + char *args[10]; + int narg; + int surfaceid; + int visible; + int raise; + + narg = pars_command(buf, args, 10); + if (narg >= 3) { + surfaceid = search_surface(display, args[0]); + visible = strtol(args[1], (char **)0, 0); + raise = strtol(args[2], (char **)0, 0); + if ((surfaceid >= 0) && (visible >= 0) && (raise >=0)) { + print_log("HOMESCREEN: visible(%s,%08x,%d,%d)", + args[0], surfaceid, visible, raise); + ico_window_mgr_set_visible(display->ico_window_mgr, surfaceid, + visible, raise); + } + else { + print_log("HOMESCREEN: Unknown surface(%s) at visible command", args[0]); + } + } + else { + print_log("HOMESCREEN: visible command[visible appid visible raise] has no argument"); + } +} + +static void +show_surface(struct display *display, char *buf, const int show) +{ + char *args[10]; + int narg; + int surfaceid; + + narg = pars_command(buf, args, 10); + if (narg >= 1) { + surfaceid = search_surface(display, args[0]); + if (surfaceid >= 0) { + if (show) { + print_log("HOMESCREEN: show(%s,%08x)", args[0], surfaceid); + ico_window_mgr_set_visible(display->ico_window_mgr, surfaceid, 1, 9); + } + else { + print_log("HOMESCREEN: hide(%s,%08x)", args[0], surfaceid); + ico_window_mgr_set_visible(display->ico_window_mgr, surfaceid, 0, 9); + } + } + else { + print_log("HOMESCREEN: Unknown surface(%s) at show/hide command", args[0]); + } + } + else { + print_log("HOMESCREEN: show command[show/hide appid] has no argument"); + } +} + +static void +raise_surface(struct display *display, char *buf, const int raise) +{ + char *args[10]; + int narg; + int surfaceid; + + narg = pars_command(buf, args, 10); + if (narg >= 1) { + surfaceid = search_surface(display, args[0]); + if (surfaceid >= 0) { + if (raise) { + print_log("HOMESCREEN: raise(%s,%08x)", args[0], surfaceid); + ico_window_mgr_set_visible(display->ico_window_mgr, surfaceid, 9, 1); + } + else { + print_log("HOMESCREEN: lower(%s,%08x)", args[0], surfaceid); + ico_window_mgr_set_visible(display->ico_window_mgr, surfaceid, 9, 0); + } + } + else { + print_log("HOMESCREEN: Unknown surface(%s) at raise/lower command", args[0]); + } + } + else { + print_log("HOMESCREEN: show command[raise/lower appid] has no argument"); + } +} + +static void +transition_surface(struct display *display, char *buf) +{ + char *args[10]; + int narg; + int surfaceid; + int transition; + + narg = pars_command(buf, args, 10); + if (narg >= 2) { + surfaceid = search_surface(display, args[0]); + transition = strtol(args[1], (char **)0, 0); + if ((surfaceid >= 0) && (transition >=0)) { + print_log("HOMESCREEN: transition(%s,%08x,%d)", args[0], surfaceid, transition); + ico_window_mgr_set_transition(display->ico_window_mgr, surfaceid, transition); + } + else { + print_log("HOMESCREEN: Unknown surface(%s) at transition command", args[0]); + } + } + else { + print_log("HOMESCREEN: transition command" + "[transition appid transition] has no argument"); + } +} + +static void +visible_layer(struct display *display, char *buf) +{ + char *args[10]; + int narg; + int layer; + int visible; + + narg = pars_command(buf, args, 10); + if (narg >= 2) { + layer = strtol(args[0], (char **)0, 0); + visible = strtol(args[1], (char **)0, 0); + ico_window_mgr_set_layer_visible(display->ico_window_mgr, layer, visible); + } + else { + print_log("HOMESCREEN: layer_visible command" + "[layer_visible layer visible] has no argument"); + } +} + +static void +input_add(struct display *display, char *buf) +{ + char *args[10]; + int narg; + int input; + int fix; + + narg = pars_command(buf, args, 10); + if (narg >= 3) { + input = strtol(args[1], (char **)0, 0); + if (narg >= 4) { + fix = strtol(args[3], (char **)0, 0); + } + else { + fix = 0; + } + if ((input >= 0) && (fix >=0)) { + print_log("HOMESCREEN: input_add(%s.%d to %s[%d])", args[0], input, args[2], fix); + ico_input_mgr_control_add_input_app(display->ico_input_mgr, + args[2], args[0], input, fix); + } + else { + print_log("HOMESCREEN: Unknown input(%s) at input_add command", args[1]); + } + } + else { + print_log("HOMESCREEN: input_add command[input_add device inputId appid fix] " + "has no argument"); + } +} + +static void +input_del(struct display *display, char *buf) +{ + char *args[10]; + int narg; + int input; + char wk1[32], wk2[32]; + + narg = pars_command(buf, args, 10); + if (narg >= 3) { + input = strtol(args[1], (char **)0, 0); + if (args[0][0] == '@') { + wk1[0] = 0; + args[0] = wk1; + } + if (args[2][0] == '@') { + wk2[0] = 0; + args[2] = wk2; + } + print_log("HOMESCREEN: input_del(%s.%d to %s)", args[0], input, args[2]); + ico_input_mgr_control_del_input_app(display->ico_input_mgr, + args[2], args[0], input); + } + else { + print_log("HOMESCREEN: input_del command[input_del device inputId appid] " + "has no argument"); + } +} + +static void +input_conf(struct display *display, char *buf) +{ + char *args[10]; + int narg; + int type; + int input; + int code; + char wk1[32], wk2[32]; + + narg = pars_command(buf, args, 10); + if (narg >= 4) { + type = strtol(args[1], (char **)0, 0); + input = strtol(args[3], (char **)0, 0); + if (narg >= 6) { + code = strtol(args[5], (char **)0, 0); + } + else { + code = 0; + args[4] = wk1; + strcpy(wk1, args[2]); + args[5] = wk2; + strcpy(wk2, "0"); + } + if ((type >= 0) && (input >= 0) && (code >=0)) { + ico_input_mgr_device_configure_input(display->ico_input_device, args[0], type, + args[2], input, args[4], code); + } + else { + print_log("HOMESCREEN: Unknown type(%s),input(%s) or code(%s) " + "at input_conf command", args[1], args[3], args[5]); + } + } + else { + print_log("HOMESCREEN: input_conf command[input_conf device type swname input " + "codename code] has no argument"); + } +} + +static void +input_code(struct display *display, char *buf) +{ + char *args[10]; + int narg; + int input; + int code; + + narg = pars_command(buf, args, 10); + if (narg >= 4) { + input = strtol(args[1], (char **)0, 0); + code = strtol(args[3], (char **)0, 0); + if ((input >= 0) && (code >= 0)) { + ico_input_mgr_device_configure_code(display->ico_input_device, args[0], input, + args[2], code); + } + else { + print_log("HOMESCREEN: Unknown input(%s) or code(%s) " + "at input_code command", args[1], args[3]); + } + } + else { + print_log("HOMESCREEN: input_conf command[input_code device input codename code] " + "has no argument"); + } +} + +static void +input_sw(struct display *display, char *buf) +{ + char *args[10]; + int narg; + int timems; + int input; + int code; + int state; + struct timeval stv; + + narg = pars_command(buf, args, 10); + if (narg >= 4) { + input = strtol(args[1], (char **)0, 0); + code = strtol(args[2], (char **)0, 0); + state = strtol(args[3], (char **)0, 0); + if ((input >= 0) && (state >= 0)) { + gettimeofday(&stv, (struct timezone *)NULL); + timems = (stv.tv_sec % 1000) * 1000 + (stv.tv_usec / 1000); + ico_input_mgr_device_input_event(display->ico_input_device, + timems, args[0], input, code, state); + } + else { + print_log("HOMESCREEN: Unknown input(%s),code(%s) or state(%s) " + "at input_sw command", args[1], args[2], args[3]); + } + } + else { + print_log("HOMESCREEN: input_sw command[input_sw device input code, state] " + "has no argument"); + } +} + +static void +send_event(const char *cmd) +{ + static int nmqinfo = 0; + static struct { + int mqkey; + int mqid; + } mqinfo[10]; + int mqkey; + int mqid; + struct { + long mtype; + char buf[240]; + } mqbuf; + int pt, i; + + if (cmd == NULL) { + return; + } + mqkey = 0; + for (pt = 0; cmd[pt]; pt++) { + if ((cmd[pt] >= '0') && (cmd[pt] <= '9')) { + mqkey = mqkey * 10 + cmd[pt] - '0'; + } + else { + break; + } + } + for (; cmd[pt] == ' '; pt++) ; + + if (mqkey <= 0) { + mqkey = 5551; + pt = 0; + } + for (i = 0; i < nmqinfo; i++) { + if (mqinfo[i].mqkey == mqkey) { + mqid = mqinfo[i].mqid; + break; + } + } + if (i >= nmqinfo) { + if (nmqinfo >= 10) { + fprintf(stderr, "HOMESCREEN: message queue(%d) overflow\n", mqkey); + return; + } + mqid = msgget(mqkey, 0); + if (mqid < 0) { + fprintf(stderr, "HOMESCREEN: message queue(%d(0x%x)) get error[%d]\n", + mqkey, mqkey, errno); + return; + } + mqinfo[nmqinfo].mqkey = mqkey; + mqinfo[nmqinfo].mqid = mqid; + nmqinfo ++; + } + + memset(&mqbuf, 0, sizeof(mqbuf)); + mqbuf.mtype = 1; + strncpy(mqbuf.buf, &cmd[pt], sizeof(mqbuf)-sizeof(long)); + + if (msgsnd(mqid, &mqbuf, sizeof(mqbuf)-sizeof(long), 0) < 0) { + fprintf(stderr, "HOMESCREEN: message queue(%d(0x%x)) send error[%d]\n", + mqkey, mqkey, errno); + return; + } +} + +/* + * Main Program + * + * usage: + * test-homescreen < test-case-data-file > test-result-output + */ +int main(int argc, char *argv[]) +{ + struct display *display; + char buf[256]; + int ret, fd; + int msec; + + display = malloc(sizeof *display); + assert(display); + memset((char *)display, 0, sizeof *display); + + display->init_width = 640; + display->init_height = 480; + display->init_color = 0xFF304010; + + for (fd = 1; fd < argc; fd++) { + if (argv[fd][0] == '-') { + if (strncasecmp(argv[fd], "-visible=", 9) == 0) { + display->visible_on_create = argv[fd][9] & 1; + } + else if (strncasecmp(argv[fd], "-display=", 9) == 0) { + strncpy(display->connect, &argv[fd][9], MAX_CON_NAME); + } + else if (strncasecmp(argv[fd], "-prompt=", 8) == 0) { + display->prompt = argv[fd][8] & 1; + } + } + } + + if (display->connect[0]) { + display->display = wl_display_connect(display->connect); + } + else { + display->display = wl_display_connect(NULL); + } + assert(display->display); + + display->registry = wl_display_get_registry(display->display); + wl_registry_add_listener(display->registry, + ®istry_listener, display); + wl_display_dispatch(display->display); + + fd = 0; + + while (1) { + sleep_with_wayland(display->display, 20); + if (display->prompt) { + printf("HOMESCREEN: "); fflush(stdout); + } + ret = getdata(display->ico_window_mgr, "HOMESCREEN: ", fd, buf, sizeof(buf)); + if (ret < 0) { + fprintf(stderr, "HOMESCREEN: read error: fd %d, %m\n", + fd); + return -1; + } + if (ret == 0) continue; + wl_display_flush(display->display); + + if ((strncasecmp(buf, "bye", 3) == 0) || + (strncasecmp(buf, "quit", 4) == 0) || + (strncasecmp(buf, "end", 3) == 0)) { + /* Exit, end of test */ + return 0; + } + else if (strncasecmp(buf, "launch", 6) == 0) { + /* Launch test application */ + launch_app(display, &buf[6]); + } + else if (strncasecmp(buf, "kill", 4) == 0) { + /* Launch test application */ + kill_app(display, &buf[4]); + } + else if (strncasecmp(buf, "layer_visible", 13) == 0) { + /* Change layer visiblety */ + visible_layer(display, &buf[13]); + } + else if (strncasecmp(buf, "layer", 5) == 0) { + /* layer change surface window */ + layer_surface(display, &buf[5]); + } + else if (strncasecmp(buf, "positionsize", 12) == 0) { + /* Move and Ressize surface window*/ + positionsize_surface(display, &buf[12]); + } + else if (strncasecmp(buf, "move", 4) == 0) { + /* Move surface window */ + move_surface(display, &buf[4]); + } + else if (strncasecmp(buf, "resize", 6) == 0) { + /* Resize surface window */ + resize_surface(display, &buf[6]); + } + else if (strncasecmp(buf, "visible", 7) == 0) { + /* Visible and Raise surface window*/ + visible_surface(display, &buf[7]); + } + else if (strncasecmp(buf, "show", 4) == 0) { + /* Show/Hide surface window */ + show_surface(display, &buf[4], 1); + } + else if (strncasecmp(buf, "hide", 4) == 0) { + /* Show/Hide surface window */ + show_surface(display, &buf[4], 0); + } + else if (strncasecmp(buf, "raise", 5) == 0) { + /* Raise/Lower surface window */ + raise_surface(display, &buf[5], 1); + } + else if (strncasecmp(buf, "lower", 5) == 0) { + /* Raise/Lower surface window */ + raise_surface(display, &buf[5], 0); + } + else if (strncasecmp(buf, "transition", 10) == 0) { + /* Set transition surface window*/ + transition_surface(display, &buf[10]); + } + else if (strncasecmp(buf, "input_add", 9) == 0) { + /* Set input switch to application */ + input_add(display, &buf[9]); + } + else if (strncasecmp(buf, "input_del", 9) == 0) { + /* Reset input switch to application*/ + input_del(display, &buf[9]); + } + else if (strncasecmp(buf, "input_conf", 10) == 0) { + /* input switch configuration */ + input_conf(display, &buf[10]); + } + else if (strncasecmp(buf, "input_code", 10) == 0) { + /* input code configuration */ + input_code(display, &buf[10]); + } + else if (strncasecmp(buf, "input_sw", 8) == 0) { + /* input switch event */ + input_sw(display, &buf[8]); + } + else if (strncasecmp(buf, "sleep", 5) == 0) { + /* Sleep */ + msec = sec_str_2_value(&buf[6]); + sleep_with_wayland(display->display, msec); + } + else if (strncasecmp(buf, "waitcreate", 10) == 0) { + /* Wait surface create */ + msec = sec_str_2_value(&buf[11]); + wait_with_wayland(display->display, msec, &display->surface_created); + } + else if (strncasecmp(buf, "waitdestroy", 11) == 0) { + /* Wait surface destrpy */ + msec = sec_str_2_value(&buf[12]); + wait_with_wayland(display->display, msec, &display->surface_destroyed); + } + else if (strncasecmp(buf, "event", 5) == 0) { + /* Send touch panel event to Weston */ + send_event(&buf[6]); + } + else { + print_log("HOMESCREEN: unknown command[%s]", buf); + return -1; + } + } + + print_log("HOMESCREEN: end"); + + send_event(NULL); + + return(0); +} + diff --git a/tests/test-send_event.c b/tests/test-send_event.c new file mode 100644 index 0000000..9165aa3 --- /dev/null +++ b/tests/test-send_event.c @@ -0,0 +1,514 @@ +/* + * Copyright (c) 2013, TOYOTA MOTOR CORPORATION. + * + * This program is licensed under the terms and conditions of the + * Apache License, version 2.0. The full text of the Apache License is at + * http://www.apache.org/licenses/LICENSE-2.0 + * + */ +/** + * @brief System Test Tool for send device input event + * + * @date Feb-20-2013 + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <pthread.h> +#include <sys/ioctl.h> +#include <sys/ipc.h> +#include <sys/msg.h> +#include <sys/time.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <signal.h> +#include <fcntl.h> +#include <linux/input.h> +#include <linux/uinput.h> +#include <linux/joystick.h> +#include "test-common.h" + +#define DEV_TOUCH 0 +#define DEV_JS 1 +#define SPECIALTYPE_XY 9991 + +static const struct { + char *prop; + short devtype; + short type; + short code; + short value; +} event_key[] = { + { "X", DEV_TOUCH, EV_ABS, ABS_X, -1 }, + { "Y", DEV_TOUCH, EV_ABS, ABS_Y, -1 }, + { "Down", DEV_TOUCH, EV_KEY, BTN_TOUCH, 1 }, + { "Up", DEV_TOUCH, EV_KEY, BTN_TOUCH, 0 }, + { "Touch", DEV_TOUCH, EV_KEY, BTN_TOUCH, -1 }, + { "XY", DEV_TOUCH, SPECIALTYPE_XY, 0, -1 }, + { "SYN", DEV_TOUCH, 0, 0, 0 }, + { "Button", DEV_TOUCH, EV_KEY, BTN_LEFT, -1 }, + { "ButtonOn", DEV_TOUCH, EV_KEY, BTN_LEFT, 1 }, + { "ButtonOff", DEV_TOUCH, EV_KEY, BTN_LEFT, 0 }, + + { "UpDown", DEV_JS, 2, 3, 1 }, + { "UD", DEV_JS, 2, 3, 1 }, + { "LeftRight", DEV_JS, 2, 2, 2 }, + { "LR", DEV_JS, 2, 2, 2 }, + { "Cross", DEV_JS, 1, 0, 3 }, + { "Squere", DEV_JS, 1, 1, 4 }, + { "Circle", DEV_JS, 1, 2, 5 }, + { "Triangle", DEV_JS, 1, 3, 6 }, + { "\0", 0, 0, 0, 0 } }; + +static int uifd = -1; +static int mqid = -1; +static int mDebug = 0; +static int mRun = 1; +static int mTouch = 1; + +static void +term_signal(const int signo) +{ + mRun = 0; +} + +static void +init_mq(const int mqkey) +{ + char dummy[256]; + + if (mqkey == 0) { + mqid = -1; + } + else { + mqid = msgget(mqkey, 0); + if (mqid < 0) { + mqid = msgget(mqkey, IPC_CREAT); + } + if (mqid < 0) { + print_log("Can not create message queue(%d(0x%x))[%d]", + mqkey, mqkey, errno); + fflush(stderr); + return; + } + while (msgrcv(mqid, dummy, sizeof(dummy)-sizeof(long), 0, IPC_NOWAIT) > 0) ; + } +} + +static void +init_device(const char *device) +{ + int fd; + int ii; + char devFile[64]; + char devName[64]; + struct uinput_user_dev uinputDevice; + uifd = open("/dev/uinput", O_RDWR); + + if (uifd < 0) { + print_log("/dev/uinput open error[%d]", errno); + fflush(stderr); + exit(1); + } + + memset(&uinputDevice, 0, sizeof(uinputDevice)); + strcpy(uinputDevice.name, device); + uinputDevice.absmax[ABS_X] = 1920; + uinputDevice.absmax[ABS_Y] = 1080; + + /* uinput device configuration */ + if (write(uifd, &uinputDevice, sizeof(uinputDevice)) < (int)sizeof(uinputDevice)) { + print_log("/dev/uinput regist error[%d]", errno); + fflush(stderr); + close(uifd); + exit(1); + } + + /* uinput set event bits */ + ioctl(uifd, UI_SET_EVBIT, EV_SYN); + + if ((mTouch != 0) && (mTouch != 3)) { + ioctl(uifd, UI_SET_EVBIT, EV_ABS); + ioctl(uifd, UI_SET_ABSBIT, ABS_X); + ioctl(uifd, UI_SET_ABSBIT, ABS_Y); + ioctl(uifd, UI_SET_EVBIT, EV_KEY); + if (mTouch == 1) { + ioctl(uifd, UI_SET_KEYBIT, BTN_LEFT); + } + else { + ioctl(uifd, UI_SET_KEYBIT, BTN_TOUCH); + ioctl(uifd, UI_SET_KEYBIT, BTN_TOOL_PEN); + } + } + else { + ioctl(uifd, UI_SET_EVBIT, EV_REL); + ioctl(uifd, UI_SET_RELBIT, REL_X); + ioctl(uifd, UI_SET_RELBIT, REL_Y); + ioctl(uifd, UI_SET_RELBIT, REL_Z); + ioctl(uifd, UI_SET_RELBIT, REL_RX); + ioctl(uifd, UI_SET_RELBIT, REL_RY); + ioctl(uifd, UI_SET_RELBIT, REL_RZ); + ioctl(uifd, UI_SET_EVBIT, EV_KEY); + ioctl(uifd, UI_SET_KEYBIT, KEY_RESERVED); + ioctl(uifd, UI_SET_KEYBIT, KEY_ESC); + ioctl(uifd, UI_SET_KEYBIT, KEY_1); + ioctl(uifd, UI_SET_KEYBIT, KEY_2); + ioctl(uifd, UI_SET_KEYBIT, KEY_3); + ioctl(uifd, UI_SET_KEYBIT, KEY_4); + ioctl(uifd, UI_SET_KEYBIT, KEY_5); + ioctl(uifd, UI_SET_KEYBIT, KEY_6); + ioctl(uifd, UI_SET_KEYBIT, KEY_7); + ioctl(uifd, UI_SET_KEYBIT, KEY_8); + ioctl(uifd, UI_SET_KEYBIT, KEY_9); + ioctl(uifd, UI_SET_KEYBIT, KEY_0); + } + + ioctl(uifd, UI_SET_EVBIT, EV_MSC); + ioctl(uifd, UI_SET_MSCBIT, MSC_SCAN); + + /* create event device */ + if (ioctl(uifd, UI_DEV_CREATE, NULL) < 0) { + print_log("/dev/uinput create error[%d]", errno); + fflush(stderr); + close(uifd); + exit(1); + } + print_log("## created event device %s", device); + + for (ii = 0; ii < 16; ii++) { + snprintf(devFile, 64, "/dev/input/event%d", ii); + fd = open(devFile, O_RDONLY); + if (fd < 0) continue; + + memset(devName, 0, sizeof(devName)); + ioctl(fd, EVIOCGNAME(sizeof(devName)), devName); + close(fd); + print_log("%d.event device(%s) is %s", ii+1, devFile, devName); + } +} + +static int +convert_value(const char *value, char **errp, int base) +{ + int i; + + for (i = 0; value[i]; i++) { + if ((value[i] == ',') || (value[i] == ';') || + (value[i] == ';') || (value[i] == ' ')) { + break; + } + } + if (errp) { + *errp = (char *)&value[i]; + } + + if ((strncasecmp(value, "on", i) == 0) || + (strncasecmp(value, "true", i) == 0) || + (strncasecmp(value, "push", i) == 0) || + (strncasecmp(value, "down", i) == 0) || + (strncasecmp(value, "right", i) == 0)) { + return 1; + } + else if ((strncasecmp(value, "off", i) == 0) || + (strncasecmp(value, "false", i) == 0) || + (strncasecmp(value, "pop", i) == 0) || + (strncasecmp(value, "up", i) == 0) || + (strncasecmp(value, "left", i) == 0)) { + return 0; + } + return strtol(value, (char **)0, 0); +} + +static void +send_event(const char *cmd) +{ + int i, j; + int key; + char prop[64]; + char value[128]; + int sec, msec; + char *errp; + struct input_event event; + struct js_event js; + + j = 0; + for (i = 0; cmd[i]; i++) { + if ((cmd[i] == '=') || (cmd[i] == ' ')) break; + if (j < (int)(sizeof(prop)-1)) { + prop[j++] = cmd[i]; + } + } + + prop[j] = 0; + j = 0; + if (cmd[i] != 0) { + for (i++; cmd[i]; i++) { + if (cmd[i] == ' ') continue; + if (j < (int)(sizeof(value)-1)) { + value[j++] = cmd[i]; + } + } + } + value[j] = 0; + + if (strcasecmp(prop, "sleep") == 0) { + sec = 0; + msec = 0; + for (i = 0; value[i]; i++) { + if (value[i] == '.') break; + sec = sec * 10 + (value[i] & 0x0f); + } + if (value[i] == '.') { + i++; + if (value[i] != 0) { + msec = (value[i] & 0x0f) * 100; + i++; + } + if (value[i] != 0) { + msec = msec + (value[i] & 0x0f) * 10; + i++; + } + if (value[i] != 0) { + msec = msec + (value[i] & 0x0f); + } + } + if (sec > 0) sleep(sec); + if (msec > 0) usleep(msec * 1000); + + return; + } + + for (key = 0; event_key[key].prop[0]; key++) { + if (strcasecmp(prop, event_key[key].prop) == 0) break; + } + if (! event_key[key].prop[0]) { + print_log("UnKnown Event name[%s]", prop); + return; + } + + if (mTouch != 0) { + memset(&event, 0, sizeof(event)); + gettimeofday(&event.time, NULL); + if (event_key[key].type == SPECIALTYPE_XY) { + event.type = EV_ABS; + event.code = ABS_X; + event.value = convert_value(value, &errp, 0); + if (mDebug) { + print_log("Send Event ABS_X=%d\t# %d.%03d", event.value, + (int)event.time.tv_sec, (int)(event.time.tv_usec/1000)); + fflush(stderr); + } + if (write(uifd, &event, sizeof(struct input_event)) < 0) { + print_log("event write error 1[%d]", errno); + fflush(stderr); + return; + } + event.code = ABS_Y; + if (*errp == ',') { + event.value = convert_value(errp + 1, (char **)0, 0); + } + else { + event.value = 0; + } + event.time.tv_usec += 200; + if (event.time.tv_usec >= 1000000) { + event.time.tv_sec ++; + event.time.tv_usec -= 1000000; + } + if (mDebug) { + print_log("Send Event ABS_Y=%d\t# %d.%03d", event.value, + (int)event.time.tv_sec, (int)(event.time.tv_usec/1000)); + fflush(stderr); + } + } + else { + event.type = event_key[key].type; + + if (event_key[key].code == -1) { + event.code = convert_value(value, (char **)0, 0); + } + else { + event.code = event_key[key].code; + event.value = convert_value(value, (char **)0, 0); + } + if (mDebug) { + if ((event.type == EV_ABS) && (event.code == ABS_X)) { + print_log("Send Event X=%d\t# %d.%03d", event.value, + (int)event.time.tv_sec, (int)(event.time.tv_usec/1000)); + } + else if ((event.type == EV_ABS) && (event.code == ABS_Y)) { + print_log("Send Event Y=%d\t %d.%03d", event.value, + (int)event.time.tv_sec, (int)(event.time.tv_usec/1000)); + } + else if ((event.type == EV_KEY) && (event.code == BTN_LEFT) && (event.value == 1)) { + print_log("Send Event BTN_LEFT=Down\t# %d.%03d", + (int)event.time.tv_sec, (int)(event.time.tv_usec/1000)); + } + else if ((event.type == EV_KEY) && (event.code == BTN_LEFT) && (event.value == 0)) { + print_log("Send Event BTN_LEFT=Up\t# %d.%03d", + (int)event.time.tv_sec, (int)(event.time.tv_usec/1000)); + } + else { + if ((event.type == EV_REL) && (event.value == 0)) { + event.value = 9; + } + else if ((event.type == EV_KEY) && (event.code == 0)) { + event.code = 9; + } + print_log("Send Event type=%d code=%d value=%d\t# %d.%03d", + event.type, event.code, event.value, + (int)event.time.tv_sec, (int)(event.time.tv_usec/1000)); + } + fflush(stderr); + } + } + if (write(uifd, &event, sizeof(struct input_event)) < 0) { + print_log("event write error 2[%d]", errno); + fflush(stderr); + } + else { + /* send EV_SYN */ + memset(&event, 0, sizeof(event)); + gettimeofday(&event.time, NULL); + event.type = EV_SYN; + event.code = SYN_REPORT; + if (write(uifd, &event, sizeof(struct input_event)) < 0) { + print_log("syn event write error 3[%d]", errno); + } + } + } + else { + memset(&js, 0, sizeof(js)); + gettimeofday(&event.time, NULL); + js.time = (event.time.tv_sec * 1000) + (event.time.tv_usec / 1000); + js.type = event_key[key].type; + js.number = event_key[key].code; + js.value = convert_value(value, (char **)0, 0); + if (mDebug) { + print_log("Send Event JS=%d,%d,%d\t# %d", + (int)js.type, (int)js.number, (int)js.value, (int)js.time); + } + if (write(uifd, &js, sizeof(struct js_event)) < 0) { + print_log("event write error 4[%d]", errno); + fflush(stderr); + } + } +} + +static void +usage(const char *prog) +{ + fprintf(stderr, "Usage: %s [-device=device] [{-m/-t/-j}] [-mq[=key]] [-d] [event=value] [event=value] ...\n", prog); + exit(0); +} + +int +main(int argc, char *argv[]) +{ + int i, j, k; + int mqkey = 0; + struct { + long mtype; + char buf[240]; + } mqbuf; + char buf[240]; + + j = 0; + strcpy(buf, "ico_test_device"); + for (i = 1; i < argc; i++) { + if (argv[i][0] == '-') { + if (strncasecmp(argv[i], "-device=", 8) == 0) { + strcpy(buf, &argv[i][8]); + } + else if (strcasecmp(argv[i], "-m") == 0) { + mTouch = 1; /* Simulate mouse */ + } + else if (strcasecmp(argv[i], "-t") == 0) { + mTouch = 2; /* Simulate touch-panel */ + } + else if (strcmp(argv[i], "-j") == 0) { + mTouch = 0; /* Simulate joystick */ + } + else if (strcmp(argv[i], "-J") == 0) { + mTouch = 3; /* Simulate joystick, but event is mouse */ + } + else if (strncasecmp(argv[i], "-mq", 3) == 0) { + if (argv[i][3] == '=') { + mqkey = strtol(&argv[i][4], (char **)0, 0); + } + else { + mqkey = 55551; /* default message queue key */ + } + } + else if (strcasecmp(argv[i], "-d") == 0) { + mDebug = 1; + } + else { + usage(argv[0]); + } + } + else { + j++; + } + } + + init_mq(mqkey); + + init_device(buf); + + mRun = 1; + + signal(SIGTERM, term_signal); + signal(SIGINT, term_signal); + + if (mqid >= 0) { + while (mRun) { + memset(&mqbuf, 0, sizeof(mqbuf)); + if (msgrcv(mqid, &mqbuf, sizeof(mqbuf)-sizeof(long), 0, 0) < 0) { + if (errno == EINTR) continue; + print_log("test-send_event: mq(%d) receive error[%d]", + mqkey, errno); + fflush(stderr); + break; + } + k = 0; + j = -1; + for (i = 0; mqbuf.buf[i]; i++) { + if ((mqbuf.buf[i] == '#') || (mqbuf.buf[i] == '\n') + || (mqbuf.buf[i] == '\r')) break; + if (mqbuf.buf[i] == '\t') buf[k++] = ' '; + else buf[k++] = mqbuf.buf[i]; + if ((j < 0) && (mqbuf.buf[i] != ' ')) j = i; + } + if (j < 0) continue; + buf[k] = 0; + send_event(&buf[j]); + } + msgctl(mqid, IPC_RMID, NULL); + } + else if (j <= 0) { + while ((mRun != 0) && (fgets(buf, sizeof(buf), stdin) != NULL)) { + j = -1; + for (i = 0; buf[i]; i++) { + if ((buf[i] == '#') || (buf[i] == '\n') || (buf[i] == '\r')) break; + if (buf[i] == '\t') buf[i] = ' '; + if ((j < 0) && (buf[i] != ' ')) j = i; + } + if (j < 0) continue; + buf[i] = 0; + send_event(&buf[j]); + } + } + else { + for (i = 1; i < argc; i++) { + if (argv[i][0] == '-') continue; + if (mRun == 0) break; + send_event(argv[i]); + } + } + exit(0); +} + diff --git a/tests/testdata/cl_surface3.dat b/tests/testdata/cl_surface3.dat new file mode 100644 index 0000000..fcd10cb --- /dev/null +++ b/tests/testdata/cl_surface3.dat @@ -0,0 +1,7 @@ +# Test for Weston IVI Plugin for Native Application +# Surface Create and Exit +# +# 1. Create Surface +create-surface +# 2. End of this Application (exit) +bye diff --git a/tests/testdata/hs_alltest.dat b/tests/testdata/hs_alltest.dat new file mode 100644 index 0000000..7f14582 --- /dev/null +++ b/tests/testdata/hs_alltest.dat @@ -0,0 +1,118 @@ +# Test for Device Input Controllers +# Input event test +# +# 1. Input test (touch event) +launch ../tests/test-client @1 -width=720 -height=760 -color=0xffff2020 -postsleep=90 < ../tests/testdata/cl_surface3.dat 2> ../tests/testlog/test-client1.log +sleep 0.5 +layer test-client@1 101 +move test-client@1 10 20 +show test-client@1 +sleep 0.3 +# +event 55551 XY=1800,250 +sleep 0.1 +event 55551 XY=1780,260 +sleep 0.1 +event 55551 XY=1760,270 +sleep 0.1 +event 55551 XY=1740,280 +event 55551 XY=1720,300 +sleep 0.1 +event 55551 Button=Down +sleep 0.1 +event 55551 XY=1710,310 +event 55551 XY=1712,308 +sleep 0.1 +event 55551 XY=1714,306 +event 55551 Button=Up +sleep 1 +kill test-client@1 +sleep 2 + +# 2. Input test (jyostick event) +launch ../tests/test-client @2 -color=0xff20ff20 -postsleep=90 < ../tests/testdata/cl_surface3.dat 2> ../tests/testlog/test-client2.log +sleep 0.3 +layer test-client@2 101 +move test-client@2 250 300 +show test-client@2 +sleep 0.2 +launch ../tests/test-client @3 -color=0xff2020ff -postsleep=90 < ../tests/testdata/cl_surface3.dat 2> ../tests/testlog/test-client3.log +sleep 0.3 +layer test-client@3 101 +move test-client@3 400 400 +show test-client@3 +sleep 0.5 +# input switch event (only send to Weston) +event 55552 UpDown=-1 +event 55552 UpDown=0 +event 55552 UpDown=1 +event 55552 UpDown=0 + +event 55552 LeftRight=-1 +event 55552 LeftRight=0 +event 55552 LeftRight=1 +event 55552 LeftRight=0 + +event 55552 Cross=1 +event 55552 Cross=0 +event 55552 Squere=1 +event 55552 Squere=0 +event 55552 Circle=1 +event 55552 Circle=0 +event 55552 Triangle=1 +event 55552 Triangle=0 + +# assign input sw to application +input_add DrivingForceGT 0 test-client@2 +input_add DrivingForceGT 1 test-client@3 +input_add DrivingForceGT 2 test-client@2 +input_add DrivingForceGT 3 test-client@3 +input_add DrivingForceGT 4 test-client@2 +input_add DrivingForceGT 5 test-client@3 +sleep 0.3 + +# input switch event (send to Application) +event 55552 UpDown=-1 +sleep 0.1 +event 55552 UpDown=0 +sleep 0.3 +event 55552 UpDown=1 +sleep 0.1 +event 55552 UpDown=0 +sleep 0.3 + +event 55552 LeftRight=-1 +sleep 0.1 +event 55552 LeftRight=0 +sleep 0.3 +event 55552 LeftRight=1 +sleep 0.1 +event 55552 LeftRight=0 +sleep 0.3 + +event 55552 Cross=1 +sleep 0.1 +event 55552 Cross=0 +sleep 0.1 +event 55552 Squere=1 +sleep 0.1 +event 55552 Squere=0 +sleep 0.1 +event 55552 Circle=1 +sleep 0.1 +event 55552 Circle=0 +sleep 0.1 +event 55552 Triangle=1 +sleep 0.1 +event 55552 Triangle=0 +sleep 1 + +# +kill test-client@2 +sleep 0.5 +kill test-client@3 +sleep 0.5 +# +# 3. End of Test +bye + diff --git a/tests/weston.ini b/tests/weston.ini new file mode 100644 index 0000000..5be1667 --- /dev/null +++ b/tests/weston.ini @@ -0,0 +1,24 @@ +[core] +modules=ico_plugin_loader.so + +#[output] +#name=HDMI3 +#mode=1680x945 +#mode=1920x1080 +#mode=173.00 1920 2048 2248 2576 1080 1083 1088 1120 -hsync +vsync +#transform=90 + +#[output] +#name=LVDS1 +#mode=1680x1050 +#transform=90 + +#[output] +#name=VGA1 +#mode=173.00 1920 2048 2248 2576 1080 1083 1088 1120 -hsync +vsync +#transform=90 + +#[output] +#name=X1 +#mode=1024x768 +#transform=flipped-270 diff --git a/tests/weston_ivi_plugin.ini b/tests/weston_ivi_plugin.ini new file mode 100644 index 0000000..89798d3 --- /dev/null +++ b/tests/weston_ivi_plugin.ini @@ -0,0 +1,18 @@ +[plugin] +modules=ico_ivi_common.so,ico_ivi_shell.so,ico_window_mgr.so,ico_input_mgr.so + +[shell] +animation=none +#animation=zoom +# 0=hide on surface create(for with HomeScreen)/1=show on surface create(for Debug) +visible_on_create=0 + +[debug] +# option flag +# 0x00000001 : =1, At the time of unvisible of surface, it travels surface outside a screen. +# : =0, Exclude surface of the unvisible from a list of surface of Westons. +option_flag=1 + +# 0=no debug write(1=err/2=warn/3=info/4=debug) +ivi_debug=4 + diff --git a/touch_egalax/Makefile.am b/touch_egalax/Makefile.am new file mode 100644 index 0000000..ea6be86 --- /dev/null +++ b/touch_egalax/Makefile.am @@ -0,0 +1,24 @@ +export abs_builddir + +AM_CFLAGS = $(GCC_CFLAGS) +AM_CPPFLAGS = -I$(top_srcdir)/src $(COMPOSITOR_CFLAGS) + +bin_PROGRAMS = \ + ico_ictl-touch_egalax \ + ico_ictl-egalax_calibration + +check_LTLIBRARIES = $(TESTS) +check_PROGRAMS = \ + ico_ictl-touch_egalax \ + ico_ictl-egalax_calibration + +AM_LDFLAGS = -module -avoid-version -rpath $(libdir) + +ico_ictl_touch_egalax_SOURCES = \ + ico_ictl-touch_egalax.c +ico_ictl_touch_egalax_LDADD = $(SIMPLE_CLIENT_LIBS) + +ico_ictl_egalax_calibration_SOURCES = \ + ico_ictl-egalax_calibration.c +ico_ictl_egalax_calibration_LDADD = $(SIMPLE_CLIENT_LIBS) + diff --git a/touch_egalax/ico_ictl-egalax_calibration.c b/touch_egalax/ico_ictl-egalax_calibration.c new file mode 100644 index 0000000..731ccca --- /dev/null +++ b/touch_egalax/ico_ictl-egalax_calibration.c @@ -0,0 +1,467 @@ +/* + * Copyright (c) 2013, TOYOTA MOTOR CORPORATION. + * + * This program is licensed under the terms and conditions of the + * Apache License, version 2.0. The full text of the Apache License is at + * http://www.apache.org/licenses/LICENSE-2.0 + * + */ +/** + * @brief Touchpanel(eGalax) Calibration Tool + * + * @date Feb-20-2013 + */ + +#include "ico_ictl-touch_egalax.h" + +/* Number of times to repeat a touch about each point */ +#define CALIBCONF_READ_NUM (5) + +static void print_usage(const char *pName); +static char *find_event_device(void); +static FILE *open_conffile(void); +static void get_coordinates(int evfd); +static void read_event(int evfd, int *x, int *y); +static void sort_data(int buff[], int left, int right); + +int mDispWidth = CALIBRATION_DISP_WIDTH; +int mDispHeight = CALIBRATION_DISP_HEIGHT; +int mPosX[4]; +int mPosY[4]; + +int mDebug = 0; + +/*--------------------------------------------------------------------------*/ +/** + * @brief Touchpanel(eGalax) Calibration Tool main routine + * + * @param arguments of standard main routeins(argc, argv) + * @return result + * @retval 0 sucess + * @retval 8 configuration file Error + * @retval 9 can not open event device(touchpanel) + */ +/*--------------------------------------------------------------------------*/ +int +main(int argc, char *argv[]) +{ + int ii, cnt; + int evfd; /* event device fd */ + char *eventDeviceName = NULL; /* event device name to hook */ + FILE *fp; + char buff[128]; + + /* Get options */ + for (ii = 1; ii < argc; ii++) { + if (strcasecmp(argv[ii], "-h") == 0) { + /* Help */ + print_usage(argv[0]); + exit(0); + } + else if (strcasecmp(argv[ii], "-width") == 0) { + /* Screen width */ + ii++; + if (ii >= argc) { + print_usage(argv[0]); + exit(0); + } + mDispWidth = strtol(argv[ii], (char **)0, 0); + if ((mDispWidth <= 0) || (mDispWidth > 8192)) { + print_usage(argv[0]); + exit(0); + } + } + else if (strcasecmp(argv[ii], "-height") == 0) { + /* Screen height */ + ii++; + if (ii >= argc) { + print_usage(argv[0]); + exit(0); + } + mDispHeight = strtol(argv[ii], (char **)0, 0); + if ((mDispHeight <= 0) || (mDispHeight > 8192)) { + print_usage(argv[0]); + exit(0); + } + } + else { + /* Input event device name */ + eventDeviceName = argv[ii]; + } + } + + if (eventDeviceName == NULL) { + /* If event device not present, get default device */ + eventDeviceName = find_event_device(); + if (eventDeviceName == NULL) { + /* System has no touchpanel, Error */ + exit(9); + } + } + + evfd = open(eventDeviceName, O_RDONLY); + if (evfd < 0) { + perror("Open event device"); + exit(9); + } + + /* Open configuration file for output */ + fp = open_conffile(); + if (fp == NULL) { + fprintf(stderr, "%s: Can not open config file\n", argv[0]); + close(evfd); + exit(8); + } + + CALIBRATION_PRINT("\n"); + CALIBRATION_PRINT("+================================================+\n"); + CALIBRATION_PRINT("| Configration Tool for Calibration Touch ver0.1 |\n"); + CALIBRATION_PRINT("+------------------------------------------------+\n"); + CALIBRATION_PRINT("| use display width = %d\n", CALIBRATION_DISP_WIDTH); + CALIBRATION_PRINT("| use display height = %d\n", CALIBRATION_DISP_HEIGHT); + CALIBRATION_PRINT("+------------------------------------------------+\n"); + + get_coordinates(evfd); + + CALIBRATION_PRINT("+------------------------------------------------+\n"); + CALIBRATION_PRINT("| save config |\n"); + CALIBRATION_PRINT("+------------------------------------------------+\n"); + + cnt = sprintf(buff, "%s=%d\n", CALIBRATOIN_STR_DISP_W, mDispWidth); + fwrite(buff, sizeof(char), cnt, fp); + CALIBRATION_PRINT("| %s", buff); + + cnt = sprintf(buff, "%s=%d\n", CALIBRATOIN_STR_DISP_H, mDispHeight); + fwrite(buff, sizeof(char), cnt, fp); + CALIBRATION_PRINT("| %s", buff); + + cnt = sprintf(buff, "%s=%d*%d\n", CALIBRATOIN_STR_POS1, mPosX[0], mPosY[0]); + fwrite(buff, sizeof(char), cnt, fp); + CALIBRATION_PRINT("| %s", buff); + + cnt = sprintf(buff, "%s=%d*%d\n", CALIBRATOIN_STR_POS2, mPosX[1], mPosY[1]); + fwrite(buff, sizeof(char), cnt, fp); + CALIBRATION_PRINT("| %s", buff); + + cnt = sprintf(buff, "%s=%d*%d\n", CALIBRATOIN_STR_POS3, mPosX[2], mPosY[2]); + fwrite(buff, sizeof(char), cnt, fp); + CALIBRATION_PRINT("| %s", buff); + + cnt = sprintf(buff, "%s=%d*%d\n", CALIBRATOIN_STR_POS4, mPosX[3], mPosY[3]); + fwrite(buff, sizeof(char), cnt, fp); + CALIBRATION_PRINT("| %s", buff); + + if (evfd >= 0) { + close(evfd); + } + + /* Close outputed configuration file */ + fclose(fp); + + CALIBRATION_PRINT("| |\n"); + CALIBRATION_PRINT("| finish Tools |\n"); + + exit(0); +} + +/*--------------------------------------------------------------------------*/ +/** + * @brief find_event_device: Find eGalax touchpanel device + * + * @param nothing + * @return device name + * @retval != NULL device name string + * @retvel == NULL system has no eGalax touchpanel + */ +/*--------------------------------------------------------------------------*/ +static char * +find_event_device(void) +{ + FILE *fp; + int eGalax = 0; + int i, j, k; + char buf[240]; + static char edevice[64]; + + /* Search input device */ + fp = fopen("/proc/bus/input/devices", "r"); + if (!fp) { + CALIBRATION_INFO("find_event_device: /proc/bus/input/devices Open Error\n"); + return(NULL); + } + + while (fgets(buf, sizeof(buf), fp)) { + if (eGalax == 0) { + for (i = 0; buf[i]; i++) { + if (strncmp(&buf[i], "eGalax", 6) == 0) { + /* Find eGalax touchpanel device */ + eGalax = 1; + break; + } + } + } + else { + for (i = 0; buf[i]; i++) { + if (strncmp(&buf[i], "Handlers", 8) == 0) { + /* Find eGalax device and Handlers */ + for (j = i+8; buf[j]; j++) { + if (buf[j] != ' ') continue; + strcpy(edevice, "/dev/input/"); + for (k = strlen(edevice); k < (int)sizeof(edevice); k++) { + j++; + if ((buf[j] == 0) || (buf[j] == ' ') || + (buf[j] == '\t') || (buf[j] == '\n') || + (buf[j] == '\r')) break; + edevice[k] = buf[j]; + } + edevice[k] = 0; + CALIBRATION_INFO("Event device of eGalax=<%s>\n", edevice); + fclose(fp); + return(edevice); + } + break; + } + } + } + } + fclose(fp); + + CALIBRATION_PRINT("System has no eGalax Touchpanel\n"); + return(NULL); +} + +/*--------------------------------------------------------------------------*/ +/** + * @brief read coordinates form touchpanel + * + * @param[in] evfd touchpanel event device + * @return nothing + */ +/*--------------------------------------------------------------------------*/ +static void +get_coordinates(int evfd) +{ + int bufX[CALIBCONF_READ_NUM]; + int bufY[CALIBCONF_READ_NUM]; + int x, y; + int ii; + + CALIBRATION_PRINT("| Touch the Top-Left corner of the screen %d times\n", + CALIBCONF_READ_NUM); + for (ii = 0; ii < CALIBCONF_READ_NUM; ii++) { + read_event(evfd, &x, &y); + bufX[ii] = x; + bufY[ii] = y; + CALIBRATION_PRINT("| # %d: %dx%d \n", ii, x, y); + } + sort_data(bufX, 0, CALIBCONF_READ_NUM - 1); + sort_data(bufY, 0, CALIBCONF_READ_NUM - 1); + mPosX[0] = bufX[CALIBCONF_READ_NUM / 2]; + mPosY[0] = bufY[CALIBCONF_READ_NUM / 2]; + + CALIBRATION_PRINT("+------------------------------------------------+\n"); + CALIBRATION_PRINT("| Touch the Top-Right corner of the screen %d times\n", + CALIBCONF_READ_NUM); + for (ii = 0; ii < CALIBCONF_READ_NUM; ii++) { + read_event(evfd, &x, &y); + bufX[ii] = x; + bufY[ii] = y; + CALIBRATION_PRINT("| # %d: %dx%d \n", ii, x, y); + } + sort_data(bufX, 0, CALIBCONF_READ_NUM - 1); + sort_data(bufY, 0, CALIBCONF_READ_NUM - 1); + mPosX[1] = bufX[CALIBCONF_READ_NUM / 2]; + mPosY[1] = bufY[CALIBCONF_READ_NUM / 2]; + + CALIBRATION_PRINT("+------------------------------------------------+\n"); + CALIBRATION_PRINT("| Touch the Bottom-Left corner of the screen %d times\n", + CALIBCONF_READ_NUM); + for (ii = 0; ii < CALIBCONF_READ_NUM; ii++) { + read_event(evfd, &x, &y); + bufX[ii] = x; + bufY[ii] = y; + CALIBRATION_PRINT("| # %d: %dx%d \n", ii, x, y); + } + sort_data(bufX, 0, CALIBCONF_READ_NUM - 1); + sort_data(bufY, 0, CALIBCONF_READ_NUM - 1); + mPosX[2] = bufX[CALIBCONF_READ_NUM / 2]; + mPosY[2] = bufY[CALIBCONF_READ_NUM / 2]; + + CALIBRATION_PRINT("+------------------------------------------------+\n"); + CALIBRATION_PRINT("| Touch the Bottom-Right corner of the screen %d times\n", + CALIBCONF_READ_NUM); + for (ii = 0; ii < CALIBCONF_READ_NUM; ii++) { + read_event(evfd, &x, &y); + bufX[ii] = x; + bufY[ii] = y; + CALIBRATION_PRINT("| # %d: %dx%d \n", ii, x, y); + } + sort_data(bufX, 0, CALIBCONF_READ_NUM - 1); + sort_data(bufY, 0, CALIBCONF_READ_NUM - 1); + mPosX[3] = bufX[CALIBCONF_READ_NUM / 2]; + mPosY[3] = bufY[CALIBCONF_READ_NUM / 2]; +} + +/*--------------------------------------------------------------------------*/ +/** + * @brief sort integer dates + * + * @param[in] buff array of integer datas + * @param[in] left array start index + * @param[in] right array end index + * @return nothing + */ +/*--------------------------------------------------------------------------*/ +static void +sort_data(int buff[], int left, int right) +{ + int ii, jj, pivot; + int tmp; + + ii = left; + jj = right; + + pivot = buff[(left + right) / 2]; + while (1) { + while (buff[ii] < pivot) { + ii++; + } + while (pivot < buff[jj]) { + jj--; + } + if (ii >= jj) { + break; + } + tmp = buff[ii]; + buff[ii] = buff[jj]; + buff[jj] = tmp; + ii++; + jj--; + } + + if (left < (ii - 1)) { + sort_data(buff, left, ii - 1); + } + if ((jj + 1) < right) { + sort_data(buff, jj + 1, right); + } +} + +/*--------------------------------------------------------------------------*/ +/** + * @brief event read from touchpanel + * + * @param[in] evfd touchpanel event device + * @return nothing + */ +/*--------------------------------------------------------------------------*/ +static void +read_event(int evfd, int *x, int *y) +{ + fd_set fds; + int ret; + int rsize; + int ii; + int flagX = 0; + int flagY = 0; + struct timeval delay; + struct input_event events[64]; + + while (1) { + /* select timeoutt value */ + delay.tv_sec = 0; + delay.tv_usec = 100*1000; + /* fs_set */ + FD_ZERO(&fds); + FD_SET(evfd, &fds); + + /* wait for event read or timedout */ + ret = select(evfd + 1, &fds, NULL, NULL, &delay); + if (ret <= 0) { + continue; + } + if (FD_ISSET(evfd, &fds)) { + /* event read */ + rsize = read(evfd, events, sizeof(events) ); + for (ii = 0; ii < (int)(rsize/sizeof(struct input_event)); ii++) { + if ((events[ii].type == EV_ABS) && (events[ii].code == ABS_X)) { + /* X */ + flagX++; + *x = events[ii].value; + } + else if ((events[ii].type == EV_ABS) && (events[ii].code == ABS_Y)) { + /* Y */ + flagY++; + *y = events[ii].value; + } + } + } + /* Input 2 times (Touch On and Off) */ + if ((flagX >= 2) && (flagY >= 2)) { + break; + } + } + + while (1) { + delay.tv_sec = 0; + delay.tv_usec = 200*1000; + FD_ZERO(&fds); + FD_SET(evfd, &fds); + + /* wait for input (or timedout) */ + ret = select(evfd + 1, &fds, NULL, NULL, &delay); + if (ret == 0) { + break; + } + else if (ret < 0) { + continue; + } + rsize = read(evfd, events, sizeof(events)); + } +} + +/*--------------------------------------------------------------------------*/ +/** + * @brief open configuration file + * + * @param nothing + * @return file descriptor + * @retval != NULL file descriptor + * @retval NULL open error + */ +/*--------------------------------------------------------------------------*/ +static FILE * +open_conffile(void) +{ + char *confp; + FILE *fp; + + /* Get configuration file path */ + confp = getenv(CALIBRATOIN_CONF_ENV); + if (! confp) { + confp = CALIBRATOIN_CONF_FILE; + } + + /* Open configuration file */ + fp = fopen(confp, "w"); + if (fp == NULL) { + perror(confp); + return fp; + } + return fp; +} + +/*--------------------------------------------------------------------------*/ +/** + * @brief print help + * + * @param[in] pName program name + * @return nothing + */ +/*--------------------------------------------------------------------------*/ +static void +print_usage(const char *pName) +{ + fprintf(stderr, "Usage: %s [-h][-width width][-height height] [device]\n", pName); +} + diff --git a/touch_egalax/ico_ictl-touch_egalax.c b/touch_egalax/ico_ictl-touch_egalax.c new file mode 100644 index 0000000..937ad4b --- /dev/null +++ b/touch_egalax/ico_ictl-touch_egalax.c @@ -0,0 +1,850 @@ +/* + * Copyright (c) 2013, TOYOTA MOTOR CORPORATION. + * + * This program is licensed under the terms and conditions of the + * Apache License, version 2.0. The full text of the Apache License is at + * http://www.apache.org/licenses/LICENSE-2.0 + * + */ +/** + * @brief Device Input Controller(eGalax Touchpanel) + * Send touchpanel input enevt to Weston + * + * @date Feb-20-2013 + */ + +#include "ico_ictl-touch_egalax.h" + +/* Change touch event */ +#define REPLACE_TOUCH_EVENT 1 /* Change touch event to mouse left button event*/ + +/* Program name */ +#define CALIBDAE_DEV_NAME "ico_ictl-touch_egalax" + +static void print_usage(const char *pName); +static char *find_event_device(void); +static int setup_uinput(char *uinputDeviceName); +static void set_eventbit(int uifd); +static int open_uinput(char *uinputDeviceName); +static void close_uinput(int uifd); +static void event_iterate(int uifd, int evfd); +static void setup_sighandler(void); +static void terminate_program(const int signal); +static int setup_program(void); +static int calibration_event(struct input_event *in, struct input_event *out); +static void push_event(struct input_event *ev); +static void push_eventlog(const char *cmd, const int value, struct timeval *tp); + +int mRunning = -1; /* Running flag */ +int mDebug = 0; /* Debug flag */ +int mEventLog = 0; /* event input log */ +struct timeval lastEvent = { 0, 0 }; /* last input event time */ + +/* Configurations */ +int mDispWidth = CALIBRATION_DISP_WIDTH; +int mDispHeight = CALIBRATION_DISP_HEIGHT; +int mPosX[4] = { 0, 0, 0, 0 }; +int mPosY[4] = { 0, 0, 0, 0 }; +int mXlow = 0; +int mXheigh = 0; +int mYlow = 0; +int mYheigh = 0; + +/* Optiones */ +int mTrans = 0; /* Rotate(0,90,180 or 270) */ +int mRevX = 0; /* Reverse X coordinate */ +int mRevY = 0; /* Reverse Y coordinate */ + +/*--------------------------------------------------------------------------*/ +/** + * @brief Device Input Controller: For eGalax TouchPanel + * main routine + * + * @param main() finction's standard parameter (argc,argv) + * @return result + * @retval 0 success + * @retval 8 failed(configuration error) + * @retval 9 failed(event device error) + */ +/*--------------------------------------------------------------------------*/ +int +main(int argc, char *argv[]) +{ + int ii; + int err; + int uifd; /* uinput fd */ + int evfd; /* event device fd */ + char *eventDeviceName = NULL; /* event device name to hook */ + char *uinputDeviceName = "/dev/uinput"; /* User Input module */ + + for (ii = 1; ii < argc; ii++) { + if (strcmp(argv[ii], "-h") == 0) { + print_usage(argv[0]); + exit(0); + } + else if (strcmp(argv[ii], "-d") == 0) { + mDebug = 1; + } + else if (strcmp(argv[ii], "-t") == 0) { + if ((ii < (argc-1)) && (argv[ii+1][0] != '-')) { + ii++; + mTrans = strtol(argv[ii], (char **)0, 0); + } + else { + mTrans = 90; + } + } + else if (strcmp(argv[ii], "-l") == 0) { + mEventLog = 1; /* Input Log for System Test */ + } + else if (strcmp(argv[ii], "-L") == 0) { + mEventLog = 2; /* Output Log for Unit Test */ + } + else { + eventDeviceName = argv[ii]; + } + } + + if (eventDeviceName == NULL) { + /* If event device not present, get default device */ + eventDeviceName = find_event_device(); + if (eventDeviceName == NULL) { + /* System has no touchpanel, Error */ + exit(9); + } + } + + err = setup_program(); + if (err < 0) { + if (err == -2) { + fprintf(stderr, "%s: Illegal config value\n", argv[0]); + } + else { + fprintf(stderr, "%s: Can not read config file\n", argv[0]); + } + exit(8); + } + + if (! mDebug) { + if (daemon(0, 1) < 0) { + fprintf(stderr, "%s: Can not Create Daemon\n", argv[0]); + exit(1); + } + } + + /* setup uinput device */ + uifd = setup_uinput(uinputDeviceName); + if (uifd < 0) { + fprintf(stderr, "uinput(%s) initialize failed. Continue anyway\n", uinputDeviceName); + exit(9); + } + + evfd = open(eventDeviceName, O_RDONLY); + if (evfd < 0) { + fprintf(stderr, "event device(%s) Open Error[%d]\n", eventDeviceName, errno); + close_uinput(uifd); + exit(9); + } + CALIBRATION_DEBUG("main: input device(%s) = %d\n", eventDeviceName, evfd); + + setup_sighandler(); + + /* event read */ + mRunning = 1; + event_iterate(uifd, evfd); + + if (evfd >= 0) { + close(evfd); + } + + close_uinput(uifd); + + exit(0); +} + +/*--------------------------------------------------------------------------*/ +/** + * @brief initialize with get configurations + * + * @param nothing + * @return result + * @retval 0 sucess + * @retval -1 config file read error + * @retval -2 illegal config value + */ +/*--------------------------------------------------------------------------*/ +static int +setup_program(void) +{ + char *confp; + char buff[128]; + FILE *fp; + int work; + + /* Get configuration file path */ + confp = getenv(CALIBRATOIN_CONF_ENV); + if (! confp) { + confp = CALIBRATOIN_CONF_FILE; + } + + /* Open configuration file */ + fp = fopen(confp, "r"); + if (fp == NULL) { + perror(confp); + return -1; + } + + while (fgets(buff, sizeof(buff), fp)) { + if (buff[0] == '#') { + /* comment line, skip */ + continue; + } + else if (strncmp(buff, + CALIBRATOIN_STR_DISP_W, + sizeof(CALIBRATOIN_STR_DISP_W) - 1) == 0) { + /* screen width */ + strtok(buff, CALIBRATOIN_STR_SEPAR); + mDispWidth = atoi(strtok(NULL, CALIBRATOIN_STR_SEPAR)); + CALIBRATION_INFO("mDispWidth = %d\n", mDispWidth); + } + else if (strncmp(buff, + CALIBRATOIN_STR_DISP_H, + sizeof(CALIBRATOIN_STR_DISP_H) - 1) == 0) { + /* screen height */ + strtok(buff, CALIBRATOIN_STR_SEPAR); + mDispHeight = atoi(strtok(NULL, CALIBRATOIN_STR_SEPAR)); + CALIBRATION_INFO("mDispHeight = %d\n", mDispHeight); + } + else if (strncmp(buff, + CALIBRATOIN_STR_POS1, + sizeof(CALIBRATOIN_STR_POS1) - 1) == 0) { + /* position1 : Top-Left */ + strtok(buff, CALIBRATOIN_STR_SEPAR); + mPosX[0] = atoi(strtok(NULL, CALIBRATOIN_STR_SEPAR)); + mPosY[0] = atoi(strtok(NULL, CALIBRATOIN_STR_SEPAR)); + CALIBRATION_INFO("POS1 = %dx%d\n", mPosX[0], mPosY[0]); + } + else if (strncmp(buff, + CALIBRATOIN_STR_POS2, + sizeof(CALIBRATOIN_STR_POS2) - 1) == 0) { + /* position2 : Top-Right */ + strtok(buff, CALIBRATOIN_STR_SEPAR); + mPosX[1] = atoi(strtok(NULL, CALIBRATOIN_STR_SEPAR)); + mPosY[1] = atoi(strtok(NULL, CALIBRATOIN_STR_SEPAR)); + CALIBRATION_INFO("POS2 = %dx%d\n", mPosX[1], mPosY[1]); + } + else if (strncmp(buff, + CALIBRATOIN_STR_POS3, + sizeof(CALIBRATOIN_STR_POS3) - 1) == 0) { + /* position3 : Bottom-Left */ + strtok(buff, CALIBRATOIN_STR_SEPAR); + mPosX[2] = atoi(strtok(NULL, CALIBRATOIN_STR_SEPAR)); + mPosY[2] = atoi(strtok(NULL, CALIBRATOIN_STR_SEPAR)); + CALIBRATION_INFO("POS3 = %dx%d\n", mPosX[2], mPosY[2]); + } + else if (strncmp(buff, + CALIBRATOIN_STR_POS4, + sizeof(CALIBRATOIN_STR_POS4) - 1) == 0) { + /* position4 : Bottom-Right */ + strtok(buff, CALIBRATOIN_STR_SEPAR); + mPosX[3] = atoi(strtok(NULL, CALIBRATOIN_STR_SEPAR)); + mPosY[3] = atoi(strtok(NULL, CALIBRATOIN_STR_SEPAR)); + CALIBRATION_INFO("POS4 = %dx%d\n", mPosX[3], mPosY[3]); + } + } + fclose(fp); + + /* Reverse X coordinate, if need */ + if (mPosX[0] > mPosX[1]) { + int work; + work = mPosX[0]; + mPosX[0] = mPosX[1]; + mPosX[1] = work; + work = mPosX[2]; + mPosX[2] = mPosX[3]; + mPosX[3] = work; + mRevX = 1; + CALIBRATION_INFO("Reverse X\n"); + } + + /* Reverse Y coordinate, if need */ + if (mPosY[0] > mPosY[2]) { + work = mPosY[0]; + mPosY[0] = mPosY[2]; + mPosY[2] = work; + work = mPosY[1]; + mPosY[1] = mPosY[3]; + mPosY[3] = work; + mRevY = 1; + CALIBRATION_INFO("Reverse Y\n"); + } + + if ((mRevX != 0) || (mRevY != 0)) { + CALIBRATION_INFO("Changed POS1 = %dx%d\n", mPosX[0], mPosY[0]); + CALIBRATION_INFO("Changed POS2 = %dx%d\n", mPosX[1], mPosY[1]); + CALIBRATION_INFO("Changed POS3 = %dx%d\n", mPosX[2], mPosY[2]); + CALIBRATION_INFO("Changed POS4 = %dx%d\n", mPosX[3], mPosY[3]); + } + + mXlow = (mPosX[0] + mPosX[2]) / 2; + mXheigh = (mPosX[1] + mPosX[3]) / 2; + if (mXheigh <= mXlow) { + return -2; + } + + mYlow = (mPosY[0] + mPosY[1]) / 2; + mYheigh = (mPosY[2] + mPosY[3]) / 2; + if (mYheigh <= mYlow) { + return -2; + } + return 1; +} + +/*--------------------------------------------------------------------------*/ +/** + * @brief signal handler + * + * + * @param[in] signal signal numnber + * @return nothing + */ +/*--------------------------------------------------------------------------*/ +static void +terminate_program(const int signal) +{ + mRunning = -signal; +} + +/*--------------------------------------------------------------------------*/ +/** + * @brief setup signal handler + * + * @param nothing + * @return nothing + */ +/*--------------------------------------------------------------------------*/ +static void +setup_sighandler(void) +{ + sigset_t mask; + + sigemptyset(&mask); + + signal(SIGTERM, terminate_program); + + sigaddset(&mask, SIGTERM); + sigprocmask(SIG_UNBLOCK, &mask, NULL); +} + +/*--------------------------------------------------------------------------*/ +/** + * @brief find_event_device: Find eGalax touchpanel device + * + * + * @param nothing + * @return device name + * @retval != NULL device name string + * @retvel == NULL system has no eGalax touchpanel + */ +/*--------------------------------------------------------------------------*/ +static char * +find_event_device(void) +{ + FILE *fp; + int eGalax = 0; + int i, j, k; + char buf[240]; + static char edevice[64]; + + char *pdev = getenv(CALIBRATOIN_INPUT_DEV); + + if ((pdev != NULL) && (*pdev != 0)) { + /* Search pseudo input device for Debug */ + int fd; + for (i = 0; i < 16; i++) { + snprintf(edevice, 64, "/dev/input/event%d", i); + fd = open(edevice, O_RDONLY | O_NONBLOCK); + if (fd < 0) continue; + + memset(buf, 0, sizeof(buf)); + ioctl(fd, EVIOCGNAME(sizeof(buf)), buf); + close(fd); + k = 0; + for (j = 0; buf[j]; j++) { + if (buf[j] != ' ') { + buf[k++] = buf[j]; + } + } + buf[k] = 0; + + if (strncasecmp(buf, pdev, sizeof(buf)) == 0) { + CALIBRATION_INFO("Event device of eGalax=<%s>\n", edevice); + return edevice; + } + } + } + else { + /* Search input device */ + fp = fopen("/proc/bus/input/devices", "r"); + if (!fp) { + CALIBRATION_PRINT("find_event_device: /proc/bus/input/devices Open Error\n"); + return NULL; + } + + while (fgets(buf, sizeof(buf), fp)) { + if (eGalax == 0) { + for (i = 0; buf[i]; i++) { + if (strncmp(&buf[i], "eGalax", 6) == 0) { + /* Find eGalax touchpanel device */ + eGalax = 1; + break; + } + } + } + else { + for (i = 0; buf[i]; i++) { + if (strncmp(&buf[i], "Handlers", 8) == 0) { + /* Find eGalax device and Handlers */ + for (j = i+8; buf[j]; j++) { + if (buf[j] != ' ') continue; + strcpy(edevice, "/dev/input/"); + for (k = strlen(edevice); k < (int)sizeof(edevice); k++) { + j++; + if ((buf[j] == 0) || (buf[j] == ' ') || + (buf[j] == '\t') || (buf[j] == '\n') || + (buf[j] == '\r')) break; + edevice[k] = buf[j]; + } + edevice[k] = 0; + CALIBRATION_INFO("Event device of eGalax=<%s>\n", edevice); + fclose(fp); + return edevice; + } + break; + } + } + } + } + fclose(fp); + } + CALIBRATION_PRINT("%s: System has no eGalax Touchpanel\n", CALIBDAE_DEV_NAME); + return NULL; +} + +/*--------------------------------------------------------------------------*/ +/** + * @brief event input and convert (main loop) + * + * + * @param[in] uifd event output file descriptor + * @param[in] evfd event input file descriptor + * @return nothing + */ +/*--------------------------------------------------------------------------*/ +static void +event_iterate(int uifd, int evfd) +{ + fd_set fds; + int ret; + int rsize; + int ii; + int retry; + struct timeval delay; + struct input_event events[128]; + struct input_event event; + + ioctl(evfd, EVIOCGRAB, 1); + + retry = 0; + + while (mRunning > 0) { + delay.tv_sec = 1; + delay.tv_usec = 0; + + FD_ZERO(&fds); + FD_SET(evfd, &fds); + + ret = select(evfd + 1, &fds, NULL, NULL, &delay); + if (ret <= 0) { + continue; + } + if (FD_ISSET(evfd, &fds)) { + rsize = read(evfd, events, sizeof(events)); + if (rsize <= 0) { + if (rsize < 0) { + CALIBRATION_PRINT("event_iterate: input device(%d) end<%d>\n", evfd, errno); + retry ++; + if (retry > CALIBRATOIN_RETRY_COUNT) { + return; + } + } + usleep(CALIBRATOIN_RETRY_WAIT * 1000); + continue; + } + retry = 0; + for (ii = 0; ii < (int)(rsize/sizeof(struct input_event)); ii++) { + ret = calibration_event(&events[ii], &event); +#ifdef REPLACE_TOUCH_EVENT + if (ret >= 0) { + if (write(uifd, &event, sizeof(struct input_event)) < 0) { + CALIBRATION_PRINT("%s: Event write error %d[%d]\n", + CALIBDAE_DEV_NAME, uifd, errno); + } + if (mEventLog == 2) { + push_event(&event); + } + if (ret > 0) { + event.type = EV_KEY; + event.code = BTN_LEFT; + event.value = 1; + if (write(uifd, &event, sizeof(struct input_event)) < 0) { + CALIBRATION_PRINT("%s: Event write error %d[%d]\n", + CALIBDAE_DEV_NAME, uifd, errno); + } + else { + CALIBRATION_DEBUG("EV_KEY=BTN_LEFT\n"); + } + if (mEventLog == 2) { + push_event(&event); + } + } + } +#else /*REPLACE_TOUCH_EVENT*/ + ret = write(uifd, &event, sizeof(struct input_event)); + if (mEventLog == 2) { + push_event(&event); + } +#endif /*REPLACE_TOUCH_EVENT*/ + } + } + } + ioctl(evfd, EVIOCGRAB, 0); +} + +static void +push_eventlog(const char *event, const int value, struct timeval *tp) +{ + struct timeval curtime; + + gettimeofday(&curtime, NULL); + + if (lastEvent.tv_sec) { + int sec, usec; + + sec = curtime.tv_sec - lastEvent.tv_sec; + usec = curtime.tv_usec - lastEvent.tv_usec; + + if (usec < 0) { + sec -= 1; + usec += 1000000; + } + usec += 500; + if( usec >= 1000000 ) { + usec -= 1000000; + sec += 1; + } + if ((sec > 0) || ((sec == 0) && (usec >= 10000))) { + printf("sleep %d.%03d\n", sec, usec / 1000); + lastEvent.tv_sec = curtime.tv_sec; + lastEvent.tv_usec = curtime.tv_usec; + } + } + else { + lastEvent.tv_sec = curtime.tv_sec; + lastEvent.tv_usec = curtime.tv_usec; + } + printf("%s=%d\t# %d.%03d\n", event, value, (int)tp->tv_sec, (int)(tp->tv_usec/1000)); + fflush(stdout); +} + +static void +push_event(struct input_event *ev) +{ + switch(ev->type) { + case EV_ABS: + switch(ev->code) { + case ABS_X: + push_eventlog("X", ev->value, &(ev->time)); + break; + case ABS_Y: + push_eventlog("Y", ev->value, &(ev->time)); + break; + default: + break; + } + break; + case EV_KEY: + switch(ev->code) { + case BTN_TOUCH: + push_eventlog("Touch", ev->value, &(ev->time)); + break; + case BTN_LEFT: + push_eventlog("Button", ev->value, &(ev->time)); + break; + default: + break; + } + break; + default: + break; + } +} + +/*--------------------------------------------------------------------------*/ +/** + * @brief convert x/y coordinates + * + * @param[in] in input event + * @param[in] out output converted event + * @return result + * @retval -1 input event queued(no output) + * @retval 0 no input event + * @retval 1 event converted + */ +/*--------------------------------------------------------------------------*/ +static int +calibration_event(struct input_event *in, struct input_event *out) +{ + int ret = 0; +#ifdef REPLACE_TOUCH_EVENT + static int queue_touch = 0; +#endif /*REPLACE_TOUCH_EVENT*/ + + memcpy(out, in, sizeof(struct input_event) ); + + switch (in->type) { + case EV_ABS: + /* absolute coordinate */ + switch (in->code) { + /* X/Y coordinate */ + case ABS_X: + out->value = mDispWidth * (in->value - mXlow) / (mXheigh - mXlow); + if (mRevX) { + out->value = mDispWidth - out->value; + } + if (out->value < 0) out->value = 0; + if (out->value >= mDispWidth) out->value = mDispWidth - 1; + + if (mTrans == 90) { + out->code = ABS_Y; + out->value = mDispWidth - out->value - 1; + } + else if (mTrans == 180) { + out->value = mDispWidth - out->value - 1; + } + else if (mTrans == 270) { + out->code = ABS_Y; + } + if (mEventLog == 1) { + push_eventlog("X", in->value, &(in->time)); + } +#ifdef REPLACE_TOUCH_EVENT + if (queue_touch & 1) { + queue_touch &= ~1; + if (queue_touch == 0) { + ret = 1; + } + } +#endif /*REPLACE_TOUCH_EVENT*/ + CALIBRATION_DEBUG("ABS_X=%s %d=>%d\n", + (out->code == ABS_X) ? "X" : "Y", + in->value, out->value); + break; + + case ABS_Y: + out->value = mDispHeight * (in->value - mYlow) / (mYheigh - mYlow); + if (mRevY) { + out->value = mDispHeight - out->value; + } + if (out->value < 0) out->value = 0; + if (out->value >= mDispHeight) out->value = mDispHeight - 1; + + if (mTrans == 90) { + out->code = ABS_X; + } + else if (mTrans == 180) { + out->value = mDispHeight - out->value - 1; + } + else if (mTrans == 270) { + out->code = ABS_X; + out->value = mDispHeight - out->value - 1; + } + if (mEventLog == 1) { + push_eventlog("Y", in->value, &(in->time)); + } +#ifdef REPLACE_TOUCH_EVENT + if (queue_touch & 2) { + queue_touch &= ~2; + if (queue_touch == 0) { + ret = 1; + } + } +#endif /*REPLACE_TOUCH_EVENT*/ + CALIBRATION_DEBUG("ABS_Y=%s %d=>%d\n", + (out->code == ABS_X) ? "X" : "Y", + in->value, out->value); + break; + + default: + CALIBRATION_DEBUG("calibration_event: Unknown code(0x%x)\n", (int)in->code); + break; + } + break; + +#ifdef REPLACE_TOUCH_EVENT + case EV_KEY: + if (in->code == BTN_TOUCH) { + if (mEventLog == 1) { + push_eventlog("Touch", in->value, &(in->time)); + } + /* Touch event change to mouse left button event */ + out->code = BTN_LEFT; + if (out->value != 0) { + queue_touch = 3; + ret = -1; + CALIBRATION_DEBUG("BTN_TOUCH=LEFT, queue(%d)\n", out->value); + } + else { + ret = 0; + CALIBRATION_DEBUG("BTN_TOUCH=LEFT(%d)\n", out->value); + } + } + break; +#endif /*REPLACE_TOUCH_EVENT*/ + + case EV_SYN: + CALIBRATION_DEBUG("calibration_event: SYN\n"); + break; + + default: + CALIBRATION_DEBUG("calibration_event: Unknown type(0x%x)\n", (int)in->type); + break; + } + if (out->value < 0) { + out->value = 0; + } + + return ret; +} + +/*--------------------------------------------------------------------------*/ +/** + * @brief setup uinput device for event output + * + * @param[in] uinputDeviceName uinput device node name + * @return uinput file descriptor + * @retval >= 0 file descriptor + * @retval < 0 error + */ +/*--------------------------------------------------------------------------*/ +static int +setup_uinput(char *uinputDeviceName) +{ + int uifd; + struct uinput_user_dev uinputDevice; + + uifd = open_uinput(uinputDeviceName); + if (uifd < 0) { + perror("Open uinput"); + return -1; + } + + memset(&uinputDevice, 0, sizeof(uinputDevice)); + strcpy(uinputDevice.name, CALIBDAE_DEV_NAME); + uinputDevice.absmax[ABS_X] = mDispWidth; + uinputDevice.absmax[ABS_Y] = mDispHeight; + + /* uinput device configuration */ + if (write(uifd, &uinputDevice, sizeof(uinputDevice)) < (int)sizeof(uinputDevice)) { + perror("Regist uinput"); + CALIBRATION_PRINT("setup_uinput: write(%d) Error[%d]\n", uifd, errno); + close(uifd); + return -1; + } + + /* uinput set event bits */ + set_eventbit(uifd); + + if (ioctl(uifd, UI_DEV_CREATE, NULL) < 0) { + CALIBRATION_PRINT("setup_uinput: ioclt(%d,UI_DEV_CREATE,) Error[%d]\n", uifd, errno); + } + return uifd; +} + +/*--------------------------------------------------------------------------*/ +/** + * @brief event bit set + * + * @param[in] uifd uinput file descriptor + * @return nothing + */ +/*--------------------------------------------------------------------------*/ +static void +set_eventbit(int uifd) +{ + ioctl(uifd, UI_SET_EVBIT, EV_SYN); + + ioctl(uifd, UI_SET_EVBIT, EV_ABS); + ioctl(uifd, UI_SET_ABSBIT, ABS_X); + ioctl(uifd, UI_SET_ABSBIT, ABS_Y); + + ioctl(uifd, UI_SET_EVBIT, EV_KEY); +#ifdef REPLACE_TOUCH_EVENT + ioctl(uifd, UI_SET_KEYBIT, BTN_LEFT); +#else /*REPLACE_TOUCH_EVENT*/ + ioctl(uifd, UI_SET_KEYBIT, BTN_TOUCH); + ioctl(uifd, UI_SET_KEYBIT, BTN_TOOL_PEN); +#endif /*REPLACE_TOUCH_EVENT*/ + + ioctl(uifd, UI_SET_EVBIT, EV_MSC); + ioctl(uifd, UI_SET_MSCBIT, MSC_SCAN); +} + +/*--------------------------------------------------------------------------*/ +/** + * @brief open uinput device + * + * @param[in] uinputDeviceName uinput device name + * @return uinput file descriptor + * @retval >= 0 file descriptor + * @retval < 0 error + */ +/*--------------------------------------------------------------------------*/ +static int +open_uinput(char *uinputDeviceName) +{ + return open(uinputDeviceName, O_RDWR); +} + +/*--------------------------------------------------------------------------*/ +/** + * @brief close uinput device + * + * @param[in] uifd uinput file descriptor + * @return nothing + */ +/*--------------------------------------------------------------------------*/ +static void +close_uinput(int uifd) +{ + if (uifd >= 0) { + ioctl(uifd, UI_DEV_DESTROY, NULL); + close(uifd); + uifd = -1; + } +} + +/*--------------------------------------------------------------------------*/ +/** + * @brief print help message + * + * @param[in] pName program name + * @return nothing + */ +/*--------------------------------------------------------------------------*/ +static void +print_usage(const char *pName) +{ + fprintf(stderr, "Usage: %s [-h][-d][-t [rotate]] [device]\n", pName ); +} + diff --git a/touch_egalax/ico_ictl-touch_egalax.h b/touch_egalax/ico_ictl-touch_egalax.h new file mode 100644 index 0000000..47af5d0 --- /dev/null +++ b/touch_egalax/ico_ictl-touch_egalax.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2013, TOYOTA MOTOR CORPORATION. + * + * This program is licensed under the terms and conditions of the + * Apache License, version 2.0. The full text of the Apache License is at + * http://www.apache.org/licenses/LICENSE-2.0 + * + */ +/** + * @brief Device Input Controller(cartouch Touchpanel) + * Program common include file + * + * @date Feb-20-2013 + */ + +#ifndef _ICO_ICTL_TOUCH_EGALAX_H_ +#define _ICO_ICTL_TOUCH_EGALAX_H_ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <signal.h> +#include <errno.h> +#include <fcntl.h> +#include <time.h> +#include <unistd.h> +#include <sys/time.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/ioctl.h> +#include <linux/input.h> +#include <linux/uinput.h> + +/* Default screen size */ +#define CALIBRATION_DISP_WIDTH 1920 +#define CALIBRATION_DISP_HEIGHT 1080 + +/* Configuration file */ +#define CALIBRATOIN_CONF_LEN_MAX 128 +#define CALIBRATOIN_CONF_ENV "CALIBRATOIN_CONF" +#define CALIBRATOIN_INPUT_DEV "ICTL_TOUCH_DEV" +#define CALIBRATOIN_CONF_FILE \ + "/opt/etc/ico-uxf-device-input-controller/egalax_calibration.conf" + +/* Configuration items */ +#define CALIBRATOIN_STR_SEPAR "=*" /* Delimitor */ +#define CALIBRATOIN_STR_DISP_W "DWIDTH" /* Screen width */ +#define CALIBRATOIN_STR_DISP_H "DHEIGHT" /* Scneen height */ +#define CALIBRATOIN_STR_POS1 "POSITION1" /* Top-Left position */ +#define CALIBRATOIN_STR_POS2 "POSITION2" /* Top-Right position */ +#define CALIBRATOIN_STR_POS3 "POSITION3" /* Bottom-Left position */ +#define CALIBRATOIN_STR_POS4 "POSITION4" /* Bottom-Right position */ + +/* Error retry */ +#define CALIBRATOIN_RETRY_COUNT 10 /* number of error retry */ +#define CALIBRATOIN_RETRY_WAIT 10 /* wait time(ms) for retry */ + +/* Debug macros */ +#define CALIBRATION_DEBUG(fmt, ...) {if (mDebug) {fprintf(stdout, "%s:%d "fmt, __func__, __LINE__, ##__VA_ARGS__); fflush(stdout);}} +#define CALIBRATION_INFO(fmt, ...) {if (mDebug) {fprintf(stdout, "%s:%d "fmt, __func__, __LINE__, ##__VA_ARGS__); fflush(stdout);}} +#define CALIBRATION_PRINT(...) {fprintf(stdout, ##__VA_ARGS__); fflush(stdout);} + +#endif /*_ICO_ICTL_TOUCH_EGALAX_H_*/ + |