• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 Advanced Driver Information Technology Joint Venture GmbH
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and
5  * its documentation for any purpose is hereby granted without fee, provided
6  * that the above copyright notice appear in all copies and that both that
7  * copyright notice and this permission notice appear in supporting
8  * documentation, and that the name of the copyright holders not be used in
9  * advertising or publicity pertaining to distribution of the software
10  * without specific, written prior permission.  The copyright holders make
11  * no representations about the suitability of this software for any
12  * purpose.  It is provided "as is" without express or implied warranty.
13  *
14  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
15  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
16  * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
17  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
18  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
19  * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21  */
22 
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
27 #include <errno.h>
28 #include <fcntl.h>
29 #include <sys/mman.h>
30 #include <assert.h>
31 #include <pthread.h>
32 #include <signal.h>
33 #include <poll.h>
34 
35 #include <wayland-cursor.h>
36 #include <ivi-application-client-protocol.h>
37 
38 #ifdef LIBWESTON_DEBUG_PROTOCOL
39 #include "dlt_common.h"
40 #include "dlt_user.h"
41 #include "weston-debug-client-protocol.h"
42 
43 #define WESTON_DLT_APP_DESC "messages from weston debug protocol"
44 #define WESTON_DLT_CONTEXT_DESC "weston debug context"
45 
46 #define WESTON_DLT_APP "WESN"
47 #define WESTON_DLT_CONTEXT "WESC"
48 
49 #define MAXSTRLEN 1024
50 #endif
51 
52 #ifndef MIN
53 #define MIN(x,y) (((x) < (y)) ? (x) : (y))
54 #endif
55 
56 static int running = 1;
57 
58 typedef struct _BkGndSettings
59 {
60     uint32_t surface_id;
61     uint32_t surface_width;
62     uint32_t surface_height;
63     uint32_t surface_stride;
64 }BkGndSettingsStruct;
65 
66 typedef struct _WaylandContext {
67     struct wl_display       *wl_display;
68     struct wl_registry      *wl_registry;
69     struct wl_compositor    *wl_compositor;
70     struct wl_shm           *wl_shm;
71     struct wl_seat          *wl_seat;
72     struct wl_pointer       *wl_pointer;
73     struct wl_surface       *wl_pointer_surface;
74     struct ivi_application  *ivi_application;
75     BkGndSettingsStruct     *bkgnd_settings;
76     struct wl_surface       *wlBkgndSurface;
77     struct ivi_surface      *ivi_surf;
78     struct wl_buffer        *wlBkgndBuffer;
79     struct wl_cursor_theme  *cursor_theme;
80     struct wl_cursor        *cursor;
81     void                    *bkgnddata;
82     uint32_t                formats;
83 #ifdef LIBWESTON_DEBUG_PROTOCOL
84     struct weston_debug_v1  *debug_iface;
85     struct wl_list          stream_list;
86     int                     debug_fd;
87     char                    thread_running;
88     pthread_t               dlt_ctx_thread;
89     int                     pipefd[2];
90 #endif
91     uint8_t                 enable_cursor;
92 }WaylandContextStruct;
93 
94 struct debug_stream {
95     struct wl_list link;
96     int should_bind;
97     char *name;
98     struct weston_debug_stream_v1 *obj;
99 };
100 
101 static const char *left_ptrs[] = {
102     "left_ptr",
103     "default",
104     "top_left_arrow",
105     "left-arrow"
106 };
107 
108 static BkGndSettingsStruct*
get_bkgnd_settings_cursor_info(WaylandContextStruct * wlcontext)109 get_bkgnd_settings_cursor_info(WaylandContextStruct* wlcontext)
110 {
111     BkGndSettingsStruct* bkgnd_settings;
112     char *option;
113     char *end;
114 
115     option = getenv("IVI_CLIENT_ENABLE_CURSOR");
116     if(option)
117         wlcontext->enable_cursor = (uint8_t)strtol(option, &end, 0);
118     else
119         wlcontext->enable_cursor = 0;
120 
121     bkgnd_settings =
122             (BkGndSettingsStruct*)calloc(1, sizeof(BkGndSettingsStruct));
123 
124     option = getenv("IVI_CLIENT_SURFACE_ID");
125     if(option)
126         bkgnd_settings->surface_id = strtol(option, &end, 0);
127     else
128         bkgnd_settings->surface_id = 10;
129 
130     bkgnd_settings->surface_width = 1;
131     bkgnd_settings->surface_height = 1;
132     bkgnd_settings->surface_stride = bkgnd_settings->surface_width * 4;
133 
134     return bkgnd_settings;
135 }
136 
137 #ifdef LIBWESTON_DEBUG_PROTOCOL
138 static struct debug_stream *
stream_alloc(WaylandContextStruct * wlcontext,const char * name)139 stream_alloc(WaylandContextStruct* wlcontext, const char *name)
140 {
141     struct debug_stream *stream;
142 
143     stream = calloc(1, (sizeof *stream));
144     if (!stream)
145         return NULL;
146 
147     stream->name = strdup(name);
148     if (!stream->name) {
149         free(stream);
150         return NULL;
151     }
152 
153     stream->should_bind = 0;
154 
155     wl_list_insert(wlcontext->stream_list.prev, &stream->link);
156 
157     return stream;
158 }
159 
160 static void
stream_destroy(struct debug_stream * stream)161 stream_destroy(struct debug_stream *stream)
162 {
163     if (stream->obj)
164         weston_debug_stream_v1_destroy(stream->obj);
165 
166     wl_list_remove(&stream->link);
167     free(stream->name);
168     free(stream);
169 }
170 
171 static void
destroy_streams(WaylandContextStruct * wlcontext)172 destroy_streams(WaylandContextStruct* wlcontext)
173 {
174     struct debug_stream *stream;
175     struct debug_stream *tmp;
176 
177     wl_list_for_each_safe(stream, tmp, &wlcontext->stream_list, link) {
178         stream_destroy(stream);
179     }
180 }
181 
182 static void
handle_stream_complete(void * data,struct weston_debug_stream_v1 * obj)183 handle_stream_complete(void *data, struct weston_debug_stream_v1 *obj)
184 {
185     struct debug_stream *stream = data;
186 
187     assert(stream->obj == obj);
188 
189     stream_destroy(stream);
190 }
191 
192 static void
handle_stream_failure(void * data,struct weston_debug_stream_v1 * obj,const char * msg)193 handle_stream_failure(void *data, struct weston_debug_stream_v1 *obj,
194 		      const char *msg)
195 {
196     struct debug_stream *stream = data;
197 
198     assert(stream->obj == obj);
199 
200     fprintf(stderr, "Debug stream '%s' aborted: %s\n", stream->name, msg);
201 
202     stream_destroy(stream);
203 }
204 
205 static const struct weston_debug_stream_v1_listener stream_listener = {
206     handle_stream_complete,
207     handle_stream_failure
208 };
209 
210 static void
start_streams(WaylandContextStruct * wlcontext)211 start_streams(WaylandContextStruct* wlcontext)
212 {
213     struct debug_stream *stream;
214 
215     wl_list_for_each(stream, &wlcontext->stream_list, link) {
216         if (stream->should_bind) {
217         stream->obj = weston_debug_v1_subscribe(wlcontext->debug_iface,
218                             stream->name,
219                             wlcontext->debug_fd);
220         weston_debug_stream_v1_add_listener(stream->obj,
221                             &stream_listener, stream);
222         }
223     }
224 }
225 
226 static void
get_debug_streams(WaylandContextStruct * wlcontext)227 get_debug_streams(WaylandContextStruct* wlcontext)
228 {
229     char *stream_names;
230     char *stream;
231     const char separator[2] = " ";
232 
233     stream_names = getenv("IVI_CLIENT_DEBUG_STREAM_NAMES");
234 
235     if(NULL == stream_names)
236         return;
237 
238     /* get the first stream */
239     stream = strtok(stream_names, separator);
240 
241     /* walk through other streams */
242     while( stream != NULL ) {
243         stream_alloc(wlcontext, stream);
244         stream = strtok(NULL, separator);
245     }
246 }
247 #endif
248 
249 static void
shm_format(void * data,struct wl_shm * wl_shm,uint32_t format)250 shm_format(void *data, struct wl_shm *wl_shm, uint32_t format)
251 {
252     WaylandContextStruct* wlcontext = data;
253 
254     wlcontext->formats |= (1 << format);
255 }
256 
257 static struct wl_shm_listener shm_listenter = {
258     shm_format
259 };
260 
create_cursors(WaylandContextStruct * wlcontext)261 static int create_cursors(WaylandContextStruct* wlcontext) {
262     int size = 32;
263     unsigned int j;
264 
265     wlcontext->cursor_theme = wl_cursor_theme_load(NULL, size, wlcontext->wl_shm);
266     if (!wlcontext->cursor_theme) {
267         fprintf(stderr, "could not load default theme\n");
268         return -1;
269     }
270 
271     wlcontext->cursor = NULL;
272 
273     for (j = 0; !wlcontext->cursor && j < 4; ++j)
274         wlcontext->cursor = wl_cursor_theme_get_cursor(wlcontext->cursor_theme, left_ptrs[j]);
275 
276     if (!wlcontext->cursor)
277     {
278         fprintf(stderr, "could not load cursor '%s'\n", left_ptrs[j]);
279         return -1;
280     }
281 
282     return 0;
283 }
284 
set_pointer_image(WaylandContextStruct * wlcontext)285 static int set_pointer_image(WaylandContextStruct* wlcontext)
286 {
287     struct wl_cursor *cursor = NULL;
288     struct wl_cursor_image *image = NULL;
289     struct wl_buffer *buffer = NULL;
290 
291     if (!wlcontext->wl_pointer || !wlcontext->cursor) {
292         fprintf(stderr, "no wl_pointer or no wl_cursor\n");
293         return -1;
294     }
295 
296     cursor = wlcontext->cursor;
297     image = cursor->images[0];
298     buffer = wl_cursor_image_get_buffer(image);
299     if (!buffer) {
300         fprintf(stderr, "buffer for cursor not available\n");
301         return -1;
302     }
303 
304     wl_pointer_set_cursor(wlcontext->wl_pointer, 0,
305                           wlcontext->wl_pointer_surface,
306                           image->hotspot_x, image->hotspot_y);
307     wl_surface_attach(wlcontext->wl_pointer_surface, buffer, 0, 0);
308     wl_surface_damage(wlcontext->wl_pointer_surface, 0, 0,
309                       image->width, image->height);
310     wl_surface_commit(wlcontext->wl_pointer_surface);
311 
312     return 0;
313 }
314 
315 static void
PointerHandleEnter(void * data,struct wl_pointer * wlPointer,uint32_t serial,struct wl_surface * wlSurface,wl_fixed_t sx,wl_fixed_t sy)316 PointerHandleEnter(void *data, struct wl_pointer *wlPointer, uint32_t serial,
317                    struct wl_surface *wlSurface, wl_fixed_t sx, wl_fixed_t sy)
318 {
319     WaylandContextStruct *wlcontext = (WaylandContextStruct*)data;
320 
321     set_pointer_image(wlcontext);
322 
323     printf("ENTER EGLWLINPUT PointerHandleEnter: x(%d), y(%d)\n",
324            wl_fixed_to_int(sx), wl_fixed_to_int(sy));
325 }
326 
327 static void
PointerHandleLeave(void * data,struct wl_pointer * wlPointer,uint32_t serial,struct wl_surface * wlSurface)328 PointerHandleLeave(void *data, struct wl_pointer *wlPointer, uint32_t serial,
329                    struct wl_surface *wlSurface)
330 {
331 
332 }
333 
334 static void
PointerHandleMotion(void * data,struct wl_pointer * wlPointer,uint32_t time,wl_fixed_t sx,wl_fixed_t sy)335 PointerHandleMotion(void *data, struct wl_pointer *wlPointer, uint32_t time,
336                     wl_fixed_t sx, wl_fixed_t sy)
337 {
338 
339 }
340 
341 static void
PointerHandleAxis(void * data,struct wl_pointer * wlPointer,uint32_t time,uint32_t axis,wl_fixed_t value)342 PointerHandleAxis(void *data, struct wl_pointer *wlPointer, uint32_t time,
343                   uint32_t axis, wl_fixed_t value)
344 {
345 
346 }
347 
348 static void
PointerHandleButton(void * data,struct wl_pointer * wlPointer,uint32_t serial,uint32_t time,uint32_t button,uint32_t state)349 PointerHandleButton(void *data, struct wl_pointer *wlPointer, uint32_t serial,
350                     uint32_t time, uint32_t button, uint32_t state)
351 {
352 
353 }
354 
355 static void
PointerHandleFrame(void * data,struct wl_pointer * wl_pointer)356 PointerHandleFrame(void *data, struct wl_pointer *wl_pointer)
357 {
358 
359 }
360 
361 static void
PointerHandleAxisSource(void * data,struct wl_pointer * wl_pointer,uint32_t axis_source)362 PointerHandleAxisSource(void *data, struct wl_pointer *wl_pointer,
363                         uint32_t axis_source)
364 {
365 
366 }
367 
368 static void
PointerHandleAxisStop(void * data,struct wl_pointer * wl_pointer,uint32_t time,uint32_t axis)369 PointerHandleAxisStop(void *data, struct wl_pointer *wl_pointer,
370                       uint32_t time, uint32_t axis)
371 {
372 
373 }
374 
375 static void
PointerHandleAxisDiscrete(void * data,struct wl_pointer * wl_pointer,uint32_t axis,int32_t discrete)376 PointerHandleAxisDiscrete(void *data, struct wl_pointer *wl_pointer,
377                           uint32_t axis, int32_t discrete)
378 {
379 
380 }
381 
382 static struct wl_pointer_listener pointer_listener = {
383     PointerHandleEnter,
384     PointerHandleLeave,
385     PointerHandleMotion,
386     PointerHandleButton,
387     PointerHandleAxis,
388     PointerHandleFrame,
389     PointerHandleAxisSource,
390     PointerHandleAxisStop,
391     PointerHandleAxisDiscrete
392 };
393 
394 static void
seat_handle_capabilities(void * data,struct wl_seat * seat,uint32_t caps)395 seat_handle_capabilities(void *data, struct wl_seat *seat, uint32_t caps)
396 {
397     WaylandContextStruct *wlcontext = (WaylandContextStruct*)data;
398     struct wl_seat *wl_seat = wlcontext->wl_seat;
399 
400     if ((caps & WL_SEAT_CAPABILITY_POINTER) && !wlcontext->wl_pointer) {
401         wlcontext->wl_pointer = wl_seat_get_pointer(wl_seat);
402         wl_pointer_add_listener(wlcontext->wl_pointer,
403                                 &pointer_listener, data);
404         /*create cursors*/
405         create_cursors(wlcontext);
406         wlcontext->wl_pointer_surface =
407                 wl_compositor_create_surface(wlcontext->wl_compositor);
408     } else
409     if (!(caps & WL_SEAT_CAPABILITY_POINTER) && wlcontext->wl_pointer) {
410         wl_pointer_destroy(wlcontext->wl_pointer);
411         wlcontext->wl_pointer = NULL;
412 
413         if (wlcontext->wl_pointer_surface) {
414             wl_surface_destroy(wlcontext->wl_pointer_surface);
415             wlcontext->wl_pointer_surface = NULL;
416         }
417 
418         if (wlcontext->cursor_theme)
419             wl_cursor_theme_destroy(wlcontext->cursor_theme);
420     }
421 }
422 
423 static void
seat_name(void * data,struct wl_seat * wl_seat,const char * name)424 seat_name(void *data, struct wl_seat *wl_seat, const char *name)
425 {
426 
427 }
428 
429 static struct wl_seat_listener seat_Listener = {
430     seat_handle_capabilities,
431     seat_name
432 };
433 
434 #ifdef LIBWESTON_DEBUG_PROTOCOL
435 static void
stream_find(WaylandContextStruct * wlcontext,const char * name,const char * desc)436 stream_find(WaylandContextStruct* wlcontext, const char *name, const char *desc)
437 {
438     struct debug_stream *stream;
439     wl_list_for_each(stream, &wlcontext->stream_list, link)
440         if (strcmp(stream->name, name) == 0) {
441             stream->should_bind = 1;
442         }
443 }
444 
445 static void
debug_advertise(void * data,struct weston_debug_v1 * debug,const char * name,const char * desc)446 debug_advertise(void *data, struct weston_debug_v1 *debug, const char *name,
447                 const char *desc)
448 {
449         WaylandContextStruct* wlcontext = data;
450         stream_find(wlcontext, name, desc);
451 }
452 
453 static const struct weston_debug_v1_listener debug_listener = {
454         debug_advertise
455 };
456 #endif
457 
458 static void
registry_handle_global(void * data,struct wl_registry * registry,uint32_t name,const char * interface,uint32_t version)459 registry_handle_global(void *data, struct wl_registry *registry, uint32_t name,
460                        const char *interface, uint32_t version)
461 {
462     WaylandContextStruct* wlcontext = (WaylandContextStruct*)data;
463 
464     if (!strcmp(interface, "wl_compositor")) {
465         wlcontext->wl_compositor =
466                 wl_registry_bind(registry, name,
467                                  &wl_compositor_interface, 1);
468     }
469     else if (!strcmp(interface, "wl_shm")) {
470         wlcontext->wl_shm =
471                 wl_registry_bind(registry, name, &wl_shm_interface, 1);
472         wl_shm_add_listener(wlcontext->wl_shm, &shm_listenter, wlcontext);
473     }
474     else if (!strcmp(interface, "ivi_application")) {
475         wlcontext->ivi_application =
476                 wl_registry_bind(registry, name,
477                                  &ivi_application_interface, 1);
478     }
479     else if (!strcmp(interface, "wl_seat")) {
480         if (wlcontext->enable_cursor) {
481             wlcontext->wl_seat =
482                 wl_registry_bind(registry, name, &wl_seat_interface, 1);
483             wl_seat_add_listener(wlcontext->wl_seat, &seat_Listener, data);
484         }
485     }
486 #ifdef LIBWESTON_DEBUG_PROTOCOL
487     else if (!strcmp(interface, weston_debug_v1_interface.name)) {
488         uint32_t myver;
489 
490         if (wlcontext->debug_iface || wl_list_empty(&wlcontext->stream_list))
491             return;
492 
493         myver = MIN(1, version);
494         wlcontext->debug_iface =
495                 wl_registry_bind(registry, name,
496                     &weston_debug_v1_interface, myver);
497         weston_debug_v1_add_listener(wlcontext->debug_iface, &debug_listener,
498                                              wlcontext);
499     }
500 #endif
501 }
502 
503 static void
registry_handle_global_remove(void * data,struct wl_registry * registry,uint32_t name)504 registry_handle_global_remove(void *data, struct wl_registry *registry,
505                               uint32_t name)
506 {
507 
508 }
509 
510 static const struct wl_registry_listener registry_listener = {
511     registry_handle_global,
512     registry_handle_global_remove
513 };
514 
init_wayland_context(WaylandContextStruct * wlcontext)515 int init_wayland_context(WaylandContextStruct* wlcontext)
516 {
517     wlcontext->wl_display = wl_display_connect(NULL);
518     if (NULL == wlcontext->wl_display) {
519         printf("Error: wl_display_connect failed\n");
520         return -1;
521     }
522 
523     wlcontext->wl_registry = wl_display_get_registry(wlcontext->wl_display);
524     wl_registry_add_listener(wlcontext->wl_registry,
525                              &registry_listener, wlcontext);
526     wl_display_roundtrip(wlcontext->wl_display);
527 
528     if (wlcontext->wl_shm == NULL) {
529         fprintf(stderr, "No wl_shm global\n");
530         return -1;
531     }
532 
533     wl_display_roundtrip(wlcontext->wl_display);
534 
535     if (!(wlcontext->formats & (1 << WL_SHM_FORMAT_XRGB8888))) {
536         fprintf(stderr, "WL_SHM_FORMAT_XRGB32 not available\n");
537         return -1;
538     }
539 
540 #ifdef LIBWESTON_DEBUG_PROTOCOL
541     if (!wl_list_empty(&wlcontext->stream_list) &&
542         (wlcontext->debug_iface == NULL)) {
543         fprintf(stderr, "WARNING: weston_debug protocol is not available,"
544                 " missed enabling --debug option to weston ?\n");
545     }
546 #endif
547 
548     return 0;
549 }
550 
destroy_wayland_context(WaylandContextStruct * wlcontext)551 void destroy_wayland_context(WaylandContextStruct* wlcontext)
552 {
553     if(wlcontext->wl_compositor)
554         wl_compositor_destroy(wlcontext->wl_compositor);
555 
556     if(wlcontext->wl_display)
557         wl_display_disconnect(wlcontext->wl_display);
558 }
559 
560 int
create_file(int size)561 create_file(int size)
562 {
563     static const char template[] = "/weston-shared-XXXXXX";
564     const char *path;
565     char *name;
566     int fd;
567     int ret;
568     long flags;
569 
570     path = getenv("XDG_RUNTIME_DIR");
571     if (!path) {
572         errno = ENOENT;
573         return -1;
574     }
575 
576     name = malloc(strlen(path) + sizeof(template));
577     if (!name)
578         return -1;
579 
580     strcpy(name, path);
581     strcat(name, template);
582 
583     fd = mkstemp(name);
584     if (fd >= 0) {
585         flags = fcntl(fd, F_GETFD);
586         fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
587         unlink(name);
588     }
589 
590     free(name);
591 
592     if (fd < 0)
593         return -1;
594 
595     ret = ftruncate(fd, size);
596     if (ret < 0) {
597         close(fd);
598         return -1;
599     }
600 
601     return fd;
602 }
603 
604 static int
create_shm_buffer(WaylandContextStruct * wlcontext)605 create_shm_buffer(WaylandContextStruct* wlcontext)
606 {
607     struct wl_shm_pool *pool;
608     BkGndSettingsStruct* bkgnd_settings = wlcontext->bkgnd_settings;
609 
610     int fd = -1;
611     int size = 0;
612     int stride = 0;
613 
614     stride = bkgnd_settings->surface_stride;
615     size = stride * bkgnd_settings->surface_height;
616     fd = create_file(size);
617     if (fd < 0) {
618         fprintf(stderr, "creating a buffer file for %d B failed: %m\n",
619                 size);
620         return -1;
621     }
622 
623     wlcontext->bkgnddata =
624             mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
625 
626     if (MAP_FAILED == wlcontext->bkgnddata) {
627         fprintf(stderr, "mmap failed: %m\n");
628         close(fd);
629         return -1;
630     }
631 
632     pool = wl_shm_create_pool(wlcontext->wl_shm, fd, size);
633     wlcontext->wlBkgndBuffer = wl_shm_pool_create_buffer(pool,
634                                                          0,
635                                                          bkgnd_settings->surface_width,
636                                                          bkgnd_settings->surface_height,
637                                                          stride,
638                                                          WL_SHM_FORMAT_ARGB8888);
639     if (NULL == wlcontext->wlBkgndBuffer) {
640         fprintf(stderr, "wl_shm_create_buffer failed: %m\n");
641         close(fd);
642         return -1;
643     }
644 
645     wl_shm_pool_destroy(pool);
646     close(fd);
647 
648     return 0;
649 }
650 
draw_bkgnd_surface(WaylandContextStruct * wlcontext)651 int draw_bkgnd_surface(WaylandContextStruct* wlcontext)
652 {
653     BkGndSettingsStruct *bkgnd_settings = wlcontext->bkgnd_settings;
654     uint32_t* pixels;
655 
656     pixels = (uint32_t*)wlcontext->bkgnddata;
657     *pixels = 0x0;
658 
659     wl_surface_attach(wlcontext->wlBkgndSurface, wlcontext->wlBkgndBuffer, 0, 0);
660     wl_surface_damage(wlcontext->wlBkgndSurface, 0, 0,
661                       bkgnd_settings->surface_width, bkgnd_settings->surface_height);
662     wl_surface_commit(wlcontext->wlBkgndSurface);
663 
664     return 0;
665 }
666 
create_bkgnd_surface(WaylandContextStruct * wlcontext)667 int create_bkgnd_surface(WaylandContextStruct* wlcontext)
668 {
669     BkGndSettingsStruct *bkgnd_settings = wlcontext->bkgnd_settings;
670 
671     wlcontext->wlBkgndSurface =
672             wl_compositor_create_surface(wlcontext->wl_compositor);
673     if (NULL == wlcontext->wlBkgndSurface) {
674         printf("Error: wl_compositor_create_surface failed.\n");
675         return -1;
676     }
677 
678     if (create_shm_buffer(wlcontext)) {
679         printf("Error: shm buffer creation failed.\n");
680         return -1;
681     }
682 
683     wlcontext->ivi_surf = ivi_application_surface_create(wlcontext->ivi_application,
684                                                          bkgnd_settings->surface_id,
685                                                          wlcontext->wlBkgndSurface);
686 
687     return 0;
688 }
689 
destroy_bkgnd_surface(WaylandContextStruct * wlcontext)690 void destroy_bkgnd_surface(WaylandContextStruct* wlcontext)
691 {
692     if (wlcontext->ivi_surf)
693         ivi_surface_destroy(wlcontext->ivi_surf);
694 
695     if (wlcontext->wlBkgndSurface)
696         wl_surface_destroy(wlcontext->wlBkgndSurface);
697 }
698 
699 #ifdef LIBWESTON_DEBUG_PROTOCOL
700 static void *
weston_dlt_thread_function(void * data)701 weston_dlt_thread_function(void *data)
702 {
703     WaylandContextStruct* wlcontext;
704     char apid[DLT_ID_SIZE];
705     char ctid[DLT_ID_SIZE];
706     DLT_DECLARE_CONTEXT(weston_dlt_context)
707 
708     wlcontext = (WaylandContextStruct*)data;
709 
710     /*init dlt*/
711     dlt_set_id(apid, WESTON_DLT_APP);
712     dlt_set_id(ctid, WESTON_DLT_CONTEXT);
713 
714     DLT_REGISTER_APP(apid, WESTON_DLT_APP_DESC);
715     DLT_REGISTER_CONTEXT(weston_dlt_context, ctid, WESTON_DLT_CONTEXT_DESC);
716 
717     /*make the stdin as read end of the pipe*/
718     dup2(wlcontext->pipefd[0], STDIN_FILENO);
719 
720     while (running && wlcontext->thread_running)
721     {
722         char str[MAXSTRLEN] = {0};
723         int i = -1;
724 
725         /* read from std-in(read end of pipe) till newline char*/
726         do {
727             i++;
728             if (read(wlcontext->pipefd[0], &str[i], 1) < 0)
729                 printf("read failed : %s", strerror(errno));
730         } while (str[i] != '\n');
731 
732         if (strcmp(str,"")!=0)
733         {
734             DLT_LOG(weston_dlt_context, DLT_LOG_INFO, DLT_STRING(str));
735         }
736     }
737 
738     DLT_UNREGISTER_CONTEXT(weston_dlt_context);
739     DLT_UNREGISTER_APP();
740     pthread_exit(NULL);
741 }
742 #endif
743 
744 static void
signal_int(int signum)745 signal_int(int signum)
746 {
747     running = 0;
748 }
749 
750 static int
display_poll(struct wl_display * display,short int events)751 display_poll(struct wl_display *display, short int events)
752 {
753     int ret;
754     struct pollfd pfd[1];
755 
756     pfd[0].fd = wl_display_get_fd(display);
757     pfd[0].events = events;
758     do {
759         ret = poll(pfd, 1, -1);
760     } while (ret == -1 && errno == EINTR && running);
761 
762     if(0 == running)
763         ret = -1;
764 
765     return ret;
766 }
767 
768 /* implemented local API for dispatch the default queue
769  * to handle the Ctrl+C signal properly, with the wl_display_dispatch
770  * the poll is continuing because the generated errno is EINTR,
771  * so added running flag also to decide whether to continue polling or not */
772 static int
display_dispatch(struct wl_display * display)773 display_dispatch(struct wl_display *display)
774 {
775     int ret;
776 
777     if (wl_display_prepare_read(display) == -1)
778         return wl_display_dispatch_pending(display);
779 
780     while (1) {
781         ret = wl_display_flush(display);
782 
783         if (ret != -1 || errno != EAGAIN)
784             break;
785 
786         if (display_poll(display, POLLOUT) == -1) {
787             wl_display_cancel_read(display);
788             return -1;
789         }
790     }
791 
792     /* Don't stop if flushing hits an EPIPE; continue so we can read any
793      * protocol error that may have triggered it. */
794     if (ret < 0 && errno != EPIPE) {
795         wl_display_cancel_read(display);
796         return -1;
797     }
798 
799     if (display_poll(display, POLLIN) == -1) {
800         wl_display_cancel_read(display);
801         return -1;
802     }
803 
804     if (wl_display_read_events(display) == -1)
805         return -1;
806 
807     return wl_display_dispatch_pending(display);
808 }
809 
main(int argc,const char * argv[])810 int main (int argc, const char * argv[])
811 {
812     WaylandContextStruct* wlcontext;
813     BkGndSettingsStruct* bkgnd_settings;
814 
815     struct sigaction sigint;
816     int ret = 0;
817 
818     sigint.sa_handler = signal_int;
819     sigemptyset(&sigint.sa_mask);
820     sigaction(SIGINT, &sigint, NULL);
821     sigaction(SIGTERM, &sigint, NULL);
822     sigaction(SIGSEGV, &sigint, NULL);
823 
824     wlcontext = (WaylandContextStruct*)calloc(1, sizeof(WaylandContextStruct));
825 
826     /*get bkgnd settings and create shm-surface*/
827     bkgnd_settings = get_bkgnd_settings_cursor_info(wlcontext);
828 
829     /*init wayland context*/
830     wlcontext->bkgnd_settings = bkgnd_settings;
831 
832 #ifdef LIBWESTON_DEBUG_PROTOCOL
833     /*init debug stream list*/
834     wl_list_init(&wlcontext->stream_list);
835     get_debug_streams(wlcontext);
836     wlcontext->debug_fd = STDOUT_FILENO;
837 #else
838     fprintf(stderr, "WARNING: weston_debug protocol is not available\n");
839 #endif
840 
841     if (init_wayland_context(wlcontext)) {
842         fprintf(stderr, "init_wayland_context failed\n");
843         goto ErrorContext;
844     }
845 
846     if (create_bkgnd_surface(wlcontext)) {
847         fprintf(stderr, "create_bkgnd_surface failed\n");
848         goto Error;
849     }
850 
851     wl_display_roundtrip(wlcontext->wl_display);
852 
853 #ifdef LIBWESTON_DEBUG_PROTOCOL
854     if (!wl_list_empty(&wlcontext->stream_list) &&
855             wlcontext->debug_iface) {
856         /* create the pipe b/w stdout and stdin
857          * stdout - write end
858          * stdin - read end
859          * weston will write to stdout and the
860          * dlt_ctx_thread will read from stdin */
861         if ((pipe(wlcontext->pipefd)) < 0)
862             printf("Error in pipe() processing : %s", strerror(errno));
863 
864         dup2(wlcontext->pipefd[1], STDOUT_FILENO);
865 
866         wlcontext->thread_running = 1;
867         pthread_create(&wlcontext->dlt_ctx_thread, NULL,
868                 weston_dlt_thread_function, wlcontext);
869         start_streams(wlcontext);
870     }
871 #endif
872 
873     /*draw the bkgnd display*/
874     draw_bkgnd_surface(wlcontext);
875 
876     while (running && (ret != -1)) {
877         ret = display_dispatch(wlcontext->wl_display);
878     }
879 
880 Error:
881 #ifdef LIBWESTON_DEBUG_PROTOCOL
882     weston_debug_v1_destroy(wlcontext->debug_iface);
883 
884     while (1) {
885         struct debug_stream *stream;
886         int empty = 1;
887 
888         wl_list_for_each(stream, &wlcontext->stream_list, link)
889             if (stream->obj) {
890                 empty = 0;
891                 break;
892             }
893 
894         if (empty)
895             break;
896 
897         if (wl_display_dispatch(wlcontext->wl_display) < 0)
898             break;
899     }
900 
901     destroy_streams(wlcontext);
902     wl_display_roundtrip(wlcontext->wl_display);
903 
904     if(wlcontext->thread_running)
905     {
906         close(wlcontext->pipefd[1]);
907         close(STDOUT_FILENO);
908         wlcontext->thread_running = 0;
909         pthread_join(wlcontext->dlt_ctx_thread, NULL);
910         close(wlcontext->pipefd[0]);
911     }
912 #endif
913 
914     destroy_bkgnd_surface(wlcontext);
915 ErrorContext:
916     destroy_wayland_context(wlcontext);
917 
918     free(bkgnd_settings);
919     free(wlcontext);
920 
921     return 0;
922 }
923