* Copyright (C) 2021 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.h"
#include "log.h"
#include "securec.h"
#include "btm.h"
#include "btstack.h"
#include "allocator.h"
#include "module.h"
#include "btm/btm_controller.h"
#include "btm/btm_inq_db.h"
#include "btm/btm_interop.h"
#include "btm/btm_le_sec.h"
#include "btm/btm_thread.h"
#include "hci/hci.h"
#include "hci/hci_error.h"
#include "smp/smp.h"
#include "smp/smp_def.h"
#include "gap_internal.h"
#include "gap_le.h"
#include "gap_task_internal.h"
static GapMng g_gapMng;
* memset_s g_gapMng back to zero, so later GapDisableTask/GapFinalizeTask
* must not walk the (NULL) lists - platform ListClear/ListDelete assert. */
static bool g_gapInitOk = false;
typedef struct {
int traceLevel;
} GapInitializeParam;
static int GapWriteScanEnable(void);
static int GapWriteInquiryScanActivity(void);
static int GapWriteInquiryScanType(void);
static int GapWriteCurrentIACLAP(void);
static int GapWritePageScanActivity(void);
static int GapWritePageScanType(void);
static int GapWriteClassOfDevice(uint32_t cod);
static void GapFreeRegSecInfo(void *data);
static void GapFreeReqSecInfo(void *data);
static void GapFreeDeviceInfo(void *data);
static void GapFreeListNode(void *data)
{
MEM_MALLOC.free(data);
}
static int GapInitCreateBlocks(void)
{
#ifdef GAP_BREDR_SUPPORT
g_gapMng.bredr.profileSecBlock.registerlist = ListCreate(GapFreeRegSecInfo);
g_gapMng.bredr.profileSecBlock.requestlist = ListCreate(GapFreeReqSecInfo);
g_gapMng.bredr.connectionInfoBlock.devicelist = ListCreate(GapFreeDeviceInfo);
#endif
#ifdef GAP_LE_SUPPORT
g_gapMng.le.connectionInfoBlock.deviceList = ListCreate(GapFreeLeDeviceInfo);
g_gapMng.le.signatureBlock.RequestList = ListCreate(GapFreeLeSignatureRequest);
g_gapMng.le.randomAddressBlock.reportRPAResolveList = ListCreate(GapFreeReportRPAResolveInfo);
g_gapMng.le.exAdvBlock.exAdvInfoList = ListCreate(GapFreeListNode);
g_gapMng.le.exAdvBlock.lock = MutexCreate();
if (g_gapMng.le.exAdvBlock.lock == NULL) {
LOG_ERROR("%{public}s: exAdvBlock lock creation failed.", __FUNCTION__);
return GAP_ERR_OUT_OF_RES;
}
#endif
return GAP_SUCCESS;
}
static void GapInitCleanupBlocks(void)
{
#ifdef GAP_LE_SUPPORT
ListDelete(g_gapMng.le.exAdvBlock.exAdvInfoList);
ListDelete(g_gapMng.le.randomAddressBlock.reportRPAResolveList);
ListDelete(g_gapMng.le.signatureBlock.RequestList);
ListDelete(g_gapMng.le.connectionInfoBlock.deviceList);
#endif
#ifdef GAP_BREDR_SUPPORT
ListDelete(g_gapMng.bredr.profileSecBlock.registerlist);
ListDelete(g_gapMng.bredr.profileSecBlock.requestlist);
ListDelete(g_gapMng.bredr.connectionInfoBlock.devicelist);
#endif
(void)memset_s(&g_gapMng, sizeof(GapMng), 0x00, sizeof(GapMng));
}
static bool GapInitLeAdvSyncGroup(void)
{
int ret = GapLePeriodicAdvSyncInit();
if (ret != GAP_SUCCESS) {
LOG_ERROR("%{public}s: GapLePeriodicAdvSyncInit failed: %{public}d.", __FUNCTION__, ret);
MutexDelete(g_gapMng.le.exAdvBlock.lock);
GapInitCleanupBlocks();
return false;
}
return true;
}
static bool GapInitLeCallbackGroup(void)
{
int ret = GapLeCallbackInit();
if (ret != GAP_SUCCESS) {
LOG_ERROR("%{public}s: GapLeCallbackInit failed: %{public}d.", __FUNCTION__, ret);
GapLeCallbackDeinit();
GapLePeriodicAdvSyncDeinit();
MutexDelete(g_gapMng.le.exAdvBlock.lock);
GapInitCleanupBlocks();
return false;
}
return true;
}
static bool GapInitLeCteGroup(void)
{
int ret = GapLeCteCallbackInit();
if (ret != GAP_SUCCESS) {
LOG_ERROR("%{public}s: GapLeCteCallbackInit failed: %{public}d.", __FUNCTION__, ret);
GapLeCteCallbackDeinit();
GapLeCallbackDeinit();
GapLePeriodicAdvSyncDeinit();
MutexDelete(g_gapMng.le.exAdvBlock.lock);
GapInitCleanupBlocks();
return false;
}
return true;
}
static bool GapInitLePowerControlGroup(void)
{
int ret = GapLePowerControlCallbackInit();
if (ret != GAP_SUCCESS) {
LOG_ERROR("%{public}s: GapLePowerControlCallbackInit failed: %{public}d.", __FUNCTION__, ret);
GapLePowerControlCallbackDeinit();
GapLeCteCallbackDeinit();
GapLeCallbackDeinit();
GapLePeriodicAdvSyncDeinit();
MutexDelete(g_gapMng.le.exAdvBlock.lock);
GapInitCleanupBlocks();
return false;
}
return true;
}
static bool GapInitLeSubrateGroup(void)
{
int ret = GapLeSubrateCallbackInit();
if (ret != GAP_SUCCESS) {
LOG_ERROR("%{public}s: GapLeSubrateCallbackInit failed: %{public}d.", __FUNCTION__, ret);
GapLeSubrateCallbackDeinit();
GapLePowerControlCallbackDeinit();
GapLeCteCallbackDeinit();
GapLeCallbackDeinit();
GapLePeriodicAdvSyncDeinit();
MutexDelete(g_gapMng.le.exAdvBlock.lock);
GapInitCleanupBlocks();
return false;
}
return true;
}
static void GapInitializeTask(void *ctx)
{
LOG_DEBUG("%{public}s:", __FUNCTION__);
(void)memset_s(&g_gapMng, sizeof(GapMng), 0x00, sizeof(GapMng));
g_gapMng.traceLevel = ((GapInitializeParam *)ctx)->traceLevel;
int ret = GapInitCreateBlocks();
if (ret != GAP_SUCCESS) {
GapInitCleanupBlocks();
return;
}
#ifdef GAP_LE_SUPPORT
if (!GapInitLeAdvSyncGroup() || !GapInitLeCallbackGroup() || !GapInitLeCteGroup() ||
!GapInitLePowerControlGroup() || !GapInitLeSubrateGroup()) {
return;
}
#endif
g_gapInitOk = true;
}
static void GapInitialize(int traceLevel)
{
LOG_INFO("%{public}s:", __FUNCTION__);
BTM_CreateProcessingQueue(PROCESSING_QUEUE_ID_GAP, BTM_PROCESSING_QUEUE_SIZE_DEFAULT);
GapInitializeParam *ctx = MEM_MALLOC.alloc(sizeof(GapInitializeParam));
if (ctx == NULL) {
LOG_ERROR("%{public}s: Alloc error.", __FUNCTION__);
return;
}
int ret = GapRunTaskBlockProcess(GapInitializeTask, ctx);
if (ret != BT_SUCCESS) {
LOG_ERROR("%{public}s: Run task error.", __FUNCTION__);
}
MEM_MALLOC.free(ctx);
}
static void GapEnableBredr(void)
{
if (BTM_IsControllerSupportBrEdr()) {
g_gapMng.bredr.isEnable = true;
g_gapMng.bredr.keyMissingRetry = true;
HciWriteInquiryModeParam writeInquiryModeParam = {
.inquiryMode = HCI_INQUIRY_MODE_STANDARD,
};
if (BTM_IsControllerSupportEirInquiryResponse()) {
writeInquiryModeParam.inquiryMode = HCI_INQUIRY_MODE_EIR;
} else if (BTM_IsControllerSupportRssiInquiryResponse()) {
writeInquiryModeParam.inquiryMode = HCI_INQUIRY_MODE_RSSI;
}
HCI_WriteInquiryMode(&writeInquiryModeParam);
}
}
static void GapEnableLe(void)
{
if (BTM_IsControllerSupportLe()) {
g_gapMng.le.isEnable = true;
g_gapMng.le.local.minEncKeySize = GAP_ENC_KEY_MAX_SIZE;
int ret = BTM_GetLocalAddr(&g_gapMng.le.local.addr);
if (ret == BT_SUCCESS) {
g_gapMng.le.local.addr.type = LOCAL_ADDR_TYPE_PUBLIC;
} else {
g_gapMng.le.local.addr.type = LOCAL_ADDR_TYPE_RANDOM;
}
if (BTM_IsControllerSupportLeExtendedAdvertising()) {
HCI_LeReadMaximumAdvertisingDataLength();
HCI_LeReadNumberofSupportedAdvertisingSets();
}
GapRegisterL2capCallbacks();
GapRegisterSmCallbacks();
}
}
static void GapEnableTask(void *ctx)
{
LOG_DEBUG("%{public}s:", __FUNCTION__);
#ifdef GAP_BREDR_SUPPORT
GapEnableBredr();
#endif
#ifdef GAP_LE_SUPPORT
GapEnableLe();
#endif
GapRegisterHciEventCallbacks();
GapRegisterBtmAclCallbacks();
}
static void GapEnable(void)
{
LOG_INFO("%{public}s:", __FUNCTION__);
int ret = GapRunTaskBlockProcess(GapEnableTask, NULL);
if (ret != BT_SUCCESS) {
LOG_ERROR("%{public}s: Run task error.", __FUNCTION__);
}
}
static void GapDisableTask(void *ctx)
{
LOG_DEBUG("%{public}s:", __FUNCTION__);
if (!g_gapInitOk) {
* resources and zeroed g_gapMng, nothing to disable. */
LOG_WARN("%{public}s: GAP was not initialized, skip.", __FUNCTION__);
return;
}
GapDeregisterHciEventCallbacks();
GapDeregisterBtmAclCallbacks();
if (BTM_IsControllerSupportBrEdr()) {
ListClear(g_gapMng.bredr.profileSecBlock.registerlist);
ListNode *node = ListGetFirstNode(g_gapMng.bredr.profileSecBlock.requestlist);
while (node != NULL) {
RequestSecInfo *reqInfo = ListGetNodeData(node);
node = ListGetNextNode(node);
if (!reqInfo->doCallback) {
ListRemoveNode(g_gapMng.bredr.profileSecBlock.requestlist, reqInfo);
}
}
ListClear(g_gapMng.bredr.connectionInfoBlock.devicelist);
g_gapMng.bredr.scanModeBlock.status = GAP_SCANMODE_STATUS_IDLE;
g_gapMng.bredr.inquiryBlock.status = GAP_INQUIRY_STATUS_IDLE;
g_gapMng.bredr.remoteNameBlock.status = GAP_REMOTE_NAME_STATUS_IDLE;
g_gapMng.bredr.encryptionBlock.status = GAP_SET_ENCRYPTION_STATUS_IDLE;
g_gapMng.bredr.isEnable = false;
}
if (BTM_IsControllerSupportLe()) {
GapDeregisterL2capCallbacks();
GapDeregisterSmCallbacks();
ListClear(g_gapMng.le.connectionInfoBlock.deviceList);
ListClear(g_gapMng.le.signatureBlock.RequestList);
ListClear(g_gapMng.le.randomAddressBlock.reportRPAResolveList);
if (g_gapMng.le.exAdvBlock.lock != NULL) {
MutexLock(g_gapMng.le.exAdvBlock.lock);
ListClear(g_gapMng.le.exAdvBlock.exAdvInfoList);
MutexUnlock(g_gapMng.le.exAdvBlock.lock);
}
g_gapMng.le.bondBlock.isPairing = false;
g_gapMng.le.randomAddressBlock.generationInfo.processing = false;
g_gapMng.le.isEnable = false;
}
}
static void GapDisable(void *ctx)
{
LOG_INFO("%{public}s:", __FUNCTION__);
int ret = GapRunTaskBlockProcess(GapDisableTask, NULL);
if (ret != BT_SUCCESS) {
LOG_ERROR("%{public}s: Run task error.", __FUNCTION__);
}
}
static void GapFinalizeTask(void *ctx)
{
LOG_INFO("%{public}s:", __FUNCTION__);
if (!g_gapInitOk) {
* resources and zeroed g_gapMng. Only the processing queue (created
* before the task ran) may still exist, so just delete it. */
LOG_WARN("%{public}s: GAP was not initialized, skip.", __FUNCTION__);
BTM_DeleteProcessingQueue(PROCESSING_QUEUE_ID_GAP);
return;
}
g_gapInitOk = false;
#ifdef GAP_BREDR_SUPPORT
ListDelete(g_gapMng.bredr.profileSecBlock.registerlist);
ListDelete(g_gapMng.bredr.profileSecBlock.requestlist);
ListDelete(g_gapMng.bredr.connectionInfoBlock.devicelist);
#endif
#ifdef GAP_LE_SUPPORT
* reference are destroyed. Any residual state will be overwritten by
* the memset_s below. Tear down in reverse order of initialization. */
int ret = GapLeCallbackDeinit();
if (ret != GAP_SUCCESS) {
LOG_WARN("%{public}s: GapLeCallbackDeinit returned %{public}d", __FUNCTION__, ret);
}
GapLePeriodicAdvSyncDeinit();
GapLeCteCallbackDeinit();
GapLePowerControlCallbackDeinit();
GapLeSubrateCallbackDeinit();
ListDelete(g_gapMng.le.connectionInfoBlock.deviceList);
ListDelete(g_gapMng.le.signatureBlock.RequestList);
ListDelete(g_gapMng.le.randomAddressBlock.reportRPAResolveList);
if (g_gapMng.le.exAdvBlock.lock != NULL) {
MutexDelete(g_gapMng.le.exAdvBlock.lock);
g_gapMng.le.exAdvBlock.lock = NULL;
}
ListDelete(g_gapMng.le.exAdvBlock.exAdvInfoList);
#endif
(void)memset_s(&g_gapMng, sizeof(GapMng), 0x00, sizeof(GapMng));
BTM_DeleteProcessingQueue(PROCESSING_QUEUE_ID_GAP);
}
static void GapFinalize(void)
{
LOG_INFO("%{public}s:", __FUNCTION__);
int ret = GapRunTaskBlockProcess(GapFinalizeTask, NULL);
if (ret != BT_SUCCESS) {
LOG_ERROR("%{public}s: Run task error.", __FUNCTION__);
}
}
void GapChangeHCIAddr(BtAddr *addr, const HciBdAddr *hciAddr, uint8_t addrType)
{
(void)memcpy_s(addr->addr, BT_ADDRESS_SIZE, hciAddr->raw, BT_ADDRESS_SIZE);
addr->type = addrType;
}
bool GapIsEmptyAddr(const uint8_t *addr)
{
for (int i = 0; i < BT_ADDRESS_SIZE; i++) {
if (addr[i] != 0) {
return false;
}
}
return true;
}
bool GapAddrCompare(const BtAddr *addr1, const BtAddr *addr2)
{
return (!memcmp(addr1->addr, addr2->addr, BT_ADDRESS_SIZE) &&
!((addr1->type == BT_PUBLIC_DEVICE_ADDRESS || addr1->type == BT_PUBLIC_IDENTITY_ADDRESS) ^
(addr2->type == BT_PUBLIC_DEVICE_ADDRESS || addr2->type == BT_PUBLIC_IDENTITY_ADDRESS)));
}
bool GapCompareChannelID(GAP_SecMultiplexingProtocol protocolID, GapSecChannel channelID1, GapSecChannel channelID2)
{
return (protocolID == SEC_PROTOCOL_L2CAP) ? (channelID1.l2capPsm == channelID2.l2capPsm)
: (channelID1.rfcommChannel == channelID2.rfcommChannel);
}
#ifdef GAP_BREDR_SUPPORT
bool GapIsBredrEnable(void)
{
return g_gapMng.bredr.isEnable;
}
ScanModeBlock *GapGetScanModeBlock(void)
{
return &g_gapMng.bredr.scanModeBlock;
}
InquiryBlock *GapGetInquiryBlock(void)
{
return &g_gapMng.bredr.inquiryBlock;
}
RemoteNameBlock *GapGetRemoteNameBlock(void)
{
return &g_gapMng.bredr.remoteNameBlock;
}
GAP_SecurityMode *GapGetSecurityMode(void)
{
return &g_gapMng.bredr.secMode;
}
ProfileSecurityBlock *GapGetProfileSecurityBlock(void)
{
return &g_gapMng.bredr.profileSecBlock;
}
ConnectionInfoBlock *GapGetConnectionInfoBlock(void)
{
return &g_gapMng.bredr.connectionInfoBlock;
}
EncryptionBlock *GapGetEncryptionBlock(void)
{
return &g_gapMng.bredr.encryptionBlock;
}
bool GapIsBondMode(void)
{
bool isBondMode;
isBondMode = (g_gapMng.bredr.bondableMode == GAP_BONDABLE_MODE);
return isBondMode;
}
#endif
#ifdef GAP_LE_SUPPORT
bool GapIsLeEnable(void)
{
return g_gapMng.le.isEnable;
}
bool GapLeRolesCheck(uint8_t role)
{
return !!(g_gapMng.le.local.role & role);
}
void GapFreeLeDeviceInfo(void *data)
{
LeDeviceInfo *deviceInfo = data;
if (deviceInfo->alarm != NULL) {
AlarmCancel(deviceInfo->alarm);
AlarmDelete(deviceInfo->alarm);
}
if (deviceInfo->securityReq != NULL) {
MEM_MALLOC.free(deviceInfo->securityReq);
deviceInfo->securityReq = NULL;
}
if (deviceInfo->paramUpdateReq != NULL) {
MEM_MALLOC.free(deviceInfo->paramUpdateReq);
deviceInfo->paramUpdateReq = NULL;
}
MEM_MALLOC.free(deviceInfo);
}
void GapFreeLeSignatureRequest(void *data)
{
MEM_MALLOC.free(data);
}
LeBondBlock *GapGetLeBondBlock(void)
{
return &g_gapMng.le.bondBlock;
}
LeConnectionInfoBlock *GapGetLeConnectionInfoBlock(void)
{
return &g_gapMng.le.connectionInfoBlock;
}
LeSignatureBlock *GapGetLeSignatureBlock(void)
{
return &g_gapMng.le.signatureBlock;
}
LeRandomAddressBlock *GapGetLeRandomAddressBlock(void)
{
return &g_gapMng.le.randomAddressBlock;
}
LeExAdvBlock *GapGetLeExAdvBlock(void)
{
return &g_gapMng.le.exAdvBlock;
}
bool GapIsLeBondableMode(void)
{
return g_gapMng.le.local.bondableMode == GAP_BONDABLE_MODE;
}
LeLocalInfo *GapGetLeLocalInfo(void)
{
return &g_gapMng.le.local;
}
#endif
#ifdef GAP_BREDR_SUPPORT
int GAP_SetScanMode(const GapDiscoverModeInfo *discoverInfo, const GapConnectableModeInfo *connectableInfo,
GapSetScanModeResultCallback callback, void *context)
{
int ret;
ScanModeBlock *scanModeBlock = NULL;
LOG_INFO("%{public}s:discoverable:[%hhu][%hhu][%04x][%04x], connectable:[%hhu][%hhu][%04x][%04x]",
__FUNCTION__,
discoverInfo->mode,
discoverInfo->type,
discoverInfo->scanInterval,
discoverInfo->scanWindow,
connectableInfo->mode,
connectableInfo->type,
connectableInfo->scanInterval,
connectableInfo->scanWindow);
if (GapIsBredrEnable() == false) {
return GAP_ERR_NOT_ENABLE;
}
if (discoverInfo->mode > GAP_DISCOVERABLE_MODE_GENERAL || discoverInfo->type > GAP_INQUIRY_SCAN_TYPE_INTERLACED ||
discoverInfo->scanInterval < GAP_SCAN_INTERVAL_RANGE_MIN ||
discoverInfo->scanInterval > GAP_SCAN_INTERVAL_RANGE_MAX ||
discoverInfo->scanWindow < GAP_SCAN_WINDOW_RANGE_MIN || discoverInfo->scanWindow > discoverInfo->scanInterval ||
connectableInfo->mode > GAP_CONNECTABLE_MODE || connectableInfo->type > GAP_PAGE_SCAN_TYPE_INTERLACED ||
connectableInfo->scanInterval < GAP_SCAN_INTERVAL_RANGE_MIN ||
connectableInfo->scanInterval > GAP_SCAN_INTERVAL_RANGE_MAX ||
connectableInfo->scanWindow < GAP_SCAN_WINDOW_RANGE_MIN ||
connectableInfo->scanWindow > connectableInfo->scanInterval) {
return GAP_ERR_INVAL_PARAM;
}
scanModeBlock = GapGetScanModeBlock();
if (scanModeBlock->status != GAP_SCANMODE_STATUS_IDLE) {
ret = GAP_ERR_INVAL_STATE;
} else {
(void)memcpy_s(
&scanModeBlock->discoverMode, sizeof(GapDiscoverModeInfo), discoverInfo, sizeof(GapDiscoverModeInfo));
(void)memcpy_s(&scanModeBlock->connectableMode,
sizeof(GapConnectableModeInfo),
connectableInfo,
sizeof(GapConnectableModeInfo));
scanModeBlock->callback = callback;
scanModeBlock->context = context;
scanModeBlock->status = GAP_SCANMODE_STATUS_CLOSING;
ret = GapWriteScanEnable();
if (ret != BT_SUCCESS) {
LOG_WARN("");
scanModeBlock->status = GAP_SCANMODE_STATUS_IDLE;
}
}
return ret;
}
static int GapWriteScanEnable(void)
{
LOG_DEBUG("%{public}s:", __FUNCTION__);
HciWriteScanEnableParam hciCmdParam;
ScanModeBlock *scanModeBlock = GapGetScanModeBlock();
uint8_t discoverMode = scanModeBlock->discoverMode.mode;
uint8_t connectableMode = scanModeBlock->connectableMode.mode;
int ret;
if (scanModeBlock->status == GAP_SCANMODE_STATUS_CLOSING) {
hciCmdParam.scanEnable = 0;
ret = HCI_WriteScanEnable(&hciCmdParam);
} else if (scanModeBlock->status == GAP_SCANMODE_STATUS_SETTING) {
if (discoverMode != GAP_DISCOVERABLE_MODE_NON && connectableMode != GAP_CONNECTABLE_MODE_NON) {
hciCmdParam.scanEnable = INQUIRY_SCAN_ENABLED_PAGE_SCAN_ENABLED;
} else if (connectableMode != GAP_DISCOVERABLE_MODE_NON) {
hciCmdParam.scanEnable = INQUIRY_SCAN_DISABLED_PAGE_SCAN_ENABLED;
} else if (discoverMode != GAP_CONNECTABLE_MODE_NON) {
hciCmdParam.scanEnable = INQUIRY_SCAN_ENABLED_PAGE_SCAN_DISABLED;
} else {
hciCmdParam.scanEnable = NO_SCANS_ENABLED;
}
ret = HCI_WriteScanEnable(&hciCmdParam);
} else {
ret = GAP_ERR_INVAL_STATE;
}
return ret;
}
NO_SANITIZE("cfi") void GapWriteScanEnableComplete(const HciWriteScanEnableReturnParam *param)
{
LOG_DEBUG("%{public}s:", __FUNCTION__);
int ret = GAP_SUCCESS;
GapSetScanModeResultCallback callback = NULL;
ScanModeBlock *scanModeBlock = NULL;
uint8_t retStatus = param->status;
if (GapIsBredrEnable() == false) {
LOG_ERROR("Not Enable.");
return;
}
scanModeBlock = GapGetScanModeBlock();
if (scanModeBlock->status == GAP_SCANMODE_STATUS_CLOSING) {
if (retStatus == HCI_SUCCESS) {
if (scanModeBlock->discoverMode.mode) {
scanModeBlock->status = GAP_SCANMODE_STATUS_SETTING;
ret = GapWriteInquiryScanActivity();
} else if (scanModeBlock->connectableMode.mode) {
scanModeBlock->status = GAP_SCANMODE_STATUS_SETTING;
ret = GapWritePageScanActivity();
} else {
scanModeBlock->status = GAP_SCANMODE_STATUS_IDLE;
callback = scanModeBlock->callback;
}
if (ret != BT_SUCCESS) {
LOG_ERROR("HCI Command Error ret = %{public}d.", ret);
retStatus = GAP_STATUS_FAILED;
callback = scanModeBlock->callback;
scanModeBlock->status = GAP_SCANMODE_STATUS_IDLE;
}
} else {
scanModeBlock->status = GAP_SCANMODE_STATUS_IDLE;
callback = scanModeBlock->callback;
}
} else if (scanModeBlock->status == GAP_SCANMODE_STATUS_SETTING) {
scanModeBlock->status = GAP_SCANMODE_STATUS_IDLE;
callback = scanModeBlock->callback;
} else {
LOG_WARN("");
}
if (callback != NULL) {
callback(retStatus, scanModeBlock->context);
}
}
static int GapWriteInquiryScanActivity(void)
{
LOG_DEBUG("%{public}s:", __FUNCTION__);
int ret;
ScanModeBlock *scanModeBlock = GapGetScanModeBlock();
HciWriteInquiryScanActivityParam hciCmdParam;
if (scanModeBlock->status == GAP_SCANMODE_STATUS_SETTING) {
hciCmdParam.inquiryScanInterval = scanModeBlock->discoverMode.scanInterval;
hciCmdParam.inquiryScanWindow = scanModeBlock->discoverMode.scanWindow;
ret = HCI_WriteInquiryScanActivity(&hciCmdParam);
} else {
ret = GAP_ERR_INVAL_STATE;
}
return ret;
}
void GapWriteInquiryScanActivityComplete(const HciWriteInquiryScanActivityReturnParam *param)
{
LOG_DEBUG("%{public}s:", __FUNCTION__);
GapSetScanModeResultCallback callback = NULL;
uint8_t retStatus = param->status;
if (GapIsBredrEnable() == false) {
LOG_ERROR("%sNot Enable.", "");
return;
}
ScanModeBlock *scanModeBlock = GapGetScanModeBlock();
if (scanModeBlock->status == GAP_SCANMODE_STATUS_SETTING) {
if (retStatus == HCI_SUCCESS) {
int ret = GapWriteInquiryScanType();
if (ret != BT_SUCCESS) {
scanModeBlock->status = GAP_SCANMODE_STATUS_IDLE;
retStatus = GAP_STATUS_FAILED;
callback = scanModeBlock->callback;
LOG_ERROR("HCI Command Error ret = %{public}d.", ret);
}
} else {
scanModeBlock->status = GAP_SCANMODE_STATUS_IDLE;
callback = scanModeBlock->callback;
}
}
if (callback != NULL) {
callback(retStatus, scanModeBlock->context);
}
}
static int GapWriteInquiryScanType(void)
{
LOG_DEBUG("%{public}s:", __FUNCTION__);
int ret;
ScanModeBlock *scanModeBlock = GapGetScanModeBlock();
HciWriteInquiryScanTypeParam hciCmdParam;
if (scanModeBlock->status == GAP_SCANMODE_STATUS_SETTING) {
hciCmdParam.scanType = scanModeBlock->discoverMode.type;
ret = HCI_WriteInquiryScanType(&hciCmdParam);
} else {
ret = GAP_ERR_INVAL_STATE;
}
return ret;
}
void GapWriteInquiryScanTypeComplete(const HciWriteInquiryScanTypeReturnParam *param)
{
LOG_DEBUG("%{public}s:", __FUNCTION__);
ScanModeBlock *scanModeBlock = NULL;
GapSetScanModeResultCallback callback = NULL;
uint8_t retStatus = param->status;
if (GapIsBredrEnable() == false) {
LOG_ERROR("%sNot Enable.", "");
return;
}
scanModeBlock = GapGetScanModeBlock();
if (scanModeBlock->status == GAP_SCANMODE_STATUS_SETTING) {
if (retStatus == HCI_SUCCESS) {
int ret = GapWriteCurrentIACLAP();
if (ret != BT_SUCCESS) {
LOG_ERROR("HCI Command Error ret = %{public}d.", ret);
callback = scanModeBlock->callback;
retStatus = GAP_STATUS_FAILED;
scanModeBlock->status = GAP_SCANMODE_STATUS_IDLE;
}
} else {
scanModeBlock->status = GAP_SCANMODE_STATUS_IDLE;
callback = scanModeBlock->callback;
}
}
if (callback != NULL) {
callback(retStatus, scanModeBlock->context);
}
}
static int GapWriteCurrentIACLAP(void)
{
LOG_DEBUG("%{public}s:", __FUNCTION__);
ScanModeBlock *scanModeBlock = GapGetScanModeBlock();
uint8_t discoverableMode = scanModeBlock->discoverMode.mode;
uint8_t numCurrentIAC = 0;
uint32_t iacLAP[CURRENT_IAC_MAX_NUM];
if (discoverableMode & GAP_DISCOVERABLE_MODE_GENERAL) {
iacLAP[numCurrentIAC] = LAP_GENERAL_INQUIRY_ACCESS;
numCurrentIAC++;
} else if (discoverableMode & GAP_DISCOVERABLE_MODE_LIMITED) {
iacLAP[numCurrentIAC] = LAP_GENERAL_INQUIRY_ACCESS;
numCurrentIAC++;
iacLAP[numCurrentIAC] = LAP_LIMITED_INQUIRY_ACCESS;
numCurrentIAC++;
}
HciWriteCurrentIacLapParam param = {
.numCurrentIAC = numCurrentIAC,
.iacLAP = iacLAP,
};
return HCI_WriteCurrentIacLap(¶m);
}
void GapWriteCurrentIACLAPComplete(const HciWriteCurrentIacLapReturnParam *param)
{
LOG_DEBUG("%{public}s:", __FUNCTION__);
ScanModeBlock *scanModeBlock = NULL;
GapSetScanModeResultCallback callback = NULL;
uint8_t retStatus = param->status;
if (GapIsBredrEnable() == false) {
LOG_ERROR("%sNot Enable.", "");
return;
}
scanModeBlock = GapGetScanModeBlock();
if (scanModeBlock->status == GAP_SCANMODE_STATUS_SETTING) {
if (retStatus == HCI_SUCCESS) {
if (scanModeBlock->discoverMode.mode & GAP_INQUIRY_MODE_LIMITED) {
g_gapMng.bredr.classOfDevice |= COD_LIMITED_DISCOVERABLE_BIT;
} else {
g_gapMng.bredr.classOfDevice &= ~COD_LIMITED_DISCOVERABLE_BIT;
}
int ret = GapWriteClassOfDevice(g_gapMng.bredr.classOfDevice);
if (ret != BT_SUCCESS) {
LOG_ERROR("HCI Command Error ret = %{public}d.", ret);
retStatus = GAP_STATUS_FAILED;
scanModeBlock->status = GAP_SCANMODE_STATUS_IDLE;
callback = scanModeBlock->callback;
}
} else {
callback = scanModeBlock->callback;
scanModeBlock->status = GAP_SCANMODE_STATUS_IDLE;
}
}
if (callback != NULL) {
callback(retStatus, scanModeBlock->context);
}
}
static int GapWritePageScanActivity(void)
{
LOG_DEBUG("%{public}s:", __FUNCTION__);
int ret;
ScanModeBlock *scanModeBlock = GapGetScanModeBlock();
HciWritePageScanActivityParam hciCmdParam;
hciCmdParam.pageScanInterval = scanModeBlock->connectableMode.scanInterval;
hciCmdParam.pageScanWindow = scanModeBlock->connectableMode.scanWindow;
ret = HCI_WritePageScanActivity(&hciCmdParam);
return ret;
}
void GapWritePageScanActivityComplete(const HciWritePageScanActivityReturnParam *param)
{
LOG_DEBUG("%{public}s:", __FUNCTION__);
GapSetScanModeResultCallback callback = NULL;
uint8_t retStatus = param->status;
if (GapIsBredrEnable() == false) {
LOG_ERROR("%sNot Enable.", "");
return;
}
ScanModeBlock *scanModeBlock = GapGetScanModeBlock();
if (scanModeBlock->status == GAP_SCANMODE_STATUS_SETTING) {
if (retStatus == HCI_SUCCESS) {
int ret = GapWritePageScanType();
if (ret != BT_SUCCESS) {
LOG_ERROR("HCI Command Error ret = %{public}d.", ret);
scanModeBlock->status = GAP_SCANMODE_STATUS_IDLE;
callback = scanModeBlock->callback;
retStatus = GAP_STATUS_FAILED;
}
} else {
callback = scanModeBlock->callback;
scanModeBlock->status = GAP_SCANMODE_STATUS_IDLE;
}
}
if (callback != NULL) {
callback(retStatus, scanModeBlock->context);
}
}
static int GapWritePageScanType(void)
{
LOG_DEBUG("%{public}s:", __FUNCTION__);
int ret;
ScanModeBlock *scanModeBlock = GapGetScanModeBlock();
HciWritePageScanTypeParam hciCmdParam;
hciCmdParam.pageScanType = scanModeBlock->connectableMode.type;
ret = HCI_WritePageScanType(&hciCmdParam);
return ret;
}
void GapWritePageScanTypeComplete(const HciWritePageScanTypeReturnParam *param)
{
LOG_DEBUG("%{public}s:", __FUNCTION__);
GapSetScanModeResultCallback callback = NULL;
uint8_t retStatus = param->status;
if (GapIsBredrEnable() == false) {
LOG_ERROR("%sNot Enable.", "");
return;
}
ScanModeBlock *scanModeBlock = GapGetScanModeBlock();
if (scanModeBlock->status == GAP_SCANMODE_STATUS_SETTING) {
if (retStatus == HCI_SUCCESS) {
int ret = GapWriteScanEnable();
if (ret != BT_SUCCESS) {
LOG_ERROR("HCI Command Error ret = %{public}d.", ret);
callback = scanModeBlock->callback;
scanModeBlock->status = GAP_SCANMODE_STATUS_IDLE;
retStatus = GAP_STATUS_FAILED;
}
} else {
callback = scanModeBlock->callback;
scanModeBlock->status = GAP_SCANMODE_STATUS_IDLE;
}
}
if (callback != NULL) {
callback(retStatus, scanModeBlock->context);
}
}
void GapReadLocalOobExtendedDataComplete(const HciReadLocalOobExtendedDataReturnParam *param)
{
if (param->status == HCI_SUCCESS) {
(void)memcpy_s(g_gapMng.bredr.oobData256.C, GAP_OOB_DATA_CONFIRM_SIZE, param->c256, GAP_OOB_DATA_CONFIRM_SIZE);
(void)memcpy_s(g_gapMng.bredr.oobData256.R, GAP_OOB_DATA_RANDOM_SIZE, param->r256, GAP_OOB_DATA_RANDOM_SIZE);
(void)memcpy_s(g_gapMng.bredr.oobData192.C, GAP_OOB_DATA_CONFIRM_SIZE, param->c192, GAP_OOB_DATA_CONFIRM_SIZE);
(void)memcpy_s(g_gapMng.bredr.oobData192.R, GAP_OOB_DATA_RANDOM_SIZE, param->r192, GAP_OOB_DATA_RANDOM_SIZE);
} else {
int ret = HCI_ReadLocalOOBData();
if (ret != BT_SUCCESS) {
LOG_WARN("%{public}s: Local OOB data read failed", __FUNCTION__);
}
}
}
void GapReadLocalOobDataComplete(const HciReadLocalOOBDataReturnParam *param)
{
if (param->status == HCI_SUCCESS) {
(void)memset_s(g_gapMng.bredr.oobData256.C, GAP_OOB_DATA_CONFIRM_SIZE, 0x00, GAP_OOB_DATA_CONFIRM_SIZE);
(void)memset_s(g_gapMng.bredr.oobData256.R, GAP_OOB_DATA_RANDOM_SIZE, 0x00, GAP_OOB_DATA_RANDOM_SIZE);
(void)memcpy_s(g_gapMng.bredr.oobData192.C, GAP_OOB_DATA_CONFIRM_SIZE, param->C, GAP_OOB_DATA_CONFIRM_SIZE);
(void)memcpy_s(g_gapMng.bredr.oobData192.R, GAP_OOB_DATA_RANDOM_SIZE, param->R, GAP_OOB_DATA_RANDOM_SIZE);
} else {
(void)memset_s(g_gapMng.bredr.oobData256.C, GAP_OOB_DATA_CONFIRM_SIZE, 0x00, GAP_OOB_DATA_CONFIRM_SIZE);
(void)memset_s(g_gapMng.bredr.oobData256.R, GAP_OOB_DATA_RANDOM_SIZE, 0x00, GAP_OOB_DATA_RANDOM_SIZE);
(void)memset_s(g_gapMng.bredr.oobData192.C, GAP_OOB_DATA_CONFIRM_SIZE, 0x00, GAP_OOB_DATA_CONFIRM_SIZE);
(void)memset_s(g_gapMng.bredr.oobData192.R, GAP_OOB_DATA_RANDOM_SIZE, 0x00, GAP_OOB_DATA_RANDOM_SIZE);
}
}
int GapReadNewLocalOOBData(void)
{
int ret;
BtmLocalVersionInformation version;
BTM_GetLocalVersionInformation(&version);
if (version.hciVersion >= BLUETOOTH_CORE_SPECIFICATION_4_1) {
ret = HCI_ReadLocalOOBExtendedData();
if (ret != BT_SUCCESS) {
LOG_WARN("%{public}s: Local OOB data read failed", __FUNCTION__);
}
} else {
ret = HCI_ReadLocalOOBData();
if (ret != BT_SUCCESS) {
LOG_WARN("%{public}s: Local OOB data read failed", __FUNCTION__);
}
}
return ret;
}
bool GapIsKeyMissingRetry(void)
{
return g_gapMng.bredr.keyMissingRetry;
}
int GAP_SetKeyMissingRetry(bool retry)
{
g_gapMng.bredr.keyMissingRetry = retry;
return GAP_SUCCESS;
}
int GAP_SetBondableMode(uint8_t bondableMode)
{
LOG_INFO("%{public}s:bondable[%hhu]", __FUNCTION__, bondableMode);
if (GapIsBredrEnable() == false) {
return GAP_ERR_NOT_ENABLE;
}
g_gapMng.bredr.bondableMode = bondableMode;
if (bondableMode == GAP_BONDABLE_MODE) {
GapReadNewLocalOOBData();
}
return GAP_SUCCESS;
}
static void GapFreeRegSecInfo(void *data)
{
MEM_MALLOC.free(data);
}
static void GapFreeReqSecInfo(void *data)
{
GapAuthenticationClearInfo(data);
MEM_MALLOC.free(data);
}
static void GapFreeDeviceInfo(void *data)
{
DeviceInfo *devInfo = data;
if (devInfo != NULL) {
if (devInfo->alarm != NULL) {
AlarmCancel(devInfo->alarm);
AlarmDelete(devInfo->alarm);
}
if (devInfo->aclAlarm != NULL) {
AlarmCancel(devInfo->aclAlarm);
AlarmDelete(devInfo->aclAlarm);
}
if (devInfo->waitEncryptAlarm != NULL) {
AlarmCancel(devInfo->waitEncryptAlarm);
AlarmDelete(devInfo->waitEncryptAlarm);
}
MEM_MALLOC.free(devInfo);
}
}
int GAP_RegisterServiceSecurity(const BtAddr *addr, const GapServiceSecurityInfo *serviceInfo, uint16_t securityMode)
{
int ret = GAP_SUCCESS;
ListNode *node = NULL;
ProfileSecurityInfo *regInfo = NULL;
if (GapIsBredrEnable() == false) {
return GAP_ERR_NOT_ENABLE;
}
ProfileSecurityBlock *profileSecurityBlock = GapGetProfileSecurityBlock();
node = ListGetFirstNode(profileSecurityBlock->registerlist);
while (node != 0) {
regInfo = (ProfileSecurityInfo *)ListGetNodeData(node);
if ((addr == NULL || GapIsEmptyAddr(addr->addr) || GapAddrCompare(addr, ®Info->addr)) &&
(regInfo->info.direction == serviceInfo->direction) &&
(regInfo->info.serviceId == serviceInfo->serviceId) &&
(regInfo->info.protocolId == serviceInfo->protocolId) &&
GapCompareChannelID(serviceInfo->protocolId, regInfo->info.channelId, serviceInfo->channelId)) {
ret = GAP_ERR_REPEATED;
LOG_WARN("Repeated Register Security %{public}d", serviceInfo->serviceId);
break;
}
node = ListGetNextNode(node);
}
if (node == NULL) {
regInfo = MEM_MALLOC.alloc(sizeof(ProfileSecurityInfo));
if (regInfo == NULL) {
ret = GAP_ERR_OUT_OF_RES;
} else {
(void)memset_s(regInfo, sizeof(ProfileSecurityInfo), 0x00, sizeof(ProfileSecurityInfo));
if (addr != NULL) {
(void)memcpy_s(®Info->addr, BT_ADDRESS_SIZE, addr, BT_ADDRESS_SIZE);
}
regInfo->info = *serviceInfo;
regInfo->securityMode = securityMode;
ListAddFirst(profileSecurityBlock->registerlist, regInfo);
}
}
if (addr != NULL) {
LOG_INFO("%{public}s:" BT_ADDR_FMT, __FUNCTION__, BT_ADDR_FMT_OUTPUT(addr->addr));
}
return ret;
}
int GAP_DeregisterServiceSecurity(const BtAddr *addr, const GapServiceSecurityInfo *serviceInfo)
{
int ret = GAP_SUCCESS;
ProfileSecurityBlock *profileSecurityBlock = NULL;
ListNode *node = NULL;
ProfileSecurityInfo *regInfo = NULL;
if (GapIsBredrEnable() == false) {
return GAP_ERR_NOT_ENABLE;
}
profileSecurityBlock = GapGetProfileSecurityBlock();
node = ListGetFirstNode(profileSecurityBlock->registerlist);
while (node != 0) {
regInfo = (ProfileSecurityInfo *)ListGetNodeData(node);
if ((addr == NULL || GapIsEmptyAddr(addr->addr) || GapAddrCompare(addr, ®Info->addr)) &&
regInfo->info.direction == serviceInfo->direction && regInfo->info.serviceId == serviceInfo->serviceId &&
regInfo->info.protocolId == serviceInfo->protocolId &&
GapCompareChannelID(serviceInfo->protocolId, regInfo->info.channelId, serviceInfo->channelId)) {
ListRemoveNode(profileSecurityBlock->registerlist, regInfo);
break;
}
node = ListGetNextNode(node);
}
if (node == NULL) {
LOG_WARN("%{public}s:not found", __FUNCTION__);
ret = GAP_ERR_INVAL_PARAM;
}
if (addr != NULL) {
LOG_INFO("%{public}s:" BT_ADDR_FMT, __FUNCTION__, BT_ADDR_FMT_OUTPUT(addr->addr));
}
return ret;
}
bool GapFindConnectionDeviceByAddr(void *nodeData, void *param)
{
DeviceInfo *deviceInfo = nodeData;
BtAddr *addr = param;
if (!memcmp(&deviceInfo->addr, addr, sizeof(BtAddr))) {
return true;
}
return false;
}
bool GapFindConnectionDeviceByHandle(void *nodeData, void *param)
{
DeviceInfo *deviceInfo = nodeData;
uint16_t handle = *(uint16_t *)param;
if (handle == deviceInfo->handle) {
return true;
}
return false;
}
bool GapFindCmpListData(void *nodeData, void *param)
{
return (nodeData == param);
}
void GapStopUseAclConnection(void *dev)
{
DeviceInfo *device = ListForEachData(GapGetConnectionInfoBlock()->devicelist, GapFindCmpListData, dev);
if (device != NULL) {
if (device->aclAlarm != NULL) {
AlarmCancel(device->aclAlarm);
}
BTM_AclRelease(device->handle);
}
}
void GapUseAclConnectionTimeoutTask(void *ctx)
{
DeviceInfo *dev = ((GapGeneralPointerInfo *)ctx)->pointer;
GapStopUseAclConnection(dev);
}
void GapUseAclConnectionTimeout(void *dev)
{
LOG_INFO("%{public}s: ", __FUNCTION__);
GapGeneralPointerInfo *ctx = MEM_MALLOC.alloc(sizeof(GapGeneralPointerInfo));
if (ctx == NULL) {
LOG_ERROR("%{public}s: Alloc error.", __FUNCTION__);
return;
}
ctx->pointer = dev;
int ret = GapRunTaskUnBlockProcess(GapUseAclConnectionTimeoutTask, ctx, NULL);
if (ret != BT_SUCCESS) {
LOG_ERROR("%{public}s: Task error:%{public}d.", __FUNCTION__, ret);
}
}
void GapStartUseAclConnection(DeviceInfo *device, uint64_t timeMs)
{
if (device != NULL) {
if (device->aclAlarm != NULL) {
AlarmCancel(device->aclAlarm);
AlarmSet(device->aclAlarm, timeMs, GapUseAclConnectionTimeout, device);
}
BTM_AclAddRef(device->handle);
}
}
int GAP_GetLocalExtendedOOBData(GapOOBData *oobData192, GapOOBData *oobData256)
{
int ret = GAP_SUCCESS;
(void)memcpy_s(oobData192, sizeof(GapOOBData), &g_gapMng.bredr.oobData192, sizeof(GapOOBData));
(void)memcpy_s(oobData256, sizeof(GapOOBData), &g_gapMng.bredr.oobData256, sizeof(GapOOBData));
return ret;
}
int GAP_GetLocalAddr(BtAddr *addr)
{
LOG_INFO("%{public}s:" BT_ADDR_FMT, __FUNCTION__, BT_ADDR_FMT_OUTPUT(addr->addr));
return BTM_GetLocalAddr(addr);
}
int GAP_SetLocalName(const char *name, int length)
{
HciWriteLocalNameParam param = {0};
LOG_INFO("%{public}s: name:%{public}s", __FUNCTION__, name);
if (GapIsBredrEnable() == false) {
return GAP_ERR_NOT_ENABLE;
}
(void)memcpy_s(param.localName, sizeof(param.localName), name, length);
return HCI_WriteLocalName(¶m);
}
int GAP_SetClassOfDevice(uint32_t cod)
{
LOG_INFO("%{public}s: cmd:%06x", __FUNCTION__, cod);
if (GapIsBredrEnable() == false) {
return GAP_ERR_NOT_ENABLE;
}
g_gapMng.bredr.classOfDevice = cod;
return GapWriteClassOfDevice(cod);
}
static int GapWriteClassOfDevice(uint32_t cod)
{
HciWriteClassofDeviceParam param = {
.classofDevice = COD_UINT_TO_ARRAY(cod),
};
return HCI_WriteClassofDevice(¶m);
}
void GapWriteClassOfDeviceComplete(const HciWriteClassofDeviceReturnParam *param)
{
LOG_DEBUG("%{public}s:", __FUNCTION__);
ScanModeBlock *scanModeBlock = NULL;
GapSetScanModeResultCallback callback = NULL;
uint8_t retStatus = param->status;
if (GapIsBredrEnable() == false) {
LOG_ERROR("%sNot Enable.", "");
return;
}
scanModeBlock = GapGetScanModeBlock();
if (scanModeBlock->status == GAP_SCANMODE_STATUS_SETTING) {
if (retStatus == HCI_SUCCESS) {
int ret;
if (scanModeBlock->connectableMode.mode) {
ret = GapWritePageScanActivity();
} else {
ret = GapWriteScanEnable();
}
if (ret != BT_SUCCESS) {
LOG_ERROR("HCI Command Error ret = %{public}d.", ret);
retStatus = GAP_STATUS_FAILED;
scanModeBlock->status = GAP_SCANMODE_STATUS_IDLE;
callback = scanModeBlock->callback;
}
} else {
scanModeBlock->status = GAP_SCANMODE_STATUS_IDLE;
callback = scanModeBlock->callback;
}
}
if (callback != NULL) {
callback(retStatus, scanModeBlock->context);
}
}
int GAP_SetExtendedInquiryResponse(const uint8_t eir[GAP_EIR_SIZE_MAX])
{
int ret;
HciWriteExtendedInquiryResponseParam hciCmdParam;
LOG_INFO("%{public}s:", __FUNCTION__);
if (GapIsBredrEnable() == false) {
return GAP_ERR_NOT_ENABLE;
}
(void)memcpy_s(hciCmdParam.extendInquiryRes, sizeof(hciCmdParam.extendInquiryRes), eir, GAP_EIR_SIZE_MAX);
hciCmdParam.fecRequired = GAP_EIR_FEC_REQUIRED;
ret = HCI_WriteExtendedInquiryResponse(&hciCmdParam);
return ret;
}
void GapSetExtendedInquiryResponseComplete(const HciWriteExtendedInquiryResponseReturnParam *param)
{
if (param->status) {
LOG_WARN("%{public}s:", __FUNCTION__);
}
}
static DeviceInfo *GapAllocDeviceInfo(const BtAddr *addr, const uint16_t handle)
{
DeviceInfo *deviceInfo = MEM_MALLOC.alloc(sizeof(DeviceInfo));
if (deviceInfo == NULL) {
LOG_ERROR("%{public}s:malloc error.", __FUNCTION__);
} else {
(void)memset_s(deviceInfo, sizeof(DeviceInfo), 0x00, sizeof(DeviceInfo));
deviceInfo->addr = *addr;
deviceInfo->handle = handle;
deviceInfo->status = GAP_DEV_SEC_STATUS_IDLE;
deviceInfo->authenticationStatus = GAP_AUTH_STATUS_IDLE;
deviceInfo->encryptionStatus = GAP_ENC_STATUS_IDLE;
deviceInfo->inDedicatedBonding = false;
deviceInfo->linkkeyType = GAP_LINK_KEY_TYPE_UNKNOWN;
deviceInfo->remoteAuthReq = AUTHENTICATION_UNKNOWN_MITM;
deviceInfo->alarm = AlarmCreate("gapSec", false);
deviceInfo->aclAlarm = AlarmCreate("gapAcl", false);
if (deviceInfo->alarm == NULL || deviceInfo->aclAlarm == NULL) {
LOG_ERROR("%{public}s: AlarmCreate failed, device tracked without alarm.", __FUNCTION__);
}
}
return deviceInfo;
}
void GapAclConnectionComplete(const BtmAclConnectCompleteParam *param, void *context)
{
ConnectionInfoBlock *connectionInfoBlock = NULL;
ProfileSecurityBlock *profileSecurityBlock = NULL;
DeviceInfo *deviceInfo = NULL;
RequestSecInfo *reqInfo = NULL;
connectionInfoBlock = GapGetConnectionInfoBlock();
profileSecurityBlock = GapGetProfileSecurityBlock();
if (param->status == HCI_SUCCESS) {
deviceInfo = GapAllocDeviceInfo(param->addr, param->connectionHandle);
if (deviceInfo == NULL) {
LOG_ERROR("%{public}s:malloc error.", __FUNCTION__);
} else {
ListAddFirst(connectionInfoBlock->devicelist, deviceInfo);
GapUpdateSecurityRequest(deviceInfo, GAP_SEC_EVENT_CONNECT_COMP, param->status);
if (*GapGetSecurityMode() != SEC_MODE_2) {
GapIsRemoteDeviceSupportHostSecureSimplePairingAsync(&deviceInfo->addr);
}
GapRequestSecurityProcess();
}
} else {
ListNode *node = ListGetFirstNode(profileSecurityBlock->requestlist);
while (node != 0) {
reqInfo = ListGetNodeData(node);
node = ListGetNextNode(node);
if (!GapAddrCompare(&reqInfo->addr, param->addr)) {
continue;
}
if (BtmInteropIsMatchedAddr(INTEROP_AUTO_RETRY_PAIRING, param->addr)) {
GapAuthenticationRetry(NULL, reqInfo, param->status);
continue;
}
reqInfo->status = GAP_SEC_REQ_STATUS_FAILED;
reqInfo->hciStatus = param->status;
if (reqInfo->info.serviceId == GAP) {
GapDoAuthenticationCallback(reqInfo);
}
if (!reqInfo->doCallback) {
reqInfo->doCallback = true;
GapDoSecurityCallback(reqInfo);
}
}
}
}
void GapAclDisconnectionComplete(uint8_t status, uint16_t connectionHandle, uint8_t reason, void *context)
{
ConnectionInfoBlock *connectionInfoBlock = NULL;
if (status == HCI_SUCCESS) {
DeviceInfo *info = NULL;
connectionInfoBlock = GapGetConnectionInfoBlock();
info = ListForEachData(
connectionInfoBlock->devicelist, GapFindConnectionDeviceByHandle, (void *)&connectionHandle);
if (info != NULL) {
GapUpdateSecurityRequest(info, GAP_SEC_EVENT_ACL_DISCONNECT, reason);
GapRequestSecurityProcess();
ListRemoveNode(connectionInfoBlock->devicelist, info);
}
}
}
#endif
#ifdef GAP_LE_SUPPORT
bool GapAddrIsResolvablePrivateAddress(const BtAddr *addr)
{
return (addr->type == BT_RANDOM_DEVICE_ADDRESS) && (addr->addr[5] & 0x40) && !(addr->addr[5] & 0x80);
}
bool GapAddrIsStaticAddress(const BtAddr *addr)
{
return (addr->type == BT_RANDOM_DEVICE_ADDRESS) && (addr->addr[5] & 0x40) && (addr->addr[5] & 0x80);
}
bool GapAddrIsPublicAddress(const BtAddr *addr)
{
return addr->type == BT_PUBLIC_DEVICE_ADDRESS;
}
bool GapAddrIsIdentityAddress(const BtAddr *addr)
{
return addr->type == BT_PUBLIC_IDENTITY_ADDRESS || addr->type == BT_RANDOM_IDENTITY_ADDRESS;
}
bool GapFindLeConnectionDeviceByAddr(void *nodeData, void *param)
{
LeDeviceInfo *deviceInfo = nodeData;
BtAddr *addr = param;
return GapAddrCompare(&deviceInfo->addr, addr);
}
bool GapFindLeConnectionDeviceByHandle(void *nodeData, void *param)
{
LeDeviceInfo *deviceInfo = nodeData;
uint16_t *handle = (uint16_t *)param;
return deviceInfo->handle == *handle;
}
int GAP_LeSetRole(uint8_t role)
{
LOG_INFO("%{public}s: role[%02x]", __FUNCTION__, role);
if (GapIsLeEnable() == false) {
return GAP_ERR_NOT_ENABLE;
}
g_gapMng.le.local.role = role;
if (GapLeRolesCheck(GAP_LE_ROLE_PERIPHERAL | GAP_LE_ROLE_CENTRAL) == true) {
BtmKey key;
BTM_GetLocalIdentityResolvingKey(&key);
SMP_SetIRK(key.key);
SMP_SetIdentAddr(&g_gapMng.le.local.addr);
}
return GAP_SUCCESS;
}
int GAP_LeSetStaticIdentityAddr(uint8_t addr[BT_ADDRESS_SIZE])
{
int ret;
LeLocalInfo *localInfo = NULL;
LOG_INFO("%{public}s:" BT_ADDR_FMT, __FUNCTION__, BT_ADDR_FMT_OUTPUT(addr));
if (GapIsLeEnable() == false) {
return GAP_ERR_NOT_ENABLE;
}
localInfo = GapGetLeLocalInfo();
if (localInfo->addr.type == BT_PUBLIC_DEVICE_ADDRESS) {
LOG_WARN("%{public}s: have public address " BT_ADDR_FMT, __FUNCTION__,
BT_ADDR_FMT_OUTPUT(localInfo->addr.addr));
localInfo->addr.type = BT_RANDOM_DEVICE_ADDRESS;
}
(void)memcpy_s(localInfo->addr.addr, BT_ADDRESS_SIZE, addr, BT_ADDRESS_SIZE);
ret = SMP_SetIdentAddr(&localInfo->addr);
return ret;
}
NO_SANITIZE("cfi") void GapGenerateRPAResult(uint8_t status, const uint8_t *addr)
{
GenResPriAddrResult callback = NULL;
void *context = NULL;
if (GapGetLeRandomAddressBlock()->generationInfo.processing) {
callback = GapGetLeRandomAddressBlock()->generationInfo.callback;
context = GapGetLeRandomAddressBlock()->generationInfo.context;
GapGetLeRandomAddressBlock()->generationInfo.processing = false;
GapGetLeRandomAddressBlock()->generationInfo.callback = NULL;
GapGetLeRandomAddressBlock()->generationInfo.context = NULL;
}
if (callback != NULL) {
callback(status, addr, context);
}
}
int GAP_LeGenResPriAddrAsync(GenResPriAddrResult callback, void *context)
{
LOG_INFO("%{public}s:", __FUNCTION__);
int ret;
BtmKey localIRK = {0};
ret = BTM_GetLocalIdentityResolvingKey(&localIRK);
if (ret != BT_SUCCESS) {
return ret;
}
ret = SMP_GenerateRPA(localIRK.key);
if (ret != BT_SUCCESS) {
return ret;
}
if (GapGetLeRandomAddressBlock()->generationInfo.processing == false) {
GapGetLeRandomAddressBlock()->generationInfo.callback = callback;
GapGetLeRandomAddressBlock()->generationInfo.context = context;
GapGetLeRandomAddressBlock()->generationInfo.processing = true;
} else {
ret = GAP_ERR_INVAL_STATE;
}
return ret;
}
#endif
Module g_gap = {
.name = MODULE_NAME_GAP,
.init = GapInitialize,
.startup = GapEnable,
.shutdown = GapDisable,
.cleanup = GapFinalize,
.dependencies = {MODULE_NAME_HCI, MODULE_NAME_L2CAP, MODULE_NAME_SMP},
};
MODULE_DECL(g_gap)