Loading system/device/include/interop.h +4 −1 Original line number Diff line number Diff line Loading @@ -99,7 +99,10 @@ typedef enum { // The public address of these devices are same as the Random address in ADV. // Then will get name by LE_Create_connection, actually fails, // but will block pairing. INTEROP_DISABLE_NAME_REQUEST INTEROP_DISABLE_NAME_REQUEST, // Respond AVRCP profile version only 1.4 for some device. INTEROP_AVRCP_1_4_ONLY } interop_feature_t; // Check if a given |addr| matches a known interoperability workaround as Loading system/device/include/interop_database.h +3 −0 Original line number Diff line number Diff line Loading @@ -150,6 +150,9 @@ static const interop_addr_entry_t interop_addr_database[] = { // for skip name request, // because BR/EDR address and ADV random address are the same {{{0xd4, 0x7a, 0xe2, 0, 0, 0}}, 3, INTEROP_DISABLE_NAME_REQUEST}, // Toyota Car Audio {{{0x00, 0x17, 0x53, 0, 0, 0}}, 3, INTEROP_AVRCP_1_4_ONLY}, }; typedef struct { Loading system/device/src/interop.cc +1 −0 Original line number Diff line number Diff line Loading @@ -132,6 +132,7 @@ static const char* interop_feature_string_(const interop_feature_t feature) { CASE_RETURN_STR(INTEROP_DISABLE_ROLE_SWITCH) CASE_RETURN_STR(INTEROP_HID_HOST_LIMIT_SNIFF_INTERVAL) CASE_RETURN_STR(INTEROP_DISABLE_NAME_REQUEST) CASE_RETURN_STR(INTEROP_AVRCP_1_4_ONLY) } return "UNKNOWN"; Loading system/stack/sdp/sdp_server.cc +16 −1 Original line number Diff line number Diff line Loading @@ -29,6 +29,8 @@ #include "bt_common.h" #include "bt_types.h" #include "avrc_defs.h" #include "device/include/interop.h" #include "osi/include/osi.h" #include "sdp_api.h" #include "sdpint.h" Loading Loading @@ -548,6 +550,7 @@ static void process_service_search_attr_req(tCONN_CB* p_ccb, uint16_t trans_num, tSDP_RECORD* p_rec; tSDP_ATTR_SEQ attr_seq, attr_seq_sav; tSDP_ATTRIBUTE* p_attr; tSDP_ATTRIBUTE attr_sav; bool maxxed_out = false, is_cont = false; uint8_t* p_seq_start; uint16_t seq_len, attr_len; Loading Loading @@ -646,6 +649,19 @@ static void process_service_search_attr_req(tCONN_CB* p_ccb, uint16_t trans_num, attr_seq.attr_entry[xx].end); if (p_attr) { // Check if the attribute contain AVRCP profile description list uint16_t avrcp_version = sdpu_is_avrcp_profile_description_list(p_attr); if (avrcp_version > AVRC_REV_1_4 && interop_match_addr(INTEROP_AVRCP_1_4_ONLY, &(p_ccb->device_address))) { SDP_TRACE_DEBUG( "%s, device=%s is only accept AVRCP 1.4, reply AVRCP 1.4 " "instead.", __func__, p_ccb->device_address.ToString().c_str()); memcpy(&attr_sav, p_attr, sizeof(tSDP_ATTRIBUTE)); attr_sav.value_ptr[attr_sav.len - 1] = 0x04; p_attr = &attr_sav; } /* Check if attribute fits. Assume 3-byte value type/length */ rem_len = max_list_len - (int16_t)(p_rsp - &p_ccb->rsp_list[0]); Loading Loading @@ -825,5 +841,4 @@ static void process_service_search_attr_req(tCONN_CB* p_ccb, uint16_t trans_num, /* Send the buffer through L2CAP */ L2CA_DataWrite(p_ccb->connection_id, p_buf); } #endif /* SDP_SERVER_ENABLED == TRUE */ system/stack/sdp/sdp_utils.cc +39 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ #include "bt_types.h" #include "btif_config.h" #include "avrc_defs.h" #include "sdp_api.h" #include "sdpint.h" Loading Loading @@ -1155,3 +1156,41 @@ uint8_t* sdpu_build_partial_attrib_entry(uint8_t* p_out, tSDP_ATTRIBUTE* p_attr, osi_free(p_attr_buff); return p_out; } /******************************************************************************* * * Function sdpu_is_avrcp_profile_description_list * * Description This function is to check if attirbute contain AVRCP profile * description list * * p_attr: attibute to be check * * Returns AVRCP profile version if matched, else 0 * ******************************************************************************/ uint16_t sdpu_is_avrcp_profile_description_list(tSDP_ATTRIBUTE* p_attr) { if (p_attr->id != ATTR_ID_BT_PROFILE_DESC_LIST || p_attr->len != 8) { return 0; } uint8_t* p_uuid = p_attr->value_ptr + 3; // Check if AVRCP profile UUID if (p_uuid[0] != 0x11 || p_uuid[1] != 0xe) { return 0; } uint8_t p_version = *(p_uuid + 4); switch (p_version) { case 0x0: return AVRC_REV_1_0; case 0x3: return AVRC_REV_1_3; case 0x4: return AVRC_REV_1_4; case 0x5: return AVRC_REV_1_5; case 0x6: return AVRC_REV_1_6; default: return 0; } } Loading
system/device/include/interop.h +4 −1 Original line number Diff line number Diff line Loading @@ -99,7 +99,10 @@ typedef enum { // The public address of these devices are same as the Random address in ADV. // Then will get name by LE_Create_connection, actually fails, // but will block pairing. INTEROP_DISABLE_NAME_REQUEST INTEROP_DISABLE_NAME_REQUEST, // Respond AVRCP profile version only 1.4 for some device. INTEROP_AVRCP_1_4_ONLY } interop_feature_t; // Check if a given |addr| matches a known interoperability workaround as Loading
system/device/include/interop_database.h +3 −0 Original line number Diff line number Diff line Loading @@ -150,6 +150,9 @@ static const interop_addr_entry_t interop_addr_database[] = { // for skip name request, // because BR/EDR address and ADV random address are the same {{{0xd4, 0x7a, 0xe2, 0, 0, 0}}, 3, INTEROP_DISABLE_NAME_REQUEST}, // Toyota Car Audio {{{0x00, 0x17, 0x53, 0, 0, 0}}, 3, INTEROP_AVRCP_1_4_ONLY}, }; typedef struct { Loading
system/device/src/interop.cc +1 −0 Original line number Diff line number Diff line Loading @@ -132,6 +132,7 @@ static const char* interop_feature_string_(const interop_feature_t feature) { CASE_RETURN_STR(INTEROP_DISABLE_ROLE_SWITCH) CASE_RETURN_STR(INTEROP_HID_HOST_LIMIT_SNIFF_INTERVAL) CASE_RETURN_STR(INTEROP_DISABLE_NAME_REQUEST) CASE_RETURN_STR(INTEROP_AVRCP_1_4_ONLY) } return "UNKNOWN"; Loading
system/stack/sdp/sdp_server.cc +16 −1 Original line number Diff line number Diff line Loading @@ -29,6 +29,8 @@ #include "bt_common.h" #include "bt_types.h" #include "avrc_defs.h" #include "device/include/interop.h" #include "osi/include/osi.h" #include "sdp_api.h" #include "sdpint.h" Loading Loading @@ -548,6 +550,7 @@ static void process_service_search_attr_req(tCONN_CB* p_ccb, uint16_t trans_num, tSDP_RECORD* p_rec; tSDP_ATTR_SEQ attr_seq, attr_seq_sav; tSDP_ATTRIBUTE* p_attr; tSDP_ATTRIBUTE attr_sav; bool maxxed_out = false, is_cont = false; uint8_t* p_seq_start; uint16_t seq_len, attr_len; Loading Loading @@ -646,6 +649,19 @@ static void process_service_search_attr_req(tCONN_CB* p_ccb, uint16_t trans_num, attr_seq.attr_entry[xx].end); if (p_attr) { // Check if the attribute contain AVRCP profile description list uint16_t avrcp_version = sdpu_is_avrcp_profile_description_list(p_attr); if (avrcp_version > AVRC_REV_1_4 && interop_match_addr(INTEROP_AVRCP_1_4_ONLY, &(p_ccb->device_address))) { SDP_TRACE_DEBUG( "%s, device=%s is only accept AVRCP 1.4, reply AVRCP 1.4 " "instead.", __func__, p_ccb->device_address.ToString().c_str()); memcpy(&attr_sav, p_attr, sizeof(tSDP_ATTRIBUTE)); attr_sav.value_ptr[attr_sav.len - 1] = 0x04; p_attr = &attr_sav; } /* Check if attribute fits. Assume 3-byte value type/length */ rem_len = max_list_len - (int16_t)(p_rsp - &p_ccb->rsp_list[0]); Loading Loading @@ -825,5 +841,4 @@ static void process_service_search_attr_req(tCONN_CB* p_ccb, uint16_t trans_num, /* Send the buffer through L2CAP */ L2CA_DataWrite(p_ccb->connection_id, p_buf); } #endif /* SDP_SERVER_ENABLED == TRUE */
system/stack/sdp/sdp_utils.cc +39 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ #include "bt_types.h" #include "btif_config.h" #include "avrc_defs.h" #include "sdp_api.h" #include "sdpint.h" Loading Loading @@ -1155,3 +1156,41 @@ uint8_t* sdpu_build_partial_attrib_entry(uint8_t* p_out, tSDP_ATTRIBUTE* p_attr, osi_free(p_attr_buff); return p_out; } /******************************************************************************* * * Function sdpu_is_avrcp_profile_description_list * * Description This function is to check if attirbute contain AVRCP profile * description list * * p_attr: attibute to be check * * Returns AVRCP profile version if matched, else 0 * ******************************************************************************/ uint16_t sdpu_is_avrcp_profile_description_list(tSDP_ATTRIBUTE* p_attr) { if (p_attr->id != ATTR_ID_BT_PROFILE_DESC_LIST || p_attr->len != 8) { return 0; } uint8_t* p_uuid = p_attr->value_ptr + 3; // Check if AVRCP profile UUID if (p_uuid[0] != 0x11 || p_uuid[1] != 0xe) { return 0; } uint8_t p_version = *(p_uuid + 4); switch (p_version) { case 0x0: return AVRC_REV_1_0; case 0x3: return AVRC_REV_1_3; case 0x4: return AVRC_REV_1_4; case 0x5: return AVRC_REV_1_5; case 0x6: return AVRC_REV_1_6; default: return 0; } }