From 80d388be9e095544b50a6004f2c8e54039ff7c18 Mon Sep 17 00:00:00 2001 From: Seunghun Lee Date: Thu, 19 Jul 2018 16:17:14 +0900 Subject: [PATCH] virtual output: Add implementation for set_available_modes, connect and disconnect. Change-Id: Ic85238c5833286ae22fc698d3d8b3fe2fc903e24 --- client/tdm_client.c | 76 ++++++++++++++++++++++- client/tdm_client_types.h | 14 +++-- haltests/src/tc_tdm_client.cpp | 56 ++++++++++++++--- protocol/tdm.xml | 23 +++++++ src/tdm_server.c | 136 +++++++++++++++++++++++++++++++++++++++-- 5 files changed, 282 insertions(+), 23 deletions(-) diff --git a/client/tdm_client.c b/client/tdm_client.c index 8d17c94..4c05811 100644 --- a/client/tdm_client.c +++ b/client/tdm_client.c @@ -92,6 +92,13 @@ typedef struct _tdm_private_client_output { typedef struct _tdm_private_client_voutput { tdm_private_client_output base; struct wl_tdm_voutput *wl_voutput; + + struct + { + int count; + tdm_client_output_mode *modes; + } available_modes; + uint32_t msg; } tdm_private_client_voutput; @@ -1679,7 +1686,6 @@ tdm_client_create_voutput(tdm_client *client, const char *name, tdm_error *error private_voutput->base.private_client = private_client; - snprintf(private_voutput->base.name, TDM_NAME_LEN, "%s", name); private_voutput->wl_voutput = wl_tdm_create_voutput((struct wl_tdm *)wrapper, private_voutput->base.name); wl_proxy_wrapper_destroy(wrapper); if (!private_voutput->wl_voutput) { @@ -1731,15 +1737,36 @@ tdm_client_voutput_destroy(tdm_client_voutput *voutput) if (!private_voutput) return; + wl_tdm_voutput_destroy(private_voutput->wl_voutput); + free(private_voutput); } tdm_error tdm_client_voutput_set_available_modes(tdm_client_voutput *voutput, const tdm_client_output_mode *modes, int count) { + tdm_private_client_voutput *private_voutput; + TDM_RETURN_VAL_IF_FAIL(voutput != NULL, TDM_ERROR_INVALID_PARAMETER); - TDM_RETURN_VAL_IF_FAIL(modes != NULL, TDM_ERROR_INVALID_PARAMETER); - TDM_RETURN_VAL_IF_FAIL(count > 0, TDM_ERROR_INVALID_PARAMETER); + + if ((count > 0) && (modes == NULL)) + return TDM_ERROR_INVALID_PARAMETER; + + private_voutput = (tdm_private_client_voutput *)voutput; + + if (private_voutput->base.connection == TDM_OUTPUT_CONN_STATUS_CONNECTED) + return TDM_ERROR_BAD_REQUEST; + + if (private_voutput->available_modes.modes) + free(private_voutput->available_modes.modes); + + private_voutput->available_modes.count = count; + + if (count != 0) + { + private_voutput->available_modes.modes = calloc(count, sizeof(tdm_client_output_mode)); + memcpy(private_voutput->available_modes.modes, modes, sizeof(tdm_client_output_mode) * count); + } return TDM_ERROR_NONE; } @@ -1807,14 +1834,57 @@ tdm_client_output_set_mode(tdm_client_output *output, const tdm_client_output_mo tdm_error tdm_client_output_connect(tdm_client_output *output) { + tdm_private_client_output *private_output; + tdm_private_client_voutput *private_voutput; + tdm_client_output_mode *modes; + int i; + TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER); + private_output = (tdm_private_client_output *)output; + private_voutput = (tdm_private_client_voutput *)output; + + TDM_RETURN_VAL_IF_FAIL(private_output->connection != TDM_OUTPUT_CONN_STATUS_CONNECTED, + TDM_ERROR_BAD_REQUEST); + + private_output->connection = TDM_OUTPUT_CONN_STATUS_CONNECTED; + + modes = private_voutput->available_modes.modes; + for (i = 0; i < private_voutput->available_modes.count; i++) + { + wl_tdm_voutput_set_available_modes(private_voutput->wl_voutput, i, + modes[i].clock, modes[i].hdisplay, + modes[i].hsync_start, modes[i].hsync_end, + modes[i].htotal, modes[i].hskew, + modes[i].vdisplay, modes[i].vsync_start, + modes[i].vsync_end, modes[i].vtotal, + modes[i].vscan, modes[i].vrefresh, + modes[i].flags, modes[i].type, + modes[i].name); + } + + wl_tdm_voutput_connect(private_voutput->wl_voutput); + return TDM_ERROR_NONE; } tdm_error tdm_client_output_disconnect(tdm_client_output *output) { + tdm_private_client_voutput *private_voutput; + tdm_private_client_output *private_output; + TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER); + + private_output = (tdm_private_client_output *)output; + private_voutput = (tdm_private_client_voutput *)output; + + TDM_RETURN_VAL_IF_FAIL(private_output->connection != TDM_OUTPUT_CONN_STATUS_DISCONNECTED, + TDM_ERROR_BAD_REQUEST); + + private_output->connection = TDM_OUTPUT_CONN_STATUS_DISCONNECTED; + + wl_tdm_voutput_disconnect(private_voutput->wl_voutput); + return TDM_ERROR_NONE; } diff --git a/client/tdm_client_types.h b/client/tdm_client_types.h index cb4e96d..096b44f 100644 --- a/client/tdm_client_types.h +++ b/client/tdm_client_types.h @@ -110,13 +110,15 @@ typedef void void *user_data); /* Virtual Output */ +/* this is a copy of server side's tdm_output_mode */ typedef struct _tdm_client_output_mode { - char name[TDM_NAME_LEN]; /**< The output name */ - unsigned int mode_count; /**< The count of available modes */ - unsigned int prop_count; /**< The count of available properties */ - unsigned int mmWidth; /**< The physical width (milimeter) */ - unsigned int mmHeight; /**< The physical height (milimeter) */ - unsigned int subpixel; /**< The subpixel */ + unsigned int clock; + unsigned int hdisplay, hsync_start, hsync_end, htotal, hskew; + unsigned int vdisplay, vsync_start, vsync_end, vtotal, vscan; + unsigned int vrefresh; + unsigned int flags; + unsigned int type; + char name[TDM_NAME_LEN]; } tdm_client_output_mode; typedef void tdm_client_voutput; diff --git a/haltests/src/tc_tdm_client.cpp b/haltests/src/tc_tdm_client.cpp index f7ff9f8..1909ff0 100644 --- a/haltests/src/tc_tdm_client.cpp +++ b/haltests/src/tc_tdm_client.cpp @@ -1412,7 +1412,7 @@ public: protected: static tdm_client *client; static tdm_client_voutput *voutput; - const int MODE_COUNT = 1; + const int MODE_COUNT = 2; private: static pid_t server_pid; @@ -1522,12 +1522,21 @@ TEST_F(TDMVirtualOutput, SetAvailableModes) for (i = 0; i < count; i++) { - modes[i].mmHeight = 1234; - modes[i].mmWidth = 1234; - modes[i].mode_count = 0; - modes[i].prop_count = 0; - modes[i].subpixel = 0; - snprintf(modes[i].name, TDM_NAME_LEN, "TestModeSetting"); + modes[i].clock = 1; + modes[i].hdisplay = 2; + modes[i].hsync_start = 3; + modes[i].hsync_end = 4; + modes[i].htotal = 5; + modes[i].hskew = 6; + modes[i].vdisplay = 7; + modes[i].vsync_start = 8; + modes[i].vsync_end = 9; + modes[i].vtotal = 10; + modes[i].vscan = 11; + modes[i].vrefresh = 12; + modes[i].flags = 13; + modes[i].type = 14; + snprintf(modes[i].name, TDM_NAME_LEN, "TestModeSetting %d", i); } ret = tdm_client_voutput_set_available_modes(this->voutput, modes, count); @@ -1545,9 +1554,6 @@ TEST_F(TDMVirtualOutput, FailTestSetAvailableModes) ret = tdm_client_voutput_set_available_modes(this->voutput, NULL, count); ASSERT_EQ(ret, TDM_ERROR_INVALID_PARAMETER); - - ret = tdm_client_voutput_set_available_modes(this->voutput, modes, 0); - ASSERT_EQ(ret, TDM_ERROR_INVALID_PARAMETER); } TEST_F(TDMVirtualOutput, SetPhysicalSize) @@ -1578,6 +1584,36 @@ TEST_F(TDMVirtualOutput, GetClientOutput) ASSERT_NE(output, NULL); } +TEST_F(TDMVirtualOutput, Connect) +{ + tdm_error ret; + tdm_client_output *output; + + output = tdm_client_voutput_get_client_output(this->voutput, &ret); + ASSERT_EQ(ret, TDM_ERROR_NONE); + ASSERT_NE(output, NULL); + + ret = tdm_client_output_connect(output); + ASSERT_EQ(ret, TDM_ERROR_NONE); + + tdm_client_handle_events_timeout(this->client, 0); +} + +TEST_F(TDMVirtualOutput, Disconnect) +{ + tdm_error ret; + tdm_client_output *output; + + output = tdm_client_voutput_get_client_output(this->voutput, &ret); + ASSERT_EQ(ret, TDM_ERROR_NONE); + ASSERT_NE(output, NULL); + + ret = tdm_client_output_disconnect(output); + ASSERT_EQ(ret, TDM_ERROR_NONE); + + tdm_client_handle_events_timeout(this->client, 0); +} + #if 0 TEST_F(TDMVirtualOutput, FailTestGetClientOutput) { diff --git a/protocol/tdm.xml b/protocol/tdm.xml index 58422cf..1248920 100644 --- a/protocol/tdm.xml +++ b/protocol/tdm.xml @@ -77,6 +77,29 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tdm_server.c b/src/tdm_server.c index d98339c..ed4ddff 100644 --- a/src/tdm_server.c +++ b/src/tdm_server.c @@ -703,6 +703,132 @@ _tdm_server_cb_create_output(struct wl_client *client, struct wl_resource *resou } } +typedef struct _tdm_server_voutput_info { + tdm_private_server *private_server; + tdm_output_conn_status status; + struct + { + int count; + tdm_output_mode *modes; + } available_modes; +} tdm_server_voutput_info; + +static void _tdm_voutput_cb_destroy(struct wl_client *client, struct wl_resource *resource) +{ + wl_resource_destroy(resource); +} + +static void +_tdm_voutput_cb_set_available_modes(struct wl_client *client, + struct wl_resource *resource, + uint32_t index, + uint32_t clock, + uint32_t hdisplay, + uint32_t hsync_start, + uint32_t hsync_end, + uint32_t htotal, + uint32_t hskew, + uint32_t vdisplay, + uint32_t vsync_start, + uint32_t vsync_end, + uint32_t vtotal, + uint32_t vscan, + uint32_t vrefresh, + uint32_t flags, + uint32_t type, + const char *name) +{ + tdm_server_voutput_info *voutput_info; + tdm_output_mode *tmp_modes, *old_modes; + tdm_output_mode *new_mode; + int count, len; + + voutput_info = wl_resource_get_user_data(resource); + + count = voutput_info->available_modes.count; + old_modes = voutput_info->available_modes.modes; + if (index >= count) + { + if (count > 0) + { + tmp_modes = malloc(count * sizeof(*tmp_modes)); + memcpy(tmp_modes, old_modes, count * sizeof(tdm_output_mode)); + } + + voutput_info->available_modes.count = index + 1; + voutput_info->available_modes.modes = + realloc(voutput_info->available_modes.modes, + sizeof(tdm_output_mode) * (index + 1)); + + if (count > 0) + { + memcpy(voutput_info->available_modes.modes, tmp_modes, count * sizeof(tdm_output_mode)); + free(tmp_modes); + } + } + + new_mode = &voutput_info->available_modes.modes[index]; + new_mode->clock = clock; + new_mode->hdisplay = hdisplay; + new_mode->hsync_start = hsync_start; + new_mode->hsync_end = hsync_end; + new_mode->htotal = htotal; + new_mode->hskew= hskew; + new_mode->vdisplay= vdisplay; + new_mode->vsync_start= vsync_start; + new_mode->vsync_end = vsync_end; + new_mode->vtotal = vtotal; + new_mode->vscan = vscan; + new_mode->vrefresh = vrefresh; + new_mode->flags = flags; + new_mode->type = type; + + len = strlen(name); + strncpy(new_mode->name, name, len); + new_mode->name[len] = '\0'; +} + +static void +_tdm_voutput_cb_connect(struct wl_client *client, struct wl_resource *resource) +{ + tdm_server_voutput_info *voutput_info; + + voutput_info = wl_resource_get_user_data(resource); + voutput_info->status = TDM_OUTPUT_CONN_STATUS_CONNECTED; +} + +static void +_tdm_voutput_cb_disconnect(struct wl_client *client, struct wl_resource *resource) +{ + tdm_server_voutput_info *voutput_info; + + voutput_info = wl_resource_get_user_data(resource); + voutput_info->status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED; + + /* Do free resources when it's being disconnected */ + free(voutput_info->available_modes.modes); + voutput_info->available_modes.modes = NULL; + voutput_info->available_modes.count = 0; +} + +static const struct wl_tdm_voutput_interface tdm_voutput_implementation = { + _tdm_voutput_cb_destroy, + _tdm_voutput_cb_set_available_modes, + _tdm_voutput_cb_connect, + _tdm_voutput_cb_disconnect +}; + +void +tdm_voutput_cb_resource_destroy(struct wl_resource *resource) +{ + tdm_server_voutput_info *voutput_info; + + voutput_info = wl_resource_get_user_data(resource); + + /* Do free your own resource */ + free(voutput_info); +} + static void _tdm_server_cb_create_virtual_output(struct wl_client *client, struct wl_resource *resource, const char *name, uint32_t id) { @@ -758,10 +884,12 @@ _tdm_server_cb_create_virtual_output(struct wl_client *client, struct wl_resourc voutput_info->resource = voutput_resource; voutput_info->output = output; LIST_INITHEAD(&voutput_info->output_list); -#if 0 - wl_resource_set_implementation(voutput_resource, &tdm_voutput_implementation, - voutput_info, destroy_voutput_callback); -#endif + + wl_resource_set_implementation(voutput_resource, + &tdm_voutput_implementation, + voutput_info, + tdm_voutput_cb_resource_destroy); + wl_tdm_voutput_send_ack_message(voutput_resource, WL_TDM_VOUTPUT_MESSAGE_ADDED); } -- 2.7.4