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"
|
#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,21 +67,54 @@ 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;
|
||||||
|
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
|
const struct
|
||||||
{
|
{
|
||||||
uint8_t Header;
|
uint8_t Header;
|
||||||
|
@ -186,105 +139,15 @@ const struct
|
||||||
"Wireless Serial Port Service",
|
"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_SERVICERECORDHANDLE, .Data = &RFCOMM_Attribute_ServiceHandle },
|
||||||
{.AttributeID = SDP_ATTRIBUTE_ID_SERVICECLASSIDS, .Data = &RFCOMM_Attribute_ServiceClassIDs },
|
{.AttributeID = SDP_ATTRIBUTE_ID_SERVICECLASSIDS, .Data = &RFCOMM_Attribute_ServiceClassIDs },
|
||||||
{.AttributeID = SDP_ATTRIBUTE_ID_PROTOCOLDESCRIPTORLIST, .Data = &RFCOMM_Attribute_ProtocolDescriptor },
|
{.AttributeID = SDP_ATTRIBUTE_ID_PROTOCOLDESCRIPTORLIST, .Data = &RFCOMM_Attribute_ProtocolDescriptor },
|
||||||
{.AttributeID = SDP_ATTRIBUTE_ID_SERVICENAME, .Data = &RFCOMM_Attribute_ServiceName },
|
{.AttributeID = SDP_ATTRIBUTE_ID_BROWSEGROUPLIST, .Data = &RFCOMM_Attribute_BrowseGroupList },
|
||||||
{.AttributeID = SDP_ATTRIBUTE_ID_SERVICEDESCRIPTION, .Data = &RFCOMM_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
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------ 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 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 @@
|
||||||
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 @@
|
||||||
} 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 @@
|
||||||
#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
|
||||||
uint16_t CurrentServiceRecordCount;
|
uint16_t CurrentServiceRecordCount;
|
||||||
uint8_t ResponseData[100];
|
uint8_t ResponseData[100];
|
||||||
} ResponsePacket;
|
} 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;
|
uint8_t AddedServiceHandles = 0;
|
||||||
|
|
||||||
/* Search through the list of UUIDs one at a time looking for matching search Attributes */
|
/* Create a pointer to the buffer to indicate the current location for response data to be added */
|
||||||
for (uint8_t CurrUUIDItem = 0; CurrUUIDItem < TotalUUIDs; CurrUUIDItem++)
|
void* CurrResponsePos = ResponsePacket.ResponseData;
|
||||||
{
|
|
||||||
ServiceAttributeTable_t* AttributeTable;
|
|
||||||
|
|
||||||
/* Retrieve the attribute table of the current search UUID from the global UUID table if it exists */
|
/* Search through the global service list an item at a time */
|
||||||
if ((AttributeTable = SDP_GetAttributeTable(UUIDList[CurrUUIDItem])) == NULL)
|
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;
|
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,
|
||||||
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
|
||||||
/* 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*
|
||||||
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
|
||||||
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
|
||||||
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++)
|
|
||||||
{
|
|
||||||
/* 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);
|
|
||||||
|
|
||||||
/* If the current table item's UUID matches the search UUID, return a pointer the table item's Attribute table */
|
/* Set all the match flags to false (not matched) before starting the search */
|
||||||
if (!(memcmp_P(UUID, &SDP_Services_Table[CurrTableItem].UUID, UUID_SIZE_BYTES)))
|
memset(UUIDMatch, false, sizeof(UUIDMatch));
|
||||||
return CurrAttributeTable;
|
|
||||||
|
const void* CurrAttribute;
|
||||||
/* Retrieve the list of the service's Class UUIDs from its Attribute table */
|
|
||||||
void* ClassUUIDs = SDP_GetAttributeValue(CurrAttributeTable, SDP_ATTRIBUTE_ID_SERVICECLASSIDS);
|
/* Search through the current attribute table, checking each attribute value for UUID matches */
|
||||||
|
while ((CurrAttribute = pgm_read_ptr(&CurrAttributeTable->Data)) != NULL)
|
||||||
/* Go to the next UUID in the table if the current item does not have a list of Class UUIDs */
|
{
|
||||||
if (ClassUUIDs == NULL)
|
SDP_CheckUUIDMatch(UUIDList, TotalUUIDs, UUIDMatch, CurrAttribute);
|
||||||
continue;
|
CurrAttributeTable++;
|
||||||
|
}
|
||||||
/* Retrieve the size of the Class UUID list and skip past the header to the first Class UUID in the list */
|
|
||||||
uint8_t ClassUUIDListHeaderSize;
|
/* Determine how many UUID matches in the list we have found */
|
||||||
uint16_t ClassUUIDListSize = SDP_GetLocalAttributeContainerSize(ClassUUIDs, &ClassUUIDListHeaderSize);
|
uint8_t UUIDMatches = 0;
|
||||||
ClassUUIDs += ClassUUIDListHeaderSize;
|
for (uint8_t i = 0; i < TotalUUIDs; i++)
|
||||||
|
{
|
||||||
/* Check each class UUID in turn for a match */
|
if (UUIDMatch[i])
|
||||||
while (ClassUUIDListSize)
|
UUIDMatches++;
|
||||||
{
|
|
||||||
/* 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;
|
/* 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
|
/** 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)
|
switch (SizeIndex)
|
||||||
{
|
{
|
||||||
case SDP_DATASIZE_Variable8Bit:
|
case SDP_DATASIZE_Variable8Bit:
|
||||||
ElementValueSize = SDP_ReadData8(DataElementHeader);
|
|
||||||
*ElementHeaderSize = (1 + sizeof(uint8_t));
|
*ElementHeaderSize = (1 + sizeof(uint8_t));
|
||||||
|
ElementValueSize = SDP_ReadData8(DataElementHeader);
|
||||||
break;
|
break;
|
||||||
case SDP_DATASIZE_Variable16Bit:
|
case SDP_DATASIZE_Variable16Bit:
|
||||||
ElementValueSize = SDP_ReadData16(DataElementHeader);
|
|
||||||
*ElementHeaderSize = (1 + sizeof(uint16_t));
|
*ElementHeaderSize = (1 + sizeof(uint16_t));
|
||||||
|
ElementValueSize = SDP_ReadData16(DataElementHeader);
|
||||||
break;
|
break;
|
||||||
case SDP_DATASIZE_Variable32Bit:
|
case SDP_DATASIZE_Variable32Bit:
|
||||||
ElementValueSize = SDP_ReadData32(DataElementHeader);
|
|
||||||
*ElementHeaderSize = (1 + sizeof(uint32_t));
|
*ElementHeaderSize = (1 + sizeof(uint32_t));
|
||||||
|
ElementValueSize = SDP_ReadData32(DataElementHeader);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ElementValueSize = (1 << SizeIndex);
|
|
||||||
*ElementHeaderSize = 1;
|
*ElementHeaderSize = 1;
|
||||||
|
ElementValueSize = (1 << SizeIndex);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,7 @@
|
||||||
|
|
||||||
/* Macros: */
|
/* 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 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_ERRORRESPONSE 0x01
|
||||||
#define SDP_PDU_SERVICESEARCHREQUEST 0x02
|
#define SDP_PDU_SERVICESEARCHREQUEST 0x02
|
||||||
|
@ -59,6 +59,8 @@
|
||||||
#define SDP_PDU_SERVICEATTRIBUTERESPONSE 0x05
|
#define SDP_PDU_SERVICEATTRIBUTERESPONSE 0x05
|
||||||
#define SDP_PDU_SERVICESEARCHATTRIBUTEREQUEST 0x06
|
#define SDP_PDU_SERVICESEARCHATTRIBUTEREQUEST 0x06
|
||||||
#define SDP_PDU_SERVICESEARCHATTRIBUTERESPONSE 0x07
|
#define SDP_PDU_SERVICESEARCHATTRIBUTERESPONSE 0x07
|
||||||
|
|
||||||
|
#define pgm_read_ptr(x) (void*)pgm_read_word(x)
|
||||||
|
|
||||||
/* Enums: */
|
/* Enums: */
|
||||||
/** Data sizes for SDP Data Element headers, to indicate the size of the data contained in the element. When creating
|
/** 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);
|
const uint8_t TotalAttributes, void** const BufferPos);
|
||||||
static uint16_t SDP_AddAttributeToResponse(const uint16_t AttributeID, const void* AttributeValue, void** ResponseBuffer);
|
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 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_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 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_GetLocalAttributeContainerSize(const void* const AttributeData, uint8_t* const HeaderSize);
|
||||||
static uint32_t SDP_GetDataElementSize(const void** const AttributeHeader, uint8_t* const ElementHeaderSize);
|
static uint32_t SDP_GetDataElementSize(const void** const AttributeHeader, uint8_t* const ElementHeaderSize);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -111,7 +111,7 @@
|
||||||
"Assertion \"%s\" failed.\r\n"), \
|
"Assertion \"%s\" failed.\r\n"), \
|
||||||
__FILE__, __func__, __LINE__, #x); } \
|
__FILE__, __func__, __LINE__, #x); } \
|
||||||
}MACROE
|
}MACROE
|
||||||
|
|
||||||
/* Inline Functions: */
|
/* 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,
|
/** Function to reverse the individual bits in a byte - i.e. bit 7 is moved to bit 0, bit 6 to bit 1,
|
||||||
* etc.
|
* etc.
|
||||||
|
|
Loading…
Reference in New Issue