forked from mfulz_github/qmk_firmware
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.
This commit is contained in:
parent
da51c1f974
commit
c362709a1e
|
@ -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,21 +67,54 @@ 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;
|
||||
uint16_t Size;
|
||||
ItemUUID_t UUIDList[];
|
||||
} PROGMEM RFCOMM_Attribute_BrowseGroupList =
|
||||
{
|
||||
(SDP_DATATYPE_Sequence | SDP_DATASIZE_Variable16Bit),
|
||||
SWAPENDIAN_16(sizeof(ItemUUID_t) * 1),
|
||||
{
|
||||
{(SDP_DATATYPE_UUID | SDP_DATASIZE_128Bit), PUBLICBROWSEGROUP_CLASS_UUID}
|
||||
}
|
||||
};
|
||||
|
||||
const struct
|
||||
{
|
||||
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_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;
|
||||
|
@ -186,105 +139,15 @@ const struct
|
|||
"Wireless Serial Port Service",
|
||||
};
|
||||
|
||||
const ServiceAttributeTable_t RFCOMM_Attribute_Table[] PROGMEM =
|
||||
const ServiceAttributeTable_t PROGMEM RFCOMM_Attribute_Table[] =
|
||||
{
|
||||
{.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 },
|
||||
{.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
|
||||
};
|
||||
|
||||
|
||||
/* ------------------------------ 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 =
|
||||
{
|
||||
(SDP_DATATYPE_Sequence | SDP_DATASIZE_Variable16Bit),
|
||||
SWAPENDIAN_16(sizeof(ItemUUID_t) * 2),
|
||||
{
|
||||
{(SDP_DATATYPE_UUID | SDP_DATASIZE_128Bit), SDP_CLASS_UUID },
|
||||
{(SDP_DATATYPE_UUID | SDP_DATASIZE_128Bit), SP_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),
|
||||
{
|
||||
{
|
||||
(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},
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const struct
|
||||
{
|
||||
uint8_t Header;
|
||||
uint8_t Size;
|
||||
char Text[];
|
||||
} PROGMEM L2CAP_Attribute_ServiceName =
|
||||
{
|
||||
(SDP_DATATYPE_String | SDP_DATASIZE_Variable8Bit),
|
||||
sizeof("L2CAP") - 1,
|
||||
"L2CAP",
|
||||
};
|
||||
|
||||
const struct
|
||||
{
|
||||
uint8_t Header;
|
||||
uint8_t Size;
|
||||
char Text[];
|
||||
} PROGMEM L2CAP_Attribute_ServiceDescription =
|
||||
{
|
||||
(SDP_DATATYPE_String | SDP_DATASIZE_Variable8Bit),
|
||||
sizeof("Logical Link Layer") - 1,
|
||||
"Logical Link Layer",
|
||||
};
|
||||
|
||||
const ServiceAttributeTable_t L2CAP_Attribute_Table[] PROGMEM =
|
||||
{
|
||||
{.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 },
|
||||
|
||||
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;
|
||||
|
||||
/* 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++)
|
||||
{
|
||||
ServiceAttributeTable_t* AttributeTable;
|
||||
/* Create a pointer to the buffer to indicate the current location for response data to be added */
|
||||
void* CurrResponsePos = ResponsePacket.ResponseData;
|
||||
|
||||
/* Retrieve the attribute table of the current search UUID from the global UUID table if it exists */
|
||||
if ((AttributeTable = SDP_GetAttributeTable(UUIDList[CurrUUIDItem])) == NULL)
|
||||
/* Search through the global service list an item at a time */
|
||||
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 = pgm_read_ptr(&SDP_Services_Table[CurrTableItem]);
|
||||
|
||||
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++)
|
||||
{
|
||||
/* 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);
|
||||
bool UUIDMatch[TotalUUIDs];
|
||||
|
||||
/* 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);
|
||||
|
||||
/* 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;
|
||||
|
||||
/* Check each class UUID in turn for a match */
|
||||
while (ClassUUIDListSize)
|
||||
{
|
||||
/* 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);
|
||||
}
|
||||
/* 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)
|
||||
{
|
||||
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++;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
/* 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);
|
||||
|
||||
CurrAttribute += SequenceHeaderSize;
|
||||
|
||||
/* Recursively unwrap the sequence container, and re-search its contents for UUIDs */
|
||||
while (SequenceSize)
|
||||
{
|
||||
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);
|
||||
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
|
||||
|
|
|
@ -111,7 +111,7 @@
|
|||
"Assertion \"%s\" failed.\r\n"), \
|
||||
__FILE__, __func__, __LINE__, #x); } \
|
||||
}MACROE
|
||||
|
||||
|
||||
/* Inline Functions: */
|
||||
/** Function to reverse the individual bits in a byte - i.e. bit 7 is moved to bit 0, bit 6 to bit 1,
|
||||
* etc.
|
||||
|
|
Loading…
Reference in New Issue