aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChen Ganir <chen.ganir@ti.com>2012-03-20 12:35:11 +0200
committerJoão Paulo Rechi Vita <jprvita@openbossa.org>2012-06-21 18:00:18 -0300
commit5677d3a93b89bcc527bfec09d818448fc7e306b8 (patch)
tree47bf597472678d0fa0ed88e635cd38e03a04255f
parentc7dfb49e00f3f6a6fb649e7aa3df26f779008759 (diff)
downloadbluez-5677d3a93b89bcc527bfec09d818448fc7e306b8.tar.gz
bluez-5677d3a93b89bcc527bfec09d818448fc7e306b8.tar.xz
bluez-5677d3a93b89bcc527bfec09d818448fc7e306b8.zip
battery: Add battery support to btd_device
Add the battery support to btd_device. When GetProperties D-BUS function is called, a list of battery object paths is provided.
-rw-r--r--batterystate/batterystate.c82
-rw-r--r--batterystate/batterystate.h3
-rw-r--r--batterystate/main.c18
-rw-r--r--batterystate/manager.c19
-rw-r--r--batterystate/manager.h2
-rw-r--r--doc/battery-api.txt34
-rw-r--r--src/device.c45
-rw-r--r--src/device.h2
8 files changed, 193 insertions, 12 deletions
diff --git a/batterystate/batterystate.c b/batterystate/batterystate.c
index 678e1230..eba910f5 100644
--- a/batterystate/batterystate.c
+++ b/batterystate/batterystate.c
@@ -24,7 +24,9 @@
#include <config.h>
#endif
-#include <glib.h>
+#include <gdbus.h>
+#include <errno.h>
+#include <dbus/dbus.h>
#include <bluetooth/uuid.h>
#include "adapter.h"
@@ -34,12 +36,16 @@
#include "att.h"
#include "gattrib.h"
#include "gatt.h"
+#include "dbus-common.h"
#include "batterystate.h"
#include "log.h"
+#define BATTERY_INTERFACE "org.bluez.Battery"
+
#define BATTERY_LEVEL_UUID "00002a19-0000-1000-8000-00805f9b34fb"
struct battery {
+ DBusConnection *conn; /* The connection to the bus */
struct btd_device *dev; /* Device reference */
GAttrib *attrib; /* GATT connection */
guint attioid; /* Att watcher id */
@@ -50,6 +56,7 @@ struct battery {
static GSList *servers = NULL;
struct characteristic {
+ char *path; /* object path */
struct gatt_char attr; /* Characteristic */
struct battery *batt; /* Parent Battery Service */
GSList *desc; /* Descriptors */
@@ -70,9 +77,20 @@ static void char_free(gpointer user_data)
g_slist_free_full(c->desc, g_free);
+ g_free(c->path);
+
g_free(c);
}
+static void char_interface_free(gpointer user_data)
+{
+ struct characteristic *c = user_data;
+ device_remove_battery(c->batt->dev, c->path);
+
+ g_dbus_unregister_interface(c->batt->conn,
+ device_get_path(c->batt->dev), BATTERY_INTERFACE);
+}
+
static gint cmp_device(gconstpointer a, gconstpointer b)
{
const struct battery *batt = a;
@@ -95,9 +113,12 @@ static void batterystate_free(gpointer user_data)
g_attrib_unref(batt->attrib);
if (batt->chars != NULL)
- g_slist_free_full(batt->chars, char_free);
+ g_slist_free_full(batt->chars, char_interface_free);
+
+ dbus_connection_unref(batt->conn);
btd_device_unref(batt->dev);
+ g_free(batt->svc_range);
g_free(batt);
}
@@ -189,6 +210,43 @@ static void discover_desc_cb(guint8 status, const guint8 *pdu, guint16 len,
att_data_list_free(list);
}
+static DBusMessage *get_properties(DBusConnection *conn, DBusMessage *msg,
+ void *data)
+{
+ struct characteristic *c = data;
+ DBusMessageIter iter;
+ DBusMessageIter dict;
+ DBusMessage *reply;
+
+ reply = dbus_message_new_method_return(msg);
+ if (reply == NULL)
+ return NULL;
+
+ dbus_message_iter_init_append(reply, &iter);
+
+ dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
+
+ dict_append_entry(&dict, "Namespace", DBUS_TYPE_BYTE, &c->ns);
+
+ dict_append_entry(&dict, "Description", DBUS_TYPE_UINT16,
+ &c->description);
+
+ dict_append_entry(&dict, "Level", DBUS_TYPE_BYTE, &c->level);
+
+ dbus_message_iter_close_container(&iter, &dict);
+
+ return reply;
+}
+
+static const GDBusMethodTable battery_methods[] = {
+ { GDBUS_METHOD("GetProperties",
+ NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
+ get_properties) },
+ { }
+};
static void configure_batterystate_cb(GSList *characteristics, guint8 status,
gpointer user_data)
@@ -215,6 +273,20 @@ static void configure_batterystate_cb(GSList *characteristics, guint8 status,
ch->attr.value_handle = c->value_handle;
memcpy(ch->attr.uuid, c->uuid, MAX_LEN_UUID_STR + 1);
ch->batt = batt;
+ ch->path = g_strdup_printf("%s/BATT%04X",
+ device_get_path(batt->dev),
+ g_slist_length(servers));
+
+ device_add_battery(batt->dev, ch->path);
+
+ if (!g_dbus_register_interface(batt->conn, ch->path,
+ BATTERY_INTERFACE,
+ battery_methods, NULL, NULL,
+ ch, char_free)) {
+ error("D-Bus register interface %s failed",
+ BATTERY_INTERFACE);
+ continue;
+ }
batt->chars = g_slist_append(batt->chars, ch);
@@ -256,13 +328,14 @@ static void attio_disconnected_cb(gpointer user_data)
batt->attrib = NULL;
}
-int batterystate_register(struct btd_device *device, struct gatt_primary *prim)
+int batterystate_register(DBusConnection *connection, struct btd_device *device,
+ struct gatt_primary *prim)
{
struct battery *batt;
batt = g_new0(struct battery, 1);
batt->dev = btd_device_ref(device);
-
+ batt->conn = dbus_connection_ref(connection);
batt->svc_range = g_new0(struct att_range, 1);
batt->svc_range->start = prim->range.start;
batt->svc_range->end = prim->range.end;
@@ -272,6 +345,7 @@ int batterystate_register(struct btd_device *device, struct gatt_primary *prim)
batt->attioid = btd_device_add_attio_callback(device,
attio_connected_cb, attio_disconnected_cb,
batt);
+
return 0;
}
diff --git a/batterystate/batterystate.h b/batterystate/batterystate.h
index 2d30028a..63b55bc2 100644
--- a/batterystate/batterystate.h
+++ b/batterystate/batterystate.h
@@ -19,5 +19,6 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
-int batterystate_register(struct btd_device *device, struct gatt_primary *prim);
+int batterystate_register(DBusConnection *conn, struct btd_device *device,
+ struct gatt_primary *prim);
void batterystate_unregister(struct btd_device *device);
diff --git a/batterystate/main.c b/batterystate/main.c
index 360254b0..041de4ee 100644
--- a/batterystate/main.c
+++ b/batterystate/main.c
@@ -25,7 +25,7 @@
#endif
#include <stdint.h>
-#include <glib.h>
+#include <gdbus.h>
#include <errno.h>
#include "hcid.h"
@@ -33,6 +33,8 @@
#include "manager.h"
#include "log.h"
+static DBusConnection *connection = NULL;
+
static int batterystate_init(void)
{
if (!main_opts.gatt_enabled) {
@@ -40,12 +42,24 @@ static int batterystate_init(void)
return -ENOTSUP;
}
- return batterystate_manager_init();
+ connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
+ if (connection == NULL)
+ return -EIO;
+
+ if (batterystate_manager_init(connection) < 0) {
+ dbus_connection_unref(connection);
+ return -EIO;
+ }
+
+ return 0;
}
static void batterystate_exit(void)
{
batterystate_manager_exit();
+
+ dbus_connection_unref(connection);
+ connection = NULL;
}
BLUETOOTH_PLUGIN_DEFINE(batterystate, VERSION,
diff --git a/batterystate/manager.c b/batterystate/manager.c
index 62076ac9..05a14130 100644
--- a/batterystate/manager.c
+++ b/batterystate/manager.c
@@ -20,7 +20,7 @@
*
*/
-#include <glib.h>
+#include <gdbus.h>
#include <errno.h>
#include <bluetooth/uuid.h>
@@ -34,6 +34,8 @@
#define BATTERY_SERVICE_UUID "0000180f-0000-1000-8000-00805f9b34fb"
+static DBusConnection *connection = NULL;
+
static gint primary_uuid_cmp(gconstpointer a, gconstpointer b)
{
const struct gatt_primary *prim = a;
@@ -56,7 +58,7 @@ static int batterystate_driver_probe(struct btd_device *device, GSList *uuids)
prim = l->data;
- return batterystate_register(device, prim);
+ return batterystate_register(connection, device, prim);
}
static void batterystate_driver_remove(struct btd_device *device)
@@ -71,12 +73,21 @@ static struct btd_device_driver battery_device_driver = {
.remove = batterystate_driver_remove
};
-int batterystate_manager_init(void)
+int batterystate_manager_init(DBusConnection *conn)
{
- return btd_register_device_driver(&battery_device_driver);
+ int ret;
+
+ ret = btd_register_device_driver(&battery_device_driver);
+ if (!ret)
+ connection = dbus_connection_ref(conn);
+
+ return ret;
}
void batterystate_manager_exit(void)
{
btd_unregister_device_driver(&battery_device_driver);
+
+ dbus_connection_unref(connection);
+ connection = NULL;
}
diff --git a/batterystate/manager.h b/batterystate/manager.h
index 7f0bf154..9f99e709 100644
--- a/batterystate/manager.h
+++ b/batterystate/manager.h
@@ -20,5 +20,5 @@
*
*/
-int batterystate_manager_init(void);
+int batterystate_manager_init(DBusConnection *conn);
void batterystate_manager_exit(void);
diff --git a/doc/battery-api.txt b/doc/battery-api.txt
new file mode 100644
index 00000000..df1fb040
--- /dev/null
+++ b/doc/battery-api.txt
@@ -0,0 +1,34 @@
+BlueZ D-Bus Battery API description
+****************************************
+
+ Texas Instruments, Inc. <chen.ganir@ti.com>
+
+Battery Service hierarchy
+=====================================
+
+Service org.bluez
+Interface org.bluez.Battery
+Object path [variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/BATTYYYY
+
+
+Methods dict GetProperties()
+
+ Returns all properties for the interface. See the
+ Properties section for the available properties.
+
+Properties byte Namespace [readonly]
+
+ Namespace value from the battery format characteristic
+ descriptor.Combined with Description provides a unique
+ battery identifyer if multiple batteries are supported.
+
+ uint16 Description [readonly]
+
+ Description value from the battery format characteristic
+ descriptor. Combined with Namespace provides a unique
+ battery identifyer if multiple batteries are supported.
+
+ byte Level [readonly]
+
+ Battery level (0-100).
+
diff --git a/src/device.c b/src/device.c
index 967685dd..42e04055 100644
--- a/src/device.c
+++ b/src/device.c
@@ -126,6 +126,10 @@ struct att_callbacks {
gpointer user_data;
};
+struct btd_battery {
+ char *path;
+};
+
struct btd_device {
bdaddr_t bdaddr;
uint8_t bdaddr_type;
@@ -171,6 +175,8 @@ struct btd_device {
GIOChannel *att_io;
guint cleanup_id;
+
+ GSList *batteries;
};
static uint16_t uuid_list[] = {
@@ -261,6 +267,7 @@ static void device_free(gpointer user_data)
g_slist_free_full(device->primaries, g_free);
g_slist_free_full(device->attios, g_free);
g_slist_free_full(device->attios_offline, g_free);
+ g_slist_free_full(device->batteries, g_free);
att_cleanup(device);
@@ -432,6 +439,15 @@ static DBusMessage *get_properties(DBusConnection *conn,
ptr = adapter_get_path(adapter);
dict_append_entry(&dict, "Adapter", DBUS_TYPE_OBJECT_PATH, &ptr);
+ /* Batteries */
+ str = g_new0(char *, g_slist_length(device->batteries) + 1);
+ for (i = 0, l = device->batteries; l; l = l->next, i++) {
+ struct btd_battery *b = l->data;
+ str[i] = b->path;
+ }
+ dict_append_array(&dict, "Batteries", DBUS_TYPE_OBJECT_PATH, &str, i);
+ g_free(str);
+
dbus_message_iter_close_container(&iter, &dict);
return reply;
@@ -1219,6 +1235,9 @@ void device_remove(struct btd_device *device, gboolean remove_stored)
g_slist_free(device->drivers);
device->drivers = NULL;
+ g_slist_free(device->batteries);
+ device->batteries = NULL;
+
attrib_client_unregister(device->services);
btd_device_unref(device);
@@ -3173,3 +3192,29 @@ void device_set_pnpid(struct btd_device *device, uint8_t vendor_id_src,
device_set_product(device, product_id);
device_set_version(device, product_ver);
}
+
+void device_add_battery(struct btd_device *device, char *path)
+{
+ struct btd_battery *batt;
+
+ batt = g_new0(struct btd_battery, 1);
+ batt->path = path;
+ device->batteries = g_slist_append(device->batteries,
+ batt);
+}
+
+void device_remove_battery(struct btd_device *device, char *path)
+{
+ GSList *l;
+
+ for (l = device->batteries; l; l = l->next) {
+ struct btd_battery *b = l->data;
+
+ if (g_strcmp0(path, b->path) == 0) {
+ device->batteries = g_slist_remove(device->batteries,
+ b);
+ g_free(b);
+ return;
+ }
+ }
+}
diff --git a/src/device.h b/src/device.h
index 26e17f7e..6ac41976 100644
--- a/src/device.h
+++ b/src/device.h
@@ -126,3 +126,5 @@ int device_unblock(DBusConnection *conn, struct btd_device *device,
void device_set_pnpid(struct btd_device *device, uint8_t vendor_id_src,
uint16_t vendor_id, uint16_t product_id,
uint16_t product_ver);
+void device_add_battery(struct btd_device *device, char *path);
+void device_remove_battery(struct btd_device *device, char *path);