From 74548f6d48a91b449b1ffda96628f5be24ba600b Mon Sep 17 00:00:00 2001 From: Avichal Agarwal Date: Tue, 7 Aug 2018 22:21:26 +0530 Subject: [PATCH] BLE Gatt Server Socket write implemetation Server with characterstics property 'write-without-response' will receive the data on socket file descriptor.AcquireWrite method handler is implemented in OAL Change-Id: I4b8134b8eda87f775ebf72b5e98ce6753e6a9b84 Signed-off-by: Avichal Agarwal --- bt-api/bt-event-handler.c | 5 + bt-api/bt-gatt-service.c | 174 ++++++++++++++++++++ bt-api/include/bt-gatt-server.h | 13 ++ bt-oal/bluez_hal/bluetooth-frwk-gap-agent.conf | 10 ++ bt-oal/bluez_hal/inc/bt-hal-msg.h | 12 ++ bt-oal/bluez_hal/src/bt-hal-gatt-server.c | 183 ++++++++++++++++++++- bt-oal/bluez_hal/src/bt-hal-gatt.c | 16 +- bt-oal/hardware/bt_gatt_server.h | 14 ++ bt-oal/include/oal-event.h | 8 + bt-oal/include/oal-gatt.h | 10 ++ bt-oal/oal-gatt.c | 34 ++++ .../services/bt-request-handler.c | 34 ++++ .../services/bt-service-event-receiver.c | 2 + .../services/bt-service-event-sender.c | 3 + .../services/gatt/bt-service-gatt.c | 81 +++++++++ .../services/include/bt-service-gatt.h | 2 + include/bluetooth-api.h | 3 +- include/bluetooth-gatt-server-api.h | 24 +++ include/bt-internal-types.h | 7 +- 19 files changed, 629 insertions(+), 6 deletions(-) create mode 100644 bt-api/include/bt-gatt-server.h diff --git a/bt-api/bt-event-handler.c b/bt-api/bt-event-handler.c index a435157..f018faa 100644 --- a/bt-api/bt-event-handler.c +++ b/bt-api/bt-event-handler.c @@ -34,6 +34,7 @@ #include "bt-event-handler.h" #include "bt-gatt-client.h" #include "bt-request-sender.h" +#include "bt-gatt-server.h" #define PROFILE_SUPPORTED 0x3 /* This corresponds to binary 0b11*/ #define BT_RELIABLE_DISABLE_TIME 300 /* 300 ms */ @@ -3838,6 +3839,10 @@ static void __bt_gatt_server_event_filter(GDBusConnection *connection, _bt_gatt_server_event_cb(BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED, result, &read_info, event_info->cb, event_info->user_data); + } else if (strcasecmp(signal_name, BT_GATT_SERVER_ACQUIRE_WRITE) == 0) { + + bluetooth_gatt_server_send_acquire_response(parameters); + } else if (strcasecmp(signal_name, BT_GATT_SERVER_NOTIFICATION_COMPLETED) == 0) { const char *address = NULL; bluetooth_device_address_t dev_address = { {0} }; diff --git a/bt-api/bt-gatt-service.c b/bt-api/bt-gatt-service.c index 0c4c127..498756b 100644 --- a/bt-api/bt-gatt-service.c +++ b/bt-api/bt-gatt-service.c @@ -22,6 +22,9 @@ #include #include #include +#include +#include +#include #include "bt-common.h" /* TODO_40 : 4.0 merge - Need to check why includes bt-event-handler.h */ @@ -3143,3 +3146,174 @@ BT_EXPORT_API int bluetooth_gatt_server_unregister(int instance_id) return result; } + +static gboolean bluetooth_gatt_server_acquire_channel_write_cb(GIOChannel *gio, + GIOCondition cond, gpointer data) +{ + + bluetooth_gatt_server_acquire_write_info_t *write_data = (bluetooth_gatt_server_acquire_write_info_t*)data; + + BT_INFO("FD io write data received remote adress [%s]\n", write_data->adress); + + if (cond & G_IO_IN) { + GIOStatus status = G_IO_STATUS_NORMAL; + GError *err = NULL; + char *buffer = NULL; + gsize len = 0; + int BUF = BLUETOOTH_GATT_ATT_DATA_LENGTH_MAX; + + buffer = g_malloc0(BUF); + + status = g_io_channel_read_chars(gio, buffer, + BUF, &len, &err); + + if (status != G_IO_STATUS_NORMAL) { + BT_ERR("IO Channel read is failed with %d", status); + g_free(buffer); + if (err) { + BT_ERR("IO Channel read error [%s]", err->message); + if (status == G_IO_STATUS_ERROR) { + BT_ERR("cond : %d", cond); + g_error_free(err); + g_io_channel_shutdown(gio, TRUE, NULL); + g_io_channel_unref(gio); + + return FALSE; + } + g_error_free(err); + } + return FALSE; + } + + if (len > 0) { + + BT_INFO(" FD io sending value changed %s %d \n", buffer, len); + + + bluetooth_gatt_server_write_requested_info_t write_info; + if (len < BLUETOOTH_GATT_ATT_DATA_LENGTH_MAX) + memcpy(write_info.data.data, buffer, len); + + write_info.length = len; + write_info.need_resp = false; + write_info.attribute_handle = write_data->attribute_handle; + //memcpy() + _bt_convert_addr_string_to_type(write_info.device_address.addr, write_data->adress); + write_info.connection_id = write_data->connection_id; + write_info.offset = write_data->offset; + write_info.request_id = -2; + + BT_INFO("ACQUIRING EVENT \n"); + + bt_event_info_t *event_info; + event_info = _bt_event_get_cb_data(BT_GATT_SERVER_EVENT); + + if (event_info) { + + _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED, + BLUETOOTH_ERROR_NONE, &write_info, + event_info->cb, event_info->user_data); + } else { + BT_ERR("eventinfo failed"); + } + + + } + g_free(buffer); + + return TRUE; + } + + if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) { + BT_ERR("Error : GIOCondition %d, ]", cond); + g_io_channel_shutdown(gio, TRUE, NULL); + g_io_channel_unref(gio); + + return FALSE; + } + + return TRUE; +} + +void bluetooth_gatt_server_send_acquire_response(GVariant * parameters) +{ + int con_id = -1; + int tran_id = -1; + int att_han = -1; + int pipefd[2] = {-1,}; + int mtu = -1; + int offset = -1; + char err_msg[512] = {'\0'}; + GIOChannel *channel = NULL; + char *addr = NULL; + int result = -1; + + g_variant_get(parameters, "(iiiiii&s)", + &result, + &con_id, + &tran_id, + &att_han, + &mtu, + &offset, + &addr); + + BT_DBG("GATT Server Acquire Write From Remote Client [%s]", addr); + BT_DBG("GATT ServerAcquire Conn ID: [%d]", con_id); + BT_DBG("GATT Server Acquire write att handle:[%d]", att_han); + BT_DBG("GATT Server Acquire Write Offset: [%d]", offset); + + + if (socketpair(AF_UNIX, SOCK_STREAM, 0, pipefd) < 0) { + strerror_r(errno, err_msg, sizeof(err_msg)); + BT_ERR("socketpair(): %s", err_msg); + return ; + } + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + //param1 = g_array_new(TRUE, TRUE, sizeof(gchar)); + bluetooth_gatt_server_acquire_response_params_t data; + data.req_type = BLUETOOTH_GATT_REQUEST_TYPE_ACQUIRE_WRITE; + data.fd = pipefd[1]; + data.mtu = mtu; + data.request_id = tran_id; + + bluetooth_gatt_server_acquire_write_info_t *write_info = g_malloc0(sizeof(bluetooth_gatt_server_acquire_write_info_t)) ; + + write_info->attribute_handle = att_han; + write_info->connection_id = tran_id; + write_info->offset = offset; + + memcpy(write_info->adress, addr , BLUETOOTH_ADDRESS_STRING_LENGTH); + + BT_INFO("FD read %d remote adress [%s ] \n", pipefd[0], addr); + + + channel = g_io_channel_unix_new(pipefd[0]); + g_io_channel_set_encoding(channel, NULL, NULL); + g_io_channel_set_buffered(channel, FALSE); + g_io_channel_set_close_on_unref(channel, TRUE); + g_io_channel_set_flags(channel, G_IO_FLAG_NONBLOCK, NULL); + g_io_add_watch(channel, (G_IO_IN | G_IO_ERR | G_IO_HUP), + bluetooth_gatt_server_acquire_channel_write_cb, write_info); + + + GUnixFDList *fd_list = g_unix_fd_list_new(); + GError *error = NULL; + + g_unix_fd_list_append(fd_list, pipefd[1], &error); + g_assert_no_error(error); + close(pipefd[1]); + + g_array_append_vals(in_param1, &data, sizeof(bluetooth_gatt_server_acquire_response_params_t)); + + BT_INFO("Sending event BT_GATT_SERVER_ACQURE_WRITE_RESPONSE file descriptor value [%d] [ %s],", data.fd, addr); + + result = _bt_send_request_with_unix_fd_list(BT_BLUEZ_SERVICE, BT_GATT_SERVER_ACQURE_WRITE_RESPONSE, + in_param1, in_param2, in_param3, in_param4, fd_list, &out_param, NULL); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + +} + diff --git a/bt-api/include/bt-gatt-server.h b/bt-api/include/bt-gatt-server.h new file mode 100644 index 0000000..4c8e01d --- /dev/null +++ b/bt-api/include/bt-gatt-server.h @@ -0,0 +1,13 @@ +#ifndef _BT_GATT_SERVER_H_ +#define _BT_GATT_SERVER_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +void bluetooth_gatt_server_send_acquire_response(GVariant * parameter); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /*_BT_GATT_SERVER_H_*/ diff --git a/bt-oal/bluez_hal/bluetooth-frwk-gap-agent.conf b/bt-oal/bluez_hal/bluetooth-frwk-gap-agent.conf index 635b385..b76e79c 100644 --- a/bt-oal/bluez_hal/bluetooth-frwk-gap-agent.conf +++ b/bt-oal/bluez_hal/bluetooth-frwk-gap-agent.conf @@ -4,18 +4,28 @@ + + + + + + + + + + diff --git a/bt-oal/bluez_hal/inc/bt-hal-msg.h b/bt-oal/bluez_hal/inc/bt-hal-msg.h index decf025..4f595b8 100644 --- a/bt-oal/bluez_hal/inc/bt-hal-msg.h +++ b/bt-oal/bluez_hal/inc/bt-hal-msg.h @@ -719,4 +719,16 @@ struct hal_ev_gatt_client_watch_notification { uint8_t svc_uuid[16]; uint8_t char_uuid[16]; } __attribute__((packed)); + +#define HAL_EV_GATT_SERVER_ACQUIRE_WRITE_RES 0XC9 +struct hal_ev_gatt_server_acquire_write_res { + int32_t mtu; + int32_t trans_id; + int32_t conn_id; + int32_t char_handl; + uint8_t bdaddr[6]; +} __attribute__((packed)); + + + #endif //_BT_HAL_MSG_H_ diff --git a/bt-oal/bluez_hal/src/bt-hal-gatt-server.c b/bt-oal/bluez_hal/src/bt-hal-gatt-server.c index b95d6a4..e306822 100644 --- a/bt-oal/bluez_hal/src/bt-hal-gatt-server.c +++ b/bt-oal/bluez_hal/src/bt-hal-gatt-server.c @@ -111,6 +111,8 @@ typedef enum { BT_HAL_GATT_REQUEST_TYPE_READ = 0x00, /* Read Requested */ BT_HAL_GATT_REQUEST_TYPE_WRITE = 0x01, /* Write Requested */ BT_HAL_GATT_REQUEST_TYPE_EXEC_WRITE = 0x02, /* Exec Write Requested */ + BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_WRITE = 0x03, /* Exec Write Requested */ + BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY = 0x04, /* Exec Write Requested */ } bt_gatt_request_type_e; struct gatt_req_info { @@ -239,6 +241,16 @@ static const gchar characteristics_introspection_xml[] = " " " " " " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " " " " " " " @@ -263,6 +275,10 @@ static const gchar characteristics_introspection_xml[] = " " " " " " +" " +" " +" " +" " " " ""; @@ -599,6 +615,8 @@ static void __bt_gatt_manager_method_call(GDBusConnection *connection, GSList *gatt_services = NULL; int *instance; instance = (int*)user_data; + gboolean writeAcquired = FALSE; + gboolean notifyAcquired = FALSE; DBG("Getting values for service, chars and descriptors"); DBG("GATT Server App for which services are requested [%d]", *instance); @@ -719,6 +737,11 @@ static void __bt_gatt_manager_method_call(GDBusConnection *connection, for (i = 0; i < char_info->flags_length; i++) { g_variant_builder_add(builder2, "s", char_info->char_flags[i]); + if (strncmp(char_info->char_flags[i], "write-without-response", 16) == 0) + writeAcquired = TRUE; + + if (strncmp(char_info->char_flags[i], "notify", 4) == 0) + notifyAcquired = TRUE; } flags_val = g_variant_new("as", builder2); @@ -730,6 +753,14 @@ static void __bt_gatt_manager_method_call(GDBusConnection *connection, g_variant_new("b", notify)); /* Unicast */ + g_variant_builder_add(inner_builder, "{sv}", "WriteAcquired", + g_variant_new("b", writeAcquired)); + + /* NotifyAcquired */ + g_variant_builder_add(inner_builder, "{sv}", "NotifyAcquired", + g_variant_new("b", notifyAcquired)); + + /* Unicast */ unicast = g_strdup("00:00:00:00:00:00"); g_variant_builder_add(inner_builder, "{sv}", "Unicast", g_variant_new("s", unicast)); @@ -1250,8 +1281,87 @@ static void __bt_gatt_char_method_call(GDBusConnection *connection, _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr); event_cb(HAL_EV_GATT_INDICATE_CFM, (void *)&ev, sizeof(ev)); - } + } else if (g_strcmp0(method_name, "AcquireWrite") == 0) { + + uint16_t mtu = 512; + int char_hdl = -1; + struct hal_ev_gatt_server_acquire_write_res ev; + struct gatt_service_info *svc_info = NULL; + struct gatt_req_info *req_info = NULL; + struct gatt_client_info_t *conn_info = NULL; + char * dev_path = NULL; + char * link = 0; + char addr[BT_HAL_ADDRESS_STRING_SIZE]; + + DBG("AcquireWrite"); + DBG("Application path = %s", object_path); + DBG("Sender = %s", sender); + + GVariantIter* iter; + g_variant_get(parameters, "(a{sv})", &iter); + char* key = NULL; + GVariant* value = NULL; + while (g_variant_iter_loop(iter, "{sv}", &key, &value)) { + if (g_strcmp0(key, "MTU") == 0) + g_variant_get(value, "i", &mtu); + else if (g_strcmp0(key, "link") == 0) + g_variant_get(value, "s", &link); + else if (g_strcmp0(key, "device") == 0) + g_variant_get(value, "o", &dev_path); + } + + DBG("AcquireWrite values retived"); + DBG(" path %s LINK = %s, MTU = %u", addr, link, mtu); + + svc_info = __bt_gatt_find_gatt_service_from_char(object_path, &char_hdl); + + _bt_hal_convert_device_path_to_address(dev_path, addr); + + DBG("remote adress %s", addr); + + /* Check if device is already in connected list */ + conn_info = __bt_find_remote_gatt_client_info(addr); + + if (conn_info == NULL) { + ERR("Cleint info not found\n"); + goto done; + } + + if (svc_info == NULL) { + ERR("svc_info info not found\n"); + goto done; + } + + /* Store requets information */ + req_info = g_new0(struct gatt_req_info, 1); + req_info->attr_path = g_strdup(object_path); + req_info->svc_path = g_strdup(svc_info->serv_path); + req_info->request_id = conn_info->connection_id; + req_info->request_type = BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_WRITE; + req_info->offset = mtu; + req_info->context = invocation; + + /* Append request info in list of requests for the particular connection */ + conn_info->gatt_req_info_list = g_slist_append(conn_info->gatt_req_info_list, req_info); + + /* Send HAL event */ + memset(&ev, 0, sizeof(ev)); + ev.conn_id = conn_info->connection_id; + ev.char_handl = char_hdl; + ev.mtu = mtu; + ev.trans_id = conn_info->connection_id; + _bt_hal_convert_addr_string_to_type(ev.bdaddr, addr); + event_cb(HAL_EV_GATT_SERVER_ACQUIRE_WRITE_RES, (void *)&ev, sizeof(ev)); + DBG("HAL_EV_GATT_ACQUIRE_WRITE_RES called"); + + + return; + } else if (g_strcmp0(method_name, "AcquireNotify") == 0) { + + + } +done: g_dbus_method_invocation_return_value(invocation, NULL); } @@ -2879,6 +2989,74 @@ static bt_status_t gatt_server_send_response(int conn_id, int trans_id, return BT_STATUS_SUCCESS; } + +static bt_status_t gatt_server_send_acquire_response(int conn_id, int trans_id, + int status, int fd, int mtu, void *fdlist) +{ + CHECK_BTGATT_INIT(); + + struct gatt_req_info *req_info = NULL; + struct gatt_client_info_t *conn_info = NULL; + int i; + + DBG("GATT Server Send Response Conn ID [%d]", conn_id); + + conn_info = __bt_find_remote_gatt_client_info_from_conn(conn_id); + if (conn_info == NULL) { + ERR("No Connection Inforamtion!!!"); + return BT_STATUS_FAIL; + } + + req_info = __bt_find_remote_gatt_client_request_info(conn_id, trans_id); + if (req_info == NULL) { + ERR("No Request Inforamtion!!!"); + return BT_STATUS_FAIL; + } + + if (status != BT_STATUS_SUCCESS) { + ERR("resp_state is 0x%X", status); + + g_dbus_method_invocation_return_dbus_error(req_info->context, + "org.bluez.Error.Failed", "Application Error"); + + conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info); + + req_info->context = NULL; + if (req_info->attr_path) + g_free(req_info->attr_path); + if (req_info->svc_path) + g_free(req_info->svc_path); + g_free(req_info); + + return BT_STATUS_SUCCESS; + } + + + if (req_info->request_type == BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_WRITE) { + + INFO("GATT Server Send Response BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_WRITE to bluez %d\n", fd); + g_dbus_method_invocation_return_value_with_unix_fd_list( + req_info->context, g_variant_new("(hq)", 0, mtu), (GUnixFDList*)fdlist); + + } else if (req_info->request_type == BT_HAL_GATT_REQUEST_TYPE_ACQUIRE_NOTIFY) { + g_dbus_method_invocation_return_value(req_info->context, + g_variant_new("(hq)", fd, mtu)); + } else { + g_dbus_method_invocation_return_value(req_info->context, NULL); + } + conn_info->gatt_req_info_list = g_slist_remove(conn_info->gatt_req_info_list, req_info); + + req_info->context = NULL; + if (req_info->attr_path) + g_free(req_info->attr_path); + if (req_info->svc_path) + g_free(req_info->svc_path); + g_free(req_info); + + return BT_STATUS_SUCCESS; +} + + static bt_status_t gatt_server_update_att_value(int server_if, int attribute_handle, int value_length, char* att_value) { @@ -3139,5 +3317,6 @@ const btgatt_server_interface_t btgatt_server_interface = { gatt_server_multi_adv_update, gatt_server_multi_adv_set_inst_data, gatt_server_multi_adv_disable, - gatt_server_get_mtu_size + gatt_server_get_mtu_size, + gatt_server_send_acquire_response }; diff --git a/bt-oal/bluez_hal/src/bt-hal-gatt.c b/bt-oal/bluez_hal/src/bt-hal-gatt.c index e6004d5..d34d339 100644 --- a/bt-oal/bluez_hal/src/bt-hal-gatt.c +++ b/bt-oal/bluez_hal/src/bt-hal-gatt.c @@ -245,11 +245,20 @@ static void __bt_hal_handle_gatt_server_write_requested(void *buf, uint16_t len) ev->is_prep, ev->value); } +static void __bt_hal_handle_gatt_server_acquire_write_requested(void *buf, uint16_t len) +{ + struct hal_ev_gatt_server_acquire_write_res *ev = buf; + + DBG("acquire write requested event recived"); + + if (bt_gatt_callbacks->server->request_acquire_write_cb) + bt_gatt_callbacks->server->request_acquire_write_cb(ev->mtu, ev->conn_id, ev->trans_id, ev->char_handl, (bt_bdaddr_t *)ev->bdaddr); +} + static void __bt_hal_handle_gatt_server_indicate_confirmed(void *buf, uint16_t len) { struct hal_ev_gatt_server_indicate_cfm *ev = buf; - if (bt_gatt_callbacks->server->indication_confirmation_cb) bt_gatt_callbacks->server->indication_confirmation_cb(ev->conn_id, ev->trans_id, ev->att_handle, (bt_bdaddr_t *) ev->bdaddr); @@ -380,6 +389,11 @@ static void __bt_hal_gatt_events(int message, void *buf, uint16_t len) __bt_handle_gatt_client_watch_notification(buf, len); break; } + case HAL_EV_GATT_SERVER_ACQUIRE_WRITE_RES:{ + __bt_hal_handle_gatt_server_acquire_write_requested(buf, len); + break; + } + default: DBG("Event Currently not handled!!"); break; diff --git a/bt-oal/hardware/bt_gatt_server.h b/bt-oal/hardware/bt_gatt_server.h index f8cd427..190cea1 100644 --- a/bt-oal/hardware/bt_gatt_server.h +++ b/bt-oal/hardware/bt_gatt_server.h @@ -127,10 +127,19 @@ typedef void (*request_write_callback)(int conn_id, int trans_id, bt_bdaddr_t *b int attr_handle, int offset, int length, bool need_rsp, bool is_prep, uint8_t* value); +/** + * Callback invoked when a remote device has requested to acqiore write to a + * characteristic . + */ +typedef void (*request_acquire_write_callback)(int mtu, int conn_id, int trans_id, + int attr_handle, bt_bdaddr_t *bda); + /** Callback invoked when a previously prepared write is to be executed */ typedef void (*request_exec_write_callback)(int conn_id, int trans_id, bt_bdaddr_t *bda, int exec_write); + + /** * Callback triggered in response to send_response if the remote device * sends a confirmation. @@ -181,6 +190,7 @@ typedef struct { #ifdef TIZEN_BT_HAL notification_enabled_callback notif_enabled_cb; #endif + request_acquire_write_callback request_acquire_write_cb; } btgatt_server_callbacks_t; /** Represents the standard BT-GATT server interface. */ @@ -261,6 +271,10 @@ typedef struct { /* Get current att mtu size of active connection */ bt_status_t (*get_att_mtu)(int conn_id, int *mtu_size); + + /** Send a response to a acquire write/notify operation */ + bt_status_t (*send_response_acquire)(int conn_id, int trans_id, + int status, int fd, int mtu, void *); } btgatt_server_interface_t; __END_DECLS diff --git a/bt-oal/include/oal-event.h b/bt-oal/include/oal-event.h index 472b9ad..5cbfca4 100644 --- a/bt-oal/include/oal-event.h +++ b/bt-oal/include/oal-event.h @@ -173,6 +173,8 @@ extern "C" { EVENT(OAL_EVENT_GATTC_SERVICE_CHANGED_IND) /* gattc service changed indication */\ EVENT(OAL_EVENT_GATTC_PREPARE_WRITE) /* gattc prepare write */\ EVENT(OAL_EVENT_GATTC_EXECUTE_WRITE) /* gattc execute write */\ + EVENT(OAL_EVENT_GATTS_REQUEST_ACQUIRE_WRITE) /* gattc acquire write */\ + EVENT(OAL_EVENT_GATTS_REQUEST_ACQUIRE_NOTIFY) /* gattc acquire notify */\ EVENT(OAL_EVENT_END) /* End of event*/\ @@ -373,6 +375,12 @@ typedef struct { typedef struct { gatts_trans_attr_t attr_trans; + int mtu; + bt_address_t address; +} event_gatts_srvc_acquire_attr_t ; + +typedef struct { + gatts_trans_attr_t attr_trans; int length; bt_address_t address; uint8_t value[OAL_GATT_MAX_ATTR_LEN]; diff --git a/bt-oal/include/oal-gatt.h b/bt-oal/include/oal-gatt.h index e448edd..eae3d6d 100644 --- a/bt-oal/include/oal-gatt.h +++ b/bt-oal/include/oal-gatt.h @@ -432,6 +432,12 @@ oal_status_t gattc_read_descriptor(int conn_id, oal_gatt_srvc_id_t *srvc_id, oal oal_status_t gattc_write_characteristic(int conn_id, oal_gatt_srvc_id_t *srvc_id, oal_gatt_id_t *char_id, oal_gatt_write_type_t write_type, int len, oal_gatt_auth_req_t auth_req, char* data); +oal_status_t gattc_acquire_notify(int conn_id, oal_gatt_srvc_id_t *srvc_id, + oal_gatt_id_t *char_id, int *fd , char *path); + +oal_status_t gattc_acquire_write(int conn_id, oal_gatt_srvc_id_t *srvc_id, + oal_gatt_id_t *char_id, oal_gatt_auth_req_t auth_req , int *fd , char *path); + oal_status_t gattc_write_descriptor(int conn_id, oal_gatt_srvc_id_t *srvc_id, oal_gatt_id_t *char_id, oal_gatt_id_t *desc_id, oal_gatt_write_type_t write_type, int len, oal_gatt_auth_req_t auth_req, char* data); @@ -444,4 +450,8 @@ oal_status_t gattc_register_for_notification(int client_id, bt_address_t * addre oal_status_t gattc_deregister_for_notification(int client_id, bt_address_t * address, oal_gatt_srvc_id_t *srvc_id, oal_gatt_id_t *char_id); + +oal_status_t gatt_send_response_acquire(int conn_id, int trans_id, + int status, int fd, int mtu, void *); + #endif /* OAL_GATT_H_ */ diff --git a/bt-oal/oal-gatt.c b/bt-oal/oal-gatt.c index 081f4cf..9d195e2 100644 --- a/bt-oal/oal-gatt.c +++ b/bt-oal/oal-gatt.c @@ -152,6 +152,8 @@ static void cb_gatts_request_write(int conn_id, int trans_id, bt_bdaddr_t *bda, bool need_rsp, bool is_prep, uint8_t* value); static void cb_gatts_response_confirmation(int status, int handle); +static void cb_gatts_acquire_write(int fd, int conn_id, int trans_id, int attr_handle, bt_bdaddr_t*); + static void cb_indication_confirmation(int conn_id, int trans_id, int attr_handle, bt_bdaddr_t *bda); static void cb_gatts_connection(int conn_id, int server_if, int connected, bt_bdaddr_t *bda); @@ -188,6 +190,7 @@ static const btgatt_server_callbacks_t btgatt_server_callbacks = { #ifdef TIZEN_BT_HAL cb_notifcation_changed, #endif + cb_gatts_acquire_write }; /* Forward declaration for GATT client callbacks */ @@ -788,7 +791,22 @@ oal_status_t gatts_get_att_mtu(int conn_id, int *mtu) BT_INFO("Current ATT MTU Size: %d", *mtu); return OAL_STATUS_SUCCESS; } +oal_status_t gatt_send_response_acquire(int conn_id, int trans_id, + int status, int fd, int mtu , void * fdlist) +{ + int ret = OAL_STATUS_SUCCESS; + + API_TRACE("Server Send Response : ConnId = %d, TransId = %d, %d", conn_id, trans_id, fd); + CHECK_OAL_GATT_ENABLED(); + + ret = gatt_api->server->send_response_acquire(conn_id, trans_id, status, fd, mtu, fdlist); + if (ret != BT_STATUS_SUCCESS) { + BT_ERR("GATT Server Send Response failed: %s", status2string(ret)); + return convert_to_oal_status(ret); + } + return OAL_STATUS_SUCCESS; +} oal_status_t gatts_add_service(int instance_id, oal_gatt_srvc_id_t *gatt_serv_id, int num_handles) { @@ -1252,6 +1270,22 @@ static void cb_gatts_request_write(int conn_id, int trans_id, send_event(OAL_EVENT_GATTS_REQUEST_WRITE, event, sizeof(event_gatts_srvc_write_attr_t)); } +static void cb_gatts_acquire_write(int mtu, int conn_id, int trans_id, int attr_handle , bt_bdaddr_t *bda) + +{ + BT_INFO("BTGATT SERVER REQUEST ACQUIRE WRITE conn_id:%d", conn_id); + + event_gatts_srvc_acquire_attr_t* event = g_new0(event_gatts_srvc_acquire_attr_t, 1); + + event->attr_trans.attr_handle = attr_handle; + event->attr_trans.conn_id = conn_id; + event->attr_trans.trans_id = trans_id; + event->mtu = mtu; + memcpy(event->address.addr, bda->address, BT_ADDRESS_BYTES_NUM); + + send_event(OAL_EVENT_GATTS_REQUEST_ACQUIRE_WRITE, event, sizeof(event_gatts_srvc_acquire_attr_t)); +} + static void cb_gatts_response_confirmation(int status, int handle) { BT_INFO("BTGATT SERVER RESPONSE CONFIRMATION CB, status:%d, handle:%d", status, handle); diff --git a/bt-service-adaptation/services/bt-request-handler.c b/bt-service-adaptation/services/bt-request-handler.c index c47990c..356db00 100644 --- a/bt-service-adaptation/services/bt-request-handler.c +++ b/bt-service-adaptation/services/bt-request-handler.c @@ -2256,6 +2256,39 @@ int __bt_bluez_request(int function_name, break; } + case BT_GATT_SERVER_ACQURE_WRITE_RESPONSE: { + + bluetooth_gatt_server_acquire_response_params_t param; + char *app; + GDBusMessage *msg; + msg = g_dbus_method_invocation_get_message(context); + GUnixFDList *fd_list; + int fd = -1;; + int *fd_list_array; + int len; + + BT_ERR("sending acquire write respose \n"); + + fd_list = g_dbus_message_get_unix_fd_list(msg); + + memset(¶m, 0x00, sizeof(bluetooth_gatt_server_acquire_response_params_t)); + + app = (char*)g_dbus_method_invocation_get_sender(context); + + __bt_service_get_parameters(in_param1, ¶m, + sizeof(bluetooth_gatt_server_acquire_response_params_t)); + + BT_ERR("sending acquire write respose sent \n "); + + fd_list_array = g_unix_fd_list_peek_fds(fd_list, &len); + BT_INFO("Num fds in fd_list is : %d, fd_list[0]: %d", len, fd_list_array[0]); + fd = fd_list_array[0]; + + param.fd = fd; + result = _bt_gatt_server_acquire_send_response(app, ¶m, fd_list); + + break; + } case BT_GATT_SERVER_SEND_INDICATION: { bluetooth_gatt_server_indication_params_t param; bluetooth_gatt_att_data_t data; @@ -3564,6 +3597,7 @@ gboolean __bt_service_check_privilege(int function_name, case BT_GATT_SERVER_STOP_SERVICE: case BT_GATT_SERVER_DELETE_SERVICE: case BT_GATT_SERVER_SEND_RESPONSE: + case BT_GATT_SERVER_ACQURE_WRITE_RESPONSE: case BT_GATT_SERVER_SEND_INDICATION: case BT_GATT_SERVER_UPDATE_VALUE: case BT_GATT_SERVER_DEREGISTER: diff --git a/bt-service-adaptation/services/bt-service-event-receiver.c b/bt-service-adaptation/services/bt-service-event-receiver.c index 74c3782..f68ff80 100644 --- a/bt-service-adaptation/services/bt-service-event-receiver.c +++ b/bt-service-adaptation/services/bt-service-event-receiver.c @@ -324,6 +324,8 @@ static gboolean __bt_handle_oal_events(gpointer data) case OAL_EVENT_GATTS_REQUEST_READ: /* gatts Request Read from client */\ case OAL_EVENT_GATTS_REQUEST_WRITE: /* gatts Request Write from client */\ case OAL_EVENT_GATTS_IND_CONFIRM: /* gatts Indicate confirmation from remote client */\ + case OAL_EVENT_GATTS_REQUEST_ACQUIRE_WRITE: + case OAL_EVENT_GATTS_REQUEST_ACQUIRE_NOTIFY: /* Tizen Platform Specific */ case OAL_EVENT_GATTS_NOTIFICATION: /* gatts Notification changed event */\ case OAL_EVENT_GATTS_MTU_CHANGED: /* gatts MTU changed event */\ diff --git a/bt-service-adaptation/services/bt-service-event-sender.c b/bt-service-adaptation/services/bt-service-event-sender.c index d21bb72..1d78046 100644 --- a/bt-service-adaptation/services/bt-service-event-sender.c +++ b/bt-service-adaptation/services/bt-service-event-sender.c @@ -482,6 +482,9 @@ int _bt_send_event(int event_type, int event, GVariant *param) case BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED: signal = BT_GATT_SERVER_NOTIFICATION_CHANGED; break; + case BLUETOOTH_EVENT_GATT_SERVER_ACQUIRE_WRITE: + signal = BT_GATT_SERVER_ACQUIRE_WRITE; + break; #endif #ifdef TIZEN_GATT_CLIENT case BLUETOOTH_EVENT_GATT_READ_CHAR: /* GATT Client */ diff --git a/bt-service-adaptation/services/gatt/bt-service-gatt.c b/bt-service-adaptation/services/gatt/bt-service-gatt.c index abcba75..6529804 100644 --- a/bt-service-adaptation/services/gatt/bt-service-gatt.c +++ b/bt-service-adaptation/services/gatt/bt-service-gatt.c @@ -1653,6 +1653,45 @@ static void __bt_handle_gatt_server_disconnection_state(event_gatts_conn_t *even } #endif + +static void __bt_handle_gatt_server_acquire_write_requested(event_gatts_srvc_acquire_attr_t *event) +{ + GVariant *param = NULL; + int result = BLUETOOTH_ERROR_NONE; + struct gatt_server_req_info *req_info = NULL; + bluetooth_device_address_t dev_addr; + char adress[BT_ADDRESS_STRING_SIZE] = {'/0',}; + ; + BT_INFO("GATT Server ACQUIRE Write Req Connection ID: [%d]", event->attr_trans.conn_id); + BT_INFO("GATT Server ACQUIRE Write Req Transaction ID:[%d]", event->attr_trans.trans_id); + BT_INFO("GATT Server ACQUIRE Write Req Attribute Handle: [%d]", event->attr_trans.attr_handle); + + //adress = g_malloc0(BT_ADDRESS_STRING_SIZE); + memcpy(dev_addr.addr, event->address.addr, 6); + + req_info = g_new0(struct gatt_server_req_info, 1); + req_info->request_id = event->attr_trans.trans_id; + req_info->attribute_handle = event->attr_trans.attr_handle; + req_info->connection_id = event->attr_trans.conn_id; + req_info->request_type = BLUETOOTH_GATT_REQUEST_TYPE_ACQUIRE_WRITE; + gatt_server_requests = g_slist_append(gatt_server_requests, req_info); + + _bt_convert_addr_type_to_string(adress, + (unsigned char *)dev_addr.addr); + + param = g_variant_new("(iiiiiis)", result, + event->attr_trans.conn_id, + event->attr_trans.trans_id, + event->attr_trans.attr_handle, + event->mtu, event->attr_trans.offset, adress); + BT_INFO("GATT Server ACQUIRE Write Req Attribute remote adress : [%s]", adress); + + + _bt_send_event(BT_GATT_SERVER_EVENT, + BLUETOOTH_EVENT_GATT_SERVER_ACQUIRE_WRITE, + param); +} + static void __bt_handle_gatt_server_write_requested(event_gatts_srvc_write_attr_t *event) { char *address; @@ -1953,6 +1992,11 @@ static void __bt_gatt_event_handler(int event_type, gpointer event_data) __bt_handle_gatt_server_write_requested((event_gatts_srvc_write_attr_t *)event_data); break; } + case OAL_EVENT_GATTS_REQUEST_ACQUIRE_WRITE: { + BT_INFO("OAL Event: GATT Server Acquire Write Request"); + __bt_handle_gatt_server_acquire_write_requested((event_gatts_srvc_acquire_attr_t*)event_data); + break; + } case OAL_EVENT_GATTS_IND_CONFIRM: { BT_INFO("OAL Event: GATT Server Indication confirmed"); __bt_handle_gatt_server_indicate_confirmed((event_gatts_ind_cnfrm_t *)event_data); @@ -2237,6 +2281,43 @@ int _bt_gatt_server_send_response(char *sender, bluetooth_gatt_att_data_t *data, return BLUETOOTH_ERROR_NONE; } +int _bt_gatt_server_acquire_send_response(char *sender, bluetooth_gatt_server_acquire_response_params_t *param , void *fd_list) +{ + BT_CHECK_PARAMETER(sender, return); + BT_CHECK_PARAMETER(param, return); + struct gatt_server_req_info *req_info = NULL; + int ret = OAL_STATUS_SUCCESS; + + + BT_INFO("GATT acquire Server Response: Req Type [%d] req_id [%d] fd [%d] mtu[%d]", + param->req_type, param->request_id, + param->fd, + param->mtu); + + /* Search for matching Request in List */ + req_info = __bt_gatt_server_find_request_info(param->request_id, param->req_type); + if (!req_info) { + BT_ERR("GATT acquire Server Req Info not found for current response..return Error"); + return BLUETOOTH_ERROR_NOT_IN_OPERATION; + } + + ret = gatt_send_response_acquire(req_info->connection_id, param->request_id, 0, param->fd, param->mtu, fd_list); + + if (ret != OAL_STATUS_SUCCESS) { + BT_ERR("ret: %d", ret); + return BLUETOOTH_ERROR_INTERNAL; + } + + BT_INFO("GATT acquire Server Response successfully sent"); + /* Remove GATT server request from list */ + gatt_server_requests = g_slist_remove(gatt_server_requests, req_info); + g_free(req_info->addr); + + return BLUETOOTH_ERROR_NONE; +} + + + int _bt_gatt_server_send_indication(char *sender, bluetooth_device_address_t *dev_addr, bluetooth_gatt_att_data_t *data, bluetooth_gatt_server_indication_params_t *param) diff --git a/bt-service-adaptation/services/include/bt-service-gatt.h b/bt-service-adaptation/services/include/bt-service-gatt.h index 95a88f9..c7be56e 100644 --- a/bt-service-adaptation/services/include/bt-service-gatt.h +++ b/bt-service-adaptation/services/include/bt-service-gatt.h @@ -95,6 +95,8 @@ int _bt_gatt_server_update_attribute_value(char *sender, int instance_id, int _bt_get_att_mtu(bluetooth_device_address_t *address, unsigned int *mtu); +int _bt_gatt_server_acquire_send_response(char *sender, bluetooth_gatt_server_acquire_response_params_t *param, void *); + #ifdef TIZEN_GATT_CLIENT char * _bt_gatt_get_default_gatt_client_uuid(void); diff --git a/include/bluetooth-api.h b/include/bluetooth-api.h index 2ee5edb..d0acb94 100644 --- a/include/bluetooth-api.h +++ b/include/bluetooth-api.h @@ -813,7 +813,8 @@ typedef enum { BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_STATE_CHANGED, /**