From 36f7f06f83143ce0dd3929e161716b61a61c477a Mon Sep 17 00:00:00 2001 From: Sehong Na Date: Sat, 31 May 2014 12:35:48 +0900 Subject: [PATCH 1/1] Initialize Tizen 2.3 --- AUTHORS | 8 + CMakeLists.txt | 400 ++++ LICENSE.Apache-2.0 | 204 ++ README.error.code | 9 + deviced.pc.in | 13 + doxygen/Doxyfile.in | 910 ++++++++ packaging/README.api | 108 + packaging/crash-daemon.service | 11 + packaging/devicectl-start@.service | 7 + packaging/devicectl-stop@.service | 7 + packaging/deviced-pre.service | 8 + packaging/deviced.manifest | 40 + packaging/deviced.rule | 11 + packaging/deviced.service | 14 + packaging/deviced.spec | 266 +++ packaging/libdeviced.manifest | 5 + packaging/liblogd-db.manifest | 11 + packaging/liblogd.manifest | 11 + packaging/shutdown-notify.service | 9 + packaging/zbooting-done.service | 10 + scripts/deviced-pre.sh | 55 + scripts/direct_set_debug.sh | 141 ++ scripts/dump_pm.sh | 21 + scripts/mmc-smack-label | 5 + scripts/movi_format.sh | 34 + scripts/set_usb_debug.sh | 70 + scripts/start_dr.sh | 9 + src/CMakeLists.txt | 3 + src/apps/apps.c | 89 + src/apps/apps.h | 54 + src/apps/launch.c | 223 ++ src/apps/lowbat.c | 112 + src/apps/lowmem.c | 51 + src/apps/mmc.c | 51 + src/apps/poweroff.c | 46 + src/apps/system.c | 91 + src/apps/usb.c | 51 + src/apps/usbotg.c | 112 + src/auto-test/CMakeLists.txt | 66 + src/auto-test/board-info.c | 108 + src/auto-test/boot.c | 177 ++ src/auto-test/cpu-info.c | 78 + src/auto-test/cradle.c | 150 ++ src/auto-test/earjack.c | 117 + src/auto-test/hdmi.c | 218 ++ src/auto-test/keyboard.c | 114 + src/auto-test/main.c | 49 + src/auto-test/power-supply.c | 398 ++++ src/auto-test/storage.c | 117 + src/auto-test/test.c | 70 + src/auto-test/test.h | 107 + src/auto-test/time.c | 114 + src/auto-test/tvout.c | 114 + src/auto-test/udev.c | 111 + src/auto-test/usb.c | 114 + src/battery/battery-micro-emul.conf | 7 + src/battery/battery-micro.conf | 7 + src/battery/battery-time.c | 473 ++++ src/battery/battery.c | 170 ++ src/battery/battery.conf | 7 + src/battery/battery.h | 43 + src/battery/config.c | 73 + src/battery/config.h | 24 + src/battery/lowbat-handler.c | 627 +++++ src/board/board-info.c | 202 ++ src/control/control.c | 238 ++ src/core/common.c | 337 +++ src/core/common.h | 108 + src/core/config-parser.c | 127 + src/core/config-parser.h | 43 + src/core/core.c | 180 ++ src/core/core.h | 28 + src/core/data.h | 31 + src/core/device-change-handler.c | 1767 ++++++++++++++ src/core/device-handler.h | 105 + src/core/device-notifier.c | 120 + src/core/device-notifier.h | 59 + src/core/device-plugin.c | 66 + src/core/device-plugin.h | 32 + src/core/devices.c | 76 + src/core/devices.h | 89 + src/core/edbus-handler.c | 587 +++++ src/core/edbus-handler.h | 62 + src/core/emulator.h | 35 + src/core/execute.c | 93 + src/core/launch.c | 342 +++ src/core/launch.h | 29 + src/core/list.h | 83 + src/core/log.h | 34 + src/core/lowstorage.c | 439 ++++ src/core/main.c | 128 + src/core/noti.c | 86 + src/core/noti.h | 28 + src/core/power-supply.c | 815 +++++++ src/core/power-supply.h | 35 + src/core/predefine.c | 273 +++ src/core/predefine.h | 27 + src/core/queue.c | 283 +++ src/core/queue.h | 67 + src/core/sig-handler.c | 93 + src/core/sysnoti.c | 342 +++ src/core/sysnoti.h | 34 + src/core/udev.h | 98 + src/cpu/cpu-handler.c | 617 +++++ src/devicectl/CMakeLists.txt | 39 + src/devicectl/devicectl.c | 211 ++ src/deviced/dd-battery.h | 147 ++ src/deviced/dd-common.h | 39 + src/deviced/dd-control.h | 118 + src/deviced/dd-deviced-managed.h | 65 + src/deviced/dd-deviced.h | 402 ++++ src/deviced/dd-display.h | 620 +++++ src/deviced/dd-haptic.h | 654 ++++++ src/deviced/dd-led.h | 191 ++ src/deviced/dd-mmc.h | 165 ++ src/deviced/dd-storage.h | 77 + src/deviced/dd-usbhost.h | 259 +++ src/deviced/deviced_doc.h | 42 + src/deviced/haptic-module.h | 88 + src/deviced/haptic-plugin-intf.h | 40 + src/display/alpm.c | 193 ++ src/display/auto-brightness.c | 686 ++++++ src/display/brightness.c | 253 ++ src/display/brightness.h | 33 + src/display/core.c | 2450 ++++++++++++++++++++ src/display/core.h | 167 ++ src/display/device-interface.c | 637 +++++ src/display/device-interface.h | 97 + src/display/display-dbus.c | 1274 ++++++++++ src/display/display-emul.conf | 37 + src/display/display-exynos.conf | 40 + src/display/display-msm.conf | 37 + src/display/display-ops.c | 74 + src/display/display-ops.h | 49 + src/display/enhance.c | 676 ++++++ src/display/enhance.h | 31 + src/display/hbm.c | 261 +++ src/display/key-filter-micro.c | 285 +++ src/display/key-filter.c | 828 +++++++ src/display/lock-detector.c | 223 ++ src/display/lock-detector.h | 35 + src/display/poll.c | 412 ++++ src/display/poll.h | 128 + src/display/setting.c | 248 ++ src/display/setting.h | 130 ++ src/display/smartstay.c | 232 ++ src/display/util.h | 48 + src/display/weaks.h | 39 + src/display/x-lcd-on.c | 65 + src/extcon/extcon.c | 111 + src/hall/hall-handler.c | 162 ++ src/hall/hall-handler.h | 33 + src/haptic/HW_touch_30ms_sharp.ivt | Bin 0 -> 38 bytes src/haptic/emulator.c | 148 ++ src/haptic/external.c | 98 + src/haptic/haptic.c | 624 +++++ src/haptic/haptic.h | 46 + src/haptic/standard.c | 367 +++ src/led/ir.c | 73 + src/led/led.xml | 41 + src/led/noti.c | 74 + src/led/pattern.c | 307 +++ src/led/rgb.c | 645 ++++++ src/led/torch.c | 243 ++ src/led/torch.h | 29 + src/led/xml.c | 253 ++ src/led/xml.h | 41 + src/libdeviced/CMakeLists.txt | 39 + src/libdeviced/battery.c | 58 + src/libdeviced/control.c | 138 ++ src/libdeviced/deviced-conf.c | 292 +++ src/libdeviced/deviced-noti.c | 605 +++++ src/libdeviced/deviced-util.c | 132 ++ src/libdeviced/display.c | 746 ++++++ src/libdeviced/haptic.c | 767 ++++++ src/libdeviced/led.c | 174 ++ src/libdeviced/mmc.c | 211 ++ src/libdeviced/storage.c | 82 + src/libdeviced/usbhost.c | 254 ++ src/mmc/app2ext.c | 166 ++ src/mmc/config.c | 104 + src/mmc/config.h | 31 + src/mmc/cprm.c | 250 ++ src/mmc/ext4.c | 197 ++ src/mmc/mmc-handler.c | 978 ++++++++ src/mmc/mmc-handler.h | 66 + src/mmc/mmc.conf | 3 + src/mmc/uevent.c | 149 ++ src/mmc/vfat.c | 151 ++ src/pmqos/pmqos-plugin.c | 153 ++ src/pmqos/pmqos.c | 385 +++ src/pmqos/pmqos.conf | 15 + src/pmqos/pmqos.h | 38 + src/power/power-handler.c | 662 ++++++ src/power/power-handler.h | 36 + src/power/systemd-power.c | 329 +++ src/powersaver/powersaver.c | 159 ++ src/predefine_act_plugin/CMakeLists.txt | 38 + src/predefine_act_plugin/build.sh | 7 + src/predefine_act_plugin/xxx-predefine.c | 45 + src/proc/cpu-info.c | 151 ++ src/proc/pmon-handler.c | 285 +++ src/proc/proc-handler.c | 772 ++++++ src/proc/proc-handler.h | 31 + src/restarter/CMakeLists.txt | 37 + src/restarter/restart.c | 34 + src/shared/CMakeLists.txt | 7 + src/shared/common.h | 49 + src/shared/dbus.c | 345 +++ src/shared/dbus.h | 221 ++ src/shared/deviced-internal.h | 38 + src/shared/deviced-priv.h | 47 + src/shared/list.h | 50 + src/shared/log-macro.h | 51 + src/shared/log.h | 30 + src/shared/score-defines.h | 31 + src/ta/ta-handler.c | 78 + src/telephony/telephony.c | 421 ++++ src/testmode/testmode.c | 87 + src/ticker/ticker.c | 77 + src/ticker/ticker.h | 37 + src/time/time-handler.c | 382 +++ src/touch/touch-controller.c | 135 ++ src/touch/touch-controller.h | 39 + src/touch/touch-plugin.c | 113 + src/touch/touch-plugin.h | 25 + src/touch/touch-util.h | 30 + src/touch/touch.c | 126 + src/touch/touch.h | 49 + src/usb/configurations/conf-supported.xml | 11 + src/usb/configurations/usb-configurations.xml | 328 +++ src/usb/usb-client-control.c | 94 + src/usb/usb-client-dbus.c | 76 + src/usb/usb-client-set.c | 601 +++++ src/usb/usb-client-xml.c | 919 ++++++++ src/usb/usb-client.c | 502 ++++ src/usb/usb-client.h | 127 + src/usb/usb-common.c | 31 + src/usb/usb-common.h | 26 + src/usb/usb-handler.c | 107 + src/usb/usb-host-camera.c | 187 ++ src/usb/usb-host-dbus.c | 759 ++++++ src/usb/usb-host-hid.c | 243 ++ src/usb/usb-host-naming.c | 147 ++ src/usb/usb-host-printer.c | 182 ++ src/usb/usb-host-storage-vfat.c | 90 + src/usb/usb-host-storage.c | 1279 ++++++++++ src/usb/usb-host.c | 437 ++++ src/usb/usb-host.h | 179 ++ test/_export_env.sh | 8 + test/_export_target_env.sh | 7 + test/build.sh | 16 + test/clean.sh | 11 + test/config | 3 + test/execute.sh | 15 + test/push.sh | 11 + test/testcase/Makefile | 28 + test/testcase/tslist | 10 + test/testcase/utc_system_deviced_battery.c | 101 + test/testcase/utc_system_deviced_control.c | 141 ++ test/testcase/utc_system_deviced_deviced.c | 714 ++++++ test/testcase/utc_system_deviced_deviced_managed.c | 422 ++++ test/testcase/utc_system_deviced_display.c | 649 ++++++ test/testcase/utc_system_deviced_haptic.c | 984 ++++++++ test/testcase/utc_system_deviced_led.c | 248 ++ test/testcase/utc_system_deviced_mmc.c | 105 + test/testcase/utc_system_deviced_storage.c | 131 ++ test/tet_scen | 7 + test/tetbuild.cfg | 5 + test/tetclean.cfg | 5 + test/tetexec.cfg | 5 + 271 files changed, 52480 insertions(+) create mode 100644 AUTHORS create mode 100755 CMakeLists.txt create mode 100644 LICENSE.Apache-2.0 create mode 100644 README.error.code create mode 100644 deviced.pc.in create mode 100644 doxygen/Doxyfile.in create mode 100644 packaging/README.api create mode 100644 packaging/crash-daemon.service create mode 100644 packaging/devicectl-start@.service create mode 100644 packaging/devicectl-stop@.service create mode 100644 packaging/deviced-pre.service create mode 100644 packaging/deviced.manifest create mode 100644 packaging/deviced.rule create mode 100644 packaging/deviced.service create mode 100644 packaging/deviced.spec create mode 100644 packaging/libdeviced.manifest create mode 100644 packaging/liblogd-db.manifest create mode 100644 packaging/liblogd.manifest create mode 100644 packaging/shutdown-notify.service create mode 100644 packaging/zbooting-done.service create mode 100755 scripts/deviced-pre.sh create mode 100755 scripts/direct_set_debug.sh create mode 100644 scripts/dump_pm.sh create mode 100755 scripts/mmc-smack-label create mode 100755 scripts/movi_format.sh create mode 100755 scripts/set_usb_debug.sh create mode 100755 scripts/start_dr.sh create mode 100755 src/CMakeLists.txt create mode 100755 src/apps/apps.c create mode 100755 src/apps/apps.h create mode 100644 src/apps/launch.c create mode 100644 src/apps/lowbat.c create mode 100644 src/apps/lowmem.c create mode 100644 src/apps/mmc.c create mode 100644 src/apps/poweroff.c create mode 100644 src/apps/system.c create mode 100644 src/apps/usb.c create mode 100644 src/apps/usbotg.c create mode 100755 src/auto-test/CMakeLists.txt create mode 100644 src/auto-test/board-info.c create mode 100644 src/auto-test/boot.c create mode 100644 src/auto-test/cpu-info.c create mode 100644 src/auto-test/cradle.c create mode 100644 src/auto-test/earjack.c create mode 100644 src/auto-test/hdmi.c create mode 100644 src/auto-test/keyboard.c create mode 100644 src/auto-test/main.c create mode 100644 src/auto-test/power-supply.c create mode 100644 src/auto-test/storage.c create mode 100644 src/auto-test/test.c create mode 100644 src/auto-test/test.h create mode 100644 src/auto-test/time.c create mode 100644 src/auto-test/tvout.c create mode 100644 src/auto-test/udev.c create mode 100644 src/auto-test/usb.c create mode 100644 src/battery/battery-micro-emul.conf create mode 100644 src/battery/battery-micro.conf create mode 100644 src/battery/battery-time.c create mode 100644 src/battery/battery.c create mode 100644 src/battery/battery.conf create mode 100644 src/battery/battery.h create mode 100644 src/battery/config.c create mode 100644 src/battery/config.h create mode 100644 src/battery/lowbat-handler.c create mode 100644 src/board/board-info.c create mode 100644 src/control/control.c create mode 100644 src/core/common.c create mode 100644 src/core/common.h create mode 100644 src/core/config-parser.c create mode 100644 src/core/config-parser.h create mode 100644 src/core/core.c create mode 100644 src/core/core.h create mode 100644 src/core/data.h create mode 100644 src/core/device-change-handler.c create mode 100644 src/core/device-handler.h create mode 100644 src/core/device-notifier.c create mode 100644 src/core/device-notifier.h create mode 100644 src/core/device-plugin.c create mode 100644 src/core/device-plugin.h create mode 100644 src/core/devices.c create mode 100644 src/core/devices.h create mode 100644 src/core/edbus-handler.c create mode 100644 src/core/edbus-handler.h create mode 100644 src/core/emulator.h create mode 100755 src/core/execute.c create mode 100644 src/core/launch.c create mode 100644 src/core/launch.h create mode 100644 src/core/list.h create mode 100644 src/core/log.h create mode 100755 src/core/lowstorage.c create mode 100644 src/core/main.c create mode 100644 src/core/noti.c create mode 100644 src/core/noti.h create mode 100644 src/core/power-supply.c create mode 100644 src/core/power-supply.h create mode 100755 src/core/predefine.c create mode 100644 src/core/predefine.h create mode 100644 src/core/queue.c create mode 100644 src/core/queue.h create mode 100644 src/core/sig-handler.c create mode 100755 src/core/sysnoti.c create mode 100644 src/core/sysnoti.h create mode 100644 src/core/udev.h create mode 100644 src/cpu/cpu-handler.c create mode 100755 src/devicectl/CMakeLists.txt create mode 100644 src/devicectl/devicectl.c create mode 100644 src/deviced/dd-battery.h create mode 100644 src/deviced/dd-common.h create mode 100644 src/deviced/dd-control.h create mode 100644 src/deviced/dd-deviced-managed.h create mode 100644 src/deviced/dd-deviced.h create mode 100644 src/deviced/dd-display.h create mode 100644 src/deviced/dd-haptic.h create mode 100644 src/deviced/dd-led.h create mode 100644 src/deviced/dd-mmc.h create mode 100644 src/deviced/dd-storage.h create mode 100644 src/deviced/dd-usbhost.h create mode 100644 src/deviced/deviced_doc.h create mode 100644 src/deviced/haptic-module.h create mode 100644 src/deviced/haptic-plugin-intf.h create mode 100644 src/display/alpm.c create mode 100644 src/display/auto-brightness.c create mode 100644 src/display/brightness.c create mode 100644 src/display/brightness.h create mode 100644 src/display/core.c create mode 100644 src/display/core.h create mode 100644 src/display/device-interface.c create mode 100644 src/display/device-interface.h create mode 100644 src/display/display-dbus.c create mode 100644 src/display/display-emul.conf create mode 100644 src/display/display-exynos.conf create mode 100644 src/display/display-msm.conf create mode 100644 src/display/display-ops.c create mode 100644 src/display/display-ops.h create mode 100644 src/display/enhance.c create mode 100644 src/display/enhance.h create mode 100644 src/display/hbm.c create mode 100644 src/display/key-filter-micro.c create mode 100644 src/display/key-filter.c create mode 100644 src/display/lock-detector.c create mode 100644 src/display/lock-detector.h create mode 100644 src/display/poll.c create mode 100644 src/display/poll.h create mode 100644 src/display/setting.c create mode 100644 src/display/setting.h create mode 100644 src/display/smartstay.c create mode 100644 src/display/util.h create mode 100644 src/display/weaks.h create mode 100644 src/display/x-lcd-on.c create mode 100644 src/extcon/extcon.c create mode 100644 src/hall/hall-handler.c create mode 100644 src/hall/hall-handler.h create mode 100755 src/haptic/HW_touch_30ms_sharp.ivt create mode 100644 src/haptic/emulator.c create mode 100644 src/haptic/external.c create mode 100644 src/haptic/haptic.c create mode 100644 src/haptic/haptic.h create mode 100644 src/haptic/standard.c create mode 100644 src/led/ir.c create mode 100644 src/led/led.xml create mode 100644 src/led/noti.c create mode 100644 src/led/pattern.c create mode 100644 src/led/rgb.c create mode 100644 src/led/torch.c create mode 100644 src/led/torch.h create mode 100644 src/led/xml.c create mode 100644 src/led/xml.h create mode 100755 src/libdeviced/CMakeLists.txt create mode 100644 src/libdeviced/battery.c create mode 100644 src/libdeviced/control.c create mode 100755 src/libdeviced/deviced-conf.c create mode 100755 src/libdeviced/deviced-noti.c create mode 100644 src/libdeviced/deviced-util.c create mode 100644 src/libdeviced/display.c create mode 100644 src/libdeviced/haptic.c create mode 100644 src/libdeviced/led.c create mode 100644 src/libdeviced/mmc.c create mode 100644 src/libdeviced/storage.c create mode 100644 src/libdeviced/usbhost.c create mode 100755 src/mmc/app2ext.c create mode 100644 src/mmc/config.c create mode 100644 src/mmc/config.h create mode 100755 src/mmc/cprm.c create mode 100644 src/mmc/ext4.c create mode 100644 src/mmc/mmc-handler.c create mode 100644 src/mmc/mmc-handler.h create mode 100644 src/mmc/mmc.conf create mode 100644 src/mmc/uevent.c create mode 100644 src/mmc/vfat.c create mode 100644 src/pmqos/pmqos-plugin.c create mode 100644 src/pmqos/pmqos.c create mode 100644 src/pmqos/pmqos.conf create mode 100644 src/pmqos/pmqos.h create mode 100644 src/power/power-handler.c create mode 100644 src/power/power-handler.h create mode 100644 src/power/systemd-power.c create mode 100644 src/powersaver/powersaver.c create mode 100644 src/predefine_act_plugin/CMakeLists.txt create mode 100755 src/predefine_act_plugin/build.sh create mode 100644 src/predefine_act_plugin/xxx-predefine.c create mode 100644 src/proc/cpu-info.c create mode 100644 src/proc/pmon-handler.c create mode 100644 src/proc/proc-handler.c create mode 100644 src/proc/proc-handler.h create mode 100644 src/restarter/CMakeLists.txt create mode 100644 src/restarter/restart.c create mode 100755 src/shared/CMakeLists.txt create mode 100644 src/shared/common.h create mode 100644 src/shared/dbus.c create mode 100644 src/shared/dbus.h create mode 100644 src/shared/deviced-internal.h create mode 100644 src/shared/deviced-priv.h create mode 100644 src/shared/list.h create mode 100644 src/shared/log-macro.h create mode 100644 src/shared/log.h create mode 100644 src/shared/score-defines.h create mode 100644 src/ta/ta-handler.c create mode 100644 src/telephony/telephony.c create mode 100644 src/testmode/testmode.c create mode 100755 src/ticker/ticker.c create mode 100755 src/ticker/ticker.h create mode 100644 src/time/time-handler.c create mode 100644 src/touch/touch-controller.c create mode 100644 src/touch/touch-controller.h create mode 100644 src/touch/touch-plugin.c create mode 100644 src/touch/touch-plugin.h create mode 100644 src/touch/touch-util.h create mode 100644 src/touch/touch.c create mode 100644 src/touch/touch.h create mode 100644 src/usb/configurations/conf-supported.xml create mode 100644 src/usb/configurations/usb-configurations.xml create mode 100755 src/usb/usb-client-control.c create mode 100755 src/usb/usb-client-dbus.c create mode 100755 src/usb/usb-client-set.c create mode 100755 src/usb/usb-client-xml.c create mode 100755 src/usb/usb-client.c create mode 100755 src/usb/usb-client.h create mode 100755 src/usb/usb-common.c create mode 100755 src/usb/usb-common.h create mode 100755 src/usb/usb-handler.c create mode 100755 src/usb/usb-host-camera.c create mode 100755 src/usb/usb-host-dbus.c create mode 100755 src/usb/usb-host-hid.c create mode 100755 src/usb/usb-host-naming.c create mode 100755 src/usb/usb-host-printer.c create mode 100644 src/usb/usb-host-storage-vfat.c create mode 100755 src/usb/usb-host-storage.c create mode 100755 src/usb/usb-host.c create mode 100755 src/usb/usb-host.h create mode 100755 test/_export_env.sh create mode 100755 test/_export_target_env.sh create mode 100755 test/build.sh create mode 100755 test/clean.sh create mode 100644 test/config create mode 100755 test/execute.sh create mode 100755 test/push.sh create mode 100644 test/testcase/Makefile create mode 100644 test/testcase/tslist create mode 100644 test/testcase/utc_system_deviced_battery.c create mode 100644 test/testcase/utc_system_deviced_control.c create mode 100644 test/testcase/utc_system_deviced_deviced.c create mode 100644 test/testcase/utc_system_deviced_deviced_managed.c create mode 100644 test/testcase/utc_system_deviced_display.c create mode 100644 test/testcase/utc_system_deviced_haptic.c create mode 100644 test/testcase/utc_system_deviced_led.c create mode 100644 test/testcase/utc_system_deviced_mmc.c create mode 100644 test/testcase/utc_system_deviced_storage.c create mode 100644 test/tet_scen create mode 100644 test/tetbuild.cfg create mode 100644 test/tetclean.cfg create mode 100644 test/tetexec.cfg diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..63a6fc5 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,8 @@ +ChanWoo Choi +Byung-Soo Kim +Taeyoung Kim +Gi-Yeol Ok +Kyungmin Park +SeungHun Pi +Juho Son +Jiyoung Yun diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100755 index 0000000..3ce4663 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,400 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(deviced C) + +######################################################## +# Generation options: +# -DBUILD_DOC_ONLY - only doxygen documentation is build +# -DBUILD_DOC - build also doxygen documentation +# +# NOTE: +# Remember to add all directories with files to DOC_SRC_DIRS_IN list +# +######################################################## + +IF(BUILD_DOC_ONLY) + SET(BUILD_EXECUTABLE FALSE) + SET(BUILD_DOC TRUE) +ELSE(BUILD_DOC_ONLY) + SET(BUILD_EXECUTABLE TRUE) +ENDIF(BUILD_DOC_ONLY) + +IF(BUILD_DOC) + SET( DOC_SRC_DIRS_IN + ${CMAKE_SOURCE_DIR}/src/deviced + ) + FOREACH(doc_dir ${DOC_SRC_DIRS_IN}) + SET(DOC_SRC_DIRS "${DOC_SRC_DIRS} ${doc_dir}") + ENDFOREACH(doc_dir) + + FIND_PACKAGE(Doxygen REQUIRED) + + get_filename_component( DOXYGEN_DOC_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR} PATH) + + #adjust the doxygen configuration for this project + configure_file(${CMAKE_SOURCE_DIR}/doxygen/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/doxygen/Doxyfile @ONLY) + + #build the documentation + add_custom_target( doc ALL + ${DOXYGEN_EXECUTABLE} + ${CMAKE_CURRENT_BINARY_DIR}/doxygen/Doxyfile + WORKING_DIRECTORY ${CMAKE_DOXYGEN_DIRECTORY} + COMMENT "Generating documentation with Doxygen" VERBATIM + ) + +ENDIF(BUILD_DOC) + +IF(BUILD_EXECUTABLE) + +######################################################## +# Build options: +# -DMICRO_DD - for tizenw project +# -DTIZEN_ENGINEER_MODE - +######################################################## +IF("$ENV{CFLAGS}" MATCHES "-DMICRO_DD") + OPTION(USE_MICRO_DD "Use Micro DD" ON) +ENDIF() + +IF("$ENV{CFLAGS}" MATCHES "-DTIZEN_ENGINEER_MODE") + OPTION(USE_ENGINEER_MODE "Use Engineer mode" ON) +ENDIF() + +IF("${ARCH}" STREQUAL "emulator") + OPTION(USE_EMULATOR "Use Emulator" ON) +ELSEIF("${ARCH}" STREQUAL "arm") + OPTION(USE_ARM "Use Arm" ON) +ENDIF() + +IF("$ENV{CFLAGS}" MATCHES "-DSYSTEMD_SHUTDOWN") + OPTION(USE_SYSTEMD_SHUTDOWN "Use systemd shutdown" ON) +ENDIF() + +######################################################## +# Deviced CMakeLists.txt +######################################################## +SET(PREFIX ${CMAKE_INSTALL_PREFIX}) +SET(EXEC_PREFIX "${PREFIX}/bin") +SET(LIBDIR "${PREFIX}/lib") +SET(INCLUDEDIR "${PREFIX}/include/${PROJECT_NAME}") +SET(DATADIR "${PREFIX}/share/${PROJECT_NAME}") +SET(VERSION 0.1.0) + +SET(SRCS + src/battery/config.c + src/battery/lowbat-handler.c + src/battery/battery.c + src/core/device-notifier.c + src/core/main.c + src/core/sysnoti.c + src/core/launch.c + src/core/queue.c + src/core/core.c + src/core/devices.c + src/core/sig-handler.c + src/core/device-change-handler.c + src/core/predefine.c + src/core/common.c + src/core/config-parser.c + src/core/execute.c + src/core/edbus-handler.c + src/core/power-supply.c + src/core/lowstorage.c + src/proc/cpu-info.c + src/board/board-info.c + src/proc/proc-handler.c + src/ta/ta-handler.c + src/time/time-handler.c + src/ticker/ticker.c + src/testmode/testmode.c +) + +IF(USE_SYSTEMD_SHUTDOWN) +SET(SRCS ${SRCS} + src/power/systemd-power.c +) +ELSE() +SET(SRCS ${SRCS} + src/power/power-handler.c +) +ENDIF() + +IF(NOT USE_MICRO_DD) + IF(USE_EMULATOR) + ADD_DEFINITIONS("-DMOBILE_EMULATOR") + SET(SRCS ${SRCS} + src/core/noti.c + ) + ENDIF(USE_EMULATOR) +ENDIF(NOT USE_MICRO_DD) + +SET(SRCS ${SRCS} + src/apps/apps.c + src/apps/lowbat.c + src/apps/poweroff.c + src/pmqos/pmqos.c + src/pmqos/pmqos-plugin.c +) + +IF(NOT USE_MICRO_DD) +SET(SRCS ${SRCS} + src/battery/battery-time.c + src/extcon/extcon.c + src/cpu/cpu-handler.c + src/hall/hall-handler.c + src/proc/pmon-handler.c + src/apps/launch.c + src/apps/lowmem.c + src/apps/mmc.c + src/apps/usb.c + src/apps/usbotg.c + src/apps/system.c +) + +IF(NOT USE_SYSTEMD_SHUTDOWN) +SET(SRCS ${SRCS} + src/telephony/telephony.c +) +ENDIF() + +SET(SRCS ${SRCS} + src/mmc/mmc-handler.c + src/mmc/uevent.c + src/mmc/config.c + src/mmc/cprm.c + src/mmc/app2ext.c +) + +FIND_PROGRAM(UNAME NAMES uname) +EXEC_PROGRAM("${UNAME}" ARGS "-m" OUTPUT_VARIABLE "ARC") +IF(USE_EMULATOR) +SET(SRCS ${SRCS} + src/mmc/ext4.c + ) +ENDIF(USE_EMULATOR) + +SET(SRCS ${SRCS} + src/mmc/vfat.c +) +ENDIF(NOT USE_MICRO_DD) + +# display(pm) +SET(SRCS ${SRCS} + src/display/core.c + src/display/display-dbus.c + src/display/hbm.c + src/display/device-interface.c + src/display/lock-detector.c + src/display/poll.c + src/display/setting.c + src/display/display-ops.c +) + +IF(USE_MICRO_DD) +SET(SRCS ${SRCS} + src/display/alpm.c + src/display/key-filter-micro.c +) +ELSE() +SET(SRCS ${SRCS} + src/display/brightness.c + src/display/key-filter.c + src/display/enhance.c + src/display/auto-brightness.c + src/display/smartstay.c +) +ENDIF(USE_MICRO_DD) + +SET(SRCS ${SRCS} + src/led/ir.c + src/led/torch.c + src/led/pattern.c + src/led/noti.c + src/led/xml.c +) + +IF(NOT USE_MICRO_DD) +SET(SRCS ${SRCS} + src/touch/touch.c + src/touch/touch-controller.c + src/touch/touch-plugin.c) + + +SET(SRCS ${SRCS} + src/led/rgb.c +) +ENDIF(NOT USE_MICRO_DD) + +SET(SRCS ${SRCS} + src/control/control.c +) + +SET(SRCS ${SRCS} + src/haptic/haptic.c + src/haptic/standard.c + src/haptic/external.c + src/haptic/emulator.c) + +# usb client +SET(SRCS ${SRCS} + src/usb/usb-common.c + src/usb/usb-client.c + src/usb/usb-client-xml.c + src/usb/usb-client-set.c + src/usb/usb-client-control.c + src/usb/usb-client-dbus.c +) + +# usb host +IF(NOT USE_MICRO_DD) +SET(SRCS ${SRCS} + src/usb/usb-common.c + src/usb/usb-host.c + src/usb/usb-host-dbus.c + src/usb/usb-host-storage.c + src/usb/usb-host-storage-vfat.c + src/usb/usb-host-hid.c + src/usb/usb-host-camera.c + src/usb/usb-host-printer.c + src/usb/usb-host-naming.c +) +ENDIF(NOT USE_MICRO_DD) + +# powersaver mode +IF(USE_MICRO_DD) +SET(SRCS ${SRCS} + src/powersaver/powersaver.c +) +ENDIF(USE_MICRO_DD) + +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/src) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/src/deviced) +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/src/logd/src/shared) + +SET(PKG_MODULES + ecore + ecore-file + ecore-x + edbus + eina + vconf + dlog + device-node + libxml-2.0 + capi-base-common +) + +IF(NOT USE_MICRO_DD) +SET(PKG_MODULES ${PKG_MODULES} + tapi + modem + sensor +) +ENDIF() + +IF(USE_TRUSTZONE_QUALCOMM) +SET(PKG_MODULES ${PKG_MODULES} + tee-qsee +) +ENDIF() + +IF(NOT USE_MICRO_DD) + IF(USE_EMULATOR) + SET(PKG_MODULES ${PKG_MODULES} + heynoti + ) + ENDIF(USE_EMULATOR) +ENDIF(NOT USE_MICRO_DD) +INCLUDE(FindPkgConfig) +pkg_check_modules(pkgs REQUIRED ${PKG_MODULES}) + +FOREACH(flag ${pkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden -Werror") +IF(USE_ENGINEER_MODE) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -g -fno-omit-frame-pointer -finstrument-functions") +ELSE() + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -g -fno-omit-frame-pointer") +ENDIF() +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -lrt") +MESSAGE("FLAGS: ${CMAKE_C_FLAGS}") + +ADD_DEFINITIONS("-DPREFIX=\"${CMAKE_INSTALL_PREFIX}\"") +ADD_DEFINITIONS("-DFACTORYFS=\"$ENV{FACTORYFS}\"") +ADD_DEFINITIONS("-DLIBDIR=\"${LIBDIR}\"") +ADD_DEFINITIONS("-DENABLE_KEY_FILTER") +ADD_DEFINITIONS("-DENABLE_X_LCD_ONOFF") +ADD_DEFINITIONS("-DENABLE_DEVICED_DLOG") +ADD_DEFINITIONS("-DENABLE_LIBDEVICED_DLOG") +ADD_DEFINITIONS("-DENABLE_PM_LOG") +IF(USE_ARM) + ADD_DEFINITIONS("-DTARGET") +ELSEIF(USE_EMULATOR) + ADD_DEFINITIONS("-DEMULATOR") +ENDIF() +ADD_DEFINITIONS("-DDEBUG") + +ADD_EXECUTABLE(${PROJECT_NAME} ${SRCS}) +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS} "-ldl" "-lm" "-ludev" "-ledbus" shared) +INSTALL(TARGETS ${PROJECT_NAME} DESTINATION bin) + +INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/src/deviced/ DESTINATION include/${PROJECT_NAME} + FILES_MATCHING + PATTERN "*_doc.h" EXCLUDE + PATTERN "*.h") + +CONFIGURE_FILE(${PROJECT_NAME}.pc.in ${PROJECT_NAME}.pc @ONLY) +INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc DESTINATION lib/pkgconfig) + +IF(USE_ARM AND NOT USE_MICRO_DD) + INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/src/haptic/HW_touch_30ms_sharp.ivt DESTINATION ${DATADIR}) + INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/src/led/led.xml DESTINATION ${DATADIR}) +ENDIF(USE_ARM AND NOT USE_MICRO_DD) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/scripts/dump_pm.sh DESTINATION /opt/etc/dump.d/module.d) + +IF(USE_TRUSTZONE_QUALCOMM) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/src/display/display-msm.conf DESTINATION /etc/deviced RENAME display.conf) +ELSEIF(USE_EMULATOR) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/src/display/display-emul.conf DESTINATION /etc/deviced RENAME display.conf) +ELSE() +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/src/display/display-exynos.conf DESTINATION /etc/deviced RENAME display.conf) +ENDIF() +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/src/mmc/mmc.conf DESTINATION /etc/deviced RENAME mmc.conf) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/src/pmqos/pmqos.conf DESTINATION /etc/deviced RENAME pmqos.conf) + +IF(USE_MICRO_DD) + IF(USE_EMULATOR) + INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/src/battery/battery-micro-emul.conf DESTINATION /etc/deviced RENAME battery.conf) + ELSE(USR_EMULATOR) + INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/src/battery/battery-micro.conf DESTINATION /etc/deviced RENAME battery.conf) + ENDIF(USE_EMULATOR) +ELSE(USE_MICRO_DD) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/src/battery/battery.conf DESTINATION /etc/deviced RENAME battery.conf) +ENDIF(USE_MICRO_DD) + +INSTALL(PROGRAMS ${CMAKE_BINARY_DIR}/scripts/deviced-pre.sh DESTINATION bin) +INSTALL(FILES ${CMAKE_SOURCE_DIR}/packaging/${PROJECT_NAME}.rule DESTINATION /etc/smack/accesses2.d) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/src/usb/configurations/conf-supported.xml DESTINATION ${DATADIR}/usb-configurations) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/src/usb/configurations/usb-configurations.xml DESTINATION ${DATADIR}/usb-configurations) + +IF(NOT USE_MICRO_DD) + INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/scripts/movi_format.sh DESTINATION bin) + INSTALL(PROGRAMS ${CMAKE_CURRENT_SOURCE_DIR}/scripts/mmc-smack-label DESTINATION bin) +ENDIF(NOT USE_MICRO_DD) + +# USB (data-router) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/scripts/start_dr.sh DESTINATION ${EXEC_PREFIX}) + +# USB (Manual setting) +IF(USE_ENGINEER_MODE) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/scripts/direct_set_debug.sh DESTINATION ${EXEC_PREFIX}) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/scripts/set_usb_debug.sh DESTINATION ${EXEC_PREFIX}) +ENDIF() + +ADD_SUBDIRECTORY(src) +ADD_SUBDIRECTORY(src/libdeviced) +ADD_SUBDIRECTORY(src/devicectl) +ADD_SUBDIRECTORY(src/auto-test) + +ENDIF(BUILD_EXECUTABLE) diff --git a/LICENSE.Apache-2.0 b/LICENSE.Apache-2.0 new file mode 100644 index 0000000..9c13a9b --- /dev/null +++ b/LICENSE.Apache-2.0 @@ -0,0 +1,204 @@ +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + diff --git a/README.error.code b/README.error.code new file mode 100644 index 0000000..61cd9c6 --- /dev/null +++ b/README.error.code @@ -0,0 +1,9 @@ +DBus Error note + +Functions Defines Values +====================================================================== +dbus_bus_get EPERM 1 +dbus_message_get_args ENOMSG 42 +dbus_connection_send_with_reply_and_block ECOMM 70 +dbus_connection_send ECOMM 70 +dbus_message_new_method_call EBADMSG 74 diff --git a/deviced.pc.in b/deviced.pc.in new file mode 100644 index 0000000..6ce4c9b --- /dev/null +++ b/deviced.pc.in @@ -0,0 +1,13 @@ +# Package Information for pkg-config + +prefix=@PREFIX@ +exec_prefix=@EXEC_PREFIX@ +libdir=/usr/lib +includedir=/usr/include/deviced + +Name: deviced +Description: Tizen platform device control library +Version: @VERSION@ +Requires: +Libs: -L${libdir} -ldeviced +Cflags: -I${includedir} diff --git a/doxygen/Doxyfile.in b/doxygen/Doxyfile.in new file mode 100644 index 0000000..73655a4 --- /dev/null +++ b/doxygen/Doxyfile.in @@ -0,0 +1,910 @@ +# Doxyfile 1.4.4 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +PROJECT_NAME = @CMAKE_PROJECT_NAME@ +PROJECT_NUMBER = +OUTPUT_DIRECTORY = @DOXYGEN_DOC_OUTPUT_DIRECTORY@/doc +CREATE_SUBDIRS = NO +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +INLINE_INHERITED_MEMB = YES + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like the Qt-style comments (thus requiring an +# explicit @brief command for a brief description. +JAVADOC_AUTOBRIEF = YES + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. +INHERIT_DOCS = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +DISTRIBUTE_GROUP_DOC = NO + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources +# only. Doxygen will then generate output that is more tailored for Java. +# For instance, namespaces will be presented as packages, qualified scopes +# will look different, etc. +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. +SUBGROUPING = YES + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. +EXTRACT_PRIVATE = YES + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. +EXTRACT_LOCAL_METHODS = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. +SHOW_INCLUDE_FILES = YES + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. +SORT_BRIEF_DOCS = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is YES. +SHOW_DIRECTORIES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from the +# version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the progam writes to standard output +# is used as the file version. See the manual for examples. +FILE_VERSION_FILTER = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. +QUIET = NO +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_IF_DOC_ERROR = YES +WARN_NO_PARAMDOC = YES +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. +INPUT = @DOC_SRC_DIRS@ + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm +FILE_PATTERNS = *.c *.h + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* +EXCLUDE_PATTERNS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be +# ignored. +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES (the default) +# then for each documented function all documented +# functions referencing it will be listed. +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES (the default) +# then for each documented function all documented entities +# called/used by that function will be listed. +REFERENCES_RELATION = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. +ALPHABETICAL_INDEX = YES + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. +HTML_ALIGN_MEMBERS = YES + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# of the generated HTML documentation. +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. +TOC_EXPAND = NO + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. +ENUM_VALUES_PER_LINE = 4 + +# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, +# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are +# probably better off using the HTML help feature. +GENERATE_TREEVIEW = YES + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. +TREEVIEW_WIDTH = 250 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +GENERATE_LATEX = NO +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. +PDF_HYPERLINKS = NO + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. +USE_PDFLATEX = NO + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. +LATEX_HIDE_INDICES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +GENERATE_XML = NO +XML_OUTPUT = xml +XML_SCHEMA = +XML_DTD = +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_PREDEFINED tags. +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. +CLASS_DIAGRAMS = YES + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) +HAVE_DOT = YES + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. +TEMPLATE_RELATIONS = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will +# generate a call dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable call graphs for selected +# functions only using the \callgraph command. +CALL_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. +DOT_PATH = /usr/bin + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). +DOTFILE_DIRS = + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that a graph may be further truncated if the graph's +# image dimensions are not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH +# and MAX_DOT_GRAPH_HEIGHT). If 0 is used for the depth value (the default), +# the graph is not depth-constrained. +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, which results in a white background. +# Warning: Depending on the platform used, enabling this option may lead to +# badly anti-aliased labels on the edges of a graph (i.e. they become hard to +# read). +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. +SEARCHENGINE = YES diff --git a/packaging/README.api b/packaging/README.api new file mode 100644 index 0000000..1f8c8ad --- /dev/null +++ b/packaging/README.api @@ -0,0 +1,108 @@ +This file has to be synced with packaging/deviced.manifest + + +DBus method_call smack authority + +* : all user can access the methods. + +Display + org.tizen.system.deviced.display.start root only + org.tizen.system.deviced.display.stop root only + org.tizen.system.deviced.display.lockstate deviced::display + org.tizen.system.deviced.display.unlockstate * + org.tizen.system.deviced.display.changestate deviced::display + org.tizen.system.deviced.display.getbrightness * + org.tizen.system.deviced.display.setbrightness * + org.tizen.system.deviced.display.getautotone * + org.tizen.system.deviced.display.setautotone * + org.tizen.system.deviced.display.getimageenhance * + org.tizen.system.deviced.display.setimageenhance * + org.tizen.system.deviced.display.setframerate * + org.tizen.system.deviced.display.getcolorblind * + org.tizen.system.deviced.display.setcolorblind * + org.tizen.system.deviced.display.setautobrightnessmin * + org.tizen.system.deviced.display.setlcdtimeout * + org.tizen.system.deviced.display.LockScreenBgOn * + org.tizen.system.deviced.display.GetDisplayCount * + org.tizen.system.deviced.display.GetMaxBrightness * + org.tizen.system.deviced.display.GetBrightness * + org.tizen.system.deviced.display.SetBrightness * + org.tizen.system.deviced.display.HoldBrightness deviced::display + org.tizen.system.deviced.display.ReleaseBrightness * + org.tizen.system.deviced.display.GetAclStatus * + org.tizen.system.deviced.display.SetAclStatus * + org.tizen.system.deviced.display.GetAutoTone * + org.tizen.system.deviced.display.SetAutoTone * + org.tizen.system.deviced.display.GetEnhanceSupported * + org.tizen.system.deviced.display.GetImageEnhance * + org.tizen.system.deviced.display.SetImageEnhance * + org.tizen.system.deviced.display.SetFrameRate * + org.tizen.system.deviced.display.GetColorBlind * + org.tizen.system.deviced.display.SetColorBlind * +Hapic + org.tizen.system.deviced.haptic.GetCount * + org.tizen.system.deviced.haptic.OpenDevice * + org.tizen.system.deviced.haptic.CloseDevice * + org.tizen.system.deviced.haptic.StopDevice * + org.tizen.system.deviced.haptic.VibrateMonotone * + org.tizen.system.deviced.haptic.VibrateBuffer * + org.tizen.system.deviced.haptic.GetState * + org.tizen.system.deviced.haptic.GetDuration * + org.tizen.system.deviced.haptic.CreateEffect * + org.tizen.system.deviced.haptic.SaveBinary * +Pass + org.tizen.system.deviced.pass.start root only + org.tizen.system.deviced.pass.stop root only + org.tizen.system.deviced.pass.bypass root only +Hall + org.tizen.system.deviced.hall.getstatus * +Power + org.tizen.system.deviced.power.setresetkeydisable deviced::power + org.tizen.system.deviced.power.entersleep root only + org.tizen.system.deviced.power.leavesleep root only + org.tizen.system.deviced.power.reboot root only + org.tizen.system.deviced.power.reboot-recovery root only + org.tizen.system.deviced.power.pwroff-popup * + org.tizen.system.deviced.power.flightmode root only +Storage + org.tizen.system.deviced.storage.getstorage * +Ode +Lowmem +Led + org.tizen.system.deviced.Led.playcustom * + org.tizen.system.deviced.Led.stopcustom * + org.tizen.system.deviced.Led.GetBrightness * + org.tizen.system.deviced.Led.GetMaxBrightness * + org.tizen.system.deviced.Led.SetBrightness * + org.tizen.system.deviced.Led.SetIrCommand * + org.tizen.system.deviced.Led.SetMode * + org.tizen.system.deviced.Led.PrintMode * + +Process + org.tizen.system.deviced.Process.foregrd root only + org.tizen.system.deviced.Process.backgrd root only + org.tizen.system.deviced.Process.active * + org.tizen.system.deviced.Process.inactive * + org.tizen.system.deviced.Process.oomadj_set root only + org.tizen.system.deviced.Process.process_group_set root only + +SysNoti + org.tizen.system.deviced.SysNoti.set_max_frequency root only + org.tizen.system.deviced.SysNoti.set_min_frequency root only + org.tizen.system.deviced.SysNoti.release_max_frequency root only + org.tizen.system.deviced.SysNoti.release_min_frequency root only + org.tizen.system.deviced.SysNoti.dump_log * + org.tizen.system.deviced.SysNoti.delete_dump * + org.tizen.system.deviced.SysNoti.set_datetime * + org.tizen.system.deviced.SysNoti.set_timezone * + org.tizen.system.deviced.SysNoti.control * + org.tizen.system.deviced.SysNoti.device_changed root only + org.tizen.system.deviced.SysNoti.power_supply root only + org.tizen.system.deviced.SysNoti.udev root only + org.tizen.system.deviced.SysNoti.factorymode root only + org.tizen.system.deviced.SysNoti.control root only +Mmc + org.tizen.system.deviced.Mmc.RequestMount * + org.tizen.system.deviced.Mmc.RequestUnmount * + org.tizen.system.deviced.Mmc.RequestFormat * + diff --git a/packaging/crash-daemon.service b/packaging/crash-daemon.service new file mode 100644 index 0000000..27e39bb --- /dev/null +++ b/packaging/crash-daemon.service @@ -0,0 +1,11 @@ +[Unit] +Description=Start the crash daemon service +After=dbus.socket + +[Service] +ExecStart=/usr/bin/crash-daemon +Restart=always +RestartSec=0 + +[Install] +WantedBy=multi-user.target diff --git a/packaging/devicectl-start@.service b/packaging/devicectl-start@.service new file mode 100644 index 0000000..3322274 --- /dev/null +++ b/packaging/devicectl-start@.service @@ -0,0 +1,7 @@ +[Unit] +Description=Device Control Start %I +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/bin/devicectl %I start diff --git a/packaging/devicectl-stop@.service b/packaging/devicectl-stop@.service new file mode 100644 index 0000000..c242e72 --- /dev/null +++ b/packaging/devicectl-stop@.service @@ -0,0 +1,7 @@ +[Unit] +Description=Device Control Stop %I +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/bin/devicectl %I stop diff --git a/packaging/deviced-pre.service b/packaging/deviced-pre.service new file mode 100644 index 0000000..0992d9d --- /dev/null +++ b/packaging/deviced-pre.service @@ -0,0 +1,8 @@ +[Unit] +Description=prepare device daemon +DefaultDependencies=no +Before=deviced.service + +[Service] +Type=oneshot +ExecStart=/usr/bin/deviced-pre.sh diff --git a/packaging/deviced.manifest b/packaging/deviced.manifest new file mode 100644 index 0000000..97710e4 --- /dev/null +++ b/packaging/deviced.manifest @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packaging/deviced.rule b/packaging/deviced.rule new file mode 100644 index 0000000..bce8fd6 --- /dev/null +++ b/packaging/deviced.rule @@ -0,0 +1,11 @@ +# subject rule +deviced sys-assert::core rwxat +deviced system::media rwxat +deviced system::vconf rwxat +deviced system::vconf_setting rw +deviced com.samsung.setting::private r +deviced system::vconf_system rw +deviced testmode::vconf r +deviced starter::vconf r +# object rule +pulseaudio deviced rw diff --git a/packaging/deviced.service b/packaging/deviced.service new file mode 100644 index 0000000..9f0661a --- /dev/null +++ b/packaging/deviced.service @@ -0,0 +1,14 @@ +[Unit] +Description=System device daemon +After=deviced-pre.service pulseaudio.service sound-init.service +Requires=deviced-pre.service + +[Service] +EnvironmentFile=/run/deviced/deviced_env +ExecStart=/usr/bin/deviced +Restart=always +RestartSec=0 +KillSignal=SIGUSR1 + +[Install] +WantedBy=multi-user.target diff --git a/packaging/deviced.spec b/packaging/deviced.spec new file mode 100644 index 0000000..0739bbc --- /dev/null +++ b/packaging/deviced.spec @@ -0,0 +1,266 @@ +Name: deviced +Summary: deviced +Version: 1.0.0 +Release: 1 +Group: Framework/system +License: Apache License, Version 2.0 +Source0: %{name}-%{version}.tar.gz +Source1: %{name}.service +Source2: zbooting-done.service +Source3: shutdown-notify.service +Source4: deviced-pre.service +Source5: devicectl-start@.service +Source6: devicectl-stop@.service +Source1001: deviced.manifest +Source1002: libdeviced.manifest +Source1003: liblogd-db.manifest +Source1004: liblogd.manifest + +BuildRequires: cmake +BuildRequires: libattr-devel +BuildRequires: gettext-devel +BuildRequires: pkgconfig(ecore) +BuildRequires: pkgconfig(vconf) +%ifnarch %{arm} +BuildRequires: pkgconfig(heynoti) +%endif +BuildRequires: pkgconfig(dlog) +BuildRequires: pkgconfig(usbutils) +BuildRequires: pkgconfig(device-node) +BuildRequires: pkgconfig(edbus) +BuildRequires: pkgconfig(libxml-2.0) +BuildRequires: pkgconfig(capi-base-common) +BuildRequires: systemd-devel +BuildRequires: pkgconfig(systemd) +BuildRequires: pkgconfig(sqlite3) +Requires(preun): /usr/bin/systemctl +Requires(post): sys-assert +Requires(post): /usr/bin/systemctl +Requires(post): /usr/bin/vconftool +Requires(postun): /usr/bin/systemctl + +%description +deviced + +%package deviced +Summary: deviced daemon +Group: main +Requires: %{name} = %{version}-%{release} + +%description deviced +deviced daemon. + +%package -n libdeviced +Summary: Deviced library +Group: Development/Libraries + +%description -n libdeviced +Deviced library for device control + +%package -n libdeviced-devel +Summary: Deviced library for (devel) +Group: Development/Libraries +Requires: libdeviced = %{version}-%{release} + +%description -n libdeviced-devel +Deviced library for device control (devel) + +%package -n logd +Summary: logd utils +Group: Framework/system + +%description -n logd +Utils for for logd + +%package -n liblogd +Summary: Activity logging API(Development) +Group: Development/Libraries + +%description -n liblogd +logd library. + +%package -n liblogd-devel +Summary: Activity logging (Development) +Summary: SLP power manager client (devel) +Group: Development/Libraries + +%description -n liblogd-devel +logd API library. + +%package -n liblogd-db +Summary: API to get activity data (Development) +Group: Development/Libraries + +%description -n liblogd-db +logd-db library. + +%package -n liblogd-db-devel +Summary: API to get activity data (Development) +Group: Development/Libraries + +%description -n liblogd-db-devel +logd-db API library. + +%prep +%setup -q +export CFLAGS+=" -DMICRO_DD" + +%if 0%{?sec_build_binary_debug_enable} +export CFLAGS+=" -DTIZEN_DEBUG_ENABLE" +%endif + +%if 0%{?tizen_build_binary_release_type_eng} +export CFLAGS+=" -DTIZEN_ENGINEER_MODE" +%define ENGINEER_MODE 1 +%else +%define ENGINEER_MODE 0 +%endif + +%ifarch %{arm} +%define ARCH arm +%else +%define ARCH emulator +%endif +cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} -DARCH=%{ARCH} + +%build +cp %{SOURCE1001} . +cp %{SOURCE1002} . +cp %{SOURCE1003} . +cp %{SOURCE1004} . + +make + +%install +rm -rf %{buildroot} +%make_install + +mkdir -p %{buildroot}%{_libdir}/systemd/system/multi-user.target.wants +mkdir -p %{buildroot}%{_libdir}/systemd/system/graphical.target.wants +mkdir -p %{buildroot}%{_libdir}/systemd/system/shutdown.target.wants +install -m 0644 %{SOURCE1} %{buildroot}%{_libdir}/systemd/system/deviced.service +install -m 0644 %{SOURCE2} %{buildroot}%{_libdir}/systemd/system/zbooting-done.service +install -m 0644 %{SOURCE3} %{buildroot}%{_libdir}/systemd/system/shutdown-notify.service +install -m 0644 %{SOURCE4} %{buildroot}%{_libdir}/systemd/system/deviced-pre.service +install -m 0644 %{SOURCE5} %{buildroot}%{_libdir}/systemd/system/devicectl-start@.service +install -m 0644 %{SOURCE6} %{buildroot}%{_libdir}/systemd/system/devicectl-stop@.service +ln -s ../deviced.service %{buildroot}%{_libdir}/systemd/system/multi-user.target.wants/deviced.service +# Temporary symlink +ln -s deviced.service %{buildroot}%{_libdir}/systemd/system/system-server.service +ln -s ../zbooting-done.service %{buildroot}%{_libdir}/systemd/system/graphical.target.wants/zbooting-done.service +ln -s ../shutdown-notify.service %{buildroot}%{_libdir}/systemd/system/shutdown.target.wants/shutdown-notify.service +ln -s ../devicectl-stop@.service %{buildroot}%{_libdir}/systemd/system/shutdown.target.wants/devicectl-stop@display.service +mkdir -p %{buildroot}%{_sysconfdir}/systemd/default-extra-dependencies/ignore-units.d/ +ln -s %{_libdir}/systemd/system/deviced.service %{buildroot}%{_sysconfdir}/systemd/default-extra-dependencies/ignore-units.d/ + +mkdir -p %{buildroot}%{_datadir}/license +cp LICENSE.Apache-2.0 %{buildroot}/usr/share/license/%{name} +cp LICENSE.Apache-2.0 %{buildroot}/usr/share/license/libdeviced + +%post +#memory type vconf key init +vconftool set -t int memory/sysman/usbhost_status -1 -i -s system::vconf_system +vconftool set -t int memory/sysman/charger_status 0 -i -s system::vconf_system +vconftool set -t int memory/sysman/charge_now 0 -i -s system::vconf_system +vconftool set -t int memory/sysman/battery_status_low -1 -i -s system::vconf_system +vconftool set -t int memory/sysman/battery_capacity -1 -i -s system::vconf_system +vconftool set -t int memory/sysman/usb_status -1 -i -s system::vconf_system +vconftool set -t int memory/sysman/factory_mode 0 -i -s system::vconf_system +vconftool set -t int memory/sysman/stime_changed 0 -i -s system::vconf_system +vconftool set -t int memory/sysman/power_off 0 -u 5000 -i -f -s system::vconf_system +vconftool set -t int memory/deviced/boot_power_on 0 -u 5000 -i -f -s system::vconf_system +vconftool set -t int memory/sysman/battery_level_status -1 -i -s system::vconf_system + +#db type vconf key init +vconftool set -t bool db/private/deviced/lcd_brightness_init 0 -i -s system::vconf_system + +vconftool set -t int memory/pm/state 0 -i -g 5000 -s system::vconf_system +vconftool set -t int memory/pm/camera_status 0 -i -s system::vconf_system +vconftool set -t int memory/pm/battery_timetofull -1 -i -s system::vconf_system +vconftool set -t int memory/pm/battery_timetoempty -1 -i -s system::vconf_system +vconftool set -t int memory/pm/sip_status 0 -i -g 5000 -s system::vconf_system +vconftool set -t int memory/pm/custom_brightness_status 0 -i -g 5000 -s system::vconf_system +vconftool set -t bool memory/pm/brt_changed_lpm 0 -i -s system::vconf_system +vconftool set -t int memory/pm/current_brt 60 -i -g 5000 -s system::vconf_system +vconftool set -t int memory/pm/lcdoff_source 0 -i -g 5000 -s system::vconf_system +vconftool set -t int memory/pm/key_ignore 0 -i -g 5000 -s system::vconf_system + +#USB client +vconftool set -t int memory/usb/cur_mode "0" -u 0 -i -s system::vconf_system +vconftool set -t int db/usb/sel_mode "1" -s system::vconf_system +vconftool set -t int db/private/usb/usb_control "1" -u 0 -i -s system::vconf_system +vconftool set -t int memory/private/usb/conf_enabled "0" -u 0 -i -s system::vconf_system + +systemctl daemon-reload +if [ $1 == 1 ]; then + systemctl restart deviced.service + systemctl restart zbooting-done.service +fi + +%preun +if [ $1 == 0 ]; then + systemctl stop deviced.service + systemctl stop zbooting-done.service +fi + +%postun +systemctl daemon-reload + +%files -n deviced +%{_bindir}/deviced-pre.sh +%{_bindir}/deviced +%{_bindir}/devicectl +%{_bindir}/deviced-auto-test +%{_libdir}/systemd/system/deviced.service +%{_libdir}/systemd/system/multi-user.target.wants/deviced.service +%{_sysconfdir}/systemd/default-extra-dependencies/ignore-units.d/deviced.service +# Temporary symlink service +%{_libdir}/systemd/system/system-server.service +%{_libdir}/systemd/system/zbooting-done.service +%{_libdir}/systemd/system/graphical.target.wants/zbooting-done.service +%{_libdir}/systemd/system/shutdown-notify.service +%{_libdir}/systemd/system/shutdown.target.wants/shutdown-notify.service +%{_libdir}/systemd/system/deviced-pre.service +%{_libdir}/systemd/system/devicectl-stop@.service +%{_libdir}/systemd/system/devicectl-start@.service +%{_libdir}/systemd/system/shutdown.target.wants/devicectl-stop@display.service +%{_datadir}/license/%{name} +%{_datadir}/deviced/usb-configurations/* +%{_sysconfdir}/smack/accesses2.d/deviced.rule + +%manifest deviced.manifest +%attr(110,root,root) /opt/etc/dump.d/module.d/dump_pm.sh +%{_sysconfdir}/deviced/display.conf +%{_sysconfdir}/deviced/mmc.conf +%{_sysconfdir}/deviced/battery.conf +%{_sysconfdir}/deviced/pmqos.conf + +%attr(750,root,root)%{_bindir}/start_dr.sh +%if %ENGINEER_MODE +%attr(750,root,root) %{_bindir}/set_usb_debug.sh +%attr(750,root,root) %{_bindir}/direct_set_debug.sh +%endif + +%files -n libdeviced +%defattr(-,root,root,-) +%{_libdir}/libdeviced.so.* +%{_datadir}/license/libdeviced +%manifest libdeviced.manifest + +%files -n libdeviced-devel +%defattr(-,root,root,-) +%{_includedir}/deviced/*.h +%{_libdir}/libdeviced.so +%{_libdir}/pkgconfig/deviced.pc + +%files -n logd + +%files -n liblogd +%manifest liblogd.manifest + +%files -n liblogd-devel + +%files -n liblogd-db +%manifest liblogd-db.manifest + +%files -n liblogd-db-devel diff --git a/packaging/libdeviced.manifest b/packaging/libdeviced.manifest new file mode 100644 index 0000000..3256181 --- /dev/null +++ b/packaging/libdeviced.manifest @@ -0,0 +1,5 @@ + + + + + diff --git a/packaging/liblogd-db.manifest b/packaging/liblogd-db.manifest new file mode 100644 index 0000000..0a38a69 --- /dev/null +++ b/packaging/liblogd-db.manifest @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/packaging/liblogd.manifest b/packaging/liblogd.manifest new file mode 100644 index 0000000..194afaf --- /dev/null +++ b/packaging/liblogd.manifest @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/packaging/shutdown-notify.service b/packaging/shutdown-notify.service new file mode 100644 index 0000000..4d274c9 --- /dev/null +++ b/packaging/shutdown-notify.service @@ -0,0 +1,9 @@ +[Unit] +Description=Broadcasing Shutdown +DefaultDependencies=no + +[Service] +ExecStart=/usr/bin/dbus-send --type=signal --system --dest=org.tizen.system.deviced.PowerOff /Org/Tizen/System/DeviceD/PowerOff org.tizen.system.deviced.PowerOff.ChangeState int32:2 + +[Install] +WantedBy=shutdown.target diff --git a/packaging/zbooting-done.service b/packaging/zbooting-done.service new file mode 100644 index 0000000..a7e7017 --- /dev/null +++ b/packaging/zbooting-done.service @@ -0,0 +1,10 @@ +[Unit] +Description=Booting Done +After=default.target + +[Service] +Type=oneshot +ExecStart=/usr/bin/dbus-send --type=signal --system /Org/Tizen/System/DeviceD/Core org.tizen.system.deviced.core.BootingDone + +[Install] +WantedBy=graphical.target diff --git a/scripts/deviced-pre.sh b/scripts/deviced-pre.sh new file mode 100755 index 0000000..85850be --- /dev/null +++ b/scripts/deviced-pre.sh @@ -0,0 +1,55 @@ +#!/bin/sh + +DEVICED_ENV_F=/run/deviced/deviced_env +[ -e $DEVICED_ENV_F ] && /bin/rm -f $DEVICED_ENV_F +[ -d ${DEVICED_ENV_F%/*} ] || /bin/mkdir -p ${DEVICED_ENV_F%/*} + +echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/lib" >> $DEVICED_ENV_F + +DEV_INPUT= +TOUCHSCREEN=400 +TOUCHKEY=200 + +for file in /sys/class/input/event*; do + if [ -e $file ]; then + dev_keytype=`/bin/cat ${file}/device/capabilities/key` + if [ "$dev_keytype" != 0 ]; then + DEV_INPUT=$DEV_INPUT:/dev/input/${file#/sys/class/input/} + var=${dev_keytype%%' '*} + if [ $var == $TOUCHSCREEN ]; then + DEV_TOUCHSCREEN=/sys/class/input/${file#/sys/class/input/}/device/enabled + echo ${var} ${file#/sys/class/input/} + fi + if [ $var == $TOUCHKEY ]; then + dev_ledtype=`/bin/cat ${file}/device/capabilities/led` + if [ "$dev_ledtype" != 0 ]; then + DEV_TOUCHKEY=/sys/class/input/${file#/sys/class/input/}/device/enabled + echo ${var} ${file#/sys/class/input/} + fi + fi + fi + fi +done + +for file in /sys/class/lcd/*; do + if [ -e $file ]; then + hbm_state=`/bin/cat ${file}/device/hbm` + if [ "$hbm_state" != 0 ]; then + HBM_NODE=${file}/device/hbm + fi + alpm_state=`/bin/cat ${file}/device/alpm` + if [ "$alpm_state" != 0 ]; then + ALPM_NODE=${file}/device/alpm + fi + fi +done + +echo "PM_INPUT=$DEV_INPUT" >> $DEVICED_ENV_F +echo "PM_TOUCHSCREEN=$DEV_TOUCHSCREEN" >> $DEVICED_ENV_F +echo "PM_TOUCHKEY=$DEV_TOUCHKEY" >> $DEVICED_ENV_F +echo "HBM_NODE=$HBM_NODE" >> $DEVICED_ENV_F +echo "ALPM_NODE=$ALPM_NODE" >> $DEVICED_ENV_F +echo "PM_TO_NORMAL=30000" >> $DEVICED_ENV_F +echo "PM_TO_LCDDIM=5000" >> $DEVICED_ENV_F +echo "PM_SYS_DIMBRT=0" >> $DEVICED_ENV_F + diff --git a/scripts/direct_set_debug.sh b/scripts/direct_set_debug.sh new file mode 100755 index 0000000..396a768 --- /dev/null +++ b/scripts/direct_set_debug.sh @@ -0,0 +1,141 @@ +#!/bin/sh + +VERSION= + +check_driver_version() { + if [ -f /sys/class/usb_mode/version ] + then + VERSION=`/bin/cat /sys/class/usb_mode/version` + else + VERSION="0.0" + fi +} + +load_usb_gadget_1_0() { + echo 0 > /sys/class/usb_mode/usb0/enable + echo 04e8 > /sys/class/usb_mode/usb0/idVendor + echo $1 > /sys/class/usb_mode/usb0/idProduct + echo $2 > /sys/class/usb_mode/usb0/functions + echo 239 > /sys/class/usb_mode/usb0/bDeviceClass + echo 2 > /sys/class/usb_mode/usb0/bDeviceSubClass + echo 1 > /sys/class/usb_mode/usb0/bDeviceProtocol + echo 1 > /sys/class/usb_mode/usb0/enable +} + +load_usb_gadget_1_1() { + echo 0 > /sys/class/usb_mode/usb0/enable + echo 04e8 > /sys/class/usb_mode/usb0/idVendor + echo $1 > /sys/class/usb_mode/usb0/idProduct + echo $2 > /sys/class/usb_mode/usb0/funcs_fconf + echo $3 > /sys/class/usb_mode/usb0/funcs_sconf + echo 239 > /sys/class/usb_mode/usb0/bDeviceClass + echo 2 > /sys/class/usb_mode/usb0/bDeviceSubClass + echo 1 > /sys/class/usb_mode/usb0/bDeviceProtocol + echo 1 > /sys/class/usb_mode/usb0/enable +} + +unload_usb_gadget_1() { + echo 0 > /sys/class/usb_mode/usb0/enable +} + +sdb_set() { + case "$VERSION" in + "1.0") + load_usb_gadget_1_0 "6860" "mtp,acm,sdb" + ;; + "1.1") + load_usb_gadget_1_1 "6860" "mtp" "mtp,acm,sdb" + ;; + *) + echo "USB driver version $VERSION is not supported" + return + ;; + esac + + /usr/bin/systemctl start sdbd.service + echo "SDB enabled" +} + +ssh_set() { + case "$VERSION" in + "1.0") + load_usb_gadget_1_0 "6864" "rndis" + ;; + "1.1") + load_usb_gadget_1_1 "6864" "rndis" " " + ;; + *) + echo "USB driver version $VERSION is not supported" + return + ;; + esac + + /sbin/ifconfig usb0 192.168.129.3 up + /sbin/route add -net 192.168.129.0 netmask 255.255.255.0 dev usb0 + /usr/bin/systemctl start sshd.service + echo "SSH enabled" +} + +usb_unset() { + case "$VERSION" in + "1.0" | "1.1") + unload_usb_gadget_1 + ;; + *) + echo "USB driver version $VERSION is not supported" + return + ;; + esac +} + +sdb_unset() { + usb_unset + /usr/bin/systemctl stop sdbd.service + echo "SDB disabled" +} + +ssh_unset() { + usb_unset + /sbin/ifconfig usb0 down + /usr/bin/systemctl stop sshd.service + echo "SSH disabled" +} + +show_options() { + echo "direct_set_debug.sh: usage:" + echo " --help This message" + echo " --sdb-set Load sdb without usb-manager" + echo " --sdb-unset Unload sdb without usb-manager" + echo " --ssh-set Load ssh without usb-manager" + echo " --ssh-unset Unload ssh without usb-manager" +} + +check_driver_version + +case "$1" in +"--sdb-set") + sdb_set + /usr/bin/set_usb_debug.sh --mtp-sdb & + ;; + +"--ssh-set") + ssh_set + /usr/bin/set_usb_debug.sh --rndis & + ;; + +"--sdb-unset") + sdb_unset + ;; + +"--ssh-unset") + ssh_unset + ;; + +"--help") + show_options + ;; + +*) + echo "Wrong parameters. Please use option --help to check options " + ;; +esac diff --git a/scripts/dump_pm.sh b/scripts/dump_pm.sh new file mode 100644 index 0000000..a43189f --- /dev/null +++ b/scripts/dump_pm.sh @@ -0,0 +1,21 @@ +#-------------------------------------- +# power-manager +#-------------------------------------- +/usr/bin/devicectl display savelog +PM_DEBUG=$1/power-manager +PM_KMG=sleep_wakeup.log +PM_KMG_SLEEP=/sys/kernel/debug/sleep_history +PM_KMG_WAKEUP=/sys/kernel/debug/wakeup_sources +/bin/mkdir -p ${PM_DEBUG} +/bin/cp -rf /opt/var/log/pm_state.log ${PM_DEBUG} + +if [ -e $PM_KMG_SLEEP ]; +then +/bin/cat ${PM_KMG_SLEEP} > ${PM_DEBUG}/${PM_KMG} +fi + +if [ -e $PM_KMG_WAKEUP ]; +then +/bin/cat ${PM_KMG_WAKEUP} >> ${PM_DEBUG}/${PM_KMG} +fi + diff --git a/scripts/mmc-smack-label b/scripts/mmc-smack-label new file mode 100755 index 0000000..8bf29cf --- /dev/null +++ b/scripts/mmc-smack-label @@ -0,0 +1,5 @@ +#!/bin/bash +MOUNT_DIRECTORY=$1 +/usr/bin/find $MOUNT_DIRECTORY -type d | /usr/bin/xargs /usr/bin/chsmack -a 'system::ext_storage' -e '' +/usr/bin/find $MOUNT_DIRECTORY -type f | /usr/bin/xargs /usr/bin/chsmack -a 'system::ext_storage' +/usr/bin/find $MOUNT_DIRECTORY | /usr/bin/xargs /bin/chown app:app diff --git a/scripts/movi_format.sh b/scripts/movi_format.sh new file mode 100755 index 0000000..8946fbe --- /dev/null +++ b/scripts/movi_format.sh @@ -0,0 +1,34 @@ +#!/bin/sh + +/sbin/fdisk -H 1 /dev/mmcblk0 << EOF +d +1 +d +2 +d +3 +n +p +1 +2 +728576 +n +p +2 + +990720 +n +p +3 + +1003520 +p +wq +EOF + +/bin/sleep 1 + +fat.format -s 32 -S 512 -F 32 /dev/mmcblk0p1 +fat.format -s 32 -S 512 -F 32 /dev/mmcblk0p2 +fat.format -s 4 -S 4096 -F 16 /dev/mmcblk0p3 + diff --git a/scripts/set_usb_debug.sh b/scripts/set_usb_debug.sh new file mode 100755 index 0000000..288ceea --- /dev/null +++ b/scripts/set_usb_debug.sh @@ -0,0 +1,70 @@ +#!/bin/sh + +case "$1" in + +"--debug") + /usr/bin/vconftool set -t int db/usb/sel_mode "2" -f + /usr/bin/vconftool set -t bool db/setting/debug_mode "1" -f + /usr/bin/vconftool set -t int db/setting/lcd_backlight_normal "600" -f + echo "The backlight time of the display is set to 10 minutes" + /usr/bin/vconftool set -t bool db/setting/brightness_automatic "1" -f + echo "Brightness is set automatic" + ;; + +"--mtp" | "--sshoff" | "--unset") + /usr/bin/vconftool set -t int db/usb/sel_mode "1" -f + /usr/bin/vconftool set -t bool db/setting/debug_mode "0" -f + ;; + +"--mtp-sdb" | "--set") + /usr/bin/vconftool set -t int db/usb/sel_mode "2" -f + /usr/bin/vconftool set -t bool db/setting/debug_mode "1" -f + ;; + +"--mtp-sdb-diag") + /usr/bin/vconftool set -t int db/usb/sel_mode "3" -f + /usr/bin/vconftool set -t bool db/setting/debug_mode "1" -f + ;; + +"--rndis-tethering") + /usr/bin/vconftool set -t int db/usb/sel_mode "4" -f + ;; + +"--rndis" | "--sshon") + /usr/bin/vconftool set -t int db/usb/sel_mode "5" -f + /usr/bin/vconftool set -t bool db/setting/debug_mode "0" -f + ;; + +"--rndis-sdb") + /usr/bin/vconftool set -t int db/usb/sel_mode "6" -f + /usr/bin/vconftool set -t bool db/setting/debug_mode "1" -f + ;; + +"--rndis-diag") + /usr/bin/vconftool set -t int db/usb/sel_mode "8" -f + /usr/bin/vconftool set -t bool db/setting/debug_mode "0" -f + ;; + +"--help") + echo "set_usb_debug.sh: usage:" + echo " --help This message " + echo " --set Load Debug mode" + echo " --unset Unload Debug mode" + echo " --debug Load debug mode with 10 minutes backlight time" + echo " and automatic brightness" + echo " --sshon Load SSH mode" + echo " --sshoff Unload SSH mode" + echo " --mtp Load mtp only" + echo " --mtp-sdb Load mtp and sdb" + echo " --mtp-sdb-diag Load mtp, sdb, and diag" + echo " If diag is not supported, mtp is loaded" + echo " --rndis Load rndis only" + echo " --rndis-diag Load rndis and diag" + echo " If diag is not supported, mtp is loaded" + ;; + +*) + echo "Wrong parameters. Please use option --help to check options " + ;; + +esac diff --git a/scripts/start_dr.sh b/scripts/start_dr.sh new file mode 100755 index 0000000..8a5c958 --- /dev/null +++ b/scripts/start_dr.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +# start data-router +if (/bin/ps -e | /bin/grep data-router); then + echo "Already DR activated. No need launch DR" +else + echo "Launch DR" + /usr/bin/data-router & +fi diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100755 index 0000000..c17e8b8 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,3 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) + +ADD_SUBDIRECTORY(shared) diff --git a/src/apps/apps.c b/src/apps/apps.c new file mode 100755 index 0000000..1560d1e --- /dev/null +++ b/src/apps/apps.c @@ -0,0 +1,89 @@ +/* + * deviced + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "core/log.h" +#include "apps.h" +#include "core/devices.h" +#include "core/list.h" + +static dd_list *apps_head = NULL; + +void add_apps(const struct apps_ops *dev) +{ + _I("add %s", dev->name); + DD_LIST_APPEND(apps_head, (void*)dev); +} + +void remove_apps(const struct apps_ops *dev) +{ + DD_LIST_REMOVE(apps_head, (void*)dev); +} + +static void apps_init(void *data) +{ + const struct apps_ops*dev; + dd_list *elem; + struct apps_data *input_data; + static int initialized =0; + + if (!initialized) { + initialized = 1; + return; + } + + input_data = (struct apps_data *)data; + if (input_data == NULL || input_data->name == NULL) + return; + + DD_LIST_FOREACH(apps_head, elem, dev) { + if (!strncmp(dev->name, (char *)input_data->name, strlen(dev->name))) { + if (dev->launch) + dev->launch(data); + break; + } + } +} + +static void apps_exit(void *data) +{ + const struct apps_ops*dev; + dd_list *elem; + struct apps_data *input_data; + + input_data = (struct apps_data *)data; + if (input_data == NULL || input_data->name == NULL) + return; + + DD_LIST_FOREACH(apps_head, elem, dev) { + if (!strncmp(dev->name, (char *)input_data->name, strlen(dev->name))) { + if (dev->terminate) + dev->terminate(data); + break; + } + } +} + +static const struct device_ops apps_device_ops = { + .priority = DEVICE_PRIORITY_NORMAL, + .name = "apps", + .init = apps_init, + .exit = apps_exit, +}; + +DEVICE_OPS_REGISTER(&apps_device_ops) diff --git a/src/apps/apps.h b/src/apps/apps.h new file mode 100755 index 0000000..8dd93d9 --- /dev/null +++ b/src/apps/apps.h @@ -0,0 +1,54 @@ +/* + * deviced + * + * Copyright (c) 2012 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 __APPS_H__ +#define __APPS_H__ + + +#include "core/edbus-handler.h" +#include "core/common.h" +#include "core/data.h" + +#define APPS_OPS_REGISTER(dev) \ +static void __CONSTRUCTOR__ module_init(void) \ +{ \ + add_apps(dev); \ +} \ +static void __DESTRUCTOR__ module_exit(void) \ +{ \ + remove_apps(dev); \ +} + +struct apps_data { + const char *name; + void *data; +}; + +struct apps_ops { + const char *name; + void (*init) (void); + void (*exit) (void); + int (*launch)(void *data); + int (*terminate)(void *data); +}; + +void add_apps(const struct apps_ops *dev); +void remove_apps(const struct apps_ops *dev); + +#endif /* __APPS_H__ */ + diff --git a/src/apps/launch.c b/src/apps/launch.c new file mode 100644 index 0000000..6b25ddd --- /dev/null +++ b/src/apps/launch.c @@ -0,0 +1,223 @@ +/* + * deviced + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include +#include "core/log.h" +#include "core/common.h" +#include "apps.h" +#include "core/edbus-handler.h" + +#define PWLOCK_NAME "pwlock" +#define CRADLE_NAME "desk-dock" + +#define RETRY_MAX 5 + +struct popup_data { + char *name; + char *value; +}; + +static pid_t cradle_pid = 0; + +static int launch_app_pwlock(void); +static int launch_app_cradle(void); + +void get_pwlock_app_pid(void *data, DBusMessage *msg, DBusError *err) +{ + DBusError r_err; + int ret; + pid_t pid; + + if (!msg) { + _E("Cannot get pid of pwlock app"); + ret = launch_app_pwlock(); + if (ret < 0) + _E("Failed to launch pwlock app(%d)", ret); + return; + } + + dbus_error_init(&r_err); + ret = dbus_message_get_args(msg, &r_err, DBUS_TYPE_INT32, &pid, DBUS_TYPE_INVALID); + if (!ret) { + _E("no message [%s:%s]", r_err.name, r_err.message); + dbus_error_free(&r_err); + return; + } + + _I("Pid of cradle app is (%d)", pid); +} + +static int launch_app_pwlock(void) +{ + int i, ret; + char *pa[2]; + + pa[0] = "after_bootup"; + pa[1] = "1"; + + i = 0; + do { + ret = dbus_method_async_with_reply(POPUP_BUS_NAME, + POPUP_PATH_APP, POPUP_IFACE_APP, + "PWLockAppLaunch", "ss", pa, + get_pwlock_app_pid, -1, NULL); + if (ret < 0) + _E("Failed to request launching cradle app(%d), retry(%d)", ret, i); + else + break; + } while(i++ < RETRY_MAX); + + return ret; +} + +void get_cradle_app_pid(void *data, DBusMessage *msg, DBusError *err) +{ + DBusError r_err; + int ret; + pid_t pid; + + if (!msg) { + _E("Cannot get pid of cradle app"); + ret = launch_app_cradle(); + if (ret < 0) + _E("Failed to launch cradle app (%d)", ret); + return; + } + + dbus_error_init(&r_err); + ret = dbus_message_get_args(msg, &r_err, DBUS_TYPE_INT32, &pid, DBUS_TYPE_INVALID); + if (!ret) { + _E("no message [%s:%s]", r_err.name, r_err.message); + dbus_error_free(&r_err); + return; + } + + cradle_pid = pid; + _I("Pid of cradle app is (%d)", cradle_pid); +} + +static int launch_app_cradle(void) +{ + int i, ret; + + i = 0; + do { + ret = dbus_method_async_with_reply(POPUP_BUS_NAME, + POPUP_PATH_APP, POPUP_IFACE_APP, + "CradleAppLaunch", NULL, NULL, + get_cradle_app_pid, -1, NULL); + if (ret < 0) + _E("Failed to request launching cradle app(%d), retry(%d)", ret, i); + else + break; + } while(i++ < RETRY_MAX); + + return ret; +} + +void get_terminate_app_result(void *data, DBusMessage *msg, DBusError *err) +{ + DBusError r_err; + int ret, result; + + if (!msg) { + _E("Cannot get result of terminating app"); + return; + } + + dbus_error_init(&r_err); + ret = dbus_message_get_args(msg, &r_err, DBUS_TYPE_INT32, &result, DBUS_TYPE_INVALID); + if (!ret) { + _E("no message [%s:%s]", r_err.name, r_err.message); + dbus_error_free(&r_err); + return; + } + + _I("The result of terminating app is (%d)", result); +} + +static int terminate_app_by_pid(pid_t pid) +{ + int i, ret; + char *pa[1]; + char cPid[32]; + + if (pid <= 0) + return -EINVAL; + + snprintf(cPid, sizeof(cPid), "%d", pid); + pa[0] = cPid; + + i = 0; + do { + ret = dbus_method_async_with_reply(POPUP_BUS_NAME, + POPUP_PATH_APP, POPUP_IFACE_APP, + "AppTerminateByPid", "i", pa, + get_terminate_app_result, -1, NULL); + if (ret < 0) + _E("Failed to request terminating app(%d), retry(%d)", ret, i); + else + break; + } while(i++ < RETRY_MAX); + + return ret; +} + +static int launch_app(void *data) +{ + int ret = 0; + struct popup_data *params; + + if (!data) + return -ENOMEM; + params = (struct popup_data *)data; + + _I("%s", params->value); + if (!strncmp(PWLOCK_NAME, params->value, strlen(params->value))) + ret = launch_app_pwlock(); + else if (!strncmp(CRADLE_NAME, params->value, strlen(params->value))) + ret = launch_app_cradle(); + return ret; +} + + +static int terminate_app(void *data) +{ + struct popup_data *params; + + if (!data || cradle_pid == 0) + return -ENOMEM; + params = (struct popup_data *)data; + _I("%s", params->value); + if (!strncmp(CRADLE_NAME, params->value, strlen(params->value))) { + if (terminate_app_by_pid(cradle_pid) < 0) + _E("Failed to terminate app (%d)", cradle_pid); + cradle_pid = 0; + } + return 0; +} + + +static const struct apps_ops launch_ops = { + .name = "launch-app", + .launch = launch_app, + .terminate = terminate_app, +}; + +APPS_OPS_REGISTER(&launch_ops) diff --git a/src/apps/lowbat.c b/src/apps/lowbat.c new file mode 100644 index 0000000..b90a7ff --- /dev/null +++ b/src/apps/lowbat.c @@ -0,0 +1,112 @@ +/* + * deviced + * + * Copyright (c) 2012 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 "core/log.h" +#include "core/common.h" +#include "apps.h" +#include "core/edbus-handler.h" + +#define LOWBAT_WARNING "warning" +#define LOWBAT_CRITICAL "critical" +#define LOWBAT_POWEROFF "poweroff" + +struct popup_data { + char *name; + char *key; + char *value; +}; + +static int lowbat_pid = 0; + +static void lowbat_cb(void *data, DBusMessage *msg, DBusError *unused) +{ + DBusError err; + int ret, id; + + if (!msg) + return; + + dbus_error_init(&err); + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &id, DBUS_TYPE_INVALID); + if (!ret) { + _E("no message [%s:%s]", err.name, err.message); + dbus_error_free(&err); + return; + } + + lowbat_pid = id; + _I("Created popup : %d", lowbat_pid); +} + +static int lowbat_launch(void *data) +{ + char *param[2]; + struct popup_data * key_data = (struct popup_data *)data; + int ret; + + param[0] = key_data->key; + param[1] = key_data->value; + + ret = dbus_method_async_with_reply(POPUP_BUS_NAME, + POPUP_PATH_LOWBAT, + POPUP_INTERFACE_LOWBAT, + POPUP_METHOD_LAUNCH, + "ss", param, lowbat_cb, -1, NULL); + + if (strncmp(key_data->value, LOWBAT_WARNING, strlen(LOWBAT_WARNING)) && + strncmp(key_data->value, LOWBAT_CRITICAL, strlen(LOWBAT_CRITICAL)) && + strncmp(key_data->value, LOWBAT_POWEROFF, strlen(LOWBAT_POWEROFF))) + _I("%s(%d)",key_data->name, ret); + + return ret; +} + +static int lowbat_terminate(void *data) +{ + int pid; + int ret; + char *param[1]; + char buf[PATH_MAX]; + + printf("\n"); + + if (lowbat_pid <= 0) + return 0; + + snprintf(buf, sizeof(buf), "%d", lowbat_pid); + param[0] = buf; + + ret = dbus_method_sync(POPUP_BUS_NAME, + POPUP_PATH_APP, + POPUP_IFACE_APP, + POPUP_METHOD_TERMINATE, "i", param); + if (ret < 0) + _E("FAIL: dbus_method_sync(): %d %d", ret, param); + lowbat_pid = 0; + return 0; +} + + +static const struct apps_ops lowbat_ops = { + .name = "lowbat-syspopup", + .launch = lowbat_launch, + .terminate = lowbat_terminate, +}; + +APPS_OPS_REGISTER(&lowbat_ops) diff --git a/src/apps/lowmem.c b/src/apps/lowmem.c new file mode 100644 index 0000000..50755f0 --- /dev/null +++ b/src/apps/lowmem.c @@ -0,0 +1,51 @@ +/* + * deviced + * + * Copyright (c) 2012 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 "core/log.h" +#include "core/common.h" +#include "apps.h" +#include "core/edbus-handler.h" + +struct popup_data { + char *name; + char *key; + char *value; +}; + +static int lowmem_launch(void *data) +{ + char *param[2]; + struct popup_data *params = (struct popup_data *)data; + + param[0] = params->key; + param[1] = params->value; + + return dbus_method_sync(POPUP_BUS_NAME, + POPUP_PATH_LOWMEM, + POPUP_INTERFACE_LOWMEM, + POPUP_METHOD_LAUNCH, "ss", param); +} + + +static const struct apps_ops lowmem_ops = { + .name = "lowmem-syspopup", + .launch = lowmem_launch, +}; + +APPS_OPS_REGISTER(&lowmem_ops) diff --git a/src/apps/mmc.c b/src/apps/mmc.c new file mode 100644 index 0000000..6698e57 --- /dev/null +++ b/src/apps/mmc.c @@ -0,0 +1,51 @@ +/* + * deviced + * + * Copyright (c) 2012 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 "core/log.h" +#include "core/common.h" +#include "apps.h" +#include "core/edbus-handler.h" + +struct popup_data { + char *name; + char *key; + char *value; +}; + +static int mmc_launch(void *data) +{ + char *param[2]; + struct popup_data *params = (struct popup_data *)data; + + param[0] = params->key; + param[1] = params->value; + + return dbus_method_sync(POPUP_BUS_NAME, + POPUP_PATH_MMC, + POPUP_INTERFACE_MMC, + POPUP_METHOD_LAUNCH, "ss", param); +} + + +static const struct apps_ops mmc_ops = { + .name = "mmc-syspopup", + .launch = mmc_launch, +}; + +APPS_OPS_REGISTER(&mmc_ops) diff --git a/src/apps/poweroff.c b/src/apps/poweroff.c new file mode 100644 index 0000000..3c9583b --- /dev/null +++ b/src/apps/poweroff.c @@ -0,0 +1,46 @@ +/* + * deviced + * + * Copyright (c) 2012 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 "core/log.h" +#include "core/common.h" +#include "apps.h" +#include "core/edbus-handler.h" +#include "core/launch.h" + +#ifdef MICRO_DD +#define POWEROFF_POPUP_BUS_NAME POPUP_BUS_NAME".Poweroff" +#else +#define POWEROFF_POPUP_BUS_NAME POPUP_BUS_NAME +#endif + +static int poweroff_launch(void *data) +{ + return dbus_method_async(POWEROFF_POPUP_BUS_NAME, + POPUP_PATH_POWEROFF, + POPUP_INTERFACE_POWEROFF, + POPUP_METHOD_LAUNCH, NULL, NULL); +} + + +static const struct apps_ops poweroff_ops = { + .name = "poweroff-syspopup", + .launch = poweroff_launch, +}; + +APPS_OPS_REGISTER(&poweroff_ops) diff --git a/src/apps/system.c b/src/apps/system.c new file mode 100644 index 0000000..99cc2c8 --- /dev/null +++ b/src/apps/system.c @@ -0,0 +1,91 @@ +/* + * deviced + * + * Copyright (c) 2012 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 "core/log.h" +#include "core/common.h" +#include "apps.h" +#include "core/edbus-handler.h" + +#define METHOD_STORAGE_WARNING "UsbotgWarningPopupLaunch" +#define METHOD_WATCHDOG "WatchdogPopupLaunch" +#define METHOD_RECOVERY "RecoveryPopupLaunch" + +struct popup_data { + char *name; + char *method; + char *key1; + char *value1; + char *key2; + char *value2; +}; + +static int system_launch_single_param(struct popup_data * key_data) +{ + char *param[2]; + + param[0] = key_data->key1; + param[1] = key_data->value1; + + return dbus_method_sync(POPUP_BUS_NAME, + POPUP_PATH_SYSTEM, + POPUP_INTERFACE_SYSTEM, + key_data->method, "ss", param); +} + +static int system_launch_double_param(struct popup_data * key_data) +{ + char *param[4]; + + param[0] = key_data->key1; + param[1] = key_data->value1; + param[2] = key_data->key2; + param[3] = key_data->key2; + + return dbus_method_sync(POPUP_BUS_NAME, + POPUP_PATH_SYSTEM, + POPUP_INTERFACE_SYSTEM, + key_data->method, "ssss", param); +} + +static int system_launch(void *data) +{ + struct popup_data *key_data = (struct popup_data *)data; + if (!key_data || !(key_data->method)) + return -EINVAL; + + if (!strncmp(key_data->method, METHOD_STORAGE_WARNING, strlen(METHOD_STORAGE_WARNING))) { + return system_launch_single_param(key_data); + } + + if (!strncmp(key_data->method, METHOD_RECOVERY, strlen(METHOD_RECOVERY))) { + return system_launch_single_param(key_data); + } + + if (!strncmp(key_data->method, METHOD_WATCHDOG, strlen(METHOD_WATCHDOG))) { + return system_launch_double_param(key_data); + } + return -EINVAL; +} + +static const struct apps_ops system_popup_ops = { + .name = "system-syspopup", + .launch = system_launch, +}; + +APPS_OPS_REGISTER(&system_popup_ops) diff --git a/src/apps/usb.c b/src/apps/usb.c new file mode 100644 index 0000000..1a8f8c8 --- /dev/null +++ b/src/apps/usb.c @@ -0,0 +1,51 @@ +/* + * deviced + * + * Copyright (c) 2012 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 "core/log.h" +#include "core/common.h" +#include "apps.h" +#include "core/edbus-handler.h" + +struct popup_data { + char *name; + char *key; + char *value; +}; + +static int usb_launch(void *data) +{ + char *param[2]; + struct popup_data * key_data = (struct popup_data *)data; + + param[0] = key_data->key; + param[1] = key_data->value; + + return dbus_method_sync(POPUP_BUS_NAME, + POPUP_PATH_USB, + POPUP_INTERFACE_USB, + POPUP_METHOD_LAUNCH, "ss", param); +} + + +static const struct apps_ops usb_popup_ops = { + .name = "usb-syspopup", + .launch = usb_launch, +}; + +APPS_OPS_REGISTER(&usb_popup_ops) diff --git a/src/apps/usbotg.c b/src/apps/usbotg.c new file mode 100644 index 0000000..e39a002 --- /dev/null +++ b/src/apps/usbotg.c @@ -0,0 +1,112 @@ +/* + * deviced + * + * Copyright (c) 2012 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 "core/log.h" +#include "core/common.h" +#include "apps.h" +#include "core/edbus-handler.h" + +#define METHOD_STORAGE_MOUNT "StoragePopupLaunch" +#define METHOD_CAMERA "CameraPopupLaunch" +#define METHOD_STORAGE_UNMOUNT "StorageUnmountPopupLaunch" + +#define RETRY_MAX 5 + +struct popup_data { + char *name; + char *method; + char *key1; + char *value1; + char *key2; + char *value2; +}; + +static int system_launch_single_param(struct popup_data * key_data) +{ + int ret, i; + char *param[2]; + + param[0] = key_data->key1; + param[1] = key_data->value1; + + i = 0; + do { + ret = dbus_method_sync(POPUP_BUS_NAME, + POPUP_PATH_USBOTG, + POPUP_INTERFACE_USBOTG, + key_data->method, "ss", param); + if (ret >= 0) + return ret; + _E("Failed to launch popup (%d).. retry (%d)", ret, i); + } while (i++ < RETRY_MAX); + + return ret; +} + +static int system_launch_double_param(struct popup_data * key_data) +{ + int ret, i; + char *param[4]; + + param[0] = key_data->key1; + param[1] = key_data->value1; + param[2] = key_data->key2; + param[3] = key_data->value2; + + i = 0; + do { + ret = dbus_method_sync(POPUP_BUS_NAME, + POPUP_PATH_USBOTG, + POPUP_INTERFACE_USBOTG, + key_data->method, "ssss", param); + if (ret >= 0) + return ret; + _E("Failed to launch popup (%d).. retry (%d)", ret, i); + } while (i++ < RETRY_MAX); + + return ret; +} + +static int system_launch(void *data) +{ + struct popup_data *key_data = (struct popup_data *)data; + if (!key_data || !(key_data->method)) + return -EINVAL; + + if (!strncmp(key_data->method, METHOD_STORAGE_MOUNT, strlen(METHOD_STORAGE_MOUNT))) { + return system_launch_double_param(key_data); + } + + if (!strncmp(key_data->method, METHOD_CAMERA, strlen(METHOD_CAMERA))) { + return system_launch_single_param(key_data); + } + + if (!strncmp(key_data->method, METHOD_STORAGE_UNMOUNT, strlen(METHOD_STORAGE_UNMOUNT))) { + return system_launch_double_param(key_data); + } + + return -EINVAL; +} + +static const struct apps_ops usbotg_popup_ops = { + .name = "usbotg-syspopup", + .launch = system_launch, +}; + +APPS_OPS_REGISTER(&usbotg_popup_ops) diff --git a/src/auto-test/CMakeLists.txt b/src/auto-test/CMakeLists.txt new file mode 100755 index 0000000..303482d --- /dev/null +++ b/src/auto-test/CMakeLists.txt @@ -0,0 +1,66 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(deviced-auto-test C) + +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/src) + +IF("$ENV{CFLAGS}" MATCHES "-DMICRO_DD") + OPTION(USE_MICRO_DD "Use Micro DD" ON) +ENDIF() + +IF("$ENV{CFLAGS}" MATCHES "-DTIZEN_ENGINEER_MODE") + OPTION(USE_ENGINEER_MODE "Use Engineer mode" ON) +ENDIF() + +SET(SRCS + test.c + main.c + udev.c + boot.c + cpu-info.c + board-info.c + time.c +) + +# extcon test +SET(SRCS ${SRCS} + power-supply.c + storage.c + usb.c +) + +IF(NOT USE_MICRO_DD) +SET(SRCS ${SRCS} + cradle.c + earjack.c + hdmi.c + keyboard.c +) +ENDIF(NOT USE_MICRO_DD) + +INCLUDE(FindPkgConfig) +pkg_check_modules(pkgs REQUIRED edbus) + +FOREACH(flag ${pkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +IF(USE_ENGINEER_MODE) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -g -fno-omit-frame-pointer -finstrument-functions") +ELSE() + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -g -fno-omit-frame-pointer") +ENDIF() + +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") +MESSAGE("FLAGS: ${CMAKE_C_FLAGS}") + +IF("$ENV{CFLAGS}" MATCHES "-DMICRO_DD") + OPTION(USE_MICRO_DD "Use Micro DD" ON) +ENDIF() + +ADD_DEFINITIONS("-DPREFIX=\"${CMAKE_INSTALL_PREFIX}\"") +ADD_DEFINITIONS("-DENABLE_TEST_DLOG") + +ADD_EXECUTABLE(${PROJECT_NAME} ${SRCS}) +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS} shared) + +INSTALL(TARGETS ${PROJECT_NAME} DESTINATION bin) diff --git a/src/auto-test/board-info.c b/src/auto-test/board-info.c new file mode 100644 index 0000000..ca4cc6d --- /dev/null +++ b/src/auto-test/board-info.c @@ -0,0 +1,108 @@ +/* + * test + * + * Copyright (c) 2013 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 "test.h" + +#define METHOD_GET_SERIAL "GetSerial" +#define METHOD_GET_REVISION "GetHWRev" + +void get_serial(void) +{ + DBusError err; + DBusMessage *msg; + int ret, val; + char *data; + + msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME, DEVICED_PATH_BOARD, + DEVICED_INTERFACE_BOARD, METHOD_GET_SERIAL, NULL, NULL); + if (!msg) { + _E("fail send message"); + return; + } + + dbus_error_init(&err); + + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &data, DBUS_TYPE_INT32, &val, DBUS_TYPE_INVALID); + if (!ret) { + _E("no message : [%s:%s]", err.name, err.message); + return; + } + dbus_message_unref(msg); + dbus_error_free(&err); + + _D("%s %d", data, val); +} + +static void get_revision(void) +{ + DBusError err; + DBusMessage *msg; + int ret, val; + + msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME, DEVICED_PATH_BOARD, + DEVICED_INTERFACE_BOARD, METHOD_GET_REVISION, NULL, NULL); + if (!msg) { + _E("fail send message"); + return; + } + dbus_error_init(&err); + + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &val, DBUS_TYPE_INVALID); + + if (!ret) { + _E("no message : [%s:%s]", err.name, err.message); + return; + } + dbus_message_unref(msg); + dbus_error_free(&err); + _E("%s-%s : %d", DEVICED_INTERFACE_BOARD, METHOD_GET_REVISION, val); + if(val >= 8) { + _D("Rinato Neo"); + } else { + _D("Rinato"); + } +} + +static void board_init(void *data) +{ + _I("start test"); + get_revision(); + get_serial(); +} + +static void board_exit(void *data) +{ + _I("end test"); +} + +static int board_unit(int argc, char **argv) +{ + get_revision(); + get_serial(); + return 0; +} + +static const struct test_ops board_test_ops = { + .priority = TEST_PRIORITY_NORMAL, + .name = "board", + .init = board_init, + .exit = board_exit, + .unit = board_unit, +}; + +TEST_OPS_REGISTER(&board_test_ops) diff --git a/src/auto-test/boot.c b/src/auto-test/boot.c new file mode 100644 index 0000000..5374e57 --- /dev/null +++ b/src/auto-test/boot.c @@ -0,0 +1,177 @@ +/* + * test + * + * Copyright (c) 2013 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 "test.h" + +#define EDBUS_INIT_RETRY_COUNT 5 +static int edbus_init_val; +static DBusConnection *conn; +static E_DBus_Connection *edbus_conn; + +static const struct boot_control_type { + char *name; + char *status; +} boot_control_types [] = { + {"poweroffpopup", "pwroff-popup"}, + {"poweroffpopup", "reboot"}, + {"poweroffpopup", "reboot-recovery"}, + {"poweroffpopup", "poweroff"}, + {"poweroffpopup", "fota"}, +}; + +static void edbus_init(void) +{ + DBusError error; + int retry = 0; + int i, ret; + + dbus_threads_init_default(); + dbus_error_init(&error); + + do { + edbus_init_val = e_dbus_init(); + if (edbus_init_val) + break; + if (retry == EDBUS_INIT_RETRY_COUNT) { + _E("fail to init edbus"); + return; + } + retry++; + } while (retry <= EDBUS_INIT_RETRY_COUNT); + + retry = 0; + do { + conn = dbus_bus_get(DBUS_BUS_SYSTEM, &error); + if (conn) + break; + if (retry == EDBUS_INIT_RETRY_COUNT) { + _E("fail to get dbus"); + goto out1; + } + retry++; + } while (retry <= EDBUS_INIT_RETRY_COUNT); + + retry = 0; + do { + edbus_conn = e_dbus_connection_setup(conn); + if (edbus_conn) + break; + if (retry == EDBUS_INIT_RETRY_COUNT) { + _E("fail to get edbus"); + goto out2; + } + retry++; + } while (retry <= EDBUS_INIT_RETRY_COUNT); + return; +out2: + dbus_connection_set_exit_on_disconnect(conn, FALSE); +out1: + e_dbus_shutdown(); +} + +static void edbus_exit(void) +{ + e_dbus_connection_close(edbus_conn); + e_dbus_shutdown(); +} + +static int broadcast_edbus_signal(const char *path, const char *interface, + const char *name, const char *sig, char *param[]) +{ + DBusMessage *msg; + DBusMessageIter iter; + int r; + + msg = dbus_message_new_signal(path, interface, name); + if (!msg) { + _E("fail to allocate new %s.%s signal", interface, name); + return -EPERM; + } + + dbus_message_iter_init_append(msg, &iter); + r = append_variant(&iter, sig, param); + if (r < 0) { + _E("append_variant error(%d)", r); + return -EPERM; + } + + e_dbus_message_send(edbus_conn, msg, NULL, -1, NULL); + + dbus_message_unref(msg); + return 0; +} + +static void poweroff_send_broadcast(char *status) +{ + char *arr[2]; + char str_status[32]; + + snprintf(str_status, sizeof(str_status), "%s", status); + arr[0] = str_status; + arr[1] = "0"; + _D("broadcast poweroff %s %s", arr[0], arr[1]); + + edbus_init(); + broadcast_edbus_signal(DEVICED_OBJECT_PATH, DEVICED_INTERFACE_NAME, + "poweroffpopup", "si", arr); + edbus_exit(); +} + +static void unit(char *unit, char *status) +{ + int index; + + for (index = 0; index < ARRAY_SIZE(boot_control_types); index++) { + if (strcmp(unit, boot_control_types[index].name) != 0 || + strcmp(status, boot_control_types[index].status) != 0) + continue; + if (strcmp(unit, "poweroffpopup") == 0) + poweroff_send_broadcast(boot_control_types[index].status); + } + +} + +static void boot_init(void *data) +{ +} + +static void boot_exit(void *data) +{ +} + +static int boot_unit(int argc, char **argv) +{ + int status; + + if (argv[1] == NULL) + return -EINVAL; + if (argc < 3) + return -EAGAIN; + unit(argv[argc-2], argv[argc-1]); +out: + return 0; +} + +static const struct test_ops boot_test_ops = { + .priority = TEST_PRIORITY_HIGH, + .name = "boot", + .init = boot_init, + .exit = boot_exit, + .unit = boot_unit, +}; + +TEST_OPS_REGISTER(&boot_test_ops) diff --git a/src/auto-test/cpu-info.c b/src/auto-test/cpu-info.c new file mode 100644 index 0000000..9a5e156 --- /dev/null +++ b/src/auto-test/cpu-info.c @@ -0,0 +1,78 @@ +/* + * test + * + * Copyright (c) 2013 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 "test.h" + +#define METHOD_GET_REVISION "GetRevision" + +static void get_revision(void) +{ + DBusError err; + DBusMessage *msg; + int ret, val; + + msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME, DEVICED_PATH_SYSNOTI, + DEVICED_INTERFACE_SYSNOTI, METHOD_GET_REVISION, NULL, NULL); + if (!msg) { + _E("fail send message"); + return; + } + dbus_error_init(&err); + + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &val, DBUS_TYPE_INVALID); + + if (!ret) { + _E("no message : [%s:%s]", err.name, err.message); + return; + } + dbus_message_unref(msg); + dbus_error_free(&err); + _E("%s-%s : %d", DEVICED_INTERFACE_SYSNOTI, METHOD_GET_REVISION, val); + if(val >= 8) { + _D("Rinato Neo"); + } else { + _D("Rinato"); + } +} + +static void cpuinfo_init(void *data) +{ + _I("start test"); + get_revision(); +} + +static void cpuinfo_exit(void *data) +{ + _I("end test"); +} + +static int cpuinfo_unit(int argc, char **argv) +{ + get_revision(); + return 0; +} + +static const struct test_ops cpuinfo_test_ops = { + .priority = TEST_PRIORITY_NORMAL, + .name = "cpuinfo", + .init = cpuinfo_init, + .exit = cpuinfo_exit, + .unit = cpuinfo_unit, +}; + +TEST_OPS_REGISTER(&cpuinfo_test_ops) diff --git a/src/auto-test/cradle.c b/src/auto-test/cradle.c new file mode 100644 index 0000000..3abe136 --- /dev/null +++ b/src/auto-test/cradle.c @@ -0,0 +1,150 @@ +/* + * test + * + * Copyright (c) 2013 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 "test.h" + +#define METHOD_GET_CRADLE "GetCradle" + +static const struct device_change_type { + char *name; + char *status; +} device_change_types [] = { + {"cradle", "1"}, + {"cradle", "0"}, +}; + +static int test_cradle(void) +{ + DBusError err; + DBusMessage *msg; + int ret, level; + + msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME, + DEVICED_PATH_SYSNOTI, + DEVICED_INTERFACE_SYSNOTI, + METHOD_GET_CRADLE, NULL, NULL); + if (!msg) { + _E("fail : %s %s %s %s", + DEVICED_BUS_NAME, DEVICED_PATH_SYSNOTI, DEVICED_INTERFACE_SYSNOTI, + METHOD_GET_CRADLE); + return -EBADMSG; + } + + dbus_error_init(&err); + + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &level, + DBUS_TYPE_INVALID); + if (!ret) { + _E("no message : [%s:%s]", err.name, err.message); + level = -1; + } + _I("%d", level); + dbus_message_unref(msg); + dbus_error_free(&err); + sleep(TEST_WAIT_TIME_INTERVAL); + return level; +} + +static int test(int index) +{ + DBusError err; + DBusMessage *msg; + int ret, ret_val; + char *param[4]; + + param[0] = METHOD_SET_DEVICE; + param[1] = "2"; + param[2] = device_change_types[index].name; + param[3] = device_change_types[index].status; + + msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME, + DEVICED_PATH_SYSNOTI, + DEVICED_INTERFACE_SYSNOTI, + METHOD_SET_DEVICE, "siss", param); + if (!msg) { + _E("fail : %s %s %s %s", + DEVICED_BUS_NAME, DEVICED_PATH_SYSNOTI, DEVICED_INTERFACE_SYSNOTI, + METHOD_SET_DEVICE); + return -EBADMSG; + } + + dbus_error_init(&err); + + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &ret_val, DBUS_TYPE_INVALID); + if (ret == 0) { + _E("no message : [%s:%s]", err.name, err.message); + dbus_error_free(&err); + ret_val = -EBADMSG; + } + _I("%s %s", device_change_types[index].name, device_change_types[index].status); + dbus_message_unref(msg); + dbus_error_free(&err); + sleep(TEST_WAIT_TIME_INTERVAL); + return ret_val; +} + +static void unit(char *unit, char *status) +{ + int index; + + for (index = 0; index < ARRAY_SIZE(device_change_types); index++) { + if (strcmp(unit, device_change_types[index].name) != 0 || + strcmp(status, device_change_types[index].status) != 0) + continue; + test(index); + test_cradle(); + } +} + +static void cradle_init(void *data) +{ + int index; + + _I("start test"); + for (index = 0; index < ARRAY_SIZE(device_change_types); index++) + test(index); +} + +static void cradle_exit(void *data) +{ + _I("end test"); +} + +static int cradle_unit(int argc, char **argv) +{ + int status; + + if (argv[1] == NULL) + return -EINVAL; + if (argc != 4) + return -EAGAIN; + + unit(argv[2], argv[3]); +out: + return 0; +} + +static const struct test_ops cradle_test_ops = { + .priority = TEST_PRIORITY_NORMAL, + .name = "cradle", + .init = cradle_init, + .exit = cradle_exit, + .unit = cradle_unit, +}; + +TEST_OPS_REGISTER(&cradle_test_ops) diff --git a/src/auto-test/earjack.c b/src/auto-test/earjack.c new file mode 100644 index 0000000..8643bdc --- /dev/null +++ b/src/auto-test/earjack.c @@ -0,0 +1,117 @@ +/* + * test + * + * Copyright (c) 2013 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 "test.h" + +static const struct device_change_type { + char *name; + char *status; +} device_change_types [] = { + {"jack", "1"}, + {"jack", "0"}, + {"key", "1"}, + {"key", "0"}, +}; + +static int test(int index) +{ + DBusError err; + DBusMessage *msg; + int ret, ret_val; + char *param[4]; + + param[0] = METHOD_SET_DEVICE; + param[1] = "2"; + param[2] = device_change_types[index].name; + param[3] = device_change_types[index].status; + + msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME, + DEVICED_PATH_SYSNOTI, + DEVICED_INTERFACE_SYSNOTI, + METHOD_SET_DEVICE, "siss", param); + if (!msg) { + _E("fail : %s %s %s %s", + DEVICED_BUS_NAME, DEVICED_PATH_SYSNOTI, DEVICED_INTERFACE_SYSNOTI, + METHOD_SET_DEVICE); + return -EBADMSG; + } + + dbus_error_init(&err); + + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &ret_val, DBUS_TYPE_INVALID); + if (ret == 0) { + _E("no message : [%s:%s]", err.name, err.message); + dbus_error_free(&err); + ret_val = -EBADMSG; + } + _I("%s %s", device_change_types[index].name, device_change_types[index].status); + dbus_message_unref(msg); + dbus_error_free(&err); + sleep(TEST_WAIT_TIME_INTERVAL); + return ret_val; +} + +static void unit(char *unit, char *status) +{ + int index; + + for (index = 0; index < ARRAY_SIZE(device_change_types); index++) { + if (strcmp(unit, device_change_types[index].name) != 0 || + strcmp(status, device_change_types[index].status) != 0) + continue; + test(index); + } +} + +static void earjack_init(void *data) +{ + int index; + + _I("start test"); + for (index = 0; index < ARRAY_SIZE(device_change_types); index++) + test(index); +} + +static void earjack_exit(void *data) +{ + _I("end test"); +} + +static int earjack_unit(int argc, char **argv) +{ + int status; + + if (argv[1] == NULL) + return -EINVAL; + if (argc != 3) + return -EAGAIN; + + unit(argv[1], argv[2]); +out: + return 0; +} + +static const struct test_ops earjack_test_ops = { + .priority = TEST_PRIORITY_NORMAL, + .name = "earjack", + .init = earjack_init, + .exit = earjack_exit, + .unit = earjack_unit, +}; + +TEST_OPS_REGISTER(&earjack_test_ops) + diff --git a/src/auto-test/hdmi.c b/src/auto-test/hdmi.c new file mode 100644 index 0000000..c1edf83 --- /dev/null +++ b/src/auto-test/hdmi.c @@ -0,0 +1,218 @@ +/* + * test + * + * Copyright (c) 2013 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 "test.h" + +#define METHOD_GET_HDMI "GetHDMI" +#define METHOD_GET_HDCP "GetHDCP" +#define METHOD_GET_HDMI_AUDIO "GetHDMIAudio" + +static const struct device_change_type { + char *name; + char *status; +} device_change_types [] = { + {"hdmi", "1"}, + {"hdmi", "0"}, +}; + +static int test_hdmi(void) +{ + DBusError err; + DBusMessage *msg; + int ret, level; + + msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME, + DEVICED_PATH_SYSNOTI, + DEVICED_INTERFACE_SYSNOTI, + METHOD_GET_HDMI, NULL, NULL); + if (!msg) { + _E("fail : %s %s %s %s", + DEVICED_BUS_NAME, DEVICED_PATH_SYSNOTI, DEVICED_INTERFACE_SYSNOTI, + METHOD_GET_HDMI); + return -EBADMSG; + } + + dbus_error_init(&err); + + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &level, + DBUS_TYPE_INVALID); + if (!ret) { + _E("no message : [%s:%s]", err.name, err.message); + level = -1; + } + _I("%d", level); + dbus_message_unref(msg); + dbus_error_free(&err); + sleep(TEST_WAIT_TIME_INTERVAL); + return level; +} + +static int test_hdcp(void) +{ + DBusError err; + DBusMessage *msg; + int ret, level; + + msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME, + DEVICED_PATH_SYSNOTI, + DEVICED_INTERFACE_SYSNOTI, + METHOD_GET_HDCP, NULL, NULL); + if (!msg) { + _E("fail : %s %s %s %s", + DEVICED_BUS_NAME, DEVICED_PATH_SYSNOTI, DEVICED_INTERFACE_SYSNOTI, + METHOD_GET_HDCP); + return -EBADMSG; + } + + dbus_error_init(&err); + + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &level, + DBUS_TYPE_INVALID); + if (!ret) { + _E("no message : [%s:%s]", err.name, err.message); + level = -1; + } + _I("%d", level); + dbus_message_unref(msg); + dbus_error_free(&err); + sleep(TEST_WAIT_TIME_INTERVAL); + return level; +} + +static int test_hdmi_audio(void) +{ + DBusError err; + DBusMessage *msg; + int ret, level; + + msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME, + DEVICED_PATH_SYSNOTI, + DEVICED_INTERFACE_SYSNOTI, + METHOD_GET_HDMI_AUDIO, NULL, NULL); + if (!msg) { + _E("fail : %s %s %s %s", + DEVICED_BUS_NAME, DEVICED_PATH_SYSNOTI, DEVICED_INTERFACE_SYSNOTI, + METHOD_GET_HDMI_AUDIO); + return -EBADMSG; + } + + dbus_error_init(&err); + + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &level, + DBUS_TYPE_INVALID); + if (!ret) { + _E("no message : [%s:%s]", err.name, err.message); + level = -1; + } + _I("%d", level); + dbus_message_unref(msg); + dbus_error_free(&err); + sleep(TEST_WAIT_TIME_INTERVAL); + return level; +} + +static int test(int index) +{ + DBusError err; + DBusMessage *msg; + int ret, ret_val; + char *param[4]; + + param[0] = METHOD_SET_DEVICE; + param[1] = "2"; + param[2] = device_change_types[index].name; + param[3] = device_change_types[index].status; + + msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME, + DEVICED_PATH_SYSNOTI, + DEVICED_INTERFACE_SYSNOTI, + METHOD_SET_DEVICE, "siss", param); + if (!msg) { + _E("fail : %s %s %s %s", + DEVICED_BUS_NAME, DEVICED_PATH_SYSNOTI, DEVICED_INTERFACE_SYSNOTI, + METHOD_SET_DEVICE); + return -EBADMSG; + } + + dbus_error_init(&err); + + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &ret_val, DBUS_TYPE_INVALID); + if (ret == 0) { + _E("no message : [%s:%s]", err.name, err.message); + dbus_error_free(&err); + ret_val = -EBADMSG; + } + _I("%s %s", device_change_types[index].name, device_change_types[index].status); + dbus_message_unref(msg); + dbus_error_free(&err); + sleep(TEST_WAIT_TIME_INTERVAL); + return ret_val; +} + +static void unit(char *unit, char *status) +{ + int index; + + for (index = 0; index < ARRAY_SIZE(device_change_types); index++) { + if (strcmp(unit, device_change_types[index].name) != 0 || + strcmp(status, device_change_types[index].status) != 0) + continue; + test(index); + } +} + +static void hdmi_init(void *data) +{ + int index; + + _I("start test"); + for (index = 0; index < ARRAY_SIZE(device_change_types); index++) { + test(index); + test_hdmi(); + test_hdcp(); + test_hdmi_audio(); + } +} + +static void hdmi_exit(void *data) +{ + _I("end test"); +} + +static int hdmi_unit(int argc, char **argv) +{ + int status; + + if (argv[1] == NULL) + return -EINVAL; + if (argc != 3) + return -EAGAIN; + + unit(argv[1], argv[2]); +out: + return 0; +} + +static const struct test_ops hdmi_test_ops = { + .priority = TEST_PRIORITY_NORMAL, + .name = "hdmi", + .init = hdmi_init, + .exit = hdmi_exit, + .unit = hdmi_unit, +}; + +TEST_OPS_REGISTER(&hdmi_test_ops) diff --git a/src/auto-test/keyboard.c b/src/auto-test/keyboard.c new file mode 100644 index 0000000..e9cec63 --- /dev/null +++ b/src/auto-test/keyboard.c @@ -0,0 +1,114 @@ +/* + * test + * + * Copyright (c) 2013 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 "test.h" + +static const struct device_change_type { + char *name; + char *status; +} device_change_types [] = { + {"keyboard", "1"}, + {"keyboard", "0"}, +}; + +static int test(int index) +{ + DBusError err; + DBusMessage *msg; + int ret, ret_val; + char *param[4]; + + param[0] = METHOD_SET_DEVICE; + param[1] = "2"; + param[2] = device_change_types[index].name; + param[3] = device_change_types[index].status; + + msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME, + DEVICED_PATH_SYSNOTI, + DEVICED_INTERFACE_SYSNOTI, + METHOD_SET_DEVICE, "siss", param); + if (!msg) { + _E("fail : %s %s %s %s", + DEVICED_BUS_NAME, DEVICED_PATH_SYSNOTI, DEVICED_INTERFACE_SYSNOTI, + METHOD_SET_DEVICE); + return -EBADMSG; + } + + dbus_error_init(&err); + + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &ret_val, DBUS_TYPE_INVALID); + if (ret == 0) { + _E("no message : [%s:%s]", err.name, err.message); + dbus_error_free(&err); + ret_val = -EBADMSG; + } + _I("%s %s", device_change_types[index].name, device_change_types[index].status); + dbus_message_unref(msg); + dbus_error_free(&err); + sleep(TEST_WAIT_TIME_INTERVAL); + return ret_val; +} + +static void unit(char *unit, char *status) +{ + int index; + + for (index = 0; index < ARRAY_SIZE(device_change_types); index++) { + if (strcmp(unit, device_change_types[index].name) != 0 || + strcmp(status, device_change_types[index].status) != 0) + continue; + test(index); + } +} + +static void keyboard_init(void *data) +{ + int index; + + _I("start test"); + for (index = 0; index < ARRAY_SIZE(device_change_types); index++) + test(index); +} + +static void keyboard_exit(void *data) +{ + _I("end test"); +} + +static int keyboard_unit(int argc, char **argv) +{ + int status; + + if (argv[1] == NULL) + return -EINVAL; + if (argc != 3) + return -EAGAIN; + + unit(argv[1], argv[2]); +out: + return 0; +} + +static const struct test_ops keyboard_test_ops = { + .priority = TEST_PRIORITY_NORMAL, + .name = "keyboard", + .init = keyboard_init, + .exit = keyboard_exit, + .unit = keyboard_unit, +}; + +TEST_OPS_REGISTER(&keyboard_test_ops) diff --git a/src/auto-test/main.c b/src/auto-test/main.c new file mode 100644 index 0000000..8344cac --- /dev/null +++ b/src/auto-test/main.c @@ -0,0 +1,49 @@ +/* + * test + * + * Copyright (c) 2013 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 "test.h" + +static void test_main(int argc, char **argv) +{ + _I("auto test all"); + test_init((void *)NULL); + test_exit((void *)NULL); +} + +static void unit_test(int argc, char **argv) +{ + const struct test_ops *ops; + + ops = find_test(argv[1]); + if (!ops) { + _E("there is no test ops : %s", argv[1]); + return; + } + ops->unit(argc, argv); +} + +int main(int argc, char **argv) +{ + if (argc >= 2 ) + unit_test(argc, argv); + else + test_main(argc, argv); + return 0; +} + diff --git a/src/auto-test/power-supply.c b/src/auto-test/power-supply.c new file mode 100644 index 0000000..d63a577 --- /dev/null +++ b/src/auto-test/power-supply.c @@ -0,0 +1,398 @@ +/* + * test + * + * Copyright (c) 2013 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 "test.h" + +#define S_ENTER 1 +#define S_LEAVE 0 + +#define SIGNAL_CHARGE_NOW "ChargeNow" +#define SIGNAL_CHARGER_STATUS "ChargerStatus" +#define SIGNAL_TEMP_GOOD "TempGood" + +static E_DBus_Signal_Handler *edbus_charge_now_handler; +static E_DBus_Signal_Handler *edbus_charger_status_handler; +static E_DBus_Signal_Handler *edbus_temp_good_handler; +static E_DBus_Connection *edbus_conn; + +static struct power_supply_type { + char *scenario; + int status; + char *capacity; + char *charge_status; + char *health; + char *online; + char *present; + char *name; +} power_supply_types [] = { + {"norm", S_ENTER, "100","Charging", "Good", "2", "1", "CHARGE"}, + {"norm", S_ENTER, "100","Discharging", "Good", "1", "1", "DISCHARGE"}, + {"norm", S_LEAVE, "100","Discharging", "Good", "1", "1", NULL}, //init + + {"heat1",S_ENTER, "100","Discharging", "Overheat", "1", "1", NULL}, + {"heat1",S_ENTER, "100","Not charging","Overheat", "2", "1", "HEALTH(H) BEFORE CHARGE"}, + {"heat1",S_LEAVE, "100","Discharging", "Overheat", "1", "1", "DISCHARGE"}, + {"heat1",S_LEAVE, "100","Discharging", "Good", "1", "1", NULL}, //init + + {"heat2",S_ENTER, "100","Charging", "Good", "2", "1", NULL}, + {"heat2",S_ENTER, "100","Not charging","Overheat", "2", "1", "HEALTH(H) AFTER CHARGE"}, + {"heat2",S_LEAVE, "100","Discharging", "Overheat", "1", "1", "DISCHARGE"}, + {"heat2",S_LEAVE, "100","Discharging", "Good", "1", "1", NULL}, //init + + {"cold1",S_ENTER, "100","Discharging", "Cold", "1", "1", NULL}, + {"cold1",S_ENTER, "100","Not charging","Cold", "2", "1", "HEALTH(L) BEFORE CHARGE"}, + {"cold1",S_LEAVE, "100","Discharging", "Cold", "1", "1", "DISCHARGE"}, + {"cold1",S_LEAVE, "100","Discharging", "Good", "1", "1", NULL}, //init + + {"cold2",S_ENTER, "100","Charging", "Good", "2", "1", NULL}, + {"cold2",S_ENTER, "100","Not charging","Cold", "2", "1", "HEALTH(L) AFTER CHARGE"}, + {"cold2",S_LEAVE, "100","Discharging", "Cold", "1", "1", "DISCHARGE"}, + {"cold2",S_LEAVE, "100","Discharging", "Good", "1", "1", NULL}, //init + + {"ovp", S_ENTER, "100","Discharging", "Over voltage", "1", "1", "OVP"}, + {"ovp", S_LEAVE, "100","Discharging", "Good", "1", "1", NULL}, //init + + {"pres1",S_ENTER, "100","Discharging", "Good", "1", "0", NULL}, + {"pres1",S_ENTER, "100","Not charging","Good", "2", "0", "PRESENT BEFORE CHARGE"}, + {"pres1",S_LEAVE, "100","Discharging", "Good", "1", "0", "DISCHARGE"}, + {"pres1",S_LEAVE, "100","Discharging", "Good", "1", "1", NULL}, //init + + {"pres2",S_ENTER, "100","Charging", "Good", "2", "1", NULL}, + {"pres2",S_ENTER, "100","Not charging","Good", "2", "0", "PRESENT AFTER CHARGE"}, + {"pres2",S_LEAVE, "100","Discharging", "Good", "1", "0", "DISCHARGE"}, + {"pres2",S_LEAVE, "100","Discharging", "Good", "1", "1", NULL}, //init + + {"bat15",S_ENTER, "15", "Discharging", "Good", "1", "1", "LOWBAT 15%"}, //lowbat 15% + {"bat15",S_LEAVE, "15", "Charging", "Good", "2", "1", "LOWBAT 15%"}, + {"bat5", S_ENTER, "5", "Discharging", "Good", "1", "1", "LOWBAT 5%"}, //lowbat 5% + {"bat5", S_LEAVE, "5", "Charging", "Good", "2", "1", "LOWBAT 5%"}, + {"bat3", S_ENTER, "3", "Discharging", "Good", "1", "1", "LOWBAT 3%"}, //lowbat 3% + {"bat3", S_LEAVE, "3", "Charging", "Good", "2", "1", "LOWBAT 3%"}, + {"bat1", S_ENTER, "1", "Discharging", "Good", "1", "1", "LOWBAT 1%"}, //lowbat 1% + {"bat1", S_LEAVE, "1", "Charging", "Good", "2", "1", "LOWBAT 1%"}, + + {"ta", S_ENTER, "100","Charging", "Good", "2", "1", "CHARGE"}, //charging + {"ta", S_LEAVE, "100","Discharging", "Good", "1", "1", "DISCHARGE"},//discharging + {"capacity", S_ENTER, "100","Discharging", "Good", "1", "1", "CAPACITY"},//charging + {"capacity", S_LEAVE, "100","Charging", "Good", "2", "1", "CAPACITY"},//discharging +}; + +static void unregister_edbus_signal_handler(void) +{ + e_dbus_signal_handler_del(edbus_conn, edbus_charge_now_handler); + e_dbus_signal_handler_del(edbus_conn, edbus_charger_status_handler); + e_dbus_signal_handler_del(edbus_conn, edbus_temp_good_handler); + e_dbus_connection_close(edbus_conn); + e_dbus_shutdown(); +} + +static void power_supply_changed(void *data, DBusMessage *msg) +{ + DBusError err; + int val; + int r; + + _I("edbus signal Received"); + + r = dbus_message_is_signal(msg, DEVICED_INTERFACE_BATTERY, SIGNAL_CHARGE_NOW); + if (!r) { + _E("dbus_message_is_signal error"); + return; + } + + _I("%s - %s", DEVICED_INTERFACE_BATTERY, SIGNAL_CHARGE_NOW); + + dbus_error_init(&err); + r = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &val, DBUS_TYPE_INVALID); + if (!r) { + _E("dbus_message_get_args error"); + return; + } + _I("receive data : %d", val); +} + +static int register_charge_now_handler(void) +{ + int ret; + + e_dbus_init(); + + edbus_conn = e_dbus_bus_get(DBUS_BUS_SYSTEM); + if (!(edbus_conn)) { + ret = -ECONNREFUSED; + goto edbus_handler_out; + } + + edbus_charge_now_handler = e_dbus_signal_handler_add(edbus_conn, NULL, DEVICED_PATH_BATTERY, + DEVICED_INTERFACE_BATTERY, SIGNAL_CHARGE_NOW, power_supply_changed, NULL); + if (!(edbus_charge_now_handler)) { + ret = -ECONNREFUSED; + goto edbus_handler_connection_out; + } + return 0; + +edbus_handler_connection_out: + e_dbus_connection_close(edbus_conn); +edbus_handler_out: + e_dbus_shutdown(); + return ret; +} + +static void charger_status_changed(void *data, DBusMessage *msg) +{ + DBusError err; + int val; + int r; + + _I("edbus signal Received"); + + r = dbus_message_is_signal(msg, DEVICED_INTERFACE_BATTERY, SIGNAL_CHARGER_STATUS); + if (!r) { + _E("dbus_message_is_signal error"); + return; + } + + _I("%s - %s", DEVICED_INTERFACE_BATTERY, SIGNAL_CHARGER_STATUS); + + dbus_error_init(&err); + r = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &val, DBUS_TYPE_INVALID); + if (!r) { + _E("dbus_message_get_args error"); + return; + } + _I("receive data : %d", val); +} + +static int register_charger_status_handler(void) +{ + int ret; + + e_dbus_init(); + + edbus_conn = e_dbus_bus_get(DBUS_BUS_SYSTEM); + if (!(edbus_conn)) { + ret = -ECONNREFUSED; + goto edbus_handler_out; + } + + edbus_charger_status_handler = e_dbus_signal_handler_add(edbus_conn, NULL, DEVICED_PATH_BATTERY, + DEVICED_INTERFACE_BATTERY, SIGNAL_CHARGER_STATUS, charger_status_changed, NULL); + if (!(edbus_charger_status_handler)) { + ret = -ECONNREFUSED; + goto edbus_handler_connection_out; + } + return 0; + +edbus_handler_connection_out: + e_dbus_connection_close(edbus_conn); +edbus_handler_out: + e_dbus_shutdown(); + return ret; +} + +static void temp_status_changed(void *data, DBusMessage *msg) +{ + DBusError err; + int val; + int r; + + _I("edbus signal Received"); + + r = dbus_message_is_signal(msg, DEVICED_INTERFACE_BATTERY, SIGNAL_TEMP_GOOD); + if (!r) { + _E("dbus_message_is_signal error"); + return; + } + + _I("%s - %s", DEVICED_INTERFACE_BATTERY, SIGNAL_TEMP_GOOD); +} + +static int register_temp_good_handler(void) +{ + int ret; + + e_dbus_init(); + + edbus_conn = e_dbus_bus_get(DBUS_BUS_SYSTEM); + if (!(edbus_conn)) { + ret = -ECONNREFUSED; + goto edbus_handler_out; + } + + edbus_temp_good_handler = e_dbus_signal_handler_add(edbus_conn, NULL, DEVICED_PATH_BATTERY, + DEVICED_INTERFACE_BATTERY, SIGNAL_TEMP_GOOD, temp_status_changed, NULL); + if (!(edbus_temp_good_handler)) { + ret = -ECONNREFUSED; + goto edbus_handler_connection_out; + } + return 0; + +edbus_handler_connection_out: + e_dbus_connection_close(edbus_conn); +edbus_handler_out: + e_dbus_shutdown(); + return ret; +} +static void test_signal(void) +{ + _I("test"); + register_charge_now_handler(); + register_charger_status_handler(); + register_temp_good_handler(); + ecore_main_loop_begin(); +} + +static int test(int index) +{ + DBusError err; + DBusMessage *msg; + int ret, ret_val; + char *param[7]; + + param[0] = POWER_SUBSYSTEM; + param[1] = "5"; + param[2] = power_supply_types[index].capacity; + param[3] = power_supply_types[index].charge_status; + param[4] = power_supply_types[index].health; + param[5] = power_supply_types[index].online; + param[6] = power_supply_types[index].present; + + msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME, + DEVICED_PATH_SYSNOTI, + DEVICED_INTERFACE_SYSNOTI, + POWER_SUBSYSTEM, "sisssss", param); + if (!msg) { + _E("fail : %s %s %s %s", + DEVICED_BUS_NAME, DEVICED_PATH_SYSNOTI, DEVICED_INTERFACE_SYSNOTI, + POWER_SUBSYSTEM); + return -EBADMSG; + } + + dbus_error_init(&err); + + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &ret_val, DBUS_TYPE_INVALID); + if (ret == 0) { + _E("no message : [%s:%s]", err.name, err.message); + dbus_error_free(&err); + ret_val = -EBADMSG; + } + + if (power_supply_types[index].name != NULL) + _I("++++++++++[START] %s ++++++++++", power_supply_types[index].name); + _I("CAPACITY(%s , %s) P(%s) STATUS(%s) HEALTH(%s)", + power_supply_types[index].capacity, + power_supply_types[index].online, + power_supply_types[index].present, + power_supply_types[index].charge_status, + power_supply_types[index].health); + if (power_supply_types[index].name != NULL) + _I("++++++++++[END] %s ++++++++++", power_supply_types[index].name); + + dbus_message_unref(msg); + dbus_error_free(&err); + sleep(TEST_WAIT_TIME_INTERVAL); + return ret_val; +} + +static void scenario(char *scenario) +{ + int index; + + for (index = 0; index < ARRAY_SIZE(power_supply_types); index++) { + if (strcmp(scenario, power_supply_types[index].scenario) != 0) + continue; + test(index); + } +} + +static void unit(char *unit, int status) +{ + int index; + int found = 0; + char *scenario = NULL; + + for (index = 0; index < ARRAY_SIZE(power_supply_types); index++) { + scenario = power_supply_types[index].scenario; + if (strcmp(unit, scenario) != 0 || + power_supply_types[index].status != status) + continue; + found = 1; + test(index); + } + + if (found) + return; + + index = strlen(unit); + if (index < 0 || index > 3) + return; + + index = strtol(unit, NULL, 10); + if (index < 0 || index > 100) + return; + + for (index = 0; index < ARRAY_SIZE(power_supply_types); index++) { + if (strcmp("capacity", power_supply_types[index].scenario) != 0 || + power_supply_types[index].status != status) + continue; + power_supply_types[index].capacity = unit; + _D("%s", power_supply_types[index].capacity); + test(index); + } +} + +static void power_supply_init(void *data) +{ + int index; + + _I("start test"); + for (index = 0; index < ARRAY_SIZE(power_supply_types); index++) + test(index); +} + +static void power_supply_exit(void *data) +{ + _I("end test"); +} + +static int power_supply_unit(int argc, char **argv) +{ + if (argv[1] == NULL) + return -EINVAL; + else if (argc != 4) + return -EAGAIN; + if (strcmp("wait", argv[2]) == 0) + test_signal(); + else if (strcmp("scenario", argv[2]) == 0) + scenario(argv[3]); + else if (strcmp("enter", argv[3]) == 0) + unit(argv[2], S_ENTER); + else if (strcmp("leave", argv[3]) == 0) + unit(argv[2], S_LEAVE); + return 0; +} + +static const struct test_ops power_test_ops = { + .priority = TEST_PRIORITY_NORMAL, + .name = "power", + .init = power_supply_init, + .exit = power_supply_exit, + .unit = power_supply_unit, +}; + +TEST_OPS_REGISTER(&power_test_ops) diff --git a/src/auto-test/storage.c b/src/auto-test/storage.c new file mode 100644 index 0000000..dad9a7c --- /dev/null +++ b/src/auto-test/storage.c @@ -0,0 +1,117 @@ +/* + * test + * + * Copyright (c) 2013 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 "test.h" + +#define METHOD_GET_STORAGE "getstorage" +#define METHOD_MEM_TRIM "MemTrim" + +static void mem_trim(void *data, DBusMessage *msg, DBusError *tmp) +{ + DBusError err; + int ret, result; + + if (!msg) + return; + + dbus_error_init(&err); + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &result, DBUS_TYPE_INVALID); + if (!ret) { + _E("no message [%s:%s]", err.name, err.message); + dbus_error_free(&err); + return; + } + _D("succeed mem trim : %d", result); +} + +static int request_mem_trim(void) +{ + int ret; + + ret = dbus_method_async_with_reply(DEVICED_BUS_NAME, + DEVICED_PATH_STORAGE, DEVICED_INTERFACE_STORAGE, + METHOD_MEM_TRIM, NULL, NULL, mem_trim, -1, NULL); + if (ret == 0) + _D("request mem trim"); + return ret; +} + +static int test_storage(void) +{ + DBusError err; + DBusMessage *msg; + int ret; + double dAvail; + double dTotal; + + msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME, + DEVICED_PATH_STORAGE, + DEVICED_INTERFACE_STORAGE, + METHOD_GET_STORAGE, NULL, NULL); + if (!msg) { + _E("fail : %s %s %s %s", + DEVICED_BUS_NAME, DEVICED_PATH_SYSNOTI, DEVICED_INTERFACE_SYSNOTI, + METHOD_GET_STORAGE); + return -EBADMSG; + } + + dbus_error_init(&err); + + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT64, &dTotal, DBUS_TYPE_INT64, &dAvail, DBUS_TYPE_INVALID);; + if (!ret) { + _E("no message : [%s:%s]", err.name, err.message); + } + _I("total : %4.4lf avail %4.4lf", dTotal, dAvail); + dbus_message_unref(msg); + dbus_error_free(&err); + sleep(TEST_WAIT_TIME_INTERVAL); + return ret; +} + +static void storage_init(void *data) +{ + _I("start test"); + test_storage(); +} + +static void storage_exit(void *data) +{ + _I("end test"); +} + +static int storage_unit(int argc, char **argv) +{ + int status; + + if (argv[1] == NULL) + return -EINVAL; + test_storage(); + request_mem_trim(); + ecore_main_loop_begin(); +out: + return 0; +} + +static const struct test_ops storage_test_ops = { + .priority = TEST_PRIORITY_NORMAL, + .name = "storage", + .init = storage_init, + .exit = storage_exit, + .unit = storage_unit, +}; + +TEST_OPS_REGISTER(&storage_test_ops) diff --git a/src/auto-test/test.c b/src/auto-test/test.c new file mode 100644 index 0000000..6253487 --- /dev/null +++ b/src/auto-test/test.c @@ -0,0 +1,70 @@ +/* + * test + * + * Copyright (c) 2013 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 "test.h" + +static dd_list *dd_head; + +void add_test(const struct test_ops *d) +{ + if (d->priority == TEST_PRIORITY_HIGH) + DD_LIST_PREPEND(dd_head, d); + else + DD_LIST_APPEND(dd_head, d); +} + +void remove_test(const struct test_ops *d) +{ + DD_LIST_REMOVE(dd_head, d); +} + +const struct test_ops *find_test(const char *name) +{ + dd_list *elem; + const struct test_ops *d; + + DD_LIST_FOREACH(dd_head, elem, d) { + if (!strcmp(d->name, name)) + return d; + } + return NULL; +} + +void test_init(void *data) +{ + dd_list *elem; + const struct test_ops *d; + + DD_LIST_FOREACH(dd_head, elem, d) { + _D("[%s] initialize", d->name); + if (d->init) + d->init(data); + } +} + +void test_exit(void *data) +{ + dd_list *elem; + const struct test_ops *d; + + DD_LIST_FOREACH(dd_head, elem, d) { + _D("[%s] deinitialize", d->name); + if (d->exit) + d->exit(data); + } +} \ No newline at end of file diff --git a/src/auto-test/test.h b/src/auto-test/test.h new file mode 100644 index 0000000..2f68f3c --- /dev/null +++ b/src/auto-test/test.h @@ -0,0 +1,107 @@ +/* + * test + * + * Copyright (c) 2013 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 __TEST_H__ +#define __TEST_H__ +#include +#include +#include + +#include "core/list.h" +#include "core/common.h" +#include "core/udev.h" +#include "shared/dbus.h" + +#ifdef ENABLE_TEST_DLOG +#define ENABLE_DLOG +#endif + +#define LOG_TAG "AUTO_TEST" +#include "shared/log-macro.h" + +#define TEST_WAIT_TIME_INTERVAL 5 +#define METHOD_SET_DEVICE "device_changed" + +enum test_priority { + TEST_PRIORITY_NORMAL = 0, + TEST_PRIORITY_HIGH, +}; + +struct test_ops { + enum test_priority priority; + char *name; + void (*init) (void *data); + void (*exit) (void *data); + int (*start) (void); + int (*stop) (void); + int (*status) (void); + int (*unit) (int argc, char **argv); +}; + +enum test_ops_status { + TEST_OPS_STATUS_UNINIT, + TEST_OPS_STATUS_START, + TEST_OPS_STATUS_STOP, + TEST_OPS_STATUS_MAX, +}; + +void test_init(void *data); +void test_exit(void *data); + +static inline int test_start(const struct test_ops *c) +{ + if (c && c->start) + return c->start(); + + return -EINVAL; +} + +static inline int test_stop(const struct test_ops *c) +{ + if (c && c->stop) + return c->stop(); + + return -EINVAL; +} + +static inline int test_get_status(const struct test_ops *c) +{ + if (c && c->status) + return c->status(); + + return -EINVAL; +} + +#define TEST_OPS_REGISTER(c) \ +static void __CONSTRUCTOR__ module_init(void) \ +{ \ + add_test(c); \ +} \ +static void __DESTRUCTOR__ module_exit(void) \ +{ \ + remove_test(c); \ +} +DBusMessage *deviced_dbus_method_sync_with_reply(const char *dest, const char *path, + const char *interface, const char *method, + const char *sig, char *param[]); +void add_test(const struct test_ops *c); +void remove_test(const struct test_ops *c); +const struct test_ops *find_test(const char *name); + +#endif diff --git a/src/auto-test/time.c b/src/auto-test/time.c new file mode 100644 index 0000000..71edb14 --- /dev/null +++ b/src/auto-test/time.c @@ -0,0 +1,114 @@ +/* + * test + * + * Copyright (c) 2013 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 "test.h" + +#define TIME_CHANGE_SIGNAL "STimeChanged" + +static E_DBus_Signal_Handler *edbus_handler; +static E_DBus_Connection *edbus_conn; + +static void unregister_edbus_signal_handler(void) +{ + e_dbus_signal_handler_del(edbus_conn, edbus_handler); + e_dbus_connection_close(edbus_conn); + e_dbus_shutdown(); +} + +static void time_changed(void *data, DBusMessage *msg) +{ + DBusError err; + int val; + int r; + + _I("edbus signal Received"); + + r = dbus_message_is_signal(msg, DEVICED_INTERFACE_TIME, TIME_CHANGE_SIGNAL); + if (!r) { + _E("dbus_message_is_signal error"); + return; + } + + _I("%s - %s", DEVICED_INTERFACE_TIME, TIME_CHANGE_SIGNAL); + + unregister_edbus_signal_handler(); + ecore_shutdown(); +} + +static int register_edbus_signal_handler(void) +{ + int ret; + + e_dbus_init(); + + edbus_conn = e_dbus_bus_get(DBUS_BUS_SYSTEM); + if (!(edbus_conn)) { + ret = -ECONNREFUSED; + goto edbus_handler_out; + } + + edbus_handler = e_dbus_signal_handler_add(edbus_conn, NULL, DEVICED_PATH_TIME, + DEVICED_INTERFACE_TIME, TIME_CHANGE_SIGNAL, time_changed, NULL); + if (!(edbus_handler)) { + ret = -ECONNREFUSED; + goto edbus_handler_connection_out; + } + return 0; + +edbus_handler_connection_out: + e_dbus_connection_close(edbus_conn); +edbus_handler_out: + e_dbus_shutdown(); + return ret; +} + +static void test_signal(void) +{ + _I("test"); + register_edbus_signal_handler(); + ecore_main_loop_begin(); +} + +static void time_init(void *data) +{ +} + +static void time_exit(void *data) +{ +} + +static int time_unit(int argc, char **argv) +{ + if (argv[1] == NULL) + return -EINVAL; + else if (argc != 4) + return -EAGAIN; + if (strcmp("wait", argv[2]) == 0) + test_signal(); + return 0; +} + +static const struct test_ops power_test_ops = { + .priority = TEST_PRIORITY_NORMAL, + .name = "time", + .init = time_init, + .exit = time_exit, + .unit = time_unit, +}; + +TEST_OPS_REGISTER(&power_test_ops) diff --git a/src/auto-test/tvout.c b/src/auto-test/tvout.c new file mode 100644 index 0000000..3b75459 --- /dev/null +++ b/src/auto-test/tvout.c @@ -0,0 +1,114 @@ +/* + * test + * + * Copyright (c) 2013 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 "test.h" + +static const struct device_change_type { + char *name; + char *status; +} device_change_types [] = { + {"tvout", "1"}, + {"tvout", "0"}, +}; + +static int test(int index) +{ + DBusError err; + DBusMessage *msg; + int ret, ret_val; + char *param[4]; + + param[0] = METHOD_SET_DEVICE; + param[1] = "2"; + param[2] = device_change_types[index].name; + param[3] = device_change_types[index].status; + + msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME, + DEVICED_PATH_SYSNOTI, + DEVICED_INTERFACE_SYSNOTI, + METHOD_SET_DEVICE, "siss", param); + if (!msg) { + _E("fail : %s %s %s %s", + DEVICED_BUS_NAME, DEVICED_PATH_SYSNOTI, DEVICED_INTERFACE_SYSNOTI, + METHOD_SET_DEVICE); + return -EBADMSG; + } + + dbus_error_init(&err); + + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &ret_val, DBUS_TYPE_INVALID); + if (ret == 0) { + _E("no message : [%s:%s]", err.name, err.message); + dbus_error_free(&err); + ret_val = -EBADMSG; + } + _I("%s %s", device_change_types[index].name, device_change_types[index].status); + dbus_message_unref(msg); + dbus_error_free(&err); + sleep(TEST_WAIT_TIME_INTERVAL); + return ret_val; +} + +static void unit(char *unit, char *status) +{ + int index; + + for (index = 0; index < ARRAY_SIZE(device_change_types); index++) { + if (strcmp(unit, device_change_types[index].name) != 0 || + strcmp(status, device_change_types[index].status) != 0) + continue; + test(index); + } +} + +static void tvout_init(void *data) +{ + int index; + + _I("start test"); + for (index = 0; index < ARRAY_SIZE(device_change_types); index++) + test(index); +} + +static void tvout_exit(void *data) +{ + _I("end test"); +} + +static int tvout_unit(int argc, char **argv) +{ + int status; + + if (argv[1] == NULL) + return -EINVAL; + if (argc != 3) + return -EAGAIN; + + unit(argv[1], argv[2]); +out: + return 0; +} + +static const struct test_ops tvout_test_ops = { + .priority = TEST_PRIORITY_NORMAL, + .name = "tvout", + .init = tvout_init, + .exit = tvout_exit, + .unit = tvout_unit, +}; + +TEST_OPS_REGISTER(&tvout_test_ops) diff --git a/src/auto-test/udev.c b/src/auto-test/udev.c new file mode 100644 index 0000000..c9818e3 --- /dev/null +++ b/src/auto-test/udev.c @@ -0,0 +1,111 @@ +/* + * test + * + * Copyright (c) 2013 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 "test.h" + +static const struct device_change_type { + char *name; + char *status; +} device_change_types [] = { + {"udev", "start"}, + {"udev", "stop"}, +}; + +static int test(int index) +{ + DBusError err; + DBusMessage *msg; + int ret, ret_val; + char *param[3]; + + param[0] = UDEV; + param[1] = "1"; + param[2] = device_change_types[index].status; + + msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME, + DEVICED_PATH_SYSNOTI, DEVICED_INTERFACE_SYSNOTI, + UDEV, "sis", param); + if (!msg) { + _E("fail : %s %s %s %s", + DEVICED_BUS_NAME, DEVICED_PATH_SYSNOTI, DEVICED_INTERFACE_SYSNOTI, + UDEV); + return -EBADMSG; + } + + dbus_error_init(&err); + + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &ret_val, DBUS_TYPE_INVALID); + if (!ret) { + _E("no message : [%s:%s]", err.name, err.message); + ret_val = -EBADMSG; + } + _I("START"); + dbus_message_unref(msg); + dbus_error_free(&err); + sleep(TEST_WAIT_TIME_INTERVAL); + return ret_val; +} + +static void unit(char *unit, char *status) +{ + int index; + + for (index = 0; index < ARRAY_SIZE(device_change_types); index++) { + if (strcmp(unit, device_change_types[index].name) != 0 || + strcmp(status, device_change_types[index].status) != 0) + continue; + test(index); + } +} + +static void udev_init(void *data) +{ + int index; + + _I("start test"); + for (index = 0; index < ARRAY_SIZE(device_change_types); index++) + test(index); +} + +static void udev_exit(void *data) +{ + _I("end test"); +} + +static int udev_unit(int argc, char **argv) +{ + int status; + + if (argv[1] == NULL) + return -EINVAL; + if (argc != 3) + return -EAGAIN; + + unit(argv[1], argv[2]); +out: + return 0; +} + +static const struct test_ops udev_test_ops = { + .priority = TEST_PRIORITY_HIGH, + .name = "udev", + .init = udev_init, + .exit = udev_exit, + .unit = udev_unit, +}; + +TEST_OPS_REGISTER(&udev_test_ops) diff --git a/src/auto-test/usb.c b/src/auto-test/usb.c new file mode 100644 index 0000000..2a8a901 --- /dev/null +++ b/src/auto-test/usb.c @@ -0,0 +1,114 @@ +/* + * test + * + * Copyright (c) 2013 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 "test.h" + +static const struct device_change_type { + char *name; + char *status; +} device_change_types [] = { + {"usb", "1"}, + {"usb", "0"}, +}; + +static int test(int index) +{ + DBusError err; + DBusMessage *msg; + int ret, ret_val; + char *param[4]; + + param[0] = METHOD_SET_DEVICE; + param[1] = "2"; + param[2] = device_change_types[index].name; + param[3] = device_change_types[index].status; + + msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME, + DEVICED_PATH_SYSNOTI, + DEVICED_INTERFACE_SYSNOTI, + METHOD_SET_DEVICE, "siss", param); + if (!msg) { + _E("fail : %s %s %s %s", + DEVICED_BUS_NAME, DEVICED_PATH_SYSNOTI, DEVICED_INTERFACE_SYSNOTI, + METHOD_SET_DEVICE); + return -EBADMSG; + } + + dbus_error_init(&err); + + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &ret_val, DBUS_TYPE_INVALID); + if (ret == 0) { + _E("no message : [%s:%s]", err.name, err.message); + dbus_error_free(&err); + ret_val = -EBADMSG; + } + _I("%s %s", device_change_types[index].name, device_change_types[index].status); + dbus_message_unref(msg); + dbus_error_free(&err); + sleep(TEST_WAIT_TIME_INTERVAL); + return ret_val; +} + +static void unit(char *unit, char *status) +{ + int index; + + for (index = 0; index < ARRAY_SIZE(device_change_types); index++) { + if (strcmp(unit, device_change_types[index].name) != 0 || + strcmp(status, device_change_types[index].status) != 0) + continue; + test(index); + } +} + +static void usb_init(void *data) +{ + int index; + + _I("start test"); + for (index = 0; index < ARRAY_SIZE(device_change_types); index++) + test(index); +} + +static void usb_exit(void *data) +{ + _I("end test"); +} + +static int usb_unit(int argc, char **argv) +{ + int status; + + if (argv[1] == NULL) + return -EINVAL; + if (argc != 3) + return -EAGAIN; + + unit(argv[1], argv[2]); +out: + return 0; +} + +static const struct test_ops usb_test_ops = { + .priority = TEST_PRIORITY_NORMAL, + .name = "usb", + .init = usb_init, + .exit = usb_exit, + .unit = usb_unit, +}; + +TEST_OPS_REGISTER(&usb_test_ops) diff --git a/src/battery/battery-micro-emul.conf b/src/battery/battery-micro-emul.conf new file mode 100644 index 0000000..3a3083a --- /dev/null +++ b/src/battery/battery-micro-emul.conf @@ -0,0 +1,7 @@ +[LOWBAT] +#low battery level +Normal=100 +Warning=15 +Critical=5 +PowerOff=3 +RealOff=0 diff --git a/src/battery/battery-micro.conf b/src/battery/battery-micro.conf new file mode 100644 index 0000000..3a3083a --- /dev/null +++ b/src/battery/battery-micro.conf @@ -0,0 +1,7 @@ +[LOWBAT] +#low battery level +Normal=100 +Warning=15 +Critical=5 +PowerOff=3 +RealOff=0 diff --git a/src/battery/battery-time.c b/src/battery/battery-time.c new file mode 100644 index 0000000..3759949 --- /dev/null +++ b/src/battery/battery-time.c @@ -0,0 +1,473 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include +#include +#include +#include +#include +#include + +#include "core/common.h" +#include "core/devices.h" +#include "core/log.h" + +#define CHARGING_STATE(x) ((x) & CHRGR_FLAG) +#define FULL_CAPACITY_RAW (10000) +#define FULL_CAPACITY (100) +#define BATTERY_FULL_THRESHOLD (98) +#define MAX_COUNT_UNCHARGING (10) +#define MAX_COUNT_CHARGING (10) +#define PRINT_ALL_BATT_NODE(x) /*print_all_batt_node(x)*/ +#define POLLING_TIME (30) /* seconds */ + +int (*get_battery_capacity_cb)(void); + +enum state_b { + B_UNCHARGING = 0, + B_CHARGING = 1, + B_END = 2 +}; + +typedef struct _batt_node { + time_t clock; + int capacity; + struct _batt_node *preview; + struct _batt_node *next; +} Batt_node; + +enum state_a { + A_TIMETOEMPTY = 0, + A_TIMETOFULL = 1, + A_END = 2 +}; + +static Ecore_Timer *timeout_id = NULL; + +static Batt_node *batt_head[B_END]; +static Batt_node *batt_tail[B_END]; +static int MAX_VALUE_COUNT[B_END] = {MAX_COUNT_UNCHARGING, MAX_COUNT_CHARGING}; +static double avg_factor[B_END] = {-1.0, -1.0}; +static int full_capacity = 0; +static int old_capacity = 0; +static int charging_state = 0; +static int multiply_value[B_END] = {-1, 1}; +extern int system_wakeup_flag; + +static int get_battery_capacity(void) +{ + int value = 0; + int ret = -1; + + ret = device_get_property(DEVICE_TYPE_POWER, + PROP_POWER_CAPACITY, &value); + + if (ret < 0) + return ret; + + if (value < 0) + return 0; + + return value; +} + +static int get_battery_capacity_raw(void) +{ + int value = 0; + int ret = -1; + + ret = device_get_property(DEVICE_TYPE_POWER, + PROP_POWER_CAPACITY_RAW, &value); + + if (ret < 0) + return ret; + + if (value < 0) + return 0; + + return value; +} + +static int get_battery_charge_full(void) +{ + int value = 0; + int ret = -1; + + ret = device_get_property(DEVICE_TYPE_POWER, + PROP_POWER_CHARGE_FULL, &value); + + if (ret < 0) + return ret; + + if (value < 0) + return 0; + + return value; +} + +static void print_all_batt_node(enum state_b b_index) +{ + Batt_node *node = NULL; + int cnt = 0; + + _I("print_all_batt_node [%d]", b_index); + + if(b_index < 0 || b_index >= B_END) + return; + + if(batt_head[b_index] == NULL) + return; + + node = batt_head[b_index]; + while(node != NULL) { + cnt++; + _I("[%d] capacity %5d, time %s", cnt, node->capacity, + ctime(&node->clock)); + node = node->next; + } +} + +static int check_value_validity(enum state_b b_index,time_t clock,int capacity) +{ + time_t old_clock = 0; + int old_capacity = 0; + int capadiff = 0; + + if(b_index < 0 || b_index >= B_END) + return -1; + + if(batt_head[b_index] == NULL) + return 0; + + old_capacity = batt_head[b_index]->capacity; + + if(system_wakeup_flag == true) { + _E("check value validity : invalid cuz system suspend!"); + system_wakeup_flag = false; + return -1; + } + /* capacity */ + capadiff = capacity - old_capacity; + if((capadiff * multiply_value[b_index]) <= 0) { + _E("check value validity : capadiff(%d) wrong!", capadiff); + return -1; + } + return 0; +} + +static int add_batt_node(enum state_b b_index, time_t clock, int capacity) +{ + Batt_node *node = NULL; + + PRINT_ALL_BATT_NODE(b_index); + + if(b_index < 0 || b_index >= B_END) + return -1; + + node = (Batt_node *) malloc(sizeof(Batt_node)); + if(node == NULL) { + _E("Not enough memory, add battery node fail!"); + return -1; + } + + node->clock = clock; + node->capacity = capacity; + + if(batt_head[b_index] == NULL && batt_tail[b_index] == NULL) { + batt_head[b_index] = batt_tail[b_index] = node; + node->preview = NULL; + node->next = NULL; + } else { + node->next = batt_head[b_index]; + node->preview = NULL; + batt_head[b_index]->preview = node; + batt_head[b_index] = node; + } + PRINT_ALL_BATT_NODE(b_index); + return 0; +} + +static int reap_batt_node(enum state_b b_index, int max_count) +{ + Batt_node *node = NULL; + Batt_node *tmp = NULL; + int cnt = 0; + + PRINT_ALL_BATT_NODE(b_index); + + if(b_index < 0 || b_index >= B_END) + return -1; + + if(max_count <= 0) + return -1; + + node = batt_head[b_index]; + + while(node != NULL) { + if(cnt >= max_count) break; + cnt++; + node = node->next; + } + + if(node != NULL && node != batt_tail[b_index]) { + batt_tail[b_index] = node; + node = node->next; + batt_tail[b_index]->next = NULL; + while(node != NULL) { + tmp = node; + node = node->next; + free(tmp); + } + } + PRINT_ALL_BATT_NODE(b_index); + return 0; +} + +static int del_all_batt_node(enum state_b b_index) +{ + Batt_node *node = NULL; + + PRINT_ALL_BATT_NODE(b_index); + + if(b_index < 0 || b_index >= B_END) + return -1; + if(batt_head[b_index] == NULL) + return 0; + + while(batt_head[b_index] != NULL) { + node = batt_head[b_index]; + batt_head[b_index] = batt_head[b_index]->next; + free(node); + } + batt_tail[b_index] = NULL; + PRINT_ALL_BATT_NODE(b_index); + return 0; +} + +static float update_factor(enum state_b b_index) +{ + Batt_node *node = NULL; + double factor = 0.0; + double total_factor = 0.0; + int cnt = 0; + double timediff = 0.0; + double capadiff = 0.0; + + if(b_index < 0 || b_index >= B_END) + return 0; + + if(batt_head[b_index] == NULL || batt_head[b_index]->next == NULL) + return avg_factor[b_index]; + + node = batt_head[b_index]; + while(1) { + timediff = difftime(node->clock, node->next->clock); + capadiff = node->capacity - node->next->capacity; + if(capadiff < 0) + capadiff*=(-1); + if(capadiff != 0) + factor = timediff / capadiff; + total_factor += factor; + + node = node->next; + cnt++; + + /*_I("[%d] timediff(%lf) / capadiff(%lf) = factor(%lf)", + cnt, timediff, capadiff, factor);*/ + factor = 0.0; + + if(node == NULL || node->next == NULL) + break; + if(cnt >= MAX_VALUE_COUNT[b_index]) { + reap_batt_node(b_index, MAX_VALUE_COUNT[b_index]); + break; + } + } + total_factor /= (float)cnt; + + return total_factor; +} + +static void update_time(enum state_a a_index, int seconds) +{ + int clock; + + if(a_index < 0 || a_index >= A_END) + return; + + if(seconds <= 0) + return; + + switch(a_index) { + case A_TIMETOFULL: + vconf_set_int(VCONFKEY_PM_BATTERY_TIMETOFULL, + seconds); + break; + case A_TIMETOEMPTY: + vconf_set_int(VCONFKEY_PM_BATTERY_TIMETOEMPTY, + seconds); + break; + } +} + +static int battinfo_calculation(void) +{ + time_t clock; + int capacity = 0; + int estimated_time = 0; + int tmp = 0; + + capacity = get_battery_capacity_cb(); + + if(capacity <= 0) + return -1; + if(capacity == old_capacity) + return 0; + + old_capacity = capacity; + + if(get_charging_status(&tmp) == 0) + charging_state = (tmp > 0 ? EINA_TRUE : EINA_FALSE); + + clock = time(NULL); + if(charging_state == EINA_TRUE) { + del_all_batt_node(B_UNCHARGING); + if((capacity * 100 / full_capacity) + >= BATTERY_FULL_THRESHOLD) { + if (get_battery_charge_full()) { + del_all_batt_node(B_CHARGING); + _I("battery fully charged!"); + update_time(A_TIMETOFULL, 0); + return 0; + } + } + if(batt_head[B_CHARGING] == NULL) { + add_batt_node(B_CHARGING, clock, capacity); + } else { + add_batt_node(B_CHARGING, clock, capacity); + avg_factor[B_CHARGING] = update_factor(B_CHARGING); + } + estimated_time = (float)(full_capacity - capacity) * + avg_factor[B_CHARGING]; + update_time(A_TIMETOFULL, estimated_time); + } else { + del_all_batt_node(B_CHARGING); + if(system_wakeup_flag == true) { + del_all_batt_node(B_UNCHARGING); + system_wakeup_flag = false; + } + if(batt_head[B_UNCHARGING] == NULL) { + add_batt_node(B_UNCHARGING, clock, capacity); + } else { + add_batt_node(B_UNCHARGING, clock, capacity); + avg_factor[B_UNCHARGING] = update_factor(B_UNCHARGING); + } + estimated_time = (float)capacity * avg_factor[B_UNCHARGING]; + update_time(A_TIMETOEMPTY, estimated_time); + } + return 0; +} + +static Eina_Bool battinfo_cb(void *data) +{ + battinfo_calculation(); + return ECORE_CALLBACK_RENEW; +} + +static int init_battery_func(void) +{ + int ret = -1; + + ret = get_battery_capacity_raw(); + if(ret >= 0) { + get_battery_capacity_cb = get_battery_capacity_raw; + full_capacity = FULL_CAPACITY_RAW; + _I("init_battery_func : full capacity(%d)", full_capacity); + return 0; + } + + ret = get_battery_capacity(); + if(ret >= 0) { + get_battery_capacity_cb = get_battery_capacity; + full_capacity = FULL_CAPACITY; + _I("init_battery_func : full capacity(%d)", full_capacity); + return 0; + } + + _E("init_battery_func : fail to get battery info!"); + return -1; +} + +static int start_battinfo_gathering(int timeout) +{ + int ret; + + _I("Start battery gathering!"); + + if(timeout <= 0) { + _E("invalid timeout value [%d]!", timeout); + return -1; + } + if(init_battery_func() != 0) + return -1; + + old_capacity = 0; + battinfo_calculation(); + + if(timeout > 0) { + /* Using g_timer for gathering battery info */ + timeout_id = ecore_timer_add(timeout, + (Ecore_Task_Cb)battinfo_cb, NULL); + } + + return 0; +} + +static void end_battinfo_gathering(void) +{ + _I("End battery gathering!"); + + if (timeout_id) { + ecore_timer_del(timeout_id); + timeout_id = NULL; + } + + del_all_batt_node(B_UNCHARGING); + del_all_batt_node(B_CHARGING); +} + +static void battery_init(void *data) +{ + start_battinfo_gathering(POLLING_TIME); +} + +static void battery_exit(void *data) +{ + end_battinfo_gathering(); +} + +static const struct device_ops battery_time_device_ops = { + .priority = DEVICE_PRIORITY_NORMAL, + .name = "battery-time", + .init = battery_init, + .exit = battery_exit, +}; + +DEVICE_OPS_REGISTER(&battery_time_device_ops) + diff --git a/src/battery/battery.c b/src/battery/battery.c new file mode 100644 index 0000000..a48ddfa --- /dev/null +++ b/src/battery/battery.c @@ -0,0 +1,170 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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. + */ + +#define USE_LOGD 1 + +#include +#include +#include +#include "core/log.h" +#include "core/devices.h" +#include "core/udev.h" +#include "device-node.h" +#include "core/device-handler.h" +#include "core/device-notifier.h" +#include "core/edbus-handler.h" + +/* + * get_capacity - get battery capacity value + * using device_get_property + */ +static int get_capacity(void) +{ + int val, ret; + + ret = device_get_property(DEVICE_TYPE_POWER, PROP_POWER_CAPACITY, &val); + if (ret < 0) { + _E("fail to get battery capacity value"); + val = ret; + } + return val; +} + +static int update_battery(void *data) +{ + static int capacity = -1; + static int charge_now = -1; + + if (battery.capacity != capacity) { + _D("capacity is changed %d -> %d", capacity, battery.capacity); + capacity = battery.capacity; + } + + if (battery.charge_now != charge_now) { + _D("chaging status is changed %d -> %d", charge_now, battery.charge_now); + charge_now = battery.charge_now; + } + return 0; +} + +static DBusMessage *edbus_get_percent(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int ret; + + ret = battery.capacity; + + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *edbus_get_percent_raw(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int ret, val; + + ret = device_get_property(DEVICE_TYPE_POWER, PROP_POWER_CAPACITY_RAW, &val); + if (ret < 0) + goto exit; + + if (val > 10000) + val = 10000; + + ret = val; + +exit: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *edbus_is_full(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int ret; + + ret = battery.charge_full; + + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *edbus_get_health(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int ret; + + ret = battery.health; + + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static const struct edbus_method edbus_methods[] = { + { "GetPercent", NULL, "i", edbus_get_percent }, + { "GetPercentRaw", NULL, "i", edbus_get_percent_raw }, + { "IsFull", NULL, "i", edbus_is_full }, + { "GetHealth", NULL, "i", edbus_get_health }, + /* Add methods here */ +}; + +/* battery ops init funcion */ +static void battery_init(void *data) +{ + int ret; + + /* init dbus interface */ + ret = register_edbus_method(DEVICED_PATH_BATTERY, + edbus_methods, ARRAY_SIZE(edbus_methods)); + if (ret < 0) + _E("fail to init edbus method(%d)", ret); + + /* get initial battery capacity */ + battery.capacity = get_capacity(); + battery.charge_now = POWER_SUPPLY_STATUS_UNKNOWN; + + /* register notifier */ + register_notifier(DEVICE_NOTIFIER_POWER_SUPPLY, update_battery); +} + +/* battery ops exit funcion */ +static void battery_exit(void *data) +{ + /* unregister notifier */ + unregister_notifier(DEVICE_NOTIFIER_POWER_SUPPLY, update_battery); +} + +static const struct device_ops battery_device_ops = { + .priority = DEVICE_PRIORITY_NORMAL, + .name = "battery", + .init = battery_init, + .exit = battery_exit, +}; + +DEVICE_OPS_REGISTER(&battery_device_ops) diff --git a/src/battery/battery.conf b/src/battery/battery.conf new file mode 100644 index 0000000..48402cc --- /dev/null +++ b/src/battery/battery.conf @@ -0,0 +1,7 @@ +[LOWBAT] +#low battery level +Normal=100 +Warning=15 +Critical=5 +PowerOff=1 +RealOff=0 diff --git a/src/battery/battery.h b/src/battery/battery.h new file mode 100644 index 0000000..b1828bd --- /dev/null +++ b/src/battery/battery.h @@ -0,0 +1,43 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 __BATTERY_H__ +#define __BATTERY_H__ + +#define BATTERY_LEVEL_CHECK_FULL 95 +#define BATTERY_LEVEL_CHECK_HIGH 15 +#define BATTERY_LEVEL_CHECK_LOW 5 +#define BATTERY_LEVEL_CHECK_CRITICAL 1 + +#define LOWBAT_OPT_WARNING 1 +#define LOWBAT_OPT_POWEROFF 2 +#define LOWBAT_OPT_CHARGEERR 3 +#define LOWBAT_OPT_CHECK 4 + +struct battery_config_info { + int normal; + int warning; + int critical; + int poweroff; + int realoff; +}; + +int battery_charge_err_low_act(void *data); +int battery_charge_err_high_act(void *data); +#endif /* __BATTERY_H__ */ diff --git a/src/battery/config.c b/src/battery/config.c new file mode 100644 index 0000000..4dd42c1 --- /dev/null +++ b/src/battery/config.c @@ -0,0 +1,73 @@ +/* + * deviced + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include +#include +#include +#include +#include +#include +#include + +#include "core/log.h" +#include "core/common.h" +#include "core/config-parser.h" +#include "battery.h" +#include "config.h" + +#define BAT_CONF_FILE "/etc/deviced/battery.conf" + +static int load_config(struct parse_result *result, void *user_data) +{ + struct battery_config_info *info = user_data; + char *name; + char *value; + + _D("%s,%s,%s", result->section, result->name, result->value); + + if (!info) + return -EINVAL; + + if (!MATCH(result->section, "LOWBAT")) + return -EINVAL; + + name = result->name; + value = result->value; + if (MATCH(name, "Normal")) + info->normal = atoi(value); + else if (MATCH(name, "Warning")) + info->warning = atoi(value); + else if (MATCH(name, "Critical")) + info->critical = atoi(value); + else if (MATCH(name, "PowerOff")) + info->poweroff = atoi(value); + else if (MATCH(name, "RealOff")) + info->realoff = atoi(value); + + return 0; +} + +void battery_config_load(struct battery_config_info *info) +{ + int ret; + + ret = config_parse(BAT_CONF_FILE, load_config, info); + if (ret < 0) + _E("Failed to load %s, %d Use default value!", BAT_CONF_FILE, ret); +} diff --git a/src/battery/config.h b/src/battery/config.h new file mode 100644 index 0000000..5f68716 --- /dev/null +++ b/src/battery/config.h @@ -0,0 +1,24 @@ +/* + * deviced + * + * Copyright (c) 2014 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 __BATTERY_CONFIG_H__ +#define __BATTERY_CONFIG_H__ + +void battery_config_load(struct battery_config_info *info); +#endif /* __BATTERY_CONFIG_H__ */ diff --git a/src/battery/lowbat-handler.c b/src/battery/lowbat-handler.c new file mode 100644 index 0000000..3d82613 --- /dev/null +++ b/src/battery/lowbat-handler.c @@ -0,0 +1,627 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 "battery.h" +#include "config.h" +#include "core/log.h" +#include "core/launch.h" +#include "core/noti.h" +#include "core/queue.h" +#include "core/data.h" +#include "core/devices.h" +#include "core/device-handler.h" +#include "core/device-notifier.h" +#include "core/common.h" +#include "core/list.h" +#include "device-node.h" +#include "display/setting.h" +#include "display/poll.h" +#include "core/edbus-handler.h" +#include "core/power-supply.h" + +#define PREDEF_LOWBAT "lowbat" +#define PREDEF_LOWBAT_CHANGE_FREQ "lowbat_change_freq" + +#define CHARGE_POWERSAVE_FREQ_ACT "charge_powersave_freq_act" +#define CHARGE_RELEASE_FREQ_ACT "charge_release_freq_act" + + +#define BATTERY_CHARGING 65535 +#define BATTERY_UNKNOWN -1 +#define BATTERY_FULL 100 + +#define WARNING_LOW_BAT_ACT "warning_low_bat_act" +#define CRITICAL_LOW_BAT_ACT "critical_low_bat_act" +#define POWER_OFF_BAT_ACT "power_off_bat_act" +#define CHARGE_BAT_ACT "charge_bat_act" +#define CHARGE_CHECK_ACT "charge_check_act" +#define CHARGE_ERROR_ACT "charge_error_act" +#define CHARGE_ERROR_LOW_ACT "charge_error_low_act" +#define CHARGE_ERROR_HIGH_ACT "charge_error_high_act" +#define CHARGE_ERROR_OVP_ACT "charge_error_ovp_act" +#define WAITING_INTERVAL 10 + +#define LOWBAT_CPU_CTRL_ID "id6" +#define LOWBAT_CPU_FREQ_RATE (0.7) + +#define LOWBAT_POPUP_NAME "lowbat-syspopup" +#define LOWBAT_EXEC_PATH PREFIX"/bin/lowbatt-popup" + +struct popup_data { + char *name; + char *key; + char *value; +}; + +struct lowbat_process_entry { + int old; + int now; + int (*func) (void *data); +}; + +static int cur_bat_state = BATTERY_UNKNOWN; +static int cur_bat_capacity = -1; + +static int lowbat_popup_option = 0; +static int lowbat_freq = -1; +static struct battery_config_info battery_info; + +static dd_list *lpe = NULL; +static int scenario_count = 0; + +static int lowbat_initialized(void *data) +{ + static int status; + + if (!data) + return status; + + status = *(int *)data; + return status; +} + +int lowbat_scenario(int old, int now, void *data) +{ + dd_list *n; + struct lowbat_process_entry *scenario; + int found = 0; + + DD_LIST_FOREACH(lpe, n, scenario) { + if (old != scenario->old || now != scenario->now) + continue; + if (!scenario->func) + continue; + scenario->func(data); + found = 1; + break; + } + return found; +} + +int lowbat_add_scenario(int old, int now, int (*func)(void *data)) +{ + struct lowbat_process_entry *scenario; + + _I("%d %d, %x", old, now, func); + + if (!func) { + _E("invalid func address!"); + return -EINVAL; + } + + scenario = malloc(sizeof(struct lowbat_process_entry)); + if (!scenario) { + _E("Fail to malloc for notifier!"); + return -ENOMEM; + } + + scenario->old = old; + scenario->now = now; + scenario->func = func; + + DD_LIST_APPEND(lpe, scenario); + scenario_count++; + return 0; +} + +static void print_lowbat_state(unsigned int bat_percent) +{ +#if 0 + int i; + for (i = 0; i < BAT_MON_SAMPLES; i++) + _D("\t%d", recent_bat_percent[i]); +#endif +} + +int battery_check_act(void *data) +{ + notify_action(PREDEF_LOWBAT, 1, CHARGE_CHECK_ACT); + return 0; +} + +int battery_warning_low_act(void *data) +{ + notify_action(PREDEF_LOWBAT, 1, WARNING_LOW_BAT_ACT); + return 0; +} + +int battery_critical_low_act(void *data) +{ + notify_action(PREDEF_LOWBAT, 1, CRITICAL_LOW_BAT_ACT); + return 0; +} + +int battery_power_off_act(void *data) +{ + vconf_set_int(VCONFKEY_SYSMAN_POWER_OFF_STATUS, VCONFKEY_SYSMAN_POWER_OFF_DIRECT); + return 0; +} + +int battery_charge_err_act(void *data) +{ + notify_action(PREDEF_LOWBAT, 1, CHARGE_ERROR_ACT); + return 0; +} + +int battery_charge_err_low_act(void *data) +{ + notify_action(PREDEF_LOWBAT, 1, CHARGE_ERROR_LOW_ACT); + return 0; +} + +int battery_charge_err_high_act(void *data) +{ + notify_action(PREDEF_LOWBAT, 1, CHARGE_ERROR_HIGH_ACT); + return 0; +} + +int battery_charge_err_ovp_act(void *data) +{ + notify_action(PREDEF_LOWBAT, 1, CHARGE_ERROR_OVP_ACT); + return 0; +} + +static int battery_charge_act(void *data) +{ +#ifdef NOUSE + int val; + char argstr[128]; + + /* instead of adding action to the queue, execute it right here */ + if (device_get_property(DEVTYPE_JACK, JACK_PROP_TA_ONLINE, &val) == 0 + && val == 1) { + snprintf(argstr, 128, "-t 4"); + launch_after_kill_if_exist(LOWBAT_EXEC_PATH, argstr); + } +#endif + return 0; +} + +static void lowbat_scenario_init(void) +{ + lowbat_add_scenario(battery_info.normal, battery_info.warning, battery_warning_low_act); + lowbat_add_scenario(battery_info.warning, battery_info.critical, battery_warning_low_act); + lowbat_add_scenario(battery_info.critical, battery_info.poweroff, battery_critical_low_act); + lowbat_add_scenario(battery_info.poweroff, battery_info.realoff, battery_power_off_act); + lowbat_add_scenario(battery_info.normal, battery_info.critical, battery_warning_low_act); + lowbat_add_scenario(battery_info.warning, battery_info.poweroff, battery_critical_low_act); + lowbat_add_scenario(battery_info.critical, battery_info.realoff, battery_power_off_act); + lowbat_add_scenario(battery_info.normal, battery_info.poweroff, battery_critical_low_act); + lowbat_add_scenario(battery_info.warning, battery_info.realoff, battery_power_off_act); + lowbat_add_scenario(battery_info.normal, battery_info.realoff, battery_power_off_act); + lowbat_add_scenario(battery_info.realoff, battery_info.realoff, battery_power_off_act); + lowbat_add_scenario(battery_info.realoff, battery_info.normal, battery_check_act); + lowbat_add_scenario(battery_info.realoff, battery_info.warning, battery_check_act); + lowbat_add_scenario(battery_info.realoff, battery_info.critical, battery_check_act); + lowbat_add_scenario(battery_info.realoff, battery_info.poweroff, battery_check_act); +} + +static void change_lowbat_level(int bat_percent) +{ + int prev, now; + + if (cur_bat_capacity == bat_percent) + return; + + if (vconf_get_int(VCONFKEY_SYSMAN_BATTERY_LEVEL_STATUS, &prev) < 0) { + _E("vconf_get_int() failed"); + return; + } + + + if (bat_percent > BATTERY_LEVEL_CHECK_FULL) { + now = VCONFKEY_SYSMAN_BAT_LEVEL_FULL; + } else if (bat_percent > BATTERY_LEVEL_CHECK_HIGH) { + now = VCONFKEY_SYSMAN_BAT_LEVEL_HIGH; + } else if (bat_percent > BATTERY_LEVEL_CHECK_LOW) { + now = VCONFKEY_SYSMAN_BAT_LEVEL_LOW; + } else if (bat_percent > BATTERY_LEVEL_CHECK_CRITICAL) { + now = VCONFKEY_SYSMAN_BAT_LEVEL_CRITICAL; + } else { + now = VCONFKEY_SYSMAN_BAT_LEVEL_EMPTY; + } + + if (prev != now) + vconf_set_int(VCONFKEY_SYSMAN_BATTERY_LEVEL_STATUS, now); +} + +static int lowbat_process(int bat_percent, void *ad) +{ + int new_bat_capacity; + int new_bat_state; + int vconf_state = -1; + int i, ret = 0; + int status = -1; + bool low_bat = false; + bool full_bat = false; + int extreme = 0; + int result = 0; + + new_bat_capacity = bat_percent; + if (new_bat_capacity < 0) + return -EINVAL; + change_lowbat_level(new_bat_capacity); + pm_lock_internal(INTERNAL_LOCK_BATTERY, LCD_OFF, STAY_CUR_STATE, 0); + + if (new_bat_capacity != cur_bat_capacity) { + _D("[BAT_MON] cur = %d new = %d", cur_bat_capacity, new_bat_capacity); + if (vconf_set_int(VCONFKEY_SYSMAN_BATTERY_CAPACITY, new_bat_capacity) == 0) + cur_bat_capacity = new_bat_capacity; + } + + if (vconf_get_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, &vconf_state) < 0) { + _E("vconf_get_int() failed"); + result = -EIO; + goto exit; + } + + if (new_bat_capacity <= battery_info.realoff) { + if (battery.charge_now) { + new_bat_state = battery_info.poweroff; + if (vconf_state != VCONFKEY_SYSMAN_BAT_POWER_OFF) + status = VCONFKEY_SYSMAN_BAT_POWER_OFF; + } else { + new_bat_state = battery_info.realoff; + if (vconf_state != VCONFKEY_SYSMAN_BAT_REAL_POWER_OFF) + status = VCONFKEY_SYSMAN_BAT_REAL_POWER_OFF; + } + } else if (new_bat_capacity <= battery_info.poweroff) { + new_bat_state = battery_info.poweroff; + if (vconf_state != VCONFKEY_SYSMAN_BAT_POWER_OFF) + status = VCONFKEY_SYSMAN_BAT_POWER_OFF; + } else if (new_bat_capacity <= battery_info.critical) { + new_bat_state = battery_info.critical; + if (vconf_state != VCONFKEY_SYSMAN_BAT_CRITICAL_LOW) + status = VCONFKEY_SYSMAN_BAT_CRITICAL_LOW; + } else if (new_bat_capacity <= battery_info.warning) { + new_bat_state = battery_info.warning; + if (vconf_state != VCONFKEY_SYSMAN_BAT_WARNING_LOW) + status = VCONFKEY_SYSMAN_BAT_WARNING_LOW; + } else { + new_bat_state = battery_info.normal; + if (new_bat_capacity == BATTERY_FULL) { + if (battery.charge_full) { + if (vconf_state != VCONFKEY_SYSMAN_BAT_FULL) + status = VCONFKEY_SYSMAN_BAT_FULL; + full_bat = true; + } else { + if (vconf_state != VCONFKEY_SYSMAN_BAT_NORMAL) + status = VCONFKEY_SYSMAN_BAT_NORMAL; + } + } else { + if (vconf_state != VCONFKEY_SYSMAN_BAT_NORMAL) + status = VCONFKEY_SYSMAN_BAT_NORMAL; + } + } + + + if (status != -1) { + ret = vconf_set_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, status); + power_supply_broadcast(CHARGE_LEVEL_SIGNAL, status); + if (update_pm_setting) + update_pm_setting(SETTING_LOW_BATT, status); + } + + if (ret < 0) { + result = -EIO; + goto exit; + } + + if (vconf_get_int(VCONFKEY_PM_KEY_IGNORE, &extreme) == 0 && extreme == TRUE && + (status > VCONFKEY_SYSMAN_BAT_POWER_OFF && status <= VCONFKEY_SYSMAN_BAT_FULL)) + if (vconf_set_int(VCONFKEY_PM_KEY_IGNORE, FALSE) == 0) + _I("release key ignore"); + + if (new_bat_capacity <= battery_info.warning) + low_bat = true; + + device_notify(DEVICE_NOTIFIER_LOWBAT, (void*)low_bat); + + if (cur_bat_state == new_bat_state && new_bat_state > battery_info.realoff) + goto exit; + + if (cur_bat_state == BATTERY_UNKNOWN) + cur_bat_state = battery_info.normal; + result = lowbat_scenario(cur_bat_state, new_bat_state, NULL); + if (result) + _I("cur_bat_state %d, new_bat_state %d", cur_bat_state, new_bat_state); + cur_bat_state = new_bat_state; +exit: + pm_unlock_internal(INTERNAL_LOCK_BATTERY, LCD_OFF, PM_SLEEP_MARGIN); + + return result; +} + +static int lowbat_read() +{ + int bat_percent, r; + + r = device_get_property(DEVICE_TYPE_POWER, PROP_POWER_CAPACITY, &bat_percent); + if (r < 0) + return r; + + return bat_percent; +} + +static void change_lowbat_cpu_freq(int bat_percent) +{ + static int init_cpu_freq = 0; + static int power_save = 0; + if (cur_bat_capacity == bat_percent) + return; + + if (bat_percent > battery_info.poweroff && init_cpu_freq == 0) { + init_cpu_freq = 1; + notify_action(PREDEF_LOWBAT_CHANGE_FREQ, 1, CHARGE_RELEASE_FREQ_ACT); + return; + } + + if (bat_percent <= battery_info.poweroff && power_save == 0) { + power_save = 1; + notify_action(PREDEF_LOWBAT_CHANGE_FREQ, 1, CHARGE_POWERSAVE_FREQ_ACT); + } else if (power_save == 1) { + power_save = 0; + notify_action(PREDEF_LOWBAT_CHANGE_FREQ, 1, CHARGE_RELEASE_FREQ_ACT); + } +} + +static int check_lowbat_percent(int *pct) +{ + int bat_percent; + + bat_percent = lowbat_read(); + if (bat_percent < 0) { + _E("[BATMON] Cannot read battery gage. stop read fuel gage"); + return -ENODEV; + } + if (bat_percent > 100) + bat_percent = 100; + change_lowbat_level(bat_percent); + change_lowbat_cpu_freq(bat_percent); + *pct = bat_percent; + return 0; +} + +void lowbat_monitor(void *data) +{ + int bat_percent, r; + + r = lowbat_initialized(NULL); + if (!r) + return; + + if (data == NULL) { + r = check_lowbat_percent(&bat_percent); + if (r < 0) + return; + } else + bat_percent = *(int *)data; + print_lowbat_state(bat_percent); + lowbat_process(bat_percent, NULL); +} + +/* for debugging (request by kernel) */ +static int check_battery() +{ + int r; + int ret = -1; + + if (device_get_property(DEVICE_TYPE_POWER, PROP_POWER_PRESENT, &ret) < 0) { + _E("FAIL: device_get_property(): [BATMON] battery check : %d", ret); + } + _D("[BATMON] battery check : %d", ret); + + return ret; +} + +static int booting_done(void *data) +{ + static int done = 0; + + if (data == NULL) + goto out; + done = (int)data; + if (!done) + goto out; + _I("booting done"); +out: + return done; +} + +int lowbat_action(int argc, char **argv) +{ + int ret, state=0; + char argstr[128]; + char* option = NULL; + char *value; + static int launched_poweroff = 0; + pid_t pid; + struct popup_data *params; + static const struct device_ops *apps = NULL; + + if (argc < 1) + return -1; + + if (strcmp(argv[0], POWER_OFF_BAT_ACT)) + launched_poweroff = 0; + + if (!strcmp(argv[0], CRITICAL_LOW_BAT_ACT)) { + value = "extreme"; + lowbat_popup_option = LOWBAT_OPT_CHECK; + } else if (!strcmp(argv[0], WARNING_LOW_BAT_ACT)) { + if (is_factory_mode() == 1) + return 0; + value = "warning"; + lowbat_popup_option = LOWBAT_OPT_WARNING; + } else if (!strcmp(argv[0], POWER_OFF_BAT_ACT)) { + value = "poweroff"; + lowbat_popup_option = LOWBAT_OPT_POWEROFF; + } else if (!strcmp(argv[0], CHARGE_ERROR_ACT)) { + value = "chargeerr"; + lowbat_popup_option = LOWBAT_OPT_CHARGEERR; + } else if (!strcmp(argv[0], CHARGE_ERROR_LOW_ACT)) { + value = "chargeerrlow"; + lowbat_popup_option = LOWBAT_OPT_CHARGEERR; + } else if (!strcmp(argv[0], CHARGE_ERROR_HIGH_ACT)) { + value = "chargeerrhigh"; + lowbat_popup_option = LOWBAT_OPT_CHARGEERR; + } else if (!strcmp(argv[0], CHARGE_ERROR_OVP_ACT)) { + value = "chargeerrovp"; + lowbat_popup_option = LOWBAT_OPT_CHARGEERR; + } else if (!strcmp(argv[0], CHARGE_CHECK_ACT)) { + launched_poweroff = 0; + return 0; + } else + return -1; + _D("%s", value); + ret = vconf_get_int(VCONFKEY_STARTER_SEQUENCE, &state); + if (state == 1 || ret != 0 || booting_done(NULL)) { + + if (launched_poweroff == 1) { + _I("will be foreced power off"); + do_poweroff(0, NULL); + return 0; + } + + if (lowbat_popup_option == LOWBAT_OPT_POWEROFF) + launched_poweroff = 1; + + pid = predefine_get_pid(LOWBAT_EXEC_PATH); + if (pid > 0) { + _I("pre launched %s destroy", LOWBAT_EXEC_PATH); + kill(pid, SIGTERM); + } + if (apps == NULL) { + apps = find_device("apps"); + if (apps == NULL) + return 0; + } + params = malloc(sizeof(struct popup_data)); + if (params == NULL) { + _E("Malloc failed"); + return -1; + } + pm_change_internal(getpid(), LCD_NORMAL); + params->name = LOWBAT_POPUP_NAME; + params->key = POPUP_KEY_CONTENT; + params->value = strdup(value); + apps->init((void *)params); + free(params->value); + free(params); + } else { + _D("boot-animation running yet"); + } + + return 0; +} + +static int check_power_save_mode(void) +{ + int ret = 0; + int power_saving_cpu_stat = -1; + + ret = vconf_get_bool(VCONFKEY_SETAPPL_PWRSV_CUSTMODE_CPU, + &power_saving_cpu_stat); + if (ret < 0) { + _E("failed to get vconf key"); + return ret; + } + + if (power_saving_cpu_stat == 1) + ret = 1; + return ret; +} + +int change_freq_action(int argc, char **argv) +{ + int val = 0; + + if (argc < 1) + return -1; + + if (!strcmp(argv[0], CHARGE_POWERSAVE_FREQ_ACT)) + val = 1; + device_notify(DEVICE_NOTIFIER_PMQOS_LOWBAT, (void*)val); + return 0; +} + +static int lowbat_monitor_init(void *data) +{ + int status = 1; + + lowbat_initialized(&status); + unregister_notifier(DEVICE_NOTIFIER_POWER_SUPPLY, lowbat_monitor_init); + battery_config_load(&battery_info); + _I("%d %d %d %d %d", battery_info.normal, battery_info.warning, + battery_info.critical, battery_info.poweroff, battery_info.realoff); + lowbat_scenario_init(); + register_action(PREDEF_LOWBAT, lowbat_action, NULL, NULL); + register_action(PREDEF_LOWBAT_CHANGE_FREQ, change_freq_action, NULL, NULL); + lowbat_process(battery.capacity, NULL); + return 0; +} + +static void lowbat_init(void *data) +{ + register_notifier(DEVICE_NOTIFIER_BOOTING_DONE, booting_done); + register_notifier(DEVICE_NOTIFIER_POWER_SUPPLY, lowbat_monitor_init); +} + +static void lowbat_exit(void *data) +{ + int status = 0; + + lowbat_initialized(&status); + unregister_notifier(DEVICE_NOTIFIER_BOOTING_DONE, booting_done); +} + +static const struct device_ops lowbat_device_ops = { + .priority = DEVICE_PRIORITY_NORMAL, + .name = "lowbat", + .init = lowbat_init, + .exit = lowbat_exit, +}; + +DEVICE_OPS_REGISTER(&lowbat_device_ops) diff --git a/src/board/board-info.c b/src/board/board-info.c new file mode 100644 index 0000000..32b53f6 --- /dev/null +++ b/src/board/board-info.c @@ -0,0 +1,202 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include + +#include "core/log.h" +#include "core/devices.h" +#include "core/edbus-handler.h" +#include "core/common.h" + +#define FILE_BUFF_MAX 1024 +#define NOT_INITIALIZED (-1) + +#define METHOD_GET_SERIAL "GetSerial" +#define SERIAL_PATH_NAME "/csa/imei/serialno.dat" + +#define METHOD_GET_REVISION "GetHWRev" +#define PATH_NAME "/proc/cpuinfo" +#define REVISION_NAME "Revision" +#define TOK_DELIMITER ":" +#define END_DELIMITER " \n" + +#define CONVERT_TYPE 10 +#define REVISION_SIZE 4 + +static int read_from_file(const char *path, char *buf, size_t size) +{ + int fd; + size_t count; + + if (!path) + return -1; + + fd = open(path, O_RDONLY, 0); + if (fd == -1) { + _E("Could not open '%s'", path); + return -1; + } + + count = read(fd, buf, size); + + if (count > 0) { + count = (count < size) ? count : size - 1; + while (count > 0 && buf[count - 1] == '\n') + count--; + buf[count] = '\0'; + } else { + buf[0] = '\0'; + } + + close(fd); + + return 0; +} + +static int get_revision(char *rev) +{ + char buf[FILE_BUFF_MAX]; + char *tag; + char *start, *ptr; + long rev_num; + const int radix = 16; + + if (rev == NULL) { + _E("Invalid argument !\n"); + return -1; + } + + if (read_from_file(PATH_NAME, buf, FILE_BUFF_MAX) < 0) { + _E("fail to read %s\n", PATH_NAME); + return -1; + } + + tag = strstr(buf, REVISION_NAME); + if (tag == NULL) { + _E("cannot find Hardware in %s\n", PATH_NAME); + return -1; + } + + start = strstr(tag, TOK_DELIMITER); + if (start == NULL) { + _E("cannot find Hardware in %s\n", PATH_NAME); + return -1; + } + + start ++; + ptr = strtok(start, END_DELIMITER); + ptr += strlen(ptr); + ptr -=2; + + memset(rev, 0x00, REVISION_SIZE); + rev_num = strtol(ptr, NULL, radix); + sprintf(rev, "%d", rev_num); + + return 0; +} + +static DBusMessage *dbus_revision_handler(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + char rev[FILE_BUFF_MAX]; + char *ptr; + static int ret = NOT_INITIALIZED; + + if (ret != NOT_INITIALIZED) + goto out; + ret = get_revision(rev); + if (ret == 0) + ret = strtol(rev, &ptr, CONVERT_TYPE); +out: + _D("rev : %d", ret); + + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static int get_serial(unsigned char *buf) +{ + int fd; + int r; + int ret = 0; + + fd = open(SERIAL_PATH_NAME, O_RDONLY, 0); + if (fd < 0) + return -ENOENT; + + r = read(fd, buf, FILE_BUFF_MAX); + if ((r >= 0) && (r < FILE_BUFF_MAX)) + buf[r] = '\0'; + else + ret = -EIO; + + close(fd); + return ret; +} + +static DBusMessage *dbus_serial_handler(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter, arr; + DBusMessage *reply; + static int len = 0; + static char buf[FILE_BUFF_MAX]; + static char *param = buf; + static int ret = NOT_INITIALIZED; + + if (ret == 0) + goto out; + ret = get_serial(buf); + if (ret == 0) { + len = strlen(buf); + goto out; + } + _E("fail to get serial"); +out: + _D("serial : %s %d", buf, len); + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, ¶m); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static const struct edbus_method edbus_methods[] = { + { METHOD_GET_SERIAL, NULL, "si", dbus_serial_handler }, + { METHOD_GET_REVISION, NULL, "i", dbus_revision_handler }, +}; + +static void board_init(void *data) +{ + int ret; + + ret = register_edbus_method(DEVICED_PATH_BOARD, edbus_methods, ARRAY_SIZE(edbus_methods)); + if (ret < 0) + _E("fail to init edbus method(%d)", ret); +} + +static const struct device_ops board_device_ops = { + .priority = DEVICE_PRIORITY_NORMAL, + .name = "board", + .init = board_init, +}; + +DEVICE_OPS_REGISTER(&board_device_ops) diff --git a/src/control/control.c b/src/control/control.c new file mode 100644 index 0000000..dcb21a9 --- /dev/null +++ b/src/control/control.c @@ -0,0 +1,238 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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/common.h" +#include "core/devices.h" +#include "core/edbus-handler.h" + +#define CONTROL_HANDLER_NAME "control" +#define CONTROL_GETTER_NAME "getcontrol" + +static const struct control_device { + const int id; + const char *name; +} devices[] = { + /* Add id & ops to provide start/stop control */ + { DEVICE_CONTROL_MMC, "mmc" }, + { DEVICE_CONTROL_USBCLIENT, "usbclient" }, + { DEVICE_CONTROL_RGBLED, "rgbled" }, +}; + +static int control_handler(int argc, char **argv) +{ + int i; + int pid; + int device; + bool enable; + int ret; + const struct device_ops *dev_ops; + + _I("argc : %d", argc); + for (i = 0; i < argc; ++i) + _I("[%2d] %s", i, argv[i]); + + if (argc > 5) { + _E("Invalid argument"); + errno = EINVAL; + return -1; + } + + pid = atoi(argv[0]); + device = atoi(argv[1]); + enable = atoi(argv[2]); + _I("pid : %d, device : %d, enable :%d", pid, device, enable); + + for (i = 0; i < ARRAY_SIZE(devices); i++) + if (devices[i].id == device) + break; + + if (i >= ARRAY_SIZE(devices)) + return -EINVAL; + + dev_ops = find_device(devices[i].name); + if (!dev_ops) + return -ENODEV; + + if (enable) + ret = device_start(dev_ops); + else + ret = device_stop(dev_ops); + + return ret; +} + +static int get_control_handler(int argc, char **argv) +{ + int i; + int pid; + int device; + bool enable; + int ret; + const struct device_ops *dev_ops; + + _I("argc : %d", argc); + for (i = 0; i < argc; ++i) + _I("[%2d] %s", i, argv[i]); + + if (argc > 4) { + _E("Invalid argument"); + errno = EINVAL; + return -1; + } + + pid = atoi(argv[0]); + device = atoi(argv[1]); + _I("pid : %d, device : %d", pid, device); + + for (i = 0; i < ARRAY_SIZE(devices); i++) + if (devices[i].id == device) + break; + + if (i >= ARRAY_SIZE(devices)) + return -EINVAL; + + dev_ops = find_device(devices[i].name); + if (!dev_ops) + return -ENODEV; + + return device_get_status(dev_ops); +} + + +static DBusMessage *dbus_control_handler(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusError err; + DBusMessageIter iter; + DBusMessage *reply; + pid_t pid; + int ret; + int argc; + char *type_str; + char *argv[3]; + + dbus_error_init(&err); + + if (!dbus_message_get_args(msg, &err, + DBUS_TYPE_STRING, &type_str, + DBUS_TYPE_INT32, &argc, + DBUS_TYPE_STRING, &argv[0], + DBUS_TYPE_STRING, &argv[1], + DBUS_TYPE_STRING, &argv[2], DBUS_TYPE_INVALID)) { + _E("there is no message"); + ret = -EINVAL; + goto out; + } + + if (argc < 0) { + _E("message is invalid!"); + ret = -EINVAL; + goto out; + } + + pid = get_edbus_sender_pid(msg); + if (kill(pid, 0) == -1) { + _E("%d process does not exist, dbus ignored!", pid); + ret = -ESRCH; + goto out; + } + + ret = control_handler(argc, (char **)&argv); +out: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + + return reply; +} + +static DBusMessage *dbus_get_control_handler(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusError err; + DBusMessageIter iter; + DBusMessage *reply; + pid_t pid; + int ret; + int argc; + char *type_str; + char *argv[2]; + + dbus_error_init(&err); + + if (!dbus_message_get_args(msg, &err, + DBUS_TYPE_STRING, &type_str, + DBUS_TYPE_INT32, &argc, + DBUS_TYPE_STRING, &argv[0], + DBUS_TYPE_STRING, &argv[1], DBUS_TYPE_INVALID)) { + _E("there is no message"); + ret = -EINVAL; + goto out; + } + + if (argc < 0) { + _E("message is invalid!"); + ret = -EINVAL; + goto out; + } + + pid = get_edbus_sender_pid(msg); + if (kill(pid, 0) == -1) { + _E("%d process does not exist, dbus ignored!", pid); + ret = -ESRCH; + goto out; + } + + ret = get_control_handler(argc, (char **)&argv); +out: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + + return reply; +} + +static const struct edbus_method edbus_methods[] = { + { CONTROL_HANDLER_NAME, "sisss", "i", dbus_control_handler }, + { CONTROL_GETTER_NAME , "siss", "i", dbus_get_control_handler }, +}; + +static void control_init(void *data) +{ + int ret; + + ret = register_edbus_method(DEVICED_PATH_SYSNOTI, edbus_methods, ARRAY_SIZE(edbus_methods)); + if (ret < 0) + _E("fail to init edbus method(%d)", ret); + + register_action(CONTROL_HANDLER_NAME, control_handler, NULL, NULL); +} + +static const struct device_ops control_device_ops = { + .priority = DEVICE_PRIORITY_NORMAL, + .name = "control", + .init = control_init, +}; + +DEVICE_OPS_REGISTER(&control_device_ops) diff --git a/src/core/common.c b/src/core/common.c new file mode 100644 index 0000000..7370ce0 --- /dev/null +++ b/src/core/common.c @@ -0,0 +1,337 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "log.h" + +#define PERMANENT_DIR "/tmp/permanent" +#define VIP_DIR "/tmp/vip" +#define BUFF_MAX 255 + +/** + * Opens "/proc/$pid/oom_score_adj" file for w/r; + * Return: FILE pointer or NULL + */ +FILE * open_proc_oom_score_adj_file(int pid, const char *mode) +{ + char buf[32]; + FILE *fp; + + snprintf(buf, sizeof(buf), "/proc/%d/oom_score_adj", pid); + fp = fopen(buf, mode); + return fp; +} + +int get_exec_pid(const char *execpath) +{ + DIR *dp; + struct dirent *dentry; + int pid = -1, fd; + int ret; + char buf[PATH_MAX]; + char buf2[PATH_MAX]; + + dp = opendir("/proc"); + if (!dp) { + _E("FAIL: open /proc"); + return -1; + } + + while ((dentry = readdir(dp)) != NULL) { + if (!isdigit(dentry->d_name[0])) + continue; + + pid = atoi(dentry->d_name); + + snprintf(buf, PATH_MAX, "/proc/%d/cmdline", pid); + fd = open(buf, O_RDONLY); + if (fd < 0) + continue; + ret = read(fd, buf2, PATH_MAX); + close(fd); + + if (ret < 0 || ret >= PATH_MAX) + continue; + + buf2[ret] = '\0'; + + if (!strcmp(buf2, execpath)) { + closedir(dp); + return pid; + } + } + + errno = ESRCH; + closedir(dp); + return -1; +} + +int get_cmdline_name(pid_t pid, char *cmdline, size_t cmdline_size) +{ + int fd, ret; + char buf[PATH_MAX + 1]; + char *filename; + + snprintf(buf, sizeof(buf), "/proc/%d/cmdline", pid); + fd = open(buf, O_RDONLY); + if (fd < 0) { + errno = ESRCH; + return -1; + } + + ret = read(fd, buf, PATH_MAX); + close(fd); + buf[PATH_MAX] = '\0'; + + filename = strrchr(buf, '/'); + if (filename == NULL) + filename = buf; + else + filename = filename + 1; + + if (cmdline_size < strlen(filename) + 1) { + errno = EOVERFLOW; + return -1; + } + + strncpy(cmdline, filename, cmdline_size - 1); + cmdline[cmdline_size - 1] = '\0'; + return 0; +} + +int is_vip(int pid) +{ + if (pid < 1) + return -1; + + char buf[PATH_MAX]; + + snprintf(buf, PATH_MAX, "%s/%d", VIP_DIR, pid); + + if (access(buf, R_OK) == 0) + return 1; + else + return 0; +} + +static int remove_dir_internal(int fd) +{ + DIR *dir; + struct dirent *de; + int subfd, ret = 0; + + dir = fdopendir(fd); + if (!dir) + return -1; + while ((de = readdir(dir))) { + if (de->d_type == DT_DIR) { + if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) + continue; + subfd = openat(fd, de->d_name, O_RDONLY | O_DIRECTORY); + if (subfd < 0) { + _SE("Couldn't openat %s: %s\n", de->d_name, strerror(errno)); + ret = -1; + continue; + } + if (remove_dir_internal(subfd)) { + ret = -1; + } + close(subfd); + if (unlinkat(fd, de->d_name, AT_REMOVEDIR) < 0) { + _SE("Couldn't unlinkat %s: %s\n", de->d_name, strerror(errno)); + ret = -1; + } + } else { + if (unlinkat(fd, de->d_name, 0) < 0) { + _SE("Couldn't unlinkat %s: %s\n", de->d_name, strerror(errno)); + ret = -1; + } + } + } + closedir(dir); + return ret; +} + +int remove_dir(char *path, int del_dir) +{ + int fd, ret = 0; + + if (!path) + return -1; + fd = open(path, O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_CLOEXEC | O_NOFOLLOW); + if (fd < 0) { + _SE("Couldn't opendir %s: %s\n", path, strerror(errno)); + return -errno; + } + ret = remove_dir_internal(fd); + close(fd); + + if (del_dir) { + if (rmdir(path)) { + _SE("Couldn't rmdir %s: %s\n", path, strerror(errno)); + ret = -1; + } + } + return ret; +} + +/* + * Helper function + * - Read from sysfs entry + * - Write to sysfs entry + */ +static int sys_read_buf(char *file, char *buf) +{ + int fd; + int r; + int ret = 0; + + fd = open(file, O_RDONLY); + if (fd == -1) + return -ENOENT; + + r = read(fd, buf, BUFF_MAX); + if ((r >= 0) && (r < BUFF_MAX)) + buf[r] = '\0'; + else + ret = -EIO; + + close(fd); + + return ret; +} + +static int sys_write_buf(char *file, char *buf) +{ + int fd; + int r; + int ret = 0; + + fd = open(file, O_WRONLY); + if (fd == -1) + return -ENOENT; + + r = write(fd, buf, strlen(buf)); + if (r < 0) + ret = -EIO; + + close(fd); + + return ret; +} + +int sys_get_int(char *fname, int *val) +{ + char buf[BUFF_MAX]; + int ret = 0; + + if (sys_read_buf(fname, buf) == 0) { + *val = atoi(buf); + } else { + *val = -1; + ret = -EIO; + } + + return ret; +} + +int sys_set_int(char *fname, int val) +{ + char buf[BUFF_MAX]; + int ret = 0; + + snprintf(buf, sizeof(buf), "%d", val); + + if (sys_write_buf(fname, buf) != 0) + ret = -EIO; + + return ret; +} + +int sys_get_str(char *fname, char *str) +{ + char buf[BUFF_MAX] = {0}; + + if (sys_read_buf(fname, buf) == 0) { + strncpy(str, buf, strlen(buf)); + return 0; + } + + return -1; +} + +int sys_set_str(char *fname, char *val) +{ + int r = -1; + + if (val != NULL) { + if (sys_write_buf(fname, val) == 0) + r = 0; + } + + return r; +} + +int terminate_process(char* partition, bool force) +{ + const char *argv[7] = {"/sbin/fuser", "-m", "-k", "-S", NULL, NULL, NULL}; + int argc; + + if (force) + argv[4] = "-SIGKILL"; + else + argv[4] = "-SIGTERM"; + argv[5] = partition; + argc = sizeof(argv) / sizeof(argv[0]); + return run_child(argc, argv); +} + +int mount_check(const char* path) +{ + int ret = false; + struct mntent* mnt; + const char* table = "/etc/mtab"; + FILE* fp; + + fp = setmntent(table, "r"); + if (!fp) + return ret; + while (mnt=getmntent(fp)) { + if (!strcmp(mnt->mnt_dir, path)) { + ret = true; + break; + } + } + endmntent(fp); + return ret; +} diff --git a/src/core/common.h b/src/core/common.h new file mode 100644 index 0000000..b25e101 --- /dev/null +++ b/src/core/common.h @@ -0,0 +1,108 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 __CORE_COMMON_H__ +#define __CORE_COMMON_H__ + +#include +#include +#include +#include + +#define ARRAY_SIZE(name) (sizeof(name)/sizeof(name[0])) + +/* + * One byte digit has 3 position in decimal representation + * 2 - 5 + * 4 - 10 + * 8 - 20 + * >8 - compile time error + * plus 1 null termination byte + * plus 1 for negative prefix + */ +#define MAX_DEC_SIZE(type) \ + (2 + (sizeof(type) <= 1 ? 3 : \ + sizeof(type) <= 2 ? 5 : \ + sizeof(type) <= 4 ? 10 : \ + sizeof(type) <= 8 ? 20 : \ + sizeof(int[-2*(sizeof(type) > 8)]))) + +#ifndef __CONSTRUCTOR__ +#define __CONSTRUCTOR__ __attribute__ ((constructor)) +#endif + +#ifndef __DESTRUCTOR__ +#define __DESTRUCTOR__ __attribute__ ((destructor)) +#endif + +#ifndef __WEAK__ +#define __WEAK__ __attribute__ ((weak)) +#endif + +#ifndef max +#define max(a, b) \ + __extension__ ({ \ + typeof(a) _a = (a); \ + typeof(b) _b = (b); \ + _a > _b ? _a : _b; \ + }) +#endif + +#ifndef min +#define min(a, b) \ + __extension__ ({ \ + typeof(a) _a = (a); \ + typeof(b) _b = (b); \ + _a < _b ? _a : _b; \ + }) +#endif + +#ifndef clamp +#define clamp(x, low, high) \ + __extension__ ({ \ + typeof(x) _x = (x); \ + typeof(low) _low = (low); \ + typeof(high) _high = (high); \ + ((_x > _high) ? _high : ((_x < _low) ? _low : _x)); \ + }) +#endif + +#ifndef SEC_TO_MSEC +#define SEC_TO_MSEC(x) ((x)*1000) +#endif +#ifndef NSEC_TO_MSEC +#define NSEC_TO_MSEC(x) ((double)x/1000000) +#endif +#ifndef USEC_TO_MSEC +#define USEC_TO_MSEC(x) ((double)x/1000) +#endif + +FILE * open_proc_oom_score_adj_file(int pid, const char *mode); +int get_exec_pid(const char *execpath); +int get_cmdline_name(pid_t pid, char *cmdline, size_t cmdline_size); +int is_vip(int pid); +int run_child(int argc, const char *argv[]); +int remove_dir(const char *path, int del_dir); +int sys_get_int(char *fname, int *val); +int sys_set_int(char *fname, int val); +int terminate_process(char* partition, bool force); +int mount_check(const char* path); + +#endif /* __CORE_COMMON_H__ */ + diff --git a/src/core/config-parser.c b/src/core/config-parser.c new file mode 100644 index 0000000..b7e164b --- /dev/null +++ b/src/core/config-parser.c @@ -0,0 +1,127 @@ +/* + * deviced + * + * Copyright (c) 2013 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 "log.h" +#include "config-parser.h" + +#define MAX_LINE 128 +#define MAX_SECTION 64 +#define WHITESPACE " \t" +#define NEWLINE "\n\r" +#define COMMENT '#' + +static inline char *trim_str(char *s) +{ + char *t; + /* left trim */ + s += strspn(s, WHITESPACE); + + /* right trim */ + for (t = strchr(s, 0); t > s; t--) + if (!strchr(WHITESPACE, t[-1])) + break; + *t = 0; + return s; +} + +int config_parse(const char *file_name, int cb(struct parse_result *result, + void *user_data), void *user_data) +{ + FILE *f = NULL; + struct parse_result result; + /* use stack for parsing */ + char line[MAX_LINE]; + char section[MAX_SECTION]; + char *start, *end, *name, *value; + int lineno = 0, ret = 0; + + if (!file_name || !cb) { + ret = -EINVAL; + goto error; + } + + /* open conf file */ + f = fopen(file_name, "r"); + if (!f) { + _E("Failed to open file %s", file_name); + ret = -EIO; + goto error; + } + + /* parsing line by line */ + while (fgets(line, MAX_LINE, f) != NULL) { + lineno++; + + start = line; + start[strcspn(start, NEWLINE)] = '\0'; + start = trim_str(start); + + if (*start == COMMENT) { + continue; + } else if (*start == '[') { + /* parse section */ + end = strchr(start, ']'); + if (!end || *end != ']') { + ret = -EBADMSG; + goto error; + } + + *end = '\0'; + strncpy(section, start + 1, sizeof(section)); + section[MAX_SECTION-1] = '\0'; + } else if (*start) { + /* parse name & value */ + end = strchr(start, '='); + if (!end || *end != '=') { + ret = -EBADMSG; + goto error; + } + *end = '\0'; + name = trim_str(start); + value = trim_str(end + 1); + end = strchr(value, COMMENT); + if (end && *end == COMMENT) { + *end = '\0'; + value = trim_str(value); + } + + result.section = section; + result.name = name; + result.value = value; + /* callback with parse result */ + ret = cb(&result, user_data); + if (ret < 0) { + ret = -EBADMSG; + goto error; + } + } + } + _D("Success to load %s", file_name); + fclose(f); + return 0; + +error: + if (f) + fclose(f); + _E("Failed to read %s:%d!", file_name, lineno); + return ret; +} + diff --git a/src/core/config-parser.h b/src/core/config-parser.h new file mode 100644 index 0000000..ed3675f --- /dev/null +++ b/src/core/config-parser.h @@ -0,0 +1,43 @@ +/* + * deviced + * + * Copyright (c) 2013 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 __CONFIG_PARSER_H__ +#define __CONFIG_PARSER_H__ + +#define MATCH(a, b) (!strncmp(a, b, strlen(a))) +#define SET_CONF(a, b) (a = (b > 0.0 ? b : a)) + +struct parse_result { + char *section; + char *name; + char *value; +}; + +/** + * @brief Parse config file and call callback\n + * @param[in] file_name conf file. + * @param[in] cb cb is called when conf file is parsed line by line. + * @param[in] user_data user data is passed to cb. + * @return 0 on success, negative if failed + */ +int config_parse(const char *file_name, int cb(struct parse_result *result, + void *user_data), void *user_data); + +#endif + diff --git a/src/core/core.c b/src/core/core.c new file mode 100644 index 0000000..1ee910d --- /dev/null +++ b/src/core/core.c @@ -0,0 +1,180 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 "data.h" +#include "queue.h" +#include "log.h" +#include "predefine.h" +#include "core.h" +#include "devices.h" +#include "common.h" + +enum core_cmd_type { + CORE_ACT_RUN, + CORE_ACT_CLEAR +}; + +struct _internal_msg { + int type; + int pid; +}; + +static int core_pipe[2]; +Ecore_Fd_Handler *g_pipe_efd = NULL; + +static int __pipe_start(struct main_data *ad); +static int __pipe_stop(int fd); + +static int _core_action_run(void *user_data, + struct run_queue_entry *rq_entry) +{ + struct action_entry *act_entry = rq_entry->action_entry; + int ret; + char tmp[128]; + + rq_entry->state = STATE_RUNNING; + ret = act_entry->predefine_action(rq_entry->argc, rq_entry->argv); + if (ret <= 0) { + if (ret < 0) + _E("predefine action failed"); + goto fast_done; + } else { + snprintf(tmp, sizeof(tmp), "/proc/%d/status", ret); + if (access(tmp, R_OK) == 0) + rq_entry->forked_pid = ret; + else + goto fast_done; + } + return 0; + + fast_done: + rq_entry->forked_pid = -1; + rq_entry->state = STATE_DONE; + core_action_clear(-1); + return 0; +} + +static Eina_Bool core_pipe_cb(void *userdata, Ecore_Fd_Handler * fd_handler) +{ + struct main_data *ad = (struct main_data *)userdata; + struct _internal_msg p_msg; + int retry_count = 0; + int r = -1; + if (!ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ)) { + _E("ecore_main_fd_handler_active_get error , return"); + return EINA_TRUE; + } + + while (retry_count < 5) { + r = read(core_pipe[0], &p_msg, sizeof(struct _internal_msg)); + if (r < 0) { + if (errno == EINTR) { + _D("Re-read for error(EINTR)"); + retry_count++; + continue; + } else { + __pipe_stop(core_pipe[0]); + __pipe_stop(core_pipe[1]); + _D("restart pipe fd"); + __pipe_start(ad); + } + } else { + break; + } + } + + switch (p_msg.type) { + case CORE_ACT_RUN: + run_queue_run(STATE_INIT, _core_action_run, ad); + break; + case CORE_ACT_CLEAR: + run_queue_del_bypid(p_msg.pid); + break; + } + return EINA_TRUE; +} + +int core_action_run() +{ + struct _internal_msg p_msg; + + p_msg.type = CORE_ACT_RUN; + p_msg.pid = 0; + write(core_pipe[1], &p_msg, sizeof(struct _internal_msg)); + + return 0; +} + +int core_action_clear(int pid) +{ + struct _internal_msg p_msg; + + p_msg.type = CORE_ACT_CLEAR; + p_msg.pid = pid; + write(core_pipe[1], &p_msg, sizeof(struct _internal_msg)); + + return 0; +} + +static int __pipe_start(struct main_data *ad) +{ + if (pipe(core_pipe) < 0) { + _E("pipe cannot create"); + exit(EXIT_FAILURE); + } + + g_pipe_efd = ecore_main_fd_handler_add(core_pipe[0], ECORE_FD_READ, + core_pipe_cb, ad, NULL, NULL); + if (!g_pipe_efd) { + _E("error ecore_main_fd_handler_add"); + return -1; + } + return 0; +} + +static int __pipe_stop(int fd) +{ + if (g_pipe_efd) { + ecore_main_fd_handler_del(g_pipe_efd); + g_pipe_efd = NULL; + } + if (fd >=0) + close(fd); + + return 0; +} + +static void core_init(void *data) +{ + struct main_data *ad = (struct main_data*)data; + + __pipe_stop(core_pipe[0]); + __pipe_stop(core_pipe[1]); + + if (__pipe_start(ad) == -1) + _E("fail pipe control fd init"); +} + +static const struct device_ops core_device_ops = { + .priority = DEVICE_PRIORITY_NORMAL, + .name = "core", + .init = core_init, +}; + +DEVICE_OPS_REGISTER(&core_device_ops) diff --git a/src/core/core.h b/src/core/core.h new file mode 100644 index 0000000..0ae3bbc --- /dev/null +++ b/src/core/core.h @@ -0,0 +1,28 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 __DD_CORE_H__ +#define __DD_CORE_H__ + +#include "data.h" + +int core_action_run(); +int core_action_clear(int pid); + +#endif /* __DD_CORE_H__ */ diff --git a/src/core/data.h b/src/core/data.h new file mode 100644 index 0000000..d07c356 --- /dev/null +++ b/src/core/data.h @@ -0,0 +1,31 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 __DD_DATA_H__ +#define __DD_DATA_H__ + +#include +#include + +struct main_data { + int sysnoti_fd; + int noti_fd; +}; + +#endif /* __DD_DATA_H__ */ diff --git a/src/core/device-change-handler.c b/src/core/device-change-handler.c new file mode 100644 index 0000000..bd3c8ba --- /dev/null +++ b/src/core/device-change-handler.c @@ -0,0 +1,1767 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "dd-deviced.h" +#include "queue.h" +#include "log.h" +#include "device-notifier.h" +#include "device-handler.h" +#include "device-node.h" +#include "noti.h" +#include "data.h" +#include "predefine.h" +#include "display/poll.h" +#include "devices.h" +#include "hall/hall-handler.h" +#include "udev.h" +#include "common.h" +#include "common.h" +#include "list.h" +#include "proc/proc-handler.h" +#include "edbus-handler.h" +#include "emulator.h" +#include "devices.h" +#include "power-supply.h" +#include "display/setting.h" +#include "display/core.h" + +#define PREDEF_EARJACKCON "earjack_predef_internal" +#define PREDEF_DEVICE_CHANGED "device_changed" +#define PREDEF_POWER_CHANGED POWER_SUBSYSTEM +#define PREDEF_UDEV_CONTROL UDEV + +#define TVOUT_X_BIN "/usr/bin/xberc" +#define TVOUT_FLAG 0x00000001 + +#define MOVINAND_MOUNT_POINT "/opt/media" +#define BUFF_MAX 255 +#define SYS_CLASS_INPUT "/sys/class/input" + +#ifdef MICRO_DD +#define USB_STATE_PATH "/sys/devices/platform/jack/usb_online" +#else +#define USB_STATE_PATH "/sys/devices/virtual/switch/usb_cable/state" +#endif + +#define HDMI_NOT_SUPPORTED (-1) +#ifdef ENABLE_EDBUS_USE +#include +static E_DBus_Connection *conn; +#endif /* ENABLE_EDBUS_USE */ + +struct input_event { + long dummy[2]; + unsigned short type; + unsigned short code; + int value; +}; + +enum snd_jack_types { + SND_JACK_HEADPHONE = 0x0001, + SND_JACK_MICROPHONE = 0x0002, + SND_JACK_HEADSET = SND_JACK_HEADPHONE | SND_JACK_MICROPHONE, + SND_JACK_LINEOUT = 0x0004, + SND_JACK_MECHANICAL = 0x0008, /* If detected separately */ + SND_JACK_VIDEOOUT = 0x0010, + SND_JACK_AVOUT = SND_JACK_LINEOUT | SND_JACK_VIDEOOUT, +}; + +#define CRADLE_APP_NAME "com.samsung.desk-dock" +#define VIRTUAL_CONTROLLER_APP_NAME "com.samsung.virtual-controller" + +#define CHANGE_ACTION "change" +#define ENV_FILTER "CHGDET" +#define USB_NAME "usb" +#define USB_NAME_LEN 3 + +#define CHARGER_NAME "charger" +#define CHARGER_NAME_LEN 7 + +#define EARJACK_NAME "earjack" +#define EARJACK_NAME_LEN 7 + +#define EARKEY_NAME "earkey" +#define EARKEY_NAME_LEN 6 + +#define TVOUT_NAME "tvout" +#define TVOUT_NAME_LEN 5 + +#define HDMI_NAME "hdmi" +#define HDMI_NAME_LEN 4 + +#define HDCP_NAME "hdcp" +#define HDCP_NAME_LEN 4 + +#define HDMI_AUDIO_NAME "ch_hdmi_audio" +#define HDMI_AUDIO_LEN 13 + +#define CRADLE_NAME "cradle" +#define CRADLE_NAME_LEN 6 + +#define KEYBOARD_NAME "keyboard" +#define KEYBOARD_NAME_LEN 8 + +#define POWER_SUPPLY_NAME_LEN 12 + +#define CHARGE_NAME_LEN 17 +#define BATTERY_NAME "battery" +#define BATTERY_NAME_LEN 7 +#define CHARGEFULL_NAME "Full" +#define CHARGEFULL_NAME_LEN 4 +#define CHARGENOW_NAME "Charging" +#define CHARGENOW_NAME_LEN 8 +#define DISCHARGE_NAME "Discharging" +#define DISCHARGE_NAME_LEN 11 +#define NOTCHARGE_NAME "Not charging" +#define NOTCHARGE_NAME_LEN 12 +#define OVERHEAT_NAME "Overheat" +#define OVERHEAT_NAME_LEN 8 +#define TEMPCOLD_NAME "Cold" +#define TEMPCOLD_NAME_LEN 4 +#define OVERVOLT_NAME "Over voltage" +#define OVERVOLT_NAME_LEN 12 + +#define SWITCH_DEVICE_USB "usb_cable" + +#define LAUNCH_APP "launch-app" +#define DESK_DOCK "desk-dock" + +/* Ticker notification */ +#define DOCK_CONNECTED "dock-connected" +#define HDMI_CONNECTED "hdmi-connected" +#define HDMI_DISCONNECTED "hdmi-disconnected" + +#define METHOD_GET_HDMI "GetHDMI" +#define METHOD_GET_HDCP "GetHDCP" +#define METHOD_GET_HDMI_AUDIO "GetHDMIAudio" +#define SIGNAL_HDMI_STATE "ChangedHDMI" +#define SIGNAL_HDCP_STATE "ChangedHDCP" +#define SIGNAL_HDMI_AUDIO_STATE "ChangedHDMIAudio" + +#define HDCP_HDMI_VALUE(HDCP, HDMI) ((HDCP << 1) | HDMI) + +#define METHOD_GET_CRADLE "GetCradle" +#define SIGNAL_CRADLE_STATE "ChangedCradle" + +struct ticker_data { + char *name; + int type; +}; + +struct popup_data { + char *name; + char *key; + char *value; +}; + +static int ss_flags = 0; + +static int input_device_number; + +/* Uevent */ +static struct udev *udev = NULL; +/* Kernel Uevent */ +static struct udev_monitor *mon = NULL; +static Ecore_Fd_Handler *ufdh = NULL; +static int ufd = -1; +/* Udev Uevent */ +static struct udev_monitor *mon_udev = NULL; +static Ecore_Fd_Handler *ufdh_udev = NULL; +static int ufd_udev = -1; + +static dd_list *opt_uevent_list = NULL; +static dd_list *opt_kernel_uevent_list = NULL; +static int hdmi_status = 0; +static const struct device_ops *lowbat_ops; + +enum udev_subsystem_type { + UDEV_HALL_IC, + UDEV_INPUT, + UDEV_LCD_EVENT, + UDEV_PLATFORM, + UDEV_POWER, + UDEV_SWITCH, +}; + +static const struct udev_subsystem { + const enum udev_subsystem_type type; + const char *str; + const char *devtype; +} udev_subsystems[] = { + { UDEV_HALL_IC, HALL_IC_SUBSYSTEM, NULL}, + { UDEV_INPUT, INPUT_SUBSYSTEM, NULL }, + { UDEV_LCD_EVENT, LCD_EVENT_SUBSYSTEM, NULL }, + { UDEV_PLATFORM, PLATFORM_SUBSYSTEM, NULL }, + { UDEV_POWER, POWER_SUBSYSTEM, NULL}, + { UDEV_SWITCH, SWITCH_SUBSYSTEM, NULL }, +}; + +static struct extcon_device { + const enum extcon_type type; + const char *str; + int fd; + int count; +} extcon_devices[] = { + { EXTCON_TA, "/csa/factory/batt_cable_count", 0, 0}, + { EXTCON_EARJACK, "/csa/factory/earjack_count", 0, 0}, +}; + +extern int battery_power_off_act(void *data); +extern int battery_charge_err_act(void *data); + +int extcon_set_count(int index) +{ + int r; + int ret = 0; + char buf[BUFF_MAX]; + + extcon_devices[index].count++; + + if (extcon_devices[index].fd < 0) { + _E("cannot open file(%s)", extcon_devices[index].str); + return -ENOENT; + } + lseek(extcon_devices[index].fd, 0, SEEK_SET); + _I("ext(%d) count %d", index, extcon_devices[index].count); + snprintf(buf, sizeof(buf), "%d", extcon_devices[index].count); + + r = write(extcon_devices[index].fd, buf, strlen(buf)); + if (r < 0) + ret = -EIO; + return ret; +} + +static int extcon_get_count(int index) +{ + int fd; + int r; + int ret = 0; + char buf[BUFF_MAX]; + + fd = open(extcon_devices[index].str, O_RDWR); + if (fd < 0) + return -ENOENT; + + r = read(fd, buf, BUFF_MAX); + if ((r >= 0) && (r < BUFF_MAX)) + buf[r] = '\0'; + else + ret = -EIO; + + if (ret != 0) { + close(fd); + return ret; + } + extcon_devices[index].fd = fd; + extcon_devices[index].count = atoi(buf); + _I("get extcon(%d:%x) count %d", + index, extcon_devices[index].fd, extcon_devices[index].count); + + return ret; +} + +static int extcon_create_count(int index) +{ + int fd; + int r; + int ret = 0; + char buf[BUFF_MAX]; + fd = open(extcon_devices[index].str, O_RDWR | O_CREAT, 0644); + if (fd < 0) { + _E("cannot open file(%s)", extcon_devices[index].str); + return -ENOENT; + } + snprintf(buf, sizeof(buf), "%d", extcon_devices[index].count); + r = write(fd, buf, strlen(buf)); + if (r < 0) + ret = -EIO; + + if (ret != 0) { + close(fd); + _E("cannot write file(%s)", extcon_devices[index].str); + return ret; + } + extcon_devices[index].fd = fd; + _I("create extcon(%d:%x) %s", + index, extcon_devices[index].fd, extcon_devices[index].str); + return ret; +} + +static int extcon_count_init(void) +{ + int i; + int ret = 0; + for (i = 0; i < ARRAY_SIZE(extcon_devices); i++) { + if (extcon_get_count(i) >= 0) + continue; + ret = extcon_create_count(i); + if (ret < 0) + break; + } + return ret; +} + +int get_usb_state_direct(void) +{ + FILE *fp; + char str[2]; + int state; + + fp = fopen(USB_STATE_PATH, "r"); + if (!fp) { + _E("Cannot open jack node"); + return -ENOMEM; + } + + if (!fgets(str, sizeof(str), fp)) { + _E("cannot get string from jack node"); + fclose(fp); + return -ENOMEM; + } + + fclose(fp); + + return atoi(str); +} + +static void usb_chgdet_cb(void *data) +{ + int val = -1; + int ret = 0; + char params[BUFF_MAX]; + + if (data == NULL) + ret = device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_USB_ONLINE, &val); + else + val = *(int *)data; + if (ret == 0) { + if (val < 0) + val = get_usb_state_direct(); + + _I("jack - usb changed %d",val); + check_lowbat_charge_device(val); + if (val==1) { + battery_noti(DEVICE_NOTI_BATT_CHARGE, DEVICE_NOTI_ON); + _D("usb device notification"); + } + } else { + _E("fail to get usb_online status"); + } +} + +static void show_ticker_notification(char *text, int queue) +{ + struct ticker_data t_data; + static const struct device_ops *ticker = NULL; + + if (!ticker) { + ticker = find_device("ticker"); + if (!ticker) + return; + } + + t_data.name = text; + t_data.type = queue; + if (ticker->init) + ticker->init(&t_data); +} + +static void launch_cradle(int val) +{ + struct popup_data *params; + static const struct device_ops *apps = NULL; + + if (apps == NULL) { + apps = find_device("apps"); + if (apps == NULL) + return; + } + params = malloc(sizeof(struct popup_data)); + if (params == NULL) { + _E("Malloc failed"); + return; + } + params->name = LAUNCH_APP; + params->key = DESK_DOCK; + _I("%s %s %x", params->name, params->key, params); + if (val == 0) { + if (apps->exit) + apps->exit((void *)params); + } else { + show_ticker_notification(DOCK_CONNECTED, 0); + if (apps->init) + apps->init((void *)params); + } + free(params); + +} + +static int display_changed(void *data) +{ + enum state_t state = (enum state_t)data; + int ret, cradle = 0; + + if (battery.charge_now == CHARGER_ABNORMAL && battery.health == HEALTH_BAD) { + pm_lock_internal(INTERNAL_LOCK_POPUP, LCD_DIM, STAY_CUR_STATE, 0); + return 0; + } + + if (state != S_NORMAL) + return 0; + + ret = vconf_get_int(VCONFKEY_SYSMAN_CRADLE_STATUS, &cradle); + if (ret >= 0 && cradle == DOCK_SOUND) { + pm_lock_internal(getpid(), LCD_DIM, STAY_CUR_STATE, 0); + _I("sound dock is connected! dim lock is on."); + } + if (hdmi_status) { + pm_lock_internal(getpid(), LCD_DIM, STAY_CUR_STATE, 0); + _I("hdmi is connected! dim lock is on."); + } + return 0; +} + +static void cradle_send_broadcast(int status) +{ + static int old = 0; + char *arr[1]; + char str_status[32]; + + if (old == status) + return; + + _I("broadcast cradle status %d", status); + old = status; + snprintf(str_status, sizeof(str_status), "%d", status); + arr[0] = str_status; + + broadcast_edbus_signal(DEVICED_PATH_SYSNOTI, DEVICED_INTERFACE_SYSNOTI, + SIGNAL_CRADLE_STATE, "i", arr); +} + +static int cradle_cb(void *data) +{ + static int old = 0; + int val = 0; + int ret = 0; + + if (data == NULL) + return old; + + val = *(int *)data; + + if (old == val) + return old; + + old = val; + cradle_send_broadcast(old); + return old; +} + +static void cradle_chgdet_cb(void *data) +{ + int val; + int ret = 0; + + pm_change_internal(getpid(), LCD_NORMAL); + + if (data) + val = *(int *)data; + else { + ret = device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_CRADLE_ONLINE, &val); + if (ret != 0) { + _E("failed to get status"); + return; + } + } + + _I("jack - cradle changed %d", val); + cradle_cb((void *)&val); + if (vconf_set_int(VCONFKEY_SYSMAN_CRADLE_STATUS, val) != 0) { + _E("failed to set vconf status"); + return; + } + + if (val == DOCK_SOUND) + pm_lock_internal(getpid(), LCD_DIM, STAY_CUR_STATE, 0); + else if (val == DOCK_NONE) + pm_unlock_internal(getpid(), LCD_DIM, PM_SLEEP_MARGIN); + + launch_cradle(val); +} + +void sync_cradle_status(void) +{ + int val; + int status; + if ((device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_CRADLE_ONLINE, &val) != 0) || + vconf_get_int(VCONFKEY_SYSMAN_CRADLE_STATUS, &status) != 0) + return; + if ((val != 0 && status == 0) || (val == 0 && status != 0)) + cradle_chgdet_cb(NULL); +} + +static void ta_chgdet_cb(struct main_data *ad) +{ + int val = -1; + int ret = -1; + int bat_state = VCONFKEY_SYSMAN_BAT_NORMAL; + char params[BUFF_MAX]; + + if (device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_TA_ONLINE, &val) == 0) { + _I("jack - ta changed %d",val); + check_lowbat_charge_device(val); + vconf_set_int(VCONFKEY_SYSMAN_CHARGER_STATUS, val); + if (val == 0) { + ret = device_get_property(DEVICE_TYPE_POWER, PROP_POWER_INSUSPEND_CHARGING_SUPPORT, &val); + if (ret != 0) + val = 0; + if (val == 0) + pm_unlock_internal(INTERNAL_LOCK_TA, LCD_OFF, STAY_CUR_STATE); + device_notify(DEVICE_NOTIFIER_BATTERY_CHARGING, (void*)FALSE); + } else { + ret = device_get_property(DEVICE_TYPE_POWER, PROP_POWER_INSUSPEND_CHARGING_SUPPORT, &val); + if (ret != 0) + val = 0; + if (val == 0) + pm_lock_internal(INTERNAL_LOCK_TA, LCD_OFF, STAY_CUR_STATE, 0); + battery_noti(DEVICE_NOTI_BATT_CHARGE, DEVICE_NOTI_ON); + _D("ta device notification"); + device_notify(DEVICE_NOTIFIER_BATTERY_CHARGING, (void*)TRUE); + } + sync_cradle_status(); + } + else + _E("failed to get ta status"); +} + +static void earjack_chgdet_cb(void *data) +{ + int val; + int ret = 0; + + if (data) + val = *(int *)data; + else { + ret = device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_EARJACK_ONLINE, &val); + if (ret != 0) { + _E("failed to get status"); + return; + } + } + _I("jack - earjack changed %d", val); + if (CONNECTED(val)) { + extcon_set_count(EXTCON_EARJACK); + predefine_pm_change_state(LCD_NORMAL); + } + vconf_set_int(VCONFKEY_SYSMAN_EARJACK, val); +} + +static void earkey_chgdet_cb(void *data) +{ + int val; + int ret = 0; + + if (data) + val = *(int *)data; + else { + ret = device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_EARKEY_ONLINE, &val); + if (ret != 0) { + _E("failed to get status"); + return; + } + } + _I("jack - earkey changed %d", val); + vconf_set_int(VCONFKEY_SYSMAN_EARJACKKEY, val); +} + +static void tvout_chgdet_cb(void *data) +{ + _I("jack - tvout changed"); + pm_change_internal(getpid(), LCD_NORMAL); +} + +static void hdcp_hdmi_send_broadcast(int status) +{ + static int old = 0; + char *arr[1]; + char str_status[32]; + + if (old == status) + return; + + _I("broadcast hdmi status %d", status); + old = status; + snprintf(str_status, sizeof(str_status), "%d", status); + arr[0] = str_status; + + broadcast_edbus_signal(DEVICED_PATH_SYSNOTI, DEVICED_INTERFACE_SYSNOTI, + SIGNAL_HDMI_STATE, "i", arr); +} + +static int hdcp_hdmi_cb(void *data) +{ + static int old = 0; + int val = 0; + int ret = 0; + + if (data == NULL) + return old; + + val = *(int *)data; + val = HDCP_HDMI_VALUE(val, hdmi_status); + + if (old == val) + return old; + + old = val; + hdcp_hdmi_send_broadcast(old); + return old; +} + +static void hdmi_chgdet_cb(void *data) +{ + int val; + int ret = 0; + + pm_change_internal(getpid(), LCD_NORMAL); + if (device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_HDMI_SUPPORT, &val) == 0) { + if (val!=1) { + _I("target is not support HDMI"); + vconf_set_int(VCONFKEY_SYSMAN_HDMI, HDMI_NOT_SUPPORTED); + return; + } + } + + if (data) + val = *(int *)data; + else { + ret = device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_HDMI_ONLINE, &val); + if (ret != 0) { + _E("failed to get status"); + return; + } + } + + _I("jack - hdmi changed %d", val); + vconf_set_int(VCONFKEY_SYSMAN_HDMI, val); + hdmi_status = val; + device_notify(DEVICE_NOTIFIER_HDMI, (void *)val); + + if(val == 1) { + pm_lock_internal(INTERNAL_LOCK_HDMI, LCD_DIM, STAY_CUR_STATE, 0); + show_ticker_notification(HDMI_CONNECTED, 0); + } else { + show_ticker_notification(HDMI_DISCONNECTED, 0); + pm_unlock_internal(INTERNAL_LOCK_HDMI, LCD_DIM, PM_SLEEP_MARGIN); + } +} + +static void hdcp_send_broadcast(int status) +{ + static int old = 0; + char *arr[1]; + char str_status[32]; + + if (old == status) + return; + + _D("broadcast hdcp status %d", status); + old = status; + snprintf(str_status, sizeof(str_status), "%d", status); + arr[0] = str_status; + + broadcast_edbus_signal(DEVICED_PATH_SYSNOTI, DEVICED_INTERFACE_SYSNOTI, + SIGNAL_HDCP_STATE, "i", arr); +} + +static int hdcp_chgdet_cb(void *data) +{ + static int old = 0; + int val = 0; + + if (data == NULL) + return old; + + val = *(int *)data; + if (old == val) + return old; + + old = val; + hdcp_send_broadcast(old); + return old; +} + +static void hdmi_audio_send_broadcast(int status) +{ + static int old = 0; + char *arr[1]; + char str_status[32]; + + if (old == status) + return; + + _D("broadcast hdmi audio status %d", status); + old = status; + snprintf(str_status, sizeof(str_status), "%d", status); + arr[0] = str_status; + + broadcast_edbus_signal(DEVICED_PATH_SYSNOTI, DEVICED_INTERFACE_SYSNOTI, + SIGNAL_HDMI_AUDIO_STATE, "i", arr); +} + +static int hdmi_audio_chgdet_cb(void *data) +{ + static int old = 0; + int val = 0; + + if (data == NULL) + return old; + + val = *(int *)data; + if (old == val) + return old; + + old = val; + hdmi_audio_send_broadcast(old); + return old; +} + +static void keyboard_chgdet_cb(void *data) +{ + int val = -1; + int ret = 0; + + if (data) + val = *(int *)data; + else { + ret = device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_KEYBOARD_ONLINE, &val); + if (ret != 0) { + _E("failed to get status"); + vconf_set_int(VCONFKEY_SYSMAN_SLIDING_KEYBOARD, VCONFKEY_SYSMAN_SLIDING_KEYBOARD_NOT_SUPPORTED); + return; + } + } + _I("jack - keyboard changed %d", val); + if(val != 1) + val = 0; + vconf_set_int(VCONFKEY_SYSMAN_SLIDING_KEYBOARD, val); +} + +static void ums_unmount_cb(void *data) +{ + umount(MOVINAND_MOUNT_POINT); +} + +#ifdef ENABLE_EDBUS_USE +static void cb_xxxxx_signaled(void *data, DBusMessage * msg) +{ + char *args; + DBusError err; + struct main_data *ad; + + ad = data; + + dbus_error_init(&err); + if (dbus_message_get_args + (msg, &err, DBUS_TYPE_STRING, &args, DBUS_TYPE_INVALID)) { + if (!strcmp(args, "action")) ; /* action */ + } + + return; +} +#endif /* ENABLE_EDBUS_USE */ + +static void check_capacity_status(const char *env_value) +{ + if (env_value == NULL) + return; + battery.capacity = atoi(env_value); +} + +static void check_charge_status(const char *env_value) +{ + if (env_value == NULL) + return; + if (strncmp(env_value, CHARGEFULL_NAME , CHARGEFULL_NAME_LEN) == 0) { + battery.charge_full = CHARGING_FULL; + battery.charge_now = CHARGER_DISCHARGING; + } else if (strncmp(env_value, CHARGENOW_NAME, CHARGENOW_NAME_LEN) == 0) { + battery.charge_full = CHARGING_NOT_FULL; + battery.charge_now = CHARGER_CHARGING; + } else if (strncmp(env_value, DISCHARGE_NAME, DISCHARGE_NAME_LEN) == 0) { + battery.charge_full = CHARGING_NOT_FULL; + battery.charge_now = CHARGER_DISCHARGING; + } else if (strncmp(env_value, NOTCHARGE_NAME, NOTCHARGE_NAME_LEN) == 0) { + battery.charge_full = CHARGING_NOT_FULL; + battery.charge_now = CHARGER_ABNORMAL; + } else { + battery.charge_full = CHARGING_NOT_FULL; + battery.charge_now = CHARGER_DISCHARGING; + } +} + +static void check_health_status(const char *env_value) +{ + if (env_value == NULL) { + battery.health = HEALTH_GOOD; + battery.temp = TEMP_LOW; + battery.ovp = OVP_NORMAL; + return; + } + if (strncmp(env_value, OVERHEAT_NAME, OVERHEAT_NAME_LEN) == 0) { + battery.health = HEALTH_BAD; + battery.temp = TEMP_HIGH; + battery.ovp = OVP_NORMAL; + } else if (strncmp(env_value, TEMPCOLD_NAME, TEMPCOLD_NAME_LEN) == 0) { + battery.health = HEALTH_BAD; + battery.temp = TEMP_LOW; + battery.ovp = OVP_NORMAL; + } else if (strncmp(env_value, OVERVOLT_NAME, OVERVOLT_NAME_LEN) == 0) { + battery.health = HEALTH_GOOD; + battery.temp = TEMP_LOW; + battery.ovp = OVP_ABNORMAL; + } else { + battery.health = HEALTH_GOOD; + battery.temp = TEMP_LOW; + battery.ovp = OVP_NORMAL; + } +} + +static void check_online_status(const char *env_value) +{ + if (env_value == NULL) + return; + battery.online = atoi(env_value); +} + +static void check_present_status(const char *env_value) +{ + if (env_value == NULL) { + battery.present = PRESENT_NORMAL; + return; + } + battery.present = atoi(env_value); +} + +static Eina_Bool uevent_kernel_control_cb(void *data, Ecore_Fd_Handler *fd_handler) +{ + struct udev_device *dev = NULL; + struct udev_list_entry *list_entry = NULL; + const char *subsystem = NULL; + const char *env_name = NULL; + const char *env_value = NULL; + const char *devpath; + const char *devnode; + const char *action; + const char *siop_level; + const char *rear_level; + dd_list *l; + void *l_data; + struct uevent_handler *uh; + int ret = -1; + int i, len; + + if ((dev = udev_monitor_receive_device(mon)) == NULL) + return EINA_TRUE; + + subsystem = udev_device_get_subsystem(dev); + + for (i = 0; i < ARRAY_SIZE(udev_subsystems); i++) { + len = strlen(udev_subsystems[i].str); + if (!strncmp(subsystem, udev_subsystems[i].str, len)) + break; + } + + if (i >= ARRAY_SIZE(udev_subsystems)) + goto out; + + devpath = udev_device_get_devpath(dev); + + switch (udev_subsystems[i].type) { + case UDEV_HALL_IC: + if (!strncmp(devpath, HALL_IC_PATH, strlen(HALL_IC_PATH))) { + notify_action(PREDEF_HALL_IC, 1, HALL_IC_NAME); + goto out; + } + break; + case UDEV_INPUT: + /* check new input device */ + if (!fnmatch(INPUT_PATH, devpath, 0)) { + action = udev_device_get_action(dev); + devnode = udev_device_get_devnode(dev); + if (!strcmp(action, UDEV_ADD)) + device_notify(DEVICE_NOTIFIER_INPUT_ADD, (void *)devnode); + else if (!strcmp(action, UDEV_REMOVE)) + device_notify(DEVICE_NOTIFIER_INPUT_REMOVE, (void *)devnode); + goto out; + } + break; + case UDEV_LCD_EVENT: + /* check new esd device */ + if (!fnmatch(LCD_ESD_PATH, devpath, 0)) { + action = udev_device_get_action(dev); + if (!strcmp(action, UDEV_CHANGE)) + device_notify(DEVICE_NOTIFIER_LCD_ESD, "ESD"); + goto out; + } + break; + case UDEV_SWITCH: + env_name = udev_device_get_property_value(dev, "SWITCH_NAME"); + env_value = udev_device_get_property_value(dev, "SWITCH_STATE"); + notify_action(PREDEF_DEVICE_CHANGED, 2, env_name, env_value); + break; + case UDEV_PLATFORM: + if (!fnmatch(THERMISTOR_PATH, devpath, 0)) { + siop_level = udev_device_get_property_value(dev, "TEMPERATURE"); + rear_level = udev_device_get_property_value(dev, "REAR_TEMPERATURE"); + notify_action(SIOP_CHANGED, 2, siop_level, rear_level); + goto out; + } + + env_value = udev_device_get_property_value(dev, ENV_FILTER); + if (!env_value) + break; + notify_action(PREDEF_DEVICE_CHANGED, 1, env_value); + break; + case UDEV_POWER: + udev_list_entry_foreach(list_entry, udev_device_get_properties_list_entry(dev)) { + env_name = udev_list_entry_get_name(list_entry); + if (env_name == NULL) + continue; + if (strncmp(env_name, CHARGE_NAME, CHARGE_NAME_LEN) == 0) { + env_value = udev_list_entry_get_value(list_entry); + if (env_value == NULL) + continue; + if (strncmp(env_value, BATTERY_NAME, BATTERY_NAME_LEN) == 0) { + ret = 0; + break; + } + } + } + if (ret != 0) + goto out; + env_value = udev_device_get_property_value(dev, CHARGE_STATUS); + check_charge_status(env_value); + env_value = udev_device_get_property_value(dev, CHARGE_ONLINE); + check_online_status(env_value); + env_value = udev_device_get_property_value(dev, CHARGE_HEALTH); + check_health_status(env_value); + env_value = udev_device_get_property_value(dev, CHARGE_PRESENT); + check_present_status(env_value); + env_value = udev_device_get_property_value(dev, CAPACITY); + check_capacity_status(env_value); + battery_noti(DEVICE_NOTI_BATT_CHARGE, DEVICE_NOTI_ON); + if (env_value) + notify_action(PREDEF_DEVICE_CHANGED, 2, subsystem, env_value); + else + notify_action(PREDEF_DEVICE_CHANGED, 1, subsystem); + break; + } + +out: + DD_LIST_FOREACH(opt_kernel_uevent_list, l, l_data) { + uh = (struct uevent_handler *)l_data; + if (strncmp(subsystem, uh->subsystem, strlen(uh->subsystem))) + continue; + uh->uevent_func(dev); + } + + udev_device_unref(dev); + return EINA_TRUE; +} + +static Eina_Bool uevent_udev_control_cb(void *data, Ecore_Fd_Handler *fd_handler) +{ + struct udev_device *dev = NULL; + dd_list *l; + void *l_data; + struct uevent_handler *uh; + const char *subsystem = NULL; + + dev = udev_monitor_receive_device(mon_udev); + if (!dev) + return EINA_TRUE; + + subsystem = udev_device_get_subsystem(dev); + if (!subsystem) { + _E("Failed to get subsystem from uevent"); + goto out; + } + + DD_LIST_FOREACH(opt_uevent_list, l, l_data) { + uh = (struct uevent_handler *)l_data; + if (strncmp(subsystem, uh->subsystem, strlen(uh->subsystem))) + continue; + uh->uevent_func(dev); + } + +out: + udev_device_unref(dev); + return EINA_TRUE; +} + +static int uevent_kernel_control_stop(void) +{ + struct udev_device *dev = NULL; + + if (ufdh) { + ecore_main_fd_handler_del(ufdh); + ufdh = NULL; + } + if (ufd >= 0) { + close(ufd); + ufd = -1; + } + if (mon) { + dev = udev_monitor_receive_device(mon); + if (dev) { + udev_device_unref(dev); + dev = NULL; + } + udev_monitor_unref(mon); + mon = NULL; + } + if (udev && !mon_udev) { + udev_unref(udev); + udev = NULL; + } + return 0; +} + +static int uevent_udev_control_stop(void) +{ + struct udev_device *dev = NULL; + + if (ufdh_udev) { + ecore_main_fd_handler_del(ufdh_udev); + ufdh_udev = NULL; + } + if (ufd_udev >= 0) { + close(ufd_udev); + ufd_udev = -1; + } + if (mon_udev) { + dev = udev_monitor_receive_device(mon_udev); + if (dev) { + udev_device_unref(dev); + dev = NULL; + } + udev_monitor_unref(mon_udev); + mon_udev = NULL; + } + if (udev && !mon) { + udev_unref(udev); + udev = NULL; + } + return 0; +} + +static int uevent_kernel_control_start(void) +{ + int i, ret; + + if (udev && mon) { + _E("uevent control routine is alreay started"); + return -EINVAL; + } + + if (!udev) { + udev = udev_new(); + if (!udev) { + _E("error create udev"); + return -EINVAL; + } + } + + mon = udev_monitor_new_from_netlink(udev, UDEV); + if (mon == NULL) { + _E("error udev_monitor create"); + goto stop; + } + + if (udev_monitor_set_receive_buffer_size(mon, UDEV_MONITOR_SIZE) != 0) { + _E("fail to set receive buffer size"); + goto stop; + } + + for (i = 0; i < ARRAY_SIZE(udev_subsystems); i++) { + ret = udev_monitor_filter_add_match_subsystem_devtype(mon, + udev_subsystems[i].str, udev_subsystems[i].devtype); + if (ret < 0) { + _E("error apply subsystem filter"); + goto stop; + } + } + + ret = udev_monitor_filter_update(mon); + if (ret < 0) + _E("error udev_monitor_filter_update"); + + ufd = udev_monitor_get_fd(mon); + if (ufd == -1) { + _E("error udev_monitor_get_fd"); + goto stop; + } + + ufdh = ecore_main_fd_handler_add(ufd, ECORE_FD_READ, + uevent_kernel_control_cb, NULL, NULL, NULL); + if (!ufdh) { + _E("error ecore_main_fd_handler_add"); + goto stop; + } + + if (udev_monitor_enable_receiving(mon) < 0) { + _E("error unable to subscribe to udev events"); + goto stop; + } + + return 0; +stop: + uevent_kernel_control_stop(); + return -EINVAL; + +} + +static int uevent_udev_control_start(void) +{ + int i, ret; + + if (udev && mon_udev) { + _E("uevent control routine is alreay started"); + return 0; + } + + if (!udev) { + udev = udev_new(); + if (!udev) { + _E("error create udev"); + return -EINVAL; + } + } + + mon_udev = udev_monitor_new_from_netlink(udev, "udev"); + if (mon_udev == NULL) { + _E("error udev_monitor create"); + goto stop; + } + + if (udev_monitor_set_receive_buffer_size(mon_udev, UDEV_MONITOR_SIZE_LARGE) != 0) { + _E("fail to set receive buffer size"); + goto stop; + } + + ufd_udev = udev_monitor_get_fd(mon_udev); + if (ufd_udev == -1) { + _E("error udev_monitor_get_fd"); + goto stop; + } + + ufdh_udev = ecore_main_fd_handler_add(ufd_udev, ECORE_FD_READ, + uevent_udev_control_cb, NULL, NULL, NULL); + if (!ufdh_udev) { + _E("error ecore_main_fd_handler_add"); + goto stop; + } + + if (udev_monitor_enable_receiving(mon_udev) < 0) { + _E("error unable to subscribe to udev events"); + goto stop; + } + + return 0; +stop: + uevent_udev_control_stop(); + return -EINVAL; +} + +int register_uevent_control(const struct uevent_handler *uh) +{ + int ret; + + if (!mon || !uh) + return -EINVAL; + + ret = udev_monitor_filter_add_match_subsystem_devtype(mon_udev, + uh->subsystem, NULL); + if (ret < 0) { + _E("FAIL: udev_monitor_filter_add_match_subsystem_devtype()"); + return -ENOMEM; + } + + ret = udev_monitor_filter_update(mon_udev); + if (ret < 0) + _E("error udev_monitor_filter_update"); + + DD_LIST_APPEND(opt_uevent_list, uh); + + return 0; +} + +void unregister_uevent_control(const struct uevent_handler *uh) +{ + dd_list *l; + void *data; + struct uevent_handler *handler; + + DD_LIST_FOREACH(opt_uevent_list, l, data) { + handler = (struct uevent_handler *)data; + if (strncmp(handler->subsystem, uh->subsystem, strlen(uh->subsystem))) + continue; + if (handler->uevent_func != uh->uevent_func) + continue; + + DD_LIST_REMOVE(opt_uevent_list, handler); + free(handler); + break; + } +} + +int register_kernel_uevent_control(const struct uevent_handler *uh) +{ + int ret; + + if (!mon || !uh) + return -EINVAL; + + ret = udev_monitor_filter_add_match_subsystem_devtype(mon, + uh->subsystem, NULL); + if (ret < 0) { + _E("FAIL: udev_monitor_filter_add_match_subsystem_devtype()"); + return -ENOMEM; + } + + ret = udev_monitor_filter_update(mon); + if (ret < 0) + _E("error udev_monitor_filter_update"); + + DD_LIST_APPEND(opt_kernel_uevent_list, uh); + + return 0; +} + +void unregister_kernel_uevent_control(const struct uevent_handler *uh) +{ + dd_list *l; + void *data; + struct uevent_handler *handler; + + DD_LIST_FOREACH(opt_kernel_uevent_list, l, data) { + handler = (struct uevent_handler *)data; + if (strncmp(handler->subsystem, uh->subsystem, strlen(uh->subsystem))) + continue; + if (handler->uevent_func != uh->uevent_func) + continue; + + DD_LIST_REMOVE(opt_kernel_uevent_list, data); + break; + } +} + +int uevent_udev_get_path(const char *subsystem, dd_list **list) +{ + struct udev_enumerate *enumerate = NULL; + struct udev_list_entry *devices, *dev_list_entry; + int ret; + + if (!udev) { + udev = udev_new(); + if (!udev) { + _E("error create udev"); + return -EIO; + } + } + + enumerate = udev_enumerate_new(udev); + if (!enumerate) + return -EIO; + + ret = udev_enumerate_add_match_subsystem(enumerate, subsystem); + if (ret < 0) + return -EIO; + + ret = udev_enumerate_scan_devices(enumerate); + if (ret < 0) + return -EIO; + + devices = udev_enumerate_get_list_entry(enumerate); + + udev_list_entry_foreach(dev_list_entry, devices) { + const char *path; + path = udev_list_entry_get_name(dev_list_entry); + _D("subsystem : %s, path : %s", subsystem, path); + DD_LIST_APPEND(*list, (void*)path); + } + + return 0; +} + +static int changed_device(int argc, char **argv) +{ + int val = 0; + int *state = NULL; + int i; + + for (i = 0 ; i < argc ; i++) { + if (argv[i] == NULL) { + _E("param is failed"); + return -EINVAL; + } + } + + if (argc == 2) { + if (argv[1] == NULL) + val = 0; + else + val = atoi(argv[1]); + state = &val; + } + + if (strncmp(argv[0], USB_NAME, USB_NAME_LEN) == 0) + usb_chgdet_cb((void *)state); + else if (strncmp(argv[0], EARJACK_NAME, EARJACK_NAME_LEN) == 0) + earjack_chgdet_cb((void *)state); + else if (strncmp(argv[0], EARKEY_NAME, EARKEY_NAME_LEN) == 0) + earkey_chgdet_cb((void *)state); + else if (strncmp(argv[0], TVOUT_NAME, TVOUT_NAME_LEN) == 0) + tvout_chgdet_cb((void *)state); + else if (strncmp(argv[0], HDMI_NAME, HDMI_NAME_LEN) == 0) + hdmi_chgdet_cb((void *)state); + else if (strncmp(argv[0], HDCP_NAME, HDCP_NAME_LEN) == 0) { + hdcp_chgdet_cb((void *)state); + hdcp_hdmi_cb((void *)state); + } + else if (strncmp(argv[0], HDMI_AUDIO_NAME, HDMI_AUDIO_LEN) == 0) + hdmi_audio_chgdet_cb((void *)state); + else if (strncmp(argv[0], CRADLE_NAME, CRADLE_NAME_LEN) == 0) + cradle_chgdet_cb((void *)state); + else if (strncmp(argv[0], KEYBOARD_NAME, KEYBOARD_NAME_LEN) == 0) + keyboard_chgdet_cb((void *)state); + else if (strncmp(argv[0], POWER_SUBSYSTEM, POWER_SUPPLY_NAME_LEN) == 0) + power_supply((void *)state); + + return 0; +} + +static int changed_dev_earjack(int argc, char **argv) +{ + int val; + + /* TODO + * if we can recognize which type of jack is changed, + * should move following code for TVOUT to a new action function */ + /* + if(device_get_property(DEVTYPE_JACK,JACK_PROP_TVOUT_ONLINE,&val) == 0) + { + if (val == 1 && + vconf_get_int(VCONFKEY_SETAPPL_TVOUT_TVSYSTEM_INT, &val) == 0) { + _E("Start TV out %s\n", (val==0)?"NTSC":(val==1)?"PAL":"Unsupported"); + switch (val) { + case 0: // NTSC + launch_after_kill_if_exist(TVOUT_X_BIN, "-connect 2"); + break; + case 1: // PAL + launch_after_kill_if_exist(TVOUT_X_BIN, "-connect 3"); + break; + default: + _E("Unsupported TV system type:%d \n", val); + return -1; + } + // UI clone on + launch_evenif_exist(TVOUT_X_BIN, "-clone 1"); + ss_flags |= TVOUT_FLAG; + return vconf_set_int(VCONFKEY_SYSMAN_EARJACK, VCONFKEY_SYSMAN_EARJACK_TVOUT); + } + else { + if(val == 1) { + _E("TV type is not set. Please set the TV type first.\n"); + return -1; + } + if (ss_flags & TVOUT_FLAG) { + _E("TV out Jack is disconnected.\n"); + // UI clone off + launch_after_kill_if_exist(TVOUT_X_BIN, "-clone 0"); + ss_flags &= ~TVOUT_FLAG; + return vconf_set_int(VCONFKEY_SYSMAN_EARJACK, VCONFKEY_SYSMAN_EARJACK_REMOVED); + } + // Current event is not TV out event. Fall through + } + } + */ + if (device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_EARJACK_ONLINE, &val) == 0) { + if (CONNECTED(val)) + extcon_set_count(EXTCON_EARJACK); + return vconf_set_int(VCONFKEY_SYSMAN_EARJACK, val); + } + + return -1; +} + +static DBusMessage *dbus_cradle_handler(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int ret; + + ret = cradle_cb(NULL); + _I("cradle %d", ret); + + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *dbus_hdcp_hdmi_handler(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int ret; + + ret = hdcp_hdmi_cb(NULL); + _I("hdmi %d", ret); + + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *dbus_hdcp_handler(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int ret; + + ret = hdcp_chgdet_cb(NULL); + _I("hdcp %d", ret); + + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *dbus_hdmi_audio_handler(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int ret; + + ret = hdmi_audio_chgdet_cb(NULL); + _I("hdmi audio %d", ret); + + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *dbus_device_handler(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusError err; + DBusMessageIter iter; + DBusMessage *reply; + pid_t pid; + int ret; + int argc; + char *type_str; + char *argv[2]; + + dbus_error_init(&err); + + if (!dbus_message_get_args(msg, &err, + DBUS_TYPE_STRING, &type_str, + DBUS_TYPE_INT32, &argc, + DBUS_TYPE_STRING, &argv[0], + DBUS_TYPE_STRING, &argv[1], DBUS_TYPE_INVALID)) { + _E("there is no message"); + ret = -EINVAL; + goto out; + } + + if (argc < 0) { + _E("message is invalid!"); + ret = -EINVAL; + goto out; + } + + pid = get_edbus_sender_pid(msg); + if (kill(pid, 0) == -1) { + _E("%d process does not exist, dbus ignored!", pid); + ret = -ESRCH; + goto out; + } + + changed_device(argc, (char **)&argv); + +out: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + + return reply; +} + +static DBusMessage *dbus_battery_handler(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusError err; + DBusMessageIter iter; + DBusMessage *reply; + pid_t pid; + int ret; + int argc; + char *type_str; + char *argv[5]; + + dbus_error_init(&err); + + if (!dbus_message_get_args(msg, &err, + DBUS_TYPE_STRING, &type_str, + DBUS_TYPE_INT32, &argc, + DBUS_TYPE_STRING, &argv[0], + DBUS_TYPE_STRING, &argv[1], + DBUS_TYPE_STRING, &argv[2], + DBUS_TYPE_STRING, &argv[3], + DBUS_TYPE_STRING, &argv[4], DBUS_TYPE_INVALID)) { + _E("there is no message"); + ret = -EINVAL; + goto out; + } + + if (argc < 0) { + _E("message is invalid!"); + ret = -EINVAL; + goto out; + } + + pid = get_edbus_sender_pid(msg); + if (kill(pid, 0) == -1) { + _E("%d process does not exist, dbus ignored!", pid); + ret = -ESRCH; + goto out; + } + check_capacity_status(argv[0]); + check_charge_status(argv[1]); + check_health_status(argv[2]); + check_online_status(argv[3]); + check_present_status(argv[4]); + _I("%d %d %d %d %d %d %d %d", + battery.capacity, + battery.charge_full, + battery.charge_now, + battery.health, + battery.online, + battery.ovp, + battery.present, + battery.temp); + battery_noti(DEVICE_NOTI_BATT_CHARGE, DEVICE_NOTI_ON); + notify_action(PREDEF_DEVICE_CHANGED, 2, POWER_SUBSYSTEM, argv[0]); +out: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + + return reply; +} + +static DBusMessage *dbus_udev_handler(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusError err; + DBusMessageIter iter; + DBusMessage *reply; + pid_t pid; + int ret; + int argc; + char *type_str; + char *argv; + + dbus_error_init(&err); + + if (!dbus_message_get_args(msg, &err, + DBUS_TYPE_STRING, &type_str, + DBUS_TYPE_INT32, &argc, + DBUS_TYPE_STRING, &argv, DBUS_TYPE_INVALID)) { + _E("there is no message"); + ret = -EINVAL; + goto out; + } + + if (argc < 0) { + _E("message is invalid!"); + ret = -EINVAL; + goto out; + } + + pid = get_edbus_sender_pid(msg); + if (kill(pid, 0) == -1) { + _E("%d process does not exist, dbus ignored!", pid); + ret = -ESRCH; + goto out; + } + + if (strncmp(argv, "start", strlen("start")) == 0) { + uevent_kernel_control_start(); + uevent_udev_control_start(); + } else if (strncmp(argv, "stop", strlen("stop")) == 0) { + uevent_kernel_control_stop(); + uevent_udev_control_stop(); + } + +out: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + + return reply; +} + +static const struct edbus_method edbus_methods[] = { + { PREDEF_DEVICE_CHANGED,"siss", "i", dbus_device_handler }, + { PREDEF_POWER_CHANGED, "sisssss", "i", dbus_battery_handler }, + { PREDEF_UDEV_CONTROL, "sis", "i", dbus_udev_handler }, + { METHOD_GET_HDCP, NULL, "i", dbus_hdcp_handler }, + { METHOD_GET_HDMI_AUDIO,NULL, "i", dbus_hdmi_audio_handler }, + { METHOD_GET_HDMI, NULL, "i", dbus_hdcp_hdmi_handler }, + { METHOD_GET_CRADLE, NULL, "i", dbus_cradle_handler }, +}; + +static int booting_done(void *data) +{ + static int done = 0; + int ret; + int val; + + if (data == NULL) + return done; + done = (int)data; + if (done == 0) + return done; + + _I("booting done"); + + register_action(PREDEF_EARJACKCON, changed_dev_earjack, NULL, NULL); + register_action(PREDEF_DEVICE_CHANGED, changed_device, NULL, NULL); + + power_supply_timer_stop(); + power_supply_init(NULL); + + if (uevent_kernel_control_start() != 0) { + _E("fail uevent control init"); + return 0; + } + + if (uevent_udev_control_start() != 0) { + _E("fail uevent control init"); + return 0; + } + + /* set initial state for devices */ + input_device_number = 0; + cradle_chgdet_cb(NULL); + keyboard_chgdet_cb(NULL); + hdmi_chgdet_cb(NULL); + + ret = vconf_get_int(VCONFKEY_SYSMAN_CRADLE_STATUS, &val); + if (ret == 0 && val != 0) + launch_cradle(val); + return done; +} + +static int device_change_poweroff(void *data) +{ + uevent_kernel_control_stop(); + uevent_udev_control_stop(); + return 0; +} + +static void device_change_init(void *data) +{ + int ret; + + power_supply_timer_start(); + if (extcon_count_init() != 0) + _E("fail to init extcon files"); + register_notifier(DEVICE_NOTIFIER_POWEROFF, device_change_poweroff); + register_notifier(DEVICE_NOTIFIER_BOOTING_DONE, booting_done); + register_notifier(DEVICE_NOTIFIER_LCD, display_changed); + ret = register_edbus_method(DEVICED_PATH_SYSNOTI, edbus_methods, ARRAY_SIZE(edbus_methods)); + if (ret < 0) + _E("fail to init edbus method(%d)", ret); + + /* for simple noti change cb */ + emulator_add_callback("device_usb_chgdet", (void *)usb_chgdet_cb, NULL); + emulator_add_callback("device_ta_chgdet", (void *)ta_chgdet_cb, data); + emulator_add_callback("device_earjack_chgdet", (void *)earjack_chgdet_cb, data); + emulator_add_callback("device_earkey_chgdet", (void *)earkey_chgdet_cb, data); + emulator_add_callback("device_tvout_chgdet", (void *)tvout_chgdet_cb, data); + emulator_add_callback("device_hdmi_chgdet", (void *)hdmi_chgdet_cb, data); + emulator_add_callback("device_cradle_chgdet", (void *)cradle_chgdet_cb, data); + emulator_add_callback("device_keyboard_chgdet", (void *)keyboard_chgdet_cb, data); + + emulator_add_callback("unmount_ums", (void *)ums_unmount_cb, NULL); + + /* check and set earjack init status */ + changed_dev_earjack(0, NULL); + /* dbus noti change cb */ +#ifdef ENABLE_EDBUS_USE + e_dbus_init(); + conn = e_dbus_bus_get(DBUS_BUS_SYSTEM); + if (!conn) + _E("check system dbus running!\n"); + + e_dbus_signal_handler_add(conn, NULL, "/system/uevent/xxxxx", + "system.uevent.xxxxx", + "Change", cb_xxxxx_signaled, data); +#endif /* ENABLE_EDBUS_USE */ +} + +static void device_change_exit(void *data) +{ + int i; + unregister_notifier(DEVICE_NOTIFIER_POWEROFF, device_change_poweroff); + unregister_notifier(DEVICE_NOTIFIER_BOOTING_DONE, booting_done); + unregister_notifier(DEVICE_NOTIFIER_LCD, display_changed); + for (i = 0; i < ARRAY_SIZE(extcon_devices); i++) { + if (extcon_devices[i].fd <= 0) + continue; + close(extcon_devices[i].fd); + } + +} + +static const struct device_ops change_device_ops = { + .priority = DEVICE_PRIORITY_NORMAL, + .name = "device change", + .init = device_change_init, + .exit = device_change_exit, +}; + +DEVICE_OPS_REGISTER(&change_device_ops) diff --git a/src/core/device-handler.h b/src/core/device-handler.h new file mode 100644 index 0000000..071b882 --- /dev/null +++ b/src/core/device-handler.h @@ -0,0 +1,105 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 __DEVICE_HANDLER_H__ +#define __DEVICE_HANDLER_H__ + +#include "data.h" + +enum extcon_type { + EXTCON_TA = 0, + EXTCON_EARJACK, +}; + +enum device_change_type { + DEVICE_CHANGE_ABNORMAL = 0, + DEVICE_CHANGE_NORMAL = 1, +}; + +enum charge_full_type { + CHARGING_NOT_FULL = 0, + CHARGING_FULL = 1, +}; +enum charge_now_type { + CHARGER_ABNORMAL = -1, + CHARGER_DISCHARGING = 0, + CHARGER_CHARGING = 1, +}; +enum health_type { + HEALTH_BAD = 0, + HEALTH_GOOD = 1, +}; + +enum temp_type { + TEMP_LOW = 0, + TEMP_HIGH = 1, +}; + +enum present_type { + PRESENT_ABNORMAL = 0, + PRESENT_NORMAL = 1, +}; + +enum ovp_type { + OVP_NORMAL = 0, + OVP_ABNORMAL = 1, +}; + +enum battery_noti_type { + DEVICE_NOTI_BATT_CHARGE = 0, + DEVICE_NOTI_BATT_LOW, + DEVICE_NOTI_BATT_FULL, + DEVICE_NOTI_MAX, +}; + +enum battery_noti_status { + DEVICE_NOTI_OFF = 0, + DEVICE_NOTI_ON = 1, +}; + +enum dock_type { + DOCK_NONE = 0, + DOCK_SOUND = 7, +}; + +struct battery_status { + int capacity; + int charge_full; + int charge_now; + int health; + int present; + int online; + int temp; + int ovp; +}; + +struct battery_status battery; + +#define CONNECTED(val) ((val) != 0) + +/* Battery functions */ +void lowbat_monitor(void *data); + +int extcon_set_count(int index); + +int get_usb_state_direct(void); + +void sync_cradle_status(void); + +#endif /* __DEVICE_HANDLER_H__ */ diff --git a/src/core/device-notifier.c b/src/core/device-notifier.c new file mode 100644 index 0000000..a02584a --- /dev/null +++ b/src/core/device-notifier.c @@ -0,0 +1,120 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 "log.h" +#include "devices.h" +#include "device-notifier.h" +#include "list.h" +#include "common.h" + +struct device_notifier { + enum device_notifier_type status; + int (*func)(void *data); +}; + +static dd_list *device_notifier_list; + +#define FIND_NOTIFIER(a, b, d, e, f) \ + DD_LIST_FOREACH(a, b, d) \ + if (e == d->e && f == (d->f)) + +int register_notifier(enum device_notifier_type status, int (*func)(void *data)) +{ + dd_list *n; + struct device_notifier *data, *notifier; + + _I("%d, %x", status, func); + + if (!func) { + _E("invalid func address!"); + return -EINVAL; + } + + FIND_NOTIFIER(device_notifier_list, n, notifier, status, func) { + _E("function is already registered! [%d, %x]", + status, func); + return -EINVAL; + } + + notifier = malloc(sizeof(struct device_notifier)); + if (!notifier) { + _E("Fail to malloc for notifier!"); + return -ENOMEM; + } + + notifier->status = status; + notifier->func = func; + + DD_LIST_APPEND(device_notifier_list, notifier); + + return 0; +} + +int unregister_notifier(enum device_notifier_type status, int (*func)(void *data)) +{ + dd_list *n; + struct device_notifier *notifier; + + if (!func) { + _E("invalid func address!"); + return -EINVAL; + } + + FIND_NOTIFIER(device_notifier_list, n, notifier, status, func) { + _I("[%d, %x]", status, func); + DD_LIST_REMOVE(device_notifier_list, notifier); + free(notifier); + } + + return 0; +} + +void device_notify(enum device_notifier_type status, void *data) +{ + dd_list *n, *next; + struct device_notifier *notifier; + int cnt = 0; + + DD_LIST_FOREACH_SAFE(device_notifier_list, n, next, notifier) { + if (status == notifier->status) { + if (notifier->func) { + notifier->func(data); + cnt++; + } + } + } +} + +static void device_notifier_exit(void *data) +{ + dd_list *n; + struct device_notifier *notifier; + + DD_LIST_FOREACH(device_notifier_list, n, notifier) + DD_LIST_REMOVE(device_notifier_list, notifier); + free(notifier); +} + +static const struct device_ops notifier_device_ops = { + .priority = DEVICE_PRIORITY_NORMAL, + .name = "notifier", + .exit = device_notifier_exit, +}; + +DEVICE_OPS_REGISTER(¬ifier_device_ops) diff --git a/src/core/device-notifier.h b/src/core/device-notifier.h new file mode 100644 index 0000000..490a98d --- /dev/null +++ b/src/core/device-notifier.h @@ -0,0 +1,59 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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. + */ + + +#ifndef __DEVICE_NOTIFIER_H__ +#define __DEVICE_NOTIFIER_H__ + +enum device_notifier_type { + DEVICE_NOTIFIER_BOOTING_DONE, + DEVICE_NOTIFIER_HALLIC_OPEN, + DEVICE_NOTIFIER_HDMI, + DEVICE_NOTIFIER_LCD, + DEVICE_NOTIFIER_LCD_ESD, + DEVICE_NOTIFIER_MMC, + DEVICE_NOTIFIER_MMC_MOUNTED, + DEVICE_NOTIFIER_LOWBAT, + DEVICE_NOTIFIER_FULLBAT, + DEVICE_NOTIFIER_INPUT_ADD, + DEVICE_NOTIFIER_INPUT_REMOVE, + DEVICE_NOTIFIER_PROCESS_TERMINATED, + DEVICE_NOTIFIER_TOUCH_HARDKEY, + DEVICE_NOTIFIER_PMQOS_POWERSAVING, + DEVICE_NOTIFIER_PMQOS_LOWBAT, + DEVICE_NOTIFIER_PMQOS_EMERGENCY, + DEVICE_NOTIFIER_PMQOS_POWEROFF, + DEVICE_NOTIFIER_POWER_SUPPLY, + DEVICE_NOTIFIER_BATTERY_HEALTH, + DEVICE_NOTIFIER_BATTERY_OVP, + DEVICE_NOTIFIER_BATTERY_CHARGING, + DEVICE_NOTIFIER_POWEROFF, + DEVICE_NOTIFIER_POWEROFF_HAPTIC, + DEVICE_NOTIFIER_PMQOS, + DEVICE_NOTIFIER_POWERSAVER, + DEVICE_NOTIFIER_MAX, +}; + +/* + * This is for internal callback method. + */ +int register_notifier(enum device_notifier_type status, int (*func)(void *data)); +int unregister_notifier_del(enum device_notifier_type status, int (*func)(void *data)); +void device_notify(enum device_notifier_type status, void *value); + +#endif /* __DEVICE_NOTIFIER_H__ */ diff --git a/src/core/device-plugin.c b/src/core/device-plugin.c new file mode 100644 index 0000000..3048892 --- /dev/null +++ b/src/core/device-plugin.c @@ -0,0 +1,66 @@ +/* + * deviced + * + * Copyright (c) 2000 - 2013 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 "log.h" +#include "device-plugin.h" + +static void *dlopen_handle; + +int _ss_devman_plugin_init() +{ + char *error; + + dlopen_handle = dlopen(DEVMAN_PLUGIN_PATH, RTLD_NOW); + if (!dlopen_handle) { + _E("dlopen() failed"); + return -1; + } + + const OEM_sys_devman_plugin_interface *(*get_devman_plugin_interface) (); + get_devman_plugin_interface = dlsym(dlopen_handle, "OEM_sys_get_devman_plugin_interface"); + if ((error = dlerror()) != NULL) { + _E("dlsym() failed: %s", error); + dlclose(dlopen_handle); + return -1; + } + + plugin_intf = get_devman_plugin_interface(); + if (!plugin_intf) { + _E("get_devman_plugin_interface() failed"); + dlclose(dlopen_handle); + return -1; + } + + return 0; +} + + +int _ss_devman_plugin_fini() +{ + if (dlopen_handle) { + dlclose(dlopen_handle); + } + + return 0; +} + + diff --git a/src/core/device-plugin.h b/src/core/device-plugin.h new file mode 100644 index 0000000..3c6df87 --- /dev/null +++ b/src/core/device-plugin.h @@ -0,0 +1,32 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 __SS_DEVICE_PLUGIN_H__ +#define __SS_DEVICE_PLUGIN_H__ + +#include "devman-plugin-intf.h" + +#define DEVMAN_PLUGIN_PATH "/usr/lib/libslp_devman_plugin.so" + +int _ss_devman_plugin_init(void); +int _ss_devman_plugin_fini(void); + +const OEM_sys_devman_plugin_interface *plugin_intf; + +#endif /* __SS_DEVICE_PLUGIN_H__ */ diff --git a/src/core/devices.c b/src/core/devices.c new file mode 100644 index 0000000..da2292f --- /dev/null +++ b/src/core/devices.c @@ -0,0 +1,76 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 "log.h" +#include "list.h" +#include "common.h" +#include "devices.h" + +static dd_list *dev_head; + +void add_device(const struct device_ops *dev) +{ + if (dev->priority == DEVICE_PRIORITY_HIGH) + DD_LIST_PREPEND(dev_head, dev); + else + DD_LIST_APPEND(dev_head, dev); +} + +void remove_device(const struct device_ops *dev) +{ + DD_LIST_REMOVE(dev_head, dev); +} + +const struct device_ops *find_device(const char *name) +{ + dd_list *elem; + const struct device_ops *dev; + + DD_LIST_FOREACH(dev_head, elem, dev) { + if (!strcmp(dev->name, name)) + return dev; + } + return NULL; +} + +void devices_init(void *data) +{ + dd_list *elem; + const struct device_ops *dev; + + DD_LIST_FOREACH(dev_head, elem, dev) { + _D("[%s] initialize", dev->name); + if (dev->init) + dev->init(data); + } +} + +void devices_exit(void *data) +{ + dd_list *elem; + const struct device_ops *dev; + + DD_LIST_FOREACH(dev_head, elem, dev) { + _D("[%s] deinitialize", dev->name); + if (dev->exit) + dev->exit(data); + } +} diff --git a/src/core/devices.h b/src/core/devices.h new file mode 100644 index 0000000..b4537ad --- /dev/null +++ b/src/core/devices.h @@ -0,0 +1,89 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 __DEVICES_H__ +#define __DEVICES_H__ + +#include +#include "common.h" + +enum device_priority { + DEVICE_PRIORITY_NORMAL = 0, + DEVICE_PRIORITY_HIGH, +}; + +struct device_ops { + enum device_priority priority; + char *name; + void (*init) (void *data); + void (*exit) (void *data); + int (*start) (void); + int (*stop) (void); + int (*status) (void); +}; + +enum device_ops_status { + DEVICE_OPS_STATUS_UNINIT, + DEVICE_OPS_STATUS_START, + DEVICE_OPS_STATUS_STOP, + DEVICE_OPS_STATUS_MAX, +}; + +void devices_init(void *data); +void devices_exit(void *data); + +static inline int device_start(const struct device_ops *dev) +{ + if (dev && dev->start) + return dev->start(); + + return -EINVAL; +} + +static inline int device_stop(const struct device_ops *dev) +{ + if (dev && dev->stop) + return dev->stop(); + + return -EINVAL; +} + +static inline int device_get_status(const struct device_ops *dev) +{ + if (dev && dev->status) + return dev->status(); + + return -EINVAL; +} + +#define DEVICE_OPS_REGISTER(dev) \ +static void __CONSTRUCTOR__ module_init(void) \ +{ \ + add_device(dev); \ +} \ +static void __DESTRUCTOR__ module_exit(void) \ +{ \ + remove_device(dev); \ +} + +void add_device(const struct device_ops *dev); +void remove_device(const struct device_ops *dev); +const struct device_ops *find_device(const char *name); + +#endif diff --git a/src/core/edbus-handler.c b/src/core/edbus-handler.c new file mode 100644 index 0000000..f03a051 --- /dev/null +++ b/src/core/edbus-handler.c @@ -0,0 +1,587 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include +#include "core/log.h" +#include "core/data.h" +#include "core/edbus-handler.h" +#include "core/common.h" +#include "core/device-notifier.h" +#include "core/list.h" + +#define EDBUS_INIT_RETRY_COUNT 5 +#define NAME_OWNER_CHANGED "NameOwnerChanged" +#define NAME_OWNER_MATCH "type='signal',sender='org.freedesktop.DBus',\ + path='/org/freedesktop/DBus',interface='org.freedesktop.DBus',\ + member='NameOwnerChanged',arg0='%s'" + +/* -1 is a default timeout value, it's converted to 25*1000 internally. */ +#define DBUS_REPLY_TIMEOUT (-1) +#define RETRY_MAX 5 + +struct edbus_list{ + char *signal_name; + E_DBus_Signal_Handler *handler; +}; + +static struct edbus_object { + const char *path; + const char *interface; + E_DBus_Object *obj; + E_DBus_Interface *iface; +} edbus_objects[] = { + { DEVICED_PATH_CORE , DEVICED_INTERFACE_CORE , NULL, NULL }, + { DEVICED_PATH_DISPLAY, DEVICED_INTERFACE_DISPLAY, NULL, NULL }, + { DEVICED_PATH_PASS , DEVICED_INTERFACE_PASS , NULL, NULL }, + { DEVICED_PATH_HALL , DEVICED_INTERFACE_HALL , NULL, NULL }, + { DEVICED_PATH_POWER , DEVICED_INTERFACE_POWER , NULL, NULL }, + { DEVICED_PATH_STORAGE, DEVICED_INTERFACE_STORAGE, NULL, NULL }, + { DEVICED_PATH_HAPTIC , DEVICED_INTERFACE_HAPTIC , NULL, NULL }, + { DEVICED_PATH_LED , DEVICED_INTERFACE_LED , NULL, NULL }, + { DEVICED_PATH_MMC , DEVICED_INTERFACE_MMC , NULL, NULL }, + { DEVICED_PATH_PROCESS, DEVICED_INTERFACE_PROCESS, NULL, NULL }, + { DEVICED_PATH_KEY , DEVICED_INTERFACE_KEY , NULL, NULL }, + { DEVICED_PATH_CPU , DEVICED_INTERFACE_CPU , NULL, NULL }, + { DEVICED_PATH_PMQOS , DEVICED_INTERFACE_PMQOS , NULL, NULL }, + { DEVICED_PATH_SYSNOTI, DEVICED_INTERFACE_SYSNOTI, NULL, NULL }, + { DEVICED_PATH_USBHOST, DEVICED_INTERFACE_USBHOST, NULL, NULL }, + { DEVICED_PATH_EXTCON , DEVICED_INTERFACE_EXTCON , NULL, NULL }, + { DEVICED_PATH_BATTERY, DEVICED_INTERFACE_BATTERY, NULL, NULL }, + { DEVICED_PATH_BOARD, DEVICED_INTERFACE_BOARD, NULL, NULL }, + { DEVICED_PATH_TESTMODE, DEVICED_INTERFACE_TESTMODE, NULL, NULL}, + /* Add new object & interface here*/ +}; + +static dd_list *edbus_handler_list; +static dd_list *edbus_watch_list; +static int edbus_init_val; +static DBusConnection *conn; +static E_DBus_Connection *edbus_conn; +static DBusPendingCall *edbus_request_name; + +static int register_edbus_interface(struct edbus_object *object) +{ + int ret; + + if (!object) { + _E("object is invalid value!"); + return -1; + } + + object->obj = e_dbus_object_add(edbus_conn, object->path, NULL); + if (!object->obj) { + _E("fail to add edbus obj"); + return -1; + } + + object->iface = e_dbus_interface_new(object->interface); + if (!object->iface) { + _E("fail to add edbus interface"); + return -1; + } + + e_dbus_object_interface_attach(object->obj, object->iface); + + return 0; +} + +E_DBus_Interface *get_edbus_interface(const char *path) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(edbus_objects); i++) + if (!strcmp(path, edbus_objects[i].path)) + return edbus_objects[i].iface; + + return NULL; +} + +pid_t get_edbus_sender_pid(DBusMessage *msg) +{ + const char *sender; + DBusMessage *send_msg; + DBusPendingCall *pending; + DBusMessageIter iter; + int ret; + pid_t pid; + + if (!msg) { + _E("invalid argument!"); + return -1; + } + + sender = dbus_message_get_sender(msg); + if (!sender) { + _E("invalid sender!"); + return -1; + } + + send_msg = dbus_message_new_method_call(DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS, + "GetConnectionUnixProcessID"); + if (!send_msg) { + _E("invalid send msg!"); + return -1; + } + + ret = dbus_message_append_args(send_msg, DBUS_TYPE_STRING, + &sender, DBUS_TYPE_INVALID); + if (!ret) { + _E("fail to append args!"); + dbus_message_unref(send_msg); + return -1; + } + + pending = e_dbus_message_send(edbus_conn, send_msg, NULL, -1, NULL); + if (!pending) { + _E("pending is null!"); + dbus_message_unref(send_msg); + return -1; + } + + dbus_message_unref(send_msg); + + /* block until reply is received */ + dbus_pending_call_block(pending); + + msg = dbus_pending_call_steal_reply(pending); + dbus_pending_call_unref(pending); + if (!msg) { + _E("reply msg is null!"); + return -1; + } + + dbus_message_iter_init(msg, &iter); + dbus_message_iter_get_basic(&iter, &pid); + dbus_message_unref(msg); + + return pid; +} + +static void unregister_edbus_signal_handle(void) +{ + dd_list *tmp; + struct edbus_list *entry; + + DD_LIST_FOREACH(edbus_handler_list, tmp, entry) { + e_dbus_signal_handler_del(edbus_conn, entry->handler); + DD_LIST_REMOVE(edbus_handler_list, entry); + free(entry->signal_name); + free(entry); + } +} + +int register_edbus_signal_handler(const char *path, const char *interface, + const char *name, E_DBus_Signal_Cb cb) +{ + dd_list *tmp; + struct edbus_list *entry; + E_DBus_Signal_Handler *handler; + + DD_LIST_FOREACH(edbus_handler_list, tmp, entry) { + if (strncmp(entry->signal_name, name, strlen(name)) == 0) + return -EEXIST; + } + + handler = e_dbus_signal_handler_add(edbus_conn, NULL, path, + interface, name, cb, NULL); + + if (!handler) { + _E("fail to add edbus handler"); + return -ENOMEM; + } + + entry = malloc(sizeof(struct edbus_list)); + + if (!entry) { + _E("Malloc failed"); + return -ENOMEM; + } + + entry->signal_name = strndup(name, strlen(name)); + + if (!entry->signal_name) { + _E("Malloc failed"); + free(entry); + return -ENOMEM; + } + + entry->handler = handler; + DD_LIST_PREPEND(edbus_handler_list, entry); + if (!edbus_handler_list) { + _E("eina_list_prepend failed"); + free(entry->signal_name); + free(entry); + return -ENOMEM; + } + return 0; +} + +int broadcast_edbus_signal(const char *path, const char *interface, + const char *name, const char *sig, char *param[]) +{ + DBusMessage *msg; + DBusMessageIter iter; + int r; + + msg = dbus_message_new_signal(path, interface, name); + if (!msg) { + _E("fail to allocate new %s.%s signal", interface, name); + return -EPERM; + } + + dbus_message_iter_init_append(msg, &iter); + r = append_variant(&iter, sig, param); + if (r < 0) { + _E("append_variant error(%d)", r); + return -EPERM; + } + + e_dbus_message_send(edbus_conn, msg, NULL, -1, NULL); + + dbus_message_unref(msg); + return 0; +} + +static DBusHandlerResult message_filter(DBusConnection *connection, + DBusMessage *message, void *data) +{ + char match[256]; + int ret; + const char *iface, *member, *arg = NULL; + struct watch *watch; + dd_list *n; + + if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_SIGNAL) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + iface = dbus_message_get_interface(message); + member = dbus_message_get_member(message); + + if (strcmp(iface, DBUS_INTERFACE_DBUS)) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + if (strcmp(member, NAME_OWNER_CHANGED)) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + ret = dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &arg, + DBUS_TYPE_INVALID); + if (!ret) { + _E("no message"); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + _D("Argument : %s", arg); + + DD_LIST_FOREACH(edbus_watch_list, n, watch) { + if (strcmp(arg, watch->name)) continue; + + if (watch->func) + watch->func(watch->name, watch->id); + + DD_LIST_REMOVE(edbus_watch_list, watch); + free(watch->name); + free(watch); + } + + /* remove registered sender */ + snprintf(match, sizeof(match), NAME_OWNER_MATCH, arg); + dbus_bus_remove_match(conn, match, NULL); + + + if (DD_LIST_LENGTH(edbus_watch_list) == 0) { + dbus_connection_remove_filter(conn, message_filter, NULL); + _I("remove message filter, no watcher!"); + } + + return DBUS_HANDLER_RESULT_HANDLED; +} + +int register_edbus_watch(DBusMessage *msg, enum watch_id id, int (*func)(char *name, enum watch_id id)) +{ + char match[256]; + const char *sender; + struct watch *watch; + dd_list *n; + int ret; + bool matched = false; + + if (!msg) { + _E("invalid argument!"); + return -EINVAL; + } + + sender = dbus_message_get_sender(msg); + if (!sender) { + _E("invalid sender!"); + return -EINVAL; + } + + /* check the sender&id is already registered */ + DD_LIST_FOREACH(edbus_watch_list, n, watch) { + if (strcmp(sender, watch->name)) + continue; + if (id != watch->id) { + matched = true; + continue; + } + + _I("%s(%d) is already watched!", watch->name, watch->id); + + return 0; + } + + watch = malloc(sizeof(struct watch)); + if (!watch) { + _E("Fail to malloc for watch!"); + return -ENOMEM; + } + + watch->id = id; + watch->func = func; + watch->name = strndup(sender, strlen(sender)); + + if (!watch->name) { + _E("Fail to malloc for watch name"); + free(watch); + return -ENOMEM; + } + + /* Add message filter */ + if (DD_LIST_LENGTH(edbus_watch_list) == 0) { + ret = dbus_connection_add_filter(conn, message_filter, NULL, NULL); + if (!ret) { + _E("fail to add message filter!"); + free(watch->name); + free(watch); + return -ENOMEM; + } + _I("success to add message filter!"); + } + + /* Add watch to watch list */ + DD_LIST_APPEND(edbus_watch_list, watch); + + if (!matched) { + snprintf(match, sizeof(match), NAME_OWNER_MATCH, watch->name); + dbus_bus_add_match(conn, match, NULL); + } + + _I("%s(%d) is watched by dbus!", watch->name, watch->id); + + return 0; +} + +int unregister_edbus_watch(DBusMessage *msg, enum watch_id id) +{ + char match[256]; + const char *sender; + struct watch *watch; + dd_list *n; + bool matched = false; + + if (!msg) { + _E("invalid argument!"); + return -EINVAL; + } + + sender = dbus_message_get_sender(msg); + if (!sender) { + _E("invalid sender!"); + return -EINVAL; + } + + DD_LIST_FOREACH(edbus_watch_list, n, watch) { + if (strcmp(sender, watch->name)) + continue; + + if (id != watch->id) { + matched = true; + continue; + } + DD_LIST_REMOVE(edbus_watch_list, watch); + free(watch->name); + free(watch); + } + + /* remove match */ + if (!matched) { + snprintf(match, sizeof(match), NAME_OWNER_MATCH, sender); + dbus_bus_remove_match(conn, match, NULL); + + if (DD_LIST_LENGTH(edbus_watch_list) == 0) + dbus_connection_remove_filter(conn, message_filter, + NULL); + } + + return 0; +} + +static void unregister_edbus_watch_all(void) +{ + char match[256]; + dd_list *n; + struct watch *watch; + + if (DD_LIST_LENGTH(edbus_watch_list) > 0) + dbus_connection_remove_filter(conn, message_filter, NULL); + + DD_LIST_FOREACH(edbus_watch_list, n, watch) { + snprintf(match, sizeof(match), NAME_OWNER_MATCH, watch->name); + dbus_bus_remove_match(conn, match, NULL); + DD_LIST_REMOVE(edbus_watch_list, watch); + free(watch->name); + free(watch); + } +} + +int register_edbus_method(const char *path, const struct edbus_method *edbus_methods, int size) +{ + E_DBus_Interface *iface; + int ret; + int i; + + iface = get_edbus_interface(path); + + if (!iface) { + _E("fail to get edbus interface!"); + return -ENODEV; + } + + for (i = 0; i < size; i++) { + ret = e_dbus_interface_method_add(iface, + edbus_methods[i].member, + edbus_methods[i].signature, + edbus_methods[i].reply_signature, + edbus_methods[i].func); + if (!ret) { + _E("fail to add method %s!", edbus_methods[i].member); + return -EINVAL; + } + } + + return 0; +} + +static void request_name_cb(void *data, DBusMessage *msg, DBusError *error) +{ + DBusError err; + unsigned int val; + int r; + + if (!msg) { + _D("invalid DBusMessage!"); + return; + } + + dbus_error_init(&err); + r = dbus_message_get_args(msg, &err, DBUS_TYPE_UINT32, &val, DBUS_TYPE_INVALID); + if (!r) { + _E("no message : [%s:%s]", err.name, err.message); + dbus_error_free(&err); + return; + } + + _I("Request Name reply : %d", val); +} + +void edbus_init(void *data) +{ + DBusError error; + int retry = 0; + int i, ret; + + dbus_threads_init_default(); + dbus_error_init(&error); + + do { + edbus_init_val = e_dbus_init(); + if (edbus_init_val) + break; + if (retry == EDBUS_INIT_RETRY_COUNT) { + _E("fail to init edbus"); + return; + } + retry++; + } while (retry <= EDBUS_INIT_RETRY_COUNT); + + retry = 0; + do { + conn = dbus_bus_get(DBUS_BUS_SYSTEM, &error); + if (conn) + break; + if (retry == EDBUS_INIT_RETRY_COUNT) { + _E("fail to get dbus"); + goto out1; + } + retry++; + } while (retry <= EDBUS_INIT_RETRY_COUNT); + + retry = 0; + do { + edbus_conn = e_dbus_connection_setup(conn); + if (edbus_conn) + break; + if (retry == EDBUS_INIT_RETRY_COUNT) { + _E("fail to get edbus"); + goto out2; + } + retry++; + } while (retry <= EDBUS_INIT_RETRY_COUNT); + + retry = 0; + do { + edbus_request_name = e_dbus_request_name(edbus_conn, DEVICED_BUS_NAME, + DBUS_NAME_FLAG_REPLACE_EXISTING, request_name_cb, NULL); + if (edbus_request_name) + break; + if (retry == EDBUS_INIT_RETRY_COUNT) { + _E("fail to request edbus name"); + goto out3; + } + retry++; + } while (retry <= EDBUS_INIT_RETRY_COUNT); + + for (i = 0; i < ARRAY_SIZE(edbus_objects); i++) { + ret = register_edbus_interface(&edbus_objects[i]); + if (ret < 0) { + _E("fail to add obj & interface for %s", + edbus_objects[i].interface); + return; + } + _D("add new obj for %s", edbus_objects[i].interface); + } + return; + +out3: + e_dbus_connection_close(edbus_conn); +out2: + dbus_connection_set_exit_on_disconnect(conn, FALSE); +out1: + e_dbus_shutdown(); +} + +void edbus_exit(void *data) +{ + unregister_edbus_signal_handle(); + unregister_edbus_watch_all(); + e_dbus_connection_close(edbus_conn); + e_dbus_shutdown(); +} diff --git a/src/core/edbus-handler.h b/src/core/edbus-handler.h new file mode 100644 index 0000000..88f2cd2 --- /dev/null +++ b/src/core/edbus-handler.h @@ -0,0 +1,62 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 __EDBUS_HANDLE_H__ +#define __EDBUS_HANDLE_H__ + +#include +#include "shared/dbus.h" + +struct edbus_method { + const char *member; + const char *signature; + const char *reply_signature; + E_DBus_Method_Cb func; +}; + +enum watch_id { + WATCH_DISPLAY_AUTOBRIGHTNESS_MIN, + WATCH_DISPLAY_LCD_TIMEOUT, + WATCH_DISPLAY_LOCK_STATE, + WATCH_DISPLAY_HOLD_BRIGHTNESS, + WATCH_HAPTIC_OPEN_DEVICE, + WATCH_POWER_RESETKEY_DISABLE, + WATCH_POWER_WAKEUPKEY, +}; + +struct watch { + enum watch_id id; + char *name; + int (*func)(char *name, enum watch_id id); +}; + +int register_edbus_method(const char *path, const struct edbus_method *edbus_methods, int size); +int register_edbus_signal_handler(const char *path, const char *interface, + const char *name, E_DBus_Signal_Cb cb); +E_DBus_Interface *get_edbus_interface(const char *path); +pid_t get_edbus_sender_pid(DBusMessage *msg); +int broadcast_edbus_signal(const char *path, const char *interface, + const char *name, const char *sig, char *param[]); +int register_edbus_watch(DBusMessage *msg, enum watch_id id, int (*func)(char *name, enum watch_id id)); +int unregister_edbus_watch(DBusMessage *msg, enum watch_id id); + +void edbus_init(void *data); +void edbus_exit(void *data); + +#endif /* __EDBUS_HANDLE_H__ */ diff --git a/src/core/emulator.h b/src/core/emulator.h new file mode 100644 index 0000000..71a5edf --- /dev/null +++ b/src/core/emulator.h @@ -0,0 +1,35 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 __EMULATOR_H__ +#define __EMULATOR_H__ + +#include "noti.h" + +#ifdef MOBILE_EMULATOR +static inline int emulator_add_callback(const char *noti, + void (*cb) (void *), void *data) +{ + return noti_add(noti, cb, data); +} +#else +#define emulator_add_callback(a, b, c) do { } while (0) +#endif + +#endif diff --git a/src/core/execute.c b/src/core/execute.c new file mode 100755 index 0000000..1c664da --- /dev/null +++ b/src/core/execute.c @@ -0,0 +1,93 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include +#include +#include +#include +#include +#include +#include + +#include "log.h" + +static int parent(pid_t pid) +{ + int status; + + /* wait for child */ + if (waitpid(pid, &status, 0) != -1) { + /* terminated normally */ + if (WIFEXITED(status)) { + _I("%d terminated by exit(%d)", pid, WEXITSTATUS(status)); + return WEXITSTATUS(status); + } else if (WIFSIGNALED(status)) + _I("%d terminated by signal %d", pid, WTERMSIG(status)); + else if (WIFSTOPPED(status)) + _I("%d stopped by signal %d", pid, WSTOPSIG(status)); + } else + _I("%d waitpid() failed : %s", pid, strerror(errno)); + + return -EAGAIN; +} + +static void child(int argc, const char *argv[]) +{ + int i, r; + + for (i = 0; i < _NSIG; ++i) + signal(i, SIG_DFL); + + r = execv(argv[0], (char **)argv); + if (r < 0) + exit(EXIT_FAILURE); +} + +int run_child(int argc, const char *argv[]) +{ + pid_t pid; + struct sigaction act, oldact; + int r; + + if (!argv) + return -EINVAL; + + /* Use default signal handler */ + act.sa_handler = SIG_DFL; + act.sa_sigaction = NULL; + act.sa_flags = 0; + sigemptyset(&act.sa_mask); + + if (sigaction(SIGCHLD, &act, &oldact) < 0) + return -errno; + + pid = fork(); + if (pid < 0) { + _E("failed to fork"); + r = -errno; + } else if (pid == 0) { + child(argc, argv); + } else + r = parent(pid); + + if (sigaction(SIGCHLD, &oldact, NULL) < 0) + _E("failed to restore sigaction"); + + return r; +} diff --git a/src/core/launch.c b/src/core/launch.c new file mode 100644 index 0000000..eb59419 --- /dev/null +++ b/src/core/launch.c @@ -0,0 +1,342 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "vconf-keys.h" +#include "log.h" +#include "launch.h" +#include "common.h" + +#define MAX_ARGS 255 + +#define _S(str) ((str == NULL) ? "" : str) + +static int set_current_lang(void) +{ + char *lang; + int ret; + + lang = (char *)vconf_get_str(VCONFKEY_LANGSET); + if (lang == NULL) + return -1; + ret = setenv("LANG", lang, 1); + if (ret < 0) + return -1; + free(lang); + return 0; +} + + +static void prepare_exec(void) +{ + int i; + int maxfd; + FILE *fp; + + maxfd = getdtablesize(); + for (i = 3; i < maxfd; i++) + close(i); + + for (i = 0; i < _NSIG; i++) + signal(i, SIG_DFL); + +} + +static int parse_cmd(const char *cmdline, char **argv, int max_args) +{ + const char *p; + char *buf, *bufp; + int nargs = 0; + int escape = 0, squote = 0, dquote = 0; + int bufsize; + + if (cmdline == NULL || cmdline[0] == '\0') + return -1; + bufsize = strlen(cmdline)+1; + bufp = buf = malloc(bufsize); + if (bufp == NULL || buf == NULL) + return -1; + memset(buf, 0, bufsize); + p = cmdline; + + while (*p) { + if (escape) { + *bufp++ = *p; + escape = 0; + } else { + switch (*p) { + case '\\': + escape = 1; + break; + case '"': + if (squote) + *bufp++ = *p; + else + dquote = !dquote; + break; + case '\'': + if (dquote) + *bufp++ = *p; + else + squote = !squote; + break; + case ' ': + if (!squote && !dquote) { + *bufp = '\0'; + if (nargs < max_args) + argv[nargs++] = strdup(buf); + bufp = buf; + break; + } + default: + *bufp++ = *p; + break; + } + } + p++; + } + + if (bufp != buf) { + *bufp = '\0'; + if (nargs < max_args) + argv[nargs++] = strdup(buf); + } + + argv[nargs++] = NULL; + + free(buf); + return nargs; +} + +int launch_app_with_nice(const char *file, char *const argv[], pid_t *pid, int _nice) +{ + int ret; + int _pid; + + if (file == NULL || access(file, X_OK) != 0) { + _E("launch app error: Invalid input"); + errno = EINVAL; + return -1; + } + + if (pid && (*pid > 0 && kill(*pid, 0) != -1)) + return *pid; + + _pid = fork(); + + if (_pid == -1) { + _E("fork error: %s", strerror(errno)); + /* keep errno */ + return -1; + } + + if (_pid > 0) { /* parent */ + if (pid) + *pid = _pid; + return _pid; + } + + /* child */ + prepare_exec(); + + ret = nice(_nice); + + if (ret == -1 && errno != 0) + _E("nice error: %s", strerror(errno)); + + ret = execvp(file, argv); + + /* If failed... */ + _E("exec. error: %s", strerror(errno)); + return -2; +} + +int launch_app_cmd_with_nice(const char *cmdline, int _nice) +{ + int i; + int nargs; + int ret; + char *argv[MAX_ARGS + 1]; + + nargs = parse_cmd(cmdline, argv, MAX_ARGS + 1); + if (nargs == -1) { + _E("launch app error: Invalid input"); + errno = EINVAL; + return -1; + } + + ret = launch_app_with_nice(argv[0], argv, NULL, _nice); + + for (i = 0; i < nargs; i++) + free(argv[i]); + + return ret; +} + +int launch_app_cmd(const char *cmdline) +{ + return launch_app_cmd_with_nice(cmdline, 0); +} + +int launch_if_noexist(const char *execpath, const char *arg, ...) +{ + char *buf; + int pid; + int nice_value = 0; + int flag = 0; + int buf_size = -1; + va_list argptr; + + if (execpath == NULL) { + errno = EINVAL; + return -1; + } + if (pid = get_exec_pid(execpath) > 0) + return pid; + + va_start(argptr, arg); + flag = va_arg(argptr, int); + + if (flag & LAUNCH_NICE) + nice_value = va_arg(argptr, int); + + va_end(argptr); + + set_current_lang(); + arg = _S(arg); + + buf_size = strlen(execpath) + strlen(arg) + 10; + buf = malloc(buf_size); + if (buf == NULL) { + /* Do something for not enought memory error */ + _E("Malloc failed"); + return -1; + } + + snprintf(buf, buf_size, "%s %s", execpath, arg); + //pid = launch_app_cmd_with_nice(buf, nice_value, flag); + pid = launch_app_cmd_with_nice(buf, nice_value); + if (pid == -2) + exit(EXIT_FAILURE); + free(buf); + + return pid; +} + +int launch_evenif_exist(const char *execpath, const char *arg, ...) +{ + char *buf; + int pid; + int nice_value = 0; + int flag = 0; + int buf_size = -1; + + va_list argptr; + + if (execpath == NULL) { + errno = EINVAL; + return -1; + } + + va_start(argptr, arg); + flag = va_arg(argptr, int); + + if (flag & LAUNCH_NICE) + nice_value = va_arg(argptr, int); + + va_end(argptr); + + set_current_lang(); + + arg = _S(arg); + + buf_size = strlen(execpath) + strlen(arg) + 10; + buf = malloc(buf_size); + if (buf == NULL) { + // Do something for not enought memory error + _E("Malloc failed"); + return -1; + } + + snprintf(buf, buf_size, "%s %s", execpath, arg); + //pid = launch_app_cmd_with_nice(buf, nice_value, flag); + pid = launch_app_cmd_with_nice(buf, nice_value); + if (pid == -2) + exit(EXIT_FAILURE); + free(buf); + + return pid; +} + +int launch_after_kill_if_exist(const char *execpath, const char *arg, ...) +{ + char *buf; + int pid; + int flag; + int buf_size; + int exist_pid; + va_list argptr; + int nice_value = 0; + + if (execpath == NULL) { + errno = EINVAL; + return -1; + } + + if ((exist_pid = get_exec_pid(execpath)) > 0) + kill(exist_pid, SIGTERM); + + va_start(argptr, arg); + flag = va_arg(argptr, int); + + if (flag & LAUNCH_NICE) + nice_value = va_arg(argptr, int); + + va_end(argptr); + + set_current_lang(); + + arg = _S(arg); + + buf_size = strlen(execpath) + strlen(arg) + 10; + buf = malloc(buf_size); + if (buf == NULL) { + /* Do something for not enought memory error */ + _E("Malloc Failed"); + return -1; + } + + snprintf(buf, buf_size, "%s %s", execpath, arg); + //pid = launch_app_cmd_with_nice(buf, nice_value, flag); + pid = launch_app_cmd_with_nice(buf, nice_value); + if (pid == -2) /* It means that the 'execvp' return -1 */ + exit(EXIT_FAILURE); + free(buf); + + return pid; + +} diff --git a/src/core/launch.h b/src/core/launch.h new file mode 100644 index 0000000..495512c --- /dev/null +++ b/src/core/launch.h @@ -0,0 +1,29 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 __LAUNCH_H__ +#define __LAUNCH_H__ + +#define LAUNCH_NICE 0x0002 + +int launch_if_noexist(const char *execpath, const char *arg, ...); +int launch_evenif_exist(const char *execpath, const char *arg, ...); +int launch_after_kill_if_exist(const char *execpath, const char *arg, ...); + +#endif /* __LAUNCH_H__ */ diff --git a/src/core/list.h b/src/core/list.h new file mode 100644 index 0000000..b688dec --- /dev/null +++ b/src/core/list.h @@ -0,0 +1,83 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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. + */ + +#ifndef __LIST_H__ +#define __LIST_H__ + +#include +#include + +#define EINA_LIST_APPEND(a, b) \ + a = eina_list_append(a, b) + +#define EINA_LIST_REMOVE(a, b) \ + a = eina_list_remove(a, b) + +#define EINA_LIST_REMOVE_LIST(a, b) \ + a = eina_list_remove_list(a, b) + +#define EINA_LIST_FREE_LIST(a) \ + a = eina_list_free(a) + +#define EINA_LIST_PROMOTE_LIST(a, b) \ + a = eina_list_promote_list(a, b) + +#ifdef EINA_LIST +typedef Eina_List dd_list; +#define DD_LIST_PREPEND(a, b) \ + a = eina_list_prepend(a, b) +#define DD_LIST_APPEND(a, b) \ + a = eina_list_append(a, b) +#define DD_LIST_REMOVE(a, b) \ + a = eina_list_remove(a, b) +#define DD_LIST_LENGTH(a) \ + eina_list_count(a) +#define DD_LIST_NTH(a, b) \ + eina_list_nth(a, b) +#define DD_LIST_FREE_LIST(a) \ + a = eina_list_free(a) +#define DD_LIST_FOREACH(head, elem, node) \ + EINA_LIST_FOREACH(head, elem, node) +#define DD_LIST_FOREACH_SAFE(head, elem, elem_next, node) \ + EINA_LIST_FOREACH_SAFE(head, elem, elem_next, node) + +#else +#include +typedef GList dd_list; +#define DD_LIST_PREPEND(a, b) \ + a = g_list_prepend(a, (gpointer)b) +#define DD_LIST_APPEND(a, b) \ + a = g_list_append(a, (gpointer)b) +#define DD_LIST_REMOVE(a, b) \ + a = g_list_remove(a, (gpointer)b) +#define DD_LIST_LENGTH(a) \ + g_list_length(a) +#define DD_LIST_NTH(a, b) \ + g_list_nth_data(a, b) +#define DD_LIST_FREE_LIST(a) \ + g_list_free(a) +#define DD_LIST_FOREACH(head, elem, node) \ + for (elem = head, node = NULL; elem && ((node = elem->data) != NULL); elem = elem->next, node = NULL) +#define DD_LIST_FOREACH_SAFE(head, elem, elem_next, node) \ + for (elem = head, elem_next = g_list_next(elem), node = NULL; \ + elem && ((node = elem->data) != NULL); \ + elem = elem_next, elem_next = g_list_next(elem), node = NULL) + +#endif + +#endif diff --git a/src/core/log.h b/src/core/log.h new file mode 100644 index 0000000..758151e --- /dev/null +++ b/src/core/log.h @@ -0,0 +1,34 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 __LOG_H__ +#define __LOG_H__ + +#ifdef ENABLE_DEVICED_DLOG +#define ENABLE_DLOG +#endif + +#ifdef LOG_TAG +#undef LOG_TAG +#endif + +#define LOG_TAG "DEVICED" +#include "shared/log-macro.h" + +#endif diff --git a/src/core/lowstorage.c b/src/core/lowstorage.c new file mode 100755 index 0000000..ce6a98e --- /dev/null +++ b/src/core/lowstorage.c @@ -0,0 +1,439 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "device-node.h" +#include "core/log.h" +#include "core/noti.h" +#include "core/queue.h" +#include "core/predefine.h" +#include "core/data.h" +#include "core/devices.h" +#include "core/common.h" +#include "core/edbus-handler.h" +#include "core/device-notifier.h" + +#define MEMNOTIFY_NORMAL 0x0000 +#define MEMNOTIFY_LOW 0xfaac +#define MEMNOTIFY_CRITICAL 0xdead +#define MEMNOTIFY_REBOOT 0xb00f + +#define MEMORY_STATUS_USR_PATH "/opt/usr" +#define MEMORY_MAX_MEM_STR_LEN 30 +#define MEMORY_KILOBYTE_VALUE 1024 +#define MEMORY_MEGABYTE_VALUE 1048576 +#define MEMORY_GIGABYTE_VALUE 1073741824 +#define MEMORY_RESERVE_VALUE (100*MEMORY_MEGABYTE_VALUE) +#define MEMNOTI_WARNING_VALUE (5) // 5% under +#define MEMNOTI_CRITICAL_VALUE (0.1) // 0.1% under +#define MEMNOTI_CRITICAL_SIZE(val) ((val*MEMNOTI_CRITICAL_VALUE)/100) +#define MEMNOTI_FULL_SIZE (MEMORY_RESERVE_VALUE + MEMORY_MEGABYTE_VALUE) + +#define SIGNAL_LOWMEM_STATE "ChangeState" +#define SIGNAL_LOWMEM_FULL "Full" + +#define POPUP_KEY_MEMNOTI "_MEM_NOTI_" +#define POPUP_KEY_APPNAME "_APP_NAME_" + +#define LOWMEM_POPUP_NAME "lowmem-syspopup" + +#define MEMNOTI_TIMER_INTERVAL 5 +#define MEM_TRIM_TIMER_INTERVAL 86400 /* 24 hour */ +#define MEM_FSTRIM_PATH "/sbin/fstrim" + +#define MEM_TRIM_START_TIME 2 // AM 02:00:00 +#define MIN_SEC (60) +#define HOUR_SEC (MIN_SEC * MIN_SEC) + +#define BUF_MAX 1024 + +enum memnoti_level { + MEMNOTI_LEVEL_CRITICAL = 0, + MEMNOTI_LEVEL_WARNING, + MEMNOTI_LEVEL_NORMAL, +} ; + +struct popup_data { + char *name; + char *key; + char *value; +}; + +static Ecore_Fd_Handler *lowmem_efd = NULL; +static int lowmem_fd; +static int cur_mem_state = MEMNOTIFY_NORMAL; + +static Ecore_Timer *memnoti_timer = NULL; +static Ecore_Timer *mem_trim_timer = NULL; + +static double memnoti_warning_level = MEMNOTI_WARNING_VALUE; +static double memnoti_critical_level = MEMNOTI_CRITICAL_VALUE; +static double memnoti_full_level; + +static void memnoti_send_broadcast(int status) +{ + static int old = 0; + char *arr[1]; + char str_status[32]; + + if (old == status) + return; + + old = status; + snprintf(str_status, sizeof(str_status), "%d", status); + arr[0] = str_status; + broadcast_edbus_signal(DEVICED_PATH_LOWMEM, DEVICED_INTERFACE_LOWMEM, + SIGNAL_LOWMEM_STATE, "i", arr); +} + +static void memnoti_level_broadcast(enum memnoti_level level) +{ + static int status = 0; + if (level == MEMNOTI_LEVEL_CRITICAL && status == 0) + status = 1; + else if (level != MEMNOTI_LEVEL_CRITICAL && status == 1) + status = 0; + else + return; + _D("send user mem noti : %d %d", level, status); + memnoti_send_broadcast(status); +} + +static int memnoti_popup(enum memnoti_level level) +{ + int ret = -1; + int val = -1; + char *value = NULL; + struct popup_data *params; + static const struct device_ops *apps = NULL; + + if (level != MEMNOTI_LEVEL_WARNING && level != MEMNOTI_LEVEL_CRITICAL) { + _E("level check error : %d",level); + return 0; + } + + if (level == MEMNOTI_LEVEL_WARNING) { + value = "warning"; + } else if (level == MEMNOTI_LEVEL_CRITICAL) { + value = "critical"; + } + + ret = vconf_get_int(VCONFKEY_STARTER_SEQUENCE, &val); + if (val == 0 || ret != 0) + goto out; + if (apps == NULL) { + apps = find_device("apps"); + if (apps == NULL) + return 0; + } + params = malloc(sizeof(struct popup_data)); + if (params == NULL) { + _E("Malloc failed"); + return -1; + } + params->name = LOWMEM_POPUP_NAME; + params->key = POPUP_KEY_MEMNOTI; + params->value = strdup(value); + apps->init((void *)params); + free(params); + return 0; +out: + return -1; +} + +static enum memnoti_level check_memnoti_level(double total, double avail) +{ + double tmp_size = (avail/total)*100; + + if (tmp_size > memnoti_warning_level) + return MEMNOTI_LEVEL_NORMAL; + if (tmp_size > memnoti_critical_level) + return MEMNOTI_LEVEL_WARNING; + return MEMNOTI_LEVEL_CRITICAL; +} + +static void memnoti_full_broadcast(double total, double avail) +{ + static int status = 0; + int tmp = 0; + double tmp_size = (avail/total)*100; + char *arr[1]; + char str_status[32]; + + tmp = status; + if (tmp_size <= memnoti_full_level && status == 0) + status = 1; + else if (tmp_size > memnoti_full_level && status == 1) + status = 0; + if (status == tmp) + return; + + _D("send memory full noti : %d (total: %4.4lf avail: %4.4lf)", status, total, avail); + snprintf(str_status, sizeof(str_status), "%d", status); + arr[0] = str_status; + broadcast_edbus_signal(DEVICED_PATH_LOWMEM, DEVICED_INTERFACE_LOWMEM, + SIGNAL_LOWMEM_FULL, "i", arr); +} + +static int __fs_stat(double* pdTotal, double* pdAvail, const char* szPath) +{ + struct statvfs s; + double reserved; + + if (NULL == pdAvail) { + _E("input param error"); + return 0; + } + + if (!statvfs(szPath, &s)) { + reserved = MEMORY_RESERVE_VALUE/s.f_bsize; + if (s.f_bavail < reserved) + s.f_bavail = 0; + else + s.f_bavail -= reserved; + *pdTotal = (double)s.f_frsize * s.f_blocks; + *pdAvail = (double)s.f_bsize * s.f_bavail; + } else { + _E("fail to get memory size"); + return 0; + } + + return 1; +} + +static void memory_status_set_full_mem_size(void) +{ + double dAvail = 0.0; + double dTotal = 0.0; + + if (__fs_stat(&dTotal, &dAvail, MEMORY_STATUS_USR_PATH) == 0) { + _E("fail to get mem size of %s",MEMORY_STATUS_USR_PATH); + return; + } + + memnoti_full_level = (MEMNOTI_FULL_SIZE/dTotal)*100; + _I("memnoti_full_level : %4.4lf(%d)", memnoti_full_level, MEMNOTI_FULL_SIZE); +} + +static Eina_Bool memory_status_get_available_size(void *data) +{ + static enum memnoti_level old = MEMNOTI_LEVEL_NORMAL; + enum memnoti_level now; + int ret; + double dAvail = 0.0; + double dTotal = 0.0; + + ret = __fs_stat(&dTotal, &dAvail, MEMORY_STATUS_USR_PATH); + if (ret == 0) { + _E("fail to get mem size of %s",MEMORY_STATUS_USR_PATH); + goto out; + } + + memnoti_full_broadcast(dTotal, dAvail); + + now = check_memnoti_level(dTotal, dAvail); + + memnoti_level_broadcast(now); + + if (now < MEMNOTI_LEVEL_NORMAL && now < old) { + ret = memnoti_popup(now); + if (ret != 0) + now = MEMNOTI_LEVEL_NORMAL; + } + old = now; + if (memnoti_timer) + ecore_timer_interval_set(memnoti_timer, MEMNOTI_TIMER_INTERVAL); +out: + return EINA_TRUE; +} + +static int __memnoti_fd_init(struct main_data *ad) +{ + memory_status_set_full_mem_size(); + memory_status_get_available_size(ad); + memnoti_timer = ecore_timer_add(MEMNOTI_TIMER_INTERVAL, + memory_status_get_available_size, ad); + if (memnoti_timer == NULL) + _E("fail mem available noti timer add"); + return 0; +} + +static Eina_Bool memory_trim_cb(void *data) +{ + ecore_timer_interval_set(memnoti_timer, MEM_TRIM_TIMER_INTERVAL); + if (launch_if_noexist(MEM_FSTRIM_PATH, MEMORY_STATUS_USR_PATH) == -1) { + _E("fail to launch fstrim"); + } else { + _D("fs memory trim is operated"); + } + return EINA_TRUE; +} + +static int __mem_trim_delta(struct tm *cur_tm) +{ + int delta = 0; + int sign_val; + + if (cur_tm->tm_hour < MEM_TRIM_START_TIME) + sign_val = 1; + else + sign_val = -1; + delta += ((sign_val) * (MEM_TRIM_START_TIME - cur_tm->tm_hour) * HOUR_SEC); + delta -= ((sign_val) * (cur_tm->tm_min * MIN_SEC + cur_tm->tm_sec)); + return delta; +} + +static int __run_mem_trim(void) +{ + time_t now; + struct tm *cur_tm; + int mem_trim_time; + + now = time(NULL); + cur_tm = (struct tm *)malloc(sizeof(struct tm)); + if (cur_tm == NULL) { + _E("Fail to memory allocation"); + return -1; + } + + if (localtime_r(&now, cur_tm) == NULL) { + _E("Fail to get localtime"); + free(cur_tm); + return -1; + } + + mem_trim_time = MEM_TRIM_TIMER_INTERVAL + __mem_trim_delta(cur_tm); + _D("start mem trim timer", mem_trim_time); + mem_trim_timer = ecore_timer_add(mem_trim_time, memory_trim_cb, NULL); + if (mem_trim_timer == NULL) { + _E("Fail to add mem trim timer"); + free(cur_tm); + return -1; + } + free(cur_tm); + return 0; +} + +static DBusMessage *edbus_getstatus(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int ret; + double dAvail = 0.0; + double dTotal = 0.0; + + ret = __fs_stat(&dTotal, &dAvail, MEMORY_STATUS_USR_PATH); + + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT64, &dTotal); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT64, &dAvail); + return reply; +} + +static DBusMessage *edbus_memtrim(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int ret; + + ret = launch_if_noexist(MEM_FSTRIM_PATH, MEMORY_STATUS_USR_PATH); + if (ret == -1) { + _E("fail to launch fstrim"); + } else { + _D("fs memory trim is operated"); + } + + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static const struct edbus_method edbus_methods[] = { + { "getstorage", NULL, "i", edbus_getstatus }, + { "MemTrim", NULL, "i", edbus_memtrim }, + /* Add methods here */ +}; + +static int booting_done(void *data) +{ + static int done = 0; + + if (data != NULL) { + done = (int)data; + if (done) + _I("booting done"); + if (__memnoti_fd_init(NULL) == -1) + _E("fail remain mem noti control fd init"); + } + return done; +} + +static int lowmem_poweroff(void *data) +{ + if (memnoti_timer) { + ecore_timer_del(memnoti_timer); + memnoti_timer = NULL; + } + if (mem_trim_timer) { + ecore_timer_del(mem_trim_timer); + mem_trim_timer = NULL; + } + return 0; +} + +static void lowmem_init(void *data) +{ + struct main_data *ad = (struct main_data*)data; + int ret; + register_notifier(DEVICE_NOTIFIER_BOOTING_DONE, booting_done); + register_notifier(DEVICE_NOTIFIER_POWEROFF, lowmem_poweroff); + ret = register_edbus_method(DEVICED_PATH_STORAGE, edbus_methods, ARRAY_SIZE(edbus_methods)); + if (ret < 0) + _E("fail to init edbus method(%d)", ret); + + if (__run_mem_trim() < 0) { + _E("fail mem trim timer start"); + } +} + +static void lowmem_exit(void *data) +{ + unregister_notifier(DEVICE_NOTIFIER_BOOTING_DONE, booting_done); + unregister_notifier(DEVICE_NOTIFIER_POWEROFF, lowmem_poweroff); +} + +static const struct device_ops lowmem_device_ops = { + .priority = DEVICE_PRIORITY_NORMAL, + .name = "lowmem", + .init = lowmem_init, + .exit = lowmem_exit, +}; + +DEVICE_OPS_REGISTER(&lowmem_device_ops) diff --git a/src/core/main.c b/src/core/main.c new file mode 100644 index 0000000..977eb06 --- /dev/null +++ b/src/core/main.c @@ -0,0 +1,128 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 "display/core.h" +#include "log.h" +#include "data.h" +#include "edbus-handler.h" +#include "devices.h" +#include "shared/dbus.h" +#include "device-notifier.h" + +#define PIDFILE_PATH "/var/run/.deviced.pid" + +static void init_ad(struct main_data *ad) +{ + memset(ad, 0x0, sizeof(struct main_data)); +} + +static void writepid(char *pidpath) +{ + FILE *fp; + + fp = fopen(pidpath, "w"); + if (fp != NULL) { + fprintf(fp, "%d", getpid()); + fclose(fp); + } +} + +static void sig_quit(int signo) +{ + _D("received SIGTERM signal %d", signo); +} + +static void sig_usr1(int signo) +{ + _D("received SIGUSR1 signal %d, deviced'll be finished!", signo); + + ecore_main_loop_quit(); +} + +static void check_systemd_active(void) +{ + DBusError err; + DBusMessage *msg; + DBusMessageIter iter, sub; + const char *state; + char *pa[2]; + + pa[0] = "org.freedesktop.systemd1.Unit"; + pa[1] = "ActiveState"; + + _I("%s %s", pa[0], pa[1]); + + msg = dbus_method_sync_with_reply("org.freedesktop.systemd1", + "/org/freedesktop/systemd1/unit/default_2etarget", + "org.freedesktop.DBus.Properties", + "Get", "ss", pa); + if (!msg) + return; + + dbus_error_init(&err); + + if (!dbus_message_iter_init(msg, &iter) || + dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) + goto out; + + dbus_message_iter_recurse(&iter, &sub); + + if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) + goto out; + + dbus_message_iter_get_basic(&sub, &state); + + if (strncmp(state, "active", 6) == 0) { + _I("notify relaunch"); + device_notify(DEVICE_NOTIFIER_BOOTING_DONE, (void *)TRUE); + } +out: + dbus_message_unref(msg); + dbus_error_free(&err); +} + +static int system_main(int argc, char **argv) +{ + struct main_data ad; + + init_ad(&ad); + edbus_init(&ad); + devices_init(&ad); + check_systemd_active(); + signal(SIGTERM, sig_quit); + signal(SIGUSR1, sig_usr1); + + ecore_main_loop_begin(); + + devices_exit(&ad); + edbus_exit(&ad); + ecore_shutdown(); + return 0; +} + +int main(int argc, char **argv) +{ + writepid(PIDFILE_PATH); + ecore_init(); + return system_main(argc, argv); +} diff --git a/src/core/noti.c b/src/core/noti.c new file mode 100644 index 0000000..8eda5d6 --- /dev/null +++ b/src/core/noti.c @@ -0,0 +1,86 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 "log.h" +#include "data.h" +#include "devices.h" +#include "common.h" + +static int noti_fd; + +int noti_getfd() +{ + return noti_fd; +} + +int noti_send(char *filename) +{ + return heynoti_publish(filename); +} + +int noti_add(const char *noti, void (*cb) (void *), void *data) +{ + if (noti_fd < 0) + return -1; + + return heynoti_subscribe(noti_fd, noti, cb, data); +} + +static void noti_init(void *data) +{ + struct main_data *ad = (struct main_data*)data; + + if ((ad->noti_fd = heynoti_init()) < 0) { + _E("Hey Notification Initialize failed"); + return; + } + if (heynoti_attach_handler(ad->noti_fd) != 0) { + _E("fail to attach hey noti handler"); + return; + } + + noti_fd = heynoti_init(); + if (noti_fd < 0) { + _E("heynoti_init error"); + return; + } + + if (heynoti_attach_handler(noti_fd) < 0) { + _E("heynoti_attach_handler error"); + return; + } +} + +static void noti_exit(void *data) +{ + struct main_data *ad = (struct main_data*)data; + + heynoti_close(ad->noti_fd); + heynoti_close(noti_fd); +} + +static const struct device_ops noti_device_ops = { + .priority = DEVICE_PRIORITY_NORMAL, + .name = "noti", + .init = noti_init, + .exit = noti_exit, +}; + +DEVICE_OPS_REGISTER(¬i_device_ops) diff --git a/src/core/noti.h b/src/core/noti.h new file mode 100644 index 0000000..6895e31 --- /dev/null +++ b/src/core/noti.h @@ -0,0 +1,28 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 __NOTI_H__ +#define __NOTI_H__ + +int noti_getfd(void); +int noti_send(char *filename); +int noti_add(const char *noti, void (*cb) (void *), void *data); +int noti_init(void); + +#endif /* __NOTI_H__ */ diff --git a/src/core/power-supply.c b/src/core/power-supply.c new file mode 100644 index 0000000..e058023 --- /dev/null +++ b/src/core/power-supply.c @@ -0,0 +1,815 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 "devices.h" +#include "predefine.h" +#include "device-handler.h" +#include "device-notifier.h" +#include "udev.h" +#include "log.h" +#include "emulator.h" +#include "display/poll.h" +#include "display/setting.h" +#include "proc/proc-handler.h" +#include "config-parser.h" +#include "power-supply.h" + +#define BUFF_MAX 255 +#define POPUP_KEY_CONTENT "_SYSPOPUP_CONTENT_" + +#define PREDEF_BATTERY_CF_OPENED "battery_cf_opened" +#define SIGNAL_CHARGEERR_RESPONSE "ChargeErrResponse" +#define SIGNAL_TEMP_GOOD "TempGood" + +#define ABNORMAL_CHECK_TIMER_INTERVAL 60 + +#define METHOD_FULL_NOTI_ON "BatteryFullNotiOn" +#define METHOD_FULL_NOTI_OFF "BatteryFullNotiOff" +#define METHOD_CHARGE_NOTI_ON "BatteryChargeNotiOn" + +#define SIOP_DISABLE "memory/private/sysman/siop_disable" + +#define RETRY_MAX 5 +#define BATTERY_CHECK_TIMER_INTERVAL (0.5) + +#ifdef MICRO_DD +#define DEVICE_NOTIFIER "/usr/bin/sys_device_noti" +#define BATT_CHARGE_NOTI "0" +#define BATT_FULL_NOTI "2" +#endif +struct popup_data { + char *name; + char *key; + char *value; +}; + +static Ecore_Timer *power_timer = NULL; +static Ecore_Timer *abnormal_timer = NULL; +extern int battery_power_off_act(void *data); + +static void pm_check_and_change(int bInserted) +{ + static int old = -1; + if (old != bInserted) { + old = bInserted; + predefine_pm_change_state(LCD_NORMAL); + } +} + +int check_lowbat_charge_device(int bInserted) +{ + static int bChargeDeviceInserted = 0; + int val = -1; + int bat_state = -1; + int ret = -1; + char *value; + struct popup_data *params; + static const struct device_ops *apps = NULL; + + pm_check_and_change(bInserted); + if (bInserted == 1) { + if (battery.charge_now) + bChargeDeviceInserted = 1; + return 0; + } else if (bInserted == 0) { + if (!battery.charge_now && bChargeDeviceInserted == 1) { + bChargeDeviceInserted = 0; + //low bat popup during charging device removing + if (vconf_get_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, &bat_state) == 0) { + if(bat_state < VCONFKEY_SYSMAN_BAT_NORMAL + || bat_state == VCONFKEY_SYSMAN_BAT_REAL_POWER_OFF) { + if (apps == NULL) { + apps = find_device("apps"); + if (apps == NULL) + return 0; + } + if(bat_state == VCONFKEY_SYSMAN_BAT_REAL_POWER_OFF) + value = "poweroff"; + else if (bat_state == VCONFKEY_SYSMAN_BAT_POWER_OFF) + value = "extreme"; + else + value = "warning"; + params = malloc(sizeof(struct popup_data)); + if (params == NULL) { + _E("Malloc failed"); + return -1; + } + params->name = "lowbat-syspopup"; + params->key = POPUP_KEY_CONTENT; + params->value = value; + _I("%s %s %s(%x)", params->name, params->key, params->value, params); + if (apps->init) + apps->init((void *)params); + free(params); + } + } else { + _E("failed to get vconf key"); + return -1; + } + } + return 0; + } + return -1; +} + +static int changed_battery_cf(int argc, char **argv) +{ + int present_status; + struct popup_data *params; + static const struct device_ops *apps = NULL; + + if (argc != 1) + return -EINVAL; + present_status = atoi(argv[0]); + + if (apps == NULL) { + apps = find_device("apps"); + if (apps == NULL) + return 0; + } + params = malloc(sizeof(struct popup_data)); + if (params == NULL) { + _E("Malloc failed"); + return -ENOMEM; + } + params->name = "lowbat-syspopup"; + params->key = POPUP_KEY_CONTENT; + params->value = "battdisconnect"; + if (apps->init == NULL || apps->exit == NULL) + goto out; + if (present_status == PRESENT_ABNORMAL) + apps->init((void *)params); + else + apps->exit((void *)params); +out: + free(params); + return 0; +} + +int check_abnormal_popup(void) +{ + int ret = HEALTH_BAD; + + if (abnormal_timer) + ret = HEALTH_GOOD; + return ret; +} + +static void abnormal_popup_timer_init(void) +{ + if (abnormal_timer == NULL) + return; + ecore_timer_del(abnormal_timer); + abnormal_timer = NULL; + _I("delete health timer"); +} + +static void health_status_broadcast(void) +{ + broadcast_edbus_signal(DEVICED_PATH_BATTERY, DEVICED_INTERFACE_BATTERY, + SIGNAL_TEMP_GOOD, NULL, NULL); +} + +static int clean_health_popup(void) +{ + struct popup_data *params; + static const struct device_ops *apps = NULL; + + if (apps == NULL) { + apps = find_device("apps"); + if (apps == NULL) + return 0; + } + params = malloc(sizeof(struct popup_data)); + if (params == NULL) { + _E("Malloc failed"); + return -ENOMEM; + } + params->name = "lowbat-syspopup"; + params->key = POPUP_KEY_CONTENT; + if (apps->exit) + apps->exit((void *)params); + health_status_broadcast(); +out: + free(params); + return 0; + +} + +static void health_timer_reset(void) +{ + abnormal_timer = NULL; +} + +static Eina_Bool health_timer_cb(void *data) +{ + health_timer_reset(); + + if (battery.health == HEALTH_GOOD) + return EINA_FALSE; + + _I("popup - Battery health status is not good"); + vconf_set_int(SIOP_DISABLE, 1); + device_notify(DEVICE_NOTIFIER_BATTERY_HEALTH, (void *)HEALTH_BAD); + pm_change_internal(getpid(), LCD_NORMAL); + pm_lock_internal(INTERNAL_LOCK_POPUP, LCD_DIM, STAY_CUR_STATE, 0); + if (battery.temp == TEMP_LOW) + battery_charge_err_low_act(NULL); + else if (battery.temp == TEMP_HIGH) + battery_charge_err_high_act(NULL); + return EINA_FALSE; +} + +static void abnormal_popup_edbus_signal_handler(void *data, DBusMessage *msg) +{ + if (battery.health == HEALTH_GOOD) + return; + _I("restart health timer"); + abnormal_timer = ecore_timer_add(ABNORMAL_CHECK_TIMER_INTERVAL, + health_timer_cb, NULL); + if (abnormal_timer == NULL) + _E("Fail to add abnormal check timer"); +} + +static int noti_id; + +static void full_noti_cb(void *data, DBusMessage *msg, DBusError *err) +{ + DBusError r_err; + int ret, id; + + if (!msg) + return; + + dbus_error_init(&r_err); + ret = dbus_message_get_args(msg, &r_err, DBUS_TYPE_INT32, &id, DBUS_TYPE_INVALID); + if (!ret) { + _E("no message [%s:%s]", r_err.name, r_err.message); + dbus_error_free(&r_err); + return; + } + + noti_id = id; + _D("Inserted battery full noti : %d", noti_id); +} + +static int send_full_noti(enum charge_full_type state) +{ + int ret = 0; +#ifdef MICRO_DD + char params[BUFF_MAX]; + snprintf(params, sizeof(params), "%s %d", BATT_FULL_NOTI, state); + launch_evenif_exist(DEVICE_NOTIFIER, params); +#else + int retry; + char str_id[32]; + char *arr[1]; + + switch (state) { + case CHARGING_FULL: + for (retry = RETRY_MAX; retry > 0 ;retry--) { + ret = dbus_method_async_with_reply(POPUP_BUS_NAME, + POPUP_PATH_BATTERY, + POPUP_INTERFACE_BATTERY, + METHOD_FULL_NOTI_ON, + NULL, NULL, full_noti_cb, -1, NULL); + if (ret == 0) { + _D("Created battery full noti"); + return ret; + } + } + _E("Failed to call dbus method (err: %d)", ret); + break; + case CHARGING_NOT_FULL: + if (noti_id <= 0) + return -EPERM; + snprintf(str_id, sizeof(str_id), "%d", noti_id); + arr[0] = str_id; + for (retry = RETRY_MAX; retry > 0 ;retry--) { + ret = dbus_method_async(POPUP_BUS_NAME, + POPUP_PATH_BATTERY, + POPUP_INTERFACE_BATTERY, + METHOD_FULL_NOTI_OFF, + "i", arr); + if (ret == 0) { + _D("Deleted battery full noti"); + noti_id = 0; + return ret; + } + } + _E("Failed to call dbus method (err: %d)", ret); + break; + } +#endif + return ret; +} + +int send_charge_noti(void) +{ + int ret = 0; +#ifdef MICRO_DD + launch_evenif_exist(DEVICE_NOTIFIER, BATT_CHARGE_NOTI); +#else + int retry; + + for (retry = RETRY_MAX; retry > 0 ;retry--) { + ret = dbus_method_async(POPUP_BUS_NAME, + POPUP_PATH_BATTERY, + POPUP_INTERFACE_BATTERY, + METHOD_CHARGE_NOTI_ON, + NULL, NULL); + if (ret == 0) { + _D("Created battery charge noti"); + return ret; + } + } + _E("Failed to call dbus method (err: %d)", ret); +#endif + return ret; +} + +void battery_noti(enum battery_noti_type type, enum battery_noti_status status) +{ + static int charge = CHARGER_DISCHARGING; + static int full = CHARGING_NOT_FULL; + int ret, i; + + if (type == DEVICE_NOTI_BATT_FULL && status == DEVICE_NOTI_ON && + full == CHARGING_NOT_FULL) { + ret = send_full_noti(CHARGING_FULL); + if (ret == 0) + full = CHARGING_FULL; + } else if (type == DEVICE_NOTI_BATT_FULL && status == DEVICE_NOTI_OFF && + full == CHARGING_FULL) { + ret = send_full_noti(CHARGING_NOT_FULL); + if (ret == 0) + full = CHARGING_NOT_FULL; + } else if (type == DEVICE_NOTI_BATT_CHARGE && + battery.charge_now == CHARGER_CHARGING && + charge == CHARGER_DISCHARGING) { + if (full == CHARGING_FULL) { + ret = send_full_noti(CHARGING_NOT_FULL); + if (ret == 0) + full = CHARGING_NOT_FULL; + } + send_charge_noti(); + } + charge = battery.charge_now; +} + +static void noti_batt_full(void) +{ + char params[BUFF_MAX]; + static int bat_full_noti = 0; + + if (!battery.charge_full && bat_full_noti == 1) { + battery_noti(DEVICE_NOTI_BATT_FULL, DEVICE_NOTI_OFF); + bat_full_noti = 0; + /* off the full charge state */ + device_notify(DEVICE_NOTIFIER_FULLBAT, (void*)false); + } + if (battery.charge_full && bat_full_noti == 0) { + battery_noti(DEVICE_NOTI_BATT_FULL, DEVICE_NOTI_ON); + bat_full_noti = 1; + /* turn on LCD, if battery is full charged */ + pm_change_internal(getpid(), LCD_NORMAL); + /* on the full charge state */ + device_notify(DEVICE_NOTIFIER_FULLBAT, (void*)true); + } +} + +static void check_power_supply(int state) +{ + int ret = -1; + int val = 0; + char params[BUFF_MAX]; + + check_lowbat_charge_device(state); + if (update_pm_setting) + update_pm_setting(SETTING_CHARGING, state); + + ret = device_get_property(DEVICE_TYPE_POWER, + PROP_POWER_INSUSPEND_CHARGING_SUPPORT, &val); + + if (ret != 0 || val == 1) { + _D("fail to check charger insuspend"); + goto out; + } + + if (state == 0) + pm_unlock_internal(INTERNAL_LOCK_TA, LCD_OFF, STAY_CUR_STATE); + else + pm_lock_internal(INTERNAL_LOCK_TA, LCD_OFF, STAY_CUR_STATE, 0); +out: + _I("ta device %d", state); + + sync_cradle_status(); +} + +static void update_present(enum battery_noti_status status) +{ + static int old = DEVICE_NOTI_OFF; + char params[BUFF_MAX]; + + if (old == status) + return; + _I("charge %d present %d", battery.charge_now, battery.present); + old = status; + pm_change_internal(getpid(), LCD_NORMAL); + if (status == DEVICE_NOTI_ON) + snprintf(params, sizeof(params), "%d", PRESENT_ABNORMAL); + else + snprintf(params, sizeof(params), "%d", PRESENT_NORMAL); + notify_action(PREDEF_BATTERY_CF_OPENED, 1, params); +} + +static void update_health(enum battery_noti_status status) +{ + static int old = DEVICE_NOTI_OFF; + + if (old == status) + return; + _I("charge %d health %d", battery.charge_now, battery.health); + old = status; + pm_change_internal(getpid(), LCD_NORMAL); + if (status == DEVICE_NOTI_ON) { + _I("popup - Battery health status is not good"); + vconf_set_int(SIOP_DISABLE, 1); + device_notify(DEVICE_NOTIFIER_BATTERY_HEALTH, (void *)HEALTH_BAD); + pm_lock_internal(INTERNAL_LOCK_POPUP, LCD_DIM, STAY_CUR_STATE, 0); + if (battery.temp == TEMP_LOW) + battery_charge_err_low_act(NULL); + else if (battery.temp == TEMP_HIGH) + battery_charge_err_high_act(NULL); + } else { + vconf_set_int(SIOP_DISABLE, 0); + device_notify(DEVICE_NOTIFIER_BATTERY_HEALTH, (void *)HEALTH_GOOD); + pm_unlock_internal(INTERNAL_LOCK_POPUP, LCD_DIM, PM_SLEEP_MARGIN); + clean_health_popup(); + abnormal_popup_timer_init(); + } +} + +static void update_ovp(enum battery_noti_status status) +{ + static int old = DEVICE_NOTI_OFF; + + if (old == status) + return; + _I("charge %d ovp %d", battery.charge_now, battery.ovp); + old = status; + pm_change_internal(getpid(), LCD_NORMAL); + if (status == DEVICE_NOTI_ON) + device_notify(DEVICE_NOTIFIER_BATTERY_OVP, (void *)OVP_ABNORMAL); + else + device_notify(DEVICE_NOTIFIER_BATTERY_OVP, (void *)OVP_NORMAL); +} + +static void check_battery_status(void) +{ + static int old = DEVICE_CHANGE_NORMAL; + int status; + + if (battery.charge_now == CHARGER_ABNORMAL && + (battery.health == HEALTH_BAD || battery.present == PRESENT_ABNORMAL)) + status = DEVICE_CHANGE_ABNORMAL; + else if (battery.ovp == OVP_ABNORMAL) + status = DEVICE_CHANGE_ABNORMAL; + else + status = DEVICE_CHANGE_NORMAL; + if (old == status) + return; + old = status; + + if (battery.charge_now == CHARGER_ABNORMAL) { + if (battery.health == HEALTH_BAD) { + update_health(DEVICE_NOTI_ON); + return; + } else if (battery.present == PRESENT_ABNORMAL) { + update_present(DEVICE_NOTI_ON); + return; + } + } + if (battery.ovp == OVP_ABNORMAL) { + update_ovp(DEVICE_NOTI_ON); + return; + } + + if (battery.charge_now != CHARGER_ABNORMAL && + status == DEVICE_CHANGE_NORMAL) { + update_health(DEVICE_NOTI_OFF); + update_ovp(DEVICE_NOTI_OFF); + update_present(DEVICE_NOTI_OFF); + } +} + +static void check_online(void) +{ + static int old_online; + + if (battery.online > POWER_SUPPLY_TYPE_BATTERY && + old_online == VCONFKEY_SYSMAN_CHARGER_DISCONNECTED) { + old_online = VCONFKEY_SYSMAN_CHARGER_CONNECTED; + vconf_set_int(VCONFKEY_SYSMAN_CHARGER_STATUS, old_online); + power_supply_broadcast(CHARGER_STATUS_SIGNAL, old_online); + extcon_set_count(EXTCON_TA); + check_power_supply(old_online); + } else if (battery.online <= POWER_SUPPLY_TYPE_BATTERY && + old_online == VCONFKEY_SYSMAN_CHARGER_CONNECTED) { + old_online = VCONFKEY_SYSMAN_CHARGER_DISCONNECTED; + vconf_set_int(VCONFKEY_SYSMAN_CHARGER_STATUS, old_online); + power_supply_broadcast(CHARGER_STATUS_SIGNAL, old_online); + check_power_supply(old_online); + } +} + +static void charge_cb(struct main_data *ad) +{ + int val = -1; + int ret; + static int present_status = PRESENT_NORMAL; + + lowbat_monitor(NULL); + + if (device_get_property(DEVICE_TYPE_POWER, PROP_POWER_CHARGE_NOW, &battery.charge_now) != 0 || + device_get_property(DEVICE_TYPE_POWER, PROP_POWER_CAPACITY, &battery.capacity) != 0) + _E("fail to get battery node value"); + + if (battery.charge_now > 0) + battery.charge_now = CHARGER_CHARGING; + else + battery.charge_now = CHARGER_DISCHARGING; + + if (battery.charge_now != CHARGER_CHARGING && battery.capacity == 0) { + _I("target will be shut down"); + battery_power_off_act(NULL); + return; + } + + ret = device_get_property(DEVICE_TYPE_POWER, PROP_POWER_PRESENT, &val); + if (ret != 0) { + battery.present = PRESENT_NORMAL; + _E("fail to get battery present value"); + goto check_health; + } +check_health: + ret = device_get_property(DEVICE_TYPE_POWER, PROP_POWER_HEALTH, &val); + if (ret != 0) { + battery.health = HEALTH_GOOD; + battery.ovp = OVP_NORMAL; + _E("failed to get battery health status"); + goto check_full; + } + if (val != BATTERY_GOOD) + _I("Battery health status is not good (%d)", val); + if (val == BATTERY_OVERHEAT) { + battery.health = HEALTH_BAD; + battery.charge_now = CHARGER_ABNORMAL; + battery.temp = TEMP_HIGH; + } else if (val == BATTERY_COLD) { + battery.health = HEALTH_BAD; + battery.charge_now = CHARGER_ABNORMAL; + battery.temp = TEMP_LOW; + } else { + battery.health = HEALTH_GOOD; + } +check_full: + ret = device_get_property(DEVICE_TYPE_POWER, PROP_POWER_CHARGE_FULL, &val); + if (ret == 0) + battery.charge_full = val; + noti_batt_full(); + check_battery_status(); + device_notify(DEVICE_NOTIFIER_BATTERY_CHARGING, (void*)battery.charge_now); +} + +static int load_uevent(struct parse_result *result, void *user_data) +{ + struct battery_status *info = user_data; + + if (!info) + return -EINVAL; + + if (MATCH(result->name, CHARGE_STATUS)) { + if (strstr(result->value, "Charging")) { + info->charge_now = CHARGER_CHARGING; + info->charge_full = CHARGING_NOT_FULL; + } else if (strstr(result->value, "Discharging")) { + info->charge_now = CHARGER_DISCHARGING; + info->charge_full = CHARGING_NOT_FULL; + } else if (strstr(result->value, "Full")) { + info->charge_now = CHARGER_DISCHARGING; + info->charge_full = CHARGING_FULL; + } else if (strstr(result->value, "Not charging")) { + info->charge_now = CHARGER_ABNORMAL; + info->charge_full = CHARGING_NOT_FULL; + } + } + else if (MATCH(result->name, CAPACITY)) + info->capacity = atoi(result->value); + return 0; +} + +static void power_load_uevent(void) +{ + int ret; + ret = config_parse(POWER_SUPPLY_UEVENT, load_uevent, &battery); + if (ret < 0) + _E("Failed to load %s, %d Use default value!", POWER_SUPPLY_UEVENT, ret); +} + +void power_supply(void *data) +{ + int ret; + + static int old_charge; + + if (old_charge != battery.charge_now || battery.charge_now == CHARGER_ABNORMAL) { + old_charge = battery.charge_now; + vconf_set_int(VCONFKEY_SYSMAN_BATTERY_CHARGE_NOW, old_charge); + power_supply_broadcast(CHARGE_NOW_SIGNAL, old_charge); + } + + lowbat_monitor(data); + check_online(); + noti_batt_full(); + check_battery_status(); + device_notify(DEVICE_NOTIFIER_POWER_SUPPLY, NULL); + device_notify(DEVICE_NOTIFIER_BATTERY_CHARGING, (void*)battery.charge_now); +} + +void power_supply_status_init(void) +{ + int ret, val; + static int charge_now = -1; + static int charge_full = -1; + static int capacity = -1; + + power_load_uevent(); + battery.health = HEALTH_GOOD; + battery.ovp = OVP_NORMAL; + battery.present = PRESENT_NORMAL; + battery.temp = TEMP_LOW; + + if (charge_now == battery.charge_now && + charge_full == battery.charge_full && + capacity == battery.capacity) + return; + + if (charge_now != battery.charge_now || + charge_full != battery.charge_full || + capacity != battery.capacity) + _I("charging %d full %d capacity %d", battery.charge_now, battery.charge_full, battery.capacity); + + if (charge_now != battery.charge_now) { + vconf_set_int(VCONFKEY_SYSMAN_BATTERY_CHARGE_NOW, battery.charge_now); + power_supply_broadcast(CHARGE_NOW_SIGNAL, battery.charge_now); + } + if (capacity != battery.capacity) + vconf_set_int(VCONFKEY_SYSMAN_BATTERY_CAPACITY, battery.capacity); + + charge_now = battery.charge_now; + charge_full = battery.charge_full; + capacity = battery.capacity; +} + +static Eina_Bool power_supply_update(void *data) +{ + power_supply_status_init(); + return EINA_TRUE; +} + +void power_supply_timer_start(void) +{ + _D("battery init timer during booting"); + power_timer = ecore_timer_add(BATTERY_CHECK_TIMER_INTERVAL, + power_supply_update, NULL); + if (power_timer == NULL) + _E("fail to add battery init timer during booting"); +} + +void power_supply_timer_stop(void) +{ + _D("battery init timer during booting"); + if (!power_timer) + return; + ecore_timer_del(power_timer); + power_timer = NULL; +} + +void power_supply_broadcast(char *sig, int status) +{ + static int old = 0; + static char sig_old[32]; + char *arr[1]; + char str_status[32]; + + if (strcmp(sig_old, sig) == 0 && old == status) + return; + + _D("%s %d", sig, status); + + old = status; + snprintf(sig_old, sizeof(sig_old), "%s", sig); + snprintf(str_status, sizeof(str_status), "%d", status); + arr[0] = str_status; + + broadcast_edbus_signal(DEVICED_PATH_BATTERY, DEVICED_INTERFACE_BATTERY, + sig, "i", arr); +} + +static DBusMessage *dbus_get_charger_status(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int ret; + + if (vconf_get_int(VCONFKEY_SYSMAN_CHARGER_STATUS, &ret) < 0) { + _E("vconf_get_int() failed"); + ret = -EIO; + } + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *dbus_get_charge_now(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int ret; + + ret = battery.charge_now; + + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *dbus_get_charge_level(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int ret; + + if (vconf_get_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, &ret) < 0) { + _E("vconf_get_int() failed"); + ret = -EIO; + } + + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static const struct edbus_method edbus_methods[] = { + { CHARGER_STATUS_SIGNAL, NULL, "i", dbus_get_charger_status }, + { CHARGE_NOW_SIGNAL, NULL, "i", dbus_get_charge_now }, + { CHARGE_LEVEL_SIGNAL, NULL, "i", dbus_get_charge_level }, +}; + +int power_supply_init(void *data) +{ + int ret; + ret = register_edbus_method(DEVICED_PATH_BATTERY, edbus_methods, ARRAY_SIZE(edbus_methods)); + if (ret < 0) + _E("fail to init edbus method(%d)", ret); + ret = register_edbus_signal_handler(DEVICED_PATH_SYSNOTI, + DEVICED_INTERFACE_SYSNOTI, SIGNAL_CHARGEERR_RESPONSE, + abnormal_popup_edbus_signal_handler); + if (ret < 0) + _E("fail to init edbus signal(%d)", ret); + + register_action(PREDEF_BATTERY_CF_OPENED, changed_battery_cf, + NULL, NULL); + + /* for simple noti change cb */ + emulator_add_callback("device_charge_chgdet", (void *)charge_cb, data); + power_supply_status_init(); + power_supply(NULL); + return ret; +} diff --git a/src/core/power-supply.h b/src/core/power-supply.h new file mode 100644 index 0000000..3dd2f94 --- /dev/null +++ b/src/core/power-supply.h @@ -0,0 +1,35 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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_SUPPLY_H__ +#define __POWER_SUPPLY_H__ + +#define CHARGER_STATUS_SIGNAL "ChargerStatus" +#define CHARGE_NOW_SIGNAL "ChargeNow" +#define CHARGE_LEVEL_SIGNAL "BatteryStatusLow" + +int check_abnormal_popup(void); +int check_lowbat_charge_device(int bInserted); +void power_supply(void *data); +int power_supply_init(void *data); +void power_supply_status_init(void); +void power_supply_timer_start(void); +void power_supply_timer_stop(void); +void power_supply_broadcast(char *sig, int status); +#endif /* __POWER_SUPPLY_H__ */ diff --git a/src/core/predefine.c b/src/core/predefine.c new file mode 100755 index 0000000..3b6c515 --- /dev/null +++ b/src/core/predefine.c @@ -0,0 +1,273 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include "dd-deviced.h" +#include "log.h" +#include "launch.h" +#include "queue.h" +#include "device-handler.h" +#include "device-node.h" +#include "predefine.h" +#include "proc/proc-handler.h" +#include "data.h" +#include "common.h" +#include "display/poll.h" +#include "display/setting.h" +#include "devices.h" +#include "battery/battery.h" +#include "edbus-handler.h" + +#define VCONFKEY_SYSMAN_FACTORY_MODE "memory/sysman/factory_mode" + +#define PREDEFINE_SO_DIR PREFIX"/lib/ss_predefine/" +#define PREDEF_CALL "call" +#define PREDEF_FACTORY_MODE "factorymode" + +#define CALL_EXEC_PATH PREFIX"/bin/call" + +#define LOWBAT_EXEC_PATH PREFIX"/bin/lowbatt-popup" + +#define HDMI_NOTI_EXEC_PATH PREFIX"/bin/hdmi_connection_noti" + + +static int bFactoryMode = 0; + +int predefine_get_pid(const char *execpath) +{ + DIR *dp; + struct dirent *dentry; + int pid = -1, fd; + int ret; + char buf[PATH_MAX]; + char buf2[PATH_MAX]; + + dp = opendir("/proc"); + if (!dp) { + _E("FAIL: open /proc"); + return -1; + } + + while ((dentry = readdir(dp)) != NULL) { + if (!isdigit(dentry->d_name[0])) + continue; + + pid = atoi(dentry->d_name); + + snprintf(buf, PATH_MAX, "/proc/%d/cmdline", pid); + fd = open(buf, O_RDONLY); + if (fd < 0) + continue; + ret = read(fd, buf2, PATH_MAX); + close(fd); + + if (ret < 0 || ret >=PATH_MAX) + continue; + + buf2[ret] = '\0'; + + if (!strcmp(buf2, execpath)) { + closedir(dp); + return pid; + } + } + + errno = ESRCH; + closedir(dp); + return -1; +} + +#ifdef NOUSE +int call_predefine_action(int argc, char **argv) +{ + char argstr[128]; + int pid; + + if (argc < 2) + return -1; + + snprintf(argstr, sizeof(argstr), "-t MT -n %s -i %s", argv[0], argv[1]); + pid = launch_if_noexist(CALL_EXEC_PATH, argstr); + if (pid < 0) { + _E("call predefine action failed"); + return -1; + } + return pid; +} +#endif + +void predefine_pm_change_state(unsigned int s_bits) +{ + if (is_factory_mode() == 1) + _D("skip LCD control for factory mode"); + else + pm_change_internal(getpid(), s_bits); +} + +int is_factory_mode(void) +{ + return bFactoryMode; +} +int set_factory_mode(int bOn) +{ + int ret = -1; + if ( bOn==1 || bOn==0 ) { + bFactoryMode = bOn; + /* For USB-server to refer the value */ + ret = vconf_set_int(VCONFKEY_SYSMAN_FACTORY_MODE, bOn); + if(ret != 0) { + _E("FAIL: vconf_set_int()"); + } + } + return bFactoryMode; +} + +int factory_mode_action(int argc, char **argv) +{ + int bOn; + if (argc != 1 || argv[0] == NULL) { + _E("Factory Mode Set predefine action failed"); + return -1; + } + bOn = atoi(argv[0]); + bOn = set_factory_mode(bOn); + return 0; + +} + +static void action_entry_load_from_sodir() +{ + DIR *dp; + struct dirent *dentry; + struct sysnoti *msg; + char *ext; + char tmp[128]; + + dp = opendir(PREDEFINE_SO_DIR); + if (!dp) { + _E("fail open %s", PREDEFINE_SO_DIR); + return; + } + + msg = malloc(sizeof(struct sysnoti)); + if (msg == NULL) { + _E("Malloc failed"); + closedir(dp); + return; + } + + msg->pid = getpid(); + + while ((dentry = readdir(dp)) != NULL) { + if ((ext = strstr(dentry->d_name, ".so")) == NULL) + continue; + + snprintf(tmp, sizeof(tmp), "%s/%s", PREDEFINE_SO_DIR, + dentry->d_name); + msg->path = tmp; + *ext = 0; + msg->type = &(dentry->d_name[3]); + register_msg(msg); + } + free(msg); + + closedir(dp); +} + +static DBusMessage *dbus_factory_mode(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusError err; + DBusMessageIter iter; + DBusMessage *reply; + pid_t pid; + int ret; + int argc; + char *type_str; + char *argv; + + dbus_error_init(&err); + + if (!dbus_message_get_args(msg, &err, + DBUS_TYPE_STRING, &type_str, + DBUS_TYPE_INT32, &argc, + DBUS_TYPE_STRING, &argv, DBUS_TYPE_INVALID)) { + _E("there is no message"); + ret = -EINVAL; + goto out; + } + + if (argc < 0) { + _E("message is invalid!"); + ret = -EINVAL; + goto out; + } + + pid = get_edbus_sender_pid(msg); + if (kill(pid, 0) == -1) { + _E("%d process does not exist, dbus ignored!", pid); + ret = -ESRCH; + goto out; + } + + ret = set_factory_mode(atoi(argv)); +out: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + + return reply; +} + +static const struct edbus_method edbus_methods[] = { + { PREDEF_FACTORY_MODE, "sis", "i", dbus_factory_mode }, +}; + +static void predefine_init(void *data) +{ + /* telephony initialize */ + int ret; + + ret = register_edbus_method(DEVICED_PATH_SYSNOTI, edbus_methods, ARRAY_SIZE(edbus_methods)); + if (ret < 0) + _E("fail to init edbus method(%d)", ret); +#ifdef NOUSE + register_action(PREDEF_CALL, call_predefine_action, NULL, NULL); +#endif + register_action(PREDEF_FACTORY_MODE, factory_mode_action, NULL, NULL); + + action_entry_load_from_sodir(); +} + +static const struct device_ops predefine_device_ops = { + .priority = DEVICE_PRIORITY_NORMAL, + .name = "predefine", + .init = predefine_init, +}; + +DEVICE_OPS_REGISTER(&predefine_device_ops) diff --git a/src/core/predefine.h b/src/core/predefine.h new file mode 100644 index 0000000..a20aaf5 --- /dev/null +++ b/src/core/predefine.h @@ -0,0 +1,27 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 __PREDEFINE_H__ +#define __PREDEFINE_H__ + +int call_predefine_action(int argc, char **argv); +int is_factory_mode(void); +void predefine_pm_change_state(unsigned int s_bits); +int predefine_get_pid(const char *execpath); +#endif /* __PREDEFINE_H__ */ diff --git a/src/core/queue.c b/src/core/queue.c new file mode 100644 index 0000000..d0da9b2 --- /dev/null +++ b/src/core/queue.c @@ -0,0 +1,283 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 "data.h" +#include "core.h" +#include "queue.h" +#include "log.h" +#include "list.h" + +#define PREDEFINE_ACT_FUNC_STR "predefine_action" +#define IS_ACCESSIBLE_FUNC_STR "is_accessible" +#define UI_VIEWABLE_FUNC_STR "ui_viewable" + +static dd_list *predef_act_list; +static dd_list *run_queue; + +static struct action_entry *find_action_entry(char *type) +{ + dd_list *tmp; + struct action_entry *data; + + DD_LIST_FOREACH(predef_act_list, tmp, data) { + if (!strcmp(data->type, type)) + return data; + } + + return NULL; +} + +int register_action(char *type, + int (*predefine_action) (), + int (*ui_viewable) (), + int (*is_accessible) (int)) +{ + struct action_entry *data; + + data = malloc(sizeof(struct action_entry)); + + if (data == NULL) { + _E("Malloc failed"); + return -1; + } + + data->type = NULL; + if (find_action_entry(type) != NULL) + goto err; + + data->handle = NULL; + data->predefine_action = predefine_action; + if (data->predefine_action == NULL) + goto err; + + data->is_accessible = is_accessible; + data->ui_viewable = ui_viewable; + data->owner_pid = getpid(); + data->type = strdup(type); + data->path = strdup(""); + + DD_LIST_PREPEND(predef_act_list, data); + + _D("add predefine action entry suceessfully - %s", + data->type); + return 0; + err: + if (data->type != NULL) + _E("adding predefine action entry failed - %s", + data->type); + free(data); + return -1; +} + +int register_msg(struct sysnoti *msg) +{ + struct action_entry *data; + + data = malloc(sizeof(struct action_entry)); + + if (data == NULL) { + _E("Malloc failed"); + return -1; + } + + if (find_action_entry(msg->type) != NULL) + goto err; + + data->handle = dlopen(msg->path, RTLD_LAZY); + if (!data->handle) { + _E("cannot find such library"); + goto err; + } + + data->predefine_action = dlsym(data->handle, PREDEFINE_ACT_FUNC_STR); + if (data->predefine_action == NULL) { + _E("cannot find predefine_action symbol : %s", + PREDEFINE_ACT_FUNC_STR); + goto err; + } + + data->is_accessible = dlsym(data->handle, IS_ACCESSIBLE_FUNC_STR); + data->ui_viewable = dlsym(data->handle, UI_VIEWABLE_FUNC_STR); + data->owner_pid = msg->pid; + data->type = strdup(msg->type); + data->path = strdup(msg->path); + + DD_LIST_PREPEND(predef_act_list, data); + + _D("add predefine action entry suceessfully - %s", + data->type); + return 0; + err: + _E("adding predefine action entry failed - %s", msg->type); + free(data); + return -1; +} + +int notify_action(char *type, int argc, ...) +{ + dd_list *tmp; + struct action_entry *data; + va_list argptr; + int i; + int ret; + char *args = NULL; + char *argv[SYSMAN_MAXARG]; + + if (argc > SYSMAN_MAXARG || type == NULL) + return -1; + + DD_LIST_FOREACH(predef_act_list, tmp, data) { + if (strcmp(data->type, type)) + continue; + va_start(argptr, argc); + for (i = 0; i < argc; i++) { + args = va_arg(argptr, char *); + if (args != NULL) + argv[i] = strdup(args); + else + argv[i] = NULL; + } + va_end(argptr); + ret=run_queue_add(data, argc, argv); + ret=core_action_run(); + return 0; + } + + return 0; +} + +int notify_msg(struct sysnoti *msg, int sockfd) +{ + dd_list *tmp; + struct action_entry *data; + int ret; + + DD_LIST_FOREACH(predef_act_list, tmp, data) { + if (strcmp(data->type, msg->type)) + continue; + if (data->is_accessible != NULL + && data->is_accessible(sockfd) == 0) { + _E("%d cannot call that predefine module", msg->pid); + return -1; + } + ret=run_queue_add(data, msg->argc, msg->argv); + ret=core_action_run(); + return 0; + } + + _E("cannot found action"); + return -1; +} + +int run_queue_add(struct action_entry *act_entry, int argc, char **argv) +{ + struct run_queue_entry *rq_entry; + int i; + + rq_entry = malloc(sizeof(struct run_queue_entry)); + + if (rq_entry == NULL) { + _E("Malloc failed"); + return -1; + } + + rq_entry->state = STATE_INIT; + rq_entry->action_entry = act_entry; + rq_entry->forked_pid = 0; + if ( argc < 0 ) { + rq_entry->argc = 0; + } else { + rq_entry->argc = argc; + for (i = 0; i < argc; i++) + rq_entry->argv[i] = argv[i]; + } + + DD_LIST_PREPEND(run_queue, rq_entry); + + return 0; +} + +int run_queue_run(enum run_state state, + int (*run_func) (void *, struct run_queue_entry *), + void *user_data) +{ + dd_list *tmp; + struct run_queue_entry *rq_entry; + + DD_LIST_FOREACH(run_queue, tmp, rq_entry) { + if (rq_entry->state == state) + run_func(user_data, rq_entry); + } + + return 0; +} + +struct run_queue_entry *run_queue_find_bypid(int pid) +{ + dd_list *tmp; + struct run_queue_entry *rq_entry; + + DD_LIST_FOREACH(run_queue, tmp, rq_entry) { + if (rq_entry->forked_pid == pid) + return rq_entry; + } + + return NULL; +} + +int run_queue_del(struct run_queue_entry *entry) +{ + dd_list *tmp; + struct run_queue_entry *rq_entry; + int i; + + DD_LIST_FOREACH(run_queue, tmp, rq_entry) { + if (rq_entry == entry) { + DD_LIST_REMOVE(run_queue, rq_entry); + for (i = 0; i < rq_entry->argc; i++) { + if (rq_entry->argv[i]) + free(rq_entry->argv[i]); + } + free(rq_entry); + } + } + + return 0; +} + +int run_queue_del_bypid(int pid) +{ + dd_list *tmp; + struct run_queue_entry *rq_entry; + int i; + + DD_LIST_FOREACH(run_queue, tmp, rq_entry) { + if (rq_entry->forked_pid == pid) { + DD_LIST_REMOVE(run_queue, rq_entry); + for (i = 0; i < rq_entry->argc; i++) { + if (rq_entry->argv[i]) + free(rq_entry->argv[i]); + } + free(rq_entry); + } + } + + return 0; +} diff --git a/src/core/queue.h b/src/core/queue.h new file mode 100644 index 0000000..dee1e7e --- /dev/null +++ b/src/core/queue.h @@ -0,0 +1,67 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 __QUEUE_H__ +#define __QUEUE_H__ + +#include "sysnoti.h" + +struct action_entry { + int owner_pid; + void *handle; + char *type; + char *path; + int (*predefine_action) (); + int (*ui_viewable) (); + int (*is_accessible) (int caller_sockfd); +}; + +enum run_state { + STATE_INIT, + STATE_RUNNING, + STATE_DONE +}; + +struct run_queue_entry { + enum run_state state; + struct action_entry *action_entry; + int forked_pid; + int argc; + char *argv[SYSMAN_MAXARG]; +}; + +int register_action(char *type, + int (*predefine_action) (), + int (*ui_viewable) (), + int (*is_accessible) (int)); +int notify_action(char *type, int argc, ...); + +int register_msg(struct sysnoti *msg); +int notify_msg(struct sysnoti *msg, int sockfd); + +int run_queue_run(enum run_state state, + int (*run_func) (void *, struct run_queue_entry *), + void *user_data); + +struct run_queue_entry *run_queue_find_bypid(int pid); +int run_queue_add(struct action_entry *act_entry, int argc, char **argv); +int run_queue_del(struct run_queue_entry *entry); +int run_queue_del_bypid(int pid); + +#endif /* __QUEUE_H__ */ diff --git a/src/core/sig-handler.c b/src/core/sig-handler.c new file mode 100644 index 0000000..89deee8 --- /dev/null +++ b/src/core/sig-handler.c @@ -0,0 +1,93 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 "core.h" +#include "log.h" +#include "edbus-handler.h" +#include "display/poll.h" +#include "devices.h" +#include "common.h" + +#if 0 +#define _E(format, args...) do { \ + char buf[255];\ + snprintf(buf, 255, format, ##args);\ + write(2, buf, strlen(buf));\ +} while (0); + +#define _D(format, args...) do { \ + char buf[255];\ + snprintf(buf, 255, format, ##args);\ + write(1, buf, strlen(buf));\ +} while (0); +#endif + +static struct sigaction sig_child_old_act; +static struct sigaction sig_pipe_old_act; + +static void sig_child_handler(int signo, siginfo_t *info, void *data) +{ + pid_t pid; + int status; + + if (!info || signo != SIGCHLD) + return; + + pid = waitpid(info->si_pid, &status, 0); + if (pid == -1) { + _E("SIGCHLD received\n"); + return; + } + + _D("sig child actend call - %d\n", info->si_pid); +} + +static void sig_pipe_handler(int signo, siginfo_t *info, void *data) +{ + +} + +static void signal_init(void *data) +{ + struct sigaction sig_act; + + sig_act.sa_handler = NULL; + sig_act.sa_sigaction = sig_child_handler; + sig_act.sa_flags = SA_SIGINFO; + sigemptyset(&sig_act.sa_mask); + sigaction(SIGCHLD, &sig_act, &sig_child_old_act); + + sig_act.sa_handler = NULL; + sig_act.sa_sigaction = sig_pipe_handler; + sig_act.sa_flags = SA_SIGINFO; + sigemptyset(&sig_act.sa_mask); + sigaction(SIGPIPE, &sig_act, &sig_pipe_old_act); +} + +static const struct device_ops signal_device_ops = { + .priority = DEVICE_PRIORITY_NORMAL, + .name = "signal", + .init = signal_init, +}; + +DEVICE_OPS_REGISTER(&signal_device_ops) diff --git a/src/core/sysnoti.c b/src/core/sysnoti.c new file mode 100755 index 0000000..7fe6b2f --- /dev/null +++ b/src/core/sysnoti.c @@ -0,0 +1,342 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 "data.h" +#include "log.h" +#include "queue.h" +#include "common.h" +#include "devices.h" + +#define SYSNOTI_SOCKET_PATH "/tmp/sn" +#define RETRY_READ_COUNT 5 +enum sysnoti_cmd { + REGISTER_MSG, + NOTIFY_MSG +}; + +static Ecore_Fd_Handler *sysnoti_efd = NULL; +static int sysnoti_fd; +static int __sysnoti_start(void); +static int __sysnoti_stop(int fd); + +static void print_sysnoti_msg(const char *title, struct sysnoti *msg) +{ + int i; + char exe_name[PATH_MAX]; + + if (get_cmdline_name(msg->pid, exe_name, PATH_MAX) < 0) + snprintf(exe_name, sizeof(exe_name), "Unknown (maybe dead)"); + + _SD("pid : %d name: %s cmd : %d type : %s path : %s", + msg->pid, exe_name, msg->cmd, msg->type, msg->path); +} + +static inline int recv_int(int fd) +{ + int val, r = -1; + int retry_count = 0; + while (retry_count < RETRY_READ_COUNT) { + r = read(fd, &val, sizeof(int)); + if (r < 0) { + if(errno == EINTR) { + _D("Re-read for error(EINTR)"); + retry_count++; + continue; + } + else { + _E("Read fail for int"); + return -1; + } + } else { + return val; + } + } + return -1; +} + +static inline char *recv_str(int fd) +{ + int len, r = -1; + int retry_count = 0; + char *str; + + while (retry_count < RETRY_READ_COUNT) { + r = read(fd, &len, sizeof(int)); + if (r < 0) { + if(errno == EINTR) { + _D("Re-read for error(EINTR)"); + retry_count++; + continue; + } + else { + _E("Read fail for str length"); + return NULL; + } + } else + break; + } + if (retry_count == RETRY_READ_COUNT) { + _E("Read retry failed"); + return NULL; + } + if (len <= 0) + return NULL; + + if (len >= INT_MAX) { + _E("size is over INT_MAX"); + return NULL; + } + + str = (char *)malloc(len + 1); + if (str == NULL) { + _E("Not enough memory"); + return NULL; + } + retry_count = 0; + while (retry_count < RETRY_READ_COUNT) { + r = read(fd, str, len); + if(r < 0) { + if(errno == EINTR) { + _D("Re-read for error(EINTR)"); + retry_count++; + continue; + } else { + _E("Read fail for str"); + free(str); + str = NULL; + return NULL; + } + } else + break; + } + if (retry_count == RETRY_READ_COUNT) { + _E("Read retry failed"); + free(str); + str = NULL; + return NULL; + } + + str[len] = 0; + return str; +} + +static int read_message(int fd, struct sysnoti *msg) +{ + int i; + + if ((msg->pid = recv_int(fd)) == -1) + return -1; + if ((msg->cmd = recv_int(fd)) == -1) + return -1; + if ((msg->type = recv_str(fd)) == NULL) + return -1; + msg->path = recv_str(fd); + msg->argc = recv_int(fd); + + if (msg->argc < 0) + return -1; + for (i = 0; i < msg->argc; i++) + msg->argv[i] = recv_str(fd); + + return 0; +} + +static inline void internal_free(char *str) +{ + if (str) + free(str); +} + +static inline void free_message(struct sysnoti *msg) +{ + internal_free(msg->type); + internal_free(msg->path); + free(msg); +} + +static Eina_Bool sysnoti_cb(void *data, Ecore_Fd_Handler * fd_handler) +{ + struct sysnoti *msg; + int ret = -1; + struct sockaddr_un client_address; + int client_sockfd; + int client_len; + + if (!ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ)) { + _E("ecore_main_fd_handler_active_get error , return"); + goto out; + } + + msg = malloc(sizeof(struct sysnoti)); + if (msg == NULL) { + _E("Not enough memory"); + goto out; + } + + client_len = sizeof(client_address); + client_sockfd = accept(sysnoti_fd, (struct sockaddr *)&client_address, (socklen_t *)&client_len); + + if (client_sockfd == -1) { + _E("socket accept error"); + free(msg); + goto out; + } + if (read_message(client_sockfd, msg) < 0) { + _E("recv error msg"); + print_sysnoti_msg(__FUNCTION__, msg); + free_message(msg); + write(client_sockfd, &ret, sizeof(int)); + close(client_sockfd); + __sysnoti_stop(sysnoti_fd); + __sysnoti_start(); + goto out; + } + + print_sysnoti_msg(__FUNCTION__, msg); + if (msg->argc > SYSMAN_MAXARG) { + _E("error argument"); + free_message(msg); + write(client_sockfd, &ret, sizeof(int)); + close(client_sockfd); + goto out; + } + + switch (msg->cmd) { +#ifdef NOUSE + case REGISTER_MSG: + ret = register_msg(msg); + _E("%d", ret); + break; +#endif + case NOTIFY_MSG: + ret = notify_msg(msg, client_sockfd); + break; + default: + ret = -1; + } + + + write(client_sockfd, &ret, sizeof(int)); + close(client_sockfd); + + free_message(msg); +out: + return EINA_TRUE; +} + +static int sysnoti_server_init(void) +{ + int fd; + struct sockaddr_un serveraddr; + + if (access(SYSNOTI_SOCKET_PATH, F_OK) == 0) + unlink(SYSNOTI_SOCKET_PATH); + + fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd < 0) { + _E("socket create failed"); + return -1; + } + if((fsetxattr(fd, "security.SMACK64IPOUT", "@", 2, 0)) < 0 ) { + _E("Socket SMACK labeling failed"); + if(errno != EOPNOTSUPP) { + close(fd); + return -1; + } + } + + if((fsetxattr(fd, "security.SMACK64IPIN", "*", 2, 0)) < 0 ) { + _E("Socket SMACK labeling failed"); + if(errno != EOPNOTSUPP) { + close(fd); + return -1; + } + } + + bzero(&serveraddr, sizeof(struct sockaddr_un)); + serveraddr.sun_family = AF_UNIX; + strncpy(serveraddr.sun_path, SYSNOTI_SOCKET_PATH, + sizeof(serveraddr.sun_path)); + + if (bind(fd, (struct sockaddr *)&serveraddr, sizeof(struct sockaddr)) < 0) { + _E("socket bind failed"); + close(fd); + return -1; + } + + if (chmod(SYSNOTI_SOCKET_PATH, (S_IRWXU | S_IRWXG | S_IRWXO)) < 0) /* 0777 */ + _E("failed to change the socket permission"); + + if (listen(fd, 5) < 0) { + _E("failed to listen"); + close(fd); + return -1; + } + + return fd; +} + +static int __sysnoti_start(void) +{ + sysnoti_fd = sysnoti_server_init(); + if ( sysnoti_fd < 0 ) + return -1; + sysnoti_efd = ecore_main_fd_handler_add(sysnoti_fd, ECORE_FD_READ, sysnoti_cb, NULL, NULL, + NULL); + if (!sysnoti_efd) { + _E("error ecore_main_fd_handler_add"); + close(sysnoti_fd); + return -1; + } + return 0; +} + +static int __sysnoti_stop(int fd) +{ + if (sysnoti_efd) { + ecore_main_fd_handler_del(sysnoti_efd); + sysnoti_efd = NULL; + } + if (fd >=0) { + close(fd); + fd = -1; + } + return 0; +} + +static void sysnoti_init(void *data) +{ + struct main_data *ad = (struct main_data*)data; + + if (__sysnoti_start() == -1) + _E("fail sys socket fd init"); +} + +static const struct device_ops sysnoti_device_ops = { + .priority = DEVICE_PRIORITY_NORMAL, + .name = "sysnoti", + .init = sysnoti_init, +}; + +DEVICE_OPS_REGISTER(&sysnoti_device_ops) diff --git a/src/core/sysnoti.h b/src/core/sysnoti.h new file mode 100644 index 0000000..aee5fee --- /dev/null +++ b/src/core/sysnoti.h @@ -0,0 +1,34 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 __SYSNOTI_H__ +#define __SYSNOTI_H__ + +#define SYSMAN_MAXARG 16 + +struct sysnoti { + int pid; + int cmd; + char *type; + char *path; + int argc; + char *argv[SYSMAN_MAXARG]; +}; + +#endif /* __SYSNOTI_H__ */ diff --git a/src/core/udev.h b/src/core/udev.h new file mode 100644 index 0000000..69a0934 --- /dev/null +++ b/src/core/udev.h @@ -0,0 +1,98 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 __UDEV_H__ +#define __UDEV_H__ + +#include + +#define UDEV "kernel" +#define UDEV_SUBSYSTEM "SUBSYSTEM" + +#define UDEV_ACTION "ACTION" +#define UDEV_CHANGE "change" +#define UDEV_ADD "add" +#define UDEV_REMOVE "remove" + +#define UDEV_DEVPATH "DEVPATH" + +#define UDEV_MONITOR_SIZE (10*1024) +#define UDEV_MONITOR_SIZE_LARGE (128*1024*1024) + +/* platform */ +#define PLATFORM_SUBSYSTEM "platform" +#define THERMISTOR_PATH "*/sec-thermistor" + +/* battery device */ +#define POWER_SUBSYSTEM "power_supply" +#define POWER_PATH "/sys/class/power_supply/battery" +#define POWER_SUPPLY_UEVENT POWER_PATH"/uevent" +#define CAPACITY "POWER_SUPPLY_CAPACITY" +#define CHARGE_FULL "POWER_SUPPLY_CHARGE_FULL" +#define CHARGE_NOW "POWER_SUPPLY_CHARGE_NOW" +#define CHARGE_HEALTH "POWER_SUPPLY_HEALTH" +#define CHARGE_PRESENT "POWER_SUPPLY_PRESENT" +#define CHARGE_NAME "POWER_SUPPLY_NAME" +#define CHARGE_STATUS "POWER_SUPPLY_STATUS" +#define CHARGE_ONLINE "POWER_SUPPLY_ONLINE" + +/* input device */ +#define INPUT_SUBSYSTEM "input" +#define INPUT_PATH "*/input[0-9]*/event[0-9]*" + +/* lcd esd device */ +#define LCD_EVENT_SUBSYSTEM "lcd_event" +#define LCD_ESD_PATH "*/lcd_event/esd" + +/* switch device */ +#define SWITCH_SUBSYSTEM "switch" + +/* host device */ +#define HOST_SUBSYSTEM "host_notify" + +/* power supply status */ +enum { + POWER_SUPPLY_STATUS_UNKNOWN = 0, + POWER_SUPPLY_STATUS_CHARGING, + POWER_SUPPLY_STATUS_DISCHARGING, + POWER_SUPPLY_STATUS_NOT_CHARGING, + POWER_SUPPLY_STATUS_FULL, +}; + +enum { + POWER_SUPPLY_TYPE_UNKNOWN = 0, + POWER_SUPPLY_TYPE_BATTERY, + POWER_SUPPLY_TYPE_UPS, + POWER_SUPPLY_TYPE_MAINS, + POWER_SUPPLY_TYPE_USB, +}; + +struct uevent_handler { + char *subsystem; + void (*uevent_func)(struct udev_device *dev); + void *data; +}; + +int register_uevent_control(const struct uevent_handler *uh); +void unregister_uevent_control(const struct uevent_handler *uh); +int register_kernel_uevent_control(const struct uevent_handler *uh); +void unregister_kernel_uevent_control(const struct uevent_handler *uh); + + +#endif /* __UDEV_H__ */ diff --git a/src/cpu/cpu-handler.c b/src/cpu/cpu-handler.c new file mode 100644 index 0000000..bc17054 --- /dev/null +++ b/src/cpu/cpu-handler.c @@ -0,0 +1,617 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 "core/list.h" +#include "core/log.h" +#include "core/data.h" +#include "core/devices.h" +#include "core/edbus-handler.h" +#include "core/common.h" +#include "core/device-notifier.h" +#include "proc/proc-handler.h" + +#define PREDEF_SET_MAX_FREQUENCY "set_max_frequency" +#define PREDEF_SET_MIN_FREQUENCY "set_min_frequency" +#define PREDEF_RELEASE_MAX_FREQUENCY "release_max_frequency" +#define PREDEF_RELEASE_MIN_FREQUENCY "release_min_frequency" +#define PREDEF_CPU_COUNT "set_cpu_count" + +#define POWER_SAVING_CPU_FREQ_RATE (0.7) + +#define DEFAULT_MAX_CPU_FREQ 1200000 +#define DEFAULT_MIN_CPU_FREQ 100000 + +enum emergency_type { + EMERGENCY_UNLOCK = 0, + EMERGENCY_LOCK = 1, +}; + +static int max_cpu_freq_limit = -1; +static int min_cpu_freq_limit = -1; +static int cur_max_cpu_freq = INT_MAX; +static int cur_min_cpu_freq = INT_MIN; +static int power_saving_freq = -1; + +static dd_list *max_cpu_freq_list; +static dd_list *min_cpu_freq_list; + +static int cpu_number_limit = -1; +static int cur_cpu_number = INT_MAX; +static dd_list *cpu_number_list; + +struct cpu_freq_entry { + int pid; + int freq; +}; + +struct cpu_number_entry { + int pid; + int number; +}; + +static int is_entry_enable(int pid) +{ + char pid_path[PATH_MAX]; + + snprintf(pid_path, PATH_MAX, "/proc/%d", pid); + if (access(pid_path, F_OK) < 0) { + return 0; + } + + return 1; +} + +static int write_min_cpu_freq(int freq) +{ + int ret; + + ret = device_set_property(DEVICE_TYPE_CPU, PROP_CPU_SCALING_MIN_FREQ, freq); + if (ret < 0) { + _E("set cpufreq min freq write error: %s", strerror(errno)); + return ret; + } + + return 0; +} + +static int write_max_cpu_freq(int freq) +{ + int ret; + + ret = device_set_property(DEVICE_TYPE_CPU, PROP_CPU_SCALING_MAX_FREQ, freq); + if (ret < 0) { + _E("set cpufreq max freq write error: %s", strerror(errno)); + return ret; + } + + return 0; +} + +static int remove_entry_from_min_cpu_freq_list(int pid) +{ + dd_list *tmp; + struct cpu_freq_entry *entry; + + cur_min_cpu_freq = INT_MIN; + + DD_LIST_FOREACH(min_cpu_freq_list, tmp, entry) { + if ((!is_entry_enable(entry->pid)) || (entry->pid == pid)) { + DD_LIST_REMOVE(min_cpu_freq_list, entry); + free(entry); + continue; + } + if (entry->freq > cur_min_cpu_freq) { + cur_min_cpu_freq = entry->freq; + } + } + + return 0; +} + +static int remove_entry_from_max_cpu_freq_list(int pid) +{ + dd_list *tmp; + struct cpu_freq_entry *entry; + + cur_max_cpu_freq = INT_MAX; + + DD_LIST_FOREACH(max_cpu_freq_list, tmp, entry) { + if ((!is_entry_enable(entry->pid)) || (entry->pid == pid)) { + DD_LIST_REMOVE(max_cpu_freq_list, entry); + free(entry); + continue; + } + if (entry->freq < cur_max_cpu_freq) { + cur_max_cpu_freq = entry->freq; + } + } + + return 0; +} + +int release_max_frequency_action(int argc, char **argv) +{ + int r; + + if (argc < 1) + return -EINVAL; + + r = remove_entry_from_max_cpu_freq_list(atoi(argv[0])); + if (r < 0) { + _E("Remove entry failed"); + return r; + } + + if (cur_max_cpu_freq == INT_MAX) + cur_max_cpu_freq = max_cpu_freq_limit; + + r = write_max_cpu_freq(cur_max_cpu_freq); + if (r < 0) { + _E("Write freq failed"); + return r; + } + + return 0; +} + +int release_min_frequency_action(int argc, char **argv) +{ + int r; + + if (argc < 1) + return -EINVAL; + + r = remove_entry_from_min_cpu_freq_list(atoi(argv[0])); + if (r < 0) { + _E("Remove entry failed"); + return r; + } + + if (cur_min_cpu_freq == INT_MIN) + cur_min_cpu_freq = min_cpu_freq_limit; + + r = write_min_cpu_freq(cur_min_cpu_freq); + if (r < 0) { + _E("Write entry failed"); + return r; + } + + return 0; +} + +static int add_entry_to_max_cpu_freq_list(int pid, int freq) +{ + int r; + struct cpu_freq_entry *entry; + + r = remove_entry_from_max_cpu_freq_list(pid); + if (r < 0) { + _E("Remove duplicated entry failed"); + } + + entry = malloc(sizeof(struct cpu_freq_entry)); + if (!entry) { + _E("Malloc failed"); + return -ENOMEM; + } + + entry->pid = pid; + entry->freq = freq; + + DD_LIST_PREPEND(max_cpu_freq_list, entry); + if (!max_cpu_freq_list) { + _E("eina_list_prepend failed"); + return -ENOSPC; + } + if (freq < cur_max_cpu_freq) { + cur_max_cpu_freq = freq; + } + return 0; +} + +static int add_entry_to_min_cpu_freq_list(int pid, int freq) +{ + int r; + struct cpu_freq_entry *entry; + + r = remove_entry_from_min_cpu_freq_list(pid); + if (r < 0) { + _E("Remove duplicated entry failed"); + } + + entry = malloc(sizeof(struct cpu_freq_entry)); + if (!entry) { + _E("Malloc failed"); + return -ENOMEM; + } + + entry->pid = pid; + entry->freq = freq; + + DD_LIST_PREPEND(min_cpu_freq_list, entry); + if (!min_cpu_freq_list) { + _E("eina_list_prepend failed"); + return -ENOSPC; + } + if (freq > cur_min_cpu_freq) { + cur_min_cpu_freq = freq; + } + return 0; +} + +int set_max_frequency_action(int argc, char **argv) +{ + int r; + + if (argc < 2) + return -EINVAL; + + r = add_entry_to_max_cpu_freq_list(atoi(argv[0]), atoi(argv[1])); + if (r < 0) { + _E("Add entry failed"); + return r; + } + + r = write_max_cpu_freq(cur_max_cpu_freq); + if (r < 0) { + _E("Write entry failed"); + return r; + } + + return 0; +} + +int set_min_frequency_action(int argc, char **argv) +{ + int r; + + if (argc < 2) + return -EINVAL; + + r = add_entry_to_min_cpu_freq_list(atoi(argv[0]), atoi(argv[1])); + if (r < 0) { + _E("Add entry failed"); + return r; + } + + r = write_min_cpu_freq(cur_min_cpu_freq); + if (r < 0) { + _E("Write entry failed"); + return r; + } + + return 0; +} + +static int power_saving_cpu_cb(keynode_t *key_nodes, void *data) +{ + int ret = 0; + int val = 0; + int power_saving_cpu_stat = -1; + + power_saving_cpu_stat = vconf_keynode_get_bool(key_nodes); + if (power_saving_cpu_stat == 1) { + val = 1; + ret = add_entry_to_max_cpu_freq_list(getpid(), power_saving_freq); + if (ret < 0) { + _E("Add entry failed"); + goto out; + } + } else { + ret = remove_entry_from_max_cpu_freq_list(getpid()); + if (ret < 0) { + _E("Remove entry failed"); + goto out; + } + if (cur_max_cpu_freq == INT_MAX) + cur_max_cpu_freq = max_cpu_freq_limit; + } + ret = write_max_cpu_freq(cur_max_cpu_freq); + if (ret < 0) + _E("Write failed"); +out: + device_notify(DEVICE_NOTIFIER_PMQOS_POWERSAVING, (void*)val); + return ret; +} + +static void set_emergency_limit(void) +{ + int ret, val; + + ret = vconf_get_int(VCONFKEY_SETAPPL_PSMODE, &val); + if (ret < 0) { + _E("failed to get vconf key"); + return; + } + if (val != SETTING_PSMODE_EMERGENCY) + return; + + val = EMERGENCY_LOCK; + device_notify(DEVICE_NOTIFIER_PMQOS_EMERGENCY, (void*)val); + +} +static int emergency_cpu_cb(keynode_t *key_nodes, void *data) +{ + int val; + + val = vconf_keynode_get_int(key_nodes); + if (val == SETTING_PSMODE_EMERGENCY) + val = EMERGENCY_LOCK; + else + val = EMERGENCY_UNLOCK; + + device_notify(DEVICE_NOTIFIER_PMQOS_EMERGENCY, (void*)val); + return 0; +} + +static void set_freq_limit(void) +{ + int ret = 0; + int val = 0; + int power_saving_stat = -1; + int power_saving_cpu_stat = -1; + + ret = device_get_property(DEVICE_TYPE_CPU, PROP_CPU_CPUINFO_MAX_FREQ, + &max_cpu_freq_limit); + if (ret < 0) { + _E("get cpufreq cpuinfo max readerror: %s", strerror(errno)); + max_cpu_freq_limit = DEFAULT_MAX_CPU_FREQ; + } + + ret = device_get_property(DEVICE_TYPE_CPU, PROP_CPU_CPUINFO_MIN_FREQ, + &min_cpu_freq_limit); + if (ret < 0) { + _E("get cpufreq cpuinfo min readerror: %s", strerror(errno)); + min_cpu_freq_limit = DEFAULT_MIN_CPU_FREQ; + } + power_saving_freq = (int)(max_cpu_freq_limit * POWER_SAVING_CPU_FREQ_RATE); + _I("max(%d) , ps(%d), min(%d)", + max_cpu_freq_limit, + power_saving_freq, + min_cpu_freq_limit); + + ret = vconf_get_bool(VCONFKEY_SETAPPL_PWRSV_CUSTMODE_CPU, + &power_saving_cpu_stat); + if (ret < 0) { + _E("failed to get vconf key"); + return; + } + if (power_saving_cpu_stat != 1) + return; + val = 1; + ret = add_entry_to_max_cpu_freq_list(getpid(), power_saving_freq); + if (ret < 0) { + _E("Add entry failed"); + goto out; + } + ret = write_max_cpu_freq(cur_max_cpu_freq); + if (ret < 0) + _E("Write entry failed"); +out: + _I("init"); + device_notify(DEVICE_NOTIFIER_PMQOS_POWERSAVING, (void*)val); +} + +static void set_cpu_number_limit(void) +{ + device_get_property(DEVICE_TYPE_CPU, PROP_CPU_ENABLE_MAX_NUMBER, + &cpu_number_limit); +} + +static int write_cpu_number(int number) +{ + int ret; + + ret = device_set_property(DEVICE_TYPE_CPU, PROP_CPU_ENABLE_MAX_NUMBER, + number); + if (ret < 0) { + _E("set cpu number max write error: %s", strerror(errno)); + return ret; + } + + return 0; +} + +static int remove_entry_from_cpu_number_list(int pid) +{ + dd_list *tmp; + struct cpu_number_entry *entry; + + cur_cpu_number = INT_MAX; + + DD_LIST_FOREACH(cpu_number_list, tmp, entry) { + if ((!is_entry_enable(entry->pid)) || (entry->pid == pid)) { + DD_LIST_REMOVE(cpu_number_list, entry); + free(entry); + continue; + } + if (entry->number < cur_cpu_number) { + cur_cpu_number = entry->number; + } + } + + return 0; +} + +static int add_entry_to_cpu_number_list(int pid, int number) +{ + int r; + struct cpu_number_entry *entry; + + r = remove_entry_from_cpu_number_list(pid); + if (r < 0) { + _E("Remove duplicated entry failed"); + } + + + + entry = malloc(sizeof(struct cpu_number_entry)); + if (!entry) { + _E("Malloc failed"); + return -ENOMEM; + } + + entry->pid = pid; + entry->number = number; + + DD_LIST_PREPEND(cpu_number_list, entry); + if (!cpu_number_list) { + _E("eina_list_prepend failed"); + return -ENOSPC; + } + if (number < cur_cpu_number) { + cur_cpu_number = number; + } + return 0; +} + +int set_cpu_number_action(int argc, char **argv) +{ + int r; + + if(cur_siop_level() != 0) + return -EINVAL; + + if (argc == 1) {// release cpu number + r = remove_entry_from_cpu_number_list(atoi(argv[0])); + if (r < 0) { + _E("Remove entry failed"); + return r; + } + + if (cur_cpu_number == INT_MAX) + cur_cpu_number = cpu_number_limit; + + r = write_cpu_number(cur_cpu_number); + if (r < 0) { + _E("Write cpu number failed"); + return r; + } + } else if (argc ==2) {//set cpu number + r = add_entry_to_cpu_number_list(atoi(argv[0]), atoi(argv[1])); + if (r < 0) { + _E("Add entry failed"); + return r; + } + + r = write_cpu_number(cur_cpu_number); + if (r < 0) { + _E("Write entry failed"); + return r; + } + } + return 0; +} + +static int booting_done(void *data) +{ + set_freq_limit(); + set_emergency_limit(); + return 0; +} + +static DBusMessage *dbus_cpu_handler(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusError err; + DBusMessageIter iter; + DBusMessage *reply; + pid_t pid; + int ret; + int argc; + char *type_str; + char *argv[2]; + + dbus_error_init(&err); + + if (!dbus_message_get_args(msg, &err, + DBUS_TYPE_STRING, &type_str, + DBUS_TYPE_INT32, &argc, + DBUS_TYPE_STRING, &argv[0], + DBUS_TYPE_STRING, &argv[1], DBUS_TYPE_INVALID)) { + _E("there is no message"); + ret = -EINVAL; + goto out; + } + + if (argc < 0) { + _E("message is invalid!"); + ret = -EINVAL; + goto out; + } + + pid = get_edbus_sender_pid(msg); + if (kill(pid, 0) == -1) { + _E("%d process does not exist, dbus ignored!", pid); + ret = -ESRCH; + goto out; + } + + if (strncmp(type_str, PREDEF_SET_MAX_FREQUENCY, strlen(PREDEF_SET_MAX_FREQUENCY)) == 0) + ret = set_max_frequency_action(argc, (char **)&argv); + else if (strncmp(type_str, PREDEF_SET_MIN_FREQUENCY, strlen(PREDEF_SET_MIN_FREQUENCY)) == 0) + ret = set_min_frequency_action(argc, (char **)&argv); + else if (strncmp(type_str, PREDEF_RELEASE_MAX_FREQUENCY, strlen(PREDEF_RELEASE_MAX_FREQUENCY)) == 0) + ret = release_max_frequency_action(argc, (char **)&argv); + else if (strncmp(type_str, PREDEF_RELEASE_MIN_FREQUENCY, strlen(PREDEF_RELEASE_MIN_FREQUENCY)) == 0) + ret = release_min_frequency_action(argc, (char **)&argv); +out: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + + return reply; +} + +static const struct edbus_method edbus_methods[] = { + { PREDEF_SET_MAX_FREQUENCY, "siss", "i", dbus_cpu_handler }, + { PREDEF_SET_MIN_FREQUENCY, "siss", "i", dbus_cpu_handler }, + { PREDEF_RELEASE_MAX_FREQUENCY, "siss", "i", dbus_cpu_handler }, + { PREDEF_RELEASE_MIN_FREQUENCY, "siss", "i", dbus_cpu_handler }, +}; + +static void cpu_init(void *data) +{ + int ret; + + register_notifier(DEVICE_NOTIFIER_BOOTING_DONE, booting_done); + ret = register_edbus_method(DEVICED_PATH_SYSNOTI, edbus_methods, ARRAY_SIZE(edbus_methods)); + if (ret < 0) + _E("fail to init edbus method(%d)", ret); + set_cpu_number_limit(); + register_action(PREDEF_SET_MAX_FREQUENCY, set_max_frequency_action, NULL, NULL); + register_action(PREDEF_SET_MIN_FREQUENCY, set_min_frequency_action, NULL, NULL); + register_action(PREDEF_RELEASE_MAX_FREQUENCY, release_max_frequency_action, NULL, NULL); + register_action(PREDEF_RELEASE_MIN_FREQUENCY, release_min_frequency_action, NULL, NULL); + register_action(PREDEF_CPU_COUNT, set_cpu_number_action, NULL, NULL); + + vconf_notify_key_changed(VCONFKEY_SETAPPL_PWRSV_CUSTMODE_CPU, (void *)power_saving_cpu_cb, NULL); + vconf_notify_key_changed(VCONFKEY_SETAPPL_PSMODE, (void *)emergency_cpu_cb, NULL); +} + +static const struct device_ops cpu_device_ops = { + .priority = DEVICE_PRIORITY_NORMAL, + .name = "cpu", + .init = cpu_init, +}; + +DEVICE_OPS_REGISTER(&cpu_device_ops) diff --git a/src/devicectl/CMakeLists.txt b/src/devicectl/CMakeLists.txt new file mode 100755 index 0000000..5d12dc4 --- /dev/null +++ b/src/devicectl/CMakeLists.txt @@ -0,0 +1,39 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(devicectl C) + +IF("$ENV{CFLAGS}" MATCHES "-DTIZEN_ENGINEER_MODE") + OPTION(USE_ENGINEER_MODE "Use Engineer mode" ON) +ENDIF() + +SET(SRCS + devicectl.c +) +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/src) + +INCLUDE(FindPkgConfig) +pkg_check_modules(pkgs REQUIRED dbus-1) + +FOREACH(flag ${pkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +IF(USE_ENGINEER_MODE) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -g -fno-omit-frame-pointer -finstrument-functions") +ELSE() + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -g -fno-omit-frame-pointer") +ENDIF() + +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") +MESSAGE("FLAGS: ${CMAKE_C_FLAGS}") + +ADD_DEFINITIONS("-DPREFIX=\"${CMAKE_INSTALL_PREFIX}\"") +ADD_DEFINITIONS("-DFACTORYFS=\"$ENV{FACTORYFS}\"") +IF( $ENV{ARCH} MATCHES "arm" ) + ADD_DEFINITIONS("-DTARGET") +ENDIF() + +ADD_EXECUTABLE(${PROJECT_NAME} ${SRCS}) +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS} shared) + +INSTALL(TARGETS ${PROJECT_NAME} DESTINATION bin) + diff --git a/src/devicectl/devicectl.c b/src/devicectl/devicectl.c new file mode 100644 index 0000000..d9dcfef --- /dev/null +++ b/src/devicectl/devicectl.c @@ -0,0 +1,211 @@ +/* + * devicectl + * + * Copyright (c) 2012 - 2013 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 +#include +#include +#include + +/* + * devicectl [device] [action] + * ex> devicectl display stop + * devicectl pass start + */ + +enum device_type { + DEVICE_CORE, + DEVICE_DISPLAY, + DEVICE_LED, + DEVICE_PASS, + DEVICE_MAX, + DEVICE_ALL, +}; +static enum device_type arg_id; + +static const struct device { + const enum device_type id; + const char *name; + const char *path; + const char *iface; +} devices[] = { + { DEVICE_CORE, "core", DEVICED_PATH_CORE, DEVICED_INTERFACE_CORE }, + { DEVICE_DISPLAY, "display", DEVICED_PATH_DISPLAY, DEVICED_INTERFACE_DISPLAY }, + { DEVICE_LED, "led", DEVICED_PATH_LED, DEVICED_INTERFACE_LED }, + { DEVICE_PASS, "pass", DEVICED_PATH_PASS, DEVICED_INTERFACE_PASS }, +}; + +static int start_device(char **args) +{ + DBusMessage *msg; + + if (!args[1]) + return -EINVAL; + + printf("start %s device!\n", args[1]); + + msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME, + devices[arg_id].path, devices[arg_id].iface, + "start", NULL, NULL); + if (!msg) + return -EBADMSG; + + dbus_message_unref(msg); + + return 0; +} + +static int stop_device(char **args) +{ + DBusMessage *msg; + + if (!args[1]) + return -EINVAL; + + printf("start %s device!\n", args[1]); + + msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME, + devices[arg_id].path, devices[arg_id].iface, + "stop", NULL, NULL); + if (!msg) + return -EBADMSG; + + dbus_message_unref(msg); + + return 0; +} + +static int dump_mode(char **args) +{ + DBusError err; + DBusMessage *msg; + int ret, val; + char *arr[1]; + + if (!args[1] || !args[2] || !args[3]) + return -EINVAL; + + printf("%s (%s %s)!\n", args[1], args[2], args[3]); + + arr[0] = args[3]; + msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME, + devices[arg_id].path, devices[arg_id].iface, + "Dumpmode", "s", arr); + if (!msg) + return -EBADMSG; + + dbus_error_init(&err); + + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &val, DBUS_TYPE_INVALID); + if (!ret) { + printf("no message : [%s:%s]", err.name, err.message); + dbus_error_free(&err); + val = -ENOMSG; + } + + dbus_message_unref(msg); + return val; +} + +static int save_log(char **args) +{ + DBusMessage *msg; + + if (!args[1]) + return -EINVAL; + + printf("save log %s device!\n", args[1]); + + msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME, + devices[arg_id].path, devices[arg_id].iface, + "SaveLog", NULL, NULL); + if (!msg) + return -EBADMSG; + + dbus_message_unref(msg); + + return 0; +} + +static const struct action { + const enum device_type id; + const char *action; + const int argc; + int (* const func)(char **args); +} actions[] = { + { DEVICE_ALL, "start", 3, start_device }, + { DEVICE_ALL, "stop", 3, stop_device }, + { DEVICE_DISPLAY, "dumpmode", 4, dump_mode }, + { DEVICE_LED, "dumpmode", 4, dump_mode }, + { DEVICE_DISPLAY, "savelog", 3, save_log }, +}; + +static inline void usage() +{ + printf("[usage] devicectl \n"); +} + +int main(int argc, char *argv[]) +{ + int i; + + if (argc < 3) { + usage(); + return -EINVAL; + } + + for (i = 0; i < argc; i++) + if (argv[i] == NULL) { + usage(); + return -EINVAL; + } + + for (i = 0; i < ARRAY_SIZE(devices); i++) + if (!strcmp(argv[1], devices[i].name)) + break; + + if (i >= ARRAY_SIZE(devices)) { + printf("invalid device name! %s\n", argv[1]); + usage(); + return -EINVAL; + } + + arg_id = devices[i].id; + + for (i = 0; i < ARRAY_SIZE(actions); i++) + if (actions[i].id == arg_id || actions[i].id == DEVICE_ALL) + if (!strcmp(argv[2], actions[i].action)) + break; + + if (i >= ARRAY_SIZE(actions)) { + printf("invalid action name! %s\n", argv[2]); + usage(); + return -EINVAL; + } + + if (actions[i].argc != argc) { + printf("invalid arg count!\n"); + usage(); + return -EINVAL; + } + + return actions[i].func(argv); +} + diff --git a/src/deviced/dd-battery.h b/src/deviced/dd-battery.h new file mode 100644 index 0000000..72beda3 --- /dev/null +++ b/src/deviced/dd-battery.h @@ -0,0 +1,147 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 __DD_BATTERY_H__ +#define __DD_BATTERY_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file dd-battery.h + * @defgroup CAPI_SYSTEM_DEVICED_BATTERY_MODULE Battery + * @ingroup CAPI_SYSTEM_DEVICED + * @brief This file provides the API for control of battery + * @section CAPI_SYSTEM_DEVICED_BATTERY_MODULE_HEADER Required Header + * \#include + */ + +/** + * @addtogroup CAPI_SYSTEM_DEVICED_BATTERY_MODULE + * @{ + */ + +/** + * @par Description + * Battery Health status + */ +enum { + BAT_UNKNOWN = 0, + BAT_GOOD, + BAT_OVERHEAT, + BAT_DEAD, + BAT_OVERVOLTAGE, + BAT_UNSPECIFIED, + BAT_COLD, + BAT_HEALTH_MAX, +}; + +/** + * @par Description: + * This API is used to get the remaining battery percentage.\n + * It gets the Battery percentage by calling device_get_property() function.\n + * It returns integer value(0~100) that indicates remaining batterty percentage on success.\n + * Or a negative value(-1) is returned on failure. + * @return On success, integer value(0~100) is returned. + * Or a negative value(-1) is returned on failure. + * @see battery_is_full(), battery_get_percent_raw() + * @par Example + * @code + * ... + * int battery; + * battery = battery_get_percent(); + * if( battery < 0 ) + * printf("Fail to get the remaining battery percentage.\n"); + * else + * printf("remaining battery percentage : %d\n", battery); + * ... + * @endcode + */ +int battery_get_percent(void); + +/** + * @par Description: + * This API is used to get the remaining battery percentage expressed 1/10000.\n + * It gets the Battery percentage by calling device_get_property() function.\n + * It returns integer value(0~10000) that indicates remaining batterty percentage on success.\n + * Or a negative value(-1) is returned on failure. + * @return On success, integer value(0~10000) is returned. + * Or a negative value(-1) is returned on failure. + * @see battery_is_full(), battery_get_percent() + * @par Example + * @code + * ... + * int battery; + * battery = battery_get_percent_raw(); + * if( battery < 0 ) + * printf("Fail to get the remaining battery percentage.\n"); + * else + * printf("remaining battery percentage expressed 1/10000 : %d\n", battery); + * ... + * @endcode + */ +int battery_get_percent_raw(void); + +/** + * @par Description: + * This API is used to get the fully charged status of battery.\n + * It gets the fully charged status of Battery by calling device_get_property() function.\n + * If the status of battery is full, it returns 1.\n + * Or a negative value(-1) is returned, if the status of battery is not full. + * @return 1 with battery full, or 0 on not full-charged, -1 if failed + * @see battery_get_percent() + * @par Example + * @code + * ... + * if( battery_is_full() > 0 ) + * printf("battery fully chared\n"); + * ... + * @endcode + */ +int battery_is_full(void); + +/** + * @par Description: + * This API is used to get the battery health status.\n + * It gets the battery health status by calling device_get_property() function.\n + * It returns integer value(0~7) that indicate battery health status on success.\n + * Or a negative value(-1) is returned, if the status of battery is not full. + * @return integer value, -1 if failed\n + * (0 BATTERY_UNKNOWN, 1 GOOD, 2 OVERHEAT, 3 DEAD, 4 OVERVOLTAGE, 5 UNSPECIFIED, 6 COLD, 7 BAT_HEALTH_MAX) + * @par Example + * @code + * ... + * int bat_health; + * bat_health = battery_get_health(); + * if( bat_health != BAT_GOOD ) + * printf("battery health is not good\n"); + * ... + * @endcode + */ +int battery_get_health(void); + +/** + * @} // end of CAPI_SYSTEM_DEVICED_BATTERY_MODULE + */ + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/deviced/dd-common.h b/src/deviced/dd-common.h new file mode 100644 index 0000000..fdfc2ac --- /dev/null +++ b/src/deviced/dd-common.h @@ -0,0 +1,39 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 __DD_COMMON_H__ +#define __DD_COMMON_H__ + +/** + * @file dd-common.h + * @ingroup CAPI_SYSTEM_DEVICED + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef DEPRECATED +#define DEPRECATED __attribute__((deprecated)) +#endif + +#ifdef __cplusplus +} +#endif +#endif /* __DD_COMMON_H__ */ diff --git a/src/deviced/dd-control.h b/src/deviced/dd-control.h new file mode 100644 index 0000000..c094196 --- /dev/null +++ b/src/deviced/dd-control.h @@ -0,0 +1,118 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 __DD_CONTROL_H__ +#define __DD_CONTROL_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/** + * @file dd-control.h + * @defgroup CAPI_SYSTEM_DEVICED_CONTROL_MODULE Control + * @ingroup CAPI_SYSTEM_DEVICED + * @brief This file provides the API to enable/disable devices + * @section CAPI_SYSTEM_DEVICED_CONTROL_MODULE_HEADER Required Header + * \#include + */ + +/** + * @addtogroup CAPI_SYSTEM_DEVICED_CONTROL_MODULE + * @{ + */ + +/** + * @par Description + * Control Device type + */ +enum control_device_type { +/* Add device define here */ + DEVICE_CONTROL_MMC, + DEVICE_CONTROL_USBCLIENT, + DEVICE_CONTROL_RGBLED, + DEVICE_CONTROL_MAX, +}; + +/** + * @par Description: + * This API is used to enable/disable mmc device.\n + * @param[in] enable enable/disable mmc device + * @return 0 on success, -1 if failed + * @par Example + * @code + * ... + * if( deviced_mmc_control(1) < 0 ) + * printf("Enable mmc device failed\n"); + * ... + * @endcode + */ +int deviced_mmc_control(bool enable); + +/** + * @par Description: + * This API is used to enable/disable usb device.\n + * @param[in] enable enable/disable usb device + * @return 0 on success, -1 if failed + * @par Example + * @code + * ... + * if( deviced_usb_control(1) < 0 ) + * printf("Enable usb device failed\n"); + * ... + * @endcode + */ +int deviced_usb_control(bool enable); + +/* Only USB-manager will use the api */ +/** + * @par Description: + * @return + * @par Example + * @code + * @endcode + * @todo describe function + */ +int deviced_get_usb_control(void); + +/** + * @par Description: + * This API is used to enable/disable rgbled device.\n + * @param[in] enable enable/disable usb device + * @return 0 on success, -1 if failed + * @par Example + * @code + * ... + * if( deviced_rgbled_control(true) < 0 ) + * printf("Enable rgbled device failed\n"); + * ... + * @endcode + */ +int deviced_rgbled_control(bool enable); + +/** + * @} // end of CAPI_SYSTEM_DEVICED_CONTROL_MODULE + */ + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/deviced/dd-deviced-managed.h b/src/deviced/dd-deviced-managed.h new file mode 100644 index 0000000..ba0af77 --- /dev/null +++ b/src/deviced/dd-deviced-managed.h @@ -0,0 +1,65 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 __DD_DEVICED_MANAGED_H__ +#define __DD_DEVICED_MANAGED_H__ + +#include +#include "dd-mmc.h" + +/** + * @file dd-deviced-managed.h + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @addtogroup CAPI_SYSTEM_DEVICED + * @{ + */ + +/** + * @fn int deviced_get_pid(const char *execpath) + * @brief This API is used to get the pid of the process which has the specified execpath.\n + * Internally, this API searches /proc/{pid}/cmdline and compares the parameter execpath with 1st argument of cmdline. \n + * If there is no process that has same execpath in /proc/{pid}/cmdline, it will return -1. + * @param[in] execpath program path which you want to know whether it is run or not + * @return pid when the program is running, -1 if it is not. + */ +int deviced_get_pid(const char *execpath); + +/** + * @fn int deviced_set_datetime(time_t timet) + * @brief This API is used to set date time.\n + * Internally, this API call predefined action API. That is send a notify message. \n + * @param[in] timet type of time which you want to set. + * @return pid when the program is running, -1 if param is less than 0 or when failed set datetime. + */ +int deviced_set_datetime(time_t timet); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif +#endif /* __DD_DEVICED_MANAGED_H__ */ diff --git a/src/deviced/dd-deviced.h b/src/deviced/dd-deviced.h new file mode 100644 index 0000000..92ef751 --- /dev/null +++ b/src/deviced/dd-deviced.h @@ -0,0 +1,402 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 __DD_DEVICED__ +#define __DD_DEVICED__ + +#include +#include +#include +#include +#include "dd-deviced-managed.h" + +/** + * @file dd-deviced.h + * @defgroup CAPI_SYSTEM_DEVICED_UTIL_MODULE Util + * @ingroup CAPI_SYSTEM_DEVICED + * @section CAPI_SYSTEM_DEVICED_UTIL_MODULE_HEADER Required Header + * \#include + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @addtogroup CAPI_SYSTEM_DEVICED_UTIL_MODULE + * @{ + */ + +/** + * @brief Policy for low memory + */ +enum mem_policy { + OOM_LIKELY, /**< For miscellaneous applications */ + OOM_IGNORE /**< For daemons */ +}; + +#define CRASH_TICKET_PATH "/opt/usr/share/crash/ticket" +#define FORCED_DUMP_DIR_PATH "/opt/usr/media/SLP_debug" +#define FORCED_DUMP_ZIP_PATH "/opt/usr/media/SLP_debug/zip" + +/** + * @brief Logs dump type + */ +enum dump_log_type { + AP_DUMP = 0, /**< Application logs dump */ + CP_DUMP = 1, /**< Modem logs dump */ + ALL_DUMP = 2 /**< All logs dump - application and modem */ +}; + +/* deviced_util */ + +/** + * @fn int deviced_get_cmdline_name(pid_t pid, char *cmdline, size_t cmdline_size) + * @brief This API is used to get the file name of command line of the process from the proc fs. + * Caller process MUST allocate enough memory for the cmdline parameter. \n + * Its size should be assigned to cmdline_size. \n + * Internally it reads the 1st argument of /proc/{pid}/cmdline and copies it to cmdline. + * @param[in] pid pid of the process that you want to get the file name of command line + * @param[out] cmdline command line of the process that you want to get the file name
+ * Callers should allocate memory to this parameter before calling this function. + * The allocated memory size must be large enough to store the file name. + * The result will include the terminating null byte('\0') at the end of the string. + * @param[in] cmdline_size + * @return 0 on success, -1 if failed.\n + * If the size of cmdline is smaller than the result, it will return -1 and \n + * errno will be set as EOVERFLOW. \n + * If the function cannot open /proc/%d/cmdline file then it will return -1 and \n + * errno will be set as ESRCH. + */ +int deviced_get_cmdline_name(pid_t pid, char *cmdline, + size_t cmdline_size); + +/** + * @fn int deviced_get_apppath(pid_t pid, char *app_path, size_t app_path_size) + * @brief This API is used to get the execution path of the process specified by the pid parameter.\n + * Caller process MUST allocate enough memory for the app_path parameter. \n + * Its size should be assigned to app_path_size. \n + * Internally it reads a link of /proc/{pid}/exe and copies the path to app_path. + * @param[in] pid pid of the process that you want to get the executed path + * @param[out] app_path the executed file path of the process
+ * Callers should allocate memory to this parameter before calling this function. + * The allocated memory size must be large enough to store the executed file path. + * The result will include the terminating null byte('\0') at the end of the string. + * @param[in] app_path_size allocated memory size of char *app_path + * @return 0 on success, -1 if failed. \n + * If the size of app_path is smaller than the result, it will return -1 and \n + * errno will be set as EOVERFLOW. + */ +int deviced_get_apppath(pid_t pid, char *app_path, size_t app_path_size); + +/* sysconf */ + +/** + * @fn int deviced_conf_set_mempolicy(enum mem_policy mempol) + * @brief This API is used to set the policy of the current process when the phone has low available memory. + * @param[in] mempol oom adjust value which you want to set + * @return 0 on success, -1 if failed. + * @see deviced_conf_set_mempolicy_bypid() + * @retval -1 operation error + * @retval -EBADMSG - dbus error (in case of any error on the bus) + * @retval -EINVAL no mandatory parameters + * @retval -ESRCH incorrect sender process id + */ +int deviced_conf_set_mempolicy(enum mem_policy mempol); + +/** + * @fn int deviced_conf_set_mempolicy_bypid(pid_t pid, enum mem_policy mempol) + * @brief This API is used to set the policy of the given process when the phone has low available memory. + * @param[in] pid process id which you want to set + * @param[in] mempol oom adjust value which you want to set + * @return 0 on success, -1 if failed. + * @retval -1 operation error + * @retval -EBADMSG - dbus error (in case of any error on the bus) + * @retval -EINVAL no mandatory parameters + * @retval -ESRCH incorrect sender process id + */ +int deviced_conf_set_mempolicy_bypid(pid_t pid, enum mem_policy mempol); + +/** + * @fn int deviced_conf_set_permanent(void) + * @brief This API is used to set itself as a permanent process.\n + * If the permanent process is dead, system server will relaunch the process automatically. + * @return 0 on success, -1 if failed. + * @see deviced_conf_set_permanent_bypid() + * @par Example + * @code + * ... + * ret = deviced_conf_set_permanent(); + * if( ret < 0 ) + * printf("Fail to set a process as permanent\n"); + * ... + * @endcode + */ +int deviced_conf_set_permanent(void); + +/** + * @fn int deviced_conf_set_permanent_bypid(pid_t pid) + * @brief This API is used to set a given process as permanent.\n + * If the permanent process is dead, system server will relaunch the process automatically. + * @param[in] pid proces id + * @return 0 on success, -1 if failed. + * @see deviced_set_permanent() + * @par Example + * @code + * ... + * ret = deviced_conf_set_permanent_bypid(pid); + * if( ret < 0 ) + * printf("Fail to set a process(%d) as permanent\n",pid); + * ... + * @endcode + */ +int deviced_conf_set_permanent_bypid(pid_t pid); + +/** + * @fn int deviced_conf_set_vip(pid_t pid) + * @brief This API is used to set a process which has pid as Very Important Process(VIP) .\n + * If the VIP process is dead, restarter program will be run. \n + * Restarter program may kill almost processes and run rc.local scripts again. + * @param[in] pid process id to be vip + * @return 0 on success, -1 if failed. + * @see sysconf_is_vip + * @par Example + * @code + * ... + * ret = deviced_conf_set_vip(pid); + * if( ret < 0 ) + * printf("Fail to set a process(%d) as VIP\n",pid); + * ... + * @endcode + */ +int deviced_conf_set_vip(pid_t pid); + +/** + * @fn int deviced_conf_is_vip(pid_t pid) + * @brief This API is used to verify that process which has pid is Very Important Process(VIP) or not. + * @param[in] pid process id to be vip + * @return 1 if given process if vip process, otherwise 0 is returned. + * @see deviced_conf_set_vip + * @par Example + * @code + * ... + * ret = deviced_conf_is_vip(pid); + * if(ret) + * printf("process(%d) is Very Important Process\n",pid); + * ... + * @endcode + */ +int deviced_conf_is_vip(pid_t pid); + +/** + * @fn int deviced_set_timezone(char *tzpath_str) + * @brief This API sets system timezone. + * @param[in] tzpath_str path to timezone definition file + * @return 0 on success, negative value if failed. + * @retval -1 operation error + * @retval -EBADMSG dbus error (in case of any error on the bus) + * @retval -EINVAL no mandatory parameters + * @retval -ESRCH incorrect sender process id + */ +int deviced_set_timezone(char *tzpath_str); + +/** + * @fn int deviced_call_predef_action(const char *type, int num, ...) + * @brief This API calls predefined systemd action. + * Internally it send message through SYSTEM_NOTI_SOCKET_PATH (/tmp/sn) UNIX socket to systemd. + * @param[in] type systemd action type name + * @param[in] num input parameters count. num cannot exceed SYSTEM_NOTI_MAXARG (16). + * @param[in] ... action input parameters. List of the parameters depends on action type. + * @return 0 on success, -1 if failed. + * If the action type is not set (is blank) or num > SYSTEM_NOTI_MAXARG it will return -1 + * and errno will be set as EINVAL. + */ +int deviced_call_predef_action(const char *type, int num, ...); + +/** + * @fn int deviced_inform_foregrd(void) + * @brief This API call notifies that current process is running in foreground. + * @return 0 or positive value on success and negative value if failed. + * @retval -1 operation error + * @retval -EBADMSG dbus error (in case of any error on the bus) + * @retval -EINVAL no mandatory parameters + * @retval -ESRCH incorrect sender process id + */ +int deviced_inform_foregrd(void); + +/** + * @fn int deviced_inform_backgrd(void) + * @brief This API call notifies that current process is running in background. + * @return 0 or positive value on success and negative value if failed. + * @retval -1 operation error + * @retval -EBADMSG dbus error (in case of any error on the bus) + * @retval -EINVAL no mandatory parameters + * @retval -ESRCH incorrect sender process id + */ +int deviced_inform_backgrd(void); + +/** + * @fn int deviced_inform_active(pid_t pid) + * @brief This API call notifies deviced daemon that given process (pid) is active. + * @param[in] pid process pid + * @return 0 or positive value on success and negative value if failed. + * @retval -1 operation error + * @retval -EBADMSG dbus error (in case of any error on the bus) + * @retval -EINVAL no mandatory parameters + * @retval -ESRCH incorrect sender process id + */ +int deviced_inform_active(pid_t pid); + +/** + * @fn int deviced_inform_active(pid_t pid) + * @brief This API call notifies deviced daemon that given process (pid) is inactive. + * @param[in] pid process pid + * @return 0 or positive value on success and negative value if failed. + * @retval -1 operation error + * @retval -EBADMSG dbus error (in case of any error on the bus) + * @retval -EINVAL no mandatory parameters + * @retval -ESRCH incorrect sender process id + */ +int deviced_inform_inactive(pid_t pid); + +/** + * @fn int deviced_request_poweroff(void) + * @brief This API call requests deviced daemon to launch "system poweroff popup". + * @return 0 or positive value on success and negative value if failed. + * @retval -1 operation error + * @retval -EBADMSG dbus error (in case of any error on the bus) + * @retval -EINVAL no mandatory parameters + * @retval -ESRCH incorrect sender process id + */ +int deviced_request_poweroff(void); + +/** + * @fn deviced_request_entersleep(void) + * @brief This API call requests deviced daemon to enter system into sleep mode. + * @return 0 or positive value on success and negative value if failed. + * @retval -EBADMSG dbus error (in case of any error on the bus) + * @retval -EINVAL no mandatory parameters + * @retval -ESRCH incorrect sender process id + */ +int deviced_request_entersleep(void); + +/** + * @fn int deviced_request_leavesleep(void) + * @brief This API calls requests deviced daemon to leave by system "sleep" mode and enter into "normal" mode. + * @return 0 or positive value on success and negative value if failed. + * @retval -EBADMSG dbus error (in case of any error on the bus) + * @retval -EINVAL no mandatory parameters + * @retval -ESRCH incorrect sender process id + */ +int deviced_request_leavesleep(void); + +/** + * @fn int deviced_request_reboot(void) + * @brief This API call requests deviced daemon to initiate system reboot. + * @return 0 on success and negative value if failed. + * @retval -EBADMSG dbus error (in case of any error on the bus) + * @retval -EINVAL no mandatory parameters + * @retval -ESRCH incorrect sender process id + */ +int deviced_request_reboot(void); + +/** + * @fn int deviced_request_set_cpu_max_frequency(int val) + * @brief This API call requests deviced daemon to set maximum CPU frequency. + * @param[in] val maximum CPU frequency to be set. + * @return 0 or positive value on success and negative value if failed. + * @retval -1 operation error + * @retval -EBADMSG - dbus error (in case of any error on the bus) + */ +int deviced_request_set_cpu_max_frequency(int val); + +/** + * @fn int deviced_request_set_cpu_min_frequency(int val) + * @brief This API call requests deviced daemon to set minimum CPU frequency. + * @param[in] val minimum CPU frequency to be set + * @return 0 or positive value on success and negative value if failed. + * @retval -1 operation error + * @retval -EBADMSG dbus error (in case of any error on the bus) + */ +int deviced_request_set_cpu_min_frequency(int val); + +/** + * @fn int deviced_release_cpu_max_frequency(void) + * @brief This API call releases limit of maximum CPU frequency set by deviced_request_set_cpu_max_frequency() API. + * @return 0 or positive value on success and negative value if failed. + * @retval -1 operation error + * @retval -EBADMSG dbus error (in case of any error on the bus) + */ +int deviced_release_cpu_max_frequency(void); + +/** + * @fn int deviced_release_cpu_min_frequency(void) + * @brief This API calls releases limit of minimum CPU frequency set by deviced_request_set_cpu_min_frequency() API. + * @return 0 or positive value on success and negative value if failed. + * @retval -1 operation error + * @retval -EBADMSG dbus error (in case of any error on the bus) + */ +int deviced_release_cpu_min_frequency(void); + +/** + * @fn int deviced_request_set_factory_mode(int val) + * @brief This API call requests systemd daemon to enter system into factory mode. + * @param[in] val factory mode level.\n + * 0 - "off" factory mode\n + * 1 - "on" factory mode. + * @return 0 or positive value on success and negative value if failed. + * @retval -1 operation error + * @retval -EBADMSG dbus error (in case of any error on the bus) + * @retval -EINVAL no mandatory parameters + * @retval -ESRCH incorrect sender process id + */ +int deviced_request_set_factory_mode(int val); + +/** + * @fn int deviced_request_dump_log(int type) + * @brief This API call force dumps all application, modem or application + modem logs. + * - if type is equal AP_DUMP application log dump will be created. + * - if type is equal CP_DUMP modem logs dump will be created + * - if dump type is equal ALL_DUMP application and modem logs dump will be created + * @param[in] type dump type. + * @return 0 or positive value on success and negative value if failed. + * @retval -1 operation error + * @retval -EBADMSG dbus error (in case of any error on the bus) + * @see dump_log_type + */ +int deviced_request_dump_log(int type); + +/** + * @fn int deviced_request_delete_dump(char *ticket) + * @brief This API call removes all dump data for given ticket from /opt/usr/share/crash/ticket directory. + * @param[in] ticket ticket name. + * @return 1 on success and negative value if failed. + * @retval -1 operation error + * @retval -EBADMSG dbus error (in case of any error on the bus) + */ +int deviced_request_delete_dump(char *ticket); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif +#endif /* __DD_DEVICED__ */ diff --git a/src/deviced/dd-display.h b/src/deviced/dd-display.h new file mode 100644 index 0000000..5d98391 --- /dev/null +++ b/src/deviced/dd-display.h @@ -0,0 +1,620 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 __DD_DISPLAY_H__ +#define __DD_DISPLAY_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file dd-display.h + * @defgroup CAPI_SYSTEM_DEVICED_DISPLAY_MODULE Display + * @ingroup CAPI_SYSTEM_DEVICED + * @brief This file provides the API for control of display + * @section CAPI_SYSTEM_DEVICED_DISPLAY_MODULE_HEADER Required Header + * \#include + */ + +/** + * @addtogroup CAPI_SYSTEM_DEVICED_DISPLAY_MODULE + * @{ + */ + +#include "dd-common.h" + +/** + * LCD state + */ +#define LCD_NORMAL 0x1 /**< NORMAL state */ +#define LCD_DIM 0x2 /**< LCD dimming state */ +#define LCD_OFF 0x4 /**< LCD off state */ +#define SUSPEND 0x8 /**< Sleep state */ +#define POWER_OFF 0x16 /**< Sleep state */ +#define SETALL (LCD_DIM | LCD_OFF | LCD_NORMAL) /*< select all state - not supported yet */ + +/** + * Parameters for display_lock_state() + */ +#define STAY_CUR_STATE 0x1 +#define GOTO_STATE_NOW 0x2 +#define HOLD_KEY_BLOCK 0x4 +#define STANDBY_MODE 0x8 + +/** + * Parameters for display_unlock_state() + */ +#define PM_SLEEP_MARGIN 0x0 /**< keep guard time for unlock */ +#define PM_RESET_TIMER 0x1 /**< reset timer for unlock */ +#define PM_KEEP_TIMER 0x2 /**< keep timer for unlock */ + +/** + * @brief enhance - info, mode, scenario, tone, outdoor + */ +enum image_enhance_type { + ENHANCE_MODE = 0, + ENHANCE_SCENARIO, + ENHANCE_TONE, + ENHANCE_OUTDOOR, +}; + +/** + * @brief mode - dynamic, standard, natural, movie + */ +enum image_enhance_mode { + MODE_DYNAMIC = 0, + MODE_STANDARD, + MODE_NATURAL, + MODE_MOVIE, +}; + +/** + * @brief scenario - ui, gallery, video, vtcall, camera, + * browser, negative, bypass + */ +enum image_enhance_scenario { + SCENARIO_UI = 0, + SCENARIO_GALLERY, + SCENARIO_VIDEO, + SCENARIO_VTCALL, + SCENARIO_CAMERA, + SCENARIO_BROWSER, + SCENARIO_NEGATIVE, + SCENARIO_BYPASS, +}; + +/** + * @brief tone - normal, warm, cold + */ +enum image_enhance_tone { + TONE_NORMAL = 0, + TONE_WARM, + TONE_COLD, +}; + +/** + * @brief outdoor - off, on + */ +enum image_enhance_outdoor { + OUTDOOR_OFF = 0, + OUTDOOR_ON, +}; + +/** + * @brief auto tone - off, on + */ +enum auto_screen_tone { + TONE_OFF = 0, + TONE_ON, +}; +/** + * @par Description: + * @todo + */ +struct blind_color_info { + unsigned int RrCr; + unsigned int RgCg; + unsigned int RbCb; + unsigned int GrMr; + unsigned int GgMg; + unsigned int GbMb; + unsigned int BrYr; + unsigned int BgYg; + unsigned int BbYb; +}; + +/** + * @brief This API is used to get number of displays on the phone.\n + * @details It returns enum value which is the current number on success.\n + * Or a negative value(-1) is returned on failure. + * @return 0 on success, -1 if failed + * @par Example + * @code + * ... + * ret = display_get_count(); + * if( ret < 0 ) + * printf("Fail to get number of displays\n"); + * ... + * @endcode + */ +int display_get_count(void); + +/** + * @brief This API is used to get the max brightness of the display.\n + * @details It gets the current brightness of the display + * by calling device_get_property() function.\n + * It returns integer value which is the max brightness on success.\n + * Or a negative value(-1) is returned on failure + * @return max brightness value on success, negative if failed + * @par Example + * @code + * ... + * int max_brt; + * max_brt = display_get_max_brightness(); + * if( max_brt < 0 ) + * printf("Fail to get the max brightness of the display.\n"); + * else + * printf("Max brightness of the display is %d\n", max_brt); + * ... + * @endcode + */ +int display_get_max_brightness(void); + +/** + * @brief This API is used to get the min brightness of the display.\n + * @details It gets the current brightness of the display + * by calling device_get_property() function.\n + * It returns integer value which is the min brightness on success.\n + * Or a negative value(-1) is returned on failure + * @return min brightness value on success, negative if failed + * @par Example + * @code + * ... + * int min_brt; + * min_brt = display_get_min_brightness(); + * if( min_brt < 0 ) + * printf("Fail to get the min brightness of the display.\n"); + * else + * printf("Min brightness of the display is %d\n", min_brt); + * ... + * @endcode + */ +int display_get_min_brightness(void); + +/** + * @brief This API is used to get the current brightness of the display.\n + * @details It gets the current brightness of the display + * by calling device_get_property() function.\n + * It returns integer value which is the current brightness on success.\n + * Or a negative value(-1) is returned on failure. + * @return current brightness value on success, negative if failed + * @par Example + * @code + * ... + * int cur_brt; + * cur_brt = display_get_brightness(); + * if( cur_brt < 0 ) + * printf("Fail to get the current brightness of the display.\n"); + * else + * printf("Current brightness of the display is %d\n", cur_brt); + * ... + * @endcode + */ +int display_get_brightness(void); + +/** + * @brief This API is used to set the current brightness of the display + * and system brightness value in settings.\n + * @details It sets the current brightness of the display + * by calling device_set_property() function.\n + * MUST use this API very carefully. \n + * This api is different from display_set_brightness api.\n + * display_set_brightness api will change only device brightness value.\n + * but this api will change device brightness + * as well as system brightness value.\n + * @param[in] val brightness value that you want to set + * @return 0 on success, negative if failed + * @see display_set_brightness() + * @par Example + * @code + * ... + * if( display_set_brightness_with_setting(6) < 0 ) + * printf("Fail to set the current brightness of the display\n"); + * else + * printf("The current brightness of the display is set 6\n"); + * ... + * @endcode + */ +int display_set_brightness_with_setting(int val); + +/** + * @brief This API is used to set the current brightness of the display.\n + * @details It sets the current brightness of the display + * by calling device_set_property() function.\n + * MUST use this API very carefully. \n + * you MUST set original brightness by display_release_brightness(), + * after you finish your job using this API. + * @param[in] val brightness value that you want to set + * @return 0 on success, negative if failed + * @see display_get_brightness(), display_release_brightness() + * @par Example + * @code + * ... + * if( display_set_brightness(6) < 0 ) + * printf("Fail to set the current brightness of the display\n"); + * else + * printf("The current brightness of the display is set 6\n"); + * ... + * @endcode + */ +int display_set_brightness(int val); + +/** + * @brief This API is used to release brightness control.\n + * @details It sets the current brightness of the display + * by calling device_set_property() function.\n + * MUST call this API after you finished the job + * which need to change the brightness. + * @return 0 on success, negative if failed + * @see display_set_brightness() + * @par Example + * @code + * ... + * org_val = display_get_brightness(); + * display_set_brightness(1); + * ... + * ret = display_release_brightness(); + * if( ret < 0 ) + * printf("Fail to release brightness control\n"); + * ... + * @endcode + */ +int display_release_brightness(void); + +/** + * @brief This API is used to get the current state for acl.\n + * @details It gets the current state for acl + * by calling device_get_property() function.\n + * @return current status for acl(1 on, 0 off) on success, negative if failed + * @see display_set_acl_status() + * @par Example + * @code + * ... + * int acl_stat; + * acl_stat = display_get_acl_status(); + * if( acl_stat < 0 ) + * printf("Fail to get the current status for acl.\n"); + * else + * printf("Current status for acl is %d\n", cur_brt); + * ... + * @endcode + */ +int display_get_acl_status(void); + +/** + * @brief This API is used to set the current status for acl.\n + * @details It sets the current status for acl + * by calling device_set_property() function.\n + * @param[in] val status for acl(1 on, 0 off) that you want to set + * @return 0 on success, negative if failed + * @see display_get_acl_status() + * @par Example + * @code + * ... + * if( display_set_acl_status(0) < 0 ) + * printf("Fail to set the current status for acl\n"); + * else + * printf("The current status for acl is set 6\n"); + * ... + * @endcode + */ +int display_set_acl_status(int val); + +/** + * @brief This API is used to get enhance mode supported.\n + * @return 1 supported, 0 not supporter, negative if failed + * @par Example + * @code + * ... + * ret = display_get_image_enhance_info(); + * if( ret < 0 ) + * printf("Not support image enhance mode on this device\n"); + * ... + * @endcode + */ +int display_get_image_enhance_info(void); + +/** + * @brief This API is used to get enhance mode state.\n + * @param[in] type enhance mode type + * @return enum value of type on success, negative if failed + * @par Example + * @code + * ... + * ret = display_get_image_enhance(ENHANCE_MODE); + * if( ret < 0 ) + * printf("Fail to get current image enhance\n"); + * ... + * @endcode + */ +int display_get_image_enhance(int type); + +/** + * @brief This API is used to set enhance mode state.\n + * @param[in] type enhance mode type + * @param[in] val enum value of enhance mode type + * @return 0 on success, negative if failed + * @par Example + * @code + * ... + * if( display_set_image_enhance(ENHANCE_MODE, MODE_DYNAMIC) < 0 ) + * printf("Fail to set the image enhance mode\n"); + * ... + * @endcode + */ +int display_set_image_enhance(int type, int val); + +/** + * @brief This API is used to set frame rate of display.\n + * @param[in] val frame rate + * @return 0 on success, negative if failed + * @par Example + * @code + * ... + * if( display_set_frame_rate() < 0 ) + * printf("Fail to set display frame rate\n"); + * ... + * @endcode + * @todo describe range of val + */ +int display_set_frame_rate(int val) DEPRECATED; + +/** + * @brief refresh app - setting, video, camera + */ +enum refresh_app { + REFRESH_SETTING, + REFRESH_VIDEO, + REFRESH_CAMERA, + REFRESH_WEB, +}; + +/** + * @brief This API is used to set refresh rate of display.\n + * @param[in] app caller application type + * @param[in] val refresh rate + * @return 0 on success, negative if failed + * @par Example + * @code + * ... + * if( display_set_refresh_rate(REFRESH_SETTING, 60) < 0 ) + * printf("Fail to set display refresh rate\n"); + * ... + * @endcode + * @todo describe range of val + */ +int display_set_refresh_rate(enum refresh_app app, int val); + +/** + * @brief This API is used to lock a particular display state + * as the current display-state.\n + * @details The parameter state specifies the display state which + * you want to lock LCD_NORMAL, LCD_DIM, LCD_OFF. \n + * The second parameter Flag is set if you want to go + * the requested lock state directly.\n + * The third parameter timeout specifies lock-timeout in milliseconds. + * If the value 0 is selected, the display state remains locked + * until display_unlock_state is called. + * @param[in] state target power state which you want to lock + * - LCD_NORMAL, LCD_DIM, LCD_OFF + * @param[in] flag set if you want to go the lock state directly \n + * GOTO_STATE_NOW - State is changed directly you want to lock.\n + * STAY_CUR_STATE - State is not changed directly and + * phone stay current state until timeout expired.\n + * HOLD_KEY_BLOCK - Hold key is blocked during locking + * LCD_NORMAL or LCD_DIM. \n + * Then LCD state transition to LCD_OFF is blocked. \n + * If this flag is not set, phone state is lcd off + * after pressing hold key. \n + * GOTO_STATE_NOW and STAY_CUR_STATE can't be applied at the same time. + * @param[in] timeout lock-timeout in miliseconds. \n + * 0 is always lock until calling display_unlock_state + * @return 0 on success, negative if failed + * @see display_unlock_state(), display_change_state() + * @par Example + * @code + * ... + * result = pm_lock_state(LCD_NORMAL, GOTO_STATE_NOW, SET_TIMEOUT); + * if( result < 0 ) + * printf("[ERROR] return value result =%d, \n",result); + * else + * printf("[SUCCESS]return value result =%d \n",result); + * ... + * @endcode + */ +int display_lock_state(unsigned int state, unsigned int flag, unsigned int timeout); + +/** + * @brief This API is used to unlock the display state. \n + * @details The parameter state specifies the display + * state which you want to unlock. \n + * Some examples are LCD_NORMAL, LCD_DIM, LCD_OFF. + * @param[in] state target display state which you want to unlock + * @param[in] flag set timer which is going to the next state after unlocking\n + * PM_SLEEP_MARGIN - If the current status is lcd off, + * deviced reset timer to 1 second. + * If the current status is not lcd off, deviced uses the existing timer.\n + * PM_RESET_TIMER - deviced resets timer. + * (lcd normal : reset timer to predfined value + * which is set in setting module, + * lcd dim : reset timer to 5 seconds, lcd off : reset timer to 1 seconds)\n + * PM_KEEP_TIMER - deviced uses the existing timer + * (if timer is already expired, deviced changes the status) \n + * @return 0 on success, negative if failed + * @see display_lock_state(), display_change_state() + * @par Example + * @code + * ... + * result = display_unlock_state(LCD_NORMAL,PM_RESET_TIMER); + * if( result < 0 ) + * printf("[ERROR] return value result =%d, \n",result); + * else + * printf("[SUCCESS]return value result =%d \n",result); + * ... + * @endcode + */ +int display_unlock_state(unsigned int state, unsigned int flag); + +/** + * @brief This API is used to change display state by force. + * @param[in] state display state - LCD_NORMAL, LCD_DIM, LCD_OFF + * @return 0 on success, negative if failed. + * @see display_lock_state(), display_unlock_state() + * @par Example + * @code + * ... + * result = display_change_state(LCD_OFF); + * if( result < 0 ) + * printf("[ERROR] return value result =%d, \n",result); + * else + * printf("[SUCCESS]return value result =%d \n",result); + * ... + * @endcode + */ +int display_change_state(unsigned int state); + +/** + * @brief This API is used to get auto screen tone.\n + * @return enum value for current tone on success, negative if failed + * @see display_set_auto_screen_tone() + * @par Example + * @code + * ... + * result = display_get_auto_screen_tone(); + * if( result == 0 ) + * printf("Display auto screen ton OFF\n"); + * else if ( result == 1 ) + * printf("Display auto screen ton ON\n"); + * ... + * @endcode + */ +int display_get_auto_screen_tone(void); + +/** + * @brief This API is used to set auto screen tone.\n + * @return 0 on success, negative if failed + * @see display_get_auto_screen_tone() + * @par Example + * @code + * ... + * result = display_set_auto_screen_tone(TONE_OFF); + * if( result < 0 ) + * printf("[ERROR] return value result =%d, \n",result); + * else + * printf("[SUCCESS] return value result =%d, \n",result); + * ... + * @endcode + */ +int display_set_auto_screen_tone(int type); + +/** + * @brief This API is used to get color blind value.\n + * @return blind value on success, negative if failed + * @see display_set_color_blind() + * @par Example + * @code + * ... + * result = display_get_color_blind(); + * if( result < 0 ) + * printf("[ERROR] return value result =%d, \n",result); + * else + * printf("[SUCCESS] return value result =%d, \n",result); + * ... + * @endcode + */ +int display_get_color_blind(void); + +/** + * @brief This API is used to set color blind value.\n + * @param[in] enable color blind on/off + * @param[in] info blind color info + * @return 0 on success, negative if failed + * @see display_set_color_blind() + * @par Example + * @code + * ... + * result = display_set_color_blind(1, info); + * if( result < 0 ) + * printf("[ERROR] return value result =%d, \n",result); + * else + * printf("[SUCCESS] return value result =%d, \n",result); + * ... + * @endcode + * @todo describe blind_color_info + */ +int display_set_color_blind(int enable, struct blind_color_info *info); + +/** + * @brief Gets touch sensitivity mode + * @return 0 on success, otherwise negative error value + * @see display_set_enhanced_touch() + */ +int display_get_enhanced_touch(void); + +/** + * @brief Sets touch sensitivity mode + * @param[in] enable 1 on enable, 0 on disable + * @return 0 on success, otherwise negative error value + * @see display_get_enhanced_touch() + */ +int display_set_enhanced_touch(int enable); + +/** + * @brief Gets HBM(High Brightness Mode) state + * @return 0 or 1 on success, otherwise negative error value + * @see display_set_hbm + */ +int display_get_hbm(void); + +/** + * @brief Sets HBM(High Brightness Mode) state + * @param[in] enable 1 on enable, 0 on disable + * @return 0 on success, otherwise negative error value + * @see display_get_hbm() + */ +int display_set_hbm(int enable); + +/** + * @brief Sets HBM(High Brightness Mode) state + * @param[in] enable 1 on enable, 0 on disable + * @param[in] timeout (second) + * @return 0 on success, otherwise negative error value + * @see display_get_hbm() + */ +int display_enable_hbm(int enable, int timeout); + +/** + * @} // end of CAPI_SYSTEM_DEVICED_DISPLAY_MODULE + */ + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/deviced/dd-haptic.h b/src/deviced/dd-haptic.h new file mode 100644 index 0000000..02b3364 --- /dev/null +++ b/src/deviced/dd-haptic.h @@ -0,0 +1,654 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 __DD_HAPTIC_H__ +#define __DD_HAPTIC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file dd-haptic.h + * @defgroup CAPI_SYSTEM_DEVICED_HAPTIC_MODULE Haptic + * @ingroup CAPI_SYSTEM_DEVICED + * @brief This file provides the API for control of haptic + * @section CAPI_SYSTEM_DEVICED_HAPTI_MODULE_HEADER Required Header + * \#include + */ + +/** + * @addtogroup CAPI_SYSTEM_DEVICED_HAPTIC_MODULE + * @{ + */ + +/** + * @brief The handle of haptic device + */ +typedef void* haptic_device_h; + +/** + * @brief The handle of haptic effect + */ +typedef void* haptic_effect_h; + +/** + * @brief Enumerations of device id for the Haptic API. + * @details We support two motors now. + */ +typedef enum { + HAPTIC_DEVICE_0 = 0x0, /**< 1st motor */ + HAPTIC_DEVICE_1 = 0x1, /**< 2nd motor */ + HAPTIC_DEVICE_ALL = 0x4, /**< both of them */ +} haptic_device_e; + +/** + * @brief Enumerations of priority level for the Haptic API. + */ +typedef enum +{ + HAPTIC_PRIORITY_MIN = 0, /**< Minimum effect priority for developers (default) */ + HAPTIC_PRIORITY_MIDDLE, /**< Maximum effect priority for developers */ + HAPTIC_PRIORITY_HIGH, /**< Maximum effect priority for OEMs */ +} haptic_priority_e; + +/** + * @brief Enumerations of feedback level for the Haptic API. + * @details Haptic level means vibration power (intensity). + */ +typedef enum +{ + HAPTIC_FEEDBACK_0 = 0, /**< feedback level 0 */ + HAPTIC_FEEDBACK_1 = 20, /**< feedback level 1 */ + HAPTIC_FEEDBACK_2 = 40, /**< feedback level 2 */ + HAPTIC_FEEDBACK_3 = 60, /**< feedback level 3 */ + HAPTIC_FEEDBACK_4 = 80, /**< feedback level 4 */ + HAPTIC_FEEDBACK_5 = 100, /**< feedback level 5 */ + HAPTIC_FEEDBACK_AUTO, /**< feedback level auto */ +} haptic_feedback_e; + +/** + * @brief Enumerations of unlimited duration for the Haptic API. + */ +typedef enum { + HAPTIC_DURATION_UNLIMITED = 0xFFFFFFFF, +} haptic_duration_e; + +/** + * @brief Enumerations of iteration count for the Haptic API. + */ +typedef enum +{ + HAPTIC_ITERATION_ONCE = 1, + HAPTIC_ITERATION_INFINITE = 256, +} haptic_iteration_e; + +/** + * @brief Enumerations of effect or device state for the Haptic API. + */ +typedef enum +{ + HAPTIC_STATE_STOP = 0, + HAPTIC_STATE_PLAYING, +} haptic_state_e; + +/** + * @brief Enumerations of error codes for the Haptic API. + */ +typedef enum +{ + HAPTIC_ERROR_NONE = 0, //TIZEN_ERROR_NONE, /**< Successful */ + HAPTIC_ERROR_INVALID_PARAMETER = -1, //TIZEN_ERROR_INVALID_PARAMETER, /**< Invalid parameter */ + HAPTIC_ERROR_FILE_EXISTS = -2, //TIZEN_ERROR_FILE_EXISTS, /**< File exists */ + HAPTIC_ERROR_NOT_INITIALIZED = -3, //TIZEN_ERROR_SYSTEM_CLASS | 0x26, /**< Not initialized */ + HAPTIC_ERROR_OPERATION_FAILED = -4, //TIZEN_ERROR_SYSTEM_CLASS | 0x28, /**< Operation failed */ + HAPTIC_ERROR_NOT_SUPPORTED_DEVICE = -5, //TIZEN_ERROR_SYSTEM_CLASS | 0x30, /**< Not supported device */ +} haptic_error_e; + +/** + * @brief Gets the number of the vibrators. + * + * @remarks The index HAPTIC_DEVICE_ALL is reserved meaning for all vibrators at a time. + * + * @param[in] device_number A number of vibrators + * + * @return 0 on success, otherwise a negative error value. + * @retval #HAPTIC_ERROR_NONE Successful + * @retval #HAPTIC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #HAPTIC_ERROR_OPERATION_FAILED Operation failed + * @retval #HAPTIC_ERROR_NOT_SUPPORTED_DEVICE Not supported device + */ +int haptic_get_count(int *device_number); + +/** + * @brief Opens a haptic-vibration device. + * + * @details Internally, it makes a connection to the vibrator. + * + * @remarks If this function is not called in advance, other functions will return #HAPTIC_ERROR_NOT_INITIALIZED. + * @remarks Haptic API must be closed by haptic_close(). + * + * @return 0 on success, otherwise a negative error value. + * @retval #HAPTIC_ERROR_NONE Successful + * @retval #HAPTIC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #HAPTIC_ERROR_OPERATION_FAILED Operation failed + * @retval #HAPTIC_ERROR_NOT_SUPPORTED_DEVICE Not supported device + * + * @see haptic_close() + */ +int haptic_open(haptic_device_e device, haptic_device_h *device_handle); + +/** + * @brief Closes a haptic-vibration device. + * + * @details Internally, it disconnects the connection to vibrator. + * + * @return 0 on success, otherwise a negative error value. + * @retval #HAPTIC_ERROR_NONE Successful + * @retval #HAPTIC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #HAPTIC_ERROR_NOT_INITIALIZED Not initialized + * @retval #HAPTIC_ERROR_OPERATION_FAILED Operation failed + * @retval #HAPTIC_ERROR_NOT_SUPPORTED_DEVICE Not supported device + * + * @see haptic_open() + */ +int haptic_close(haptic_device_h device_handle); + +/** + * @brief Vibrates during the specified time with a constant intensity. + * @details + * This function can be used to start monotonous vibration for specified time. + * + * @remark + * If you don't use th api regarding effect_handle, you can pass in a NULL value to last parameter.\n + * And default value of feedback and priority is used.\n + * feedback level is reserved for auto chaning to save variable in the settings.\n + * priority level uses HAPTIC_PRIORITY_MIN. + * + * @param[in] device_handle The device handle from haptic_open() + * @param[in] duration The play duration in milliseconds + * @param[out] effect_handle Pointer to the variable that will receive a handle to the playing effect + * + * @return 0 on success, otherwise a negative error value. + * @retval #HAPTIC_ERROR_NONE Successful + * @retval #HAPTIC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #HAPTIC_ERROR_NOT_INITIALIZED Not initialized + * @retval #HAPTIC_ERROR_OPERATION_FAILED Operation failed + * @retval #HAPTIC_ERROR_NOT_SUPPORTED_DEVICE Not supported device + * + * @see haptic_vibrate_monotone_with_detail() + * @see haptic_vibrate_file() + * @see haptic_vibrate_buffer() + * @see haptic_get_count() + */ +int haptic_vibrate_monotone(haptic_device_h device_handle, int duration, haptic_effect_h *effect_handle); + +/** + * @brief Vibrates during the specified time with a constant intensity. + * @details + * This function can be used to start monotonous vibration for specified time. + * + * @remark + * If you don't use th api regarding effect_handle, you can pass in a NULL value to last parameter. + * + * @param[in] device_handle The device handle from haptic_open() + * @param[in] duration The play duration in milliseconds + * @param[in] feedback The amount of the intensity variation + * @param[in] priority The priority from HAPTIC_PRIORITY_MIN to HAPTIC_PRIORITY_HIGH + * @param[out] effect_handle Pointer to the variable that will receive a handle to the playing effect + * + * @return 0 on success, otherwise a negative error value. + * @retval #HAPTIC_ERROR_NONE Successful + * @retval #HAPTIC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #HAPTIC_ERROR_NOT_INITIALIZED Not initialized + * @retval #HAPTIC_ERROR_OPERATION_FAILED Operation failed + * @retval #HAPTIC_ERROR_NOT_SUPPORTED_DEVICE Not supported device + * + * @see haptic_vibrate_monotone() + * @see haptic_vibrate_file_with_detail() + * @see haptic_vibrate_buffer_with_detail() + * @see haptic_get_count() + */ +int haptic_vibrate_monotone_with_detail(haptic_device_h device_handle, + int duration, + haptic_feedback_e feedback, + haptic_priority_e priority, + haptic_effect_h *effect_handle); + +/** + * @brief Vibrates a predefined rhythmic haptic-vibration pattern file. + * @details + * This function can be used to play a haptic-vibration pattern file. + * + * @remark + * If you don't use th api regarding effect_handle, you can pass in a NULL value to last parameter.\n + * And default value of feedback and priority is used.\n + * feedback level is reserved for auto chaning to save variable in the settings.\n + * priority level uses HAPTIC_PRIORITY_MIN. + * + * @param[in] device_handle The device handle from haptic_open() + * @param[in] file_path Vibration pattern file with path + * @param[out] effect_handle Pointer to the variable that will receive a handle to the playing effect + * + * @return 0 on success, otherwise a negative error value. + * @retval #HAPTIC_ERROR_NONE Successful + * @retval #HAPTIC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #HAPTIC_ERROR_NOT_INITIALIZED Not initialized + * @retval #HAPTIC_ERROR_OPERATION_FAILED Operation failed + * @retval #HAPTIC_ERROR_NOT_SUPPORTED_DEVICE Not supported device + * + * @see haptic_vibrate_file_with_detail() + * @see haptic_vibrate_monotone() + * @see haptic_vibrate_buffer() + * @see haptic_get_count() + */ +int haptic_vibrate_file(haptic_device_h device_handle, const char *file_path, haptic_effect_h *effect_handle); + +/** + * @brief Vibrates a predefined rhythmic haptic-vibration pattern file. + * @details + * This function can be used to play a haptic-vibration pattern file. + * + * @remark + * If you don't use th api regarding effect_handle, you can pass in a NULL value to last parameter. + * + * @param[in] device_handle The device handle from haptic_open() + * @param[in] file_path Vibration pattern file with path + * @param[in] iteration The number of times to repeat the effect + * @param[in] feedback The amount of the intensity variation + * @param[in] priority The priority from HAPTIC_PRIORITY_MIN to HAPTIC_PRIORITY_HIGH + * @param[out] effect_handle Pointer to the variable that will receive a handle to the playing effect + * + * @return 0 on success, otherwise a negative error value. + * @retval #HAPTIC_ERROR_NONE Successful + * @retval #HAPTIC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #HAPTIC_ERROR_NOT_INITIALIZED Not initialized + * @retval #HAPTIC_ERROR_OPERATION_FAILED Operation failed + * @retval #HAPTIC_ERROR_NOT_SUPPORTED_DEVICE Not supported device + * + * @see haptic_vibrate_file() + * @see haptic_vibrate_monotone_with_detail() + * @see haptic_vibrate_buffer_with_detail() + * @see haptic_get_count() + */ +int haptic_vibrate_file_with_detail(haptic_device_h device_handle, + const char *file_path, + haptic_iteration_e iteration, + haptic_feedback_e feedback, + haptic_priority_e priority, + haptic_effect_h *effect_handle); + +/** + * @brief Vibrates a predefined rhythmic haptic-vibration pattern buffer. + * @details + * This function can be used to play a haptic-vibration pattern buffer. + * + * @remark + * If you don't use th api regarding effect_handle, you can pass in a NULL value to last parameter.\n + * And default value of feedback and priority is used.\n + * feedback level is reserved for auto chaning to save variable in the settings.\n + * priority level uses HAPTIC_PRIORITY_MIN. + * + * @param[in] device_handle The device handle from haptic_open() + * @param[in] vibe_buffer Pointer to the vibration pattern + * @param[out] effect_handle Pointer to the variable that will receive a handle to the playing effect + * + * @return 0 on success, otherwise a negative error value. + * @retval #HAPTIC_ERROR_NONE Successful + * @retval #HAPTIC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #HAPTIC_ERROR_NOT_INITIALIZED Not initialized + * @retval #HAPTIC_ERROR_OPERATION_FAILED Operation failed + * @retval #HAPTIC_ERROR_NOT_SUPPORTED_DEVICE Not supported device + * + * @see haptic_vibrate_buffer_with_detail() + * @see haptic_vibrate_monotone() + * @see haptic_vibrate_file() + * @see haptic_get_count() + */ +int haptic_vibrate_buffer(haptic_device_h device_handle, const unsigned char *vibe_buffer, haptic_effect_h *effect_handle); + +/** + * @brief Vibrates a predefined rhythmic haptic-vibration pattern buffer. + * @details + * This function can be used to play a haptic-vibration pattern buffer. + * + * @remark + * If you don't use th api regarding effect_handle, you can pass in a NULL value to last parameter. + * + * @param[in] device_handle The device handle from haptic_open() + * @param[in] vibe_buffer Pointer to the vibration pattern + * @param[in] iteration The number of times to repeat the effect + * @param[in] feedback The amount of the intensity variation + * @param[in] priority The priority from HAPTIC_PRIORITY_MIN to HAPTIC_PRIORITY_HIGH + * @param[out] effect_handle Pointer to the variable that will receive a handle to the playing effect + * + * @return 0 on success, otherwise a negative error value. + * @retval #HAPTIC_ERROR_NONE Successful + * @retval #HAPTIC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #HAPTIC_ERROR_NOT_INITIALIZED Not initialized + * @retval #HAPTIC_ERROR_OPERATION_FAILED Operation failed + * @retval #HAPTIC_ERROR_NOT_SUPPORTED_DEVICE Not supported device + * + * @see haptic_vibrate_buffer() + * @see haptic_vibrate_monotone_with_detail() + * @see haptic_vibrate_file_with_detail() + * @see haptic_get_count() + */ +int haptic_vibrate_buffer_with_detail(haptic_device_h device_handle, + const unsigned char *vibe_buffer, + haptic_iteration_e iteration, + haptic_feedback_e feedback, + haptic_priority_e priority, + haptic_effect_h *effect_handle); + +/** + * @brief Vibrates a predefined rhythmic haptic-vibration pattern buffer. + * @details + * This function can be used to play a haptic-vibration pattern buffer. + * + * @remark + * If you don't use th api regarding effect_handle, you can pass in a NULL value to last parameter.\n + * And default value of feedback and priority is used.\n + * feedback level is reserved for auto chaning to save variable in the settings.\n + * priority level uses HAPTIC_PRIORITY_MIN. + * + * @param[in] device_handle The device handle from haptic_open() + * @param[in] vibe_buffer Pointer to the vibration pattern + * @param[in] size Size to the vibration pattern + * @param[out] effect_handle Pointer to the variable that will receive a handle to the playing effect + * + * @return 0 on success, otherwise a negative error value. + * @retval #HAPTIC_ERROR_NONE Successful + * @retval #HAPTIC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #HAPTIC_ERROR_NOT_INITIALIZED Not initialized + * @retval #HAPTIC_ERROR_OPERATION_FAILED Operation failed + * @retval #HAPTIC_ERROR_NOT_SUPPORTED_DEVICE Not supported device + * + * @see haptic_vibrate_buffer_with_detail() + * @see haptic_vibrate_monotone() + * @see haptic_vibrate_file() + * @see haptic_get_count() + */ +int haptic_vibrate_buffers(haptic_device_h device_handle, + const unsigned char *vibe_buffer, + int size, + haptic_effect_h *effect_handle); + +/** + * @brief Vibrates a predefined rhythmic haptic-vibration pattern buffer. + * @details + * This function can be used to play a haptic-vibration pattern buffer. + * + * @remark + * If you don't use th api regarding effect_handle, you can pass in a NULL value to last parameter. + * + * @param[in] device_handle The device handle from haptic_open() + * @param[in] vibe_buffer Pointer to the vibration pattern + * @param[in] size Size to the vibration pattern + * @param[in] iteration The number of times to repeat the effect + * @param[in] feedback The amount of the intensity variation + * @param[in] priority The priority from HAPTIC_PRIORITY_MIN to HAPTIC_PRIORITY_HIGH + * @param[out] effect_handle Pointer to the variable that will receive a handle to the playing effect + * + * @return 0 on success, otherwise a negative error value. + * @retval #HAPTIC_ERROR_NONE Successful + * @retval #HAPTIC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #HAPTIC_ERROR_NOT_INITIALIZED Not initialized + * @retval #HAPTIC_ERROR_OPERATION_FAILED Operation failed + * @retval #HAPTIC_ERROR_NOT_SUPPORTED_DEVICE Not supported device + * + * @see haptic_vibrate_buffer() + * @see haptic_vibrate_monotone_with_detail() + * @see haptic_vibrate_file_with_detail() + * @see haptic_get_count() + */ +int haptic_vibrate_buffers_with_detail(haptic_device_h device_handle, + const unsigned char *vibe_buffer, + int size, + haptic_iteration_e iteration, + haptic_feedback_e feedback, + haptic_priority_e priority, + haptic_effect_h *effect_handle); + +/** + * @brief Stops the current vibration effect which is being played. + * @details This function can be used to stop each effect started by haptic_vibrate_xxx(). + * + * @remark + * + * @param[in] device_handle The device handle from haptic_open() + * @param[in] effect_handle The effect handle from haptic_vibrate_xxx() + * + * @return 0 on success, otherwise a negative error value. + * @retval #HAPTIC_ERROR_NONE Successful + * @retval #HAPTIC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #HAPTIC_ERROR_NOT_INITIALIZED Not initialized + * @retval #HAPTIC_ERROR_OPERATION_FAILED Operation failed + * @retval #HAPTIC_ERROR_NOT_SUPPORTED_DEVICE Not supported device + * + * @see haptic_vibrate_buffer() + * @see haptic_vibrate_monotone() + * @see haptic_vibrate_file() + * @see haptic_get_count() + * @see haptic_stop_all_effects() + */ +int haptic_stop_effect(haptic_device_h device_handle, haptic_effect_h effect_handle); + +/** + * @brief Stops all vibration effects which are being played. + * @details This function can be used to stop all effects started by haptic_vibrate_xxx(). + * + * @remark + * + * @param[in] device_handle The device handle from haptic_open() + * + * @return 0 on success, otherwise a negative error value. + * @retval #HAPTIC_ERROR_NONE Successful + * @retval #HAPTIC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #HAPTIC_ERROR_NOT_INITIALIZED Not initialized + * @retval #HAPTIC_ERROR_OPERATION_FAILED Operation failed + * @retval #HAPTIC_ERROR_NOT_SUPPORTED_DEVICE Not supported device + * + * @see haptic_vibrate_buffer() + * @see haptic_vibrate_monotone() + * @see haptic_vibrate_file() + * @see haptic_get_count() + * @see haptic_stop_effect() + */ +int haptic_stop_all_effects(haptic_device_h device_handle); + +/** + * @brief Gets the status of the effect. + * @details This function can be used to get the status of the effect wheter the effect are playing or not. + * + * @remark + * + * @param[in] device_handle The device handle from haptic_open() + * @param[in] effect_handle The effect handle from haptic_vibrate_xxx() + * @param[out] state The pointer to variable that will receive the status of the effect. + * + * @return 0 on success, otherwise a negative error value. + * @retval #HAPTIC_ERROR_NONE Successful + * @retval #HAPTIC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #HAPTIC_ERROR_NOT_INITIALIZED Not initialized + * @retval #HAPTIC_ERROR_OPERATION_FAILED Operation failed + * @retval #HAPTIC_ERROR_NOT_SUPPORTED_DEVICE Not supported device + * + * @see haptic_vibrate_buffer() + * @see haptic_vibrate_monotone() + * @see haptic_vibrate_file() + * @see haptic_get_count() + * @see haptic_stop_effect() + * @see haptic_stop_all_effects() + */ +int haptic_get_effect_state(haptic_device_h device_handle, haptic_effect_h effect_handle, haptic_state_e *state); + +/** + * @par Description: + * effect element for haptic. + */ +typedef struct { + int haptic_duration; /**< Start time of the effect element in millisecond */ + int haptic_level; /**< Duration of the effect element in millisecond */ +} haptic_effect_element_s; + +/** + * @brief Creates an effect buffer. + * @details This function can be used to create an effect buffer using effeclt_element variable. + * + * @remark + * + * @param[out] vibe_buffer Pointer to the vibration pattern + * @param[in] max_bufsize The size of the buffer pointed to by vibe_buffer + * @param[in] elem_arr Pointer to an haptic_effect_element_s structure + * @param[in] max_elemcnt The size fo the buffer pointed to by elem_arr + * + * @return 0 on success, otherwise a negative error value. + * @retval #HAPTIC_ERROR_NONE Successful + * @retval #HAPTIC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #HAPTIC_ERROR_NOT_INITIALIZED Not initialized + * @retval #HAPTIC_ERROR_OPERATION_FAILED Operation failed + * @retval #HAPTIC_ERROR_NOT_SUPPORTED_DEVICE Not supported device + * + * @see haptic_save_effect() + */ +int haptic_create_effect(unsigned char *vibe_buffer, + int max_bufsize, + haptic_effect_element_s *elem_arr, + int max_elemcnt); + +/** + * @brief Save an effect buffer to the file. + * @details This function can be used to save an effect buffer to the file using third parameter. + * + * @remark + * + * @param[in] vibe_buffer Pointer to the vibration pattern + * @param[in] max_bufsize The size of the buffer pointed to by vibe_buffer + * @param[in] file_path The pointer to the character buffer containing the path to save + * + * @return 0 on success, otherwise a negative error value. + * @retval #HAPTIC_ERROR_NONE Successful + * @retval #HAPTIC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #HAPTIC_ERROR_NOT_INITIALIZED Not initialized + * @retval #HAPTIC_ERROR_FILE_EXISTS File exists + * @retval #HAPTIC_ERROR_OPERATION_FAILED Operation failed + * @retval #HAPTIC_ERROR_NOT_SUPPORTED_DEVICE Not supported device + * + * @see haptic_create_effect() + */ +int haptic_save_effect(const unsigned char *vibe_buffer, + int max_bufsize, + const char *file_path); + +/** + * @brief Gets a duration time value from file. + * @details This function can be used to get a duration time value from the file using second parameter. + * + * @remark + * + * @param[in] device_handle The device handle from haptic_open() + * @param[in] file_path The pointer to the character buffer containing the path to save + * @param[out] duration The pointer to the duration time value + * + * @return 0 on success, otherwise a negative error value. + * @retval #HAPTIC_ERROR_NONE Successful + * @retval #HAPTIC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #HAPTIC_ERROR_NOT_INITIALIZED Not initialized + * @retval #HAPTIC_ERROR_OPERATION_FAILED Operation failed + * @retval #HAPTIC_ERROR_NOT_SUPPORTED_DEVICE Not supported device + * + * @see haptic_get_buffer_duration() + */ +int haptic_get_file_duration(haptic_device_h device_handle, const char *file_path, int *duration); + +/** + * @brief Gets a duration time value from buffer. + * @details This function can be used to get a duration time value from the buffer using second parameter. + * + * @remark + * + * @param[in] device_handle The device handle from haptic_open() + * @param[in] vibe_buffer Pointer to the vibration pattern buffer + * @param[out] duration The pointer to the duration time value + * + * @return 0 on success, otherwise a negative error value. + * @retval #HAPTIC_ERROR_NONE Successful + * @retval #HAPTIC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #HAPTIC_ERROR_NOT_INITIALIZED Not initialized + * @retval #HAPTIC_ERROR_OPERATION_FAILED Operation failed + * @retval #HAPTIC_ERROR_NOT_SUPPORTED_DEVICE Not supported device + * + * @see haptic_get_file_duration() + */ +int haptic_get_buffer_duration(haptic_device_h device_handle, const unsigned char *vibe_buffer, int *duration); + +/** + * @brief Gets a duration time value from buffer. + * @details This function can be used to get a duration time value from the buffer using second parameter. + * + * @remark + * + * @param[in] device_handle The device handle from haptic_open() + * @param[in] vibe_buffer Pointer to the vibration pattern buffer + * @param[in] size Size to the vibration pattern buffer + * @param[out] buffer_duration The pointer to the duration time value + * + * @return 0 on success, otherwise a negative error value. + * @retval #HAPTIC_ERROR_NONE Successful + * @retval #HAPTIC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #HAPTIC_ERROR_NOT_INITIALIZED Not initialized + * @retval #HAPTIC_ERROR_OPERATION_FAILED Operation failed + * @retval #HAPTIC_ERROR_NOT_SUPPORTED_DEVICE Not supported device + * + * @see haptic_get_file_duration() + */ +int haptic_get_buffers_duration(haptic_device_h device_handle, const unsigned char *vibe_buffer, int size, int *buffer_duration); + +/** + * @brief Save an effect buffer to the led file. + * @details This function can be used to save an effect buffer to the led file which name is third parameter. + * + * @remark + * Third parameter should be compatible with ledplayer file. + * + * @param[in] vibe_buffer Pointer to the vibration pattern + * @param[in] max_bufsize The size of the buffer pointed to by vibe_buffer + * @param[in] file_path The pointer to the character buffer containing the path to save + * + * @return 0 on success, otherwise a negative error value. + * @retval #HAPTIC_ERROR_NONE Successful + * @retval #HAPTIC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #HAPTIC_ERROR_NOT_INITIALIZED Not initialized + * @retval #HAPTIC_ERROR_FILE_EXISTS File exists + * @retval #HAPTIC_ERROR_OPERATION_FAILED Operation failed + * @retval #HAPTIC_ERROR_NOT_SUPPORTED_DEVICE Not supported device + * + * @see haptic_save_effect() + */ +int haptic_save_led(const unsigned char *vibe_buffer, int max_bufsize, const char *file_path); + +/** + * @} end of CAPI_SYSTEM_DEVICED_HAPTIC_MODULE + */ + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/deviced/dd-led.h b/src/deviced/dd-led.h new file mode 100644 index 0000000..b00efd6 --- /dev/null +++ b/src/deviced/dd-led.h @@ -0,0 +1,191 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 __DD_LED_H__ +#define __DD_LED_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/** + * @file dd-led.h + * @defgroup CAPI_SYSTEM_DEVICED_LED_MODULE Led + * @ingroup CAPI_SYSTEM_DEVICED + * @brief This file provides the API for control of led + * @section CAPI_SYSTEM_DEVICED_LED_MODULE_HEADER Required Header + * \#include + */ + +/** + * @addtogroup CAPI_SYSTEM_DEVICED_LED_MODULE + * @{ + */ + +/** + * @par Description + * LED mode + */ +enum LED_MODE { + LED_OFF = 0, + LED_LOW_BATTERY, + LED_CHARGING, + LED_FULLY_CHARGED, + LED_CHARGING_ERROR, + LED_MISSED_NOTI, + LED_VOICE_RECORDING, + LED_POWER_OFF, + LED_CUSTOM, + LED_MODE_MAX, +}; + +#define led_set_brightness(val) \ + led_set_brightness_with_noti(val, false) + +#define led_set_mode(mode, on) \ + led_set_mode_with_color(mode, on, 0) + +/** + * @par Description: + * This API is used to get the current brightness of the led.\n + * It gets the current brightness of the led by calling device_get_property() function.\n + * It returns integer value which is the current brightness on success.\n + * Or a negative value(-1) is returned on failure. + * @return current brightness value on success, -1 if failed + * @see led_set_brightness_with_noti() + * @par Example + * @code + * ... + * int cur_brt; + * cur_brt = led_get_brightness(); + * if( cur_brt < 0 ) + * printf("Fail to get the current brightness of the led.\n"); + * else + * printf("Current brightness of the led is %d\n", cur_brt); + * ... + * @endcode + */ +int led_get_brightness(void); + +/** + * @par Description: + * This API is used to get the max brightness of the led.\n + * It gets the max brightness of the led by calling device_get_property() function.\n + * It returns integer value which is the max brightness on success.\n + * Or a negative value(-1) is returned on failure + * @return max brightness value on success, -1 if failed + * @par Example + * @code + * ... + * int max_brt; + * max_brt = led_get_max_brightness(); + * if( max_brt < 0 ) + * printf("Fail to get the max brightness of the led.\n"); + * ... + * @endcode + */ +int led_get_max_brightness(void); + +/** + * @par Description: + * This API is used to set the current brightness of the led.\n + * It sets the current brightness of the led by calling device_set_property() function.\n + * @param[in] val brightness value that you want to set + * @param[in] enable noti + * @return 0 on success, -1 if failed + * @see led_get_brightness() + * @par Example + * @code + * ... + * if( led_set_brightness_with_noti(1, 1) < 0 ) + * printf("Fail to set the brightness of the led\n"); + * ... + * @endcode + */ +int led_set_brightness_with_noti(int val, bool enable); + +/** + * @par Description: + * This API is used to set command of the irled.\n + * It sets the command to control irled by calling device_set_property() function.\n + * @param[in] value string that you want to set + * @return 0 on success, -1 if failed + * @see led_set_brightness_with_noti() + * @par Example + * @code + * ... + * if( led_set_ir_command(("38000,173,171,24,...,1880") < 0 ) + * printf("Fail to set the command of the irled\n"); + * ... + * @endcode + */ +int led_set_ir_command(char *value); + +/** + * @par Description: + * This API is used to set LED mode with color.\n + * It sets the command to set LED mode by calling device_set_property() function.\n + * @param[in] mode LED mode + * @param[in] on enable/disable LED + * @param[in] color LED color + * @return 0 on success, -1 if failed + * @see LED_MODE + * @par Example + * @code + * ... + * if( led_set_mode_with_color(LED_LOW_BATTERY, 1, 0) < 0 ) + * printf("Fail to set LED mode with color\n"); + * ... + * @endcode + * @todo describe color + */ +int led_set_mode_with_color(int mode, bool on, unsigned int color); + +/** + * @par Description: + * This API is used to set LED mode with all option such as on/off duty and color.\n + * It sets the command to set LED mode by calling device_set_property() function.\n + * @param[in] mode LED mode + * @param[in] val enable/disable LED + * @param[in] on duty value (millisecond) + * @param[in] off duty value (millisecond) + * @param[in] color LED color + * @return 0 on success, -1 if failed + * @see LED_MODE + * @par Example + * @code + * ... + * if( led_set_mode_with_property(LED_LOW_BATTERY, true, 500, 5000, 0xFFFF0000) < 0 ) + * printf("Fail to set LED mode with color\n"); + * ... + * @endcode + * @todo describe color + */ +int led_set_mode_with_property(int mode, bool val, int on, int off, unsigned int color); + +/** + * @} // end of CAPI_SYSTEM_DEVICED_LED_MODULE + */ + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/deviced/dd-mmc.h b/src/deviced/dd-mmc.h new file mode 100644 index 0000000..b387e3e --- /dev/null +++ b/src/deviced/dd-mmc.h @@ -0,0 +1,165 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 __DD_MMC_H__ +#define __DD_MMC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file dd-mmc.h + * @defgroup CAPI_SYSTEM_DEVICED_MMC_MODULE MMC + * @ingroup CAPI_SYSTEM_DEVICED + * @brief This file provides the API for control of mmc(sd-card) + * @section CAPI_SYSTEM_DEVICED_MMC_MODULE_HEADER Required Header + * \#include + */ + +/** + * @addtogroup CAPI_SYSTEM_DEVICED_MMC_MODULE + * @{ + */ + +/** + * @par Description: + * This API is used to mount mmc.\n + * @param[in] mount_point pointer to the character buffer containing the path + * @return 0 on success, -1 if failed + * @par Example + * @code + * ... + * if( mmc_secure_mount(mount_point) < 0 ) + * printf("Mount mmc failed\n"); + * ... + * @endcode + */ +int mmc_secure_mount(const char *mount_point); + +/** + * @par Description: + * This API is used to unmount mmc.\n + * @param[in] mount_point pointer to the character buffer containing the path + * @return 0 on success, -1 if failed + * @par Example + * @code + * ... + * if( mmc_secure_unmount(mount_point) < 0 ) + * printf("Unmount mmc failed\n"); + * ... + * @endcode + */ +int mmc_secure_unmount(const char *mount_point); + +/** + * @brief This structure defines the data for receive result of mmc operations(mount/unmount/format) + */ +struct mmc_contents { + void (*mmc_cb) (int result, void* data);/**< user callback function for receive result of mmc operations */ + void* user_data;/**< input data for callback function's second-param(data) */ +}; + +/** + * @fn int deviced_request_mount_mmc(struct mmc_contents *mmc_data) + * @brief This API is used to mount mmc.\n + * Internally, this API call predefined action API. That is send a notify message. \n + * and when mount operation is finished, cb of deviced_mmc_content struct is called with cb's param1(result). \n + * means of param1 - 0(mount success) and negative value if failed \n + * [mount fail value] \n + * -1 : operation not permmitted \n + * -2 : no such file or directory \n + * -6 : no such device or address \n + * -12 : out of memory \n + * -13 : A component of a path was not searchable \n + * -14 : bad address \n + * -15 : block device is requested \n + * -16 : device or resource busy \n + * -19 : filesystemtype not configured in the kernel \n + * -20 : target, or a prefix of source, is not a directory \n + * -22 : point does not exist \n + * -24 : table of dummy devices is full \n + * -36 : requested name is too long \n + * -40 : Too many links encountered during pathname resolution. \n + * Or, a move was attempted, while target is a descendant of source \n + * @param[in] mmc_data for receive result of mount operation + * @return non-zero on success message sending, -1 if message sending is failed. + */ +int deviced_request_mount_mmc(struct mmc_contents *mmc_data); + +/** + * @fn int deviced_request_unmount_mmc(struct mmc_contents *mmc_data,int option) + * @brief This API is used to unmount mmc.\n + * Internally, this API call predefined action API. That is send a notify message. \n + * and when unmount opeation is finished, cb of deviced_mmc_content struct is called with cb's param1(result). \n + * means of param1 - 0(unmount success) and negative value if failed \n + * [unmount fail value] \n + * -1 : operation not permmitted \n + * -2 : no such file or directory \n + * -11 : try again \n + * -12 : out of memory \n + * -14 : bad address \n + * -16 : device or resource busy \n + * -22 : point does not exist \n + * -36 : requested name is too long \n + * @param[in] mmc_data for receive result of unmount operation + * @param[in] option type of unmount option \n + * 0 : Normal unmount \n + * (if other process still access a sdcard, \n + * unmount will be failed.) \n + * 1 : Force unmount \n + * (if other process still access a sdcard, \n + * this process will be received SIGTERM or SIGKILL.) + * @return non-zero on success message sending, -1 if message sending is failed. + */ +int deviced_request_unmount_mmc(struct mmc_contents *mmc_data, int option); + +/** + * @fn int deviced_request_format_mmc(struct mmc_contents *mmc_data) + * @brief This API is used to format mmc.\n + * Internally, this API call predefined action API. That is send a notify message. \n + * and when format opeation is finished, cb of deviced_mmc_content struct is called with cb's param1(result). \n + * means of param1 - 0(format success) , -1(format fail) + * @param[in] mmc_data for receive result of format operation + * @return non-zero on success message sending, -1 if message sending is failed. + */ +int deviced_request_format_mmc(struct mmc_contents *mmc_data); + +/** + * @fn int deviced_format_mmc(struct mmc_contents *mmc_data, int option) + * @brief This API is used to format mmc.\n + * Internally, this API call predefined action API. That is send a notify message. \n + * and when format opeation is finished, cb of deviced_mmc_content struct is called with cb's param1(result). \n + * means of param1 - 0(format success) and negative value if failed \n + * [format fail value] \n + * -22 : Invalid argument(EINVAL) \n + * @param[in] mmc_data for receive result of format operation + * @param[in] option FMT_NORMAL is 0, FMT_FORCE is 1 + * @return non-zero on success message sending, -1 if message sending is failed. + */ +int deviced_format_mmc(struct mmc_contents *mmc_data, int option); + +/** + * @} // end of CAPI_SYSTEM_DEVICED_MMC_MODULE + */ + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/deviced/dd-storage.h b/src/deviced/dd-storage.h new file mode 100644 index 0000000..deb3cd8 --- /dev/null +++ b/src/deviced/dd-storage.h @@ -0,0 +1,77 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 __DD_STORAGE_H__ +#define __DD_STORAGE_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file dd-storage.h + * @defgroup CAPI_SYSTEM_DEVICED_STORAGE_MODULE Storage + * @ingroup CAPI_SYSTEM_DEVICED + * @brief This file provides the API for control of storage + * @section CAPI_SYSTEM_DEVICED_STORAGE_MODULE_HEADER Required Header + * \#include + */ + +/** + * @addtogroup CAPI_SYSTEM_DEVICED_STORAGE_MODULE + * @{ + */ + +/** + * @par Description + * Storage path type + */ +enum storage_path_type { + STORAGE_DEFAULT = 0, + STORAGE_INTERNAL, + STORAGE_EXTERNAL, + STORAGE_MAX, +}; + +/** + * @par Description: + * This API is used go get storage path.\n + * @param[in] type storage path type + * @param[in] path pointer to a buffer where the path is stored + * @param[in] size size of buffer + * @return 0 on success, -1 if failed + * @see storage_path_type + * @par Example + * @code + * ... + * if ( storage_get_path(STORAGE_INTERNAL, path, 50) < 0 ) + * printf("Get storage path failed\n"); + * ... + * @endcode + */ +int storage_get_path(int type, unsigned char *path, int size); + +/** + * @} // end of CAPI_SYSTEM_DEVICED_STORAGE_MODULE + */ + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/deviced/dd-usbhost.h b/src/deviced/dd-usbhost.h new file mode 100644 index 0000000..424469b --- /dev/null +++ b/src/deviced/dd-usbhost.h @@ -0,0 +1,259 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 __DD_USBHOST_H__ +#define __DD_USBHOST_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file dd-usbhost.h + * @ingroup CAPI_SYSTEM_DEVICED + * @defgroup CAPI_SYSTEM_DEVICED_USBHOST_MODULE usbhost + * @brief This file provides the API for usb host operations + */ + +/** + * @addtogroup CAPI_SYSTEM_DEVICED_USBHOST_MODULE + * @{ + */ + +/** + * @par Description: + * This API is used to initialize usbhost signal \n + * @return 0 on success, negative if failed + * @par Example + * @code + * ... + * if (init_usbhost_signal() < 0) + * printf("Failed to initialize usbhost signal\n"); + * ... + * @endcode + */ +int init_usbhost_signal(void); + +/** + * @par Description: + * This API is used to deinitialize usbhost signal \n + * @par Example + * @code + * ... + * if (init_usbhost_signal() < 0) + * printf("Failed to initialize usbhost signal\n"); + * + * // Do something + * + * deinit_usbhost_signal(); + * ... + * @endcode + */ +void deinit_usbhost_signal(void); + +/** + * @par Description: + * This API is used to register usbhost signal \n + * @param[in] storage_changed callback function which is called when the usbhost signal is delivered + * @param[in] data parameter of storage_changed callback function + * @return 0 on success, negative if failed + * @par Example + * @code + * ... + * if (init_usbhost_signal() < 0) + * printf("Failed to initialize usbhost signal\n"); + * + * if (register_usb_storage_change_handler(storage_cb, data) < 0) { + * printf("Failed to register storage signal\n"); + * deinit_usbhost_signal(); + * return; + * } + * + * // Do something + * + * if (unregister_usb_storage_change_handler() < 0) + * printf("Failed to unregister storage signal\n"); + * + * deinit_usbhost_signal(); + * ... + * @endcode + */ +int register_usb_storage_change_handler( + void (*storage_changed)(char *type, char *path, int mount, void *), + void *data); + +/** + * @par Description: + * This API is used to unregister usbhost signal \n + * @return 0 on success, negative if failed + * @par Example + * @code + * ... + * if (init_usbhost_signal() < 0) + * printf("Failed to initialize usbhost signal\n"); + * + * if (register_usb_storage_change_handler(storage_cb, data) < 0) { + * printf("Failed to register storage signal\n"); + * deinit_usbhost_signal(); + * return; + * } + * + * // Do something + * + * if (unregister_usb_storage_change_handler() < 0) + * printf("Failed to unregister storage signal\n"); + * + * deinit_usbhost_signal(); + * ... + * @endcode + */ +int unregister_usb_storage_change_handler(void); + +/** + * @par Description: + * This API is used to request usb storage information \n + * @return 0 on success, negative if failed + * @par Example + * @code + * ... + * if (init_usbhost_signal() < 0) + * printf("Failed to initialize usbhost signal\n"); + * + * if (register_usb_storage_change_handler(storage_cb, data) < 0) { + * printf("Failed to register storage signal\n"); + * deinit_usbhost_signal(); + * return; + * } + * + * if (request_usb_storage_info() < 0) + * printf("Failed to request all of storage information"); + * + * // Do someting + * + * if (unregister_usb_storage_change_handler() < 0) + * printf("Failed to unregister storage signal\n"); + * + * deinit_usbhost_signal(); + * ... + * @endcode + */ +int request_usb_storage_info(void); + +/** + * @par Description: + * This API is used to mount usb storage \n + * @param[in] path path to unmount + * @return 0 on success, negative if failed + * @par Example + * @code + * ... + * if (init_usbhost_signal() < 0) + * printf("Failed to initialize usbhost signal\n"); + * + * if (register_usb_storage_change_handler(storage_cb, data) < 0) { + * printf("Failed to register storage signal\n"); + * deinit_usbhost_signal(); + * return; + * } + * + * if (mount_usb_storage("/opt/storage/usb/UsbDriveA1") < 0) + * printf("Failed to mount usb storage"); + * + * // Do something.. Mounting takes some time + * + * if (unregister_usb_storage_change_handler() < 0) + * printf("Failed to unregister storage signal\n"); + * + * deinit_usbhost_signal(); + * ... + * @endcode + */ +int mount_usb_storage(char *path); + +/** + * @par Description: + * This API is used to unmount usb storage \n + * @param[in] path path to mount + * @return 0 on success, negative if failed + * @par Example + * @code + * ... + * if (init_usbhost_signal() < 0) + * printf("Failed to initialize usbhost signal\n"); + * + * if (register_usb_storage_change_handler(storage_cb, data) < 0) { + * printf("Failed to register storage signal\n"); + * deinit_usbhost_signal(); + * return; + * } + * + * if (ummount_usb_storage("/opt/storage/usb/UsbDriveA1") < 0) + * printf("Failed to unmount usb storage"); + * + * // Do something.. Unmounting takes some time + * + * if (unregister_usb_storage_change_handler() < 0) + * printf("Failed to unregister storage signal\n"); + * + * deinit_usbhost_signal(); + * ... + * @endcode + */ +int unmount_usb_storage(char *path); + +/** + * @par Description: + * This API is used to format usb storage \n + * @param[in] path path to format + * @return 0 on success, negative if failed + * @par Example + * @code + * ... + * if (init_usbhost_signal() < 0) + * printf("Failed to initialize usbhost signal\n"); + * + * if (register_usb_storage_change_handler(storage_cb, data) < 0) { + * printf("Failed to register storage signal\n"); + * deinit_usbhost_signal(); + * return; + * } + * + * if (format_usb_storage("/opt/storage/usb/UsbDriveA1") < 0) + * printf("Failed to unmount usb storage"); + * + * // Do something.. Formatting takes some time + * + * if (unregister_usb_storage_change_handler() < 0) + * printf("Failed to unregister storage signal\n"); + * + * deinit_usbhost_signal(); + * ... + * @endcode + */ +int format_usb_storage(char *path); + + +/** + * @} // end of CAPI_SYSTEM_DEVICED_USBHOST_MODULE + */ + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/deviced/deviced_doc.h b/src/deviced/deviced_doc.h new file mode 100644 index 0000000..6a478a3 --- /dev/null +++ b/src/deviced/deviced_doc.h @@ -0,0 +1,42 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 __TIZEN_SYSTEM_DEVICED_DOC_H__ +#define __TIZEN_SYSTEM_DEVICED_DOC_H__ + +/** + * @defgroup CAPI_SYSTEM_DEVICED deviced + * @brief The deviced APIs provide functions to control devices. + * @ingroup CAPI_SYSTEM_FRAMEWORK + * @section CAPI_SYSTEM_DEVICED_HEADER Required Header + * \#include + * + * @section CAPI_SYSTEM_SYSTEM_DEVICED_OVERVIEW Overview + * Provides access to a set of device like battery, display, haptic, LED, etc. + * The state of the device is changed or obtained by using APIs provided. + * + * - battery percentage, full charging state, etc. + * - brightness control, enhance mode setting, display lock/unlock, etc. + * - haptic play + * - service led control + * - other devices + * + */ + +#endif /* __TIZEN_SYSTEM_DEVICED_DOC_H__ */ diff --git a/src/deviced/haptic-module.h b/src/deviced/haptic-module.h new file mode 100644 index 0000000..ba72d32 --- /dev/null +++ b/src/deviced/haptic-module.h @@ -0,0 +1,88 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 __HAPTIC_MODULE_H__ +#define __HAPTIC_MODULE_H__ + +/** + * @brief Enumerations of device id for the Haptic Module API. + * @details We support two motors now. + */ +typedef enum { + HAPTIC_MODULE_DEVICE_0 = 0x0, /**< 1st motor */ + HAPTIC_MODULE_DEVICE_1 = 0x1, /**< 2nd motor */ + HAPTIC_MODULE_DEVICE_ALL = 0x4, /**< both of them */ +} haptic_module_device; + +/** + * @brief Enumerations of priority level for the Haptic Module API. + */ +typedef enum +{ + HAPTIC_MODULE_PRIORITY_MIN = 0, /**< Minimum effect priority for developers (default) */ + HAPTIC_MODULE_PRIORITY_MIDDLE, /**< Maximum effect priority for developers */ + HAPTIC_MODULE_PRIORITY_HIGH, /**< Maximum effect priority for OEMs */ +} haptic_module_priority; + +/** + * @brief Enumerations of feedback level for the Haptic Module API. + * @details Haptic level means vibration power (intensity). + */ +typedef enum +{ + HAPTIC_MODULE_FEEDBACK_MIN = 0, + HAPTIC_MODULE_FEEDBACK_MAX = 100, +} haptic_module_feedback; + +/** + * @brief Enumerations of iteration count for the Haptic Module API. + */ +typedef enum +{ + HAPTIC_MODULE_ITERATION_ONCE = 1, + HAPTIC_MODULE_ITERATION_INFINITE = 256, +} haptic_module_iteration; + +/** + * @brief Enumerations of effect or device state for the Haptic Module API. + */ +typedef enum +{ + HAPTIC_MODULE_STATE_STOP = 0, + HAPTIC_MODULE_STATE_PLAYING, +} haptic_module_state; + +/* Error and Return value codes */ +#define HAPTIC_MODULE_ERROR_NONE 0 +#define HAPTIC_MODULE_NOT_INITIALIZED -1 +#define HAPTIC_MODULE_ALREADY_INITIALIZED -2 +#define HAPTIC_MODULE_INVALID_ARGUMENT -3 +#define HAPTIC_MODULE_OPERATION_FAILED -4 +#define HAPTIC_MODULE_NOT_SUPPORTED -5 + +/** + * @par Description: + * effect element for haptic module. + */ +typedef struct { + int haptic_duration; /**< Start time of the effect element in millisecond */ + int haptic_level; /**< Duration of the effect element in millisecond */ +} haptic_module_effect_element; + +#endif /* __HAPTIC_MODULE_H__ */ diff --git a/src/deviced/haptic-plugin-intf.h b/src/deviced/haptic-plugin-intf.h new file mode 100644 index 0000000..97351c8 --- /dev/null +++ b/src/deviced/haptic-plugin-intf.h @@ -0,0 +1,40 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 __HAPTIC_PLUGIN_INTF_H__ +#define __HAPTIC_PLUGIN_INTF_H__ + +#include "haptic-module.h" + +struct haptic_plugin_ops { + int (*get_device_count) (int*); + int (*open_device) (int, int*); + int (*close_device) (int); + int (*vibrate_monotone) (int, int, int, int, int*); + int (*vibrate_buffer) (int, const unsigned char*, int, int, int, int*); + int (*stop_device) (int); + int (*get_device_state) (int, int*); + int (*create_effect) (unsigned char*, int, haptic_module_effect_element*, int); + int (*get_buffer_duration) (int, const unsigned char*, int*); + int (*convert_binary) (const unsigned char*, int, const char*); +}; + +const struct haptic_plugin_ops *get_haptic_plugin_interface(); + +#endif /* __HAPTIC_PLUGIN_INTF_H__ */ diff --git a/src/display/alpm.c b/src/display/alpm.c new file mode 100644 index 0000000..3a0770c --- /dev/null +++ b/src/display/alpm.c @@ -0,0 +1,193 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 "util.h" +#include "core.h" +#include "display-ops.h" +#include "weaks.h" +#include "core/edbus-handler.h" + +#define ON "on" +#define OFF "off" + +#define SIGNAL_ALPM_ON "ALPMOn" +#define SIGNAL_ALPM_OFF "ALPMOff" +#define CLOCK_START "clockstart" +#define CLOCK_END "clockend" +#define ALPM_MAX_TIME 30 /* minutes */ + +static char *alpm_path; +static int update_count; +static int alpm_state; + +void broadcast_alpm_state(int state) +{ + char *signal; + + signal = (state == true ? SIGNAL_ALPM_ON : SIGNAL_ALPM_OFF); + + broadcast_edbus_signal(DEVICED_PATH_DISPLAY, DEVICED_INTERFACE_DISPLAY, + signal, NULL, NULL); +} + +int alpm_get_state(void) +{ + char state[4]; + int ret, alpm; + + if (!alpm_path) + return -ENODEV; + + ret = sys_get_str(alpm_path, state); + if (ret < 0) + return ret; + + if (!strncmp(state, ON, strlen(ON))) + alpm = true; + else if (!strncmp(state, OFF, strlen(OFF))) + alpm = false; + else + alpm = -EINVAL; + + return alpm; +} + +int alpm_set_state(int on) +{ + if (!alpm_path) + return -ENODEV; + + broadcast_alpm_state(on); + + update_count = 0; + + _D("ALPM is %s", (on ? ON : OFF)); + + alpm_state = on; + + return sys_set_str(alpm_path, (on ? ON : OFF)); +} + +static void start_clock(void) +{ + struct timespec now_time; + static struct timespec start_time; + int diff_time; + + if (pm_cur_state == S_NORMAL || + pm_cur_state == S_LCDDIM || + alpm_state == false) + return; + + _D("lcd on"); + + if (update_count == 0) + clock_gettime(CLOCK_REALTIME, &start_time); + + update_count++; + + _D("clock update count : %d", update_count); + + clock_gettime(CLOCK_REALTIME, &now_time); + diff_time = (now_time.tv_sec - start_time.tv_sec) / 60; + + if (diff_time >= ALPM_MAX_TIME) { + _D("Exit ALPM state, LCD off"); + alpm_set_state(false); + backlight_ops.on(); + backlight_ops.off(); + return; + } + + /* change pmstate in order that apps can know the state */ + set_setting_pmstate(S_NORMAL); + backlight_ops.on(); + + sleep(1); + + _D("lcd off"); + set_setting_pmstate(S_LCDOFF); + backlight_ops.off(); + + _D("finished!"); +} + +static void end_clock(void) +{ + if (pm_cur_state == S_NORMAL || + pm_cur_state == S_LCDDIM || + alpm_state == false) + return; + + _D("end clock : lcd off"); +} + +int set_alpm_screen(char *screen) +{ + if (!screen) + return -EINVAL; + + if (!alpm_path) + return -ENODEV; + + if (!strncmp(screen, CLOCK_START, + strlen(CLOCK_START))) { + start_clock(); + } else if (!strncmp(screen, CLOCK_END, + strlen(CLOCK_END))) { + end_clock(); + } + + return 0; +} + +static void alpm_init(void *data) +{ + int fd; + + alpm_path = getenv("ALPM_NODE"); + + /* Check alpm node is valid */ + fd = open(alpm_path, O_RDONLY); + if (fd < 0) { + _E("alpm node is invalid"); + alpm_path = NULL; + return; + } else { + _I("alpm path[%s] is initialized!", alpm_path); + } + close(fd); +} + +static void alpm_exit(void *data) +{ + alpm_set_state(false); +} + +static const struct display_ops display_alpm_ops = { + .name = "alpm", + .init = alpm_init, + .exit = alpm_exit, +}; + +DISPLAY_OPS_REGISTER(&display_alpm_ops) + diff --git a/src/display/auto-brightness.c b/src/display/auto-brightness.c new file mode 100644 index 0000000..45356f4 --- /dev/null +++ b/src/display/auto-brightness.c @@ -0,0 +1,686 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "util.h" +#include "core.h" +#include "display-ops.h" +#include "device-node.h" +#include "proc/proc-handler.h" + +#define DISP_FORCE_SHIFT 12 +#define DISP_FORCE_CMD(prop, force) (((force) << DISP_FORCE_SHIFT) | prop) + +#define SAMPLING_INTERVAL 1 /* 1 sec */ +#define MAX_SAMPLING_COUNT 3 +#define MAX_FAULT 5 +#define DEFAULT_AUTOMATIC_BRT 5 +#define MAX_AUTOMATIC_COUNT 11 +#define AUTOMATIC_DEVIDE_VAL 10 +#define AUTOMATIC_DELAY_TIME 0.5 /* 0.5 sec */ +#define MAX_NORMAL_LUX 10000 + +#define RADIAN_VALUE (57.2957) +#define ROTATION_90 90 +#define WORKING_ANGLE_MIN 0 +#define WORKING_ANGLE_MAX 20 + +#define ISVALID_AUTOMATIC_INDEX(index) (index >= 0 && index < MAX_AUTOMATIC_COUNT) + +static int (*_default_action) (int); +static Ecore_Timer *alc_timeout_id = 0; +static Ecore_Timer *update_timeout; +static int light_handle = -1; +static int accel_handle = -1; +static int fault_count = 0; +static int automatic_brt = DEFAULT_AUTOMATIC_BRT; +static int min_brightness = PM_MIN_BRIGHTNESS; +static char *min_brightness_name = 0; +static int last_autobrightness = 0; +static int value_table[MAX_AUTOMATIC_COUNT]; + +static bool update_working_position(void) +{ + sensor_data_t data; + int ret; + float x, y, z, pitch, realg; + + ret = sf_get_data(accel_handle, ACCELEROMETER_BASE_DATA_SET, &data); + if (ret < 0) { + _E("Fail to get accelerometer data! %d", ret); + return true; + } + + x = data.values[0]; + y = data.values[1]; + z = data.values[2]; + + realg = (float)sqrt((x * x) + (y * y) + (z * z)); + pitch = ROTATION_90 - abs((int) (asin(z / realg) * RADIAN_VALUE)); + + _D("accel data [%f, %f, %f] - %f", x, y, z, pitch); + + if (pitch >= WORKING_ANGLE_MIN && pitch <= WORKING_ANGLE_MAX) + return true; + return false; +} + +static int get_siop_brightness(int value) +{ + int cmd, ret, brt; + + cmd = DISP_CMD(PROP_DISPLAY_MAX_BRIGHTNESS, DEFAULT_DISPLAY); + ret = device_get_property(DEVICE_TYPE_DISPLAY, cmd, &brt); + if (ret >= 0 && value > brt) + return brt; + + return value; +} + +static void alc_set_brightness(int setting, int value, int lux) +{ + static int old; + int position, cmd, tmp_value = 0; + + cmd = DISP_CMD(PROP_DISPLAY_BRIGHTNESS, DEFAULT_DISPLAY); + if (device_get_property(DEVICE_TYPE_DISPLAY, cmd, &tmp_value) < 0) { + _E("Fail to get display brightness!"); + return; + } + + if (value < min_brightness) + value = min_brightness; + + if (cur_siop_level() != 0) + value = get_siop_brightness(value); + + if (tmp_value != value) { + if (!setting && min_brightness == PM_MIN_BRIGHTNESS) { + position = update_working_position(); + if (!position && (old > lux)) { + _D("It's not working position, " + "LCD isn't getting dark!"); + return; + } + } + int diff, step; + + diff = value - tmp_value; + if (abs(diff) < display_conf.brightness_change_step) + step = (diff > 0 ? 1 : -1); + else + step = (int)ceil(diff / + (float)display_conf.brightness_change_step); + + _D("%d", step); + while (tmp_value != value) { + if (step == 0) break; + + tmp_value += step; + if ((step > 0 && tmp_value > value) || + (step < 0 && tmp_value < value)) + tmp_value = value; + + backlight_ops.set_default_brt(tmp_value); + backlight_ops.update(); + last_autobrightness = tmp_value; + } + _I("load light data:%d lux,auto brt %d,min brightness %d," + "brightness %d", lux, automatic_brt, min_brightness, value); + old = lux; + } +} + +static bool check_brightness_changed(int value) +{ + int i; + static int values[MAX_SAMPLING_COUNT], count = 0; + + if (count >= MAX_SAMPLING_COUNT || count < 0) + count = 0; + + values[count++] = value; + + for (i = 0; i < MAX_SAMPLING_COUNT - 1; i++) + if (values[i] != values[i+1]) + return false; + return true; +} + +static void set_brightness_direct(void) +{ + int ret, cmd, value; + sensor_data_t light_data; + + if (pm_cur_state != S_NORMAL || !get_hallic_open()) + return; + + /* direct update if it's previous value */ + if (last_autobrightness > 0) { + backlight_ops.set_default_brt(last_autobrightness); + backlight_ops.update(); + return; + } + + /* get lux value from light sensor */ + ret = sf_get_data(light_handle, LIGHT_LUX_DATA_SET, &light_data); + if (ret < 0 || (int)light_data.values[0] < 0) + return; + + /* get brightness by lux */ + cmd = DISP_FORCE_CMD(PROP_DISPLAY_BRIGHTNESS_BY_LUX, true); + cmd = DISP_CMD(cmd, (int)light_data.values[0]); + ret = device_get_property(DEVICE_TYPE_DISPLAY, cmd, value_table); + if (ret < 0) + return; + + /* get auto brightness level from value table*/ + value = (ISVALID_AUTOMATIC_INDEX(automatic_brt) ? + value_table[automatic_brt] : value_table[DEFAULT_AUTOMATIC_BRT]); + + /* update brightness actually */ + backlight_ops.set_default_brt(value); + backlight_ops.update(); + last_autobrightness = value; +} + +static bool check_hbm(int lux) +{ + int ret, old_state, new_state; + + ret = device_get_property(DEVICE_TYPE_DISPLAY, + PROP_DISPLAY_HBM_CONTROL, &old_state); + if (ret < 0) { + _E("Failed to get HBM state!"); + return false; + } + + if (old_state) + new_state = (lux <= MAX_NORMAL_LUX ? 0 : 1); + else + new_state = (lux >= display_conf.hbm_lux_threshold ? 1 : 0); + + if (old_state != new_state) { + _D("hbm is %s", (new_state ? "on" : "off")); + ret = device_set_property(DEVICE_TYPE_DISPLAY, + PROP_DISPLAY_HBM_CONTROL, new_state); + if (ret < 0) + _E("Failed to set HBM state!"); + /* + * Brightness is changed directly + * when hbm state is changed from on to off + */ + if (!new_state) + set_brightness_direct(); + } + + return (new_state ? true : false); +} + +static bool alc_update_brt(bool setting) +{ + int value = 0; + int cal_value = 0; + int ret = -1; + int cmd; + sensor_data_t light_data; + + ret = sf_get_data(light_handle, LIGHT_LUX_DATA_SET, &light_data); + if (ret < 0 || (int)light_data.values[0] < 0) { + fault_count++; + } else { + int force = (setting ? 1 : 0); + cmd = DISP_FORCE_CMD(PROP_DISPLAY_BRIGHTNESS_BY_LUX, force); + cmd = DISP_CMD(cmd, (int)light_data.values[0]); + ret = device_get_property(DEVICE_TYPE_DISPLAY, cmd, value_table); + + value = (ISVALID_AUTOMATIC_INDEX(automatic_brt) ? + value_table[automatic_brt] : value_table[DEFAULT_AUTOMATIC_BRT]); + + if (ret < 0 || value < PM_MIN_BRIGHTNESS || + value > PM_MAX_BRIGHTNESS) { + _E("fail to load light data : %d lux, %d", + (int)light_data.values[0], value); + fault_count++; + } else { + fault_count = 0; + + /* Check HBM (High Brightness Mode) */ + if (check_hbm((int)light_data.values[0])) + return EINA_TRUE; + + if (!check_brightness_changed(value) && !setting) + return EINA_TRUE; + + alc_set_brightness(setting, value, (int)light_data.values[0]); + } + } + + if ((fault_count > MAX_FAULT) && !(pm_status_flag & PWROFF_FLAG)) { + if (alc_timeout_id > 0) + ecore_timer_del(alc_timeout_id); + alc_timeout_id = NULL; + vconf_set_int(VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT, + SETTING_BRIGHTNESS_AUTOMATIC_OFF); + _E("Fault counts is over %d, disable automatic brightness", + MAX_FAULT); + return EINA_FALSE; + } + return EINA_TRUE; +} + +static bool alc_handler(void* data) +{ + if (pm_cur_state != S_NORMAL || !get_hallic_open()){ + if (alc_timeout_id > 0) + ecore_timer_del(alc_timeout_id); + alc_timeout_id = NULL; + return EINA_FALSE; + } + + if (alc_update_brt(false) == EINA_FALSE) + return EINA_FALSE; + + if (alc_timeout_id != 0) + return EINA_TRUE; + + return EINA_FALSE; +} + +static int alc_action(int timeout) +{ + /* sampling timer add */ + if (alc_timeout_id == 0 && !(pm_status_flag & PWRSV_FLAG)) { + display_info.update_auto_brightness(true); + + alc_timeout_id = + ecore_timer_add(display_conf.lightsensor_interval, + (Ecore_Task_Cb)alc_handler, NULL); + } + + if (_default_action != NULL) + return _default_action(timeout); + + /* unreachable code */ + return -1; +} + +static int connect_sfsvc(void) +{ + int sf_state = -1; + + _I("connect with sensor fw"); + /* light sensor */ + light_handle = sf_connect(LIGHT_SENSOR); + if (light_handle < 0) { + _E("light sensor attach fail"); + goto error; + } + sf_state = sf_start(light_handle, 0); + if (sf_state < 0) { + _E("light sensor attach fail"); + sf_disconnect(light_handle); + light_handle = -1; + goto error; + } + /* accelerometer sensor */ + accel_handle = sf_connect(ACCELEROMETER_SENSOR); + if (accel_handle < 0) { + _E("accelerometer sensor attach fail"); + goto error; + } + sf_state = sf_start(accel_handle, 0); + if (sf_state < 0) { + _E("accelerometer sensor attach fail"); + sf_disconnect(accel_handle); + accel_handle = -1; + goto error; + } + + fault_count = 0; + return 0; + +error: + if (light_handle >= 0) { + sf_stop(light_handle); + sf_disconnect(light_handle); + light_handle = -1; + } + if (accel_handle >= 0) { + sf_stop(accel_handle); + sf_disconnect(accel_handle); + accel_handle = -1; + } + return -EIO; +} + +static int disconnect_sfsvc(void) +{ + _I("disconnect with sensor fw"); + /* light sensor*/ + if(light_handle >= 0) { + sf_stop(light_handle); + sf_disconnect(light_handle); + light_handle = -1; + } + /* accelerometer sensor*/ + if(accel_handle >= 0) { + sf_stop(accel_handle); + sf_disconnect(accel_handle); + accel_handle = -1; + } + + if (_default_action != NULL) { + states[S_NORMAL].action = _default_action; + _default_action = NULL; + } + if (alc_timeout_id > 0) { + ecore_timer_del(alc_timeout_id); + alc_timeout_id = NULL; + } + + return 0; +} + +static inline void set_brtch_state(void) +{ + if (pm_status_flag & PWRSV_FLAG) { + pm_status_flag |= BRTCH_FLAG; + vconf_set_bool(VCONFKEY_PM_BRIGHTNESS_CHANGED_IN_LPM, true); + _D("brightness changed in low battery," + "escape dim state (light)"); + } +} + +static int set_autobrightness_state(int status) +{ + int ret = -1; + int brt = -1; + int default_brt = -1; + int max_brt = -1; + + if (status == SETTING_BRIGHTNESS_AUTOMATIC_ON) { + if(connect_sfsvc() < 0) + return -1; + + /* escape dim state if it's in low battery.*/ + set_brtch_state(); + + /* change alc action func */ + if (_default_action == NULL) + _default_action = states[S_NORMAL].action; + states[S_NORMAL].action = alc_action; + + set_brightness_direct(); + alc_timeout_id = + ecore_timer_add(display_conf.lightsensor_interval, + (Ecore_Task_Cb)alc_handler, NULL); + } else if (status == SETTING_BRIGHTNESS_AUTOMATIC_PAUSE) { + _I("auto brightness paused!"); + disconnect_sfsvc(); + backlight_ops.hbm_off(); + } else { + disconnect_sfsvc(); + backlight_ops.hbm_off(); + /* escape dim state if it's in low battery.*/ + set_brtch_state(); + + ret = get_setting_brightness(&default_brt); + if (ret != 0 || (default_brt < PM_MIN_BRIGHTNESS || default_brt > PM_MAX_BRIGHTNESS)) { + _I("fail to read vconf value for brightness"); + brt = PM_DEFAULT_BRIGHTNESS; + if(default_brt < PM_MIN_BRIGHTNESS || default_brt > PM_MAX_BRIGHTNESS) + vconf_set_int(VCONFKEY_SETAPPL_LCD_BRIGHTNESS, brt); + default_brt = brt; + } + + backlight_ops.set_default_brt(default_brt); + backlight_ops.update(); + } + + return 0; +} + +static void set_alc_function(keynode_t *key_nodes, void *data) +{ + int status, ret; + + if (key_nodes == NULL) { + _E("wrong parameter, key_nodes is null"); + return; + } + + status = vconf_keynode_get_int(key_nodes); + + switch (status) { + case SETTING_BRIGHTNESS_AUTOMATIC_OFF: + case SETTING_BRIGHTNESS_AUTOMATIC_ON: + case SETTING_BRIGHTNESS_AUTOMATIC_PAUSE: + ret = set_autobrightness_state(status); + _D("set auto brightness : %d", ret); + break; + default: + _E("invalid value! %d", status); + } +} + +static bool check_sfsvc(void* data) +{ + /* this function will return opposite value for re-callback in fail */ + int vconf_auto; + int sf_state = 0; + + _I("register sfsvc"); + + vconf_get_int(VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT, &vconf_auto); + if (vconf_auto == SETTING_BRIGHTNESS_AUTOMATIC_ON) { + if(connect_sfsvc() < 0) + return EINA_TRUE; + + /* change alc action func */ + if (_default_action == NULL) + _default_action = states[S_NORMAL].action; + states[S_NORMAL].action = alc_action; + alc_timeout_id = + ecore_timer_add(display_conf.lightsensor_interval, + (Ecore_Task_Cb)alc_handler, NULL); + if (alc_timeout_id > 0) + return EINA_FALSE; + disconnect_sfsvc(); + return EINA_TRUE; + } + _I("change vconf value before registering sfsvc"); + return EINA_FALSE; +} + +static void set_alc_automatic_brt(keynode_t *key_nodes, void *data) +{ + if (key_nodes == NULL) { + _E("wrong parameter, key_nodes is null"); + return; + } + automatic_brt = vconf_keynode_get_int(key_nodes) / AUTOMATIC_DEVIDE_VAL; + _D("automatic brt : %d", automatic_brt); + + alc_update_brt(true); +} + +static Eina_Bool update_handler(void* data) +{ + int ret, on; + + update_timeout = NULL; + + if (pm_cur_state != S_NORMAL) + return EINA_FALSE; + + if (!get_hallic_open()) + return EINA_FALSE; + + ret = vconf_get_int(VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT, &on); + if (ret < 0 || on != SETTING_BRIGHTNESS_AUTOMATIC_ON) + return EINA_FALSE; + + _D("auto brightness is working!"); + + sf_change_sensor_option(light_handle, 1); + alc_update_brt(true); + sf_change_sensor_option(light_handle, 0); + + return EINA_FALSE; +} + +static void update_auto_brightness(bool update) +{ + if (update_timeout) { + ecore_timer_del(update_timeout); + update_timeout = NULL; + } + + if (update) { + update_timeout = ecore_timer_add(AUTOMATIC_DELAY_TIME, + update_handler, NULL); + } +} + +static int prepare_lsensor(void *data) +{ + int status, ret; + int sf_state = 0; + int brt = -1; + + ret = vconf_get_int(VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT, &status); + + if (ret == 0 && status == SETTING_BRIGHTNESS_AUTOMATIC_ON) + set_autobrightness_state(status); + + /* add auto_brt_setting change handler */ + vconf_notify_key_changed(VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT, + set_alc_function, NULL); + + vconf_get_int(VCONFKEY_SETAPPL_LCD_AUTOMATIC_BRIGHTNESS, &brt); + if (brt < PM_MIN_BRIGHTNESS || brt > PM_MAX_BRIGHTNESS) { + _E("Failed to get automatic brightness!"); + } else { + automatic_brt = brt / AUTOMATIC_DEVIDE_VAL; + _I("automatic brt init success %d", automatic_brt); + } + + vconf_notify_key_changed(VCONFKEY_SETAPPL_LCD_AUTOMATIC_BRIGHTNESS, + set_alc_automatic_brt, NULL); + + return 0; +} + +static inline void update_brightness_direct(void) +{ + int ret, status; + + ret = vconf_get_int(VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT, &status); + if (ret == 0 && status == SETTING_BRIGHTNESS_AUTOMATIC_ON) + alc_update_brt(true); +} + +static int set_autobrightness_min(int val, char *name) +{ + if (!name) + return -EINVAL; + + if (val < PM_MIN_BRIGHTNESS || val > PM_MAX_BRIGHTNESS) + return -EINVAL; + + min_brightness = val; + + if (min_brightness_name) { + free(min_brightness_name); + min_brightness_name = 0; + } + min_brightness_name = strndup(name, strlen(name)); + + update_brightness_direct(); + + _I("auto brightness min value changed! (%d, %s)", + min_brightness, min_brightness_name); + + return 0; +} + +static int reset_autobrightness_min(char *name, enum watch_id id) +{ + if (!name) + return -EINVAL; + + if (!min_brightness_name) + return -EINVAL; + + if (strcmp(name, min_brightness_name)) + return -EINVAL; + + _I("change to default %d -> %d, %s", min_brightness, + PM_MIN_BRIGHTNESS, min_brightness_name); + min_brightness = PM_MIN_BRIGHTNESS; + if (min_brightness_name) { + free(min_brightness_name); + min_brightness_name = 0; + } + + update_brightness_direct(); + + return 0; +} + +static void auto_brightness_init(void *data) +{ + display_info.update_auto_brightness = update_auto_brightness; + display_info.set_autobrightness_min = set_autobrightness_min; + display_info.reset_autobrightness_min = reset_autobrightness_min; + + prepare_lsensor(NULL); +} + +static void auto_brightness_exit(void *data) +{ + vconf_ignore_key_changed(VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT, + set_alc_function); + + vconf_ignore_key_changed(VCONFKEY_SETAPPL_LCD_AUTOMATIC_BRIGHTNESS, + set_alc_automatic_brt); + + set_autobrightness_state(SETTING_BRIGHTNESS_AUTOMATIC_OFF); +} + +static const struct display_ops display_autobrightness_ops = { + .name = "auto-brightness", + .init = auto_brightness_init, + .exit = auto_brightness_exit, +}; + +DISPLAY_OPS_REGISTER(&display_autobrightness_ops) + diff --git a/src/display/brightness.c b/src/display/brightness.c new file mode 100644 index 0000000..370de9a --- /dev/null +++ b/src/display/brightness.c @@ -0,0 +1,253 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include +#include +#include +#include +#include +#include + +#include "util.h" +#include "core.h" +#include "brightness.h" +#include "display-ops.h" +#include "core/common.h" +#include "core/device-notifier.h" +#include "core/edbus-handler.h" +#include "shared/dbus.h" + +#define KEY_WAITING_TIME 3 /* 3 seconds */ + +#define SIGNAL_BRIGHTNESS_READY "BrightnessReady" +#define SIGNAL_BRIGHTNESS_CHANGED "BrightnessChanged" + +#define METHOD_BRIGHTNESS "BrightnessPopupLaunch" +#define POPUP_TYPE_LAUNCH "launch" +#define POPUP_TYPE_TERMINATE "terminate" + +static Ecore_Timer *popup_timer = NULL; +static int popup_pid = -1; +static bool brightness_ready = false; + +static void broadcast_brightness_changed(int val) +{ + char *arr[1]; + char str[32]; + + snprintf(str, sizeof(str), "%d", val); + arr[0] = str; + + broadcast_edbus_signal(DEVICED_PATH_DISPLAY, DEVICED_INTERFACE_DISPLAY, + SIGNAL_BRIGHTNESS_CHANGED, "i", arr); +} + +static int process_syspopup(char *type) +{ + int pid; + char *pa[4]; + pa[0] = "_SYSPOPUP_CONTENT_"; + pa[1] = "brightness"; + pa[2] = "_TYPE_"; + pa[3] = type; + + pid = dbus_method_sync(POPUP_BUS_NAME, POPUP_PATH_SYSTEM, + POPUP_INTERFACE_SYSTEM, METHOD_BRIGHTNESS, "ssss", pa); + + if (pid < 0) + _E("Failed to syspopup(%d)", pid); + + return pid; +} + +static inline int calculate_brightness(int val, int action) +{ + if (action == BRIGHTNESS_UP) + val += BRIGHTNESS_CHANGE; + else if (action == BRIGHTNESS_DOWN) + val -= BRIGHTNESS_CHANGE; + + val = clamp(val, PM_MIN_BRIGHTNESS, PM_MAX_BRIGHTNESS); + + return val; +} + +static void update_brightness(int action) +{ + int ret, val, new_val; + + ret = vconf_get_int(VCONFKEY_SETAPPL_LCD_BRIGHTNESS, &val); + if (ret < 0) { + _E("Fail to get brightness!"); + return; + } + + new_val = calculate_brightness(val, action); + + if (new_val == val) + return; + + broadcast_brightness_changed(new_val); + + ret = vconf_set_int(VCONFKEY_SETAPPL_LCD_BRIGHTNESS, new_val); + if (!ret) { + backlight_ops.update(); + _I("brightness is changed! (%d)", new_val); + } else { + _E("Fail to set brightness!"); + } +} + +static Eina_Bool key_waiting_expired(void *data) +{ + int ret; + char name[PATH_MAX]; + + popup_timer = NULL; + brightness_ready = false; + + get_pname(popup_pid, name); + if (!name[0]) + return EINA_FALSE; + + ret = process_syspopup(POPUP_TYPE_TERMINATE); + + if (ret < 0) + _E("Failed to terminate syspopup!(%d:%d)", popup_pid, ret); + else + _D("syspopup is terminated!(%d:%d)", popup_pid, ret); + + popup_pid = -1; + + return EINA_FALSE; +} + +int control_brightness_key(int action) +{ + int ret, val; + char name[PATH_MAX]; + + ret = vconf_get_int(VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT, &val); + if (!ret && val == SETTING_BRIGHTNESS_AUTOMATIC_ON) { + vconf_set_int(VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT, + SETTING_BRIGHTNESS_AUTOMATIC_OFF); + } + + get_pname(popup_pid, name); + if (popup_pid < 0 || !name[0]) { + brightness_ready = false; + popup_pid = process_syspopup(POPUP_TYPE_LAUNCH); + + if (popup_pid > 0) + _D("popup is launched! (%d)", popup_pid); + else + _E("Failed to launch popup! (%d)", popup_pid); + } + + if (!brightness_ready) + return false; + + if (popup_timer) + ecore_timer_reset(popup_timer); + else + popup_timer = ecore_timer_add(KEY_WAITING_TIME, + key_waiting_expired, NULL); + + update_brightness(action); + return false; +} + +static int lcd_changed_cb(void *data) +{ + int lcd_state = (int)data; + + if (lcd_state == S_LCDOFF && popup_pid > 0) { + if (popup_timer) + ecore_timer_del(popup_timer); + + key_waiting_expired(NULL); + } + return 0; +} + +static void brightness_ready_handler(void *data, DBusMessage *msg) +{ + DBusError err; + int ret, state; + + ret = dbus_message_is_signal(msg, DEVICED_INTERFACE_DISPLAY, + SIGNAL_BRIGHTNESS_READY); + if (!ret) { + _E("there is no brightness ready signal"); + return; + } + + dbus_error_init(&err); + + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &state, + DBUS_TYPE_INVALID); + if (!ret) { + _E("no message : [%s:%s]", err.name, err.message); + dbus_error_free(&err); + return; + } + + if (state) { + _D("brightness popup is ready!"); + brightness_ready = true; + } else { + _D("brightness popup is not ready! "); + brightness_ready = false; + + if (popup_timer) + ecore_timer_del(popup_timer); + + key_waiting_expired(NULL); + } +} + +static void brightness_init(void *data) +{ + int ret; + + /* register signal handler to get brightness popup state */ + ret = register_edbus_signal_handler(DEVICED_PATH_DISPLAY, + DEVICED_INTERFACE_DISPLAY, SIGNAL_BRIGHTNESS_READY, + brightness_ready_handler); + if (ret < 0) + _E("Failed to register signal handler! %d", ret); + + /* register notifier */ + register_notifier(DEVICE_NOTIFIER_LCD, lcd_changed_cb); +} + +static void brightness_exit(void *data) +{ + /* unregister notifier */ + unregister_notifier(DEVICE_NOTIFIER_LCD, lcd_changed_cb); +} + +static const struct display_ops display_brightness_ops = { + .name = "brightness", + .init = brightness_init, + .exit = brightness_exit, +}; + +DISPLAY_OPS_REGISTER(&display_brightness_ops) + diff --git a/src/display/brightness.h b/src/display/brightness.h new file mode 100644 index 0000000..34125f8 --- /dev/null +++ b/src/display/brightness.h @@ -0,0 +1,33 @@ +/* + * deviced + * + * Copyright (c) 2011 - 2013 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. + */ + + +/** + * @file brightness.h + * @brief brightness control about brightness popup or the like + */ +#ifndef __BRIGHTNESS_H__ +#define __BRIGHTNESS_H__ + +#define BRIGHTNESS_UP 1 +#define BRIGHTNESS_DOWN 2 +#define BRIGHTNESS_CHANGE 10 + +int control_brightness_key(int action); +#endif + diff --git a/src/display/core.c b/src/display/core.c new file mode 100644 index 0000000..6cfa81a --- /dev/null +++ b/src/display/core.c @@ -0,0 +1,2450 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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. + */ + + +/** + * @file core.c + * @brief Power manager main loop. + * + * This file includes Main loop, the FSM, signal processing. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "util.h" +#include "core.h" +#include "device-node.h" +#include "lock-detector.h" +#include "display-ops.h" +#include "core/queue.h" +#include "core/data.h" +#include "core/devices.h" +#include "core/device-notifier.h" +#include "core/device-handler.h" +#include "core/udev.h" +#include "core/list.h" +#include "core/common.h" +#include "core/edbus-handler.h" +#include "core/config-parser.h" +#include "dd-display.h" +#include "weaks.h" + +#define PM_STATE_LOG_FILE "/var/log/pm_state.log" +#define DISPLAY_CONF_FILE "/etc/deviced/display.conf" + +/** + * @addtogroup POWER_MANAGER + * @{ + */ + +#define SET_BRIGHTNESS_IN_BOOTLOADER "/usr/bin/save_blenv SLP_LCD_BRIGHT" +#define LOCK_SCREEN_INPUT_TIMEOUT 10000 +#define LOCK_SCREEN_CONTROL_TIMEOUT 5000 +#define DD_LCDOFF_INPUT_TIMEOUT 3000 + +unsigned int pm_status_flag; + +static void (*power_saving_func) (int onoff); +static enum device_ops_status status = DEVICE_OPS_STATUS_UNINIT; + +int pm_cur_state; +int pm_old_state; +Ecore_Timer *timeout_src_id; +static int pre_suspend_flag = false; +int system_wakeup_flag = false; +static unsigned int custom_normal_timeout = 0; +static unsigned int custom_dim_timeout = 0; +static int custom_holdkey_block = false; +static int custom_change_pid = -1; +static char *custom_change_name; +static int standby_mode = false; +static int standby_state = false; +static Eina_List *standby_mode_list = NULL; +static int (*basic_action) (int); +static bool hallic_open = true; +static Ecore_Timer *lock_timeout_id; +static int lock_screen_timeout = LOCK_SCREEN_INPUT_TIMEOUT; +static int hdmi_state = 0; +static int tts_state = false; +static struct timeval lcdon_tv; + +/* default transition, action fuctions */ +static int default_trans(int evt); +static int default_action(int timeout); +static int default_check(int next); + +struct state states[S_END] = { + {S_START, default_trans, default_action, default_check,}, + {S_NORMAL, default_trans, default_action, default_check,}, + {S_LCDDIM, default_trans, default_action, default_check,}, + {S_LCDOFF, default_trans, default_action, default_check,}, + {S_SLEEP, default_trans, default_action, default_check,} +}; + +static const char state_string[5][10] = + { "S_START", "S_NORMAL", "S_LCDDIM", "S_LCDOFF", "S_SLEEP" }; + +static int trans_table[S_END][EVENT_END] = { + /* Timeout , Input */ + {S_START, S_START}, /* S_START */ + {S_LCDDIM, S_NORMAL}, /* S_NORMAL */ + {S_LCDOFF, S_NORMAL}, /* S_LCDDIM */ + {S_SLEEP, S_NORMAL}, /* S_LCDOFF */ + {S_LCDOFF, S_NORMAL}, /* S_SLEEP */ +}; + +#define SHIFT_UNLOCK 4 +#define MASK_RESET_TIMEOUT 0x8 /* 1000 */ +#define MASK_MARGIN_TIMEOUT (0x1 << 8) +#define SHIFT_CHANGE_STATE 7 +#define CHANGE_STATE_BIT 0xF00 /* 1111 0000 0000 */ +#define SHIFT_LOCK_FLAG 16 +#define SHIFT_CHANGE_TIMEOUT 20 +#define CUSTOM_TIMEOUT_BIT 0x1 +#define CUSTOM_HOLDKEY_BIT 0x2 +#define HOLD_KEY_BLOCK_BIT 0x1 +#define STANDBY_MODE_BIT 0x2 +#define TIMEOUT_NONE (-1) + +#define S_COVER_TIMEOUT 8000 +#define GET_HOLDKEY_BLOCK_STATE(x) ((x >> SHIFT_LOCK_FLAG) & HOLD_KEY_BLOCK_BIT) +#define GET_STANDBY_MODE_STATE(x) ((x >> SHIFT_LOCK_FLAG) & STANDBY_MODE_BIT) +#define MASK32 0xffffffff +#define BOOTING_DONE_WATING_TIME 60000 /* 1 minute */ +#define LOCK_TIME_ERROR 600 /* 600 seconds */ +#define LOCK_TIME_WARNING 60 /* 60 seconds */ + +#define ACTIVE_ACT "active" +#define INACTIVE_ACT "inactive" +#define SIGNAL_LCD_ON "LCDOn" +#define SIGNAL_LCD_OFF "LCDOff" + +#define LOCK_SCREEN_WATING_TIME 0.3 /* 0.3 second */ +#define LONG_PRESS_INTERVAL 2 /* 2 seconds */ +#define SAMPLING_INTERVAL 1 /* 1 sec */ +#define BRIGHTNESS_CHANGE_STEP 10 +#define HBM_LUX_THRESHOLD 32768 /* lux */ +#define LCD_ALWAYS_ON 0 +#define LCDOFF_TIMEOUT 500 /* milli second */ + +#define DIFF_TIMEVAL_MS(a, b) \ + (((a.tv_sec * 1000000 + a.tv_usec) - \ + (b.tv_sec * 1000000 + b.tv_usec)) \ + / 1000) + +struct display_config display_conf = { + .lock_wait_time = LOCK_SCREEN_WATING_TIME, + .longpress_interval = LONG_PRESS_INTERVAL, + .lightsensor_interval = SAMPLING_INTERVAL, + .lcdoff_timeout = LCDOFF_TIMEOUT, + .brightness_change_step = BRIGHTNESS_CHANGE_STEP, + .hbm_lux_threshold = HBM_LUX_THRESHOLD, + .lcd_always_on = LCD_ALWAYS_ON, + .framerate_app = {0,0,0,0}, + .control_display = 0, + .powerkey_doublepress = 0, + .alpm_on = 0, +}; + +struct display_function_info display_info = { + .update_auto_brightness = NULL, + .set_autobrightness_min = NULL, + .reset_autobrightness_min = NULL, + .face_detection = NULL, +}; + +typedef struct _pm_lock_node { + pid_t pid; + Ecore_Timer *timeout_id; + time_t time; + bool holdkey_block; + struct _pm_lock_node *next; +} PmLockNode; + +static PmLockNode *cond_head[S_END]; + +static void set_process_active(bool flag, pid_t pid) +{ + char str[6]; + char *arr[2]; + int ret; + + if (pid >= INTERNAL_LOCK_BASE) + return; + + sprintf(str, "%d", (int)pid); + + arr[0] = (flag ? ACTIVE_ACT : INACTIVE_ACT); + arr[1] = str; + + /* Send dbug to resourced */ + ret = broadcast_edbus_signal(RESOURCED_PATH_PROCESS, + RESOURCED_INTERFACE_PROCESS, RESOURCED_METHOD_ACTIVE, "si", arr); + if (ret < 0) + _E("Fail to send dbus signal to resourced!!"); +} + +int get_standby_state(void) +{ + return standby_state; +} + +static inline void set_standby_state(bool state) +{ + if (standby_state != state) + standby_state = state; +} + +void broadcast_lcd_on(void) +{ + broadcast_edbus_signal(DEVICED_PATH_DISPLAY, DEVICED_INTERFACE_DISPLAY, + SIGNAL_LCD_ON, NULL, NULL); +} + +void broadcast_lcd_off(void) +{ + broadcast_edbus_signal(DEVICED_PATH_DISPLAY, DEVICED_INTERFACE_DISPLAY, + SIGNAL_LCD_OFF, NULL, NULL); +} + +void tts_lcd_off(void) +{ + int ret; + + ret = dbus_method_sync(POPUP_BUS_NAME, POPUP_PATH_SERVANT, + POPUP_IFACE_SERVANT, POPUP_METHOD_SCREENOFF_TTS, NULL, NULL); + + if (ret < 0) + _E("Failed to tts(%d)", ret); +} + +inline void lcd_on_procedure(void) +{ + broadcast_lcd_on(); + /* AMOLED Low Power Mode off */ + if (display_conf.alpm_on == true && + alpm_set_state != NULL) { + if (alpm_set_state(false) < 0) + _E("Failed to ALPM off"); + } + backlight_ops.update(); + backlight_ops.on(); + touch_ops.screen_on(); +} + +inline void lcd_off_procedure(void) +{ + if (standby_mode) { + _D("standby mode! lcd off logic is skipped"); + return; + } + /* AMOLED Low Power Mode on */ + if (display_conf.alpm_on == true && + alpm_set_state != NULL) { + if (alpm_set_state(true) < 0) + _E("Failed to ALPM on!"); + } + broadcast_lcd_off(); + backlight_ops.off(); + touch_ops.screen_off(); + + if (tts_state) + tts_lcd_off(); +} + +int low_battery_state(int val) +{ + switch (val) { + case VCONFKEY_SYSMAN_BAT_POWER_OFF: + case VCONFKEY_SYSMAN_BAT_CRITICAL_LOW: + case VCONFKEY_SYSMAN_BAT_REAL_POWER_OFF: + return true; + } + return false; +} + +int get_hallic_open(void) +{ + return hallic_open; +} + +static int refresh_app_cond() +{ + trans_condition = 0; + + if (cond_head[S_LCDDIM] != NULL) + trans_condition = trans_condition | MASK_DIM; + if (cond_head[S_LCDOFF] != NULL) + trans_condition = trans_condition | MASK_OFF; + if (cond_head[S_SLEEP] != NULL) + trans_condition = trans_condition | MASK_SLP; + + return 0; +} + +static PmLockNode *find_node(enum state_t s_index, pid_t pid) +{ + PmLockNode *t = cond_head[s_index]; + + while (t != NULL) { + if (t->pid == pid) + break; + t = t->next; + } + return t; +} + +static PmLockNode *add_node(enum state_t s_index, pid_t pid, Ecore_Timer *timeout_id, + bool holdkey_block) +{ + PmLockNode *n; + time_t now; + + n = (PmLockNode *) malloc(sizeof(PmLockNode)); + if (n == NULL) { + _E("Not enough memory, add cond. fail"); + return NULL; + } + + time(&now); + n->pid = pid; + n->timeout_id = timeout_id; + n->time = now; + n->holdkey_block = holdkey_block; + n->next = cond_head[s_index]; + cond_head[s_index] = n; + + refresh_app_cond(); + return n; +} + +static int del_node(enum state_t s_index, PmLockNode *n) +{ + PmLockNode *t; + PmLockNode *prev; + + if (n == NULL) + return 0; + + t = cond_head[s_index]; + prev = NULL; + while (t != NULL) { + if (t == n) { + if (prev != NULL) + prev->next = t->next; + else + cond_head[s_index] = cond_head[s_index]->next; + /* delete timer */ + if (t->timeout_id) + ecore_timer_del(t->timeout_id); + free(t); + break; + } + prev = t; + t = t->next; + } + refresh_app_cond(); + return 0; +} + +static void print_node(int next) +{ + PmLockNode *n; + char buf[30]; + time_t now; + double diff; + + if (next <= S_START || next >= S_END) + return; + + time(&now); + n = cond_head[next]; + while (n != NULL) { + diff = difftime(now, n->time); + ctime_r(&n->time, buf); + + if (diff > LOCK_TIME_ERROR) + _E("over %.0f s, pid: %5d, lock time: %s", diff, n->pid, buf); + else if (diff > LOCK_TIME_WARNING) + _I("over %.0f s, pid: %5d, lock time: %s", diff, n->pid, buf); + else + _I("pid: %5d, lock time: %s", n->pid, buf); + + n = n->next; + } +} + +void get_pname(pid_t pid, char *pname) +{ + char buf[PATH_MAX]; + int cmdline, r; + + if (pid >= INTERNAL_LOCK_BASE) + snprintf(buf, PATH_MAX, "/proc/%d/cmdline", getpid()); + else + snprintf(buf, PATH_MAX, "/proc/%d/cmdline", pid); + + cmdline = open(buf, O_RDONLY); + if (cmdline < 0) { + pname[0] = '\0'; + _E("%d does not exist now(may be dead without unlock)", pid); + return; + } + + r = read(cmdline, pname, PATH_MAX); + if ((r >= 0) && (r < PATH_MAX)) + pname[r] = '\0'; + else + pname[0] = '\0'; + + close(cmdline); +} + +static Eina_Bool del_dim_cond(void *data) +{ + PmLockNode *tmp = NULL; + char pname[PATH_MAX]; + pid_t pid = (pid_t)data; + + _I("delete prohibit dim condition by timeout\n"); + + tmp = find_node(S_LCDDIM, pid); + del_node(S_LCDDIM, tmp); + get_pname(pid, pname); + set_unlock_time(pname, S_NORMAL); + + if (!timeout_src_id) + states[pm_cur_state].trans(EVENT_TIMEOUT); + + return EINA_FALSE; +} + +static Eina_Bool del_off_cond(void *data) +{ + PmLockNode *tmp = NULL; + char pname[PATH_MAX]; + pid_t pid = (pid_t)data; + + _I("delete prohibit off condition by timeout\n"); + + tmp = find_node(S_LCDOFF, pid); + del_node(S_LCDOFF, tmp); + get_pname(pid, pname); + set_unlock_time(pname, S_LCDDIM); + + if (!timeout_src_id) + states[pm_cur_state].trans(EVENT_TIMEOUT); + + return EINA_FALSE; +} + +static Eina_Bool del_sleep_cond(void *data) +{ + PmLockNode *tmp = NULL; + char pname[PATH_MAX]; + pid_t pid = (pid_t)data; + + _I("delete prohibit sleep condition by timeout\n"); + + tmp = find_node(S_SLEEP, pid); + del_node(S_SLEEP, tmp); + get_pname(pid, pname); + set_unlock_time(pname, S_LCDOFF); + + if (!timeout_src_id) + states[pm_cur_state].trans(EVENT_TIMEOUT); + + set_process_active(EINA_FALSE, (pid_t)data); + return EINA_FALSE; +} + +/* timeout handler */ +Eina_Bool timeout_handler(void *data) +{ + _I("Time out state %s\n", state_string[pm_cur_state]); + + if (timeout_src_id) { + ecore_timer_del(timeout_src_id); + timeout_src_id = NULL; + } + + states[pm_cur_state].trans(EVENT_TIMEOUT); + return EINA_FALSE; +} + +inline static void reset_timeout(int timeout) +{ + if (timeout_src_id != 0) { + ecore_timer_del(timeout_src_id); + timeout_src_id = NULL; + } + if (timeout > 0) + timeout_src_id = ecore_timer_add(MSEC_TO_SEC(timeout), + (Ecore_Task_Cb)timeout_handler, NULL); + else if (timeout == 0) + states[pm_cur_state].trans(EVENT_TIMEOUT); +} + +/* get configurations from setting */ +static int get_lcd_timeout_from_settings(void) +{ + int i; + int val = 0; + int ret = -1; + char *buf; + + for (i = 0; i < S_END; i++) { + switch (states[i].state) { + case S_NORMAL: + ret = get_run_timeout(&val); + if (ret != 0) { + buf = getenv("PM_TO_NORMAL"); + val = (buf ? atoi(buf) : DEFAULT_NORMAL_TIMEOUT); + } + break; + case S_LCDDIM: + get_dim_timeout(&val); + break; + case S_LCDOFF: + val = display_conf.lcdoff_timeout; + break; + default: + /* This state doesn't need to set time out. */ + val = 0; + break; + } + if (val > 0) + states[i].timeout = val; + + _I("%s state : %d ms timeout", state_string[i], + states[i].timeout); + } + + return 0; +} + +static void update_display_time(void) +{ + int ret, run_timeout, val; + + /* first priority : s cover */ + if (!hallic_open) { + states[S_NORMAL].timeout = S_COVER_TIMEOUT; + _I("S cover closed : timeout is set by normal(%d ms)", + S_COVER_TIMEOUT); + return; + } + + /* second priority : custom timeout */ + if (custom_normal_timeout > 0) { + states[S_NORMAL].timeout = custom_normal_timeout; + states[S_LCDDIM].timeout = custom_dim_timeout; + _I("CUSTOM : timeout is set by normal(%d ms), dim(%d ms)", + custom_normal_timeout, custom_dim_timeout); + return; + } + + /* third priority : lock state */ + if ((get_lock_screen_state() == VCONFKEY_IDLE_LOCK) && + !get_lock_screen_bg_state()) { + if (pm_status_flag & SMAST_FLAG) { + /* smart stay is on, timeout is always 5 seconds. */ + states[S_NORMAL].timeout = LOCK_SCREEN_CONTROL_TIMEOUT; + _I("LOCK : timeout is set, smart stay timeout(%d ms)", + LOCK_SCREEN_CONTROL_TIMEOUT); + } else { + /* timeout is different according to key or event. */ + states[S_NORMAL].timeout = lock_screen_timeout; + _I("LOCK : timeout is set by normal(%d ms)", + lock_screen_timeout); + } + return; + } + + /* default setting */ + ret = get_run_timeout(&run_timeout); + if (ret < 0 || run_timeout <= 0) { + _E("Can not get run timeout. set default %d ms", + DEFAULT_NORMAL_TIMEOUT); + run_timeout = DEFAULT_NORMAL_TIMEOUT; + } + states[S_NORMAL].timeout = run_timeout; + + get_dim_timeout(&val); + states[S_LCDDIM].timeout = val; + + _I("Normal: NORMAL timeout is set by %d ms", states[S_NORMAL].timeout); + _I("Normal: DIM timeout is set by %d ms", states[S_LCDDIM].timeout); +} + +static void update_display_locktime(int time) +{ + lock_screen_timeout = time; + update_display_time(); +} + +void lcd_on_direct(void) +{ + int ret, call_state; + + if (power_ops.get_power_lock_support() + && pm_cur_state == S_SLEEP) + power_ops.power_lock(); + + if (pre_suspend_flag == true) { + power_ops.post_resume(); + pre_suspend_flag = false; + } +#ifdef MICRO_DD + _D("lcd is on directly"); + gettimeofday(&lcdon_tv, NULL); + if (hbm_check_timeout != NULL) + hbm_check_timeout(); + lcd_on_procedure(); + reset_timeout(DD_LCDOFF_INPUT_TIMEOUT); +#else + ret = vconf_get_int(VCONFKEY_CALL_STATE, &call_state); + if ((ret >= 0 && call_state != VCONFKEY_CALL_OFF) || + (get_lock_screen_state() == VCONFKEY_IDLE_LOCK)) { + _D("LOCK state, lcd is on directly"); + lcd_on_procedure(); + } + reset_timeout(display_conf.lcdoff_timeout); +#endif + update_display_locktime(LOCK_SCREEN_INPUT_TIMEOUT); +} + +int custom_lcdon(int timeout) +{ + struct state *st; + + if (timeout <= 0) + return -EINVAL; + + if (backlight_ops.get_lcd_power() != PM_LCD_POWER_ON) + lcd_on_direct(); + + _I("custom lcd on %d ms", timeout); + if (set_custom_lcdon_timeout(timeout) == true) + update_display_time(); + + /* state transition */ + pm_old_state = pm_cur_state; + pm_cur_state = S_NORMAL; + st = &states[pm_cur_state]; + + /* enter action */ + if (st->action) { + st->action(st->timeout); + } + + return 0; +} + +static int proc_change_state(unsigned int cond, pid_t pid) +{ + int next_state = 0; + struct state *st; + int i; + + for (i = S_NORMAL; i < S_END; i++) { + if ((cond >> (SHIFT_CHANGE_STATE + i)) & 0x1) { + next_state = i; + break; + } + } + _I("Change State to %s (%d)", state_string[next_state], pid); + + if (next_state == S_NORMAL) { + if (backlight_ops.get_lcd_power() != PM_LCD_POWER_ON) + lcd_on_direct(); + } else if (next_state == S_LCDOFF) { + if (backlight_ops.get_lcd_power() != PM_LCD_POWER_OFF) + lcd_off_procedure(); + } + + if (next_state == S_LCDOFF) + if (set_custom_lcdon_timeout(0) == true) + update_display_time(); + + switch (next_state) { + case S_NORMAL: + update_display_locktime(LOCK_SCREEN_CONTROL_TIMEOUT); + /* fall through */ + case S_LCDDIM: + /* fall through */ + case S_LCDOFF: + /* state transition */ + pm_old_state = pm_cur_state; + pm_cur_state = next_state; + st = &states[pm_cur_state]; + + /* pm state is updated to dim because of standby mode */ + if (standby_mode && (pm_cur_state == S_LCDOFF)) + set_setting_pmstate(S_LCDDIM); + + /* enter action */ + if (st->action) { + st->action(st->timeout); + } + break; + case S_SLEEP: + _I("Dangerous requests."); + /* at first LCD_OFF and then goto sleep */ + /* state transition */ + pm_old_state = pm_cur_state; + pm_cur_state = S_LCDOFF; + st = &states[pm_cur_state]; + if (st->action) { + st->action(TIMEOUT_NONE); + } + delete_condition(S_SLEEP); + pm_old_state = pm_cur_state; + pm_cur_state = S_SLEEP; + st = &states[pm_cur_state]; + if (st->action) { + st->action(TIMEOUT_NONE); + } + break; + + default: + return -1; + } + + return 0; +} + +static int standby_action(int timeout) +{ + if (backlight_ops.standby() < 0) { + _E("Fail to start standby mode!"); + return -EIO; + } + if (CHECK_OPS(keyfilter_ops, backlight_enable)) + keyfilter_ops->backlight_enable(false); + touch_ops.key_off(); + touch_ops.screen_off(); + + set_standby_state(true); + + _I("standby mode (only LCD OFF, But phone is working normal)"); + reset_timeout(timeout); + + return 0; +} + +static void set_standby_mode(pid_t pid, int enable) +{ + Eina_List *l = NULL; + Eina_List *l_next = NULL; + int *data = 0; + + if (enable) { + EINA_LIST_FOREACH(standby_mode_list, l, data) + if (pid == (int) data) { + _E("%d already acquired standby mode", pid); + return; + } + EINA_LIST_APPEND(standby_mode_list, (void *)pid); + _I("%d acquire standby mode", pid); + if (standby_mode) + return; + standby_mode = true; + basic_action = states[S_LCDOFF].action; + states[S_LCDOFF].action = standby_action; + trans_table[S_LCDOFF][EVENT_TIMEOUT] = S_LCDOFF; + _I("Standby mode is enabled!"); + } else { + if (!standby_mode) + return; + EINA_LIST_FOREACH_SAFE(standby_mode_list, l, l_next, data) + if (pid == (int) data) { + standby_mode_list = eina_list_remove_list( + standby_mode_list, l); + _I("%d release standby mode", pid); + } + if (standby_mode_list != NULL) + return; + set_standby_state(false); + standby_mode = false; + if (basic_action != NULL) { + states[S_LCDOFF].action = basic_action; + } + trans_table[S_LCDOFF][EVENT_TIMEOUT] = S_SLEEP; + proc_change_state(S_NORMAL << (SHIFT_CHANGE_STATE + S_NORMAL), + getpid()); + _I("Standby mode is disabled!"); + } +} + +/* update transition condition for application requrements */ +static int proc_condition(PMMsg *data) +{ + PmLockNode *tmp = NULL; + unsigned int val = data->cond; + pid_t pid = data->pid; + Ecore_Timer *cond_timeout_id = NULL; + bool holdkey_block = 0; + int val_timeout; + + if (val == 0) + return 0; + /* for debug */ + char pname[PATH_MAX]; + time_t now; + + get_pname(pid, pname); + val_timeout = val >> SHIFT_CHANGE_TIMEOUT; + if (val_timeout & (CUSTOM_TIMEOUT_BIT | CUSTOM_HOLDKEY_BIT)) { + if (data->timeout == 0 && data->timeout2 == 0) { + _I("LCD timeout changed : default setting"); + get_lcd_timeout_from_settings(); + if (get_lock_screen_state() == VCONFKEY_IDLE_LOCK) { + _I("LOCK state : setting lock timeout!"); + states[S_NORMAL].timeout = lock_screen_timeout; + } + custom_normal_timeout = custom_dim_timeout = 0; + if (!(val_timeout & CUSTOM_HOLDKEY_BIT)) + custom_change_pid = -1; + } else { + _I("LCD timeout changed : normal(%d s), dim(%d s)", + data->timeout, data->timeout2); + custom_normal_timeout = SEC_TO_MSEC(data->timeout); + states[S_NORMAL].timeout = custom_normal_timeout; + custom_dim_timeout = SEC_TO_MSEC(data->timeout2); + states[S_LCDDIM].timeout = custom_dim_timeout; + custom_change_pid = pid; + } + + if (val_timeout & CUSTOM_HOLDKEY_BIT) { + custom_holdkey_block = true; + custom_change_pid = pid; + _I("hold key disabled !"); + } else { + custom_holdkey_block = false; + _I("hold key enabled !"); + } + } + + if (val & MASK_DIM) { + if (data->timeout > 0) { + cond_timeout_id = + ecore_timer_add(MSEC_TO_SEC(data->timeout), + (Ecore_Task_Cb)del_dim_cond, (void*)pid); + } + holdkey_block = GET_HOLDKEY_BLOCK_STATE(val); + tmp = find_node(S_LCDDIM, pid); + if (tmp == NULL) { + add_node(S_LCDDIM, pid, cond_timeout_id, holdkey_block); + } else { + if (data->timeout > 0) { + time(&now); + tmp->time = now; + } + if (tmp->timeout_id) { + ecore_timer_del(tmp->timeout_id); + tmp->timeout_id = cond_timeout_id; + } + tmp->holdkey_block = holdkey_block; + } + /* for debug */ + _SD("[%s] locked by pid %d - process %s holdkeyblock %d\n", + "S_NORMAL", pid, pname, holdkey_block); + set_lock_time(pname, S_NORMAL); + } + if (val & MASK_OFF) { + if (data->timeout > 0) { + cond_timeout_id = + ecore_timer_add(MSEC_TO_SEC(data->timeout), + (Ecore_Task_Cb)del_off_cond, (void*)pid); + } + holdkey_block = GET_HOLDKEY_BLOCK_STATE(val); + tmp = find_node(S_LCDOFF, pid); + if (tmp == NULL) { + add_node(S_LCDOFF, pid, cond_timeout_id, holdkey_block); + } else { + if (data->timeout > 0) { + time(&now); + tmp->time = now; + } + if (tmp->timeout_id) { + ecore_timer_del(tmp->timeout_id); + tmp->timeout_id = cond_timeout_id; + } + tmp->holdkey_block = holdkey_block; + } + /* for debug */ + _SD("[%s] locked by pid %d - process %s holdkeyblock %d\n", + "S_LCDDIM", pid, pname, holdkey_block); + set_lock_time(pname, S_LCDDIM); + } + if (val & MASK_SLP) { + /* + * pm-state must be changed to LCDOFF, + * to guarantee of LCDOFF-lock + * when system resumes from suspend state. + */ + if (pm_cur_state == S_SLEEP) + proc_change_state(S_LCDOFF << + (SHIFT_CHANGE_STATE + S_LCDOFF), getpid()); + if (data->timeout > 0) { + cond_timeout_id = + ecore_timer_add(MSEC_TO_SEC(data->timeout), + (Ecore_Task_Cb)del_sleep_cond, (void*)pid); + } + if (GET_STANDBY_MODE_STATE(val)) + set_standby_mode(pid, true); + tmp = find_node(S_SLEEP, pid); + if (tmp == NULL) { + add_node(S_SLEEP, pid, cond_timeout_id, 0); + } else { + if (data->timeout > 0) { + time(&now); + tmp->time = now; + } + if (tmp->timeout_id) { + ecore_timer_del(tmp->timeout_id); + tmp->timeout_id = cond_timeout_id; + } + tmp->holdkey_block = 0; + } + set_process_active(EINA_TRUE, pid); + + /* for debug */ + _SD("[%s] locked by pid %d - process %s\n", "S_LCDOFF", pid, + pname); + set_lock_time(pname, S_LCDOFF); + } + + /* UNLOCK(GRANT) condition processing */ + val = val >> SHIFT_UNLOCK; + if (val & MASK_DIM) { + tmp = find_node(S_LCDDIM, pid); + del_node(S_LCDDIM, tmp); + _SD("[%s] unlocked by pid %d - process %s\n", "S_NORMAL", + pid, pname); + set_unlock_time(pname, S_NORMAL); + } + if (val & MASK_OFF) { + tmp = find_node(S_LCDOFF, pid); + del_node(S_LCDOFF, tmp); + _SD("[%s] unlocked by pid %d - process %s\n", "S_LCDDIM", + pid, pname); + set_unlock_time(pname, S_LCDDIM); + } + if (val & MASK_SLP) { + tmp = find_node(S_SLEEP, pid); + del_node(S_SLEEP, tmp); + if (standby_mode) + set_standby_mode(pid, false); + set_process_active(EINA_FALSE, pid); + + _SD("[%s] unlocked by pid %d - process %s\n", "S_LCDOFF", + pid, pname); + set_unlock_time(pname, S_LCDOFF); + } + val = val >> 8; + if (val != 0) { + if ((val & 0x1)) { + reset_timeout(states[pm_cur_state].timeout); + _I("reset timeout (%d ms)", + states[pm_cur_state].timeout); + } + } else { + /* guard time for suspend */ + if (pm_cur_state == S_LCDOFF) { + reset_timeout(states[S_LCDOFF].timeout); + _I("margin timeout (%d ms)", + states[S_LCDOFF].timeout); + } + } + + if (timeout_src_id == 0) + states[pm_cur_state].trans(EVENT_TIMEOUT); + + return 0; +} + +/* If some changed, return 1 */ +int check_processes(enum state_t prohibit_state) +{ + PmLockNode *t = cond_head[prohibit_state]; + PmLockNode *tmp = NULL; + int ret = 0; + + while (t != NULL) { + if (t->pid < INTERNAL_LOCK_BASE && kill(t->pid, 0) == -1) { + _E("%d process does not exist, delete the REQ" + " - prohibit state %d ", + t->pid, prohibit_state); + if (t->pid == custom_change_pid) { + get_lcd_timeout_from_settings(); + custom_normal_timeout = custom_dim_timeout = 0; + custom_change_pid = -1; + } + if (standby_mode) + set_standby_mode(t->pid, false); + tmp = t; + ret = 1; + } + t = t->next; + + if (tmp != NULL) { + del_node(prohibit_state, tmp); + tmp = NULL; + } + } + + return ret; +} + +int check_holdkey_block(enum state_t state) +{ + PmLockNode *t = cond_head[state]; + int ret = 0; + + _I("check holdkey block : state of %s", state_string[state]); + + if (custom_holdkey_block == true) { + _I("custom hold key blocked by pid(%d)", + custom_change_pid); + return 1; + } + + while (t != NULL) { + if (t->holdkey_block == true) { + ret = 1; + _I("Hold key blocked by pid(%d)!", t->pid); + break; + } + t = t->next; + } + + return ret; +} + +int delete_condition(enum state_t state) +{ + PmLockNode *t = cond_head[state]; + int ret = 0; + PmLockNode *tmp = NULL; + pid_t pid; + char pname[PATH_MAX]; + + _I("delete condition : state of %s", state_string[state]); + + while (t != NULL) { + if (t->timeout_id > 0) { + ecore_timer_del(t->timeout_id); + t->timeout_id = NULL; + } + tmp = t; + t = t->next; + pid = tmp->pid; + if (state == S_SLEEP) + set_process_active(EINA_FALSE, pid); + _I("delete node of pid(%d)", pid); + del_node(state, tmp); + get_pname(pid, pname); + set_unlock_time(pname, state-1); + } + + return 0; +} + +void update_lcdoff_source(int source) +{ + if (standby_mode) + return; + + switch(source) { + case VCONFKEY_PM_LCDOFF_BY_TIMEOUT: + _I("LCD OFF by timeout"); + break; + case VCONFKEY_PM_LCDOFF_BY_POWERKEY: + _I("LCD OFF by powerkey"); + break; + default: + _E("Invalid value(%d)", source); + return; + } + vconf_set_int(VCONFKEY_PM_LCDOFF_SOURCE, source); +} + +#ifdef ENABLE_PM_LOG + +typedef struct _pm_history { + time_t time; + enum pm_log_type log_type; + int keycode; +} pm_history; + +static int max_history_count = MAX_LOG_COUNT; +static pm_history pm_history_log[MAX_LOG_COUNT] = {0,}; +static int history_count = 0; + +static const char history_string[PM_LOG_MAX][15] = + {"PRESS", "LONG PRESS", "RELEASE", "LCD ON", "LCD ON FAIL", + "LCD DIM", "LCD DIM FAIL", "LCD OFF", "LCD OFF FAIL", "SLEEP"}; + +void pm_history_init() +{ + memset(pm_history_log, 0x0, sizeof(pm_history_log)); + history_count = 0; + max_history_count = MAX_LOG_COUNT; +} + +void pm_history_save(enum pm_log_type log_type, int code) +{ + time_t now; + + time(&now); + pm_history_log[history_count].time = now; + pm_history_log[history_count].log_type = log_type; + pm_history_log[history_count].keycode = code; + history_count++; + + if (history_count >= max_history_count) + history_count = 0; +} + +void pm_history_print(int fd, int count) +{ + int start_index, index, i; + char buf[255]; + char time_buf[30]; + + if (count <= 0 || count > max_history_count) + return; + + start_index = (history_count - count + max_history_count) + % max_history_count; + + for (i = 0; i < count; i++) { + index = (start_index + i) % max_history_count; + + if (pm_history_log[index].time == 0) + continue; + + if (pm_history_log[index].log_type < PM_LOG_MIN || + pm_history_log[index].log_type >= PM_LOG_MAX) + continue; + ctime_r(&pm_history_log[index].time, time_buf); + snprintf(buf, sizeof(buf), "[%3d] %15s %3d %s", + index, + history_string[pm_history_log[index].log_type], + pm_history_log[index].keycode, + time_buf); + write(fd, buf, strlen(buf)); + } +} +#endif + +/* logging indev_list for debug */ +void print_dev_list(int fd) +{ + int i; + unsigned int total = 0; + indev *tmp; + + total = eina_list_count(indev_list); + _I("***** total list : %d *****", total); + for (i = 0; i < total; i++) { + tmp = (indev*)eina_list_nth(indev_list, i); + _I("* %d | path:%s, fd:%d, dev_fd:%d", + i, tmp->dev_path, tmp->fd, tmp->dev_fd); + if (fd >= 0) { + char buf[255]; + snprintf(buf, sizeof(buf), " %2d| path:%s, fd:%d, dev_fd:%d\n", + i, tmp->dev_path, tmp->fd, tmp->dev_fd); + write(fd, buf, strlen(buf)); + } + } + _I("***************************\n"); +} + +void print_info(int fd) +{ + int s_index = 0; + char buf[255]; + int i = 1, ret; + Eina_List *l = NULL; + int *data = 0; + char pname[PATH_MAX]; + + if (fd < 0) + return; + + snprintf(buf, sizeof(buf), + "\n===========================================" + "===========================\n"); + write(fd, buf, strlen(buf)); + snprintf(buf, sizeof(buf),"Timeout Info: Run[%dms] Dim[%dms] Off[%dms]\n", + states[S_NORMAL].timeout, + states[S_LCDDIM].timeout, states[S_LCDOFF].timeout); + write(fd, buf, strlen(buf)); + + snprintf(buf, sizeof(buf), "Tran. Locked : %s %s %s\n", + (trans_condition & MASK_DIM) ? state_string[S_NORMAL] : "-", + (trans_condition & MASK_OFF) ? state_string[S_LCDDIM] : "-", + (trans_condition & MASK_SLP) ? state_string[S_LCDOFF] : "-"); + write(fd, buf, strlen(buf)); + + snprintf(buf, sizeof(buf), "Current State: %s\n", + state_string[pm_cur_state]); + write(fd, buf, strlen(buf)); + + snprintf(buf, sizeof(buf), "Current Lock Conditions: \n"); + write(fd, buf, strlen(buf)); + + for (s_index = S_NORMAL; s_index < S_END; s_index++) { + PmLockNode *t; + char time_buf[30]; + t = cond_head[s_index]; + + while (t != NULL) { + get_pname((pid_t)t->pid, pname); + ctime_r(&t->time, time_buf); + snprintf(buf, sizeof(buf), + " %d: [%s] locked by pid %d %s %s", + i++, state_string[s_index - 1], t->pid, pname, time_buf); + write(fd, buf, strlen(buf)); + t = t->next; + } + } + + print_dev_list(fd); + + if (standby_mode) { + snprintf(buf, sizeof(buf), "\n\nstandby mode is on\n"); + write(fd, buf, strlen(buf)); + + EINA_LIST_FOREACH(standby_mode_list, l, data) { + get_pname((pid_t)data, pname); + snprintf(buf, sizeof(buf), + " standby mode acquired by pid %d" + " - process %s\n", data, pname); + write(fd, buf, strlen(buf)); + } + } + print_lock_info_list(fd); + +#ifdef ENABLE_PM_LOG + pm_history_print(fd, 250); +#endif +} + +void save_display_log(void) +{ + int fd; + char buf[255]; + time_t now_time; + char time_buf[30]; + + _D("internal state is saved!"); + + time(&now_time); + ctime_r(&now_time, time_buf); + + fd = open(PM_STATE_LOG_FILE, O_CREAT | O_TRUNC | O_WRONLY, 0644); + if (fd != -1) { + snprintf(buf, sizeof(buf), + "\npm_state_log now-time : %d(s) %s\n\n", + (int)now_time, time_buf); + write(fd, buf, strlen(buf)); + + snprintf(buf, sizeof(buf), "pm_status_flag: %x\n", pm_status_flag); + write(fd, buf, strlen(buf)); + + snprintf(buf, sizeof(buf), "screen lock status : %d\n", + get_lock_screen_state()); + write(fd, buf, strlen(buf)); + + print_info(fd); + close(fd); + } + + fd = open("/dev/console", O_WRONLY); + if (fd != -1) { + print_info(fd); + close(fd); + } +} + +/* SIGHUP signal handler + * For debug... print info to syslog + */ +static void sig_hup(int signo) +{ + save_display_log(); +} + +static void sig_usr(int signo) +{ + pm_status_flag |= VCALL_FLAG; +} + +int check_lcdoff_direct(void) +{ + int ret, lock, cradle; + + if (standby_mode) + return false; + + lock = get_lock_screen_state(); + if (lock != VCONFKEY_IDLE_LOCK && hallic_open) + return false; + + if (hdmi_state) + return false; + + ret = vconf_get_int(VCONFKEY_SYSMAN_CRADLE_STATUS, &cradle); + if (ret >= 0 && cradle == DOCK_SOUND) + return false; + + if (pm_old_state != S_NORMAL) + return false; + + if (pm_cur_state != S_LCDDIM) + return false; + + /* + * goto lcd dim state when battery health is bad + * and abnormal popup shows + */ + if ((pm_status_flag & DIMSTAY_FLAG) && + (check_abnormal_popup() == HEALTH_BAD)) + return false; + + _D("Goto LCDOFF direct(%d,%d,%d)", lock, hdmi_state, cradle); + + return true; +} + +int check_lcdoff_lock_state(void) +{ + if (cond_head[S_SLEEP] != NULL) + return true; + + return false; +} + +/* + * default transition function + * 1. call check + * 2. transition + * 3. call enter action function + */ +static int default_trans(int evt) +{ + struct state *st = &states[pm_cur_state]; + int next_state; + + next_state = (enum state_t)trans_table[pm_cur_state][evt]; + + /* check conditions */ + while (st->check && !st->check(next_state)) { + /* There is a condition. */ + if (standby_mode) { + _D("standby mode, goto next_state %s", + state_string[next_state]); + break; + } + _I("%s -> %s : check fail", state_string[pm_cur_state], + state_string[next_state]); + if (!check_processes(next_state)) { + /* this is valid condition - the application that sent the condition is running now. */ + return -1; + } + } + + /* smart stay */ + if (display_info.face_detection && + (pm_status_flag & SMAST_FLAG) && hallic_open) { + if (display_info.face_detection(evt, pm_cur_state, next_state)) + return 0; + } + + /* state transition */ + pm_old_state = pm_cur_state; + pm_cur_state = next_state; + st = &states[pm_cur_state]; + + /* enter action */ + if (st->action) { + if (pm_cur_state == S_LCDOFF) + update_lcdoff_source(VCONFKEY_PM_LCDOFF_BY_TIMEOUT); + + if (pm_cur_state == S_NORMAL || pm_cur_state == S_LCDOFF) + if (set_custom_lcdon_timeout(0) == true) + update_display_time(); + + if (check_lcdoff_direct() == true) { + /* enter next state directly */ + states[pm_cur_state].trans(EVENT_TIMEOUT); + } + else { + st->action(st->timeout); + } + } + + return 0; +} + +static Eina_Bool lcd_on_expired(void *data) +{ + int lock_state, ret; + + if (lock_timeout_id) + lock_timeout_id = NULL; + + /* check state of lock */ + ret = vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, &lock_state); + + if (ret > 0 && lock_state == VCONFKEY_IDLE_LOCK) + return EINA_FALSE; + + if (backlight_ops.get_lcd_power() == PM_LCD_POWER_ON) + return EINA_FALSE; + + /* lock screen is not launched yet, but lcd is on */ + if (backlight_ops.get_lcd_power() != PM_LCD_POWER_ON) + lcd_on_procedure(); + + return EINA_FALSE; +} + +static inline void stop_lock_timer(void) +{ + if (lock_timeout_id) { + ecore_timer_del(lock_timeout_id); + lock_timeout_id = NULL; + } +} + +static void check_lock_screen(void) +{ + int lock_setting, lock_state, app_state, ret; + + stop_lock_timer(); + + ret = vconf_get_int(VCONFKEY_CALL_STATE, &app_state); + if (ret >= 0 && app_state != VCONFKEY_CALL_OFF) + goto lcd_on; + + /* check setting of lock screen is enabled. */ + ret = vconf_get_int(VCONFKEY_SETAPPL_SCREEN_LOCK_TYPE_INT, + &lock_setting); + + if (ret < 0 || lock_setting == SETTING_SCREEN_LOCK_TYPE_NONE) + goto lcd_on; + + /* check state of lock */ + ret = vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, &lock_state); + + if (ret < 0 || lock_state == VCONFKEY_IDLE_LOCK) + goto lcd_on; + + /* Use time to check lock is done. */ + lock_timeout_id = ecore_timer_add(display_conf.lock_wait_time, + (Ecore_Task_Cb)lcd_on_expired, (void*)NULL); + + return; + +lcd_on: + if (backlight_ops.get_lcd_power() != PM_LCD_POWER_ON) + lcd_on_procedure(); +} + +/* default enter action function */ +static int default_action(int timeout) +{ + int ret; + int wakeup_count = -1; + char buf[NAME_MAX]; + char *pkgname = NULL; + int i = 0; + int lock_state = -1; + int app_state = -1; + time_t now; + double diff; + static time_t last_update_time = 0; + static int last_timeout = 0; + struct timeval now_tv; + + if (status != DEVICE_OPS_STATUS_START) { + _E("display is not started!"); + return -EINVAL; + } + + if (pm_cur_state != S_SLEEP) { + if (pm_cur_state == S_NORMAL && + lcdon_tv.tv_sec != 0) { + gettimeofday(&now_tv, NULL); + timeout -= DIFF_TIMEVAL_MS(now_tv, lcdon_tv); + lcdon_tv.tv_sec = 0; + } + /* set timer with current state timeout */ + reset_timeout(timeout); + + if (pm_cur_state == S_NORMAL) { + time(&last_update_time); + last_timeout = timeout; + } else { + _I("timout set: %s state %d ms", + state_string[pm_cur_state], timeout); + } + } + + if (pm_cur_state != pm_old_state && pm_cur_state != S_SLEEP) { + if (power_ops.get_power_lock_support()) + power_ops.power_lock(); + if (pm_cur_state != S_LCDOFF) + set_setting_pmstate(pm_cur_state); + device_notify(DEVICE_NOTIFIER_LCD, (void *)pm_cur_state); + } + + if (pm_old_state == S_NORMAL && pm_cur_state != S_NORMAL) { + time(&now); + diff = difftime(now, last_update_time); + _I("S_NORMAL is changed to %s [%d ms, %.0f s]", + state_string[pm_cur_state], last_timeout, diff); + } + + switch (pm_cur_state) { + case S_NORMAL: + /* + * normal state : backlight on and restore + * the previous brightness + */ + if (pm_old_state == S_LCDOFF || pm_old_state == S_SLEEP) { + if (pre_suspend_flag == true) { + power_ops.post_resume(); + pre_suspend_flag = false; + } + check_lock_screen(); + } else if (pm_old_state == S_LCDDIM) + backlight_ops.update(); + set_standby_state(false); + break; + + case S_LCDDIM: + if (pm_old_state == S_NORMAL && + backlight_ops.get_custom_status()) + backlight_ops.save_custom_brightness(); + /* lcd dim state : dim the brightness */ + backlight_ops.dim(); + if (pm_old_state == S_LCDOFF || pm_old_state == S_SLEEP) { + broadcast_lcd_on(); + backlight_ops.on(); + touch_ops.screen_on(); + touch_ops.key_on(); + } + set_standby_state(false); + break; + + case S_LCDOFF: + if (pm_old_state != S_SLEEP && pm_old_state != S_LCDOFF) { + stop_lock_timer(); + /* lcd off state : turn off the backlight */ + if (backlight_ops.get_lcd_power() != PM_LCD_POWER_OFF) + lcd_off_procedure(); + set_setting_pmstate(pm_cur_state); + + if (pre_suspend_flag == false) { + pre_suspend_flag = true; + power_ops.pre_suspend(); + } + } + + if (backlight_ops.get_lcd_power() != PM_LCD_POWER_OFF) + lcd_off_procedure(); + break; + + case S_SLEEP: + if (pm_old_state != S_SLEEP && pm_old_state != S_LCDOFF) + stop_lock_timer(); + + if (backlight_ops.get_lcd_power() != PM_LCD_POWER_OFF) + lcd_off_procedure(); + + if (!power_ops.get_power_lock_support()) { + /* sleep state : set system mode to SUSPEND */ + if (device_get_property(DEVICE_TYPE_POWER, + PROP_POWER_WAKEUP_COUNT, &wakeup_count) < 0) + _E("wakeup count read error"); + + if (wakeup_count < 0) { + _I("Wakup Event! Can not enter suspend mode."); + goto go_lcd_off; + } + + if (device_set_property(DEVICE_TYPE_POWER, + PROP_POWER_WAKEUP_COUNT, wakeup_count) < 0) { + _E("wakeup count write error"); + goto go_lcd_off; + } + } + goto go_suspend; + } + + return 0; + +go_suspend: +#ifdef ENABLE_PM_LOG + pm_history_save(PM_LOG_SLEEP, pm_cur_state); +#endif + if (power_ops.get_power_lock_support()) { + if (power_ops.power_unlock() < 0) + _E("power unlock state error!"); + } else { + power_ops.suspend(); + _I("system wakeup!!"); + system_wakeup_flag = true; + /* Resume !! */ + if (power_ops.check_wakeup_src() == EVENT_DEVICE) + /* system waked up by devices */ + states[pm_cur_state].trans(EVENT_DEVICE); + else + /* system waked up by user input */ + states[pm_cur_state].trans(EVENT_INPUT); + } + return 0; + +go_lcd_off: + if (!power_ops.get_power_lock_support()) { + /* Resume !! */ + states[pm_cur_state].trans(EVENT_DEVICE); + } + return 0; +} + +/* + * default check function + * return + * 0 : can't transit, others : transitable + */ +static int default_check(int next) +{ + int trans_cond = trans_condition & MASK_BIT; + int lock_state = -1; + int app_state = -1; + + vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, &lock_state); + if (lock_state==VCONFKEY_IDLE_LOCK && next != S_SLEEP) { + while(0) { + vconf_get_int(VCONFKEY_CALL_STATE, &app_state); + if (app_state != VCONFKEY_CALL_OFF) + break; + vconf_get_bool(VCONFKEY_ALARM_RINGING, &app_state); + if (app_state == EINA_TRUE) + break; + _I("default_check:LOCK STATE, it's transitable"); + return 1; + } + } + + switch (next) { + case S_LCDDIM: + trans_cond = trans_cond & MASK_DIM; + break; + case S_LCDOFF: + trans_cond = trans_cond & MASK_OFF; + break; + case S_SLEEP: + trans_cond = trans_cond & MASK_SLP; + break; + default: /* S_NORMAL is exceptional */ + trans_cond = 0; + break; + } + + if (trans_cond != 0) { + print_node(next); + return 0; + } + + return 1; /* transitable */ +} + +static void default_saving_mode(int onoff) +{ + if (onoff) { + pm_status_flag |= PWRSV_FLAG; + /* off hbm state, it's power saving mode */ + if (hbm_get_state != NULL && + hbm_get_state() == true) + hbm_set_state_with_timeout(false, 0); + } else { + pm_status_flag &= ~PWRSV_FLAG; + } + if (pm_cur_state == S_NORMAL) + backlight_ops.update(); +} + +static int poll_callback(int condition, PMMsg *data) +{ + static time_t last_t; + time_t now; + + if (status != DEVICE_OPS_STATUS_START) { + _E("display logic is not started!"); + return -ECANCELED; + } + + if (condition == INPUT_POLL_EVENT) { + if (pm_cur_state == S_LCDOFF || pm_cur_state == S_SLEEP) + _I("Power key input"); + time(&now); + if (last_t != now) { + states[pm_cur_state].trans(EVENT_INPUT); + last_t = now; + } + } else if (condition == PM_CONTROL_EVENT) { + if (data->cond & MASK_BIT + || ((data->cond >> SHIFT_UNLOCK) & MASK_BIT) + || (data->cond >> SHIFT_CHANGE_TIMEOUT)) + proc_condition(data); + + if (data->cond & CHANGE_STATE_BIT) + proc_change_state(data->cond, data->pid); + } + + return 0; +} + +static int update_setting(int key_idx, int val) +{ + char buf[PATH_MAX]; + int ret = -1; + int run_timeout = -1; + int power_saving_stat = -1; + int power_saving_display_stat = -1; + + switch (key_idx) { + case SETTING_TO_NORMAL: + ret = get_run_timeout(&run_timeout); + if (ret < 0 || run_timeout <= 0) { + _E("Can not get run timeout. set default %.2f ms", + DEFAULT_NORMAL_TIMEOUT); + run_timeout = DEFAULT_NORMAL_TIMEOUT; + } + states[S_NORMAL].timeout = run_timeout; + states[pm_cur_state].trans(EVENT_INPUT); + break; + case SETTING_HALLIC_OPEN: + hallic_open = val; + update_display_time(); + if (pm_cur_state == S_NORMAL || pm_cur_state == S_LCDDIM) + states[pm_cur_state].trans(EVENT_INPUT); + else if (pm_cur_state == S_SLEEP && hallic_open) + proc_change_state(S_LCDOFF << + (SHIFT_CHANGE_STATE + S_LCDOFF), getpid()); + break; + case SETTING_LOW_BATT: + if (low_battery_state(val)) { + if (!(pm_status_flag & CHRGR_FLAG)) + power_saving_func(true); + pm_status_flag |= LOWBT_FLAG; + } else { + if (pm_status_flag & PWRSV_FLAG) + power_saving_func(false); + pm_status_flag &= ~LOWBT_FLAG; + pm_status_flag &= ~BRTCH_FLAG; + vconf_set_bool(VCONFKEY_PM_BRIGHTNESS_CHANGED_IN_LPM, + false); + } + break; + case SETTING_CHARGING: + if (val) { + if (pm_status_flag & LOWBT_FLAG) { + power_saving_func(false); + pm_status_flag &= ~LOWBT_FLAG; + } + pm_status_flag |= CHRGR_FLAG; + } else { + int bat_state = VCONFKEY_SYSMAN_BAT_NORMAL; + vconf_get_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, + &bat_state); + if (low_battery_state(bat_state)) { + power_saving_func(true); + pm_status_flag |= LOWBT_FLAG; + } + pm_status_flag &= ~CHRGR_FLAG; + } + break; + case SETTING_BRT_LEVEL: + if (pm_status_flag & PWRSV_FLAG) { + pm_status_flag |= BRTCH_FLAG; + vconf_set_bool(VCONFKEY_PM_BRIGHTNESS_CHANGED_IN_LPM, + true); + _I("brightness changed in low battery," + "escape dim state"); + } + backlight_ops.set_default_brt(val); + snprintf(buf, sizeof(buf), "%d", val); + _D("Brightness set in bl : %d",val); + launch_evenif_exist(SET_BRIGHTNESS_IN_BOOTLOADER, buf); + break; + case SETTING_LOCK_SCREEN: + set_lock_screen_state(val); + if (val == VCONFKEY_IDLE_UNLOCK) { + if (CHECK_OPS(keyfilter_ops, backlight_enable)) + keyfilter_ops->backlight_enable(false); + } + + /* LCD on if lock screen show before waiting time */ + if (pm_cur_state == S_NORMAL && + val == VCONFKEY_IDLE_LOCK && + backlight_ops.get_lcd_power() != PM_LCD_POWER_ON) + lcd_on_procedure(); + stop_lock_timer(); + update_display_time(); + if (pm_cur_state == S_NORMAL) { + states[pm_cur_state].trans(EVENT_INPUT); + } + break; + case SETTING_LOCK_SCREEN_BG: + set_lock_screen_bg_state(val); + update_display_time(); + if (pm_cur_state == S_NORMAL) { + states[pm_cur_state].trans(EVENT_INPUT); + } + break; + case SETTING_POWER_SAVING: + if (val == 1) + vconf_get_bool(VCONFKEY_SETAPPL_PWRSV_CUSTMODE_DISPLAY, + &power_saving_display_stat); + if (power_saving_display_stat != 1) + power_saving_display_stat = 0; + if (device_set_property(DEVICE_TYPE_DISPLAY, PROP_DISPLAY_FRAME_RATE, + power_saving_display_stat) < 0) { + _E("Fail to set display frame rate!"); + } + backlight_ops.update(); + break; + case SETTING_POWER_SAVING_DISPLAY: + vconf_get_bool(VCONFKEY_SETAPPL_PWRSV_SYSMODE_STATUS, + &power_saving_stat); + if (power_saving_stat == 1) { + if (val == 1) + power_saving_display_stat = 1; + else + power_saving_display_stat = 0; + if (device_set_property(DEVICE_TYPE_DISPLAY, + PROP_DISPLAY_FRAME_RATE, power_saving_display_stat) < 0) { + _E("Fail to set display frame rate!"); + } + backlight_ops.update(); + } + break; + case SETTING_SMART_STAY: + if (!val) { + pm_status_flag &= ~SMAST_FLAG; + _I("Smart Stay Feature off"); + } else { + pm_status_flag |= SMAST_FLAG; + _I("Smart Stay Feature on"); + } + break; + case SETTING_POWEROFF: + switch (val) { + case VCONFKEY_SYSMAN_POWER_OFF_NONE: + case VCONFKEY_SYSMAN_POWER_OFF_POPUP: + pm_status_flag &= ~PWROFF_FLAG; + break; + case VCONFKEY_SYSMAN_POWER_OFF_DIRECT: + case VCONFKEY_SYSMAN_POWER_OFF_RESTART: + pm_status_flag |= PWROFF_FLAG; + break; + } + break; + case SETTING_BOOT_POWER_ON_STATUS: + /* + * Unlock lcd off after booting is done. + * deviced guarantees all booting script is executing. + * Last script of booting unlocks this suspend blocking state. + */ + if (val == VCONFKEY_DEVICED_BOOT_POWER_ON_DONE) { + _I("booting done"); + pm_unlock_internal(INTERNAL_LOCK_BOOTING, LCD_OFF, PM_SLEEP_MARGIN); + } + break; + case SETTING_POWER_CUSTOM_BRIGHTNESS: + if (val == VCONFKEY_PM_CUSTOM_BRIGHTNESS_ON) + backlight_ops.set_custom_status(true); + else + backlight_ops.set_custom_status(false); + break; + case SETTING_ACCESSIBILITY_TTS: + tts_state = val; + _I("TTS is %s", (val ? "ON" : "OFF")); + break; + + default: + return -1; + } + return 0; +} + +static void check_seed_status(void) +{ + int ret = -1; + int tmp = 0; + int bat_state = VCONFKEY_SYSMAN_BAT_NORMAL; + int max_brt = 0; + int brt = 0; + int lock_state = -1; + int power_saving_stat = -1; + int power_saving_display_stat = -1; + int smart_stay_on = 0; + + /* Charging check */ + if ((get_charging_status(&tmp) == 0) && (tmp > 0)) { + pm_status_flag |= CHRGR_FLAG; + } + + ret = get_setting_brightness(&tmp); + if (ret != 0 || (tmp < PM_MIN_BRIGHTNESS || tmp > PM_MAX_BRIGHTNESS)) { + _I("fail to read vconf value for brightness"); + brt = PM_DEFAULT_BRIGHTNESS; + if (tmp < PM_MIN_BRIGHTNESS || tmp > PM_MAX_BRIGHTNESS) + vconf_set_int(VCONFKEY_SETAPPL_LCD_BRIGHTNESS, brt); + tmp = brt; + } + _I("Set brightness from Setting App. %d", tmp); + backlight_ops.set_default_brt(tmp); + + vconf_get_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, &bat_state); + if (low_battery_state(bat_state)) { + if (!(pm_status_flag & CHRGR_FLAG)) { + power_saving_func(true); + pm_status_flag |= LOWBT_FLAG; + } + } + backlight_ops.update(); + backlight_ops.on(); + touch_ops.screen_on(); + touch_ops.key_on(); + + /* lock screen check */ + ret = vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, &lock_state); + set_lock_screen_state(lock_state); + if (lock_state == VCONFKEY_IDLE_LOCK) { + states[S_NORMAL].timeout = lock_screen_timeout; + _I("LCD NORMAL timeout is set by %d ms" + " for lock screen", lock_screen_timeout); + } + + /* power saving display stat */ + vconf_get_bool(VCONFKEY_SETAPPL_PWRSV_SYSMODE_STATUS, + &power_saving_stat); + if (power_saving_stat <= 0) { + power_saving_display_stat = 0; + } else { + vconf_get_bool(VCONFKEY_SETAPPL_PWRSV_CUSTMODE_DISPLAY, + &power_saving_display_stat); + } + if (power_saving_display_stat < 0) { + _E("failed to read power saving display stat!"); + } else { + _I("power saving display stat : %d", + power_saving_display_stat); + } + + /* Smart stay status */ + vconf_get_int(VCONFKEY_SETAPPL_SMARTSCREEN_SMARTSTAY_STATUS, &smart_stay_on); + if (!smart_stay_on) { + _I("Smart Stay Feature off"); + } else { + _I("Smart Stay Feature on"); + pm_status_flag |= SMAST_FLAG; + } + + /* TTS state */ + ret = vconf_get_bool(VCONFKEY_SETAPPL_ACCESSIBILITY_TTS, &tts_state); + if (ret < 0) + _E("Failed to get TTS setting! (%d)", ret); + _I("TTS is %s", (tts_state ? "ON" : "OFF")); + + return; +} + +enum { + INIT_SETTING = 0, + INIT_INTERFACE, + INIT_POLL, + INIT_FIFO, + INIT_DBUS, + INIT_END +}; + +static const char *errMSG[INIT_END] = { + [INIT_SETTING] = "setting init error", + [INIT_INTERFACE] = "lowlevel interface(sysfs or others) init error", + [INIT_POLL] = "input devices poll init error", + [INIT_FIFO] = "FIFO poll init error", + [INIT_DBUS] = "d-bus init error", +}; + +static int input_action(char* input_act, char* input_path) +{ + int ret = -EINVAL; + Eina_List *list_node = NULL; + Eina_List *l = NULL; + Eina_List *l_next = NULL; + indev *data = NULL; + PmLockNode *tmp = NULL; + + if (!strcmp("add", input_act)) { + _I("add input path : %s", input_path); + ret = init_pm_poll_input(poll_callback, input_path); + } else if (!strcmp("remove", input_act)) { + EINA_LIST_FOREACH_SAFE(indev_list, l, l_next, data) + if(!strcmp(input_path, data->dev_path)) { + _I("remove %s", input_path); + ecore_main_fd_handler_del(data->dev_fd); + close(data->fd); + free(data->dev_path); + free(data); + indev_list = eina_list_remove_list(indev_list, l); + } + ret = 0; + } else if (!strcmp("change", input_act)) { + if (!strcmp("ESD", input_path)) { + _I("ESD on"); + if (pm_cur_state == S_NORMAL) { + backlight_ops.off(); + backlight_ops.on(); + } else if (pm_cur_state == S_LCDDIM) { + backlight_ops.off(); + backlight_ops.dim(); + } + ret = 0; + } + } + return ret; +} + +int set_lcd_timeout(int on, int dim, int holdkey_block, char *name) +{ + if (on == 0 && dim == 0) { + _I("LCD timeout changed : default setting"); + custom_normal_timeout = custom_dim_timeout = 0; + } else if (on < 0 || dim < 0) { + _E("fail to set value (%d,%d)", on, dim); + return -EINVAL; + } else { + _I("LCD timeout changed : on(%ds), dim(%ds)", on, dim); + custom_normal_timeout = SEC_TO_MSEC(on); + custom_dim_timeout = SEC_TO_MSEC(dim); + } + /* Apply new backlight time */ + update_display_time(); + + if (holdkey_block) { + custom_holdkey_block = true; + _I("hold key disabled !"); + } else { + custom_holdkey_block = false; + _I("hold key enabled !"); + } + + if (custom_change_name) { + free(custom_change_name); + custom_change_name = 0; + } + + if (custom_normal_timeout == 0 && + custom_dim_timeout == 0 && + !holdkey_block) + return 0; + + custom_change_name = strndup(name, strlen(name)); + if (!custom_change_name) { + _E("Malloc falied!"); + custom_normal_timeout = custom_dim_timeout = 0; + custom_holdkey_block = false; + return -ENOMEM; + } + + return 0; +} + +int reset_lcd_timeout(char *name, enum watch_id id) +{ + if (!name) + return -EINVAL; + + if (!custom_change_name) + return -EINVAL; + + if (strcmp(name, custom_change_name)) + return -EINVAL; + + _I("reset lcd timeout %s: set default timeout", name); + + free(custom_change_name); + custom_change_name = 0; + custom_normal_timeout = custom_dim_timeout = 0; + custom_holdkey_block = false; + + update_display_time(); + if (pm_cur_state == S_NORMAL) { + states[pm_cur_state].trans(EVENT_INPUT); + } + + return 0; +} + +int get_hdmi_state(void) +{ + return hdmi_state; +} + +static int hdmi_changed(void *data) +{ + hdmi_state = (int)data; + + return 0; +} + +static int hall_ic_open(void *data) +{ + int open = (int)data; + + update_pm_setting(SETTING_HALLIC_OPEN, open); + + return 0; +} + +static int input_device_add(void *data) +{ + char *path = (char *)data; + + if (!path) + return -EINVAL; + + input_action(UDEV_ADD, path); + + return 0; +} + +static int input_device_remove(void *data) +{ + char *path = (char *)data; + + if (!path) + return -EINVAL; + + input_action(UDEV_REMOVE, path); + + return 0; +} + +static int booting_done(void *data) +{ + static bool done = false; + + if (done) + return 0; + + _I("booting done, unlock LCD_OFF"); + pm_unlock_internal(INTERNAL_LOCK_BOOTING, LCD_OFF, PM_SLEEP_MARGIN); + done = true; + + return 0; +} + +static int lcd_esd(void *data) +{ + char *path = data; + + if (!path) + return -EINVAL; + + input_action(UDEV_CHANGE, path); + + return 0; +} + +static int battery_health_changed(void *data) +{ + int health = (int)data; + + if (health == HEALTH_GOOD) { + _D("battery health good"); + pm_status_flag &= ~DIMSTAY_FLAG; + + } else if (health == HEALTH_BAD) { + _D("battery health bad"); + pm_status_flag |= DIMSTAY_FLAG; + } + + return 0; +} + +static int display_load_config(struct parse_result *result, void *user_data) +{ + struct display_config *c = user_data; + + _D("%s,%s,%s", result->section, result->name, result->value); + + if (!c) + return -EINVAL; + + if (!MATCH(result->section, "Display")) + return -EINVAL; + + if (MATCH(result->name, "LockScreenWaitingTime")) { + SET_CONF(c->lock_wait_time, atof(result->value)); + _D("lock wait time is %.3f", c->lock_wait_time); + } else if (MATCH(result->name, "LongPressInterval")) { + SET_CONF(c->longpress_interval, atof(result->value)); + _D("long press interval is %.3f", c->longpress_interval); + } else if (MATCH(result->name, "LightSensorSamplingInterval")) { + SET_CONF(c->lightsensor_interval, atof(result->value)); + _D("lightsensor interval is %.3f", c->lightsensor_interval); + } else if (MATCH(result->name, "LCDOffTimeout")) { + SET_CONF(c->lcdoff_timeout, atoi(result->value)); + _D("lcdoff timeout is %d ms", c->lcdoff_timeout); + } else if (MATCH(result->name, "BrightnessChangeStep")) { + SET_CONF(c->brightness_change_step, atoi(result->value)); + _D("brightness change step is %d", c->brightness_change_step); + } else if (MATCH(result->name, "HBMLuxThreshold")) { + SET_CONF(c->hbm_lux_threshold, atoi(result->value)); + _D("HBM lux threshold is %d", c->hbm_lux_threshold); + } else if (MATCH(result->name, "LCDAlwaysOn")) { + c->lcd_always_on = (MATCH(result->value, "yes") ? 1 : 0); + _D("LCD always on is %d", c->lcd_always_on); + } else if (MATCH(result->name, "ChangedFrameRateAllowed")) { + if (strstr(result->value, "setting")) { + c->framerate_app[REFRESH_SETTING] = 1; + _D("framerate app is Setting"); + } + if (strstr(result->value, "all")) { + memset(c->framerate_app, 1, sizeof(c->framerate_app)); + _D("framerate app is All"); + } + } else if (MATCH(result->name, "ControlDisplay")) { + c->control_display = (MATCH(result->value, "yes") ? 1 : 0); + _D("ControlDisplay is %d", c->control_display); + } else if (MATCH(result->name, "PowerKeyDoublePressSupport")) { + c->powerkey_doublepress = (MATCH(result->value, "yes") ? 1 : 0); + _D("PowerKeyDoublePressSupport is %d", c->powerkey_doublepress); + } else if (MATCH(result->name, "UseALPM")) { + c->alpm_on = (MATCH(result->value, "yes") ? 1 : 0); + _D("UseALPM is %d", c->alpm_on); + } + + return 0; +} + +/** + * Power manager Main + * + */ +static void display_init(void *data) +{ + int ret, i; + unsigned int flags = (WITHOUT_STARTNOTI | FLAG_X_DPMS); + int timeout = 0; + + _I("Start power manager"); + + signal(SIGHUP, sig_hup); + + power_saving_func = default_saving_mode; + /* noti init for new input device like bt mouse */ + indev_list = NULL; + + /* load configutation */ + ret = config_parse(DISPLAY_CONF_FILE, display_load_config, &display_conf); + if (ret < 0) + _W("Failed to load %s, %s Use default value!", + DISPLAY_CONF_FILE, ret); + + register_notifier(DEVICE_NOTIFIER_HALLIC_OPEN, hall_ic_open); + register_notifier(DEVICE_NOTIFIER_INPUT_ADD, input_device_add); + register_notifier(DEVICE_NOTIFIER_INPUT_REMOVE, input_device_remove); + register_notifier(DEVICE_NOTIFIER_BOOTING_DONE, booting_done); + register_notifier(DEVICE_NOTIFIER_LCD_ESD, lcd_esd); + register_notifier(DEVICE_NOTIFIER_HDMI, hdmi_changed); + register_notifier(DEVICE_NOTIFIER_BATTERY_HEALTH, battery_health_changed); + + for (i = INIT_SETTING; i < INIT_END; i++) { + switch (i) { + case INIT_SETTING: + ret = init_setting(update_setting); + break; + case INIT_INTERFACE: + get_lcd_timeout_from_settings(); + ret = init_sysfs(flags); + break; + case INIT_POLL: + _I("poll init"); + ret = init_pm_poll(poll_callback); + break; + case INIT_DBUS: + _I("dbus init"); + ret = init_pm_dbus(); + break; + } + if (ret != 0) { + _E("%s", errMSG[i]); + break; + } + } + + if (i == INIT_END) { + display_ops_init(NULL); +#ifdef ENABLE_PM_LOG + pm_history_init(); +#endif + check_seed_status(); + + if (display_conf.lcd_always_on) { + _D("LCD always on!"); + trans_table[S_NORMAL][EVENT_TIMEOUT] = S_NORMAL; + } + + if (flags & WITHOUT_STARTNOTI) { /* start without noti */ + _I("Start Power managing without noti"); + pm_cur_state = S_NORMAL; + set_setting_pmstate(pm_cur_state); + + timeout = states[S_NORMAL].timeout; + /* check minimun lcd on time */ + if (timeout < DEFAULT_NORMAL_TIMEOUT) + timeout = DEFAULT_NORMAL_TIMEOUT; + + reset_timeout(timeout); + + /* + * Lock lcd off until booting is done. + * deviced guarantees all booting script is executing. + * Last script of booting unlocks this suspend blocking state. + */ + pm_lock_internal(INTERNAL_LOCK_BOOTING, LCD_OFF, + STAY_CUR_STATE, BOOTING_DONE_WATING_TIME); + } + if (CHECK_OPS(keyfilter_ops, init)) + keyfilter_ops->init(); + } + status = DEVICE_OPS_STATUS_START; +} + +static void display_exit(void *data) +{ + int i = INIT_END; + + status = DEVICE_OPS_STATUS_STOP; + + /* Set current state to S_NORMAL */ + pm_cur_state = S_NORMAL; + set_setting_pmstate(pm_cur_state); + /* timeout is not needed */ + reset_timeout(0); + + if (CHECK_OPS(keyfilter_ops, exit)) + keyfilter_ops->exit(); + + display_ops_exit(NULL); + + for (i = i - 1; i >= INIT_SETTING; i--) { + switch (i) { + case INIT_SETTING: + exit_setting(); + break; + case INIT_INTERFACE: + exit_sysfs(); + break; + case INIT_POLL: + unregister_notifier(DEVICE_NOTIFIER_HALLIC_OPEN, hall_ic_open); + unregister_notifier(DEVICE_NOTIFIER_INPUT_ADD, + input_device_add); + unregister_notifier(DEVICE_NOTIFIER_INPUT_REMOVE, + input_device_remove); + unregister_notifier(DEVICE_NOTIFIER_BOOTING_DONE, + booting_done); + unregister_notifier(DEVICE_NOTIFIER_LCD_ESD, lcd_esd); + unregister_notifier(DEVICE_NOTIFIER_HDMI, hdmi_changed); + unregister_notifier(DEVICE_NOTIFIER_BATTERY_HEALTH, + battery_health_changed); + + exit_pm_poll(); + break; + } + } + free_lock_info_list(); + + _I("Stop power manager"); +} + +static int display_start(void) +{ + if (status == DEVICE_OPS_STATUS_START) + return -EALREADY; + + display_init(NULL); + + return 0; +} + +static int display_stop(void) +{ + if (status == DEVICE_OPS_STATUS_STOP) + return -EALREADY; + + display_exit(NULL); + + return 0; +} + +static int display_status(void) +{ + return status; +} + +static const struct device_ops display_device_ops = { + .priority = DEVICE_PRIORITY_HIGH, + .name = "display", + .init = display_init, + .exit = display_exit, + .start = display_start, + .stop = display_stop, + .status = display_status, +}; + +DEVICE_OPS_REGISTER(&display_device_ops) + +/** + * @} + */ diff --git a/src/display/core.h b/src/display/core.h new file mode 100644 index 0000000..c5bf7e1 --- /dev/null +++ b/src/display/core.h @@ -0,0 +1,167 @@ +/* + * deviced + * + * Copyright (c) 2011 - 2013 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. + */ + + +/** + * @file core.h + * @brief Power manager main loop header file + */ +#ifndef __POWER_MANAGER_H__ +#define __POWER_MANAGER_H__ + +#include "poll.h" +#include "device-interface.h" +#include "setting.h" + +#define WITHOUT_STARTNOTI 0x1 +#define MASK_BIT 0x7 /* 111 */ +#define MASK_DIM 0x1 /* 001 */ +#define MASK_OFF 0x2 /* 010 */ +#define MASK_SLP 0x4 /* 100 */ + +#define VCALL_FLAG 0x00000001 +#define LOWBT_FLAG 0x00000100 +#define CHRGR_FLAG 0x00000200 +#define PWRSV_FLAG 0x00000400 +#define SMAST_FLAG 0x00001000 +#define BRTCH_FLAG 0x00002000 +#define PWROFF_FLAG 0x00004000 +#define DIMSTAY_FLAG 0x00008000 + +#define DEFAULT_NORMAL_TIMEOUT 30000 +#define DEFAULT_DIM_TIMEOUT 5000 +#define DEFAULT_OFF_TIMEOUT 1000 + +#define MASK32 0xffffffff + +#define CHECK_OPS(d, op) (d != NULL && d->op != NULL) + +#ifdef ENABLE_PM_LOG +#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_FAIL, + PM_LOG_LCD_DIM, + PM_LOG_LCD_DIM_FAIL, + PM_LOG_LCD_OFF, + PM_LOG_LCD_OFF_FAIL, + PM_LOG_SLEEP, + PM_LOG_MAX +}; + +void pm_history_save(enum pm_log_type, int); +#endif + +extern unsigned int pm_status_flag; + +/* + * State enumeration + */ +enum state_t { + S_START = 0, + S_NORMAL, /*< normal state */ + S_LCDDIM, /*< LCD dimming */ + S_LCDOFF, /*< LCD off */ + S_SLEEP, /*< system suspend */ + S_END +}; + +/* + * Global variables + * pm_cur_state : current state + * states : state definitions + * trans_table : state transition table + */ +int pm_cur_state; +int pm_old_state; + +/* + * @brief State structure + */ +struct state { + enum state_t state; /**< state number */ + int (*trans) (int evt); /**< transition function pointer */ + int (*action) (int timeout); /**< enter action */ + int (*check) (int next); /**< transition check function */ + int timeout; +} states[S_END]; + +/* + * @brief Configuration structure + */ +struct display_config { + double lock_wait_time; + double longpress_interval; + double lightsensor_interval; + int lcdoff_timeout; + int brightness_change_step; + int hbm_lux_threshold; + int lcd_always_on; + int framerate_app[4]; + int control_display; + int powerkey_doublepress; + int alpm_on; +}; + +/* + * Global variables + * display_conf : configuration of display + */ +extern struct display_config display_conf; + +/* + * @brief Display Extension features + */ +struct display_function_info { + void (*update_auto_brightness)(bool); + int (*set_autobrightness_min)(int, char *); + int (*reset_autobrightness_min)(char *, enum watch_id); + int (*face_detection)(int, int, int); +}; + +extern struct display_function_info display_info; + +struct display_keyfilter_ops { + void (*init)(void); + void (*exit)(void); + int (*check)(int, char[], int); + void (*set_powerkey_ignore)(int); + int (*powerkey_lcdoff)(void); + void (*backlight_enable)(bool); +}; + +extern const struct display_keyfilter_ops *keyfilter_ops; + +/* If the bit in a condition variable is set, + * we cannot transit the state until clear this bit. */ +int trans_condition; +pid_t idle_pid; +int check_processes(enum state_t prohibit_state); +extern struct state state[S_END]; +int reset_lcd_timeout(char *name, enum watch_id id); +int check_lcdoff_lock_state(void); +/** + * @} + */ + +#endif diff --git a/src/display/device-interface.c b/src/display/device-interface.c new file mode 100644 index 0000000..fe95194 --- /dev/null +++ b/src/display/device-interface.c @@ -0,0 +1,637 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "core/log.h" +#include "util.h" +#include "device-interface.h" +#include "vconf.h" +#include "core.h" +#include "device-node.h" +#include "weaks.h" + +#define TOUCH_ON 1 +#define TOUCH_OFF 0 + +typedef struct _PMSys PMSys; +struct _PMSys { + int def_brt; + int dim_brt; + + int (*sys_power_state) (PMSys *, int); + int (*sys_power_lock) (PMSys *, int); + int (*sys_get_power_lock_support) (PMSys *); + int (*sys_get_lcd_power) (PMSys *); + int (*bl_onoff) (PMSys *, int); + int (*bl_brt) (PMSys *, int); +}; + +static PMSys *pmsys; +struct _backlight_ops backlight_ops; +struct _touch_ops touch_ops; +struct _power_ops power_ops; + +static char *touchscreen_node; +static char *touchkey_node; + +#ifdef ENABLE_X_LCD_ONOFF +#include "x-lcd-on.c" +static bool x_dpms_enable = false; +#endif + +static int power_lock_support = -1; +static bool custom_status = false; +static int custom_brightness = 0; +static int force_brightness = 0; + +static int _bl_onoff(PMSys *p, int on) +{ + int cmd; + + cmd = DISP_CMD(PROP_DISPLAY_ONOFF, DEFAULT_DISPLAY); + return device_set_property(DEVICE_TYPE_DISPLAY, cmd, on); +} + +static int _bl_brt(PMSys *p, int brightness) +{ + int ret = -1; + int cmd; + int prev; + + if (force_brightness > 0 && brightness != p->dim_brt) { + _I("brightness(%d), force brightness(%d)", + brightness, force_brightness); + brightness = force_brightness; + } + + cmd = DISP_CMD(PROP_DISPLAY_BRIGHTNESS, DEFAULT_DISPLAY); + ret = device_get_property(DEVICE_TYPE_DISPLAY, cmd, &prev); + + /* Update new brightness to vconf */ + if (!ret && (brightness != prev)) { + vconf_set_int(VCONFKEY_PM_CURRENT_BRIGHTNESS, brightness); + } + + /* Update device brightness */ + ret = device_set_property(DEVICE_TYPE_DISPLAY, cmd, brightness); + + _I("set brightness %d, %d", brightness, ret); + + return ret; +} + +static int _sys_power_state(PMSys *p, int state) +{ + if (state < POWER_STATE_SUSPEND || state > POWER_STATE_POST_RESUME) + return 0; + return device_set_property(DEVICE_TYPE_POWER, PROP_POWER_STATE, state); +} + +static int _sys_power_lock(PMSys *p, int state) +{ + if (state != POWER_LOCK && state != POWER_UNLOCK) + return -1; + return device_set_property(DEVICE_TYPE_POWER, PROP_POWER_LOCK, state); +} + +static int _sys_get_power_lock_support(PMSys *p) +{ + int value = 0; + int ret = -1; + + ret = device_get_property(DEVICE_TYPE_POWER, PROP_POWER_LOCK_SUPPORT, + &value); + + if (ret < 0) + return -1; + + if (value < 0) + return 0; + + return value; +} + +static int _sys_get_lcd_power(PMSys *p) +{ + int value = -1; + int ret = -1; + int cmd; + + cmd = DISP_CMD(PROP_DISPLAY_ONOFF, DEFAULT_DISPLAY); + ret = device_get_property(DEVICE_TYPE_DISPLAY, cmd, &value); + + if (ret < 0 || value < 0) + return -1; + + return value; +} + +static void _init_bldev(PMSys *p, unsigned int flags) +{ + int ret; + //_update_curbrt(p); + p->bl_brt = _bl_brt; + p->bl_onoff = _bl_onoff; +#ifdef ENABLE_X_LCD_ONOFF + if (flags & FLAG_X_DPMS) { + p->bl_onoff = pm_x_set_lcd_backlight; + x_dpms_enable = true; + } +#endif +} + +static void _init_pmsys(PMSys *p) +{ + char *val; + + val = getenv("PM_SYS_DIMBRT"); + p->dim_brt = (val ? atoi(val) : 0); + p->sys_power_state = _sys_power_state; + p->sys_power_lock = _sys_power_lock; + p->sys_get_power_lock_support = _sys_get_power_lock_support; + p->sys_get_lcd_power = _sys_get_lcd_power; +} + +static void *_system_suspend_cb(void *data) +{ + int ret; + + _I("enter system suspend"); + if (pmsys && pmsys->sys_power_state) + ret = pmsys->sys_power_state(pmsys, POWER_STATE_SUSPEND); + else + ret = -EFAULT; + + if (ret < 0) + _E("Failed to system suspend! %d", ret); + + return (void *)ret; +} + +static int system_suspend(void) +{ + pthread_t pth; + int ret; + + ret = pthread_create(&pth, 0, _system_suspend_cb, (void*)NULL); + if (ret < 0) { + _E("pthread creation failed!, suspend directly!"); + _system_suspend_cb((void*)NULL); + } else { + pthread_join(pth, NULL); + } + + return 0; +} + +static int system_pre_suspend(void) +{ + _I("enter system pre suspend"); + if (pmsys && pmsys->sys_power_state) + return pmsys->sys_power_state(pmsys, POWER_STATE_PRE_SUSPEND); + + return 0; +} + +static int system_post_resume(void) +{ + _I("enter system post resume"); + if (pmsys && pmsys->sys_power_state) + return pmsys->sys_power_state(pmsys, POWER_STATE_POST_RESUME); + + return 0; +} + +static int system_power_lock(void) +{ + _I("system power lock"); + if (pmsys && pmsys->sys_power_lock) + return pmsys->sys_power_lock(pmsys, POWER_LOCK); + + return 0; +} + +static int system_power_unlock(void) +{ + _I("system power unlock"); + if (pmsys && pmsys->sys_power_lock) + return pmsys->sys_power_lock(pmsys, POWER_UNLOCK); + + return 0; +} + +static int system_get_power_lock_support(void) +{ + int value = -1; + + if (power_lock_support == -1) { + if (pmsys && pmsys->sys_get_power_lock_support) { + value = pmsys->sys_get_power_lock_support(pmsys); + if (value == 1) { + _I("system power lock : support"); + power_lock_support = 1; + } else { + _E("system power lock : not support"); + power_lock_support = 0; + } + } else { + _E("system power lock : read fail"); + power_lock_support = 0; + } + } + + return power_lock_support; +} + +static int get_lcd_power(void) +{ + if (pmsys && pmsys->sys_get_lcd_power) { + return pmsys->sys_get_lcd_power(pmsys); + } + + return -1; +} + +static int backlight_hbm_off(void) +{ +#ifdef MICRO_DD + return -EINVAL; +#else + int ret, state; + + ret = device_get_property(DEVICE_TYPE_DISPLAY, + PROP_DISPLAY_HBM_CONTROL, &state); + if (ret < 0) + return ret; + + if (state) { + ret = device_set_property(DEVICE_TYPE_DISPLAY, + PROP_DISPLAY_HBM_CONTROL, 0); + if (ret < 0) + return ret; + _D("hbm is off!"); + } + return 0; +#endif +} + +static int touchscreen_on(void) +{ + int ret; + + if (!touchscreen_node) + return -ENOENT; + + ret = sys_set_int(touchscreen_node, TOUCH_ON); + if (ret < 0) + _E("Failed to on touch screen!"); + + return ret; + +} + +static int touchscreen_off(void) +{ + int ret; + + if (!touchscreen_node) + return -ENOENT; + + if (display_conf.alpm_on == true) + return -EPERM; + + ret = sys_set_int(touchscreen_node, TOUCH_OFF); + if (ret < 0) + _E("Failed to off touch screen!"); + + return ret; +} + +static int touchkey_on(void) +{ + int ret; + + if (!touchkey_node) + return -ENOENT; + + ret = sys_set_int(touchkey_node, TOUCH_ON); + if (ret < 0) + _E("Failed to on touch key!"); + + return ret; + +} + +static int touchkey_off(void) +{ + int ret; + + if (!touchkey_node) + return -ENOENT; + + ret = sys_set_int(touchkey_node, TOUCH_OFF); + if (ret < 0) + _E("Failed to off touch key!"); + + return ret; +} + +static int backlight_on(void) +{ + int ret = -1; + int i; + + _D("LCD on"); + + if (!pmsys || !pmsys->bl_onoff) + return -1; + + for (i = 0; i < PM_LCD_RETRY_CNT; i++) { + ret = pmsys->bl_onoff(pmsys, STATUS_ON); + if (get_lcd_power() == PM_LCD_POWER_ON) { +#ifdef ENABLE_PM_LOG + pm_history_save(PM_LOG_LCD_ON, pm_cur_state); +#endif + break; + } else { +#ifdef ENABLE_PM_LOG + pm_history_save(PM_LOG_LCD_ON_FAIL, pm_cur_state); +#endif +#ifdef ENABLE_X_LCD_ONOFF + _E("Failed to LCD on, through xset"); +#else + _E("Failed to LCD on, through OAL"); +#endif + ret = -1; + } + } + + return ret; +} + +static int backlight_off(void) +{ + int ret = -1; + int i; + + _D("LCD off"); + + if (!pmsys || !pmsys->bl_onoff) + return -1; + + for (i = 0; i < PM_LCD_RETRY_CNT; i++) { +#ifdef ENABLE_X_LCD_ONOFF + if (x_dpms_enable == false) +#endif + usleep(30000); + ret = pmsys->bl_onoff(pmsys, STATUS_OFF); + if (get_lcd_power() == PM_LCD_POWER_OFF) { +#ifdef ENABLE_PM_LOG + pm_history_save(PM_LOG_LCD_OFF, pm_cur_state); +#endif + break; + } else { +#ifdef ENABLE_PM_LOG + pm_history_save(PM_LOG_LCD_OFF_FAIL, pm_cur_state); +#endif +#ifdef ENABLE_X_LCD_ONOFF + _E("Failed to LCD off, through xset"); +#else + _E("Failed to LCD off, through OAL"); +#endif + ret = -1; + } + } + return ret; +} + +static int backlight_dim(void) +{ + int ret = 0; + if (pmsys && pmsys->bl_brt) { + ret = pmsys->bl_brt(pmsys, pmsys->dim_brt); +#ifdef ENABLE_PM_LOG + if (!ret) + pm_history_save(PM_LOG_LCD_DIM, pm_cur_state); + else + pm_history_save(PM_LOG_LCD_DIM_FAIL, pm_cur_state); +#endif + } + return ret; +} + +static int set_custom_status(bool on) +{ + custom_status = on; + return 0; +} + +static bool get_custom_status(void) +{ + return custom_status; +} + +static int save_custom_brightness(void) +{ + int cmd, ret, brightness; + + cmd = DISP_CMD(PROP_DISPLAY_BRIGHTNESS, DEFAULT_DISPLAY); + ret = device_get_property(DEVICE_TYPE_DISPLAY, cmd, &brightness); + + custom_brightness = brightness; + + return ret; +} + +static int custom_backlight_update(void) +{ + int ret = 0; + + if (custom_brightness < PM_MIN_BRIGHTNESS || + custom_brightness > PM_MAX_BRIGHTNESS) + return -EINVAL; + + if ((pm_status_flag & PWRSV_FLAG) && !(pm_status_flag & BRTCH_FLAG)) { + ret = backlight_dim(); + } else if (pmsys && pmsys->bl_brt) { + _I("custom brightness restored! %d", custom_brightness); + ret = pmsys->bl_brt(pmsys, custom_brightness); + } + + return ret; +} + +static int set_force_brightness(int level) +{ + if (level < 0 || level > PM_MAX_BRIGHTNESS) + return -EINVAL; + + force_brightness = level; + + return 0; +} + +static int backlight_update(void) +{ + int ret = 0; + + if (hbm_get_state != NULL && hbm_get_state() == true) { + _I("HBM is on, backlight is not updated!"); + return 0; + } + + if (get_custom_status()) { + _I("custom brightness mode! brt no updated"); + return 0; + } + if ((pm_status_flag & PWRSV_FLAG) && !(pm_status_flag & BRTCH_FLAG)) { + ret = backlight_dim(); + } else if (pmsys && pmsys->bl_brt) { + ret = pmsys->bl_brt(pmsys, pmsys->def_brt); + } + return ret; +} + +static int backlight_standby(void) +{ + int ret = -1; + if (!pmsys || !pmsys->bl_onoff) + return -1; + + if (get_lcd_power() == PM_LCD_POWER_ON) { + _I("LCD standby"); + ret = pmsys->bl_onoff(pmsys, STATUS_STANDBY); + } + + return ret; +} + +static int set_default_brt(int level) +{ + if (!pmsys) + return -EFAULT; + + if (level < PM_MIN_BRIGHTNESS || level > PM_MAX_BRIGHTNESS) + level = PM_DEFAULT_BRIGHTNESS; + pmsys->def_brt = level; + + return 0; +} + + + +static int check_wakeup_src(void) +{ + /* TODO if nedded. + * return wackeup source. user input or device interrupts? (EVENT_DEVICE or EVENT_INPUT) + */ + return EVENT_DEVICE; +} + +void _init_ops(void) +{ + backlight_ops.off = backlight_off; + backlight_ops.dim = backlight_dim; + backlight_ops.on = backlight_on; + backlight_ops.update = backlight_update; + backlight_ops.standby = backlight_standby; + backlight_ops.hbm_off = backlight_hbm_off; + backlight_ops.set_default_brt = set_default_brt; + backlight_ops.get_lcd_power = get_lcd_power; + backlight_ops.set_custom_status = set_custom_status; + backlight_ops.get_custom_status = get_custom_status; + backlight_ops.save_custom_brightness = save_custom_brightness; + backlight_ops.custom_update = custom_backlight_update; + backlight_ops.set_force_brightness = set_force_brightness; + + touch_ops.screen_on = touchscreen_on; + touch_ops.screen_off = touchscreen_off; + touch_ops.key_on = touchkey_on; + touch_ops.key_off = touchkey_off; + + power_ops.suspend = system_suspend; + power_ops.pre_suspend = system_pre_suspend; + power_ops.post_resume = system_post_resume; + power_ops.power_lock = system_power_lock; + power_ops.power_unlock = system_power_unlock; + power_ops.get_power_lock_support = system_get_power_lock_support; + power_ops.check_wakeup_src = check_wakeup_src; +} + +int init_sysfs(unsigned int flags) +{ + int ret; + + pmsys = (PMSys *) malloc(sizeof(PMSys)); + if (pmsys == NULL) { + _E("Not enough memory to alloc PM Sys"); + return -1; + } + + memset(pmsys, 0x0, sizeof(PMSys)); + + _init_pmsys(pmsys); + _init_bldev(pmsys, flags); + + if (pmsys->bl_onoff == NULL || pmsys->sys_power_state == NULL) { + _E("We have no managable resource to reduce the power consumption"); + return -1; + } + + touchscreen_node = getenv("PM_TOUCHSCREEN"); + _D("touchscreen node : %s", touchscreen_node); + + touchkey_node = getenv("PM_TOUCHKEY"); + _D("touchkey node : %s", touchkey_node); + + _init_ops(); + + return 0; +} + +int exit_sysfs(void) +{ + int fd; + + fd = open("/tmp/sem.pixmap_1", O_RDONLY); + if (fd == -1) { + _E("X server disable"); + backlight_on(); + } + + backlight_update(); + touchscreen_on(); + touchkey_on(); + + free(pmsys); + pmsys = NULL; + if(fd != -1) + close(fd); + + return 0; +} diff --git a/src/display/device-interface.h b/src/display/device-interface.h new file mode 100644 index 0000000..f50f1da --- /dev/null +++ b/src/display/device-interface.h @@ -0,0 +1,97 @@ +/* + * deviced + * + * Copyright (c) 2011 - 2013 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. + */ + + +/** + * @file device-interface.h + * @brief backlight, touch, power devices interface module header + */ +#ifndef __DEVICE_INTERFACE_H__ +#define __DEVICE_INTERFACE_H__ + +#include + +#define FLAG_X_DPMS 0x2 + +#define DEFAULT_DISPLAY 0 + +#define PM_MAX_BRIGHTNESS 100 +#define PM_MIN_BRIGHTNESS 1 +#define PM_DEFAULT_BRIGHTNESS 60 + +#define PM_LCD_POWER_ON 0 +#define PM_LCD_POWER_OFF 4 + +#define PM_LCD_RETRY_CNT 3 +#define STATUS_STANDBY (STATUS_ON + 1) + +#define DISP_INDEX_SHIFT 16 +#define DISP_CMD(prop, index) ((index << DISP_INDEX_SHIFT) | prop) + +/* + * Event type enumeration + */ +enum { + EVENT_TIMEOUT = 0, /*< time out event from timer */ + EVENT_DEVICE = EVENT_TIMEOUT, /*< wake up by devices except input devices */ + EVENT_INPUT, /*< input event from noti service */ + EVENT_END, +}; + +extern int init_sysfs(unsigned int); +extern int exit_sysfs(void); + +struct _backlight_ops { + int (*off)(void); + int (*dim)(void); + int (*on)(void); + int (*update)(void); + int (*standby)(void); + int (*hbm_off)(void); + int (*set_default_brt)(int level); + int (*get_lcd_power)(void); + int (*set_custom_status)(bool on); + bool (*get_custom_status)(void); + int (*save_custom_brightness)(void); + int (*custom_update)(void); + int (*set_force_brightness)(int level); +}; + +struct _touch_ops { + int (*screen_on)(void); + int (*screen_off)(void); + int (*key_on)(void); + int (*key_off)(void); +}; + +struct _power_ops { + int (*suspend)(void); + int (*pre_suspend)(void); + int (*post_resume)(void); + int (*power_lock)(void); + int (*power_unlock)(void); + int (*get_power_lock_support)(void); + int (*check_wakeup_src)(void); +}; + +extern struct _backlight_ops backlight_ops; +extern struct _touch_ops touch_ops; +extern struct _power_ops power_ops; + +#endif + diff --git a/src/display/display-dbus.c b/src/display/display-dbus.c new file mode 100644 index 0000000..e533f51 --- /dev/null +++ b/src/display/display-dbus.c @@ -0,0 +1,1274 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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. + */ + + +/** + * @file display-dbus.c + * @brief dbus interface + * + */ + +#include +#include +#include +#include + +#include "core/log.h" +#include "util.h" +#include "core.h" +#include "weaks.h" +#include "core/common.h" +#include "core/devices.h" +#include "dd-display.h" + +#define TELEPHONY_PATH "/org/tizen/telephony/SAMSUNG_QMI" +#define TELEPHONY_INTERFACE_SIM "org.tizen.telephony.Sim" +#define SIGNAL_SIM_STATUS "Status" +#define SIM_CARD_NOT_PRESENT (0x01) + +#define VCONFKEY_LCD_BRIGHTNESS_INIT "db/private/deviced/lcd_brightness_init" + +#define SIGNAL_HOMESCREEN "HomeScreen" +#define SIGNAL_EXTREME "Extreme" +#define SIGNAL_NOTEXTREME "NotExtreme" + +#define BLIND_MASK(val) ((val) & 0xFFFF) +#define BLIND_RED(val) BLIND_MASK((val) >> 32) +#define BLIND_GREEN(val) BLIND_MASK((val) >> 16) +#define BLIND_BLUE(val) BLIND_MASK((val)) + +#define DISPLAY_DIM_BRIGHTNESS 0 +#define DUMP_MODE_WATING_TIME 600000 + +static DBusMessage *edbus_start(E_DBus_Object *obj, DBusMessage *msg) +{ + static const struct device_ops *display_device_ops; + + if (!display_device_ops) { + display_device_ops = find_device("display"); + if (!display_device_ops) + return dbus_message_new_method_return(msg); + } + + display_device_ops->start(); + return dbus_message_new_method_return(msg); +} + +static DBusMessage *edbus_stop(E_DBus_Object *obj, DBusMessage *msg) +{ + static const struct device_ops *display_device_ops; + + if (!display_device_ops) { + display_device_ops = find_device("display"); + if (!display_device_ops) + return dbus_message_new_method_return(msg); + } + + display_device_ops->stop(); + return dbus_message_new_method_return(msg); +} + +static DBusMessage *edbus_lockstate(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusError err; + DBusMessageIter iter; + DBusMessage *reply; + char *state_str; + char *option1_str; + char *option2_str; + int timeout; + pid_t pid; + int state; + int flag; + int ret; + + dbus_error_init(&err); + + if (!dbus_message_get_args(msg, &err, + DBUS_TYPE_STRING, &state_str, + DBUS_TYPE_STRING, &option1_str, + DBUS_TYPE_STRING, &option2_str, + DBUS_TYPE_INT32, &timeout, DBUS_TYPE_INVALID)) { + _E("there is no message"); + ret = -EINVAL; + goto out; + } + + if (!state_str || timeout < 0) { + _E("message is invalid!"); + ret = -EINVAL; + goto out; + } + + pid = get_edbus_sender_pid(msg); + if (kill(pid, 0) == -1) { + _E("%d process does not exist, dbus ignored!", pid); + ret = -ESRCH; + goto out; + } + + if (!strcmp(state_str, PM_LCDON_STR)) + state = LCD_NORMAL; + else if (!strcmp(state_str, PM_LCDDIM_STR)) + state = LCD_DIM; + else if (!strcmp(state_str, PM_LCDOFF_STR)) + state = LCD_OFF; + else { + _E("%s state is invalid, dbus ignored!", state_str); + ret = -EINVAL; + goto out; + } + + if (!strcmp(option1_str, STAYCURSTATE_STR)) + flag = STAY_CUR_STATE; + else if (!strcmp(option1_str, GOTOSTATENOW_STR)) + flag = GOTO_STATE_NOW; + else { + _E("%s option is invalid. set default option!", option1_str); + flag = STAY_CUR_STATE; + } + + if (!strcmp(option2_str, HOLDKEYBLOCK_STR)) + flag |= HOLD_KEY_BLOCK; + else if (!strcmp(option2_str, STANDBYMODE_STR)) + flag |= STANDBY_MODE; + + if (check_dimstay(state, flag) == true) { + _E("LCD state can not be changed to OFF state now!"); + flag &= ~GOTO_STATE_NOW; + flag |= STAY_CUR_STATE; + } + + ret = pm_lock_internal(pid, state, flag, timeout); +out: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + + return reply; +} + +static DBusMessage *edbus_unlockstate(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusError err; + DBusMessageIter iter; + DBusMessage *reply; + char *state_str; + char *option_str; + pid_t pid; + int state; + int flag; + int ret; + + dbus_error_init(&err); + + if (!dbus_message_get_args(msg, &err, + DBUS_TYPE_STRING, &state_str, + DBUS_TYPE_STRING, &option_str, DBUS_TYPE_INVALID)) { + _E("there is no message"); + ret = -EINVAL; + goto out; + } + + if (!state_str) { + _E("message is invalid!"); + ret = -EINVAL; + goto out; + } + + pid = get_edbus_sender_pid(msg); + if (kill(pid, 0) == -1) { + _E("%d process does not exist, dbus ignored!", pid); + ret = -ESRCH; + goto out; + } + + if (!strcmp(state_str, PM_LCDON_STR)) + state = LCD_NORMAL; + else if (!strcmp(state_str, PM_LCDDIM_STR)) + state = LCD_DIM; + else if (!strcmp(state_str, PM_LCDOFF_STR)) + state = LCD_OFF; + else { + _E("%s state is invalid, dbus ignored!", state_str); + ret = -EINVAL; + goto out; + } + + if (!strcmp(option_str, SLEEP_MARGIN_STR)) + flag = PM_SLEEP_MARGIN; + else if (!strcmp(option_str, RESET_TIMER_STR)) + flag = PM_RESET_TIMER; + else if (!strcmp(option_str, KEEP_TIMER_STR)) + flag = PM_KEEP_TIMER; + else { + _E("%s option is invalid. set default option!", option_str); + flag = PM_RESET_TIMER; + } + + ret = pm_unlock_internal(pid, state, flag); +out: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + + return reply; +} + +static DBusMessage *edbus_changestate(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusError err; + DBusMessageIter iter; + DBusMessage *reply; + char *state_str; + pid_t pid; + int state; + int ret; + + dbus_error_init(&err); + + if (!dbus_message_get_args(msg, &err, + DBUS_TYPE_STRING, &state_str, DBUS_TYPE_INVALID)) { + _E("there is no message"); + ret = -EINVAL; + goto out; + } + + if (!state_str) { + _E("message is invalid!"); + ret = -EINVAL; + goto out; + } + + pid = get_edbus_sender_pid(msg); + if (kill(pid, 0) == -1) { + _E("%d process does not exist, dbus ignored!", pid); + ret = -ESRCH; + goto out; + } + + if (!strcmp(state_str, PM_LCDON_STR)) + state = LCD_NORMAL; + else if (!strcmp(state_str, PM_LCDDIM_STR)) + state = LCD_DIM; + else if (!strcmp(state_str, PM_LCDOFF_STR)) + state = LCD_OFF; + else if (!strcmp(state_str, PM_SUSPEND_STR)) + state = SUSPEND; + else { + _E("%s state is invalid, dbus ignored!", state_str); + ret = -EINVAL; + goto out; + } + + if (check_dimstay(state, GOTO_STATE_NOW) == true) { + _E("LCD state can not be changed to OFF state!"); + ret = -EBUSY; + goto out; + } + + ret = pm_change_internal(pid, state); + + if (!ret && state == LCD_OFF) + update_lcdoff_source(VCONFKEY_PM_LCDOFF_BY_TIMEOUT); +out: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + + return reply; +} + +static DBusMessage *edbus_getdisplaycount(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int cmd, cnt, ret; + + cmd = DISP_CMD(PROP_DISPLAY_DISPLAY_COUNT, DEFAULT_DISPLAY); + ret = device_get_property(DEVICE_TYPE_DISPLAY, cmd, &cnt); + if (ret >= 0) + ret = cnt; + + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *edbus_getmaxbrightness(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int cmd, brt, ret; + + cmd = DISP_CMD(PROP_DISPLAY_MAX_BRIGHTNESS, DEFAULT_DISPLAY); + ret = device_get_property(DEVICE_TYPE_DISPLAY, cmd, &brt); + if (ret >= 0) + ret = brt; + + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *edbus_setmaxbrightness(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int cmd, brt, ret; + + dbus_message_iter_init(msg, &iter); + dbus_message_iter_get_basic(&iter, &brt); + + cmd = DISP_CMD(PROP_DISPLAY_MAX_BRIGHTNESS, DEFAULT_DISPLAY); + ret = device_set_property(DEVICE_TYPE_DISPLAY, cmd, brt); + + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *edbus_getbrightness(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int cmd, brt, ret; + + cmd = DISP_CMD(PROP_DISPLAY_BRIGHTNESS, DEFAULT_DISPLAY); + ret = device_get_property(DEVICE_TYPE_DISPLAY, cmd, &brt); + if (ret >= 0) + ret = brt; + + _I("get brightness %d, %d", brt, ret); + + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &brt); + return reply; +} + +static DBusMessage *edbus_setbrightness(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int cmd, brt, powersaver, autobrt, ret; + + dbus_message_iter_init(msg, &iter); + dbus_message_iter_get_basic(&iter, &brt); + + if (brt == DISPLAY_DIM_BRIGHTNESS) { + _E("application can not set this value(DIM VALUE:%d)", brt); + ret = -EPERM; + goto error; + } + + if (vconf_get_int(VCONFKEY_SETAPPL_PSMODE, &powersaver) != 0) { + _E("Failed to get VCONFKEY_SETAPPL_PSMODE value"); + powersaver = SETTING_PSMODE_NORMAL; + } + + if (powersaver == SETTING_PSMODE_WEARABLE) { + _D("brightness is changed in powersaver mode!"); + backlight_ops.set_force_brightness(0); + } + + if (vconf_get_int(VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT, &autobrt) != 0) { + _E("Failed to get VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT value"); + autobrt = SETTING_BRIGHTNESS_AUTOMATIC_OFF; + } + + if (autobrt == SETTING_BRIGHTNESS_AUTOMATIC_ON) { + _D("auto_brightness state is ON, can not change the brightness value"); + ret = 0; + goto error; + } + + cmd = DISP_CMD(PROP_DISPLAY_BRIGHTNESS, DEFAULT_DISPLAY); + ret = device_set_property(DEVICE_TYPE_DISPLAY, cmd, brt); + if (ret < 0) + goto error; + if (vconf_set_int(VCONFKEY_SETAPPL_LCD_BRIGHTNESS, brt) != 0) + _E("Failed to set VCONFKEY_SETAPPL_LCD_BRIGHTNESS value"); + + if (vconf_set_int(VCONFKEY_PM_CURRENT_BRIGHTNESS, brt) != 0) + _E("Failed to set VCONFKEY_PM_CURRENT_BRIGHTNESS value"); + + _I("set brightness %d, %d", brt, ret); + +error: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *edbus_holdbrightness(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int cmd, brt, powersaver, autobrt, ret; + + dbus_message_iter_init(msg, &iter); + dbus_message_iter_get_basic(&iter, &brt); + + if (brt == DISPLAY_DIM_BRIGHTNESS) { + _E("application can not set this value(DIM VALUE:%d)", brt); + ret = -EPERM; + goto error; + } + + if (vconf_get_int(VCONFKEY_SETAPPL_PSMODE, &powersaver) != 0) { + _E("Failed to get VCONFKEY_SETAPPL_PSMODE value"); + powersaver = SETTING_PSMODE_NORMAL; + } + + if (powersaver == SETTING_PSMODE_WEARABLE) { + _D("Powersaver mode! brightness can not be changed!"); + ret = -EPERM; + goto error; + } + + if (vconf_get_int(VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT, &autobrt) != 0) { + _E("Failed to get VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT value"); + autobrt = SETTING_BRIGHTNESS_AUTOMATIC_OFF; + } + + vconf_set_int(VCONFKEY_PM_CUSTOM_BRIGHTNESS_STATUS, VCONFKEY_PM_CUSTOM_BRIGHTNESS_ON); + + cmd = DISP_CMD(PROP_DISPLAY_BRIGHTNESS, DEFAULT_DISPLAY); + ret = device_set_property(DEVICE_TYPE_DISPLAY, cmd, brt); + if (ret < 0) + goto error; + + if (autobrt == SETTING_BRIGHTNESS_AUTOMATIC_ON) { + _D("Auto brightness will be paused"); + vconf_set_int(VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT, SETTING_BRIGHTNESS_AUTOMATIC_PAUSE); + } + + if (vconf_set_int(VCONFKEY_PM_CURRENT_BRIGHTNESS, brt) != 0) + _E("Failed to set VCONFKEY_PM_CURRENT_BRIGHTNESS value"); + + _I("hold brightness %d, %d", brt, ret); + +error: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; + +} + +static DBusMessage *edbus_releasebrightness(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int cmd, bat, charger, changed, setting, brt, autobrt, ret = 0; + + if (vconf_get_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, &bat) != 0) { + _E("Failed to get VCONFKEY_SYSMAN_BATTERY_STATUS_LOW value"); + ret = -EPERM; + goto error; + } + + if (vconf_get_int(VCONFKEY_SYSMAN_CHARGER_STATUS, &charger) != 0) { + _E("Failed to get VCONFKEY_SYSMAN_CHARGER_STATUS value"); + ret = -EPERM; + goto error; + } + + if (vconf_get_bool(VCONFKEY_PM_BRIGHTNESS_CHANGED_IN_LPM, &changed) != 0) { + _E("Failed to get VCONFKEY_PM_BRIGHTNESS_CHANGED_IN_LPM value"); + ret = -EPERM; + goto error; + } + + if (vconf_get_int(VCONFKEY_SETAPPL_LCD_BRIGHTNESS, &setting) != 0) { + _E("Failed to get VCONFKEY_SETAPPL_LCD_BRIGHTNESS value"); + ret = -EPERM; + goto error; + } + + if (vconf_get_int(VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT, &autobrt) != 0) { + _E("Failed to get VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT value"); + ret = -EPERM; + goto error; + } + + vconf_set_int(VCONFKEY_PM_CUSTOM_BRIGHTNESS_STATUS, VCONFKEY_PM_CUSTOM_BRIGHTNESS_OFF); + + cmd = DISP_CMD(PROP_DISPLAY_BRIGHTNESS, DEFAULT_DISPLAY); + ret = device_get_property(DEVICE_TYPE_DISPLAY, cmd, &brt); + if (ret < 0) + brt = ret; + + // check dim state + if (low_battery_state(bat) && + charger == VCONFKEY_SYSMAN_CHARGER_DISCONNECTED && !changed) { + _D("batt warning low : brightness is not changed!"); + if (brt != 0) { + device_set_property(DEVICE_TYPE_DISPLAY, PROP_DISPLAY_BRIGHTNESS, 0); + } + goto error; + } + + if (autobrt == SETTING_BRIGHTNESS_AUTOMATIC_OFF) { + if (brt != setting) { + device_set_property(DEVICE_TYPE_DISPLAY, PROP_DISPLAY_BRIGHTNESS, setting); + if (vconf_set_int(VCONFKEY_PM_CURRENT_BRIGHTNESS, setting) != 0) { + _E("Failed to set VCONFKEY_PM_CURRENT_BRIGHTNESS value"); + } + } + } else if (autobrt == SETTING_BRIGHTNESS_AUTOMATIC_PAUSE) { + _D("Auto brightness will be enable"); + vconf_set_int(VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT, SETTING_BRIGHTNESS_AUTOMATIC_ON); + } + +error: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *edbus_getaclstatus(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int cmd, st, ret; + + cmd = DISP_CMD(PROP_DISPLAY_ACL_CONTROL, DEFAULT_DISPLAY); + ret = device_get_property(DEVICE_TYPE_DISPLAY, cmd, &st); + if (ret >= 0) + ret = st; + + _I("get acl status %d, %d", st, ret); + + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *edbus_setaclstatus(E_DBus_Object *ob, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int cmd, st, ret; + + dbus_message_iter_init(msg, &iter); + dbus_message_iter_get_basic(&iter, &st); + + cmd = DISP_CMD(PROP_DISPLAY_ACL_CONTROL, DEFAULT_DISPLAY); + ret = device_set_property(DEVICE_TYPE_DISPLAY, cmd, st); + + _I("set acl status %d, %d", st, ret); + + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *edbus_getautotone(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int cmd, tone, ret; + + cmd = DISP_CMD(PROP_DISPLAY_AUTO_SCREEN_TONE, DEFAULT_DISPLAY); + ret = device_get_property(DEVICE_TYPE_DISPLAY, cmd, &tone); + if (ret >= 0) + ret = tone; + + _I("get auto screen tone %d, %d", tone, ret); + + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *edbus_setautotone(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int cmd, tone, ret; + + dbus_message_iter_init(msg, &iter); + dbus_message_iter_get_basic(&iter, &tone); + + cmd = DISP_CMD(PROP_DISPLAY_AUTO_SCREEN_TONE, DEFAULT_DISPLAY); + ret = device_set_property(DEVICE_TYPE_DISPLAY, cmd, tone); + + _I("set auto screen tone %d, %d", tone, ret); + + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *edbus_setautotoneforce(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int cmd, tone, ret; + + dbus_message_iter_init(msg, &iter); + dbus_message_iter_get_basic(&iter, &tone); + + cmd = DISP_CMD(PROP_DISPLAY_AUTO_SCREEN_TONE_FORCE, DEFAULT_DISPLAY); + ret = device_set_property(DEVICE_TYPE_DISPLAY, cmd, tone); + + _I("set auto screen tone force %d, %d", tone, ret); + + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *edbus_setrefreshrate(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int app, val, cmd, ret, control; + + ret = dbus_message_get_args(msg, NULL, + DBUS_TYPE_INT32, &app, + DBUS_TYPE_INT32, &val, DBUS_TYPE_INVALID); + if (!ret) { + _I("there is no message"); + ret = -EINVAL; + goto error; + } + + if (app < 0 || app >= ARRAY_SIZE(display_conf.framerate_app) || val < 0) { + ret = -EINVAL; + goto error; + } + + if (!display_conf.framerate_app[app]) { + _I("This case(%d) is not support in this target", app); + ret = -EPERM; + goto error; + } + + control = display_conf.control_display; + + if (control) + backlight_ops.off(); + + _D("app : %d, value : %d", app, val); + cmd = DISP_CMD(PROP_DISPLAY_FRAME_RATE, DEFAULT_DISPLAY); + ret = device_set_property(DEVICE_TYPE_DISPLAY, cmd, val); + + if (control) + backlight_ops.on(); + +error: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *edbus_getcolorblind(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int cmd, val, ret; + + cmd = DISP_CMD(PROP_DISPLAY_IMAGE_ENHANCE_COLOR_BLIND, DEFAULT_DISPLAY); + ret = device_get_property(DEVICE_TYPE_DISPLAY, cmd, &val); + if (ret >= 0) + ret = val; + + _I("get color blind %d", val); + + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *edbus_setcolorblind(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int cmd, val, ret; + unsigned int power; + uint64_t red, grn, blu; + struct color_blind_info info; + + ret = dbus_message_get_args(msg, NULL, DBUS_TYPE_UINT32, &power, + DBUS_TYPE_UINT64, &red, DBUS_TYPE_UINT64, &grn, + DBUS_TYPE_UINT64, &blu, DBUS_TYPE_INVALID); + if (!ret) { + _I("there is no message"); + ret = -EINVAL; + goto error; + } + + info.power = power; + info.RrCr = BLIND_RED(red); + info.RgCg = BLIND_GREEN(red); + info.RbCb = BLIND_BLUE(red); + info.GrMr = BLIND_RED(grn); + info.GgMg = BLIND_GREEN(grn); + info.GbMb = BLIND_BLUE(grn); + info.BrYr = BLIND_RED(blu); + info.BgYg = BLIND_GREEN(blu); + info.BbYb = BLIND_BLUE(blu); + + cmd = DISP_CMD(PROP_DISPLAY_IMAGE_ENHANCE_COLOR_BLIND, DEFAULT_DISPLAY); + ret = device_set_property(DEVICE_TYPE_DISPLAY, cmd, (int)&info); + + _I("set color blind %d, %hu, %hu, %hu, %hu, %hu, %hu, %hu, %hu, %hu, %d", + info.power, info.RrCr, info.RgCg, info.RbCb, info.GrMr, info.GgMg, + info.GbMb, info.BrYr, info.BgYg, info.BbYb, ret); + +error: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *edbus_gethbm(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int hbm; + + if (!msg) { + _E("msg is empty!"); + return NULL; + } + + /* check weak function symbol */ + if (!hbm_get_state) { + hbm = -ENOSYS; + goto error; + } + + hbm = hbm_get_state(); + + if (hbm < 0) + _E("failed to get high brightness mode %d", hbm); + else + _D("get high brightness mode %d", hbm); +error: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &hbm); + return reply; +} + +static DBusMessage *edbus_sethbm(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int hbm, ret; + + if (!msg) { + _E("msg is empty!"); + return NULL; + } + + if (!dbus_message_get_args(msg, NULL, + DBUS_TYPE_INT32, &hbm, + DBUS_TYPE_INVALID)) { + _E("there is no message"); + ret = -EINVAL; + goto error; + } + + /* check weak function symbol */ + if (!hbm_set_state) { + ret = -ENOSYS; + goto error; + } + + ret = hbm_set_state(hbm); + + if (ret < 0) + _E("failed to set high brightness mode (%d,%d)", ret, hbm); + else + _I("set high brightness mode (%d,%d)", ret, hbm); +error: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *edbus_sethbm_timeout(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int hbm, timeout, ret; + + if (!msg) { + _E("msg is empty!"); + return NULL; + } + + if (!dbus_message_get_args(msg, NULL, + DBUS_TYPE_INT32, &hbm, + DBUS_TYPE_INT32, &timeout, DBUS_TYPE_INVALID)) { + _E("there is no message"); + ret = -EINVAL; + goto error; + } + + /* check weak function symbol */ + if (!hbm_set_state_with_timeout) { + ret = -ENOSYS; + goto error; + } + + ret = hbm_set_state_with_timeout(hbm, timeout); + + if (ret < 0) + _E("failed to set high brightness mode (%d,%d,%d)", + ret, hbm, timeout); + else + _I("set high brightness mode (%d,%d,%d)", + ret, hbm, timeout); +error: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *edbus_setautobrightnessmin(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int val, ret; + pid_t pid; + const char *sender; + + sender = dbus_message_get_sender(msg); + if (!sender) { + _E("invalid sender name!"); + ret = -EINVAL; + goto error; + } + if (!display_info.set_autobrightness_min) { + ret = -EIO; + goto error; + } + dbus_message_iter_init(msg, &iter); + dbus_message_iter_get_basic(&iter, &val); + + pid = get_edbus_sender_pid(msg); + ret = display_info.set_autobrightness_min(val, (char *)sender); + if (ret) { + _W("fail to set autobrightness min %d, %d by %d", val, ret, pid); + goto error; + } + if (display_info.reset_autobrightness_min) { + register_edbus_watch(msg, WATCH_DISPLAY_AUTOBRIGHTNESS_MIN, + display_info.reset_autobrightness_min); + _I("set autobrightness min %d by %d", val, pid); + } +error: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + + return reply; +} + +static DBusMessage *edbus_setlcdtimeout(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int on, dim, holdkey_block, ret; + pid_t pid; + const char *sender; + + sender = dbus_message_get_sender(msg); + if (!sender) { + _E("invalid sender name!"); + ret = -EINVAL; + goto error; + } + + ret = dbus_message_get_args(msg, NULL, DBUS_TYPE_INT32, &on, + DBUS_TYPE_INT32, &dim, DBUS_TYPE_INT32, &holdkey_block, + DBUS_TYPE_INVALID); + + pid = get_edbus_sender_pid(msg); + ret = set_lcd_timeout(on, dim, holdkey_block, sender); + if (ret) { + _W("fail to set lcd timeout %d by %d", ret, pid); + } else { + register_edbus_watch(msg, WATCH_DISPLAY_LCD_TIMEOUT, + reset_lcd_timeout); + _I("set lcd timeout on %d, dim %d, holdblock %d by %d", + on, dim, holdkey_block, pid); + } +error: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + + return reply; +} + +static DBusMessage *edbus_lockscreenbgon(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int ret = 0; + char *on; + + ret = dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &on, + DBUS_TYPE_INVALID); + + if (!ret) { + _E("fail to update lcdscreen bg on state %d", ret); + ret = -EINVAL; + goto error; + } + + if (!strcmp(on, "true")) + update_pm_setting(SETTING_LOCK_SCREEN_BG, true); + else if (!strcmp(on, "false")) + update_pm_setting(SETTING_LOCK_SCREEN_BG, false); + else + ret = -EINVAL; + +error: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + + return reply; +} + +static DBusMessage *edbus_dumpmode(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int ret = 0; + char *on; + + ret = dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &on, + DBUS_TYPE_INVALID); + + if (!ret) { + _E("fail to get dumpmode state %d", ret); + ret = -EINVAL; + goto error; + } + + if (!strcmp(on, "on")) + pm_lock_internal(INTERNAL_LOCK_DUMPMODE, LCD_OFF, + STAY_CUR_STATE, DUMP_MODE_WATING_TIME); + else if (!strcmp(on, "off")) + pm_unlock_internal(INTERNAL_LOCK_DUMPMODE, LCD_OFF, + PM_SLEEP_MARGIN); + else + ret = -EINVAL; + +error: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + + return reply; +} + +static DBusMessage *edbus_savelog(E_DBus_Object *obj, DBusMessage *msg) +{ + save_display_log(); + return dbus_message_new_method_return(msg); +} + +static DBusMessage *edbus_powerkeyignore(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int ret = 0; + int on; + + ret = dbus_message_get_args(msg, NULL, DBUS_TYPE_INT32, &on, + DBUS_TYPE_INVALID); + + if (!ret) { + _E("fail to get powerkey ignore %d", ret); + ret = -EINVAL; + goto error; + } + + if (CHECK_OPS(keyfilter_ops, set_powerkey_ignore)) + keyfilter_ops->set_powerkey_ignore(on == 1 ? true : false); +error: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + + return reply; +} + +static DBusMessage *edbus_powerkeylcdoff(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int ret; + + if (CHECK_OPS(keyfilter_ops, powerkey_lcdoff)) + ret = keyfilter_ops->powerkey_lcdoff(); + else + ret = -ENOSYS; + + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + + return reply; +} + +static DBusMessage *edbus_customlcdon(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int ret = 0; + int timeout; + + ret = dbus_message_get_args(msg, NULL, DBUS_TYPE_INT32, &timeout, + DBUS_TYPE_INVALID); + + if (!ret) { + _E("fail to get custom lcd timeout %d", ret); + ret = -EINVAL; + goto error; + } + + ret = custom_lcdon(timeout); + +error: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + + return reply; +} + +static const struct edbus_method edbus_methods[] = { + { "start", NULL, NULL, edbus_start }, + { "stop", NULL, NULL, edbus_stop }, + { "lockstate", "sssi", "i", edbus_lockstate }, + { "unlockstate", "ss", "i", edbus_unlockstate }, + { "changestate", "s", "i", edbus_changestate }, + { "getbrightness", NULL, "i", edbus_getbrightness }, /* deprecated */ + { "setbrightness", "i", "i", edbus_setbrightness }, /* deprecated */ + { "getautotone", NULL, "i", edbus_getautotone }, /* deprecated */ + { "setautotone", "i", "i", edbus_setautotone }, /* deprecated */ + { "setframerate", "ii", "i", edbus_setrefreshrate }, /* deprecated */ + { "getcolorblind", NULL, "i", edbus_getcolorblind }, /* deprecated */ + { "setcolorblind", "uttt", "i", edbus_setcolorblind }, /* deprecated */ + { "setautobrightnessmin", "i", "i", edbus_setautobrightnessmin }, + { "setlcdtimeout", "iii", "i", edbus_setlcdtimeout }, + { "LockScreenBgOn", "s", "i", edbus_lockscreenbgon }, + { "GetDisplayCount", NULL, "i", edbus_getdisplaycount }, + { "GetMaxBrightness",NULL, "i", edbus_getmaxbrightness }, + { "SetMaxBrightness", "i", "i", edbus_setmaxbrightness }, + { "GetBrightness", NULL, "i", edbus_getbrightness }, + { "SetBrightness", "i", "i", edbus_setbrightness }, + { "HoldBrightness", "i", "i", edbus_holdbrightness }, + { "ReleaseBrightness", NULL, "i", edbus_releasebrightness }, + { "GetAclStatus", NULL, "i", edbus_getaclstatus }, + { "SetAclStatus", NULL, "i", edbus_setaclstatus }, + { "GetAutoTone", NULL, "i", edbus_getautotone }, + { "SetAutoTone", "i", "i", edbus_setautotone }, + { "SetAutoToneForce", "i", "i", edbus_setautotoneforce }, + { "SetRefreshRate", "ii", "i", edbus_setrefreshrate }, + { "GetColorBlind", NULL, "i", edbus_getcolorblind }, + { "SetColorBlind", "uttt", "i", edbus_setcolorblind }, + { "GetHBM", NULL, "i", edbus_gethbm }, + { "SetHBM", "i", "i", edbus_sethbm }, + { "SetHBMTimeout" ,"ii", "i", edbus_sethbm_timeout }, + { "Dumpmode", "s", "i", edbus_dumpmode }, + { "SaveLog", NULL, NULL, edbus_savelog }, + { "PowerKeyIgnore", "i", NULL, edbus_powerkeyignore }, + { "PowerKeyLCDOff", NULL, "i", edbus_powerkeylcdoff }, + { "CustomLCDOn", "i", "i", edbus_customlcdon }, + /* Add methods here */ +}; + +static void sim_signal_handler(void *data, DBusMessage *msg) +{ + DBusError err; + int ret, val; + static int state = false; + + if (state) + return; + + ret = dbus_message_is_signal(msg, TELEPHONY_INTERFACE_SIM, + SIGNAL_SIM_STATUS); + if (!ret) { + _E("there is no power off popup signal"); + return; + } + + ret = vconf_get_bool(VCONFKEY_LCD_BRIGHTNESS_INIT, &state); + if (ret < 0 || state) + return; + + dbus_error_init(&err); + + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &val, + DBUS_TYPE_INVALID); + if (!ret) { + _E("no message : [%s:%s]", err.name, err.message); + dbus_error_free(&err); + } + + if (val != SIM_CARD_NOT_PRESENT) { + /* change setting : autobrightness on */ + state = true; + vconf_set_bool(VCONFKEY_LCD_BRIGHTNESS_INIT, state); + vconf_set_int(VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT, + SETTING_BRIGHTNESS_AUTOMATIC_ON); + vconf_set_int(VCONFKEY_SETAPPL_LCD_BRIGHTNESS, + PM_DEFAULT_BRIGHTNESS); + _I("SIM card is inserted at first!"); + } +} + +static void homescreen_signal_handler(void *data, DBusMessage *msg) +{ + DBusError err; + int ret; + char *screen; + + + ret = dbus_message_is_signal(msg, DEVICED_INTERFACE_NAME, + SIGNAL_HOMESCREEN); + if (!ret) { + _E("there is no homescreen signal"); + return; + } + + dbus_error_init(&err); + + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &screen, + DBUS_TYPE_INVALID); + if (!ret) { + _E("no message : [%s:%s]", err.name, err.message); + dbus_error_free(&err); + } + + _D("screen : %s", screen); + + if (set_alpm_screen) + set_alpm_screen(screen); + else + _E("alpm screen mode is not supported!"); +} + +static void extreme_signal_handler(void *data, DBusMessage *msg) +{ + int ret; + + ret = dbus_message_is_signal(msg, POPUP_INTERFACE_LOWBAT, + SIGNAL_EXTREME); + if (!ret) { + _E("there is no extreme signal"); + return; + } + + pm_status_flag &= ~BRTCH_FLAG; + if (hbm_get_state != NULL && hbm_get_state() == true) + hbm_set_state_with_timeout(false, 0); + backlight_ops.update(); + _D("extreme mode : enter dim state!"); + if (vconf_set_int(VCONFKEY_PM_KEY_IGNORE, TRUE) != 0) + _E("failed to set vconf status"); +} + +static void not_extreme_signal_handler(void *data, DBusMessage *msg) +{ + int ret; + + ret = dbus_message_is_signal(msg, POPUP_INTERFACE_LOWBAT, + SIGNAL_NOTEXTREME); + if (!ret) { + _E("there is no extreme signal"); + return; + } + + _D("release extreme mode"); + if (vconf_set_int(VCONFKEY_PM_KEY_IGNORE, FALSE) != 0) + _E("failed to set vconf status"); +} + +int init_pm_dbus(void) +{ + int ret; + + ret = register_edbus_method(DEVICED_PATH_DISPLAY, + edbus_methods, ARRAY_SIZE(edbus_methods)); + if (ret < 0) { + _E("Failed to register edbus method! %d", ret); + return ret; + } + + ret = register_edbus_signal_handler(TELEPHONY_PATH, + TELEPHONY_INTERFACE_SIM, SIGNAL_SIM_STATUS, + sim_signal_handler); + if (ret < 0 && ret != -EEXIST) { + _E("Failed to register signal handler! %d", ret); + return ret; + } + + ret = register_edbus_signal_handler(DEVICED_OBJECT_PATH, + DEVICED_INTERFACE_NAME, SIGNAL_HOMESCREEN, + homescreen_signal_handler); + if (ret < 0 && ret != -EEXIST) { + _E("Failed to register signal handler! %d", ret); + return ret; + } + + ret = register_edbus_signal_handler(POPUP_PATH_LOWBAT, + POPUP_INTERFACE_LOWBAT, SIGNAL_EXTREME, + extreme_signal_handler); + if (ret < 0 && ret != -EEXIST) { + _E("Failed to register signal handler! %d", ret); + return ret; + } + ret = register_edbus_signal_handler(POPUP_PATH_LOWBAT, + POPUP_INTERFACE_LOWBAT, SIGNAL_NOTEXTREME, + not_extreme_signal_handler); + if (ret < 0 && ret != -EEXIST) { + _E("Failed to register signal handler! %d", ret); + return ret; + } + return 0; +} + diff --git a/src/display/display-emul.conf b/src/display/display-emul.conf new file mode 100644 index 0000000..707b817 --- /dev/null +++ b/src/display/display-emul.conf @@ -0,0 +1,37 @@ +[Display] +# deviced is pending lcd on until lock screen shows. +# This is the maximum pending time. +LockScreenWaitingTime=0.3 #second + +# Power-off popup is launched when power key is long pressed. +# This is duration of pressing power key. +LongPressInterval=2 #second + +# This is polling time of auto brightness. +LightSensorSamplingInterval=1 #second + +# display state is changed to SLEEP state after this time. +# If this value is large, it causes power consumption problem. +LCDOffTimeout=500 # milli second + +# This is n step of auto brightness. +# If brightness is change from a to b, brightness's changed n times from a to b. +BrightnessChangeStep=10 + +# This is threshold value of light sensor. +# If lux value is greater than threshold, +# HBM(High Brightness Mode) is on. +HBMLuxThreshold=39768 + +# If this value is yes, LCD is always on except pressing power key. +# Default value is no, LCD is turned off by lcd timeout. +LCDAlwaysOn=yes # yes or no + +# Just below application only allow to change display frame rate. +# refer to enum refresh_app +ChangedFrameRateAllowed=all # all +ControlDisplay=no # yes or no + +# LCD is not turned off when this value is yes and key double pressed +PowerKeyDoublePressSupport=yes # yes or no + diff --git a/src/display/display-exynos.conf b/src/display/display-exynos.conf new file mode 100644 index 0000000..8924ae9 --- /dev/null +++ b/src/display/display-exynos.conf @@ -0,0 +1,40 @@ +[Display] +# deviced is pending lcd on until lock screen shows. +# This is the maximum pending time. +LockScreenWaitingTime=0.3 #second + +# Power-off popup is launched when power key is long pressed. +# This is duration of pressing power key. +LongPressInterval=2 #second + +# This is polling time of auto brightness. +LightSensorSamplingInterval=1 #second + +# display state is changed to SLEEP state after this time. +# If this value is large, it causes power consumption problem. +LCDOffTimeout=500 # milli second + +# This is n step of auto brightness. +# If brightness is change from a to b, brightness's changed n times from a to b. +BrightnessChangeStep=10 + +# This is threshold value of light sensor. +# If lux value is greater than threshold, +# HBM(High Brightness Mode) is on. +HBMLuxThreshold=39768 + +# If this value is yes, LCD is always on except pressing power key. +# Default value is no, LCD is turned off by lcd timeout. +LCDAlwaysOn=no # yes or no + +# Just below application only allow to change display frame rate. +# refer to enum refresh_app +ChangedFrameRateAllowed=all # all +ControlDisplay=no # yes or no + +# LCD is not turned off when this value is yes and key double pressed +PowerKeyDoublePressSupport=yes # yes or no + +# ALPM(AMOLED Low Power Mode) +UseALPM=no # yes or no + diff --git a/src/display/display-msm.conf b/src/display/display-msm.conf new file mode 100644 index 0000000..f9d065f --- /dev/null +++ b/src/display/display-msm.conf @@ -0,0 +1,37 @@ +[Display] +# deviced is pending lcd on until lock screen shows. +# This is the maximum pending time. +LockScreenWaitingTime=0.3 #second + +# Power-off popup is launched when power key is long pressed. +# This is duration of pressing power key. +LongPressInterval=2 #second + +# This is polling time of auto brightness. +LightSensorSamplingInterval=1 #second + +# display state is changed to SLEEP state after this time. +# If this value is large, it causes power consumption problem. +LCDOffTimeout=500 # milli second + +# This is n step of auto brightness. +# If brightness is change from a to b, brightness's changed n times from a to b. +BrightnessChangeStep=10 + +# This is threshold value of light sensor. +# If lux value is greater than threshold, +# HBM(High Brightness Mode) is on. +HBMLuxThreshold=39768 + +# If this value is yes, LCD is always on except pressing power key. +# Default value is no, LCD is turned off by lcd timeout. +LCDAlwaysOn=no # yes or no + +# Just below application only allow to change display frame rate. +# refer to enum refresh_app +ChangedFrameRateAllowed=setting # setting +ControlDisplay=yes # yes or no + +# LCD is not turned off when this value is yes and key double pressed +PowerKeyDoublePressSupport=no # yes or no + diff --git a/src/display/display-ops.c b/src/display/display-ops.c new file mode 100644 index 0000000..172b707 --- /dev/null +++ b/src/display/display-ops.c @@ -0,0 +1,74 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 "util.h" +#include "display-ops.h" +#include "core/list.h" +#include "core/common.h" + +static dd_list *disp_head; + +void add_display(const struct display_ops *disp) +{ + DD_LIST_APPEND(disp_head, disp); +} + +void remove_display(const struct display_ops *disp) +{ + DD_LIST_REMOVE(disp_head, disp); +} + +const struct display_ops *find_display(const char *name) +{ + dd_list *elem; + const struct display_ops *disp; + + DD_LIST_FOREACH(disp_head, elem, disp) { + if (!strcmp(disp->name, name)) + return disp; + } + return NULL; +} + +void display_ops_init(void *data) +{ + dd_list *elem; + const struct display_ops *disp; + + DD_LIST_FOREACH(disp_head, elem, disp) { + _D("[%s] initialize", disp->name); + if (disp->init) + disp->init(data); + } +} + +void display_ops_exit(void *data) +{ + dd_list *elem; + const struct display_ops *disp; + + DD_LIST_FOREACH(disp_head, elem, disp) { + _D("[%s] deinitialize", disp->name); + if (disp->exit) + disp->exit(data); + } +} + diff --git a/src/display/display-ops.h b/src/display/display-ops.h new file mode 100644 index 0000000..c11e188 --- /dev/null +++ b/src/display/display-ops.h @@ -0,0 +1,49 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 __DISPLAY_OPS_H__ +#define __DISPLAY_OPS_H__ + +#include +#include "core/common.h" + +struct display_ops { + char *name; + void (*init) (void *data); + void (*exit) (void *data); +}; + +void display_ops_init(void *data); +void display_ops_exit(void *data); + +#define DISPLAY_OPS_REGISTER(disp) \ +static void __CONSTRUCTOR__ module_init(void) \ +{ \ + add_display(disp); \ +} \ +static void __DESTRUCTOR__ module_exit(void) \ +{ \ + remove_display(disp); \ +} + +void add_display(const struct display_ops *disp); +void remove_display(const struct display_ops *disp); +const struct display_ops *find_display(const char *name); + +#endif diff --git a/src/display/enhance.c b/src/display/enhance.c new file mode 100644 index 0000000..fb7a2e7 --- /dev/null +++ b/src/display/enhance.c @@ -0,0 +1,676 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "core.h" +#include "core/data.h" +#include "core/devices.h" +#include "core/queue.h" +#include "core/log.h" +#include "core/common.h" +#include "proc/proc-handler.h" +#include "device-interface.h" + +#define VCONFKEY_ENHANCE_MODE "db/private/sysman/enhance_mode" +#define VCONFKEY_ENHANCE_SCENARIO "db/private/sysman/enhance_scenario" +#define VCONFKEY_ENHANCE_TONE "db/private/sysman/enhance_tone" +#define VCONFKEY_ENHANCE_OUTDOOR "db/private/sysman/enhance_outdoor" +#define VCONFKEY_ENHANCE_PID "memory/private/sysman/enhance_pid" + +#ifndef VCONFKEY_SETAPPL_LCD_AUTO_DISPLAY_ADJUSTMENT +#define VCONFKEY_SETAPPL_LCD_AUTO_DISPLAY_ADJUSTMENT "db/setting/auto_display_adjustment" +#endif + +#define SETTING_NAME "setting" +#define CLUSTER_HOME "cluster-home" +#define BROWSER_NAME "browser" + +enum lcd_enhance_type{ + ENHANCE_MODE = 0, + ENHANCE_SCENARIO, + ENHANCE_TONE, + ENHANCE_OUTDOOR, + ENHANCE_MAX, +}; + +struct enhance_entry_t{ + int pid; + int type[ENHANCE_MAX]; +}; + +static Eina_List *enhance_ctl_list; +static struct enhance_entry_t default_enhance; + +int get_glove_state(void) +{ + int ret, val; + + ret = device_get_property(DEVICE_TYPE_TOUCH, PROP_TOUCH_SCREEN_GLOVE_MODE, &val); + if (ret < 0) { + return ret; + } + return val; +} + +void switch_glove_key(int val) +{ + int ret, exval; + + ret = device_get_property(DEVICE_TYPE_TOUCH, PROP_TOUCH_KEY_GLOVE_MODE, &exval); + if (ret < 0 || exval != val) { + ret = device_set_property(DEVICE_TYPE_TOUCH, PROP_TOUCH_KEY_GLOVE_MODE, val); + if (ret < 0) + _E("fail to set touch key glove mode"); + else + _D("glove key mode is %s", (val ? "on" : "off")); + } +} + +static int check_default_process(int pid, char *default_name) +{ + char exe_name[PATH_MAX]; + if (get_cmdline_name(pid, exe_name, PATH_MAX) != 0) { + _E("fail to check cmdline: %d (%s)", pid, default_name); + return -EINVAL; + } + if (strncmp(exe_name, default_name, strlen(default_name)) != 0) { + return -EINVAL; + } + return 0; +} + +static void restore_enhance_status(struct enhance_entry_t *entry) +{ + int ret; + int scenario; + static int pid; + + if (pid == entry->pid) + return; + + pid = entry->pid; + + ret = device_get_property(DEVICE_TYPE_DISPLAY, + PROP_DISPLAY_IMAGE_ENHANCE_SCENARIO, &scenario); + if (ret != 0) { + _E("fail to get status"); + return; + } + if (entry->type[ENHANCE_SCENARIO] == scenario) + goto restore_enhance; + + _D("clear tone and outdoor"); + device_set_property(DEVICE_TYPE_DISPLAY, + PROP_DISPLAY_IMAGE_ENHANCE_TONE, 0); + device_set_property(DEVICE_TYPE_DISPLAY, + PROP_DISPLAY_IMAGE_ENHANCE_OUTDOOR, 0); + +restore_enhance: + _D("restore [%d:%d:%d:%d]", + entry->type[ENHANCE_MODE], entry->type[ENHANCE_SCENARIO], + entry->type[ENHANCE_TONE], entry->type[ENHANCE_OUTDOOR]); + + device_set_property(DEVICE_TYPE_DISPLAY, + PROP_DISPLAY_IMAGE_ENHANCE_MODE, + entry->type[ENHANCE_MODE]); + device_set_property(DEVICE_TYPE_DISPLAY, + PROP_DISPLAY_IMAGE_ENHANCE_SCENARIO, + entry->type[ENHANCE_SCENARIO]); + device_set_property(DEVICE_TYPE_DISPLAY, + PROP_DISPLAY_IMAGE_ENHANCE_TONE, + entry->type[ENHANCE_TONE]); + device_set_property(DEVICE_TYPE_DISPLAY, + PROP_DISPLAY_IMAGE_ENHANCE_OUTDOOR, + entry->type[ENHANCE_OUTDOOR]); +} + +static int find_entry_from_enhance_ctl_list(int pid) +{ + Eina_List *n; + Eina_List *next; + struct enhance_entry_t* entry; + char exe_name[PATH_MAX]; + + EINA_LIST_FOREACH_SAFE(enhance_ctl_list, n, next, entry) { + if (entry != NULL && entry->pid == pid && get_cmdline_name(entry->pid, exe_name, PATH_MAX) == 0) { + _D("find enhance list"); + restore_enhance_status(entry); + return 1; + } + } + return 0; +} + +static void remove_entry_from_enhance_ctl_list(int pid) +{ + Eina_List *n; + Eina_List *next; + struct enhance_entry_t *entry; + char exe_name[PATH_MAX]; + + if (pid <= 0) + return; + + EINA_LIST_FOREACH_SAFE(enhance_ctl_list, n, next, entry) { + if (entry != NULL && + (get_cmdline_name(entry->pid, exe_name, PATH_MAX) != 0 || (entry->pid == pid))) { + _D("remove enhance list"); + enhance_ctl_list = eina_list_remove(enhance_ctl_list, entry); + free(entry); + } + } +} + +static int check_entry_to_enhance_ctl_list(int pid) +{ + int oom_score_adj; + if (pid <= 0) + return -EINVAL; + + if (get_oom_score_adj(pid, &oom_score_adj) < 0) { + _E("fail to get adj value of pid: %d (%d)", pid); + return -EINVAL; + } + + switch (oom_score_adj) { + case OOMADJ_FOREGRD_LOCKED: + case OOMADJ_FOREGRD_UNLOCKED: + if (!find_entry_from_enhance_ctl_list(pid)) + return -EINVAL; + return 0; + case OOMADJ_BACKGRD_LOCKED: + case OOMADJ_BACKGRD_UNLOCKED: + remove_entry_from_enhance_ctl_list(pid); + return -EINVAL; + case OOMADJ_SU: + if (check_default_process(pid, CLUSTER_HOME) != 0) + return 0; + return -EINVAL; + default: + return 0; + } +} + +static void update_enhance_status(struct enhance_entry_t *entry, int index) +{ + char exe_name[PATH_MAX]; + int type; + + if (index == ENHANCE_MODE) + type = PROP_DISPLAY_IMAGE_ENHANCE_MODE; + else if (index == ENHANCE_SCENARIO) + type = PROP_DISPLAY_IMAGE_ENHANCE_SCENARIO; + else if (index == ENHANCE_TONE) + type = PROP_DISPLAY_IMAGE_ENHANCE_TONE; + else if (index == ENHANCE_OUTDOOR) + type = PROP_DISPLAY_IMAGE_ENHANCE_OUTDOOR; + else { + _E("abnormal type is inserted(%d)", index); + return; + } + + _I("[ENHANCE(%d)] %d", index, entry->type[index]); + device_set_property(DEVICE_TYPE_DISPLAY, type, entry->type[index]); +} + +static int change_default_enhance_status(int pid, int index, int val) +{ + Eina_List *n, *next; + struct enhance_entry_t *entry; + char exe_name[PATH_MAX]; + + if (check_default_process(pid, SETTING_NAME) != 0) + return -EINVAL; + default_enhance.pid = pid; + default_enhance.type[index] = val; + switch (index) { + case ENHANCE_MODE: + vconf_set_int(VCONFKEY_ENHANCE_MODE, val); + EINA_LIST_FOREACH_SAFE(enhance_ctl_list, n, next, entry) { + if (!entry) + continue; + entry->type[index] = default_enhance.type[index]; + } + break; + case ENHANCE_SCENARIO: + vconf_set_int(VCONFKEY_ENHANCE_SCENARIO, val); + break; + case ENHANCE_TONE: + vconf_set_int(VCONFKEY_ENHANCE_TONE, val); + break; + case ENHANCE_OUTDOOR: + vconf_set_int(VCONFKEY_ENHANCE_OUTDOOR, val); + break; + default: + _E("input index is abnormal value"); + return -EINVAL; + } + update_enhance_status(&default_enhance, index); + return 0; +} + +static int add_entry_to_enhance_ctl_list(int pid, int index, int val) +{ + int find_node = 0; + Eina_List *n, *next; + struct enhance_entry_t *entry; + struct enhance_entry_t *entry_buf; + int oom_score_adj; + + if (pid <= 0) + return -EINVAL; + + EINA_LIST_FOREACH_SAFE(enhance_ctl_list, n, next, entry) { + if (entry != NULL && entry->pid == pid) { + find_node = 1; + break; + } + } + + entry_buf = malloc(sizeof(struct enhance_entry_t)); + if (!entry_buf) { + _E("Malloc failed"); + return -EINVAL; + } + + if (find_node) { + memcpy(entry_buf, entry, sizeof(struct enhance_entry_t)); + entry_buf->type[index] = val; + remove_entry_from_enhance_ctl_list(pid); + } else { + memset(entry_buf, 0, sizeof(struct enhance_entry_t)); + entry_buf->type[ENHANCE_MODE] = default_enhance.type[ENHANCE_MODE]; + entry_buf->pid = pid; + entry_buf->type[index] = val; + } + + enhance_ctl_list = eina_list_prepend(enhance_ctl_list, entry_buf); + if (!enhance_ctl_list) { + _E("eina_list_prepend failed"); + return -EINVAL; + } + + if (get_oom_score_adj(entry_buf->pid, &oom_score_adj) < 0) { + _E("fail to get adj value of pid: %d (%d)", pid); + return -EINVAL; + } + return 0; +} + +static void enhance_control_pid_cb(keynode_t *in_key, struct main_data *ad) +{ + int pid; + + if (vconf_get_int(VCONFKEY_ENHANCE_PID, &pid) != 0) + return; + + if (check_entry_to_enhance_ctl_list(pid) == 0) + return; + + restore_enhance_status(&default_enhance); +} + +static void enhance_auto_control_cb(keynode_t *in_key, struct main_data *ad) +{ + int val; + + if (vconf_get_bool(VCONFKEY_SETAPPL_LCD_AUTO_DISPLAY_ADJUSTMENT, &val) != 0) { + _E("fail to get %s", VCONFKEY_SETAPPL_LCD_AUTO_DISPLAY_ADJUSTMENT); + return; + } + + _I("set auto adjust screen tone (%d)", val); + device_set_property(DEVICE_TYPE_DISPLAY, PROP_DISPLAY_AUTO_SCREEN_TONE, val); + device_set_property(DEVICE_TYPE_DISPLAY, + PROP_DISPLAY_IMAGE_ENHANCE_MODE, + default_enhance.type[ENHANCE_MODE]); +} + +static void init_colorblind_status(void) +{ + struct color_blind_info info; + char *str, *it; + int val, cnt, cmd, ret, sum; + unsigned int color[9]; + + /* get the status if colorblind is ON or not */ + if (vconf_get_bool(VCONFKEY_SETAPPL_COLORBLIND_STATUS_BOOL, &val) != 0) + return; + + if (!val) { + _D("color blind status is FALSE"); + return; + } + + /* get the value of color blind */ + str = vconf_get_str(VCONFKEY_SETAPPL_COLORBLIND_LAST_RGBCMY_STR); + if (!str) + return; + + cnt = strlen(str)/4 - 1; + if (cnt != 8) + return; + + /* token the color blind value string to integer */ + sum = 0; + for (it = str+cnt*4; cnt >= 0 && it; --cnt, it -= 4) { + color[cnt] = strtol(it, NULL, 16); + sum += color[cnt]; + *it = '\0'; + _D("color[%d] : %d", cnt, color[cnt]); + } + + /* ignore colorblind when all of value is invalid */ + if (!sum) + return; + + cnt = 0; + info.power = val; + info.RrCr = color[cnt++]; + info.RgCg = color[cnt++]; + info.RbCb = color[cnt++]; + info.GrMr = color[cnt++]; + info.GgMg = color[cnt++]; + info.GbMb = color[cnt++]; + info.BrYr = color[cnt++]; + info.BgYg = color[cnt++]; + info.BbYb = color[cnt++]; + + /* write to the kernel node */ + cmd = DISP_CMD(PROP_DISPLAY_IMAGE_ENHANCE_COLOR_BLIND, DEFAULT_DISPLAY); + ret = device_set_property(DEVICE_TYPE_DISPLAY, cmd, (int)&info); + if (ret < 0) + _E("fail to set color blind value : %d", ret); +} + +static void reset_default_enhance_status(struct enhance_entry_t *entry) +{ + _D("reset [%d:%d:%d:%d]", + entry->type[ENHANCE_MODE], entry->type[ENHANCE_SCENARIO], + entry->type[ENHANCE_TONE], entry->type[ENHANCE_OUTDOOR]); + + device_set_property(DEVICE_TYPE_DISPLAY, + PROP_DISPLAY_IMAGE_ENHANCE_MODE, + entry->type[ENHANCE_MODE]); + device_set_property(DEVICE_TYPE_DISPLAY, + PROP_DISPLAY_IMAGE_ENHANCE_SCENARIO, + entry->type[ENHANCE_SCENARIO]); + device_set_property(DEVICE_TYPE_DISPLAY, + PROP_DISPLAY_IMAGE_ENHANCE_TONE, + entry->type[ENHANCE_TONE]); + device_set_property(DEVICE_TYPE_DISPLAY, + PROP_DISPLAY_IMAGE_ENHANCE_OUTDOOR, + entry->type[ENHANCE_OUTDOOR]); +} + +static void init_default_enhance_status(void) +{ + int val; + + memset(&default_enhance, 0, sizeof(struct enhance_entry_t)); + + if (vconf_get_bool(VCONFKEY_SETAPPL_LCD_AUTO_DISPLAY_ADJUSTMENT, &val) == 0) { + _I("set auto adjust screen tone (%d)", val); + device_set_property(DEVICE_TYPE_DISPLAY, PROP_DISPLAY_AUTO_SCREEN_TONE, val); + } + + if (vconf_notify_key_changed(VCONFKEY_SETAPPL_LCD_AUTO_DISPLAY_ADJUSTMENT, + (void *)enhance_auto_control_cb, NULL) < 0) { + _E("failed to set : KEY(%s)", VCONFKEY_SETAPPL_LCD_AUTO_DISPLAY_ADJUSTMENT); + } + + if (vconf_get_int(VCONFKEY_ENHANCE_MODE, &val) == 0 && val >= 0) { + default_enhance.type[ENHANCE_MODE] = val; + } + if (vconf_get_int(VCONFKEY_ENHANCE_SCENARIO, &val) == 0 && val >= 0) { + default_enhance.type[ENHANCE_SCENARIO] = val; + } + if (vconf_get_int(VCONFKEY_ENHANCE_TONE, &val) == 0 && val >= 0) { + default_enhance.type[ENHANCE_TONE] = val; + } + if (vconf_get_int(VCONFKEY_ENHANCE_OUTDOOR, &val) == 0 && val >= 0) { + default_enhance.type[ENHANCE_OUTDOOR] = val; + } + reset_default_enhance_status(&default_enhance); +} + +int changed_enhance_value(int pid, int prop, int val) +{ + int index; + + index = prop - PROP_DISPLAY_IMAGE_ENHANCE_MODE; + + if (change_default_enhance_status(pid, index, val) == 0) + return 0; + if (add_entry_to_enhance_ctl_list(pid, index, val) == 0) + return 0; + + _E("fail to set enhance (p:%d,t:%d,v:%d)", pid, index, val); + return -EINVAL; +} + +int set_enhance_pid(int pid) +{ + return vconf_set_int(VCONFKEY_ENHANCE_PID, pid); +} + +static DBusMessage *edbus_getenhancesupported(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int cmd, val, ret; + + cmd = DISP_CMD(PROP_DISPLAY_IMAGE_ENHANCE_INFO, DEFAULT_DISPLAY); + ret = device_get_property(DEVICE_TYPE_DISPLAY, cmd, &val); + if (ret >= 0) + ret = val; + + _I("get imange enhance supported %d, %d", val, ret); + + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *edbus_getimageenhance(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int type, prop, cmd, val, ret; + + dbus_message_iter_init(msg, &iter); + dbus_message_iter_get_basic(&iter, &type); + + _I("get image enhance type %d", type); + + switch (type) { + case ENHANCE_MODE: + prop = PROP_DISPLAY_IMAGE_ENHANCE_MODE; + break; + case ENHANCE_SCENARIO: + prop = PROP_DISPLAY_IMAGE_ENHANCE_SCENARIO; + break; + case ENHANCE_TONE: + prop = PROP_DISPLAY_IMAGE_ENHANCE_TONE; + break; + case ENHANCE_OUTDOOR: + prop = PROP_DISPLAY_IMAGE_ENHANCE_OUTDOOR; + break; + default: + ret = -EINVAL; + goto error; + } + + cmd = DISP_CMD(prop, DEFAULT_DISPLAY); + ret = device_get_property(DEVICE_TYPE_DISPLAY, cmd, &val); + if (ret >= 0) + ret = val; + +error: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *edbus_setimageenhance(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int type, prop, cmd, val, ret; + pid_t pid; + + ret = dbus_message_get_args(msg, NULL, DBUS_TYPE_INT32, &type, DBUS_TYPE_INT32, &val, DBUS_TYPE_INVALID); + if (!ret) { + _I("there is no message"); + ret = -EINVAL; + goto error; + } + + _I("set image enhance type %d, %d", type, val); + + switch (type) { + case ENHANCE_MODE: + prop = PROP_DISPLAY_IMAGE_ENHANCE_MODE; + break; + case ENHANCE_SCENARIO: + prop = PROP_DISPLAY_IMAGE_ENHANCE_SCENARIO; + break; + case ENHANCE_TONE: + prop = PROP_DISPLAY_IMAGE_ENHANCE_TONE; + break; + case ENHANCE_OUTDOOR: + prop = PROP_DISPLAY_IMAGE_ENHANCE_OUTDOOR; + break; + default: + ret = -EINVAL; + goto error; + } + + cmd = DISP_CMD(prop, DEFAULT_DISPLAY); + ret = device_set_property(DEVICE_TYPE_DISPLAY, cmd, val); + + /* notify to deviced with the purpose of stroing latest enhance value */ + pid = get_edbus_sender_pid(msg); + changed_enhance_value(pid, prop, val); + +error: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *edbus_getenhancedtouch(E_DBus_Object *obj, DBusMessage *msg) +{ + int ret; + int val; + DBusMessageIter iter; + DBusMessage *reply; + + ret = device_get_property(DEVICE_TYPE_TOUCH, PROP_TOUCH_SCREEN_GLOVE_MODE, &val); + if (ret < 0) { + val = -1; + } + + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &val); + return reply; +} + +static DBusMessage *edbus_setenhancedtouch(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int val, exval, ret; + + ret = dbus_message_get_args(msg, NULL, + DBUS_TYPE_INT32, &val, DBUS_TYPE_INVALID); + if (!ret) { + _I("there is no message"); + ret = -EINVAL; + goto error; + } + + if (!val) + ret = device_set_property(DEVICE_TYPE_TOUCH, PROP_TOUCH_KEY_GLOVE_MODE, val); + if (ret < 0) + _E("fail to off touch key glove mode"); + + ret = device_get_property(DEVICE_TYPE_TOUCH, PROP_TOUCH_SCREEN_GLOVE_MODE, &exval); + if (ret < 0 || exval != val) + ret = device_set_property(DEVICE_TYPE_TOUCH, PROP_TOUCH_SCREEN_GLOVE_MODE, val); + if (ret < 0) { + _E("fail to set touch screen glove mode (%d)", val); + goto error; + } + +error: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static const struct edbus_method edbus_methods[] = { + { "getimageenhance", "i", "i", edbus_getimageenhance }, /* deprecated */ + { "setimageenhance", "ii", "i", edbus_setimageenhance }, /* deprecated */ + { "GetEnhanceSupported", NULL, "i", edbus_getenhancesupported }, + { "GetImageEnhance", "i", "i", edbus_getimageenhance }, + { "SetImageEnhance", "ii", "i", edbus_setimageenhance }, + { "GetEnhancedTouch", NULL, "i", edbus_getenhancedtouch }, + { "SetEnhancedTouch", "i", "i", edbus_setenhancedtouch }, +}; + +static void enhance_init(void *data) +{ + int ret; + + ret = register_edbus_method(DEVICED_PATH_DISPLAY, + edbus_methods, ARRAY_SIZE(edbus_methods)); + if (ret < 0) + _E("Failed to register edbus method! %d", ret); + + if (vconf_notify_key_changed(VCONFKEY_ENHANCE_PID, + (void *)enhance_control_pid_cb, NULL) < 0) { + _E("failed to set : KEY(%s)", VCONFKEY_ENHANCE_PID); + } + + init_default_enhance_status(); + init_colorblind_status(); +} + +static const struct device_ops enhance_device_ops = { + .priority = DEVICE_PRIORITY_NORMAL, + .name = "enhance", + .init = enhance_init, +}; + +DEVICE_OPS_REGISTER(&enhance_device_ops) diff --git a/src/display/enhance.h b/src/display/enhance.h new file mode 100644 index 0000000..a274cc9 --- /dev/null +++ b/src/display/enhance.h @@ -0,0 +1,31 @@ +/* + * deviced + * + * Copyright (c) 2000 - 2013 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. + */ + + +#ifndef __LCD_HANDLER_H__ +#define __LCD_HANDLER_H__ + +int changed_enhance_value(int pid, int prop, int val); + +#ifdef MICRO_DD +static inline int set_enhance_pid(int pid) {return 0;} +#else +int set_enhance_pid(int pid); +#endif + +#endif /* __LCD_HANDLER_H__ */ diff --git a/src/display/hbm.c b/src/display/hbm.c new file mode 100644 index 0000000..2251acc --- /dev/null +++ b/src/display/hbm.c @@ -0,0 +1,261 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 "util.h" +#include "core.h" +#include "display-ops.h" +#include "core/common.h" +#include "core/device-notifier.h" +#include "core/edbus-handler.h" + +#define ON "on" +#define OFF "off" + +#define SIGNAL_HBM_OFF "HBMOff" + +#define DEFAULT_BRIGHTNESS_LEVEL 80 + +static Ecore_Timer *timer = NULL; +static struct timespec offtime; +static char *hbm_path; + +static void broadcast_hbm_off(void) +{ + broadcast_edbus_signal(DEVICED_PATH_DISPLAY, DEVICED_INTERFACE_DISPLAY, + SIGNAL_HBM_OFF, NULL, NULL); +} + +static void hbm_set_offtime(int timeout) +{ + struct timespec now; + + if (timeout <= 0) { + offtime.tv_sec = 0; + return; + } + + clock_gettime(CLOCK_REALTIME, &now); + offtime.tv_sec = now.tv_sec + timeout; +} + +static Eina_Bool hbm_off_cb(void *data) +{ + int ret; + + timer = NULL; + + if (pm_cur_state != S_NORMAL) { + _D("hbm timeout! but it's not lcd normal"); + return EINA_FALSE; + } + hbm_set_offtime(0); + + ret = sys_set_str(hbm_path, OFF); + if (ret < 0) + _E("Failed to off hbm"); + + vconf_set_int(VCONFKEY_SETAPPL_LCD_BRIGHTNESS, + DEFAULT_BRIGHTNESS_LEVEL); + backlight_ops.set_default_brt(DEFAULT_BRIGHTNESS_LEVEL); + backlight_ops.update(); + broadcast_hbm_off(); + + return EINA_FALSE; +} + +static void hbm_start_timer(int timeout) +{ + if (timer) { + ecore_timer_del(timer); + timer = NULL; + } + if (!timer) { + timer = ecore_timer_add(timeout, + hbm_off_cb, NULL); + } +} + +static void hbm_end_timer(void) +{ + if (timer) { + ecore_timer_del(timer); + timer = NULL; + } +} + +int hbm_get_state(void) +{ + char state[4]; + int ret, hbm; + + if (!hbm_path) + return -ENODEV; + + ret = sys_get_str(hbm_path, state); + if (ret < 0) + return ret; + + if (!strncmp(state, ON, strlen(ON))) + hbm = true; + else if (!strncmp(state, OFF, strlen(OFF))) + hbm = false; + else + hbm = -EINVAL; + + return hbm; +} + +int hbm_set_state(int hbm) +{ + if (!hbm_path) + return -ENODEV; + + return sys_set_str(hbm_path, (hbm ? ON : OFF)); +} + +int hbm_set_state_with_timeout(int hbm, int timeout) +{ + int ret; + + if (hbm && (timeout <= 0)) + return -EINVAL; + + ret = hbm_set_state(hbm); + if (ret < 0) + return ret; + + _D("timeout is %d", timeout); + + if (hbm) { + /* + * hbm is turned off after timeout. + */ + hbm_set_offtime(timeout); + hbm_start_timer(timeout); + } else { + hbm_set_offtime(0); + hbm_end_timer(); + broadcast_hbm_off(); + } + + return 0; +} + +void hbm_check_timeout(void) +{ + struct timespec now; + int ret; + + if (timer) { + ecore_timer_del(timer); + timer = NULL; + } + + if (offtime.tv_sec == 0) { + if (hbm_get_state() == true) { + _E("It's invalid state. hbm is off"); + hbm_set_state(false); + } + return; + } + + clock_gettime(CLOCK_REALTIME, &now); + _D("now %d, offtime %d", now.tv_sec, offtime.tv_sec); + + /* check it's timeout */ + if (now.tv_sec >= offtime.tv_sec) { + hbm_set_offtime(0); + + ret = sys_set_str(hbm_path, OFF); + if (ret < 0) + _E("Failed to off hbm"); + vconf_set_int(VCONFKEY_SETAPPL_LCD_BRIGHTNESS, + DEFAULT_BRIGHTNESS_LEVEL); + backlight_ops.set_default_brt(DEFAULT_BRIGHTNESS_LEVEL); + backlight_ops.update(); + broadcast_hbm_off(); + } else { + _D("hbm state is restored!"); + hbm_set_state(true); + hbm_start_timer(offtime.tv_sec - now.tv_sec); + } +} + +static int lcd_state_changed(void *data) +{ + int state = (int)data; + int ret; + + switch (state) { + case S_NORMAL: + /* restore hbm when old state is dim */ + if (pm_old_state == S_LCDDIM) + hbm_check_timeout(); + break; + case S_LCDDIM: + if (hbm_get_state() == true) { + ret = hbm_set_state(false); + if (ret < 0) + _E("Failed to off hbm!"); + } + /* fall through */ + case S_LCDOFF: + case S_SLEEP: + hbm_end_timer(); + break; + } + + return 0; +} + +static void hbm_init(void *data) +{ + int fd, ret; + + hbm_path = getenv("HBM_NODE"); + + /* Check HBM node is valid */ + fd = open(hbm_path, O_RDONLY); + if (fd < 0) { + hbm_path = NULL; + return; + } + close(fd); + + /* register notifier */ + register_notifier(DEVICE_NOTIFIER_LCD, lcd_state_changed); +} + +static void hbm_exit(void *data) +{ + /* unregister notifier */ + unregister_notifier(DEVICE_NOTIFIER_LCD, lcd_state_changed); +} + +static const struct display_ops display_hbm_ops = { + .name = "hbm", + .init = hbm_init, + .exit = hbm_exit, +}; + +DISPLAY_OPS_REGISTER(&display_hbm_ops) + diff --git a/src/display/key-filter-micro.c b/src/display/key-filter-micro.c new file mode 100644 index 0000000..731e9e6 --- /dev/null +++ b/src/display/key-filter-micro.c @@ -0,0 +1,285 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include +#include +#include +#include + +#include +#include + +#include "util.h" +#include "core.h" +#include "poll.h" +#include "brightness.h" +#include "device-node.h" +#include "core/queue.h" +#include "core/common.h" +#include "core/data.h" +#include "core/device-notifier.h" +#include "core/edbus-handler.h" +#include "core/device-handler.h" + +#include + +#define POWEROFF_ACT "poweroff" + +#define KEY_RELEASED 0 +#define KEY_PRESSED 1 + +#define NORMAL_POWER(val) (val == 0) +#define KEY_TEST_MODE_POWER(val) (val == 2) + +#define SIGNAL_LCDON_BY_POWERKEY "LCDOnByPowerkey" + +static Ecore_Timer *longkey_timeout_id; +static bool ignore_powerkey = false; + +static inline int current_state_in_on(void) +{ + return (pm_cur_state == S_LCDDIM || pm_cur_state == S_NORMAL); +} + +static void longkey_pressed() +{ + int val, ret; + + _I("Power key long pressed!"); + + ret = vconf_get_int(VCONFKEY_TESTMODE_POWER_OFF_POPUP, &val); + if (ret < 0) + return; + + if (NORMAL_POWER(val) || KEY_TEST_MODE_POWER(val)) + return; + + /* + * Poweroff-popup has been launched by app. + * deviced only turns off the phone by power key + * when power-off popup is disabled for testmode. + */ + _I("power off action!"); + notify_action(POWEROFF_ACT, 0); +} + +static Eina_Bool longkey_pressed_cb(void *data) +{ + longkey_pressed(); + longkey_timeout_id = NULL; + + return EINA_FALSE; +} + +static inline void check_key_pair(int code, int new, int *old) +{ + if (new == *old) + _E("key pair is not matched! (%d, %d)", code, new); + else + *old = new; +} + +static inline void broadcast_lcdon_by_powerkey(void) +{ + broadcast_edbus_signal(DEVICED_PATH_DISPLAY, DEVICED_INTERFACE_DISPLAY, + SIGNAL_LCDON_BY_POWERKEY, NULL, NULL); +} + +static inline bool switch_on_lcd(void) +{ + if (current_state_in_on()) + return false; + + if (backlight_ops.get_lcd_power() == PM_LCD_POWER_ON) + return false; + + broadcast_lcdon_by_powerkey(); + + lcd_on_direct(); + + return true; +} + +static inline void switch_off_lcd(void) +{ + if (!current_state_in_on()) + return; + + if (backlight_ops.get_lcd_power() == PM_LCD_POWER_OFF) + return; + + lcd_off_procedure(); +} + +static int process_power_key(struct input_event *pinput) +{ + int ignore = true; + static int value = KEY_RELEASED; + + switch (pinput->value) { + case KEY_RELEASED: + check_key_pair(pinput->code, pinput->value, &value); + ignore = false; + + if (longkey_timeout_id > 0) { + ecore_timer_del(longkey_timeout_id); + longkey_timeout_id = NULL; + } + break; + case KEY_PRESSED: + switch_on_lcd(); + check_key_pair(pinput->code, pinput->value, &value); + _I("power key pressed"); + + /* add long key timer */ + longkey_timeout_id = ecore_timer_add( + display_conf.longpress_interval, + longkey_pressed_cb, NULL); + ignore = false; + break; + } + return ignore; +} + +static int check_key(struct input_event *pinput, int fd) +{ + int ignore = true; + + switch (pinput->code) { + case KEY_POWER: + ignore = process_power_key(pinput); + break; + case KEY_PHONE: /* Flick up key */ + case KEY_BACK: /* Flick down key */ + case KEY_VOLUMEUP: + case KEY_VOLUMEDOWN: + case KEY_CAMERA: + case KEY_EXIT: + case KEY_CONFIG: + case KEY_MEDIA: + case KEY_MUTE: + case KEY_PLAYPAUSE: + case KEY_PLAYCD: + case KEY_PAUSECD: + case KEY_STOPCD: + case KEY_NEXTSONG: + case KEY_PREVIOUSSONG: + case KEY_REWIND: + case KEY_FASTFORWARD: + /* These case do not turn on the lcd */ + if (current_state_in_on()) + ignore = false; + break; + default: + ignore = false; + } +#ifdef ENABLE_PM_LOG + if (pinput->value == KEY_PRESSED) + pm_history_save(PM_LOG_KEY_PRESS, pinput->code); + else if (pinput->value == KEY_RELEASED) + pm_history_save(PM_LOG_KEY_RELEASE, pinput->code); +#endif + return ignore; +} + +static int check_key_filter(int length, char buf[], int fd) +{ + struct input_event *pinput; + int ignore = true; + int idx = 0; + static int old_fd, code, value; + + do { + pinput = (struct input_event *)&buf[idx]; + switch (pinput->type) { + case EV_KEY: + if (pinput->code == code && pinput->value == value) { + _E("Same key(%d, %d) is polled [%d,%d]", + code, value, old_fd, fd); + } + old_fd = fd; + code = pinput->code; + value = pinput->value; + + ignore = check_key(pinput, fd); + break; + case EV_REL: + ignore = false; + break; + case EV_ABS: + if (current_state_in_on()) + ignore = false; + else if (display_conf.alpm_on == true) { + switch_on_lcd(); + ignore = false; + } + if (pm_cur_state == S_LCDDIM && + backlight_ops.get_custom_status()) + backlight_ops.custom_update(); + + break; + } + idx += sizeof(struct input_event); + if (ignore == true && length <= idx) + return 1; + } while (length > idx); + + return 0; +} + +static void set_powerkey_ignore(int on) +{ + _D("ignore powerkey %d", on); + ignore_powerkey = on; +} + +static int powerkey_lcdoff(void) +{ + /* Remove non est processes */ + check_processes(S_LCDOFF); + check_processes(S_LCDDIM); + + /* check holdkey block flag in lock node */ + if (check_holdkey_block(S_LCDOFF) || + check_holdkey_block(S_LCDDIM)) { + return -ECANCELED; + } + + _I("power key lcdoff"); + switch_off_lcd(); + delete_condition(S_LCDOFF); + delete_condition(S_LCDDIM); + update_lcdoff_source(VCONFKEY_PM_LCDOFF_BY_POWERKEY); + recv_data.pid = -1; + recv_data.cond = 0x400; + (*g_pm_callback)(PM_CONTROL_EVENT, &recv_data); + + return 0; +} + +static const struct display_keyfilter_ops micro_keyfilter_ops = { + .init = NULL, + .exit = NULL, + .check = check_key_filter, + .set_powerkey_ignore = set_powerkey_ignore, + .powerkey_lcdoff = powerkey_lcdoff, + .backlight_enable = NULL, +}; +const struct display_keyfilter_ops *keyfilter_ops = µ_keyfilter_ops; + diff --git a/src/display/key-filter.c b/src/display/key-filter.c new file mode 100644 index 0000000..acb6192 --- /dev/null +++ b/src/display/key-filter.c @@ -0,0 +1,828 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include +#include +#include +#include + +#include +#include + +#include "util.h" +#include "core.h" +#include "poll.h" +#include "brightness.h" +#include "device-node.h" +#include "core/queue.h" +#include "core/common.h" +#include "core/data.h" +#include "core/device-notifier.h" +#include "core/edbus-handler.h" +#include "core/device-handler.h" + +#include +#ifndef KEY_SCREENLOCK +#define KEY_SCREENLOCK 0x98 +#endif +#ifndef SW_GLOVE +#define SW_GLOVE 0x16 +#endif + +#define PREDEF_LEAVESLEEP "leavesleep" +#define POWEROFF_ACT "poweroff" +#define PWROFF_POPUP_ACT "pwroff-popup" +#define USEC_PER_SEC 1000000 +#define COMBINATION_INTERVAL 0.5 /* 0.5 second */ +#define KEYBACKLIGHT_TIME_90 90 /* 1.5 second */ +#define KEYBACKLIGHT_TIME_360 360 /* 6 second */ +#define KEYBACKLIGHT_TIME_ALWAYS_ON -1 /* always on */ +#define KEYBACKLIGHT_TIME_ALWAYS_OFF 0 /* always off */ +#define KEYBACKLIGHT_BASE_TIME 60 /* 1min = 60sec */ +#define KEYBACKLIGHT_PRESSED_TIME 15 /* 15 second */ +#define KEY_MAX_DELAY_TIME 700 /* ms */ + +#define KEY_RELEASED 0 +#define KEY_PRESSED 1 +#define KEY_BEING_PRESSED 2 + +#define KEY_COMBINATION_STOP 0 +#define KEY_COMBINATION_START 1 +#define KEY_COMBINATION_SCREENCAPTURE 2 + +#define SIGNAL_CHANGE_HARDKEY "ChangeHardkey" + +#define NORMAL_POWER(val) (val == 0) +#define KEY_TEST_MODE_POWER(val) (val == 2) + +#define TOUCH_RELEASE (-1) + +#ifndef VCONFKEY_SETAPPL_TOUCHKEY_LIGHT_DURATION +#define VCONFKEY_SETAPPL_TOUCHKEY_LIGHT_DURATION VCONFKEY_SETAPPL_PREFIX"/display/touchkey_light_duration" +#endif + +#define GLOVE_MODE 1 + +int __WEAK__ get_glove_state(void); +void __WEAK__ switch_glove_key(int val); + +static struct timeval pressed_time; +static Ecore_Timer *longkey_timeout_id = NULL; +static Ecore_Timer *combination_timeout_id = NULL; +static Ecore_Timer *hardkey_timeout_id = NULL; +static int cancel_lcdoff; +static int key_combination = KEY_COMBINATION_STOP; +static int volumedown_pressed = false; +static int hardkey_duration; +static bool touch_pressed = false; +static int skip_lcd_off = false; +static bool powerkey_pressed = false; + +static inline int current_state_in_on(void) +{ + return (pm_cur_state == S_LCDDIM || pm_cur_state == S_NORMAL); +} + +static inline void restore_custom_brightness(void) +{ + if (pm_cur_state == S_LCDDIM && + backlight_ops.get_custom_status()) + backlight_ops.custom_update(); +} + +static void longkey_pressed() +{ + int val = 0; + int ret; + int csc_mode; + char *opt; + _I("Power key long pressed!"); + cancel_lcdoff = 1; + + /* change state - LCD on */ + recv_data.pid = -1; + recv_data.cond = 0x100; + (*g_pm_callback)(PM_CONTROL_EVENT, &recv_data); + + (*g_pm_callback) (INPUT_POLL_EVENT, NULL); + + ret = vconf_get_int(VCONFKEY_TESTMODE_POWER_OFF_POPUP, &val); + if (ret != 0 || NORMAL_POWER(val)) { + ret = vconf_get_int(VCONFKEY_CSC_CONFIG_MODE_RUNNING, + &csc_mode); + if (ret >= 0 && csc_mode) { + _I("csc config mode! No poweroff-popup!"); + return; + } + opt = PWROFF_POPUP_ACT; + goto entry_call; + } + if (KEY_TEST_MODE_POWER(val)) { + _I("skip power off control during factory key test mode"); + return; + } + opt = POWEROFF_ACT; +entry_call: + notify_action(opt, 0); +} + +static Eina_Bool longkey_pressed_cb(void *data) +{ + longkey_pressed(); + longkey_timeout_id = NULL; + + return EINA_FALSE; +} + +static Eina_Bool combination_failed_cb(void *data) +{ + key_combination = KEY_COMBINATION_STOP; + combination_timeout_id = NULL; + + return EINA_FALSE; +} + +static unsigned long timediff_usec(struct timeval t1, struct timeval t2) +{ + unsigned long udiff; + + udiff = (t2.tv_sec - t1.tv_sec) * USEC_PER_SEC; + udiff += (t2.tv_usec - t1.tv_usec); + + return udiff; +} + +static void stop_key_combination(void) +{ + key_combination = KEY_COMBINATION_STOP; + if (combination_timeout_id > 0) { + g_source_remove(combination_timeout_id); + combination_timeout_id = NULL; + } +} + +static inline void check_key_pair(int code, int new, int *old) +{ + if (new == *old) + _E("key pair is not matched! (%d, %d)", code, new); + else + *old = new; +} + +static inline bool switch_on_lcd(void) +{ + if (current_state_in_on()) + return false; + + if (backlight_ops.get_lcd_power() == PM_LCD_POWER_ON) + return false; + + lcd_on_direct(); + + return true; +} + +static inline void switch_off_lcd(void) +{ + if (!current_state_in_on()) + return; + + if (backlight_ops.get_lcd_power() == PM_LCD_POWER_OFF) + return; + + lcd_off_procedure(); +} + +static int process_menu_key(struct input_event *pinput) +{ + if (pinput->value == KEY_PRESSED) + switch_on_lcd(); + + stop_key_combination(); + + return false; +} + +static int decide_lcdoff(void) +{ + /* It's not needed if it's already LCD off state */ + if (!current_state_in_on() && + backlight_ops.get_lcd_power() != PM_LCD_POWER_ON) + return false; + + /* + * This flag is set at the moment + * that LCD is turned on by power key + * LCD has not to turned off in the situation. + */ + if (skip_lcd_off) + return false; + + /* LCD is not turned off when powerkey is pressed,not released */ + if (powerkey_pressed) + return false; + + /* LCD-off is blocked at the moment poweroff popup shows */ + if (cancel_lcdoff) + return false; + + /* LCD-off is blocked at the moment volumedown key is pressed */ + if (volumedown_pressed) + return false; + + /* LCD-off is blocked when powerkey and volmedown key are pressed */ + if (key_combination == KEY_COMBINATION_SCREENCAPTURE) + return false; + + return true; +} + +static int lcdoff_powerkey(void) +{ + int ignore = true; + + if (decide_lcdoff() == true) { + check_processes(S_LCDOFF); + check_processes(S_LCDDIM); + + if (!check_holdkey_block(S_LCDOFF) && + !check_holdkey_block(S_LCDDIM)) { + if (display_info.update_auto_brightness) + display_info.update_auto_brightness(false); + switch_off_lcd(); + delete_condition(S_LCDOFF); + delete_condition(S_LCDDIM); + update_lcdoff_source(VCONFKEY_PM_LCDOFF_BY_POWERKEY); + recv_data.pid = -1; + recv_data.cond = 0x400; + (*g_pm_callback)(PM_CONTROL_EVENT, &recv_data); + } + } else { + ignore = false; + } + cancel_lcdoff = 0; + + return ignore; +} + +static int process_power_key(struct input_event *pinput) +{ + int ignore = true; + static int value = KEY_RELEASED; + + switch (pinput->value) { + case KEY_RELEASED: + powerkey_pressed = false; + check_key_pair(pinput->code, pinput->value, &value); + + if (!display_conf.powerkey_doublepress) { + ignore = lcdoff_powerkey(); + } else if (skip_lcd_off) { + ignore = false; + } + + stop_key_combination(); + if (longkey_timeout_id > 0) { + ecore_timer_del(longkey_timeout_id); + longkey_timeout_id = NULL; + } + + break; + case KEY_PRESSED: + powerkey_pressed = true; + skip_lcd_off = switch_on_lcd(); + check_key_pair(pinput->code, pinput->value, &value); + _I("power key pressed"); + pressed_time.tv_sec = (pinput->time).tv_sec; + pressed_time.tv_usec = (pinput->time).tv_usec; + if (key_combination == KEY_COMBINATION_STOP) { + /* add long key timer */ + longkey_timeout_id = ecore_timer_add( + display_conf.longpress_interval, + (Ecore_Task_Cb)longkey_pressed_cb, NULL); + key_combination = KEY_COMBINATION_START; + combination_timeout_id = ecore_timer_add( + COMBINATION_INTERVAL, + (Ecore_Task_Cb)combination_failed_cb, NULL); + } else if (key_combination == KEY_COMBINATION_START) { + if (combination_timeout_id > 0) { + ecore_timer_del(combination_timeout_id); + combination_timeout_id = NULL; + } + _I("capture mode"); + key_combination = KEY_COMBINATION_SCREENCAPTURE; + skip_lcd_off = true; + ignore = false; + } + if (skip_lcd_off) + ignore = false; + cancel_lcdoff = 0; + + break; + case KEY_BEING_PRESSED: + if (timediff_usec(pressed_time, pinput->time) > + (display_conf.longpress_interval * USEC_PER_SEC)) + longkey_pressed(); + break; + } + return ignore; +} + +static int process_volumedown_key(struct input_event *pinput) +{ + int ignore = true; + + if (pinput->value == KEY_PRESSED) { + if (key_combination == KEY_COMBINATION_STOP) { + key_combination = KEY_COMBINATION_START; + combination_timeout_id = ecore_timer_add( + COMBINATION_INTERVAL, + (Ecore_Task_Cb)combination_failed_cb, NULL); + } else if (key_combination == KEY_COMBINATION_START) { + if (combination_timeout_id > 0) { + ecore_timer_del(combination_timeout_id); + combination_timeout_id = NULL; + } + if (longkey_timeout_id > 0) { + ecore_timer_del(longkey_timeout_id); + longkey_timeout_id = NULL; + } + _I("capture mode"); + key_combination = KEY_COMBINATION_SCREENCAPTURE; + skip_lcd_off = true; + ignore = false; + } + volumedown_pressed = true; + } else if (pinput->value == KEY_RELEASED) { + if (key_combination != KEY_COMBINATION_SCREENCAPTURE) { + stop_key_combination(); + if (current_state_in_on()) + ignore = false; + } + volumedown_pressed = false; + } + + return ignore; +} + +static int process_brightness_key(struct input_event *pinput, int action) +{ + if (pinput->value == KEY_RELEASED) { + stop_key_combination(); + return true; + } + + if (get_lock_screen_state() == VCONFKEY_IDLE_LOCK) + return false; + + /* check weak function symbol */ + if (!control_brightness_key) + return true; + + return control_brightness_key(action); +} + +static int process_screenlock_key(struct input_event *pinput) +{ + if (pinput->value != KEY_RELEASED) { + stop_key_combination(); + return true; + } + + if (!current_state_in_on()) + return false; + + check_processes(S_LCDOFF); + check_processes(S_LCDDIM); + + if (!check_holdkey_block(S_LCDOFF) && !check_holdkey_block(S_LCDDIM)) { + delete_condition(S_LCDOFF); + delete_condition(S_LCDDIM); + update_lcdoff_source(VCONFKEY_PM_LCDOFF_BY_POWERKEY); + + /* LCD off forcly */ + recv_data.pid = -1; + recv_data.cond = 0x400; + (*g_pm_callback)(PM_CONTROL_EVENT, &recv_data); + } + + return true; +} + +static void turnon_hardkey_backlight(void) +{ + int val, ret; + + ret = device_get_property(DEVICE_TYPE_LED, PROP_LED_HARDKEY, &val); + if (ret < 0 || !val) { + /* key backlight on */ + ret = device_set_property(DEVICE_TYPE_LED, + PROP_LED_HARDKEY, STATUS_ON); + if (ret < 0) + _E("Fail to turn off key backlight!"); + } +} + +static void turnoff_hardkey_backlight(void) +{ + int val, ret; + + ret = device_get_property(DEVICE_TYPE_LED, PROP_LED_HARDKEY, &val); + /* check key backlight is already off */ + if (!ret && !val) + return; + + /* key backlight off */ + ret = device_set_property(DEVICE_TYPE_LED, PROP_LED_HARDKEY, STATUS_OFF); + if (ret < 0) + _E("Fail to turn off key backlight!"); +} + +static Eina_Bool key_backlight_expired(void *data) +{ + hardkey_timeout_id = NULL; + + turnoff_hardkey_backlight(); + + return ECORE_CALLBACK_CANCEL; +} + +static void sound_vibrate_hardkey(void) +{ + /* device notify(vibrator) */ + device_notify(DEVICE_NOTIFIER_TOUCH_HARDKEY, NULL); + /* sound(dbus) */ + broadcast_edbus_signal(DEVICED_PATH_KEY, DEVICED_INTERFACE_KEY, + SIGNAL_CHANGE_HARDKEY, NULL, NULL); +} + +static void process_hardkey_backlight(struct input_event *pinput) +{ + float fduration; + + if (pinput->value == KEY_PRESSED) { + if (touch_pressed) { + _I("Touch is pressed, then hard key is not working!"); + return; + } + /* Sound & Vibrate only in unlock state */ + if (get_lock_screen_state() == VCONFKEY_IDLE_UNLOCK + || get_lock_screen_bg_state()) + sound_vibrate_hardkey(); + /* release existing timer */ + if (hardkey_timeout_id > 0) { + ecore_timer_del(hardkey_timeout_id); + hardkey_timeout_id = NULL; + } + /* if hardkey option is always off */ + if (hardkey_duration == KEYBACKLIGHT_TIME_ALWAYS_OFF) + return; + /* turn on hardkey backlight */ + turnon_hardkey_backlight(); + /* start timer */ + hardkey_timeout_id = ecore_timer_add( + KEYBACKLIGHT_PRESSED_TIME, + key_backlight_expired, NULL); + + } else if (pinput->value == KEY_RELEASED) { + /* if lockscreen is idle lock */ + if (get_lock_screen_state() == VCONFKEY_IDLE_LOCK) { + _D("Lock state, key backlight is off when phone is unlocked!"); + return; + } + /* release existing timer */ + if (hardkey_timeout_id > 0) { + ecore_timer_del(hardkey_timeout_id); + hardkey_timeout_id = NULL; + } + /* if hardkey option is always on or off */ + if (hardkey_duration == KEYBACKLIGHT_TIME_ALWAYS_ON || + hardkey_duration == KEYBACKLIGHT_TIME_ALWAYS_OFF) + return; + /* start timer */ + fduration = (float)hardkey_duration / KEYBACKLIGHT_BASE_TIME; + hardkey_timeout_id = ecore_timer_add( + fduration, + key_backlight_expired, NULL); + } +} + +static int check_key(struct input_event *pinput, int fd) +{ + int ignore = true; + + switch (pinput->code) { + case KEY_MENU: + ignore = process_menu_key(pinput); + break; + case KEY_POWER: + ignore = process_power_key(pinput); + break; + case KEY_VOLUMEDOWN: + ignore = process_volumedown_key(pinput); + break; + case KEY_BRIGHTNESSDOWN: + ignore = process_brightness_key(pinput, BRIGHTNESS_DOWN); + break; + case KEY_BRIGHTNESSUP: + ignore = process_brightness_key(pinput, BRIGHTNESS_UP); + break; + case KEY_SCREENLOCK: + ignore = process_screenlock_key(pinput); + break; + case KEY_BACK: + case KEY_PHONE: + stop_key_combination(); + if (current_state_in_on()) { + process_hardkey_backlight(pinput); + ignore = false; + } else if (!check_pre_install(fd)) { + ignore = false; + } + break; + case KEY_VOLUMEUP: + case KEY_CAMERA: + case KEY_EXIT: + case KEY_CONFIG: + case KEY_MEDIA: + case KEY_MUTE: + case KEY_PLAYPAUSE: + case KEY_PLAYCD: + case KEY_PAUSECD: + case KEY_STOPCD: + case KEY_NEXTSONG: + case KEY_PREVIOUSSONG: + case KEY_REWIND: + case KEY_FASTFORWARD: + stop_key_combination(); + if (current_state_in_on()) + ignore = false; + break; + case 0x1DB: + case 0x1DC: + case 0x1DD: + case 0x1DE: + stop_key_combination(); + break; + default: + stop_key_combination(); + ignore = false; + } +#ifdef ENABLE_PM_LOG + if (pinput->value == KEY_PRESSED) + pm_history_save(PM_LOG_KEY_PRESS, pinput->code); + else if (pinput->value == KEY_RELEASED) + pm_history_save(PM_LOG_KEY_RELEASE, pinput->code); +#endif + return ignore; +} + +static inline int check_powerkey_delay(struct input_event *pinput) +{ + struct timespec tp; + int delay; + + if (pinput->code != KEY_POWER || + pinput->value != KEY_PRESSED) + return false; + + if (backlight_ops.get_lcd_power() != PM_LCD_POWER_ON) + return false; + + clock_gettime(CLOCK_MONOTONIC, &tp); + + delay = SEC_TO_MSEC(tp.tv_sec) + + NSEC_TO_MSEC(tp.tv_nsec) - + (SEC_TO_MSEC((pinput->time).tv_sec) + + USEC_TO_MSEC((pinput->time).tv_usec)); + + if (delay < KEY_MAX_DELAY_TIME) + return false; + + return true; +} + +static int check_key_filter(int length, char buf[], int fd) +{ + struct input_event *pinput; + int ignore = true; + int idx = 0; + static int old_fd, code, value; + + do { + pinput = (struct input_event *)&buf[idx]; + switch (pinput->type) { + case EV_KEY: + if (pinput->code == BTN_TOUCH && + pinput->value == KEY_RELEASED) + touch_pressed = false; + /* + * The later inputs are going to be ignored when + * powerkey is pressed several times for a short time + */ + if (check_powerkey_delay(pinput) == true) { + _D("power key is delayed, then ignored!"); + return 0; + } + /* + * Normally, touch press/release events don't occur + * in lcd off state. But touch release events can occur + * in the state abnormally. Then touch events are ignored + * when lcd is off state. + */ + if (pinput->code == BTN_TOUCH && !current_state_in_on()) + break; + if (get_standby_state() && pinput->code != KEY_POWER) { + _D("standby mode,key ignored except powerkey"); + break; + } + if (pinput->code == code && pinput->value == value) { + _E("Same key(%d, %d) is polled [%d,%d]", + code, value, old_fd, fd); + } + old_fd = fd; + code = pinput->code; + value = pinput->value; + + ignore = check_key(pinput, fd); + restore_custom_brightness(); + + break; + case EV_REL: + if (get_standby_state()) + break; + ignore = false; + break; + case EV_ABS: + if (get_standby_state()) + break; + if (current_state_in_on()) + ignore = false; + restore_custom_brightness(); + + touch_pressed = + (pinput->value == TOUCH_RELEASE ? false : true); + break; + case EV_SW: + if (!get_glove_state || !switch_glove_key) + break; + if (pinput->code == SW_GLOVE && + get_glove_state() == GLOVE_MODE) { + switch_glove_key(pinput->value); + } + break; + } + idx += sizeof(struct input_event); + if (ignore == true && length <= idx) + return 1; + } while (length > idx); + + return 0; +} + +void key_backlight_enable(bool enable) +{ + /* release existing timer */ + if (hardkey_timeout_id > 0) { + ecore_timer_del(hardkey_timeout_id); + hardkey_timeout_id = NULL; + } + + /* start timer in case of backlight enabled */ + if (enable) { + /* if hardkey option is always off */ + if (hardkey_duration == KEYBACKLIGHT_TIME_ALWAYS_OFF) + return; + + /* turn on hardkey backlight */ + turnon_hardkey_backlight(); + + /* do not create turnoff timer in case of idle lock state */ + if (get_lock_screen_state() == VCONFKEY_IDLE_LOCK) + return; + + /* start timer */ + hardkey_timeout_id = ecore_timer_add( + KEYBACKLIGHT_PRESSED_TIME, + key_backlight_expired, NULL); + } else { + /* if hardkey option is always on */ + if (hardkey_duration == KEYBACKLIGHT_TIME_ALWAYS_ON) + return; + + /* turn off hardkey backlight */ + turnoff_hardkey_backlight(); + } +} + +static void hardkey_duration_cb(keynode_t *key, void *data) +{ + float duration; + + hardkey_duration = vconf_keynode_get_int(key); + + /* release existing timer */ + if (hardkey_timeout_id > 0) { + ecore_timer_del(hardkey_timeout_id); + hardkey_timeout_id = NULL; + } + + /* if hardkey option is always off */ + if (hardkey_duration == KEYBACKLIGHT_TIME_ALWAYS_OFF) { + /* turn off hardkey backlight */ + turnoff_hardkey_backlight(); + return; + } + + /* turn on hardkey backlight */ + turnon_hardkey_backlight(); + + /* if hardkey option is always on */ + if (hardkey_duration == KEYBACKLIGHT_TIME_ALWAYS_ON) + return; + + /* start timer */ + duration = (float)hardkey_duration / KEYBACKLIGHT_BASE_TIME; + hardkey_timeout_id = ecore_timer_add( + duration, + key_backlight_expired, NULL); +} + +static int hardkey_lcd_changed_cb(void *data) +{ + int lcd_state = (int)data; + + if (lcd_state == S_NORMAL + && battery.temp == TEMP_HIGH + && hardkey_duration == KEYBACKLIGHT_TIME_ALWAYS_ON) { + turnon_hardkey_backlight(); + return 0; + } + + /* when lcd state is dim and battery is over temp, + hardkey led should turn off */ + if (lcd_state == S_LCDDIM && battery.health == HEALTH_BAD) { + /* release existing timer */ + if (hardkey_timeout_id > 0) { + ecore_timer_del(hardkey_timeout_id); + hardkey_timeout_id = NULL; + } + + /* turn off hardkey backlight */ + turnoff_hardkey_backlight(); + } + return 0; +} + +static void keyfilter_init(void) +{ + /* get touchkey light duration setting */ + if (vconf_get_int(VCONFKEY_SETAPPL_TOUCHKEY_LIGHT_DURATION, &hardkey_duration) < 0) { + _W("Fail to get VCONFKEY_SETAPPL_TOUCHKEY_LIGHT_DURATION!!"); + hardkey_duration = KEYBACKLIGHT_TIME_90; + } + + vconf_notify_key_changed(VCONFKEY_SETAPPL_TOUCHKEY_LIGHT_DURATION, hardkey_duration_cb, NULL); + + /* register notifier */ + register_notifier(DEVICE_NOTIFIER_LCD, hardkey_lcd_changed_cb); + + /* update touchkey light duration right now */ + if (hardkey_duration == KEYBACKLIGHT_TIME_ALWAYS_ON) + turnon_hardkey_backlight(); +} + +static void keyfilter_exit(void) +{ + /* unregister notifier */ + unregister_notifier(DEVICE_NOTIFIER_LCD, hardkey_lcd_changed_cb); + + vconf_ignore_key_changed(VCONFKEY_SETAPPL_TOUCHKEY_LIGHT_DURATION, hardkey_duration_cb); +} + +static const struct display_keyfilter_ops normal_keyfilter_ops = { + .init = keyfilter_init, + .exit = keyfilter_exit, + .check = check_key_filter, + .set_powerkey_ignore = NULL, + .powerkey_lcdoff = NULL, + .backlight_enable = key_backlight_enable, +}; +const struct display_keyfilter_ops *keyfilter_ops = &normal_keyfilter_ops; + diff --git a/src/display/lock-detector.c b/src/display/lock-detector.c new file mode 100644 index 0000000..91c486e --- /dev/null +++ b/src/display/lock-detector.c @@ -0,0 +1,223 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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. + */ + + +/** + * @file lock-detector.c + * @brief + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "util.h" +#include "core.h" +#include "core/list.h" + +struct lock_info { + unsigned long hash; + char *name; + int state; + int count; + long locktime; + long unlocktime; + long time; +}; + +#define LIMIT_COUNT 128 + +static Eina_List *lock_info_list; + +static long get_time(void) +{ + struct timeval now; + gettimeofday(&now, NULL); + return (long)(now.tv_sec * 1000 + now.tv_usec / 1000); +} + +static void shrink_lock_info_list(void) +{ + Eina_List *l, *l_prev; + struct lock_info *info; + unsigned int count; + + count = eina_list_count(lock_info_list); + if (count <= LIMIT_COUNT) + return; + _D("list is shrink : count %d", count); + + EINA_LIST_REVERSE_FOREACH_SAFE(lock_info_list, l, l_prev, info) { + if (info->locktime == 0) { + EINA_LIST_REMOVE_LIST(lock_info_list, l); + if (info->name) + free(info->name); + free(info); + count--; + } + if (count <= (LIMIT_COUNT / 2)) + break; + } +} + +int set_lock_time(const char *pname, int state) +{ + struct lock_info *info; + Eina_List *l; + unsigned long val; + + if (!pname) + return -EINVAL; + + if (state < S_NORMAL || state > S_SLEEP) + return -EINVAL; + + val = eina_hash_superfast(pname, strlen(pname)); + + EINA_LIST_FOREACH(lock_info_list, l, info) + if (info->hash == val && info->state == state) { + info->count += 1; + if (info->locktime == 0) + info->locktime = get_time(); + info->unlocktime = 0; + EINA_LIST_PROMOTE_LIST(lock_info_list, l); + eina_list_data_set(l, info); + return 0; + } + + info = malloc(sizeof(struct lock_info)); + if (!info) { + _E("Malloc is failed for lock_info!"); + return -ENOMEM; + } + + info->hash = val; + info->name = strndup(pname, strlen(pname)); + info->state = state; + info->count = 1; + info->locktime = get_time(); + info->unlocktime = 0; + info->time = 0; + + EINA_LIST_APPEND(lock_info_list, info); + + return 0; +} + +int set_unlock_time(const char *pname, int state) +{ + bool find = false; + long diff; + struct lock_info *info; + Eina_List *l; + unsigned long val; + + if (!pname) + return -EINVAL; + + if (state < S_NORMAL || state > S_SLEEP) + return -EINVAL; + + val = eina_hash_superfast(pname, strlen(pname)); + + EINA_LIST_FOREACH(lock_info_list, l, info) + if (info->hash == val && info->state == state) { + EINA_LIST_PROMOTE_LIST(lock_info_list, l); + find = true; + break; + } + + if (!find) + return -EINVAL; + + if (info->locktime == 0) + return -EINVAL; + + /* update time */ + info->unlocktime = get_time(); + diff = info->unlocktime - info->locktime; + if (diff > 0) + info->time += diff; + info->locktime = 0; + + eina_list_data_set(l, info); + + if (eina_list_count(lock_info_list) > LIMIT_COUNT) + shrink_lock_info_list(); + + return 0; +} + +void free_lock_info_list(void) +{ + Eina_List *l, *l_next; + struct lock_info *info; + + if (!lock_info_list) + return; + + EINA_LIST_FOREACH_SAFE(lock_info_list, l, l_next, info) { + EINA_LIST_REMOVE(lock_info_list, l); + if (info->name) + free(info->name); + free(info); + } + lock_info_list = NULL; +} + +void print_lock_info_list(int fd) +{ + struct lock_info *info; + Eina_List *l; + char buf[255]; + + if (!lock_info_list) + return; + + snprintf(buf, sizeof(buf), + "current time : %u ms\n", get_time()); + write(fd, buf, strlen(buf)); + + snprintf(buf, sizeof(buf), + "[%10s %6s] %6s %10s %10s %10s %s\n", "hash", "state", + "count", "locktime", "unlocktime", "time", "process name"); + write(fd, buf, strlen(buf)); + + EINA_LIST_FOREACH(lock_info_list, l, info) { + long time = 0; + if (info->locktime != 0 && info->unlocktime == 0) + time = get_time() - info->locktime; + snprintf(buf, sizeof(buf), + "[%10u %6d] %6d %10u %10u %10u %s\n", + info->hash, + info->state, + info->count, + info->locktime, + info->unlocktime, + info->time + time, + info->name); + write(fd, buf, strlen(buf)); + } +} + diff --git a/src/display/lock-detector.h b/src/display/lock-detector.h new file mode 100644 index 0000000..681b896 --- /dev/null +++ b/src/display/lock-detector.h @@ -0,0 +1,35 @@ +/* + * deviced + * + * Copyright (c) 2011 - 2013 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. + */ + + +/** + * @file lock-detector.h + * @brief + * + */ + +#ifndef _LOCK_DETECTOR_H_ +#define _LOCK_DETECTOR_H_ + +int set_lock_time(const char *pname, int state); +int set_unlock_time(const char *pname, int state); +void free_lock_info_list(void); +void print_lock_info_list(int fd); + +#endif //_LOCK_DETECTOR_H_ + diff --git a/src/display/poll.c b/src/display/poll.c new file mode 100644 index 0000000..652df6d --- /dev/null +++ b/src/display/poll.c @@ -0,0 +1,412 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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. + */ + + +/** + * @file poll.c + * @brief Power Manager poll implementation (input devices & a domain socket file) + * + * This file includes the input device poll implementation. + * Default input devices are /dev/event0 and /dev/event1 + * User can use "PM_INPUT" for setting another input device poll in an environment file (/etc/profile). + * (ex: PM_INPUT=/dev/event0:/dev/event1:/dev/event5 ) + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "util.h" +#include "core.h" +#include "poll.h" + +#define SHIFT_UNLOCK 4 +#define SHIFT_UNLOCK_PARAMETER 12 +#define SHIFT_CHANGE_STATE 8 +#define SHIFT_CHANGE_TIMEOUT 20 +#define LOCK_FLAG_SHIFT 16 +#define __HOLDKEY_BLOCK_BIT 0x1 +#define __STANDBY_MODE_BIT 0x2 +#define HOLDKEY_BLOCK_BIT (__HOLDKEY_BLOCK_BIT << LOCK_FLAG_SHIFT) +#define STANDBY_MODE_BIT (__STANDBY_MODE_BIT << LOCK_FLAG_SHIFT) + +#define DEV_PATH_DLM ":" + +PMMsg recv_data; +int (*g_pm_callback) (int, PMMsg *); + +#ifdef ENABLE_KEY_FILTER +extern int check_key_filter(int length, char buf[], int fd); +# define CHECK_KEY_FILTER(a, b, c) \ + do { \ + if (CHECK_OPS(keyfilter_ops, check) && \ + keyfilter_ops->check(a, b, c) != 0) \ + return EINA_TRUE;\ + } while (0); +#else +# define CHECK_KEY_FILTER(a, b, c) +#endif + +#define DEFAULT_DEV_PATH "/dev/event1:/dev/event0" + +static Eina_Bool pm_handler(void *data, Ecore_Fd_Handler *fd_handler) +{ + char buf[1024]; + struct sockaddr_un clientaddr; + + int fd = (int)data; + int ret; + static const struct device_ops *display_device_ops; + + if (!display_device_ops) { + display_device_ops = find_device("display"); + if (!display_device_ops) + return -ENODEV; + } + + if (device_get_status(display_device_ops) != DEVICE_OPS_STATUS_START) { + _E("display is not started!"); + return EINA_FALSE; + } + + if (g_pm_callback == NULL) { + return EINA_FALSE; + } + + ret = read(fd, buf, sizeof(buf)); + CHECK_KEY_FILTER(ret, buf, fd); + (*g_pm_callback) (INPUT_POLL_EVENT, NULL); + + return EINA_TRUE; +} + +int init_pm_poll(int (*pm_callback) (int, PMMsg *)) +{ + char *dev_paths, *path_tok, *pm_input_env, *save_ptr; + int dev_paths_size; + + Ecore_Fd_Handler *fd_handler; + int fd = -1; + indev *new_dev = NULL; + + g_pm_callback = pm_callback; + + _I("initialize pm poll - input devices(deviced)"); + + pm_input_env = getenv("PM_INPUT"); + if ((pm_input_env != NULL) && (strlen(pm_input_env) < 1024)) { + _I("Getting input device path from environment: %s", + pm_input_env); + /* Add 2 bytes for following strncat() */ + dev_paths_size = strlen(pm_input_env) + 1; + dev_paths = (char *)malloc(dev_paths_size); + if (!dev_paths) { + _E("Fail to malloc for dev path"); + return -ENOMEM; + } + snprintf(dev_paths, dev_paths_size, "%s", pm_input_env); + } else { + /* Add 2 bytes for following strncat() */ + dev_paths_size = strlen(DEFAULT_DEV_PATH) + 1; + dev_paths = (char *)malloc(dev_paths_size); + if (!dev_paths) { + _E("Fail to malloc for dev path"); + return -ENOMEM; + } + snprintf(dev_paths, dev_paths_size, "%s", DEFAULT_DEV_PATH); + } + + /* add the UNIX domain socket file path */ + strncat(dev_paths, DEV_PATH_DLM, strlen(DEV_PATH_DLM)); + dev_paths[dev_paths_size - 1] = '\0'; + + path_tok = strtok_r(dev_paths, DEV_PATH_DLM, &save_ptr); + if (path_tok == NULL) { + _E("Device Path Tokeninzing Failed"); + free(dev_paths); + return -1; + } + + do { + char *path, *new_path; + int len; + + fd = open(path_tok, O_RDONLY); + path = path_tok; + _I("pm_poll input device file: %s, fd: %d", path_tok, fd); + + if (fd == -1) { + _E("Cannot open the file: %s", path_tok); + goto out1; + } + + fd_handler = ecore_main_fd_handler_add(fd, + ECORE_FD_READ|ECORE_FD_ERROR, + pm_handler, (void *)fd, NULL, NULL); + if (fd_handler == NULL) { + _E("Failed ecore_main_handler_add() in init_pm_poll()"); + goto out2; + } + + new_dev = (indev *)malloc(sizeof(indev)); + + if (!new_dev) { + _E("Fail to malloc for new_dev %s", path); + goto out3; + } + + memset(new_dev, 0, sizeof(indev)); + + len = strlen(path) + 1; + new_path = (char*) malloc(len); + if (!new_path) { + _E("Fail to malloc for dev_path %s", path); + goto out4; + } + + strncpy(new_path, path, len); + new_dev->dev_path = new_path; + new_dev->fd = fd; + new_dev->dev_fd = fd_handler; + new_dev->pre_install = true; + indev_list = eina_list_append(indev_list, new_dev); + + } while ((path_tok = strtok_r(NULL, DEV_PATH_DLM, &save_ptr))); + + free(dev_paths); + return 0; + +out4: + free(new_dev); +out3: + ecore_main_fd_handler_del(fd_handler); +out2: + close(fd); +out1: + free(dev_paths); + + return -ENOMEM; +} + +int exit_pm_poll(void) +{ + Eina_List *l = NULL; + Eina_List *l_next = NULL; + indev *data = NULL; + + EINA_LIST_FOREACH_SAFE(indev_list, l, l_next, data) { + ecore_main_fd_handler_del(data->dev_fd); + close(data->fd); + free(data->dev_path); + free(data); + indev_list = eina_list_remove_list(indev_list, l); + } + + _I("pm_poll is finished"); + return 0; +} + +int init_pm_poll_input(int (*pm_callback)(int , PMMsg * ), const char *path) +{ + indev *new_dev = NULL; + indev *data = NULL; + Ecore_Fd_Handler *fd_handler = NULL; + Eina_List *l = NULL; + Eina_List *l_next = NULL; + int fd = -1; + char *dev_path = NULL; + + if (!pm_callback || !path) { + _E("argument is NULL! (%x,%x)", pm_callback, path); + return -1; + } + + EINA_LIST_FOREACH_SAFE(indev_list, l, l_next, data) + if(!strcmp(path, data->dev_path)) { + _E("%s is already polled!", path); + return -1; + } + + _I("initialize pm poll for bt %s", path); + + g_pm_callback = pm_callback; + + fd = open(path, O_RDONLY); + if (fd == -1) { + _E("Cannot open the file for BT: %s", path); + return -1; + } + + dev_path = (char*)malloc(strlen(path) + 1); + if (!dev_path) { + _E("Fail to malloc for dev_path"); + close(fd); + return -1; + } + strncpy(dev_path, path, strlen(path) +1); + + fd_handler = ecore_main_fd_handler_add(fd, + ECORE_FD_READ|ECORE_FD_ERROR, + pm_handler, (void *)fd, NULL, NULL); + if (!fd_handler) { + _E("Fail to ecore fd handler add! %s", path); + close(fd); + free(dev_path); + return -1; + } + + new_dev = (indev *)malloc(sizeof(indev)); + if (!new_dev) { + _E("Fail to malloc for new_dev %s", path); + ecore_main_fd_handler_del(fd_handler); + close(fd); + free(dev_path); + return -1; + } + new_dev->dev_path = dev_path; + new_dev->fd = fd; + new_dev->dev_fd = fd_handler; + new_dev->pre_install = false; + + _I("pm_poll for BT input device file(path: %s, fd: %d", + new_dev->dev_path, new_dev->fd); + indev_list = eina_list_append(indev_list, new_dev); + + return 0; +} + +int check_pre_install(int fd) +{ + indev *data = NULL; + Eina_List *l = NULL; + Eina_List *l_next = NULL; + + EINA_LIST_FOREACH_SAFE(indev_list, l, l_next, data) + if(fd == data->fd) { + return data->pre_install; + } + + return -ENODEV; +} + +int check_dimstay(int next_state, int flag) +{ + if (next_state != LCD_OFF) + return false; + + if (!(flag & GOTO_STATE_NOW)) + return false; + + if (!(pm_status_flag & DIMSTAY_FLAG)) + return false; + + if (check_abnormal_popup() != HEALTH_BAD) + return false; + + return true; +} + +int pm_lock_internal(pid_t pid, int s_bits, int flag, int timeout) +{ + if (!g_pm_callback) + return -1; + + switch (s_bits) { + case LCD_NORMAL: + case LCD_DIM: + case LCD_OFF: + break; + default: + return -1; + } + if (flag & GOTO_STATE_NOW) + /* if the flag is true, go to the locking state directly */ + s_bits = s_bits | (s_bits << SHIFT_CHANGE_STATE); + + if (flag & HOLD_KEY_BLOCK) + s_bits = s_bits | HOLDKEY_BLOCK_BIT; + + if (flag & STANDBY_MODE) + s_bits = s_bits | STANDBY_MODE_BIT; + + recv_data.pid = pid; + recv_data.cond = s_bits; + recv_data.timeout = timeout; + + (*g_pm_callback)(PM_CONTROL_EVENT, &recv_data); + + return 0; +} + +int pm_unlock_internal(pid_t pid, int s_bits, int flag) +{ + if (!g_pm_callback) + return -1; + + switch (s_bits) { + case LCD_NORMAL: + case LCD_DIM: + case LCD_OFF: + break; + default: + return -1; + } + + s_bits = (s_bits << SHIFT_UNLOCK); + s_bits = (s_bits | (flag << SHIFT_UNLOCK_PARAMETER)); + + recv_data.pid = pid; + recv_data.cond = s_bits; + + (*g_pm_callback)(PM_CONTROL_EVENT, &recv_data); + + return 0; +} + +int pm_change_internal(pid_t pid, int s_bits) +{ + if (!g_pm_callback) + return -1; + + switch (s_bits) { + case LCD_NORMAL: + case LCD_DIM: + case LCD_OFF: + case SUSPEND: + break; + default: + return -1; + } + + recv_data.pid = pid; + recv_data.cond = s_bits << SHIFT_CHANGE_STATE; + + (*g_pm_callback)(PM_CONTROL_EVENT, &recv_data); + + return 0; +} + diff --git a/src/display/poll.h b/src/display/poll.h new file mode 100644 index 0000000..30268d9 --- /dev/null +++ b/src/display/poll.h @@ -0,0 +1,128 @@ +/* + * deviced + * + * Copyright (c) 2011 - 2013 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. + */ + + +/** + * @file poll.h + * @brief Power Manager input device poll implementation + * + * This file includes the input device poll implementation. + * Default input devices are /dev/event0 and /dev/event1 + * User can use "PM_INPUT_DEV" for setting another input device poll in an environment file (/etc/profile). + * (ex: PM_INPUT_DEV=/dev/event0:/dev/event1:/dev/event5 ) + */ + +#ifndef __PM_POLL_H__ +#define __PM_POLL_H__ + +#include +#include "core/edbus-handler.h" +/** + * @addtogroup POWER_MANAGER + * @{ + */ + +enum { + INPUT_POLL_EVENT = -9, + SIDEKEY_POLL_EVENT, + PWRKEY_POLL_EVENT, + PM_CONTROL_EVENT, +}; + +enum { + INTERNAL_LOCK_BASE = 100000, + INTERNAL_LOCK_BATTERY, + INTERNAL_LOCK_BOOTING, + INTERNAL_LOCK_DUMPMODE, + INTERNAL_LOCK_HDMI, + INTERNAL_LOCK_ODE, + INTERNAL_LOCK_POPUP, + INTERNAL_LOCK_SOUNDDOCK, + INTERNAL_LOCK_TA, + INTERNAL_LOCK_TIME, + INTERNAL_LOCK_USB, +}; + +#define SIGNAL_NAME_LCD_CONTROL "lcdcontol" + +#define LCD_NORMAL 0x1 /**< NORMAL state */ +#define LCD_DIM 0x2 /**< LCD dimming state */ +#define LCD_OFF 0x4 /**< LCD off state */ +#define SUSPEND 0x8 /**< Suspend state */ +#define POWER_OFF 0x16 /**< Sleep state */ + +#define STAY_CUR_STATE 0x1 +#define GOTO_STATE_NOW 0x2 +#define HOLD_KEY_BLOCK 0x4 +#define STANDBY_MODE 0x8 + +#define PM_SLEEP_MARGIN 0x0 /**< keep guard time for unlock */ +#define PM_RESET_TIMER 0x1 /**< reset timer for unlock */ +#define PM_KEEP_TIMER 0x2 /**< keep timer for unlock */ + +#define PM_LOCK_STR "lock" +#define PM_UNLOCK_STR "unlock" +#define PM_CHANGE_STR "change" + +#define PM_LCDOFF_STR "lcdoff" +#define PM_LCDDIM_STR "lcddim" +#define PM_LCDON_STR "lcdon" +#define PM_SUSPEND_STR "suspend" + +#define STAYCURSTATE_STR "staycurstate" +#define GOTOSTATENOW_STR "gotostatenow" + +#define HOLDKEYBLOCK_STR "holdkeyblock" +#define STANDBYMODE_STR "standbymode" + +#define SLEEP_MARGIN_STR "sleepmargin" +#define RESET_TIMER_STR "resettimer" +#define KEEP_TIMER_STR "keeptimer" + +typedef struct { + pid_t pid; + unsigned int cond; + unsigned int timeout; + unsigned int timeout2; +} PMMsg; + +typedef struct { + char *dev_path; + int fd; + Ecore_Fd_Handler *dev_fd; + int pre_install; +} indev; + +Eina_List *indev_list; + +PMMsg recv_data; +int (*g_pm_callback) (int, PMMsg *); + +extern int init_pm_poll(int (*pm_callback) (int, PMMsg *)); +extern int exit_pm_poll(); +extern int init_pm_poll_input(int (*pm_callback)(int , PMMsg * ), const char *path); + +extern int pm_lock_internal(pid_t pid, int s_bits, int flag, int timeout); +extern int pm_unlock_internal(pid_t pid, int s_bits, int flag); +extern int pm_change_internal(pid_t pid, int s_bits); + +/** + * @} + */ + +#endif /*__PM_POLL_H__ */ diff --git a/src/display/setting.c b/src/display/setting.c new file mode 100644 index 0000000..2fc1dfd --- /dev/null +++ b/src/display/setting.c @@ -0,0 +1,248 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 "core.h" +#include "util.h" +#include "setting.h" + +#define LCD_DIM_RATIO 0.2 +#define LCD_MAX_DIM_TIMEOUT 7000 + +static const char *setting_keys[SETTING_GET_END] = { + [SETTING_TO_NORMAL] = VCONFKEY_SETAPPL_LCD_TIMEOUT_NORMAL, + [SETTING_BRT_LEVEL] = VCONFKEY_SETAPPL_LCD_BRIGHTNESS, + [SETTING_LOCK_SCREEN] = VCONFKEY_IDLE_LOCK_STATE, + [SETTING_POWER_SAVING] = VCONFKEY_SETAPPL_PWRSV_SYSMODE_STATUS, + [SETTING_POWER_SAVING_DISPLAY] = VCONFKEY_SETAPPL_PWRSV_CUSTMODE_DISPLAY, + [SETTING_SMART_STAY] = VCONFKEY_SETAPPL_SMARTSCREEN_SMARTSTAY_STATUS, + [SETTING_BOOT_POWER_ON_STATUS] = VCONFKEY_DEVICED_BOOT_POWER_ON_STATUS, + [SETTING_POWER_CUSTOM_BRIGHTNESS] = VCONFKEY_PM_CUSTOM_BRIGHTNESS_STATUS, + [SETTING_ACCESSIBILITY_TTS] = VCONFKEY_SETAPPL_ACCESSIBILITY_TTS, +}; + +static int lock_screen_state = VCONFKEY_IDLE_UNLOCK; +static bool lock_screen_bg_state = false; +static int force_lcdtimeout = 0; +static int custom_on_timeout = 0; +static int custom_normal_timeout = 0; +static int custom_dim_timeout = 0; + +int (*update_pm_setting) (int key_idx, int val); + +int set_force_lcdtimeout(int timeout) +{ + if (timeout < 0) + return -EINVAL; + + force_lcdtimeout = timeout; + + return 0; +} + +int get_lock_screen_state(void) +{ + return lock_screen_state; +} + +void set_lock_screen_state(int state) +{ + switch (state) { + case VCONFKEY_IDLE_LOCK: + case VCONFKEY_IDLE_UNLOCK: + lock_screen_state = state; + break; + default: + lock_screen_state = VCONFKEY_IDLE_UNLOCK; + } +} + +int get_lock_screen_bg_state(void) +{ + return lock_screen_bg_state; +} + +void set_lock_screen_bg_state(bool state) +{ + _I("state is %d", state); + lock_screen_bg_state = state; +} + +int get_charging_status(int *val) +{ + return vconf_get_int(VCONFKEY_SYSMAN_BATTERY_CHARGE_NOW, val); +} + +int get_lowbatt_status(int *val) +{ + return vconf_get_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, val); +} + +int get_usb_status(int *val) +{ + return vconf_get_int(VCONFKEY_SYSMAN_USB_STATUS, val); +} + +int set_setting_pmstate(int val) +{ + return vconf_set_int(VCONFKEY_PM_STATE, val); +} + +int get_setting_brightness(int *level) +{ + return vconf_get_int(VCONFKEY_SETAPPL_LCD_BRIGHTNESS, level); +} + +int get_dim_timeout(int *dim_timeout) +{ + int vconf_timeout, on_timeout, val, ret; + + if (custom_dim_timeout > 0) { + *dim_timeout = custom_dim_timeout; + return 0; + } + + ret = vconf_get_int(setting_keys[SETTING_TO_NORMAL], &vconf_timeout); + if (ret != 0) { + _E("Failed ro get setting timeout!"); + vconf_timeout = DEFAULT_NORMAL_TIMEOUT; + } + + if (force_lcdtimeout > 0) + on_timeout = SEC_TO_MSEC(force_lcdtimeout); + else + on_timeout = SEC_TO_MSEC(vconf_timeout); + + val = (double)on_timeout * LCD_DIM_RATIO; + if (val > LCD_MAX_DIM_TIMEOUT) + val = LCD_MAX_DIM_TIMEOUT; + + *dim_timeout = val; + + return 0; +} + +int get_run_timeout(int *timeout) +{ + int dim_timeout = -1; + int vconf_timeout = -1; + int on_timeout; + int ret; + + if (custom_normal_timeout > 0) { + *timeout = custom_normal_timeout; + return 0; + } + + ret = vconf_get_int(setting_keys[SETTING_TO_NORMAL], &vconf_timeout); + if (ret != 0) { + _E("Failed ro get setting timeout!"); + vconf_timeout = DEFAULT_NORMAL_TIMEOUT; + } + + if (force_lcdtimeout > 0) + on_timeout = SEC_TO_MSEC(force_lcdtimeout); + else + on_timeout = SEC_TO_MSEC(vconf_timeout); + + get_dim_timeout(&dim_timeout); + + if (on_timeout <= 0) + ret = -ERANGE; + else + *timeout = on_timeout - dim_timeout; + + return ret; +} + +int set_custom_lcdon_timeout(int timeout) +{ + int changed = (custom_on_timeout == timeout ? false : true); + + custom_on_timeout = timeout; + + if (timeout <= 0) { + custom_normal_timeout = 0; + custom_dim_timeout = 0; + return changed; + } + + custom_dim_timeout = (double)timeout * LCD_DIM_RATIO; + custom_normal_timeout = timeout - custom_dim_timeout; + + _I("custom normal(%d), dim(%d)", custom_normal_timeout, + custom_dim_timeout); + + return changed; +} + +static int setting_cb(keynode_t *key_nodes, void *data) +{ + keynode_t *tmp = key_nodes; + + if ((int)data > SETTING_END) { + _E("Unknown setting key: %s, idx=%d", + vconf_keynode_get_name(tmp), (int)data); + return -1; + } + if (update_pm_setting != NULL) { + switch((int)data) { + case SETTING_POWER_SAVING: + case SETTING_POWER_SAVING_DISPLAY: + case SETTING_ACCESSIBILITY_TTS: + update_pm_setting((int)data, vconf_keynode_get_bool(tmp)); + break; + default: + update_pm_setting((int)data, vconf_keynode_get_int(tmp)); + break; + } + } + + return 0; +} + +int init_setting(int (*func) (int key_idx, int val)) +{ + int i; + + if (func != NULL) + update_pm_setting = func; + + for (i = SETTING_BEGIN; i < SETTING_GET_END; i++) { + vconf_notify_key_changed(setting_keys[i], (void *)setting_cb, + (void *)i); + } + + return 0; +} + +int exit_setting(void) +{ + int i; + for (i = SETTING_BEGIN; i < SETTING_GET_END; i++) { + vconf_ignore_key_changed(setting_keys[i], (void *)setting_cb); + } + + return 0; +} + diff --git a/src/display/setting.h b/src/display/setting.h new file mode 100644 index 0000000..7c48397 --- /dev/null +++ b/src/display/setting.h @@ -0,0 +1,130 @@ +/* + * deviced + * + * Copyright (c) 2011 - 2013 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. + */ + + +/* + * @file setting.h + * @brief Power manager setting module header + */ +#ifndef __PM_SETTING_H__ +#define __PM_SETTING_H__ + +#include + +/* + * @addtogroup POWER_MANAGER + * @{ + */ + +enum { + SETTING_BEGIN = 0, + SETTING_TO_NORMAL = SETTING_BEGIN, + SETTING_BRT_LEVEL, + SETTING_LOCK_SCREEN, + SETTING_POWER_SAVING, + SETTING_POWER_SAVING_DISPLAY, + SETTING_SMART_STAY, + SETTING_BOOT_POWER_ON_STATUS, + SETTING_POWER_CUSTOM_BRIGHTNESS, + SETTING_ACCESSIBILITY_TTS, + SETTING_GET_END, + SETTING_PM_STATE = SETTING_GET_END, + SETTING_LOW_BATT, + SETTING_CHARGING, + SETTING_POWEROFF, + SETTING_HALLIC_OPEN, + SETTING_LOCK_SCREEN_BG, + SETTING_END +}; + +extern int (*update_pm_setting) (int key_idx, int val); + +extern int get_setting_brightness(); + +/* + * @brief setting initialization function + * + * get the variables if it exists. otherwise, set the default. + * and register some callback functions. + * + * @internal + * @param[in] func configuration change callback function + * @return 0 : success, -1 : error + */ +extern int init_setting(int (*func) (int key_idx, int val)); + +extern int exit_setting(); + +/* + * get normal state timeout from SLP-setting SLP_SETTING_LCD_TIMEOUT_NORMAL + * + * @internal + * @param[out] timeout timeout variable pointer + * @return 0 : success, -1 : error + */ +extern int get_run_timeout(int *timeout); + +/* + * get LCD dim state timeout from environment variable. + * + * @internal + * @param[out] dim_timeout timeout variable pointer + * @return 0 : success, negative value : error + */ +extern int get_dim_timeout(int *dim_timeout); +/* + * get USB connection status from SLP-setting SLP_SETTING_USB_STATUS + * + * @internal + * @param[out] val usb connection status variable pointer, 0 is disconnected, others is connected. + * @return 0 : success, -1 : error + */ +extern int get_usb_status(int *val); + +/* + * set Current power manager state at SLP-setting "memory/pwrmgr/state" + * + * @internal + * @param[in] val current power manager state. + * @return 0 : success, -1 : error + */ +extern int set_setting_pmstate(int val); + +/* + * get charging status at SLP-setting "memory/Battery/Charger" + * + * @internal + * @param[in] val charging or not (1 or 0 respectively). + * @return 0 : success, -1 : error + */ +extern int get_charging_status(int *val); + +/* + * get current battery low status at SLP-setting "memory/Battery/Status/Low" + * + * @internal + * @param[in] val current low battery status + * @return 0 : success, -1 : error + */ +extern int get_lowbatt_status(int *val); + +/* + * @} + */ + +#endif diff --git a/src/display/smartstay.c b/src/display/smartstay.c new file mode 100644 index 0000000..6f9cb32 --- /dev/null +++ b/src/display/smartstay.c @@ -0,0 +1,232 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 "util.h" +#include "core.h" +#include "display-ops.h" +#include "core/common.h" +#include "core/device-handler.h" + +#define SMART_STAY 2 +#define SMART_DETECTION_LIB "/usr/lib/sensor_framework/libsmart_detection.so" +#define CB_TIMEOUT 3 /* seconds */ +#define OCCUPIED_FAIL -2 + +typedef void (*detection_cb)(int result, void *data); + +static void *detect_handle = NULL; +static int (*get_detection)(detection_cb callback, int type, void* user_data1, void* user_data2); +static bool block_state = EINA_FALSE; +static bool cb_state = EINA_FALSE; +static Ecore_Timer *cb_timeout_id = NULL; + +static void init_smart_lib(void) +{ + detect_handle = dlopen(SMART_DETECTION_LIB, RTLD_LAZY); + + if (!detect_handle) { + _E("dlopen error"); + } else { + get_detection = (int (*)(detection_cb, int, void *, void *)) + dlsym(detect_handle, "get_smart_detection"); + + if (!get_detection) { + _E("dl_sym fail"); + dlclose(detect_handle); + detect_handle = NULL; + } + } +} + +static Eina_Bool check_cb_state(void *data) +{ + struct state *st; + int next_state; + int user_data = (int)(data); + + cb_timeout_id = NULL; + + if (cb_state) { + _I("smart detection cb is already working!"); + return ECORE_CALLBACK_CANCEL; + } + + if (block_state) { + _I("input event occur, smart detection is ignored!"); + block_state = EINA_FALSE; + return ECORE_CALLBACK_CANCEL; + } + + if (user_data < S_START || user_data > S_LCDOFF) { + _E("next state is wrong [%d], set to [%d]", + user_data, S_NORMAL); + user_data = S_NORMAL; + } + + _I("smart detection cb is failed, goes to [%d]", user_data); + + next_state = user_data; + pm_old_state = pm_cur_state; + pm_cur_state = next_state; + + st = &states[pm_cur_state]; + if (st->action) + st->action(st->timeout); + + if (pm_cur_state == S_LCDOFF) + update_lcdoff_source(VCONFKEY_PM_LCDOFF_BY_TIMEOUT); + + return ECORE_CALLBACK_CANCEL; +} + +static void detection_callback(int degree, void *data) +{ + struct state *st; + int next_state; + int user_data = (int)(data); + + cb_state = EINA_TRUE; + + if (block_state) { + _I("input event occur, face detection is ignored!"); + block_state = EINA_FALSE; + return; + } + + if (!get_hallic_open()) { + _I("hallic is closed! Skip detection logic!"); + return; + } + + _I("degree = [%d], user_data = [%d]", degree, user_data); + + switch (degree) + { + case 270: + case 90: + case 180: + case 0: + _I("face detection success, goes to [%d]", + S_NORMAL); + pm_old_state = pm_cur_state; + pm_cur_state = S_NORMAL; + break; + case OCCUPIED_FAIL: + _I("camera is occupied, stay current state"); + break; + default: + if (user_data < S_START || user_data > S_LCDOFF) { + _E("next state is wrong [%d], set to [%d]", + user_data, S_NORMAL); + user_data = S_NORMAL; + } + + next_state = user_data; + + pm_old_state = pm_cur_state; + pm_cur_state = next_state; + + if (check_lcdoff_direct() == true) + pm_cur_state = S_LCDOFF; + + _I("smart detection is failed, goto [%d]state", pm_cur_state); + + break; + } + + st = &states[pm_cur_state]; + if (st->action) + st->action(st->timeout); + + if (pm_cur_state == S_LCDOFF) + update_lcdoff_source(VCONFKEY_PM_LCDOFF_BY_TIMEOUT); +} + +static int check_face_detection(int evt, int pm_cur_state, int next_state) +{ + int lock_state = EINA_FALSE; + int state; + + if (cb_timeout_id) { + ecore_timer_del(cb_timeout_id); + cb_timeout_id = NULL; + } + + if (evt == EVENT_INPUT) { + block_state = EINA_TRUE; + return EINA_FALSE; + } + block_state = EINA_FALSE; + + if (evt != EVENT_TIMEOUT) + return EINA_FALSE; + + if (pm_cur_state != S_NORMAL) + return EINA_FALSE; + + if (!get_detection) { + init_smart_lib(); + if (!get_detection) { + _E("%s load failed!", SMART_DETECTION_LIB); + return EINA_FALSE; + } + } + + state = get_detection(detection_callback, SMART_STAY, NULL, (void*)next_state); + + if (state != 0) + _E("get detection FAIL [%d]", state); + else + _I("get detection success"); + + cb_state = EINA_FALSE; + cb_timeout_id = ecore_timer_add(CB_TIMEOUT, + (Ecore_Task_Cb)check_cb_state, (void*)next_state); + return EINA_TRUE; +} + +static void smartstay_init(void *data) +{ + display_info.face_detection = check_face_detection; +} + +static void smartstay_exit(void *data) +{ + if (detect_handle) { + dlclose(detect_handle); + detect_handle = NULL; + _D("detect handle is closed!"); + } + get_detection = NULL; + display_info.face_detection = NULL; +} + +static const struct display_ops display_smartstay_ops = { + .name = "smartstay", + .init = smartstay_init, + .exit = smartstay_exit, +}; + +DISPLAY_OPS_REGISTER(&display_smartstay_ops) + diff --git a/src/display/util.h b/src/display/util.h new file mode 100644 index 0000000..a55f130 --- /dev/null +++ b/src/display/util.h @@ -0,0 +1,48 @@ +/* + * deviced + * + * Copyright (c) 2011 - 2013 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. + */ + + +/** + * @file util.h + * @brief Utilities header for Power manager + */ +#ifndef __DEF_UTIL_H__ +#define __DEF_UTIL_H__ + +/** + * @addtogroup POWER_MANAGER + * @{ + */ +#ifdef ENABLE_DEVICED_DLOG +#define ENABLE_DLOG +#endif + +#ifdef LOG_TAG +#undef LOG_TAG +#endif + +#define LOG_TAG "POWER_MANAGER" +#include "shared/log-macro.h" + +#define SEC_TO_MSEC(x) ((x)*1000) +#define MSEC_TO_SEC(x) ((x)/1000) + +/** + * @} + */ +#endif diff --git a/src/display/weaks.h b/src/display/weaks.h new file mode 100644 index 0000000..88c887d --- /dev/null +++ b/src/display/weaks.h @@ -0,0 +1,39 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 __DISPLAY_WEAKS_H__ +#define __DISPLAY_WEAKS_H__ + +#include "core/common.h" + +/* src/display/hbm.c */ +int __WEAK__ hbm_get_state(void); +int __WEAK__ hbm_set_state(int); +int __WEAK__ hbm_set_state_with_timeout(int, int); +void __WEAK__ hbm_check_timeout(void); + +/* src/display/brightness.c */ +int __WEAK__ control_brightness_key(int action); + +/* src/display/alpm.c */ +int __WEAK__ alpm_set_state(int); +int __WEAK__ set_alpm_screen(char *); + +#endif + diff --git a/src/display/x-lcd-on.c b/src/display/x-lcd-on.c new file mode 100644 index 0000000..807b6b3 --- /dev/null +++ b/src/display/x-lcd-on.c @@ -0,0 +1,65 @@ +/* + * deviced + * + * Copyright (c) 2011 - 2013 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. + * +*/ + + +#ifndef __PM_X_LCD_ONOFF_C__ +#define __PM_X_LCD_ONOFF_C__ + +#include +#include +#include + +#include "core/log.h" +#include "core/common.h" + +#define CMD_ON "on" +#define CMD_OFF "off" +#define CMD_STANDBY "standby" + +static const char *xset_arg[] = { + "/usr/bin/xset", + "dpms", "force", NULL, NULL, +}; + +static int pm_x_set_lcd_backlight(struct _PMSys *p, int on) +{ + pid_t pid; + char cmd_line[8]; + int argc; + + _D("Backlight on=%d", on); + + switch (on) { + case STATUS_ON: + snprintf(cmd_line, sizeof(cmd_line), "%s", CMD_ON); + break; + case STATUS_OFF: + snprintf(cmd_line, sizeof(cmd_line), "%s", CMD_OFF); + break; + case STATUS_STANDBY: + snprintf(cmd_line, sizeof(cmd_line), "%s", CMD_STANDBY); + break; + } + + argc = ARRAY_SIZE(xset_arg); + xset_arg[argc - 2] = cmd_line; + return run_child(argc, xset_arg); +} + +#endif /*__PM_X_LCD_ONOFF_C__ */ diff --git a/src/extcon/extcon.c b/src/extcon/extcon.c new file mode 100644 index 0000000..5296bd6 --- /dev/null +++ b/src/extcon/extcon.c @@ -0,0 +1,111 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 "core/log.h" +#include "core/edbus-handler.h" +#include "core/devices.h" + +static DBusMessage *dbus_get_usb_id(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int val, ret; + + ret = device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_USB_ID, &val); + if (ret >= 0) + ret = val; + + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *dbus_get_muic_adc_enable(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int val, ret; + + ret = device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_MUIC_ADC_ENABLE, &val); + if (ret >= 0) + ret = val; + + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *dbus_set_muic_adc_enable(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int val, ret; + + if (!dbus_message_get_args(msg, NULL, + DBUS_TYPE_INT32, &val, DBUS_TYPE_INVALID)) { + _E("there is no message"); + ret = -EINVAL; + goto out; + } + + ret = device_set_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_MUIC_ADC_ENABLE, val); + +out: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; + +} + +static const struct edbus_method edbus_methods[] = { + { "GetUsbId", NULL, "i", dbus_get_usb_id }, + { "GetMuicAdcEnable", NULL, "i", dbus_get_muic_adc_enable }, + { "SetMuicAdcEnable", "i", "i", dbus_set_muic_adc_enable }, +}; + +static void extcon_init(void *data) +{ + int ret, otg_mode = 0; + + ret = register_edbus_method(DEVICED_PATH_EXTCON, edbus_methods, ARRAY_SIZE(edbus_methods)); + if (ret < 0) + _E("fail to init edbus method(%d)", ret); + + if (vconf_get_bool(VCONFKEY_SETAPPL_USB_OTG_MODE, &otg_mode) < 0) + _E("failed to get VCONFKEY_SETAPPL_USB_OTG_MODE"); + + /* if otg_mode key is on, deviced turns on the otg_mode */ + if (otg_mode) + device_set_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_MUIC_ADC_ENABLE, otg_mode); +} + +static const struct device_ops extcon_device_ops = { + .priority = DEVICE_PRIORITY_NORMAL, + .name = "extcon", + .init = extcon_init, +}; + +DEVICE_OPS_REGISTER(&extcon_device_ops) diff --git a/src/hall/hall-handler.c b/src/hall/hall-handler.c new file mode 100644 index 0000000..ef83327 --- /dev/null +++ b/src/hall/hall-handler.c @@ -0,0 +1,162 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "core/log.h" +#include "core/data.h" +#include "core/common.h" +#include "core/devices.h" +#include "core/device-notifier.h" +#include "core/edbus-handler.h" +#include "hall-handler.h" + +#define SIGNAL_HALL_STATE "ChangeState" + +static int hall_ic_status = HALL_IC_OPENED; + +static int hall_ic_get_status(void) +{ + return hall_ic_status; +} + +static void hall_ic_chgdet_cb(struct main_data *ad) +{ + int val = -1; + int fd, r, ret; + char buf[2]; + char *arr[1]; + char str_status[32]; + + fd = open(HALL_IC_STATUS, O_RDONLY); + if (fd == -1) { + _E("%s open error: %s", HALL_IC_STATUS, strerror(errno)); + return; + } + r = read(fd, buf, 1); + close(fd); + if (r != 1) { + _E("fail to get hall status %d", r); + return; + } + + buf[1] = '\0'; + + hall_ic_status = atoi(buf); + _I("cover is opened(%d)", hall_ic_status); + + device_notify(DEVICE_NOTIFIER_HALLIC_OPEN, (void *)hall_ic_status); + + snprintf(str_status, sizeof(str_status), "%d", hall_ic_status); + arr[0] = str_status; + + broadcast_edbus_signal(DEVICED_PATH_HALL, DEVICED_INTERFACE_HALL, + SIGNAL_HALL_STATE, "i", arr); + + /* Set touch screen flip mode when cover is closed */ + ret = device_set_property(DEVICE_TYPE_TOUCH, + PROP_TOUCH_SCREEN_FLIP_MODE, (hall_ic_status ? 0 : 1)); + if (ret < 0) + _E("Failed to set touch screen flip mode!"); + + /* Set touch key flip mode when cover is closed */ + ret = device_set_property(DEVICE_TYPE_TOUCH, + PROP_TOUCH_KEY_FLIP_MODE, (hall_ic_status ? 0 : 1)); + if (ret < 0) + _E("Failed to set touch key flip mode!"); + +} + +static int hall_action(int argc, char **argv) +{ + int i; + int pid; + int prop; + + if (strncmp(argv[0], HALL_IC_NAME, strlen(HALL_IC_NAME)) == 0) + hall_ic_chgdet_cb(NULL); + return 0; +} + +static void hall_edbus_signal_handler(void *data, DBusMessage *msg) +{ + _D("hall_edbus_signal_handler occurs!!!"); +} + +static DBusMessage *edbus_getstatus_cb(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int val, ret; + + ret = device_get_property(DEVICE_TYPE_HALL, PROP_HALL_STATUS, &val); + if (ret >= 0) + ret = val; + + _D("get hall status %d, %d", val, ret); + + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static const struct edbus_method edbus_methods[] = { + { "getstatus", NULL, "i", edbus_getstatus_cb }, + /* Add methods here */ +}; + +static void hall_ic_init(void *data) +{ + int ret, val; + + /* init dbus interface */ + ret = register_edbus_method(DEVICED_PATH_HALL, edbus_methods, ARRAY_SIZE(edbus_methods)); + if (ret < 0) + _E("fail to init edbus method(%d)", ret); + + register_action(PREDEF_HALL_IC, hall_action, NULL, NULL); + + register_edbus_signal_handler(DEVICED_PATH_HALL, DEVICED_INTERFACE_HALL, + SIGNAL_HALL_STATE, + hall_edbus_signal_handler); + + if (device_get_property(DEVICE_TYPE_HALL, PROP_HALL_STATUS, &val) >= 0) + hall_ic_status = val; +} + +static const struct device_ops hall_device_ops = { + .priority = DEVICE_PRIORITY_NORMAL, + .name = HALL_IC_NAME, + .init = hall_ic_init, + .status = hall_ic_get_status, +}; + +DEVICE_OPS_REGISTER(&hall_device_ops) diff --git a/src/hall/hall-handler.h b/src/hall/hall-handler.h new file mode 100644 index 0000000..75760b3 --- /dev/null +++ b/src/hall/hall-handler.h @@ -0,0 +1,33 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 __HALL_HANDLER_H__ +#define __HALL_HANDLER_H__ + +#define HALL_IC_CLOSED 0 +#define HALL_IC_OPENED 1 + +#define HALL_IC_SUBSYSTEM "flip" +#define HALL_IC_NAME "hall_ic" +#define HALL_IC_PATH "/devices/virtual/"HALL_IC_SUBSYSTEM"/"HALL_IC_NAME +#define HALL_IC_STATUS "/sys/class/"HALL_IC_SUBSYSTEM"/"HALL_IC_NAME"/cover_status" + +#define PREDEF_HALL_IC HALL_IC_NAME + +#endif //__HALL_HANDLER_H__ diff --git a/src/haptic/HW_touch_30ms_sharp.ivt b/src/haptic/HW_touch_30ms_sharp.ivt new file mode 100755 index 0000000000000000000000000000000000000000..97c7978ce605cde44a2931f215e9ce52c3e707f3 GIT binary patch literal 38 qcmZQ%U}WH85Mf|oP+(+WsAph!#K7RokjRkE5X?}{kP3taKsf+MJp{Y} literal 0 HcmV?d00001 diff --git a/src/haptic/emulator.c b/src/haptic/emulator.c new file mode 100644 index 0000000..b6adad9 --- /dev/null +++ b/src/haptic/emulator.c @@ -0,0 +1,148 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 "haptic.h" + +#define DEFAULT_HAPTIC_HANDLE 0xFFFF +#define DEFAULT_EFFECT_HANDLE 0xFFFA + +/* START: Haptic Module APIs */ +static int get_device_count(int *count) +{ + if (count) + *count = 1; + + return 0; +} + +static int open_device(int device_index, int *device_handle) +{ + if (device_handle) + *device_handle = DEFAULT_HAPTIC_HANDLE; + + return 0; +} + +static int close_device(int device_handle) +{ + if (device_handle != DEFAULT_HAPTIC_HANDLE) + return -EINVAL; + + return 0; +} + +static int vibrate_monotone(int device_handle, int duration, int feedback, int priority, int *effect_handle) +{ + if (device_handle != DEFAULT_HAPTIC_HANDLE) + return -EINVAL; + + if (effect_handle) + *effect_handle = DEFAULT_EFFECT_HANDLE; + + return 0; +} + +static int vibrate_buffer(int device_handle, const unsigned char *vibe_buffer, int iteration, int feedback, int priority, int *effect_handle) +{ + if (device_handle != DEFAULT_HAPTIC_HANDLE) + return -EINVAL; + + if (effect_handle) + *effect_handle = DEFAULT_EFFECT_HANDLE; + + return 0; +} + +static int stop_device(int device_handle) +{ + if (device_handle != DEFAULT_HAPTIC_HANDLE) + return -EINVAL; + + return 0; +} + +static int get_device_state(int device_index, int *effect_state) +{ + if (effect_state) + *effect_state = 0; + + return 0; +} + +static int create_effect(unsigned char *vibe_buffer, int max_bufsize, haptic_module_effect_element *elem_arr, int max_elemcnt) +{ + _E("Not support feature"); + return -EACCES; +} + +static int get_buffer_duration(int device_handle, const unsigned char *vibe_buffer, int *buffer_duration) +{ + if (device_handle != DEFAULT_HAPTIC_HANDLE) + return -EINVAL; + + _E("Not support feature"); + return -EACCES; +} + +static int convert_binary(const unsigned char *vibe_buffer, int max_bufsize, const char *file_path) +{ + _E("Not support feature"); + return -EACCES; +} +/* END: Haptic Module APIs */ + +static const struct haptic_plugin_ops default_plugin = { + .get_device_count = get_device_count, + .open_device = open_device, + .close_device = close_device, + .vibrate_monotone = vibrate_monotone, + .vibrate_buffer = vibrate_buffer, + .stop_device = stop_device, + .get_device_state = get_device_state, + .create_effect = create_effect, + .get_buffer_duration = get_buffer_duration, + .convert_binary = convert_binary, +}; + +static bool is_valid(void) +{ +#ifdef EMULATOR + _I("Support emulator haptic device"); + return true; +#else + _E("Do not support emulator haptic device"); + return false; +#endif +} + +static const struct haptic_plugin_ops *load(void) +{ + return &default_plugin; +} + +static const struct haptic_ops emul_ops = { + .is_valid = is_valid, + .load = load, +}; + +HAPTIC_OPS_REGISTER(&emul_ops) diff --git a/src/haptic/external.c b/src/haptic/external.c new file mode 100644 index 0000000..f0be7f7 --- /dev/null +++ b/src/haptic/external.c @@ -0,0 +1,98 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include +#include +#include +#include +#include +#include + +#include "core/log.h" +#include "haptic.h" + +#define HAPTIC_MODULE_PATH "/usr/lib/libhaptic-module.so" + +/* Haptic Plugin Interface */ +static void *dlopen_handle; +static const struct haptic_plugin_ops *plugin_intf; + +static bool is_valid(void) +{ + struct stat buf; + const struct haptic_plugin_ops *(*get_haptic_plugin_interface) () = NULL; + + if (stat(HAPTIC_MODULE_PATH, &buf)) { + _E("file(%s) is not presents", HAPTIC_MODULE_PATH); + goto error; + } + + dlopen_handle = dlopen(HAPTIC_MODULE_PATH, RTLD_NOW); + if (!dlopen_handle) { + _E("dlopen failed: %s", dlerror()); + goto error; + } + + get_haptic_plugin_interface = dlsym(dlopen_handle, "get_haptic_plugin_interface"); + if (!get_haptic_plugin_interface) { + _E("dlsym failed : %s", dlerror()); + goto error; + } + + plugin_intf = get_haptic_plugin_interface(); + if (!plugin_intf) { + _E("get_haptic_plugin_interface() failed"); + goto error; + } + + _I("Support external haptic device"); + return true; + +error: + if (dlopen_handle) { + dlclose(dlopen_handle); + dlopen_handle = NULL; + } + + _I("Do not support external haptic device"); + return false; +} + +static const struct haptic_plugin_ops *load(void) +{ + return plugin_intf; +} + +static void release(void) +{ + if (dlopen_handle) { + dlclose(dlopen_handle); + dlopen_handle = NULL; + } + + plugin_intf = NULL; +} + +static const struct haptic_ops ext_ops = { + .is_valid = is_valid, + .load = load, + .release = release, +}; + +HAPTIC_OPS_REGISTER(&ext_ops) diff --git a/src/haptic/haptic.c b/src/haptic/haptic.c new file mode 100644 index 0000000..a211e41 --- /dev/null +++ b/src/haptic/haptic.c @@ -0,0 +1,624 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 "core/log.h" +#include "core/list.h" +#include "core/common.h" +#include "core/devices.h" +#include "core/edbus-handler.h" +#include "core/device-notifier.h" +#include "haptic.h" + +#ifndef DATADIR +#define DATADIR "/usr/share/deviced" +#endif + +/* hardkey vibration variable */ +#define HARDKEY_VIB_RESOURCE DATADIR"/HW_touch_30ms_sharp.ivt" +#define HARDKEY_VIB_ITERATION 1 +#define HARDKEY_VIB_FEEDBACK 3 +#define HARDKEY_VIB_PRIORITY 2 +#define HAPTIC_FEEDBACK_STEP 20 + +/* power on, power off vibration variable */ +#define POWER_ON_VIB_DURATION 300 +#define POWER_OFF_VIB_DURATION 300 +#define POWER_VIB_FEEDBACK 100 + +#define MAX_EFFECT_BUFFER (64*1024) + +#define RETRY_CNT 3 + +#define CHECK_VALID_OPS(ops, r) ((ops) ? true : !(r = -ENODEV)) + +/* for playing */ +static int g_handle; + +/* haptic operation variable */ +static dd_list *h_head; +static const struct haptic_plugin_ops *h_ops; +static bool haptic_disabled; + +static int haptic_start(void); +static int haptic_stop(void); +static int haptic_internal_init(void); + +void add_haptic(const struct haptic_ops *ops) +{ + DD_LIST_APPEND(h_head, (void*)ops); +} + +void remove_haptic(const struct haptic_ops *ops) +{ + DD_LIST_REMOVE(h_head, (void*)ops); +} + +static int haptic_module_load(void) +{ + struct haptic_ops *ops; + dd_list *elem; + int r; + + /* find valid plugin */ + DD_LIST_FOREACH(h_head, elem, ops) { + if (ops->is_valid && ops->is_valid()) { + if (ops->load) + h_ops = ops->load(); + break; + } + } + + if (!CHECK_VALID_OPS(h_ops, r)) { + _E("Can't find the valid haptic device"); + return r; + } + + /* solution bug + we do not use internal vibration except power off + but module does not stop vibrating, although called terminate function */ + haptic_internal_init(); + + return 0; +} + +static DBusMessage *edbus_get_count(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int ret, val; + + if (!CHECK_VALID_OPS(h_ops, ret)) + goto exit; + + ret = h_ops->get_device_count(&val); + if (ret >= 0) + ret = val; + +exit: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *edbus_open_device(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int index, handle, ret; + + if (!CHECK_VALID_OPS(h_ops, ret)) + goto exit; + + if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_INT32, &index, DBUS_TYPE_INVALID)) { + ret = -EINVAL; + goto exit; + } + + ret = h_ops->open_device(index, &handle); + if (ret >= 0) + ret = handle; + +exit: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *edbus_close_device(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + unsigned int handle; + int ret; + + if (!CHECK_VALID_OPS(h_ops, ret)) + goto exit; + + if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_UINT32, &handle, DBUS_TYPE_INVALID)) { + ret = -EINVAL; + goto exit; + } + + ret = h_ops->close_device(handle); + +exit: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *edbus_vibrate_monotone(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + unsigned int handle; + int duration, level, priority, e_handle, ret; + + if (!CHECK_VALID_OPS(h_ops, ret)) + goto exit; + + if (haptic_disabled) { + ret = -EACCES; + goto exit; + } + + if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_UINT32, &handle, + DBUS_TYPE_INT32, &duration, + DBUS_TYPE_INT32, &level, + DBUS_TYPE_INT32, &priority, DBUS_TYPE_INVALID)) { + ret = -EINVAL; + goto exit; + } + + ret = h_ops->vibrate_monotone(handle, duration, level, priority, &e_handle); + if (ret >= 0) + ret = e_handle; + +exit: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; + +} + +static DBusMessage *edbus_vibrate_buffer(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + unsigned int handle; + unsigned char *data; + int size, iteration, level, priority, e_handle, ret; + + if (!CHECK_VALID_OPS(h_ops, ret)) + goto exit; + + if (haptic_disabled) { + ret = -EACCES; + goto exit; + } + + if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_UINT32, &handle, + DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &data, &size, + DBUS_TYPE_INT32, &iteration, + DBUS_TYPE_INT32, &level, + DBUS_TYPE_INT32, &priority, DBUS_TYPE_INVALID)) { + ret = -EINVAL; + goto exit; + } + + ret = h_ops->vibrate_buffer(handle, data, iteration, level, priority, &e_handle); + if (ret >= 0) + ret = e_handle; + +exit: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *edbus_stop_device(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + unsigned int handle; + int ret; + + if (!CHECK_VALID_OPS(h_ops, ret)) + goto exit; + + if (haptic_disabled) { + ret = -EACCES; + goto exit; + } + + if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_UINT32, &handle, DBUS_TYPE_INVALID)) { + ret = -EINVAL; + goto exit; + } + + ret = h_ops->stop_device(handle); + +exit: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *edbus_get_state(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int index, state, ret; + + if (!CHECK_VALID_OPS(h_ops, ret)) + goto exit; + + if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_INT32, &index, DBUS_TYPE_INVALID)) { + ret = -EINVAL; + goto exit; + } + + ret = h_ops->get_device_state(index, &state); + if (ret >= 0) + ret = state; + +exit: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *edbus_create_effect(E_DBus_Object *obj, DBusMessage *msg) +{ + static unsigned char data[MAX_EFFECT_BUFFER]; + static unsigned char *p = data; + DBusMessageIter iter, arr; + DBusMessage *reply; + haptic_module_effect_element *elem_arr; + int i, size, cnt, ret, bufsize = sizeof(data); + + if (!CHECK_VALID_OPS(h_ops, ret)) + goto exit; + + if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_INT32, &bufsize, + DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &elem_arr, &size, + DBUS_TYPE_INT32, &cnt, DBUS_TYPE_INVALID)) { + ret = -EINVAL; + goto exit; + } + + if (bufsize > MAX_EFFECT_BUFFER) { + ret = -ENOMEM; + goto exit; + } + + for (i = 0; i < cnt; ++i) + _D("[%2d] %d %d", i, elem_arr[i].haptic_duration, elem_arr[i].haptic_level); + + memset(data, 0, MAX_EFFECT_BUFFER); + ret = h_ops->create_effect(data, bufsize, elem_arr, cnt); + +exit: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE_AS_STRING, &arr); + dbus_message_iter_append_fixed_array(&arr, DBUS_TYPE_BYTE, &p, bufsize); + dbus_message_iter_close_container(&iter, &arr); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *edbus_get_duration(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + unsigned int handle; + unsigned char *data; + int size, duration, ret; + + if (!CHECK_VALID_OPS(h_ops, ret)) + goto exit; + + if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_UINT32, &handle, + DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &data, &size, + DBUS_TYPE_INVALID)) { + ret = -EINVAL; + goto exit; + } + + ret = h_ops->get_buffer_duration(handle, data, &duration); + if (ret >= 0) + ret = duration; + +exit: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *edbus_save_binary(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + unsigned char *data; + unsigned char *path; + int size, ret; + + if (!CHECK_VALID_OPS(h_ops, ret)) + goto exit; + + if (!dbus_message_get_args(msg, NULL, + DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &data, &size, + DBUS_TYPE_STRING, &path, DBUS_TYPE_INVALID)) { + ret = -EINVAL; + goto exit; + } + + _D("file path : %s", path); + ret = h_ops->convert_binary(data, size, path); + +exit: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static unsigned char* convert_file_to_buffer(const char *file_name, int *size) +{ + FILE *pf; + long file_size; + unsigned char *pdata = NULL; + + if (!file_name) + return NULL; + + /* Get File Stream Pointer */ + pf = fopen(file_name, "rb"); + if (!pf) { + _E("fopen failed : %s", strerror(errno)); + return NULL; + } + + if (fseek(pf, 0, SEEK_END)) + goto error; + + file_size = ftell(pf); + if (fseek(pf, 0, SEEK_SET)) + goto error; + + if (file_size < 0) + goto error; + + pdata = (unsigned char*)malloc(file_size); + if (!pdata) + goto error; + + if (fread(pdata, 1, file_size, pf) != file_size) + goto err_free; + + fclose(pf); + *size = file_size; + return pdata; + +err_free: + free(pdata); + +error: + fclose(pf); + + _E("failed to convert file to buffer (%s)", strerror(errno)); + return NULL; +} + +static int haptic_internal_init(void) +{ + int r; + if (!CHECK_VALID_OPS(h_ops, r)) + return r; + return h_ops->open_device(HAPTIC_MODULE_DEVICE_ALL, &g_handle); +} + +static int haptic_internal_exit(void) +{ + int r; + if (!CHECK_VALID_OPS(h_ops, r)) + return r; + return h_ops->close_device(g_handle); +} + +static int haptic_booting_done_cb(void *data) +{ + return haptic_module_load(); +} + +static int haptic_hardkey_changed_cb(void *data) +{ + int size, level, status, e_handle, ret, cnt = RETRY_CNT; + unsigned char *buf; + + while (!CHECK_VALID_OPS(h_ops, ret) && cnt--) { + haptic_module_load(); + if (!cnt) + return ret; + } + + if (!g_handle) + haptic_internal_init(); + + if (vconf_get_bool(VCONFKEY_SETAPPL_HAPTIC_FEEDBACK_STATUS_BOOL, &status) < 0) { + _E("fail to get VCONFKEY_SETAPPL_HAPTIC_FEEDBACK_STATUS_BOOL"); + status = 1; + } + + /* when turn off haptic feedback option */ + if (!status) + return 0; + + buf = convert_file_to_buffer(HARDKEY_VIB_RESOURCE, &size); + if (!buf) + return -1; + + ret = vconf_get_int(VCONFKEY_SETAPPL_TOUCH_FEEDBACK_VIBRATION_LEVEL_INT, &level); + if (ret < 0) { + _E("fail to get VCONFKEY_SETAPPL_TOUCH_FEEDBACK_VIBRATION_LEVEL_INT"); + level = HARDKEY_VIB_FEEDBACK; + } + + ret = h_ops->vibrate_buffer(g_handle, buf, HARDKEY_VIB_ITERATION, + level*HAPTIC_FEEDBACK_STEP, HARDKEY_VIB_PRIORITY, &e_handle); + if (ret < 0) + _E("fail to vibrate buffer : %d", ret); + + free(buf); + return ret; +} + +static int haptic_poweroff_cb(void *data) +{ + int e_handle, ret, cnt = RETRY_CNT; + + while (!CHECK_VALID_OPS(h_ops, ret) && cnt--) { + haptic_module_load(); + if (!cnt) + return ret; + } + + if (!g_handle) + haptic_internal_init(); + + /* power off vibration */ + ret = h_ops->vibrate_monotone(g_handle, POWER_OFF_VIB_DURATION, + POWER_VIB_FEEDBACK, HARDKEY_VIB_PRIORITY, &e_handle); + if (ret < 0) { + _E("fail to vibrate_monotone : %d", ret); + return ret; + } + + /* sleep for vibration */ + usleep(POWER_OFF_VIB_DURATION*1000); + return 0; +} + +static int haptic_powersaver_cb(void *data) +{ + int powersaver_on = (int)data; + + if (powersaver_on) + haptic_stop(); + else + haptic_start(); + + return 0; +} + +static const struct edbus_method edbus_methods[] = { + { "GetCount", NULL, "i", edbus_get_count }, + { "OpenDevice", "i", "i", edbus_open_device }, + { "CloseDevice", "u", "i", edbus_close_device }, + { "StopDevice", "u", "i", edbus_stop_device }, + { "VibrateMonotone", "uiii", "i", edbus_vibrate_monotone }, + { "VibrateBuffer", "uayiii", "i", edbus_vibrate_buffer }, + { "GetState", "i", "i", edbus_get_state }, + { "GetDuration", "uay", "i", edbus_get_duration }, + { "CreateEffect", "iayi", "ayi", edbus_create_effect }, + { "SaveBinary", "ays", "i", edbus_save_binary }, + /* Add methods here */ +}; + +static void haptic_init(void *data) +{ + int r; + + /* init dbus interface */ + r = register_edbus_method(DEVICED_PATH_HAPTIC, edbus_methods, ARRAY_SIZE(edbus_methods)); + if (r < 0) + _E("fail to init edbus method(%d)", r); + + /* register notifier for below each event */ + register_notifier(DEVICE_NOTIFIER_BOOTING_DONE, haptic_booting_done_cb); + register_notifier(DEVICE_NOTIFIER_TOUCH_HARDKEY, haptic_hardkey_changed_cb); + register_notifier(DEVICE_NOTIFIER_POWEROFF_HAPTIC, haptic_poweroff_cb); + register_notifier(DEVICE_NOTIFIER_POWERSAVER, haptic_powersaver_cb); +} + +static void haptic_exit(void *data) +{ + struct haptic_ops *ops; + dd_list *elem; + int r; + + /* unregister notifier for below each event */ + unregister_notifier(DEVICE_NOTIFIER_BOOTING_DONE, haptic_booting_done_cb); + unregister_notifier(DEVICE_NOTIFIER_TOUCH_HARDKEY, haptic_hardkey_changed_cb); + unregister_notifier(DEVICE_NOTIFIER_POWEROFF_HAPTIC, haptic_poweroff_cb); + unregister_notifier(DEVICE_NOTIFIER_POWERSAVER, haptic_powersaver_cb); + + if (!CHECK_VALID_OPS(h_ops, r)) + return; + + /* haptic exit for deviced */ + haptic_internal_exit(); + + /* release plugin */ + DD_LIST_FOREACH(h_head, elem, ops) { + if (ops->is_valid && ops->is_valid()) { + if (ops->release) + ops->release(); + h_ops = NULL; + break; + } + } +} + +static int haptic_start(void) +{ + _I("start"); + haptic_disabled = false; + return 0; +} + +static int haptic_stop(void) +{ + _I("stop"); + haptic_disabled = true; + return 0; +} + +static const struct device_ops haptic_device_ops = { + .priority = DEVICE_PRIORITY_NORMAL, + .name = "haptic", + .init = haptic_init, + .exit = haptic_exit, +}; + +DEVICE_OPS_REGISTER(&haptic_device_ops) diff --git a/src/haptic/haptic.h b/src/haptic/haptic.h new file mode 100644 index 0000000..dfda5d3 --- /dev/null +++ b/src/haptic/haptic.h @@ -0,0 +1,46 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 __HAPTIC_H__ +#define __HAPTIC_H__ + +#include +#include "core/common.h" +#include "haptic-plugin-intf.h" + +#define HAPTIC_OPS_REGISTER(dev) \ +static void __CONSTRUCTOR__ module_init(void) \ +{ \ + add_haptic(dev); \ +} \ +static void __DESTRUCTOR__ module_exit(void) \ +{ \ + remove_haptic(dev); \ +} + +struct haptic_ops { + bool (*is_valid)(void); + const struct haptic_plugin_ops *(*load)(void); + void (*release)(void); +}; + +void add_haptic(const struct haptic_ops *ops); +void remove_haptic(const struct haptic_ops *ops); + +#endif /* __HAPTIC_H__ */ diff --git a/src/haptic/standard.c b/src/haptic/standard.c new file mode 100644 index 0000000..35e0666 --- /dev/null +++ b/src/haptic/standard.c @@ -0,0 +1,367 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "core/log.h" +#include "haptic.h" + +#define DEFAULT_HAPTIC_HANDLE 0xFFFF +#define MAX_MAGNITUDE 0xFFFF +#define PERIODIC_MAX_MAGNITUDE 0x7FFF /* 0.5 * MAX_MAGNITUDE */ + +#define DEV_INPUT "/dev/input" +#define EVENT "event" + +#define BITS_PER_LONG (sizeof(long) * 8) +#define OFF(x) ((x)%BITS_PER_LONG) +#define BIT(x) (1UL<> OFF(bit)) & 1) + +static struct ff_effect ff_effect; +static char ff_path[PATH_MAX]; +static int ff_use_count; +static int ff_fd; +static Ecore_Timer *timer; + +static int ff_stop(int fd); +static Eina_Bool timer_cb(void *data) +{ + /* stop previous vibration */ + ff_stop(ff_fd); + _I("stop vibration by timer"); + + return ECORE_CALLBACK_CANCEL; +} + +static int register_timer(int ms) +{ + /* add new timer */ + timer = ecore_timer_add(ms/1000.f, timer_cb, NULL); + if (!timer) + return -EPERM; + + return 0; +} + +static int unregister_timer(void) +{ + if (timer) { + ecore_timer_del(timer); + timer = NULL; + } + + return 0; +} + +static int ff_find_device(char *path, int size) +{ + DIR *dir; + struct dirent *dent; + char ev_path[PATH_MAX]; + unsigned long features[1+FF_MAX/sizeof(unsigned long)]; + int fd, ret; + + dir = opendir(DEV_INPUT); + if (!dir) + return -errno; + + while ((dent = readdir(dir))) { + if (dent->d_type == DT_DIR || + !strstr(dent->d_name, "event")) + continue; + + snprintf(ev_path, sizeof(ev_path), "%s/%s", DEV_INPUT, dent->d_name); + + fd = open(ev_path, O_RDWR); + if (fd < 0) + continue; + + /* get force feedback device */ + memset(features, 0, sizeof(features)); + ret = ioctl(fd, EVIOCGBIT(EV_FF, sizeof(features)), features); + if (ret == -1) { + close(fd); + continue; + } + + if (test_bit(FF_CONSTANT, features)) + _D("%s type : constant", ev_path); + if (test_bit(FF_PERIODIC, features)) + _D("%s type : periodic", ev_path); + if (test_bit(FF_SPRING, features)) + _D("%s type : spring", ev_path); + if (test_bit(FF_FRICTION, features)) + _D("%s type : friction", ev_path); + if (test_bit(FF_RUMBLE, features)) + _D("%s type : rumble", ev_path); + + if (test_bit(FF_PERIODIC, features)) { + memcpy(ff_path, ev_path, strlen(ev_path)); + close(fd); + closedir(dir); + return 0; + } + + close(fd); + } + + closedir(dir); + return -1; +} + +static int ff_play(int fd, int length, int level) +{ + struct input_event play; + int r = 0; + double magnitude; + + if (fd < 0) + return -EINVAL; + + /* unregister existing timer */ + unregister_timer(); + + magnitude = (double)level/HAPTIC_MODULE_FEEDBACK_MAX; + magnitude *= PERIODIC_MAX_MAGNITUDE; + + _I("info : magnitude(%d) length(%d)", (int)magnitude, length); + + /* Set member variables in effect struct */ + ff_effect.type = FF_PERIODIC; + if (!ff_effect.id) + ff_effect.id = -1; + ff_effect.u.periodic.waveform = FF_SQUARE; + ff_effect.u.periodic.period = 0.1*0x100; /* 0.1 second */ + ff_effect.u.periodic.magnitude = (int)magnitude; + ff_effect.u.periodic.offset = 0; + ff_effect.u.periodic.phase = 0; + ff_effect.direction = 0x4000; /* Along X axis */ + ff_effect.u.periodic.envelope.attack_length = 0; + ff_effect.u.periodic.envelope.attack_level = 0; + ff_effect.u.periodic.envelope.fade_length = 0; + ff_effect.u.periodic.envelope.fade_level = 0; + ff_effect.trigger.button = 0; + ff_effect.trigger.interval = 0; + ff_effect.replay.length = length; + ff_effect.replay.delay = 0; + + if (ioctl(fd, EVIOCSFF, &ff_effect) == -1) { + /* workaround: if effect is erased, try one more */ + ff_effect.id = -1; + if (ioctl(fd, EVIOCSFF, &ff_effect) == -1) + return -errno; + } + + /* Play vibration*/ + play.type = EV_FF; + play.code = ff_effect.id; + play.value = 1; /* 1 : PLAY, 0 : STOP */ + + if (write(fd, (const void*)&play, sizeof(play)) == -1) + return -errno; + + /* register timer */ + register_timer(length); + + return 0; +} + +static int ff_stop(int fd) +{ + struct input_event stop; + int r = 0; + + if (fd < 0) + return -EINVAL; + + /* Stop vibration */ + stop.type = EV_FF; + stop.code = ff_effect.id; + stop.value = 0; + + if (write(fd, (const void*)&stop, sizeof(stop)) == -1) + return -errno; + + return 0; +} + +/* START: Haptic Module APIs */ +static int get_device_count(int *count) +{ + if (count) + *count = 1; + + return 0; +} + +static int open_device(int device_index, int *device_handle) +{ + /* open ff driver */ + if (ff_use_count == 0) { + ff_fd = open(ff_path, O_RDWR); + if (!ff_fd) { + _E("Failed to open %s : %s", ff_path, strerror(errno)); + return -errno; + } + } + + /* Increase handle count */ + ff_use_count++; + + if (device_handle) + *device_handle = DEFAULT_HAPTIC_HANDLE; + + return 0; +} + +static int close_device(int device_handle) +{ + if (device_handle != DEFAULT_HAPTIC_HANDLE) + return -EINVAL; + + if (ff_use_count == 0) + return -EPERM; + + ff_stop(ff_fd); + + /* Decrease handle count */ + ff_use_count--; + + /* close ff driver */ + if (ff_use_count == 0) { + /* Initialize effect structure */ + memset(&ff_effect, 0, sizeof(ff_effect)); + close(ff_fd); + ff_fd = -1; + } + + return 0; +} + +static int vibrate_monotone(int device_handle, int duration, int feedback, int priority, int *effect_handle) +{ + if (device_handle != DEFAULT_HAPTIC_HANDLE) + return -EINVAL; + + return ff_play(ff_fd, duration, feedback); +} + +static int vibrate_buffer(int device_handle, const unsigned char *vibe_buffer, int iteration, int feedback, int priority, int *effect_handle) +{ + if (device_handle != DEFAULT_HAPTIC_HANDLE) + return -EINVAL; + + /* temporary code */ + return ff_play(ff_fd, 300, feedback); +} + +static int stop_device(int device_handle) +{ + if (device_handle != DEFAULT_HAPTIC_HANDLE) + return -EINVAL; + + return ff_stop(ff_fd); +} + +static int get_device_state(int device_index, int *effect_state) +{ + int status; + + if (ff_effect.id != 0) + status = 1; + else + status = 0; + + if (effect_state) + *effect_state = status; + + return 0; +} + +static int create_effect(unsigned char *vibe_buffer, int max_bufsize, haptic_module_effect_element *elem_arr, int max_elemcnt) +{ + _E("Not support feature"); + return -EACCES; +} + +static int get_buffer_duration(int device_handle, const unsigned char *vibe_buffer, int *buffer_duration) +{ + if (device_handle != DEFAULT_HAPTIC_HANDLE) + return -EINVAL; + + _E("Not support feature"); + return -EACCES; +} + +static int convert_binary(const unsigned char *vibe_buffer, int max_bufsize, const char *file_path) +{ + _E("Not support feature"); + return -EACCES; +} +/* END: Haptic Module APIs */ + +static const struct haptic_plugin_ops default_plugin = { + .get_device_count = get_device_count, + .open_device = open_device, + .close_device = close_device, + .vibrate_monotone = vibrate_monotone, + .vibrate_buffer = vibrate_buffer, + .stop_device = stop_device, + .get_device_state = get_device_state, + .create_effect = create_effect, + .get_buffer_duration = get_buffer_duration, + .convert_binary = convert_binary, +}; + +static bool is_valid(void) +{ + int ret; + + ret = ff_find_device(ff_path, sizeof(ff_path)); + + if (ret < 0) + return false; + + return true; +} + +static const struct haptic_plugin_ops *load(void) +{ + return &default_plugin; +} + +static const struct haptic_ops std_ops = { + .is_valid = is_valid, + .load = load, +}; + +HAPTIC_OPS_REGISTER(&std_ops) diff --git a/src/led/ir.c b/src/led/ir.c new file mode 100644 index 0000000..86f1767 --- /dev/null +++ b/src/led/ir.c @@ -0,0 +1,73 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 "core/log.h" +#include "core/edbus-handler.h" +#include "core/devices.h" + +static DBusMessage *edbus_set_ir_command(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + char *str; + int ret; + + ret = dbus_message_get_args(msg, NULL, + DBUS_TYPE_STRING, &str, DBUS_TYPE_INVALID); + if (!ret) { + _I("there is no message"); + ret = -EINVAL; + goto error; + } + + ret = device_set_property(DEVICE_TYPE_LED, PROP_LED_IR_COMMAND, (int)str); + +error: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static const struct edbus_method edbus_methods[] = { + { "SetIrCommand", "s", "i", edbus_set_ir_command }, + /* Add methods here */ +}; + +static void ir_init(void *data) +{ + int ret; + + /* init dbus interface */ + ret = register_edbus_method(DEVICED_PATH_LED, edbus_methods, ARRAY_SIZE(edbus_methods)); + if (ret < 0) + _E("fail to init edbus method(%d)", ret); +} + +static const struct device_ops irled_device_ops = { + .priority = DEVICE_PRIORITY_NORMAL, + .name = "irled", + .init = ir_init, +}; + +DEVICE_OPS_REGISTER(&irled_device_ops) diff --git a/src/led/led.xml b/src/led/led.xml new file mode 100644 index 0000000..9b908df --- /dev/null +++ b/src/led/led.xml @@ -0,0 +1,41 @@ + + + + led indicator helps to give notification + + 0 + + + + 2 + + + + 2 + + + + 2 + + + + 0 + + + + 1 + + + + 1 + + + + 0 + + + + 1 + + + diff --git a/src/led/noti.c b/src/led/noti.c new file mode 100644 index 0000000..cc17dae --- /dev/null +++ b/src/led/noti.c @@ -0,0 +1,74 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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/edbus-handler.h" + +#define METHOD_TORCH_NOTI_ON "TorchNotiOn" +#define METHOD_TORCH_NOTI_OFF "TorchNotiOff" + +static int noti_h; + +int ongoing_show(void) +{ + int ret, ret_val; + + if (noti_h > 0) { + _D("already ongoing noti show : handle(%d)", noti_h); + return 0; + } + + ret_val = dbus_method_sync(POPUP_BUS_NAME, + POPUP_PATH_LED, + POPUP_INTERFACE_LED, + METHOD_TORCH_NOTI_ON, + NULL, NULL); + + noti_h = ret_val; + _D("insert noti handle : %d", noti_h); + return (ret_val < 0) ? ret_val : 0; +} + +int ongoing_clear(void) +{ + char str_h[32]; + char *arr[1]; + int ret, ret_val; + + if (noti_h <= 0) { + _D("already ongoing noti clear"); + return 0; + } + + snprintf(str_h, sizeof(str_h), "%d", noti_h); + arr[0] = str_h; + + ret_val = dbus_method_sync(POPUP_BUS_NAME, + POPUP_PATH_LED, + POPUP_INTERFACE_LED, + METHOD_TORCH_NOTI_OFF, + "i", arr); + + _D("delete noti handle : %d", noti_h); + noti_h = 0; + return ret_val; +} diff --git a/src/led/pattern.c b/src/led/pattern.c new file mode 100644 index 0000000..cee8b88 --- /dev/null +++ b/src/led/pattern.c @@ -0,0 +1,307 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include +#include +#include +#include +#include +#include +#include + +#include "core/log.h" + +#define SAMPLE_INTERVAL 50 +#define ITERATION_INFINITE 255 + +#define PTHREAD_SELF (pthread_self()) + +enum led_brt { + LED_OFF = 0, + LED_ON, +}; + +static struct led_pattern { + char *buffer; + int len; + int cnt; + int index; +} pattern; + +static pthread_t tid; + +static int led_set_brt(enum led_brt brt) +{ + int ret, val; + + ret = device_get_property(DEVICE_TYPE_LED, PROP_LED_MAX_BRIGHTNESS, &val); + if (ret < 0) + return ret; + + if (brt != LED_OFF) + brt = val; + + ret = device_set_property(DEVICE_TYPE_LED, PROP_LED_BRIGHTNESS, brt); + if (ret < 0) + return ret; + + return 0; +} + +static void clean_up(void *arg) +{ + struct led_pattern *pt = (struct led_pattern*)arg; + int torch_status = 0; + + _D("[%u] Clean up thread", PTHREAD_SELF); + + /* Release memory after use */ + if (pt->buffer) { + free(pt->buffer); + pt->buffer = NULL; + } + + /* Get assistive light status */ + if (vconf_get_bool(VCONFKEY_SETAPPL_ACCESSIBILITY_TORCH_LIGHT, &torch_status) < 0) + _E("[%u] Failed to get VCONFKEY_SETAPPL_ACCESSIBILITY_TORCH_LIGHT value", PTHREAD_SELF); + + /* Restore assistive light */ + if (torch_status) { + _D("[%u] assistive light turns on", PTHREAD_SELF); + led_set_brt(LED_ON); + } else /* For abnormal termination */ + led_set_brt(LED_OFF); + + tid = 0; +} + +static void* play_cb(void *arg) +{ + struct led_pattern *pt = (struct led_pattern*)arg; + int val; + + _D("[%u] Start thread", PTHREAD_SELF); + pthread_cleanup_push(clean_up, arg); + + if (!pt->buffer) + goto error; + + _D("[%u] index(%d), length(%d), repeat count(%d)", PTHREAD_SELF, pt->index, pt->len, pt->cnt); + + /* Play LED accroding to buffer */ + led_set_brt(LED_OFF); + while (pt->cnt) { + /* do not reset index to use exisiting value */ + for ( ; pt->index < pt->len; pt->index++) { + val = (int)(pt->buffer[pt->index] - '0'); + /* Verify buffer data */ + if (val & 0xFE) + break; + + led_set_brt(val); + + /* Sleep time 50*999us = 49.950ms (Vibration unit 50ms) */ + usleep(SAMPLE_INTERVAL*999); + } + + /* reset index */ + pt->index = 0; + + /* Decrease count when play with limit */ + if (pt->cnt != ITERATION_INFINITE) + pt->cnt--; + } + + led_set_brt(LED_OFF); + + /* Sleep 500ms before turning on assistive light */ + usleep(500000); + +error: + pthread_cleanup_pop(1); + + _D("[%u] End thread", PTHREAD_SELF); + pthread_exit((void*)0); +} + +static int create_thread(struct led_pattern *pattern) +{ + int ret; + + if (tid) { + _E("pthread already created"); + return -EEXIST; + } + + ret = pthread_create(&tid, NULL, play_cb, pattern); + if (ret != 0) { + _E("fail to create thread : %s", strerror(errno)); + return -errno; + } + + return 0; +} + +static int cancel_thread(void) +{ + int ret; + void *retval; + + if (!tid) { + _D("pthread not initialized"); + return 0; + } + + ret = pthread_cancel(tid); + if (ret != 0) { + _E("fail to cancel thread(%d) : %s", tid, strerror(errno)); + return -errno; + } + + ret = pthread_join(tid, &retval); + if (ret != 0) { + _E("fail to join thread(%d) : %s", tid, strerror(errno)); + return -errno; + } + + if (retval == PTHREAD_CANCELED) + _D("pthread canceled"); + else + _D("pthread already finished"); + + return 0; +} + +static int detach_thread(void) +{ + int ret; + + if (!tid) { + _D("pthread not initialized"); + return 0; + } + + ret = pthread_detach(tid); + if (ret != 0) { + _E("fail to detach thread(%d) : %s", tid, strerror(errno)); + return ret; + } + + tid = 0; + return 0; +} + +static int load_file(const char *path, char **buffer, int *len) +{ + FILE *fp; + char *buf = NULL; + int l; + + if (!path || !buffer || !len) { + _E("invalid argument"); + return -EINVAL; + } + + /* Open file */ + fp = fopen(path, "rb"); + if (!fp) { + _E("fail to open file(%s) : %s", path, strerror(errno)); + return -errno; + } + + /* Get file length */ + fseek(fp, 0, SEEK_END); + l = ftell(fp); + fseek(fp, 0, SEEK_SET); + + if (l < 0) + goto error; + + buf = malloc(l*sizeof(char)); + if (!buf) { + _E("fail to allocate memory : %s", strerror(errno)); + goto error; + } + + /* Read file contents into buffer */ + if (fread(buf, 1, l, fp) < l) { + _E("fail to read file data : %s", strerror(errno)); + goto error; + } + + /* Close file */ + fclose(fp); + + *buffer = buf; + *len = l; + return 0; + +error: + /* Close file */ + fclose(fp); + + /* Free unnecessary memory */ + free(buf); + return -EPERM; +} + +int play_pattern(const char *path, int cnt) +{ + int ret; + + /* Check if thread already started */ + ret = cancel_thread(); + if (ret < 0) { + _E("fail to cancel thread"); + return ret; + } + + /* Load led file to buffer */ + ret = load_file(path, &(pattern.buffer), &(pattern.len)); + if (ret < 0) { + _E("fail to load file(%s)", path); + return ret; + } + + /* Set the led data */ + pattern.cnt = cnt; + pattern.index = 0; + + /* Create and Execute thread */ + ret = create_thread(&pattern); + if (ret < 0) { + _E("fail to create thread"); + return ret; + } + + return 0; +} + +int stop_pattern(void) +{ + int ret; + + ret = cancel_thread(); + if (ret < 0) { + _E("fail to cancel thread"); + return ret; + } + + return 0; +} diff --git a/src/led/rgb.c b/src/led/rgb.c new file mode 100644 index 0000000..be01dfc --- /dev/null +++ b/src/led/rgb.c @@ -0,0 +1,645 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include +#include +#include +#include +#include +#include + +#include "deviced/dd-led.h" +#include "xml.h" +#include "core/log.h" +#include "core/common.h" +#include "core/edbus-handler.h" +#include "core/devices.h" +#include "core/device-notifier.h" +#include "core/device-handler.h" +#include "display/core.h" + +#define BOOT_ANIMATION_FINISHED 1 + +#define LED_VALUE(high, low) (((high)<<16)|((low)&0xFFFF)) + +#define BG_COLOR 0x00000000 +#define GET_ALPHA(x) (((x)>>24) & 0xFF) +#define GET_RED(x) (((x)>>16) & 0xFF) +#define GET_GREEN(x) (((x)>> 8) & 0xFF) +#define GET_BLUE(x) ((x) & 0xFF) +#define COMBINE_RGB(r,g,b) ((((r) & 0xFF) << 16) | (((g) & 0xFF) << 8) | ((b) & 0xFF)) + +#define SET_WAVE_BIT (0x6 << 24) +#define DUMPMODE_WAITING_TIME 600000 + +enum { + LED_CUSTOM_DUTY_ON = 1 << 0, /* this enum doesn't blink on led */ + LED_CUSTOM_DEFAULT = (LED_CUSTOM_DUTY_ON), +}; + +static bool charging_key; +static bool lowbat_key; +static bool charging_state; +static bool lowbat_state; +static bool full_state; +static bool badbat_state; +static bool ovp_state; +static bool rgb_blocked = false; +static bool rgb_dumpmode = false; +static Ecore_Timer *dumpmode_timer = NULL; +static enum state_t lcd_state = S_NORMAL; + +static int led_prop(int mode, int on, int off, unsigned int color) +{ + struct led_mode *led; + + if (mode < 0 || mode > LED_MODE_MAX) + return -EINVAL; + + led = find_led_data(mode); + if (!led) { + _E("no find data(%d)", mode); + return -EINVAL; + } + + switch (mode) { + case LED_MISSED_NOTI: + case LED_VOICE_RECORDING: + case LED_CUSTOM: + if (on >= 0) + led->data.on = on; + if (off >= 0) + led->data.off = off; + if (color) + led->data.color = color; + break; + default: + /* the others couldn't change any property */ + break; + } + + _D("changed mode(%d) : on(%d), off(%d), color(%x)", + mode, led->data.on, led->data.off, led->data.color); + return 0; +} + +static int led_mode(int mode, bool enable) +{ + struct led_mode *led; + + if (mode < 0 || mode > LED_MODE_MAX) + return -EINVAL; + + led = find_led_data(mode); + if (!led) { + _E("no find data(%d)", mode); + return -EINVAL; + } + + led->state = enable; + return 0; +} + +static int get_led_mode_state(int mode, bool *state) +{ + struct led_mode *led; + + if (mode < 0 || mode > LED_MODE_MAX) + return -EINVAL; + + led = find_led_data(mode); + if (!led) { + _E("no find data(%d)", mode); + return -EINVAL; + } + + if (led->state) + *state = true; + else + *state = false; + return 0; +} + +static unsigned int led_blend(unsigned int before) +{ + unsigned int alpha, alpha_inv; + unsigned char red, grn, blu; + + alpha = GET_ALPHA(before) + 1; + alpha_inv = 256 - alpha; + + red = ((alpha * GET_RED(before) + alpha_inv * GET_RED(BG_COLOR)) >> 8); + grn = ((alpha * GET_GREEN(before) + alpha_inv * GET_GREEN(BG_COLOR)) >> 8); + blu = ((alpha * GET_BLUE(before) + alpha_inv * GET_BLUE(BG_COLOR)) >> 8); + return COMBINE_RGB(red, grn, blu); +} + +static int led_mode_to_device(struct led_mode *led) +{ + int val, color; + + if (led == NULL) + return 0; + + if (rgb_dumpmode) + return 0; + + if (rgb_blocked && led->mode != LED_POWER_OFF && led->mode != LED_OFF) + return 0; + + val = LED_VALUE(led->data.on, led->data.off); + color = led_blend(led->data.color); + + /* if wave status is ON, color should be combined with WAVE_BIT */ + if (led->data.wave) + color |= SET_WAVE_BIT; + + device_set_property(DEVICE_TYPE_LED, PROP_LED_COLOR, color); + device_set_property(DEVICE_TYPE_LED, PROP_LED_BLINK, val); + return 0; +} + +static int led_display_changed_cb(void *data) +{ + struct led_mode *led = NULL; + int val; + + /* store last display condition */ + lcd_state = (enum state_t)data; + + /* charging error state */ + if (badbat_state) + return 0; + + if (lcd_state == S_LCDOFF) + led = get_valid_led_data(); + else if (lcd_state == S_NORMAL || lcd_state == S_LCDDIM) + led = find_led_data(LED_OFF); + + return led_mode_to_device(led); +} + +static int led_charging_changed_cb(void *data) +{ + int v = (int)data; + + if (v == CHARGER_CHARGING) + charging_state = true; + else + charging_state = false; + + if (charging_key) + led_mode(LED_CHARGING, charging_state); + + return 0; +} + +static int led_lowbat_changed_cb(void *data) +{ + lowbat_state = (bool)data; + + if (lowbat_key) + led_mode(LED_LOW_BATTERY, lowbat_state); + + return 0; +} + +static int led_fullbat_changed_cb(void *data) +{ + full_state = (bool)data; + + if (charging_key) + led_mode(LED_FULLY_CHARGED, full_state); + + return 0; +} + +static int led_battery_health_changed_cb(void *data) +{ + struct led_mode *led; + bool cur; + + cur = ((int)data == HEALTH_BAD) ? true : false; + + /* do not enter below scenario in case of same state */ + if (cur == badbat_state) + return 0; + + badbat_state = cur; + + /* set charging error mode */ + led_mode(LED_CHARGING_ERROR, badbat_state); + + /* update the led state */ + if (badbat_state) { /* charging error */ + led = find_led_data(LED_CHARGING_ERROR); + led_mode_to_device(led); + } else { + led = find_led_data(LED_OFF); + led_mode_to_device(led); + if (lcd_state == S_LCDOFF) + led_display_changed_cb((void*)S_LCDOFF); + } + + return 0; +} + +static int led_battery_ovp_changed_cb(void *data) +{ + int cur = (int)data; + + /* do not enter below flow in case of same state */ + if (cur == ovp_state) + return 0; + + ovp_state = cur; + + if (ovp_state == OVP_NORMAL && lcd_state == S_LCDOFF) + led_display_changed_cb((void*)S_LCDOFF); + + return 0; +} + +static void led_poweron_changed_cb(keynode_t *key, void *data) +{ + int state; + struct led_mode *led; + + state = vconf_keynode_get_int(key); + + if (state != BOOT_ANIMATION_FINISHED) + return; + + led = find_led_data(LED_OFF); + led_mode_to_device(led); + + vconf_ignore_key_changed(VCONFKEY_BOOT_ANIMATION_FINISHED, + led_poweron_changed_cb); +} + +static void led_poweroff_changed_cb(keynode_t *key, void *data) +{ + int state; + struct led_mode *led; + + state = vconf_keynode_get_int(key); + + if (state == VCONFKEY_SYSMAN_POWER_OFF_NONE || + state == VCONFKEY_SYSMAN_POWER_OFF_POPUP) + return; + + led = find_led_data(LED_POWER_OFF); + led_mode_to_device(led); + + vconf_ignore_key_changed(VCONFKEY_SYSMAN_POWER_OFF_STATUS, + led_poweroff_changed_cb); +} + +static void led_vconf_charging_cb(keynode_t *key, void *data) +{ + charging_key = vconf_keynode_get_bool(key); + + if (charging_key) { + led_mode(LED_CHARGING, charging_state); + led_mode(LED_FULLY_CHARGED, full_state); + } else { + led_mode(LED_CHARGING, false); + led_mode(LED_FULLY_CHARGED, false); + } +} + +static void led_vconf_lowbat_cb(keynode_t *key, void *data) +{ + lowbat_key = vconf_keynode_get_bool(key); + + if (lowbat_key) + led_mode(LED_LOW_BATTERY, lowbat_state); + else + led_mode(LED_LOW_BATTERY, false); +} + +static void led_vconf_blocking_cb(keynode_t *key, void *data) +{ + rgb_blocked = vconf_keynode_get_bool(key); + _I("rgbled blocking mode %s", (rgb_blocked ? "started" : "stopped")); +} + +static DBusMessage *edbus_playcustom(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int cmd, val, ret; + int on, off; + unsigned int color, flags; + + ret = dbus_message_get_args(msg, NULL, + DBUS_TYPE_INT32, &on, + DBUS_TYPE_INT32, &off, + DBUS_TYPE_UINT32, &color, + DBUS_TYPE_UINT32, &flags, DBUS_TYPE_INVALID); + if (!ret) { + _I("there is no message"); + ret = -EINVAL; + goto error; + } + + /* not to play blink, on and off value should be zero */ + if (!(flags & LED_CUSTOM_DUTY_ON)) + on = off = 0; + + /* set new value in case of LED_CUSTOM value */ + ret = led_mode(LED_CUSTOM, true); + ret = led_prop(LED_CUSTOM, on, off, color); + + _D("play custom %d, %d, %x, %d", on, off, color, ret); + +error: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *edbus_stopcustom(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int val, ret; + + /* reset default value */ + ret = led_mode(LED_CUSTOM, false); + ret = led_prop(LED_CUSTOM, 500, 5000, 255); + + _D("stop custom %d", ret); + + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *edbus_set_mode(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + unsigned int color; + int mode, val, on, off, ret; + struct led_mode *led; + bool mode_enabled = false; + + ret = dbus_message_get_args(msg, NULL, + DBUS_TYPE_INT32, &mode, + DBUS_TYPE_INT32, &val, + DBUS_TYPE_INT32, &on, + DBUS_TYPE_INT32, &off, + DBUS_TYPE_UINT32, &color, DBUS_TYPE_INVALID); + if (!ret) { + _I("there is no message"); + ret = -EINVAL; + goto error; + } + + ret = get_led_mode_state(mode, &mode_enabled); + if (ret) { + _I("failed to get led mode state : %d", ret); + goto error; + } + + ret = led_mode(mode, val); + ret = led_prop(mode, on, off, color); + + /* Exception case : + in case of display off condition, + who requests missed noti event, it should change the device value */ + if (mode == LED_MISSED_NOTI && lcd_state == S_LCDOFF) { + if (!mode_enabled || on == 0) { + /* turn off previous setting */ + led = find_led_data(LED_OFF); + led_mode_to_device(led); + /* update the led state */ + led_display_changed_cb((void*)S_LCDOFF); + } + } + +error: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static void set_dumpmode(bool on) +{ + struct led_mode *led; + int val, color; + + if (on) { + val = LED_VALUE(200, 100); + color = led_blend(0xFFFF0000); + device_set_property(DEVICE_TYPE_LED, PROP_LED_COLOR, color); + device_set_property(DEVICE_TYPE_LED, PROP_LED_BLINK, val); + rgb_dumpmode = true; + _I("dump_mode on"); + } else { + if (dumpmode_timer) { + ecore_timer_del(dumpmode_timer); + dumpmode_timer = NULL; + } + if (rgb_dumpmode) + rgb_dumpmode = false; + else + return; + led = find_led_data(LED_OFF); + led_mode_to_device(led); + _I("dump_mode off"); + } +} + +static void dumpmode_timer_cb(void *data) +{ + set_dumpmode(false); +} + +static DBusMessage *edbus_dump_mode(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int ret = 0; + char *on; + + ret = dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &on, + DBUS_TYPE_INVALID); + + if (!ret) { + _E("fail to get dumpmode state %d", ret); + ret = -EINVAL; + goto error; + } + + if (!strcmp(on, "on")) { + set_dumpmode(true); + dumpmode_timer = ecore_timer_add(DUMPMODE_WAITING_TIME, + (Ecore_Task_Cb)dumpmode_timer_cb, NULL); + } else if (!strcmp(on, "off")) { + set_dumpmode(false); + } else + ret = -EINVAL; + +error: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + + return reply; +} + +static DBusMessage *edbus_print_mode(E_DBus_Object *obj, DBusMessage *msg) +{ + print_all_data(); + return dbus_message_new_method_return(msg); +} + +static const struct edbus_method edbus_methods[] = { + { "playcustom", "iiuu", "i", edbus_playcustom }, + { "stopcustom", NULL, "i", edbus_stopcustom }, + { "SetMode", "iiiiu", "i", edbus_set_mode }, + { "PrintMode", NULL, NULL, edbus_print_mode }, + { "Dumpmode", "s", "i", edbus_dump_mode }, + /* Add methods here */ +}; + +static void rgb_init(void *data) +{ + int ta_connected, boot; + int ret; + struct led_mode *led; + + /* init dbus interface */ + ret = register_edbus_method(DEVICED_PATH_LED, edbus_methods, ARRAY_SIZE(edbus_methods)); + if (ret < 0) + _E("fail to init edbus method(%d)", ret); + + /* get led mode data from xml */ + get_led_data(); + + /* verify booting or restart */ + ret = vconf_get_int(VCONFKEY_BOOT_ANIMATION_FINISHED, &boot); + if (ret != 0) + boot = 0; /* set booting state */ + + /* in case of restart */ + if (boot) + goto next; + + /* when booting, led indicator will be work */ + led = find_led_data(LED_POWER_OFF); + led_mode_to_device(led); + vconf_notify_key_changed(VCONFKEY_BOOT_ANIMATION_FINISHED, + led_poweron_changed_cb, NULL); + +next: + /* register power off callback */ + vconf_notify_key_changed(VCONFKEY_SYSMAN_POWER_OFF_STATUS, + led_poweroff_changed_cb, NULL); + + /* register notifier for each event */ + register_notifier(DEVICE_NOTIFIER_LCD, led_display_changed_cb); + register_notifier(DEVICE_NOTIFIER_BATTERY_CHARGING, led_charging_changed_cb); + register_notifier(DEVICE_NOTIFIER_LOWBAT, led_lowbat_changed_cb); + register_notifier(DEVICE_NOTIFIER_FULLBAT, led_fullbat_changed_cb); + register_notifier(DEVICE_NOTIFIER_BATTERY_HEALTH, led_battery_health_changed_cb); + register_notifier(DEVICE_NOTIFIER_BATTERY_OVP, led_battery_ovp_changed_cb); + + /* initialize vconf value */ + vconf_get_bool(VCONFKEY_SETAPPL_LED_INDICATOR_CHARGING, (int*)&charging_key); + vconf_get_bool(VCONFKEY_SETAPPL_LED_INDICATOR_LOW_BATT, (int*)&lowbat_key); + + /* initialize led indicator blocking value */ + vconf_get_bool(VCONFKEY_SETAPPL_BLOCKINGMODE_LED_INDICATOR, (int*)&rgb_blocked); + + /* register vconf callback */ + vconf_notify_key_changed(VCONFKEY_SETAPPL_LED_INDICATOR_CHARGING, + led_vconf_charging_cb, NULL); + vconf_notify_key_changed(VCONFKEY_SETAPPL_LED_INDICATOR_LOW_BATT, + led_vconf_lowbat_cb, NULL); + + /* register led indicator blocking vconf callback */ + vconf_notify_key_changed(VCONFKEY_SETAPPL_BLOCKINGMODE_LED_INDICATOR, + led_vconf_blocking_cb, NULL); + + ret = device_get_property(DEVICE_TYPE_POWER, PROP_POWER_CHARGE_NOW, &ta_connected); + if (!ret && ta_connected) + led_charging_changed_cb((void*)ta_connected); +} + +static void rgb_exit(void *data) +{ + struct led_mode *led; + + /* unregister vconf callback */ + vconf_ignore_key_changed(VCONFKEY_SETAPPL_LED_INDICATOR_CHARGING, + led_vconf_charging_cb); + vconf_ignore_key_changed(VCONFKEY_SETAPPL_LED_INDICATOR_LOW_BATT, + led_vconf_lowbat_cb); + + /* unregister led indicatore blocking vconf callback */ + vconf_ignore_key_changed(VCONFKEY_SETAPPL_BLOCKINGMODE_LED_INDICATOR, + led_vconf_blocking_cb); + + /* unregister notifier for each event */ + unregister_notifier(DEVICE_NOTIFIER_LCD, led_display_changed_cb); + unregister_notifier(DEVICE_NOTIFIER_BATTERY_CHARGING, led_charging_changed_cb); + unregister_notifier(DEVICE_NOTIFIER_LOWBAT, led_lowbat_changed_cb); + unregister_notifier(DEVICE_NOTIFIER_FULLBAT, led_fullbat_changed_cb); + unregister_notifier(DEVICE_NOTIFIER_BATTERY_HEALTH, led_battery_health_changed_cb); + unregister_notifier(DEVICE_NOTIFIER_BATTERY_OVP, led_battery_ovp_changed_cb); + + set_dumpmode(false); + /* turn off led */ + led = find_led_data(LED_OFF); + led_mode_to_device(led); + + /* release led mode data */ + release_led_data(); +} + +static int rgb_start(void) +{ + _I("rgbled device will be started"); + rgb_blocked = false; + return 0; +} + +static int rgb_stop(void) +{ + _I("rgbled device will be stopped"); + rgb_blocked = true; + return 0; +} + +static const struct device_ops rgbled_device_ops = { + .priority = DEVICE_PRIORITY_NORMAL, + .name = "rgbled", + .init = rgb_init, + .exit = rgb_exit, + .start = rgb_start, + .stop = rgb_stop, +}; + +DEVICE_OPS_REGISTER(&rgbled_device_ops) diff --git a/src/led/torch.c b/src/led/torch.c new file mode 100644 index 0000000..fbd4ece --- /dev/null +++ b/src/led/torch.c @@ -0,0 +1,243 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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/edbus-handler.h" +#include "core/devices.h" +#include "torch.h" + +static int camera_status; + +static DBusMessage *edbus_get_brightness(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int val, ret; + + ret = device_get_property(DEVICE_TYPE_LED, PROP_LED_BRIGHTNESS, &val); + if (ret >= 0) + ret = val; + + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *edbus_get_max_brightness(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int val, ret; + + ret = device_get_property(DEVICE_TYPE_LED, PROP_LED_MAX_BRIGHTNESS, &val); + if (ret >= 0) + ret = val; + + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *edbus_set_brightness(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int val, enable, ret; + + ret = dbus_message_get_args(msg, NULL, + DBUS_TYPE_INT32, &val, + DBUS_TYPE_INT32, &enable, DBUS_TYPE_INVALID); + if (!ret) { + _I("there is no message"); + ret = -EINVAL; + goto error; + } + + ret = device_set_property(DEVICE_TYPE_LED, PROP_LED_BRIGHTNESS, val); + if (ret < 0) + goto error; + + /* if enable is ON, noti will be show or hide */ + if (enable) { + if (val) + ongoing_show(); + else + ongoing_clear(); + } + +error: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *edbus_get_camera_brightness(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int val, ret; + + ret = device_get_property(DEVICE_TYPE_LED, PROP_LED_FLASH_BRIGHTNESS, &val); + if (ret >= 0) + ret = val; + + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *edbus_set_camera_brightness(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int val, enable, ret; + + ret = dbus_message_get_args(msg, NULL, + DBUS_TYPE_INT32, &val, DBUS_TYPE_INVALID); + if (!ret) { + _I("there is no message"); + ret = -EINVAL; + goto error; + } + + ret = device_set_property(DEVICE_TYPE_LED, PROP_LED_FLASH_BRIGHTNESS, val); + +error: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *edbus_play_pattern(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + char *path; + int cnt, ret; + + ret = dbus_message_get_args(msg, NULL, + DBUS_TYPE_STRING, &path, + DBUS_TYPE_INT32, &cnt, DBUS_TYPE_INVALID); + if (!ret) { + _I("there is no message"); + ret = -EINVAL; + goto exit; + } + + /* check camera status + Do not play led notification during the video recording */ + if (camera_status == VCONFKEY_CAMERA_STATE_RECORDING) { + _D("Camera is recording (status : %d)", camera_status); + ret = 0; + goto exit; + } + + /* TODO: Now we passed led file path from other module. + But led file is not a common file structure, + so we should change to be passed vibration pattern path + then it converts to led data internally */ + ret = play_pattern(path, cnt); + +exit: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *edbus_stop_pattern(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int ret; + + ret = stop_pattern(); + + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static void camera_status_cb(keynode_t *key, void *data) +{ + camera_status = vconf_keynode_get_int(key); + + _D("recording status changed!! new status => %d", camera_status); + + if (camera_status != VCONFKEY_CAMERA_STATE_RECORDING) + return; + + /* If camera state is recording, stop to play ledplayer */ + stop_pattern(); +} + +static const struct edbus_method edbus_methods[] = { + { "GetBrightness", NULL, "i", edbus_get_brightness }, + { "GetMaxBrightness", NULL, "i", edbus_get_max_brightness }, + { "SetBrightness", "ii", "i", edbus_set_brightness }, + { "GetCameraBrightness", NULL, "i", edbus_get_camera_brightness }, + { "SetCameraBrightness", "i", "i", edbus_set_camera_brightness }, + { "PlayPattern", "si", "i", edbus_play_pattern }, + { "StopPattern", NULL, "i", edbus_stop_pattern }, + /* Add methods here */ +}; + +static void torch_init(void *data) +{ + int ret; + + /* init dbus interface */ + ret = register_edbus_method(DEVICED_PATH_LED, edbus_methods, ARRAY_SIZE(edbus_methods)); + if (ret < 0) + _E("fail to init edbus method(%d)", ret); + + /* Get camera status */ + if (vconf_get_int(VCONFKEY_CAMERA_STATE, &camera_status) < 0) + _E("Failed to get VCONFKEY_CAMERA_STATE value"); + + /* add watch for status value */ + vconf_notify_key_changed(VCONFKEY_CAMERA_STATE, camera_status_cb, NULL); +} + +static void torch_exit(void *data) +{ + /* Release vconf callback */ + vconf_ignore_key_changed(VCONFKEY_CAMERA_STATE, camera_status_cb); +} + +static const struct device_ops torchled_device_ops = { + .priority = DEVICE_PRIORITY_NORMAL, + .name = "torchled", + .init = torch_init, + .exit = torch_exit, +}; + +DEVICE_OPS_REGISTER(&torchled_device_ops) diff --git a/src/led/torch.h b/src/led/torch.h new file mode 100644 index 0000000..8a8a8d3 --- /dev/null +++ b/src/led/torch.h @@ -0,0 +1,29 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 __TORCH_H__ +#define __TORCH_H__ + +int ongoing_show(void); +int ongoing_clear(void); + +int play_pattern(const char *path, int cnt); +int stop_pattern(void); + +#endif diff --git a/src/led/xml.c b/src/led/xml.c new file mode 100644 index 0000000..66a3b8d --- /dev/null +++ b/src/led/xml.c @@ -0,0 +1,253 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 "deviced/dd-led.h" +#include "xml.h" +#include "core/log.h" +#include "core/list.h" + +#ifndef DATADIR +#define DATADIR "/usr/share/deviced" +#endif + +#define LED_XML DATADIR"/led.xml" +#define LED_STR "led" + +static const char* led_str[] = { + [LED_OFF] = "off", + [LED_LOW_BATTERY] = "low battery", + [LED_CHARGING] = "charging", + [LED_FULLY_CHARGED] = "fully charged", + [LED_CHARGING_ERROR] = "charging error", + [LED_MISSED_NOTI] = "missed noti", + [LED_VOICE_RECORDING] = "voice recording", + [LED_POWER_OFF] = "power off", + [LED_CUSTOM] = "custom", +}; + +static dd_list *led_head; + +static xmlDocPtr xml_open(const char *xml) +{ + xmlDocPtr doc; + + doc = xmlReadFile(xml, NULL, 0); + if (doc == NULL) { + _E("xmlReadFile fail"); + return NULL; + } + + return doc; +} + +static void xml_close(xmlDocPtr doc) +{ + xmlFreeDoc(doc); +} + +static xmlNodePtr xml_find(xmlDocPtr doc, const xmlChar* expr) +{ + xmlNodePtr root; + xmlNodePtr cur; + xmlChar *key; + + assert(doc); + assert(expr); + + root = xmlDocGetRootElement(doc); + if (root == NULL) { + _E("xmlDocGetRootElement fail"); + return NULL; + } + + for (cur = root->children; cur != NULL; cur = cur->next) { + if (xmlStrcmp(cur->name, (const xmlChar*)LED_STR)) + continue; + + key = xmlGetProp(cur, (const xmlChar*)"label"); + if (key && !xmlStrcmp(key, expr)) { + _D("%s", key); + xmlFree(key); + return cur; + } + } + + return NULL; +} + +static struct led_mode *xml_parse(xmlDocPtr doc, xmlNodePtr cur) +{ + xmlNodePtr node; + xmlNodePtr attr; + struct led_mode *led; + xmlChar *key; + int i = 0; + + assert(doc); + assert(cur); + + led = (struct led_mode*)malloc(sizeof(struct led_mode)); + if (led == NULL) { + _E("out of memory"); + return NULL; + } + + for (node = cur->children; node != NULL; node = node->next) { + if (node->type != XML_ELEMENT_NODE) + continue; + + if (!xmlStrcmp(node->name, "priority")) { + key = xmlNodeListGetString(doc, node->children, 1); + if (!key) + continue; + led->data.priority = atoi(key); + xmlFree(key); + } else if (!xmlStrcmp(node->name, "data")) { + key = xmlGetProp(node, (const xmlChar*)"on"); + if (!key) + continue; + led->data.on = atoi(key); + xmlFree(key); + + key = xmlGetProp(node, (const xmlChar*)"off"); + if (!key) + continue; + led->data.off = atoi(key); + xmlFree(key); + + key = xmlGetProp(node, (const xmlChar*)"color"); + if (!key) + continue; + led->data.color = (unsigned int)strtoul(key, NULL, 16); + xmlFree(key); + + key = xmlGetProp(node, (const xmlChar*)"wave"); + if (!key || xmlStrcmp(key, "on")) + led->data.wave = false; + else + led->data.wave = true; + xmlFree(key); + } + } + + _D("priority : %d, on : %d, off : %d, color : %x, wave : %d", + led->data.priority, led->data.on, led->data.off, + led->data.color, led->data.wave); + return led; +} + +int get_led_data(void) +{ + xmlDocPtr doc; + xmlNodePtr cur; + struct led_mode *led; + int i; + int r; + + doc = xml_open(LED_XML); + if (doc == NULL) { + _E("xml_open(%s) fail", LED_XML); + errno = EPERM; + return -1; + } + + for (i = 0; i < LED_MODE_MAX; ++i) { + cur = xml_find(doc, (const xmlChar*)led_str[i]); + if (cur == NULL) { + _E("xml_find(%s) fail", led_str[i]); + break; + } + + led = xml_parse(doc, cur); + if (led == NULL) { + _E("xml_parse fail"); + break; + } + + led->mode = i; + led->state = 0; + DD_LIST_APPEND(led_head, led); + } + + xml_close(doc); + return 0; +} + +void release_led_data(void) +{ + dd_list *l; + struct led_mode *node; + + DD_LIST_FOREACH(led_head, l, node) { + _D("node name : %d", node->mode); + DD_LIST_REMOVE(led_head, node); + free(node); + } +} + +struct led_mode *find_led_data(int mode) +{ + dd_list *l; + struct led_mode *node; + + DD_LIST_FOREACH(led_head, l, node) { + if (node->mode == mode) + return node; + } + + return NULL; +} + +struct led_mode *get_valid_led_data(void) +{ + dd_list *l; + struct led_mode *node; + struct led_mode *cur = NULL; + int pr = 2; + + DD_LIST_FOREACH(led_head, l, node) { + if (!node->state) + continue; + if (node->data.priority <= pr) { + pr = node->data.priority; + cur = node; + } + } + + return cur; +} + +void print_all_data(void) +{ + dd_list *l; + struct led_mode *node; + + _D("Mode State priority on off color wave"); + DD_LIST_FOREACH(led_head, l, node) { + _D("%4d %5d %8d %4d %4d %x %4d", + node->mode, node->state, node->data.priority, + node->data.on, node->data.off, node->data.color, node->data.wave); + } +} diff --git a/src/led/xml.h b/src/led/xml.h new file mode 100644 index 0000000..a85375b --- /dev/null +++ b/src/led/xml.h @@ -0,0 +1,41 @@ +/* + * deviced + * + * Copyright (c) 2012 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 __XML_H__ +#define __XML_H__ + +struct led_mode { + int mode; + int state; + struct led_data { + int priority; + int on; + int off; + unsigned int color; + int wave; + } data; +}; + +int get_led_data(void); +void release_led_data(void); +struct led_mode *find_led_data(int mode); +struct led_mode *get_valid_led_data(void); +void print_all_data(void); + +#endif diff --git a/src/libdeviced/CMakeLists.txt b/src/libdeviced/CMakeLists.txt new file mode 100755 index 0000000..fc6a787 --- /dev/null +++ b/src/libdeviced/CMakeLists.txt @@ -0,0 +1,39 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(libdeviced C) + +SET(LIBDEVICED_SRCS + battery.c + control.c + display.c + haptic.c + led.c + mmc.c + storage.c + usbhost.c + deviced-conf.c + deviced-noti.c + deviced-util.c +) + +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/src/deviced ${CMAKE_SOURCE_DIR}/src/shared) + +INCLUDE(FindPkgConfig) +pkg_check_modules(libpkgs REQUIRED + vconf + dlog + dbus-1 + edbus) + +FOREACH(flag ${libpkgs_CFLAGS}) + SET(EXTRA_LIB_CFLAGS "${EXTRA_LIB_CFLAGS} ${flag}") +ENDFOREACH(flag) + +# libdeviced +ADD_LIBRARY(${PROJECT_NAME} SHARED ${LIBDEVICED_SRCS}) +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${libpkgs_LDFLAGS} shared) +SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES VERSION ${VERSION}) +# CMake Policy (CMP0002) +# The logical name of executable and library targes +# does not have to correspond to the physical file name built. +SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES OUTPUT_NAME deviced) +INSTALL(TARGETS ${PROJECT_NAME} DESTINATION lib COMPONENT RuntimeLibraries) diff --git a/src/libdeviced/battery.c b/src/libdeviced/battery.c new file mode 100644 index 0000000..8606ac6 --- /dev/null +++ b/src/libdeviced/battery.c @@ -0,0 +1,58 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 "log.h" +#include "dbus.h" +#include "common.h" + +#define METHOD_GET_PERCENT "GetPercent" +#define METHOD_GET_PERCENT_RAW "GetPercentRaw" +#define METHOD_IS_FULL "IsFull" +#define METHOD_GET_HEALTH "GetHealth" + +API int battery_get_percent(void) +{ + return dbus_method_sync(DEVICED_BUS_NAME, + DEVICED_PATH_BATTERY, DEVICED_INTERFACE_BATTERY, + METHOD_GET_PERCENT, NULL, NULL); +} + +API int battery_get_percent_raw(void) +{ + return dbus_method_sync(DEVICED_BUS_NAME, + DEVICED_PATH_BATTERY, DEVICED_INTERFACE_BATTERY, + METHOD_GET_PERCENT_RAW, NULL, NULL); +} + +API int battery_is_full(void) +{ + return dbus_method_sync(DEVICED_BUS_NAME, + DEVICED_PATH_BATTERY, DEVICED_INTERFACE_BATTERY, + METHOD_IS_FULL, NULL, NULL); +} + +API int battery_get_health(void) +{ + return dbus_method_sync(DEVICED_BUS_NAME, + DEVICED_PATH_BATTERY, DEVICED_INTERFACE_BATTERY, + METHOD_GET_HEALTH, NULL, NULL); +} diff --git a/src/libdeviced/control.c b/src/libdeviced/control.c new file mode 100644 index 0000000..bcea37b --- /dev/null +++ b/src/libdeviced/control.c @@ -0,0 +1,138 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 "log.h" +#include "dbus.h" +#include "common.h" +#include "dd-control.h" + +#define CONTROL_HANDLER_NAME "control" +#define CONTROL_GETTER_NAME "getcontrol" + +static int deviced_control_common(int device, bool enable) +{ + DBusError err; + DBusMessage *msg; + char *pa[5]; + int ret, val; + char buf_pid[6]; + char buf_dev[3]; + char buf_enable[2]; + + snprintf(buf_pid, sizeof(buf_pid), "%d", getpid()); + snprintf(buf_dev, sizeof(buf_dev), "%d", device); + snprintf(buf_enable, sizeof(buf_enable), "%d", enable); + + pa[0] = CONTROL_HANDLER_NAME; + pa[1] = "3"; + pa[2] = buf_pid; + pa[3] = buf_dev; + pa[4] = buf_enable; + + msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME, + DEVICED_PATH_SYSNOTI, DEVICED_INTERFACE_SYSNOTI, + pa[0], "sisss", pa); + if (!msg) + return -EBADMSG; + + dbus_error_init(&err); + + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &val, DBUS_TYPE_INVALID); + if (!ret) { + _E("no message : [%s:%s]", err.name, err.message); + val = -EBADMSG; + } + + dbus_message_unref(msg); + dbus_error_free(&err); + + _D("%s-%s : %d", DEVICED_INTERFACE_SYSNOTI, pa[0], val); + return val; +} + +static int deviced_get_control(int device, void *data) +{ + DBusError err; + DBusMessage *msg; + char *pa[4]; + int ret, val; + char buf_pid[6]; + char buf_dev[3]; + + snprintf(buf_pid, sizeof(buf_pid), "%d", getpid()); + snprintf(buf_dev, sizeof(buf_dev), "%d", device); + + pa[0] = CONTROL_GETTER_NAME; + pa[1] = "2"; + pa[2] = buf_pid; + pa[3] = buf_dev; + + msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME, + DEVICED_PATH_SYSNOTI, DEVICED_INTERFACE_SYSNOTI, + pa[0], "siss", pa); + if (!msg) + return -EBADMSG; + + dbus_error_init(&err); + + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &val, DBUS_TYPE_INVALID); + if (!ret) { + _E("no message : [%s:%s]", err.name, err.message); + val = -EBADMSG; + } + + dbus_message_unref(msg); + dbus_error_free(&err); + + _D("%s-%s : %d", DEVICED_INTERFACE_SYSNOTI, pa[0], val); + return val; +} + + +/* + * example of control api + * API int deviced_display_control(bool enable) + * { + * return deviced_control_common(DEVICE_CONTROL_DISPLAY, enable); + * } + */ + +API int deviced_mmc_control(bool enable) +{ + return deviced_control_common(DEVICE_CONTROL_MMC, enable); +} + +API int deviced_usb_control(bool enable) +{ + return deviced_control_common(DEVICE_CONTROL_USBCLIENT, enable); +} + +API int deviced_get_usb_control(void) +{ + return deviced_get_control(DEVICE_CONTROL_USBCLIENT, NULL); +} + +API int deviced_rgbled_control(bool enable) +{ + return deviced_control_common(DEVICE_CONTROL_RGBLED, enable); +} diff --git a/src/libdeviced/deviced-conf.c b/src/libdeviced/deviced-conf.c new file mode 100755 index 0000000..a00e233 --- /dev/null +++ b/src/libdeviced/deviced-conf.c @@ -0,0 +1,292 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include +#include +#include +#include +#include +#include +#include + +#include "log.h" +#include "deviced-priv.h" +#include "dd-deviced.h" +#include "dbus.h" +#include "score-defines.h" + +#define PERMANENT_DIR "/tmp/permanent" +#define VIP_DIR "/tmp/vip" + +#define OOMADJ_SET "oomadj_set" +#define PROCESS_GROUP_SET "process_group_set" +#define PROCESS_VIP "process_vip" +#define PROCESS_PERMANENT "process_permanent" + +enum mp_entry_type { + MP_VIP, + MP_PERMANENT, + MP_NONE +}; + +int util_oomadj_set(int pid, int oomadj_val) +{ + DBusError err; + DBusMessage *msg; + char *pa[4]; + char buf1[SYSTEM_NOTI_MAXARG]; + char buf2[SYSTEM_NOTI_MAXARG]; + int ret, val; + + snprintf(buf1, sizeof(buf1), "%d", pid); + snprintf(buf2, sizeof(buf2), "%d", oomadj_val); + + pa[0] = OOMADJ_SET; + pa[1] = "2"; + pa[2] = buf1; + pa[3] = buf2; + + msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME, + DEVICED_PATH_PROCESS, DEVICED_INTERFACE_PROCESS, + pa[0], "siss", pa); + if (!msg) + return -EBADMSG; + + dbus_error_init(&err); + + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &val, DBUS_TYPE_INVALID); + if (!ret) { + _E("no message : [%s:%s]", err.name, err.message); + val = -EBADMSG; + } + + dbus_message_unref(msg); + dbus_error_free(&err); + + _D("%s-%s : %d", DEVICED_INTERFACE_PROCESS, pa[0], val); + return val; +} + +static int util_process_group_set(char* name, int pid) +{ + DBusError err; + DBusMessage *msg; + char *pa[4]; + char buf[SYSTEM_NOTI_MAXARG]; + int ret, val; + + if (strncmp(PROCESS_VIP, name, strlen(name)) != 0 && + strncmp(PROCESS_PERMANENT, name, strlen(name)) != 0) { + _E("fail to insert at %s group", name); + return -1; + } + + snprintf(buf, sizeof(buf), "%d", pid); + _D("pid(%d) is inserted at vip", pid); + + pa[0] = PROCESS_GROUP_SET; + pa[1] = "2"; + pa[2] = buf; + pa[3] = name; + + msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME, + DEVICED_PATH_PROCESS, DEVICED_INTERFACE_PROCESS, + pa[0], "siss", pa); + if (!msg) + return -EBADMSG; + + dbus_error_init(&err); + + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &val, DBUS_TYPE_INVALID); + if (!ret) { + _E("no message : [%s:%s]", err.name, err.message); + val = -EBADMSG; + } + + dbus_message_unref(msg); + dbus_error_free(&err); + + _D("%s-%s : %d", DEVICED_INTERFACE_PROCESS, pa[0], val); + return val; +} + +API int deviced_conf_set_mempolicy_bypid(int pid, enum mem_policy mempol) +{ + if (pid < 1) + return -1; + + int oomadj_val = 0; + + switch (mempol) { + case OOM_LIKELY: + oomadj_val = OOMADJ_BACKGRD_UNLOCKED; + break; + case OOM_IGNORE: + oomadj_val = OOMADJ_SU; + break; + default: + return -1; + } + + return util_oomadj_set(pid, oomadj_val); +} + +API int deviced_conf_set_mempolicy(enum mem_policy mempol) +{ + return deviced_conf_set_mempolicy_bypid(getpid(), mempol); +} + +static int already_permanent(int pid) +{ + char buf[BUFF_MAX]; + + snprintf(buf, BUFF_MAX, "%s/%d", PERMANENT_DIR, pid); + + if (access(buf, R_OK) == 0) { + _D("already_permanent process : %d", pid); + return 1; + } + return 0; +} + +static int copy_cmdline(int pid) +{ + char buf[PATH_MAX]; + char filepath[PATH_MAX]; + int fd; + int cnt; + int r; + + if (access(PERMANENT_DIR, R_OK) < 0) { + _D("no predefined matrix dir = %s, so created", PERMANENT_DIR); + r = mkdir(PERMANENT_DIR, 0777); + if(r < 0) { + _E("permanent directory mkdir is failed"); + return -1; + } + } + + snprintf(filepath, PATH_MAX, "/proc/%d/cmdline", pid); + + fd = open(filepath, O_RDONLY); + if (fd == -1) { + _E("Failed to open"); + return -1; + } + + cnt = read(fd, buf, PATH_MAX); + close(fd); + + if (cnt <= 0) { + /* Read /proc//cmdline error */ + _E("Failed to read"); + return -1; + } + + snprintf(filepath, PATH_MAX, "%s/%d", PERMANENT_DIR, pid); + + fd = open(filepath, O_CREAT | O_WRONLY, 0644); + if (fd == -1) { + _E("Failed to open"); + return -1; + } + + if (write(fd, buf, cnt) == -1) { + _E("Failed to write"); + close(fd); + return -1; + } + + close(fd); + return 0; +} + +API int deviced_conf_set_vip(int pid) +{ + char buf[BUFF_MAX]; + int fd; + int r; + + if (pid < 1) + return -1; + + if (access(VIP_DIR, R_OK) < 0) { + _D("no predefined matrix dir = %s, so created", VIP_DIR); + r = mkdir(VIP_DIR, 0777); + if(r < 0) { + _E("sysconf_set_vip vip mkdir is failed"); + return -1; + } + } + + snprintf(buf, BUFF_MAX, "%s/%d", VIP_DIR, pid); + fd = open(buf, O_CREAT | O_RDWR, 0644); + if (fd < 0) { + _E("sysconf_set_vip fd open failed"); + return -1; + } + close(fd); + if (util_process_group_set(PROCESS_VIP, pid) < 0) { + _E("set vip failed"); + return -1; + } + + return 0; +} + +API int deviced_conf_is_vip(int pid) +{ + if (pid < 1) + return -1; + + char buf[BUFF_MAX]; + + snprintf(buf, BUFF_MAX, "%s/%d", VIP_DIR, pid); + + if (access(buf, R_OK) == 0) + return 1; + else + return 0; +} + +API int deviced_conf_set_permanent_bypid(int pid) +{ + int fd; + if (already_permanent(pid)) + goto MEMPOL_SET; + + if (copy_cmdline(pid) < 0) + return -1; + + if (util_process_group_set(PROCESS_PERMANENT, pid) < 0) { + _E("set vip failed"); + return -1; + } + + MEMPOL_SET: + util_oomadj_set(pid, OOMADJ_SU); + + return 0; +} + +API int deviced_conf_set_permanent() +{ + pid_t pid = getpid(); + return deviced_conf_set_permanent_bypid(pid); +} diff --git a/src/libdeviced/deviced-noti.c b/src/libdeviced/deviced-noti.c new file mode 100755 index 0000000..3ae6746 --- /dev/null +++ b/src/libdeviced/deviced-noti.c @@ -0,0 +1,605 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dd-deviced.h" +#include "deviced-priv.h" +#include "log.h" +#include "dbus.h" + +#define PREDEF_PWROFF_POPUP "pwroff-popup" +#define PREDEF_ENTERSLEEP "entersleep" +#define PREDEF_LEAVESLEEP "leavesleep" +#define PREDEF_REBOOT "reboot" +#define PREDEF_BACKGRD "backgrd" +#define PREDEF_FOREGRD "foregrd" +#define PREDEF_ACTIVE "active" +#define PREDEF_INACTIVE "inactive" +#define PREDEF_SET_DATETIME "set_datetime" +#define PREDEF_SET_TIMEZONE "set_timezone" + +#define PREDEF_SET_MAX_FREQUENCY "set_max_frequency" +#define PREDEF_SET_MIN_FREQUENCY "set_min_frequency" +#define PREDEF_RELEASE_MAX_FREQUENCY "release_max_frequency" +#define PREDEF_RELEASE_MIN_FREQUENCY "release_min_frequency" + +#define PREDEF_FACTORY_MODE "factorymode" + +#define PREDEF_DUMP_LOG "dump_log" +#define PREDEF_DELETE_DUMP "delete_dump" +#define PREDEF_FLIGHT_MODE "flightmode" +#define PREDEF_LED_CMD "ledcmd" +#define PREDEF_LED_BRT "ledbrt" +#define PREDEF_LED_MODE "ledmode" + +#define ALARM_BUS_NAME "com.samsung.alarm.manager" +#define ALARM_PATH_NAME "/com/samsung/alarm/manager" +#define ALARM_INTERFACE_NAME ALARM_BUS_NAME +#define ALARM_SET_TIME_METHOD "alarm_set_time" + +enum deviced_noti_cmd { + ADD_deviced_ACTION, + CALL_deviced_ACTION +}; + +#define SYSTEM_NOTI_SOCKET_PATH "/tmp/sn" +#define RETRY_READ_COUNT 10 + +static inline int send_int(int fd, int val) +{ + return write(fd, &val, sizeof(int)); +} + +static inline int send_str(int fd, char *str) +{ + int len; + int ret; + if (str == NULL) { + len = 0; + ret = write(fd, &len, sizeof(int)); + } else { + len = strlen(str); + if (len > SYSTEM_NOTI_MAXSTR) + len = SYSTEM_NOTI_MAXSTR; + write(fd, &len, sizeof(int)); + ret = write(fd, str, len); + } + return ret; +} + +static int noti_send(struct sysnoti *msg) +{ + int client_len; + int client_sockfd; + int result; + int r; + int retry_count = 0; + struct sockaddr_un clientaddr; + int i; + + client_sockfd = socket(AF_UNIX, SOCK_STREAM, 0); + if (client_sockfd == -1) { + _E("socket create failed"); + return -1; + } + bzero(&clientaddr, sizeof(clientaddr)); + clientaddr.sun_family = AF_UNIX; + strncpy(clientaddr.sun_path, SYSTEM_NOTI_SOCKET_PATH, sizeof(clientaddr.sun_path) - 1); + client_len = sizeof(clientaddr); + + if (connect(client_sockfd, (struct sockaddr *)&clientaddr, client_len) < + 0) { + _E("connect failed"); + close(client_sockfd); + return -1; + } + + send_int(client_sockfd, msg->pid); + send_int(client_sockfd, msg->cmd); + send_str(client_sockfd, msg->type); + send_str(client_sockfd, msg->path); + send_int(client_sockfd, msg->argc); + for (i = 0; i < msg->argc; i++) + send_str(client_sockfd, msg->argv[i]); + + while (retry_count < RETRY_READ_COUNT) { + r = read(client_sockfd, &result, sizeof(int)); + if (r < 0) { + if (errno == EINTR) { + _E("Re-read for error(EINTR)"); + retry_count++; + continue; + } + _E("Read fail for str length"); + result = -1; + break; + + } + break; + } + if (retry_count == RETRY_READ_COUNT) { + _E("Read retry failed"); + } + + close(client_sockfd); + return result; +} + +API int deviced_call_predef_action(const char *type, int num, ...) +{ + struct sysnoti *msg; + int ret; + va_list argptr; + int i; + char *args = NULL; + + if (type == NULL || num > SYSTEM_NOTI_MAXARG) { + errno = EINVAL; + return -1; + } + + msg = malloc(sizeof(struct sysnoti)); + + if (msg == NULL) { + /* Do something for not enought memory error */ + return -1; + } + + msg->pid = getpid(); + msg->cmd = CALL_deviced_ACTION; + msg->type = (char *)type; + msg->path = NULL; + + msg->argc = num; + va_start(argptr, num); + for (i = 0; i < num; i++) { + args = va_arg(argptr, char *); + msg->argv[i] = args; + } + va_end(argptr); + + ret = noti_send(msg); + free(msg); + + return ret; +} + +static int dbus_proc_handler(char* type, char *buf) +{ + DBusError err; + DBusMessage *msg; + char *pa[3]; + int ret, val; + + pa[0] = type; + pa[1] = "1"; + pa[2] = buf; + + msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME, + DEVICED_PATH_PROCESS, DEVICED_INTERFACE_PROCESS, + pa[0], "sis", pa); + if (!msg) + return -EBADMSG; + + dbus_error_init(&err); + + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &val, DBUS_TYPE_INVALID); + if (!ret) { + _E("no message : [%s:%s]", err.name, err.message); + val = -EBADMSG; + } + + dbus_message_unref(msg); + dbus_error_free(&err); + + _D("%s-%s : %d", DEVICED_INTERFACE_PROCESS, pa[0], val); + return val; +} + +API int deviced_inform_foregrd(void) +{ + char buf[255]; + snprintf(buf, sizeof(buf), "%d", getpid()); + return dbus_proc_handler(PREDEF_FOREGRD, buf); +} + +API int deviced_inform_backgrd(void) +{ + char buf[255]; + snprintf(buf, sizeof(buf), "%d", getpid()); + return dbus_proc_handler(PREDEF_BACKGRD, buf); +} + +API int deviced_inform_active(pid_t pid) +{ + char buf[255]; + snprintf(buf, sizeof(buf), "%d", pid); + return dbus_proc_handler(PREDEF_ACTIVE, buf); +} + +API int deviced_inform_inactive(pid_t pid) +{ + char buf[255]; + snprintf(buf, sizeof(buf), "%d", pid); + return dbus_proc_handler(PREDEF_INACTIVE, buf); +} + +static int dbus_power_handler(char* type) +{ + DBusError err; + DBusMessage *msg; + char *pa[2]; + int ret, val; + + pa[0] = type; + pa[1] = "0"; + + msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME, + DEVICED_PATH_POWER, DEVICED_INTERFACE_POWER, + pa[0], "si", pa); + if (!msg) + return -EBADMSG; + + dbus_error_init(&err); + + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &val, DBUS_TYPE_INVALID); + if (!ret) { + _E("no message : [%s:%s]", err.name, err.message); + val = -EBADMSG; + } + + dbus_message_unref(msg); + dbus_error_free(&err); + + _D("%s-%s : %d", DEVICED_INTERFACE_POWER, pa[0], val); + return val; +} + +API int deviced_request_poweroff(void) +{ + return dbus_power_handler(PREDEF_PWROFF_POPUP); +} + +API int deviced_request_entersleep(void) +{ + return dbus_power_handler(PREDEF_ENTERSLEEP); +} + +API int deviced_request_leavesleep(void) +{ + return dbus_power_handler(PREDEF_LEAVESLEEP); +} + +API int deviced_request_reboot(void) +{ + return dbus_power_handler(PREDEF_REBOOT); +} + +static int dbus_time_handler(char* type, char* buf) +{ + DBusError err; + DBusMessage *msg; + pid_t pid; + char name[PATH_MAX]; + char *pa[3]; + int ret, val; + + pa[0] = type; + pa[1] = "1"; + pa[2] = buf; + + pid = getpid(); + ret = deviced_get_cmdline_name(pid, name, sizeof(name)); + if (ret != 0) + snprintf(name, sizeof(name), "%d", pid); + + msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME, + DEVICED_PATH_SYSNOTI, DEVICED_INTERFACE_SYSNOTI, + pa[0], "sis", pa); + if (!msg) + return -EBADMSG; + + dbus_error_init(&err); + + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &val, DBUS_TYPE_INVALID); + if (!ret) { + _E("no message : [%s:%s]", err.name, err.message); + val = -EBADMSG; + } + + dbus_message_unref(msg); + dbus_error_free(&err); + + _SI("[%s] %s-%s(%s) : %d", name, DEVICED_INTERFACE_SYSNOTI, pa[0], pa[2], val); + + return val; +} + +static DBusMessage *alarm_set_time_sync_with_reply(time_t timet) +{ + DBusConnection *conn; + DBusMessage *msg; + DBusMessageIter iter; + DBusMessage *reply; + DBusError err; + int r; + + conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL); + if (!conn) { + _E("dbus_bus_get error"); + return NULL; + } + + msg = dbus_message_new_method_call(ALARM_BUS_NAME, ALARM_PATH_NAME, ALARM_INTERFACE_NAME, ALARM_SET_TIME_METHOD); + if (!msg) { + _E("dbus_message_new_method_call(%s:%s-%s)", + ALARM_PATH_NAME, ALARM_INTERFACE_NAME, ALARM_SET_TIME_METHOD); + return NULL; + } + + dbus_message_iter_init_append(msg, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &timet); + + dbus_error_init(&err); + + reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, &err); + if (!reply) { + _E("dbus_connection_send error(No reply) %s %s:%s-%s", + ALARM_BUS_NAME, ALARM_PATH_NAME, ALARM_INTERFACE_NAME, ALARM_SET_TIME_METHOD); + } + + if (dbus_error_is_set(&err)) { + _E("dbus_connection_send error(%s:%s) %s %s:%s-%s", + err.name, err.message, ALARM_BUS_NAME, ALARM_PATH_NAME, ALARM_INTERFACE_NAME, ALARM_SET_TIME_METHOD); + dbus_error_free(&err); + reply = NULL; + } + + dbus_message_unref(msg); + return reply; +} + +static int alarm_set_time(time_t timet) +{ + DBusError err; + DBusMessage *msg; + pid_t pid; + char name[PATH_MAX]; + int ret, val; + + pid = getpid(); + ret = deviced_get_cmdline_name(pid, name, sizeof(name)); + if (ret != 0) + snprintf(name, sizeof(name), "%d", pid); + _SI("[%s]start %s %ld", name, ALARM_INTERFACE_NAME, timet); + + msg = alarm_set_time_sync_with_reply(timet); + if (!msg) + return -EBADMSG; + + dbus_error_init(&err); + + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &val, DBUS_TYPE_INVALID); + if (!ret) { + _E("no message : [%s:%s]", err.name, err.message); + val = -EBADMSG; + } + + dbus_message_unref(msg); + dbus_error_free(&err); + + _SI("[%s]end %s %ld, %d", name, ALARM_INTERFACE_NAME, timet, val); + return val; +} + +API int deviced_set_datetime(time_t timet) +{ + if (timet < 0L) + return -1; + return alarm_set_time(timet); +} + +API int deviced_set_timezone(char *tzpath_str) +{ + if (tzpath_str == NULL) + return -1; + char buf[255]; + snprintf(buf, sizeof(buf), "%s", tzpath_str); + return dbus_time_handler(PREDEF_SET_TIMEZONE, buf); +} + +static int dbus_cpu_handler(char* type, char* buf_pid, char* buf_freq) +{ + DBusError err; + DBusMessage *msg; + char *pa[4]; + int ret, val; + + pa[0] = type; + pa[1] = "2"; + pa[2] = buf_pid; + pa[3] = buf_freq; + + msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME, + DEVICED_PATH_SYSNOTI, DEVICED_INTERFACE_SYSNOTI, + pa[0], "siss", pa); + if (!msg) + return -EBADMSG; + + dbus_error_init(&err); + + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &val, DBUS_TYPE_INVALID); + if (!ret) { + _E("no message : [%s:%s]", err.name, err.message); + val = -EBADMSG; + } + + dbus_message_unref(msg); + dbus_error_free(&err); + + _D("%s-%s : %d", DEVICED_INTERFACE_SYSNOTI, pa[0], val); + return val; +} + +API int deviced_request_set_cpu_max_frequency(int val) +{ + char buf_pid[8]; + char buf_freq[256]; + + // to do - need to check new frequncy is valid + snprintf(buf_pid, sizeof(buf_pid), "%d", getpid()); + snprintf(buf_freq, sizeof(buf_freq), "%d", val * 1000); + + return dbus_cpu_handler(PREDEF_SET_MAX_FREQUENCY, buf_pid, buf_freq); +} + +API int deviced_request_set_cpu_min_frequency(int val) +{ + char buf_pid[8]; + char buf_freq[256]; + + // to do - need to check new frequncy is valid + snprintf(buf_pid, sizeof(buf_pid), "%d", getpid()); + snprintf(buf_freq, sizeof(buf_freq), "%d", val * 1000); + + return dbus_cpu_handler(PREDEF_SET_MIN_FREQUENCY, buf_pid, buf_freq); +} + +API int deviced_release_cpu_max_frequency() +{ + char buf_pid[8]; + + snprintf(buf_pid, sizeof(buf_pid), "%d", getpid()); + + return dbus_cpu_handler(PREDEF_RELEASE_MAX_FREQUENCY, buf_pid, "2"); +} + +API int deviced_release_cpu_min_frequency() +{ + char buf_pid[8]; + + snprintf(buf_pid, sizeof(buf_pid), "%d", getpid()); + + return dbus_cpu_handler(PREDEF_RELEASE_MIN_FREQUENCY, buf_pid, "2"); +} + +static int dbus_factory_handler(char* type, char* buf) +{ + DBusError err; + DBusMessage *msg; + char *pa[3]; + int ret, val; + + pa[0] = type; + pa[1] = "1"; + pa[2] = buf; + + msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME, + DEVICED_PATH_SYSNOTI, DEVICED_INTERFACE_SYSNOTI, + pa[0], "sis", pa); + if (!msg) + return -EBADMSG; + + dbus_error_init(&err); + + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &val, DBUS_TYPE_INVALID); + if (!ret) { + _E("no message : [%s:%s]", err.name, err.message); + val = -EBADMSG; + } + + dbus_message_unref(msg); + dbus_error_free(&err); + + _D("%s-%s : %d", DEVICED_INTERFACE_SYSNOTI, pa[0], val); + return val; +} + +API int deviced_request_set_factory_mode(int val) +{ + char buf_mode[8]; + if ( val == 0 || val == 1 ) { + snprintf(buf_mode, sizeof(buf_mode), "%d", val); + return dbus_factory_handler(PREDEF_FACTORY_MODE, buf_mode); + } else { + return -1; + } +} + +static int dbus_crash_handler(char* type, char* buf) +{ + DBusError err; + DBusMessage *msg; + char *pa[3]; + int ret, val; + + pa[0] = type; + pa[1] = "1"; + pa[2] = buf; + msg = dbus_method_sync_with_reply(CRASHD_BUS_NAME, + CRASHD_PATH_CRASH, CRASHD_INTERFACE_CRASH, + pa[0], "sis", pa); + if (!msg) + return -EBADMSG; + + dbus_error_init(&err); + + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &val, DBUS_TYPE_INVALID); + if (!ret) { + _E("no message : [%s:%s]", err.name, err.message); + val = -EBADMSG; + } + + dbus_message_unref(msg); + dbus_error_free(&err); + + _D("%s-%s : %d", CRASHD_INTERFACE_CRASH, pa[0], val); + return val; +} + +API int deviced_request_dump_log(int type) +{ + char buf_mode[8]; + if ( type == AP_DUMP || type == CP_DUMP || type == ALL_DUMP) { + snprintf(buf_mode, sizeof(buf_mode), "%d", type); + return dbus_crash_handler(PREDEF_DUMP_LOG, buf_mode); + } else { + return -1; + } +} + +API int deviced_request_delete_dump(char *ticket) +{ + char buf[255]; + if ( ticket == NULL) { + return -1; + } + snprintf(buf, sizeof(buf), "%s", ticket); + return dbus_crash_handler(PREDEF_DELETE_DUMP, buf); +} diff --git a/src/libdeviced/deviced-util.c b/src/libdeviced/deviced-util.c new file mode 100644 index 0000000..3cb19a6 --- /dev/null +++ b/src/libdeviced/deviced-util.c @@ -0,0 +1,132 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "log.h" +#include "dd-deviced.h" +#include "deviced-priv.h" + +API int deviced_get_pid(const char *execpath) +{ + DIR *dp; + struct dirent *dentry; + int pid = -1, fd; + char buf[BUFF_MAX]; + char buf2[BUFF_MAX]; + int ret; + + dp = opendir("/proc"); + if (!dp) { + _E("open /proc"); + return -1; + } + + while ((dentry = readdir(dp)) != NULL) { + if (!isdigit(dentry->d_name[0])) + continue; + + pid = atoi(dentry->d_name); + + snprintf(buf, BUFF_MAX, "/proc/%d/cmdline", pid); + fd = open(buf, O_RDONLY); + if (fd < 0) + continue; + + ret = read(fd, buf2, BUFF_MAX); + close(fd); + + if (ret < 0 || ret >=BUFF_MAX) + continue; + + buf2[ret] = '\0'; + + if (!strcmp(buf2, execpath)) { + closedir(dp); + return pid; + } + } + + errno = ESRCH; + closedir(dp); + return -1; +} + +API int deviced_get_cmdline_name(pid_t pid, char *cmdline, size_t cmdline_size) +{ + int fd, ret; + char buf[PATH_MAX + 1]; + char *filename; + + snprintf(buf, sizeof(buf), "/proc/%d/cmdline", pid); + fd = open(buf, O_RDONLY); + if (fd < 0) { + errno = ESRCH; + return -1; + } + + ret = read(fd, buf, PATH_MAX); + close(fd); + buf[PATH_MAX] = '\0'; + + filename = strrchr(buf, '/'); + if (filename == NULL) + filename = buf; + else + filename = filename + 1; + + if (cmdline_size < strlen(filename) + 1) { + errno = EOVERFLOW; + return -1; + } + + strncpy(cmdline, filename, cmdline_size - 1); + cmdline[cmdline_size - 1] = '\0'; + return 0; +} + +API int deviced_get_apppath(pid_t pid, char *app_path, size_t app_path_size) +{ + char buf[PATH_MAX]; + int ret; + + snprintf(buf, PATH_MAX, "/proc/%d/exe", pid); + if (app_path == NULL + || (ret = readlink(buf, app_path, app_path_size)) == -1) + return -1; + if (app_path_size == ret) { + app_path[ret - 1] = '\0'; + errno = EOVERFLOW; + return -1; + } + + app_path[ret] = '\0'; + return 0; +} diff --git a/src/libdeviced/display.c b/src/libdeviced/display.c new file mode 100644 index 0000000..70daf48 --- /dev/null +++ b/src/libdeviced/display.c @@ -0,0 +1,746 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 "log.h" +#include "dbus.h" +#include "common.h" +#include "dd-display.h" + +#define DISPLAY_MAX_BRIGHTNESS 100 +#define DISPLAY_MIN_BRIGHTNESS 1 +#define DISPLAY_DIM_BRIGHTNESS 0 + +#define HOLDKEY_BLOCK_BIT 0x1 +#define STANDBY_MODE_BIT 0x2 + +#define BLIND_MASK(val) ((val) & 0xFFFF) +#define BLIND_COLOR(a,b,c) ((BLIND_MASK((unsigned long long)(a)) << 32) | \ + (BLIND_MASK(b) << 16) | BLIND_MASK(c)) + +#define METHOD_GET_ENHANCE_SUPPORTED "GetEnhanceSupported" +#define METHOD_GET_IMAGE_ENHANCE "GetImageEnhance" +#define METHOD_SET_IMAGE_ENHANCE "SetImageEnhance" +#define METHOD_SET_REFRESH_RATE "SetRefreshRate" +#define METHOD_GET_COLOR_BLIND "GetColorBlind" +#define METHOD_SET_COLOR_BLIND "SetColorBlind" +#define METHOD_LOCK_STATE "lockstate" +#define METHOD_UNLOCK_STATE "unlockstate" +#define METHOD_CHANGE_STATE "changestate" +#define METHOD_GET_DISPLAY_COUNT "GetDisplayCount" +#define METHOD_GET_MAX_BRIGHTNESS "GetMaxBrightness" +#define METHOD_GET_BRIGHTNESS "GetBrightness" +#define METHOD_SET_BRIGHTNESS "SetBrightness" +#define METHOD_HOLD_BRIGHTNESS "HoldBrightness" +#define METHOD_RELEASE_BRIGHTNESS "ReleaseBrightness" +#define METHOD_GET_ACL_STATUS "GetAclStatus" +#define METHOD_SET_ACL_STATUS "SetAclStatus" +#define METHOD_GET_AUTO_TONE "GetAutoTone" +#define METHOD_SET_AUTO_TONE "SetAutoTone" +#define METHOD_GET_ENHANCED_TOUCH "GetEnhancedTouch" +#define METHOD_SET_ENHANCED_TOUCH "SetEnhancedTouch" +#define METHOD_GET_HBM "GetHBM" +#define METHOD_SET_HBM "SetHBM" +#define METHOD_SET_HBM_TIMEOUT "SetHBMTimeout" + +#define STR_LCD_OFF "lcdoff" +#define STR_LCD_DIM "lcddim" +#define STR_LCD_ON "lcdon" +#define STR_SUSPEND "suspend" + +#define STR_STAYCURSTATE "staycurstate" +#define STR_GOTOSTATENOW "gotostatenow" + +#define STR_HOLDKEYBLOCK "holdkeyblock" +#define STR_STANDBYMODE "standbymode" +#define STR_NULL "NULL" + +#define STR_SLEEP_MARGIN "sleepmargin" +#define STR_RESET_TIMER "resettimer" +#define STR_KEEP_TIMER "keeptimer" + +API int display_get_count(void) +{ + DBusError err; + DBusMessage *msg; + int ret, ret_val; + + msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME, + DEVICED_PATH_DISPLAY, DEVICED_INTERFACE_DISPLAY, + METHOD_GET_DISPLAY_COUNT, NULL, NULL); + if (!msg) + return -EBADMSG; + + dbus_error_init(&err); + + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &ret_val, DBUS_TYPE_INVALID); + if (!ret) { + _E("no message : [%s:%s]", err.name, err.message); + dbus_error_free(&err); + ret_val = -EBADMSG; + } + + dbus_message_unref(msg); + return ret_val; +} + +API int display_get_max_brightness(void) +{ + int ret; + + ret = dbus_method_sync(DEVICED_BUS_NAME, + DEVICED_PATH_DISPLAY, DEVICED_INTERFACE_DISPLAY, + METHOD_GET_MAX_BRIGHTNESS, NULL, NULL); + if (ret < 0) + return DISPLAY_MAX_BRIGHTNESS; + + _D("get max brightness : %d", ret); + return ret; +} + +API int display_get_min_brightness(void) +{ + return DISPLAY_MIN_BRIGHTNESS; +} + +API int display_get_brightness(void) +{ + DBusError err; + DBusMessage *msg; + int ret, ret_val; + + msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME, + DEVICED_PATH_DISPLAY, DEVICED_INTERFACE_DISPLAY, + METHOD_GET_BRIGHTNESS, NULL, NULL); + if (!msg) + return -EBADMSG; + + dbus_error_init(&err); + + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &ret_val, DBUS_TYPE_INVALID); + if (!ret) { + _E("no message : [%s:%s]", err.name, err.message); + dbus_error_free(&err); + ret_val = -EBADMSG; + } + + dbus_message_unref(msg); + return ret_val; +} + +API int display_set_brightness_with_setting(int val) +{ + char str_val[32]; + char *arr[1]; + int ret; + + if (val < 0 || val > 100) + return -EINVAL; + + snprintf(str_val, sizeof(str_val), "%d", val); + arr[0] = str_val; + + ret = dbus_method_async(DEVICED_BUS_NAME, + DEVICED_PATH_DISPLAY, DEVICED_INTERFACE_DISPLAY, + METHOD_SET_BRIGHTNESS, "i", arr); + if (ret < 0) + _E("no message : failed to setting"); + + return ret; +} + +API int display_set_brightness(int val) +{ + DBusError err; + DBusMessage *msg; + char str_val[32]; + char *arr[1]; + int ret, ret_val; + + snprintf(str_val, sizeof(str_val), "%d", val); + arr[0] = str_val; + + msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME, + DEVICED_PATH_DISPLAY, DEVICED_INTERFACE_DISPLAY, + METHOD_HOLD_BRIGHTNESS, "i", arr); + if (!msg) + return -EBADMSG; + + dbus_error_init(&err); + + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &ret_val, DBUS_TYPE_INVALID); + if (!ret) { + _E("no message : [%s:%s]", err.name, err.message); + dbus_error_free(&err); + ret_val = -EBADMSG; + } + + dbus_message_unref(msg); + return ret_val; +} + +API int display_release_brightness(void) +{ + DBusError err; + DBusMessage *msg; + int ret, ret_val; + + msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME, + DEVICED_PATH_DISPLAY, DEVICED_INTERFACE_DISPLAY, + METHOD_RELEASE_BRIGHTNESS, NULL, NULL); + if (!msg) + return -EBADMSG; + + dbus_error_init(&err); + + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &ret_val, DBUS_TYPE_INVALID); + if (!ret) { + _E("no message : [%s:%s]", err.name, err.message); + dbus_error_free(&err); + ret_val = -EBADMSG; + } + + dbus_message_unref(msg); + return ret_val; +} + +API int display_get_acl_status(void) +{ + DBusError err; + DBusMessage *msg; + int ret, ret_val; + + msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME, + DEVICED_PATH_DISPLAY, DEVICED_INTERFACE_DISPLAY, + METHOD_GET_ACL_STATUS, NULL, NULL); + if (!msg) + return -EBADMSG; + + dbus_error_init(&err); + + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &ret_val, DBUS_TYPE_INVALID); + if (!ret) { + _E("no message : [%s:%s]", err.name, err.message); + dbus_error_free(&err); + ret_val = -EBADMSG; + } + + dbus_message_unref(msg); + return ret_val; +} + +API int display_set_acl_status(int val) +{ + DBusError err; + DBusMessage *msg; + char str_val[32]; + char *arr[1]; + int ret, ret_val; + + snprintf(str_val, sizeof(str_val), "%d", val); + arr[0] = str_val; + + msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME, + DEVICED_PATH_DISPLAY, DEVICED_INTERFACE_DISPLAY, + METHOD_SET_ACL_STATUS, "i", arr); + if (!msg) + return -EBADMSG; + + dbus_error_init(&err); + + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &ret_val, DBUS_TYPE_INVALID); + if (!ret) { + _E("no message : [%s:%s]", err.name, err.message); + dbus_error_free(&err); + ret_val = -EBADMSG; + } + + dbus_message_unref(msg); + return ret_val; +} + +API int display_get_auto_screen_tone(void) +{ + DBusError err; + DBusMessage *msg; + int ret, ret_val; + + msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME, + DEVICED_PATH_DISPLAY, DEVICED_INTERFACE_DISPLAY, + METHOD_GET_AUTO_TONE, NULL, NULL); + if (!msg) + return -EBADMSG; + + dbus_error_init(&err); + + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &ret_val, DBUS_TYPE_INVALID); + if (!ret) { + _E("no message : [%s:%s]", err.name, err.message); + dbus_error_free(&err); + ret_val = -EBADMSG; + } + + dbus_message_unref(msg); + return ret_val; +} + +API int display_set_auto_screen_tone(int val) +{ + DBusError err; + DBusMessage *msg; + char str_val[32]; + char *arr[1]; + int ret, ret_val; + + snprintf(str_val, sizeof(str_val), "%d", val); + arr[0] = str_val; + + msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME, + DEVICED_PATH_DISPLAY, DEVICED_INTERFACE_DISPLAY, + METHOD_SET_AUTO_TONE, "i", arr); + if (!msg) + return -EBADMSG; + + dbus_error_init(&err); + + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &ret_val, DBUS_TYPE_INVALID); + if (!ret) { + _E("no message : [%s:%s]", err.name, err.message); + dbus_error_free(&err); + ret_val = -EBADMSG; + } + + dbus_message_unref(msg); + return ret_val; +} + +API int display_get_image_enhance_info(void) +{ + DBusError err; + DBusMessage *msg; + int ret, ret_val; + + msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME, + DEVICED_PATH_DISPLAY, DEVICED_INTERFACE_DISPLAY, + METHOD_GET_ENHANCE_SUPPORTED, NULL, NULL); + if (!msg) + return -EBADMSG; + + dbus_error_init(&err); + + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &ret_val, DBUS_TYPE_INVALID); + if (!ret) { + _E("no message : [%s:%s]", err.name, err.message); + dbus_error_free(&err); + ret_val = -EBADMSG; + } + + dbus_message_unref(msg); + return ret_val; +} + +API int display_get_image_enhance(int type) +{ + DBusError err; + DBusMessage *msg; + char str_type[32]; + char *arr[1]; + int ret, ret_val; + + snprintf(str_type, sizeof(str_type), "%d", type); + arr[0] = str_type; + + msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME, + DEVICED_PATH_DISPLAY, DEVICED_INTERFACE_DISPLAY, + METHOD_GET_IMAGE_ENHANCE, "i", arr); + if (!msg) + return -EBADMSG; + + dbus_error_init(&err); + + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &ret_val, DBUS_TYPE_INVALID); + if (!ret) { + _E("no message : [%s:%s]", err.name, err.message); + dbus_error_free(&err); + ret_val = -EBADMSG; + } + + dbus_message_unref(msg); + return ret_val; +} + +API int display_set_image_enhance(int type, int val) +{ + DBusError err; + DBusMessage *msg; + char str_type[32]; + char str_val[32]; + char *arr[2]; + int ret, ret_val; + + snprintf(str_type, sizeof(str_type), "%d", type); + arr[0] = str_type; + snprintf(str_val, sizeof(str_val), "%d", val); + arr[1] = str_val; + + msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME, + DEVICED_PATH_DISPLAY, DEVICED_INTERFACE_DISPLAY, + METHOD_SET_IMAGE_ENHANCE, "ii", arr); + if (!msg) + return -EBADMSG; + + dbus_error_init(&err); + + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &ret_val, DBUS_TYPE_INVALID); + if (!ret) { + _E("no message : [%s:%s]", err.name, err.message); + dbus_error_free(&err); + ret_val = -EBADMSG; + } + + dbus_message_unref(msg); + return ret_val; +} + +API int display_set_frame_rate(int val) +{ + return display_set_refresh_rate(REFRESH_SETTING, val); +} + +API int display_set_refresh_rate(enum refresh_app app, int val) +{ + char str_app[32]; + char str_val[32]; + char *arr[2]; + + snprintf(str_app, sizeof(str_app), "%d", app); + arr[0] = str_app; + snprintf(str_val, sizeof(str_val), "%d", val); + arr[1] = str_val; + + return dbus_method_sync(DEVICED_BUS_NAME, + DEVICED_PATH_DISPLAY, DEVICED_INTERFACE_DISPLAY, + METHOD_SET_REFRESH_RATE, "ii", arr); +} + +API int display_get_color_blind(void) +{ + DBusError err; + DBusMessage *msg; + int ret, ret_val; + + msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME, + DEVICED_PATH_DISPLAY, DEVICED_INTERFACE_DISPLAY, + METHOD_GET_COLOR_BLIND, NULL, NULL); + if (!msg) + return -EBADMSG; + + dbus_error_init(&err); + + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &ret_val, DBUS_TYPE_INVALID); + if (!ret) { + _E("no message : [%s:%s]", err.name, err.message); + dbus_error_free(&err); + ret_val = -EBADMSG; + } + + dbus_message_unref(msg); + return ret_val; +} + +API int display_set_color_blind(int enable, struct blind_color_info *info) +{ + DBusError err; + DBusMessage *msg; + char str_enable[32]; + char str_red[32]; + char str_grn[32]; + char str_blu[32]; + char *arr[4]; + int ret, ret_val; + + snprintf(str_enable, sizeof(str_enable), "%d", enable); + arr[0] = str_enable; + snprintf(str_red, sizeof(str_red), "%llu", BLIND_COLOR(info->RrCr, info->RgCg, info->RbCb)); + arr[1] = str_red; + snprintf(str_grn, sizeof(str_grn), "%llu", BLIND_COLOR(info->GrMr, info->GgMg, info->GbMb)); + arr[2] = str_grn; + snprintf(str_blu, sizeof(str_blu), "%llu", BLIND_COLOR(info->BrYr, info->BgYg, info->BbYb)); + arr[3] = str_blu; + + _D("red : %s, grn : %s, blu : %s", str_red, str_grn, str_blu); + + msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME, + DEVICED_PATH_DISPLAY, DEVICED_INTERFACE_DISPLAY, + METHOD_SET_COLOR_BLIND, "uttt", arr); + if (!msg) + return -EBADMSG; + + dbus_error_init(&err); + + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &ret_val, DBUS_TYPE_INVALID); + if (!ret) { + _E("no message : [%s:%s]", err.name, err.message); + dbus_error_free(&err); + ret_val = -EBADMSG; + } + + dbus_message_unref(msg); + return ret_val; +} + +static inline char *get_lcd_str(unsigned int val) +{ + switch (val) { + case LCD_NORMAL: + return STR_LCD_ON; + case LCD_DIM: + return STR_LCD_DIM; + case LCD_OFF: + return STR_LCD_OFF; + case SUSPEND: + return STR_SUSPEND; + default: + return NULL; + } +} + +static void display_change_cb(void *data, DBusMessage *msg, DBusError *unused) +{ + DBusError err; + int ret, val; + + if (!msg) + return; + + dbus_error_init(&err); + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &val, DBUS_TYPE_INVALID); + if (!ret) { + _E("no message [%s:%s]", err.name, err.message); + dbus_error_free(&err); + return; + } + _D("%s-%s : %d", DEVICED_INTERFACE_DISPLAY, METHOD_CHANGE_STATE, val); +} + +API int display_change_state(unsigned int s_bits) +{ + char *p, *pa[1]; + int ret; + + p = get_lcd_str(s_bits); + if (!p) + return -EINVAL; + pa[0] = p; + + ret = dbus_method_async_with_reply(DEVICED_BUS_NAME, + DEVICED_PATH_DISPLAY, DEVICED_INTERFACE_DISPLAY, + METHOD_CHANGE_STATE, "s", pa, display_change_cb, -1, NULL); + if (ret < 0) + _E("no message : failed to change state"); + + _D("%s-%s : %d", DEVICED_INTERFACE_DISPLAY, METHOD_CHANGE_STATE, ret); + + return ret; +} + +static void display_lock_cb(void *data, DBusMessage *msg, DBusError *unused) +{ + DBusError err; + int ret, val; + + if (!msg) + return; + + dbus_error_init(&err); + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &val, DBUS_TYPE_INVALID); + if (!ret) { + _E("no message [%s:%s]", err.name, err.message); + dbus_error_free(&err); + return; + } + _D("%s-%s : %d", DEVICED_INTERFACE_DISPLAY, METHOD_LOCK_STATE, val); +} + +API int display_lock_state(unsigned int s_bits, unsigned int flag, + unsigned int timeout) +{ + char *p, *pa[4]; + char str_timeout[32]; + int ret; + + p = get_lcd_str(s_bits); + if (!p) + return -EINVAL; + pa[0] = p; + + if (flag & GOTO_STATE_NOW) + /* if the flag is true, go to the locking state directly */ + p = STR_GOTOSTATENOW; + else + p = STR_STAYCURSTATE; + pa[1] = p; + + if (flag & HOLD_KEY_BLOCK) + p = STR_HOLDKEYBLOCK; + else if (flag & STANDBY_MODE) + p = STR_STANDBYMODE; + else + p = STR_NULL; + pa[2] = p; + + if (timeout < 0) + return -EINVAL; + + snprintf(str_timeout, sizeof(str_timeout), "%d", timeout); + pa[3] = str_timeout; + + ret = dbus_method_async_with_reply(DEVICED_BUS_NAME, + DEVICED_PATH_DISPLAY, DEVICED_INTERFACE_DISPLAY, + METHOD_LOCK_STATE, "sssi", pa, display_lock_cb, -1, NULL); + if (ret < 0) + _E("no message : failed to lock state"); + + _D("%s-%s : %d", DEVICED_INTERFACE_DISPLAY, METHOD_LOCK_STATE, ret); + + return ret; +} + +static void display_unlock_cb(void *data, DBusMessage *msg, DBusError *unused) +{ + DBusError err; + int ret, val; + + if (!msg) + return; + + dbus_error_init(&err); + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &val, DBUS_TYPE_INVALID); + if (!ret) { + _E("no message [%s:%s]", err.name, err.message); + dbus_error_free(&err); + return; + } + _D("%s-%s : %d", DEVICED_INTERFACE_DISPLAY, METHOD_UNLOCK_STATE, val); +} + +API int display_unlock_state(unsigned int s_bits, unsigned int flag) +{ + char *p, *pa[2]; + int ret; + + p = get_lcd_str(s_bits); + if (!p) + return -EINVAL; + pa[0] = p; + + switch (flag) { + case PM_SLEEP_MARGIN: + p = STR_SLEEP_MARGIN; + break; + case PM_RESET_TIMER: + p = STR_RESET_TIMER; + break; + case PM_KEEP_TIMER: + p = STR_KEEP_TIMER; + break; + default: + return -EINVAL; + } + pa[1] = p; + + ret = dbus_method_async_with_reply(DEVICED_BUS_NAME, + DEVICED_PATH_DISPLAY, DEVICED_INTERFACE_DISPLAY, + METHOD_UNLOCK_STATE, "ss", pa, display_unlock_cb, -1, NULL); + if (ret < 0) + _E("no message : failed to unlock state"); + + _D("%s-%s : %d", DEVICED_INTERFACE_DISPLAY, METHOD_UNLOCK_STATE, ret); + + return ret; +} + +API int display_get_enhanced_touch(void) +{ + return dbus_method_sync(DEVICED_BUS_NAME, + DEVICED_PATH_DISPLAY, DEVICED_INTERFACE_DISPLAY, + METHOD_GET_ENHANCED_TOUCH, NULL, NULL); +} + +API int display_set_enhanced_touch(int enable) +{ + char *arr[1]; + char str_enable[32]; + + snprintf(str_enable, sizeof(str_enable), "%d", enable); + arr[0] = str_enable; + + return dbus_method_sync(DEVICED_BUS_NAME, + DEVICED_PATH_DISPLAY, DEVICED_INTERFACE_DISPLAY, + METHOD_SET_ENHANCED_TOUCH, "i", arr); +} + +API int display_get_hbm(void) +{ + return dbus_method_sync(DEVICED_BUS_NAME, + DEVICED_PATH_DISPLAY, DEVICED_INTERFACE_DISPLAY, + METHOD_GET_HBM, NULL, NULL); +} + +API int display_set_hbm(int enable) +{ + char *arr[1]; + char str_enable[2]; + + if (enable != 0 && enable != 1) + return -EINVAL; + + snprintf(str_enable, sizeof(str_enable), "%d", enable); + arr[0] = str_enable; + + return dbus_method_sync(DEVICED_BUS_NAME, + DEVICED_PATH_DISPLAY, DEVICED_INTERFACE_DISPLAY, + METHOD_SET_HBM, "i", arr); +} + +API int display_enable_hbm(int enable, int timeout) +{ + char *arr[2]; + char str_enable[2]; + char str_timeout[32]; + + if (enable != 0 && enable != 1) + return -EINVAL; + + if (timeout < 0) + return -EINVAL; + + snprintf(str_enable, sizeof(str_enable), "%d", enable); + arr[0] = str_enable; + + snprintf(str_timeout, sizeof(str_timeout), "%d", timeout); + arr[1] = str_timeout; + + return dbus_method_sync(DEVICED_BUS_NAME, + DEVICED_PATH_DISPLAY, DEVICED_INTERFACE_DISPLAY, + METHOD_SET_HBM_TIMEOUT, "ii", arr); +} + diff --git a/src/libdeviced/haptic.c b/src/libdeviced/haptic.c new file mode 100644 index 0000000..7940923 --- /dev/null +++ b/src/libdeviced/haptic.c @@ -0,0 +1,767 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "log.h" +#include "dbus.h" +#include "haptic-plugin-intf.h" +#include "dd-haptic.h" +#include "common.h" + +#define METHOD_OPEN_DEVICE "OpenDevice" +#define METHOD_CLOSE_DEVICE "CloseDevice" +#define METHOD_STOP_DEVICE "StopDevice" +#define METHOD_VIBRATE_MONOTONE "VibrateMonotone" +#define METHOD_VIBRATE_BUFFER "VibrateBuffer" +#define METHOD_GET_COUNT "GetCount" +#define METHOD_GET_STATE "GetState" +#define METHOD_GET_DURATION "GetDuration" +#define METHOD_CREATE_EFFECT "CreateEffect" +#define METHOD_SAVE_BINARY "SaveBinary" + +#define TEMP_BUFFER_SIZE (64*1024) + +/* START of Static Function Section */ +static unsigned char* convert_file_to_buffer(const char *file_name, int *size) +{ + FILE *pf; + long file_size; + unsigned char *pdata = NULL; + + if (!file_name) + return NULL; + + /* Get File Stream Pointer */ + pf = fopen(file_name, "rb"); + if (!pf) { + _E("fopen failed : %s", strerror(errno)); + return NULL; + } + + if (fseek(pf, 0, SEEK_END)) + goto error; + + file_size = ftell(pf); + if (fseek(pf, 0, SEEK_SET)) + goto error; + + if (file_size < 0) + goto error; + + pdata = (unsigned char*)malloc(file_size); + if (!pdata) + goto error; + + if (fread(pdata, 1, file_size, pf) != file_size) + goto err_free; + + fclose(pf); + *size = file_size; + return pdata; + +err_free: + free(pdata); + +error: + fclose(pf); + + _E("failed to convert file to buffer (%s)", strerror(errno)); + return NULL; +} + +static int save_data(const unsigned char *data, int size, const char *file_path) +{ + FILE *file; + int fd; + + file = fopen(file_path, "wb+"); + if (file == NULL) { + _E("To open file is failed : %s", strerror(errno)); + return -1; + } + + if (fwrite(data, 1, size, file) != size) { + _E("To write file is failed : %s", strerror(errno)); + fclose(file); + return -1; + } + + fd = fileno(file); + if (fd < 0) { + _E("To get file descriptor is failed : %s", strerror(errno)); + fclose(file); + return -1; + } + + if (fsync(fd) < 0) { + _E("To be synchronized with the disk is failed : %s", strerror(errno)); + fclose(file); + return -1; + } + + fclose(file); + return 0; +} + +static haptic_feedback_e convert_setting_to_module_level(void) +{ + int setting_fb_level; + + if (vconf_get_int(VCONFKEY_SETAPPL_TOUCH_FEEDBACK_VIBRATION_LEVEL_INT, &setting_fb_level) < 0) { + setting_fb_level = SETTING_VIB_FEEDBACK_LEVEL3; + } + + if (setting_fb_level < HAPTIC_FEEDBACK_0 || setting_fb_level > HAPTIC_FEEDBACK_5) + return -1; + + switch (setting_fb_level) { + case SETTING_VIB_FEEDBACK_LEVEL0 : return HAPTIC_FEEDBACK_0; + case SETTING_VIB_FEEDBACK_LEVEL1 : return HAPTIC_FEEDBACK_1; + case SETTING_VIB_FEEDBACK_LEVEL2 : return HAPTIC_FEEDBACK_2; + case SETTING_VIB_FEEDBACK_LEVEL3 : return HAPTIC_FEEDBACK_3; + case SETTING_VIB_FEEDBACK_LEVEL4 : return HAPTIC_FEEDBACK_4; + case SETTING_VIB_FEEDBACK_LEVEL5 : return HAPTIC_FEEDBACK_5; + default: + break; + } + return -1; +} +/* END of Static Function Section */ + +API int haptic_get_count(int *device_number) +{ + int ret; + + /* check if pointer is valid */ + if (device_number == NULL) { + _E("Invalid parameter : device_number(NULL)"); + return HAPTIC_ERROR_INVALID_PARAMETER; + } + + /* request to deviced to get haptic count */ + ret = dbus_method_sync(DEVICED_BUS_NAME, + DEVICED_PATH_HAPTIC, DEVICED_INTERFACE_HAPTIC, + METHOD_GET_COUNT, NULL, NULL); + if (ret < 0) + return HAPTIC_ERROR_OPERATION_FAILED; + + *device_number = ret; + return HAPTIC_ERROR_NONE; +} + +API int haptic_open(haptic_device_e device_index, haptic_device_h *device_handle) +{ + char str_index[32]; + char *arr[1]; + int ret; + + /* check if index is valid */ + if (!(device_index == HAPTIC_DEVICE_0 || device_index == HAPTIC_DEVICE_1 || + device_index == HAPTIC_DEVICE_ALL)) { + _E("Invalid parameter : device_index(%d)", device_index); + return HAPTIC_ERROR_INVALID_PARAMETER; + } + + /* check if pointer is valid */ + if (device_handle == NULL) { + _E("Invalid parameter : device_handle(NULL)"); + return HAPTIC_ERROR_INVALID_PARAMETER; + } + + snprintf(str_index, sizeof(str_index), "%d", device_index); + arr[0] = str_index; + + /* request to deviced to open haptic device */ + ret = dbus_method_sync(DEVICED_BUS_NAME, + DEVICED_PATH_HAPTIC, DEVICED_INTERFACE_HAPTIC, + METHOD_OPEN_DEVICE, "i", arr); + if (ret < 0) + return HAPTIC_ERROR_OPERATION_FAILED; + + *device_handle = (haptic_device_h)ret; + return HAPTIC_ERROR_NONE; +} + +API int haptic_close(haptic_device_h device_handle) +{ + char str_handle[32]; + char *arr[1]; + int ret; + + /* check if handle is valid */ + if (device_handle == NULL) { + _E("Invalid parameter : device_handle(NULL)"); + return HAPTIC_ERROR_INVALID_PARAMETER; + } + + snprintf(str_handle, sizeof(str_handle), "%u", device_handle); + arr[0] = str_handle; + + /* request to deviced to open haptic device */ + ret = dbus_method_sync(DEVICED_BUS_NAME, + DEVICED_PATH_HAPTIC, DEVICED_INTERFACE_HAPTIC, + METHOD_CLOSE_DEVICE, "u", arr); + if (ret < 0) + return HAPTIC_ERROR_OPERATION_FAILED; + + return HAPTIC_ERROR_NONE; +} + +API int haptic_vibrate_monotone(haptic_device_h device_handle, int duration, haptic_effect_h *effect_handle) +{ + return haptic_vibrate_monotone_with_detail(device_handle, + duration, + HAPTIC_FEEDBACK_AUTO, + HAPTIC_PRIORITY_MIN, + effect_handle); +} + +API int haptic_vibrate_monotone_with_detail(haptic_device_h device_handle, + int duration, + haptic_feedback_e feedback, + haptic_priority_e priority, + haptic_effect_h *effect_handle) +{ + char str_handle[32]; + char str_duration[32]; + char str_feedback[32]; + char str_priority[32]; + char *arr[4]; + int ret; + + /* check if handle is valid */ + if (device_handle == NULL) { + _E("Invalid parameter : device_handle(NULL)"); + return HAPTIC_ERROR_INVALID_PARAMETER; + } + + /* check if passed arguments are valid */ + if (duration < 0 && duration != HAPTIC_DURATION_UNLIMITED) { + _E("Invalid parameter : duration(%d)", duration); + return HAPTIC_ERROR_INVALID_PARAMETER; + } + + if (feedback < HAPTIC_FEEDBACK_0 || feedback > HAPTIC_FEEDBACK_AUTO) { + _E("Invalid parameter : feedback(%d)", feedback); + return HAPTIC_ERROR_INVALID_PARAMETER; + } + + if (priority < HAPTIC_PRIORITY_MIN || priority > HAPTIC_PRIORITY_HIGH) { + _E("Invalid parameter : priority(%d)", priority); + return HAPTIC_ERROR_INVALID_PARAMETER; + } + + /* in case of FEEDBACK_AUTO, should be converted */ + if (feedback == HAPTIC_FEEDBACK_AUTO) + feedback = convert_setting_to_module_level(); + + snprintf(str_handle, sizeof(str_handle), "%u", device_handle); + arr[0] = str_handle; + snprintf(str_duration, sizeof(str_duration), "%d", duration); + arr[1] = str_duration; + snprintf(str_feedback, sizeof(str_feedback), "%d", feedback); + arr[2] = str_feedback; + snprintf(str_priority, sizeof(str_priority), "%d", priority); + arr[3] = str_priority; + + /* request to deviced to open haptic device */ + ret = dbus_method_sync(DEVICED_BUS_NAME, + DEVICED_PATH_HAPTIC, DEVICED_INTERFACE_HAPTIC, + METHOD_VIBRATE_MONOTONE, "uiii", arr); + if (ret < 0) + return HAPTIC_ERROR_OPERATION_FAILED; + + if (effect_handle != NULL) + *effect_handle = (haptic_effect_h)ret; + + return HAPTIC_ERROR_NONE; +} + +API int haptic_vibrate_file(haptic_device_h device_handle, const char *file_path, haptic_effect_h *effect_handle) +{ + char *vibe_buffer; + int size, ret; + + vibe_buffer = convert_file_to_buffer(file_path, &size); + if (!vibe_buffer) { + _E("Convert file to buffer error"); + return HAPTIC_ERROR_OPERATION_FAILED; + } + + ret = haptic_vibrate_buffers_with_detail(device_handle, + vibe_buffer, + size, + HAPTIC_ITERATION_ONCE, + HAPTIC_FEEDBACK_AUTO, + HAPTIC_PRIORITY_MIN, + effect_handle); + free(vibe_buffer); + return ret; +} + +API int haptic_vibrate_file_with_detail(haptic_device_h device_handle, + const char *file_path, + haptic_iteration_e iteration, + haptic_feedback_e feedback, + haptic_priority_e priority, + haptic_effect_h *effect_handle) +{ + char *vibe_buffer; + int size, ret; + + vibe_buffer = convert_file_to_buffer(file_path, &size); + if (!vibe_buffer) { + _E("Convert file to buffer error"); + return HAPTIC_ERROR_OPERATION_FAILED; + } + + ret = haptic_vibrate_buffers_with_detail(device_handle, + vibe_buffer, + size, + iteration, + feedback, + priority, + effect_handle); + free(vibe_buffer); + return ret; +} + +API int haptic_vibrate_buffer(haptic_device_h device_handle, const unsigned char *vibe_buffer, haptic_effect_h *effect_handle) +{ + return haptic_vibrate_buffers_with_detail(device_handle, + vibe_buffer, + TEMP_BUFFER_SIZE, + HAPTIC_ITERATION_ONCE, + HAPTIC_FEEDBACK_AUTO, + HAPTIC_PRIORITY_MIN, + effect_handle); +} + +API int haptic_vibrate_buffer_with_detail(haptic_device_h device_handle, + const unsigned char *vibe_buffer, + haptic_iteration_e iteration, + haptic_feedback_e feedback, + haptic_priority_e priority, + haptic_effect_h *effect_handle) +{ + return haptic_vibrate_buffers_with_detail(device_handle, + vibe_buffer, + TEMP_BUFFER_SIZE, + iteration, + feedback, + priority, + effect_handle); +} + +API int haptic_vibrate_buffers(haptic_device_h device_handle, + const unsigned char *vibe_buffer, + int size, + haptic_effect_h *effect_handle) +{ + return haptic_vibrate_buffers_with_detail(device_handle, + vibe_buffer, + size, + HAPTIC_ITERATION_ONCE, + HAPTIC_FEEDBACK_AUTO, + HAPTIC_PRIORITY_MIN, + effect_handle); +} + +API int haptic_vibrate_buffers_with_detail(haptic_device_h device_handle, + const unsigned char *vibe_buffer, + int size, + haptic_iteration_e iteration, + haptic_feedback_e feedback, + haptic_priority_e priority, + haptic_effect_h *effect_handle) +{ + char str_handle[32]; + char str_iteration[32]; + char str_feedback[32]; + char str_priority[32]; + char *arr[6]; + struct dbus_byte bytes; + int ret; + + /* check if handle is valid */ + if (device_handle == NULL) { + _E("Invalid parameter : device_handle(NULL)"); + return HAPTIC_ERROR_INVALID_PARAMETER; + } + + /* check if passed arguments are valid */ + if (vibe_buffer == NULL) { + _E("Invalid parameter : vibe_buffer(NULL)"); + return HAPTIC_ERROR_INVALID_PARAMETER; + } + + if (iteration < HAPTIC_ITERATION_ONCE || iteration > HAPTIC_ITERATION_INFINITE) { + _E("Invalid parameter : iteration(%d)", iteration); + return HAPTIC_ERROR_INVALID_PARAMETER; + } + + if (feedback < HAPTIC_FEEDBACK_0 || feedback > HAPTIC_FEEDBACK_AUTO) { + _E("Invalid parameter : feedback(%d)", feedback); + return HAPTIC_ERROR_INVALID_PARAMETER; + } + + if (priority < HAPTIC_PRIORITY_MIN || priority > HAPTIC_PRIORITY_HIGH) { + _E("Invalid parameter : priority(%d)", priority); + return HAPTIC_ERROR_INVALID_PARAMETER; + } + + /* in case of FEEDBACK_AUTO, should be converted */ + if (feedback == HAPTIC_FEEDBACK_AUTO) + feedback = convert_setting_to_module_level(); + + snprintf(str_handle, sizeof(str_handle), "%u", device_handle); + arr[0] = str_handle; + bytes.size = size; + bytes.data = vibe_buffer; + arr[2] = (char*)&bytes; + snprintf(str_iteration, sizeof(str_iteration), "%d", iteration); + arr[3] = str_iteration; + snprintf(str_feedback, sizeof(str_feedback), "%d", feedback); + arr[4] = str_feedback; + snprintf(str_priority, sizeof(str_priority), "%d", priority); + arr[5] = str_priority; + + /* request to deviced to open haptic device */ + ret = dbus_method_sync(DEVICED_BUS_NAME, + DEVICED_PATH_HAPTIC, DEVICED_INTERFACE_HAPTIC, + METHOD_VIBRATE_BUFFER, "uayiii", arr); + if (ret < 0) + return HAPTIC_ERROR_OPERATION_FAILED; + + if (effect_handle != NULL) + *effect_handle = (haptic_effect_h)ret; + + return HAPTIC_ERROR_NONE; +} + +API int haptic_stop_effect(haptic_device_h device_handle, haptic_effect_h effect_handle) +{ + return haptic_stop_all_effects(device_handle); +} + +API int haptic_stop_all_effects(haptic_device_h device_handle) +{ + char str_handle[32]; + char *arr[1]; + int ret; + + /* check if handle is valid */ + if (device_handle == NULL) { + _E("Invalid parameter : device_handle(NULL)"); + return HAPTIC_ERROR_INVALID_PARAMETER; + } + + snprintf(str_handle, sizeof(str_handle), "%u", device_handle); + arr[0] = str_handle; + + /* request to deviced to open haptic device */ + ret = dbus_method_sync(DEVICED_BUS_NAME, + DEVICED_PATH_HAPTIC, DEVICED_INTERFACE_HAPTIC, + METHOD_STOP_DEVICE, "u", arr); + if (ret < 0) + return HAPTIC_ERROR_OPERATION_FAILED; + + return HAPTIC_ERROR_NONE; +} + +API int haptic_get_effect_state(haptic_device_h device_handle, haptic_effect_h effect_handle, haptic_state_e *effect_state) +{ + char str_index[32]; + char *arr[1]; + int ret; + + /* check if handle is valid */ + if (device_handle == NULL) { + _E("Invalid parameter : device_handle(NULL)"); + return HAPTIC_ERROR_INVALID_PARAMETER; + } + + /* check if pointer is valid */ + if (effect_state == NULL) { + _E("Invalid parameter : effect_state(NULL)"); + return HAPTIC_ERROR_INVALID_PARAMETER; + } + + snprintf(str_index, sizeof(str_index), "%d", HAPTIC_DEVICE_0); + arr[0] = str_index; + + /* request to deviced to open haptic device */ + ret = dbus_method_sync(DEVICED_BUS_NAME, + DEVICED_PATH_HAPTIC, DEVICED_INTERFACE_HAPTIC, + METHOD_GET_STATE, "i", arr); + if (ret < 0) + return HAPTIC_ERROR_OPERATION_FAILED; + + *effect_state = (haptic_state_e)ret; + return HAPTIC_ERROR_NONE; +} + +API int haptic_create_effect(unsigned char *vibe_buffer, + int max_bufsize, + haptic_effect_element_s *elem_arr, + int max_elemcnt) +{ + DBusError err; + DBusMessage *msg; + dbus_bool_t ret; + char str_bufsize[32]; + char str_elemcnt[32]; + char *arr[4]; + char *data; + int i, temp, size, ret_val; + struct dbus_byte bytes; + + /* check if passed arguments are valid */ + if (vibe_buffer == NULL) { + _E("Invalid parameter : vibe_buffer(NULL)"); + return HAPTIC_ERROR_INVALID_PARAMETER; + } + + if (max_bufsize <= 0) { + _E("Invalid parameter : max_bufsize(%d)", max_bufsize); + return HAPTIC_ERROR_INVALID_PARAMETER; + } + + if (elem_arr == NULL) { + _E("Invalid parameter : elem_arr(NULL)"); + return HAPTIC_ERROR_INVALID_PARAMETER; + } + + if (max_elemcnt <= 0) { + _E("Invalid parameter : max_elemcnt(%d)", max_elemcnt); + return HAPTIC_ERROR_INVALID_PARAMETER; + } + + /* convert to proper feedback level in case of auto */ + for (i = 0; i < max_elemcnt; i++) { + if (elem_arr[i].haptic_level == HAPTIC_FEEDBACK_AUTO) { + vconf_get_int(VCONFKEY_SETAPPL_TOUCH_FEEDBACK_VIBRATION_LEVEL_INT, &temp); + elem_arr[i].haptic_level = temp*20; + } + } + + snprintf(str_bufsize, sizeof(str_bufsize), "%d", max_bufsize); + arr[0] = str_bufsize; + bytes.size = sizeof(haptic_effect_element_s)*max_elemcnt; + bytes.data = (unsigned char*)elem_arr; + arr[2] = (char*)&bytes; + snprintf(str_elemcnt, sizeof(str_elemcnt), "%d", max_elemcnt); + arr[3] = str_elemcnt; + + /* request to deviced to open haptic device */ + msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME, + DEVICED_PATH_HAPTIC, DEVICED_INTERFACE_HAPTIC, + METHOD_CREATE_EFFECT, "iayi", arr); + if (!msg) + return HAPTIC_ERROR_OPERATION_FAILED; + + dbus_error_init(&err); + + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &data, &size, + DBUS_TYPE_INT32, &ret_val, DBUS_TYPE_INVALID); + if (!ret) { + _E("no message : [%s:%s]", err.name, err.message); + dbus_error_free(&err); + goto err; + } + + if (ret_val < 0) { + _E("%s-%s failed : %d", DEVICED_INTERFACE_HAPTIC, METHOD_CREATE_EFFECT, ret_val); + goto err; + } + + if (max_bufsize < size) { + _E("max_bufsize(%d) is smaller than effect buffer size(%d)", max_bufsize, size); + goto err; + } + + memcpy(vibe_buffer, data, max_bufsize); + dbus_message_unref(msg); + return HAPTIC_ERROR_NONE; +err: + dbus_message_unref(msg); + return HAPTIC_ERROR_OPERATION_FAILED; +} + +API int haptic_save_effect(const unsigned char *vibe_buffer, + int max_bufsize, + const char *file_path) +{ + struct stat buf; + int size, ret; + + /* check if passed arguments are valid */ + if (vibe_buffer == NULL) { + _E("Invalid parameter : vibe_buffer(NULL)"); + return HAPTIC_ERROR_INVALID_PARAMETER; + } + + if (max_bufsize <= 0) { + _E("Invalid parameter : max_bufsize(%d)", max_bufsize); + return HAPTIC_ERROR_INVALID_PARAMETER; + } + + if (file_path == NULL) { + _E("Invalid parameter : file_path(NULL)"); + return HAPTIC_ERROR_INVALID_PARAMETER; + } + + /* check if the file already exists */ + if (!stat(file_path, &buf)) { + _E("Already exist : file_path(%s)", file_path); + return HAPTIC_ERROR_FILE_EXISTS; + } + + _D("file path : %s", file_path); + ret = save_data(vibe_buffer, max_bufsize, file_path); + if (ret < 0) { + _E("fail to save data"); + return HAPTIC_MODULE_OPERATION_FAILED; + } + + return HAPTIC_ERROR_NONE; +} + +API int haptic_get_file_duration(haptic_device_h device_handle, const char *file_path, int *file_duration) +{ + char *vibe_buffer; + int size, ret; + + vibe_buffer = convert_file_to_buffer(file_path, &size); + if (!vibe_buffer) { + _E("Convert file to buffer error"); + return HAPTIC_ERROR_OPERATION_FAILED; + } + + ret = haptic_get_buffers_duration(device_handle, + vibe_buffer, + size, + file_duration); + free(vibe_buffer); + return ret; +} + +API int haptic_get_buffer_duration(haptic_device_h device_handle, const unsigned char *vibe_buffer, int *buffer_duration) +{ + return haptic_get_buffers_duration(device_handle, + vibe_buffer, + TEMP_BUFFER_SIZE, + buffer_duration); +} + +API int haptic_get_buffers_duration(haptic_device_h device_handle, const unsigned char *vibe_buffer, int size, int *buffer_duration) +{ + char str_handle[32]; + char *arr[3]; + struct dbus_byte bytes; + int ret; + + /* check if handle is valid */ + if (device_handle == NULL) { + _E("Invalid parameter : device_handle(NULL)"); + return HAPTIC_ERROR_INVALID_PARAMETER; + } + + if (vibe_buffer == NULL) { + _E("Invalid parameter : vibe_buffer(NULL)"); + return HAPTIC_ERROR_INVALID_PARAMETER; + } + + /* check if pointer is valid */ + if (buffer_duration == NULL) { + _E("Invalid parameter : buffer_duration(NULL)"); + return HAPTIC_ERROR_INVALID_PARAMETER; + } + + snprintf(str_handle, sizeof(str_handle), "%u", device_handle); + arr[0] = str_handle; + bytes.size = size; + bytes.data = vibe_buffer; + arr[2] = (char*)&bytes; + + /* request to deviced to open haptic device */ + ret = dbus_method_sync(DEVICED_BUS_NAME, + DEVICED_PATH_HAPTIC, DEVICED_INTERFACE_HAPTIC, + METHOD_GET_DURATION, "uay", arr); + if (ret < 0) + return HAPTIC_ERROR_OPERATION_FAILED; + + *buffer_duration = ret; + return HAPTIC_ERROR_NONE; +} + +API int haptic_save_led(const unsigned char *vibe_buffer, int max_bufsize, const char *file_path) +{ + struct stat buf; + char str_bufsize[32]; + char *arr[3]; + struct dbus_byte bytes; + int ret; + + /* check if passed arguments are valid */ + if (vibe_buffer == NULL) { + _E("Invalid parameter : vibe_buffer(NULL)"); + return HAPTIC_ERROR_INVALID_PARAMETER; + } + + if (max_bufsize <= 0) { + _E("Invalid parameter : max_bufsize(%d)", max_bufsize); + return HAPTIC_ERROR_INVALID_PARAMETER; + } + + if (file_path == NULL) { + _E("Invalid parameter : file_path(NULL)"); + return HAPTIC_ERROR_INVALID_PARAMETER; + } + + /* check if the file already exists */ + if (!stat(file_path, &buf)) { + _E("Already exist : file_path(%s)", file_path); + return HAPTIC_ERROR_FILE_EXISTS; + } + + bytes.size = max_bufsize; + bytes.data = vibe_buffer; + arr[1] = (char*)&bytes; + arr[2] = (char*)file_path; + + /* request to deviced to open haptic device */ + ret = dbus_method_sync(DEVICED_BUS_NAME, + DEVICED_PATH_HAPTIC, DEVICED_INTERFACE_HAPTIC, + METHOD_SAVE_BINARY, "ays", arr); + if (ret < 0) + return HAPTIC_ERROR_OPERATION_FAILED; + + return HAPTIC_ERROR_NONE; +} diff --git a/src/libdeviced/led.c b/src/libdeviced/led.c new file mode 100644 index 0000000..86c23a7 --- /dev/null +++ b/src/libdeviced/led.c @@ -0,0 +1,174 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 "log.h" +#include "dbus.h" +#include "common.h" + +#define METHOD_GET_BRIGHTNESS "GetBrightness" +#define METHOD_GET_MAX_BRIGHTNESS "GetMaxBrightness" +#define METHOD_SET_BRIGHTNESS "SetBrightness" +#define METHOD_SET_IR_COMMAND "SetIrCommand" +#define METHOD_SET_MODE "SetMode" + +API int led_get_brightness(void) +{ + DBusError err; + DBusMessage *msg; + int ret, ret_val; + + msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME, + DEVICED_PATH_LED, DEVICED_INTERFACE_LED, + METHOD_GET_BRIGHTNESS, NULL, NULL); + if (!msg) + return -EBADMSG; + + dbus_error_init(&err); + + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &ret_val, DBUS_TYPE_INVALID); + if (!ret) { + _E("no message : [%s:%s]", err.name, err.message); + dbus_error_free(&err); + ret_val = -EBADMSG; + } + + dbus_message_unref(msg); + return ret_val; +} + +API int led_get_max_brightness(void) +{ + DBusError err; + DBusMessage *msg; + int ret, ret_val; + + msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME, + DEVICED_PATH_LED, DEVICED_INTERFACE_LED, + METHOD_GET_MAX_BRIGHTNESS, NULL, NULL); + if (!msg) + return -EBADMSG; + + dbus_error_init(&err); + + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &ret_val, DBUS_TYPE_INVALID); + if (!ret) { + _E("no message : [%s:%s]", err.name, err.message); + dbus_error_free(&err); + ret_val = -EBADMSG; + } + + dbus_message_unref(msg); + return ret_val; +} + +API int led_set_brightness_with_noti(int val, bool enable) +{ + DBusError err; + DBusMessage *msg; + char *arr[2]; + char buf_val[32]; + char buf_noti[32]; + int ret, ret_val; + + snprintf(buf_val, sizeof(buf_val), "%d", val); + arr[0] = buf_val; + snprintf(buf_noti, sizeof(buf_noti), "%d", enable); + arr[1] = buf_noti; + + msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME, + DEVICED_PATH_LED, DEVICED_INTERFACE_LED, + METHOD_SET_BRIGHTNESS, "ii", arr); + if (!msg) + return -EBADMSG; + + dbus_error_init(&err); + + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &ret_val, DBUS_TYPE_INVALID); + if (!ret) { + _E("no message : [%s:%s]", err.name, err.message); + dbus_error_free(&err); + ret_val = -EBADMSG; + } + + dbus_message_unref(msg); + return ret_val; +} + +API int led_set_ir_command(char *value) +{ + DBusError err; + DBusMessage *msg; + char *arr[1]; + int ret, ret_val; + + arr[0] = value; + + msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME, + DEVICED_PATH_LED, DEVICED_INTERFACE_LED, + METHOD_SET_IR_COMMAND, "s", arr); + if (!msg) + return -EBADMSG; + + dbus_error_init(&err); + + ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &ret_val, DBUS_TYPE_INVALID); + if (!ret) { + _E("no message : [%s:%s]", err.name, err.message); + dbus_error_free(&err); + ret_val = -EBADMSG; + } + + dbus_message_unref(msg); + return ret_val; +} + +API int led_set_mode_with_property(int mode, bool val, int on, int off, unsigned int color) +{ + DBusError err; + DBusMessage *msg; + char *arr[5]; + char buf_mode[32], buf_val[32]; + char buf_on[32], buf_off[32]; + char buf_color[32]; + int ret, ret_val; + + snprintf(buf_mode, sizeof(buf_mode), "%d", mode); + arr[0] = buf_mode; + snprintf(buf_val, sizeof(buf_val), "%d", val); + arr[1] = buf_val; + snprintf(buf_on, sizeof(buf_on), "%d", on); + arr[2] = buf_on; + snprintf(buf_off, sizeof(buf_off), "%d", off); + arr[3] = buf_off; + snprintf(buf_color, sizeof(buf_color), "%lu", color); + arr[4] = buf_color; + + return dbus_method_sync(DEVICED_BUS_NAME, + DEVICED_PATH_LED, DEVICED_INTERFACE_LED, + METHOD_SET_MODE, "iiiiu", arr); +} + +API int led_set_mode_with_color(int mode, bool on, unsigned int color) +{ + return led_set_mode_with_property(mode, on, -1, -1, color); +} diff --git a/src/libdeviced/mmc.c b/src/libdeviced/mmc.c new file mode 100644 index 0000000..73f1a1e --- /dev/null +++ b/src/libdeviced/mmc.c @@ -0,0 +1,211 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 "log.h" +#include "dbus.h" +#include "common.h" +#include "dd-mmc.h" + +#define METHOD_REQUEST_SECURE_MOUNT "RequestSecureMount" +#define METHOD_REQUEST_SECURE_UNMOUNT "RequestSecureUnmount" +#define METHOD_REQUEST_MOUNT "RequestMount" +#define METHOD_REQUEST_UNMOUNT "RequestUnmount" +#define METHOD_REQUEST_FORMAT "RequestFormat" + +#define ODE_MOUNT_STATE 1 + +API int mmc_secure_mount(const char *mount_point) +{ + char *arr[1]; + arr[0] = (char *)mount_point; + return dbus_method_sync(DEVICED_BUS_NAME, DEVICED_PATH_MMC, + DEVICED_INTERFACE_MMC, METHOD_REQUEST_SECURE_MOUNT, "s", arr); +} + +API int mmc_secure_unmount(const char *mount_point) +{ + char *arr[1]; + arr[0] = (char *)mount_point; + return dbus_method_sync(DEVICED_BUS_NAME, DEVICED_PATH_MMC, + DEVICED_INTERFACE_MMC, METHOD_REQUEST_SECURE_UNMOUNT, "s", arr); +} + +static void mount_mmc_cb(void *data, DBusMessage *msg, DBusError *err) +{ + struct mmc_contents *mmc_data = (struct mmc_contents*)data; + DBusError r_err; + int r, mmc_ret; + + _D("mount_mmc_cb called"); + + if (!msg) { + _E("no message [%s:%s]", err->name, err->message); + mmc_ret = -EBADMSG; + goto exit; + } + + dbus_error_init(&r_err); + r = dbus_message_get_args(msg, &r_err, DBUS_TYPE_INT32, &mmc_ret, DBUS_TYPE_INVALID); + if (!r) { + _E("no message [%s:%s]", r_err.name, r_err.message); + dbus_error_free(&r_err); + mmc_ret = -EBADMSG; + goto exit; + } + + _I("Mount State : %d", mmc_ret); + +// if (mmc_ret == ODE_MOUNT_STATE) +// return; + +exit: + (mmc_data->mmc_cb)(mmc_ret, mmc_data->user_data); +} + +API int deviced_request_mount_mmc(struct mmc_contents *mmc_data) +{ + void (*mount_cb)(void*, DBusMessage*, DBusError*) = NULL; + void *data = NULL; + + if (mmc_data != NULL && mmc_data->mmc_cb != NULL) { + mount_cb = mount_mmc_cb; + data = mmc_data; + } + + return dbus_method_async_with_reply(DEVICED_BUS_NAME, + DEVICED_PATH_MMC, + DEVICED_INTERFACE_MMC, + METHOD_REQUEST_MOUNT, + NULL, NULL, mount_cb, -1, data); +} + +static void unmount_mmc_cb(void *data, DBusMessage *msg, DBusError *err) +{ + struct mmc_contents *mmc_data = (struct mmc_contents*)data; + DBusError r_err; + int r, mmc_ret; + + _D("unmount_mmc_cb called"); + + if (!msg) { + _E("no message [%s:%s]", err->name, err->message); + mmc_ret = -EBADMSG; + goto exit; + } + + dbus_error_init(&r_err); + r = dbus_message_get_args(msg, &r_err, DBUS_TYPE_INT32, &mmc_ret, DBUS_TYPE_INVALID); + if (!r) { + _E("no message [%s:%s]", r_err.name, r_err.message); + dbus_error_free(&r_err); + mmc_ret = -EBADMSG; + goto exit; + } + + _I("Unmount State : %d", mmc_ret); + +exit: + (mmc_data->mmc_cb)(mmc_ret, mmc_data->user_data); +} + +API int deviced_request_unmount_mmc(struct mmc_contents *mmc_data, int option) +{ + char *arr[1]; + char buf_opt[32]; + void (*unmount_cb)(void*, DBusMessage*, DBusError*) = NULL; + void *data = NULL; + + if (option < 0 || option > 1) + return -EINVAL; + + if (mmc_data != NULL && mmc_data->mmc_cb != NULL) { + unmount_cb = unmount_mmc_cb; + data = mmc_data; + } + + snprintf(buf_opt, sizeof(buf_opt), "%d", option); + arr[0] = buf_opt; + return dbus_method_async_with_reply(DEVICED_BUS_NAME, + DEVICED_PATH_MMC, + DEVICED_INTERFACE_MMC, + METHOD_REQUEST_UNMOUNT, + "i", arr, unmount_cb, -1, data); +} + +static void format_mmc_cb(void *data, DBusMessage *msg, DBusError *err) +{ + struct mmc_contents *mmc_data = (struct mmc_contents*)data; + DBusError r_err; + int r, mmc_ret; + + _D("format_mmc_cb called"); + + if (!msg) { + _E("no message [%s:%s]", err->name, err->message); + mmc_ret = -EBADMSG; + goto exit; + } + + dbus_error_init(&r_err); + r = dbus_message_get_args(msg, &r_err, DBUS_TYPE_INT32, &mmc_ret, DBUS_TYPE_INVALID); + if (!r) { + _E("no message [%s:%s]", r_err.name, r_err.message); + dbus_error_free(&r_err); + mmc_ret = -EBADMSG; + goto exit; + } + + _I("Format State : %d", mmc_ret); + +exit: + (mmc_data->mmc_cb)(mmc_ret, mmc_data->user_data); +} + +API int deviced_request_format_mmc(struct mmc_contents *mmc_data) +{ + return deviced_format_mmc(mmc_data, 1); +} + +API int deviced_format_mmc(struct mmc_contents *mmc_data, int option) +{ + char *arr[1]; + char buf_opt[32]; + void (*format_cb)(void*, DBusMessage*, DBusError*) = NULL; + void *data = NULL; + + if (option < 0 || option > 1) + return -EINVAL; + + if (mmc_data != NULL && mmc_data->mmc_cb != NULL) { + format_cb = format_mmc_cb; + data = mmc_data; + } + + snprintf(buf_opt, sizeof(buf_opt), "%d", option); + arr[0] = buf_opt; + return dbus_method_async_with_reply(DEVICED_BUS_NAME, + DEVICED_PATH_MMC, + DEVICED_INTERFACE_MMC, + METHOD_REQUEST_FORMAT, + "i", arr, format_cb, -1, data); +} diff --git a/src/libdeviced/storage.c b/src/libdeviced/storage.c new file mode 100644 index 0000000..bd2552c --- /dev/null +++ b/src/libdeviced/storage.c @@ -0,0 +1,82 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 "log.h" +#include "common.h" +#include "dd-deviced.h" +#include "dd-storage.h" + +#define INT_PATH "/opt/media" +#define EXT_PATH "/opt/storage/sdcard" +#define EXT_PARENT_PATH "/opt/storage" +#define EXT_OPTION1_PATH "/mnt/mmc" + +static bool check_ext_mount(void) +{ + struct stat parent, ext; + + if (stat(EXT_PATH, &ext) != 0 || stat(EXT_PARENT_PATH, &parent) != 0) + return false; + + if (ext.st_dev == parent.st_dev) + return false; + + return true; +} + +API int storage_get_path(int type, unsigned char *path, int size) +{ + char *ext_path = EXT_PATH; + int option; + + if (type > STORAGE_MAX || path == NULL) + return -EINVAL; + + if (vconf_get_int(VCONFKEY_DEVICED_MOUNT_PATH_OPTION, &option) < 0) + return -EPERM; + + _D("VCONFKEY_DEVICED_MOUNT_PATH_OPTION1 : %d, option : %d", VCONFKEY_DEVICED_MOUNT_PATH_OPTION1, option); + if (option == VCONFKEY_DEVICED_MOUNT_PATH_OPTION1) + ext_path = EXT_OPTION1_PATH; + + switch (type) { + case STORAGE_DEFAULT: + if (check_ext_mount()) + snprintf(path, size, "%s", ext_path); + else + snprintf(path, size, ""); + break; + case STORAGE_INTERNAL: + snprintf(path, size, "%s", INT_PATH); + break; + case STORAGE_EXTERNAL: + snprintf(path, size, "%s", ext_path); + break; + default: + break; + } + + return 0; +} diff --git a/src/libdeviced/usbhost.c b/src/libdeviced/usbhost.c new file mode 100644 index 0000000..ad5104a --- /dev/null +++ b/src/libdeviced/usbhost.c @@ -0,0 +1,254 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 "log.h" +#include "common.h" +#include "dbus.h" + +#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0])) + +#define METHOD_REQUEST_STORAGE_INFO_ALL "StorageInfoAll" +#define METHOD_REQUEST_STORAGE_MOUNT "StorageMount" +#define METHOD_REQUEST_STORAGE_UNMOUNT "StorageUnmount" +#define METHOD_REQUEST_STORAGE_FORMAT "StorageFormat" +#define SIGNAL_NAME_USB_STORAGE_CHANGED "usb_storage_changed" +#define RETRY_MAX 5 + +struct signal_handler { + char *name; + E_DBus_Signal_Handler *handler; + void (*action)(char *type, char *path, int mount, void *param); + void *data; +}; + +static struct signal_handler handlers[] = { + { SIGNAL_NAME_USB_STORAGE_CHANGED , NULL, NULL, NULL }, +}; + +static E_DBus_Connection *conn = NULL; + +static int register_edbus_signal_handler(const char *path, const char *interface, + const char *name, E_DBus_Signal_Cb cb, + void (*action)(char *type, char *path, int mount, void *param), + void *data) +{ + int i, ret; + + if (!conn) { + _E("Use init_usbhost_signal() first to use this function"); + ret = -1; + goto out; + } + + for (i = 0 ; i < ARRAY_SIZE(handlers) ; i++) { + if (strncmp(handlers[i].name, name, strlen(name))) + continue; + break; + } + if (i >= ARRAY_SIZE(handlers)) { + _E("Failed to find \"storage_changed\" signal"); + ret = -1; + goto out; + } + + if (handlers[i].handler) { + _E("The handler is already registered"); + ret = -1; + goto out; + } + + handlers[i].handler = e_dbus_signal_handler_add(conn, NULL, path, + interface, name, cb, NULL); + if (!(handlers[i].handler)) { + _E("fail to add edbus handler"); + ret = -1; + goto out; + } + handlers[i].action = action; + handlers[i].data = data; + + return 0; + +out: + return ret; +} + +static void storage_signal_handler(void *data, DBusMessage *msg) +{ + int i; + char *type, *path; + int mount; + DBusError err; + + if (dbus_message_is_signal(msg, DEVICED_INTERFACE_USBHOST, SIGNAL_NAME_USB_STORAGE_CHANGED) == 0) { + _E("The signal is not for storage changed"); + return; + } + + dbus_error_init(&err); + + if (dbus_message_get_args(msg, &err, + DBUS_TYPE_STRING, &type, + DBUS_TYPE_STRING, &path, + DBUS_TYPE_INT32, &mount, + DBUS_TYPE_INVALID) == 0) { + _E("Failed to get storage info"); + return; + } + + for (i = 0 ; i < ARRAY_SIZE(handlers) ; i++) { + if (strcmp(handlers[i].name, SIGNAL_NAME_USB_STORAGE_CHANGED)) + continue; + break; + } + if (i >= ARRAY_SIZE(handlers)) { + _E("Failed to find \"storage_changed\" signal"); + return; + } + + if (handlers[i].action) + handlers[i].action(type, path, mount, handlers[i].data); +} + +API int init_usbhost_signal(void) +{ + int retry; + + if (conn) + return 0; + + retry = 0; + do { + if (e_dbus_init() > 0) + break; + if (retry >= RETRY_MAX) + return -1; + } while (retry++ < RETRY_MAX); + + conn = e_dbus_bus_get(DBUS_BUS_SYSTEM); + if (!conn) { + _E("Failed to get edbus bus"); + e_dbus_shutdown(); + return -1; + } + + return 0; +} + +API void deinit_usbhost_signal(void) +{ + int i; + + if (!conn) + return; + + for (i = 0 ; i < ARRAY_SIZE(handlers) ; i++) { + if (handlers[i].handler) { + e_dbus_signal_handler_del(conn, handlers[i].handler); + handlers[i].handler = NULL; + } + handlers[i].action = NULL; + handlers[i].data = NULL; + } + + e_dbus_connection_close(conn); + conn = NULL; + + e_dbus_shutdown(); +} + +API int request_usb_storage_info(void) +{ + return dbus_method_sync(DEVICED_BUS_NAME, DEVICED_PATH_USBHOST, + DEVICED_INTERFACE_USBHOST, METHOD_REQUEST_STORAGE_INFO_ALL, NULL, NULL); +} + +API int register_usb_storage_change_handler( + void (*storage_changed)(char *type, char *path, int mount, void *), + void *data) +{ + if (!storage_changed) + return -EINVAL; + + return register_edbus_signal_handler(DEVICED_PATH_USBHOST, + DEVICED_INTERFACE_USBHOST, + SIGNAL_NAME_USB_STORAGE_CHANGED, + storage_signal_handler, + storage_changed, + data); +} + +API int unregister_usb_storage_change_handler(void) +{ + int i; + + for (i = 0 ; i < ARRAY_SIZE(handlers) ; i++) { + if (strcmp(handlers[i].name, SIGNAL_NAME_USB_STORAGE_CHANGED)) + continue; + if (handlers[i].handler == NULL) + continue; + + e_dbus_signal_handler_del(conn, handlers[i].handler); + handlers[i].handler = NULL; + handlers[i].action = NULL; + handlers[i].data = NULL; + return 0; + } + return -1; +} + +API int mount_usb_storage(char *path) +{ + char *param[1]; + + if (!path) + return -1; + + param[0] = path; + return dbus_method_sync(DEVICED_BUS_NAME, DEVICED_PATH_USBHOST, + DEVICED_INTERFACE_USBHOST, METHOD_REQUEST_STORAGE_MOUNT, "s", param); +} + +API int unmount_usb_storage(char *path) +{ + char *param[1]; + + if (!path) + return -1; + + param[0] = path; + return dbus_method_sync(DEVICED_BUS_NAME, DEVICED_PATH_USBHOST, + DEVICED_INTERFACE_USBHOST, METHOD_REQUEST_STORAGE_UNMOUNT, "s", param); +} + +API int format_usb_storage(char *path) +{ + char *param[1]; + + if (!path) + return -1; + + param[0] = path; + return dbus_method_sync(DEVICED_BUS_NAME, DEVICED_PATH_USBHOST, + DEVICED_INTERFACE_USBHOST, METHOD_REQUEST_STORAGE_FORMAT, "s", param); +} diff --git a/src/mmc/app2ext.c b/src/mmc/app2ext.c new file mode 100755 index 0000000..a1318a6 --- /dev/null +++ b/src/mmc/app2ext.c @@ -0,0 +1,166 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 "core/log.h" +#include "core/devices.h" +#include "core/edbus-handler.h" +#include "core/list.h" +#include "mmc/mmc-handler.h" + +#define APP2EXT_PLUGIN_PATH LIBDIR"/libapp2ext.so.0" + +static void *app2ext_dl; +static int (*app2ext_enable)(const char *pkgid); +static int (*app2ext_disable)(const char *pkgid); + +static dd_list *pkgid_head; + +static int app2ext_mount(const char *pkgid) +{ + int r; + + if (!app2ext_enable) + return -ENOENT; + + _I("Attempt mount %s app to sdcard", pkgid); + r = app2ext_enable(pkgid); + if (r < 0) + return r; + + _I("Mount %s app to sdcard", pkgid); + DD_LIST_APPEND(pkgid_head, strdup(pkgid)); + return 0; +} + +int app2ext_unmount(void) +{ + char *str; + dd_list *elem; + int r, n, i; + + if (!app2ext_disable) + return -ENOENT; + + /* if there is no mounted pkg */ + if (!pkgid_head) + return 0; + + n = DD_LIST_LENGTH(pkgid_head); + _I("pkgid_head count : %d", n); + + for (i = 0; i < n; ++i) { + str = DD_LIST_NTH(pkgid_head, 0); + _I("Attempt unmount %s app from sdcard", str); + r = app2ext_disable(str); + if (r < 0) + return r; + _I("Unmount %s app from sdcard", str); + DD_LIST_REMOVE(pkgid_head, str); + free(str); + } + + return 0; +} + +static DBusMessage *edbus_request_mount_app2ext(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + char *pkgid; + int ret; + + ret = dbus_message_get_args(msg, NULL, + DBUS_TYPE_STRING, &pkgid, DBUS_TYPE_INVALID); + if (!ret) { + _I("there is no message"); + ret = -EINVAL; + goto error; + } + + if (!mmc_check_mounted(MMC_MOUNT_POINT)) { + _I("Do not mounted"); + ret = -ENODEV; + goto error; + } + + ret = app2ext_mount(pkgid); + +error: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static const struct edbus_method edbus_methods[] = { + { "RequestMountApp2ext", "s", "i", edbus_request_mount_app2ext }, +}; + +static void app2ext_init(void *data) +{ + int ret; + + app2ext_dl = dlopen(APP2EXT_PLUGIN_PATH, RTLD_LAZY|RTLD_GLOBAL); + if (!app2ext_dl) { + _E("dlopen error (%s)", dlerror()); + return; + } + + app2ext_enable = dlsym(app2ext_dl, "app2ext_enable_external_pkg"); + if (!app2ext_enable) { + _E("dlsym error (%s)", dlerror()); + dlclose(app2ext_dl); + app2ext_dl = NULL; + return; + } + + app2ext_disable = dlsym(app2ext_dl, "app2ext_disable_external_pkg"); + if (!app2ext_disable) { + _E("dlsym error (%s)", dlerror()); + dlclose(app2ext_dl); + app2ext_dl = NULL; + return; + } + + ret = register_edbus_method(DEVICED_PATH_MMC, edbus_methods, ARRAY_SIZE(edbus_methods)); + if (ret < 0) + _E("fail to init edbus method(%d)", ret); +} + +static void app2ext_exit(void *data) +{ + if(!app2ext_dl) + return; + + dlclose(app2ext_dl); + app2ext_dl = NULL; +} + +const struct device_ops app2ext_device_ops = { + .priority = DEVICE_PRIORITY_NORMAL, + .name = "app2ext", + .init = app2ext_init, + .exit = app2ext_exit, +}; + +DEVICE_OPS_REGISTER(&app2ext_device_ops) diff --git a/src/mmc/config.c b/src/mmc/config.c new file mode 100644 index 0000000..7202f16 --- /dev/null +++ b/src/mmc/config.c @@ -0,0 +1,104 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include +#include +#include +#include +#include +#include +#include + +#include "core/log.h" +#include "core/common.h" +#include "core/config-parser.h" +#include "mmc-handler.h" +#include "config.h" + +#define MAX_RATIO_CONF_FILE "/etc/deviced/mmc.conf" +#define MAX_RATIO_PATH "/sys/class/block/mmcblk%d/bdi/max_ratio" +#define MAX_RATIO_CONFIG_RETRY 5 +#define MAX_RATIO_DURATION 100 + +static struct mmc_policy_type { + int max_ratio; +} mmc_policy = { + .max_ratio = MAX_RATIO_DURATION, +}; + +static void mmc_max_ratio(void) +{ + char buf[PATH_MAX]; + FILE *fp; + int ret; + int num; + int retry; + + num = get_block_number(); + snprintf(buf, PATH_MAX, MAX_RATIO_PATH, num); + + for (retry = MAX_RATIO_CONFIG_RETRY; retry > 0 ; retry--) { + ret = sys_set_int(buf, mmc_policy.max_ratio); + if (ret == 0) + break; + } + if (ret < 0) + _E("fail path : %s max_ratio: %d ret %d", buf, mmc_policy.max_ratio, ret); + else + _D("mmc bdi max : %d", mmc_policy.max_ratio); +} + +static int load_config(struct parse_result *result, void *user_data) +{ + struct mmc_policy_type *policy = user_data; + char *name; + char *value; + + _D("%s,%s,%s", result->section, result->name, result->value); + + if (!policy) + return -EINVAL; + + if (!MATCH(result->section, "MMC")) + return -EINVAL; + + name = result->name; + value = result->value; + if (MATCH(name, "MaxRatio")) + policy->max_ratio = atoi(value); + + return 0; +} + +void mmc_load_config(void) +{ + int ret; + ret = config_parse(MAX_RATIO_CONF_FILE, load_config, &mmc_policy); + if (ret < 0) + _E("Failed to load %s, %d Use default value!", MAX_RATIO_CONF_FILE, ret); +} + +void mmc_set_config(enum mmc_config_type type) +{ + switch(type) { + case MAX_RATIO: + mmc_max_ratio(); + break; + } +} diff --git a/src/mmc/config.h b/src/mmc/config.h new file mode 100644 index 0000000..0397910 --- /dev/null +++ b/src/mmc/config.h @@ -0,0 +1,31 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 __MMC_CONFIG_H__ +#define __MMC_CONFIG_H__ + +#include + +enum mmc_config_type { + MAX_RATIO = 0, +}; + +void mmc_set_config(enum mmc_config_type type); +void mmc_load_config(void); +#endif /* __MMC_CONFIG_H__ */ diff --git a/src/mmc/cprm.c b/src/mmc/cprm.c new file mode 100755 index 0000000..776b69d --- /dev/null +++ b/src/mmc/cprm.c @@ -0,0 +1,250 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 "core/log.h" +#include "core/common.h" +#include "core/devices.h" +#include "mmc-handler.h" +#include "core/edbus-handler.h" + +#define CPRM_E_BADARG -2 /* Bad argments */ +#define CPRM_E_FAIL -1 /* General error */ +#define CPRM_E_SUCCESS 0 /* Success */ + +#define SETRESP(x) (x << 11) +#define R1RESP SETRESP(1) /* R1 response command */ +#define ACMD 0x0400 /* Is ACMD */ +#define DT 0x8000 /* With data */ +#define DIR_IN 0x0000 /* Data transfer read */ +#define DIR_OUT 0x4000 /* Data transfer write */ + +#define ACMD18 (18+R1RESP+ACMD+DT+DIR_IN) /* Secure Read Multi Block */ +#define ACMD25 (25+R1RESP+ACMD+DT+DIR_OUT) /* Secure Write Multiple Block */ +#define ACMD43 (43+R1RESP+ACMD+DT+DIR_IN) /* Get MKB */ +#define ACMD44 (44+R1RESP+ACMD+DT+DIR_IN) /* Get MID */ +#define ACMD45 (45+R1RESP+ACMD+DT+DIR_OUT) /* Set CER RN1 */ +#define ACMD46 (46+R1RESP+ACMD+DT+DIR_IN) /* Get CER RN2 */ +#define ACMD47 (47+R1RESP+ACMD+DT+DIR_OUT) /* Set CER RES2 */ +#define ACMD48 (48+R1RESP+ACMD+DT+DIR_IN) /* Get CER RES1 */ + +#define MMC_IOCTL_BASE 0xB3 /* Same as MMC block device major number */ +#define MMC_IOCTL_SET_RETRY_AKE_PROCESS _IOR(MMC_IOCTL_BASE, 104, int) + +struct cprm_request { + unsigned int cmd; + unsigned long arg; + unsigned int *buff; + unsigned int len; +}; + +static int cprm_fd; + +static DBusMessage *edbus_cprm_init(E_DBus_Object *obj, DBusMessage *msg) +{ + + DBusMessageIter iter; + DBusMessage *reply; + int opt, ret = CPRM_E_SUCCESS; + char path[NAME_MAX]; + + ret = get_mmc_devpath(path); + if (ret < 0) { + ret = CPRM_E_SUCCESS; + _E("fail to check mmc"); + if (cprm_fd) + close(cprm_fd); + goto out; + } + _I("devpath :%s", path); + cprm_fd = open(path, O_RDWR); + if (cprm_fd < 0) + _E("fail to open"); +out: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *edbus_cprm_terminate(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int opt, ret = CPRM_E_SUCCESS; + + close(cprm_fd); + _I("cprm is terminated"); + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *edbus_cprm_sendcmd(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter, arr; + DBusMessage *reply; + DBusError err; + int ret = CPRM_E_BADARG; + int result = CPRM_E_FAIL; + int slot; + struct cprm_request cprm_req; + char *data; + char path[NAME_MAX]; + + memset(&cprm_req, 0, sizeof(struct cprm_request)); + ret = get_mmc_devpath(path); + if (ret < 0) { + _E("fail to check mmc"); + ret = CPRM_E_FAIL; + if (cprm_fd) + close(cprm_fd); + goto out; + } + + if (cprm_fd <= 0) { + _E("fail to init"); + goto out; + } + + dbus_error_init(&err); + + ret = dbus_message_get_args(msg, &err, + DBUS_TYPE_INT32, &slot, + DBUS_TYPE_INT32, &cprm_req.cmd, + DBUS_TYPE_UINT32, &cprm_req.arg, + DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &data, &cprm_req.len, + DBUS_TYPE_INVALID); + + if (!ret) { + _E("there is no message"); + ret = CPRM_E_BADARG; + goto out; + } + + if (cprm_req.len <= 0) { + _E("fail to check length %d", cprm_req.len); + goto out; + } + + if ((cprm_req.cmd == ACMD43) || (cprm_req.cmd == ACMD18) || (cprm_req.cmd == ACMD25)) + ret = ((cprm_req.len % 512) != 0) ? CPRM_E_BADARG : CPRM_E_SUCCESS; + else if ((cprm_req.cmd == ACMD44) || (cprm_req.cmd == ACMD45) || (cprm_req.cmd == ACMD46) || + (cprm_req.cmd == ACMD47) || (cprm_req.cmd == ACMD48)) + ret = (cprm_req.len != 8) ? CPRM_E_BADARG : CPRM_E_SUCCESS; + else + ret = CPRM_E_BADARG; + + if (ret != CPRM_E_SUCCESS) { + _E("fail to check param cmd %d. Invalid arguments..", (cprm_req.cmd & 0x3f)); + goto out; + } + + cprm_req.buff = (unsigned int *)data; + + result = ioctl(cprm_fd, cprm_req.cmd, &cprm_req); + + if (result != CPRM_E_SUCCESS) { + _E("cprm_drvr_sendcmd: STUB_SENDCMD() return fail! result:%d", result); + ret = CPRM_E_FAIL; + } else { + ret = CPRM_E_SUCCESS; + } +out: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE_AS_STRING, &arr); + dbus_message_iter_append_fixed_array(&arr, DBUS_TYPE_BYTE, &data, cprm_req.len); + dbus_message_iter_close_container(&iter, &arr); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *edbus_cprm_getslotstat(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + unsigned long ret = 0xFFFFFFFF; + + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT32, &ret); + return reply; +} + +static DBusMessage *edbus_cprm_retry(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int ret = CPRM_E_BADARG; + char path[NAME_MAX]; + + ret = get_mmc_devpath(path); + + if (ret < 0) { + _E("[cprm_drvr_retry] fail, so close cprm handle"); + ret = CPRM_E_FAIL; + if (cprm_fd) + close(cprm_fd); + goto out; + } + + ret = ioctl(cprm_fd, MMC_IOCTL_SET_RETRY_AKE_PROCESS, NULL); + + if (ret != CPRM_E_SUCCESS) { + _E("fail to retry :%d", ret); + ret = CPRM_E_FAIL; + } else { + ret = CPRM_E_SUCCESS; + } +out: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static const struct edbus_method edbus_methods[] = { + { "CprmInit", NULL, "i", edbus_cprm_init}, + { "CprmTerminate", NULL, "i", edbus_cprm_terminate}, + { "CprmSendcmd", "iiuay","ayi", edbus_cprm_sendcmd}, + { "CprmGetslotstat", NULL, "u", edbus_cprm_getslotstat}, + { "CprmRetry", NULL, "i", edbus_cprm_retry}, +}; + +static void cprm_init(void *data) +{ + int ret; + + ret = register_edbus_method(DEVICED_PATH_MMC, edbus_methods, ARRAY_SIZE(edbus_methods)); + if (ret < 0) + _E("fail to init edbus method(%d)", ret); +} + +const struct device_ops cprm_device_ops = { + .priority = DEVICE_PRIORITY_NORMAL, + .name = "cprm", + .init = cprm_init, +}; + +DEVICE_OPS_REGISTER(&cprm_device_ops) diff --git a/src/mmc/ext4.c b/src/mmc/ext4.c new file mode 100644 index 0000000..6253dac --- /dev/null +++ b/src/mmc/ext4.c @@ -0,0 +1,197 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "core/common.h" +#include "core/devices.h" +#include "core/log.h" +#include "mmc-handler.h" + +#define FS_EXT4_NAME "ext4" + +#define FS_EXT4_SMACK_LABEL " /usr/bin/mmc-smack-label" + +struct popup_data { + char *name; + char *key; + char *value; +}; + +static const char *ext4_arg[] = { + "/sbin/mkfs.ext4", + NULL, NULL, +}; + +static const char *ext4_check_arg[] = { + "/sbin/fsck.ext4", + "-f", "-y", NULL, NULL, +}; + +static struct fs_check ext4_info = { + FS_TYPE_EXT4, + "ext4", + 0x438, + 2, + {0x53, 0xef}, +}; + +static int mmc_popup_pid; + +static bool ext4_match(const char *devpath) +{ + char buf[4]; + int fd, r; + + fd = open(devpath, O_RDONLY); + if (fd < 0) { + _E("failed to open fd(%s) : %s", devpath, strerror(errno)); + return false; + } + + /* check fs type with magic code */ + r = lseek(fd, ext4_info.offset, SEEK_SET); + if (r < 0) + goto error; + + r = read(fd, buf, 2); + if (r < 0) + goto error; + + _D("mmc search magic : 0x%2x, 0x%2x", buf[0],buf[1]); + if (memcmp(buf, ext4_info.magic, ext4_info.magic_sz)) + goto error; + + close(fd); + _D("MMC type : %s", ext4_info.name); + return true; + +error: + close(fd); + _E("failed to match with ext4(%s)", devpath); + return false; +} + +static int ext4_check(const char *devpath) +{ + int argc; + argc = ARRAY_SIZE(ext4_check_arg); + ext4_check_arg[argc - 2] = devpath; + return run_child(argc, ext4_check_arg); +} + +static int mmc_check_smack(const char *mount_point) +{ + char buf[NAME_MAX] = {0,}; + + snprintf(buf, sizeof(buf), "%s", mount_point); + launch_evenif_exist(FS_EXT4_SMACK_LABEL, buf); + + vconf_set_int(VCONFKEY_SYSMAN_MMC_STATUS, VCONFKEY_SYSMAN_MMC_MOUNTED); + vconf_set_int(VCONFKEY_SYSMAN_MMC_MOUNT, VCONFKEY_SYSMAN_MMC_MOUNT_COMPLETED); + if (mmc_popup_pid > 0) { + _E("will be killed mmc-popup(%d)", mmc_popup_pid); + kill(mmc_popup_pid, SIGTERM); + } + return 0; +} + +static int check_smack_popup(void) +{ + int ret = -1; + int val = -1; + struct popup_data *params; + static const struct device_ops *apps = NULL; + + ret = vconf_get_int(VCONFKEY_STARTER_SEQUENCE, &val); + if (val == 1 || ret != 0) { + if (apps == NULL) { + apps = find_device("apps"); + if (apps == NULL) + return 0; + } + params = malloc(sizeof(struct popup_data)); + if (params == NULL) { + _E("Malloc failed"); + return -1; + } + params->name = MMC_POPUP_NAME; + params->key = MMC_POPUP_APP_KEY; + params->value = MMC_POPUP_SMACK_VALUE; + apps->init(params); + free(params); + } + + return 0; +} + +static int ext4_mount(bool smack, const char *devpath, const char *mount_point) +{ + int r, retry = RETRY_COUNT; + + do { + r = mount(devpath, mount_point, "ext4", 0, NULL); + if (!r) { + _D("Mounted mmc card [ext4]"); + if (smack) { + check_smack_popup(); + mmc_check_smack(mount_point); + } + return 0; + } + usleep(100000); + } while (r < 0 && errno == ENOENT && retry-- > 0); + + return -errno; +} + +static int ext4_format(const char *devpath) +{ + int argc; + argc = ARRAY_SIZE(ext4_arg); + ext4_arg[argc - 2] = devpath; + return run_child(argc, ext4_arg); +} + +static const struct mmc_fs_ops ext4_ops = { + .type = FS_TYPE_EXT4, + .name = "ext4", + .match = ext4_match, + .check = ext4_check, + .mount = ext4_mount, + .format = ext4_format, +}; + +static void __CONSTRUCTOR__ module_init(void) +{ + add_fs(&ext4_ops); +} +/* +static void __DESTRUCTOR__ module_exit(void) +{ + remove_fs(&ext4_ops); +} +*/ diff --git a/src/mmc/mmc-handler.c b/src/mmc/mmc-handler.c new file mode 100644 index 0000000..5493a92 --- /dev/null +++ b/src/mmc/mmc-handler.c @@ -0,0 +1,978 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "core/log.h" +#include "core/device-handler.h" +#include "core/device-notifier.h" +#include "core/common.h" +#include "core/devices.h" +#include "mmc-handler.h" +#include "config.h" +#include "core/edbus-handler.h" +#include "core/list.h" +#include "core/config-parser.h" + +#define VCONFKEY_INTERNAL_PRIVATE_MMC_ID "db/private/sysman/mmc_device_id" + +#define MMC_PARENT_PATH "/opt/storage" +#define MMC_DEV "/dev/mmcblk" + +#define SMACKFS_MAGIC 0x43415d53 +#define SMACKFS_MNT "/smack" + +#ifndef ST_RDONLY +#define ST_RDONLY 0x0001 +#endif + +#define MMC_32GB_SIZE 61315072 +#define FORMAT_RETRY 3 +#define UNMOUNT_RETRY 5 + +#define ODE_MOUNT_STATE 1 + +enum unmount_operation { + UNMOUNT_NORMAL = 0, + UNMOUNT_FORCE, +}; + +enum mmc_operation { + MMC_MOUNT = 0, + MMC_UNMOUNT, + MMC_FORMAT, + MMC_END, +}; + +static void *mount_start(void *arg); +static void *unmount_start(void *arg); +static void *format_start(void *arg); + +static const struct mmc_thread_func { + enum mmc_operation type; + void *(*func) (void*); +} mmc_func[MMC_END] = { + [MMC_MOUNT] = {.type = MMC_MOUNT, .func = mount_start}, + [MMC_UNMOUNT] = {.type = MMC_UNMOUNT, .func = unmount_start}, + [MMC_FORMAT] = {.type = MMC_FORMAT, .func = format_start}, +}; + +struct mmc_data { + int option; + char *devpath; +}; + +struct popup_data { + char *name; + char *key; + char *value; +}; + +static dd_list *fs_head; +static char *mmc_curpath; +static bool smack = false; +static bool mmc_disabled = false; + +int __WEAK__ app2ext_unmount(void); + +static void __CONSTRUCTOR__ smack_check(void) +{ + struct statfs sfs; + int ret; + + do { + ret = statfs(SMACKFS_MNT, &sfs); + } while (ret < 0 && errno == EINTR); + + if (ret == 0 && sfs.f_type == SMACKFS_MAGIC) + smack = true; + _I("smackfs check %d", smack); +} + +void add_fs(const struct mmc_fs_ops *fs) +{ + DD_LIST_APPEND(fs_head, (void*)fs); +} + +void remove_fs(const struct mmc_fs_ops *fs) +{ + DD_LIST_REMOVE(fs_head, (void*)fs); +} + +const struct mmc_fs_ops *find_fs(enum mmc_fs_type type) +{ + struct mmc_fs_ops *fs; + dd_list *elem; + + DD_LIST_FOREACH(fs_head, elem, fs) { + if (fs->type == type) + return fs; + } + return NULL; +} + +bool mmc_check_mounted(const char *mount_point) +{ + struct stat parent_stat, mount_stat; + char parent_path[PATH_MAX]; + + snprintf(parent_path, sizeof(parent_path), "%s", MMC_PARENT_PATH); + + if (stat(mount_point, &mount_stat) != 0 || stat(parent_path, &parent_stat) != 0) + return false; + + if (mount_stat.st_dev == parent_stat.st_dev) + return false; + + return true; +} + +static void launch_syspopup(char *str) +{ + struct popup_data *params; + static const struct device_ops *apps = NULL; + + if (apps == NULL) { + apps = find_device("apps"); + if (apps == NULL) + return; + } + params = malloc(sizeof(struct popup_data)); + if (params == NULL) { + _E("Malloc failed"); + return; + } + params->name = MMC_POPUP_NAME; + params->key = POPUP_KEY_CONTENT; + params->value = strdup(str); + apps->init((void *)params); + free(params); +} + +static int get_partition(const char *devpath, char *subpath) +{ + char path[NAME_MAX]; + int i; + + for (i = 1; i < 5; ++i) { + snprintf(path, sizeof(path), "%sp%d", devpath, i); + if (!access(path, R_OK)) { + strncpy(subpath, path, strlen(path)); + return 0; + } + } + return -ENODEV; +} + +static int create_partition(const char *devpath) +{ + int r; + char data[NAME_MAX]; + + snprintf(data, sizeof(data), "\"n\\n\\n\\n\\n\\nw\" | fdisk %s", devpath); + + r = launch_evenif_exist("/usr/bin/printf", data); + if (WIFSIGNALED(r) && (WTERMSIG(r) == SIGINT || WTERMSIG(r) == SIGQUIT || WEXITSTATUS(r))) + return -1; + + return 0; +} + +static int mmc_check_and_unmount(const char *path) +{ + int ret = 0, retry = 0; + while (mount_check(path)) { + ret = umount(path); + if (ret < 0) { + retry++; + if (retry > UNMOUNT_RETRY) + return -errno; + } + } + return ret; +} + +int get_block_number(void) +{ + DIR *dp; + struct dirent *dir; + struct stat stat; + char buf[255]; + int fd; + int r; + int mmcblk_num; + char *pre_mmc_device_id = NULL; + int mmc_dev_changed = 0; + + if ((dp = opendir("/sys/block")) == NULL) { + _E("Can not open directory.."); + return -1; + } + + r = chdir("/sys/block"); + if (r < 0) { + _E("Fail to change the directory.."); + closedir(dp); + return r; + } + + while ((dir = readdir(dp)) != NULL) { + memset(&stat, 0, sizeof(struct stat)); + if(lstat(dir->d_name, &stat) < 0) {continue;} + if (S_ISDIR(stat.st_mode) || S_ISLNK(stat.st_mode)) { + if (strncmp(".", dir->d_name, 1) == 0 + || strncmp("..", dir->d_name, 2) == 0) + continue; + if (strncmp("mmcblk", dir->d_name, 6) == 0) { + snprintf(buf, 255, "/sys/block/%s/device/type", + dir->d_name); + + fd = open(buf, O_RDONLY); + if (fd == -1) { + continue; + } + r = read(fd, buf, 10); + if ((r >= 0) && (r < 10)) + buf[r] = '\0'; + else + _E("%s read error: %s", buf, + strerror(errno)); + close(fd); + if (strncmp("SD", buf, 2) == 0) { + char *str_mmcblk_num = strndup((dir->d_name) + 6, 1); + if (str_mmcblk_num == NULL) { + _E("Memory Allocation Failed"); + closedir(dp); + return -1; + } + mmcblk_num = + atoi(str_mmcblk_num); + + free(str_mmcblk_num); + closedir(dp); + _D("%d", mmcblk_num); + + snprintf(buf, 255, "/sys/block/%s/device/cid", dir->d_name); + + fd = open(buf, O_RDONLY); + if (fd == -1) { + _E("%s open error", buf, strerror(errno)); + return mmcblk_num; + } + r = read(fd, buf, 255); + if ((r >=0) && (r < 255)) { + buf[r] = '\0'; + } else { + _E("%s read error: %s", buf,strerror(errno)); + } + close(fd); + pre_mmc_device_id = vconf_get_str(VCONFKEY_INTERNAL_PRIVATE_MMC_ID); + if (pre_mmc_device_id) { + if (strcmp(pre_mmc_device_id, "") == 0) { + vconf_set_str(VCONFKEY_INTERNAL_PRIVATE_MMC_ID, buf); + } else if (strncmp(pre_mmc_device_id,buf,33) == 0) { + if ( vconf_get_int(VCONFKEY_SYSMAN_MMC_DEVICE_CHANGED,&mmc_dev_changed) == 0 + && mmc_dev_changed != VCONFKEY_SYSMAN_MMC_NOT_CHANGED) { + vconf_set_int(VCONFKEY_SYSMAN_MMC_DEVICE_CHANGED, VCONFKEY_SYSMAN_MMC_NOT_CHANGED); + } + } else if (strncmp(pre_mmc_device_id,buf,32) != 0) { + vconf_set_str(VCONFKEY_INTERNAL_PRIVATE_MMC_ID, buf); + vconf_set_int(VCONFKEY_SYSMAN_MMC_DEVICE_CHANGED, VCONFKEY_SYSMAN_MMC_CHANGED); + } + free(pre_mmc_device_id); + } else { + _E("failed to get pre_mmc_device_id"); + } + return mmcblk_num; + } + } + + } + } + closedir(dp); + _E("failed to find mmc block number"); + return -1; +} + +static int find_mmc_node(char devpath[]) +{ + int num; + + num = get_block_number(); + if (num < 0) + return -ENODEV; + + snprintf(devpath, NAME_MAX, "%s%d", MMC_DEV, num); + return 0; +} + +static int get_mmc_size(const char *devpath) +{ + int fd, r; + unsigned long long ullbytes; + unsigned int nbytes; + + fd = open(devpath, O_RDONLY); + if (fd < 0) { + _E("open error"); + return -EINVAL; + } + + r = ioctl(fd, BLKGETSIZE64, &ullbytes); + close(fd); + + if (r < 0) { + _E("ioctl BLKGETSIZE64 error"); + return -EINVAL; + } + + nbytes = ullbytes/512; + _D("block size(64) : %d", nbytes); + return nbytes; +} + +static int rw_mount(const char *szPath) +{ + struct statvfs mount_stat; + if (!statvfs(szPath, &mount_stat)) { + if ((mount_stat.f_flag & ST_RDONLY) == ST_RDONLY) + return -1; + } + return 0; +} + +static int mmc_mount(const char *devpath, const char *mount_point) +{ + struct mmc_fs_ops *fs; + dd_list *elem; + char path[NAME_MAX] = {0,}; + int r; + + /* mmc_disabled set by start/stop func. */ + if (mmc_disabled) + return -EWOULDBLOCK; + + if (!devpath) + return -ENODEV; + + /* check partition */ + r = get_partition(devpath, path); + if (!r) + devpath = path; + + DD_LIST_FOREACH(fs_head, elem, fs) { + if (fs->match(devpath)) + break; + } + + if (!fs) + return -EINVAL; + + _D("devpath : %s", devpath); + r = fs->check(devpath); + if (r < 0) + _E("failt to check devpath : %s", devpath); + + r = fs->mount(smack, devpath, mount_point); + if (r < 0) + return r; + + r = rw_mount(mount_point); + if (r < 0) + return -EROFS; + + return 0; +} + +static void *mount_start(void *arg) +{ + struct mmc_data *data = (struct mmc_data*)arg; + char *devpath; + int r; + + devpath = data->devpath; + + assert(devpath); + + /* clear previous filesystem */ + mmc_check_and_unmount(MMC_MOUNT_POINT); + + /* check mount point */ + if (access(MMC_MOUNT_POINT, R_OK) != 0) { + if (mkdir(MMC_MOUNT_POINT, 0755) < 0) { + r = -errno; + goto error; + } + } + + /* mount operation */ + r = mmc_mount(devpath, MMC_MOUNT_POINT); + if (r == -EROFS) + launch_syspopup("mountrdonly"); + else if (r < 0) + goto error; + + mmc_set_config(MAX_RATIO); + + free(devpath); + free(data); + vconf_set_int(VCONFKEY_SYSMAN_MMC_STATUS, VCONFKEY_SYSMAN_MMC_MOUNTED); + vconf_set_int(VCONFKEY_SYSMAN_MMC_MOUNT, VCONFKEY_SYSMAN_MMC_MOUNT_COMPLETED); + return 0; + +error: + launch_syspopup("mounterr"); + vconf_set_int(VCONFKEY_SYSMAN_MMC_MOUNT, VCONFKEY_SYSMAN_MMC_MOUNT_FAILED); + vconf_set_int(VCONFKEY_SYSMAN_MMC_STATUS, VCONFKEY_SYSMAN_MMC_INSERTED_NOT_MOUNTED); + + free(devpath); + free(data); + _E("failed to mount device : %s", strerror(-r)); + return (void *)r; +} + +static int mmc_unmount(int option, const char *mount_point) +{ + int r, retry = 0; + int kill_op; + + /* try to unmount app2ext */ + r = app2ext_unmount(); + if (r < 0) + _I("Faild to unmount app2ext : %s", strerror(-r)); + r = mmc_check_and_unmount(mount_point); + if (!r) + return r; + if (option == UNMOUNT_NORMAL) { + _I("Failed to unmount with normal option : %s", strerror(-r)); + return r; + } + + _I("Execute force unmount!"); + /* Force Unmount Scenario */ + while (1) { + switch (retry++) { + case 0: + /* At first, notify to other app who already access sdcard */ + _I("Notify to other app who already access sdcard"); + vconf_set_int(VCONFKEY_SYSMAN_MMC_STATUS, VCONFKEY_SYSMAN_MMC_INSERTED_NOT_MOUNTED); + break; + case 1: + /* Second, kill app with SIGTERM */ + _I("Kill app with SIGTERM"); + terminate_process(MMC_MOUNT_POINT, false); + break; + case 2: + /* Last time, kill app with SIGKILL */ + _I("Kill app with SIGKILL"); + terminate_process(MMC_MOUNT_POINT, true); + break; + default: + if (umount2(mount_point, MNT_DETACH) != 0) { + _I("Failed to unmount with lazy option : %s", strerror(errno)); + return -errno; + } + return 0; + } + + /* it takes some seconds til other app completely clean up */ + usleep(500*1000); + + /* try to unmount app2ext */ + r = app2ext_unmount(); + if (r < 0) + _I("Faild to unmount app2ext : %s", strerror(-r)); + + r = mmc_check_and_unmount(mount_point); + if (!r) + break; + } + + return r; +} + +static void *unmount_start(void *arg) +{ + struct mmc_data *data = (struct mmc_data*)arg; + int option, r; + + option = data->option; + + assert(option == UNMOUNT_NORMAL || option == UNMOUNT_FORCE); + + r = mmc_unmount(option, MMC_MOUNT_POINT); + if (r < 0) + goto error; + + free(data); + vconf_set_int(VCONFKEY_SYSMAN_MMC_STATUS, VCONFKEY_SYSMAN_MMC_INSERTED_NOT_MOUNTED); + return 0; + +error: + free(data); + _E("Failed to unmount device : %s", strerror(-r)); + vconf_set_int(VCONFKEY_SYSMAN_MMC_STATUS, VCONFKEY_SYSMAN_MMC_MOUNTED); + return (void *)r; +} + +static int format(const char *devpath) +{ + const struct mmc_fs_ops *fs = NULL; + dd_list *elem; + char path[NAME_MAX] = {0,}; + int r, size, retry; + + if (!devpath) + return -ENODEV; + + /* check partition */ + r = get_partition(devpath, path); + if (!r) { + /* if there is partition, find partition file system */ + DD_LIST_FOREACH(fs_head, elem, fs) { + if (fs->match(path)) + break; + } + } else { + /* if there isn't partition, create partition */ + create_partition(devpath); + r = get_partition(devpath, path); + if (r < 0) + memcpy(path, devpath, strlen(devpath)); + } + + _I("format partition : %s", path); + + if (!fs) { + /* find root file system */ + DD_LIST_FOREACH(fs_head, elem, fs) { + if (fs->match(devpath)) + break; + } + } + + if (!fs) { + /* cannot find root and partition file system, + find suitable file system */ + size = get_mmc_size(path); + if (size <= MMC_32GB_SIZE) + fs = find_fs(FS_TYPE_VFAT); + else + fs = find_fs(FS_TYPE_EXFAT); + } + + if (!fs) + return -EINVAL; + + for (retry = FORMAT_RETRY; retry > 0; --retry) { + fs->check(devpath); + _D("format path : %s", path); + r = fs->format(path); + if (!r) + break; + } + return r; +} + +static void *format_start(void *arg) +{ + struct mmc_data *data = (struct mmc_data*)arg; + char *devpath; + int option, r, key = VCONFKEY_SYSMAN_MMC_MOUNTED; + bool format_ret = true; + + option = data->option; + devpath = data->devpath; + + assert(devpath); + assert(option == UNMOUNT_NORMAL || option == UNMOUNT_FORCE); + + _I("Format Start (option:%d)", option); + r = mmc_unmount(option, MMC_MOUNT_POINT); + if (r < 0) + goto release_memory; + + vconf_set_int(VCONFKEY_SYSMAN_MMC_FORMAT_PROGRESS, VCONFKEY_SYSMAN_MMC_FORMAT_PROGRESS_NOW); + r = format(devpath); + vconf_set_int(VCONFKEY_SYSMAN_MMC_FORMAT_PROGRESS, VCONFKEY_SYSMAN_MMC_FORMAT_PROGRESS_NONE); + if (r != 0) + format_ret = false; + + mount_start(arg); + if (!format_ret) + goto error; + _I("Format Successful"); + vconf_set_int(VCONFKEY_SYSMAN_MMC_FORMAT, VCONFKEY_SYSMAN_MMC_FORMAT_COMPLETED); + return 0; + +release_memory: + free(devpath); + free(data); +error: + _E("Format Failed : %s", strerror(-r)); + vconf_set_int(VCONFKEY_SYSMAN_MMC_FORMAT, VCONFKEY_SYSMAN_MMC_FORMAT_FAILED); + return (void*)r; +} + +static int mmc_make_thread(int type, int option, const char *devpath) +{ + pthread_t th; + struct mmc_data *pdata; + int r; + + if (type < 0 || type >= MMC_END) + return -EINVAL; + + pdata = malloc(sizeof(struct mmc_data)); + if (!pdata) { + _E("malloc failed"); + return -errno; + } + + if (option >= 0) + pdata->option = option; + if (devpath) + pdata->devpath = strdup(devpath); + r = pthread_create(&th, NULL, mmc_func[type].func, pdata); + if (r != 0) { + _E("pthread create failed"); + free(pdata->devpath); + free(pdata); + return -EPERM; + } + + pthread_detach(th); + return 0; +} + +static int mmc_inserted(const char *devpath) +{ + int r; + _I("MMC inserted : %s", devpath); + mmc_curpath = strdup(devpath); + r = mmc_make_thread(MMC_MOUNT, -1, devpath); + if (r < 0) + return r; + return 0; +} + +static int mmc_removed(void) +{ + _I("MMC removed"); + /* first, try to unmount app2ext */ + app2ext_unmount(); + /* unmount */ + mmc_check_and_unmount((const char *)MMC_MOUNT_POINT); + vconf_set_int(VCONFKEY_SYSMAN_MMC_STATUS, VCONFKEY_SYSMAN_MMC_REMOVED); + free(mmc_curpath); + mmc_curpath = NULL; + return 0; +} + +static int mmc_changed_cb(void *data) +{ + char *devpath = (char*)data; + + /* if MMC is inserted */ + if (devpath) + return mmc_inserted(devpath); + else + return mmc_removed(); +} + +static int mmc_booting_done(void* data) +{ + char devpath[NAME_MAX] = {0,}; + int r; + + /* check mmc exists */ + r = find_mmc_node(devpath); + if (r < 0) + return 0; + + /* if MMC exists */ + return mmc_inserted(devpath); +} + +static DBusMessage *edbus_request_secure_mount(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + char *path; + int ret; + + ret = dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &path, + DBUS_TYPE_INVALID); + if (!ret) { + ret = -EBADMSG; + goto error; + } + + if (!mmc_curpath) { + ret = -ENODEV; + goto error; + } + + /* check mount point */ + if (access(path, R_OK) != 0) { + if (mkdir(path, 0755) < 0) { + ret = -errno; + goto error; + } + } + + _D("mount path : %s", path); + ret = mmc_mount(mmc_curpath, path); + +error: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *edbus_request_secure_unmount(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + char *path; + int ret; + + ret = dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &path, + DBUS_TYPE_INVALID); + if (!ret) { + ret = -EBADMSG; + goto error; + } + + _D("unmount path : %s", path); + ret = mmc_unmount(UNMOUNT_NORMAL, path); + +error: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *edbus_request_mount(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + struct mmc_data *pdata; + int ret; + + if (!mmc_curpath) { + ret = -ENODEV; + goto error; + } + + pdata = malloc(sizeof(struct mmc_data)); + if (!pdata) { + _E("malloc failed"); + ret = -errno; + goto error; + } + + pdata->devpath = strdup(mmc_curpath); + if (!pdata->devpath) { + free(pdata); + ret = -errno; + goto error; + } + + ret = (int)mount_start(pdata); + +error: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *edbus_request_unmount(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int opt, ret; + char params[NAME_MAX]; + struct mmc_data *pdata; + + ret = dbus_message_get_args(msg, NULL, + DBUS_TYPE_INT32, &opt, DBUS_TYPE_INVALID); + if (!ret) { + _I("there is no message"); + ret = -EBADMSG; + goto error; + } + + pdata = malloc(sizeof(struct mmc_data)); + if (!pdata) { + _E("malloc failed"); + ret = -errno; + goto error; + } + + pdata->option = opt; + ret = (int)unmount_start(pdata); + +error: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *edbus_request_format(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int opt, ret; + struct mmc_data *pdata; + + ret = dbus_message_get_args(msg, NULL, + DBUS_TYPE_INT32, &opt, DBUS_TYPE_INVALID); + if (!ret) { + _I("there is no message"); + ret = -EBADMSG; + goto error; + } + + if (!mmc_curpath) { + ret = -ENODEV; + goto error; + } + + pdata = malloc(sizeof(struct mmc_data)); + if (!pdata) { + _E("malloc failed"); + ret = -errno; + goto error; + } + + pdata->option = opt; + pdata->devpath = strdup(mmc_curpath); + if (!pdata->devpath) { + free(pdata); + ret = -errno; + goto error; + } + + ret = (int)format_start(pdata); + +error: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +int get_mmc_devpath(char devpath[]) +{ + if (mmc_disabled) + return -EWOULDBLOCK; + if (!mmc_curpath) + return -ENODEV; + snprintf(devpath, NAME_MAX, "%s", mmc_curpath); + return 0; +} + +static const struct edbus_method edbus_methods[] = { + { "RequestSecureMount", "s", "i", edbus_request_secure_mount }, + { "RequestSecureUnmount", "s", "i", edbus_request_secure_unmount }, + { "RequestMount", NULL, "i", edbus_request_mount }, + { "RequestUnmount", "i", "i", edbus_request_unmount }, + { "RequestFormat", "i", "i", edbus_request_format }, +}; + +static int mmc_poweroff(void *data) +{ + mmc_uevent_stop(); + return 0; +} + +static void mmc_init(void *data) +{ + int ret; + + mmc_load_config(); + ret = register_edbus_method(DEVICED_PATH_MMC, edbus_methods, ARRAY_SIZE(edbus_methods)); + if (ret < 0) + _E("fail to init edbus method(%d)", ret); + + /* register mmc uevent control routine */ + ret = mmc_uevent_start(); + if (ret < 0) + _E("fail to mmc uevent start"); + + /* register notifier if mmc exist or not */ + register_notifier(DEVICE_NOTIFIER_POWEROFF, mmc_poweroff); + register_notifier(DEVICE_NOTIFIER_BOOTING_DONE, mmc_booting_done); + register_notifier(DEVICE_NOTIFIER_MMC, mmc_changed_cb); +} + +static void mmc_exit(void *data) +{ + /* unregister notifier */ + unregister_notifier(DEVICE_NOTIFIER_POWEROFF, mmc_poweroff); + unregister_notifier(DEVICE_NOTIFIER_MMC, mmc_changed_cb); + unregister_notifier(DEVICE_NOTIFIER_BOOTING_DONE, mmc_booting_done); + + /* unregister mmc uevent control routine */ + mmc_uevent_stop(); +} + +static int mmc_start(void) +{ + mmc_disabled = false; + _D("start"); + return 0; +} + +static int mmc_stop(void) +{ + mmc_disabled = true; + vconf_set_int(VCONFKEY_SYSMAN_MMC_STATUS, VCONFKEY_SYSMAN_MMC_REMOVED); + _D("stop"); + return 0; +} + +const struct device_ops mmc_device_ops = { + .priority = DEVICE_PRIORITY_NORMAL, + .name = "mmc", + .init = mmc_init, + .exit = mmc_exit, + .start = mmc_start, + .stop = mmc_stop, +}; + +DEVICE_OPS_REGISTER(&mmc_device_ops) diff --git a/src/mmc/mmc-handler.h b/src/mmc/mmc-handler.h new file mode 100644 index 0000000..d1d9c91 --- /dev/null +++ b/src/mmc/mmc-handler.h @@ -0,0 +1,66 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 __MMC_HANDLER_H__ +#define __MMC_HANDLER_H__ + +#include + +#define SMACKFS_MOUNT_OPT "smackfsroot=*,smackfsdef=*" +#define MMC_MOUNT_POINT "/opt/storage/sdcard" + +#define BUF_LEN 20 +#define RETRY_COUNT 10 + +#define MMC_POPUP_NAME "mmc-syspopup" +#define MMC_POPUP_APP_KEY "_APP_NAME_" +#define MMC_POPUP_SMACK_VALUE "checksmack" + +enum mmc_fs_type { + FS_TYPE_VFAT = 0, + FS_TYPE_EXFAT, + FS_TYPE_EXT4, +}; + +struct mmc_fs_ops { + enum mmc_fs_type type; + const char *name; + bool (*match) (const char *); + int (*check) (const char *); + int (*mount) (bool, const char *, const char *); + int (*format) (const char *); +}; + +struct fs_check { + int type; + char *name; + unsigned int offset; + unsigned int magic_sz; + char magic[4]; +}; + +void add_fs(const struct mmc_fs_ops *fs); +void remove_fs(const struct mmc_fs_ops *fs); +int get_mmc_devpath(char devpath[]); +bool mmc_check_mounted(const char *mount_point); + +int mmc_uevent_start(void); +int mmc_uevent_stop(void); +int get_block_number(void); +#endif /* __MMC_HANDLER_H__ */ diff --git a/src/mmc/mmc.conf b/src/mmc/mmc.conf new file mode 100644 index 0000000..55539b9 --- /dev/null +++ b/src/mmc/mmc.conf @@ -0,0 +1,3 @@ +[MMC] +#mmc bdi max ratio +MaxRatio=10 diff --git a/src/mmc/uevent.c b/src/mmc/uevent.c new file mode 100644 index 0000000..873b213 --- /dev/null +++ b/src/mmc/uevent.c @@ -0,0 +1,149 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 "core/udev.h" +#include "core/device-notifier.h" +#include "core/log.h" + +/* block device */ +#define BLOCK_SUBSYSTEM "block" +#define MMC_PATH "*/mmcblk[0-9]" +#define BLOCK_DEVPATH "disk" + +static struct udev_monitor *mon; +static struct udev *udev; +static Ecore_Fd_Handler *ufdh; +static int ufd; + +static Eina_Bool mmc_uevent_cb(void *data, Ecore_Fd_Handler *fd_handler) +{ + struct udev_device *dev; + const char *subsystem, *devpath, *action, *devnode; + + dev = udev_monitor_receive_device(mon); + if (!dev) + return EINA_TRUE; + + subsystem = udev_device_get_subsystem(dev); + if (strcmp(subsystem, BLOCK_SUBSYSTEM)) + goto out; + + devpath = udev_device_get_devpath(dev); + if (fnmatch(MMC_PATH, devpath, 0)) + goto out; + + _D("mmc uevent occurs!"); + + action = udev_device_get_action(dev); + devnode = udev_device_get_devnode(dev); + if (!action || !devnode) + goto out; + + if (!strcmp(action, UDEV_ADD)) + device_notify(DEVICE_NOTIFIER_MMC, (void *)devnode); + else if (!strcmp(action, UDEV_REMOVE)) + device_notify(DEVICE_NOTIFIER_MMC, NULL); + +out: + udev_device_unref(dev); + return EINA_TRUE; +} + +int mmc_uevent_start(void) +{ + int r; + + if (udev) { + _D("uevent control is already started"); + return -EPERM; + } + + udev = udev_new(); + if (!udev) + return -EPERM; + + mon = udev_monitor_new_from_netlink(udev, UDEV); + if (!mon) + goto stop; + + r = udev_monitor_set_receive_buffer_size(mon, UDEV_MONITOR_SIZE); + if (r < 0) + goto stop; + + r = udev_monitor_filter_add_match_subsystem_devtype(mon, BLOCK_SUBSYSTEM, NULL); + if (r < 0) + goto stop; + + r = udev_monitor_filter_update(mon); + if (r < 0) + _E("error udev_monitor_filter_update"); + + ufd = udev_monitor_get_fd(mon); + if (ufd < 0) + goto stop; + + ufdh = ecore_main_fd_handler_add(ufd, ECORE_FD_READ, mmc_uevent_cb, NULL, NULL, NULL); + if (!ufdh) + goto stop; + + r = udev_monitor_enable_receiving(mon); + if (r < 0) + goto stop; + + return 0; + +stop: + mmc_uevent_stop(); + return -EPERM; +} + +int mmc_uevent_stop(void) +{ + struct udev_device *dev = NULL; + + if (ufdh) { + ecore_main_fd_handler_del(ufdh); + ufdh = NULL; + } + + if (ufd >= 0) { + close(ufd); + ufd = -1; + } + + if (mon) { + dev = udev_monitor_receive_device(mon); + if (dev) { + udev_device_unref(dev); + dev = NULL; + } + udev_monitor_unref(mon); + mon = NULL; + } + + if (udev) { + udev_unref(udev); + udev = NULL; + } + + return 0; +} diff --git a/src/mmc/vfat.c b/src/mmc/vfat.c new file mode 100644 index 0000000..1cab15d --- /dev/null +++ b/src/mmc/vfat.c @@ -0,0 +1,151 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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/common.h" +#include "core/log.h" +#include "mmc-handler.h" + +#define FS_VFAT_NAME "mkdosfs" + +#define FS_VFAT_MOUNT_OPT "uid=5000,gid=5000,dmask=0002,fmask=0002,iocharset=iso8859-1,utf8,shortname=mixed" + +static const char *vfat_arg[] = { + "/sbin/mkfs.vfat", + NULL, NULL, +}; + +static const char *vfat_check_arg[] = { + "/usr/bin/fsck_msdosfs", + "-pf", NULL, NULL, +}; + +static struct fs_check vfat_info = { + FS_TYPE_VFAT, + "vfat", + 0x1fe, + 2, + {0x55, 0xAA}, +}; + +static int vfat_check(const char *devpath) +{ + int argc, r, pass = 0; + + argc = ARRAY_SIZE(vfat_check_arg); + vfat_check_arg[argc - 2] = devpath; + + do { + r = run_child(argc, vfat_check_arg); + + switch (r) { + case 0: + _I("filesystem check completed OK"); + return 0; + case 2: + _I("file system check failed (not a FAT filesystem)"); + errno = ENODATA; + return -1; + case 4: + if (pass++ <= 2) { + _I("filesystem modified - rechecking (pass : %d)", pass); + continue; + } + _I("failing check after rechecks, but file system modified"); + return 0; + default: + _I("filesystem check failed (unknown exit code %d)", r); + errno = EIO; + return -1; + } + } while (1); + + return 0; +} + +static bool vfat_match(const char *devpath) +{ + int r; + + r = vfat_check(devpath); + if (r < 0) { + _E("failed to match with vfat(%s)", devpath); + return false; + } + + _D("MMC type : %s", vfat_info.name); + return true; +} + +static int vfat_mount(bool smack, const char *devpath, const char *mount_point) +{ + char options[NAME_MAX]; + int r, retry = RETRY_COUNT; + + if (smack) + snprintf(options, sizeof(options), "%s,%s", FS_VFAT_MOUNT_OPT, SMACKFS_MOUNT_OPT); + else + snprintf(options, sizeof(options), "%s", FS_VFAT_MOUNT_OPT); + + do { + r = mount(devpath, mount_point, "vfat", 0, options); + if (!r) { + _D("Mounted mmc card [vfat]"); + return 0; + } + _D("mount fail : r = %d, err = %d", r, errno); + usleep(100000); + } while (r < 0 && errno == ENOENT && retry-- > 0); + + return -errno; +} + +static int vfat_format(const char *devpath) +{ + int argc; + argc = ARRAY_SIZE(vfat_arg); + vfat_arg[argc - 2] = devpath; + return run_child(argc, vfat_arg); +} + +static const struct mmc_fs_ops vfat_ops = { + .type = FS_TYPE_VFAT, + .name = "vfat", + .match = vfat_match, + .check = vfat_check, + .mount = vfat_mount, + .format = vfat_format, +}; + +static void __CONSTRUCTOR__ module_init(void) +{ + add_fs(&vfat_ops); +} +/* +static void __DESTRUCTOR__ module_exit(void) +{ + _D("module exit"); + remove_fs(&vfat_ops); +} +*/ diff --git a/src/pmqos/pmqos-plugin.c b/src/pmqos/pmqos-plugin.c new file mode 100644 index 0000000..9a720ab --- /dev/null +++ b/src/pmqos/pmqos-plugin.c @@ -0,0 +1,153 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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/edbus-handler.h" +#include "core/config-parser.h" +#include "pmqos.h" + +static bool is_supported(const char *value) +{ + assert(value); + + if (MATCH(value, "yes")) + return true; + return false; +} + +static int pmqos_parse_scenario(struct parse_result *result, void *user_data, unsigned int index) +{ + struct pmqos_scenario *scenarios = (struct pmqos_scenario*)user_data; + + assert(result); + assert(result->section && result->name && result->value); + + /* Parse 'PmqosScenario' section */ + if (MATCH(result->section, "PmqosScenario")) { + if (MATCH(result->name, "scenario_support")) + scenarios->support = is_supported(result->value); + else if (MATCH(result->name, "scenario_num")) { + scenarios->num = atoi(result->value); + if (scenarios->num > 0) { + scenarios->list = malloc(sizeof(struct scenario)*scenarios->num); + if (!scenarios->list) { + _E("failed to allocat memory for scenario"); + return -errno; + } + } + } + } + + /* Do not support pmqos scenario */ + if (!scenarios->support) + return 0; + + /* Do not have pmqos scenario */ + if (!scenarios->num) + return 0; + + /* No item to parse */ + if (index > scenarios->num) + return 0; + + /* Parse 'Scenario' section */ + if (MATCH(result->name, "name")) + strcpy(scenarios->list[index].name, result->value); + else if (MATCH(result->name, "support")) + scenarios->list[index].support = is_supported(result->value); + + return 0; +} + +static int pmqos_load_config(struct parse_result *result, void *user_data) +{ + struct pmqos_scenario *scenarios = (struct pmqos_scenario*)user_data; + char name[NAME_MAX]; + int ret; + static int index; + + if (!result) + return 0; + + if (!result->section || !result->name || !result->value) + return 0; + + /* Parsing 'PMQOS' section */ + if (MATCH(result->section, "PMQOS")) + goto out; + + /* Parsing 'Pmqos Scenario' section */ + if (MATCH(result->section, "PmqosScenario")) { + ret = pmqos_parse_scenario(result, user_data, -1); + if (ret < 0) { + _E("failed to parse [PmqosScenario] section : %d", ret); + return ret; + } + goto out; + } + + /* Parsing 'Scenario' section */ + for (index = 0; index < scenarios->num; ++index) { + snprintf(name, sizeof(name), "Scenario%d", index); + + if (MATCH(result->section, name)) { + ret = pmqos_parse_scenario(result, user_data, index); + if (ret < 0) { + _E("failed to parse [Scenario%d] section : %d", index, ret); + return ret; + } + goto out; + } + } + +out: + return 0; +} + +int release_pmqos_table(struct pmqos_scenario *scenarios) +{ + if (!scenarios) + return -EINVAL; + + if (scenarios->num > 0 && !scenarios->list) + free(scenarios->list); + + return 0; +} + +int get_pmqos_table(const char *path, struct pmqos_scenario *scenarios) +{ + int ret; + + /* get configuration file */ + ret = config_parse(path, pmqos_load_config, scenarios); + if (ret < 0) { + _E("failed to load conficuration file(%s) : %d", path, ret); + release_pmqos_table(scenarios); + return ret; + } + + return 0; +} diff --git a/src/pmqos/pmqos.c b/src/pmqos/pmqos.c new file mode 100644 index 0000000..51af26d --- /dev/null +++ b/src/pmqos/pmqos.c @@ -0,0 +1,385 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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/edbus-handler.h" +#include "core/devices.h" +#include "core/common.h" +#include "core/list.h" +#include "core/device-notifier.h" +#include "pmqos.h" + +#define DEFAULT_PMQOS_TIMER 3000 + +#define PMQOS_CONF_PATH "/etc/deviced/pmqos.conf" + +struct pmqos_cpu { + char name[NAME_MAX]; + Ecore_Timer *timer; +}; + +static dd_list *pmqos_head; + +int set_cpu_pmqos(const char *name, int val) +{ + char scenario[100]; + + snprintf(scenario, sizeof(scenario), "%s%s", name, (val ? "Lock" : "Unlock")); + _D("Set pm scenario : %s", scenario); + device_notify(DEVICE_NOTIFIER_PMQOS, (void *)scenario); + return device_set_property(DEVICE_TYPE_CPU, PROP_CPU_PM_SCENARIO, (int)scenario); +} + +static int pmqos_cpu_cancel(const char *name) +{ + dd_list *elem; + struct pmqos_cpu *cpu; + + /* Find previous request */ + DD_LIST_FOREACH(pmqos_head, elem, cpu) { + if (!strcmp(cpu->name, name)) + break; + } + + /* In case of already end up request */ + if(!cpu) { + _I("%s request is already canceled", name); + return 0; + } + + /* Set cpu unlock */ + set_cpu_pmqos(cpu->name, false); + + /* Delete previous request */ + DD_LIST_REMOVE(pmqos_head, cpu); + ecore_timer_del(cpu->timer); + free(cpu); + + return 0; +} + +static Eina_Bool pmqos_cpu_timer(void *data) +{ + char *name = (char*)data; + int ret; + + _I("%s request will be unlocked", name); + ret = pmqos_cpu_cancel(name); + if (ret < 0) + _E("Can not find %s request", name); + + free(name); + return ECORE_CALLBACK_CANCEL; +} + +static int pmqos_cpu_request(const char *name, int val) +{ + dd_list *elem; + struct pmqos_cpu *cpu; + Ecore_Timer *timer; + bool locked = false; + + /* Check valid parameter */ + if (val > DEFAULT_PMQOS_TIMER) { + _I("The timer value cannot be higher than default time value(%dms)", DEFAULT_PMQOS_TIMER); + val = DEFAULT_PMQOS_TIMER; + } + + /* Find previous request */ + DD_LIST_FOREACH(pmqos_head, elem, cpu) { + if (!strcmp(cpu->name, name)) { + ecore_timer_reset(cpu->timer); + locked = true; + break; + } + } + + /* In case of first request */ + if (!cpu) { + /* Add new timer */ + timer = ecore_timer_add(val/1000.f, pmqos_cpu_timer, (void*)strdup(name)); + if (!timer) + return -EPERM; + + cpu = malloc(sizeof(struct pmqos_cpu)); + if (!cpu) { + ecore_timer_del(timer); + return -ENOMEM; + } + snprintf(cpu->name, sizeof(cpu->name), "%s", name); + cpu->timer = timer; + DD_LIST_APPEND(pmqos_head, cpu); + } + + /* Set cpu lock */ + if(!locked) { + set_cpu_pmqos(cpu->name, true); + } + + return 0; +} + +static int pmqos_powersaving(void *data) +{ + return set_cpu_pmqos("PowerSaving", (int)data); +} + +static int pmqos_lowbat(void *data) +{ + return set_cpu_pmqos("LowBattery", (int)data); +} + +static int pmqos_emergency(void *data) +{ + return set_cpu_pmqos("Emergency", (int)data); +} + +static int pmqos_poweroff(void *data) +{ + return set_cpu_pmqos("PowerOff", (int)data); +} + +static DBusMessage *dbus_pmqos_handler(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + const char *member; + int val, ret; + + if (!dbus_message_get_args(msg, NULL, + DBUS_TYPE_INT32, &val, DBUS_TYPE_INVALID)) { + _E("there is no message"); + ret = -EINVAL; + goto error; + } + + if (val < 0) { + ret = -EINVAL; + goto error; + } + + member = dbus_message_get_member(msg); + + if (val) + ret = pmqos_cpu_request(member, val); + else + ret = pmqos_cpu_cancel(member); + +error: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *dbus_wifi_pmqos_handler(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + const char *member; + char name[NAME_MAX]; + int bps, val, ret; + + if (!dbus_message_get_args(msg, NULL, + DBUS_TYPE_INT32, &bps, + DBUS_TYPE_INT32, &val, DBUS_TYPE_INVALID)) { + _E("there is no message"); + ret = -EINVAL; + goto error; + } + + if (bps < 0 || val < 0) { + ret = -EINVAL; + goto error; + } + + member = dbus_message_get_member(msg); + + /* combine bps and member */ + snprintf(name, sizeof(name), "%s%d", member, bps); + + if (val) + ret = pmqos_cpu_request(name, val); + else + ret = pmqos_cpu_cancel(name); + +error: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *dbus_getdefaultlocktime(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int ret; + + ret = DEFAULT_PMQOS_TIMER; + + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static int get_methods_from_conf(const char *path, struct edbus_method **edbus_methods) +{ + struct edbus_method *methods; + struct pmqos_scenario scenarios = {0,}; + int i, ret; + + /* get pmqos table from conf */ + ret = get_pmqos_table(path, &scenarios); + if (ret < 0) { + /* release scenarios memory */ + release_pmqos_table(&scenarios); + return ret; + } + + /* if do not support scenario */ + if (!scenarios.support) + return 0; + + /* if do not have scenarios */ + if (scenarios.num <= 0) + return 0; + + /* allocate edbus methods structure */ + methods = malloc(sizeof(struct edbus_method)*scenarios.num); + if (!methods) { + _E("failed to allocate methods memory : %s", strerror(errno)); + /* release scenarios memory */ + release_pmqos_table(&scenarios); + return -errno; + } + + /* set edbus_methods structure */ + for (i = 0; i < scenarios.num; ++i) { + + /* if this scenario does not support */ + if (!scenarios.list[i].support) { + _I("do not support [%s] scenario", scenarios.list[i].name); + continue; + } + + methods[i].member = scenarios.list[i].name; + methods[i].signature = "i"; + methods[i].reply_signature = "i"; + methods[i].func = dbus_pmqos_handler; + _D("support [%s] scenario", scenarios.list[i].name); + } + + *edbus_methods = methods; + return scenarios.num; +} + +/* Add pmqos name as alphabetically */ +static const struct edbus_method edbus_methods[] = { + { "AppLaunch", "i", "i", dbus_pmqos_handler }, + { "BeautyShot", "i", "i", dbus_pmqos_handler }, + { "Browser", "i", "i", dbus_pmqos_handler }, + { "BrowserDash", "i", "i", dbus_pmqos_handler }, + { "BrowserJavaScript", "i", "i", dbus_pmqos_handler }, + { "BrowserLoading", "i", "i", dbus_pmqos_handler }, + { "BrowserScroll", "i", "i", dbus_pmqos_handler }, + { "CallSound", "i", "i", dbus_pmqos_handler }, + { "CameraBurstShot", "i", "i", dbus_pmqos_handler }, + { "CameraCaptureAtRec", "i", "i", dbus_pmqos_handler }, + { "CameraPreview", "i", "i", dbus_pmqos_handler }, + { "CameraSoundAndShot", "i", "i", dbus_pmqos_handler }, + { "Emergency", "i", "i", dbus_pmqos_handler }, + { "GalleryRotation", "i", "i", dbus_pmqos_handler }, + { "GetDefaultLockTime", NULL, "i", dbus_getdefaultlocktime }, + { "GpsSerialCno", "i", "i", dbus_pmqos_handler }, + { "GpuBoost", "i", "i", dbus_pmqos_handler }, + { "GpuWakeup", "i", "i", dbus_pmqos_handler }, + { "ImageViewer", "i", "i", dbus_pmqos_handler }, + { "IMEInput", "i", "i", dbus_pmqos_handler }, + { "LockScreen", "i", "i", dbus_pmqos_handler }, + { "LowBattery", "i", "i", dbus_pmqos_handler }, + { "MtpSendFile", "i", "i", dbus_pmqos_handler }, + { "PowerSaving", "i", "i", dbus_pmqos_handler }, + { "ProcessCrashed", "i", "i", dbus_pmqos_handler }, + { "ReservedMode", "i", "i", dbus_pmqos_handler }, + { "ScreenMirroring", "i", "i", dbus_pmqos_handler }, + { "SmemoZoom", "i", "i", dbus_pmqos_handler }, + { "SVoice", "i", "i", dbus_pmqos_handler }, + { "WebappLaunch", "i", "i", dbus_pmqos_handler }, + { "WifiThroughput", "ii", "i", dbus_wifi_pmqos_handler }, + { "PowerOff", "i", "i", dbus_pmqos_handler }, + { "WebAppDrag", "i", "i", dbus_pmqos_handler }, + { "WebAppFlick", "i", "i", dbus_pmqos_handler }, + { "SensorWakeup", "i", "i", dbus_pmqos_handler }, +}; + +static void pmqos_init(void *data) +{ + struct edbus_method *methods = NULL; + int ret, size; + + /* register edbus methods */ + ret = register_edbus_method(DEVICED_PATH_PMQOS, edbus_methods, ARRAY_SIZE(edbus_methods)); + if (ret < 0) + _E("fail to init edbus method(%d)", ret); + + /* get methods from config file */ + size = get_methods_from_conf(PMQOS_CONF_PATH, &methods); + if (size < 0) + _E("failed to load configuration file(%s)", PMQOS_CONF_PATH); + + /* register edbus methods for pmqos */ + if (methods) { + ret = register_edbus_method(DEVICED_PATH_PMQOS, methods, size); + if (ret < 0) + _E("fail to init edbus method from conf(%d)", ret); + free(methods); + } + + /* register notifier for each event */ + register_notifier(DEVICE_NOTIFIER_PMQOS_POWERSAVING, pmqos_powersaving); + register_notifier(DEVICE_NOTIFIER_PMQOS_LOWBAT, pmqos_lowbat); + register_notifier(DEVICE_NOTIFIER_PMQOS_EMERGENCY, pmqos_emergency); + register_notifier(DEVICE_NOTIFIER_PMQOS_POWEROFF, pmqos_poweroff); +} + +static void pmqos_exit(void *data) +{ + /* unregister notifier for each event */ + unregister_notifier(DEVICE_NOTIFIER_PMQOS_POWERSAVING, pmqos_powersaving); + unregister_notifier(DEVICE_NOTIFIER_PMQOS_LOWBAT, pmqos_lowbat); + unregister_notifier(DEVICE_NOTIFIER_PMQOS_EMERGENCY, pmqos_emergency); + unregister_notifier(DEVICE_NOTIFIER_PMQOS_POWEROFF, pmqos_poweroff); +} + +static const struct device_ops pmqos_device_ops = { + .priority = DEVICE_PRIORITY_NORMAL, + .name = "pmqos", + .init = pmqos_init, + .exit = pmqos_exit, +}; + +DEVICE_OPS_REGISTER(&pmqos_device_ops) diff --git a/src/pmqos/pmqos.conf b/src/pmqos/pmqos.conf new file mode 100644 index 0000000..83025a9 --- /dev/null +++ b/src/pmqos/pmqos.conf @@ -0,0 +1,15 @@ +[PMQOS] + +############################ +### Add list of scenario ### +############################ +[PmqosScenario] +# set to "yes" scenario_support (Default value is no) +# set scenario_num to be tested +scenario_support=no +scenario_num=0 + +# describe the scenario section as follows +#[Scenario0] +#name=AppLaunch # (dbus method name) +#support=yes diff --git a/src/pmqos/pmqos.h b/src/pmqos/pmqos.h new file mode 100644 index 0000000..531847c --- /dev/null +++ b/src/pmqos/pmqos.h @@ -0,0 +1,38 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 __PMQOS_H__ +#define __PMQOS_H__ + +#include +#include + +struct pmqos_scenario { + struct scenario { + char name[NAME_MAX]; + bool support; + } *list; + int num; + bool support; +}; + +int get_pmqos_table(const char *path, struct pmqos_scenario *scenarios); +int release_pmqos_table(struct pmqos_scenario *scenarios); + +#endif /* __PMQOS_H__ */ diff --git a/src/power/power-handler.c b/src/power/power-handler.c new file mode 100644 index 0000000..80321e8 --- /dev/null +++ b/src/power/power-handler.c @@ -0,0 +1,662 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "dd-deviced.h" +#include "core/log.h" +#include "core/launch.h" +#include "core/queue.h" +#include "core/device-handler.h" +#include "core/device-notifier.h" +#include "core/predefine.h" +#include "core/data.h" +#include "core/common.h" +#include "core/devices.h" +#include "proc/proc-handler.h" +#include "display/poll.h" +#include "display/setting.h" +#include "core/edbus-handler.h" +#include "display/core.h" +#include "power-handler.h" +#include "hall/hall-handler.h" + +#define SIGNAL_NAME_POWEROFF_POPUP "poweroffpopup" +#define SIGNAL_BOOTING_DONE "BootingDone" + +#define PREDEF_PWROFF_POPUP "pwroff-popup" +#define PREDEF_INTERNAL_POWEROFF "internal_poweroff" + +#define POWEROFF_NOTI_NAME "power_off_start" +#define POWEROFF_DURATION 2 +#define MAX_RETRY 2 + +#define SYSTEMD_STOP_POWER_OFF 4 + +#define SIGNAL_POWEROFF_STATE "ChangeState" + +#define POWEROFF_POPUP_NAME "poweroff-syspopup" +#define UMOUNT_RW_PATH "/opt/usr" + + +struct popup_data { + char *name; + char *key; +}; + +static struct timeval tv_start_poweroff; + +static int power_off = 0; +static const struct device_ops *telephony; +static const struct device_ops *hall_ic = NULL; +static void telephony_init(void) +{ + if (telephony) + return; + telephony = find_device("telephony"); + _I("telephony (%d)", telephony); +} + +static void telephony_start(void) +{ + telephony_init(); + if (telephony) + telephony->start(); +} + +static void telephony_stop(void) +{ + if (telephony) + telephony->stop(); +} + +static int telephony_exit(void *data) +{ + if (!telephony) + return -EINVAL; + telephony->exit(data); + return 0; +} + +static void poweroff_popup_edbus_signal_handler(void *data, DBusMessage *msg) +{ + DBusError err; + char *str; + int val = 0; + + if (dbus_message_is_signal(msg, DEVICED_INTERFACE_NAME, SIGNAL_NAME_POWEROFF_POPUP) == 0) { + _E("there is no power off popup signal"); + return; + } + + dbus_error_init(&err); + + if (dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &str, DBUS_TYPE_INVALID) == 0) { + _E("there is no message"); + return; + } + + if (strncmp(str, PREDEF_PWROFF_POPUP, strlen(PREDEF_PWROFF_POPUP)) == 0) + val = VCONFKEY_SYSMAN_POWER_OFF_POPUP; + else if (strncmp(str, PREDEF_POWEROFF, strlen(PREDEF_POWEROFF)) == 0) + val = VCONFKEY_SYSMAN_POWER_OFF_DIRECT; + else if (strncmp(str, PREDEF_REBOOT, strlen(PREDEF_REBOOT)) == 0) + val = VCONFKEY_SYSMAN_POWER_OFF_RESTART; + else if (strncmp(str, PREDEF_FOTA_REBOOT, strlen(PREDEF_FOTA_REBOOT)) == 0) + val = SYSTEMD_STOP_POWER_RESTART_FOTA; + if (val == 0) { + _E("not supported message : %s", str); + return; + } + vconf_set_int(VCONFKEY_SYSMAN_POWER_OFF_STATUS, val); +} + +static void booting_done_edbus_signal_handler(void *data, DBusMessage *msg) +{ + if (!dbus_message_is_signal(msg, DEVICED_INTERFACE_CORE, SIGNAL_BOOTING_DONE)) { + _E("there is no bootingdone signal"); + return; + } + + device_notify(DEVICE_NOTIFIER_BOOTING_DONE, (void *)TRUE); + telephony_init(); +} + +static void poweroff_send_broadcast(int status) +{ + static int old = 0; + char *arr[1]; + char str_status[32]; + + if (old == status) + return; + + _D("broadcast poweroff %d", status); + + old = status; + snprintf(str_status, sizeof(str_status), "%d", status); + arr[0] = str_status; + + broadcast_edbus_signal(DEVICED_PATH_POWEROFF, DEVICED_INTERFACE_POWEROFF, + SIGNAL_POWEROFF_STATE, "i", arr); +} + +static void poweroff_stop_systemd_service(void) +{ + char buf[256]; + _D("systemd service stop"); + umount2("/sys/fs/cgroup", MNT_FORCE |MNT_DETACH); +} + +static void poweroff_start_animation(void) +{ + char params[128]; + snprintf(params, sizeof(params), "/usr/bin/boot-animation --stop --clear"); + launch_app_cmd_with_nice(params, -20); + launch_evenif_exist("/usr/bin/sound_server", "--poweroff"); + device_notify(DEVICE_NOTIFIER_POWEROFF_HAPTIC, NULL); +} + +static void poweroff_control_cb(keynode_t *in_key, struct main_data *ad) +{ + int val; + int ret; + int recovery; + + telephony_start(); + + if (vconf_get_int(VCONFKEY_SYSMAN_POWER_OFF_STATUS, &val) != 0) + return; + + recovery = val; + + if (val == SYSTEMD_STOP_POWER_OFF || + val == SYSTEMD_STOP_POWER_RESTART || + val == SYSTEMD_STOP_POWER_RESTART_RECOVERY || + val == SYSTEMD_STOP_POWER_RESTART_FOTA) { + poweroff_stop_systemd_service(); + if (val == SYSTEMD_STOP_POWER_OFF) + val = VCONFKEY_SYSMAN_POWER_OFF_DIRECT; + else + val = VCONFKEY_SYSMAN_POWER_OFF_RESTART; + vconf_ignore_key_changed(VCONFKEY_SYSMAN_POWER_OFF_STATUS, (void*)poweroff_control_cb); + vconf_set_int(VCONFKEY_SYSMAN_POWER_OFF_STATUS, val); + } + + if (val == VCONFKEY_SYSMAN_POWER_OFF_DIRECT || val == VCONFKEY_SYSMAN_POWER_OFF_RESTART) + poweroff_send_broadcast(val); + + switch (val) { + case VCONFKEY_SYSMAN_POWER_OFF_DIRECT: + device_notify(DEVICE_NOTIFIER_POWEROFF, (void *)val); + notify_action(PREDEF_POWEROFF, 0); + break; + case VCONFKEY_SYSMAN_POWER_OFF_POPUP: + notify_action(PREDEF_PWROFF_POPUP, 0); + break; + case VCONFKEY_SYSMAN_POWER_OFF_RESTART: + device_notify(DEVICE_NOTIFIER_POWEROFF, (void *)val); + if (recovery == SYSTEMD_STOP_POWER_RESTART_RECOVERY) + notify_action(PREDEF_RECOVERY, 0); + else if (recovery == SYSTEMD_STOP_POWER_RESTART_FOTA) + notify_action(PREDEF_FOTA_REBOOT, 0); + else + notify_action(PREDEF_REBOOT, 0); + break; + } + + if (update_pm_setting) + update_pm_setting(SETTING_POWEROFF, val); +} + +/* umount usr data partition */ +static void unmount_rw_partition() +{ + int retry = 0; + sync(); + if (!mount_check(UMOUNT_RW_PATH)) + return; + while (1) { + switch (retry++) { + case 0: + /* Second, kill app with SIGTERM */ + _I("Kill app with SIGTERM"); + terminate_process(UMOUNT_RW_PATH, false); + sleep(3); + break; + case 1: + /* Last time, kill app with SIGKILL */ + _I("Kill app with SIGKILL"); + terminate_process(UMOUNT_RW_PATH, true); + sleep(1); + break; + default: + if (umount2(UMOUNT_RW_PATH, 0) != 0) { + _I("Failed to unmount %s", UMOUNT_RW_PATH); + return; + } + _I("%s unmounted successfully", UMOUNT_RW_PATH); + return; + } + if (umount2(UMOUNT_RW_PATH, 0) == 0) { + _I("%s unmounted successfully", UMOUNT_RW_PATH); + return; + } + } +} + +static void powerdown(void) +{ + static int wait = 0; + struct timeval now; + int poweroff_duration = POWEROFF_DURATION; + int check_duration = 0; + char *buf; + + if (power_off == 1) { + _E("during power off"); + return; + } + telephony_stop(); + vconf_ignore_key_changed(VCONFKEY_SYSMAN_POWER_OFF_STATUS, (void*)poweroff_control_cb); + power_off = 1; + sync(); + + buf = getenv("PWROFF_DUR"); + if (buf != NULL && strlen(buf) < 1024) + poweroff_duration = atoi(buf); + if (poweroff_duration < 0 || poweroff_duration > 60) + poweroff_duration = POWEROFF_DURATION; + gettimeofday(&now, NULL); + check_duration = now.tv_sec - tv_start_poweroff.tv_sec; + while (check_duration < poweroff_duration) { + if (wait == 0) { + _I("wait poweroff %d %d", check_duration, poweroff_duration); + wait = 1; + } + usleep(100000); + gettimeofday(&now, NULL); + check_duration = now.tv_sec - tv_start_poweroff.tv_sec; + if (check_duration < 0) + break; + } + unmount_rw_partition(); +} + +static void restart_by_mode(int mode) +{ + if (mode == SYSTEMD_STOP_POWER_RESTART_RECOVERY) + launch_evenif_exist("/usr/sbin/reboot", "recovery"); + else if (mode == SYSTEMD_STOP_POWER_RESTART_FOTA) + launch_evenif_exist("/usr/sbin/reboot", "fota"); + else + reboot(RB_AUTOBOOT); +} + +int internal_poweroff_def_predefine_action(int argc, char **argv) +{ + int ret; + const struct device_ops *display_device_ops; + + telephony_start(); + + display_device_ops = find_device("display"); + if (!display_device_ops) { + _E("Can't find display_device_ops"); + return -ENODEV; + } + + display_device_ops->exit(NULL); + sync(); + + gettimeofday(&tv_start_poweroff, NULL); + + ret = telephony_exit(PREDEF_POWEROFF); + + if (ret < 0) { + powerdown_ap(NULL); + return 0; + } + return ret; +} + +int do_poweroff(int argc, char **argv) +{ + return internal_poweroff_def_predefine_action(argc, argv); +} + +int poweroff_def_predefine_action(int argc, char **argv) +{ + int retry_count = 0; + poweroff_start_animation(); + while (retry_count < MAX_RETRY) { + if (notify_action(PREDEF_INTERNAL_POWEROFF, 0) < 0) { + _E("failed to request poweroff to deviced"); + retry_count++; + continue; + } + vconf_ignore_key_changed(VCONFKEY_SYSMAN_POWER_OFF_STATUS, (void*)poweroff_control_cb); + return 0; + } + return -1; +} + +static int hall_ic_status(void) +{ + if (!hall_ic) + return HALL_IC_OPENED; + return hall_ic->status(); +} + +int launching_predefine_action(int argc, char **argv) +{ + struct popup_data *params; + static const struct device_ops *apps = NULL; + int val; + + val = hall_ic_status(); + if (val == HALL_IC_CLOSED) { + _I("cover is closed"); + return 0; + } + if (apps == NULL) { + apps = find_device("apps"); + if (apps == NULL) + return 0; + } + params = malloc(sizeof(struct popup_data)); + if (params == NULL) { + _E("Malloc failed"); + return -1; + } + params->name = POWEROFF_POPUP_NAME; + apps->init((void *)params); + free(params); + return 0; +} + +int restart_def_predefine_action(int argc, char **argv) +{ + int ret; + int data = 0; + + const struct device_ops *display_device_ops; + poweroff_start_animation(); + telephony_start(); + + display_device_ops = find_device("display"); + if (!display_device_ops) { + _E("Can't find display_device_ops"); + return -ENODEV; + } + + pm_change_internal(getpid(), LCD_NORMAL); + display_device_ops->exit(NULL); + sync(); + + gettimeofday(&tv_start_poweroff, NULL); + + if (argc == 1 && argv) + data = atoi(argv[0]); + if (data == SYSTEMD_STOP_POWER_RESTART_RECOVERY) + ret = telephony_exit(PREDEF_RECOVERY); + else if (data == SYSTEMD_STOP_POWER_RESTART_FOTA) + ret = telephony_exit(PREDEF_FOTA_REBOOT); + else + ret = telephony_exit(PREDEF_REBOOT); + + if (ret < 0) { + restart_ap((void *)data); + return 0; + } + return ret; +} + +int restart_recovery_def_predefine_action(int argc, char **argv) +{ + int ret; + char *param[1]; + char status[32]; + + snprintf(status, sizeof(status), "%d", SYSTEMD_STOP_POWER_RESTART_RECOVERY); + param[0] = status; + + return restart_def_predefine_action(1, param); +} + +int restart_fota_def_predefine_action(int argc, char **argv) +{ + int ret; + char *param[1]; + char status[32]; + + snprintf(status, sizeof(status), "%d", SYSTEMD_STOP_POWER_RESTART_FOTA); + param[0] = status; + + return restart_def_predefine_action(1, param); +} + +int reset_resetkey_disable(char *name, enum watch_id id) +{ + _D("force reset power resetkey disable to zero"); + return device_set_property(DEVICE_TYPE_POWER, PROP_POWER_RESETKEY_DISABLE, 0); +} + +static DBusMessage *edbus_resetkeydisable(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int val, ret; + + ret = dbus_message_get_args(msg, NULL, DBUS_TYPE_INT32, &val, + DBUS_TYPE_INVALID); + if (!ret) { + _E("there is no message"); + ret = -EINVAL; + goto error; + } + + ret = device_set_property(DEVICE_TYPE_POWER, PROP_POWER_RESETKEY_DISABLE, val); + if (ret < 0) + goto error; + + if (val) + register_edbus_watch(msg, WATCH_POWER_RESETKEY_DISABLE, reset_resetkey_disable); + else + unregister_edbus_watch(msg, WATCH_POWER_RESETKEY_DISABLE); + + _D("get power resetkey disable %d, %d", val, ret); + +error: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static int reset_wakeupkey(char *name, enum watch_id id) +{ + _D("force reset wakeupkey to zero"); + return device_set_property(DEVICE_TYPE_POWER, PROP_POWER_WAKEUP_KEY, 0); +} + +static DBusMessage *edbus_set_wakeup_key(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int val, ret; + + ret = dbus_message_get_args(msg, NULL, + DBUS_TYPE_INT32, &val, + DBUS_TYPE_INVALID); + if (!ret) { + _E("there is no message"); + ret = -EINVAL; + goto error; + } + + ret = device_set_property(DEVICE_TYPE_POWER, PROP_POWER_WAKEUP_KEY, val); + if (ret < 0) + goto error; + + if (val) + register_edbus_watch(msg, WATCH_POWER_WAKEUPKEY, reset_wakeupkey); + else + unregister_edbus_watch(msg, WATCH_POWER_WAKEUPKEY); + + _D("set power wakeup key %d %d", val, ret); + +error: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *dbus_power_handler(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusError err; + DBusMessageIter iter; + DBusMessage *reply; + pid_t pid; + int ret; + int argc; + char *type_str; + + dbus_error_init(&err); + + if (!dbus_message_get_args(msg, &err, + DBUS_TYPE_STRING, &type_str, + DBUS_TYPE_INT32, &argc, DBUS_TYPE_INVALID)) { + _E("there is no message"); + ret = -EINVAL; + goto out; + } + + if (argc < 0) { + _E("message is invalid!"); + ret = -EINVAL; + goto out; + } + + pid = get_edbus_sender_pid(msg); + if (kill(pid, 0) == -1) { + _E("%d process does not exist, dbus ignored!", pid); + ret = -ESRCH; + goto out; + } + + telephony_start(); + + if(strncmp(type_str, PREDEF_REBOOT, strlen(PREDEF_REBOOT)) == 0) + restart_def_predefine_action(0, NULL); + else if(strncmp(type_str, PREDEF_RECOVERY, strlen(PREDEF_RECOVERY)) == 0) + restart_recovery_def_predefine_action(0, NULL); + else if(strncmp(type_str, PREDEF_PWROFF_POPUP, strlen(PREDEF_PWROFF_POPUP)) == 0) + launching_predefine_action(0, NULL); + +out: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + + return reply; +} + +void powerdown_ap(void *data) +{ + _I("Power off"); + powerdown(); + reboot(RB_POWER_OFF); +} + +void restart_ap(void *data) +{ + _I("Restart %d", (int)data); + powerdown(); + restart_by_mode((int)data); +} + +static const struct edbus_method edbus_methods[] = { + { "setresetkeydisable", "i", "i", edbus_resetkeydisable }, + { "SetWakeupKey", "i", "i", edbus_set_wakeup_key }, + { PREDEF_REBOOT, "si", "i", dbus_power_handler }, + { PREDEF_RECOVERY, "si", "i", dbus_power_handler }, + { PREDEF_PWROFF_POPUP, "si", "i", dbus_power_handler }, + /* Add methods here */ +}; + +static void power_init(void *data) +{ + int bTelReady = 0; + int ret; + + /* init dbus interface */ + ret = register_edbus_method(DEVICED_PATH_POWER, edbus_methods, ARRAY_SIZE(edbus_methods)); + if (ret < 0) + _E("fail to init edbus method(%d)", ret); + + register_action(PREDEF_POWEROFF, + poweroff_def_predefine_action, NULL, NULL); + register_action(PREDEF_PWROFF_POPUP, + launching_predefine_action, NULL, NULL); + register_action(PREDEF_REBOOT, + restart_def_predefine_action, NULL, NULL); + register_action(PREDEF_RECOVERY, + restart_recovery_def_predefine_action, NULL, NULL); + register_action(PREDEF_FOTA_REBOOT, + restart_fota_def_predefine_action, NULL, NULL); + + register_action(PREDEF_INTERNAL_POWEROFF, + internal_poweroff_def_predefine_action, NULL, NULL); + + if (vconf_notify_key_changed(VCONFKEY_SYSMAN_POWER_OFF_STATUS, (void *)poweroff_control_cb, NULL) < 0) { + _E("Vconf notify key chaneged failed: KEY(%s)", VCONFKEY_SYSMAN_POWER_OFF_STATUS); + } + + register_edbus_signal_handler(DEVICED_OBJECT_PATH, DEVICED_INTERFACE_NAME, + SIGNAL_NAME_POWEROFF_POPUP, + poweroff_popup_edbus_signal_handler); + register_edbus_signal_handler(DEVICED_PATH_CORE, + DEVICED_INTERFACE_CORE, + SIGNAL_BOOTING_DONE, + booting_done_edbus_signal_handler); + hall_ic = find_device(HALL_IC_NAME); +} + +static const struct device_ops power_device_ops = { + .priority = DEVICE_PRIORITY_NORMAL, + .name = "power", + .init = power_init, +}; + +DEVICE_OPS_REGISTER(&power_device_ops) diff --git a/src/power/power-handler.h b/src/power/power-handler.h new file mode 100644 index 0000000..106bfe5 --- /dev/null +++ b/src/power/power-handler.h @@ -0,0 +1,36 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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_HANDLE_H__ +#define __POWER_HANDLE_H__ + +#define PREDEF_POWEROFF "poweroff" +#define PREDEF_REBOOT "reboot" +#define PREDEF_RECOVERY "reboot-recovery" +#define PREDEF_FOTA_REBOOT "fota" + +#define SYSTEMD_STOP_POWER_RESTART 5 +#define SYSTEMD_STOP_POWER_RESTART_RECOVERY 6 +#define SYSTEMD_STOP_POWER_RESTART_FOTA 7 + +#ifndef SYSTEMD_SHUTDOWN +void restart_ap(void *data); +void powerdown_ap(void *data); +#endif + +#endif /* __POWER_HANDLE_H__ */ diff --git a/src/power/systemd-power.c b/src/power/systemd-power.c new file mode 100644 index 0000000..40a402c --- /dev/null +++ b/src/power/systemd-power.c @@ -0,0 +1,329 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "core/common.h" +#include "core/data.h" +#include "core/device-handler.h" +#include "core/device-notifier.h" +#include "core/devices.h" +#include "core/edbus-handler.h" +#include "core/launch.h" +#include "core/log.h" +#include "core/predefine.h" +#include "core/queue.h" +#include "dd-deviced.h" +#include "display/poll.h" +#include "display/setting.h" +#include "hall/hall-handler.h" +#include "power-handler.h" +#include "proc/proc-handler.h" + +#define SIGNAL_BOOTING_DONE "BootingDone" +#define PREDEF_PWROFF_POPUP "pwroff-popup" +#define POWEROFF_POPUP_NAME "poweroff-syspopup" +#define RECOVERY_POWER_OFF "reboot recovery" + +#define SYSTEMD_STOP_POWER_OFF 4 +#define SYSTEMD_STOP_POWER_RESTART 5 +#define SYSTEMD_STOP_POWER_RESTART_RECOVERY 6 +#define SYSTEMD_CHECK_POWER_OFF 15 + +struct popup_data { + char *name; + char *key; +}; + +static const struct device_ops *hall_ic = NULL; +static Ecore_Timer *systemd_poweroff_timer = NULL; + +static Eina_Bool systemd_force_shutdown_cb(void *arg) +{ + char params[128]; + if (systemd_poweroff_timer) { + ecore_timer_del(systemd_poweroff_timer); + systemd_poweroff_timer = NULL; + } + snprintf(params, sizeof(params), "%s -f", (char*)arg); + launch_evenif_exist("/usr/bin/systemctl", params); + return EINA_TRUE; +} + +static void start_boot_animation(void) +{ + char params[128]; + snprintf(params, sizeof(params), "--stop --clear"); + launch_evenif_exist("/usr/bin/boot-animation", params); +} + +static int systemd_shutdown(const char *arg) +{ + assert(arg); + systemd_poweroff_timer = ecore_timer_add(SYSTEMD_CHECK_POWER_OFF, + systemd_force_shutdown_cb, (void *)arg); + start_boot_animation(); + device_notify(DEVICE_NOTIFIER_POWEROFF_HAPTIC, NULL); + return launch_evenif_exist("/usr/bin/systemctl", arg); +} + +int do_poweroff(int argc, char **argv) +{ + return vconf_set_int(VCONFKEY_SYSMAN_POWER_OFF_STATUS, + VCONFKEY_SYSMAN_POWER_OFF_DIRECT); +} + +static void poweroff_control_cb(keynode_t *in_key, struct main_data *ad) +{ + int val; + int ret; + + if (vconf_get_int(in_key->keyname, &val) != 0) + return; + + if (val == SYSTEMD_STOP_POWER_OFF + || val == SYSTEMD_STOP_POWER_RESTART + || val == SYSTEMD_STOP_POWER_RESTART_RECOVERY) { + vconf_ignore_key_changed(in_key->keyname, + (void*)poweroff_control_cb); + vconf_set_int(in_key->keyname, val); + } + + device_notify(DEVICE_NOTIFIER_PMQOS_POWEROFF, (void*)1); + + switch (val) { + case SYSTEMD_STOP_POWER_OFF: + case VCONFKEY_SYSMAN_POWER_OFF_DIRECT: + device_notify(DEVICE_NOTIFIER_POWEROFF, + (void *)VCONFKEY_SYSMAN_POWER_OFF_DIRECT); + ret = systemd_shutdown(PREDEF_POWEROFF); + if (ret < 0) + _E("fail to do (%s)", PREDEF_POWEROFF); + break; + case SYSTEMD_STOP_POWER_RESTART: + case VCONFKEY_SYSMAN_POWER_OFF_RESTART: + device_notify(DEVICE_NOTIFIER_POWEROFF, + (void *)VCONFKEY_SYSMAN_POWER_OFF_RESTART); + ret = systemd_shutdown(PREDEF_REBOOT); + if (ret < 0) + _E("fail to do (%s)", PREDEF_REBOOT); + break; + case SYSTEMD_STOP_POWER_RESTART_RECOVERY: + device_notify(DEVICE_NOTIFIER_POWEROFF, + (void *)VCONFKEY_SYSMAN_POWER_OFF_RESTART); + ret = systemd_shutdown(RECOVERY_POWER_OFF); + if (ret < 0) + _E("fail to do (%s)", RECOVERY_POWER_OFF); + break; + case VCONFKEY_SYSMAN_POWER_OFF_POPUP: + notify_action(PREDEF_PWROFF_POPUP, 0); + break; + } + + if (update_pm_setting) + update_pm_setting(SETTING_POWEROFF, val); +} + +static void booting_done_edbus_signal_handler(void *data, DBusMessage *msg) +{ + if (!dbus_message_is_signal(msg, + DEVICED_INTERFACE_CORE, + SIGNAL_BOOTING_DONE)) { + _E("there is no bootingdone signal"); + return; + } + + device_notify(DEVICE_NOTIFIER_BOOTING_DONE, (void *)TRUE); +} + +static int hall_ic_status(void) +{ + if (!hall_ic) + return HALL_IC_OPENED; + return hall_ic->status(); +} + +int reset_resetkey_disable(char *name, enum watch_id id) +{ + _D("force reset power resetkey disable to zero"); + return device_set_property(DEVICE_TYPE_POWER, + PROP_POWER_RESETKEY_DISABLE, + 0); +} + +static DBusMessage *edbus_resetkeydisable(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int val, ret; + + ret = dbus_message_get_args(msg, NULL, DBUS_TYPE_INT32, &val, + DBUS_TYPE_INVALID); + if (!ret) { + _E("there is no message"); + ret = -EINVAL; + goto error; + } + + ret = device_set_property(DEVICE_TYPE_POWER, + PROP_POWER_RESETKEY_DISABLE, + val); + if (ret < 0) + goto error; + + if (val) + register_edbus_watch(msg, + WATCH_POWER_RESETKEY_DISABLE, + reset_resetkey_disable); + else + unregister_edbus_watch(msg, + WATCH_POWER_RESETKEY_DISABLE); + + _D("get power resetkey disable %d, %d", val, ret); + +error: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static int reset_wakeupkey(char *name, enum watch_id id) +{ + _D("force reset wakeupkey to zero"); + return device_set_property(DEVICE_TYPE_POWER, PROP_POWER_WAKEUP_KEY, 0); +} + +static DBusMessage *edbus_set_wakeup_key(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int val, ret; + + ret = dbus_message_get_args(msg, NULL, + DBUS_TYPE_INT32, &val, + DBUS_TYPE_INVALID); + if (!ret) { + _E("there is no message"); + ret = -EINVAL; + goto error; + } + + ret = device_set_property(DEVICE_TYPE_POWER, PROP_POWER_WAKEUP_KEY, val); + if (ret < 0) + goto error; + + if (val) + register_edbus_watch(msg, WATCH_POWER_WAKEUPKEY, reset_wakeupkey); + else + unregister_edbus_watch(msg, WATCH_POWER_WAKEUPKEY); + + _D("set power wakeup key %d %d", val, ret); + +error: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static const struct edbus_method edbus_methods[] = { + { "setresetkeydisable", "i", "i", edbus_resetkeydisable }, + { "SetWakeupKey", "i", "i", edbus_set_wakeup_key }, + /* Add methods here */ +}; + +int launching_predefine_action(int argc, char **argv) +{ + struct popup_data *params; + static const struct device_ops *apps = NULL; + int val; + + val = hall_ic_status(); + if (val == HALL_IC_CLOSED) { + _I("cover is closed"); + return 0; + } + if (apps == NULL) { + apps = find_device("apps"); + if (apps == NULL) + return 0; + } + params = malloc(sizeof(struct popup_data)); + if (params == NULL) { + _E("Malloc failed"); + return -1; + } + params->name = POWEROFF_POPUP_NAME; + apps->init((void *)params); + free(params); + return 0; +} + +static void power_init(void *data) +{ + int bTelReady = 0; + int ret; + + /* init dbus interface */ + ret = register_edbus_method(DEVICED_PATH_POWER, + edbus_methods, + ARRAY_SIZE(edbus_methods)); + if (ret < 0) + _E("fail to init edbus method(%d)", ret); + + ret = register_edbus_signal_handler(DEVICED_PATH_CORE, + DEVICED_INTERFACE_CORE, + SIGNAL_BOOTING_DONE, + booting_done_edbus_signal_handler); + if (ret < 0) + _E("fail to register handler for signal: %s", + SIGNAL_BOOTING_DONE); + + register_action(PREDEF_POWEROFF, + do_poweroff, NULL, NULL); + register_action(PREDEF_PWROFF_POPUP, + launching_predefine_action, NULL, NULL); + + ret = vconf_notify_key_changed(VCONFKEY_SYSMAN_POWER_OFF_STATUS, + (void *)poweroff_control_cb, + NULL); + if (ret < 0) + _E("Vconf notify key chaneged failed: KEY(%s)", + VCONFKEY_SYSMAN_POWER_OFF_STATUS); + hall_ic = find_device(HALL_IC_NAME); +} + +static const struct device_ops power_device_ops = { + .priority = DEVICE_PRIORITY_NORMAL, + .name = "systemd-power", + .init = power_init, +}; + +DEVICE_OPS_REGISTER(&power_device_ops) diff --git a/src/powersaver/powersaver.c b/src/powersaver/powersaver.c new file mode 100644 index 0000000..dae3128 --- /dev/null +++ b/src/powersaver/powersaver.c @@ -0,0 +1,159 @@ +/* + * deviced + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include + +#include "core/common.h" +#include "core/devices.h" +#include "core/device-notifier.h" +#include "core/log.h" +#include "display/core.h" +#include "display/device-interface.h" + +static int set_powersaver_mode(int on) +{ + int ret; + int brightness, timeout; + + _I("powersaver mode %s", (on ? "on" : "off")); + device_notify(DEVICE_NOTIFIER_POWERSAVER, (void*)on); + + /* powersaver mode off */ + if (!on) { + backlight_ops.set_force_brightness(0); + set_force_lcdtimeout(0); + goto update_state; + } + + /* powersaver mode on (brightness) */ + ret = vconf_get_int(VCONFKEY_SETAPPL_EMERGENCY_LCD_BRIGHTNESS_INT, + &brightness); + if (ret != 0) { + _E("Failed to get powersaver brightness!"); + return ret; + } + ret = backlight_ops.set_force_brightness(brightness); + if (ret < 0) { + _E("Failed to set force brightness!"); + return ret; + } + _I("force brightness %d", brightness); + + /* powersaver mode on (lcd timeout) */ + ret = vconf_get_int(VCONFKEY_SETAPPL_EMERGENCY_LCD_TIMEOUT_INT, + &timeout); + if (ret != 0) { + _E("Failed to get powersaver lcd timeout!"); + return ret; + } + ret = set_force_lcdtimeout(timeout); + if (ret < 0) { + _E("Failed to set force timeout!"); + return ret; + } + _I("force timeout %d", timeout); + +update_state: + /* update internal state */ + if (hbm_get_state()) + hbm_set_state_with_timeout(false, 0); + backlight_ops.update(); + ret = get_run_timeout(&timeout); + if (ret >= 0) + states[S_NORMAL].timeout = timeout; + states[pm_cur_state].trans(EVENT_INPUT); + + return 0; +} + +static void powersaver_status_changed(keynode_t *key_nodes, void *data) +{ + int status, on, ret; + + if (key_nodes == NULL) { + _E("wrong parameter, key_nodes is null"); + return; + } + + status = vconf_keynode_get_int(key_nodes); + if (status == SETTING_PSMODE_NORMAL) + on = false; + else if (status == SETTING_PSMODE_WEARABLE) + on = true; + else + return; + + ret = set_powersaver_mode(on); + if (ret < 0) + _E("Failed to update powersaver state %d", ret); +} + +static int booting_done(void *data) +{ + int ret, status; + + ret = vconf_get_int(VCONFKEY_SETAPPL_PSMODE, &status); + if (ret != 0) { + _E("Failed to vconf get bool!"); + return -EIO; + } + + if (status != SETTING_PSMODE_WEARABLE) + return 0; + + _D("powersaver mode on!"); + ret = set_powersaver_mode(true); + if (ret < 0) + _E("Failed to update powersaver state %d", ret); + + return ret; +} + +static void powersaver_init(void *data) +{ + int ret; + + ret = vconf_notify_key_changed(VCONFKEY_SETAPPL_PSMODE, + powersaver_status_changed, NULL); + if (ret != 0) + _E("Failed to vconf_notify_key_changed!"); + + register_notifier(DEVICE_NOTIFIER_BOOTING_DONE, booting_done); +} + +static void powersaver_exit(void *data) +{ + int ret; + + ret = vconf_ignore_key_changed(VCONFKEY_SETAPPL_PSMODE, + powersaver_status_changed); + if (ret != 0) + _E("Failed to vconf_ignore_key_changed!"); + + unregister_notifier(DEVICE_NOTIFIER_BOOTING_DONE, booting_done); +} + +static const struct device_ops powersaver_device_ops = { + .priority = DEVICE_PRIORITY_NORMAL, + .name = "powersaver", + .init = powersaver_init, + .exit = powersaver_exit, +}; + +DEVICE_OPS_REGISTER(&powersaver_device_ops) diff --git a/src/predefine_act_plugin/CMakeLists.txt b/src/predefine_act_plugin/CMakeLists.txt new file mode 100644 index 0000000..100c04f --- /dev/null +++ b/src/predefine_act_plugin/CMakeLists.txt @@ -0,0 +1,38 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(xxx-predefine C) + +SET(SRCS xxx-predefine.c) + +SET(PREFIX ${CMAKE_INSTALL_PREFIX}) +SET(EXEC_PREFIX "\${prefix}") +SET(LIBDIR "\${prefix}/lib") +SET(INCLUDEDIR "\${prefix}/include") +SET(VERSION 1.0) + +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) + +INCLUDE(FindPkgConfig) +pkg_check_modules(pkgs REQUIRED sysman) + +FOREACH(flag ${pkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -g -fno-omit-frame-pointer") + +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") +MESSAGE("FLAGS: ${CMAKE_C_FLAGS}") + +ADD_DEFINITIONS("-DPREFIX=\"${CMAKE_INSTALL_PREFIX}\"") +ADD_DEFINITIONS("-DFACTORYFS=\"$ENV{FACTORYFS}\"") +ADD_DEFINITIONS("-DDEBUG") +IF( $ENV{ARCH} MATCHES "arm" ) + ADD_DEFINITIONS("-DTARGET") +ENDIF() + +SET(CMAKE_LDFLAGS "-Wl,zdefs") +ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS}) +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS}) + +INSTALL(TARGETS ${PROJECT_NAME} DESTINATION lib COMPONENT RuntimeLibraries) + diff --git a/src/predefine_act_plugin/build.sh b/src/predefine_act_plugin/build.sh new file mode 100755 index 0000000..c0cc290 --- /dev/null +++ b/src/predefine_act_plugin/build.sh @@ -0,0 +1,7 @@ +cd `dirname $0` + +. ../../../../../setup.conf || exit 1 + +. ${TPLDIR}/cmake.tpl +run + diff --git a/src/predefine_act_plugin/xxx-predefine.c b/src/predefine_act_plugin/xxx-predefine.c new file mode 100644 index 0000000..507bf09 --- /dev/null +++ b/src/predefine_act_plugin/xxx-predefine.c @@ -0,0 +1,45 @@ +/* + * system-server + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: DongGi Jang + * + * 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 SS_PREDEFINE_ACT_FUNC(int argc, char **argv) +{ + int i; + printf("kqwekrqkwerqwer\n"); + for (i = 0; i < argc; i++) + printf("%s\n", argv[i]); + return 0; +} + +int SS_IS_ACCESSABLE_FUNC(int pid) +{ + printf("qwerqerqewr %d\n", pid); + return 1; +} + +int SS_UI_VIEWABLE_FUNC() +{ + printf("kakak viewable\n"); + return 1; +} diff --git a/src/proc/cpu-info.c b/src/proc/cpu-info.c new file mode 100644 index 0000000..2c8e00e --- /dev/null +++ b/src/proc/cpu-info.c @@ -0,0 +1,151 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include + +#include "core/log.h" +#include "core/devices.h" +#include "core/edbus-handler.h" +#include "core/common.h" + +#define METHOD_GET_REVISION "GetRevision" +#define PATH_NAME "/proc/cpuinfo" +#define REVISION_NAME "Revision" +#define TOK_DELIMITER ":" +#define END_DELIMITER " \n" + +#define CONVERT_TYPE 10 +#define REVISION_SIZE 4 +#define FILE_BUFF_MAX 1024 +#define NOT_INITIALIZED (-1) + +static int read_from_file(const char *path, char *buf, size_t size) +{ + int fd; + size_t count; + + if (!path) + return -1; + + fd = open(path, O_RDONLY, 0); + if (fd == -1) { + _E("Could not open '%s'", path); + return -1; + } + + count = read(fd, buf, size); + + if (count > 0) { + count = (count < size) ? count : size - 1; + while (count > 0 && buf[count - 1] == '\n') + count--; + buf[count] = '\0'; + } else { + buf[0] = '\0'; + } + + close(fd); + + return 0; +} + +static int get_revision(char *rev) +{ + char buf[FILE_BUFF_MAX]; + char *tag; + char *start, *ptr; + long rev_num; + const int radix = 16; + + if (rev == NULL) { + _E("Invalid argument !\n"); + return -1; + } + + if (read_from_file(PATH_NAME, buf, FILE_BUFF_MAX) < 0) { + _E("fail to read %s\n", PATH_NAME); + return -1; + } + + tag = strstr(buf, REVISION_NAME); + if (tag == NULL) { + _E("cannot find Hardware in %s\n", PATH_NAME); + return -1; + } + + start = strstr(tag, TOK_DELIMITER); + if (start == NULL) { + _E("cannot find Hardware in %s\n", PATH_NAME); + return -1; + } + + start ++; + ptr = strtok(start, END_DELIMITER); + ptr += strlen(ptr); + ptr -=2; + + memset(rev, 0x00, REVISION_SIZE); + rev_num = strtol(ptr, NULL, radix); + sprintf(rev, "%d", rev_num); + + return 0; +} + +static DBusMessage *dbus_revision_handler(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + char rev[FILE_BUFF_MAX]; + char *ptr; + static int ret = NOT_INITIALIZED; + + if (ret != NOT_INITIALIZED) + goto out; + ret = get_revision(rev); + if (ret == 0) + ret = strtol(rev, &ptr, CONVERT_TYPE); +out: + _D("rev : %d", ret); + + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static const struct edbus_method edbus_methods[] = { + { METHOD_GET_REVISION, NULL, "i", dbus_revision_handler }, +}; + +static void cpu_info_init(void *data) +{ + int ret; + + ret = register_edbus_method(DEVICED_PATH_SYSNOTI, edbus_methods, ARRAY_SIZE(edbus_methods)); + if (ret < 0) + _E("fail to init edbus method(%d)", ret); +} + +static const struct device_ops cpu_info_device_ops = { + .priority = DEVICE_PRIORITY_NORMAL, + .name = "cpu_info", + .init = cpu_info_init, +}; + +DEVICE_OPS_REGISTER(&cpu_info_device_ops) diff --git a/src/proc/pmon-handler.c b/src/proc/pmon-handler.c new file mode 100644 index 0000000..98abc37 --- /dev/null +++ b/src/proc/pmon-handler.c @@ -0,0 +1,285 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include +#include +#include +#include +#include +#include + +#include "core/log.h" +#include "core/launch.h" +#include "core/data.h" +#include "core/common.h" +#include "core/devices.h" + +#define PMON_PERMANENT_DIR "/tmp/permanent" + +static Ecore_Fd_Handler *pmon_efd = NULL; + +static int __pmon_start(struct main_data *ad); +static int __pmon_stop(int fd); +static int replace_char(int size, char *t) +{ + while (size > 0) { + if (*t == 0) + *t = ' '; + size--; + t++; + } + return 0; +} + +static char *pmon_get_permanent_pname(int pid) +{ + int fd; + int ret; + char buf[PATH_MAX]; + struct stat st; + char *cmdline = NULL; + + snprintf(buf, sizeof(buf), "%s/%d", PMON_PERMANENT_DIR, pid); + fd = open(buf, O_RDONLY); + if (fd == -1) { + _E("file open error"); + return NULL; + } + + if (fstat(fd, &st) < 0) { + _E("fstat error"); + close(fd); + return NULL; + } + _D("size = %d", (int)st.st_size); + + cmdline = malloc(st.st_size + 1); + if (cmdline == NULL) { + _E("Not enough memory"); + close(fd); + return NULL; + } + memset(cmdline, 0, st.st_size + 1); + + ret = read(fd, cmdline, st.st_size); + if (ret >= 0 && ret < st.st_size) { + /* TODO - must change more smarter */ + replace_char(st.st_size - 1, cmdline); + } + close(fd); + + return cmdline; +} + +static void print_pmon_state(unsigned int dead_pid) +{ + _D("[Process MON] %d killed", dead_pid); +} + +static int pmon_process(int pid, void *ad) +{ + char *cmdline; + int new_pid; + char old_file[PATH_MAX]; + int fd; + int r; + + if (is_vip(pid)) { + _I("======================================="); + _I("[Process MON] VIP process dead."); + _I("======================================="); + } + /* If there is NOT a .hibernation_start file, run following codes + * On hibernation processing, just ignore relaunching */ + else if (access("/tmp/.hibernation_start", R_OK) != 0) { + cmdline = pmon_get_permanent_pname(pid); + if (cmdline != NULL) { + _I("[Process MON] %s relaunch", cmdline); + new_pid = launch_evenif_exist(cmdline, ""); + free(cmdline); + if (new_pid > 0) { + /* TODO - set oom */ + char buf[PATH_MAX]; + char filepath[PATH_MAX]; + int cnt; + + if (access(PMON_PERMANENT_DIR, R_OK) < 0) { + _I("no predefined matrix dir = %s, so created", PMON_PERMANENT_DIR); + r = mkdir(PMON_PERMANENT_DIR, 0777); + if(r < 0) { + _E("Make Directory is failed"); + return -1; + } + } + + snprintf(filepath, sizeof(filepath), "%s/%d", PMON_PERMANENT_DIR, pid); + fd = open(filepath, O_RDONLY); + if (fd == -1) { + _E("Failed to open"); + return -1; + } + cnt = read(fd, buf, PATH_MAX); + close(fd); + + if (cnt <= 0) { + _E("Failed to read"); + return -1; + } + + snprintf(filepath, sizeof(filepath), "%s/%d", PMON_PERMANENT_DIR, new_pid); + + fd = open(filepath, O_CREAT | O_WRONLY, 0644); + if (fd == -1) { + _E("Failed to open"); + return -1; + } + if (write(fd, buf, cnt) == -1) { + _E("Failed to write"); + close(fd); + return -1; + } + close(fd); + if ( device_set_property(DEVICE_TYPE_PROCESS, PROP_PROCESS_MP_PNP, new_pid) < 0) { + _E("Write new pid failed"); + } + _I("[Process MON] %d ", new_pid); + + FILE *fp; + + _I("[Process MON] OOMADJ_SET : pid %d, new_oomadj %d", + new_pid, (-17)); + + fp = open_proc_oom_score_adj_file(new_pid, "w"); + if (fp == NULL) + return -1; + fprintf(fp, "%d",0); + fclose(fp); + + snprintf(old_file, sizeof(old_file), "%s/%d", + PMON_PERMANENT_DIR, pid); + unlink(old_file); + } else { + _I("[Process MON] failed relaunching"); + } + } + } + return 0; +} +/* +static unsigned int pmon_read(int fd) +{ + unsigned int pid; + read(fd, &pid, sizeof(pid)); + return pid; +} +*/ + +static Eina_Bool pmon_cb(void *data, Ecore_Fd_Handler * fd_handler) +{ + int fd; + struct main_data *ad = (struct main_data *)data; + int dead_pid; + char pid_str[PATH_MAX]; + int ret; + + if (!ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ)) { + _E("ecore_main_fd_handler_active_get error , return"); + goto out; + } + + fd = ecore_main_fd_handler_fd_get(fd_handler); + + if (fd < 0) { + _E("ecore_main_fd_handler_fd_get error , return"); + goto out; + } + + ret = read(fd, pid_str, PATH_MAX); + + if (ret < 0 || ret >= PATH_MAX) { + __pmon_stop(fd); + _E("Reading DEAD_PID failed, restart ecore fd"); + __pmon_start(ad); + goto out; + } + + pid_str[ret] = '\0'; + dead_pid = strtoul(pid_str, NULL, 10); + print_pmon_state(dead_pid); + pmon_process(dead_pid, ad); +out: + return EINA_TRUE; +} + +static int __pmon_start(struct main_data *ad) +{ + int pmon_fd = -1; + char pmon_dev_node[PATH_MAX]; + if (device_get_property(DEVICE_TYPE_PROCESS, PROP_PROCESS_NODE, + (int *)pmon_dev_node) < 0) { + _E("ss_pmon_init get dev node path failed"); + return -1; + } + + pmon_fd = open(pmon_dev_node, O_RDONLY); + if (pmon_fd < 0) { + _E("ss_pmon_init fd open failed"); + return -1; + } + pmon_efd = ecore_main_fd_handler_add(pmon_fd, ECORE_FD_READ, pmon_cb, ad, NULL, NULL); + if (!pmon_efd) { + _E("error ecore_main_fd_handler_add"); + return -1; + } + return 0; +} +static int __pmon_stop(int fd) +{ + if (pmon_efd) { + ecore_main_fd_handler_del(pmon_efd); + pmon_efd = NULL; + } + if (fd >=0) { + close(fd); + fd = -1; + } + return 0; +} + +static void pmon_init(void *data) +{ + struct main_data *ad = (struct main_data*)data; + int ret = -1; + + if (pmon_efd) { + ecore_main_fd_handler_del(pmon_efd); + pmon_efd = NULL; + } + if (__pmon_start(ad) == -1) { + _E("fail pmon control fd init"); + } +} + +static const struct device_ops pmon_device_ops = { + .priority = DEVICE_PRIORITY_NORMAL, + .name = "pmon", + .init = pmon_init, +}; + +DEVICE_OPS_REGISTER(&pmon_device_ops) diff --git a/src/proc/proc-handler.c b/src/proc/proc-handler.c new file mode 100644 index 0000000..7b4c258 --- /dev/null +++ b/src/proc/proc-handler.c @@ -0,0 +1,772 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "core/data.h" +#include "core/queue.h" +#include "core/log.h" +#include "core/common.h" +#include "core/devices.h" +#include "core/device-notifier.h" +#include "display/enhance.h" +#include "proc-handler.h" +#include "core/edbus-handler.h" + +#define LIMITED_PROCESS_OOMADJ 15 + +#define PROCESS_VIP "process_vip" +#define PROCESS_PERMANENT "process_permanent" +#define OOMADJ_SET "oomadj_set" + +#define PREDEF_BACKGRD "backgrd" +#define PREDEF_FOREGRD "foregrd" +#define PREDEF_ACTIVE "active" +#define PREDEF_INACTIVE "inactive" +#define PROCESS_GROUP_SET "process_group_set" + +#define VCONFKEY_INTERNAL_PRIVATE_SIOP_DISABLE "memory/private/sysman/siop_disable" + +#define BUFF_MAX 255 +#define SIOP_CTRL_LEVEL_MASK 0xFFFF +#define SIOP_CTRL_LEVEL(val) ((val & SIOP_CTRL_LEVEL_MASK) << 16) +#define SIOP_CTRL_VALUE(s, r) (s | (r << 4)) +#define SIOP_VALUE(d, val) ((d) * (val & 0xF)) +#define REAR_VALUE(val) (val >> 4) + +#define SIGNAL_SIOP_CHANGED "ChangedSiop" +#define SIGNAL_REAR_CHANGED "ChangedRear" +#define SIOP_LEVEL_GET "GetSiopLevel" +#define REAR_LEVEL_GET "GetRearLevel" +#define SIOP_LEVEL_SET "SetSiopLevel" + +#define SIGNAL_NAME_OOMADJ_SET "OomadjSet" + +enum SIOP_DOMAIN_TYPE { + SIOP_NEGATIVE = -1, + SIOP_POSITIVE = 1, +}; + +static int siop = 0; +static int mode = 0; +static int siop_domain = SIOP_POSITIVE; + +enum siop_scenario { + MODE_NONE = 0, + MODE_LCD = 1, +}; +#ifdef NOUSE +typedef struct _node { + pid_t pid; + struct _node *next; +} Node; + +static Node *head = NULL; + +static Node *find_node(pid_t pid) +{ + Node *t = head; + + while (t != NULL) { + if (t->pid == pid) + break; + t = t->next; + } + return t; +} + +static Node *add_node(pid_t pid) +{ + Node *n; + + n = (Node *) malloc(sizeof(Node)); + if (n == NULL) { + _E("Not enough memory, add cond. fail"); + return NULL; + } + + n->pid = pid; + n->next = head; + head = n; + + return n; +} + +static int del_node(Node *n) +{ + Node *t; + Node *prev; + + if (n == NULL) + return 0; + + t = head; + prev = NULL; + while (t != NULL) { + if (t == n) { + if (prev != NULL) + prev->next = t->next; + else + head = head->next; + free(t); + break; + } + prev = t; + t = t->next; + } + return 0; +} +#endif + +int cur_siop_level(void) +{ + return SIOP_VALUE(siop_domain, siop); +} + +static void siop_level_action(int level) +{ + int val = SIOP_CTRL_LEVEL(level); + static int old; + static int siop_level = 0; + static int rear_level = 0; + static int initialized = 0; + static int domain = 0; + char *arr[1]; + char str_level[32]; + + if (initialized && siop == level && mode == old && domain == siop_domain) + return; + initialized = 1; + siop = level; + domain = siop_domain; + if (siop_domain == SIOP_NEGATIVE) + val = 0; + old = mode; + val |= old; + + device_set_property(DEVICE_TYPE_POWER, PROP_POWER_SIOP_CONTROL, val); + + val = SIOP_VALUE(siop_domain, level); + if (siop_level != val) { + siop_level = val; + snprintf(str_level, sizeof(str_level), "%d", siop_level); + arr[0] = str_level; + _I("broadcast siop %s", str_level); + broadcast_edbus_signal(DEVICED_PATH_PROCESS, DEVICED_INTERFACE_PROCESS, + SIGNAL_SIOP_CHANGED, "i", arr); + } + + val = REAR_VALUE(level); + if (rear_level != val) { + rear_level = val; + snprintf(str_level, sizeof(str_level), "%d", rear_level); + arr[0] = str_level; + _I("broadcast rear %s", str_level); + broadcast_edbus_signal(DEVICED_PATH_PROCESS, DEVICED_INTERFACE_PROCESS, + SIGNAL_REAR_CHANGED, "i", arr); + } + _I("level is d:%d(0x%x) s:%d r:%d", siop_domain, siop, siop_level, rear_level); +} + +static int siop_changed(int argc, char **argv) +{ +#ifdef MICRO_DD + return 0; +#else + int siop_level = 0; + int rear_level = 0; + int level; + int siop_disable; + int ret; + + if (argc != 2 || argv[0] == NULL) { + _E("fail to check value"); + return -1; + } + + if (argv[0] == NULL) + goto out; + + level = atoi(argv[0]); + device_set_property(DEVICE_TYPE_DISPLAY, PROP_DISPLAY_ELVSS_CONTROL, level); + ret = device_get_property(DEVICE_TYPE_POWER, PROP_POWER_SIOP_LEVEL, &level); + if (ret != 0) + goto check_rear; + + if (level <= SIOP_NEGATIVE) + siop_domain = SIOP_NEGATIVE; + else + siop_domain = SIOP_POSITIVE; + siop_level = siop_domain * level; + +check_rear: + if (argv[1] == NULL) + goto out; + + level = atoi(argv[1]); + if (device_get_property(DEVICE_TYPE_POWER, PROP_POWER_REAR_LEVEL, &level) == 0) + rear_level = level; + +out: + level = SIOP_CTRL_VALUE(siop_level, rear_level); + siop_level_action(level); + return 0; +#endif +} + +static int siop_mode_lcd(keynode_t *key_nodes, void *data) +{ + int pm_state; + if (vconf_get_int(VCONFKEY_PM_STATE, &pm_state) != 0) + _E("Fail to get vconf value for pm state\n"); + if (pm_state == VCONFKEY_PM_STATE_LCDOFF) + mode = MODE_LCD; + else + mode = MODE_NONE; + siop_level_action(siop); + return 0; +} + +static void memcg_move_group(int pid, int oom_score_adj) +{ + char buf[100]; + FILE *f; + int ret, size; + char exe_name[PATH_MAX]; + + if (get_cmdline_name(pid, exe_name, PATH_MAX) != 0) { + _E("fail to get process name(%d)", pid); + return; + } + + _SD("memcg_move_group : %s, pid = %d", exe_name, pid); + if (oom_score_adj >= OOMADJ_BACKGRD_LOCKED) + sprintf(buf, "/sys/fs/cgroup/memory/background/cgroup.procs"); + else if (oom_score_adj >= OOMADJ_FOREGRD_LOCKED && oom_score_adj < OOMADJ_BACKGRD_LOCKED) + sprintf(buf, "/sys/fs/cgroup/memory/foreground/cgroup.procs"); + else + return; + + f = fopen(buf, "w"); + if (f == NULL) + return; + size = sprintf(buf, "%d", pid); + if (fwrite(buf, size, 1, f) != 1) + _E("fwrite cgroup tasks : %d\n", pid);; + fclose(f); +} + +int get_oom_score_adj(int pid, int *oom_score_adj) +{ + char buf[PATH_MAX]; + FILE *fp; + + if (pid < 0) + return -1; + + fp = open_proc_oom_score_adj_file(pid, "r"); + if (fp == NULL) + return -1; + if (fgets(buf, PATH_MAX, fp) == NULL) { + fclose(fp); + return -1; + } + + *oom_score_adj = atoi(buf); + fclose(fp); + return 0; +} + +int set_oom_score_adj(pid_t pid, int new_oom_score_adj) +{ + FILE *fp; + int old_oom_score_adj; + char exe_name[PATH_MAX]; + + if (get_cmdline_name(pid, exe_name, PATH_MAX) < 0) + snprintf(exe_name, sizeof(exe_name), "Unknown (maybe dead)"); + + if (get_oom_score_adj(pid, &old_oom_score_adj) < 0) + return -1; + + _SI("Process %s, pid %d, old_oom_score_adj %d new_oom_score_adj %d", + exe_name, pid, old_oom_score_adj, new_oom_score_adj); + + if (new_oom_score_adj < OOMADJ_SU) + new_oom_score_adj = OOMADJ_SU; + + fp = open_proc_oom_score_adj_file(pid, "w"); + if (fp == NULL) + return -1; + + fprintf(fp, "%d", new_oom_score_adj); + fclose(fp); + + return 0; +} + +int set_su_oom_score_adj(pid_t pid) +{ + return set_oom_score_adj(pid, OOMADJ_SU); +} + +int check_oom_score_adj(int oom_score_adj) +{ + if (oom_score_adj != OOMADJ_FOREGRD_LOCKED && oom_score_adj != OOMADJ_FOREGRD_UNLOCKED) + return 0; + return -1; +} + +int set_oom_score_adj_action(int argc, char **argv) +{ + FILE *fp; + int pid = -1; + int new_oom_score_adj = 0; + + if (argc < 2) + return -1; + if ((pid = atoi(argv[0])) < 0 || (new_oom_score_adj = atoi(argv[1])) <= -20) + return -1; + + _I("OOMADJ_SET : pid %d, new_oom_score_adj %d", pid, new_oom_score_adj); + + fp = open_proc_oom_score_adj_file(pid, "w"); + if (fp == NULL) + return -1; + if (new_oom_score_adj < OOMADJ_SU) + new_oom_score_adj = OOMADJ_SU; + fprintf(fp, "%d", new_oom_score_adj); + fclose(fp); + + memcg_move_group(pid, new_oom_score_adj); + return 0; +} + +int set_active_action(int argc, char **argv) +{ + int pid = -1; + int ret = 0; + int oom_score_adj = 0; + + if (argc < 1) + return -1; + if ((pid = atoi(argv[0])) < 0) + return -1; + + if (get_oom_score_adj(pid, &oom_score_adj) < 0) + return -1; + + switch (oom_score_adj) { + case OOMADJ_FOREGRD_LOCKED: + case OOMADJ_BACKGRD_LOCKED: + case OOMADJ_SU: + ret = 0; + break; + case OOMADJ_FOREGRD_UNLOCKED: + ret = set_oom_score_adj((pid_t) pid, OOMADJ_FOREGRD_LOCKED); + break; + case OOMADJ_BACKGRD_UNLOCKED: + ret = set_oom_score_adj((pid_t) pid, OOMADJ_BACKGRD_LOCKED); + break; + case OOMADJ_INIT: + ret = set_oom_score_adj((pid_t) pid, OOMADJ_BACKGRD_LOCKED); + break; + default: + if(oom_score_adj > OOMADJ_BACKGRD_UNLOCKED) { + ret = set_oom_score_adj((pid_t) pid, OOMADJ_BACKGRD_LOCKED); + } else { + _E("Unknown oom_score_adj value (%d) !", oom_score_adj); + ret = -1; + } + break; + } + set_enhance_pid(pid); + return ret; +} + +int set_inactive_action(int argc, char **argv) +{ + int pid = -1; + int ret = 0; + int oom_score_adj = 0; + + if (argc < 1) + return -1; + if ((pid = atoi(argv[0])) < 0) + return -1; + + if (get_oom_score_adj(pid, &oom_score_adj) < 0) + return -1; + + switch (oom_score_adj) { + case OOMADJ_FOREGRD_UNLOCKED: + case OOMADJ_BACKGRD_UNLOCKED: + case OOMADJ_SU: + ret = 0; + break; + case OOMADJ_FOREGRD_LOCKED: + ret = set_oom_score_adj((pid_t) pid, OOMADJ_FOREGRD_UNLOCKED); + break; + case OOMADJ_BACKGRD_LOCKED: + ret = set_oom_score_adj((pid_t) pid, OOMADJ_BACKGRD_UNLOCKED); + break; + case OOMADJ_INIT: + ret = set_oom_score_adj((pid_t) pid, OOMADJ_BACKGRD_UNLOCKED); + break; + default: + if(oom_score_adj > OOMADJ_BACKGRD_UNLOCKED) { + ret = 0; + } else { + _E("Unknown oom_score_adj value (%d) !", oom_score_adj); + ret = -1; + } + break; + + } + set_enhance_pid(pid); + return ret; +} + +int set_process_action(int argc, char **argv) +{ + int pid = -1; + int ret = 0; + + if (argc < 1) + return -1; + if ((pid = atoi(argv[0])) < 0) + return -1; + + set_enhance_pid(pid); + return ret; +} + +int set_process_group_action(int argc, char **argv) +{ + int pid = -1; + int ret = -1; + + if (argc != 2) + return -1; + if ((pid = atoi(argv[0])) < 0) + return -1; + + if (strncmp(argv[1], PROCESS_VIP, strlen(PROCESS_VIP)) == 0) + ret = device_set_property(DEVICE_TYPE_PROCESS, PROP_PROCESS_MP_VIP, pid); + else if (strncmp(argv[1], PROCESS_PERMANENT, strlen(PROCESS_PERMANENT)) == 0) + ret = device_set_property(DEVICE_TYPE_PROCESS, PROP_PROCESS_MP_PNP, pid); + + if (ret == 0) + _I("%s : pid %d", argv[1], pid); + else + _E("fail to set %s : pid %d",argv[1], pid); + return 0; +} + +void check_siop_disable_process(int pid, char *default_name) +{ + int oom_score_adj; + char exe_name[PATH_MAX]; + if (pid <= 0) + return; + + if (get_oom_score_adj(pid, &oom_score_adj) < 0) { + _E("fail to get adj value of pid: %d (%d)", pid); + return; + } + + if (get_cmdline_name(pid, exe_name, PATH_MAX) != 0) { + _E("fail to check cmdline: %d (%s)", pid, default_name); + return; + } + + if (strncmp(exe_name, default_name, strlen(default_name)) != 0) { + return; + } + + switch (oom_score_adj) { + case OOMADJ_FOREGRD_LOCKED: + case OOMADJ_FOREGRD_UNLOCKED: + siop_level_action(0); + vconf_set_int(VCONFKEY_INTERNAL_PRIVATE_SIOP_DISABLE, 1); + return; + case OOMADJ_BACKGRD_LOCKED: + case OOMADJ_BACKGRD_UNLOCKED: + case OOMADJ_SU: + vconf_set_int(VCONFKEY_INTERNAL_PRIVATE_SIOP_DISABLE, 0); + } + return; +} + +static DBusMessage *dbus_proc_handler(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusError err; + DBusMessageIter iter; + DBusMessage *reply; + pid_t pid; + int ret; + int argc; + char *type_str; + char *argv; + + dbus_error_init(&err); + + if (!dbus_message_get_args(msg, &err, + DBUS_TYPE_STRING, &type_str, + DBUS_TYPE_INT32, &argc, + DBUS_TYPE_STRING, &argv, DBUS_TYPE_INVALID)) { + _E("there is no message"); + ret = -EINVAL; + goto out; + } + + if (argc < 0) { + _E("message is invalid!"); + ret = -EINVAL; + goto out; + } + + pid = get_edbus_sender_pid(msg); + if (kill(pid, 0) == -1) { + _E("%d process does not exist, dbus ignored!", pid); + ret = -ESRCH; + goto out; + } + + if (strncmp(type_str, PREDEF_FOREGRD, strlen(PREDEF_FOREGRD)) == 0) + ret = set_process_action(argc, (char **)&argv); + else if (strncmp(type_str, PREDEF_BACKGRD, strlen(PREDEF_BACKGRD)) == 0) + ret = set_process_action(argc, (char **)&argv); + else if (strncmp(type_str, PREDEF_ACTIVE, strlen(PREDEF_ACTIVE)) == 0) + ret = set_active_action(argc, (char **)&argv); + else if (strncmp(type_str, PREDEF_INACTIVE, strlen(PREDEF_INACTIVE)) == 0) + ret = set_inactive_action(argc, (char **)&argv); +out: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + + return reply; +} + +static DBusMessage *dbus_oom_handler(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusError err; + DBusMessageIter iter; + DBusMessage *reply; + pid_t pid; + int ret; + int argc; + char *type_str; + char *argv[2]; + + dbus_error_init(&err); + + if (!dbus_message_get_args(msg, &err, + DBUS_TYPE_STRING, &type_str, + DBUS_TYPE_INT32, &argc, + DBUS_TYPE_STRING, &argv[0], + DBUS_TYPE_STRING, &argv[1], DBUS_TYPE_INVALID)) { + _E("there is no message"); + ret = -EINVAL; + goto out; + } + + if (argc < 0) { + _E("message is invalid!"); + ret = -EINVAL; + goto out; + } + + pid = get_edbus_sender_pid(msg); + if (kill(pid, 0) == -1) { + _E("%d process does not exist, dbus ignored!", pid); + ret = -ESRCH; + goto out; + } + + if (strncmp(type_str, OOMADJ_SET, strlen(OOMADJ_SET)) == 0) + ret = set_oom_score_adj_action(argc, (char **)&argv); + else if (strncmp(type_str, PROCESS_GROUP_SET, strlen(PROCESS_GROUP_SET)) == 0) + ret = set_process_group_action(argc, (char **)&argv); +out: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + + return reply; +} + +static DBusMessage *dbus_get_siop_level(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int level; + + level = SIOP_VALUE(siop_domain, siop); + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &level); + return reply; +} + +static DBusMessage *dbus_get_rear_level(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int level; + + level = REAR_VALUE(siop); + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &level); + return reply; +} + +static DBusMessage *dbus_set_siop_level(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusError err; + DBusMessageIter iter; + DBusMessage *reply; + int ret; + char *argv[2]; + + dbus_error_init(&err); + + if (!dbus_message_get_args(msg, &err, + DBUS_TYPE_STRING, &argv[0], + DBUS_TYPE_STRING, &argv[1], DBUS_TYPE_INVALID)) { + _E("there is no message"); + ret = -EINVAL; + goto out; + } + ret = siop_changed(2, (char **)&argv); +out: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + + return reply; +} + +static void dbus_proc_oomadj_set_signal_handler(void *data, DBusMessage *msg) + +{ + DBusError err; + pid_t pid; + int ret = -EINVAL; + int argc; + char *type_str; + char *argv; + + dbus_error_init(&err); + + if (!dbus_message_get_args(msg, &err, + DBUS_TYPE_STRING, &type_str, + DBUS_TYPE_INT32, &argc, + DBUS_TYPE_STRING, &argv, DBUS_TYPE_INVALID)) { + _E("there is no message"); + return; + } + + if (argc < 0) { + _E("message is invalid!"); + return; + } + + pid = get_edbus_sender_pid(msg); + if (kill(pid, 0) == -1) { + _E("%d process does not exist, dbus ignored!", pid); + return; + } + + if (strncmp(type_str, PREDEF_FOREGRD, strlen(PREDEF_FOREGRD)) == 0) + ret = set_process_action(argc, (char **)&argv); + else if (strncmp(type_str, PREDEF_BACKGRD, strlen(PREDEF_BACKGRD)) == 0) + ret = set_process_action(argc, (char **)&argv); + else if (strncmp(type_str, PREDEF_ACTIVE, strlen(PREDEF_ACTIVE)) == 0) + ret = set_active_action(argc, (char **)&argv); + else if (strncmp(type_str, PREDEF_INACTIVE, strlen(PREDEF_INACTIVE)) == 0) + ret = set_inactive_action(argc, (char **)&argv); + + if (ret < 0) + _E("set_process_action error!"); +} + + +static const struct edbus_method edbus_methods[] = { + { PREDEF_FOREGRD, "sis", "i", dbus_proc_handler }, + { PREDEF_BACKGRD, "sis", "i", dbus_proc_handler }, + { PREDEF_ACTIVE, "sis", "i", dbus_proc_handler }, + { PREDEF_INACTIVE, "sis", "i", dbus_proc_handler }, + { OOMADJ_SET, "siss", "i", dbus_oom_handler }, + { PROCESS_GROUP_SET, "siss", "i", dbus_oom_handler }, + { SIOP_LEVEL_GET, NULL, "i", dbus_get_siop_level }, + { REAR_LEVEL_GET, NULL, "i", dbus_get_rear_level }, + { SIOP_LEVEL_SET, "ss", "i", dbus_set_siop_level }, +}; + +static int proc_booting_done(void *data) +{ + register_action(SIOP_CHANGED, siop_changed, NULL, NULL); + if (vconf_notify_key_changed(VCONFKEY_PM_STATE, (void *)siop_mode_lcd, NULL) < 0) + _E("Vconf notify key chaneged failed: KEY(%s)", VCONFKEY_PM_STATE); + siop_mode_lcd(NULL, NULL); + return 0; +} +static void process_init(void *data) +{ + int ret; + + register_edbus_signal_handler(DEVICED_PATH_PROCESS, DEVICED_INTERFACE_PROCESS, + SIGNAL_NAME_OOMADJ_SET, + dbus_proc_oomadj_set_signal_handler); + + ret = register_edbus_method(DEVICED_PATH_PROCESS, edbus_methods, ARRAY_SIZE(edbus_methods)); + if (ret < 0) + _E("fail to init edbus method(%d)", ret); + + register_action(PREDEF_FOREGRD, set_process_action, NULL, NULL); + register_action(PREDEF_BACKGRD, set_process_action, NULL, NULL); + register_action(PREDEF_ACTIVE, set_active_action, NULL, NULL); + register_action(PREDEF_INACTIVE, set_inactive_action, NULL, NULL); + register_action(OOMADJ_SET, set_oom_score_adj_action, NULL, NULL); + register_action(PROCESS_GROUP_SET, set_process_group_action, NULL, NULL); + + register_notifier(DEVICE_NOTIFIER_BOOTING_DONE, proc_booting_done); +} + +static const struct device_ops process_device_ops = { + .priority = DEVICE_PRIORITY_NORMAL, + .name = "process", + .init = process_init, +}; + +DEVICE_OPS_REGISTER(&process_device_ops) diff --git a/src/proc/proc-handler.h b/src/proc/proc-handler.h new file mode 100644 index 0000000..4a87faf --- /dev/null +++ b/src/proc/proc-handler.h @@ -0,0 +1,31 @@ +/* + * deviced + * + * Copyright (c) 2000 - 2011 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. + */ + + +#ifndef __PROC_HANDLER_H__ +#define __PROC_HANDLER_H__ + +#include "shared/score-defines.h" + +#define SIOP_CHANGED "siop_level" + +int get_oom_score_adj(int pid, int *oom_score_adj); +int set_oom_score_adj(int pid, int new_oom_score_adj); +void check_siop_disable_process(int pid, char *default_name); +int cur_siop_level(void); +#endif /* __PROC_HANDLER_H__ */ diff --git a/src/restarter/CMakeLists.txt b/src/restarter/CMakeLists.txt new file mode 100644 index 0000000..1b0f9bf --- /dev/null +++ b/src/restarter/CMakeLists.txt @@ -0,0 +1,37 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(restart C) + +IF("$ENV{CFLAGS}" MATCHES "-DTIZEN_ENGINEER_MODE") + OPTION(USE_ENGINEER_MODE "Use Engineer mode" ON) +ENDIF() + +SET(SRCS restart.c) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) + +INCLUDE(FindPkgConfig) + +FOREACH(flag ${pkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +IF(USE_ENGINEER_MODE) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -g -fno-omit-frame-pointer -finstrument-functions") +ELSE() + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -g -fno-omit-frame-pointer") +ENDIF() + +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") +MESSAGE("FLAGS: ${CMAKE_C_FLAGS}") + +ADD_DEFINITIONS("-DPREFIX=\"${CMAKE_INSTALL_PREFIX}\"") +ADD_DEFINITIONS("-DFACTORYFS=\"$ENV{FACTORYFS}\"") +IF( $ENV{ARCH} MATCHES "arm" ) + ADD_DEFINITIONS("-DTARGET") +ENDIF() +ADD_DEFINITIONS("-DSLP_DEBUG") +ADD_DEFINITIONS("-DSLP_PROF") + +ADD_EXECUTABLE(${PROJECT_NAME} ${SRCS}) +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS}) + +INSTALL(TARGETS ${PROJECT_NAME} DESTINATION bin) diff --git a/src/restarter/restart.c b/src/restarter/restart.c new file mode 100644 index 0000000..550f469 --- /dev/null +++ b/src/restarter/restart.c @@ -0,0 +1,34 @@ +/* + * system-server + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: DongGi Jang + * + * 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 + +int main(int argc, char *argv[]) +{ + launch_evenif_exist("/etc/rc.d/rc.shutdown", "&"); + sleep(1); + sync(); + reboot(RB_AUTOBOOT); + return 0; +} diff --git a/src/shared/CMakeLists.txt b/src/shared/CMakeLists.txt new file mode 100755 index 0000000..e687346 --- /dev/null +++ b/src/shared/CMakeLists.txt @@ -0,0 +1,7 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) + +SET(SHARED_SRCS + dbus.c +) +ADD_LIBRARY(shared STATIC ${SHARED_SRCS}) +SET_TARGET_PROPERTIES(shared PROPERTIES COMPILE_FLAGS "-fPIC") diff --git a/src/shared/common.h b/src/shared/common.h new file mode 100644 index 0000000..5a3ef23 --- /dev/null +++ b/src/shared/common.h @@ -0,0 +1,49 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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. + */ + +#ifndef __DD_COMMON_H__ +#define __DD_COMMON_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef API +#define API __attribute__ ((visibility("default"))) +#endif + +#ifndef DEPRECATED +#define DEPRECATED __attribute__ ((deprecated)) +#endif + +#ifndef __CONSTRUCTOR__ +#define __CONSTRUCTOR__ __attribute__ ((constructor)) +#endif + +#ifndef __DESTRUCTOR__ +#define __DESTRUCTOR__ __attribute__ ((destructor)) +#endif + +#ifdef __cplusplus + +} +#endif +#endif /* __DD_COMMON_H__ */ diff --git a/src/shared/dbus.c b/src/shared/dbus.c new file mode 100644 index 0000000..23bedad --- /dev/null +++ b/src/shared/dbus.c @@ -0,0 +1,345 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 "common.h" +#include "log.h" +#include "dbus.h" + +/* -1 is a default timeout value, it's converted to 25*1000 internally. */ +#define DBUS_REPLY_TIMEOUT (-1) + +struct pending_call_data { + dbus_pending_cb func; + void *data; +}; + +int append_variant(DBusMessageIter *iter, const char *sig, char *param[]) +{ + char *ch; + int i; + int int_type; + uint64_t int64_type; + DBusMessageIter arr; + struct dbus_byte *byte; + + if (!sig || !param) + return 0; + + for (ch = (char*)sig, i = 0; *ch != '\0'; ++i, ++ch) { + switch (*ch) { + case 'i': + int_type = atoi(param[i]); + dbus_message_iter_append_basic(iter, DBUS_TYPE_INT32, &int_type); + break; + case 'u': + int_type = strtoul(param[i], NULL, 10); + dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &int_type); + break; + case 't': + int64_type = atoll(param[i]); + dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT64, &int64_type); + break; + case 's': + dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, ¶m[i]); + break; + case 'a': + ++i, ++ch; + switch (*ch) { + case 'y': + dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE_AS_STRING, &arr); + byte = (struct dbus_byte*)param[i]; + dbus_message_iter_append_fixed_array(&arr, DBUS_TYPE_BYTE, &(byte->data), byte->size); + dbus_message_iter_close_container(iter, &arr); + break; + default: + break; + } + break; + default: + return -EINVAL; + } + } + + return 0; +} + +DBusMessage *dbus_method_sync_with_reply(const char *dest, const char *path, + const char *interface, const char *method, + const char *sig, char *param[]) +{ + DBusConnection *conn; + DBusMessage *msg; + DBusMessageIter iter; + DBusMessage *reply; + DBusError err; + int r; + + conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL); + if (!conn) { + _E("dbus_bus_get error"); + return NULL; + } + + msg = dbus_message_new_method_call(dest, path, interface, method); + if (!msg) { + _E("dbus_message_new_method_call(%s:%s-%s)", + path, interface, method); + return NULL; + } + + dbus_message_iter_init_append(msg, &iter); + r = append_variant(&iter, sig, param); + if (r < 0) { + _E("append_variant error(%d) %s %s:%s-%s", + r, dest, path, interface, method); + dbus_message_unref(msg); + return NULL; + } + + dbus_error_init(&err); + + reply = dbus_connection_send_with_reply_and_block(conn, msg, DBUS_REPLY_TIMEOUT, &err); + if (!reply) { + _E("dbus_connection_send error(No reply) %s %s:%s-%s", + dest, path, interface, method); + } + + if (dbus_error_is_set(&err)) { + _E("dbus_connection_send error(%s:%s) %s %s:%s-%s", + err.name, err.message, dest, path, interface, method); + dbus_error_free(&err); + reply = NULL; + } + + dbus_message_unref(msg); + return reply; +} + +int dbus_method_sync(const char *dest, const char *path, + const char *interface, const char *method, + const char *sig, char *param[]) +{ + DBusConnection *conn; + DBusMessage *msg; + DBusMessageIter iter; + DBusMessage *reply; + DBusError err; + int ret, result; + + conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL); + if (!conn) { + _E("dbus_bus_get error"); + return -EPERM; + } + + msg = dbus_message_new_method_call(dest, path, interface, method); + if (!msg) { + _E("dbus_message_new_method_call(%s:%s-%s)", + path, interface, method); + return -EBADMSG; + } + + dbus_message_iter_init_append(msg, &iter); + ret = append_variant(&iter, sig, param); + if (ret < 0) { + _E("append_variant error(%d) %s %s:%s-%s", + ret, dest, path, interface, method); + dbus_message_unref(msg); + return ret; + } + + dbus_error_init(&err); + + reply = dbus_connection_send_with_reply_and_block(conn, msg, DBUS_REPLY_TIMEOUT, &err); + dbus_message_unref(msg); + if (!reply) { + _E("dbus_connection_send error(%s:%s) %s %s:%s-%s", + err.name, err.message, dest, path, interface, method); + dbus_error_free(&err); + return -ECOMM; + } + + ret = dbus_message_get_args(reply, &err, DBUS_TYPE_INT32, &result, DBUS_TYPE_INVALID); + dbus_message_unref(reply); + if (!ret) { + _E("no message : [%s:%s] %s %s:%s-%s", + err.name, err.message, dest, path, interface, method); + dbus_error_free(&err); + return -ENOMSG; + } + + return result; +} + +int dbus_method_async(const char *dest, const char *path, + const char *interface, const char *method, + const char *sig, char *param[]) +{ + DBusConnection *conn; + DBusMessage *msg; + DBusMessageIter iter; + int ret; + + conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL); + if (!conn) { + _E("dbus_bus_get error"); + return -EPERM; + } + + msg = dbus_message_new_method_call(dest, path, interface, method); + if (!msg) { + _E("dbus_message_new_method_call(%s:%s-%s)", + path, interface, method); + return -EBADMSG; + } + + dbus_message_iter_init_append(msg, &iter); + ret = append_variant(&iter, sig, param); + if (ret < 0) { + _E("append_variant error(%d) %s %s:%s-%s", + ret, dest, path, interface, method); + dbus_message_unref(msg); + return ret; + } + + ret = dbus_connection_send(conn, msg, NULL); + dbus_message_unref(msg); + if (ret != TRUE) { + _E("dbus_connection_send error(%s %s:%s-%s)", + dest, path, interface, method); + return -ECOMM; + } + + return 0; +} + +static void cb_pending(DBusPendingCall *pending, void *user_data) +{ + DBusMessage *msg; + DBusError err; + struct pending_call_data *data = user_data; + int ret; + + ret = dbus_pending_call_get_completed(pending); + if (!ret) { + _I("dbus_pending_call_get_completed() fail"); + dbus_pending_call_unref(pending); + return; + } + + dbus_error_init(&err); + msg = dbus_pending_call_steal_reply(pending); + if (!msg) { + _E("no message : [%s:%s]", err.name, err.message); + + if (data->func) { + dbus_set_error(&err, "org.tizen.system.deviced.NoReply", + "There was no reply to this method call"); + data->func(data->data, NULL, &err); + dbus_error_free(&err); + } + return; + } + + ret = dbus_set_error_from_message(&err, msg); + if (ret) { + _E("error msg : [%s:%s]", err.name, err.message); + + if (data->func) + data->func(data->data, NULL, &err); + dbus_error_free(&err); + } else { + if (data->func) + data->func(data->data, msg, &err); + } + + dbus_message_unref(msg); + dbus_pending_call_unref(pending); +} + +int dbus_method_async_with_reply(const char *dest, const char *path, + const char *interface, const char *method, + const char *sig, char *param[], dbus_pending_cb cb, int timeout, void *data) +{ + DBusConnection *conn; + DBusMessage *msg; + DBusMessageIter iter; + DBusPendingCall *pending = NULL; + struct pending_call_data *pdata; + int ret; + + conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL); + if (!conn) { + _E("dbus_bus_get error"); + return -EPERM; + } + + msg = dbus_message_new_method_call(dest, path, interface, method); + if (!msg) { + _E("dbus_message_new_method_call(%s:%s-%s)", + path, interface, method); + return -EBADMSG; + } + + dbus_message_iter_init_append(msg, &iter); + ret = append_variant(&iter, sig, param); + if (ret < 0) { + _E("append_variant error(%d)%s %s:%s-%s", + ret, dest, path, interface, method); + dbus_message_unref(msg); + return ret; + } + + ret = dbus_connection_send_with_reply(conn, msg, &pending, timeout); + if (!ret) { + dbus_message_unref(msg); + _E("dbus_connection_send error(%s %s:%s-%s)", + dest, path, interface, method); + return -ECOMM; + } + + if (cb && pending) { + pdata = malloc(sizeof(struct pending_call_data)); + if (!pdata) + return -ENOMEM; + + pdata->func = cb; + pdata->data = data; + + ret = dbus_pending_call_set_notify(pending, cb_pending, pdata, free); + if (!ret) { + free(pdata); + dbus_message_unref(msg); + dbus_pending_call_cancel(pending); + return -ECOMM; + } + } + + return 0; +} + +static void __CONSTRUCTOR__ dbus_init(void) +{ + dbus_threads_init_default(); +} diff --git a/src/shared/dbus.h b/src/shared/dbus.h new file mode 100644 index 0000000..1aa4bc9 --- /dev/null +++ b/src/shared/dbus.h @@ -0,0 +1,221 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 __DBUS_H__ +#define __DBUS_H__ + +#include + +/* + * Template + * +#define XXX_BUS_NAME "org.tizen.system.XXX" +#define XXX_OBJECT_PATH "/Org/Tizen/System/XXX" +#define XXX_INTERFACE_NAME XXX_BUS_NAME +#define XXX_PATH_YYY XXX_OBJECT_PATH"/YYY" +#define XXX_INTERFACE_YYY XXX_INTERFACE_NAME".YYY" +#define XXX_SIGNAL_ZZZ "ZZZ" +#define XXX_METHOD_ZZZ "ZZZ" + */ + +/* + * Device daemon + */ +#define DEVICED_BUS_NAME "org.tizen.system.deviced" +#define DEVICED_OBJECT_PATH "/Org/Tizen/System/DeviceD" +#define DEVICED_INTERFACE_NAME DEVICED_BUS_NAME +/* Core service: get/set device status operations about device */ +#define DEVICED_PATH_CORE DEVICED_OBJECT_PATH"/Core" +#define DEVICED_INTERFACE_CORE DEVICED_INTERFACE_NAME".core" +/* Display service: start/stop display(pm), get/set brightness operations about display */ +#define DEVICED_PATH_DISPLAY DEVICED_OBJECT_PATH"/Display" +#define DEVICED_INTERFACE_DISPLAY DEVICED_INTERFACE_NAME".display" +/* Pass service: start/stop pass operations about pass */ +#define DEVICED_PATH_PASS DEVICED_OBJECT_PATH"/Pass" +#define DEVICED_INTERFACE_PASS DEVICED_INTERFACE_NAME".pass" +/* Hall service: get hall status operations about hall */ +#define DEVICED_PATH_HALL DEVICED_OBJECT_PATH"/Hall" +#define DEVICED_INTERFACE_HALL DEVICED_INTERFACE_NAME".hall" +/* Power service: set resetkey disable operations about power */ +#define DEVICED_PATH_POWER DEVICED_OBJECT_PATH"/Power" +#define DEVICED_INTERFACE_POWER DEVICED_INTERFACE_NAME".power" +/* Storage service: get storage size operatioins about storage */ +#define DEVICED_PATH_STORAGE DEVICED_OBJECT_PATH"/Storage" +#define DEVICED_INTERFACE_STORAGE DEVICED_INTERFACE_NAME".storage" +/* ODE service: request ode popup result operatioins about storage */ +#define DEVICED_PATH_ODE DEVICED_OBJECT_PATH"/Ode" +#define DEVICED_INTERFACE_ODE DEVICED_INTERFACE_NAME".ode" +/* Haptic service: operatioins about haptic */ +#define DEVICED_PATH_HAPTIC DEVICED_OBJECT_PATH"/Haptic" +#define DEVICED_INTERFACE_HAPTIC DEVICED_INTERFACE_NAME".haptic" +/* Lowmem service: get critical low status operations about Lowmem */ +#define DEVICED_PATH_LOWMEM DEVICED_OBJECT_PATH"/Lowmem" +#define DEVICED_INTERFACE_LOWMEM DEVICED_INTERFACE_NAME".lowmem" +/* Poweroff service: get power off status operations about Poweroff */ +#define DEVICED_PATH_POWEROFF DEVICED_OBJECT_PATH"/PowerOff" +#define DEVICED_INTERFACE_POWEROFF DEVICED_INTERFACE_NAME".PowerOff" +/* Led service: play/stop led operations about led */ +#define DEVICED_PATH_LED DEVICED_OBJECT_PATH"/Led" +#define DEVICED_INTERFACE_LED DEVICED_INTERFACE_NAME".Led" +/* MMC service: mount/unmount/format mmc operations about mmc */ +#define DEVICED_PATH_MMC DEVICED_OBJECT_PATH"/Mmc" +#define DEVICED_INTERFACE_MMC DEVICED_INTERFACE_NAME".Mmc" +/* Process service: operations about process */ +#define DEVICED_PATH_PROCESS DEVICED_OBJECT_PATH"/Process" +#define DEVICED_INTERFACE_PROCESS DEVICED_INTERFACE_NAME".Process" +/* Key service: operations about key */ +#define DEVICED_PATH_KEY DEVICED_OBJECT_PATH"/Key" +#define DEVICED_INTERFACE_KEY DEVICED_INTERFACE_NAME".Key" +/* USB client service: change usb connection mode */ +#define DEVICED_PATH_USB DEVICED_OBJECT_PATH"/Usb" +#define DEVICED_INTERFACE_USB DEVICED_INTERFACE_NAME".Usb" +/* USB start/stop service: operations about usb start/stop */ +#define DEVICED_PATH_USB_CONTROL DEVICED_OBJECT_PATH"/UsbControl" +#define DEVICED_INTERFACE_USB_CONTROL DEVICED_INTERFACE_NAME".UsbControl" +/* USB host service: operations about usb start/stop */ +#define DEVICED_PATH_USBHOST DEVICED_OBJECT_PATH"/Usbhost" +#define DEVICED_INTERFACE_USBHOST DEVICED_INTERFACE_NAME".Usbhost" +/* Cpu service: operations about cpu */ +#define DEVICED_PATH_CPU DEVICED_OBJECT_PATH"/Cpu" +#define DEVICED_INTERFACE_CPU DEVICED_INTERFACE_NAME".Cpu" +/* PmQos service: operations about pmqos */ +#define DEVICED_PATH_PMQOS DEVICED_OBJECT_PATH"/PmQos" +#define DEVICED_INTERFACE_PMQOS DEVICED_INTERFACE_NAME".PmQos" +/* Sysnoti service */ +#define DEVICED_PATH_SYSNOTI DEVICED_OBJECT_PATH"/SysNoti" +#define DEVICED_INTERFACE_SYSNOTI DEVICED_INTERFACE_NAME".SysNoti" +/* ExtCon service */ +#define DEVICED_PATH_EXTCON DEVICED_OBJECT_PATH"/ExtCon" +#define DEVICED_INTERFACE_EXTCON DEVICED_INTERFACE_NAME".ExtCon" +/* Battery service */ +#define DEVICED_PATH_BATTERY DEVICED_OBJECT_PATH"/Battery" +#define DEVICED_INTERFACE_BATTERY DEVICED_INTERFACE_NAME".Battery" +/* Time service */ +#define DEVICED_PATH_TIME DEVICED_OBJECT_PATH"/Time" +#define DEVICED_INTERFACE_TIME DEVICED_INTERFACE_NAME".Time" +/* Board service */ +#define DEVICED_PATH_BOARD DEVICED_OBJECT_PATH"/Board" +#define DEVICED_INTERFACE_BOARD DEVICED_INTERFACE_NAME".Board" +/* Testmode service */ +#define DEVICED_PATH_TESTMODE DEVICED_OBJECT_PATH"/Testmode" +#define DEVICED_INTERFACE_TESTMODE DEVICED_INTERFACE_NAME".Testmode" + +/* + * Resource daemon + */ +#define RESOURCED_BUS_NAME "org.tizen.resourced" +#define RESOURCED_OBJECT_PATH "/Org/Tizen/ResourceD" +#define RESOURCED_INTERFACE_NAME RESOURCED_BUS_NAME + +#define RESOURCED_PATH_PROCESS RESOURCED_OBJECT_PATH"/Process" +#define RESOURCED_INTERFACE_PROCESS RESOURCED_INTERFACE_NAME".process" +#define RESOURCED_METHOD_ACTIVE "Active" + +/* + * Popup launcher + */ +#define POPUP_BUS_NAME "org.tizen.system.popup" +#define POPUP_OBJECT_PATH "/Org/Tizen/System/Popup" +#define POPUP_INTERFACE_NAME POPUP_BUS_NAME +/* LED */ +#define POPUP_PATH_LED POPUP_OBJECT_PATH"/Led" +#define POPUP_INTERFACE_LED POPUP_INTERFACE_NAME".Led" +/* TICKER */ +#define POPUP_PATH_TICKER POPUP_OBJECT_PATH"/Ticker" +#define POPUP_INTERFACE_TICKER POPUP_INTERFACE_NAME".Ticker" +/* Power off */ +#define POPUP_PATH_POWEROFF POPUP_OBJECT_PATH"/Poweroff" +#define POPUP_INTERFACE_POWEROFF POPUP_INTERFACE_NAME".Poweroff" +/* Low battery */ +#define POPUP_PATH_LOWBAT POPUP_OBJECT_PATH"/Lowbat" +#define POPUP_INTERFACE_LOWBAT POPUP_INTERFACE_NAME".Lowbat" +/* Low memory */ +#define POPUP_PATH_LOWMEM POPUP_OBJECT_PATH"/Lowmem" +#define POPUP_INTERFACE_LOWMEM POPUP_INTERFACE_NAME".Lowmem" +/* MMC */ +#define POPUP_PATH_MMC POPUP_OBJECT_PATH"/Mmc" +#define POPUP_INTERFACE_MMC POPUP_INTERFACE_NAME".Mmc" +/* USB */ +#define POPUP_PATH_USB POPUP_OBJECT_PATH"/Usb" +#define POPUP_INTERFACE_USB POPUP_INTERFACE_NAME".Usb" +/* USB otg */ +#define POPUP_PATH_USBOTG POPUP_OBJECT_PATH"/Usbotg" +#define POPUP_INTERFACE_USBOTG POPUP_INTERFACE_NAME".Usbotg" +/* USB host */ +#define POPUP_PATH_USBHOST POPUP_OBJECT_PATH"/Usbhost" +#define POPUP_INTERFACE_USBHOST POPUP_INTERFACE_NAME".Usbhost" +/* System */ +#define POPUP_PATH_SYSTEM POPUP_OBJECT_PATH"/System" +#define POPUP_INTERFACE_SYSTEM POPUP_INTERFACE_NAME".System" +/* Crash */ +#define POPUP_PATH_CRASH POPUP_OBJECT_PATH"/Crash" +#define POPUP_INTERFACE_CRASH POPUP_INTERFACE_NAME".Crash" +/* ODE */ +#define POPUP_PATH_ODE POPUP_OBJECT_PATH"/Ode" +#define POPUP_INTERFACE_ODE POPUP_INTERFACE_NAME".Ode" +/* Battery */ +#define POPUP_PATH_BATTERY POPUP_OBJECT_PATH"/Battery" +#define POPUP_INTERFACE_BATTERY POPUP_INTERFACE_NAME".Battery" +/* Servant */ +#define POPUP_PATH_SERVANT POPUP_OBJECT_PATH"/Servant" +#define POPUP_IFACE_SERVANT POPUP_INTERFACE_NAME".Servant" + +#define POPUP_PATH_APP POPUP_OBJECT_PATH"/Apps" +#define POPUP_IFACE_APP POPUP_BUS_NAME".Apps" + +#define POPUP_METHOD_LAUNCH "PopupLaunch" +#define POPUP_METHOD_TERMINATE "AppTerminateByPid" +#define POPUP_KEY_CONTENT "_SYSPOPUP_CONTENT_" +#define POPUP_METHOD_SCREENOFF_TTS "ScreenOffTts" + +/* + * Crash daemon + */ +#define CRASHD_BUS_NAME "org.tizen.system.crashd" +#define CRASHD_OBJECT_PATH "/Org/Tizen/System/CrashD" +#define CRASHD_INTERFACE_NAME CRASHD_BUS_NAME + +#define CRASHD_PATH_CRASH CRASHD_OBJECT_PATH"/Crash" +#define CRASHD_INTERFACE_CRASH CRASHD_INTERFACE_NAME".Crash" + +struct dbus_byte { + const char *data; + int size; +}; + +int append_variant(DBusMessageIter *iter, const char *sig, char *param[]); + +DBusMessage *dbus_method_sync_with_reply(const char *dest, const char *path, + const char *interface, const char *method, + const char *sig, char *param[]); + +int dbus_method_sync(const char *dest, const char *path, + const char *interface, const char *method, + const char *sig, char *param[]); + +int dbus_method_async(const char *dest, const char *path, + const char *interface, const char *method, + const char *sig, char *param[]); + +typedef void (*dbus_pending_cb)(void *data, DBusMessage *msg, DBusError *err); + +int dbus_method_async_with_reply(const char *dest, const char *path, + const char *interface, const char *method, + const char *sig, char *param[], dbus_pending_cb cb, int timeout, void *data); +#endif diff --git a/src/shared/deviced-internal.h b/src/shared/deviced-internal.h new file mode 100644 index 0000000..b26d67e --- /dev/null +++ b/src/shared/deviced-internal.h @@ -0,0 +1,38 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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_INTERNAL___ +#define ___DEVICED_INTERNAL___ +#include +#include "dd-deviced.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* This file will be removed */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif +#endif /* ___DEVICED_INTERNAL___ */ diff --git a/src/shared/deviced-priv.h b/src/shared/deviced-priv.h new file mode 100644 index 0000000..0adb00f --- /dev/null +++ b/src/shared/deviced-priv.h @@ -0,0 +1,47 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 __SYSTEM_PRIVATE__ +#define __SYSTEM_PRIVATE__ + +#include "common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define SYSTEM_NOTI_MAXARG 16 +#define SYSTEM_NOTI_MAXSTR 255 +#define BUFF_MAX 255 + +struct sysnoti { + int pid; + int cmd; + char *type; + char *path; + int argc; + char *argv[SYSTEM_NOTI_MAXARG]; +}; + + int util_launch_app_cmd(const char *cmdline); + +#ifdef __cplusplus +} +#endif +#endif /* __SYSTEM_PRIVATE__ */ diff --git a/src/shared/list.h b/src/shared/list.h new file mode 100644 index 0000000..b05e35f --- /dev/null +++ b/src/shared/list.h @@ -0,0 +1,50 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 __LIST_H__ +#define __LIST_H__ + +#include + +#define LIST_ADD(head, data) \ + do { \ + head = g_list_append(head, data); \ + } while(0) + +#define LIST_DEL(head, data) \ + do { \ + head = g_list_remove(head, data); \ + } while(0) + +#define LIST_FIND(head, node, t, name, data) \ + do { \ + t *tmp; \ + GList *elem; \ + for (elem = head; elem; elem = elem->next) { \ + tmp = elem->data; \ + if (tmp->##name != data) \ + continue; \ + node = tmp; \ + } \ + } while(0) + +#define LIST_FOREACH(head, item) \ + for (item = head; item; item = item->next) + +#endif diff --git a/src/shared/log-macro.h b/src/shared/log-macro.h new file mode 100644 index 0000000..407995e --- /dev/null +++ b/src/shared/log-macro.h @@ -0,0 +1,51 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 __LOG_MACRO_H__ +#define __LOG_MACRO_H__ + +#ifdef ENABLE_DLOG +#include +#define _D(fmt, arg...) \ + do { SLOGD(fmt, ##arg); } while(0) +#define _I(fmt, arg...) \ + do { SLOGI(fmt, ##arg); } while(0) +#define _W(fmt, arg...) \ + do { SLOGW(fmt, ##arg); } while(0) +#define _E(fmt, arg...) \ + do { SLOGE(fmt, ##arg); } while(0) +#define _SD(fmt, arg...) \ + do { SECURE_SLOGD(fmt, ##arg); } while(0) +#define _SI(fmt, arg...) \ + do { SECURE_SLOGI(fmt, ##arg); } while(0) +#define _SW(fmt, arg...) \ + do { SECURE_SLOGW(fmt, ##arg); } while(0) +#define _SE(fmt, arg...) \ + do { SECURE_SLOGE(fmt, ##arg); } while(0) +#else +#define _D(...) do { } while (0) +#define _I(...) do { } while (0) +#define _W(...) do { } while (0) +#define _E(...) do { } while (0) +#define _SD(...) do { } while (0) +#define _SI(...) do { } while (0) +#define _SW(...) do { } while (0) +#define _SE(...) do { } while (0) +#endif +#endif diff --git a/src/shared/log.h b/src/shared/log.h new file mode 100644 index 0000000..29b6c85 --- /dev/null +++ b/src/shared/log.h @@ -0,0 +1,30 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 __LOG_H__ +#define __LOG_H__ + +#ifdef ENABLE_LIBDEVICED_DLOG +#define ENABLE_DLOG +#endif + +#define LOG_TAG "DEVICED" +#include "shared/log-macro.h" + +#endif diff --git a/src/shared/score-defines.h b/src/shared/score-defines.h new file mode 100644 index 0000000..44638e7 --- /dev/null +++ b/src/shared/score-defines.h @@ -0,0 +1,31 @@ +/* + * deviced + * + * Copyright (c) 2000 - 2011 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. + */ + + +#ifndef __OOM_H__ +#define __OOM_H__ + +#define OOMADJ_SU (0) +#define OOMADJ_INIT (100) +#define OOMADJ_FOREGRD_LOCKED (150) +#define OOMADJ_FOREGRD_UNLOCKED (200) +#define OOMADJ_BACKGRD_LOCKED (250) +#define OOMADJ_BACKGRD_UNLOCKED (300) +#define OOMADJ_APP_LIMIT OOMADJ_INIT + +#endif /* __OOM_H__ */ diff --git a/src/ta/ta-handler.c b/src/ta/ta-handler.c new file mode 100644 index 0000000..e67c9ea --- /dev/null +++ b/src/ta/ta-handler.c @@ -0,0 +1,78 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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/data.h" +#include "core/devices.h" +#include "display/poll.h" +#include "core/common.h" + +#define RETRY 3 + +enum ta_connect_status{ + TA_OFFLINE = 0, + TA_ONLINE = 1, +}; + +static int __check_insuspend_charging(void) +{ + int val, ret; + + ret = device_get_property(DEVICE_TYPE_POWER, PROP_POWER_INSUSPEND_CHARGING_SUPPORT, &val); + if (ret != 0) + val = 0; + if (val == 0) + ret = pm_lock_internal(INTERNAL_LOCK_TA, LCD_OFF, STAY_CUR_STATE, 0); + else + ret = 0; + return ret; +} + +static void ta_init(void *data) +{ + int val, i = 0; + int ret; + + if (device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_TA_ONLINE, &val) != 0) + val = -EINVAL; + + if (val == TA_ONLINE) { + vconf_set_int(VCONFKEY_SYSMAN_CHARGER_STATUS, + VCONFKEY_SYSMAN_CHARGER_CONNECTED); + while (i < RETRY + && __check_insuspend_charging() == -1) { + i++; + sleep(1); + } + } else if (val == TA_OFFLINE) { + vconf_set_int(VCONFKEY_SYSMAN_CHARGER_STATUS, + VCONFKEY_SYSMAN_CHARGER_DISCONNECTED); + } +} + +static const struct device_ops ta_device_ops = { + .priority = DEVICE_PRIORITY_NORMAL, + .name = "ta", + .init = ta_init, +}; + +DEVICE_OPS_REGISTER(&ta_device_ops) diff --git a/src/telephony/telephony.c b/src/telephony/telephony.c new file mode 100644 index 0000000..cd28f7e --- /dev/null +++ b/src/telephony/telephony.c @@ -0,0 +1,421 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include "dd-deviced.h" +#include "core/log.h" +#include "core/queue.h" +#include "core/predefine.h" +#include "core/data.h" +#include "core/common.h" +#include "core/devices.h" +#include "core/edbus-handler.h" +#include "display/core.h" +#include "power/power-handler.h" + +#define PREDEF_FLIGHT_MODE "flightmode" +#define PREDEF_ENTERSLEEP "entersleep" +#define PREDEF_LEAVESLEEP "leavesleep" + +#define POWER_RESTART 5 + +static TapiHandle *tapi_handle = NULL; +static Ecore_Timer *poweroff_timer_id = NULL; +static int reboot_opt; + +static Eina_Bool telephony_powerdown_ap_internal(void *data) +{ + powerdown_ap(data); + return EINA_FALSE; +} +static void telephony_powerdown_ap(TapiHandle *handle, const char *noti_id, void *data, void *user_data) +{ + telephony_powerdown_ap_internal(data); +} + +static void telephony_restart_ap(TapiHandle *handle, const char *noti_id, void *data, void *user_data) +{ + restart_ap((void *)reboot_opt); +} + +static Eina_Bool telephony_restart_ap_by_force(void *data) +{ + if (poweroff_timer_id) { + ecore_timer_del(poweroff_timer_id); + poweroff_timer_id = NULL; + } + restart_ap(data); + return EINA_TRUE; +} + +static void powerdown_res_cb(TapiHandle *handle, int result, void *data, void *user_data) +{ + _D("poweroff command request : %d",result); +} + +static Eina_Bool telephony_powerdown_ap_by_force(void *data) +{ + if (poweroff_timer_id) { + ecore_timer_del(poweroff_timer_id); + poweroff_timer_id = NULL; + } + powerdown_ap(data); + return EINA_TRUE; +} + +static int telephony_start(void) +{ + int ready = 0; + + if (tapi_handle) { + _I("already initialized"); + return 0; + } + if (vconf_get_bool(VCONFKEY_TELEPHONY_READY,&ready) != 0 || ready != 1) { + _E("fail to get %s(%d)", VCONFKEY_TELEPHONY_READY, ready); + return -EINVAL; + } + tapi_handle = tel_init(NULL); + if (tapi_handle == NULL) { + _E("tapi init error"); + return -EINVAL; + } + return 0; +} + +static int telephony_stop(void) +{ + int ret; + tel_deregister_noti_event(tapi_handle, TAPI_NOTI_MODEM_POWER); + ret = tel_deinit(tapi_handle); + if (ret != 0) { + _E("fail to deinit"); + return -EINVAL; + } + tapi_handle = NULL; + return 0; +} + +static void telephony_exit(void *data) +{ + int ret; + + if (!data) { + _E("Option Failed"); + return; + } + + if (!strncmp(data, PREDEF_POWEROFF, strlen(PREDEF_POWEROFF))) { + _I("Terminate"); + ret = tel_register_noti_event(tapi_handle, TAPI_NOTI_MODEM_POWER, + telephony_powerdown_ap, NULL); + if (ret != TAPI_API_SUCCESS) { + _E("tel_register_event is not subscribed. error %d", ret); + telephony_powerdown_ap_by_force(NULL); + return; + } + ret = tel_process_power_command(tapi_handle, TAPI_PHONE_POWER_OFF, + powerdown_res_cb, NULL); + if (ret != TAPI_API_SUCCESS) { + _E("tel_process_power_command() error %d\n", ret); + telephony_powerdown_ap_by_force(NULL); + return; + } + poweroff_timer_id = ecore_timer_add(15, + telephony_powerdown_ap_internal, NULL); + return; + } + + if (strncmp(data, PREDEF_REBOOT, strlen(PREDEF_REBOOT)) && + strncmp(data, PREDEF_RECOVERY, strlen(PREDEF_RECOVERY)) && + strncmp(data, PREDEF_FOTA_REBOOT, strlen(PREDEF_FOTA_REBOOT))) { + _E("Fail %s", data); + return; + } + + _I("Option: %s", data); + if (!strncmp(data, PREDEF_RECOVERY, strlen(PREDEF_RECOVERY))) + reboot_opt = SYSTEMD_STOP_POWER_RESTART_RECOVERY; + else if (!strncmp(data, PREDEF_REBOOT, strlen(PREDEF_REBOOT))) + reboot_opt = SYSTEMD_STOP_POWER_RESTART; + else if (!strncmp(data, PREDEF_FOTA_REBOOT, strlen(PREDEF_FOTA_REBOOT))) + reboot_opt = SYSTEMD_STOP_POWER_RESTART_FOTA; + + ret = tel_register_noti_event(tapi_handle, TAPI_NOTI_MODEM_POWER, + telephony_restart_ap, NULL); + if (ret != TAPI_API_SUCCESS) { + _E("tel_register_event is not subscribed. error %d", ret); + telephony_restart_ap_by_force((void *)POWER_RESTART); + return; + } + ret = tel_process_power_command(tapi_handle, TAPI_PHONE_POWER_OFF, + powerdown_res_cb, NULL); + if (ret != TAPI_API_SUCCESS) { + _E("tel_process_power_command() error %d", ret); + telephony_restart_ap_by_force((void *)reboot_opt); + return; + } + poweroff_timer_id = ecore_timer_add(15,telephony_restart_ap_by_force, + (void *)reboot_opt); +} + +static void telephony_flight_mode_on(TapiHandle *handle, int result, void *data, void *user_data) +{ + int ret; + int bCurFlightMode = 0; + + if (result != TAPI_POWER_FLIGHT_MODE_ENTER) { + _E("flight mode enter failed %d", result); + return; + } + _D("enter flight mode result : %d", result); + ret = vconf_get_bool(VCONFKEY_TELEPHONY_FLIGHT_MODE, &bCurFlightMode); + if (ret == 0) + _D("Flight Mode is %d", bCurFlightMode); + else + _E("failed to get vconf key"); +} + +static void telephony_flight_mode_off(TapiHandle *handle, int result, void *data, void *user_data) +{ + int ret; + int bCurFlightMode = 0; + + if (result != TAPI_POWER_FLIGHT_MODE_LEAVE) { + _E("flight mode leave failed %d", result); + return; + } + _D("leave flight mode result : %d", result); + ret = vconf_get_bool(VCONFKEY_TELEPHONY_FLIGHT_MODE, &bCurFlightMode); + if (ret == 0) + _D("Flight Mode is %d", bCurFlightMode); + else + _E("failed to get vconf key"); +} + +static int telephony_flight_mode(int argc, char **argv) +{ + int ret; + int mode; + int err = TAPI_API_SUCCESS; + + if (argc != 1 || argv[0] == NULL) { + _E("FlightMode Set predefine action failed"); + return -1; + } + mode = atoi(argv[0]); + + if (tapi_handle == NULL) { + ret = telephony_start(); + if (ret != 0) { + _E("fail to get tapi handle"); + return -1; + } + } + + if (mode == 1) { + err = tel_set_flight_mode(tapi_handle, TAPI_POWER_FLIGHT_MODE_LEAVE, + telephony_flight_mode_off, NULL); + } else if (mode == 0) { + err = tel_set_flight_mode(tapi_handle, TAPI_POWER_FLIGHT_MODE_ENTER, + telephony_flight_mode_on, NULL); + } + if (err != TAPI_API_SUCCESS) + _E("FlightMode tel api action failed %d",err); + + return 0; +} + +static int telephony_enter_sleep(int argc, char **argv) +{ + int ret; + + pm_change_internal(getpid(), LCD_NORMAL); + sync(); + + /* flight mode + * TODO - add check, cb, etc... + * should be checked wirh telephony part */ + ret = tel_set_flight_mode(tapi_handle, TAPI_POWER_FLIGHT_MODE_ENTER, + telephony_flight_mode_on, NULL); + _I("request for changing into flight mode : %d", ret); + + launch_evenif_exist("/etc/rc.d/rc.entersleep", ""); + pm_change_internal(getpid(), POWER_OFF); + + return 0; +} + +static int telephony_leave_sleep(int argc, char **argv) +{ + int ret; + + pm_change_internal(getpid(), LCD_NORMAL); + sync(); + + /* flight mode + * TODO - add check, cb, etc... + * should be checked wirh telephony part */ + ret = tel_set_flight_mode(tapi_handle, TAPI_POWER_FLIGHT_MODE_LEAVE, + telephony_flight_mode_off, NULL); + _I("request for changing into flight mode : %d", ret); + + return 0; +} + +static DBusMessage *flight_mode_handler(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusError err; + DBusMessageIter iter; + DBusMessage *reply; + pid_t pid; + int ret; + int argc; + char *type_str; + char *argv; + + dbus_error_init(&err); + + if (!dbus_message_get_args(msg, &err, + DBUS_TYPE_STRING, &type_str, + DBUS_TYPE_INT32, &argc, + DBUS_TYPE_STRING, &argv, DBUS_TYPE_INVALID)) { + _E("there is no message"); + ret = -EINVAL; + goto out; + } + + if (argc < 0) { + _E("message is invalid!"); + ret = -EINVAL; + goto out; + } + + pid = get_edbus_sender_pid(msg); + if (kill(pid, 0) == -1) { + _E("%d process does not exist, dbus ignored!", pid); + ret = -ESRCH; + goto out; + } + + telephony_flight_mode(argc, (char **)&argv); + +out: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + + return reply; +} + +static DBusMessage *telephony_handler(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusError err; + DBusMessageIter iter; + DBusMessage *reply; + pid_t pid; + int ret; + int argc; + char *type_str; + + dbus_error_init(&err); + + if (!dbus_message_get_args(msg, &err, + DBUS_TYPE_STRING, &type_str, + DBUS_TYPE_INT32, &argc, DBUS_TYPE_INVALID)) { + _E("there is no message"); + ret = -EINVAL; + goto out; + } + + if (argc < 0) { + _E("message is invalid!"); + ret = -EINVAL; + goto out; + } + + pid = get_edbus_sender_pid(msg); + if (kill(pid, 0) == -1) { + _E("%d process does not exist, dbus ignored!", pid); + ret = -ESRCH; + goto out; + } + + if (tapi_handle == NULL) { + if (telephony_start() != 0) + _E("fail to get tapi handle"); + } + + if (!strncmp(type_str, PREDEF_ENTERSLEEP, strlen(PREDEF_ENTERSLEEP))) + ret = telephony_enter_sleep(0, NULL); + else if (!strncmp(type_str, PREDEF_LEAVESLEEP, strlen(PREDEF_LEAVESLEEP))) + ret = telephony_leave_sleep(0, NULL); + +out: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + + return reply; +} + +static const struct edbus_method edbus_methods[] = { + { PREDEF_FLIGHT_MODE, "sis", "i", flight_mode_handler }, + { PREDEF_ENTERSLEEP, "si", "i", telephony_handler }, + { PREDEF_LEAVESLEEP, "si", "i", telephony_handler }, + /* Add methods here */ +}; + +static void telephony_init(void *data) +{ + int ret; + + /* init dbus interface */ + ret = register_edbus_method(DEVICED_PATH_POWER, edbus_methods, + ARRAY_SIZE(edbus_methods)); + if (ret < 0) + _E("fail to init edbus method(%d)", ret); + + register_action(PREDEF_FLIGHT_MODE, telephony_flight_mode, NULL, NULL); + register_action(PREDEF_ENTERSLEEP, telephony_enter_sleep, NULL, NULL); + register_action(PREDEF_LEAVESLEEP, telephony_leave_sleep, NULL, NULL); +} + +static const struct device_ops tel_device_ops = { + .priority = DEVICE_PRIORITY_NORMAL, + .name = "telephony", + .init = telephony_init, + .start = telephony_start, + .stop = telephony_stop, + .exit = telephony_exit, +}; + +DEVICE_OPS_REGISTER(&tel_device_ops) diff --git a/src/testmode/testmode.c b/src/testmode/testmode.c new file mode 100644 index 0000000..0c246b9 --- /dev/null +++ b/src/testmode/testmode.c @@ -0,0 +1,87 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 "core/log.h" +#include "core/devices.h" +#include "core/edbus-handler.h" +#include "core/launch.h" + +static DBusMessage *edbus_testmode_launch(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusError err; + DBusMessageIter iter; + DBusMessage *reply; + pid_t pid; + int ret; + int argc; + char *argv; + char param[32]; + + dbus_error_init(&err); + + if (!dbus_message_get_args(msg, &err, + DBUS_TYPE_STRING, &argv, DBUS_TYPE_INVALID)) { + _E("there is no message"); + ret = -EINVAL; + goto out; + } + sprintf(param, "%s", argv); + _D("param %s", param); + + launch_evenif_exist("/usr/bin/testmode-env.sh", param); +out: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + + return reply; +} + +static const struct edbus_method edbus_methods[] = { + { "Launch", "s", "i", edbus_testmode_launch }, + /* Add methods here */ +}; + +/* battery ops init funcion */ +static void testmode_init(void *data) +{ + int ret; + + /* init dbus interface */ + ret = register_edbus_method(DEVICED_PATH_TESTMODE, + edbus_methods, ARRAY_SIZE(edbus_methods)); + if (ret < 0) + _E("fail to init edbus method(%d)", ret); +} + +/* battery ops exit funcion */ +static void testmode_exit(void *data) +{ +} + +static const struct device_ops battery_device_ops = { + .priority = DEVICE_PRIORITY_NORMAL, + .name = "testmode", + .init = testmode_init, + .exit = testmode_exit, +}; + +DEVICE_OPS_REGISTER(&battery_device_ops) diff --git a/src/ticker/ticker.c b/src/ticker/ticker.c new file mode 100755 index 0000000..89bed50 --- /dev/null +++ b/src/ticker/ticker.c @@ -0,0 +1,77 @@ +/* + * deviced + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "core/log.h" +#include "ticker.h" +#include "core/devices.h" +#include "core/edbus-handler.h" + +void show_ticker_noti(char *name) +{ + int ret, ret_val; + char *param[1]; + + if (!name) + return ; + + param[0] = name; + + ret_val = dbus_method_async(POPUP_BUS_NAME, + POPUP_PATH_TICKER, + POPUP_INTERFACE_TICKER, + "TickerNotiOn", "s", param); + return; +} + +void insert_ticker_queue(char *name) +{ + /* TODO: Implement queue for ticker noti */ +} + +static void ticker_init(void *data) +{ + const struct ticker_ops *dev; + struct ticker_data *input; + static int initialized = 0; + + if (!initialized) { + initialized = 1; + return; + } + + input = (struct ticker_data *)data; + if (input == NULL || input->name == NULL) + return; + + if (input->type == WITHOUT_QUEUE) { + _E("without queue"); + show_ticker_noti(input->name); + } else { + _E("with queue"); + insert_ticker_queue(input->name); + } +} + +static const struct device_ops ticker_device_ops = { + .priority = DEVICE_PRIORITY_NORMAL, + .name = "ticker", + .init = ticker_init, +}; + +DEVICE_OPS_REGISTER(&ticker_device_ops) diff --git a/src/ticker/ticker.h b/src/ticker/ticker.h new file mode 100755 index 0000000..3d1b36a --- /dev/null +++ b/src/ticker/ticker.h @@ -0,0 +1,37 @@ +/* + * deviced + * + * Copyright (c) 2012 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 __TICKER_H__ +#define __TICKER_H__ + + +#include "core/common.h" +#include "core/data.h" + +enum ticker_type { + WITHOUT_QUEUE, /* for usb client */ + WITH_QUEUE, /* for other situations */ +}; + +struct ticker_data { + char *name; + int type; +}; + +#endif /* __TICKER_H__ */ + diff --git a/src/time/time-handler.c b/src/time/time-handler.c new file mode 100644 index 0000000..3eb241b --- /dev/null +++ b/src/time/time-handler.c @@ -0,0 +1,382 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "core/data.h" +#include "core/queue.h" +#include "core/log.h" +#include "core/devices.h" +#include "display/poll.h" +#include "display/core.h" +#include "core/edbus-handler.h" +#include "core/common.h" +#include "core/device-notifier.h" + +#define PREDEF_SET_DATETIME "set_datetime" +#define PREDEF_SET_TIMEZONE "set_timezone" + +#ifndef TFD_TIMER_CANCELON_SET +#define TFD_TIMER_CANCELON_SET (1<<1) +#endif +#ifndef O_CLOEXEC +#define O_CLOEXEC 0x2000000 +#endif + +#ifndef O_NONBLOCK +#define O_NONBLOCK 0x4000 +#endif + +#ifndef TFD_CLOEXEC +#define TFD_CLOEXEC O_CLOEXEC +#endif + +#ifndef TFD_NONBLOCK +#define TFD_NONBLOCK O_NONBLOCK +#endif + +#define TIME_CHANGE_SIGNAL "STimeChanged" + +static const char default_rtc0[] = "/dev/rtc0"; +static const char default_rtc1[] = "/dev/rtc1"; +static const char default_localtime[] = "/opt/etc/localtime"; + +static const time_t default_time = 2147483645; // max(32bit) -3sec +static Ecore_Fd_Handler *tfdh = NULL; // tfd change noti + +static Eina_Bool tfd_cb(void *data, Ecore_Fd_Handler * fd_handler); +static int timerfd_check_stop(int fd); +static int timerfd_check_start(void); + +char *substring(const char *str, size_t begin, size_t len) +{ + if (str == 0 || strlen(str) == 0 || strlen(str) < begin + || strlen(str) < (begin + len)) + return 0; + + return strndup(str + begin, len); +} + +int handle_timezone(char *str) +{ + int ret; + struct stat sts; + time_t now; + struct tm *ts; + const char *sympath = default_localtime; + + if (str == NULL) + return -1; + const char *tzpath = str; + + _D("TZPATH = %s", tzpath); + + if (stat(tzpath, &sts) == -1 && errno == ENOENT) { + _E("invalid tzpath(%s)", tzpath); + return -EINVAL; + } + + /* FIXME for debugging purpose */ + time(&now); + ts = localtime(&now); + _D("cur local time is %s", asctime(ts)); + + /* unlink current link + * eg. rm /opt/etc/localtime */ + if (stat(sympath, &sts) == -1 && errno == ENOENT) { + /* DO NOTHING */ + } else { + ret = unlink(sympath); + if (ret < 0) { + _E("unlink error : [%d]%s", ret, + strerror(errno)); + return -1; + } + _D("unlink success"); + } + + /* symlink new link + * eg. ln -s /usr/share/zoneinfo/Asia/Seoul /opt/etc/localtime */ + ret = symlink(tzpath, sympath); + if (ret < 0) { + _E("symlink error : [%d]%s", ret, strerror(errno)); + return -1; + } + _D("symlink success"); + + tzset(); + + /* FIXME for debugging purpose */ + ts = localtime(&now); + _D("new local time is %s", asctime(ts)); + return 0; +} + +/* + * TODO : error handling code should be added here. + */ +int handle_date(char *str) +{ + long int tmp = 0; + time_t timet = 0; + time_t before = 0; + + if (str == NULL) + return -1; + + tmp = (long int)atoi(str); + timet = (time_t) tmp; + + _D("ctime = %s", ctime(&timet)); + vconf_set_int(VCONFKEY_SYSTEM_TIMECHANGE, timet); + + return 0; +} + +int set_datetime_action(int argc, char **argv) +{ + int ret = 0; + unsigned int pm_state; + if (argc < 1) + return -1; + if (vconf_get_int(VCONFKEY_PM_STATE, &ret) != 0) + _E("Fail to get vconf value for pm state\n"); + if (ret == 1) + pm_state = 0x1; + else if (ret == 2) + pm_state = 0x2; + else + pm_state = 0x4; + + pm_lock_internal(INTERNAL_LOCK_TIME, pm_state, STAY_CUR_STATE, 0); + ret = handle_date(argv[0]); + pm_unlock_internal(INTERNAL_LOCK_TIME, pm_state, STAY_CUR_STATE); + return ret; +} + +int set_timezone_action(int argc, char **argv) +{ + int ret; + unsigned int pm_state; + if (argc < 1) + return -1; + if (vconf_get_int(VCONFKEY_PM_STATE, &ret) != 0) + _E("Fail to get vconf value for pm state\n"); + if (ret == 1) + pm_state = 0x1; + else if (ret == 2) + pm_state = 0x2; + else + pm_state = 0x4; + + pm_lock_internal(INTERNAL_LOCK_TIME, pm_state, STAY_CUR_STATE, 0); + ret = handle_timezone(argv[0]); + pm_unlock_internal(INTERNAL_LOCK_TIME, pm_state, STAY_CUR_STATE); + return ret; +} + +static void time_changed_broadcast(void) +{ + broadcast_edbus_signal(DEVICED_PATH_TIME, DEVICED_INTERFACE_TIME, + TIME_CHANGE_SIGNAL, NULL, NULL); +} + +static int timerfd_check_start(void) +{ + int tfd; + struct itimerspec tmr; + + if ((tfd = timerfd_create(CLOCK_REALTIME,TFD_NONBLOCK|TFD_CLOEXEC)) == -1) { + _E("error timerfd_create() %d", errno); + tfdh = NULL; + return -1; + } + + tfdh = ecore_main_fd_handler_add(tfd,ECORE_FD_READ,tfd_cb,NULL,NULL,NULL); + if (!tfdh) { + _E("error ecore_main_fd_handler_add"); + return -1; + } + memset(&tmr, 0, sizeof(tmr)); + tmr.it_value.tv_sec = default_time; + + if (timerfd_settime(tfd,TFD_TIMER_ABSTIME|TFD_TIMER_CANCELON_SET,&tmr,NULL) < 0) { + _E("error timerfd_settime() %d", errno); + return -1; + } + return 0; +} + +static int timerfd_check_stop(int tfd) +{ + if (tfdh) { + ecore_main_fd_handler_del(tfdh); + tfdh = NULL; + } + if (tfd >=0) { + close(tfd); + tfd = -1; + } + return 0; +} + +static Eina_Bool tfd_cb(void *data, Ecore_Fd_Handler * fd_handler) +{ + int tfd = -1; + u_int64_t ticks; + int ret = -1; + + if (!ecore_main_fd_handler_active_get(fd_handler,ECORE_FD_READ)) { + _E("error ecore_main_fd_handler_get()"); + goto out; + } + + if((tfd = ecore_main_fd_handler_fd_get(fd_handler)) == -1) { + _E("error ecore_main_fd_handler_fd_get()"); + goto out; + } + + ret = read(tfd,&ticks,sizeof(ticks)); + if (ret < 0 && errno == ECANCELED) { + vconf_set_int(VCONFKEY_SYSMAN_STIME, VCONFKEY_SYSMAN_STIME_CHANGED); + time_changed_broadcast(); + timerfd_check_stop(tfd); + _D("NOTIFICATION here"); + timerfd_check_start(); + } else { + _E("unexpected read (err:%d)", errno); + } +out: + return EINA_TRUE; +} + +static DBusMessage *dbus_time_handler(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusError err; + DBusMessageIter iter; + DBusMessage *reply; + pid_t pid; + int ret; + int argc; + char *type_str; + char *argv; + + dbus_error_init(&err); + + if (!dbus_message_get_args(msg, &err, + DBUS_TYPE_STRING, &type_str, + DBUS_TYPE_INT32, &argc, + DBUS_TYPE_STRING, &argv, DBUS_TYPE_INVALID)) { + _E("there is no message"); + ret = -EINVAL; + goto out; + } + + if (argc < 0) { + _E("message is invalid!"); + ret = -EINVAL; + goto out; + } + + pid = get_edbus_sender_pid(msg); + if (kill(pid, 0) == -1) { + _E("%d process does not exist, dbus ignored!", pid); + ret = -ESRCH; + goto out; + } + + if (strncmp(type_str, PREDEF_SET_DATETIME, strlen(PREDEF_SET_DATETIME)) == 0) + ret = set_datetime_action(argc, (char **)&argv); + else if (strncmp(type_str, PREDEF_SET_TIMEZONE, strlen(PREDEF_SET_TIMEZONE)) == 0) + ret = set_timezone_action(argc, (char **)&argv); +out: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + + return reply; +} + +static const struct edbus_method edbus_methods[] = { + { PREDEF_SET_DATETIME, "sis", "i", dbus_time_handler }, + { PREDEF_SET_TIMEZONE, "sis", "i", dbus_time_handler }, + +}; + +static int time_lcd_changed_cb(void *data) +{ + int lcd_state = (int)data; + int tfd = -1; + + if (lcd_state < S_LCDOFF) + goto restart; + + lcd_state = check_lcdoff_lock_state(); + if (lcd_state || !tfdh) + goto out; + tfd = ecore_main_fd_handler_fd_get(tfdh); + if (tfd == -1) + goto out; + + _D("stop tfd"); + timerfd_check_stop(tfd); + goto out; +restart: + if (tfdh) + return 0; + _D("restart tfd"); + timerfd_check_start(); +out: + return 0; +} + +static void time_init(void *data) +{ + int ret; + + ret = register_edbus_method(DEVICED_PATH_SYSNOTI, edbus_methods, ARRAY_SIZE(edbus_methods)); + if (ret < 0) + _E("fail to init edbus method(%d)", ret); + + register_action(PREDEF_SET_DATETIME, set_datetime_action, NULL, NULL); + register_action(PREDEF_SET_TIMEZONE, set_timezone_action, NULL, NULL); + if (timerfd_check_start() == -1) { + _E("fail system time change detector init"); + } + register_notifier(DEVICE_NOTIFIER_LCD, time_lcd_changed_cb); +} + +static const struct device_ops time_device_ops = { + .priority = DEVICE_PRIORITY_NORMAL, + .name = "time", + .init = time_init, +}; + +DEVICE_OPS_REGISTER(&time_device_ops) diff --git a/src/touch/touch-controller.c b/src/touch/touch-controller.c new file mode 100644 index 0000000..b9a453d --- /dev/null +++ b/src/touch/touch-controller.c @@ -0,0 +1,135 @@ +/* + * Touch controller + * + * Copyright (c) 2013 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 "touch-controller.h" +#include "core/common.h" + +static struct touch_control *touch_control; + +/****************************************************** + * Touch VCONF interface * + ******************************************************/ +static void touch_vconf_pm_sip_status(keynode_t *key, void* data) +{ + int sip_state; + + if (vconf_get_int(VCONFKEY_ISF_INPUT_PANEL_STATE, &sip_state) != 0) + return; + + switch (sip_state) { + case VCONFKEY_ISF_INPUT_PANEL_STATE_HIDE: + /* If SIP is off state, should turn on touch boost feature */ + touch_boost_enable(touch_control, TOUCH_TYPE_VCONF_SIP, TOUCH_BOOST_ON); + break; + case VCONFKEY_ISF_INPUT_PANEL_STATE_SHOW: + /* If SIP is on state, should turn off touch boost feature */ + touch_boost_enable(touch_control, TOUCH_TYPE_VCONF_SIP, TOUCH_BOOST_OFF); + break; + default: + _E("Unknow SIP type"); + return; + } +} + +static struct touch_vconf_block vconf_block[] = { + { + .vconf = VCONFKEY_ISF_INPUT_PANEL_STATE, + .vconf_function = touch_vconf_pm_sip_status, + }, +}; + +static int touch_vconf_stop(void) +{ + int i; + int ret; + int size; + + if (!touch_control) { + _E("cannot stop touch_vconf"); + return -EINVAL; + } + + /* Unregister callback function of VCONFKEY */ + size = ARRAY_SIZE(vconf_block); + for (i = 0; i < size; i++) { + ret = vconf_ignore_key_changed(vconf_block[i].vconf, + vconf_block[i].vconf_function); + if (ret < 0) + _E("cannot unregister 'vconf function' : %d", + vconf_block[i].vconf); + } + + _I("Stop Touch of VCONF"); + + return 0; +} + +static int touch_vconf_start(void) +{ + int i; + int ret; + int size; + + if (!touch_control) { + _E("cannot start touch_vconf"); + return -EINVAL; + } + + size = ARRAY_SIZE(vconf_block); + + /* Register callback function of VCONFKEY */ + for (i = 0; i < size; i++) { + ret = vconf_notify_key_changed(vconf_block[i].vconf, + vconf_block[i].vconf_function, + (void *)touch_control); + if (ret < 0) + _E("cannot register 'vconf function' : %d", + vconf_block[i].vconf); + } + + _I("Start Touch of VCONF"); + + return 0; +} + +/****************************************************** + * Touch controller interface * + ******************************************************/ +API void touch_controller_start(void) +{ + touch_vconf_start(); + + /* Add to start() of new touch type */ +} + +API void touch_controller_stop(void) +{ + touch_vconf_stop(); + + /* Add to stop() of new touch type */ +} + +API void touch_controller_init(struct touch_control *tc) +{ + touch_control = tc; +} + +API void touch_controller_exit(void) +{ + touch_control = NULL; +} diff --git a/src/touch/touch-controller.h b/src/touch/touch-controller.h new file mode 100644 index 0000000..284d8a2 --- /dev/null +++ b/src/touch/touch-controller.h @@ -0,0 +1,39 @@ +/* + * Touch controller + * + * Copyright (c) 2013 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. + * + */ + +#ifndef __TOUCH_CONTROLLER__ +#define __TOUCH_CONTROLLER__ + +#include "touch.h" +#include "shared/common.h" + +/* + * struct touch_vconf_block + */ +struct touch_vconf_block { + char *vconf; + void (*vconf_function)(keynode_t *key, void* data); +}; + +void touch_controller_init(struct touch_control *); +void touch_controller_exit(void); +void touch_controller_start(void); +void touch_controller_stop(void); + +#endif /* __TOUCH_CONTROLLER__ */ diff --git a/src/touch/touch-plugin.c b/src/touch/touch-plugin.c new file mode 100644 index 0000000..8900e40 --- /dev/null +++ b/src/touch/touch-plugin.c @@ -0,0 +1,113 @@ +/* + * Touch - Support plugin feature for Touch + * + * Copyright (c) 2013 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 +#include + +#include "touch-plugin.h" + +#define TOUCH_BOOST_OFF "/sys/devices/system/cpu/cpu0/cpufreq/touch_boost_off" + +/* + * Helper function + * - Read from sysfs entry + * - Write to sysfs entry + */ +#define BUFF_MAX 255 +static int sys_read_buf(char *file, char *buf) +{ + int fd; + int r; + int ret = 0; + + fd = open(file, O_RDONLY); + if (fd == -1) + return -ENOENT; + + r = read(fd, buf, BUFF_MAX); + if ((r >= 0) && (r < BUFF_MAX)) + buf[r] = '\0'; + else + ret = -EIO; + + close(fd); + + return ret; +} + +static int sys_write_buf(char *file, char *buf) +{ + int fd; + int r; + int ret = 0; + + fd = open(file, O_WRONLY); + if (fd == -1) + return -ENOENT; + + r = write(fd, buf, strlen(buf)); + if (r < 0) + ret = -EIO; + + close(fd); + + return ret; +} + +static int sys_get_int(char *fname, int *val) +{ + char buf[BUFF_MAX]; + int ret = 0; + + if (sys_read_buf(fname, buf) == 0) { + *val = atoi(buf); + } else { + *val = -1; + ret = -EIO; + } + + return ret; +} + +static int sys_set_int(char *fname, int val) +{ + char buf[BUFF_MAX]; + int ret = 0; + + snprintf(buf, sizeof(buf), "%d", val); + + if (sys_write_buf(fname, buf) != 0) + ret = -EIO; + + return ret; +} + +/* + * Get/Set touch_boost_off state + */ +int get_cpufreq_touch_boost_off(int *touch_boost_off) +{ + return sys_get_int(TOUCH_BOOST_OFF, touch_boost_off); +} + +int set_cpufreq_touch_boost_off(int touch_boost_off) +{ + return sys_set_int(TOUCH_BOOST_OFF, touch_boost_off); +} diff --git a/src/touch/touch-plugin.h b/src/touch/touch-plugin.h new file mode 100644 index 0000000..b8e17ad --- /dev/null +++ b/src/touch/touch-plugin.h @@ -0,0 +1,25 @@ +/* + * Touch - Support plugin feature for Touch + * + * Copyright (c) 2013 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. + */ + +#ifndef __TOUCH_PLUGIN__ +#define __TOUCH_PLUGIN__ + +int get_cpufreq_touch_boost_off(int *); +int set_cpufreq_touch_boost_off(int); + +#endif /* __TOUCH_PLUGIN__ */ diff --git a/src/touch/touch-util.h b/src/touch/touch-util.h new file mode 100644 index 0000000..b53af78 --- /dev/null +++ b/src/touch/touch-util.h @@ -0,0 +1,30 @@ +/* + * Touch + * + * Copyright (c) 2011 - 2013 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. + * + */ + +#ifndef __TOUCH_UTIL_H__ +#define __TOUCh_UTIL_H__ + +#ifdef ENABLE_DEVICED_DLOG +#define ENABLE_DLOG +#endif + +#define LOG_TAG "TOUCH" +#include "shared/log-macro.h" + +#endif /* __TOUCH_UTIL_H__ */ diff --git a/src/touch/touch.c b/src/touch/touch.c new file mode 100644 index 0000000..bb1ab61 --- /dev/null +++ b/src/touch/touch.c @@ -0,0 +1,126 @@ +/* + * Touch + * + * Copyright (c) 2013 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 + +#include "touch.h" +#include "touch-controller.h" + +#include "core/devices.h" +#include "core/common.h" + +void touch_boost_enable(struct touch_control *touch_control, + enum touch_type type, enum touch_boost_state state) +{ + if (!touch_control) + return; + + switch (state) { + case TOUCH_BOOST_ON: + touch_control->mask |= (1 << type); + break; + case TOUCH_BOOST_OFF: + touch_control->mask &= ~(1 << type); + break; + default: + _E("Unknow touch boost state"); + return; + } + + /* + * Touch should update touch_control->cur_state after updating + * touch_control->mask variable because Touch need what some module + * turn on/off touch boost feature. + */ + if (touch_control->cur_state == state) + return; + + switch (type) { + case TOUCH_TYPE_VCONF_SIP: + set_cpufreq_touch_boost_off(state); + break; + default: + _E("Unknow touch type"); + return; + } + + touch_control->cur_state = state; + + _I("Touch Boost is %s", state == TOUCH_BOOST_ON ? "ON" : "OFF"); +} + +/* Define global variable of struct touch_control */ +static struct touch_control touch_control; + +static int touch_stop(void) +{ + /* Restore touch boost state as ON state */ + set_cpufreq_touch_boost_off(TOUCH_BOOST_ON); + + touch_controller_stop(); + + _I("Stop Touch"); + + return 0; +} + +static int touch_start(void) +{ + int i; + + /* Touch Boost is default on state */ + touch_control.cur_state = TOUCH_BOOST_ON; + + for (i = 0; i < TOUCH_TYPE_MAX; i++) + touch_control.mask |= (1 << i); + + touch_controller_start(); + + _I("Start Touch"); + + return 0; +} + +/* + * touch_init - Initialize Touch module + */ +static void touch_init(void *data) +{ + touch_controller_init(&touch_control); +} + +/* + * touch_exit - Exit Touch module + */ +static void touch_exit(void *data) +{ + touch_controller_exit(); +} + +static const struct device_ops touch_device_ops = { + .priority = DEVICE_PRIORITY_NORMAL, + .name = "touch", + .init = touch_init, + .exit = touch_exit, + .start = touch_start, + .stop = touch_stop, +}; + +DEVICE_OPS_REGISTER(&touch_device_ops) diff --git a/src/touch/touch.h b/src/touch/touch.h new file mode 100644 index 0000000..e7ab2e6 --- /dev/null +++ b/src/touch/touch.h @@ -0,0 +1,49 @@ +/* + * Touch + * + * Copyright (c) 2013 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. + * + */ + +#ifndef __TOUCH__ +#define __TOUCH__ + +#include +#include +#include "touch-util.h" + +/* Define touch type */ +enum touch_type { + TOUCH_TYPE_VCONF_SIP = 0, + TOUCH_TYPE_MAX, +}; + +/* Define touch boost state */ +enum touch_boost_state { + TOUCH_BOOST_ON = 0, + TOUCH_BOOST_OFF = 1, +}; + +/* + * struct touch_control_block + */ +struct touch_control { + unsigned int mask; + enum touch_boost_state cur_state; +}; + +void touch_boost_enable(struct touch_control *, + enum touch_type, enum touch_boost_state); +#endif /* __TOUCH__ */ diff --git a/src/usb/configurations/conf-supported.xml b/src/usb/configurations/conf-supported.xml new file mode 100644 index 0000000..306d75e --- /dev/null +++ b/src/usb/configurations/conf-supported.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/usb/configurations/usb-configurations.xml b/src/usb/configurations/usb-configurations.xml new file mode 100644 index 0000000..8f71d22 --- /dev/null +++ b/src/usb/configurations/usb-configurations.xml @@ -0,0 +1,328 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/usb/usb-client-control.c b/src/usb/usb-client-control.c new file mode 100755 index 0000000..2c4d36d --- /dev/null +++ b/src/usb/usb-client-control.c @@ -0,0 +1,94 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 "usb-client.h" +#include "core/device-notifier.h" + +#define VCONFKEY_USB_CONTROL "db/private/usb/usb_control" + +static int usb_control = DEVICE_OPS_STATUS_START; + +int control_start(void) +{ + if (usb_control == DEVICE_OPS_STATUS_START) + return 0; + + usb_control = DEVICE_OPS_STATUS_START; + if (vconf_set_int(VCONFKEY_USB_CONTROL, usb_control) != 0) + _E("Failed to set vconf"); + + if (check_current_usb_state() > 0) + act_usb_connected(); + + return 0; +} + +int control_stop(void) +{ + int cur_mode; + if (usb_control == DEVICE_OPS_STATUS_STOP) + return 0; + + usb_control = DEVICE_OPS_STATUS_STOP; + if (vconf_set_int(VCONFKEY_USB_CONTROL, usb_control) != 0) + _E("Failed to set vconf"); + + cur_mode = get_current_usb_mode(); + if (cur_mode <= SET_USB_NONE) { + _E("Current usb mode is already none"); + return 0; + } + + unset_client_mode(cur_mode, false); + + launch_syspopup(USB_RESTRICT); + + return 0; +} + +int control_status(void) +{ + return usb_control; +} + +static void check_prev_control_status(void) +{ + if (vconf_get_int(VCONFKEY_USB_CONTROL, &usb_control) != 0) + usb_control = DEVICE_OPS_STATUS_START; +} + +static int usb_client_booting_done(void *data) +{ + unregister_notifier(DEVICE_NOTIFIER_BOOTING_DONE, usb_client_booting_done); + check_prev_control_status(); + + usbclient_init_booting_done(); + + if (check_current_usb_state() > 0) + act_usb_connected(); + + return 0; +} + +void wait_until_booting_done(void) +{ + register_notifier(DEVICE_NOTIFIER_BOOTING_DONE, usb_client_booting_done); + usb_control = DEVICE_OPS_STATUS_STOP; +} diff --git a/src/usb/usb-client-dbus.c b/src/usb/usb-client-dbus.c new file mode 100755 index 0000000..4aa0a95 --- /dev/null +++ b/src/usb/usb-client-dbus.c @@ -0,0 +1,76 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 "usb-client.h" +#include "core/edbus-handler.h" + +#define CHANGE_USB_MODE "ChangeUsbMode" + +static void change_usb_client_mode(void *data, DBusMessage *msg) +{ + DBusError err; + int mode, debug; + + if (dbus_message_is_signal(msg, DEVICED_INTERFACE_USB, CHANGE_USB_MODE) == 0) { + _E("The signal is not for changing usb mode"); + return; + } + + dbus_error_init(&err); + + if (dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &mode, DBUS_TYPE_INVALID) == 0) { + _E("FAIL: dbus_message_get_args"); + goto out; + } + + switch (mode){ + case SET_USB_DEFAULT: + case SET_USB_RNDIS: + case SET_USB_RNDIS_DIAG: + debug = 0; + break; + case SET_USB_SDB: + case SET_USB_SDB_DIAG: + case SET_USB_RNDIS_SDB: + debug = 1; + break; + default: + _E("(%d) is unknown usb mode", mode); + goto out; + } + + if (vconf_set_int(VCONFKEY_USB_SEL_MODE, mode) != 0) + _E("Failed to set usb mode (%d)", mode); + + if (vconf_set_bool(VCONFKEY_SETAPPL_USB_DEBUG_MODE_BOOL, debug) != 0) + _E("Failed to set usb debug toggle (%d)", debug); + +out: + dbus_error_free(&err); + return; +} + + +int register_usb_client_change_request(void) +{ + return register_edbus_signal_handler(DEVICED_PATH_USB, + DEVICED_INTERFACE_USB, + CHANGE_USB_MODE, change_usb_client_mode); +} + diff --git a/src/usb/usb-client-set.c b/src/usb/usb-client-set.c new file mode 100755 index 0000000..5ed9152 --- /dev/null +++ b/src/usb/usb-client-set.c @@ -0,0 +1,601 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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/devices.h" +#include "core/launch.h" +#include "usb-client.h" + +#define BUF_MAX 256 + +#define TICKER_TYPE_DEFAULT "usb-client-default" +#define TICKER_TYPE_SSH "usb-client-ssh" + +#ifdef TIZEN_ENGINEER_MODE +const static bool eng_mode = true; +#else +const static bool eng_mode = false; +#endif + +struct ticker_data { + char *name; + int type; +}; + +static int debug = 0; + +static int write_sysfs(char *path, char *value) +{ + FILE *fp; + int ret; + + if (!path || !value) + return -ENOMEM; + + fp = fopen(path, "w"); + if (!fp) { + _E("FAIL: fopen(%s)", path); + return -ENOMEM; + } + + ret = fwrite(value, sizeof(char), strlen(value), fp); + if (ret < strlen(value)) { + _E("FAIL: fwrite(%s)", value); + ret = -ENOMEM; + goto out; + } + +out: + if (fclose(fp) != 0) + _E("FAIL: fclose()"); + return ret; +} + +static int set_configurations_to_sysfs(dd_list *list) +{ + dd_list *l; + struct xmlConfiguration *conf; + int ret; + + if (!list) + return -EINVAL; + + DD_LIST_FOREACH(list, l, conf) { + if (!(conf->value)) + continue; + + ret = write_sysfs(conf->path, conf->value); + if (ret < 0) { + _E("FAIL: write_sysfs(%s, %s)", conf->path, conf->value); + return ret; + } + } + return 0; +} + +static void run_operations_for_usb_mode(dd_list *list) +{ + dd_list *l; + int ret; + struct xmlOperation *oper; + + if (!list) + return ; + + DD_LIST_FOREACH(list, l, oper) { + ret = launch_app_cmd(oper->oper); + _I("operation: %s(%d)", oper->oper, ret); + } +} + +void unset_client_mode(int mode, bool change) +{ + int ret; + dd_list *conf_list; + dd_list *oper_list; + + if (!change) + update_current_usb_mode(SET_USB_NONE); + + if (update_usb_state(VCONFKEY_SYSMAN_USB_DISCONNECTED) < 0) + _E("FAIL: update_usb_state(%d)", VCONFKEY_SYSMAN_USB_DISCONNECTED); + + ret = make_configuration_list(SET_USB_NONE); + if (ret == 0) { + ret = get_configurations_list(&conf_list); + if (ret == 0) { + ret = set_configurations_to_sysfs(conf_list); + if (ret < 0) + _E("FAIL: set_configurations_to_sysfs()"); + } + } + + ret = make_operation_list(mode, USB_CON_UNSET); + if (ret == 0) { + ret = get_operations_list(&oper_list); + if (ret == 0) + run_operations_for_usb_mode(oper_list); + } + + release_operations_list(); +} + +static void launch_ticker_notification(int cur_mode, int sel_mode) +{ + struct ticker_data ticker; + const struct device_ops *ticker_ops; + + switch(sel_mode) { + case SET_USB_DEFAULT: + case SET_USB_SDB: + case SET_USB_SDB_DIAG: + if (cur_mode == SET_USB_DEFAULT + || cur_mode == SET_USB_SDB + || cur_mode == SET_USB_SDB_DIAG) + return; + + ticker.name = TICKER_TYPE_DEFAULT; + ticker.type = 0; /* WITHOUT_QUEUE */ + break; + case SET_USB_RNDIS: + case SET_USB_RNDIS_DIAG: + case SET_USB_RNDIS_SDB: + if (cur_mode == SET_USB_RNDIS + || cur_mode == SET_USB_RNDIS_TETHERING + || cur_mode == SET_USB_RNDIS_DIAG + || cur_mode == SET_USB_RNDIS_SDB) + return; + + ticker.name = TICKER_TYPE_SSH; + ticker.type = 0; /* WITHOUT_QUEUE */ + break; + case SET_USB_NONE: + case SET_USB_RNDIS_TETHERING: + default: + return; + } + + ticker_ops = find_device("ticker"); + + if (get_cradle_status() > 0) + return; + + if (ticker_ops && ticker_ops->init) + ticker_ops->init(&ticker); + else + _E("cannot find \"ticker\" ops"); +} + +static int get_selected_mode_by_debug_mode(int mode) +{ + int ret; + + debug = get_debug_mode(); + + switch (mode) { + case SET_USB_DEFAULT: + if (debug == 1) /* debug on */ + mode = SET_USB_SDB; + break; + case SET_USB_SDB: + case SET_USB_SDB_DIAG: + if (debug == 0) /* debug off */ + mode = SET_USB_DEFAULT; + break; + default: + break; + } + + return mode; +} + +static bool get_usb_tethering_state(void) +{ + int state; + int ret; + + if (vconf_get_int(VCONFKEY_MOBILE_HOTSPOT_MODE, &state) == 0 + && (state & VCONFKEY_MOBILE_HOTSPOT_MODE_USB)) { + _I("USB tethering is on"); + return true; + } + + _I("USB tethering is off"); + return false; +} + +static bool check_usb_tethering(int sel_mode) +{ + bool state; + + state = get_usb_tethering_state(); + + if (state == false) + return state; + + switch (sel_mode) { + case SET_USB_RNDIS_TETHERING: + case SET_USB_RNDIS: + return false; + default: + break; + } + + if (change_selected_usb_mode(SET_USB_RNDIS_TETHERING) != 0) { + _E("Failed to set usb selected mode (%d)", SET_USB_RNDIS_TETHERING); + return false; + } + + return true; +} + +static int turn_on_debug(void) +{ + debug = 1; + return vconf_set_bool(VCONFKEY_SETAPPL_USB_DEBUG_MODE_BOOL, debug); +} + +static int check_first_eng_mode(int sel_mode) +{ + static bool first = true; + + if (!eng_mode || !first) + return sel_mode; + + first = false; + + if (sel_mode == SET_USB_DEFAULT) { + sel_mode = SET_USB_SDB; + if (turn_on_debug() != 0) + _E("Failed to turn on debug toggle"); + } + + return sel_mode; +} + +static int decide_selected_mode(int sel_mode, int cur_mode) +{ + int mode; + + if (check_usb_tethering(sel_mode)) + return -ECANCELED; + + mode = check_first_eng_mode(sel_mode); + + mode = get_selected_mode_by_debug_mode(mode); + + if (mode == cur_mode) { + _I("Selected usb mode (%d) is same with current usb mode (%d)", mode, cur_mode); + return -ECANCELED; + } + + _I("Selected mode decided is (%d)", mode); + + return mode; +} + +void change_client_setting(int options) +{ + int sel_mode; + int cur_mode; + bool tethering; + int ret; + char *action; + dd_list *conf_list; + dd_list *oper_list; + + if (control_status() == DEVICE_OPS_STATUS_STOP) { + launch_syspopup(USB_RESTRICT); + return; + } + + sel_mode = get_selected_usb_mode(); + cur_mode = get_current_usb_mode(); + + sel_mode = decide_selected_mode(sel_mode, cur_mode); + if (sel_mode == -ECANCELED) + return; + else if (sel_mode <= 0) { + _E("Failed to get selected mode"); + return; + } + + if (options & SET_CONFIGURATION) { + if (cur_mode != SET_USB_NONE) { + unset_client_mode(cur_mode, true); + } + + ret = make_configuration_list(sel_mode); + if (ret < 0) { + _E("FAIL: make_configuration_list(%d)", sel_mode); + goto out_configuration; + } + + ret = get_configurations_list(&conf_list); + if (ret < 0) { + _E("failed to get configuration list"); + goto out_configuration; + } + + ret = set_configurations_to_sysfs(conf_list); + if (ret < 0) { + _E("FAIL: set_configurations_to_sysfs()"); + goto out_configuration; + } + } + + if (options & SET_OPERATION) { + ret = make_operation_list(sel_mode, USB_CON_SET); + if (ret < 0) { + _E("FAIL: make_operation_list()"); + goto out_operation; + } + + ret = get_operations_list(&oper_list); + if (ret < 0) { + _E("failed to get operation list"); + goto out_operation; + } + + if (update_usb_state(VCONFKEY_SYSMAN_USB_AVAILABLE) < 0) + _E("FAIL: update_usb_state(%d)", VCONFKEY_SYSMAN_USB_AVAILABLE); + + update_current_usb_mode(sel_mode); + + run_operations_for_usb_mode(oper_list); + } + + if (options & SET_NOTIFICATION) { + launch_ticker_notification(cur_mode, sel_mode); + } + + ret = 0; + +out_operation: + release_operations_list(); + +out_configuration: + if (make_configuration_list(SET_USB_NONE) < 0) + _E("Release configurations info error"); + + if (ret < 0) + launch_syspopup(USB_ERROR); + + return; +} + +void client_mode_changed(keynode_t* key, void *data) +{ + int ret; + + if (get_wait_configured()) + return; + + change_client_setting(SET_CONFIGURATION | SET_OPERATION | SET_NOTIFICATION); +} + +#if 0 +void client_mode_changed(keynode_t* key, void *data) +{ + int sel_mode; + int cur_mode; + int ret; + char *action; + dd_list *conf_list; + dd_list *oper_list; + + if (control_status() == DEVICE_OPS_STATUS_STOP) { + launch_syspopup(USB_RESTRICT); + return; + } + + sel_mode = get_selected_usb_mode(); + if (sel_mode <= SET_USB_NONE) { + _E("Getting selected usb mode error(%d)", sel_mode); + return; + } + + if (check_usb_tethering()) { + _I("Turning on the usb tethering"); + return; + } + + ret = check_debug_mode(sel_mode); + if (ret != 0) + return; + + sel_mode = check_first_eng_mode(sel_mode); + + cur_mode = get_current_usb_mode(); + if (cur_mode < SET_USB_NONE) { + _E("Getting current usb mode error(%d)", cur_mode); + return ; + } + + if (cur_mode == sel_mode) { + _I("Current usb mode(%d) is same with selected usb mode(%d)", cur_mode, sel_mode); + return ; + } + + if (cur_mode != SET_USB_NONE) { + unset_client_mode(cur_mode); + } + + ret = make_configuration_list(sel_mode); + if (ret < 0) { + _E("FAIL: make_configuration_list(%d)", sel_mode); + goto out; + } + + ret = make_operation_list(sel_mode, USB_CON_SET); + if (ret < 0) { + _E("FAIL: make_operation_list()"); + goto out; + } + + ret = get_configurations_list(&conf_list); + if (ret < 0) { + _E("failed to get configuration list"); + goto out; + } + + ret = get_operations_list(&oper_list); + if (ret < 0) { + _E("failed to get operation list"); + goto out; + } + + ret = set_configurations_to_sysfs(conf_list); + if (ret < 0) { + _E("FAIL: set_configurations_to_sysfs()"); + goto out; + } + + update_current_usb_mode(sel_mode); + + run_operations_for_usb_mode(oper_list); + + launch_ticker_notification(cur_mode, sel_mode); + + ret = 0; + +out: + if (ret < 0) + launch_syspopup(USB_ERROR); + + release_operations_list(); + ret = make_configuration_list(SET_USB_NONE); + if (ret < 0) + _E("release configurations info error"); + return; +} +#endif + +void debug_mode_changed(keynode_t* key, void *data) +{ + int new_debug; + int cur_mode; + int sel_mode; + + if (control_status() == DEVICE_OPS_STATUS_STOP) + return; + + new_debug = get_debug_mode(); + _I("old debug(%d), new debug(%d)", debug, new_debug); + if (debug == new_debug) + return; + + cur_mode = get_current_usb_mode(); + _I("cur_mode(%d)", cur_mode); + + switch (cur_mode) { + case SET_USB_DEFAULT: + case SET_USB_SDB: + case SET_USB_SDB_DIAG: + if (new_debug == 0) + sel_mode = SET_USB_DEFAULT; + else + sel_mode = SET_USB_SDB; + break; + default: + return ; + } + + if (change_selected_usb_mode(sel_mode) != 0) + _E("FAIL: change_selected_usb_mode(%d)", sel_mode); + + return; +} + +/* USB tethering */ +static int turn_on_usb_tethering(void) +{ + int cur_mode; + int sel_mode; + int ret; + + cur_mode = get_current_usb_mode(); + sel_mode = get_selected_usb_mode(); + + switch (cur_mode) { + case SET_USB_RNDIS: + case SET_USB_RNDIS_TETHERING: + return 0; + default: + break; + } + + switch (sel_mode) { + case SET_USB_RNDIS: + case SET_USB_RNDIS_TETHERING: + break; + default: + sel_mode = SET_USB_RNDIS_TETHERING; + break; + } + + ret = change_selected_usb_mode(sel_mode); + if (ret != 0) + _E("FAIL: change_selected_usb_mode(%d)", sel_mode); + + return ret; +} + +static int turn_off_usb_tethering(void) +{ + int cur_mode; + int sel_mode; + int ret; + + cur_mode = get_current_usb_mode(); + + switch(cur_mode) { + case SET_USB_RNDIS: + case SET_USB_RNDIS_TETHERING: + sel_mode = get_default_mode(); + ret = change_selected_usb_mode(sel_mode); + if (ret != 0) + _E("FAIL: change_selected_usb_mode(%d)", sel_mode); + return ret; + + default: + return 0; + } +} + +void tethering_status_changed(keynode_t* key, void *data) +{ + bool usb_tethering; + int ret; + + if (control_status() == DEVICE_OPS_STATUS_STOP) + return; + + usb_tethering = get_usb_tethering_state(); + if (usb_tethering) + ret = turn_on_usb_tethering(); + else + ret = turn_off_usb_tethering(); + + if (ret != 0) + _E("Failed to change tethering mode"); + + return; +} diff --git a/src/usb/usb-client-xml.c b/src/usb/usb-client-xml.c new file mode 100755 index 0000000..49d27a7 --- /dev/null +++ b/src/usb/usb-client-xml.c @@ -0,0 +1,919 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 "core/log.h" +#include "core/list.h" +#include "usb-client.h" + +#define BUF_MAX 256 + +#define DEFAULT_IPRODUCT_NAME "TIZEN" + +#define CONF_PATH "/usr/share/deviced/usb-configurations" +#define SUPPORTED_CONF_PATH CONF_PATH"/conf-supported.xml" +#define USB_CONFIGURATIONS_PATH CONF_PATH"/usb-configurations.xml" + +#define USB_CON_SET "set" +#define USB_CON_UNSET "unset" + +#define NODE_NAME_TEXT "text" +#define NODE_NAME_COMMENT "comment" +#define NODE_NAME_CONFIG_NODES "config-nodes" +#define NODE_NAME_CONFIG_files "config-files" +#define NODE_NAME_USB_CONFIG "usb-config" +#define NODE_NAME_CONF_FILE "conf-file" +#define NODE_NAME_USB_CONFS "usb-configurations" +#define NODE_NAME_USB_OPERS "usb-operations" +#define NODE_NAME_DRIVER "driver" +#define NODE_NAME_USB_DRV "usb-drv" +#define NODE_NAME_MODE "mode" +#define NODE_NAME_ACTION "action" +#define NODE_NAME_IPRODUCT "iProduct" +#define ATTR_VALUE "value" +#define ATTR_VERSION "ver" +#define ATTR_BACKGROUND "background" + +static dd_list *supported_list; /* Supported Configurations */ +static dd_list *oper_list; /* Operations for USB mode */ +static dd_list *conf_list; /* Configurations for usb mode */ +static char *driver; /* usb driver version (ex. 1.0, 1.1, none, ... ) */ + +int get_operations_list(dd_list **list) +{ + if (!list) + return -EINVAL; + + *list = oper_list; + return 0; +} + +int get_configurations_list(dd_list **list) +{ + if (!list) + return -EINVAL; + + *list = conf_list; + return 0; +} + +#ifdef USB_DEBUG +static void show_supported_confs_list(void) +{ + int i; + dd_list *l; + struct xmlSupported *sp; + void *mode; + + if (!supported_list) { + _D("Supported Confs list is empty"); + return; + } + + _D("********************************"); + _D("** Supported Confs list"); + _D("********************************"); + + DD_LIST_FOREACH(supported_list, l, sp) { + _D("** Mode : %d", sp->mode); + _D("********************************"); + } +} + +static void show_operation_list(void) +{ + int i; + dd_list *l; + struct xmlOperation *oper; + + _D("********************************"); + _D("** Operation list"); + _D("********************************"); + if (!oper_list) { + _D("Operation list is empty"); + _D("********************************"); + return; + } + + i = 0; + DD_LIST_FOREACH(oper_list, l, oper) { + _D("** Number : %d", i++); + _D("** Name : %s", oper->name); + _D("** Operation : %s", oper->oper); + _D("** Background: %d", oper->background); + _D("********************************"); + } +} + +static void show_configuration_list(void) +{ + int i; + dd_list *l; + struct xmlConfiguration *conf; + + if (!conf_list) { + _D("Configuration list is empty"); + return; + } + + _D("********************************"); + _D("** Configuration list"); + _D("********************************"); + + i = 0; + DD_LIST_FOREACH(conf_list, l, conf) { + _D("** Number: %d", i++); + _D("** Name : %s", conf->name); + _D("** Path : %s", conf->path); + _D("** Value : %s", conf->value); + _D("********************************"); + } +} +#else +#define show_supported_confs_list() do {} while(0) +#define show_operation_list() do {} while(0) +#define show_configuration_list() do {} while(0) +#endif + +static xmlDocPtr xml_open(const char *xml) +{ + if (!xml) + return NULL; + + return xmlReadFile(xml, NULL, 0); +} + +static void xml_close(xmlDocPtr doc) +{ + xmlFreeDoc(doc); +} + +static bool skip_node(xmlNodePtr node) +{ + if (!node) + return true; + + if (!xmlStrcmp(node->name, (const xmlChar *)NODE_NAME_TEXT)) + return true; + if (!xmlStrcmp(node->name, (const xmlChar *)NODE_NAME_COMMENT)) + return true; + + return false; +} + +static int get_xml_property(xmlNodePtr node, char *property, char *value, int len) +{ + xmlChar *xmlprop; + + xmlprop = xmlGetProp(node, (const xmlChar *)property); + if (!xmlprop) + return -ENOMEM; + + snprintf(value, len, "%s", (char *)xmlprop); + xmlFree(xmlprop); + + return 0; +} + +static bool is_usb_mode_supported(int usb_mode) +{ + dd_list *l; + struct xmlSupported *sp; + + DD_LIST_FOREACH(supported_list, l, sp) { + if (sp->mode == usb_mode) + return true; + } + + return false; +} + +static int get_iproduct_name(char *name, int size) +{ + if (!name) + return -EINVAL; + + /* TODO: Product name should be set using device model + * ex) TIZEN_SM-Z9005 */ + + snprintf(name, size, "%s", DEFAULT_IPRODUCT_NAME); + return 0; +} + +static int get_driver_version(xmlNodePtr root) +{ + int ret; + xmlNodePtr node; + FILE *fp; + char buf[BUF_MAX]; + char path[BUF_MAX]; + + if (!root) + return -EINVAL; + + for (node = root->children ; node ; node = node->next) { + if (skip_node(node)) + continue; + + if (xmlStrcmp(node->name, (const xmlChar *)NODE_NAME_DRIVER)) + continue; + + ret = get_xml_property(node, ATTR_VALUE, path, sizeof(path)); + if (ret < 0) { + _E("Failed to get property(%d)", ret); + return ret; + } + + if (access(path, F_OK) != 0) { + /* TODO: If the path does not exist, + * usb gadgets are not from Galaxy, but from Linux Kernel */ + driver = NULL; + return 0; + } + + fp = fopen(path, "r"); + if (!fp) { + _E("fopen() failed(%s)", path); + return -ENOMEM; + } + + if (!fgets(buf, sizeof(buf), fp)) { + _E("fgets() failed"); + fclose(fp); + return -ENOMEM; + } + + fclose(fp); + + driver = strdup(buf); + break; + } + return 0; +} + +/* Getting sysfs nodes to set usb configurations */ +static int add_conf_nodes_to_list(xmlNodePtr root) +{ + int ret; + xmlNodePtr node; + struct xmlConfiguration *conf; + char path[BUF_MAX]; + + if (!root) + return -EINVAL; + + for (node = root->children ; node ; node = node->next) { + if (skip_node(node)) + continue; + + ret = get_xml_property(node, ATTR_VALUE, path, sizeof(path)); + if (ret < 0) { + _E("Failed to get property(%d)", ret); + return ret; + } + + conf = (struct xmlConfiguration *)malloc(sizeof(struct xmlConfiguration)); + if (!conf) { + _E("malloc() failed"); + return -ENOMEM; + } + + conf->name = strdup((const char *)(node->name)); + conf->path = strdup(path); + conf->value = NULL; + + if (!(conf->name) || !(conf->path)) { + _E("strdup() failed"); + if (conf->name) + free(conf->name); + if (conf->path) + free(conf->path); + free(conf); + continue; + } + + DD_LIST_APPEND(conf_list, conf); + } + + return 0; +} + +static int get_configuration_nodes(xmlNodePtr root) +{ + int ret; + xmlNodePtr node; + char ver[BUF_MAX]; + + if (!root) + return -EINVAL; + + for (node = root->children ; node ; node = node->next) { + if (skip_node(node)) + continue; + + if (xmlStrcmp(node->name, (const xmlChar *)NODE_NAME_USB_DRV)) + continue; + + ret = get_xml_property(node, ATTR_VERSION, ver, sizeof(ver)); + if (ret < 0) { + _E("Failed to get property(%d)", ret); + return ret; + } + + if (strncmp(ver, driver, strlen(ver))) + continue; + + return add_conf_nodes_to_list(node); + } + + return -ENOMEM; +} + +int make_empty_configuration_list(void) +{ + int ret; + xmlDocPtr doc; + xmlNodePtr root; + xmlNodePtr node; + + doc = xml_open(USB_CONFIGURATIONS_PATH); + if (!doc) { + _E("fail to open xml file (%s)", USB_CONFIGURATIONS_PATH); + return -ENOMEM; + } + + root = xmlDocGetRootElement(doc); + if (!root) { + _E("FAIL: xmlDocGetRootElement()"); + ret = -ENOMEM; + goto out; + } + + for (node = root->children ; node ; node = node->next) { + if (skip_node(node)) + continue; + + if (!xmlStrcmp(node->name, (const xmlChar *)NODE_NAME_CONFIG_NODES)) { + ret = get_driver_version(node); + if (ret < 0) { + _E("Failed to get usb driver version"); + ret = -ENOMEM; + goto out; + } + + ret = get_configuration_nodes(node); + if (ret < 0) { + _E("Failed to get conf nodes"); + ret = -ENOMEM; + goto out; + } + + show_configuration_list(); + break; + } + } + + ret = 0; + +out: + xml_close(doc); + return ret; +} + +static int add_configurations_to_list(xmlNodePtr root) +{ + int ret; + dd_list *l; + struct xmlConfiguration *conf; + xmlNodePtr node; + char buf[BUF_MAX]; + char value[BUF_MAX]; + + if (!root) + return -EINVAL; + + DD_LIST_FOREACH(conf_list, l, conf) { + if (conf->value) { + free(conf->value); + conf->value = NULL; + } + + if (!strncmp(conf->name, NODE_NAME_IPRODUCT, strlen(NODE_NAME_IPRODUCT))) { + ret = get_iproduct_name(buf, sizeof(buf)); + if (ret == 0) + conf->value = strdup(buf); + continue; + } + + for (node = root->children ; node ; node = node->next) { + if (skip_node(node)) + continue; + + if (xmlStrcmp((const xmlChar *)conf->name, node->name)) + continue; + + ret = get_xml_property(node, ATTR_VALUE, value, sizeof(value)); + if (ret < 0) { + _E("Failed to get property(%d)", ret); + return ret; + } + + conf->value = strdup(value); + break; + } + } + + return 0; +} + +static int get_configurations_by_usb_mode(xmlNodePtr root, int mode) +{ + xmlNodePtr node; + char cMode[BUF_MAX]; + int iMode, ret; + + if (!root) + return -EINVAL; + + for (node = root->children ; node ; node = node->next) { + if (skip_node(node)) + continue; + + if (xmlStrcmp(node->name, (const xmlChar *)NODE_NAME_MODE)) + continue; + + ret = get_xml_property(node, ATTR_VALUE, cMode, sizeof(cMode)); + if (ret < 0) { + _E("Failed to get property(%d)", ret); + return ret; + } + + iMode = atoi(cMode); + if (mode != iMode) + continue; + + return add_configurations_to_list(node); + } + return -EINVAL; +} + +static int get_configurations_by_version(xmlNodePtr root, int mode) +{ + xmlNodePtr node; + char ver[BUF_MAX]; + int ret; + + if (!root) + return -EINVAL; + + for (node = root->children ; node ; node = node->next) { + if (skip_node(node)) + continue; + + if (xmlStrcmp(node->name, (const xmlChar *)NODE_NAME_USB_DRV)) + continue; + + ret = get_xml_property(node, ATTR_VERSION, ver, sizeof(ver)); + if (ret < 0) { + _E("Failed to get property(%d)", ret); + return ret; + } + + if (strncmp(ver, driver, strlen(ver))) + continue; + + return get_configurations_by_usb_mode(node, mode); + } + + return -EINVAL; +} + +static int get_configurations_info(xmlNodePtr root, int mode) +{ + xmlNodePtr node; + + if (!root) + return -EINVAL; + + for (node = root->children ; node ; node = node->next) { + if (skip_node(node)) + continue; + + if (xmlStrcmp(node->name, (const xmlChar *)NODE_NAME_USB_CONFS)) + continue; + + return get_configurations_by_version(node, mode); + } + + return -EINVAL; +} + +int make_configuration_list(int usb_mode) +{ + int ret; + xmlDocPtr doc; + xmlNodePtr root; + xmlNodePtr node; + + if (!is_usb_mode_supported(usb_mode)) { + _E("USB mode (%d) is not supported", usb_mode); + return -EINVAL; + } + + doc = xml_open(USB_CONFIGURATIONS_PATH); + if (!doc) { + _E("fail to open xml file (%s)", USB_CONFIGURATIONS_PATH); + return -ENOMEM; + } + + root = xmlDocGetRootElement(doc); + if (!root) { + _E("FAIL: xmlDocGetRootElement()"); + ret = -ENOMEM; + goto out; + } + + ret = get_configurations_info(root, usb_mode); + if (ret < 0) { + _E("Failed to get operations for usb mode(%d)", usb_mode); + ret = -ENOMEM; + goto out; + } + + show_configuration_list(); + ret = 0; + +out: + xml_close(doc); + return ret; +} + + +void release_configuration_list(void) +{ + dd_list *l; + struct xmlConfiguration *conf; + + if (!conf_list) + return; + + DD_LIST_FOREACH(conf_list, l, conf) { + if (conf->name) + free(conf->name); + if (conf->path) + free(conf->path); + if (conf->value) + free(conf->value); + if (conf) + free(conf); + } + + DD_LIST_FREE_LIST(conf_list); + conf_list = NULL; +} + +/* Getting configurations supported */ +static int get_supported_confs(xmlNodePtr root) +{ + int ret; + xmlNodePtr node; + char cMode[BUF_MAX]; + int iMode; + struct xmlSupported *sp; + + if (!root) + return -EINVAL; + + for (node = root->children ; node ; node = node->next) { + if (skip_node(node)) + continue; + + if (xmlStrcmp(node->name, (const xmlChar *)NODE_NAME_MODE)) + continue; + + ret = get_xml_property(node, ATTR_VALUE, cMode, sizeof(cMode)); + if (ret < 0) { + _E("Failed to get property(%d)", ret); + return ret; + } + + iMode = atoi(cMode); + + sp = (struct xmlSupported *)malloc(sizeof(struct xmlSupported)); + if (!sp) { + _E("malloc() failed"); + return -ENOMEM; + } + + sp->mode = iMode; + + DD_LIST_APPEND(supported_list, sp); + } + + return 0; +} + +int make_supported_confs_list(void) +{ + int ret; + xmlDocPtr doc; + xmlNodePtr root; + xmlNodePtr node; + + doc = xml_open(SUPPORTED_CONF_PATH); + if (!doc) { + _E("fail to open xml file (%s)", SUPPORTED_CONF_PATH); + return -ENOMEM; + } + + root = xmlDocGetRootElement(doc); + if (!root) { + _E("FAIL: xmlDocGetRootElement()"); + ret = -ENOMEM; + goto out; + } + + ret = get_supported_confs(root); + if (ret < 0) { + _E("Failed to get supported confs"); + ret = -ENOMEM; + goto out; + } + + show_supported_confs_list(); + ret = 0; + +out: + xml_close(doc); + return ret; +} + +void release_supported_confs_list(void) +{ + struct xmlSupported *sp; + dd_list *l; + + if (!supported_list) + return; + + DD_LIST_FOREACH(supported_list, l, sp) { + free(sp); + } + + DD_LIST_FREE_LIST(supported_list); + supported_list = NULL; +} + +/* Getting operations for each usb mode */ +static int get_operations_info(xmlNodePtr node, struct xmlOperation **oper) +{ + int ret; + char background[BUF_MAX]; + char operation[BUF_MAX]; + + if (!node || !oper) + return -EINVAL; + + ret = get_xml_property(node, ATTR_VALUE, operation, sizeof(operation)); + if (ret < 0) { + _E("Failed to get property(%d)", ret); + return ret; + } + + *oper = (struct xmlOperation *)malloc(sizeof(struct xmlOperation)); + if (!(*oper)) { + _E("malloc() failed"); + return -ENOMEM; + } + + (*oper)->name = strdup((const char *)(node->name)); + (*oper)->oper = strdup(operation); + + if (!((*oper)->name) || !((*oper)->oper)) { + if ((*oper)->name) + free((*oper)->name); + if ((*oper)->oper) + free((*oper)->oper); + if (*oper) { + free(*oper); + *oper = NULL; + } + return -ENOMEM; + } + + ret = get_xml_property(node, ATTR_BACKGROUND, background, sizeof(background)); + if (ret < 0) { + (*oper)->background = false; + return 0; + } + + if (strncmp(background, "true", strlen(background))) + (*oper)->background = false; + else + (*oper)->background = true; + + return 0; +} + +static int add_operations_to_list(xmlNodePtr root) +{ + int ret; + xmlNodePtr node; + struct xmlOperation *oper; + + if (!root) + return -EINVAL; + + for (node = root->children ; node ; node = node->next) { + if (skip_node(node)) + continue; + + ret = get_operations_info(node, &oper); + if (ret < 0 || !oper) { + _E("Failed to get operations info"); + return -ENOMEM; + } + + DD_LIST_APPEND(oper_list, oper); + } + + return 0; +} + +static int get_operations_by_usb_mode(xmlNodePtr root, int usb_mode) +{ + int ret; + xmlNodePtr node; + char cMode[BUF_MAX]; + int iMode; + + if (!root) + return -EINVAL; + + for (node = root->children ; node ; node = node->next) { + if (skip_node(node)) + continue; + + if (xmlStrcmp(node->name, (const xmlChar *)NODE_NAME_MODE)) + continue; + + ret = get_xml_property(node, ATTR_VALUE, cMode, sizeof(cMode)); + if (ret < 0) { + _E("Failed to get property(%d)", ret); + return ret; + } + + iMode = atoi(cMode); + + if (usb_mode != iMode) + continue; + + ret = add_operations_to_list(node); + if (ret < 0) { + _E("Failed to add operations to list "); + return -ENOMEM; + } + break; + } + + return 0; +} + +static int get_operations_by_action(xmlNodePtr root, int usb_mode, char *action) +{ + int ret; + xmlNodePtr node; + char act[BUF_MAX]; + + if (!root || !action) + return -EINVAL; + + for (node = root->children ; node ; node = node->next) { + if (skip_node(node)) + continue; + + if (xmlStrcmp(node->name, (const xmlChar *)NODE_NAME_ACTION)) + continue; + + ret = get_xml_property(node, ATTR_VALUE, act, sizeof(act)); + if (ret < 0) { + _E("Failed to get property(%d)", ret); + return ret; + } + + if (strncmp(act, action, strlen(act))) + continue; + + ret = get_operations_by_usb_mode(node, usb_mode); + if (ret < 0) { + _E("Failed to get operations for usb_mode (%d)", usb_mode); + return -ENOMEM; + } + break; + } + + return 0; +} + +static int get_usb_operations(xmlNodePtr root, int usb_mode, char *action) +{ + xmlNodePtr node; + + if (!root || !action) + return -EINVAL; + + for (node = root->children ; node ; node = node->next) { + if (skip_node(node)) + continue; + + if (xmlStrcmp(node->name, (const xmlChar *)NODE_NAME_USB_OPERS)) + continue; + + return get_operations_by_action(node, usb_mode, action); + } + + return -ENOMEM; +} + +int make_operation_list(int usb_mode, char *action) +{ + int ret; + xmlDocPtr doc; + xmlNodePtr root; + xmlNodePtr node; + char conf_file_path[BUF_MAX]; + + if (!action) + return -EINVAL; + + if (!is_usb_mode_supported(usb_mode)) { + _E("USB mode (%d) is not supported", usb_mode); + return -EINVAL; + } + + doc = xml_open(USB_CONFIGURATIONS_PATH); + if (!doc) { + _E("fail to open xml file (%s)", USB_CONFIGURATIONS_PATH); + return -ENOMEM; + } + + root = xmlDocGetRootElement(doc); + if (!root) { + _E("FAIL: xmlDocGetRootElement()"); + ret = -ENOMEM; + goto out; + } + + ret = get_usb_operations(root, usb_mode, action); + if (ret < 0) { + _E("Failed to get operations info(%d, %s)", usb_mode, action); + ret = -ENOMEM; + goto out; + } + + show_operation_list(); + ret = 0; + +out: + xml_close(doc); + return ret; +} + +void release_operations_list(void) +{ + dd_list *l; + struct xmlOperation *oper; + + if (!oper_list) + return; + + DD_LIST_FOREACH(oper_list, l, oper) { + if (oper->name) + free(oper->name); + if (oper->oper) + free(oper->oper); + if (oper) + free(oper); + } + + DD_LIST_FREE_LIST(oper_list); + oper_list = NULL; +} diff --git a/src/usb/usb-client.c b/src/usb/usb-client.c new file mode 100755 index 0000000..5df9f42 --- /dev/null +++ b/src/usb/usb-client.c @@ -0,0 +1,502 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 "usb-client.h" +#include "core/device-handler.h" +#include "core/edbus-handler.h" + +#define USB_POPUP_NAME "usb-syspopup" + +#ifndef VCONFKEY_USB_CONFIGURATION_ENABLED +#define VCONFKEY_USB_CONFIGURATION_ENABLED "memory/private/usb/conf_enabled" +#endif + +struct popup_data { + char *name; + char *key; + char *value; +}; + +enum usb_enabled { + USB_CONF_DISABLED, + USB_CONF_ENABLED, +}; + +static bool client_mode = false; +static char *driver_version = NULL; +static bool wait_configured = false; + +void launch_syspopup(char *str) +{ + struct popup_data params; + static const struct device_ops *apps = NULL; + + if (apps == NULL) { + apps = find_device("apps"); + if (apps == NULL) + return; + } + + params.name = USB_POPUP_NAME; + params.key = POPUP_KEY_CONTENT; + params.value = str; + + if (apps->init) + apps->init(¶ms); +} + +bool get_wait_configured(void) +{ + return wait_configured; +} + +int get_debug_mode(void) +{ + int debug; + if (vconf_get_bool(VCONFKEY_SETAPPL_USB_DEBUG_MODE_BOOL, &debug) != 0) + return 1; /* 0 means debug mode is on */ + + return debug; +} + +int get_default_mode(void) +{ + if (get_debug_mode() == 0) + return SET_USB_DEFAULT; + + return SET_USB_SDB; +} + +int update_usb_state(int state) +{ + return vconf_set_int(VCONFKEY_SYSMAN_USB_STATUS, state); +} + +int update_current_usb_mode(int mode) +{ + /*************************************************/ + /* TODO: This legacy vconf key should be removed */ + /* The legacy vconf key is used by mtp and OSP */ + int legacy; + + switch(mode) { + case SET_USB_DEFAULT: + case SET_USB_SDB: + case SET_USB_SDB_DIAG: + legacy = SETTING_USB_SAMSUNG_KIES; + break; + case SET_USB_RNDIS: + case SET_USB_RNDIS_DIAG: + case SET_USB_RNDIS_SDB: + legacy = SETTING_USB_DEBUG_MODE; + break; + case SET_USB_RNDIS_TETHERING: + legacy = SETTING_USB_TETHERING_MODE; + break; + case SET_USB_NONE: + default: + legacy = SETTING_USB_NONE_MODE; + break; + } + + if (vconf_set_int(VCONFKEY_SETAPPL_USB_MODE_INT, legacy) != 0) + _E("Failed to set legacy vconf key for current usb mode"); + /****************************************************/ + + return vconf_set_int(VCONFKEY_USB_CUR_MODE, mode); +} + +int check_current_usb_state(void) +{ + int ret; + int state; + + ret = device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_USB_ONLINE, &state); + if (ret != 0) + return -ENOMEM; + + return state; +} + +int get_current_usb_mode(void) +{ + int ret; + int mode; + + ret = vconf_get_int(VCONFKEY_USB_CUR_MODE, &mode); + if (ret != 0) + return -ENOMEM; + + return mode; +} + +int get_selected_usb_mode(void) +{ + int ret; + int mode; + + ret = vconf_get_int(VCONFKEY_USB_SEL_MODE, &mode); + if (ret != 0) + return -ENOMEM; + + return mode; +} + +int change_selected_usb_mode(int mode) +{ + if (mode <= SET_USB_NONE) + return -EINVAL; + return vconf_set_int(VCONFKEY_USB_SEL_MODE, mode); +} + +static int notify_vconf_keys(void) +{ + int ret; + + ret = vconf_notify_key_changed( + VCONFKEY_USB_SEL_MODE, + client_mode_changed, NULL); + if (ret != 0) { + _E("FAIL: vconf_notify_key_changed()"); + return ret; + } + + ret = vconf_notify_key_changed( + VCONFKEY_SETAPPL_USB_DEBUG_MODE_BOOL, + debug_mode_changed, NULL); + if (ret != 0) + _E("FAIL: vconf_notify_key_changed()"); + + ret = vconf_notify_key_changed( + VCONFKEY_MOBILE_HOTSPOT_MODE, + tethering_status_changed, NULL); + if (ret != 0) + _E("FAIL: vconf_notify_key_changed()"); + + return 0; +} + +static int ignore_vconf_keys(void) +{ + int ret; + + ret = vconf_ignore_key_changed( + VCONFKEY_USB_SEL_MODE, + client_mode_changed); + if (ret != 0) { + _E("FAIL: vconf_ignore_key_changed()"); + return ret; + } + + ret = vconf_ignore_key_changed( + VCONFKEY_SETAPPL_USB_DEBUG_MODE_BOOL, + debug_mode_changed); + if (ret != 0) + _E("FAIL: vconf_ignore_key_changed()"); + + ret = vconf_ignore_key_changed( + VCONFKEY_MOBILE_HOTSPOT_MODE, + tethering_status_changed); + if (ret != 0) + _E("FAIL: vconf_ignore_key_changed()"); + + return 0; +} + + +static int register_client_handlers(void) +{ + int ret; + + ret = notify_vconf_keys(); + if (ret < 0) + return ret; + + /* TODO: register other handler (ex. dbus, ... ) */ + + return 0; +} + +static int unregister_client_handlers(void) +{ + int ret; + + ret = ignore_vconf_keys(); + if (ret < 0) + return ret; + + /* TODO: unregister other handler (ex. dbus, ... ) */ + + return 0; +} + +static int init_client_values(void) +{ + int ret; + + ret = make_empty_configuration_list(); + if (ret < 0) + _E("Failed to get information of usb configurations"); + + ret = make_supported_confs_list(); + if (ret < 0) + _E("Failed to get information of usb configuration files"); + + return 0; +} + +static void deinit_client_values(void) +{ + int sel_mode; + + sel_mode = get_selected_usb_mode(); + switch (sel_mode) { + case SET_USB_RNDIS_TETHERING: + case SET_USB_RNDIS_DIAG: + if (change_selected_usb_mode(get_default_mode()) != 0) + _E("Failed to set selected usb mode"); + break; + default: + break; + } + + release_supported_confs_list(); + release_configuration_list(); +} + +static int init_client(void) +{ + int ret; + + client_mode = true; + + ret = register_client_handlers(); + if (ret < 0) + return ret; + + ret = init_client_values(); + if (ret < 0) + return ret; + + return 0; +} + +static int deinit_client(void) +{ + int ret; + + client_mode = false; + + ret = unregister_client_handlers(); + if (ret < 0) + _E("FAIL: unregister_client_handlers()"); + + deinit_client_values(); + + return 0; +} + +#ifdef MICRO_DD +void act_usb_connected(void) +{ + wait_configured = false; + + if (vconf_set_int(VCONFKEY_USB_CONFIGURATION_ENABLED, USB_CONF_ENABLED) != 0) + _E("Failed to set vconf key (%s)", VCONFKEY_USB_CONFIGURATION_ENABLED); + + if (init_client() < 0) + _E("FAIL: init_client()"); + + change_client_setting(SET_CONFIGURATION | SET_OPERATION | SET_NOTIFICATION); + + pm_lock_internal(getpid(), LCD_OFF, STAY_CUR_STATE, 0); +} +#else +void act_usb_connected(void) +{ + wait_configured = true; + + if (vconf_set_int(VCONFKEY_USB_CONFIGURATION_ENABLED, USB_CONF_ENABLED) != 0) + _E("Failed to set vconf key (%s)", VCONFKEY_USB_CONFIGURATION_ENABLED); + + if (init_client() < 0) + _E("FAIL: init_client()"); + + change_client_setting(SET_CONFIGURATION); + + pm_lock_internal(getpid(), LCD_OFF, STAY_CUR_STATE, 0); +} +#endif + +static void act_usb_disconnected(void) +{ + int cur_mode; + + wait_configured = false; + + if (vconf_set_int(VCONFKEY_USB_CONFIGURATION_ENABLED, USB_CONF_DISABLED) != 0) + _E("Failed to set vconf key (%s)", VCONFKEY_USB_CONFIGURATION_ENABLED); + + pm_unlock_internal(getpid(), LCD_OFF, STAY_CUR_STATE); + + cur_mode = get_current_usb_mode(); + if (cur_mode > SET_USB_NONE) + unset_client_mode(cur_mode, false); + + if (deinit_client() < 0) + _E("FAIL: deinit_client()"); + + if (update_usb_state(VCONFKEY_SYSMAN_USB_DISCONNECTED) < 0) + _E("FAIL: update_usb_state(%d)", VCONFKEY_SYSMAN_USB_DISCONNECTED); +} + +static void subsystem_switch_changed (struct udev_device *dev) +{ + const char *name = NULL; + const char *state = NULL; + int ret; + int cur_mode; + + name = udev_device_get_property_value(dev, UDEV_PROP_KEY_SWITCH_NAME); + if (!name) + return; + + if (strncmp(name, UDEV_PROP_VALUE_USB_CABLE, strlen(UDEV_PROP_VALUE_USB_CABLE))) + return; + + state = udev_device_get_property_value(dev, UDEV_PROP_KEY_SWITCH_STATE); + if (!state) + return; + + /* USB cable disconnected */ + if (!strncmp(state, UDEV_PROP_VALUE_DISCON, strlen(UDEV_PROP_VALUE_DISCON))) { + _I("USB cable is disconnected"); + act_usb_disconnected(); + return; + } + + /* USB cable connected */ + if (!strncmp(state, UDEV_PROP_VALUE_CON, strlen(UDEV_PROP_VALUE_CON))) { + _I("USB cable is connected"); + act_usb_connected(); + return; + } +} + +static void subsystem_platform_changed (struct udev_device *dev) +{ + const char *chgdet = NULL; + int state; + int ret; + + chgdet = udev_device_get_property_value(dev, UDEV_PROP_KEY_CHGDET); + if (!chgdet) + return; + + if (strncmp(chgdet, UDEV_PROP_VALUE_USB, strlen(UDEV_PROP_VALUE_USB))) + return; + + if (device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_USB_ONLINE, &state) != 0 + || (state != 0 && state != 1)) { + _E("cannot get the usb cable connection status"); + state = get_usb_state_direct(); + } + + /* USB cable disconnected */ + if (state == 0) { + _I("USB cable is disconnected"); + act_usb_disconnected(); + return; + } + + /* USB cable connected */ + if (state == 1) { + _I("USB cable is connected"); + act_usb_connected(); + return; + } + + _E("USB state is unknown(%d)", state); +} + +static void subsystem_usbmode_changed (struct udev_device *dev) +{ + const char *state = NULL; + + if (!wait_configured) + return; + + wait_configured = false; + + state = udev_device_get_property_value(dev, UDEV_PROP_KEY_USB_STATE); + if (!state) + return ; + + if (strncmp(state, UDEV_PROP_VALUE_CONFIGURED, strlen(state))) + return; + + _I("Real USB cable is connected"); + change_client_setting(SET_OPERATION | SET_NOTIFICATION); +} + +const static struct uevent_handler uhs[] = { + { SWITCH_SUBSYSTEM , subsystem_switch_changed , NULL }, + { USBMODE_SUBSYSTEM , subsystem_usbmode_changed , NULL }, + { PLATFORM_SUBSYSTEM , subsystem_platform_changed , NULL }, +}; + +void usbclient_init_booting_done(void) +{ + int ret, i; + + for (i = 0 ; i < ARRAY_SIZE(uhs) ; i++) { + ret = register_kernel_uevent_control(&uhs[i]); + if (ret < 0) + _E("FAIL: reg_uevent_control()"); + } + + if (register_usb_client_change_request() < 0) + _E("Failed to register the request to change usb mode"); +} + +static void usbclient_init(void *data) +{ + wait_until_booting_done(); +} + +static void usbclient_exit(void *data) +{ + int i; + + for (i = 0 ; i < ARRAY_SIZE(uhs) ; i++) { + unregister_kernel_uevent_control(&uhs[i]); + } +} + +static const struct device_ops usbclient_device_ops = { + .priority = DEVICE_PRIORITY_NORMAL, + .name = "usbclient", + .init = usbclient_init, + .exit = usbclient_exit, + .start = control_start, + .stop = control_stop, + .status = control_status, +}; + +DEVICE_OPS_REGISTER(&usbclient_device_ops) diff --git a/src/usb/usb-client.h b/src/usb/usb-client.h new file mode 100755 index 0000000..674afe1 --- /dev/null +++ b/src/usb/usb-client.h @@ -0,0 +1,127 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __USB_CLIENT_H__ +#define __USB_CLIENT_H__ + +#include +#include + +#include "core/log.h" +#include "core/devices.h" +#include "display/poll.h" +#include "core/udev.h" +#include "core/common.h" +#include "core/list.h" +#include "apps/apps.h" +#include "usb-common.h" + +/* Switch uevent */ +#define UDEV_PROP_KEY_SWITCH_NAME "SWITCH_NAME" +#define UDEV_PROP_VALUE_USB_CABLE "usb_cable" + +#define UDEV_PROP_KEY_SWITCH_STATE "SWITCH_STATE" +#define UDEV_PROP_VALUE_DISCON "0" +#define UDEV_PROP_VALUE_CON "1" + +/* usb_mode uevnet */ +#define USBMODE_SUBSYSTEM "usb_mode" +#define UDEV_PROP_KEY_USB_STATE "USB_STATE" +#define UDEV_PROP_VALUE_CONFIGURED "CONFIGURED" + +/* Platform uevent */ +#define UDEV_PROP_KEY_CHGDET "CHGDET" +#define UDEV_PROP_VALUE_USB "usb" + +#define USB_CON_SET "set" +#define USB_CON_UNSET "unset" + +#define USB_RESTRICT "restrict" +#define USB_ERROR "error" + +//#define USB_DEBUG + +enum usbclient_setting_option { + SET_CONFIGURATION = 0x0001, + SET_OPERATION = 0x0010, + SET_NOTIFICATION = 0x0100, +}; + +struct xmlSupported { + int mode; +}; + +struct xmlOperation { + char *name; + char *oper; + bool background; +}; + +struct xmlConfiguration { + char *name; + char *path; + char *value; +}; + +/* XML */ +int make_empty_configuration_list(void); +int make_configuration_list(int usb_mode); +void release_configuration_list(void); +int make_supported_confs_list(void); +void release_supported_confs_list(void); +int make_operation_list(int usb_mode, char *action); +void release_operations_list(void); + +int get_operations_list(dd_list **list); +int get_configurations_list(dd_list **list); + +/* vconf callbacks */ +void client_mode_changed(keynode_t* key, void *data); +void prev_client_mode_changed(keynode_t* key, void *data); +void debug_mode_changed(keynode_t* key, void *data); +void tethering_status_changed(keynode_t* key, void *data); + +/* Check usb state */ +int get_default_mode(void); +int check_current_usb_state(void); +int get_current_usb_mode(void); +int get_selected_usb_mode(void); +int get_debug_mode(void); +int change_selected_usb_mode(int mode); +int update_current_usb_mode(int mode); +int update_usb_state(int state); + +/* Unset usb mode */ +void unset_client_mode(int mode, bool change); + +/* USB control */ +int control_start(void); +int control_stop(void); +int control_status(void); +void wait_until_booting_done(void); +void usbclient_init_booting_done(void); +void act_usb_connected(void); + +/* USB syspopup */ +void launch_syspopup(char *str); + +/* Change usb mode */ +void change_client_setting(int options); +bool get_wait_configured(void); + +#endif /* __USB_CLIENT_H__ */ diff --git a/src/usb/usb-common.c b/src/usb/usb-common.c new file mode 100755 index 0000000..fd9d241 --- /dev/null +++ b/src/usb/usb-common.c @@ -0,0 +1,31 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 "usb-common.h" + +int get_cradle_status(void) +{ + int cradle; + + /* If cradle == 0, cradle is not connected. + * And if cradle > 0, cradle is connected. */ + if (vconf_get_int(VCONFKEY_SYSMAN_CRADLE_STATUS, &cradle) != 0) + return 0; + + return cradle; +} diff --git a/src/usb/usb-common.h b/src/usb/usb-common.h new file mode 100755 index 0000000..c411632 --- /dev/null +++ b/src/usb/usb-common.h @@ -0,0 +1,26 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __USB_COMMON_H__ +#define __USB_COMMON_H__ + +#include + +int get_cradle_status(void); + +#endif /* __USB_COMMON_H__ */ diff --git a/src/usb/usb-handler.c b/src/usb/usb-handler.c new file mode 100755 index 0000000..2c913aa --- /dev/null +++ b/src/usb/usb-handler.c @@ -0,0 +1,107 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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/launch.h" +#include "core/data.h" +#include "core/devices.h" +#include "core/edbus-handler.h" +#include "display/poll.h" +#include "core/common.h" + +#define USBCON_EXEC_PATH PREFIX"/bin/usb-server" +#define RETRY 3 + +#define SIGNAL_USB_CONTROL "UsbControl" + +static int usb_control = DEVICE_OPS_STATUS_START; + +static void usb_init(void *data) +{ + int val, i = 0, pid; + + if (device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_USB_ONLINE, &val) == 0) { + if (val==1) { + vconf_set_int(VCONFKEY_SYSMAN_USB_STATUS, + VCONFKEY_SYSMAN_USB_AVAILABLE); + while (i < RETRY + && pm_lock_internal(getpid(), LCD_OFF, STAY_CUR_STATE, 0) == -1) { + i++; + sleep(1); + } + pid = launch_if_noexist(USBCON_EXEC_PATH, NULL); + if (pid < 0) { + _E("usb appl launching failed\n"); + return; + } + } + else if (val==0) + vconf_set_int(VCONFKEY_SYSMAN_USB_STATUS,VCONFKEY_SYSMAN_USB_DISCONNECTED); + } +} + +static int usb_set_control(int control) +{ + char buf[2]; + char *arr[1]; + + if (usb_control == control) + return 0; + + usb_control = control; + _D("USB control: %d", usb_control); + + snprintf(buf, sizeof(buf), "%d", usb_control); + arr[0] = buf; + + broadcast_edbus_signal(DEVICED_PATH_USB_CONTROL, + DEVICED_INTERFACE_USB_CONTROL, + SIGNAL_USB_CONTROL, "i", arr); + + return 0; +} + +static int usb_start(void) +{ + return usb_set_control(DEVICE_OPS_STATUS_START); +} + +static int usb_stop(void) +{ + return usb_set_control(DEVICE_OPS_STATUS_STOP); +} + +static int usb_status(void) +{ + return usb_control; +} + +static const struct device_ops usb_device_ops = { + .priority = DEVICE_PRIORITY_NORMAL, + .name = "usb", + .init = usb_init, + .start = usb_start, + .stop = usb_stop, + .status = usb_status, +}; + +DEVICE_OPS_REGISTER(&usb_device_ops) diff --git a/src/usb/usb-host-camera.c b/src/usb/usb-host-camera.c new file mode 100755 index 0000000..6a28953 --- /dev/null +++ b/src/usb/usb-host-camera.c @@ -0,0 +1,187 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 "usb-host.h" +#include "core/device-notifier.h" + +#define UDEV_PROP_GPHOTO2_DRIVER "GPHOTO2_DRIVER" +#define UDEV_PROP_ACTION "ACTION" +#define UDEV_PROP_DEVNAME "DEVNAME" +#define UDEV_PROP_MODEL "ID_MODEL" +#define UDEV_PROP_MODEL_ID "ID_MODEL_ID" +#define UDEV_PROP_VENDOR "ID_VENDOR" +#define UDEV_PROP_VENDOR_ID "ID_VENDOR_ID" + +/* Popup */ +#define USBOTG_SYSPOPUP "usbotg-syspopup" +#define METHOD_CAMERA "CameraPopupLaunch" +#define PARAM_CAMERA_ADD "camera_add" +#define PARAM_CAMERA_REMOVE "camera_remove" + +static void camera_device_added (struct udev_device *dev) +{ + const char *driver = NULL; + const char *name = NULL; + const char *model = NULL; + const char *model_id = NULL; + const char *vendor = NULL; + const char *vendor_id = NULL; + char v_vendor[BUF_MAX]; + char v_model[BUF_MAX]; + int dev_type; + + if (!dev) + return; + + driver = udev_device_get_property_value(dev, UDEV_PROP_GPHOTO2_DRIVER); + if (!driver) + return; + + dev_type = USBHOST_CAMERA; + + name = udev_device_get_property_value(dev, UDEV_PROP_DEVNAME); + if (!name) { + _E("cannot get device name"); + return; + } + + vendor = udev_device_get_property_value(dev, UDEV_PROP_VENDOR); + vendor_id = udev_device_get_property_value(dev, UDEV_PROP_VENDOR_ID); + if (vendor && vendor_id + && !strncmp(vendor, vendor_id, strlen(vendor))) + memset(v_vendor, 0, sizeof(v_vendor)); + else { + if (verify_vendor_name(vendor, v_vendor, sizeof(v_vendor)) < 0) + memset(v_vendor, 0, sizeof(v_vendor)); + } + + model = udev_device_get_property_value(dev, UDEV_PROP_MODEL); + model_id = udev_device_get_property_value(dev, UDEV_PROP_MODEL_ID); + if (model && model_id + && !strncmp(model, model_id, strlen(model))) + memset(v_model, 0, sizeof(v_model)); + else { + if (verify_model_name(model, v_vendor, v_model, sizeof(v_vendor)) < 0) + memset(v_model, 0, sizeof(v_model)); + } + + + if (add_usb_device_to_list(dev_type, name, v_model, v_vendor) < 0) { + _E("Failed to add device to dev_list"); + return; + } + + launch_ticker_notification(TICKER_NAME_CAMERA_CONNECTED); + + launch_host_syspopup(USBOTG_SYSPOPUP, METHOD_CAMERA, + POPUP_KEY_CONTENT, PARAM_CAMERA_ADD, + NULL, NULL); + + send_msg_camera_added(); +} + +static void camera_device_removed (struct udev_device *dev) +{ + const char *name = NULL; + + if (!dev) + return; + + name= udev_device_get_property_value(dev, UDEV_PROP_DEVNAME); + if (!name) { + return; + } + + if (remove_usb_device_from_list(name, USBHOST_CAMERA) < 0) { + return; + } + + launch_ticker_notification(TICKER_NAME_DEVICE_DISCONNECTED); + + launch_host_syspopup(USBOTG_SYSPOPUP, METHOD_CAMERA, + POPUP_KEY_CONTENT, PARAM_CAMERA_REMOVE, + NULL, NULL); + + send_msg_camera_removed(); +} + +static void subsystem_usb_changed (struct udev_device *dev) +{ + const char *action = NULL; + if (!dev) + return; + + if (!is_host_uevent_enabled()) + return; + + action = udev_device_get_property_value(dev, UDEV_PROP_ACTION); + if (!action) + return; + + if (!strncmp(action, "add", strlen("add"))) { + camera_device_added(dev); + return; + } + + if (!strncmp(action, "remove", strlen("remove"))) { + camera_device_removed(dev); + return; + } +} + +const static struct uevent_handler uhs_camera[] = { + { USB_SUBSYSTEM , subsystem_usb_changed , NULL }, +}; + +static int usbhost_camera_init_booting_done(void *data) +{ + int ret, i; + + unregister_notifier(DEVICE_NOTIFIER_BOOTING_DONE, usbhost_camera_init_booting_done); + + for (i = 0 ; i < ARRAY_SIZE(uhs_camera) ; i++) { + ret = register_uevent_control(&uhs_camera[i]); + if (ret < 0) + _E("FAIL: reg_uevent_control()"); + } + + return 0; +} + +static void usbhost_camera_init(void *data) +{ + register_notifier(DEVICE_NOTIFIER_BOOTING_DONE, usbhost_camera_init_booting_done); +} + +static void usbhost_camera_exit(void *data) +{ + int i; + + for (i = 0 ; i < ARRAY_SIZE(uhs_camera) ; i++) { + unregister_uevent_control(&uhs_camera[i]); + } +} + +static const struct device_ops usbhost_device_camera_ops = { + .priority = DEVICE_PRIORITY_NORMAL, + .name = "usbhost_camera", + .init = usbhost_camera_init, + .exit = usbhost_camera_exit, +}; + +DEVICE_OPS_REGISTER(&usbhost_device_camera_ops) diff --git a/src/usb/usb-host-dbus.c b/src/usb/usb-host-dbus.c new file mode 100755 index 0000000..5f00d46 --- /dev/null +++ b/src/usb/usb-host-dbus.c @@ -0,0 +1,759 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 "usb-host.h" +#include "core/edbus-handler.h" + +#define RETRY_MAX 5 + +#define BUS_NAME_PREFIX "org.tizen.usb" +#define OBJECT_PATH_PREFIX "/Org/Tizen/Usb" + +/* Notice for usb storage mount/unmount success */ +#define STORAGE_BUS_NAME BUS_NAME_PREFIX".storage" +#define STORAGE_OBJECT_PATH OBJECT_PATH_PREFIX"/Storage" +#define STORAGE_INTERFACE_NAME STORAGE_BUS_NAME + +/* Notice for device changed */ +#define HOST_BUS_NAME BUS_NAME_PREFIX".host" +#define HOST_OBJECT_PATH OBJECT_PATH_PREFIX"/Host" +#define HOST_INTERFACE_NAME HOST_BUS_NAME +#define HOST_MOUSE_SIGNAL "usbmouse" +#define HOST_KEYBOARD_SIGNAL "usbkeyboard" +#define HOST_STORAGE_SIGNAL "usbstorage" +#define HOST_CAMERA_SIGNAL "usbcamera" +#define HOST_ADDED "added" +#define HOST_REMOVED "removed" + +/* Notification */ +#define POPUP_BUS_NAME "org.tizen.system.popup" +#define POPUP_OBJECT_PATH "/Org/Tizen/System/Popup" +#define POPUP_INTERFACE_NAME POPUP_BUS_NAME + +#define POPUP_PATH_USBHOST POPUP_OBJECT_PATH"/Usbhost" +#define POPUP_INTERFACE_USBHOST POPUP_INTERFACE_NAME".Usbhost" + +#define METHOD_STORAGE_NOTI_ON "UsbStorageNotiOn" +#define METHOD_STORAGE_RO_NOTI_ON "UsbStorageRoNotiOn" +#define METHOD_STORAGE_NOTI_OFF "UsbStorageNotiOff" +#define METHOD_DEVICE_NOTI_ON "UsbDeviceNotiOn" +#define METHOD_DEVICE_NOTI_UPDATE "UsbDeviceNotiUpdate" +#define METHOD_DEVICE_NOTI_OFF "UsbDeviceNotiOff" + +/* Unmount */ +#define SIGNAL_NAME_UNMOUNT "unmount_storage" + +/* Send device info to host-devices app */ +#define SIGNAL_NAME_DEVICE_ALL "host_device_all" +#define SIGNAL_NAME_DEVICE_ADDED "host_device_add" +#define SIGNAL_NAME_DEVICE_REMOVED "host_device_remove" + +/* USB storage update signal */ +#define SIGNAL_NAME_USB_STORAGE_CHANGED "usb_storage_changed" +#define STORAGE_ADDED "storage_added" +#define STORAGE_REMOVED "storage_removed" +#define STORAGE_UPDATED "storage_updated" + + +struct noti_keyword { + int type; + char *key; +}; + +static struct noti_keyword noti_key[] = { + { USBHOST_KEYBOARD , "keyboard" }, + { USBHOST_MOUSE , "mouse" }, + { USBHOST_CAMERA , "camera" }, + { USBHOST_PRINTER , "printer" }, + { USBHOST_UNKNOWN , "unknown" }, +}; + +static int noti_id = 0; + +void send_msg_storage_added(bool mount) +{ + char *param[1]; + + param[0] = HOST_ADDED; + + if (mount) { + if (broadcast_edbus_signal(STORAGE_OBJECT_PATH, + STORAGE_INTERFACE_NAME, + HOST_STORAGE_SIGNAL, + "s", param) < 0) + _E("Failed to send dbus signal"); + } else { + if (broadcast_edbus_signal(HOST_OBJECT_PATH, + HOST_INTERFACE_NAME, + HOST_STORAGE_SIGNAL, + "s", param) < 0) + _E("Failed to send dbus signal"); + } +} + +void send_msg_storage_removed(bool mount) +{ + char *param[1]; + + param[0] = HOST_REMOVED; + + if (mount) { + if (broadcast_edbus_signal(STORAGE_OBJECT_PATH, + STORAGE_INTERFACE_NAME, + HOST_STORAGE_SIGNAL, + "s", param) < 0) + _E("Failed to send dbus signal"); + } else { + if (broadcast_edbus_signal(HOST_OBJECT_PATH, + HOST_INTERFACE_NAME, + HOST_STORAGE_SIGNAL, + "s", param) < 0) + _E("Failed to send dbus signal"); + } +} + +static void send_msg_device_changed(char *signal, char* action) +{ + char *param[1]; + + param[0] = action; + + if (broadcast_edbus_signal(HOST_OBJECT_PATH, + HOST_INTERFACE_NAME, + signal, + "s", param) < 0) + _E("Failed to send dbus signal"); +} + +void send_msg_keyboard_added(void) +{ + send_msg_device_changed(HOST_KEYBOARD_SIGNAL, HOST_ADDED); +} + +void send_msg_keyboard_removed(void) +{ + send_msg_device_changed(HOST_KEYBOARD_SIGNAL, HOST_REMOVED); +} + +void send_msg_mouse_added(void) +{ + send_msg_device_changed(HOST_MOUSE_SIGNAL, HOST_ADDED); +} + +void send_msg_mouse_removed(void) +{ + send_msg_device_changed(HOST_MOUSE_SIGNAL, HOST_REMOVED); +} + +void send_msg_camera_added(void) +{ + send_msg_device_changed(HOST_CAMERA_SIGNAL, HOST_ADDED); +} + +void send_msg_camera_removed(void) +{ + send_msg_device_changed(HOST_CAMERA_SIGNAL, HOST_REMOVED); +} + +int activate_storage_notification(char *path, int mount_type) +{ + char devpath[BUF_MAX]; + char *arr[1]; + int ret, i; + char *method; + + if (!path) + return -EINVAL; + + switch (mount_type) { + case STORAGE_MOUNT_RW: + method = METHOD_STORAGE_NOTI_ON; + break; + case STORAGE_MOUNT_RO: + method = METHOD_STORAGE_RO_NOTI_ON; + break; + default: + _E("Unknown mount type(%d)", mount_type); + return -EINVAL; + } + + snprintf(devpath, sizeof(devpath), "%s", path); + arr[0] = devpath; + + i = 0; + do { + ret = dbus_method_sync(POPUP_BUS_NAME, + POPUP_PATH_USBHOST, + POPUP_INTERFACE_USBHOST, + METHOD_STORAGE_NOTI_ON, + "s", arr); + if (ret < 0) + _E("Retry to activate notification (path: %s, ret: %d, retry: %d)", path, ret, i); + else + break; + } while (i++ < RETRY_MAX); + + return ret; +} + +int deactivate_storage_notification(int id) +{ + char devpath[BUF_MAX]; + char *arr[1]; + int ret, i; + + if (id <= 0) + return -EINVAL; + + snprintf(devpath, sizeof(devpath), "%d", id); + arr[0] = devpath; + + i = 0; + do { + ret = dbus_method_sync(POPUP_BUS_NAME, + POPUP_PATH_USBHOST, + POPUP_INTERFACE_USBHOST, + METHOD_STORAGE_NOTI_OFF, + "i", arr); + if (ret < 0) + _E("Retry to deactivate notification (ret: %d, retry: %d)", ret, i); + else + break; + } while (i++ < RETRY_MAX); + + return ret; +} + +static void unmount_signal_handler(void *data, DBusMessage *msg) +{ + DBusError err; + char *path; + struct usb_device dev; + int ret; + + if (dbus_message_is_signal(msg, DEVICED_INTERFACE_USBHOST, SIGNAL_NAME_UNMOUNT) == 0) { + _E("The signal is not for unmounting storage"); + return; + } + + dbus_error_init(&err); + + if (dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &path, DBUS_TYPE_INVALID) == 0) { + _E("FAIL: dbus_message_get_args"); + return; + } + + snprintf(dev.mntpath, sizeof(dev.mntpath), "%s", path); + if (is_storage_mounted(path)) { + if (add_job(STORAGE_UNMOUNT, &dev, true) < 0) + _E("Failed to add job(%d, %s)", STORAGE_UNMOUNT, path); + } else { + _E("Failed to unmount since the storage (%s) is not mounted", path); + } +} + +int register_unmount_signal_handler(void) +{ + return register_edbus_signal_handler(DEVICED_PATH_USBHOST, + DEVICED_INTERFACE_USBHOST, + SIGNAL_NAME_UNMOUNT, unmount_signal_handler); +} + +static int get_product_name(struct usb_device *dev, char *product, int len) +{ + int v_len, m_len; + if (!dev || !product || len <= 0) + return -EINVAL; + + v_len = strlen(dev->vendor); + m_len = strlen(dev->model); + + if (v_len > 0 && m_len > 0) + snprintf(product, len, "%s %s", dev->vendor, dev->model); + else if (v_len > 0) + snprintf(product, len, "%s", dev->vendor); + else if (m_len > 0) + snprintf(product, len, "%s", dev->model); + else + memset(product, 0, len); + + return 0; +} + +static int launch_device_notification(int type, char *product) +{ + char *noti_type = NULL; + int i; + char devpath[BUF_MAX]; + char *arr[2]; + int ret, ret_val; + + for (i = 0; i < ARRAY_SIZE(noti_key) ; i++) { + if (noti_key[i].type == type) { + noti_type = noti_key[i].key; + break; + } + } + if (!noti_type) + return -EINVAL; + + arr[0] = noti_type; + arr[1] = product; + + i = 0; + do { + ret = dbus_method_sync(POPUP_BUS_NAME, + POPUP_PATH_USBHOST, + POPUP_INTERFACE_USBHOST, + METHOD_DEVICE_NOTI_ON, + "ss", arr); + if (ret < 0) + _E("Retry to activate notification (product: %s, ret: %d, retry: %d)", product, ret, i); + else + break; + } while (i++ < RETRY_MAX); + + return ret; +} + +static int remove_device_notification(void) +{ + char *arr[1]; + int ret, ret_val, i; + char id[8]; + + snprintf(id, sizeof(id), "%d", noti_id); + arr[0] = id; + + i = 0; + do { + ret = dbus_method_sync(POPUP_BUS_NAME, + POPUP_PATH_USBHOST, + POPUP_INTERFACE_USBHOST, + METHOD_DEVICE_NOTI_OFF, + "i", arr); + if (ret < 0) + _E("Retry to deactivate notification (ret: %d, retry: %d)", ret, i); + else + break; + } while (i++ < RETRY_MAX); + + return ret; +} + +static int update_device_notification(int devlen, int type, char *product) +{ + char *noti_type = NULL; + int i, ret; + char devpath[BUF_MAX]; + char *arr[4]; + char id[8]; + char len[4]; + + if (noti_id <= 0) + return -EINVAL; + + for (i = 0; i < ARRAY_SIZE(noti_key) ; i++) { + if (noti_key[i].type == type) { + noti_type = noti_key[i].key; + break; + } + } + if (!noti_type) + return -EINVAL; + + snprintf(id, sizeof(id), "%d", noti_id); + snprintf(len, sizeof(len), "%d", devlen); + arr[0] = id; + arr[1] = len; + arr[2] = noti_type; + arr[3] = product; + + i = 0; + do { + ret = dbus_method_sync(POPUP_BUS_NAME, + POPUP_PATH_USBHOST, + POPUP_INTERFACE_USBHOST, + METHOD_DEVICE_NOTI_UPDATE, + "isss", arr); + if (ret < 0) + _E("Retry to update notification (ret: %d, retry: %d)", ret, i); + else + break; + } while (i++ < RETRY_MAX); + + return ret; +} + +int activate_device_notification(struct usb_device *dev, int len) +{ + char product[BUF_MAX]; + int ret; + + if (!dev) + return -EINVAL; + + ret = get_product_name(dev, product, sizeof(product)); + if (ret < 0) { + _E("cannot get product name to show"); + return ret; + } + + if (len > 0) { + return update_device_notification(len + 1, dev->type, product); + } else { + noti_id= launch_device_notification(dev->type, product); + if (noti_id < 0) + return noti_id; + else + return 0; + } +} + +int deactivate_device_notification(struct usb_device *dev, int len) +{ + char product[BUF_MAX]; + int ret; + + if (len <= 0) { + ret = remove_device_notification(); + noti_id = 0; + if (ret < 0) + _E("Faile to remove notification"); + return ret; + } + + ret = get_product_name(dev, product, sizeof(product)); + if (ret < 0) { + _E("cannot get product name to show"); + return ret; + } + + return update_device_notification(len, dev->type, product); +} + +static int send_device_changed_info(struct usb_device *dev, char *signal) +{ + char *param[3]; + char v_vendor[BUF_MAX]; + char v_model[BUF_MAX]; + int i; + char *noti_type; + + int ret; + + if (!dev | !signal) + return -EINVAL; + + ret = verify_vendor_name(dev->vendor, v_vendor, sizeof(v_vendor)); + if (ret < 0) + return ret; + ret = verify_model_name(dev->model, v_vendor, v_model, sizeof(v_model)); + if (ret < 0) + return ret; + + noti_type = NULL; + for (i = 0; i < ARRAY_SIZE(noti_key) ; i++) { + if (noti_key[i].type == dev->type) { + noti_type = noti_key[i].key; + break; + } + } + if (!noti_type) + return -EINVAL; + + param[0] = noti_type; + param[1] = v_vendor; + param[2] = v_model; + + ret = broadcast_edbus_signal(DEVICED_PATH_USBHOST, + DEVICED_INTERFACE_USBHOST, + signal, + "sss", param); + return ret; +} + +int send_device_added_info(struct usb_device *dev) +{ + return send_device_changed_info(dev, SIGNAL_NAME_DEVICE_ADDED); +} + +int send_device_removed_info(struct usb_device *dev) +{ + return send_device_changed_info(dev, SIGNAL_NAME_DEVICE_REMOVED); +} + +static int send_all_device_info(void) +{ + dd_list *l; + dd_list *dev_list; + struct usb_device *dev; + + dev_list = get_device_list(); + if (!dev_list) { + _E("cannot get device list()"); + return -ENOMEM; + } + + _I("device list length: %d", DD_LIST_LENGTH(dev_list)); + + DD_LIST_FOREACH(dev_list, l, dev) { + if (send_device_added_info(dev) < 0) + _E("Failed to send device info"); + } + + return 0; +} + +static void host_device_all_signal_handler(void *data, DBusMessage *msg) +{ + DBusError err; + char *str; + char *path; + + _I("All device info are requested"); + + if (dbus_message_is_signal(msg, DEVICED_INTERFACE_USBHOST, SIGNAL_NAME_DEVICE_ALL) == 0) { + _E("The signal is not for unmounting storage"); + return; + } + + if (send_all_device_info() < 0) + _E("Failed to send device info"); +} + +int register_device_all_signal_handler(void) +{ + return register_edbus_signal_handler(DEVICED_PATH_USBHOST, + DEVICED_INTERFACE_USBHOST, + SIGNAL_NAME_DEVICE_ALL, host_device_all_signal_handler); +} + +int send_storage_changed_info(struct usb_device *dev, char *type) +{ + char *param[3]; + char mounted[2]; + + if (!dev | !type) + return -EINVAL; + + param[0] = type; + param[1] = dev->mntpath; + snprintf(mounted, sizeof(mounted), "%d", dev->is_mounted); + param[2] = mounted; + + return broadcast_edbus_signal(DEVICED_PATH_USBHOST, + DEVICED_INTERFACE_USBHOST, + SIGNAL_NAME_USB_STORAGE_CHANGED, + "ssi", param); +} + +static int send_all_storage_info(void) +{ + dd_list *storage_list, *l; + struct usb_device *dev; + + storage_list = get_storage_list(); + if (!storage_list) + return 0; + + DD_LIST_FOREACH (storage_list, l, dev) { + if (send_storage_changed_info(dev, STORAGE_UPDATED) < 0) + _E("Failed to send storage info (%s, %s)", dev->name, dev->mntpath); + } + return 0; +} + +static DBusMessage *send_storage_info_all(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int ret; + + ret = send_all_storage_info(); + + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *send_storage_mount(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + char *path; + int ret; + struct usb_device dev; + + + ret = dbus_message_get_args(msg, NULL, + DBUS_TYPE_STRING, &path, + DBUS_TYPE_INVALID); + if (ret == 0) { + _E("Failed to get path information"); + ret = -ENOMEM; + goto out; + } + + snprintf(dev.mntpath, sizeof(dev.mntpath), "%s", path); + if (!is_storage_mounted(path)) { + ret = add_job(STORAGE_MOUNT, &dev, true); + if (ret < 0) + _E("Failed to add job(%d, %s)", STORAGE_MOUNT, path); + } else { + _E("Failed to mount since the storage (%s) is already mounted", path); + } + +out: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *send_storage_unmount(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + char *path; + int ret; + struct usb_device dev; + + ret = dbus_message_get_args(msg, NULL, + DBUS_TYPE_STRING, &path, + DBUS_TYPE_INVALID); + if (ret == 0) { + _E("Failed to get path information"); + ret = -ENOMEM; + goto out; + } + + snprintf(dev.mntpath, sizeof(dev.mntpath), "%s", path); + if (is_storage_mounted(path)) { + ret = add_job(STORAGE_UNMOUNT, &dev, true); + if (ret < 0) + _E("Failed to add job(%d, %s)", STORAGE_UNMOUNT, path); + } else { + _E("Failed to unmount since the storage (%s) is not mounted", path); + ret = -ECANCELED; + } + +out: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *send_storage_format(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + char *path; + int ret; + struct usb_device dev; + + ret = dbus_message_get_args(msg, NULL, + DBUS_TYPE_STRING, &path, + DBUS_TYPE_INVALID); + if (ret == 0) { + _E("Failed to get path information"); + ret = -ENOMEM; + goto out; + } + + snprintf(dev.mntpath, sizeof(dev.mntpath), "%s", path); + ret = add_job(STORAGE_FORMAT, &dev, true); + if (ret < 0) + _E("Failed to add job(%d, %s)", STORAGE_FORMAT, path); + +out: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static int is_device_connected(int type) +{ + int ret; + dd_list *device_list, *l; + struct usb_device *dev; + + ret = DEVICE_DISCONNECTED; + + device_list = get_device_list(); + if (!device_list) { + _E("Device list is empty"); + return ret; + } + + DD_LIST_FOREACH(device_list, l, dev) { + if (dev->type == type) { + ret = DEVICE_CONNECTED; + break; + } + } + _I("Device (%d) state is (%d)", type, ret); + return ret; +} + +static DBusMessage *send_keyboard_state(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int ret; + + ret = is_device_connected(USBHOST_KEYBOARD); + +out: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static DBusMessage *send_mouse_state(E_DBus_Object *obj, DBusMessage *msg) +{ + DBusMessageIter iter; + DBusMessage *reply; + int ret; + + ret = is_device_connected(USBHOST_MOUSE); + +out: + reply = dbus_message_new_method_return(msg); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret); + return reply; +} + +static const struct edbus_method edbus_methods[] = { + { "StorageInfoAll" , NULL, "i" , send_storage_info_all }, + { "StorageMount" , "s", "i" , send_storage_mount }, + { "StorageUnmount" , "s", "i" , send_storage_unmount }, + { "StorageFormat" , "s", "i" , send_storage_format }, + { "GetKeyboardState", NULL, "i" , send_keyboard_state }, + { "GetMouseState" , NULL, "i" , send_mouse_state }, +}; + +int register_usbhost_dbus_methods(void) +{ + return register_edbus_method(DEVICED_PATH_USBHOST, edbus_methods, ARRAY_SIZE(edbus_methods)); +} diff --git a/src/usb/usb-host-hid.c b/src/usb/usb-host-hid.c new file mode 100755 index 0000000..7749274 --- /dev/null +++ b/src/usb/usb-host-hid.c @@ -0,0 +1,243 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 "usb-host.h" +#include "core/device-notifier.h" +#include + +#define UDEV_PROP_DEVLINKS "DEVLINKS" +#define UDEV_PROP_PATH "ID_PATH" +#define UDEV_PROP_KEYBOARD "ID_INPUT_KEYBOARD" +#define UDEV_PROP_MOUSE "ID_INPUT_MOUSE" +#define UDEV_PROP_MODEL "ID_MODEL" +#define UDEV_PROP_MODEL_ID "ID_MODEL_ID" +#define UDEV_PROP_VENDOR "ID_VENDOR" +#define UDEV_PROP_VENDOR_ID "ID_VENDOR_ID" + +static bool check_same_hid(const char *name) +{ + dd_list *dev_list, *l; + struct usb_device *dev; + char head[BUF_MAX]; + char *term; + + if (!name) + return false; + + dev_list = get_device_list(); + if (!dev_list) + return false; + + snprintf(head, sizeof(head), "%s", name); + term = strrchr(head, ':'); + if (!term) + return false; + *term = '\0'; + _I("hid name head:(%s)", head); + + DD_LIST_FOREACH(dev_list, l, dev) { + if (strstr(dev->name, head)) + return true; + } + + return false; +} + +static void hid_device_added (struct udev_device *dev) +{ + const char *path = NULL; + const char *type = NULL; + const char *model = NULL; + const char *model_id = NULL; + const char *vendor = NULL; + const char *vendor_id = NULL; + char v_vendor[BUF_MAX]; + char v_model[BUF_MAX]; + int dev_type; + + if (!dev) + return; + + if (udev_device_get_property_value(dev, UDEV_PROP_DEVLINKS)) + return; + + path = udev_device_get_property_value(dev, UDEV_PROP_PATH); + if (!path) { + _E("cannot get device path"); + return; + } + + if (check_same_hid(path)) { + _E("Same device is already connected"); + return; + } + + type = udev_device_get_property_value(dev, UDEV_PROP_KEYBOARD); + if (type) + dev_type = USBHOST_KEYBOARD; + else { + type = udev_device_get_property_value(dev, UDEV_PROP_MOUSE); + if (type) + dev_type = USBHOST_MOUSE; + } + if (!type) { + _E("cannot get device type"); + return; + } + + vendor = udev_device_get_property_value(dev, UDEV_PROP_VENDOR); + vendor_id = udev_device_get_property_value(dev, UDEV_PROP_VENDOR_ID); + if (vendor && vendor_id + && !strncmp(vendor, vendor_id, strlen(vendor))) + memset(v_vendor, 0, sizeof(v_vendor)); + else { + if (verify_vendor_name(vendor, v_vendor, sizeof(v_vendor)) < 0) + memset(v_vendor, 0, sizeof(v_vendor)); + } + + model = udev_device_get_property_value(dev, UDEV_PROP_MODEL); + model_id = udev_device_get_property_value(dev, UDEV_PROP_MODEL_ID); + if (model && model_id + && !strncmp(model, model_id, strlen(model))) + memset(v_model, 0, sizeof(v_model)); + else { + if (verify_model_name(model, v_vendor, v_model, sizeof(v_vendor)) < 0) + memset(v_model, 0, sizeof(v_model)); + } + + if (add_usb_device_to_list(dev_type, path, v_model, v_vendor) < 0) { + _E("Failed to add device to dev_list"); + return; + } + + if (dev_type == USBHOST_KEYBOARD) { + launch_ticker_notification(TICKER_NAME_KEYBOARD_CONNECTED); + send_msg_keyboard_added(); + } else if (dev_type == USBHOST_MOUSE) { + launch_ticker_notification(TICKER_NAME_MOUSE_CONNECTED); + send_msg_mouse_added(); + } +} + +static void hid_device_removed (struct udev_device *dev) +{ + const char *path = NULL; + const char *type = NULL; + int dev_type; + + if (!dev) + return; + + if (udev_device_get_property_value(dev, UDEV_PROP_DEVLINKS)) + return; + + type = udev_device_get_property_value(dev, UDEV_PROP_KEYBOARD); + if (type) + dev_type = USBHOST_KEYBOARD; + else { + type = udev_device_get_property_value(dev, UDEV_PROP_MOUSE); + if (type) + dev_type = USBHOST_MOUSE; + else + return; + } + + path = udev_device_get_property_value(dev, UDEV_PROP_PATH); + if (!path) { + _E("cannot get device path"); + return; + } + + if (remove_usb_device_from_list(path, dev_type) < 0) { + _E("Failed to remove device from dev_list"); + return; + } + + launch_ticker_notification(TICKER_NAME_DEVICE_DISCONNECTED); + + if (dev_type == USBHOST_KEYBOARD) + send_msg_keyboard_removed(); + else if (dev_type == USBHOST_MOUSE) + send_msg_mouse_removed(); +} + +static void subsystem_input_changed (struct udev_device *dev) +{ + const char *action = NULL; + if (!dev) + return; + + if (!is_host_uevent_enabled()) + return; + + action = udev_device_get_property_value(dev, "ACTION"); + if (!action) + return; + + if (!strncmp(action, "add", strlen("add"))) { + hid_device_added(dev); + return; + } + + if (!strncmp(action, "remove", strlen("remove"))) { + hid_device_removed(dev); + return; + } +} + +const static struct uevent_handler uhs_hid[] = { + { INPUT_SUBSYSTEM , subsystem_input_changed , NULL }, +}; + +static int usbhost_hid_init_booting_done(void *data) +{ + int ret, i; + + unregister_notifier(DEVICE_NOTIFIER_BOOTING_DONE, usbhost_hid_init_booting_done); + + for (i = 0 ; i < ARRAY_SIZE(uhs_hid) ; i++) { + ret = register_uevent_control(&uhs_hid[i]); + if (ret < 0) + _E("FAIL: reg_uevent_control()"); + } + + return 0; +} + +static void usbhost_hid_init(void *data) +{ + register_notifier(DEVICE_NOTIFIER_BOOTING_DONE, usbhost_hid_init_booting_done); +} + +static void usbhost_hid_exit(void *data) +{ + int i; + + for (i = 0 ; i < ARRAY_SIZE(uhs_hid) ; i++) { + unregister_uevent_control(&uhs_hid[i]); + } +} + +static const struct device_ops usbhost_device_hid_ops = { + .priority = DEVICE_PRIORITY_NORMAL, + .name = "usbhost_hid", + .init = usbhost_hid_init, + .exit = usbhost_hid_exit, +}; + +DEVICE_OPS_REGISTER(&usbhost_device_hid_ops) diff --git a/src/usb/usb-host-naming.c b/src/usb/usb-host-naming.c new file mode 100755 index 0000000..a92cb3f --- /dev/null +++ b/src/usb/usb-host-naming.c @@ -0,0 +1,147 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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. + */ + +#define _GNU_SOURCE +#include "usb-host.h" +#include + +#define VENDOR_HP_1 "Hewlett-Packard" +#define VENDOR_HP_2 "Hewlett Packard" +#define VENDOR_HP_3 "HP" +#define VENDOR_SAMSUNG "Samsung" + +static void remove_underbar(char *name) +{ + int i; + char *temp = name; + + if (!temp) + return; + + for (i = 0 ; i < strlen(name); temp++, i++) { + if (*temp == '_') + *temp = ' '; + } +} + +static void remove_non_alphabet(char *name) +{ + int i; + char *pos, *temp; + + if (!name) + return; + + pos = name + strlen(name) - 1; + + for (i = strlen(name); i > 0 ; i--, pos--) { + if ((*pos >= 48 && *pos <= 57) /* number */ + || (*pos >= 65 && *pos <= 90) /* uppercase letter */ + || (*pos >= 97 && *pos <= 122) /* lowercase letter */ + || *pos == '-' /* hyphen */ + || *pos == ' ') /* white space */ + continue; + + temp = pos; + while (*temp != '\0') { + *temp = *(temp + 1); + temp++; + } + } +} + +static void change_to_short(char *name, int len) +{ + if (strcasestr(name, VENDOR_HP_1)) { + snprintf(name, len, "%s", VENDOR_HP_3); + return; + } + + if (strcasestr(name, VENDOR_HP_2)) { + snprintf(name, len, "%s", VENDOR_HP_3); + return; + } + + if (strcasestr(name, VENDOR_HP_3)) { + snprintf(name, len, "%s", VENDOR_HP_3); + return; + } + + if (strcasestr(name, VENDOR_SAMSUNG)) { + snprintf(name, len, "%s", VENDOR_SAMSUNG); + return; + } +} + +static void remove_vendor(char *model, char *vendor) +{ + char *pos, *temp; + int i; + + pos = strcasestr(model, vendor); + if (!pos) + return; + + temp = pos + strlen(vendor); + + while(*pos != '\0') { + *pos = *temp; + pos++; + temp++; + } +} + +int verify_vendor_name(const char *vendor, char *buf, int len) +{ + char name[BUF_MAX]; + + if (!vendor || !buf || len <= 0) + return -EINVAL; + + snprintf(name, sizeof(name), "%s", vendor); + + remove_underbar(name); + + remove_non_alphabet(name); + + change_to_short(name, strlen(name)); + + snprintf(buf, len, "%s", name); + return 0; +} + +int verify_model_name(const char *model, char *vendor, char *buf, int len) +{ + char name[BUF_MAX]; + + if (!model || !vendor || !buf || len <= 0) + return -EINVAL; + + snprintf(name, sizeof(name), "%s", model); + + remove_underbar(name); + + remove_non_alphabet(name); + + change_to_short(name, strlen(name)); + + remove_vendor(name, vendor); + + snprintf(buf, len, "%s", name); + return 0; +} diff --git a/src/usb/usb-host-printer.c b/src/usb/usb-host-printer.c new file mode 100755 index 0000000..d1a1124 --- /dev/null +++ b/src/usb/usb-host-printer.c @@ -0,0 +1,182 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 "usb-host.h" +#include "core/device-notifier.h" + +#define UDEV_PROP_ACTION "ACTION" +#define UDEV_PROP_SYSTEMD_WANTS "SYSTEMD_WANTS" +#define UDEV_PROP_DEVPATH "DEVPATH" +#define UDEV_PROP_MODEL "ID_MODEL" +#define UDEV_PROP_MODEL_ID "ID_MODEL_ID" +#define UDEV_PROP_VENDOR "ID_VENDOR" +#define UDEV_PROP_VENDOR_ID "ID_VENDOR_ID" + +static void printer_device_added (struct udev_device *dev) +{ + const char *printer = NULL; + const char *path = NULL; + const char *model = NULL; + const char *model_id = NULL; + const char *vendor = NULL; + const char *vendor_id = NULL; + char v_vendor[BUF_MAX]; + char v_model[BUF_MAX]; + char *temp; + int dev_type; + + if (!dev) + return; + + printer = udev_device_get_property_value(dev, UDEV_PROP_SYSTEMD_WANTS); + if (!printer) + return; + + if (!strstr(printer, "printer")) + return; + + path = udev_device_get_property_value(dev, UDEV_PROP_DEVPATH); + if (!path) + return; + + temp = strrchr(path, '/'); + if (!temp) + return; + + if (strstr(temp, "lp")) + return; + + dev_type = USBHOST_PRINTER; + + vendor = udev_device_get_property_value(dev, UDEV_PROP_VENDOR); + vendor_id = udev_device_get_property_value(dev, UDEV_PROP_VENDOR_ID); + if (vendor && vendor_id + && !strncmp(vendor, vendor_id, strlen(vendor))) + memset(v_vendor, 0, sizeof(v_vendor)); + else { + if (verify_vendor_name(vendor, v_vendor, sizeof(v_vendor)) < 0) + memset(v_vendor, 0, sizeof(v_vendor)); + } + + model = udev_device_get_property_value(dev, UDEV_PROP_MODEL); + model_id = udev_device_get_property_value(dev, UDEV_PROP_MODEL_ID); + if (model && model_id + && !strncmp(model, model_id, strlen(model))) + memset(v_model, 0, sizeof(v_model)); + else { + if (verify_model_name(model, v_vendor, v_model, sizeof(v_vendor)) < 0) + memset(v_model, 0, sizeof(v_model)); + } + + if (add_usb_device_to_list(dev_type, path, v_model, v_vendor) < 0) { + _E("Failed to add device to dev_list"); + return; + } + + launch_ticker_notification(TICKER_NAME_PRINTER_CONNECTED); +} + +static void printer_device_removed (struct udev_device *dev) +{ + const char *path = NULL; + const char *printer = NULL; + + if (!dev) + return; + + printer = udev_device_get_property_value(dev, UDEV_PROP_SYSTEMD_WANTS); + if (!printer) + return; + if (!strstr(printer, "printer")) + return; + + path = udev_device_get_property_value(dev, UDEV_PROP_DEVPATH); + if (!path) + return; + + if (remove_usb_device_from_list(path, USBHOST_PRINTER) < 0) + return; + + launch_ticker_notification(TICKER_NAME_DEVICE_DISCONNECTED); +} + +static void subsystem_usb_changed (struct udev_device *dev) +{ + const char *action = NULL; + if (!dev) + return; + + if (!is_host_uevent_enabled()) + return; + + action = udev_device_get_property_value(dev, UDEV_PROP_ACTION); + if (!action) + return; + + if (!strncmp(action, "add", strlen("add"))) { + printer_device_added(dev); + return; + } + + if (!strncmp(action, "remove", strlen("remove"))) { + printer_device_removed(dev); + return; + } +} + +const static struct uevent_handler uhs_printer[] = { + { USB_SUBSYSTEM , subsystem_usb_changed , NULL }, +}; + +static int usbhost_printer_init_booting_done(void *data) +{ + int ret, i; + + unregister_notifier(DEVICE_NOTIFIER_BOOTING_DONE, usbhost_printer_init_booting_done); + + for (i = 0 ; i < ARRAY_SIZE(uhs_printer) ; i++) { + ret = register_uevent_control(&uhs_printer[i]); + if (ret < 0) + _E("FAIL: reg_uevent_control()"); + } + + return 0; +} + +static void usbhost_printer_init(void *data) +{ + register_notifier(DEVICE_NOTIFIER_BOOTING_DONE, usbhost_printer_init_booting_done); +} + +static void usbhost_printer_exit(void *data) +{ + int i; + + for (i = 0 ; i < ARRAY_SIZE(uhs_printer) ; i++) { + unregister_uevent_control(&uhs_printer[i]); + } +} + +static const struct device_ops usbhost_device_printer_ops = { + .priority = DEVICE_PRIORITY_NORMAL, + .name = "usbhost_printer", + .init = usbhost_printer_init, + .exit = usbhost_printer_exit, +}; + +DEVICE_OPS_REGISTER(&usbhost_device_printer_ops) diff --git a/src/usb/usb-host-storage-vfat.c b/src/usb/usb-host-storage-vfat.c new file mode 100644 index 0000000..cc2bf78 --- /dev/null +++ b/src/usb/usb-host-storage-vfat.c @@ -0,0 +1,90 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 "core/common.h" +#include "usb-host.h" + +#define VFAT_MOUNT_OPT "uid=5000,gid=5000,dmask=0002,fmask=0002,iocharset=iso8859-1,utf8,shortname=mixed" +#define SMACK_MOUNT_OPT "smackfsroot=*,smackfsdef=*" + +static const char *vfat_check_arg[] = { + "/usr/bin/fsck_msdosfs", + "-pf", NULL, NULL, +}; + +static const char *vfat_arg[] = { + "/sbin/mkfs.vfat", + NULL, NULL, +}; + +static int vfat_check(const char *devname) +{ + int argc; + argc = ARRAY_SIZE(vfat_check_arg); + vfat_check_arg[argc - 2] = devname; + return run_child(argc, vfat_check_arg); +} + +static void get_mount_options(bool smack, char *options, int len) +{ + if (smack) + snprintf(options, len, "%s,%s", VFAT_MOUNT_OPT, SMACK_MOUNT_OPT); + else + snprintf(options, len, "%s", VFAT_MOUNT_OPT); +} + +static int vfat_mount(bool smack, const char *devpath, const char *mount_point) +{ + char options[NAME_MAX]; + get_mount_options(smack, options, sizeof(options)); + return mount(devpath, mount_point, "vfat", 0, options); +} + +static int vfat_mount_rdonly(bool smack, const char *devpath, const char *mount_point) +{ + char options[NAME_MAX]; + get_mount_options(smack, options, sizeof(options)); + return mount(devpath, mount_point, "vfat", MS_RDONLY, options); +} + +static int vfat_format(const char *path) +{ + int argc; + argc = ARRAY_SIZE(vfat_arg); + vfat_arg[argc - 2] = path; + return run_child(argc, vfat_arg); +} + +static const struct storage_fs_ops vfat_ops = { + .name = "vfat", + .check = vfat_check, + .mount = vfat_mount, + .mount_rdonly = vfat_mount_rdonly, + .format = vfat_format, +}; + +static void __CONSTRUCTOR__ vfat_init(void) +{ + register_fs(&vfat_ops); +} diff --git a/src/usb/usb-host-storage.c b/src/usb/usb-host-storage.c new file mode 100755 index 0000000..d51c0cd --- /dev/null +++ b/src/usb/usb-host-storage.c @@ -0,0 +1,1279 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 "usb-host.h" +#include "core/device-notifier.h" +#include +#include +#include +#include +#include + +#define MOUNT_POINT "/opt/storage/usb" +#define FS_TMPFS "tmpfs" +#define SMACKFS_MNT "/smack" +#define SMACKFS_MAGIC 0x43415d53 +#define SIZE_32GB 61315072 + +#define BLOCK_DEVICE_PATH "/sys/block" +#define BLOCK_DEVICE_POLLING_TIME "events_poll_msecs" +#define POLLING_TIME_ABNORMAL 200 +#define POLLING_TIME_NORMAL 500 + +#define RETRY_MAX 5 + +#define SYSTEM_SYSPOPUP "system-syspopup" +#define METHOD_STORAGE_WARNING "UsbotgWarningPopupLaunch" +#define METHOD_WATCHDOG "WatchdogPopupLaunch" +#define METHOD_RECOVERY "RecoveryPopupLaunch" +#define PARAM_MOUNTFAIL "usbotg_mount_failed" +#define PARAM_REMOVED_UNSAFE "usbotg_removed_unsafe" + +#define USBOTG_SYSPOPUP "usbotg-syspopup" +#define METHOD_STORAGE_MOUNT "StoragePopupLaunch" +#define METHOD_CAMERA "CameraPopupLaunch" +#define METHOD_STORAGE_UNMOUNT "StorageUnmountPopupLaunch" +#define PARAM_STORAGE_ADD "storage_add" +#define PARAM_STORAGE_REMOVE "storage_remove" +#define POPUP_KEY_DEVICE_PATH "_DEVICE_PATH_" + +static int parts_num = 0; +static bool mount_flag = false; +static bool path_init = false; + +static bool smack = false; +static dd_list *fs_list = NULL; + +static int pipe_out[2]; + +struct job_data { + int type; + bool safe; + struct usb_device dev; +}; + +static dd_list *storage_job = NULL; +static Ecore_Fd_Handler *pipe_handler; + +static void __CONSTRUCTOR__ smack_check(void) +{ + struct statfs sfs; + int ret; + + do { + ret = statfs(SMACKFS_MNT, &sfs); + } while (ret < 0 && errno == EINTR); + + if (ret == 0 && sfs.f_type == SMACKFS_MAGIC) + smack = true; + _I("smackfs check %d", smack); +} + +void register_fs(const struct storage_fs_ops *ops) +{ + if (!ops) + return; + DD_LIST_APPEND(fs_list, ops); +} + +void unregister_fs(const struct storage_fs_ops *ops) +{ + if (!ops) + return; + DD_LIST_REMOVE(fs_list, ops); +} + +static struct storage_fs_ops *get_fs_ops(char *name) +{ + dd_list *l; + struct storage_fs_ops *ops; + + if (!name) + return NULL; + + DD_LIST_FOREACH(fs_list, l, ops) { + if (!strncmp(ops->name, name, strlen(name))) + return ops; + } + return NULL; +} + +static int get_storage_size(char *name) +{ + int fd, ret; + uint64_t size; + + if (!name) + return -EINVAL; + + if (access(name, F_OK) != 0) + return -EINVAL; + + fd = open(name, O_RDONLY); + if (fd < 0) { + _E("Failed to open (%s) with errno(%d)", name, errno); + return -errno; + } + + if (ioctl(fd, BLKGETSIZE64, &size) < 0) { + _E("Failed to get size of (%s), errno(%d)", name, errno); + size = -errno; + } + + close(fd); + return size; +} + +static int get_block_device_name(const char *devname, char *block, int len) +{ + char *name; + + name = strstr(devname, "sd"); + if (!name) { + _E("Cannot get the device name"); + return -ENOMEM; + } + + snprintf(block, len, "%s", name); + name = block; + while (*name) { + if (*name >= 48 && *name <= 57) { + *name = '\0'; + break; + } + name = name + 1; + } + _I("Block device name: (%s)", block); + + return 0; +} +static int get_block_size(const char *devname) +{ + char block[32]; + char block_size[BUF_MAX]; + char size[32]; + FILE *fp; + int ret; + + ret = get_block_device_name(devname, block, sizeof(block)); + if (ret < 0) { + _E("Failed to get block device name(%s)", devname); + return ret; + } + + snprintf(block_size, sizeof(block_size), "%s/%s/size", BLOCK_DEVICE_PATH, block); + + fp = fopen(block_size, "r"); + if (!fp) { + _E("Failed to open block device size node"); + return -ENOMEM; + } + + ret = fread(size, 1, sizeof(size), fp); + fclose(fp); + if (ret <= 0) { + _E("Cannot read size of block device(%d)", ret); + return -ENOMEM; + } + + return atoi(size); +} + +static int set_block_polling_time(char *devname, int time) +{ + FILE *fp; + char block[32]; + char ptime[32]; + char tpath[BUF_MAX]; + int ret; + + ret = get_block_device_name(devname, block, sizeof(block)); + if (ret < 0) { + _E("Failed to get block device name(%s)", devname); + return ret; + } + + snprintf(ptime, sizeof(ptime), "%d", time); + snprintf(tpath, sizeof(tpath), "%s/%s/%s", + BLOCK_DEVICE_PATH, block, BLOCK_DEVICE_POLLING_TIME); + fp = fopen(tpath, "w"); + if (!fp) { + _E("Failed to open file (%s)", tpath); + return -ENOMEM; + } + + ret = fwrite(ptime, 1, strlen(ptime), fp); + fclose(fp); + if (ret <= 0) { + _E("Failed to write (%s) to file (%s)", ptime, tpath); + return -ENOMEM; + } + + return 0; +} + +static int check_changed_storage(struct udev_device *dev) +{ + const char *devname; + int size; + + if (!dev) + return -EINVAL; + + devname = udev_device_get_property_value(dev, "DEVNAME"); + if (!devname) { + _E("Failed to get device name"); + return -EINVAL; + } + + return get_block_size(devname); +} + +static bool check_storage_exists(struct udev_device *dev) +{ + const char *devname; + char mntpath[BUF_MAX]; + bool same; + int ret; + + if (!dev) + return false; + + devname = udev_device_get_property_value(dev, "DEVNAME"); + if (!devname) { + _E("Failed to get device name"); + return false; + } + + ret = get_mount_path(devname, mntpath, sizeof(mntpath)); + if (ret < 0) { + _E("Cannot get mount path"); + return false; + } + + same = check_same_mntpath(mntpath); + if (!same) + set_block_polling_time((char *)devname, POLLING_TIME_ABNORMAL); + return same; +} + +static int mount_path_init(void) +{ + int ret, retry; + + if (path_init) + return 0; + + if (access(MOUNT_POINT, F_OK) < 0) { + ret = mkdir(MOUNT_POINT, 0755); + if (ret < 0) { + _E("Failed to make directory to mount usb storage"); + return ret; + } + } + + retry = 0; + do { + ret = mount(FS_TMPFS, MOUNT_POINT, FS_TMPFS, 0, ""); + if (ret == 0) + break; + } while (retry ++ < RETRY_MAX); + + if (ret < 0) { + _E("Failed to mount tmpfs to mount point(%s)", MOUNT_POINT); + goto out; + } + + ret = chmod(MOUNT_POINT, 0755); + if (ret < 0) { + _E("Failed to change permission(%d)", MOUNT_POINT); + goto out_unmount; + } + + path_init = true; + return 0; + +out_unmount: + if (umount2(MOUNT_POINT, MNT_DETACH) < 0) + _E("Failed to unmount tmpfs(%s)", MOUNT_POINT); +out: + if (rmdir(MOUNT_POINT) < 0) + _E("Failed to remove directory(%s)", MOUNT_POINT); + + return ret; +} + +static void mount_path_deinit(void) +{ + int ret, retry, len; + dd_list *storage_list, *l; + struct usb_device *dev; + + storage_list = get_storage_list(); + DD_LIST_FOREACH(storage_list, l, dev) { + if (dev->is_mounted == true) + return; + } + + path_init = false; + + if (access(MOUNT_POINT, F_OK) < 0) + return; + + if (umount2(MOUNT_POINT, MNT_DETACH) < 0) + _E("Failed to unmount tmpfs(%s)", MOUNT_POINT); + + if (rmdir(MOUNT_POINT) < 0) + _E("Failed to remove directory(%s)", MOUNT_POINT); + + return; +} + +static void add_partition_number(int num) +{ + if (num <= 0) + return; + + if (parts_num >= 0) { + parts_num += num; + return; + } + + parts_num = num; +} + +static void launch_mount_popup_by_flag(bool success, char *path) +{ + if (parts_num > 0) + parts_num--; + else + parts_num = 0; + + if (success) + mount_flag = true; + + if (parts_num != 0) + return; + + if (mount_flag) + mount_flag = false; + else + launch_host_syspopup(SYSTEM_SYSPOPUP, METHOD_STORAGE_WARNING, + POPUP_KEY_CONTENT, PARAM_MOUNTFAIL, NULL, NULL); +} + +int get_mount_path(const char *name, char *path, int len) +{ + char *dev; + char buf[BUF_MAX]; + + if (!name || !path || len <= 0) + return -EINVAL; + + dev = strstr(name, "/sd"); + if (!dev) + return -ENOMEM; + + dev = dev + 3; + + snprintf(buf, sizeof(buf), "%s", dev); + if (*buf >= 97 && *buf <= 122) + *buf = *buf - 32; + + snprintf(path, len, "%s/UsbDrive%s", MOUNT_POINT, buf); + + return 0; +} + +int get_devname_by_path(char *path, char *name, int len) +{ + char *dev; + char buf[BUF_MAX]; + + if (!path || !name || len <= 0) + return -EINVAL; + + dev = strstr(path, "UsbDrive"); + if (!dev) + return -EINVAL; + + dev = dev + 8; + + snprintf(buf, sizeof(buf), "%s", dev); + if (*buf >= 65 && *buf <= 90) + *buf = *buf + 32; + + snprintf(name, len, "/dev/sd%s", buf); + + return 0; +} + + +static int find_app_accessing_storage(char *path) +{ + const char *argv[7] = {"/sbin/fuser", "-m", "-S", NULL, NULL, NULL}; + int argc; + + if (!path) + return -EINVAL; + + argv[5] = path; + + argc = ARRAY_SIZE(argv); + + return run_child(argc, argv); +} + +static int mount_storage(const char *fstype, const char *devname, char *path) +{ + dd_list *l; + struct storage_fs_ops *ops; + int ret, retry; + + if (!fstype || !devname || !path) + return -EINVAL; + + ret = mount_path_init(); + if (ret < 0) { + _E("Failed to init mount path"); + return ret; + } + + DD_LIST_FOREACH(fs_list, l, ops) { + if (strncmp(ops->name, fstype, strlen(fstype))) + continue; + + ret = mkdir(path, 0755); + if (ret < 0) { + if (errno != EEXIST) { + _E("Failed to make mount path(%s)", path); + return -errno; + } + } + + if (ops->check) { + ret = ops->check(devname); + if (ret < 0) { + _E("Failed to check device file system(%s, %s)", fstype, devname); + goto out; + } + } + + if (!(ops->mount)) { + _E("Cannot mount device"); + ret = -EINVAL; + goto out; + } + + retry = 0; + do { + ret = ops->mount(smack, devname, path); + if (ret == 0 || errno == EROFS) + break; + } while (retry++ < RETRY_MAX); + + if (ret == 0) + return ret; + + if (errno == EROFS && ops->mount_rdonly) { + _I("Read only file system is connected"); + retry = 0; + do { + ret = ops->mount_rdonly(smack, devname, path); + if (ret == 0) { + ret = EROFS; + break; + } + } while (retry++ < RETRY_MAX); + } + + if (ret < 0) { + _E("Failed to mount usb storage (devname: %s, ret: %d, errno: %d)", devname, ret, errno); + goto out; + } + + return ret; + } + + _E("Not supported file system"); + ret = -ENOTSUP; +out: + if (access(path, F_OK) == 0) { + if (rmdir(path) < 0) + _E("Failed to remove dir(%s)", path); + } + return ret; +} + +static int unmount_storage(char *path) +{ + int ret; + + if (!path) + return -EINVAL; + + ret = access(path, F_OK); + if (ret < 0) { + _E("The mount path (%s) does not exist", path); + return ret; + } + + ret = umount2(path, MNT_DETACH); + if (ret < 0) { + _E("Failed to unmount storage (%s), errno(%d)", path, errno); + goto out; + } + + ret = rmdir(path); + if (ret < 0) { + _E("Failed to remove mount path(%d), errno(%d)", path, errno); + goto out; + } + + return 0; + +out: + if (find_app_accessing_storage(path) < 0) + _E("Failed to find apps accessing the storage(%d)", path); + + return ret; +} + +int mount_usb_storage(const char *name) +{ + dd_list *storage_list, *l; + struct usb_device *dev; + bool found; + int ret, mount_type; + + storage_list = get_storage_list(); + if (!storage_list) { + _E("Storage list is NULL"); + return -ENOMEM; + } + + found = false; + DD_LIST_FOREACH(storage_list, l, dev) { + if (strncmp(dev->name, name, strlen(name))) + continue; + found = true; + break; + } + if (!found) { + _E("Cannot find storage whose name is (%s)", name); + return -EINVAL; + } + + if (dev->is_mounted == true) { + _E("(%s) is already mounted", dev->name); + return -ECANCELED; + } + + ret = mount_storage(dev->fs, dev->name, dev->mntpath); + if (ret < 0) { + _E("Failed to mount usb storage(%s, %s, %s): %d", dev->fs, dev->name, dev->mntpath, ret); + launch_mount_popup_by_flag(false, dev->mntpath); + return ret; + } + + if (ret == EROFS) + mount_type = STORAGE_MOUNT_RO; + else + mount_type = STORAGE_MOUNT_RW; + + dev->noti_id = activate_storage_notification(dev->mntpath, mount_type); + dev->is_mounted = true; + + return ret; +} + +static int format_usb_storage(const char *path) +{ + int ret, i; + char name[BUF_MAX]; + dd_list *storage_list, *l; + struct usb_device *dev; + struct storage_fs_ops *fs_ops; + bool found; + + if (!path) + return -EINVAL; + + storage_list = get_storage_list(); + if (!storage_list) { + _E("Storage list is NULL"); + return -ENOMEM; + } + + found = false; + DD_LIST_FOREACH(storage_list, l, dev) { + if (strncmp(dev->mntpath, path, strlen(path))) + continue; + found = true; + break; + } + if (!found) { + _I("Cannot find storage whose name is (%s)", name); + return -ENOENT; + } + + if (dev->is_mounted == true) { + ret = unmount_storage(dev->mntpath); + if (ret < 0) { + _E("Failed to unmount storage(%s): %d", dev->mntpath, ret); + return ret; + } + dev->is_mounted = false; + dev->noti_id = deactivate_storage_notification(dev->noti_id); + } + + fs_ops = get_fs_ops(dev->fs); + if (!fs_ops) { + if (get_storage_size(dev->name) <= SIZE_32GB) + fs_ops = get_fs_ops("vfat"); + else + fs_ops = get_fs_ops("exfat"); + if (!fs_ops) { + _E("Cannot get file system to format"); + return -EINVAL; + } + } + + ret = -1; + if (fs_ops->format) { + i = 0; + do { + ret = fs_ops->format(dev->name); + if (ret < 0) { + _E("Failed to format (%s, %d).. retry(%d)", dev->name, ret, i); + continue; + } + break; + } while (i++ < RETRY_MAX); + } + if (ret < 0) { + _E("Falied to format (%s, %d)", dev->name, ret); + return ret; + } + + ret = mount_usb_storage(dev->name); + if (ret < 0) { + _E("Falied to mount storage(%s): %d", dev->mntpath, ret); + return ret; + } + + return 0; +} + +int unmount_usb_storage(const char *path, bool safe) +{ + int ret; + char name[BUF_MAX]; + dd_list *storage_list, *l; + struct usb_device *dev; + bool found; + + if (!path) + return -EINVAL; + + storage_list = get_storage_list(); + if (!storage_list) { + _E("Storage list is NULL"); + return -ENOMEM; + } + + found = false; + DD_LIST_FOREACH(storage_list, l, dev) { + if (strncmp(dev->mntpath, path, strlen(path))) + continue; + found = true; + break; + } + if (!found) { + _I("Cannot find storage whose name is (%s)", name); + mount_path_deinit(); + return -ENOENT; + } + + if (dev->is_mounted == false) { + _I("(%s) is already unmounted", dev->name); + mount_path_deinit(); + return -ENOENT; + } + + ret = unmount_storage(dev->mntpath); + if (ret < 0) { + _E("Failed to unmount storage(%s): %d", dev->mntpath, ret); + return ret; + } + + dev->is_mounted = false; + dev->noti_id = deactivate_storage_notification(dev->noti_id); + mount_path_deinit(); + + return 0; +} + +static void storage_device_added (struct udev_device *dev) +{ + const char *nparts; + const char *fstype; + const char *devname; + const char *vendor; + const char *model; + char mountpath[BUF_MAX]; + int num, ret; + bool mounted; + int noti_id; + struct usb_device usb_dev; + + if (!dev) + return; + + nparts = udev_device_get_property_value(dev, "NPARTS"); + if (nparts) { + num = atoi(nparts); + if (num > 0) { + add_partition_number(num); + return; + } + } + + fstype = udev_device_get_property_value(dev, "ID_FS_TYPE"); + if (!fstype) { + _E("Failed to get file system type"); + return; + } + + devname = udev_device_get_property_value(dev, "DEVNAME"); + if (!devname) { + _E("Failed to get device name"); + return; + } + + model = udev_device_get_property_value(dev, "ID_MODEL"); + if (!model) + _E("Failed to get model information"); + + vendor = udev_device_get_property_value(dev, "ID_VENDOR"); + if (!vendor) + _E("Failed to get vendor information"); + + snprintf(usb_dev.name, sizeof(usb_dev.name), "%s", devname); + snprintf(usb_dev.fs, sizeof(usb_dev.fs), "%s", fstype); + snprintf(usb_dev.model, sizeof(usb_dev.model), "%s", model); + snprintf(usb_dev.vendor, sizeof(usb_dev.vendor), "%s", vendor); + ret = get_mount_path(devname, usb_dev.mntpath, sizeof(usb_dev.mntpath)); + if (ret < 0) { + _E("Failed to get mount path(%d, %s)", ret, usb_dev.name); + return ; + } + + set_block_polling_time(usb_dev.name, POLLING_TIME_NORMAL); + + ret = add_job(STORAGE_ADD, &usb_dev, true); + if (ret < 0) { + _E("Failed to add job (%d, %s, %d)", STORAGE_ADD, usb_dev.name, ret); + return ; + } + + ret = add_job(STORAGE_MOUNT, &usb_dev, true); + if (ret < 0) + _E("Falied to mount storage (%d, %s, %d)", STORAGE_MOUNT, usb_dev.name, ret); +} + +static void storage_device_removed (struct udev_device *dev) +{ + const char *devname = NULL; + const char *nparts = NULL; + char mountpath[BUF_MAX]; + int ret; + struct usb_device usb_dev; + dd_list *storage_list, *l; + + if (!dev) + return; + + nparts = udev_device_get_property_value(dev, "NPARTS"); + if (nparts) { + ret = atoi(nparts); + if (ret > 0) + return; + if (ret == 0) { + if (!udev_device_get_property_value(dev, "ID_FS_TYPE") + && !udev_device_get_property_value(dev, "DISK_MEDIA_CHANGE")) { + return; + } + } + } + + devname = udev_device_get_property_value(dev, "DEVNAME"); + if (!devname) { + _E("cannot get device name"); + return; + } + + snprintf(usb_dev.name, sizeof(usb_dev.name), "%s", devname); + ret = get_mount_path(devname, usb_dev.mntpath, sizeof(usb_dev.mntpath)); + if (ret < 0) { + _E("Failed to get mount path(%d, %s)", ret, usb_dev.name); + return ; + } + + ret = add_job(STORAGE_UNMOUNT, &usb_dev, false); + if (ret < 0) { + _E("Failed to add job (%d, %s, %d)", STORAGE_UNMOUNT, usb_dev.name, ret); + return ; + } + + ret = add_job(STORAGE_REMOVE, &usb_dev, true); + if (ret < 0) + _E("Falied to mount storage (%d, %s, %d)", STORAGE_REMOVE, usb_dev.name, ret); +} + +static void *start_job(void *data) +{ + int result; + struct job_data *job; + struct usb_device *dev; + + if (DD_LIST_LENGTH(storage_job) <= 0) { + _E("storage job list is NULL"); + result = -1; + goto out; + } + + job = DD_LIST_NTH(storage_job, 0); + if (!job) { + _E("cannot get 0th job"); + result = -1; + goto out; + } + + dev = &(job->dev); + if (!dev) { + _E("job->dev == NULL"); + result = -1; + goto out; + } + + switch (job->type) { + case STORAGE_ADD: + if (check_same_mntpath(dev->mntpath)) + result = -1; + else + result = add_usb_storage_to_list(dev->name, dev->vendor, dev->model, dev->fs); + break; + + case STORAGE_REMOVE: + if (check_same_mntpath(dev->mntpath)) + result = remove_usb_storage_from_list(dev->name); + else + result = -1; + break; + + case STORAGE_MOUNT: + if (is_storage_mounted(dev->mntpath)) + result = -1; + else + result = mount_usb_storage(dev->name); + break; + + case STORAGE_UNMOUNT: + if (is_storage_mounted(dev->mntpath)) + result = unmount_usb_storage(dev->mntpath, job->safe); + else + result = -1; + break; + + case STORAGE_FORMAT: + if (check_same_mntpath(dev->mntpath)) + result = format_usb_storage(dev->mntpath); + else + result = -1; + break; + + default: + _E("Unknown job type (%d)", job->type); + result = -1; + break; + } + + _I("Job(%d, %s) is done: (%d)", job->type, dev->mntpath, result); + +out: + write(pipe_out[1], &result, sizeof(int)); + return NULL; +} + +static int trigger_job(void) +{ + pthread_t th; + int ret; + + if (DD_LIST_LENGTH(storage_job) <= 0) { + return 0; + } + + ret = pthread_create(&th, NULL, start_job, NULL); + if (ret < 0) { + _E("Failed to create pthread"); + return ret; + } + pthread_detach(th); + + return 0; +} + +int add_job(int type, struct usb_device *dev, bool safe) +{ + struct job_data *job; + struct usb_device *usb_dev; + int len; + + len = DD_LIST_LENGTH(storage_job); + + job = (struct job_data *)malloc(sizeof(struct job_data)); + if (!job) { + _E("malloc() failed"); + return -ENOMEM; + } + + job->type = type; + job->safe = safe; + snprintf((job->dev).name, sizeof((job->dev).name), "%s", dev->name); + snprintf((job->dev).mntpath, sizeof((job->dev).mntpath), "%s", dev->mntpath); + snprintf((job->dev).vendor, sizeof((job->dev).vendor), "%s", dev->vendor); + snprintf((job->dev).model, sizeof((job->dev).model), "%s", dev->model); + snprintf((job->dev).fs, sizeof((job->dev).fs), "%s", dev->fs); + + DD_LIST_APPEND(storage_job, job); + + _I("ADD Job(%d, %s, %d)", job->type, (job->dev).name, job->safe); + + if (len > 0) + return 0; + + if (trigger_job() < 0) + _E("Failed to trigger job"); + + + return 0; +} + +static bool check_to_skip_unmount_error(struct usb_device *dev) +{ + dd_list *l; + struct job_data *job; + int i; + + if (!storage_job || DD_LIST_LENGTH(storage_job) <= 0) + return false; + if (!dev) + return false; + + i = 0; + DD_LIST_FOREACH(storage_job, l, job) { + if (i++ == 0) + continue; + if (strncmp((job->dev).mntpath, dev->mntpath, strlen((job->dev).mntpath))) + continue; + + if (job->type == STORAGE_MOUNT) + return true; + } + + return false; +} + +static int send_storage_notification(struct job_data *job, int result) +{ + char *noti_type; + + if (!job) + return -EINVAL; + + if (result < 0 && job->type != STORAGE_FORMAT) + return -EINVAL; + + switch (job->type) { + case STORAGE_ADD: + (job->dev).is_mounted = false; + if (send_storage_changed_info(&(job->dev), "storage_unmount") < 0) + _E("Failed to send signal"); + break; + + case STORAGE_REMOVE: + (job->dev).is_mounted = false; + if (send_storage_changed_info(&(job->dev), "storage_remove") < 0) + _E("Failed to send signal"); + break; + + case STORAGE_FORMAT: + if (result < 0) { + (job->dev).is_mounted = false; + send_msg_storage_removed(true); + if (send_storage_changed_info(&(job->dev), "storage_unmount") < 0) + _E("Failed to send signal"); + break; + } + /* if result >= 0, the notifications are same with storage mount */ + + case STORAGE_MOUNT: + if (result == EROFS) + noti_type = TICKER_NAME_STORAGE_RO_CONNECTED; + else + noti_type = TICKER_NAME_STORAGE_CONNECTED; + + (job->dev).is_mounted = true; + launch_mount_popup_by_flag(true, (job->dev).mntpath); + launch_ticker_notification(noti_type); + send_msg_storage_added(true); + if (send_storage_changed_info(&(job->dev), "storage_mount") < 0) + _E("Failed to send signal"); + launch_host_syspopup(USBOTG_SYSPOPUP, METHOD_STORAGE_MOUNT, + POPUP_KEY_CONTENT, PARAM_STORAGE_ADD, + POPUP_KEY_DEVICE_PATH, (job->dev).mntpath); + break; + + case STORAGE_UNMOUNT: + (job->dev).is_mounted = false; + _I("Safe: (%d)", job->safe ? 1 : 0); + if (job->safe) + launch_ticker_notification(TICKER_NAME_STORAGE_DISCONNECTED_SAFE); + else { + if (!check_to_skip_unmount_error(&(job->dev))) + launch_host_syspopup(SYSTEM_SYSPOPUP, METHOD_STORAGE_WARNING, + POPUP_KEY_CONTENT, PARAM_REMOVED_UNSAFE, NULL, NULL); + } + send_msg_storage_removed(true); + if (send_storage_changed_info(&(job->dev), "storage_unmount") < 0) + _E("Failed to send signal"); + launch_host_syspopup(USBOTG_SYSPOPUP, METHOD_STORAGE_MOUNT, + POPUP_KEY_CONTENT, PARAM_STORAGE_REMOVE, + POPUP_KEY_DEVICE_PATH, (job->dev).mntpath); + + break; + + default: + _E("Invalid job type(%d)", job->type); + return -EINVAL; + } + + return 0; +} + +static void remove_job(int result) +{ + struct job_data *job; + + if (!storage_job || DD_LIST_LENGTH(storage_job) <= 0) { + return ; + } + + job = DD_LIST_NTH(storage_job, 0); + if (!job) { + _E("Failed to get job from the storage_job list"); + return; + } + + if (send_storage_notification(job, result) < 0) + _E("Failed to send notification"); + + _I("Remove Job(%d, %s)", job->type, (job->dev).name); + + DD_LIST_REMOVE(storage_job, job); + free(job); + + if (DD_LIST_LENGTH(storage_job) <= 0) { + _I("REMOVE storage_job FULL"); + DD_LIST_FREE_LIST(storage_job); + storage_job = NULL; + return ; + } + + if (trigger_job() < 0) + _E("Failed to trigger job"); + +} + +static Eina_Bool job_done(void *data, Ecore_Fd_Handler *fd_handler) +{ + int result; + int ret, retry; + + update_usbhost_state(); + + if (!ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ)) { + _E("ecore_main_fd_handler_active_get error , return"); + return EINA_TRUE; + } + + retry = 0; + do { + ret = read(pipe_out[0], &result, sizeof(int)); + if (ret >= 0) + break; + if (errno != EINTR) + goto out; + } while (retry++ < RETRY_MAX); + + + if (result < 0) { + /*Error handling*/ + _E("Job of thread failed (%d)", result); + } + +out: + remove_job(result); + + return EINA_TRUE; +} + +static void subsystem_block_changed (struct udev_device *dev) +{ + const char *action = NULL; + const char *bus = NULL; + int size; + + if (!dev) + return; + + if (!is_host_uevent_enabled()) + return; + + /* Check whether or not the block device is usb device */ + bus = udev_device_get_property_value(dev, "ID_BUS"); + if (!bus) + return; + if (strncmp(bus, "usb", strlen(bus))) + return; + + + action = udev_device_get_property_value(dev, "ACTION"); + if (!action) + return; + + if (!strncmp(action, "add", strlen("add"))) { + send_msg_storage_added(false); + storage_device_added(dev); + return; + } + + if (!strncmp(action, "remove", strlen("remove"))) { + send_msg_storage_removed(false); + storage_device_removed(dev); + return; + } + + if (!strncmp(action, "change", strlen("change"))) { + size = check_changed_storage(dev); + _I("block size(%d)", size); + if (size > 0) { + send_msg_storage_added(false); + storage_device_added(dev); + } else { + if (check_storage_exists(dev)) { + send_msg_storage_removed(false); + storage_device_removed(dev); + } + } + return; + } +} + +static int pipe_start(void) +{ + int ret; + + ret = pipe(pipe_out); + if (ret < 0) { + _E("Failed to make pipe(%d)", ret); + return ret; + } + + pipe_handler = ecore_main_fd_handler_add(pipe_out[0], ECORE_FD_READ, + job_done, NULL, NULL, NULL); + if (!pipe_handler) { + _E("Failed to register pipe handler"); + return -ENOMEM; + } + + return 0; +} + +static void pipe_stop(void) +{ + if (pipe_handler) { + ecore_main_fd_handler_del(pipe_handler); + pipe_handler = NULL; + } + + if (pipe_out[0] >= 0) + close(pipe_out[0]); + if (pipe_out[1] >= 0) + close(pipe_out[1]); +} + +const static struct uevent_handler uhs_storage[] = { + { BLOCK_SUBSYSTEM , subsystem_block_changed , NULL }, +}; + +static int usbhost_storage_init_booting_done(void *data) +{ + int ret, i; + + unregister_notifier(DEVICE_NOTIFIER_BOOTING_DONE, usbhost_storage_init_booting_done); + + for (i = 0 ; i < ARRAY_SIZE(uhs_storage) ; i++) { + ret = register_uevent_control(&uhs_storage[i]); + if (ret < 0) + _E("FAIL: reg_uevent_control()"); + } + + ret = pipe_start(); + if (ret < 0) + _E("Failed to make pipe(%d)", ret); + + return 0; +} + +static void usbhost_storage_init(void *data) +{ + register_notifier(DEVICE_NOTIFIER_BOOTING_DONE, usbhost_storage_init_booting_done); +} + +static void usbhost_storage_exit(void *data) +{ + int i, ret; + + for (i = 0 ; i < ARRAY_SIZE(uhs_storage) ; i++) { + unregister_uevent_control(&uhs_storage[i]); + } + + pipe_stop(); +} + +static const struct device_ops usbhost_device_storage_ops = { + .priority = DEVICE_PRIORITY_NORMAL, + .name = "usbhost_storage", + .init = usbhost_storage_init, + .exit = usbhost_storage_exit, +}; + +DEVICE_OPS_REGISTER(&usbhost_device_storage_ops) diff --git a/src/usb/usb-host.c b/src/usb/usb-host.c new file mode 100755 index 0000000..80c9cf6 --- /dev/null +++ b/src/usb/usb-host.c @@ -0,0 +1,437 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 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 "usb-host.h" +#include "core/device-notifier.h" + +static dd_list *storage_list; +static dd_list *device_list; + +static int noti_id = 0; + +struct ticker_data { + char *name; + int type; +}; + +struct popup_data { + char *name; + char *method; + char *key1; + char *value1; + char *key2; + char *value2; +}; + +/* Do not handle usb host uevents if host_uevent_enable is false + * host_uevent_enable is set to true when usb host connector is connected first*/ +static bool host_uevent_enabled = false; + +bool is_host_uevent_enabled(void) +{ + return host_uevent_enabled; +} + +int get_storage_list_length(void) +{ + return DD_LIST_LENGTH(storage_list); +} + +dd_list *get_storage_list(void) +{ + return storage_list; +} + +dd_list *get_device_list(void) +{ + return device_list; +} + +void launch_ticker_notification(char *name) +{ + struct ticker_data ticker; + const struct device_ops *ticker_ops; + + if (!name) { + _E("ticker noti name is NULL"); + return; + } + + ticker.name = name; + ticker.type = 0; /* WITHOUT_QUEUE */ + + ticker_ops = find_device("ticker"); + + if (ticker_ops && ticker_ops->init) + ticker_ops->init(&ticker); + else + _E("cannot find \"ticker\" ops"); +} + +void launch_host_syspopup(char *name, char *method, + char *key1, char *value1, + char *key2, char *value2) +{ + struct popup_data params; + static const struct device_ops *apps = NULL; + + if (!name || !method) + return; + + if (apps == NULL) { + apps = find_device("apps"); + if (apps == NULL) + return; + } + + params.name = name; + params.method = method; + params.key1 = key1; + params.value1 = value1; + params.key2 = key2; + params.value2 = value2; + + if (apps->init) + apps->init(¶ms); +} + +static int get_number_of_mounted_storages(void) +{ + int num; + dd_list *l; + struct usb_device *dev; + + if (!storage_list || DD_LIST_LENGTH(storage_list) == 0) + return 0; + + num = 0; + DD_LIST_FOREACH(storage_list, l, dev) { + if (dev && dev->is_mounted) + num++; + } + + return num; +} + +void update_usbhost_state(void) +{ + int prev, curr; + + if (vconf_get_int(VCONFKEY_SYSMAN_USB_HOST_STATUS, &prev) != 0) + prev = -1; + + if (get_number_of_mounted_storages() == 0 + && (!device_list || DD_LIST_LENGTH(device_list) == 0)) + curr = VCONFKEY_SYSMAN_USB_HOST_DISCONNECTED; + else + curr = VCONFKEY_SYSMAN_USB_HOST_CONNECTED; + + if (prev == curr) + return; + + if (vconf_set_int(VCONFKEY_SYSMAN_USB_HOST_STATUS, curr) != 0) + _E("Failed to set vconf key"); +} + +bool check_same_mntpath(const char *mntpath) +{ + dd_list *l; + struct usb_device *dev; + + DD_LIST_FOREACH(storage_list, l, dev) { + if (!strncmp(dev->mntpath, mntpath, strlen(dev->mntpath))) + return true; + } + return false; +} + +bool is_storage_mounted(const char *mntpath) +{ + dd_list *l; + struct usb_device *dev; + + DD_LIST_FOREACH(storage_list, l, dev) { + if (!strncmp(dev->mntpath, mntpath, strlen(dev->mntpath))) + break; + } + if (l && dev) + return dev->is_mounted; + return false; +} + +static int add_usb_host_device_to_list(int type, + const char *name, + const char *vendor, + const char *model, + const char *fstype, + char *path) +{ + struct usb_device *dev; + int id; + + if (!name || type < 0) + return -EINVAL; + + if (type == USBHOST_STORAGE && !path) + return -EINVAL; + + dev = (struct usb_device *)malloc(sizeof(struct usb_device)); + if (!dev) { + _E("Failed to assign memory"); + return -ENOMEM; + } + + dev->type = type; + dev->is_mounted = false; + dev->noti_id = 0; + snprintf(dev->name, sizeof(dev->name), "%s", name); + snprintf(dev->mntpath, sizeof(dev->mntpath), "%s", path); + + if (model) + snprintf(dev->model, sizeof(dev->model), "%s", model); + else + memset(dev->model, 0, sizeof(dev->model)); + + if (vendor) + snprintf(dev->vendor, sizeof(dev->vendor), "%s", vendor); + else + memset(dev->vendor, 0, sizeof(dev->vendor)); + + if (fstype) + snprintf(dev->fs, sizeof(dev->fs), "%s", fstype); + else + memset(dev->fs, 0, sizeof(dev->fs)); + + if (type == USBHOST_STORAGE) { + if (!check_same_mntpath(path)) + DD_LIST_APPEND(storage_list, dev); + else + free(dev); + } else { + dev->noti_id = activate_device_notification(dev, DD_LIST_LENGTH(device_list)); + DD_LIST_APPEND(device_list, dev); + if (send_device_added_info(dev) < 0) + _E("Failed to send device info"); + } + + return 0; +} + +int add_usb_storage_to_list(const char *name, + const char *vendor, + const char *model, + const char *fstype) +{ + char path[BUF_MAX]; + int ret; + + if (!name) + return -EINVAL; + + ret = get_mount_path(name, path, sizeof(path)); + if (ret < 0) { + _E("Failed to get mount path"); + return ret; + } + + ret = add_usb_host_device_to_list(USBHOST_STORAGE, + name, vendor, model, fstype, path); + + update_usbhost_state(); + + return ret; +} + +int add_usb_device_to_list(int type, + const char *name, + const char *vendor, + const char *model) +{ + int ret; + + ret = add_usb_host_device_to_list(type, + name, vendor, model, NULL, NULL); + + update_usbhost_state(); + + return ret; +} + +int remove_usb_storage_from_list(const char *name) +{ + dd_list *l; + struct usb_device *dev; + bool found; + + if (!name) + return -EINVAL; + + found = false; + DD_LIST_FOREACH(storage_list, l, dev) { + if (strncmp(dev->name, name, strlen(name))) + continue; + + found = true; + break; + } + if (!found) { + return -EINVAL; + } + + DD_LIST_REMOVE(storage_list, dev); + free(dev); + + update_usbhost_state(); + + return 0; +} + +int remove_usb_device_from_list(const char *name, int type) +{ + dd_list *l; + struct usb_device *dev; + bool found; + int len; + + if (!name) + return -EINVAL; + + found = false; + DD_LIST_FOREACH(device_list, l, dev) { + if (type == USBHOST_PRINTER) { + if (!strstr(name, dev->name)) + continue; + } else { + if (strncmp(dev->name, name, strlen(name))) + continue; + } + + found = true; + break; + } + if (!found) { + return -EINVAL; + } + + if (send_device_removed_info(dev) < 0) + _E("Failed to send device info"); + + DD_LIST_REMOVE(device_list, dev); + free(dev); + + len = DD_LIST_LENGTH(device_list); + if (len <= 0) + dev = NULL; + else + dev = DD_LIST_NTH(device_list, 0); /* First element */ + + if (deactivate_device_notification(dev, len)) + _E("Failed to remove notification"); + + update_usbhost_state(); + + return 0; +} + +static void subsystem_host_changed (struct udev_device *dev) +{ + const char *state = NULL; + int ret; + static int cradle; + + state = udev_device_get_property_value(dev, UDEV_PROP_KEY_STATE); + if (!state) + return; + + if (!strncmp(state, UDEV_PROP_VALUE_ADD, strlen(UDEV_PROP_VALUE_ADD))) { + _I("USB host connector is added"); + + if (!host_uevent_enabled) + host_uevent_enabled = true; + + cradle = get_cradle_status(); + if (cradle == 0) { + launch_ticker_notification(TICKER_NAME_CONNECTOR_CONNECTED); + } + + return; + } + + if (!strncmp(state, UDEV_PROP_VALUE_REMOVE, strlen(UDEV_PROP_VALUE_REMOVE))) { + _I("USB host connector is removed"); + + if (cradle == 0) { + launch_ticker_notification(TICKER_NAME_CONNECTOR_DISCONNECTED); + } else { + cradle = 0; + } + + return; + } +} + +const static struct uevent_handler uhs[] = { + { HOST_SUBSYSTEM , subsystem_host_changed , NULL }, +}; + +static int usbhost_init_booting_done(void *data) +{ + int ret, i; + + unregister_notifier(DEVICE_NOTIFIER_BOOTING_DONE, usbhost_init_booting_done); + + for (i = 0 ; i < ARRAY_SIZE(uhs) ; i++) { + ret = register_uevent_control(&uhs[i]); + if (ret < 0) + _E("FAIL: reg_uevent_control()"); + } + + if (register_unmount_signal_handler() < 0) + _E("Failed to register handler for unmount signal"); + + if (register_device_all_signal_handler() < 0) + _E("Failed to register handler for device info"); + + if (register_usbhost_dbus_methods() < 0) + _E("Failed to register dbus handler for usbhost"); + + return 0; +} + +static void usbhost_init(void *data) +{ + register_notifier(DEVICE_NOTIFIER_BOOTING_DONE, usbhost_init_booting_done); +} + +static void usbhost_exit(void *data) +{ + int i; + + for (i = 0 ; i < ARRAY_SIZE(uhs) ; i++) { + unregister_uevent_control(&uhs[i]); + } +} + +static const struct device_ops usbhost_device_ops = { + .priority = DEVICE_PRIORITY_NORMAL, + .name = "usbhost", + .init = usbhost_init, + .exit = usbhost_exit, +}; + +DEVICE_OPS_REGISTER(&usbhost_device_ops) diff --git a/src/usb/usb-host.h b/src/usb/usb-host.h new file mode 100755 index 0000000..a89d9b8 --- /dev/null +++ b/src/usb/usb-host.h @@ -0,0 +1,179 @@ +/* + * deviced + * + * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __USB_HOST_H__ +#define __USB_HOST_H__ + +#include +#include "core/udev.h" +#include "core/log.h" +#include "core/devices.h" +#include "display/poll.h" +#include "core/udev.h" +#include "core/common.h" +#include "core/list.h" +#include "usb-common.h" + +#define BLOCK_SUBSYSTEM "block" +#define INPUT_SUBSYSTEM "input" +#define USB_SUBSYSTEM "usb" + +#define UDEV_PROP_KEY_STATE "STATE" +#define UDEV_PROP_VALUE_ADD "ADD" +#define UDEV_PROP_VALUE_REMOVE "REMOVE" + +#define TICKER_NAME_CONNECTOR_CONNECTED "connector-connected" +#define TICKER_NAME_CONNECTOR_DISCONNECTED "connector-disconnected" +#define TICKER_NAME_STORAGE_CONNECTED "storage-connected" +#define TICKER_NAME_STORAGE_RO_CONNECTED "storage-ro-connected" +#define TICKER_NAME_STORAGE_DISCONNECTED_SAFE "storage-disconnected-safe" +#define TICKER_NAME_STORAGE_DISCONNECTED_UNSAFE "storage-disconnected-unsafe" +#define TICKER_NAME_KEYBOARD_CONNECTED "keyboard-connected" +#define TICKER_NAME_MOUSE_CONNECTED "mouse-connected" +#define TICKER_NAME_CAMERA_CONNECTED "camera-connected" +#define TICKER_NAME_PRINTER_CONNECTED "printer-connected" +#define TICKER_NAME_DEVICE_DISCONNECTED "device-disconnected" + +#define BUF_MAX 256 +#define RETRY_MAX 5 + +enum action_type { + STORAGE_ADD, + STORAGE_REMOVE, + STORAGE_MOUNT, + STORAGE_UNMOUNT, + STORAGE_FORMAT, +}; + +struct pipe_data { + int type; + int result; + void *data; +}; + +struct usb_device { + int type; + char name[BUF_MAX]; + char mntpath[BUF_MAX]; + char vendor[BUF_MAX]; + char model[BUF_MAX]; + char fs[BUF_MAX]; + bool is_mounted; + int noti_id; +}; + +struct storage_fs_ops { + char *name; + int (*check)(const char *devname); + int (*mount)(bool smack, const char *devname, const char *mount_point); + int (*mount_rdonly)(bool smack, const char *devname, const char *mount_point); + int (*format)(const char *path); +}; + +enum usb_host_type { + USBHOST_KEYBOARD, + USBHOST_MOUSE, + USBHOST_STORAGE, + USBHOST_CAMERA, + USBHOST_PRINTER, + USBHOST_UNKNOWN, + /* add type of usb host */ + USBHOST_TYPE_MAX, +}; + +enum mount_type { + STORAGE_MOUNT_RW, + STORAGE_MOUNT_RO, +}; + +enum device_state { + DEVICE_DISCONNECTED = 0, + DEVICE_CONNECTED = 1, +}; + +void launch_ticker_notification(char *name); +bool is_host_uevent_enabled(void); +dd_list *get_device_list(void); +dd_list *get_storage_list(void); +int get_mount_path(const char *name, char *path, int len); +int get_devname_by_path(char *path, char *name, int len); +bool check_same_mntpath(const char *mntpath); +bool is_storage_mounted(const char *mntpath); +void update_usbhost_state(void); + +void register_fs(const struct storage_fs_ops *ops); +void unregister_fs(const struct storage_fs_ops *ops); + +int get_storage_list_length(void); + +/* Add/Remove usb storage to list */ +int add_usb_storage_to_list(const char *name, + const char *vendor, + const char *model, + const char *fstype); +int remove_usb_storage_from_list(const char *name); + +/* Add/Remove usb device to list */ +int add_usb_device_to_list(int type, + const char *name, + const char *vendor, + const char *model); +int remove_usb_device_from_list(const char *name, int type); + +/* Mount/Unmount usb storge */ +int mount_usb_storage(const char *name); +int unmount_usb_storage(const char *path, bool safe); + +void launch_host_syspopup(char *name, char *method, + char *key1, char *value1, char *key2, char *value2); + +/* Thread Job */ +int add_job(int type, struct usb_device *dev, bool safe); + +/* Device changed signal */ +void send_msg_storage_added(bool mount); +void send_msg_storage_removed(bool mount); +void send_msg_keyboard_added(void); +void send_msg_keyboard_removed(void); +void send_msg_mouse_added(void); +void send_msg_mouse_removed(void); +void send_msg_camera_added(void); +void send_msg_camera_removed(void); + +/* Ongoing notification */ +int activate_storage_notification(char *path, int mount_type); +int deactivate_storage_notification(int id); +int activate_device_notification(struct usb_device *dev, int len); +int deactivate_device_notification(struct usb_device *dev, int len); + +/* Unmount signal handler */ +int register_unmount_signal_handler(void); +int unmount_storage_by_dbus_signal(char *path); + +/* device info signal handler */ +int register_device_all_signal_handler(void); +int send_device_added_info(struct usb_device *dev); +int send_device_removed_info(struct usb_device *dev); +int register_usbhost_dbus_methods(void); +int send_storage_changed_info(struct usb_device *dev, char *type); + +/* Vendor, model name */ +int verify_vendor_name(const char *vendor, char *buf, int len); +int verify_model_name(const char *model, char *vendor, char *buf, int len); + +#endif /* __USB_HOST_H__ */ diff --git a/test/_export_env.sh b/test/_export_env.sh new file mode 100755 index 0000000..72a11ec --- /dev/null +++ b/test/_export_env.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +. ./config +export TET_INSTALL_PATH=$TET_INSTALL_HOST_PATH # tetware root path +export TET_TARGET_PATH=$TET_INSTALL_PATH/tetware-target # tetware target path +export PATH=$TET_TARGET_PATH/bin:$PATH +export LD_LIBRARY_PATH=$TET_TARGET_PATH/lib/tet3:$LD_LIBRARY_PATH +export TET_ROOT=$TET_TARGET_PATH diff --git a/test/_export_target_env.sh b/test/_export_target_env.sh new file mode 100755 index 0000000..5ddaa53 --- /dev/null +++ b/test/_export_target_env.sh @@ -0,0 +1,7 @@ +#!/bin/sh +. ./config +export TET_INSTALL_PATH=$TET_INSTALL_TARGET_PATH # path to path +export TET_TARGET_PATH=$TET_INSTALL_PATH/tetware-target +export PATH=$TET_TARGET_PATH/bin:$PATH +export LD_LIBRARY_PATH=$TET_TARGET_PATH/lib/tet3:$LD_LIBRARY_PATH +export TET_ROOT=$TET_TARGET_PATH diff --git a/test/build.sh b/test/build.sh new file mode 100755 index 0000000..d58c039 --- /dev/null +++ b/test/build.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +. ./_export_env.sh # setting environment variables + +export TET_SUITE_ROOT=`pwd` +FILE_NAME_EXTENSION=`date +%s` + +RESULT_DIR=results +HTML_RESULT=$RESULT_DIR/build-tar-result-$FILE_NAME_EXTENSION.html +JOURNAL_RESULT=$RESULT_DIR/build-tar-result-$FILE_NAME_EXTENSION.journal + +mkdir -p $RESULT_DIR + +tcc -c -p ./ +tcc -b -j $JOURNAL_RESULT -p ./ +grw -c 3 -f chtml -o $HTML_RESULT $JOURNAL_RESULT diff --git a/test/clean.sh b/test/clean.sh new file mode 100755 index 0000000..29743e0 --- /dev/null +++ b/test/clean.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +. ./_export_env.sh # setting environment variables + +export TET_SUITE_ROOT=`pwd` +RESULT_DIR=results + +tcc -c -p ./ # executing tcc, with clean option (-c) +rm -r $RESULT_DIR +rm -r tet_tmp_dir +rm testcase/tet_captured diff --git a/test/config b/test/config new file mode 100644 index 0000000..457c529 --- /dev/null +++ b/test/config @@ -0,0 +1,3 @@ +PKG_NAME=deviced +TET_INSTALL_HOST_PATH=/var/tmp/dts_fw/TETware +TET_INSTALL_TARGET_PATH=/opt/home/TETware diff --git a/test/execute.sh b/test/execute.sh new file mode 100755 index 0000000..a4f6095 --- /dev/null +++ b/test/execute.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +. ./_export_target_env.sh # setting environment variables + +export TET_SUITE_ROOT=`pwd` +FILE_NAME_EXTENSION=`date +%s` + +RESULT_DIR=results +HTML_RESULT=$RESULT_DIR/exec-tar-result-$FILE_NAME_EXTENSION.html +JOURNAL_RESULT=$RESULT_DIR/exec-tar-result-$FILE_NAME_EXTENSION.journal + +mkdir -p $RESULT_DIR + +tcc -e -j $JOURNAL_RESULT -p ./ +grw -c 3 -f chtml -o $HTML_RESULT $JOURNAL_RESULT diff --git a/test/push.sh b/test/push.sh new file mode 100755 index 0000000..2bbab27 --- /dev/null +++ b/test/push.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +. ./config + +TC_PATH=/opt/home/$PKG_NAME + +echo $TC_PATH + +sdb root on +sdb shell "mkdir -p $TC_PATH" +sdb push . $TC_PATH diff --git a/test/testcase/Makefile b/test/testcase/Makefile new file mode 100644 index 0000000..db70570 --- /dev/null +++ b/test/testcase/Makefile @@ -0,0 +1,28 @@ +CC = gcc + +C_FILES = $(shell ls *.c) + +PKGS = deviced + +#TET_ROOT = /home/idkiller/work/tetware/TETware/tetware-target + +LDFLAGS += $(TET_ROOT)/lib/tet3/tcm_s.o +LDFLAGS += -L$(TET_ROOT)/lib/tet3 -ltcm_s +LDFLAGS += -L$(TET_ROOT)/lib/tet3 -lapi_s +LDFLAGS += `pkg-config --libs $(PKGS)` + +CFLAGS += `pkg-config --cflags $(PKGS)` +CFLAGS += -I. +CFLAGS += -I$(TET_ROOT)/inc/tet3 +CFLAGS += -Wall + +#TARGETS = $(C_FILES:%.c=tc-%) +TCS := $(shell ls -1 *.c | cut -d. -f1) + +all: $(TCS) + +%: %.c + $(CC) -o $@ $< $(CFLAGS) $(LDFLAGS) + +clean: + rm -f $(TCS) diff --git a/test/testcase/tslist b/test/testcase/tslist new file mode 100644 index 0000000..cc10762 --- /dev/null +++ b/test/testcase/tslist @@ -0,0 +1,10 @@ +/testcase/utc_system_deviced_battery +/testcase/utc_system_deviced_control +/testcase/utc_system_deviced_deviced +/testcase/utc_system_deviced_deviced_managed +/testcase/utc_system_deviced_display +/testcase/utc_system_deviced_haptic +/testcase/utc_system_deviced_led +/testcase/utc_system_deviced_mmc +/testcase/utc_system_deviced_storage + diff --git a/test/testcase/utc_system_deviced_battery.c b/test/testcase/utc_system_deviced_battery.c new file mode 100644 index 0000000..83eea6a --- /dev/null +++ b/test/testcase/utc_system_deviced_battery.c @@ -0,0 +1,101 @@ +/* + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * PROPRIETARY/CONFIDENTIAL + * + * This software is the confidential and proprietary information of SAMSUNG + * ELECTRONICS ("Confidential Information"). You agree and acknowledge that + * this software is owned by Samsung and you shall not disclose such + * Confidential Information and shall use it only in accordance with the terms + * of the license agreement you entered into with SAMSUNG ELECTRONICS. SAMSUNG + * make no representations or warranties about the suitability of the software, + * either express or implied, including but not limited to the implied + * warranties of merchantability, fitness for a particular purpose, or + * non-infringement. SAMSUNG shall not be liable for any damages suffered by + * licensee arising out of or related to this software. + * + */ +#include +#include + +#define API_NAME_BATTERY_GET_PERCENT "battery_get_percent" +#define API_NAME_BATTERY_GET_PERCENT_RAW "battery_get_percent_raw" +#define API_NAME_BATTERY_IS_FULL "battery_is_full" +#define API_NAME_BATTERY_GET_HEALTH "battery_get_health" + +static void startup(void); +static void cleanup(void); + +void (*tet_startup)(void) = startup; +void (*tet_cleanup)(void) = cleanup; + + +static void utc_system_deviced_battery_get_percent_p(void); +static void utc_system_deviced_battery_get_percent_raw_p(void); +static void utc_system_deviced_battery_is_full_p(void); +static void utc_system_deviced_battery_get_health_p(void); + +enum { + POSITIVE_TC_IDX = 0x01, + NEGATIVE_TC_IDX, +}; + +struct tet_testlist tet_testlist[] = { + { utc_system_deviced_battery_get_percent_p, POSITIVE_TC_IDX }, + { utc_system_deviced_battery_get_percent_raw_p, POSITIVE_TC_IDX }, + { utc_system_deviced_battery_is_full_p, POSITIVE_TC_IDX }, + { utc_system_deviced_battery_get_health_p, POSITIVE_TC_IDX }, + { NULL, 0 }, +}; + +static void startup(void) +{ +} + +static void cleanup(void) +{ +} + +/** + * @brief Positive test case of battery_get_percent() + */ +static void utc_system_deviced_battery_get_percent_p(void) +{ + int ret; + + ret = battery_get_percent(); + dts_check_ge(API_NAME_BATTERY_GET_PERCENT, ret, 0); +} + +/** + * @brief Positive test case of battery_get_percent_raw() + */ +static void utc_system_deviced_battery_get_percent_raw_p(void) +{ + int ret; + + ret = battery_get_percent_raw(); + dts_check_ge(API_NAME_BATTERY_GET_PERCENT_RAW, ret, 0); +} + +/** + * @brief Positive test case of battery_is_full() + */ +static void utc_system_deviced_battery_is_full_p(void) +{ + int ret; + + ret = battery_is_full(); + dts_check_ge(API_NAME_BATTERY_IS_FULL, ret, 0); +} + +/** + * @brief Positive test case of battery_get_health() + */ +static void utc_system_deviced_battery_get_health_p(void) +{ + int ret; + + ret = battery_get_health(); + dts_check_ge(API_NAME_BATTERY_GET_HEALTH, ret, 0); +} diff --git a/test/testcase/utc_system_deviced_control.c b/test/testcase/utc_system_deviced_control.c new file mode 100644 index 0000000..ab12ade --- /dev/null +++ b/test/testcase/utc_system_deviced_control.c @@ -0,0 +1,141 @@ +/* + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * PROPRIETARY/CONFIDENTIAL + * + * This software is the confidential and proprietary information of SAMSUNG + * ELECTRONICS ("Confidential Information"). You agree and acknowledge that + * this software is owned by Samsung and you shall not disclose such + * Confidential Information and shall use it only in accordance with the terms + * of the license agreement you entered into with SAMSUNG ELECTRONICS. SAMSUNG + * make no representations or warranties about the suitability of the software, + * either express or implied, including but not limited to the implied + * warranties of merchantability, fitness for a particular purpose, or + * non-infringement. SAMSUNG shall not be liable for any damages suffered by + * licensee arising out of or related to this software. + * + */ +#include +#include + +#define API_NAME_DEVICED_MMC_CONTROL "deviced_mmc_control" +#define API_NAME_DEVICED_USB_CONTROL "deviced_usb_control" +#define API_NAME_DEVICED_GET_USB_CONTROL "deviced_get_usb_control" +#define API_NAME_DEVICED_RGBLED_CONTROL "deviced_rgbled_control" + +static void startup(void); +static void cleanup(void); + +void (*tet_startup)(void) = startup; +void (*tet_cleanup)(void) = cleanup; + + +static void utc_system_deviced_deviced_mmc_control_p_1(void); +static void utc_system_deviced_deviced_mmc_control_p_2(void); +static void utc_system_deviced_deviced_usb_control_p_1(void); +static void utc_system_deviced_deviced_usb_control_p_2(void); +static void utc_system_deviced_deviced_get_usb_control_p(void); +static void utc_system_deviced_deviced_rgbled_control_p_1(void); +static void utc_system_deviced_deviced_rgbled_control_p_2(void); +static void utc_system_deviced_deviced_rgbled_control_n(void); + +enum { + POSITIVE_TC_IDX = 0x01, + NEGATIVE_TC_IDX, +}; + +struct tet_testlist tet_testlist[] = { + { utc_system_deviced_deviced_mmc_control_p_1, POSITIVE_TC_IDX }, + { utc_system_deviced_deviced_mmc_control_p_2, POSITIVE_TC_IDX }, +// { utc_system_deviced_deviced_usb_control_p_1, POSITIVE_TC_IDX }, +// { utc_system_deviced_deviced_usb_control_p_2, POSITIVE_TC_IDX }, + { utc_system_deviced_deviced_get_usb_control_p, POSITIVE_TC_IDX }, + { utc_system_deviced_deviced_rgbled_control_p_1, POSITIVE_TC_IDX }, + { utc_system_deviced_deviced_rgbled_control_p_2, POSITIVE_TC_IDX }, + { NULL, 0 }, +}; + +static void startup(void) +{ +} + +static void cleanup(void) +{ +} + +/** + * @brief Positive test case of deviced_mmc_control() + */ +static void utc_system_deviced_deviced_mmc_control_p_1(void) +{ + int ret; + + ret = deviced_mmc_control(false); + dts_check_eq(API_NAME_DEVICED_MMC_CONTROL, ret, 0, "Disable MMC"); +} + +/** + * @brief Positive test case of deviced_mmc_control() + */ +static void utc_system_deviced_deviced_mmc_control_p_2(void) +{ + int ret; + + ret = deviced_mmc_control(true); + dts_check_eq(API_NAME_DEVICED_MMC_CONTROL, ret, 0, "Enable MMC"); +} + +/** + * @brief Positive test case of deviced_usb_control() + */ +static void utc_system_deviced_deviced_usb_control_p_1(void) +{ + int ret; + + ret = deviced_usb_control(false); + dts_check_eq(API_NAME_DEVICED_USB_CONTROL, ret, 0, "Disable USB"); +} + +/** + * @brief Positive test case of deviced_usb_control() + */ +static void utc_system_deviced_deviced_usb_control_p_2(void) +{ + int ret; + + ret = deviced_usb_control(true); + dts_check_eq(API_NAME_DEVICED_USB_CONTROL, ret, 0, "Enable USB"); +} + +/** + * @brief Positive test case of deviced_get_usb_control() + */ +static void utc_system_deviced_deviced_get_usb_control_p(void) +{ + int ret; + + ret = deviced_get_usb_control(); + dts_check_ge(API_NAME_DEVICED_GET_USB_CONTROL, ret, 0); +} + +/** + * @brief Positive test case of deviced_rgbled_control() + */ +static void utc_system_deviced_deviced_rgbled_control_p_1(void) +{ + int ret; + + ret = deviced_rgbled_control(false); + dts_check_eq(API_NAME_DEVICED_RGBLED_CONTROL, ret, 0, "Disable RGB led"); +} + +/** + * @brief Positive test case of deviced_rgbled_control() + */ +static void utc_system_deviced_deviced_rgbled_control_p_2(void) +{ + int ret; + + ret = deviced_rgbled_control(true); + dts_check_eq(API_NAME_DEVICED_USB_CONTROL, ret, 0, "Enable RGB led"); +} diff --git a/test/testcase/utc_system_deviced_deviced.c b/test/testcase/utc_system_deviced_deviced.c new file mode 100644 index 0000000..6782bbf --- /dev/null +++ b/test/testcase/utc_system_deviced_deviced.c @@ -0,0 +1,714 @@ +/* + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * PROPRIETARY/CONFIDENTIAL + * + * This software is the confidential and proprietary information of SAMSUNG + * ELECTRONICS ("Confidential Information"). You agree and acknowledge that + * this software is owned by Samsung and you shall not disclose such + * Confidential Information and shall use it only in accordance with the terms + * of the license agreement you entered into with SAMSUNG ELECTRONICS. SAMSUNG + * make no representations or warranties about the suitability of the software, + * either express or implied, including but not limited to the implied + * warranties of merchantability, fitness for a particular purpose, or + * non-infringement. SAMSUNG shall not be liable for any damages suffered by + * licensee arising out of or related to this software. + * + */ +#include +#include + +#define API_NAME_DEVICED_GET_CMDLINE_NAME "deviced_get_cmdline_name" +#define API_NAME_DEVICED_GET_APPPATH "deviced_get_apppath" +#define API_NAME_DEVICED_CONF_SET_MEMPOLICY "deviced_conf_set_mempolicy" +#define API_NAME_DEVICED_CONF_SET_MEMPOLICY_BYPID "deviced_conf_set_mempolicy_bypid" +#define API_NAME_DEVICED_CONF_SET_PERMANENT "deviced_conf_set_permanent" +#define API_NAME_DEVICED_CONF_SET_PERMANENT_BYPID "deviced_conf_set_permanent_bypid" +#define API_NAME_DEVICED_CONF_SET_VIP "deviced_conf_set_vip" +#define API_NAME_DEVICED_CONF_IS_VIP "deviced_conf_is_vip" +#define API_NAME_DEVICED_SET_TIMEZONE "deviced_set_timezone" +#define API_NAME_DEVICED_INFORM_FOREGRD "deviced_inform_foregrd" +#define API_NAME_DEVICED_INFORM_BACKGRD "deviced_inform_backgrd" +#define API_NAME_DEVICED_INFORM_ACTIVE "deviced_inform_active" +#define API_NAME_DEVICED_INFORM_INACTIVE "deviced_inform_active" +#define API_NAME_DEVICED_REQUEST_POWEROFF "deviced_request_poweroff" +#define API_NAME_DEVICED_REQUEST_ENTERSLEEP "deviced_request_entersleep" +#define API_NAME_DEVICED_REQUEST_LEAVESLEEP "deviced_request_leavesleep" +#define API_NAME_DEVICED_REQUEST_REBOOT "deviced_request_reboot" +#define API_NAME_DEVICED_REQUEST_SET_CPU_MAX_FREQUENCY "deviced_request_set_cpu_max_frequency" +#define API_NAME_DEVICED_REQUEST_SET_CPU_MIN_FREQUENCY "deviced_request_set_cpu_min_frequency" +#define API_NAME_DEVICED_RELEASE_CPU_MAX_FREQUENCY "deviced_release_cpu_max_frequency" +#define API_NAME_DEVICED_RELEASE_CPU_MIN_FREQUENCY "deviced_release_cpu_min_frequency" +#define API_NAME_DEVICED_REQUEST_SET_FACTORY_MODE "deviced_request_set_factory_mode" +#define API_NAME_DEVICED_REQUEST_DUMP_LOG "deviced_request_dump_log" +#define API_NAME_DEVICED_REQUEST_DELETE_DUMP "deviced_request_delete_dump" + +static void startup(void); +static void cleanup(void); + +void (*tet_startup)(void) = startup; +void (*tet_cleanup)(void) = cleanup; + + +static void utc_system_deviced_deviced_get_cmdline_name_p(void); +static void utc_system_deviced_deviced_get_cmdline_name_n_1(void); +static void utc_system_deviced_deviced_get_cmdline_name_n_2(void); +static void utc_system_deviced_deviced_get_cmdline_name_n_3(void); +static void utc_system_deviced_deviced_get_apppath_p(void); +static void utc_system_deviced_deviced_get_apppath_n_1(void); +static void utc_system_deviced_deviced_get_apppath_n_2(void); +static void utc_system_deviced_deviced_get_apppath_n_3(void); +static void utc_system_deviced_deviced_conf_set_mempolicy_p(void); +static void utc_system_deviced_deviced_conf_set_mempolicy_n(void); +static void utc_system_deviced_deviced_conf_set_mempolicy_bypid_p(void); +static void utc_system_deviced_deviced_conf_set_mempolicy_bypid_n_1(void); +static void utc_system_deviced_deviced_conf_set_mempolicy_bypid_n_2(void); +static void utc_system_deviced_deviced_conf_set_permanent_p(void); +static void utc_system_deviced_deviced_conf_set_permanent_bypid_p(void); +static void utc_system_deviced_deviced_conf_set_permanent_bypid_n(void); +static void utc_system_deviced_deviced_conf_set_vip_p(void); +static void utc_system_deviced_deviced_conf_set_vip_n(void); +static void utc_system_deviced_deviced_conf_is_vip_p(void); +static void utc_system_deviced_deviced_conf_is_vip_n(void); +static void utc_system_deviced_deviced_set_timezone_p(void); +static void utc_system_deviced_deviced_set_timezone_n(void); +static void utc_system_deviced_deviced_inform_foregrd_p(void); +static void utc_system_deviced_deviced_inform_backgrd_p(void); +static void utc_system_deviced_deviced_inform_active_p(void); +static void utc_system_deviced_deviced_inform_active_n(void); +static void utc_system_deviced_deviced_inform_inactive_p(void); +static void utc_system_deviced_deviced_inform_inactive_n(void); +static void utc_system_deviced_deviced_request_poweroff_p(void); +static void utc_system_deviced_deviced_request_entersleep_p(void); +static void utc_system_deviced_deviced_request_leavesleep_p(void); +static void utc_system_deviced_deviced_request_reboot_p(void); +static void utc_system_deviced_deviced_request_set_cpu_max_frequency_p(void); +static void utc_system_deviced_deviced_request_set_cpu_max_frequency_n(void); +static void utc_system_deviced_deviced_request_set_cpu_min_frequency_p(void); +static void utc_system_deviced_deviced_request_set_cpu_min_frequency_n(void); +static void utc_system_deviced_deviced_release_cpu_max_frequency_p(void); +static void utc_system_deviced_deviced_release_cpu_min_frequency_p(void); +static void utc_system_deviced_deviced_request_set_factory_mode_p_1(void); +static void utc_system_deviced_deviced_request_set_factory_mode_p_2(void); +static void utc_system_deviced_deviced_request_set_factory_mode_n(void); +static void utc_system_deviced_deviced_request_dump_log_p_1(void); +static void utc_system_deviced_deviced_request_dump_log_p_2(void); +static void utc_system_deviced_deviced_request_dump_log_n(void); +static void utc_system_deviced_deviced_request_delete_dump_p(void); +static void utc_system_deviced_deviced_request_delete_dump_n(void); + +enum { + POSITIVE_TC_IDX = 0x01, + NEGATIVE_TC_IDX, +}; + +struct tet_testlist tet_testlist[] = { + { utc_system_deviced_deviced_get_cmdline_name_p, POSITIVE_TC_IDX }, + { utc_system_deviced_deviced_get_cmdline_name_n_1, NEGATIVE_TC_IDX }, + { utc_system_deviced_deviced_get_cmdline_name_n_2, NEGATIVE_TC_IDX }, + { utc_system_deviced_deviced_get_cmdline_name_n_3, NEGATIVE_TC_IDX }, + { utc_system_deviced_deviced_get_apppath_p, POSITIVE_TC_IDX }, + { utc_system_deviced_deviced_get_apppath_n_1, NEGATIVE_TC_IDX }, + { utc_system_deviced_deviced_get_apppath_n_2, NEGATIVE_TC_IDX }, + { utc_system_deviced_deviced_get_apppath_n_3, NEGATIVE_TC_IDX }, + { utc_system_deviced_deviced_conf_set_mempolicy_p, POSITIVE_TC_IDX }, + { utc_system_deviced_deviced_conf_set_mempolicy_n, NEGATIVE_TC_IDX }, + { utc_system_deviced_deviced_conf_set_mempolicy_bypid_p, POSITIVE_TC_IDX }, + { utc_system_deviced_deviced_conf_set_mempolicy_bypid_n_1, NEGATIVE_TC_IDX }, + { utc_system_deviced_deviced_conf_set_mempolicy_bypid_n_2, NEGATIVE_TC_IDX }, + { utc_system_deviced_deviced_conf_set_permanent_p, POSITIVE_TC_IDX }, + { utc_system_deviced_deviced_conf_set_permanent_bypid_p, POSITIVE_TC_IDX }, + { utc_system_deviced_deviced_conf_set_permanent_bypid_n, NEGATIVE_TC_IDX }, + { utc_system_deviced_deviced_conf_set_vip_p, POSITIVE_TC_IDX }, + { utc_system_deviced_deviced_conf_set_vip_n, NEGATIVE_TC_IDX }, + { utc_system_deviced_deviced_conf_is_vip_p, POSITIVE_TC_IDX }, + { utc_system_deviced_deviced_conf_is_vip_n, NEGATIVE_TC_IDX }, + { utc_system_deviced_deviced_set_timezone_p, POSITIVE_TC_IDX }, + { utc_system_deviced_deviced_set_timezone_n, NEGATIVE_TC_IDX }, + { utc_system_deviced_deviced_inform_foregrd_p, POSITIVE_TC_IDX }, + { utc_system_deviced_deviced_inform_backgrd_p, POSITIVE_TC_IDX }, + { utc_system_deviced_deviced_inform_active_p, POSITIVE_TC_IDX }, + { utc_system_deviced_deviced_inform_active_n, NEGATIVE_TC_IDX }, + { utc_system_deviced_deviced_inform_inactive_p, POSITIVE_TC_IDX }, + { utc_system_deviced_deviced_inform_inactive_n, NEGATIVE_TC_IDX }, +// { utc_system_deviced_deviced_request_poweroff_p, POSITIVE_TC_IDX }, + { utc_system_deviced_deviced_request_entersleep_p, POSITIVE_TC_IDX }, + { utc_system_deviced_deviced_request_leavesleep_p, POSITIVE_TC_IDX }, +// { utc_system_deviced_deviced_request_reboot_p, POSITIVE_TC_IDX }, + { utc_system_deviced_deviced_request_set_cpu_max_frequency_p, POSITIVE_TC_IDX }, + { utc_system_deviced_deviced_request_set_cpu_max_frequency_n, NEGATIVE_TC_IDX }, + { utc_system_deviced_deviced_request_set_cpu_min_frequency_p, POSITIVE_TC_IDX }, + { utc_system_deviced_deviced_request_set_cpu_min_frequency_n, NEGATIVE_TC_IDX }, + { utc_system_deviced_deviced_release_cpu_max_frequency_p, POSITIVE_TC_IDX }, + { utc_system_deviced_deviced_release_cpu_min_frequency_p, POSITIVE_TC_IDX }, + { utc_system_deviced_deviced_request_set_factory_mode_p_1, POSITIVE_TC_IDX }, + { utc_system_deviced_deviced_request_set_factory_mode_p_2, POSITIVE_TC_IDX }, + { utc_system_deviced_deviced_request_set_factory_mode_n, NEGATIVE_TC_IDX }, + { utc_system_deviced_deviced_request_dump_log_p_1, POSITIVE_TC_IDX }, + { utc_system_deviced_deviced_request_dump_log_p_2, POSITIVE_TC_IDX }, + { utc_system_deviced_deviced_request_dump_log_n, NEGATIVE_TC_IDX }, + { utc_system_deviced_deviced_request_delete_dump_p, POSITIVE_TC_IDX }, + { utc_system_deviced_deviced_request_delete_dump_n, NEGATIVE_TC_IDX }, + { NULL, 0 }, +}; + +static void startup(void) +{ +} + +static void cleanup(void) +{ +} + +/** + * @brief Positive test case of deviced_get_cmdline_name() + */ +static void utc_system_deviced_deviced_get_cmdline_name_p(void) +{ + pid_t pid; + char str[1024]; + int ret; + + pid = getpid(); + + ret = deviced_get_cmdline_name(pid, str, sizeof(str)); + dts_check_eq(API_NAME_DEVICED_GET_CMDLINE_NAME, ret, 0); +} + +/** + * @brief Negative test case of deviced_get_cmdline_name() + */ +static void utc_system_deviced_deviced_get_cmdline_name_n_1(void) +{ + char str[1024]; + int ret; + + ret = deviced_get_cmdline_name(-1, str, sizeof(str)); + dts_check_ne(API_NAME_DEVICED_GET_CMDLINE_NAME, ret, 0); +} + +/** + * @brief Negative test case of deviced_get_cmdline_name() + */ +static void utc_system_deviced_deviced_get_cmdline_name_n_2(void) +{ + pid_t pid; + char str[1024]; + int ret; + + pid = getpid(); + + ret = deviced_get_cmdline_name(pid, NULL, sizeof(str)); + dts_check_ne(API_NAME_DEVICED_GET_CMDLINE_NAME, ret, 0); +} + +/** + * @brief Negative test case of deviced_get_cmdline_name() + */ +static void utc_system_deviced_deviced_get_cmdline_name_n_3(void) +{ + pid_t pid; + char str[1024]; + int ret; + + pid = getpid(); + + ret = deviced_get_cmdline_name(pid, str, -1); + dts_check_ne(API_NAME_DEVICED_GET_CMDLINE_NAME, ret, 0); +} + +/** + * @brief Positive test case of deviced_get_apppath() + */ +static void utc_system_deviced_deviced_get_apppath_p(void) +{ + pid_t pid; + char str[1024]; + int ret; + + pid = getpid(); + + ret = deviced_get_apppath(pid, str, sizeof(str)); + dts_check_eq(API_NAME_DEVICED_GET_APPPATH, ret, 0); +} + +/** + * @brief Negative test case of deviced_get_apppath() + */ +static void utc_system_deviced_deviced_get_apppath_n_1(void) +{ + char str[1024]; + int ret; + + ret = deviced_get_apppath(-1, str, sizeof(str)); + dts_check_ne(API_NAME_DEVICED_GET_APPPATH, ret, 0); +} + +/** + * @brief Negative test case of deviced_get_apppath() + */ +static void utc_system_deviced_deviced_get_apppath_n_2(void) +{ + pid_t pid; + char str[1024]; + int ret; + + pid = getpid(); + + ret = deviced_get_apppath(pid, NULL, sizeof(str)); + dts_check_ne(API_NAME_DEVICED_GET_APPPATH, ret, 0); +} + +/** + * @brief Negative test case of deviced_get_apppath() + */ +static void utc_system_deviced_deviced_get_apppath_n_3(void) +{ + pid_t pid; + char str[1024]; + int ret; + + pid = getpid(); + + ret = deviced_get_apppath(pid, str, -1); + dts_check_ne(API_NAME_DEVICED_GET_APPPATH, ret, 0); +} + +/** + * @brief Positive test case of deviced_conf_set_mempolicy() + */ +static void utc_system_deviced_deviced_conf_set_mempolicy_p(void) +{ + int ret; + + ret = deviced_conf_set_mempolicy(OOM_LIKELY); + dts_check_eq(API_NAME_DEVICED_CONF_SET_MEMPOLICY, ret, 0); +} + +/** + * @brief Negative test case of deviced_conf_set_mempolicy() + */ +static void utc_system_deviced_deviced_conf_set_mempolicy_n(void) +{ + int ret; + + ret = deviced_conf_set_mempolicy(-1); + dts_check_ne(API_NAME_DEVICED_CONF_SET_MEMPOLICY, ret, 0); +} + +/** + * @brief Positive test case of deviced_conf_set_mempolicy_bypid() + */ +static void utc_system_deviced_deviced_conf_set_mempolicy_bypid_p(void) +{ + pid_t pid; + int ret; + + pid = getpid(); + + ret = deviced_conf_set_mempolicy_bypid(pid, OOM_LIKELY); + dts_check_eq(API_NAME_DEVICED_CONF_SET_MEMPOLICY_BYPID, ret, 0); +} + +/** + * @brief Negative test case of deviced_conf_set_mempolicy_bypid() + */ +static void utc_system_deviced_deviced_conf_set_mempolicy_bypid_n_1(void) +{ + int ret; + + ret = deviced_conf_set_mempolicy_bypid(-1, OOM_LIKELY); + dts_check_ne(API_NAME_DEVICED_CONF_SET_MEMPOLICY_BYPID, ret, 0); +} + +/** + * @brief Negative test case of deviced_conf_set_mempolicy_bypid() + */ +static void utc_system_deviced_deviced_conf_set_mempolicy_bypid_n_2(void) +{ + pid_t pid; + int ret; + + pid = getpid(); + + ret = deviced_conf_set_mempolicy_bypid(pid, -1); + dts_check_ne(API_NAME_DEVICED_CONF_SET_MEMPOLICY_BYPID, ret, 0); +} + +/** + * @brief Positive test case of deviced_conf_set_permanent() + */ +static void utc_system_deviced_deviced_conf_set_permanent_p(void) +{ + int ret; + + ret = deviced_conf_set_permanent(); + dts_check_eq(API_NAME_DEVICED_CONF_SET_PERMANENT, ret, 0); +} + +/** + * @brief Positive test case of deviced_conf_set_permanent_bypid() + */ +static void utc_system_deviced_deviced_conf_set_permanent_bypid_p(void) +{ + pid_t pid; + int ret; + + pid = getpid(); + + ret = deviced_conf_set_permanent_bypid(pid); + dts_check_eq(API_NAME_DEVICED_CONF_SET_PERMANENT_BYPID, ret, 0); +} + +/** + * @brief Negative test case of deviced_conf_set_permanent_bypid() + */ +static void utc_system_deviced_deviced_conf_set_permanent_bypid_n(void) +{ + int ret; + + ret = deviced_conf_set_permanent_bypid(-1); + dts_check_ne(API_NAME_DEVICED_CONF_SET_PERMANENT_BYPID, ret, 0); +} + +/** + * @brief Positive test case of deviced_conf_set_vip() + */ +static void utc_system_deviced_deviced_conf_set_vip_p(void) +{ + pid_t pid; + int ret; + + pid = getpid(); + + ret = deviced_conf_set_vip(pid); + dts_check_eq(API_NAME_DEVICED_CONF_SET_VIP, ret, 0); +} + +/** + * @brief Negative test case of deviced_conf_set_vip() + */ +static void utc_system_deviced_deviced_conf_set_vip_n(void) +{ + int ret; + + ret = deviced_conf_set_vip(-1); + dts_check_ne(API_NAME_DEVICED_CONF_SET_VIP, ret, 0); +} + +/** + * @brief Positive test case of deviced_conf_is_vip() + */ +static void utc_system_deviced_deviced_conf_is_vip_p(void) +{ + pid_t pid; + int ret; + + pid = getpid(); + + ret = deviced_conf_is_vip(pid); + dts_check_ge(API_NAME_DEVICED_CONF_IS_VIP, ret, 0); +} + +/** + * @brief Negative test case of deviced_conf_is_vip() + */ +static void utc_system_deviced_deviced_conf_is_vip_n(void) +{ + int ret; + + ret = deviced_conf_is_vip(-1); + dts_check_lt(API_NAME_DEVICED_CONF_IS_VIP, ret, 0); +} + +/** + * @brief Positive test case of deviced_set_timezone() + */ +static void utc_system_deviced_deviced_set_timezone_p(void) +{ + int ret; + + ret = deviced_set_timezone("/usr/share/zoneinfo/Asia/Seoul"); + dts_check_eq(API_NAME_DEVICED_SET_TIMEZONE, ret, 0); +} + +/** + * @brief Negative test case of deviced_set_timezone() + */ +static void utc_system_deviced_deviced_set_timezone_n(void) +{ + int ret; + + ret = deviced_set_timezone(NULL); + dts_check_ne(API_NAME_DEVICED_SET_TIMEZONE, ret, 0); +} + +/** + * @brief Positive test case of deviced_inform_foregrd() + */ +static void utc_system_deviced_deviced_inform_foregrd_p(void) +{ + int ret; + + ret = deviced_inform_foregrd(); + dts_check_eq(API_NAME_DEVICED_INFORM_FOREGRD, ret, 0); +} + +/** + * @brief Positive test case of deviced_inform_backgrd() + */ +static void utc_system_deviced_deviced_inform_backgrd_p(void) +{ + int ret; + + ret = deviced_inform_backgrd(); + dts_check_eq(API_NAME_DEVICED_INFORM_BACKGRD, ret, 0); +} + +/** + * @brief Positive test case of deviced_inform_active() + */ +static void utc_system_deviced_deviced_inform_active_p(void) +{ + pid_t pid; + int ret; + + pid = getpid(); + + ret = deviced_inform_active(pid); + dts_check_eq(API_NAME_DEVICED_INFORM_ACTIVE, ret, 0); +} + +/** + * @brief Negative test case of deviced_inform_active() + */ +static void utc_system_deviced_deviced_inform_active_n(void) +{ + int ret; + + ret = deviced_inform_active(-1); + dts_check_ne(API_NAME_DEVICED_INFORM_ACTIVE, ret, 0); +} + +/** + * @brief Positive test case of deviced_inform_inactive() + */ +static void utc_system_deviced_deviced_inform_inactive_p(void) +{ + pid_t pid; + int ret; + + pid = getpid(); + + ret = deviced_inform_inactive(pid); + dts_check_eq(API_NAME_DEVICED_INFORM_INACTIVE, ret, 0); +} + +/** + * @brief Negative test case of deviced_inform_inactive() + */ +static void utc_system_deviced_deviced_inform_inactive_n(void) +{ + int ret; + + ret = deviced_inform_inactive(-1); + dts_check_ne(API_NAME_DEVICED_INFORM_INACTIVE, ret, 0); +} + +/** + * @brief Positive test case of deviced_request_poweroff() + */ +static void utc_system_deviced_deviced_request_poweroff_p(void) +{ + int ret; + + ret = deviced_request_poweroff(); + dts_check_eq(API_NAME_DEVICED_REQUEST_POWEROFF, ret, 0); +} + +/** + * @brief Positive test case of deviced_request_entersleep() + */ +static void utc_system_deviced_deviced_request_entersleep_p(void) +{ + int ret; + + ret = deviced_request_entersleep(); + dts_check_eq(API_NAME_DEVICED_REQUEST_ENTERSLEEP, ret, 0); +} + +/** + * @brief Positive test case of deviced_request_leavesleep() + */ +static void utc_system_deviced_deviced_request_leavesleep_p(void) +{ + int ret; + + ret = deviced_request_leavesleep(); + dts_check_eq(API_NAME_DEVICED_REQUEST_LEAVESLEEP, ret, 0); +} + +/** + * @brief Positive test case of deviced_request_reboot() + */ +static void utc_system_deviced_deviced_request_reboot_p(void) +{ + int ret; + + ret = deviced_request_reboot(); + dts_check_eq(API_NAME_DEVICED_REQUEST_REBOOT, ret, 0); +} + +/** + * @brief Positive test case of deviced_request_set_cpu_max_frequency() + */ +static void utc_system_deviced_deviced_request_set_cpu_max_frequency_p(void) +{ + int ret; + + ret = deviced_request_set_cpu_max_frequency(60); + dts_check_eq(API_NAME_DEVICED_REQUEST_SET_CPU_MAX_FREQUENCY, ret, 0); +} + +/** + * @brief Negative test case of deviced_request_set_cpu_max_frequency() + */ +static void utc_system_deviced_deviced_request_set_cpu_max_frequency_n(void) +{ + int ret; + + ret = deviced_request_set_cpu_max_frequency(-1); + dts_check_ne(API_NAME_DEVICED_REQUEST_SET_CPU_MAX_FREQUENCY, ret, 0); +} + +/** + * @brief Positive test case of deviced_request_set_cpu_min_frequency() + */ +static void utc_system_deviced_deviced_request_set_cpu_min_frequency_p(void) +{ + int ret; + + ret = deviced_request_set_cpu_min_frequency(60); + dts_check_eq(API_NAME_DEVICED_REQUEST_SET_CPU_MIN_FREQUENCY, ret, 0); +} + +/** + * @brief Negative test case of deviced_request_set_cpu_min_frequency() + */ +static void utc_system_deviced_deviced_request_set_cpu_min_frequency_n(void) +{ + int ret; + + ret = deviced_request_set_cpu_min_frequency(-1); + dts_check_ne(API_NAME_DEVICED_REQUEST_SET_CPU_MIN_FREQUENCY, ret, 0); +} + +/** + * @brief Positive test case of deviced_release_cpu_max_frequency() + */ +static void utc_system_deviced_deviced_release_cpu_max_frequency_p(void) +{ + int ret; + + ret = deviced_release_cpu_max_frequency(); + dts_check_eq(API_NAME_DEVICED_RELEASE_CPU_MAX_FREQUENCY, ret, 0); +} + +/** + * @brief Positive test case of deviced_release_cpu_min_frequency() + */ +static void utc_system_deviced_deviced_release_cpu_min_frequency_p(void) +{ + int ret; + + ret = deviced_release_cpu_min_frequency(); + dts_check_eq(API_NAME_DEVICED_RELEASE_CPU_MIN_FREQUENCY, ret, 0); +} + +/** + * @brief Positive test case of deviced_request_set_factory_mode() + */ +static void utc_system_deviced_deviced_request_set_factory_mode_p_1(void) +{ + int ret; + + ret = deviced_request_set_factory_mode(1); + dts_check_eq(API_NAME_DEVICED_REQUEST_SET_FACTORY_MODE, ret, 1, "Enable factory mode"); +} + +/** + * @brief Positive test case of deviced_request_set_factory_mode() + */ +static void utc_system_deviced_deviced_request_set_factory_mode_p_2(void) +{ + int ret; + + ret = deviced_request_set_factory_mode(0); + dts_check_eq(API_NAME_DEVICED_REQUEST_SET_FACTORY_MODE, ret, 0, "Disable factory mode"); +} + +/** + * @brief Negative test case of deviced_request_set_factory_mode() + */ +static void utc_system_deviced_deviced_request_set_factory_mode_n(void) +{ + int ret; + + ret = deviced_request_set_factory_mode(-1); + dts_check_ne(API_NAME_DEVICED_REQUEST_SET_FACTORY_MODE, ret, 0); +} + +/** + * @brief Positive test case of deviced_request_dump_log() + */ +static void utc_system_deviced_deviced_request_dump_log_p_1(void) +{ + int ret; + + ret = deviced_request_dump_log(AP_DUMP); + dts_check_ge(API_NAME_DEVICED_REQUEST_DUMP_LOG, ret, 0); +} + +/** + * @brief Positive test case of deviced_request_dump_log() + */ +static void utc_system_deviced_deviced_request_dump_log_p_2(void) +{ + int ret; + + ret = deviced_request_dump_log(CP_DUMP); + dts_check_eq(API_NAME_DEVICED_REQUEST_DUMP_LOG, ret, 0); +} + +/** + * @brief Positive test case of deviced_request_dump_log() + */ +static void utc_system_deviced_deviced_request_dump_log_n(void) +{ + int ret; + + ret = deviced_request_dump_log(-1); + dts_check_ne(API_NAME_DEVICED_REQUEST_DUMP_LOG, ret, 0); +} + +/** + * @brief Positive test case of deviced_request_delete_dump() + */ +static void utc_system_deviced_deviced_request_delete_dump_p(void) +{ + int ret; + + ret = deviced_request_delete_dump(""); + dts_check_eq(API_NAME_DEVICED_REQUEST_DELETE_DUMP, ret, 0); +} + +/** + * @brief Negative test case of deviced_request_delete_dump() + */ +static void utc_system_deviced_deviced_request_delete_dump_n(void) +{ + int ret; + + ret = deviced_request_delete_dump(NULL); + dts_check_ne(API_NAME_DEVICED_REQUEST_DELETE_DUMP, ret, 0); +} diff --git a/test/testcase/utc_system_deviced_deviced_managed.c b/test/testcase/utc_system_deviced_deviced_managed.c new file mode 100644 index 0000000..78ac62f --- /dev/null +++ b/test/testcase/utc_system_deviced_deviced_managed.c @@ -0,0 +1,422 @@ +/* + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * PROPRIETARY/CONFIDENTIAL + * + * This software is the confidential and proprietary information of SAMSUNG + * ELECTRONICS ("Confidential Information"). You agree and acknowledge that + * this software is owned by Samsung and you shall not disclose such + * Confidential Information and shall use it only in accordance with the terms + * of the license agreement you entered into with SAMSUNG ELECTRONICS. SAMSUNG + * make no representations or warranties about the suitability of the software, + * either express or implied, including but not limited to the implied + * warranties of merchantability, fitness for a particular purpose, or + * non-infringement. SAMSUNG shall not be liable for any damages suffered by + * licensee arising out of or related to this software. + * + */ +#include +#include +#include + +#define API_NAME_DEVICED_GET_PID "deviced_get_pid" +#define API_NAME_DEVICED_SET_DATETIME "deviced_set_datetime" +#define API_NAME_DEVICED_REQUEST_MOUNT_MMC "deviced_request_mount_mmc" +#define API_NAME_DEVICED_REQUEST_UNMOUNT_MMC "deviced_request_unmount_mmc" +#define API_NAME_DEVICED_REQUEST_FORMAT_MMC "deviced_request_format_mmc" +#define API_NAME_DEVICED_FORMAT_MMC "deviced_format_mmc" + +static void startup(void); +static void cleanup(void); + +void (*tet_startup)(void) = startup; +void (*tet_cleanup)(void) = cleanup; + + +static void utc_system_deviced_deviced_get_pid_p(void); +static void utc_system_deviced_deviced_get_pid_n(void); +static void utc_system_deviced_deviced_set_datetime_n(void); +static void utc_system_deviced_deviced_set_datetime_p(void); +static void utc_system_deviced_deviced_request_mount_mmc_p_1(void); +static void utc_system_deviced_deviced_request_mount_mmc_p_2(void); +static void utc_system_deviced_deviced_request_mount_mmc_p_3(void); +static void utc_system_deviced_deviced_request_unmount_mmc_p_1(void); +static void utc_system_deviced_deviced_request_unmount_mmc_p_2(void); +static void utc_system_deviced_deviced_request_unmount_mmc_p_3(void); +static void utc_system_deviced_deviced_request_unmount_mmc_p_4(void); +static void utc_system_deviced_deviced_request_unmount_mmc_n(void); +static void utc_system_deviced_deviced_request_format_mmc_p_1(void); +static void utc_system_deviced_deviced_request_format_mmc_p_2(void); +static void utc_system_deviced_deviced_request_format_mmc_p_3(void); +static void utc_system_deviced_deviced_format_mmc_p_1(void); +static void utc_system_deviced_deviced_format_mmc_p_2(void); +static void utc_system_deviced_deviced_format_mmc_p_3(void); +static void utc_system_deviced_deviced_format_mmc_p_4(void); +static void utc_system_deviced_deviced_format_mmc_n(void); + +enum { + POSITIVE_TC_IDX = 0x01, + NEGATIVE_TC_IDX, +}; + +struct tet_testlist tet_testlist[] = { + /* The following TCs are for root application */ +// { utc_system_deviced_deviced_get_pid_p, POSITIVE_TC_IDX }, +// { utc_system_deviced_deviced_get_pid_n, NEGATIVE_TC_IDX }, + { utc_system_deviced_deviced_set_datetime_n, NEGATIVE_TC_IDX }, + { utc_system_deviced_deviced_set_datetime_p, POSITIVE_TC_IDX }, + { utc_system_deviced_deviced_request_mount_mmc_p_1, POSITIVE_TC_IDX }, + { utc_system_deviced_deviced_request_mount_mmc_p_2, POSITIVE_TC_IDX }, + { utc_system_deviced_deviced_request_mount_mmc_p_3, POSITIVE_TC_IDX }, + { utc_system_deviced_deviced_request_unmount_mmc_p_1, POSITIVE_TC_IDX }, + { utc_system_deviced_deviced_request_unmount_mmc_p_2, POSITIVE_TC_IDX }, + { utc_system_deviced_deviced_request_unmount_mmc_p_3, POSITIVE_TC_IDX }, + { utc_system_deviced_deviced_request_unmount_mmc_p_4, POSITIVE_TC_IDX }, + { utc_system_deviced_deviced_request_unmount_mmc_n, NEGATIVE_TC_IDX }, + { utc_system_deviced_deviced_request_format_mmc_p_1, POSITIVE_TC_IDX }, + { utc_system_deviced_deviced_request_format_mmc_p_2, POSITIVE_TC_IDX }, + { utc_system_deviced_deviced_request_format_mmc_p_3, POSITIVE_TC_IDX }, + { utc_system_deviced_deviced_format_mmc_p_1, POSITIVE_TC_IDX }, + { utc_system_deviced_deviced_format_mmc_p_2, POSITIVE_TC_IDX }, + { utc_system_deviced_deviced_format_mmc_p_3, POSITIVE_TC_IDX }, + { utc_system_deviced_deviced_format_mmc_p_4, POSITIVE_TC_IDX }, + { utc_system_deviced_deviced_format_mmc_n, NEGATIVE_TC_IDX }, + { NULL, 0 }, +}; + +static void startup(void) +{ +} + +static void cleanup(void) +{ +} + +/** + * @brief Positive test case of deviced_get_pid() + */ +static void utc_system_deviced_deviced_get_pid_p(void) +{ + int ret; + + ret = deviced_get_pid("/usb/bin/deviced"); + dts_check_ge(API_NAME_DEVICED_GET_PID, ret, 0); +} + +/** + * @brief Negative test case of deviced_get_pid() + */ +static void utc_system_deviced_deviced_get_pid_n(void) +{ + int ret; + + ret = deviced_get_pid(NULL); + dts_check_lt(API_NAME_DEVICED_GET_PID, ret, 0); +} + +/** + * @brief Negative test case of deviced_set_datetime() + */ +static void utc_system_deviced_deviced_set_datetime_n(void) +{ + int ret; + + ret = deviced_set_datetime(-1); + dts_check_lt(API_NAME_DEVICED_SET_DATETIME, ret, 0); +} + +/** + * @brief Positive test case of deviced_set_datetime() + */ +static void utc_system_deviced_deviced_set_datetime_p(void) +{ + int ret; + time_t now; + + localtime(&now); + + ret = deviced_set_datetime(now); + dts_check_ge(API_NAME_DEVICED_SET_DATETIME, ret, 0); +} + +static void mount_cb(int result, void *data) +{ + dts_message(API_NAME_DEVICED_REQUEST_MOUNT_MMC, + "mount callback result : %d", result); +} + +/** + * @brief Positive test case of deviced_request_mount_mmc() + */ +static void utc_system_deviced_deviced_request_mount_mmc_p_1(void) +{ + int ret; + struct mmc_contents data = {.mmc_cb = mount_cb, .user_data = NULL}; + + dts_message(API_NAME_DEVICED_REQUEST_MOUNT_MMC, + "This testcase is only valid when mmc is inserted"); + + ret = deviced_request_mount_mmc(&data); + dts_check_eq(API_NAME_DEVICED_REQUEST_MOUNT_MMC, ret, 0); + + sleep(1); +} + +/** + * @brief Positive test case of deviced_request_mount_mmc() + */ +static void utc_system_deviced_deviced_request_mount_mmc_p_2(void) +{ + int ret; + struct mmc_contents data = {.mmc_cb = NULL, .user_data = NULL}; + + dts_message(API_NAME_DEVICED_REQUEST_MOUNT_MMC, + "This testcase is only valid when mmc is inserted"); + + ret = deviced_request_mount_mmc(&data); + dts_check_eq(API_NAME_DEVICED_REQUEST_MOUNT_MMC, ret, 0); + + sleep(1); +} + +/** + * @brief Positive test case of deviced_request_mount_mmc() + */ +static void utc_system_deviced_deviced_request_mount_mmc_p_3(void) +{ + int ret; + + dts_message(API_NAME_DEVICED_REQUEST_MOUNT_MMC, + "This testcase is only valid when mmc is inserted"); + + ret = deviced_request_mount_mmc(NULL); + dts_check_eq(API_NAME_DEVICED_REQUEST_MOUNT_MMC, ret, 0); + + sleep(1); +} + +static void unmount_cb(int result, void *data) +{ + dts_message(API_NAME_DEVICED_REQUEST_UNMOUNT_MMC, + "unmount callback result : %d", result); +} + +/** + * @brief Positive test case of deviced_request_unmount_mmc() + */ +static void utc_system_deviced_deviced_request_unmount_mmc_p_1(void) +{ + int ret; + struct mmc_contents data = {.mmc_cb = unmount_cb, .user_data = NULL}; + + dts_message(API_NAME_DEVICED_REQUEST_UNMOUNT_MMC, + "This testcase is only valid when mmc is inserted"); + + ret = deviced_request_unmount_mmc(&data, 0); + dts_check_eq(API_NAME_DEVICED_REQUEST_UNMOUNT_MMC, ret, 0); + + sleep(1); +} + +/** + * @brief Positive test case of deviced_request_unmount_mmc() + */ +static void utc_system_deviced_deviced_request_unmount_mmc_p_2(void) +{ + int ret; + struct mmc_contents data = {.mmc_cb = unmount_cb, .user_data = NULL}; + + dts_message(API_NAME_DEVICED_REQUEST_UNMOUNT_MMC, + "This testcase is only valid when mmc is inserted"); + + ret = deviced_request_unmount_mmc(&data, 1); + dts_check_eq(API_NAME_DEVICED_REQUEST_UNMOUNT_MMC, ret, 0); + + sleep(1); +} + +/** + * @brief Positive test case of deviced_request_unmount_mmc() + */ +static void utc_system_deviced_deviced_request_unmount_mmc_p_3(void) +{ + int ret; + struct mmc_contents data = {.mmc_cb = NULL, .user_data = NULL}; + + dts_message(API_NAME_DEVICED_REQUEST_UNMOUNT_MMC, + "This testcase is only valid when mmc is inserted"); + + ret = deviced_request_unmount_mmc(&data, 1); + dts_check_eq(API_NAME_DEVICED_REQUEST_UNMOUNT_MMC, ret, 0); + + sleep(1); +} + +/** + * @brief Positive test case of deviced_request_unmount_mmc() + */ +static void utc_system_deviced_deviced_request_unmount_mmc_p_4(void) +{ + int ret; + + dts_message(API_NAME_DEVICED_REQUEST_UNMOUNT_MMC, + "This testcase is only valid when mmc is inserted"); + + ret = deviced_request_unmount_mmc(NULL, 0); + dts_check_eq(API_NAME_DEVICED_REQUEST_UNMOUNT_MMC, ret, 0); + + sleep(1); +} + +/** + * @brief Negative test case of deviced_request_unmount_mmc() + */ +static void utc_system_deviced_deviced_request_unmount_mmc_n(void) +{ + int ret; + struct mmc_contents data = {.mmc_cb = unmount_cb, .user_data = NULL}; + + dts_message(API_NAME_DEVICED_REQUEST_UNMOUNT_MMC, + "This testcase is only valid when mmc is inserted"); + + ret = deviced_request_unmount_mmc(&data, -1); + dts_check_ne(API_NAME_DEVICED_REQUEST_UNMOUNT_MMC, ret, 0); +} + +static void format_cb(int result, void *data) +{ + dts_message(API_NAME_DEVICED_REQUEST_FORMAT_MMC, + "format callback result : %d", result); +} + +/** + * @brief Positive test case of deviced_request_format_mmc() + */ +static void utc_system_deviced_deviced_request_format_mmc_p_1(void) +{ + int ret; + struct mmc_contents data = {.mmc_cb = format_cb, .user_data = NULL}; + + dts_message(API_NAME_DEVICED_REQUEST_FORMAT_MMC, + "This testcase is only valid when mmc is inserted"); + + ret = deviced_request_format_mmc(&data); + dts_check_eq(API_NAME_DEVICED_REQUEST_FORMAT_MMC, ret, 0); + + sleep(1); +} + +/** + * @brief Positive test case of deviced_request_format_mmc() + */ +static void utc_system_deviced_deviced_request_format_mmc_p_2(void) +{ + int ret; + struct mmc_contents data = {.mmc_cb = NULL, .user_data = NULL}; + + dts_message(API_NAME_DEVICED_REQUEST_FORMAT_MMC, + "This testcase is only valid when mmc is inserted"); + + ret = deviced_request_format_mmc(&data); + dts_check_eq(API_NAME_DEVICED_REQUEST_FORMAT_MMC, ret, 0); + + sleep(1); +} + +/** + * @brief Positive test case of deviced_request_format_mmc() + */ +static void utc_system_deviced_deviced_request_format_mmc_p_3(void) +{ + int ret; + + dts_message(API_NAME_DEVICED_REQUEST_FORMAT_MMC, + "This testcase is only valid when mmc is inserted"); + + ret = deviced_request_format_mmc(NULL); + dts_check_eq(API_NAME_DEVICED_REQUEST_FORMAT_MMC, ret, 0); + + sleep(1); +} + +/** + * @brief Positive test case of deviced_format_mmc() + */ +static void utc_system_deviced_deviced_format_mmc_p_1(void) +{ + int ret; + struct mmc_contents data = {.mmc_cb = format_cb, .user_data = NULL}; + + dts_message(API_NAME_DEVICED_REQUEST_FORMAT_MMC, + "This testcase is only valid when mmc is inserted"); + + ret = deviced_format_mmc(&data, 0); + dts_check_eq(API_NAME_DEVICED_FORMAT_MMC, ret, 0); + + sleep(1); +} + +/** + * @brief Positive test case of deviced_format_mmc() + */ +static void utc_system_deviced_deviced_format_mmc_p_2(void) +{ + int ret; + struct mmc_contents data = {.mmc_cb = format_cb, .user_data = NULL}; + + dts_message(API_NAME_DEVICED_REQUEST_FORMAT_MMC, + "This testcase is only valid when mmc is inserted"); + + ret = deviced_format_mmc(&data, 1); + dts_check_eq(API_NAME_DEVICED_FORMAT_MMC, ret, 0); + + sleep(1); +} + +/** + * @brief Positive test case of deviced_format_mmc() + */ +static void utc_system_deviced_deviced_format_mmc_p_3(void) +{ + int ret; + struct mmc_contents data = {.mmc_cb = NULL, .user_data = NULL}; + + dts_message(API_NAME_DEVICED_REQUEST_FORMAT_MMC, + "This testcase is only valid when mmc is inserted"); + + ret = deviced_format_mmc(&data, 1); + dts_check_eq(API_NAME_DEVICED_FORMAT_MMC, ret, 0); + + sleep(1); +} + +/** + * @brief Positive test case of deviced_format_mmc() + */ +static void utc_system_deviced_deviced_format_mmc_p_4(void) +{ + int ret; + + dts_message(API_NAME_DEVICED_REQUEST_FORMAT_MMC, + "This testcase is only valid when mmc is inserted"); + + ret = deviced_format_mmc(NULL, 0); + dts_check_eq(API_NAME_DEVICED_FORMAT_MMC, ret, 0); + + sleep(1); +} + +/** + * @brief Negative test case of deviced_format_mmc() + */ +static void utc_system_deviced_deviced_format_mmc_n(void) +{ + int ret; + struct mmc_contents data = {.mmc_cb = format_cb, .user_data = NULL}; + + dts_message(API_NAME_DEVICED_REQUEST_FORMAT_MMC, + "This testcase is only valid when mmc is inserted"); + + ret = deviced_format_mmc(&data, -1); + dts_check_ne(API_NAME_DEVICED_FORMAT_MMC, ret, 0); +} diff --git a/test/testcase/utc_system_deviced_display.c b/test/testcase/utc_system_deviced_display.c new file mode 100644 index 0000000..812b4bd --- /dev/null +++ b/test/testcase/utc_system_deviced_display.c @@ -0,0 +1,649 @@ +/* + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * PROPRIETARY/CONFIDENTIAL + * + * This software is the confidential and proprietary information of SAMSUNG + * ELECTRONICS ("Confidential Information"). You agree and acknowledge that + * this software is owned by Samsung and you shall not disclose such + * Confidential Information and shall use it only in accordance with the terms + * of the license agreement you entered into with SAMSUNG ELECTRONICS. SAMSUNG + * make no representations or warranties about the suitability of the software, + * either express or implied, including but not limited to the implied + * warranties of merchantability, fitness for a particular purpose, or + * non-infringement. SAMSUNG shall not be liable for any damages suffered by + * licensee arising out of or related to this software. + * + */ +#include +#include +#include + +#define API_NAME_DISPLAY_GET_COUNT "display_get_count" +#define API_NAME_DISPLAY_GET_MAX_BRIGHTNESS "display_get_max_brightness" +#define API_NAME_DISPLAY_GET_MIN_BRIGHTNESS "display_get_min_brightness" +#define API_NAME_DISPLAY_GET_BRIGHTNESS "display_get_brightness" +#define API_NAME_DISPLAY_SET_BRIGHTNESS_WITH_SETTING "display_set_brightness_with_setting" +#define API_NAME_DISPLAY_SET_BRIGHTNESS "display_set_brightness" +#define API_NAME_DISPLAY_RELEASE_BRIGHTNESS "display_release_brightness" +#define API_NAME_DISPLAY_GET_ACL_STATUS "display_get_acl_status" +#define API_NAME_DISPLAY_SET_ACL_STATUS "display_set_acl_status" +#define API_NAME_DISPLAY_GET_IMAGE_ENHANCE_INFO "display_get_enhance_info" +#define API_NAME_DISPLAY_GET_IMAGE_ENHANCE "display_get_image_enhance" +#define API_NAME_DISPLAY_SET_IMAGE_ENHANCE "display_set_image_enhance" +#define API_NAME_DISPLAY_SET_REFRESH_RATE "display_set_refresh_rate" +#define API_NAME_DISPLAY_LOCK_STATE "display_lock_state" +#define API_NAME_DISPLAY_UNLOCK_STATE "display_unlock_state" +#define API_NAME_DISPLAY_CHANGE_STATE "display_change_state" +#define API_NAME_DISPLAY_GET_AUTO_SCREEN_TONE "display_get_auto_screen_tone" +#define API_NAME_DISPLAY_SET_AUTO_SCREEN_TONE "display_Set_auto_screen_tone" +#define API_NAME_DISPLAY_GET_COLOR_BLIND "display_get_color_blind" +#define API_NAME_DISPLAY_SET_COLOR_BLIND "display_set_color_blind" +#define API_NAME_DISPLAY_GET_ENHANCED_TOUCH "display_get_enhanced_touch" +#define API_NAME_DISPLAY_SET_ENHANCED_TOUCH "display_set_enhanced_touch" + +static void startup(void); +static void cleanup(void); + +void (*tet_startup)(void) = startup; +void (*tet_cleanup)(void) = cleanup; + + +static void utc_system_deviced_display_get_count_p(void); +static void utc_system_deviced_display_get_max_brightness_p(void); +static void utc_system_deviced_display_get_min_brightness_p(void); +static void utc_system_deviced_display_get_brightness_p(void); +static void utc_system_deviced_display_set_brightness_with_setting_p(void); +static void utc_system_deviced_display_set_brightness_with_setting_n(void); +static void utc_system_deviced_display_set_brightness_p(void); +static void utc_system_deviced_display_set_brightness_n(void); +static void utc_system_deviced_display_release_brightness_p(void); +static void utc_system_deviced_display_get_acl_status_p(void); +static void utc_system_deviced_display_set_acl_status_p_1(void); +static void utc_system_deviced_display_set_acl_status_p_2(void); +static void utc_system_deviced_display_set_acl_status_n(void); +static void utc_system_deviced_display_get_image_enhance_info_p(void); +static void utc_system_deviced_display_get_image_enhance_p(void); +static void utc_system_deviced_display_get_image_enhance_n(void); +static void utc_system_deviced_display_set_image_enhance_p(void); +static void utc_system_deviced_display_set_image_enhance_n_1(void); +static void utc_system_deviced_display_set_image_enhance_n_2(void); +static void utc_system_deviced_display_set_refresh_rate_p(void); +static void utc_system_deviced_display_set_refresh_rate_n_1(void); +static void utc_system_deviced_display_set_refresh_rate_n_2(void); +static void utc_system_deviced_display_lock_state_p(void); +static void utc_system_deviced_display_lock_state_n_1(void); +static void utc_system_deviced_display_lock_state_n_2(void); +static void utc_system_deviced_display_lock_state_n_3(void); +static void utc_system_deviced_display_unlock_state_p(void); +static void utc_system_deviced_display_unlock_state_n_1(void); +static void utc_system_deviced_display_unlock_state_n_2(void); +static void utc_system_deviced_display_change_state_p(void); +static void utc_system_deviced_display_change_state_n(void); +static void utc_system_deviced_display_get_auto_screen_tone_p(void); +static void utc_system_deviced_display_set_auto_screen_tone_p_1(void); +static void utc_system_deviced_display_set_auto_screen_tone_p_2(void); +static void utc_system_deviced_display_set_auto_screen_tone_n(void); +static void utc_system_deviced_display_get_color_blind_p(void); +static void utc_system_deviced_display_set_color_blind_p_1(void); +static void utc_system_deviced_display_set_color_blind_p_2(void); +static void utc_system_deviced_display_set_color_blind_n_1(void); +static void utc_system_deviced_display_set_color_blind_n_2(void); +static void utc_system_deviced_display_get_enhanced_touch_p(void); +static void utc_system_deviced_display_set_enhanced_touch_p_1(void); +static void utc_system_deviced_display_set_enhanced_touch_p_2(void); +static void utc_system_deviced_display_set_enhanced_touch_n(void); + +enum { + POSITIVE_TC_IDX = 0x01, + NEGATIVE_TC_IDX, +}; + +struct tet_testlist tet_testlist[] = { + { utc_system_deviced_display_get_count_p, POSITIVE_TC_IDX }, + { utc_system_deviced_display_get_max_brightness_p, POSITIVE_TC_IDX }, + { utc_system_deviced_display_get_min_brightness_p, POSITIVE_TC_IDX }, + { utc_system_deviced_display_get_brightness_p, POSITIVE_TC_IDX }, + { utc_system_deviced_display_set_brightness_with_setting_p, POSITIVE_TC_IDX }, + { utc_system_deviced_display_set_brightness_with_setting_n, NEGATIVE_TC_IDX }, + { utc_system_deviced_display_set_brightness_p, POSITIVE_TC_IDX }, + { utc_system_deviced_display_set_brightness_n, NEGATIVE_TC_IDX }, + { utc_system_deviced_display_release_brightness_p, POSITIVE_TC_IDX }, + { utc_system_deviced_display_get_acl_status_p, POSITIVE_TC_IDX }, + { utc_system_deviced_display_set_acl_status_p_1, POSITIVE_TC_IDX }, + { utc_system_deviced_display_set_acl_status_p_2, POSITIVE_TC_IDX }, + { utc_system_deviced_display_set_acl_status_n, NEGATIVE_TC_IDX }, + { utc_system_deviced_display_get_image_enhance_info_p, POSITIVE_TC_IDX }, + { utc_system_deviced_display_get_image_enhance_p, POSITIVE_TC_IDX }, + { utc_system_deviced_display_get_image_enhance_n, NEGATIVE_TC_IDX }, + { utc_system_deviced_display_set_image_enhance_p, POSITIVE_TC_IDX }, + { utc_system_deviced_display_set_image_enhance_n_1, NEGATIVE_TC_IDX }, + { utc_system_deviced_display_set_image_enhance_n_2, NEGATIVE_TC_IDX }, + { utc_system_deviced_display_set_refresh_rate_p, POSITIVE_TC_IDX }, + { utc_system_deviced_display_set_refresh_rate_n_1, NEGATIVE_TC_IDX }, + { utc_system_deviced_display_set_refresh_rate_n_2, NEGATIVE_TC_IDX }, + { utc_system_deviced_display_lock_state_p, POSITIVE_TC_IDX }, + { utc_system_deviced_display_lock_state_n_1, NEGATIVE_TC_IDX }, + { utc_system_deviced_display_lock_state_n_2, NEGATIVE_TC_IDX }, + { utc_system_deviced_display_lock_state_n_3, NEGATIVE_TC_IDX }, + { utc_system_deviced_display_unlock_state_p, POSITIVE_TC_IDX }, + { utc_system_deviced_display_unlock_state_n_1, NEGATIVE_TC_IDX }, + { utc_system_deviced_display_unlock_state_n_2, NEGATIVE_TC_IDX }, + { utc_system_deviced_display_change_state_p, POSITIVE_TC_IDX }, + { utc_system_deviced_display_change_state_n, NEGATIVE_TC_IDX }, + { utc_system_deviced_display_get_auto_screen_tone_p, POSITIVE_TC_IDX }, + { utc_system_deviced_display_set_auto_screen_tone_p_1, POSITIVE_TC_IDX }, + { utc_system_deviced_display_set_auto_screen_tone_p_2, POSITIVE_TC_IDX }, + { utc_system_deviced_display_set_auto_screen_tone_n, NEGATIVE_TC_IDX }, + { utc_system_deviced_display_get_color_blind_p, POSITIVE_TC_IDX }, + { utc_system_deviced_display_set_color_blind_p_1, POSITIVE_TC_IDX }, + { utc_system_deviced_display_set_color_blind_p_2, POSITIVE_TC_IDX }, + { utc_system_deviced_display_set_color_blind_n_1, NEGATIVE_TC_IDX }, + { utc_system_deviced_display_set_color_blind_n_2, NEGATIVE_TC_IDX }, + { utc_system_deviced_display_get_enhanced_touch_p, POSITIVE_TC_IDX }, + { utc_system_deviced_display_set_enhanced_touch_p_1, POSITIVE_TC_IDX }, + { utc_system_deviced_display_set_enhanced_touch_p_2, POSITIVE_TC_IDX }, + { utc_system_deviced_display_set_enhanced_touch_n, NEGATIVE_TC_IDX }, + { NULL, 0 }, +}; + +static void startup(void) +{ +} + +static void cleanup(void) +{ +} + +/** + * @brief Positive test case of display_get_count() + */ +static void utc_system_deviced_display_get_count_p(void) +{ + int ret; + + ret = display_get_count(); + dts_check_ge(API_NAME_DISPLAY_GET_COUNT, ret, 0); +} + +/** + * @brief Positive test case of display_get_max_brightness() + */ +static void utc_system_deviced_display_get_max_brightness_p(void) +{ + int ret; + + ret = display_get_max_brightness(); + dts_check_ge(API_NAME_DISPLAY_GET_MAX_BRIGHTNESS, ret, 0); +} + +/** + * @brief Positive test case of display_get_min_brightness() + */ +static void utc_system_deviced_display_get_min_brightness_p(void) +{ + int ret; + + ret = display_get_min_brightness(); + dts_check_ge(API_NAME_DISPLAY_GET_MIN_BRIGHTNESS, ret, 0); +} + +/** + * @brief Positive test case of display_get_brightness() + */ +static void utc_system_deviced_display_get_brightness_p(void) +{ + int ret; + + ret = display_get_brightness(); + dts_check_ge(API_NAME_DISPLAY_GET_BRIGHTNESS, ret, 0); +} + +/** + * @brief Positive test case of display_set_brightness_with_setting() + */ +static void utc_system_deviced_display_set_brightness_with_setting_p(void) +{ + int ret; + + ret = display_set_brightness_with_setting(100); + dts_check_eq(API_NAME_DISPLAY_SET_BRIGHTNESS_WITH_SETTING, ret, 0); +} + +/** + * @brief Negative test case of display_set_brightness_with_setting() + */ +static void utc_system_deviced_display_set_brightness_with_setting_n(void) +{ + int ret; + + ret = display_set_brightness_with_setting(-1); + dts_check_ne(API_NAME_DISPLAY_SET_BRIGHTNESS_WITH_SETTING, ret, 0); +} + +/** + * @brief Positive test case of display_set_brightness() + */ +static void utc_system_deviced_display_set_brightness_p(void) +{ + int ret; + + ret = display_set_brightness(50); + dts_check_eq(API_NAME_DISPLAY_SET_BRIGHTNESS, ret, 0); +} + +/** + * @brief Negative test case of display_set_brightness() + */ +static void utc_system_deviced_display_set_brightness_n(void) +{ + int ret; + + ret = display_set_brightness(-1); + dts_check_ne(API_NAME_DISPLAY_SET_BRIGHTNESS, ret, 0); +} + +/** + * @brief Positive test case of display_release_brightness() + */ +static void utc_system_deviced_display_release_brightness_p(void) +{ + int ret; + + ret = display_release_brightness(); + dts_check_eq(API_NAME_DISPLAY_RELEASE_BRIGHTNESS, ret, 0); +} + +/** + * @brief Positive test case of display_get_acl_status() + */ +static void utc_system_deviced_display_get_acl_status_p(void) +{ + int ret; + + ret = display_get_acl_status(); + dts_check_ge(API_NAME_DISPLAY_GET_ACL_STATUS, ret, 0); +} + +/** + * @brief Positive test case of display_set_acl_status() + */ +static void utc_system_deviced_display_set_acl_status_p_1(void) +{ + int ret; + + ret = display_set_acl_status(1); + dts_check_eq(API_NAME_DISPLAY_SET_ACL_STATUS, ret, 0, "Enable acl"); +} + +/** + * @brief Positive test case of display_set_acl_status() + */ +static void utc_system_deviced_display_set_acl_status_p_2(void) +{ + int ret; + + ret = display_set_acl_status(0); + dts_check_eq(API_NAME_DISPLAY_SET_ACL_STATUS, ret, 0, "Disable acl"); +} + +/** + * @brief Negative test case of display_set_acl_status() + */ +static void utc_system_deviced_display_set_acl_status_n(void) +{ + int ret; + + ret = display_set_acl_status(-1); + dts_check_ne(API_NAME_DISPLAY_SET_ACL_STATUS, ret, 0); +} + +/** + * @brief Positive test case of display_get_image_enhance_info() + */ +static void utc_system_deviced_display_get_image_enhance_info_p(void) +{ + int ret; + + ret = display_get_image_enhance_info(); + dts_check_ge(API_NAME_DISPLAY_GET_IMAGE_ENHANCE_INFO, ret, 0); +} + +/** + * @brief Positive test case of display_get_image_enhance() + */ +static void utc_system_deviced_display_get_image_enhance_p(void) +{ + int i, ret; + + for (i = ENHANCE_MODE; i <= ENHANCE_OUTDOOR; ++i) { + ret = display_get_image_enhance(i); + dts_check_ge(API_NAME_DISPLAY_GET_IMAGE_ENHANCE, ret, 0, "enhance type : %d", i); + } +} + +/** + * @brief Negative test case of display_get_image_enhance() + */ +static void utc_system_deviced_display_get_image_enhance_n(void) +{ + int ret; + + ret = display_get_image_enhance(-1); + dts_check_ne(API_NAME_DISPLAY_GET_IMAGE_ENHANCE, ret, 0); +} + +/** + * @brief Positive test case of display_set_image_enhance() + */ +static void utc_system_deviced_display_set_image_enhance_p(void) +{ + int i, ret; + + for (i = ENHANCE_MODE; i <= ENHANCE_OUTDOOR; ++i) { + ret = display_set_image_enhance(i, 0); + dts_check_eq(API_NAME_DISPLAY_SET_IMAGE_ENHANCE, ret, 0, "enhance type : %d", i); + } +} + +/** + * @brief Negative test case of display_set_image_enhance() + */ +static void utc_system_deviced_display_set_image_enhance_n_1(void) +{ + int ret; + + ret = display_set_image_enhance(-1, 0); + dts_check_ne(API_NAME_DISPLAY_SET_IMAGE_ENHANCE, ret, 0); +} + +/** + * @brief Negative test case of display_set_image_enhance() + */ +static void utc_system_deviced_display_set_image_enhance_n_2(void) +{ + int ret; + + ret = display_set_image_enhance(0, -1); + dts_check_ne(API_NAME_DISPLAY_SET_IMAGE_ENHANCE, ret, 0); +} + +/** + * @brief Positive test case of display_set_refresh_rate() + */ +static void utc_system_deviced_display_set_refresh_rate_p(void) +{ + int i, ret; + + for (i = REFRESH_SETTING; i <= REFRESH_WEB; ++i) { + ret = display_set_refresh_rate(i, 60); + dts_check_eq(API_NAME_DISPLAY_SET_REFRESH_RATE, ret, 0, "refresh type : %d", i); + } +} + +/** + * @brief Negative test case of display_set_refresh_rate() + */ +static void utc_system_deviced_display_set_refresh_rate_n_1(void) +{ + int ret; + + ret = display_set_refresh_rate(-1, 60); + dts_check_ne(API_NAME_DISPLAY_SET_REFRESH_RATE, ret, 0); +} + +/** + * @brief Negative test case of display_set_refresh_rate() + */ +static void utc_system_deviced_display_set_refresh_rate_n_2(void) +{ + int ret; + + ret = display_set_refresh_rate(0, -1); + dts_check_ne(API_NAME_DISPLAY_SET_REFRESH_RATE, ret, 0); +} + +/** + * @brief Positive test case of display_lock_state() + */ +static void utc_system_deviced_display_lock_state_p(void) +{ + int ret; + + ret = display_lock_state(LCD_NORMAL, GOTO_STATE_NOW, 0); + dts_check_eq(API_NAME_DISPLAY_LOCK_STATE, ret, 0); +} + +/** + * @brief Negative test case of display_lock_state() + */ +static void utc_system_deviced_display_lock_state_n_1(void) +{ + int ret; + + ret = display_lock_state(-1, GOTO_STATE_NOW, 0); + dts_check_ne(API_NAME_DISPLAY_LOCK_STATE, ret, 0); +} + +/** + * @brief Negative test case of display_lock_state() + */ +static void utc_system_deviced_display_lock_state_n_2(void) +{ + int ret; + + ret = display_lock_state(LCD_NORMAL, -1, 0); + dts_check_ne(API_NAME_DISPLAY_LOCK_STATE, ret, 0); +} + +/** + * @brief Negative test case of display_lock_state() + */ +static void utc_system_deviced_display_lock_state_n_3(void) +{ + int ret; + + ret = display_lock_state(LCD_NORMAL, GOTO_STATE_NOW, -1); + dts_check_ne(API_NAME_DISPLAY_LOCK_STATE, ret, 0); +} + +/** + * @brief Positive test case of display_unlock_state() + */ +static void utc_system_deviced_display_unlock_state_p(void) +{ + int ret; + + ret = display_unlock_state(LCD_NORMAL, PM_RESET_TIMER); + dts_check_eq(API_NAME_DISPLAY_UNLOCK_STATE, ret, 0); +} + +/** + * @brief Negative test case of display_unlock_state() + */ +static void utc_system_deviced_display_unlock_state_n_1(void) +{ + int ret; + + ret = display_unlock_state(-1, PM_RESET_TIMER); + dts_check_ne(API_NAME_DISPLAY_UNLOCK_STATE, ret, 0); +} + +/** + * @brief Negative test case of display_unlock_state() + */ +static void utc_system_deviced_display_unlock_state_n_2(void) +{ + int ret; + + ret = display_unlock_state(LCD_NORMAL, -1); + dts_check_ne(API_NAME_DISPLAY_UNLOCK_STATE, ret, 0); +} + +/** + * @brief Positive test case of display_change_state() + */ +static void utc_system_deviced_display_change_state_p(void) +{ + int ret; + + ret = display_change_state(LCD_NORMAL); + dts_check_eq(API_NAME_DISPLAY_CHANGE_STATE, ret, 0); +} + +/** + * @brief Positive test case of display_change_state() + */ +static void utc_system_deviced_display_change_state_n(void) +{ + int ret; + + ret = display_change_state(-1); + dts_check_ne(API_NAME_DISPLAY_CHANGE_STATE, ret, 0); +} + +/** + * @brief Positive test case of display_get_auto_screen_tone() + */ +static void utc_system_deviced_display_get_auto_screen_tone_p(void) +{ + int ret; + + ret = display_get_auto_screen_tone(); + dts_check_ge(API_NAME_DISPLAY_GET_AUTO_SCREEN_TONE, ret, 0); +} + +/** + * @brief Positive test case of display_set_auto_screen_tone() + */ +static void utc_system_deviced_display_set_auto_screen_tone_p_1(void) +{ + int ret; + + ret = display_set_auto_screen_tone(TONE_ON); + dts_check_eq(API_NAME_DISPLAY_SET_AUTO_SCREEN_TONE, ret, 0, "Enable auto screen tone"); +} + +/** + * @brief Positive test case of display_set_auto_screen_tone() + */ +static void utc_system_deviced_display_set_auto_screen_tone_p_2(void) +{ + int ret; + + ret = display_set_auto_screen_tone(TONE_OFF); + dts_check_eq(API_NAME_DISPLAY_SET_AUTO_SCREEN_TONE, ret, 0, "Disable auto screen tone"); +} + +/** + * @brief Negative test case of display_set_auto_screen_tone() + */ +static void utc_system_deviced_display_set_auto_screen_tone_n(void) +{ + int ret; + + ret = display_set_auto_screen_tone(-1); + dts_check_ne(API_NAME_DISPLAY_SET_AUTO_SCREEN_TONE, ret, 0); +} + +/** + * @brief Positive test case of display_get_color_blind() + */ +static void utc_system_deviced_display_get_color_blind_p(void) +{ + int ret; + + ret = display_get_color_blind(); + dts_check_ge(API_NAME_DISPLAY_GET_COLOR_BLIND, ret, 0); +} + +/** + * @brief Positive test case of display_set_color_blind() + */ +static void utc_system_deviced_display_set_color_blind_p_1(void) +{ + int ret; + struct blind_color_info info = {0,}; + + ret = display_set_color_blind(true, &info); + dts_check_eq(API_NAME_DISPLAY_SET_COLOR_BLIND, ret, 0); +} + +/** + * @brief Positive test case of display_set_color_blind() + */ +static void utc_system_deviced_display_set_color_blind_p_2(void) +{ + int ret; + struct blind_color_info info = {0,}; + + ret = display_set_color_blind(false, &info); + dts_check_eq(API_NAME_DISPLAY_SET_COLOR_BLIND, ret, 0); +} + +/** + * @brief Negative test case of display_set_color_blind() + */ +static void utc_system_deviced_display_set_color_blind_n_1(void) +{ + int ret; + struct blind_color_info info = {0,}; + + ret = display_set_color_blind(-1, &info); + dts_check_ne(API_NAME_DISPLAY_SET_COLOR_BLIND, ret, 0); +} + +/** + * @brief Positive test case of display_set_color_blind() + */ +static void utc_system_deviced_display_set_color_blind_n_2(void) +{ + int ret; + + ret = display_set_color_blind(true, NULL); + dts_check_ne(API_NAME_DISPLAY_SET_COLOR_BLIND, ret, 0); +} + +/** + * @brief Positive test case of display_get_enhanced_touch() + */ +static void utc_system_deviced_display_get_enhanced_touch_p(void) +{ + int ret; + + ret = display_get_enhanced_touch(); + dts_check_ge(API_NAME_DISPLAY_GET_ENHANCED_TOUCH, ret, 0); +} + +/** + * @brief Positive test case of display_set_enhanced_touch() + */ +static void utc_system_deviced_display_set_enhanced_touch_p_1(void) +{ + int ret; + + ret = display_set_enhanced_touch(true); + dts_check_eq(API_NAME_DISPLAY_SET_ENHANCED_TOUCH, ret, 0, "Enable enhanced touch"); +} + +/** + * @brief Positive test case of display_set_enhanced_touch() + */ +static void utc_system_deviced_display_set_enhanced_touch_p_2(void) +{ + int ret; + + ret = display_set_enhanced_touch(false); + dts_check_eq(API_NAME_DISPLAY_SET_ENHANCED_TOUCH, ret, 0, "Disable enhanced touch"); +} + +/** + * @brief Negative test case of display_set_enhanced_touch() + */ +static void utc_system_deviced_display_set_enhanced_touch_n(void) +{ + int ret; + + ret = display_set_enhanced_touch(-1); + dts_check_ne(API_NAME_DISPLAY_SET_ENHANCED_TOUCH, ret, 0); +} diff --git a/test/testcase/utc_system_deviced_haptic.c b/test/testcase/utc_system_deviced_haptic.c new file mode 100644 index 0000000..d32283e --- /dev/null +++ b/test/testcase/utc_system_deviced_haptic.c @@ -0,0 +1,984 @@ +/* + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * PROPRIETARY/CONFIDENTIAL + * + * This software is the confidential and proprietary information of SAMSUNG + * ELECTRONICS ("Confidential Information"). You agree and acknowledge that + * this software is owned by Samsung and you shall not disclose such + * Confidential Information and shall use it only in accordance with the terms + * of the license agreement you entered into with SAMSUNG ELECTRONICS. SAMSUNG + * make no representations or warranties about the suitability of the software, + * either express or implied, including but not limited to the implied + * warranties of merchantability, fitness for a particular purpose, or + * non-infringement. SAMSUNG shall not be liable for any damages suffered by + * licensee arising out of or related to this software. + * + */ +#include +#include +#include +#include + +#define API_NAME_HAPTIC_STARTUP "haptic_startup" +#define API_NAME_HAPTIC_GET_COUNT "haptic_get_count" +#define API_NAME_HAPTIC_OPEN "haptic_open" +#define API_NAME_HAPTIC_CLOSE "haptic_close" +#define API_NAME_HAPTIC_VIBRATE_MONOTONE "haptic_vibrate_monotone" +#define API_NAME_HAPTIC_VIBRATE_MONOTONE_WITH_DETAIL "haptic_vibrate_monotone_with_detail" +#define API_NAME_HAPTIC_VIBRATE_FILE "haptic_vibrate_file" +#define API_NAME_HAPTIC_VIBRATE_FILE_WITH_DETAIL "haptic_vibrate_file_with_detail" +#define API_NAME_HAPTIC_VIBRATE_BUFFERS "haptic_vibrate_buffers" +#define API_NAME_HAPTIC_VIBRATE_BUFFERS_WITH_DETAIL "haptic_vibrate_buffers_with_detail" +#define API_NAME_HAPTIC_STOP_ALL_EFFECTS "haptic_stop_all_effects" +#define API_NAME_HAPTIC_GET_EFFECT_STATE "haptic_get_effect_state" +#define API_NAME_HAPTIC_CREATE_EFFECT "haptic_create_effect" +#define API_NAME_HAPTIC_SAVE_EFFECT "haptic_save_effect" +#define API_NAME_HAPTIC_GET_FILE_DURATION "haptic_get_file_duration" +#define API_NAME_HAPTIC_GET_BUFFER_DURATION "haptic_get_buffer_duration" +#define API_NAME_HAPTIC_SAVE_LED "haptic_save_led" + + +static void startup(void); +static void cleanup(void); + +void (*tet_startup)(void) = startup; +void (*tet_cleanup)(void) = cleanup; + + +static void utc_system_deviced_haptic_get_count_p(void); +static void utc_system_deviced_haptic_get_count_n(void); +static void utc_system_deviced_haptic_open_p(void); +static void utc_system_deviced_haptic_open_n_1(void); +static void utc_system_deviced_haptic_open_n_2(void); +static void utc_system_deviced_haptic_close_p(void); +static void utc_system_deviced_haptic_close_n(void); +static void utc_system_deviced_haptic_vibrate_monotone_p_1(void); +static void utc_system_deviced_haptic_vibrate_monotone_p_2(void); +static void utc_system_deviced_haptic_vibrate_monotone_n_1(void); +static void utc_system_deviced_haptic_vibrate_monotone_n_2(void); +static void utc_system_deviced_haptic_vibrate_monotone_with_detail_p_1(void); +static void utc_system_deviced_haptic_vibrate_monotone_with_detail_p_2(void); +static void utc_system_deviced_haptic_vibrate_monotone_with_detail_n_1(void); +static void utc_system_deviced_haptic_vibrate_monotone_with_detail_n_2(void); +static void utc_system_deviced_haptic_vibrate_monotone_with_detail_n_3(void); +static void utc_system_deviced_haptic_vibrate_monotone_with_detail_n_4(void); +static void utc_system_deviced_haptic_vibrate_file_p_1(void); +static void utc_system_deviced_haptic_vibrate_file_p_2(void); +static void utc_system_deviced_haptic_vibrate_file_n_1(void); +static void utc_system_deviced_haptic_vibrate_file_n_2(void); +static void utc_system_deviced_haptic_vibrate_file_with_detail_p_1(void); +static void utc_system_deviced_haptic_vibrate_file_with_detail_p_2(void); +static void utc_system_deviced_haptic_vibrate_file_with_detail_n_1(void); +static void utc_system_deviced_haptic_vibrate_file_with_detail_n_2(void); +static void utc_system_deviced_haptic_vibrate_file_with_detail_n_3(void); +static void utc_system_deviced_haptic_vibrate_file_with_detail_n_4(void); +static void utc_system_deviced_haptic_vibrate_file_with_detail_n_5(void); +static void utc_system_deviced_haptic_vibrate_buffers_p_1(void); +static void utc_system_deviced_haptic_vibrate_buffers_p_2(void); +static void utc_system_deviced_haptic_vibrate_buffers_n_1(void); +static void utc_system_deviced_haptic_vibrate_buffers_n_2(void); +static void utc_system_deviced_haptic_vibrate_buffers_n_3(void); +static void utc_system_deviced_haptic_vibrate_buffers_with_detail_p_1(void); +static void utc_system_deviced_haptic_vibrate_buffers_with_detail_p_2(void); +static void utc_system_deviced_haptic_vibrate_buffers_with_detail_n_1(void); +static void utc_system_deviced_haptic_vibrate_buffers_with_detail_n_2(void); +static void utc_system_deviced_haptic_vibrate_buffers_with_detail_n_3(void); +static void utc_system_deviced_haptic_vibrate_buffers_with_detail_n_4(void); +static void utc_system_deviced_haptic_vibrate_buffers_with_detail_n_5(void); +static void utc_system_deviced_haptic_vibrate_buffers_with_detail_n_6(void); +static void utc_system_deviced_haptic_stop_all_effects_p(void); +static void utc_system_deviced_haptic_stop_all_effects_n(void); +static void utc_system_deviced_haptic_get_effect_state_p(void); +static void utc_system_deviced_haptic_get_effect_state_n_1(void); +static void utc_system_deviced_haptic_get_effect_state_n_2(void); +static void utc_system_deviced_haptic_create_effect_p(void); +static void utc_system_deviced_haptic_create_effect_n_1(void); +static void utc_system_deviced_haptic_create_effect_n_2(void); +static void utc_system_deviced_haptic_create_effect_n_3(void); +static void utc_system_deviced_haptic_create_effect_n_4(void); +static void utc_system_deviced_haptic_save_effect_p(void); +static void utc_system_deviced_haptic_save_effect_n_1(void); +static void utc_system_deviced_haptic_save_effect_n_2(void); +static void utc_system_deviced_haptic_save_effect_n_3(void); +static void utc_system_deviced_haptic_get_file_duration_p(void); +static void utc_system_deviced_haptic_get_file_duration_n_1(void); +static void utc_system_deviced_haptic_get_file_duration_n_2(void); +static void utc_system_deviced_haptic_get_file_duration_n_3(void); +static void utc_system_deviced_haptic_get_buffer_duration_p(void); +static void utc_system_deviced_haptic_get_buffer_duration_n_1(void); +static void utc_system_deviced_haptic_get_buffer_duration_n_2(void); +static void utc_system_deviced_haptic_get_buffer_duration_n_3(void); +static void utc_system_deviced_haptic_save_led_p(void); +static void utc_system_deviced_haptic_save_led_n_1(void); +static void utc_system_deviced_haptic_save_led_n_2(void); +static void utc_system_deviced_haptic_save_led_n_3(void); + +enum { + POSITIVE_TC_IDX = 0x01, + NEGATIVE_TC_IDX, +}; + +struct tet_testlist tet_testlist[] = { + { utc_system_deviced_haptic_get_count_p, POSITIVE_TC_IDX }, + { utc_system_deviced_haptic_get_count_n, NEGATIVE_TC_IDX }, + { utc_system_deviced_haptic_open_p, POSITIVE_TC_IDX }, + { utc_system_deviced_haptic_open_n_1, NEGATIVE_TC_IDX }, + { utc_system_deviced_haptic_open_n_2, NEGATIVE_TC_IDX }, + { utc_system_deviced_haptic_create_effect_p, POSITIVE_TC_IDX }, + { utc_system_deviced_haptic_create_effect_n_1, NEGATIVE_TC_IDX }, + { utc_system_deviced_haptic_create_effect_n_2, NEGATIVE_TC_IDX }, + { utc_system_deviced_haptic_create_effect_n_3, NEGATIVE_TC_IDX }, + { utc_system_deviced_haptic_create_effect_n_4, NEGATIVE_TC_IDX }, + { utc_system_deviced_haptic_save_effect_p, POSITIVE_TC_IDX }, + { utc_system_deviced_haptic_save_effect_n_1, NEGATIVE_TC_IDX }, + { utc_system_deviced_haptic_save_effect_n_2, NEGATIVE_TC_IDX }, + { utc_system_deviced_haptic_save_effect_n_3, NEGATIVE_TC_IDX }, + { utc_system_deviced_haptic_vibrate_monotone_p_1, POSITIVE_TC_IDX }, + { utc_system_deviced_haptic_vibrate_monotone_p_2, POSITIVE_TC_IDX }, + { utc_system_deviced_haptic_vibrate_monotone_n_1, NEGATIVE_TC_IDX }, + { utc_system_deviced_haptic_vibrate_monotone_n_2, NEGATIVE_TC_IDX }, + { utc_system_deviced_haptic_vibrate_monotone_with_detail_p_1, POSITIVE_TC_IDX }, + { utc_system_deviced_haptic_vibrate_monotone_with_detail_p_2, POSITIVE_TC_IDX }, + { utc_system_deviced_haptic_vibrate_monotone_with_detail_n_1, NEGATIVE_TC_IDX }, + { utc_system_deviced_haptic_vibrate_monotone_with_detail_n_2, NEGATIVE_TC_IDX }, + { utc_system_deviced_haptic_vibrate_monotone_with_detail_n_3, NEGATIVE_TC_IDX }, + { utc_system_deviced_haptic_vibrate_monotone_with_detail_n_4, NEGATIVE_TC_IDX }, + { utc_system_deviced_haptic_vibrate_file_p_1, POSITIVE_TC_IDX }, + { utc_system_deviced_haptic_vibrate_file_p_2, POSITIVE_TC_IDX }, + { utc_system_deviced_haptic_vibrate_file_n_1, NEGATIVE_TC_IDX }, + { utc_system_deviced_haptic_vibrate_file_n_2, NEGATIVE_TC_IDX }, + { utc_system_deviced_haptic_vibrate_file_with_detail_p_1, POSITIVE_TC_IDX }, + { utc_system_deviced_haptic_vibrate_file_with_detail_p_2, POSITIVE_TC_IDX }, + { utc_system_deviced_haptic_vibrate_file_with_detail_n_1, NEGATIVE_TC_IDX }, + { utc_system_deviced_haptic_vibrate_file_with_detail_n_2, NEGATIVE_TC_IDX }, + { utc_system_deviced_haptic_vibrate_file_with_detail_n_3, NEGATIVE_TC_IDX }, + { utc_system_deviced_haptic_vibrate_file_with_detail_n_4, NEGATIVE_TC_IDX }, + { utc_system_deviced_haptic_vibrate_file_with_detail_n_5, NEGATIVE_TC_IDX }, + { utc_system_deviced_haptic_vibrate_buffers_p_1, POSITIVE_TC_IDX }, + { utc_system_deviced_haptic_vibrate_buffers_p_2, POSITIVE_TC_IDX }, + { utc_system_deviced_haptic_vibrate_buffers_n_1, NEGATIVE_TC_IDX }, + { utc_system_deviced_haptic_vibrate_buffers_n_2, NEGATIVE_TC_IDX }, + { utc_system_deviced_haptic_vibrate_buffers_n_3, NEGATIVE_TC_IDX }, + { utc_system_deviced_haptic_vibrate_buffers_with_detail_p_1, POSITIVE_TC_IDX }, + { utc_system_deviced_haptic_vibrate_buffers_with_detail_p_2, POSITIVE_TC_IDX }, + { utc_system_deviced_haptic_vibrate_buffers_with_detail_n_1, NEGATIVE_TC_IDX }, + { utc_system_deviced_haptic_vibrate_buffers_with_detail_n_2, NEGATIVE_TC_IDX }, + { utc_system_deviced_haptic_vibrate_buffers_with_detail_n_3, NEGATIVE_TC_IDX }, + { utc_system_deviced_haptic_vibrate_buffers_with_detail_n_4, NEGATIVE_TC_IDX }, + { utc_system_deviced_haptic_vibrate_buffers_with_detail_n_5, NEGATIVE_TC_IDX }, + { utc_system_deviced_haptic_vibrate_buffers_with_detail_n_6, NEGATIVE_TC_IDX }, + { utc_system_deviced_haptic_stop_all_effects_p, POSITIVE_TC_IDX }, + { utc_system_deviced_haptic_stop_all_effects_n, NEGATIVE_TC_IDX }, + { utc_system_deviced_haptic_get_effect_state_p, POSITIVE_TC_IDX }, + { utc_system_deviced_haptic_get_effect_state_n_1, NEGATIVE_TC_IDX }, + { utc_system_deviced_haptic_get_effect_state_n_2, NEGATIVE_TC_IDX }, + { utc_system_deviced_haptic_get_file_duration_p, POSITIVE_TC_IDX }, + { utc_system_deviced_haptic_get_file_duration_n_1, NEGATIVE_TC_IDX }, + { utc_system_deviced_haptic_get_file_duration_n_2, NEGATIVE_TC_IDX }, + { utc_system_deviced_haptic_get_file_duration_n_3, NEGATIVE_TC_IDX }, + { utc_system_deviced_haptic_get_buffer_duration_p, POSITIVE_TC_IDX }, + { utc_system_deviced_haptic_get_buffer_duration_n_1, NEGATIVE_TC_IDX }, + { utc_system_deviced_haptic_get_buffer_duration_n_2, NEGATIVE_TC_IDX }, + { utc_system_deviced_haptic_get_buffer_duration_n_3, NEGATIVE_TC_IDX }, + { utc_system_deviced_haptic_save_led_p, POSITIVE_TC_IDX }, + { utc_system_deviced_haptic_save_led_n_1, NEGATIVE_TC_IDX }, + { utc_system_deviced_haptic_save_led_n_2, NEGATIVE_TC_IDX }, + { utc_system_deviced_haptic_save_led_n_3, NEGATIVE_TC_IDX }, + { utc_system_deviced_haptic_close_p, POSITIVE_TC_IDX }, + { utc_system_deviced_haptic_close_n, NEGATIVE_TC_IDX }, + { NULL, 0 }, +}; + +#define DEVICED_FILE_PATH "/opt/usr/share/deviced" +#define HAPTIC_FILE_PATH DEVICED_FILE_PATH"/test.ivt" +#define BINARY_FILE_PATH DEVICED_FILE_PATH"/test.led" + +static haptic_device_h haptic_h; +static unsigned char haptic_buffer[1024]; +static int haptic_buf_size = 1024; + +static void startup(void) +{ + int ret; + + ret = mkdir(DEVICED_FILE_PATH, 0777); + if (ret < 0) + dts_message(API_NAME_HAPTIC_STARTUP, + "fail to make direcotry(%s) : %s", + DEVICED_FILE_PATH, strerror(errno)); +} + +static void cleanup(void) +{ +} + +/** + * @brief Positive test case of haptic_get_count() + */ +static void utc_system_deviced_haptic_get_count_p(void) +{ + int val, ret; + + ret = haptic_get_count(&val); + dts_check_eq(API_NAME_HAPTIC_GET_COUNT, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Negative test case of haptic_get_count() + */ +static void utc_system_deviced_haptic_get_count_n(void) +{ + int ret; + + ret = haptic_get_count(NULL); + dts_check_ne(API_NAME_HAPTIC_GET_COUNT, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Positive test case of haptic_open() + */ +static void utc_system_deviced_haptic_open_p(void) +{ + int ret; + + ret = haptic_open(HAPTIC_DEVICE_ALL, &haptic_h); + dts_check_eq(API_NAME_HAPTIC_OPEN, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Negative test case of haptic_open() + */ +static void utc_system_deviced_haptic_open_n_1(void) +{ + int ret; + + ret = haptic_open(-1, &haptic_h); + dts_check_ne(API_NAME_HAPTIC_OPEN, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Negative test case of haptic_open() + */ +static void utc_system_deviced_haptic_open_n_2(void) +{ + int ret; + + ret = haptic_open(HAPTIC_DEVICE_ALL, NULL); + dts_check_ne(API_NAME_HAPTIC_OPEN, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Positive test case of haptic_close() + */ +static void utc_system_deviced_haptic_close_p(void) +{ + int ret; + + ret = haptic_close(haptic_h); + dts_check_eq(API_NAME_HAPTIC_CLOSE, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Negative test case of haptic_close() + */ +static void utc_system_deviced_haptic_close_n(void) +{ + int ret; + + ret = haptic_close((haptic_device_h)-1); + dts_check_ne(API_NAME_HAPTIC_CLOSE, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Positive test case of haptic_vibrate_monotone() + */ +static void utc_system_deviced_haptic_vibrate_monotone_p_1(void) +{ + haptic_effect_h eh; + int ret; + + ret = haptic_vibrate_monotone(haptic_h, 1000, &eh); + dts_check_eq(API_NAME_HAPTIC_VIBRATE_MONOTONE, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Positive test case of haptic_vibrate_monotone() + */ +static void utc_system_deviced_haptic_vibrate_monotone_p_2(void) +{ + int ret; + + ret = haptic_vibrate_monotone(haptic_h, 1000, NULL); + dts_check_eq(API_NAME_HAPTIC_VIBRATE_MONOTONE, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Negative test case of haptic_vibrate_monotone() + */ +static void utc_system_deviced_haptic_vibrate_monotone_n_1(void) +{ + int ret; + + ret = haptic_vibrate_monotone((haptic_device_h)-1, 1000, NULL); + dts_check_ne(API_NAME_HAPTIC_VIBRATE_MONOTONE, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Negative test case of haptic_vibrate_monotone() + */ +static void utc_system_deviced_haptic_vibrate_monotone_n_2(void) +{ + int ret; + + ret = haptic_vibrate_monotone(haptic_h, -1, NULL); + dts_check_ne(API_NAME_HAPTIC_VIBRATE_MONOTONE, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Positive test case of haptic_vibrate_monotone_with_detail() + */ +static void utc_system_deviced_haptic_vibrate_monotone_with_detail_p_1(void) +{ + haptic_effect_h eh; + int ret; + + ret = haptic_vibrate_monotone_with_detail(haptic_h, 1000, + HAPTIC_FEEDBACK_5, HAPTIC_PRIORITY_MIN, &eh); + dts_check_eq(API_NAME_HAPTIC_VIBRATE_MONOTONE_WITH_DETAIL, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Positive test case of haptic_vibrate_monotone_with_detail() + */ +static void utc_system_deviced_haptic_vibrate_monotone_with_detail_p_2(void) +{ + int ret; + + ret = haptic_vibrate_monotone_with_detail(haptic_h, 1000, + HAPTIC_FEEDBACK_5, HAPTIC_PRIORITY_MIN, NULL); + dts_check_eq(API_NAME_HAPTIC_VIBRATE_MONOTONE_WITH_DETAIL, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Negative test case of haptic_vibrate_monotone_with_detail() + */ +static void utc_system_deviced_haptic_vibrate_monotone_with_detail_n_1(void) +{ + int ret; + + ret = haptic_vibrate_monotone_with_detail((haptic_device_h)-1, 1000, + HAPTIC_FEEDBACK_5, HAPTIC_PRIORITY_MIN, NULL); + dts_check_ne(API_NAME_HAPTIC_VIBRATE_MONOTONE_WITH_DETAIL, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Negative test case of haptic_vibrate_monotone_with_detail() + */ +static void utc_system_deviced_haptic_vibrate_monotone_with_detail_n_2(void) +{ + int ret; + + ret = haptic_vibrate_monotone_with_detail(haptic_h, -1, + HAPTIC_FEEDBACK_5, HAPTIC_PRIORITY_MIN, NULL); + dts_check_ne(API_NAME_HAPTIC_VIBRATE_MONOTONE_WITH_DETAIL, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Negative test case of haptic_vibrate_monotone_with_detail() + */ +static void utc_system_deviced_haptic_vibrate_monotone_with_detail_n_3(void) +{ + int ret; + + ret = haptic_vibrate_monotone_with_detail(haptic_h, 1000, + -1, HAPTIC_PRIORITY_MIN, NULL); + dts_check_ne(API_NAME_HAPTIC_VIBRATE_MONOTONE_WITH_DETAIL, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Negative test case of haptic_vibrate_monotone_with_detail() + */ +static void utc_system_deviced_haptic_vibrate_monotone_with_detail_n_4(void) +{ + int ret; + + ret = haptic_vibrate_monotone_with_detail(haptic_h, 1000, + HAPTIC_FEEDBACK_5, -1, NULL); + dts_check_ne(API_NAME_HAPTIC_VIBRATE_MONOTONE_WITH_DETAIL, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Positive test case of haptic_vibrate_file() + */ +static void utc_system_deviced_haptic_vibrate_file_p_1(void) +{ + haptic_effect_h eh; + int ret; + + ret = haptic_vibrate_file(haptic_h, HAPTIC_FILE_PATH, &eh); + dts_check_eq(API_NAME_HAPTIC_VIBRATE_FILE, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Positive test case of haptic_vibrate_file() + */ +static void utc_system_deviced_haptic_vibrate_file_p_2(void) +{ + int ret; + + ret = haptic_vibrate_file(haptic_h, HAPTIC_FILE_PATH, NULL); + dts_check_eq(API_NAME_HAPTIC_VIBRATE_FILE, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Negative test case of haptic_vibrate_file() + */ +static void utc_system_deviced_haptic_vibrate_file_n_1(void) +{ + int ret; + + ret = haptic_vibrate_file((haptic_device_h)-1, HAPTIC_FILE_PATH, NULL); + dts_check_ne(API_NAME_HAPTIC_VIBRATE_FILE, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Negative test case of haptic_vibrate_file() + */ +static void utc_system_deviced_haptic_vibrate_file_n_2(void) +{ + int ret; + + ret = haptic_vibrate_file(haptic_h, NULL, NULL); + dts_check_ne(API_NAME_HAPTIC_VIBRATE_FILE, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Positive test case of haptic_vibrate_file_with_detail() + */ +static void utc_system_deviced_haptic_vibrate_file_with_detail_p_1(void) +{ + haptic_effect_h eh; + int ret; + + ret = haptic_vibrate_file_with_detail(haptic_h, HAPTIC_FILE_PATH, + HAPTIC_ITERATION_ONCE, HAPTIC_FEEDBACK_5, HAPTIC_PRIORITY_MIN, &eh); + dts_check_eq(API_NAME_HAPTIC_VIBRATE_FILE_WITH_DETAIL, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Positive test case of haptic_vibrate_file_with_detail() + */ +static void utc_system_deviced_haptic_vibrate_file_with_detail_p_2(void) +{ + int ret; + + ret = haptic_vibrate_file_with_detail(haptic_h, HAPTIC_FILE_PATH, + HAPTIC_ITERATION_ONCE, HAPTIC_FEEDBACK_5, HAPTIC_PRIORITY_MIN, NULL); + dts_check_eq(API_NAME_HAPTIC_VIBRATE_FILE_WITH_DETAIL, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Negative test case of haptic_vibrate_file_with_detail() + */ +static void utc_system_deviced_haptic_vibrate_file_with_detail_n_1(void) +{ + int ret; + + ret = haptic_vibrate_file_with_detail((haptic_device_h)-1, HAPTIC_FILE_PATH, + HAPTIC_ITERATION_ONCE, HAPTIC_FEEDBACK_5, HAPTIC_PRIORITY_MIN, NULL); + dts_check_ne(API_NAME_HAPTIC_VIBRATE_FILE_WITH_DETAIL, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Negative test case of haptic_vibrate_file_with_detail() + */ +static void utc_system_deviced_haptic_vibrate_file_with_detail_n_2(void) +{ + int ret; + + ret = haptic_vibrate_file_with_detail(haptic_h, NULL, + HAPTIC_ITERATION_ONCE, HAPTIC_FEEDBACK_5, HAPTIC_PRIORITY_MIN, NULL); + dts_check_ne(API_NAME_HAPTIC_VIBRATE_FILE_WITH_DETAIL, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Negative test case of haptic_vibrate_file_with_detail() + */ +static void utc_system_deviced_haptic_vibrate_file_with_detail_n_3(void) +{ + int ret; + + ret = haptic_vibrate_file_with_detail(haptic_h, HAPTIC_FILE_PATH, + -1, HAPTIC_FEEDBACK_5, HAPTIC_PRIORITY_MIN, NULL); + dts_check_ne(API_NAME_HAPTIC_VIBRATE_FILE_WITH_DETAIL, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Negative test case of haptic_vibrate_file_with_detail() + */ +static void utc_system_deviced_haptic_vibrate_file_with_detail_n_4(void) +{ + int ret; + + ret = haptic_vibrate_file_with_detail(haptic_h, HAPTIC_FILE_PATH, + HAPTIC_ITERATION_ONCE, -1, HAPTIC_PRIORITY_MIN, NULL); + dts_check_ne(API_NAME_HAPTIC_VIBRATE_FILE_WITH_DETAIL, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Negative test case of haptic_vibrate_file_with_detail() + */ +static void utc_system_deviced_haptic_vibrate_file_with_detail_n_5(void) +{ + int ret; + + ret = haptic_vibrate_file_with_detail(haptic_h, HAPTIC_FILE_PATH, + HAPTIC_ITERATION_ONCE, HAPTIC_FEEDBACK_5, -1, NULL); + dts_check_ne(API_NAME_HAPTIC_VIBRATE_FILE_WITH_DETAIL, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Positive test case of haptic_vibrate_buffers() + */ +static void utc_system_deviced_haptic_vibrate_buffers_p_1(void) +{ + haptic_effect_h eh; + int ret; + + ret = haptic_vibrate_buffers(haptic_h, haptic_buffer, haptic_buf_size, &eh); + dts_check_eq(API_NAME_HAPTIC_VIBRATE_BUFFERS, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Positive test case of haptic_vibrate_buffers() + */ +static void utc_system_deviced_haptic_vibrate_buffers_p_2(void) +{ + int ret; + + ret = haptic_vibrate_buffers(haptic_h, haptic_buffer, haptic_buf_size, NULL); + dts_check_eq(API_NAME_HAPTIC_VIBRATE_BUFFERS, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Negative test case of haptic_vibrate_buffers() + */ +static void utc_system_deviced_haptic_vibrate_buffers_n_1(void) +{ + int ret; + + ret = haptic_vibrate_buffers((haptic_device_h)-1, haptic_buffer, haptic_buf_size, NULL); + dts_check_ne(API_NAME_HAPTIC_VIBRATE_BUFFERS, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Negative test case of haptic_vibrate_buffers() + */ +static void utc_system_deviced_haptic_vibrate_buffers_n_2(void) +{ + int ret; + + ret = haptic_vibrate_buffers(haptic_h, NULL, haptic_buf_size, NULL); + dts_check_ne(API_NAME_HAPTIC_VIBRATE_BUFFERS, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Negative test case of haptic_vibrate_buffers() + */ +static void utc_system_deviced_haptic_vibrate_buffers_n_3(void) +{ + int ret; + + ret = haptic_vibrate_buffers(haptic_h, haptic_buffer, -1, NULL); + dts_check_ne(API_NAME_HAPTIC_VIBRATE_BUFFERS, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Positive test case of haptic_vibrate_buffers_with_detail() + */ +static void utc_system_deviced_haptic_vibrate_buffers_with_detail_p_1(void) +{ + haptic_effect_h eh; + int ret; + + ret = haptic_vibrate_buffers_with_detail(haptic_h, haptic_buffer, haptic_buf_size, + HAPTIC_ITERATION_ONCE, HAPTIC_FEEDBACK_5, HAPTIC_PRIORITY_MIN, &eh); + dts_check_eq(API_NAME_HAPTIC_VIBRATE_BUFFERS_WITH_DETAIL, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Positive test case of haptic_vibrate_buffers_with_detail() + */ +static void utc_system_deviced_haptic_vibrate_buffers_with_detail_p_2(void) +{ + int ret; + + ret = haptic_vibrate_buffers_with_detail(haptic_h, haptic_buffer, haptic_buf_size, + HAPTIC_ITERATION_ONCE, HAPTIC_FEEDBACK_5, HAPTIC_PRIORITY_MIN, NULL); + dts_check_eq(API_NAME_HAPTIC_VIBRATE_BUFFERS_WITH_DETAIL, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Negative test case of haptic_vibrate_buffers_with_detail() + */ +static void utc_system_deviced_haptic_vibrate_buffers_with_detail_n_1(void) +{ + int ret; + + ret = haptic_vibrate_buffers_with_detail((haptic_device_h)-1, haptic_buffer, haptic_buf_size, + HAPTIC_ITERATION_ONCE, HAPTIC_FEEDBACK_5, HAPTIC_PRIORITY_MIN, NULL); + dts_check_ne(API_NAME_HAPTIC_VIBRATE_BUFFERS_WITH_DETAIL, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Negative test case of haptic_vibrate_buffers_with_detail() + */ +static void utc_system_deviced_haptic_vibrate_buffers_with_detail_n_2(void) +{ + int ret; + + ret = haptic_vibrate_buffers_with_detail(haptic_h, NULL, haptic_buf_size, + HAPTIC_ITERATION_ONCE, HAPTIC_FEEDBACK_5, HAPTIC_PRIORITY_MIN, NULL); + dts_check_ne(API_NAME_HAPTIC_VIBRATE_BUFFERS_WITH_DETAIL, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Negative test case of haptic_vibrate_buffers_with_detail() + */ +static void utc_system_deviced_haptic_vibrate_buffers_with_detail_n_3(void) +{ + int ret; + + ret = haptic_vibrate_buffers_with_detail(haptic_h, haptic_buffer, -1, + HAPTIC_ITERATION_ONCE, HAPTIC_FEEDBACK_5, HAPTIC_PRIORITY_MIN, NULL); + dts_check_ne(API_NAME_HAPTIC_VIBRATE_BUFFERS_WITH_DETAIL, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Negative test case of haptic_vibrate_buffers_with_detail() + */ +static void utc_system_deviced_haptic_vibrate_buffers_with_detail_n_4(void) +{ + int ret; + + ret = haptic_vibrate_buffers_with_detail(haptic_h, haptic_buffer, haptic_buf_size, + -1, HAPTIC_FEEDBACK_5, HAPTIC_PRIORITY_MIN, NULL); + dts_check_ne(API_NAME_HAPTIC_VIBRATE_BUFFERS_WITH_DETAIL, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Negative test case of haptic_vibrate_buffers_with_detail() + */ +static void utc_system_deviced_haptic_vibrate_buffers_with_detail_n_5(void) +{ + int ret; + + ret = haptic_vibrate_buffers_with_detail(haptic_h, haptic_buffer, haptic_buf_size, + HAPTIC_ITERATION_ONCE, -1, HAPTIC_PRIORITY_MIN, NULL); + dts_check_ne(API_NAME_HAPTIC_VIBRATE_BUFFERS_WITH_DETAIL, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Negative test case of haptic_vibrate_buffers_with_detail() + */ +static void utc_system_deviced_haptic_vibrate_buffers_with_detail_n_6(void) +{ + int ret; + + ret = haptic_vibrate_buffers_with_detail(haptic_h, haptic_buffer, haptic_buf_size, + HAPTIC_ITERATION_ONCE, HAPTIC_FEEDBACK_5, -1, NULL); + dts_check_ne(API_NAME_HAPTIC_VIBRATE_BUFFERS_WITH_DETAIL, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Positive test case of haptic_stop_all_effects() + */ +static void utc_system_deviced_haptic_stop_all_effects_p(void) +{ + int ret; + + ret = haptic_stop_all_effects(haptic_h); + dts_check_eq(API_NAME_HAPTIC_STOP_ALL_EFFECTS, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Negative test case of haptic_stop_all_effects() + */ +static void utc_system_deviced_haptic_stop_all_effects_n(void) +{ + int ret; + + ret = haptic_stop_all_effects((haptic_device_h)-1); + dts_check_ne(API_NAME_HAPTIC_STOP_ALL_EFFECTS, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Positive test case of haptic_get_effect_state() + */ +static void utc_system_deviced_haptic_get_effect_state_p(void) +{ + haptic_state_e val; + int ret; + + ret = haptic_get_effect_state(haptic_h, (haptic_effect_h)0, &val); + dts_check_eq(API_NAME_HAPTIC_GET_EFFECT_STATE, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Negative test case of haptic_get_effect_state() + */ +static void utc_system_deviced_haptic_get_effect_state_n_1(void) +{ + haptic_state_e val; + int ret; + + ret = haptic_get_effect_state((haptic_device_h)NULL, (haptic_effect_h)0, &val); + dts_check_ne(API_NAME_HAPTIC_GET_EFFECT_STATE, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Negative test case of haptic_get_effect_state() + */ +static void utc_system_deviced_haptic_get_effect_state_n_2(void) +{ + int ret; + + ret = haptic_get_effect_state(haptic_h, 0, NULL); + dts_check_ne(API_NAME_HAPTIC_GET_EFFECT_STATE, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Positive test case of haptic_create_effect() + */ +static void utc_system_deviced_haptic_create_effect_p(void) +{ + int ret; + haptic_effect_element_s elem[3] = { {1000, 100}, {500, 0}, {500, 100} }; + + ret = haptic_create_effect(haptic_buffer, haptic_buf_size, elem, 3); + dts_check_eq(API_NAME_HAPTIC_CREATE_EFFECT, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Negative test case of haptic_create_effect() + */ +static void utc_system_deviced_haptic_create_effect_n_1(void) +{ + int ret; + haptic_effect_element_s elem[3] = { {1000, 100}, {500, 0}, {500, 100} }; + + ret = haptic_create_effect(NULL, haptic_buf_size, elem, 3); + dts_check_ne(API_NAME_HAPTIC_CREATE_EFFECT, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Negative test case of haptic_create_effect() + */ +static void utc_system_deviced_haptic_create_effect_n_2(void) +{ + int ret; + haptic_effect_element_s elem[3] = { {1000, 100}, {500, 0}, {500, 100} }; + + ret = haptic_create_effect(haptic_buffer, -1, elem, 3); + dts_check_ne(API_NAME_HAPTIC_CREATE_EFFECT, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Negative test case of haptic_create_effect() + */ +static void utc_system_deviced_haptic_create_effect_n_3(void) +{ + int ret; + + ret = haptic_create_effect(haptic_buffer, haptic_buf_size, NULL, 3); + dts_check_ne(API_NAME_HAPTIC_CREATE_EFFECT, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Negative test case of haptic_create_effect() + */ +static void utc_system_deviced_haptic_create_effect_n_4(void) +{ + int ret; + haptic_effect_element_s elem[3] = { {1000, 100}, {500, 0}, {500, 100} }; + + ret = haptic_create_effect(haptic_buffer, haptic_buf_size, elem, -1); + dts_check_ne(API_NAME_HAPTIC_CREATE_EFFECT, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Positive test case of haptic_save_effect() + */ +static void utc_system_deviced_haptic_save_effect_p(void) +{ + int ret; + + ret = haptic_save_effect(haptic_buffer, haptic_buf_size, HAPTIC_FILE_PATH); + dts_check_eq(API_NAME_HAPTIC_SAVE_EFFECT, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Negative test case of haptic_save_effect() + */ +static void utc_system_deviced_haptic_save_effect_n_1(void) +{ + int ret; + + ret = haptic_save_effect(NULL, haptic_buf_size, HAPTIC_FILE_PATH); + dts_check_ne(API_NAME_HAPTIC_SAVE_EFFECT, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Negative test case of haptic_save_effect() + */ +static void utc_system_deviced_haptic_save_effect_n_2(void) +{ + int ret; + + ret = haptic_save_effect(haptic_buffer, -1, HAPTIC_FILE_PATH); + dts_check_ne(API_NAME_HAPTIC_SAVE_EFFECT, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Negative test case of haptic_save_effect() + */ +static void utc_system_deviced_haptic_save_effect_n_3(void) +{ + int ret; + + ret = haptic_save_effect(haptic_buffer, haptic_buf_size, NULL); + dts_check_ne(API_NAME_HAPTIC_SAVE_EFFECT, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Positive test case of haptic_get_file_duration() + */ +static void utc_system_deviced_haptic_get_file_duration_p(void) +{ + int val, ret; + + ret = haptic_get_file_duration(haptic_h, HAPTIC_FILE_PATH, &val); + dts_check_eq(API_NAME_HAPTIC_GET_FILE_DURATION, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Negative test case of haptic_get_file_duration() + */ +static void utc_system_deviced_haptic_get_file_duration_n_1(void) +{ + int val, ret; + + ret = haptic_get_file_duration((haptic_device_h)-1, HAPTIC_FILE_PATH, &val); + dts_check_ne(API_NAME_HAPTIC_GET_FILE_DURATION, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Negative test case of haptic_get_file_duration() + */ +static void utc_system_deviced_haptic_get_file_duration_n_2(void) +{ + int val, ret; + + ret = haptic_get_file_duration(haptic_h, NULL, &val); + dts_check_ne(API_NAME_HAPTIC_GET_FILE_DURATION, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Negative test case of haptic_get_file_duration() + */ +static void utc_system_deviced_haptic_get_file_duration_n_3(void) +{ + int ret; + + ret = haptic_get_file_duration(haptic_h, HAPTIC_FILE_PATH, NULL); + dts_check_ne(API_NAME_HAPTIC_GET_FILE_DURATION, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Positive test case of haptic_get_buffer_duration() + */ +static void utc_system_deviced_haptic_get_buffer_duration_p(void) +{ + int val, ret; + + ret = haptic_get_buffer_duration(haptic_h, haptic_buffer, &val); + dts_check_eq(API_NAME_HAPTIC_GET_BUFFER_DURATION, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Negative test case of haptic_get_buffer_duration() + */ +static void utc_system_deviced_haptic_get_buffer_duration_n_1(void) +{ + int val, ret; + + ret = haptic_get_buffer_duration((haptic_device_h)-1, haptic_buffer, &val); + dts_check_ne(API_NAME_HAPTIC_GET_BUFFER_DURATION, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Negative test case of haptic_get_buffer_duration() + */ +static void utc_system_deviced_haptic_get_buffer_duration_n_2(void) +{ + int val, ret; + + ret = haptic_get_buffer_duration(haptic_h, NULL, &val); + dts_check_ne(API_NAME_HAPTIC_GET_BUFFER_DURATION, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Negative test case of haptic_get_buffer_duration() + */ +static void utc_system_deviced_haptic_get_buffer_duration_n_3(void) +{ + int ret; + + ret = haptic_get_buffer_duration(haptic_h, haptic_buffer, NULL); + dts_check_ne(API_NAME_HAPTIC_GET_BUFFER_DURATION, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Positive test case of haptic_save_led() + */ +static void utc_system_deviced_haptic_save_led_p(void) +{ + int ret; + + ret = haptic_save_led(haptic_buffer, haptic_buf_size, BINARY_FILE_PATH); + dts_check_eq(API_NAME_HAPTIC_SAVE_LED, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Negative test case of haptic_save_led() + */ +static void utc_system_deviced_haptic_save_led_n_1(void) +{ + int ret; + + ret = haptic_save_led(NULL, haptic_buf_size, BINARY_FILE_PATH); + dts_check_ne(API_NAME_HAPTIC_SAVE_LED, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Negative test case of haptic_save_led() + */ +static void utc_system_deviced_haptic_save_led_n_2(void) +{ + int ret; + + ret = haptic_save_led(haptic_buffer, -1, BINARY_FILE_PATH); + dts_check_ne(API_NAME_HAPTIC_SAVE_LED, ret, HAPTIC_ERROR_NONE); +} + +/** + * @brief Negative test case of haptic_save_led() + */ +static void utc_system_deviced_haptic_save_led_n_3(void) +{ + int ret; + + ret = haptic_save_led(haptic_buffer, haptic_buf_size, NULL); + dts_check_ne(API_NAME_HAPTIC_SAVE_LED, ret, HAPTIC_ERROR_NONE); +} diff --git a/test/testcase/utc_system_deviced_led.c b/test/testcase/utc_system_deviced_led.c new file mode 100644 index 0000000..0bb512f --- /dev/null +++ b/test/testcase/utc_system_deviced_led.c @@ -0,0 +1,248 @@ +/* + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * PROPRIETARY/CONFIDENTIAL + * + * This software is the confidential and proprietary information of SAMSUNG + * ELECTRONICS ("Confidential Information"). You agree and acknowledge that + * this software is owned by Samsung and you shall not disclose such + * Confidential Information and shall use it only in accordance with the terms + * of the license agreement you entered into with SAMSUNG ELECTRONICS. SAMSUNG + * make no representations or warranties about the suitability of the software, + * either express or implied, including but not limited to the implied + * warranties of merchantability, fitness for a particular purpose, or + * non-infringement. SAMSUNG shall not be liable for any damages suffered by + * licensee arising out of or related to this software. + * + */ +#include +#include + +#define API_NAME_LED_GET_BRIGHTNESS "led_get_brightness" +#define API_NAME_LED_GET_MAX_BRIGHTNESS "led_get_max_brightness" +#define API_NAME_LED_SET_BRIGHTNESS_WITH_NOTI "led_set_brightness_with_noti" +#define API_NAME_LED_SET_IR_COMMAND "led_set_ir_command" +#define API_NAME_LED_SET_MODE_WITH_COLOR "led_set_mode_with_color" +#define API_NAME_LED_SET_MODE_WITH_PROPERTY "led_set_mode_with_property" + +static void startup(void); +static void cleanup(void); + +void (*tet_startup)(void) = startup; +void (*tet_cleanup)(void) = cleanup; + + +static void utc_system_deviced_led_get_brightness_p(void); +static void utc_system_deviced_led_get_max_brightness_p(void); +static void utc_system_deviced_led_set_brightness_with_noti_p_1(void); +static void utc_system_deviced_led_set_brightness_with_noti_p_2(void); +static void utc_system_deviced_led_set_brightness_with_noti_n(void); +static void utc_system_deviced_led_set_ir_command_p(void); +static void utc_system_deviced_led_set_ir_command_n(void); +static void utc_system_deviced_led_set_mode_with_color_p_1(void); +static void utc_system_deviced_led_set_mode_with_color_p_2(void); +static void utc_system_deviced_led_set_mode_with_color_n(void); +static void utc_system_deviced_led_set_mode_with_property_p_1(void); +static void utc_system_deviced_led_set_mode_with_property_p_2(void); +static void utc_system_deviced_led_set_mode_with_property_p_3(void); +static void utc_system_deviced_led_set_mode_with_property_p_4(void); +static void utc_system_deviced_led_set_mode_with_property_n(void); + +enum { + POSITIVE_TC_IDX = 0x01, + NEGATIVE_TC_IDX, +}; + +struct tet_testlist tet_testlist[] = { + { utc_system_deviced_led_get_brightness_p, POSITIVE_TC_IDX }, + { utc_system_deviced_led_get_max_brightness_p, POSITIVE_TC_IDX }, + { utc_system_deviced_led_set_brightness_with_noti_p_1, POSITIVE_TC_IDX }, + { utc_system_deviced_led_set_brightness_with_noti_p_2, POSITIVE_TC_IDX }, + { utc_system_deviced_led_set_brightness_with_noti_n, NEGATIVE_TC_IDX }, + { utc_system_deviced_led_set_ir_command_p, POSITIVE_TC_IDX }, + { utc_system_deviced_led_set_ir_command_n, NEGATIVE_TC_IDX }, + { utc_system_deviced_led_set_mode_with_color_p_1, POSITIVE_TC_IDX }, + { utc_system_deviced_led_set_mode_with_color_p_2, POSITIVE_TC_IDX }, + { utc_system_deviced_led_set_mode_with_color_n, NEGATIVE_TC_IDX }, + { utc_system_deviced_led_set_mode_with_property_p_1, POSITIVE_TC_IDX }, + { utc_system_deviced_led_set_mode_with_property_p_2, POSITIVE_TC_IDX }, + { utc_system_deviced_led_set_mode_with_property_p_3, POSITIVE_TC_IDX }, + { utc_system_deviced_led_set_mode_with_property_p_4, POSITIVE_TC_IDX }, + { utc_system_deviced_led_set_mode_with_property_n, NEGATIVE_TC_IDX }, + { NULL, 0 }, +}; + +static void startup(void) +{ +} + +static void cleanup(void) +{ +} + +/** + * @brief Positive test case of led_get_brightness() + */ +static void utc_system_deviced_led_get_brightness_p(void) +{ + int ret; + + ret = led_get_brightness(); + dts_check_ge(API_NAME_LED_GET_BRIGHTNESS, ret, 0); +} + +/** + * @brief Positive test case of led_get_max_brightness() + */ +static void utc_system_deviced_led_get_max_brightness_p(void) +{ + int ret; + + ret = led_get_max_brightness(); + dts_check_ge(API_NAME_LED_GET_MAX_BRIGHTNESS, ret, 0); +} + +/** + * @brief Positive test case of led_set_brightness_with_noti() + */ +static void utc_system_deviced_led_set_brightness_with_noti_p_1(void) +{ + int max, ret; + + max = led_get_max_brightness(); + + ret = led_set_brightness_with_noti(max, true); + dts_check_eq(API_NAME_LED_SET_BRIGHTNESS_WITH_NOTI, ret, 0, "Turn on torchled"); +} + +/** + * @brief Positive test case of led_set_brightness_with_noti() + */ +static void utc_system_deviced_led_set_brightness_with_noti_p_2(void) +{ + int ret; + + ret = led_set_brightness_with_noti(0, true); + dts_check_eq(API_NAME_LED_SET_BRIGHTNESS_WITH_NOTI, ret, 0, "Turn off torchled"); +} + +/** + * @brief Negative test case of led_set_brightness_with_noti() + */ +static void utc_system_deviced_led_set_brightness_with_noti_n(void) +{ + int ret; + + ret = led_set_brightness_with_noti(-1, true); + dts_check_ne(API_NAME_LED_SET_BRIGHTNESS_WITH_NOTI, ret, 0); +} + +/** + * @brief Positive test case of led_set_ir_command() + */ +static void utc_system_deviced_led_set_ir_command_p(void) +{ + int ret; + + ret = led_set_ir_command("38000,173,171,24,1880"); + dts_check_eq(API_NAME_LED_SET_IR_COMMAND, ret, 0); +} + +/** + * @brief Negative test case of led_set_ir_command() + */ +static void utc_system_deviced_led_set_ir_command_n(void) +{ + int ret; + + ret = led_set_ir_command(NULL); + dts_check_ne(API_NAME_LED_SET_IR_COMMAND, ret, 0); +} + +/** + * @brief Positive test case of led_set_mode_with_color() + */ +static void utc_system_deviced_led_set_mode_with_color_p_1(void) +{ + int ret; + + ret = led_set_mode_with_color(LED_MISSED_NOTI, true, 0xffff00ff); + dts_check_eq(API_NAME_LED_SET_MODE_WITH_COLOR, ret, 0); +} + +/** + * @brief Positive test case of led_set_mode_with_color() + */ +static void utc_system_deviced_led_set_mode_with_color_p_2(void) +{ + int ret; + + ret = led_set_mode_with_color(LED_MISSED_NOTI, false, 0xffff00ff); + dts_check_eq(API_NAME_LED_SET_MODE_WITH_COLOR, ret, 0); +} + +/** + * @brief Negative test case of led_set_mode_with_color() + */ +static void utc_system_deviced_led_set_mode_with_color_n(void) +{ + int ret; + + ret = led_set_mode_with_color(-1, true, 0xffff00ff); + dts_check_ne(API_NAME_LED_SET_MODE_WITH_COLOR, ret, 0); +} + +/** + * @brief Positive test case of led_set_mode_with_property() + */ +static void utc_system_deviced_led_set_mode_with_property_p_1(void) +{ + int ret; + + ret = led_set_mode_with_property(LED_MISSED_NOTI, true, 500, 500, 0xffff00ff); + dts_check_eq(API_NAME_LED_SET_MODE_WITH_PROPERTY, ret, 0); +} + +/** + * @brief Positive test case of led_set_mode_with_property() + */ +static void utc_system_deviced_led_set_mode_with_property_p_2(void) +{ + int ret; + + ret = led_set_mode_with_property(LED_MISSED_NOTI, false, 500, 500, 0xffff00ff); + dts_check_eq(API_NAME_LED_SET_MODE_WITH_PROPERTY, ret, 0); +} + +/** + * @brief Positive test case of led_set_mode_with_property() + */ +static void utc_system_deviced_led_set_mode_with_property_p_3(void) +{ + int ret; + + ret = led_set_mode_with_property(LED_MISSED_NOTI, true, -1, 500, 0xffff00ff); + dts_check_eq(API_NAME_LED_SET_MODE_WITH_PROPERTY, ret, 0); +} + +/** + * @brief Positive test case of led_set_mode_with_property() + */ +static void utc_system_deviced_led_set_mode_with_property_p_4(void) +{ + int ret; + + ret = led_set_mode_with_property(LED_MISSED_NOTI, true, 500, -1, 0xffff00ff); + dts_check_eq(API_NAME_LED_SET_MODE_WITH_PROPERTY, ret, 0); +} + +/** + * @brief Negative test case of led_set_mode_with_property() + */ +static void utc_system_deviced_led_set_mode_with_property_n(void) +{ + int ret; + + ret = led_set_mode_with_property(-1, true, 500, 500, 0xffff00ff); + dts_check_ne(API_NAME_LED_SET_MODE_WITH_PROPERTY, ret, 0); +} diff --git a/test/testcase/utc_system_deviced_mmc.c b/test/testcase/utc_system_deviced_mmc.c new file mode 100644 index 0000000..8a326b9 --- /dev/null +++ b/test/testcase/utc_system_deviced_mmc.c @@ -0,0 +1,105 @@ +/* + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * PROPRIETARY/CONFIDENTIAL + * + * This software is the confidential and proprietary information of SAMSUNG + * ELECTRONICS ("Confidential Information"). You agree and acknowledge that + * this software is owned by Samsung and you shall not disclose such + * Confidential Information and shall use it only in accordance with the terms + * of the license agreement you entered into with SAMSUNG ELECTRONICS. SAMSUNG + * make no representations or warranties about the suitability of the software, + * either express or implied, including but not limited to the implied + * warranties of merchantability, fitness for a particular purpose, or + * non-infringement. SAMSUNG shall not be liable for any damages suffered by + * licensee arising out of or related to this software. + * + */ +#include +#include + +#define API_NAME_MMC_SECURE_MOUNT "mmc_secure_mount" +#define API_NAME_MMC_SECURE_UNMOUNT "mmc_secure_unmount" + +static void startup(void); +static void cleanup(void); + +void (*tet_startup)(void) = startup; +void (*tet_cleanup)(void) = cleanup; + + +static void utc_system_deviced_mmc_secure_mount_p(void); +static void utc_system_deviced_mmc_secure_mount_n(void); +static void utc_system_deviced_mmc_secure_unmount_p(void); +static void utc_system_deviced_mmc_secure_unmount_n(void); + +enum { + POSITIVE_TC_IDX = 0x01, + NEGATIVE_TC_IDX, +}; + +struct tet_testlist tet_testlist[] = { + { utc_system_deviced_mmc_secure_mount_p, POSITIVE_TC_IDX }, + { utc_system_deviced_mmc_secure_mount_n, NEGATIVE_TC_IDX }, + { utc_system_deviced_mmc_secure_unmount_p, POSITIVE_TC_IDX }, + { utc_system_deviced_mmc_secure_unmount_n, NEGATIVE_TC_IDX }, + { NULL, 0 }, +}; + +#define SECURE_MOUNT_POINT "/opt/storage/secure" + +static void startup(void) +{ +} + +static void cleanup(void) +{ +} + +/** + * @brief Positive test case of mmc_secure_mount() + */ +static void utc_system_deviced_mmc_secure_mount_p(void) +{ + int ret; + + dts_message("This testcase is only valid when mmc is inserted"); + + ret = mmc_secure_mount(SECURE_MOUNT_POINT); + dts_check_eq(API_NAME_MMC_SECURE_MOUNT, ret, 0); +} + +/** + * @brief Negative test case of mmc_secure_mount() + */ +static void utc_system_deviced_mmc_secure_mount_n(void) +{ + int ret; + + dts_message("This testcase is only valid when mmc is inserted"); + + ret = mmc_secure_mount(NULL); + dts_check_ne(API_NAME_MMC_SECURE_MOUNT, ret, 0); +} + +/** + * @brief Positive test case of mmc_secure_unmount() + */ +static void utc_system_deviced_mmc_secure_unmount_p(void) +{ + int ret; + + ret = mmc_secure_unmount(SECURE_MOUNT_POINT); + dts_check_eq(API_NAME_MMC_SECURE_UNMOUNT, ret, 0); +} + +/** + * @brief Negative test case of mmc_secure_unmount() + */ +static void utc_system_deviced_mmc_secure_unmount_n(void) +{ + int ret; + + ret = mmc_secure_unmount(NULL); + dts_check_ne(API_NAME_MMC_SECURE_UNMOUNT, ret, 0); +} diff --git a/test/testcase/utc_system_deviced_storage.c b/test/testcase/utc_system_deviced_storage.c new file mode 100644 index 0000000..3eab765 --- /dev/null +++ b/test/testcase/utc_system_deviced_storage.c @@ -0,0 +1,131 @@ +/* + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * PROPRIETARY/CONFIDENTIAL + * + * This software is the confidential and proprietary information of SAMSUNG + * ELECTRONICS ("Confidential Information"). You agree and acknowledge that + * this software is owned by Samsung and you shall not disclose such + * Confidential Information and shall use it only in accordance with the terms + * of the license agreement you entered into with SAMSUNG ELECTRONICS. SAMSUNG + * make no representations or warranties about the suitability of the software, + * either express or implied, including but not limited to the implied + * warranties of merchantability, fitness for a particular purpose, or + * non-infringement. SAMSUNG shall not be liable for any damages suffered by + * licensee arising out of or related to this software. + * + */ +#include +#include + +#define API_NAME_STORAGE_GET_PATH "storage_get_path" + +static void startup(void); +static void cleanup(void); + +void (*tet_startup)(void) = startup; +void (*tet_cleanup)(void) = cleanup; + + +static void utc_system_deviced_storage_get_path_p_1(void); +static void utc_system_deviced_storage_get_path_p_2(void); +static void utc_system_deviced_storage_get_path_p_3(void); +static void utc_system_deviced_storage_get_path_n_1(void); +static void utc_system_deviced_storage_get_path_n_2(void); +static void utc_system_deviced_storage_get_path_n_3(void); + +enum { + POSITIVE_TC_IDX = 0x01, + NEGATIVE_TC_IDX, +}; + +struct tet_testlist tet_testlist[] = { + { utc_system_deviced_storage_get_path_p_1, POSITIVE_TC_IDX }, + { utc_system_deviced_storage_get_path_p_2, POSITIVE_TC_IDX }, + { utc_system_deviced_storage_get_path_p_3, POSITIVE_TC_IDX }, + { utc_system_deviced_storage_get_path_n_1, NEGATIVE_TC_IDX }, + { utc_system_deviced_storage_get_path_n_2, NEGATIVE_TC_IDX }, + { utc_system_deviced_storage_get_path_n_3, NEGATIVE_TC_IDX }, + { NULL, 0 }, +}; + + +static void startup(void) +{ +} + +static void cleanup(void) +{ +} + +/** + * @brief Positive test case of storage_get_path() + */ +static void utc_system_deviced_storage_get_path_p_1(void) +{ + char path[40]; + int ret; + + ret = storage_get_path(STORAGE_DEFAULT, path, sizeof(path)); + dts_check_eq(API_NAME_STORAGE_GET_PATH, ret, 0, "Default storage"); +} + +/** + * @brief Positive test case of storage_get_path() + */ +static void utc_system_deviced_storage_get_path_p_2(void) +{ + char path[40]; + int ret; + + ret = storage_get_path(STORAGE_INTERNAL, path, sizeof(path)); + dts_check_eq(API_NAME_STORAGE_GET_PATH, ret, 0, "Internal storage"); +} + +/** + * @brief Positive test case of storage_get_path() + */ +static void utc_system_deviced_storage_get_path_p_3(void) +{ + char path[40]; + int ret; + + ret = storage_get_path(STORAGE_EXTERNAL, path, sizeof(path)); + dts_check_eq(API_NAME_STORAGE_GET_PATH, ret, 0, "External storage"); +} + +/** + * @brief Negative test case of storage_get_path() + */ +static void utc_system_deviced_storage_get_path_n_1(void) +{ + char path[40]; + int ret; + + ret = storage_get_path(-1, path, sizeof(path)); + dts_check_ne(API_NAME_STORAGE_GET_PATH, ret, 0); +} + +/** + * @brief Negative test case of storage_get_path() + */ +static void utc_system_deviced_storage_get_path_n_2(void) +{ + char path[40]; + int ret; + + ret = storage_get_path(STORAGE_DEFAULT, NULL, sizeof(path)); + dts_check_ne(API_NAME_STORAGE_GET_PATH, ret, 0); +} + +/** + * @brief Negative test case of storage_get_path() + */ +static void utc_system_deviced_storage_get_path_n_3(void) +{ + char path[40]; + int ret; + + ret = storage_get_path(STORAGE_DEFAULT, path, -1); + dts_check_ne(API_NAME_STORAGE_GET_PATH, ret, 0); +} diff --git a/test/tet_scen b/test/tet_scen new file mode 100644 index 0000000..03f029a --- /dev/null +++ b/test/tet_scen @@ -0,0 +1,7 @@ +all + ^TEST +##### Scenarios for TEST ##### + +# Test scenario +TEST + :include:/testcase/tslist diff --git a/test/tetbuild.cfg b/test/tetbuild.cfg new file mode 100644 index 0000000..f7eda55 --- /dev/null +++ b/test/tetbuild.cfg @@ -0,0 +1,5 @@ +TET_OUTPUT_CAPTURE=True # capture option for build operation checking +TET_BUILD_TOOL=make # build with using make command +TET_BUILD_FILE=-f Makefile # execution file (Makefile) for build +TET_API_COMPLIANT=True # use TET API in Test Case ? +TET_PASS_TC_NAME=True # report passed TC name in Journal file? diff --git a/test/tetclean.cfg b/test/tetclean.cfg new file mode 100644 index 0000000..02d7030 --- /dev/null +++ b/test/tetclean.cfg @@ -0,0 +1,5 @@ +TET_OUTPUT_CAPTURE=True # capture option +TET_CLEAN_TOOL= make clean # clean tool +TET_CLEAN_FILE= Makefile # file for clean +TET_API_COMPLIANT=True # TET API useage +TET_PASS_TC_NAME=True # showing name , passed TC diff --git a/test/tetexec.cfg b/test/tetexec.cfg new file mode 100644 index 0000000..ef3e452 --- /dev/null +++ b/test/tetexec.cfg @@ -0,0 +1,5 @@ +TET_OUTPUT_CAPTURE=True # capturing execution or not +TET_EXEC_TOOL= # ex) exec : execution tool set up/ Optional +TET_EXEC_FILE= # ex) exectool : execution file/ Optional +TET_API_COMPLIANT=True # Test case or Tool usesTET API? +TET_PASS_TC_NAME=True # showing Passed TC name ? -- 2.7.4