Linux bluetooth development
 help / color / mirror / Atom feed
From: <chen.ganir@ti.com>
To: <linux-bluetooth@vger.kernel.org>
Cc: <chen.ganir@ti.com>
Subject: [PATCH v2 10/10] battery: Support persistent battery level
Date: Thu, 13 Sep 2012 16:03:23 +0300	[thread overview]
Message-ID: <1347541403-11780-11-git-send-email-chen.ganir@ti.com> (raw)
In-Reply-To: <1347541403-11780-1-git-send-email-chen.ganir@ti.com>

From: Chen Ganir <chen.ganir@ti.com>

Store battery level when read, and use the level from storage
when connecting, to reduce GATT traffic.
---
 profiles/battery/battery.c |  107 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 105 insertions(+), 2 deletions(-)

diff --git a/profiles/battery/battery.c b/profiles/battery/battery.c
index 355c7b4..6808f1e 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);
@@ -148,6 +247,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)
@@ -313,6 +414,7 @@ static void discover_desc_cb(guint8 status, const guint8 *pdu, guint16 len,
 	}
 
 	att_data_list_free(list);
+
 }
 
 static void configure_battery_cb(GSList *characteristics, guint8 status,
@@ -364,7 +466,8 @@ static void configure_battery_cb(GSList *characteristics, guint8 status,
 						   batterylevel_refresh_cb,
 						   BATTERY_OPT_INVALID);
 
-			process_batteryservice_char(ch);
+			if (!read_battery_level_value(ch))
+				process_batteryservice_char(ch);
 		}
 	}
 }
@@ -425,7 +528,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


      parent reply	other threads:[~2012-09-13 13:03 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-09-13 13:03 [PATCH v2 00/10] Implement Generic battery and LE Battery client chen.ganir
2012-09-13 13:03 ` [PATCH v2 01/10] battery: Add generic device battery documentation chen.ganir
2012-09-13 13:03 ` [PATCH v2 02/10] battery: Implement Generic device battery chen.ganir
2012-09-13 13:03 ` [PATCH v2 03/10] battery: Add GATT Battery Client Service skeleton chen.ganir
2012-09-13 13:03 ` [PATCH v2 04/10] battery: Add client connection logic chen.ganir
2012-09-13 13:03 ` [PATCH v2 05/10] battery: Discover Characteristic Descriptors chen.ganir
2012-09-13 13:03 ` [PATCH v2 06/10] battery: Get Battery ID chen.ganir
2012-09-13 13:03 ` [PATCH v2 07/10] battery: Add Battery to device chen.ganir
2012-09-14 16:15   ` Andrzej Kaczmarek
2012-09-14 16:20     ` Andrzej Kaczmarek
2012-09-13 13:03 ` [PATCH v2 08/10] battery: Read Battery level characteristic chen.ganir
2012-09-13 14:47   ` Anderson Lizardo
2012-09-13 13:03 ` [PATCH v2 09/10] battery: Add support for notifications chen.ganir
2012-09-13 14:50   ` Anderson Lizardo
2012-09-13 13:03 ` chen.ganir [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1347541403-11780-11-git-send-email-chen.ganir@ti.com \
    --to=chen.ganir@ti.com \
    --cc=linux-bluetooth@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox