/****************************************************************************** * * Copyright 2010-2012 Broadcom Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ******************************************************************************/ /****************************************************************************** * * This is the implementation of the API for GATT module of BTA. * ******************************************************************************/ #include "bt_target.h" #include <string.h> #include <base/bind.h> #include <base/bind_helpers.h> #include <base/callback.h> #include "bt_common.h" #include "bta_gatt_api.h" #include "bta_gattc_int.h" #include "bta_sys.h" #include "device/include/controller.h" #include "stack/include/btu.h" using bluetooth::Uuid; /***************************************************************************** * Constants ****************************************************************************/ static const tBTA_SYS_REG bta_gattc_reg = {bta_gattc_hdl_event, BTA_GATTC_Disable}; /******************************************************************************* * * Function BTA_GATTC_Disable * * Description This function is called to disable GATTC module * * Parameters None. * * Returns None * ******************************************************************************/ void BTA_GATTC_Disable(void) { if (!bta_sys_is_register(BTA_ID_GATTC)) { LOG(WARNING) << "GATTC Module not enabled/already disabled"; return; } do_in_main_thread(FROM_HERE, base::Bind(&bta_gattc_disable)); bta_sys_deregister(BTA_ID_GATTC); } /** * This function is called to register application callbacks with BTA GATTC * module. |client_cb| pointer to the application callback function. * |cb| one time callback when registration is finished */ void BTA_GATTC_AppRegister(tBTA_GATTC_CBACK* p_client_cb, BtaAppRegisterCallback cb) { if (!bta_sys_is_register(BTA_ID_GATTC)) bta_sys_register(BTA_ID_GATTC, &bta_gattc_reg); do_in_main_thread( FROM_HERE, base::Bind(&bta_gattc_register, Uuid::GetRandom(), p_client_cb, std::move(cb))); } static void app_deregister_impl(tGATT_IF client_if) { bta_gattc_deregister(bta_gattc_cl_get_regcb(client_if)); } /******************************************************************************* * * Function BTA_GATTC_AppDeregister * * Description This function is called to deregister an application * from BTA GATTC module. * * Parameters client_if - client interface identifier. * * Returns None * ******************************************************************************/ void BTA_GATTC_AppDeregister(tGATT_IF client_if) { do_in_main_thread(FROM_HERE, base::Bind(&app_deregister_impl, client_if)); } /******************************************************************************* * * Function BTA_GATTC_Open * * Description Open a direct connection or add a background auto connection * bd address * * Parameters client_if: server interface. * remote_bda: remote device BD address. * is_direct: direct connection or background auto connection * transport: Transport to be used for GATT connection * (BREDR/LE) * initiating_phys: LE PHY to use, optional * opportunistic: wether the connection shall be opportunistic, * and don't impact the disconnection timer * ******************************************************************************/ void BTA_GATTC_Open(tGATT_IF client_if, const RawAddress& remote_bda, bool is_direct, tGATT_TRANSPORT transport, bool opportunistic) { uint8_t phy = controller_get_interface()->get_le_all_initiating_phys(); BTA_GATTC_Open(client_if, remote_bda, is_direct, transport, opportunistic, phy); } void BTA_GATTC_Open(tGATT_IF client_if, const RawAddress& remote_bda, bool is_direct, tGATT_TRANSPORT transport, bool opportunistic, uint8_t initiating_phys) { tBTA_GATTC_API_OPEN* p_buf = (tBTA_GATTC_API_OPEN*)osi_malloc(sizeof(tBTA_GATTC_API_OPEN)); p_buf->hdr.event = BTA_GATTC_API_OPEN_EVT; p_buf->client_if = client_if; p_buf->is_direct = is_direct; p_buf->transport = transport; p_buf->initiating_phys = initiating_phys; p_buf->opportunistic = opportunistic; p_buf->remote_bda = remote_bda; bta_sys_sendmsg(p_buf); } /******************************************************************************* * * Function BTA_GATTC_CancelOpen * * Description Cancel a direct open connection or remove a background auto * connection * bd address * * Parameters client_if: server interface. * remote_bda: remote device BD address. * is_direct: direct connection or background auto connection * * Returns void * ******************************************************************************/ void BTA_GATTC_CancelOpen(tGATT_IF client_if, const RawAddress& remote_bda, bool is_direct) { tBTA_GATTC_API_CANCEL_OPEN* p_buf = (tBTA_GATTC_API_CANCEL_OPEN*)osi_malloc( sizeof(tBTA_GATTC_API_CANCEL_OPEN)); p_buf->hdr.event = BTA_GATTC_API_CANCEL_OPEN_EVT; p_buf->client_if = client_if; p_buf->is_direct = is_direct; p_buf->remote_bda = remote_bda; bta_sys_sendmsg(p_buf); } /******************************************************************************* * * Function BTA_GATTC_Close * * Description Close a connection to a GATT server. * * Parameters conn_id: connectino ID to be closed. * * Returns void * ******************************************************************************/ void BTA_GATTC_Close(uint16_t conn_id) { BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR)); p_buf->event = BTA_GATTC_API_CLOSE_EVT; p_buf->layer_specific = conn_id; bta_sys_sendmsg(p_buf); } /******************************************************************************* * * Function BTA_GATTC_ConfigureMTU * * Description Configure the MTU size in the GATT channel. This can be done * only once per connection. * * Parameters conn_id: connection ID. * mtu: desired MTU size to use. * * Returns void * ******************************************************************************/ void BTA_GATTC_ConfigureMTU(uint16_t conn_id, uint16_t mtu) { tBTA_GATTC_API_CFG_MTU* p_buf = (tBTA_GATTC_API_CFG_MTU*)osi_malloc(sizeof(tBTA_GATTC_API_CFG_MTU)); p_buf->hdr.event = BTA_GATTC_API_CFG_MTU_EVT; p_buf->hdr.layer_specific = conn_id; p_buf->mtu = mtu; bta_sys_sendmsg(p_buf); } /******************************************************************************* * * Function BTA_GATTC_ServiceSearchRequest * * Description This function is called to request a GATT service discovery * on a GATT server. This function report service search * result by a callback event, and followed by a service search * complete event. * * Parameters conn_id: connection ID. * p_srvc_uuid: a UUID of the service application is interested * in. * If Null, discover for all services. * * Returns None * ******************************************************************************/ void BTA_GATTC_ServiceSearchRequest(uint16_t conn_id, Uuid* p_srvc_uuid) { const size_t len = sizeof(tBTA_GATTC_API_SEARCH) + sizeof(Uuid); tBTA_GATTC_API_SEARCH* p_buf = (tBTA_GATTC_API_SEARCH*)osi_calloc(len); p_buf->hdr.event = BTA_GATTC_API_SEARCH_EVT; p_buf->hdr.layer_specific = conn_id; if (p_srvc_uuid) { p_buf->p_srvc_uuid = (Uuid*)(p_buf + 1); *p_buf->p_srvc_uuid = *p_srvc_uuid; } else { p_buf->p_srvc_uuid = NULL; } bta_sys_sendmsg(p_buf); } void BTA_GATTC_DiscoverServiceByUuid(uint16_t conn_id, const Uuid& srvc_uuid) { do_in_main_thread( FROM_HERE, base::Bind( base::IgnoreResult<tGATT_STATUS (*)(uint16_t, tGATT_DISC_TYPE, uint16_t, uint16_t, const Uuid&)>( &GATTC_Discover), conn_id, GATT_DISC_SRVC_BY_UUID, 0x0001, 0xFFFF, srvc_uuid)); } /******************************************************************************* * * Function BTA_GATTC_GetServices * * Description This function is called to find the services on the given * server. * * Parameters conn_id: connection ID which identify the server. * * Returns returns list of gatt::Service or NULL. * ******************************************************************************/ const std::list<gatt::Service>* BTA_GATTC_GetServices(uint16_t conn_id) { return bta_gattc_get_services(conn_id); } /******************************************************************************* * * Function BTA_GATTC_GetCharacteristic * * Description This function is called to find the characteristic on the * given server. * * Parameters conn_id - connection ID which identify the server. * handle - characteristic handle * * Returns returns pointer to gatt::Characteristic or NULL. * ******************************************************************************/ const gatt::Characteristic* BTA_GATTC_GetCharacteristic(uint16_t conn_id, uint16_t handle) { return bta_gattc_get_characteristic(conn_id, handle); } /******************************************************************************* * * Function BTA_GATTC_GetDescriptor * * Description This function is called to find the characteristic on the * given server. * * Parameters conn_id - connection ID which identify the server. * handle - descriptor handle * * Returns returns pointer to gatt::Descriptor or NULL. * ******************************************************************************/ const gatt::Descriptor* BTA_GATTC_GetDescriptor(uint16_t conn_id, uint16_t handle) { return bta_gattc_get_descriptor(conn_id, handle); } /* Return characteristic that owns descriptor with handle equal to |handle|, or * NULL */ const gatt::Characteristic* BTA_GATTC_GetOwningCharacteristic(uint16_t conn_id, uint16_t handle) { return bta_gattc_get_owning_characteristic(conn_id, handle); } /* Return service that owns descriptor or characteristic with handle equal to * |handle|, or NULL */ const gatt::Service* BTA_GATTC_GetOwningService(uint16_t conn_id, uint16_t handle) { return bta_gattc_get_service_for_handle(conn_id, handle); } /******************************************************************************* * * Function BTA_GATTC_GetGattDb * * Description This function is called to get the GATT database. * * Parameters conn_id: connection ID which identify the server. * db: output parameter which will contain the GATT database * copy. Caller is responsible for freeing it. * count: number of elements in database. * ******************************************************************************/ void BTA_GATTC_GetGattDb(uint16_t conn_id, uint16_t start_handle, uint16_t end_handle, btgatt_db_element_t** db, int* count) { bta_gattc_get_gatt_db(conn_id, start_handle, end_handle, db, count); } /******************************************************************************* * * Function BTA_GATTC_ReadCharacteristic * * Description This function is called to read a characteristics value * * Parameters conn_id - connection ID. * handle - characteritic handle to read. * * Returns None * ******************************************************************************/ void BTA_GATTC_ReadCharacteristic(uint16_t conn_id, uint16_t handle, tGATT_AUTH_REQ auth_req, GATT_READ_OP_CB callback, void* cb_data) { tBTA_GATTC_API_READ* p_buf = (tBTA_GATTC_API_READ*)osi_calloc(sizeof(tBTA_GATTC_API_READ)); p_buf->hdr.event = BTA_GATTC_API_READ_EVT; p_buf->hdr.layer_specific = conn_id; p_buf->auth_req = auth_req; p_buf->handle = handle; p_buf->read_cb = callback; p_buf->read_cb_data = cb_data; bta_sys_sendmsg(p_buf); } /** * This function is called to read a value of characteristic with uuid equal to * |uuid| */ void BTA_GATTC_ReadUsingCharUuid(uint16_t conn_id, const Uuid& uuid, uint16_t s_handle, uint16_t e_handle, tGATT_AUTH_REQ auth_req, GATT_READ_OP_CB callback, void* cb_data) { tBTA_GATTC_API_READ* p_buf = (tBTA_GATTC_API_READ*)osi_calloc(sizeof(tBTA_GATTC_API_READ)); p_buf->hdr.event = BTA_GATTC_API_READ_EVT; p_buf->hdr.layer_specific = conn_id; p_buf->auth_req = auth_req; p_buf->handle = 0; p_buf->uuid = uuid; p_buf->s_handle = s_handle; p_buf->e_handle = e_handle; p_buf->read_cb = callback; p_buf->read_cb_data = cb_data; bta_sys_sendmsg(p_buf); } /******************************************************************************* * * Function BTA_GATTC_ReadCharDescr * * Description This function is called to read a descriptor value. * * Parameters conn_id - connection ID. * handle - descriptor handle to read. * * Returns None * ******************************************************************************/ void BTA_GATTC_ReadCharDescr(uint16_t conn_id, uint16_t handle, tGATT_AUTH_REQ auth_req, GATT_READ_OP_CB callback, void* cb_data) { tBTA_GATTC_API_READ* p_buf = (tBTA_GATTC_API_READ*)osi_calloc(sizeof(tBTA_GATTC_API_READ)); p_buf->hdr.event = BTA_GATTC_API_READ_EVT; p_buf->hdr.layer_specific = conn_id; p_buf->auth_req = auth_req; p_buf->handle = handle; p_buf->read_cb = callback; p_buf->read_cb_data = cb_data; bta_sys_sendmsg(p_buf); } /******************************************************************************* * * Function BTA_GATTC_ReadMultiple * * Description This function is called to read multiple characteristic or * characteristic descriptors. * * Parameters conn_id - connectino ID. * p_read_multi - pointer to the read multiple parameter. * * Returns None * ******************************************************************************/ void BTA_GATTC_ReadMultiple(uint16_t conn_id, tBTA_GATTC_MULTI* p_read_multi, tGATT_AUTH_REQ auth_req) { tBTA_GATTC_API_READ_MULTI* p_buf = (tBTA_GATTC_API_READ_MULTI*)osi_calloc(sizeof(tBTA_GATTC_API_READ_MULTI)); p_buf->hdr.event = BTA_GATTC_API_READ_MULTI_EVT; p_buf->hdr.layer_specific = conn_id; p_buf->auth_req = auth_req; p_buf->num_attr = p_read_multi->num_attr; if (p_buf->num_attr > 0) memcpy(p_buf->handles, p_read_multi->handles, sizeof(uint16_t) * p_read_multi->num_attr); bta_sys_sendmsg(p_buf); } /******************************************************************************* * * Function BTA_GATTC_WriteCharValue * * Description This function is called to write characteristic value. * * Parameters conn_id - connection ID. * handle - characteristic handle to write. * write_type - type of write. * value - the value to be written. * * Returns None * ******************************************************************************/ void BTA_GATTC_WriteCharValue(uint16_t conn_id, uint16_t handle, tGATT_WRITE_TYPE write_type, std::vector<uint8_t> value, tGATT_AUTH_REQ auth_req, GATT_WRITE_OP_CB callback, void* cb_data) { tBTA_GATTC_API_WRITE* p_buf = (tBTA_GATTC_API_WRITE*)osi_calloc( sizeof(tBTA_GATTC_API_WRITE) + value.size()); p_buf->hdr.event = BTA_GATTC_API_WRITE_EVT; p_buf->hdr.layer_specific = conn_id; p_buf->auth_req = auth_req; p_buf->handle = handle; p_buf->write_type = write_type; p_buf->len = value.size(); p_buf->write_cb = callback; p_buf->write_cb_data = cb_data; if (value.size() > 0) { p_buf->p_value = (uint8_t*)(p_buf + 1); memcpy(p_buf->p_value, value.data(), value.size()); } bta_sys_sendmsg(p_buf); } /******************************************************************************* * * Function BTA_GATTC_WriteCharDescr * * Description This function is called to write descriptor value. * * Parameters conn_id - connection ID * handle - descriptor hadle to write. * value - the value to be written. * * Returns None * ******************************************************************************/ void BTA_GATTC_WriteCharDescr(uint16_t conn_id, uint16_t handle, std::vector<uint8_t> value, tGATT_AUTH_REQ auth_req, GATT_WRITE_OP_CB callback, void* cb_data) { tBTA_GATTC_API_WRITE* p_buf = (tBTA_GATTC_API_WRITE*)osi_calloc( sizeof(tBTA_GATTC_API_WRITE) + value.size()); p_buf->hdr.event = BTA_GATTC_API_WRITE_EVT; p_buf->hdr.layer_specific = conn_id; p_buf->auth_req = auth_req; p_buf->handle = handle; p_buf->write_type = GATT_WRITE; p_buf->write_cb = callback; p_buf->write_cb_data = cb_data; if (value.size() != 0) { p_buf->p_value = (uint8_t*)(p_buf + 1); p_buf->len = value.size(); memcpy(p_buf->p_value, value.data(), value.size()); } bta_sys_sendmsg(p_buf); } /******************************************************************************* * * Function BTA_GATTC_PrepareWrite * * Description This function is called to prepare write a characteristic * value. * * Parameters conn_id - connection ID. * p_char_id - GATT characteritic ID of the service. * offset - offset of the write value. * value - the value to be written. * * Returns None * ******************************************************************************/ void BTA_GATTC_PrepareWrite(uint16_t conn_id, uint16_t handle, uint16_t offset, std::vector<uint8_t> value, tGATT_AUTH_REQ auth_req, GATT_WRITE_OP_CB callback, void* cb_data) { tBTA_GATTC_API_WRITE* p_buf = (tBTA_GATTC_API_WRITE*)osi_calloc( sizeof(tBTA_GATTC_API_WRITE) + value.size()); p_buf->hdr.event = BTA_GATTC_API_WRITE_EVT; p_buf->hdr.layer_specific = conn_id; p_buf->auth_req = auth_req; p_buf->handle = handle; p_buf->write_cb = callback; p_buf->write_cb_data = cb_data; p_buf->write_type = BTA_GATTC_WRITE_PREPARE; p_buf->offset = offset; p_buf->len = value.size(); if (value.size() > 0) { p_buf->p_value = (uint8_t*)(p_buf + 1); memcpy(p_buf->p_value, value.data(), value.size()); } bta_sys_sendmsg(p_buf); } /******************************************************************************* * * Function BTA_GATTC_ExecuteWrite * * Description This function is called to execute write a prepare write * sequence. * * Parameters conn_id - connection ID. * is_execute - execute or cancel. * * Returns None * ******************************************************************************/ void BTA_GATTC_ExecuteWrite(uint16_t conn_id, bool is_execute) { tBTA_GATTC_API_EXEC* p_buf = (tBTA_GATTC_API_EXEC*)osi_calloc(sizeof(tBTA_GATTC_API_EXEC)); p_buf->hdr.event = BTA_GATTC_API_EXEC_EVT; p_buf->hdr.layer_specific = conn_id; p_buf->is_execute = is_execute; bta_sys_sendmsg(p_buf); } /******************************************************************************* * * Function BTA_GATTC_SendIndConfirm * * Description This function is called to send handle value confirmation. * * Parameters conn_id - connection ID. * p_char_id - characteristic ID to confirm. * * Returns None * ******************************************************************************/ void BTA_GATTC_SendIndConfirm(uint16_t conn_id, uint16_t handle) { tBTA_GATTC_API_CONFIRM* p_buf = (tBTA_GATTC_API_CONFIRM*)osi_calloc(sizeof(tBTA_GATTC_API_CONFIRM)); VLOG(1) << __func__ << ": conn_id=" << +conn_id << " handle=0x" << std::hex << +handle; p_buf->hdr.event = BTA_GATTC_API_CONFIRM_EVT; p_buf->hdr.layer_specific = conn_id; p_buf->handle = handle; bta_sys_sendmsg(p_buf); } /******************************************************************************* * * Function BTA_GATTC_RegisterForNotifications * * Description This function is called to register for notification of a * service. * * Parameters client_if - client interface. * bda - target GATT server. * handle - GATT characteristic handle. * * Returns OK if registration succeed, otherwise failed. * ******************************************************************************/ tGATT_STATUS BTA_GATTC_RegisterForNotifications(tGATT_IF client_if, const RawAddress& bda, uint16_t handle) { tBTA_GATTC_RCB* p_clreg; tGATT_STATUS status = GATT_ILLEGAL_PARAMETER; uint8_t i; if (!handle) { LOG(ERROR) << __func__ << ": registration failed, handle is 0"; return status; } p_clreg = bta_gattc_cl_get_regcb(client_if); if (p_clreg != NULL) { for (i = 0; i < BTA_GATTC_NOTIF_REG_MAX; i++) { if (p_clreg->notif_reg[i].in_use && p_clreg->notif_reg[i].remote_bda == bda && p_clreg->notif_reg[i].handle == handle) { LOG(WARNING) << "notification already registered"; status = GATT_SUCCESS; break; } } if (status != GATT_SUCCESS) { for (i = 0; i < BTA_GATTC_NOTIF_REG_MAX; i++) { if (!p_clreg->notif_reg[i].in_use) { memset((void*)&p_clreg->notif_reg[i], 0, sizeof(tBTA_GATTC_NOTIF_REG)); p_clreg->notif_reg[i].in_use = true; p_clreg->notif_reg[i].remote_bda = bda; p_clreg->notif_reg[i].handle = handle; status = GATT_SUCCESS; break; } } if (i == BTA_GATTC_NOTIF_REG_MAX) { status = GATT_NO_RESOURCES; LOG(ERROR) << "Max Notification Reached, registration failed."; } } } else { LOG(ERROR) << "client_if=" << +client_if << " Not Registered"; } return status; } /******************************************************************************* * * Function BTA_GATTC_DeregisterForNotifications * * Description This function is called to de-register for notification of a * service. * * Parameters client_if - client interface. * remote_bda - target GATT server. * handle - GATT characteristic handle. * * Returns OK if deregistration succeed, otherwise failed. * ******************************************************************************/ tGATT_STATUS BTA_GATTC_DeregisterForNotifications(tGATT_IF client_if, const RawAddress& bda, uint16_t handle) { if (!handle) { LOG(ERROR) << __func__ << ": deregistration failed, handle is 0"; return GATT_ILLEGAL_PARAMETER; } tBTA_GATTC_RCB* p_clreg = bta_gattc_cl_get_regcb(client_if); if (p_clreg == NULL) { LOG(ERROR) << __func__ << " client_if=" << +client_if << " not registered bd_addr=" << bda; return GATT_ILLEGAL_PARAMETER; } for (int i = 0; i < BTA_GATTC_NOTIF_REG_MAX; i++) { if (p_clreg->notif_reg[i].in_use && p_clreg->notif_reg[i].remote_bda == bda && p_clreg->notif_reg[i].handle == handle) { VLOG(1) << __func__ << " deregistered bd_addr=" << bda; memset(&p_clreg->notif_reg[i], 0, sizeof(tBTA_GATTC_NOTIF_REG)); return GATT_SUCCESS; } } LOG(ERROR) << __func__ << " registration not found bd_addr=" << bda; return GATT_ERROR; } /******************************************************************************* * * Function BTA_GATTC_Refresh * * Description Refresh the server cache of the remote device * * Parameters remote_bda: remote device BD address. * * Returns void * ******************************************************************************/ void BTA_GATTC_Refresh(const RawAddress& remote_bda) { do_in_main_thread(FROM_HERE, base::Bind(&bta_gattc_process_api_refresh, remote_bda)); }