/** Recursively unwraps 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] UUIDMatchFlags 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, uint16_t* const UUIDMatchFlags, 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) { uint16_t CurrUUIDMatchMask = (1 << 0); /* Look for matches in the UUID list against the current attribute UUID value */ for (uint8_t i = 0; i < TotalUUIDs; i++) { /* Check if the current unmatched UUID is identical to the search UUID */ if (!(*UUIDMatchFlags & CurrUUIDMatchMask) && !(memcmp_P(UUIDList[i], (CurrAttribute + 1), UUID_SIZE_BYTES))) { /* Indicate match found for the current attribute UUID and early-abort */ *UUIDMatchFlags |= CurrUUIDMatchMask; break; } CurrUUIDMatchMask <<= 1; } } 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); /* Recursively search of the next element in the sequence, trying to match UUIDs with the UUID list */ SDP_CheckUUIDMatch(UUIDList, TotalUUIDs, UUIDMatchFlags, CurrAttribute); /* Skip to the next element in the sequence */ SequenceSize -= InnerHeaderSize + InnerSize; CurrAttribute += InnerHeaderSize + InnerSize; } } }
/** Retrieves the Attribute table for the given UUID list if it exists. * * \param[in] ServiceEntry Pointer to the service entry whose attribute table is to be examined * \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 * * \return True if all the UUIDs given in the UUID list appear in the given attribute table, false otherwise */ static bool SDP_SearchServiceTable(const SDP_ServiceEntry_t* const ServiceEntry, uint8_t UUIDList[][UUID_SIZE_BYTES], const uint8_t TotalUUIDs) { uint16_t UUIDMatchFlags = 0; /* Search through the current attribute table, checking each attribute value for UUID matches */\ for (uint8_t i = 0; i < ServiceEntry->TotalTableAttributes; i++) { const void* CurrAttribute = pgm_read_ptr(&ServiceEntry->AttributeTable[i].Data); SDP_CheckUUIDMatch(UUIDList, TotalUUIDs, &UUIDMatchFlags, CurrAttribute); } /* Determine how many UUID matches in the list we have found */ uint8_t UUIDMatches; for (UUIDMatches = 0; UUIDMatchFlags; UUIDMatches++) UUIDMatchFlags &= (UUIDMatchFlags - 1); /* If all UUIDs have been matched to the current service, return true */ return (UUIDMatches == TotalUUIDs); }
/** Retrieves the Attribute table for the given UUID list if it exists. * * \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 True if all the UUIDs given in the UUID list appear in the given attribute table, false otherwise */ static bool SDP_SearchServiceTable(uint8_t UUIDList[][UUID_SIZE_BYTES], const uint8_t TotalUUIDs, const ServiceAttributeTable_t* CurrAttributeTable) { const void* CurrAttribute; uint16_t UUIDMatchFlags = 0; /* 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, &UUIDMatchFlags, CurrAttribute); CurrAttributeTable++; } /* Determine how many UUID matches in the list we have found */ uint8_t UUIDMatches; for (UUIDMatches = 0; UUIDMatchFlags; UUIDMatches++) UUIDMatchFlags &= (UUIDMatchFlags - 1); /* If all UUIDs have been matched to the current service, return true */ return (UUIDMatches == TotalUUIDs); }