Bug fix TIVI-839 ,change the design and permit operation of the music player while...
[profile/ivi/ico-uxf-homescreen.git] / src / home_screen_lib.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   library to communicate with outer process
11  *
12  * @date    Feb-15-2013
13  */
14
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <unistd.h>
18 #include <signal.h>
19 #include <string.h>
20 #include <math.h>
21 #include <glib.h>
22 #include <stdbool.h>
23 #include <sys/epoll.h>
24
25 #include <getopt.h>
26 #include <libwebsockets.h>
27
28 #include <Eina.h>
29 #include <Ecore.h>
30 #include <Ecore_Evas.h>
31 #include <Edje.h>
32
33 #include "ico_uxf.h"
34 #include "ico_uxf_conf_common.h"
35
36 #include "home_screen_parser.h"
37 #include "home_screen.h"
38 #include "home_screen_lib.h"
39
40 /*============================================================================*/
41 /* definition                                                                 */
42 /*============================================================================*/
43 #define WEBSOCKET_MAX_BUFFER    (4096)
44 #define HS_REQ_ANS_HELLO        "REQ_ANS_HELLO"
45 typedef struct _hs_lib_poll hs_lib_poll_t;
46 typedef struct _hs_lib_handle hs_lib_handle_t;
47 typedef struct _hs_lib_msg hs_lib_msg_t;
48
49 /* management connection */
50 struct _hs_lib_handle {
51     hs_lib_handle_t *next; /* next handle                          */
52     int fd; /* Socket file descriptor               */
53     int service_on;
54     int type;
55     struct libwebsocket_context *wsi_context;
56     /* Context of libwebsockets             */
57     struct libwebsocket *wsi; /* WSI of libwebsockets                 */
58     hs_lib_poll_t *poll;
59     char appid[ICO_UXF_MAX_PROCESS_NAME];
60 };
61
62 struct _hs_lib_poll {
63     hs_lib_poll_t *next;
64     int fd;
65     int flags;
66     void *user_data;
67     hs_lib_handle_t *handle;
68 };
69
70 struct _hs_lib_msg {
71     hs_lib_msg_t *next;
72     char *data;
73     int len;
74     int type;
75     hs_lib_handle_t *handle;
76 };
77
78 /*============================================================================*/
79 /* variabe                                                                    */
80 /*============================================================================*/
81 static struct libwebsocket_context *hs_wsicontext = NULL;
82 static hs_lib_msg_t *hs_send_msg = NULL;
83 static hs_lib_msg_t *hs_recv_msg = NULL;
84 static hs_lib_msg_t *hs_free_msg = NULL;
85 static hs_lib_handle_t *hs_handles = NULL;
86 static hs_lib_handle_t *hs_handles_free = NULL;
87 static hs_lib_poll_t *hs_polls = NULL;
88 static hs_lib_poll_t *hs_polls_free = NULL;
89
90 /*============================================================================*/
91 /* Function prototype for static(internal) functions                          */
92 /*============================================================================*/
93 static void hs_lib_handle_command(hs_lib_msg_t *msg);
94 static void hs_lib_handle_application(hs_lib_msg_t *msg);
95 static void hs_lib_handle_onscreen(hs_lib_msg_t *msg);
96 static hs_lib_msg_t *hs_lib_alloc_msg(char *data, int len);
97 static void hs_lib_free_msg(hs_lib_msg_t *msg);
98 static void hs_lib_free_handle(hs_lib_handle_t *handle);
99 static hs_lib_handle_t *hs_lib_alloc_handle(void);
100 static void hs_lib_realsend(hs_lib_msg_t *msg);
101 static hs_lib_msg_t *hs_lib_get_sendmsg(int type);
102 static int hs_lib_put_sendmsg(hs_lib_msg_t *send);
103 static hs_lib_msg_t *hs_lib_get_recvmsg(void);
104 static void hs_lib_put_recvmsg(hs_lib_msg_t *recv);
105 static void hs_lib_com_dispatch(hs_lib_handle_t *_handle, int timeoutms);
106 static void hs_lib_poll_fd_event(hs_lib_poll_t *poll, int flags);
107 static Eina_Bool hs_lib_ecore_fdevent(void *data, Ecore_Fd_Handler *handler);
108 static void hs_lib_control_fd(hs_lib_poll_t *fd_ctl[], const int num_fds);
109 static int hs_lib_add_poll_fd(int fd, int flags);
110 static void hs_lib_del_poll_fd(int fd);
111 static void hs_lib_set_mode_poll_fd(int fd, int flags);
112 static void hs_lib_clear_mode_poll_fd(int fd, int flags);
113 static char *get_parsed_str(char *in, char *out, int len, int arg_idx);
114 static char *getFileName(char *filepath, int len);
115 static int hs_lib_callback_http(struct libwebsocket_context *context,
116                      struct libwebsocket *wsi,
117                      enum libwebsocket_callback_reasons reason, void *user,
118                      void *in, size_t len);
119 static int hs_lib_callback_command(struct libwebsocket_context *context,
120                         struct libwebsocket *wsi,
121                         enum libwebsocket_callback_reasons reason, void *user,
122                         void *in, size_t len);
123 static int hs_lib_callback_statusbar(struct libwebsocket_context *context,
124                           struct libwebsocket *wsi,
125                           enum libwebsocket_callback_reasons reason,
126                           void *user, void *in, size_t len);
127 static int hs_lib_callback_onscreen(struct libwebsocket_context *context,
128                          struct libwebsocket *wsi,
129                          enum libwebsocket_callback_reasons reason, void *user,
130                          void *in, size_t len);
131 static int hs_lib_callback_app(struct libwebsocket_context *context,
132                     struct libwebsocket *wsi,
133                     enum libwebsocket_callback_reasons reason, void *user,
134                     void *in, size_t len);
135
136 /*============================================================================*/
137 /* table                                                                      */
138 /*============================================================================*/
139 static struct libwebsocket_protocols protocols[] = {
140     {
141         "http-only",
142         hs_lib_callback_http,
143         0
144     },
145     { /* HomeScreen - command */
146         ICO_HS_PROTOCOL_CM,
147         hs_lib_callback_command,
148         0
149     },
150     { /* HomeScreen - StatusBar */
151         ICO_HS_PROTOCOL_SB,
152         hs_lib_callback_statusbar,
153         0
154     },
155     { /* HomeScreen - OnScreen */
156         ICO_HS_PROTOCOL_OS,
157         hs_lib_callback_onscreen,
158         0
159     },
160     { /* HomeScreen - OtherNatiiveApps */
161         ICO_HS_PROTOCOL_APP,
162         hs_lib_callback_app,
163         0
164     },
165     {
166         NULL,
167         NULL,
168         0
169     }
170 };
171
172 /*============================================================================*/
173 /* functions                                                                  */
174 /*============================================================================*/
175 /*--------------------------------------------------------------------------*/
176 /**
177  * @brief   hs_lib_handle_command
178  *          callback at received message from external command tools,
179  *          and handle the message.
180  *
181  * @param[in]   msg                 received message
182  * @return      none
183  */
184 /*--------------------------------------------------------------------------*/
185 static void
186 hs_lib_handle_command(hs_lib_msg_t *msg)
187 {
188     int cnt = 0;
189     int ret;
190     char buff[ICO_HS_MSG_SIZE];
191     hs_lib_msg_t *send;
192
193     uifw_trace("hs_lib_handle_command: Enter");
194
195     if (strcmp(msg->data, HS_REQ_ANS_HELLO) == 0) {
196         memset(buff, 0, sizeof(buff));
197
198         send = hs_lib_alloc_msg("ANS HELLO", strlen("ANS HELLO"));
199         if (!send) {
200             uifw_warn("hs_lib_handle_command: ERROR(allocate send msg)");
201             return;
202         }
203         send->type = ICO_HS_PROTOCOL_TYPE_CM;
204
205         hs_lib_put_sendmsg(send);
206
207         uifw_trace("hs_lib_handle_command: Leave");
208
209         return;
210     }
211
212     /* data sent by command is parsed and controlled for the window */
213     ret = hs_parse_form(msg->data, msg->len);
214     if (hs_req_touch == ICO_HS_TOUCH_TOBE_HIDE) {
215         hs_show_appscreen(NULL);
216         hs_control_app_screen();
217     }
218     else if (hs_req_touch == ICO_HS_TOUCH_TOBE_SHOW) {
219         hs_get_tilescreendata();
220         hs_dump_app();
221         hs_req_ctlr_tile();
222     }
223
224     /* return message */
225     memset(buff, 0, sizeof(buff));
226     if (ret == 0) {
227         cnt = snprintf(buff, sizeof(buff), "ANS %s OK", msg->data);
228     }
229     else {
230         cnt = snprintf(buff, sizeof(buff), "ERR %s FAILED", msg->data);
231     }
232
233     if (cnt > 0) {
234         send = hs_lib_alloc_msg(buff, cnt);
235         if (!send) {
236             uifw_warn("hs_lib_handle_command: ERROR(allocate send msg)");
237             return;
238         }
239         send->type = ICO_HS_PROTOCOL_TYPE_CM;
240
241         hs_lib_put_sendmsg(send);
242     }
243
244     uifw_trace("hs_lib_handle_command: Leave");
245 }
246
247 /*--------------------------------------------------------------------------*/
248 /**
249  * @brief   hs_lib_handle_application
250  *          callback at received message from a application, and handle the
251  *          message.
252  *
253  * @param[in]   msg                 received message
254  * @return      none
255  */
256 /*--------------------------------------------------------------------------*/
257 static void
258 hs_lib_handle_application(hs_lib_msg_t *msg)
259 {
260     char *app_id;
261     char msg_data[ICO_HS_MSG_SIZE];
262     char tmp_buf[ICO_HS_MSG_SIZE];
263     char *data = msg->data;
264     hs_lib_msg_t *send;
265
266     uifw_trace("hs_lib_handle_application: Enter");
267
268     if (strncmp("OPEN", data, 4) == 0) {
269         strncpy(msg_data, get_parsed_str(data, tmp_buf, sizeof(tmp_buf), 2),
270                 sizeof(msg_data));
271         app_id = msg_data;
272         uifw_trace("hs_lib_callback_app: app_id = %s, msg_data - %s, in - %s",
273                    app_id, msg_data, data);
274         strncpy(hs_active_onscreen, app_id, sizeof(hs_active_onscreen));
275         strncpy(msg->handle->appid, app_id, sizeof(hs_active_onscreen));
276
277         send = hs_lib_alloc_msg(data, msg->len);
278         if (!send) {
279             uifw_warn("hs_lib_callback_app: ERROR(allocate send msg)");
280             return;
281         }
282         send->type = ICO_HS_PROTOCOL_TYPE_OS;
283
284         hs_lib_put_sendmsg(send);
285     }
286     else if (strncmp("CLOSE", data, 5) == 0) {
287         /* native apps only */
288         hs_hide_onscreen();
289         memset(hs_active_onscreen, 0, sizeof(hs_active_onscreen));
290         /* disconnect app-protocol */
291         if ((msg->handle != NULL) && (msg->handle->wsi != NULL)) {
292             libwebsocket_close_and_free_session(msg->handle->wsi_context,
293                                                 msg->handle->wsi,
294                                                 LWS_CLOSE_STATUS_NORMAL);
295         }
296     }
297     uifw_trace("hs_lib_handle_application: Leave");
298 }
299
300 /*--------------------------------------------------------------------------*/
301 /**
302  * @brief   hs_lib_handle_onscreen
303  *          callback at received message from onscreen, and handle the
304  *          message.
305  *
306  * @param[in]   msg                 received message
307  * @return      none
308  */
309 /*--------------------------------------------------------------------------*/
310 static void
311 hs_lib_handle_onscreen(hs_lib_msg_t *msg)
312 {
313     char msg_buf[ICO_HS_MSG_SIZE];
314     char msg_data[ICO_HS_MSG_SIZE];
315     char tmp_buf[ICO_HS_MSG_SIZE];
316     char *p_msg_data;
317     char *ptr;
318     int ret, idx;
319     const Ico_Uxf_conf_application *appConf = NULL;
320     char *data = msg->data;
321     hs_lib_handle_t *handle;
322     hs_lib_msg_t *send;
323
324     uifw_trace("hs_lib_handle_onscreen: Enter");
325
326     /* init buffers */
327     memset(msg_data, 0x00, sizeof(msg_data));
328     p_msg_data = &msg_data[0];
329     strncpy(p_msg_data, data, msg->len);
330
331     uifw_trace("hs_lib_handle_onscreen: hs_active_onscreen = %s",
332                hs_active_onscreen);
333     /* parse message from OnScreen */
334     if (strncmp("RESULT", p_msg_data, 6) == 0) {
335         /* get 2nd phrase */
336         ptr = get_parsed_str(p_msg_data, tmp_buf, sizeof(tmp_buf), 1);
337         if (strncmp("SUCCESS", ptr, 7) == 0) {
338             /* loaded edje: success */
339             hs_show_onscreen();
340             send = hs_lib_alloc_msg(data, msg->len);
341             if (!send) {
342                 uifw_warn("hs_lib_handle_onscreen: ERROR(allocate send msg)");
343                 return;
344             }
345             send->type = ICO_HS_PROTOCOL_TYPE_APP;
346             hs_lib_put_sendmsg(send);
347         }
348         else if (strncmp("FAILED", ptr, 6) == 0) {
349             /* not loaded edje: failed */
350             if (strcmp(hs_active_onscreen, ICO_UXF_PROC_DEFAULT_HOMESCREEN)
351                     == 0) {
352                 /* appli_list or appli_kill: raise touch layer */
353                 hs_hide_onscreen();
354             }
355             else {
356                 /* native apps: raise own */
357                 hs_hide_onscreen();
358             }
359             memset(hs_active_onscreen, 0, sizeof(hs_active_onscreen));
360             /* disconnect app-protocol */
361             handle = hs_handles;
362             while (handle) {
363                 if (handle->type == ICO_HS_PROTOCOL_TYPE_APP) {
364                     libwebsocket_close_and_free_session(handle->wsi_context,
365                                                         handle->wsi,
366                                                         LWS_CLOSE_STATUS_NORMAL);
367
368                 }
369                 handle = handle->next;
370             }
371         }
372     }
373     else if (strncmp("TOUCH", data, 5) == 0) {
374         if (strlen(hs_active_onscreen) == 0) {
375             /* do nothing */
376         }
377         else if (strcmp(hs_active_onscreen, ICO_UXF_PROC_DEFAULT_HOMESCREEN)
378                  == 0)  {
379             /* get 2nd phrase */
380             ptr = get_parsed_str(p_msg_data, tmp_buf, sizeof(tmp_buf), 1);
381             if (strncmp(getFileName(ptr, strlen(ptr)),
382                         ICO_HS_ONS_APPLI_LIST_NAME,
383                         sizeof(ICO_HS_ONS_APPLI_LIST_NAME)) == 0) {
384                 /* get 3rd phrase */
385                 ptr = get_parsed_str(p_msg_data, tmp_buf, sizeof(tmp_buf), 2);
386                 appConf = ico_uxf_getAppByAppid(ptr);
387                 uifw_trace(
388                            "hs_lib_handle_onscreen: hs_tile_get_index_app = %d(%s)",
389                            (int)appConf, ptr);
390                 if (appConf != NULL) {
391                     sprintf(msg_buf, "FOCUS %s", ptr);
392                     send = hs_lib_alloc_msg(msg_buf, strlen(msg_buf));
393                     if (!send) {
394                         uifw_warn(
395                                   "hs_lib_handle_onscreen: ERROR(allocate send msg)");
396                         return;
397                     }
398                     send->type = ICO_HS_PROTOCOL_TYPE_CM;
399                     ret = hs_lib_put_sendmsg(send);
400                     if (ret < 0) {
401                         ret = ico_uxf_process_execute(ptr);
402                         hs_hide_onscreen();
403                         if ((ret == ICO_UXF_EOK) || (ret == ICO_UXF_EBUSY)) {
404                             idx = hs_tile_get_index_app(ptr);
405                             if (idx < 0) {
406                                 idx = hs_tile_get_minchange();
407                             }
408                             hs_tile_set_app(idx, ptr);
409                         }
410                         hs_tile_show_screen();
411                     }
412                     else {
413                         usleep(100000);
414                         hs_hide_onscreen();
415                     }
416                     memset(hs_active_onscreen, 0, sizeof(hs_active_onscreen));
417                 }
418                 else {
419                     if (strncmp(ptr, "next_bt", 7) == 0) {
420                         hs_get_ons_edj_path(tmp_buf, sizeof(tmp_buf));
421                         sprintf(msg_buf, "OPEN %s%s %s", tmp_buf,
422                                 ICO_HS_ONS_APPLI_LIST_NAME,
423                                 ICO_UXF_PROC_DEFAULT_HOMESCREEN);
424                         uifw_trace("send '%s' to onscreen", msg_buf);
425                         send = hs_lib_alloc_msg(msg_buf, strlen(msg_buf));
426                         if (!send) {
427                             uifw_warn(
428                                       "hs_lib_handle_onscreen: ERROR(allocate send msg)");
429                             return;
430                         }
431                         send->type = ICO_HS_PROTOCOL_TYPE_OS;
432                         (void)hs_lib_put_sendmsg(send);
433                     }
434                     else if (strncmp(ptr, "cancel_bt", 8) == 0) {
435                         hs_hide_onscreen();
436                         memset(hs_active_onscreen, 0,
437                                sizeof(hs_active_onscreen));
438                     }
439                     else {
440                         hs_hide_onscreen();
441                         memset(hs_active_onscreen, 0,
442                                sizeof(hs_active_onscreen));
443                     }
444                 }
445             }
446             else if (strncmp(getFileName(ptr, strlen(ptr)),
447                              ICO_HS_ONS_APPLI_KILL_NAME,
448                              sizeof(ICO_HS_ONS_APPLI_KILL_NAME)) == 0) {
449                 /* get 3rd phrase */
450                 ptr = get_parsed_str(p_msg_data, tmp_buf, sizeof(tmp_buf), 2);
451                 if (strncmp(ptr, "ok_bt", 5) == 0) {
452                     uifw_trace("%s: ok_bt", ICO_HS_ONS_APPLI_KILL_NAME);
453                     if (strlen(hs_kill_appid) == 0) {
454                         hs_hide_onscreen();
455                         memset(hs_active_onscreen, 0,
456                                sizeof(hs_active_onscreen));
457                         return;
458                     }
459                     sprintf((char *)msg_buf, "FOCUS %s", hs_kill_appid);
460                     uifw_trace("send '%s' to command", msg_buf);
461                     send = hs_lib_alloc_msg(msg_buf, strlen(msg_buf));
462                     if (!send) {
463                         uifw_warn(
464                                   "hs_lib_handle_onscreen: ERROR(allocate send msg)");
465                         return;
466                     }
467                     send->type = ICO_HS_PROTOCOL_TYPE_CM;
468                     ret = hs_lib_put_sendmsg(send);
469                     if (ret < 0) {
470                         hs_hide_onscreen();
471                         hs_tile_kill_app(hs_kill_appid);
472                         hs_tile_show_screen();
473                     }
474                     else {
475                         hs_hide_onscreen();
476                     }
477                 }
478                 else if (strncmp(ptr, "cancel_bt", 8) == 0) {
479                     uifw_trace("%s: cancel_bt", ICO_HS_ONS_APPLI_KILL_NAME);
480                     hs_hide_onscreen();
481                     hs_tile_show_screen();
482                 }
483                 else {
484                     uifw_trace("%s: else %s", ICO_HS_ONS_APPLI_KILL_NAME, ptr);
485                     hs_hide_onscreen();
486                 }
487                 memset(hs_active_onscreen, 0, sizeof(hs_active_onscreen));
488                 memset(hs_kill_appid, 0, sizeof(hs_kill_appid));
489             }
490         }
491         else {
492             uifw_trace("send %s to app", data);
493             send = hs_lib_alloc_msg(data, msg->len);
494             if (!send) {
495                 uifw_warn("hs_lib_handle_onscreen: ERROR(allocate send msg)");
496                 return;
497             }
498             send->type = ICO_HS_PROTOCOL_TYPE_APP;
499             hs_lib_put_sendmsg(send);
500         }
501     }
502
503     uifw_trace("hs_lib_handle_onscreen: Leave");
504 }
505 /*--------------------------------------------------------------------------*/
506 /**
507  * @brief   hs_lib_handle_statusbar
508  *          callback at received message from statusbar, and handle the
509  *          message.
510  *
511  * @param[in]   msg                 received message
512  * @return      none
513  */
514 /*--------------------------------------------------------------------------*/
515 static void
516 hs_lib_handle_statusbar(hs_lib_msg_t *msg)
517 {
518     hs_lib_msg_t *send;
519     char tmp_buf[ICO_HS_MSG_SIZE];
520     char *cmd;
521     Ico_Uxf_ProcessWin wins[1];
522     Ico_Uxf_ProcessAttr attr;
523     int ret;
524     int idx;
525     int cnt = 0;
526
527     uifw_trace("hs_lib_handle_statusbar: Enter(%s)", msg->data);
528
529     if (strncmp("CLICK ESCUTCHEON", msg->data, 16) == 0) {
530         /* clicked escutcheon button and send a command to outer commander */
531         hs_click_escutcheon();
532         /* send "Receive OK" message to statusbar */
533         send = hs_lib_alloc_msg("RECEIVE OK", strlen("RECEIVE OK"));
534         if (send) {
535             send->type = ICO_HS_PROTOCOL_TYPE_SB;
536             hs_lib_put_sendmsg(send);
537         }
538     }
539     else if (strncmp("OPEN", msg->data, 4) == 0) {
540         /* forward the message to onscreen */
541         if (hs_click_applist()) {
542             send = hs_lib_alloc_msg(msg->data, msg->len);
543             if (send) {
544                 strncpy(hs_active_onscreen, ICO_UXF_PROC_DEFAULT_HOMESCREEN,
545                         sizeof(hs_active_onscreen));
546                 send->type = ICO_HS_PROTOCOL_TYPE_OS;
547                 hs_lib_put_sendmsg(send);
548             }
549         }
550         /* send "Receive OK" message to statusbar */
551         send = hs_lib_alloc_msg("RECEIVE OK", strlen("RECEIVE OK"));
552         if (send) {
553             send->type = ICO_HS_PROTOCOL_TYPE_SB;
554             hs_lib_put_sendmsg(send);
555         }
556     }
557     else if (strncmp("SHOW", msg->data, 4) == 0) {
558         /* show the application on the application screen */
559         cmd = get_parsed_str(msg->data, tmp_buf, sizeof(tmp_buf), 1);
560         if (cmd) {
561             /* wait for creating the application's window */
562             memset(wins, 0, sizeof(wins));
563             while (wins[0].window <= 0) {
564                 ret = ico_uxf_process_window_get(cmd, wins, 1);
565                 if (ret > 0) {
566                     ret = ico_uxf_process_attribute_get(cmd, &attr);
567                     if (wins[0].window > 0) {
568                         break;
569                     }
570                     else if ((ret >= 0) && (attr.status != ICO_UXF_PROCSTATUS_RUN)) {
571                         /* launch the application */
572                         ret = ico_uxf_process_execute(cmd);
573                         if ((ret == ICO_UXF_EOK) || (ret == ICO_UXF_EBUSY)) {
574                             idx = hs_tile_get_index_app(cmd);
575                             if (idx < 0) {
576                                 idx = hs_tile_get_minchange();
577                             }
578                             hs_tile_set_app(idx, cmd);
579                         }
580                     }
581                 }
582                 else {
583                     /* unknown application */
584                     break;
585                 }
586                 usleep(10000);
587                 ecore_main_loop_iterate();
588
589                 if (cnt > 100) {
590                     break;
591                 }
592                 else {
593                     cnt++;
594                 }
595             }
596
597             /* show the application screen*/
598             hs_show_appscreen(cmd);
599         }
600         /* send "Receive OK" message to statusbar */
601         send = hs_lib_alloc_msg("RECEIVE OK", strlen("RECEIVE OK"));
602         if (send) {
603             send->type = ICO_HS_PROTOCOL_TYPE_SB;
604             hs_lib_put_sendmsg(send);
605         }
606     }
607     uifw_trace("hs_lib_handle_statusbar: Leave");
608 }
609
610 /*--------------------------------------------------------------------------*/
611 /**
612  * @brief   hs_lib_alloc_msg
613  *          Allocate a msg structure
614  *
615  * @param[in]   data                data
616  * @param[in]   len                 data length
617  * @return      address
618  * @retval      > 0                 success
619  * @retval      NULL                error
620  */
621 /*--------------------------------------------------------------------------*/
622 static hs_lib_msg_t *
623 hs_lib_alloc_msg(char *data, int len)
624 {
625     hs_lib_msg_t *msg;
626
627     if (!hs_free_msg) {
628         msg = malloc(sizeof(hs_lib_msg_t));
629         if (!msg) {
630             return NULL;
631         }
632     }
633     else {
634         msg = hs_free_msg;
635         hs_free_msg = hs_free_msg->next;
636     }
637     memset(msg, 0, sizeof(hs_lib_msg_t));
638
639     msg->len = len;
640     msg->data = strdup(data);
641     if (!msg->data) {
642         free(msg);
643         return NULL;
644     }
645
646     return msg;
647 }
648
649 /*--------------------------------------------------------------------------*/
650 /**
651  * @brief   hs_lib_free_msg
652  *          free the msg
653  *
654  * @param[in]   data                data
655  * @param[in]   free                data lenght
656  * @return      none
657  */
658 /*--------------------------------------------------------------------------*/
659 static void
660 hs_lib_free_msg(hs_lib_msg_t *msg)
661 {
662     if (!msg) {
663         return;
664     }
665
666     if (msg->data) {
667         free(msg->data);
668     }
669
670     memset(msg, 0, sizeof(hs_lib_msg_t));
671
672     msg->next = hs_free_msg;
673     hs_free_msg = msg;
674
675     return;
676 }
677
678 /*--------------------------------------------------------------------------*/
679 /**
680  * @brief   hs_lib_free_handle
681  *          free the indecated handle.
682  *
683  * @param       handle              handle to free
684  * @return      none
685  */
686 /*--------------------------------------------------------------------------*/
687 static void
688 hs_lib_free_handle(hs_lib_handle_t *handle)
689 {
690     hs_lib_handle_t *free;
691     hs_lib_handle_t *bfree;
692
693     free = hs_handles;
694     bfree = NULL;
695     while (free) {
696         if (free == handle)
697             break;
698         bfree = free;
699         free = free->next;
700     }
701     if (free) {
702         if (bfree) {
703             bfree->next = free->next;
704         }
705         else {
706             hs_handles = free->next;
707         }
708         free->next = hs_handles_free;
709         hs_handles_free = free;
710     }
711 }
712
713 /*--------------------------------------------------------------------------*/
714 /**
715  * @brief   hs_lib_alloc_handle
716  *          Allocate handle.
717  *
718  * @param       none
719  * @return      address
720  * @retval      > 0                 success
721  * @retval      NULL                error
722  */
723 /*--------------------------------------------------------------------------*/
724 static hs_lib_handle_t *
725 hs_lib_alloc_handle(void)
726 {
727     hs_lib_handle_t *handle;
728
729     if (!hs_handles_free) {
730         handle = malloc(sizeof(hs_lib_handle_t));
731         if (!handle) {
732             return NULL;
733         }
734     }
735     else {
736         handle = hs_handles_free;
737         hs_handles_free = hs_handles_free->next;
738     }
739     memset(handle, 0, sizeof(hs_lib_handle_t));
740
741     if (hs_handles) {
742         handle->next = hs_handles;
743     }
744     hs_handles = handle;
745
746     return handle;
747 }
748
749 /*--------------------------------------------------------------------------*/
750 /**
751  * @brief   hs_lib_realsend
752  *          write send message to websocket actually.
753  *
754  * @param[in]   msg                 write message
755  * @return      none
756  */
757 /*--------------------------------------------------------------------------*/
758 static void
759 hs_lib_realsend(hs_lib_msg_t *msg)
760 {
761     unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 512
762             + LWS_SEND_BUFFER_POST_PADDING];
763     unsigned char *pt = &buf[LWS_SEND_BUFFER_PRE_PADDING];
764     int n;
765
766     strcpy((char*)pt, msg->data);
767
768     uifw_trace("hs_lib_realsend: send(wsi=%x, type=h:%d(m:%d), len=%d, msg=%s)",
769                msg->handle->wsi, msg->handle->type, msg->type, msg->len, msg->data);
770     n = libwebsocket_write(msg->handle->wsi, pt, strlen((char *)pt),
771                            LWS_WRITE_TEXT);
772
773     if (n < 0) {
774         uifw_warn("hs_lib_realsend: ERROR(fail to write ws)");
775     }
776
777     hs_lib_free_msg(msg);
778
779     uifw_warn("hs_lib_realsend: Leave(send len = %d)", n);
780
781     usleep(200);
782 }
783
784 /*--------------------------------------------------------------------------*/
785 /**
786  * @brief   hs_lib_get_sendmsg
787  *          get the send message from the send queue.
788  *
789  * @param[in]   type                receiver
790  * @return      send message address
791  * @retval      > 0                 success
792  * @retval      NULL                error
793  */
794 /*--------------------------------------------------------------------------*/
795 static hs_lib_msg_t *
796 hs_lib_get_sendmsg(int type)
797 {
798     hs_lib_msg_t *msg;
799     hs_lib_msg_t *bmsg;
800
801     msg = hs_send_msg;
802     bmsg = NULL;
803     while (msg) {
804         if (msg->type == type) {
805             break;
806         }
807         bmsg = msg;
808         msg = msg->next;
809     }
810     if (msg) {
811         if (!bmsg) {
812             /* top */
813             hs_send_msg = msg->next;
814             msg->next = NULL;
815         }
816         else {
817             bmsg->next = msg->next;
818             msg->next = NULL;
819         }
820     }
821
822     return msg;
823 }
824
825 /*--------------------------------------------------------------------------*/
826 /**
827  * @brief   hs_lib_put_sendmsg
828  *          put the send message to the send queue end.
829  *
830  * @param[in]   data                send message
831  * @return      result
832  * @retval      ICO_HS_OK           success
833  * @retval      ICO_HS_ERR          error
834  */
835 /*--------------------------------------------------------------------------*/
836 static int
837 hs_lib_put_sendmsg(hs_lib_msg_t *send)
838 {
839     hs_lib_msg_t *msg;
840     hs_lib_handle_t *handle;
841
842     uifw_trace("hs_lib_put_sendmsg: Enter");
843
844     handle = hs_handles;
845     while (handle) {
846         if (handle->type == send->type) {
847             break;
848         }
849         handle = handle->next;
850     }
851     if (!handle) {
852         uifw_trace("hs_lib_put_sendmsg: Leave(target(type:%d) does not exist", send->type);
853         hs_lib_free_msg(send);
854         return ICO_HS_ERR;
855     }
856
857     msg = hs_send_msg;
858     while (msg) {
859         if (!msg->next) {
860             break;
861         }
862         msg = msg->next;
863     }
864     if (!msg) {
865         hs_send_msg = send;
866     }
867     else {
868         msg->next = send;
869     }
870
871     if (handle) {
872         send->handle = handle;
873         uifw_trace("hs_lib_put_sendmsg: libwebsocket_callback_on_writable"
874             "(wsi_ctx=%x, wsi=%x", handle->wsi_context, handle->wsi);
875         libwebsocket_callback_on_writable(handle->wsi_context, handle->wsi);
876
877         hs_lib_com_dispatch(handle, 0);
878     }
879
880     uifw_trace("hs_lib_put_sendmsg: Leave");
881
882     return ICO_HS_OK;
883 }
884
885 /*--------------------------------------------------------------------------*/
886 /**
887  * @brief   hs_lib_get_recvmsg
888  *          get the receive message from the receive queue end.
889  *
890  * @param       none
891  * @return      recv message address
892  * @retval      > 0                 success
893  * @retval      NULL                error
894  */
895 /*--------------------------------------------------------------------------*/
896 static hs_lib_msg_t *
897 hs_lib_get_recvmsg(void)
898 {
899     hs_lib_msg_t *msg;
900
901     msg = hs_recv_msg;
902     if (msg) {
903         hs_recv_msg = msg->next;
904         msg->next = NULL;
905     }
906
907     return msg;
908 }
909
910 /*--------------------------------------------------------------------------*/
911 /**
912  * @brief   hs_lib_put_recvmsg
913  *          put the receive message to the receive queue end.
914  *
915  * @param[in]   data                receive message
916  * @return      none
917  */
918 /*--------------------------------------------------------------------------*/
919 static void
920 hs_lib_put_recvmsg(hs_lib_msg_t *recv)
921 {
922     hs_lib_msg_t *msg;
923
924     msg = hs_recv_msg;
925     while (msg) {
926         if (!msg->next) {
927             break;
928         }
929         msg = msg->next;
930     }
931     if (!msg) {
932         hs_recv_msg = recv;
933     }
934     else {
935         msg->next = recv;
936     }
937 }
938
939 /*--------------------------------------------------------------------------*/
940 /**
941  * @brief   hs_lib_com_dispatch
942  *          The accumulated data that transmitted or received is procecssed
943  *
944  * @param[in]   _handle             connect handle,
945  *                                  if NULL target is all connection
946  * @param[in]   timeoutms           maximum wait time on miri-sec.
947  *                                  0 is no wait, -1 is wait forever.
948  * @return      none
949  */
950 /*--------------------------------------------------------------------------*/
951 static void
952 hs_lib_com_dispatch(hs_lib_handle_t *_handle, int timeoutms)
953 {
954     hs_lib_handle_t *handle;
955     hs_lib_msg_t *msg;
956
957     if (_handle) {
958         handle = _handle;
959     }
960     else {
961         handle = hs_handles;
962     }
963
964     while (handle) {
965         uifw_warn("hs_lib_com_dispatch: wsi=%x", handle->wsi_context);
966         if (libwebsocket_service(handle->wsi_context, timeoutms) < 0) {
967             uifw_warn("hs_lib_com_dispatch: fd=%d is done", handle->fd);
968         }
969
970         /* treate received buffer */
971         msg = hs_lib_get_recvmsg();
972         while (msg) {
973             switch (msg->type) {
974             case ICO_HS_PROTOCOL_TYPE_CM:
975                 hs_lib_handle_command(msg);
976                 break;
977
978             case ICO_HS_PROTOCOL_TYPE_SB:
979                 hs_lib_handle_statusbar(msg);
980                 break;
981
982             case ICO_HS_PROTOCOL_TYPE_OS:
983                 hs_lib_handle_onscreen(msg);
984                 break;
985
986             case ICO_HS_PROTOCOL_TYPE_APP:
987                 hs_lib_handle_application(msg);
988                 break;
989
990             default:
991                 break;
992             }
993             hs_lib_free_msg(msg);
994             msg = hs_lib_get_recvmsg();
995         }
996
997         if (_handle)
998             break;
999         handle = handle->next;
1000     }
1001 }
1002
1003 /*--------------------------------------------------------------------------*/
1004 /**
1005  * @brief   hs_lib_poll_fd_event
1006  *          Notify the changes of file descriptor's state
1007  *
1008  * @param[in]   fd_ctl              The structure of file descriptor's controller
1009  * @param[in]   flags               Flags
1010  * @return      none
1011  */
1012 /*--------------------------------------------------------------------------*/
1013 static void
1014 hs_lib_poll_fd_event(hs_lib_poll_t *poll, int flags)
1015 {
1016     hs_lib_handle_t *handle = poll->handle;
1017
1018     uifw_trace("hs_lib_ecore_fdevent: Enter(flags=%08x)", flags);
1019
1020     /* try to ws service */
1021     hs_lib_com_dispatch(handle, 0);
1022
1023     /* control polling fd's event? */
1024
1025     return;
1026 }
1027
1028 /*--------------------------------------------------------------------------*/
1029 /**
1030  * @brief   hs_lib_ecore_fdevent
1031  *          callback function called by Ecore when the websocket's file
1032  *          descriptor had change
1033  *
1034  * @param[in]   data                user data(ico_apf_com_poll_t)
1035  * @param[in]   handler             Ecore file descriptor handler
1036  * @return      call back setting
1037  * @retval      ECORE_CALLBACK_RENEW    set callback
1038  */
1039 /*--------------------------------------------------------------------------*/
1040 static Eina_Bool
1041 hs_lib_ecore_fdevent(void *data, Ecore_Fd_Handler *handler)
1042 {
1043     int flags;
1044
1045     uifw_trace("hs_lib_ecore_fdevent: Enter");
1046
1047     flags
1048             = (ecore_main_fd_handler_active_get(handler, ECORE_FD_READ))
1049                                                                          ? EPOLLIN
1050                                                                          : 0;
1051     if (ecore_main_fd_handler_active_get(handler, ECORE_FD_WRITE)) {
1052         flags |= ECORE_FD_WRITE;
1053     }
1054     if (ecore_main_fd_handler_active_get(handler, ECORE_FD_ERROR)) {
1055         flags |= EPOLLERR;
1056     }
1057
1058     hs_lib_poll_fd_event((hs_lib_poll_t *)data, flags);
1059
1060     return ECORE_CALLBACK_RENEW;
1061 }
1062
1063 /*--------------------------------------------------------------------------*/
1064 /**
1065  * @brief   hs_lib_control_fd
1066  *          control file descriptors to add or delete ecore event handler
1067  *
1068  * @param[in]   fd_ctl              file descriptors
1069  * @param[in]   num_fds             number of file descriptors
1070  * @return      none
1071  */
1072 /*--------------------------------------------------------------------------*/
1073 static void
1074 hs_lib_control_fd(hs_lib_poll_t *fd_ctl[], const int num_fds)
1075 {
1076     int ii;
1077     Ecore_Fd_Handler_Flags flags;
1078
1079     for (ii = 0; ii < num_fds; ii++) {
1080         if (fd_ctl[ii]->flags) {
1081             flags = (fd_ctl[ii]->flags & EPOLLIN) ? ECORE_FD_READ : 0;
1082             if (fd_ctl[ii]->flags & EPOLLOUT) {
1083                 flags |= ECORE_FD_WRITE;
1084             }
1085             if (fd_ctl[ii]->flags & (EPOLLERR | EPOLLPRI)) {
1086                 flags |= ECORE_FD_ERROR;
1087             }
1088             if (!fd_ctl[ii]->user_data) {
1089                 uifw_trace(
1090                            "hs_lib_control_fd: ADD(fd=%d, flg=%08x, eflg=%08x)",
1091                            fd_ctl[ii]->fd, fd_ctl[ii]->flags, flags);
1092                 fd_ctl[ii]->user_data
1093                         = (void *)ecore_main_fd_handler_add(
1094                                                             fd_ctl[ii]->fd,
1095                                                             flags,
1096                                                             hs_lib_ecore_fdevent,
1097                                                             (void *)fd_ctl[ii],
1098                                                             NULL, NULL);
1099             }
1100             else {
1101                 uifw_trace(
1102                            "hs_lib_control_fd: CHANGE(fd=%d, flg=%08x, eflg=%08x)",
1103                            fd_ctl[ii]->fd, fd_ctl[ii]->flags, flags);
1104                 ecore_main_fd_handler_active_set(
1105                                                  (Ecore_Fd_Handler *)fd_ctl[ii]->user_data,
1106                                                  flags);
1107             }
1108         }
1109         else {
1110             /* remove file descriptor */
1111             uifw_trace("hs_lib_control_fd: DELL(fd=%d)", fd_ctl[ii]->fd);
1112             ecore_main_fd_handler_del((Ecore_Fd_Handler *)fd_ctl[ii]->user_data);
1113         }
1114     }
1115 }
1116
1117 /*--------------------------------------------------------------------------*/
1118 /**
1119  * @brief   hs_lib_add_poll_fd
1120  *          add file descriptor of websocket for poll
1121  *
1122  * @param[in]   fd                  file descriptor
1123  * @param[in]   flags               event flag
1124  * @return      result
1125  * @retval      ICO_HS_OK           success
1126  * @retval      ICO_HS_ERR          error
1127  */
1128 /*--------------------------------------------------------------------------*/
1129 static int
1130 hs_lib_add_poll_fd(int fd, int flags)
1131 {
1132     hs_lib_poll_t *poll;
1133     hs_lib_poll_t *fds[0];
1134     hs_lib_handle_t *handle;
1135
1136     /* get management table */
1137     poll = hs_polls;
1138     while (poll) {
1139         if (poll->fd == fd) {
1140             break;
1141         }
1142         poll = poll->next;
1143     }
1144     if (!poll) {
1145         if (hs_polls_free) {
1146             poll = hs_polls_free;
1147             hs_polls_free = poll->next;
1148             poll->user_data = NULL;
1149         }
1150         else {
1151             poll = calloc(sizeof(hs_lib_poll_t), 1);
1152             if (!poll) {
1153                 uifw_warn("hs_lib_add_poll_fd: ERR(allocate poll table failed)");
1154                 return ICO_HS_ERR;
1155             }
1156         }
1157         poll->fd = fd;
1158         poll->next = hs_polls;
1159         hs_polls = poll;
1160     }
1161     poll->flags = flags;
1162
1163     /* if the fd is same as wsi_context, set the handle */
1164     handle = hs_handles;
1165     while (handle) {
1166         if (handle->fd == fd)
1167             break;
1168         handle = handle->next;
1169     }
1170     if (handle) {
1171         poll->handle = handle;
1172         handle->poll = poll;
1173     }
1174     else {
1175         poll->handle = NULL;
1176     }
1177
1178     /* control fds */
1179     fds[0] = poll;
1180     hs_lib_control_fd(fds, 1);
1181
1182     return ICO_HS_OK;
1183 }
1184
1185 /*--------------------------------------------------------------------------*/
1186 /**
1187  * @brief   hs_lib_del_poll_fd
1188  *          delete file descriptor of websocket for poll
1189  *
1190  * @param[in]   fd                  file descriptor
1191  * @return      none
1192  */
1193 /*--------------------------------------------------------------------------*/
1194 static void
1195 hs_lib_del_poll_fd(int fd)
1196 {
1197     hs_lib_poll_t *poll;
1198     hs_lib_poll_t *fds[0];
1199
1200     /* get management table */
1201     poll = hs_polls;
1202     while (poll) {
1203         if (poll->fd == fd) {
1204             hs_polls = poll->next;
1205
1206             /* control fds */
1207             poll->flags = 0;
1208             fds[0] = poll;
1209             hs_lib_control_fd(fds, 1);
1210
1211             /* add free polls */
1212             poll->next = hs_polls_free;
1213             hs_polls_free = poll;
1214             break;
1215         }
1216         poll = poll->next;
1217     }
1218
1219     return;
1220 }
1221
1222 /*--------------------------------------------------------------------------*/
1223 /**
1224  * @brief   hs_lib_set_mode_poll_fd
1225  *          set event to file descriptor of websocket for poll
1226  *
1227  * @param[in]   fd                  file descriptor
1228  * @param[in]   flags               event flag
1229  * @return      none
1230  */
1231 /*--------------------------------------------------------------------------*/
1232 static void
1233 hs_lib_set_mode_poll_fd(int fd, int flags)
1234 {
1235     hs_lib_poll_t *poll;
1236     hs_lib_poll_t *fds[0];
1237
1238     /* get management table */
1239     poll = hs_polls;
1240     while (poll) {
1241         if (poll->fd == fd) {
1242             /* control fds */
1243             poll->flags |= flags;
1244             fds[0] = poll;
1245             hs_lib_control_fd(fds, 1);
1246         }
1247         poll = poll->next;
1248     }
1249
1250     return;
1251 }
1252
1253 /*--------------------------------------------------------------------------*/
1254 /**
1255  * @brief   hs_lib_clear_mode_poll_fd
1256  *          clear event to file descriptor of websocket for poll
1257  *
1258  * @param[in]   fd                  file descriptor
1259  * @param[in]   flags               event flag
1260  * @return      none
1261  */
1262 /*--------------------------------------------------------------------------*/
1263 static void
1264 hs_lib_clear_mode_poll_fd(int fd, int flags)
1265 {
1266     hs_lib_poll_t *poll;
1267     hs_lib_poll_t *fds[0];
1268
1269     /* get management table */
1270     poll = hs_polls;
1271     while (poll) {
1272         if (poll->fd == fd) {
1273             /* control fds */
1274             poll->flags &= ~flags;
1275             fds[0] = poll;
1276             hs_lib_control_fd(fds, 1);
1277         }
1278         poll = poll->next;
1279     }
1280
1281     return;
1282 }
1283
1284 /*--------------------------------------------------------------------------*/
1285 /**
1286  * @brief   get_parsed_str
1287  *          extract word by the given arg_idx.
1288  *
1289  * @param[in]   in                  source char array
1290  * @param[in]   out                 char array store word
1291  * @param[in]   len                 char array length
1292  * @param[in]   arg_idx             index
1293  * @return      none
1294  * @retval      >=0                 pointer to extract word
1295  */
1296 /*--------------------------------------------------------------------------*/
1297 static char *
1298 get_parsed_str(char *in, char *out, int len, int arg_idx)
1299 {
1300     int ii;
1301     char *data;
1302
1303     uifw_trace("get_parsed_str: %s arg = %d", in, arg_idx);
1304
1305     memset(out, 0, len);
1306     strncpy(out, in, len);
1307     data = strtok(out, " ");
1308     for (ii = 0; ii < arg_idx; ii++) {
1309         data = strtok(NULL, " ");
1310     }
1311
1312     uifw_trace("get_parsed_str data: %s", data);
1313
1314     return data;
1315 }
1316
1317 /* get filename from the full path */
1318 static char *
1319 getFileName(char *filepath, int len)
1320 {
1321     int ii;
1322     char *name = filepath;
1323
1324     for (ii = 0; ii < len - 1; ii++) {
1325         if (filepath[ii] == 0)
1326             break;
1327         if (filepath[ii] == '/')
1328             name = &filepath[ii + 1];
1329     }
1330
1331     uifw_trace("getFileName name: %s", name);
1332
1333     return name;
1334 }
1335
1336 /*--------------------------------------------------------------------------*/
1337 /**
1338  * @brief   hs_lib_event_message
1339  *          send message
1340  *
1341  * @param[in]   type                receiver
1342  * @param[in]   fromat              message to send
1343  * @return      result
1344  * @retval      ICO_HS_OK           success
1345  * @retval      ICO_HS_ERR          error
1346  */
1347 /*--------------------------------------------------------------------------*/
1348 int
1349 hs_lib_event_message(int type, char *format, ...)
1350 {
1351     va_list list;
1352     char message[ICO_HS_MSG_SIZE];
1353     hs_lib_msg_t *send;
1354
1355     memset(message, 0, sizeof(message));
1356
1357     va_start(list, format);
1358     vsnprintf(message, sizeof(message), format, list);
1359     va_end(list);
1360
1361     uifw_trace("hs_lib_event_message: message to %d, %s", type, message);
1362     send = hs_lib_alloc_msg(message, strlen(message));
1363     if (!send) {
1364         uifw_warn("hs_lib_event_message: ERROR(allocate send msg)");
1365         return ICO_HS_ERR;
1366     }
1367     send->type = type;
1368
1369     return hs_lib_put_sendmsg(send);
1370 }
1371
1372 /*--------------------------------------------------------------------------*/
1373 /*
1374  * @brief   hs_lib_callback_http
1375  *          Connection status is notified from libwebsockets.
1376  *
1377  * @param[in]   context             libwebsockets context
1378  * @param[in]   wsi                 libwebsockets management table
1379  * @param[in]   reason              event type
1380  * @param[in]   user                intact
1381  * @param[in]   in                  receive message
1382  * @param[in]   len                 message size[BYTE]
1383  * @return      result
1384  * @retval      =0                  success
1385  * @retval      =1                  error
1386  */
1387 /*--------------------------------------------------------------------------*/
1388 static int
1389 hs_lib_callback_http(struct libwebsocket_context *context,
1390                      struct libwebsocket *wsi,
1391                      enum libwebsocket_callback_reasons reason, void *user,
1392                      void *in, size_t len)
1393 {
1394     int fd;
1395
1396     uifw_trace("hs_lib_callback_http: context=%p", context);
1397     uifw_trace("HS-REASON %d", reason);
1398
1399     fd = libwebsocket_get_socket_fd(wsi);
1400     switch (reason) {
1401     case LWS_CALLBACK_ADD_POLL_FD:
1402         uifw_trace("LWS_CALLBACK_ADD_POLL_FD: wsi_fd=%d fd=%d flg=%08x", fd,
1403                    (int)(long)user, (int)len);
1404         (void)hs_lib_add_poll_fd(fd, (int)len);
1405         break;
1406
1407     case LWS_CALLBACK_DEL_POLL_FD:
1408         uifw_trace("LWS_CALLBACK_DEL_POLL_FD: wsi_fd=%d fd=%d flg=%08x", fd,
1409                    (int)(long)user, (int)len);
1410         hs_lib_del_poll_fd(fd);
1411         break;
1412
1413     case LWS_CALLBACK_SET_MODE_POLL_FD:
1414         uifw_trace("LWS_CALLBACK_SET_MODE_POLL_FD: wsi_fd=%d fd=%d flg=%08x",
1415                    fd, (int)(long)user, (int)len);
1416         hs_lib_set_mode_poll_fd(fd, (int)len);
1417         break;
1418
1419     case LWS_CALLBACK_CLEAR_MODE_POLL_FD:
1420         uifw_trace("LWS_CALLBACK_CLEAR_MODE_POLL_FD: wsi_fd=%d fd=%d flg=%08x",
1421                    fd, (int)(long)user, (int)len);
1422         hs_lib_clear_mode_poll_fd(fd, (int)len);
1423         break;
1424
1425     default:
1426         break;
1427     }
1428
1429     return 0;
1430 }
1431
1432 /*--------------------------------------------------------------------------*/
1433 /*
1434  * @brief   hs_lib_callback_command
1435  *          this callback function is notified from libwebsockets
1436  *          command protocol
1437  *
1438  * @param[in]   context             libwebsockets context
1439  * @param[in]   wsi                 libwebsockets management table
1440  * @param[in]   reason              event type
1441  * @param[in]   user                intact
1442  * @param[in]   in                  receive message
1443  * @param[in]   len                 message size[BYTE]
1444  * @return      result
1445  * @retval      =0                  success
1446  * @retval      =1                  error
1447  */
1448 /*--------------------------------------------------------------------------*/
1449 static int
1450 hs_lib_callback_command(struct libwebsocket_context *context,
1451                         struct libwebsocket *wsi,
1452                         enum libwebsocket_callback_reasons reason, void *user,
1453                         void *in, size_t len)
1454 {
1455     int fd;
1456     hs_lib_handle_t *handle;
1457     hs_lib_poll_t *poll;
1458     hs_lib_msg_t *msg;
1459
1460     uifw_trace("hs_lib_callback_command: Enter(ctx=%p, wsi_fd=%d, reason=%d",
1461                context, libwebsocket_get_socket_fd(wsi), reason);
1462
1463     fd = libwebsocket_get_socket_fd(wsi);
1464     if (reason == LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION) {
1465         /* connect from client. the client must exist only one */
1466         uifw_trace("hs_lib_callback_command: "
1467             "LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION(fd=%d)", fd);
1468         handle = hs_handles;
1469         while (handle) {
1470             if (handle->fd == fd)
1471                 break;
1472             handle = handle->next;
1473         }
1474         if (!handle) {
1475             handle = hs_lib_alloc_handle();
1476             if (!handle) {
1477                 uifw_warn("hs_lib_callback_command: ERROR(allocate handle)");
1478             }
1479         }
1480         handle->wsi_context = hs_wsicontext;
1481         handle->wsi = wsi;
1482         handle->fd = fd;
1483         handle->type = ICO_HS_PROTOCOL_TYPE_CM;
1484
1485         poll = hs_polls;
1486         while (poll) {
1487             if (poll->fd == handle->fd) {
1488                 poll->handle = handle;
1489                 handle->poll = poll;
1490             }
1491             poll = poll->next;
1492         }
1493         return 0;
1494     }
1495
1496     handle = hs_handles;
1497     while (handle) {
1498         if (handle->wsi == wsi)
1499             break;
1500         handle = handle->next;
1501     }
1502
1503     switch (reason) {
1504     case LWS_CALLBACK_ESTABLISHED:
1505         uifw_trace("hs_lib_callback_command: "
1506             "LWS_CALLBACK_ESTABLISHED(wsi=%x)", wsi);
1507         handle->service_on = 1;
1508
1509         msg = hs_lib_alloc_msg(HS_REQ_ANS_HELLO, strlen(HS_REQ_ANS_HELLO));
1510         if (!msg) {
1511             uifw_warn("hs_lib_callback_command: ERROR(allocate recv msg)");
1512             break;
1513         }
1514         msg->type = ICO_HS_PROTOCOL_TYPE_CM;
1515         msg->handle = handle;
1516
1517         hs_lib_put_recvmsg(msg);
1518         uifw_trace("hs_lib_callback_command: "
1519             "LWS_CALLBACK_ESTABLISHED: Leave");
1520         break;
1521
1522     case LWS_CALLBACK_RECEIVE:
1523         uifw_trace("hs_lib_callback_command: "
1524             "LWS_CALLBACK_RECEIVE:(len=%d \"%s\")", len, in);
1525         if (strlen(in) == 0)
1526             break;
1527
1528         msg = hs_lib_alloc_msg((char *)in, len);
1529         if (!msg) {
1530             uifw_warn("hs_lib_callback_command: ERROR(allocate recv msg)");
1531             break;
1532         }
1533         msg->type = ICO_HS_PROTOCOL_TYPE_CM;
1534         msg->handle = handle;
1535
1536         hs_lib_put_recvmsg(msg);
1537         uifw_trace("hs_lib_callback_command: "
1538             "LWS_CALLBACK_RECEIVE: Leave");
1539         break;
1540
1541     case LWS_CALLBACK_CLOSED:
1542         uifw_trace("hs_lib_callback_command: "
1543             "LWS_CALLBACK_CLOSED:(wsi=%x)", wsi);
1544         hs_lib_free_handle(handle);
1545         break;
1546
1547     case LWS_CALLBACK_SERVER_WRITEABLE:
1548         uifw_trace("hs_lib_callback_command: "
1549             "LWS_CALLBACK_SERVER_WRITEABLE:(wsi=%x)", wsi);
1550         hs_lib_realsend(hs_lib_get_sendmsg(ICO_HS_PROTOCOL_TYPE_CM));
1551
1552     default:
1553         uifw_trace("HS-REASON %d", reason);
1554         break;
1555     }
1556
1557     return 0;
1558 }
1559
1560 /*--------------------------------------------------------------------------*/
1561 /*
1562  * @brief   hs_lib_callback_statusbar
1563  *          this callback function is notified from libwebsockets
1564  *          statusbar protocol
1565  *
1566  * @param[in]   context             libwebsockets context
1567  * @param[in]   wsi                 libwebsockets management table
1568  * @param[in]   reason              event type
1569  * @param[in]   user                intact
1570  * @param[in]   in                  receive message
1571  * @param[in]   len                 message size[BYTE]
1572  * @return      result
1573  * @retval      =0                  success
1574  * @retval      =1                  error
1575  */
1576 /*--------------------------------------------------------------------------*/
1577 static int
1578 hs_lib_callback_statusbar(struct libwebsocket_context *context,
1579                           struct libwebsocket *wsi,
1580                           enum libwebsocket_callback_reasons reason,
1581                           void *user, void *in, size_t len)
1582 {
1583     int fd;
1584     hs_lib_handle_t *handle;
1585     hs_lib_poll_t *poll;
1586     hs_lib_msg_t *msg;
1587
1588     uifw_trace("hs_lib_callback_statusbar: Enter(ctx=%p, wsi_fd=%d, reason=%d",
1589                context, libwebsocket_get_socket_fd(wsi), reason);
1590
1591     fd = libwebsocket_get_socket_fd(wsi);
1592     if (reason == LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION) {
1593         /* connect from client. the client must exist only one */
1594         uifw_trace("hs_lib_callback_statusbar: "
1595             "LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION(fd=%d)", fd);
1596         handle = hs_handles;
1597         while (handle) {
1598             if (handle->fd == fd)
1599                 break;
1600             handle = handle->next;
1601         }
1602         if (!handle) {
1603             handle = hs_lib_alloc_handle();
1604             if (!handle) {
1605                 uifw_warn("hs_lib_callback_statusbar: ERROR(allocate handle)");
1606             }
1607         }
1608         handle->wsi_context = hs_wsicontext;
1609         handle->wsi = wsi;
1610         handle->fd = fd;
1611         handle->type = ICO_HS_PROTOCOL_TYPE_SB;
1612
1613         poll = hs_polls;
1614         while (poll) {
1615             if (poll->fd == handle->fd) {
1616                 poll->handle = handle;
1617                 handle->poll = poll;
1618             }
1619             poll = poll->next;
1620         }
1621         return 0;
1622     }
1623
1624     handle = hs_handles;
1625     while (handle) {
1626         if (handle->wsi == wsi)
1627             break;
1628         handle = handle->next;
1629     }
1630
1631     switch (reason) {
1632     case LWS_CALLBACK_ESTABLISHED:
1633         uifw_trace("hs_lib_callback_statusbar: "
1634             "LWS_CALLBACK_ESTABLISHED(wsi=%x)", wsi);
1635         handle->service_on = 1;
1636         break;
1637
1638     case LWS_CALLBACK_RECEIVE:
1639         uifw_trace("hs_lib_callback_statusbar: "
1640             "LWS_CALLBACK_RECEIVE:(len=%d \"%s\")", len, in);
1641
1642         if (strlen(in) == 0)
1643             break;
1644
1645         msg = hs_lib_alloc_msg((char *)in, len);
1646         if (!msg) {
1647             uifw_warn("hs_lib_callback_statusbar: ERROR(allocate recv msg)");
1648             break;
1649         }
1650         msg->type = ICO_HS_PROTOCOL_TYPE_SB;
1651         msg->handle = handle;
1652
1653         hs_lib_put_recvmsg(msg);
1654         uifw_trace("hs_lib_callback_statusbar: "
1655             "LWS_CALLBACK_RECEIVE: Leave");
1656         break;
1657
1658     case LWS_CALLBACK_CLOSED:
1659         uifw_trace("hs_lib_callback_statusbar: "
1660             "LWS_CALLBACK_CLOSED:(wsi=%x)", wsi);
1661         hs_lib_free_handle(handle);
1662         break;
1663
1664     case LWS_CALLBACK_SERVER_WRITEABLE:
1665         uifw_trace("hs_lib_callback_statusbar: "
1666             "LWS_CALLBACK_SERVER_WRITEABLE:(wsi=%x)", wsi);
1667         hs_lib_realsend(hs_lib_get_sendmsg(ICO_HS_PROTOCOL_TYPE_SB));
1668
1669     default:
1670         uifw_trace("HS-REASON %d", reason);
1671         break;
1672     }
1673
1674     return 0;
1675 }
1676
1677 /*--------------------------------------------------------------------------*/
1678 /*
1679  * @brief   hs_lib_callback_onscreen
1680  *          this callback function is notified from libwebsockets
1681  *          statusbar protocol
1682  *
1683  * @param[in]   context             libwebsockets context
1684  * @param[in]   wsi                 libwebsockets management table
1685  * @param[in]   reason              event type
1686  * @param[in]   user                intact
1687  * @param[in]   in                  receive message
1688  * @param[in]   len                 message size[BYTE]
1689  * @return      result
1690  * @retval      =0                  success
1691  * @retval      =1                  error
1692  */
1693 /*--------------------------------------------------------------------------*/
1694 static int
1695 hs_lib_callback_onscreen(struct libwebsocket_context *context,
1696                          struct libwebsocket *wsi,
1697                          enum libwebsocket_callback_reasons reason, void *user,
1698                          void *in, size_t len)
1699 {
1700     int fd;
1701     hs_lib_handle_t *handle;
1702     hs_lib_poll_t *poll;
1703     hs_lib_msg_t *msg;
1704
1705     uifw_trace("hs_lib_callback_onscreen: Enter(ctx=%p, wsi_fd=%d, reason=%d",
1706                context, libwebsocket_get_socket_fd(wsi), reason);
1707
1708     fd = libwebsocket_get_socket_fd(wsi);
1709     if (reason == LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION) {
1710         /* connect from client. the client must exist only one */
1711         uifw_trace("hs_lib_callback_onscreen: "
1712             "LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION(fd=%d)", fd);
1713         handle = hs_handles;
1714         while (handle) {
1715             if (handle->fd == fd)
1716                 break;
1717             handle = handle->next;
1718         }
1719         if (!handle) {
1720             handle = hs_lib_alloc_handle();
1721             if (!handle) {
1722                 uifw_warn("hs_lib_callback_onscreen: ERROR(allocate handle)");
1723             }
1724         }
1725         handle->wsi_context = hs_wsicontext;
1726         handle->wsi = wsi;
1727         handle->fd = fd;
1728         handle->type = ICO_HS_PROTOCOL_TYPE_OS;
1729
1730         poll = hs_polls;
1731         while (poll) {
1732             if (poll->fd == handle->fd) {
1733                 poll->handle = handle;
1734                 handle->poll = poll;
1735             }
1736             poll = poll->next;
1737         }
1738         return 0;
1739     }
1740
1741     handle = hs_handles;
1742     while (handle) {
1743         if (handle->wsi == wsi)
1744             break;
1745         handle = handle->next;
1746     }
1747
1748     switch (reason) {
1749     case LWS_CALLBACK_ESTABLISHED:
1750         uifw_trace("hs_lib_callback_onscreen: "
1751             "LWS_CALLBACK_ESTABLISHED(wsi=%x)", wsi);
1752         handle->service_on = 1;
1753         break;
1754
1755     case LWS_CALLBACK_RECEIVE:
1756         uifw_trace("hs_lib_callback_onscreen: "
1757             "LWS_CALLBACK_RECEIVE:(len=%d \"%s\")", len, in);
1758
1759         if (strlen(in) == 0)
1760             break;
1761
1762         msg = hs_lib_alloc_msg((char *)in, len);
1763         if (!msg) {
1764             uifw_warn("hs_lib_callback_onscreen: ERROR(allocate recv msg)");
1765             break;
1766         }
1767         msg->type = ICO_HS_PROTOCOL_TYPE_OS;
1768         msg->handle = handle;
1769
1770         hs_lib_put_recvmsg(msg);
1771         uifw_trace("hs_lib_callback_onscreen: "
1772             "LWS_CALLBACK_RECEIVE: Leave");
1773         break;
1774
1775     case LWS_CALLBACK_CLOSED:
1776         uifw_trace("hs_lib_callback_onscreen: "
1777             "LWS_CALLBACK_CLOSED:(wsi=%x)", wsi);
1778         hs_lib_free_handle(handle);
1779         break;
1780
1781     case LWS_CALLBACK_SERVER_WRITEABLE:
1782         uifw_trace("hs_lib_callback_onscreen: "
1783             "LWS_CALLBACK_SERVER_WRITEABLE:(wsi=%x)", wsi);
1784         hs_lib_realsend(hs_lib_get_sendmsg(ICO_HS_PROTOCOL_TYPE_OS));
1785
1786         break;
1787
1788     default:
1789         uifw_trace("hs_lib_callback_onscreen: HS-REASON %d", reason);
1790         break;
1791     }
1792
1793     return 0;
1794 }
1795
1796 /*--------------------------------------------------------------------------*/
1797 /*
1798  * @brief   hs_lib_callback_app
1799  *          this callback function is notified from libwebsockets
1800  *          application protocol
1801  *
1802  * @param[in]   context             libwebsockets context
1803  * @param[in]   wsi                 libwebsockets management table
1804  * @param[in]   reason              event type
1805  * @param[in]   user                intact
1806  * @param[in]   in                  receive message
1807  * @param[in]   len                 message size[BYTE]
1808  * @return      result
1809  * @retval      =0                  success
1810  * @retval      =1                  error
1811  */
1812 /*--------------------------------------------------------------------------*/
1813 static int
1814 hs_lib_callback_app(struct libwebsocket_context *context,
1815                     struct libwebsocket *wsi,
1816                     enum libwebsocket_callback_reasons reason, void *user,
1817                     void *in, size_t len)
1818 {
1819     int fd;
1820     hs_lib_handle_t *handle;
1821     hs_lib_poll_t *poll;
1822     hs_lib_msg_t *msg;
1823
1824     uifw_trace("hs_lib_callback_app: Enter(ctx=%p, wsi_fd=%d, reason=%d",
1825                context, libwebsocket_get_socket_fd(wsi), reason);
1826
1827     fd = libwebsocket_get_socket_fd(wsi);
1828     if (reason == LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION) {
1829         /* connect from client.*/
1830         uifw_trace("hs_lib_callback_app: "
1831             "LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION(fd=%d)", fd);
1832         handle = hs_handles;
1833         while (handle) {
1834             if (handle->fd == fd)
1835                 break;
1836             handle = handle->next;
1837         }
1838         if (!handle) {
1839             handle = hs_lib_alloc_handle();
1840             if (!handle) {
1841                 uifw_warn("hs_lib_callback_app: ERROR(allocate handle)");
1842             }
1843         }
1844         handle->wsi_context = hs_wsicontext;
1845         handle->wsi = wsi;
1846         handle->fd = fd;
1847         handle->type = ICO_HS_PROTOCOL_TYPE_APP;
1848
1849         poll = hs_polls;
1850         while (poll) {
1851             if (poll->fd == handle->fd) {
1852                 poll->handle = handle;
1853                 handle->poll = poll;
1854             }
1855             poll = poll->next;
1856         }
1857         return 0;
1858     }
1859
1860     handle = hs_handles;
1861     while (handle) {
1862         if (handle->wsi == wsi)
1863             break;
1864         handle = handle->next;
1865     }
1866
1867     switch (reason) {
1868     case LWS_CALLBACK_ESTABLISHED:
1869         uifw_trace("hs_lib_callback_app: "
1870             "LWS_CALLBACK_ESTABLISHED(wsi=%x)", wsi);
1871         handle->service_on = 1;
1872         break;
1873
1874     case LWS_CALLBACK_RECEIVE:
1875         uifw_trace("hs_lib_callback_app: "
1876             "LWS_CALLBACK_RECEIVE:(len=%d \"%s\")", len, in);
1877
1878         if (strlen(in) == 0)
1879             break;
1880
1881         msg = hs_lib_alloc_msg((char *)in, len);
1882         if (!msg) {
1883             uifw_warn("hs_lib_callback_app: ERROR(allocate recv msg)");
1884             break;
1885         }
1886         msg->type = ICO_HS_PROTOCOL_TYPE_APP;
1887         msg->handle = handle;
1888
1889         hs_lib_put_recvmsg(msg);
1890         uifw_trace("hs_lib_callback_app: "
1891             "LWS_CALLBACK_RECEIVE: Leave");
1892         break;
1893
1894     case LWS_CALLBACK_CLOSED:
1895         uifw_trace("hs_lib_callback_app: "
1896             "LWS_CALLBACK_CLOSED:(wsi=%x)", wsi);
1897         hs_lib_free_handle(handle);
1898         break;
1899
1900     case LWS_CALLBACK_SERVER_WRITEABLE:
1901         uifw_trace("hs_lib_callback_app: "
1902             "LWS_CALLBACK_SERVER_WRITEABLE:(wsi=%x)", wsi);
1903         hs_lib_realsend(hs_lib_get_sendmsg(ICO_HS_PROTOCOL_TYPE_APP));
1904
1905     default:
1906         uifw_trace("hs_lib_callback_app: HS-REASON %d", reason);
1907         break;
1908     }
1909
1910     return 0;
1911 }
1912
1913 /*--------------------------------------------------------------------------*/
1914 /**
1915  * @brief   hs_lib_main
1916  *          initialize homescreen lib to connect statusbar and onscreen,
1917  *          external command tools.
1918  *
1919  * @param[in]   port                websocket port
1920  * @return      result
1921  * @retval      ICO_HS_OK           success
1922  * @retval      ICO_HS_ERR          error
1923  */
1924 /*--------------------------------------------------------------------------*/
1925 int
1926 hs_lib_main(int port)
1927 {
1928     int opts = 0;
1929     hs_lib_handle_t *handle;
1930
1931     handle = hs_lib_alloc_handle();
1932     handle->wsi_context
1933             = libwebsocket_create_context(ICO_HS_WS_PORT, NULL, protocols,
1934                                           libwebsocket_internal_extensions,
1935                                           NULL, NULL, -1, -1, opts);
1936     if (handle->wsi_context == NULL) {
1937         uifw_warn(
1938                   "home_screen_lib_main: ERROR(libwebsocket_create_context failed.)");
1939         return ICO_HS_ERR;
1940     }
1941     hs_wsicontext = handle->wsi_context;
1942
1943     return ICO_HS_OK;
1944 }