Support Tizen 3.0
[profile/ivi/ico-uxf-weston-plugin.git] / src / ico_input_mgr.c
1 /*
2  * Copyright © 2010-2011 Intel Corporation
3  * Copyright © 2008-2011 Kristian Høgsberg
4  * Copyright © 2013 TOYOTA MOTOR CORPORATION.
5  *
6  * Permission to use, copy, modify, distribute, and sell this software and
7  * its documentation for any purpose is hereby granted without fee, provided
8  * that the above copyright notice appear in all copies and that both that
9  * copyright notice and this permission notice appear in supporting
10  * documentation, and that the name of the copyright holders not be used in
11  * advertising or publicity pertaining to distribution of the software
12  * without specific, written prior permission.  The copyright holders make
13  * no representations about the suitability of this software for any
14  * purpose.  It is provided "as is" without express or implied warranty.
15  *
16  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
17  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
18  * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
19  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
20  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
21  * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
22  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23  */
24 /**
25  * @brief   Multi Input Manager (Weston(Wayland) PlugIn)
26  *
27  * @date    Jul-26-2013
28  */
29
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <stdbool.h>
33 #include <string.h>
34 #include <unistd.h>
35 #include <linux/input.h>
36 #include <assert.h>
37 #include <signal.h>
38 #include <math.h>
39 #include <time.h>
40 #include <sys/types.h>
41
42 #include <wayland-server.h>
43 #include <weston/compositor.h>
44 #include "ico_ivi_common.h"
45 #include "ico_ivi_shell.h"
46 #include "ico_window_mgr.h"
47 #include "ico_input_mgr.h"
48 #include "ico_input_mgr-server-protocol.h"
49
50 /* degine maximum length                */
51 #define ICO_MINPUT_DEVICE_LEN           32
52 #define ICO_MINPUT_SW_LEN               20
53 #define ICO_MINPUT_MAX_CODES            20
54
55 /* structure definition */
56 /* working table of Multi Input Manager */
57 struct ico_input_mgr {
58     struct weston_compositor *compositor;   /* Weston Compositor                    */
59     struct wl_list  ictl_list;              /* Input Controller List                */
60     struct wl_list  app_list;               /* application List                     */
61     struct wl_resource *inputmgr;
62 };
63
64 /* Input Switch Table                   */
65 struct ico_ictl_code {
66     uint16_t    code;                       /* input code numner                    */
67     char        name[ICO_MINPUT_SW_LEN];    /* input code name                      */
68 };
69
70 struct ico_ictl_input {
71     struct wl_list link;                    /* link                                 */
72     char        swname[ICO_MINPUT_SW_LEN];  /* input switch name                    */
73     int32_t     input;                      /* input Id                             */
74     uint16_t    fix;                        /* fixed assign to application          */
75     uint16_t    ncode;                      /* number of codes                      */
76     struct ico_ictl_code code[ICO_MINPUT_MAX_CODES];   /* codes                     */
77     struct ico_app_mgr  *app;               /* send event tagret application        */
78 };
79
80 /* Input Controller Management Table    */
81 struct ico_ictl_mgr {
82     struct wl_list link;                    /* link                                 */
83     struct wl_client    *client;            /* client                               */
84     struct wl_resource  *resource;          /* resource                             */
85     char    device[ICO_MINPUT_DEVICE_LEN];  /* device name                          */
86     int     type;                           /* device type                          */
87     struct wl_list ico_ictl_input;          /* list of input switchs                */
88 };
89
90 /* Application Management Table */
91 struct ico_app_mgr {
92     struct wl_list link;                    /* link                                 */
93     struct wl_client    *client;            /* client                               */
94     struct wl_resource  *resource;          /* resource for send event              */
95     struct wl_resource  *mgr_resource;      /* resource as manager(if NULL, client) */
96     char    appid[ICO_IVI_APPID_LENGTH];    /* application id                       */
97 };
98
99 /* prototype of static function */
100 /* bind input manager form manager(ex.HomeScreen)   */
101 static void ico_control_bind(struct wl_client *client, void *data,
102                              uint32_t version, uint32_t id);
103 /* unbind input manager form manager(ex.HomeScreen) */
104 static void ico_control_unbind(struct wl_resource *resource);
105 /* bind input manager form input controller         */
106 static void ico_device_bind(struct wl_client *client, void *data,
107                             uint32_t version, uint32_t id);
108 /* unbind input manager form input controller       */
109 static void ico_device_unbind(struct wl_resource *resource);
110 /* bind input manager (form application)            */
111 static void ico_exinput_bind(struct wl_client *client, void *data,
112                              uint32_t version, uint32_t id);
113 /* unbind input manager (form application)          */
114 static void ico_exinput_unbind(struct wl_resource *resource);
115
116 /* find ictl manager by device name */
117 static struct ico_ictl_mgr *find_ictlmgr_by_device(const char *device);
118 /* find ictl input switch by input Id */
119 static struct ico_ictl_input *find_ictlinput_by_input(struct ico_ictl_mgr *pIctlMgr,
120                                                       const int32_t input);
121 /* find app manager by application Id */
122 static struct ico_app_mgr *find_app_by_appid(const char *appid);
123 /* add input event to application     */
124 static void ico_mgr_add_input_app(struct wl_client *client, struct wl_resource *resource,
125                                   const char *appid, const char *device, int32_t input,
126                                   int32_t fix, int32_t keycode);
127 /* delete input event to application  */
128 static void ico_mgr_del_input_app(struct wl_client *client, struct wl_resource *resource,
129                                   const char *appid, const char *device, int32_t input);
130 /* create and regist Input Controller table */
131 static void ico_device_configure_input(struct wl_client *client,
132                                        struct wl_resource *resource, const char *device,
133                                        int32_t type, const char *swname, int32_t input,
134                                        const char *codename, int32_t code);
135 /* add input to from Input Controller table */
136 static void ico_device_configure_code(struct wl_client *client,
137                                       struct wl_resource *resource, const char *device,
138                                       int32_t input, const char *codename, int32_t code);
139 /* device input event                       */
140 static void ico_device_input_event(struct wl_client *client, struct wl_resource *resource,
141                                    uint32_t time, const char *device,
142                                    int32_t input, int32_t code, int32_t state);
143
144 /* definition of Wayland protocol */
145 /* mgr interface */
146 static const struct ico_input_mgr_control_interface ico_input_mgr_implementation = {
147     ico_mgr_add_input_app,
148     ico_mgr_del_input_app,
149 };
150
151 /* Input Controller interface */
152 static const struct ico_input_mgr_device_interface input_mgr_ictl_implementation = {
153     ico_device_configure_input,
154     ico_device_configure_code,
155     ico_device_input_event
156 };
157
158 /* definition of class variable */
159 struct ico_input_mgr    *pInputMgr = NULL;
160
161 /* implementation */
162 /*--------------------------------------------------------------------------*/
163 /**
164  * @brief   ico_mgr_add_input_app: add input event to application from HomeScreen.
165  *
166  * @param[in]   client          client(HomeScreen)
167  * @param[in]   resource        resource of request
168  * @param[in]   appid           target application id
169  * @param[in]   device          device name
170  * @param[in]   input           input switch number
171  * @param[in]   fix             fix to application(1=fix,0=general)
172  * @param[in]   keycode         switch map to keyboard operation(0=not map to keyboard)
173  * @return      none
174  */
175 /*--------------------------------------------------------------------------*/
176 static void
177 ico_mgr_add_input_app(struct wl_client *client, struct wl_resource *resource,
178                       const char *appid, const char *device, int32_t input,
179                       int32_t fix, int32_t keycode)
180 {
181     uifw_trace("ico_mgr_add_input_app: Enter(appid=%s,dev=%s,input=%d,fix=%d,key=%d)",
182                appid, device, input, fix, keycode);
183
184     struct ico_ictl_mgr     *pIctlMgr;
185     struct ico_ictl_input   *pInput;
186     struct ico_app_mgr      *pAppMgr;
187
188     pIctlMgr = find_ictlmgr_by_device(device);
189     if (! pIctlMgr) {
190         /* not configure input controller, create   */
191         ico_device_configure_input(NULL, NULL, device, 0, NULL, input, NULL, 0);
192         pIctlMgr = find_ictlmgr_by_device(device);
193         if (! pIctlMgr) {
194             uifw_error("ico_mgr_add_input_app: Leave(No Memory)");
195             return;
196         }
197     }
198     pInput = find_ictlinput_by_input(pIctlMgr, input);
199     if (! pInput)   {
200         /* not configure input switch, create   */
201         ico_device_configure_input(NULL, NULL, device, 0, NULL, input, NULL, 0);
202         pInput = find_ictlinput_by_input(pIctlMgr, input);
203         if (! pInput)   {
204             uifw_error("ico_mgr_add_input_app: Leave(No Memory)");
205             return;
206         }
207     }
208
209     /* find application         */
210     pAppMgr = find_app_by_appid(appid);
211     if (! pAppMgr)  {
212         /* create Application Management Table  */
213         pAppMgr = (struct ico_app_mgr *)malloc(sizeof(struct ico_app_mgr));
214         if (! pAppMgr)  {
215             uifw_error("ico_mgr_add_input_app: Leave(No Memory)");
216             return;
217         }
218         memset(pAppMgr, 0, sizeof(struct ico_app_mgr));
219         strncpy(pAppMgr->appid, appid, sizeof(pAppMgr->appid)-1);
220         wl_list_insert(pInputMgr->app_list.prev, &pAppMgr->link);
221     }
222
223     pInput->app = pAppMgr;
224     pInput->fix = fix;
225     uifw_trace("ico_mgr_add_input_app: Leave(%s.%s[%d] assign to %s)",
226                pIctlMgr->device, pInput->swname ? pInput->swname : "(NULL)", input,
227                pAppMgr->appid);
228 }
229
230 /*--------------------------------------------------------------------------*/
231 /**
232  * @brief   ico_mgr_del_input_app: delete input event at application from HomeScreen.
233  *
234  * @param[in]   client          client(HomeScreen)
235  * @param[in]   resource        resource of request
236  * @param[in]   appid           target application id,
237  *                              if NULL, all applictions without fixed assign switch
238  * @param[in]   device          device name
239  *                              if NULL, all device without fixed assign switch
240  * @param[in]   input           input switch number
241  *                              if -1, all input without fixed assign switch
242  * @return      none
243  */
244 /*--------------------------------------------------------------------------*/
245 static void
246 ico_mgr_del_input_app(struct wl_client *client, struct wl_resource *resource,
247                       const char *appid, const char *device, int32_t input)
248 {
249     uifw_trace("ico_mgr_del_input_app: Enter(appid=%s,dev=%s,input=%d)",
250                appid ? appid : "(NULL)", device ? device : "(NULL)", input);
251
252     int     alldev = 0;
253     struct ico_ictl_mgr     *pIctlMgr = NULL;
254     struct ico_ictl_input   *pInput = NULL;
255     struct ico_app_mgr      *pAppMgr;
256
257     if ((device != NULL) && (*device != 0)) {
258         pIctlMgr = find_ictlmgr_by_device(device);
259         if (! pIctlMgr) {
260             /* not configure input controller, NOP  */
261             uifw_trace("ico_mgr_del_input_app: Leave(%s dose not exist)", device);
262             return;
263         }
264         if (input >= 0) {
265             pInput = find_ictlinput_by_input(pIctlMgr, input);
266             if (! pInput)   {
267                 /* not configure input switch, NOP  */
268                 uifw_trace("ico_mgr_del_input_app: Leave(%s.%d dose not exist)",
269                            device, input);
270                 return;
271             }
272         }
273     }
274     else    {
275         alldev = 1;
276     }
277
278     /* find application         */
279     if ((appid != NULL) && (*appid != 0))   {
280         pAppMgr = find_app_by_appid(appid);
281         if (! pAppMgr)  {
282             /* application dose not exist, NOP  */
283             uifw_trace("ico_mgr_del_input_app: Leave(app.%s dose not exist)", appid);
284             return;
285         }
286         if (alldev == 0)    {
287             if (input >= 0) {
288                 if (pInput->app != pAppMgr) {
289                     /* not same application, NOP        */
290                     uifw_trace("ico_mgr_del_input_app: Leave(%s.%d not app.%s, current %s)",
291                                device, input, appid,
292                                pInput->app ? pInput->app->appid : "(NULL)");
293                     return;
294                 }
295                 uifw_trace("ico_mgr_del_input_app: Leave(%s.%d app.%s deleted)",
296                            device, input, appid);
297                 pInput->app = NULL;
298                 return;
299             }
300             else    {
301                 wl_list_for_each (pInput, &pIctlMgr->ico_ictl_input, link)  {
302                     if ((pInput->fix == 0) && (pInput->app == pAppMgr))   {
303                         uifw_trace("ico_mgr_del_input_app: %s.%d app.%s deleted",
304                                    pIctlMgr->device, pInput->input, appid);
305                         pInput->app = NULL;
306                     }
307                 }
308             }
309         }
310         else    {
311             /* reset all device without fixed assign    */
312             wl_list_for_each (pIctlMgr, &pInputMgr->ictl_list, link)    {
313                 wl_list_for_each (pInput, &pIctlMgr->ico_ictl_input, link)  {
314                     if ((pInput->fix == 0) && (pInput->app == pAppMgr))   {
315                         uifw_trace("ico_mgr_del_input_app: %s.%d app.%s deleted",
316                                    pIctlMgr->device, pInput->input, pInput->app->appid);
317                         pInput->app = NULL;
318                     }
319                 }
320             }
321         }
322     }
323     else    {
324         if (alldev == 0)    {
325             if (input >= 0) {
326                 if ((pInput->fix == 0) && (pInput->app != NULL))    {
327                     uifw_trace("ico_mgr_del_input_app: %s.%d app.%s deleted",
328                                pIctlMgr->device, pInput->input, pInput->app->appid);
329                     pInput->app = NULL;
330                 }
331             }
332             else    {
333                 wl_list_for_each (pInput, &pIctlMgr->ico_ictl_input, link)  {
334                     if ((pInput->fix == 0) && (pInput->app != NULL))    {
335                         uifw_trace("ico_mgr_del_input_app: %s.%d app.%s deleted",
336                                pIctlMgr->device, pInput->input, pInput->app->appid);
337                         pInput->app = NULL;
338                     }
339                 }
340             }
341         }
342         else    {
343             /* reset all application without fixed assign       */
344             wl_list_for_each (pIctlMgr, &pInputMgr->ictl_list, link)    {
345                 wl_list_for_each (pInput, &pIctlMgr->ico_ictl_input, link)  {
346                     if ((pInput->fix == 0) && (pInput->app != NULL))    {
347                         uifw_trace("ico_mgr_del_input_app: %s.%d app.%s deleted",
348                                    pIctlMgr->device, pInput->input, pInput->app->appid);
349                         pInput->app = NULL;
350                     }
351                 }
352             }
353         }
354     }
355     uifw_trace("ico_mgr_del_input_app: Leave");
356 }
357
358 /*--------------------------------------------------------------------------*/
359 /**
360  * @brief   ico_device_configure_input: configure input device and input switch
361  *          from Device Input Controller.
362  *
363  * @param[in]   client          client(Device Input Controller)
364  * @param[in]   resource        resource of request
365  * @param[in]   device          device name
366  * @param[in]   type            device type(saved but unused)
367  * @param[in]   swname          input switch name
368  * @param[in]   input           input switch number
369  * @param[in]   codename        input code name
370  * @param[in]   code            input code number
371  * @return      none
372  */
373 /*--------------------------------------------------------------------------*/
374 static void
375 ico_device_configure_input(struct wl_client *client, struct wl_resource *resource,
376                            const char *device, int32_t type, const char *swname,
377                            int32_t input, const char *codename, int32_t code)
378 {
379     uifw_trace("ico_device_configure_input: Enter(client=%08x,dev=%s,type=%d,swname=%s,"
380                "input=%d,code=%d[%s])", (int)client, device, type,
381                swname ? swname : "(NULL)", input, code, codename ? codename : " ");
382
383     struct ico_ictl_mgr     *pIctlMgr;
384     struct ico_ictl_input   *pInput;
385     struct ico_app_mgr      *pAppMgr;
386
387     pIctlMgr = find_ictlmgr_by_device(device);
388     if (! pIctlMgr) {
389         /* create ictl mgr table */
390         pIctlMgr = (struct ico_ictl_mgr *)malloc(sizeof(struct ico_ictl_mgr));
391         if (pIctlMgr == NULL) {
392             uifw_error("ico_device_configure_input: Leave(No Memory)");
393             return;
394         }
395         uifw_trace("ico_device_configure_input: create pIctlMgr(mgr=%08x,input=%d)",
396                    (int)pIctlMgr, input);
397         memset(pIctlMgr, 0, sizeof(struct ico_ictl_mgr));
398         wl_list_init(&pIctlMgr->ico_ictl_input);
399         strncpy(pIctlMgr->device, device, sizeof(pIctlMgr->device)-1);
400
401         /* add list */
402         wl_list_insert(pInputMgr->ictl_list.prev, &pIctlMgr->link);
403     }
404     pIctlMgr->client = client;
405     pIctlMgr->resource = resource;
406     if (type)   {
407         pIctlMgr->type = type;
408     }
409
410     /* search and add input switch  */
411     wl_list_for_each (pInput, &pIctlMgr->ico_ictl_input, link)  {
412         if (pInput->input == input)     break;
413     }
414     if (&pInput->link == &pIctlMgr->ico_ictl_input)    {
415         uifw_trace("ico_device_configure_input: create %s.%s(%d) switch",
416                    device, swname, input);
417         pInput = (struct ico_ictl_input *)malloc(sizeof(struct ico_ictl_input));
418         if (pInput == NULL) {
419             uifw_error("ico_device_configure_input: Leave(No Memory)");
420             return;
421         }
422         memset(pInput, 0, sizeof(struct ico_ictl_input));
423         if (swname) {
424             strncpy(pInput->swname, swname, sizeof(pInput->swname)-1);
425         }
426         else    {
427             strcpy(pInput->swname, "(Unknown)");
428         }
429         wl_list_insert(pIctlMgr->ico_ictl_input.prev, &pInput->link);
430     }
431     if (swname) {
432         strncpy(pInput->swname, swname, sizeof(pInput->swname)-1);
433     }
434     pInput->input = input;
435     memset(pInput->code, 0, sizeof(pInput->code));
436     pInput->ncode = 1;
437     pInput->code[0].code = code;
438     if (codename)   {
439         strncpy(pInput->code[0].name, codename, sizeof(pInput->code[0].name)-1);
440     }
441
442     if (client == NULL) {
443         /* internal call for table create   */
444         uifw_trace("ico_device_configure_input: Leave(table create)");
445         return;
446     }
447
448     /* send to application and manager(ex.HomeScreen)   */
449     wl_list_for_each (pAppMgr, &pInputMgr->app_list, link)  {
450         if (pAppMgr->resource == NULL)  continue;
451         if ((pInput->app != NULL) && (pInput->app != pAppMgr) && (pInput->fix)) continue;
452
453         uifw_trace("ico_device_configure_input: send capabilities to app(%s) %s.%s[%d]",
454                    pAppMgr->appid, device, pInput->swname, input);
455         ico_exinput_send_capabilities(pAppMgr->resource, device, pIctlMgr->type,
456                                       pInput->swname, input,
457                                       pInput->code[0].name, pInput->code[0].code);
458     }
459     uifw_trace("ico_device_configure_input: Leave");
460 }
461
462 /*--------------------------------------------------------------------------*/
463 /**
464  * @brief   ico_device_configure_code: add input switch from Device Input Controller.
465  *
466  * @param[in]   client          client(Device Input Controller)
467  * @param[in]   resource        resource of request
468  * @param[in]   device          device name
469  * @param[in]   input           input switch number
470  * @param[in]   codename        input code name
471  * @param[in]   code            input code number
472  * @return      none
473  */
474 /*--------------------------------------------------------------------------*/
475 static void
476 ico_device_configure_code(struct wl_client *client, struct wl_resource *resource,
477                           const char *device, int32_t input,
478                           const char *codename, int32_t code)
479 {
480     uifw_trace("ico_device_configure_code: Enter(client=%08x,dev=%s,input=%d,code=%d[%s])",
481                (int)client, device, input, code, codename ? codename : " ");
482
483     int     i;
484     struct ico_ictl_mgr     *pIctlMgr;
485     struct ico_ictl_input   *pInput;
486     struct ico_app_mgr      *pAppMgr;
487
488     pIctlMgr = find_ictlmgr_by_device(device);
489     if (! pIctlMgr) {
490         uifw_warn("ico_device_configure_code: Leave(dev=%s dose not exist)", device);
491         return;
492     }
493     /* search input switch      */
494     wl_list_for_each (pInput, &pIctlMgr->ico_ictl_input, link)  {
495         if (pInput->input == input)     break;
496     }
497     if (&pInput->link == &pIctlMgr->ico_ictl_input)    {
498         uifw_warn("ico_device_configure_code: Leave(input=%s.%d dose not exist)",
499                   device, input);
500         return;
501     }
502
503     /* search input code        */
504     for (i = 0; i < pInput->ncode; i++) {
505         if (pInput->code[i].code == code)   break;
506     }
507     if (i >= pInput->ncode) {
508         /* code dose not exist, add */
509         if (pInput->ncode >= ICO_MINPUT_MAX_CODES) {
510             uifw_warn("ico_device_configure_code: Leave(input=%s.%d code overflow)",
511                       device, input);
512             return;
513         }
514         i = pInput->ncode;
515         pInput->ncode ++;
516         pInput->code[i].code = code;
517     }
518     memset(pInput->code[i].name, 0, sizeof(pInput->code[i].name));
519     strncpy(pInput->code[i].name, codename, sizeof(pInput->code[i].name)-1);
520
521     /* send to application and manager(ex.HomeScreen)   */
522     wl_list_for_each (pAppMgr, &pInputMgr->app_list, link)  {
523         if (pAppMgr->resource == NULL)  continue;
524         if ((pInput->app != NULL) && (pInput->app != pAppMgr) && (pInput->fix)) continue;
525         uifw_trace("ico_device_configure_input: send code to app(%s) %s.%s[%d]",
526                    pAppMgr->appid, device, pInput->swname, input);
527         ico_exinput_send_code(pAppMgr->resource, device, input,
528                               pInput->code[i].name, pInput->code[i].code);
529     }
530     uifw_trace("ico_device_configure_code: Leave");
531 }
532
533 /*--------------------------------------------------------------------------*/
534 /**
535  * @brief   ico_device_input_event: device input event from Device Input Controller.
536  *
537  * @param[in]   client          client(Device Input Controller)
538  * @param[in]   resource        resource of request
539  * @param[in]   time            device input time(miri-sec)
540  * @param[in]   device          device name
541  * @param[in]   input           input switch number
542  * @param[in]   code            input code number
543  * @param[in]   state           input state(1=On, 0=Off)
544  * @return      none
545  */
546 /*--------------------------------------------------------------------------*/
547 static void
548 ico_device_input_event(struct wl_client *client, struct wl_resource *resource,
549                        uint32_t time, const char *device,
550                        int32_t input, int32_t code, int32_t state)
551 {
552     uifw_trace("ico_device_input_event: Enter(time=%d,dev=%s,input=%d,code=%d,state=%d)",
553                time, device, input, code, state);
554
555     struct ico_ictl_mgr     *pIctlMgr;
556     struct ico_ictl_input   *pInput;
557
558     /* find input devcie by client      */
559     pIctlMgr = find_ictlmgr_by_device(device);
560     if (! pIctlMgr) {
561         uifw_error("ico_device_input_event: Leave(Unknown client(%08x))", (int)client);
562         return;
563     }
564     /* find input switch by input Id    */
565     pInput = find_ictlinput_by_input(pIctlMgr, input);
566     if (! pInput) {
567         uifw_warn("ico_device_input_event: Leave(Unknown input(%s,%d))",
568                   pIctlMgr->device, input);
569         return;
570     }
571
572     if (! pInput->app)  {
573         uifw_trace("ico_device_input_event: Leave(%s.%s not assign)",
574                   pIctlMgr->device, pInput->swname);
575         return;
576     }
577
578     /* send event to application        */
579     uifw_trace("ico_device_input_event: send event=%s.%s[%d],%d,%d to App.%s",
580                pIctlMgr->device, pInput->swname, input, code, state, pInput->app->appid);
581     ico_exinput_send_input(pInput->app->resource, time, pIctlMgr->device,
582                            input, code, state);
583
584     uifw_trace("ico_device_input_event: Leave");
585 }
586
587 /*--------------------------------------------------------------------------*/
588 /**
589  * @brief   ico_control_bind: ico_input_mgr_control bind from HomeScreen
590  *
591  * @param[in]   client          client(HomeScreen)
592  * @param[in]   data            data(unused)
593  * @param[in]   version         protocol version(unused)
594  * @param[in]   id              client object id
595  * @return      none
596  */
597 /*--------------------------------------------------------------------------*/
598 static void
599 ico_control_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id)
600 {
601     char                    *appid;
602     struct ico_app_mgr      *pAppMgr;
603
604     uifw_trace("ico_control_bind: Enter(client=%08x)", (int)client);
605     appid = ico_window_mgr_get_appid(client);
606
607     if (! appid)    {
608         /* client dose not exist        */
609         uifw_warn("ico_control_bind: Leave(client=%08x dose not exist)", (int)client);
610         return;
611     }
612
613     /* find application         */
614     pAppMgr = find_app_by_appid(appid);
615     if (! pAppMgr)  {
616         /* create Application Management Table  */
617         pAppMgr = (struct ico_app_mgr *)malloc(sizeof(struct ico_app_mgr));
618         if (! pAppMgr)  {
619             uifw_error("ico_control_bind: Leave(No Memory)");
620             return;
621         }
622         memset(pAppMgr, 0, sizeof(struct ico_app_mgr));
623         strncpy(pAppMgr->appid, appid, sizeof(pAppMgr->appid)-1);
624         wl_list_insert(pInputMgr->app_list.prev, &pAppMgr->link);
625     }
626     pAppMgr->client = client;
627     if (! pAppMgr->mgr_resource)    {
628         pAppMgr->mgr_resource = wl_resource_create(client,
629                                                    &ico_input_mgr_control_interface, 1, id);
630         if (pAppMgr->mgr_resource)  {
631             wl_resource_set_implementation(pAppMgr->mgr_resource,
632                                            &ico_input_mgr_implementation,
633                                            pInputMgr, ico_control_unbind);
634         }
635     }
636     uifw_trace("ico_control_bind: Leave");
637 }
638
639 /*--------------------------------------------------------------------------*/
640 /**
641  * @brief   ico_control_unbind: ico_input_mgr_control unbind from HomeScreen
642  *
643  * @param[in]   resource        client resource(HomeScreen)
644  * @return      none
645  */
646 /*--------------------------------------------------------------------------*/
647 static void
648 ico_control_unbind(struct wl_resource *resource)
649 {
650     struct ico_app_mgr      *pAppMgr;
651
652     uifw_trace("ico_control_unbind: Enter(resource=%08x)", (int)resource);
653
654     wl_list_for_each (pAppMgr, &pInputMgr->app_list, link)  {
655         if (pAppMgr->mgr_resource == resource)  {
656             uifw_trace("ico_control_unbind: find app.%s", pAppMgr->appid);
657             pAppMgr->mgr_resource = NULL;
658             break;
659         }
660     }
661     uifw_trace("ico_control_unbind: Leave");
662 }
663
664 /*--------------------------------------------------------------------------*/
665 /**
666  * @brief   ico_device_bind: ico_input_mgr_device bind from Device Input Controller
667  *
668  * @param[in]   client          client(Device Input Controller)
669  * @param[in]   data            data(unused)
670  * @param[in]   version         protocol version(unused)
671  * @param[in]   id              client object id
672  * @return      none
673  */
674 /*--------------------------------------------------------------------------*/
675 static void
676 ico_device_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id)
677 {
678     struct wl_resource *mgr_resource;
679
680     uifw_trace("ico_device_bind: Enter(client=%08x)", (int)client);
681
682     mgr_resource = wl_resource_create(client, &ico_input_mgr_device_interface, 1, id);
683     if (mgr_resource)   {
684         wl_resource_set_implementation(mgr_resource, &input_mgr_ictl_implementation,
685                                        NULL, ico_device_unbind);
686     }
687     uifw_trace("ico_device_bind: Leave");
688 }
689
690 /*--------------------------------------------------------------------------*/
691 /**
692  * @brief   ico_device_unbind: ico_input_mgr_device unbind from Device Input Controller
693  *
694  * @param[in]   resource        client resource(Device Input Controller)
695  * @return      none
696  */
697 /*--------------------------------------------------------------------------*/
698 static void
699 ico_device_unbind(struct wl_resource *resource)
700 {
701     uifw_trace("ico_device_unbind: Enter(resource=%08x)", (int)resource);
702     uifw_trace("ico_device_unbind: Leave");
703 }
704
705 /*--------------------------------------------------------------------------*/
706 /**
707  * @brief   ico_exinput_bind: ico_exinput bind from Application
708  *
709  * @param[in]   client          client(Application)
710  * @param[in]   data            data(unused)
711  * @param[in]   version         protocol version(unused)
712  * @param[in]   id              client object id
713  * @return      none
714  */
715 /*--------------------------------------------------------------------------*/
716 static void
717 ico_exinput_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id)
718 {
719     int                     i;
720     char                    *appid;
721     struct ico_app_mgr      *pAppMgr;
722     struct ico_ictl_mgr     *pIctlMgr;
723     struct ico_ictl_input   *pInput;
724
725     appid = ico_window_mgr_get_appid(client);
726     uifw_trace("ico_exinput_bind: Enter(client=%08x,%s)", (int)client,
727                appid ? appid : "(NULL)");
728
729     if (! appid)    {
730         /* client dose not exist        */
731         uifw_warn("ico_exinput_bind: Leave(client=%08x dose not exist)", (int)client);
732         return;
733     }
734
735     /* find application         */
736     pAppMgr = find_app_by_appid(appid);
737     if (! pAppMgr)  {
738         /* create Application Management Table  */
739         pAppMgr = (struct ico_app_mgr *)malloc(sizeof(struct ico_app_mgr));
740         if (! pAppMgr)  {
741             uifw_error("ico_exinput_bind: Leave(No Memory)");
742             return;
743         }
744         memset(pAppMgr, 0, sizeof(struct ico_app_mgr));
745         strncpy(pAppMgr->appid, appid, sizeof(pAppMgr->appid)-1);
746         wl_list_insert(pInputMgr->app_list.prev, &pAppMgr->link);
747         uifw_trace("ico_exinput_bind: Create App.%s table", appid);
748     }
749     pAppMgr->client = client;
750     if (! pAppMgr->resource)    {
751         pAppMgr->resource = wl_resource_create(client, &ico_exinput_interface, 1, id);
752         if (pAppMgr->resource)  {
753             wl_resource_set_implementation(pAppMgr->resource, NULL,
754                                            pInputMgr, ico_exinput_unbind);
755         }
756     }
757
758     /* send all capabilities    */
759     wl_list_for_each (pIctlMgr, &pInputMgr->ictl_list, link)    {
760         if (pIctlMgr->client == NULL)   {
761             uifw_trace("ico_exinput_bind: Input controller.%s not initialized",
762                        pIctlMgr->device);
763             continue;
764         }
765
766         wl_list_for_each (pInput, &pIctlMgr->ico_ictl_input, link)  {
767             if (pInput->swname[0] == 0) {
768                 uifw_trace("ico_exinput_bind: Input %s not initialized", pIctlMgr->device);
769                 continue;
770             }
771             if ((pInput->app != NULL) && (pInput->app != pAppMgr) && (pInput->fix)) {
772                 uifw_trace("ico_exinput_bind: Input %s.%s fixed assign to App.%s",
773                            pIctlMgr->device, pInput->swname, pInput->app->appid);
774                 continue;
775             }
776             uifw_trace("ico_exinput_bind: send capabilities to app(%s) %s.%s[%d]",
777                        pAppMgr->appid, pIctlMgr->device, pInput->swname, pInput->input);
778             ico_exinput_send_capabilities(pAppMgr->resource, pIctlMgr->device,
779                                           pIctlMgr->type, pInput->swname, pInput->input,
780                                           pInput->code[0].name, pInput->code[0].code);
781             for (i = 1; i < pInput->ncode; i++) {
782                 ico_exinput_send_code(pAppMgr->resource, pIctlMgr->device, pInput->input,
783                                       pInput->code[i].name, pInput->code[i].code);
784             }
785         }
786     }
787     uifw_trace("ico_exinput_bind: Leave");
788 }
789
790 /*--------------------------------------------------------------------------*/
791 /**
792  * @brief   ico_exinput_unbind: ico_exinput unbind from Application
793  *
794  * @param[in]   resource        client resource(Application)
795  * @return      none
796  */
797 /*--------------------------------------------------------------------------*/
798 static void
799 ico_exinput_unbind(struct wl_resource *resource)
800 {
801     struct ico_app_mgr      *pAppMgr;
802     struct ico_app_mgr      *pAppMgrTmp;
803     struct ico_ictl_mgr     *pIctlMgr;
804     struct ico_ictl_input   *pInput;
805     int                     fix = 0;
806
807     uifw_trace("ico_exinput_unbind: Enter(resource=%08x)", (int)resource);
808
809     wl_list_for_each_safe (pAppMgr, pAppMgrTmp, &pInputMgr->app_list, link) {
810         if (pAppMgr->resource == resource)  {
811             uifw_trace("ico_exinput_unbind: find app.%s", pAppMgr->appid);
812
813             /* release application from input switch    */
814             wl_list_for_each (pIctlMgr, &pInputMgr->ictl_list, link)    {
815                 wl_list_for_each (pInput, &pIctlMgr->ico_ictl_input, link)  {
816                     if (pInput->app == pAppMgr) {
817                         if (pInput->fix == 0)   {
818                             uifw_trace("ico_exinput_unbind: app.%s remove %s.%s",
819                                        pAppMgr->appid, pIctlMgr->device, pInput->swname);
820                             pInput->app = NULL;
821                         }
822                         else    {
823                             uifw_trace("ico_exinput_unbind: app.%s fix assign %s.%s",
824                                        pAppMgr->appid, pIctlMgr->device, pInput->swname);
825                             fix ++;
826                         }
827                     }
828                 }
829             }
830             if (fix == 0)   {
831                 wl_list_remove(&pAppMgr->link);
832                 free(pAppMgr);
833             }
834             else    {
835                 pAppMgr->client = NULL;
836                 pAppMgr->resource = NULL;
837             }
838         }
839     }
840     uifw_trace("ico_exinput_unbind: Leave");
841 }
842
843 /*--------------------------------------------------------------------------*/
844 /**
845  * @brief   find_ictlmgr_by_device: find Input Controller by device name
846  *
847  * @param[in]   device          device name
848  * @return      Input Controller Manager table address
849  * @retval      !=NULL          address
850  * @retval      ==NULL          not exist
851  */
852 /*--------------------------------------------------------------------------*/
853 static struct ico_ictl_mgr *
854 find_ictlmgr_by_device(const char *device)
855 {
856     struct ico_ictl_mgr     *pIctlMgr;
857
858     wl_list_for_each (pIctlMgr, &pInputMgr->ictl_list, link)    {
859         if (strcmp(pIctlMgr->device, device) == 0)  {
860             return pIctlMgr;
861         }
862     }
863     return NULL;
864 }
865
866 /*--------------------------------------------------------------------------*/
867 /**
868  * @brief   find_ictlinput_by_input: find Input Switch by input Id
869  *
870  * @param[in]   pIctlMgr        Input Controller device
871  * @param[in]   input           Input Id
872  * @return      Input Switch table address
873  * @retval      !=NULL          address
874  * @retval      ==NULL          not exist
875  */
876 /*--------------------------------------------------------------------------*/
877 static struct ico_ictl_input *
878 find_ictlinput_by_input(struct ico_ictl_mgr *pIctlMgr, const int32_t input)
879 {
880     struct ico_ictl_input   *pInput;
881
882     wl_list_for_each (pInput, &pIctlMgr->ico_ictl_input, link)  {
883         if (pInput->input == input) {
884             return pInput;
885         }
886     }
887     return NULL;
888 }
889
890 /*--------------------------------------------------------------------------*/
891 /**
892  * @brief   find_app_by_appid: find Application by application Id
893  *
894  * @param[in]   appid           application Id
895  * @return      Application Management table address
896  * @retval      !=NULL          address
897  * @retval      ==NULL          not exist
898  */
899 /*--------------------------------------------------------------------------*/
900 static struct ico_app_mgr *
901 find_app_by_appid(const char *appid)
902 {
903     struct ico_app_mgr      *pAppMgr;
904
905     wl_list_for_each (pAppMgr, &pInputMgr->app_list, link)  {
906         if (strcmp(pAppMgr->appid, appid) == 0) {
907             return pAppMgr;
908         }
909     }
910     return NULL;
911 }
912
913 /*--------------------------------------------------------------------------*/
914 /**
915  * @brief   module_init: initialization of this plugin
916  *
917  * @param[in]   ec          weston compositor
918  * @param[in]   argc        number of arguments(unused)
919  * @param[in]   argv        argument list(unused)
920  * @return      result
921  * @retval      0           OK
922  * @retval      -1          error
923  */
924 /*--------------------------------------------------------------------------*/
925 WL_EXPORT int
926 module_init(struct weston_compositor *ec, int *argc, char *argv[])
927 {
928     uifw_info("ico_input_mgr: Enter(module_init)");
929
930     /* initialize management table */
931     pInputMgr = (struct ico_input_mgr *)malloc(sizeof(struct ico_input_mgr));
932     if (pInputMgr == NULL) {
933         uifw_trace("ico_input_mgr: malloc failed");
934         return -1;
935     }
936     memset(pInputMgr, 0, sizeof(struct ico_input_mgr));
937     pInputMgr->compositor = ec;
938
939     /* interface to desktop manager(ex.HomeScreen)  */
940     if (wl_global_create(ec->wl_display, &ico_input_mgr_control_interface, 1,
941                          pInputMgr, ico_control_bind) == NULL) {
942         uifw_trace("ico_input_mgr: wl_global_create mgr failed");
943         return -1;
944     }
945
946     /* interface to Input Controller(ictl) */
947     if (wl_global_create(ec->wl_display, &ico_input_mgr_device_interface, 1,
948                          pInputMgr, ico_device_bind) == NULL) {
949         uifw_trace("ico_input_mgr: wl_global_create ictl failed");
950         return -1;
951     }
952
953     /* interface to App(exinput) */
954     if (wl_global_create(ec->wl_display, &ico_exinput_interface, 1,
955                          pInputMgr, ico_exinput_bind) == NULL) {
956         uifw_trace("ico_input_mgr: wl_global_create exseat failed");
957         return -1;
958     }
959
960     /* initialize list */
961     wl_list_init(&pInputMgr->ictl_list);
962     wl_list_init(&pInputMgr->app_list);
963
964     uifw_info("ico_input_mgr: Leave(module_init)");
965     return 0;
966 }
967