From 4e14612aef78e56456e59b458c1561f808ba0ec7 Mon Sep 17 00:00:00 2001 From: Simon Busch Date: Thu, 4 Oct 2012 07:55:26 +0200 Subject: [PATCH 1/2] battery: split out common file handling methods into separate source file Having common functionality separated from the specific ones makes it easier to implement for a target device which is not the emulator. Both can still share the same common functionality. Open-webOS-DCO-1.0-Signed-off-by: Simon Busch --- src/rockhopper/battery/CMakeLists.txt | 3 +- .../battery/emulator/fake_battery.c | 91 +------------ src/rockhopper/battery/fileutils.c | 123 ++++++++++++++++++ src/rockhopper/battery/fileutils.h | 30 +++++ 4 files changed, 155 insertions(+), 92 deletions(-) create mode 100644 src/rockhopper/battery/fileutils.c create mode 100644 src/rockhopper/battery/fileutils.h diff --git a/src/rockhopper/battery/CMakeLists.txt b/src/rockhopper/battery/CMakeLists.txt index 0e04c5f..c9f909b 100644 --- a/src/rockhopper/battery/CMakeLists.txt +++ b/src/rockhopper/battery/CMakeLists.txt @@ -18,6 +18,5 @@ include_directories(.) -nyx_create_module(BatteryMain batterylib.c emulator/fake_battery.c) +nyx_create_module(BatteryMain fileutils.c batterylib.c emulator/fake_battery.c) install(FILES emulator/fake_battery_values.sh DESTINATION "/usr/sbin") - diff --git a/src/rockhopper/battery/emulator/fake_battery.c b/src/rockhopper/battery/emulator/fake_battery.c index 0db0ba3..4a26f90 100644 --- a/src/rockhopper/battery/emulator/fake_battery.c +++ b/src/rockhopper/battery/emulator/fake_battery.c @@ -34,6 +34,7 @@ #include "batterylib.h" #include "battery_read.h" +#include "fileutils.h" #include @@ -55,96 +56,6 @@ #define CHARGE_MAX_TEMPERATURE_C 57 #define BATTERY_MAX_TEMPERATURE_C 60 -/** - * Returns string in pre-allocated buffer. - */ - -int -FileGetString(const char *path, char *ret_string, size_t maxlen) -{ - GError *gerror = NULL; - char *contents = NULL; - gsize len; - - if (!path || !g_file_get_contents(path, &contents, &len, &gerror)) { - if (gerror) { - nyx_critical( "%s: %s", __FUNCTION__, gerror->message); - g_error_free(gerror); - } - return -1; - } - - g_strstrip(contents); - g_strlcpy(ret_string, contents, maxlen); - - g_free(contents); - - return 0; -} - -int -FileGetInt(const char *path, int *ret_data) -{ - GError *gerror = NULL; - char *contents = NULL; - char *endptr; - gsize len; - long int val; - - if (!path || !g_file_get_contents(path, &contents, &len, &gerror)) { - if (gerror) { - nyx_critical( "%s: %s", __FUNCTION__, gerror->message); - g_error_free(gerror); - } - return -1; - } - - val = strtol(contents, &endptr, 10); - if (endptr == contents) { - nyx_critical( "%s: Invalid input in %s.", - __FUNCTION__, path); - goto end; - } - - if (ret_data) - *ret_data = val; -end: - g_free(contents); - return 0; -} - -int -FileGetDouble(const char *path, double *ret_data) -{ - GError *gerror = NULL; - char *contents = NULL; - char *endptr; - gsize len; - float val; - - if (!path || !g_file_get_contents(path, &contents, &len, &gerror)) { - if (gerror) { - nyx_critical( "%s: %s", __FUNCTION__, gerror->message); - g_error_free(gerror); - } - return -1; - } - - val = strtod(contents, &endptr); - if (endptr == contents) { - nyx_critical( "%s: Invalid input in %s.", - __FUNCTION__, path); - goto end; - } - - if (ret_data) - *ret_data = val; -end: - g_free(contents); - return 0; -} - - nyx_battery_ctia_t battery_ctia_params; nyx_battery_ctia_t *get_battery_ctia_params(void) diff --git a/src/rockhopper/battery/fileutils.c b/src/rockhopper/battery/fileutils.c new file mode 100644 index 0000000..84218cc --- /dev/null +++ b/src/rockhopper/battery/fileutils.c @@ -0,0 +1,123 @@ +/* @@@LICENSE +* +* Copyright (c) 2010-2012 Hewlett-Packard Development Company, L.P. +* +* 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. +* +* LICENSE@@@ */ + +/** +* @file fileutils.c +* +* @brief Common methods to read values from a file. +* +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include + +/** + * Returns string in pre-allocated buffer. + */ + +int +FileGetString(const char *path, char *ret_string, size_t maxlen) +{ + GError *gerror = NULL; + char *contents = NULL; + gsize len; + + if (!path || !g_file_get_contents(path, &contents, &len, &gerror)) { + if (gerror) { + nyx_critical( "%s: %s", __FUNCTION__, gerror->message); + g_error_free(gerror); + } + return -1; + } + + g_strstrip(contents); + g_strlcpy(ret_string, contents, maxlen); + + g_free(contents); + + return 0; +} + +int +FileGetInt(const char *path, int *ret_data) +{ + GError *gerror = NULL; + char *contents = NULL; + char *endptr; + gsize len; + long int val; + + if (!path || !g_file_get_contents(path, &contents, &len, &gerror)) { + if (gerror) { + nyx_critical( "%s: %s", __FUNCTION__, gerror->message); + g_error_free(gerror); + } + return -1; + } + + val = strtol(contents, &endptr, 10); + if (endptr == contents) { + nyx_critical( "%s: Invalid input in %s.", + __FUNCTION__, path); + goto end; + } + + if (ret_data) + *ret_data = val; +end: + g_free(contents); + return 0; +} + +int +FileGetDouble(const char *path, double *ret_data) +{ + GError *gerror = NULL; + char *contents = NULL; + char *endptr; + gsize len; + float val; + + if (!path || !g_file_get_contents(path, &contents, &len, &gerror)) { + if (gerror) { + nyx_critical( "%s: %s", __FUNCTION__, gerror->message); + g_error_free(gerror); + } + return -1; + } + + val = strtod(contents, &endptr); + if (endptr == contents) { + nyx_critical( "%s: Invalid input in %s.", + __FUNCTION__, path); + goto end; + } + + if (ret_data) + *ret_data = val; +end: + g_free(contents); + return 0; +} diff --git a/src/rockhopper/battery/fileutils.h b/src/rockhopper/battery/fileutils.h new file mode 100644 index 0000000..3aa65a4 --- /dev/null +++ b/src/rockhopper/battery/fileutils.h @@ -0,0 +1,30 @@ +/* @@@LICENSE +* +* Copyright (c) 2010-2012 Hewlett-Packard Development Company, L.P. +* +* 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. +* +* LICENSE@@@ */ + +/** + * @file fileutils.h + */ + +#ifndef FILEUTILS_H_ +#define FILEUTILS_H_ + +int FileGetString(const char *path, char *ret_string, size_t maxlen); +int FileGetInt(const char *path, int *ret_data); +int FileGetDouble(const char *path, double *ret_data); + +#endif From ec1fa3baa5d4bfcd08b0ccd86ffffae047b9cde8 Mon Sep 17 00:00:00 2001 From: Simon Busch Date: Tue, 2 Oct 2012 14:13:55 +0200 Subject: [PATCH 2/2] battery: add a device specific implementation The implementation is based on the common linux power supply interface and is detected changes to the current status with processing uevents due to the use of libudev. Open-webOS-DCO-1.0-Signed-off-by: Simon Busch --- src/CMakeLists.txt | 10 +- src/rockhopper/battery/CMakeLists.txt | 8 +- src/rockhopper/battery/device/battery.c | 290 ++++++++++++++++++++++++ 3 files changed, 305 insertions(+), 3 deletions(-) create mode 100644 src/rockhopper/battery/device/battery.c diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 96b7b30..52dafa8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -26,6 +26,14 @@ pkg_check_modules(GLIB2 REQUIRED glib-2.0) include_directories(${GLIB2_INCLUDE_DIRS}) webos_add_compiler_flags(ALL ${GLIB2_CFLAGS_OTHER}) +pkg_check_modules(GIO REQUIRED gio-2.0) +include_directories(${GIO_INCLUDE_DIRS}) +webos_add_compiler_flags(ALL ${GIO_CFLAGS_OTHER}) + +pkg_check_modules(UDEV REQUIRED libudev) +include_directories(${UDEV_INCLUDE_DIRS}) +webos_add_compiler_flags(ALL ${UDEV_CFLAGS_OTHER}) + pkg_check_modules(NYXLIB REQUIRED nyx) include_directories(${NYXLIB_INCLUDE_DIRS}) webos_add_compiler_flags(ALL ${NYXLIB_CFLAGS_OTHER}) @@ -69,7 +77,7 @@ endif() macro(nyx_create_module module) add_library(${module} MODULE ${ARGN}) - target_link_libraries(${module} ${GLIB2_LDFLAGS} ${NYXLIB_LDFLAGS} -lrt -lpthread) + target_link_libraries(${module} ${GLIB2_LDFLAGS} ${GIO_LDFLAGS} ${UDEV_LDFLAGS} ${NYXLIB_LDFLAGS} -lrt -lpthread) install(TARGETS ${module} DESTINATION ${NYX_MODULE_DIR}) endmacro() diff --git a/src/rockhopper/battery/CMakeLists.txt b/src/rockhopper/battery/CMakeLists.txt index c9f909b..ec141d0 100644 --- a/src/rockhopper/battery/CMakeLists.txt +++ b/src/rockhopper/battery/CMakeLists.txt @@ -18,5 +18,9 @@ include_directories(.) -nyx_create_module(BatteryMain fileutils.c batterylib.c emulator/fake_battery.c) -install(FILES emulator/fake_battery_values.sh DESTINATION "/usr/sbin") +if(${WEBOS_TARGET_MACHINE_IMPL} STREQUAL emulator) + nyx_create_module(BatteryMain fileutils.c batterylib.c emulator/fake_battery.c) + install(FILES emulator/fake_battery_values.sh DESTINATION "/usr/sbin") +elseif(${WEBOS_TARGET_MACHINE_IMPL} STREQUAL device) + nyx_create_module(BatteryMain fileutils.c batterylib.c device/battery.c) +endif() diff --git a/src/rockhopper/battery/device/battery.c b/src/rockhopper/battery/device/battery.c new file mode 100644 index 0000000..5970e2f --- /dev/null +++ b/src/rockhopper/battery/device/battery.c @@ -0,0 +1,290 @@ +/* @@@LICENSE +* +* Copyright (c) 2010-2012 Hewlett-Packard Development Company, L.P. +* Copyright (c) 2012 Simon Busch +* +* 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. +* +* LICENSE@@@ */ + + +/** +* @file fake_battery.c +* +* @brief Interface for reading all the battery registers in case of qemux86 or using fake batteries. +* +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include "batterylib.h" +#include "battery_read.h" +#include "fileutils.h" + +#include + +#include +#include + +#define LOG_DOMAIN "common_linux_battery: " + +#define CHARGE_MIN_TEMPERATURE_C 0 +#define CHARGE_MAX_TEMPERATURE_C 57 +#define BATTERY_MAX_TEMPERATURE_C 60 + +nyx_battery_ctia_t battery_ctia_params; + +GIOChannel *channel; + +struct udev *udev; +struct udev_monitor *mon; + +extern nyx_device_t *nyxDev; +extern void *battery_callback_context; +extern nyx_device_callback_function_t battery_callback; + +nyx_battery_ctia_t *get_battery_ctia_params(void) +{ + battery_ctia_params.charge_min_temp_c=0; + battery_ctia_params.charge_max_temp_c=CHARGE_MAX_TEMPERATURE_C; + battery_ctia_params.battery_crit_max_temp=BATTERY_MAX_TEMPERATURE_C; + battery_ctia_params.skip_battery_authentication=true; + + return &battery_ctia_params; +} + +/** + * @brief Read battery percentage + * + * @retval Battery percentage (integer) + */ +int battery_percent(void) +{ + int now, full; + int capacity; + + /* try capacity node first but keep in mind it's not supported by all power class + * devices */ + if (!g_file_test(BATTERY_SYSFS_PATH "capacity", G_FILE_TEST_EXISTS) || + FileGetInt(BATTERY_SYSFS_PATH "capacity", &capacity) < 0) + { + /* capacity node is not available so next try is energy_now/energy_full */ + if (g_file_test(BATTERY_SYSFS_PATH "energy_now", G_FILE_TEST_EXISTS) && + g_file_test(BATTERY_SYSFS_PATH "energy_full", G_FILE_TEST_EXISTS)) + { + if (FileGetInt(BATTERY_SYSFS_PATH "energy_now", &now) < 0) + return -1; + + if (FileGetInt(BATTERY_SYSFS_PATH "energy_full", &full) < 0) + return -1; + + capacity = (now / full); + } + /* as last try we can use charge_full or charge_now */ + else if (g_file_test(BATTERY_SYSFS_PATH "charge_full", G_FILE_TEST_EXISTS) && + g_file_test(BATTERY_SYSFS_PATH "charge_now", G_FILE_TEST_EXISTS)) + { + if (FileGetInt(BATTERY_SYSFS_PATH "charge_full", &full) < 0) + return -1; + + if (FileGetInt(BATTERY_SYSFS_PATH "charge_now", &now) < 0) + return -1; + + capacity = (now / full); + } + else + { + return -1; + } + } + + return capacity; +} +/** + * @brief Read battery temperature + * + * @retval Battery temperature (integer) + */ +int battery_temperature(void) +{ + int temp; + + if (!g_file_test(BATTERY_SYSFS_PATH "temp", G_FILE_TEST_EXISTS) || + FileGetInt(BATTERY_SYSFS_PATH "temp", &temp) < 0) + return -1; + + return temp; +} + +/** + * @brief Read battery voltage + * + * @retval Battery voltage (integer) + */ + +int battery_voltage(void) +{ + int voltage; + + if (!g_file_test(BATTERY_SYSFS_PATH "voltage_now", G_FILE_TEST_EXISTS) || + FileGetInt(BATTERY_SYSFS_PATH "voltage_now", &voltage) < 0) + return -1; + + return voltage; +} + +/** + * @brief Read the amount of current being drawn by the battery. + * + * @retval Current (integer) + */ +int battery_current(void) +{ + return -1; +} + +/** + * @brief Read average current being drawn by the battery. + * + * @retval Current (integer) + */ + +int battery_avg_current(void) +{ + return -1; +} + +/** + * @brief Read battery full capacity + * + * @retval Battery capacity (double) + */ +double battery_full40(void) +{ + int energy_full; + + if (g_file_test(BATTERY_SYSFS_PATH "energy_full", G_FILE_TEST_EXISTS) && + FileGetInt(BATTERY_SYSFS_PATH "energy_full", &energy_full) < 0) + return -1; + + return (double) energy_full; +} + +/** + * @brief Read battery current raw capacity + * + * @retval Battery capacity (double) + */ + +double battery_rawcoulomb(void) +{ + return -1; +} + +/** + * @brief Read battery current capacity + * + * @retval Battery capacity (double) + */ + +double battery_coulomb(void) +{ + return -1; +} + +/** + * @brief Read battery age + * + * @retval Battery age (double) + */ +double battery_age(void) +{ + return -1; +} + + +bool battery_is_present(void) +{ + int present; + + /* We can either take present or online property into account */ + if (!g_file_test(BATTERY_SYSFS_PATH "present", G_FILE_TEST_EXISTS) || + FileGetInt(BATTERY_SYSFS_PATH "present", &present) < 0) + { + if (!g_file_test(BATTERY_SYSFS_PATH "online", G_FILE_TEST_EXISTS) || + FileGetInt(BATTERY_SYSFS_PATH "online", &present) < 0) + { + return -1; + } + } + + return present == 1 ? true : false; +} + +gboolean _handle_event(GIOChannel *channel, GIOCondition condition, gpointer data) +{ + struct udev_device *dev; + + if ((condition & G_IO_IN) == G_IO_IN) { + dev = udev_monitor_receive_device(mon); + if (dev) { + battery_callback(nyxDev, NYX_CALLBACK_STATUS_DONE, battery_callback_context); + } + } + + return TRUE; +} + +void battery_read_init(void) +{ + int fd; + + udev = udev_new(); + if (!udev) { + nyx_error("Could not initialize udev component; battery status updates will not be available"); + return; + } + + mon = udev_monitor_new_from_netlink(udev, "kernel"); + udev_monitor_filter_add_match_subsystem_devtype(mon, "power_supply", NULL); + udev_monitor_enable_receiving(mon); + fd = udev_monitor_get_fd(mon); + + channel = g_io_channel_unix_new(fd); + g_io_add_watch(channel, G_IO_IN | G_IO_HUP | G_IO_NVAL, _handle_event, NULL); +} + +bool battery_is_authenticated(const char *pair_challenge, const char *pair_response) +{ + /* not supported */ + return true; +} + +bool battery_authenticate(void) +{ + /* not supported */ + return true; +} + +void battery_set_wakeup_percent(int percentage) +{ + /* no supported */ + return; +} +