From 0454c3830b4a1c8265f05b8aacf8d47847518443 Mon Sep 17 00:00:00 2001 From: "pr.jung" Date: Fri, 2 Dec 2016 13:31:32 +0900 Subject: [PATCH] haptic: Guarantee device_handle validation when device-vibrator crashs. - Add InitiateVibrator signal handler - Return pointer of handle structure instead of integer value for device_handle Change-Id: I0fe08ebbd252c12e02afa50d3dbc4343296f97cc Signed-off-by: pr.jung --- src/dbus.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++ src/dbus.h | 4 +++ src/haptic.c | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 201 insertions(+), 4 deletions(-) diff --git a/src/dbus.c b/src/dbus.c index 15e7051..b5d5757 100644 --- a/src/dbus.c +++ b/src/dbus.c @@ -27,12 +27,15 @@ #include "dbus.h" #define DBUS_REPLY_TIMEOUT (-1) +#define SIGNAL_VIBRATOR_INITIATED "InitiateVibrator" struct pending_call_data { dbus_pending_cb func; void *data; }; +static guint haptic_id = 0; + //LCOV_EXCL_START System Error static int g_dbus_error_to_errno(int code) { @@ -345,3 +348,90 @@ int dbus_method_async_with_reply(const char *dest, const char *path, return 0; } + +static void haptic_signal_callback(GDBusConnection *conn, + const gchar *sender, + const gchar *path, + const gchar *iface, + const gchar *signal, + GVariant *params, + gpointer user_data) +{ + size_t iface_len, signal_len; + + if (!params || !sender || !path || !iface || !signal) + return; + + iface_len = strlen(iface) + 1; + signal_len = strlen(signal) + 1; + + if (strncmp(iface, VIBRATOR_INTERFACE_HAPTIC, iface_len)) + return; + + if (strncmp(signal, SIGNAL_VIBRATOR_INITIATED, signal_len)) + return; + + restart_callback(); +} + +int register_signal_handler(void) +{ + GDBusConnection *conn; + GError *err = NULL; + int result = 0; + + conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err); + if (!conn) { +//LCOV_EXCL_START System Error + if (err) { + _E("g_bus_get_sync error : (%d-%s)", err->code, err->message); + result = g_dbus_error_to_errno(err->code); + g_clear_error(&err); + } + return result; +//LCOV_EXCL_STOP + } + + haptic_id = g_dbus_connection_signal_subscribe(conn, + NULL, + VIBRATOR_INTERFACE_HAPTIC, + NULL, + VIBRATOR_PATH_HAPTIC, + NULL, + G_DBUS_SIGNAL_FLAGS_NONE, + haptic_signal_callback, + NULL, + NULL); + + g_object_unref(conn); + if (haptic_id == 0) { + _E("Failed to subscrive bus signal"); + return -EPERM; + } + + return 0; +} + +int unregister_signal_handler(void) +{ + GDBusConnection *conn; + GError *err = NULL; + int result = 0; + + conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err); + if (!conn) { +//LCOV_EXCL_START System Error + if (err) { + _E("g_bus_get_sync error : (%d-%s)", err->code, err->message); + result = g_dbus_error_to_errno(err->code); + g_clear_error(&err); + } + return result; +//LCOV_EXCL_STOP + } + + g_dbus_connection_signal_unsubscribe(conn, haptic_id); + g_object_unref(conn); + + return 0; +} diff --git a/src/dbus.h b/src/dbus.h index 41a8805..27a58e0 100644 --- a/src/dbus.h +++ b/src/dbus.h @@ -77,4 +77,8 @@ int dbus_method_async_with_reply(const char *dest, const char *path, const char *interface, const char *method, const char *sig, char *param[], dbus_pending_cb cb, int timeout, void *data); +void restart_callback(void); + +int register_signal_handler(void); +int unregister_signal_handler(void); #endif diff --git a/src/haptic.c b/src/haptic.c index b510ffd..2fcf096 100644 --- a/src/haptic.c +++ b/src/haptic.c @@ -19,10 +19,12 @@ #include #include +#include #include "haptic.h" #include "common.h" #include "dbus.h" +#include "list.h" #define METHOD_GET_COUNT "GetCount" #define METHOD_OPEN_DEVICE "OpenDevice" @@ -41,6 +43,13 @@ enum priority_e { HAPTIC_PRIORITY_HIGH, }; +struct haptic_handle { + int index; + int handle; +}; + +static dd_list *handle_list; + int device_haptic_get_count(int *device_number) { int ret; @@ -65,11 +74,38 @@ int device_haptic_get_count(int *device_number) return DEVICE_ERROR_NONE; } +void restart_callback(void) +{ + dd_list *elem; + char str_index[32]; + char *arr[1]; + struct haptic_handle *temp; + int ret; + + DD_LIST_FOREACH(handle_list, elem, temp) { + snprintf(str_index, sizeof(str_index), "%d", temp->index); + arr[0] = str_index; + ret = dbus_method_sync(VIBRATOR_BUS_NAME, + VIBRATOR_PATH_HAPTIC, VIBRATOR_INTERFACE_HAPTIC, + METHOD_OPEN_DEVICE, "i", arr); + if (ret < 0) { + _E("Failed to open device"); + continue; + } + temp->handle = ret; + } + +} + int device_haptic_open(int device_index, haptic_device_h *device_handle) { + dd_list *elem; + struct haptic_handle *handle; + struct haptic_handle *temp; char str_index[32]; char *arr[1]; int ret, max; + bool found = false; ret = device_haptic_get_count(&max); if (ret < 0) @@ -91,20 +127,55 @@ int device_haptic_open(int device_index, haptic_device_h *device_handle) if (ret < 0) return errno_to_device_error(ret); //LCOV_EXCL_LINE System Error - *device_handle = (haptic_device_h)ret; + DD_LIST_FOREACH(handle_list, elem, temp) { + if (temp->handle == ret) { + found = true; + temp->index = device_index; + break; + } + } + + if (!found) { + handle = (struct haptic_handle *)malloc(sizeof(struct haptic_handle)); + handle->handle = ret; + handle->index = device_index; + DD_LIST_APPEND(handle_list, handle); + *device_handle = (haptic_device_h)handle; + } + if (DD_LIST_LENGTH(handle_list) == 1) { + ret = register_signal_handler(); + if (ret < 0) + _E("Faild to register signal handler"); + } + return DEVICE_ERROR_NONE; } int device_haptic_close(haptic_device_h device_handle) { + dd_list *elem; + struct haptic_handle *handle = (struct haptic_handle *)device_handle; + struct haptic_handle *temp; char str_handle[32]; char *arr[1]; int ret; + bool found = false; if (!device_handle) return DEVICE_ERROR_INVALID_PARAMETER; - snprintf(str_handle, sizeof(str_handle), "%u", (unsigned int)device_handle); + DD_LIST_FOREACH(handle_list, elem, temp) { + if (temp->handle != handle->handle) + continue; + found = true; + break; + } + + if (!found) + return DEVICE_ERROR_OPERATION_FAILED; + DD_LIST_REMOVE(handle_list, handle); + snprintf(str_handle, sizeof(str_handle), "%u", (unsigned int)handle->handle); + free(handle); arr[0] = str_handle; /* request to deviced to open haptic device */ @@ -114,17 +185,27 @@ int device_haptic_close(haptic_device_h device_handle) if (ret < 0) return errno_to_device_error(ret); //LCOV_EXCL_LINE System Error + if (DD_LIST_LENGTH(handle_list) == 0) { + ret = unregister_signal_handler(); + if (ret < 0) + _E("Failed to unregister signal handler"); + } + return DEVICE_ERROR_NONE; } int device_haptic_vibrate(haptic_device_h device_handle, int duration, int feedback, haptic_effect_h *effect_handle) { + dd_list *elem; + struct haptic_handle *handle = (struct haptic_handle *)device_handle; + struct haptic_handle *temp; char str_handle[32]; char str_duration[32]; char str_feedback[32]; char str_priority[32]; char *arr[4]; int ret, priority; + bool found = false; if (!device_handle) return DEVICE_ERROR_INVALID_PARAMETER; @@ -137,7 +218,16 @@ int device_haptic_vibrate(haptic_device_h device_handle, int duration, int feedb priority = HAPTIC_PRIORITY_MIN; - snprintf(str_handle, sizeof(str_handle), "%u", (unsigned int)device_handle); + DD_LIST_FOREACH(handle_list, elem, temp) { + if (temp != handle) + continue; + found = true; + break; + } + if (!found) + return DEVICE_ERROR_INVALID_PARAMETER; + + snprintf(str_handle, sizeof(str_handle), "%u", (unsigned int)handle->handle); arr[0] = str_handle; snprintf(str_duration, sizeof(str_duration), "%d", duration); arr[1] = str_duration; @@ -161,15 +251,28 @@ int device_haptic_vibrate(haptic_device_h device_handle, int duration, int feedb int device_haptic_stop(haptic_device_h device_handle, haptic_effect_h effect_handle) { + dd_list *elem; + struct haptic_handle *handle = (struct haptic_handle *)device_handle; + struct haptic_handle *temp; char str_handle[32]; char *arr[1]; int ret; + bool found = false; if (!device_handle) return DEVICE_ERROR_INVALID_PARAMETER; + DD_LIST_FOREACH(handle_list, elem, temp) { + if (temp != handle) + continue; + found = true; + break; + } + if (!found) + return DEVICE_ERROR_INVALID_PARAMETER; + /* TODO : support to stop haptic effect */ - snprintf(str_handle, sizeof(str_handle), "%u", (unsigned int)device_handle); + snprintf(str_handle, sizeof(str_handle), "%u", (unsigned int)handle->handle); arr[0] = str_handle; /* request to deviced to open haptic device */ -- 2.7.4