Merge "Update packages changelog." into 2.0alpha-wayland
[profile/ivi/ico-uxf-device-input-controller.git] / joystick_gtforce / ico_ictl-joystick.c
1 /*
2  * Copyright (c) 2013, TOYOTA MOTOR CORPORATION.
3  *
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
7  *
8  */
9 /**
10  * @brief   Device Input Controller(GtForce joystick)
11  * @brief   joystick input event to Input Manager
12  *
13  * @date    Feb-08-2013
14  */
15
16 #include    <stdio.h>
17 #include    <stdlib.h>
18 #include    <unistd.h>
19 #include    <strings.h>
20 #include    <errno.h>
21 #include    <pthread.h>
22 #include    <sys/ioctl.h>
23 #include    <linux/joystick.h>
24 #include    <glib.h>
25
26 #include    "ico_ictl-local.h"
27
28 /* type definition                                                                  */
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)        */
35 }   Ico_ICtl_JS;
36
37 typedef struct  _Ico_Ictl_Code  {
38     unsigned short          code;               /* code value                       */
39     char                    name[20];           /* code name                        */
40 }   Ico_Ictl_Code;
41
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                  */
49 }   Ico_ICtl_JS_Input;
50
51 /* prototype of static function                                                     */
52 static void PrintUsage(const char *pName);
53
54 /* table/variable                                                                   */
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)       */
60
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;
66
67 /* static functions                 */
68 /*--------------------------------------------------------------------------*/
69 /**
70  * @brief   ico_ictl_find_input_by_name: find Input Table by input switch name
71  *
72  * @param[in]   name        input switch name
73  * @return  result
74  * @retval  !=NULL      success(Input Table address)
75  * @retval  ==NULL      failed
76  */
77 /*--------------------------------------------------------------------------*/
78 static Ico_ICtl_JS_Input *
79 ico_ictl_find_input_by_name(const char *name)
80 {
81     Ico_ICtl_JS_Input   *iMng = NULL;
82     int                  ii;
83
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];
87             break;
88         }
89     }
90     return iMng;
91 }
92
93 /*--------------------------------------------------------------------------*/
94 /**
95  * @brief   ico_ictl_find_input_by_param: find Input Table by input switch type and number
96  *
97  * @param[in]   type        input event type (of Linux Input subsystem)
98  * @param[in]   number      input event number (of Linux Input subsystem)
99  * @return  result
100  * @retval  !=NULL      success(Input Table address)
101  * @retval  ==NULL      failed
102  */
103 /*--------------------------------------------------------------------------*/
104 static Ico_ICtl_JS_Input *
105 ico_ictl_find_input_by_param(int type, int number)
106 {
107     Ico_ICtl_JS_Input   *iMng = NULL;
108     int                  ii;
109
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];
114             break;
115         }
116     }
117     return iMng;
118 }
119
120 /*--------------------------------------------------------------------------*/
121 /**
122  * @brief   conf_getUint: convert integer string to value
123  *
124  * @param[in]   str         integer string
125  * @return  result
126  * @retval  >=0         success(converted vaule)
127  * @retval  -1          failed
128  */
129 /*--------------------------------------------------------------------------*/
130 static int
131 conf_getUint(const char *str)
132 {
133     int     key = -1;
134     char    *errpt;
135
136     if (str != NULL)    {
137         errpt = NULL;
138         key = strtol(str, &errpt, 0);
139         if ((errpt) && (*errpt != 0))  {
140             key = -1;
141         }
142     }
143     return key;
144 }
145
146 /*--------------------------------------------------------------------------*/
147 /**
148  * @brief   conf_countNumericalKey: get configuration list
149  *
150  * @param[in]   keyfile     configuration file
151  * @param[in]   group       configuration key group name
152  * @return  result
153  * @retval  !=NULL          success(configuration list)
154  * @retval  ==NULL          failed
155  */
156 /*--------------------------------------------------------------------------*/
157 static GList *
158 conf_countNumericalKey(GKeyFile *keyfile, const char *group)
159 {
160     GList* list=NULL;
161     char **result;
162     gsize length;
163     int i;
164
165     result = g_key_file_get_keys(keyfile, group, &length, NULL);
166
167     for (i = 0; i < (int)length; i++) {
168         int id = conf_getUint(result[i]);
169         if (id >= 0) {
170             list=g_list_append(list, g_strdup(result[i]));
171         }
172     }
173     g_strfreev(result);
174     return list;
175 }
176
177 /*--------------------------------------------------------------------------*/
178 /**
179  * @brief   conf_appendStr: connect strings
180  *
181  * @param[in]   str1        string 1
182  * @param[in]   str2        string 2
183  * @return  connected string
184  */
185 /*--------------------------------------------------------------------------*/
186 static char *
187 conf_appendStr(const char *str1, const char *str2)
188 {
189     static char buf[128];
190     snprintf(buf, sizeof(buf)-1, "%s%s", str1, str2);
191     return buf;
192 }
193
194 /*--------------------------------------------------------------------------*/
195 /**
196  * @brief   ico_ictl_read_conf: read configuration file
197  *
198  * @param[in]   file        configuration file path name
199  * @return  result
200  * @retval  ICO_ICTL_OK     sccess
201  * @retval  ICO_ICTL_ERR    failed
202  */
203 /*--------------------------------------------------------------------------*/
204 static int
205 ico_ictl_read_conf(const char *file)
206 {
207     DEBUG_PRINT("ico_ictl_read_conf: Enter(file=%s)", file);
208
209     GKeyFile            *keyfile;
210     GKeyFileFlags       flags;
211     GString             *filepath;
212     GList               *idlist;
213     GError              *error = NULL;
214     Ico_ICtl_JS_Input   *iMng;
215     char                *name;
216     gsize               length;
217     int                 ii, jj;
218
219     keyfile = g_key_file_new();
220     flags = G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS;
221
222     filepath = g_string_new(file);
223
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);
227         return ICO_ICTL_ERR;
228     }
229     g_string_free(filepath, TRUE);
230
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);
234     if (name)   {
235         strncpy(gIco_ICtrl_JS.device, name, sizeof(gIco_ICtrl_JS.device)-1);
236     }
237     name = g_key_file_get_string(keyfile, "device", "ictl", &error);
238     if (name)   {
239         strncpy(gIco_ICtrl_JS.ictl, name, sizeof(gIco_ICtrl_JS.ictl)-1);
240     }
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);
243
244     /* count number of key in [input] section   */
245     idlist = conf_countNumericalKey(keyfile, "input");
246     length = g_list_length(idlist);
247     if (length <= 0)    {
248         length = 1;
249     }
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");
254         exit(1);
255     }
256     memset((char *)gIco_ICtrl_JS_Input, 0, sizeof(Ico_ICtl_JS_Input) * length);
257
258     for (ii = 0; ii < (int)length; ii++) {
259         const char  *g = "input";
260         char        *key = (char *)g_list_nth_data(idlist, ii);
261         gsize       listsize;
262         gint        *attr;
263         gchar       **code;
264
265         name = g_key_file_get_string(keyfile, g, key, &error);
266         if (name == NULL)   continue;
267
268         iMng = ico_ictl_find_input_by_name(name);
269         if (iMng != NULL)   {
270             /* multiple define  */
271             ERROR_PRINT("ico_ictl_read_conf: switch name(%s) re-define", name);
272             continue;
273         }
274         iMng = &gIco_ICtrl_JS_Input[nIco_ICtrl_JS_Input];
275
276         iMng->input = conf_getUint(key);
277         strncpy(iMng->name, name, sizeof(iMng->name)-1);
278
279         /* event            */
280         attr = g_key_file_get_integer_list(keyfile, g, conf_appendStr(key, ".event"),
281                                            &listsize, &error);
282         if (listsize < 2)   continue;
283         iMng->type = attr[0];
284         iMng->number = attr[1];
285
286         /* code             */
287         code = g_key_file_get_string_list(keyfile, g, conf_appendStr(key, ".code"),
288                                           &listsize, &error);
289         if ((code == NULL) || (listsize <= 0))  {
290             strcpy(iMng->code[0].name, iMng->name);
291         }
292         else    {
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';
298                     p ++;
299                 }
300                 if (*p) {
301                     p ++;
302                     strncpy(iMng->code[jj].name, p, sizeof(iMng->code[jj].name)-1);
303                 }
304                 if (iMng->code[jj].name[0] == 0)    {
305                     strcpy(iMng->code[jj].name, iMng->name);
306                 }
307             }
308         }
309         if (code)   g_strfreev(code);
310
311         nIco_ICtrl_JS_Input ++;
312
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);
317     }
318     DEBUG_PRINT("ico_ictl_read_conf: Leave");
319
320     return ICO_ICTL_OK;
321 }
322
323 /*--------------------------------------------------------------------------*/
324 /**
325  * @brief   ico_ictl_js_open: open input jyostick input device
326  *
327  * @param[in]   ictlDevName     device name
328  * @return  result
329  * @retval  >= 0            sccess(device file descriptor)
330  * @retval  ICO_ICTL_ERR    failed
331  */
332 /*--------------------------------------------------------------------------*/
333 static int
334 ico_ictl_js_open(const char *ictlDevName)
335 {
336     DEBUG_PRINT("ico_ictl_js_open: Enter(device=%s)", ictlDevName)
337
338     int                 fd = -1;
339     char                devFile[64];
340     char                devName[64];
341     int                 ii, jj, kk;
342
343     if (ictlDevName == NULL) {
344         ERROR_PRINT("ico_ictl_js_open: Leave(failed devname NULL)");
345         return ICO_ICTL_ERR;
346     }
347
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);
351         mPseudo = 1;
352     }
353     else    {
354         pdev = (char *)ictlDevName;
355     }
356     for (ii = 0; ii < 16; ii++) {
357         if (mPseudo)    {
358             snprintf(devFile, 64, "/dev/input/event%d", ii);
359         }
360         else    {
361             snprintf(devFile, 64, "/dev/input/js%d", ii);
362         }
363         fd = open(devFile, O_RDONLY | O_NONBLOCK);
364         if (fd < 0)     continue;
365
366         memset(devName, 0, sizeof(devName));
367         if (mPseudo)    {
368             ioctl(fd, EVIOCGNAME(sizeof(devName)), devName);
369         }
370         else    {
371             ioctl(fd, JSIOCGNAME(sizeof(devName)), devName);
372         }
373         kk = 0;
374         for (jj = 0; devName[jj]; jj++) {
375             if (devName[jj] != ' ') {
376                 devName[kk++] = devName[jj];
377             }
378         }
379         devName[kk] = 0;
380         DEBUG_PRINT("ico_ictl_js_open: %d.%s", ii+1, devName);
381
382         if (strncasecmp(devName, pdev, sizeof(devName)) == 0)   break;
383         /* not match, close */
384         close(fd);
385         fd = -1;
386     }
387
388     if (fd < 0) {
389         ERROR_PRINT("ico_ictl_js_open: Leave(not find device file)");
390         return ICO_ICTL_ERR;
391     }
392     DEBUG_PRINT("ico_ictl_js_open: Leave(found %s[%s] as %s)", pdev, devFile, ictlDevName);
393     return fd;
394 }
395
396 /*--------------------------------------------------------------------------*/
397 /**
398  * @brief   ico_ictl_js_read: read input jyostick input device
399  *
400  * @param[in]   fd          file descriptor
401  * @return      nothing
402  */
403 /*--------------------------------------------------------------------------*/
404 static void
405 ico_ictl_js_read(int fd)
406 {
407     DEBUG_PRINT("ico_ictl_js_read: Enter(fd=%d)", fd)
408
409     struct js_event     events[8];
410     struct input_event  pevents[8];
411     int                 rSize;
412     int                 ii, jj;
413     int                 number, value, type, code, state;
414
415     if (mPseudo)    {
416         /* Pseudo event input for Debug */
417         rSize = read(fd, pevents, sizeof(pevents));
418         if (rSize > 0)  {
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;
427                 }
428                 else if ((events[ii].type == 1) && (events[ii].number == 9))    {
429                     events[ii].number = 0;
430                 }
431                 DEBUG_PRINT("ico_ictl_js_read: pseude event.%d %d.%d.%d",
432                             ii, events[ii].type, events[ii].number, events[ii].value);
433             }
434             rSize = ii * sizeof(struct js_event);
435         }
436     }
437     else    {
438         rSize = read(fd, events, sizeof(events));
439     }
440     if (rSize < 0)  {
441         ii = errno;
442         if ((ii == EINTR) || (ii == EAGAIN))    {
443             return;
444         }
445         DEBUG_PRINT("ico_ictl_js_read: Leave(read error[%d])", ii)
446         exit(9);
447     }
448     for (ii = 0; ii < (rSize / (int)sizeof(struct js_event)); ii++) {
449         Ico_ICtl_JS_Input   *iMng = NULL;
450
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);
456
457         iMng = ico_ictl_find_input_by_param(type, number);
458         if (iMng == NULL) {
459             continue;
460         }
461
462         if (mEventLog)  {
463             struct timeval  curtime;
464             gettimeofday(&curtime, NULL);
465
466             if (lastEvent.tv_sec)   {
467                 int     sec, usec;
468
469                 sec = curtime.tv_sec - lastEvent.tv_sec;
470                 usec = curtime.tv_usec - lastEvent.tv_usec;
471
472                 if (usec < 0)   {
473                     sec -= 1;
474                     usec += 1000000;
475                 }
476                 usec += 500;
477                 if( usec >= 1000000 )   {
478                     usec -= 1000000;
479                     sec += 1;
480                 }
481                 if ((sec > 0) || ((sec == 0) && (usec >= 10000)))   {
482                     lastEvent.tv_sec = curtime.tv_sec;
483                     lastEvent.tv_usec = curtime.tv_usec;
484                 }
485             }
486             else    {
487                 lastEvent.tv_sec = curtime.tv_sec;
488                 lastEvent.tv_usec = curtime.tv_usec;
489             }
490             for (jj = 0;
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))  {
494                     break;
495                 }
496             }
497         }
498
499         if (iMng->code[1].code != 0)    {
500             if (value < 0) {
501                 code = iMng->code[0].code;
502                 state = WL_KEYBOARD_KEY_STATE_PRESSED;
503                 iMng->last = code;
504             }
505             else if (value > 0) {
506                 code = iMng->code[1].code;
507                 state = WL_KEYBOARD_KEY_STATE_PRESSED;
508                 iMng->last = code;
509             }
510             else {
511                 if (iMng->last != iMng->code[0].code && iMng->last != iMng->code[1].code) {
512                     continue;
513                 }
514                 code = iMng->last;
515                 state = WL_KEYBOARD_KEY_STATE_RELEASED;
516                 iMng->last = -1;
517             }
518         }
519         else    {
520             if (value == 0) {
521                 code = iMng->code[0].code;
522                 state = WL_KEYBOARD_KEY_STATE_RELEASED;
523             }
524             else if (value == 1) {
525                 code = iMng->code[0].code;
526                 state = WL_KEYBOARD_KEY_STATE_PRESSED;
527             }
528             else {
529                 continue;
530             }
531         }
532         ico_input_mgr_device_input_event(gIco_ICtrl_Mng.Wayland_InputMgr, events[ii].time,
533                                          gIco_ICtrl_JS.device, iMng->input, code, state);
534     }
535 }
536
537 /*--------------------------------------------------------------------------*/
538 /**
539  * @brief   signal_int: signal handler
540  *
541  * @param[in]   signum      signal number(unused)
542  * @return      nothing
543  */
544 /*--------------------------------------------------------------------------*/
545 static void
546 signal_int(int signum)
547 {
548     gRunning = 0;
549 }
550
551 /*--------------------------------------------------------------------------*/
552 /**
553  * @brief   Device Input Controllers: For Joy Stick
554  *          main routine
555  *
556  * @param   main() finction's standard parameter (argc,argv)
557  * @return  result
558  * @retval  0       success
559  * @retval  1       failed
560  */
561 /*--------------------------------------------------------------------------*/
562 int main(int argc, char *argv[])
563 {
564     struct epoll_event  ev_ret[16];
565     char                *ictlDevName = "DrivingForceGT";
566     int                 JSfd;
567     int                 ii, jj;
568     int                 ret;
569     struct sigaction    sigint;
570
571     /* get device name from parameter   */
572     for (ii = 1; ii < argc; ii++) {
573         if (strcasecmp( argv[ii], "-h") == 0) {
574             PrintUsage(argv[0]);
575             exit( 0 );
576         }
577         else if (strcasecmp( argv[ii], "-d") == 0) {
578             /* debug    */
579             mDebug = 1;
580         }
581         else if (strcasecmp( argv[ii], "-l") == 0) {
582             /* event input log  */
583             mEventLog = 1;
584         }
585         else {
586             ictlDevName = argv[ii];
587         }
588     }
589
590     /* change to daemon */
591     if (! mDebug) {
592         if (daemon(0, 1) < 0) {
593             fprintf(stderr, "%s: Can not Create Daemon\n", argv[0]);
594             exit(1);
595         }
596     }
597
598     /* open joystick    */
599     JSfd = ico_ictl_js_open(ictlDevName);
600     if (JSfd < 0) {
601         ERROR_PRINT("main: Leave(Error device open)");
602         exit(1);
603     }
604     gIco_ICtrl_JS.fd = JSfd;
605
606     /* read conf file   */
607     char *confpath = getenv(ICO_ICTL_CONF_ENV);
608     if (!confpath)  {
609         confpath = ICO_ICTL_CONF_FILE;
610     }
611     ico_ictl_read_conf(confpath);
612
613     /* initialize wayland   */
614     ico_ictl_wayland_init(NULL, NULL);
615     ico_ictl_add_fd(JSfd);
616
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);
629         }
630     }
631
632     /* signal init  */
633     sigint.sa_handler = signal_int;
634     sigemptyset(&sigint.sa_mask);
635     sigint.sa_flags = SA_RESETHAND;
636     sigaction(SIGINT, &sigint, NULL);
637
638     /* main loop    */
639     while (gRunning) {
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);
644             }
645         }
646     }
647     ico_ictl_wayland_finish();
648
649     exit(0);
650 }
651
652 static void PrintUsage(const char *pName)
653 {
654     fprintf( stderr, "Usage: %s [-h] [-d] DeviceName\n", pName );
655     fprintf( stderr, "       ex)\n");
656     fprintf( stderr, "          %s \"Driving Force GT\"\n", pName);
657 }
658