* [PATCH 01/28] android/hidhost: Create bt_gatt_client
2015-04-01 16:40 [PATCH 00/28] android/hog Introduce bt_gatt_client Mariusz Skamra
@ 2015-04-01 16:40 ` Mariusz Skamra
2015-04-02 14:16 ` Szymon Janc
2015-04-01 16:40 ` [PATCH 02/28] android/hog: Introduce bt_gatt_client Mariusz Skamra
` (26 subsequent siblings)
27 siblings, 1 reply; 41+ messages in thread
From: Mariusz Skamra @ 2015-04-01 16:40 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Mariusz Skamra
From: Mariusz Skamra <mariusz.skamra@gmail.com>
This patch introduces bt_gatt_client to be used by HoG profile.
As long as the android/gatt doesn't use bt_gatt_client, initialization
can be performed here.
---
android/Android.mk | 2 ++
android/hidhost.c | 75 +++++++++++++++++++++++++++++++++++++++++++++---------
2 files changed, 65 insertions(+), 12 deletions(-)
diff --git a/android/Android.mk b/android/Android.mk
index f218805..b9dd1c8 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -72,6 +72,8 @@ LOCAL_SRC_FILES := \
bluez/src/shared/crypto.c \
bluez/src/shared/uhid.c \
bluez/src/shared/att.c \
+ bluez/src/shared/gatt-helpers.c \
+ bluez/src/shared/gatt-client.c \
bluez/src/sdpd-database.c \
bluez/src/sdpd-service.c \
bluez/src/sdpd-request.c \
diff --git a/android/hidhost.c b/android/hidhost.c
index 729b884..3da1130 100644
--- a/android/hidhost.c
+++ b/android/hidhost.c
@@ -36,15 +36,22 @@
#include "btio/btio.h"
#include "lib/bluetooth.h"
+#include "lib/uuid.h"
#include "lib/sdp.h"
#include "lib/sdp_lib.h"
#include "src/shared/mgmt.h"
+#include "src/shared/queue.h"
#include "src/shared/util.h"
#include "src/shared/uhid.h"
+#include "src/shared/att.h"
+#include "src/shared/gatt-db.h"
+#include "src/shared/gatt-client.h"
#include "src/sdp-client.h"
#include "src/uuid-helper.h"
#include "src/log.h"
+#include "attrib/gattrib.h"
+
#include "hal-msg.h"
#include "ipc-common.h"
#include "ipc.h"
@@ -113,6 +120,9 @@ struct hid_device {
uint8_t last_hid_msg;
struct bt_hog *hog;
int sec_level;
+ GAttrib *attrib;
+ struct gatt_db *db;
+ struct bt_gatt_client *client;
};
static int device_cmp(gconstpointer s, gconstpointer user_data)
@@ -142,8 +152,15 @@ static void hid_device_free(void *data)
if (dev->uhid)
bt_uhid_unref(dev->uhid);
- if (dev->hog)
+ if (dev->hog) {
bt_hog_unref(dev->hog);
+ dev->hog = NULL;
+ }
+
+ if (dev->db) {
+ gatt_db_unref(dev->db);
+ dev->db = NULL;
+ }
g_free(dev->rd_data);
g_free(dev);
@@ -792,10 +809,37 @@ fail:
hid_device_remove(dev);
}
+static void client_ready_cb(bool success, uint8_t att_ecode, void *user_data)
+{
+ struct hid_device *dev = user_data;
+
+ if (!success) {
+ error("HoG: client not ready");
+ goto fail;
+ }
+
+ if (!bt_hog_attach(dev->hog, dev->attrib)) {
+ error("HoG: unable to attach");
+ goto fail;
+ }
+
+ bt_hid_notify_state(dev, HAL_HIDHOST_STATE_CONNECTED);
+
+ if (!bt_gatt_add_autoconnect(hog_app, &dev->dst))
+ error("HoG: Could not add to autoconnect list");
+
+ return;
+fail:
+ bt_hid_notify_state(dev, HAL_HIDHOST_STATE_DISCONNECTED);
+ hid_device_remove(dev);
+}
+
static void hog_conn_cb(const bdaddr_t *addr, int err, void *attrib)
{
GSList *l;
struct hid_device *dev;
+ struct bt_att *att;
+ uint16_t mtu;
l = g_slist_find_custom(devices, addr, device_cmp);
dev = l ? l->data : NULL;
@@ -807,6 +851,8 @@ static void hog_conn_cb(const bdaddr_t *addr, int err, void *attrib)
bt_hid_notify_state(dev,
HAL_HIDHOST_STATE_DISCONNECTED);
bt_hog_detach(dev->hog);
+ bt_gatt_client_unref(dev->client);
+ g_attrib_unref(dev->attrib);
return;
}
goto fail;
@@ -816,34 +862,39 @@ static void hog_conn_cb(const bdaddr_t *addr, int err, void *attrib)
dev = hid_device_new(addr);
if (!dev->hog) {
- /* TODO: Get device details and primary */
+ /* TODO: Get device details */
dev->hog = bt_hog_new_default("bluez-input-device", dev->vendor,
dev->product, dev->version, NULL);
if (!dev->hog) {
error("HoG: unable to create session");
goto fail;
}
- }
- if (!bt_hog_attach(dev->hog, attrib)) {
- error("HoG: unable to attach");
- goto fail;
+ dev->db = gatt_db_new();
+ if (!dev->db) {
+ error("HoG: unable to create gatt_db");
+ goto fail;
+ }
}
- if (!bt_gatt_set_security(addr, BT_IO_SEC_MEDIUM)) {
+ att = g_attrib_get_att(attrib);
+ dev->attrib = g_attrib_ref(attrib);
+ mtu = bt_att_get_mtu(att);
+
+ /* Enable encryption before gatt_client starts discovering services */
+ if (!bt_att_set_sec_level(att, BT_SECURITY_MEDIUM)) {
error("Failed to set security level");
goto fail;
}
DBG("");
- bt_hid_notify_state(dev, HAL_HIDHOST_STATE_CONNECTED);
-
- if (!bt_gatt_add_autoconnect(hog_app, &dev->dst))
- error("hidhost: Could not add to autoconnect list");
+ dev->client = bt_gatt_client_new(dev->db, att, mtu);
+ /* Wait until client is initialized */
+ bt_gatt_client_set_ready_handler(dev->client, client_ready_cb,
+ dev, NULL);
return;
-
fail:
bt_hid_notify_state(dev, HAL_HIDHOST_STATE_DISCONNECTED);
hid_device_remove(dev);
--
1.9.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* Re: [PATCH 01/28] android/hidhost: Create bt_gatt_client
2015-04-01 16:40 ` [PATCH 01/28] android/hidhost: Create bt_gatt_client Mariusz Skamra
@ 2015-04-02 14:16 ` Szymon Janc
0 siblings, 0 replies; 41+ messages in thread
From: Szymon Janc @ 2015-04-02 14:16 UTC (permalink / raw)
To: Mariusz Skamra; +Cc: linux-bluetooth, Mariusz Skamra
Hi Mariusz,
On Wednesday 01 of April 2015 18:40:17 Mariusz Skamra wrote:
> From: Mariusz Skamra <mariusz.skamra@gmail.com>
>
> This patch introduces bt_gatt_client to be used by HoG profile.
> As long as the android/gatt doesn't use bt_gatt_client, initialization
> can be performed here.
> ---
> android/Android.mk | 2 ++
> android/hidhost.c | 75
> +++++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 65
> insertions(+), 12 deletions(-)
>
> diff --git a/android/Android.mk b/android/Android.mk
> index f218805..b9dd1c8 100644
> --- a/android/Android.mk
> +++ b/android/Android.mk
> @@ -72,6 +72,8 @@ LOCAL_SRC_FILES := \
> bluez/src/shared/crypto.c \
> bluez/src/shared/uhid.c \
> bluez/src/shared/att.c \
> + bluez/src/shared/gatt-helpers.c \
> + bluez/src/shared/gatt-client.c \
> bluez/src/sdpd-database.c \
> bluez/src/sdpd-service.c \
> bluez/src/sdpd-request.c \
> diff --git a/android/hidhost.c b/android/hidhost.c
> index 729b884..3da1130 100644
> --- a/android/hidhost.c
> +++ b/android/hidhost.c
> @@ -36,15 +36,22 @@
>
> #include "btio/btio.h"
> #include "lib/bluetooth.h"
> +#include "lib/uuid.h"
> #include "lib/sdp.h"
> #include "lib/sdp_lib.h"
> #include "src/shared/mgmt.h"
> +#include "src/shared/queue.h"
> #include "src/shared/util.h"
> #include "src/shared/uhid.h"
> +#include "src/shared/att.h"
> +#include "src/shared/gatt-db.h"
> +#include "src/shared/gatt-client.h"
> #include "src/sdp-client.h"
> #include "src/uuid-helper.h"
> #include "src/log.h"
>
> +#include "attrib/gattrib.h"
> +
> #include "hal-msg.h"
> #include "ipc-common.h"
> #include "ipc.h"
> @@ -113,6 +120,9 @@ struct hid_device {
> uint8_t last_hid_msg;
> struct bt_hog *hog;
> int sec_level;
> + GAttrib *attrib;
> + struct gatt_db *db;
> + struct bt_gatt_client *client;
> };
>
> static int device_cmp(gconstpointer s, gconstpointer user_data)
> @@ -142,8 +152,15 @@ static void hid_device_free(void *data)
> if (dev->uhid)
> bt_uhid_unref(dev->uhid);
>
> - if (dev->hog)
> + if (dev->hog) {
> bt_hog_unref(dev->hog);
> + dev->hog = NULL;
> + }
dev is freed few lines later so setting dev->hog to NULL shouldn't be needed.
> +
> + if (dev->db) {
> + gatt_db_unref(dev->db);
> + dev->db = NULL;
> + }
Same here.
>
> g_free(dev->rd_data);
> g_free(dev);
> @@ -792,10 +809,37 @@ fail:
> hid_device_remove(dev);
> }
>
> +static void client_ready_cb(bool success, uint8_t att_ecode, void
> *user_data) +{
> + struct hid_device *dev = user_data;
> +
> + if (!success) {
> + error("HoG: client not ready");
> + goto fail;
> + }
> +
> + if (!bt_hog_attach(dev->hog, dev->attrib)) {
> + error("HoG: unable to attach");
> + goto fail;
> + }
> +
> + bt_hid_notify_state(dev, HAL_HIDHOST_STATE_CONNECTED);
> +
> + if (!bt_gatt_add_autoconnect(hog_app, &dev->dst))
> + error("HoG: Could not add to autoconnect list");
> +
> + return;
> +fail:
> + bt_hid_notify_state(dev, HAL_HIDHOST_STATE_DISCONNECTED);
> + hid_device_remove(dev);
> +}
> +
> static void hog_conn_cb(const bdaddr_t *addr, int err, void *attrib)
> {
> GSList *l;
> struct hid_device *dev;
> + struct bt_att *att;
> + uint16_t mtu;
>
> l = g_slist_find_custom(devices, addr, device_cmp);
> dev = l ? l->data : NULL;
> @@ -807,6 +851,8 @@ static void hog_conn_cb(const bdaddr_t *addr, int err,
> void *attrib) bt_hid_notify_state(dev,
> HAL_HIDHOST_STATE_DISCONNECTED);
> bt_hog_detach(dev->hog);
> + bt_gatt_client_unref(dev->client);
> + g_attrib_unref(dev->attrib);
Shouldn't we NULL those to avoid dangling pointers?
> return;
> }
> goto fail;
> @@ -816,34 +862,39 @@ static void hog_conn_cb(const bdaddr_t *addr, int err,
> void *attrib) dev = hid_device_new(addr);
>
> if (!dev->hog) {
> - /* TODO: Get device details and primary */
> + /* TODO: Get device details */
> dev->hog = bt_hog_new_default("bluez-input-device", dev->vendor,
> dev->product, dev->version, NULL);
> if (!dev->hog) {
> error("HoG: unable to create session");
> goto fail;
> }
> - }
>
> - if (!bt_hog_attach(dev->hog, attrib)) {
> - error("HoG: unable to attach");
> - goto fail;
> + dev->db = gatt_db_new();
> + if (!dev->db) {
> + error("HoG: unable to create gatt_db");
> + goto fail;
> + }
> }
>
> - if (!bt_gatt_set_security(addr, BT_IO_SEC_MEDIUM)) {
> + att = g_attrib_get_att(attrib);
> + dev->attrib = g_attrib_ref(attrib);
> + mtu = bt_att_get_mtu(att);
> +
> + /* Enable encryption before gatt_client starts discovering services */
> + if (!bt_att_set_sec_level(att, BT_SECURITY_MEDIUM)) {
> error("Failed to set security level");
> goto fail;
> }
>
> DBG("");
>
> - bt_hid_notify_state(dev, HAL_HIDHOST_STATE_CONNECTED);
> -
> - if (!bt_gatt_add_autoconnect(hog_app, &dev->dst))
> - error("hidhost: Could not add to autoconnect list");
> + dev->client = bt_gatt_client_new(dev->db, att, mtu);
This can return NULL.
>
> + /* Wait until client is initialized */
> + bt_gatt_client_set_ready_handler(dev->client, client_ready_cb,
> + dev, NULL);
> return;
> -
> fail:
> bt_hid_notify_state(dev, HAL_HIDHOST_STATE_DISCONNECTED);
> hid_device_remove(dev);
--
BR
Szymon Janc
^ permalink raw reply [flat|nested] 41+ messages in thread
* [PATCH 02/28] android/hog: Introduce bt_gatt_client
2015-04-01 16:40 [PATCH 00/28] android/hog Introduce bt_gatt_client Mariusz Skamra
2015-04-01 16:40 ` [PATCH 01/28] android/hidhost: Create bt_gatt_client Mariusz Skamra
@ 2015-04-01 16:40 ` Mariusz Skamra
2015-04-02 14:17 ` Szymon Janc
2015-04-01 16:40 ` [PATCH 03/28] shared/gatt-client: Expose gatt_db Mariusz Skamra
` (25 subsequent siblings)
27 siblings, 1 reply; 41+ messages in thread
From: Mariusz Skamra @ 2015-04-01 16:40 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Mariusz Skamra
This patch introduces bt_gatt_client to HoG. Service handle will be used
to obtain the attribute from cached database.
---
android/hidhost.c | 4 ++--
android/hog.c | 30 +++++++++++++++++++++---------
android/hog.h | 6 +++---
unit/test-hog.c | 4 ++--
4 files changed, 28 insertions(+), 16 deletions(-)
diff --git a/android/hidhost.c b/android/hidhost.c
index 3da1130..47e5840 100644
--- a/android/hidhost.c
+++ b/android/hidhost.c
@@ -818,7 +818,7 @@ static void client_ready_cb(bool success, uint8_t att_ecode, void *user_data)
goto fail;
}
- if (!bt_hog_attach(dev->hog, dev->attrib)) {
+ if (!bt_hog_attach(dev->hog, dev->attrib, dev->client)) {
error("HoG: unable to attach");
goto fail;
}
@@ -864,7 +864,7 @@ static void hog_conn_cb(const bdaddr_t *addr, int err, void *attrib)
if (!dev->hog) {
/* TODO: Get device details */
dev->hog = bt_hog_new_default("bluez-input-device", dev->vendor,
- dev->product, dev->version, NULL);
+ dev->product, dev->version, NULL, 0);
if (!dev->hog) {
error("HoG: unable to create session");
goto fail;
diff --git a/android/hog.c b/android/hog.c
index ff77bb3..5b8c079 100644
--- a/android/hog.c
+++ b/android/hog.c
@@ -45,6 +45,9 @@
#include "src/shared/util.h"
#include "src/shared/uhid.h"
#include "src/shared/queue.h"
+#include "src/shared/att.h"
+#include "src/shared/gatt-db.h"
+#include "src/shared/gatt-client.h"
#include "src/log.h"
#include "attrib/att.h"
@@ -79,6 +82,7 @@
struct bt_hog {
int ref_count;
+ uint16_t service_handle;
char *name;
uint16_t vendor;
uint16_t product;
@@ -103,6 +107,7 @@ struct bt_hog {
struct queue *bas;
GSList *instances;
struct queue *gatt_op;
+ struct bt_gatt_client *client;
};
struct report {
@@ -1173,14 +1178,15 @@ static void hog_free(void *data)
struct bt_hog *bt_hog_new_default(const char *name, uint16_t vendor,
uint16_t product, uint16_t version,
- void *primary)
+ void *primary, uint16_t service_handle)
{
- return bt_hog_new(-1, name, vendor, product, version, primary);
+ return bt_hog_new(-1, name, vendor, product, version, primary,
+ service_handle);
}
struct bt_hog *bt_hog_new(int fd, const char *name, uint16_t vendor,
uint16_t product, uint16_t version,
- void *primary)
+ void *primary, uint16_t service_handle)
{
struct bt_hog *hog;
@@ -1211,6 +1217,9 @@ struct bt_hog *bt_hog_new(int fd, const char *name, uint16_t vendor,
if (primary)
hog->primary = g_memdup(primary, sizeof(*hog->primary));
+ if (service_handle)
+ hog->service_handle = service_handle;
+
return bt_hog_ref(hog);
}
@@ -1321,14 +1330,14 @@ static void hog_attach_hog(struct bt_hog *hog, struct gatt_primary *primary)
}
instance = bt_hog_new(hog->uhid_fd, hog->name, hog->vendor,
- hog->product, hog->version, primary);
+ hog->product, hog->version, primary, 0);
if (!instance)
return;
find_included(instance, hog->attrib, primary->range.start,
primary->range.end, find_included_cb, instance);
- bt_hog_attach(instance, hog->attrib);
+ bt_hog_attach(instance, hog->attrib, hog->client);
hog->instances = g_slist_append(hog->instances, instance);
}
@@ -1377,15 +1386,16 @@ static void primary_cb(uint8_t status, GSList *services, void *user_data)
}
}
-bool bt_hog_attach(struct bt_hog *hog, void *gatt)
+bool bt_hog_attach(struct bt_hog *hog, void *gatt, void *client)
{
struct gatt_primary *primary = hog->primary;
GSList *l;
- if (hog->attrib)
+ if (hog->attrib || hog->client)
return false;
hog->attrib = g_attrib_ref(gatt);
+ hog->client = bt_gatt_client_ref(client);
if (!primary) {
discover_primary(hog, hog->attrib, NULL, primary_cb, hog);
@@ -1403,7 +1413,7 @@ bool bt_hog_attach(struct bt_hog *hog, void *gatt)
for (l = hog->instances; l; l = l->next) {
struct bt_hog *instance = l->data;
- bt_hog_attach(instance, gatt);
+ bt_hog_attach(instance, gatt, client);
}
if (hog->reports == NULL) {
@@ -1429,7 +1439,7 @@ void bt_hog_detach(struct bt_hog *hog)
{
GSList *l;
- if (!hog->attrib)
+ if (!hog->attrib || !hog->client)
return;
queue_foreach(hog->bas, (void *) bt_bas_detach, NULL);
@@ -1456,7 +1466,9 @@ void bt_hog_detach(struct bt_hog *hog)
bt_dis_detach(hog->dis);
queue_foreach(hog->gatt_op, (void *) cancel_gatt_req, NULL);
+ bt_gatt_client_unref(hog->client);
g_attrib_unref(hog->attrib);
+ hog->client = NULL;
hog->attrib = NULL;
}
diff --git a/android/hog.h b/android/hog.h
index 2a9b899..61d756c 100644
--- a/android/hog.h
+++ b/android/hog.h
@@ -25,16 +25,16 @@ struct bt_hog;
struct bt_hog *bt_hog_new_default(const char *name, uint16_t vendor,
uint16_t product, uint16_t version,
- void *primary);
+ void *primary, uint16_t service_handle);
struct bt_hog *bt_hog_new(int fd, const char *name, uint16_t vendor,
uint16_t product, uint16_t version,
- void *primary);
+ void *primary, uint16_t service_handle);
struct bt_hog *bt_hog_ref(struct bt_hog *hog);
void bt_hog_unref(struct bt_hog *hog);
-bool bt_hog_attach(struct bt_hog *hog, void *gatt);
+bool bt_hog_attach(struct bt_hog *hog, void *gatt, void *client);
void bt_hog_detach(struct bt_hog *hog);
int bt_hog_set_control_point(struct bt_hog *hog, bool suspend);
diff --git a/unit/test-hog.c b/unit/test-hog.c
index 2a25d09..c7c64e4 100644
--- a/unit/test-hog.c
+++ b/unit/test-hog.c
@@ -196,7 +196,7 @@ static struct context *create_context(gconstpointer data)
fd = open("/dev/null", O_WRONLY | O_CLOEXEC);
g_assert(fd > 0);
- context->hog = bt_hog_new(fd, name, vendor, product, version, NULL);
+ context->hog = bt_hog_new(fd, name, vendor, product, version, NULL, 0);
g_assert(context->hog);
channel = g_io_channel_unix_new(sv[1]);
@@ -222,7 +222,7 @@ static void test_hog(gconstpointer data)
{
struct context *context = create_context(data);
- g_assert(bt_hog_attach(context->hog, context->attrib));
+ g_assert(bt_hog_attach(context->hog, context->attrib, NULL));
}
int main(int argc, char *argv[])
--
1.9.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* Re: [PATCH 02/28] android/hog: Introduce bt_gatt_client
2015-04-01 16:40 ` [PATCH 02/28] android/hog: Introduce bt_gatt_client Mariusz Skamra
@ 2015-04-02 14:17 ` Szymon Janc
0 siblings, 0 replies; 41+ messages in thread
From: Szymon Janc @ 2015-04-02 14:17 UTC (permalink / raw)
To: Mariusz Skamra; +Cc: linux-bluetooth
Hi Mariusz,
On Wednesday 01 of April 2015 18:40:18 Mariusz Skamra wrote:
> This patch introduces bt_gatt_client to HoG. Service handle will be used
> to obtain the attribute from cached database.
> ---
> android/hidhost.c | 4 ++--
> android/hog.c | 30 +++++++++++++++++++++---------
> android/hog.h | 6 +++---
> unit/test-hog.c | 4 ++--
> 4 files changed, 28 insertions(+), 16 deletions(-)
>
> diff --git a/android/hidhost.c b/android/hidhost.c
> index 3da1130..47e5840 100644
> --- a/android/hidhost.c
> +++ b/android/hidhost.c
> @@ -818,7 +818,7 @@ static void client_ready_cb(bool success, uint8_t
> att_ecode, void *user_data) goto fail;
> }
>
> - if (!bt_hog_attach(dev->hog, dev->attrib)) {
> + if (!bt_hog_attach(dev->hog, dev->attrib, dev->client)) {
> error("HoG: unable to attach");
> goto fail;
> }
> @@ -864,7 +864,7 @@ static void hog_conn_cb(const bdaddr_t *addr, int err,
> void *attrib) if (!dev->hog) {
> /* TODO: Get device details */
> dev->hog = bt_hog_new_default("bluez-input-device", dev->vendor,
> - dev->product, dev->version, NULL);
> + dev->product, dev->version, NULL, 0);
> if (!dev->hog) {
> error("HoG: unable to create session");
> goto fail;
> diff --git a/android/hog.c b/android/hog.c
> index ff77bb3..5b8c079 100644
> --- a/android/hog.c
> +++ b/android/hog.c
> @@ -45,6 +45,9 @@
> #include "src/shared/util.h"
> #include "src/shared/uhid.h"
> #include "src/shared/queue.h"
> +#include "src/shared/att.h"
> +#include "src/shared/gatt-db.h"
> +#include "src/shared/gatt-client.h"
> #include "src/log.h"
>
> #include "attrib/att.h"
> @@ -79,6 +82,7 @@
>
> struct bt_hog {
> int ref_count;
> + uint16_t service_handle;
> char *name;
> uint16_t vendor;
> uint16_t product;
> @@ -103,6 +107,7 @@ struct bt_hog {
> struct queue *bas;
> GSList *instances;
> struct queue *gatt_op;
> + struct bt_gatt_client *client;
> };
>
> struct report {
> @@ -1173,14 +1178,15 @@ static void hog_free(void *data)
>
> struct bt_hog *bt_hog_new_default(const char *name, uint16_t vendor,
> uint16_t product, uint16_t version,
> - void *primary)
> + void *primary, uint16_t service_handle)
> {
> - return bt_hog_new(-1, name, vendor, product, version, primary);
> + return bt_hog_new(-1, name, vendor, product, version, primary,
> + service_handle);
> }
>
> struct bt_hog *bt_hog_new(int fd, const char *name, uint16_t vendor,
> uint16_t product, uint16_t version,
> - void *primary)
> + void *primary, uint16_t service_handle)
> {
> struct bt_hog *hog;
>
> @@ -1211,6 +1217,9 @@ struct bt_hog *bt_hog_new(int fd, const char *name,
> uint16_t vendor, if (primary)
> hog->primary = g_memdup(primary, sizeof(*hog->primary));
>
> + if (service_handle)
> + hog->service_handle = service_handle;
> +
> return bt_hog_ref(hog);
> }
>
> @@ -1321,14 +1330,14 @@ static void hog_attach_hog(struct bt_hog *hog,
> struct gatt_primary *primary) }
>
> instance = bt_hog_new(hog->uhid_fd, hog->name, hog->vendor,
> - hog->product, hog->version, primary);
> + hog->product, hog->version, primary, 0);
> if (!instance)
> return;
>
> find_included(instance, hog->attrib, primary->range.start,
> primary->range.end, find_included_cb, instance);
>
> - bt_hog_attach(instance, hog->attrib);
> + bt_hog_attach(instance, hog->attrib, hog->client);
> hog->instances = g_slist_append(hog->instances, instance);
> }
>
> @@ -1377,15 +1386,16 @@ static void primary_cb(uint8_t status, GSList
> *services, void *user_data) }
> }
>
> -bool bt_hog_attach(struct bt_hog *hog, void *gatt)
> +bool bt_hog_attach(struct bt_hog *hog, void *gatt, void *client)
> {
> struct gatt_primary *primary = hog->primary;
> GSList *l;
>
> - if (hog->attrib)
> + if (hog->attrib || hog->client)
> return false;
>
> hog->attrib = g_attrib_ref(gatt);
> + hog->client = bt_gatt_client_ref(client);
>
> if (!primary) {
> discover_primary(hog, hog->attrib, NULL, primary_cb, hog);
> @@ -1403,7 +1413,7 @@ bool bt_hog_attach(struct bt_hog *hog, void *gatt)
> for (l = hog->instances; l; l = l->next) {
> struct bt_hog *instance = l->data;
>
> - bt_hog_attach(instance, gatt);
> + bt_hog_attach(instance, gatt, client);
> }
>
> if (hog->reports == NULL) {
> @@ -1429,7 +1439,7 @@ void bt_hog_detach(struct bt_hog *hog)
> {
> GSList *l;
>
> - if (!hog->attrib)
> + if (!hog->attrib || !hog->client)
> return;
>
> queue_foreach(hog->bas, (void *) bt_bas_detach, NULL);
> @@ -1456,7 +1466,9 @@ void bt_hog_detach(struct bt_hog *hog)
> bt_dis_detach(hog->dis);
>
> queue_foreach(hog->gatt_op, (void *) cancel_gatt_req, NULL);
> + bt_gatt_client_unref(hog->client);
> g_attrib_unref(hog->attrib);
> + hog->client = NULL;
> hog->attrib = NULL;
Usually we do this like:
unref(foo);
foo = NULL;
unref(bar);
bar = NULL;
> }
>
> diff --git a/android/hog.h b/android/hog.h
> index 2a9b899..61d756c 100644
> --- a/android/hog.h
> +++ b/android/hog.h
> @@ -25,16 +25,16 @@ struct bt_hog;
>
> struct bt_hog *bt_hog_new_default(const char *name, uint16_t vendor,
> uint16_t product, uint16_t version,
> - void *primary);
> + void *primary, uint16_t service_handle);
>
> struct bt_hog *bt_hog_new(int fd, const char *name, uint16_t vendor,
> uint16_t product, uint16_t version,
> - void *primary);
> + void *primary, uint16_t service_handle);
>
> struct bt_hog *bt_hog_ref(struct bt_hog *hog);
> void bt_hog_unref(struct bt_hog *hog);
>
> -bool bt_hog_attach(struct bt_hog *hog, void *gatt);
> +bool bt_hog_attach(struct bt_hog *hog, void *gatt, void *client);
> void bt_hog_detach(struct bt_hog *hog);
>
> int bt_hog_set_control_point(struct bt_hog *hog, bool suspend);
> diff --git a/unit/test-hog.c b/unit/test-hog.c
> index 2a25d09..c7c64e4 100644
> --- a/unit/test-hog.c
> +++ b/unit/test-hog.c
> @@ -196,7 +196,7 @@ static struct context *create_context(gconstpointer
> data) fd = open("/dev/null", O_WRONLY | O_CLOEXEC);
> g_assert(fd > 0);
>
> - context->hog = bt_hog_new(fd, name, vendor, product, version, NULL);
> + context->hog = bt_hog_new(fd, name, vendor, product, version, NULL, 0);
> g_assert(context->hog);
>
> channel = g_io_channel_unix_new(sv[1]);
> @@ -222,7 +222,7 @@ static void test_hog(gconstpointer data)
> {
> struct context *context = create_context(data);
>
> - g_assert(bt_hog_attach(context->hog, context->attrib));
> + g_assert(bt_hog_attach(context->hog, context->attrib, NULL));
> }
>
> int main(int argc, char *argv[])
--
BR
Szymon Janc
^ permalink raw reply [flat|nested] 41+ messages in thread
* [PATCH 03/28] shared/gatt-client: Expose gatt_db
2015-04-01 16:40 [PATCH 00/28] android/hog Introduce bt_gatt_client Mariusz Skamra
2015-04-01 16:40 ` [PATCH 01/28] android/hidhost: Create bt_gatt_client Mariusz Skamra
2015-04-01 16:40 ` [PATCH 02/28] android/hog: Introduce bt_gatt_client Mariusz Skamra
@ 2015-04-01 16:40 ` Mariusz Skamra
2015-04-02 14:20 ` Szymon Janc
2015-04-01 16:40 ` [PATCH 04/28] android/hog: Remove tracking gatt operations Mariusz Skamra
` (24 subsequent siblings)
27 siblings, 1 reply; 41+ messages in thread
From: Mariusz Skamra @ 2015-04-01 16:40 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Mariusz Skamra
This patch adds the bt_gatt_client_get_db function, which allows
to get a reference to db from client structure. This is useful
when as a client we need to have an access db, to explore some
attributes.
---
src/shared/gatt-client.c | 8 ++++++++
src/shared/gatt-client.h | 1 +
2 files changed, 9 insertions(+)
diff --git a/src/shared/gatt-client.c b/src/shared/gatt-client.c
index 729bd87..877abea 100644
--- a/src/shared/gatt-client.c
+++ b/src/shared/gatt-client.c
@@ -1760,6 +1760,14 @@ uint16_t bt_gatt_client_get_mtu(struct bt_gatt_client *client)
return bt_att_get_mtu(client->att);
}
+struct gatt_db *bt_gatt_client_get_db(struct bt_gatt_client *client)
+{
+ if (!client || !client->db)
+ return 0;
+
+ return gatt_db_ref(client->db);
+}
+
static bool match_req_id(const void *a, const void *b)
{
const struct request *req = a;
diff --git a/src/shared/gatt-client.h b/src/shared/gatt-client.h
index 8e5e0f5..f539a61 100644
--- a/src/shared/gatt-client.h
+++ b/src/shared/gatt-client.h
@@ -70,6 +70,7 @@ bool bt_gatt_client_set_debug(struct bt_gatt_client *client,
bt_gatt_client_destroy_func_t destroy);
uint16_t bt_gatt_client_get_mtu(struct bt_gatt_client *client);
+struct gatt_db *bt_gatt_client_get_db(struct bt_gatt_client *client);
bool bt_gatt_client_cancel(struct bt_gatt_client *client, unsigned int id);
bool bt_gatt_client_cancel_all(struct bt_gatt_client *client);
--
1.9.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* Re: [PATCH 03/28] shared/gatt-client: Expose gatt_db
2015-04-01 16:40 ` [PATCH 03/28] shared/gatt-client: Expose gatt_db Mariusz Skamra
@ 2015-04-02 14:20 ` Szymon Janc
0 siblings, 0 replies; 41+ messages in thread
From: Szymon Janc @ 2015-04-02 14:20 UTC (permalink / raw)
To: Mariusz Skamra; +Cc: linux-bluetooth
Hi Mariusz,
On Wednesday 01 of April 2015 18:40:19 Mariusz Skamra wrote:
> This patch adds the bt_gatt_client_get_db function, which allows
> to get a reference to db from client structure. This is useful
> when as a client we need to have an access db, to explore some
> attributes.
> ---
> src/shared/gatt-client.c | 8 ++++++++
> src/shared/gatt-client.h | 1 +
> 2 files changed, 9 insertions(+)
>
> diff --git a/src/shared/gatt-client.c b/src/shared/gatt-client.c
> index 729bd87..877abea 100644
> --- a/src/shared/gatt-client.c
> +++ b/src/shared/gatt-client.c
> @@ -1760,6 +1760,14 @@ uint16_t bt_gatt_client_get_mtu(struct bt_gatt_client
> *client) return bt_att_get_mtu(client->att);
> }
>
> +struct gatt_db *bt_gatt_client_get_db(struct bt_gatt_client *client)
> +{
> + if (!client || !client->db)
> + return 0;
Should be NULL instead of 0. I wonder why GCC didn't warn on this since
Wint-to-pointer-cast is enabled by default.
> +
> + return gatt_db_ref(client->db);
I'd leave getting reference to the user instead of doing this implicitly in
bt_gatt_client_get_db.
> +}
> +
> static bool match_req_id(const void *a, const void *b)
> {
> const struct request *req = a;
> diff --git a/src/shared/gatt-client.h b/src/shared/gatt-client.h
> index 8e5e0f5..f539a61 100644
> --- a/src/shared/gatt-client.h
> +++ b/src/shared/gatt-client.h
> @@ -70,6 +70,7 @@ bool bt_gatt_client_set_debug(struct bt_gatt_client
> *client, bt_gatt_client_destroy_func_t destroy);
>
> uint16_t bt_gatt_client_get_mtu(struct bt_gatt_client *client);
> +struct gatt_db *bt_gatt_client_get_db(struct bt_gatt_client *client);
>
> bool bt_gatt_client_cancel(struct bt_gatt_client *client, unsigned int id);
> bool bt_gatt_client_cancel_all(struct bt_gatt_client *client);
--
BR
Szymon Janc
^ permalink raw reply [flat|nested] 41+ messages in thread
* [PATCH 04/28] android/hog: Remove tracking gatt operations
2015-04-01 16:40 [PATCH 00/28] android/hog Introduce bt_gatt_client Mariusz Skamra
` (2 preceding siblings ...)
2015-04-01 16:40 ` [PATCH 03/28] shared/gatt-client: Expose gatt_db Mariusz Skamra
@ 2015-04-01 16:40 ` Mariusz Skamra
2015-04-01 16:40 ` [PATCH 05/28] android/hog: Use bt_gatt_client to read characteristic value Mariusz Skamra
` (23 subsequent siblings)
27 siblings, 0 replies; 41+ messages in thread
From: Mariusz Skamra @ 2015-04-01 16:40 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Mariusz Skamra
Since the use of bt_gatt_client there is no need to queue pending gatt
operations. bt_gatt_client already keeps track on that, so that
on bt_gatt_client_unref the queue of pending requests is destroyed.
---
android/hog.c | 283 +++++++---------------------------------------------------
1 file changed, 33 insertions(+), 250 deletions(-)
diff --git a/android/hog.c b/android/hog.c
index 5b8c079..4c39ad7 100644
--- a/android/hog.c
+++ b/android/hog.c
@@ -106,7 +106,6 @@ struct bt_hog {
struct bt_dis *dis;
struct queue *bas;
GSList *instances;
- struct queue *gatt_op;
struct bt_gatt_client *client;
};
@@ -121,168 +120,6 @@ struct report {
uint8_t *value;
};
-struct gatt_request {
- unsigned int id;
- struct bt_hog *hog;
- void *user_data;
-};
-
-static struct gatt_request *create_request(struct bt_hog *hog,
- void *user_data)
-{
- struct gatt_request *req;
-
- req = new0(struct gatt_request, 1);
- if (!req)
- return NULL;
-
- req->user_data = user_data;
- req->hog = bt_hog_ref(hog);
-
- return req;
-}
-
-static bool set_and_store_gatt_req(struct bt_hog *hog,
- struct gatt_request *req,
- unsigned int id)
-{
- req->id = id;
- return queue_push_head(hog->gatt_op, req);
-}
-
-static void destroy_gatt_req(struct gatt_request *req)
-{
- queue_remove(req->hog->gatt_op, req);
- bt_hog_unref(req->hog);
- free(req);
-}
-
-static void write_char(struct bt_hog *hog, GAttrib *attrib, uint16_t handle,
- const uint8_t *value, size_t vlen,
- GAttribResultFunc func,
- gpointer user_data)
-{
- struct gatt_request *req;
- unsigned int id;
-
- req = create_request(hog, user_data);
- if (!req)
- return;
-
- id = gatt_write_char(attrib, handle, value, vlen, func, req);
-
- if (set_and_store_gatt_req(hog, req, id))
- return;
-
- error("hog: Could not read char");
- g_attrib_cancel(attrib, id);
- free(req);
-}
-
-static void read_char(struct bt_hog *hog, GAttrib *attrib, uint16_t handle,
- GAttribResultFunc func, gpointer user_data)
-{
- struct gatt_request *req;
- unsigned int id;
-
- req = create_request(hog, user_data);
- if (!req)
- return;
-
- id = gatt_read_char(attrib, handle, func, req);
-
- if (set_and_store_gatt_req(hog, req, id))
- return;
-
- error("hog: Could not read char");
- g_attrib_cancel(attrib, id);
- free(req);
-}
-
-static void discover_desc(struct bt_hog *hog, GAttrib *attrib,
- uint16_t start, uint16_t end, gatt_cb_t func,
- gpointer user_data)
-{
- struct gatt_request *req;
- unsigned int id;
-
- req = create_request(hog, user_data);
- if (!req)
- return;
-
- id = gatt_discover_desc(attrib, start, end, NULL, func, req);
- if (set_and_store_gatt_req(hog, req, id))
- return;
-
- error("hog: Could not discover descriptors");
- g_attrib_cancel(attrib, id);
- free(req);
-}
-
-static void discover_char(struct bt_hog *hog, GAttrib *attrib,
- uint16_t start, uint16_t end,
- bt_uuid_t *uuid, gatt_cb_t func,
- gpointer user_data)
-{
- struct gatt_request *req;
- unsigned int id;
-
- req = create_request(hog, user_data);
- if (!req)
- return;
-
- id = gatt_discover_char(attrib, start, end, uuid, func, req);
-
- if (set_and_store_gatt_req(hog, req, id))
- return;
-
- error("hog: Could not discover characteristic");
- g_attrib_cancel(attrib, id);
- free(req);
-}
-
-static void discover_primary(struct bt_hog *hog, GAttrib *attrib,
- bt_uuid_t *uuid, gatt_cb_t func,
- gpointer user_data)
-{
- struct gatt_request *req;
- unsigned int id;
-
- req = create_request(hog, user_data);
- if (!req)
- return;
-
- id = gatt_discover_primary(attrib, uuid, func, req);
-
- if (set_and_store_gatt_req(hog, req, id))
- return;
-
- error("hog: Could not send discover primary");
- g_attrib_cancel(attrib, id);
- free(req);
-}
-
-static void find_included(struct bt_hog *hog, GAttrib *attrib,
- uint16_t start, uint16_t end,
- gatt_cb_t func, gpointer user_data)
-{
- struct gatt_request *req;
- unsigned int id;
-
- req = create_request(hog, user_data);
- if (!req)
- return;
-
- id = gatt_find_included(attrib, start, end, func, req);
-
- if (set_and_store_gatt_req(hog, req, id))
- return;
-
- error("Could not find included");
- g_attrib_cancel(attrib, id);
- free(req);
-}
-
static void report_value_cb(const guint8 *pdu, guint16 len, gpointer user_data)
{
struct report *report = user_data;
@@ -326,12 +163,9 @@ static void report_value_cb(const guint8 *pdu, guint16 len, gpointer user_data)
static void report_ccc_written_cb(guint8 status, const guint8 *pdu,
guint16 plen, gpointer user_data)
{
- struct gatt_request *req = user_data;
- struct report *report = req->user_data;
+ struct report *report = user_data;
struct bt_hog *hog = report->hog;
- destroy_gatt_req(req);
-
if (status != 0) {
error("Write report characteristic descriptor failed: %s",
att_ecode2str(status));
@@ -353,17 +187,14 @@ static void write_ccc(struct bt_hog *hog, GAttrib *attrib, uint16_t handle,
put_le16(GATT_CLIENT_CHARAC_CFG_NOTIF_BIT, value);
- write_char(hog, attrib, handle, value, sizeof(value),
+ gatt_write_char(attrib, handle, value, sizeof(value),
report_ccc_written_cb, user_data);
}
static void ccc_read_cb(guint8 status, const guint8 *pdu, guint16 len,
gpointer user_data)
{
- struct gatt_request *req = user_data;
- struct report *report = req->user_data;
-
- destroy_gatt_req(req);
+ struct report *report = user_data;
if (status != 0) {
error("Error reading CCC value: %s", att_ecode2str(status));
@@ -376,10 +207,7 @@ static void ccc_read_cb(guint8 status, const guint8 *pdu, guint16 len,
static void report_reference_cb(guint8 status, const guint8 *pdu,
guint16 plen, gpointer user_data)
{
- struct gatt_request *req = user_data;
- struct report *report = req->user_data;
-
- destroy_gatt_req(req);
+ struct report *report = user_data;
if (status != 0) {
error("Read Report Reference descriptor failed: %s",
@@ -398,7 +226,7 @@ static void report_reference_cb(guint8 status, const guint8 *pdu,
/* Enable notifications only for Input Reports */
if (report->type == HOG_REPORT_TYPE_INPUT)
- read_char(report->hog, report->hog->attrib, report->ccc_handle,
+ gatt_read_char(report->hog->attrib, report->ccc_handle,
ccc_read_cb, report);
}
@@ -407,10 +235,7 @@ static void external_report_reference_cb(guint8 status, const guint8 *pdu,
static void discover_external_cb(uint8_t status, GSList *descs, void *user_data)
{
- struct gatt_request *req = user_data;
- struct bt_hog *hog = req->user_data;
-
- destroy_gatt_req(req);
+ struct bt_hog *hog = user_data;
if (status != 0) {
error("Discover external descriptors failed: %s",
@@ -421,7 +246,7 @@ static void discover_external_cb(uint8_t status, GSList *descs, void *user_data)
for ( ; descs; descs = descs->next) {
struct gatt_desc *desc = descs->data;
- read_char(hog, hog->attrib, desc->handle,
+ gatt_read_char(hog->attrib, desc->handle,
external_report_reference_cb,
hog);
}
@@ -438,18 +263,15 @@ static void discover_external(struct bt_hog *hog, GAttrib *attrib,
bt_uuid16_create(&uuid, GATT_EXTERNAL_REPORT_REFERENCE);
- discover_desc(hog, attrib, start, end, discover_external_cb,
+ gatt_discover_desc(attrib, start, end, NULL, discover_external_cb,
user_data);
}
static void discover_report_cb(uint8_t status, GSList *descs, void *user_data)
{
- struct gatt_request *req = user_data;
- struct report *report = req->user_data;
+ struct report *report = user_data;
struct bt_hog *hog = report->hog;
- destroy_gatt_req(req);
-
if (status != 0) {
error("Discover report descriptors failed: %s",
att_ecode2str(status));
@@ -464,7 +286,7 @@ static void discover_report_cb(uint8_t status, GSList *descs, void *user_data)
report->ccc_handle = desc->handle;
break;
case GATT_REPORT_REFERENCE:
- read_char(hog, hog->attrib, desc->handle,
+ gatt_read_char(hog->attrib, desc->handle,
report_reference_cb, report);
break;
}
@@ -478,16 +300,14 @@ static void discover_report(struct bt_hog *hog, GAttrib *attrib,
if (start > end)
return;
- discover_desc(hog, attrib, start, end, discover_report_cb, user_data);
+ gatt_discover_desc(attrib, start, end, NULL, discover_report_cb,
+ user_data);
}
static void report_read_cb(guint8 status, const guint8 *pdu, guint16 len,
gpointer user_data)
{
- struct gatt_request *req = user_data;
- struct report *report = req->user_data;
-
- destroy_gatt_req(req);
+ struct report *report = user_data;
if (status != 0) {
error("Error reading Report value: %s", att_ecode2str(status));
@@ -510,7 +330,7 @@ static struct report *report_new(struct bt_hog *hog, struct gatt_char *chr)
report->decl = g_memdup(chr, sizeof(*chr));
hog->reports = g_slist_append(hog->reports, report);
- read_char(hog, hog->attrib, chr->value_handle, report_read_cb, report);
+ gatt_read_char(hog->attrib, chr->value_handle, report_read_cb, report);
return report;
}
@@ -518,14 +338,11 @@ static struct report *report_new(struct bt_hog *hog, struct gatt_char *chr)
static void external_service_char_cb(uint8_t status, GSList *chars,
void *user_data)
{
- struct gatt_request *req = user_data;
- struct bt_hog *hog = req->user_data;
+ struct bt_hog *hog = user_data;
struct gatt_primary *primary = hog->primary;
struct report *report;
GSList *l;
- destroy_gatt_req(req);
-
if (status != 0) {
const char *str = att_ecode2str(status);
DBG("Discover external service characteristic failed: %s", str);
@@ -552,13 +369,10 @@ static void external_service_char_cb(uint8_t status, GSList *chars,
static void external_report_reference_cb(guint8 status, const guint8 *pdu,
guint16 plen, gpointer user_data)
{
- struct gatt_request *req = user_data;
- struct bt_hog *hog = req->user_data;
+ struct bt_hog *hog = user_data;
uint16_t uuid16;
bt_uuid_t uuid;
- destroy_gatt_req(req);
-
if (status != 0) {
error("Read External Report Reference descriptor failed: %s",
att_ecode2str(status));
@@ -579,7 +393,7 @@ static void external_report_reference_cb(guint8 status, const guint8 *pdu,
return;
bt_uuid16_create(&uuid, uuid16);
- discover_char(hog, hog->attrib, 0x0001, 0xffff, &uuid,
+ gatt_discover_char(hog->attrib, 0x0001, 0xffff, &uuid,
external_service_char_cb, hog);
}
@@ -637,10 +451,6 @@ static struct report *find_report_by_rtype(struct bt_hog *hog, uint8_t rtype,
static void output_written_cb(guint8 status, const guint8 *pdu,
guint16 plen, gpointer user_data)
{
- struct gatt_request *req = user_data;
-
- destroy_gatt_req(req);
-
if (status != 0) {
error("Write output report failed: %s", att_ecode2str(status));
return;
@@ -673,7 +483,7 @@ static void forward_report(struct uhid_event *ev, void *user_data)
return;
if (report->decl->properties & GATT_CHR_PROP_WRITE)
- write_char(hog, hog->attrib, report->decl->value_handle,
+ gatt_write_char(hog->attrib, report->decl->value_handle,
data, size, output_written_cb, hog);
else if (report->decl->properties & GATT_CHR_PROP_WRITE_WITHOUT_RESP)
gatt_write_cmd(hog->attrib, report->decl->value_handle,
@@ -933,8 +743,7 @@ static char *item2string(char *str, uint8_t *buf, uint8_t len)
static void report_map_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
gpointer user_data)
{
- struct gatt_request *req = user_data;
- struct bt_hog *hog = req->user_data;
+ struct bt_hog *hog = user_data;
uint8_t value[HOG_REPORT_MAP_MAX_SIZE];
struct uhid_event ev;
ssize_t vlen;
@@ -942,8 +751,6 @@ static void report_map_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
int i, err;
GError *gerr = NULL;
- destroy_gatt_req(req);
-
if (status != 0) {
error("Report Map read failed: %s", att_ecode2str(status));
return;
@@ -1016,13 +823,10 @@ static void report_map_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
static void info_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
gpointer user_data)
{
- struct gatt_request *req = user_data;
- struct bt_hog *hog = req->user_data;
+ struct bt_hog *hog = user_data;
uint8_t value[HID_INFO_SIZE];
ssize_t vlen;
- destroy_gatt_req(req);
-
if (status != 0) {
error("HID Information read failed: %s",
att_ecode2str(status));
@@ -1046,13 +850,10 @@ static void info_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
static void proto_mode_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
gpointer user_data)
{
- struct gatt_request *req = user_data;
- struct bt_hog *hog = req->user_data;
+ struct bt_hog *hog = user_data;
uint8_t value;
ssize_t vlen;
- destroy_gatt_req(req);
-
if (status != 0) {
error("Protocol Mode characteristic read failed: %s",
att_ecode2str(status));
@@ -1078,8 +879,7 @@ static void proto_mode_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
static void char_discovered_cb(uint8_t status, GSList *chars, void *user_data)
{
- struct gatt_request *req = user_data;
- struct bt_hog *hog = req->user_data;
+ struct bt_hog *hog = user_data;
struct gatt_primary *primary = hog->primary;
bt_uuid_t report_uuid, report_map_uuid, info_uuid;
bt_uuid_t proto_mode_uuid, ctrlpt_uuid;
@@ -1087,8 +887,6 @@ static void char_discovered_cb(uint8_t status, GSList *chars, void *user_data)
GSList *l;
uint16_t info_handle = 0, proto_mode_handle = 0;
- destroy_gatt_req(req);
-
if (status != 0) {
const char *str = att_ecode2str(status);
DBG("Discover all characteristics failed: %s", str);
@@ -1121,7 +919,7 @@ static void char_discovered_cb(uint8_t status, GSList *chars, void *user_data)
report = report_new(hog, chr);
discover_report(hog, hog->attrib, start, end, report);
} else if (bt_uuid_cmp(&uuid, &report_map_uuid) == 0) {
- read_char(hog, hog->attrib, chr->value_handle,
+ gatt_read_char(hog->attrib, chr->value_handle,
report_map_read_cb, hog);
discover_external(hog, hog->attrib, start, end, hog);
} else if (bt_uuid_cmp(&uuid, &info_uuid) == 0)
@@ -1134,12 +932,12 @@ static void char_discovered_cb(uint8_t status, GSList *chars, void *user_data)
if (proto_mode_handle) {
hog->proto_mode_handle = proto_mode_handle;
- read_char(hog, hog->attrib, proto_mode_handle,
+ gatt_read_char(hog->attrib, proto_mode_handle,
proto_mode_read_cb, hog);
}
if (info_handle)
- read_char(hog, hog->attrib, info_handle, info_read_cb, hog);
+ gatt_read_char(hog->attrib, info_handle, info_read_cb, hog);
}
static void report_free(void *data)
@@ -1151,12 +949,6 @@ static void report_free(void *data)
g_free(report);
}
-static void cancel_gatt_req(struct gatt_request *req)
-{
- if (g_attrib_cancel(req->hog->attrib, req->id))
- destroy_gatt_req(req);
-}
-
static void hog_free(void *data)
{
struct bt_hog *hog = data;
@@ -1172,7 +964,6 @@ static void hog_free(void *data)
g_slist_free_full(hog->reports, report_free);
g_free(hog->name);
g_free(hog->primary);
- queue_destroy(hog->gatt_op, (void *) destroy_gatt_req);
g_free(hog);
}
@@ -1194,7 +985,6 @@ struct bt_hog *bt_hog_new(int fd, const char *name, uint16_t vendor,
if (!hog)
return NULL;
- hog->gatt_op = queue_new();
hog->bas = queue_new();
if (fd < 0)
@@ -1204,7 +994,7 @@ struct bt_hog *bt_hog_new(int fd, const char *name, uint16_t vendor,
hog->uhid_fd = fd;
- if (!hog->gatt_op || !hog->bas || !hog->uhid) {
+ if (!hog->bas || !hog->uhid) {
hog_free(hog);
return NULL;
}
@@ -1246,13 +1036,10 @@ void bt_hog_unref(struct bt_hog *hog)
static void find_included_cb(uint8_t status, GSList *services, void *user_data)
{
- struct gatt_request *req = user_data;
GSList *l;
DBG("");
- destroy_gatt_req(req);
-
if (status) {
const char *str = att_ecode2str(status);
DBG("Find included failed: %s", str);
@@ -1321,10 +1108,10 @@ static void hog_attach_hog(struct bt_hog *hog, struct gatt_primary *primary)
if (!hog->primary) {
hog->primary = g_memdup(primary, sizeof(*primary));
- discover_char(hog, hog->attrib, primary->range.start,
+ gatt_discover_char(hog->attrib, primary->range.start,
primary->range.end, NULL,
char_discovered_cb, hog);
- find_included(hog, hog->attrib, primary->range.start,
+ gatt_find_included(hog->attrib, primary->range.start,
primary->range.end, find_included_cb, hog);
return;
}
@@ -1334,7 +1121,7 @@ static void hog_attach_hog(struct bt_hog *hog, struct gatt_primary *primary)
if (!instance)
return;
- find_included(instance, hog->attrib, primary->range.start,
+ gatt_find_included(hog->attrib, primary->range.start,
primary->range.end, find_included_cb, instance);
bt_hog_attach(instance, hog->attrib, hog->client);
@@ -1343,15 +1130,12 @@ static void hog_attach_hog(struct bt_hog *hog, struct gatt_primary *primary)
static void primary_cb(uint8_t status, GSList *services, void *user_data)
{
- struct gatt_request *req = user_data;
- struct bt_hog *hog = req->user_data;
+ struct bt_hog *hog = user_data;
struct gatt_primary *primary;
GSList *l;
DBG("");
- destroy_gatt_req(req);
-
if (status) {
const char *str = att_ecode2str(status);
DBG("Discover primary failed: %s", str);
@@ -1398,7 +1182,7 @@ bool bt_hog_attach(struct bt_hog *hog, void *gatt, void *client)
hog->client = bt_gatt_client_ref(client);
if (!primary) {
- discover_primary(hog, hog->attrib, NULL, primary_cb, hog);
+ gatt_discover_primary(hog->attrib, NULL, primary_cb, hog);
return true;
}
@@ -1417,7 +1201,7 @@ bool bt_hog_attach(struct bt_hog *hog, void *gatt, void *client)
}
if (hog->reports == NULL) {
- discover_char(hog, hog->attrib, primary->range.start,
+ gatt_discover_char(hog->attrib, primary->range.start,
primary->range.end, NULL,
char_discovered_cb, hog);
return true;
@@ -1465,7 +1249,6 @@ void bt_hog_detach(struct bt_hog *hog)
if (hog->dis)
bt_dis_detach(hog->dis);
- queue_foreach(hog->gatt_op, (void *) cancel_gatt_req, NULL);
bt_gatt_client_unref(hog->client);
g_attrib_unref(hog->attrib);
hog->client = NULL;
@@ -1506,7 +1289,7 @@ int bt_hog_send_report(struct bt_hog *hog, void *data, size_t size, int type)
DBG("hog: Write report, handle 0x%X", report->decl->value_handle);
if (report->decl->properties & GATT_CHR_PROP_WRITE)
- write_char(hog, hog->attrib, report->decl->value_handle,
+ gatt_write_char(hog->attrib, report->decl->value_handle,
data, size, output_written_cb, hog);
if (report->decl->properties & GATT_CHR_PROP_WRITE_WITHOUT_RESP)
--
1.9.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [PATCH 05/28] android/hog: Use bt_gatt_client to read characteristic value
2015-04-01 16:40 [PATCH 00/28] android/hog Introduce bt_gatt_client Mariusz Skamra
` (3 preceding siblings ...)
2015-04-01 16:40 ` [PATCH 04/28] android/hog: Remove tracking gatt operations Mariusz Skamra
@ 2015-04-01 16:40 ` Mariusz Skamra
2015-04-01 16:40 ` [PATCH 06/28] android/hog: Use bt_gatt_client to register for notifications Mariusz Skamra
` (22 subsequent siblings)
27 siblings, 0 replies; 41+ messages in thread
From: Mariusz Skamra @ 2015-04-01 16:40 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Mariusz Skamra
This patch replaces gatt_read_char from gattib library with equivalent
bt_gatt_client_read_value function. It requires some changes in declaration
list of callbacks. Since the actual value is read, not pdu, some changes
in code are necessary.
---
android/hog.c | 149 +++++++++++++++++++++++++++-------------------------------
1 file changed, 69 insertions(+), 80 deletions(-)
diff --git a/android/hog.c b/android/hog.c
index 4c39ad7..ec81f0f 100644
--- a/android/hog.c
+++ b/android/hog.c
@@ -204,25 +204,26 @@ static void ccc_read_cb(guint8 status, const guint8 *pdu, guint16 len,
write_ccc(report->hog, report->hog->attrib, report->ccc_handle, report);
}
-static void report_reference_cb(guint8 status, const guint8 *pdu,
- guint16 plen, gpointer user_data)
+static void report_reference_cb(bool success, uint8_t status,
+ const uint8_t *value, uint16_t length,
+ void *user_data)
{
struct report *report = user_data;
- if (status != 0) {
+ if (!success) {
error("Read Report Reference descriptor failed: %s",
att_ecode2str(status));
return;
}
- if (plen != 3) {
+ if (length != 2) {
error("Malformed ATT read response");
return;
}
- report->id = pdu[1];
- report->type = pdu[2];
- DBG("Report ID: 0x%02x Report type: 0x%02x", pdu[1], pdu[2]);
+ report->id = value[0];
+ report->type = value[1];
+ DBG("Report ID: 0x%02x Report type: 0x%02x", value[0], value[1]);
/* Enable notifications only for Input Reports */
if (report->type == HOG_REPORT_TYPE_INPUT)
@@ -230,8 +231,9 @@ static void report_reference_cb(guint8 status, const guint8 *pdu,
ccc_read_cb, report);
}
-static void external_report_reference_cb(guint8 status, const guint8 *pdu,
- guint16 plen, gpointer user_data);
+static void external_report_reference_cb(bool success, uint8_t status,
+ const uint8_t *value, uint16_t length,
+ void *user_data);
static void discover_external_cb(uint8_t status, GSList *descs, void *user_data)
{
@@ -246,9 +248,8 @@ static void discover_external_cb(uint8_t status, GSList *descs, void *user_data)
for ( ; descs; descs = descs->next) {
struct gatt_desc *desc = descs->data;
- gatt_read_char(hog->attrib, desc->handle,
- external_report_reference_cb,
- hog);
+ bt_gatt_client_read_value(hog->client, desc->handle,
+ external_report_reference_cb, hog, NULL);
}
}
@@ -286,8 +287,8 @@ static void discover_report_cb(uint8_t status, GSList *descs, void *user_data)
report->ccc_handle = desc->handle;
break;
case GATT_REPORT_REFERENCE:
- gatt_read_char(hog->attrib, desc->handle,
- report_reference_cb, report);
+ bt_gatt_client_read_value(hog->client, desc->handle,
+ report_reference_cb, report, NULL);
break;
}
}
@@ -304,20 +305,22 @@ static void discover_report(struct bt_hog *hog, GAttrib *attrib,
user_data);
}
-static void report_read_cb(guint8 status, const guint8 *pdu, guint16 len,
- gpointer user_data)
+static void report_read_cb(bool success, uint8_t att_ecode,
+ const uint8_t *value, uint16_t len,
+ void *user_data)
{
struct report *report = user_data;
- if (status != 0) {
- error("Error reading Report value: %s", att_ecode2str(status));
+ if (!success) {
+ error("Error reading Report value: %s",
+ att_ecode2str(att_ecode));
return;
}
if (report->value)
g_free(report->value);
- report->value = g_memdup(pdu, len);
+ report->value = g_memdup(value, len);
report->len = len;
}
@@ -330,7 +333,8 @@ static struct report *report_new(struct bt_hog *hog, struct gatt_char *chr)
report->decl = g_memdup(chr, sizeof(*chr));
hog->reports = g_slist_append(hog->reports, report);
- gatt_read_char(hog->attrib, chr->value_handle, report_read_cb, report);
+ bt_gatt_client_read_value(hog->client, chr->value_handle,
+ report_read_cb, report, NULL);
return report;
}
@@ -366,25 +370,26 @@ static void external_service_char_cb(uint8_t status, GSList *chars,
}
}
-static void external_report_reference_cb(guint8 status, const guint8 *pdu,
- guint16 plen, gpointer user_data)
+static void external_report_reference_cb(bool success, uint8_t status,
+ const uint8_t *value, uint16_t length,
+ void *user_data)
{
struct bt_hog *hog = user_data;
uint16_t uuid16;
bt_uuid_t uuid;
- if (status != 0) {
+ if (!success) {
error("Read External Report Reference descriptor failed: %s",
att_ecode2str(status));
return;
}
- if (plen != 3) {
+ if (length != 2) {
error("Malformed ATT read response");
return;
}
- uuid16 = get_le16(&pdu[1]);
+ uuid16 = get_le16(value);
DBG("External report reference read, external report characteristic "
"UUID: 0x%04x", uuid16);
@@ -595,8 +600,8 @@ fail:
set_report_cb(err, NULL, 0, hog);
}
-static void get_report_cb(guint8 status, const guint8 *pdu, guint16 len,
- gpointer user_data)
+static void get_report_cb(bool success, uint8_t status, const uint8_t *value,
+ uint16_t len, void *user_data)
{
struct bt_hog *hog = user_data;
struct uhid_event rsp;
@@ -608,7 +613,7 @@ static void get_report_cb(guint8 status, const guint8 *pdu, guint16 len,
rsp.type = UHID_GET_REPORT_REPLY;
rsp.u.get_report_reply.id = hog->getrep_id;
- if (status != 0) {
+ if (!success) {
error("Error reading Report value: %s", att_ecode2str(status));
goto exit;
}
@@ -619,21 +624,21 @@ static void get_report_cb(guint8 status, const guint8 *pdu, guint16 len,
goto exit;
}
- if (pdu[0] != 0x0b) {
- error("Error reading Report, invalid response: %02x", pdu[0]);
+ if (value[0] != 0x0b) {
+ error("Error reading Report, invalid response: %02x", value[0]);
status = EPROTO;
goto exit;
}
--len;
- ++pdu;
+ ++value;
if (hog->has_report_id && len > 0) {
--len;
- ++pdu;
+ ++value;
}
rsp.u.get_report_reply.size = len;
- memcpy(rsp.u.get_report_reply.data, pdu, len);
+ memcpy(rsp.u.get_report_reply.data, value, len);
exit:
rsp.u.get_report_reply.err = status;
@@ -650,7 +655,7 @@ static void get_report(struct uhid_event *ev, void *user_data)
/* uhid never sends reqs in parallel; if there's a req, it timed out */
if (hog->getrep_att) {
- g_attrib_cancel(hog->attrib, hog->getrep_att);
+ bt_gatt_client_cancel(hog->client, hog->getrep_att);
hog->getrep_att = 0;
}
@@ -663,9 +668,9 @@ static void get_report(struct uhid_event *ev, void *user_data)
goto fail;
}
- hog->getrep_att = gatt_read_char(hog->attrib,
+ hog->getrep_att = bt_gatt_client_read_value(hog->client,
report->decl->value_handle,
- get_report_cb, hog);
+ get_report_cb, hog, NULL);
if (!hog->getrep_att) {
err = ENOMEM;
goto fail;
@@ -675,11 +680,11 @@ static void get_report(struct uhid_event *ev, void *user_data)
fail:
/* cancel the request on failure */
- get_report_cb(err, NULL, 0, hog);
+ get_report_cb(false, err, NULL, 0, hog);
}
-static bool get_descriptor_item_info(uint8_t *buf, ssize_t blen, ssize_t *len,
- bool *is_long)
+static bool get_descriptor_item_info(const uint8_t *buf, ssize_t blen,
+ ssize_t *len, bool *is_long)
{
if (!blen)
return false;
@@ -718,7 +723,7 @@ static bool get_descriptor_item_info(uint8_t *buf, ssize_t blen, ssize_t *len,
return *len <= blen;
}
-static char *item2string(char *str, uint8_t *buf, uint8_t len)
+static char *item2string(char *str, const uint8_t *buf, uint8_t len)
{
char *p = str;
int i;
@@ -740,25 +745,18 @@ static char *item2string(char *str, uint8_t *buf, uint8_t len)
return str;
}
-static void report_map_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
- gpointer user_data)
+static void report_map_read_cb(bool success, uint8_t att_ecode,
+ const uint8_t *value, uint16_t vlen,
+ void *user_data)
{
struct bt_hog *hog = user_data;
- uint8_t value[HOG_REPORT_MAP_MAX_SIZE];
struct uhid_event ev;
- ssize_t vlen;
char itemstr[20]; /* 5x3 (data) + 4 (continuation) + 1 (null) */
int i, err;
GError *gerr = NULL;
- if (status != 0) {
- error("Report Map read failed: %s", att_ecode2str(status));
- return;
- }
-
- vlen = dec_read_resp(pdu, plen, value, sizeof(value));
- if (vlen < 0) {
- error("ATT protocol error");
+ if (!success) {
+ error("Report Map read failed: %s", att_ecode2str(att_ecode));
return;
}
@@ -805,7 +803,7 @@ static void report_map_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
ev.u.create.version = hog->version;
ev.u.create.country = hog->bcountrycode;
ev.u.create.bus = BUS_BLUETOOTH;
- ev.u.create.rd_data = value;
+ ev.u.create.rd_data = (uint8_t *) value;
ev.u.create.rd_size = vlen;
err = bt_uhid_send(hog->uhid, &ev);
@@ -820,20 +818,16 @@ static void report_map_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
bt_uhid_register(hog->uhid, UHID_SET_REPORT, set_report, hog);
}
-static void info_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
- gpointer user_data)
+static void info_read_cb(bool success, uint8_t status, const uint8_t *value,
+ uint16_t vlen, void *user_data)
{
struct bt_hog *hog = user_data;
- uint8_t value[HID_INFO_SIZE];
- ssize_t vlen;
- if (status != 0) {
- error("HID Information read failed: %s",
- att_ecode2str(status));
+ if (!success) {
+ error("HID Information read failed: %s", att_ecode2str(status));
return;
}
- vlen = dec_read_resp(pdu, plen, value, sizeof(value));
if (vlen != 4) {
error("ATT protocol error");
return;
@@ -847,33 +841,26 @@ static void info_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
hog->bcdhid, hog->bcountrycode, hog->flags);
}
-static void proto_mode_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
- gpointer user_data)
+static void proto_mode_read_cb(bool success, uint8_t att_ecode,
+ const uint8_t *value, uint16_t length,
+ void *user_data)
{
struct bt_hog *hog = user_data;
- uint8_t value;
- ssize_t vlen;
- if (status != 0) {
+ if (!success) {
error("Protocol Mode characteristic read failed: %s",
- att_ecode2str(status));
- return;
- }
-
- vlen = dec_read_resp(pdu, plen, &value, sizeof(value));
- if (vlen < 0) {
- error("ATT protocol error");
+ att_ecode2str(att_ecode));
return;
}
- if (value == HOG_PROTO_MODE_BOOT) {
+ if (value[0] == HOG_PROTO_MODE_BOOT) {
uint8_t nval = HOG_PROTO_MODE_REPORT;
DBG("HoG is operating in Boot Procotol Mode");
gatt_write_cmd(hog->attrib, hog->proto_mode_handle, &nval,
sizeof(nval), NULL, NULL);
- } else if (value == HOG_PROTO_MODE_REPORT)
+ } else if (value[0] == HOG_PROTO_MODE_REPORT)
DBG("HoG is operating in Report Protocol Mode");
}
@@ -919,8 +906,9 @@ static void char_discovered_cb(uint8_t status, GSList *chars, void *user_data)
report = report_new(hog, chr);
discover_report(hog, hog->attrib, start, end, report);
} else if (bt_uuid_cmp(&uuid, &report_map_uuid) == 0) {
- gatt_read_char(hog->attrib, chr->value_handle,
- report_map_read_cb, hog);
+ bt_gatt_client_read_long_value(hog->client,
+ chr->value_handle, 0, report_map_read_cb,
+ hog, NULL);
discover_external(hog, hog->attrib, start, end, hog);
} else if (bt_uuid_cmp(&uuid, &info_uuid) == 0)
info_handle = chr->value_handle;
@@ -932,12 +920,13 @@ static void char_discovered_cb(uint8_t status, GSList *chars, void *user_data)
if (proto_mode_handle) {
hog->proto_mode_handle = proto_mode_handle;
- gatt_read_char(hog->attrib, proto_mode_handle,
- proto_mode_read_cb, hog);
+ bt_gatt_client_read_value(hog->client, proto_mode_handle,
+ proto_mode_read_cb, hog, NULL);
}
if (info_handle)
- gatt_read_char(hog->attrib, info_handle, info_read_cb, hog);
+ bt_gatt_client_read_value(hog->client, info_handle,
+ info_read_cb, hog, NULL);
}
static void report_free(void *data)
--
1.9.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [PATCH 06/28] android/hog: Use bt_gatt_client to register for notifications
2015-04-01 16:40 [PATCH 00/28] android/hog Introduce bt_gatt_client Mariusz Skamra
` (4 preceding siblings ...)
2015-04-01 16:40 ` [PATCH 05/28] android/hog: Use bt_gatt_client to read characteristic value Mariusz Skamra
@ 2015-04-01 16:40 ` Mariusz Skamra
2015-04-01 16:40 ` [PATCH 07/28] android/hog: Use bt_gatt_client to write without response Mariusz Skamra
` (21 subsequent siblings)
27 siblings, 0 replies; 41+ messages in thread
From: Mariusz Skamra @ 2015-04-01 16:40 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Mariusz Skamra
This patch replaces g_attrib_register with bt_gatt_client_register_notify
to register for notifications of report reference.
Since bt_gatt_client_notify_callback_t returns a pointer to value
not pdu, notification header is not present and
ATT_NOTIFICATION_HEADER_SIZE can be removed.
There is no need to read and store ccc_handle, because it's already cached
and keep by bt_gatt_client. To register for notification only
characteristic value handle is needed.
---
android/hog.c | 73 +++++++++++++----------------------------------------------
1 file changed, 16 insertions(+), 57 deletions(-)
diff --git a/android/hog.c b/android/hog.c
index ec81f0f..3f28ecb 100644
--- a/android/hog.c
+++ b/android/hog.c
@@ -78,7 +78,6 @@
#define HOG_REPORT_MAP_MAX_SIZE 512
#define HID_INFO_SIZE 4
-#define ATT_NOTIFICATION_HEADER_SIZE 3
struct bt_hog {
int ref_count;
@@ -113,14 +112,14 @@ struct report {
struct bt_hog *hog;
uint8_t id;
uint8_t type;
- uint16_t ccc_handle;
- guint notifyid;
+ uint32_t notifyid;
struct gatt_char *decl;
uint16_t len;
uint8_t *value;
};
-static void report_value_cb(const guint8 *pdu, guint16 len, gpointer user_data)
+static void report_value_cb(uint16_t value_handle, const uint8_t *value,
+ uint16_t len, void *user_data)
{
struct report *report = user_data;
struct bt_hog *hog = report->hog;
@@ -128,14 +127,6 @@ static void report_value_cb(const guint8 *pdu, guint16 len, gpointer user_data)
uint8_t *buf;
int err;
- if (len < ATT_NOTIFICATION_HEADER_SIZE) {
- error("Malformed ATT notification");
- return;
- }
-
- pdu += ATT_NOTIFICATION_HEADER_SIZE;
- len -= ATT_NOTIFICATION_HEADER_SIZE;
-
memset(&ev, 0, sizeof(ev));
ev.type = UHID_INPUT;
buf = ev.u.input.data;
@@ -143,11 +134,11 @@ static void report_value_cb(const guint8 *pdu, guint16 len, gpointer user_data)
if (hog->has_report_id) {
buf[0] = report->id;
len = MIN(len, sizeof(ev.u.input.data) - 1);
- memcpy(buf + 1, pdu, len);
+ memcpy(buf + 1, value, len);
ev.u.input.size = ++len;
} else {
len = MIN(len, sizeof(ev.u.input.data));
- memcpy(buf, pdu, len);
+ memcpy(buf, value, len);
ev.u.input.size = len;
}
@@ -160,55 +151,23 @@ static void report_value_cb(const guint8 *pdu, guint16 len, gpointer user_data)
DBG("HoG report (%u bytes)", ev.u.input.size);
}
-static void report_ccc_written_cb(guint8 status, const guint8 *pdu,
- guint16 plen, gpointer user_data)
+static void report_ccc_written_cb(uint16_t status, void *user_data)
{
- struct report *report = user_data;
- struct bt_hog *hog = report->hog;
-
if (status != 0) {
error("Write report characteristic descriptor failed: %s",
att_ecode2str(status));
return;
}
- report->notifyid = g_attrib_register(hog->attrib,
- ATT_OP_HANDLE_NOTIFY,
- report->decl->value_handle,
- report_value_cb, report, NULL);
-
DBG("Report characteristic descriptor written: notifications enabled");
}
-static void write_ccc(struct bt_hog *hog, GAttrib *attrib, uint16_t handle,
- void *user_data)
-{
- uint8_t value[2];
-
- put_le16(GATT_CLIENT_CHARAC_CFG_NOTIF_BIT, value);
-
- gatt_write_char(attrib, handle, value, sizeof(value),
- report_ccc_written_cb, user_data);
-}
-
-static void ccc_read_cb(guint8 status, const guint8 *pdu, guint16 len,
- gpointer user_data)
-{
- struct report *report = user_data;
-
- if (status != 0) {
- error("Error reading CCC value: %s", att_ecode2str(status));
- return;
- }
-
- write_ccc(report->hog, report->hog->attrib, report->ccc_handle, report);
-}
-
static void report_reference_cb(bool success, uint8_t status,
const uint8_t *value, uint16_t length,
void *user_data)
{
struct report *report = user_data;
+ struct bt_gatt_client *client = report->hog->client;
if (!success) {
error("Read Report Reference descriptor failed: %s",
@@ -227,8 +186,10 @@ static void report_reference_cb(bool success, uint8_t status,
/* Enable notifications only for Input Reports */
if (report->type == HOG_REPORT_TYPE_INPUT)
- gatt_read_char(report->hog->attrib, report->ccc_handle,
- ccc_read_cb, report);
+ report->notifyid = bt_gatt_client_register_notify(client,
+ report->decl->value_handle,
+ report_ccc_written_cb,
+ report_value_cb, report, NULL);
}
static void external_report_reference_cb(bool success, uint8_t status,
@@ -283,9 +244,6 @@ static void discover_report_cb(uint8_t status, GSList *descs, void *user_data)
struct gatt_desc *desc = descs->data;
switch (desc->uuid16) {
- case GATT_CLIENT_CHARAC_CFG_UUID:
- report->ccc_handle = desc->handle;
- break;
case GATT_REPORT_REFERENCE:
bt_gatt_client_read_value(hog->client, desc->handle,
report_reference_cb, report, NULL);
@@ -1198,10 +1156,10 @@ bool bt_hog_attach(struct bt_hog *hog, void *gatt, void *client)
for (l = hog->reports; l; l = l->next) {
struct report *r = l->data;
-
- r->notifyid = g_attrib_register(hog->attrib,
- ATT_OP_HANDLE_NOTIFY,
+ if (r->type == HOG_REPORT_TYPE_INPUT)
+ r->notifyid = bt_gatt_client_register_notify(client,
r->decl->value_handle,
+ report_ccc_written_cb,
report_value_cb, r, NULL);
}
@@ -1227,7 +1185,8 @@ void bt_hog_detach(struct bt_hog *hog)
struct report *r = l->data;
if (r->notifyid > 0) {
- g_attrib_unregister(hog->attrib, r->notifyid);
+ bt_gatt_client_unregister_notify(hog->client,
+ r->notifyid);
r->notifyid = 0;
}
}
--
1.9.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [PATCH 07/28] android/hog: Use bt_gatt_client to write without response
2015-04-01 16:40 [PATCH 00/28] android/hog Introduce bt_gatt_client Mariusz Skamra
` (5 preceding siblings ...)
2015-04-01 16:40 ` [PATCH 06/28] android/hog: Use bt_gatt_client to register for notifications Mariusz Skamra
@ 2015-04-01 16:40 ` Mariusz Skamra
2015-04-01 16:40 ` [PATCH 08/28] android/hog: Replace gatt_write_char with bt_gatt_client_write_value Mariusz Skamra
` (20 subsequent siblings)
27 siblings, 0 replies; 41+ messages in thread
From: Mariusz Skamra @ 2015-04-01 16:40 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Mariusz Skamra
This patch replaces gatt_write_cmd with
bt_gatt_client_write_without_response.
---
android/hog.c | 23 +++++++++++++----------
1 file changed, 13 insertions(+), 10 deletions(-)
diff --git a/android/hog.c b/android/hog.c
index 3f28ecb..bcda1af 100644
--- a/android/hog.c
+++ b/android/hog.c
@@ -449,8 +449,9 @@ static void forward_report(struct uhid_event *ev, void *user_data)
gatt_write_char(hog->attrib, report->decl->value_handle,
data, size, output_written_cb, hog);
else if (report->decl->properties & GATT_CHR_PROP_WRITE_WITHOUT_RESP)
- gatt_write_cmd(hog->attrib, report->decl->value_handle,
- data, size, NULL, NULL);
+ bt_gatt_client_write_without_response(hog->client,
+ report->decl->value_handle,
+ false, data, size);
}
static void get_feature(struct uhid_event *ev, void *user_data)
@@ -816,8 +817,9 @@ static void proto_mode_read_cb(bool success, uint8_t att_ecode,
DBG("HoG is operating in Boot Procotol Mode");
- gatt_write_cmd(hog->attrib, hog->proto_mode_handle, &nval,
- sizeof(nval), NULL, NULL);
+ bt_gatt_client_write_without_response(hog->client,
+ hog->proto_mode_handle, false,
+ &nval, sizeof(nval));
} else if (value[0] == HOG_PROTO_MODE_REPORT)
DBG("HoG is operating in Report Protocol Mode");
}
@@ -1207,14 +1209,14 @@ int bt_hog_set_control_point(struct bt_hog *hog, bool suspend)
{
uint8_t value = suspend ? 0x00 : 0x01;
- if (hog->attrib == NULL)
+ if (hog->client == NULL)
return -ENOTCONN;
if (hog->ctrlpt_handle == 0)
return -ENOTSUP;
- gatt_write_cmd(hog->attrib, hog->ctrlpt_handle, &value,
- sizeof(value), NULL, NULL);
+ bt_gatt_client_write_without_response(hog->client, hog->ctrlpt_handle,
+ false, &value, sizeof(value));
return 0;
}
@@ -1227,7 +1229,7 @@ int bt_hog_send_report(struct bt_hog *hog, void *data, size_t size, int type)
if (!hog)
return -EINVAL;
- if (!hog->attrib)
+ if (!hog->client)
return -ENOTCONN;
report = find_report(hog, type, 0);
@@ -1241,8 +1243,9 @@ int bt_hog_send_report(struct bt_hog *hog, void *data, size_t size, int type)
data, size, output_written_cb, hog);
if (report->decl->properties & GATT_CHR_PROP_WRITE_WITHOUT_RESP)
- gatt_write_cmd(hog->attrib, report->decl->value_handle,
- data, size, NULL, NULL);
+ bt_gatt_client_write_without_response(hog->client,
+ report->decl->value_handle,
+ false, data, size);
for (l = hog->instances; l; l = l->next) {
struct bt_hog *instance = l->data;
--
1.9.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [PATCH 08/28] android/hog: Replace gatt_write_char with bt_gatt_client_write_value
2015-04-01 16:40 [PATCH 00/28] android/hog Introduce bt_gatt_client Mariusz Skamra
` (6 preceding siblings ...)
2015-04-01 16:40 ` [PATCH 07/28] android/hog: Use bt_gatt_client to write without response Mariusz Skamra
@ 2015-04-01 16:40 ` Mariusz Skamra
2015-04-01 16:40 ` [PATCH 09/28] android/hog: Use gatt_db to search for services and characteristics in db Mariusz Skamra
` (19 subsequent siblings)
27 siblings, 0 replies; 41+ messages in thread
From: Mariusz Skamra @ 2015-04-01 16:40 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Mariusz Skamra
---
android/hog.c | 38 ++++++++++++++++++++------------------
1 file changed, 20 insertions(+), 18 deletions(-)
diff --git a/android/hog.c b/android/hog.c
index bcda1af..85a2b6a 100644
--- a/android/hog.c
+++ b/android/hog.c
@@ -411,10 +411,9 @@ static struct report *find_report_by_rtype(struct bt_hog *hog, uint8_t rtype,
return find_report(hog, type, id);
}
-static void output_written_cb(guint8 status, const guint8 *pdu,
- guint16 plen, gpointer user_data)
+static void output_written_cb(bool success, uint8_t status, void *user_data)
{
- if (status != 0) {
+ if (!success) {
error("Write output report failed: %s", att_ecode2str(status));
return;
}
@@ -442,12 +441,14 @@ static void forward_report(struct uhid_event *ev, void *user_data)
DBG("Sending report type %d ID %d to handle 0x%X", report->type,
report->id, report->decl->value_handle);
- if (hog->attrib == NULL)
+ if (hog->client == NULL)
return;
if (report->decl->properties & GATT_CHR_PROP_WRITE)
- gatt_write_char(hog->attrib, report->decl->value_handle,
- data, size, output_written_cb, hog);
+ bt_gatt_client_write_value(hog->client,
+ report->decl->value_handle,
+ data, size, output_written_cb,
+ hog, NULL);
else if (report->decl->properties & GATT_CHR_PROP_WRITE_WITHOUT_RESP)
bt_gatt_client_write_without_response(hog->client,
report->decl->value_handle,
@@ -486,8 +487,7 @@ done:
error("bt_uhid_send: %s", strerror(-err));
}
-static void set_report_cb(guint8 status, const guint8 *pdu,
- guint16 plen, gpointer user_data)
+static void set_report_cb(bool success, uint8_t status, void *user_data)
{
struct bt_hog *hog = user_data;
struct uhid_event rsp;
@@ -500,7 +500,7 @@ static void set_report_cb(guint8 status, const guint8 *pdu,
rsp.u.set_report_reply.id = hog->setrep_id;
rsp.u.set_report_reply.err = status;
- if (status != 0)
+ if (!success)
error("Error setting Report value: %s", att_ecode2str(status));
err = bt_uhid_send(hog->uhid, &rsp);
@@ -518,7 +518,7 @@ static void set_report(struct uhid_event *ev, void *user_data)
/* uhid never sends reqs in parallel; if there's a req, it timed out */
if (hog->setrep_att) {
- g_attrib_cancel(hog->attrib, hog->setrep_att);
+ bt_gatt_client_cancel(hog->client, hog->setrep_att);
hog->setrep_att = 0;
}
@@ -541,13 +541,13 @@ static void set_report(struct uhid_event *ev, void *user_data)
DBG("Sending report type %d ID %d to handle 0x%X", report->type,
report->id, report->decl->value_handle);
- if (hog->attrib == NULL)
+ if (hog->client == NULL)
return;
- hog->setrep_att = gatt_write_char(hog->attrib,
- report->decl->value_handle,
- data, size, set_report_cb,
- hog);
+ hog->setrep_att = bt_gatt_client_write_value(hog->client,
+ report->decl->value_handle, data, size,
+ set_report_cb, hog, NULL);
+
if (!hog->setrep_att) {
err = ENOMEM;
goto fail;
@@ -556,7 +556,7 @@ static void set_report(struct uhid_event *ev, void *user_data)
return;
fail:
/* cancel the request on failure */
- set_report_cb(err, NULL, 0, hog);
+ set_report_cb(false, err, hog);
}
static void get_report_cb(bool success, uint8_t status, const uint8_t *value,
@@ -1239,8 +1239,10 @@ int bt_hog_send_report(struct bt_hog *hog, void *data, size_t size, int type)
DBG("hog: Write report, handle 0x%X", report->decl->value_handle);
if (report->decl->properties & GATT_CHR_PROP_WRITE)
- gatt_write_char(hog->attrib, report->decl->value_handle,
- data, size, output_written_cb, hog);
+ bt_gatt_client_write_value(hog->client,
+ report->decl->value_handle,
+ data, size, output_written_cb,
+ hog, NULL);
if (report->decl->properties & GATT_CHR_PROP_WRITE_WITHOUT_RESP)
bt_gatt_client_write_without_response(hog->client,
--
1.9.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [PATCH 09/28] android/hog: Use gatt_db to search for services and characteristics in db
2015-04-01 16:40 [PATCH 00/28] android/hog Introduce bt_gatt_client Mariusz Skamra
` (7 preceding siblings ...)
2015-04-01 16:40 ` [PATCH 08/28] android/hog: Replace gatt_write_char with bt_gatt_client_write_value Mariusz Skamra
@ 2015-04-01 16:40 ` Mariusz Skamra
2015-04-02 15:22 ` Szymon Janc
2015-04-01 16:40 ` [PATCH 10/28] android/hog: Add helper to create uhid device Mariusz Skamra
` (18 subsequent siblings)
27 siblings, 1 reply; 41+ messages in thread
From: Mariusz Skamra @ 2015-04-01 16:40 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Mariusz Skamra
With this patch services and characteristics are searched in previously
cached database. This required changes in declarations of callbacks.
char_discovered_cb has been rebuilt to be called everytime when some
characteristic is found. Method of discovering report and external
report has been also simplified.
Moreover this patch:
1. Separates callbacks for services discovery:
services_cb: Services which already use database cached by bt_gatt_client
primary_cb: for attrib
2. Instead of using gatt_primary to create new instance of service
service handle will be used. On attach, having service handle we can call
gatt_db_get_attribute.
---
android/hidhost.c | 2 +-
android/hog.c | 299 ++++++++++++++++++++++--------------------------------
android/hog.h | 4 +-
unit/test-hog.c | 2 +-
4 files changed, 125 insertions(+), 182 deletions(-)
diff --git a/android/hidhost.c b/android/hidhost.c
index 47e5840..8513a1d 100644
--- a/android/hidhost.c
+++ b/android/hidhost.c
@@ -864,7 +864,7 @@ static void hog_conn_cb(const bdaddr_t *addr, int err, void *attrib)
if (!dev->hog) {
/* TODO: Get device details */
dev->hog = bt_hog_new_default("bluez-input-device", dev->vendor,
- dev->product, dev->version, NULL, 0);
+ dev->product, dev->version, 0);
if (!dev->hog) {
error("HoG: unable to create session");
goto fail;
diff --git a/android/hog.c b/android/hog.c
index 85a2b6a..5b93cb5 100644
--- a/android/hog.c
+++ b/android/hog.c
@@ -86,7 +86,6 @@ struct bt_hog {
uint16_t vendor;
uint16_t product;
uint16_t version;
- struct gatt_primary *primary;
GAttrib *attrib;
GSList *reports;
struct bt_uhid *uhid;
@@ -106,6 +105,7 @@ struct bt_hog {
struct queue *bas;
GSList *instances;
struct bt_gatt_client *client;
+ struct gatt_db *db;
};
struct report {
@@ -196,71 +196,35 @@ static void external_report_reference_cb(bool success, uint8_t status,
const uint8_t *value, uint16_t length,
void *user_data);
-static void discover_external_cb(uint8_t status, GSList *descs, void *user_data)
+static void discover_external_cb(struct gatt_db_attribute *attrib,
+ void *user_data)
{
struct bt_hog *hog = user_data;
+ bt_uuid_t ext_rep_uuid;
+ const bt_uuid_t *uuid = gatt_db_attribute_get_type(attrib);
+ uint16_t handle = gatt_db_attribute_get_handle(attrib);
- if (status != 0) {
- error("Discover external descriptors failed: %s",
- att_ecode2str(status));
- return;
- }
-
- for ( ; descs; descs = descs->next) {
- struct gatt_desc *desc = descs->data;
+ bt_uuid16_create(&ext_rep_uuid, GATT_EXTERNAL_REPORT_REFERENCE);
- bt_gatt_client_read_value(hog->client, desc->handle,
+ if (!bt_uuid_cmp(&ext_rep_uuid, uuid))
+ bt_gatt_client_read_value(hog->client, handle,
external_report_reference_cb, hog, NULL);
- }
-}
-
-static void discover_external(struct bt_hog *hog, GAttrib *attrib,
- uint16_t start, uint16_t end,
- gpointer user_data)
-{
- bt_uuid_t uuid;
-
- if (start > end)
- return;
-
- bt_uuid16_create(&uuid, GATT_EXTERNAL_REPORT_REFERENCE);
-
- gatt_discover_desc(attrib, start, end, NULL, discover_external_cb,
- user_data);
}
-static void discover_report_cb(uint8_t status, GSList *descs, void *user_data)
+static void discover_report_cb(struct gatt_db_attribute *attrib,
+ void *user_data)
{
struct report *report = user_data;
struct bt_hog *hog = report->hog;
+ bt_uuid_t rep_ref_uuid;
+ const bt_uuid_t *uuid = gatt_db_attribute_get_type(attrib);
+ uint16_t handle = gatt_db_attribute_get_handle(attrib);
- if (status != 0) {
- error("Discover report descriptors failed: %s",
- att_ecode2str(status));
- return;
- }
+ bt_uuid16_create(&rep_ref_uuid, GATT_REPORT_REFERENCE);
- for ( ; descs; descs = descs->next) {
- struct gatt_desc *desc = descs->data;
-
- switch (desc->uuid16) {
- case GATT_REPORT_REFERENCE:
- bt_gatt_client_read_value(hog->client, desc->handle,
+ if (!bt_uuid_cmp(&rep_ref_uuid, uuid))
+ bt_gatt_client_read_value(hog->client, handle,
report_reference_cb, report, NULL);
- break;
- }
- }
-}
-
-static void discover_report(struct bt_hog *hog, GAttrib *attrib,
- uint16_t start, uint16_t end,
- gpointer user_data)
-{
- if (start > end)
- return;
-
- gatt_discover_desc(attrib, start, end, NULL, discover_report_cb,
- user_data);
}
static void report_read_cb(bool success, uint8_t att_ecode,
@@ -282,50 +246,37 @@ static void report_read_cb(bool success, uint8_t att_ecode,
report->len = len;
}
-static struct report *report_new(struct bt_hog *hog, struct gatt_char *chr)
+static struct report *report_new(struct bt_hog *hog, uint16_t value_handle,
+ uint8_t properties)
{
struct report *report;
report = g_new0(struct report, 1);
report->hog = hog;
- report->decl = g_memdup(chr, sizeof(*chr));
+ report->decl = new0(struct gatt_char, 1);
+ report->decl->value_handle = value_handle;
+ report->decl->properties = properties;
hog->reports = g_slist_append(hog->reports, report);
- bt_gatt_client_read_value(hog->client, chr->value_handle,
+ bt_gatt_client_read_value(hog->client, value_handle,
report_read_cb, report, NULL);
return report;
}
-static void external_service_char_cb(uint8_t status, GSList *chars,
- void *user_data)
+static void external_service_char_cb(void *data, void *user_data)
{
struct bt_hog *hog = user_data;
- struct gatt_primary *primary = hog->primary;
+ struct gatt_db_attribute *attrib = data;
struct report *report;
- GSList *l;
+ uint16_t value_handle;
+ uint8_t properties;
- if (status != 0) {
- const char *str = att_ecode2str(status);
- DBG("Discover external service characteristic failed: %s", str);
- return;
- }
-
- for (l = chars; l; l = g_slist_next(l)) {
- struct gatt_char *chr, *next;
- uint16_t start, end;
-
- chr = l->data;
- next = l->next ? l->next->data : NULL;
-
- DBG("0x%04x UUID: %s properties: %02x",
- chr->handle, chr->uuid, chr->properties);
+ gatt_db_attribute_get_char_data(attrib, NULL, &value_handle,
+ &properties, NULL);
- report = report_new(hog, chr);
- start = chr->value_handle + 1;
- end = (next ? next->handle - 1 : primary->range.end);
- discover_report(hog, hog->attrib, start, end, report);
- }
+ report = report_new(hog, value_handle, properties);
+ gatt_db_service_foreach_desc(attrib, discover_report_cb, report);
}
static void external_report_reference_cb(bool success, uint8_t status,
@@ -335,6 +286,7 @@ static void external_report_reference_cb(bool success, uint8_t status,
struct bt_hog *hog = user_data;
uint16_t uuid16;
bt_uuid_t uuid;
+ struct queue *chrs;
if (!success) {
error("Read External Report Reference descriptor failed: %s",
@@ -355,9 +307,19 @@ static void external_report_reference_cb(bool success, uint8_t status,
if (uuid16 != HOG_REPORT_UUID)
return;
+ chrs = queue_new();
+ if (!chrs) {
+ error("Insufficient resources");
+ return;
+ }
+
bt_uuid16_create(&uuid, uuid16);
- gatt_discover_char(hog->attrib, 0x0001, 0xffff, &uuid,
- external_service_char_cb, hog);
+ gatt_db_read_by_type(hog->db, 0x0001, 0xffff, uuid, chrs);
+
+ if (queue_isempty(chrs))
+ return;
+
+ queue_foreach(chrs, external_service_char_cb, hog);
}
static int report_cmp(gconstpointer a, gconstpointer b)
@@ -824,21 +786,15 @@ static void proto_mode_read_cb(bool success, uint8_t att_ecode,
DBG("HoG is operating in Report Protocol Mode");
}
-static void char_discovered_cb(uint8_t status, GSList *chars, void *user_data)
+static void char_discovered_cb(struct gatt_db_attribute *attrib,
+ void *user_data)
{
struct bt_hog *hog = user_data;
- struct gatt_primary *primary = hog->primary;
- bt_uuid_t report_uuid, report_map_uuid, info_uuid;
- bt_uuid_t proto_mode_uuid, ctrlpt_uuid;
+ bt_uuid_t report_uuid, report_map_uuid, proto_mode_uuid, ctrlpt_uuid;
+ bt_uuid_t info_uuid, uuid;
struct report *report;
- GSList *l;
- uint16_t info_handle = 0, proto_mode_handle = 0;
-
- if (status != 0) {
- const char *str = att_ecode2str(status);
- DBG("Discover all characteristics failed: %s", str);
- return;
- }
+ uint16_t value_handle;
+ uint8_t properties;
bt_uuid16_create(&report_uuid, HOG_REPORT_UUID);
bt_uuid16_create(&report_map_uuid, HOG_REPORT_MAP_UUID);
@@ -846,47 +802,27 @@ static void char_discovered_cb(uint8_t status, GSList *chars, void *user_data)
bt_uuid16_create(&proto_mode_uuid, HOG_PROTO_MODE_UUID);
bt_uuid16_create(&ctrlpt_uuid, HOG_CONTROL_POINT_UUID);
- for (l = chars; l; l = g_slist_next(l)) {
- struct gatt_char *chr, *next;
- bt_uuid_t uuid;
- uint16_t start, end;
-
- chr = l->data;
- next = l->next ? l->next->data : NULL;
-
- DBG("0x%04x UUID: %s properties: %02x",
- chr->handle, chr->uuid, chr->properties);
-
- bt_string_to_uuid(&uuid, chr->uuid);
-
- start = chr->value_handle + 1;
- end = (next ? next->handle - 1 : primary->range.end);
-
- if (bt_uuid_cmp(&uuid, &report_uuid) == 0) {
- report = report_new(hog, chr);
- discover_report(hog, hog->attrib, start, end, report);
- } else if (bt_uuid_cmp(&uuid, &report_map_uuid) == 0) {
- bt_gatt_client_read_long_value(hog->client,
- chr->value_handle, 0, report_map_read_cb,
- hog, NULL);
- discover_external(hog, hog->attrib, start, end, hog);
- } else if (bt_uuid_cmp(&uuid, &info_uuid) == 0)
- info_handle = chr->value_handle;
- else if (bt_uuid_cmp(&uuid, &proto_mode_uuid) == 0)
- proto_mode_handle = chr->value_handle;
- else if (bt_uuid_cmp(&uuid, &ctrlpt_uuid) == 0)
- hog->ctrlpt_handle = chr->value_handle;
- }
-
- if (proto_mode_handle) {
- hog->proto_mode_handle = proto_mode_handle;
- bt_gatt_client_read_value(hog->client, proto_mode_handle,
+ gatt_db_attribute_get_char_data(attrib, NULL, &value_handle,
+ &properties, &uuid);
+
+ if (!bt_uuid_cmp(&uuid, &report_uuid)) {
+ report = report_new(hog, value_handle, properties);
+ gatt_db_service_foreach_desc(attrib, discover_report_cb,
+ report);
+ } else if (!bt_uuid_cmp(&uuid, &report_map_uuid)) {
+ bt_gatt_client_read_long_value(hog->client, value_handle, 0,
+ report_map_read_cb, hog, NULL);
+ gatt_db_service_foreach_desc(attrib, discover_external_cb, hog);
+ } else if (!bt_uuid_cmp(&uuid, &info_uuid)) {
+ bt_gatt_client_read_value(hog->client, value_handle,
+ info_read_cb, hog, NULL);
+ } else if (!bt_uuid_cmp(&uuid, &proto_mode_uuid)) {
+ hog->proto_mode_handle = value_handle;
+ bt_gatt_client_read_value(hog->client, value_handle,
proto_mode_read_cb, hog, NULL);
+ } else if (!bt_uuid_cmp(&uuid, &ctrlpt_uuid)) {
+ hog->ctrlpt_handle = value_handle;
}
-
- if (info_handle)
- bt_gatt_client_read_value(hog->client, info_handle,
- info_read_cb, hog, NULL);
}
static void report_free(void *data)
@@ -894,7 +830,7 @@ static void report_free(void *data)
struct report *report = data;
g_free(report->value);
- g_free(report->decl);
+ free(report->decl);
g_free(report);
}
@@ -912,21 +848,19 @@ static void hog_free(void *data)
bt_uhid_unref(hog->uhid);
g_slist_free_full(hog->reports, report_free);
g_free(hog->name);
- g_free(hog->primary);
g_free(hog);
}
struct bt_hog *bt_hog_new_default(const char *name, uint16_t vendor,
uint16_t product, uint16_t version,
- void *primary, uint16_t service_handle)
+ uint16_t service_handle)
{
- return bt_hog_new(-1, name, vendor, product, version, primary,
- service_handle);
+ return bt_hog_new(-1, name, vendor, product, version, service_handle);
}
struct bt_hog *bt_hog_new(int fd, const char *name, uint16_t vendor,
uint16_t product, uint16_t version,
- void *primary, uint16_t service_handle)
+ uint16_t service_handle)
{
struct bt_hog *hog;
@@ -953,9 +887,6 @@ struct bt_hog *bt_hog_new(int fd, const char *name, uint16_t vendor,
hog->product = product;
hog->version = version;
- if (primary)
- hog->primary = g_memdup(primary, sizeof(*hog->primary));
-
if (service_handle)
hog->service_handle = service_handle;
@@ -983,24 +914,13 @@ void bt_hog_unref(struct bt_hog *hog)
hog_free(hog);
}
-static void find_included_cb(uint8_t status, GSList *services, void *user_data)
+static void find_included_cb(struct gatt_db_attribute *attrib, void *user_data)
{
- GSList *l;
-
- DBG("");
-
- if (status) {
- const char *str = att_ecode2str(status);
- DBG("Find included failed: %s", str);
- return;
- }
+ uint16_t start_handle;
- for (l = services; l; l = l->next) {
- struct gatt_included *include = l->data;
+ gatt_db_attribute_get_incl_data(attrib, NULL, &start_handle, NULL);
- DBG("included: handle %x, uuid %s",
- include->handle, include->uuid);
- }
+ DBG("included: handle %x", start_handle);
}
static void hog_attach_scpp(struct bt_hog *hog, struct gatt_primary *primary)
@@ -1051,28 +971,25 @@ static void hog_attach_bas(struct bt_hog *hog, struct gatt_primary *primary)
queue_push_head(hog->bas, instance);
}
-static void hog_attach_hog(struct bt_hog *hog, struct gatt_primary *primary)
+static void hog_attach_hog(struct bt_hog *hog, uint16_t service_handle)
{
struct bt_hog *instance;
+ struct gatt_db_attribute *attrib;
+
+ attrib = gatt_db_get_attribute(hog->db, service_handle);
- if (!hog->primary) {
- hog->primary = g_memdup(primary, sizeof(*primary));
- gatt_discover_char(hog->attrib, primary->range.start,
- primary->range.end, NULL,
- char_discovered_cb, hog);
- gatt_find_included(hog->attrib, primary->range.start,
- primary->range.end, find_included_cb, hog);
+ if (!hog->service_handle) {
+ hog->service_handle = service_handle;
+ gatt_db_service_foreach_char(attrib, char_discovered_cb, hog);
+ gatt_db_service_foreach_incl(attrib, find_included_cb, hog);
return;
}
instance = bt_hog_new(hog->uhid_fd, hog->name, hog->vendor,
- hog->product, hog->version, primary, 0);
+ hog->product, hog->version, service_handle);
if (!instance)
return;
- gatt_find_included(hog->attrib, primary->range.start,
- primary->range.end, find_included_cb, instance);
-
bt_hog_attach(instance, hog->attrib, hog->client);
hog->instances = g_slist_append(hog->instances, instance);
}
@@ -1111,17 +1028,38 @@ static void primary_cb(uint8_t status, GSList *services, void *user_data)
if (strcmp(primary->uuid, BATTERY_UUID) == 0) {
hog_attach_bas(hog, primary);
- continue;
}
-
- if (strcmp(primary->uuid, HOG_UUID) == 0)
- hog_attach_hog(hog, primary);
}
}
+static void service_cb(struct gatt_db_attribute *attrib, void *user_data)
+{
+ struct bt_hog *hog = user_data;
+ bt_uuid_t service_uuid;
+ char uuid[MAX_LEN_UUID_STR + 1];
+ uint16_t service_handle;
+
+ if (!gatt_db_attribute_get_service_data(attrib, &service_handle,
+ NULL, NULL, &service_uuid))
+ return;
+
+ bt_uuid_to_string(&service_uuid, uuid, sizeof(uuid));
+
+ if (!bt_uuid_strcmp(uuid, HOG_UUID))
+ hog_attach_hog(hog, service_handle);
+ else if (!bt_uuid_strcmp(uuid, SCAN_PARAMETERS_UUID))
+ /* TODO */
+ return;
+ else if (!bt_uuid_strcmp(uuid, DEVICE_INFORMATION_UUID))
+ /* TODO */
+ return;
+ else if (!bt_uuid_strcmp(uuid, BATTERY_UUID))
+ /* TODO */
+ return;
+}
+
bool bt_hog_attach(struct bt_hog *hog, void *gatt, void *client)
{
- struct gatt_primary *primary = hog->primary;
GSList *l;
if (hog->attrib || hog->client)
@@ -1129,8 +1067,10 @@ bool bt_hog_attach(struct bt_hog *hog, void *gatt, void *client)
hog->attrib = g_attrib_ref(gatt);
hog->client = bt_gatt_client_ref(client);
+ hog->db = bt_gatt_client_get_db(hog->client);
- if (!primary) {
+ if (!hog->service_handle) {
+ gatt_db_foreach_service(hog->db, NULL, service_cb, hog);
gatt_discover_primary(hog->attrib, NULL, primary_cb, hog);
return true;
}
@@ -1150,9 +1090,11 @@ bool bt_hog_attach(struct bt_hog *hog, void *gatt, void *client)
}
if (hog->reports == NULL) {
- gatt_discover_char(hog->attrib, primary->range.start,
- primary->range.end, NULL,
- char_discovered_cb, hog);
+ struct gatt_db_attribute *service;
+
+ service = gatt_db_get_attribute(hog->db, hog->service_handle);
+ gatt_db_service_foreach_char(service, char_discovered_cb, hog);
+ gatt_db_service_foreach_incl(service, find_included_cb, hog);
return true;
}
@@ -1199,6 +1141,7 @@ void bt_hog_detach(struct bt_hog *hog)
if (hog->dis)
bt_dis_detach(hog->dis);
+ gatt_db_unref(hog->db);
bt_gatt_client_unref(hog->client);
g_attrib_unref(hog->attrib);
hog->client = NULL;
diff --git a/android/hog.h b/android/hog.h
index 61d756c..cfe6873 100644
--- a/android/hog.h
+++ b/android/hog.h
@@ -25,11 +25,11 @@ struct bt_hog;
struct bt_hog *bt_hog_new_default(const char *name, uint16_t vendor,
uint16_t product, uint16_t version,
- void *primary, uint16_t service_handle);
+ uint16_t service_handle);
struct bt_hog *bt_hog_new(int fd, const char *name, uint16_t vendor,
uint16_t product, uint16_t version,
- void *primary, uint16_t service_handle);
+ uint16_t service_handle);
struct bt_hog *bt_hog_ref(struct bt_hog *hog);
void bt_hog_unref(struct bt_hog *hog);
diff --git a/unit/test-hog.c b/unit/test-hog.c
index c7c64e4..5794c5e 100644
--- a/unit/test-hog.c
+++ b/unit/test-hog.c
@@ -196,7 +196,7 @@ static struct context *create_context(gconstpointer data)
fd = open("/dev/null", O_WRONLY | O_CLOEXEC);
g_assert(fd > 0);
- context->hog = bt_hog_new(fd, name, vendor, product, version, NULL, 0);
+ context->hog = bt_hog_new(fd, name, vendor, product, version, 0);
g_assert(context->hog);
channel = g_io_channel_unix_new(sv[1]);
--
1.9.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* Re: [PATCH 09/28] android/hog: Use gatt_db to search for services and characteristics in db
2015-04-01 16:40 ` [PATCH 09/28] android/hog: Use gatt_db to search for services and characteristics in db Mariusz Skamra
@ 2015-04-02 15:22 ` Szymon Janc
0 siblings, 0 replies; 41+ messages in thread
From: Szymon Janc @ 2015-04-02 15:22 UTC (permalink / raw)
To: Mariusz Skamra; +Cc: linux-bluetooth
Hi Mariusz,
On Wednesday 01 of April 2015 18:40:25 Mariusz Skamra wrote:
> With this patch services and characteristics are searched in previously
> cached database. This required changes in declarations of callbacks.
> char_discovered_cb has been rebuilt to be called everytime when some
> characteristic is found. Method of discovering report and external
> report has been also simplified.
>
> Moreover this patch:
>
> 1. Separates callbacks for services discovery:
> services_cb: Services which already use database cached by bt_gatt_client
> primary_cb: for attrib
>
> 2. Instead of using gatt_primary to create new instance of service
> service handle will be used. On attach, having service handle we can call
> gatt_db_get_attribute.
> ---
> android/hidhost.c | 2 +-
> android/hog.c | 299
> ++++++++++++++++++++++-------------------------------- android/hog.h |
> 4 +-
> unit/test-hog.c | 2 +-
> 4 files changed, 125 insertions(+), 182 deletions(-)
>
> diff --git a/android/hidhost.c b/android/hidhost.c
> index 47e5840..8513a1d 100644
> --- a/android/hidhost.c
> +++ b/android/hidhost.c
> @@ -864,7 +864,7 @@ static void hog_conn_cb(const bdaddr_t *addr, int err,
> void *attrib) if (!dev->hog) {
> /* TODO: Get device details */
> dev->hog = bt_hog_new_default("bluez-input-device", dev->vendor,
> - dev->product, dev->version, NULL, 0);
> + dev->product, dev->version, 0);
> if (!dev->hog) {
> error("HoG: unable to create session");
> goto fail;
> diff --git a/android/hog.c b/android/hog.c
> index 85a2b6a..5b93cb5 100644
> --- a/android/hog.c
> +++ b/android/hog.c
> @@ -86,7 +86,6 @@ struct bt_hog {
> uint16_t vendor;
> uint16_t product;
> uint16_t version;
> - struct gatt_primary *primary;
> GAttrib *attrib;
> GSList *reports;
> struct bt_uhid *uhid;
> @@ -106,6 +105,7 @@ struct bt_hog {
> struct queue *bas;
> GSList *instances;
> struct bt_gatt_client *client;
> + struct gatt_db *db;
> };
>
> struct report {
> @@ -196,71 +196,35 @@ static void external_report_reference_cb(bool success,
> uint8_t status, const uint8_t *value, uint16_t length,
> void *user_data);
>
> -static void discover_external_cb(uint8_t status, GSList *descs, void
> *user_data) +static void discover_external_cb(struct gatt_db_attribute
> *attrib, + void *user_data)
> {
> struct bt_hog *hog = user_data;
> + bt_uuid_t ext_rep_uuid;
> + const bt_uuid_t *uuid = gatt_db_attribute_get_type(attrib);
> + uint16_t handle = gatt_db_attribute_get_handle(attrib);
>
> - if (status != 0) {
> - error("Discover external descriptors failed: %s",
> - att_ecode2str(status));
> - return;
> - }
> -
> - for ( ; descs; descs = descs->next) {
> - struct gatt_desc *desc = descs->data;
> + bt_uuid16_create(&ext_rep_uuid, GATT_EXTERNAL_REPORT_REFERENCE);
>
> - bt_gatt_client_read_value(hog->client, desc->handle,
> + if (!bt_uuid_cmp(&ext_rep_uuid, uuid))
> + bt_gatt_client_read_value(hog->client, handle,
> external_report_reference_cb, hog, NULL);
> - }
> -}
> -
> -static void discover_external(struct bt_hog *hog, GAttrib *attrib,
> - uint16_t start, uint16_t end,
> - gpointer user_data)
> -{
> - bt_uuid_t uuid;
> -
> - if (start > end)
> - return;
> -
> - bt_uuid16_create(&uuid, GATT_EXTERNAL_REPORT_REFERENCE);
> -
> - gatt_discover_desc(attrib, start, end, NULL, discover_external_cb,
> - user_data);
> }
>
> -static void discover_report_cb(uint8_t status, GSList *descs, void
> *user_data) +static void discover_report_cb(struct gatt_db_attribute
> *attrib,
> + void *user_data)
> {
> struct report *report = user_data;
> struct bt_hog *hog = report->hog;
> + bt_uuid_t rep_ref_uuid;
> + const bt_uuid_t *uuid = gatt_db_attribute_get_type(attrib);
> + uint16_t handle = gatt_db_attribute_get_handle(attrib);
>
> - if (status != 0) {
> - error("Discover report descriptors failed: %s",
> - att_ecode2str(status));
> - return;
> - }
> + bt_uuid16_create(&rep_ref_uuid, GATT_REPORT_REFERENCE);
>
> - for ( ; descs; descs = descs->next) {
> - struct gatt_desc *desc = descs->data;
> -
> - switch (desc->uuid16) {
> - case GATT_REPORT_REFERENCE:
> - bt_gatt_client_read_value(hog->client, desc->handle,
> + if (!bt_uuid_cmp(&rep_ref_uuid, uuid))
> + bt_gatt_client_read_value(hog->client, handle,
> report_reference_cb, report, NULL);
> - break;
> - }
> - }
> -}
> -
> -static void discover_report(struct bt_hog *hog, GAttrib *attrib,
> - uint16_t start, uint16_t end,
> - gpointer user_data)
> -{
> - if (start > end)
> - return;
> -
> - gatt_discover_desc(attrib, start, end, NULL, discover_report_cb,
> - user_data);
> }
>
> static void report_read_cb(bool success, uint8_t att_ecode,
> @@ -282,50 +246,37 @@ static void report_read_cb(bool success, uint8_t
> att_ecode, report->len = len;
> }
>
> -static struct report *report_new(struct bt_hog *hog, struct gatt_char *chr)
> +static struct report *report_new(struct bt_hog *hog, uint16_t
> value_handle, + uint8_t properties)
> {
> struct report *report;
>
> report = g_new0(struct report, 1);
> report->hog = hog;
> - report->decl = g_memdup(chr, sizeof(*chr));
> + report->decl = new0(struct gatt_char, 1);
> + report->decl->value_handle = value_handle;
> + report->decl->properties = properties;
> hog->reports = g_slist_append(hog->reports, report);
>
> - bt_gatt_client_read_value(hog->client, chr->value_handle,
> + bt_gatt_client_read_value(hog->client, value_handle,
> report_read_cb, report, NULL);
>
> return report;
> }
>
> -static void external_service_char_cb(uint8_t status, GSList *chars,
> - void *user_data)
> +static void external_service_char_cb(void *data, void *user_data)
> {
> struct bt_hog *hog = user_data;
> - struct gatt_primary *primary = hog->primary;
> + struct gatt_db_attribute *attrib = data;
> struct report *report;
> - GSList *l;
> + uint16_t value_handle;
> + uint8_t properties;
>
> - if (status != 0) {
> - const char *str = att_ecode2str(status);
> - DBG("Discover external service characteristic failed: %s", str);
> - return;
> - }
> -
> - for (l = chars; l; l = g_slist_next(l)) {
> - struct gatt_char *chr, *next;
> - uint16_t start, end;
> -
> - chr = l->data;
> - next = l->next ? l->next->data : NULL;
> -
> - DBG("0x%04x UUID: %s properties: %02x",
> - chr->handle, chr->uuid, chr->properties);
> + gatt_db_attribute_get_char_data(attrib, NULL, &value_handle,
> + &properties, NULL);
>
> - report = report_new(hog, chr);
> - start = chr->value_handle + 1;
> - end = (next ? next->handle - 1 : primary->range.end);
> - discover_report(hog, hog->attrib, start, end, report);
> - }
> + report = report_new(hog, value_handle, properties);
> + gatt_db_service_foreach_desc(attrib, discover_report_cb, report);
> }
>
> static void external_report_reference_cb(bool success, uint8_t status,
> @@ -335,6 +286,7 @@ static void external_report_reference_cb(bool success,
> uint8_t status, struct bt_hog *hog = user_data;
> uint16_t uuid16;
> bt_uuid_t uuid;
> + struct queue *chrs;
>
> if (!success) {
> error("Read External Report Reference descriptor failed: %s",
> @@ -355,9 +307,19 @@ static void external_report_reference_cb(bool success,
> uint8_t status, if (uuid16 != HOG_REPORT_UUID)
> return;
>
> + chrs = queue_new();
> + if (!chrs) {
> + error("Insufficient resources");
> + return;
> + }
> +
> bt_uuid16_create(&uuid, uuid16);
> - gatt_discover_char(hog->attrib, 0x0001, 0xffff, &uuid,
> - external_service_char_cb, hog);
> + gatt_db_read_by_type(hog->db, 0x0001, 0xffff, uuid, chrs);
> +
> + if (queue_isempty(chrs))
> + return;
> +
> + queue_foreach(chrs, external_service_char_cb, hog);
Shouldn't chrs queue be destroyed before returning from function?
> }
>
> static int report_cmp(gconstpointer a, gconstpointer b)
> @@ -824,21 +786,15 @@ static void proto_mode_read_cb(bool success, uint8_t
> att_ecode, DBG("HoG is operating in Report Protocol Mode");
> }
>
> -static void char_discovered_cb(uint8_t status, GSList *chars, void
> *user_data) +static void char_discovered_cb(struct gatt_db_attribute
> *attrib,
> + void *user_data)
> {
> struct bt_hog *hog = user_data;
> - struct gatt_primary *primary = hog->primary;
> - bt_uuid_t report_uuid, report_map_uuid, info_uuid;
> - bt_uuid_t proto_mode_uuid, ctrlpt_uuid;
> + bt_uuid_t report_uuid, report_map_uuid, proto_mode_uuid, ctrlpt_uuid;
> + bt_uuid_t info_uuid, uuid;
> struct report *report;
> - GSList *l;
> - uint16_t info_handle = 0, proto_mode_handle = 0;
> -
> - if (status != 0) {
> - const char *str = att_ecode2str(status);
> - DBG("Discover all characteristics failed: %s", str);
> - return;
> - }
> + uint16_t value_handle;
> + uint8_t properties;
>
> bt_uuid16_create(&report_uuid, HOG_REPORT_UUID);
> bt_uuid16_create(&report_map_uuid, HOG_REPORT_MAP_UUID);
> @@ -846,47 +802,27 @@ static void char_discovered_cb(uint8_t status, GSList
> *chars, void *user_data) bt_uuid16_create(&proto_mode_uuid,
> HOG_PROTO_MODE_UUID);
> bt_uuid16_create(&ctrlpt_uuid, HOG_CONTROL_POINT_UUID);
>
> - for (l = chars; l; l = g_slist_next(l)) {
> - struct gatt_char *chr, *next;
> - bt_uuid_t uuid;
> - uint16_t start, end;
> -
> - chr = l->data;
> - next = l->next ? l->next->data : NULL;
> -
> - DBG("0x%04x UUID: %s properties: %02x",
> - chr->handle, chr->uuid, chr->properties);
> -
> - bt_string_to_uuid(&uuid, chr->uuid);
> -
> - start = chr->value_handle + 1;
> - end = (next ? next->handle - 1 : primary->range.end);
> -
> - if (bt_uuid_cmp(&uuid, &report_uuid) == 0) {
> - report = report_new(hog, chr);
> - discover_report(hog, hog->attrib, start, end, report);
> - } else if (bt_uuid_cmp(&uuid, &report_map_uuid) == 0) {
> - bt_gatt_client_read_long_value(hog->client,
> - chr->value_handle, 0, report_map_read_cb,
> - hog, NULL);
> - discover_external(hog, hog->attrib, start, end, hog);
> - } else if (bt_uuid_cmp(&uuid, &info_uuid) == 0)
> - info_handle = chr->value_handle;
> - else if (bt_uuid_cmp(&uuid, &proto_mode_uuid) == 0)
> - proto_mode_handle = chr->value_handle;
> - else if (bt_uuid_cmp(&uuid, &ctrlpt_uuid) == 0)
> - hog->ctrlpt_handle = chr->value_handle;
> - }
> -
> - if (proto_mode_handle) {
> - hog->proto_mode_handle = proto_mode_handle;
> - bt_gatt_client_read_value(hog->client, proto_mode_handle,
> + gatt_db_attribute_get_char_data(attrib, NULL, &value_handle,
> + &properties, &uuid);
> +
> + if (!bt_uuid_cmp(&uuid, &report_uuid)) {
> + report = report_new(hog, value_handle, properties);
> + gatt_db_service_foreach_desc(attrib, discover_report_cb,
> + report);
> + } else if (!bt_uuid_cmp(&uuid, &report_map_uuid)) {
> + bt_gatt_client_read_long_value(hog->client, value_handle, 0,
> + report_map_read_cb, hog, NULL);
> + gatt_db_service_foreach_desc(attrib, discover_external_cb, hog);
> + } else if (!bt_uuid_cmp(&uuid, &info_uuid)) {
> + bt_gatt_client_read_value(hog->client, value_handle,
> + info_read_cb, hog, NULL);
> + } else if (!bt_uuid_cmp(&uuid, &proto_mode_uuid)) {
> + hog->proto_mode_handle = value_handle;
> + bt_gatt_client_read_value(hog->client, value_handle,
> proto_mode_read_cb, hog, NULL);
> + } else if (!bt_uuid_cmp(&uuid, &ctrlpt_uuid)) {
> + hog->ctrlpt_handle = value_handle;
> }
> -
> - if (info_handle)
> - bt_gatt_client_read_value(hog->client, info_handle,
> - info_read_cb, hog, NULL);
> }
>
> static void report_free(void *data)
> @@ -894,7 +830,7 @@ static void report_free(void *data)
> struct report *report = data;
>
> g_free(report->value);
> - g_free(report->decl);
> + free(report->decl);
> g_free(report);
> }
>
> @@ -912,21 +848,19 @@ static void hog_free(void *data)
> bt_uhid_unref(hog->uhid);
> g_slist_free_full(hog->reports, report_free);
> g_free(hog->name);
> - g_free(hog->primary);
> g_free(hog);
> }
>
> struct bt_hog *bt_hog_new_default(const char *name, uint16_t vendor,
> uint16_t product, uint16_t version,
> - void *primary, uint16_t service_handle)
> + uint16_t service_handle)
> {
> - return bt_hog_new(-1, name, vendor, product, version, primary,
> - service_handle);
> + return bt_hog_new(-1, name, vendor, product, version, service_handle);
> }
>
> struct bt_hog *bt_hog_new(int fd, const char *name, uint16_t vendor,
> uint16_t product, uint16_t version,
> - void *primary, uint16_t service_handle)
> + uint16_t service_handle)
> {
> struct bt_hog *hog;
>
> @@ -953,9 +887,6 @@ struct bt_hog *bt_hog_new(int fd, const char *name,
> uint16_t vendor, hog->product = product;
> hog->version = version;
>
> - if (primary)
> - hog->primary = g_memdup(primary, sizeof(*hog->primary));
> -
> if (service_handle)
> hog->service_handle = service_handle;
>
> @@ -983,24 +914,13 @@ void bt_hog_unref(struct bt_hog *hog)
> hog_free(hog);
> }
>
> -static void find_included_cb(uint8_t status, GSList *services, void
> *user_data) +static void find_included_cb(struct gatt_db_attribute *attrib,
> void *user_data) {
> - GSList *l;
> -
> - DBG("");
> -
> - if (status) {
> - const char *str = att_ecode2str(status);
> - DBG("Find included failed: %s", str);
> - return;
> - }
> + uint16_t start_handle;
>
> - for (l = services; l; l = l->next) {
> - struct gatt_included *include = l->data;
> + gatt_db_attribute_get_incl_data(attrib, NULL, &start_handle, NULL);
>
> - DBG("included: handle %x, uuid %s",
> - include->handle, include->uuid);
> - }
> + DBG("included: handle %x", start_handle);
> }
>
> static void hog_attach_scpp(struct bt_hog *hog, struct gatt_primary
> *primary) @@ -1051,28 +971,25 @@ static void hog_attach_bas(struct bt_hog
> *hog, struct gatt_primary *primary) queue_push_head(hog->bas, instance);
> }
>
> -static void hog_attach_hog(struct bt_hog *hog, struct gatt_primary
> *primary) +static void hog_attach_hog(struct bt_hog *hog, uint16_t
> service_handle) {
> struct bt_hog *instance;
> + struct gatt_db_attribute *attrib;
> +
> + attrib = gatt_db_get_attribute(hog->db, service_handle);
>
> - if (!hog->primary) {
> - hog->primary = g_memdup(primary, sizeof(*primary));
> - gatt_discover_char(hog->attrib, primary->range.start,
> - primary->range.end, NULL,
> - char_discovered_cb, hog);
> - gatt_find_included(hog->attrib, primary->range.start,
> - primary->range.end, find_included_cb, hog);
> + if (!hog->service_handle) {
> + hog->service_handle = service_handle;
> + gatt_db_service_foreach_char(attrib, char_discovered_cb, hog);
> + gatt_db_service_foreach_incl(attrib, find_included_cb, hog);
> return;
> }
>
> instance = bt_hog_new(hog->uhid_fd, hog->name, hog->vendor,
> - hog->product, hog->version, primary, 0);
> + hog->product, hog->version, service_handle);
> if (!instance)
> return;
>
> - gatt_find_included(hog->attrib, primary->range.start,
> - primary->range.end, find_included_cb, instance);
> -
> bt_hog_attach(instance, hog->attrib, hog->client);
> hog->instances = g_slist_append(hog->instances, instance);
> }
> @@ -1111,17 +1028,38 @@ static void primary_cb(uint8_t status, GSList
> *services, void *user_data)
>
> if (strcmp(primary->uuid, BATTERY_UUID) == 0) {
> hog_attach_bas(hog, primary);
> - continue;
> }
> -
> - if (strcmp(primary->uuid, HOG_UUID) == 0)
> - hog_attach_hog(hog, primary);
> }
> }
>
> +static void service_cb(struct gatt_db_attribute *attrib, void *user_data)
> +{
> + struct bt_hog *hog = user_data;
> + bt_uuid_t service_uuid;
> + char uuid[MAX_LEN_UUID_STR + 1];
> + uint16_t service_handle;
> +
> + if (!gatt_db_attribute_get_service_data(attrib, &service_handle,
> + NULL, NULL, &service_uuid))
> + return;
> +
> + bt_uuid_to_string(&service_uuid, uuid, sizeof(uuid));
> +
> + if (!bt_uuid_strcmp(uuid, HOG_UUID))
> + hog_attach_hog(hog, service_handle);
> + else if (!bt_uuid_strcmp(uuid, SCAN_PARAMETERS_UUID))
> + /* TODO */
> + return;
> + else if (!bt_uuid_strcmp(uuid, DEVICE_INFORMATION_UUID))
> + /* TODO */
> + return;
> + else if (!bt_uuid_strcmp(uuid, BATTERY_UUID))
> + /* TODO */
> + return;
> +}
> +
> bool bt_hog_attach(struct bt_hog *hog, void *gatt, void *client)
> {
> - struct gatt_primary *primary = hog->primary;
> GSList *l;
>
> if (hog->attrib || hog->client)
> @@ -1129,8 +1067,10 @@ bool bt_hog_attach(struct bt_hog *hog, void *gatt,
> void *client)
>
> hog->attrib = g_attrib_ref(gatt);
> hog->client = bt_gatt_client_ref(client);
> + hog->db = bt_gatt_client_get_db(hog->client);
>
> - if (!primary) {
> + if (!hog->service_handle) {
> + gatt_db_foreach_service(hog->db, NULL, service_cb, hog);
> gatt_discover_primary(hog->attrib, NULL, primary_cb, hog);
> return true;
> }
> @@ -1150,9 +1090,11 @@ bool bt_hog_attach(struct bt_hog *hog, void *gatt,
> void *client) }
>
> if (hog->reports == NULL) {
> - gatt_discover_char(hog->attrib, primary->range.start,
> - primary->range.end, NULL,
> - char_discovered_cb, hog);
> + struct gatt_db_attribute *service;
> +
> + service = gatt_db_get_attribute(hog->db, hog->service_handle);
> + gatt_db_service_foreach_char(service, char_discovered_cb, hog);
> + gatt_db_service_foreach_incl(service, find_included_cb, hog);
> return true;
> }
>
> @@ -1199,6 +1141,7 @@ void bt_hog_detach(struct bt_hog *hog)
> if (hog->dis)
> bt_dis_detach(hog->dis);
>
> + gatt_db_unref(hog->db);
> bt_gatt_client_unref(hog->client);
> g_attrib_unref(hog->attrib);
> hog->client = NULL;
> diff --git a/android/hog.h b/android/hog.h
> index 61d756c..cfe6873 100644
> --- a/android/hog.h
> +++ b/android/hog.h
> @@ -25,11 +25,11 @@ struct bt_hog;
>
> struct bt_hog *bt_hog_new_default(const char *name, uint16_t vendor,
> uint16_t product, uint16_t version,
> - void *primary, uint16_t service_handle);
> + uint16_t service_handle);
>
> struct bt_hog *bt_hog_new(int fd, const char *name, uint16_t vendor,
> uint16_t product, uint16_t version,
> - void *primary, uint16_t service_handle);
> + uint16_t service_handle);
>
> struct bt_hog *bt_hog_ref(struct bt_hog *hog);
> void bt_hog_unref(struct bt_hog *hog);
> diff --git a/unit/test-hog.c b/unit/test-hog.c
> index c7c64e4..5794c5e 100644
> --- a/unit/test-hog.c
> +++ b/unit/test-hog.c
> @@ -196,7 +196,7 @@ static struct context *create_context(gconstpointer
> data) fd = open("/dev/null", O_WRONLY | O_CLOEXEC);
> g_assert(fd > 0);
>
> - context->hog = bt_hog_new(fd, name, vendor, product, version, NULL, 0);
> + context->hog = bt_hog_new(fd, name, vendor, product, version, 0);
> g_assert(context->hog);
>
> channel = g_io_channel_unix_new(sv[1]);
--
BR
Szymon Janc
^ permalink raw reply [flat|nested] 41+ messages in thread
* [PATCH 10/28] android/hog: Add helper to create uhid device
2015-04-01 16:40 [PATCH 00/28] android/hog Introduce bt_gatt_client Mariusz Skamra
` (8 preceding siblings ...)
2015-04-01 16:40 ` [PATCH 09/28] android/hog: Use gatt_db to search for services and characteristics in db Mariusz Skamra
@ 2015-04-01 16:40 ` Mariusz Skamra
2015-04-01 16:40 ` [PATCH 11/28] lib/uuid: Add define for HoG UUID Mariusz Skamra
` (17 subsequent siblings)
27 siblings, 0 replies; 41+ messages in thread
From: Mariusz Skamra @ 2015-04-01 16:40 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Mariusz Skamra
This patch moves the code responsible for creation of uhid device
into separate function. This improves code readability.
---
android/hog.c | 82 ++++++++++++++++++++++++++++++++++-------------------------
1 file changed, 47 insertions(+), 35 deletions(-)
diff --git a/android/hog.c b/android/hog.c
index 5b93cb5..ac8c819 100644
--- a/android/hog.c
+++ b/android/hog.c
@@ -666,15 +666,57 @@ static char *item2string(char *str, const uint8_t *buf, uint8_t len)
return str;
}
+static bool uhid_create(struct bt_hog *hog, const uint8_t *value, uint16_t vlen)
+{
+ struct uhid_event ev;
+ int err;
+ GError *gerr = NULL;
+
+ /* create uHID device */
+ memset(&ev, 0, sizeof(ev));
+ ev.type = UHID_CREATE;
+
+ bt_io_get(g_attrib_get_channel(hog->attrib), &gerr,
+ BT_IO_OPT_SOURCE, ev.u.create.phys,
+ BT_IO_OPT_DEST, ev.u.create.uniq,
+ BT_IO_OPT_INVALID);
+ if (gerr) {
+ error("Failed to connection details: %s", gerr->message);
+ g_error_free(gerr);
+ return false;
+ }
+
+ strcpy((char *) ev.u.create.name, hog->name);
+ ev.u.create.vendor = hog->vendor;
+ ev.u.create.product = hog->product;
+ ev.u.create.version = hog->version;
+ ev.u.create.country = hog->bcountrycode;
+ ev.u.create.bus = BUS_BLUETOOTH;
+ ev.u.create.rd_data = (uint8_t *) value;
+ ev.u.create.rd_size = vlen;
+
+ err = bt_uhid_send(hog->uhid, &ev);
+ if (err < 0) {
+ error("bt_uhid_send: %s", strerror(-err));
+ return false;
+ }
+
+ bt_uhid_register(hog->uhid, UHID_OUTPUT, forward_report, hog);
+ bt_uhid_register(hog->uhid, UHID_FEATURE, get_feature, hog);
+ bt_uhid_register(hog->uhid, UHID_GET_REPORT, get_report, hog);
+ bt_uhid_register(hog->uhid, UHID_SET_REPORT, set_report, hog);
+
+ return true;
+}
+
static void report_map_read_cb(bool success, uint8_t att_ecode,
const uint8_t *value, uint16_t vlen,
void *user_data)
{
struct bt_hog *hog = user_data;
- struct uhid_event ev;
+
char itemstr[20]; /* 5x3 (data) + 4 (continuation) + 1 (null) */
- int i, err;
- GError *gerr = NULL;
+ int i;
if (!success) {
error("Report Map read failed: %s", att_ecode2str(att_ecode));
@@ -704,39 +746,9 @@ static void report_map_read_cb(bool success, uint8_t att_ecode,
}
}
- /* create uHID device */
- memset(&ev, 0, sizeof(ev));
- ev.type = UHID_CREATE;
-
- bt_io_get(g_attrib_get_channel(hog->attrib), &gerr,
- BT_IO_OPT_SOURCE, ev.u.create.phys,
- BT_IO_OPT_DEST, ev.u.create.uniq,
- BT_IO_OPT_INVALID);
- if (gerr) {
- error("Failed to connection details: %s", gerr->message);
- g_error_free(gerr);
+ /* TODO Error handling */
+ if (!uhid_create(hog, value, vlen))
return;
- }
-
- strcpy((char *) ev.u.create.name, hog->name);
- ev.u.create.vendor = hog->vendor;
- ev.u.create.product = hog->product;
- ev.u.create.version = hog->version;
- ev.u.create.country = hog->bcountrycode;
- ev.u.create.bus = BUS_BLUETOOTH;
- ev.u.create.rd_data = (uint8_t *) value;
- ev.u.create.rd_size = vlen;
-
- err = bt_uhid_send(hog->uhid, &ev);
- if (err < 0) {
- error("bt_uhid_send: %s", strerror(-err));
- return;
- }
-
- bt_uhid_register(hog->uhid, UHID_OUTPUT, forward_report, hog);
- bt_uhid_register(hog->uhid, UHID_FEATURE, get_feature, hog);
- bt_uhid_register(hog->uhid, UHID_GET_REPORT, get_report, hog);
- bt_uhid_register(hog->uhid, UHID_SET_REPORT, set_report, hog);
}
static void info_read_cb(bool success, uint8_t status, const uint8_t *value,
--
1.9.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [PATCH 11/28] lib/uuid: Add define for HoG UUID
2015-04-01 16:40 [PATCH 00/28] android/hog Introduce bt_gatt_client Mariusz Skamra
` (9 preceding siblings ...)
2015-04-01 16:40 ` [PATCH 10/28] android/hog: Add helper to create uhid device Mariusz Skamra
@ 2015-04-01 16:40 ` Mariusz Skamra
2015-04-01 16:40 ` [PATCH 12/28] android/hog: Replace list of reports with a queue of reports Mariusz Skamra
` (16 subsequent siblings)
27 siblings, 0 replies; 41+ messages in thread
From: Mariusz Skamra @ 2015-04-01 16:40 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Mariusz Skamra
From: Mariusz Skamra <mariusz.skamra@gmail.com>
This patch moves the HOG_UUID define to lib/uuid.
---
android/hidhost.c | 2 --
android/hog.c | 2 --
lib/uuid.h | 1 +
3 files changed, 1 insertion(+), 4 deletions(-)
diff --git a/android/hidhost.c b/android/hidhost.c
index 8513a1d..98eceee 100644
--- a/android/hidhost.c
+++ b/android/hidhost.c
@@ -90,8 +90,6 @@
/* HID Virtual Cable Unplug */
#define HID_VIRTUAL_CABLE_UNPLUG 0x05
-#define HOG_UUID "00001812-0000-1000-8000-00805f9b34fb"
-
static bdaddr_t adapter_addr;
static GIOChannel *ctrl_io = NULL;
diff --git a/android/hog.c b/android/hog.c
index ac8c819..e3e79cb 100644
--- a/android/hog.c
+++ b/android/hog.c
@@ -61,8 +61,6 @@
#include "android/bas.h"
#include "android/hog.h"
-#define HOG_UUID "00001812-0000-1000-8000-00805f9b34fb"
-
#define HOG_INFO_UUID 0x2A4A
#define HOG_REPORT_MAP_UUID 0x2A4B
#define HOG_REPORT_UUID 0x2A4D
diff --git a/lib/uuid.h b/lib/uuid.h
index 2dcfe9e..fd67ebb 100644
--- a/lib/uuid.h
+++ b/lib/uuid.h
@@ -88,6 +88,7 @@ extern "C" {
#define HDP_SINK_UUID "00001402-0000-1000-8000-00805f9b34fb"
#define HID_UUID "00001124-0000-1000-8000-00805f9b34fb"
+#define HOG_UUID "00001812-0000-1000-8000-00805f9b34fb"
#define DUN_GW_UUID "00001103-0000-1000-8000-00805f9b34fb"
--
1.9.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [PATCH 12/28] android/hog: Replace list of reports with a queue of reports
2015-04-01 16:40 [PATCH 00/28] android/hog Introduce bt_gatt_client Mariusz Skamra
` (10 preceding siblings ...)
2015-04-01 16:40 ` [PATCH 11/28] lib/uuid: Add define for HoG UUID Mariusz Skamra
@ 2015-04-01 16:40 ` Mariusz Skamra
2015-04-01 16:40 ` [PATCH 13/28] android/hog: Replace definitions of characteristic uuids with bt_uuids Mariusz Skamra
` (15 subsequent siblings)
27 siblings, 0 replies; 41+ messages in thread
From: Mariusz Skamra @ 2015-04-01 16:40 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Mariusz Skamra
From: Mariusz Skamra <mariusz.skamra@gmail.com>
Thanks to this patch reports can be now stored in queue. This will help
to clean the code from glib dependencies.
Two helpers for enable/disable notification have been added to be used with
queue_foreach.
---
android/hog.c | 79 +++++++++++++++++++++++++++++++++--------------------------
1 file changed, 44 insertions(+), 35 deletions(-)
diff --git a/android/hog.c b/android/hog.c
index e3e79cb..08196d4 100644
--- a/android/hog.c
+++ b/android/hog.c
@@ -85,7 +85,7 @@ struct bt_hog {
uint16_t product;
uint16_t version;
GAttrib *attrib;
- GSList *reports;
+ struct queue *reports;
struct bt_uhid *uhid;
int uhid_fd;
gboolean has_report_id;
@@ -160,12 +160,35 @@ static void report_ccc_written_cb(uint16_t status, void *user_data)
DBG("Report characteristic descriptor written: notifications enabled");
}
+static void report_enable_notif(void *data, void *user_data)
+{
+ struct report *report = data;
+ struct bt_gatt_client *client = report->hog->client;
+
+ /* Enable notifications only for Input Reports */
+ if (report->type == HOG_REPORT_TYPE_INPUT)
+ report->notifyid = bt_gatt_client_register_notify(client,
+ report->decl->value_handle,
+ report_ccc_written_cb,
+ report_value_cb, report, NULL);
+}
+
+static void report_disable_notif(void *data, void *user_data)
+{
+ struct report *report = data;
+ struct bt_gatt_client *client = report->hog->client;
+
+ if (report->notifyid > 0) {
+ bt_gatt_client_unregister_notify(client, report->notifyid);
+ report->notifyid = 0;
+ }
+}
+
static void report_reference_cb(bool success, uint8_t status,
const uint8_t *value, uint16_t length,
void *user_data)
{
struct report *report = user_data;
- struct bt_gatt_client *client = report->hog->client;
if (!success) {
error("Read Report Reference descriptor failed: %s",
@@ -182,12 +205,7 @@ static void report_reference_cb(bool success, uint8_t status,
report->type = value[1];
DBG("Report ID: 0x%02x Report type: 0x%02x", value[0], value[1]);
- /* Enable notifications only for Input Reports */
- if (report->type == HOG_REPORT_TYPE_INPUT)
- report->notifyid = bt_gatt_client_register_notify(client,
- report->decl->value_handle,
- report_ccc_written_cb,
- report_value_cb, report, NULL);
+ report_enable_notif(report, NULL);
}
static void external_report_reference_cb(bool success, uint8_t status,
@@ -254,7 +272,7 @@ static struct report *report_new(struct bt_hog *hog, uint16_t value_handle,
report->decl = new0(struct gatt_char, 1);
report->decl->value_handle = value_handle;
report->decl->properties = properties;
- hog->reports = g_slist_append(hog->reports, report);
+ queue_push_tail(hog->reports, report);
bt_gatt_client_read_value(hog->client, value_handle,
report_read_cb, report, NULL);
@@ -320,10 +338,8 @@ static void external_report_reference_cb(bool success, uint8_t status,
queue_foreach(chrs, external_service_char_cb, hog);
}
-static int report_cmp(gconstpointer a, gconstpointer b)
+static int report_cmp(const struct report *ra, const struct report *rb)
{
- const struct report *ra = a, *rb = b;
-
/* sort by type first.. */
if (ra->type != rb->type)
return ra->type - rb->type;
@@ -339,14 +355,21 @@ static int report_cmp(gconstpointer a, gconstpointer b)
static struct report *find_report(struct bt_hog *hog, uint8_t type, uint8_t id)
{
struct report cmp;
- GSList *l;
+ const struct queue_entry *report_entry;
cmp.type = type;
cmp.id = hog->has_report_id ? id : 0;
- l = g_slist_find_custom(hog->reports, &cmp, report_cmp);
+ report_entry = queue_get_entries(hog->reports);
+ while (report_entry) {
+ struct report *report = report_entry->data;
+
+ if (!report_cmp(report, &cmp))
+ return report;
- return l ? l->data : NULL;
+ report_entry = report_entry->next;
+ }
+ return NULL;
}
static struct report *find_report_by_rtype(struct bt_hog *hog, uint8_t rtype,
@@ -856,7 +879,7 @@ static void hog_free(void *data)
bt_scpp_unref(hog->scpp);
bt_dis_unref(hog->dis);
bt_uhid_unref(hog->uhid);
- g_slist_free_full(hog->reports, report_free);
+ queue_destroy(hog->reports, report_free);
g_free(hog->name);
g_free(hog);
}
@@ -879,6 +902,7 @@ struct bt_hog *bt_hog_new(int fd, const char *name, uint16_t vendor,
return NULL;
hog->bas = queue_new();
+ hog->reports = queue_new();
if (fd < 0)
hog->uhid = bt_uhid_new_default();
@@ -887,7 +911,7 @@ struct bt_hog *bt_hog_new(int fd, const char *name, uint16_t vendor,
hog->uhid_fd = fd;
- if (!hog->bas || !hog->uhid) {
+ if (!hog->bas || !hog->uhid || !hog->reports) {
hog_free(hog);
return NULL;
}
@@ -1099,7 +1123,7 @@ bool bt_hog_attach(struct bt_hog *hog, void *gatt, void *client)
bt_hog_attach(instance, gatt, client);
}
- if (hog->reports == NULL) {
+ if (queue_isempty(hog->reports)) {
struct gatt_db_attribute *service;
service = gatt_db_get_attribute(hog->db, hog->service_handle);
@@ -1108,14 +1132,7 @@ bool bt_hog_attach(struct bt_hog *hog, void *gatt, void *client)
return true;
}
- for (l = hog->reports; l; l = l->next) {
- struct report *r = l->data;
- if (r->type == HOG_REPORT_TYPE_INPUT)
- r->notifyid = bt_gatt_client_register_notify(client,
- r->decl->value_handle,
- report_ccc_written_cb,
- report_value_cb, r, NULL);
- }
+ queue_foreach(hog->reports, report_enable_notif, NULL);
return true;
}
@@ -1135,15 +1152,7 @@ void bt_hog_detach(struct bt_hog *hog)
bt_hog_detach(instance);
}
- for (l = hog->reports; l; l = l->next) {
- struct report *r = l->data;
-
- if (r->notifyid > 0) {
- bt_gatt_client_unregister_notify(hog->client,
- r->notifyid);
- r->notifyid = 0;
- }
- }
+ queue_foreach(hog->reports, report_disable_notif, NULL);
if (hog->scpp)
bt_scpp_detach(hog->scpp);
--
1.9.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [PATCH 13/28] android/hog: Replace definitions of characteristic uuids with bt_uuids
2015-04-01 16:40 [PATCH 00/28] android/hog Introduce bt_gatt_client Mariusz Skamra
` (11 preceding siblings ...)
2015-04-01 16:40 ` [PATCH 12/28] android/hog: Replace list of reports with a queue of reports Mariusz Skamra
@ 2015-04-01 16:40 ` Mariusz Skamra
2015-04-02 15:26 ` Szymon Janc
2015-04-01 16:40 ` [PATCH 14/28] android/hog: Replace GSList of hog instances with queue of instances Mariusz Skamra
` (14 subsequent siblings)
27 siblings, 1 reply; 41+ messages in thread
From: Mariusz Skamra @ 2015-04-01 16:40 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Mariusz Skamra
Instead of using simply define and then convert the uuid values to
bt_uuid everytime the char_discovered_cb is called, it's better to
define these bt_uuids directly.
---
android/hog.c | 40 ++++++++++++++++++----------------------
1 file changed, 18 insertions(+), 22 deletions(-)
diff --git a/android/hog.c b/android/hog.c
index 08196d4..e1ccaf3 100644
--- a/android/hog.c
+++ b/android/hog.c
@@ -61,12 +61,6 @@
#include "android/bas.h"
#include "android/hog.h"
-#define HOG_INFO_UUID 0x2A4A
-#define HOG_REPORT_MAP_UUID 0x2A4B
-#define HOG_REPORT_UUID 0x2A4D
-#define HOG_PROTO_MODE_UUID 0x2A4E
-#define HOG_CONTROL_POINT_UUID 0x2A4C
-
#define HOG_REPORT_TYPE_INPUT 1
#define HOG_REPORT_TYPE_OUTPUT 2
#define HOG_REPORT_TYPE_FEATURE 3
@@ -77,6 +71,17 @@
#define HOG_REPORT_MAP_MAX_SIZE 512
#define HID_INFO_SIZE 4
+static const bt_uuid_t info_uuid = { .type = BT_UUID16,
+ .value.u16 = 0x2A4A };
+static const bt_uuid_t report_map_uuid = { .type = BT_UUID16,
+ .value.u16 = 0x2A4B };
+static const bt_uuid_t control_point_uuid = { .type = BT_UUID16,
+ .value.u16 = 0x2A4C };
+static const bt_uuid_t report_uuid = { .type = BT_UUID16,
+ .value.u16 = 0x2A4D };
+static const bt_uuid_t protocol_mode_uuid = { .type = BT_UUID16,
+ .value.u16 = 0x2A4E };
+
struct bt_hog {
int ref_count;
uint16_t service_handle;
@@ -300,7 +305,6 @@ static void external_report_reference_cb(bool success, uint8_t status,
void *user_data)
{
struct bt_hog *hog = user_data;
- uint16_t uuid16;
bt_uuid_t uuid;
struct queue *chrs;
@@ -315,12 +319,12 @@ static void external_report_reference_cb(bool success, uint8_t status,
return;
}
- uuid16 = get_le16(value);
- DBG("External report reference read, external report characteristic "
- "UUID: 0x%04x", uuid16);
+ DBG("External report characteristic UUID: 0x%04x", get_le16(value));
+
+ bt_uuid16_create(&uuid, get_le16(value));
/* Do not discover if is not a Report */
- if (uuid16 != HOG_REPORT_UUID)
+ if (bt_uuid_cmp(&uuid, &report_uuid))
return;
chrs = queue_new();
@@ -329,7 +333,6 @@ static void external_report_reference_cb(bool success, uint8_t status,
return;
}
- bt_uuid16_create(&uuid, uuid16);
gatt_db_read_by_type(hog->db, 0x0001, 0xffff, uuid, chrs);
if (queue_isempty(chrs))
@@ -823,18 +826,11 @@ static void char_discovered_cb(struct gatt_db_attribute *attrib,
void *user_data)
{
struct bt_hog *hog = user_data;
- bt_uuid_t report_uuid, report_map_uuid, proto_mode_uuid, ctrlpt_uuid;
- bt_uuid_t info_uuid, uuid;
+ bt_uuid_t uuid;
struct report *report;
uint16_t value_handle;
uint8_t properties;
- bt_uuid16_create(&report_uuid, HOG_REPORT_UUID);
- bt_uuid16_create(&report_map_uuid, HOG_REPORT_MAP_UUID);
- bt_uuid16_create(&info_uuid, HOG_INFO_UUID);
- bt_uuid16_create(&proto_mode_uuid, HOG_PROTO_MODE_UUID);
- bt_uuid16_create(&ctrlpt_uuid, HOG_CONTROL_POINT_UUID);
-
gatt_db_attribute_get_char_data(attrib, NULL, &value_handle,
&properties, &uuid);
@@ -849,11 +845,11 @@ static void char_discovered_cb(struct gatt_db_attribute *attrib,
} else if (!bt_uuid_cmp(&uuid, &info_uuid)) {
bt_gatt_client_read_value(hog->client, value_handle,
info_read_cb, hog, NULL);
- } else if (!bt_uuid_cmp(&uuid, &proto_mode_uuid)) {
+ } else if (!bt_uuid_cmp(&uuid, &protocol_mode_uuid)) {
hog->proto_mode_handle = value_handle;
bt_gatt_client_read_value(hog->client, value_handle,
proto_mode_read_cb, hog, NULL);
- } else if (!bt_uuid_cmp(&uuid, &ctrlpt_uuid)) {
+ } else if (!bt_uuid_cmp(&uuid, &control_point_uuid)) {
hog->ctrlpt_handle = value_handle;
}
}
--
1.9.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* Re: [PATCH 13/28] android/hog: Replace definitions of characteristic uuids with bt_uuids
2015-04-01 16:40 ` [PATCH 13/28] android/hog: Replace definitions of characteristic uuids with bt_uuids Mariusz Skamra
@ 2015-04-02 15:26 ` Szymon Janc
0 siblings, 0 replies; 41+ messages in thread
From: Szymon Janc @ 2015-04-02 15:26 UTC (permalink / raw)
To: Mariusz Skamra; +Cc: linux-bluetooth
Hi Mariusz,
On Wednesday 01 of April 2015 18:40:29 Mariusz Skamra wrote:
> Instead of using simply define and then convert the uuid values to
> bt_uuid everytime the char_discovered_cb is called, it's better to
> define these bt_uuids directly.
> ---
> android/hog.c | 40 ++++++++++++++++++----------------------
> 1 file changed, 18 insertions(+), 22 deletions(-)
>
> diff --git a/android/hog.c b/android/hog.c
> index 08196d4..e1ccaf3 100644
> --- a/android/hog.c
> +++ b/android/hog.c
> @@ -61,12 +61,6 @@
> #include "android/bas.h"
> #include "android/hog.h"
>
> -#define HOG_INFO_UUID 0x2A4A
> -#define HOG_REPORT_MAP_UUID 0x2A4B
> -#define HOG_REPORT_UUID 0x2A4D
> -#define HOG_PROTO_MODE_UUID 0x2A4E
> -#define HOG_CONTROL_POINT_UUID 0x2A4C
> -
> #define HOG_REPORT_TYPE_INPUT 1
> #define HOG_REPORT_TYPE_OUTPUT 2
> #define HOG_REPORT_TYPE_FEATURE 3
> @@ -77,6 +71,17 @@
> #define HOG_REPORT_MAP_MAX_SIZE 512
> #define HID_INFO_SIZE 4
>
> +static const bt_uuid_t info_uuid = { .type = BT_UUID16,
> + .value.u16 = 0x2A4A };
> +static const bt_uuid_t report_map_uuid = { .type = BT_UUID16,
> + .value.u16 = 0x2A4B };
> +static const bt_uuid_t control_point_uuid = { .type = BT_UUID16,
> + .value.u16 = 0x2A4C };
> +static const bt_uuid_t report_uuid = { .type = BT_UUID16,
> + .value.u16 = 0x2A4D };
> +static const bt_uuid_t protocol_mode_uuid = { .type = BT_UUID16,
> + .value.u16 = 0x2A4E };
We usually keep those as defines and create by_uuid where needed. Since this
is used only in discovery (ie not performance critical) I'd just skip this
patch for now.
> +
> struct bt_hog {
> int ref_count;
> uint16_t service_handle;
> @@ -300,7 +305,6 @@ static void external_report_reference_cb(bool success,
> uint8_t status, void *user_data)
> {
> struct bt_hog *hog = user_data;
> - uint16_t uuid16;
> bt_uuid_t uuid;
> struct queue *chrs;
>
> @@ -315,12 +319,12 @@ static void external_report_reference_cb(bool success,
> uint8_t status, return;
> }
>
> - uuid16 = get_le16(value);
> - DBG("External report reference read, external report characteristic "
> - "UUID: 0x%04x", uuid16);
> + DBG("External report characteristic UUID: 0x%04x", get_le16(value));
> +
> + bt_uuid16_create(&uuid, get_le16(value));
>
> /* Do not discover if is not a Report */
> - if (uuid16 != HOG_REPORT_UUID)
> + if (bt_uuid_cmp(&uuid, &report_uuid))
> return;
>
> chrs = queue_new();
> @@ -329,7 +333,6 @@ static void external_report_reference_cb(bool success,
> uint8_t status, return;
> }
>
> - bt_uuid16_create(&uuid, uuid16);
> gatt_db_read_by_type(hog->db, 0x0001, 0xffff, uuid, chrs);
>
> if (queue_isempty(chrs))
> @@ -823,18 +826,11 @@ static void char_discovered_cb(struct
> gatt_db_attribute *attrib, void *user_data)
> {
> struct bt_hog *hog = user_data;
> - bt_uuid_t report_uuid, report_map_uuid, proto_mode_uuid, ctrlpt_uuid;
> - bt_uuid_t info_uuid, uuid;
> + bt_uuid_t uuid;
> struct report *report;
> uint16_t value_handle;
> uint8_t properties;
>
> - bt_uuid16_create(&report_uuid, HOG_REPORT_UUID);
> - bt_uuid16_create(&report_map_uuid, HOG_REPORT_MAP_UUID);
> - bt_uuid16_create(&info_uuid, HOG_INFO_UUID);
> - bt_uuid16_create(&proto_mode_uuid, HOG_PROTO_MODE_UUID);
> - bt_uuid16_create(&ctrlpt_uuid, HOG_CONTROL_POINT_UUID);
> -
> gatt_db_attribute_get_char_data(attrib, NULL, &value_handle,
> &properties, &uuid);
>
> @@ -849,11 +845,11 @@ static void char_discovered_cb(struct
> gatt_db_attribute *attrib, } else if (!bt_uuid_cmp(&uuid, &info_uuid)) {
> bt_gatt_client_read_value(hog->client, value_handle,
> info_read_cb, hog, NULL);
> - } else if (!bt_uuid_cmp(&uuid, &proto_mode_uuid)) {
> + } else if (!bt_uuid_cmp(&uuid, &protocol_mode_uuid)) {
> hog->proto_mode_handle = value_handle;
> bt_gatt_client_read_value(hog->client, value_handle,
> proto_mode_read_cb, hog, NULL);
> - } else if (!bt_uuid_cmp(&uuid, &ctrlpt_uuid)) {
> + } else if (!bt_uuid_cmp(&uuid, &control_point_uuid)) {
> hog->ctrlpt_handle = value_handle;
> }
> }
--
BR
Szymon Janc
^ permalink raw reply [flat|nested] 41+ messages in thread
* [PATCH 14/28] android/hog: Replace GSList of hog instances with queue of instances
2015-04-01 16:40 [PATCH 00/28] android/hog Introduce bt_gatt_client Mariusz Skamra
` (12 preceding siblings ...)
2015-04-01 16:40 ` [PATCH 13/28] android/hog: Replace definitions of characteristic uuids with bt_uuids Mariusz Skamra
@ 2015-04-01 16:40 ` Mariusz Skamra
2015-04-02 15:29 ` Szymon Janc
2015-04-01 16:40 ` [PATCH 15/28] android/dis: Remove tracking pending gatt operations Mariusz Skamra
` (13 subsequent siblings)
27 siblings, 1 reply; 41+ messages in thread
From: Mariusz Skamra @ 2015-04-01 16:40 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Mariusz Skamra
Thanks to this patch hog instances can be now stored in queue.
This will help to clean the code from glib dependencies.
---
android/hog.c | 34 +++++++++++++++-------------------
1 file changed, 15 insertions(+), 19 deletions(-)
diff --git a/android/hog.c b/android/hog.c
index e1ccaf3..9f4ca44 100644
--- a/android/hog.c
+++ b/android/hog.c
@@ -106,7 +106,7 @@ struct bt_hog {
struct bt_scpp *scpp;
struct bt_dis *dis;
struct queue *bas;
- GSList *instances;
+ struct queue *instances;
struct bt_gatt_client *client;
struct gatt_db *db;
};
@@ -870,7 +870,7 @@ static void hog_free(void *data)
bt_hog_detach(hog);
queue_destroy(hog->bas, (void *) bt_bas_unref);
- g_slist_free_full(hog->instances, hog_free);
+ queue_destroy(hog->instances, hog_free);
bt_scpp_unref(hog->scpp);
bt_dis_unref(hog->dis);
@@ -899,6 +899,7 @@ struct bt_hog *bt_hog_new(int fd, const char *name, uint16_t vendor,
hog->bas = queue_new();
hog->reports = queue_new();
+ hog->instances = queue_new();
if (fd < 0)
hog->uhid = bt_uhid_new_default();
@@ -907,7 +908,7 @@ struct bt_hog *bt_hog_new(int fd, const char *name, uint16_t vendor,
hog->uhid_fd = fd;
- if (!hog->bas || !hog->uhid || !hog->reports) {
+ if (!hog->bas || !hog->uhid || !hog->reports || !hog->instances) {
hog_free(hog);
return NULL;
}
@@ -1021,7 +1022,7 @@ static void hog_attach_hog(struct bt_hog *hog, uint16_t service_handle)
return;
bt_hog_attach(instance, hog->attrib, hog->client);
- hog->instances = g_slist_append(hog->instances, instance);
+ queue_push_tail(hog->instances, instance);
}
static void primary_cb(uint8_t status, GSList *services, void *user_data)
@@ -1090,7 +1091,7 @@ static void service_cb(struct gatt_db_attribute *attrib, void *user_data)
bool bt_hog_attach(struct bt_hog *hog, void *gatt, void *client)
{
- GSList *l;
+ const struct queue_entry *hog_entry;
if (hog->attrib || hog->client)
return false;
@@ -1113,8 +1114,9 @@ bool bt_hog_attach(struct bt_hog *hog, void *gatt, void *client)
queue_foreach(hog->bas, (void *) bt_bas_attach, gatt);
- for (l = hog->instances; l; l = l->next) {
- struct bt_hog *instance = l->data;
+ hog_entry = queue_get_entries(hog->instances);
+ while (hog_entry) {
+ struct bt_hog *instance = hog_entry->data;
bt_hog_attach(instance, gatt, client);
}
@@ -1135,19 +1137,11 @@ bool bt_hog_attach(struct bt_hog *hog, void *gatt, void *client)
void bt_hog_detach(struct bt_hog *hog)
{
- GSList *l;
-
if (!hog->attrib || !hog->client)
return;
queue_foreach(hog->bas, (void *) bt_bas_detach, NULL);
-
- for (l = hog->instances; l; l = l->next) {
- struct bt_hog *instance = l->data;
-
- bt_hog_detach(instance);
- }
-
+ queue_foreach(hog->instances, (void *) bt_hog_detach, NULL);
queue_foreach(hog->reports, report_disable_notif, NULL);
if (hog->scpp)
@@ -1182,7 +1176,7 @@ int bt_hog_set_control_point(struct bt_hog *hog, bool suspend)
int bt_hog_send_report(struct bt_hog *hog, void *data, size_t size, int type)
{
struct report *report;
- GSList *l;
+ const struct queue_entry *hog_entry;
if (!hog)
return -EINVAL;
@@ -1207,10 +1201,12 @@ int bt_hog_send_report(struct bt_hog *hog, void *data, size_t size, int type)
report->decl->value_handle,
false, data, size);
- for (l = hog->instances; l; l = l->next) {
- struct bt_hog *instance = l->data;
+ hog_entry = queue_get_entries(hog->instances);
+ while (hog_entry) {
+ struct bt_hog *instance = hog_entry->data;
bt_hog_send_report(instance, data, size, type);
+ hog_entry = hog_entry->next;
}
return 0;
--
1.9.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* Re: [PATCH 14/28] android/hog: Replace GSList of hog instances with queue of instances
2015-04-01 16:40 ` [PATCH 14/28] android/hog: Replace GSList of hog instances with queue of instances Mariusz Skamra
@ 2015-04-02 15:29 ` Szymon Janc
0 siblings, 0 replies; 41+ messages in thread
From: Szymon Janc @ 2015-04-02 15:29 UTC (permalink / raw)
To: Mariusz Skamra; +Cc: linux-bluetooth
Hi Mariusz,
On Wednesday 01 of April 2015 18:40:30 Mariusz Skamra wrote:
> Thanks to this patch hog instances can be now stored in queue.
> This will help to clean the code from glib dependencies.
> ---
> android/hog.c | 34 +++++++++++++++-------------------
> 1 file changed, 15 insertions(+), 19 deletions(-)
>
> diff --git a/android/hog.c b/android/hog.c
> index e1ccaf3..9f4ca44 100644
> --- a/android/hog.c
> +++ b/android/hog.c
> @@ -106,7 +106,7 @@ struct bt_hog {
> struct bt_scpp *scpp;
> struct bt_dis *dis;
> struct queue *bas;
> - GSList *instances;
> + struct queue *instances;
> struct bt_gatt_client *client;
> struct gatt_db *db;
> };
> @@ -870,7 +870,7 @@ static void hog_free(void *data)
> bt_hog_detach(hog);
>
> queue_destroy(hog->bas, (void *) bt_bas_unref);
> - g_slist_free_full(hog->instances, hog_free);
> + queue_destroy(hog->instances, hog_free);
>
> bt_scpp_unref(hog->scpp);
> bt_dis_unref(hog->dis);
> @@ -899,6 +899,7 @@ struct bt_hog *bt_hog_new(int fd, const char *name,
> uint16_t vendor,
>
> hog->bas = queue_new();
> hog->reports = queue_new();
> + hog->instances = queue_new();
>
> if (fd < 0)
> hog->uhid = bt_uhid_new_default();
> @@ -907,7 +908,7 @@ struct bt_hog *bt_hog_new(int fd, const char *name,
> uint16_t vendor,
>
> hog->uhid_fd = fd;
>
> - if (!hog->bas || !hog->uhid || !hog->reports) {
> + if (!hog->bas || !hog->uhid || !hog->reports || !hog->instances) {
> hog_free(hog);
> return NULL;
> }
> @@ -1021,7 +1022,7 @@ static void hog_attach_hog(struct bt_hog *hog,
> uint16_t service_handle) return;
>
> bt_hog_attach(instance, hog->attrib, hog->client);
> - hog->instances = g_slist_append(hog->instances, instance);
> + queue_push_tail(hog->instances, instance);
> }
>
> static void primary_cb(uint8_t status, GSList *services, void *user_data)
> @@ -1090,7 +1091,7 @@ static void service_cb(struct gatt_db_attribute
> *attrib, void *user_data)
>
> bool bt_hog_attach(struct bt_hog *hog, void *gatt, void *client)
> {
> - GSList *l;
> + const struct queue_entry *hog_entry;
>
> if (hog->attrib || hog->client)
> return false;
> @@ -1113,8 +1114,9 @@ bool bt_hog_attach(struct bt_hog *hog, void *gatt,
> void *client)
>
> queue_foreach(hog->bas, (void *) bt_bas_attach, gatt);
>
> - for (l = hog->instances; l; l = l->next) {
> - struct bt_hog *instance = l->data;
> + hog_entry = queue_get_entries(hog->instances);
> + while (hog_entry) {
> + struct bt_hog *instance = hog_entry->data;
>
> bt_hog_attach(instance, gatt, client);
> }
> @@ -1135,19 +1137,11 @@ bool bt_hog_attach(struct bt_hog *hog, void *gatt,
> void *client)
>
> void bt_hog_detach(struct bt_hog *hog)
> {
> - GSList *l;
> -
> if (!hog->attrib || !hog->client)
> return;
>
> queue_foreach(hog->bas, (void *) bt_bas_detach, NULL);
> -
> - for (l = hog->instances; l; l = l->next) {
> - struct bt_hog *instance = l->data;
> -
> - bt_hog_detach(instance);
> - }
> -
> + queue_foreach(hog->instances, (void *) bt_hog_detach, NULL);
> queue_foreach(hog->reports, report_disable_notif, NULL);
>
> if (hog->scpp)
> @@ -1182,7 +1176,7 @@ int bt_hog_set_control_point(struct bt_hog *hog, bool
> suspend) int bt_hog_send_report(struct bt_hog *hog, void *data, size_t
> size, int type) {
> struct report *report;
> - GSList *l;
> + const struct queue_entry *hog_entry;
>
> if (!hog)
> return -EINVAL;
> @@ -1207,10 +1201,12 @@ int bt_hog_send_report(struct bt_hog *hog, void
> *data, size_t size, int type) report->decl->value_handle,
> false, data, size);
>
> - for (l = hog->instances; l; l = l->next) {
> - struct bt_hog *instance = l->data;
> + hog_entry = queue_get_entries(hog->instances);
> + while (hog_entry) {
> + struct bt_hog *instance = hog_entry->data;
>
> bt_hog_send_report(instance, data, size, type);
> + hog_entry = hog_entry->next;
> }
I think queue_get_entries() was meant to be used for early breaking from loop.
Why not just use queue_foreach() when doing foreach loop?
>
> return 0;
--
BR
Szymon Janc
^ permalink raw reply [flat|nested] 41+ messages in thread
* [PATCH 15/28] android/dis: Remove tracking pending gatt operations
2015-04-01 16:40 [PATCH 00/28] android/hog Introduce bt_gatt_client Mariusz Skamra
` (13 preceding siblings ...)
2015-04-01 16:40 ` [PATCH 14/28] android/hog: Replace GSList of hog instances with queue of instances Mariusz Skamra
@ 2015-04-01 16:40 ` Mariusz Skamra
2015-04-01 16:40 ` [PATCH 16/28] android/dis: Introduce bt_gatt_client Mariusz Skamra
` (12 subsequent siblings)
27 siblings, 0 replies; 41+ messages in thread
From: Mariusz Skamra @ 2015-04-01 16:40 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Mariusz Skamra
Since the use of bt_gatt_client there is no need to queue pending gatt
operations. bt_gatt_client already keeps track on that, so that
on bt_gatt_client_unref the queue of pending requests is destroyed.
---
android/dis.c | 107 +++-------------------------------------------------------
1 file changed, 4 insertions(+), 103 deletions(-)
diff --git a/android/dis.c b/android/dis.c
index 75dbe3d..f699046 100644
--- a/android/dis.c
+++ b/android/dis.c
@@ -57,7 +57,6 @@ struct bt_dis {
struct gatt_primary *primary; /* Primary details */
bt_dis_notify notify;
void *notify_data;
- struct queue *gatt_op;
};
struct characteristic {
@@ -65,25 +64,11 @@ struct characteristic {
struct bt_dis *d; /* deviceinfo where the char belongs */
};
-struct gatt_request {
- unsigned int id;
- struct bt_dis *dis;
- void *user_data;
-};
-
-static void destroy_gatt_req(struct gatt_request *req)
-{
- queue_remove(req->dis->gatt_op, req);
- bt_dis_unref(req->dis);
- free(req);
-}
-
static void dis_free(struct bt_dis *dis)
{
bt_dis_detach(dis);
g_free(dis->primary);
- queue_destroy(dis->gatt_op, (void *) destroy_gatt_req);
g_free(dis);
}
@@ -95,12 +80,6 @@ struct bt_dis *bt_dis_new(void *primary)
if (!dis)
return NULL;
- dis->gatt_op = queue_new();
- if (!dis->gatt_op) {
- dis_free(dis);
- return NULL;
- }
-
if (primary)
dis->primary = g_memdup(primary, sizeof(*dis->primary));
@@ -128,39 +107,13 @@ void bt_dis_unref(struct bt_dis *dis)
dis_free(dis);
}
-static struct gatt_request *create_request(struct bt_dis *dis,
- void *user_data)
-{
- struct gatt_request *req;
-
- req = new0(struct gatt_request, 1);
- if (!req)
- return NULL;
-
- req->user_data = user_data;
- req->dis = bt_dis_ref(dis);
-
- return req;
-}
-
-static bool set_and_store_gatt_req(struct bt_dis *dis,
- struct gatt_request *req,
- unsigned int id)
-{
- req->id = id;
- return queue_push_head(dis->gatt_op, req);
-}
-
static void read_pnpid_cb(guint8 status, const guint8 *pdu, guint16 len,
gpointer user_data)
{
- struct gatt_request *req = user_data;
- struct bt_dis *dis = req->user_data;
+ struct bt_dis *dis = user_data;
uint8_t value[PNP_ID_SIZE];
ssize_t vlen;
- destroy_gatt_req(req);
-
if (status != 0) {
error("Error reading PNP_ID value: %s", att_ecode2str(status));
return;
@@ -190,57 +143,12 @@ static void read_pnpid_cb(guint8 status, const guint8 *pdu, guint16 len,
dis->version, dis->notify_data);
}
-static void read_char(struct bt_dis *dis, GAttrib *attrib, uint16_t handle,
- GAttribResultFunc func, gpointer user_data)
-{
- struct gatt_request *req;
- unsigned int id;
-
- req = create_request(dis, user_data);
- if (!req)
- return;
-
- id = gatt_read_char(attrib, handle, func, req);
-
- if (set_and_store_gatt_req(dis, req, id))
- return;
-
- error("dis: Could not read characteristic");
- g_attrib_cancel(attrib, id);
- free(req);
-}
-
-static void discover_char(struct bt_dis *dis, GAttrib *attrib,
- uint16_t start, uint16_t end,
- bt_uuid_t *uuid, gatt_cb_t func,
- gpointer user_data)
-{
- struct gatt_request *req;
- unsigned int id;
-
- req = create_request(dis, user_data);
- if (!req)
- return;
-
- id = gatt_discover_char(attrib, start, end, uuid, func, req);
-
- if (set_and_store_gatt_req(dis, req, id))
- return;
-
- error("dis: Could not send discover characteristic");
- g_attrib_cancel(attrib, id);
- free(req);
-}
-
static void configure_deviceinfo_cb(uint8_t status, GSList *characteristics,
void *user_data)
{
- struct gatt_request *req = user_data;
- struct bt_dis *d = req->user_data;
+ struct bt_dis *d = user_data;
GSList *l;
- destroy_gatt_req(req);
-
if (status != 0) {
error("Discover deviceinfo characteristics: %s",
att_ecode2str(status));
@@ -252,7 +160,7 @@ static void configure_deviceinfo_cb(uint8_t status, GSList *characteristics,
if (strcmp(c->uuid, PNPID_UUID) == 0) {
d->handle = c->value_handle;
- read_char(d, d->attrib, d->handle, read_pnpid_cb, d);
+ gatt_read_char(d->attrib, d->handle, read_pnpid_cb, d);
break;
}
}
@@ -268,25 +176,18 @@ bool bt_dis_attach(struct bt_dis *dis, void *attrib)
dis->attrib = g_attrib_ref(attrib);
if (!dis->handle)
- discover_char(dis, dis->attrib, primary->range.start,
+ gatt_discover_char(dis->attrib, primary->range.start,
primary->range.end, NULL,
configure_deviceinfo_cb, dis);
return true;
}
-static void cancel_gatt_req(struct gatt_request *req)
-{
- if (g_attrib_cancel(req->dis->attrib, req->id))
- destroy_gatt_req(req);
-}
-
void bt_dis_detach(struct bt_dis *dis)
{
if (!dis->attrib)
return;
- queue_foreach(dis->gatt_op, (void *) cancel_gatt_req, NULL);
g_attrib_unref(dis->attrib);
dis->attrib = NULL;
}
--
1.9.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [PATCH 16/28] android/dis: Introduce bt_gatt_client
2015-04-01 16:40 [PATCH 00/28] android/hog Introduce bt_gatt_client Mariusz Skamra
` (14 preceding siblings ...)
2015-04-01 16:40 ` [PATCH 15/28] android/dis: Remove tracking pending gatt operations Mariusz Skamra
@ 2015-04-01 16:40 ` Mariusz Skamra
2015-04-01 16:40 ` [PATCH 17/28] android/scpp: Remove tracking pending gatt operations Mariusz Skamra
` (11 subsequent siblings)
27 siblings, 0 replies; 41+ messages in thread
From: Mariusz Skamra @ 2015-04-01 16:40 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Mariusz Skamra
This patch replaces gattrib with bt_gatt_client and strips glib dependencies.
---
android/dis.c | 104 ++++++++++++++++++++++------------------------------------
android/dis.h | 4 +--
android/hog.c | 18 ++++------
3 files changed, 48 insertions(+), 78 deletions(-)
diff --git a/android/dis.c b/android/dis.c
index f699046..4a28c5a 100644
--- a/android/dis.c
+++ b/android/dis.c
@@ -27,61 +27,52 @@
#include <stdbool.h>
#include <errno.h>
-#include <glib.h>
-
#include "src/log.h"
#include "lib/bluetooth.h"
-#include "lib/sdp.h"
#include "lib/uuid.h"
#include "src/shared/util.h"
#include "src/shared/queue.h"
-
-#include "attrib/gattrib.h"
-#include "attrib/att.h"
-#include "attrib/gatt.h"
+#include "src/shared/att.h"
+#include "src/shared/gatt-db.h"
+#include "src/shared/gatt-client.h"
#include "android/dis.h"
-#define PNP_ID_SIZE 7
-
struct bt_dis {
int ref_count;
+ uint16_t service_handle;
uint16_t handle;
uint8_t source;
uint16_t vendor;
uint16_t product;
uint16_t version;
- GAttrib *attrib; /* GATT connection */
- struct gatt_primary *primary; /* Primary details */
bt_dis_notify notify;
void *notify_data;
-};
-
-struct characteristic {
- struct gatt_char attr; /* Characteristic */
- struct bt_dis *d; /* deviceinfo where the char belongs */
+ struct bt_gatt_client *client;
+ struct gatt_db *db;
};
static void dis_free(struct bt_dis *dis)
{
bt_dis_detach(dis);
- g_free(dis->primary);
- g_free(dis);
+ free(dis);
}
-struct bt_dis *bt_dis_new(void *primary)
+struct bt_dis *bt_dis_new(uint16_t service_handle)
{
struct bt_dis *dis;
- dis = g_try_new0(struct bt_dis, 1);
+ if (!service_handle)
+ return NULL;
+
+ dis = new0(struct bt_dis, 1);
if (!dis)
return NULL;
- if (primary)
- dis->primary = g_memdup(primary, sizeof(*dis->primary));
+ dis->service_handle = service_handle;
return bt_dis_ref(dis);
}
@@ -107,26 +98,13 @@ void bt_dis_unref(struct bt_dis *dis)
dis_free(dis);
}
-static void read_pnpid_cb(guint8 status, const guint8 *pdu, guint16 len,
- gpointer user_data)
+static void read_pnpid_cb(bool success, uint8_t att_ecode, const uint8_t *value,
+ uint16_t length, void *user_data)
{
struct bt_dis *dis = user_data;
- uint8_t value[PNP_ID_SIZE];
- ssize_t vlen;
-
- if (status != 0) {
- error("Error reading PNP_ID value: %s", att_ecode2str(status));
- return;
- }
-
- vlen = dec_read_resp(pdu, len, value, sizeof(value));
- if (vlen < 0) {
- error("Error reading PNP_ID: Protocol error");
- return;
- }
- if (vlen < 7) {
- error("Error reading PNP_ID: Invalid pdu length received");
+ if (length < 7) {
+ error("Error reading PNP_ID: Invalid length received");
return;
}
@@ -143,53 +121,51 @@ static void read_pnpid_cb(guint8 status, const guint8 *pdu, guint16 len,
dis->version, dis->notify_data);
}
-static void configure_deviceinfo_cb(uint8_t status, GSList *characteristics,
+static void configure_deviceinfo_cb(struct gatt_db_attribute *attrib,
void *user_data)
{
- struct bt_dis *d = user_data;
- GSList *l;
+ struct bt_dis *dis = user_data;
+ bt_uuid_t uuid, pnpid_uuid;
+ uint16_t value_handle;
- if (status != 0) {
- error("Discover deviceinfo characteristics: %s",
- att_ecode2str(status));
- return;
- }
+ gatt_db_attribute_get_char_data(attrib, NULL, &value_handle,
+ NULL, &uuid);
- for (l = characteristics; l; l = l->next) {
- struct gatt_char *c = l->data;
+ bt_string_to_uuid(&pnpid_uuid, PNPID_UUID);
- if (strcmp(c->uuid, PNPID_UUID) == 0) {
- d->handle = c->value_handle;
- gatt_read_char(d->attrib, d->handle, read_pnpid_cb, d);
- break;
- }
+ if (!bt_uuid_cmp(&uuid, &pnpid_uuid)) {
+ dis->handle = value_handle;
+ bt_gatt_client_read_value(dis->client, value_handle,
+ read_pnpid_cb, dis, NULL);
}
}
-bool bt_dis_attach(struct bt_dis *dis, void *attrib)
+bool bt_dis_attach(struct bt_dis *dis, struct bt_gatt_client *client)
{
- struct gatt_primary *primary = dis->primary;
+ struct gatt_db_attribute *attrib;
- if (dis->attrib || !primary)
+ if (!dis || dis->client || !dis->service_handle)
return false;
- dis->attrib = g_attrib_ref(attrib);
+ dis->client = bt_gatt_client_ref(client);
+ dis->db = bt_gatt_client_get_db(client);
+ attrib = gatt_db_get_attribute(dis->db, dis->service_handle);
if (!dis->handle)
- gatt_discover_char(dis->attrib, primary->range.start,
- primary->range.end, NULL,
- configure_deviceinfo_cb, dis);
+ gatt_db_service_foreach_char(attrib, configure_deviceinfo_cb,
+ dis);
return true;
}
void bt_dis_detach(struct bt_dis *dis)
{
- if (!dis->attrib)
+ if (!dis->client)
return;
- g_attrib_unref(dis->attrib);
- dis->attrib = NULL;
+ gatt_db_unref(dis->db);
+ bt_gatt_client_unref(dis->client);
+ dis->client = NULL;
}
bool bt_dis_set_notification(struct bt_dis *dis, bt_dis_notify func,
diff --git a/android/dis.h b/android/dis.h
index faf27b3..55c6625 100644
--- a/android/dis.h
+++ b/android/dis.h
@@ -23,12 +23,12 @@
struct bt_dis;
-struct bt_dis *bt_dis_new(void *primary);
+struct bt_dis *bt_dis_new(uint16_t service_handle);
struct bt_dis *bt_dis_ref(struct bt_dis *dis);
void bt_dis_unref(struct bt_dis *dis);
-bool bt_dis_attach(struct bt_dis *dis, void *gatt);
+bool bt_dis_attach(struct bt_dis *dis, struct bt_gatt_client *client);
void bt_dis_detach(struct bt_dis *dis);
typedef void (*bt_dis_notify) (uint8_t source, uint16_t vendor,
diff --git a/android/hog.c b/android/hog.c
index 9f4ca44..71f8c50 100644
--- a/android/hog.c
+++ b/android/hog.c
@@ -976,17 +976,17 @@ static void dis_notify(uint8_t source, uint16_t vendor, uint16_t product,
hog->version = version;
}
-static void hog_attach_dis(struct bt_hog *hog, struct gatt_primary *primary)
+static void hog_attach_dis(struct bt_hog *hog, uint16_t service_handle)
{
if (hog->dis) {
- bt_dis_attach(hog->dis, hog->attrib);
+ bt_dis_attach(hog->dis, hog->client);
return;
}
- hog->dis = bt_dis_new(primary);
+ hog->dis = bt_dis_new(service_handle);
if (hog->dis) {
bt_dis_set_notification(hog->dis, dis_notify, hog);
- bt_dis_attach(hog->dis, hog->attrib);
+ bt_dis_attach(hog->dis, hog->client);
}
}
@@ -1052,11 +1052,6 @@ static void primary_cb(uint8_t status, GSList *services, void *user_data)
continue;
}
- if (strcmp(primary->uuid, DEVICE_INFORMATION_UUID) == 0) {
- hog_attach_dis(hog, primary);
- continue;
- }
-
if (strcmp(primary->uuid, BATTERY_UUID) == 0) {
hog_attach_bas(hog, primary);
}
@@ -1082,8 +1077,7 @@ static void service_cb(struct gatt_db_attribute *attrib, void *user_data)
/* TODO */
return;
else if (!bt_uuid_strcmp(uuid, DEVICE_INFORMATION_UUID))
- /* TODO */
- return;
+ hog_attach_dis(hog, service_handle);
else if (!bt_uuid_strcmp(uuid, BATTERY_UUID))
/* TODO */
return;
@@ -1110,7 +1104,7 @@ bool bt_hog_attach(struct bt_hog *hog, void *gatt, void *client)
bt_scpp_attach(hog->scpp, gatt);
if (hog->dis)
- bt_dis_attach(hog->dis, gatt);
+ bt_dis_attach(hog->dis, hog->client);
queue_foreach(hog->bas, (void *) bt_bas_attach, gatt);
--
1.9.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [PATCH 17/28] android/scpp: Remove tracking pending gatt operations
2015-04-01 16:40 [PATCH 00/28] android/hog Introduce bt_gatt_client Mariusz Skamra
` (15 preceding siblings ...)
2015-04-01 16:40 ` [PATCH 16/28] android/dis: Introduce bt_gatt_client Mariusz Skamra
@ 2015-04-01 16:40 ` Mariusz Skamra
2015-04-01 16:40 ` [PATCH 18/28] android/scpp: Introduce bt_gatt_client Mariusz Skamra
` (10 subsequent siblings)
27 siblings, 0 replies; 41+ messages in thread
From: Mariusz Skamra @ 2015-04-01 16:40 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Mariusz Skamra
From: Mariusz Skamra <mariusz.skamra@gmail.com>
Since the use of bt_gatt_client there is no need to queue pending gatt
operations. bt_gatt_client already keeps track on that, so that
on bt_gatt_client_unref the queue of pending requests is destroyed.
---
android/scpp.c | 72 ++++------------------------------------------------------
1 file changed, 4 insertions(+), 68 deletions(-)
diff --git a/android/scpp.c b/android/scpp.c
index f8f81f3..a28fbb6 100644
--- a/android/scpp.c
+++ b/android/scpp.c
@@ -62,62 +62,13 @@ struct bt_scpp {
uint16_t iwhandle;
uint16_t refresh_handle;
guint refresh_cb_id;
- struct queue *gatt_op;
};
-static void discover_char(struct bt_scpp *scpp, GAttrib *attrib,
- uint16_t start, uint16_t end,
- bt_uuid_t *uuid, gatt_cb_t func,
- gpointer user_data)
-{
- unsigned int id;
-
- id = gatt_discover_char(attrib, start, end, uuid, func, user_data);
-
- if (queue_push_head(scpp->gatt_op, UINT_TO_PTR(id)))
- return;
-
- error("scpp: Could not discover characteristic");
- g_attrib_cancel(attrib, id);
-}
-
-static void discover_desc(struct bt_scpp *scpp, GAttrib *attrib,
- uint16_t start, uint16_t end, bt_uuid_t *uuid,
- gatt_cb_t func, gpointer user_data)
-{
- unsigned int id;
-
- id = gatt_discover_desc(attrib, start, end, uuid, func, user_data);
-
- if (queue_push_head(scpp->gatt_op, UINT_TO_PTR(id)))
- return;
-
- error("scpp: Could not discover descriptor");
- g_attrib_cancel(attrib, id);
-}
-
-static void write_char(struct bt_scpp *scan, GAttrib *attrib, uint16_t handle,
- const uint8_t *value, size_t vlen,
- GAttribResultFunc func,
- gpointer user_data)
-{
- unsigned int id;
-
- id = gatt_write_char(attrib, handle, value, vlen, func, user_data);
-
- if (queue_push_head(scan->gatt_op, UINT_TO_PTR(id)))
- return;
-
- error("scpp: Could not read char");
- g_attrib_cancel(attrib, id);
-}
-
static void scpp_free(struct bt_scpp *scan)
{
bt_scpp_detach(scan);
g_free(scan->primary);
- queue_destroy(scan->gatt_op, NULL); /* cleared in bt_scpp_detach */
g_free(scan);
}
@@ -132,12 +83,6 @@ struct bt_scpp *bt_scpp_new(void *primary)
scan->interval = SCAN_INTERVAL;
scan->window = SCAN_WINDOW;
- scan->gatt_op = queue_new();
- if (!scan->gatt_op) {
- scpp_free(scan);
- return NULL;
- }
-
if (primary)
scan->primary = g_memdup(primary, sizeof(*scan->primary));
@@ -213,7 +158,7 @@ static void write_ccc(struct bt_scpp *scan, GAttrib *attrib, uint16_t handle,
put_le16(GATT_CLIENT_CHARAC_CFG_NOTIF_BIT, value);
- write_char(scan, attrib, handle, value, sizeof(value), ccc_written_cb,
+ gatt_write_char(attrib, handle, value, sizeof(value), ccc_written_cb,
user_data);
}
@@ -266,7 +211,7 @@ static void refresh_discovered_cb(uint8_t status, GSList *chars,
bt_uuid16_create(&uuid, GATT_CLIENT_CHARAC_CFG_UUID);
- discover_desc(scan, scan->attrib, start, end, &uuid,
+ gatt_discover_desc(scan->attrib, start, end, &uuid,
discover_descriptor_cb, user_data);
}
@@ -304,7 +249,7 @@ bool bt_scpp_attach(struct bt_scpp *scan, void *attrib)
scan->window);
else {
bt_uuid16_create(&iwin_uuid, SCAN_INTERVAL_WIN_UUID);
- discover_char(scan, scan->attrib, scan->primary->range.start,
+ gatt_discover_char(scan->attrib, scan->primary->range.start,
scan->primary->range.end, &iwin_uuid,
iwin_discovered_cb, scan);
}
@@ -315,7 +260,7 @@ bool bt_scpp_attach(struct bt_scpp *scan, void *attrib)
refresh_value_cb, scan, NULL);
else {
bt_uuid16_create(&refresh_uuid, SCAN_REFRESH_UUID);
- discover_char(scan, scan->attrib, scan->primary->range.start,
+ gatt_discover_char(scan->attrib, scan->primary->range.start,
scan->primary->range.end, &refresh_uuid,
refresh_discovered_cb, scan);
}
@@ -323,14 +268,6 @@ bool bt_scpp_attach(struct bt_scpp *scan, void *attrib)
return true;
}
-static void cancel_gatt_req(void *data, void *user_data)
-{
- unsigned int id = PTR_TO_UINT(data);
- struct bt_scpp *scan = user_data;
-
- g_attrib_cancel(scan->attrib, id);
-}
-
void bt_scpp_detach(struct bt_scpp *scan)
{
if (!scan || !scan->attrib)
@@ -341,7 +278,6 @@ void bt_scpp_detach(struct bt_scpp *scan)
scan->refresh_cb_id = 0;
}
- queue_foreach(scan->gatt_op, cancel_gatt_req, scan);
g_attrib_unref(scan->attrib);
scan->attrib = NULL;
}
--
1.9.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [PATCH 18/28] android/scpp: Introduce bt_gatt_client
2015-04-01 16:40 [PATCH 00/28] android/hog Introduce bt_gatt_client Mariusz Skamra
` (16 preceding siblings ...)
2015-04-01 16:40 ` [PATCH 17/28] android/scpp: Remove tracking pending gatt operations Mariusz Skamra
@ 2015-04-01 16:40 ` Mariusz Skamra
2015-04-02 15:34 ` Szymon Janc
2015-04-01 16:40 ` [PATCH 19/28] android/scpp: Merge refresh_discovered_cb with iwin_discovered_cb Mariusz Skamra
` (9 subsequent siblings)
27 siblings, 1 reply; 41+ messages in thread
From: Mariusz Skamra @ 2015-04-01 16:40 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Mariusz Skamra
From: Mariusz Skamra <mariusz.skamra@gmail.com>
This patch replaces gattrib with bt_gatt_client and strips glib dependencies.
---
android/hog.c | 18 ++----
android/scpp.c | 196 +++++++++++++++++++++------------------------------------
android/scpp.h | 4 +-
3 files changed, 80 insertions(+), 138 deletions(-)
diff --git a/android/hog.c b/android/hog.c
index 71f8c50..78c1b26 100644
--- a/android/hog.c
+++ b/android/hog.c
@@ -954,16 +954,16 @@ static void find_included_cb(struct gatt_db_attribute *attrib, void *user_data)
DBG("included: handle %x", start_handle);
}
-static void hog_attach_scpp(struct bt_hog *hog, struct gatt_primary *primary)
+static void hog_attach_scpp(struct bt_hog *hog, uint16_t service_handle)
{
if (hog->scpp) {
- bt_scpp_attach(hog->scpp, hog->attrib);
+ bt_scpp_attach(hog->scpp, hog->client);
return;
}
- hog->scpp = bt_scpp_new(primary);
+ hog->scpp = bt_scpp_new(service_handle);
if (hog->scpp)
- bt_scpp_attach(hog->scpp, hog->attrib);
+ bt_scpp_attach(hog->scpp, hog->client);
}
static void dis_notify(uint8_t source, uint16_t vendor, uint16_t product,
@@ -1047,11 +1047,6 @@ static void primary_cb(uint8_t status, GSList *services, void *user_data)
for (l = services; l; l = l->next) {
primary = l->data;
- if (strcmp(primary->uuid, SCAN_PARAMETERS_UUID) == 0) {
- hog_attach_scpp(hog, primary);
- continue;
- }
-
if (strcmp(primary->uuid, BATTERY_UUID) == 0) {
hog_attach_bas(hog, primary);
}
@@ -1074,8 +1069,7 @@ static void service_cb(struct gatt_db_attribute *attrib, void *user_data)
if (!bt_uuid_strcmp(uuid, HOG_UUID))
hog_attach_hog(hog, service_handle);
else if (!bt_uuid_strcmp(uuid, SCAN_PARAMETERS_UUID))
- /* TODO */
- return;
+ hog_attach_scpp(hog, service_handle);
else if (!bt_uuid_strcmp(uuid, DEVICE_INFORMATION_UUID))
hog_attach_dis(hog, service_handle);
else if (!bt_uuid_strcmp(uuid, BATTERY_UUID))
@@ -1101,7 +1095,7 @@ bool bt_hog_attach(struct bt_hog *hog, void *gatt, void *client)
}
if (hog->scpp)
- bt_scpp_attach(hog->scpp, gatt);
+ bt_scpp_attach(hog->scpp, hog->client);
if (hog->dis)
bt_dis_attach(hog->dis, hog->client);
diff --git a/android/scpp.c b/android/scpp.c
index a28fbb6..37bd82e 100644
--- a/android/scpp.c
+++ b/android/scpp.c
@@ -26,23 +26,16 @@
#include <config.h>
#endif
-#include <stdbool.h>
-#include <errno.h>
-
-#include <glib.h>
-
#include "src/log.h"
#include "lib/bluetooth.h"
-#include "lib/sdp.h"
#include "lib/uuid.h"
#include "src/shared/util.h"
#include "src/shared/queue.h"
-
-#include "attrib/att.h"
-#include "attrib/gattrib.h"
-#include "attrib/gatt.h"
+#include "src/shared/att.h"
+#include "src/shared/gatt-db.h"
+#include "src/shared/gatt-client.h"
#include "android/scpp.h"
@@ -55,36 +48,37 @@
struct bt_scpp {
int ref_count;
- GAttrib *attrib;
- struct gatt_primary *primary;
+ uint16_t service_handle;
uint16_t interval;
uint16_t window;
uint16_t iwhandle;
uint16_t refresh_handle;
- guint refresh_cb_id;
+ uint32_t refresh_cb_id;
+ struct bt_gatt_client *client;
+ struct gatt_db *db;
};
static void scpp_free(struct bt_scpp *scan)
{
bt_scpp_detach(scan);
- g_free(scan->primary);
- g_free(scan);
+ free(scan);
}
-struct bt_scpp *bt_scpp_new(void *primary)
+struct bt_scpp *bt_scpp_new(uint16_t service_handle)
{
struct bt_scpp *scan;
- scan = g_try_new0(struct bt_scpp, 1);
+ if (!service_handle)
+ return NULL;
+
+ scan = new0(struct bt_scpp, 1);
if (!scan)
return NULL;
scan->interval = SCAN_INTERVAL;
scan->window = SCAN_WINDOW;
-
- if (primary)
- scan->primary = g_memdup(primary, sizeof(*scan->primary));
+ scan->service_handle = service_handle;
return bt_scpp_ref(scan);
}
@@ -110,7 +104,7 @@ void bt_scpp_unref(struct bt_scpp *scan)
scpp_free(scan);
}
-static void write_scan_params(GAttrib *attrib, uint16_t handle,
+static void write_scan_params(struct bt_gatt_client *client, uint16_t handle,
uint16_t interval, uint16_t window)
{
uint8_t value[4];
@@ -118,168 +112,122 @@ static void write_scan_params(GAttrib *attrib, uint16_t handle,
put_le16(interval, &value[0]);
put_le16(window, &value[2]);
- gatt_write_cmd(attrib, handle, value, sizeof(value), NULL, NULL);
+ bt_gatt_client_write_without_response(client, handle, NULL, value,
+ sizeof(value));
}
-static void refresh_value_cb(const uint8_t *pdu, uint16_t len,
- gpointer user_data)
+static void refresh_value_cb(uint16_t value_handle, const uint8_t *value,
+ uint16_t length, void *user_data)
{
struct bt_scpp *scan = user_data;
- DBG("Server requires refresh: %d", pdu[3]);
+ DBG("Server requires refresh: %d", value[0]);
- if (pdu[3] == SERVER_REQUIRES_REFRESH)
- write_scan_params(scan->attrib, scan->iwhandle, scan->interval,
+ if (value[0] == SERVER_REQUIRES_REFRESH)
+ write_scan_params(scan->client, scan->iwhandle, scan->interval,
scan->window);
}
-static void ccc_written_cb(guint8 status, const guint8 *pdu,
- guint16 plen, gpointer user_data)
+static void ccc_written_cb(uint16_t att_ecode, void *user_data)
{
- struct bt_scpp *scan = user_data;
-
- if (status != 0) {
- error("Write Scan Refresh CCC failed: %s",
- att_ecode2str(status));
+ if (att_ecode != 0) {
+ error("Write Scan Refresh CCC failed: att_ecode %d", att_ecode);
return;
}
DBG("Scan Refresh: notification enabled");
-
- scan->refresh_cb_id = g_attrib_register(scan->attrib,
- ATT_OP_HANDLE_NOTIFY, scan->refresh_handle,
- refresh_value_cb, scan, NULL);
}
-static void write_ccc(struct bt_scpp *scan, GAttrib *attrib, uint16_t handle,
+static void refresh_discovered_cb(struct gatt_db_attribute *attrib,
void *user_data)
{
- uint8_t value[2];
-
- put_le16(GATT_CLIENT_CHARAC_CFG_NOTIF_BIT, value);
+ struct bt_scpp *scan = user_data;
+ bt_uuid_t uuid, refresh_uuid;
+ uint16_t value_handle;
- gatt_write_char(attrib, handle, value, sizeof(value), ccc_written_cb,
- user_data);
-}
+ gatt_db_attribute_get_char_data(attrib, NULL, &value_handle, NULL,
+ &uuid);
-static void discover_descriptor_cb(uint8_t status, GSList *descs,
- void *user_data)
-{
- struct bt_scpp *scan = user_data;
- struct gatt_desc *desc;
+ bt_uuid16_create(&refresh_uuid, SCAN_REFRESH_UUID);
- if (status != 0) {
- error("Discover descriptors failed: %s", att_ecode2str(status));
+ if (bt_uuid_cmp(&uuid, &refresh_uuid))
return;
- }
- /* There will be only one descriptor on list and it will be CCC */
- desc = descs->data;
+ scan->refresh_handle = value_handle;
+
+ DBG("Scan Refresh handle: 0x%04x", scan->refresh_handle);
- write_ccc(scan, scan->attrib, desc->handle, scan);
+ scan->refresh_cb_id = bt_gatt_client_register_notify(scan->client,
+ scan->refresh_handle, ccc_written_cb,
+ refresh_value_cb, scan, NULL);
}
-static void refresh_discovered_cb(uint8_t status, GSList *chars,
+static void iwin_discovered_cb(struct gatt_db_attribute *attrib,
void *user_data)
{
struct bt_scpp *scan = user_data;
- struct gatt_char *chr;
- uint16_t start, end;
- bt_uuid_t uuid;
+ bt_uuid_t uuid, iwin_uuid;
+ uint16_t value_handle;
- if (status) {
- error("Scan Refresh %s", att_ecode2str(status));
- return;
- }
+ gatt_db_attribute_get_char_data(attrib, NULL, &value_handle, NULL,
+ &uuid);
- if (!chars) {
- DBG("Scan Refresh not supported");
- return;
- }
-
- chr = chars->data;
-
- DBG("Scan Refresh handle: 0x%04x", chr->value_handle);
-
- start = chr->value_handle + 1;
- end = scan->primary->range.end;
-
- if (start > end)
- return;
-
- scan->refresh_handle = chr->value_handle;
-
- bt_uuid16_create(&uuid, GATT_CLIENT_CHARAC_CFG_UUID);
+ bt_uuid16_create(&iwin_uuid, SCAN_INTERVAL_WIN_UUID);
- gatt_discover_desc(scan->attrib, start, end, &uuid,
- discover_descriptor_cb, user_data);
-}
-
-static void iwin_discovered_cb(uint8_t status, GSList *chars, void *user_data)
-{
- struct bt_scpp *scan = user_data;
- struct gatt_char *chr;
-
- if (status) {
- error("Discover Scan Interval Window: %s",
- att_ecode2str(status));
+ if (bt_uuid_cmp(&uuid, &iwin_uuid))
return;
- }
- chr = chars->data;
- scan->iwhandle = chr->value_handle;
+ scan->iwhandle = value_handle;
DBG("Scan Interval Window handle: 0x%04x", scan->iwhandle);
- write_scan_params(scan->attrib, scan->iwhandle, scan->interval,
+ write_scan_params(scan->client, scan->iwhandle, scan->interval,
scan->window);
}
-bool bt_scpp_attach(struct bt_scpp *scan, void *attrib)
+bool bt_scpp_attach(struct bt_scpp *scan, struct bt_gatt_client *client)
{
- bt_uuid_t iwin_uuid, refresh_uuid;
+ struct gatt_db_attribute *attrib;
- if (!scan || scan->attrib || !scan->primary)
+ if (!scan || scan->client || !scan->service_handle)
return false;
- scan->attrib = g_attrib_ref(attrib);
+ scan->client = bt_gatt_client_ref(client);
+ scan->db = bt_gatt_client_get_db(client);
+ attrib = gatt_db_get_attribute(scan->db, scan->service_handle);
if (scan->iwhandle)
- write_scan_params(scan->attrib, scan->iwhandle, scan->interval,
+ write_scan_params(scan->client, scan->iwhandle, scan->interval,
scan->window);
- else {
- bt_uuid16_create(&iwin_uuid, SCAN_INTERVAL_WIN_UUID);
- gatt_discover_char(scan->attrib, scan->primary->range.start,
- scan->primary->range.end, &iwin_uuid,
- iwin_discovered_cb, scan);
- }
-
- if (scan->refresh_handle)
- scan->refresh_cb_id = g_attrib_register(scan->attrib,
- ATT_OP_HANDLE_NOTIFY, scan->refresh_handle,
- refresh_value_cb, scan, NULL);
- else {
- bt_uuid16_create(&refresh_uuid, SCAN_REFRESH_UUID);
- gatt_discover_char(scan->attrib, scan->primary->range.start,
- scan->primary->range.end, &refresh_uuid,
- refresh_discovered_cb, scan);
- }
+ else
+ gatt_db_service_foreach_char(attrib, iwin_discovered_cb, scan);
+
+ if (scan->refresh_handle) {
+ uint32_t id = bt_gatt_client_register_notify(scan->client,
+ scan->refresh_handle, ccc_written_cb,
+ refresh_value_cb, scan, NULL);
+ scan->refresh_cb_id = id;
+ } else
+ gatt_db_service_foreach_char(attrib, refresh_discovered_cb,
+ scan);
return true;
}
void bt_scpp_detach(struct bt_scpp *scan)
{
- if (!scan || !scan->attrib)
+ if (!scan || !scan->client)
return;
if (scan->refresh_cb_id > 0) {
- g_attrib_unregister(scan->attrib, scan->refresh_cb_id);
+ bt_gatt_client_unregister_notify(scan->client,
+ scan->refresh_cb_id);
scan->refresh_cb_id = 0;
}
- g_attrib_unref(scan->attrib);
- scan->attrib = NULL;
+ gatt_db_unref(scan->db);
+ bt_gatt_client_unref(scan->client);
+ scan->client = NULL;
}
bool bt_scpp_set_interval(struct bt_scpp *scan, uint16_t value)
diff --git a/android/scpp.h b/android/scpp.h
index 048fb9f..65e54c1 100644
--- a/android/scpp.h
+++ b/android/scpp.h
@@ -23,12 +23,12 @@
struct bt_scpp;
-struct bt_scpp *bt_scpp_new(void *primary);
+struct bt_scpp *bt_scpp_new(uint16_t service_handle);
struct bt_scpp *bt_scpp_ref(struct bt_scpp *scan);
void bt_scpp_unref(struct bt_scpp *scan);
-bool bt_scpp_attach(struct bt_scpp *scan, void *gatt);
+bool bt_scpp_attach(struct bt_scpp *scan, struct bt_gatt_client *client);
void bt_scpp_detach(struct bt_scpp *scan);
bool bt_scpp_set_interval(struct bt_scpp *scan, uint16_t value);
--
1.9.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* Re: [PATCH 18/28] android/scpp: Introduce bt_gatt_client
2015-04-01 16:40 ` [PATCH 18/28] android/scpp: Introduce bt_gatt_client Mariusz Skamra
@ 2015-04-02 15:34 ` Szymon Janc
0 siblings, 0 replies; 41+ messages in thread
From: Szymon Janc @ 2015-04-02 15:34 UTC (permalink / raw)
To: Mariusz Skamra; +Cc: linux-bluetooth, Mariusz Skamra
Hi Mariusz,
On Wednesday 01 of April 2015 18:40:34 Mariusz Skamra wrote:
> From: Mariusz Skamra <mariusz.skamra@gmail.com>
>
> This patch replaces gattrib with bt_gatt_client and strips glib
> dependencies. ---
> android/hog.c | 18 ++----
> android/scpp.c | 196
> +++++++++++++++++++++------------------------------------ android/scpp.h |
> 4 +-
> 3 files changed, 80 insertions(+), 138 deletions(-)
>
> diff --git a/android/hog.c b/android/hog.c
> index 71f8c50..78c1b26 100644
> --- a/android/hog.c
> +++ b/android/hog.c
> @@ -954,16 +954,16 @@ static void find_included_cb(struct gatt_db_attribute
> *attrib, void *user_data) DBG("included: handle %x", start_handle);
> }
>
> -static void hog_attach_scpp(struct bt_hog *hog, struct gatt_primary
> *primary) +static void hog_attach_scpp(struct bt_hog *hog, uint16_t
> service_handle) {
> if (hog->scpp) {
> - bt_scpp_attach(hog->scpp, hog->attrib);
> + bt_scpp_attach(hog->scpp, hog->client);
> return;
> }
>
> - hog->scpp = bt_scpp_new(primary);
> + hog->scpp = bt_scpp_new(service_handle);
> if (hog->scpp)
> - bt_scpp_attach(hog->scpp, hog->attrib);
> + bt_scpp_attach(hog->scpp, hog->client);
> }
>
> static void dis_notify(uint8_t source, uint16_t vendor, uint16_t product,
> @@ -1047,11 +1047,6 @@ static void primary_cb(uint8_t status, GSList
> *services, void *user_data) for (l = services; l; l = l->next) {
> primary = l->data;
>
> - if (strcmp(primary->uuid, SCAN_PARAMETERS_UUID) == 0) {
> - hog_attach_scpp(hog, primary);
> - continue;
> - }
> -
> if (strcmp(primary->uuid, BATTERY_UUID) == 0) {
> hog_attach_bas(hog, primary);
> }
> @@ -1074,8 +1069,7 @@ static void service_cb(struct gatt_db_attribute
> *attrib, void *user_data) if (!bt_uuid_strcmp(uuid, HOG_UUID))
> hog_attach_hog(hog, service_handle);
> else if (!bt_uuid_strcmp(uuid, SCAN_PARAMETERS_UUID))
> - /* TODO */
> - return;
> + hog_attach_scpp(hog, service_handle);
> else if (!bt_uuid_strcmp(uuid, DEVICE_INFORMATION_UUID))
> hog_attach_dis(hog, service_handle);
> else if (!bt_uuid_strcmp(uuid, BATTERY_UUID))
> @@ -1101,7 +1095,7 @@ bool bt_hog_attach(struct bt_hog *hog, void *gatt,
> void *client) }
>
> if (hog->scpp)
> - bt_scpp_attach(hog->scpp, gatt);
> + bt_scpp_attach(hog->scpp, hog->client);
>
> if (hog->dis)
> bt_dis_attach(hog->dis, hog->client);
> diff --git a/android/scpp.c b/android/scpp.c
> index a28fbb6..37bd82e 100644
> --- a/android/scpp.c
> +++ b/android/scpp.c
> @@ -26,23 +26,16 @@
> #include <config.h>
> #endif
>
> -#include <stdbool.h>
> -#include <errno.h>
> -
> -#include <glib.h>
> -
> #include "src/log.h"
>
> #include "lib/bluetooth.h"
> -#include "lib/sdp.h"
> #include "lib/uuid.h"
>
> #include "src/shared/util.h"
> #include "src/shared/queue.h"
> -
> -#include "attrib/att.h"
> -#include "attrib/gattrib.h"
> -#include "attrib/gatt.h"
> +#include "src/shared/att.h"
> +#include "src/shared/gatt-db.h"
> +#include "src/shared/gatt-client.h"
>
> #include "android/scpp.h"
>
> @@ -55,36 +48,37 @@
>
> struct bt_scpp {
> int ref_count;
> - GAttrib *attrib;
> - struct gatt_primary *primary;
> + uint16_t service_handle;
> uint16_t interval;
> uint16_t window;
> uint16_t iwhandle;
> uint16_t refresh_handle;
> - guint refresh_cb_id;
> + uint32_t refresh_cb_id;
> + struct bt_gatt_client *client;
> + struct gatt_db *db;
> };
>
> static void scpp_free(struct bt_scpp *scan)
> {
> bt_scpp_detach(scan);
>
> - g_free(scan->primary);
> - g_free(scan);
> + free(scan);
> }
>
> -struct bt_scpp *bt_scpp_new(void *primary)
> +struct bt_scpp *bt_scpp_new(uint16_t service_handle)
> {
> struct bt_scpp *scan;
>
> - scan = g_try_new0(struct bt_scpp, 1);
> + if (!service_handle)
> + return NULL;
> +
> + scan = new0(struct bt_scpp, 1);
> if (!scan)
> return NULL;
>
> scan->interval = SCAN_INTERVAL;
> scan->window = SCAN_WINDOW;
> -
> - if (primary)
> - scan->primary = g_memdup(primary, sizeof(*scan->primary));
> + scan->service_handle = service_handle;
>
> return bt_scpp_ref(scan);
> }
> @@ -110,7 +104,7 @@ void bt_scpp_unref(struct bt_scpp *scan)
> scpp_free(scan);
> }
>
> -static void write_scan_params(GAttrib *attrib, uint16_t handle,
> +static void write_scan_params(struct bt_gatt_client *client, uint16_t
> handle, uint16_t interval, uint16_t window)
> {
> uint8_t value[4];
> @@ -118,168 +112,122 @@ static void write_scan_params(GAttrib *attrib,
> uint16_t handle, put_le16(interval, &value[0]);
> put_le16(window, &value[2]);
>
> - gatt_write_cmd(attrib, handle, value, sizeof(value), NULL, NULL);
> + bt_gatt_client_write_without_response(client, handle, NULL, value,
> + sizeof(value));
> }
>
> -static void refresh_value_cb(const uint8_t *pdu, uint16_t len,
> - gpointer user_data)
> +static void refresh_value_cb(uint16_t value_handle, const uint8_t *value,
> + uint16_t length, void *user_data)
> {
> struct bt_scpp *scan = user_data;
>
> - DBG("Server requires refresh: %d", pdu[3]);
> + DBG("Server requires refresh: %d", value[0]);
>
> - if (pdu[3] == SERVER_REQUIRES_REFRESH)
> - write_scan_params(scan->attrib, scan->iwhandle, scan->interval,
> + if (value[0] == SERVER_REQUIRES_REFRESH)
> + write_scan_params(scan->client, scan->iwhandle, scan->interval,
> scan->window);
> }
>
> -static void ccc_written_cb(guint8 status, const guint8 *pdu,
> - guint16 plen, gpointer user_data)
> +static void ccc_written_cb(uint16_t att_ecode, void *user_data)
> {
> - struct bt_scpp *scan = user_data;
> -
> - if (status != 0) {
> - error("Write Scan Refresh CCC failed: %s",
> - att_ecode2str(status));
> + if (att_ecode != 0) {
> + error("Write Scan Refresh CCC failed: att_ecode %d", att_ecode);
> return;
> }
>
> DBG("Scan Refresh: notification enabled");
> -
> - scan->refresh_cb_id = g_attrib_register(scan->attrib,
> - ATT_OP_HANDLE_NOTIFY, scan->refresh_handle,
> - refresh_value_cb, scan, NULL);
> }
>
> -static void write_ccc(struct bt_scpp *scan, GAttrib *attrib, uint16_t
> handle, +static void refresh_discovered_cb(struct gatt_db_attribute
> *attrib, void *user_data)
> {
> - uint8_t value[2];
> -
> - put_le16(GATT_CLIENT_CHARAC_CFG_NOTIF_BIT, value);
> + struct bt_scpp *scan = user_data;
> + bt_uuid_t uuid, refresh_uuid;
> + uint16_t value_handle;
>
> - gatt_write_char(attrib, handle, value, sizeof(value), ccc_written_cb,
> - user_data);
> -}
> + gatt_db_attribute_get_char_data(attrib, NULL, &value_handle, NULL,
> + &uuid);
>
> -static void discover_descriptor_cb(uint8_t status, GSList *descs,
> - void *user_data)
> -{
> - struct bt_scpp *scan = user_data;
> - struct gatt_desc *desc;
> + bt_uuid16_create(&refresh_uuid, SCAN_REFRESH_UUID);
>
> - if (status != 0) {
> - error("Discover descriptors failed: %s", att_ecode2str(status));
> + if (bt_uuid_cmp(&uuid, &refresh_uuid))
> return;
> - }
>
> - /* There will be only one descriptor on list and it will be CCC */
> - desc = descs->data;
> + scan->refresh_handle = value_handle;
> +
> + DBG("Scan Refresh handle: 0x%04x", scan->refresh_handle);
>
> - write_ccc(scan, scan->attrib, desc->handle, scan);
> + scan->refresh_cb_id = bt_gatt_client_register_notify(scan->client,
> + scan->refresh_handle, ccc_written_cb,
> + refresh_value_cb, scan, NULL);
> }
>
> -static void refresh_discovered_cb(uint8_t status, GSList *chars,
> +static void iwin_discovered_cb(struct gatt_db_attribute *attrib,
> void *user_data)
> {
> struct bt_scpp *scan = user_data;
> - struct gatt_char *chr;
> - uint16_t start, end;
> - bt_uuid_t uuid;
> + bt_uuid_t uuid, iwin_uuid;
> + uint16_t value_handle;
>
> - if (status) {
> - error("Scan Refresh %s", att_ecode2str(status));
> - return;
> - }
> + gatt_db_attribute_get_char_data(attrib, NULL, &value_handle, NULL,
> + &uuid);
>
> - if (!chars) {
> - DBG("Scan Refresh not supported");
> - return;
> - }
> -
> - chr = chars->data;
> -
> - DBG("Scan Refresh handle: 0x%04x", chr->value_handle);
> -
> - start = chr->value_handle + 1;
> - end = scan->primary->range.end;
> -
> - if (start > end)
> - return;
> -
> - scan->refresh_handle = chr->value_handle;
> -
> - bt_uuid16_create(&uuid, GATT_CLIENT_CHARAC_CFG_UUID);
> + bt_uuid16_create(&iwin_uuid, SCAN_INTERVAL_WIN_UUID);
>
> - gatt_discover_desc(scan->attrib, start, end, &uuid,
> - discover_descriptor_cb, user_data);
> -}
> -
> -static void iwin_discovered_cb(uint8_t status, GSList *chars, void
> *user_data) -{
> - struct bt_scpp *scan = user_data;
> - struct gatt_char *chr;
> -
> - if (status) {
> - error("Discover Scan Interval Window: %s",
> - att_ecode2str(status));
> + if (bt_uuid_cmp(&uuid, &iwin_uuid))
> return;
> - }
>
> - chr = chars->data;
> - scan->iwhandle = chr->value_handle;
> + scan->iwhandle = value_handle;
>
> DBG("Scan Interval Window handle: 0x%04x", scan->iwhandle);
>
> - write_scan_params(scan->attrib, scan->iwhandle, scan->interval,
> + write_scan_params(scan->client, scan->iwhandle, scan->interval,
> scan->window);
> }
>
> -bool bt_scpp_attach(struct bt_scpp *scan, void *attrib)
> +bool bt_scpp_attach(struct bt_scpp *scan, struct bt_gatt_client *client)
> {
> - bt_uuid_t iwin_uuid, refresh_uuid;
> + struct gatt_db_attribute *attrib;
>
> - if (!scan || scan->attrib || !scan->primary)
> + if (!scan || scan->client || !scan->service_handle)
> return false;
>
> - scan->attrib = g_attrib_ref(attrib);
> + scan->client = bt_gatt_client_ref(client);
> + scan->db = bt_gatt_client_get_db(client);
> + attrib = gatt_db_get_attribute(scan->db, scan->service_handle);
>
> if (scan->iwhandle)
> - write_scan_params(scan->attrib, scan->iwhandle, scan->interval,
> + write_scan_params(scan->client, scan->iwhandle, scan->interval,
> scan->window);
> - else {
> - bt_uuid16_create(&iwin_uuid, SCAN_INTERVAL_WIN_UUID);
> - gatt_discover_char(scan->attrib, scan->primary->range.start,
> - scan->primary->range.end, &iwin_uuid,
> - iwin_discovered_cb, scan);
> - }
> -
> - if (scan->refresh_handle)
> - scan->refresh_cb_id = g_attrib_register(scan->attrib,
> - ATT_OP_HANDLE_NOTIFY, scan->refresh_handle,
> - refresh_value_cb, scan, NULL);
> - else {
> - bt_uuid16_create(&refresh_uuid, SCAN_REFRESH_UUID);
> - gatt_discover_char(scan->attrib, scan->primary->range.start,
> - scan->primary->range.end, &refresh_uuid,
> - refresh_discovered_cb, scan);
> - }
> + else
> + gatt_db_service_foreach_char(attrib, iwin_discovered_cb, scan);
> +
> + if (scan->refresh_handle) {
> + uint32_t id = bt_gatt_client_register_notify(scan->client,
> + scan->refresh_handle, ccc_written_cb,
> + refresh_value_cb, scan, NULL);
> + scan->refresh_cb_id = id;
> + } else
> + gatt_db_service_foreach_char(attrib, refresh_discovered_cb,
> + scan);
>
> return true;
> }
>
> void bt_scpp_detach(struct bt_scpp *scan)
> {
> - if (!scan || !scan->attrib)
> + if (!scan || !scan->client)
> return;
>
> if (scan->refresh_cb_id > 0) {
> - g_attrib_unregister(scan->attrib, scan->refresh_cb_id);
> + bt_gatt_client_unregister_notify(scan->client,
> + scan->refresh_cb_id);
> scan->refresh_cb_id = 0;
> }
>
> - g_attrib_unref(scan->attrib);
> - scan->attrib = NULL;
> + gatt_db_unref(scan->db);
Missing scan->db = NULL; ?
> + bt_gatt_client_unref(scan->client);
> + scan->client = NULL;
> }
>
> bool bt_scpp_set_interval(struct bt_scpp *scan, uint16_t value)
> diff --git a/android/scpp.h b/android/scpp.h
> index 048fb9f..65e54c1 100644
> --- a/android/scpp.h
> +++ b/android/scpp.h
> @@ -23,12 +23,12 @@
>
> struct bt_scpp;
>
> -struct bt_scpp *bt_scpp_new(void *primary);
> +struct bt_scpp *bt_scpp_new(uint16_t service_handle);
>
> struct bt_scpp *bt_scpp_ref(struct bt_scpp *scan);
> void bt_scpp_unref(struct bt_scpp *scan);
>
> -bool bt_scpp_attach(struct bt_scpp *scan, void *gatt);
> +bool bt_scpp_attach(struct bt_scpp *scan, struct bt_gatt_client *client);
> void bt_scpp_detach(struct bt_scpp *scan);
>
> bool bt_scpp_set_interval(struct bt_scpp *scan, uint16_t value);
--
BR
Szymon Janc
^ permalink raw reply [flat|nested] 41+ messages in thread
* [PATCH 19/28] android/scpp: Merge refresh_discovered_cb with iwin_discovered_cb
2015-04-01 16:40 [PATCH 00/28] android/hog Introduce bt_gatt_client Mariusz Skamra
` (17 preceding siblings ...)
2015-04-01 16:40 ` [PATCH 18/28] android/scpp: Introduce bt_gatt_client Mariusz Skamra
@ 2015-04-01 16:40 ` Mariusz Skamra
2015-04-01 16:40 ` [PATCH 20/28] android/bas: Remove tracking pending gatt operations Mariusz Skamra
` (8 subsequent siblings)
27 siblings, 0 replies; 41+ messages in thread
From: Mariusz Skamra @ 2015-04-01 16:40 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Mariusz Skamra
This two callbacks do the same work when used with
gatt_db_service_foreach_char, because search for characteristic with
specificis not performed, so they can be merged.
---
android/scpp.c | 56 ++++++++++++++++++++------------------------------------
1 file changed, 20 insertions(+), 36 deletions(-)
diff --git a/android/scpp.c b/android/scpp.c
index 37bd82e..bf0a3db 100644
--- a/android/scpp.c
+++ b/android/scpp.c
@@ -138,51 +138,36 @@ static void ccc_written_cb(uint16_t att_ecode, void *user_data)
DBG("Scan Refresh: notification enabled");
}
-static void refresh_discovered_cb(struct gatt_db_attribute *attrib,
- void *user_data)
+static void characteristic_cb(struct gatt_db_attribute *attrib, void *user_data)
{
struct bt_scpp *scan = user_data;
- bt_uuid_t uuid, refresh_uuid;
+ bt_uuid_t uuid, iwin_uuid, refresh_uuid;
uint16_t value_handle;
gatt_db_attribute_get_char_data(attrib, NULL, &value_handle, NULL,
&uuid);
-
+ bt_uuid16_create(&iwin_uuid, SCAN_INTERVAL_WIN_UUID);
bt_uuid16_create(&refresh_uuid, SCAN_REFRESH_UUID);
- if (bt_uuid_cmp(&uuid, &refresh_uuid))
- return;
+ if (!scan->iwhandle && !bt_uuid_cmp(&uuid, &iwin_uuid)) {
+ scan->iwhandle = value_handle;
- scan->refresh_handle = value_handle;
+ DBG("Scan Interval Window handle: 0x%04x", scan->iwhandle);
- DBG("Scan Refresh handle: 0x%04x", scan->refresh_handle);
+ write_scan_params(scan->client, scan->iwhandle, scan->interval,
+ scan->window);
+ }
- scan->refresh_cb_id = bt_gatt_client_register_notify(scan->client,
- scan->refresh_handle, ccc_written_cb,
+ if (!scan->refresh_handle && !bt_uuid_cmp(&uuid, &refresh_uuid)) {
+ uint32_t id = bt_gatt_client_register_notify(scan->client,
+ value_handle, ccc_written_cb,
refresh_value_cb, scan, NULL);
-}
-
-static void iwin_discovered_cb(struct gatt_db_attribute *attrib,
- void *user_data)
-{
- struct bt_scpp *scan = user_data;
- bt_uuid_t uuid, iwin_uuid;
- uint16_t value_handle;
- gatt_db_attribute_get_char_data(attrib, NULL, &value_handle, NULL,
- &uuid);
-
- bt_uuid16_create(&iwin_uuid, SCAN_INTERVAL_WIN_UUID);
-
- if (bt_uuid_cmp(&uuid, &iwin_uuid))
- return;
-
- scan->iwhandle = value_handle;
+ DBG("Scan Refresh handle: 0x%04x", value_handle);
- DBG("Scan Interval Window handle: 0x%04x", scan->iwhandle);
-
- write_scan_params(scan->client, scan->iwhandle, scan->interval,
- scan->window);
+ scan->refresh_handle = value_handle;
+ scan->refresh_cb_id = id;
+ }
}
bool bt_scpp_attach(struct bt_scpp *scan, struct bt_gatt_client *client)
@@ -199,17 +184,16 @@ bool bt_scpp_attach(struct bt_scpp *scan, struct bt_gatt_client *client)
if (scan->iwhandle)
write_scan_params(scan->client, scan->iwhandle, scan->interval,
scan->window);
- else
- gatt_db_service_foreach_char(attrib, iwin_discovered_cb, scan);
if (scan->refresh_handle) {
uint32_t id = bt_gatt_client_register_notify(scan->client,
scan->refresh_handle, ccc_written_cb,
refresh_value_cb, scan, NULL);
scan->refresh_cb_id = id;
- } else
- gatt_db_service_foreach_char(attrib, refresh_discovered_cb,
- scan);
+ }
+
+ if (!scan->iwhandle || !scan->refresh_handle)
+ gatt_db_service_foreach_char(attrib, characteristic_cb, scan);
return true;
}
--
1.9.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [PATCH 20/28] android/bas: Remove tracking pending gatt operations
2015-04-01 16:40 [PATCH 00/28] android/hog Introduce bt_gatt_client Mariusz Skamra
` (18 preceding siblings ...)
2015-04-01 16:40 ` [PATCH 19/28] android/scpp: Merge refresh_discovered_cb with iwin_discovered_cb Mariusz Skamra
@ 2015-04-01 16:40 ` Mariusz Skamra
2015-04-01 16:40 ` [PATCH 21/28] android/bas: Start using bt_gatt_client Mariusz Skamra
` (7 subsequent siblings)
27 siblings, 0 replies; 41+ messages in thread
From: Mariusz Skamra @ 2015-04-01 16:40 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Mariusz Skamra
Since the use of bt_gatt_client there is no need to queue pending gatt
operations. bt_gatt_client already keeps track on that, so that
on bt_gatt_client_unref the queue of pending requests is destroyed.
---
android/bas.c | 166 ++++------------------------------------------------------
1 file changed, 9 insertions(+), 157 deletions(-)
diff --git a/android/bas.c b/android/bas.c
index dcbf9de..c5de3b1 100644
--- a/android/bas.c
+++ b/android/bas.c
@@ -55,28 +55,13 @@ struct bt_bas {
uint16_t handle;
uint16_t ccc_handle;
guint id;
- struct queue *gatt_op;
};
-struct gatt_request {
- unsigned int id;
- struct bt_bas *bas;
- void *user_data;
-};
-
-static void destroy_gatt_req(struct gatt_request *req)
-{
- queue_remove(req->bas->gatt_op, req);
- bt_bas_unref(req->bas);
- free(req);
-}
-
static void bas_free(struct bt_bas *bas)
{
bt_bas_detach(bas);
g_free(bas->primary);
- queue_destroy(bas->gatt_op, (void *) destroy_gatt_req);
g_free(bas);
}
@@ -88,12 +73,6 @@ struct bt_bas *bt_bas_new(void *primary)
if (!bas)
return NULL;
- bas->gatt_op = queue_new();
- if (!bas->gatt_op) {
- bas_free(bas);
- return NULL;
- }
-
if (primary)
bas->primary = g_memdup(primary, sizeof(*bas->primary));
@@ -121,114 +100,6 @@ void bt_bas_unref(struct bt_bas *bas)
bas_free(bas);
}
-static struct gatt_request *create_request(struct bt_bas *bas,
- void *user_data)
-{
- struct gatt_request *req;
-
- req = new0(struct gatt_request, 1);
- if (!req)
- return NULL;
-
- req->user_data = user_data;
- req->bas = bt_bas_ref(bas);
-
- return req;
-}
-
-static bool set_and_store_gatt_req(struct bt_bas *bas,
- struct gatt_request *req,
- unsigned int id)
-{
- req->id = id;
- return queue_push_head(bas->gatt_op, req);
-}
-
-static void write_char(struct bt_bas *bas, GAttrib *attrib, uint16_t handle,
- const uint8_t *value, size_t vlen,
- GAttribResultFunc func,
- gpointer user_data)
-{
- struct gatt_request *req;
- unsigned int id;
-
- req = create_request(bas, user_data);
- if (!req)
- return;
-
- id = gatt_write_char(attrib, handle, value, vlen, func, req);
-
- if (set_and_store_gatt_req(bas, req, id))
- return;
-
- error("bas: Could not write characteristic");
- g_attrib_cancel(attrib, id);
- free(req);
-
-}
-
-static void read_char(struct bt_bas *bas, GAttrib *attrib, uint16_t handle,
- GAttribResultFunc func, gpointer user_data)
-{
- struct gatt_request *req;
- unsigned int id;
-
- req = create_request(bas, user_data);
- if (!req)
- return;
-
- id = gatt_read_char(attrib, handle, func, req);
-
- if (set_and_store_gatt_req(bas, req, id))
- return;
-
- error("bas: Could not read characteristic");
- g_attrib_cancel(attrib, id);
- free(req);
-}
-
-static void discover_char(struct bt_bas *bas, GAttrib *attrib,
- uint16_t start, uint16_t end,
- bt_uuid_t *uuid, gatt_cb_t func,
- gpointer user_data)
-{
- struct gatt_request *req;
- unsigned int id;
-
- req = create_request(bas, user_data);
- if (!req)
- return;
-
- id = gatt_discover_char(attrib, start, end, uuid, func, req);
-
- if (set_and_store_gatt_req(bas, req, id))
- return;
-
- error("bas: Could not discover characteristic");
- g_attrib_cancel(attrib, id);
- free(req);
-}
-
-static void discover_desc(struct bt_bas *bas, GAttrib *attrib,
- uint16_t start, uint16_t end, bt_uuid_t *uuid,
- gatt_cb_t func, gpointer user_data)
-{
- struct gatt_request *req;
- unsigned int id;
-
- req = create_request(bas, user_data);
- if (!req)
- return;
-
- id = gatt_discover_desc(attrib, start, end, uuid, func, req);
- if (set_and_store_gatt_req(bas, req, id))
- return;
-
- error("bas: Could not discover descriptor");
- g_attrib_cancel(attrib, id);
- free(req);
-}
-
static void notification_cb(const guint8 *pdu, guint16 len, gpointer user_data)
{
DBG("Battery Level at %u", pdu[ATT_NOTIFICATION_HEADER_SIZE]);
@@ -243,10 +114,7 @@ static void read_value_cb(guint8 status, const guint8 *pdu, guint16 len,
static void ccc_written_cb(guint8 status, const guint8 *pdu,
guint16 plen, gpointer user_data)
{
- struct gatt_request *req = user_data;
- struct bt_bas *bas = req->user_data;
-
- destroy_gatt_req(req);
+ struct bt_bas *bas = user_data;
if (status != 0) {
error("Write Scan Refresh CCC failed: %s",
@@ -268,17 +136,14 @@ static void write_ccc(struct bt_bas *bas, GAttrib *attrib, uint16_t handle,
put_le16(GATT_CLIENT_CHARAC_CFG_NOTIF_BIT, value);
- write_char(bas, attrib, handle, value, sizeof(value), ccc_written_cb,
+ gatt_write_char(attrib, handle, value, sizeof(value), ccc_written_cb,
user_data);
}
static void ccc_read_cb(guint8 status, const guint8 *pdu, guint16 len,
gpointer user_data)
{
- struct gatt_request *req = user_data;
- struct bt_bas *bas = req->user_data;
-
- destroy_gatt_req(req);
+ struct bt_bas *bas = user_data;
if (status != 0) {
error("Error reading CCC value: %s", att_ecode2str(status));
@@ -291,12 +156,9 @@ static void ccc_read_cb(guint8 status, const guint8 *pdu, guint16 len,
static void discover_descriptor_cb(uint8_t status, GSList *descs,
void *user_data)
{
- struct gatt_request *req = user_data;
- struct bt_bas *bas = req->user_data;
+ struct bt_bas *bas = user_data;
struct gatt_desc *desc;
- destroy_gatt_req(req);
-
if (status != 0) {
error("Discover descriptors failed: %s", att_ecode2str(status));
return;
@@ -306,19 +168,16 @@ static void discover_descriptor_cb(uint8_t status, GSList *descs,
desc = descs->data;
bas->ccc_handle = desc->handle;
- read_char(bas, bas->attrib, desc->handle, ccc_read_cb, bas);
+ gatt_read_char(bas->attrib, desc->handle, ccc_read_cb, bas);
}
static void bas_discovered_cb(uint8_t status, GSList *chars, void *user_data)
{
- struct gatt_request *req = user_data;
- struct bt_bas *bas = req->user_data;
+ struct bt_bas *bas = user_data;
struct gatt_char *chr;
uint16_t start, end;
bt_uuid_t uuid;
- destroy_gatt_req(req);
-
if (status) {
error("Battery: %s", att_ecode2str(status));
return;
@@ -329,14 +188,14 @@ static void bas_discovered_cb(uint8_t status, GSList *chars, void *user_data)
DBG("Battery handle: 0x%04x", bas->handle);
- read_char(bas, bas->attrib, bas->handle, read_value_cb, bas);
+ gatt_read_char(bas->attrib, bas->handle, read_value_cb, bas);
start = chr->value_handle + 1;
end = bas->primary->range.end;
bt_uuid16_create(&uuid, GATT_CLIENT_CHARAC_CFG_UUID);
- discover_desc(bas, bas->attrib, start, end, &uuid,
+ gatt_discover_desc(bas->attrib, start, end, &uuid,
discover_descriptor_cb, bas);
}
@@ -350,19 +209,13 @@ bool bt_bas_attach(struct bt_bas *bas, void *attrib)
if (bas->handle > 0)
return true;
- discover_char(bas, bas->attrib, bas->primary->range.start,
+ gatt_discover_char(bas->attrib, bas->primary->range.start,
bas->primary->range.end, NULL,
bas_discovered_cb, bas);
return true;
}
-static void cancel_gatt_req(struct gatt_request *req)
-{
- if (g_attrib_cancel(req->bas->attrib, req->id))
- destroy_gatt_req(req);
-}
-
void bt_bas_detach(struct bt_bas *bas)
{
if (!bas || !bas->attrib)
@@ -373,7 +226,6 @@ void bt_bas_detach(struct bt_bas *bas)
bas->id = 0;
}
- queue_foreach(bas->gatt_op, (void *) cancel_gatt_req, NULL);
g_attrib_unref(bas->attrib);
bas->attrib = NULL;
}
--
1.9.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [PATCH 21/28] android/bas: Start using bt_gatt_client
2015-04-01 16:40 [PATCH 00/28] android/hog Introduce bt_gatt_client Mariusz Skamra
` (19 preceding siblings ...)
2015-04-01 16:40 ` [PATCH 20/28] android/bas: Remove tracking pending gatt operations Mariusz Skamra
@ 2015-04-01 16:40 ` Mariusz Skamra
2015-04-02 15:37 ` Szymon Janc
2015-04-01 16:40 ` [PATCH 22/28] android/hog: Strip btio dependencies Mariusz Skamra
` (6 subsequent siblings)
27 siblings, 1 reply; 41+ messages in thread
From: Mariusz Skamra @ 2015-04-01 16:40 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Mariusz Skamra
This patch replaces gattrib with bt_gatt_client and strips glib dependencies.
---
android/bas.c | 162 ++++++++++++++++++----------------------------------------
android/bas.h | 4 +-
android/hog.c | 40 ++-------------
3 files changed, 57 insertions(+), 149 deletions(-)
diff --git a/android/bas.c b/android/bas.c
index c5de3b1..3b641eb 100644
--- a/android/bas.c
+++ b/android/bas.c
@@ -28,53 +28,47 @@
#include <stdbool.h>
#include <errno.h>
-#include <glib.h>
-
#include "src/log.h"
#include "lib/bluetooth.h"
-#include "lib/sdp.h"
#include "lib/uuid.h"
#include "src/shared/util.h"
#include "src/shared/queue.h"
-
-#include "attrib/gattrib.h"
-#include "attrib/att.h"
-#include "attrib/gatt.h"
+#include "src/shared/att.h"
+#include "src/shared/gatt-db.h"
+#include "src/shared/gatt-client.h"
#include "android/bas.h"
-#define ATT_NOTIFICATION_HEADER_SIZE 3
-#define ATT_READ_RESPONSE_HEADER_SIZE 1
-
struct bt_bas {
int ref_count;
- GAttrib *attrib;
- struct gatt_primary *primary;
- uint16_t handle;
- uint16_t ccc_handle;
- guint id;
+ uint16_t service_handle; /* Battery service start handle */
+ uint16_t handle; /* Battery level value handle */
+ uint32_t id;
+ struct bt_gatt_client *client;
+ struct gatt_db *db;
};
static void bas_free(struct bt_bas *bas)
{
bt_bas_detach(bas);
- g_free(bas->primary);
- g_free(bas);
+ free(bas);
}
-struct bt_bas *bt_bas_new(void *primary)
+struct bt_bas *bt_bas_new(uint16_t service_handle)
{
struct bt_bas *bas;
- bas = g_try_new0(struct bt_bas, 1);
+ if (!service_handle)
+ return NULL;
+
+ bas = new0(struct bt_bas, 1);
if (!bas)
return NULL;
- if (primary)
- bas->primary = g_memdup(primary, sizeof(*bas->primary));
+ bas->service_handle = service_handle;
return bt_bas_ref(bas);
}
@@ -100,132 +94,76 @@ void bt_bas_unref(struct bt_bas *bas)
bas_free(bas);
}
-static void notification_cb(const guint8 *pdu, guint16 len, gpointer user_data)
-{
- DBG("Battery Level at %u", pdu[ATT_NOTIFICATION_HEADER_SIZE]);
-}
-
-static void read_value_cb(guint8 status, const guint8 *pdu, guint16 len,
- gpointer user_data)
-{
- DBG("Battery Level at %u", pdu[ATT_READ_RESPONSE_HEADER_SIZE]);
-}
-
-static void ccc_written_cb(guint8 status, const guint8 *pdu,
- guint16 plen, gpointer user_data)
+static void notification_cb(uint16_t value_handle, const uint8_t *value,
+ uint16_t length, void *user_data)
{
- struct bt_bas *bas = user_data;
-
- if (status != 0) {
- error("Write Scan Refresh CCC failed: %s",
- att_ecode2str(status));
- return;
- }
-
- DBG("Battery Level: notification enabled");
-
- bas->id = g_attrib_register(bas->attrib, ATT_OP_HANDLE_NOTIFY,
- bas->handle, notification_cb, bas,
- NULL);
+ DBG("Battery Level at %u", value[0]);
}
-static void write_ccc(struct bt_bas *bas, GAttrib *attrib, uint16_t handle,
- void *user_data)
+static void read_value_cb(bool success, uint8_t att_ecode, const uint8_t *value,
+ uint16_t length, void *user_data)
{
- uint8_t value[2];
+ if (!success)
+ error("Read battery level failed: att_ecode %d", att_ecode);
- put_le16(GATT_CLIENT_CHARAC_CFG_NOTIF_BIT, value);
-
- gatt_write_char(attrib, handle, value, sizeof(value), ccc_written_cb,
- user_data);
+ DBG("Battery Level at %u", value[0]);
}
-static void ccc_read_cb(guint8 status, const guint8 *pdu, guint16 len,
- gpointer user_data)
+static void ccc_written_cb(uint16_t att_ecode, void *user_data)
{
- struct bt_bas *bas = user_data;
-
- if (status != 0) {
- error("Error reading CCC value: %s", att_ecode2str(status));
- return;
- }
-
- write_ccc(bas, bas->attrib, bas->ccc_handle, bas);
-}
-
-static void discover_descriptor_cb(uint8_t status, GSList *descs,
- void *user_data)
-{
- struct bt_bas *bas = user_data;
- struct gatt_desc *desc;
-
- if (status != 0) {
- error("Discover descriptors failed: %s", att_ecode2str(status));
- return;
- }
-
- /* There will be only one descriptor on list and it will be CCC */
- desc = descs->data;
- bas->ccc_handle = desc->handle;
-
- gatt_read_char(bas->attrib, desc->handle, ccc_read_cb, bas);
+ DBG("Battery Level: notification enabled");
}
-static void bas_discovered_cb(uint8_t status, GSList *chars, void *user_data)
+static void bas_discovered_cb(struct gatt_db_attribute *attrib, void *user_data)
{
struct bt_bas *bas = user_data;
- struct gatt_char *chr;
- uint16_t start, end;
+ uint16_t value_handle;
bt_uuid_t uuid;
- if (status) {
- error("Battery: %s", att_ecode2str(status));
- return;
- }
+ gatt_db_attribute_get_char_data(attrib, NULL, &value_handle,
+ NULL, &uuid);
- chr = chars->data;
- bas->handle = chr->value_handle;
+ bas->handle = value_handle;
DBG("Battery handle: 0x%04x", bas->handle);
- gatt_read_char(bas->attrib, bas->handle, read_value_cb, bas);
-
- start = chr->value_handle + 1;
- end = bas->primary->range.end;
+ bt_gatt_client_read_value(bas->client, bas->handle, read_value_cb,
+ bas, NULL);
- bt_uuid16_create(&uuid, GATT_CLIENT_CHARAC_CFG_UUID);
+ bas->id = bt_gatt_client_register_notify(bas->client, bas->handle,
+ ccc_written_cb, notification_cb, bas, NULL);
- gatt_discover_desc(bas->attrib, start, end, &uuid,
- discover_descriptor_cb, bas);
+ /* TODO Characteristic Presentation Format shall be read */
}
-bool bt_bas_attach(struct bt_bas *bas, void *attrib)
+bool bt_bas_attach(struct bt_bas *bas, struct bt_gatt_client *client)
{
- if (!bas || bas->attrib || !bas->primary)
- return false;
+ struct gatt_db_attribute *attrib;
- bas->attrib = g_attrib_ref(attrib);
+ if (!bas || bas->client || !bas->service_handle)
+ return false;
- if (bas->handle > 0)
- return true;
+ bas->client = bt_gatt_client_ref(client);
+ bas->db = bt_gatt_client_get_db(client);
+ attrib = gatt_db_get_attribute(bas->db, bas->service_handle);
- gatt_discover_char(bas->attrib, bas->primary->range.start,
- bas->primary->range.end, NULL,
- bas_discovered_cb, bas);
+ if (!bas->handle)
+ gatt_db_service_foreach_char(attrib, bas_discovered_cb, bas);
return true;
}
void bt_bas_detach(struct bt_bas *bas)
{
- if (!bas || !bas->attrib)
+ if (!bas || !bas->client)
return;
- if (bas->id > 0) {
- g_attrib_unregister(bas->attrib, bas->id);
+ if (bas->id) {
+ bt_gatt_client_unregister_notify(bas->client, bas->id);
bas->id = 0;
}
- g_attrib_unref(bas->attrib);
- bas->attrib = NULL;
+ gatt_db_unref(bas->db);
+ bt_gatt_client_unref(bas->client);
+ bas->client = NULL;
}
diff --git a/android/bas.h b/android/bas.h
index 3e175b5..ce903e3 100644
--- a/android/bas.h
+++ b/android/bas.h
@@ -23,10 +23,10 @@
struct bt_bas;
-struct bt_bas *bt_bas_new(void *primary);
+struct bt_bas *bt_bas_new(uint16_t service_handle);
struct bt_bas *bt_bas_ref(struct bt_bas *bas);
void bt_bas_unref(struct bt_bas *bas);
-bool bt_bas_attach(struct bt_bas *bas, void *gatt);
+bool bt_bas_attach(struct bt_bas *bas, struct bt_gatt_client *client);
void bt_bas_detach(struct bt_bas *bas);
diff --git a/android/hog.c b/android/hog.c
index 78c1b26..4565e86 100644
--- a/android/hog.c
+++ b/android/hog.c
@@ -990,15 +990,15 @@ static void hog_attach_dis(struct bt_hog *hog, uint16_t service_handle)
}
}
-static void hog_attach_bas(struct bt_hog *hog, struct gatt_primary *primary)
+static void hog_attach_bas(struct bt_hog *hog, uint16_t service_handle)
{
struct bt_bas *instance;
- instance = bt_bas_new(primary);
+ instance = bt_bas_new(service_handle);
if (!instance)
return;
- bt_bas_attach(instance, hog->attrib);
+ bt_bas_attach(instance, hog->client);
queue_push_head(hog->bas, instance);
}
@@ -1025,34 +1025,6 @@ static void hog_attach_hog(struct bt_hog *hog, uint16_t service_handle)
queue_push_tail(hog->instances, instance);
}
-static void primary_cb(uint8_t status, GSList *services, void *user_data)
-{
- struct bt_hog *hog = user_data;
- struct gatt_primary *primary;
- GSList *l;
-
- DBG("");
-
- if (status) {
- const char *str = att_ecode2str(status);
- DBG("Discover primary failed: %s", str);
- return;
- }
-
- if (!services) {
- DBG("No primary service found");
- return;
- }
-
- for (l = services; l; l = l->next) {
- primary = l->data;
-
- if (strcmp(primary->uuid, BATTERY_UUID) == 0) {
- hog_attach_bas(hog, primary);
- }
- }
-}
-
static void service_cb(struct gatt_db_attribute *attrib, void *user_data)
{
struct bt_hog *hog = user_data;
@@ -1073,8 +1045,7 @@ static void service_cb(struct gatt_db_attribute *attrib, void *user_data)
else if (!bt_uuid_strcmp(uuid, DEVICE_INFORMATION_UUID))
hog_attach_dis(hog, service_handle);
else if (!bt_uuid_strcmp(uuid, BATTERY_UUID))
- /* TODO */
- return;
+ hog_attach_bas(hog, service_handle);
}
bool bt_hog_attach(struct bt_hog *hog, void *gatt, void *client)
@@ -1090,7 +1061,6 @@ bool bt_hog_attach(struct bt_hog *hog, void *gatt, void *client)
if (!hog->service_handle) {
gatt_db_foreach_service(hog->db, NULL, service_cb, hog);
- gatt_discover_primary(hog->attrib, NULL, primary_cb, hog);
return true;
}
@@ -1100,7 +1070,7 @@ bool bt_hog_attach(struct bt_hog *hog, void *gatt, void *client)
if (hog->dis)
bt_dis_attach(hog->dis, hog->client);
- queue_foreach(hog->bas, (void *) bt_bas_attach, gatt);
+ queue_foreach(hog->bas, (void *) bt_bas_attach, hog->client);
hog_entry = queue_get_entries(hog->instances);
while (hog_entry) {
--
1.9.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* Re: [PATCH 21/28] android/bas: Start using bt_gatt_client
2015-04-01 16:40 ` [PATCH 21/28] android/bas: Start using bt_gatt_client Mariusz Skamra
@ 2015-04-02 15:37 ` Szymon Janc
0 siblings, 0 replies; 41+ messages in thread
From: Szymon Janc @ 2015-04-02 15:37 UTC (permalink / raw)
To: Mariusz Skamra; +Cc: linux-bluetooth
Hi Mariusz,
On Wednesday 01 of April 2015 18:40:37 Mariusz Skamra wrote:
> This patch replaces gattrib with bt_gatt_client and strips glib
> dependencies. ---
> android/bas.c | 162
> ++++++++++++++++++---------------------------------------- android/bas.h |
> 4 +-
> android/hog.c | 40 ++-------------
> 3 files changed, 57 insertions(+), 149 deletions(-)
>
> diff --git a/android/bas.c b/android/bas.c
> index c5de3b1..3b641eb 100644
> --- a/android/bas.c
> +++ b/android/bas.c
> @@ -28,53 +28,47 @@
> #include <stdbool.h>
> #include <errno.h>
>
> -#include <glib.h>
> -
> #include "src/log.h"
>
> #include "lib/bluetooth.h"
> -#include "lib/sdp.h"
> #include "lib/uuid.h"
>
> #include "src/shared/util.h"
> #include "src/shared/queue.h"
> -
> -#include "attrib/gattrib.h"
> -#include "attrib/att.h"
> -#include "attrib/gatt.h"
> +#include "src/shared/att.h"
> +#include "src/shared/gatt-db.h"
> +#include "src/shared/gatt-client.h"
>
> #include "android/bas.h"
>
> -#define ATT_NOTIFICATION_HEADER_SIZE 3
> -#define ATT_READ_RESPONSE_HEADER_SIZE 1
> -
> struct bt_bas {
> int ref_count;
> - GAttrib *attrib;
> - struct gatt_primary *primary;
> - uint16_t handle;
> - uint16_t ccc_handle;
> - guint id;
> + uint16_t service_handle; /* Battery service start handle */
> + uint16_t handle; /* Battery level value handle */
> + uint32_t id;
> + struct bt_gatt_client *client;
> + struct gatt_db *db;
> };
>
> static void bas_free(struct bt_bas *bas)
> {
> bt_bas_detach(bas);
>
> - g_free(bas->primary);
> - g_free(bas);
> + free(bas);
> }
>
> -struct bt_bas *bt_bas_new(void *primary)
> +struct bt_bas *bt_bas_new(uint16_t service_handle)
> {
> struct bt_bas *bas;
>
> - bas = g_try_new0(struct bt_bas, 1);
> + if (!service_handle)
> + return NULL;
> +
> + bas = new0(struct bt_bas, 1);
> if (!bas)
> return NULL;
>
> - if (primary)
> - bas->primary = g_memdup(primary, sizeof(*bas->primary));
> + bas->service_handle = service_handle;
>
> return bt_bas_ref(bas);
> }
> @@ -100,132 +94,76 @@ void bt_bas_unref(struct bt_bas *bas)
> bas_free(bas);
> }
>
> -static void notification_cb(const guint8 *pdu, guint16 len, gpointer
> user_data) -{
> - DBG("Battery Level at %u", pdu[ATT_NOTIFICATION_HEADER_SIZE]);
> -}
> -
> -static void read_value_cb(guint8 status, const guint8 *pdu, guint16 len,
> - gpointer user_data)
> -{
> - DBG("Battery Level at %u", pdu[ATT_READ_RESPONSE_HEADER_SIZE]);
> -}
> -
> -static void ccc_written_cb(guint8 status, const guint8 *pdu,
> - guint16 plen, gpointer user_data)
> +static void notification_cb(uint16_t value_handle, const uint8_t *value,
> + uint16_t length, void *user_data)
> {
> - struct bt_bas *bas = user_data;
> -
> - if (status != 0) {
> - error("Write Scan Refresh CCC failed: %s",
> - att_ecode2str(status));
> - return;
> - }
> -
> - DBG("Battery Level: notification enabled");
> -
> - bas->id = g_attrib_register(bas->attrib, ATT_OP_HANDLE_NOTIFY,
> - bas->handle, notification_cb, bas,
> - NULL);
> + DBG("Battery Level at %u", value[0]);
> }
>
> -static void write_ccc(struct bt_bas *bas, GAttrib *attrib, uint16_t handle,
> - void *user_data)
> +static void read_value_cb(bool success, uint8_t att_ecode, const uint8_t
> *value, + uint16_t length, void *user_data)
> {
> - uint8_t value[2];
> + if (!success)
> + error("Read battery level failed: att_ecode %d", att_ecode);
>
> - put_le16(GATT_CLIENT_CHARAC_CFG_NOTIF_BIT, value);
> -
> - gatt_write_char(attrib, handle, value, sizeof(value), ccc_written_cb,
> - user_data);
> + DBG("Battery Level at %u", value[0]);
> }
>
> -static void ccc_read_cb(guint8 status, const guint8 *pdu, guint16 len,
> - gpointer user_data)
> +static void ccc_written_cb(uint16_t att_ecode, void *user_data)
> {
> - struct bt_bas *bas = user_data;
> -
> - if (status != 0) {
> - error("Error reading CCC value: %s", att_ecode2str(status));
> - return;
> - }
> -
> - write_ccc(bas, bas->attrib, bas->ccc_handle, bas);
> -}
> -
> -static void discover_descriptor_cb(uint8_t status, GSList *descs,
> - void *user_data)
> -{
> - struct bt_bas *bas = user_data;
> - struct gatt_desc *desc;
> -
> - if (status != 0) {
> - error("Discover descriptors failed: %s", att_ecode2str(status));
> - return;
> - }
> -
> - /* There will be only one descriptor on list and it will be CCC */
> - desc = descs->data;
> - bas->ccc_handle = desc->handle;
> -
> - gatt_read_char(bas->attrib, desc->handle, ccc_read_cb, bas);
> + DBG("Battery Level: notification enabled");
> }
>
> -static void bas_discovered_cb(uint8_t status, GSList *chars, void
> *user_data) +static void bas_discovered_cb(struct gatt_db_attribute
> *attrib, void *user_data) {
> struct bt_bas *bas = user_data;
> - struct gatt_char *chr;
> - uint16_t start, end;
> + uint16_t value_handle;
> bt_uuid_t uuid;
>
> - if (status) {
> - error("Battery: %s", att_ecode2str(status));
> - return;
> - }
> + gatt_db_attribute_get_char_data(attrib, NULL, &value_handle,
> + NULL, &uuid);
>
> - chr = chars->data;
> - bas->handle = chr->value_handle;
> + bas->handle = value_handle;
>
> DBG("Battery handle: 0x%04x", bas->handle);
>
> - gatt_read_char(bas->attrib, bas->handle, read_value_cb, bas);
> -
> - start = chr->value_handle + 1;
> - end = bas->primary->range.end;
> + bt_gatt_client_read_value(bas->client, bas->handle, read_value_cb,
> + bas, NULL);
>
> - bt_uuid16_create(&uuid, GATT_CLIENT_CHARAC_CFG_UUID);
> + bas->id = bt_gatt_client_register_notify(bas->client, bas->handle,
> + ccc_written_cb, notification_cb, bas, NULL);
>
> - gatt_discover_desc(bas->attrib, start, end, &uuid,
> - discover_descriptor_cb, bas);
> + /* TODO Characteristic Presentation Format shall be read */
> }
>
> -bool bt_bas_attach(struct bt_bas *bas, void *attrib)
> +bool bt_bas_attach(struct bt_bas *bas, struct bt_gatt_client *client)
> {
> - if (!bas || bas->attrib || !bas->primary)
> - return false;
> + struct gatt_db_attribute *attrib;
>
> - bas->attrib = g_attrib_ref(attrib);
> + if (!bas || bas->client || !bas->service_handle)
> + return false;
>
> - if (bas->handle > 0)
> - return true;
> + bas->client = bt_gatt_client_ref(client);
> + bas->db = bt_gatt_client_get_db(client);
> + attrib = gatt_db_get_attribute(bas->db, bas->service_handle);
>
> - gatt_discover_char(bas->attrib, bas->primary->range.start,
> - bas->primary->range.end, NULL,
> - bas_discovered_cb, bas);
> + if (!bas->handle)
> + gatt_db_service_foreach_char(attrib, bas_discovered_cb, bas);
>
> return true;
> }
>
> void bt_bas_detach(struct bt_bas *bas)
> {
> - if (!bas || !bas->attrib)
> + if (!bas || !bas->client)
> return;
>
> - if (bas->id > 0) {
> - g_attrib_unregister(bas->attrib, bas->id);
> + if (bas->id) {
> + bt_gatt_client_unregister_notify(bas->client, bas->id);
> bas->id = 0;
> }
>
> - g_attrib_unref(bas->attrib);
> - bas->attrib = NULL;
> + gatt_db_unref(bas->db);
bas->db = NULL;
> + bt_gatt_client_unref(bas->client);
> + bas->client = NULL;
> }
> diff --git a/android/bas.h b/android/bas.h
> index 3e175b5..ce903e3 100644
> --- a/android/bas.h
> +++ b/android/bas.h
> @@ -23,10 +23,10 @@
>
> struct bt_bas;
>
> -struct bt_bas *bt_bas_new(void *primary);
> +struct bt_bas *bt_bas_new(uint16_t service_handle);
>
> struct bt_bas *bt_bas_ref(struct bt_bas *bas);
> void bt_bas_unref(struct bt_bas *bas);
>
> -bool bt_bas_attach(struct bt_bas *bas, void *gatt);
> +bool bt_bas_attach(struct bt_bas *bas, struct bt_gatt_client *client);
> void bt_bas_detach(struct bt_bas *bas);
> diff --git a/android/hog.c b/android/hog.c
> index 78c1b26..4565e86 100644
> --- a/android/hog.c
> +++ b/android/hog.c
> @@ -990,15 +990,15 @@ static void hog_attach_dis(struct bt_hog *hog,
> uint16_t service_handle) }
> }
>
> -static void hog_attach_bas(struct bt_hog *hog, struct gatt_primary
> *primary) +static void hog_attach_bas(struct bt_hog *hog, uint16_t
> service_handle) {
> struct bt_bas *instance;
>
> - instance = bt_bas_new(primary);
> + instance = bt_bas_new(service_handle);
> if (!instance)
> return;
>
> - bt_bas_attach(instance, hog->attrib);
> + bt_bas_attach(instance, hog->client);
> queue_push_head(hog->bas, instance);
> }
>
> @@ -1025,34 +1025,6 @@ static void hog_attach_hog(struct bt_hog *hog,
> uint16_t service_handle) queue_push_tail(hog->instances, instance);
> }
>
> -static void primary_cb(uint8_t status, GSList *services, void *user_data)
> -{
> - struct bt_hog *hog = user_data;
> - struct gatt_primary *primary;
> - GSList *l;
> -
> - DBG("");
> -
> - if (status) {
> - const char *str = att_ecode2str(status);
> - DBG("Discover primary failed: %s", str);
> - return;
> - }
> -
> - if (!services) {
> - DBG("No primary service found");
> - return;
> - }
> -
> - for (l = services; l; l = l->next) {
> - primary = l->data;
> -
> - if (strcmp(primary->uuid, BATTERY_UUID) == 0) {
> - hog_attach_bas(hog, primary);
> - }
> - }
> -}
> -
> static void service_cb(struct gatt_db_attribute *attrib, void *user_data)
> {
> struct bt_hog *hog = user_data;
> @@ -1073,8 +1045,7 @@ static void service_cb(struct gatt_db_attribute
> *attrib, void *user_data) else if (!bt_uuid_strcmp(uuid,
> DEVICE_INFORMATION_UUID))
> hog_attach_dis(hog, service_handle);
> else if (!bt_uuid_strcmp(uuid, BATTERY_UUID))
> - /* TODO */
> - return;
> + hog_attach_bas(hog, service_handle);
> }
>
> bool bt_hog_attach(struct bt_hog *hog, void *gatt, void *client)
> @@ -1090,7 +1061,6 @@ bool bt_hog_attach(struct bt_hog *hog, void *gatt,
> void *client)
>
> if (!hog->service_handle) {
> gatt_db_foreach_service(hog->db, NULL, service_cb, hog);
> - gatt_discover_primary(hog->attrib, NULL, primary_cb, hog);
> return true;
> }
>
> @@ -1100,7 +1070,7 @@ bool bt_hog_attach(struct bt_hog *hog, void *gatt,
> void *client) if (hog->dis)
> bt_dis_attach(hog->dis, hog->client);
>
> - queue_foreach(hog->bas, (void *) bt_bas_attach, gatt);
> + queue_foreach(hog->bas, (void *) bt_bas_attach, hog->client);
>
> hog_entry = queue_get_entries(hog->instances);
> while (hog_entry) {
--
BR
Szymon Janc
^ permalink raw reply [flat|nested] 41+ messages in thread
* [PATCH 22/28] android/hog: Strip btio dependencies
2015-04-01 16:40 [PATCH 00/28] android/hog Introduce bt_gatt_client Mariusz Skamra
` (20 preceding siblings ...)
2015-04-01 16:40 ` [PATCH 21/28] android/bas: Start using bt_gatt_client Mariusz Skamra
@ 2015-04-01 16:40 ` Mariusz Skamra
2015-04-02 15:39 ` Szymon Janc
2015-04-01 16:40 ` [PATCH 23/28] android/hog: Enable Input Report notifications only if uhid is created Mariusz Skamra
` (5 subsequent siblings)
27 siblings, 1 reply; 41+ messages in thread
From: Mariusz Skamra @ 2015-04-01 16:40 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Mariusz Skamra
bt_io_get from btio library is used only to get address of adapter
and connected hid device. We can just simply pass this addresses
using bt_hog_new argument list. It's temporary solution, just to
be able to move the code to shared.
---
android/hidhost.c | 3 ++-
android/hog.c | 36 +++++++++++++++++-------------------
android/hog.h | 10 ++++++----
unit/test-hog.c | 7 ++++++-
4 files changed, 31 insertions(+), 25 deletions(-)
diff --git a/android/hidhost.c b/android/hidhost.c
index 98eceee..3d4ee85 100644
--- a/android/hidhost.c
+++ b/android/hidhost.c
@@ -862,7 +862,8 @@ static void hog_conn_cb(const bdaddr_t *addr, int err, void *attrib)
if (!dev->hog) {
/* TODO: Get device details */
dev->hog = bt_hog_new_default("bluez-input-device", dev->vendor,
- dev->product, dev->version, 0);
+ dev->product, dev->version, addr,
+ &adapter_addr, 0);
if (!dev->hog) {
error("HoG: unable to create session");
goto fail;
diff --git a/android/hog.c b/android/hog.c
index 4565e86..b5b772c 100644
--- a/android/hog.c
+++ b/android/hog.c
@@ -54,8 +54,6 @@
#include "attrib/gattrib.h"
#include "attrib/gatt.h"
-#include "btio/btio.h"
-
#include "android/scpp.h"
#include "android/dis.h"
#include "android/bas.h"
@@ -82,9 +80,12 @@ static const bt_uuid_t report_uuid = { .type = BT_UUID16,
static const bt_uuid_t protocol_mode_uuid = { .type = BT_UUID16,
.value.u16 = 0x2A4E };
+static bdaddr_t adapter_addr;
+
struct bt_hog {
int ref_count;
uint16_t service_handle;
+ bdaddr_t device_addr;
char *name;
uint16_t vendor;
uint16_t product;
@@ -694,22 +695,13 @@ static bool uhid_create(struct bt_hog *hog, const uint8_t *value, uint16_t vlen)
{
struct uhid_event ev;
int err;
- GError *gerr = NULL;
/* create uHID device */
memset(&ev, 0, sizeof(ev));
ev.type = UHID_CREATE;
- bt_io_get(g_attrib_get_channel(hog->attrib), &gerr,
- BT_IO_OPT_SOURCE, ev.u.create.phys,
- BT_IO_OPT_DEST, ev.u.create.uniq,
- BT_IO_OPT_INVALID);
- if (gerr) {
- error("Failed to connection details: %s", gerr->message);
- g_error_free(gerr);
- return false;
- }
-
+ ba2str(&adapter_addr, (char *) ev.u.create.phys);
+ ba2str(&hog->device_addr, (char *) ev.u.create.uniq);
strcpy((char *) ev.u.create.name, hog->name);
ev.u.create.vendor = hog->vendor;
ev.u.create.product = hog->product;
@@ -881,15 +873,18 @@ static void hog_free(void *data)
}
struct bt_hog *bt_hog_new_default(const char *name, uint16_t vendor,
- uint16_t product, uint16_t version,
- uint16_t service_handle)
+ uint16_t product, uint16_t version,
+ const bdaddr_t *addr, const bdaddr_t *adapter,
+ uint16_t service_handle)
{
- return bt_hog_new(-1, name, vendor, product, version, service_handle);
+ return bt_hog_new(-1, name, vendor, product, version, addr, adapter,
+ service_handle);
}
struct bt_hog *bt_hog_new(int fd, const char *name, uint16_t vendor,
- uint16_t product, uint16_t version,
- uint16_t service_handle)
+ uint16_t product, uint16_t version,
+ const bdaddr_t *addr, const bdaddr_t *adapter,
+ uint16_t service_handle)
{
struct bt_hog *hog;
@@ -917,6 +912,8 @@ struct bt_hog *bt_hog_new(int fd, const char *name, uint16_t vendor,
hog->vendor = vendor;
hog->product = product;
hog->version = version;
+ bacpy(&hog->device_addr, addr);
+ bacpy(&adapter_addr, adapter);
if (service_handle)
hog->service_handle = service_handle;
@@ -1017,7 +1014,8 @@ static void hog_attach_hog(struct bt_hog *hog, uint16_t service_handle)
}
instance = bt_hog_new(hog->uhid_fd, hog->name, hog->vendor,
- hog->product, hog->version, service_handle);
+ hog->product, hog->version, &hog->device_addr,
+ &adapter_addr, service_handle);
if (!instance)
return;
diff --git a/android/hog.h b/android/hog.h
index cfe6873..8fe8422 100644
--- a/android/hog.h
+++ b/android/hog.h
@@ -24,12 +24,14 @@
struct bt_hog;
struct bt_hog *bt_hog_new_default(const char *name, uint16_t vendor,
- uint16_t product, uint16_t version,
- uint16_t service_handle);
+ uint16_t product, uint16_t version,
+ const bdaddr_t *addr, const bdaddr_t *adapter,
+ uint16_t service_handle);
struct bt_hog *bt_hog_new(int fd, const char *name, uint16_t vendor,
- uint16_t product, uint16_t version,
- uint16_t service_handle);
+ uint16_t product, uint16_t version,
+ const bdaddr_t *addr, const bdaddr_t *adapter,
+ uint16_t service_handle);
struct bt_hog *bt_hog_ref(struct bt_hog *hog);
void bt_hog_unref(struct bt_hog *hog);
diff --git a/unit/test-hog.c b/unit/test-hog.c
index 5794c5e..16805e7 100644
--- a/unit/test-hog.c
+++ b/unit/test-hog.c
@@ -32,6 +32,8 @@
#include <glib.h>
+#include "lib/bluetooth.h"
+
#include "src/shared/util.h"
#include "src/shared/tester.h"
@@ -179,6 +181,8 @@ static struct context *create_context(gconstpointer data)
uint16_t vendor = 0x0002;
uint16_t product = 0x0001;
uint16_t version = 0x0001;
+ const bdaddr_t *device_addr = NULL;
+ const bdaddr_t *adapter_addr = NULL;
context = g_new0(struct context, 1);
err = socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0, sv);
@@ -196,7 +200,8 @@ static struct context *create_context(gconstpointer data)
fd = open("/dev/null", O_WRONLY | O_CLOEXEC);
g_assert(fd > 0);
- context->hog = bt_hog_new(fd, name, vendor, product, version, 0);
+ context->hog = bt_hog_new(fd, name, vendor, product, version,
+ device_addr, adapter_addr, 0);
g_assert(context->hog);
channel = g_io_channel_unix_new(sv[1]);
--
1.9.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* Re: [PATCH 22/28] android/hog: Strip btio dependencies
2015-04-01 16:40 ` [PATCH 22/28] android/hog: Strip btio dependencies Mariusz Skamra
@ 2015-04-02 15:39 ` Szymon Janc
0 siblings, 0 replies; 41+ messages in thread
From: Szymon Janc @ 2015-04-02 15:39 UTC (permalink / raw)
To: Mariusz Skamra; +Cc: linux-bluetooth
Hi Mariusz,
On Wednesday 01 of April 2015 18:40:38 Mariusz Skamra wrote:
> bt_io_get from btio library is used only to get address of adapter
> and connected hid device. We can just simply pass this addresses
> using bt_hog_new argument list. It's temporary solution, just to
> be able to move the code to shared.
shared code is required to be LGPL so I'd just skip this patch for now.
> ---
> android/hidhost.c | 3 ++-
> android/hog.c | 36 +++++++++++++++++-------------------
> android/hog.h | 10 ++++++----
> unit/test-hog.c | 7 ++++++-
> 4 files changed, 31 insertions(+), 25 deletions(-)
>
> diff --git a/android/hidhost.c b/android/hidhost.c
> index 98eceee..3d4ee85 100644
> --- a/android/hidhost.c
> +++ b/android/hidhost.c
> @@ -862,7 +862,8 @@ static void hog_conn_cb(const bdaddr_t *addr, int err,
> void *attrib) if (!dev->hog) {
> /* TODO: Get device details */
> dev->hog = bt_hog_new_default("bluez-input-device", dev->vendor,
> - dev->product, dev->version, 0);
> + dev->product, dev->version, addr,
> + &adapter_addr, 0);
> if (!dev->hog) {
> error("HoG: unable to create session");
> goto fail;
> diff --git a/android/hog.c b/android/hog.c
> index 4565e86..b5b772c 100644
> --- a/android/hog.c
> +++ b/android/hog.c
> @@ -54,8 +54,6 @@
> #include "attrib/gattrib.h"
> #include "attrib/gatt.h"
>
> -#include "btio/btio.h"
> -
> #include "android/scpp.h"
> #include "android/dis.h"
> #include "android/bas.h"
> @@ -82,9 +80,12 @@ static const bt_uuid_t report_uuid = { .type = BT_UUID16,
> static const bt_uuid_t protocol_mode_uuid = { .type = BT_UUID16,
> .value.u16 = 0x2A4E };
>
> +static bdaddr_t adapter_addr;
> +
> struct bt_hog {
> int ref_count;
> uint16_t service_handle;
> + bdaddr_t device_addr;
> char *name;
> uint16_t vendor;
> uint16_t product;
> @@ -694,22 +695,13 @@ static bool uhid_create(struct bt_hog *hog, const
> uint8_t *value, uint16_t vlen) {
> struct uhid_event ev;
> int err;
> - GError *gerr = NULL;
>
> /* create uHID device */
> memset(&ev, 0, sizeof(ev));
> ev.type = UHID_CREATE;
>
> - bt_io_get(g_attrib_get_channel(hog->attrib), &gerr,
> - BT_IO_OPT_SOURCE, ev.u.create.phys,
> - BT_IO_OPT_DEST, ev.u.create.uniq,
> - BT_IO_OPT_INVALID);
> - if (gerr) {
> - error("Failed to connection details: %s", gerr->message);
> - g_error_free(gerr);
> - return false;
> - }
> -
> + ba2str(&adapter_addr, (char *) ev.u.create.phys);
> + ba2str(&hog->device_addr, (char *) ev.u.create.uniq);
> strcpy((char *) ev.u.create.name, hog->name);
> ev.u.create.vendor = hog->vendor;
> ev.u.create.product = hog->product;
> @@ -881,15 +873,18 @@ static void hog_free(void *data)
> }
>
> struct bt_hog *bt_hog_new_default(const char *name, uint16_t vendor,
> - uint16_t product, uint16_t version,
> - uint16_t service_handle)
> + uint16_t product, uint16_t version,
> + const bdaddr_t *addr, const bdaddr_t *adapter,
> + uint16_t service_handle)
> {
> - return bt_hog_new(-1, name, vendor, product, version, service_handle);
> + return bt_hog_new(-1, name, vendor, product, version, addr, adapter,
> + service_handle);
> }
>
> struct bt_hog *bt_hog_new(int fd, const char *name, uint16_t vendor,
> - uint16_t product, uint16_t version,
> - uint16_t service_handle)
> + uint16_t product, uint16_t version,
> + const bdaddr_t *addr, const bdaddr_t *adapter,
> + uint16_t service_handle)
> {
> struct bt_hog *hog;
>
> @@ -917,6 +912,8 @@ struct bt_hog *bt_hog_new(int fd, const char *name,
> uint16_t vendor, hog->vendor = vendor;
> hog->product = product;
> hog->version = version;
> + bacpy(&hog->device_addr, addr);
> + bacpy(&adapter_addr, adapter);
>
> if (service_handle)
> hog->service_handle = service_handle;
> @@ -1017,7 +1014,8 @@ static void hog_attach_hog(struct bt_hog *hog,
> uint16_t service_handle) }
>
> instance = bt_hog_new(hog->uhid_fd, hog->name, hog->vendor,
> - hog->product, hog->version, service_handle);
> + hog->product, hog->version, &hog->device_addr,
> + &adapter_addr, service_handle);
> if (!instance)
> return;
>
> diff --git a/android/hog.h b/android/hog.h
> index cfe6873..8fe8422 100644
> --- a/android/hog.h
> +++ b/android/hog.h
> @@ -24,12 +24,14 @@
> struct bt_hog;
>
> struct bt_hog *bt_hog_new_default(const char *name, uint16_t vendor,
> - uint16_t product, uint16_t version,
> - uint16_t service_handle);
> + uint16_t product, uint16_t version,
> + const bdaddr_t *addr, const bdaddr_t *adapter,
> + uint16_t service_handle);
>
> struct bt_hog *bt_hog_new(int fd, const char *name, uint16_t vendor,
> - uint16_t product, uint16_t version,
> - uint16_t service_handle);
> + uint16_t product, uint16_t version,
> + const bdaddr_t *addr, const bdaddr_t *adapter,
> + uint16_t service_handle);
>
> struct bt_hog *bt_hog_ref(struct bt_hog *hog);
> void bt_hog_unref(struct bt_hog *hog);
> diff --git a/unit/test-hog.c b/unit/test-hog.c
> index 5794c5e..16805e7 100644
> --- a/unit/test-hog.c
> +++ b/unit/test-hog.c
> @@ -32,6 +32,8 @@
>
> #include <glib.h>
>
> +#include "lib/bluetooth.h"
> +
> #include "src/shared/util.h"
> #include "src/shared/tester.h"
>
> @@ -179,6 +181,8 @@ static struct context *create_context(gconstpointer
> data) uint16_t vendor = 0x0002;
> uint16_t product = 0x0001;
> uint16_t version = 0x0001;
> + const bdaddr_t *device_addr = NULL;
> + const bdaddr_t *adapter_addr = NULL;
>
> context = g_new0(struct context, 1);
> err = socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0, sv);
> @@ -196,7 +200,8 @@ static struct context *create_context(gconstpointer
> data) fd = open("/dev/null", O_WRONLY | O_CLOEXEC);
> g_assert(fd > 0);
>
> - context->hog = bt_hog_new(fd, name, vendor, product, version, 0);
> + context->hog = bt_hog_new(fd, name, vendor, product, version,
> + device_addr, adapter_addr, 0);
> g_assert(context->hog);
>
> channel = g_io_channel_unix_new(sv[1]);
--
BR
Szymon Janc
^ permalink raw reply [flat|nested] 41+ messages in thread
* [PATCH 23/28] android/hog: Enable Input Report notifications only if uhid is created
2015-04-01 16:40 [PATCH 00/28] android/hog Introduce bt_gatt_client Mariusz Skamra
` (21 preceding siblings ...)
2015-04-01 16:40 ` [PATCH 22/28] android/hog: Strip btio dependencies Mariusz Skamra
@ 2015-04-01 16:40 ` Mariusz Skamra
2015-04-01 16:40 ` [PATCH 24/28] android/bas: Enable Battery Level notifications after reconnection Mariusz Skamra
` (4 subsequent siblings)
27 siblings, 0 replies; 41+ messages in thread
From: Mariusz Skamra @ 2015-04-01 16:40 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Mariusz Skamra
This prevents against the situation when notification is received
before uhid is created. Otherwise bt_uhid error message appears.
---
android/hog.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/android/hog.c b/android/hog.c
index b5b772c..9276d40 100644
--- a/android/hog.c
+++ b/android/hog.c
@@ -210,8 +210,6 @@ static void report_reference_cb(bool success, uint8_t status,
report->id = value[0];
report->type = value[1];
DBG("Report ID: 0x%02x Report type: 0x%02x", value[0], value[1]);
-
- report_enable_notif(report, NULL);
}
static void external_report_reference_cb(bool success, uint8_t status,
@@ -717,6 +715,7 @@ static bool uhid_create(struct bt_hog *hog, const uint8_t *value, uint16_t vlen)
return false;
}
+ queue_foreach(hog->reports, report_enable_notif, NULL);
bt_uhid_register(hog->uhid, UHID_OUTPUT, forward_report, hog);
bt_uhid_register(hog->uhid, UHID_FEATURE, get_feature, hog);
bt_uhid_register(hog->uhid, UHID_GET_REPORT, get_report, hog);
--
1.9.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [PATCH 24/28] android/bas: Enable Battery Level notifications after reconnection
2015-04-01 16:40 [PATCH 00/28] android/hog Introduce bt_gatt_client Mariusz Skamra
` (22 preceding siblings ...)
2015-04-01 16:40 ` [PATCH 23/28] android/hog: Enable Input Report notifications only if uhid is created Mariusz Skamra
@ 2015-04-01 16:40 ` Mariusz Skamra
2015-04-01 16:40 ` [PATCH 25/28] android/hog: Add MIN definition Mariusz Skamra
` (3 subsequent siblings)
27 siblings, 0 replies; 41+ messages in thread
From: Mariusz Skamra @ 2015-04-01 16:40 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Mariusz Skamra
---
android/bas.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/android/bas.c b/android/bas.c
index 3b641eb..ab33d59 100644
--- a/android/bas.c
+++ b/android/bas.c
@@ -149,6 +149,10 @@ bool bt_bas_attach(struct bt_bas *bas, struct bt_gatt_client *client)
if (!bas->handle)
gatt_db_service_foreach_char(attrib, bas_discovered_cb, bas);
+ else
+ bas->id = bt_gatt_client_register_notify(bas->client,
+ bas->handle, ccc_written_cb,
+ notification_cb, bas, NULL);
return true;
}
--
1.9.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [PATCH 25/28] android/hog: Add MIN definition
2015-04-01 16:40 [PATCH 00/28] android/hog Introduce bt_gatt_client Mariusz Skamra
` (23 preceding siblings ...)
2015-04-01 16:40 ` [PATCH 24/28] android/bas: Enable Battery Level notifications after reconnection Mariusz Skamra
@ 2015-04-01 16:40 ` Mariusz Skamra
2015-04-02 15:41 ` Szymon Janc
2015-04-01 16:40 ` [PATCH 26/28] android/hog: Remove attrib/ Mariusz Skamra
` (2 subsequent siblings)
27 siblings, 1 reply; 41+ messages in thread
From: Mariusz Skamra @ 2015-04-01 16:40 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Mariusz Skamra
It's needed to delete attrib, where the previous definition was.
---
android/hog.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/android/hog.c b/android/hog.c
index 9276d40..eb9c9d4 100644
--- a/android/hog.c
+++ b/android/hog.c
@@ -59,6 +59,10 @@
#include "android/bas.h"
#include "android/hog.h"
+#ifndef MIN
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+
#define HOG_REPORT_TYPE_INPUT 1
#define HOG_REPORT_TYPE_OUTPUT 2
#define HOG_REPORT_TYPE_FEATURE 3
--
1.9.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* Re: [PATCH 25/28] android/hog: Add MIN definition
2015-04-01 16:40 ` [PATCH 25/28] android/hog: Add MIN definition Mariusz Skamra
@ 2015-04-02 15:41 ` Szymon Janc
0 siblings, 0 replies; 41+ messages in thread
From: Szymon Janc @ 2015-04-02 15:41 UTC (permalink / raw)
To: Mariusz Skamra; +Cc: linux-bluetooth
Hi Mariusz,
On Wednesday 01 of April 2015 18:40:41 Mariusz Skamra wrote:
> It's needed to delete attrib, where the previous definition was.
Just squeeze this patch with one that requires this macro.
> ---
> android/hog.c | 4 ++++
> 1 file changed, 4 insertions(+)
>
> diff --git a/android/hog.c b/android/hog.c
> index 9276d40..eb9c9d4 100644
> --- a/android/hog.c
> +++ b/android/hog.c
> @@ -59,6 +59,10 @@
> #include "android/bas.h"
> #include "android/hog.h"
>
> +#ifndef MIN
> +#define MIN(a, b) (((a) < (b)) ? (a) : (b))
> +#endif
> +
> #define HOG_REPORT_TYPE_INPUT 1
> #define HOG_REPORT_TYPE_OUTPUT 2
> #define HOG_REPORT_TYPE_FEATURE 3
--
BR
Szymon Janc
^ permalink raw reply [flat|nested] 41+ messages in thread
* [PATCH 26/28] android/hog: Remove attrib/
2015-04-01 16:40 [PATCH 00/28] android/hog Introduce bt_gatt_client Mariusz Skamra
` (24 preceding siblings ...)
2015-04-01 16:40 ` [PATCH 25/28] android/hog: Add MIN definition Mariusz Skamra
@ 2015-04-01 16:40 ` Mariusz Skamra
2015-04-02 15:44 ` Szymon Janc
2015-04-01 16:40 ` [PATCH 27/28] android/hog: Remove glib dependencies Mariusz Skamra
2015-04-01 16:40 ` [PATCH 28/28] android/hog: Remove redundant code Mariusz Skamra
27 siblings, 1 reply; 41+ messages in thread
From: Mariusz Skamra @ 2015-04-01 16:40 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Mariusz Skamra
All the attrib/ include files can be now removed since all the dependencies
have been previously removed.
---
android/hidhost.c | 2 +-
android/hog.c | 62 +++++++++++++++++++++++++++----------------------------
android/hog.h | 2 +-
unit/test-hog.c | 2 +-
4 files changed, 33 insertions(+), 35 deletions(-)
diff --git a/android/hidhost.c b/android/hidhost.c
index 3d4ee85..9bd96a1 100644
--- a/android/hidhost.c
+++ b/android/hidhost.c
@@ -816,7 +816,7 @@ static void client_ready_cb(bool success, uint8_t att_ecode, void *user_data)
goto fail;
}
- if (!bt_hog_attach(dev->hog, dev->attrib, dev->client)) {
+ if (!bt_hog_attach(dev->hog, dev->client)) {
error("HoG: unable to attach");
goto fail;
}
diff --git a/android/hog.c b/android/hog.c
index eb9c9d4..c2017f8 100644
--- a/android/hog.c
+++ b/android/hog.c
@@ -50,10 +50,6 @@
#include "src/shared/gatt-client.h"
#include "src/log.h"
-#include "attrib/att.h"
-#include "attrib/gattrib.h"
-#include "attrib/gatt.h"
-
#include "android/scpp.h"
#include "android/dis.h"
#include "android/bas.h"
@@ -94,7 +90,6 @@ struct bt_hog {
uint16_t vendor;
uint16_t product;
uint16_t version;
- GAttrib *attrib;
struct queue *reports;
struct bt_uhid *uhid;
int uhid_fd;
@@ -116,6 +111,11 @@ struct bt_hog {
struct gatt_db *db;
};
+struct gatt_char {
+ uint8_t properties;
+ uint16_t value_handle;
+};
+
struct report {
struct bt_hog *hog;
uint8_t id;
@@ -162,8 +162,8 @@ static void report_value_cb(uint16_t value_handle, const uint8_t *value,
static void report_ccc_written_cb(uint16_t status, void *user_data)
{
if (status != 0) {
- error("Write report characteristic descriptor failed: %s",
- att_ecode2str(status));
+ error("Write report characteristic descriptor failed: %d",
+ status);
return;
}
@@ -201,8 +201,8 @@ static void report_reference_cb(bool success, uint8_t status,
struct report *report = user_data;
if (!success) {
- error("Read Report Reference descriptor failed: %s",
- att_ecode2str(status));
+ error("Read Report Reference descriptor failed: att_ecode %d",
+ status);
return;
}
@@ -258,8 +258,7 @@ static void report_read_cb(bool success, uint8_t att_ecode,
struct report *report = user_data;
if (!success) {
- error("Error reading Report value: %s",
- att_ecode2str(att_ecode));
+ error("Error reading Report value: att_ecode %d", att_ecode);
return;
}
@@ -312,8 +311,8 @@ static void external_report_reference_cb(bool success, uint8_t status,
struct queue *chrs;
if (!success) {
- error("Read External Report Reference descriptor failed: %s",
- att_ecode2str(status));
+ error("Read External Report Reference descriptor failed: %d",
+ status);
return;
}
@@ -403,7 +402,7 @@ static struct report *find_report_by_rtype(struct bt_hog *hog, uint8_t rtype,
static void output_written_cb(bool success, uint8_t status, void *user_data)
{
if (!success) {
- error("Write output report failed: %s", att_ecode2str(status));
+ error("Write output report failed: att_ecode %d", status);
return;
}
}
@@ -414,6 +413,7 @@ static void forward_report(struct uhid_event *ev, void *user_data)
struct report *report;
void *data;
int size;
+ uint8_t properties;
report = find_report_by_rtype(hog, ev->u.output.rtype,
ev->u.output.data[0]);
@@ -433,12 +433,13 @@ static void forward_report(struct uhid_event *ev, void *user_data)
if (hog->client == NULL)
return;
- if (report->decl->properties & GATT_CHR_PROP_WRITE)
+ properties = report->decl->properties;
+ if (properties & BT_GATT_CHRC_PROP_WRITE)
bt_gatt_client_write_value(hog->client,
report->decl->value_handle,
data, size, output_written_cb,
hog, NULL);
- else if (report->decl->properties & GATT_CHR_PROP_WRITE_WITHOUT_RESP)
+ else if (properties & BT_GATT_CHRC_PROP_WRITE_WITHOUT_RESP)
bt_gatt_client_write_without_response(hog->client,
report->decl->value_handle,
false, data, size);
@@ -490,7 +491,7 @@ static void set_report_cb(bool success, uint8_t status, void *user_data)
rsp.u.set_report_reply.err = status;
if (!success)
- error("Error setting Report value: %s", att_ecode2str(status));
+ error("Error setting Report value: att_ecode %d", status);
err = bt_uhid_send(hog->uhid, &rsp);
if (err < 0)
@@ -562,7 +563,7 @@ static void get_report_cb(bool success, uint8_t status, const uint8_t *value,
rsp.u.get_report_reply.id = hog->getrep_id;
if (!success) {
- error("Error reading Report value: %s", att_ecode2str(status));
+ error("Error reading Report value: att_ecode %d", status);
goto exit;
}
@@ -738,7 +739,7 @@ static void report_map_read_cb(bool success, uint8_t att_ecode,
int i;
if (!success) {
- error("Report Map read failed: %s", att_ecode2str(att_ecode));
+ error("Report Map read failed: att_ecode %d", att_ecode);
return;
}
@@ -776,7 +777,7 @@ static void info_read_cb(bool success, uint8_t status, const uint8_t *value,
struct bt_hog *hog = user_data;
if (!success) {
- error("HID Information read failed: %s", att_ecode2str(status));
+ error("HID Information read failed: att_ecode %d", status);
return;
}
@@ -800,8 +801,8 @@ static void proto_mode_read_cb(bool success, uint8_t att_ecode,
struct bt_hog *hog = user_data;
if (!success) {
- error("Protocol Mode characteristic read failed: %s",
- att_ecode2str(att_ecode));
+ error("Protocol Mode characteristic read failed: att_ecode %d",
+ att_ecode);
return;
}
@@ -1022,7 +1023,7 @@ static void hog_attach_hog(struct bt_hog *hog, uint16_t service_handle)
if (!instance)
return;
- bt_hog_attach(instance, hog->attrib, hog->client);
+ bt_hog_attach(instance, hog->client);
queue_push_tail(hog->instances, instance);
}
@@ -1049,14 +1050,13 @@ static void service_cb(struct gatt_db_attribute *attrib, void *user_data)
hog_attach_bas(hog, service_handle);
}
-bool bt_hog_attach(struct bt_hog *hog, void *gatt, void *client)
+bool bt_hog_attach(struct bt_hog *hog, void *client)
{
const struct queue_entry *hog_entry;
- if (hog->attrib || hog->client)
+ if (hog->client)
return false;
- hog->attrib = g_attrib_ref(gatt);
hog->client = bt_gatt_client_ref(client);
hog->db = bt_gatt_client_get_db(hog->client);
@@ -1077,7 +1077,7 @@ bool bt_hog_attach(struct bt_hog *hog, void *gatt, void *client)
while (hog_entry) {
struct bt_hog *instance = hog_entry->data;
- bt_hog_attach(instance, gatt, client);
+ bt_hog_attach(instance, client);
}
if (queue_isempty(hog->reports)) {
@@ -1096,7 +1096,7 @@ bool bt_hog_attach(struct bt_hog *hog, void *gatt, void *client)
void bt_hog_detach(struct bt_hog *hog)
{
- if (!hog->attrib || !hog->client)
+ if (!hog->client)
return;
queue_foreach(hog->bas, (void *) bt_bas_detach, NULL);
@@ -1111,9 +1111,7 @@ void bt_hog_detach(struct bt_hog *hog)
gatt_db_unref(hog->db);
bt_gatt_client_unref(hog->client);
- g_attrib_unref(hog->attrib);
hog->client = NULL;
- hog->attrib = NULL;
}
int bt_hog_set_control_point(struct bt_hog *hog, bool suspend)
@@ -1149,13 +1147,13 @@ int bt_hog_send_report(struct bt_hog *hog, void *data, size_t size, int type)
DBG("hog: Write report, handle 0x%X", report->decl->value_handle);
- if (report->decl->properties & GATT_CHR_PROP_WRITE)
+ if (report->decl->properties & BT_GATT_CHRC_PROP_WRITE)
bt_gatt_client_write_value(hog->client,
report->decl->value_handle,
data, size, output_written_cb,
hog, NULL);
- if (report->decl->properties & GATT_CHR_PROP_WRITE_WITHOUT_RESP)
+ if (report->decl->properties & BT_GATT_CHRC_PROP_WRITE_WITHOUT_RESP)
bt_gatt_client_write_without_response(hog->client,
report->decl->value_handle,
false, data, size);
diff --git a/android/hog.h b/android/hog.h
index 8fe8422..fa3d114 100644
--- a/android/hog.h
+++ b/android/hog.h
@@ -36,7 +36,7 @@ struct bt_hog *bt_hog_new(int fd, const char *name, uint16_t vendor,
struct bt_hog *bt_hog_ref(struct bt_hog *hog);
void bt_hog_unref(struct bt_hog *hog);
-bool bt_hog_attach(struct bt_hog *hog, void *gatt, void *client);
+bool bt_hog_attach(struct bt_hog *hog, void *client);
void bt_hog_detach(struct bt_hog *hog);
int bt_hog_set_control_point(struct bt_hog *hog, bool suspend);
diff --git a/unit/test-hog.c b/unit/test-hog.c
index 16805e7..81aada2 100644
--- a/unit/test-hog.c
+++ b/unit/test-hog.c
@@ -227,7 +227,7 @@ static void test_hog(gconstpointer data)
{
struct context *context = create_context(data);
- g_assert(bt_hog_attach(context->hog, context->attrib, NULL));
+ g_assert(bt_hog_attach(context->hog, NULL));
}
int main(int argc, char *argv[])
--
1.9.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* Re: [PATCH 26/28] android/hog: Remove attrib/
2015-04-01 16:40 ` [PATCH 26/28] android/hog: Remove attrib/ Mariusz Skamra
@ 2015-04-02 15:44 ` Szymon Janc
0 siblings, 0 replies; 41+ messages in thread
From: Szymon Janc @ 2015-04-02 15:44 UTC (permalink / raw)
To: Mariusz Skamra; +Cc: linux-bluetooth
On Wednesday 01 of April 2015 18:40:42 Mariusz Skamra wrote:
> All the attrib/ include files can be now removed since all the dependencies
> have been previously removed.
Make this commit subject a bit more intuitive, my first impression was 'why to
remove attrib/ folder in hog patch' :)
> ---
> android/hidhost.c | 2 +-
> android/hog.c | 62
> +++++++++++++++++++++++++++---------------------------- android/hog.h |
> 2 +-
> unit/test-hog.c | 2 +-
> 4 files changed, 33 insertions(+), 35 deletions(-)
>
> diff --git a/android/hidhost.c b/android/hidhost.c
> index 3d4ee85..9bd96a1 100644
> --- a/android/hidhost.c
> +++ b/android/hidhost.c
> @@ -816,7 +816,7 @@ static void client_ready_cb(bool success, uint8_t
> att_ecode, void *user_data) goto fail;
> }
>
> - if (!bt_hog_attach(dev->hog, dev->attrib, dev->client)) {
> + if (!bt_hog_attach(dev->hog, dev->client)) {
> error("HoG: unable to attach");
> goto fail;
> }
> diff --git a/android/hog.c b/android/hog.c
> index eb9c9d4..c2017f8 100644
> --- a/android/hog.c
> +++ b/android/hog.c
> @@ -50,10 +50,6 @@
> #include "src/shared/gatt-client.h"
> #include "src/log.h"
>
> -#include "attrib/att.h"
> -#include "attrib/gattrib.h"
> -#include "attrib/gatt.h"
> -
> #include "android/scpp.h"
> #include "android/dis.h"
> #include "android/bas.h"
> @@ -94,7 +90,6 @@ struct bt_hog {
> uint16_t vendor;
> uint16_t product;
> uint16_t version;
> - GAttrib *attrib;
> struct queue *reports;
> struct bt_uhid *uhid;
> int uhid_fd;
> @@ -116,6 +111,11 @@ struct bt_hog {
> struct gatt_db *db;
> };
>
> +struct gatt_char {
> + uint8_t properties;
> + uint16_t value_handle;
> +};
> +
> struct report {
> struct bt_hog *hog;
> uint8_t id;
> @@ -162,8 +162,8 @@ static void report_value_cb(uint16_t value_handle, const
> uint8_t *value, static void report_ccc_written_cb(uint16_t status, void
> *user_data) {
> if (status != 0) {
> - error("Write report characteristic descriptor failed: %s",
> - att_ecode2str(status));
> + error("Write report characteristic descriptor failed: %d",
> + status);
Hmm I think we could have similar code2str function in src/shared/att.
> return;
> }
>
> @@ -201,8 +201,8 @@ static void report_reference_cb(bool success, uint8_t
> status, struct report *report = user_data;
>
> if (!success) {
> - error("Read Report Reference descriptor failed: %s",
> - att_ecode2str(status));
> + error("Read Report Reference descriptor failed: att_ecode %d",
> + status);
> return;
> }
>
> @@ -258,8 +258,7 @@ static void report_read_cb(bool success, uint8_t
> att_ecode, struct report *report = user_data;
>
> if (!success) {
> - error("Error reading Report value: %s",
> - att_ecode2str(att_ecode));
> + error("Error reading Report value: att_ecode %d", att_ecode);
> return;
> }
>
> @@ -312,8 +311,8 @@ static void external_report_reference_cb(bool success,
> uint8_t status, struct queue *chrs;
>
> if (!success) {
> - error("Read External Report Reference descriptor failed: %s",
> - att_ecode2str(status));
> + error("Read External Report Reference descriptor failed: %d",
> + status);
> return;
> }
>
> @@ -403,7 +402,7 @@ static struct report *find_report_by_rtype(struct bt_hog
> *hog, uint8_t rtype, static void output_written_cb(bool success, uint8_t
> status, void *user_data) {
> if (!success) {
> - error("Write output report failed: %s", att_ecode2str(status));
> + error("Write output report failed: att_ecode %d", status);
> return;
> }
> }
> @@ -414,6 +413,7 @@ static void forward_report(struct uhid_event *ev, void
> *user_data) struct report *report;
> void *data;
> int size;
> + uint8_t properties;
>
> report = find_report_by_rtype(hog, ev->u.output.rtype,
> ev->u.output.data[0]);
> @@ -433,12 +433,13 @@ static void forward_report(struct uhid_event *ev, void
> *user_data) if (hog->client == NULL)
> return;
>
> - if (report->decl->properties & GATT_CHR_PROP_WRITE)
> + properties = report->decl->properties;
> + if (properties & BT_GATT_CHRC_PROP_WRITE)
> bt_gatt_client_write_value(hog->client,
> report->decl->value_handle,
> data, size, output_written_cb,
> hog, NULL);
> - else if (report->decl->properties & GATT_CHR_PROP_WRITE_WITHOUT_RESP)
> + else if (properties & BT_GATT_CHRC_PROP_WRITE_WITHOUT_RESP)
> bt_gatt_client_write_without_response(hog->client,
> report->decl->value_handle,
> false, data, size);
> @@ -490,7 +491,7 @@ static void set_report_cb(bool success, uint8_t status,
> void *user_data) rsp.u.set_report_reply.err = status;
>
> if (!success)
> - error("Error setting Report value: %s", att_ecode2str(status));
> + error("Error setting Report value: att_ecode %d", status);
>
> err = bt_uhid_send(hog->uhid, &rsp);
> if (err < 0)
> @@ -562,7 +563,7 @@ static void get_report_cb(bool success, uint8_t status,
> const uint8_t *value, rsp.u.get_report_reply.id = hog->getrep_id;
>
> if (!success) {
> - error("Error reading Report value: %s", att_ecode2str(status));
> + error("Error reading Report value: att_ecode %d", status);
> goto exit;
> }
>
> @@ -738,7 +739,7 @@ static void report_map_read_cb(bool success, uint8_t
> att_ecode, int i;
>
> if (!success) {
> - error("Report Map read failed: %s", att_ecode2str(att_ecode));
> + error("Report Map read failed: att_ecode %d", att_ecode);
> return;
> }
>
> @@ -776,7 +777,7 @@ static void info_read_cb(bool success, uint8_t status,
> const uint8_t *value, struct bt_hog *hog = user_data;
>
> if (!success) {
> - error("HID Information read failed: %s", att_ecode2str(status));
> + error("HID Information read failed: att_ecode %d", status);
> return;
> }
>
> @@ -800,8 +801,8 @@ static void proto_mode_read_cb(bool success, uint8_t
> att_ecode, struct bt_hog *hog = user_data;
>
> if (!success) {
> - error("Protocol Mode characteristic read failed: %s",
> - att_ecode2str(att_ecode));
> + error("Protocol Mode characteristic read failed: att_ecode %d",
> + att_ecode);
> return;
> }
>
> @@ -1022,7 +1023,7 @@ static void hog_attach_hog(struct bt_hog *hog,
> uint16_t service_handle) if (!instance)
> return;
>
> - bt_hog_attach(instance, hog->attrib, hog->client);
> + bt_hog_attach(instance, hog->client);
> queue_push_tail(hog->instances, instance);
> }
>
> @@ -1049,14 +1050,13 @@ static void service_cb(struct gatt_db_attribute
> *attrib, void *user_data) hog_attach_bas(hog, service_handle);
> }
>
> -bool bt_hog_attach(struct bt_hog *hog, void *gatt, void *client)
> +bool bt_hog_attach(struct bt_hog *hog, void *client)
> {
> const struct queue_entry *hog_entry;
>
> - if (hog->attrib || hog->client)
> + if (hog->client)
> return false;
>
> - hog->attrib = g_attrib_ref(gatt);
> hog->client = bt_gatt_client_ref(client);
> hog->db = bt_gatt_client_get_db(hog->client);
>
> @@ -1077,7 +1077,7 @@ bool bt_hog_attach(struct bt_hog *hog, void *gatt,
> void *client) while (hog_entry) {
> struct bt_hog *instance = hog_entry->data;
>
> - bt_hog_attach(instance, gatt, client);
> + bt_hog_attach(instance, client);
> }
>
> if (queue_isempty(hog->reports)) {
> @@ -1096,7 +1096,7 @@ bool bt_hog_attach(struct bt_hog *hog, void *gatt,
> void *client)
>
> void bt_hog_detach(struct bt_hog *hog)
> {
> - if (!hog->attrib || !hog->client)
> + if (!hog->client)
> return;
>
> queue_foreach(hog->bas, (void *) bt_bas_detach, NULL);
> @@ -1111,9 +1111,7 @@ void bt_hog_detach(struct bt_hog *hog)
>
> gatt_db_unref(hog->db);
> bt_gatt_client_unref(hog->client);
> - g_attrib_unref(hog->attrib);
> hog->client = NULL;
> - hog->attrib = NULL;
> }
>
> int bt_hog_set_control_point(struct bt_hog *hog, bool suspend)
> @@ -1149,13 +1147,13 @@ int bt_hog_send_report(struct bt_hog *hog, void
> *data, size_t size, int type)
>
> DBG("hog: Write report, handle 0x%X", report->decl->value_handle);
>
> - if (report->decl->properties & GATT_CHR_PROP_WRITE)
> + if (report->decl->properties & BT_GATT_CHRC_PROP_WRITE)
> bt_gatt_client_write_value(hog->client,
> report->decl->value_handle,
> data, size, output_written_cb,
> hog, NULL);
>
> - if (report->decl->properties & GATT_CHR_PROP_WRITE_WITHOUT_RESP)
> + if (report->decl->properties & BT_GATT_CHRC_PROP_WRITE_WITHOUT_RESP)
> bt_gatt_client_write_without_response(hog->client,
> report->decl->value_handle,
> false, data, size);
> diff --git a/android/hog.h b/android/hog.h
> index 8fe8422..fa3d114 100644
> --- a/android/hog.h
> +++ b/android/hog.h
> @@ -36,7 +36,7 @@ struct bt_hog *bt_hog_new(int fd, const char *name,
> uint16_t vendor, struct bt_hog *bt_hog_ref(struct bt_hog *hog);
> void bt_hog_unref(struct bt_hog *hog);
>
> -bool bt_hog_attach(struct bt_hog *hog, void *gatt, void *client);
> +bool bt_hog_attach(struct bt_hog *hog, void *client);
> void bt_hog_detach(struct bt_hog *hog);
>
> int bt_hog_set_control_point(struct bt_hog *hog, bool suspend);
> diff --git a/unit/test-hog.c b/unit/test-hog.c
> index 16805e7..81aada2 100644
> --- a/unit/test-hog.c
> +++ b/unit/test-hog.c
> @@ -227,7 +227,7 @@ static void test_hog(gconstpointer data)
> {
> struct context *context = create_context(data);
>
> - g_assert(bt_hog_attach(context->hog, context->attrib, NULL));
> + g_assert(bt_hog_attach(context->hog, NULL));
> }
>
> int main(int argc, char *argv[])
--
BR
Szymon Janc
^ permalink raw reply [flat|nested] 41+ messages in thread
* [PATCH 27/28] android/hog: Remove glib dependencies
2015-04-01 16:40 [PATCH 00/28] android/hog Introduce bt_gatt_client Mariusz Skamra
` (25 preceding siblings ...)
2015-04-01 16:40 ` [PATCH 26/28] android/hog: Remove attrib/ Mariusz Skamra
@ 2015-04-01 16:40 ` Mariusz Skamra
2015-04-02 15:45 ` Szymon Janc
2015-04-01 16:40 ` [PATCH 28/28] android/hog: Remove redundant code Mariusz Skamra
27 siblings, 1 reply; 41+ messages in thread
From: Mariusz Skamra @ 2015-04-01 16:40 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Mariusz Skamra
All the glib functions and types have been replaced so that
glib can be excluded
---
android/hog.c | 27 +++++++++++++--------------
1 file changed, 13 insertions(+), 14 deletions(-)
diff --git a/android/hog.c b/android/hog.c
index c2017f8..a18275e 100644
--- a/android/hog.c
+++ b/android/hog.c
@@ -36,8 +36,6 @@
#include <sys/stat.h>
#include <fcntl.h>
-#include <glib.h>
-
#include "lib/bluetooth.h"
#include "lib/sdp.h"
#include "lib/uuid.h"
@@ -93,7 +91,7 @@ struct bt_hog {
struct queue *reports;
struct bt_uhid *uhid;
int uhid_fd;
- gboolean has_report_id;
+ bool has_report_id;
uint16_t bcdhid;
uint8_t bcountrycode;
uint16_t proto_mode_handle;
@@ -263,9 +261,10 @@ static void report_read_cb(bool success, uint8_t att_ecode,
}
if (report->value)
- g_free(report->value);
+ free(report->value);
- report->value = g_memdup(value, len);
+ report->value = new0(uint8_t, len);
+ memcpy(report->value, value, len);
report->len = len;
}
@@ -274,7 +273,7 @@ static struct report *report_new(struct bt_hog *hog, uint16_t value_handle,
{
struct report *report;
- report = g_new0(struct report, 1);
+ report = new0(struct report, 1);
report->hog = hog;
report->decl = new0(struct gatt_char, 1);
report->decl->value_handle = value_handle;
@@ -600,7 +599,7 @@ static void get_report(struct uhid_event *ev, void *user_data)
{
struct bt_hog *hog = user_data;
struct report *report;
- guint8 err;
+ uint8_t err;
/* uhid never sends reqs in parallel; if there's a req, it timed out */
if (hog->getrep_att) {
@@ -752,7 +751,7 @@ static void report_map_read_cb(bool success, uint8_t att_ecode,
&long_item)) {
/* Report ID is short item with prefix 100001xx */
if (!long_item && (value[i] & 0xfc) == 0x84)
- hog->has_report_id = TRUE;
+ hog->has_report_id = true;
DBG("\t%s", item2string(itemstr, &value[i], ilen));
@@ -854,9 +853,9 @@ static void report_free(void *data)
{
struct report *report = data;
- g_free(report->value);
+ free(report->value);
free(report->decl);
- g_free(report);
+ free(report);
}
static void hog_free(void *data)
@@ -872,8 +871,8 @@ static void hog_free(void *data)
bt_dis_unref(hog->dis);
bt_uhid_unref(hog->uhid);
queue_destroy(hog->reports, report_free);
- g_free(hog->name);
- g_free(hog);
+ free(hog->name);
+ free(hog);
}
struct bt_hog *bt_hog_new_default(const char *name, uint16_t vendor,
@@ -892,7 +891,7 @@ struct bt_hog *bt_hog_new(int fd, const char *name, uint16_t vendor,
{
struct bt_hog *hog;
- hog = g_try_new0(struct bt_hog, 1);
+ hog = new0(struct bt_hog, 1);
if (!hog)
return NULL;
@@ -912,7 +911,7 @@ struct bt_hog *bt_hog_new(int fd, const char *name, uint16_t vendor,
return NULL;
}
- hog->name = g_strdup(name);
+ hog->name = strdup(name);
hog->vendor = vendor;
hog->product = product;
hog->version = version;
--
1.9.1
^ permalink raw reply related [flat|nested] 41+ messages in thread
* Re: [PATCH 27/28] android/hog: Remove glib dependencies
2015-04-01 16:40 ` [PATCH 27/28] android/hog: Remove glib dependencies Mariusz Skamra
@ 2015-04-02 15:45 ` Szymon Janc
0 siblings, 0 replies; 41+ messages in thread
From: Szymon Janc @ 2015-04-02 15:45 UTC (permalink / raw)
To: Mariusz Skamra; +Cc: linux-bluetooth
Hi Mariusz,
On Wednesday 01 of April 2015 18:40:43 Mariusz Skamra wrote:
> All the glib functions and types have been replaced so that
> glib can be excluded
> ---
> android/hog.c | 27 +++++++++++++--------------
> 1 file changed, 13 insertions(+), 14 deletions(-)
>
> diff --git a/android/hog.c b/android/hog.c
> index c2017f8..a18275e 100644
> --- a/android/hog.c
> +++ b/android/hog.c
> @@ -36,8 +36,6 @@
> #include <sys/stat.h>
> #include <fcntl.h>
>
> -#include <glib.h>
> -
> #include "lib/bluetooth.h"
> #include "lib/sdp.h"
> #include "lib/uuid.h"
> @@ -93,7 +91,7 @@ struct bt_hog {
> struct queue *reports;
> struct bt_uhid *uhid;
> int uhid_fd;
> - gboolean has_report_id;
> + bool has_report_id;
> uint16_t bcdhid;
> uint8_t bcountrycode;
> uint16_t proto_mode_handle;
> @@ -263,9 +261,10 @@ static void report_read_cb(bool success, uint8_t
> att_ecode, }
>
> if (report->value)
> - g_free(report->value);
> + free(report->value);
>
> - report->value = g_memdup(value, len);
> + report->value = new0(uint8_t, len);
This can return NULL.
> + memcpy(report->value, value, len);
> report->len = len;
> }
>
> @@ -274,7 +273,7 @@ static struct report *report_new(struct bt_hog *hog,
> uint16_t value_handle, {
> struct report *report;
>
> - report = g_new0(struct report, 1);
> + report = new0(struct report, 1);
Ditto.
> report->hog = hog;
> report->decl = new0(struct gatt_char, 1);
> report->decl->value_handle = value_handle;
> @@ -600,7 +599,7 @@ static void get_report(struct uhid_event *ev, void
> *user_data) {
> struct bt_hog *hog = user_data;
> struct report *report;
> - guint8 err;
> + uint8_t err;
>
> /* uhid never sends reqs in parallel; if there's a req, it timed out */
> if (hog->getrep_att) {
> @@ -752,7 +751,7 @@ static void report_map_read_cb(bool success, uint8_t
> att_ecode, &long_item)) {
> /* Report ID is short item with prefix 100001xx */
> if (!long_item && (value[i] & 0xfc) == 0x84)
> - hog->has_report_id = TRUE;
> + hog->has_report_id = true;
>
> DBG("\t%s", item2string(itemstr, &value[i], ilen));
>
> @@ -854,9 +853,9 @@ static void report_free(void *data)
> {
> struct report *report = data;
>
> - g_free(report->value);
> + free(report->value);
> free(report->decl);
> - g_free(report);
> + free(report);
> }
>
> static void hog_free(void *data)
> @@ -872,8 +871,8 @@ static void hog_free(void *data)
> bt_dis_unref(hog->dis);
> bt_uhid_unref(hog->uhid);
> queue_destroy(hog->reports, report_free);
> - g_free(hog->name);
> - g_free(hog);
> + free(hog->name);
> + free(hog);
> }
>
> struct bt_hog *bt_hog_new_default(const char *name, uint16_t vendor,
> @@ -892,7 +891,7 @@ struct bt_hog *bt_hog_new(int fd, const char *name,
> uint16_t vendor, {
> struct bt_hog *hog;
>
> - hog = g_try_new0(struct bt_hog, 1);
> + hog = new0(struct bt_hog, 1);
> if (!hog)
> return NULL;
>
> @@ -912,7 +911,7 @@ struct bt_hog *bt_hog_new(int fd, const char *name,
> uint16_t vendor, return NULL;
> }
>
> - hog->name = g_strdup(name);
> + hog->name = strdup(name);
Ditto.
> hog->vendor = vendor;
> hog->product = product;
> hog->version = version;
--
BR
Szymon Janc
^ permalink raw reply [flat|nested] 41+ messages in thread
* [PATCH 28/28] android/hog: Remove redundant code
2015-04-01 16:40 [PATCH 00/28] android/hog Introduce bt_gatt_client Mariusz Skamra
` (26 preceding siblings ...)
2015-04-01 16:40 ` [PATCH 27/28] android/hog: Remove glib dependencies Mariusz Skamra
@ 2015-04-01 16:40 ` Mariusz Skamra
27 siblings, 0 replies; 41+ messages in thread
From: Mariusz Skamra @ 2015-04-01 16:40 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Mariusz Skamra
---
android/hog.c | 8 --------
1 file changed, 8 deletions(-)
diff --git a/android/hog.c b/android/hog.c
index a18275e..9f64e41 100644
--- a/android/hog.c
+++ b/android/hog.c
@@ -31,13 +31,8 @@
#include <stdlib.h>
#include <stdbool.h>
#include <errno.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
#include "lib/bluetooth.h"
-#include "lib/sdp.h"
#include "lib/uuid.h"
#include "src/shared/util.h"
@@ -64,9 +59,6 @@
#define HOG_PROTO_MODE_BOOT 0
#define HOG_PROTO_MODE_REPORT 1
-#define HOG_REPORT_MAP_MAX_SIZE 512
-#define HID_INFO_SIZE 4
-
static const bt_uuid_t info_uuid = { .type = BT_UUID16,
.value.u16 = 0x2A4A };
static const bt_uuid_t report_map_uuid = { .type = BT_UUID16,
--
1.9.1
^ permalink raw reply related [flat|nested] 41+ messages in thread