679 lines
20 KiB
C
679 lines
20 KiB
C
|
#include <string.h>
|
||
|
#include <stdio.h>
|
||
|
#include <assert.h>
|
||
|
|
||
|
#include "fr30xx.h"
|
||
|
|
||
|
#include "btdm_host.h"
|
||
|
#include "FreeRTOS.h"
|
||
|
#include "timers.h"
|
||
|
#include "semphr.h"
|
||
|
|
||
|
#include "fdb_app.h"
|
||
|
#include "host.h"
|
||
|
|
||
|
#include "me_api.h"
|
||
|
#include "bt_types.h"
|
||
|
#include "app_config.h"
|
||
|
|
||
|
#define HOST_DDB_RECORD_COUNT 8
|
||
|
#define HOST_DDB_INFOR_VERSION 0x01
|
||
|
|
||
|
#define HCI_UART UART0
|
||
|
#define HCI_UART_IRQn UART0_IRQn
|
||
|
|
||
|
/* Uart backup/restore */
|
||
|
typedef struct
|
||
|
{
|
||
|
volatile uint8_t BAK_DLL;
|
||
|
volatile uint8_t BAK_DLH;
|
||
|
volatile uint8_t BAK_DLF;
|
||
|
volatile uint8_t BAK_IER;
|
||
|
volatile uint8_t BAK_FCR;
|
||
|
volatile uint8_t BAK_LCR;
|
||
|
volatile uint8_t BAK_MCR;
|
||
|
}struct_UartRES_t;
|
||
|
|
||
|
struct host_ddb_info {
|
||
|
uint8_t version;
|
||
|
uint8_t used_count;
|
||
|
BtDeviceRecord ddb[HOST_DDB_RECORD_COUNT];
|
||
|
};
|
||
|
|
||
|
static TimerHandle_t btdm_host_timer = NULL;
|
||
|
static bool btdm_host_timer_inited = false;
|
||
|
|
||
|
static const uint8_t *write_buffer = 0;
|
||
|
static uint32_t write_length = 0;
|
||
|
static void (*write_callback)(void) = 0;
|
||
|
|
||
|
static uint8_t *read_buffer = 0;
|
||
|
static uint32_t read_length = 0;
|
||
|
static void (*read_callback)(void *, uint8_t) = 0;
|
||
|
static void *read_dummy = 0;
|
||
|
|
||
|
/* host semaphore handle */
|
||
|
SemaphoreHandle_t host_Semaphore_handle;
|
||
|
|
||
|
/* host task handle */
|
||
|
static TaskHandle_t btdm_host_handle;
|
||
|
|
||
|
/* hardware handlers */
|
||
|
static UART_HandleTypeDef HCI_handle;
|
||
|
|
||
|
/* structure used to save and restore uart configuration when sleep mode is enabled */
|
||
|
static struct_UartRES_t uart_regs;
|
||
|
|
||
|
#define READ_REG(__ADDR__) (*(volatile uint32_t *)(__ADDR__))
|
||
|
#define WRTIE_REG(__ADDR__, __VALUE__) (*(volatile uint32_t *)(__ADDR__) = (__VALUE__))
|
||
|
|
||
|
/************************************************************************************
|
||
|
* @fn Uart_backup/Uart_restore
|
||
|
*
|
||
|
* @brief Uart low-power backup/restore
|
||
|
*/
|
||
|
__RAM_CODE static void __Uart_backup(struct_UART_t *Uartx, struct_UartRES_t *UartRES)
|
||
|
{
|
||
|
volatile uint32_t UartxBase = (uint32_t)Uartx;
|
||
|
|
||
|
UartRES->BAK_LCR = READ_REG(UartxBase + 0x0C);
|
||
|
UartRES->BAK_MCR = READ_REG(UartxBase + 0x10);
|
||
|
UartRES->BAK_FCR = 0x09;
|
||
|
UartRES->BAK_IER = READ_REG(UartxBase + 0x04);
|
||
|
|
||
|
WRTIE_REG(UartxBase + 0x0C, UartRES->BAK_LCR | 0x80);
|
||
|
|
||
|
UartRES->BAK_DLL = READ_REG(UartxBase);
|
||
|
UartRES->BAK_DLH = READ_REG(UartxBase + 0x04);
|
||
|
UartRES->BAK_DLF = READ_REG(UartxBase + 0xC0);
|
||
|
|
||
|
WRTIE_REG(UartxBase + 0x0C, UartRES->BAK_LCR);
|
||
|
}
|
||
|
__RAM_CODE static void __Uart_restore(struct_UART_t *Uartx, struct_UartRES_t *UartRES)
|
||
|
{
|
||
|
volatile uint32_t UartxBase = (uint32_t)Uartx;
|
||
|
|
||
|
WRTIE_REG(UartxBase + 0x04, UartRES->BAK_IER);
|
||
|
WRTIE_REG(UartxBase + 0x08, UartRES->BAK_FCR);
|
||
|
WRTIE_REG(UartxBase + 0x10, UartRES->BAK_MCR);
|
||
|
WRTIE_REG(UartxBase + 0x0C, UartRES->BAK_LCR | 0x80);
|
||
|
WRTIE_REG(UartxBase, UartRES->BAK_DLL);
|
||
|
WRTIE_REG(UartxBase + 0x04, UartRES->BAK_DLH);
|
||
|
WRTIE_REG(UartxBase + 0xC0, UartRES->BAK_DLF);
|
||
|
WRTIE_REG(UartxBase + 0x0C, UartRES->BAK_LCR);
|
||
|
}
|
||
|
|
||
|
static void hci_uart_rx_callback(UART_HandleTypeDef *h)
|
||
|
{
|
||
|
read_length = 0;
|
||
|
read_callback(read_dummy, 0);
|
||
|
}
|
||
|
|
||
|
static void hci_uart_tx_callback(UART_HandleTypeDef *h)
|
||
|
{
|
||
|
write_length = 0;
|
||
|
write_callback();
|
||
|
system_prevent_sleep_clear(SYSTEM_PREVENT_SLEEP_TYPE_HCI_TX);
|
||
|
}
|
||
|
|
||
|
static void vTimerCallback( TimerHandle_t pxTimer )
|
||
|
{
|
||
|
btdm_timer_trigger();
|
||
|
}
|
||
|
|
||
|
void btdm_timer_start(uint32_t ms)
|
||
|
{
|
||
|
if (!btdm_host_timer_inited) {
|
||
|
btdm_host_timer = xTimerCreate( "Timer", ms / portTICK_PERIOD_MS, pdTRUE, NULL, vTimerCallback);
|
||
|
btdm_host_timer_inited = true;
|
||
|
}
|
||
|
xTimerStop(btdm_host_timer, portMAX_DELAY);
|
||
|
xTimerChangePeriod(btdm_host_timer, ms / portTICK_RATE_MS, portMAX_DELAY);
|
||
|
xTimerStart(btdm_host_timer, portMAX_DELAY);
|
||
|
}
|
||
|
|
||
|
void btdm_timer_stop(void)
|
||
|
{
|
||
|
if(btdm_host_timer) {
|
||
|
xTimerStop(btdm_host_timer, portMAX_DELAY);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
uint32_t btdm_get_system_time(void)
|
||
|
{
|
||
|
return xTaskGetTickCount() * portTICK_RATE_MS;
|
||
|
}
|
||
|
|
||
|
int btdm_time_diff(uint32_t a_time, uint32_t b_time)
|
||
|
{
|
||
|
return b_time - a_time;
|
||
|
}
|
||
|
|
||
|
void hci_if_do_send(const uint8_t *buffer, uint32_t length, void (*func)(void))
|
||
|
{
|
||
|
struct app_task_event * event;
|
||
|
uint32_t print_size = length > 8 ? 8 : length;
|
||
|
|
||
|
assert(write_length == 0);
|
||
|
|
||
|
write_buffer = buffer;
|
||
|
write_length = length;
|
||
|
write_callback = func;
|
||
|
|
||
|
#if 1
|
||
|
system_prevent_sleep_set(SYSTEM_PREVENT_SLEEP_TYPE_HCI_TX);
|
||
|
uart_transmit_IT(&HCI_handle, (void *)buffer, length);
|
||
|
#else
|
||
|
uart_transmit(&HCI_handle, (void *)buffer, length);
|
||
|
write_callback();
|
||
|
write_length = 0;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
void hci_if_do_recv(uint8_t *bufptr, uint32_t size, void *arg, void* dummy)
|
||
|
{
|
||
|
struct app_task_event * event;
|
||
|
|
||
|
assert(read_length == 0);
|
||
|
|
||
|
read_buffer = bufptr;
|
||
|
read_length = size;
|
||
|
read_callback = (void (*)(void *, uint8_t))arg;
|
||
|
read_dummy = dummy;
|
||
|
|
||
|
uart_receive_IT(&HCI_handle, bufptr, size);
|
||
|
}
|
||
|
|
||
|
void btdm_host_notify_schedule(void)
|
||
|
{
|
||
|
if(xPortIsInsideInterrupt()) {
|
||
|
vTaskNotifyGiveFromISR(btdm_host_handle, NULL);
|
||
|
}
|
||
|
else {
|
||
|
xTaskNotifyGive(btdm_host_handle);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
__WEAK void host_ready_cb(void)
|
||
|
{
|
||
|
// struct app_task_event *event;
|
||
|
// /* notify application BTDM stack is ready. */
|
||
|
// event = app_task_event_alloc(APP_TASK_EVENT_HOST_INITED, 0, true);
|
||
|
// app_task_event_post(event, false);
|
||
|
}
|
||
|
|
||
|
static void host_hw_init(uint32_t baudrate)
|
||
|
{
|
||
|
GPIO_InitTypeDef gpio_config;
|
||
|
/* configure PA0 and PA1 to UART0 function */
|
||
|
gpio_config.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3;
|
||
|
gpio_config.Mode = GPIO_MODE_AF_PP;
|
||
|
gpio_config.Pull = GPIO_PULLUP;
|
||
|
gpio_config.Alternate = GPIO_FUNCTION_1;
|
||
|
gpio_init(GPIOA, &gpio_config);
|
||
|
|
||
|
/* UART0: used for Log and AT command */
|
||
|
HCI_handle.UARTx = HCI_UART;
|
||
|
HCI_handle.Init.BaudRate = baudrate;
|
||
|
HCI_handle.Init.DataLength = UART_DATA_LENGTH_8BIT;
|
||
|
HCI_handle.Init.StopBits = UART_STOPBITS_1;
|
||
|
HCI_handle.Init.Parity = UART_PARITY_NONE;
|
||
|
HCI_handle.Init.FIFO_Mode = UART_FIFO_ENABLE;
|
||
|
HCI_handle.TxCpltCallback = hci_uart_tx_callback;
|
||
|
HCI_handle.RxCpltCallback = hci_uart_rx_callback;
|
||
|
uart_init(&HCI_handle);
|
||
|
/* keep RTS is inactive before HCI is ready */
|
||
|
__UART_AUTO_FLOW_CONTROL_DISABLE(HCI_handle.UARTx);
|
||
|
__UART_RTS_INACTIVE(HCI_handle.UARTx);
|
||
|
// __UART_RxFIFO_THRESHOLD((&HCI_handle), 2);
|
||
|
NVIC_SetPriority(HCI_UART_IRQn, 2);
|
||
|
NVIC_EnableIRQ(HCI_UART_IRQn);
|
||
|
}
|
||
|
|
||
|
static void host_btdm_task(void *ble_static_addr)
|
||
|
{
|
||
|
struct host_ddb_info *info;
|
||
|
size_t size;
|
||
|
|
||
|
/* Initialize BLE stack */
|
||
|
struct ble_host_param param;
|
||
|
if (ble_static_addr) {
|
||
|
param.own_addr_type = 1;
|
||
|
memcpy(¶m.own_addr.addr[0], ble_static_addr, 6);
|
||
|
}
|
||
|
else {
|
||
|
param.own_addr_type = 0;
|
||
|
}
|
||
|
|
||
|
host_Semaphore_handle = xSemaphoreCreateRecursiveMutex();
|
||
|
|
||
|
ble_host_init(¶m);
|
||
|
|
||
|
/* HCI is ready */
|
||
|
__UART_AUTO_FLOW_CONTROL_ENABLE(HCI_handle.UARTx);
|
||
|
__UART_RTS_ACTIVE(HCI_handle.UARTx);
|
||
|
while(ble_host_ready() == false) {
|
||
|
ulTaskNotifyTake(pdFALSE, portMAX_DELAY);
|
||
|
btdm_host_schedule_ble();
|
||
|
}
|
||
|
|
||
|
/* check whether link key information stored in flashdb is valid or not */
|
||
|
info = pvPortMalloc(sizeof(struct host_ddb_info));
|
||
|
size = flashdb_get(FDB_KEY_BT_LINKKEY, (void *)info, sizeof(struct host_ddb_info));
|
||
|
if ((size != 0)
|
||
|
&& ((sizeof(struct host_ddb_info) != size)
|
||
|
|| (info->version != HOST_DDB_INFOR_VERSION)
|
||
|
|| (info->used_count > HOST_DDB_RECORD_COUNT))) {
|
||
|
flashdb_del(FDB_KEY_BT_LINKKEY);
|
||
|
}
|
||
|
vPortFree(info);
|
||
|
|
||
|
// Initialize BT stack
|
||
|
bt_host_init();
|
||
|
#if BTDM_STACK_ENABLE_A2DP_SNK | BTDM_STACK_ENABLE_A2DP_SRC
|
||
|
bt_a2dp_init();
|
||
|
#endif
|
||
|
#if BTDM_STACK_ENABLE_AVRCP
|
||
|
bt_avrcp_init();
|
||
|
#endif
|
||
|
#if BTDM_STACK_ENABLE_HF
|
||
|
bt_hf_init();
|
||
|
#endif
|
||
|
#if BTDM_STACK_ENABLE_AG
|
||
|
bt_hfg_init();
|
||
|
#endif
|
||
|
|
||
|
#if BTDM_STACK_ENABLE_PAN
|
||
|
bt_pan_init();
|
||
|
#endif
|
||
|
#if BTDM_STACK_ENABLE_PBAP
|
||
|
bt_pbap_init();
|
||
|
#endif
|
||
|
#if BTDM_STACK_ENABLE_SPP
|
||
|
bt_spp_init();
|
||
|
#endif
|
||
|
while(bt_host_ready() == false) {
|
||
|
ulTaskNotifyTake(pdFALSE, portMAX_DELAY);
|
||
|
btdm_host_schedule();
|
||
|
}
|
||
|
|
||
|
host_ready_cb();
|
||
|
|
||
|
while(1) {
|
||
|
ulTaskNotifyTake(pdFALSE, portMAX_DELAY);
|
||
|
btdm_host_schedule();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void host_ble_task(void *ble_static_addr)
|
||
|
{
|
||
|
struct app_task_event *event;
|
||
|
struct host_ddb_info *info;
|
||
|
size_t size;
|
||
|
|
||
|
/* Initialize BLE stack */
|
||
|
struct ble_host_param param;
|
||
|
if (ble_static_addr) {
|
||
|
param.own_addr_type = 1;
|
||
|
memcpy(¶m.own_addr.addr[0], ble_static_addr, 6);
|
||
|
}
|
||
|
else {
|
||
|
param.own_addr_type = 0;
|
||
|
}
|
||
|
ble_host_init(¶m);
|
||
|
printf("HCI is ready.\r\n");
|
||
|
/* HCI is ready */
|
||
|
__UART_AUTO_FLOW_CONTROL_ENABLE(HCI_handle.UARTx);
|
||
|
__UART_RTS_ACTIVE(HCI_handle.UARTx);
|
||
|
while(ble_host_ready() == false) {
|
||
|
ulTaskNotifyTake(pdFALSE, portMAX_DELAY);
|
||
|
btdm_host_schedule_ble();
|
||
|
}
|
||
|
|
||
|
host_ready_cb();
|
||
|
|
||
|
while(1) {
|
||
|
ulTaskNotifyTake(pdFALSE, portMAX_DELAY);
|
||
|
btdm_host_schedule_ble();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/************************************************************************************
|
||
|
* @fn host_btdm_start
|
||
|
*
|
||
|
* @brief Initializes bt dual mode host, host task will be created in this function.
|
||
|
* host_ble_start and host_btdm_start should not be called together.
|
||
|
*
|
||
|
* @param baudrate: uart baudrate of HCI
|
||
|
* stack_size: stack size of host task
|
||
|
* priority: priority of host task
|
||
|
* ble_static_addr: If public address will be used as identity address, this field
|
||
|
* should be set NULL. Otherwise random static address stored in
|
||
|
* ble_static_addr will be used as identity address.
|
||
|
*/
|
||
|
void host_btdm_start(uint32_t baudrate, uint32_t stack_size, uint8_t priority, const uint8_t *ble_static_addr)
|
||
|
{
|
||
|
host_hw_init(baudrate);
|
||
|
xTaskCreate(host_btdm_task, "host", stack_size, (void *)ble_static_addr, priority, &btdm_host_handle);
|
||
|
}
|
||
|
|
||
|
/************************************************************************************
|
||
|
* @fn host_ble_start
|
||
|
*
|
||
|
* @brief Initializes ble host, host task will be created in this function.
|
||
|
* host_ble_start and host_btdm_start should not be called together.
|
||
|
*
|
||
|
* @param baudrate: uart baudrate of HCI
|
||
|
* stack_size: stack size of host task
|
||
|
* priority: priority of host task
|
||
|
* ble_static_addr: If public address will be used as identity address, this field
|
||
|
* should be set NULL. Otherwise random static address stored in
|
||
|
* ble_static_addr will be used as identity address.
|
||
|
*/
|
||
|
void host_ble_start(uint32_t baudrate, uint32_t stack_size, uint8_t priority, const uint8_t *ble_static_addr)
|
||
|
{
|
||
|
host_hw_init(baudrate);
|
||
|
xTaskCreate(host_ble_task, "host", stack_size, (void *)ble_static_addr, priority, &btdm_host_handle);
|
||
|
}
|
||
|
|
||
|
//void host_stop(void)
|
||
|
//{
|
||
|
// uint32_t *dst, *src, *end;
|
||
|
|
||
|
// if(btdm_host_timer_inited) {
|
||
|
// xTimerDelete(btdm_host_timer, portMAX_DELAY);
|
||
|
// btdm_host_timer = NULL;
|
||
|
// btdm_host_timer_inited = false;
|
||
|
// }
|
||
|
// vTaskDelete(btdm_host_handle);
|
||
|
//
|
||
|
// btdm_mem_uninit();
|
||
|
|
||
|
// write_buffer = 0;
|
||
|
// write_length = 0;
|
||
|
// write_callback = 0;
|
||
|
|
||
|
// read_buffer = 0;
|
||
|
// read_length = 0;
|
||
|
// read_callback = 0;
|
||
|
// read_dummy = 0;
|
||
|
//
|
||
|
// dst = (uint32_t *)&Image$$HOST_DATA$$RW$$Base;
|
||
|
// src=(uint32_t *)&Load$$HOST_DATA$$RW$$Base;
|
||
|
// end = (uint32_t *)&Load$$HOST_DATA$$RW$$Limit;
|
||
|
// for(; (uint32_t)src<(uint32_t)end;)
|
||
|
// {
|
||
|
// *dst++ = *src++;
|
||
|
// }
|
||
|
|
||
|
// dst = (uint32_t *)&Image$$HOST_DATA$$ZI$$Base;
|
||
|
// end = (uint32_t *)&Image$$HOST_DATA$$ZI$$Limit;
|
||
|
// for(; dst < end;)
|
||
|
// {
|
||
|
// *dst++ = 0;
|
||
|
// }
|
||
|
//}
|
||
|
|
||
|
BtStatus DDB_AddRecord(const BtDeviceRecord* record)
|
||
|
{
|
||
|
fdb_err_t err;
|
||
|
struct host_ddb_info *info;
|
||
|
size_t size;
|
||
|
|
||
|
info = pvPortMalloc(sizeof(struct host_ddb_info));
|
||
|
if (info) {
|
||
|
uint32_t index = 0;
|
||
|
size = flashdb_get(FDB_KEY_BT_LINKKEY, (void *)info, sizeof(struct host_ddb_info));
|
||
|
if (size == 0) {
|
||
|
info->version = HOST_DDB_INFOR_VERSION;
|
||
|
info->used_count = 0;
|
||
|
}
|
||
|
else {
|
||
|
if ((size != sizeof(struct host_ddb_info))
|
||
|
|| (info->version != HOST_DDB_INFOR_VERSION)
|
||
|
|| (info->used_count > HOST_DDB_RECORD_COUNT)) {
|
||
|
if (flashdb_del(FDB_KEY_BT_LINKKEY) != FDB_NO_ERR) {
|
||
|
vPortFree(info);
|
||
|
return BT_STATUS_FAILED;
|
||
|
}
|
||
|
else {
|
||
|
info->version = HOST_DDB_INFOR_VERSION;
|
||
|
info->used_count = 0;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* search for duplicated record according to bluetooth device address */
|
||
|
for (index = 0; index < info->used_count; index++) {
|
||
|
if (memcmp((void *)&info->ddb[index].bdAddr.A, (void *)&record->bdAddr, sizeof(BD_ADDR)) == 0) {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if (index < info->used_count) {
|
||
|
/* duplicated device is found, delete the found device and move forward the information of subsequence devices */
|
||
|
memcpy((void *)&info->ddb[index], (void *)&info->ddb[index+1], sizeof(BtDeviceRecord) * (info->used_count-1-index));
|
||
|
index = info->used_count - 1;
|
||
|
}
|
||
|
else {
|
||
|
if (info->used_count == HOST_DDB_RECORD_COUNT) {
|
||
|
/* the table is full, remove the oldest device information */
|
||
|
memcpy((void *)&info->ddb[0], (void *)&info->ddb[1], sizeof(BtDeviceRecord) * (HOST_DDB_RECORD_COUNT-1));
|
||
|
index = HOST_DDB_RECORD_COUNT-1;
|
||
|
}
|
||
|
else {
|
||
|
index = info->used_count;
|
||
|
info->used_count++;
|
||
|
}
|
||
|
}
|
||
|
memcpy((void *)&info->ddb[index], (void *)record, sizeof(BtDeviceRecord));
|
||
|
|
||
|
printf("linkey: ");
|
||
|
for(uint8_t i=0; i<16; i++){
|
||
|
printf("%02x ",record->linkKey[i]);
|
||
|
}
|
||
|
printf("\r\n");
|
||
|
|
||
|
err = flashdb_set(FDB_KEY_BT_LINKKEY, (void *)info, sizeof(struct host_ddb_info));
|
||
|
vPortFree(info);
|
||
|
if (err != FDB_NO_ERR) {
|
||
|
return BT_STATUS_FAILED;
|
||
|
}
|
||
|
else {
|
||
|
return BT_STATUS_SUCCESS;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
return BT_STATUS_FAILED;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
BtStatus DDB_FindRecord(const BD_ADDR *bdAddr, BtDeviceRecord* record)
|
||
|
{
|
||
|
fdb_err_t err;
|
||
|
struct host_ddb_info *info;
|
||
|
size_t size;
|
||
|
BtStatus status;
|
||
|
|
||
|
info = pvPortMalloc(sizeof(struct host_ddb_info));
|
||
|
if (info) {
|
||
|
uint32_t index = 0;
|
||
|
size = flashdb_get(FDB_KEY_BT_LINKKEY, (void *)info, sizeof(struct host_ddb_info));
|
||
|
if (size == 0) {
|
||
|
vPortFree(info);
|
||
|
return BT_STATUS_FAILED;
|
||
|
}
|
||
|
else {
|
||
|
if ((size != sizeof(struct host_ddb_info))
|
||
|
|| (info->version != HOST_DDB_INFOR_VERSION)
|
||
|
|| (info->used_count > HOST_DDB_RECORD_COUNT)) {
|
||
|
flashdb_del(FDB_KEY_BT_LINKKEY);
|
||
|
vPortFree(info);
|
||
|
return BT_STATUS_FAILED;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* search for duplicated record according to bluetooth device address */
|
||
|
for (index = 0; index < info->used_count; index++) {
|
||
|
if (memcmp((void *)&info->ddb[index].bdAddr.A, (void *)bdAddr, sizeof(BD_ADDR)) == 0) {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if (index < info->used_count) {
|
||
|
/* information is found */
|
||
|
memcpy((void *)record, (void *)&info->ddb[index], sizeof(BtDeviceRecord));
|
||
|
status = BT_STATUS_SUCCESS;
|
||
|
if ((index+1) != info->used_count) {
|
||
|
memcpy((void *)&info->ddb[index], (void *)&info->ddb[index+1], sizeof(BtDeviceRecord) * (info->used_count-1-index));
|
||
|
memcpy((void *)&info->ddb[info->used_count - 1], (void *)record, sizeof(BtDeviceRecord));
|
||
|
|
||
|
err = flashdb_set(FDB_KEY_BT_LINKKEY, (void *)info, sizeof(struct host_ddb_info));
|
||
|
if (err != FDB_NO_ERR) {
|
||
|
status = BT_STATUS_FAILED;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
status = BT_STATUS_FAILED;
|
||
|
}
|
||
|
|
||
|
vPortFree(info);
|
||
|
return status;
|
||
|
}
|
||
|
else {
|
||
|
return BT_STATUS_FAILED;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
enum btdm_nvds_status btdm_nvds_put(uint8_t tag, uint16_t length, uint8_t *data)
|
||
|
{
|
||
|
enum btdm_nvds_status status = BTDM_NVDS_STATUS_FAILED;
|
||
|
uint32_t fdb_key;
|
||
|
|
||
|
if (tag == BTDM_NVDS_TAG_CONTROLLER_INFO) {
|
||
|
fdb_key = FDB_KEY_CONTROLLER_INFO;
|
||
|
}
|
||
|
else {
|
||
|
fdb_key = FDB_KEY_BTDM_LIB_BASE | tag;
|
||
|
}
|
||
|
if (flashdb_set(fdb_key, data, length) == FDB_NO_ERR) {
|
||
|
status = BTDM_NVDS_STATUS_OK;
|
||
|
}
|
||
|
else {
|
||
|
status = BTDM_NVDS_STATUS_FAILED;
|
||
|
}
|
||
|
|
||
|
return status;
|
||
|
}
|
||
|
|
||
|
enum btdm_nvds_status btdm_nvds_get(uint8_t tag, uint16_t *length, uint8_t *buffer)
|
||
|
{
|
||
|
*length = flashdb_get(FDB_KEY_BTDM_LIB_BASE | tag, buffer, *length);
|
||
|
|
||
|
if (*length == 0) {
|
||
|
return BTDM_NVDS_STATUS_FAILED;
|
||
|
}
|
||
|
else {
|
||
|
return BTDM_NVDS_STATUS_OK;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
enum btdm_nvds_status btdm_nvds_del(uint8_t tag)
|
||
|
{
|
||
|
enum btdm_nvds_status status = BTDM_NVDS_STATUS_FAILED;
|
||
|
|
||
|
if (flashdb_del(FDB_KEY_BTDM_LIB_BASE | tag) == FDB_NO_ERR) {
|
||
|
status = BTDM_NVDS_STATUS_OK;
|
||
|
}
|
||
|
else {
|
||
|
status = BTDM_NVDS_STATUS_FAILED;
|
||
|
}
|
||
|
|
||
|
return status;
|
||
|
}
|
||
|
|
||
|
void uart0_irq(void)
|
||
|
{
|
||
|
uart_IRQHandler(&HCI_handle);
|
||
|
}
|
||
|
|
||
|
/************************************************************************************
|
||
|
* @fn host_before_sleep_check
|
||
|
*
|
||
|
* @brief user should call this function to check whether HCI is in busy state before
|
||
|
* enter sleep mode. When HCI is in IDLE state, this function will return True and
|
||
|
* RTS will be changed to GPIO mode and output high level to suspend HCI transfer.
|
||
|
*
|
||
|
* @return True: HCI is in IDLE state, user is allowed to enter sleep mode.
|
||
|
* False: HCI is in busy state, user is not allowed to enter sleep mode.
|
||
|
*/
|
||
|
__RAM_CODE bool host_before_sleep_check(void)
|
||
|
{
|
||
|
if (__UART_IS_TxFIFO_EMPTY(HCI_handle.UARTx) == 0) {
|
||
|
return false;
|
||
|
}
|
||
|
/* set RTS to notice host device that UART is not available*/
|
||
|
__SYSTEM_GPIOA_CLK_ENABLE();
|
||
|
GPIOA->GPIO_OutputEN &= (~GPIO_PIN_3);
|
||
|
GPIOA->GPIO_BIT_SET = GPIO_PIN_3;
|
||
|
SYSTEM->PortA_L_FuncMux &= (~(0xf<<12));
|
||
|
system_delay_us(100);
|
||
|
if (__UART_IS_RxFIFO_EMPTY(HCI_handle.UARTx)) {
|
||
|
/* keep RTS pin is controllered by GPIO */
|
||
|
__Uart_backup(HCI_handle.UARTx, &uart_regs);
|
||
|
return true;
|
||
|
}
|
||
|
else {
|
||
|
/* recover RTS pin is controllered by UART */
|
||
|
SYSTEM->PortA_L_FuncMux |= (GPIO_FUNCTION_1<<12);
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/************************************************************************************
|
||
|
* @fn host_hci_reinit
|
||
|
*
|
||
|
* @brief When system wake up from sleep mode, user should call this function to recover
|
||
|
* HCI.
|
||
|
*/
|
||
|
__RAM_CODE void host_hci_reinit(void)
|
||
|
{
|
||
|
GPIO_InitTypeDef gpio_config;
|
||
|
|
||
|
/* configure PA0 and PA1 to UART0 function */
|
||
|
gpio_config.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3;
|
||
|
gpio_config.Mode = GPIO_MODE_AF_PP;
|
||
|
gpio_config.Pull = GPIO_PULLUP;
|
||
|
gpio_config.Alternate = GPIO_FUNCTION_1;
|
||
|
gpio_init(GPIOA, &gpio_config);
|
||
|
|
||
|
__SYSTEM_UART0_CLK_ENABLE();
|
||
|
__Uart_restore(HCI_handle.UARTx, &uart_regs);
|
||
|
|
||
|
NVIC_SetPriority(HCI_UART_IRQn, 2);
|
||
|
NVIC_EnableIRQ(HCI_UART_IRQn);
|
||
|
}
|
||
|
|
||
|
void btdm_host_lock(void)
|
||
|
{
|
||
|
// volatile uint32_t address;
|
||
|
// __asm("MOV %[result], LR":[result] "=r" (address));
|
||
|
|
||
|
if(xPortIsInsideInterrupt() == 0){
|
||
|
xSemaphoreTakeRecursive(host_Semaphore_handle,portMAX_DELAY);
|
||
|
}
|
||
|
else{
|
||
|
while(1);
|
||
|
//xSemaphoreTakeFromISR(host_Semaphore_handle,NULL);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void btdm_host_unlock(void)
|
||
|
{
|
||
|
if(xPortIsInsideInterrupt() == 0){
|
||
|
xSemaphoreGiveRecursive(host_Semaphore_handle);
|
||
|
}
|
||
|
else{
|
||
|
while(1);
|
||
|
}
|
||
|
}
|