From 65a8648ffaca491aa4d16640f1633f5f0cd0b07a Mon Sep 17 00:00:00 2001 From: Boram Park Date: Fri, 2 Mar 2018 16:38:27 +0900 Subject: [PATCH] client: add tdm_client_handle_events_timeout Change-Id: Ifebfbe10670f7f8af366e26c8ea8e172f024d6a1 --- client/tdm_client.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++ client/tdm_client.h | 12 ++++++++ include/tdm_common.h | 1 + 3 files changed, 98 insertions(+) diff --git a/client/tdm_client.c b/client/tdm_client.c index e71c691..84b4c07 100644 --- a/client/tdm_client.c +++ b/client/tdm_client.c @@ -42,6 +42,7 @@ #include #include #include +#include #include @@ -570,6 +571,90 @@ tdm_client_handle_events(tdm_client *client) /* LCOV_EXCL_STOP */ } +static int +_tdm_client_poll(struct wl_display *display, short int events, int timeout) +{ + int ret; + struct pollfd pfd[1]; + + pfd[0].fd = wl_display_get_fd(display); + pfd[0].events = events; + do { + ret = poll(pfd, 1, timeout); + } while (ret == -1 && errno == EINTR); + + return ret; +} + +static tdm_error +_tdm_client_dispatch_timeout(tdm_private_client *private_client, int timeout) +{ + int ret; + struct wl_display *display = private_client->display; + + if (wl_display_prepare_read(display) == -1) + return wl_display_dispatch_pending(display); + + while (true) { + ret = wl_display_flush(display); + + if (ret != -1 || errno != EAGAIN) + break; + + if (_tdm_client_poll(display, POLLOUT, -1) == -1) { + wl_display_cancel_read(display); + TDM_ERR("_tdm_client_poll failed"); + return TDM_ERROR_OPERATION_FAILED; + } + } + + /* Don't stop if flushing hits an EPIPE; continue so we can read any + * protocol error that may have triggered it. */ + if (ret < 0 && errno != EPIPE) { + TDM_ERR("ret(%d) errno(%d)", ret, errno); + wl_display_cancel_read(display); + return TDM_ERROR_OPERATION_FAILED; + } + + ret = _tdm_client_poll(display, POLLIN, timeout); + if (ret <= 0) { + wl_display_cancel_read(display); + if (ret == 0) { + TDM_ERR("_tdm_client_poll timeout."); + return TDM_ERROR_TIMEOUT; + } else { + TDM_ERR("_tdm_client_poll failed. (ret:%d)", ret); + return TDM_ERROR_OPERATION_FAILED; + } + } + + if (wl_display_read_events(display) == -1) { + TDM_ERR("wl_display_read_events failed"); + return TDM_ERROR_OPERATION_FAILED; + } + + ret = wl_display_dispatch_pending(display); + + if (ret < 0) { + TDM_ERR("_tdm_client_dispatch_timeout failed"); + return TDM_ERROR_OPERATION_FAILED; + } + + return TDM_ERROR_NONE; +} + +tdm_error +tdm_client_handle_events_timeout(tdm_client *client, int ms_timeout) +{ + tdm_private_client *private_client; + + TDM_RETURN_VAL_IF_FAIL(client != NULL, TDM_ERROR_INVALID_PARAMETER); + + private_client = (tdm_private_client*)client; + + return _tdm_client_dispatch_timeout(private_client, ms_timeout); +} + typedef struct _tdm_client_vblank_temp { tdm_client_vblank_handler2 func; void *user_data; diff --git a/client/tdm_client.h b/client/tdm_client.h index 4ef687b..2b9dc1e 100644 --- a/client/tdm_client.h +++ b/client/tdm_client.h @@ -117,6 +117,18 @@ tdm_error tdm_client_handle_events(tdm_client *client); /** + * @brief Handle the events of the given file descriptor with millisecond timeout + * @details + * -1: infinite. 0: return immediately. Otherwise, waiting for ms_timeout milliseconds. + * @param[in] client A TDM client object + * @param[in] ms_timeout timeout value. + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + * @see #tdm_client_get_fd + */ +tdm_error +tdm_client_handle_events_timeout(tdm_client *client, int ms_timeout); + +/** * @brief @b Deprecated. Wait for VBLANK. * @deprecated * @details After interval vblanks, a client vblank handler will be called. diff --git a/include/tdm_common.h b/include/tdm_common.h index 4c264ed..db7e087 100644 --- a/include/tdm_common.h +++ b/include/tdm_common.h @@ -69,6 +69,7 @@ typedef enum { TDM_ERROR_DPMS_OFF = -10, /**< dpms off */ TDM_ERROR_OUTPUT_DISCONNECTED = -11, /**< output disconnected */ TDM_ERROR_PROTOCOL_ERROR = -12, /**< protocol error */ + TDM_ERROR_TIMEOUT = -13, /**< timeout */ } tdm_error; /** -- 2.7.4