blob: eedebcc9f3dbc2b10c563b475f1fbe0d0627e52c [file] [log] [blame]
/*
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
*/
/*
* Copyright (C) 2003-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
*/
/******************************************************************************
*
* This is the main implementation file for the BTA LE audio call Gateway.
*
******************************************************************************/
#include "bta_api.h"
#include "btif_util.h"
#include "bt_target.h"
#include "bta_cc_api.h"
#include "gatts_ops_queue.h"
#include "btm_int.h"
#include "device/include/controller.h"
#include "osi/include/properties.h"
#include "osi/include/alarm.h"
#include "osi/include/allocator.h"
#include "osi/include/osi.h"
#include "bta_sys.h"
#include <vector>
#include <iostream>
#include <string.h>
#include <base/bind.h>
#include <base/callback.h>
#include <base/logging.h>
#include <base/location.h>
#include <hardware/bluetooth.h>
#include <base/strings/string_number_conversions.h>
#include <vector>
#include <string.h>
#include <algorithm>
#include <map>
#define MAX_URI_SIZE 50
#define STANDARD_BEARER_UCI "un000"
#define MS_IN_SEC 1000
#define CCS_DEFAULT_INDEX_VAL 0
#define DEFAULT_INDICIES_COUNT 1
using bluetooth::Uuid;
using bluetooth::bap::GattsOpsQueue;
class CallControllerImpl;
static CallControllerImpl *cc_instance;
static bool gIsTerminatedInitiatedFromClient = false;
static int gTerminateIntiatedIndex = 0;
static bool gIsActiveCC = false;
//GTBS UUID (4B: TBS, 4C: GTBS)
Uuid CALL_CONTROL_SERVER_UUID = Uuid::FromString("0000184C-0000-1000-8000-00805F9B34FB");
Uuid GTBS_CALL_BEARER_NAME_UUID = Uuid::FromString("00002bb3-0000-1000-8000-00805F9B34FB");
Uuid GTBS_BEARER_UCI = Uuid::FromString("00002bb4-0000-1000-8000-00805F9B34FB");
Uuid GTBS_BEARER_TECHNOLOGY = Uuid::FromString("00002bb5-0000-1000-8000-00805F9B34FB");
Uuid GTBS_BEARER_URI_SCHEMES = Uuid::FromString("00002bb6-0000-1000-8000-00805F9B34FB");
Uuid GTBS_SIGNAL_STRENGTH = Uuid::FromString("00002bb7-0000-1000-8000-00805F9B34FB");
Uuid GTBS_SIGNAL_STRENGTH_REPORTINTERVAL = Uuid::FromString("00002bb8-0000-1000-8000-00805F9B34FB");
Uuid GTBS_BEARER_LIST_CURRENT_CALLS = Uuid::FromString("00002bb9-0000-1000-8000-00805F9B34FB");
Uuid GTBS_CONTENT_CONTROLID = Uuid::FromString("00002bba-0000-1000-8000-00805F9B34FB");
Uuid GTBS_CALL_STATUS_FLAGS = Uuid::FromString("00002bbb-0000-1000-8000-00805F9B34FB");
Uuid GTBS_INCOMINGCALL_TARGET_URI = Uuid::FromString("00002bbc-0000-1000-8000-00805F9B34FB");
Uuid GTBS_CALL_STATE_UUID = Uuid::FromString("00002bbd-0000-1000-8000-00805F9B34FB");
Uuid GTBS_CALL_CONTROL_POINT_OPS = Uuid::FromString("00002bbe-0000-1000-8000-00805F9B34FB");
Uuid GTBS_CALL_CONTROL_POINT_OPTIONAL_OPS = Uuid::FromString("00002bbf-0000-1000-8000-00805F9B34FB");
Uuid GTBS_CALL_TERMINATION_REASON = Uuid::FromString("00002bc0-0000-1000-8000-00805F9B34FB");
Uuid GTBS_INCOMING_CALL = Uuid::FromString("00002bc1-0000-1000-8000-00805F9B34FB");
Uuid GTBS_CALL_FRIENDLY_NAME = Uuid::FromString("00002bc2-0000-1000-8000-00805F9B34FB");
Uuid GTBS_DESCRIPTOR_UUID = Uuid::FromString("00002902-0000-1000-8000-00805f9b34fb");
//global varibale
CcsControlServiceInfo_t ccsControlServiceInfo;
tCCS_CALL_STATE CallStateInfo;
std::map<uint8_t, tCCS_CALL_STATE> CallStatelist;
std::map<uint8_t, tCCS_BEARER_LIST_CURRENT_CALLS> BlccInfolist;
tCCS_CALL_CONTROL_POINT CallControllerOps;
tCCS_CALL_CONTROL_RESPONSE CallControllerResp;
tCCS_BEARER_LIST_CURRENT_CALLS BlccInfo;
tCCS_BEARER_PROVIDER_INFO BearerProviderInfo;
tCCS_CONTENT_CONTROL_ID CcidInfo;
tCCS_STATUS_FLAGS StatusFlags;
tCCS_INCOMING_CALL IncomingCallInfo;
tCCS_INCOMING_CALL_URI IncomingCallTargetUri;
tCCS_TERM_REASON TerminationReason;
tCCS_FRIENDLY_NAME FriendlyName;
tCCS_SUPP_OPTIONAL_OPCODES SupportedOptionalOpcodes;
void BTCcCback(tBTA_GATTS_EVT event, tBTA_GATTS* param);
void ReverseByteOrder(unsigned char s[], int length);
typedef base::Callback<void(uint8_t status, int server_if,
std::vector<btgatt_db_element_t> service)>
OnGtbsServiceAdded;
static void OnGtbsServiceAddedCb(uint8_t status, int serverIf,
std::vector<btgatt_db_element_t> service);
const char* bta_cc_event_str(uint32_t event) {
switch (event) {
CASE_RETURN_STR(CCS_NONE_EVENT)
CASE_RETURN_STR(CCS_INIT_EVENT)
CASE_RETURN_STR(CCS_CLEANUP_EVENT)
CASE_RETURN_STR(CCS_CALL_STATE_UPDATE)
CASE_RETURN_STR(CCS_BEARER_NAME_UPDATE)
CASE_RETURN_STR(CCS_BEARER_UCI_UPDATE)
CASE_RETURN_STR(CCS_BEARER_URI_SCHEMES_SUPPORTED)
CASE_RETURN_STR(CCS_UPDATE)
CASE_RETURN_STR(CCS_OPT_OPCODES)
CASE_RETURN_STR(CCS_BEARER_CURRENT_CALL_LIST_UPDATE)
CASE_RETURN_STR(CCS_BEARER_SIGNAL_STRENGTH_UPDATE)
CASE_RETURN_STR(CCS_SIGNAL_STRENGTH_REPORT_INTERVAL)
CASE_RETURN_STR(CCS_STATUS_FLAGS_UPDATE)
CASE_RETURN_STR(CCS_INCOMING_CALL_UPDATE)
CASE_RETURN_STR(CCS_INCOMING_TARGET_URI_UPDATE)
CASE_RETURN_STR(CCS_TERMINATION_REASON_UPDATE)
CASE_RETURN_STR(CCS_BEARER_TECHNOLOGY_UPDATE)
CASE_RETURN_STR(CCS_CCID_UPDATE)
CASE_RETURN_STR(CCS_ACTIVE_DEVICE_UPDATE)
CASE_RETURN_STR(CCS_CALL_CONTROL_RESPONSE)
CASE_RETURN_STR(CCS_NOTIFY_ALL)
CASE_RETURN_STR(CCS_WRITE_RSP)
CASE_RETURN_STR(CCS_READ_RSP)
CASE_RETURN_STR(CCS_DESCRIPTOR_WRITE_RSP)
CASE_RETURN_STR(CCS_DESCRIPTOR_READ_RSP)
CASE_RETURN_STR(CCS_CONNECTION)
CASE_RETURN_STR(CCS_DISCONNECTION)
CASE_RETURN_STR(CCS_CONNECTION_UPDATE)
CASE_RETURN_STR(CCS_CONGESTION_UPDATE)
CASE_RETURN_STR(CCS_PHY_UPDATE)
CASE_RETURN_STR(CCS_MTU_UPDATE)
CASE_RETURN_STR(CCS_SET_ACTIVE_DEVICE)
CASE_RETURN_STR(CCS_CONNECTION_CLOSE_EVENT)
CASE_RETURN_STR(CCS_BOND_STATE_CHANGE_EVENT)
default:
return (char*)"Unknown bta cc event";
}
}
class CallControllerDevices {
private:
CallActiveDevice activeDevice;
//int max_connection;
public:
bool Add(CallControllerDeviceList device) {
if (devices.size() == MAX_CCS_CONNECTION) {
return false;
}
if (FindByAddress(device.peer_bda) != nullptr) return false;
device.DeviceStateHandlerPointer[CCS_DISCONNECTED] = DeviceStateDisconnectedHandler;
device.DeviceStateHandlerPointer[CCS_CONNECTED] = DeviceStateConnectionHandler;
device.signal_strength_report_interval = 0;
std::string alarmName = device.peer_bda.ToString();
alarmName.append("-CC_SSReportingTimer");
device.signal_strength_reporting_timer = alarm_new_periodic(alarmName.c_str());
devices.push_back(device);
return true;
}
void Remove(RawAddress& address) {
for (auto it = devices.begin(); it != devices.end();) {
if (it->peer_bda != address) {
++it;
continue;
}
if (it == devices.end()) {
LOG(ERROR) << __func__ <<"no matching device";
return;
}
//Cancel SSReporting timer
if (it->signal_strength_report_interval != 0 &&
it->signal_strength_reporting_timer != nullptr) {
alarm_cancel(it->signal_strength_reporting_timer);
alarm_free(it->signal_strength_reporting_timer);
}
it = devices.erase(it);
return;
}
}
void RemoveDevices() {
for (auto it = devices.begin(); it != devices.end();) {
it = devices.erase(it);
}
return;
}
CallControllerDeviceList* FindByAddress(const RawAddress& address) {
auto iter = std::find_if(devices.begin(), devices.end(),
[&address](const CallControllerDeviceList& device) {
return device.peer_bda == address;
});
return (iter == devices.end()) ? nullptr : &(*iter);
}
CallControllerDeviceList* FindByConnId(uint16_t conn_id) {
auto iter = std::find_if(devices.begin(), devices.end(),
[&conn_id](const CallControllerDeviceList& device) {
return device.conn_id == conn_id;
});
return (iter == devices.end()) ? nullptr : &(*iter);
}
size_t size() { return (devices.size()); }
std::vector<CallControllerDeviceList> GetRemoteDevices() {
return devices;
}
std::vector<CallControllerDeviceList> FindNotifyDevices(uint16_t handle) {
std::vector<CallControllerDeviceList> notify_devices;
for (size_t it = 0; it != devices.size(); it++){
if(ccsControlServiceInfo.bearer_provider_name_handle == handle &&
devices[it].bearer_provider_name_notify) {
notify_devices.push_back(devices[it]);
} else if(ccsControlServiceInfo.bearer_technology_handle == handle &&
devices[it].bearer_technology_changed_notify) {
notify_devices.push_back(devices[it]);
} else if(ccsControlServiceInfo.bearer_signal_strength_handle == handle &&
devices[it].bearer_signal_strength_notify) {
notify_devices.push_back(devices[it]);
} else if(ccsControlServiceInfo.bearer_list_currentcalls_handle == handle &&
devices[it].bearer_current_calls_list_notify) {
notify_devices.push_back(devices[it]);
} else if(ccsControlServiceInfo.call_status_flags_handle == handle &&
devices[it].status_flags_notify) {
notify_devices.push_back(devices[it]);
} else if(ccsControlServiceInfo.incoming_call_target_beareruri_handle == handle &&
devices[it].incoming_call_target_URI_notify) {
notify_devices.push_back(devices[it]);
} else if(ccsControlServiceInfo.call_state_handle == handle &&
devices[it].call_state_notify) {
notify_devices.push_back(devices[it]);
} else if(ccsControlServiceInfo.call_control_point_handle == handle &&
devices[it].call_control_point_notify) {
notify_devices.push_back(devices[it]);
} else if(ccsControlServiceInfo.call_termination_reason_handle == handle &&
devices[it].call_termination_reason_notify) {
notify_devices.push_back(devices[it]);
} else if(ccsControlServiceInfo.incoming_call_handle == handle &&
devices[it].incoming_call_state_notify) {
notify_devices.push_back(devices[it]);
} else if(ccsControlServiceInfo.call_friendly_name_handle == handle &&
devices[it].call_friendly_name_notify) {
notify_devices.push_back(devices[it]);
}
}
return notify_devices;
}
void AddSetActiveDevice(tCCS_SET_ACTIVE_DEVICE *device) {
if (device->set_id == activeDevice.set_id) {
activeDevice.address.push_back(device->address);
} else {
activeDevice.address.clear();
activeDevice.set_id = device->set_id;
activeDevice.address.push_back(device->address);
}
}
bool FindActiveDevice(CallControllerDeviceList *remoteDevice) {
bool flag = false;
for (auto& it : activeDevice.address) {
if(remoteDevice->peer_bda == it) {
flag = true;
break;
}
}
return flag;
}
static void SSReportingTimerExpired(void *data) {
LOG(INFO) << __func__ ;
CallControllerDeviceList* dev = (CallControllerDeviceList*)data;
if (dev == nullptr) {
LOG(ERROR) << __func__ << "no valid dev handle";
return;
}
//send Notification for Signal Strength
tcc_resp_t *rsp = new tcc_resp_t();
if (rsp == NULL) {
LOG(ERROR) << __func__ << "Allocation error!";
return;
}
std::vector<uint8_t> _data;
_data.clear();
rsp->remoteDevice = dev;
rsp->event = CCS_NOTIFY_ALL;
rsp->handle = ccsControlServiceInfo.bearer_signal_strength_handle;
_data.push_back(BearerProviderInfo.signal);
rsp->oper.CallControllerOp.data = std::move(_data);
//force the Notification on timer expiry
rsp->force = true;
if (dev->bearer_signal_strength_notify) {
LOG(INFO) << "Caling device state handler for SSReporting";
dev->DeviceStateHandlerPointer[dev->state](CCS_NOTIFY_ALL, rsp);
} else {
LOG(INFO) << "SSReporting Interval set without Desc write for SSR";
}
}
static void SetupSSReportingInterval (CallControllerDeviceList* dev) {
LOG(INFO) << __func__ ;
if (alarm_is_scheduled(dev->signal_strength_reporting_timer)) {
alarm_cancel(dev->signal_strength_reporting_timer);
}
if (dev->signal_strength_report_interval != 0) {
alarm_set(dev->signal_strength_reporting_timer,
(period_ms_t)dev->signal_strength_report_interval*MS_IN_SEC,
SSReportingTimerExpired,
(void*)dev);
}
}
bool UpdateSSReportingInterval(const RawAddress& address, uint8_t ssrInterval) {
bool ret = false;
CallControllerDeviceList *dev = FindByAddress(address);
if (dev != nullptr) {
dev->signal_strength_report_interval = ssrInterval;
SetupSSReportingInterval(dev);
ret = true;
}
return ret;
}
std::vector<CallControllerDeviceList> devices;
};
class CallControllerImpl : public CallController {
bluetooth::call_control::CallControllerCallbacks* callbacks;
Uuid app_uuid;
int max_clients;
bool inband_ring_support;
public:
CallControllerDevices remoteDevices;
virtual ~CallControllerImpl() = default;
CallControllerImpl(bluetooth::call_control::CallControllerCallbacks* callback,
Uuid uuid, int max_ccs_clients, bool inband_ringing_enabled)
:callbacks(callback),
app_uuid(uuid),
max_clients(max_ccs_clients),
inband_ring_support(inband_ringing_enabled) {
// HandleCcsEvent(CCS_INIT_EVENT, &app_uuid);
LOG(INFO) << "max_clients " << max_clients;
if (inband_ring_support) {
StatusFlags.supported_flags = (StatusFlags.supported_flags & 0x0000) | INBAND_RINGTONE_FEATURE_BIT;
} else {
StatusFlags.supported_flags = 0x0000;
}
LOG(INFO) << "CallControllerImpl gatts app register";
BTA_GATTS_AppRegister(app_uuid, BTCcCback, true);
}
void Disconnect(const RawAddress& bd_addr) {
LOG(INFO) << __func__;
tCCS_CONNECTION_CLOSE ConnectClosingOp;
ConnectClosingOp.addr = bd_addr;
HandleCcsEvent(CCS_CONNECTION_CLOSE_EVENT, &ConnectClosingOp);
}
void SetActiveDevice(const RawAddress& address, int setId) {
LOG(INFO) << __func__ ;
tCCS_SET_ACTIVE_DEVICE SetActiveDeviceOp;
SetActiveDeviceOp.set_id = setId;
SetActiveDeviceOp.address = address;
HandleCcsEvent(CCS_ACTIVE_DEVICE_UPDATE, &SetActiveDeviceOp);
}
void CallState(int len, std::vector<uint8_t> call_state_list) {
tCCS_CALL_STATE CallStateOp;
for (int k=0; k<len; k++) {
LOG(INFO) << __func__ << " " << k <<" : index: " << (unsigned)call_state_list[3*k + 0]
<< " state: " << (unsigned) call_state_list[3*k + 1]
<< " flags: " << (unsigned) call_state_list[3*k + 2];
CallStateOp.index = call_state_list[3*k + 0];
CallStateOp.state = call_state_list[3*k + 1];
CallStateOp.flags = call_state_list[3*k + 2];
BlccInfo.call_flags = CallStateOp.flags;
BlccInfo.call_index = CallStateOp.index;
BlccInfo.call_state = CallStateOp.state;
if (CallStateOp.state == CCS_STATE_INCOMING) {
int len = strlen((char *)IncomingCallInfo.incoming_uri);
memcpy(BlccInfo.call_uri, IncomingCallInfo.incoming_uri, len);
BlccInfo.list_length = 3 + len;
} else {
BlccInfo.list_length = 3;
}
if (CallStateOp.state == CCS_STATE_DISCONNECTED) {
//clear off the Incoming call related things as well
if (IncomingCallInfo.index == CallStateOp.index) {
IncomingCallInfo.index = 0;
memset(IncomingCallInfo.incoming_uri, 0, MAX_URI_LENGTH);
}
if (IncomingCallTargetUri.index == CallStateOp.index) {
IncomingCallTargetUri.index = 0;
memset(IncomingCallTargetUri.incoming_target_uri, 0, MAX_URI_LENGTH);
}
TerminationReason.index = CallStateOp.index;
if (gIsTerminatedInitiatedFromClient &&
CallStateOp.index == gIsTerminatedInitiatedFromClient) {
TerminationReason.reason = CC_TERM_END_FROM_CLIENT;
} else {
TerminationReason.reason = CC_TERM_END_FROM_SERVER;
}
gIsTerminatedInitiatedFromClient = false;
gTerminateIntiatedIndex = 0;
HandleCcsEvent(CCS_INCOMING_CALL_UPDATE, &IncomingCallInfo);
HandleCcsEvent(CCS_INCOMING_TARGET_URI_UPDATE, &IncomingCallTargetUri);
HandleCcsEvent(CCS_TERMINATION_REASON_UPDATE, &TerminationReason);
//erase the disconnected Indicies
BlccInfolist.erase(CallStateOp.index);
CallStatelist.erase(CallStateOp.index);
} else {
//keep appending the data
std::map<uint8_t, tCCS_BEARER_LIST_CURRENT_CALLS>::iterator i = BlccInfolist.find(BlccInfo.call_index);
if (i != BlccInfolist.end()) {
LOG(INFO) << __func__ << " update existing Blcc";
i->second = BlccInfo;
} else {
BlccInfolist.insert({BlccInfo.call_index, BlccInfo});
}
std::map<uint8_t, tCCS_CALL_STATE>::iterator j = CallStatelist.find(CallStateOp.index);
if (j != CallStatelist.end()) {
j->second = CallStateOp;
} else {
CallStatelist.insert({CallStateOp.index, CallStateOp});
}
//clear the term reason
if (CallStateOp.index == TerminationReason.index) {
TerminationReason.index = 0;
TerminationReason.reason = CC_TERM_INVALID_ORIG_URI;
}
}
}
HandleCcsEvent(CCS_CALL_STATE_UPDATE, &CallStatelist);
HandleCcsEvent(CCS_BEARER_CURRENT_CALL_LIST_UPDATE, &BlccInfolist);
}
void BearerInfoName(uint8_t* name) {
LOG(INFO) << __func__ << name;
tCCS_BEARER_PROVIDER_INFO BearerProviderOp;
BearerProviderOp.length = strlen((char *)name);
memcpy(BearerProviderOp.name, name, BearerProviderOp.length+1);
HandleCcsEvent(CCS_BEARER_NAME_UPDATE, &BearerProviderOp);
}
void UpdateBearerTechnology(int tech_type) {
LOG(INFO) << __func__ << " tech type: " <<tech_type;
tCCS_BEARER_PROVIDER_INFO bearerProviderOp;
BearerProviderInfo.technology_type = tech_type;
HandleCcsEvent(CCS_BEARER_TECHNOLOGY_UPDATE, &bearerProviderOp);
}
void UpdateBearerSignalStrength(int signal) {
LOG(INFO) << __func__<< " signal: " << signal;
tCCS_BEARER_PROVIDER_INFO BearerProviderOp;
BearerProviderOp.signal = signal;
HandleCcsEvent(CCS_BEARER_SIGNAL_STRENGTH_UPDATE, &BearerProviderOp);
}
void UpdateStatusFlags(uint8_t status_flag) {
LOG(INFO) << __func__ << " status_flag: " <<status_flag;
tCCS_STATUS_FLAGS StatusFlagsOp;
StatusFlagsOp.supported_flags = status_flag;
HandleCcsEvent(CCS_STATUS_FLAGS_UPDATE, &StatusFlagsOp);
}
void CallControlOptionalOpSupported(int feature) {
LOG(INFO) << __func__ << " feature: " << feature;
tCCS_SUPP_OPTIONAL_OPCODES opSupportedFeatures;
opSupportedFeatures.supp_opcode = (uint16_t)0x00FF&feature;
HandleCcsEvent(CCS_OPT_OPCODES, &opSupportedFeatures);
}
void UpdateSupportedBearerList(uint8_t* list) {
LOG(INFO) << __func__ << " list: " <<list;
tCCS_BEARER_PROVIDER_INFO BearerProviderOp;
BearerProviderOp.bearer_list_len = strlen((char *)list);
LOG(INFO) << __func__ << " list len:" << BearerProviderOp.bearer_list_len;
memcpy(BearerProviderOp.bearer_schemes_list, list, BearerProviderOp.bearer_list_len+1);
HandleCcsEvent(CCS_BEARER_URI_SCHEMES_SUPPORTED, &BearerProviderOp);
}
void UpdateIncomingCall(int index, uint8_t* Uri) {
LOG(INFO) << __func__ << " Uri: " << Uri;
std::map<uint8_t, tCCS_BEARER_LIST_CURRENT_CALLS>::iterator it;
tCCS_INCOMING_CALL IncomingCall;
int len = strlen((char *)Uri);
memcpy(IncomingCall.incoming_uri, Uri, len+1);
IncomingCall.index = index;
for (it = BlccInfolist.begin(); it != BlccInfolist.end(); it++) {
tCCS_BEARER_LIST_CURRENT_CALLS blccObj = it->second;
if (blccObj.call_index == index) {
memcpy(blccObj.call_uri, Uri, strlen((char *)Uri)+1);
break;
}
}
HandleCcsEvent(CCS_INCOMING_CALL_UPDATE, &IncomingCall);
//update Target URI as well with same Info
UpdateIncomingCallTargetUri(index, Uri);
}
void UpdateIncomingCallTargetUri(int index, uint8_t* target_uri) {
LOG(INFO) << __func__ << " target_uri: " << target_uri;
tCCS_INCOMING_CALL_URI IncomingcallUri;
int len = strlen((char *)target_uri);
memcpy(IncomingcallUri.incoming_target_uri, target_uri, len+1);
IncomingcallUri.index = index;
HandleCcsEvent(CCS_INCOMING_TARGET_URI_UPDATE, &IncomingcallUri);
}
void ContentControlId(uint32_t ccid) {
LOG(INFO) << __func__;
tCCS_CONTENT_CONTROL_ID ContentControlIdOp;
ContentControlIdOp.ccid = ccid;
HandleCcsEvent(CCS_CCID_UPDATE, &ContentControlIdOp);
}
int GetDialingCallIndex() {
int retIndex = 0;
std::map<uint8_t, tCCS_CALL_STATE>::iterator it;
for (it = CallStatelist.begin(); it != CallStatelist.end(); it++) {
tCCS_CALL_STATE obj = it->second;
if (obj.state == CCS_STATE_DIALING || obj.state == CCS_STATE_ALERTING) {
LOG(INFO) << __func__ << " call state match: " << obj.index;
retIndex = obj.index;
break;
}
}
return retIndex;
}
void CallControlResponse(uint8_t op, uint8_t index, uint32_t status, const RawAddress& address) {
LOG(INFO) << __func__;
tCCS_CALL_CONTROL_RESPONSE CallControlResponse;
CallControllerResp.opcode = op;
CallControllerResp.response_status = status;
CallControllerResp.remote_address = address;
CallControllerResp.index = index;
if (status == CCS_STATUS_SUCCESS && op == CALL_ORIGINATE) {
//get proper call Index for call orignate status
CallControllerResp.index = GetDialingCallIndex();
}
HandleCcsEvent(CCS_CALL_CONTROL_RESPONSE, &CallControlResponse);
}
void CallControlInitializedCallback(uint8_t state) {
LOG(INFO) << __func__ << " state" << state;
callbacks->CallControlInitializedCallback(state);
if (state == 0) {
//Initialize local char values
memcpy(BearerProviderInfo.uci, STANDARD_BEARER_UCI, strlen(STANDARD_BEARER_UCI));
}
}
void ConnectionStateCallback(uint8_t state, const RawAddress& address) {
LOG(INFO) << __func__ << " state: " << state;
callbacks->ConnectionStateCallback(state, address);
}
void CallControlPointChange(uint8_t op, uint8_t* indices, int count, char* uri, const RawAddress& address) {
LOG(INFO) << __func__ << " op: " <<op << " count :" << count;
std::vector<uint8_t> uri_data;
if (uri != NULL) {
LOG(INFO) << __func__ <<" uri=" << uri;
uri_data.insert(uri_data.begin(), uri, uri + strlen(uri));
}
std::vector<int32_t> call_indicies;
for (int i=0; i<count; i++) {
call_indicies.push_back(indices[i]);
}
callbacks->CallControlCallback(op, call_indicies, count, uri_data, address);
}
};
void CallController::CleanUp() {
HandleCcsEvent(CCS_CLEANUP_EVENT, NULL);
delete cc_instance;
cc_instance = nullptr;
}
CallController* CallController::Get() {
CHECK(cc_instance);
return cc_instance;
}
void CallController::Initialize(bluetooth::call_control::CallControllerCallbacks* callbacks,
Uuid uuid, int max_ccs_clients, bool inband_ringing_enabled) {
if (cc_instance) {
LOG(ERROR) << "Already initialized!";
} else {
cc_instance = new CallControllerImpl(callbacks, uuid, max_ccs_clients, inband_ringing_enabled);
}
char activeCC[PROPERTY_VALUE_MAX] = "false";
if(osi_property_get("persist.vendor.service.bt.activeCC", activeCC, "false") &&
!strcmp(activeCC, "true")) {
gIsActiveCC = true;
}
}
bool CallController::IsCcServiceRunnig() { return cc_instance; }
static std::vector<btgatt_db_element_t> CcAddService(int server_if) {
std::vector<btgatt_db_element_t> ccs_services;
ccs_services.clear();
//service
btgatt_db_element_t service = {};
service.uuid = CALL_CONTROL_SERVER_UUID;
service.type = BTGATT_DB_PRIMARY_SERVICE;
ccs_services.push_back(service);
ccsControlServiceInfo.ccs_service_uuid = service.uuid;
btgatt_db_element_t bearer_provider_name_char = {};
bearer_provider_name_char.uuid = GTBS_CALL_BEARER_NAME_UUID;
bearer_provider_name_char.type = BTGATT_DB_CHARACTERISTIC;
bearer_provider_name_char.properties = GATT_CHAR_PROP_BIT_READ|GATT_CHAR_PROP_BIT_NOTIFY;
bearer_provider_name_char.permissions = GATT_PERM_READ;
ccs_services.push_back(bearer_provider_name_char);
ccsControlServiceInfo.bearer_provider_name_uuid = bearer_provider_name_char.uuid;
btgatt_db_element_t bearer_provider_name_desc = {};
bearer_provider_name_desc.uuid = GTBS_DESCRIPTOR_UUID;
bearer_provider_name_desc.type = BTGATT_DB_DESCRIPTOR;
bearer_provider_name_desc.permissions = GATT_PERM_READ|GATT_PERM_WRITE;
ccs_services.push_back(bearer_provider_name_desc);
btgatt_db_element_t bearer_technology_char = {};
bearer_technology_char.uuid = GTBS_BEARER_TECHNOLOGY;
bearer_technology_char.type = BTGATT_DB_CHARACTERISTIC;
bearer_technology_char.properties = GATT_CHAR_PROP_BIT_READ|GATT_CHAR_PROP_BIT_NOTIFY;
bearer_technology_char.permissions = GATT_PERM_READ;
ccs_services.push_back(bearer_technology_char);
ccsControlServiceInfo.bearer_technology_uuid = bearer_technology_char.uuid;
btgatt_db_element_t bearer_technology_desc = {};
bearer_technology_desc.uuid = GTBS_DESCRIPTOR_UUID;
bearer_technology_desc.type = BTGATT_DB_DESCRIPTOR;
bearer_technology_desc.permissions = GATT_PERM_READ|GATT_PERM_WRITE;
ccs_services.push_back(bearer_technology_desc);
btgatt_db_element_t gtbs_cc_optional_opcode_char = {};
gtbs_cc_optional_opcode_char.uuid = GTBS_CALL_CONTROL_POINT_OPTIONAL_OPS;
gtbs_cc_optional_opcode_char.type = BTGATT_DB_CHARACTERISTIC;
gtbs_cc_optional_opcode_char.properties = GATT_CHAR_PROP_BIT_READ;
gtbs_cc_optional_opcode_char.permissions = GATT_PERM_READ;
ccs_services.push_back(gtbs_cc_optional_opcode_char);
ccsControlServiceInfo.call_control_point_opcode_supported_uuid = gtbs_cc_optional_opcode_char.uuid;
btgatt_db_element_t gtbs_call_state_char = {};
gtbs_call_state_char.uuid = GTBS_CALL_STATE_UUID;
gtbs_call_state_char.type = BTGATT_DB_CHARACTERISTIC;
gtbs_call_state_char.properties = GATT_CHAR_PROP_BIT_READ|GATT_CHAR_PROP_BIT_NOTIFY;
gtbs_call_state_char.permissions = GATT_PERM_READ;
ccs_services.push_back(gtbs_call_state_char);
ccsControlServiceInfo.call_state_uuid = gtbs_call_state_char.uuid;
btgatt_db_element_t gtbs_call_state_desc = {};
gtbs_call_state_desc.uuid = GTBS_DESCRIPTOR_UUID;
gtbs_call_state_desc.type = BTGATT_DB_DESCRIPTOR;
gtbs_call_state_desc.permissions = GATT_PERM_READ|GATT_PERM_WRITE;
ccs_services.push_back(gtbs_call_state_desc);
btgatt_db_element_t gtbs_call_control_point_char = {};
gtbs_call_control_point_char.uuid = GTBS_CALL_CONTROL_POINT_OPS;
gtbs_call_control_point_char.type = BTGATT_DB_CHARACTERISTIC;
gtbs_call_control_point_char.properties = GATT_CHAR_PROP_BIT_WRITE|GATT_CHAR_PROP_BIT_NOTIFY|GATT_CHAR_PROP_BIT_WRITE_NR;
gtbs_call_control_point_char.permissions = GATT_PERM_WRITE;
ccs_services.push_back(gtbs_call_control_point_char);
ccsControlServiceInfo.call_control_point_uuid = gtbs_call_control_point_char.uuid;
btgatt_db_element_t gtbs_call_control_point_desc = {};
gtbs_call_control_point_desc.uuid = GTBS_DESCRIPTOR_UUID;
gtbs_call_control_point_desc.type = BTGATT_DB_DESCRIPTOR;
gtbs_call_control_point_desc.permissions = GATT_PERM_READ|GATT_PERM_WRITE;
ccs_services.push_back(gtbs_call_control_point_desc);
btgatt_db_element_t gtbs_bearer_uci_char = {};
gtbs_bearer_uci_char.uuid = GTBS_BEARER_UCI;
gtbs_bearer_uci_char.type = BTGATT_DB_CHARACTERISTIC;
gtbs_bearer_uci_char.properties = GATT_CHAR_PROP_BIT_READ;
gtbs_bearer_uci_char.permissions = GATT_PERM_READ;
ccs_services.push_back(gtbs_bearer_uci_char);
ccsControlServiceInfo.bearer_uci_uuid= gtbs_bearer_uci_char.uuid;
btgatt_db_element_t gtbs_bearer_URI_schemes_char = {};
gtbs_bearer_URI_schemes_char.uuid = GTBS_BEARER_URI_SCHEMES;
gtbs_bearer_URI_schemes_char.type = BTGATT_DB_CHARACTERISTIC;
gtbs_bearer_URI_schemes_char.properties = GATT_CHAR_PROP_BIT_READ|GATT_CHAR_PROP_BIT_NOTIFY;
gtbs_bearer_URI_schemes_char.permissions = GATT_PERM_READ;
ccs_services.push_back(gtbs_bearer_URI_schemes_char);
ccsControlServiceInfo.bearer_uri_schemes_supported_uuid = gtbs_bearer_URI_schemes_char.uuid;
btgatt_db_element_t gtbs_bearer_URI_schemes_desc = {};
gtbs_bearer_URI_schemes_desc.uuid = GTBS_DESCRIPTOR_UUID;
gtbs_bearer_URI_schemes_desc.type = BTGATT_DB_DESCRIPTOR;
gtbs_bearer_URI_schemes_desc.permissions = GATT_PERM_READ|GATT_PERM_WRITE;
ccs_services.push_back(gtbs_bearer_URI_schemes_desc);
btgatt_db_element_t gtbs_signal_strength_char = {};
gtbs_signal_strength_char.uuid = GTBS_SIGNAL_STRENGTH;
gtbs_signal_strength_char.type = BTGATT_DB_CHARACTERISTIC;
gtbs_signal_strength_char.properties = GATT_CHAR_PROP_BIT_READ|GATT_CHAR_PROP_BIT_NOTIFY;
gtbs_signal_strength_char.permissions = GATT_PERM_READ;
ccs_services.push_back(gtbs_signal_strength_char);
ccsControlServiceInfo.bearer_signal_strength_uuid = gtbs_signal_strength_char.uuid;
btgatt_db_element_t gtbs_signal_strength_desc = {};
gtbs_signal_strength_desc.uuid = GTBS_DESCRIPTOR_UUID;
gtbs_signal_strength_desc.type = BTGATT_DB_DESCRIPTOR;
gtbs_signal_strength_desc.permissions = GATT_PERM_READ|GATT_PERM_WRITE;
ccs_services.push_back(gtbs_signal_strength_desc);
btgatt_db_element_t gtbs_signal_strength_report_interval_char = {};
gtbs_signal_strength_report_interval_char.uuid = GTBS_SIGNAL_STRENGTH_REPORTINTERVAL;
gtbs_signal_strength_report_interval_char.type = BTGATT_DB_CHARACTERISTIC;
gtbs_signal_strength_report_interval_char.properties = GATT_CHAR_PROP_BIT_READ|GATT_CHAR_PROP_BIT_WRITE|GATT_CHAR_PROP_BIT_WRITE_NR;
gtbs_signal_strength_report_interval_char.permissions = GATT_PERM_READ|GATT_PERM_WRITE;
ccs_services.push_back(gtbs_signal_strength_report_interval_char);
ccsControlServiceInfo.bearer_signal_strength_report_interval_uuid = gtbs_signal_strength_report_interval_char.uuid;
btgatt_db_element_t gtbs_list_current_calls_char = {};
gtbs_list_current_calls_char.uuid = GTBS_BEARER_LIST_CURRENT_CALLS;
gtbs_list_current_calls_char.type = BTGATT_DB_CHARACTERISTIC;
gtbs_list_current_calls_char.properties = GATT_CHAR_PROP_BIT_READ|GATT_CHAR_PROP_BIT_NOTIFY;
gtbs_list_current_calls_char.permissions = GATT_PERM_READ;
ccs_services.push_back(gtbs_list_current_calls_char);
ccsControlServiceInfo.bearer_list_currentcalls_uuid = gtbs_list_current_calls_char.uuid;
btgatt_db_element_t gtbs_list_current_calls_desc = {};
gtbs_list_current_calls_desc.uuid = GTBS_DESCRIPTOR_UUID;
gtbs_list_current_calls_desc.type = BTGATT_DB_DESCRIPTOR;
gtbs_list_current_calls_desc.permissions = GATT_PERM_READ|GATT_PERM_WRITE;
ccs_services.push_back(gtbs_list_current_calls_desc);
btgatt_db_element_t gtbs_call_status_flags_char = {};
gtbs_call_status_flags_char.uuid = GTBS_CALL_STATUS_FLAGS;
gtbs_call_status_flags_char.type = BTGATT_DB_CHARACTERISTIC;
gtbs_call_status_flags_char.properties = GATT_CHAR_PROP_BIT_READ|GATT_CHAR_PROP_BIT_NOTIFY;
gtbs_call_status_flags_char.permissions = GATT_PERM_READ;
ccs_services.push_back(gtbs_call_status_flags_char);
ccsControlServiceInfo.call_status_flags_uuid = gtbs_call_status_flags_char.uuid;
btgatt_db_element_t gtbs_call_status_flags_desc = {};
gtbs_call_status_flags_desc.uuid = GTBS_DESCRIPTOR_UUID;
gtbs_call_status_flags_desc.type = BTGATT_DB_DESCRIPTOR;
gtbs_call_status_flags_desc.permissions = GATT_PERM_READ|GATT_PERM_WRITE;
ccs_services.push_back(gtbs_call_status_flags_desc);
btgatt_db_element_t gtbs_incomingcall_target_bearer_URI_char = {};
gtbs_incomingcall_target_bearer_URI_char.uuid = GTBS_INCOMINGCALL_TARGET_URI;
gtbs_incomingcall_target_bearer_URI_char.type = BTGATT_DB_CHARACTERISTIC;
gtbs_incomingcall_target_bearer_URI_char.properties = GATT_CHAR_PROP_BIT_READ|GATT_CHAR_PROP_BIT_NOTIFY;
gtbs_incomingcall_target_bearer_URI_char.permissions = GATT_PERM_READ;
ccs_services.push_back(gtbs_incomingcall_target_bearer_URI_char);
ccsControlServiceInfo.incoming_call_target_beareruri_uuid = gtbs_incomingcall_target_bearer_URI_char.uuid;
btgatt_db_element_t gtbs_incomingcall_target_bearer_URI_desc = {};
gtbs_incomingcall_target_bearer_URI_desc.uuid = GTBS_DESCRIPTOR_UUID;
gtbs_incomingcall_target_bearer_URI_desc.type = BTGATT_DB_DESCRIPTOR;
gtbs_incomingcall_target_bearer_URI_desc.permissions = GATT_PERM_READ|GATT_PERM_WRITE;
ccs_services.push_back(gtbs_incomingcall_target_bearer_URI_desc);
btgatt_db_element_t gtbs_incomingcall_char = {};
gtbs_incomingcall_char.uuid = GTBS_INCOMING_CALL;
gtbs_incomingcall_char.type = BTGATT_DB_CHARACTERISTIC;
gtbs_incomingcall_char.properties = GATT_CHAR_PROP_BIT_READ|GATT_CHAR_PROP_BIT_NOTIFY;
gtbs_incomingcall_char.permissions = GATT_PERM_READ;
ccs_services.push_back(gtbs_incomingcall_char);
ccsControlServiceInfo.incoming_call_uuid = gtbs_incomingcall_char.uuid;
btgatt_db_element_t gtbs_incomingcall_desc = {};
gtbs_incomingcall_desc.uuid = GTBS_DESCRIPTOR_UUID;
gtbs_incomingcall_desc.type = BTGATT_DB_DESCRIPTOR;
gtbs_incomingcall_desc.permissions = GATT_PERM_READ|GATT_PERM_WRITE;
ccs_services.push_back(gtbs_incomingcall_desc);
btgatt_db_element_t gtbs_call_termination_reason_char = {};
gtbs_call_termination_reason_char.uuid = GTBS_CALL_TERMINATION_REASON;
gtbs_call_termination_reason_char.type = BTGATT_DB_CHARACTERISTIC;
gtbs_call_termination_reason_char.properties = GATT_CHAR_PROP_BIT_NOTIFY;
ccs_services.push_back(gtbs_call_termination_reason_char);
ccsControlServiceInfo.call_termination_reason_uuid = gtbs_call_termination_reason_char.uuid;
btgatt_db_element_t gtbs_call_termination_reason_desc = {};
gtbs_call_termination_reason_desc.uuid = GTBS_DESCRIPTOR_UUID;
gtbs_call_termination_reason_desc.type = BTGATT_DB_DESCRIPTOR;
gtbs_call_termination_reason_desc.permissions = GATT_PERM_READ|GATT_PERM_WRITE;
ccs_services.push_back(gtbs_call_termination_reason_desc);
btgatt_db_element_t gtbs_call_friendly_name_char = {};
gtbs_call_friendly_name_char.uuid = GTBS_CALL_FRIENDLY_NAME;
gtbs_call_friendly_name_char.type = BTGATT_DB_CHARACTERISTIC;
gtbs_call_friendly_name_char.properties = GATT_CHAR_PROP_BIT_READ|GATT_CHAR_PROP_BIT_NOTIFY;
gtbs_call_friendly_name_char.permissions = GATT_PERM_READ;
ccs_services.push_back(gtbs_call_friendly_name_char);
ccsControlServiceInfo.call_friendly_name_uuid = gtbs_call_friendly_name_char.uuid;
btgatt_db_element_t gtbs_call_friendly_name_desc = {};
gtbs_call_friendly_name_desc.uuid = GTBS_DESCRIPTOR_UUID;
gtbs_call_friendly_name_desc.type = BTGATT_DB_DESCRIPTOR;
gtbs_call_friendly_name_desc.permissions = GATT_PERM_READ|GATT_PERM_WRITE;
ccs_services.push_back(gtbs_call_friendly_name_desc);
btgatt_db_element_t gtbs_ccid_char = {};
gtbs_ccid_char.uuid = GTBS_CONTENT_CONTROLID;
gtbs_ccid_char.type = BTGATT_DB_CHARACTERISTIC;
gtbs_ccid_char.properties = GATT_CHAR_PROP_BIT_READ;
gtbs_ccid_char.permissions = GATT_PERM_READ;
ccs_services.push_back(gtbs_ccid_char);
ccsControlServiceInfo.gtbs_ccid_uuid = gtbs_ccid_char.uuid;
return ccs_services;
}
static void OnGtbsServiceAddedCb(uint8_t status, int serverIf,
std::vector<btgatt_db_element_t> service) {
if (service[0].uuid == Uuid::From16Bit(UUID_SERVCLASS_GATT_SERVER) ||
service[0].uuid == Uuid::From16Bit(UUID_SERVCLASS_GAP_SERVER)) {
LOG(INFO) << "%s: Attempt to register restricted service"<< __func__;
return;
}
for(int i=0; i< (int)service.size(); i++) {
if (service[i].uuid == CALL_CONTROL_SERVER_UUID) {
LOG(INFO) << __func__ << " GTBS service added attr handle: " << service[i].attribute_handle;
} else if(service[i].uuid == GTBS_CALL_BEARER_NAME_UUID) {
ccsControlServiceInfo.bearer_provider_name_handle = service[i++].attribute_handle;
ccsControlServiceInfo.bearer_provider_name_desc = service[i].attribute_handle;
LOG(INFO) << __func__ << " bearer_provider_name_attr: "
<< ccsControlServiceInfo.bearer_provider_name_handle
<< " bearer_provider_name_desc: "
<< ccsControlServiceInfo.bearer_provider_name_desc;
} else if(service[i].uuid == GTBS_BEARER_TECHNOLOGY) {
ccsControlServiceInfo.bearer_technology_handle = service[i++].attribute_handle;
ccsControlServiceInfo.bearer_technology_desc = service[i].attribute_handle;
LOG(INFO) << __func__ << " bearer_technology_handle: "
<< ccsControlServiceInfo.bearer_technology_handle
<< " bearer_technology_desc: "
<< ccsControlServiceInfo.bearer_technology_desc;
} else if(service[i].uuid == GTBS_CALL_CONTROL_POINT_OPTIONAL_OPS) {
ccsControlServiceInfo.call_control_point_opcode_supported_handle =
service[i].attribute_handle;
LOG(INFO) << __func__ << " call_control_point_opcode_supported_handle register: "
<< ccsControlServiceInfo.call_control_point_opcode_supported_handle;
} else if (service[i].uuid == GTBS_CALL_STATE_UUID) {
ccsControlServiceInfo.call_state_handle = service[i++].attribute_handle;
ccsControlServiceInfo.call_state_desc = service[i].attribute_handle;
LOG(INFO) << __func__ << " call_state_handle: "
<< ccsControlServiceInfo.call_state_handle
<< " call_state_handle desc: "
<< ccsControlServiceInfo.call_state_desc;
} else if(service[i].uuid == GTBS_CALL_CONTROL_POINT_OPS) {
ccsControlServiceInfo.call_control_point_handle = service[i++].attribute_handle;
ccsControlServiceInfo.call_control_point_desc = service[i].attribute_handle;
LOG(INFO) << __func__ << " call_control_point_handle: "
<< ccsControlServiceInfo.call_control_point_handle
<< " call_control_point_desc: "
<< ccsControlServiceInfo.call_control_point_desc;
} else if(service[i].uuid == GTBS_BEARER_UCI) {
ccsControlServiceInfo.bearer_uci_handle = service[i].attribute_handle;
LOG(INFO) << __func__ << " bearer_uci_handle: "
<< ccsControlServiceInfo.bearer_uci_handle;
} else if(service[i].uuid == GTBS_BEARER_URI_SCHEMES) {
ccsControlServiceInfo.bearer_uri_schemes_supported_handle =
service[i++].attribute_handle;
ccsControlServiceInfo.bearer_uri_schemes_supported_desc =
service[i].attribute_handle;
LOG(INFO) << __func__ << " bearer_uri_schemes_supported_handle: "
<< ccsControlServiceInfo.bearer_uri_schemes_supported_handle
<< " bearer_uri_schemes_supported_desc: "
<< ccsControlServiceInfo.bearer_uri_schemes_supported_desc;
} else if(service[i].uuid == GTBS_SIGNAL_STRENGTH) {
ccsControlServiceInfo.bearer_signal_strength_handle =
service[i++].attribute_handle;
ccsControlServiceInfo.bearer_signal_strength_desc =
service[i].attribute_handle;
LOG(INFO) << __func__ << " bearer_signal_strength_handle: "
<< ccsControlServiceInfo.bearer_signal_strength_handle
<< " bearer_signal_strength_desc: "
<< ccsControlServiceInfo.bearer_signal_strength_desc;
} else if(service[i].uuid == GTBS_SIGNAL_STRENGTH_REPORTINTERVAL) {
ccsControlServiceInfo.bearer_signal_strength_report_interval_handle =
service[i].attribute_handle;
LOG(INFO) << __func__ << " bearer_signal_strength_report_interval_handle: "
<< ccsControlServiceInfo.bearer_signal_strength_report_interval_handle;
} else if(service[i].uuid == GTBS_BEARER_LIST_CURRENT_CALLS) {
ccsControlServiceInfo.bearer_list_currentcalls_handle =
service[i++].attribute_handle;
ccsControlServiceInfo.bearer_list_currentcalls_desc =
service[i].attribute_handle;
LOG(INFO) << __func__ << " bearer_list_currentcalls_handle: "
<< ccsControlServiceInfo.bearer_list_currentcalls_handle
<< " bearer_list_currentcalls_desc: "
<< ccsControlServiceInfo.bearer_list_currentcalls_desc;
} else if(service[i].uuid == GTBS_CALL_STATUS_FLAGS) {
ccsControlServiceInfo.call_status_flags_handle = service[i++].attribute_handle;
ccsControlServiceInfo.call_status_flags_desc = service[i].attribute_handle;
LOG(INFO) << __func__ << " call_status_flags_handle: "
<< ccsControlServiceInfo.call_status_flags_handle
<< " call_status_flags_desc: "
<< ccsControlServiceInfo.call_status_flags_desc;
} else if(service[i].uuid == GTBS_INCOMINGCALL_TARGET_URI) {
ccsControlServiceInfo.incoming_call_target_beareruri_handle =
service[i++].attribute_handle;
ccsControlServiceInfo.incoming_call_target_bearerURI_desc =
service[i].attribute_handle;
LOG(INFO) << __func__ << " incoming_call_target_beareruri_handle: "
<< ccsControlServiceInfo.incoming_call_target_beareruri_handle
<< " incoming_call_target_bearerURI_desc: "
<< ccsControlServiceInfo.incoming_call_target_bearerURI_desc;
} else if(service[i].uuid == GTBS_INCOMING_CALL) {
ccsControlServiceInfo.incoming_call_handle = service[i++].attribute_handle;
ccsControlServiceInfo.incoming_call_desc = service[i].attribute_handle;
LOG(INFO) << __func__ << " incoming_call_handle: "
<< ccsControlServiceInfo.incoming_call_handle
<< " incoming_call_desc: "
<< ccsControlServiceInfo.incoming_call_desc;
} else if(service[i].uuid == GTBS_CONTENT_CONTROLID) {
ccsControlServiceInfo.ccid_handle = service[i].attribute_handle;
LOG(INFO) << __func__ << " ccid_handle: " << ccsControlServiceInfo.ccid_handle;
//Declare the CC Initialization
cc_instance->CallControlInitializedCallback(0);
} else if(service[i].uuid == GTBS_CALL_TERMINATION_REASON) {
ccsControlServiceInfo.call_termination_reason_handle =
service[i++].attribute_handle;
ccsControlServiceInfo.call_termination_reason_desc =
service[i].attribute_handle;
LOG(INFO) << __func__ << " call_termination_reason_handle: "
<< ccsControlServiceInfo.call_termination_reason_handle
<< " call_termination_reason_desc: "
<< ccsControlServiceInfo.call_termination_reason_desc;
} else if(service[i].uuid == GTBS_CALL_FRIENDLY_NAME) {
ccsControlServiceInfo.call_friendly_name_handle = service[i++].attribute_handle;
ccsControlServiceInfo.call_friendly_name_desc = service[i].attribute_handle;
LOG(INFO) << __func__ << " call_friendly_name_handle: "
<< ccsControlServiceInfo.call_friendly_name_handle
<< " call_friendly_name_desc: "
<< ccsControlServiceInfo.call_friendly_name_desc;
}
}
}
void PrintData(uint8_t data[], uint16_t len) {
for (int i=0; i<len; i++) {
LOG(INFO) << __func__ << " data[" << i << "] = " << std::hex << std::setfill('0') << std::setw(2) << data[i] << std::endl;
}
}
void ReverseByteOrder(unsigned char s[], int length)
{
char revbytes_enabled[PROPERTY_VALUE_MAX] = "false";
osi_property_get("persist.bluetooth.ccp_rev", revbytes_enabled, "false");
bool revNeeded = strncmp(revbytes_enabled, "true", 4) == 0;;
if (revNeeded) {
int tmp, i, j;
for (i = 0, j = length-1; i < j; i++, j--)
{
tmp = s[i];
s[i] = s[j];
s[j] = tmp;
}
}
}
void HandleCcsEvent(uint32_t event, void* param) {
LOG(INFO) << __func__ << " event: " << bta_cc_event_str(event);
tBTA_GATTS* p_data = NULL;
tcc_resp_t *rsp = new tcc_resp_t();
if (rsp == NULL) {
LOG(INFO) << __func__ << " ccs handle return rsp not allocated ";
return;
}
std::vector<uint8_t> _data;
_data.clear();
uint8_t status = BT_STATUS_SUCCESS;
rsp->event = CCS_NONE_EVENT;
bool isCallControllerOpUsed = false;
switch (event) {
case CCS_INIT_EVENT:
{
Uuid aap_uuid = bluetooth::Uuid::GetRandom();
BTA_GATTS_AppRegister(aap_uuid, BTCcCback, true);
break;
}
case CCS_CLEANUP_EVENT:
{
//unregister APP
BTA_GATTS_AppDeregister(ccsControlServiceInfo.server_if);
cc_instance->remoteDevices.RemoveDevices();
break;
}
case BTA_GATTS_REG_EVT:
{
p_data = (tBTA_GATTS*)param;
if (p_data->reg_oper.status == BT_STATUS_SUCCESS) {
ccsControlServiceInfo.server_if = p_data->reg_oper.server_if;
std::vector<btgatt_db_element_t> service;
service = CcAddService(ccsControlServiceInfo.server_if);
if (service[0].uuid == Uuid::From16Bit(UUID_SERVCLASS_GATT_SERVER) ||
service[0].uuid == Uuid::From16Bit(UUID_SERVCLASS_GAP_SERVER)) {
LOG(INFO) << __func__ << " service app register uuid is not valid";
break;
}
LOG(INFO) << __func__ << " service app register";
BTA_GATTS_AddService(ccsControlServiceInfo.server_if, service, base::Bind(&OnGtbsServiceAddedCb));
}
break;
}
case BTA_GATTS_DEREG_EVT:
{
break;
}
case BTA_GATTS_CONF_EVT: {
p_data = (tBTA_GATTS*)param;
uint16_t conn_id = p_data->req_data.conn_id;
uint8_t status = p_data->req_data.status;
LOG(INFO) << __func__ << "conn_id :" << conn_id << "status:" << status;
if (status == BT_STATUS_SUCCESS) {
LOG(INFO) << __func__ << "Notification callback for conn_id :" << conn_id;
GattsOpsQueue::NotificationCallback(conn_id);
}
break;
}
case BTA_GATTS_CONGEST_EVT:
{
p_data = (tBTA_GATTS*)param;
CallControllerDeviceList *remoteDevice;
remoteDevice = cc_instance->remoteDevices.FindByConnId(p_data->congest.conn_id);
if(remoteDevice == NULL) {
LOG(INFO) << __func__ << " connection entry not found conn_id: "
<< p_data->congest.conn_id;
break;
}
// rsp->ConngestionOp.status = p_data->req_data.status;
rsp->remoteDevice = remoteDevice;
rsp->oper.CongestionOp.congested = p_data->congest.congested;
rsp->event = CCS_CONGESTION_UPDATE;
break;
}
case BTA_GATTS_MTU_EVT: {
p_data = (tBTA_GATTS*)param;
CallControllerDeviceList *remoteDevice;
remoteDevice = cc_instance->remoteDevices.FindByConnId(p_data->congest.conn_id);
if(remoteDevice == NULL) {
LOG(INFO) << __func__ << " connection entry not found conn_id: "
<< p_data->congest.conn_id;
break;
}
rsp->event = CCS_MTU_UPDATE;
rsp->remoteDevice = remoteDevice;
rsp->oper.MtuOp.mtu = p_data->req_data.p_data->mtu;
break;
}
case BTA_GATTS_CONNECT_EVT: {
p_data = (tBTA_GATTS*)param;
LOG(INFO) << __func__ << " remote devices connected";
/*
#if (!defined(BTA_SKIP_BLE_START_ENCRYPTION) || BTA_SKIP_BLE_START_ENCRYPTION == FALSE)
btif_gatt_check_encrypted_link(p_data->conn.remote_bda,
p_data->conn.transport);
#endif*/
CallControllerDeviceList remoteDevice;
memset(&remoteDevice, 0, sizeof(remoteDevice));
if(cc_instance->remoteDevices.FindByAddress(p_data->conn.remote_bda)) {
LOG(INFO) << __func__ << " remote devices already there is connected list";
status = BT_STATUS_FAIL;
return;
}
remoteDevice.peer_bda = p_data->conn.remote_bda;
remoteDevice.conn_id = p_data->conn.conn_id;
if(cc_instance->remoteDevices.Add(remoteDevice) == false) {
LOG(INFO) << __func__ << " remote device is not added : max connection reached";
//<TBD> need to check disconnection required
break;
}
remoteDevice.state = CCS_DISCONNECTED;
LOG(INFO) << __func__ << " remote devices connected conn_id: "<< remoteDevice.conn_id <<
"bd_addr " << remoteDevice.peer_bda;
rsp->event = CCS_CONNECTION;
rsp->remoteDevice = cc_instance->remoteDevices.FindByAddress(p_data->conn.remote_bda);
if (rsp->remoteDevice == NULL) {
LOG(INFO)<<__func__ << " remote dev is null";
break;
}
break;
}
case BTA_GATTS_DISCONNECT_EVT: {
LOG(INFO) << __func__ << " remote devices disconnected";
p_data = (tBTA_GATTS*)param;
CallControllerDeviceList *remoteDevice;
remoteDevice = cc_instance->remoteDevices.FindByConnId(p_data->conn_update.conn_id);
if((!remoteDevice) ) {
status = BT_STATUS_FAIL;
break;
}
rsp->remoteDevice->peer_bda = remoteDevice->peer_bda;
rsp->event = CCS_DISCONNECTION;
rsp->remoteDevice = remoteDevice;
break;
}
case BTA_GATTS_STOP_EVT:
//Do nothing
break;
case BTA_GATTS_DELELTE_EVT:
//Do nothing
break;
case BTA_GATTS_READ_CHARACTERISTIC_EVT: {
p_data = (tBTA_GATTS*)param;
std::vector<uint8_t> value;
CallControllerDeviceList *remoteDevice =
cc_instance->remoteDevices.FindByConnId(p_data->req_data.conn_id);
LOG(INFO) << __func__ << " charateristcs read handle " <<
p_data->req_data.p_data->read_req.handle <<" trans_id : " <<
p_data->req_data.trans_id;
if(remoteDevice == NULL) {
LOG(INFO) << __func__ << " device not found ignore read operation";
status = BT_STATUS_FAIL;
break;
}
LOG(INFO) <<" offset: " << p_data->req_data.p_data->read_req.offset <<
" long : " << p_data->req_data.p_data->read_req.is_long;
tGATTS_RSP rsp_struct;
rsp_struct.attr_value.auth_req = 0;
rsp_struct.attr_value.handle = p_data->req_data.p_data->read_req.handle;
rsp_struct.attr_value.offset = p_data->req_data.p_data->read_req.offset;
if(p_data->req_data.p_data->read_req.handle ==
ccsControlServiceInfo.call_state_handle) {
std::vector<uint8_t> loc_desc_value;
std::map<uint8_t, tCCS_CALL_STATE>::iterator it;
for (it = CallStatelist.begin(); it != CallStatelist.end(); it++){
tCCS_CALL_STATE obj = it->second;
loc_desc_value.push_back(obj.index);
loc_desc_value.push_back(obj.state);
loc_desc_value.push_back(obj.flags);
}
size_t count = std::min((size_t)GATT_MAX_ATTR_LEN, loc_desc_value.size());
rsp_struct.attr_value.len = count;
memcpy(rsp_struct.attr_value.value, loc_desc_value.data(), rsp_struct.attr_value.len);
LOG(INFO) << __func__ << " CallStateInfo read";
} else if(p_data->req_data.p_data->read_req.handle ==
ccsControlServiceInfo.call_control_point_opcode_supported_handle) {
rsp_struct.attr_value.len = sizeof(SupportedOptionalOpcodes.supp_opcode);
memcpy(rsp_struct.attr_value.value, &SupportedOptionalOpcodes.supp_opcode, rsp_struct.attr_value.len);
LOG(INFO) << __func__ << " callcontrol_point_opcode_supported_handle read";
} else if(p_data->req_data.p_data->read_req.handle ==
ccsControlServiceInfo.bearer_provider_name_handle) {
LOG(INFO) << __func__ << " BearerProviderInfo name read " << BearerProviderInfo.name;
rsp_struct.attr_value.len = strlen((char *)BearerProviderInfo.name);
LOG(INFO) << __func__ << " BearerProviderInfo name len: " <<rsp_struct.attr_value.len;
memcpy(rsp_struct.attr_value.value, BearerProviderInfo.name, rsp_struct.attr_value.len);
} else if(p_data->req_data.p_data->read_req.handle ==
ccsControlServiceInfo.bearer_list_currentcalls_handle) {
std::vector<uint8_t> loc_desc_value;
std::map<uint8_t, tCCS_BEARER_LIST_CURRENT_CALLS>::iterator it;
for (it = BlccInfolist.begin(); it != BlccInfolist.end(); it++){
tCCS_BEARER_LIST_CURRENT_CALLS obj = it->second;
loc_desc_value.push_back(obj.list_length);
loc_desc_value.push_back(obj.call_index);
loc_desc_value.push_back(obj.call_state);
loc_desc_value.push_back(obj.call_flags);
loc_desc_value.insert(loc_desc_value.end(),
obj.call_uri, obj.call_uri+(obj.list_length-3));
}
size_t count = std::min((size_t)GATT_MAX_ATTR_LEN, loc_desc_value.size());
rsp_struct.attr_value.len = count;
memcpy(rsp_struct.attr_value.value, loc_desc_value.data(), rsp_struct.attr_value.len);
LOG(INFO) << __func__ << " BlccInfo read";
} else if(p_data->req_data.p_data->read_req.handle ==
ccsControlServiceInfo.bearer_technology_handle) {
rsp_struct.attr_value.len = sizeof(BearerProviderInfo.technology_type);
memcpy(rsp_struct.attr_value.value, &BearerProviderInfo.technology_type, rsp_struct.attr_value.len);
LOG(INFO) << __func__ << " technology_type read";
} else if(p_data->req_data.p_data->read_req.handle ==
ccsControlServiceInfo.bearer_uci_handle) {
rsp_struct.attr_value.len = strlen((char *)BearerProviderInfo.uci);
memcpy(rsp_struct.attr_value.value, BearerProviderInfo.uci, rsp_struct.attr_value.len);
LOG(INFO) << __func__ << " Bearer UCI read";
} else if(p_data->req_data.p_data->read_req.handle ==
ccsControlServiceInfo.bearer_signal_strength_handle) {
rsp_struct.attr_value.len = sizeof(BearerProviderInfo.signal);
memcpy(rsp_struct.attr_value.value, &BearerProviderInfo.signal, rsp_struct.attr_value.len);
LOG(INFO) << __func__ << " signal strength read";
} else if(p_data->req_data.p_data->read_req.handle ==
ccsControlServiceInfo.bearer_signal_strength_report_interval_handle) {
rsp_struct.attr_value.len = sizeof(BearerProviderInfo.signal_report_interval);
memcpy(rsp_struct.attr_value.value, &BearerProviderInfo.signal_report_interval, rsp_struct.attr_value.len);
LOG(INFO) << __func__ << " signal_report_interval read";
} else if(p_data->req_data.p_data->read_req.handle ==
ccsControlServiceInfo.bearer_uri_schemes_supported_handle) {
rsp_struct.attr_value.len = strlen((const char*)BearerProviderInfo.bearer_schemes_list);
memcpy(rsp_struct.attr_value.value, BearerProviderInfo.bearer_schemes_list, rsp_struct.attr_value.len);
LOG(INFO) << __func__ << " bearer_schemes_list read";
}else if(p_data->req_data.p_data->read_req.handle ==
ccsControlServiceInfo.incoming_call_handle) {
rsp_struct.attr_value.len = 1 + strlen((char*)IncomingCallInfo.incoming_uri);
memcpy(rsp_struct.attr_value.value, &IncomingCallInfo, rsp_struct.attr_value.len);
LOG(INFO) << __func__ << " Incoming call read";
} else if(p_data->req_data.p_data->read_req.handle ==
ccsControlServiceInfo.incoming_call_target_beareruri_handle) {
rsp_struct.attr_value.len = 1 + strlen((char*)IncomingCallTargetUri.incoming_target_uri);
memcpy(rsp_struct.attr_value.value, &IncomingCallTargetUri, rsp_struct.attr_value.len);
LOG(INFO) << __func__ << " Incoming Call target URI read";
} else if(p_data->req_data.p_data->read_req.handle ==
ccsControlServiceInfo.ccid_handle) {
rsp_struct.attr_value.len = sizeof(CcidInfo);
memcpy(rsp_struct.attr_value.value, &CcidInfo, rsp_struct.attr_value.len);
LOG(INFO) << __func__ << " Content Control read";
} else if(p_data->req_data.p_data->read_req.handle ==
ccsControlServiceInfo.call_status_flags_handle) {
rsp_struct.attr_value.len = sizeof(StatusFlags.supported_flags);
memcpy(rsp_struct.attr_value.value, &StatusFlags.supported_flags, rsp_struct.attr_value.len);
LOG(INFO) << __func__ << " Status flags read";
} else if(p_data->req_data.p_data->read_req.handle ==
ccsControlServiceInfo.call_friendly_name_handle) {
rsp_struct.attr_value.len = 1 + strlen((char*)FriendlyName.name);
memcpy(rsp_struct.attr_value.value, &FriendlyName, rsp_struct.attr_value.len);
LOG(INFO) << __func__ << " Call friendly name read";
}else if(p_data->req_data.p_data->read_req.handle ==
ccsControlServiceInfo.call_termination_reason_handle) {
rsp_struct.attr_value.len = sizeof(TerminationReason);
memcpy(rsp_struct.attr_value.value, &TerminationReason, rsp_struct.attr_value.len);
LOG(INFO) << __func__ << " Termination Reason read";
}
else {
LOG(INFO) << __func__ << " read request for unknow handle " << p_data->req_data.p_data->read_req.handle;
status = BT_STATUS_FAIL;
break;
}
LOG(INFO) << __func__ << " read request handle " << p_data->req_data.p_data->read_req.handle <<
"connection id " << p_data->req_data.conn_id;
rsp->oper.ReadOp.char_handle = rsp_struct.attr_value.handle;
rsp->oper.ReadOp.trans_id = p_data->req_data.trans_id;
rsp->oper.ReadOp.status = BT_STATUS_SUCCESS;
rsp->event = CCS_READ_RSP;
rsp->remoteDevice = remoteDevice;
memcpy((void*)&rsp->rsp_value, &rsp_struct, sizeof(rsp_struct));
break;
}
case BTA_GATTS_READ_DESCRIPTOR_EVT: {
LOG(INFO) << __func__ << " read descriptor";
p_data = (tBTA_GATTS*)param;
LOG(INFO) << __func__ << " charateristcs read desc handle " <<
p_data->req_data.p_data->read_req.handle << " offset : "
<< p_data->req_data.p_data->read_req.offset;
CallControllerDeviceList *remoteDevice =
cc_instance->remoteDevices.FindByConnId(p_data->req_data.conn_id);
if(remoteDevice == NULL) {
LOG(INFO) << __func__ << " device not found ignore write";
status = BT_STATUS_FAIL;
break;
}
uint16_t data = 0x00;
if(p_data->req_data.p_data->read_req.handle ==
ccsControlServiceInfo.call_state_desc) {
LOG(INFO) << __func__ << " call_state_desc read";
data = remoteDevice->call_state_notify;
} else if(p_data->req_data.p_data->read_req.handle ==
ccsControlServiceInfo.call_control_point_desc) {
LOG(INFO) << __func__ << " callcontrol_point_desc read";
data = remoteDevice->call_control_point_notify;
} else if(p_data->req_data.p_data->read_req.handle ==
ccsControlServiceInfo.bearer_provider_name_desc) {
LOG(INFO) << __func__ << " bearer_provider_name_desc read";
data = remoteDevice->bearer_provider_name_notify;
} else if(p_data->req_data.p_data->read_req.handle ==
ccsControlServiceInfo.bearer_signal_strength_desc) {
LOG(INFO) << __func__ << " bearer_signal_strength desc read";
data = remoteDevice->bearer_signal_strength_notify;
} else if(p_data->req_data.p_data->read_req.handle ==
ccsControlServiceInfo.bearer_list_currentcalls_desc) {
LOG(INFO) << __func__ << " bearer_list_currentcall read";
data = remoteDevice->bearer_current_calls_list_notify;
} else if(p_data->req_data.p_data->read_req.handle ==
ccsControlServiceInfo.bearer_technology_desc) {
LOG(INFO) << __func__ << " bearer_technology_desc read";
data = remoteDevice->bearer_technology_changed_notify;
} else if(p_data->req_data.p_data->read_req.handle ==
ccsControlServiceInfo.bearer_uci_desc) {
LOG(INFO) << __func__ << " bearer_uci_desc read";
data = remoteDevice->bearer_uci_notify;
} else if(p_data->req_data.p_data->read_req.handle ==
ccsControlServiceInfo.bearer_uri_schemes_supported_desc) {
LOG(INFO) << __func__ << " bearer_uri_schemes_supported_desc read";
data = remoteDevice->bearer_uri_schemes_supported_notify;
} else if(p_data->req_data.p_data->read_req.handle ==
ccsControlServiceInfo.call_friendly_name_desc) {
LOG(INFO) << __func__ << " call_friendly_name_desc read";
data = remoteDevice->call_friendly_name_notify;
} else if(p_data->req_data.p_data->read_req.handle ==
ccsControlServiceInfo.call_control_point_opcode_supported_desc) {
LOG(INFO) << __func__ << " call_control_point_opcode_supported_desc read";
data = remoteDevice->call_control_point_opcode_supported_notify;
} else if(p_data->req_data.p_data->read_req.handle ==
ccsControlServiceInfo.call_termination_reason_desc) {
LOG(INFO) << __func__ << " call_termination_reason_desc read";
data = remoteDevice->call_termination_reason_notify;
} else if(p_data->req_data.p_data->read_req.handle ==
ccsControlServiceInfo.bearer_signal_strength_report_interval_desc) {
LOG(INFO) << __func__ << " bearer_signal_strength_report_interval_desc read";
data = remoteDevice->bearer_signal_strength_report_interval_notify;
} else {
LOG(INFO) << __func__ << " read request for unknown handle " << p_data->req_data.p_data->read_req.handle;
status = BT_STATUS_FAIL;
break;
}
rsp->rsp_value.attr_value.auth_req = 0;
rsp->rsp_value.attr_value.handle = p_data->req_data.p_data->read_req.handle;
rsp->rsp_value.attr_value.offset = p_data->req_data.p_data->read_req.offset;
*(uint16_t *)rsp->rsp_value.attr_value.value = (uint16_t)data;
rsp->rsp_value.attr_value.len = sizeof(data);
//cc response
rsp->oper.ReadDescOp.desc_handle = p_data->req_data.p_data->read_req.handle;
rsp->oper.ReadDescOp.trans_id = p_data->req_data.trans_id;
rsp->oper.ReadDescOp.status = BT_STATUS_SUCCESS;
rsp->remoteDevice = remoteDevice;
rsp->event = CCS_DESCRIPTOR_READ_RSP;
break;
}
case BTA_GATTS_WRITE_CHARACTERISTIC_EVT: {
p_data = (tBTA_GATTS*)param;
tGATT_WRITE_REQ req = p_data->req_data.p_data->write_req;
LOG(INFO) << __func__ << " write characteristics len: " << req.len;
PrintData(req.value, req.len);
CallControllerDeviceList *remoteDevice =
cc_instance->remoteDevices.FindByConnId(p_data->req_data.conn_id);
if(remoteDevice == NULL) {
LOG(INFO) << __func__ << " device not found ignore write";
status = BT_STATUS_FAIL;
break;
}
if ( status != BT_STATUS_FAIL) {
rsp->oper.WriteOp.char_handle = req.handle;
rsp->oper.WriteOp.trans_id = p_data->req_data.trans_id;
rsp->oper.WriteOp.status = BT_STATUS_SUCCESS;
rsp->remoteDevice = remoteDevice;
rsp->oper.WriteOp.need_rsp = req.need_rsp;
rsp->oper.WriteOp.offset = req.offset;
rsp->oper.WriteOp.len = req.len;
rsp->oper.WriteOp.data = (uint8_t*) malloc(sizeof(uint8_t)*req.len);
memcpy(rsp->oper.WriteOp.data, req.value, req.len);
rsp->event = CCS_WRITE_RSP;
}
break;
}
case BTA_GATTS_WRITE_DESCRIPTOR_EVT: {
p_data = (tBTA_GATTS* )param;
std::vector<uint8_t> write_desc_value;
write_desc_value.clear();
uint16_t handle = 0;
uint16_t req_value = 0;
const auto& req = p_data->req_data.p_data->write_req;
CallControllerDeviceList *remoteDevice =
cc_instance->remoteDevices.FindByConnId(p_data->req_data.conn_id);
if(remoteDevice == NULL) {
LOG(INFO) << __func__ << " device not found ignore notification";
break;
}
req_value = *(uint16_t* )req.value;
//need to initialized with proper error code
int status = BT_STATUS_SUCCESS;
LOG(INFO) << __func__ << " write descriptor :" << req.handle <<
" is resp: " << req.need_rsp << "is prep: " << req.is_prep << " value " << req_value;
if(req.handle ==
ccsControlServiceInfo.call_state_desc) {
LOG(INFO) << __func__ << " call_state_desc descriptor write";
remoteDevice->call_state_notify = req_value;
std::map<uint8_t, tCCS_CALL_STATE>::iterator it;
for (it = CallStatelist.begin(); it != CallStatelist.end(); it++){
tCCS_CALL_STATE obj = it->second;
write_desc_value.push_back(obj.index);
write_desc_value.push_back(obj.state);
write_desc_value.push_back(obj.flags);
}
handle = ccsControlServiceInfo.call_state_handle;
} else if(req.handle ==
ccsControlServiceInfo.bearer_provider_name_desc) {
remoteDevice->bearer_provider_name_notify = req_value;
LOG(INFO) << __func__ << " bearer_provider_name_desc descriptor write";
write_desc_value.assign(BearerProviderInfo.name,
BearerProviderInfo.name + strlen((char*)BearerProviderInfo.name));
handle = ccsControlServiceInfo.bearer_provider_name_handle;
} else if(req.handle ==
ccsControlServiceInfo.call_control_point_desc) {
LOG(INFO) << __func__ << " callcontrol_point_desc write";
write_desc_value.push_back(CallControllerResp.opcode);
write_desc_value.push_back(CallControllerResp.index);
write_desc_value.push_back(CallControllerResp.response_status);
remoteDevice->call_control_point_notify = req_value;
handle = ccsControlServiceInfo.call_control_point_handle;
} else if(req.handle ==
ccsControlServiceInfo.bearer_signal_strength_desc) {
LOG(INFO) << __func__ << " bearer_signal_strength desc write";
write_desc_value.push_back(BearerProviderInfo.signal);
remoteDevice->bearer_signal_strength_notify = req_value;
handle = ccsControlServiceInfo.bearer_signal_strength_handle;
} else if(req.handle ==
ccsControlServiceInfo.bearer_uri_schemes_supported_desc) {
remoteDevice->bearer_uri_schemes_supported_notify = req_value;
write_desc_value.assign(BearerProviderInfo.bearer_schemes_list,
BearerProviderInfo.bearer_schemes_list + strlen((char*)BearerProviderInfo.bearer_schemes_list));
LOG(INFO) << __func__ << " bearer_schemes_list Desc write";
} else if(req.handle ==
ccsControlServiceInfo.bearer_list_currentcalls_desc) {
std::map<uint8_t, tCCS_BEARER_LIST_CURRENT_CALLS>::iterator it;
LOG(INFO) << __func__ << " bearer_list_currentcall desc write";
for (it = BlccInfolist.begin(); it != BlccInfolist.end(); it++){
tCCS_BEARER_LIST_CURRENT_CALLS obj = it->second;
write_desc_value.push_back(obj.list_length);
write_desc_value.push_back(obj.call_index);
write_desc_value.push_back(obj.call_state);
write_desc_value.push_back(obj.call_flags);
write_desc_value.insert(write_desc_value.end(),
obj.call_uri, obj.call_uri+(obj.list_length-3));
}
remoteDevice->bearer_current_calls_list_notify = req_value;
handle = ccsControlServiceInfo.bearer_list_currentcalls_handle;
} else if(req.handle ==
ccsControlServiceInfo.bearer_technology_desc) {
LOG(INFO) << __func__ << " bearer_technology_desc write";
remoteDevice->bearer_technology_changed_notify = req_value;
write_desc_value.push_back(BearerProviderInfo.technology_type);
handle = ccsControlServiceInfo.bearer_technology_handle;
} else if(req.handle ==
ccsControlServiceInfo.call_friendly_name_desc) {
LOG(INFO) << __func__ << " call_friendly_name_desc read";
remoteDevice->call_friendly_name_notify = req_value;
int len = 1 + strlen((char*)FriendlyName.name);
write_desc_value.assign((uint8_t*)&FriendlyName, (uint8_t*)&FriendlyName+len);
handle = ccsControlServiceInfo.call_friendly_name_handle;
} else if(req.handle ==
ccsControlServiceInfo.call_termination_reason_desc) {
LOG(INFO) << __func__ << " call_termination_reason_desc write";
remoteDevice->call_termination_reason_notify = req_value;
handle = ccsControlServiceInfo.call_termination_reason_handle;
write_desc_value.push_back(TerminationReason.index);
write_desc_value.push_back(TerminationReason.reason);
handle = ccsControlServiceInfo.call_termination_reason_handle;
} else if(req.handle ==
ccsControlServiceInfo.call_status_flags_desc) {
LOG(INFO) << __func__ << " Status Flags Desc write";
remoteDevice->status_flags_notify= req_value;
write_desc_value.push_back(StatusFlags.supported_flags);
handle = ccsControlServiceInfo.call_status_flags_handle;
} else if(req.handle ==
ccsControlServiceInfo.incoming_call_target_bearerURI_desc) {
LOG(INFO) << __func__ << " Incoming target bearer desc write";
int len = 1 + strlen((char*)IncomingCallTargetUri.incoming_target_uri);
write_desc_value.assign((uint8_t*)&IncomingCallTargetUri, (uint8_t*)&IncomingCallTargetUri+len);
remoteDevice->incoming_call_target_URI_notify= req_value;
handle = ccsControlServiceInfo.incoming_call_target_beareruri_handle;
} else if(req.handle ==
ccsControlServiceInfo.incoming_call_desc) {
LOG(INFO) << __func__ << " Incoming Call desc write";
remoteDevice->incoming_call_state_notify = req_value;
int len = 1 + strlen((char*)IncomingCallInfo.incoming_uri);
write_desc_value.assign((uint8_t*)&IncomingCallInfo, (uint8_t*)&IncomingCallInfo+len);
handle = ccsControlServiceInfo.incoming_call_handle;
} else {
LOG(INFO) << __func__ << " descriptor write not matched";
status = 4; //check error code
}
rsp->oper.WriteDescOp.desc_handle = req.handle;
rsp->oper.WriteDescOp.char_handle = handle;
rsp->oper.WriteDescOp.trans_id = p_data->req_data.trans_id;
rsp->oper.WriteDescOp.status = status;
rsp->oper.WriteDescOp.need_rsp = req.need_rsp;
rsp->oper.WriteDescOp.notification = req_value;
rsp->oper.WriteDescOp.value = std::move(write_desc_value);
rsp->event = CCS_DESCRIPTOR_WRITE_RSP;
rsp->remoteDevice = remoteDevice;
break;
}
case BTA_GATTS_EXEC_WRITE_EVT: {
p_data = (tBTA_GATTS*)param;
break;
}
case BTA_GATTS_CLOSE_EVT: {
//not required
break;
}
case BTA_GATTS_PHY_UPDATE_EVT: {
p_data = (tBTA_GATTS*)param;
CallControllerDeviceList *remoteDevice =
cc_instance->remoteDevices.FindByConnId(p_data->phy_update.conn_id);
if(remoteDevice == NULL) {
LOG(INFO) << __func__ << " device not found ignore phy update "
<< p_data->phy_update.status;
status = BT_STATUS_FAIL;
break;
}
rsp->event = CCS_PHY_UPDATE;
rsp->oper.PhyOp.rx_phy = p_data->phy_update.rx_phy;
rsp->oper.PhyOp.tx_phy = p_data->phy_update.tx_phy;
rsp->remoteDevice = remoteDevice;
break;
}
case BTA_GATTS_CONN_UPDATE_EVT: {
p_data = (tBTA_GATTS*)param;
CallControllerDeviceList *remoteDevice =
cc_instance->remoteDevices.FindByConnId(p_data->phy_update.conn_id);
if(remoteDevice == NULL) {
LOG(INFO) << __func__ << " connection update device not found";
break;
}
LOG(INFO) << __func__ << " connection update status " << p_data->phy_update.status;
rsp->event = CCS_CONNECTION_UPDATE;
rsp->oper.ConnectionUpdateOp.remoteDevice = remoteDevice;
rsp->oper.ConnectionUpdateOp.remoteDevice->latency = p_data->conn_update.latency;
rsp->oper.ConnectionUpdateOp.remoteDevice->timeout = p_data->conn_update.timeout;
rsp->oper.ConnectionUpdateOp.remoteDevice->interval = p_data->conn_update.interval;
rsp->oper.ConnectionUpdateOp.status = p_data->conn_update.status;
rsp->remoteDevice = remoteDevice;
break;
}
case CCS_ACTIVE_DEVICE_UPDATE:
{
tCCS_SET_ACTIVE_DEVICE *data = (tCCS_SET_ACTIVE_DEVICE *)param;
LOG(INFO) << __func__ << " CCS_ACTIVE_DEVICE_UPDATE address " << data->address;
if (cc_instance->remoteDevices.FindByAddress(data->address) != NULL) {
cc_instance->remoteDevices.AddSetActiveDevice(data);
} else {
LOG(ERROR) << __func__ << " CCS_ACTIVE_DEVICE_UPDATE failed as given remote is not registered for notif " << data->address;
}
break;
}
case CCS_CONNECTION_CLOSE_EVENT:
{
break;
}
case CCS_CALL_STATE_UPDATE:
{
std::map<uint8_t, tCCS_CALL_STATE>::iterator it;
for (it = CallStatelist.begin(); it != CallStatelist.end(); it++){
tCCS_CALL_STATE obj = it->second;
_data.push_back(obj.index);
_data.push_back(obj.state);
_data.push_back(obj.flags);
}
rsp->event = CCS_NOTIFY_ALL;
rsp->handle = ccsControlServiceInfo.call_state_handle;
isCallControllerOpUsed = true;
break;
}
case CCS_BEARER_NAME_UPDATE:
{
LOG(INFO) << __func__ << " CCS_BEARER_NAME_UPDATE";
tCCS_BEARER_PROVIDER_INFO *data = (tCCS_BEARER_PROVIDER_INFO*) param;
uint16_t len = strlen((char*)data->name);
ReverseByteOrder(data->name, len);
memcpy(BearerProviderInfo.name, data->name, len);
rsp->event = CCS_NOTIFY_ALL;
rsp->handle = ccsControlServiceInfo.bearer_provider_name_handle;
_data.assign(BearerProviderInfo.name,
BearerProviderInfo.name + len);
isCallControllerOpUsed = true;
break;
}
case CCS_OPT_OPCODES:
{
LOG(INFO) << __func__ << " CCS_OPT_OPCODES";
tCCS_SUPP_OPTIONAL_OPCODES *data = (tCCS_SUPP_OPTIONAL_OPCODES*) param;
SupportedOptionalOpcodes.supp_opcode = data->supp_opcode;
rsp->event = CCS_NOTIFY_ALL;
rsp->handle = ccsControlServiceInfo.call_control_point_opcode_supported_handle;
_data.push_back(SupportedOptionalOpcodes.supp_opcode);
isCallControllerOpUsed = true;
break;
}
case CCS_BEARER_CURRENT_CALL_LIST_UPDATE:
{
LOG(INFO) << __func__ << " CCS_BEARER_CURRENT_CALL_LIST_UPDATE";
std::map<uint8_t, tCCS_BEARER_LIST_CURRENT_CALLS>::iterator it;
for (it = BlccInfolist.begin(); it != BlccInfolist.end(); it++){
tCCS_BEARER_LIST_CURRENT_CALLS obj = it->second;
_data.push_back(obj.list_length);
_data.push_back(obj.call_index);
_data.push_back(obj.call_state);
_data.push_back(obj.call_flags);
_data.insert(_data.end(),
obj.call_uri, obj.call_uri+(obj.list_length-3));
}
rsp->event = CCS_NOTIFY_ALL;
rsp->handle = ccsControlServiceInfo.bearer_list_currentcalls_handle;
isCallControllerOpUsed = true;
break;
}
case CCS_BEARER_SIGNAL_STRENGTH_UPDATE:
{
LOG(INFO) << __func__ << " CCS_BEARER_SIGNAL_STRENGTH_UPDATE";
tCCS_BEARER_PROVIDER_INFO *data = (tCCS_BEARER_PROVIDER_INFO *) param;
BearerProviderInfo.signal = data->signal;
rsp->event = CCS_NOTIFY_ALL;
rsp->handle = ccsControlServiceInfo.bearer_signal_strength_handle;
//control whether notification has to happen based
//on reporting Interval time or not
rsp->force = false;
_data.push_back(BearerProviderInfo.signal);
isCallControllerOpUsed = true;
break;
}
case CCS_BEARER_TECHNOLOGY_UPDATE:
{
LOG(INFO) << __func__ << " CCS_BEARER_TECHNOLOGY_UPDATE";
tCCS_BEARER_PROVIDER_INFO *data = (tCCS_BEARER_PROVIDER_INFO *) param;
BearerProviderInfo.technology_type = data->technology_type;
rsp->event = CCS_NOTIFY_ALL;
rsp->handle = ccsControlServiceInfo.bearer_technology_handle;
_data.push_back(BearerProviderInfo.technology_type);
isCallControllerOpUsed = true;
break;
}
case CCS_BEARER_URI_SCHEMES_SUPPORTED: {
LOG(INFO) << __func__ << " CCS_BEARER_URI_SCHEMES_SUPPORTED";
tCCS_BEARER_PROVIDER_INFO *data = (tCCS_BEARER_PROVIDER_INFO*) param;
BearerProviderInfo.bearer_list_len = data->bearer_list_len;
LOG(INFO) << __func__ << " CCS_BEARER_URI_SCHEMES_SUPPORTED: len " <<BearerProviderInfo.bearer_list_len;
ReverseByteOrder(data->bearer_schemes_list, BearerProviderInfo.bearer_list_len);
memcpy(BearerProviderInfo.bearer_schemes_list, data->bearer_schemes_list, BearerProviderInfo.bearer_list_len);
rsp->event = CCS_NOTIFY_ALL;
rsp->handle = ccsControlServiceInfo.bearer_uri_schemes_supported_handle;
isCallControllerOpUsed = true;
_data.assign(BearerProviderInfo.bearer_schemes_list,
BearerProviderInfo.bearer_schemes_list + BearerProviderInfo.bearer_list_len);
isCallControllerOpUsed = true;
break;
}
case CCS_INCOMING_CALL_UPDATE:
{
LOG(INFO) << __func__ << " CCS_INCOMING_CALL_UPDATE";
tCCS_INCOMING_CALL* data = (tCCS_INCOMING_CALL *) param;
IncomingCallInfo.index = data->index;
uint16_t len = strlen((char*)data->incoming_uri);
ReverseByteOrder(data->incoming_uri, len);
memcpy(IncomingCallInfo.incoming_uri, data->incoming_uri, len);
rsp->event = CCS_NOTIFY_ALL;
rsp->handle = ccsControlServiceInfo.incoming_call_handle;
_data.push_back(IncomingCallInfo.index);
_data.insert(_data.end(), IncomingCallInfo.incoming_uri,
IncomingCallInfo.incoming_uri + len);
isCallControllerOpUsed = true;
break;
}
case CCS_INCOMING_TARGET_URI_UPDATE:
{
LOG(INFO) << __func__ << " CCS_INCOMING_TARGET_URI_UPDATE";
tCCS_INCOMING_CALL_URI* data = (tCCS_INCOMING_CALL_URI *) param;
IncomingCallTargetUri.index = data->index;
uint16_t len = strlen((char*)data->incoming_target_uri);
LOG(INFO) << __func__ << " CCS_INCOMING_TARGET_URI_UPDATE: urilen " << len;
ReverseByteOrder(data->incoming_target_uri, len);
memcpy(IncomingCallTargetUri.incoming_target_uri, data->incoming_target_uri, len);
rsp->event = CCS_NOTIFY_ALL;
rsp->handle = ccsControlServiceInfo.incoming_call_target_beareruri_handle;
_data.push_back(IncomingCallTargetUri.index);
_data.insert(_data.end(), IncomingCallTargetUri.incoming_target_uri,
IncomingCallTargetUri.incoming_target_uri + len);
isCallControllerOpUsed = true;
break;
}
case CCS_TERMINATION_REASON_UPDATE:
{
LOG(INFO) << __func__ << " CCS_TERMINATION_REASON_UPDATE";
tCCS_TERM_REASON* data = (tCCS_TERM_REASON *) param;
TerminationReason.index = data->index;
TerminationReason.reason = data->reason;
rsp->event = CCS_NOTIFY_ALL;
rsp->handle = ccsControlServiceInfo.call_termination_reason_handle;
_data.push_back(TerminationReason.index);
_data.push_back(TerminationReason.reason);
isCallControllerOpUsed = true;
break;
}
case CCS_STATUS_FLAGS_UPDATE:
{
LOG(INFO) << __func__ << " CCS_STATUS_FLAGS_UPDATE";
tCCS_STATUS_FLAGS *data = (tCCS_STATUS_FLAGS*) param;
ReverseByteOrder((unsigned char*)&data->supported_flags, sizeof(data->supported_flags));
StatusFlags.supported_flags = data->supported_flags;
rsp->event = CCS_NOTIFY_ALL;
rsp->handle = ccsControlServiceInfo.call_status_flags_handle;
_data.push_back(StatusFlags.supported_flags);
isCallControllerOpUsed = true;
break;
}
case CCS_CCID_UPDATE:
{
LOG(INFO) << __func__ << " CCS_CCID_UPDATE";
tCCS_CONTENT_CONTROL_ID *data = (tCCS_CONTENT_CONTROL_ID *) param;
ReverseByteOrder((unsigned char*)&data->ccid, sizeof(data->ccid));
CcidInfo.ccid = (uint32_t)data->ccid;
rsp->event = CCS_NOTIFY_ALL;
rsp->handle = ccsControlServiceInfo.ccid_handle;
_data.push_back(CcidInfo.ccid);
isCallControllerOpUsed = true;
break;
}
case CCS_CALL_CONTROL_RESPONSE:
{
LOG(INFO) << __func__ << " CCS_CALL_CONTROL_RESPONSE";
rsp->event = CCS_NOTIFY_ALL;
rsp->handle = ccsControlServiceInfo.call_control_point_handle;
_data.push_back(CallControllerResp.opcode);
_data.push_back(CallControllerResp.index);
_data.push_back(CallControllerResp.response_status);
isCallControllerOpUsed = true;
break;
}
default:
LOG(INFO) << __func__ << " event not matched !!";
break;
}
if(rsp->event != CCS_NONE_EVENT) {
if (isCallControllerOpUsed == true) {
rsp->oper.CallControllerOp.data = std::move(_data);
LOG(INFO) << __func__ << " After Moving size " << rsp->oper.CallControllerOp.data.size();
}
CCSHandler(rsp->event, rsp);
}
if(rsp) {
LOG(INFO) << __func__ << "free rsp data";
free(rsp);
}
}
void BTCcCback(tBTA_GATTS_EVT event, tBTA_GATTS* param) {
HandleCcsEvent((uint32_t)event, param);
}
bool DeviceStateConnectionHandler(uint32_t event, void* param) {
LOG(INFO) << __func__ << " device connected handle " << event;
tcc_resp_t *p_data = (tcc_resp_t *) param;
switch (event) {
case CCS_NOTIFY_ALL: {
LOG(INFO) << __func__ << " device notify all";
if (p_data->handle == ccsControlServiceInfo.bearer_signal_strength_handle) {
if (p_data->force == false &&
p_data->remoteDevice->signal_strength_report_interval != 0) {
LOG(INFO) << __func__ << "Not a timer expired push, dont notify to remote";
break;
}
}
GattsOpsQueue::SendNotification(p_data->remoteDevice->conn_id, p_data->handle,
p_data->oper.CallControllerOp.data, false);
break;
}
case CCS_READ_RSP:
LOG(INFO) << __func__ << " device CCS_READ_RSP update " << event;
BTA_GATTS_SendRsp(p_data->remoteDevice->conn_id, p_data->oper.ReadOp.trans_id,
BT_STATUS_SUCCESS, &p_data->rsp_value);
break;
case CCS_DESCRIPTOR_READ_RSP:
LOG(INFO) << __func__ << " device CCS_DESCRIPTOR_READ_RSP update " << event;
BTA_GATTS_SendRsp(p_data->remoteDevice->conn_id, p_data->oper.ReadDescOp.trans_id,
BT_STATUS_SUCCESS, &p_data->rsp_value);
break;
case CCS_DESCRIPTOR_WRITE_RSP:
{
LOG(INFO) << __func__ << " device CCS_DESCRIPTOR_WRITE_RSP update rsp: " << p_data->oper.WriteDescOp.need_rsp;
tGATTS_RSP rsp_struct;
rsp_struct.attr_value.handle = p_data->rsp_value.attr_value.handle;
rsp_struct.attr_value.offset = p_data->rsp_value.attr_value.offset;
if (p_data->remoteDevice->congested == false &&
p_data->oper.WriteDescOp.need_rsp) {
//send rsp to write
LOG(INFO) << __func__ << " gett send rsp";
BTA_GATTS_SendRsp(p_data->remoteDevice->conn_id, p_data->oper.WriteDescOp.trans_id,
p_data->oper.WriteDescOp.status, &rsp_struct);
}
if (!p_data->oper.WriteDescOp.status && p_data->oper.WriteDescOp.notification) {
//notify update to register device
GattsOpsQueue::SendNotification(p_data->remoteDevice->conn_id,
p_data->oper.WriteDescOp.char_handle,
p_data->oper.WriteDescOp.value, false);
} else {
LOG(INFO) << __func__ << " notification disable handle : " << p_data->oper.WriteDescOp.char_handle;
}
break;
}
case CCS_WRITE_RSP: {
LOG(INFO) << __func__ << " device CCS_WRITE_RSP update " << event;
bool need_rsp = p_data->oper.WriteOp.need_rsp;
LOG(INFO) << __func__ << " device CCS_WRITE_RSP update " << event << " need_rsp: " <<need_rsp;
if (need_rsp) {
BTA_GATTS_SendRsp(p_data->remoteDevice->conn_id, p_data->oper.WriteOp.trans_id,
BT_STATUS_SUCCESS, &p_data->rsp_value);
}
break;
}
case CCS_CONNECTION_UPDATE: {
LOG(INFO) << __func__ << " device cconnection update " << event;
break;
}
case CCS_PHY_UPDATE: {
LOG(INFO) << __func__ << " device CCS_PHY_UPDATE update " << event;
p_data->remoteDevice->rx_phy = p_data->oper.PhyOp.rx_phy;
p_data->remoteDevice->tx_phy = p_data->oper.PhyOp.tx_phy;
break;
}
case CCS_MTU_UPDATE: {
LOG(INFO) << __func__ << " device CCS_MTU_UPDATE update " << event;
p_data->remoteDevice->mtu = p_data->oper.MtuOp.mtu;
break;
}
case CCS_CONGESTION_UPDATE: {
LOG(INFO) << __func__ << ": device CCS_CONGESTION_UPDATE update: " << event;
CcpCongestionUpdate(p_data);
break;
}
case CCS_DISCONNECTION: {
LOG(INFO) << __func__ << " device CCS_DISCONNECTION remove " << event;
cc_instance->remoteDevices.Remove(p_data->remoteDevice->peer_bda);
cc_instance->ConnectionStateCallback(CCS_DISCONNECTED, p_data->remoteDevice->peer_bda);
break;
}
case CCS_CONNECTION_CLOSE_EVENT: {
LOG(INFO) << __func__ << " device connection closing";
// Close active connection
if (p_data->remoteDevice->conn_id != 0)
BTA_GATTS_Close(p_data->remoteDevice->conn_id);
else
BTA_GATTS_CancelOpen(ccsControlServiceInfo.server_if, p_data->remoteDevice->peer_bda, true);
// Cancel pending background connections
BTA_GATTS_CancelOpen(ccsControlServiceInfo.server_if, p_data->remoteDevice->peer_bda, false);
break;
}
case CCS_BOND_STATE_CHANGE_EVENT:
LOG(INFO) << __func__ << " Bond state change";
cc_instance->remoteDevices.Remove(p_data->remoteDevice->peer_bda);
break;
default:
LOG(INFO) << __func__ << " event not matched";
break;
}
return BT_STATUS_SUCCESS;
}
bool DeviceStateDisconnectedHandler(uint32_t event, void* param) {
LOG(INFO) << __func__ << " device disconnected handle " << event;
tcc_resp_t *p_data = (tcc_resp_t *) param;
switch (event) {
case CCS_CONNECTION:
{
LOG(INFO) << __func__ << " connection processing " << event;
p_data->remoteDevice->state = CCS_CONNECTED;
p_data->remoteDevice->call_state_notify = 0x00;
p_data->remoteDevice->bearer_provider_name_notify = 0x00;
p_data->remoteDevice->call_control_point_notify = 0x00;
p_data->remoteDevice->bearer_technology_changed_notify = 0x00;
p_data->remoteDevice->bearer_uci_notify = 0x00;
p_data->remoteDevice->bearer_current_calls_list_notify = 0x00;
p_data->remoteDevice->call_friendly_name_notify = 0x00;
p_data->remoteDevice->call_termination_reason_notify = 0x00;
p_data->remoteDevice->congested = false;
// p_data->remoteDevice->conn_id;
p_data->remoteDevice->timeout = 0;
p_data->remoteDevice->latency = 0;
p_data->remoteDevice->interval = 0;
p_data->remoteDevice->rx_phy = 0;
p_data->remoteDevice->tx_phy = 0;
cc_instance->ConnectionStateCallback(CCS_CONNECTED, p_data->remoteDevice->peer_bda);
break;
}
case CCS_CONGESTION_UPDATE: {
LOG(INFO) << __func__ << ": device CCS_CONGESTION_UPDATE update: " << event;
CcpCongestionUpdate(p_data);
break;
}
case CCS_MTU_UPDATE:
case CCS_PHY_UPDATE:
case CCS_DISCONNECTED:
case CCS_READ_RSP:
case CCS_DESCRIPTOR_READ_RSP:
case CCS_WRITE_RSP:
case CCS_DESCRIPTOR_WRITE_RSP:
case CCS_NOTIFY_ALL:
case CCS_DISCONNECTION:
default:
//ignore event
LOG(INFO) << __func__ << " Ignore event " << event;
break;
}
return BT_STATUS_SUCCESS;
}
bool is_digits(const std::string &str)
{
return str.find_first_not_of("0123456789+") == std::string::npos;
}
bool IsValidOriginateUri(std::string uri) {
bool ret = false;
std::vector<std::string> out;
char *token;
char* rest = const_cast<char*>(uri.c_str());
while ((token = strtok_r(rest, ":", &rest)))
{
out.push_back(std::string(token));
}
if (out.size() == 2) {
if (out[0].compare("tel") == 0 && is_digits(out[1])) {
ret = true;
}
}
LOG(INFO) << __func__ << " ret: " << ret;
return ret;
}
bool CCSActiveProfile(RawAddress addr) {
bool isCCSActiveProfile = false;
int32_t activeProfile;
activeProfile = osi_property_get_int32("persist.vendor.qcom.bluetooth.default_profiles",0);
if ((activeProfile&0x2000) == 0x2000) {
isCCSActiveProfile = true;
}
LOG(INFO) << __func__ << " activeProfile "<< activeProfile <<" for" << addr;
return isCCSActiveProfile;
}
bool CCSHandler(uint32_t event, void* param) {
tcc_resp_t *p_data = (tcc_resp_t *)param;
CallControllerDeviceList *device = p_data->remoteDevice;
LOG(INFO) << __func__ << " inactive ccs handle event "<< bta_cc_event_str(event);
switch(p_data->event) {
case CCS_NOTIFY_ALL: {
std::vector<CallControllerDeviceList>notifyDevices = cc_instance->remoteDevices.FindNotifyDevices(p_data->handle);
std::vector<CallControllerDeviceList>::iterator it;
LOG(INFO) << __func__ << " Notify all handle "<< p_data->handle;
if (notifyDevices.size() <= 0) {
LOG(INFO) << __func__ << " No device register for notification";
break;
}
for (it = notifyDevices.begin(); it != notifyDevices.end(); it++){
if (CCSActiveProfile(it->peer_bda)) {
LOG(INFO) << __func__ << " Notify all handle device id " << it->conn_id;
p_data->remoteDevice = cc_instance->remoteDevices.FindByConnId(it->conn_id);
it->DeviceStateHandlerPointer[it->state](p_data->event, p_data);
}
}
break;
}
case CCS_WRITE_RSP: {
LOG(INFO) << __func__ << " Push Write response first: " << device->state;
device = p_data->remoteDevice;
device->DeviceStateHandlerPointer[device->state](p_data->event, p_data);
//Process the values now
uint8_t* data = p_data->oper.WriteOp.data;
int len = p_data->oper.WriteOp.len;
RawAddress peer_bda = p_data->remoteDevice->peer_bda;
std::map<uint8_t, tCCS_CALL_STATE>::iterator it;
bool valid_index = false;
uint8_t indices[10];
char URI[MAX_URI_SIZE];
int i;
uint32_t handle = p_data->oper.WriteOp.char_handle;
if(handle == ccsControlServiceInfo.call_control_point_handle) {
CallControllerOps.operation = data[0];
LOG(INFO) << __func__ << " operation: " << std::hex << CallControllerOps.operation;
if (gIsActiveCC == true && !cc_instance->remoteDevices.FindActiveDevice(p_data->remoteDevice) &&
(CallControllerOps.operation == CALL_TERMINATE ||
CallControllerOps.operation == CALL_LOCAL_HOLD ||
CallControllerOps.operation == CALL_LOCAL_RETRIEVE)) {
LOG(ERROR) << __func__ << "TERM|HOLD|RET|JOIN triggered from non-active Device";
cc_instance->CallControlResponse(CallControllerOps.operation,
CCS_DEFAULT_INDEX_VAL,
CCS_OPCODE_UNSUCCESSFUL, peer_bda);
return true;
}
switch(CallControllerOps.operation) {
case CALL_ACCEPT:{
if (len != 2) {
LOG(ERROR) << __func__ << " Invalid params";
valid_index = false;
} else {
indices[0] = data[1];
valid_index = false;
for (i=0,it = CallStatelist.begin(); it != CallStatelist.end(); it++, i++){
tCCS_CALL_STATE obj = it->second;
if (obj.index == indices[0] && obj.state == CCS_STATE_INCOMING) {
valid_index = true;
break;
}
}
}
if (valid_index == true) {
cc_instance->CallControlPointChange(CallControllerOps.operation, indices,
DEFAULT_INDICIES_COUNT, NULL,
device->peer_bda);
cc_instance->CallControlResponse(CallControllerOps.operation,
indices[0],
CCS_STATUS_SUCCESS, peer_bda);
} else {
LOG(INFO) << " ACCEPT ignored as there is no valid Index";
cc_instance->CallControlResponse(CallControllerOps.operation,
CCS_DEFAULT_INDEX_VAL,
CCS_INVALID_INDEX, peer_bda);
}
break;
}
case CALL_TERMINATE: {
if (len != 2) {
LOG(ERROR) << __func__ << " Invalid params";
valid_index = false;
} else {
indices[0] = data[1];
valid_index = false;
for (i=0,it = CallStatelist.begin(); it != CallStatelist.end(); it++, i++) {
tCCS_CALL_STATE obj = it->second;
if (obj.index == indices[0]) {
LOG(INFO) << __func__ << " call index match: " << indices[0];
valid_index = true;
break;
}
}
}
if (valid_index == true) {
cc_instance->CallControlPointChange(CallControllerOps.operation, indices,
DEFAULT_INDICIES_COUNT, NULL,
device->peer_bda);
cc_instance->CallControlResponse(CallControllerOps.operation,
indices[0],
CCS_STATUS_SUCCESS, peer_bda);
gIsTerminatedInitiatedFromClient = true;
gTerminateIntiatedIndex = indices[0];
} else {
LOG(INFO) << " TERMINATE ignored as there is no valid Index";
cc_instance->CallControlResponse(CallControllerOps.operation,
CCS_DEFAULT_INDEX_VAL,
CCS_INVALID_INDEX, peer_bda);
}
break;
}
case CALL_LOCAL_HOLD: {
if (len != 2) {
LOG(ERROR) << __func__ << " Invalid params";
valid_index = false;
} else {
indices[0]= data[1];
valid_index = false;
for (i=0,it = CallStatelist.begin(); it != CallStatelist.end(); it++, i++) {
tCCS_CALL_STATE obj = it->second;
if (obj.index == indices[0] &&
(obj.state == CCS_STATE_INCOMING || obj.state == CCS_STATE_ACTIVE)) {
LOG(INFO) << __func__ << " call index match: " << indices[0];
valid_index = true;
break;
}
}
}
if (valid_index == true) {
cc_instance->CallControlPointChange(CallControllerOps.operation, indices,
DEFAULT_INDICIES_COUNT, NULL,
device->peer_bda);
} else {
LOG(INFO) << " CALL_LOCAL_HOLD ignored as there is no valid Index";
cc_instance->CallControlResponse(CallControllerOps.operation,
CCS_DEFAULT_INDEX_VAL,
CCS_INVALID_INDEX, peer_bda);
}
break;
}
case CALL_LOCAL_RETRIEVE: {
if (len != 2) {
LOG(ERROR) << __func__ << " Invalid params";
valid_index = false;
} else {
indices[0]= data[1];
valid_index = false;
for (i=0,it = CallStatelist.begin(); it != CallStatelist.end(); it++, i++) {
tCCS_CALL_STATE obj = it->second;
if (obj.index == indices[0] && (obj.state == CCS_STATE_LOCAL_HELD )) {
LOG(INFO) << __func__ << " call index match: " << indices[0];
valid_index = true;
break;
}
}
}
if (valid_index == true) {
cc_instance->CallControlPointChange( CallControllerOps.operation, indices,
DEFAULT_INDICIES_COUNT, NULL,
device->peer_bda);
} else {
LOG(INFO) << " CALL_LOCAL_RETRIEVE ignored as there is no valid Index";
cc_instance->CallControlResponse(CallControllerOps.operation,
CCS_DEFAULT_INDEX_VAL,
CCS_INVALID_INDEX, peer_bda);
}
break;
}
case CALL_ORIGINATE: {
LOG(INFO) << __func__ << " CALL_ORIGINATE match:";
memset(URI, '\0', sizeof(char)*MAX_URI_SIZE);
strlcpy(URI, (char*)&data[1], len);
LOG(INFO) << __func__ << " ORIGINATE: " << URI;
if (IsValidOriginateUri(URI)) {
cc_instance->CallControlPointChange(CallControllerOps.operation, /*unused*/0,
/*count*/0, URI, device->peer_bda);
} else {
cc_instance->CallControlResponse(CallControllerOps.operation,
CCS_DEFAULT_INDEX_VAL,
CCS_INVALID_OUTGOING_URI, peer_bda);
}
break;
}
case CALL_JOIN: {
int count = len-1;
uint8_t *start_of_indicies = &(data[1]);
uint8_t indices[MAX_CCS_CONNECTION];
valid_index = true;
bool atleastOneHeldCall = false;
for (int i=0; i<count; i++) {
indices[i] = start_of_indicies[i];
LOG(INFO) << __func__ << " Indicies: " << i << ": " <<indices[i];
std::map<uint8_t, tCCS_CALL_STATE>::iterator j = CallStatelist.find(indices[i]);
if (j == CallStatelist.end()) {
valid_index = false;
break;
} else if (j->second.state == CCS_STATE_LOCAL_HELD) {
atleastOneHeldCall = true;
}
}
if (CallStatelist.size() < 2 || atleastOneHeldCall == false) {
LOG(INFO) << __func__ << " Join is not valid: ";
valid_index = false;
}
if (count > 1 && valid_index == true) {
cc_instance->CallControlPointChange(CallControllerOps.operation,
indices, count,
NULL, device->peer_bda);
} else {
LOG(INFO) << __func__ << " no valid indices found for JOIN operation ";
cc_instance->CallControlResponse(CallControllerOps.operation,
CCS_DEFAULT_INDEX_VAL,
CCS_INVALID_INDEX, peer_bda);
}
break;
}
default:
LOG(ERROR) << __func__ << " Unhandled Event: " << CallControllerOps.operation;
cc_instance->CallControlResponse(CallControllerOps.operation,
CCS_DEFAULT_INDEX_VAL,
CCS_OPCODE_NOT_SUPPORTED, peer_bda);
}
} else if (handle == ccsControlServiceInfo.bearer_signal_strength_report_interval_handle) {
if (len != 1) {
LOG(ERROR) << " Invalid input for SSR interval";
return BT_STATUS_SUCCESS;
}
LOG(INFO) << __func__ << " signal strength repo Interval: " << data[0];
BearerProviderInfo.signal_report_interval = data[0];
cc_instance->remoteDevices.UpdateSSReportingInterval(device->peer_bda, BearerProviderInfo.signal_report_interval);
}
break;
}
case CCS_CONGESTION_UPDATE: {
LOG(INFO) << __func__ << ": device CCS_CONGESTION_UPDATE update: " << event;
CcpCongestionUpdate(p_data);
break;
}
case CCS_READ_RSP:
case CCS_DESCRIPTOR_READ_RSP:
case CCS_DESCRIPTOR_WRITE_RSP:
case CCS_CONNECTION_UPDATE:
case CCS_PHY_UPDATE:
case CCS_CONNECTION:
LOG(INFO) << __func__ << " calling device state " << device->state;
device = p_data->remoteDevice;
device->DeviceStateHandlerPointer[device->state](p_data->event, p_data);
break;
default:
LOG(INFO) << __func__ << " event is not in list";
break;
}
return BT_STATUS_SUCCESS;
}
void CcpCongestionUpdate(tcc_resp_t* p_data) {
p_data->remoteDevice->congested = p_data->oper.CongestionOp.congested;
LOG(INFO) << __func__ << ": conn_id: " << p_data->remoteDevice->conn_id
<< ", congested: " << p_data->remoteDevice->congested;
GattsOpsQueue::CongestionCallback(p_data->remoteDevice->conn_id,
p_data->remoteDevice->congested);
}