#define NUM_UUID 20
#define UUID_MAX_LEN 50
+#ifdef TIZEN_BLUEDROID_PORTING
+typedef struct {
+ int connection_id;
+ int request_id;
+ char *device_address;
+ char *value;
+ int handle;
+ int offset;
+ int length;
+ bluetooth_gatt_att_request_type_e request_type;
+ int prep_request_count;
+} bt_gatt_prep_write_data_t;
+
+static GSList *g_pending_write_list = NULL;
+#endif
+
#define BDADDR_ANY (&(bluetooth_device_address_t) {{0, 0, 0, 0, 0, 0} })
static char uuid_list[NUM_UUID][BT_UUID_STRING_MAX] = {"0000b00b-0000-0000-f065-080080fa49b5", /* Used by BLEAPP */
param);
}
+#ifdef TIZEN_BLUEDROID_PORTING
+static bt_gatt_prep_write_data_t* __bt_create_prep_write_data(event_gatts_srvc_write_attr_t *event)
+{
+ bluetooth_device_address_t dev_addr;
+ char *addr;
+ bt_gatt_prep_write_data_t *prep_data = NULL;
+
+ prep_data = g_malloc0(sizeof(bt_gatt_prep_write_data_t));
+ prep_data->connection_id = event->attr_trans.conn_id;
+ prep_data->request_id = event->attr_trans.trans_id;
+ prep_data->handle = event->attr_trans.attr_handle;
+ prep_data->request_type = BLUETOOTH_GATT_REQUEST_TYPE_WRITE;
+ memcpy(dev_addr.addr, event->address.addr, 6);
+ addr = g_malloc0(BT_ADDRESS_STRING_SIZE);
+ _bt_convert_addr_type_to_string(addr,
+ (unsigned char *)dev_addr.addr);
+ prep_data->device_address = addr;
+ prep_data->offset = event->attr_trans.offset;
+ prep_data->length = event->length;
+ prep_data->value = g_memdup(&event->value[0], event->length);
+
+ return prep_data;
+}
+
+static int __bt_gatt_server_send_long_write_response(bt_gatt_prep_write_data_t *prep_data, int resp_status, int auth_req)
+{
+ int ret = OAL_STATUS_SUCCESS;
+ oal_gatt_response_t response;
+
+ memset(&response, 0x00, sizeof(oal_gatt_response_t));
+
+ BT_INFO("GATT Server Write Res Connection ID: [%d]", prep_data->connection_id);
+ BT_INFO("GATT Server Write Res Transaction ID:[%d]", prep_data->request_id);
+ BT_INFO("GATT Server Write Res Attribute Handle: [%d]", prep_data->handle);
+ BT_INFO("GATT Server Write Res Attribute Offset: [%d]", prep_data->offset);
+ BT_INFO("GATT Server Write Res value length [%d]", prep_data->length);
+
+ response.handle = prep_data->handle;
+ response.attr_value.auth_req = auth_req;
+ response.attr_value.handle = prep_data->handle;
+ response.attr_value.offset = prep_data->offset;
+ response.attr_value.len = prep_data->length;
+ memcpy(&response.attr_value.value, &prep_data->value[0], prep_data->length);
+
+ ret = gatts_send_response(prep_data->connection_id, prep_data->request_id,
+ resp_status, &response);
+ return ret;
+}
+
+static bt_gatt_prep_write_data_t* __bt_find_prep_write_data_from_request_id(int request_id)
+{
+ GSList *l;
+ bt_gatt_prep_write_data_t *prep_data = NULL;
+
+ for (l = g_pending_write_list; l != NULL; l = g_slist_next(l)) {
+ prep_data = (bt_gatt_prep_write_data_t*)l->data;
+ if (prep_data && (prep_data->request_id == request_id) &&
+ (prep_data->request_type == BLUETOOTH_GATT_REQUEST_TYPE_WRITE)) {
+ BT_INFO("prep_data found for request id [%d]", request_id);
+ return prep_data;
+ }
+ }
+ BT_INFO("prep_data not found for request [%d]", request_id);
+ return NULL;
+}
+
+static bt_gatt_prep_write_data_t* __bt_find_exec_write_req(int conn_id)
+{
+ GSList *l;
+ bt_gatt_prep_write_data_t *prep_data = NULL;
+
+ for (l = g_pending_write_list; l != NULL; l = g_slist_next(l)) {
+ prep_data = (bt_gatt_prep_write_data_t*)l->data;
+ if (prep_data && (prep_data->request_type == BLUETOOTH_GATT_REQUEST_TYPE_EXEC_WRITE)
+ && (prep_data->connection_id == conn_id)) {
+ BT_INFO("Exec request found");
+ return prep_data;
+ }
+ }
+ BT_INFO("Exec request not found");
+ return NULL;
+}
+
+static int __bt_get_prep_request_count(int conn_id)
+{
+ int count = 0;
+ GSList *l;
+ bt_gatt_prep_write_data_t *prep_data = NULL;
+
+ for (l = g_pending_write_list; l != NULL; l = g_slist_next(l)) {
+ prep_data = (bt_gatt_prep_write_data_t*)l->data;
+ if (prep_data && (prep_data->connection_id == conn_id) &&
+ (prep_data->request_type == BLUETOOTH_GATT_REQUEST_TYPE_WRITE))
+ count++;
+ }
+ return count;
+}
+
+static bt_gatt_prep_write_data_t* __bt_find_prep_write_data_from_handle(int conn_id, int handle)
+{
+ GSList *l;
+ bt_gatt_prep_write_data_t *prep_data = NULL;
+ bt_gatt_prep_write_data_t *last_prep_data = NULL;
+
+ for (l = g_pending_write_list; l != NULL; l = g_slist_next(l)) {
+ prep_data = (bt_gatt_prep_write_data_t*)l->data;
+ if (prep_data && (prep_data->connection_id == conn_id) && (prep_data->handle == handle)) {
+ BT_INFO("prep_data entry found for handle [%d]", handle);
+ last_prep_data = prep_data;
+ }
+ }
+
+ if (!last_prep_data)
+ BT_INFO("prep_data entry not found for handle [%d]", handle);
+
+ return last_prep_data;
+}
+
+static void __bt_gatt_server_send_prep_write_req(int conn_id)
+{
+ int result = BLUETOOTH_ERROR_NONE;
+ GSList *l;
+ bt_gatt_prep_write_data_t *prep_data = NULL;
+
+ for (l = g_pending_write_list; l != NULL; l = g_slist_next(l)) {
+ prep_data = (bt_gatt_prep_write_data_t*)l->data;
+ if (prep_data && (prep_data->connection_id == conn_id) &&
+ (prep_data->request_type == BLUETOOTH_GATT_REQUEST_TYPE_WRITE)) {
+ BT_INFO("sending prep_req, req_id=%d", prep_data->request_id);
+ GVariant *data = NULL;
+ GVariant *param = NULL;
+ data = g_variant_new_from_data(
+ G_VARIANT_TYPE_BYTESTRING,
+ prep_data->value,
+ prep_data->length,
+ TRUE, NULL, NULL);
+
+ param = g_variant_new("(iiiiiibbsn@ay)", result,
+ prep_data->connection_id,
+ prep_data->request_id,
+ prep_data->handle,
+ prep_data->offset,
+ prep_data->length,
+ 1,
+ 0,
+ prep_data->device_address,
+ prep_data->length,
+ data);
+
+ _bt_send_event(BT_GATT_SERVER_EVENT,
+ BLUETOOTH_EVENT_GATT_SERVER_VALUE_CHANGED,
+ param);
+ }
+ }
+}
+
+static void __bt_remove_all_prep_write_req(int conn_id)
+{
+ GSList *l;
+ bt_gatt_prep_write_data_t *prep_data = NULL;
+
+ BT_INFO("Removing all req for conn_id %d", conn_id);
+ for (l = g_pending_write_list; l != NULL;) {
+ prep_data = (bt_gatt_prep_write_data_t*)l->data;
+ l = g_slist_next(l);
+ if (prep_data && (prep_data->connection_id == conn_id)) {
+ BT_INFO("Removing req for req_id %d", prep_data->request_id);
+ g_pending_write_list = g_slist_remove(g_pending_write_list, prep_data);
+ g_free(prep_data->value);
+ g_free(prep_data->device_address);
+ g_free(prep_data);
+ prep_data = NULL;
+ }
+ }
+}
+
+static bool __bt_update_prep_write_data(bt_gatt_prep_write_data_t *prep_data, int offset,
+ int length, char *value)
+{
+ char *val;
+ int len;
+
+ if (!length)
+ return true;
+
+ len = prep_data->length + length;
+ val = g_realloc(prep_data->value, len);
+ if (!val)
+ return false;
+
+ memcpy(val + prep_data->length, value, length);
+ prep_data->value = val;
+ prep_data->length = len;
+
+ BT_INFO("updated prep_data->length %d, prep_data->req_id %d", prep_data->length, prep_data->request_id);
+ return true;
+}
+
+static bool __bt_handle_gatt_server_prepare_write_response(int *res,
+ bluetooth_gatt_server_response_params_t *param)
+{
+ bt_gatt_prep_write_data_t *prep_data = NULL;
+ bt_gatt_prep_write_data_t *exec_data = NULL;
+ int conn_id = -1;
+
+ /* Search for matching Request in prepare write List */
+ prep_data = __bt_find_prep_write_data_from_request_id(param->request_id);
+
+ if (!prep_data)
+ return false;
+
+ conn_id = prep_data->connection_id;
+ exec_data = __bt_find_exec_write_req(conn_id);
+
+ if (!exec_data) {
+ BT_ERR("Oops, Something weird has happened!!!");
+ *res = BLUETOOTH_ERROR_INTERNAL;
+ __bt_remove_all_prep_write_req(conn_id);
+ } else {
+ // remove pending write request from the list
+ BT_INFO("Removing prending write request, request id = %d", prep_data->request_id);
+ g_pending_write_list = g_slist_remove(g_pending_write_list, prep_data);
+ g_free(prep_data->value);
+ g_free(prep_data->device_address);
+ g_free(prep_data);
+
+ exec_data->prep_request_count--;
+ if (param->response_status || !exec_data->prep_request_count) {
+ BT_INFO("Sending exec response with status = %d", param->response_status);
+ ret = __bt_gatt_server_send_long_write_response(exec_data, param->response_status, param->auth_req);
+ if (ret != OAL_STATUS_SUCCESS) {
+ BT_ERR("ret: %d", ret);
+ *res = BLUETOOTH_ERROR_INTERNAL;
+ }
+ __bt_remove_all_prep_write_req(conn_id);
+ }
+ }
+ return true;
+}
+
+static void __bt_handle_gatt_server_prepare_write_requested(event_gatts_srvc_write_attr_t *event)
+{
+ bt_gatt_prep_write_data_t *pdata = NULL;
+ bt_gatt_prep_write_data_t *prep_data = NULL;
+ int ret;
+ int resp_status = BLUETOOTH_ATT_ERROR_NONE;
+
+ prep_data = __bt_create_prep_write_data(event);
+
+ /* Find if the req node for that attribute already exists */
+ pdata = __bt_find_prep_write_data_from_handle(prep_data->connection_id, prep_data->handle);
+
+ if (!pdata || (prep_data->offset != (pdata->length + pdata->offset))) {
+ BT_INFO("prep_write_req node doestn't exist or data is not in continuation, offset=%d", prep_data->offset);
+ pdata = prep_data;
+ g_pending_write_list = g_slist_append(g_pending_write_list, (gpointer)pdata);
+ BT_INFO("Send prep_write_response");
+ ret = __bt_gatt_server_send_long_write_response(prep_data, resp_status, 0);
+ } else {
+ /* Update the data and offset in attribute node */
+ if (!(__bt_update_prep_write_data(pdata, prep_data->offset, prep_data->length, prep_data->value))) {
+ BT_ERR("prep_data couldnot be updated");
+ resp_status = BLUETOOTH_ATT_ERROR_INSUFFICIENT_RESOURCES;
+ }
+ BT_INFO("Send prep_write_response");
+ ret = __bt_gatt_server_send_long_write_response(prep_data, resp_status, 0);
+ g_free(prep_data->device_address);
+ g_free(prep_data->value);
+ g_free(prep_data);
+ }
+
+ if (ret != OAL_STATUS_SUCCESS)
+ BT_ERR("ret: %d", ret);
+}
+#endif
+
static void __bt_handle_gatt_server_write_requested(event_gatts_srvc_write_attr_t *event)
{
char *address;
return;
}
+#ifdef TIZEN_BLUEDROID_PORTING
+ if (event->is_prep) {
+ BT_INFO("receive prepare_write request");
+ return __bt_handle_gatt_server_prepare_write_requested(event);
+ }
+#endif
+
need_resp = event->need_rsp;
is_prepare_write = event->is_prep;
g_free(write_val);
}
+#ifdef TIZEN_BLUEDROID_PORTING
+static void __bt_handle_gatt_server_exec_write_requested(event_gatts_srvc_exec_write_attr_t *event)
+{
+ char *address;
+ bluetooth_device_address_t dev_addr;
+ int ret;
+ bt_gatt_prep_write_data_t *exec_data = NULL;
+ int resp_status = BLUETOOTH_ATT_ERROR_NONE;
+ BT_INFO("GATT Server Execute Write Requested");
+
+ memcpy(dev_addr.addr, event->address.addr, 6);
+ address = g_malloc0(BT_ADDRESS_STRING_SIZE);
+ _bt_convert_addr_type_to_string(address,
+ (unsigned char *)dev_addr.addr);
+
+ BT_INFO("GATT Server Exec Write Req Connection ID: [%d]", event->conn_id);
+ BT_INFO("GATT Server Exec Write Req Transaction ID:[%d]", event->trans_id);
+ BT_INFO("GATT Server Exec Write Req Exec Write: [%d]", event->exec_write);
+
+ // prepare exec response data
+ exec_data = g_malloc0(sizeof(bt_gatt_prep_write_data_t));
+ exec_data->connection_id = event->conn_id;
+ exec_data->request_id = event->trans_id;
+ exec_data->device_address = address;
+ exec_data->request_type = BLUETOOTH_GATT_REQUEST_TYPE_EXEC_WRITE;
+ exec_data->prep_request_count = __bt_get_prep_request_count(exec_data->connection_id);
+
+ if ((exec_data->prep_request_count != 1) || !event->exec_write) {
+ if (!event->exec_write) {
+ BT_INFO("Cancelling all prepared writes, removing all pending entries");
+ __bt_remove_all_prep_write_req(event->conn_id);
+ } else if (exec_data->prep_request_count > 1) {
+ /* TODO: Handle reliable-write session */
+ BT_INFO("This may be reliable write session. Not yet supported!!!, prep_request_count =%d",
+ exec_data->prep_request_count);
+ resp_status = BLUETOOTH_ATT_ERROR_REQUEST_NOT_SUPPORTED;
+ __bt_remove_all_prep_write_req(event->conn_id);
+ }
+
+ BT_INFO("Send exec response");
+ // Made response and send it.
+ ret = __bt_gatt_server_send_long_write_response(exec_data, resp_status, 0);
+ if (ret != OAL_STATUS_SUCCESS)
+ BT_ERR("ret: %d", ret);
+
+ g_free(exec_data->device_address);
+ g_free(exec_data);
+ return;
+ }
+
+ BT_INFO("Write all pending prepared values");
+ __bt_gatt_server_send_prep_write_req(exec_data->connection_id);
+
+ // Add exec request in the queue.
+ g_pending_write_list = g_slist_append(g_pending_write_list, (gpointer)exec_data);
+}
+#endif
+
static void __bt_handle_gatt_server_read_requested(event_gatts_srvc_read_attr_t *event)
{
char *address = g_malloc0(BT_ADDRESS_STRING_SIZE);
__bt_handle_gatt_server_write_requested((event_gatts_srvc_write_attr_t *)event_data);
break;
}
+#ifdef TIZEN_BLUEDROID_PORTING
+ case OAL_EVENT_GATTS_EXEC_REQUEST_WRITE: {
+ BT_INFO("OAL Event: GATT Server Exec Write Request");
+ __bt_handle_gatt_server_exec_write_requested((event_gatts_srvc_exec_write_attr_t *)event_data);
+ break;
+ }
+#endif
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);
BT_CHECK_PARAMETER(param, return);
struct gatt_server_req_info *req_info = NULL;
int ret = OAL_STATUS_SUCCESS;
-
+#ifdef TIZEN_BLUEDROID_PORTING
+ int res = BLUETOOTH_ERROR_NONE;
+#endif
oal_gatt_response_t response;
- BT_DBG("GATT Server Response: Req Type [%d] req_id [%d] status [%d] auth_req [%d] offset[%d] data len[%d]",
+ BT_INFO("GATT Server Response: Req Type [%d] req_id [%d] status [%d] auth_req [%d] offset[%d] data len[%d]",
param->req_type, param->request_id,
param->response_status, param->auth_req,
data->offset, data->length);
+#ifdef TIZEN_BLUEDROID_PORTING
+ if (__bt_handle_gatt_server_prepare_write_response(&res, param))
+ return res;
+#endif
+
/* Search for matching Request in List */
req_info = __bt_gatt_server_find_request_info(param->request_id, param->req_type);
if (!req_info) {