From 1c840558d1e95d9f2d782ee826fd28b69578006e Mon Sep 17 00:00:00 2001 From: Youngjae Cho Date: Thu, 14 Apr 2022 11:10:32 +0900 Subject: [PATCH 01/16] usb-gadget: relocate declarations of enum Move USB_FUNCTION_IDX_* from hal-api-device to deviced. Move USB_FUNCTION_* from hal-api-device to capi-system-device. Change-Id: I820fa7532c9376ccf41fdfe7684a39613e60e16b Signed-off-by: Youngjae Cho --- src/usb/usb-dbus.c | 1 + src/usb/usb-debug.c | 1 + src/usb/usb-gadget.h | 15 ++++++++++++++- src/usb/usb-tethering.c | 1 + 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/usb/usb-dbus.c b/src/usb/usb-dbus.c index 137a5e1..35eb16d 100644 --- a/src/usb/usb-dbus.c +++ b/src/usb/usb-dbus.c @@ -25,6 +25,7 @@ #include "core/log.h" #include "usb.h" +#include "usb-gadget.h" #include "usb-debug.h" /* Legacy signals */ diff --git a/src/usb/usb-debug.c b/src/usb/usb-debug.c index f6bfb23..22b5025 100644 --- a/src/usb/usb-debug.c +++ b/src/usb/usb-debug.c @@ -26,6 +26,7 @@ #include "shared/device-notifier.h" #include "usb.h" +#include "usb-gadget.h" static bool debug_state; diff --git a/src/usb/usb-gadget.h b/src/usb/usb-gadget.h index 161be96..e98442f 100644 --- a/src/usb/usb-gadget.h +++ b/src/usb/usb-gadget.h @@ -2,7 +2,7 @@ #define __USB_GADGET_H__ #include -#include +#include /*The default USB configuration */ #define DEFAULT_VID 0x04e8 @@ -73,6 +73,19 @@ struct usb_gadget_id { unsigned int function_mask; }; +enum { + USB_FUNCTION_IDX_MTP = 0, + USB_FUNCTION_IDX_ACM = 1, + USB_FUNCTION_IDX_SDB = 2, + USB_FUNCTION_IDX_RNDIS = 3, + USB_FUNCTION_IDX_DIAG = 4, + USB_FUNCTION_IDX_CONN_GADGET = 5, + USB_FUNCTION_IDX_DM = 6, + USB_FUNCTION_IDX_RMNET = 7, + USB_FUNCTION_IDX_MAX = USB_FUNCTION_IDX_RMNET + 1 +}; + + struct usb_function *find_usb_function_by_name(const char *name); struct usb_function *find_usb_function_by_name_instance(const char *name, const char *instance); diff --git a/src/usb/usb-tethering.c b/src/usb/usb-tethering.c index f0d7142..76dcb7d 100644 --- a/src/usb/usb-tethering.c +++ b/src/usb/usb-tethering.c @@ -25,6 +25,7 @@ #include "shared/device-notifier.h" #include "usb.h" +#include "usb-gadget.h" static bool tethering_state; -- 2.7.4 From 144e15b472e90840d6bb7c6c5dfec91774cc1a7f Mon Sep 17 00:00:00 2001 From: Youngjae Cho Date: Thu, 14 Apr 2022 09:33:24 +0900 Subject: [PATCH 02/16] Rename usb modules - usb -> usb-gadget - usbhost -> usb-host Change-Id: I2ccce17d76e71399798424654dca9844f9874625 Signed-off-by: Youngjae Cho --- CMakeLists.txt | 4 ++-- src/{usb => usb-gadget}/usb-dbus.c | 0 src/{usb => usb-gadget}/usb-debug.c | 0 src/{usb => usb-gadget}/usb-debug.h | 0 src/{usb => usb-gadget}/usb-gadget-cfs-gadget.c | 0 src/{usb => usb-gadget}/usb-gadget-legacy-gadget.c | 0 src/{usb => usb-gadget}/usb-gadget.c | 0 src/{usb => usb-gadget}/usb-gadget.h | 0 src/{usb => usb-gadget}/usb-state.c | 0 src/{usb => usb-gadget}/usb-tethering.c | 0 src/{usb => usb-gadget}/usb-tethering.h | 0 src/{usb => usb-gadget}/usb.c | 0 src/{usb => usb-gadget}/usb.h | 0 src/{usbhost => usb-host}/usb-host.c | 0 14 files changed, 2 insertions(+), 2 deletions(-) rename src/{usb => usb-gadget}/usb-dbus.c (100%) rename src/{usb => usb-gadget}/usb-debug.c (100%) rename src/{usb => usb-gadget}/usb-debug.h (100%) rename src/{usb => usb-gadget}/usb-gadget-cfs-gadget.c (100%) rename src/{usb => usb-gadget}/usb-gadget-legacy-gadget.c (100%) rename src/{usb => usb-gadget}/usb-gadget.c (100%) rename src/{usb => usb-gadget}/usb-gadget.h (100%) rename src/{usb => usb-gadget}/usb-state.c (100%) rename src/{usb => usb-gadget}/usb-tethering.c (100%) rename src/{usb => usb-gadget}/usb-tethering.h (100%) rename src/{usb => usb-gadget}/usb.c (100%) rename src/{usb => usb-gadget}/usb.h (100%) rename src/{usbhost => usb-host}/usb-host.c (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 287aac9..6143791 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -122,13 +122,13 @@ ENDIF() # usb client IF(USB_MODULE STREQUAL on) - ADD_SOURCE(src/usb USB_SRCS) + ADD_SOURCE(src/usb-gadget USB_SRCS) SET(SRCS ${SRCS} ${USB_SRCS}) ENDIF() # usb host IF(USBHOST_MODULE STREQUAL on) - ADD_SOURCE(src/usbhost USBHOST_SRCS) + ADD_SOURCE(src/usb-host USBHOST_SRCS) SET(SRCS ${SRCS} ${USBHOST_SRCS}) ENDIF() diff --git a/src/usb/usb-dbus.c b/src/usb-gadget/usb-dbus.c similarity index 100% rename from src/usb/usb-dbus.c rename to src/usb-gadget/usb-dbus.c diff --git a/src/usb/usb-debug.c b/src/usb-gadget/usb-debug.c similarity index 100% rename from src/usb/usb-debug.c rename to src/usb-gadget/usb-debug.c diff --git a/src/usb/usb-debug.h b/src/usb-gadget/usb-debug.h similarity index 100% rename from src/usb/usb-debug.h rename to src/usb-gadget/usb-debug.h diff --git a/src/usb/usb-gadget-cfs-gadget.c b/src/usb-gadget/usb-gadget-cfs-gadget.c similarity index 100% rename from src/usb/usb-gadget-cfs-gadget.c rename to src/usb-gadget/usb-gadget-cfs-gadget.c diff --git a/src/usb/usb-gadget-legacy-gadget.c b/src/usb-gadget/usb-gadget-legacy-gadget.c similarity index 100% rename from src/usb/usb-gadget-legacy-gadget.c rename to src/usb-gadget/usb-gadget-legacy-gadget.c diff --git a/src/usb/usb-gadget.c b/src/usb-gadget/usb-gadget.c similarity index 100% rename from src/usb/usb-gadget.c rename to src/usb-gadget/usb-gadget.c diff --git a/src/usb/usb-gadget.h b/src/usb-gadget/usb-gadget.h similarity index 100% rename from src/usb/usb-gadget.h rename to src/usb-gadget/usb-gadget.h diff --git a/src/usb/usb-state.c b/src/usb-gadget/usb-state.c similarity index 100% rename from src/usb/usb-state.c rename to src/usb-gadget/usb-state.c diff --git a/src/usb/usb-tethering.c b/src/usb-gadget/usb-tethering.c similarity index 100% rename from src/usb/usb-tethering.c rename to src/usb-gadget/usb-tethering.c diff --git a/src/usb/usb-tethering.h b/src/usb-gadget/usb-tethering.h similarity index 100% rename from src/usb/usb-tethering.h rename to src/usb-gadget/usb-tethering.h diff --git a/src/usb/usb.c b/src/usb-gadget/usb.c similarity index 100% rename from src/usb/usb.c rename to src/usb-gadget/usb.c diff --git a/src/usb/usb.h b/src/usb-gadget/usb.h similarity index 100% rename from src/usb/usb.h rename to src/usb-gadget/usb.h diff --git a/src/usbhost/usb-host.c b/src/usb-host/usb-host.c similarity index 100% rename from src/usbhost/usb-host.c rename to src/usb-host/usb-host.c -- 2.7.4 From 0bef4a1e57519e6cc08b879a83240a99ec6c9eeb Mon Sep 17 00:00:00 2001 From: Hyotaek Shim Date: Tue, 19 Apr 2022 14:28:11 +0900 Subject: [PATCH 03/16] Fix DAC permission for board commands not to use SETUID Instead, board user modules including booting-done.service will have privileged credentials. Change-Id: I9d838bc266fbb40d67ad61083254a7a527ae9ea3 Signed-off-by: Hyotaek Shim --- packaging/deviced.spec | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/packaging/deviced.spec b/packaging/deviced.spec index 91cc598..debab7d 100644 --- a/packaging/deviced.spec +++ b/packaging/deviced.spec @@ -321,15 +321,15 @@ mv %{_libdir}/iot-headless-battery.so %{_libdir}/deviced/battery.so %{_bindir}/direct_set_debug.sh #endif %{TZ_SYS_DUMPGEN}/dump_pmstate_log.sh -%attr(4554,root,system_fw) %{_bindir}/device_board_set_boot_success -%attr(4554,root,system_fw) %{_bindir}/device_board_clear_boot_mode -%attr(4555,root,system_fw) %{_bindir}/device_board_get_boot_mode -%attr(4554,root,system_fw) %{_bindir}/device_board_switch_partition -%attr(4554,root,system_fw) %{_bindir}/device_board_set_partition_ab_cloned -%attr(4554,root,system_fw) %{_bindir}/device_board_clear_partition_ab_cloned -%attr(4555,root,system_fw) %{_bindir}/device_board_get_partition_ab_cloned -%attr(4554,root,system_fw) %{_bindir}/device_board_set_upgrade_status -%attr(4555,root,system_fw) %{_bindir}/device_board_get_upgrade_status +%attr(0554,system_fw,system_fw) %{_bindir}/device_board_set_boot_success +%attr(0554,system_fw,system_fw) %{_bindir}/device_board_clear_boot_mode +%attr(0555,system_fw,system_fw) %{_bindir}/device_board_get_boot_mode +%attr(0554,system_fw,system_fw) %{_bindir}/device_board_switch_partition +%attr(0554,system_fw,system_fw) %{_bindir}/device_board_set_partition_ab_cloned +%attr(0554,system_fw,system_fw) %{_bindir}/device_board_clear_partition_ab_cloned +%attr(0555,system_fw,system_fw) %{_bindir}/device_board_get_partition_ab_cloned +%attr(0554,system_fw,system_fw) %{_bindir}/device_board_set_upgrade_status +%attr(0555,system_fw,system_fw) %{_bindir}/device_board_get_upgrade_status %files auto-test %manifest deviced.manifest -- 2.7.4 From 3e07cc5f5bffa4163413435cd47c88cde38a0113 Mon Sep 17 00:00:00 2001 From: Hyotaek Shim Date: Tue, 19 Apr 2022 12:45:17 +0900 Subject: [PATCH 04/16] Add missing dependency to security-config -- RPM install (w/ security-config) --- root:~> ls -alZ /usr/bin/device_board_* -r-sr-xr-- 1 system_fw system_fw _ 6912 Apr 19 2022 /usr/bin/device_board_clear_boot_mode -r-sr-xr-- 1 system_fw system_fw _ 6920 Apr 19 2022 /usr/bin/device_board_clear_partition_ab_cloned -r-sr-xr-x 1 system_fw system_fw _ 6920 Apr 19 2022 /usr/bin/device_board_get_boot_mode -r-sr-xr-x 1 system_fw system_fw _ 6928 Apr 19 2022 /usr/bin/device_board_get_partition_ab_cloned -r-sr-xr-x 1 system_fw system_fw _ 6920 Apr 19 2022 /usr/bin/device_board_get_upgrade_status -r-sr-xr-- 1 system_fw system_fw _ 6912 Apr 19 2022 /usr/bin/device_board_set_boot_success -r-sr-xr-- 1 system_fw system_fw _ 6920 Apr 19 2022 /usr/bin/device_board_set_partition_ab_cloned -r-sr-xr-- 1 system_fw system_fw _ 6928 Apr 19 2022 /usr/bin/device_board_set_upgrade_status -r-sr-xr-- 1 system_fw system_fw _ 6912 Apr 19 2022 /usr/bin/device_board_switch_partition -- QuickBuild image (w/o security-config) --- root:~> ls -alZ /usr/bin/device_board_* -r-sr-xr-- 1 root root _ 6912 Apr 18 2022 /usr/bin/device_board_clear_boot_mode -r-sr-xr-- 1 root root _ 6920 Apr 18 2022 /usr/bin/device_board_clear_partition_ab_cloned -r-sr-xr-x 1 root root _ 6920 Apr 18 2022 /usr/bin/device_board_get_boot_mode -r-sr-xr-x 1 root root _ 6928 Apr 18 2022 /usr/bin/device_board_get_partition_ab_cloned -r-sr-xr-x 1 root root _ 6920 Apr 18 2022 /usr/bin/device_board_get_upgrade_status -r-sr-xr-- 1 root root _ 6912 Apr 18 2022 /usr/bin/device_board_set_boot_success -r-sr-xr-- 1 root root _ 6920 Apr 18 2022 /usr/bin/device_board_set_partition_ab_cloned -r-sr-xr-- 1 root root _ 6928 Apr 18 2022 /usr/bin/device_board_set_upgrade_status -r-sr-xr-- 1 root root _ 6912 Apr 18 2022 /usr/bin/device_board_switch_partition Change-Id: Ie60cb0e6af7012f186555d3af4835e123052882c Signed-off-by: Hyotaek Shim (cherry picked from commit f0a2614d54446bd47aebde72575ae1655fa29da0) --- packaging/deviced.spec | 1 + 1 file changed, 1 insertion(+) diff --git a/packaging/deviced.spec b/packaging/deviced.spec index debab7d..5d19ec8 100644 --- a/packaging/deviced.spec +++ b/packaging/deviced.spec @@ -75,6 +75,7 @@ devel package. %package tools Summary: Deviced tools Group: System/Utilities +Requires: security-config %description tools Deviced helper programs. -- 2.7.4 From b8fca3a46cccba73c05f5014d2c26f781555f50b Mon Sep 17 00:00:00 2001 From: Youngjae Cho Date: Tue, 19 Apr 2022 18:18:53 -0700 Subject: [PATCH 05/16] usb-gadget: reinforce error log in opening a gadget Change-Id: I44aaa629e7592ccb9c982266b16f31b71d0210ec Signed-off-by: Youngjae Cho --- src/usb-gadget/usb-gadget-cfs-gadget.c | 13 ++++++++++--- src/usb-gadget/usb-gadget.c | 10 +++++++++- src/usb-gadget/usb.c | 2 +- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/usb-gadget/usb-gadget-cfs-gadget.c b/src/usb-gadget/usb-gadget-cfs-gadget.c index 61583e0..c178c0f 100644 --- a/src/usb-gadget/usb-gadget-cfs-gadget.c +++ b/src/usb-gadget/usb-gadget-cfs-gadget.c @@ -550,23 +550,30 @@ static int usb_gadget_cfs_open(void) int ret; g_cfs_client = calloc(1, sizeof(*g_cfs_client)); - if (!g_cfs_client) + if (!g_cfs_client) { + _E("Failed to alloc g_cfs_client."); return -ENOMEM; + } ret = usbg_init(CONFIGFS_PATH, &g_cfs_client->ctx); - if (ret) + if (ret) { + _E("Failed to usbg_init(), ret=%d", ret); goto err_usbg_init; + } g_cfs_client->udc = usbg_get_first_udc(g_cfs_client->ctx); if (!g_cfs_client->udc) { + _E("There is no availabe UDC."); ret = -ENODEV; goto err_no_udc; } ret = usbg_create_gadget(g_cfs_client->ctx, CONFIGFS_GADGET_NAME, &default_g_attrs, &default_g_strs, &g_cfs_client->gadget); - if (ret) + if (ret) { + _E("Failed to usbg_create_gadget(), ret=%d", ret); goto err_create_gadget; + } return 0; diff --git a/src/usb-gadget/usb-gadget.c b/src/usb-gadget/usb-gadget.c index efa1da8..59888ea 100644 --- a/src/usb-gadget/usb-gadget.c +++ b/src/usb-gadget/usb-gadget.c @@ -414,6 +414,8 @@ int usb_gadget_change_mode(unsigned int mode) int usb_gadget_init(void) { + int ret; + if (usb_gadget_legacy_supported()) { /* legacy samsung gadget */ usb_gadget_bind_legacy_gadget(&__usb_gadget_open, @@ -434,7 +436,13 @@ int usb_gadget_init(void) } /* open supported usb-gadget */ - __usb_gadget_open(); + if (__usb_gadget_open) { + ret = __usb_gadget_open(); + if (ret != 0) { + CRITICAL_LOG("Failed to open usb-gadget, %d", ret); + return ret; + } + } /* Use mtp-responder-dummy.socket when there is no mtp-responser.socket. * diff --git a/src/usb-gadget/usb.c b/src/usb-gadget/usb.c index c71da85..5c6ab63 100644 --- a/src/usb-gadget/usb.c +++ b/src/usb-gadget/usb.c @@ -287,7 +287,7 @@ static void usb_init(void *data) ret = usb_gadget_init(); if (ret < 0) { - _E("USB client cannot be used: %d", ret); + CRITICAL_LOG("USB client cannot be used: %d", ret); return; } -- 2.7.4 From 6c40650791fb99dea6b1734c0e700c3bb27fcb43 Mon Sep 17 00:00:00 2001 From: Youngjae Cho Date: Thu, 14 Apr 2022 19:00:24 +0900 Subject: [PATCH 06/16] usb-gadget: introduce configurable function set Previously, only a few predefine set of usb-gadget function can be utilized for setting usb-gadget, e.g., SET_USB_SDB_DIAG means it only activates usb-gadget functions of sdb/diag, and you are not allowed to activates any other usb-gadget combination than those predefined set. For a better intuitive useability, remove those predefined set. And you are now allowed to combine any kind of usb-gadget functions you want to use, making up a bitmap, which can be used for activating all those usb-gadget functions through vconf(db/usb/sel_mode). Usb-gadget functions are defined in capi-system-device. - USB_GADGET_FUNC_NONE = 0x00 - USB_GADGET_FUNC_SDB = 0x01 - USB_GADGET_FUNC_MTP = 0x02 - USB_GADGET_FUNC_RNDIS = 0x04 - USB_GADGET_FUNC_ACM = 0x08 - USB_GADGET_FUNC_DIAG = 0x10 - USB_GADGET_FUNC_RMNET = 0x20 Change-Id: I44c2bb2c751129613a3470569edf8babbe710845 Signed-off-by: Youngjae Cho --- src/usb-gadget/usb-dbus.c | 19 +- src/usb-gadget/usb-debug.c | 28 +- src/usb-gadget/usb-debug.h | 6 +- ...sb-gadget-cfs-gadget.c => usb-gadget-cfs-ops.c} | 8 +- src/usb-gadget/usb-gadget-cfs-ops.h | 12 + ...get-legacy-gadget.c => usb-gadget-legacy-ops.c} | 10 +- src/usb-gadget/usb-gadget-legacy-ops.h | 12 + src/usb-gadget/usb-gadget-ops.c | 518 +++++++++++++++++ src/usb-gadget/usb-gadget-ops.h | 99 ++++ src/usb-gadget/usb-gadget.c | 618 ++++++++------------- src/usb-gadget/usb-gadget.h | 164 ++---- src/usb-gadget/usb-state.c | 307 +--------- src/usb-gadget/usb-tethering.c | 39 +- src/usb-gadget/usb.c | 340 ------------ src/usb-gadget/usb.h | 50 -- 15 files changed, 1008 insertions(+), 1222 deletions(-) rename src/usb-gadget/{usb-gadget-cfs-gadget.c => usb-gadget-cfs-ops.c} (98%) create mode 100644 src/usb-gadget/usb-gadget-cfs-ops.h rename src/usb-gadget/{usb-gadget-legacy-gadget.c => usb-gadget-legacy-ops.c} (96%) create mode 100644 src/usb-gadget/usb-gadget-legacy-ops.h create mode 100644 src/usb-gadget/usb-gadget-ops.c create mode 100644 src/usb-gadget/usb-gadget-ops.h delete mode 100644 src/usb-gadget/usb.c delete mode 100644 src/usb-gadget/usb.h diff --git a/src/usb-gadget/usb-dbus.c b/src/usb-gadget/usb-dbus.c index 35eb16d..9803b98 100644 --- a/src/usb-gadget/usb-dbus.c +++ b/src/usb-gadget/usb-dbus.c @@ -24,8 +24,8 @@ #include "core/log.h" -#include "usb.h" #include "usb-gadget.h" +#include "usb-gadget-ops.h" #include "usb-debug.h" /* Legacy signals */ @@ -101,18 +101,23 @@ static void change_usb_client_mode(GDBusConnection *conn, return; } - _I("USB mode is changed by dbus signal to %d.", req_vconf); + // XXX: The mode has been changed to bitmap not only the predefined set but any possible combination + // of usb-gadget functions. But it hadn't been thoroughly investigated where this dbus signal is + // broadcasted. (I found one. It was invocation from factory testing of MCD, but that code has + // been dropped nowadays.) Therefore broadcasting from an old code with an old fashioned req_vconf + // might be an error. + _I("USB mode is changed by dbus signal to %#x.", req_vconf); - mode = get_mode_bitmap_from_vconf(req_vconf); + mode = req_vconf; - if (mode == USB_FUNCTION_INVALID) { + if (mode == USB_GADGET_FUNC_INVALID) { _E("Failed to convert vconf to USB mode. There is no mode matches up with vconf %d.", req_vconf); return; } - /* Deviced must never run in USB_FUNCTION_NONE mode. */ - if (mode == USB_FUNCTION_NONE) { - _E("Ignore this request. There is USB_FUNCTION_NONE mode matches up with vconf %d.", req_vconf); + /* Deviced must never run in USB_GADGET_FUNC_NONE mode. */ + if (mode == USB_GADGET_FUNC_NONE) { + _E("Ignore this request. There is USB_GADGET_FUNC_NONE mode matches up with vconf %d.", req_vconf); return; } diff --git a/src/usb-gadget/usb-debug.c b/src/usb-gadget/usb-debug.c index 22b5025..7b88ea3 100644 --- a/src/usb-gadget/usb-debug.c +++ b/src/usb-gadget/usb-debug.c @@ -25,8 +25,8 @@ #include "core/log.h" #include "shared/device-notifier.h" -#include "usb.h" #include "usb-gadget.h" +#include "usb-gadget-ops.h" static bool debug_state; @@ -84,30 +84,12 @@ static int usb_debug_mode_changed(void *on) { int ret; unsigned int new_mode; - bool rndis_is_enabled = false; const unsigned int curr_mode = usb_state_get_selected_mode(); - if (curr_mode & USB_FUNCTION_RNDIS) - rndis_is_enabled = true; - - /* - * debug on + rndis on : USB_FUNCTION_ACM | USB_FUNCTION_SDB | USB_FUNCTION_RNDIS - * debug on + rndis off : USB_FUNCTION_MTP | USB_FUNCTION_ACM | USB_FUNCTION_SDB - * debug off + rndis on : USB_FUNCTION_RNDIS - * debug off + rndis off : USB_FUNCTION_MTP | USB_FUNCTION_ACM - */ - - if ((int)(intptr_t) on) { - if (rndis_is_enabled) - new_mode = USB_FUNCTION_ACM | USB_FUNCTION_SDB | USB_FUNCTION_RNDIS; - else - new_mode = USB_FUNCTION_MTP | USB_FUNCTION_ACM | USB_FUNCTION_SDB; - } else { - if (rndis_is_enabled) - new_mode = USB_FUNCTION_RNDIS; - else - new_mode = USB_FUNCTION_MTP | USB_FUNCTION_ACM; - } + if ((int)(intptr_t) on) + new_mode = curr_mode | USB_GADGET_FUNC_SDB; + else + new_mode = curr_mode & (~USB_GADGET_FUNC_SDB); ret = usb_change_mode(new_mode, false); if (ret < 0) diff --git a/src/usb-gadget/usb-debug.h b/src/usb-gadget/usb-debug.h index bab0392..0eeea2c 100644 --- a/src/usb-gadget/usb-debug.h +++ b/src/usb-gadget/usb-debug.h @@ -16,8 +16,8 @@ * limitations under the License. */ -#ifndef __USB_DEBUG_H__ -#define __USB_DEBUG_H__ +#ifndef __USB_GADGET_DEBUG_H__ +#define __USB_GADGET_DEBUG_H__ #include @@ -26,4 +26,4 @@ void set_usb_debug_state(bool on); void add_usb_debug_handler(void); void remove_usb_debug_handler(void); -#endif /* __USB_DEBUG_H__ */ +#endif /* __USB_GADGET_DEBUG_H__ */ diff --git a/src/usb-gadget/usb-gadget-cfs-gadget.c b/src/usb-gadget/usb-gadget-cfs-ops.c similarity index 98% rename from src/usb-gadget/usb-gadget-cfs-gadget.c rename to src/usb-gadget/usb-gadget-cfs-ops.c index c178c0f..e33fcdf 100644 --- a/src/usb-gadget/usb-gadget-cfs-gadget.c +++ b/src/usb-gadget/usb-gadget-cfs-ops.c @@ -12,7 +12,7 @@ #include #include -#include "usb-gadget.h" +#include "usb-gadget-ops.h" #define CONFIGFS_PATH "/sys/kernel/config" @@ -628,8 +628,10 @@ int usb_gadget_cfs_supported(void) return 0; while (getline(&line, &len, fp) != -1) { - if (strstr(line, "configfs")) + if (strstr(line, "configfs")) { configfs = 1; + break; + } } fclose(fp); @@ -641,7 +643,7 @@ int usb_gadget_cfs_supported(void) return configfs; } -void usb_gadget_bind_cfs_gadget(int (**open) (void), int (**close) (void), int (**enable) (void), +void usb_gadget_bind_cfs_ops(int (**open) (void), int (**close) (void), int (**enable) (void), int (**disable) (void), int (**reconfigure) (struct usb_gadget *)) { *open = usb_gadget_cfs_open; diff --git a/src/usb-gadget/usb-gadget-cfs-ops.h b/src/usb-gadget/usb-gadget-cfs-ops.h new file mode 100644 index 0000000..2f1fd9e --- /dev/null +++ b/src/usb-gadget/usb-gadget-cfs-ops.h @@ -0,0 +1,12 @@ +#ifndef __USB_GADGET_CFS_OPS_H__ +#define __USB_GADGET_CFS_OPS_H__ + +/* configfs/functionfs gadget */ +int usb_gadget_cfs_supported(void); +void usb_gadget_bind_cfs_ops(int (**open) (void), + int (**close) (void), + int (**enable) (void), + int (**disable) (void), + int (**reconfigure) (struct usb_gadget *)); + +#endif //__USB_GADGET_CFS_OPS_H__ diff --git a/src/usb-gadget/usb-gadget-legacy-gadget.c b/src/usb-gadget/usb-gadget-legacy-ops.c similarity index 96% rename from src/usb-gadget/usb-gadget-legacy-gadget.c rename to src/usb-gadget/usb-gadget-legacy-ops.c index aa1f6b1..9bc8305 100644 --- a/src/usb-gadget/usb-gadget-legacy-gadget.c +++ b/src/usb-gadget/usb-gadget-legacy-ops.c @@ -9,7 +9,7 @@ #include #include -#include "usb-gadget.h" +#include "usb-gadget-ops.h" #define MAX_GADGET_STR_LEN 256 @@ -193,7 +193,7 @@ static void legacy_start_stop_service_and_handler(bool start) char *sep = LEGACY_FUNC_SEP; char buf[MAX_GADGET_STR_LEN]; struct usb_function *func; - struct usb_function *funcs[USB_FUNCTION_IDX_MAX]; + struct usb_function *funcs[USB_GADGET_FUNC_IDX_MAX]; /* SLP gadget uses two USB configuration. * (/sys/class/usb_mode/usb0/funcs_fconf and /sys/class/usb_mode/usb0/funcs_sconf) @@ -224,7 +224,7 @@ static void legacy_start_stop_service_and_handler(bool start) if (funcs[i] == func) continue; - if(n_func >= USB_FUNCTION_IDX_MAX) /* What happen */ + if(n_func >= USB_GADGET_FUNC_IDX_MAX) /* What happen */ break; funcs[n_func] = func; @@ -252,7 +252,7 @@ second_configuration: if (funcs[i] == func) continue; - if(n_func >= USB_FUNCTION_IDX_MAX) /* What happen */ + if(n_func >= USB_GADGET_FUNC_IDX_MAX) /* What happen */ break; funcs[n_func] = func; @@ -347,7 +347,7 @@ int usb_gadget_legacy_supported(void) return ret; } -void usb_gadget_bind_legacy_gadget(int (**open) (void), int (**close) (void), int (**enable) (void), +void usb_gadget_bind_legacy_ops(int (**open) (void), int (**close) (void), int (**enable) (void), int (**disable) (void), int (**reconfigure) (struct usb_gadget *)) { *open = usb_gadget_legacy_open; diff --git a/src/usb-gadget/usb-gadget-legacy-ops.h b/src/usb-gadget/usb-gadget-legacy-ops.h new file mode 100644 index 0000000..279edc7 --- /dev/null +++ b/src/usb-gadget/usb-gadget-legacy-ops.h @@ -0,0 +1,12 @@ +#ifndef __USB_GADGET_LEGACY_OPS_H__ +#define __USB_GADGET_LEGACY_OPS_H__ + +/* legacy samsung gadget */ +int usb_gadget_legacy_supported(void); +void usb_gadget_bind_legacy_ops(int (**open) (void), + int (**close) (void), + int (**enable) (void), + int (**disable) (void), + int (**reconfigure) (struct usb_gadget *)); + +#endif //__USB_GADGET_LEGACY_OPS_H__ diff --git a/src/usb-gadget/usb-gadget-ops.c b/src/usb-gadget/usb-gadget-ops.c new file mode 100644 index 0000000..14d7a20 --- /dev/null +++ b/src/usb-gadget/usb-gadget-ops.c @@ -0,0 +1,518 @@ +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "usb-gadget-ops.h" +#include "usb-gadget-cfs-ops.h" +#include "usb-gadget-legacy-ops.h" + +#define PATH_USB_GADGET_CONF "/hal/etc/deviced/usb-gadget.conf" + +/* These usb-gadget operations are determined by available subsystem, + * configfs usb-gadget or legacy samsung-gadget */ +static int (*__usb_gadget_open) (void); +static int (*__usb_gadget_close) (void); +static int (*__usb_gadget_enable) (void); +static int (*__usb_gadget_disable) (void); +static int (*__usb_gadget_reconfigure) (struct usb_gadget *gadget); + +struct usb_gadget_config { + unsigned int mode; /* Bitmap of usb function combination */ + struct usb_gadget_attrs attrs; +}; +static GList *usb_gadget_config_list; + +struct service_config { + char name[128]; + int remain_after_disable; /* do not stop the service on disabling usb-gadget function */ +}; +static GList *service_config_list; + +static char board_serial[128] = "01234TEST"; + +static void rndis_handler(int enable) +{ + if (enable) + (void)systemd_start_unit_wait_started("rndis.service", NULL, -1); + else + (void)systemd_stop_unit_wait_stopped("rndis.service", NULL, -1); +} + +#define DEFINE_USB_FUNCTION(_id, _name, _is_functionfs, _service, _handler) \ + static struct usb_function _##_name##_function = { \ + .id = _id, \ + .name = #_name, \ + .instance = "default", \ + .is_functionfs = _is_functionfs, \ + .service = _service, \ + .remain_after_disable = 0, \ + .handler = _handler, \ + } + +DEFINE_USB_FUNCTION(USB_GADGET_FUNC_MTP, mtp, 1, "mtp-responder", NULL); +DEFINE_USB_FUNCTION(USB_GADGET_FUNC_ACM, acm, 0, "data-router", NULL); +DEFINE_USB_FUNCTION(USB_GADGET_FUNC_SDB, sdb, 1, "sdbd", NULL); +DEFINE_USB_FUNCTION(USB_GADGET_FUNC_RNDIS, rndis, 0, "sshd", rndis_handler); +DEFINE_USB_FUNCTION(USB_GADGET_FUNC_DIAG, diag, 1, "diag", NULL); + +#undef DEFINE_USB_FUNCTION + +static struct usb_function *available_funcs[] = { + [USB_GADGET_FUNC_IDX_MTP] = &_mtp_function, + [USB_GADGET_FUNC_IDX_ACM] = &_acm_function, + [USB_GADGET_FUNC_IDX_SDB] = &_sdb_function, + [USB_GADGET_FUNC_IDX_RNDIS] = &_rndis_function, + [USB_GADGET_FUNC_IDX_DIAG] = &_diag_function, + [USB_GADGET_FUNC_IDX_MAX] = NULL /* An indicator to end the array */ +}; +static struct usb_function *find_usb_function_by_id(int id); + +struct usb_function *find_usb_function_by_name(const char *name) +{ + int i; + + if(!name || !name[0]) + return NULL; + + for (i = 0; available_funcs[i]; i++) + if (!strcmp(name, available_funcs[i]->name)) + return available_funcs[i]; + + return NULL; +} + +struct usb_function *find_usb_function_by_name_instance(const char *name, const char *instance) +{ + int i; + + if(!name || !name[0] || !instance || !instance[0]) + return NULL; + + for (i = 0; available_funcs[i]; ++i) + if (!strcmp(name, available_funcs[i]->name) && !strcmp(instance, available_funcs[i]->instance)) + return available_funcs[i]; + + return NULL; +} + +static void simple_cleanup_config(struct usb_configuration *config) +{ + if (!config) + return; + + free(config->strs.config_str); + + if (config->funcs) + free(config->funcs); + + free(config); +} + +static void cleanup_gadget(struct usb_gadget *gadget) +{ + int i; + + if (!gadget) + return; + + free(gadget->strs.manufacturer); + free(gadget->strs.product); + free(gadget->strs.serial); + + if (gadget->configs) { + for (i = 0; gadget->configs[i]; ++i) + simple_cleanup_config(gadget->configs[i]); + + free(gadget->configs); + } + + free(gadget); +} + +static int alloc_default_config(struct usb_configuration **_config) +{ + struct usb_configuration *config; + + config = calloc(1, sizeof(*config)); + if (!config) + return -ENOMEM; + + config->attrs.bmAttributs = DEFAULT_BMATTRIBUTES; + config->attrs.MaxPower = DEFAULT_MAX_POWER; + + /* TODO. Here is where to set the string used in config of configfs */ + + *_config = config; + + return 0; +} + +static int alloc_default_gadget(struct usb_gadget **_gadget) +{ + struct usb_gadget *gadget; + struct usb_configuration **configs; + + gadget = calloc(1, sizeof(*gadget)); + if (!gadget) + goto out; + + gadget->attrs.idVendor = DEFAULT_VID; + gadget->attrs.idProduct = DEFAULT_PID; + gadget->attrs.bcdDevice = DEFAULT_BCD_DEVICE; + + gadget->strs.lang_code = DEFAULT_LANG; + gadget->strs.manufacturer = strdup(DEFAULT_MANUFACTURER); + gadget->strs.product = strdup(DEFAULT_PRODUCT); + gadget->strs.serial = strdup(board_serial); + + if (!gadget->strs.manufacturer || !gadget->strs.product || !gadget->strs.serial) + goto free_strs; + + /* slp-gadget use max 2 confiuration and NULL termination */ + configs = calloc(3, sizeof(*configs)); + if (!configs) + goto free_strs; + + gadget->configs = configs; + *_gadget = gadget; + + return 0; + +free_strs: + free(gadget->strs.manufacturer); + free(gadget->strs.product); + free(gadget->strs.serial); + free(gadget); +out: + return -ENOMEM; +} + +static int id_to_gadget(struct usb_gadget_id *gadget_id, struct usb_gadget **_gadget) +{ + int ret; + int i, j; + int n_configs; + struct usb_gadget *gadget; + int functions[2][sizeof(gadget_id->function_mask)*8]; /* zero terminates */ + + GList *elem; + const struct usb_gadget_config *gc = NULL; + + if (!gadget_id || !_gadget) + return -EINVAL; + + ret = alloc_default_gadget(&gadget); + if (ret) + goto out; + + /* set custom attrs */ + SYS_G_LIST_FOREACH(usb_gadget_config_list, elem, gc) { + if (gc->mode == gadget_id->function_mask) { + if (gc->attrs.idVendor) { + gadget->attrs.idVendor = gc->attrs.idVendor; + _D("Reconfigure usb-gadget attribute idVendor=%#x", gadget->attrs.idVendor); + } + if (gc->attrs.idProduct) { + gadget->attrs.idProduct = gc->attrs.idProduct; + _D("Reconfigure usb-gadget attribute idProduct=%#x", gadget->attrs.idProduct); + } + break; + } + } + + if ((gadget_id->function_mask & USB_GADGET_FUNC_SDB) && (gadget->attrs.idVendor != DEFAULT_VID)) + _W("The sdb of host PC might not able to recognize target as it expects idVendor of %#x(current=%#x).", + DEFAULT_VID, gadget->attrs.idVendor); + + j = 0; + n_configs = 1; + for (i = 0; i < USB_GADGET_FUNC_IDX_MAX; ++i) { + if (gadget_id->function_mask & (1 << i)) + functions[0][j++] = (1 << i); + } + functions[0][j] = 0; + + for (j = 0; j < n_configs; ++j) { + int n_funcs_in_config; + struct usb_configuration *config; + + for (i = 0; functions[j][i]; ++i); + n_funcs_in_config = i; + + ret = alloc_default_config(&config); + if (ret) + goto free_configs; + + gadget->configs[j] = config; + config->funcs = calloc(n_funcs_in_config + 1, sizeof(void *)); + if (!config->funcs) + goto free_configs; + + for (i = 0; functions[j][i]; ++i) { + config->funcs[i] = find_usb_function_by_id(functions[j][i]); + if (!config->funcs[i]) + goto free_configs; + } + } + + *_gadget = gadget; + + return 0; + +free_configs: + cleanup_gadget(gadget); +out: + return ret; +} + + +static struct usb_function *find_usb_function_by_id(int id) +{ + int i; + + for (i = 0; available_funcs[i]; i++) + if (available_funcs[i]->id == id) + return available_funcs[i]; + + return NULL; +} + + +int usb_gadget_enable(void) +{ + if (!__usb_gadget_enable) { + _E("Not supported usb_gadget_enable."); + return -ENOTSUP; + } + + return __usb_gadget_enable(); +} + +int usb_gadget_disable(void) +{ + if (!__usb_gadget_disable) { + _E("Not supported usb_gadget_disable."); + return -ENOTSUP; + } + + return __usb_gadget_disable(); +} + +int usb_gadget_change_mode(unsigned int mode) +{ + struct usb_gadget *gadget; + struct usb_gadget_id gadget_id = {0, }; + int ret; + + if (!__usb_gadget_reconfigure) { + _E("Not supported usb_gadget_reconfigure."); + return -ENOTSUP; + } + + gadget_id.function_mask = mode; + + ret = id_to_gadget(&gadget_id, &gadget); + if (ret) { + _E("Failed to id_to_gadget, %d", ret); + return ret; + } + + ret = __usb_gadget_reconfigure(gadget); + cleanup_gadget(gadget); + if (ret) { + _E("Failed to reconfigure gadget, %d", ret); + return ret; + } + + return 0; +} + + +static void parse_property_systemd_unit(gpointer data, gpointer udata) +{ + struct section_property *prop = (struct section_property *) data; + struct service_config *svc = (struct service_config *) udata; + + if (MATCH(prop->key, "Service")) { + strncpy(svc->name, prop->value, sizeof(svc->name) - 1); + svc->name[sizeof(svc->name) - 1] = '\0'; + } else if (MATCH(prop->key, "RemainAfterDisable")) { + svc->remain_after_disable = MATCH(prop->value, "yes"); + } +} + +static unsigned int parse_usb_function(char *fstr) +{ + // Parse Function=, e.g., "Function=diag|acm" + unsigned int ret = USB_GADGET_FUNC_NONE; + char *p, *saveptr; + + if (!fstr) + return ret; + + p = strtok_r(fstr, "|", &saveptr); + if (!p) + return ret; + + do { + if (strncasecmp(p, "mtp", sizeof("mtp")) == 0) { + ret |= USB_GADGET_FUNC_MTP; + } else if (strncasecmp(p, "acm", sizeof("acm")) == 0) { + ret |= USB_GADGET_FUNC_ACM; + } else if(strncasecmp(p, "sdb", sizeof("sdb")) == 0) { + ret |= USB_GADGET_FUNC_SDB; + } else if (strncasecmp(p, "rndis", sizeof("rndis")) == 0) { + ret |= USB_GADGET_FUNC_RNDIS; + } else if (strncasecmp(p, "diag", sizeof("diag")) == 0) { + ret |= USB_GADGET_FUNC_DIAG; + } else if (strncasecmp(p, "rmnet", sizeof("rmnet")) == 0) { + ret |= USB_GADGET_FUNC_RMNET; + } + } while ((p = strtok_r(NULL, "|", &saveptr))); + + return ret; +} + +static void parse_property_attribute(gpointer data, gpointer udata) +{ + struct section_property *prop = (struct section_property *) data; + struct usb_gadget_config *gc = (struct usb_gadget_config *) udata; + unsigned int value; + + if (MATCH(prop->key, "Function")) { + gc->mode = parse_usb_function(prop->value); + } else if (MATCH(prop->key, "bDeviceClass")) { + sscanf(prop->value, "%x", &value); + gc->attrs.bDeviceClass = (uint8_t) value; + } else if (MATCH(prop->key, "bDeviceSubClass")) { + sscanf(prop->value, "%x", &value); + gc->attrs.bDeviceSubClass = (uint8_t) value; + } else if (MATCH(prop->key, "bDeviceProtocol")) { + sscanf(prop->value, "%x", &value); + gc->attrs.bDeviceProtocol = (uint8_t) value; + } else if (MATCH(prop->key, "idVendor")) { + sscanf(prop->value, "%x", &value); + gc->attrs.idVendor = (uint16_t) value; + } else if (MATCH(prop->key, "idProduct")) { + sscanf(prop->value, "%x", &value); + gc->attrs.idProduct = (uint16_t) value; + } else if (MATCH(prop->key, "bcdDevice")) { + sscanf(prop->value, "%x", &value); + gc->attrs.bcdDevice = (uint16_t) value; + } +} + +static int load_usb_gadget_config(const struct parse_result *result, void *data) +{ + if (MATCH(result->section, "SystemdUnit")) { + struct service_config svc = { 0, }; + void *entry = NULL; + + g_list_foreach(result->props, parse_property_systemd_unit, &svc); + + entry = malloc(sizeof(struct service_config)); + if (!entry) { + _E("Failed to alloc service config"); + return 0; + } + + _I("usb-gadget service config: name=%s, remain_after_disable=%d", + svc.name, svc.remain_after_disable); + service_config_list = g_list_prepend(service_config_list, memcpy(entry, &svc, sizeof(svc))); + + } else if (MATCH(result->section, "Attribute")) { + struct usb_gadget_config gc = { 0, }; + void *entry = NULL; + + g_list_foreach(result->props, parse_property_attribute, &gc); + + // if it hasn't defined mode, use default + if (gc.mode == USB_GADGET_FUNC_NONE) + gc.mode = USB_GADGET_FUNC_MTP | USB_GADGET_FUNC_ACM; + + entry = malloc(sizeof(struct usb_gadget_config)); + if (!entry) { + _E("Failed to alloc mapping gc"); + return 0; + } + + _I("Custom usb-gadget: mode=%d, function=%#x, idVendor=%#x, idProduct=%#x", + gc.mode, gc.mode, gc.attrs.idVendor, gc.attrs.idProduct); + + usb_gadget_config_list = g_list_prepend(usb_gadget_config_list, memcpy(entry, &gc, sizeof(gc))); + } + + return 0; +} + +int usb_gadget_ops_init(void) +{ + int ret; + int retval; + + libsys_config_parse_by_section(PATH_USB_GADGET_CONF, load_usb_gadget_config, NULL); + + if (usb_gadget_legacy_supported()) { + usb_gadget_bind_legacy_ops(&__usb_gadget_open, + &__usb_gadget_close, + &__usb_gadget_enable, + &__usb_gadget_disable, + &__usb_gadget_reconfigure); + } else if (usb_gadget_cfs_supported()) { + usb_gadget_bind_cfs_ops(&__usb_gadget_open, + &__usb_gadget_close, + &__usb_gadget_enable, + &__usb_gadget_disable, + &__usb_gadget_reconfigure); + } else { + CRITICAL_LOG("Usb-gadget is not supported."); + return -ENOTSUP; + } + + /* open supported usb-gadget */ + if (__usb_gadget_open) { + ret = __usb_gadget_open(); + if (ret != 0) { + CRITICAL_LOG("Failed to open usb-gadget, %d", ret); + return ret; + } + } + + /* Use mtp-responder-dummy.socket when there is no mtp-responser.socket. + * + * The mtp-responder.socket is special in the configfs environment. + * If mtp-responder.socket is missing, gadget configuration will fail. + * As a result, all usb operations do not work properly. + * So in environments that mtp doesn't support, use dummy mtp. + */ + if (access("/usr/lib/systemd/system/mtp-responder.socket", F_OK)) { + available_funcs[USB_GADGET_FUNC_IDX_MTP]->service = "mtp-responder-dummy"; + } + + retval = hal_device_board_get_device_serial_number(board_serial, sizeof(board_serial)); + if (retval != 0) + _E("Failed to get board serial number, use default=%s", board_serial); + + return 0; +} + +int usb_gadget_ops_exit(void) +{ + if (__usb_gadget_close) + __usb_gadget_close(); + + __usb_gadget_open = NULL; + __usb_gadget_close = NULL; + __usb_gadget_enable = NULL; + __usb_gadget_disable = NULL; + __usb_gadget_reconfigure = NULL; + + return 0; +} diff --git a/src/usb-gadget/usb-gadget-ops.h b/src/usb-gadget/usb-gadget-ops.h new file mode 100644 index 0000000..c89ddd0 --- /dev/null +++ b/src/usb-gadget/usb-gadget-ops.h @@ -0,0 +1,99 @@ +#ifndef __USB_GADGET_OPS_H__ +#define __USB_GADGET_OPS_H__ + +#include +#include + +/*The default USB configuration */ +#define DEFAULT_VID 0x04e8 +#define DEFAULT_PID 0x6860 +#define DEFAULT_BCD_DEVICE 0x0100 + +#define DEFAULT_LANG 0x409 /* US_en */ +#define DEFAULT_MANUFACTURER "Samsung" +#define DEFAULT_PRODUCT "TIZEN" +#define DEFAULT_SERIAL "01234TEST" + +#define DEFAULT_BMATTRIBUTES ((1 << 7) | (1 << 6)) +#define DEFAULT_MAX_POWER 500 + +struct usb_function { + int id; + const char *name; + const char *instance; + + int is_functionfs; + const char *service; + + /* do not stop the service on disabling usb-gadget function */ + int remain_after_disable; + + void (*handler)(int enable); +}; + +struct usb_configuration_attributes { + uint8_t bmAttributs; + int MaxPower; +}; + +struct usb_configuration_strings { + uint16_t lang_code; + char *config_str; +}; + +struct usb_configuration { + struct usb_configuration_attributes attrs; + struct usb_configuration_strings strs; + struct usb_function **funcs; +}; + +struct usb_gadget_attrs { + uint8_t bDeviceClass; + uint8_t bDeviceSubClass; + uint8_t bDeviceProtocol; + uint16_t idVendor; + uint16_t idProduct; + uint16_t bcdDevice; +}; + +struct usb_gadget_strings { + uint16_t lang_code; + char *manufacturer; + char *product; + char *serial; +}; + +struct usb_gadget { + struct usb_gadget_attrs attrs; + struct usb_gadget_strings strs; + struct usb_configuration **configs; +}; + +struct usb_gadget_id { + unsigned int function_mask; +}; + +enum { + USB_GADGET_FUNC_IDX_MTP = 0, + USB_GADGET_FUNC_IDX_ACM = 1, + USB_GADGET_FUNC_IDX_SDB = 2, + USB_GADGET_FUNC_IDX_RNDIS = 3, + USB_GADGET_FUNC_IDX_DIAG = 4, + USB_GADGET_FUNC_IDX_CONN_GADGET = 5, + USB_GADGET_FUNC_IDX_DM = 6, + USB_GADGET_FUNC_IDX_RMNET = 7, + USB_GADGET_FUNC_IDX_MAX = USB_GADGET_FUNC_IDX_RMNET + 1 +}; + + +struct usb_function *find_usb_function_by_name(const char *name); +struct usb_function *find_usb_function_by_name_instance(const char *name, const char *instance); + +int usb_gadget_ops_init(void); +int usb_gadget_ops_exit(void); + +int usb_gadget_enable(void); +int usb_gadget_disable(void); +int usb_gadget_change_mode(unsigned int mode); + +#endif //__USB_GADGET_OPS_H__ diff --git a/src/usb-gadget/usb-gadget.c b/src/usb-gadget/usb-gadget.c index 59888ea..6b01ae5 100644 --- a/src/usb-gadget/usb-gadget.c +++ b/src/usb-gadget/usb-gadget.c @@ -1,473 +1,339 @@ -#include -#include - +/* + * 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 -#include -#include +#include "core/log.h" +#include "core/udev.h" +#include "display/poll.h" +#include "display/display-ops.h" +#include "shared/plugin.h" #include "usb-gadget.h" +#include "usb-gadget-ops.h" +#include "usb-debug.h" +#include "usb-tethering.h" -static int (*__usb_gadget_open) (void); -static int (*__usb_gadget_close) (void); -static int (*__usb_gadget_enable) (void); -static int (*__usb_gadget_disable) (void); -static int (*__usb_gadget_reconfigure) (struct usb_gadget *gadget); - -/* temporary extern access */ -struct _usb_mode_mapping_table { - int mode_v; /* Integer defined by vconf */ - unsigned int mode; /* Bitmap of usb function combination */ - struct usb_gadget_attrs attrs; -}; -extern GList *usb_mode_mapping_table_custom; +static int usb_change_gadget(unsigned mode); -static void rndis_handler(int enable) -{ - if (enable) - (void)systemd_start_unit_wait_started("rndis.service", NULL, -1); - else - (void)systemd_stop_unit_wait_stopped("rndis.service", NULL, -1); -} +static struct display_plugin *disp_plgn; -#define DEFINE_USB_FUNCTION(_id, _name, _is_functionfs, _service, _handler) \ - static struct usb_function _##_name##_function = { \ - .id = _id, \ - .name = #_name, \ - .instance = "default", \ - .is_functionfs = _is_functionfs, \ - .service = _service, \ - .remain_after_disable = 0, \ - .handler = _handler, \ - } +static int usb_config_init(void) +{ + unsigned int mode = usb_state_get_selected_mode(); -DEFINE_USB_FUNCTION(USB_FUNCTION_MTP, mtp, 1, "mtp-responder", NULL); -DEFINE_USB_FUNCTION(USB_FUNCTION_ACM, acm, 0, "data-router", NULL); -DEFINE_USB_FUNCTION(USB_FUNCTION_SDB, sdb, 1, "sdbd", NULL); -DEFINE_USB_FUNCTION(USB_FUNCTION_RNDIS, rndis, 0, "sshd", rndis_handler); -DEFINE_USB_FUNCTION(USB_FUNCTION_DIAG, diag, 1, "diag", NULL); -DEFINE_USB_FUNCTION(USB_FUNCTION_CONN_GADGET, conn_gadget, 0, NULL, NULL); -DEFINE_USB_FUNCTION(USB_FUNCTION_DM, dm, 0, NULL, NULL); -DEFINE_USB_FUNCTION(USB_FUNCTION_RMNET, rmnet, 0, NULL, NULL); - -#undef DEFINE_USB_FUNCTION - -/* Caution: index order of arrary is important, because simple_translator_open() uses it. */ -static struct usb_function *_available_funcs[] = { - [USB_FUNCTION_IDX_MTP] = &_mtp_function, - [USB_FUNCTION_IDX_ACM] = &_acm_function, - [USB_FUNCTION_IDX_SDB] = &_sdb_function, - [USB_FUNCTION_IDX_RNDIS] = &_rndis_function, - [USB_FUNCTION_IDX_DIAG] = &_diag_function, - [USB_FUNCTION_IDX_CONN_GADGET] = &_conn_gadget_function, - [USB_FUNCTION_IDX_DM] = &_dm_function, - [USB_FUNCTION_IDX_RMNET] = &_rmnet_function, - [USB_FUNCTION_IDX_MAX] = NULL /* An indicator to end the array */ -}; -static struct usb_function *find_usb_function_by_id(int id); + return usb_change_gadget(mode); +} -struct usb_function *find_usb_function_by_name(const char *name) +/* Precondition: USB_GADGET_FUNC_NONE */ +static int usb_change_gadget(unsigned mode) { - int i; + int ret; - if(!name || !name[0]) - return NULL; + ret = usb_gadget_change_mode(mode); + if (ret) { + /* because usb does not work properly */ + (void)usb_state_set_current_mode(USB_GADGET_FUNC_NONE); + return ret; + } - for (i = 0; _available_funcs[i]; i++) - if (!strcmp(name, _available_funcs[i]->name)) - return _available_funcs[i]; + _I("USB gadget changed to (%#x)", mode); - return NULL; + return 0; } -struct usb_function *find_usb_function_by_name_instance(const char *name, const char *instance) +/* Precondition: USB_CONNECTED, USB_GADGET_FUNC_NONE */ +static int usb_enable(unsigned int mode) { - int i; + int ret; - if(!name || !name[0] || !instance || !instance[0]) - return NULL; + ret = usb_gadget_enable(); + if (ret < 0) { + _E("Failed to enable USB config: %d", ret); + goto out; + } - for (i = 0; _available_funcs[i]; ++i) - if (!strcmp(name, _available_funcs[i]->name) && !strcmp(instance, _available_funcs[i]->instance)) - return _available_funcs[i]; + send_usb_state_changed_event(VCONFKEY_SYSMAN_USB_AVAILABLE); + (void)usb_state_set_current_mode(mode); + change_usb_state_notification_handler(mode); - return NULL; + return 0; + +out: + /* Although this function has a USB_GADGET_FUNC_NONE precondition, it is to protect against coding mistakes. */ + (void)usb_state_set_current_mode(USB_GADGET_FUNC_NONE); /* because usb does not work properly */ + return ret; } -static void simple_cleanup_config(struct usb_configuration *config) +/* Precondition: N/A */ +static int usb_disable(void) { - if (!config) - return; + int ret; - free(config->strs.config_str); + (void)usb_state_set_current_mode(USB_GADGET_FUNC_NONE); + change_usb_state_notification_handler(USB_GADGET_FUNC_NONE); - if (config->funcs) - free(config->funcs); + ret = usb_gadget_disable(); + if (ret < 0) { + _E("Failed to disable USB config: %d", ret); + return ret; + } - free(config); + return 0; } -static void cleanup_gadget(struct usb_gadget *gadget) +/* Precondition: USB_DISCONNECTED (Implicitly contains USB_GADGET_FUNC_NONE) */ +static int usb_connected(void) { - int i; - - if (!gadget) - return; + int ret; + unsigned int mode = usb_state_get_selected_mode(); - free(gadget->strs.manufacturer); - free(gadget->strs.product); - free(gadget->strs.serial); + if (disp_plgn->pm_lock_internal) + disp_plgn->pm_lock_internal(INTERNAL_LOCK_USB, LCD_OFF, STAY_CUR_STATE, 0); - if (gadget->configs) { - for (i = 0; gadget->configs[i]; ++i) - simple_cleanup_config(gadget->configs[i]); + usb_state_set_connection(USB_CONNECTED); + send_usb_state_changed_event(VCONFKEY_SYSMAN_USB_CONNECTED); - free(gadget->configs); + ret = usb_enable(mode); + if (ret < 0) { + _E("Failed to enable USB gadget(%#x): %d", mode, ret); + return ret; } - free(gadget); + return 0; } -static int alloc_default_config(struct usb_configuration **_config) +/* Precondition: USB_CONNECTED */ +static int usb_disconnected(void) { - struct usb_configuration *config; - - config = calloc(1, sizeof(*config)); - if (!config) - return -ENOMEM; + int ret; - config->attrs.bmAttributs = DEFAULT_BMATTRIBUTES; - config->attrs.MaxPower = DEFAULT_MAX_POWER; + usb_state_set_connection(USB_DISCONNECTED); + send_usb_state_changed_event(VCONFKEY_SYSMAN_USB_DISCONNECTED); - /* TODO. Here is where to set the string used in config of configfs */ + ret = usb_disable(); + if(ret < 0) { + _E("Failed to disable USB gadget: %d", ret); + /* Important: You have to keep going to unlock disp_plgn->pm_unlock_internal */ + } - *_config = config; + if (disp_plgn->pm_unlock_internal) + disp_plgn->pm_unlock_internal(INTERNAL_LOCK_USB, LCD_OFF, STAY_CUR_STATE); - return 0; + return ret; } -static int alloc_default_gadget(char *serial, struct usb_gadget **_gadget) +/* Called by dbus signal and vconf change(tethering, debug mode) */ +int usb_change_mode(unsigned int new_mode, bool change_debug_mode) { - struct usb_gadget *gadget; - struct usb_configuration **configs; + int ret; + const unsigned int curr_mode = usb_state_get_current_mode(); + const unsigned int prev_mode = usb_state_get_selected_mode(); - gadget = calloc(1, sizeof(*gadget)); - if (!gadget) - goto out; + if (prev_mode == new_mode) { + _I("already using USB mode(%#x), current running mode (%#x)", prev_mode, curr_mode); + return 0; + } - gadget->attrs.idVendor = DEFAULT_VID; - gadget->attrs.idProduct = DEFAULT_PID; - gadget->attrs.bcdDevice = DEFAULT_BCD_DEVICE; + _I("USB change mode (%#x) -> (%#x), current running mode (%#x)", prev_mode, new_mode, curr_mode); - gadget->strs.lang_code = DEFAULT_LANG; - gadget->strs.manufacturer = strdup(DEFAULT_MANUFACTURER); - gadget->strs.product = strdup(DEFAULT_PRODUCT); - gadget->strs.serial = strdup(serial); + /* + * When you change the gadget(usb_change_gadget) for new usb mode, you must disable the gadget first. + * + * Even if the usb cable is plugged in, the current mode may be NULL due to usb fail. + * So to find out which mode you are in, you should use the current mode, not the selected mode. + */ + if (curr_mode != USB_GADGET_FUNC_NONE) { + /* Special case: Because usb gadget is disabled, temporarily switch usb state from available to connected. */ + send_usb_state_changed_event(VCONFKEY_SYSMAN_USB_CONNECTED); + + ret = usb_disable(); + if (ret < 0) { + _E("Failed to disable current USB mode."); + return ret; + } + } + + /* + * You should always change the gadget once when the usb mode is changed. + * In this state, usb_enable() is called when the usb cable is connected + * and usb_disable() is called when the usb cable is disconnected. + */ + ret = usb_change_gadget(new_mode); + if (ret < 0) { + _E("Failed to change USB gadget: %d", ret); + return ret; + } - if (!gadget->strs.manufacturer || !gadget->strs.product || !gadget->strs.serial) - goto free_strs; + if (usb_state_get_connection() == USB_CONNECTED) { + ret = usb_enable(new_mode); + if (ret < 0) { + _E("Failed to enable USB mode: %d", ret); + return ret; + } + } - /* slp-gadget use max 2 confiuration and NULL termination */ - configs = calloc(3, sizeof(*configs)); - if (!configs) - goto free_strs; + /* If you success to change the runtime usb configuration, do change the selected mode. */ + (void)usb_state_set_selected_mode(new_mode); - gadget->configs = configs; - *_gadget = gadget; + /* To sync with vconf for debug mode */ + if (change_debug_mode) + set_usb_debug_state((bool)(new_mode & USB_GADGET_FUNC_SDB)); return 0; - -free_strs: - free(gadget->strs.manufacturer); - free(gadget->strs.product); - free(gadget->strs.serial); - free(gadget); -out: - return -ENOMEM; } -static int id_to_gadget(struct usb_gadget_id *gadget_id, char *serial, struct usb_gadget **_gadget) +/* Called by extcon udev event */ +static int usb_state_changed(const char *index, int new_status) { - int ret; - int i, j; - int n_configs; - struct usb_gadget *gadget; - int functions[2][sizeof(gadget_id->function_mask)*8]; /* zero terminates */ + int ret = -1; + static int old_status = -1; /* -1: Uninitialized, 0: disconnected, 1: connected */ - GList *elem; - const struct _usb_mode_mapping_table *cm = NULL; + /* For debugging. Do not move the location. */ + _I("USB state is changed by extcon from (%d) to (%d).", old_status, new_status); - if (!gadget_id || !serial || !_gadget) - return -EINVAL; + if (old_status == new_status) + return 0; - ret = alloc_default_gadget(serial, &gadget); - if (ret) - goto out; + switch (new_status) { + case USB_CONNECTED: + ret = usb_connected(); + break; - /* find custom mode */ - SYS_G_LIST_FOREACH(usb_mode_mapping_table_custom, elem, cm) { - if (cm->mode == gadget_id->function_mask) - break; - } + case USB_DISCONNECTED: + if (old_status == -1) { + /* only initialize the internal data state and skip usb hal operation. */ + _I("USB is initialized without USB connection"); - if (cm) { - int i, j; - - j = 0; - n_configs = 1; - for (i = 0; i < USB_FUNCTION_IDX_MAX; ++i) { - if (cm->mode & (1 << i)) - functions[0][j++] = (1 << i); - } - functions[0][j] = 0; - - if (cm->attrs.idVendor) - gadget->attrs.idVendor = cm->attrs.idVendor; - if (cm->attrs.idProduct) - gadget->attrs.idProduct = cm->attrs.idProduct; - - } else { - /* - * Currently all gadgets use inly single configuration but - * slp-gadget is capable to handle two of them - * - * Order of interfaces in configuration is significant - * so in this switch we sort our functions in a correct order - */ - switch (gadget_id->function_mask) { - /* MTP, ACM, SDB */ - case USB_FUNCTION_MTP | USB_FUNCTION_ACM: - n_configs = 1; - functions[0][0] = USB_FUNCTION_MTP; - functions[0][1] = USB_FUNCTION_ACM; - functions[0][2] = 0; - gadget->attrs.idProduct = 0x6860; - break; - - case USB_FUNCTION_MTP | USB_FUNCTION_ACM | USB_FUNCTION_SDB: - n_configs = 1; - functions[0][0] = USB_FUNCTION_MTP; - functions[0][1] = USB_FUNCTION_ACM; - functions[0][2] = USB_FUNCTION_SDB; - functions[0][3] = 0; - gadget->attrs.idProduct = 0x6860; - break; - - /* DIAG */ - case USB_FUNCTION_MTP | USB_FUNCTION_ACM | USB_FUNCTION_SDB | USB_FUNCTION_DIAG: - n_configs = 1; - functions[0][0] = USB_FUNCTION_MTP; - functions[0][1] = USB_FUNCTION_ACM; - functions[0][2] = USB_FUNCTION_SDB; - functions[0][3] = USB_FUNCTION_DIAG; - functions[0][4] = 0; - gadget->attrs.idProduct = 0x6860; - break; - - /* RNDIS */ - case USB_FUNCTION_RNDIS: - n_configs = 1; - functions[0][0] = USB_FUNCTION_RNDIS; - functions[0][1] = 0; - gadget->attrs.idProduct = 0x6863; - break; - - case USB_FUNCTION_RNDIS | USB_FUNCTION_DIAG: - n_configs = 1; - functions[0][0] = USB_FUNCTION_RNDIS; - functions[0][1] = USB_FUNCTION_DIAG; - functions[0][2] = 0; - gadget->attrs.idProduct = 0x6864; - break; - - case USB_FUNCTION_ACM | USB_FUNCTION_SDB | USB_FUNCTION_RNDIS: - n_configs = 1; - functions[0][0] = USB_FUNCTION_RNDIS; - functions[0][1] = USB_FUNCTION_ACM; - functions[0][2] = USB_FUNCTION_SDB; - functions[0][3] = 0; - gadget->attrs.idProduct = 0x6864; - break; - - /* RMNET */ - case USB_FUNCTION_DIAG | USB_FUNCTION_RMNET: - n_configs = 1; - functions[0][0] = USB_FUNCTION_DIAG; - functions[0][1] = USB_FUNCTION_RMNET; - functions[0][2] = 0; - gadget->attrs.idProduct = 0x685d; - break; - - /* DM */ - case USB_FUNCTION_ACM | USB_FUNCTION_SDB | USB_FUNCTION_DM: - n_configs = 1; - functions[0][0] = USB_FUNCTION_ACM; - functions[0][1] = USB_FUNCTION_SDB; - functions[0][2] = USB_FUNCTION_DM; - functions[0][3] = 0; - gadget->attrs.idProduct = 0x6860; - break; - - default: - ret = -EINVAL; - goto free_gadget; - }; - } + /* From usb_disconnected() */ + usb_state_set_connection(USB_DISCONNECTED); + send_usb_state_changed_event(VCONFKEY_SYSMAN_USB_DISCONNECTED); - for (j = 0; j < n_configs; ++j) { - int n_funcs_in_config; - struct usb_configuration *config; + /* From usb_disable() */ + (void)usb_state_set_current_mode(USB_GADGET_FUNC_NONE); + change_usb_state_notification_handler(USB_GADGET_FUNC_NONE); - for (i = 0; functions[j][i]; ++i); - n_funcs_in_config = i; + ret = 0; + } else + ret = usb_disconnected(); + break; - ret = alloc_default_config(&config); - if (ret) - goto free_configs; - - gadget->configs[j] = config; - config->funcs = calloc(n_funcs_in_config + 1, sizeof(void *)); - if (!config->funcs) - goto free_configs; + default: + _E("Invalid USB state(%d).", new_status); + return -EINVAL; + } - for (i = 0; functions[j][i]; ++i) { - config->funcs[i] = find_usb_function_by_id(functions[j][i]); - if (!config->funcs[i]) - goto free_configs; - } + if (ret < 0) { + _E("Failed to operate USB connection: %d", ret); + return ret; } - *_gadget = gadget; + old_status = new_status; - return 0; - -free_configs: -free_gadget: - cleanup_gadget(gadget); -out: return ret; } - -static struct usb_function *find_usb_function_by_id(int id) +static void uevent_usb_mode_handler(struct udev_device *dev) { - int i; + const char *state = NULL; - for (i = 0; _available_funcs[i]; i++) - if (_available_funcs[i]->id == id) - return _available_funcs[i]; - - return NULL; -} + state = udev_device_get_property_value(dev, "USB_STATE"); + if (!state) + return; + if (strncmp(state, "CONFIGURED", strlen(state) + 1)) + return; -int usb_gadget_enable(void) -{ - if (!__usb_gadget_enable) { - _E("Not supported usb_gadget_enable."); - return -ENOTSUP; - } + _I("USB udev event happend : CONFIGURED USB_STATE"); - return __usb_gadget_enable(); -} + if (usb_state_get_selected_mode() & USB_GADGET_FUNC_ACM) + systemd_start_unit_wait_started ("data-router.service", NULL, -1); -int usb_gadget_disable(void) -{ - if (!__usb_gadget_disable) { - _E("Not supported usb_gadget_disable."); - return -ENOTSUP; - } + if (usb_state_get_selected_mode() & USB_GADGET_FUNC_SDB) + systemd_start_unit_wait_started ("sdbd.service", NULL, -1); - return __usb_gadget_disable(); + if (usb_state_get_selected_mode() & USB_GADGET_FUNC_MTP) + systemd_start_unit_wait_started ("mtp-responder.service", NULL, -1); } -int usb_gadget_change_mode(unsigned int mode) +static struct uevent_handler uh = { + .subsystem = "usb_mode", + .uevent_func = uevent_usb_mode_handler, +}; + +static void usb_init(void *data) { - struct usb_gadget *gadget; - struct usb_gadget_id gadget_id = {0, }; - char serial[] = "123456"; int ret; - if (!__usb_gadget_reconfigure) { - _E("Not supported usb_gadget_reconfigure."); - return -ENOTSUP; + usb_state_retrieve_selected_mode(); + + ret = usb_gadget_ops_init(); + if (ret < 0) { + CRITICAL_LOG("USB client cannot be used: %d", ret); + return; } - gadget_id.function_mask = mode; + ret = usb_config_init(); + if (ret < 0) + _E("Failed to initialize USB configuation."); - ret = id_to_gadget(&gadget_id, serial, &gadget); - if (ret) { - _E("Failed to id_to_gadget, %d", ret); - return ret; - } + ret = register_udev_uevent_control(&uh); + if (ret < 0) + _E("Failed to register udev event(%d) for USB", ret); - ret = __usb_gadget_reconfigure(gadget); - cleanup_gadget(gadget); - if (ret) { - _E("Failed to reconfigure gadget, %d", ret); - return ret; - } + ret = usb_dbus_init(); + if (ret < 0) + _E("Failed to init dbus(%d) for USB", ret); - return 0; + add_usb_tethering_handler(); + add_usb_debug_handler(); } -int usb_gadget_init(void) +static void usb_exit(void *data) { - int ret; + remove_usb_debug_handler(); + remove_usb_tethering_handler(); - if (usb_gadget_legacy_supported()) { - /* legacy samsung gadget */ - usb_gadget_bind_legacy_gadget(&__usb_gadget_open, - &__usb_gadget_close, - &__usb_gadget_enable, - &__usb_gadget_disable, - &__usb_gadget_reconfigure); - } else if (usb_gadget_cfs_supported()) { - /* configfs/functionfs gadget */ - usb_gadget_bind_cfs_gadget(&__usb_gadget_open, - &__usb_gadget_close, - &__usb_gadget_enable, - &__usb_gadget_disable, - &__usb_gadget_reconfigure); - } else { - CRITICAL_LOG("Usb-gadget is not supported."); - return -ENOTSUP; - } + usb_state_set_connection(USB_DISCONNECTED); + send_usb_state_changed_event(VCONFKEY_SYSMAN_USB_DISCONNECTED); + (void)usb_state_set_current_mode(USB_GADGET_FUNC_NONE); + change_usb_state_notification_handler(USB_GADGET_FUNC_NONE); - /* open supported usb-gadget */ - if (__usb_gadget_open) { - ret = __usb_gadget_open(); - if (ret != 0) { - CRITICAL_LOG("Failed to open usb-gadget, %d", ret); - return ret; - } - } - - /* Use mtp-responder-dummy.socket when there is no mtp-responser.socket. - * - * The mtp-responder.socket is special in the configfs environment. - * If mtp-responder.socket is missing, gadget configuration will fail. - * As a result, all usb operations do not work properly. - * So in environments that mtp doesn't support, use dummy mtp. - */ - if (access("/usr/lib/systemd/system/mtp-responder.socket", F_OK)) { - _available_funcs[USB_FUNCTION_IDX_MTP]->service = "mtp-responder-dummy"; - } + unregister_udev_uevent_control(&uh); + usb_gadget_disable(); + usb_gadget_ops_exit(); - return 0; } -int usb_gadget_exit(void) -{ - if (__usb_gadget_close) - __usb_gadget_close(); +static struct extcon_ops extcon_usb_ops = { + .name = EXTCON_CABLE_USB, + .init = usb_init, + .exit = usb_exit, + .update = usb_state_changed, +}; - __usb_gadget_open = NULL; - __usb_gadget_close = NULL; - __usb_gadget_enable = NULL; - __usb_gadget_disable = NULL; - __usb_gadget_reconfigure = NULL; +EXTCON_OPS_REGISTER(extcon_usb_ops) - return 0; +static void __CONSTRUCTOR__ initialize(void) +{ + disp_plgn = get_var_display_plugin(); + if (!disp_plgn) + _E("Failed to get display plugin variable."); } diff --git a/src/usb-gadget/usb-gadget.h b/src/usb-gadget/usb-gadget.h index e98442f..f686acb 100644 --- a/src/usb-gadget/usb-gadget.h +++ b/src/usb-gadget/usb-gadget.h @@ -1,114 +1,50 @@ -#ifndef __USB_GADGET_H__ -#define __USB_GADGET_H__ - -#include -#include - -/*The default USB configuration */ -#define DEFAULT_VID 0x04e8 -#define DEFAULT_PID 0x6860 -#define DEFAULT_BCD_DEVICE 0x0100 - -#define DEFAULT_LANG 0x409 /* US_en */ -#define DEFAULT_MANUFACTURER "Samsung" -#define DEFAULT_PRODUCT "TIZEN" -#define DEFAULT_SERIAL "01234TEST" - -#define DEFAULT_BMATTRIBUTES ((1 << 7) | (1 << 6)) -#define DEFAULT_MAX_POWER 500 - -struct usb_function { - int id; - const char *name; - const char *instance; - - int is_functionfs; - const char *service; - - /* do not stop the service on disabling usb-gadget function */ - int remain_after_disable; - - void (*handler)(int enable); -}; - -struct usb_configuration_attributes { - uint8_t bmAttributs; - int MaxPower; -}; - -struct usb_configuration_strings { - uint16_t lang_code; - char *config_str; -}; - -struct usb_configuration { - struct usb_configuration_attributes attrs; - struct usb_configuration_strings strs; - struct usb_function **funcs; -}; - -struct usb_gadget_attrs { - uint8_t bDeviceClass; - uint8_t bDeviceSubClass; - uint8_t bDeviceProtocol; - uint16_t idVendor; - uint16_t idProduct; - uint16_t bcdDevice; -}; - -struct usb_gadget_strings { - uint16_t lang_code; - char *manufacturer; - char *product; - char *serial; -}; - -struct usb_gadget { - struct usb_gadget_attrs attrs; - struct usb_gadget_strings strs; - struct usb_configuration **configs; -}; - -struct usb_gadget_id { - unsigned int function_mask; -}; - -enum { - USB_FUNCTION_IDX_MTP = 0, - USB_FUNCTION_IDX_ACM = 1, - USB_FUNCTION_IDX_SDB = 2, - USB_FUNCTION_IDX_RNDIS = 3, - USB_FUNCTION_IDX_DIAG = 4, - USB_FUNCTION_IDX_CONN_GADGET = 5, - USB_FUNCTION_IDX_DM = 6, - USB_FUNCTION_IDX_RMNET = 7, - USB_FUNCTION_IDX_MAX = USB_FUNCTION_IDX_RMNET + 1 -}; - - -struct usb_function *find_usb_function_by_name(const char *name); -struct usb_function *find_usb_function_by_name_instance(const char *name, const char *instance); - -int usb_gadget_enable(void); -int usb_gadget_disable(void); -int usb_gadget_change_mode(unsigned int mode); -int usb_gadget_init(void); -int usb_gadget_exit(void); - -/* legacy samsung gadget */ -int usb_gadget_legacy_supported(void); -void usb_gadget_bind_legacy_gadget(int (**open) (void), - int (**close) (void), - int (**enable) (void), - int (**disable) (void), - int (**reconfigure) (struct usb_gadget *)); - -/* configfs/functionfs gadget */ -int usb_gadget_cfs_supported(void); -void usb_gadget_bind_cfs_gadget(int (**open) (void), - int (**close) (void), - int (**enable) (void), - int (**disable) (void), - int (**reconfigure) (struct usb_gadget *)); - -#endif //__USB_GADGET_H__ +/* + * 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 __DEVICED_USB_GADGET_H___ +#define __DEVICED_USB_GADGET_H___ + +#include +#include +#include "extcon/extcon.h" + +#define USB_GADGET_FUNC_INVALID UINT_MAX +#define SET_USB_INVALID INT_MAX + +int usb_dbus_init(void); + +void usb_state_load_custom_mode(void); + +int usb_change_mode(unsigned int mode, bool change_debug_mode); +void usb_state_retrieve_selected_mode(void); +unsigned int get_mode_bitmap_from_vconf(int mode_v); + +void broadcast_usb_state_changed(void); +void send_usb_state_changed_event(int status); +void change_usb_state_notification_handler(unsigned int mode); + +unsigned int usb_state_get_selected_mode(void); +int usb_state_set_selected_mode(unsigned int mode); + +unsigned int usb_state_get_current_mode(void); +int usb_state_set_current_mode(unsigned int mode); + +extcon_usb_state_e usb_state_get_connection(void); +void usb_state_set_connection(extcon_usb_state_e conn); + +#endif /* __DEVICED_USB_GADGET_H__ */ diff --git a/src/usb-gadget/usb-state.c b/src/usb-gadget/usb-state.c index d05f9a3..a3e766d 100644 --- a/src/usb-gadget/usb-state.c +++ b/src/usb-gadget/usb-state.c @@ -21,123 +21,22 @@ #include #include #include -#include #include "core/log.h" #include "apps/apps.h" #include "extcon/extcon.h" -#include "usb.h" -#include "usb-debug.h" #include "usb-gadget.h" - -#define PATH_USB_GADGET_CONF "/hal/etc/deviced/usb_gadget.conf" +#include "usb-debug.h" +#include "usb-gadget-ops.h" static int noti_id = -1; -static unsigned int usb_current_mode = USB_FUNCTION_NONE; -static unsigned int usb_selected_mode = USB_FUNCTION_NONE; +static unsigned int usb_current_mode = USB_GADGET_FUNC_NONE; +static unsigned int usb_selected_mode = USB_GADGET_FUNC_NONE; static extcon_usb_state_e usb_connection = USB_DISCONNECTED; -/** - * Important - * You must keep the order for the specific items. - * - * There may be several mode_v for a mode. - * In this case, the representative value should be placed on top. - * - * In case of SET_USB_SDB_DIAG and SET_USB_DIAG_SDB, the SET_USB_SDB_DIAG should be above. - * As another example, SET_USB_RNDIS_SDB should be at the top of them. - */ -static const struct _usb_mode_mapping_table { - int mode_v; /* Integer defined by vconf */ - unsigned int mode; /* Bitmap of usb function combination */ - struct usb_gadget_attrs attrs; -} usb_mode_mapping_table[] = { - /* Hack for performance. In most cases this is the value. */ - {SET_USB_DEFAULT, USB_FUNCTION_MTP | USB_FUNCTION_ACM}, - {SET_USB_SDB, USB_FUNCTION_MTP | USB_FUNCTION_ACM | USB_FUNCTION_SDB}, - - {SET_USB_NONE, USB_FUNCTION_NONE}, - {SET_USB_RNDIS, USB_FUNCTION_RNDIS}, - {SET_USB_RNDIS_DIAG, USB_FUNCTION_RNDIS | USB_FUNCTION_DIAG}, - {SET_USB_DIAG_RMNET, USB_FUNCTION_DIAG | USB_FUNCTION_RMNET}, - {SET_USB_ACM_SDB_DM, USB_FUNCTION_ACM | USB_FUNCTION_SDB | USB_FUNCTION_DM}, - - {SET_USB_SDB_DIAG, USB_FUNCTION_MTP | USB_FUNCTION_ACM | USB_FUNCTION_SDB | USB_FUNCTION_DIAG}, - {SET_USB_DIAG_SDB, USB_FUNCTION_MTP | USB_FUNCTION_ACM | USB_FUNCTION_SDB | USB_FUNCTION_DIAG}, - - {SET_USB_RNDIS_SDB, USB_FUNCTION_ACM | USB_FUNCTION_SDB | USB_FUNCTION_RNDIS}, - {SET_USB_RNDIS_TETHERING, USB_FUNCTION_ACM | USB_FUNCTION_SDB | USB_FUNCTION_RNDIS}, - {SET_USB_RNDIS_SDB_ACM, USB_FUNCTION_ACM | USB_FUNCTION_SDB | USB_FUNCTION_RNDIS}, -}; - -static const int mapping_table_len = sizeof(usb_mode_mapping_table) / sizeof(usb_mode_mapping_table[0]); - -/* - * Private, custom defined mode mapping. - * You can define custom mode_v with mode from /hal/etc/deviced/usb_gadget.conf - * A custom mapping precedes the above default mapping if the custom mode_v overlaps - * default mode_v. - * - * Do not declare it with static storage class as it will be exported as dynamic symbol - * so that dlopen-ed device-common can refer it. - */ -GList *usb_mode_mapping_table_custom; - -/* - * Do not declare it with static storage class as it will be exported as dynamic symbol - * so that dlopen-ed device-common can refer it. - */ -struct service_config { - char name[128]; - int remain_after_disable; /* do not stop the service on disabling usb-gadget function */ -}; -GList *service_config_list; - -unsigned int get_mode_bitmap_from_vconf(int mode_v) -{ - int i; - GList *elem; - struct _usb_mode_mapping_table *table; - - /* lookup from custom mapping table first */ - SYS_G_LIST_FOREACH(usb_mode_mapping_table_custom, elem, table) { - if (table->mode_v == mode_v) - return table->mode; - } - - /* and then lookup the default mapping table */ - for (i = 0; i < mapping_table_len; i++) { - if (usb_mode_mapping_table[i].mode_v == mode_v) - return usb_mode_mapping_table[i].mode; - } - - return USB_FUNCTION_INVALID; -} - -static int get_mode_vconf_from_bitmap(unsigned int mode) -{ - int i; - GList *elem; - struct _usb_mode_mapping_table *table; - - /* lookup from custom mapping table first */ - SYS_G_LIST_FOREACH(usb_mode_mapping_table_custom, elem, table) { - if (table->mode == mode) - return table->mode_v; - } - - /* Caution: The order to search the usb_mode_mapping_table must start with a low index. */ - for (i = 0; i < mapping_table_len; i++) { - if (usb_mode_mapping_table[i].mode == mode) - return usb_mode_mapping_table[i].mode_v; - } - - return SET_USB_INVALID; -} - static void usb_state_send_system_event(int status) { bundle *b; @@ -168,178 +67,41 @@ static void usb_state_send_system_event(int status) bundle_free(b); } -static void parse_property_systemd_unit(gpointer data, gpointer udata) -{ - struct section_property *prop = (struct section_property *) data; - struct service_config *svc = (struct service_config *) udata; - - if (MATCH(prop->key, "Service")) { - strncpy(svc->name, prop->value, sizeof(svc->name) - 1); - svc->name[sizeof(svc->name) - 1] = '\0'; - } else if (MATCH(prop->key, "RemainAfterDisable")) { - svc->remain_after_disable = MATCH(prop->value, "yes"); - } -} - -static unsigned int parse_usb_function(char *fstr) -{ - // Parse Function=, e.g., "Function=diag,acm" - unsigned int ret = USB_FUNCTION_NONE; - char *p, *saveptr; - - if (!fstr) - return ret; - - p = strtok_r(fstr, ",", &saveptr); - if (!p) - return ret; - - do { - if (strncasecmp(p, "mtp", sizeof("mtp")) == 0) { - ret |= USB_FUNCTION_MTP; - } else if (strncasecmp(p, "acm", sizeof("acm")) == 0) { - ret |= USB_FUNCTION_ACM; - } else if(strncasecmp(p, "sdb", sizeof("sdb")) == 0) { - ret |= USB_FUNCTION_SDB; - } else if (strncasecmp(p, "rndis", sizeof("rndis")) == 0) { - ret |= USB_FUNCTION_RNDIS; - } else if (strncasecmp(p, "diag", sizeof("diag")) == 0) { - ret |= USB_FUNCTION_DIAG; - } else if (strncasecmp(p, "conngadget", sizeof("conngadget")) == 0) { - ret |= USB_FUNCTION_CONN_GADGET; - } else if (strncasecmp(p, "dm", sizeof("dm")) == 0) { - ret |= USB_FUNCTION_DM; - } else if (strncasecmp(p, "rmnet", sizeof("rmnet")) == 0) { - ret |= USB_FUNCTION_RMNET; - } - } while ((p = strtok_r(NULL, ",", &saveptr))); - - return ret; -} - -static void parse_property_attribute(gpointer data, gpointer udata) -{ - struct section_property *prop = (struct section_property *) data; - struct _usb_mode_mapping_table *table = (struct _usb_mode_mapping_table *) udata; - unsigned int value; - - if (MATCH(prop->key, "Mode")) { - sscanf(prop->value, "%d", &table->mode_v); - } else if (MATCH(prop->key, "Function")) { - table->mode = parse_usb_function(prop->value); - } else if (MATCH(prop->key, "bDeviceClass")) { - sscanf(prop->value, "%x", &value); - table->attrs.bDeviceClass = (uint8_t) value; - } else if (MATCH(prop->key, "bDeviceSubClass")) { - sscanf(prop->value, "%x", &value); - table->attrs.bDeviceSubClass = (uint8_t) value; - } else if (MATCH(prop->key, "bDeviceProtocol")) { - sscanf(prop->value, "%x", &value); - table->attrs.bDeviceProtocol = (uint8_t) value; - } else if (MATCH(prop->key, "idVendor")) { - sscanf(prop->value, "%x", &value); - table->attrs.idVendor = (uint16_t) value; - } else if (MATCH(prop->key, "idProduct")) { - sscanf(prop->value, "%x", &value); - table->attrs.idProduct = (uint16_t) value; - } else if (MATCH(prop->key, "bcdDevice")) { - sscanf(prop->value, "%x", &value); - table->attrs.bcdDevice = (uint16_t) value; - } -} - -static int load_usb_gadget_config(const struct parse_result *result, void *data) -{ - if (MATCH(result->section, "SystemdUnit")) { - struct service_config svc = { 0, }; - void *entry = NULL; - - g_list_foreach(result->props, parse_property_systemd_unit, &svc); - - entry = malloc(sizeof(struct service_config)); - if (!entry) { - _E("Failed to alloc service config"); - return 0; - } - - _I("usb-gadget service config: name=%s, remain_after_disable=%d", - svc.name, svc.remain_after_disable); - service_config_list = g_list_prepend(service_config_list, memcpy(entry, &svc, sizeof(svc))); - - } else if (MATCH(result->section, "Attribute")) { - struct _usb_mode_mapping_table table = { 0, }; - void *entry = NULL; - - g_list_foreach(result->props, parse_property_attribute, &table); - - // if it hasn't defined mode, use default or pre-defined one - if (table.mode == USB_FUNCTION_NONE) - table.mode = get_mode_bitmap_from_vconf(table.mode_v); - - if (table.mode == USB_FUNCTION_INVALID) - return 0; - - if (table.mode_v >= SET_USB_NONE && table.mode_v <= SET_USB_RNDIS_SDB_ACM) - _W("The custom mode=%d replaces the predefined usb-gadget configuration", table.mode_v); - - entry = malloc(sizeof(struct _usb_mode_mapping_table)); - if (!entry) { - _E("Failed to alloc mapping table"); - return 0; - } - - _I("Custom usb-gadget: mode=%d, function=%#x, idVendor=%#x, idProduct=%#x", - table.mode_v, table.mode, table.attrs.idVendor, table.attrs.idProduct); - - usb_mode_mapping_table_custom = g_list_prepend(usb_mode_mapping_table_custom, memcpy(entry, &table, sizeof(table))); - } - - return 0; -} - -void usb_state_load_custom_mode(void) -{ - libsys_config_parse_by_section(PATH_USB_GADGET_CONF, load_usb_gadget_config, NULL); -} - void usb_state_retrieve_selected_mode(void) { - int mode_v; - unsigned int mode; - const unsigned int default_mode = USB_FUNCTION_MTP | USB_FUNCTION_ACM; + int mode; + const unsigned int default_mode = USB_GADGET_FUNC_MTP | USB_GADGET_FUNC_ACM; - /* Never return here because deviced must never run in USB_FUNCTION_NONE mode */ - if (vconf_get_int(VCONFKEY_USB_SEL_MODE, &mode_v) != VCONF_OK) { - mode_v = SET_USB_INVALID; + /* Never return here because deviced must never run in USB_GADGET_FUNC_NONE mode */ + if (vconf_get_int(VCONFKEY_USB_SEL_MODE, &mode) != VCONF_OK) { + mode = USB_GADGET_FUNC_INVALID; _E("Failed to get vconf value for USB sel mode: %d", vconf_get_ext_errno()); } - mode = get_mode_bitmap_from_vconf(mode_v); - /* - * Deviced must never run in USB_FUNCTION_NONE mode. + * Deviced must never run in USB_GADGET_FUNC_NONE mode. * So if vconf value is invalid, deviced uses the default usb mode internally. * Keep the problematic vconf values in order to define the problem correctly. */ switch (mode) { - case USB_FUNCTION_INVALID: /* Invalid vconf */ + case USB_GADGET_FUNC_INVALID: /* Invalid vconf */ usb_selected_mode = default_mode; - _E("Failed to convert vconf to USB mode. There is no mode matches up with vconf %d. Use default mode=%#x.", mode_v, default_mode); + _E("Failed to convert vconf to USB mode. There is no mode matches up with vconf %#x. Use default mode=%#x.", mode, default_mode); break; - case USB_FUNCTION_NONE: /* Invalid vconf */ + case USB_GADGET_FUNC_NONE: /* Invalid vconf */ usb_selected_mode = default_mode; - _E("There is USB_FUNCTION_NONE USB mode matches up with vconf %d. Use default mode=%#x.", mode_v, default_mode); + _E("There is USB_GADGET_FUNC_NONE USB mode matches up with vconf %#x. Use default mode=%#x.", mode, default_mode); break; default: /* Success */ usb_selected_mode = mode; - _I("Succeeded to convert vconf to USB mode. vconf=%d, mode=%#x.", mode_v, mode); + _I("Succeeded to convert vconf to USB mode=%#x", mode); break; } /* To sync with vconf for debug mode */ - set_usb_debug_state((bool)(usb_selected_mode & USB_FUNCTION_SDB)); + set_usb_debug_state((bool)(usb_selected_mode & USB_GADGET_FUNC_SDB)); } /* Cache of vconf_get_int(VCONFKEY_USB_SEL_MODE) */ @@ -352,17 +114,10 @@ unsigned int usb_state_get_selected_mode(void) int usb_state_set_selected_mode(unsigned int mode) { int ret; - int mode_v; usb_selected_mode = mode; - mode_v = get_mode_vconf_from_bitmap(mode); - if (mode_v == SET_USB_INVALID) { - _E("Failed to convert USB selected_mode to vconf. There is no vconf matches up with USB mode %#x", mode); - return -EINVAL; - } - - ret = vconf_set_int(VCONFKEY_USB_SEL_MODE, mode_v); + ret = vconf_set_int(VCONFKEY_USB_SEL_MODE, mode); if (ret != VCONF_OK) _E("Failed to set vconf value for USB selected mode: %d", vconf_get_ext_errno()); @@ -379,24 +134,18 @@ unsigned int usb_state_get_current_mode(void) int usb_state_set_current_mode(unsigned int mode) { int ret = 0; - int mode_v; - static int old_mode_v = -1; + static int old_mode = -1; usb_current_mode = mode; - mode_v = get_mode_vconf_from_bitmap(mode); - if (mode_v == SET_USB_INVALID) { - _E("Failed to convert USB current_mode to vconf. There is no vconf matches up with mode %#x", mode); - return -EINVAL; - } - - if (old_mode_v != mode_v) { - old_mode_v = mode_v; - ret = vconf_set_int(VCONFKEY_USB_CUR_MODE, mode_v); + if (old_mode != mode) { + old_mode = mode; + ret = vconf_set_int(VCONFKEY_USB_CUR_MODE, mode); if (ret < 0) - _E("Failed to set vconf value for USB current mode: %d", vconf_get_ext_errno()); + _E("Failed to set vconf value for USB current mode=%#x, error=%d", mode, vconf_get_ext_errno()); } + return ret; } @@ -458,19 +207,19 @@ static void remove_notification_handler(void) void change_usb_state_notification_handler(unsigned int mode) { - if (mode & USB_FUNCTION_MTP) + if (mode & USB_GADGET_FUNC_MTP) add_notification_handler(); - else if (mode == USB_FUNCTION_NONE) + else if (mode == USB_GADGET_FUNC_NONE) remove_notification_handler(); } /* * USB_DISCONNECTED : VCONFKEY_SYSMAN_USB_DISCONNECTED - * USB_CONNECTED + USB_FUNCTION_NONE : VCONFKEY_SYSMAN_USB_CONNECTED - * USB_CONNECTED + USB_FUNCTION_OOOO : VCONFKEY_SYSMAN_USB_AVAILABLE + * USB_CONNECTED + USB_GADGET_FUNC_NONE : VCONFKEY_SYSMAN_USB_CONNECTED + * USB_CONNECTED + USB_GADGET_FUNC_OOOO : VCONFKEY_SYSMAN_USB_AVAILABLE * * When connecting the usb cable : "disconnected"(previous value) -> "connected" -> "available" - * When disconnecting the usb cable : "available"(previous value) -> "dosconnected" + * When disconnecting the usb cable : "available"(previous value) -> "disconnected" * When changing usb mode : "available"(previous value) -> "connected" -> "available" * * When USB cable is connected but USB initialization fails : It stays "connected" without going to "available" diff --git a/src/usb-gadget/usb-tethering.c b/src/usb-gadget/usb-tethering.c index 76dcb7d..1b952dd 100644 --- a/src/usb-gadget/usb-tethering.c +++ b/src/usb-gadget/usb-tethering.c @@ -24,8 +24,8 @@ #include "core/log.h" #include "shared/device-notifier.h" -#include "usb.h" #include "usb-gadget.h" +#include "usb-gadget-ops.h" static bool tethering_state; @@ -56,18 +56,15 @@ static int usb_tethering_mode_changed(void *on) { int ret; unsigned new_mode; - static unsigned int saved_prev_mode = USB_FUNCTION_NONE; const unsigned int curr_mode = usb_state_get_selected_mode(); - const unsigned int predefined_rndis_mode_off = USB_FUNCTION_ACM | USB_FUNCTION_MTP; - const unsigned int predefined_rndis_mode_on = USB_FUNCTION_ACM | USB_FUNCTION_SDB | USB_FUNCTION_RNDIS; /* - * On: Use predefined mode (USB_FUNCTION_ACM | USB_FUNCTION_SDB | USB_FUNCTION_RNDIS) - * Off: Use predefined mode (USB_FUNCTION_MTP | USB_FUNCTION_ACM) + USB_FUNCTION_SDB(conditional) + * On: Use predefined mode (USB_GADGET_FUNC_ACM | USB_GADGET_FUNC_SDB | USB_GADGET_FUNC_RNDIS) + * Off: Use predefined mode (USB_GADGET_FUNC_MTP | USB_GADGET_FUNC_ACM) + USB_GADGET_FUNC_SDB(conditional) * - * Caution: If usb debug menu was enabled, add USB_FUNCTION_SDB to new mode to use. + * Caution: If usb debug menu was enabled, add USB_GADGET_FUNC_SDB to new mode to use. * - * When tethering is enabled, additionally enable usb debug(USB_FUNCTION_SDB) unconditionally. + * When tethering is enabled, additionally enable usb debug(USB_GADGET_FUNC_SDB) unconditionally. * Since usb debug is always enabled when you turn off usb tethering, there is no way to know if usb debug was enabled or not. * So before enabling usb tethering, save the previous state. * This saved value is used to check if the debug menu was enabled or not when you turn off usb tethering. @@ -75,22 +72,20 @@ static int usb_tethering_mode_changed(void *on) * In addition, if someone changes the usb mode while tethering on, * use the latest usb mode to determine the usb debug mode instead of using the saved value. * + * =================================== + * + * The above policy, which is forcing combination of usb-gadget functions to a predefined set, is not + * mandatory anymore since introduction of usb-gadget bitmap. The usb-gadget bitmap would rather allow + * user to combine any kind of usb-gadget functions. This works in assumption that user knows validity + * of the combination, e.g., mtp would not work properly with rndis. Therefore, the deviced exactly + * does what a user did, not caring about validity of the combination. + * */ - if ((bool)on) { - new_mode = predefined_rndis_mode_on; - saved_prev_mode = curr_mode; - } else { - new_mode = predefined_rndis_mode_off; - - if (curr_mode != predefined_rndis_mode_on) /* someone changes the usb mode while tethering on, use latest usb mode */ - saved_prev_mode = curr_mode; - - if(saved_prev_mode & USB_FUNCTION_SDB) - new_mode |= USB_FUNCTION_SDB; - - saved_prev_mode = USB_FUNCTION_NONE; - } + if ((int)(intptr_t) on) + new_mode = curr_mode | USB_GADGET_FUNC_RNDIS; + else + new_mode = curr_mode & (~USB_GADGET_FUNC_RNDIS); ret = usb_change_mode(new_mode, true); if (ret < 0) diff --git a/src/usb-gadget/usb.c b/src/usb-gadget/usb.c deleted file mode 100644 index 5c6ab63..0000000 --- a/src/usb-gadget/usb.c +++ /dev/null @@ -1,340 +0,0 @@ -/* - * 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/udev.h" -#include "display/poll.h" -#include "display/display-ops.h" -#include "shared/plugin.h" - -#include "usb.h" -#include "usb-gadget.h" -#include "usb-debug.h" -#include "usb-tethering.h" - -static int usb_change_gadget(unsigned mode); - -static struct display_plugin *disp_plgn; - -static int usb_config_init(void) -{ - unsigned int mode = usb_state_get_selected_mode(); - - return usb_change_gadget(mode); -} - -/* Precondition: USB_FUNCTION_NONE */ -static int usb_change_gadget(unsigned mode) -{ - int ret; - - ret = usb_gadget_change_mode(mode); - if (ret) { - /* because usb does not work properly */ - (void)usb_state_set_current_mode(USB_FUNCTION_NONE); - return ret; - } - - _I("USB gadget changed to (%#x)", mode); - - return 0; -} - -/* Precondition: USB_CONNECTED, USB_FUNCTION_NONE */ -static int usb_enable(unsigned int mode) -{ - int ret; - - ret = usb_gadget_enable(); - if (ret < 0) { - _E("Failed to enable USB config: %d", ret); - goto out; - } - - send_usb_state_changed_event(VCONFKEY_SYSMAN_USB_AVAILABLE); - (void)usb_state_set_current_mode(mode); - change_usb_state_notification_handler(mode); - - return 0; - -out: - /* Although this function has a USB_FUNCTION_NONE precondition, it is to protect against coding mistakes. */ - (void)usb_state_set_current_mode(USB_FUNCTION_NONE); /* because usb does not work properly */ - return ret; -} - -/* Precondition: N/A */ -static int usb_disable(void) -{ - int ret; - - (void)usb_state_set_current_mode(USB_FUNCTION_NONE); - change_usb_state_notification_handler(USB_FUNCTION_NONE); - - ret = usb_gadget_disable(); - if (ret < 0) { - _E("Failed to disable USB config: %d", ret); - return ret; - } - - return 0; -} - -/* Precondition: USB_DISCONNECTED (Implicitly contains USB_FUNCTION_NONE) */ -static int usb_connected(void) -{ - int ret; - unsigned int mode = usb_state_get_selected_mode(); - - if (disp_plgn->pm_lock_internal) - disp_plgn->pm_lock_internal(INTERNAL_LOCK_USB, LCD_OFF, STAY_CUR_STATE, 0); - - usb_state_set_connection(USB_CONNECTED); - send_usb_state_changed_event(VCONFKEY_SYSMAN_USB_CONNECTED); - - ret = usb_enable(mode); - if (ret < 0) { - _E("Failed to enable USB gadget(%#x): %d", mode, ret); - return ret; - } - - return 0; -} - -/* Precondition: USB_CONNECTED */ -static int usb_disconnected(void) -{ - int ret; - - usb_state_set_connection(USB_DISCONNECTED); - send_usb_state_changed_event(VCONFKEY_SYSMAN_USB_DISCONNECTED); - - ret = usb_disable(); - if(ret < 0) { - _E("Failed to disable USB gadget: %d", ret); - /* Important: You have to keep going to unlock disp_plgn->pm_unlock_internal */ - } - - if (disp_plgn->pm_unlock_internal) - disp_plgn->pm_unlock_internal(INTERNAL_LOCK_USB, LCD_OFF, STAY_CUR_STATE); - - return ret; -} - -/* Called by dbus signal and vconf change(tethering, debug mode) */ -int usb_change_mode(unsigned int new_mode, bool change_debug_mode) -{ - int ret; - const unsigned int curr_mode = usb_state_get_current_mode(); - const unsigned int prev_mode = usb_state_get_selected_mode(); - - if (prev_mode == new_mode) { - _I("already using USB mode(%#x), current running mode (%#x)", prev_mode, curr_mode); - return 0; - } - - _I("USB change mode (%#x) -> (%#x), current running mode (%#x)", prev_mode, new_mode, curr_mode); - - /* - * When you change the gadget(usb_change_gadget) for new usb mode, you must disable the gadget first. - * - * Even if the usb cable is plugged in, the current mode may be NULL due to usb fail. - * So to find out which mode you are in, you should use the current mode, not the selected mode. - */ - if (curr_mode != USB_FUNCTION_NONE) { - /* Special case: Because usb gadget is disabled, temporarily switch usb state from available to connected. */ - send_usb_state_changed_event(VCONFKEY_SYSMAN_USB_CONNECTED); - - ret = usb_disable(); - if (ret < 0) { - _E("Failed to disable current USB mode."); - return ret; - } - } - - /* - * You should always change the gadget once when the usb mode is changed. - * In this state, usb_enable() is called when the usb cable is connected - * and usb_disable() is called when the usb cable is disconnected. - */ - ret = usb_change_gadget(new_mode); - if (ret < 0) { - _E("Failed to change USB gadget: %d", ret); - return ret; - } - - if (usb_state_get_connection() == USB_CONNECTED) { - ret = usb_enable(new_mode); - if (ret < 0) { - _E("Failed to enable USB mode: %d", ret); - return ret; - } - } - - /* If you success to change the runtime usb configuration, do change the selected mode. */ - (void)usb_state_set_selected_mode(new_mode); - - /* To sync with vconf for debug mode */ - if (change_debug_mode) - set_usb_debug_state((bool)(new_mode & USB_FUNCTION_SDB)); - - return 0; -} - -/* Called by extcon udev event */ -static int usb_state_changed(const char *index, int new_status) -{ - int ret = -1; - static int old_status = -1; /* -1: Uninitialized, 0: disconnected, 1: connected */ - - /* For debugging. Do not move the location. */ - _I("USB state is changed by extcon from (%d) to (%d).", old_status, new_status); - - if (old_status == new_status) - return 0; - - switch (new_status) { - case USB_CONNECTED: - ret = usb_connected(); - break; - - case USB_DISCONNECTED: - if (old_status == -1) { - /* only initialize the internal data state and skip usb hal operation. */ - _I("USB is initialized without USB connection"); - - /* From usb_disconnected() */ - usb_state_set_connection(USB_DISCONNECTED); - send_usb_state_changed_event(VCONFKEY_SYSMAN_USB_DISCONNECTED); - - /* From usb_disable() */ - (void)usb_state_set_current_mode(USB_FUNCTION_NONE); - change_usb_state_notification_handler(USB_FUNCTION_NONE); - - ret = 0; - } else - ret = usb_disconnected(); - break; - - default: - _E("Invalid USB state(%d).", new_status); - return -EINVAL; - } - - if (ret < 0) { - _E("Failed to operate USB connection: %d", ret); - return ret; - } - - old_status = new_status; - - return ret; -} - -static void uevent_usb_mode_handler(struct udev_device *dev) -{ - const char *state = NULL; - - state = udev_device_get_property_value(dev, "USB_STATE"); - if (!state) - return; - - if (strncmp(state, "CONFIGURED", strlen(state) + 1)) - return; - - _I("USB udev event happend : CONFIGURED USB_STATE"); - - if (usb_state_get_selected_mode() & USB_FUNCTION_ACM) - systemd_start_unit_wait_started ("data-router.service", NULL, -1); - - if (usb_state_get_selected_mode() & USB_FUNCTION_SDB) - systemd_start_unit_wait_started ("sdbd.service", NULL, -1); - - if (usb_state_get_selected_mode() & USB_FUNCTION_MTP) - systemd_start_unit_wait_started ("mtp-responder.service", NULL, -1); -} - -static struct uevent_handler uh = { - .subsystem = "usb_mode", - .uevent_func = uevent_usb_mode_handler, -}; - -static void usb_init(void *data) -{ - int ret; - - usb_state_load_custom_mode(); - usb_state_retrieve_selected_mode(); - - ret = usb_gadget_init(); - if (ret < 0) { - CRITICAL_LOG("USB client cannot be used: %d", ret); - return; - } - - ret = usb_config_init(); - if (ret < 0) - _E("Failed to initialize USB configuation."); - - ret = register_udev_uevent_control(&uh); - if (ret < 0) - _E("Failed to register udev event(%d) for USB", ret); - - ret = usb_dbus_init(); - if (ret < 0) - _E("Failed to init dbus(%d) for USB", ret); - - add_usb_tethering_handler(); - add_usb_debug_handler(); -} - -static void usb_exit(void *data) -{ - remove_usb_debug_handler(); - remove_usb_tethering_handler(); - - usb_state_set_connection(USB_DISCONNECTED); - send_usb_state_changed_event(VCONFKEY_SYSMAN_USB_DISCONNECTED); - (void)usb_state_set_current_mode(USB_FUNCTION_NONE); - change_usb_state_notification_handler(USB_FUNCTION_NONE); - - unregister_udev_uevent_control(&uh); - usb_gadget_disable(); - usb_gadget_exit(); - -} - -static struct extcon_ops extcon_usb_ops = { - .name = EXTCON_CABLE_USB, - .init = usb_init, - .exit = usb_exit, - .update = usb_state_changed, -}; - -EXTCON_OPS_REGISTER(extcon_usb_ops) - -static void __CONSTRUCTOR__ initialize(void) -{ - disp_plgn = get_var_display_plugin(); - if (!disp_plgn) - _E("Failed to get display plugin variable."); -} diff --git a/src/usb-gadget/usb.h b/src/usb-gadget/usb.h deleted file mode 100644 index 0e30b2e..0000000 --- a/src/usb-gadget/usb.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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 __DEVICED_USB_H__ -#define __DEVICED_USB_H__ - -#include -#include -#include "extcon/extcon.h" - -#define USB_FUNCTION_INVALID UINT_MAX -#define SET_USB_INVALID INT_MAX - -int usb_dbus_init(void); - -void usb_state_load_custom_mode(void); - -int usb_change_mode(unsigned int mode, bool change_debug_mode); -void usb_state_retrieve_selected_mode(void); -unsigned int get_mode_bitmap_from_vconf(int mode_v); - -void broadcast_usb_state_changed(void); -void send_usb_state_changed_event(int status); -void change_usb_state_notification_handler(unsigned int mode); - -unsigned int usb_state_get_selected_mode(void); -int usb_state_set_selected_mode(unsigned int mode); - -unsigned int usb_state_get_current_mode(void); -int usb_state_set_current_mode(unsigned int mode); - -extcon_usb_state_e usb_state_get_connection(void); -void usb_state_set_connection(extcon_usb_state_e conn); - -#endif /* __USB_CLIENT_H__ */ -- 2.7.4 From f1a8ac03bb44221943cdd032f65e1e6cc917d543 Mon Sep 17 00:00:00 2001 From: Youngjae Cho Date: Mon, 2 May 2022 17:06:31 +0900 Subject: [PATCH 07/16] usb-gadget: add dummy operations for emulator Change-Id: I6491d3b918073ab9990a8c6d065c64badcf40d73 Signed-off-by: Youngjae Cho --- src/usb-gadget/usb-gadget-ops.c | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/src/usb-gadget/usb-gadget-ops.c b/src/usb-gadget/usb-gadget-ops.c index 14d7a20..ededc18 100644 --- a/src/usb-gadget/usb-gadget-ops.c +++ b/src/usb-gadget/usb-gadget-ops.c @@ -8,6 +8,7 @@ #include #include +#include #include "usb-gadget-ops.h" #include "usb-gadget-cfs-ops.h" @@ -37,6 +38,31 @@ static GList *service_config_list; static char board_serial[128] = "01234TEST"; +static int dummy_usb_gadget_open(void) +{ + return 0; +} + +static int dummy_usb_gadget_close(void) +{ + return 0; +} + +static int dummy_usb_gadget_enable(void) +{ + return 0; +} + +static int dummy_usb_gadget_disable(void) +{ + return 0; +} + +static int dummy_usb_gadget_reconfigure(struct usb_gadget *gadget) +{ + return 0; +} + static void rndis_handler(int enable) { if (enable) @@ -459,7 +485,13 @@ int usb_gadget_ops_init(void) libsys_config_parse_by_section(PATH_USB_GADGET_CONF, load_usb_gadget_config, NULL); - if (usb_gadget_legacy_supported()) { + if (is_emulator()) { + __usb_gadget_open = dummy_usb_gadget_open; + __usb_gadget_close = dummy_usb_gadget_close; + __usb_gadget_enable = dummy_usb_gadget_enable; + __usb_gadget_disable = dummy_usb_gadget_disable; + __usb_gadget_reconfigure = dummy_usb_gadget_reconfigure; + } else if (usb_gadget_legacy_supported()) { usb_gadget_bind_legacy_ops(&__usb_gadget_open, &__usb_gadget_close, &__usb_gadget_enable, -- 2.7.4 From 490f2cc3375d071c5a1a5aeb4879aaced1477541 Mon Sep 17 00:00:00 2001 From: SangYoun Kwak Date: Mon, 2 May 2022 14:37:12 +0900 Subject: [PATCH 08/16] Add new command to get current partition and modify switch-partition command Change-Id: I32bfe926c07ae82db5c977a889c7302e03a207a8 Signed-off-by: SangYoun Kwak --- packaging/deviced.spec | 1 + tools/board/CMakeLists.txt | 1 + tools/board/clear-partition-ab-cloned.c | 2 +- tools/board/get-current-partition.c | 37 +++++++++++++++++++++++++++++++++ tools/board/get-partition-ab-cloned.c | 2 +- tools/board/get-upgrade-status.c | 2 +- tools/board/set-partition-ab-cloned.c | 2 +- tools/board/set-upgrade-status.c | 2 +- tools/board/switch-partition.c | 14 +++++++------ 9 files changed, 52 insertions(+), 11 deletions(-) create mode 100644 tools/board/get-current-partition.c diff --git a/packaging/deviced.spec b/packaging/deviced.spec index 5d19ec8..4fdeb7a 100644 --- a/packaging/deviced.spec +++ b/packaging/deviced.spec @@ -325,6 +325,7 @@ mv %{_libdir}/iot-headless-battery.so %{_libdir}/deviced/battery.so %attr(0554,system_fw,system_fw) %{_bindir}/device_board_set_boot_success %attr(0554,system_fw,system_fw) %{_bindir}/device_board_clear_boot_mode %attr(0555,system_fw,system_fw) %{_bindir}/device_board_get_boot_mode +%attr(0554,system_fw,system_fw) %{_bindir}/device_board_get_current_partition %attr(0554,system_fw,system_fw) %{_bindir}/device_board_switch_partition %attr(0554,system_fw,system_fw) %{_bindir}/device_board_set_partition_ab_cloned %attr(0554,system_fw,system_fw) %{_bindir}/device_board_clear_partition_ab_cloned diff --git a/tools/board/CMakeLists.txt b/tools/board/CMakeLists.txt index 533901d..83c1d31 100644 --- a/tools/board/CMakeLists.txt +++ b/tools/board/CMakeLists.txt @@ -19,6 +19,7 @@ ADD_BOOT_EXECUTABLE(device_board_set_boot_success set-boot-success.c) ADD_BOOT_EXECUTABLE(device_board_clear_boot_mode clear-boot-mode.c) ADD_BOOT_EXECUTABLE(device_board_get_boot_mode get-boot-mode.c) +ADD_BOOT_EXECUTABLE(device_board_get_current_partition get-current-partition.c) ADD_BOOT_EXECUTABLE(device_board_switch_partition switch-partition.c) ADD_BOOT_EXECUTABLE(device_board_clear_partition_ab_cloned clear-partition-ab-cloned.c) ADD_BOOT_EXECUTABLE(device_board_get_partition_ab_cloned get-partition-ab-cloned.c) diff --git a/tools/board/clear-partition-ab-cloned.c b/tools/board/clear-partition-ab-cloned.c index 6c4437d..7311b05 100644 --- a/tools/board/clear-partition-ab-cloned.c +++ b/tools/board/clear-partition-ab-cloned.c @@ -1,5 +1,5 @@ /* - * device-board-get-boot-mode + * device-board-clear-partition-ab-cloned * * Copyright (c) 2022 Samsung Electronics Co., Ltd. All rights reserved. * diff --git a/tools/board/get-current-partition.c b/tools/board/get-current-partition.c new file mode 100644 index 0000000..23f1177 --- /dev/null +++ b/tools/board/get-current-partition.c @@ -0,0 +1,37 @@ +/* + * device-board-get-current-partition + * + * Copyright (c) 2022 Samsung Electronics Co., Ltd. All rights reserved. + * + * 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 + +int main(int argc, char *argv[]) +{ + char partition_ab; + int ret; + + ret = hal_device_board_get_current_partition(&partition_ab); + + if(ret < 0) { + printf("FAILURE\n"); + return 1; + } + + printf("%c\n", partition_ab); + return 0; +} diff --git a/tools/board/get-partition-ab-cloned.c b/tools/board/get-partition-ab-cloned.c index d843930..2de6932 100644 --- a/tools/board/get-partition-ab-cloned.c +++ b/tools/board/get-partition-ab-cloned.c @@ -1,5 +1,5 @@ /* - * device-board-get-boot-mode + * device-board-get-partition-ab-cloned * * Copyright (c) 2022 Samsung Electronics Co., Ltd. All rights reserved. * diff --git a/tools/board/get-upgrade-status.c b/tools/board/get-upgrade-status.c index f66ad36..860f01a 100644 --- a/tools/board/get-upgrade-status.c +++ b/tools/board/get-upgrade-status.c @@ -1,5 +1,5 @@ /* - * device-board-get-boot-mode + * device-board-get-upgrade-status * * Copyright (c) 2022 Samsung Electronics Co., Ltd. All rights reserved. * diff --git a/tools/board/set-partition-ab-cloned.c b/tools/board/set-partition-ab-cloned.c index 941fe0d..6bc927e 100644 --- a/tools/board/set-partition-ab-cloned.c +++ b/tools/board/set-partition-ab-cloned.c @@ -1,5 +1,5 @@ /* - * device-board-get-boot-mode + * device-board-set-partition-ab-cloned * * Copyright (c) 2022 Samsung Electronics Co., Ltd. All rights reserved. * diff --git a/tools/board/set-upgrade-status.c b/tools/board/set-upgrade-status.c index 6080d63..c0810e4 100644 --- a/tools/board/set-upgrade-status.c +++ b/tools/board/set-upgrade-status.c @@ -1,5 +1,5 @@ /* - * device-board-switch-partition + * device-board-set-upgrade-status * * Copyright (c) 2022 Samsung Electronics Co., Ltd. All rights reserved. * diff --git a/tools/board/switch-partition.c b/tools/board/switch-partition.c index 973e4ac..639a29f 100644 --- a/tools/board/switch-partition.c +++ b/tools/board/switch-partition.c @@ -27,12 +27,14 @@ int main(int argc, char *argv[]) int ret; if(argc < 2) { - goto err; - } - - partition_ab = argv[1][0]; - if(partition_ab != 'a' && partition_ab != 'b') { - goto err; + /* toggle partition */ + partition_ab = '\0'; + } else { + partition_ab = argv[1][0]; + + if(partition_ab != 'a' && partition_ab != 'b') { + goto err; + } } ret = hal_device_board_switch_partition(partition_ab); -- 2.7.4 From 27edc1ad0dddbb25f64fae3699c3bad76e215678 Mon Sep 17 00:00:00 2001 From: SangYoun Kwak Date: Tue, 3 May 2022 18:03:15 +0900 Subject: [PATCH 09/16] Add new command to set/get partition status Change-Id: Idbbed070614b0d4438ad71a34f50c406e86f9c16 Signed-off-by: SangYoun Kwak --- packaging/deviced.spec | 2 ++ tools/board/CMakeLists.txt | 2 ++ tools/board/get-partition-status.c | 51 +++++++++++++++++++++++++++ tools/board/set-partition-status.c | 72 ++++++++++++++++++++++++++++++++++++++ tools/board/switch-partition.c | 1 - 5 files changed, 127 insertions(+), 1 deletion(-) create mode 100644 tools/board/get-partition-status.c create mode 100644 tools/board/set-partition-status.c diff --git a/packaging/deviced.spec b/packaging/deviced.spec index 4fdeb7a..378d02d 100644 --- a/packaging/deviced.spec +++ b/packaging/deviced.spec @@ -330,6 +330,8 @@ mv %{_libdir}/iot-headless-battery.so %{_libdir}/deviced/battery.so %attr(0554,system_fw,system_fw) %{_bindir}/device_board_set_partition_ab_cloned %attr(0554,system_fw,system_fw) %{_bindir}/device_board_clear_partition_ab_cloned %attr(0555,system_fw,system_fw) %{_bindir}/device_board_get_partition_ab_cloned +%attr(0555,system_fw,system_fw) %{_bindir}/device_board_set_partition_status +%attr(0555,system_fw,system_fw) %{_bindir}/device_board_get_partition_status %attr(0554,system_fw,system_fw) %{_bindir}/device_board_set_upgrade_status %attr(0555,system_fw,system_fw) %{_bindir}/device_board_get_upgrade_status diff --git a/tools/board/CMakeLists.txt b/tools/board/CMakeLists.txt index 83c1d31..a87ccc0 100644 --- a/tools/board/CMakeLists.txt +++ b/tools/board/CMakeLists.txt @@ -24,6 +24,8 @@ ADD_BOOT_EXECUTABLE(device_board_switch_partition switch-partition.c) ADD_BOOT_EXECUTABLE(device_board_clear_partition_ab_cloned clear-partition-ab-cloned.c) ADD_BOOT_EXECUTABLE(device_board_get_partition_ab_cloned get-partition-ab-cloned.c) ADD_BOOT_EXECUTABLE(device_board_set_partition_ab_cloned set-partition-ab-cloned.c) +ADD_BOOT_EXECUTABLE(device_board_get_partition_status get-partition-status.c) +ADD_BOOT_EXECUTABLE(device_board_set_partition_status set-partition-status.c) ADD_BOOT_EXECUTABLE(device_board_set_upgrade_status set-upgrade-status.c) ADD_BOOT_EXECUTABLE(device_board_get_upgrade_status get-upgrade-status.c) diff --git a/tools/board/get-partition-status.c b/tools/board/get-partition-status.c new file mode 100644 index 0000000..20b6938 --- /dev/null +++ b/tools/board/get-partition-status.c @@ -0,0 +1,51 @@ +/* + * device-board-get-partition-status + * + * Copyright (c) 2022 Samsung Electronics Co., Ltd. All rights reserved. + * + * 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 + +int main(int argc, char *argv[]) +{ + char buffer[1024] = { 0, }; + char partition_ab; + int ret; + + if (argc < 2) { + partition_ab = '\0'; + } else { + partition_ab = argv[1][0]; + + if (partition_ab != 'a' && partition_ab != 'b') { + goto err; + } + } + + ret = hal_device_board_get_partition_status(partition_ab, buffer, sizeof(buffer)); + + if (ret < 0) { + goto err; + } + + printf("%s\n", buffer); + return 0; + +err: + printf("FAILURE\n"); + return 1; +} diff --git a/tools/board/set-partition-status.c b/tools/board/set-partition-status.c new file mode 100644 index 0000000..467bae6 --- /dev/null +++ b/tools/board/set-partition-status.c @@ -0,0 +1,72 @@ +/* + * device-board-set-partition-status + * + * Copyright (c) 2022 Samsung Electronics Co., Ltd. All rights reserved. + * + * 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 + +#define AVAILABLE_STATUS_NUM 3 + +int main(int argc, char *argv[]) +{ + const char *available_status[AVAILABLE_STATUS_NUM] = { "ok", "failed", "corrupted" }; + const char *status; + int is_status_available; + char partition_ab; + int ret; + + if (argc < 2) { + goto err; + } else if (argc == 2) { + partition_ab = '\0'; + status = argv[1]; + } else { + partition_ab = argv[1][0]; + status = argv[2]; + + if (partition_ab != 'a' && partition_ab != 'b') { + goto err; + } + } + + is_status_available = 0; + for (int i = 0; i < AVAILABLE_STATUS_NUM; ++i) { + if (!strncmp(status, available_status[i], strlen(available_status[i]))) { + is_status_available = 1; + break; + } + } + + if (!is_status_available) { + goto err; + } + + ret = hal_device_board_set_partition_status(partition_ab, status); + + if(ret < 0) { + goto err; + } + + printf("SUCCESS\n"); + return 0; + +err: + printf("FAILURE\n"); + return 1; +} diff --git a/tools/board/switch-partition.c b/tools/board/switch-partition.c index 639a29f..0c7fa6f 100644 --- a/tools/board/switch-partition.c +++ b/tools/board/switch-partition.c @@ -18,7 +18,6 @@ */ #include -#include #include int main(int argc, char *argv[]) -- 2.7.4 From eaad5947a1d52f17f958a3e18f318167b93ecc26 Mon Sep 17 00:00:00 2001 From: Youngjae Cho Date: Mon, 9 May 2022 13:56:22 +0900 Subject: [PATCH 10/16] usb-gadget: fix usb-gadget configuration parsing The section [SystemdUnit] is now properly applied. Change-Id: I204d2fb7bee19b0dfac1feebe0c2876051b0937c Signed-off-by: Youngjae Cho --- src/usb-gadget/usb-gadget-ops.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/src/usb-gadget/usb-gadget-ops.c b/src/usb-gadget/usb-gadget-ops.c index ededc18..6d7872c 100644 --- a/src/usb-gadget/usb-gadget-ops.c +++ b/src/usb-gadget/usb-gadget-ops.c @@ -34,7 +34,6 @@ struct service_config { char name[128]; int remain_after_disable; /* do not stop the service on disabling usb-gadget function */ }; -static GList *service_config_list; static char board_serial[128] = "01234TEST"; @@ -128,6 +127,20 @@ struct usb_function *find_usb_function_by_name_instance(const char *name, const return NULL; } +static struct usb_function *find_usb_function_by_service_name(const char *service) +{ + int i; + + if(!service || !service[0]) + return NULL; + + for (i = 0; available_funcs[i]; ++i) + if (!strcmp(service, available_funcs[i]->service)) + return available_funcs[i]; + + return NULL; +} + static void simple_cleanup_config(struct usb_configuration *config) { if (!config) @@ -439,20 +452,16 @@ static int load_usb_gadget_config(const struct parse_result *result, void *data) { if (MATCH(result->section, "SystemdUnit")) { struct service_config svc = { 0, }; - void *entry = NULL; + struct usb_function *func; g_list_foreach(result->props, parse_property_systemd_unit, &svc); - entry = malloc(sizeof(struct service_config)); - if (!entry) { - _E("Failed to alloc service config"); - return 0; + func = find_usb_function_by_service_name(svc.name); + if (func) { + _I("usb-gadget service config: name=%s, remain_after_disable=%d", + svc.name, svc.remain_after_disable); + func->remain_after_disable = svc.remain_after_disable; } - - _I("usb-gadget service config: name=%s, remain_after_disable=%d", - svc.name, svc.remain_after_disable); - service_config_list = g_list_prepend(service_config_list, memcpy(entry, &svc, sizeof(svc))); - } else if (MATCH(result->section, "Attribute")) { struct usb_gadget_config gc = { 0, }; void *entry = NULL; -- 2.7.4 From b7c7cb5e26b13fd8f0b885daf08e09428aa998f1 Mon Sep 17 00:00:00 2001 From: Youngjae Cho Date: Fri, 1 Apr 2022 17:25:40 +0900 Subject: [PATCH 11/16] power: refactor power operations Fix wake lock/unlock operation to have prefix of "power". And it replaces indirect invocation through device_notify(), which is often in iot-headless. Add functions for add/remove poweroff wait for internal usage. It is similar to the existing add/remove dbus methods, but only differs in that the function can be invoked by the deviced itself. Change-Id: Ide3ceb5f894b376901637992d66401a110eafbf0 Signed-off-by: Youngjae Cho --- plugins/iot-headed/display/core.c | 10 ++-- plugins/iot-headless/power/power-dbus.c | 27 +++------- plugins/iot-headless/power/power-state-manager.c | 15 +++--- plugins/mobile/display/core.c | 10 ++-- plugins/tv/display/core.c | 10 ++-- plugins/wearable/display/core.c | 10 ++-- src/display/core.h | 21 +------- src/power/power-control.c | 48 ++++------------- src/power/power-control.h | 27 ++++++++-- src/power/power-handler.c | 67 +++++++++++++++--------- src/power/power-handler.h | 6 ++- src/shared/device-notifier.h | 4 -- 12 files changed, 116 insertions(+), 139 deletions(-) diff --git a/plugins/iot-headed/display/core.c b/plugins/iot-headed/display/core.c index 71376ad..12cad43 100644 --- a/plugins/iot-headed/display/core.c +++ b/plugins/iot-headed/display/core.c @@ -722,7 +722,7 @@ void lcd_on_direct(enum device_flags flags) if (pm_get_power_lock_support() && (get_pm_cur_state() == S_SLEEP)) { broadcast_pm_wakeup(); - pm_power_lock(); + power_acquire_wakelock(); set_pm_cur_state(S_NORMAL); } @@ -1446,7 +1446,7 @@ static int default_action(int timeout) if ((get_pm_cur_state() != get_pm_old_state()) && (get_pm_cur_state() != S_SLEEP)) { if (pm_get_power_lock_support()) { broadcast_pm_wakeup(); - pm_power_lock(); + power_acquire_wakelock(); } set_setting_pmstate(get_pm_cur_state()); pm_cur_state = get_pm_cur_state(); @@ -1532,9 +1532,9 @@ go_suspend: #endif broadcast_pm_suspend(); if (pm_get_power_lock_support()) { - pm_enable_autosleep(); + power_enable_autosleep(); - if (pm_power_unlock() < 0) + if (power_release_wakelock() < 0) _E("Power unlock state error."); } else { pm_suspend(); @@ -2178,7 +2178,7 @@ static void display_init(void *data) _I("Start Power managing without noti"); if (pm_get_power_lock_support()) { broadcast_pm_wakeup(); - pm_power_lock(); + power_acquire_wakelock(); } /* * Lock lcd off until booting is done. diff --git a/plugins/iot-headless/power/power-dbus.c b/plugins/iot-headless/power/power-dbus.c index 8143f3c..0cbc34f 100644 --- a/plugins/iot-headless/power/power-dbus.c +++ b/plugins/iot-headless/power/power-dbus.c @@ -30,6 +30,7 @@ #include "shared/log.h" #include "shared/device-notifier.h" +#include "power/power-control.h" #include "power-state-manager.h" #include "power-state-wait.h" @@ -58,23 +59,6 @@ static void print_lock_node(void) node->pid, node->comm, node->locktime, node->timeout); } -/* check the lock_list is empty. - * if it is, then request wake unlock */ -static void try_wake_unlock(void) -{ - if (SYS_G_LIST_LENGTH(lock_list) == 0) - device_notify(DEVICE_NOTIFIER_REQUEST_WAKE_UNLOCK, NULL); - else - print_lock_node(); -} - -static void try_wake_lock(void) -{ - device_notify(DEVICE_NOTIFIER_REQUEST_WAKE_LOCK, NULL); -} - -/* remove given node from lock list. - * after removing the node, request wake unlock if possible */ static void remove_lock_node(struct lock_node *node) { if (!node) @@ -88,7 +72,12 @@ static void remove_lock_node(struct lock_node *node) SYS_G_LIST_REMOVE(lock_list, node); free(node); - try_wake_unlock(); + /* Check the lock_list is empty after removing the node. + * If it is, then request wake unlock */ + if (SYS_G_LIST_LENGTH(lock_list) == 0) + power_release_wakelock(); + else + print_lock_node(); } static gboolean lock_expired_cb(void *data) @@ -190,7 +179,7 @@ static GVariant *dbus_power_lock_cpu(GDBusConnection *conn, } _D("pid=%d(%s) request CPU lock for %dms", pid, node->comm, timeout); - try_wake_lock(); + power_acquire_wakelock(); if (timeout > 0) node->timer_id = g_timeout_add(timeout, lock_expired_cb, node); diff --git a/plugins/iot-headless/power/power-state-manager.c b/plugins/iot-headless/power/power-state-manager.c index a2e90ad..3bf6d42 100644 --- a/plugins/iot-headless/power/power-state-manager.c +++ b/plugins/iot-headless/power/power-state-manager.c @@ -26,6 +26,7 @@ #include "shared/devices.h" #include "shared/device-notifier.h" #include "shared/log.h" +#include "power/power-control.h" #include "power-state-manager.h" #include "power-dbus.h" #include "power-state-wait.h" @@ -58,7 +59,7 @@ static void psm_wake_unlock(void) return; } - device_notify(DEVICE_NOTIFIER_REQUEST_WAKE_UNLOCK, NULL); + power_release_wakelock(); } static void psm_trigger_poweroff(void) @@ -70,7 +71,7 @@ static void psm_trigger_poweroff(void) return; if (power_device->execute) { - device_notify(DEVICE_NOTIFIER_REQUEST_DISABLE_AUTOSLEEP, NULL); + power_disable_autosleep(); power_device->execute("poweroff"); } } @@ -103,7 +104,7 @@ static void psm_transition_start_to_normal(const struct trans_info *ti) { current = PSM_NORMAL; - device_notify(DEVICE_NOTIFIER_REQUEST_WAKE_LOCK, NULL); + power_acquire_wakelock(); broadcast_transition_info(ti); } @@ -113,7 +114,7 @@ static void psm_transition_start_to_sleep(const struct trans_info *ti) current = PSM_SLEEP; - device_notify(DEVICE_NOTIFIER_REQUEST_WAKE_LOCK, NULL); + power_acquire_wakelock(); broadcast_transition_info(ti); waiting = update_change_state_wait(state_transition_counter, ti, psm_wake_unlock); if (waiting > 0) { @@ -150,7 +151,7 @@ static void psm_transition_sleep_to_normal(const struct trans_info *ti) { current = PSM_NORMAL; - device_notify(DEVICE_NOTIFIER_REQUEST_WAKE_LOCK, NULL); + power_acquire_wakelock(); broadcast_transition_info(ti); update_change_state_wait(state_transition_counter, ti, NULL); } @@ -159,7 +160,7 @@ static void psm_transition_sleep_to_sleep(const struct trans_info *ti) { int waiting; - device_notify(DEVICE_NOTIFIER_REQUEST_WAKE_LOCK, NULL); + power_acquire_wakelock(); broadcast_transition_info(ti); waiting = update_change_state_wait(state_transition_counter, ti, psm_wake_unlock); if (waiting > 0) { @@ -277,7 +278,7 @@ static int delayed_init_cb(void *data) /* Deferred autosleep enable, * This prevents system go suspend during booting */ - device_notify(DEVICE_NOTIFIER_REQUEST_ENABLE_AUTOSLEEP, NULL); + power_enable_autosleep(); return 0; } diff --git a/plugins/mobile/display/core.c b/plugins/mobile/display/core.c index 7180885..0f12f68 100644 --- a/plugins/mobile/display/core.c +++ b/plugins/mobile/display/core.c @@ -729,7 +729,7 @@ void lcd_on_direct(enum device_flags flags) if (pm_get_power_lock_support() && (get_pm_cur_state() == S_SLEEP)) { broadcast_pm_wakeup(); - pm_power_lock(); + power_acquire_wakelock(); set_pm_cur_state(S_NORMAL); } @@ -1456,7 +1456,7 @@ static int default_action(int timeout) if ((get_pm_cur_state() != get_pm_old_state()) && (get_pm_cur_state() != S_SLEEP)) { if (pm_get_power_lock_support()) { broadcast_pm_wakeup(); - pm_power_lock(); + power_acquire_wakelock(); } set_setting_pmstate(get_pm_cur_state()); pm_cur_state = get_pm_cur_state(); @@ -1542,9 +1542,9 @@ go_suspend: #endif broadcast_pm_suspend(); if (pm_get_power_lock_support()) { - pm_enable_autosleep(); + power_enable_autosleep(); - if (pm_power_unlock() < 0) + if (power_release_wakelock() < 0) _E("Power unlock state error."); } else { pm_suspend(); @@ -2184,7 +2184,7 @@ static void display_init(void *data) _I("Start Power managing without noti"); if (pm_get_power_lock_support()) { broadcast_pm_wakeup(); - pm_power_lock(); + power_acquire_wakelock(); } /* * Lock lcd off until booting is done. diff --git a/plugins/tv/display/core.c b/plugins/tv/display/core.c index 33b3775..8dcdbea 100644 --- a/plugins/tv/display/core.c +++ b/plugins/tv/display/core.c @@ -722,7 +722,7 @@ void lcd_on_direct(enum device_flags flags) if (pm_get_power_lock_support() && (get_pm_cur_state() == S_SLEEP)) { broadcast_pm_wakeup(); - pm_power_lock(); + power_acquire_wakelock(); set_pm_cur_state(S_NORMAL); } @@ -1446,7 +1446,7 @@ static int default_action(int timeout) if ((get_pm_cur_state() != get_pm_old_state()) && (get_pm_cur_state() != S_SLEEP)) { if (pm_get_power_lock_support()) { broadcast_pm_wakeup(); - pm_power_lock(); + power_acquire_wakelock(); } set_setting_pmstate(get_pm_cur_state()); pm_cur_state = get_pm_cur_state(); @@ -1532,9 +1532,9 @@ go_suspend: #endif broadcast_pm_suspend(); if (pm_get_power_lock_support()) { - pm_enable_autosleep(); + power_enable_autosleep(); - if (pm_power_unlock() < 0) + if (power_release_wakelock() < 0) _E("Power unlock state error."); } else { pm_suspend(); @@ -2175,7 +2175,7 @@ static void display_init(void *data) _I("Start Power managing without noti"); if (pm_get_power_lock_support()) { broadcast_pm_wakeup(); - pm_power_lock(); + power_acquire_wakelock(); } /* * Lock lcd off until booting is done. diff --git a/plugins/wearable/display/core.c b/plugins/wearable/display/core.c index bd6349c..8dd7d48 100644 --- a/plugins/wearable/display/core.c +++ b/plugins/wearable/display/core.c @@ -939,7 +939,7 @@ void lcd_on_direct(enum device_flags flags) if (pm_get_power_lock_support() && (get_pm_cur_state() == S_SLEEP)) { broadcast_pm_wakeup(); - pm_power_lock(); + power_acquire_wakelock(); set_pm_cur_state(S_NORMAL); } @@ -1719,7 +1719,7 @@ static int default_action(int timeout) if ((get_pm_cur_state() != get_pm_old_state()) && (get_pm_cur_state() != S_SLEEP)) { if (pm_get_power_lock_support()) { broadcast_pm_wakeup(); - pm_power_lock(); + power_acquire_wakelock(); } set_setting_pmstate(get_pm_cur_state()); pm_cur_state = get_pm_cur_state(); @@ -1808,9 +1808,9 @@ go_suspend: #endif broadcast_pm_suspend(); if (pm_get_power_lock_support()) { - pm_enable_autosleep(); + power_enable_autosleep(); - if (pm_power_unlock() < 0) + if (power_release_wakelock() < 0) _E("Power unlock state error."); } else { pm_suspend(); @@ -2505,7 +2505,7 @@ static void display_init(void *data) _I("Start Power managing without noti"); if (pm_get_power_lock_support()) { broadcast_pm_wakeup(); - pm_power_lock(); + power_acquire_wakelock(); } /* * Lock lcd off until booting is done. diff --git a/src/display/core.h b/src/display/core.h index 816e00b..c8062ac 100644 --- a/src/display/core.h +++ b/src/display/core.h @@ -53,27 +53,8 @@ #define CHECK_OPS(d, op) (d != NULL && d->op != NULL) #ifdef ENABLE_PM_LOG +#include "power/power-control.h" #define MAX_LOG_COUNT 250 - -enum pm_log_type { - PM_LOG_MIN = 0, - PM_LOG_KEY_PRESS = PM_LOG_MIN, /* key log */ - PM_LOG_KEY_LONG_PRESS, - PM_LOG_KEY_RELEASE, - PM_LOG_LCD_ON, /* lcd log */ - PM_LOG_LCD_ON_COMPLETE, - PM_LOG_LCD_ON_FAIL, - PM_LOG_LCD_DIM, - PM_LOG_LCD_DIM_FAIL, - PM_LOG_LCD_OFF, - PM_LOG_LCD_OFF_COMPLETE, - PM_LOG_LCD_OFF_FAIL, - PM_LOG_LCD_CONTROL_FAIL, - PM_LOG_SLEEP, - PM_LOG_MAX -}; - -void pm_history_save(enum pm_log_type, int); #endif /* diff --git a/src/power/power-control.c b/src/power/power-control.c index 91d07b9..e4dbb1e 100644 --- a/src/power/power-control.c +++ b/src/power/power-control.c @@ -212,20 +212,23 @@ int pm_suspend(void) return 0; } -int pm_enable_autosleep(void) +int power_enable_autosleep(void) { _I("System autosleep enabled."); return sys_set_str(POWER_AUTOSLEEP_PATH, "mem"); } -int pm_disable_autosleep(void) +int power_disable_autosleep(void) { _I("System autosleep disabled."); return sys_set_str(POWER_AUTOSLEEP_PATH, "off"); } -int pm_power_lock(void) +int power_acquire_wakelock(void) { + if (mainlock_status == POWER_LOCK) + return 0; + _I("system power lock"); suspend_other_process(VITAL_WAKEUP); mainlock_status = POWER_LOCK; @@ -259,8 +262,11 @@ out: return power_lock_support; } -int pm_power_unlock(void) +int power_release_wakelock(void) { + if (mainlock_status == POWER_UNLOCK) + return 0; + _I("system power unlock"); suspend_other_process(VITAL_SLEEP); mainlock_status = POWER_UNLOCK; @@ -303,33 +309,6 @@ int set_wakeup_count(int cnt) return 0; } -static int __pm_enable_autosleep(void *data) -{ - return pm_enable_autosleep(); -} - -static int __pm_disable_autosleep(void *data) -{ - - return pm_disable_autosleep(); -} - -static int __pm_power_lock(void *data) -{ - if (mainlock_status == POWER_UNLOCK) - pm_power_lock(); - - return 0; -} - -static int __pm_power_unlock(void *data) -{ - if (mainlock_status == POWER_LOCK) - pm_power_unlock(); - - return 0; -} - static int load_sleep_config(struct parse_result *result, void *user_data) { if (!MATCH(result->section, "PowerState")) @@ -357,13 +336,6 @@ static void power_control_init(void *data) if (check_default(plugin_device_ops)) return; - /* if there is plugin of power-control, - * register notifier for the plugin module */ - register_notifier(DEVICE_NOTIFIER_REQUEST_ENABLE_AUTOSLEEP, __pm_enable_autosleep); - register_notifier(DEVICE_NOTIFIER_REQUEST_DISABLE_AUTOSLEEP, __pm_disable_autosleep); - register_notifier(DEVICE_NOTIFIER_REQUEST_WAKE_LOCK, __pm_power_lock); - register_notifier(DEVICE_NOTIFIER_REQUEST_WAKE_UNLOCK, __pm_power_unlock); - _D("[%s] Initialization.", plugin_device_ops->name); if (plugin_device_ops->init) plugin_device_ops->init(NULL); diff --git a/src/power/power-control.h b/src/power/power-control.h index e4d1a18..ead8e98 100644 --- a/src/power/power-control.h +++ b/src/power/power-control.h @@ -21,7 +21,6 @@ #include "display/core.h" - #define POWER_AUTOSLEEP_PATH "/sys/power/autosleep" #define POWER_LOCK_PATH "/sys/power/wake_lock" #define POWER_UNLOCK_PATH "/sys/power/wake_unlock" @@ -47,6 +46,25 @@ enum vital_state { VITAL_EXIT, }; +enum pm_log_type { + PM_LOG_MIN = 0, + PM_LOG_KEY_PRESS = PM_LOG_MIN, /* key log */ + PM_LOG_KEY_LONG_PRESS, + PM_LOG_KEY_RELEASE, + PM_LOG_LCD_ON, /* lcd log */ + PM_LOG_LCD_ON_COMPLETE, + PM_LOG_LCD_ON_FAIL, + PM_LOG_LCD_DIM, + PM_LOG_LCD_DIM_FAIL, + PM_LOG_LCD_OFF, + PM_LOG_LCD_OFF_COMPLETE, + PM_LOG_LCD_OFF_FAIL, + PM_LOG_LCD_CONTROL_FAIL, + PM_LOG_SLEEP, + PM_LOG_MAX +}; + + extern bool timeout_sleep_support; #ifdef ENABLE_PM_LOG @@ -57,9 +75,10 @@ void pm_history_print(int fd, int count); bool vital_mode(void); int vital_state_changed(void *data); int pm_suspend(void); -int pm_enable_autosleep(void); -int pm_power_lock(void); -int pm_power_unlock(void); +int power_enable_autosleep(void); +int power_disable_autosleep(void); +int power_acquire_wakelock(void); +int power_release_wakelock(void); int pm_get_power_lock(void); int pm_get_power_lock_support(void); int check_wakeup_src(void); diff --git a/src/power/power-handler.c b/src/power/power-handler.c index 9e09401..7464068 100644 --- a/src/power/power-handler.c +++ b/src/power/power-handler.c @@ -331,6 +331,36 @@ static void poweroff_remove_handle(pid_t pid) free(handle); } +static int poweroff_add_handle(pid_t pid) +{ + struct poweroff_handle *handle; + GList *l; + + SYS_G_LIST_FOREACH(poweroff_handles, l, handle) { + if (handle->pid == pid) + break; + } + + if (handle) + poweroff_remove_handle(pid); + + _D("Make a new handle."); + handle = (struct poweroff_handle *)malloc(sizeof(struct poweroff_handle)); + if (handle == NULL) { + _E("Not enough memory."); + return -ENOMEM; + } + + handle->pid = pid; + handle->timeout_id = 0; + handle->timeout = POWEROFF_WAIT_MAX; + + SYS_G_LIST_APPEND(poweroff_handles, handle); + _D("Add a new poweroff timer. pid=%d timeout=%d timeout_id=%d)", handle->pid, handle->timeout, handle->timeout_id); + + return 0; +} + static gboolean poweroff_wait_timeout_cb(void *data) { char timeout[50] = {0,}; @@ -598,10 +628,8 @@ static GVariant *add_poweroff_time(GDBusConnection *conn, const gchar *sender, const gchar *path, const gchar *iface, const gchar *name, GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data) { - struct poweroff_handle *handle; int ret; pid_t pid; - GList *l; if (poweroff_stage >= POWEROFF_WAIT_OTHERS) { _E("It's too late. Poweroff is already in waiting stage."); @@ -617,30 +645,7 @@ static GVariant *add_poweroff_time(GDBusConnection *conn, CRITICAL_LOG("PID %d requested to a poweroff timer.", pid); - SYS_G_LIST_FOREACH(poweroff_handles, l, handle) { - if (handle->pid == pid) - break; - } - - if (handle) - poweroff_remove_handle(pid); - - _D("Make a new handle."); - handle = (struct poweroff_handle *)malloc(sizeof(struct poweroff_handle)); - if (handle == NULL) { - _E("Not enough memory."); - ret = -1; - goto out; - } - - handle->pid = pid; - handle->timeout_id = 0; - handle->timeout = POWEROFF_WAIT_MAX; - - SYS_G_LIST_APPEND(poweroff_handles, handle); - _D("Add a new poweroff timer. pid=%d timeout=%d timeout_id=%d)", handle->pid, handle->timeout, handle->timeout_id); - - ret = 0; + ret = poweroff_add_handle(pid); out: return g_variant_new("(i)", ret); @@ -727,6 +732,16 @@ static int add_poweroff_option(enum poweroff_type type, const char *option) return 0; } +int poweroff_add_wait(pid_t pid) +{ + return poweroff_add_handle(pid); +} + +void poweroff_remove_wait(pid_t pid) +{ + g_idle_add(poweroff_wait_timeout_cb, (void *)(intptr_t) pid); +} + static int load_config(struct parse_result *result, void *user_data) { enum poweroff_type type; diff --git a/src/power/power-handler.h b/src/power/power-handler.h index 48c0927..8c7e16b 100644 --- a/src/power/power-handler.h +++ b/src/power/power-handler.h @@ -19,6 +19,8 @@ #ifndef __POWER_HANDLE_H__ #define __POWER_HANDLE_H__ +#include + #define POWER_OPS_NAME "power" #define POWER_POWEROFF "poweroff" @@ -57,7 +59,9 @@ struct poweroff_handle { }; int check_power_flag(void); -void poweroff(void); void poweroff_request_shutdown(void); +int poweroff_add_wait(pid_t pid); +void poweroff_remove_wait(pid_t pid); + #endif /* __POWER_HANDLE_H__ */ diff --git a/src/shared/device-notifier.h b/src/shared/device-notifier.h index 6ccae1a..3a24a2f 100644 --- a/src/shared/device-notifier.h +++ b/src/shared/device-notifier.h @@ -71,10 +71,6 @@ enum device_notifier_type { /* Purpose of calling methods of different modules * Use prefix DEVICE_NOTIFIER_REQUEST */ - DEVICE_NOTIFIER_REQUEST_ENABLE_AUTOSLEEP, - DEVICE_NOTIFIER_REQUEST_DISABLE_AUTOSLEEP, - DEVICE_NOTIFIER_REQUEST_WAKE_LOCK, - DEVICE_NOTIFIER_REQUEST_WAKE_UNLOCK, DEVICE_NOTIFIER_REQUEST_TRANSITION_STATE, DEVICE_NOTIFIER_MAX, }; -- 2.7.4 From 5b1e838e42a4dae6a6b8ca88ed1b96c0bdea376c Mon Sep 17 00:00:00 2001 From: Youngjae Cho Date: Thu, 12 May 2022 10:49:08 +0900 Subject: [PATCH 12/16] power: elevate iot-headless power plugin to core The power plugin, power-state-manager, has merged into core module and now it administers the whole power module instead of existing power-handler. The power-handler has renamed to power-off to match up with its functionality. Change-Id: I8c93162639d1793635e9b7620ecf4210c4dca23b Signed-off-by: Youngjae Cho --- CMakeLists.txt | 1 - packaging/deviced.spec | 1 - plugins/iot-headed/display/core.c | 8 +- plugins/iot-headed/display/device-interface.c | 2 +- plugins/iot-headed/display/key-filter.c | 4 +- plugins/iot-headless/battery/battery-plugin.c | 2 +- plugins/iot-headless/input/input-config.c | 2 +- plugins/iot-headless/power/CMakeLists.txt | 17 ---- plugins/iot-headless/power/power-config-parse.c | 91 ---------------------- plugins/iot-headless/power/power-config-parse.h | 24 ------ plugins/mobile/display/core.c | 8 +- plugins/mobile/display/device-interface.c | 4 +- plugins/mobile/display/key-filter.c | 4 +- plugins/tv/display/core.c | 8 +- plugins/tv/display/device-interface.c | 2 +- plugins/tv/display/key-filter.c | 4 +- plugins/tv/display/state-tv.c | 6 +- plugins/wearable/display/core.c | 8 +- plugins/wearable/display/device-interface.c | 2 +- plugins/wearable/display/key-filter.c | 4 +- src/battery/lowbat-handler.c | 4 +- src/core/main.c | 6 +- src/display/core.h | 2 +- src/power/{boot.c => power-boot.c} | 83 +++++++++++++++++--- src/power/{boot.h => power-boot.h} | 7 +- {plugins/iot-headless => src}/power/power-dbus.c | 4 +- {plugins/iot-headless => src}/power/power-dbus.h | 2 +- src/power/{doze.c => power-doze.c} | 2 +- src/power/{doze.h => power-doze.h} | 4 +- .../iot-headless => src}/power/power-event-lock.c | 0 .../iot-headless => src}/power/power-event-lock.h | 0 src/power/{power-handler.c => power-off.c} | 48 +++++------- src/power/{power-handler.h => power-off.h} | 15 ++-- .../power/power-state-manager.c | 66 ++++++++-------- .../power/power-state-manager.h | 0 .../iot-headless => src}/power/power-state-wait.c | 5 +- .../iot-headless => src}/power/power-state-wait.h | 0 src/power/{power-control.c => power-suspend.c} | 24 +----- src/power/{power-control.h => power-suspend.h} | 7 +- src/touchscreen/touchscreen.c | 2 +- 40 files changed, 194 insertions(+), 289 deletions(-) delete mode 100644 plugins/iot-headless/power/CMakeLists.txt delete mode 100644 plugins/iot-headless/power/power-config-parse.c delete mode 100644 plugins/iot-headless/power/power-config-parse.h rename src/power/{boot.c => power-boot.c} (60%) rename src/power/{boot.h => power-boot.h} (82%) rename {plugins/iot-headless => src}/power/power-dbus.c (99%) rename {plugins/iot-headless => src}/power/power-dbus.h (94%) rename src/power/{doze.c => power-doze.c} (99%) rename src/power/{doze.h => power-doze.h} (92%) rename {plugins/iot-headless => src}/power/power-event-lock.c (100%) rename {plugins/iot-headless => src}/power/power-event-lock.h (100%) rename src/power/{power-handler.c => power-off.c} (94%) rename src/power/{power-handler.h => power-off.h} (88%) rename {plugins/iot-headless => src}/power/power-state-manager.c (81%) rename {plugins/iot-headless => src}/power/power-state-manager.h (100%) rename {plugins/iot-headless => src}/power/power-state-wait.c (97%) rename {plugins/iot-headless => src}/power/power-state-wait.h (100%) rename src/power/{power-control.c => power-suspend.c} (91%) rename src/power/{power-control.h => power-suspend.h} (93%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6143791..de82918 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -337,7 +337,6 @@ ADD_SUBDIRECTORY(plugins/wearable/display) ADD_SUBDIRECTORY(plugins/tv/display) ADD_SUBDIRECTORY(plugins/iot-headed/display) ADD_SUBDIRECTORY(plugins/iot-headless/input) -ADD_SUBDIRECTORY(plugins/iot-headless/power) ADD_SUBDIRECTORY(plugins/iot-headless/battery) IF(BATTERY_MODULE STREQUAL on) ADD_SUBDIRECTORY(plugins/mobile/battery) diff --git a/packaging/deviced.spec b/packaging/deviced.spec index 378d02d..326d3fd 100644 --- a/packaging/deviced.spec +++ b/packaging/deviced.spec @@ -393,7 +393,6 @@ mv %{_libdir}/iot-headless-battery.so %{_libdir}/deviced/battery.so %config %{_sysconfdir}/deviced/input-profile-iot-headless.conf %config %{_sysconfdir}/deviced/power-profile-iot-headless.conf %{_libdir}/iot-headless-input-handler.so -%{_libdir}/iot-headless-power.so %{_libdir}/iot-headless-battery.so %{_unitdir}/rndis.service %{_bindir}/rndis.sh diff --git a/plugins/iot-headed/display/core.c b/plugins/iot-headed/display/core.c index 12cad43..841818b 100644 --- a/plugins/iot-headed/display/core.c +++ b/plugins/iot-headed/display/core.c @@ -54,10 +54,10 @@ #include "apps/apps.h" #include "extcon/extcon.h" #include "battery/power-supply.h" -#include "power/power-handler.h" -#include "power/power-control.h" -#include "power/boot.h" -#include "power/doze.h" +#include "power/power-off.h" +#include "power/power-suspend.h" +#include "power/power-boot.h" +#include "power/power-doze.h" #include "display-dpms.h" #include "display-signal.h" #include "display-lock.h" diff --git a/plugins/iot-headed/display/device-interface.c b/plugins/iot-headed/display/device-interface.c index 99dba58..bef99b0 100644 --- a/plugins/iot-headed/display/device-interface.c +++ b/plugins/iot-headed/display/device-interface.c @@ -33,7 +33,7 @@ #include #include "ambient-mode.h" -#include "power/power-control.h" +#include "power/power-suspend.h" #include "core/log.h" #include "shared/devices.h" #include "shared/common.h" diff --git a/plugins/iot-headed/display/key-filter.c b/plugins/iot-headed/display/key-filter.c index ec07875..5f0d544 100644 --- a/plugins/iot-headed/display/key-filter.c +++ b/plugins/iot-headed/display/key-filter.c @@ -38,11 +38,11 @@ #include "shared/device-notifier.h" #include "shared/common.h" #include "shared/plugin.h" -#include "power/power-handler.h" +#include "power/power-off.h" +#include "power/power-suspend.h" #include "led/touch-key.h" #include "apps/apps.h" #include "display/display-lock.h" -#include "power/power-control.h" #ifndef KEY_SCREENLOCK #define KEY_SCREENLOCK 0x98 diff --git a/plugins/iot-headless/battery/battery-plugin.c b/plugins/iot-headless/battery/battery-plugin.c index 717fada..2ae0b0b 100644 --- a/plugins/iot-headless/battery/battery-plugin.c +++ b/plugins/iot-headless/battery/battery-plugin.c @@ -25,7 +25,7 @@ #include "shared/log.h" #include "battery/battery-ops.h" -#include "power-state-manager.h" +#include "power/power-state-manager.h" #define BATTERY_CONF_PATH "/etc/deviced/battery.conf" diff --git a/plugins/iot-headless/input/input-config.c b/plugins/iot-headless/input/input-config.c index 4c7be93..ce97c19 100644 --- a/plugins/iot-headless/input/input-config.c +++ b/plugins/iot-headless/input/input-config.c @@ -29,7 +29,7 @@ #include "shared/log.h" #include "input-config.h" -#include "power-state-manager.h" +#include "power/power-state-manager.h" #define INPUT_CONF_PATH "/etc/deviced/input.conf" diff --git a/plugins/iot-headless/power/CMakeLists.txt b/plugins/iot-headless/power/CMakeLists.txt deleted file mode 100644 index 2f9a962..0000000 --- a/plugins/iot-headless/power/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 2.6) - -PROJECT(iot-headless-power C) - -INCLUDE(FindPkgConfig) -PKG_CHECK_MODULES(REQUIRED_PKGS REQUIRED - glib-2.0 - dlog - libsyscommon) - -INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/src) - -FILE(GLOB SRCS "*.c") -ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS}) -SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES PREFIX "") -SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES OUTPUT_NAME iot-headless-power) -INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${LIB_INSTALL_DIR} COMPONENT RuntimeLibraries) diff --git a/plugins/iot-headless/power/power-config-parse.c b/plugins/iot-headless/power/power-config-parse.c deleted file mode 100644 index d846ebc..0000000 --- a/plugins/iot-headless/power/power-config-parse.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * deviced - * - * Copyright (c) 2022 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 "power-state-manager.h" - -#define INIT_CONF_PATH "/etc/deviced/init.conf" - -static struct trans_info initial_transition_info = { - .reason = -1, - .curr = PSM_START, - .next = PSM_NORMAL, -}; - -static void parse_transition_info(const char *action) -{ - char curr[16] = { 0, }; - char next[16] = { 0, }; - - if (sscanf(action, "%15[^,],%15s", curr, next) == 2) { - initial_transition_info.curr = convert_action_string_to_psm_state(curr); - initial_transition_info.next = convert_action_string_to_psm_state(next); - } -} - -static void parse_initial_transition_info(const struct parse_result *result) -{ - GList *elem; - struct section_property *prop; - - SYS_G_LIST_FOREACH(result->props, elem, prop) { - if (MATCH(prop->key, "Enum")) - initial_transition_info.reason = atoi(prop->value); - else if (MATCH(prop->key, "Action")) - parse_transition_info(prop->value); - } -} - -static int parse_matching_bootreason(const struct parse_result *result, void *data) -{ - GList *elem; - struct section_property *prop; - char *bootreason = (char *) data; - - if (!MATCH(result->section, "EventAction")) - return 0; - - SYS_G_LIST_FOREACH(result->props, elem, prop) { - if (MATCH(prop->key, "BootReason") && MATCH(prop->value, bootreason)) - parse_initial_transition_info(result); - } - - return 0; -} - -void parse_initial_transition(void *data) -{ - int retval; - char bootreason[64] = "Unknown"; - GList **head = (GList **) data; - - if (!head) - return; - - retval = hal_device_board_get_boot_reason(bootreason, sizeof(bootreason)); - if (retval == 0) - libsys_config_parse_by_section(INIT_CONF_PATH, parse_matching_bootreason, bootreason); - - CRITICAL_LOG("BootReason=%s", bootreason); - - *head = g_list_append(*head, &initial_transition_info); -} diff --git a/plugins/iot-headless/power/power-config-parse.h b/plugins/iot-headless/power/power-config-parse.h deleted file mode 100644 index a5844b4..0000000 --- a/plugins/iot-headless/power/power-config-parse.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * deviced - * - * Copyright (c) 2022 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 __POWER_CONFIG_PARSE_H__ -#define __POWER_CONFIG_PARSE_H__ - -void parse_initial_transition(void *data); - -#endif //__POWER_CONFIG_PARSE_H__ diff --git a/plugins/mobile/display/core.c b/plugins/mobile/display/core.c index 0f12f68..918ae54 100644 --- a/plugins/mobile/display/core.c +++ b/plugins/mobile/display/core.c @@ -53,10 +53,10 @@ #include "apps/apps.h" #include "extcon/extcon.h" #include "battery/power-supply.h" -#include "power/power-handler.h" -#include "power/power-control.h" -#include "power/boot.h" -#include "power/doze.h" +#include "power/power-off.h" +#include "power/power-suspend.h" +#include "power/power-boot.h" +#include "power/power-doze.h" #include "display/display-dpms.h" #include "proximity.h" #include "display-info.h" diff --git a/plugins/mobile/display/device-interface.c b/plugins/mobile/display/device-interface.c index c66f5bd..28d4f1c 100644 --- a/plugins/mobile/display/device-interface.c +++ b/plugins/mobile/display/device-interface.c @@ -44,8 +44,8 @@ #include "display/display-dpms.h" #include "display/display.h" #include "display/display-lock.h" -#include "power/boot.h" -#include "power/power-control.h" +#include "power/power-boot.h" +#include "power/power-suspend.h" #define TOUCH_ON 1 #define TOUCH_OFF 0 diff --git a/plugins/mobile/display/key-filter.c b/plugins/mobile/display/key-filter.c index c4d5b0a..c596cc1 100644 --- a/plugins/mobile/display/key-filter.c +++ b/plugins/mobile/display/key-filter.c @@ -38,8 +38,8 @@ #include "shared/device-notifier.h" #include "shared/common.h" #include "shared/plugin.h" -#include "power/power-handler.h" -#include "power/power-control.h" +#include "power/power-off.h" +#include "power/power-suspend.h" #include "led/touch-key.h" #include "apps/apps.h" #include "display/display-lock.h" diff --git a/plugins/tv/display/core.c b/plugins/tv/display/core.c index 8dcdbea..61f435a 100644 --- a/plugins/tv/display/core.c +++ b/plugins/tv/display/core.c @@ -53,10 +53,10 @@ #include "apps/apps.h" #include "extcon/extcon.h" #include "battery/power-supply.h" -#include "power/power-handler.h" -#include "power/power-control.h" -#include "power/boot.h" -#include "power/doze.h" +#include "power/power-off.h" +#include "power/power-suspend.h" +#include "power/power-boot.h" +#include "power/power-doze.h" #include "display-dpms.h" #include "display-signal.h" #include "display-lock.h" diff --git a/plugins/tv/display/device-interface.c b/plugins/tv/display/device-interface.c index a67f924..d377ac8 100644 --- a/plugins/tv/display/device-interface.c +++ b/plugins/tv/display/device-interface.c @@ -43,7 +43,7 @@ #include "core.h" #include "display/display-dpms.h" #include "display/display.h" -#include "power/power-control.h" +#include "power/power-suspend.h" #include "display/display-lock.h" #define TOUCH_ON 1 diff --git a/plugins/tv/display/key-filter.c b/plugins/tv/display/key-filter.c index 7f78ef0..dc2c2bd 100644 --- a/plugins/tv/display/key-filter.c +++ b/plugins/tv/display/key-filter.c @@ -38,8 +38,8 @@ #include "shared/device-notifier.h" #include "shared/common.h" #include "shared/plugin.h" -#include "power/power-handler.h" -#include "power/power-control.h" +#include "power/power-off.h" +#include "power/power-suspend.h" #include "led/touch-key.h" #include "apps/apps.h" #include "display/display-lock.h" diff --git a/plugins/tv/display/state-tv.c b/plugins/tv/display/state-tv.c index fc6fb5b..2237011 100644 --- a/plugins/tv/display/state-tv.c +++ b/plugins/tv/display/state-tv.c @@ -26,8 +26,8 @@ #include "shared/devices.h" #include "display/display-ops.h" #include "display/display-lock.h" -#include "power/power-handler.h" -#include "power/power-control.h" +#include "power/power-off.h" +#include "power/power-suspend.h" #include "core.h" #include "poll.h" #include "device-interface.h" @@ -492,7 +492,7 @@ static int poweroff_action(int timeout) { static const struct device_ops *ops; - FIND_DEVICE_INT(ops, POWER_OPS_NAME); + FIND_DEVICE_INT(ops, "power-state-manager"); return ops->execute(POWER_POWEROFF); } diff --git a/plugins/wearable/display/core.c b/plugins/wearable/display/core.c index 8dd7d48..ff2c6e0 100644 --- a/plugins/wearable/display/core.c +++ b/plugins/wearable/display/core.c @@ -54,10 +54,10 @@ #include "apps/apps.h" #include "extcon/extcon.h" #include "battery/power-supply.h" -#include "power/power-handler.h" -#include "power/power-control.h" -#include "power/boot.h" -#include "power/doze.h" +#include "power/power-off.h" +#include "power/power-suspend.h" +#include "power/power-boot.h" +#include "power/power-doze.h" #include "display/display-dpms.h" #include "display-info.h" #include "battery-monitor.h" diff --git a/plugins/wearable/display/device-interface.c b/plugins/wearable/display/device-interface.c index 6f4d30f..8ff62de 100644 --- a/plugins/wearable/display/device-interface.c +++ b/plugins/wearable/display/device-interface.c @@ -46,7 +46,7 @@ #include "display/display-lock.h" #include "battery-monitor.h" #include "battery/power-supply.h" -#include "power/power-control.h" +#include "power/power-suspend.h" #include "shared/plugin.h" #define TOUCH_ON 1 diff --git a/plugins/wearable/display/key-filter.c b/plugins/wearable/display/key-filter.c index bb89700..68e774f 100644 --- a/plugins/wearable/display/key-filter.c +++ b/plugins/wearable/display/key-filter.c @@ -38,8 +38,8 @@ #include "shared/device-notifier.h" #include "shared/common.h" #include "shared/plugin.h" -#include "power/power-handler.h" -#include "power/power-control.h" +#include "power/power-off.h" +#include "power/power-suspend.h" #include "led/touch-key.h" #include "apps/apps.h" #include "display/display-lock.h" diff --git a/src/battery/lowbat-handler.c b/src/battery/lowbat-handler.c index 7358f40..44b7fd3 100644 --- a/src/battery/lowbat-handler.c +++ b/src/battery/lowbat-handler.c @@ -42,7 +42,7 @@ #include "display/setting.h" #include "display/poll.h" #include "display/display-ops.h" -#include "power/power-handler.h" +#include "power/power-off.h" #include "apps/apps.h" #include "power-supply.h" @@ -158,7 +158,7 @@ static int power_execute(void *data) return 0; } - FIND_DEVICE_INT(ops, POWER_OPS_NAME); + FIND_DEVICE_INT(ops, "power-state-manager"); return ops->execute(data); } diff --git a/src/core/main.c b/src/core/main.c index ecbf942..88a36e4 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -31,8 +31,8 @@ #include "log.h" #include "shared/common.h" #include "shared/devices.h" -#include "power/boot.h" -#include "power/power-handler.h" +#include "power/power-boot.h" +#include "power/power-off.h" #include "shared/plugin.h" #include "shared/device-notifier.h" #include "core/devices.h" @@ -105,7 +105,7 @@ static int deviced_main(int argc, char **argv) CRITICAL_LOG("Initializing deviced."); mainloop = g_main_loop_new(NULL, FALSE); - ret = check_power_flag(); + ret = poweroff_check_revived(); if (ret) { /* Restarted: deviced was terminated * in middle of reboot/poweroff - resume procedure diff --git a/src/display/core.h b/src/display/core.h index c8062ac..94dab95 100644 --- a/src/display/core.h +++ b/src/display/core.h @@ -53,7 +53,7 @@ #define CHECK_OPS(d, op) (d != NULL && d->op != NULL) #ifdef ENABLE_PM_LOG -#include "power/power-control.h" +#include "power/power-suspend.h" #define MAX_LOG_COUNT 250 #endif diff --git a/src/power/boot.c b/src/power/power-boot.c similarity index 60% rename from src/power/boot.c rename to src/power/power-boot.c index a819fed..634dd69 100644 --- a/src/power/boot.c +++ b/src/power/power-boot.c @@ -22,6 +22,10 @@ #include #include #include +#include +#include +#include +#include #include "core/log.h" #include "shared/device-notifier.h" @@ -29,12 +33,20 @@ #include "display/poll.h" #include "display/display-ops.h" #include "shared/plugin.h" -#include "doze.h" +#include "power-doze.h" +#include "power-state-manager.h" #define SYSTEMD_DBUS_SIGNAL_SYSTEM_STARTUP_FINISHED "StartupFinished" #define SYSTEMD_DBUS_SIGNAL_USER_STARTUP_FINISHED "UserSessionStartupFinished" -static struct display_plugin *disp_plgn; +#define INIT_CONF_PATH "/etc/deviced/init.conf" + +static struct trans_info initial_transition_info = { + .reason = -1, + .curr = PSM_START, + .next = PSM_NORMAL, +}; + static guint sig_id[2] = {0, 0}; void remove_delayed_init_done_handler(void *data) @@ -78,12 +90,6 @@ static void delayed_init_done_received(GDBusConnection *conn, remove_delayed_init_done_handler(NULL); - _I("Real booting done. Unlock LCD_OFF."); - if (disp_plgn->pm_unlock_internal) - disp_plgn->pm_unlock_internal(INTERNAL_LOCK_BOOTING, LCD_OFF, PM_SLEEP_MARGIN); - - _I("Signal booting done."); - doze_init(); } @@ -113,9 +119,62 @@ void add_delayed_init_done_handler(void *data) _E("Failed to init dbus signal(%s).", SYSTEMD_DBUS_SIGNAL_USER_STARTUP_FINISHED); } -static void __CONSTRUCTOR__ initialize(void) +static void parse_transition_info(const char *action) +{ + char curr[16] = { 0, }; + char next[16] = { 0, }; + + if (sscanf(action, "%15[^,],%15s", curr, next) == 2) { + initial_transition_info.curr = convert_action_string_to_psm_state(curr); + initial_transition_info.next = convert_action_string_to_psm_state(next); + } +} + +static void parse_initial_transition_info(const struct parse_result *result) +{ + GList *elem; + struct section_property *prop; + + SYS_G_LIST_FOREACH(result->props, elem, prop) { + if (MATCH(prop->key, "Enum")) + initial_transition_info.reason = atoi(prop->value); + else if (MATCH(prop->key, "Action")) + parse_transition_info(prop->value); + } +} + +static int parse_matching_bootreason(const struct parse_result *result, void *data) { - disp_plgn = get_var_display_plugin(); - if (!disp_plgn) - _E("Failed to get display plugin variable."); + GList *elem; + struct section_property *prop; + char *bootreason = (char *) data; + + if (!MATCH(result->section, "EventAction")) + return 0; + + SYS_G_LIST_FOREACH(result->props, elem, prop) { + if (MATCH(prop->key, "BootReason") && MATCH(prop->value, bootreason)) + parse_initial_transition_info(result); + } + + return 0; +} + +/* the initial transition by bootreason is defined in init.conf */ +void get_initial_transition_by_bootreason(void *data) +{ + int retval; + char bootreason[64] = "Unknown"; + GList **head = (GList **) data; + + if (!head) + return; + + retval = hal_device_board_get_boot_reason(bootreason, sizeof(bootreason)); + if (retval == 0) + libsys_config_parse_by_section(INIT_CONF_PATH, parse_matching_bootreason, bootreason); + + CRITICAL_LOG("BootReason=%s", bootreason); + + *head = g_list_append(*head, &initial_transition_info); } diff --git a/src/power/boot.h b/src/power/power-boot.h similarity index 82% rename from src/power/boot.h rename to src/power/power-boot.h index a5d5b7f..7c339e0 100644 --- a/src/power/boot.h +++ b/src/power/power-boot.h @@ -16,12 +16,13 @@ * limitations under the License. */ -#ifndef __DEVICED_BOOT_H__ -#define __DEVICED_BOOT_H__ +#ifndef __DEVICED_POWER_BOOT_H__ +#define __DEVICED_POWER_BOOT_H__ void add_delayed_init_done_handler(void *data); void remove_delayed_init_done_handler(void *data); +void get_initial_transition_by_bootreason(void *data); extern int silent_boot; -#endif /* __DEVICED_BOOT_H__ */ +#endif /* __DEVICED_POWER_BOOT_H__ */ diff --git a/plugins/iot-headless/power/power-dbus.c b/src/power/power-dbus.c similarity index 99% rename from plugins/iot-headless/power/power-dbus.c rename to src/power/power-dbus.c index 0cbc34f..e6ec1e9 100644 --- a/plugins/iot-headless/power/power-dbus.c +++ b/src/power/power-dbus.c @@ -30,7 +30,7 @@ #include "shared/log.h" #include "shared/device-notifier.h" -#include "power/power-control.h" +#include "power-suspend.h" #include "power-state-manager.h" #include "power-state-wait.h" @@ -303,7 +303,7 @@ static const dbus_interface_u dbus_interface = { .nr_methods = ARRAY_SIZE(dbus_methods), }; -void power_plugin_dbus_init(void *data) +void power_dbus_init(void) { int retval; diff --git a/plugins/iot-headless/power/power-dbus.h b/src/power/power-dbus.h similarity index 94% rename from plugins/iot-headless/power/power-dbus.h rename to src/power/power-dbus.h index a3fde6d..4e34361 100644 --- a/plugins/iot-headless/power/power-dbus.h +++ b/src/power/power-dbus.h @@ -19,6 +19,6 @@ #ifndef __POWER_DBUS_H__ #define __POWER_DBUS_H__ -void power_plugin_dbus_init(void *data); +void power_dbus_init(void); #endif //__POWER_DBUS_H__ diff --git a/src/power/doze.c b/src/power/power-doze.c similarity index 99% rename from src/power/doze.c rename to src/power/power-doze.c index 572db6b..6679381 100644 --- a/src/power/doze.c +++ b/src/power/power-doze.c @@ -17,7 +17,7 @@ */ #include -#include "doze.h" +#include "power-doze.h" #include "core/log.h" #include "shared/device-notifier.h" #include "display/core.h" diff --git a/src/power/doze.h b/src/power/power-doze.h similarity index 92% rename from src/power/doze.h rename to src/power/power-doze.h index e6236e9..734f49b 100644 --- a/src/power/doze.h +++ b/src/power/power-doze.h @@ -16,8 +16,8 @@ * limitations under the License. */ -#ifndef __DOZE_H__ -#define __DOZE_H__ +#ifndef __DEVICED_POWER_DOZE_H__ +#define __DEVICED_POWER_DOZE_H__ /* To request pmqos start and stop for Doze */ #define DOZE_PMQOS_START 1 diff --git a/plugins/iot-headless/power/power-event-lock.c b/src/power/power-event-lock.c similarity index 100% rename from plugins/iot-headless/power/power-event-lock.c rename to src/power/power-event-lock.c diff --git a/plugins/iot-headless/power/power-event-lock.h b/src/power/power-event-lock.h similarity index 100% rename from plugins/iot-headless/power/power-event-lock.h rename to src/power/power-event-lock.h diff --git a/src/power/power-handler.c b/src/power/power-off.c similarity index 94% rename from src/power/power-handler.c rename to src/power/power-off.c index 7464068..08bbc3d 100644 --- a/src/power/power-handler.c +++ b/src/power/power-off.c @@ -46,9 +46,9 @@ #include "display/setting.h" #include "display/core.h" #include "display/display-ops.h" -#include "power-handler.h" +#include "power-off.h" #include "apps/apps.h" -#include "boot.h" +#include "power-boot.h" #include "shared/plugin.h" #define POWEROFF_WAIT_RESOURCED (0.5*1000) /* 0.5 seconds */ @@ -266,7 +266,7 @@ void poweroff_prepare(void) device_notify(DEVICE_NOTIFIER_POWEROFF, &off); } -int check_power_flag(void) +int poweroff_check_revived(void) { for (int i = 0; i < ARRAY_SIZE(poweroff_type_flagpaths); i++) { if (access(poweroff_type_flagpaths[i], F_OK) == 0) { @@ -319,7 +319,7 @@ static void poweroff_remove_handle(pid_t pid) assert(handle); - _D("Remove handle pid=%d timeout=%d timeout_id=%d.", handle->pid, handle->timeout, handle->timeout_id); + _D("Remove handle pid=%d(%s) timeout=%d timeout_id=%d.", handle->pid, handle->comm, handle->timeout, handle->timeout_id); SYS_G_LIST_REMOVE(poweroff_handles, handle); if (handle->timeout_id) { @@ -354,9 +354,10 @@ static int poweroff_add_handle(pid_t pid) handle->pid = pid; handle->timeout_id = 0; handle->timeout = POWEROFF_WAIT_MAX; + get_command(pid, handle->comm, sizeof(handle->comm)); SYS_G_LIST_APPEND(poweroff_handles, handle); - _D("Add a new poweroff timer. pid=%d timeout=%d timeout_id=%d)", handle->pid, handle->timeout, handle->timeout_id); + _D("Add a new poweroff timer. pid=%d(%s) timeout=%d", handle->pid, handle->comm, handle->timeout); return 0; } @@ -404,11 +405,11 @@ static gboolean poweroff_start_timers(void *data) SYS_G_LIST_FOREACH(poweroff_handles, l, handle) { pid_alive = kill(handle->pid, 0); if (pid_alive == -1) { - _D("Pid(%d) is dead.", handle->pid); + _D("Pid=%d(%s) is dead.", handle->pid, handle->comm); handle->timeout = 0; } - _D("Run timer, pid=%d timeout=%d timeout_id=%d.", handle->pid, handle->timeout, handle->timeout_id); + _D("Run timer, pid=%d(%s) timeout=%d timeout_id=%d.", handle->pid, handle->comm, handle->timeout, handle->timeout_id); handle->timeout_id = g_timeout_add_seconds(handle->timeout, poweroff_wait_timeout_cb, @@ -505,7 +506,7 @@ static void poweroff_send_broadcast(int status) _E("Failed to send dbus signal(%s)", SIGNAL_POWEROFF_STATE); } -static int power_execute_pid(const char *typename, const char *option) +static int __poweroff_trigger_poweroff(const char *typename, const char *option) { int ret_val; @@ -555,9 +556,9 @@ static int power_execute_pid(const char *typename, const char *option) return 0; } -static int power_execute(void *data) +int poweroff_trigger_poweroff(void *data) { - return power_execute_pid((char *)data, NULL); + return __poweroff_trigger_poweroff((char *)data, NULL); } static int check_sender_process(GDBusConnection *conn, const char *sender) @@ -583,6 +584,7 @@ static GVariant *dbus_power_handler(GDBusConnection *conn, GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data) { int ret; + char comm[128] = "Unknown"; char *type_str; g_variant_get(param, "(s)", &type_str); @@ -591,9 +593,10 @@ static GVariant *dbus_power_handler(GDBusConnection *conn, if (ret < 0) goto out; + get_command(ret, comm, sizeof(comm)); - CRITICAL_LOG("Poweroff PID(%d) requests %s.", ret, type_str); - ret = power_execute_pid(type_str, NULL); + CRITICAL_LOG("Poweroff pid=%d(%s) requests %s.", ret, comm, type_str); + ret = __poweroff_trigger_poweroff(type_str, NULL); out: g_free(type_str); @@ -605,6 +608,7 @@ static GVariant *dbus_power_option_handler(GDBusConnection *conn, GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data) { int ret; + char comm[128] = "Unknown"; char *type, *option; g_variant_get(param, "(ss)", &type, &option); @@ -613,9 +617,10 @@ static GVariant *dbus_power_option_handler(GDBusConnection *conn, if (ret < 0) goto out; + get_command(ret, comm, sizeof(comm)); - CRITICAL_LOG("Poweroff PID(%d) requests type=%s option=%s.", ret, type, option); - ret = power_execute_pid(type, option); + CRITICAL_LOG("Poweroff pid=%d(%s) requests type=%s option=%s.", ret, comm, type, option); + ret = __poweroff_trigger_poweroff(type, option); out: g_free(type); @@ -642,9 +647,6 @@ static GVariant *add_poweroff_time(GDBusConnection *conn, goto out; pid = (pid_t)ret; - - CRITICAL_LOG("PID %d requested to a poweroff timer.", pid); - ret = poweroff_add_handle(pid); out: @@ -666,8 +668,6 @@ static GVariant *remove_poweroff_time(GDBusConnection *conn, pid = (pid_t)ret; - CRITICAL_LOG("PID %d requested to remove poweroff timer.", pid); - SYS_G_LIST_FOREACH(poweroff_handles, l, handle) { if (handle->pid == pid) break; @@ -771,7 +771,7 @@ out: return done; } -static void power_init(void *data) +void power_off_init(void) { int ret_val; @@ -795,14 +795,6 @@ static void power_init(void *data) poweroff_stage = POWEROFF_DEFAULT; } -static const struct device_ops power_device_ops = { - DECLARE_NAME_LEN(POWER_OPS_NAME), - .init = power_init, - .execute = power_execute, -}; - -DEVICE_OPS_REGISTER(&power_device_ops) - static void __CONSTRUCTOR__ initialize(void) { disp_plgn = get_var_display_plugin(); diff --git a/src/power/power-handler.h b/src/power/power-off.h similarity index 88% rename from src/power/power-handler.h rename to src/power/power-off.h index 8c7e16b..be605fa 100644 --- a/src/power/power-handler.h +++ b/src/power/power-off.h @@ -16,13 +16,11 @@ * limitations under the License. */ -#ifndef __POWER_HANDLE_H__ -#define __POWER_HANDLE_H__ +#ifndef __DEVICED_POWER_OFF_H__ +#define __DEVICED_POWER_OFF_H__ #include -#define POWER_OPS_NAME "power" - #define POWER_POWEROFF "poweroff" #define POWER_REBOOT "reboot" #define POWER_OFF_POPUP "pwroff-popup" @@ -55,13 +53,16 @@ struct power_option { struct poweroff_handle { pid_t pid; int timeout; + char comm[128]; guint timeout_id; }; -int check_power_flag(void); +void power_off_init(void); + +int poweroff_trigger_poweroff(void *data); +int poweroff_check_revived(void); void poweroff_request_shutdown(void); int poweroff_add_wait(pid_t pid); void poweroff_remove_wait(pid_t pid); - -#endif /* __POWER_HANDLE_H__ */ +#endif /* __DEVICED_POWER_OFF_H__ */ diff --git a/plugins/iot-headless/power/power-state-manager.c b/src/power/power-state-manager.c similarity index 81% rename from plugins/iot-headless/power/power-state-manager.c rename to src/power/power-state-manager.c index 3bf6d42..52c622c 100644 --- a/plugins/iot-headless/power/power-state-manager.c +++ b/src/power/power-state-manager.c @@ -26,12 +26,13 @@ #include "shared/devices.h" #include "shared/device-notifier.h" #include "shared/log.h" -#include "power/power-control.h" #include "power-state-manager.h" +#include "power-suspend.h" #include "power-dbus.h" +#include "power-boot.h" +#include "power-off.h" #include "power-state-wait.h" #include "power-event-lock.h" -#include "power-config-parse.h" #define EVENT_TYPE_SLEEP 0 #define EVENT_TYPE_WAKEUP 1 @@ -48,7 +49,7 @@ static int delayed_init_done = 0; static guint64 state_transition_counter = 0; static enum psm_state current = PSM_START; -/* hold trans_info until booting done */ +/* hold trans_info until delayed_init_done */ static GList *deferred_transition_list; static void psm_wake_unlock(void) @@ -64,16 +65,7 @@ static void psm_wake_unlock(void) static void psm_trigger_poweroff(void) { - const struct device_ops *power_device; - - power_device = find_device("power"); - if (check_default(power_device)) - return; - - if (power_device->execute) { - power_disable_autosleep(); - power_device->execute("poweroff"); - } + poweroff_trigger_poweroff("poweroff"); } static void broadcast_transition_info(const struct trans_info *ti) @@ -118,7 +110,7 @@ static void psm_transition_start_to_sleep(const struct trans_info *ti) broadcast_transition_info(ti); waiting = update_change_state_wait(state_transition_counter, ti, psm_wake_unlock); if (waiting > 0) { - _D("Defer wake unlock"); + _D("Defer wake unlock."); return; } @@ -140,7 +132,7 @@ static void psm_transition_normal_to_sleep(const struct trans_info *ti) broadcast_transition_info(ti); waiting = update_change_state_wait(state_transition_counter, ti, psm_wake_unlock); if (waiting > 0) { - _D("Defer wake unlock"); + _D("Defer wake unlock."); return; } @@ -164,7 +156,7 @@ static void psm_transition_sleep_to_sleep(const struct trans_info *ti) broadcast_transition_info(ti); waiting = update_change_state_wait(state_transition_counter, ti, psm_wake_unlock); if (waiting > 0) { - _D("Defer wake unlock"); + _D("Defer wake unlock."); return; } @@ -180,7 +172,7 @@ static void psm_transition_normal_to_poweroff(const struct trans_info *ti) broadcast_transition_info(ti); waiting = update_change_state_wait(state_transition_counter, ti, psm_trigger_poweroff); if (waiting > 0) { - _D("Defer poweroff"); + _D("Defer poweroff."); return; } @@ -221,6 +213,7 @@ static void transition_state(const struct trans_info *ti) static void deferred_transition_state(gpointer data) { transition_state(data); + free(data); } static int psm_transition_state_cb(void *data) @@ -242,20 +235,22 @@ static int psm_transition_state_cb(void *data) if (!ti) return 0; - /* defer state transition until booting done */ + /* defer state transition until delayed_init_done */ if (!delayed_init_done) { struct trans_info *deferred_ti = calloc(1, sizeof(struct trans_info)); if (!deferred_ti) { - CRITICAL_LOG("Failed to defer transition"); + CRITICAL_LOG("Failed to defer transition."); return 0; } - // mocking state transition + // Pseudo state transition. current = ti->next; + // Reserve the trans_info. + // Those are used on receiving delayed_init_done for real transitioning state. memcpy(deferred_ti, ti, sizeof(struct trans_info)); deferred_transition_list = g_list_append(deferred_transition_list, deferred_ti); - _D("Defer state transition %s->%s until booting done", psm_name[ti->curr], psm_name[ti->next]); + _D("Defer state transition %s->%s until delayed init done.", psm_name[ti->curr], psm_name[ti->next]); return 0; } @@ -269,15 +264,15 @@ static int delayed_init_cb(void *data) { delayed_init_done = 1; - _D("Start deferred state transition"); + _D("Start deferred state transition."); + /* rewind current state to initial state and do the deferred transition */ current = PSM_START; - g_list_free_full(deferred_transition_list, deferred_transition_state); - deferred_transition_list = NULL; - _D("Finished deferred state transition"); + g_list_free_full(g_steal_pointer(&deferred_transition_list), deferred_transition_state); - /* Deferred autosleep enable, - * This prevents system go suspend during booting */ + /* Enable autosleep at this point. + * This prevents system go suspend(autosleep) before booting done */ + _D("Finished deferred state transition. Enable autosleep."); power_enable_autosleep(); return 0; @@ -290,20 +285,27 @@ void power_state_manager_init(void *data) register_notifier(DEVICE_NOTIFIER_DELAYED_INIT, delayed_init_cb); register_notifier(DEVICE_NOTIFIER_REQUEST_TRANSITION_STATE, psm_transition_state_cb); - power_plugin_dbus_init(NULL); + power_dbus_init(); + power_off_init(); + power_suspend_init(); power_event_lock_init(); power_state_wait_init(); - /* initialize the power state */ - parse_initial_transition(&initial_ti); + /* Take the first transition from PSM_START. + * It is determined by bootreason to which state to transition, PSM_NORMAL or PSM_SLEEP. */ + get_initial_transition_by_bootreason(&initial_ti); psm_transition_state_cb(initial_ti); g_list_free(initial_ti); } static const struct device_ops power_state_manager_device_ops = { - DECLARE_NAME_LEN("power-control-plugin"), + DECLARE_NAME_LEN("power-state-manager"), .init = power_state_manager_init, - .disable_auto_init = true, /* initialized by core power module */ + /* It should be initilalized earlier than the almost other modules so that + * it can receive and handle power request from the other modules. Therefore + * give a high enough priority. */ + .priority = 990, + .execute = poweroff_trigger_poweroff, }; DEVICE_OPS_REGISTER(&power_state_manager_device_ops) diff --git a/plugins/iot-headless/power/power-state-manager.h b/src/power/power-state-manager.h similarity index 100% rename from plugins/iot-headless/power/power-state-manager.h rename to src/power/power-state-manager.h diff --git a/plugins/iot-headless/power/power-state-wait.c b/src/power/power-state-wait.c similarity index 97% rename from plugins/iot-headless/power/power-state-wait.c rename to src/power/power-state-wait.c index 93868e4..44b6ffb 100644 --- a/plugins/iot-headless/power/power-state-wait.c +++ b/src/power/power-state-wait.c @@ -104,11 +104,10 @@ int add_change_state_wait(pid_t pid, guint64 state) struct proc_info *pi; GList *elem; - _D("pid=%d added csw for %#"PRIx64, pid, state); - SYS_G_LIST_FOREACH(proc_list, elem, pi) { if (pi->pid == pid) { pi->state_bitmap |= state; + _D("pid=%d(%s) updated csw for %#"PRIx64, pid, pi->comm, state); return 0; } } @@ -122,6 +121,8 @@ int add_change_state_wait(pid_t pid, guint64 state) get_command(pid, pi->comm, sizeof(pi->comm)); SYS_G_LIST_APPEND(proc_list, pi); + _D("pid=%d(%s) added csw for %#"PRIx64, pid, pi->comm, state); + return 0; } diff --git a/plugins/iot-headless/power/power-state-wait.h b/src/power/power-state-wait.h similarity index 100% rename from plugins/iot-headless/power/power-state-wait.h rename to src/power/power-state-wait.h diff --git a/src/power/power-control.c b/src/power/power-suspend.c similarity index 91% rename from src/power/power-control.c rename to src/power/power-suspend.c index e4dbb1e..f7cf357 100644 --- a/src/power/power-control.c +++ b/src/power/power-suspend.c @@ -40,8 +40,8 @@ #include "vconf.h" #include "display/display-dpms.h" #include "display/display.h" -#include "power/boot.h" -#include "power-control.h" +#include "power-boot.h" +#include "power-suspend.h" #define POWER_CONF_FILE "/etc/deviced/power.conf" @@ -322,29 +322,11 @@ static int load_sleep_config(struct parse_result *result, void *user_data) return 0; } -static void power_control_init(void *data) +void power_suspend_init(void) { - const struct device_ops *plugin_device_ops; int retval; retval = config_parse(POWER_CONF_FILE, load_sleep_config, NULL); if (retval < 0) _E("Failed to load sleep config: %d", retval); - - - plugin_device_ops = find_device("power-control-plugin"); - if (check_default(plugin_device_ops)) - return; - - _D("[%s] Initialization.", plugin_device_ops->name); - if (plugin_device_ops->init) - plugin_device_ops->init(NULL); } - -static const struct device_ops power_control_device_ops = { - DECLARE_NAME_LEN("power-control"), - .init = power_control_init, - .priority = 900, /* power-control should be initialized asap */ -}; - -DEVICE_OPS_REGISTER(&power_control_device_ops) diff --git a/src/power/power-control.h b/src/power/power-suspend.h similarity index 93% rename from src/power/power-control.h rename to src/power/power-suspend.h index ead8e98..a14b9d0 100644 --- a/src/power/power-control.h +++ b/src/power/power-suspend.h @@ -16,8 +16,8 @@ * limitations under the License. */ -#ifndef __POWER_CONTROL_H__ -#define __POWER_CONTROL_H__ +#ifndef __DEVICED_POWER_SUSPEND_H__ +#define __DEVICED_POWER_SUSPEND_H__ #include "display/core.h" @@ -85,4 +85,5 @@ int check_wakeup_src(void); int get_wakeup_count(int *cnt); int set_wakeup_count(int cnt); int suspend_other_process(int type); -#endif /* __POWER_CONTROL_H__ */ +void power_suspend_init(void); +#endif /* __DEVICED_POWER_SUSPEND_H__ */ diff --git a/src/touchscreen/touchscreen.c b/src/touchscreen/touchscreen.c index c642203..183a407 100644 --- a/src/touchscreen/touchscreen.c +++ b/src/touchscreen/touchscreen.c @@ -29,7 +29,7 @@ #include "battery/power-supply.h" #include "display/core.h" #include "display/display-ops.h" -#include "power/boot.h" +#include "power/power-boot.h" #include "shared/plugin.h" enum ps_mode { -- 2.7.4 From d10635a899e9b55ef64a5c4804425d95bd3f2863 Mon Sep 17 00:00:00 2001 From: Youngjae Cho Date: Fri, 13 May 2022 09:48:25 +0900 Subject: [PATCH 13/16] device-notifier: prevent index out of bound Change-Id: I5d0ab792bb605f259bc6c7f0a486ecb84d4e3930 Signed-off-by: Youngjae Cho --- src/shared/device-notifier.c | 26 ++++++++++++++++++++++++++ src/shared/device-notifier.h | 3 ++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/shared/device-notifier.c b/src/shared/device-notifier.c index 661fae7..48c6716 100644 --- a/src/shared/device-notifier.c +++ b/src/shared/device-notifier.c @@ -54,6 +54,8 @@ static const char *device_notifier_type_str[DEVICE_NOTIFIER_MAX] = { NOTIFY_STR(DEVICE_NOTIFIER_DELAYED_INIT), NOTIFY_STR(DEVICE_NOTIFIER_LCD), NOTIFY_STR(DEVICE_NOTIFIER_LCD_OFF), + NOTIFY_STR(DEVICE_NOTIFIER_LCD_OFF_COMPLETE), + NOTIFY_STR(DEVICE_NOTIFIER_LCD_AUTOBRT_SENSING), NOTIFY_STR(DEVICE_NOTIFIER_LOWBAT), NOTIFY_STR(DEVICE_NOTIFIER_FULLBAT), NOTIFY_STR(DEVICE_NOTIFIER_POWER_SUPPLY), @@ -61,6 +63,8 @@ static const char *device_notifier_type_str[DEVICE_NOTIFIER_MAX] = { NOTIFY_STR(DEVICE_NOTIFIER_BATTERY_PRESENT), NOTIFY_STR(DEVICE_NOTIFIER_BATTERY_OVP), NOTIFY_STR(DEVICE_NOTIFIER_BATTERY_CHARGING), + NOTIFY_STR(DEVICE_NOTIFIER_BATTERY_CHARGER_CONNECTED), + NOTIFY_STR(DEVICE_NOTIFIER_BATTERY_CHARGER_DISCONNECTED), NOTIFY_STR(DEVICE_NOTIFIER_DISPLAY_AMBIENT_CONDITION), NOTIFY_STR(DEVICE_NOTIFIER_DISPLAY_AMBIENT_STATE), NOTIFY_STR(DEVICE_NOTIFIER_DISPLAY_LOCK), @@ -72,6 +76,8 @@ static const char *device_notifier_type_str[DEVICE_NOTIFIER_MAX] = { NOTIFY_STR(DEVICE_NOTIFIER_USB_DEBUG_MODE), NOTIFY_STR(DEVICE_NOTIFIER_USB_TETHERING_MODE), NOTIFY_STR(DEVICE_NOTIFIER_EVENT_HANDLER), + NOTIFY_STR(DEVICE_NOTIFIER_CPU_BOOST_LOWBAT), + NOTIFY_STR(DEVICE_NOTIFIER_CPU_BOOST_POWEROFF), NOTIFY_STR(DEVICE_NOTIFIER_PMQOS), NOTIFY_STR(DEVICE_NOTIFIER_PMQOS_ULTRAPOWERSAVING), NOTIFY_STR(DEVICE_NOTIFIER_PMQOS_POWERSAVING), @@ -83,6 +89,17 @@ static const char *device_notifier_type_str[DEVICE_NOTIFIER_MAX] = { NOTIFY_STR(DEVICE_NOTIFIER_BEZEL_WAKEUP), NOTIFY_STR(DEVICE_NOTIFIER_DISPLAY_BRIGHTNESS), NOTIFY_STR(DEVICE_NOTIFIER_ULTRAPOWERSAVING), + NOTIFY_STR(DEVICE_NOTIFIER_EXTCON_COUNT), + NOTIFY_STR(DEVICE_NOTIFIER_KEY_PRESS), + NOTIFY_STR(DEVICE_NOTIFIER_KEY_RELEASE), + + /* action triggered by input event */ + NOTIFY_STR(DEVICE_NOTIFIER_INPUT_TRIGGER_POWEROFF), + NOTIFY_STR(DEVICE_NOTIFIER_INPUT_BROADCAST_SIGNAL), + + /* Purpose of calling methods of different modules + * Use prefix DEVICE_NOTIFIER_REQUEST */ + NOTIFY_STR(DEVICE_NOTIFIER_REQUEST_TRANSITION_STATE), }; static gint compare_priority(gconstpointer a, gconstpointer b) @@ -96,6 +113,9 @@ int __register_notifier(enum device_notifier_type type, notify_cb func, int prio GList *n; struct device_notifier *notifier; + if (type < DEVICE_NOTIFIER_MIN || type >= DEVICE_NOTIFIER_MAX) + return -EINVAL; + _I("%s, %p by %s", device_notifier_type_str[type], func, caller); if (!func) { @@ -131,6 +151,9 @@ int __register_notifier_udata(enum device_notifier_type type, struct device_notifier *notifier; static int id = 1; + if (type < DEVICE_NOTIFIER_MIN || type >= DEVICE_NOTIFIER_MAX) + return -EINVAL; + _I("%s, %p by %s", device_notifier_type_str[type], func_udata, caller); if (!func_udata) { @@ -163,6 +186,9 @@ int __unregister_notifier(enum device_notifier_type type, notify_cb func, const GList *n; struct device_notifier *notifier; + if (type < DEVICE_NOTIFIER_MIN || type >= DEVICE_NOTIFIER_MAX) + return -EINVAL; + if (!func) { _E("invalid func address of %s! by %s", device_notifier_type_str[type], caller); return -EINVAL; diff --git a/src/shared/device-notifier.h b/src/shared/device-notifier.h index 3a24a2f..1635b3d 100644 --- a/src/shared/device-notifier.h +++ b/src/shared/device-notifier.h @@ -21,7 +21,8 @@ #define __DEVICE_NOTIFIER_H__ enum device_notifier_type { - DEVICE_NOTIFIER_DAEMON_RESTARTED, + DEVICE_NOTIFIER_MIN, + DEVICE_NOTIFIER_DAEMON_RESTARTED = DEVICE_NOTIFIER_MIN, DEVICE_NOTIFIER_DELAYED_INIT, DEVICE_NOTIFIER_LCD, DEVICE_NOTIFIER_LCD_OFF, -- 2.7.4 From b632b19c6f569153fa53a7bc2c648b9fe1d0ec0e Mon Sep 17 00:00:00 2001 From: Youngjae Cho Date: Wed, 11 May 2022 17:52:25 +0900 Subject: [PATCH 14/16] input: support bluetooth key input for iot-headless Change-Id: I9a082c36bba8a737a3f2fe29d8d75dc444803400 Signed-off-by: Youngjae Cho --- conf/input-profile-iot-headless.conf | 2 +- plugins/iot-headless/input/input-config.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/conf/input-profile-iot-headless.conf b/conf/input-profile-iot-headless.conf index 02bcd4a..5640a99 100644 --- a/conf/input-profile-iot-headless.conf +++ b/conf/input-profile-iot-headless.conf @@ -18,7 +18,7 @@ [EventAction] Name=BLINKKEY_EDGE Enum=1000 -Keycode=power +Keycode=bluetooth Duration=0,2000 TriggerType=edge Action=sleep,sleep diff --git a/plugins/iot-headless/input/input-config.c b/plugins/iot-headless/input/input-config.c index ce97c19..faeffb8 100644 --- a/plugins/iot-headless/input/input-config.c +++ b/plugins/iot-headless/input/input-config.c @@ -52,6 +52,8 @@ static void parse_keycode(struct input_event_unit *ieu, const char *keycode) { if (MATCH(keycode, "power")) ieu->keycode = KEY_POWER; + else if (MATCH(keycode, "bluetooth")) + ieu->keycode = KEY_BLUETOOTH; /* add keycode list here */ } -- 2.7.4 From 2a4c1949067c440573d0c167115bae4d352ba3cd Mon Sep 17 00:00:00 2001 From: Youngjae Cho Date: Fri, 13 May 2022 10:49:05 +0900 Subject: [PATCH 15/16] power: refactor poweroff sequence This is intermediate patch before applying power-state-wait mechanism to power-off. Change-Id: Ie5e302962ffd206b61a8b3f9857e83e22f83ed17 Signed-off-by: Youngjae Cho --- plugins/iot-headed/display/core.c | 29 +++-- plugins/mobile/display/core.c | 29 +++-- plugins/tv/display/core.c | 29 +++-- plugins/wearable/display/core.c | 29 +++-- src/power/power-off.c | 264 +++++++++++++++++--------------------- src/power/power-off.h | 2 +- src/shared/device-notifier.c | 1 + src/shared/device-notifier.h | 1 + 8 files changed, 191 insertions(+), 193 deletions(-) diff --git a/plugins/iot-headed/display/core.c b/plugins/iot-headed/display/core.c index 841818b..31d05af 100644 --- a/plugins/iot-headed/display/core.c +++ b/plugins/iot-headed/display/core.c @@ -1729,17 +1729,6 @@ static int update_setting(int key_idx, int val) if (get_pm_cur_state() == S_NORMAL) states[get_pm_cur_state()].trans(EVENT_INPUT); break; - case SETTING_POWEROFF: - switch (val) { - case POWEROFF_TYPE_NONE: - clear_pm_status_flag(PWROFF_FLAG); - break; - case POWEROFF_TYPE_DIRECT: - case POWEROFF_TYPE_RESTART: - set_pm_status_flag(PWROFF_FLAG); - break; - } - break; case SETTING_POWER_CUSTOM_BRIGHTNESS: if (val == VCONFKEY_PM_CUSTOM_BRIGHTNESS_ON) backlight_ops->set_custom_status(true); @@ -2046,6 +2035,23 @@ static int input_init_handler(void) return 0; } +static int poweroff_triggered_callback(void *udata) +{ + int val = (int)(intptr_t) udata; + + switch (val) { + case POWEROFF_TYPE_NONE: + clear_pm_status_flag(PWROFF_FLAG); + break; + case POWEROFF_TYPE_DIRECT: + case POWEROFF_TYPE_RESTART: + set_pm_status_flag(PWROFF_FLAG); + break; + } + + return 0; +} + static void esd_action(void) { const struct device_ops *touchscreen_ops = NULL; @@ -2111,6 +2117,7 @@ static void display_init(void *data) register_notifier(DEVICE_NOTIFIER_BATTERY_HEALTH, battery_health_changed); register_notifier(DEVICE_NOTIFIER_DISPLAY_BRIGHTNESS, display_brightness_changed); register_notifier(DEVICE_NOTIFIER_LCD_AUTOBRT_SENSING, display_auto_brightness_sensing); + register_notifier(DEVICE_NOTIFIER_POWEROFF_TRIGGERED, poweroff_triggered_callback); init_save_userlock(); diff --git a/plugins/mobile/display/core.c b/plugins/mobile/display/core.c index 918ae54..3011edf 100644 --- a/plugins/mobile/display/core.c +++ b/plugins/mobile/display/core.c @@ -1739,17 +1739,6 @@ static int update_setting(int key_idx, int val) if (get_pm_cur_state() == S_NORMAL) states[get_pm_cur_state()].trans(EVENT_INPUT); break; - case SETTING_POWEROFF: - switch (val) { - case POWEROFF_TYPE_NONE: - clear_pm_status_flag(PWROFF_FLAG); - break; - case POWEROFF_TYPE_DIRECT: - case POWEROFF_TYPE_RESTART: - set_pm_status_flag(PWROFF_FLAG); - break; - } - break; case SETTING_POWER_CUSTOM_BRIGHTNESS: if (val == VCONFKEY_PM_CUSTOM_BRIGHTNESS_ON) backlight_ops->set_custom_status(true); @@ -2052,6 +2041,23 @@ static int input_init_handler(void) return 0; } +static int poweroff_triggered_callback(void *udata) +{ + int val = (int)(intptr_t) udata; + + switch (val) { + case POWEROFF_TYPE_NONE: + clear_pm_status_flag(PWROFF_FLAG); + break; + case POWEROFF_TYPE_DIRECT: + case POWEROFF_TYPE_RESTART: + set_pm_status_flag(PWROFF_FLAG); + break; + } + + return 0; +} + static void esd_action(void) { const struct device_ops *touchscreen_ops = NULL; @@ -2117,6 +2123,7 @@ static void display_init(void *data) register_notifier(DEVICE_NOTIFIER_BATTERY_HEALTH, battery_health_changed); register_notifier(DEVICE_NOTIFIER_DISPLAY_BRIGHTNESS, display_brightness_changed); register_notifier(DEVICE_NOTIFIER_LCD_AUTOBRT_SENSING, display_auto_brightness_sensing); + register_notifier(DEVICE_NOTIFIER_POWEROFF_TRIGGERED, poweroff_triggered_callback); init_save_userlock(); diff --git a/plugins/tv/display/core.c b/plugins/tv/display/core.c index 61f435a..3203445 100644 --- a/plugins/tv/display/core.c +++ b/plugins/tv/display/core.c @@ -1729,17 +1729,6 @@ static int update_setting(int key_idx, int val) if (get_pm_cur_state() == S_NORMAL) states[get_pm_cur_state()].trans(EVENT_INPUT); break; - case SETTING_POWEROFF: - switch (val) { - case POWEROFF_TYPE_NONE: - clear_pm_status_flag(PWROFF_FLAG); - break; - case POWEROFF_TYPE_DIRECT: - case POWEROFF_TYPE_RESTART: - set_pm_status_flag(PWROFF_FLAG); - break; - } - break; case SETTING_POWER_CUSTOM_BRIGHTNESS: if (val == VCONFKEY_PM_CUSTOM_BRIGHTNESS_ON) backlight_ops->set_custom_status(true); @@ -2043,6 +2032,23 @@ static int input_init_handler(void) return 0; } +static int poweroff_triggered_callback(void *udata) +{ + int val = (int)(intptr_t) udata; + + switch (val) { + case POWEROFF_TYPE_NONE: + clear_pm_status_flag(PWROFF_FLAG); + break; + case POWEROFF_TYPE_DIRECT: + case POWEROFF_TYPE_RESTART: + set_pm_status_flag(PWROFF_FLAG); + break; + } + + return 0; +} + static void esd_action(void) { const struct device_ops *touchscreen_ops = NULL; @@ -2108,6 +2114,7 @@ static void display_init(void *data) register_notifier(DEVICE_NOTIFIER_BATTERY_HEALTH, battery_health_changed); register_notifier(DEVICE_NOTIFIER_DISPLAY_BRIGHTNESS, display_brightness_changed); register_notifier(DEVICE_NOTIFIER_LCD_AUTOBRT_SENSING, display_auto_brightness_sensing); + register_notifier(DEVICE_NOTIFIER_POWEROFF_TRIGGERED, poweroff_triggered_callback); init_save_userlock(); diff --git a/plugins/wearable/display/core.c b/plugins/wearable/display/core.c index ff2c6e0..d8bfcfe 100644 --- a/plugins/wearable/display/core.c +++ b/plugins/wearable/display/core.c @@ -2001,17 +2001,6 @@ static int update_setting(int key_idx, int val) if (get_pm_cur_state() == S_NORMAL) states[get_pm_cur_state()].trans(EVENT_INPUT); break; - case SETTING_POWEROFF: - switch (val) { - case POWEROFF_TYPE_NONE: - clear_pm_status_flag(PWROFF_FLAG); - break; - case POWEROFF_TYPE_DIRECT: - case POWEROFF_TYPE_RESTART: - set_pm_status_flag(PWROFF_FLAG); - break; - } - break; case SETTING_POWER_CUSTOM_BRIGHTNESS: if (val == VCONFKEY_PM_CUSTOM_BRIGHTNESS_ON) backlight_ops->set_custom_status(true); @@ -2335,6 +2324,23 @@ static int input_init_handler(void) return 0; } +static int poweroff_triggered_callback(void *udata) +{ + int val = (int)(intptr_t) udata; + + switch (val) { + case POWEROFF_TYPE_NONE: + clear_pm_status_flag(PWROFF_FLAG); + break; + case POWEROFF_TYPE_DIRECT: + case POWEROFF_TYPE_RESTART: + set_pm_status_flag(PWROFF_FLAG); + break; + } + + return 0; +} + static void esd_action(void) { const struct device_ops *touchscreen_ops = NULL; @@ -2438,6 +2444,7 @@ static void display_init(void *data) register_notifier(DEVICE_NOTIFIER_BATTERY_HEALTH, battery_health_changed); register_notifier(DEVICE_NOTIFIER_DISPLAY_BRIGHTNESS, display_brightness_changed); register_notifier(DEVICE_NOTIFIER_LCD_AUTOBRT_SENSING, display_auto_brightness_sensing); + register_notifier(DEVICE_NOTIFIER_POWEROFF_TRIGGERED, poweroff_triggered_callback); init_save_userlock(); diff --git a/src/power/power-off.c b/src/power/power-off.c index 08bbc3d..4f7d402 100644 --- a/src/power/power-off.c +++ b/src/power/power-off.c @@ -57,11 +57,9 @@ #define SIGNAL_POWEROFF_STATE "ChangeState" #define POWER_CONF_FILE "/etc/deviced/power.conf" -static struct display_plugin *disp_plgn; - static struct timeval tv_start_poweroff; -static GList *poweroff_options; -static struct power_option poweroff_opt; +static GList *poweroff_options_list; +static enum poweroff_type poweroff_type = POWEROFF_TYPE_REBOOT; static GList *poweroff_handles; static const char *poweroff_type_flagpaths[] = { // index denotes type @@ -177,24 +175,24 @@ static bool disable_coredump_handler(void) void poweroff_request_shutdown(void) { - const char *method; + const char *systemd_poweroff_method = "Reboot"; - if (poweroff_opt.type == POWEROFF_TYPE_REBOOT) - method = "Reboot"; - else if (poweroff_opt.type == POWEROFF_TYPE_POWEROFF) - method = "PowerOff"; - else if (poweroff_opt.type == POWEROFF_TYPE_EXIT) - method = "Exit"; - else { - _E("Poweroff invalid type(%d).", poweroff_opt.type); + if (poweroff_type == POWEROFF_TYPE_REBOOT) { + systemd_poweroff_method = "Reboot"; + } else if (poweroff_type == POWEROFF_TYPE_POWEROFF) { + systemd_poweroff_method = "PowerOff"; + } else if (poweroff_type == POWEROFF_TYPE_EXIT) { + systemd_poweroff_method = "Exit"; + } else { + _E("Invalid poweroff type=%d", poweroff_type); return; } - CRITICAL_LOG("Requested %s via systemd.", method); + CRITICAL_LOG("Requested %s via systemd.", systemd_poweroff_method); gdbus_call_sync_with_reply_timeout(SYSTEMD_DBUS_DEST, SYSTEMD_DBUS_PATH, SYSTEMD_DBUS_IFACE_MANAGER, - method, + systemd_poweroff_method, NULL, NULL, POWEROFF_WAIT_SYSTEMD_MS); @@ -235,19 +233,15 @@ static void poweroff_delay_for_seconds(void) void poweroff_prepare(void) { - int off = poweroff_opt.type; - - if (off == POWEROFF_TYPE_POWEROFF) + if (poweroff_type == POWEROFF_TYPE_POWEROFF) CRITICAL_LOG("Prepare PowerOff."); - else if (off == POWEROFF_TYPE_REBOOT) + else if (poweroff_type == POWEROFF_TYPE_REBOOT) CRITICAL_LOG("Prepare Reboot."); poweroff_notify_resourced(); disable_systemd_journald(); disable_coredump_handler(); - poweroff_delay_for_seconds(); - disable_display(); /* Below functions follow after notifying DEVICE_NOTIFIER_POWEROFF @@ -263,28 +257,41 @@ void poweroff_prepare(void) - device_change_poweroff() - uevent_control_stop() */ - device_notify(DEVICE_NOTIFIER_POWEROFF, &off); + device_notify_once(DEVICE_NOTIFIER_POWEROFF, (void *)(intptr_t) poweroff_type); } int poweroff_check_revived(void) { - for (int i = 0; i < ARRAY_SIZE(poweroff_type_flagpaths); i++) { - if (access(poweroff_type_flagpaths[i], F_OK) == 0) { - poweroff_opt.type = i; - poweroff_opt.option = NULL; - return 1; - } + if (access(POWER_FLAG_POWEROFF, F_OK) == 0) { + poweroff_type = POWEROFF_TYPE_POWEROFF; + return 1; + } + + if (access(POWER_FLAG_REBOOT, F_OK) == 0) { + poweroff_type = POWEROFF_TYPE_REBOOT; + return 1; + } + + if (access(POWER_FLAG_EXIT, F_OK) == 0) { + poweroff_type = POWEROFF_TYPE_EXIT; + return 1; } return 0; } -static void make_power_flag(enum poweroff_type type, const char *option) +static void mark_poweroff_option(struct power_option *opt) { const char *path; int fd; ssize_t len; + if (!opt) + return; + + enum poweroff_type type = opt->type; + const char *option = opt->option; + if (type <= 0 || type >= ARRAY_SIZE(poweroff_type_flagpaths)) return; @@ -362,30 +369,45 @@ static int poweroff_add_handle(pid_t pid) return 0; } -static gboolean poweroff_wait_timeout_cb(void *data) +static gboolean __poweroff_main(gpointer data) { - char timeout[50] = {0,}; - pid_t pid = (pid_t)((intptr_t)data); + CRITICAL_LOG("Starting poweroff sequence."); - poweroff_remove_handle(pid); + // Watchdog timeout 90 -> 30 sec to reduce delay from unexpected poweroff failure. + sd_notifyf(0, "WATCHDOG_USEC=%llu", (unsigned long long)POWEROFF_WAIT_SYSTEMD_MS*1000); - /* All other processes finished cleanup. Poweroff is now on standby */ - if (poweroff_stage == POWEROFF_WAIT_OTHERS && SYS_G_LIST_LENGTH(poweroff_handles) == 0) { - _D("The last poweroff wait timer for pid %d is expired. Poweroff is now on standby.", pid); + poweroff_prepare(); + poweroff_request_shutdown(); - CRITICAL_LOG("Starting poweroff sequence."); + return G_SOURCE_REMOVE; +} + +static void poweroff_main(void) +{ + static guint poweroff_id = 0; - // Watchdog timeout 90 -> 30 sec to reduce delay from unexpected poweroff failure. - snprintf(timeout, sizeof(timeout), "WATCHDOG_USEC=%llu", (unsigned long long)POWEROFF_WAIT_SYSTEMD_MS*1000); - sd_notify(0, timeout); + if (poweroff_id > 0) + return; - make_power_flag(poweroff_opt.type, poweroff_opt.option); + /* Terminate this subroutine at this point. The procedure returns to the caller, therefore + * the RemovePowerOffWait caller would not be blocked, if they invoked method synchronously. + * And the deviced enter poweroff_main on the next gmainloop iteration. */ + poweroff_id = g_idle_add(__poweroff_main, NULL); +} - if (disp_plgn->pm_lock_internal) - disp_plgn->pm_lock_internal(INTERNAL_LOCK_POWEROFF, LCD_OFF, STAY_CUR_STATE, 0); +static gboolean poweroff_wait_timeout_cb(void *data) +{ + pid_t pid = (pid_t)((intptr_t)data); + + poweroff_remove_handle(pid); - poweroff_prepare(); - poweroff_request_shutdown(); + if (poweroff_stage < POWEROFF_WAIT_OTHERS) + return G_SOURCE_REMOVE; + + /* All other processes finished cleanup. Poweroff is now on standby */ + if (SYS_G_LIST_LENGTH(poweroff_handles) == 0) { + _D("The last poweroff wait timer for pid %d is expired. Poweroff is now on standby.", pid); + poweroff_main(); } else { _D("Poweroff wait timer for pid %d is expired, but keep waiting for others...", pid); } @@ -396,20 +418,20 @@ static gboolean poweroff_wait_timeout_cb(void *data) static gboolean poweroff_start_timers(void *data) { struct poweroff_handle *handle = NULL; - GList *l; + GList *l, *l_next; bool timer_exist = false; - int pid_alive = 0; + _D("POWEROFF_STAGE=WAIT_OTHERS"); poweroff_stage = POWEROFF_WAIT_OTHERS; - SYS_G_LIST_FOREACH(poweroff_handles, l, handle) { - pid_alive = kill(handle->pid, 0); - if (pid_alive == -1) { + SYS_G_LIST_FOREACH_SAFE(poweroff_handles, l, l_next, handle) { + if (kill(handle->pid, 0) == -1) { _D("Pid=%d(%s) is dead.", handle->pid, handle->comm); - handle->timeout = 0; + SYS_G_LIST_REMOVE(poweroff_handles, handle); + continue; } - _D("Run timer, pid=%d(%s) timeout=%d timeout_id=%d.", handle->pid, handle->comm, handle->timeout, handle->timeout_id); + _D("Run timer, pid=%d(%s) timeout=%d", handle->pid, handle->comm, handle->timeout); handle->timeout_id = g_timeout_add_seconds(handle->timeout, poweroff_wait_timeout_cb, @@ -418,33 +440,11 @@ static gboolean poweroff_start_timers(void *data) timer_exist = true; } - if (timer_exist) { + if (timer_exist) return G_SOURCE_REMOVE; - } else { - _D("Handle is NULL."); - - handle = (struct poweroff_handle *)malloc(sizeof(struct poweroff_handle)); - if (handle == NULL) { - _E("Not enough memory."); - return G_SOURCE_REMOVE; - } - handle->pid = getpid(); - handle->timeout = 0; - handle->timeout_id = g_timeout_add_seconds(handle->timeout, - poweroff_wait_timeout_cb, - (void *)((intptr_t)(handle->pid))); - - if (!handle->timeout_id) { - _E("Failed to timer_add."); - free(handle); - return G_SOURCE_REMOVE; - } - - SYS_G_LIST_APPEND(poweroff_handles, handle); - } - - _D("Last Timer: timer_id=%d pid=%d timeout=%d", handle->timeout_id, handle->pid, handle->timeout); + // No need to wait. Strat main poweroff procedure immediately. + poweroff_main(); return G_SOURCE_REMOVE; } @@ -459,31 +459,6 @@ static void system_shutdown_send_system_event(void) bundle_free(b); } -static int poweroff_option_valid(enum poweroff_type type_e, const char *option) -{ - GList *l; - struct power_option *elem; - - SYS_G_LIST_FOREACH(poweroff_options, l, elem) { - if (elem->type != type_e) - continue; - - /* Do not match option - if (option) { - if (elem->option == NULL) - continue; - if (strncmp(elem->option, option, strlen(elem->option))) - continue; - } else { - if (elem->option != NULL) - continue; - } */ - return 1; - } - - return 0; -} - static void poweroff_send_broadcast(int status) { static int old = 0; @@ -509,43 +484,49 @@ static void poweroff_send_broadcast(int status) static int __poweroff_trigger_poweroff(const char *typename, const char *option) { int ret_val; + GList *l; + struct power_option *opt = NULL; if (poweroff_stage >= POWEROFF_TRIGGERED) { _E("Duplicate poweroff request. Poweroff was already triggered."); return -EINVAL; } - enum poweroff_type type_e = poweroff_name_to_type(typename); - if (type_e == POWEROFF_TYPE_INVALID) { - _E("Failed to get type enum value(%d).", type_e); + enum poweroff_type type = poweroff_name_to_type(typename); + if (type == POWEROFF_TYPE_INVALID) { + _E("Failed to get type enum value(%d).", type); return -EINVAL; } - if (poweroff_option_valid(type_e, option)) { - poweroff_opt.type = type_e; - free(poweroff_opt.option); - poweroff_opt.option = NULL; - if (option) - poweroff_opt.option = strdup(option); - } else { - _E("Failed to find supported type(%s). option=%s", typename, (option ? option : "NULL")); - return -EINVAL; + poweroff_type = type; + + if (option) { + SYS_G_LIST_FOREACH(poweroff_options_list, l, opt) { + if (opt->type == type && strncmp(opt->option, option, sizeof(opt->option)) == 0) + break; + } + + /* It writes option onto file /run/reboot. + * The deviced shutdown binary, which is exec of systemd, refers the file. */ + if (opt) + mark_poweroff_option(opt); } - ret_val = vconf_set_int(VCONFKEY_SYSMAN_POWER_OFF_STATUS, poweroff_opt.type); + ret_val = vconf_set_int(VCONFKEY_SYSMAN_POWER_OFF_STATUS, type); if (ret_val < 0) _E("Failed to set vconf value for power off status: %d", vconf_get_ext_errno()); + _D("POWEROFF_STAGE=TRIGGERED"); poweroff_stage = POWEROFF_TRIGGERED; - if (disp_plgn->update_pm_setting) - disp_plgn->update_pm_setting(SETTING_POWEROFF, poweroff_opt.type); + power_disable_autosleep(); + device_notify_once(DEVICE_NOTIFIER_POWEROFF_TRIGGERED, (void *)(intptr_t) type); /* Poweroff event broadcasting */ system_shutdown_send_system_event(); - poweroff_send_broadcast(poweroff_opt.type); + poweroff_send_broadcast(type); /* Skip running animation if option is silent */ - if (poweroff_opt.option != NULL && !strcmp(poweroff_opt.option, "silent")) + if (opt && strncmp(opt->option, "silent", sizeof("silent")) == 0) _D("Skip running poweroff animation."); else poweroff_start_animation(); @@ -658,7 +639,7 @@ static GVariant *remove_poweroff_time(GDBusConnection *conn, GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data) { struct poweroff_handle *handle; - GList *l; + GList *l, *l_next; int ret = 0; pid_t pid; @@ -668,22 +649,16 @@ static GVariant *remove_poweroff_time(GDBusConnection *conn, pid = (pid_t)ret; - SYS_G_LIST_FOREACH(poweroff_handles, l, handle) { - if (handle->pid == pid) + SYS_G_LIST_FOREACH_SAFE(poweroff_handles, l, l_next, handle) { + if (handle->pid == pid) { + _D("Removed poweroff timer. pid=%d(%s)", handle->pid, handle->comm); + SYS_G_LIST_REMOVE(poweroff_handles, handle); break; + } } - if (handle) { - if (handle->timeout_id) - g_source_remove(handle->timeout_id); - handle->timeout = 0; - handle->timeout_id = g_timeout_add_seconds(handle->timeout, - poweroff_wait_timeout_cb, - (void *)((intptr_t)(handle->pid))); - } else { - _E("Invalid pid(%d).", pid); - ret = -1; - } + if (poweroff_stage == POWEROFF_WAIT_OTHERS && SYS_G_LIST_LENGTH(poweroff_handles) == 0) + poweroff_main(); out: return g_variant_new("(i)", ret); @@ -694,6 +669,9 @@ static const dbus_method_s dbus_methods[] = { { "PowerOffWithOption", "ss", "i", dbus_power_option_handler }, /* Public API device_power_reboot() calls this dbus method. */ { "AddPowerOffWait" , NULL, "i", add_poweroff_time }, + /* It is recommended to invoke RemovePowerOffWait by async as the invocation + * could be the last removal of poweroff waitings. And if it is, the deviced + * immediately fall into poweroff main sequence without returning to the caller. */ { "RemovePowerOffWait", NULL, "i", remove_poweroff_time }, /* Add methods here */ }; @@ -723,9 +701,10 @@ static int add_poweroff_option(enum poweroff_type type, const char *option) } opt->type = type; - opt->option = (option ? strdup(option) : NULL); + if (option) + strncpy(opt->option, option, sizeof(opt->option) - 1); - SYS_G_LIST_APPEND(poweroff_options, opt); + SYS_G_LIST_APPEND(poweroff_options_list, opt); _D("Add %s option=%s", name, opt->option); @@ -744,14 +723,10 @@ void poweroff_remove_wait(pid_t pid) static int load_config(struct parse_result *result, void *user_data) { - enum poweroff_type type; - if (MATCH(result->section, "PowerOff") && MATCH(result->name, "Option")) { - type = POWEROFF_TYPE_DIRECT; - add_poweroff_option(type, result->value); + add_poweroff_option(POWEROFF_TYPE_POWEROFF, result->value); } else if (MATCH(result->section, "Reboot") && MATCH(result->name, "Option")) { - type = POWEROFF_TYPE_RESTART; - add_poweroff_option(type, result->value); + add_poweroff_option(POWEROFF_TYPE_REBOOT, result->value); } else if (MATCH(result->section, "PowerState") && MATCH(result->name, "PowerOffDelaySecond")) { sscanf(result->value, "%d", &poweroff_delay_second); } @@ -794,10 +769,3 @@ void power_off_init(void) poweroff_stage = POWEROFF_DEFAULT; } - -static void __CONSTRUCTOR__ initialize(void) -{ - disp_plgn = get_var_display_plugin(); - if (!disp_plgn) - _E("Failed to get display plugin variable."); -} diff --git a/src/power/power-off.h b/src/power/power-off.h index be605fa..c6f8ebf 100644 --- a/src/power/power-off.h +++ b/src/power/power-off.h @@ -47,7 +47,7 @@ enum poweroff_type { struct power_option { enum poweroff_type type; - char *option; + char option[32]; }; struct poweroff_handle { diff --git a/src/shared/device-notifier.c b/src/shared/device-notifier.c index 48c6716..badf4e7 100644 --- a/src/shared/device-notifier.c +++ b/src/shared/device-notifier.c @@ -69,6 +69,7 @@ static const char *device_notifier_type_str[DEVICE_NOTIFIER_MAX] = { NOTIFY_STR(DEVICE_NOTIFIER_DISPLAY_AMBIENT_STATE), NOTIFY_STR(DEVICE_NOTIFIER_DISPLAY_LOCK), NOTIFY_STR(DEVICE_NOTIFIER_POWER_RESUME), + NOTIFY_STR(DEVICE_NOTIFIER_POWEROFF_TRIGGERED), NOTIFY_STR(DEVICE_NOTIFIER_POWEROFF), NOTIFY_STR(DEVICE_NOTIFIER_APPLICATION_BACKGROUND), NOTIFY_STR(DEVICE_NOTIFIER_APPLICATION_FOREGROUND), diff --git a/src/shared/device-notifier.h b/src/shared/device-notifier.h index 1635b3d..3acf22e 100644 --- a/src/shared/device-notifier.h +++ b/src/shared/device-notifier.h @@ -41,6 +41,7 @@ enum device_notifier_type { DEVICE_NOTIFIER_DISPLAY_AMBIENT_STATE, DEVICE_NOTIFIER_DISPLAY_LOCK, DEVICE_NOTIFIER_POWER_RESUME, + DEVICE_NOTIFIER_POWEROFF_TRIGGERED, DEVICE_NOTIFIER_POWEROFF, DEVICE_NOTIFIER_APPLICATION_BACKGROUND, DEVICE_NOTIFIER_APPLICATION_FOREGROUND, -- 2.7.4 From d134245613be47a5b31f5881f25a9591fc820517 Mon Sep 17 00:00:00 2001 From: Youngjae Cho Date: Thu, 26 May 2022 14:07:46 +0900 Subject: [PATCH 16/16] Fix dbus policy typo Change-Id: I84382003be4a4631fdabdc728a739ab755c291c6 Signed-off-by: Youngjae Cho --- conf/org.tizen.system.deviced.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/org.tizen.system.deviced.conf b/conf/org.tizen.system.deviced.conf index a548416..613a72d 100644 --- a/conf/org.tizen.system.deviced.conf +++ b/conf/org.tizen.system.deviced.conf @@ -40,7 +40,7 @@ - -- 2.7.4