bluez remote improvements

	* log BLE battery level to /tmp/batteries/dev_XX_XX_XX_XX_XX_XX
	* allow /tmp/gfrm200.{gp,ti}.bin to override /etc/remote/*.bin
	* cleanup

Change-Id: Ib84ca289a1b043d0c0f889d8d105938f565af3c4
diff --git a/profiles/battery/battery.c b/profiles/battery/battery.c
index 1bbaa48..58be9fd 100644
--- a/profiles/battery/battery.c
+++ b/profiles/battery/battery.c
@@ -37,6 +37,7 @@
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/param.h>
 #include <fcntl.h>
 
 #include <bluetooth/bluetooth.h>
@@ -61,8 +62,9 @@
 #define BATT_UUID		"0000180f-0000-1000-8000-00805f9b34fb"
 #define BATT_LEVEL_UUID		"00002a19-0000-1000-8000-00805f9b34fb"
 
-//#define CHECK_TIME		(24*60*60)
-#define CHECK_TIME		10
+#define BATTERY_DIR		"/tmp/batteries"
+
+#define CHECK_TIME		(8*60*60)
 
 struct service {
 	guint			attio_id;
@@ -79,7 +81,9 @@
 
 	struct service		level;
 
-	time_t			lastCheck;
+	int			batt_level;
+
+	time_t			next_check;
 };
 
 static GSList *devices = NULL;
@@ -89,7 +93,6 @@
 {
 	struct batt_device *battdev;
 
-	DBG("BATT trace");
 	battdev = g_try_new0(struct batt_device, 1);
 	if (!battdev)
 		return NULL;
@@ -102,7 +105,6 @@
 
 static void batt_free_device(struct batt_device *battdev)
 {
-	DBG("BATT trace");
 	btd_device_unref(battdev->device);
 	g_attrib_unref(battdev->attrib);
 	g_free(battdev->batt_primary);
@@ -119,23 +121,67 @@
 	return ts.tv_sec;
 }
 
+/* should really be done in the dbus agent, I think */
+static void batt_update_level_file(struct batt_device* battdev)
+{
+	char path[MAXPATHLEN], pathnew[MAXPATHLEN];
+
+	const char* addr = NULL;
+	const char* id = device_get_path(battdev->device);
+
+	/* id == /org/bluez/hci0/dev_D0_5F_B8_29_10_8D */
+
+	if (id != NULL) {
+		addr = rindex(id, '/');
+		if (addr == NULL) {
+			addr = id;
+		} else {
+			addr++;
+		}
+	}
+	if (addr == NULL || *addr == '\0') {
+		addr = "UNKNOWN";
+	}
+
+	snprintf(path, sizeof path, "%s/%s", BATTERY_DIR, addr);
+	snprintf(pathnew, sizeof pathnew, "%s.new", path);
+
+	if (mkdir(BATTERY_DIR, 0777) < 0 && errno != EEXIST) {
+		error("BATT mkdir: %s: %s", BATTERY_DIR, strerror(errno));
+		return;
+	}
+
+	FILE* fp = fopen(pathnew, "w");
+	if (fp == NULL) {
+		error("BATT fopen: %s: %s", pathnew, strerror(errno));
+		return;
+	}
+	fprintf(fp, "%d\n", battdev->batt_level);
+	fclose(fp);
+
+	if (rename(pathnew, path) != 0) {
+		error("BATT rename: %s -> %s: %s", pathnew, path, strerror(errno));
+		return;
+	}
+}
+
 static void level_read_char_cb(guint8 status, const guint8 *pdu, guint16 len,
 							gpointer user_data)
 {
 	struct batt_device *battdev = user_data;
 
-	DBG("BATT trace");
 	if (status != 0) {
 		error("BATT %s failed: %s", __func__, att_ecode2str(status));
 		return;
 	}
-	int level = pdu[1];
-	DBG("BATT level=%d", level);
+	battdev->batt_level = pdu[1];
+	DBG("BATT level=%d", battdev->batt_level);
+	batt_update_level_file(battdev);
 }
 
-static void checkLevel(struct batt_device *battdev)
+static void check_level(struct batt_device *battdev)
 {
-	battdev->lastCheck = wallclock();
+	battdev->next_check = wallclock() + CHECK_TIME;
 	if (battdev->level.value_handle == 0)
 		return;
 
@@ -143,13 +189,11 @@
 						level_read_char_cb, battdev);
 }
 
-static int isTimeForLevelCheck(struct batt_device* battdev)
+static int is_time_for_level_check(struct batt_device* battdev)
 {
-	DBG("BATT trace");
 
 	time_t now = wallclock();
-	time_t dt = now - battdev->lastCheck;
-	if (dt < CHECK_TIME) {
+	if (now < battdev->next_check) {
 		DBG("BATT not time for level check yet");
 		return 0;
 	}
@@ -190,8 +234,8 @@
 			battdev->level.value_handle = chr->value_handle;
 			DBG("BATT found BATT_LEVEL_UUID value_handle=0x%04x", chr->value_handle);
 			//discover_desc(battdev, chr, next);
-			if (isTimeForLevelCheck(battdev)) {
-				checkLevel(battdev);
+			if (is_time_for_level_check(battdev)) {
+				check_level(battdev);
 			}
 		}
 	}
@@ -203,7 +247,6 @@
 	struct gatt_primary *prim = battdev->batt_primary;
 	GSList *l;
 
-	DBG("BATT trace");
 	DBG("BATT connected");
 
 	battdev->attrib = g_attrib_ref(attrib);
@@ -216,8 +259,8 @@
 						prim->range.end, NULL,
 						char_discovered_cb, battdev);
 	} else {
-		if (isTimeForLevelCheck(battdev)) {
-			checkLevel(battdev);
+		if (is_time_for_level_check(battdev)) {
+			check_level(battdev);
 		}
 	}
 }
@@ -227,7 +270,6 @@
 	struct batt_device *battdev = user_data;
 	GSList *l;
 
-	DBG("BATT trace");
 	DBG("BATT disconnected");
 
 	if (battdev->level.attio_id > 0) {
@@ -246,7 +288,6 @@
 	GIOCondition cond = G_IO_IN | G_IO_ERR | G_IO_NVAL;
 	GIOChannel *io;
 
-	DBG("BATT trace");
 	battdev = batt_new_device(device, prim->range.start);
 	if (!battdev)
 		return NULL;
@@ -263,7 +304,6 @@
 
 static int batt_unregister_device(struct batt_device *battdev)
 {
-	DBG("BATT trace");
 	btd_device_remove_attio_callback(battdev->device, battdev->attioid);
 	batt_free_device(battdev);
 
@@ -276,7 +316,6 @@
 	const char *path = device_get_path(device);
 	GSList *primaries, *l;
 
-	DBG("BATT trace");
 	DBG("BATT path %s", path);
 
 	primaries = btd_device_get_primaries(device);
@@ -307,7 +346,6 @@
 	struct batt_device *battdev = a;
 	struct btd_device *device = b;
 
-	DBG("BATT trace");
 	if (battdev->device != device)
 		return;
 
@@ -320,7 +358,6 @@
 	struct btd_device *device = btd_service_get_device(service);
 	const char *path = device_get_path(device);
 
-	DBG("BATT trace");
 	DBG("BATT path %s", path);
 
 	g_slist_foreach(devices, remove_device, device);
@@ -337,13 +374,11 @@
 {
 	int err;
 
-	DBG("BATT trace");
 	return btd_profile_register(&batt_profile);
 }
 
 static void batt_exit(void)
 {
-	DBG("BATT trace");
 	btd_profile_unregister(&batt_profile);
 }
 
diff --git a/profiles/oad/oad.c b/profiles/oad/oad.c
index 28ab2ce..fd37cd7 100644
--- a/profiles/oad/oad.c
+++ b/profiles/oad/oad.c
@@ -131,6 +131,7 @@
 	struct oad_fwinfo	disk[OADFW_Total];
 	struct oad_fwinfo	remote[OADFW_Total];
 
+	int			force_upgrade;
 	int			retries;
 	int			num_blocks;
 	int			progress;
@@ -182,6 +183,7 @@
 		error("OAD %s failed: %s", __func__, att_ecode2str(status));
 		return;
 	}
+	oaddev->retries = 0;	// successful write
 }
 
 static void oad_identity_char_write_cb(guint8 status, const guint8 *pdu, guint16 len, gpointer user_data)
@@ -252,8 +254,6 @@
 			}
 			gatt_write_char(oaddev->attrib, oaddev->block.value_handle, block,
 				sizeof(block), oad_block_char_write_cb, oaddev);
-
-			oaddev->retries = 0;	// got a successful request
 		}
 		break;
 	case OADSTATUS_TransferSuccess:		// OK, successful transfer
@@ -400,12 +400,18 @@
 {
 	memset(oaddev->disk, 0, sizeof oaddev->disk);
 
-	// TODO(edjames): change to a directory search list
-	// /tmp for debugging
-	oad_get_firmware_info(oaddev, "/tmp/" OAD_GP_FIRMWARE);
-	oad_get_firmware_info(oaddev, "/tmp/" OAD_TI_FIRMWARE);
-	oad_get_firmware_info(oaddev, "/etc/remote/" OAD_GP_FIRMWARE);
-	oad_get_firmware_info(oaddev, "/etc/remote/" OAD_TI_FIRMWARE);
+	/* check in tmp first, to make debugging easier */
+	if (access("/tmp/" OAD_GP_FIRMWARE, R_OK) == 0 ||
+	    access("/tmp/" OAD_TI_FIRMWARE, R_OK) == 0) {
+		DBG("OAD found firmware in /tmp, ignoring /etc/remote, enabling downgrade.");
+		oaddev->force_upgrade = 1;	// allow downgrade
+		oad_get_firmware_info(oaddev, "/tmp/" OAD_GP_FIRMWARE);
+		oad_get_firmware_info(oaddev, "/tmp/" OAD_TI_FIRMWARE);
+	} else {
+		oaddev->force_upgrade = 0;
+		oad_get_firmware_info(oaddev, "/etc/remote/" OAD_GP_FIRMWARE);
+		oad_get_firmware_info(oaddev, "/etc/remote/" OAD_TI_FIRMWARE);
+	}
 
 	int i;
 	for (i = 0; i < OADFW_Total; i++) {
@@ -424,19 +430,12 @@
 
 static void oad_check_for_upgrade(struct oad_device *oaddev)
 {
-
 	if (!oad_is_time_for_upgrade_check(oaddev)) {
 		return;
 	}
 
 	oad_find_firmware(oaddev);
 
-	int force_upgrade = 0;
-//#define FORCE_UPGRADE
-#ifdef FORCE_UPGRADE
-	force_upgrade = 1;		// force backward update
-#endif
-
 	struct oad_fwinfo* fp = NULL;
 	int i;
 	for (i = 0; i < OADFW_Total; i++) {
@@ -446,7 +445,8 @@
 			continue;
 		}
 		if (oaddev->disk[i].version == oaddev->remote[i].version ||
-		    (!force_upgrade && oaddev->disk[i].version < oaddev->remote[i].version)) {
+		    (!oaddev->force_upgrade &&
+		     oaddev->disk[i].version < oaddev->remote[i].version)) {
 			DBG("OAD %s firmware is up to date", typeStr);
 		} else {
 			fp = &oaddev->disk[i];