X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=bt-oal%2Foal-gatt.c;h=081f4cf9aadd9a3a5457cfb7de6ad311933cbd70;hb=refs%2Fchanges%2F15%2F186215%2F1;hp=3eca8fbeb3506d22d304f31ff34cd1f0e825d8e2;hpb=f5b1701014d67b941e2bf1ae52bcda49e9279789;p=platform%2Fcore%2Fconnectivity%2Fbluetooth-frwk.git diff --git a/bt-oal/oal-gatt.c b/bt-oal/oal-gatt.c index 3eca8fb..081f4cf 100644 --- a/bt-oal/oal-gatt.c +++ b/bt-oal/oal-gatt.c @@ -29,7 +29,7 @@ #define DEV_APPEARANCE 0x0000 #define DEFAULT_GATT_CLIENT_UUID "0000A00A-1111-1111-0123-456789ABCDEF" -#define MAX_PROP_LEN 90 +#define MAX_PROP_LEN 95 /* SVACE WGID: 324403*/ #define MAX_PERM_LEN 80 //Fix for svace wgid:324402 #define NUM_SERVER_INST 10 // Maximum slots supported by stack is set to 10 @@ -80,6 +80,23 @@ } \ } while (0) +#define CHECK_CLIENT_REGISTRATION(client_id) \ + do { \ + if (client_id <= 0) { \ + BT_DBG("No client registered yet...");\ + return OAL_STATUS_INTERNAL_ERROR;\ + } \ + } while (0) + +#define CHECK_CLIENT_CONNECTION(conn_id) \ + do { \ + if (conn_id <= 0) {\ + BT_ERR("No active connection");\ + return OAL_STATUS_INTERNAL_ERROR;\ + } \ + } while (0) + + typedef enum { GATT_INS_DISABLED, GATT_INS_DATA_SETTING, @@ -111,9 +128,6 @@ static const btgatt_interface_t * gatt_api; static gboolean cur_adv_state[NUM_SERVER_INST]; static gatt_server_t gatt_servers[NUM_SERVER_INST]; -static int default_client_id = -1; -static int pending_gattc_req = OAL_REQ_NONE; - /* Forward declarations of GATT Server callbacks */ static void cb_gatts_register_app(int status, int server_if, bt_uuid_t *uuid); static void cb_gatts_multi_adv_enable(int server_if, int status); @@ -179,24 +193,38 @@ static const btgatt_server_callbacks_t btgatt_server_callbacks = { /* Forward declaration for GATT client callbacks */ static void cb_gattc_register_app(int status, int clientIf, bt_uuid_t *app_uuid); static void cb_gattc_scan_result(bt_bdaddr_t* bdaddress, int rssi, uint8_t *adv_data); +static void cb_gattc_connection(int conn_id, int status, int client_if, bt_bdaddr_t* bda); +static void cb_gattc_disconnect(int conn_id, int status, int client_if, bt_bdaddr_t* bda); +static void cb_gattc_search_result(int conn_id, btgatt_srvc_id_t *srvc_id); +static void cb_gattc_search_complete(int conn_id, int status); +static void cb_gattc_get_characteristics(int conn_id, int status, btgatt_srvc_id_t *srvc_id, + btgatt_gatt_id_t *char_id, int char_prop); +static void cb_gattc_get_descriptor(int conn_id, int status, btgatt_srvc_id_t *srvc_id, + btgatt_gatt_id_t *char_id, btgatt_gatt_id_t *descr_id); +static void cb_gattc_read_characteristic(int conn_id, int status, btgatt_read_params_t *p_data); +static void cb_gattc_read_descriptor(int conn_id, int status, btgatt_read_params_t *p_data); +static void cb_gattc_write_characteristic(int conn_id, int status, btgatt_write_params_t *p_data); +static void cb_gattc_write_descriptor(int conn_id, int status, btgatt_write_params_t *p_data); +static void cb_gattc_register_for_notification(int conn_id, int registered, int status, + btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id); /*TODO GATT CLient callbacks will be implemented in subsequent patches */ static const btgatt_client_callbacks_t btgatt_client_callbacks = { cb_gattc_register_app, cb_gattc_scan_result, - NULL, /*cb_gattc_connection*/ - NULL, /*cb_gattc_disconnect*/ - NULL, /*cb_gattc_search_complete*/ - NULL, /*cb_gattc_search_result*/ - NULL, /*cb_gattc_get_characteristics*/ - NULL, /*cb_gattc_get_descriptor*/ + cb_gattc_connection, /*cb_gattc_connection*/ + cb_gattc_disconnect, /*cb_gattc_disconnect*/ + cb_gattc_search_complete, /*cb_gattc_search_complete*/ + cb_gattc_search_result, /*cb_gattc_search_result*/ + cb_gattc_get_characteristics, /*cb_gattc_get_characteristics*/ + cb_gattc_get_descriptor, /*cb_gattc_get_descriptor*/ NULL, /*cb_gattc_get_included_service*/ - NULL, /*cb_gattc_register_for_notification*/ + cb_gattc_register_for_notification, /*cb_gattc_register_for_notification*/ NULL, /*cb_gattc_notify*/ - NULL, /*cb_gattc_read_characteristic*/ - NULL, /*cb_gattc_write_characteristic*/ - NULL, /*cb_gattc_read_descriptor*/ - NULL, /*cb_gattc_write_descriptor*/ + cb_gattc_read_characteristic, /*cb_gattc_read_characteristic*/ + cb_gattc_write_characteristic, /*cb_gattc_write_characteristic*/ + cb_gattc_read_descriptor, /*cb_gattc_read_descriptor*/ + cb_gattc_write_descriptor, /*cb_gattc_write_descriptor*/ NULL, /*cb_gattc_execute_write*/ NULL, /*cb_gattc_remote_rssi*/ NULL, /*cb_gattc_configure_mtu_cmpl*/ @@ -568,12 +596,12 @@ oal_status_t gatts_multi_adv_set_inst_data(int instance_id, adv_setup.server_if = gatt_servers[instance_id - 1].server_id; if (adv_setup.manufacturer_data_len > 0 && adv_setup.manufacturer_data != NULL) { BT_INFO("Manufacture data.....\n"); - PRINT_ADV_DATA(adv_setup.manufacturer_data_len, adv_setup.manufacturer_data, adv_setup.set_scan_rsp); + PRINT_ADV_DATA(adv_setup.manufacturer_data_len, (unsigned char *)adv_setup.manufacturer_data, adv_setup.set_scan_rsp); } if (adv_setup.service_uuid_len > 0 && adv_setup.service_uuid != NULL) { BT_INFO("Service uuid.....\n"); - PRINT_ADV_DATA(adv_setup.service_uuid_len, adv_setup.service_uuid, FALSE); + PRINT_ADV_DATA(adv_setup.service_uuid_len, (unsigned char*)adv_setup.service_uuid, FALSE); } @@ -634,6 +662,7 @@ static void cb_gatts_listen(int status, int server_if) cur_adv_state[event->server_inst - 1] = new_state; } else { BT_ERR("Invalid Callback..."); + g_free(event); return; } @@ -982,9 +1011,6 @@ oal_status_t gatts_update_att_value(int ins_id, oal_gatt_value_t *value) { int ret = OAL_STATUS_SUCCESS; - API_TRACE("Server Update Value: Ins_id = [%d], att handle = [%d] data len [%d]", - ins_id, value->handle, value->len); - CHECK_OAL_GATT_ENABLED(); CHECK_SERVER_INSTANCE(ins_id); @@ -996,6 +1022,9 @@ oal_status_t gatts_update_att_value(int ins_id, oal_gatt_value_t *value) return OAL_STATUS_INVALID_PARAM; } + API_TRACE("Server Update Value: Ins_id = [%d], att handle = [%d] data len [%d]", + ins_id, value->handle, value->len); + ret = gatt_api->server->update_att_value(gatt_servers[ins_id - 1].server_id, (int)value->handle, (int)value->len, (char*)value->value); @@ -1286,40 +1315,18 @@ static void cb_gattc_register_app(int status, int clientIf, bt_uuid_t *app_uuid) char uuid_str[BT_UUID_STRING_MAX]; event_gattc_register_t *event; + BT_INFO("+"); + /* Check if GATT client registered for Default GATT client UUID */ uuid_to_string((service_uuid_t *)app_uuid, uuid_str); - if (!strncasecmp(DEFAULT_GATT_CLIENT_UUID, - uuid_str, strlen(DEFAULT_GATT_CLIENT_UUID))) { - default_client_id = clientIf; - switch (pending_gattc_req) { - case OAL_REQ_LE_SCAN: - if (0 != status) { - default_client_id = -1; - pending_gattc_req = OAL_REQ_NONE; - BT_ERR("Default client app creation failed"); - send_event(OAL_EVENT_BLE_DISCOVERY_STOPPED, NULL, 0); - break; - } - - if (OAL_STATUS_SUCCESS != gattc_start_le_discovery()) { - BT_ERR("Error:Start LE Discovery failed"); - send_event(OAL_EVENT_BLE_DISCOVERY_STOPPED, NULL, 0); - } - break; - default: - BT_ERR("Unknown pending request: %d", pending_gattc_req); - } - - /* Return from here, no need to send GATTC_REGISTRATION event */ - return; - } + BT_INFO("UUID:%s", uuid_str); BT_INFO("BTGATT CLIENT REGISTER APP CB, status:%d, clientIf:%d", status, clientIf); event = g_new0(event_gattc_register_t, 1); event->client_if = clientIf; event->status = (status == 0 ? OAL_STATUS_SUCCESS : OAL_STATUS_INTERNAL_ERROR); memcpy(event->client_uuid.uuid, app_uuid->uu, sizeof(oal_uuid_t)); - send_event_no_trace(OAL_EVENT_GATTC_REGISTRATION, event, sizeof(event_gattc_register_t)); + send_event(OAL_EVENT_GATTC_REGISTRATION, event, sizeof(event_gattc_register_t)); } static void cb_gattc_scan_result(bt_bdaddr_t* bdaddress, int rssi, uint8_t *adv_data) @@ -1334,78 +1341,309 @@ static void cb_gattc_scan_result(bt_bdaddr_t* bdaddress, int rssi, uint8_t *adv_ sizeof(event_ble_scan_result_info), (bt_address_t *)bdaddress); } -/* Register default gatt client to be used in LE scan etc. */ -static oal_status_t __register_default_gatt_client(void) +static void cb_gattc_connection(int conn_id, int status, int client_if, bt_bdaddr_t* bda) { - bt_uuid_t uuid; - int ret; + event_gattc_conn_t *event; + BT_INFO("BTGATT CLIENT CONNECTED CB, status:[%d] client_if[%d] id[%d]", + status, client_if, conn_id); - API_TRACE("GATT client register"); - CHECK_OAL_GATT_ENABLED(); + event = g_new0(event_gattc_conn_t, 1); + memcpy(event->address.addr, bda->address, BT_ADDRESS_BYTES_NUM); + event->client_if = client_if; - if (default_client_id >= 0) { - BT_ERR("Client Already registered"); - return OAL_STATUS_ALREADY_DONE; + if (BT_STATUS_SUCCESS != status) { + event->status = OAL_STATUS_INTERNAL_ERROR; + BT_ERR("gattc connection Error: %d", status); + } else { + event->conn_id = conn_id; + event->status = OAL_STATUS_SUCCESS; } - string_to_uuid(DEFAULT_GATT_CLIENT_UUID, (service_uuid_t *)&uuid); - ret = gatt_api->client->register_client(&uuid); - if (ret != BT_STATUS_SUCCESS) { - BT_ERR("GATT client register failed: %s", status2string(ret)); - return convert_to_oal_status(ret); + send_event_bda_trace(OAL_EVENT_GATTC_CONNECTION_COMPLETED, event, + sizeof(*event), (bt_address_t *)bda); +} + + +static void cb_gattc_disconnect(int conn_id, int status, int client_if, bt_bdaddr_t* bda) +{ + event_gattc_conn_t *event; + BT_INFO("BTGATT Client Disconnect Complete cb, status:[%d], client_if[%d] id[%d]", + status, client_if, conn_id); + event = g_new0(event_gattc_conn_t, 1); + event->status = convert_to_oal_status(status); + event->client_if = client_if; + event->conn_id = conn_id; + memcpy(event->address.addr, bda->address, BT_ADDRESS_BYTES_NUM); + send_event_bda_trace(OAL_EVENT_GATTC_DISCONNECTION_COMPLETED, event, + sizeof(*event), (bt_address_t *)bda); +} + +static void cb_gattc_search_result(int conn_id, btgatt_srvc_id_t *srvc_id) +{ + char uuid_str[2*BT_UUID_STRING_MAX]; + + BT_INFO("BTGATT Client Service Search Result cb, conn_id:%d", conn_id); + + uuid_to_stringname((oal_uuid_t *)&(srvc_id->id.uuid), uuid_str); + BT_INFO("Service=> UUID: [%s], Inst_id: [%u], Type: [%s]", + uuid_str, srvc_id->id.inst_id, srvc_id->is_primary ? "Primary" : "Secondary"); + + event_gattc_service_result_t *event = g_new0(event_gattc_service_result_t, 1); + event->conn_status.status = OAL_STATUS_SUCCESS; + event->conn_status.conn_id = conn_id; + memcpy(&(event->srvc_id), srvc_id, sizeof(oal_gatt_srvc_id_t)); + + send_event(OAL_EVENT_GATTC_SERVICE_SEARCH_RESULT, event, sizeof(*event)); +} + +static void cb_gattc_search_complete(int conn_id, int status) +{ + BT_INFO("BTGATT Client Service Search Complete cb, status:%d, conn_id:%d", + status, conn_id); + + event_gattc_conn_status_t *event = g_new0(event_gattc_conn_status_t, 1); + event->conn_id = conn_id; + event->status = convert_to_oal_status(status); + + send_event(OAL_EVENT_GATTC_SERVICE_SEARCH_DONE, event, sizeof(*event)); +} + + +static void cb_gattc_get_characteristics(int conn_id, int status, btgatt_srvc_id_t *srvc_id, + btgatt_gatt_id_t *char_id, int char_prop) +{ + char uuid_str1[2*BT_UUID_STRING_MAX]; + char uuid_str2[2*BT_UUID_STRING_MAX]; + char str[50]; + BT_INFO("BTGATT Client Get Characteristic Callback, conn_id:%d, status:%d", conn_id, status); + uuid_to_stringname((oal_uuid_t *)&(srvc_id->id.uuid), uuid_str1); + BT_INFO("Service=> UUID: [%s], Inst_id: [%u], Type: [%s]", + uuid_str1, srvc_id->id.inst_id, srvc_id->is_primary ? "Primary" : "Secondary"); + + event_gattc_characteristic_result_t *event = g_new0(event_gattc_characteristic_result_t, 1); + event->conn_status.conn_id = conn_id; + event->conn_status.status = convert_to_oal_status(status); + memcpy(&(event->srvc_id), srvc_id, sizeof(oal_gatt_srvc_id_t)); + + if (status == 0) { + uuid_to_stringname((oal_uuid_t *)&(char_id->uuid), uuid_str2); + BT_INFO("Charac=> UUID: [%s], Inst_id: [%u], Prop: [%s]", + uuid_str2, char_id->inst_id, char_prop_to_string(char_prop, str)); + event->char_prop = char_prop; + memcpy(&(event->char_id), char_id, sizeof(oal_gatt_id_t)); } + send_event(OAL_EVENT_GATTC_CHARAC_SERACH_RESULT, event, sizeof(*event)); +} - return OAL_STATUS_SUCCESS; + + +static void cb_gattc_get_descriptor(int conn_id, int status, btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id, btgatt_gatt_id_t *descr_id) +{ + char uuid_str1[2*BT_UUID_STRING_MAX]; + char uuid_str2[2*BT_UUID_STRING_MAX]; + char uuid_str3[2*BT_UUID_STRING_MAX]; + BT_INFO("BTGATT Client Get Descriptor Callback, conn_id:%d, status:%d", conn_id, status); + uuid_to_stringname((oal_uuid_t *)&(srvc_id->id.uuid), uuid_str1); + uuid_to_stringname((oal_uuid_t *)&(char_id->uuid), uuid_str2); + BT_INFO("Service=> UUID: [%s], Inst_id: [%u], Type: [%s]", + uuid_str1, srvc_id->id.inst_id, srvc_id->is_primary ? "Primary" : "Secondary"); + BT_INFO("Charac=> UUID: [%s], Inst_id: [%u]", uuid_str2, char_id->inst_id); + + event_gattc_descriptor_result_t *event = g_new0(event_gattc_descriptor_result_t, 1); + event->conn_status.conn_id = conn_id; + event->conn_status.status = convert_to_oal_status(status); + memcpy(&(event->srvc_id), srvc_id, sizeof(oal_gatt_srvc_id_t)); + memcpy(&(event->char_id), char_id, sizeof(oal_gatt_id_t)); + + if (status == 0) { + uuid_to_stringname((oal_uuid_t *)&(descr_id->uuid), uuid_str3); + BT_INFO("Desc=> UUID: [%s], Inst_id: [%u]", uuid_str3, descr_id->inst_id); + memcpy(&(event->descr_id), descr_id, sizeof(oal_gatt_id_t)); + } + send_event(OAL_EVENT_GATTC_DESC_SERACH_RESULT, event, sizeof(*event)); } -oal_status_t gattc_start_le_discovery(void) +static void cb_gattc_register_for_notification(int client_if, int registered, int status, btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id) { - int ret; + char uuid_str1[2*BT_UUID_STRING_MAX]; + char uuid_str2[2*BT_UUID_STRING_MAX]; + BT_INFO("BTGATT Client Register For Notification Callback, client_if:%d, status:%d, registered: %s", + client_if, status, registered == 1 ? "REGISTERED" : "DEREGISTERED"); + uuid_to_stringname((oal_uuid_t *)&(srvc_id->id.uuid), uuid_str1); + uuid_to_stringname((oal_uuid_t *)&(char_id->uuid), uuid_str2); + BT_INFO("Service=> UUID: [%s], Inst_id: [%u], Type: [%s]", uuid_str1, srvc_id->id.inst_id, srvc_id->is_primary ? "Primary" : "Secondary"); + BT_INFO("Charac=> UUID: [%s], Inst_id: [%u]", uuid_str2, char_id->inst_id); + + event_gattc_regdereg_notify_t *event = g_new0(event_gattc_regdereg_notify_t, 1); + oal_event_t event_type = (registered == 1 ? OAL_EVENT_GATTC_NOTIFICATION_REGISTERED : OAL_EVENT_GATTC_NOTIFICATION_DEREGISTERED); + event->client_if = client_if; + event->status = convert_to_oal_status(status); + memcpy(&(event->srvc_id), srvc_id, sizeof(oal_gatt_srvc_id_t)); + memcpy(&(event->char_id), char_id, sizeof(oal_gatt_id_t)); - API_TRACE("BTGATT CLIENT SCAN START"); - CHECK_OAL_GATT_ENABLED(); + send_event(event_type, event, sizeof(*event)); +} - if (default_client_id < 0) { - if (pending_gattc_req != OAL_REQ_NONE) { - BT_ERR("Another request: %d already in progress", pending_gattc_req); - return OAL_STATUS_INTERNAL_ERROR; - } - pending_gattc_req = OAL_REQ_LE_SCAN; - ret = __register_default_gatt_client(); - if (OAL_STATUS_SUCCESS != ret) { - BT_ERR("__register_default_gatt_client failed"); - pending_gattc_req = OAL_REQ_NONE; - return OAL_STATUS_INTERNAL_ERROR; +static void cb_gattc_read_characteristic(int conn_id, int status, btgatt_read_params_t *p_data) +{ + char uuid_str1[2*BT_UUID_STRING_MAX]; + char uuid_str2[2*BT_UUID_STRING_MAX]; + BT_INFO("BTGATT Client Read Charcateristic Callback, conn_id:%d, read_status:%d", conn_id, status); + + event_gattc_read_data *event = g_new0(event_gattc_read_data, 1); + event->uuid_status.conn_status.conn_id = conn_id; + event->uuid_status.conn_status.status = convert_to_oal_status(status); + event->value_type = p_data->value_type; + memcpy(&(event->uuid_status.srvc_id), &(p_data->srvc_id), sizeof(oal_gatt_srvc_id_t)); + memcpy(&(event->uuid_status.char_id), &(p_data->char_id), sizeof(oal_gatt_id_t)); + if (status == 0) { + uuid_to_stringname((oal_uuid_t *)&(p_data->srvc_id.id.uuid), uuid_str1); + uuid_to_stringname((oal_uuid_t *)&(p_data->char_id.uuid), uuid_str2); + BT_INFO("Service=> UUID: [%s], Inst_id: [%u], Type: [%s]", uuid_str1, + p_data->srvc_id.id.inst_id, p_data->srvc_id.is_primary ? "Primary" : "Secondary"); + BT_INFO("Charac=> UUID: [%s], Inst_id: [%u]", uuid_str2, p_data->char_id.inst_id); + BT_INFO("Len: %u, value_type: %u", p_data->value.len, p_data->value_type); + if (p_data->value.len > 0 && event->value_type == GATTC_READ_VALUE_TYPE_VALUE) { + char *data = NULL; + data = g_malloc(3*p_data->value.len+1); + if (!data) { + BT_ERR("memory allocation failed"); + g_free(event); + return; + } + convert_hex_2_str((unsigned char *)p_data->value.value, p_data->value.len, data); + BT_INFO("Read Data: [%s]", data); + event->data_len = p_data->value.len; + memcpy(&(event->data), &(p_data->value.value), event->data_len); + g_free(data); } + } + send_event(OAL_EVENT_GATTC_READ_CHARAC, event, sizeof(*event)); +} + +static void cb_gattc_write_characteristic(int conn_id, int status, btgatt_write_params_t *p_data) +{ + char uuid_str1[2*BT_UUID_STRING_MAX]; + char uuid_str2[2*BT_UUID_STRING_MAX]; + BT_INFO("BTGATT Client Write Charcateristic Callback, conn_id:%d, write_status:%d", conn_id, status); + + event_gattc_write_data *event = g_new0(event_gattc_write_data, 1); + event->conn_status.conn_id = conn_id; + event->conn_status.status = convert_to_oal_status(status); + memcpy(&(event->srvc_id), &(p_data->srvc_id), sizeof(oal_gatt_srvc_id_t)); + memcpy(&(event->char_id), &(p_data->char_id), sizeof(oal_gatt_id_t)); + if (status == 0) { + uuid_to_stringname((oal_uuid_t *)&(p_data->srvc_id.id.uuid), uuid_str1); + uuid_to_stringname((oal_uuid_t *)&(p_data->char_id.uuid), uuid_str2); + BT_INFO("Service=> UUID: [%s], Inst_id: [%u], Type: [%s]", uuid_str1, + p_data->srvc_id.id.inst_id, p_data->srvc_id.is_primary ? "Primary" : "Secondary"); + BT_INFO("Charac=> UUID: [%s], Inst_id: [%u]", uuid_str2, p_data->char_id.inst_id); + } + send_event(OAL_EVENT_GATTC_WRITE_CHARAC, event, sizeof(*event)); +} - return OAL_STATUS_SUCCESS; +static void cb_gattc_write_descriptor(int conn_id, int status, btgatt_write_params_t *p_data) +{ + char uuid_str1[2*BT_UUID_STRING_MAX]; + char uuid_str2[2*BT_UUID_STRING_MAX]; + char uuid_str3[2*BT_UUID_STRING_MAX]; + BT_INFO("BTGATT Client Write Descriptor Callback, conn_id:%d, write_status:%d", conn_id, status); + + event_gattc_write_data *event = g_new0(event_gattc_write_data, 1); + event->conn_status.conn_id = conn_id; + event->conn_status.status = convert_to_oal_status(status); + memcpy(&(event->srvc_id), &(p_data->srvc_id), sizeof(oal_gatt_srvc_id_t)); + memcpy(&(event->char_id), &(p_data->char_id), sizeof(oal_gatt_id_t)); + memcpy(&(event->descr_id), &(p_data->descr_id), sizeof(oal_gatt_id_t)); + if (status == 0) { + uuid_to_stringname((oal_uuid_t *)&(p_data->srvc_id.id.uuid), uuid_str1); + uuid_to_stringname((oal_uuid_t *)&(p_data->char_id.uuid), uuid_str2); + uuid_to_stringname((oal_uuid_t *)&(p_data->descr_id.uuid), uuid_str3); + BT_INFO("Service=> UUID: [%s], Inst_id: [%u], Type: [%s]", uuid_str1, + p_data->srvc_id.id.inst_id, p_data->srvc_id.is_primary ? "Primary" : "Secondary"); + BT_INFO("Charac=> UUID: [%s], Inst_id: [%u]", uuid_str2, p_data->char_id.inst_id); + BT_INFO("Desc=> UUID: [%s], Inst_id: [%u]", uuid_str3, p_data->descr_id.inst_id); } + send_event(OAL_EVENT_GATTC_WRITE_DESCR, event, sizeof(*event)); +} + + + +static void cb_gattc_read_descriptor(int conn_id, int status, btgatt_read_params_t *p_data) +{ + char uuid_str1[2*BT_UUID_STRING_MAX]; + char uuid_str2[2*BT_UUID_STRING_MAX]; + char uuid_str3[2*BT_UUID_STRING_MAX]; + BT_INFO("BTGATT Client Read Descriptor Callback, conn_id:%d, read_status:%d", conn_id, status); + + event_gattc_read_data *event = g_new0(event_gattc_read_data, 1); + event->uuid_status.conn_status.conn_id = conn_id; + event->uuid_status.conn_status.status = convert_to_oal_status(status); + event->value_type = p_data->value_type; + memcpy(&(event->uuid_status.srvc_id), &(p_data->srvc_id), sizeof(oal_gatt_srvc_id_t)); + memcpy(&(event->uuid_status.char_id), &(p_data->char_id), sizeof(oal_gatt_id_t)); + memcpy(&(event->uuid_status.descr_id), &(p_data->descr_id), sizeof(oal_gatt_id_t)); + + if (status == 0) { + uuid_to_stringname((oal_uuid_t *)&(p_data->srvc_id.id.uuid), uuid_str1); + uuid_to_stringname((oal_uuid_t *)&(p_data->char_id.uuid), uuid_str2); + uuid_to_stringname((oal_uuid_t *)&(p_data->descr_id.uuid), uuid_str3); + BT_INFO("Service=> UUID: [%s], Inst_id: [%u], Type: [%s]", uuid_str1, + p_data->srvc_id.id.inst_id, p_data->srvc_id.is_primary ? "Primary" : "Secondary"); + BT_INFO("Charac=> UUID: [%s], Inst_id: [%u]", uuid_str2, p_data->char_id.inst_id); + BT_INFO("Desc=> UUID: [%s], Inst_id: [%u]", uuid_str3, p_data->descr_id.inst_id); + BT_INFO("Len: %u, value_type: %u", p_data->value.len, p_data->value_type); + if (p_data->value.len > 0 && event->value_type == GATTC_READ_VALUE_TYPE_VALUE) { + char *data = NULL; + data = g_malloc(3*p_data->value.len+1); + if (!data) { + BT_ERR("memory allocation failed"); + g_free(event); + return; + } + convert_hex_2_str((unsigned char *)p_data->value.value, p_data->value.len, data); + BT_INFO("Read Data: [%s]", data); + event->data_len = p_data->value.len; + memcpy(&(event->data), &(p_data->value.value), event->data_len); + g_free(data); + } + } + send_event(OAL_EVENT_GATTC_READ_DESCR, event, sizeof(*event)); +} + +oal_status_t gattc_start_le_discovery(int client_id) +{ + + int ret = OAL_STATUS_SUCCESS; + + API_TRACE("BTGATT CLIENT SCAN START"); + CHECK_OAL_GATT_ENABLED(); + CHECK_CLIENT_REGISTRATION(client_id); - ret = gatt_api->client->scan(default_client_id, true); + ret = gatt_api->client->scan(client_id, 1); if (ret != BT_STATUS_SUCCESS) { BT_ERR("Error:Start LE Discovery failed: %s", status2string(ret)); return convert_to_oal_status(ret); } - send_event(OAL_EVENT_BLE_DISCOVERY_STARTED, NULL, 0); return OAL_STATUS_SUCCESS; } -oal_status_t gattc_stop_le_discovery(void) +oal_status_t gattc_stop_le_discovery(int client_id) { - int ret; + + int ret = OAL_STATUS_SUCCESS; API_TRACE("Scan is stopped"); CHECK_OAL_GATT_ENABLED(); - - ret = gatt_api->client->scan(default_client_id, false); + CHECK_CLIENT_REGISTRATION(client_id); + ret = gatt_api->client->scan(client_id, 0); if (ret != BT_STATUS_SUCCESS) { BT_ERR("Error:Stop LE Discovery failed: %s", status2string(ret)); return convert_to_oal_status(ret); - } - - send_event(OAL_EVENT_BLE_DISCOVERY_STOPPED, NULL, 0); + } else + send_event(OAL_EVENT_BLE_DISCOVERY_STOPPED, NULL, 0); return OAL_STATUS_SUCCESS; } @@ -1433,3 +1671,321 @@ oal_status_t gattc_set_le_scan_param(int scan_type, int itv, int win) return OAL_STATUS_SUCCESS; } /************************************ GATT Client ***********************************/ +oal_status_t gattc_register(oal_uuid_t* client_uuid) +{ + + char str[2*BT_UUID_STRING_MAX]; + int ret = OAL_STATUS_SUCCESS; + + CHECK_OAL_GATT_ENABLED(); + uuid_to_stringname(client_uuid, str); + API_TRACE("uuid: [%s]", str); + /* We will perform actual registration in cb_gattc_register_app callback */ + ret = gatt_api->client->register_client((bt_uuid_t *)client_uuid); + if (ret != BT_STATUS_SUCCESS) { + BT_ERR("GATT client register failed: %s", status2string(ret)); + return convert_to_oal_status(ret); + } + return OAL_STATUS_SUCCESS; +} + +oal_status_t gattc_deregister(int client_id) +{ + int ret = OAL_STATUS_SUCCESS; + + API_TRACE("GATT client deregister"); + CHECK_OAL_GATT_ENABLED(); + CHECK_CLIENT_REGISTRATION(client_id); + + ret = gatt_api->client->unregister_client(client_id); + if (ret != BT_STATUS_SUCCESS) { + BT_ERR("GATT client deregister failed: %s", status2string(ret)); + return convert_to_oal_status(ret); + } + + return OAL_STATUS_SUCCESS; +} + +oal_status_t gattc_connect(int client_id, bt_address_t *device_address, int isDirect) +{ + int ret = OAL_STATUS_SUCCESS; + bdstr_t bdstr; + + OAL_CHECK_PARAMETER(device_address, return); + API_TRACE("Client Connect: [%s]", bdt_bd2str(device_address, &bdstr)); + CHECK_OAL_GATT_ENABLED(); + CHECK_CLIENT_REGISTRATION(client_id); + + /* Handle the actual connection in cb_gattc_connection callback */ + ret = gatt_api->client->connect(client_id, (bt_bdaddr_t *)device_address, isDirect); + if (ret != BT_STATUS_SUCCESS) { + BT_ERR("GATT client connect failed: %s", status2string(ret)); + return convert_to_oal_status(ret); + } + return OAL_STATUS_SUCCESS; +} + +oal_status_t gattc_disconnect(int client_id, bt_address_t *device_address, int conn_id) +{ + + int ret = OAL_STATUS_SUCCESS; + bdstr_t bdstr; + + OAL_CHECK_PARAMETER(device_address, return); + API_TRACE("Client Disconnect: [%s]", bdt_bd2str(device_address, &bdstr)); + CHECK_OAL_GATT_ENABLED(); + CHECK_CLIENT_REGISTRATION(client_id); + CHECK_CLIENT_CONNECTION(conn_id); + + /* Handle actual disconnection in callback */ + ret = gatt_api->client->disconnect(client_id, (bt_bdaddr_t *) device_address, conn_id); + if (ret != BT_STATUS_SUCCESS) { + BT_ERR("GATT client disconnect failed: %s", status2string(ret)); + return convert_to_oal_status(ret); + } + return OAL_STATUS_SUCCESS; +} + + +oal_status_t gattc_search_service(int conn_id, oal_uuid_t *service_uuid) +{ + int ret = OAL_STATUS_SUCCESS; + char uuid_str[2*BT_UUID_STRING_MAX]; + + if (service_uuid) { + uuid_to_stringname(service_uuid, uuid_str); + API_TRACE("Client Service Search UUID: [%s]", uuid_str); + } else + API_TRACE("Client Service Search All"); + + CHECK_OAL_GATT_ENABLED(); + CHECK_CLIENT_CONNECTION(conn_id); + ret = gatt_api->client->search_service(conn_id, (bt_uuid_t *)service_uuid); + + if (ret != BT_STATUS_SUCCESS) { + BT_ERR("GATT client service search failed: %s", status2string(ret)); + return convert_to_oal_status(ret); + } + return OAL_STATUS_SUCCESS; +} + +oal_status_t gattc_get_characteristic(int conn_id, oal_gatt_srvc_id_t *srvc_id, oal_gatt_id_t *char_id) +{ + int ret = OAL_STATUS_SUCCESS; + char uuid_str[2*BT_UUID_STRING_MAX]; + + OAL_CHECK_PARAMETER(srvc_id, return); + uuid_to_stringname(&(srvc_id->id.uuid), uuid_str); + API_TRACE("Client Get Characteristic, Service_uuid: [%s]", uuid_str); + CHECK_OAL_GATT_ENABLED(); + CHECK_CLIENT_CONNECTION(conn_id); + ret = gatt_api->client->get_characteristic(conn_id, (btgatt_srvc_id_t *)srvc_id, + (btgatt_gatt_id_t *)char_id); + if (ret != BT_STATUS_SUCCESS) { + BT_ERR("GATT client get characteristic failed: %s", status2string(ret)); + return convert_to_oal_status(ret); + } + return OAL_STATUS_SUCCESS; +} + +oal_status_t gattc_get_descriptor(int conn_id, oal_gatt_srvc_id_t *srvc_id, + oal_gatt_id_t *char_id, oal_gatt_id_t *desc_id) +{ + int ret = OAL_STATUS_SUCCESS; + char uuid_str1[2*BT_UUID_STRING_MAX]; + char uuid_str2[2*BT_UUID_STRING_MAX]; + + OAL_CHECK_PARAMETER(srvc_id, return); + OAL_CHECK_PARAMETER(char_id, return); + uuid_to_stringname(&(srvc_id->id.uuid), uuid_str1); + uuid_to_stringname(&(char_id->uuid), uuid_str2); + API_TRACE("Client Get Descriptor, Service_uuid: [%s], Char_uuid: [%s]", uuid_str1, uuid_str2); + CHECK_OAL_GATT_ENABLED(); + CHECK_CLIENT_CONNECTION(conn_id); + ret = gatt_api->client->get_descriptor(conn_id, (btgatt_srvc_id_t *)srvc_id, + (btgatt_gatt_id_t *)char_id, (btgatt_gatt_id_t *)desc_id); + if (ret != BT_STATUS_SUCCESS) { + BT_ERR("GATT client get descriptor failed: %s", status2string(ret)); + return convert_to_oal_status(ret); + } + return OAL_STATUS_SUCCESS; +} + +oal_status_t gattc_register_for_notification(int client_id, bt_address_t * address, + oal_gatt_srvc_id_t *srvc_id, oal_gatt_id_t *char_id) { + int ret = OAL_STATUS_SUCCESS; + char uuid_str1[2*BT_UUID_STRING_MAX]; + char uuid_str2[2*BT_UUID_STRING_MAX]; + bdstr_t bdstr; + + OAL_CHECK_PARAMETER(address, return); + OAL_CHECK_PARAMETER(srvc_id, return); + OAL_CHECK_PARAMETER(char_id, return); + uuid_to_stringname(&(srvc_id->id.uuid), uuid_str1); + uuid_to_stringname(&(char_id->uuid), uuid_str2); + API_TRACE("Client Register Notification: [%s], Service_uuid: [%s], Char_uuid: [%s]", bdt_bd2str(address, &bdstr), uuid_str1, uuid_str2); + CHECK_OAL_GATT_ENABLED(); + CHECK_CLIENT_REGISTRATION(client_id); + + ret = gatt_api->client->register_for_notification(client_id, (bt_bdaddr_t *)address, (btgatt_srvc_id_t *)srvc_id, (btgatt_gatt_id_t *)char_id); + if (ret != BT_STATUS_SUCCESS) { + BT_ERR("GATT client register notification failed: %s", status2string(ret)); + return convert_to_oal_status(ret); + } + + return OAL_STATUS_SUCCESS; +} + +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) { + int ret = OAL_STATUS_SUCCESS; + char uuid_str1[2*BT_UUID_STRING_MAX]; + char uuid_str2[2*BT_UUID_STRING_MAX]; + bdstr_t bdstr; + + OAL_CHECK_PARAMETER(address, return); + OAL_CHECK_PARAMETER(srvc_id, return); + OAL_CHECK_PARAMETER(char_id, return); + uuid_to_stringname(&(srvc_id->id.uuid), uuid_str1); + uuid_to_stringname(&(char_id->uuid), uuid_str2); + API_TRACE("Client Deregister Notification: [%s], Service_uuid: [%s], Char_uuid: [%s]", bdt_bd2str(address, &bdstr), uuid_str1, uuid_str2); + CHECK_OAL_GATT_ENABLED(); + CHECK_CLIENT_REGISTRATION(client_id); + + ret = gatt_api->client->deregister_for_notification(client_id, (bt_bdaddr_t *)address, (btgatt_srvc_id_t *)srvc_id, (btgatt_gatt_id_t *)char_id); + if (ret != BT_STATUS_SUCCESS) { + BT_ERR("GATT client deregister notification failed: %s", status2string(ret)); + return convert_to_oal_status(ret); + } + + return OAL_STATUS_SUCCESS; +} + + +oal_status_t gattc_read_characteristic(int conn_id, oal_gatt_srvc_id_t *srvc_id, + oal_gatt_id_t *char_id, oal_gatt_auth_req_t auth_req) +{ + int ret = OAL_STATUS_SUCCESS; + char uuid_str1[2*BT_UUID_STRING_MAX]; + char uuid_str2[2*BT_UUID_STRING_MAX]; + + OAL_CHECK_PARAMETER(srvc_id, return); + OAL_CHECK_PARAMETER(char_id, return); + uuid_to_stringname(&(srvc_id->id.uuid), uuid_str1); + uuid_to_stringname(&(char_id->uuid), uuid_str2); + API_TRACE("Client Read Characteristic: Service_uuid: [%s], Char_uuid: [%s]", uuid_str1, uuid_str2); + CHECK_OAL_GATT_ENABLED(); + CHECK_CLIENT_CONNECTION(conn_id); + + ret = gatt_api->client->read_characteristic(conn_id, (btgatt_srvc_id_t *)srvc_id, + (btgatt_gatt_id_t *)char_id, auth_req); + if (ret != BT_STATUS_SUCCESS) { + BT_ERR("GATT client read characteristic failed: %s", status2string(ret)); + return convert_to_oal_status(ret); + } + + return OAL_STATUS_SUCCESS; +} + +oal_status_t gattc_read_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_auth_req_t auth_req) +{ + int ret = OAL_STATUS_SUCCESS; + char uuid_str1[2*BT_UUID_STRING_MAX]; + char uuid_str2[2*BT_UUID_STRING_MAX]; + char uuid_str3[2*BT_UUID_STRING_MAX]; + + OAL_CHECK_PARAMETER(srvc_id, return); + OAL_CHECK_PARAMETER(char_id, return); + OAL_CHECK_PARAMETER(desc_id, return); + uuid_to_stringname(&(srvc_id->id.uuid), uuid_str1); + uuid_to_stringname(&(char_id->uuid), uuid_str2); + uuid_to_stringname(&(desc_id->uuid), uuid_str3); + API_TRACE("Client Read Descriptor: Service_uuid: [%s], Char_uuid: [%s], Desc_uuid: [%s]", + uuid_str1, uuid_str2, uuid_str3); + CHECK_OAL_GATT_ENABLED(); + CHECK_CLIENT_CONNECTION(conn_id); + + ret = gatt_api->client->read_descriptor(conn_id, (btgatt_srvc_id_t *)srvc_id, + (btgatt_gatt_id_t *)char_id, (btgatt_gatt_id_t *)desc_id, auth_req); + if (ret != BT_STATUS_SUCCESS) { + BT_ERR("GATT client read descriptor failed: %s", status2string(ret)); + return convert_to_oal_status(ret); + } + + return OAL_STATUS_SUCCESS; +} + +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) +{ + int ret = OAL_STATUS_SUCCESS; + char uuid_str1[2*BT_UUID_STRING_MAX]; + char uuid_str2[2*BT_UUID_STRING_MAX]; + OAL_CHECK_PARAMETER(srvc_id, return); + OAL_CHECK_PARAMETER(char_id, return); + OAL_CHECK_PARAMETER(data, return); + uuid_to_stringname(&(srvc_id->id.uuid), uuid_str1); + uuid_to_stringname(&(char_id->uuid), uuid_str2); + API_TRACE("Client Write Characteristic: Service_uuid: [%s], Char_uuid: [%s]", uuid_str1, uuid_str2); + CHECK_OAL_GATT_ENABLED(); + CHECK_CLIENT_CONNECTION(conn_id); + + ret = gatt_api->client->write_characteristic(conn_id, (btgatt_srvc_id_t *)srvc_id, + (btgatt_gatt_id_t *)char_id, write_type, len, auth_req, data); + if (ret != BT_STATUS_SUCCESS) { + BT_ERR("GATT client write characteristic failed: %s", status2string(ret)); + return convert_to_oal_status(ret); + } + + return OAL_STATUS_SUCCESS; +} + +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) +{ + int ret = OAL_STATUS_SUCCESS; + char uuid_str1[2*BT_UUID_STRING_MAX]; + char uuid_str2[2*BT_UUID_STRING_MAX]; + char uuid_str3[2*BT_UUID_STRING_MAX]; + OAL_CHECK_PARAMETER(srvc_id, return); + OAL_CHECK_PARAMETER(char_id, return); + OAL_CHECK_PARAMETER(desc_id, return); + OAL_CHECK_PARAMETER(data, return); + uuid_to_stringname(&(srvc_id->id.uuid), uuid_str1); + uuid_to_stringname(&(char_id->uuid), uuid_str2); + uuid_to_stringname(&(desc_id->uuid), uuid_str3); + API_TRACE("Client Write Descriptor: Service_uuid: [%s], Char_uuid: [%s], Desc_uuid: [%s]", + uuid_str1, uuid_str2, uuid_str3); + CHECK_OAL_GATT_ENABLED(); + CHECK_CLIENT_CONNECTION(conn_id); + + ret = gatt_api->client->write_descriptor(conn_id, (btgatt_srvc_id_t *)srvc_id, + (btgatt_gatt_id_t *)char_id, (btgatt_gatt_id_t *)desc_id, write_type, len, auth_req, data); + if (ret != BT_STATUS_SUCCESS) { + BT_ERR("GATT client write characteristic failed: %s", status2string(ret)); + return convert_to_oal_status(ret); + } + + return OAL_STATUS_SUCCESS; +} + +oal_status_t gattc_conn_param_update(bt_address_t * address, int min, int max, int latency, int timeout) +{ + int ret; + bdstr_t bdstr; + + OAL_CHECK_PARAMETER(address, return); + API_TRACE("Conn Param Update: [%s]", bdt_bd2str(address, &bdstr)); + CHECK_OAL_GATT_ENABLED(); + + BT_INFO("[%s] min[%d] max[%d] latency[%d] timeout[%d]", bdt_bd2str(address, &bdstr), min, max, latency, timeout); + ret = gatt_api->client->conn_parameter_update((bt_bdaddr_t *)address, min, max, latency, timeout); + if (ret != BT_STATUS_SUCCESS) { + BT_ERR("error: %s", status2string(ret)); + return convert_to_oal_status(ret); + } + return OAL_STATUS_SUCCESS; +}