1774275e485af1fdaa62fecedd43a6ab9427a27a
[profile/ivi/ico-uxf-homescreen.git] / lib / system-controller / CicoSCWayland.cpp
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 //==========================================================================    
11 /**
12  *  @file   CicoSCWayland.cpp
13  *
14  *  @brief  This file implementation of CicoSCWayland class
15  */
16 //==========================================================================    
17
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <unistd.h>
21 #include <string.h>
22 #include <signal.h>
23 #include <errno.h>
24 #include <sys/ioctl.h>
25 #include <Ecore.h>
26
27 #include <map>
28 using namespace std;
29
30 #include <wayland-client.h>
31 #include <ilm/ilm_control.h>
32
33 #include "CicoSCWayland.h"
34 #include "CicoSCWlWinMgrIF.h"
35 #include "CicoSCWindowController.h"
36 #include "CicoLog.h"
37 #include "ico_syc_error.h"
38
39 //==========================================================================    
40 //  private static variable
41 //==========================================================================    
42 CicoSCWayland* CicoSCWayland::ms_myInstance = NULL;
43
44 //--------------------------------------------------------------------------
45 /**
46  *  @brief  default constructor
47  */
48 //--------------------------------------------------------------------------
49 CicoSCWayland::CicoSCWayland()
50     : m_wlDisplay(NULL),
51       m_wlRegistry(NULL),
52       m_wlFd(-1),
53       m_ecoreFdHandler(NULL)
54 {
55     // wayland callbacks
56     m_wlListener.global        = wlGlobalCB;
57     m_wlListener.global_remove = NULL;
58
59     CicoSCWayland::ms_myInstance = this;
60 }
61
62 //--------------------------------------------------------------------------
63 /**
64  *  @brief  destructor
65  */
66 //--------------------------------------------------------------------------
67 CicoSCWayland::~CicoSCWayland()
68 {
69     CicoSCWayland::ms_myInstance = NULL;
70 }
71
72 //--------------------------------------------------------------------------
73 /**
74  *  @brief  get instance of CicoSCWayland
75  *
76  *  @return instance of CicoSCWayland
77  */
78 //--------------------------------------------------------------------------
79 CicoSCWayland*
80 CicoSCWayland::getInstance(void)
81 {
82     if (NULL == ms_myInstance) {
83         ms_myInstance = new CicoSCWayland();
84     }
85
86     return ms_myInstance;
87 }
88
89 //--------------------------------------------------------------------------
90 /**
91  *  @brief  initialize wayland connection
92  *
93  *  @return ICO_SYC_EOK on success, other on error
94  */
95 //--------------------------------------------------------------------------
96 int
97 CicoSCWayland::initialize(void)
98 {
99     ICO_TRA("CicoSCWayland::initialize Enter");
100
101     // initialize genivi ivi-shell
102     if (ilm_init() != ILM_SUCCESS)  {
103         ICO_ERR("ilm_init failed.");
104         ICO_TRA("CicoSCWayland::initialize Leave(EIO)");
105         return ICO_SYC_EIO;
106     }
107
108     for (int i = 0; i < (5000/50); ++i)  {
109         m_wlDisplay = wl_display_connect(NULL);
110         if (NULL != m_wlDisplay) {
111             break;
112         }
113         usleep(50*1000);
114     }
115
116     if (NULL == m_wlDisplay) {
117         ICO_ERR("wl_display_connect failed.");
118         ICO_TRA("CicoSCWayland::initialize Leave(EIO)");
119         return ICO_SYC_EIO;
120     }
121
122     ICO_DBG("called: wl_display_get_registry(wlDisplay=0x%08x)", m_wlDisplay);
123     m_wlRegistry = wl_display_get_registry(m_wlDisplay);
124     if (NULL == m_wlRegistry) {
125         ICO_ERR("wl_display_get_registry failed.");
126         ICO_TRA("CicoSCWayland::initialize Leave(EIO)");
127         return ICO_SYC_EIO;
128     }
129
130     // add wayland global callbacks
131     ICO_DBG("called: wl_registry_add_listener");
132     wl_registry_add_listener(m_wlRegistry, &m_wlListener, this);
133
134     int initCount = 0;
135     int ifcount = m_wlInterfaceList.size();
136     for (int i = 0; i < (500/20); ++i) {
137         initCount = 0;
138         map<string, CicoSCWaylandIF*>::iterator itr;
139         itr = m_wlInterfaceList.begin();
140         for (; itr != m_wlInterfaceList.end(); ++itr) {
141             if(true == itr->second->isInitialized()) {
142                 initCount++;
143             }
144         }
145         if (ifcount == initCount) {
146             break;
147         }
148         ICO_DBG("called: wl_display_dispatch"
149                 "(wlDisplay=0x%08x)", (int)m_wlDisplay);
150         wl_display_dispatch(m_wlDisplay);
151         usleep(20*1000);
152     }
153
154     if (ifcount != initCount) {
155         ICO_ERR("initialize interface time up NG");
156         ICO_TRA("CicoSCWayland::initialize Leave(EIO)");
157         return ICO_SYC_EIO;
158     }
159     else {
160         ICO_DBG("initialize interface all OK");
161     }
162
163     // flush display 
164     ICO_DBG("called: wl_display_flush(wlDisplay=0x%08x)", (int)m_wlDisplay);
165     wl_display_flush(m_wlDisplay);
166
167     ICO_DBG("called: wl_display_get_fd(wlDisplay=0x%08x)", (int)m_wlDisplay);
168     m_wlFd = wl_display_get_fd(m_wlDisplay);
169     ICO_DBG("CicoSCWayland::initialize: Wayland/Weston fd=%d", m_wlFd);
170
171     ICO_DBG("CicoSCWayland::initialize: Wayland/Weston connect OK");
172
173     // initialize genivi callbacks
174     CicoSCWindowController::getInstance()->initializeGeniviLMS();
175
176     ICO_TRA("CicoSCWayland::initialize: Leave(EOK)");
177     return ICO_SYC_EOK;
178 }
179
180 //--------------------------------------------------------------------------
181 /**
182  *  @brief  flush display
183  */
184 //--------------------------------------------------------------------------
185 void
186 CicoSCWayland::flushDisplay(void)
187 {
188     if (NULL == m_wlDisplay) {
189         ICO_ERR("wlDisplay == NULL");
190         return;
191     }
192 //    ICO_DBG("called: wl_display_flush(0x%08x)", (int)m_wlDisplay);
193     int wlret = wl_display_flush(m_wlDisplay);
194     if (-1 == wlret) {
195         int error = wl_display_get_error(m_wlDisplay);
196         ICO_ERR("wayland error(%d)", error);
197     }
198 }
199
200 //--------------------------------------------------------------------------
201 /**
202  *  @brief  dispatch display
203  */
204 //--------------------------------------------------------------------------
205 void
206 CicoSCWayland::dispatchDisplay(void)
207 {
208     if (NULL == m_wlDisplay) {
209         ICO_ERR("wlDisplay == NULL");
210         return;
211     }
212 //    ICO_DBG("call wl_display_dispatch(0x%08x)", (int)m_wlDisplay);
213     int wlret = wl_display_dispatch(m_wlDisplay);
214     if (-1 == wlret) {
215         int error =  wl_display_get_error(m_wlDisplay);
216         ICO_ERR("wl_display_dispatch failed. error(%d)", error);
217
218         if (error == EINVAL)    {
219             exit(9);
220         }
221     }
222 }
223
224 //--------------------------------------------------------------------------
225 /**
226  *  @brief  get wayland error
227  */
228 //--------------------------------------------------------------------------
229 int
230 CicoSCWayland::getError(void)
231 {
232     if (NULL == m_wlDisplay) {
233         ICO_ERR("wlDisplay == NULL");
234         return -1;
235     }
236
237     ICO_DBG("fd=%d", wl_display_get_fd(m_wlDisplay));
238     return wl_display_get_error(m_wlDisplay);
239 }
240
241 //--------------------------------------------------------------------------
242 /**
243  *  @brief  get wayland file destructor
244  *
245  *  @return wayland file destructor
246  */
247 //--------------------------------------------------------------------------
248 int CicoSCWayland::getWlFd(void)
249 {
250     return m_wlFd;
251 }
252
253 //--------------------------------------------------------------------------
254 /**
255  *  @brief  add wayland file destructor handler to ecore main 
256  *
257  *  @return ICO_SYC_EOK on success, other on error
258  *  @retval ICO_SYC_EIO ecore_main_fd_handler_add failed
259  */
260 //--------------------------------------------------------------------------
261 int
262 CicoSCWayland::addEcoreMainWlFdHandler(void)
263 {
264     ICO_TRA("CicoSCWayland::addEcoreMainWlFdHandler Enter");
265     ICO_DBG("called: ecore_main_fd_handler_add(fd=%d)", m_wlFd);
266     m_ecoreFdHandler = ecore_main_fd_handler_add(m_wlFd, 
267                                                  ECORE_FD_READ,
268                                                  &waylandFdHandler,
269                                                  NULL,
270                                                  NULL,
271                                                  NULL);
272     if (NULL == m_ecoreFdHandler) {
273         ICO_ERR("ecore_main_fd_handler_add failed.");
274         ICO_TRA("CicoSCWayland::addEcoreMainWlFdHandler Leave(EIO)");
275         return ICO_SYC_EIO;
276     }
277     ecore_main_loop_iterate();
278
279     int arg = 0;
280     if (ioctl(m_wlFd, FIONREAD, &arg) < 0) {
281         ICO_WRN("ioclt(FIONREAD) failed. errno=%d:%s", errno, strerror(errno));
282         arg = 0;
283     }
284     if (arg > 0)   {
285         CicoSCWayland::getInstance()->dispatchDisplay();
286     }
287
288     ICO_TRA("CicoSCWayland::addEcoreMainWlFdHandler Leave");
289     return ICO_SYC_EOK;
290 }
291
292 //--------------------------------------------------------------------------
293 /**
294  *  @brief   add wayland interface
295  *
296  *  @param [in] name        interface name
297  *  @param [in] interface   interface instance
298  */
299 //--------------------------------------------------------------------------
300 void
301 CicoSCWayland::addWaylandIF(const char *name, CicoSCWaylandIF* interface)
302 {
303     m_wlInterfaceList[name] = interface;
304 }
305
306 //--------------------------------------------------------------------------
307 /**
308  *  @brief   wayland global callback
309  *
310  *  @param [in] data        user data(unused)
311  *  @param [in] registry    wayland registry
312  *  @param [in] name        wayland display Id(unused)
313  *  @param [in] interface   wayland interface name
314  *  @param [in] version     wayland interface version number(unused)
315  */
316 //--------------------------------------------------------------------------
317 void
318 CicoSCWayland::globalCB(void               *data,
319                         struct wl_registry *registry,
320                         uint32_t           name,
321                         const char         *interface,
322                         uint32_t           version)
323 {
324     map<string, CicoSCWaylandIF*>::iterator itr;
325     itr = m_wlInterfaceList.find(interface);
326
327     if (m_wlInterfaceList.end() == itr) {
328         ICO_DBG("skip interface=%s", interface);
329         return;
330     }
331
332     CicoSCWaylandIF *wlIF = itr->second;
333     wlIF->initInterface(data, registry, name, interface, version);
334
335     // flush display 
336     wl_display_flush(m_wlDisplay);
337 }
338
339 //--------------------------------------------------------------------------
340 /**
341  *  @brief   wayland global callback
342  *
343  *  @param [in] data        user data
344  *  @param [in] registry    wayland registry
345  *  @param [in] name        wayland display Id(unused)
346  *  @param [in] interface   wayland interface name
347  *  @param [in] version     wayland interface version number(unused)
348  */
349 //--------------------------------------------------------------------------
350 void
351 CicoSCWayland::wlGlobalCB(void               *data,
352                           struct wl_registry *registry,
353                           uint32_t           name,
354                           const char         *interface,
355                           uint32_t           version)
356 {
357     if (NULL == data) {
358         ICO_ERR("data == NULL");
359         return;
360     }
361
362     static_cast<CicoSCWayland*>(data)->globalCB(data, registry, name,
363                                                 interface, version);
364 }
365
366 //--------------------------------------------------------------------------
367 /**
368  *  @brief  wayland global callback
369  *
370  *  @param [in] data        user data
371  *  @param [in] handler     ecore file destructor handler
372  *
373  *  @return ECORE_CALLBACK_RENEW on retry , ECORE_CALLBACK_CANCEL on cancel
374  */
375 //--------------------------------------------------------------------------
376 Eina_Bool
377 CicoSCWayland::waylandFdHandler(void *data, Ecore_Fd_Handler *handler)
378 {
379 //    ICO_TRA("waylandFdHandler: Enter");
380
381     CicoSCWayland::getInstance()->flushDisplay();
382
383     int arg = 0;
384     if (ioctl(CicoSCWayland::getInstance()->getWlFd(), FIONREAD, &arg) < 0) {
385         ICO_WRN("ioclt(FIONREAD) failed. errno=%d:%s", errno, strerror(errno));
386         arg = 0;
387     }
388
389 //    ICO_DBG("waylandFdHandler: arg(%d))", arg);
390     if (arg > 0) {
391         CicoSCWayland::getInstance()->dispatchDisplay();
392     }
393
394     if (0 == arg) {
395         ICO_ERR("wayland fd read error.");
396         ICO_DBG("called: ecore_main_loop_quit()");
397         ecore_main_loop_quit();
398         return ECORE_CALLBACK_CANCEL;
399     }
400
401     CicoSCWayland::getInstance()->flushDisplay();
402 //    ICO_TRA("waylandFdHandler: Leave");
403     return ECORE_CALLBACK_RENEW ;
404 }
405 // vim:set expandtab ts=4 sw=4: