Merge "Bluetooth: Increasing the size of security service record and Adding null check to avoid exception after l2cap psm assigned"
diff --git a/bta/av/bta_av_act.c b/bta/av/bta_av_act.c
index fb1d560..d5fb64c 100644
--- a/bta/av/bta_av_act.c
+++ b/bta/av/bta_av_act.c
@@ -1526,10 +1526,13 @@
UNUSED(p_data);
p_cb->disabling = TRUE;
-
bta_av_close_all_rc(p_cb);
- utl_freebuf((void **) &p_cb->p_disc_db);
+ /*Cancel SDP if it had been started. */
+ if(p_cb->p_disc_db) {
+ (void)SDP_CancelServiceSearch (p_cb->p_disc_db);
+ utl_freebuf((void **) &p_cb->p_disc_db);
+ }
/* disable audio/video - de-register all channels,
* expect BTA_AV_DEREG_COMP_EVT when deregister is complete */
diff --git a/bta/dm/bta_dm_cfg.c b/bta/dm/bta_dm_cfg.c
index b09c7af..eac4269 100644
--- a/bta/dm/bta_dm_cfg.c
+++ b/bta/dm/bta_dm_cfg.c
@@ -56,6 +56,15 @@
#define tBTA_DM_PM_TYPE_QUALIFIER
#endif
+/* Reduce Idle timeout value due to intermediate timer */
+#ifndef BTA_JVS_IDLE_TO_SNIFF_DELAY_MS
+#define BTA_JVS_IDLE_TO_SNIFF_DELAY_MS BTA_FTS_OPS_IDLE_TO_SNIFF_DELAY_MS-BTA_JV_IDLE_TIMEOUT*1000
+#endif
+
+#ifndef BTA_JVC_IDLE_TO_SNIFF_DELAY_MS
+#define BTA_JVC_IDLE_TO_SNIFF_DELAY_MS 5000-BTA_JV_IDLE_TIMEOUT*1000
+#endif
+
const tBTA_DM_CFG bta_dm_cfg =
{
@@ -284,7 +293,7 @@
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app close */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco open */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco close */
- {{BTA_DM_PM_SNIFF_A2DP_IDX, 5000}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
+ {{BTA_DM_PM_SNIFF_A2DP_IDX, BTA_JVC_IDLE_TO_SNIFF_DELAY_MS}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
{{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */
}
@@ -303,7 +312,7 @@
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app close */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco open */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco close */
- {{BTA_DM_PM_SNIFF_A2DP_IDX, BTA_FTS_OPS_IDLE_TO_SNIFF_DELAY_MS}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
+ {{BTA_DM_PM_SNIFF_A2DP_IDX, BTA_JVS_IDLE_TO_SNIFF_DELAY_MS}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
{{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */
}
diff --git a/bta/include/bta_jv_api.h b/bta/include/bta_jv_api.h
index 2cd0d8e..f269266 100644
--- a/bta/include/bta_jv_api.h
+++ b/bta/include/bta_jv_api.h
@@ -68,6 +68,9 @@
#define BTA_JV_LAST_SERVICE_ID BTA_LAST_JV_SERVICE_ID
#define BTA_JV_NUM_SERVICE_ID (BTA_LAST_JV_SERVICE_ID - BTA_FIRST_JV_SERVICE_ID + 1)
+/* Intermediate Idle timeout(s) for TX/RX*/
+#define BTA_JV_IDLE_TIMEOUT 1
+
/* Discoverable modes */
enum
{
diff --git a/bta/jv/bta_jv_act.c b/bta/jv/bta_jv_act.c
index a1a61d6..9b58ba0 100644
--- a/bta/jv/bta_jv_act.c
+++ b/bta/jv/bta_jv_act.c
@@ -27,6 +27,7 @@
#include <stdlib.h>
#include "osi/include/allocator.h"
+#include "btu.h"
#include "bt_types.h"
#include "gki.h"
#include "utl.h"
@@ -77,7 +78,6 @@
static uint32_t fc_next_id;
static pthread_once_t fc_init_once = PTHREAD_ONCE_INIT;
-
static void fc_init_work(void)
{
fc_clients = NULL;
@@ -430,6 +430,13 @@
/* needs to be called if registered with bta pm, otherwise we may run out of dm pm slots! */
if (close_conn)
bta_sys_conn_close(BTA_ID_JV, p_pm_cb->app_id, p_pm_cb->peer_bd_addr);
+
+ if (p_pm_cb->is_idle_timer_started == TRUE)
+ {
+ /* Ensure that timer is stopped */
+ btu_stop_timer (&p_pm_cb->idle_tle);
+ p_pm_cb->is_idle_timer_started = FALSE;
+ }
p_pm_cb->state = BTA_JV_PM_FREE_ST;
p_pm_cb->app_id = BTA_JV_PM_ALL;
p_pm_cb->handle = BTA_JV_PM_HANDLE_CLEAR;
@@ -592,6 +599,10 @@
bta_jv_cb.pm_cb[i].app_id = app_id;
bdcpy(bta_jv_cb.pm_cb[i].peer_bd_addr, peer_bd_addr);
bta_jv_cb.pm_cb[i].state = BTA_JV_PM_IDLE_ST;
+ bta_jv_cb.pm_cb[i].is_idle_timer_started = FALSE;
+ bta_jv_cb.pm_cb[i].idle_tle.param = (UINT32) bta_jv_idle_timeout_handler;
+ bta_jv_cb.pm_cb[i].idle_tle.data = (UINT32) &bta_jv_cb.pm_cb[i];
+ APPL_TRACE_DEBUG("bta_jv_alloc_set_pm_profile_cb: %d, PM_cb: %p", i, &bta_jv_cb.pm_cb[i]);
return &bta_jv_cb.pm_cb[i];
}
APPL_TRACE_WARNING("bta_jv_alloc_set_pm_profile_cb(jv_handle: 0x%x, app_id: %d) "
@@ -1400,7 +1411,7 @@
evt_data.status = BTA_JV_SUCCESS;
}
ls->p_cb->p_cback(BTA_JV_L2CAP_WRITE_EVT, (tBTA_JV *)&evt_data, ls->user_data);
- bta_jv_set_pm_conn_state(ls->p_cb->p_pm_cb, BTA_JV_CONN_IDLE);
+ bta_jv_pm_conn_idle(ls->p_cb->p_pm_cb);
} else {
/* As this pointer is checked in the API function, this occurs only when the channel is
* disconnected after the API function is called, but before the message is handled. */
@@ -1464,7 +1475,9 @@
switch(type)
{
case DATA_CO_CALLBACK_TYPE_INCOMING:
+ bta_jv_pm_conn_busy(p_pcb->p_pm_cb);
ret = bta_co_rfc_data_incoming(p_pcb->user_data, (BT_HDR*)buf);
+ bta_jv_pm_conn_idle(p_pcb->p_pm_cb);
return ret;
case DATA_CO_CALLBACK_TYPE_OUTGOING_SIZE:
return bta_co_rfc_data_outgoing_size(p_pcb->user_data, (int*)buf);
@@ -2258,7 +2271,17 @@
static void bta_jv_pm_conn_busy(tBTA_JV_PM_CB *p_cb)
{
if ((NULL != p_cb) && (BTA_JV_PM_IDLE_ST == p_cb->state))
- bta_jv_pm_state_change(p_cb, BTA_JV_CONN_BUSY);
+ {
+ tBTM_PM_MODE mode = BTM_PM_MD_ACTIVE;
+ if (BTM_ReadPowerMode(p_cb->peer_bd_addr, &mode) == BTM_SUCCESS) {
+ if (mode == BTM_PM_MD_SNIFF) {
+ bta_jv_pm_state_change(p_cb, BTA_JV_CONN_BUSY);
+ } else {
+ p_cb->state = BTA_JV_PM_BUSY_ST;
+ APPL_TRACE_DEBUG("bta_jv_pm_conn_busy:power mode: %d", mode);
+ }
+ }
+ }
}
/*******************************************************************************
@@ -2274,8 +2297,17 @@
*******************************************************************************/
static void bta_jv_pm_conn_idle(tBTA_JV_PM_CB *p_cb)
{
- if ((NULL != p_cb) && (BTA_JV_PM_IDLE_ST != p_cb->state))
- bta_jv_pm_state_change(p_cb, BTA_JV_CONN_IDLE);
+ if ((NULL != p_cb) && (BTA_JV_PM_IDLE_ST != p_cb->state)) {
+ APPL_TRACE_DEBUG("bta_jv_pm_conn_idle, p_cb->is_idle_timer_started: %d, p_cb: %p",
+ p_cb->is_idle_timer_started, p_cb);
+ p_cb->state = BTA_JV_PM_IDLE_ST;
+ if (p_cb->is_idle_timer_started == FALSE) {
+ // start intermediate idle timer for 1s
+ btu_start_timer(&p_cb->idle_tle, BTU_TTYPE_USER_FUNC,
+ BTA_JV_IDLE_TIMEOUT);
+ p_cb->is_idle_timer_started = TRUE;
+ }
+ }
}
/*******************************************************************************
@@ -2753,3 +2785,34 @@
if (t)
fcclient_free(t);
}
+
+/*******************************************************************************
+**
+** Function bta_jv_idle_timeout_handler
+**
+** Description Bta JV specific idle timeout handler
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_jv_idle_timeout_handler(TIMER_LIST_ENT *tle) {
+ tBTA_JV_PM_CB *p_cb = (tBTA_JV_PM_CB *)tle->data;;
+ APPL_TRACE_DEBUG("%s p_cb: %p", __func__, p_cb);
+
+ if (NULL != p_cb) {
+ p_cb->is_idle_timer_started = FALSE;
+
+ tBTM_PM_MODE mode = BTM_PM_MD_ACTIVE;
+ if (BTM_ReadPowerMode(p_cb->peer_bd_addr, &mode) == BTM_SUCCESS) {
+ if (mode == BTM_PM_MD_SNIFF) {
+ APPL_TRACE_WARNING("%s: %d", __func__, mode)
+ return;
+ } else {
+ APPL_TRACE_DEBUG("%s: %d", __func__, mode);
+ }
+ }
+ bta_jv_pm_state_change(p_cb, BTA_JV_CONN_IDLE);
+ }
+}
+
diff --git a/bta/jv/bta_jv_int.h b/bta/jv/bta_jv_int.h
index eaaa75c..119f291 100644
--- a/bta/jv/bta_jv_int.h
+++ b/bta/jv/bta_jv_int.h
@@ -103,6 +103,8 @@
UINT8 state; /* state: see above enum */
tBTA_JV_PM_ID app_id; /* JV app specific id indicating power table to use */
BD_ADDR peer_bd_addr; /* Peer BD address */
+ BOOLEAN is_idle_timer_started; /* intermediate idle timer running status */
+ TIMER_LIST_ENT idle_tle; /* intermediate idle timer for paricular scb */
} tBTA_JV_PM_CB;
enum
@@ -447,5 +449,6 @@
extern void bta_jv_l2cap_stop_server_le (tBTA_JV_MSG *p_data);
extern void bta_jv_l2cap_write_fixed (tBTA_JV_MSG *p_data);
extern void bta_jv_l2cap_close_fixed (tBTA_JV_MSG *p_data);
+extern void bta_jv_idle_timeout_handler(TIMER_LIST_ENT *tle);
#endif /* BTA_JV_INT_H */
diff --git a/hci/include/hci_internals.h b/hci/include/hci_internals.h
index 6b9fb01..e28de6e 100644
--- a/hci/include/hci_internals.h
+++ b/hci/include/hci_internals.h
@@ -18,6 +18,14 @@
#pragma once
+#define REMOVE_EAGER_THREADS TRUE
+
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+#include "allocator.h"
+#include "thread.h"
+#include "reactor.h"
+#endif
+
// 2 bytes for opcode, 1 byte for parameter length (Volume 2, Part E, 5.4.1)
#define HCI_COMMAND_PREAMBLE_SIZE 3
// 2 bytes for handle, 2 bytes for data length (Volume 2, Part E, 5.4.2)
@@ -26,3 +34,31 @@
#define HCI_SCO_PREAMBLE_SIZE 3
// 1 byte for event code, 1 byte for parameter length (Volume 2, Part E, 5.4.4)
#define HCI_EVENT_PREAMBLE_SIZE 2
+
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+struct hci_reader_t {
+ int inbound_fd;
+
+ const allocator_t *allocator;
+ size_t buffer_size;
+ uint8_t *data_buffer;
+ int rd_ptr;
+ int wr_ptr;
+
+ thread_t *inbound_read_thread;
+ reactor_object_t *inbound_read_object;
+};
+typedef struct hci_reader_t hci_reader_t;
+typedef void (*hci_reader_cb)(void *context);
+
+hci_reader_t *hci_reader_new(
+ int fd_to_read,
+ size_t buffer_size,
+ size_t max_buffer_count,
+ thread_t *thread,
+ hci_reader_cb read_cb
+ );
+
+size_t hci_reader_read(hci_reader_t *reader, uint8_t *buffer, size_t max_size);
+void hci_reader_free(hci_reader_t *reader);
+#endif
diff --git a/hci/src/hci_hal.c b/hci/src/hci_hal.c
index fa526ce..a50d7ea 100644
--- a/hci/src/hci_hal.c
+++ b/hci/src/hci_hal.c
@@ -17,6 +17,14 @@
******************************************************************************/
#include "hci_hal.h"
+#include "hci_internals.h"
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+#include <assert.h>
+#include <string.h>
+#include "eager_reader.h"
+#include "osi.h"
+#include "log.h"
+#endif
const hci_hal_t *hci_hal_get_interface() {
#if HCI_USE_MCT
@@ -26,3 +34,87 @@
#endif
}
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+void hci_reader_free(hci_reader_t *reader) {
+ if (!reader)
+ return;
+
+ // Only unregister from the input if we actually did register
+ if (reader->inbound_read_object)
+ reactor_unregister(reader->inbound_read_object);
+
+ // Free the current buffer, because it's not in the queue
+ // and won't be freed below
+ if (reader->data_buffer)
+ osi_free(reader->data_buffer);
+
+ osi_free(reader);
+}
+
+hci_reader_t *hci_reader_new(
+ int fd_to_read,
+ size_t buffer_size,
+ size_t max_buffer_count,
+ thread_t *thread,
+ hci_reader_cb read_cb
+ ) {
+
+ assert(fd_to_read != INVALID_FD);
+ assert(buffer_size > 0);
+ assert(max_buffer_count > 0);
+
+
+ hci_reader_t *ret = osi_calloc(sizeof(hci_reader_t));
+ if (!ret) {
+ LOG_ERROR("%s unable to allocate memory for new hci_reader.", __func__);
+ goto error;
+ }
+
+ ret->inbound_fd = fd_to_read;
+
+ ret->data_buffer = osi_calloc(buffer_size);
+ ret->buffer_size = buffer_size;
+ ret->rd_ptr = 0;
+ ret->wr_ptr = 0;
+
+ ret->inbound_read_thread = thread;
+ if (!ret->inbound_read_thread) {
+ LOG_ERROR("%s unable to make reading thread.", __func__);
+ goto error;
+ }
+
+ ret->inbound_read_object = reactor_register(
+ thread_get_reactor(ret->inbound_read_thread),
+ fd_to_read,
+ ret,
+ read_cb,
+ NULL
+ );
+
+ return ret;
+
+error:;
+ hci_reader_free(ret);
+ return NULL;
+}
+
+size_t hci_reader_read(hci_reader_t *reader, uint8_t *buffer, size_t req_size) {
+ size_t bytes_read = 0;
+ assert(reader != NULL);
+ assert(buffer != NULL);
+
+ // If the caller wants nonblocking behavior, poll to see if we have
+ // any bytes available before reading.
+ if (reader->rd_ptr < reader->wr_ptr) {
+ bytes_read = reader->wr_ptr - reader->rd_ptr;
+ if (bytes_read > req_size)
+ bytes_read = req_size;
+ memcpy(buffer, reader->data_buffer+reader->rd_ptr, bytes_read);
+ reader->rd_ptr += bytes_read;
+ } else {
+ bytes_read = read(reader->inbound_fd, buffer, req_size);
+ }
+
+ return bytes_read;
+}
+#endif
diff --git a/hci/src/hci_hal_h4.c b/hci/src/hci_hal_h4.c
index 332c1a2..d4dc105 100644
--- a/hci/src/hci_hal_h4.c
+++ b/hci/src/hci_hal_h4.c
@@ -45,13 +45,23 @@
static thread_t *thread; // Not owned by us
static int uart_fd;
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+static hci_reader_t *uart_stream;
+#else
static eager_reader_t *uart_stream;
+#endif
static serial_data_type_t current_data_type;
static bool stream_has_interpretation;
static bool stream_corruption_detected;
static uint8_t stream_corruption_bytes_to_ignore;
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+static void event_uart_has_bytes(void *context);
+#else
static void event_uart_has_bytes(eager_reader_t *reader, void *context);
+#endif
+
+static bool stream_corrupted_during_le_scan_workaround(const uint8_t byte_read);
// Interface functions
@@ -82,20 +92,28 @@
goto error;
}
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+ uart_stream = hci_reader_new(uart_fd, HCI_HAL_SERIAL_BUFFER_SIZE, SIZE_MAX, thread, event_uart_has_bytes);
+ if (!uart_stream) {
+ LOG_ERROR("%s unable to create hci reader for the uart serial port.", __func__);
+ goto error;
+ }
+#else
uart_stream = eager_reader_new(uart_fd, &allocator_malloc, HCI_HAL_SERIAL_BUFFER_SIZE, SIZE_MAX, "hci_single_channel");
if (!uart_stream) {
LOG_ERROR("%s unable to create eager reader for the uart serial port.", __func__);
goto error;
}
+ eager_reader_register(uart_stream, thread_get_reactor(thread), event_uart_has_bytes, NULL);
+ thread_set_priority(eager_reader_get_read_thread(uart_stream), HCI_THREAD_PRIORITY);
+#endif
stream_has_interpretation = false;
stream_corruption_detected = false;
stream_corruption_bytes_to_ignore = 0;
- eager_reader_register(uart_stream, thread_get_reactor(thread), event_uart_has_bytes, NULL);
// Raise thread priorities to keep up with audio
thread_set_priority(thread, HCI_THREAD_PRIORITY);
- thread_set_priority(eager_reader_get_read_thread(uart_stream), HCI_THREAD_PRIORITY);
return true;
@@ -107,8 +125,12 @@
static void hal_close() {
LOG_INFO("%s", __func__);
-
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+ hci_reader_free(uart_stream);
+#else
eager_reader_free(uart_stream);
+#endif
+
vendor->send_command(VENDOR_CLOSE_USERIAL, NULL);
uart_fd = INVALID_FD;
}
@@ -125,7 +147,11 @@
return 0;
}
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+ return hci_reader_read(uart_stream, buffer, max_size);
+#else
return eager_reader_read(uart_stream, buffer, max_size, block);
+#endif
}
static void packet_finished(serial_data_type_t type) {
@@ -134,7 +160,24 @@
else if (current_data_type != type)
LOG_ERROR("%s with different type than existing interpretation.", __func__);
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+ if (uart_stream->rd_ptr == uart_stream->wr_ptr) {
+ uart_stream->rd_ptr = uart_stream->wr_ptr = 0;
+ stream_has_interpretation = false;
+ } else {
+ uint8_t type_byte;
+ type_byte = uart_stream->data_buffer[uart_stream->rd_ptr++];
+ if (type_byte < DATA_TYPE_ACL || type_byte > DATA_TYPE_EVENT) {
+ LOG_ERROR("%s Unknown HCI message type. Dropping this byte 0x%x, min %x, max %x", __func__,
+ type_byte, DATA_TYPE_ACL, DATA_TYPE_EVENT);
+ return;
+ }
+ current_data_type = type_byte;
+ callbacks->data_ready(current_data_type);
+ }
+#else
stream_has_interpretation = false;
+#endif
}
static uint16_t transmit_data(serial_data_type_t type, uint8_t *data, uint16_t length) {
@@ -225,6 +268,33 @@
}
// See what data is waiting, and notify the upper layer
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+static void event_uart_has_bytes(void *context) {
+ uint8_t type_byte;
+ size_t bytes_read;
+ hci_reader_t *reader = (hci_reader_t *) context;
+ bytes_read = read(reader->inbound_fd, reader->data_buffer + reader->wr_ptr, reader->buffer_size - reader->wr_ptr);
+
+ if (bytes_read <= 0) {
+ LOG_ERROR("%s could not read HCI message type", __func__);
+ return;
+ }
+ reader->wr_ptr += bytes_read;
+ if (!stream_has_interpretation) {
+ type_byte = reader->data_buffer[reader->rd_ptr++];
+
+ if (type_byte < DATA_TYPE_ACL || type_byte > DATA_TYPE_EVENT) {
+ LOG_ERROR("%s Unknown HCI message type. Dropping this byte 0x%x, min %x, max %x", __func__, type_byte, DATA_TYPE_ACL, DATA_TYPE_EVENT);
+ return;
+ }
+
+ stream_has_interpretation = true;
+ current_data_type = type_byte;
+ }
+
+ callbacks->data_ready(current_data_type);
+}
+#else
static void event_uart_has_bytes(eager_reader_t *reader, UNUSED_ATTR void *context) {
if (stream_has_interpretation) {
callbacks->data_ready(current_data_type);
@@ -247,6 +317,7 @@
current_data_type = type_byte;
}
}
+#endif
static const hci_hal_t interface = {
hal_init,
diff --git a/hci/src/hci_hal_mct.c b/hci/src/hci_hal_mct.c
index adc17c3..2c7a323 100644
--- a/hci/src/hci_hal_mct.c
+++ b/hci/src/hci_hal_mct.c
@@ -45,12 +45,22 @@
static thread_t *thread; // Not owned by us
static int uart_fds[CH_MAX];
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+static hci_reader_t *event_stream;
+static hci_reader_t *acl_stream;
+#else
static eager_reader_t *event_stream;
static eager_reader_t *acl_stream;
+#endif
static uint16_t transmit_data_on(int fd, uint8_t *data, uint16_t length);
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+static void event_event_stream_has_bytes(void *context);
+static void event_acl_stream_has_bytes(void *context);
+#else
static void event_event_stream_has_bytes(eager_reader_t *reader, void *context);
static void event_acl_stream_has_bytes(eager_reader_t *reader, void *context);
+#endif
// Interface functions
@@ -97,6 +107,21 @@
goto error;
}
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+ event_stream = hci_reader_new(uart_fds[CH_EVT], HCI_HAL_SERIAL_BUFFER_SIZE, SIZE_MAX,
+ thread, event_event_stream_has_bytes);
+ if (!event_stream) {
+ LOG_ERROR("%s unable to create hci reader for the event uart serial port.", __func__);
+ goto error;
+ }
+
+ acl_stream = hci_reader_new(uart_fds[CH_ACL_IN], HCI_HAL_SERIAL_BUFFER_SIZE, SIZE_MAX,
+ thread, event_acl_stream_has_bytes);
+ if (!acl_stream) {
+ LOG_ERROR("%s unable to create hci reader for the acl-in uart serial port.", __func__);
+ goto error;
+ }
+#else
event_stream = eager_reader_new(uart_fds[CH_EVT], &allocator_malloc, HCI_HAL_SERIAL_BUFFER_SIZE, SIZE_MAX, "hci_mct");
if (!event_stream) {
LOG_ERROR("%s unable to create eager reader for the event uart serial port.", __func__);
@@ -104,7 +129,7 @@
}
acl_stream = eager_reader_new(uart_fds[CH_ACL_IN], &allocator_malloc, HCI_HAL_SERIAL_BUFFER_SIZE, SIZE_MAX, "hci_mct");
- if (!event_stream) {
+ if (!acl_stream) {
LOG_ERROR("%s unable to create eager reader for the acl-in uart serial port.", __func__);
goto error;
}
@@ -112,6 +137,8 @@
eager_reader_register(event_stream, thread_get_reactor(thread), event_event_stream_has_bytes, NULL);
eager_reader_register(acl_stream, thread_get_reactor(thread), event_acl_stream_has_bytes, NULL);
+#endif
+
return true;
error:;
@@ -122,8 +149,14 @@
static void hal_close() {
LOG_INFO("%s", __func__);
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+ hci_reader_free(event_stream);
+ hci_reader_free(acl_stream);
+#else
eager_reader_free(event_stream);
eager_reader_free(acl_stream);
+#endif
+
vendor->send_command(VENDOR_CLOSE_USERIAL, NULL);
for (int i = 0; i < CH_MAX; i++)
@@ -156,11 +189,19 @@
#endif
static size_t read_data(serial_data_type_t type, uint8_t *buffer, size_t max_size, bool block) {
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+ if (type == DATA_TYPE_ACL) {
+ return hci_reader_read(acl_stream, buffer, max_size);
+ } else if (type == DATA_TYPE_EVENT) {
+ return hci_reader_read(event_stream, buffer, max_size);
+ }
+#else
if (type == DATA_TYPE_ACL) {
return eager_reader_read(acl_stream, buffer, max_size, block);
} else if (type == DATA_TYPE_EVENT) {
return eager_reader_read(event_stream, buffer, max_size, block);
}
+#endif
LOG_ERROR("%s invalid data type: %d", __func__, type);
return 0;
@@ -168,6 +209,25 @@
static void packet_finished(UNUSED_ATTR serial_data_type_t type) {
// not needed by this protocol
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+ hci_reader_t *stream = NULL;
+ if (type == DATA_TYPE_ACL) {
+ stream = acl_stream;
+ } else if (type == DATA_TYPE_EVENT) {
+ stream = event_stream;
+ }
+
+ if(!stream) {
+ LOG_ERROR("%s invalid data type: %d", __func__, type);
+ return;
+ }
+
+ if (stream->rd_ptr == stream->wr_ptr) {
+ stream->rd_ptr = stream->wr_ptr = 0;
+ } else {
+ callbacks->data_ready(type);
+ }
+#endif
}
static uint16_t transmit_data(serial_data_type_t type, uint8_t *data, uint16_t length) {
@@ -208,14 +268,45 @@
return transmitted_length;
}
-static void event_event_stream_has_bytes(UNUSED_ATTR eager_reader_t *reader, UNUSED_ATTR void *context) {
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+static void event_event_stream_has_bytes(void *context) {
+ size_t bytes_read;
+ hci_reader_t *reader = (hci_reader_t *) context;
+ bytes_read = read(reader->inbound_fd, reader->data_buffer+reader->wr_ptr,
+ reader->buffer_size - reader->wr_ptr);
+ if (bytes_read <= 0) {
+ LOG_ERROR("%s could not read HCI message type", __func__);
+ return;
+ }
+ reader->wr_ptr += bytes_read;
callbacks->data_ready(DATA_TYPE_EVENT);
}
+#else
+static void event_event_stream_has_bytes(UNUSED_ATTR eager_reader_t *reader, UNUSED_ATTR void *context) {
+ callbacks->data_ready(DATA_TYPE_EVENT);
+}
+#endif
-static void event_acl_stream_has_bytes(UNUSED_ATTR eager_reader_t *reader, UNUSED_ATTR void *context) {
+#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
+static void event_acl_stream_has_bytes(void *context) {
// No real concept of incoming SCO typed data, just ACL
+ size_t bytes_read;
+ hci_reader_t *reader = (hci_reader_t *) context;
+ bytes_read = read(reader->inbound_fd, reader->data_buffer+reader->wr_ptr,
+ reader->buffer_size - reader->wr_ptr);
+ if (bytes_read <= 0) {
+ LOG_ERROR("%s could not read HCI message type", __func__);
+ return;
+ }
+ reader->wr_ptr += bytes_read;
callbacks->data_ready(DATA_TYPE_ACL);
}
+#else
+static void event_acl_stream_has_bytes(UNUSED_ATTR eager_reader_t *reader, UNUSED_ATTR void *context) {
+ // No real concept of incoming SCO typed data, just ACL
+ callbacks->data_ready(DATA_TYPE_ACL);
+}
+#endif
static const hci_hal_t interface = {
hal_init,
diff --git a/stack/btu/btu_task.c b/stack/btu/btu_task.c
index e785f48..dc4351f 100644
--- a/stack/btu/btu_task.c
+++ b/stack/btu/btu_task.c
@@ -467,7 +467,6 @@
LOG_ERROR("%s Unable to create alarm", __func__);
return;
}
- alarm_cancel(alarm);
p_tle->event = type;
// NOTE: This value is in seconds but stored in a ticks field.
@@ -547,7 +546,6 @@
LOG_ERROR("%s Unable to create alarm", __func__);
return;
}
- alarm_cancel(alarm);
p_tle->event = type;
p_tle->ticks = timeout_ticks;
@@ -609,7 +607,6 @@
LOG_ERROR("%s Unable to create alarm", __func__);
return;
}
- alarm_cancel(alarm);
p_tle->event = type;
p_tle->in_use = TRUE;
diff --git a/stack/l2cap/l2c_fcr.c b/stack/l2cap/l2c_fcr.c
index 1bac4fa..f8011ae 100644
--- a/stack/l2cap/l2c_fcr.c
+++ b/stack/l2cap/l2c_fcr.c
@@ -195,6 +195,35 @@
/*******************************************************************************
**
+** Function l2c_fcr_restart_timer
+**
+** Description This function starts the (monitor or retransmission) timer.
+**
+** Returns -
+**
+*******************************************************************************/
+void l2c_fcr_restart_timer (tL2C_CCB *p_ccb)
+{
+ assert(p_ccb != NULL);
+ UINT32 tout;
+
+ /* The timers which are in milliseconds */
+ if (p_ccb->fcrb.wait_ack)
+ {
+ tout = (UINT32)p_ccb->our_cfg.fcr.mon_tout;
+ }
+ else
+ {
+ tout = (UINT32)p_ccb->our_cfg.fcr.rtrans_tout;
+ }
+
+ /* restart the mentioned timer */
+ btu_start_quick_timer (&p_ccb->fcrb.mon_retrans_timer, BTU_TTYPE_L2CAP_CHNL, tout*QUICK_TIMER_TICKS_PER_SEC/1000);
+}
+
+
+/*******************************************************************************
+**
** Function l2c_fcr_stop_timer
**
** Description This function stops the (monitor or transmission) timer.
@@ -1000,8 +1029,6 @@
}
/* If we are still in a wait_ack state, do not mess with the timer */
- if (!p_ccb->fcrb.wait_ack)
- l2c_fcr_stop_timer (p_ccb);
/* Check if we need to call the "packet_sent" callback */
if ( (p_ccb->p_rcb) && (p_ccb->p_rcb->api.pL2CA_TxComplete_Cb) && (full_sdus_xmitted) )
@@ -1015,8 +1042,13 @@
}
/* If anything still waiting for ack, restart the timer if it was stopped */
- if (!GKI_queue_is_empty(&p_fcrb->waiting_for_ack_q))
- l2c_fcr_start_timer (p_ccb);
+ if(!p_ccb->fcrb.wait_ack) {
+ if (!GKI_queue_is_empty(&p_fcrb->waiting_for_ack_q)) {
+ l2c_fcr_restart_timer (p_ccb);
+ }
+ else
+ l2c_fcr_stop_timer (p_ccb);
+ }
return (TRUE);
}