From c67debace2c0a2f2bfb53b9d71cb18d3a6f947fc Mon Sep 17 00:00:00 2001 From: Yunhee Seo Date: Mon, 9 Jan 2023 23:18:46 +0900 Subject: [PATCH] input: add the dbus interface and input config parser Add input device information dbus methods Input event on/off option can be handled by device id number. With config file, user can set the customed input devices and input-parser will mananging input devices from it. [InputDeivce] format which is in input.conf InputDeviceType -> hal_deivce_input_type InputDeviceId -> id number which exist under the /sys/class/input/inputXX path InputDeviceName -> device name InputDeviceDefault -> yes/no Input dbus methods 1. Get input devices path: /Org/Tizen/System/DeviceD/Input interface: org.tizen.system.deviced.input member: InputGetDevices parameter: "(i)", input device type to get device id list return: "(ai)", get int device id list on success, empty list on error. 2. Get default device path: /Org/Tizen/System/DeviceD/Input interface: org.tizen.system.deviced.input member: InputGetDefaultDevice parameter: "(i)", input device type to get default devicd id return: "(i)", get device id value on success, negative on error. 3. Get device name path: /Org/Tizen/System/DeviceD/Input interface: org.tizen.system.deviced.input member: InputGetDeviceName parameter: "(i)", input device id to get device name return: "(is)", (ret_val, ret_dev_name) negative ret_val means error, otherwise success. Change-Id: I0977c29f538f432cb5ab82e610130698ce7ad5b9 Signed-off-by: Yunhee Seo --- src/input/input-dbus.c | 67 +++++++++++++++++ src/input/input-device-manager.c | 156 +++++++++++++++++++++++++++++++++++++++ src/input/input-device-manager.h | 30 ++++++++ src/input/input-parser.c | 136 ++++++++++++++++++++++++++++++++++ src/input/input-parser.h | 26 +++++++ src/input/input.c | 14 ++++ 6 files changed, 429 insertions(+) create mode 100644 src/input/input-device-manager.c create mode 100644 src/input/input-device-manager.h create mode 100644 src/input/input-parser.c create mode 100644 src/input/input-parser.h diff --git a/src/input/input-dbus.c b/src/input/input-dbus.c index ba00174..df7ccd7 100644 --- a/src/input/input-dbus.c +++ b/src/input/input-dbus.c @@ -34,6 +34,7 @@ #include "input.h" #include "input-dbus.h" #include "input-interface.h" +#include "input-device-manager.h" /* FIXME: input.keyboard feature check should be added and return DEVICE_ERROR_NOT_SUPPORTED */ static GVariant *dbus_inputseteventstate(GDBusConnection *conn, @@ -94,10 +95,76 @@ static GVariant *dbus_emulate_key(GDBusConnection *conn, return gdbus_new_g_variant_tuple(); } +static GVariant *dbus_inputgetdevices(GDBusConnection *conn, + const gchar *sender, const gchar *path, const gchar *iface, const gchar *name, + GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data) +{ + int input_type; + pid_t pid; + GVariant* input_device_list; + + g_variant_get(param, "(i)", &input_type); + input_device_list = input_devman_find_device_list(input_type); + + pid = gdbus_connection_get_sender_pid(conn, sender); + _D("Input get devices pid=%d input device type=%d", pid, input_type); + + return input_device_list; +} + +static GVariant *dbus_inputgetdefaultdevice(GDBusConnection *conn, + const gchar *sender, const gchar *path, const gchar *iface, const gchar *name, + GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data) +{ + int input_type, input_default_device_id = 0, ret = 0; + pid_t pid; + + g_variant_get(param, "(i)", &input_type); + + ret = input_devman_find_default_device(input_type, &input_default_device_id); + if (ret < 0) + _E("Failed to get input default device id"); + else + ret = input_default_device_id; + + pid = gdbus_connection_get_sender_pid(conn, sender); + _D("Input get default device pid=%d input device type=%d", pid, input_type); + + return g_variant_new("(i)", ret); +} + +static GVariant *dbus_inputgetdevicename(GDBusConnection *conn, + const gchar *sender, const gchar *path, const gchar *iface, const gchar *name, + GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data) +{ + GVariant *dbus_ret; + int input_id, ret = 0; + char *input_device_name; + pid_t pid; + + g_variant_get(param, "(i)", &input_id); + + ret = input_devman_find_device_name(input_id, &input_device_name); + if (ret < 0) + _E("Failed to get input device name"); + + pid = gdbus_connection_get_sender_pid(conn, sender); + _D("Input get device name pid=%d input device id=%d input device name=%s", + pid, input_id, input_device_name); + + dbus_ret = g_variant_new("(is)", ret, input_device_name); + free(input_device_name); + + return dbus_ret; +} + static const dbus_method_s dbus_methods[] = { {"InputSetEventState", "ii", "i", dbus_inputseteventstate}, {"InputGetEventState", "i", "i", dbus_inputgeteventstate}, {"EmulateKey", "ii", NULL, dbus_emulate_key}, + {"InputGetDevices", "i", "ai", dbus_inputgetdevices}, + {"InputGetDefaultDevice","i", "i", dbus_inputgetdefaultdevice}, + {"InputGetDeviceName","i", "is", dbus_inputgetdevicename}, /* Add methods here */ }; diff --git a/src/input/input-device-manager.c b/src/input/input-device-manager.c new file mode 100644 index 0000000..3bd966a --- /dev/null +++ b/src/input/input-device-manager.c @@ -0,0 +1,156 @@ +/* + * deviced + * + * Copyright (c) 2023 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include + +#include "shared/log.h" +#include "input-device-manager.h" + +static struct input_device_element { + int id; + int device_default; + char *name; +}; + +static GHashTable *g_input_device_list; + +static void destroy_input_device_hashtable_value(gpointer data) +{ + g_list_free((GList*)data); +} + +int input_devman_init(void) +{ + g_input_device_list = g_hash_table_new_full(g_int_hash, g_int_equal, + g_free, destroy_input_device_hashtable_value); + if (g_input_device_list) + return 0; + return -EPERM; +} + +void input_devman_exit(void) +{ + if (g_input_device_list) + g_hash_table_destroy(g_steal_pointer(&g_input_device_list)); +} + +static struct input_device_element* find_input_device_info_element_by_device_id(int input_device_id) +{ + GList *all_input_device_list = g_hash_table_get_values(g_input_device_list); + GList *temp_glist1, *temp_glist2, *temp_input_device_list; + struct input_device_element *input_device_elem; + + SYS_G_LIST_FOREACH(all_input_device_list, temp_glist1, temp_input_device_list) { + SYS_G_LIST_FOREACH(temp_input_device_list, temp_glist2, input_device_elem) { + if (input_device_id == input_device_elem->id) + return input_device_elem; + } + } + return NULL; +} + +static GList* find_input_device_list_by_device_type(int input_device_type) +{ + gint *hash_key = g_new(gint, 1); + *hash_key = input_device_type; + GList *find_list = g_hash_table_lookup(g_input_device_list, hash_key); + g_free(hash_key); + return find_list; +} + +int input_devman_find_default_device(int input_device_type, int *input_device_id) +{ + GList *find_input_device_list = find_input_device_list_by_device_type(input_device_type); + GList *temp_glist1; + struct input_device_element *input_device_elem; + + if (find_input_device_list == NULL) + return -ENXIO; + + SYS_G_LIST_FOREACH(find_input_device_list, temp_glist1, input_device_elem) { + if (input_device_elem->device_default == 1) { + *input_device_id = input_device_elem->id; + return 0; + } + } + return -ENXIO; +} + +GVariant *input_devman_find_device_list(int input_device_type) +{ + GList *find_input_device_list = find_input_device_list_by_device_type(input_device_type); + GList *temp_glist1; + GVariantBuilder *input_device_list_builder = g_variant_builder_new(G_VARIANT_TYPE("ai")); + GVariant *id_list; + struct input_device_element *input_device_elem; + int num_input_ids = g_list_length(find_input_device_list); + + if (num_input_ids <= 0) { + id_list = g_variant_new("(ai)", input_device_list_builder); + goto out; + } + + SYS_G_LIST_FOREACH(find_input_device_list, temp_glist1, input_device_elem) { + g_variant_builder_add(input_device_list_builder, "i", input_device_elem->id); + } + id_list = g_variant_new("(ai)", input_device_list_builder); +out: + g_variant_builder_unref(input_device_list_builder); + return id_list; +} + +int input_devman_find_device_name(int input_device_id, char** input_device_name) +{ + struct input_device_element *input_device_elem = find_input_device_info_element_by_device_id(input_device_id); + + if (input_device_elem == NULL) + return -ENXIO; + + *input_device_name = strndup(input_device_elem->name, 32); + return 0; +} + +int input_devman_add_device(int input_device_type, int input_device_id, + int input_device_default, char *input_device_name) +{ + struct input_device_element *input_device_elem = NULL; + GList* hash_value_list = NULL; + gint *hash_key = g_new(gint, 1); + + input_device_elem = malloc(sizeof(struct input_device_element)); + if (!input_device_elem) { + _E("Failed to malloc input device element"); + return -ENOMEM; + } + input_device_elem->id = input_device_id; + input_device_elem->device_default = input_device_default; + input_device_elem->name = strndup(input_device_name, 32); + *hash_key = input_device_type; + hash_value_list = g_hash_table_lookup(g_input_device_list, hash_key); + + if (hash_value_list != NULL) { + hash_value_list = g_list_append(hash_value_list, input_device_elem); + g_free(hash_key); + } else { + hash_value_list = g_list_append(hash_value_list, input_device_elem); + g_hash_table_insert(g_input_device_list, hash_key, hash_value_list); + } + return 0; +} \ No newline at end of file diff --git a/src/input/input-device-manager.h b/src/input/input-device-manager.h new file mode 100644 index 0000000..782345f --- /dev/null +++ b/src/input/input-device-manager.h @@ -0,0 +1,30 @@ +/* + * deviced + * + * Copyright (c) 2023 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __INPUT_DEVICE_MANAGER_H__ +#define __INPUT_DEVICE_MANAGER_H__ + +int input_devman_init(void); +void input_devman_exit(void); +int input_devman_find_default_device(int input_device_type, int *input_device_id); +GVariant *input_devman_find_device_list(int input_device_type); +int input_devman_find_device_name(int input_device_id, char** input_device_name); +int input_devman_add_device(int input_device_type, int input_device_id, + int input_device_default, char *input_device_name); + +#endif /* __INPUT_DEVICE_MANAGER_H__ */ \ No newline at end of file diff --git a/src/input/input-parser.c b/src/input/input-parser.c new file mode 100644 index 0000000..ea45fdb --- /dev/null +++ b/src/input/input-parser.c @@ -0,0 +1,136 @@ +/* + * deviced + * + * Copyright (c) 2023 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "shared/log.h" +#include "input-parser.h" +#include "input-device-manager.h" + +#define INPUT_CONF_PATH "/hal/etc/deviced/input.conf" + +static struct input_device_info { + int input_device_type; + int input_device_id; + char *input_device_name; + int input_device_default; +}; + +static GHashTable *g_hash_table_to_check_default_duplicated; + +static bool is_default_input_device_duplicated(int input_device_type) +{ + gint *hash_key = g_new(gint, 1); + *hash_key = input_device_type; + if (g_hash_table_contains(g_hash_table_to_check_default_duplicated, hash_key)) { + g_free(hash_key); + return true; + } else { + g_hash_table_insert(g_hash_table_to_check_default_duplicated, hash_key, NULL); + } + return false; +} + +static void parse_input_device_property(gpointer data, gpointer user_data) +{ + struct section_property *prop = (struct section_property *) data; + struct input_device_info *input_dev_info = *(struct input_device_info **)user_data; + + if (!prop || !input_dev_info) + return; + + if (MATCH(prop->key, "InputDeviceType")) { + if (MATCH(prop->value, "unknown")) + input_dev_info->input_device_type = (int)HAL_DEVICE_INPUT_TYPE_UNKNOWN; + else if (MATCH(prop->value, "mouse")) + input_dev_info->input_device_type = (int)HAL_DEVICE_INPUT_TYPE_MOUSE; + else if (MATCH(prop->value, "keyboard")) + input_dev_info->input_device_type = (int)HAL_DEVICE_INPUT_TYPE_KEYBOARD; + else if (MATCH(prop->value, "custom_knob")) + input_dev_info->input_device_type = (int)HAL_DEVICE_INPUT_TYPE_CUSTOM_KNOB; + } else if (MATCH(prop->key, "InputDeviceId")) { + sscanf(prop->value, "%d", (&input_dev_info->input_device_id)); + } else if (MATCH(prop->key, "InputDeviceName")) { + input_dev_info->input_device_name = calloc(sizeof(prop->value), sizeof(char)); + strcpy(input_dev_info->input_device_name, prop->value); + } else if (MATCH(prop->key, "InputDeviceDefault")) { + if (MATCH(prop->value, "yes")) + input_dev_info->input_device_default = 1; + else if (MATCH(prop->value, "no")) + input_dev_info->input_device_default = 0; + } +} + +static int parse_input_device_section(const struct parse_result *result, void *data) +{ + struct input_device_info *input_dev_info; + int ret; + + if (!result || !result->props) + return 0; + + if (!MATCH(result->section, "InputDevice")) + return 0; + + input_dev_info = calloc(1, sizeof(struct input_device_info)); + if (!input_dev_info) + return -ENOMEM; + + g_list_foreach(result->props, parse_input_device_property, &input_dev_info); + if (input_dev_info->input_device_default == 1) { + if (is_default_input_device_duplicated(input_dev_info->input_device_type)) + return -EPERM; + } + ret = input_devman_add_device(input_dev_info->input_device_type, + input_dev_info->input_device_id, + input_dev_info->input_device_default, + input_dev_info->input_device_name); + free(input_dev_info); + + if (ret < 0) + return ret; + + return 0; +} + +int input_parser_init(void) +{ + int ret; + + g_hash_table_to_check_default_duplicated = g_hash_table_new_full(g_int_hash, g_int_equal, + g_free, g_free); + + ret = libsys_config_parse_by_section(INPUT_CONF_PATH, parse_input_device_section, NULL); + + if (g_hash_table_to_check_default_duplicated) { + g_hash_table_destroy(g_steal_pointer(&g_hash_table_to_check_default_duplicated)); + } + + if (ret < 0) + return ret; + + return 0; +} \ No newline at end of file diff --git a/src/input/input-parser.h b/src/input/input-parser.h new file mode 100644 index 0000000..f041c11 --- /dev/null +++ b/src/input/input-parser.h @@ -0,0 +1,26 @@ +/* + * deviced + * + * Copyright (c) 2023 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __INPUT_PARSER_H__ +#define __INPUT_PARSER_H__ + +#include + +int input_parser_init(void); + +#endif //__INPUT_PARSER_H__ \ No newline at end of file diff --git a/src/input/input.c b/src/input/input.c index 20b4faf..e30357f 100644 --- a/src/input/input.c +++ b/src/input/input.c @@ -34,7 +34,9 @@ #include "shared/log.h" #include "input.h" #include "input-dbus.h" +#include "input-parser.h" #include "input-interface.h" +#include "input-device-manager.h" #define SEAT_NAME "seat0" @@ -119,6 +121,16 @@ static void input_init(void *data) if (input_plugin_ops == NULL) _E("Failed to init input_ops"); + ret = input_devman_init(); + if (ret < 0) + _E("Failed to initialize input device manager(%d)", ret); + + ret = input_parser_init(); + if (ret < 0) { + _E("Failed to parsing input config file(%d)", ret); + input_devman_exit(); + } + ret = input_dbus_init(); if (ret < 0) _E("Failed to init input device dbus interface(%d)", ret); @@ -176,6 +188,8 @@ static void input_exit(void *data) input_handler->exit(NULL); input_handler = NULL; + + input_devman_exit(); } static const struct device_ops input_device_ops = { -- 2.7.4