system/bt
Revision | 6b3a12d3ad7fafa30341edc3ac125409f944d43b (tree) |
---|---|
Zeit | 2017-05-08 17:36:03 |
Autor | siminy <siminy@code...> |
Commiter | Gerrit - the friendly Code Review server |
SDP: Add logic to downgrade PBAP version for blacklisted device
As some remote devices go in bad state on parsing PBAP 1.2 SDP record.
Add them to PBAP version downgrade blacklist.Upgrade PBAP version
downgrade logic from to include name based blacklist and also remove
SDP attributes not suppported in PBAP 1.1 specifications like
GoepL2capPsm, SupportedFeatures.
CRs-Fixed: 2038030
Change-Id: I7fdb0433353ba5793470313d205a68e8eb3fb5ac
@@ -110,6 +110,11 @@ typedef enum { | ||
110 | 110 | // Some car kits going bad state when DUT initiate profile connection in collision scenerio |
111 | 111 | // Hence don't initaite profile level connections and wait for incoming connetcion |
112 | 112 | INTEROP_DISABLE_CONNECTION_AFTER_COLLISION, |
113 | + | |
114 | + // Devices requiring this workaround do not handle Bluetooth PBAP 1.2 version correctly, | |
115 | + // leading them to go in bad state. So for better interoperability respond with PBAP 1.1 | |
116 | + // as supported version. | |
117 | + INTEROP_ADV_PBAP_VER_1_1, | |
113 | 118 | } interop_feature_t; |
114 | 119 | |
115 | 120 | // Check if a given |addr| matches a known interoperability workaround as identified |
@@ -127,6 +127,13 @@ static const interop_addr_entry_t interop_addr_database[] = { | ||
127 | 127 | {{{0x04, 0xf8, 0xc2, 0,0,0}}, 3, INTEROP_DISABLE_ABSOLUTE_VOLUME}, |
128 | 128 | // HONDA HFT |
129 | 129 | {{{0xA0, 0x14, 0x3D, 0,0,0}}, 3, INTEROP_DISABLE_CONNECTION_AFTER_COLLISION}, |
130 | + | |
131 | + // Land Rover Carkit(s) | |
132 | + {{{0x00, 0x00, 0x31, 0,0,0}}, 3, INTEROP_ADV_PBAP_VER_1_1}, | |
133 | + {{{0x00, 0x00, 0x41, 0,0,0}}, 3, INTEROP_ADV_PBAP_VER_1_1}, | |
134 | + {{{0x00, 0x00, 0x6a, 0,0,0}}, 3, INTEROP_ADV_PBAP_VER_1_1}, | |
135 | + {{{0x00, 0x00, 0x7f, 0,0,0}}, 3, INTEROP_ADV_PBAP_VER_1_1}, | |
136 | + {{{0x00, 0x01, 0x0a, 0,0,0}}, 3, INTEROP_ADV_PBAP_VER_1_1}, | |
130 | 137 | }; |
131 | 138 | |
132 | 139 | typedef struct { |
@@ -167,6 +174,9 @@ static const interop_name_entry_t interop_name_database[] = { | ||
167 | 174 | {"Motorola Keyboard KZ500", 23, INTEROP_REMOVE_HID_DIG_DESCRIPTOR}, |
168 | 175 | {"Motorola Keyboard KZ500 v122", 28, INTEROP_REMOVE_HID_DIG_DESCRIPTOR}, |
169 | 176 | {"MB Bluetooth", 12, INTEROP_ADV_AVRCP_VER_1_3}, |
177 | + | |
178 | + // Land Rover Carkit | |
179 | + {"Discovery Sport", 15, INTEROP_ADV_PBAP_VER_1_1}, | |
170 | 180 | }; |
171 | 181 | |
172 | 182 | typedef struct { |
@@ -60,7 +60,7 @@ bool interop_match_name(const interop_feature_t feature, const char *name) { | ||
60 | 60 | const size_t db_size = sizeof(interop_name_database) / sizeof(interop_name_entry_t); |
61 | 61 | for (size_t i = 0; i != db_size; ++i) { |
62 | 62 | if (feature == interop_name_database[i].feature && |
63 | - strlen(name) >= interop_name_database[i].length && | |
63 | + strlen(name) == interop_name_database[i].length && | |
64 | 64 | strncmp(name, interop_name_database[i].name, interop_name_database[i].length) == 0) { |
65 | 65 | LOG_WARN(LOG_TAG, "%s() Device with name: %s is a match for interop workaround %s", __func__, |
66 | 66 | name, interop_feature_string_(feature)); |
@@ -157,6 +157,7 @@ static const char* interop_feature_string_(const interop_feature_t feature) { | ||
157 | 157 | CASE_RETURN_STR(INTEROP_DISABLE_LE_CONN_PREFERRED_PARAMS) |
158 | 158 | CASE_RETURN_STR(INTEROP_ADV_AVRCP_VER_1_3) |
159 | 159 | CASE_RETURN_STR(INTEROP_DISABLE_CONNECTION_AFTER_COLLISION) |
160 | + CASE_RETURN_STR(INTEROP_ADV_PBAP_VER_1_1) | |
160 | 161 | } |
161 | 162 | |
162 | 163 | return "UNKNOWN"; |
@@ -398,7 +398,7 @@ BOOLEAN SDP_AddAttribute (UINT32 handle, UINT16 attr_id, UINT8 attr_type, | ||
398 | 398 | UINT32 attr_len, UINT8 *p_val) |
399 | 399 | { |
400 | 400 | #if SDP_SERVER_ENABLED == TRUE |
401 | - UINT16 xx, yy, zz; | |
401 | + UINT16 xx; | |
402 | 402 | tSDP_RECORD *p_rec = &sdp_cb.server_db.record[0]; |
403 | 403 | |
404 | 404 | #if (BT_TRACE_VERBOSE == TRUE) |
@@ -436,81 +436,84 @@ BOOLEAN SDP_AddAttribute (UINT32 handle, UINT16 attr_id, UINT8 attr_type, | ||
436 | 436 | #endif |
437 | 437 | |
438 | 438 | /* Find the record in the database */ |
439 | - for (zz = 0; zz < sdp_cb.server_db.num_records; zz++, p_rec++) | |
439 | + for (xx = 0; xx < sdp_cb.server_db.num_records; xx++, p_rec++) | |
440 | 440 | { |
441 | 441 | if (p_rec->record_handle == handle) |
442 | - { | |
443 | - tSDP_ATTRIBUTE *p_attr = &p_rec->attribute[0]; | |
442 | + return SDP_AddAttributetoRecord (p_rec, attr_id, attr_type, attr_len, p_val); | |
443 | + } | |
444 | +#endif | |
445 | + return (FALSE); | |
446 | +} | |
444 | 447 | |
445 | - /* Found the record. Now, see if the attribute already exists */ | |
446 | - for (xx = 0; xx < p_rec->num_attributes; xx++, p_attr++) | |
447 | - { | |
448 | - /* The attribute exists. replace it */ | |
449 | - if (p_attr->id == attr_id) | |
450 | - { | |
451 | - SDP_DeleteAttribute (handle, attr_id); | |
452 | - break; | |
453 | - } | |
454 | - if (p_attr->id > attr_id) | |
455 | - break; | |
456 | - } | |
448 | +BOOLEAN SDP_AddAttributetoRecord (tSDP_RECORD *p_rec, UINT16 attr_id, UINT8 attr_type, | |
449 | + UINT32 attr_len, UINT8 *p_val) | |
450 | +{ | |
451 | + UINT16 xx, yy; | |
452 | + tSDP_ATTRIBUTE *p_attr = &p_rec->attribute[0]; | |
453 | + /* Found the record. Now, see if the attribute already exists */ | |
454 | + for (xx = 0; xx < p_rec->num_attributes; xx++, p_attr++) | |
455 | + { | |
456 | + /* The attribute exists. replace it */ | |
457 | + if (p_attr->id == attr_id) | |
458 | + { | |
459 | + SDP_DeleteAttributefromRecord (p_rec, attr_id); | |
460 | + break; | |
461 | + } | |
462 | + if (p_attr->id > attr_id) | |
463 | + break; | |
464 | + } | |
457 | 465 | |
458 | - if (p_rec->num_attributes == SDP_MAX_REC_ATTR) | |
459 | - return (FALSE); | |
466 | + if (p_rec->num_attributes == SDP_MAX_REC_ATTR) | |
467 | + return (FALSE); | |
460 | 468 | |
461 | - /* If not found, see if we can allocate a new entry */ | |
462 | - if (xx == p_rec->num_attributes) | |
463 | - p_attr = &p_rec->attribute[p_rec->num_attributes]; | |
464 | - else | |
465 | - { | |
466 | - /* Since the attributes are kept in sorted order, insert ours here */ | |
467 | - for (yy = p_rec->num_attributes; yy > xx; yy--) | |
468 | - p_rec->attribute[yy] = p_rec->attribute[yy - 1]; | |
469 | - } | |
469 | + /* If not found, see if we can allocate a new entry */ | |
470 | + if (xx == p_rec->num_attributes) | |
471 | + p_attr = &p_rec->attribute[p_rec->num_attributes]; | |
472 | + else | |
473 | + { | |
474 | + /* Since the attributes are kept in sorted order, insert ours here */ | |
475 | + for (yy = p_rec->num_attributes; yy > xx; yy--) | |
476 | + p_rec->attribute[yy] = p_rec->attribute[yy - 1]; | |
477 | + } | |
470 | 478 | |
471 | - p_attr->id = attr_id; | |
472 | - p_attr->type = attr_type; | |
473 | - p_attr->len = attr_len; | |
479 | + p_attr->id = attr_id; | |
480 | + p_attr->type = attr_type; | |
481 | + p_attr->len = attr_len; | |
474 | 482 | |
475 | - if (p_rec->free_pad_ptr + attr_len >= SDP_MAX_PAD_LEN) | |
476 | - { | |
477 | - /* do truncate only for text string type descriptor */ | |
478 | - if (attr_type == TEXT_STR_DESC_TYPE) | |
479 | - { | |
480 | - SDP_TRACE_WARNING("SDP_AddAttribute: attr_len:%d too long. truncate to (%d)", | |
481 | - attr_len, SDP_MAX_PAD_LEN - p_rec->free_pad_ptr ); | |
482 | - | |
483 | - attr_len = SDP_MAX_PAD_LEN - p_rec->free_pad_ptr; | |
484 | - p_val[SDP_MAX_PAD_LEN - p_rec->free_pad_ptr] = '\0'; | |
485 | - p_val[SDP_MAX_PAD_LEN - p_rec->free_pad_ptr+1] = '\0'; | |
486 | - } | |
487 | - else | |
488 | - attr_len = 0; | |
489 | - } | |
483 | + if (p_rec->free_pad_ptr + attr_len >= SDP_MAX_PAD_LEN) | |
484 | + { | |
485 | + /* do truncate only for text string type descriptor */ | |
486 | + if (attr_type == TEXT_STR_DESC_TYPE) | |
487 | + { | |
488 | + SDP_TRACE_WARNING("SDP_AddAttributetoRecord: attr_len:%d too long. truncate to (%d)", | |
489 | + attr_len, SDP_MAX_PAD_LEN - p_rec->free_pad_ptr ); | |
490 | 490 | |
491 | - if ((attr_len > 0) && (p_val != 0)) | |
492 | - { | |
493 | - p_attr->len = attr_len; | |
494 | - memcpy (&p_rec->attr_pad[p_rec->free_pad_ptr], p_val, (size_t)attr_len); | |
495 | - p_attr->value_ptr = &p_rec->attr_pad[p_rec->free_pad_ptr]; | |
496 | - p_rec->free_pad_ptr += attr_len; | |
497 | - } | |
498 | - else if ((attr_len == 0 && p_attr->len != 0) || /* if truncate to 0 length, simply don't add */ | |
499 | - p_val == 0) | |
500 | - { | |
501 | - SDP_TRACE_ERROR("SDP_AddAttribute fail, length exceed maximum: ID %d: attr_len:%d ", | |
502 | - attr_id, attr_len ); | |
503 | - p_attr->id = p_attr->type = p_attr->len = 0; | |
504 | - return (FALSE); | |
505 | - } | |
506 | - p_rec->num_attributes++; | |
507 | - return (TRUE); | |
491 | + attr_len = SDP_MAX_PAD_LEN - p_rec->free_pad_ptr; | |
492 | + p_val[SDP_MAX_PAD_LEN - p_rec->free_pad_ptr] = '\0'; | |
493 | + p_val[SDP_MAX_PAD_LEN - p_rec->free_pad_ptr+1] = '\0'; | |
508 | 494 | } |
495 | + else | |
496 | + attr_len = 0; | |
509 | 497 | } |
510 | -#endif | |
511 | - return (FALSE); | |
512 | -} | |
513 | 498 | |
499 | + if ((attr_len > 0) && (p_val != 0)) | |
500 | + { | |
501 | + p_attr->len = attr_len; | |
502 | + memcpy (&p_rec->attr_pad[p_rec->free_pad_ptr], p_val, (size_t)attr_len); | |
503 | + p_attr->value_ptr = &p_rec->attr_pad[p_rec->free_pad_ptr]; | |
504 | + p_rec->free_pad_ptr += attr_len; | |
505 | + } | |
506 | + else if ((attr_len == 0 && p_attr->len != 0) || /* if truncate to 0 length, simply don't add */ | |
507 | + p_val == 0) | |
508 | + { | |
509 | + SDP_TRACE_ERROR("SDP_AddAttributetoRecord fail, length exceed maximum: ID %d: attr_len:%d ", | |
510 | + attr_id, attr_len ); | |
511 | + p_attr->id = p_attr->type = p_attr->len = 0; | |
512 | + return (FALSE); | |
513 | + } | |
514 | + p_rec->num_attributes++; | |
515 | + return (TRUE); | |
516 | +} | |
514 | 517 | |
515 | 518 | /******************************************************************************* |
516 | 519 | ** |
@@ -705,7 +708,7 @@ BOOLEAN SDP_AddAdditionProtoLists (UINT32 handle, UINT16 num_elem, | ||
705 | 708 | *p_len = (UINT8)(p - p_len - 1); |
706 | 709 | } |
707 | 710 | result = SDP_AddAttribute (handle, ATTR_ID_ADDITION_PROTO_DESC_LISTS,DATA_ELE_SEQ_DESC_TYPE, |
708 | - (UINT32) (p - p_buff), p_buff); | |
711 | + (UINT32) (p - p_buff), p_buff); | |
709 | 712 | osi_free(p_buff); |
710 | 713 | return result; |
711 | 714 |
@@ -757,6 +760,36 @@ BOOLEAN SDP_AddProfileDescriptorList (UINT32 handle, UINT16 profile_uuid, | ||
757 | 760 | #endif |
758 | 761 | } |
759 | 762 | |
763 | +BOOLEAN SDP_AddProfileDescriptorListtoRecord (tSDP_RECORD *prec, UINT16 profile_uuid, | |
764 | + UINT16 version) | |
765 | +{ | |
766 | +#if SDP_SERVER_ENABLED == TRUE | |
767 | + UINT8 *p; | |
768 | + BOOLEAN result; | |
769 | + UINT8 *p_buff = (UINT8 *)osi_malloc(sizeof(UINT8) * SDP_MAX_ATTR_LEN); | |
770 | + | |
771 | + p = p_buff + 2; | |
772 | + | |
773 | + /* First, build the profile descriptor list. This consists of a data element sequence. */ | |
774 | + /* The sequence consists of profile's UUID and version number */ | |
775 | + UINT8_TO_BE_STREAM (p, (UUID_DESC_TYPE << 3) | SIZE_TWO_BYTES); | |
776 | + UINT16_TO_BE_STREAM (p, profile_uuid); | |
777 | + | |
778 | + UINT8_TO_BE_STREAM (p, (UINT_DESC_TYPE << 3) | SIZE_TWO_BYTES); | |
779 | + UINT16_TO_BE_STREAM (p, version); | |
780 | + | |
781 | + /* Add in type and length fields */ | |
782 | + *p_buff = (UINT8) ((DATA_ELE_SEQ_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE); | |
783 | + *(p_buff+1) = (UINT8) (p - (p_buff+2)); | |
784 | + | |
785 | + result = SDP_AddAttributetoRecord (prec, ATTR_ID_BT_PROFILE_DESC_LIST,DATA_ELE_SEQ_DESC_TYPE, (UINT32) (p - p_buff), p_buff); | |
786 | + osi_free(p_buff); | |
787 | + return result; | |
788 | + | |
789 | +#else /* SDP_SERVER_ENABLED == FALSE */ | |
790 | + return (FALSE); | |
791 | +#endif | |
792 | +} | |
760 | 793 | |
761 | 794 | /******************************************************************************* |
762 | 795 | ** |
@@ -853,67 +886,75 @@ BOOLEAN SDP_AddServiceClassIdList (UINT32 handle, UINT16 num_services, | ||
853 | 886 | BOOLEAN SDP_DeleteAttribute (UINT32 handle, UINT16 attr_id) |
854 | 887 | { |
855 | 888 | #if SDP_SERVER_ENABLED == TRUE |
856 | - UINT16 xx, yy; | |
889 | + UINT16 xx; | |
857 | 890 | tSDP_RECORD *p_rec = &sdp_cb.server_db.record[0]; |
858 | - UINT8 *pad_ptr; | |
859 | - UINT32 len; /* Number of bytes in the entry */ | |
860 | 891 | |
861 | 892 | /* Find the record in the database */ |
862 | 893 | for (xx = 0; xx < sdp_cb.server_db.num_records; xx++, p_rec++) |
863 | 894 | { |
864 | 895 | if (p_rec->record_handle == handle) |
865 | 896 | { |
866 | - tSDP_ATTRIBUTE *p_attr = &p_rec->attribute[0]; | |
867 | - | |
868 | 897 | SDP_TRACE_API("Deleting attr_id 0x%04x for handle 0x%x", attr_id, handle); |
869 | - /* Found it. Now, find the attribute */ | |
870 | - for (xx = 0; xx < p_rec->num_attributes; xx++, p_attr++) | |
898 | + if (SDP_DeleteAttributefromRecord (p_rec, attr_id)) | |
899 | + return (TRUE); | |
900 | + } | |
901 | + } | |
902 | +#endif | |
903 | + /* If here, not found */ | |
904 | + return (FALSE); | |
905 | +} | |
906 | + | |
907 | +BOOLEAN SDP_DeleteAttributefromRecord (tSDP_RECORD *p_rec, UINT16 attr_id) | |
908 | +{ | |
909 | + UINT16 xx, yy; | |
910 | + tSDP_ATTRIBUTE *p_attr = &p_rec->attribute[0]; | |
911 | + UINT8 *pad_ptr; | |
912 | + UINT32 len; /* Number of bytes in the entry */ | |
913 | + | |
914 | + /* Found it. Now, find the attribute */ | |
915 | + for (xx = 0; xx < p_rec->num_attributes; xx++, p_attr++) | |
916 | + { | |
917 | + if (p_attr->id == attr_id) | |
918 | + { | |
919 | + pad_ptr = p_attr->value_ptr; | |
920 | + len = p_attr->len; | |
921 | + if (p_rec->free_pad_ptr + p_attr->len >= SDP_MAX_PAD_LEN) | |
922 | + { | |
923 | + SDP_TRACE_ERROR("Deleting attr_id 0x%04x len %d exceeds 600", attr_id, len); | |
924 | + if (p_attr->type == TEXT_STR_DESC_TYPE) | |
925 | + len = SDP_MAX_PAD_LEN - p_rec->free_pad_ptr; | |
926 | + else | |
927 | + len = 0; | |
928 | + } | |
929 | + if (len) | |
871 | 930 | { |
872 | - if (p_attr->id == attr_id) | |
931 | + for (yy = 0; yy < p_rec->num_attributes; yy++) | |
873 | 932 | { |
874 | - pad_ptr = p_attr->value_ptr; | |
875 | - len = p_attr->len; | |
876 | - if (p_rec->free_pad_ptr + p_attr->len >= SDP_MAX_PAD_LEN) | |
877 | - { | |
878 | - SDP_TRACE_ERROR("Deleting attr_id 0x%04x len %d exceeds 600", attr_id, len); | |
879 | - if (p_attr->type == TEXT_STR_DESC_TYPE) | |
880 | - len = SDP_MAX_PAD_LEN - p_rec->free_pad_ptr; | |
881 | - else | |
882 | - len = 0; | |
883 | - } | |
884 | - if (len) | |
885 | - { | |
886 | - for (yy = 0; yy < p_rec->num_attributes; yy++) | |
887 | - { | |
888 | - if( p_rec->attribute[yy].value_ptr > pad_ptr ) | |
889 | - p_rec->attribute[yy].value_ptr -= len; | |
890 | - } | |
891 | - } | |
892 | - | |
893 | - /* Found it. Shift everything up one */ | |
894 | - p_rec->num_attributes--; | |
895 | - | |
896 | - for (yy = xx; yy < p_rec->num_attributes; yy++, p_attr++) | |
897 | - { | |
898 | - *p_attr = *(p_attr + 1); | |
899 | - } | |
900 | - | |
901 | - /* adjust attribute values if needed */ | |
902 | - if (len) | |
903 | - { | |
904 | - xx = (p_rec->free_pad_ptr - ((pad_ptr+len) - | |
905 | - &p_rec->attr_pad[0])); | |
906 | - for( yy=0; yy<xx; yy++, pad_ptr++) | |
907 | - *pad_ptr = *(pad_ptr+len); | |
908 | - p_rec->free_pad_ptr -= len; | |
909 | - } | |
910 | - return (TRUE); | |
933 | + if( p_rec->attribute[yy].value_ptr > pad_ptr ) | |
934 | + p_rec->attribute[yy].value_ptr -= len; | |
911 | 935 | } |
912 | 936 | } |
937 | + | |
938 | + /* Found it. Shift everything up one */ | |
939 | + p_rec->num_attributes--; | |
940 | + | |
941 | + for (yy = xx; yy < p_rec->num_attributes; yy++, p_attr++) | |
942 | + { | |
943 | + *p_attr = *(p_attr + 1); | |
944 | + } | |
945 | + | |
946 | + /* adjust attribute values if needed */ | |
947 | + if (len) | |
948 | + { | |
949 | + xx = (p_rec->free_pad_ptr - ((pad_ptr+len) - | |
950 | + &p_rec->attr_pad[0])); | |
951 | + for( yy=0; yy<xx; yy++, pad_ptr++) | |
952 | + *pad_ptr = *(pad_ptr+len); | |
953 | + p_rec->free_pad_ptr -= len; | |
954 | + } | |
955 | + return (TRUE); | |
913 | 956 | } |
914 | 957 | } |
915 | -#endif | |
916 | - /* If here, not found */ | |
917 | 958 | return (FALSE); |
918 | 959 | } |
919 | 960 |
@@ -59,6 +59,8 @@ extern fixed_queue_t *btu_general_alarm_queue; | ||
59 | 59 | #define AVRCP_SUPPORTED_FEATURES_POSITION 1 |
60 | 60 | #define AVRCP_BROWSE_SUPPORT_BITMASK 0x40 |
61 | 61 | #define AVRCP_CA_SUPPORT_BITMASK 0x01 |
62 | +#define PBAP_SKIP_GOEP_L2CAP_PSM_LEN 0x06 | |
63 | +#define PBAP_SKIP_SUPP_FEA_LEN 0x08 | |
62 | 64 | |
63 | 65 | /********************************************************************************/ |
64 | 66 | /* L O C A L F U N C T I O N P R O T O T Y P E S */ |
@@ -75,6 +77,10 @@ static void process_service_search_attr_req (tCONN_CB *p_ccb, UINT16 trans_num, | ||
75 | 77 | UINT16 param_len, UINT8 *p_req, |
76 | 78 | UINT8 *p_req_end); |
77 | 79 | |
80 | +static BOOLEAN is_pbap_record_blacklisted (tSDP_ATTRIBUTE attr, BD_ADDR remote_address); | |
81 | + | |
82 | +static tSDP_RECORD *sdp_update_pbap_record_if_blacklisted(tSDP_RECORD *p_rec, | |
83 | + BD_ADDR remote_address); | |
78 | 84 | |
79 | 85 | /********************************************************************************/ |
80 | 86 | /* E R R O R T E X T S T R I N G S */ |
@@ -120,6 +126,8 @@ struct blacklist_entry | ||
120 | 126 | char addr[3]; |
121 | 127 | }; |
122 | 128 | |
129 | +static tSDP_RECORD pbap_temp_sdp_rec; | |
130 | + | |
123 | 131 | int sdp_get_stored_avrc_tg_version(BD_ADDR addr) |
124 | 132 | { |
125 | 133 | int stored_ver = AVRC_REV_INVALID; |
@@ -632,6 +640,8 @@ static void process_service_attr_req (tCONN_CB *p_ccb, UINT16 trans_num, | ||
632 | 640 | return; |
633 | 641 | } |
634 | 642 | |
643 | + p_rec = sdp_update_pbap_record_if_blacklisted(p_rec, p_ccb->device_address); | |
644 | + | |
635 | 645 | /* Free and reallocate buffer */ |
636 | 646 | osi_free(p_ccb->rsp_list); |
637 | 647 | p_ccb->rsp_list = (UINT8 *)osi_malloc(max_list_len); |
@@ -699,6 +709,7 @@ static void process_service_attr_req (tCONN_CB *p_ccb, UINT16 trans_num, | ||
699 | 709 | #endif |
700 | 710 | #endif |
701 | 711 | is_hfp_fallback = sdp_change_hfp_version (p_attr, p_ccb->device_address); |
712 | + | |
702 | 713 | /* Check if attribute fits. Assume 3-byte value type/length */ |
703 | 714 | rem_len = max_list_len - (INT16) (p_rsp - &p_ccb->rsp_list[0]); |
704 | 715 |
@@ -922,6 +933,7 @@ static void process_service_search_attr_req (tCONN_CB *p_ccb, UINT16 trans_num, | ||
922 | 933 | UINT8 *p_rsp, *p_rsp_start, *p_rsp_param_len; |
923 | 934 | UINT16 rsp_param_len, xx; |
924 | 935 | tSDP_RECORD *p_rec; |
936 | + tSDP_RECORD *p_prev_rec; | |
925 | 937 | tSDP_ATTR_SEQ attr_seq, attr_seq_sav; |
926 | 938 | tSDP_ATTRIBUTE *p_attr; |
927 | 939 | BT_HDR *p_buf; |
@@ -932,6 +944,7 @@ static void process_service_search_attr_req (tCONN_CB *p_ccb, UINT16 trans_num, | ||
932 | 944 | BOOLEAN is_avrcp_ca_bit_reset = FALSE; |
933 | 945 | UINT8 *p_seq_start = NULL; |
934 | 946 | UINT16 seq_len, attr_len; |
947 | + UINT16 blacklist_skip_len = 0; | |
935 | 948 | UNUSED(p_req_end); |
936 | 949 | |
937 | 950 | /* Extract the UUID sequence to search for */ |
@@ -958,7 +971,6 @@ static void process_service_search_attr_req (tCONN_CB *p_ccb, UINT16 trans_num, | ||
958 | 971 | } |
959 | 972 | |
960 | 973 | memcpy(&attr_seq_sav, &attr_seq, sizeof(tSDP_ATTR_SEQ)) ; |
961 | - | |
962 | 974 | /* Free and reallocate buffer */ |
963 | 975 | osi_free(p_ccb->rsp_list); |
964 | 976 | p_ccb->rsp_list = (UINT8 *)osi_malloc(max_list_len); |
@@ -1010,6 +1022,34 @@ static void process_service_search_attr_req (tCONN_CB *p_ccb, UINT16 trans_num, | ||
1010 | 1022 | for (p_rec = sdp_db_service_search (p_ccb->cont_info.prev_sdp_rec, &uid_seq); p_rec; p_rec = sdp_db_service_search (p_rec, &uid_seq)) |
1011 | 1023 | { |
1012 | 1024 | p_ccb->cont_info.curr_sdp_rec = p_rec; |
1025 | + /* Store the actual record pointer which would be reused later */ | |
1026 | + p_prev_rec = p_rec; | |
1027 | + p_rec = sdp_update_pbap_record_if_blacklisted(p_rec, p_ccb->device_address); | |
1028 | + if (p_rec != p_prev_rec) { | |
1029 | + /* Remote device is blacklisted for PBAP, calculate the reduction in length */ | |
1030 | + for (xx = p_ccb->cont_info.next_attr_index; xx < attr_seq_sav.num_attr; xx++) { | |
1031 | + if (attr_seq_sav.attr_entry[xx].start == attr_seq_sav.attr_entry[xx].end) { | |
1032 | + if (attr_seq_sav.attr_entry[xx].start == ATTR_ID_GOEP_L2CAP_PSM) { | |
1033 | + blacklist_skip_len += PBAP_SKIP_GOEP_L2CAP_PSM_LEN; | |
1034 | + SDP_TRACE_ERROR("%s: ATTR_ID_GOEP_L2CAP_PSM requested," | |
1035 | + " need to reduce length by %d", __func__, | |
1036 | + blacklist_skip_len); | |
1037 | + } else if (attr_seq_sav.attr_entry[xx].start == | |
1038 | + ATTR_ID_PBAP_SUPPORTED_FEATURES) { | |
1039 | + blacklist_skip_len += PBAP_SKIP_SUPP_FEA_LEN; | |
1040 | + SDP_TRACE_DEBUG("%s: ATTR_ID_PBAP_SUPPORTED_FEATURES requested," | |
1041 | + " need to reduce length by %d", __func__, | |
1042 | + blacklist_skip_len); | |
1043 | + } | |
1044 | + } else { | |
1045 | + blacklist_skip_len = PBAP_SKIP_GOEP_L2CAP_PSM_LEN + | |
1046 | + PBAP_SKIP_SUPP_FEA_LEN; | |
1047 | + SDP_TRACE_DEBUG("%s: All attributes requested" | |
1048 | + " need to reduce length by %d", __func__, | |
1049 | + blacklist_skip_len); | |
1050 | + } | |
1051 | + } | |
1052 | + } | |
1013 | 1053 | /* Allow space for attribute sequence type and length */ |
1014 | 1054 | p_seq_start = p_rsp; |
1015 | 1055 | if (p_ccb->cont_info.last_attr_seq_desc_sent == FALSE) |
@@ -1210,6 +1250,8 @@ static void process_service_search_attr_req (tCONN_CB *p_ccb, UINT16 trans_num, | ||
1210 | 1250 | |
1211 | 1251 | /* Reset the next attr index */ |
1212 | 1252 | p_ccb->cont_info.next_attr_index = 0; |
1253 | + /* restore the record pointer.*/ | |
1254 | + p_rec = p_prev_rec; | |
1213 | 1255 | p_ccb->cont_info.prev_sdp_rec = p_rec; |
1214 | 1256 | p_ccb->cont_info.last_attr_seq_desc_sent = FALSE; |
1215 | 1257 | } |
@@ -1244,6 +1286,13 @@ static void process_service_search_attr_req (tCONN_CB *p_ccb, UINT16 trans_num, | ||
1244 | 1286 | { |
1245 | 1287 | /* Get the total list length for requested uid and attribute sequence */ |
1246 | 1288 | p_ccb->list_len = sdpu_get_list_len(&uid_seq, &attr_seq_sav) + 3; |
1289 | + if (blacklist_skip_len && | |
1290 | + p_ccb->list_len > blacklist_skip_len) { | |
1291 | + p_ccb->list_len -= blacklist_skip_len; | |
1292 | + SDP_TRACE_DEBUG("%s: reducing list_len by %d for blacklisted device", | |
1293 | + __func__, blacklist_skip_len); | |
1294 | + blacklist_skip_len = 0; | |
1295 | + } | |
1247 | 1296 | /* Put in the sequence header (2 or 3 bytes) */ |
1248 | 1297 | if (p_ccb->list_len > 255) |
1249 | 1298 | { |
@@ -1285,6 +1334,14 @@ static void process_service_search_attr_req (tCONN_CB *p_ccb, UINT16 trans_num, | ||
1285 | 1334 | |
1286 | 1335 | p_ccb->cont_offset += len_to_send; |
1287 | 1336 | |
1337 | + if (blacklist_skip_len && | |
1338 | + p_ccb->list_len > blacklist_skip_len) { | |
1339 | + p_ccb->list_len -= blacklist_skip_len; | |
1340 | + SDP_TRACE_DEBUG("%s: reducing list_len by %d for blacklisted device", | |
1341 | + __func__, blacklist_skip_len); | |
1342 | + blacklist_skip_len = 0; | |
1343 | + } | |
1344 | + | |
1288 | 1345 | /* If anything left to send, continuation needed */ |
1289 | 1346 | if (p_ccb->cont_offset < p_ccb->list_len) |
1290 | 1347 | { |
@@ -1308,4 +1365,91 @@ static void process_service_search_attr_req (tCONN_CB *p_ccb, UINT16 trans_num, | ||
1308 | 1365 | L2CA_DataWrite (p_ccb->connection_id, p_buf); |
1309 | 1366 | } |
1310 | 1367 | |
1368 | +/************************************************************************************* | |
1369 | +** | |
1370 | +** Function is_pbap_record_blacklisted | |
1371 | +** | |
1372 | +** Description Checks if given PBAP record is for PBAP PSE and blacklisted | |
1373 | +** | |
1374 | +** Returns BOOLEAN | |
1375 | +** | |
1376 | +***************************************************************************************/ | |
1377 | +static BOOLEAN is_pbap_record_blacklisted (tSDP_ATTRIBUTE attr, | |
1378 | + BD_ADDR remote_address) | |
1379 | +{ | |
1380 | + if ((attr.id == ATTR_ID_SERVICE_CLASS_ID_LIST) && | |
1381 | + (((attr.value_ptr[1] << 8) | (attr.value_ptr[2])) == | |
1382 | + UUID_SERVCLASS_PBAP_PSE)) | |
1383 | + { | |
1384 | + bt_bdaddr_t remote_bdaddr; | |
1385 | + bdcpy(remote_bdaddr.address, remote_address); | |
1386 | + | |
1387 | + bt_property_t prop_name; | |
1388 | + bt_bdname_t bdname; | |
1389 | + | |
1390 | + memset(&bdname, 0, sizeof(bt_bdname_t)); | |
1391 | + | |
1392 | + BTIF_STORAGE_FILL_PROPERTY(&prop_name, BT_PROPERTY_BDNAME, | |
1393 | + sizeof(bt_bdname_t), &bdname); | |
1394 | + if (btif_storage_get_remote_device_property(&remote_bdaddr, | |
1395 | + &prop_name) != BT_STATUS_SUCCESS) { | |
1396 | + SDP_TRACE_DEBUG("%s: BT_PROPERTY_BDNAME failed", __func__); | |
1397 | + } | |
1398 | + if (interop_match_addr(INTEROP_ADV_PBAP_VER_1_1, &remote_bdaddr) || | |
1399 | + (strlen((const char *)bdname.name) != 0 && | |
1400 | + interop_match_name(INTEROP_ADV_PBAP_VER_1_1, | |
1401 | + (const char *)bdname.name))) { | |
1402 | + SDP_TRACE_DEBUG("%s: device is blacklisted for pbap version downgrade", __func__); | |
1403 | + return TRUE; | |
1404 | + } | |
1405 | + } | |
1406 | + | |
1407 | + return FALSE; | |
1408 | +} | |
1409 | + | |
1410 | +/************************************************************************************* | |
1411 | +** | |
1412 | +** Function sdp_update_pbap_record_if_blacklisted | |
1413 | +** | |
1414 | +** Description updates pbap record after checking if blacklisted | |
1415 | +** | |
1416 | +** Returns the address of updated record | |
1417 | +** | |
1418 | +***************************************************************************************/ | |
1419 | +static tSDP_RECORD *sdp_update_pbap_record_if_blacklisted(tSDP_RECORD *p_rec, | |
1420 | + BD_ADDR remote_address) | |
1421 | +{ | |
1422 | + /* Check if the given SDP record is blacklisted and requires updatiion */ | |
1423 | + if (is_pbap_record_blacklisted(p_rec->attribute[1], remote_address)) { | |
1424 | + bool status = TRUE; | |
1425 | + int xx; | |
1426 | + UINT8 supported_repositories = 0x03; | |
1427 | + UINT16 legacy_version = 0x0101; | |
1428 | + memset(&pbap_temp_sdp_rec, 0, sizeof(tSDP_RECORD)); | |
1429 | + | |
1430 | + tSDP_ATTRIBUTE *p_attr = &p_rec->attribute[0]; | |
1431 | + | |
1432 | + /* Copying contents of the PBAP PSE record to a temporary record */ | |
1433 | + for (xx = 0; xx < p_rec->num_attributes; xx++, p_attr++) | |
1434 | + SDP_AddAttributetoRecord (&pbap_temp_sdp_rec, p_attr->id, | |
1435 | + p_attr->type, p_attr->len, p_attr->value_ptr); | |
1436 | + | |
1437 | + status &= SDP_DeleteAttributefromRecord (&pbap_temp_sdp_rec, | |
1438 | + ATTR_ID_PBAP_SUPPORTED_FEATURES); | |
1439 | + status &= SDP_DeleteAttributefromRecord (&pbap_temp_sdp_rec, | |
1440 | + ATTR_ID_GOEP_L2CAP_PSM); | |
1441 | + status &= SDP_AddAttributetoRecord (&pbap_temp_sdp_rec, | |
1442 | + ATTR_ID_SUPPORTED_REPOSITORIES, UINT_DESC_TYPE, (UINT32)1, | |
1443 | + (UINT8*)&supported_repositories); | |
1444 | + status &= SDP_AddProfileDescriptorListtoRecord(&pbap_temp_sdp_rec, | |
1445 | + UUID_SERVCLASS_PHONE_ACCESS, legacy_version); | |
1446 | + if (!status) { | |
1447 | + SDP_TRACE_ERROR("%s() FAILED", __func__); | |
1448 | + return p_rec; | |
1449 | + } | |
1450 | + return &pbap_temp_sdp_rec; | |
1451 | + } | |
1452 | + return p_rec; | |
1453 | +} | |
1454 | + | |
1311 | 1455 | #endif /* SDP_SERVER_ENABLED == TRUE */ |
@@ -301,6 +301,11 @@ extern void sdpu_uuid16_to_uuid128(UINT16 uuid16, UINT8* p_uuid128); | ||
301 | 301 | extern tSDP_RECORD *sdp_db_service_search (tSDP_RECORD *p_rec, tSDP_UUID_SEQ *p_seq); |
302 | 302 | extern tSDP_RECORD *sdp_db_find_record (UINT32 handle); |
303 | 303 | extern tSDP_ATTRIBUTE *sdp_db_find_attr_in_rec (tSDP_RECORD *p_rec, UINT16 start_attr, UINT16 end_attr); |
304 | +extern BOOLEAN SDP_AddAttributetoRecord (tSDP_RECORD *p_rec, UINT16 attr_id, UINT8 attr_type, | |
305 | + UINT32 attr_len, UINT8 *p_val); | |
306 | +extern BOOLEAN SDP_AddProfileDescriptorListtoRecord (tSDP_RECORD *p_rec, UINT16 profile_uuid, | |
307 | + UINT16 version); | |
308 | +extern BOOLEAN SDP_DeleteAttributefromRecord (tSDP_RECORD *p_rec, UINT16 attr_id); | |
304 | 309 | |
305 | 310 | |
306 | 311 | /* Functions provided by sdp_server.c |