2 * Copyright (c) 2013, TOYOTA MOTOR CORPORATION.
4 * This program is licensed under the terms and conditions of the
5 * Apache License, version 2.0. The full text of the Apache License is at
6 * http://www.apache.org/licenses/LICENSE-2.0
10 * @brief Device Input Controller(GtForce joystick)
11 * @brief joystick input event to Input Manager
22 #include <sys/ioctl.h>
23 #include <linux/joystick.h>
26 #include "ico_ictl-local.h"
29 typedef struct _Ico_ICtl_JS {
30 int fd; /* device file fd */
31 char device[32]; /* device name */
32 char ictl[32]; /* input controller name */
33 int type; /* device type */
34 int hostid; /* host Id(currently unused) */
37 typedef struct _Ico_Ictl_Code {
38 unsigned short code; /* code value */
39 char name[20]; /* code name */
42 typedef struct _Ico_ICtl_JS_Input {
43 char name[20]; /* input switch name */
44 int input; /* input number */
45 int type; /* input event type */
46 int number; /* input event number */
47 Ico_Ictl_Code code[20]; /* key code */
48 int last; /* last input code */
51 /* prototype of static function */
52 static void PrintUsage(const char *pName);
55 int mPseudo = 0; /* pseudo input device for test */
56 int mDebug = 0; /* debug mode */
57 int mEventLog = 0; /* event input log */
58 struct timeval lastEvent = { 0, 0 }; /* last input event time */
59 int gRunning = 1; /* run state(1:run, 0:finish) */
61 /* Input Contorller Table */
62 Ico_ICtl_Mng gIco_ICtrl_Mng = { 0 };
63 Ico_ICtl_JS gIco_ICtrl_JS = { 0 };
64 int nIco_ICtrl_JS_Input = 0;
65 Ico_ICtl_JS_Input *gIco_ICtrl_JS_Input = NULL;
67 /* static functions */
68 /*--------------------------------------------------------------------------*/
70 * @brief ico_ictl_find_input_by_name: find Input Table by input switch name
72 * @param[in] name input switch name
74 * @retval !=NULL success(Input Table address)
75 * @retval ==NULL failed
77 /*--------------------------------------------------------------------------*/
78 static Ico_ICtl_JS_Input *
79 ico_ictl_find_input_by_name(const char *name)
81 Ico_ICtl_JS_Input *iMng = NULL;
84 for (ii = 0; ii < nIco_ICtrl_JS_Input; ii++) {
85 if (strncasecmp(name, gIco_ICtrl_JS_Input[ii].name, 16) == 0) {
86 iMng = &gIco_ICtrl_JS_Input[ii];
93 /*--------------------------------------------------------------------------*/
95 * @brief ico_ictl_find_input_by_param: find Input Table by input switch type and number
97 * @param[in] type input event type (of Linux Input subsystem)
98 * @param[in] number input event number (of Linux Input subsystem)
100 * @retval !=NULL success(Input Table address)
101 * @retval ==NULL failed
103 /*--------------------------------------------------------------------------*/
104 static Ico_ICtl_JS_Input *
105 ico_ictl_find_input_by_param(int type, int number)
107 Ico_ICtl_JS_Input *iMng = NULL;
110 for (ii = 0; ii < nIco_ICtrl_JS_Input; ii++) {
111 if ((gIco_ICtrl_JS_Input[ii].type == type)
112 && (gIco_ICtrl_JS_Input[ii].number == number)) {
113 iMng = &gIco_ICtrl_JS_Input[ii];
120 /*--------------------------------------------------------------------------*/
122 * @brief conf_getUint: convert integer string to value
124 * @param[in] str integer string
126 * @retval >=0 success(converted vaule)
129 /*--------------------------------------------------------------------------*/
131 conf_getUint(const char *str)
138 key = strtol(str, &errpt, 0);
139 if ((errpt) && (*errpt != 0)) {
146 /*--------------------------------------------------------------------------*/
148 * @brief conf_countNumericalKey: get configuration list
150 * @param[in] keyfile configuration file
151 * @param[in] group configuration key group name
153 * @retval !=NULL success(configuration list)
154 * @retval ==NULL failed
156 /*--------------------------------------------------------------------------*/
158 conf_countNumericalKey(GKeyFile *keyfile, const char *group)
165 result = g_key_file_get_keys(keyfile, group, &length, NULL);
167 for (i = 0; i < (int)length; i++) {
168 int id = conf_getUint(result[i]);
170 list=g_list_append(list, g_strdup(result[i]));
177 /*--------------------------------------------------------------------------*/
179 * @brief conf_appendStr: connect strings
181 * @param[in] str1 string 1
182 * @param[in] str2 string 2
183 * @return connected string
185 /*--------------------------------------------------------------------------*/
187 conf_appendStr(const char *str1, const char *str2)
189 static char buf[128];
190 snprintf(buf, sizeof(buf)-1, "%s%s", str1, str2);
194 /*--------------------------------------------------------------------------*/
196 * @brief ico_ictl_read_conf: read configuration file
198 * @param[in] file configuration file path name
200 * @retval ICO_ICTL_OK sccess
201 * @retval ICO_ICTL_ERR failed
203 /*--------------------------------------------------------------------------*/
205 ico_ictl_read_conf(const char *file)
207 DEBUG_PRINT("ico_ictl_read_conf: Enter(file=%s)", file);
213 GError *error = NULL;
214 Ico_ICtl_JS_Input *iMng;
219 keyfile = g_key_file_new();
220 flags = G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS;
222 filepath = g_string_new(file);
224 if (! g_key_file_load_from_file(keyfile, filepath->str, flags, &error)) {
225 ERROR_PRINT("ico_ictl_read_conf: Leave(can not open conf file)");
226 g_string_free(filepath, TRUE);
229 g_string_free(filepath, TRUE);
231 /* count number of key in [device] section */
232 memset((char *)&gIco_ICtrl_JS, 0, sizeof(gIco_ICtrl_JS));
233 name = g_key_file_get_string(keyfile, "device", "name", &error);
235 strncpy(gIco_ICtrl_JS.device, name, sizeof(gIco_ICtrl_JS.device)-1);
237 name = g_key_file_get_string(keyfile, "device", "ictl", &error);
239 strncpy(gIco_ICtrl_JS.ictl, name, sizeof(gIco_ICtrl_JS.ictl)-1);
241 gIco_ICtrl_JS.type = g_key_file_get_integer(keyfile, "device", "type", &error);
242 gIco_ICtrl_JS.hostid = g_key_file_get_integer(keyfile, "device", "ecu", &error);
244 /* count number of key in [input] section */
245 idlist = conf_countNumericalKey(keyfile, "input");
246 length = g_list_length(idlist);
250 nIco_ICtrl_JS_Input = 0;
251 gIco_ICtrl_JS_Input = (Ico_ICtl_JS_Input *)malloc(sizeof(Ico_ICtl_JS_Input) * length);
252 if (! gIco_ICtrl_JS_Input) {
253 ERROR_PRINT("joystick_gtforce: No Memory");
256 memset((char *)gIco_ICtrl_JS_Input, 0, sizeof(Ico_ICtl_JS_Input) * length);
258 for (ii = 0; ii < (int)length; ii++) {
259 const char *g = "input";
260 char *key = (char *)g_list_nth_data(idlist, ii);
265 name = g_key_file_get_string(keyfile, g, key, &error);
266 if (name == NULL) continue;
268 iMng = ico_ictl_find_input_by_name(name);
270 /* multiple define */
271 ERROR_PRINT("ico_ictl_read_conf: switch name(%s) re-define", name);
274 iMng = &gIco_ICtrl_JS_Input[nIco_ICtrl_JS_Input];
276 iMng->input = conf_getUint(key);
277 strncpy(iMng->name, name, sizeof(iMng->name)-1);
280 attr = g_key_file_get_integer_list(keyfile, g, conf_appendStr(key, ".event"),
282 if (listsize < 2) continue;
283 iMng->type = attr[0];
284 iMng->number = attr[1];
287 code = g_key_file_get_string_list(keyfile, g, conf_appendStr(key, ".code"),
289 if ((code == NULL) || (listsize <= 0)) {
290 strcpy(iMng->code[0].name, iMng->name);
293 if ((int)listsize > 20) listsize = 20;
294 for (jj = 0; jj < (int)listsize; jj++) {
295 char *p = (char *)code[jj];
296 while ((*p != 0) && (*p != ':')) {
297 iMng->code[jj].code = iMng->code[jj].code * 10 + *p - '0';
302 strncpy(iMng->code[jj].name, p, sizeof(iMng->code[jj].name)-1);
304 if (iMng->code[jj].name[0] == 0) {
305 strcpy(iMng->code[jj].name, iMng->name);
309 if (code) g_strfreev(code);
311 nIco_ICtrl_JS_Input ++;
313 DEBUG_PRINT("%s input:%d(type=%d,number=%d,code=%d[%s],%d[%s])",
314 iMng->name, iMng->input, iMng->type, iMng->number,
315 iMng->code[0].code, iMng->code[0].name,
316 iMng->code[1].code, iMng->code[1].name);
318 DEBUG_PRINT("ico_ictl_read_conf: Leave");
323 /*--------------------------------------------------------------------------*/
325 * @brief ico_ictl_js_open: open input jyostick input device
327 * @param[in] ictlDevName device name
329 * @retval >= 0 sccess(device file descriptor)
330 * @retval ICO_ICTL_ERR failed
332 /*--------------------------------------------------------------------------*/
334 ico_ictl_js_open(const char *ictlDevName)
336 DEBUG_PRINT("ico_ictl_js_open: Enter(device=%s)", ictlDevName)
343 if (ictlDevName == NULL) {
344 ERROR_PRINT("ico_ictl_js_open: Leave(failed devname NULL)");
348 char *pdev = getenv(ICO_ICTL_INPUT_DEV);
349 if ((pdev != NULL) && (*pdev != 0)) {
350 DEBUG_PRINT("ico_ictl_js_open: Pseudo input device(%s)", pdev);
354 pdev = (char *)ictlDevName;
356 for (ii = 0; ii < 16; ii++) {
358 snprintf(devFile, 64, "/dev/input/event%d", ii);
361 snprintf(devFile, 64, "/dev/input/js%d", ii);
363 fd = open(devFile, O_RDONLY | O_NONBLOCK);
364 if (fd < 0) continue;
366 memset(devName, 0, sizeof(devName));
368 ioctl(fd, EVIOCGNAME(sizeof(devName)), devName);
371 ioctl(fd, JSIOCGNAME(sizeof(devName)), devName);
374 for (jj = 0; devName[jj]; jj++) {
375 if (devName[jj] != ' ') {
376 devName[kk++] = devName[jj];
380 DEBUG_PRINT("ico_ictl_js_open: %d.%s", ii+1, devName);
382 if (strncasecmp(devName, pdev, sizeof(devName)) == 0) break;
383 /* not match, close */
389 ERROR_PRINT("ico_ictl_js_open: Leave(not find device file)");
392 DEBUG_PRINT("ico_ictl_js_open: Leave(found %s[%s] as %s)", pdev, devFile, ictlDevName);
396 /*--------------------------------------------------------------------------*/
398 * @brief ico_ictl_js_read: read input jyostick input device
400 * @param[in] fd file descriptor
403 /*--------------------------------------------------------------------------*/
405 ico_ictl_js_read(int fd)
407 DEBUG_PRINT("ico_ictl_js_read: Enter(fd=%d)", fd)
409 struct js_event events[8];
410 struct input_event pevents[8];
413 int number, value, type, code, state;
416 /* Pseudo event input for Debug */
417 rSize = read(fd, pevents, sizeof(pevents));
419 for (ii = 0; ii < rSize/((int)sizeof(struct input_event)); ii++) {
420 events[ii].time = (pevents[ii].time.tv_sec % 1000) * 1000 +
421 pevents[ii].time.tv_usec / 1000;
422 events[ii].type = pevents[ii].type;
423 events[ii].number = pevents[ii].code;
424 events[ii].value = pevents[ii].value;
425 if ((events[ii].type == 2) && (events[ii].value == 9)) {
426 events[ii].value = 0;
428 else if ((events[ii].type == 1) && (events[ii].number == 9)) {
429 events[ii].number = 0;
431 DEBUG_PRINT("ico_ictl_js_read: pseude event.%d %d.%d.%d",
432 ii, events[ii].type, events[ii].number, events[ii].value);
434 rSize = ii * sizeof(struct js_event);
438 rSize = read(fd, events, sizeof(events));
442 if ((ii == EINTR) || (ii == EAGAIN)) {
445 DEBUG_PRINT("ico_ictl_js_read: Leave(read error[%d])", ii)
448 for (ii = 0; ii < (rSize / (int)sizeof(struct js_event)); ii++) {
449 Ico_ICtl_JS_Input *iMng = NULL;
451 type = events[ii].type;
452 number = events[ii].number;
453 value = events[ii].value;
454 DEBUG_PRINT("ico_ictl_js_read: Read(type=%d, number=%d, value=%d",
455 type, number, value);
457 iMng = ico_ictl_find_input_by_param(type, number);
463 struct timeval curtime;
464 gettimeofday(&curtime, NULL);
466 if (lastEvent.tv_sec) {
469 sec = curtime.tv_sec - lastEvent.tv_sec;
470 usec = curtime.tv_usec - lastEvent.tv_usec;
477 if( usec >= 1000000 ) {
481 if ((sec > 0) || ((sec == 0) && (usec >= 10000))) {
482 lastEvent.tv_sec = curtime.tv_sec;
483 lastEvent.tv_usec = curtime.tv_usec;
487 lastEvent.tv_sec = curtime.tv_sec;
488 lastEvent.tv_usec = curtime.tv_usec;
491 jj < (int)(sizeof(gIco_ICtrl_JS_Input)/sizeof(Ico_ICtl_JS_Input)); jj++) {
492 if ((type == gIco_ICtrl_JS_Input[jj].type) &&
493 (number == gIco_ICtrl_JS_Input[jj].number)) {
499 if (iMng->code[1].code != 0) {
501 code = iMng->code[0].code;
502 state = WL_KEYBOARD_KEY_STATE_PRESSED;
505 else if (value > 0) {
506 code = iMng->code[1].code;
507 state = WL_KEYBOARD_KEY_STATE_PRESSED;
511 if (iMng->last != iMng->code[0].code && iMng->last != iMng->code[1].code) {
515 state = WL_KEYBOARD_KEY_STATE_RELEASED;
521 code = iMng->code[0].code;
522 state = WL_KEYBOARD_KEY_STATE_RELEASED;
524 else if (value == 1) {
525 code = iMng->code[0].code;
526 state = WL_KEYBOARD_KEY_STATE_PRESSED;
532 ico_input_mgr_device_input_event(gIco_ICtrl_Mng.Wayland_InputMgr, events[ii].time,
533 gIco_ICtrl_JS.device, iMng->input, code, state);
537 /*--------------------------------------------------------------------------*/
539 * @brief signal_int: signal handler
541 * @param[in] signum signal number(unused)
544 /*--------------------------------------------------------------------------*/
546 signal_int(int signum)
551 /*--------------------------------------------------------------------------*/
553 * @brief Device Input Controllers: For Joy Stick
556 * @param main() finction's standard parameter (argc,argv)
561 /*--------------------------------------------------------------------------*/
562 int main(int argc, char *argv[])
564 struct epoll_event ev_ret[16];
565 char *ictlDevName = "DrivingForceGT";
569 struct sigaction sigint;
571 /* get device name from parameter */
572 for (ii = 1; ii < argc; ii++) {
573 if (strcasecmp( argv[ii], "-h") == 0) {
577 else if (strcasecmp( argv[ii], "-d") == 0) {
581 else if (strcasecmp( argv[ii], "-l") == 0) {
582 /* event input log */
586 ictlDevName = argv[ii];
590 /* change to daemon */
592 if (daemon(0, 1) < 0) {
593 fprintf(stderr, "%s: Can not Create Daemon\n", argv[0]);
599 JSfd = ico_ictl_js_open(ictlDevName);
601 ERROR_PRINT("main: Leave(Error device open)");
604 gIco_ICtrl_JS.fd = JSfd;
607 char *confpath = getenv(ICO_ICTL_CONF_ENV);
609 confpath = ICO_ICTL_CONF_FILE;
611 ico_ictl_read_conf(confpath);
613 /* initialize wayland */
614 ico_ictl_wayland_init(NULL, NULL);
615 ico_ictl_add_fd(JSfd);
617 /* send configuration informations to Multi Input Manager */
618 for (ii = 0; ii < nIco_ICtrl_JS_Input; ii++) {
619 ico_input_mgr_device_configure_input(
620 gIco_ICtrl_Mng.Wayland_InputMgr, gIco_ICtrl_JS.device, gIco_ICtrl_JS.type,
621 gIco_ICtrl_JS_Input[ii].name, gIco_ICtrl_JS_Input[ii].input,
622 gIco_ICtrl_JS_Input[ii].code[0].name, gIco_ICtrl_JS_Input[ii].code[0].code);
623 for (jj = 1; jj < 20; jj++) {
624 if (gIco_ICtrl_JS_Input[ii].code[jj].code == 0) break;
625 ico_input_mgr_device_configure_code(
626 gIco_ICtrl_Mng.Wayland_InputMgr, gIco_ICtrl_JS.device,
627 gIco_ICtrl_JS_Input[ii].input, gIco_ICtrl_JS_Input[ii].code[jj].name,
628 gIco_ICtrl_JS_Input[ii].code[jj].code);
633 sigint.sa_handler = signal_int;
634 sigemptyset(&sigint.sa_mask);
635 sigint.sa_flags = SA_RESETHAND;
636 sigaction(SIGINT, &sigint, NULL);
640 ret = ico_ictl_wayland_iterate(ev_ret, 200);
641 for (ii = 0; ii < ret; ii++) {
642 if (ev_ret[ii].data.fd == JSfd) {
643 ico_ictl_js_read(JSfd);
647 ico_ictl_wayland_finish();
652 static void PrintUsage(const char *pName)
654 fprintf( stderr, "Usage: %s [-h] [-d] DeviceName\n", pName );
655 fprintf( stderr, " ex)\n");
656 fprintf( stderr, " %s \"Driving Force GT\"\n", pName);