* Copyright (C) 2021-2022 Huawei Device Co., Ltd.
* 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.
*/
#include "gap_internal.h"
#include "gap_task_internal.h"
#include <securec.h>
#include "allocator.h"
#include "log.h"
#include "btm.h"
#include "btm/btm_acl.h"
#include "btm/btm_thread.h"
#ifdef GAP_BREDR_SUPPORT
typedef struct {
uint8_t status;
uint16_t connectionHandle;
BtAddr addr;
uint8_t classOfDevice[BT_COD_SIZE];
bool encyptionEnabled;
void *context;
} GapAclConnectionCompleteParam;
typedef struct {
uint8_t status;
uint16_t connectionHandle;
uint8_t reason;
void *context;
} GapAclDisconnectionCompleteParam;
typedef struct {
BtAddr addr;
bool support;
} GapRemoteDeviceSupportCallbackParam;
static void GapAclConnectionCompleteTask(void *ctx)
{
GapAclConnectionCompleteParam *param = ctx;
BtmAclConnectCompleteParam btmParam = {.addr = ¶m->addr};
btmParam.status = param->status;
btmParam.connectionHandle = param->connectionHandle;
(void)memcpy_s(
btmParam.classOfDevice, sizeof(btmParam.classOfDevice), param->classOfDevice, sizeof(param->classOfDevice));
btmParam.encyptionEnabled = param->encyptionEnabled;
GapAclConnectionComplete(&btmParam, param->context);
}
static void GapRecvAclConnectionComplete(const BtmAclConnectCompleteParam *param, void *context)
{
LOG_INFO("%{public}s: status:0x%{public}02x handle:0x%{public}04x " BT_ADDR_FMT,
__FUNCTION__,
param->status,
param->connectionHandle,
BT_ADDR_FMT_OUTPUT(param->addr->addr));
GapAclConnectionCompleteParam *btmParam = MEM_MALLOC.alloc(sizeof(GapAclConnectionCompleteParam));
if (btmParam == NULL) {
LOG_ERROR("%{public}s: Alloc error.", __FUNCTION__);
return;
}
btmParam->status = param->status;
btmParam->connectionHandle = param->connectionHandle;
btmParam->addr = *param->addr;
(void)memcpy_s(
btmParam->classOfDevice, sizeof(btmParam->classOfDevice), param->classOfDevice, sizeof(param->classOfDevice));
btmParam->encyptionEnabled = param->encyptionEnabled;
btmParam->context = context;
int ret = GapRunTaskUnBlockProcess(GapAclConnectionCompleteTask, btmParam, NULL);
if (ret != BT_SUCCESS) {
LOG_ERROR("%{public}s: Task error:%{public}d.", __FUNCTION__, ret);
}
}
static void GapAclDisconnectionCompleteTask(void *ctx)
{
GapAclDisconnectionCompleteParam *param = ctx;
GapAclDisconnectionComplete(param->status, param->connectionHandle, param->reason, param->context);
}
static void GapRecvAclDisconnectionComplete(uint8_t status, uint16_t connectionHandle, uint8_t reason, void *context)
{
LOG_INFO("%{public}s: status:0x%{public}02x handle:0x%{public}04x reason:0x%{public}02x", __FUNCTION__,
status, connectionHandle, reason);
GapAclDisconnectionCompleteParam *btmParam = MEM_MALLOC.alloc(sizeof(GapAclDisconnectionCompleteParam));
if (btmParam == NULL) {
LOG_ERROR("%{public}s: Alloc error.", __FUNCTION__);
return;
}
btmParam->status = status;
btmParam->connectionHandle = connectionHandle;
btmParam->reason = reason;
btmParam->context = context;
int ret = GapRunTaskUnBlockProcess(GapAclDisconnectionCompleteTask, btmParam, NULL);
if (ret != BT_SUCCESS) {
LOG_ERROR("%{public}s: Task error:%{public}d.", __FUNCTION__, ret);
}
}
#endif
#ifdef GAP_LE_SUPPORT
typedef struct {
uint8_t status;
uint16_t connectionHandle;
BtAddr addr;
uint8_t role;
void *context;
} GapLeConnectionCompleteParam;
typedef struct {
uint8_t status;
uint16_t connectionHandle;
uint8_t reason;
void *context;
} GapLeDisconnectionCompleteParam;
static void GapLeConnectionCompleteTask(void *ctx)
{
GapLeConnectionCompleteParam *param = ctx;
GapLeConnectionComplete(param->status, param->connectionHandle, ¶m->addr, param->role, param->context);
}
static void GapRecvLeConnectionComplete(
uint8_t status, uint16_t connectionHandle, const BtAddr *addr, uint8_t role, void *context)
{
LOG_INFO("%{public}s: status:0x%{public}02x role:%{public}hhu handle:0x%{public}04x " BT_ADDR_FMT,
__FUNCTION__,
status,
role,
connectionHandle,
BT_ADDR_FMT_OUTPUT(addr->addr));
GapLeConnectionCompleteParam *btmParam = MEM_MALLOC.alloc(sizeof(GapLeConnectionCompleteParam));
if (btmParam == NULL) {
LOG_ERROR("%{public}s: Alloc error.", __FUNCTION__);
return;
}
btmParam->status = status;
btmParam->connectionHandle = connectionHandle;
btmParam->addr = *addr;
btmParam->role = role;
btmParam->context = context;
int ret = GapRunTaskUnBlockProcess(GapLeConnectionCompleteTask, btmParam, NULL);
if (ret != BT_SUCCESS) {
LOG_ERROR("%{public}s: Task error:%{public}d.", __FUNCTION__, ret);
}
}
static void GapLeDisconnectionCompleteTask(void *ctx)
{
GapLeDisconnectionCompleteParam *param = ctx;
GapLeDisconnectionComplete(param->status, param->connectionHandle, param->reason, param->context);
}
static void GapRecvLeDisconnectionComplete(uint8_t status, uint16_t connectionHandle, uint8_t reason, void *context)
{
LOG_INFO("%{public}s: status:0x%{public}02x handle:0x%{public}04x reason:0x%{public}02x", __FUNCTION__,
status, connectionHandle, reason);
GapLeDisconnectionCompleteParam *btmParam = MEM_MALLOC.alloc(sizeof(GapLeDisconnectionCompleteParam));
if (btmParam == NULL) {
LOG_ERROR("%{public}s: Alloc error.", __FUNCTION__);
return;
}
btmParam->status = status;
btmParam->connectionHandle = connectionHandle;
btmParam->reason = reason;
btmParam->context = context;
int ret = GapRunTaskUnBlockProcess(GapLeDisconnectionCompleteTask, btmParam, NULL);
if (ret != BT_SUCCESS) {
LOG_ERROR("%{public}s: Task error:%{public}d.", __FUNCTION__, ret);
}
}
#endif
static BtmAclCallbacks g_aclCallback = {0};
void GapRegisterBtmAclCallbacks(void)
{
#ifdef GAP_BREDR_SUPPORT
g_aclCallback.connectionComplete = GapRecvAclConnectionComplete;
g_aclCallback.disconnectionComplete = GapRecvAclDisconnectionComplete;
#endif
#ifdef GAP_LE_SUPPORT
g_aclCallback.leConnectionComplete = GapRecvLeConnectionComplete;
g_aclCallback.leDisconnectionComplete = GapRecvLeDisconnectionComplete;
#endif
BTM_RegisterAclCallbacks(&g_aclCallback, NULL);
}
void GapDeregisterBtmAclCallbacks(void)
{
BTM_DeregisterAclCallbacks(&g_aclCallback);
}
static void GapRemoteDeviceSupportHostSecureSimplePairingCallbackTask(void *ctx)
{
GapRemoteDeviceSupportCallbackParam *param = ctx;
GapRemoteDeviceSupportHostSecureSimplePairingCallback(¶m->addr, param->support);
}
static void GapRecvRemoteDeviceSupportHostSecureSimplePairingCallback(const BtAddr *addr, bool support)
{
LOG_INFO("%{public}s: " BT_ADDR_FMT " support:%{public}d", __FUNCTION__, BT_ADDR_FMT_OUTPUT(addr->addr), support);
GapRemoteDeviceSupportCallbackParam *supportParam = MEM_MALLOC.alloc(sizeof(GapRemoteDeviceSupportCallbackParam));
if (supportParam == NULL) {
LOG_ERROR("%{public}s: Alloc error.", __FUNCTION__);
return;
}
supportParam->addr = *addr;
supportParam->support = support;
int ret = GapRunTaskUnBlockProcess(GapRemoteDeviceSupportHostSecureSimplePairingCallbackTask, supportParam, NULL);
if (ret != BT_SUCCESS) {
LOG_ERROR("%{public}s: Task error:%{public}d.", __FUNCTION__, ret);
}
}
void GapIsRemoteDeviceSupportHostSecureSimplePairingAsync(const BtAddr *addr)
{
BTM_IsRemoteDeviceSupportHostSecureSimplePairing(addr, GapRecvRemoteDeviceSupportHostSecureSimplePairingCallback);
}