* [PATCH 1/2] android/gatt: Keep client notify functions names consistent
@ 2014-03-24 14:27 Grzegorz Kolodziejczyk
2014-03-24 14:27 ` [PATCH 2/2] android/gatt: Handle get characteristic client command Grzegorz Kolodziejczyk
2014-03-25 10:36 ` [PATCH 1/2] android/gatt: Keep client notify functions names consistent Szymon Janc
0 siblings, 2 replies; 3+ messages in thread
From: Grzegorz Kolodziejczyk @ 2014-03-24 14:27 UTC (permalink / raw)
To: linux-bluetooth
We should use consistent names for client notify functions.
---
android/gatt.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/android/gatt.c b/android/gatt.c
index 2189e8e..302a9b9 100644
--- a/android/gatt.c
+++ b/android/gatt.c
@@ -292,7 +292,7 @@ static void connection_cleanup(struct gatt_device *device)
}
}
-static void send_disconnect_notify(int32_t id, struct gatt_device *dev,
+static void send_client_disconnect_notify(int32_t id, struct gatt_device *dev,
uint8_t status)
{
struct hal_ev_gatt_client_disconnect ev;
@@ -306,12 +306,12 @@ static void send_disconnect_notify(int32_t id, struct gatt_device *dev,
HAL_EV_GATT_CLIENT_DISCONNECT, sizeof(ev), &ev);
}
-static void disconnect_notify(void *data, void *user_data)
+static void client_disconnect_notify(void *data, void *user_data)
{
struct gatt_device *dev = user_data;
int32_t id = PTR_TO_INT(data);
- send_disconnect_notify(id, dev, HAL_STATUS_SUCCESS);
+ send_client_disconnect_notify(id, dev, HAL_STATUS_SUCCESS);
}
static bool is_device_wating_for_connect(const bdaddr_t *addr,
@@ -402,7 +402,7 @@ static gboolean disconnected_cb(GIOChannel *io, GIOCondition cond,
done:
connection_cleanup(dev);
- queue_foreach(dev->clients, disconnect_notify, dev);
+ queue_foreach(dev->clients, client_disconnect_notify, dev);
destroy_device(dev);
return FALSE;
@@ -802,7 +802,7 @@ reply:
* If this is last client, this is still OK to do because on connect
* request we do le scan and wait until remote device start
* advertisement */
- send_disconnect_notify(cmd->client_if, dev, HAL_STATUS_SUCCESS);
+ send_client_disconnect_notify(cmd->client_if, dev, HAL_STATUS_SUCCESS);
/* If there is more clients just return */
if (!queue_isempty(dev->clients))
--
1.8.5.2
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH 2/2] android/gatt: Handle get characteristic client command
2014-03-24 14:27 [PATCH 1/2] android/gatt: Keep client notify functions names consistent Grzegorz Kolodziejczyk
@ 2014-03-24 14:27 ` Grzegorz Kolodziejczyk
2014-03-25 10:36 ` [PATCH 1/2] android/gatt: Keep client notify functions names consistent Szymon Janc
1 sibling, 0 replies; 3+ messages in thread
From: Grzegorz Kolodziejczyk @ 2014-03-24 14:27 UTC (permalink / raw)
To: linux-bluetooth
This adds get characteristic client command handling.
---
android/gatt.c | 247 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 242 insertions(+), 5 deletions(-)
diff --git a/android/gatt.c b/android/gatt.c
index 302a9b9..fbc3b61 100644
--- a/android/gatt.c
+++ b/android/gatt.c
@@ -53,6 +53,28 @@ struct gatt_client {
uint8_t uuid[16];
};
+struct gatt_id {
+ bt_uuid_t uuid;
+ uint8_t inst_id;
+};
+
+struct gatt_srvc_char {
+ struct gatt_id id;
+ struct gatt_char ch;
+};
+
+struct gatt_srvc {
+ struct gatt_id id;
+ struct gatt_primary service;
+
+ struct queue *chars;
+};
+
+struct generic_call_data {
+ struct gatt_device *dev;
+ struct gatt_srvc *gatt_srvc;
+};
+
struct gatt_device {
bdaddr_t bdaddr;
uint8_t bdaddr_type;
@@ -66,6 +88,7 @@ struct gatt_device {
GIOChannel *att_io;
struct queue *services;
+ uint8_t char_inst_id;
guint watch_id;
};
@@ -79,6 +102,14 @@ static struct queue *conn_wait_queue = NULL; /* Devs waiting to connect */
static void bt_le_discovery_stop_cb(void);
+static void free_gatt_service(void *data)
+{
+ struct gatt_srvc *srvc = data;
+
+ queue_destroy(srvc->chars, free);
+ free(srvc);
+}
+
static bool match_client_by_uuid(const void *data, const void *user_data)
{
const uint8_t *exp_uuid = user_data;
@@ -123,12 +154,43 @@ static bool match_dev_by_conn_id(const void *data, const void *user_data)
return dev->conn_id == conn_id;
}
+static bool match_srvc_by_gatt_id(const void *data, const void *user_data)
+{
+ const struct gatt_id *exp_id = user_data;
+ const struct gatt_srvc *service = data;
+ bt_uuid_t uuid;
+
+ bt_string_to_uuid(&uuid, service->service.uuid);
+ if (service->id.inst_id == exp_id->inst_id)
+ return !bt_uuid_cmp(&uuid, &exp_id->uuid);
+
+ return false;
+}
+
+static bool match_char_by_higher_inst_id(const void *data,
+ const void *user_data)
+{
+ const struct gatt_srvc_char *chars = data;
+ uint8_t inst_id = PTR_TO_INT(user_data);
+
+ /* For now we match inst_id as it is unique, we'll match uuids later */
+ return inst_id < chars->id.inst_id;
+}
+
+static bool match_char_by_inst_id(const void *data, const void *user_data)
+{
+ const struct gatt_srvc_char *chars = data;
+ uint8_t inst_id = PTR_TO_INT(user_data);
+
+ return inst_id == chars->id.inst_id;
+}
+
static void destroy_device(void *data)
{
struct gatt_device *dev = data;
queue_destroy(dev->clients, NULL);
- queue_destroy(dev->services, free);
+ queue_destroy(dev->services, free_gatt_service);
free(dev);
}
@@ -224,19 +286,26 @@ static void primary_cb(uint8_t status, GSList *services, void *user_data)
for (l = services; l; l = l->next) {
struct hal_ev_gatt_client_search_result ev_res;
struct gatt_primary *prim = l->data;
- struct gatt_primary *p;
+ struct gatt_srvc *p;
bt_uuid_t uuid;
- p = new0(struct gatt_primary, 1);
+ p = new0(struct gatt_srvc, 1);
if (!p) {
error("gatt: Cannot allocate memory for gatt_primary");
continue;
}
+ p->chars = queue_new();
+ if (!p->chars) {
+ error("gatt: Cannot allocate memory for char cache");
+ free(p);
+ continue;
+ }
+
memset(&ev_res, 0, sizeof(ev_res));
/* Put primary service to our local list */
- memcpy(p, prim, sizeof(*p));
+ memcpy(&p->service, prim, sizeof(p->service));
if (!queue_push_tail(dev->services, p)) {
error("gatt: Cannot push primary service to the list");
free(p);
@@ -869,13 +938,181 @@ static void handle_client_get_included_service(const void *buf, uint16_t len)
HAL_STATUS_FAILED);
}
+static void send_client_char_notify(const struct gatt_srvc_char *chars,
+ uint8_t status, struct generic_call_data *data)
+{
+ struct hal_ev_gatt_client_get_characteristic ev;
+ bt_uuid_t uuid;
+
+ ev.conn_id = data->dev->conn_id;
+ ev.status = status;
+ ev.char_prop = chars->ch.properties;
+
+ /* TODO need to be handled for included services too */
+ ev.srvc_id.is_primary = 1;
+ ev.srvc_id.inst_id = data->gatt_srvc->id.inst_id;
+ bt_string_to_uuid(&uuid, data->gatt_srvc->service.uuid);
+ memcpy(&ev.srvc_id.uuid, &uuid.value.u128.data,
+ sizeof(ev.srvc_id.uuid));
+
+ ev.char_id.inst_id = chars->id.inst_id;
+ bt_string_to_uuid(&uuid, chars->ch.uuid);
+ memcpy(&ev.char_id.uuid, &uuid.value.u128.data,
+ sizeof(ev.char_id.uuid));
+
+ ipc_send_notif(hal_ipc, HAL_SERVICE_ID_GATT,
+ HAL_EV_GATT_CLIENT_GET_CHARACTERISTIC,
+ sizeof(ev), &ev);
+}
+
+static void cache_all_srvc_chars(GSList *characteristics, struct queue *q)
+{
+ uint16_t inst_id = 0;
+ bt_uuid_t uuid;
+ GSList *l;
+
+ /* Refresh chararcter cache if already exist */
+ if (!queue_isempty(q))
+ queue_remove_all(q, NULL, NULL, free);
+
+ for (l = characteristics; l; l = l->next) {
+ struct gatt_srvc_char *chars;
+
+ chars = new0(struct gatt_srvc_char, 1);
+ if (!chars) {
+ error("gatt: Could not allocate characteristic");
+ continue;
+ }
+
+ memcpy(&chars->ch, l->data, sizeof(chars->ch));
+
+ bt_string_to_uuid(&uuid, chars->ch.uuid);
+ bt_uuid_to_uuid128(&chars->id.uuid, &uuid);
+
+ /* For now we increment inst_id and use it as characteristic
+ * handle
+ */
+ chars->id.inst_id = ++inst_id;
+
+ if (!queue_push_tail(q, chars))
+ info("gatt: Error while caching characteristic");
+ }
+}
+
+static void gatt_discover_char_cb(uint8_t status, GSList *characteristics,
+ void *user_data)
+{
+ struct generic_call_data *call_data = user_data;
+
+ cache_all_srvc_chars(characteristics, call_data->gatt_srvc->chars);
+
+ if (call_data && !queue_isempty(call_data->gatt_srvc->chars))
+ send_client_char_notify(queue_peek_head(
+ call_data->gatt_srvc->chars),
+ HAL_STATUS_SUCCESS, call_data);
+
+ free(call_data);
+}
+
+static void hal_srvc_id_to_gatt_id(const struct hal_gatt_srvc_id *from,
+ struct gatt_id *to)
+{
+ uint128_t uuid128;
+
+ to->inst_id = from->inst_id;
+
+ memcpy(&uuid128.data, &from->uuid, sizeof(uuid128));
+ bt_uuid128_create(&to->uuid, uuid128);
+}
+
static void handle_client_get_characteristic(const void *buf, uint16_t len)
{
+ const struct hal_cmd_gatt_client_get_characteristic *cmd = buf;
+ struct generic_call_data *call_data = NULL;
+ struct gatt_srvc_char *chars = NULL;
+ struct gatt_id match_id;
+ struct gatt_device *dev;
+ struct gatt_srvc *srvc;
+ uint8_t status;
+ uint8_t char_status;
+
DBG("");
+ if (!cmd) {
+ status = HAL_STATUS_FAILED;
+ goto done;
+ }
+
+ /* search on list by connection id */
+ dev = queue_find(conn_list, match_dev_by_conn_id,
+ INT_TO_PTR(cmd->conn_id));
+ if (!dev) {
+ error("gatt: conn_id=%d not found", cmd->conn_id);
+ status = HAL_STATUS_FAILED;
+ goto done;
+ }
+
+ hal_srvc_id_to_gatt_id(&cmd->srvc_id, &match_id);
+ srvc = queue_find(dev->services, match_srvc_by_gatt_id, &match_id);
+ if (!srvc) {
+ error("gatt: Service with inst_id: %d not found",
+ match_id.inst_id);
+ status = HAL_STATUS_FAILED;
+ goto done;
+ }
+
+ call_data = new0(struct generic_call_data, 1);
+ if (!call_data) {
+ error("gatt: Cannot allocate call data");
+ status = HAL_STATUS_FAILED;
+ goto done;
+ }
+
+ call_data->gatt_srvc = srvc;
+ call_data->dev = dev;
+
+ /* Discover all characteristics for services */
+ if (queue_isempty(srvc->chars)) {
+ gatt_discover_char(dev->attrib, srvc->service.range.start,
+ srvc->service.range.end, NULL,
+ gatt_discover_char_cb, call_data);
+ } else {
+ if (cmd->number)
+ chars = queue_find(srvc->chars,
+ match_char_by_higher_inst_id,
+ INT_TO_PTR(cmd->gatt_id[0].inst_id));
+ else
+ chars = queue_peek_head(srvc->chars);
+
+ char_status = HAL_STATUS_SUCCESS;
+
+ if (!chars) {
+ error("gatt: Can't get next char");
+ /* Return last known/given char with failed status if
+ * no char left.
+ */
+ chars = queue_find(srvc->chars, match_char_by_inst_id,
+ INT_TO_PTR(cmd->gatt_id[0].inst_id));
+
+ char_status = HAL_STATUS_FAILED;
+
+ /* free generic data if no given char is found */
+ if (!chars)
+ free(call_data);
+ }
+ }
+
+ status = HAL_STATUS_SUCCESS;
+
+done:
ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_GATT,
HAL_OP_GATT_CLIENT_GET_CHARACTERISTIC,
- HAL_STATUS_FAILED);
+ status);
+
+ if (chars) {
+ send_client_char_notify(chars, char_status, call_data);
+ free(call_data);
+ }
}
static void handle_client_get_descriptor(const void *buf, uint16_t len)
--
1.8.5.2
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH 1/2] android/gatt: Keep client notify functions names consistent
2014-03-24 14:27 [PATCH 1/2] android/gatt: Keep client notify functions names consistent Grzegorz Kolodziejczyk
2014-03-24 14:27 ` [PATCH 2/2] android/gatt: Handle get characteristic client command Grzegorz Kolodziejczyk
@ 2014-03-25 10:36 ` Szymon Janc
1 sibling, 0 replies; 3+ messages in thread
From: Szymon Janc @ 2014-03-25 10:36 UTC (permalink / raw)
To: Grzegorz Kolodziejczyk; +Cc: linux-bluetooth
Hi Grzegorz,
On Monday 24 of March 2014 15:27:23 Grzegorz Kolodziejczyk wrote:
> We should use consistent names for client notify functions.
> ---
> android/gatt.c | 10 +++++-----
> 1 file changed, 5 insertions(+), 5 deletions(-)
>
> diff --git a/android/gatt.c b/android/gatt.c
> index 2189e8e..302a9b9 100644
> --- a/android/gatt.c
> +++ b/android/gatt.c
> @@ -292,7 +292,7 @@ static void connection_cleanup(struct gatt_device
> *device) }
> }
>
> -static void send_disconnect_notify(int32_t id, struct gatt_device *dev,
> +static void send_client_disconnect_notify(int32_t id, struct gatt_device
> *dev, uint8_t status)
> {
> struct hal_ev_gatt_client_disconnect ev;
> @@ -306,12 +306,12 @@ static void send_disconnect_notify(int32_t id, struct
> gatt_device *dev, HAL_EV_GATT_CLIENT_DISCONNECT, sizeof(ev), &ev);
> }
>
> -static void disconnect_notify(void *data, void *user_data)
> +static void client_disconnect_notify(void *data, void *user_data)
> {
> struct gatt_device *dev = user_data;
> int32_t id = PTR_TO_INT(data);
>
> - send_disconnect_notify(id, dev, HAL_STATUS_SUCCESS);
> + send_client_disconnect_notify(id, dev, HAL_STATUS_SUCCESS);
> }
>
> static bool is_device_wating_for_connect(const bdaddr_t *addr,
> @@ -402,7 +402,7 @@ static gboolean disconnected_cb(GIOChannel *io,
> GIOCondition cond, done:
> connection_cleanup(dev);
>
> - queue_foreach(dev->clients, disconnect_notify, dev);
> + queue_foreach(dev->clients, client_disconnect_notify, dev);
> destroy_device(dev);
>
> return FALSE;
> @@ -802,7 +802,7 @@ reply:
> * If this is last client, this is still OK to do because on connect
> * request we do le scan and wait until remote device start
> * advertisement */
> - send_disconnect_notify(cmd->client_if, dev, HAL_STATUS_SUCCESS);
> + send_client_disconnect_notify(cmd->client_if, dev, HAL_STATUS_SUCCESS);
>
> /* If there is more clients just return */
> if (!queue_isempty(dev->clients))
Patch 1 is now applied, thanks.
Patch 2 needs fixing as discussed offline.
--
BR
Szymon Janc
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2014-03-25 10:36 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-03-24 14:27 [PATCH 1/2] android/gatt: Keep client notify functions names consistent Grzegorz Kolodziejczyk
2014-03-24 14:27 ` [PATCH 2/2] android/gatt: Handle get characteristic client command Grzegorz Kolodziejczyk
2014-03-25 10:36 ` [PATCH 1/2] android/gatt: Keep client notify functions names consistent Szymon Janc
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.