diff options
author | Dean Camera <dean@fourwalledcubicle.com> | 2010-06-02 07:05:34 +0000 |
---|---|---|
committer | Dean Camera <dean@fourwalledcubicle.com> | 2010-06-02 07:05:34 +0000 |
commit | c362709a1e2b0252cffbf1633f7cce41fea4d769 (patch) | |
tree | cbe6188d1b4e00c42045d2318964cceebedee91a /Demos/Host | |
parent | da51c1f9749842b65608d6505a41b05981416443 (diff) | |
download | lufa-c362709a1e2b0252cffbf1633f7cce41fea4d769.tar.gz lufa-c362709a1e2b0252cffbf1633f7cce41fea4d769.tar.bz2 lufa-c362709a1e2b0252cffbf1633f7cce41fea4d769.zip |
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.
Diffstat (limited to 'Demos/Host')
4 files changed, 158 insertions, 252 deletions
diff --git a/Demos/Host/Incomplete/BluetoothHost/Lib/SDPServices.c b/Demos/Host/Incomplete/BluetoothHost/Lib/SDPServices.c index 96401c010..511e0b074 100644 --- a/Demos/Host/Incomplete/BluetoothHost/Lib/SDPServices.c +++ b/Demos/Host/Incomplete/BluetoothHost/Lib/SDPServices.c @@ -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
};
diff --git a/Demos/Host/Incomplete/BluetoothHost/Lib/SDPServices.h b/Demos/Host/Incomplete/BluetoothHost/Lib/SDPServices.h index a11850dcb..654ed94e0 100644 --- a/Demos/Host/Incomplete/BluetoothHost/Lib/SDPServices.h +++ b/Demos/Host/Incomplete/BluetoothHost/Lib/SDPServices.h @@ -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
diff --git a/Demos/Host/Incomplete/BluetoothHost/Lib/ServiceDiscoveryProtocol.c b/Demos/Host/Incomplete/BluetoothHost/Lib/ServiceDiscoveryProtocol.c index c6b394819..ffe2be0b7 100644 --- a/Demos/Host/Incomplete/BluetoothHost/Lib/ServiceDiscoveryProtocol.c +++ b/Demos/Host/Incomplete/BluetoothHost/Lib/ServiceDiscoveryProtocol.c @@ -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; } diff --git a/Demos/Host/Incomplete/BluetoothHost/Lib/ServiceDiscoveryProtocol.h b/Demos/Host/Incomplete/BluetoothHost/Lib/ServiceDiscoveryProtocol.h index ec55b2fb1..50f436642 100644 --- a/Demos/Host/Incomplete/BluetoothHost/Lib/ServiceDiscoveryProtocol.h +++ b/Demos/Host/Incomplete/BluetoothHost/Lib/ServiceDiscoveryProtocol.h @@ -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); - 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); + static void SDP_CheckUUIDMatch(uint8_t UUIDList[][UUID_SIZE_BYTES], const uint8_t TotalUUIDs, bool UUIDMatch[], + const void* CurrAttribute); + static uint8_t SDP_GetAttributeList(uint16_t AttributeList[][2], const void** const CurrentParameter); static uint8_t SDP_GetUUIDList(uint8_t UUIDList[][UUID_SIZE_BYTES], const void** const CurrentParameter); + static uint32_t SDP_GetLocalAttributeContainerSize(const void* const AttributeData, uint8_t* const HeaderSize); static uint32_t SDP_GetDataElementSize(const void** const AttributeHeader, uint8_t* const ElementHeaderSize); #endif |