* [PATCHv3 1/8] android/gatt: Add helper for getting device by conn_id
@ 2014-03-28 9:45 Marcin Kraglak
2014-03-28 9:45 ` [PATCHv3 2/8] android/gatt: Add initial implementation of get_included_service Marcin Kraglak
` (7 more replies)
0 siblings, 8 replies; 9+ messages in thread
From: Marcin Kraglak @ 2014-03-28 9:45 UTC (permalink / raw)
To: linux-bluetooth
It will look for cgatt_device by conn_id.
---
android/gatt.c | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/android/gatt.c b/android/gatt.c
index 81b29af..92e16d4 100644
--- a/android/gatt.c
+++ b/android/gatt.c
@@ -722,6 +722,11 @@ static struct gatt_device *find_device(bdaddr_t *addr)
return NULL;
}
+static struct gatt_device *find_device_by_conn_id(int32_t conn_id)
+{
+ return queue_find(conn_list, match_dev_by_conn_id, INT_TO_PTR(conn_id));
+}
+
static void handle_client_connect(const void *buf, uint16_t len)
{
const struct hal_cmd_gatt_client_connect *cmd = buf;
@@ -858,8 +863,7 @@ static void handle_client_disconnect(const void *buf, uint16_t len)
ba2str((bdaddr_t *)&cmd->bdaddr, addr);
- dev = queue_find(conn_list, match_dev_by_conn_id,
- INT_TO_PTR(cmd->conn_id));
+ dev = find_device_by_conn_id(cmd->conn_id);
if (!dev) {
error("gatt: dev %s with conn_id=%d not found",
addr, cmd->conn_id);
@@ -924,8 +928,7 @@ static void handle_client_search_service(const void *buf, uint16_t len)
DBG("");
- dev = queue_find(conn_list, match_dev_by_conn_id,
- INT_TO_PTR(cmd->conn_id));
+ dev = find_device_by_conn_id(cmd->conn_id);
if (!dev) {
error("gatt: dev with conn_id=%d not found", cmd->conn_id);
status = HAL_STATUS_FAILED;
@@ -1048,8 +1051,7 @@ static bool find_service(int32_t conn_id, struct element_id *service_id,
struct gatt_device *device;
struct service *service;
- device = queue_find(conn_list, match_dev_by_conn_id,
- INT_TO_PTR(conn_id));
+ device = find_device_by_conn_id(conn_id);
if (!device) {
error("gatt: conn_id=%d not found", conn_id);
return false;
--
1.8.3.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCHv3 2/8] android/gatt: Add initial implementation of get_included_service
2014-03-28 9:45 [PATCHv3 1/8] android/gatt: Add helper for getting device by conn_id Marcin Kraglak
@ 2014-03-28 9:45 ` Marcin Kraglak
2014-03-28 9:45 ` [PATCHv3 3/8] android/gatt: Add get_included_data struct and callback Marcin Kraglak
` (6 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Marcin Kraglak @ 2014-03-28 9:45 UTC (permalink / raw)
To: linux-bluetooth
It will look for included service in range passed in command.
It call gatt_find_included(), but without result callback now,
as it is initial version.
---
android/gatt.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 55 insertions(+), 1 deletion(-)
diff --git a/android/gatt.c b/android/gatt.c
index 92e16d4..a801525 100644
--- a/android/gatt.c
+++ b/android/gatt.c
@@ -949,13 +949,67 @@ reply:
HAL_OP_GATT_CLIENT_SEARCH_SERVICE, status);
}
+static bool match_service_by_uuid(const void *data, const void *user_data)
+{
+ const struct service *service = data;
+ const bt_uuid_t *uuid = user_data;
+ bt_uuid_t service_uuid;
+
+ if (bt_string_to_uuid(&service_uuid, service->primary.uuid) < 0)
+ return false;
+
+ return !bt_uuid_cmp(uuid, &service_uuid);
+}
+
+static struct service *find_service_bu_uuid(struct gatt_device *device,
+ bt_uuid_t *uuid)
+{
+ return queue_find(device->services, match_service_by_uuid, uuid);
+}
+
static void handle_client_get_included_service(const void *buf, uint16_t len)
{
+ const struct hal_cmd_gatt_client_get_included_service *cmd = buf;
+ struct gatt_device *device;
+ struct service *service;
+ uint8_t status;
+
DBG("");
+ device = find_device_by_conn_id(cmd->conn_id);
+ if (!device) {
+ status = HAL_STATUS_FAILED;
+ goto failed;
+ }
+
+ if (queue_isempty(device->services)) {
+ status = HAL_STATUS_FAILED;
+ goto failed;
+ }
+
+ if (!cmd->number) {
+ service = queue_peek_head(device->services);
+ } else {
+ bt_uuid_t uuid;
+
+ android2uuid(cmd->srvc_id->uuid, &uuid);
+ service = find_service_bu_uuid(device, &uuid);
+ }
+
+ if (!service) {
+ status = HAL_STATUS_FAILED;
+ goto failed;
+ }
+
+ gatt_find_included(device->attrib, service->primary.range.start,
+ service->primary.range.end, NULL, NULL);
+
+ status = HAL_STATUS_SUCCESS;
+
+failed:
ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_GATT,
HAL_OP_GATT_CLIENT_GET_INCLUDED_SERVICE,
- HAL_STATUS_FAILED);
+ status);
}
static void send_client_char_notify(const struct characteristic *ch,
--
1.8.3.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCHv3 3/8] android/gatt: Add get_included_data struct and callback
2014-03-28 9:45 [PATCHv3 1/8] android/gatt: Add helper for getting device by conn_id Marcin Kraglak
2014-03-28 9:45 ` [PATCHv3 2/8] android/gatt: Add initial implementation of get_included_service Marcin Kraglak
@ 2014-03-28 9:45 ` Marcin Kraglak
2014-03-28 9:45 ` [PATCHv3 4/8] android/gatt: Add implementation of get_included_cb Marcin Kraglak
` (5 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Marcin Kraglak @ 2014-03-28 9:45 UTC (permalink / raw)
To: linux-bluetooth
Create user data passed to callback get_included_cb.
It will handle included services and pass it to notification.
---
android/gatt.c | 27 ++++++++++++++++++++++++++-
1 file changed, 26 insertions(+), 1 deletion(-)
diff --git a/android/gatt.c b/android/gatt.c
index a801525..e2accb7 100644
--- a/android/gatt.c
+++ b/android/gatt.c
@@ -967,9 +967,23 @@ static struct service *find_service_bu_uuid(struct gatt_device *device,
return queue_find(device->services, match_service_by_uuid, uuid);
}
+struct get_included_data {
+ struct service *service;
+ struct gatt_device *device;
+};
+
+static void get_included_cb(uint8_t status, GSList *included, void *user_data)
+{
+ struct get_included_data *data = user_data;
+
+ /* TODO pass included services to notification */
+ free(data);
+}
+
static void handle_client_get_included_service(const void *buf, uint16_t len)
{
const struct hal_cmd_gatt_client_get_included_service *cmd = buf;
+ struct get_included_data *data;
struct gatt_device *device;
struct service *service;
uint8_t status;
@@ -1001,8 +1015,19 @@ static void handle_client_get_included_service(const void *buf, uint16_t len)
goto failed;
}
+ data = new0(struct get_included_data, 1);
+ if (!data) {
+ error("gatt: failed to allocate memory for included_data");
+ status = HAL_STATUS_FAILED;
+ goto failed;
+ }
+
+ data->service = service;
+ data->device = device;
+
gatt_find_included(device->attrib, service->primary.range.start,
- service->primary.range.end, NULL, NULL);
+ service->primary.range.end, get_included_cb,
+ data);
status = HAL_STATUS_SUCCESS;
--
1.8.3.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCHv3 4/8] android/gatt: Add implementation of get_included_cb
2014-03-28 9:45 [PATCHv3 1/8] android/gatt: Add helper for getting device by conn_id Marcin Kraglak
2014-03-28 9:45 ` [PATCHv3 2/8] android/gatt: Add initial implementation of get_included_service Marcin Kraglak
2014-03-28 9:45 ` [PATCHv3 3/8] android/gatt: Add get_included_data struct and callback Marcin Kraglak
@ 2014-03-28 9:45 ` Marcin Kraglak
2014-03-28 9:45 ` [PATCHv3 5/8] android/gatt: Add initial implementation of register_for_notification Marcin Kraglak
` (4 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Marcin Kraglak @ 2014-03-28 9:45 UTC (permalink / raw)
To: linux-bluetooth
It will pass found services to upper layer with notification.
Caching included services should be done later.
---
android/gatt.c | 44 +++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 43 insertions(+), 1 deletion(-)
diff --git a/android/gatt.c b/android/gatt.c
index e2accb7..9c17963 100644
--- a/android/gatt.c
+++ b/android/gatt.c
@@ -974,10 +974,52 @@ struct get_included_data {
static void get_included_cb(uint8_t status, GSList *included, void *user_data)
{
+ struct hal_ev_gatt_client_get_inc_service ev;
struct get_included_data *data = user_data;
+ struct gatt_device *device = data->device;
+ struct service *service = data->service;
+ bt_uuid_t uuid;
+
+ DBG("");
- /* TODO pass included services to notification */
free(data);
+
+ if (status) {
+ error("gatt: no included services found");
+ return;
+ }
+
+ bt_string_to_uuid(&uuid, service->primary.uuid);
+
+ /* TODO store included services in device->services list */
+ for (; included; included = included->next) {
+ struct gatt_included *included_service = included->data;
+ bt_uuid_t included_uuid;
+
+ ev.conn_id = device->conn_id;
+ ev.status = HAL_STATUS_SUCCESS;
+
+ ev.srvc_id.inst_id = 0;
+ uuid2android(&uuid, ev.srvc_id.uuid);
+
+ ev.incl_srvc_id.inst_id = 0;
+ bt_string_to_uuid(&included_uuid, included_service->uuid);
+ uuid2android(&included_uuid, ev.incl_srvc_id.uuid);
+
+ ipc_send_notif(hal_ipc, HAL_SERVICE_ID_GATT ,
+ HAL_EV_GATT_CLIENT_GET_INC_SERVICE,
+ sizeof(ev), &ev);
+ }
+
+ /* Android expects notification with error status in the end */
+ ev.conn_id = device->conn_id;
+ ev.status = HAL_STATUS_FAILED;
+ ev.srvc_id.inst_id = 0;
+ uuid2android(&uuid, ev.srvc_id.uuid);
+
+ ipc_send_notif(hal_ipc, HAL_SERVICE_ID_GATT ,
+ HAL_EV_GATT_CLIENT_GET_INC_SERVICE,
+ sizeof(ev), &ev);
}
static void handle_client_get_included_service(const void *buf, uint16_t len)
--
1.8.3.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCHv3 5/8] android/gatt: Add initial implementation of register_for_notification
2014-03-28 9:45 [PATCHv3 1/8] android/gatt: Add helper for getting device by conn_id Marcin Kraglak
` (2 preceding siblings ...)
2014-03-28 9:45 ` [PATCHv3 4/8] android/gatt: Add implementation of get_included_cb Marcin Kraglak
@ 2014-03-28 9:45 ` Marcin Kraglak
2014-03-28 9:45 ` [PATCHv3 6/8] android/gatt: Add send_register_for_notif_ev function Marcin Kraglak
` (3 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Marcin Kraglak @ 2014-03-28 9:45 UTC (permalink / raw)
To: linux-bluetooth
It will register notification and indication handler for given parameters.
Proper callback should be send with status of registration.
---
android/gatt.c | 188 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 186 insertions(+), 2 deletions(-)
diff --git a/android/gatt.c b/android/gatt.c
index 9c17963..aaf4393 100644
--- a/android/gatt.c
+++ b/android/gatt.c
@@ -51,6 +51,7 @@
struct gatt_client {
int32_t id;
uint8_t uuid[16];
+ struct queue *notifications;
};
struct element_id {
@@ -70,6 +71,16 @@ struct service {
struct queue *chars;
};
+struct notification_data {
+ struct hal_gatt_srvc_id service;
+ struct hal_gatt_gatt_id ch;
+ struct gatt_client *client;
+ struct gatt_device *dev;
+ guint notif_id;
+ guint ind_id;
+ int ref;
+};
+
struct gatt_device {
bdaddr_t bdaddr;
uint8_t bdaddr_type;
@@ -204,6 +215,54 @@ static bool match_char_by_higher_inst_id(const void *data,
return inst_id < ch->id.instance;
}
+static bool match_char_by_instance(const void *data, const void *user_data)
+{
+ const struct characteristic *ch = data;
+ uint8_t inst_id = PTR_TO_INT(user_data);
+
+ return inst_id == ch->id.instance;
+}
+
+static bool match_notification(const void *a, const void *b)
+{
+ const struct notification_data *a1 = a;
+ const struct notification_data *b1 = b;
+
+ if (bacmp(&a1->dev->bdaddr, &b1->dev->bdaddr))
+ return false;
+ if (memcmp(&a1->ch, &b1->ch, sizeof(a1->ch)))
+ return false;
+ if (memcmp(&a1->service, &b1->service, sizeof(a1->service)))
+ return false;
+
+ return true;
+}
+
+static void destroy_notification(void *data)
+{
+ struct notification_data *notification = data;
+
+ if (--notification->ref)
+ return;
+
+ queue_remove_if(notification->client->notifications, match_notification,
+ notification);
+ free(notification);
+}
+
+static void unregister_notification(void *data)
+{
+ struct notification_data *notification = data;
+
+ if (notification->notif_id)
+ g_attrib_unregister(notification->dev->attrib,
+ notification->notif_id);
+
+ if (notification->ind_id)
+ g_attrib_unregister(notification->dev->attrib,
+ notification->ind_id);
+}
+
static void destroy_device(void *data)
{
struct gatt_device *dev = data;
@@ -216,6 +275,26 @@ static void destroy_device(void *data)
free(dev);
}
+static void destroy_gatt_client(void *data)
+{
+ struct gatt_client *client = data;
+
+ /* First we want to get all notifications and unregister them.
+ * We don't pass unregister_notiication to queue_destroy,
+ * because destroy notification performs operations on queue
+ * too. So remove all elements and then destroy queue */
+ while (queue_peek_head(client->notifications)) {
+ struct notification_data *notification;
+
+ notification = queue_pop_head(client->notifications);
+ unregister_notification(notification);
+ }
+
+ queue_destroy(client->notifications, free);
+
+ free(client);
+}
+
static void handle_client_register(const void *buf, uint16_t len)
{
const struct hal_cmd_gatt_client_register *cmd = buf;
@@ -247,6 +326,14 @@ static void handle_client_register(const void *buf, uint16_t len)
memcpy(client->uuid, cmd->uuid, sizeof(client->uuid));
+ client->notifications = queue_new();
+ if (!client->notifications) {
+ error("gatt: couldn't allocate notifications queue");
+ destroy_gatt_client(client);
+ status = HAL_STATUS_FAILED;
+ goto failed;
+ }
+
client->id = client_cnt++;
queue_push_head(gatt_clients, client);
@@ -281,7 +368,7 @@ static void handle_client_unregister(const void *buf, uint16_t len)
goto failed;
}
- free(cl);
+ destroy_gatt_client(cl);
status = HAL_STATUS_SUCCESS;
failed:
@@ -1311,11 +1398,108 @@ static void handle_client_execute_write(const void *buf, uint16_t len)
static void handle_client_register_for_notification(const void *buf,
uint16_t len)
{
+ const struct hal_cmd_gatt_client_register_for_notification *cmd = buf;
+ struct notification_data *notification;
+ char uuid[MAX_LEN_UUID_STR];
+ struct gatt_client *client;
+ struct characteristic *c;
+ struct element_id match_id;
+ struct gatt_device *dev;
+ struct service *service;
+ uint8_t status;
+ bdaddr_t addr;
+
DBG("");
+ client = find_client_by_id(cmd->client_if);
+ if (!client) {
+ status = HAL_STATUS_FAILED;
+ goto failed;
+ }
+
+ android2bdaddr((bdaddr_t *)&cmd->bdaddr, &addr);
+
+ dev = queue_find(conn_list, match_dev_by_bdaddr, &addr);
+ if (!dev) {
+ status = HAL_STATUS_FAILED;
+ goto failed;
+ }
+
+ hal_srvc_id_to_element_id(&cmd->srvc_id, &match_id);
+ service = queue_find(dev->services, match_srvc_by_element_id,
+ &match_id);
+ bt_uuid_to_string(&match_id.uuid, uuid, MAX_LEN_UUID_STR);
+ if (!service) {
+ status = HAL_STATUS_FAILED;
+ goto failed;
+ }
+
+ c = queue_find(service->chars, match_char_by_instance,
+ INT_TO_PTR(cmd->char_id.inst_id));
+ if (!c) {
+ status = HAL_STATUS_FAILED;
+ goto failed;
+ }
+
+ notification = new0(struct notification_data, 1);
+ if (!notification) {
+ status = HAL_STATUS_FAILED;
+ goto failed;
+ }
+
+ memcpy(¬ification->ch, &cmd->char_id, sizeof(notification->ch));
+ memcpy(¬ification->service, &cmd->srvc_id,
+ sizeof(notification->service));
+ notification->dev = dev;
+ notification->client = client;
+
+ if (queue_find(client->notifications, match_notification,
+ notification)) {
+ free(notification);
+ status = HAL_STATUS_SUCCESS;
+ goto failed;
+ }
+
+ notification->notif_id = g_attrib_register(dev->attrib,
+ ATT_OP_HANDLE_NOTIFY,
+ c->ch.value_handle,
+ NULL, notification,
+ destroy_notification);
+ if (!notification->notif_id) {
+ free(notification);
+ status = HAL_STATUS_FAILED;
+ goto failed;
+ }
+
+ notification->ind_id = g_attrib_register(dev->attrib, ATT_OP_HANDLE_IND,
+ c->ch.value_handle,
+ NULL, notification,
+ destroy_notification);
+ if (!notification->ind_id) {
+ g_attrib_unregister(dev->attrib, notification->notif_id);
+ free(notification);
+ status = HAL_STATUS_FAILED;
+ goto failed;
+ }
+
+ /* Because same data - notification - is shared by two handlers, we
+ * introduce ref counter to be sure that data can be freed with no risk.
+ * Counter is decremented in destroy_notification */
+ notification->ref = 2;
+
+ if (!queue_push_tail(client->notifications, notification)) {
+ unregister_notification(notification);
+ status = HAL_STATUS_FAILED;
+ goto failed;
+ }
+
+ status = HAL_STATUS_SUCCESS;
+
+failed:
+ /* TODO: send callback with notification enabled/disabled */
ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_GATT,
HAL_OP_GATT_CLIENT_REGISTER_FOR_NOTIFICATION,
- HAL_STATUS_FAILED);
+ status);
}
static void handle_client_deregister_for_notification(const void *buf,
--
1.8.3.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCHv3 6/8] android/gatt: Add send_register_for_notif_ev function
2014-03-28 9:45 [PATCHv3 1/8] android/gatt: Add helper for getting device by conn_id Marcin Kraglak
` (3 preceding siblings ...)
2014-03-28 9:45 ` [PATCHv3 5/8] android/gatt: Add initial implementation of register_for_notification Marcin Kraglak
@ 2014-03-28 9:45 ` Marcin Kraglak
2014-03-28 9:45 ` [PATCHv3 7/8] android/gatt: Add handler for ATT_OP_HANDLE_NOTIFY and ATT_OP_HANDLE_IND Marcin Kraglak
` (2 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Marcin Kraglak @ 2014-03-28 9:45 UTC (permalink / raw)
To: linux-bluetooth
It will be called with register/deregister will be called.
It will send status, service id and characteristic id.
---
android/gatt.c | 23 ++++++++++++++++++++++-
1 file changed, 22 insertions(+), 1 deletion(-)
diff --git a/android/gatt.c b/android/gatt.c
index aaf4393..e6a1711 100644
--- a/android/gatt.c
+++ b/android/gatt.c
@@ -1395,6 +1395,23 @@ static void handle_client_execute_write(const void *buf, uint16_t len)
HAL_OP_GATT_CLIENT_EXECUTE_WRITE, HAL_STATUS_FAILED);
}
+static void send_register_for_notification_ev(int32_t id, int32_t registered,
+ int32_t status,
+ const struct hal_gatt_srvc_id *srvc,
+ const struct hal_gatt_gatt_id *ch)
+{
+ struct hal_ev_gatt_client_reg_for_notif ev;
+
+ ev.conn_id = id;
+ ev.status = status;
+ ev.registered = registered;
+ memcpy(&ev.srvc_id, srvc, sizeof(ev.srvc_id));
+ memcpy(&ev.char_id, ch, sizeof(ev.char_id));
+
+ ipc_send_notif(hal_ipc, HAL_SERVICE_ID_GATT,
+ HAL_EV_GATT_CLIENT_REGISTER_FOR_NOTIF, sizeof(ev), &ev);
+}
+
static void handle_client_register_for_notification(const void *buf,
uint16_t len)
{
@@ -1406,6 +1423,7 @@ static void handle_client_register_for_notification(const void *buf,
struct element_id match_id;
struct gatt_device *dev;
struct service *service;
+ int32_t conn_id = 0;
uint8_t status;
bdaddr_t addr;
@@ -1425,6 +1443,8 @@ static void handle_client_register_for_notification(const void *buf,
goto failed;
}
+ conn_id = dev->conn_id;
+
hal_srvc_id_to_element_id(&cmd->srvc_id, &match_id);
service = queue_find(dev->services, match_srvc_by_element_id,
&match_id);
@@ -1496,7 +1516,8 @@ static void handle_client_register_for_notification(const void *buf,
status = HAL_STATUS_SUCCESS;
failed:
- /* TODO: send callback with notification enabled/disabled */
+ send_register_for_notification_ev(conn_id, 1, status, &cmd->srvc_id,
+ &cmd->char_id);
ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_GATT,
HAL_OP_GATT_CLIENT_REGISTER_FOR_NOTIFICATION,
status);
--
1.8.3.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCHv3 7/8] android/gatt: Add handler for ATT_OP_HANDLE_NOTIFY and ATT_OP_HANDLE_IND
2014-03-28 9:45 [PATCHv3 1/8] android/gatt: Add helper for getting device by conn_id Marcin Kraglak
` (4 preceding siblings ...)
2014-03-28 9:45 ` [PATCHv3 6/8] android/gatt: Add send_register_for_notif_ev function Marcin Kraglak
@ 2014-03-28 9:45 ` Marcin Kraglak
2014-03-28 9:45 ` [PATCHv3 8/8] android/gatt: Add deregister_for_notification implementation Marcin Kraglak
2014-03-28 10:28 ` [PATCHv3 1/8] android/gatt: Add helper for getting device by conn_id Szymon Janc
7 siblings, 0 replies; 9+ messages in thread
From: Marcin Kraglak @ 2014-03-28 9:45 UTC (permalink / raw)
To: linux-bluetooth
Invoke callback notify_cb with received data. We set flag is_notify
properly to inform Android what type of notification has been received.
---
android/gatt.c | 35 +++++++++++++++++++++++++++++++++--
1 file changed, 33 insertions(+), 2 deletions(-)
diff --git a/android/gatt.c b/android/gatt.c
index e6a1711..a5d40fc 100644
--- a/android/gatt.c
+++ b/android/gatt.c
@@ -1395,6 +1395,35 @@ static void handle_client_execute_write(const void *buf, uint16_t len)
HAL_OP_GATT_CLIENT_EXECUTE_WRITE, HAL_STATUS_FAILED);
}
+static void handle_notification(const uint8_t *pdu, uint16_t len,
+ gpointer user_data)
+{
+ uint8_t buf[IPC_MTU];
+ struct hal_ev_gatt_client_notify *ev = (void *) buf;
+ struct notification_data *notification = user_data;
+ uint8_t is_notify;
+ uint8_t offset;
+
+ if (len < 3)
+ return;
+
+ is_notify = pdu[0] == ATT_OP_HANDLE_NOTIFY ? true : false;
+
+ memcpy(&ev->char_id, ¬ification->ch, sizeof(ev->char_id));
+ memcpy(&ev->srvc_id, ¬ification->service, sizeof(ev->srvc_id));
+ bdaddr2android(¬ification->dev->bdaddr, &ev->bda);
+ ev->conn_id = notification->dev->conn_id;
+ ev->is_notify = is_notify;
+
+ /* We have to cut opcode and handle from data */
+ offset = sizeof(is_notify) + sizeof(uint16_t);
+ ev->len = len - offset;
+ memcpy(ev->value, pdu + offset, len - offset);
+
+ ipc_send_notif(hal_ipc, HAL_SERVICE_ID_GATT, HAL_EV_GATT_CLIENT_NOTIFY,
+ sizeof(*ev) + ev->len, ev);
+}
+
static void send_register_for_notification_ev(int32_t id, int32_t registered,
int32_t status,
const struct hal_gatt_srvc_id *srvc,
@@ -1483,7 +1512,8 @@ static void handle_client_register_for_notification(const void *buf,
notification->notif_id = g_attrib_register(dev->attrib,
ATT_OP_HANDLE_NOTIFY,
c->ch.value_handle,
- NULL, notification,
+ handle_notification,
+ notification,
destroy_notification);
if (!notification->notif_id) {
free(notification);
@@ -1493,7 +1523,8 @@ static void handle_client_register_for_notification(const void *buf,
notification->ind_id = g_attrib_register(dev->attrib, ATT_OP_HANDLE_IND,
c->ch.value_handle,
- NULL, notification,
+ handle_notification,
+ notification,
destroy_notification);
if (!notification->ind_id) {
g_attrib_unregister(dev->attrib, notification->notif_id);
--
1.8.3.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCHv3 8/8] android/gatt: Add deregister_for_notification implementation
2014-03-28 9:45 [PATCHv3 1/8] android/gatt: Add helper for getting device by conn_id Marcin Kraglak
` (5 preceding siblings ...)
2014-03-28 9:45 ` [PATCHv3 7/8] android/gatt: Add handler for ATT_OP_HANDLE_NOTIFY and ATT_OP_HANDLE_IND Marcin Kraglak
@ 2014-03-28 9:45 ` Marcin Kraglak
2014-03-28 10:28 ` [PATCHv3 1/8] android/gatt: Add helper for getting device by conn_id Szymon Janc
7 siblings, 0 replies; 9+ messages in thread
From: Marcin Kraglak @ 2014-03-28 9:45 UTC (permalink / raw)
To: linux-bluetooth
This will unregister handlers for notification and indications
and remove notification_data from client's list.
---
android/gatt.c | 44 +++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 43 insertions(+), 1 deletion(-)
diff --git a/android/gatt.c b/android/gatt.c
index a5d40fc..85db3d6 100644
--- a/android/gatt.c
+++ b/android/gatt.c
@@ -1557,11 +1557,53 @@ failed:
static void handle_client_deregister_for_notification(const void *buf,
uint16_t len)
{
+ const struct hal_cmd_gatt_client_deregister_for_notification *cmd = buf;
+ struct notification_data *notification, notif;
+ struct gatt_client *client;
+ struct gatt_device *dev;
+ int32_t conn_id = 0;
+ uint8_t status;
+ bdaddr_t addr;
+
DBG("");
+ client = find_client_by_id(cmd->client_if);
+ if (!client) {
+ status = HAL_STATUS_FAILED;
+ goto failed;
+ }
+
+ android2bdaddr(&cmd->bdaddr, &addr);
+
+ dev = find_device(&addr);
+ if (!dev) {
+ status = HAL_STATUS_FAILED;
+ goto failed;
+ }
+
+ conn_id = dev->conn_id;
+ memcpy(¬if.ch, &cmd->char_id, sizeof(notif.ch));
+ memcpy(¬if.service, &cmd->srvc_id, sizeof(notif.service));
+ notif.dev = dev;
+
+ notification = queue_find(client->notifications,
+ match_notification, ¬if);
+ if (!notification) {
+ status = HAL_STATUS_FAILED;
+ goto failed;
+ }
+
+ unregister_notification(notification);
+
+ status = HAL_STATUS_SUCCESS;
+
+failed:
+ send_register_for_notification_ev(conn_id, 0, status, &cmd->srvc_id,
+ &cmd->char_id);
+
ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_GATT,
HAL_OP_GATT_CLIENT_DEREGISTER_FOR_NOTIFICATION,
- HAL_STATUS_FAILED);
+ status);
}
static void handle_client_read_remote_rssi(const void *buf, uint16_t len)
--
1.8.3.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCHv3 1/8] android/gatt: Add helper for getting device by conn_id
2014-03-28 9:45 [PATCHv3 1/8] android/gatt: Add helper for getting device by conn_id Marcin Kraglak
` (6 preceding siblings ...)
2014-03-28 9:45 ` [PATCHv3 8/8] android/gatt: Add deregister_for_notification implementation Marcin Kraglak
@ 2014-03-28 10:28 ` Szymon Janc
7 siblings, 0 replies; 9+ messages in thread
From: Szymon Janc @ 2014-03-28 10:28 UTC (permalink / raw)
To: Marcin Kraglak; +Cc: linux-bluetooth
Hi Marcin,
On Friday 28 of March 2014 10:45:52 Marcin Kraglak wrote:
> It will look for cgatt_device by conn_id.
> ---
> android/gatt.c | 14 ++++++++------
> 1 file changed, 8 insertions(+), 6 deletions(-)
>
> diff --git a/android/gatt.c b/android/gatt.c
> index 81b29af..92e16d4 100644
> --- a/android/gatt.c
> +++ b/android/gatt.c
> @@ -722,6 +722,11 @@ static struct gatt_device *find_device(bdaddr_t *addr)
> return NULL;
> }
>
> +static struct gatt_device *find_device_by_conn_id(int32_t conn_id)
> +{
> + return queue_find(conn_list, match_dev_by_conn_id, INT_TO_PTR(conn_id));
> +}
> +
> static void handle_client_connect(const void *buf, uint16_t len)
> {
> const struct hal_cmd_gatt_client_connect *cmd = buf;
> @@ -858,8 +863,7 @@ static void handle_client_disconnect(const void *buf, uint16_t len)
>
> ba2str((bdaddr_t *)&cmd->bdaddr, addr);
>
> - dev = queue_find(conn_list, match_dev_by_conn_id,
> - INT_TO_PTR(cmd->conn_id));
> + dev = find_device_by_conn_id(cmd->conn_id);
> if (!dev) {
> error("gatt: dev %s with conn_id=%d not found",
> addr, cmd->conn_id);
> @@ -924,8 +928,7 @@ static void handle_client_search_service(const void *buf, uint16_t len)
>
> DBG("");
>
> - dev = queue_find(conn_list, match_dev_by_conn_id,
> - INT_TO_PTR(cmd->conn_id));
> + dev = find_device_by_conn_id(cmd->conn_id);
> if (!dev) {
> error("gatt: dev with conn_id=%d not found", cmd->conn_id);
> status = HAL_STATUS_FAILED;
> @@ -1048,8 +1051,7 @@ static bool find_service(int32_t conn_id, struct element_id *service_id,
> struct gatt_device *device;
> struct service *service;
>
> - device = queue_find(conn_list, match_dev_by_conn_id,
> - INT_TO_PTR(conn_id));
> + device = find_device_by_conn_id(conn_id);
> if (!device) {
> error("gatt: conn_id=%d not found", conn_id);
> return false;
>
This patch is now upstream. Thanks.
--
Best regards,
Szymon Janc
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2014-03-28 10:28 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-03-28 9:45 [PATCHv3 1/8] android/gatt: Add helper for getting device by conn_id Marcin Kraglak
2014-03-28 9:45 ` [PATCHv3 2/8] android/gatt: Add initial implementation of get_included_service Marcin Kraglak
2014-03-28 9:45 ` [PATCHv3 3/8] android/gatt: Add get_included_data struct and callback Marcin Kraglak
2014-03-28 9:45 ` [PATCHv3 4/8] android/gatt: Add implementation of get_included_cb Marcin Kraglak
2014-03-28 9:45 ` [PATCHv3 5/8] android/gatt: Add initial implementation of register_for_notification Marcin Kraglak
2014-03-28 9:45 ` [PATCHv3 6/8] android/gatt: Add send_register_for_notif_ev function Marcin Kraglak
2014-03-28 9:45 ` [PATCHv3 7/8] android/gatt: Add handler for ATT_OP_HANDLE_NOTIFY and ATT_OP_HANDLE_IND Marcin Kraglak
2014-03-28 9:45 ` [PATCHv3 8/8] android/gatt: Add deregister_for_notification implementation Marcin Kraglak
2014-03-28 10:28 ` [PATCHv3 1/8] android/gatt: Add helper for getting device by conn_id 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.