diff options
33 files changed, 411 insertions, 114 deletions
diff --git a/audio_a2dp_hw/audio_a2dp_hw.c b/audio_a2dp_hw/audio_a2dp_hw.c index 3e2bc2dde..19f7dfd04 100644 --- a/audio_a2dp_hw/audio_a2dp_hw.c +++ b/audio_a2dp_hw/audio_a2dp_hw.c @@ -125,6 +125,8 @@ struct a2dp_stream_common { struct a2dp_stream_out { struct audio_stream_out stream; struct a2dp_stream_common common; + uint64_t frames_presented; // frames written, never reset + uint64_t frames_rendered; // frames written, reset on standby }; struct a2dp_stream_in { @@ -720,6 +722,10 @@ static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, out->common.state = AUDIO_A2DP_STATE_STOPPED; else ERROR("write failed : stream suspended, avoid resetting state"); + } else { + const size_t frames = bytes / audio_stream_out_frame_size(stream); + out->frames_rendered += frames; + out->frames_presented += frames; } DEBUG("wrote %d bytes out of %zu bytes", sent, bytes); @@ -801,9 +807,9 @@ static int out_standby(struct audio_stream *stream) DUT need to clear flag else start will not happen but Do nothing in SUSPENDED state. */ if (out->common.state != AUDIO_A2DP_STATE_SUSPENDED) - retVal = suspend_audio_datapath(&out->common, true); - - pthread_mutex_unlock(&out->common.lock); + retVal = suspend_audio_datapath(&out->common, true); + out->frames_rendered = 0; // rendered is reset, presented is not + pthread_mutex_unlock (&out->common.lock); return retVal; } @@ -972,16 +978,45 @@ static int out_set_volume(struct audio_stream_out *stream, float left, return -ENOSYS; } +static int out_get_presentation_position(const struct audio_stream_out *stream, + uint64_t *frames, struct timespec *timestamp) +{ + struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; + FNLOG(); + if (stream == NULL || frames == NULL || timestamp == NULL) + return -EINVAL; + + int ret = -EWOULDBLOCK; + pthread_mutex_lock(&out->common.lock); + uint64_t latency_frames = (uint64_t)out_get_latency(stream) * out->common.cfg.rate / 1000; + if (out->frames_presented >= latency_frames) { + *frames = out->frames_presented - latency_frames; + clock_gettime(CLOCK_MONOTONIC, timestamp); // could also be associated with out_write(). + ret = 0; + } + pthread_mutex_unlock(&out->common.lock); + return ret; +} static int out_get_render_position(const struct audio_stream_out *stream, uint32_t *dsp_frames) { - UNUSED(stream); - UNUSED(dsp_frames); + struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; FNLOG(); - return -EINVAL; + if (stream == NULL || dsp_frames == NULL) + return -EINVAL; + + pthread_mutex_lock(&out->common.lock); + uint64_t latency_frames = (uint64_t)out_get_latency(stream) * out->common.cfg.rate / 1000; + if (out->frames_rendered >= latency_frames) { + *dsp_frames = (uint32_t)(out->frames_rendered - latency_frames); + } else { + *dsp_frames = 0; + } + pthread_mutex_unlock(&out->common.lock); + return 0; } static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect) @@ -1239,6 +1274,8 @@ static int adev_open_output_stream(struct audio_hw_device *dev, out->stream.set_volume = out_set_volume; out->stream.write = out_write; out->stream.get_render_position = out_get_render_position; + out->stream.get_presentation_position = out_get_presentation_position; + /* initialize a2dp specifics */ a2dp_stream_common_init(&out->common); diff --git a/bta/dm/bta_dm_act.c b/bta/dm/bta_dm_act.c index d81fb32dc..8d441c322 100644 --- a/bta/dm/bta_dm_act.c +++ b/bta/dm/bta_dm_act.c @@ -3565,7 +3565,6 @@ static void bta_dm_disable_conn_down_timer_cback (TIMER_LIST_ENT *p_tle) *******************************************************************************/ static void bta_dm_rm_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8 app_id, BD_ADDR peer_addr) { - UINT8 j; tBTA_PREF_ROLES role; tBTA_DM_PEER_DEVICE *p_dev; @@ -3619,7 +3618,11 @@ static void bta_dm_rm_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8 app_id, APPL_TRACE_WARNING("bta_dm_rm_cback:%d, status:%d", bta_dm_cb.cur_av_count, status); } - bta_dm_adjust_roles(FALSE); + /* Don't adjust roles for each busy/idle state transition to avoid + excessive switch requests when individual profile busy/idle status + changes */ + if ((status != BTA_SYS_CONN_BUSY) && (status != BTA_SYS_CONN_IDLE)) + bta_dm_adjust_roles(FALSE); } /******************************************************************************* @@ -3734,7 +3737,7 @@ static void bta_dm_adjust_roles(BOOLEAN delay_role_switch) } if((bta_dm_cb.device_list.peer_device[i].pref_role == BTA_MASTER_ROLE_ONLY) - || (bta_dm_cb.device_list.count > 1)) + || (br_count > 1)) { /* Initiating immediate role switch with certain remote devices @@ -3743,7 +3746,8 @@ static void bta_dm_adjust_roles(BOOLEAN delay_role_switch) versions are stored in a blacklist and role switch with these devices are delayed to avoid the collision with link encryption setup */ - if (delay_role_switch == FALSE) + if (bta_dm_cb.device_list.peer_device[i].pref_role != BTA_SLAVE_ROLE_ONLY && + delay_role_switch == FALSE) { BTM_SwitchRole (bta_dm_cb.device_list.peer_device[i].peer_bdaddr, HCI_ROLE_MASTER, NULL); diff --git a/bta/dm/bta_dm_cfg.c b/bta/dm/bta_dm_cfg.c index 48b442bf3..b09c7afd6 100644 --- a/bta/dm/bta_dm_cfg.c +++ b/bta/dm/bta_dm_cfg.c @@ -86,7 +86,11 @@ const tBTA_DM_CFG bta_dm_cfg = #define BTA_AV_ROLE BTA_MASTER_ROLE_PREF #endif -#define BTA_DM_NUM_RM_ENTRY 4 +#ifndef BTA_PANU_ROLE +/* By default, AV role (backward BTA_MASTER_ROLE_PREF) */ +#define BTA_PANU_ROLE BTA_SLAVE_ROLE_ONLY +#endif +#define BTA_DM_NUM_RM_ENTRY 6 /* appids for PAN used by insight sample application these have to be same as defined in btui_int.h */ @@ -100,8 +104,10 @@ const tBTA_DM_CFG bta_dm_cfg = const tBTA_DM_RM bta_dm_rm_cfg[] = { {BTA_ID_SYS, BTA_DM_NUM_RM_ENTRY, BTA_DM_SCATTERNET}, - {BTA_ID_PAN, BTUI_PAN_ID_NAP, BTA_MASTER_ROLE_ONLY}, - {BTA_ID_PAN, BTUI_PAN_ID_GN, BTA_MASTER_ROLE_ONLY}, + {BTA_ID_PAN, BTUI_PAN_ID_NAP, BTA_ANY_ROLE}, + {BTA_ID_PAN, BTUI_PAN_ID_GN, BTA_ANY_ROLE}, + {BTA_ID_PAN, BTA_APP_ID_PAN_MULTI, BTA_MASTER_ROLE_ONLY}, + {BTA_ID_PAN, BTUI_PAN_ID_PANU, BTA_PANU_ROLE}, {BTA_ID_HH, BTA_ALL_APP_ID, BTA_HH_ROLE}, {BTA_ID_AV, BTA_ALL_APP_ID, BTA_AV_ROLE} }; diff --git a/bta/gatt/bta_gattc_act.c b/bta/gatt/bta_gattc_act.c index 078de1271..4ec1f33ab 100755 --- a/bta/gatt/bta_gattc_act.c +++ b/bta/gatt/bta_gattc_act.c @@ -54,6 +54,9 @@ static void bta_gattc_conn_cback(tGATT_IF gattc_if, BD_ADDR bda, UINT16 conn_id, static void bta_gattc_cmpl_cback(UINT16 conn_id, tGATTC_OPTYPE op, tGATT_STATUS status, tGATT_CL_COMPLETE *p_data); +static void bta_gattc_cmpl_sendmsg(UINT16 conn_id, tGATTC_OPTYPE op, + tBTA_GATT_STATUS status, + tGATT_CL_COMPLETE *p_data); static void bta_gattc_deregister_cmpl(tBTA_GATTC_RCB *p_clreg); static void bta_gattc_enc_cmpl_cback(tGATT_IF gattc_if, BD_ADDR bda); @@ -934,7 +937,6 @@ void bta_gattc_restart_discover(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data *******************************************************************************/ void bta_gattc_cfg_mtu(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) { - tBTA_GATTC_OP_CMPL op_cmpl; tBTA_GATT_STATUS status; if (bta_gattc_enqueue(p_clcb, p_data)) @@ -944,13 +946,11 @@ void bta_gattc_cfg_mtu(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) /* if failed, return callback here */ if (status != GATT_SUCCESS && status != GATT_CMD_STARTED) { - memset(&op_cmpl, 0, sizeof(tBTA_GATTC_OP_CMPL)); + /* Dequeue the data, if it was enqueued */ + if (p_clcb->p_q_cmd == p_data) + p_clcb->p_q_cmd = NULL; - op_cmpl.status = status; - op_cmpl.op_code = GATTC_OPTYPE_CONFIG; - op_cmpl.p_cmpl = NULL; - - bta_gattc_sm_execute(p_clcb, BTA_GATTC_OP_CMPL_EVT, (tBTA_GATTC_DATA *)&op_cmpl); + bta_gattc_cmpl_sendmsg(p_clcb->bta_conn_id, GATTC_OPTYPE_CONFIG, status, NULL); } } } @@ -1094,10 +1094,9 @@ void bta_gattc_read(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) { UINT16 handle = 0; tGATT_READ_PARAM read_param; - tBTA_GATTC_OP_CMPL op_cmpl; + tBTA_GATT_STATUS status; memset (&read_param, 0 ,sizeof(tGATT_READ_PARAM)); - memset (&op_cmpl, 0 ,sizeof(tBTA_GATTC_OP_CMPL)); if (bta_gattc_enqueue(p_clcb, p_data)) { @@ -1106,23 +1105,24 @@ void bta_gattc_read(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) &p_data->api_read.char_id, p_data->api_read.p_descr_type)) == 0) { - op_cmpl.status = BTA_GATT_ERROR; + status = BTA_GATT_ERROR; } else { read_param.by_handle.handle = handle; read_param.by_handle.auth_req = p_data->api_read.auth_req; - op_cmpl.status = GATTC_Read(p_clcb->bta_conn_id, GATT_READ_BY_HANDLE, &read_param); + status = GATTC_Read(p_clcb->bta_conn_id, GATT_READ_BY_HANDLE, &read_param); } /* read fail */ - if (op_cmpl.status != BTA_GATT_OK) + if (status != BTA_GATT_OK) { - op_cmpl.op_code = GATTC_OPTYPE_READ; - op_cmpl.p_cmpl = NULL; + /* Dequeue the data, if it was enqueued */ + if (p_clcb->p_q_cmd == p_data) + p_clcb->p_q_cmd = NULL; - bta_gattc_sm_execute(p_clcb, BTA_GATTC_OP_CMPL_EVT, (tBTA_GATTC_DATA *)&op_cmpl); + bta_gattc_cmpl_sendmsg(p_clcb->bta_conn_id, GATTC_OPTYPE_READ, status, NULL); } } } @@ -1139,7 +1139,6 @@ void bta_gattc_read_multi(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) UINT16 i, handle; tBTA_GATT_STATUS status = BTA_GATT_OK; tGATT_READ_PARAM read_param; - tBTA_GATTC_OP_CMPL op_cmpl; tBTA_GATTC_ATTR_ID *p_id; if (bta_gattc_enqueue(p_clcb, p_data)) @@ -1188,13 +1187,11 @@ void bta_gattc_read_multi(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) /* read fail */ if (status != BTA_GATT_OK) { - memset(&op_cmpl, 0, sizeof(tBTA_GATTC_OP_CMPL)); - - op_cmpl.status = status; - op_cmpl.op_code = GATTC_OPTYPE_READ; - op_cmpl.p_cmpl = NULL; + /* Dequeue the data, if it was enqueued */ + if (p_clcb->p_q_cmd == p_data) + p_clcb->p_q_cmd = NULL; - bta_gattc_sm_execute(p_clcb, BTA_GATTC_OP_CMPL_EVT, (tBTA_GATTC_DATA *)&op_cmpl); + bta_gattc_cmpl_sendmsg(p_clcb->bta_conn_id, GATTC_OPTYPE_READ, status, NULL); } } } @@ -1211,7 +1208,6 @@ void bta_gattc_write(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) { UINT16 handle = 0; tGATT_VALUE attr = {0}; - tBTA_GATTC_OP_CMPL op_cmpl; tBTA_GATT_STATUS status = BTA_GATT_OK; if (bta_gattc_enqueue(p_clcb, p_data)) @@ -1239,13 +1235,11 @@ void bta_gattc_write(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) /* write fail */ if (status != BTA_GATT_OK) { - memset(&op_cmpl, 0, sizeof(tBTA_GATTC_OP_CMPL)); - - op_cmpl.status = status; - op_cmpl.op_code = GATTC_OPTYPE_WRITE; - op_cmpl.p_cmpl = NULL; + /* Dequeue the data, if it was enqueued */ + if (p_clcb->p_q_cmd == p_data) + p_clcb->p_q_cmd = NULL; - bta_gattc_sm_execute(p_clcb, BTA_GATTC_OP_CMPL_EVT, (tBTA_GATTC_DATA *)&op_cmpl); + bta_gattc_cmpl_sendmsg(p_clcb->bta_conn_id, GATTC_OPTYPE_WRITE, status, NULL); } } } @@ -1259,7 +1253,6 @@ void bta_gattc_write(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) *********************************************************************************/ void bta_gattc_execute(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) { - tBTA_GATTC_OP_CMPL op_cmpl; tBTA_GATT_STATUS status; if (bta_gattc_enqueue(p_clcb, p_data)) @@ -1268,13 +1261,11 @@ void bta_gattc_execute(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) if (status != BTA_GATT_OK) { - memset(&op_cmpl, 0, sizeof(tBTA_GATTC_OP_CMPL)); + /* Dequeue the data, if it was enqueued */ + if (p_clcb->p_q_cmd == p_data) + p_clcb->p_q_cmd = NULL; - op_cmpl.status = status; - op_cmpl.op_code = GATTC_OPTYPE_EXE_WRITE; - op_cmpl.p_cmpl = NULL; - - bta_gattc_sm_execute(p_clcb, BTA_GATTC_OP_CMPL_EVT, (tBTA_GATTC_DATA *)&op_cmpl); + bta_gattc_cmpl_sendmsg(p_clcb->bta_conn_id, GATTC_OPTYPE_EXE_WRITE, status, NULL); } } } @@ -1801,7 +1792,6 @@ static void bta_gattc_deregister_cmpl(tBTA_GATTC_RCB *p_clreg) /******************************************************************************* ** ** Function bta_gattc_conn_cback -** bta_gattc_cmpl_cback ** ** Description callback functions to GATT client stack. ** @@ -2140,10 +2130,7 @@ void bta_gattc_process_indicate(UINT16 conn_id, tGATTC_OPTYPE op, tGATT_CL_COMPL static void bta_gattc_cmpl_cback(UINT16 conn_id, tGATTC_OPTYPE op, tGATT_STATUS status, tGATT_CL_COMPLETE *p_data) { - tBTA_GATTC_CLCB *p_clcb ; - tBTA_GATTC_OP_CMPL *p_buf; - UINT16 len = sizeof(tBTA_GATTC_OP_CMPL) + sizeof(tGATT_CL_COMPLETE); - + tBTA_GATTC_CLCB *p_clcb; APPL_TRACE_DEBUG("bta_gattc_cmpl_cback: conn_id = %d op = %d status = %d", conn_id, op, status); p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id); @@ -2169,7 +2156,26 @@ static void bta_gattc_cmpl_cback(UINT16 conn_id, tGATTC_OPTYPE op, tGATT_STATUS bta_sys_idle(BTA_ID_GATTC, BTA_ALL_APP_ID, p_clcb->bda); } - if ((p_buf = (tBTA_GATTC_OP_CMPL *) GKI_getbuf(len)) != NULL) + bta_gattc_cmpl_sendmsg(conn_id, op, status, p_data); +} + +/******************************************************************************* +** +** Function bta_gattc_cmpl_sendmsg +** +** Description client operation complete send message +** +** Returns None. +** +*******************************************************************************/ +static void bta_gattc_cmpl_sendmsg(UINT16 conn_id, tGATTC_OPTYPE op, + tBTA_GATT_STATUS status, + tGATT_CL_COMPLETE *p_data) +{ + const UINT16 len = sizeof(tBTA_GATTC_OP_CMPL) + sizeof(tGATT_CL_COMPLETE); + tBTA_GATTC_OP_CMPL *p_buf = (tBTA_GATTC_OP_CMPL *) GKI_getbuf(len); + + if (p_buf != NULL) { memset(p_buf, 0, len); p_buf->hdr.event = BTA_GATTC_OP_CMPL_EVT; @@ -2185,8 +2191,6 @@ static void bta_gattc_cmpl_cback(UINT16 conn_id, tGATTC_OPTYPE op, tGATT_STATUS bta_sys_sendmsg(p_buf); } - - return; } /******************************************************************************* diff --git a/bta/include/bta_api.h b/bta/include/bta_api.h index b6446eecc..5f9d05536 100644 --- a/bta/include/bta_api.h +++ b/bta/include/bta_api.h @@ -187,6 +187,7 @@ typedef UINT16 tBTA_SEC; /* Ignore for Discoverable, Connectable only for LE modes */ #define BTA_DM_LE_IGNORE 0xFF00 +#define BTA_APP_ID_PAN_MULTI 0xFE /* app id for pan multiple connection */ #define BTA_ALL_APP_ID 0xFF /* Discoverable Modes */ @@ -254,6 +255,7 @@ typedef UINT8 tBTA_AUTH_RESP; #define BTA_ANY_ROLE 0x00 #define BTA_MASTER_ROLE_PREF 0x01 #define BTA_MASTER_ROLE_ONLY 0x02 +#define BTA_SLAVE_ROLE_ONLY 0x03 /* Used for PANU only, skip role switch to master */ typedef UINT8 tBTA_PREF_ROLES; diff --git a/bta/pan/bta_pan_act.c b/bta/pan/bta_pan_act.c index 2256ae973..c81fe7173 100644 --- a/bta/pan/bta_pan_act.c +++ b/bta/pan/bta_pan_act.c @@ -318,6 +318,53 @@ static void bta_pan_mfilt_ind_cback(UINT16 handle, BOOLEAN indication,tBNEP_RESU /******************************************************************************* ** +** Function bta_pan_has_multiple_connections +** +** Description Check whether there are multiple GN/NAP connections to +** different devices +** +** +** Returns BOOLEAN +** +*******************************************************************************/ +static BOOLEAN bta_pan_has_multiple_connections(UINT8 app_id) +{ + tBTA_PAN_SCB *p_scb = NULL; + BOOLEAN found = FALSE; + BD_ADDR bd_addr; + + for (UINT8 index = 0; index < BTA_PAN_NUM_CONN; index++) + { + p_scb = &bta_pan_cb.scb[index]; + if (p_scb->in_use == TRUE && app_id == p_scb->app_id) + { + /* save temp bd_addr */ + bdcpy(bd_addr, p_scb->bd_addr); + found = TRUE; + break; + } + } + + /* If cannot find a match then there is no connection at all */ + if (found == FALSE) + return FALSE; + + /* Find whether there is another connection with different device other than PANU. + Could be same service or different service */ + for (UINT8 index = 0; index < BTA_PAN_NUM_CONN; index++) + { + p_scb = &bta_pan_cb.scb[index]; + if (p_scb->in_use == TRUE && p_scb->app_id != bta_pan_cb.app_id[0] && + bdcmp(bd_addr, p_scb->bd_addr)) + { + return TRUE; + } + } + return FALSE; +} + +/******************************************************************************* +** ** Function bta_pan_enable ** ** Description @@ -592,6 +639,18 @@ void bta_pan_conn_open(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data) data.status = BTA_PAN_FAIL; } + p_scb->pan_flow_enable = TRUE; + p_scb->app_flow_enable = TRUE; + + /* If app_id is NAP/GN, check whether there are multiple connections. + If there are, provide a special app_id to dm to enforce master role only. */ + if ((p_scb->app_id == bta_pan_cb.app_id[1] || p_scb->app_id == bta_pan_cb.app_id[2]) && + bta_pan_has_multiple_connections(p_scb->app_id)) + { + p_scb->app_id = BTA_APP_ID_PAN_MULTI; + } + + bta_sys_conn_open(BTA_ID_PAN, p_scb->app_id, p_scb->bd_addr); bta_pan_cb.p_cback(BTA_PAN_OPEN_EVT, (tBTA_PAN *)&data); diff --git a/btcore/src/counter.c b/btcore/src/counter.c index 08aa518ae..b88c7a27e 100644 --- a/btcore/src/counter.c +++ b/btcore/src/counter.c @@ -257,6 +257,10 @@ static bool counter_foreach_cb_(hash_map_entry_t *hash_map_entry, void *context) } static bool counter_socket_open(void) { +#if (!defined(BT_NET_DEBUG) || (BT_NET_DEBUG != TRUE)) + return true; // Disable using network sockets for security reasons +#endif + assert(listen_socket_ == NULL); assert(thread_ == NULL); assert(clients_ == NULL); @@ -294,6 +298,10 @@ error:; } static void counter_socket_close(void) { +#if (!defined(BT_NET_DEBUG) || (BT_NET_DEBUG != TRUE)) + return; // Disable using network sockets for security reasons +#endif + socket_free(listen_socket_); thread_free(thread_); list_free(clients_); diff --git a/btif/co/bta_hh_co.c b/btif/co/bta_hh_co.c index bbe11390d..66c43f764 100644 --- a/btif/co/bta_hh_co.c +++ b/btif/co/bta_hh_co.c @@ -43,7 +43,6 @@ const char *dev_path = "/dev/uhid"; static tBTA_HH_RPT_CACHE_ENTRY sReportCache[BTA_HH_NV_LOAD_MAX]; #endif - #define REPORT_DESC_REPORT_ID 0x05 #define REPORT_DESC_DIGITIZER_PAGE 0x0D #define REPORT_DESC_START_COLLECTION 0xA1 @@ -169,12 +168,23 @@ static void remove_digitizer_descriptor(UINT8 **data, UINT16 *length) } } } +void uhid_set_non_blocking(int fd) +{ + int opts = fcntl(fd, F_GETFL); + if (opts < 0) + APPL_TRACE_ERROR("%s() Getting flags failed (%s)", __func__, strerror(errno)); + + opts |= O_NONBLOCK; + + if (fcntl(fd, F_SETFL, opts) < 0) + APPL_TRACE_EVENT("%s() Setting non-blocking flag failed (%s)", __func__, strerror(errno)); +} /*Internal function to perform UHID write and error checking*/ static int uhid_write(int fd, const struct uhid_event *ev) { - ssize_t ret; - ret = write(fd, ev, sizeof(*ev)); + ssize_t ret = write(fd, ev, sizeof(*ev)); + if (ret < 0){ int rtn = -errno; APPL_TRACE_ERROR("%s: Cannot write to uhid:%s", @@ -184,9 +194,9 @@ static int uhid_write(int fd, const struct uhid_event *ev) APPL_TRACE_ERROR("%s: Wrong size written to uhid: %zd != %zu", __FUNCTION__, ret, sizeof(*ev)); return -EFAULT; - } else { - return 0; } + + return 0; } /* Internal function to parse the events received from UHID driver*/ @@ -209,24 +219,31 @@ static int uhid_event(btif_hh_device_t *p_dev) APPL_TRACE_ERROR("%s: Cannot read uhid-cdev: %s", __FUNCTION__, strerror(errno)); return -errno; - } else if (ret < (ssize_t)sizeof(ev.type)) { - APPL_TRACE_ERROR("%s: Invalid size read from uhid-dev: %zd < %zu", + } else if ((ev.type == UHID_OUTPUT) || (ev.type==UHID_OUTPUT_EV)) { + // Only these two types havae payload, + // ensure we read full event descriptor + if (ret < (ssize_t)sizeof(ev)) { + APPL_TRACE_ERROR("%s: Invalid size read from uhid-dev: %ld != %lu", __FUNCTION__, ret, sizeof(ev.type)); - return -EFAULT; + return -EFAULT; + } } switch (ev.type) { case UHID_START: APPL_TRACE_DEBUG("UHID_START from uhid-dev\n"); + p_dev->ready_for_data = TRUE; break; case UHID_STOP: APPL_TRACE_DEBUG("UHID_STOP from uhid-dev\n"); + p_dev->ready_for_data = FALSE; break; case UHID_OPEN: APPL_TRACE_DEBUG("UHID_OPEN from uhid-dev\n"); break; case UHID_CLOSE: APPL_TRACE_DEBUG("UHID_CLOSE from uhid-dev\n"); + p_dev->ready_for_data = FALSE; break; case UHID_OUTPUT: if (ret < (ssize_t)(sizeof(ev.type) + sizeof(ev.u.output))) { @@ -335,14 +352,17 @@ static inline pthread_t create_thread(void *(*start_routine)(void *), void * arg *******************************************************************************/ static void *btif_hh_poll_event_thread(void *arg) { - btif_hh_device_t *p_dev = arg; APPL_TRACE_DEBUG("%s: Thread created fd = %d", __FUNCTION__, p_dev->fd); struct pollfd pfds[1]; int ret; + pfds[0].fd = p_dev->fd; pfds[0].events = POLLIN; + // Set the uhid fd as non-blocking to ensure we never block the BTU thread + uhid_set_non_blocking(p_dev->fd); + while(p_dev->hh_keep_polling){ ret = poll(pfds, 1, 50); if (ret < 0) { @@ -384,7 +404,8 @@ void bta_hh_co_destroy(int fd) int bta_hh_co_write(int fd, UINT8* rpt, UINT16 len) { - APPL_TRACE_VERBOSE("bta_hh_co_data: UHID write"); + APPL_TRACE_DEBUG("%s: UHID write %d", __func__, len); + struct uhid_event ev; memset(&ev, 0, sizeof(ev)); ev.type = UHID_INPUT; @@ -395,6 +416,7 @@ int bta_hh_co_write(int fd, UINT8* rpt, UINT16 len) return -1; } memcpy(ev.u.input.data, rpt, len); + return uhid_write(fd, &ev); } @@ -440,9 +462,11 @@ void bta_hh_co_open(UINT8 dev_handle, UINT8 sub_class, tBTA_HH_ATTR_MASK attr_ma if (p_dev->fd < 0){ APPL_TRACE_ERROR("%s: Error: failed to open uhid, err:%s", __FUNCTION__,strerror(errno)); + return; }else APPL_TRACE_DEBUG("%s: uhid fd = %d", __FUNCTION__, p_dev->fd); } + p_dev->hh_keep_polling = 1; p_dev->hh_poll_thread_id = create_thread(btif_hh_poll_event_thread, p_dev); break; @@ -467,6 +491,7 @@ void bta_hh_co_open(UINT8 dev_handle, UINT8 sub_class, tBTA_HH_ATTR_MASK attr_ma if (p_dev->fd < 0){ APPL_TRACE_ERROR("%s: Error: failed to open uhid, err:%s", __FUNCTION__,strerror(errno)); + return; }else{ APPL_TRACE_DEBUG("%s: uhid fd = %d", __FUNCTION__, p_dev->fd); p_dev->hh_keep_polling = 1; @@ -557,11 +582,13 @@ void bta_hh_co_data(UINT8 dev_handle, UINT8 *p_rpt, UINT16 len, tBTA_HH_PROTO_MO APPL_TRACE_WARNING("%s: Error: unknown HID device handle %d", __FUNCTION__, dev_handle); return; } - // Send the HID report to the kernel. - if (p_dev->fd >= 0) { + + // Send the HID data to the kernel. + if ((p_dev->fd >= 0) && p_dev->ready_for_data) { bta_hh_co_write(p_dev->fd, p_rpt, len); }else { - APPL_TRACE_WARNING("%s: Error: fd = %d, len = %d", __FUNCTION__, p_dev->fd, len); + APPL_TRACE_WARNING("%s: Error: fd = %d, ready %d, len = %d", __FUNCTION__, p_dev->fd, + p_dev->ready_for_data, len); } } @@ -618,7 +645,7 @@ void bta_hh_co_send_hid_info(btif_hh_device_t *p_dev, char *dev_name, UINT16 ven ev.u.create.country = ctry_code; result = uhid_write(p_dev->fd, &ev); - APPL_TRACE_WARNING("%s: fd = %d, dscp_len = %d, result = %d", __FUNCTION__, + APPL_TRACE_WARNING("%s: wrote descriptor to fd = %d, dscp_len = %d, result = %d", __FUNCTION__, p_dev->fd, dscp_len, result); if (result) { diff --git a/btif/include/btif_common.h b/btif/include/btif_common.h index 2c4276d92..7e8c50640 100644 --- a/btif/include/btif_common.h +++ b/btif/include/btif_common.h @@ -145,6 +145,16 @@ enum #define PERSIST_BDADDR_PROPERTY "persist.service.bdroid.bdaddr" #endif +/** + * FACTORY_BT_BDADDR_PROPERTY + * If there is no valid bdaddr available from PROPERTY_BT_BDADDR_PATH + * and there is no available persistent bdaddr available from + * PERSIST_BDADDR_PROPERTY use a factory set address + */ +#ifndef FACTORY_BT_ADDR_PROPERTY +#define FACTORY_BT_ADDR_PROPERTY "ro.boot.btmacaddr" +#endif + #define FACTORY_BT_BDADDR_STORAGE_LEN 17 diff --git a/btif/include/btif_hh.h b/btif/include/btif_hh.h index dfe61fd42..1e80b0664 100644 --- a/btif/include/btif_hh.h +++ b/btif/include/btif_hh.h @@ -69,6 +69,7 @@ typedef struct UINT8 sub_class; UINT8 app_id; int fd; + BOOLEAN ready_for_data; pthread_t hh_poll_thread_id; UINT8 hh_keep_polling; BOOLEAN vup_timer_active; diff --git a/btif/src/btif_core.c b/btif/src/btif_core.c index c1a7bdd24..1fc263c08 100644 --- a/btif/src/btif_core.c +++ b/btif/src/btif_core.c @@ -131,6 +131,7 @@ static BOOLEAN ssr_triggered = FALSE; ************************************************************************************/ static void btif_jni_associate(UNUSED_ATTR uint16_t event, UNUSED_ATTR char *p_param); static void btif_jni_disassociate(UNUSED_ATTR uint16_t event, UNUSED_ATTR char *p_param); +static bool btif_fetch_property(const char *key, bt_bdaddr_t *addr); /* sends message to btif task */ static void btif_sendmsg(void *p_msg); @@ -378,10 +379,22 @@ static bool fetch_vendor_addr (bt_bdaddr_t *local_addr) close(addr_fd); return status; } +static bool btif_fetch_property(const char *key, bt_bdaddr_t *addr) { + char val[PROPERTY_VALUE_MAX] = {0}; + + if (property_get(key, val, NULL)) { + if (string_to_bdaddr(val, addr)) { + BTIF_TRACE_DEBUG("%s: Got BDA %s", __func__, val); + return TRUE; + } + BTIF_TRACE_DEBUG("%s: System Property did not contain valid bdaddr", __func__); + } + return FALSE; +} static void btif_fetch_local_bdaddr(bt_bdaddr_t *local_addr) { - char val[256]; + char val[PROPERTY_VALUE_MAX] = {0}; uint8_t valid_bda = FALSE; int val_size = 0; const uint8_t null_bdaddr[BD_ADDR_LEN] = {0,0,0,0,0,0}; @@ -391,22 +404,19 @@ static void btif_fetch_local_bdaddr(bt_bdaddr_t *local_addr) { int addr_fd; - BTIF_TRACE_DEBUG("local bdaddr is stored in %s", val); + BTIF_TRACE_DEBUG("%s, local bdaddr is stored in %s", __func__, val); if ((addr_fd = open(val, O_RDONLY)) != -1) { memset(val, 0, sizeof(val)); read(addr_fd, val, FACTORY_BT_BDADDR_STORAGE_LEN); - string_to_bdaddr(val, local_addr); /* If this is not a reserved/special bda, then use it */ - if (memcmp(local_addr->address, null_bdaddr, BD_ADDR_LEN) != 0) + if ((string_to_bdaddr(val, local_addr)) && + (memcmp(local_addr->address, null_bdaddr, BD_ADDR_LEN) != 0)) { valid_bda = TRUE; - BTIF_TRACE_DEBUG("Got Factory BDA %02X:%02X:%02X:%02X:%02X:%02X", - local_addr->address[0], local_addr->address[1], local_addr->address[2], - local_addr->address[3], local_addr->address[4], local_addr->address[5]); + BTIF_TRACE_DEBUG("%s: Got Factory BDA %s", __func__, val); } - close(addr_fd); } } @@ -423,14 +433,13 @@ static void btif_fetch_local_bdaddr(bt_bdaddr_t *local_addr) } /* No factory BDADDR found. Look for previously generated random BDA */ - if ((!valid_bda) && \ - (property_get(PERSIST_BDADDR_PROPERTY, val, NULL))) - { - string_to_bdaddr(val, local_addr); - valid_bda = TRUE; - BTIF_TRACE_DEBUG("Got prior random BDA %02X:%02X:%02X:%02X:%02X:%02X", - local_addr->address[0], local_addr->address[1], local_addr->address[2], - local_addr->address[3], local_addr->address[4], local_addr->address[5]); + if (!valid_bda) { + valid_bda = btif_fetch_property(PERSIST_BDADDR_PROPERTY, local_addr); + } + + /* No BDADDR found in file. Look for BDA in factory property */ + if (!valid_bda) { + valid_bda = btif_fetch_property(FACTORY_BT_ADDR_PROPERTY, local_addr); } /* No factory BDADDR found. Look for BDA in ro.boot.btmacaddr */ diff --git a/btif/src/btif_dm.c b/btif/src/btif_dm.c index 93760582c..01a80fa23 100644 --- a/btif/src/btif_dm.c +++ b/btif/src/btif_dm.c @@ -3165,6 +3165,8 @@ static void btif_dm_ble_auth_cmpl_evt (tBTA_DM_AUTH_CMPL *p_auth_cmpl) state = BT_BOND_STATE_NONE; } else { btif_dm_save_ble_bonding_keys(); + BTA_GATTC_Refresh(bd_addr.address); + btif_dm_get_remote_services_by_transport(&bd_addr, BTA_GATT_TRANSPORT_LE); } BTA_GATTC_Refresh(bd_addr.address); if(!p_auth_cmpl->smp_over_br) diff --git a/btif/src/btif_gatt_client.c b/btif/src/btif_gatt_client.c index 253ca2bd1..a959cdd73 100644 --- a/btif/src/btif_gatt_client.c +++ b/btif/src/btif_gatt_client.c @@ -458,8 +458,6 @@ static void btif_gattc_update_properties ( btif_gattc_cb_t *p_btif_cb ) btif_dm_update_ble_remote_properties( p_btif_cb->bd_addr.address, bdname.name, p_btif_cb->device_type); } - - btif_storage_set_remote_addr_type( &p_btif_cb->bd_addr, p_btif_cb->addr_type); } static void btif_gattc_upstreams_evt(uint16_t event, char* p_param) @@ -646,6 +644,8 @@ static void btif_gattc_upstreams_evt(uint16_t event, char* p_param) BT_PROPERTY_TYPE_OF_DEVICE, sizeof(dev_type), &dev_type); btif_storage_set_remote_device_property(&(p_btif_cb->bd_addr), &properties); + btif_storage_set_remote_addr_type( &p_btif_cb->bd_addr, p_btif_cb->addr_type); + HAL_CBACK(bt_gatt_callbacks, client->scan_result_cb, &p_btif_cb->bd_addr, p_btif_cb->rssi, p_btif_cb->value); break; diff --git a/btif/src/btif_hh.c b/btif/src/btif_hh.c index f8230241e..8188942b5 100644 --- a/btif/src/btif_hh.c +++ b/btif/src/btif_hh.c @@ -533,6 +533,8 @@ void btif_hh_remove_device(bt_bdaddr_t bd_addr) p_dev->dev_status = BTHH_CONN_STATE_UNKNOWN; p_dev->dev_handle = BTA_HH_INVALID_HANDLE; + p_dev->ready_for_data = FALSE; + if (btif_hh_cb.device_num > 0) { btif_hh_cb.device_num--; } diff --git a/device/include/interop_database.h b/device/include/interop_database.h index e7e0da32c..a0bdae756 100644 --- a/device/include/interop_database.h +++ b/device/include/interop_database.h @@ -46,9 +46,6 @@ static const interop_addr_t interop_addr_database[] = { {{0xac, 0x9e, 0x17, 0,0,0}, 3, INTEROP_DISABLE_LE_SECURE_CONNECTIONS}, {{0xf0, 0x79, 0x59, 0,0,0}, 3, INTEROP_DISABLE_LE_SECURE_CONNECTIONS}, - // Polar Heart Rate Monitor - {{0x00, 0x22, 0xd0, 0,0,0}, 3, INTEROP_DISABLE_LE_SECURE_CONNECTIONS}, - // Motorola Key Link {{0x1c, 0x96, 0x5a, 0,0,0}, 3, INTEROP_DISABLE_LE_SECURE_CONNECTIONS}, @@ -56,6 +53,8 @@ static const interop_addr_t interop_addr_database[] = { {{0x80, 0xea, 0xCa, 0,0,0}, 3, INTEROP_DISABLE_LE_SECURE_CONNECTIONS}, // Xiaomi Mi Band {{0x88, 0x0f, 0x10, 0,0,0}, 3, INTEROP_DISABLE_LE_SECURE_CONNECTIONS}, + // Flic smart button + {{0x80, 0xe4, 0xda, 0x70, 0,0}, 4, INTEROP_DISABLE_LE_SECURE_CONNECTIONS}, // BMW car kits (Harman/Becker) {{0x9c, 0xdf, 0x03, 0,0,0}, 3, INTEROP_AUTO_RETRY_PAIRING}, diff --git a/hci/src/btsnoop_net.c b/hci/src/btsnoop_net.c index 8c69b6732..077a4d432 100644 --- a/hci/src/btsnoop_net.c +++ b/hci/src/btsnoop_net.c @@ -77,6 +77,10 @@ static int local_socket_create(void) { } void btsnoop_net_open() { +#if (!defined(BT_NET_DEBUG) || (BT_NET_DEBUG != TRUE)) + return; // Disable using network sockets for security reasons +#endif + listen_thread_valid_ = (pthread_create(&listen_thread_, NULL, listen_fn_, NULL) == 0); if (!listen_thread_valid_) { LOG_ERROR("%s pthread_create failed: %s", __func__, strerror(errno)); @@ -86,6 +90,10 @@ void btsnoop_net_open() { } void btsnoop_net_close() { +#if (!defined(BT_NET_DEBUG) || (BT_NET_DEBUG != TRUE)) + return; // Disable using network sockets for security reasons +#endif + if (listen_thread_valid_) { shutdown(listen_socket_, SHUT_RDWR); shutdown(listen_socket_local_, SHUT_RDWR); @@ -97,6 +105,9 @@ void btsnoop_net_close() { void btsnoop_net_write(const void *data, size_t length) { ssize_t ret; +#if (!defined(BT_NET_DEBUG) || (BT_NET_DEBUG != TRUE)) + return; // Disable using network sockets for security reasons +#endif pthread_mutex_lock(&client_socket_lock_); if (client_socket_btsnoop != -1) { diff --git a/hci/src/hci_hal_h4.c b/hci/src/hci_hal_h4.c index 0a9333ced..332c1a2ba 100644 --- a/hci/src/hci_hal_h4.c +++ b/hci/src/hci_hal_h4.c @@ -27,9 +27,15 @@ #include "osi/include/osi.h" #include "osi/include/log.h" #include "osi/include/reactor.h" +#include "osi/include/thread.h" #include "vendor.h" #define HCI_HAL_SERIAL_BUFFER_SIZE 1026 +#define HCI_BLE_EVENT 0x3e + +// Increased HCI thread priority to keep up with the audio sub-system +// when streaming time sensitive data (A2DP). +#define HCI_THREAD_PRIORITY -19 // Our interface and modules we import static const hci_hal_t interface; @@ -42,6 +48,8 @@ static int uart_fd; static eager_reader_t *uart_stream; 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; static void event_uart_has_bytes(eager_reader_t *reader, void *context); @@ -81,8 +89,14 @@ static bool hal_open() { } 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; error: @@ -176,6 +190,40 @@ static bool hal_dev_in_reset() // Internal functions +// WORKAROUND: +// As exhibited by b/23934838, during result-heavy LE scans, the UART byte +// stream can get corrupted, leading to assertions caused by mis-interpreting +// the bytes following the corruption. +// This workaround looks for tell-tale signs of a BLE event and attempts to +// skip the correct amount of bytes in the stream to re-synchronize onto +// a packet boundary. +// Function returns true if |byte_read| has been processed by the workaround. +static bool stream_corrupted_during_le_scan_workaround(const uint8_t byte_read) +{ + if (!stream_corruption_detected && byte_read == HCI_BLE_EVENT) { + LOG_ERROR("%s HCI stream corrupted (message type 0x3E)!", __func__); + stream_corruption_detected = true; + return true; + } + + if (stream_corruption_detected) { + if (stream_corruption_bytes_to_ignore == 0) { + stream_corruption_bytes_to_ignore = byte_read; + LOG_ERROR("%s About to skip %d bytes...", __func__, stream_corruption_bytes_to_ignore); + } else { + --stream_corruption_bytes_to_ignore; + } + + if (stream_corruption_bytes_to_ignore == 0) { + LOG_ERROR("%s Back to our regularly scheduled program...", __func__); + stream_corruption_detected = false; + } + return true; + } + + return false; +} + // See what data is waiting, and notify the upper layer static void event_uart_has_bytes(eager_reader_t *reader, UNUSED_ATTR void *context) { if (stream_has_interpretation) { @@ -186,6 +234,10 @@ static void event_uart_has_bytes(eager_reader_t *reader, UNUSED_ATTR void *conte LOG_ERROR("%s could not read HCI message type", __func__); return; } + + if (stream_corrupted_during_le_scan_workaround(type_byte)) + return; + 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; diff --git a/hci/src/hci_inject.c b/hci/src/hci_inject.c index a17a3d3b7..8ba5f989a 100644 --- a/hci/src/hci_inject.c +++ b/hci/src/hci_inject.c @@ -61,6 +61,10 @@ static void read_ready(socket_t *socket, void *context); static void client_free(void *ptr); bool hci_inject_open(const hci_t *hci_interface) { +#if (!defined(BT_NET_DEBUG) || (BT_NET_DEBUG != TRUE)) + return true; // Disable using network sockets for security reasons +#endif + assert(listen_socket == NULL); assert(thread == NULL); assert(clients == NULL); @@ -92,6 +96,10 @@ error:; } void hci_inject_close(void) { +#if (!defined(BT_NET_DEBUG) || (BT_NET_DEBUG != TRUE)) + return; // Disable using network sockets for security reasons +#endif + socket_free(listen_socket); list_free(clients); thread_free(thread); diff --git a/hci/src/low_power_manager.c b/hci/src/low_power_manager.c index 9435e4fe1..00d0fae53 100644 --- a/hci/src/low_power_manager.c +++ b/hci/src/low_power_manager.c @@ -79,7 +79,6 @@ static void init(thread_t *post_thread) { thread = post_thread; vendor->set_callback(VENDOR_SET_LPM_MODE, vendor_enable_disable_callback); - vendor->send_command(VENDOR_GET_LPM_IDLE_TIMEOUT, &idle_timeout_ms); idle_alarm = alarm_new(); if (!idle_alarm) { @@ -121,7 +120,7 @@ static void wake_assert() { static void transmit_done() { transmit_is_done = true; - if (wake_state == LPM_WAKE_W4_TX_DONE) { + if (wake_state == LPM_WAKE_W4_TX_DONE || wake_state == LPM_WAKE_ASSERTED) { wake_state = LPM_WAKE_W4_TIMEOUT; start_idle_timer(); } @@ -147,6 +146,8 @@ static void enable(bool enable) { } else { uint8_t command = enable ? BT_VND_LPM_ENABLE : BT_VND_LPM_DISABLE; state = enable ? LPM_ENABLING : LPM_DISABLING; + if (state == LPM_ENABLING) + vendor->send_command(VENDOR_GET_LPM_IDLE_TIMEOUT, &idle_timeout_ms); vendor->send_async_command(VENDOR_SET_LPM_MODE, &command); } } diff --git a/hci/test/hci_hal_h4_test.cpp b/hci/test/hci_hal_h4_test.cpp index 2c4030d4f..d64e8c4d2 100644 --- a/hci/test/hci_hal_h4_test.cpp +++ b/hci/test/hci_hal_h4_test.cpp @@ -43,6 +43,9 @@ DECLARE_TEST_MODES( type_byte_only ); +// Use as packet type to test stream_corrupted_during_le_scan_workaround() +static const uint8_t HCI_BLE_EVENT = 0x3e; + static char sample_data1[100] = "A point is that which has no part."; static char sample_data2[100] = "A line is breadthless length."; static char sample_data3[100] = "The ends of a line are points."; @@ -50,6 +53,9 @@ static char acl_data[100] = "A straight line is a line which lies evenly wit static char sco_data[100] = "A surface is that which has length and breadth only."; static char event_data[100] = "The edges of a surface are lines."; +// Test data for stream_corrupted_during_le_scan_workaround() +static char corrupted_data[] = { 0x5 /* length of remaining data */, 'H', 'e', 'l', 'l', 'o' }; + static const hci_hal_t *hal; static int dummy_serial_fd; static int reentry_i = 0; @@ -221,6 +227,7 @@ TEST_F(HciHalH4Test, test_read_synchronous) { reset_for(read_synchronous); write_packet(sockfd[1], DATA_TYPE_ACL, acl_data); + write_packet(sockfd[1], HCI_BLE_EVENT, corrupted_data); write_packet(sockfd[1], DATA_TYPE_SCO, sco_data); write_packet(sockfd[1], DATA_TYPE_EVENT, event_data); diff --git a/osi/include/eager_reader.h b/osi/include/eager_reader.h index 3bf1e6edf..a172f06e8 100644 --- a/osi/include/eager_reader.h +++ b/osi/include/eager_reader.h @@ -23,6 +23,7 @@ #include <stdint.h> #include "allocator.h" +#include "osi/include/thread.h" typedef struct eager_reader_t eager_reader_t; typedef struct reactor_t reactor_t; @@ -61,3 +62,7 @@ void eager_reader_unregister(eager_reader_t *reader); // but you should probably only be reading from one thread anyway, // otherwise the byte stream probably doesn't make sense. size_t eager_reader_read(eager_reader_t *reader, uint8_t *buffer, size_t max_size, bool block); + +// Returns the inbound read thread for a given |reader| or NULL if the thread +// is not running. +thread_t* eager_reader_get_read_thread(const eager_reader_t *reader); diff --git a/osi/src/alarm.c b/osi/src/alarm.c index ff168297c..720020bfb 100644 --- a/osi/src/alarm.c +++ b/osi/src/alarm.c @@ -35,6 +35,12 @@ #include "osi/include/semaphore.h" #include "osi/include/thread.h" +// Make callbacks run at high thread priority. Some callbacks are used for audio +// related timer tasks as well as re-transmissions etc. Since we at this point +// cannot differentiate what callback we are dealing with, assume high priority +// for now. +// TODO(eisenbach): Determine correct thread priority (from parent?/per alarm?) +static const int CALLBACK_THREAD_PRIORITY_HIGH = -19; struct alarm_t { // The lock is held while the callback for this alarm is being executed. @@ -246,8 +252,7 @@ static bool lazy_initialize(void) { // during a2dp music playback, media task/btu/hci/event threads are all high priority // but actual callback thread is remaining normal which mean it's possible not to // schedule alarm callback in-time if system is busy - thread_set_priority(callback_thread, TIMER_CALLBACK_THREAD_PRIORITY); - + thread_set_priority(callback_thread, CALLBACK_THREAD_PRIORITY_HIGH); thread_post(callback_thread, callback_dispatch, NULL); return true; } diff --git a/osi/src/eager_reader.c b/osi/src/eager_reader.c index 63b190ea6..3ca8ad13c 100644 --- a/osi/src/eager_reader.c +++ b/osi/src/eager_reader.c @@ -30,7 +30,6 @@ #include "osi/include/osi.h" #include "osi/include/log.h" #include "osi/include/reactor.h" -#include "osi/include/thread.h" #if !defined(EFD_SEMAPHORE) # define EFD_SEMAPHORE (1 << 0) @@ -212,6 +211,11 @@ size_t eager_reader_read(eager_reader_t *reader, uint8_t *buffer, size_t max_siz return bytes_consumed; } +thread_t* eager_reader_get_read_thread(const eager_reader_t *reader) { + assert(reader != NULL); + return reader->inbound_read_thread; +} + static bool has_byte(const eager_reader_t *reader) { assert(reader != NULL); diff --git a/stack/btm/btm_acl.c b/stack/btm/btm_acl.c index e4dca3fb8..7f1ba27cb 100644 --- a/stack/btm/btm_acl.c +++ b/stack/btm/btm_acl.c @@ -1007,15 +1007,16 @@ void btm_read_remote_version_complete (UINT8 *p) UINT16 handle; int xx; BTM_TRACE_DEBUG ("btm_read_remote_version_complete"); + STREAM_TO_UINT8 (status, p); - if (status == HCI_SUCCESS) - { - STREAM_TO_UINT16 (handle, p); + STREAM_TO_UINT16 (handle, p); - /* Look up the connection by handle and copy features */ - for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_acl_cb++) + /* Look up the connection by handle and copy features */ + for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_acl_cb++) + { + if ((p_acl_cb->in_use) && (p_acl_cb->hci_handle == handle)) { - if ((p_acl_cb->in_use) && (p_acl_cb->hci_handle == handle)) + if (status == HCI_SUCCESS) { STREAM_TO_UINT8 (p_acl_cb->lmp_version, p); STREAM_TO_UINT16 (p_acl_cb->manufacturer, p); @@ -1028,6 +1029,10 @@ void btm_read_remote_version_complete (UINT8 *p) btm_read_remote_features (p_acl_cb->hci_handle); break; } + + if (p_acl_cb->transport == BT_TRANSPORT_LE) + l2cble_notify_le_connection (p_acl_cb->remote_addr); + break; } } } diff --git a/stack/btm/btm_ble_gap.c b/stack/btm/btm_ble_gap.c index 19ec9e75a..8c24e7da9 100644 --- a/stack/btm/btm_ble_gap.c +++ b/stack/btm/btm_ble_gap.c @@ -3215,8 +3215,7 @@ void btm_ble_read_remote_features_complete(UINT8 *p) if ((p_acl_cb->in_use) && (p_acl_cb->hci_handle == handle)) { STREAM_TO_ARRAY(p_acl_cb->peer_le_features, p, BD_FEATURES_LEN); - /*notify link up here */ - l2cble_notify_le_connection (p_acl_cb->remote_addr); + btsnd_hcic_rmt_ver_req (p_acl_cb->hci_handle); break; } } diff --git a/stack/btu/btu_init.c b/stack/btu/btu_init.c index 0888cb57e..250c1c43e 100644 --- a/stack/btu/btu_init.c +++ b/stack/btu/btu_init.c @@ -45,6 +45,10 @@ #endif #endif +// Increase BTU task thread priority to avoid pre-emption +// of audio realated tasks. +#define BTU_TASK_THREAD_PRIORITY -19 + extern fixed_queue_t *btif_msg_queue; // Communication queue from bta thread to bt_workqueue. @@ -193,6 +197,8 @@ void BTU_StartUp(void) if (bt_workqueue_thread == NULL) goto error_exit; + thread_set_priority(bt_workqueue_thread, BTU_TASK_THREAD_PRIORITY); + // Continue startup on bt workqueue thread. thread_post(bt_workqueue_thread, btu_task_start_up, NULL); return; diff --git a/stack/gatt/gatt_auth.c b/stack/gatt/gatt_auth.c index ae5214592..89e2cc1cd 100644 --- a/stack/gatt/gatt_auth.c +++ b/stack/gatt/gatt_auth.c @@ -103,6 +103,11 @@ void gatt_verify_signature(tGATT_TCB *p_tcb, BT_HDR *p_buf) UINT8 *p, *p_orig = (UINT8 *)(p_buf + 1) + p_buf->offset; UINT32 counter; + if (p_buf->len < GATT_AUTH_SIGN_LEN + 4) { + GATT_TRACE_ERROR("%s: Data length %u less than expected %u", + __func__, p_buf->len, GATT_AUTH_SIGN_LEN + 4); + return; + } cmd_len = p_buf->len - GATT_AUTH_SIGN_LEN + 4; p = p_orig + cmd_len - 4; STREAM_TO_UINT32(counter, p); diff --git a/stack/gatt/gatt_utils.c b/stack/gatt/gatt_utils.c index 5030c5328..907862ff1 100644 --- a/stack/gatt/gatt_utils.c +++ b/stack/gatt/gatt_utils.c @@ -1497,7 +1497,7 @@ UINT32 gatt_add_sdp_record (tBT_UUID *p_uuid, UINT16 start_hdl, UINT16 end_hdl) case LEN_UUID_128: UINT8_TO_BE_STREAM (p, (UUID_DESC_TYPE << 3) | SIZE_SIXTEEN_BYTES); - ARRAY_TO_BE_STREAM (p, p_uuid->uu.uuid128, LEN_UUID_128); + ARRAY_TO_BE_STREAM_REVERSE (p, p_uuid->uu.uuid128, LEN_UUID_128); SDP_AddAttribute (sdp_handle, ATTR_ID_SERVICE_CLASS_ID_LIST, DATA_ELE_SEQ_DESC_TYPE, (UINT32) (p - buff), buff); break; diff --git a/stack/include/bt_types.h b/stack/include/bt_types.h index 4ea447eca..453aa38a3 100644 --- a/stack/include/bt_types.h +++ b/stack/include/bt_types.h @@ -286,6 +286,7 @@ typedef struct #define UINT16_TO_BE_STREAM(p, u16) {*(p)++ = (UINT8)((u16) >> 8); *(p)++ = (UINT8)(u16);} #define UINT8_TO_BE_STREAM(p, u8) {*(p)++ = (UINT8)(u8);} #define ARRAY_TO_BE_STREAM(p, a, len) {register int ijk; for (ijk = 0; ijk < len; ijk++) *(p)++ = (UINT8) a[ijk];} +#define ARRAY_TO_BE_STREAM_REVERSE(p, a, len) {register int ijk; for (ijk = 0; ijk < len; ijk++) *(p)++ = (UINT8) a[len - ijk - 1];} #define BE_STREAM_TO_UINT8(u8, p) {u8 = (UINT8)(*(p)); (p) += 1;} #define BE_STREAM_TO_UINT16(u16, p) {u16 = (UINT16)(((UINT16)(*(p)) << 8) + (UINT16)(*((p) + 1))); (p) += 2;} diff --git a/stack/include/hcidefs.h b/stack/include/hcidefs.h index 41dc936c0..4cd34852a 100644 --- a/stack/include/hcidefs.h +++ b/stack/include/hcidefs.h @@ -24,6 +24,9 @@ #define HCI_PROTO_VERSION_2_0 0x03 /* Version for BT spec 2.0 */ #define HCI_PROTO_VERSION_2_1 0x04 /* Version for BT spec 2.1 [Lisbon] */ #define HCI_PROTO_VERSION_3_0 0x05 /* Version for BT spec 3.0 */ +#define HCI_PROTO_VERSION_4_0 0x06 /* Version for BT spec 4.0 */ +#define HCI_PROTO_VERSION_4_1 0x07 /* Version for BT spec 4.1 */ +#define HCI_PROTO_VERSION_4_2 0x08 /* Version for BT spec 4.2 */ #define HCI_PROTO_REVISION 0x000C /* Current implementation version */ /* ** Definitions for HCI groups diff --git a/stack/sdp/sdp_api.c b/stack/sdp/sdp_api.c index d96ace91d..720fad717 100644 --- a/stack/sdp/sdp_api.c +++ b/stack/sdp/sdp_api.c @@ -357,7 +357,8 @@ BOOLEAN SDP_FindServiceUUIDInRec(tSDP_DISC_REC *p_rec, tBT_UUID * p_uuid) else if (SDP_DISC_ATTR_LEN(p_sattr->attr_len_type) == LEN_UUID_128) { p_uuid->len = LEN_UUID_128; - memcpy(p_uuid->uu.uuid128, p_sattr->attr_value.v.array, LEN_UUID_128); + for (uint8_t i = 0; i != LEN_UUID_128; ++i) + p_uuid->uu.uuid128[i] = p_sattr->attr_value.v.array[LEN_UUID_128-i-1]; } else if (SDP_DISC_ATTR_LEN(p_sattr->attr_len_type) == LEN_UUID_32) { @@ -443,8 +444,9 @@ BOOLEAN SDP_FindServiceUUIDInRec_128bit(tSDP_DISC_REC *p_rec, tBT_UUID * p_uuid) /* only support 128 bits UUID for now */ if (SDP_DISC_ATTR_LEN(p_sattr->attr_len_type) == 16) { - p_uuid->len = 16; - memcpy(p_uuid->uu.uuid128, p_sattr->attr_value.v.array, MAX_UUID_SIZE); + p_uuid->len = LEN_UUID_128; + for (uint8_t i = 0; i != LEN_UUID_128; ++i) + p_uuid->uu.uuid128[i] = p_sattr->attr_value.v.array[LEN_UUID_128-i-1]; } return(TRUE); } @@ -457,8 +459,9 @@ BOOLEAN SDP_FindServiceUUIDInRec_128bit(tSDP_DISC_REC *p_rec, tBT_UUID * p_uuid) /* only support 128 bits UUID for now */ && (SDP_DISC_ATTR_LEN(p_attr->attr_len_type) == 16)) { - p_uuid->len = 16; - memcpy(p_uuid->uu.uuid128, p_attr->attr_value.v.array, MAX_UUID_SIZE); + p_uuid->len = LEN_UUID_128; + for (uint8_t i = 0; i != LEN_UUID_128; ++i) + p_uuid->uu.uuid128[i] = p_attr->attr_value.v.array[LEN_UUID_128-i-1]; return(TRUE); } } diff --git a/stack/smp/smp_act.c b/stack/smp/smp_act.c index 462b02dce..8f758890c 100644 --- a/stack/smp/smp_act.c +++ b/stack/smp/smp_act.c @@ -51,6 +51,18 @@ const tSMP_ACT smp_distribute_act [] = smp_set_derive_link_key }; +static bool lmp_version_below(BD_ADDR bda, uint8_t version) +{ + tACL_CONN *acl = btm_bda_to_acl(bda, BT_TRANSPORT_LE); + if (acl == NULL || acl->lmp_version == 0) + { + SMP_TRACE_WARNING("%s cannot retrieve LMP version...", __func__); + return false; + } + SMP_TRACE_WARNING("%s LMP version %d < %d", __func__, acl->lmp_version, version); + return acl->lmp_version < version; +} + /******************************************************************************* ** Function smp_update_key_mask ** Description This function updates the key mask for sending or receiving. @@ -174,7 +186,8 @@ void smp_send_app_cback(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) if (!(p_cb->loc_auth_req & SMP_SC_SUPPORT_BIT) || interop_addr_match(INTEROP_DISABLE_LE_SECURE_CONNECTIONS, - (const bt_bdaddr_t *)&p_cb->pairing_bda)) + (const bt_bdaddr_t *)&p_cb->pairing_bda) + || lmp_version_below(p_cb->pairing_bda, HCI_PROTO_VERSION_4_2)) { p_cb->loc_auth_req &= ~SMP_KP_SUPPORT_BIT; p_cb->local_i_key &= ~SMP_SEC_KEY_TYPE_LK; diff --git a/utils/src/bt_utils.c b/utils/src/bt_utils.c index 4bd4abdf6..38dd3d51b 100644 --- a/utils/src/bt_utils.c +++ b/utils/src/bt_utils.c @@ -170,8 +170,7 @@ void raise_priority_a2dp(tHIGH_PRIORITY_TASK high_task) { // its prio individually. All other threads can be dynamically adjusted voa // adjust_priority_a2dp() - if (high_task == TASK_HIGH_HCI_WORKER) - priority = ANDROID_PRIORITY_URGENT_AUDIO; + priority = ANDROID_PRIORITY_URGENT_AUDIO; if (setpriority(PRIO_PROCESS, tid, priority) < 0) { LOG_WARN("failed to change priority tid: %d to %d", tid, priority); |