Commit c362709a authored by Dean Camera's avatar Dean Camera
Browse files

The SDP UUID lists should be searched and ALL UUIDs matched for a record to be...

The SDP UUID lists should be searched and ALL UUIDs matched for a record to be retrieved, not partial matches. Change the SDP code so that the entire list must be matched against a service attribute table's contents before it is returned.

Change matching algorithm so that it recursively searches through the entire attribute table, and not just pre-specified sequence attributes.

Add browse lists and proper descriptions to the Serial Port service.
parent da51c1f9
......@@ -30,86 +30,6 @@
#include "SDPServices.h"
/* ------------------------------ SDP SERVICE ATTRIBUTES ------------------------------ */
const struct
{
uint8_t Header;
uint32_t Data;
} PROGMEM SDP_Attribute_ServiceHandle =
{
(SDP_DATATYPE_UnsignedInt | SDP_DATASIZE_32Bit),
SWAPENDIAN_32(0x00010000),
};
const struct
{
uint8_t Header;
uint16_t Size;
ItemUUID_t UUIDList[];
} PROGMEM SDP_Attribute_ServiceClassIDs =
{
(SDP_DATATYPE_Sequence | SDP_DATASIZE_Variable16Bit),
SWAPENDIAN_16(sizeof(ItemUUID_t) * 1),
{
{(SDP_DATATYPE_UUID | SDP_DATASIZE_128Bit), SDP_CLASS_UUID}
}
};
const struct
{
uint8_t Header;
uint8_t Size;
Item16Bit_t VersionList[];
} PROGMEM SDP_Attribute_Version =
{
(SDP_DATATYPE_Sequence | SDP_DATASIZE_Variable8Bit),
(sizeof(Item16Bit_t) * 1),
{
{(SDP_DATATYPE_UnsignedInt | SDP_DATASIZE_16Bit), SWAPENDIAN_16(0x0100)}
}
};
const struct
{
uint8_t Header;
uint8_t Size;
char Text[];
} PROGMEM SDP_Attribute_ServiceName =
{
(SDP_DATATYPE_String | SDP_DATASIZE_Variable8Bit),
(sizeof("SDP") - 1),
"SDP",
};
const struct
{
uint8_t Header;
uint8_t Size;
char Text[];
} PROGMEM SDP_Attribute_ServiceDescription =
{
(SDP_DATATYPE_String | SDP_DATASIZE_Variable8Bit),
(sizeof("Service Discovery Protocol Server") - 1),
"Service Discovery Protocol Server",
};
/** Service Discovery Protocol attribute table, listing all supported attributes of the service. */
const ServiceAttributeTable_t SDP_Attribute_Table[] PROGMEM =
{
{.AttributeID = SDP_ATTRIBUTE_ID_SERVICERECORDHANDLE, .Data = &SDP_Attribute_ServiceHandle },
{.AttributeID = SDP_ATTRIBUTE_ID_SERVICECLASSIDS, .Data = &SDP_Attribute_ServiceClassIDs },
{.AttributeID = SDP_ATTRIBUTE_ID_VERSION, .Data = &SDP_Attribute_Version },
{.AttributeID = SDP_ATTRIBUTE_ID_SERVICENAME, .Data = &SDP_Attribute_ServiceName },
{.AttributeID = SDP_ATTRIBUTE_ID_SERVICEDESCRIPTION, .Data = &SDP_Attribute_ServiceDescription },
SERVICE_ATTRIBUTE_TABLE_TERMINATOR
};
/* ------------------------------ RFCOMM SERVICE ATTRIBUTES ------------------------------ */
const struct
{
uint8_t Header;
......@@ -147,123 +67,64 @@ const struct
{
{
(SDP_DATATYPE_Sequence | SDP_DATASIZE_Variable8Bit),
sizeof(UUID_t),
sizeof(ItemUUID_t),
{
{(SDP_DATATYPE_UUID | SDP_DATASIZE_128Bit), L2CAP_UUID},
}
},
{
(SDP_DATATYPE_Sequence | SDP_DATASIZE_Variable8Bit),
sizeof(UUID_t),
sizeof(ItemUUID_t),
{
{(SDP_DATATYPE_UUID | SDP_DATASIZE_128Bit), RFCOMM_UUID},
}
}
},
}
};
const struct
{
uint8_t Header;
uint8_t Size;
char Text[];
} PROGMEM RFCOMM_Attribute_ServiceName =
{
(SDP_DATATYPE_String | SDP_DATASIZE_Variable8Bit),
sizeof("Serial Port") - 1,
"Serial Port",
};
const struct
{
uint8_t Header;
uint8_t Size;
char Text[];
} PROGMEM RFCOMM_Attribute_ServiceDescription =
{
(SDP_DATATYPE_String | SDP_DATASIZE_Variable8Bit),
sizeof("Wireless Serial Port Service") - 1,
"Wireless Serial Port Service",
};
const ServiceAttributeTable_t RFCOMM_Attribute_Table[] PROGMEM =
{
{.AttributeID = SDP_ATTRIBUTE_ID_SERVICERECORDHANDLE, .Data = &RFCOMM_Attribute_ServiceHandle },
{.AttributeID = SDP_ATTRIBUTE_ID_SERVICECLASSIDS, .Data = &RFCOMM_Attribute_ServiceClassIDs },
{.AttributeID = SDP_ATTRIBUTE_ID_PROTOCOLDESCRIPTORLIST, .Data = &RFCOMM_Attribute_ProtocolDescriptor },
{.AttributeID = SDP_ATTRIBUTE_ID_SERVICENAME, .Data = &RFCOMM_Attribute_ServiceName },
{.AttributeID = SDP_ATTRIBUTE_ID_SERVICEDESCRIPTION, .Data = &RFCOMM_Attribute_ServiceDescription },
SERVICE_ATTRIBUTE_TABLE_TERMINATOR
};
/* ------------------------------ L2CAP SERVICE ATTRIBUTES ------------------------------ */
const struct
{
uint8_t Header;
uint32_t Data;
} PROGMEM L2CAP_Attribute_ServiceHandle =
{
(SDP_DATATYPE_UnsignedInt | SDP_DATASIZE_32Bit),
SWAPENDIAN_32(0x00010002),
};
const struct
{
uint8_t Header;
uint16_t Size;
ItemUUID_t UUIDList[];
} PROGMEM L2CAP_Attribute_ServiceClassIDs =
} PROGMEM RFCOMM_Attribute_BrowseGroupList =
{
(SDP_DATATYPE_Sequence | SDP_DATASIZE_Variable16Bit),
SWAPENDIAN_16(sizeof(ItemUUID_t) * 2),
SWAPENDIAN_16(sizeof(ItemUUID_t) * 1),
{
{(SDP_DATATYPE_UUID | SDP_DATASIZE_128Bit), SDP_CLASS_UUID },
{(SDP_DATATYPE_UUID | SDP_DATASIZE_128Bit), SP_CLASS_UUID },
{(SDP_DATATYPE_UUID | SDP_DATASIZE_128Bit), PUBLICBROWSEGROUP_CLASS_UUID}
}
};
const struct
{
uint8_t Header;
uint16_t Size;
ItemProtocol_t ProtocolList[];
} PROGMEM L2CAP_Attribute_ProtocolDescriptor =
{
(SDP_DATATYPE_Sequence | SDP_DATASIZE_Variable16Bit),
SWAPENDIAN_16(sizeof(ItemProtocol_t) * 2),
{
uint8_t Header;
uint8_t Size;
ItemLangID_t OffsetList[];
} PROGMEM RFCOMM_Attribute_LanguageBaseIDOffset =
{
.Header = (SDP_DATATYPE_Sequence | SDP_DATASIZE_Variable8Bit),
.Size = (sizeof(ItemLangID_t) * 1),
.OffsetList =
{
(SDP_DATATYPE_Sequence | SDP_DATASIZE_Variable8Bit),
sizeof(UUID_t),
{
{(SDP_DATATYPE_UUID | SDP_DATASIZE_128Bit), L2CAP_UUID},
}
},
{
(SDP_DATATYPE_Sequence | SDP_DATASIZE_Variable8Bit),
sizeof(UUID_t),
{
{(SDP_DATATYPE_UUID | SDP_DATASIZE_128Bit), RFCOMM_UUID},
{(SDP_DATATYPE_UnsignedInt | SDP_DATASIZE_16Bit), SWAPENDIAN_16(0x454E)},
{(SDP_DATATYPE_UnsignedInt | SDP_DATASIZE_16Bit), SWAPENDIAN_16(0x006A)},
{(SDP_DATATYPE_UnsignedInt | SDP_DATASIZE_16Bit), SWAPENDIAN_16(0x0100)},
}
}
}
};
};
const struct
{
uint8_t Header;
uint8_t Size;
char Text[];
} PROGMEM L2CAP_Attribute_ServiceName =
} PROGMEM RFCOMM_Attribute_ServiceName =
{
(SDP_DATATYPE_String | SDP_DATASIZE_Variable8Bit),
sizeof("L2CAP") - 1,
"L2CAP",
sizeof("Serial Port") - 1,
"Serial Port",
};
const struct
......@@ -271,20 +132,22 @@ const struct
uint8_t Header;
uint8_t Size;
char Text[];
} PROGMEM L2CAP_Attribute_ServiceDescription =
} PROGMEM RFCOMM_Attribute_ServiceDescription =
{
(SDP_DATATYPE_String | SDP_DATASIZE_Variable8Bit),
sizeof("Logical Link Layer") - 1,
"Logical Link Layer",
sizeof("Wireless Serial Port Service") - 1,
"Wireless Serial Port Service",
};
const ServiceAttributeTable_t L2CAP_Attribute_Table[] PROGMEM =
const ServiceAttributeTable_t PROGMEM RFCOMM_Attribute_Table[] =
{
{.AttributeID = SDP_ATTRIBUTE_ID_SERVICERECORDHANDLE, .Data = &L2CAP_Attribute_ServiceHandle },
{.AttributeID = SDP_ATTRIBUTE_ID_SERVICECLASSIDS, .Data = &L2CAP_Attribute_ServiceClassIDs },
{.AttributeID = SDP_ATTRIBUTE_ID_PROTOCOLDESCRIPTORLIST, .Data = &L2CAP_Attribute_ProtocolDescriptor },
{.AttributeID = SDP_ATTRIBUTE_ID_SERVICENAME, .Data = &L2CAP_Attribute_ServiceName },
{.AttributeID = SDP_ATTRIBUTE_ID_SERVICEDESCRIPTION, .Data = &L2CAP_Attribute_ServiceDescription },
{.AttributeID = SDP_ATTRIBUTE_ID_SERVICERECORDHANDLE, .Data = &RFCOMM_Attribute_ServiceHandle },
{.AttributeID = SDP_ATTRIBUTE_ID_SERVICECLASSIDS, .Data = &RFCOMM_Attribute_ServiceClassIDs },
{.AttributeID = SDP_ATTRIBUTE_ID_PROTOCOLDESCRIPTORLIST, .Data = &RFCOMM_Attribute_ProtocolDescriptor },
{.AttributeID = SDP_ATTRIBUTE_ID_BROWSEGROUPLIST, .Data = &RFCOMM_Attribute_BrowseGroupList },
{.AttributeID = SDP_ATTRIBUTE_ID_LANGUAGEBASEATTROFFSET, .Data = &RFCOMM_Attribute_LanguageBaseIDOffset},
{.AttributeID = SDP_ATTRIBUTE_ID_SERVICENAME, .Data = &RFCOMM_Attribute_ServiceName },
{.AttributeID = SDP_ATTRIBUTE_ID_SERVICEDESCRIPTION, .Data = &RFCOMM_Attribute_ServiceDescription },
SERVICE_ATTRIBUTE_TABLE_TERMINATOR
};
......@@ -49,14 +49,15 @@
#define SDP_UUID {BASE_80BIT_UUID, {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}}
#define RFCOMM_UUID {BASE_80BIT_UUID, {0x00, 0x00, 0x00, 0x00, 0x00, 0x03}}
#define L2CAP_UUID {BASE_80BIT_UUID, {0x00, 0x00, 0x00, 0x00, 0x01, 0x00}}
#define UPNP_UUID {BASE_80BIT_UUID, {0x00, 0x00, 0x00, 0x00, 0x00, 0x10}}
#define SDP_CLASS_UUID {BASE_80BIT_UUID, {0x00, 0x00, 0x00, 0x00, 0x10, 0x00}}
#define SP_CLASS_UUID {BASE_80BIT_UUID, {0x00, 0x00, 0x00, 0x00, 0x11, 0x01}}
#define UPNP_CLASS_UUID {BASE_80BIT_UUID, {0x00, 0x00, 0x00, 0x00, 0x12, 0x00}}
#define PUBLICBROWSEGROUP_CLASS_UUID {BASE_80BIT_UUID, {0x00, 0x00, 0x00, 0x00, 0x10, 0x02}}
#define SDP_ATTRIBUTE_ID_SERVICERECORDHANDLE 0x0000
#define SDP_ATTRIBUTE_ID_SERVICECLASSIDS 0x0001
#define SDP_ATTRIBUTE_ID_PROTOCOLDESCRIPTORLIST 0x0004
#define SDP_ATTRIBUTE_ID_BROWSEGROUPLIST 0x0005
#define SDP_ATTRIBUTE_ID_LANGUAGEBASEATTROFFSET 0x0006
#define SDP_ATTRIBUTE_ID_VERSION 0x0200
#define SDP_ATTRIBUTE_ID_SERVICENAME 0x0100
#define SDP_ATTRIBUTE_ID_SERVICEDESCRIPTION 0x0101
......@@ -87,15 +88,6 @@
const void* Data; /**< Pointer to the attribute data, located in PROGMEM memory space */
} ServiceAttributeTable_t;
/** Structure for the association of service UUID values to attribute tables stored in FLASH. A table of these
* structures can then be built up for each supported UUID service within the device.
*/
typedef struct
{
UUID_t UUID; /**< UUID of a service supported by the device */
const void* AttributeTable; /**< Pointer to the UUID's attribute table, located in PROGMEM memory space */
} ServiceTable_t;
/** Structure for a list of Data Elements containing 8-bit integers, for service attributes requiring such lists. */
typedef struct
{
......@@ -138,9 +130,14 @@
} Protocol;
} ItemProtocol_t;
typedef struct
{
Item16Bit_t LanguageID;
Item16Bit_t EncodingID;
Item16Bit_t OffsetID;
} ItemLangID_t;
/* External Variables: */
extern const ServiceAttributeTable_t SDP_Attribute_Table[];
extern const ServiceAttributeTable_t RFCOMM_Attribute_Table[];
extern const ServiceAttributeTable_t L2CAP_Attribute_Table[];
#endif
......@@ -31,14 +31,10 @@
#define INCLUDE_FROM_SERVICEDISCOVERYPROTOCOL_C
#include "ServiceDiscoveryProtocol.h"
/** Master service table, listing all supported services (and their attribute tables) of the device, including
* each service's UUID.
*/
const ServiceTable_t SDP_Services_Table[] PROGMEM =
/** Service attribute table list, containing a pointer to each service attribute table the device contains */
const ServiceAttributeTable_t* SDP_Services_Table[] PROGMEM =
{
{ .UUID = SDP_UUID , .AttributeTable = SDP_Attribute_Table },
{ .UUID = RFCOMM_UUID, .AttributeTable = RFCOMM_Attribute_Table },
{ .UUID = L2CAP_UUID , .AttributeTable = L2CAP_Attribute_Table },
RFCOMM_Attribute_Table,
};
/** Base UUID value common to all standardized Bluetooth services */
......@@ -101,25 +97,25 @@ static void SDP_ProcessServiceSearch(const SDP_PDUHeader_t* const SDPHeader, Blu
uint16_t CurrentServiceRecordCount;
uint8_t ResponseData[100];
} ResponsePacket;
uint8_t AddedServiceHandles = 0;
/* Create a pointer to the buffer to indicate the current location for response data to be added */
void* CurrResponsePos = ResponsePacket.ResponseData;
uint8_t AddedServiceHandles = 0;
/* Search through the list of UUIDs one at a time looking for matching search Attributes */
for (uint8_t CurrUUIDItem = 0; CurrUUIDItem < TotalUUIDs; CurrUUIDItem++)
/* Search through the global service list an item at a time */
for (uint8_t CurrTableItem = 0; CurrTableItem < (sizeof(SDP_Services_Table) / sizeof(void*)); CurrTableItem++)
{
ServiceAttributeTable_t* AttributeTable;
/* Read in a pointer to the current UUID table entry's Attribute table */
ServiceAttributeTable_t* CurrAttributeTable = pgm_read_ptr(&SDP_Services_Table[CurrTableItem]);
/* Retrieve the attribute table of the current search UUID from the global UUID table if it exists */
if ((AttributeTable = SDP_GetAttributeTable(UUIDList[CurrUUIDItem])) == NULL)
if (!(SDP_SearchServiceTable(UUIDList, TotalUUIDs, CurrAttributeTable)))
continue;
BT_SDP_DEBUG(2, " -- Found UUID %d in table", CurrUUIDItem);
BT_SDP_DEBUG(2, " -- Found search match in table");
/* Retrieve a PROGMEM pointer to the value of the service's record handle */
const void* AttributeValue = SDP_GetAttributeValue(AttributeTable, SDP_ATTRIBUTE_ID_SERVICERECORDHANDLE);
const void* AttributeValue = SDP_GetAttributeValue(CurrAttributeTable, SDP_ATTRIBUTE_ID_SERVICERECORDHANDLE);
/* Copy over the service record handle to the response list */
uint8_t AttrHeaderSize;
......@@ -197,10 +193,10 @@ static void SDP_ProcessServiceAttribute(const SDP_PDUHeader_t* const SDPHeader,
uint16_t TotalResponseSize = 0;
/* Search through the global UUID list an item at a time */
for (uint8_t CurrTableItem = 0; CurrTableItem < (sizeof(SDP_Services_Table) / sizeof(ServiceTable_t)); CurrTableItem++)
for (uint8_t CurrTableItem = 0; CurrTableItem < (sizeof(SDP_Services_Table) / sizeof(void*)); CurrTableItem++)
{
/* Read in a pointer to the current UUID table entry's Attribute table */
ServiceAttributeTable_t* CurrAttributeTable = (ServiceAttributeTable_t*)pgm_read_word(&SDP_Services_Table[CurrTableItem].AttributeTable);
ServiceAttributeTable_t* CurrAttributeTable = pgm_read_ptr(&SDP_Services_Table[CurrTableItem]);
/* Retrieve a PROGMEM pointer to the value of the Service Record Handle */
const void* ServiceRecord = SDP_GetAttributeValue(CurrAttributeTable, SDP_ATTRIBUTE_ID_SERVICERECORDHANDLE);
......@@ -288,19 +284,19 @@ static void SDP_ProcessServiceSearchAttribute(const SDP_PDUHeader_t* const SDPHe
/* Add the outer Data Element Sequence header for all of the retrieved Attributes */
uint16_t* TotalResponseSize = SDP_AddSequence16(&CurrResponsePos);
/* Search through the list of UUIDs one at a time looking for matching search Attributes */
for (uint8_t CurrUUIDItem = 0; CurrUUIDItem < TotalUUIDs; CurrUUIDItem++)
/* Search through the global service list an item at a time */
for (uint8_t CurrTableItem = 0; CurrTableItem < (sizeof(SDP_Services_Table) / sizeof(void*)); CurrTableItem++)
{
ServiceAttributeTable_t* AttributeTable;
/* Read in a pointer to the current UUID table entry's Attribute table */
ServiceAttributeTable_t* CurrAttributeTable = pgm_read_ptr(&SDP_Services_Table[CurrTableItem]);
/* Retrieve the attribute table of the current search UUID from the global UUID table if it exists */
if ((AttributeTable = SDP_GetAttributeTable(UUIDList[CurrUUIDItem])) == NULL)
if (!(SDP_SearchServiceTable(UUIDList, TotalUUIDs, CurrAttributeTable)))
continue;
BT_SDP_DEBUG(2, " -- Found UUID %d in table", CurrUUIDItem);
BT_SDP_DEBUG(2, " -- Found search match in table");
/* Add the listed attributes for the found UUID to the response */
*TotalResponseSize += SDP_AddListedAttributesToResponse(AttributeTable, AttributeList, TotalAttributes,
*TotalResponseSize += SDP_AddListedAttributesToResponse(CurrAttributeTable, AttributeList, TotalAttributes,
&CurrResponsePos);
}
......@@ -355,7 +351,7 @@ static uint16_t SDP_AddListedAttributesToResponse(const ServiceAttributeTable_t*
void* AttributeValue;
/* Look through the current service's attribute list, examining all the attributes */
while ((AttributeValue = (void*)pgm_read_word(&AttributeTable->Data)) != NULL)
while ((AttributeValue = pgm_read_ptr(&AttributeTable->Data)) != NULL)
{
/* Get the current Attribute's ID from the current attribute table entry */
uint16_t CurrAttributeID = pgm_read_word(&AttributeTable->AttributeID);
......@@ -421,7 +417,7 @@ static void* SDP_GetAttributeValue(const ServiceAttributeTable_t* AttributeTable
void* CurrTableItemData;
/* Search through the current Attribute table, abort when the terminator item has been reached */
while ((CurrTableItemData = (void*)pgm_read_word(&AttributeTable->Data)) != NULL)
while ((CurrTableItemData = pgm_read_ptr(&AttributeTable->Data)) != NULL)
{
/* Check if the current Attribute ID matches the search ID - if so return a pointer to it */
if (pgm_read_word(&AttributeTable->AttributeID) == AttributeID)
......@@ -433,49 +429,91 @@ static void* SDP_GetAttributeValue(const ServiceAttributeTable_t* AttributeTable
return NULL;
}
/** Retrieves the Attribute table for the given UUID if it exists.
/** Retrieves the Attribute table for the given UUID list if it exists.
*
* \param[in] UUID UUID to search for
* \param[in] UUIDList List of UUIDs which must be matched within the service attribute table
* \param[in] TotalUUIDs Total number of UUIDs stored in the UUID list
* \param[in] CurrAttributeTable Pointer to the service attribute table to search through
*
* \return Pointer to the UUID's associated Attribute table if found in the global UUID table, NULL otherwise
* \return True if all the UUIDs given in the UUID list appear in the given attribute table, false otherwise
*/
static ServiceAttributeTable_t* SDP_GetAttributeTable(const uint8_t* const UUID)
static bool SDP_SearchServiceTable(uint8_t UUIDList[][UUID_SIZE_BYTES], const uint8_t TotalUUIDs,
const ServiceAttributeTable_t* CurrAttributeTable)
{
/* Search through the global UUID list an item at a time */
for (uint8_t CurrTableItem = 0; CurrTableItem < (sizeof(SDP_Services_Table) / sizeof(ServiceTable_t)); CurrTableItem++)
bool UUIDMatch[TotalUUIDs];
/* Set all the match flags to false (not matched) before starting the search */
memset(UUIDMatch, false, sizeof(UUIDMatch));
const void* CurrAttribute;
/* Search through the current attribute table, checking each attribute value for UUID matches */
while ((CurrAttribute = pgm_read_ptr(&CurrAttributeTable->Data)) != NULL)
{
/* Read in a pointer to the current UUID table entry's Attribute table */
ServiceAttributeTable_t* CurrAttributeTable = (ServiceAttributeTable_t*)pgm_read_word(&SDP_Services_Table[CurrTableItem].AttributeTable);
SDP_CheckUUIDMatch(UUIDList, TotalUUIDs, UUIDMatch, CurrAttribute);
CurrAttributeTable++;
}
/* Determine how many UUID matches in the list we have found */
uint8_t UUIDMatches = 0;
for (uint8_t i = 0; i < TotalUUIDs; i++)
{
if (UUIDMatch[i])
UUIDMatches++;
}
/* If the current table item's UUID matches the search UUID, return a pointer the table item's Attribute table */
if (!(memcmp_P(UUID, &SDP_Services_Table[CurrTableItem].UUID, UUID_SIZE_BYTES)))
return CurrAttributeTable;
/* Retrieve the list of the service's Class UUIDs from its Attribute table */
void* ClassUUIDs = SDP_GetAttributeValue(CurrAttributeTable, SDP_ATTRIBUTE_ID_SERVICECLASSIDS);
/* If all UUIDs have been matched to the current service, return true */
return (UUIDMatches == TotalUUIDs);
}
/** Recursively upwraps the given locally stored attribute (in PROGMEM space), searching for UUIDs to match against
* the given UUID list. As matches are found, they are indicated in the UUIDMatch flag list.
*
* \param[in] UUIDList List of UUIDs which must be matched within the service attribute table
* \param[in] TotalUUIDs Total number of UUIDs stored in the UUID list
* \param[in, out] UUIDMatch Array of flags indicating which UUIDs in the list have already been matched
* \param[in] CurrAttribute Pointer to the current attribute to search through
*
* \return True if all the UUIDs given in the UUID list appear in the given attribute table, false otherwise
*/
static void SDP_CheckUUIDMatch(uint8_t UUIDList[][UUID_SIZE_BYTES], const uint8_t TotalUUIDs, bool UUIDMatch[],
const void* CurrAttribute)
{
uint8_t CurrAttributeType = (pgm_read_byte(CurrAttribute) & ~0x07);
/* Check the data type of the current attribute value - if UUID, compare, if Sequence, unwrap and recurse */
if (CurrAttributeType == SDP_DATATYPE_UUID)
{
/* Look for matches in the UUID list against the current attribute UUID value */
for (uint8_t i = 0; i < TotalUUIDs; i++)
{
if (!(UUIDMatch[i]) && !(memcmp_P(UUIDList[i], (CurrAttribute + 1), UUID_SIZE_BYTES)))
{
/* Indicate match found for the current attribute UUID and early-abort */
UUIDMatch[i] = true;
break;
}
}
}
else if (CurrAttributeType == SDP_DATATYPE_Sequence)
{
uint8_t SequenceHeaderSize;
uint16_t SequenceSize = SDP_GetLocalAttributeContainerSize(CurrAttribute, &SequenceHeaderSize);
/* Go to the next UUID in the table if the current item does not have a list of Class UUIDs */
if (ClassUUIDs == NULL)
continue;
/* Retrieve the size of the Class UUID list and skip past the header to the first Class UUID in the list */
uint8_t ClassUUIDListHeaderSize;
uint16_t ClassUUIDListSize = SDP_GetLocalAttributeContainerSize(ClassUUIDs, &ClassUUIDListHeaderSize);
ClassUUIDs += ClassUUIDListHeaderSize;
CurrAttribute += SequenceHeaderSize;
/* Check each class UUID in turn for a match */
while (ClassUUIDListSize)
/* Recursively unwrap the sequence container, and re-search its contents for UUIDs */
while (SequenceSize)
{
/* Current Service UUID's Class UUID list has a matching entry, return the Attribute table */
if (!(memcmp_P(UUID, &((ItemUUID_t*)ClassUUIDs)->UUID, UUID_SIZE_BYTES)))
return CurrAttributeTable;
ClassUUIDListSize -= sizeof(ItemUUID_t);
ClassUUIDs += sizeof(ItemUUID_t);
}
}
return NULL;
uint8_t InnerHeaderSize;
uint16_t InnerSize = SDP_GetLocalAttributeContainerSize(CurrAttribute, &InnerHeaderSize);
SDP_CheckUUIDMatch(UUIDList, TotalUUIDs, UUIDMatch, CurrAttribute);
SequenceSize -= InnerHeaderSize + InnerSize;
CurrAttribute += InnerHeaderSize + InnerSize;
}
}
}
/** Reads in the collection of Attribute ranges from the input buffer's Data Element Sequence container, into the given
......@@ -620,20 +658,20 @@ static uint32_t SDP_GetDataElementSize(const void** const DataElementHeader, uin
switch (SizeIndex)
{
case SDP_DATASIZE_Variable8Bit:
ElementValueSize = SDP_ReadData8(DataElementHeader);
*ElementHeaderSize = (1 + sizeof(uint8_t));
ElementValueSize = SDP_ReadData8(DataElementHeader);
break;
case SDP_DATASIZE_Variable16Bit:
ElementValueSize = SDP_ReadData16(DataElementHeader);
*ElementHeaderSize = (1 + sizeof(uint16_t));
ElementValueSize = SDP_ReadData16(DataElementHeader);
break;
case SDP_DATASIZE_Variable32Bit:
ElementValueSize = SDP_ReadData32(DataElementHeader);
*ElementHeaderSize = (1 + sizeof(uint32_t));
ElementValueSize = SDP_ReadData32(DataElementHeader);
break;
default:
ElementValueSize = (1 << SizeIndex);
*ElementHeaderSize = 1;
ElementValueSize = (1 << SizeIndex);
break;
}
......
......@@ -50,7 +50,7 @@
/* Macros: */
#define BT_SDP_DEBUG(l, s, ...) do { if (SDP_DEBUG_LEVEL >= l) printf_P(PSTR("(SDP) " s "\r\n"), ##__VA_ARGS__); } while (0)
#define SDP_DEBUG_LEVEL 2
#define SDP_DEBUG_LEVEL 1
#define SDP_PDU_ERRORRESPONSE 0x01
#define SDP_PDU_SERVICESEARCHREQUEST 0x02
......@@ -59,6 +59,8 @@
#define SDP_PDU_SERVICEATTRIBUTERESPONSE 0x05
#define SDP_PDU_SERVICESEARCHATTRIBUTEREQUEST 0x06
#define SDP_PDU_SERVICESEARCHATTRIBUTERESPONSE 0x07
#define pgm_read_ptr(x) (void*)pgm_read_word(x)
/* Enums: */
/** Data sizes for SDP Data Element headers, to indicate the size of the data contained in the element. When creating
......@@ -213,9 +215,15 @@
const uint8_t TotalAttributes, void** const BufferPos);
static uint16_t SDP_AddAttributeToResponse(const uint16_t AttributeID, const void* AttributeValue, void** ResponseBuffer);
static void* SDP_GetAttributeValue(const ServiceAttributeTable_t* AttributeTable, const uint16_t AttributeID);