From 3344b0a0696c2670ccdc7fa9fb619efdf3764fca Mon Sep 17 00:00:00 2001 From: Veeresh Kadasani Date: Fri, 31 May 2019 11:14:15 +0900 Subject: receiver: Introduce waltham-receiver NewFeature-AGL: SPEC-2445 waltham-receiver sample component is a receiver side implementation for using waltham protocol to obtain and process remote output received from waltham-transmitter Change-Id: I85983a0ac41c3a086f43fb5912e23f95609e3559 Signed-off-by: Veeresh Kadasani Signed-off-by: Naoko Tanibata --- waltham-receiver/src/wth-receiver-comm.c | 1176 ++++++++++++++++++++++++++++++ 1 file changed, 1176 insertions(+) create mode 100644 waltham-receiver/src/wth-receiver-comm.c (limited to 'waltham-receiver/src/wth-receiver-comm.c') diff --git a/waltham-receiver/src/wth-receiver-comm.c b/waltham-receiver/src/wth-receiver-comm.c new file mode 100644 index 0000000..af42f1b --- /dev/null +++ b/waltham-receiver/src/wth-receiver-comm.c @@ -0,0 +1,1176 @@ +/* + * Copyright © 2019 Advanced Driver Information Technology GmbH + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/******************************************************************************* +** ** +** TARGET : linux ** +** ** +** PROJECT : waltham-receiver ** +** ** +** PURPOSE : This file acts as interface to waltham IPC library ** +** ** +** ** +*******************************************************************************/ + +#include "wth-receiver-comm.h" + +extern int wth_receiver_weston_main(struct window *); + +extern void wth_receiver_weston_shm_attach(struct window *, uint32_t data_sz, void * data, + int32_t width, int32_t height, int32_t stride, uint32_t format); +extern void wth_receiver_weston_shm_damage(struct window *); +extern void wth_receiver_weston_shm_commit(struct window *); + +/* + * utility functions + */ +static int +watch_ctl(struct watch *w, int op, uint32_t events) +{ + wth_verbose("%s >>> \n",__func__); + struct epoll_event ee; + + ee.events = events; + ee.data.ptr = w; + wth_verbose(" <<< %s \n",__func__); + return epoll_ctl(w->receiver->epoll_fd, op, w->fd, &ee); +} + +static void +client_post_out_of_memory(struct client *c) +{ + wth_verbose("%s >>> \n",__func__); + struct wth_display *disp; + + disp = wth_connection_get_display(c->connection); + wth_object_post_error((struct wth_object *)disp, 1, + "out of memory"); + wth_verbose(" <<< %s \n",__func__); +} + +/* + * waltham surface implementation + */ +static void +surface_destroy(struct surface *surface) +{ + wth_verbose("%s >>> \n",__func__); + wth_verbose("surface %p destroy\n", surface->obj); + + wthp_surface_free(surface->obj); + wl_list_remove(&surface->link); + free(surface); + wth_verbose(" <<< %s \n",__func__); +} + +static void +surface_handle_destroy(struct wthp_surface *wthp_surface) +{ + wth_verbose("%s >>> \n",__func__); + struct surface *surface = wth_object_get_user_data((struct wth_object *)wthp_surface); + + assert(wthp_surface == surface->obj); + + surface_destroy(surface); + wth_verbose(" <<< %s \n",__func__); +} + +static void +surface_handle_attach(struct wthp_surface *wthp_surface, + struct wthp_buffer *wthp_buffer, int32_t x, int32_t y) +{ + wth_verbose("%s >>> \n",__func__); + struct surface *surf = wth_object_get_user_data((struct wth_object *)wthp_surface); + struct buffer *buf = NULL; + + buf = container_of(wthp_buffer, struct buffer, obj); + + if (surf->ivi_id != 0) { + wth_receiver_weston_shm_attach(surf->shm_window, + buf->data_sz, + buf->data, + buf->width, + buf->height, + buf->stride, + buf->format); + + wthp_buffer_send_complete(wthp_buffer, 0); + } + wth_verbose(" <<< %s \n",__func__); +} + +static void +surface_handle_damage(struct wthp_surface *wthp_surface, + int32_t x, int32_t y, int32_t width, int32_t height) +{ + wth_verbose("%s >>> \n",__func__); + + wth_verbose("surface %p damage(%d, %d, %d, %d)\n", + wthp_surface, x, y, width, height); + + struct surface *surf = wth_object_get_user_data((struct wth_object *)wthp_surface); + + if (surf->ivi_id != 0) { + wth_receiver_weston_shm_damage(surf->shm_window); + } + wth_verbose(" <<< %s \n",__func__); +} + +static void +surface_handle_frame(struct wthp_surface *wthp_surface, + struct wthp_callback *callback) +{ + wth_verbose("%s >>> \n",__func__); + struct surface *surf = wth_object_get_user_data((struct wth_object *)wthp_surface); + wth_verbose("surface %p callback(%p)\n",wthp_surface, callback); + + surf->cb = callback; + wth_verbose(" <<< %s \n",__func__); +} + +static void +surface_handle_set_opaque_region(struct wthp_surface *wthp_surface, + struct wthp_region *region) +{ + wth_verbose("surface %p set_opaque_region(%p)\n", + wthp_surface, region); +} + +static void +surface_handle_set_input_region(struct wthp_surface *wthp_surface, + struct wthp_region *region) +{ + wth_verbose("surface %p set_input_region(%p)\n", + wthp_surface, region); +} + +static void +surface_handle_commit(struct wthp_surface *wthp_surface) +{ + wth_verbose("%s >>> \n",__func__); + + struct surface *surf = wth_object_get_user_data((struct wth_object *)wthp_surface); + wth_verbose("commit %p\n",wthp_surface); + + if (surf->ivi_id != 0) { + wth_receiver_weston_shm_commit(surf->shm_window); + } + wth_verbose(" <<< %s \n",__func__); +} + +static void +surface_handle_set_buffer_transform(struct wthp_surface *wthp_surface, + int32_t transform) +{ + wth_verbose("surface %p et_buffer_transform(%d)\n", + wthp_surface, transform); +} + +static void +surface_handle_set_buffer_scale(struct wthp_surface *wthp_surface, + int32_t scale) +{ + wth_verbose("surface %p set_buffer_scale(%d)\n", + wthp_surface, scale); +} + +static void +surface_handle_damage_buffer(struct wthp_surface *wthp_surface, + int32_t x, int32_t y, int32_t width, int32_t height) +{ + wth_verbose("surface %p damage_buffer(%d, %d, %d, %d)\n", + wthp_surface, x, y, width, height); +} + +static const struct wthp_surface_interface surface_implementation = { + surface_handle_destroy, + surface_handle_attach, + surface_handle_damage, + surface_handle_frame, + surface_handle_set_opaque_region, + surface_handle_set_input_region, + surface_handle_commit, + surface_handle_set_buffer_transform, + surface_handle_set_buffer_scale, + surface_handle_damage_buffer +}; + + +/* BEGIN wthp_region implementation */ + +static void +buffer_handle_destroy(struct wthp_buffer *wthp_buffer) +{ + struct buffer *buf = wth_object_get_user_data((struct wth_object *)wthp_buffer); + + wthp_buffer_free(wthp_buffer); + wl_list_remove(&buf->link); + free(buf); +} + +static const struct wthp_buffer_interface buffer_implementation = { + buffer_handle_destroy +}; + +/* END wthp_region implementation */ + +/* BEGIN wthp_blob_factory implementation */ + +static void +blob_factory_create_buffer(struct wthp_blob_factory *blob_factory, + struct wthp_buffer *wthp_buffer, uint32_t data_sz, void *data, + int32_t width, int32_t height, int32_t stride, uint32_t format) +{ + struct blob_factory *blob = wth_object_get_user_data((struct wth_object *)blob_factory); + struct buffer *buffer; + + + wth_verbose("wthp_blob_factory %p create_buffer(%p, %d, %p, %d, %d, %d, %d)\n", + blob_factory, wthp_buffer, data_sz, data, width, height, stride, format); + + buffer = zalloc(sizeof *buffer); + if (!buffer) { + client_post_out_of_memory(blob->client); + return; + } + + wl_list_insert(&blob->client->buffer_list, &buffer->link); + + buffer->data_sz = data_sz; + buffer->data = data; + buffer->width = width; + buffer->height = height; + buffer->stride = stride; + buffer->format = format; + buffer->obj = wthp_buffer; + + wthp_buffer_set_interface(wthp_buffer, &buffer_implementation, buffer); +} + +static const struct wthp_blob_factory_interface blob_factory_implementation = { + blob_factory_create_buffer +}; + +static void +client_bind_blob_factory(struct client *c, struct wthp_blob_factory *obj) +{ + struct blob_factory *blob; + + blob = zalloc(sizeof *blob); + if (!blob) { + client_post_out_of_memory(c); + return; + } + + blob->obj = obj; + blob->client = c; + wl_list_insert(&c->compositor_list, &blob->link); + + wthp_blob_factory_set_interface(obj, &blob_factory_implementation, + blob); + fprintf(stderr, "client %p bound wthp_blob_factory\n", c); +} + +/* + * waltam ivi surface implementation + */ +static void +wthp_ivi_surface_destroy(struct wthp_ivi_surface * ivi_surface) +{ + wth_verbose("%s >>> \n",__func__); + struct ivisurface *ivisurf = wth_object_get_user_data((struct wth_object *)ivi_surface); + free(ivisurf); + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wthp_ivi_surface_interface wthp_ivi_surface_implementation = { + wthp_ivi_surface_destroy, +}; + + +/* + * waltham ivi application implementation + */ +static void +wthp_ivi_application_surface_create(struct wthp_ivi_application * ivi_application, uint32_t ivi_id, + struct wthp_surface * wthp_surface, struct wthp_ivi_surface *obj) +{ + wth_verbose("%s >>> \n",__func__); + wth_verbose("ivi_application %p surface_create(%d, %p, %p)\n", + ivi_application, ivi_id, wthp_surface, obj); + struct surface *surface = wth_object_get_user_data((struct wth_object *)wthp_surface); + wth_verbose("----------------------------------\n\n\n"); + wth_verbose("surface [%p]\n", surface); + wth_verbose("shm_window [%p]\n\n\n", surface->shm_window); + wth_verbose("----------------------------------\n"); + + surface->ivi_id = ivi_id + 100; + surface->shm_window->id_ivisurf = surface->ivi_id; + struct ivisurface *ivisurf; + + ivisurf = zalloc(sizeof *ivisurf); + if (!ivisurf) { + return; + } + + ivisurf->obj = obj; + ivisurf->surf = surface; + + wth_receiver_weston_main(surface->shm_window); + + while (!surface->shm_window->ready) + usleep(1); + + wthp_ivi_surface_set_interface(obj, &wthp_ivi_surface_implementation, + ivisurf); + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wthp_ivi_application_interface wthp_ivi_application_implementation = { + wthp_ivi_application_surface_create, +}; + +static void +client_bind_wthp_ivi_application(struct client *c, struct wthp_ivi_application *obj) +{ + wth_verbose("%s >>> \n",__func__); + + struct application *app; + + app = zalloc(sizeof *app); + if (!app) { + client_post_out_of_memory(c); + return; + } + + app->obj = obj; + app->client = c; + wl_list_insert(&c->compositor_list, &app->link); + + wthp_ivi_application_set_interface(obj, &wthp_ivi_application_implementation, + app); + wth_verbose("client %p bound wthp_ivi_application\n", c); + wth_verbose(" <<< %s \n",__func__); +} + +/* + * APIs to send pointer events to waltham client + */ + +void +waltham_pointer_enter(struct window *window, uint32_t serial, + wl_fixed_t sx, wl_fixed_t sy) +{ + wth_verbose("%s >>> \n",__func__); + + struct surface *surface = window->receiver_surf; + struct seat *seat = window->receiver_seat; + struct pointer *pointer = seat->pointer; + + wth_verbose("waltham_pointer_enter [%d]\n", window->receiver_surf->ivi_id); + + wthp_pointer_send_enter (pointer->obj, serial, surface->obj, sx, sy); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +void +waltham_pointer_leave(struct window *window, uint32_t serial) +{ + wth_verbose("%s >>> \n",__func__); + struct surface *surface = window->receiver_surf; + struct seat *seat = window->receiver_seat; + struct pointer *pointer = seat->pointer; + + wth_verbose("waltham_pointer_leave [%d]\n", window->receiver_surf->ivi_id); + + wthp_pointer_send_leave (pointer->obj, serial, surface->obj); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +void +waltham_pointer_motion(struct window *window, uint32_t time, + wl_fixed_t sx, wl_fixed_t sy) +{ + wth_verbose("%s >>> \n",__func__); + struct seat *seat = window->receiver_seat; + struct pointer *pointer = seat->pointer; + + wthp_pointer_send_motion (pointer->obj, time, sx, sy); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +void +waltham_pointer_button(struct window *window, uint32_t serial, + uint32_t time, uint32_t button, + uint32_t state) +{ + wth_verbose("%s >>> \n",__func__); + struct seat *seat = window->receiver_seat; + struct pointer *pointer = seat->pointer; + + wthp_pointer_send_button (pointer->obj, serial, time, button, state); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +void +waltham_pointer_axis(struct window *window, uint32_t time, + uint32_t axis, wl_fixed_t value) +{ + wth_verbose("%s >>> \n",__func__); + struct seat *seat = window->receiver_seat; + struct pointer *pointer = seat->pointer; + + wthp_pointer_send_axis (pointer->obj, time, axis, value); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +/* + * waltham pointer implementation + */ +static void +pointer_set_cursor(struct wthp_pointer *wthp_pointer, int32_t serial, struct wthp_surface *surface, + int32_t hotspot_x, int32_t hotspot_y) +{ + struct pointer *pointer = wth_object_get_user_data((struct wth_object *)wthp_pointer); + + wth_verbose("wthp_pointer %p (%d, %p, %d, %d)\n", + wthp_pointer, serial, surface, hotspot_x, hotspot_y); + +} + +static void +pointer_release(struct wthp_pointer *wthp_pointer) +{ + struct pointer *pointer = wth_object_get_user_data((struct wth_object *)wthp_pointer); + + wth_verbose("wthp_pointer %p\n",wthp_pointer); +} + +static const struct wthp_pointer_interface pointer_implementation = { + pointer_set_cursor, + pointer_release +}; + +/* + * APIs to send touch events to waltham client + */ + +void +waltham_touch_down(struct window *window, uint32_t serial, + uint32_t time, int32_t id, + wl_fixed_t x_w, wl_fixed_t y_w) +{ + wth_verbose("%s >>> \n",__func__); + struct surface *surface = window->receiver_surf; + struct seat *seat = window->receiver_seat; + struct touch *touch = seat->touch; + + wth_verbose("touch_handle_down surface [%d]\n", surface->ivi_id); + wthp_touch_send_down(touch->obj, serial, time, surface->obj, id, x_w, y_w); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +void +waltham_touch_up(struct window *window, uint32_t serial, + uint32_t time, int32_t id) +{ + wth_verbose("%s >>> \n",__func__); + struct seat *seat = window->receiver_seat; + struct touch *touch = seat->touch; + + wthp_touch_send_up(touch->obj, serial, time, id); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +void +waltham_touch_motion(struct window *window, uint32_t time, + int32_t id, wl_fixed_t x_w, wl_fixed_t y_w) +{ + wth_verbose("%s >>> \n",__func__); + struct seat *seat = window->receiver_seat; + struct touch *touch = seat->touch; + + wthp_touch_send_motion(touch->obj, time, id, x_w, y_w); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +void +waltham_touch_frame(struct window *window) +{ + wth_verbose("%s >>> \n",__func__); + struct seat *seat = window->receiver_seat; + struct touch *touch = seat->touch; + + wthp_touch_send_frame(touch->obj); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +void +waltham_touch_cancel(struct window *window) +{ + wth_verbose("%s >>> \n",__func__); + struct seat *seat = window->receiver_seat; + struct touch *touch = seat->touch; + + wthp_touch_send_cancel(touch->obj); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +/* + * waltham touch implementation + */ +static void +touch_release(struct wthp_touch *wthp_touch) +{ + wth_verbose("%s >>> \n",__func__); + struct touch *touch = wth_object_get_user_data((struct wth_object *)wthp_touch); + + wth_verbose("%p\n",wthp_touch); +} + +static const struct wthp_touch_interface touch_implementation = { + touch_release, +}; + +/* + * waltham seat implementation + */ +static void +seat_get_pointer(struct wthp_seat *wthp_seat, struct wthp_pointer *wthp_pointer) +{ + wth_verbose("%s >>> \n",__func__); + + wth_verbose("wthp_seat %p get_pointer(%p)\n", + wthp_seat, wthp_pointer); + + struct seat *seat = wth_object_get_user_data((struct wth_object *)wthp_seat); + struct pointer *pointer; + + pointer = zalloc(sizeof *pointer); + if (!pointer) { + client_post_out_of_memory(seat->client); + return; + } + + pointer->obj = wthp_pointer; + pointer->seat = seat; + seat->pointer = pointer; + wl_list_insert(&seat->client->pointer_list, &pointer->link); + + wthp_pointer_set_interface(wthp_pointer, &pointer_implementation, pointer); + wth_verbose(" <<< %s \n",__func__); +} + +static void +seat_get_touch(struct wthp_seat *wthp_seat, struct wthp_touch *wthp_touch) +{ + wth_verbose("%s >>> \n",__func__); + wth_verbose("wthp_seat %p get_touch(%p)\n", + wthp_seat, wthp_touch); + + struct seat *seat = wth_object_get_user_data((struct wth_object *)wthp_seat); + struct touch *touch; + + touch = zalloc(sizeof *touch); + if (!touch) { + client_post_out_of_memory(seat->client); + return; + } + + touch->obj = wthp_touch; + touch->seat = seat; + seat->touch = touch; + wl_list_insert(&seat->client->touch_list, &touch->link); + + wthp_touch_set_interface(wthp_touch, &touch_implementation, touch); + wth_verbose(" <<< %s \n",__func__); +} + +static void +seat_release(struct wthp_seat *wthp_seat) +{ +} + +static const struct wthp_seat_interface seat_implementation = { + seat_get_pointer, + NULL, + seat_get_touch, + seat_release, + NULL +}; + +static void +seat_send_updated_caps(struct seat *seat) +{ + wth_verbose("%s >>> \n",__func__); + enum wthp_seat_capability caps = 0; + + caps |= WTHP_SEAT_CAPABILITY_POINTER; + wth_verbose("WTHP_SEAT_CAPABILITY_POINTER %d\n", caps); + + caps |= WTHP_SEAT_CAPABILITY_TOUCH; + wth_verbose("WTHP_SEAT_CAPABILITY_TOUCH %d\n", caps); + + wthp_seat_send_capabilities(seat->obj, caps); + wth_verbose(" <<< %s \n",__func__); +} + +static void +client_bind_seat(struct client *c, struct wthp_seat *obj) +{ + wth_verbose("%s >>> \n",__func__); + struct seat *seat; + + seat = zalloc(sizeof *seat); + if (!seat) { + client_post_out_of_memory(c); + return; + } + + seat->obj = obj; + seat->client = c; + wl_list_insert(&c->seat_list, &seat->link); + wth_verbose("wthp_seat object=%p and seat=%p\n",obj,seat); + wthp_seat_set_interface(obj, &seat_implementation, + seat); + wth_verbose("client %p bound wthp_seat\n", c); + seat_send_updated_caps(seat); + wth_verbose(" <<< %s \n",__func__); +} + +/* + * waltham region implementation + */ + +static void +region_destroy(struct region *region) +{ + wth_verbose("%s >>> \n",__func__); + wth_verbose("region %p destroy\n", region->obj); + + wthp_region_free(region->obj); + wl_list_remove(®ion->link); + free(region); + wth_verbose(" <<< %s \n",__func__); +} + +static void +region_handle_destroy(struct wthp_region *wthp_region) +{ + wth_verbose("%s >>> \n",__func__); + struct region *region = wth_object_get_user_data((struct wth_object *)wthp_region); + + assert(wthp_region == region->obj); + + region_destroy(region); + wth_verbose(" <<< %s \n",__func__); +} + +static void +region_handle_add(struct wthp_region *wthp_region, + int32_t x, int32_t y, int32_t width, int32_t height) +{ + wth_verbose("region %p add(%d, %d, %d, %d)\n", + wthp_region, x, y, width, height); +} + +static void +region_handle_subtract(struct wthp_region *wthp_region, + int32_t x, int32_t y, + int32_t width, int32_t height) +{ + wth_verbose("region %p subtract(%d, %d, %d, %d)\n", + wthp_region, x, y, width, height); +} + +static const struct wthp_region_interface region_implementation = { + region_handle_destroy, + region_handle_add, + region_handle_subtract +}; + +/* + * waltham compositor implementation + */ +static void +compositor_destroy(struct compositor *comp) +{ + wth_verbose("%s >>> \n",__func__); + wth_verbose("%s: %p\n", __func__, comp->obj); + + wthp_compositor_free(comp->obj); + wl_list_remove(&comp->link); + free(comp); + wth_verbose(" <<< %s \n",__func__); +} + +static void +compositor_handle_create_surface(struct wthp_compositor *compositor, + struct wthp_surface *id) +{ + wth_verbose("%s >>> \n",__func__); + struct compositor *comp = wth_object_get_user_data((struct wth_object *)compositor); + struct client *client = comp->client; + struct surface *surface; + struct seat *seat, *tmp; + + wth_verbose("client %p create surface %p\n", + comp->client, id); + + surface = zalloc(sizeof *surface); + if (!surface) { + client_post_out_of_memory(comp->client); + return; + } + + surface->obj = id; + wl_list_insert(&comp->client->surface_list, &surface->link); + + wthp_surface_set_interface(id, &surface_implementation, surface); + + surface->shm_window = calloc(1, sizeof *surface->shm_window); + if (!surface->shm_window) + return; + + surface->shm_window->receiver_surf = surface; + surface->shm_window->ready = false; + surface->ivi_id = 0; + + wl_list_for_each_safe(seat, tmp, &client->seat_list, link) { + surface->shm_window->receiver_seat = seat; + } + + wth_verbose(" <<< %s \n",__func__); +} + +static void +compositor_handle_create_region(struct wthp_compositor *compositor, + struct wthp_region *id) +{ + wth_verbose("%s >>> \n",__func__); + struct compositor *comp = wth_object_get_user_data((struct wth_object *)compositor); + struct region *region; + + wth_verbose("client %p create region %p\n", + comp->client, id); + + region = zalloc(sizeof *region); + if (!region) { + client_post_out_of_memory(comp->client); + return; + } + + region->obj = id; + wl_list_insert(&comp->client->region_list, ®ion->link); + + wthp_region_set_interface(id, ®ion_implementation, region); + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wthp_compositor_interface compositor_implementation = { + compositor_handle_create_surface, + compositor_handle_create_region +}; + +static void +client_bind_compositor(struct client *c, struct wthp_compositor *obj) +{ + wth_verbose("%s >>> \n",__func__); + struct compositor *comp; + + comp = zalloc(sizeof *comp); + if (!comp) { + client_post_out_of_memory(c); + return; + } + + comp->obj = obj; + comp->client = c; + wl_list_insert(&c->compositor_list, &comp->link); + + wthp_compositor_set_interface(obj, &compositor_implementation, + comp); + wth_verbose("client %p bound wthp_compositor\n", c); + wth_verbose(" <<< %s \n",__func__); +} + +/* + * waltham registry implementation + */ +static void +registry_destroy(struct registry *reg) +{ + wth_verbose("%s >>> \n",__func__); + wth_verbose("%s: %p\n", __func__, reg->obj); + + wthp_registry_free(reg->obj); + wl_list_remove(®->link); + free(reg); + wth_verbose(" <<< %s \n",__func__); +} + +static void +registry_handle_destroy(struct wthp_registry *registry) +{ + wth_verbose("%s >>> \n",__func__); + struct registry *reg = wth_object_get_user_data((struct wth_object *)registry); + + registry_destroy(reg); + wth_verbose(" <<< %s \n",__func__); +} + +static void +registry_handle_bind(struct wthp_registry *registry, + uint32_t name, + struct wth_object *id, + const char *interface, + uint32_t version) +{ + wth_verbose("%s >>> \n",__func__); + struct registry *reg = wth_object_get_user_data((struct wth_object *)registry); + wth_verbose("Recieved registry : %s\n", interface); + + if (strcmp(interface, "wthp_compositor") == 0) { + client_bind_compositor(reg->client, (struct wthp_compositor *)id); + } else if (strcmp(interface, "wthp_blob_factory") == 0) { + client_bind_blob_factory(reg->client, (struct wthp_blob_factory *)id); + struct client *client = reg->client; + struct seat *seat, *tmp,*get_seat; + wl_list_for_each_safe(seat, tmp, &client->seat_list, link) { + get_seat = seat; + } + wth_verbose("get_seat : %p\n", get_seat); + seat_send_updated_caps(get_seat); + } else if (strcmp(interface, "wthp_ivi_application") == 0) { + client_bind_wthp_ivi_application(reg->client, (struct wthp_ivi_application *)id); + } else if (strcmp(interface, "wthp_seat") == 0) { + client_bind_seat(reg->client, (struct wthp_seat *)id); + } else { + wth_object_post_error((struct wth_object *)registry, 0, + "%s: unknown name %u", __func__, name); + wth_object_delete(id); + } + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wthp_registry_interface registry_implementation = { + registry_handle_destroy, + registry_handle_bind +}; + +/* + * waltham display implementation + */ + +static void +display_handle_client_version(struct wth_display *wth_display, + uint32_t client_version) +{ + wth_verbose("%s >>> \n",__func__); + wth_object_post_error((struct wth_object *)wth_display, 0, + "unimplemented: %s", __func__); + wth_verbose(" <<< %s \n",__func__); +} + +static void +display_handle_sync(struct wth_display * wth_display, struct wthp_callback * callback) +{ + wth_verbose("%s >>> \n",__func__); + struct client *c = wth_object_get_user_data((struct wth_object *)wth_display); + + wth_verbose("Client %p requested wth_display.sync\n", c); + wthp_callback_send_done(callback, 0); + wthp_callback_free(callback); + wth_verbose(" <<< %s \n",__func__); +} + +static void +display_handle_get_registry(struct wth_display *wth_display, + struct wthp_registry *registry) +{ + wth_verbose("%s >>> \n",__func__); + struct client *c = wth_object_get_user_data((struct wth_object *)wth_display); + struct registry *reg; + + reg = zalloc(sizeof *reg); + if (!reg) { + client_post_out_of_memory(c); + return; + } + + reg->obj = registry; + reg->client = c; + wl_list_insert(&c->registry_list, ®->link); + wthp_registry_set_interface(registry, + ®istry_implementation, reg); + + wthp_registry_send_global(registry, 1, "wthp_compositor", 4); + wthp_registry_send_global(registry, 1, "wthp_ivi_application", 1); + wthp_registry_send_global(registry, 1, "wthp_seat", 4); + wthp_registry_send_global(registry, 1, "wthp_blob_factory", 4); + wth_verbose(" <<< %s \n",__func__); +} + +const struct wth_display_interface display_implementation = { + display_handle_client_version, + display_handle_sync, + display_handle_get_registry +}; + +/* + * functions to handle waltham client connections + */ +static void +connection_handle_data(struct watch *w, uint32_t events) +{ + wth_verbose("%s >>> \n",__func__); + struct client *c = container_of(w, struct client, conn_watch); + int ret; + + if (events & EPOLLERR) { + wth_error("Client %p errored out.\n", c); + client_destroy(c); + + return; + } + + if (events & EPOLLHUP) { + wth_error("Client %p hung up.\n", c); + client_destroy(c); + + return; + } + + if (events & EPOLLOUT) { + ret = wth_connection_flush(c->connection); + if (ret == 0) + watch_ctl(&c->conn_watch, EPOLL_CTL_MOD, EPOLLIN); + else if (ret < 0 && errno != EAGAIN){ + wth_error("Client %p flush error.\n", c); + client_destroy(c); + + return; + } + } + + if (events & EPOLLIN) { + ret = wth_connection_read(c->connection); + if (ret < 0) { + wth_error("Client %p read error.\n", c); + client_destroy(c); + + return; + } + + ret = wth_connection_dispatch(c->connection); + if (ret < 0 && errno != EPROTO) { + wth_error("Client %p dispatch error.\n", c); + client_destroy(c); + + return; + } + } + wth_verbose(" <<< %s \n",__func__); +} + +/** +* client_create +* +* Create new client connection +* +* @param srv receiver structure +* @param wth_connection Waltham connection handle +* @return Pointer to client structure +*/ +static struct client * +client_create(struct receiver *srv, struct wth_connection *conn) +{ + wth_verbose("%s >>> \n",__func__); + struct client *c; + struct wth_display *disp; + + c = zalloc(sizeof *c); + if (!c) + return NULL; + + c->receiver = srv; + c->connection = conn; + + c->conn_watch.receiver = srv; + c->conn_watch.fd = wth_connection_get_fd(conn); + c->conn_watch.cb = connection_handle_data; + if (watch_ctl(&c->conn_watch, EPOLL_CTL_ADD, EPOLLIN) < 0) { + free(c); + return NULL; + } + + wth_verbose("Client %p connected.\n", c); + + wl_list_insert(&srv->client_list, &c->link); + + wl_list_init(&c->registry_list); + wl_list_init(&c->compositor_list); + wl_list_init(&c->seat_list); + wl_list_init(&c->pointer_list); + wl_list_init(&c->touch_list); + wl_list_init(&c->region_list); + wl_list_init(&c->surface_list); + wl_list_init(&c->buffer_list); + + disp = wth_connection_get_display(c->connection); + wth_display_set_interface(disp, &display_implementation, c); + + wth_verbose(" <<< %s \n",__func__); + return c; +} + +/** +* client_destroy +* +* Destroy client connection +* +* @param names struct client *c +* @param value client data +* @return none +*/ +void +client_destroy(struct client *c) +{ + wth_verbose("%s >>> \n",__func__); + struct region *region; + struct compositor *comp; + struct registry *reg; + struct surface *surface; + + wth_verbose("Client %p disconnected.\n", c); + + /* clean up remaining client resources in case the client + * did not. + */ + wl_list_last_until_empty(region, &c->region_list, link) + region_destroy(region); + + wl_list_last_until_empty(comp, &c->compositor_list, link) + compositor_destroy(comp); + + wl_list_last_until_empty(reg, &c->registry_list, link) + registry_destroy(reg); + + wl_list_last_until_empty(surface, &c->surface_list, link) + surface_destroy(surface); + + wl_list_remove(&c->link); + watch_ctl(&c->conn_watch, EPOLL_CTL_DEL, 0); + wth_connection_destroy(c->connection); + free(c); + wth_verbose(" <<< %s \n",__func__); +} + +/** +* receiver_flush_clients +* +* write all the pending requests from the clients to socket +* +* @param names struct receiver *srv +* @param value socket connection info and client data +* @return none +*/ +void +receiver_flush_clients(struct receiver *srv) +{ + wth_verbose("%s >>> \n",__func__); + struct client *c, *tmp; + int ret; + + wl_list_for_each_safe(c, tmp, &srv->client_list, link) { + /* Flush out buffered requests. If the Waltham socket is + * full, poll it for writable too. + */ + ret = wth_connection_flush(c->connection); + if (ret < 0 && errno == EAGAIN) { + watch_ctl(&c->conn_watch, EPOLL_CTL_MOD, EPOLLIN | EPOLLOUT); + } else if (ret < 0) { + perror("Connection flush failed"); + client_destroy(c); + return; + } + } + + wth_verbose(" <<< %s \n",__func__); + +} + +/** +* receiver_accept_client +* +* Accepts new waltham client connection and instantiates client structure +* +* @param names struct receiver *srv +* @param value socket connection info and client data +* @return none +*/ +void +receiver_accept_client(struct receiver *srv) +{ + wth_verbose("%s >>> \n",__func__); + struct client *client; + struct wth_connection *conn; + struct sockaddr_in addr; + socklen_t len; + + len = sizeof addr; + conn = wth_accept(srv->listen_fd, (struct sockaddr *)&addr, &len); + if (!conn) { + wth_error("Failed to accept a connection.\n"); + return; + } + + client = client_create(srv, conn); + if (!client) { + wth_error("Failed client_create().\n"); + return; + } + wth_verbose(" <<< %s \n",__func__); +} -- cgit 1.2.3-korg