From 74d7482d9f5e479685abc82a28a531e13bc439d5 Mon Sep 17 00:00:00 2001 From: Jiyoung Yun Date: Fri, 6 Feb 2015 11:47:05 +0900 Subject: [PATCH 01/16] deviced: Remove unnecessary initialization DEVICE_PRIORITY_NORMAL value is zero. And static structure value is initilized zero automatically. Do not need to reassign the same value. Change-Id: Ib03242ebbf246ee8fbfc0f099cd5808886cfb68a Signed-off-by: Jiyoung Yun --- src/apps/apps.c | 1 - src/battery/battery-time.c | 1 - src/battery/lowbat-handler.c | 1 - src/bs/bs.c | 1 - src/control/control.c | 1 - src/core/sig-handler.c | 1 - src/cpu/cpu-handler.c | 1 - src/earjack/earjack.c | 1 - src/gpio/gpio.c | 1 - src/haptic/haptic.c | 1 - src/led/ir.c | 1 - src/led/torch.c | 1 - src/mmc/mmc-handler.c | 1 - src/power/power-handler.c | 1 - src/proc/cpu-info.c | 1 - src/proc/pmon-handler.c | 1 - src/proc/proc-handler.c | 1 - src/storage/storage.c | 1 - src/ta/ta-handler.c | 1 - src/telephony/telephony.c | 1 - src/time/time-handler.c | 1 - 21 files changed, 21 deletions(-) diff --git a/src/apps/apps.c b/src/apps/apps.c index a4d1530..e3a897d 100644 --- a/src/apps/apps.c +++ b/src/apps/apps.c @@ -85,7 +85,6 @@ static void apps_exit(void *data) } static const struct device_ops apps_device_ops = { - .priority = DEVICE_PRIORITY_NORMAL, .name = "apps", .init = apps_init, .exit = apps_exit, diff --git a/src/battery/battery-time.c b/src/battery/battery-time.c index 3759949..ee0f8af 100644 --- a/src/battery/battery-time.c +++ b/src/battery/battery-time.c @@ -463,7 +463,6 @@ static void battery_exit(void *data) } static const struct device_ops battery_time_device_ops = { - .priority = DEVICE_PRIORITY_NORMAL, .name = "battery-time", .init = battery_init, .exit = battery_exit, diff --git a/src/battery/lowbat-handler.c b/src/battery/lowbat-handler.c index b7fead2..8e19789 100644 --- a/src/battery/lowbat-handler.c +++ b/src/battery/lowbat-handler.c @@ -550,7 +550,6 @@ static void lowbat_exit(void *data) } static const struct device_ops lowbat_device_ops = { - .priority = DEVICE_PRIORITY_NORMAL, .name = "lowbat", .probe = lowbat_probe, .init = lowbat_init, diff --git a/src/bs/bs.c b/src/bs/bs.c index ae38ddb..590ba11 100644 --- a/src/bs/bs.c +++ b/src/bs/bs.c @@ -453,7 +453,6 @@ static void bs_init(void *data) } static const struct device_ops bs_device_ops = { - .priority = DEVICE_PRIORITY_NORMAL, .name = "bs", .init = bs_init, }; diff --git a/src/control/control.c b/src/control/control.c index 950d531..de37c47 100644 --- a/src/control/control.c +++ b/src/control/control.c @@ -221,7 +221,6 @@ static void control_init(void *data) } static const struct device_ops control_device_ops = { - .priority = DEVICE_PRIORITY_NORMAL, .name = "control", .init = control_init, }; diff --git a/src/core/sig-handler.c b/src/core/sig-handler.c index a04253c..e0bc74a 100644 --- a/src/core/sig-handler.c +++ b/src/core/sig-handler.c @@ -70,7 +70,6 @@ static void signal_init(void *data) } static const struct device_ops signal_device_ops = { - .priority = DEVICE_PRIORITY_NORMAL, .name = "signal", .init = signal_init, }; diff --git a/src/cpu/cpu-handler.c b/src/cpu/cpu-handler.c index 71d6d36..8724339 100644 --- a/src/cpu/cpu-handler.c +++ b/src/cpu/cpu-handler.c @@ -545,7 +545,6 @@ static void cpu_init(void *data) } static const struct device_ops cpu_device_ops = { - .priority = DEVICE_PRIORITY_NORMAL, .name = "cpu", .init = cpu_init, }; diff --git a/src/earjack/earjack.c b/src/earjack/earjack.c index bcc785e..c454745 100644 --- a/src/earjack/earjack.c +++ b/src/earjack/earjack.c @@ -131,7 +131,6 @@ static int earjack_execute(void *data) } static const struct device_ops earjack_device_ops = { - .priority = DEVICE_PRIORITY_NORMAL, .name = "earjack", .init = earjack_init, .status = earjack_get_status, diff --git a/src/gpio/gpio.c b/src/gpio/gpio.c index eea1751..0e15528 100644 --- a/src/gpio/gpio.c +++ b/src/gpio/gpio.c @@ -116,7 +116,6 @@ static void gpio_init(void *data) } const struct device_ops gpio_device_ops = { - .priority = DEVICE_PRIORITY_NORMAL, .name = "gpio", .init = gpio_init, }; diff --git a/src/haptic/haptic.c b/src/haptic/haptic.c index 2f0ff09..2884ac9 100644 --- a/src/haptic/haptic.c +++ b/src/haptic/haptic.c @@ -735,7 +735,6 @@ static int haptic_stop(void) } static const struct device_ops haptic_device_ops = { - .priority = DEVICE_PRIORITY_NORMAL, .name = "haptic", .init = haptic_init, .exit = haptic_exit, diff --git a/src/led/ir.c b/src/led/ir.c index 86f1767..af448ff 100644 --- a/src/led/ir.c +++ b/src/led/ir.c @@ -65,7 +65,6 @@ static void ir_init(void *data) } static const struct device_ops irled_device_ops = { - .priority = DEVICE_PRIORITY_NORMAL, .name = "irled", .init = ir_init, }; diff --git a/src/led/torch.c b/src/led/torch.c index ed734bb..f1cf6a3 100644 --- a/src/led/torch.c +++ b/src/led/torch.c @@ -112,7 +112,6 @@ static void torch_init(void *data) } static const struct device_ops torchled_device_ops = { - .priority = DEVICE_PRIORITY_NORMAL, .name = "torchled", .init = torch_init, }; diff --git a/src/mmc/mmc-handler.c b/src/mmc/mmc-handler.c index 84d20ef..7827e55 100644 --- a/src/mmc/mmc-handler.c +++ b/src/mmc/mmc-handler.c @@ -969,7 +969,6 @@ static int mmc_stop(enum device_flags flags) } const struct device_ops mmc_device_ops = { - .priority = DEVICE_PRIORITY_NORMAL, .name = "mmc", .init = mmc_init, .exit = mmc_exit, diff --git a/src/power/power-handler.c b/src/power/power-handler.c index efc36ad..9ae300e 100644 --- a/src/power/power-handler.c +++ b/src/power/power-handler.c @@ -541,7 +541,6 @@ static void power_init(void *data) } static const struct device_ops power_device_ops = { - .priority = DEVICE_PRIORITY_NORMAL, .name = POWER_OPS_NAME, .init = power_init, .execute = power_execute, diff --git a/src/proc/cpu-info.c b/src/proc/cpu-info.c index 2c8e00e..ae69559 100644 --- a/src/proc/cpu-info.c +++ b/src/proc/cpu-info.c @@ -143,7 +143,6 @@ static void cpu_info_init(void *data) } static const struct device_ops cpu_info_device_ops = { - .priority = DEVICE_PRIORITY_NORMAL, .name = "cpu_info", .init = cpu_info_init, }; diff --git a/src/proc/pmon-handler.c b/src/proc/pmon-handler.c index 7f88d0f..6e993be 100644 --- a/src/proc/pmon-handler.c +++ b/src/proc/pmon-handler.c @@ -274,7 +274,6 @@ static void pmon_init(void *data) } static const struct device_ops pmon_device_ops = { - .priority = DEVICE_PRIORITY_NORMAL, .name = "pmon", .init = pmon_init, }; diff --git a/src/proc/proc-handler.c b/src/proc/proc-handler.c index 25bac1f..deeddba 100644 --- a/src/proc/proc-handler.c +++ b/src/proc/proc-handler.c @@ -787,7 +787,6 @@ static void process_init(void *data) } static const struct device_ops process_device_ops = { - .priority = DEVICE_PRIORITY_NORMAL, .name = PROC_OPS_NAME, .init = process_init, .execute = process_execute, diff --git a/src/storage/storage.c b/src/storage/storage.c index af89d5a..87060be 100755 --- a/src/storage/storage.c +++ b/src/storage/storage.c @@ -426,7 +426,6 @@ static void lowmem_exit(void *data) } static const struct device_ops lowmem_device_ops = { - .priority = DEVICE_PRIORITY_NORMAL, .name = "lowmem", .init = lowmem_init, .exit = lowmem_exit, diff --git a/src/ta/ta-handler.c b/src/ta/ta-handler.c index bfa7770..0345f27 100644 --- a/src/ta/ta-handler.c +++ b/src/ta/ta-handler.c @@ -69,7 +69,6 @@ static void ta_init(void *data) } static const struct device_ops ta_device_ops = { - .priority = DEVICE_PRIORITY_NORMAL, .name = "ta", .init = ta_init, }; diff --git a/src/telephony/telephony.c b/src/telephony/telephony.c index 4d75554..a01bb72 100644 --- a/src/telephony/telephony.c +++ b/src/telephony/telephony.c @@ -411,7 +411,6 @@ static void telephony_init(void *data) } static const struct device_ops tel_device_ops = { - .priority = DEVICE_PRIORITY_NORMAL, .name = "telephony", .init = telephony_init, .start = telephony_start, diff --git a/src/time/time-handler.c b/src/time/time-handler.c index 879c1a9..17d5888 100644 --- a/src/time/time-handler.c +++ b/src/time/time-handler.c @@ -376,7 +376,6 @@ static void time_init(void *data) } static const struct device_ops time_device_ops = { - .priority = DEVICE_PRIORITY_NORMAL, .name = "time", .init = time_init, }; -- 2.7.4 From 6baf202211e5e635b58be30669f351030ca604a5 Mon Sep 17 00:00:00 2001 From: Jiyoung Yun Date: Fri, 6 Feb 2015 15:44:17 +0900 Subject: [PATCH 02/16] deviced: Fix library path under 64-bit architecture on pc file Change-Id: I2801f800b7251ae76daf634a2dd9906db77993d0 Signed-off-by: Jiyoung Yun --- deviced.pc.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deviced.pc.in b/deviced.pc.in index 6ce4c9b..fe1f8f2 100644 --- a/deviced.pc.in +++ b/deviced.pc.in @@ -2,7 +2,7 @@ prefix=@PREFIX@ exec_prefix=@EXEC_PREFIX@ -libdir=/usr/lib +libdir=@LIB_INSTALL_DIR@ includedir=/usr/include/deviced Name: deviced -- 2.7.4 From e60f8942718b3db28b43e63488459e4fdecebe42 Mon Sep 17 00:00:00 2001 From: taeyoung Date: Wed, 4 Feb 2015 17:46:53 +0900 Subject: [PATCH 03/16] extcon: add extcon uevent handler - The following is a example of extcon state in the uevent delivered when extcon devices are connected. USB=1 TA=0 FAST-CHARGER=0 SLOW-CHARGER=0 CHARGER-DOWNSTREAM=0 JIG-USB-ON=0 JIG-USB-OFF=0 JIG-UART-OFF=0 JIG-UART-ON=0 - extcon handler parses the extcon state information and notifies to the deviced modules related with the extcon devices. - 'struct extcon_ops' is used to register extcon devices. Change-Id: I612c4b38f527a0095c49b72958c595d72a99e56f Signed-off-by: taeyoung --- CMakeLists.txt | 1 + src/core/device-change-handler.c | 17 +++- src/core/udev.h | 3 + src/extcon/extcon.c | 212 +++++++++++++++++++++++++++++++++++++++ src/extcon/extcon.h | 46 +++++++++ 5 files changed, 276 insertions(+), 3 deletions(-) create mode 100755 src/extcon/extcon.c create mode 100755 src/extcon/extcon.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 7a6f018..88229eb 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,6 +33,7 @@ SET(SRCS src/core/log.c src/core/main.c src/core/sig-handler.c + src/extcon/extcon.c src/gpio/gpio.c src/power/power-handler.c src/proc/cpu-info.c diff --git a/src/core/device-change-handler.c b/src/core/device-change-handler.c index 2ba0feb..74e9391 100644 --- a/src/core/device-change-handler.c +++ b/src/core/device-change-handler.c @@ -43,6 +43,7 @@ #include "devices.h" #include "display/setting.h" #include "display/core.h" +#include "extcon/extcon.h" #define PREDEF_DEVICE_CHANGED "device_changed" #define PREDEF_POWER_CHANGED POWER_SUBSYSTEM @@ -153,6 +154,7 @@ enum udev_subsystem_type { UDEV_INPUT, UDEV_PLATFORM, UDEV_SWITCH, + UDEV_EXTCON, }; static const struct udev_subsystem { @@ -160,9 +162,10 @@ static const struct udev_subsystem { const char *str; const char *devtype; } udev_subsystems[] = { - { UDEV_INPUT, INPUT_SUBSYSTEM, NULL }, - { UDEV_PLATFORM, PLATFORM_SUBSYSTEM, NULL }, - { UDEV_SWITCH, SWITCH_SUBSYSTEM, NULL }, + { UDEV_INPUT, INPUT_SUBSYSTEM, NULL }, + { UDEV_PLATFORM, PLATFORM_SUBSYSTEM, NULL }, + { UDEV_SWITCH, SWITCH_SUBSYSTEM, NULL }, + { UDEV_EXTCON, EXTCON_SUBSYSTEM, NULL }, }; static dd_list *udev_event_list; @@ -786,6 +789,14 @@ static Eina_Bool uevent_kernel_control_cb(void *data, Ecore_Fd_Handler *fd_handl break; changed_device(env_value, NULL); break; + case UDEV_EXTCON: + env_value = udev_device_get_property_value(dev, "STATE"); + if (!env_value) + break; + ret = extcon_update(env_value); + if (ret < 0) + _E("Failed to update extcon status"); + break; } out: diff --git a/src/core/udev.h b/src/core/udev.h index f477a9d..ab231b4 100644 --- a/src/core/udev.h +++ b/src/core/udev.h @@ -58,6 +58,9 @@ /* switch device */ #define SWITCH_SUBSYSTEM "switch" +/* extcon */ +#define EXTCON_SUBSYSTEM "extcon" + /* host device */ #define HOST_SUBSYSTEM "host_notify" diff --git a/src/extcon/extcon.c b/src/extcon/extcon.c new file mode 100755 index 0000000..629c459 --- /dev/null +++ b/src/extcon/extcon.c @@ -0,0 +1,212 @@ +/* + * deviced + * + * Copyright (c) 2015 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 "core/log.h" +#include "core/list.h" +#include "core/common.h" +#include "core/devices.h" +#include "core/config-parser.h" +#include "core/device-notifier.h" +#include "extcon.h" + +#define EXTCON_PATH "/sys/class/extcon" + +#define BUF_MAX 256 + +static dd_list *extcon_list; + +void add_extcon(const struct extcon_ops *dev) +{ + DD_LIST_APPEND(extcon_list, dev); +} + +void remove_extcon(const struct extcon_ops *dev) +{ + DD_LIST_REMOVE(extcon_list, dev); +} + +static int extcon_changed(struct extcon_ops *dev, int status) +{ + if (!dev) + return -EINVAL; + + if (dev->status == status) + return 0; + + _I("Changed %s device : %d -> %d", dev->name, dev->status, status); + + dev->status = status; + device_notify(dev->noti, &status); + + return 0; +} + +static struct extcon_ops *find_extcon(const char *name) +{ + dd_list *l; + struct extcon_ops *dev; + + if (!name) + return NULL; + + DD_LIST_FOREACH(extcon_list, l, dev) { + if (!strcmp(dev->name, name)) + return dev; + } + + return NULL; +} + +int extcon_update(const char *value) +{ + char *s, *p; + char name[NAME_MAX]; + struct extcon_ops *dev; + + if (!value) + return -EINVAL; + + s = (char*)value; + while (s && *s != '\0') { + p = strchr(s, '='); + if (!p) + break; + memset(name, 0, sizeof(name)); + memcpy(name, s, p-s); + dev = find_extcon(name); + if (dev) + extcon_changed(dev, atoi(p+1)); + s = strchr(p, '\n'); + if (!s) + break; + s += 1; + } + + return 0; +} + +static int extcon_load_uevent(struct parse_result *result, void *user_data) +{ + struct extcon_ops *dev; + int val; + + if (!result) + return 0; + + if (!result->name || !result->value) + return 0; + + val = atoi(result->value); + dev = find_extcon(result->name); + if (dev) + extcon_changed(dev, val); + + return 0; +} + +static int get_extcon_uevent_state(char *state, unsigned int len) +{ + DIR *dir; + struct dirent *entry; + char node[BUF_MAX]; + int ret; + + if (!state) + return -EINVAL; + + dir = opendir(EXTCON_PATH); + if (!dir) { + ret = -errno; + _E("Cannot open dir (%s, errno:%d)", EXTCON_PATH, ret); + return ret; + } + + ret = -ENOENT; + while ((entry = readdir(dir))) { + if (entry->d_name[0] == '.') + continue; + snprintf(node, sizeof(node), "%s/%s/state", + EXTCON_PATH, entry->d_name); + _I("checking node (%s)", node); + if (access(node, F_OK) != 0) + continue; + + ret = 0; + break; + } + + if (dir) + closedir(dir); + + if (ret == 0) { + strncpy(state, node, len - 1); + state[len -1] = '\0'; + } + + return ret; +} + +static void extcon_init(void *data) +{ + int ret; + char state[256]; + dd_list *l; + struct extcon_ops *dev; + + if (!extcon_list) + return; + + DD_LIST_FOREACH(extcon_list, l, dev) { + _I("[extcon] init (%s)", dev->name); + if (dev->init) + dev->init(data); + } + + /* load extcon uevent */ + ret = get_extcon_uevent_state(state, sizeof(state)); + if (ret == 0) { + ret = config_parse(state, extcon_load_uevent, NULL); + if (ret < 0) + _E("Failed to load %s file : %d", EXTCON_PATH, ret); + } else { + _E("Failed to get extcon uevent state node"); + } +} + +static void extcon_exit(void *data) +{ + dd_list *l; + struct extcon_ops *dev; + + DD_LIST_FOREACH(extcon_list, l, dev) { + _I("[extcon] deinit (%s)", dev->name); + if (dev->exit) + dev->exit(data); + } +} + +const struct device_ops extcon_device_ops = { + .name = "extcon", + .init = extcon_init, + .exit = extcon_exit, +}; + +DEVICE_OPS_REGISTER(&extcon_device_ops) diff --git a/src/extcon/extcon.h b/src/extcon/extcon.h new file mode 100755 index 0000000..9b2e699 --- /dev/null +++ b/src/extcon/extcon.h @@ -0,0 +1,46 @@ +/* + * deviced + * + * Copyright (c) 2015 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 __EXTCON_H__ +#define __EXTCON_H__ + +struct extcon_ops { + const char *name; + int status; + enum device_notifier_type noti; + void (*init)(void *data); + void (*exit)(void *data); +}; + +#define EXTCON_OPS_REGISTER(dev) \ +static void __CONSTRUCTOR__ extcon_init(void) \ +{ \ + add_extcon(dev); \ +} \ +static void __DESTRUCTOR__ extcon_exit(void) \ +{ \ + remove_extcon(dev); \ +} + +void add_extcon(const struct extcon_ops *dev); +void remove_extcon(const struct extcon_ops *dev); + +int extcon_update(const char *value); + +#endif /* __EXTCON_H__ */ -- 2.7.4 From bc0f549edbfbcf70a098f367d8998249b0bf09c6 Mon Sep 17 00:00:00 2001 From: taeyoung Date: Wed, 4 Feb 2015 20:15:42 +0900 Subject: [PATCH 04/16] notifier: change the function name for unregistering device notification - There is a mismatching for the function name between the prototype and its implementation. Thus the name is changed correctly. unregister_notifier_del() -> unregister_notifier() Change-Id: I5387aae2837d457d0ad610e767e0979ea38a67e5 Signed-off-by: taeyoung --- src/core/device-notifier.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/device-notifier.h b/src/core/device-notifier.h index 9e32fce..597217a 100644 --- a/src/core/device-notifier.h +++ b/src/core/device-notifier.h @@ -41,7 +41,7 @@ enum device_notifier_type { * This is for internal callback method. */ int register_notifier(enum device_notifier_type status, int (*func)(void *data)); -int unregister_notifier_del(enum device_notifier_type status, int (*func)(void *data)); +int unregister_notifier(enum device_notifier_type status, int (*func)(void *data)); void device_notify(enum device_notifier_type status, void *value); #endif /* __DEVICE_NOTIFIER_H__ */ -- 2.7.4 From 9e396ae38dea5a5c8b19db66785b79a6a0c1d195 Mon Sep 17 00:00:00 2001 From: taeyoung Date: Wed, 4 Feb 2015 22:18:15 +0900 Subject: [PATCH 05/16] extcon: add function to get current device status - Each extcon device can have scenario in which they should get the current status of itself. Thus the getter function for current device status is added. Change-Id: I4898d5d9968ff95ee27d7c871cf65b13ca7fc559 Signed-off-by: taeyoung --- src/extcon/extcon.c | 14 ++++++++++++++ src/extcon/extcon.h | 1 + 2 files changed, 15 insertions(+) diff --git a/src/extcon/extcon.c b/src/extcon/extcon.c index 629c459..842c3c5 100755 --- a/src/extcon/extcon.c +++ b/src/extcon/extcon.c @@ -75,6 +75,20 @@ static struct extcon_ops *find_extcon(const char *name) return NULL; } +int extcon_get_status(const char *name) +{ + struct extcon_ops *dev; + + if (!name) + return -EINVAL; + + dev = find_extcon(name); + if (!dev) + return -ENOENT; + + return dev->status; +} + int extcon_update(const char *value) { char *s, *p; diff --git a/src/extcon/extcon.h b/src/extcon/extcon.h index 9b2e699..f0b6ea1 100755 --- a/src/extcon/extcon.h +++ b/src/extcon/extcon.h @@ -42,5 +42,6 @@ void add_extcon(const struct extcon_ops *dev); void remove_extcon(const struct extcon_ops *dev); int extcon_update(const char *value); +int extcon_get_status(const char *name); #endif /* __EXTCON_H__ */ -- 2.7.4 From 357bd782f458f4ed8e22c8a1377db6672f588bf9 Mon Sep 17 00:00:00 2001 From: taeyoung Date: Mon, 9 Feb 2015 15:59:19 +0900 Subject: [PATCH 06/16] extcon: change extcon object type from 'const' to normal - Extcon object contains status element and it can be updated by extcon status. Thus 'const' is removed for the extcon object Change-Id: I7a26af7ac8c878a145a4a68d77e9af2cc72607b1 Signed-off-by: taeyoung --- src/extcon/extcon.c | 4 ++-- src/extcon/extcon.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/extcon/extcon.c b/src/extcon/extcon.c index 842c3c5..cd2cc5f 100755 --- a/src/extcon/extcon.c +++ b/src/extcon/extcon.c @@ -33,12 +33,12 @@ static dd_list *extcon_list; -void add_extcon(const struct extcon_ops *dev) +void add_extcon(struct extcon_ops *dev) { DD_LIST_APPEND(extcon_list, dev); } -void remove_extcon(const struct extcon_ops *dev) +void remove_extcon(struct extcon_ops *dev) { DD_LIST_REMOVE(extcon_list, dev); } diff --git a/src/extcon/extcon.h b/src/extcon/extcon.h index f0b6ea1..28fc8a1 100755 --- a/src/extcon/extcon.h +++ b/src/extcon/extcon.h @@ -38,8 +38,8 @@ static void __DESTRUCTOR__ extcon_exit(void) \ remove_extcon(dev); \ } -void add_extcon(const struct extcon_ops *dev); -void remove_extcon(const struct extcon_ops *dev); +void add_extcon(struct extcon_ops *dev); +void remove_extcon(struct extcon_ops *dev); int extcon_update(const char *value); int extcon_get_status(const char *name); -- 2.7.4 From 578c6966ecec6a76e8d71eed5534e07b5e7ef176 Mon Sep 17 00:00:00 2001 From: Jiyoung Yun Date: Thu, 12 Feb 2015 19:20:27 +0900 Subject: [PATCH 07/16] deviced: Add extcon probe function If there is no extcon class, deviced does not load extcon module. Change-Id: I07f7986e4f4d0c27d4020683ea8a3039fbe9d805 Signed-off-by: Jiyoung Yun --- src/extcon/extcon.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/extcon/extcon.c b/src/extcon/extcon.c index cd2cc5f..c4046f0 100755 --- a/src/extcon/extcon.c +++ b/src/extcon/extcon.c @@ -178,6 +178,21 @@ static int get_extcon_uevent_state(char *state, unsigned int len) return ret; } +static int extcon_probe(void *data) +{ + /** + * find extcon class. + * if there is no extcon class, + * deviced does not control extcon devices. + */ + if (access(EXTCON_PATH, R_OK) != 0) { + _E("there is no extcon class"); + return -ENODEV; + } + + return 0; +} + static void extcon_init(void *data) { int ret; @@ -218,9 +233,10 @@ static void extcon_exit(void *data) } const struct device_ops extcon_device_ops = { - .name = "extcon", - .init = extcon_init, - .exit = extcon_exit, + .name = "extcon", + .probe = extcon_probe, + .init = extcon_init, + .exit = extcon_exit, }; DEVICE_OPS_REGISTER(&extcon_device_ops) -- 2.7.4 From e7eb568dabd1d8d1c9ec77c774e5e43682c0b93c Mon Sep 17 00:00:00 2001 From: Jiyoung Yun Date: Wed, 11 Feb 2015 17:27:29 +0900 Subject: [PATCH 08/16] deviced: Change the way to register edbus object and interface Each module can register their method using the same interface. In that case, edbus will return error because object is already registered. And there are no ways to get an edbus interface using another information. So I change implementation to register by object and interface string. Edbus logic will maintain each edbus interface in edbus_object_list. Change-Id: I175973b1a7d59088cb93545ed2701b30e3d0fadc Signed-off-by: Jiyoung Yun --- src/battery/power-supply.c | 8 ++---- src/core/edbus-handler.c | 69 ++++++++++++++++++++++++++++++++++++++++------ src/core/edbus-handler.h | 10 ++----- 3 files changed, 65 insertions(+), 22 deletions(-) diff --git a/src/battery/power-supply.c b/src/battery/power-supply.c index 2a78d08..eb45968 100644 --- a/src/battery/power-supply.c +++ b/src/battery/power-supply.c @@ -953,16 +953,12 @@ static const struct edbus_method edbus_methods[] = { { POWER_SUBSYSTEM, "sisssss", "i", dbus_battery_handler }, }; -static struct edbus_object battery_obj = { - .path = DEVICED_PATH_BATTERY, - .interface = DEVICED_INTERFACE_BATTERY, -}; - int power_supply_init(void *data) { int ret; - ret = register_edbus_interface_with_method(&battery_obj, + ret = register_edbus_interface_and_method(DEVICED_PATH_BATTERY, + DEVICED_INTERFACE_BATTERY, edbus_methods, ARRAY_SIZE(edbus_methods)); if (ret < 0) _E("fail to init edbus interface and method(%d)", ret); diff --git a/src/core/edbus-handler.c b/src/core/edbus-handler.c index 572dd42..3c50ba3 100644 --- a/src/core/edbus-handler.c +++ b/src/core/edbus-handler.c @@ -35,6 +35,13 @@ #define DBUS_REPLY_TIMEOUT (-1) #define RETRY_MAX 5 +struct edbus_object { + const char *path; + const char *interface; + E_DBus_Object *obj; + E_DBus_Interface *iface; +}; + struct edbus_list{ char *signal_name; E_DBus_Signal_Handler *handler; @@ -60,6 +67,7 @@ static struct edbus_object edbus_objects[] = { /* Add new object & interface here*/ }; +static dd_list *edbus_object_list; static dd_list *edbus_owner_list; static dd_list *edbus_handler_list; static dd_list *edbus_watch_list; @@ -475,31 +483,75 @@ static int register_method(E_DBus_Interface *iface, return 0; } -int register_edbus_interface_with_method(struct edbus_object *object, +int register_edbus_interface_and_method(const char *path, + const char *interface, const struct edbus_method *edbus_methods, int size) { + struct edbus_object *obj; + dd_list *elem; int ret; - if (!object || !edbus_methods || size < 1) { + if (!path || !interface || !edbus_methods || size < 1) { _E("invalid parameter"); return -EINVAL; } - ret = register_edbus_interface(object); - if (ret < 0) { - _E("fail to register %s interface(%d)", object->path, ret); - return ret; + /* find matched obj */ + DD_LIST_FOREACH(edbus_object_list, elem, obj) { + if (strncmp(obj->path, path, strlen(obj->path)) == 0 && + strncmp(obj->interface, interface, strlen(obj->interface)) == 0) { + _I("found matched item : obj(%p)", obj); + break; + } } - ret = register_method(object->iface, edbus_methods, size); + /* if there is no matched obj */ + if (!obj) { + obj = malloc(sizeof(struct edbus_object)); + if (!obj) { + _E("fail to allocate %s interface(%d)", path, ret); + return -ENOMEM; + } + + obj->path = strdup(path); + obj->interface = strdup(interface); + + ret = register_edbus_interface(obj); + if (ret < 0) { + _E("fail to register %s interface(%d)", obj->path, ret); + free(obj->path); + free(obj->interface); + free(obj); + return ret; + } + + DD_LIST_APPEND(edbus_object_list, obj); + } + + ret = register_method(obj->iface, edbus_methods, size); if (ret < 0) { - _E("fail to register %s method(%d)", object->path, ret); + _E("fail to register %s method(%d)", obj->path, ret); return ret; } return 0; } +int unregister_edbus_interface_all(void) +{ + struct edbus_object *obj; + dd_list *elem, *n; + + DD_LIST_FOREACH_SAFE(edbus_object_list, elem, n, obj) { + DD_LIST_REMOVE(edbus_object_list, obj); + free(obj->path); + free(obj->interface); + free(obj); + } + + return 0; +} + int register_edbus_method(const char *path, const struct edbus_method *edbus_methods, int size) { E_DBus_Interface *iface; @@ -709,6 +761,7 @@ void edbus_exit(void *data) { unregister_edbus_signal_handle(); unregister_edbus_watch_all(); + unregister_edbus_interface_all(); e_dbus_connection_close(edbus_conn); e_dbus_shutdown(); } diff --git a/src/core/edbus-handler.h b/src/core/edbus-handler.h index fa84818..cd2d266 100644 --- a/src/core/edbus-handler.h +++ b/src/core/edbus-handler.h @@ -23,13 +23,6 @@ #include #include "shared/dbus.h" -struct edbus_object { - const char *path; - const char *interface; - E_DBus_Object *obj; - E_DBus_Interface *iface; -}; - struct edbus_method { const char *member; const char *signature; @@ -50,7 +43,8 @@ struct watch { int (*func)(char *name, enum watch_id id); }; -int register_edbus_interface_with_method(struct edbus_object *object, +int register_edbus_interface_and_method(const char *path, + const char *interface, const struct edbus_method *edbus_methods, int size); int register_edbus_method(const char *path, const struct edbus_method *edbus_methods, int size); int register_edbus_signal_handler(const char *path, const char *interface, -- 2.7.4 From 9603477d906917419b0402b7498011659526f6af Mon Sep 17 00:00:00 2001 From: taeyoung Date: Wed, 4 Feb 2015 22:27:18 +0900 Subject: [PATCH 09/16] usb: add usb handler - Usb connection status is delivered to the handler by extcon module Change-Id: Ieec715641fa758693a5614203f865adb9eb17732 Signed-off-by: taeyoung --- CMakeLists.txt | 4 +++ src/core/device-notifier.h | 1 + src/usb/usb.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 94 insertions(+) create mode 100644 src/usb/usb.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 88229eb..9ff2c69 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,6 +41,10 @@ SET(SRCS src/time/time-handler.c ) +SET(SRCS ${SRCS} + src/usb/usb.c +) + IF(TIZEN_BUZZER) SET(SRCS ${SRCS} src/gpio/buzzer.c) diff --git a/src/core/device-notifier.h b/src/core/device-notifier.h index 597217a..aba3e13 100644 --- a/src/core/device-notifier.h +++ b/src/core/device-notifier.h @@ -26,6 +26,7 @@ enum device_notifier_type { DEVICE_NOTIFIER_LCD, DEVICE_NOTIFIER_MMC, DEVICE_NOTIFIER_TA, + DEVICE_NOTIFIER_USB, DEVICE_NOTIFIER_LOWBAT, DEVICE_NOTIFIER_TOUCH_HARDKEY, DEVICE_NOTIFIER_INPUT_ADD, diff --git a/src/usb/usb.c b/src/usb/usb.c new file mode 100644 index 0000000..3d2830c --- /dev/null +++ b/src/usb/usb.c @@ -0,0 +1,89 @@ +/* + * deviced + * + * Copyright (c) 2015 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 "core/log.h" +#include "core/common.h" +#include "core/device-notifier.h" +#include "extcon/extcon.h" + +enum usb_state { + USB_DISCONNECTED, + USB_CONNECTED, +}; + +struct extcon_ops extcon_usb_ops; + +static int usb_state_changed(void *data) +{ + static int state = USB_DISCONNECTED; + int input; + + if (!data) + return -EINVAL; + + input = *(int *)data; + + _I("USB state is changed from (%d) to (%d)", state, input); + + if (state == input) + return 0; + + switch (input) { + case USB_CONNECTED: + _I("USB cable is connected"); + break; + case USB_DISCONNECTED: + _I("USB cable is disconnected"); + break; + default: + _E("Invalid USB state(%d)", state); + return -EINVAL; + } + + state = input; + + return 0; +} + +static void usb_init(void *data) +{ + int ret, status; + + register_notifier(DEVICE_NOTIFIER_USB, usb_state_changed); + + ret = usb_state_changed(&(extcon_usb_ops.status)); + if (ret < 0) + _E("Failed to update usb status(%d)", ret); +} + +static void usb_exit(void *data) +{ + unregister_notifier(DEVICE_NOTIFIER_USB, usb_state_changed); +} + +struct extcon_ops extcon_usb_ops = { + .name = "USB", + .noti = DEVICE_NOTIFIER_USB, + .init = usb_init, + .exit = usb_exit, +}; + +EXTCON_OPS_REGISTER(&extcon_usb_ops) -- 2.7.4 From 54e4cc087ea8ce909f9b0179455b4e6d27ea3a49 Mon Sep 17 00:00:00 2001 From: taeyoung Date: Tue, 10 Feb 2015 16:54:30 +0900 Subject: [PATCH 10/16] usb: add plugin interfaces for usb configuration - USB configuration manner can be changed according to the Kernel or vendors. Thus USB configuration setting codes should be implemented by plugin structure. - This modification contains basic structure for the USB configuration plugin. Change-Id: I4afb1033fb59ba132182ae16ffef9fbb34192f13 Signed-off-by: taeyoung --- src/usb/usb.c | 138 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--- src/usb/usb.h | 50 +++++++++++++++++++++ 2 files changed, 183 insertions(+), 5 deletions(-) create mode 100644 src/usb/usb.h diff --git a/src/usb/usb.c b/src/usb/usb.c index 3d2830c..02fd197 100644 --- a/src/usb/usb.c +++ b/src/usb/usb.c @@ -20,21 +20,133 @@ #include #include "core/log.h" +#include "core/list.h" #include "core/common.h" #include "core/device-notifier.h" #include "extcon/extcon.h" +#include "usb.h" enum usb_state { USB_DISCONNECTED, USB_CONNECTED, }; +static dd_list *config_list; struct extcon_ops extcon_usb_ops; +static const struct usb_config_plugin_ops *config_plugin; + +void add_usb_config(const struct usb_config_ops *ops) +{ + DD_LIST_APPEND(config_list, ops); +} + +void remove_usb_config(const struct usb_config_ops *ops) +{ + DD_LIST_REMOVE(config_list, ops); +} + +static int usb_config_module_load(void) +{ + dd_list *l; + struct usb_config_ops *ops; + + DD_LIST_FOREACH(config_list, l, ops) { + if (ops->is_valid && ops->is_valid()) { + if (ops->load) + config_plugin = ops->load(); + return 0; + } + } + return -ENOENT; +} + +static void usb_config_module_unload(void) +{ + dd_list *l; + struct usb_config_ops *ops; + + config_plugin = NULL; + + DD_LIST_FOREACH(config_list, l, ops) { + if (ops->is_valid && ops->is_valid()) { + if (ops->release) + ops->release(); + } + } +} + +static int usb_config_init(void) +{ + if (!config_plugin) { + _E("There is no usb config plugin"); + return -ENOENT; + } + + if (config_plugin->init == NULL) { + _E("There is no usb config init function"); + return -ENOENT; + } + + /* TODO: + * parameter "DEFAULT" can be changed */ + return config_plugin->init("DEFAULT"); +} + +static void usb_config_deinit(void) +{ + if (!config_plugin) { + _E("There is no usb config plugin"); + return; + } + + if (config_plugin->deinit == NULL) { + _E("There is no usb config deinit function"); + return; + } + + /* TODO: + * parameter "DEFAULT" can be changed */ + config_plugin->deinit("DEFAULT"); +} + +static int usb_config_enable(void) +{ + if (!config_plugin) { + _E("There is no usb config plugin"); + return -ENOENT; + } + + if (config_plugin->enable == NULL) { + _E("There is no usb config enable function"); + return -ENOENT; + } + + /* TODO: + * parameter "DEFAULT" can be changed */ + return config_plugin->enable("DEFAULT"); +} + +static int usb_config_disable(void) +{ + if (!config_plugin) { + _E("There is no usb config plugin"); + return -ENOENT; + } + + if (config_plugin->disable == NULL) { + _E("There is no usb config disable function"); + return -ENOENT; + } + + /* TODO: + * parameter "DEFAULT" can be changed */ + return config_plugin->disable("DEFAULT"); +} static int usb_state_changed(void *data) { static int state = USB_DISCONNECTED; - int input; + int input, ret; if (!data) return -EINVAL; @@ -49,26 +161,40 @@ static int usb_state_changed(void *data) switch (input) { case USB_CONNECTED: _I("USB cable is connected"); + ret = usb_config_enable(); break; case USB_DISCONNECTED: _I("USB cable is disconnected"); + ret = usb_config_disable(); break; default: _E("Invalid USB state(%d)", state); return -EINVAL; } + if (ret < 0) + _E("Failed to operate usb connection(%d)", ret); + else + state = input; - state = input; - - return 0; + return ret; } static void usb_init(void *data) { - int ret, status; + int ret; register_notifier(DEVICE_NOTIFIER_USB, usb_state_changed); + ret = usb_config_module_load(); + if (ret < 0) { + _E("Failed to get config module (%d)", ret); + return; + } + + ret = usb_config_init(); + if (ret < 0) + _E("Failed to initialize usb configuation"); + ret = usb_state_changed(&(extcon_usb_ops.status)); if (ret < 0) _E("Failed to update usb status(%d)", ret); @@ -77,6 +203,8 @@ static void usb_init(void *data) static void usb_exit(void *data) { unregister_notifier(DEVICE_NOTIFIER_USB, usb_state_changed); + usb_config_deinit(); + usb_config_module_unload(); } struct extcon_ops extcon_usb_ops = { diff --git a/src/usb/usb.h b/src/usb/usb.h new file mode 100644 index 0000000..5c3276d --- /dev/null +++ b/src/usb/usb.h @@ -0,0 +1,50 @@ +/* + * deviced + * + * Copyright (c) 2015 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 __USB_CLIENT_H__ +#define __USB_CLIENT_H__ + +#define USB_CONFIG_OPS_REGISTER(dev) \ +static void __CONSTRUCTOR__ usb_config_init(void) \ +{ \ + add_usb_config(dev); \ +} \ +static void __DESTRUCTOR__ usb_config_exit(void) \ +{ \ + remove_usb_config(dev); \ +} + +struct usb_config_ops { + bool (*is_valid)(void); + const struct usb_config_plugin_ops *(*load)(void); + void (*release)(void); +}; + +/* TODO + * move it to proper location */ +struct usb_config_plugin_ops { + int (*init)(char *name); + void (*deinit)(char *name); + int (*enable)(char *name); + int (*disable)(char *name); +}; + +void add_usb_config(const struct usb_config_ops *ops); +void remove_usb_config(const struct usb_config_ops *ops); + +#endif /* __USB_CLIENT_H__ */ -- 2.7.4 From 33404cf65e730398c4bb97e32d26452a6e895d0a Mon Sep 17 00:00:00 2001 From: Jiyoung Yun Date: Fri, 13 Feb 2015 13:59:06 +0900 Subject: [PATCH 11/16] extcon: Register extcon uevent inside extcon module If there is no extcon module, deviced does not need to register extcon uevent. So the code is moved into extcon module. Change-Id: Ib36295a1f54c3528bb0c3473201b1f1d36671e9c Signed-off-by: Jiyoung Yun --- src/core/device-change-handler.c | 10 ---------- src/extcon/extcon.c | 38 ++++++++++++++++++++++++++++++++++++-- src/extcon/extcon.h | 1 - 3 files changed, 36 insertions(+), 13 deletions(-) diff --git a/src/core/device-change-handler.c b/src/core/device-change-handler.c index 74e9391..794a9f9 100644 --- a/src/core/device-change-handler.c +++ b/src/core/device-change-handler.c @@ -154,7 +154,6 @@ enum udev_subsystem_type { UDEV_INPUT, UDEV_PLATFORM, UDEV_SWITCH, - UDEV_EXTCON, }; static const struct udev_subsystem { @@ -165,7 +164,6 @@ static const struct udev_subsystem { { UDEV_INPUT, INPUT_SUBSYSTEM, NULL }, { UDEV_PLATFORM, PLATFORM_SUBSYSTEM, NULL }, { UDEV_SWITCH, SWITCH_SUBSYSTEM, NULL }, - { UDEV_EXTCON, EXTCON_SUBSYSTEM, NULL }, }; static dd_list *udev_event_list; @@ -789,14 +787,6 @@ static Eina_Bool uevent_kernel_control_cb(void *data, Ecore_Fd_Handler *fd_handl break; changed_device(env_value, NULL); break; - case UDEV_EXTCON: - env_value = udev_device_get_property_value(dev, "STATE"); - if (!env_value) - break; - ret = extcon_update(env_value); - if (ret < 0) - _E("Failed to update extcon status"); - break; } out: diff --git a/src/extcon/extcon.c b/src/extcon/extcon.c index c4046f0..5f87442 100755 --- a/src/extcon/extcon.c +++ b/src/extcon/extcon.c @@ -25,9 +25,11 @@ #include "core/devices.h" #include "core/config-parser.h" #include "core/device-notifier.h" +#include "core/udev.h" #include "extcon.h" -#define EXTCON_PATH "/sys/class/extcon" +#define EXTCON_PATH "/sys/class/extcon" +#define STATE_NAME "STATE" #define BUF_MAX 256 @@ -89,7 +91,7 @@ int extcon_get_status(const char *name) return dev->status; } -int extcon_update(const char *value) +static int extcon_update(const char *value) { char *s, *p; char name[NAME_MAX]; @@ -178,6 +180,22 @@ static int get_extcon_uevent_state(char *state, unsigned int len) return ret; } +static void uevent_extcon_handler(struct udev_device *dev) +{ + const char *env_value; + int ret; + + env_value = udev_device_get_property_value(dev, STATE_NAME); + if (!env_value) + return; + + ret = extcon_update(env_value); + if (ret < 0) + _E("fail to update extcon status : %d", ret); + + return; +} + static int extcon_probe(void *data) { /** @@ -193,6 +211,11 @@ static int extcon_probe(void *data) return 0; } +static struct uevent_handler uh = { + .subsystem = EXTCON_SUBSYSTEM, + .uevent_func = uevent_extcon_handler, +}; + static void extcon_init(void *data) { int ret; @@ -209,6 +232,11 @@ static void extcon_init(void *data) dev->init(data); } + /* register extcon uevent */ + ret = register_kernel_uevent_control(&uh); + if (ret < 0) + _E("fail to register extcon uevent : %d", ret); + /* load extcon uevent */ ret = get_extcon_uevent_state(state, sizeof(state)); if (ret == 0) { @@ -224,6 +252,12 @@ static void extcon_exit(void *data) { dd_list *l; struct extcon_ops *dev; + int ret; + + /* unreigster extcon uevent */ + ret = unregister_kernel_uevent_control(&uh); + if (ret < 0) + _E("fail to unregister extcon uevent : %d", ret); DD_LIST_FOREACH(extcon_list, l, dev) { _I("[extcon] deinit (%s)", dev->name); diff --git a/src/extcon/extcon.h b/src/extcon/extcon.h index 28fc8a1..989da1a 100755 --- a/src/extcon/extcon.h +++ b/src/extcon/extcon.h @@ -41,7 +41,6 @@ static void __DESTRUCTOR__ extcon_exit(void) \ void add_extcon(struct extcon_ops *dev); void remove_extcon(struct extcon_ops *dev); -int extcon_update(const char *value); int extcon_get_status(const char *name); #endif /* __EXTCON_H__ */ -- 2.7.4 From ded250a3e17978bc77349490dfbc89757cb563c3 Mon Sep 17 00:00:00 2001 From: Jiyoung Yun Date: Fri, 13 Feb 2015 14:04:46 +0900 Subject: [PATCH 12/16] extcon: Register GetStatus dbus method GetStatus method returns the current device status. The first string argument should be the same with EXTCON_XXX name. Change-Id: Ifaf2baa26e1189bc6d91e4be6e522df7631ce53f Signed-off-by: Jiyoung Yun --- src/core/edbus-handler.c | 1 - src/extcon/extcon.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++ src/extcon/extcon.h | 12 ++++++++++++ src/usb/usb.c | 2 +- 4 files changed, 62 insertions(+), 2 deletions(-) diff --git a/src/core/edbus-handler.c b/src/core/edbus-handler.c index 3c50ba3..6d24931 100644 --- a/src/core/edbus-handler.c +++ b/src/core/edbus-handler.c @@ -61,7 +61,6 @@ static struct edbus_object edbus_objects[] = { { DEVICED_PATH_SYSNOTI, DEVICED_INTERFACE_SYSNOTI, NULL, NULL }, { DEVICED_PATH_USB , DEVICED_INTERFACE_USB , NULL, NULL }, { DEVICED_PATH_USBHOST, DEVICED_INTERFACE_USBHOST, NULL, NULL }, - { DEVICED_PATH_EXTCON , DEVICED_INTERFACE_EXTCON , NULL, NULL }, { DEVICED_PATH_GPIO, DEVICED_INTERFACE_GPIO, NULL, NULL}, { DEVICED_PATH_HDMICEC, DEVICED_INTERFACE_HDMICEC, NULL, NULL}, /* Add new object & interface here*/ diff --git a/src/extcon/extcon.c b/src/extcon/extcon.c index 5f87442..54c4b33 100755 --- a/src/extcon/extcon.c +++ b/src/extcon/extcon.c @@ -25,6 +25,7 @@ #include "core/devices.h" #include "core/config-parser.h" #include "core/device-notifier.h" +#include "core/edbus-handler.h" #include "core/udev.h" #include "extcon.h" @@ -196,6 +197,44 @@ static void uevent_extcon_handler(struct udev_device *dev) return; } +static DBusMessage *dbus_get_extcon_status(E_DBus_Object *obj, + DBusMessage *msg) +{ + DBusError err; + DBusMessageIter iter; + DBusMessage *reply; + struct extcon_ops *dev; + char *str; + int ret; + + dbus_error_init(&err); + + if (!dbus_message_get_args(msg, &err, + DBUS_TYPE_STRING, &str, + DBUS_TYPE_INVALID)) { + _E("fail to get message : %s - %s", err.name, err.message); + dbus_error_free(&err); + ret = -EINVAL; + goto error; + } + + dev = find_extcon(str); + if (!dev) { + _E("fail to matched extcon device : %s", str); + ret = -ENOENT; + goto error; + } + + ret = dev->status; + _D("Extcon device : %s, status : %d", dev->name, dev->status); + +error: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + static int extcon_probe(void *data) { /** @@ -216,6 +255,10 @@ static struct uevent_handler uh = { .uevent_func = uevent_extcon_handler, }; +static const struct edbus_method edbus_methods[] = { + { "GetStatus", "s", "i", dbus_get_extcon_status }, +}; + static void extcon_init(void *data) { int ret; @@ -246,6 +289,12 @@ static void extcon_init(void *data) } else { _E("Failed to get extcon uevent state node"); } + + ret = register_edbus_interface_and_method(DEVICED_PATH_EXTCON, + DEVICED_INTERFACE_EXTCON, + edbus_methods, ARRAY_SIZE(edbus_methods)); + if (ret < 0) + _E("fail to init edbus interface and method(%d)", ret); } static void extcon_exit(void *data) diff --git a/src/extcon/extcon.h b/src/extcon/extcon.h index 989da1a..4fd8d6d 100755 --- a/src/extcon/extcon.h +++ b/src/extcon/extcon.h @@ -20,6 +20,18 @@ #ifndef __EXTCON_H__ #define __EXTCON_H__ +/** + * Extcon cable name is shared with kernel extcon class. + * So do not change below strings. + */ +#define EXTCON_CABLE_USB "USB" +#define EXTCON_CABLE_USB_HOST "USB-Host" +#define EXTCON_CABLE_TA "TA" +#define EXTCON_CABLE_HDMI "HDMI" +#define EXTCON_CABLE_DOCK "Dock" +#define EXTCON_CABLE_MIC_IN "Microphone" +#define EXTCON_CABLE_HEADPHONE_OUT "Headphone" + struct extcon_ops { const char *name; int status; diff --git a/src/usb/usb.c b/src/usb/usb.c index 02fd197..7595da7 100644 --- a/src/usb/usb.c +++ b/src/usb/usb.c @@ -208,7 +208,7 @@ static void usb_exit(void *data) } struct extcon_ops extcon_usb_ops = { - .name = "USB", + .name = EXTCON_CABLE_USB, .noti = DEVICE_NOTIFIER_USB, .init = usb_init, .exit = usb_exit, -- 2.7.4 From 0223019c976544d3b04c0938b2156f41837a39cf Mon Sep 17 00:00:00 2001 From: Jiyoung Yun Date: Fri, 13 Feb 2015 18:18:21 +0900 Subject: [PATCH 13/16] extcon: Replace device-notifier with update callback function Device-notifier makes to be tight code among each other modules. And update callback is more useful without any effort to register or unregister device-notifier. Change-Id: I6a9ba2eafb26973bf15f18b2dc74a0e1bd970e43 Signed-off-by: Jiyoung Yun --- src/core/device-notifier.h | 1 - src/extcon/extcon.c | 3 ++- src/extcon/extcon.h | 2 +- src/usb/usb.c | 26 +++++++++----------------- 4 files changed, 12 insertions(+), 20 deletions(-) diff --git a/src/core/device-notifier.h b/src/core/device-notifier.h index aba3e13..597217a 100644 --- a/src/core/device-notifier.h +++ b/src/core/device-notifier.h @@ -26,7 +26,6 @@ enum device_notifier_type { DEVICE_NOTIFIER_LCD, DEVICE_NOTIFIER_MMC, DEVICE_NOTIFIER_TA, - DEVICE_NOTIFIER_USB, DEVICE_NOTIFIER_LOWBAT, DEVICE_NOTIFIER_TOUCH_HARDKEY, DEVICE_NOTIFIER_INPUT_ADD, diff --git a/src/extcon/extcon.c b/src/extcon/extcon.c index 54c4b33..37635f5 100755 --- a/src/extcon/extcon.c +++ b/src/extcon/extcon.c @@ -57,7 +57,8 @@ static int extcon_changed(struct extcon_ops *dev, int status) _I("Changed %s device : %d -> %d", dev->name, dev->status, status); dev->status = status; - device_notify(dev->noti, &status); + if (dev->update) + dev->update(status); return 0; } diff --git a/src/extcon/extcon.h b/src/extcon/extcon.h index 4fd8d6d..c41857a 100755 --- a/src/extcon/extcon.h +++ b/src/extcon/extcon.h @@ -35,9 +35,9 @@ struct extcon_ops { const char *name; int status; - enum device_notifier_type noti; void (*init)(void *data); void (*exit)(void *data); + int (*update)(int status); }; #define EXTCON_OPS_REGISTER(dev) \ diff --git a/src/usb/usb.c b/src/usb/usb.c index 7595da7..4cfa55d 100644 --- a/src/usb/usb.c +++ b/src/usb/usb.c @@ -143,22 +143,17 @@ static int usb_config_disable(void) return config_plugin->disable("DEFAULT"); } -static int usb_state_changed(void *data) +static int usb_state_changed(int status) { - static int state = USB_DISCONNECTED; - int input, ret; - - if (!data) - return -EINVAL; - - input = *(int *)data; + static int old = USB_DISCONNECTED; + int ret; - _I("USB state is changed from (%d) to (%d)", state, input); + _I("USB state is changed from (%d) to (%d)", old, status); - if (state == input) + if (old == status) return 0; - switch (input) { + switch (status) { case USB_CONNECTED: _I("USB cable is connected"); ret = usb_config_enable(); @@ -168,13 +163,13 @@ static int usb_state_changed(void *data) ret = usb_config_disable(); break; default: - _E("Invalid USB state(%d)", state); + _E("Invalid USB state(%d)", status); return -EINVAL; } if (ret < 0) _E("Failed to operate usb connection(%d)", ret); else - state = input; + old = status; return ret; } @@ -183,8 +178,6 @@ static void usb_init(void *data) { int ret; - register_notifier(DEVICE_NOTIFIER_USB, usb_state_changed); - ret = usb_config_module_load(); if (ret < 0) { _E("Failed to get config module (%d)", ret); @@ -202,16 +195,15 @@ static void usb_init(void *data) static void usb_exit(void *data) { - unregister_notifier(DEVICE_NOTIFIER_USB, usb_state_changed); usb_config_deinit(); usb_config_module_unload(); } struct extcon_ops extcon_usb_ops = { .name = EXTCON_CABLE_USB, - .noti = DEVICE_NOTIFIER_USB, .init = usb_init, .exit = usb_exit, + .update = usb_state_changed, }; EXTCON_OPS_REGISTER(&extcon_usb_ops) -- 2.7.4 From ec7bef629e2ff6811292fdccb887444b8f13d3ce Mon Sep 17 00:00:00 2001 From: taeyoung Date: Tue, 10 Feb 2015 20:13:38 +0900 Subject: [PATCH 14/16] usb: set default usb config to usb sdb - Default usb config is used from Tizen 1.0 to tizen 2.3. USB nodes at sysfs are used to set usb configuration. - Default usb config is not plugin type since it will be used when other plugin does not exist Change-Id: I0f1f3ed1ff128d6cb62c410529c6227981a1f5de Signed-off-by: taeyoung --- CMakeLists.txt | 3 + packaging/deviced.spec | 2 + src/usb/usb-default.c | 273 +++++++++++++++++++++++++++++++++++++++++++++ src/usb/usb-operation.conf | 3 + src/usb/usb-setting.conf | 14 +++ src/usb/usb.c | 16 +-- 6 files changed, 299 insertions(+), 12 deletions(-) create mode 100644 src/usb/usb-default.c create mode 100644 src/usb/usb-operation.conf create mode 100644 src/usb/usb-setting.conf diff --git a/CMakeLists.txt b/CMakeLists.txt index 9ff2c69..fd65784 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,6 +43,7 @@ SET(SRCS SET(SRCS ${SRCS} src/usb/usb.c + src/usb/usb-default.c ) IF(TIZEN_BUZZER) @@ -189,6 +190,8 @@ INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc DESTINATION ${LIB_I INSTALL(PROGRAMS ${CMAKE_CURRENT_SOURCE_DIR}/scripts/deviced-pre.sh DESTINATION bin) INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/scripts/deviced.conf DESTINATION /etc/dbus-1/system.d) INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/scripts/movi_format.sh DESTINATION bin) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/src/usb/usb-setting.conf DESTINATION /etc/deviced) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/src/usb/usb-operation.conf DESTINATION /etc/deviced) IF(TIZEN_SDCARD) INSTALL(PROGRAMS ${CMAKE_CURRENT_SOURCE_DIR}/scripts/mmc-smack-label DESTINATION bin) INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/src/fsck-msdos/LICENSE DESTINATION share/license RENAME fsck_msdosfs) diff --git a/packaging/deviced.spec b/packaging/deviced.spec index fc0397f..d18c5ad 100755 --- a/packaging/deviced.spec +++ b/packaging/deviced.spec @@ -317,6 +317,8 @@ systemctl daemon-reload %{_bindir}/deviced %{_bindir}/devicectl %{_bindir}/movi_format.sh +%{_sysconfdir}/deviced/usb-setting.conf +%{_sysconfdir}/deviced/usb-operation.conf %if %{with sdcard} %{_bindir}/mmc-smack-label %{_bindir}/fsck_msdosfs diff --git a/src/usb/usb-default.c b/src/usb/usb-default.c new file mode 100644 index 0000000..2154641 --- /dev/null +++ b/src/usb/usb-default.c @@ -0,0 +1,273 @@ +/* + * deviced + * + * Copyright (c) 2015 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 "core/log.h" +#include "core/common.h" +#include "core/config-parser.h" +#include "core/launch.h" +#include "usb.h" + +#define USB_SETTING "/etc/deviced/usb-setting.conf" +#define USB_OPERATION "/etc/deviced/usb-operation.conf" + +#define SECTION_BASE "BASE" +#define KEY_ROOTPATH "rootpath" +#define KEY_LOAD "load" +#define KEY_DEFAULT "default" +#define KEY_START "start" +#define KEY_STOP "stop" + +#define CONFIG_ENABLE "1" +#define CONFIG_DISABLE "0" + +#define BUF_MAX 128 + +struct oper_data { + char *type; + char *name; +}; + +static char config_rootpath[BUF_MAX]; +static char config_load[BUF_MAX]; +static char config_default[BUF_MAX]; + +static int write_file(char *path, char *val) +{ + FILE *fp; + int ret; + unsigned int len; + + if (!path || !val) + return -EINVAL; + + fp = fopen(path, "w"); + if (!fp) { + ret = -errno; + _E("Failed to open file (%s, errno:%d)", path, ret); + return ret; + } + + len = strlen(val); + ret = fwrite(val, sizeof(char), len, fp); + fclose(fp); + if (ret < len) { + _E("Failed to write (%s, %s)", path, val); + return -ENOMEM; + } + + return 0; +} + +static int load_setting_config(struct parse_result *result, void *user_data) +{ + char *section = user_data; + char path[BUF_MAX]; + int ret; + + if (!result || !section) + return -EINVAL; + + if (result->section == NULL || result->name == NULL) + return -EINVAL; + + if (strncmp(section, result->section, strlen(section))) + return 0; + + snprintf(path, sizeof(path), "%s/%s", config_rootpath, result->name); + ret = write_file(path, result->value); + if (ret < 0) + _E("Failed to write (%s, %s)", path, result->value); + + return ret; +} + +static int load_base_config(struct parse_result *result, void *user_data) +{ + unsigned int len; + + if (!result) + return -EINVAL; + + if (result->section == NULL || result->name == NULL) + return -EINVAL; + + if (strncmp(result->section, SECTION_BASE, sizeof(SECTION_BASE))) + return 0; + + if (!strncmp(result->name, KEY_ROOTPATH, sizeof(KEY_ROOTPATH))) { + snprintf(config_rootpath, sizeof(config_rootpath), + "%s", result->value); + _I("USB config rootpath(%s)", config_rootpath); + } + + else if (!strncmp(result->name, KEY_LOAD, sizeof(KEY_LOAD))) { + snprintf(config_load, sizeof(config_load), + "%s", result->value); + _I("USB config load(%s)", config_load); + } + + else if (!strncmp(result->name, KEY_DEFAULT, sizeof(KEY_DEFAULT))) { + snprintf(config_default, sizeof(config_default), + "%s", result->value); + _I("USB config default(%s)", config_default); + } + + return 0; +} + +static int load_operation_config(struct parse_result *result, void *user_data) +{ + struct oper_data *data = user_data; + int ret; + + if (!data || !result) + return -EINVAL; + + if (strncmp(result->section, data->type, strlen(result->section))) + return 0; + + if (strncmp(result->name, data->name, strlen(result->name))) + return 0; + + ret = launch_app_cmd(result->value); + + _I("Execute(%s: %d)", result->value, ret); + + return ret; +} + +static int usb_execute_operation(char *type, char *name) +{ + int ret; + struct oper_data data; + + if (!name) + return -EINVAL; + + if (!type) + type = config_default; + + data.name = name; + data.type = type; + + ret = config_parse(USB_OPERATION, + load_operation_config, &data); + if (ret < 0) + _E("Failed to load usb operation (%d)", ret); + + return ret; +} + +static int usb_load_configuration(char *enable) +{ + int ret; + static char buf[BUF_MAX]; + static bool node = false; + + if (!node) { + snprintf(buf, sizeof(buf), "%s/%s", + config_rootpath, config_load); + node = true; + } + + ret = write_file(buf, enable); + if (ret < 0) + _E("Failed to write (%s, %s)", buf, enable); + + return ret; +} + +static int usb_update_configuration(char *name) +{ + if (!name) + name = config_default; + + return config_parse(USB_SETTING, + load_setting_config, name); +} + +static int usb_init(char *name) +{ + int ret; + + ret = config_parse(USB_SETTING, + load_base_config, name); + if (ret < 0) { + _E("Failed to get base information(%d)", ret); + return ret; + } + + ret = usb_update_configuration(name); + if (ret < 0) + _E("Failed to update usb configuration(%d)", ret); + + return ret; +} + +static int usb_enable(char *name) +{ + int ret; + + ret = usb_load_configuration(CONFIG_DISABLE); + if (ret < 0) { + _E("Failed to disable usb config"); + return ret; + } + + ret = usb_load_configuration(CONFIG_ENABLE); + if (ret < 0) { + _E("Failed to enable usb config"); + return ret; + } + + return usb_execute_operation(name, KEY_START); +} + +static int usb_disable(char *name) +{ + return usb_execute_operation(name, KEY_STOP); +} + +static const struct usb_config_plugin_ops default_plugin = { + .init = usb_init, + .enable = usb_enable, + .disable = usb_disable, +}; + +static bool usb_valid(void) +{ + /* TODO + * add checking default config valid condition */ + return true; +} + +static const struct usb_config_plugin_ops *usb_load(void) +{ + return &default_plugin; +} + +static const struct usb_config_ops usb_config_default_ops = { + .is_valid = usb_valid, + .load = usb_load, +}; + +USB_CONFIG_OPS_REGISTER(&usb_config_default_ops) diff --git a/src/usb/usb-operation.conf b/src/usb/usb-operation.conf new file mode 100644 index 0000000..8db280d --- /dev/null +++ b/src/usb/usb-operation.conf @@ -0,0 +1,3 @@ +[SDB] +start=/usr/bin/systemctl start sdbd.service +stop=/usr/bin/systemctl stop sdbd.service diff --git a/src/usb/usb-setting.conf b/src/usb/usb-setting.conf new file mode 100644 index 0000000..755937f --- /dev/null +++ b/src/usb/usb-setting.conf @@ -0,0 +1,14 @@ +[BASE] +rootpath=/sys/class/usb_mode/usb0 +load=enable +default=SDB + +[SDB] +idVendor=04e8 +idProduct=6860 +funcs_fconf=sdb +funcs_sconf=sdb +bDeviceClass=239 +bDeviceSubClass=2 +bDeviceProtocol=1 +iProduct=TIZEN diff --git a/src/usb/usb.c b/src/usb/usb.c index 02fd197..bee3b0c 100644 --- a/src/usb/usb.c +++ b/src/usb/usb.c @@ -87,9 +87,7 @@ static int usb_config_init(void) return -ENOENT; } - /* TODO: - * parameter "DEFAULT" can be changed */ - return config_plugin->init("DEFAULT"); + return config_plugin->init(NULL); } static void usb_config_deinit(void) @@ -104,9 +102,7 @@ static void usb_config_deinit(void) return; } - /* TODO: - * parameter "DEFAULT" can be changed */ - config_plugin->deinit("DEFAULT"); + config_plugin->deinit(NULL); } static int usb_config_enable(void) @@ -121,9 +117,7 @@ static int usb_config_enable(void) return -ENOENT; } - /* TODO: - * parameter "DEFAULT" can be changed */ - return config_plugin->enable("DEFAULT"); + return config_plugin->enable(NULL); } static int usb_config_disable(void) @@ -138,9 +132,7 @@ static int usb_config_disable(void) return -ENOENT; } - /* TODO: - * parameter "DEFAULT" can be changed */ - return config_plugin->disable("DEFAULT"); + return config_plugin->disable(NULL); } static int usb_state_changed(void *data) -- 2.7.4 From ee16b8e1929be48ccb750134ce5426d578674240 Mon Sep 17 00:00:00 2001 From: Jiyoung Yun Date: Tue, 24 Feb 2015 19:08:05 +0900 Subject: [PATCH 15/16] deviced: Set vconf as NOTSUP error in no battery model Runtime-info and Capi-system-device api uses battery vconf to get battery status. So if there is no battery in target, deviced set vconf as -ENOTSUP value. Change-Id: I9fe23fb6671493394a02ff5b4c7d8a91437e48fe Signed-off-by: Jiyoung Yun --- src/battery/lowbat-handler.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/battery/lowbat-handler.c b/src/battery/lowbat-handler.c index 8e19789..52baa79 100644 --- a/src/battery/lowbat-handler.c +++ b/src/battery/lowbat-handler.c @@ -520,6 +520,14 @@ static int lowbat_probe(void *data) * deviced does not activate a battery module. */ if (access(POWER_PATH, R_OK) != 0) { + /** + * Set battery vconf as -ENOTSUP + * These vconf key used by runtime-info and capi-system-device. + */ + vconf_set_int(VCONFKEY_SYSMAN_CHARGER_STATUS, -ENOTSUP); + vconf_set_int(VCONFKEY_SYSMAN_BATTERY_CHARGE_NOW, -ENOTSUP); + vconf_set_int(VCONFKEY_SYSMAN_BATTERY_LEVEL_STATUS, -ENOTSUP); + _E("there is no power-supply class"); return -ENODEV; } -- 2.7.4 From af9e4848023c0e119870db80ffa944bb020653f7 Mon Sep 17 00:00:00 2001 From: Jiyoung Yun Date: Wed, 25 Feb 2015 20:35:32 +0900 Subject: [PATCH 16/16] deviced: Change wrong dbus configuration Root, console and default user can send to device object path. Change-Id: I22e24d33cf5b3f93731982f805aba6f2fadccd03 Signed-off-by: Jiyoung Yun --- scripts/deviced.conf | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/scripts/deviced.conf b/scripts/deviced.conf index e70c8e8..51ca6a0 100644 --- a/scripts/deviced.conf +++ b/scripts/deviced.conf @@ -1,23 +1,16 @@ - + - - + + + + + - - - - - - - - - - - + -- 2.7.4