diff --git a/components/bt/bluedroid/btc/core/btc_profile_queue.c b/components/bt/bluedroid/btc/core/btc_profile_queue.c new file mode 100644 index 000000000..41300375e --- /dev/null +++ b/components/bt/bluedroid/btc/core/btc_profile_queue.c @@ -0,0 +1,169 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE 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 +#include "esp_bt_main.h" +#include "bt_trace.h" +#include "bt_defs.h" + +#include "btc_profile_queue.h" +#include "gki.h" +#include "list.h" +#include "allocator.h" + +/******************************************************************************* +** Local type definitions +*******************************************************************************/ +/******************************************************************************* +** Static variables +*******************************************************************************/ + +static list_t *connect_queue; + +static const size_t MAX_REASONABLE_REQUESTS = 10; + +/******************************************************************************* +** Queue helper functions +*******************************************************************************/ + +static void queue_int_add(connect_node_t *p_param) +{ + if (!connect_queue) { + connect_queue = list_new(osi_free_func); + assert(connect_queue != NULL); + } + + // Sanity check to make sure we're not leaking connection requests + assert(list_length(connect_queue) < MAX_REASONABLE_REQUESTS); + + for (const list_node_t *node = list_begin(connect_queue); node != list_end(connect_queue); node = list_next(node)) { + if (((connect_node_t *)list_node(node))->uuid == p_param->uuid) { + LOG_INFO("%s dropping duplicate connect request for uuid: %04x", __func__, p_param->uuid); + return; + } + } + + connect_node_t *p_node = osi_malloc(sizeof(connect_node_t)); + assert(p_node != NULL); + memcpy(p_node, p_param, sizeof(connect_node_t)); + list_append(connect_queue, p_node); +} + +static void queue_int_advance() +{ + if (connect_queue && !list_is_empty(connect_queue)) { + list_remove(connect_queue, list_front(connect_queue)); + } +} + +void btc_profile_queue_handler(btc_msg_t *msg) +{ + btc_prf_que_args_t *arg = (btc_prf_que_args_t *)(msg->arg); + switch (msg->act) { + case BTC_PRF_QUE_CONNECT: + queue_int_add(&(arg->connect_node)); + break; + + case BTC_PRF_QUE_ADVANCE: + queue_int_advance(); + break; + } + + if (esp_bluedroid_get_status() == ESP_BLUEDROID_STATUS_ENABLED) { + btc_queue_connect_next(); + } +} + +/******************************************************************************* +** +** Function btc_queue_connect +** +** Description Add a new connection to the queue and trigger the next +** scheduled connection. +** +** Returns BT_STATUS_SUCCESS if successful +** +*******************************************************************************/ +bt_status_t btc_queue_connect(uint16_t uuid, const bt_bdaddr_t *bda, btc_connect_cb_t connect_cb) +{ + btc_msg_t msg; + btc_prf_que_args_t arg; + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_PRF_QUE; + msg.act = BTC_PRF_QUE_CONNECT; + + memset(&arg, 0, sizeof(btc_prf_que_args_t)); + memcpy(&arg.connect_node.bda, bda, sizeof(bt_bdaddr_t)); + arg.connect_node.uuid = uuid; + arg.connect_node.connect_cb = connect_cb; + + return btc_transfer_context(&msg, &arg, sizeof(btc_prf_que_args_t), NULL); +} +/******************************************************************************* +** +** Function btif_queue_advance +** +** Description Clear the queue's busy status and advance to the next +** scheduled connection. +** +** Returns void +** +*******************************************************************************/ +void btc_queue_advance(void) +{ + btc_msg_t msg; + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_PRF_QUE; + msg.act = BTC_PRF_QUE_ADVANCE; + + btc_transfer_context(&msg, NULL, 0, NULL); +} + +// This function dispatches the next pending connect request. It is called from +// stack_manager when the stack comes up. +bt_status_t btc_queue_connect_next(void) +{ + if (!connect_queue || list_is_empty(connect_queue)) { + return BT_STATUS_FAIL; + } + + connect_node_t *p_head = list_front(connect_queue); + + // If the queue is currently busy, we return success anyway, + // since the connection has been queued... + if (p_head->busy) { + return BT_STATUS_SUCCESS; + } + + p_head->busy = true; + return p_head->connect_cb(&p_head->bda, p_head->uuid); +} + + +/******************************************************************************* +** +** Function btc_queue_release +** +** Description Free up all the queue nodes and set the queue head to NULL +** +** Returns void +** +*******************************************************************************/ +void btc_queue_release(void) +{ + list_free(connect_queue); + connect_queue = NULL; +} diff --git a/components/bt/bluedroid/btc/core/btc_task.c b/components/bt/bluedroid/btc/core/btc_task.c index 49c42bfde..58d1d0e5d 100644 --- a/components/bt/bluedroid/btc/core/btc_task.c +++ b/components/bt/bluedroid/btc/core/btc_task.c @@ -26,6 +26,7 @@ #include "btc_gap_bt.h" #include "btc_blufi_prf.h" #include "btc_dm.h" +#include "btc_profile_queue.h" #include "bta_gatt_api.h" @@ -44,7 +45,8 @@ static btc_func_t profile_tab[BTC_PID_NUM] = { [BTC_PID_SPP] = {NULL, NULL}, [BTC_PID_SPPLIKE] = {NULL, NULL}, [BTC_PID_BLUFI] = {btc_blufi_call_handler, btc_blufi_cb_handler }, - [BTC_PID_DM_SEC] = {NULL, btc_dm_sec_cb_handler } + [BTC_PID_DM_SEC] = {NULL, btc_dm_sec_cb_handler }, + [BTC_PID_PRF_QUE] = {btc_profile_queue_handler, NULL} }; /***************************************************************************** diff --git a/components/bt/bluedroid/btc/include/btc_profile_queue.h b/components/bt/bluedroid/btc/include/btc_profile_queue.h new file mode 100644 index 000000000..53e186762 --- /dev/null +++ b/components/bt/bluedroid/btc/include/btc_profile_queue.h @@ -0,0 +1,55 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE 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. + +/******************************************************************************* + * + * Filename: btC_profile_queue.h + * + * Description: Bluetooth remote device connection queuing + * + *******************************************************************************/ + +#ifndef __BTC_PROFILE_QUEUE_H__ +#define __BTC_PROFILE_QUEUE_H__ + +#include "bt_defs.h" +#include "btc_task.h" + +typedef enum { + BTC_PRF_QUE_CONNECT = 0, + BTC_PRF_QUE_ADVANCE +} btc_prf_que_act_t; + +typedef bt_status_t (*btc_connect_cb_t) (bt_bdaddr_t *bda, uint16_t uuid); + +typedef struct connect_node_t { + bt_bdaddr_t bda; + uint16_t uuid; + bool busy; + btc_connect_cb_t connect_cb; +} connect_node_t; + +/* btc_prf_que_args_t */ +typedef union { + // BTC_PRF_QUE_CONNECT + connect_node_t connect_node; +} btc_prf_que_args_t; + +bt_status_t btc_queue_connect(uint16_t uuid, const bt_bdaddr_t *bda, btc_connect_cb_t connect_cb); +void btc_queue_advance(void); +bt_status_t btc_queue_connect_next(void); +void btc_queue_release(void); + +void btc_profile_queue_handler(btc_msg_t *msg); +#endif /* __BTC_PROFILE_QUEUE_H__ */ diff --git a/components/bt/bluedroid/btc/include/btc_task.h b/components/bt/bluedroid/btc/include/btc_task.h index 4f9774000..5e6dbce2e 100644 --- a/components/bt/bluedroid/btc/include/btc_task.h +++ b/components/bt/bluedroid/btc/include/btc_task.h @@ -46,6 +46,7 @@ typedef enum { BTC_PID_SPPLIKE, BTC_PID_BLUFI, BTC_PID_DM_SEC, + BTC_PID_PRF_QUE, BTC_PID_NUM, } btc_pid_t; //btc profile id