From: Luiz Augusto von Dentz <luiz.von.dentz@xxxxxxxxx> This in future gonna be used by HoG to receive connection notifications. --- android/gatt.c | 143 ++++++++++++++++++++++++++++++++++++++++++++++----------- android/gatt.h | 15 ++++++ 2 files changed, 130 insertions(+), 28 deletions(-) diff --git a/android/gatt.c b/android/gatt.c index 429181f..a893407 100644 --- a/android/gatt.c +++ b/android/gatt.c @@ -87,11 +87,6 @@ static const char const *device_state_str[] = { "CONNECTED", }; -typedef enum { - APP_CLIENT, - APP_SERVER, -} gatt_app_type_t; - struct pending_trans_data { unsigned int id; uint8_t opcode; @@ -101,13 +96,15 @@ struct gatt_app { int32_t id; uint8_t uuid[16]; - gatt_app_type_t type; + gatt_type_t type; /* Valid for client applications */ struct queue *notifications; /* Transaction data valid for server application */ struct pending_trans_data trans_id; + + gatt_conn_cb_t func; }; struct element_id { @@ -617,7 +614,7 @@ static void destroy_gatt_app(void *data) * too. So remove all elements and then destroy queue. */ - if (app->type == APP_CLIENT) + if (app->type == GATT_CLIENT) while (queue_peek_head(app->notifications)) { struct notification_data *notification; @@ -630,14 +627,14 @@ static void destroy_gatt_app(void *data) free(app); } -static int register_app(const uint8_t *uuid, gatt_app_type_t app_type) +static struct gatt_app *register_app(const uint8_t *uuid, gatt_type_t type) { static int32_t application_id = 1; struct gatt_app *app; if (queue_find(gatt_apps, match_app_by_uuid, uuid)) { error("gatt: app uuid is already on list"); - return 0; + return NULL; } app = new0(struct gatt_app, 1); @@ -646,14 +643,14 @@ static int register_app(const uint8_t *uuid, gatt_app_type_t app_type) return 0; } - app->type = app_type; + app->type = type; - if (app->type == APP_CLIENT) { + if (app->type == GATT_CLIENT) { app->notifications = queue_new(); if (!app->notifications) { error("gatt: couldn't allocate notifications queue"); destroy_gatt_app(app); - return 0; + return NULL; } } @@ -664,33 +661,35 @@ static int register_app(const uint8_t *uuid, gatt_app_type_t app_type) if (!queue_push_head(gatt_apps, app)) { error("gatt: Cannot push app on the list"); destroy_gatt_app(app); - return 0; + return NULL; } - if ((app->type == APP_SERVER) && + if ((app->type == GATT_SERVER) && !queue_push_tail(listen_apps, INT_TO_PTR(app->id))) { error("gatt: Cannot push server on the list"); destroy_gatt_app(app); - return 0; + return NULL; } - return app->id; + return app; } static void handle_client_register(const void *buf, uint16_t len) { const struct hal_cmd_gatt_client_register *cmd = buf; struct hal_ev_gatt_client_register_client ev; + struct gatt_app *app; DBG(""); memset(&ev, 0, sizeof(ev)); - ev.client_if = register_app(cmd->uuid, APP_CLIENT); + app = register_app(cmd->uuid, GATT_CLIENT); - if (ev.client_if) + if (app) { + ev.client_if = app->id; ev.status = GATT_SUCCESS; - else + } else ev.status = GATT_FAILURE; /* We should send notification with given in cmd UUID */ @@ -708,6 +707,12 @@ static void send_client_disconnection_notify(struct app_connection *connection, { struct hal_ev_gatt_client_disconnect ev; + if (connection->app->func) { + connection->app->func(&connection->device->bdaddr, -ENOTCONN, + connection->device->attrib); + return; + } + ev.client_if = connection->app->id; ev.conn_id = connection->id; ev.status = status; @@ -716,6 +721,7 @@ static void send_client_disconnection_notify(struct app_connection *connection, ipc_send_notif(hal_ipc, HAL_SERVICE_ID_GATT, HAL_EV_GATT_CLIENT_DISCONNECT, sizeof(ev), &ev); + } static void send_client_connection_notify(struct app_connection *connection, @@ -723,6 +729,13 @@ static void send_client_connection_notify(struct app_connection *connection, { struct hal_ev_gatt_client_connect ev; + if (connection->app->func) { + connection->app->func(&connection->device->bdaddr, + status == GATT_SUCCESS ? 0 : -ENOTCONN, + connection->device->attrib); + return; + } + ev.client_if = connection->app->id; ev.conn_id = connection->id; ev.status = status; @@ -738,6 +751,13 @@ static void send_server_connection_notify(struct app_connection *connection, { struct hal_ev_gatt_server_connection ev; + if (connection->app->func) { + connection->app->func(&connection->device->bdaddr, + connected ? 0 : -ENOTCONN, + connection->device->attrib); + return; + } + ev.server_if = connection->app->id; ev.conn_id = connection->id; ev.connected = connected; @@ -751,7 +771,7 @@ static void send_server_connection_notify(struct app_connection *connection, static void send_app_disconnect_notify(struct app_connection *connection, int32_t status) { - if (connection->app->type == APP_CLIENT) + if (connection->app->type == GATT_CLIENT) send_client_disconnection_notify(connection, status); else send_server_connection_notify(connection, !!status); @@ -760,9 +780,9 @@ static void send_app_disconnect_notify(struct app_connection *connection, static void send_app_connect_notify(struct app_connection *connection, int32_t status) { - if (connection->app->type == APP_CLIENT) + if (connection->app->type == GATT_CLIENT) send_client_connection_notify(connection, status); - else + else if (connection->app->type == GATT_SERVER) send_server_connection_notify(connection, !status); } @@ -3510,9 +3530,11 @@ static void handle_client_test_command(const void *buf, uint16_t len) switch (cmd->command) { case GATT_CLIENT_TEST_CMD_ENABLE: if (cmd->u1) { - if (!test_client_if) - test_client_if = register_app(TEST_UUID, - APP_CLIENT); + if (!test_client_if) { + app = register_app(TEST_UUID, GATT_CLIENT); + if (app) + test_client_if = app->id; + } if (test_client_if) status = HAL_STATUS_SUCCESS; @@ -3557,16 +3579,18 @@ static void handle_server_register(const void *buf, uint16_t len) { const struct hal_cmd_gatt_server_register *cmd = buf; struct hal_ev_gatt_server_register ev; + struct gatt_app *app; DBG(""); memset(&ev, 0, sizeof(ev)); - ev.server_if = register_app(cmd->uuid, APP_SERVER); + app = register_app(cmd->uuid, GATT_SERVER); - if (ev.server_if) + if (app) { + ev.server_if = app->id; ev.status = GATT_SUCCESS; - else + } else ev.status = GATT_FAILURE; memcpy(ev.uuid, cmd->uuid, sizeof(ev.uuid)); @@ -5746,3 +5770,66 @@ void bt_gatt_unregister(void) bt_crypto_unref(crypto); crypto = NULL; } + + +unsigned int bt_gatt_register_app(const char *uuid, gatt_type_t type, + gatt_conn_cb_t func) +{ + struct gatt_app *app; + bt_uuid_t uuid128; + + bt_string_to_uuid(&uuid128, uuid); + app = register_app((void *) &uuid128.value.u128, type); + if (!app) + return 0; + + app->func = func; + + return app->id; +} + +bool bt_gatt_unregister_app(unsigned int id) +{ + uint8_t status; + + status = unregister_client(id); + + return status != HAL_STATUS_FAILED; +} + +bool bt_gatt_connect_app(unsigned int id, const bdaddr_t *addr) +{ + uint8_t status; + + status = handle_connect(id, addr); + + return status != HAL_STATUS_FAILED; +} + +bool bt_gatt_disconnect_app(unsigned int id, const bdaddr_t *addr) +{ + struct app_connection match; + struct app_connection *conn; + struct gatt_device *device; + struct gatt_app *app; + + app = find_app_by_id(id); + if (!app) + return false; + + device = find_device_by_addr(addr); + if (!device) + return false; + + match.device = device; + match.app = app; + + conn = queue_find(app_connections, match_connection_by_device_and_app, + &match); + if (!conn) + return false; + + trigger_disconnection(conn); + + return true; +} diff --git a/android/gatt.h b/android/gatt.h index d4392d9..5ba9161 100644 --- a/android/gatt.h +++ b/android/gatt.h @@ -23,3 +23,18 @@ bool bt_gatt_register(struct ipc *ipc, const bdaddr_t *addr); void bt_gatt_unregister(void); + + +typedef enum { + GATT_CLIENT, + GATT_SERVER, +} gatt_type_t; + +typedef void (*gatt_conn_cb_t)(const bdaddr_t *addr, int err, void *attrib); + +unsigned int bt_gatt_register_app(const char *uuid, gatt_type_t type, + gatt_conn_cb_t func); +bool bt_gatt_unregister_app(unsigned int id); + +bool bt_gatt_connect_app(unsigned int id, const bdaddr_t *addr); +bool bt_gatt_disconnect_app(unsigned int id, const bdaddr_t *addr); -- 1.9.0 -- To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html