From: Chen Ganir <chen.ganir@xxxxxx> Store battery level when read, and use the level from storage when connecting, to reduce GATT traffic. --- profiles/battery/battery.c | 106 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 104 insertions(+), 2 deletions(-) diff --git a/profiles/battery/battery.c b/profiles/battery/battery.c index 95f548e..bae9487 100644 --- a/profiles/battery/battery.c +++ b/profiles/battery/battery.c @@ -27,6 +27,8 @@ #include <glib.h> #include <bluetooth/uuid.h> #include <stdbool.h> +#include <sys/file.h> +#include <stdlib.h> #include "adapter.h" #include "device.h" @@ -37,6 +39,10 @@ #include "gatt.h" #include "battery.h" #include "log.h" +#include "storage.h" + +#define BATTERY_KEY_FORMAT "%17s#%04X" +#define BATTERY_LEVEL_FORMAT "%03d" struct battery { struct btd_device *dev; /* Device reference */ @@ -77,10 +83,103 @@ static gint cmp_device(gconstpointer a, gconstpointer b) return -1; } +static inline int create_filename(char *buf, size_t size, + const bdaddr_t *bdaddr, const char *name) +{ + char addr[18]; + + ba2str(bdaddr, addr); + + return create_name(buf, size, STORAGEDIR, addr, name); +} + +static int store_battery_char(struct characteristic *chr) +{ + char filename[PATH_MAX + 1], addr[18], key[23]; + bdaddr_t sba, dba; + char level[4]; + + adapter_get_address(device_get_adapter(chr->batt->dev), &sba); + device_get_address(chr->batt->dev, &dba, NULL); + + create_filename(filename, PATH_MAX, &sba, "battery_gatt_client"); + + create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + + ba2str(&dba, addr); + + snprintf(key, sizeof(key), BATTERY_KEY_FORMAT, addr, chr->attr.handle); + snprintf(level, sizeof(level), BATTERY_LEVEL_FORMAT, chr->level); + + return textfile_caseput(filename, key, level); +} + +static char *read_battery_char(struct characteristic *chr) +{ + char filename[PATH_MAX + 1], addr[18], key[23]; + char *str, *strnew; + bdaddr_t sba, dba; + + adapter_get_address(device_get_adapter(chr->batt->dev), &sba); + device_get_address(chr->batt->dev, &dba, NULL); + + create_filename(filename, PATH_MAX, &sba, "battery_gatt_client"); + + ba2str(&dba, addr); + snprintf(key, sizeof(key), BATTERY_KEY_FORMAT, addr, chr->attr.handle); + + str = textfile_caseget(filename, key); + if (str == NULL) + return NULL; + + strnew = g_strdup(str); + g_free(str); + + return strnew; +} + +static void del_battery_char(struct characteristic *chr) +{ + char filename[PATH_MAX + 1], addr[18], key[23]; + bdaddr_t sba, dba; + + adapter_get_address(device_get_adapter(chr->batt->dev), &sba); + device_get_address(chr->batt->dev, &dba, NULL); + + create_filename(filename, PATH_MAX, &sba, "battery_gatt_client"); + + ba2str(&dba, addr); + snprintf(key, sizeof(key), BATTERY_KEY_FORMAT, addr, chr->attr.handle); + + textfile_casedel(filename, key); +} + +static gboolean read_battery_level_value(struct characteristic *chr) +{ + char *str; + + if (!chr) + return FALSE; + + str = read_battery_char(chr); + if (!str) + return FALSE; + + chr->level = atoi(str); + + btd_device_set_battery_opt(chr->devbatt, BATTERY_OPT_LEVEL, chr->level, + BATTERY_OPT_INVALID); + + g_free(str); + return TRUE; +} + static void char_free(gpointer user_data) { struct characteristic *c = user_data; + del_battery_char(c); + g_slist_free_full(c->desc, g_free); btd_device_remove_battery(c->devbatt); @@ -144,6 +243,8 @@ static void read_batterylevel_cb(guint8 status, const guint8 *pdu, guint16 len, ch->level = value[0]; btd_device_set_battery_opt(ch->devbatt, BATTERY_OPT_LEVEL, ch->level, BATTERY_OPT_INVALID); + + store_battery_char(ch); } static void process_batteryservice_char(struct characteristic *ch) @@ -315,7 +416,8 @@ update_char: btd_device_set_battery_opt(ch->devbatt, BATTERY_OPT_REFRESH_FUNC, batterylevel_refresh_cb, BATTERY_OPT_INVALID); - process_batteryservice_char(ch); + if (!read_battery_level_value(ch)) + process_batteryservice_char(ch); } static void configure_battery_cb(GSList *characteristics, guint8 status, @@ -421,7 +523,7 @@ static void attio_connected_cb(GAttrib *attrib, gpointer user_data) GSList *l; for (l = batt->chars; l; l = l->next) { struct characteristic *c = l->data; - if (!c->canNotify) + if (!read_battery_level_value(c) && !c->canNotify) process_batteryservice_char(c); } } -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html