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 @@ ...@@ -30,86 +30,6 @@
#include "SDPServices.h" #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 const struct
{ {
uint8_t Header; uint8_t Header;
...@@ -147,123 +67,64 @@ const struct ...@@ -147,123 +67,64 @@ const struct
{ {
{ {
(SDP_DATATYPE_Sequence | SDP_DATASIZE_Variable8Bit), (SDP_DATATYPE_Sequence | SDP_DATASIZE_Variable8Bit),
sizeof(UUID_t), sizeof(ItemUUID_t),
{ {
{(SDP_DATATYPE_UUID | SDP_DATASIZE_128Bit), L2CAP_UUID}, {(SDP_DATATYPE_UUID | SDP_DATASIZE_128Bit), L2CAP_UUID},
} }
}, },
{ {
(SDP_DATATYPE_Sequence | SDP_DATASIZE_Variable8Bit), (SDP_DATATYPE_Sequence | SDP_DATASIZE_Variable8Bit),
sizeof(UUID_t), sizeof(ItemUUID_t),
{ {
{(SDP_DATATYPE_UUID | SDP_DATASIZE_128Bit), RFCOMM_UUID}, {(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 const struct
{ {
uint8_t Header; uint8_t Header;
uint16_t Size; uint16_t Size;
ItemUUID_t UUIDList[]; ItemUUID_t UUIDList[];
} PROGMEM L2CAP_Attribute_ServiceClassIDs = } PROGMEM RFCOMM_Attribute_BrowseGroupList =
{ {
(SDP_DATATYPE_Sequence | SDP_DATASIZE_Variable16Bit), (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), PUBLICBROWSEGROUP_CLASS_UUID}
{(SDP_DATATYPE_UUID | SDP_DATASIZE_128Bit), SP_CLASS_UUID },
} }
}; };
const struct const struct
{ {
uint8_t Header; uint8_t Header;
uint16_t Size; uint8_t Size;
ItemLangID_t OffsetList[];
ItemProtocol_t ProtocolList[]; } PROGMEM RFCOMM_Attribute_LanguageBaseIDOffset =
} PROGMEM L2CAP_Attribute_ProtocolDescriptor = {
{ .Header = (SDP_DATATYPE_Sequence | SDP_DATASIZE_Variable8Bit),
(SDP_DATATYPE_Sequence | SDP_DATASIZE_Variable16Bit), .Size = (sizeof(ItemLangID_t) * 1),
SWAPENDIAN_16(sizeof(ItemProtocol_t) * 2), .OffsetList =
{
{ {
(SDP_DATATYPE_Sequence | SDP_DATASIZE_Variable8Bit),
sizeof(UUID_t),
{ {
{(SDP_DATATYPE_UUID | SDP_DATASIZE_128Bit), L2CAP_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)},
{
(SDP_DATATYPE_Sequence | SDP_DATASIZE_Variable8Bit),
sizeof(UUID_t),
{
{(SDP_DATATYPE_UUID | SDP_DATASIZE_128Bit), RFCOMM_UUID},
} }
} }
} };
};
const struct const struct
{ {
uint8_t Header; uint8_t Header;
uint8_t Size; uint8_t Size;
char Text[]; char Text[];
} PROGMEM L2CAP_Attribute_ServiceName = } PROGMEM RFCOMM_Attribute_ServiceName =
{ {
(SDP_DATATYPE_String | SDP_DATASIZE_Variable8Bit), (SDP_DATATYPE_String | SDP_DATASIZE_Variable8Bit),
sizeof("L2CAP") - 1, sizeof("Serial Port") - 1,
"L2CAP", "Serial Port",
}; };
const struct const struct
...@@ -271,20 +132,22 @@ const struct ...@@ -271,20 +132,22 @@ const struct
uint8_t Header; uint8_t Header;
uint8_t Size; uint8_t Size;
char Text[]; char Text[];
} PROGMEM L2CAP_Attribute_ServiceDescription = } PROGMEM RFCOMM_Attribute_ServiceDescription =
{ {
(SDP_DATATYPE_String | SDP_DATASIZE_Variable8Bit), (SDP_DATATYPE_String | SDP_DATASIZE_Variable8Bit),
sizeof("Logical Link Layer") - 1, sizeof("Wireless Serial Port Service") - 1,
"Logical Link Layer", "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_SERVICERECORDHANDLE, .Data = &RFCOMM_Attribute_ServiceHandle },
{.AttributeID = SDP_ATTRIBUTE_ID_SERVICECLASSIDS, .Data = &L2CAP_Attribute_ServiceClassIDs }, {.AttributeID = SDP_ATTRIBUTE_ID_SERVICECLASSIDS, .Data = &RFCOMM_Attribute_ServiceClassIDs },
{.AttributeID = SDP_ATTRIBUTE_ID_PROTOCOLDESCRIPTORLIST, .Data = &L2CAP_Attribute_ProtocolDescriptor }, {.AttributeID = SDP_ATTRIBUTE_ID_PROTOCOLDESCRIPTORLIST, .Data = &RFCOMM_Attribute_ProtocolDescriptor },
{.AttributeID = SDP_ATTRIBUTE_ID_SERVICENAME, .Data = &L2CAP_Attribute_ServiceName }, {.AttributeID = SDP_ATTRIBUTE_ID_BROWSEGROUPLIST, .Data = &RFCOMM_Attribute_BrowseGroupList },
{.AttributeID = SDP_ATTRIBUTE_ID_SERVICEDESCRIPTION, .Data = &L2CAP_Attribute_ServiceDescription }, {.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 SERVICE_ATTRIBUTE_TABLE_TERMINATOR
}; };
...@@ -49,14 +49,15 @@ ...@@ -49,14 +49,15 @@
#define SDP_UUID {BASE_80BIT_UUID, {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}} #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 RFCOMM_UUID {BASE_80BIT_UUID, {0x00, 0x00, 0x00, 0x00, 0x00, 0x03}}
#define L2CAP_UUID {BASE_80BIT_UUID, {0x00, 0x00, 0x00, 0x00, 0x01, 0x00}} #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 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 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_SERVICERECORDHANDLE 0x0000
#define SDP_ATTRIBUTE_ID_SERVICECLASSIDS 0x0001 #define SDP_ATTRIBUTE_ID_SERVICECLASSIDS 0x0001
#define SDP_ATTRIBUTE_ID_PROTOCOLDESCRIPTORLIST 0x0004 #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_VERSION 0x0200
#define SDP_ATTRIBUTE_ID_SERVICENAME 0x0100 #define SDP_ATTRIBUTE_ID_SERVICENAME 0x0100
#define SDP_ATTRIBUTE_ID_SERVICEDESCRIPTION 0x0101 #define SDP_ATTRIBUTE_ID_SERVICEDESCRIPTION 0x0101
...@@ -87,15 +88,6 @@ ...@@ -87,15 +88,6 @@
const void* Data; /**< Pointer to the attribute data, located in PROGMEM memory space */ const void* Data; /**< Pointer to the attribute data, located in PROGMEM memory space */
} ServiceAttributeTable_t; } 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. */ /** Structure for a list of Data Elements containing 8-bit integers, for service attributes requiring such lists. */
typedef struct typedef struct
{ {
...@@ -138,9 +130,14 @@ ...@@ -138,9 +130,14 @@
} Protocol; } Protocol;
} ItemProtocol_t; } ItemProtocol_t;
typedef struct
{
Item16Bit_t LanguageID;
Item16Bit_t EncodingID;
Item16Bit_t OffsetID;
} ItemLangID_t;
/* External Variables: */ /* External Variables: */
extern const ServiceAttributeTable_t SDP_Attribute_Table[];
extern const ServiceAttributeTable_t RFCOMM_Attribute_Table[]; extern const ServiceAttributeTable_t RFCOMM_Attribute_Table[];
extern const ServiceAttributeTable_t L2CAP_Attribute_Table[];
#endif #endif
...@@ -31,14 +31,10 @@ ...@@ -31,14 +31,10 @@
#define INCLUDE_FROM_SERVICEDISCOVERYPROTOCOL_C #define INCLUDE_FROM_SERVICEDISCOVERYPROTOCOL_C
#include "ServiceDiscoveryProtocol.h" #include "ServiceDiscoveryProtocol.h"
/** Master service table, listing all supported services (and their attribute tables) of the device, including /** Service attribute table list, containing a pointer to each service attribute table the device contains */
* each service's UUID. const ServiceAttributeTable_t* SDP_Services_Table[] PROGMEM =
*/
const ServiceTable_t SDP_Services_Table[] PROGMEM =
{ {
{ .UUID = SDP_UUID , .AttributeTable = SDP_Attribute_Table }, RFCOMM_Attribute_Table,
{ .UUID = RFCOMM_UUID, .AttributeTable = RFCOMM_Attribute_Table },
{ .UUID = L2CAP_UUID , .AttributeTable = L2CAP_Attribute_Table },
}; };
/** Base UUID value common to all standardized Bluetooth services */ /** Base UUID value common to all standardized Bluetooth services */
...@@ -101,25 +97,25 @@ static void SDP_ProcessServiceSearch(const SDP_PDUHeader_t* const SDPHeader, Blu ...@@ -101,25 +97,25 @@ static void SDP_ProcessServiceSearch(const SDP_PDUHeader_t* const SDPHeader, Blu
uint16_t CurrentServiceRecordCount; uint16_t CurrentServiceRecordCount;
uint8_t ResponseData[100]; uint8_t ResponseData[100];
} ResponsePacket; } ResponsePacket;
uint8_t AddedServiceHandles = 0;
/* Create a pointer to the buffer to indicate the current location for response data to be added */ /* Create a pointer to the buffer to indicate the current location for response data to be added */
void* CurrResponsePos = ResponsePacket.ResponseData; void* CurrResponsePos = ResponsePacket.ResponseData;
uint8_t AddedServiceHandles = 0;
/* Search through the list of UUIDs one at a time looking for matching search Attributes */ /* Search through the global service list an item at a time */
for (uint8_t CurrUUIDItem = 0; CurrUUIDItem < TotalUUIDs; CurrUUIDItem++) 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 (!(SDP_SearchServiceTable(UUIDList, TotalUUIDs, CurrAttributeTable)))
if ((AttributeTable = SDP_GetAttributeTable(UUIDList[CurrUUIDItem])) == NULL)
continue; 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 */ /* 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 */ /* Copy over the service record handle to the response list */
uint8_t AttrHeaderSize; uint8_t AttrHeaderSize;
...@@ -197,10 +193,10 @@ static void SDP_ProcessServiceAttribute(const SDP_PDUHeader_t* const SDPHeader, ...@@ -197,10 +193,10 @@ static void SDP_ProcessServiceAttribute(const SDP_PDUHeader_t* const SDPHeader,
uint16_t TotalResponseSize = 0; uint16_t TotalResponseSize = 0;
/* Search through the global UUID list an item at a time */ /* 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 */ /* 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 */ /* Retrieve a PROGMEM pointer to the value of the Service Record Handle */
const void* ServiceRecord = SDP_GetAttributeValue(CurrAttributeTable, SDP_ATTRIBUTE_ID_SERVICERECORDHANDLE); const void* ServiceRecord = SDP_GetAttributeValue(CurrAttributeTable, SDP_ATTRIBUTE_ID_SERVICERECORDHANDLE);
...@@ -288,19 +284,19 @@ static void SDP_ProcessServiceSearchAttribute(const SDP_PDUHeader_t* const SDPHe ...@@ -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 */ /* Add the outer Data Element Sequence header for all of the retrieved Attributes */
uint16_t* TotalResponseSize = SDP_AddSequence16(&CurrResponsePos); uint16_t* TotalResponseSize = SDP_AddSequence16(&CurrResponsePos);
/* Search through the list of UUIDs one at a time looking for matching search Attributes */ /* Search through the global service list an item at a time */
for (uint8_t CurrUUIDItem = 0; CurrUUIDItem < TotalUUIDs; CurrUUIDItem++) 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 (!(SDP_SearchServiceTable(UUIDList, TotalUUIDs, CurrAttributeTable)))
if ((AttributeTable = SDP_GetAttributeTable(UUIDList[CurrUUIDItem])) == NULL)
continue; 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 */ /* Add the listed attributes for the found UUID to the response */
*TotalResponseSize += SDP_AddListedAttributesToResponse(AttributeTable, AttributeList, TotalAttributes, *TotalResponseSize += SDP_AddListedAttributesToResponse(CurrAttributeTable, AttributeList, TotalAttributes,
&CurrResponsePos); &CurrResponsePos);
} }
...@@ -355,7 +351,7 @@ static uint16_t SDP_AddListedAttributesToResponse(const ServiceAttributeTable_t* ...@@ -355,7 +351,7 @@ static uint16_t SDP_AddListedAttributesToResponse(const ServiceAttributeTable_t*
void* AttributeValue; void* AttributeValue;
/* Look through the current service's attribute list, examining all the attributes */ /* 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 */ /* Get the current Attribute's ID from the current attribute table entry */
uint16_t CurrAttributeID = pgm_read_word(&AttributeTable->AttributeID); uint16_t CurrAttributeID = pgm_read_word(&AttributeTable->AttributeID);
...@@ -421,7 +417,7 @@ static void* SDP_GetAttributeValue(const ServiceAttributeTable_t* AttributeTable ...@@ -421,7 +417,7 @@ static void* SDP_GetAttributeValue(const ServiceAttributeTable_t* AttributeTable
void* CurrTableItemData; void* CurrTableItemData;
/* Search through the current Attribute table, abort when the terminator item has been reached */ /* 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 */ /* Check if the current Attribute ID matches the search ID - if so return a pointer to it */
if (pgm_read_word(&AttributeTable->AttributeID) == AttributeID) if (pgm_read_word(&AttributeTable->AttributeID) == AttributeID)
...@@ -433,49 +429,91 @@ static void* SDP_GetAttributeValue(const ServiceAttributeTable_t* AttributeTable ...@@ -433,49 +429,91 @@ static void* SDP_GetAttributeValue(const ServiceAttributeTable_t* AttributeTable
return NULL; 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 */ bool UUIDMatch[TotalUUIDs];
for (uint8_t CurrTableItem = 0; CurrTableItem < (sizeof(SDP_Services_Table) / sizeof(ServiceTable_t)); CurrTableItem++)
/* 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 */ SDP_CheckUUIDMatch(UUIDList, TotalUUIDs, UUIDMatch, CurrAttribute);
ServiceAttributeTable_t* CurrAttributeTable = (ServiceAttributeTable_t*)pgm_read_word(&SDP_Services_Table[CurrTableItem].AttributeTable); 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 all UUIDs have been matched to the current service, return true */
if (!(memcmp_P(UUID, &SDP_Services_Table[CurrTableItem].UUID, UUID_SIZE_BYTES))) return (UUIDMatches == TotalUUIDs);
return CurrAttributeTable; }
/* Retrieve the list of the service's Class UUIDs from its Attribute table */ /** Recursively upwraps the given locally stored attribute (in PROGMEM space), searching for UUIDs to match against
void* ClassUUIDs = SDP_GetAttributeValue(CurrAttributeTable, SDP_ATTRIBUTE_ID_SERVICECLASSIDS); * 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);