1 /**************************************************************************
5 * Copyright 2015 Samsung Electronics co., Ltd. All Rights Reserved.
7 * Contact: Eunchul Kim <chulspro.kim@samsung.com>,
8 * JinYoung Jeon <jy0.jeon@samsung.com>,
9 * Taeheon Kim <th908.kim@samsung.com>,
10 * YoungJun Cho <yj44.cho@samsung.com>,
11 * SooChan Lim <sc1.lim@samsung.com>,
12 * Boram Park <sc1.lim@samsung.com>
14 * Permission is hereby granted, free of charge, to any person obtaining a
15 * copy of this software and associated documentation files (the
16 * "Software"), to deal in the Software without restriction, including
17 * without limitation the rights to use, copy, modify, merge, publish,
18 * distribute, sub license, and/or sell copies of the Software, and to
19 * permit persons to whom the Software is furnished to do so, subject to
20 * the following conditions:
22 * The above copyright notice and this permission notice (including the
23 * next paragraph) shall be included in all copies or substantial portions
26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
27 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
29 * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
30 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
31 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
32 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 **************************************************************************/
44 #include "tdm_client.h"
45 #include "tdm_macro.h"
47 typedef struct _tdm_test_client_arg {
56 } tdm_test_client_arg;
58 typedef struct _tdm_test_client {
59 tdm_test_client_arg args;
87 static struct typestrings typestrs[] = {
93 static struct optstrings optstrs[] = {
94 {OPT_QRY, "qo", "output objects info", "<output_name>", "primary"},
95 {OPT_TST, "v", "vblank test", "<output_name>[,<sync>][@<fps>][~<interval>][+<offset>][*fake][^vblank_name]", "primary,0@60~1+0*1^test"},
101 int type_size = sizeof(typestrs) / sizeof(struct typestrings);
102 int opt_size = sizeof(optstrs) / sizeof(struct optstrings);
105 printf("usage: %s \n\n", app_name);
107 for (t = 0; t < type_size; t++) {
110 for (o = 0; o < opt_size; o++)
111 if (optstrs[o].type == typestrs[t].type) {
113 printf(" %s options:\n\n", typestrs[t].string);
114 printf("\t-%s\t%s\n", optstrs[o].opt, optstrs[o].desc);
116 printf("\t\t %s\n", optstrs[o].arg);
118 printf("\t\t ex) %s\n", optstrs[o].ex);
129 parse_arg_qo(tdm_test_client *data, char *arg)
131 char name[TDM_NAME_LEN];
132 strtostr(name, TDM_NAME_LEN, arg, TDM_DELIM);
133 data->args.output_name = strndup(name, TDM_NAME_LEN);
136 //"<output_name>[,<sync>][@<fps>][~<interval>][+<offset>][*fake]"
138 parse_arg_v(tdm_test_client *data, char *arg)
141 char name[TDM_NAME_LEN];
143 end = strtostr(name, TDM_NAME_LEN, arg, TDM_DELIM);
144 data->args.output_name = strndup(name, TDM_NAME_LEN);
148 data->args.sync = strtol(arg, &end, 10);
153 data->args.fps = strtol(arg, &end, 10);
158 data->args.interval = strtol(arg, &end, 10);
161 if (*end == '+' || *end == '-') {
163 data->args.offset = strtol(arg, &end, 10);
168 data->args.enable_fake = strtol(arg, &end, 10);
172 char name[TDM_NAME_LEN];
174 end = strtostr(name, TDM_NAME_LEN, arg, TDM_DELIM);
175 data->args.vblank_name = strndup(name, TDM_NAME_LEN);
180 parse_args(tdm_test_client *data, int argc, char *argv[])
189 memset(data, 0, sizeof *data);
190 data->args.interval = 1;
192 for (i = 1; i < argc; i++) {
193 if (!strncmp(argv[i] + 1, "qo", 2)) {
195 parse_arg_qo(data, argv[++i]);
196 } else if (!strncmp(argv[i] + 1, "v", 1)) {
198 parse_arg_v(data, argv[++i]);
211 if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0)
212 return (double)tp.tv_sec + ((double)tp.tv_nsec) / 1000000000.0;
218 _client_vblank_handler(tdm_client_vblank *vblank, tdm_error error, unsigned int sequence,
219 unsigned int tv_sec, unsigned int tv_usec, void *user_data)
221 tdm_test_client *data = user_data;
223 static double p_vbl = 0;
227 if (error == TDM_ERROR_DPMS_OFF) {
228 printf("exit: dpms off\n");
232 if (error != TDM_ERROR_NONE) {
233 printf("exit: error(%d)\n", error);
238 vbl = (double)tv_sec + ((double)tv_usec) / 1000000.0;
240 printf("vblank : %.6f us vbl(%.6f)\n", vbl - p_vbl, vbl);
242 if (cur - vbl > 0.002) /* 2ms */
243 printf("kernel -> tdm-client: %.0f us\n", (cur - vbl) * 1000000.0);
248 static char *conn_str[3] = {"disconnected", "connected", "mode_setted"};
249 static char *dpms_str[4] = {"on", "standy", "suspend", "off"};
252 _client_output_handler(tdm_client_output *output, tdm_output_change_type type,
253 tdm_value value, void *user_data)
255 if (type == TDM_OUTPUT_CHANGE_CONNECTION)
256 printf("output %s.\n", conn_str[value.u32]);
257 else if (type == TDM_OUTPUT_CHANGE_DPMS)
258 printf("dpms %s.\n", dpms_str[value.u32]);
262 do_query(tdm_test_client *data)
264 tdm_client_output *output;
265 tdm_output_conn_status status;
266 tdm_output_dpms dpms;
267 unsigned int refresh;
270 output = tdm_client_get_output(data->client, NULL, &error);
271 if (error != TDM_ERROR_NONE) {
272 printf("tdm_client_get_output failed\n");
276 tdm_client_output_get_conn_status(output, &status);
277 tdm_client_output_get_dpms(output, &dpms);
278 tdm_client_output_get_refresh_rate(output, &refresh);
280 printf("tdm_output \"%s\"\n", data->args.output_name);
281 printf("\tstatus : %s\n", conn_str[status]);
282 printf("\tdpms : %s\n", dpms_str[dpms]);
283 printf("\trefresh : %d\n", refresh);
287 do_vblank(tdm_test_client *data)
289 tdm_client_output *output;
290 tdm_client_vblank *vblank = NULL;
295 output = tdm_client_get_output(data->client, data->args.output_name, &error);
296 if (error != TDM_ERROR_NONE) {
297 printf("tdm_client_get_output failed\n");
301 tdm_client_output_add_change_handler(output, _client_output_handler, NULL);
303 vblank = tdm_client_output_create_vblank(output, &error);
304 if (error != TDM_ERROR_NONE) {
305 printf("tdm_client_output_create_vblank failed\n");
309 tdm_client_vblank_set_name(vblank, data->args.vblank_name);
310 tdm_client_vblank_set_enable_fake(vblank, data->args.enable_fake);
311 tdm_client_vblank_set_sync(vblank, data->args.sync);
312 if (data->args.fps > 0)
313 tdm_client_vblank_set_fps(vblank, data->args.fps);
314 tdm_client_vblank_set_offset(vblank, data->args.offset);
316 error = tdm_client_get_fd(data->client, &fd);
317 if (error != TDM_ERROR_NONE || fd < 0) {
318 printf("tdm_client_get_fd failed\n");
329 if (!data->waiting) {
330 error = tdm_client_vblank_wait(vblank, data->args.interval,
331 _client_vblank_handler, data);
332 if (error == TDM_ERROR_DPMS_OFF) {
333 printf("tdm_client_vblank_wait failed (dpms off)\n");
336 if (error != TDM_ERROR_NONE) {
337 printf("tdm_client_vblank_wait failed (error: %d)\n", error);
343 if (!data->args.sync) {
344 ret = poll(&fds, 1, -1);
346 if (errno == EINTR || errno == EAGAIN) /* normal case */
349 printf("poll failed: %m\n");
354 error = tdm_client_handle_events(data->client);
355 if (error != TDM_ERROR_NONE) {
356 printf("tdm_client_handle_events failed\n");
364 tdm_client_vblank_destroy(vblank);
367 static tdm_test_client ttc_data;
370 main(int argc, char *argv[])
372 tdm_test_client *data = &ttc_data;
375 #if 1 /* for testing */
376 const char *xdg = (const char*)getenv("XDG_RUNTIME_DIR");
379 snprintf(buf, sizeof(buf), "/run");
380 int ret = setenv("XDG_RUNTIME_DIR", (const char*)buf, 1);
386 parse_args(data, argc, argv);
388 printf("sync(%d) fps(%d) interval(%d) offset(%d) enable_fake(%d) pid(%d)\n",
389 data->args.sync, data->args.fps, data->args.interval,
390 data->args.offset, data->args.enable_fake, data->args.pid);
392 data->client = tdm_client_create(&error);
393 if (error != TDM_ERROR_NONE) {
394 printf("tdm_client_create failed\n");
404 if (data->args.output_name)
405 free(data->args.output_name);
406 if (data->args.vblank_name)
407 free(data->args.vblank_name);
409 tdm_client_destroy(data->client);