2012-03-28 14:46:25

by Ganir, Chen

[permalink] [raw]
Subject: [PATCH 0/4] Add Property Changed callbacks to btd_device

From: Chen Ganir <[email protected]>

Add a callback mechanism for the btd_device, allowing other parts of the bluez
stack to receive notifications for device properties which are changed. This
mechanism is based on the D-BUS API for Device PropertyChanged.

Chen Ganir (4):
Add property changed callback
Centralize property changed events
Use macros instead of strings
Call registered callbacks

src/device.c | 223 +++++++++++++++++++++++++++++++++++++++++++++++++---------
src/device.h | 93 ++++++++++++++++++++++++
2 files changed, 281 insertions(+), 35 deletions(-)

--
1.7.4.1



2012-03-29 10:29:13

by Johan Hedberg

[permalink] [raw]
Subject: Re: [PATCH 0/4] Add Property Changed callbacks to btd_device

Hi Chen,

On Wed, Mar 28, 2012, [email protected] wrote:
> Add a callback mechanism for the btd_device, allowing other parts of
> the bluez stack to receive notifications for device properties which
> are changed. This mechanism is based on the D-BUS API for Device
> PropertyChanged.
>
> Chen Ganir (4):
> Add property changed callback
> Centralize property changed events
> Use macros instead of strings
> Call registered callbacks
>
> src/device.c | 223 +++++++++++++++++++++++++++++++++++++++++++++++++---------
> src/device.h | 93 ++++++++++++++++++++++++
> 2 files changed, 281 insertions(+), 35 deletions(-)

I don't think all this extra code is necessary for exposing a single
device parameter like you described in the use case that you need this
for. Instead we could consider introducing a callback specific to this
very information.

If some time in the future the amount of similar callbacks grows for
various device parameters we could consider creating something more
generic for them however even then that wouldn't be based on top of
D-Bus properties (the inverse might be possible though: handling the
D-Bus property signals using this generic framework).

Johan

2012-03-29 07:44:47

by Ganir, Chen

[permalink] [raw]
Subject: RE: [PATCH 0/4] Add Property Changed callbacks to btd_device

hi,

This patch set comes as a reply to a previous discussion over the DIS plugin, with Claudio Takashi. The main concern Claudio raised was with a race condition which may occur, when HID Service is loaded before DIS is fully updated with the PNP_ID information, which is required for HID Service /dev/uhid configuration. To prevent this a few ideas were raised, and callback mechanism was one of them.

This mechanism will allow a HID Service to check for the validity of the peer device PNP_ID information (version, vendor, vendor src and product version), and if these are still missing, register a callback for those parameters to follow up with its connection to the device. HID Service cannot operate without this information, so there is no point opening a /dev/uhid before you have this information.

The internal mechanism mimics the D-BUS PropertyChanged events and uses the same events.

Currently, only the "Connected" event is implemented, just to show the idea behind this. After this patch set is applied, we can add more events as needed.

To test this, I simply used a small patch on the adapter.c file, creating a callback and printing the events after a device is created :

diff --git a/src/adapter.c b/src/adapter.c
index 7a2214a..5b57de9 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -1380,6 +1380,16 @@ static DBusMessage *cancel_device_creation(DBusConnection *conn,
return dbus_message_new_method_return(msg);
}

+static void dev_prop_changed_cb(uint16_t property, uint8_t *value, uint16_t len,struct btd_device *device)
+{
+ DBG("property:%X len:%d",property,len);
+
+ if (property == DEVICE_PROPERTY_CHANGED_CONNECTED) {
+ struct property_changed_connected *p =(struct property_changed_connected*)value;
+ DBG("Device %p connected state is %d",device,p->connected);
+ }
+}
+
static struct btd_device *create_device_internal(DBusConnection *conn,
struct btd_adapter *adapter,
const char *address, int *err)
@@ -1401,6 +1411,8 @@ static struct btd_device *create_device_internal(DBusConnection *conn,
if (!device && err)
*err = -ENOMEM;

+ btd_device_add_prop_changed_cb(device,dev_prop_changed_cb);
+
return device;
}

Thanks,
Chen Ganir


> -----Original Message-----
> From: Chen Ganir [mailto:[email protected]] On Behalf Of Ganir, Chen
> Sent: Wednesday, March 28, 2012 4:46 PM
> To: [email protected]
> Cc: Ganir, Chen
> Subject: [PATCH 0/4] Add Property Changed callbacks to btd_device
>
> From: Chen Ganir <[email protected]>
>
> Add a callback mechanism for the btd_device, allowing other parts of
> the bluez
> stack to receive notifications for device properties which are changed.
> This
> mechanism is based on the D-BUS API for Device PropertyChanged.
>
> Chen Ganir (4):
> Add property changed callback
> Centralize property changed events
> Use macros instead of strings
> Call registered callbacks
>
> src/device.c | 223 +++++++++++++++++++++++++++++++++++++++++++++++++-
> --------
> src/device.h | 93 ++++++++++++++++++++++++
> 2 files changed, 281 insertions(+), 35 deletions(-)
>
> --
> 1.7.4.1


2012-03-28 14:46:29

by Ganir, Chen

[permalink] [raw]
Subject: [PATCH 4/4] Call registered callbacks

From: Chen Ganir <[email protected]>

On Property Changed, call the registered callbacks, with the event
data payload.
---
src/device.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++
src/device.h | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 130 insertions(+), 1 deletions(-)

diff --git a/src/device.c b/src/device.c
index dbabd87..4e7685e 100644
--- a/src/device.c
+++ b/src/device.c
@@ -128,6 +128,13 @@ struct att_callbacks {
struct prop_changed_cb {
guint id;
dev_property_changed_cb cb;
+ struct btd_device *device;
+};
+
+struct prop_changed_cb_data {
+ uint16_t property;
+ uint16_t len;
+ void *data;
};

struct btd_device {
@@ -205,6 +212,13 @@ const char *property_name[] = { "Address",
"Adapter",
"LegacyPairing"};

+static void property_changed_update_cb(struct prop_changed_cb *cb,
+ struct prop_changed_cb_data *data)
+{
+ if (cb->cb != NULL)
+ (cb->cb)(data->property, data->data, data->len,cb->device);
+}
+
static void notify_property_changed(struct btd_device *device,
DBusConnection *conn,
const char *path,
@@ -213,12 +227,56 @@ static void notify_property_changed(struct btd_device *device,
{
const char *interface = DEVICE_INTERFACE;
const char *name = "";
+ struct prop_changed_cb_data *cb_data = NULL;

if (property > 0 && property <= DEVICE_PROPERTY_CHANGED_LEGACYPAIRING)
name = property_name[property-1];
else
name = "UNKNOWN";

+ cb_data = g_new0(struct prop_changed_cb_data, 1);
+
+ if (cb_data != NULL) {
+ cb_data->property = property;
+
+ switch (property) {
+ case DEVICE_PROPERTY_CHANGED_CONNECTED:
+ {
+ struct property_changed_connected *p = g_new0(struct property_changed_connected,1);
+ p->connected = *(gboolean*)value;
+ cb_data->data = p;
+ cb_data->len = sizeof(struct property_changed_connected);
+ break;
+ }
+ case DEVICE_PROPERTY_CHANGED_ADDRESS:
+ case DEVICE_PROPERTY_CHANGED_NAME:
+ case DEVICE_PROPERTY_CHANGED_VENDOR:
+ case DEVICE_PROPERTY_CHANGED_PRODUCT:
+ case DEVICE_PROPERTY_CHANGED_VERSION:
+ case DEVICE_PROPERTY_CHANGED_ICON:
+ case DEVICE_PROPERTY_CHANGED_CLASS:
+ case DEVICE_PROPERTY_CHANGED_UUIDS:
+ case DEVICE_PROPERTY_CHANGED_SERVICES:
+ case DEVICE_PROPERTY_CHANGED_PAIRED:
+ case DEVICE_PROPERTY_CHANGED_TRUSTED:
+ case DEVICE_PROPERTY_CHANGED_BLOCKED:
+ case DEVICE_PROPERTY_CHANGED_ALIAS:
+ case DEVICE_PROPERTY_CHANGED_NODES:
+ case DEVICE_PROPERTY_CHANGED_ADAPTER:
+ case DEVICE_PROPERTY_CHANGED_LEGACYPAIRING:
+ default:
+ break;
+ }
+
+ if (cb_data != NULL && cb_data->len > 0 && cb_data->data != NULL) {
+ g_slist_foreach(device->cb_list, (GFunc) property_changed_update_cb, cb_data);
+ }
+
+ g_free(cb_data->data);
+ g_free(cb_data);
+ }
+
+
if (num == 0)
emit_property_changed(conn, path,
interface, name,
@@ -3067,6 +3125,7 @@ guint btd_device_add_prop_changed_cb(struct btd_device *device, dev_property_cha
cb = g_new0(struct prop_changed_cb, 1);
cb->id = ++cb_id;
cb->cb = cbfunc;
+ cb->device = device;

device->cb_list = g_slist_append(device->cb_list, cb);

diff --git a/src/device.h b/src/device.h
index ce0a83a..3c54255 100644
--- a/src/device.h
+++ b/src/device.h
@@ -26,25 +26,95 @@

struct btd_device;

-typedef void (*dev_property_changed_cb)(uint16_t property, uint8_t *value, uint16_t len);
+typedef void (*dev_property_changed_cb)(uint16_t property, uint8_t *value, uint16_t len,struct btd_device *device);

#define DEVICE_PROPERTY_CHANGED_ADDRESS 0x01
+struct property_changed_address {
+ char *address;
+};
+
#define DEVICE_PROPERTY_CHANGED_NAME 0x02
+struct property_changed_name {
+ char *name;
+};
+
#define DEVICE_PROPERTY_CHANGED_VENDOR 0x03
+struct propery_changed_vendor {
+ uint16_t vendor;
+};
+
#define DEVICE_PROPERTY_CHANGED_PRODUCT 0x04
+struct propery_changed_product {
+ uint16_t product;
+};
+
#define DEVICE_PROPERTY_CHANGED_VERSION 0x05
+struct propery_changed_version {
+ uint16_t version;
+};
+
#define DEVICE_PROPERTY_CHANGED_ICON 0x06
+struct property_changed_icon {
+ char *icon;
+};
+
#define DEVICE_PROPERTY_CHANGED_CLASS 0x07
+struct propery_changed_class {
+ uint32_t class;
+};
+
#define DEVICE_PROPERTY_CHANGED_UUIDS 0x08
+struct propery_changed_uuid {
+ uint16_t count;
+ char *uuid[];
+};
+
#define DEVICE_PROPERTY_CHANGED_SERVICES 0x09
+struct propery_changed_services {
+ uint16_t count;
+ char *services[];
+};
+
#define DEVICE_PROPERTY_CHANGED_PAIRED 0x0A
+struct propery_changed_paired {
+ gboolean paired;
+};
+
#define DEVICE_PROPERTY_CHANGED_CONNECTED 0x0B
+struct property_changed_connected {
+ gboolean connected;
+};
+
#define DEVICE_PROPERTY_CHANGED_TRUSTED 0x0C
+struct propery_changed_trusted {
+ gboolean trusted;
+};
+
#define DEVICE_PROPERTY_CHANGED_BLOCKED 0x0D
+struct propery_changed_blocked {
+ gboolean blocked;
+};
+
#define DEVICE_PROPERTY_CHANGED_ALIAS 0x0E
+struct property_changed_alias {
+ char *alias;
+};
+
#define DEVICE_PROPERTY_CHANGED_NODES 0x0F
+struct propery_changed_nodes {
+ uint16_t count;
+ char *nodes[];
+};
+
#define DEVICE_PROPERTY_CHANGED_ADAPTER 0x10
+struct propery_changed_adapter {
+ char adapter;
+};
+
#define DEVICE_PROPERTY_CHANGED_LEGACYPAIRING 0x11
+struct propery_changed_legacy_pairing {
+ gboolean legacy_pairing;
+};

typedef enum {
AUTH_TYPE_PINCODE,
--
1.7.4.1


2012-03-28 14:46:28

by Ganir, Chen

[permalink] [raw]
Subject: [PATCH 3/4] Use macros instead of strings

From: Chen Ganir <[email protected]>

Use macros instead of strings when calling notify_property_changed.
Use a helper array to get the correct D-BUS Property name.
---
src/device.c | 96 ++++++++++++++++++++++++++++++++++++++++------------------
src/device.h | 18 +++++++++++
2 files changed, 84 insertions(+), 30 deletions(-)

diff --git a/src/device.c b/src/device.c
index fbed9f8..dbabd87 100644
--- a/src/device.c
+++ b/src/device.c
@@ -187,13 +187,37 @@ static uint16_t uuid_list[] = {

static GSList *device_drivers = NULL;

-
-static void notify_property_changed(DBusConnection *conn,
+const char *property_name[] = { "Address",
+ "Name",
+ "Vendor",
+ "Product",
+ "Version",
+ "Icon",
+ "Class",
+ "UUIDs",
+ "Services",
+ "Paired",
+ "Connected",
+ "Trusted",
+ "Blocked",
+ "Alias",
+ "Nodes",
+ "Adapter",
+ "LegacyPairing"};
+
+static void notify_property_changed(struct btd_device *device,
+ DBusConnection *conn,
const char *path,
- const char *name,
+ const uint16_t property,
int type, void *value, int num)
{
const char *interface = DEVICE_INTERFACE;
+ const char *name = "";
+
+ if (property > 0 && property <= DEVICE_PROPERTY_CHANGED_LEGACYPAIRING)
+ name = property_name[property-1];
+ else
+ name = "UNKNOWN";

if (num == 0)
emit_property_changed(conn, path,
@@ -480,8 +504,9 @@ static DBusMessage *set_alias(DBusConnection *conn, DBusMessage *msg,
g_free(device->alias);
device->alias = g_str_equal(alias, "") ? NULL : g_strdup(alias);

- notify_property_changed(conn, dbus_message_get_path(msg),
- "Alias", DBUS_TYPE_STRING, &alias, 0);
+ notify_property_changed(device, conn, dbus_message_get_path(msg),
+ DEVICE_PROPERTY_CHANGED_ALIAS,
+ DBUS_TYPE_STRING, &alias, 0);

return dbus_message_new_method_return(msg);
}
@@ -508,8 +533,9 @@ static DBusMessage *set_trust(DBusConnection *conn, DBusMessage *msg,

device->trusted = value;

- notify_property_changed(conn, dbus_message_get_path(msg),
- "Trusted", DBUS_TYPE_BOOLEAN, &value, 0);
+ notify_property_changed(device, conn, dbus_message_get_path(msg),
+ DEVICE_PROPERTY_CHANGED_TRUSTED,
+ DBUS_TYPE_BOOLEAN, &value, 0);

return dbus_message_new_method_return(msg);
}
@@ -565,8 +591,9 @@ int device_block(DBusConnection *conn, struct btd_device *device,

device_set_temporary(device, FALSE);

- notify_property_changed(conn, device->path, "Blocked",
- DBUS_TYPE_BOOLEAN, &device->blocked, 0);
+ notify_property_changed(device, conn, device->path,
+ DEVICE_PROPERTY_CHANGED_BLOCKED, DBUS_TYPE_BOOLEAN,
+ &device->blocked, 0);

return 0;
}
@@ -596,8 +623,10 @@ int device_unblock(DBusConnection *conn, struct btd_device *device,
error("write_blocked(): %s (%d)", strerror(-err), -err);

if (!silent) {
- notify_property_changed(conn, device->path,
- "Blocked", DBUS_TYPE_BOOLEAN, &device->blocked, 0);
+ notify_property_changed(device, conn, device->path,
+ DEVICE_PROPERTY_CHANGED_BLOCKED,
+ DBUS_TYPE_BOOLEAN, &device->blocked, 0);
+
device_probe_drivers(device, device->uuids);
}

@@ -922,8 +951,10 @@ void device_add_connection(struct btd_device *device, DBusConnection *conn)

device->connected = TRUE;

- notify_property_changed(conn, device->path,
- "Connected", DBUS_TYPE_BOOLEAN, &device->connected, 0);
+ notify_property_changed(device, conn, device->path,
+ DEVICE_PROPERTY_CHANGED_CONNECTED,
+ DBUS_TYPE_BOOLEAN, &device->connected, 0);
+
}

void device_remove_connection(struct btd_device *device, DBusConnection *conn)
@@ -952,8 +983,9 @@ void device_remove_connection(struct btd_device *device, DBusConnection *conn)
if (device_is_paired(device) && !device_is_bonded(device))
device_set_paired(device, FALSE);

- notify_property_changed(conn, device->path,
- "Connected", DBUS_TYPE_BOOLEAN, &device->connected, 0);
+ notify_property_changed(device, conn, device->path,
+ DEVICE_PROPERTY_CHANGED_CONNECTED,
+ DBUS_TYPE_BOOLEAN, &device->connected, 0);
}

guint device_add_disconnect_watch(struct btd_device *device,
@@ -1001,8 +1033,8 @@ static void device_set_vendor(struct btd_device *device, uint16_t value)

device->vendor = value;

- notify_property_changed(conn, device->path, "Vendor",
- DBUS_TYPE_UINT16, &value, 0);
+ notify_property_changed(device, conn, device->path,
+ DEVICE_PROPERTY_CHANGED_VENDOR, DBUS_TYPE_UINT16, &value, 0);
}

static void device_set_product(struct btd_device *device, uint16_t value)
@@ -1014,8 +1046,8 @@ static void device_set_product(struct btd_device *device, uint16_t value)

device->product = value;

- notify_property_changed(conn, device->path, "Product",
- DBUS_TYPE_UINT16, &value, 0);
+ notify_property_changed(device, conn, device->path,
+ DEVICE_PROPERTY_CHANGED_PRODUCT, DBUS_TYPE_UINT16, &value, 0);
}

static void device_set_version(struct btd_device *device, uint16_t value)
@@ -1027,8 +1059,8 @@ static void device_set_version(struct btd_device *device, uint16_t value)

device->version = value;

- notify_property_changed(conn, device->path, "Version",
- DBUS_TYPE_UINT16, &value, 0);
+ notify_property_changed(device, conn, device->path,
+ DEVICE_PROPERTY_CHANGED_VERSION, DBUS_TYPE_UINT16, &value, 0);
}

struct btd_device *device_create(DBusConnection *conn,
@@ -1102,14 +1134,17 @@ void device_set_name(struct btd_device *device, const char *name)

strncpy(device->name, name, MAX_NAME_LENGTH);

- notify_property_changed(conn, device->path,
- "Name", DBUS_TYPE_STRING, &name, 0);
+ notify_property_changed(device, conn, device->path,
+ DEVICE_PROPERTY_CHANGED_NAME,
+ DBUS_TYPE_STRING, &name, 0);

if (device->alias != NULL)
return;

- notify_property_changed(conn, device->path,
- "Alias", DBUS_TYPE_STRING, &name, 0);
+ notify_property_changed(device, conn, device->path,
+ DEVICE_PROPERTY_CHANGED_ALIAS,
+ DBUS_TYPE_STRING, &name, 0);
+
}

void device_get_name(struct btd_device *device, char *name, size_t len)
@@ -1399,7 +1434,8 @@ static void services_changed(struct btd_device *device)
for (i = 0, l = device->uuids; l; l = l->next, i++)
uuids[i] = l->data;

- notify_property_changed(conn, device->path, "UUIDs",
+ notify_property_changed(device, conn, device->path,
+ DEVICE_PROPERTY_CHANGED_UUIDS,
DBUS_TYPE_STRING, &uuids, i);

g_free(uuids);
@@ -2333,8 +2369,8 @@ void device_set_paired(struct btd_device *device, gboolean value)

device->paired = value;

- notify_property_changed(conn, device->path, "Paired",
- DBUS_TYPE_BOOLEAN, &value, 0);
+ notify_property_changed(device, conn, device->path,
+ DEVICE_PROPERTY_CHANGED_PAIRED, DBUS_TYPE_BOOLEAN, &value, 0);
}

static void device_agent_removed(struct agent *agent, void *user_data)
@@ -2920,8 +2956,8 @@ void device_set_class(struct btd_device *device, uint32_t value)
{
DBusConnection *conn = get_dbus_connection();

- notify_property_changed(conn, device->path, "Class",
- DBUS_TYPE_UINT32, &value, 0);
+ notify_property_changed(device, conn, device->path,
+ DEVICE_PROPERTY_CHANGED_CLASS, DBUS_TYPE_UINT32, &value, 0);
}

static gboolean notify_attios(gpointer user_data)
diff --git a/src/device.h b/src/device.h
index ba9ed32..ce0a83a 100644
--- a/src/device.h
+++ b/src/device.h
@@ -28,6 +28,24 @@ struct btd_device;

typedef void (*dev_property_changed_cb)(uint16_t property, uint8_t *value, uint16_t len);

+#define DEVICE_PROPERTY_CHANGED_ADDRESS 0x01
+#define DEVICE_PROPERTY_CHANGED_NAME 0x02
+#define DEVICE_PROPERTY_CHANGED_VENDOR 0x03
+#define DEVICE_PROPERTY_CHANGED_PRODUCT 0x04
+#define DEVICE_PROPERTY_CHANGED_VERSION 0x05
+#define DEVICE_PROPERTY_CHANGED_ICON 0x06
+#define DEVICE_PROPERTY_CHANGED_CLASS 0x07
+#define DEVICE_PROPERTY_CHANGED_UUIDS 0x08
+#define DEVICE_PROPERTY_CHANGED_SERVICES 0x09
+#define DEVICE_PROPERTY_CHANGED_PAIRED 0x0A
+#define DEVICE_PROPERTY_CHANGED_CONNECTED 0x0B
+#define DEVICE_PROPERTY_CHANGED_TRUSTED 0x0C
+#define DEVICE_PROPERTY_CHANGED_BLOCKED 0x0D
+#define DEVICE_PROPERTY_CHANGED_ALIAS 0x0E
+#define DEVICE_PROPERTY_CHANGED_NODES 0x0F
+#define DEVICE_PROPERTY_CHANGED_ADAPTER 0x10
+#define DEVICE_PROPERTY_CHANGED_LEGACYPAIRING 0x11
+
typedef enum {
AUTH_TYPE_PINCODE,
AUTH_TYPE_PASSKEY,
--
1.7.4.1


2012-03-28 14:46:27

by Ganir, Chen

[permalink] [raw]
Subject: [PATCH 2/4] Centralize property changed events

From: Chen Ganir <[email protected]>

Move all D-BUS property changed events into one function, allowing
more logic to be added later.
---
src/device.c | 82 +++++++++++++++++++++++++++++++++------------------------
1 files changed, 47 insertions(+), 35 deletions(-)

diff --git a/src/device.c b/src/device.c
index 45ce62e..fbed9f8 100644
--- a/src/device.c
+++ b/src/device.c
@@ -187,6 +187,25 @@ static uint16_t uuid_list[] = {

static GSList *device_drivers = NULL;

+
+static void notify_property_changed(DBusConnection *conn,
+ const char *path,
+ const char *name,
+ int type, void *value, int num)
+{
+ const char *interface = DEVICE_INTERFACE;
+
+ if (num == 0)
+ emit_property_changed(conn, path,
+ interface, name,
+ type, value);
+ else
+ emit_array_property_changed(conn, path,
+ interface, name,
+ type, value,num);
+}
+
+
static void browse_request_free(struct browse_req *req)
{
if (req->listener_id)
@@ -461,9 +480,8 @@ static DBusMessage *set_alias(DBusConnection *conn, DBusMessage *msg,
g_free(device->alias);
device->alias = g_str_equal(alias, "") ? NULL : g_strdup(alias);

- emit_property_changed(conn, dbus_message_get_path(msg),
- DEVICE_INTERFACE, "Alias",
- DBUS_TYPE_STRING, &alias);
+ notify_property_changed(conn, dbus_message_get_path(msg),
+ "Alias", DBUS_TYPE_STRING, &alias, 0);

return dbus_message_new_method_return(msg);
}
@@ -490,9 +508,8 @@ static DBusMessage *set_trust(DBusConnection *conn, DBusMessage *msg,

device->trusted = value;

- emit_property_changed(conn, dbus_message_get_path(msg),
- DEVICE_INTERFACE, "Trusted",
- DBUS_TYPE_BOOLEAN, &value);
+ notify_property_changed(conn, dbus_message_get_path(msg),
+ "Trusted", DBUS_TYPE_BOOLEAN, &value, 0);

return dbus_message_new_method_return(msg);
}
@@ -548,8 +565,8 @@ int device_block(DBusConnection *conn, struct btd_device *device,

device_set_temporary(device, FALSE);

- emit_property_changed(conn, device->path, DEVICE_INTERFACE, "Blocked",
- DBUS_TYPE_BOOLEAN, &device->blocked);
+ notify_property_changed(conn, device->path, "Blocked",
+ DBUS_TYPE_BOOLEAN, &device->blocked, 0);

return 0;
}
@@ -579,9 +596,8 @@ int device_unblock(DBusConnection *conn, struct btd_device *device,
error("write_blocked(): %s (%d)", strerror(-err), -err);

if (!silent) {
- emit_property_changed(conn, device->path,
- DEVICE_INTERFACE, "Blocked",
- DBUS_TYPE_BOOLEAN, &device->blocked);
+ notify_property_changed(conn, device->path,
+ "Blocked", DBUS_TYPE_BOOLEAN, &device->blocked, 0);
device_probe_drivers(device, device->uuids);
}

@@ -906,9 +922,8 @@ void device_add_connection(struct btd_device *device, DBusConnection *conn)

device->connected = TRUE;

- emit_property_changed(conn, device->path,
- DEVICE_INTERFACE, "Connected",
- DBUS_TYPE_BOOLEAN, &device->connected);
+ notify_property_changed(conn, device->path,
+ "Connected", DBUS_TYPE_BOOLEAN, &device->connected, 0);
}

void device_remove_connection(struct btd_device *device, DBusConnection *conn)
@@ -937,9 +952,8 @@ void device_remove_connection(struct btd_device *device, DBusConnection *conn)
if (device_is_paired(device) && !device_is_bonded(device))
device_set_paired(device, FALSE);

- emit_property_changed(conn, device->path,
- DEVICE_INTERFACE, "Connected",
- DBUS_TYPE_BOOLEAN, &device->connected);
+ notify_property_changed(conn, device->path,
+ "Connected", DBUS_TYPE_BOOLEAN, &device->connected, 0);
}

guint device_add_disconnect_watch(struct btd_device *device,
@@ -987,8 +1001,8 @@ static void device_set_vendor(struct btd_device *device, uint16_t value)

device->vendor = value;

- emit_property_changed(conn, device->path, DEVICE_INTERFACE, "Vendor",
- DBUS_TYPE_UINT16, &value);
+ notify_property_changed(conn, device->path, "Vendor",
+ DBUS_TYPE_UINT16, &value, 0);
}

static void device_set_product(struct btd_device *device, uint16_t value)
@@ -1000,8 +1014,8 @@ static void device_set_product(struct btd_device *device, uint16_t value)

device->product = value;

- emit_property_changed(conn, device->path, DEVICE_INTERFACE, "Product",
- DBUS_TYPE_UINT16, &value);
+ notify_property_changed(conn, device->path, "Product",
+ DBUS_TYPE_UINT16, &value, 0);
}

static void device_set_version(struct btd_device *device, uint16_t value)
@@ -1013,8 +1027,8 @@ static void device_set_version(struct btd_device *device, uint16_t value)

device->version = value;

- emit_property_changed(conn, device->path, DEVICE_INTERFACE, "Version",
- DBUS_TYPE_UINT16, &value);
+ notify_property_changed(conn, device->path, "Version",
+ DBUS_TYPE_UINT16, &value, 0);
}

struct btd_device *device_create(DBusConnection *conn,
@@ -1088,16 +1102,14 @@ void device_set_name(struct btd_device *device, const char *name)

strncpy(device->name, name, MAX_NAME_LENGTH);

- emit_property_changed(conn, device->path,
- DEVICE_INTERFACE, "Name",
- DBUS_TYPE_STRING, &name);
+ notify_property_changed(conn, device->path,
+ "Name", DBUS_TYPE_STRING, &name, 0);

if (device->alias != NULL)
return;

- emit_property_changed(conn, device->path,
- DEVICE_INTERFACE, "Alias",
- DBUS_TYPE_STRING, &name);
+ notify_property_changed(conn, device->path,
+ "Alias", DBUS_TYPE_STRING, &name, 0);
}

void device_get_name(struct btd_device *device, char *name, size_t len)
@@ -1387,8 +1399,8 @@ static void services_changed(struct btd_device *device)
for (i = 0, l = device->uuids; l; l = l->next, i++)
uuids[i] = l->data;

- emit_array_property_changed(conn, device->path, DEVICE_INTERFACE,
- "UUIDs", DBUS_TYPE_STRING, &uuids, i);
+ notify_property_changed(conn, device->path, "UUIDs",
+ DBUS_TYPE_STRING, &uuids, i);

g_free(uuids);
}
@@ -2321,8 +2333,8 @@ void device_set_paired(struct btd_device *device, gboolean value)

device->paired = value;

- emit_property_changed(conn, device->path, DEVICE_INTERFACE, "Paired",
- DBUS_TYPE_BOOLEAN, &value);
+ notify_property_changed(conn, device->path, "Paired",
+ DBUS_TYPE_BOOLEAN, &value, 0);
}

static void device_agent_removed(struct agent *agent, void *user_data)
@@ -2908,8 +2920,8 @@ void device_set_class(struct btd_device *device, uint32_t value)
{
DBusConnection *conn = get_dbus_connection();

- emit_property_changed(conn, device->path, DEVICE_INTERFACE, "Class",
- DBUS_TYPE_UINT32, &value);
+ notify_property_changed(conn, device->path, "Class",
+ DBUS_TYPE_UINT32, &value, 0);
}

static gboolean notify_attios(gpointer user_data)
--
1.7.4.1


2012-03-28 14:46:26

by Ganir, Chen

[permalink] [raw]
Subject: [PATCH 1/4] Add property changed callback

From: Chen Ganir <[email protected]>

Add property changed callback mechanism for internal use between
different bluez modules. This mechanism will allow any module
holding a btd_device pointer, to register for proerty changed
events, similar to the D-BUS PropertyChanged signal.
---
src/device.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
src/device.h | 5 +++++
2 files changed, 51 insertions(+), 0 deletions(-)

diff --git a/src/device.c b/src/device.c
index eab7e4c..45ce62e 100644
--- a/src/device.c
+++ b/src/device.c
@@ -125,6 +125,11 @@ struct att_callbacks {
gpointer user_data;
};

+struct prop_changed_cb {
+ guint id;
+ dev_property_changed_cb cb;
+};
+
struct btd_device {
bdaddr_t bdaddr;
addr_type_t type;
@@ -169,6 +174,8 @@ struct btd_device {

GIOChannel *att_io;
guint cleanup_id;
+
+ GSList *cb_list;
};

static uint16_t uuid_list[] = {
@@ -259,6 +266,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->cb_list,g_free);

att_cleanup(device);

@@ -2992,3 +3000,41 @@ gboolean btd_device_remove_attio_callback(struct btd_device *device, guint id)

return TRUE;
}
+
+static int prop_changed_cb_cmp(gconstpointer a, gconstpointer b)
+{
+ const struct prop_changed_cb *cb = a;
+ guint id = GPOINTER_TO_UINT(b);
+
+ return cb->id - id;
+}
+
+guint btd_device_add_prop_changed_cb(struct btd_device *device, dev_property_changed_cb cbfunc)
+{
+ struct prop_changed_cb *cb;
+ static guint cb_id = 0;
+
+ DBG("%p registered device propery changed callback", device);
+
+ cb = g_new0(struct prop_changed_cb, 1);
+ cb->id = ++cb_id;
+ cb->cb = cbfunc;
+
+ device->cb_list = g_slist_append(device->cb_list, cb);
+
+ return cb->id;
+}
+
+void btd_device_remove_prop_changed_cb(struct btd_device *device, guint id)
+{
+ struct prop_changed_cb *cb;
+ GSList *l;
+
+ l = g_slist_find_custom(device->cb_list, GUINT_TO_POINTER(id),
+ prop_changed_cb_cmp);
+ if (l) {
+ cb = l->data;
+ device->cb_list = g_slist_remove(device->cb_list, cb);
+ g_free(cb);
+ }
+}
diff --git a/src/device.h b/src/device.h
index 7cb9bb2..ba9ed32 100644
--- a/src/device.h
+++ b/src/device.h
@@ -26,6 +26,8 @@

struct btd_device;

+typedef void (*dev_property_changed_cb)(uint16_t property, uint8_t *value, uint16_t len);
+
typedef enum {
AUTH_TYPE_PINCODE,
AUTH_TYPE_PASSKEY,
@@ -120,3 +122,6 @@ int device_block(DBusConnection *conn, struct btd_device *device,
gboolean update_only);
int device_unblock(DBusConnection *conn, struct btd_device *device,
gboolean silent, gboolean update_only);
+guint btd_device_add_prop_changed_cb(struct btd_device *device,
+ dev_property_changed_cb cb);
+void btd_device_remove_prop_changed_cb(struct btd_device *device, guint id);
--
1.7.4.1