2020-10-28 07:10:59 +11:00
/*
* Copyright ( c ) 2020 The ZMK Contributors
*
* SPDX - License - Identifier : MIT
*/
# include <device.h>
2021-07-18 08:49:37 +10:00
# include <devicetree.h>
2020-10-28 07:10:59 +11:00
# include <init.h>
# include <kernel.h>
# include <drivers/sensor.h>
# include <bluetooth/services/bas.h>
# include <logging/log.h>
LOG_MODULE_DECLARE ( zmk , CONFIG_ZMK_LOG_LEVEL ) ;
2020-12-23 02:56:00 +11:00
# include <zmk/event_manager.h>
2021-03-07 16:45:51 +11:00
# include <zmk/battery.h>
2020-12-23 02:56:00 +11:00
# include <zmk/events/battery_state_changed.h>
2020-11-02 16:10:21 +11:00
2021-03-07 16:45:51 +11:00
static uint8_t last_state_of_charge = 0 ;
2021-03-05 12:50:32 +11:00
2021-03-07 16:45:51 +11:00
uint8_t zmk_battery_state_of_charge ( ) { return last_state_of_charge ; }
2021-03-05 12:50:32 +11:00
2021-07-18 08:49:37 +10:00
# if DT_HAS_CHOSEN(zmk_battery)
static const struct device * const battery = DEVICE_DT_GET ( DT_CHOSEN ( zmk_battery ) ) ;
# else
2022-04-16 13:09:35 +10:00
# warning \
" Using a node labeled BATTERY for the battery sensor is deprecated. Set a zmk,battery chosen node instead. (Ignore this if you don't have a battery sensor.) "
2021-07-18 08:49:37 +10:00
static const struct device * battery ;
# endif
2020-12-11 06:31:51 +11:00
static int zmk_battery_update ( const struct device * battery ) {
2020-10-28 07:10:59 +11:00
struct sensor_value state_of_charge ;
int rc = sensor_sample_fetch_chan ( battery , SENSOR_CHAN_GAUGE_STATE_OF_CHARGE ) ;
if ( rc ! = 0 ) {
LOG_DBG ( " Failed to fetch battery values: %d " , rc ) ;
return rc ;
}
rc = sensor_channel_get ( battery , SENSOR_CHAN_GAUGE_STATE_OF_CHARGE , & state_of_charge ) ;
if ( rc ! = 0 ) {
LOG_DBG ( " Failed to get battery state of charge: %d " , rc ) ;
return rc ;
}
2021-03-05 12:50:32 +11:00
if ( last_state_of_charge ! = state_of_charge . val1 ) {
2021-03-07 15:32:19 +11:00
last_state_of_charge = state_of_charge . val1 ;
2021-03-07 16:45:51 +11:00
LOG_DBG ( " Setting BAS GATT battery level to %d. " , last_state_of_charge ) ;
2020-10-28 07:10:59 +11:00
2021-03-07 16:45:51 +11:00
rc = bt_bas_set_battery_level ( last_state_of_charge ) ;
2020-11-02 16:10:21 +11:00
2021-03-05 12:50:32 +11:00
if ( rc ! = 0 ) {
LOG_WRN ( " Failed to set BAS GATT battery level (err %d) " , rc ) ;
return rc ;
}
rc = ZMK_EVENT_RAISE ( new_zmk_battery_state_changed (
2021-03-07 16:45:51 +11:00
( struct zmk_battery_state_changed ) { . state_of_charge = last_state_of_charge } ) ) ;
2020-11-02 16:10:21 +11:00
}
2021-03-05 12:50:32 +11:00
return rc ;
2020-10-28 07:10:59 +11:00
}
static void zmk_battery_work ( struct k_work * work ) {
int rc = zmk_battery_update ( battery ) ;
if ( rc ! = 0 ) {
LOG_DBG ( " Failed to update battery value: %d. " , rc ) ;
}
}
K_WORK_DEFINE ( battery_work , zmk_battery_work ) ;
static void zmk_battery_timer ( struct k_timer * timer ) { k_work_submit ( & battery_work ) ; }
K_TIMER_DEFINE ( battery_timer , zmk_battery_timer , NULL ) ;
2020-12-11 06:31:51 +11:00
static int zmk_battery_init ( const struct device * _arg ) {
2021-07-18 08:49:37 +10:00
# if !DT_HAS_CHOSEN(zmk_battery)
2020-10-28 07:10:59 +11:00
battery = device_get_binding ( " BATTERY " ) ;
2020-10-29 01:17:08 +11:00
if ( battery = = NULL ) {
2021-07-18 08:49:37 +10:00
return - ENODEV ;
}
LOG_WRN ( " Finding battery device labeled BATTERY is deprecated. Use zmk,battery chosen node. " ) ;
# endif
if ( ! device_is_ready ( battery ) ) {
LOG_ERR ( " Battery device \" %s \" is not ready " , battery - > name ) ;
2020-10-28 07:10:59 +11:00
return - ENODEV ;
}
int rc = zmk_battery_update ( battery ) ;
if ( rc ! = 0 ) {
LOG_DBG ( " Failed to update battery value: %d. " , rc ) ;
return rc ;
}
2022-05-17 14:51:28 +10:00
k_timer_start ( & battery_timer , K_MINUTES ( 1 ) , K_SECONDS ( CONFIG_ZMK_BATTERY_REPORT_INTERVAL ) ) ;
2020-10-28 07:10:59 +11:00
return 0 ;
}
SYS_INIT ( zmk_battery_init , APPLICATION , CONFIG_APPLICATION_INIT_PRIORITY ) ;