Add Mecurial repository mirror link to the library documentation.
[pub/USBasp.git] / Demos / Host / Incomplete / BluetoothHost / Lib / ServiceDiscoveryProtocol.c
index 589d0e1..5223d29 100644 (file)
   this software.
 */
 
+/** \file
+ *
+ *  SDP layer module. This module implements a simple Service Discovery
+ *  Protocol server, which can broadcast the device's supported services
+ *  to other Bluetooth devices upon request, so that they can determine
+ *  what services are available.
+ */
+
+/*
+       TODO: Honor remote device's buffer size constraints via continuation state
+ */
+
 #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 =
        {
-               {   // 128-bit UUID for the SDP service
-                       .UUID  = {BASE_80BIT_UUID, {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}},
-                       .AttributeTable = SDP_Attribute_Table,
-               },
-               {   // 128-bit UUID for the RFCOMM service
-                       .UUID  = {BASE_80BIT_UUID, {0x00, 0x00, 0x00, 0x00, 0x00, 0x03}},
-                       .AttributeTable = RFCOMM_Attribute_Table,
-               },
+               SerialPort_Attribute_Table,
        };
 
 /** Base UUID value common to all standardized Bluetooth services */
-const UUID_t BaseUUID PROGMEM = {BASE_80BIT_UUID, {0, 0, 0, 0, 0, 0}};
+const UUID_t BaseUUID PROGMEM = {0x00000000, BASE_80BIT_UUID};
+
+/** Initializes the SDP service, ready for new connections from a SDP client. */
+void SDP_Initialize(void)
+{
+       /* Not currently used */
+}
 
 /** Main Service Discovery Protocol packet processing routine. This function processes incomming SDP packets from
  *  a connected Bluetooth device, and sends back appropriate responses to allow other devices to determine the
@@ -65,6 +74,7 @@ void SDP_ProcessPacket(void* Data, Bluetooth_Channel_t* const Channel)
        BT_SDP_DEBUG(2, "-- PDU ID: 0x%02X", SDPHeader->PDU);
        BT_SDP_DEBUG(2, "-- Param Length: 0x%04X", SDPHeader->ParameterLength);
 
+       /* Dispatch to the correct processing routine for the given SDP packet type */
        switch (SDPHeader->PDU)
        {
                case SDP_PDU_SERVICESEARCHREQUEST:
@@ -106,33 +116,32 @@ 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;
-               SDP_GetLocalAttributeContainerSize(AttributeValue, &AttrHeaderSize);
-               memcpy_P(CurrResponsePos, AttributeValue + AttrHeaderSize, sizeof(uint32_t));
-               CurrResponsePos += AttrHeaderSize + sizeof(uint32_t);
+               uint8_t AttrSize = SDP_GetLocalAttributeContainerSize(AttributeValue, &AttrHeaderSize);
+               memcpy_P(CurrResponsePos, AttributeValue + AttrHeaderSize, AttrSize);
+               CurrResponsePos += AttrHeaderSize + AttrSize;
                
-               /* Increment the total number of service records added to the list */
                AddedServiceHandles++;
        }
 
@@ -181,7 +190,7 @@ static void SDP_ProcessServiceAttribute(const SDP_PDUHeader_t* const SDPHeader,
        BT_SDP_DEBUG(2, "-- Max Return Attribute Bytes: 0x%04X", MaxAttributeSize);
        
        /* Retrieve the list of Attributes from the request */
-       uint16_t AttributeList[15][2];
+       uint16_t AttributeList[8][2];
        uint8_t  TotalAttributes = SDP_GetAttributeList(AttributeList, &CurrentParameter);
        BT_SDP_DEBUG(2, "-- Total Attributes: %d", TotalAttributes);
 
@@ -199,14 +208,13 @@ static void SDP_ProcessServiceAttribute(const SDP_PDUHeader_t* const SDPHeader,
        if (MaxAttributeSize > sizeof(ResponsePacket.ResponseData))
          MaxAttributeSize = sizeof(ResponsePacket.ResponseData);
 
-       /* Add the outer Data Element Sequence header for all of the retrieved Attributes */
-       uint16_t* TotalResponseSize = SDP_AddDataElementHeader16(&CurrResponsePos, SDP_DATATYPE_Sequence);
+       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);
@@ -222,8 +230,8 @@ static void SDP_ProcessServiceAttribute(const SDP_PDUHeader_t* const SDPHeader,
                if (ServiceHandle == CurrServiceHandle)
                {
                        /* Add the listed attributes for the found UUID to the response */
-                       *TotalResponseSize += SDP_AddListedAttributesToResponse(CurrAttributeTable, AttributeList, TotalAttributes,
-                                                                           &CurrResponsePos);
+                       TotalResponseSize = SDP_AddListedAttributesToResponse(CurrAttributeTable, AttributeList, TotalAttributes,
+                                                                         &CurrResponsePos);
                        
                        /* Requested service found, abort the search through the service table */
                        break;
@@ -234,22 +242,17 @@ static void SDP_ProcessServiceAttribute(const SDP_PDUHeader_t* const SDPHeader,
        SDP_WriteData8(&CurrResponsePos, 0);
 
        /* Set the total response list size to the size of the outer container plus its header size and continuation state */
-       ResponsePacket.AttributeListByteCount    = SwapEndian_16(3 + *TotalResponseSize);
+       ResponsePacket.AttributeListByteCount    = SwapEndian_16(TotalResponseSize);
 
        /* Calculate the total parameter length that is to be sent, including the fixed return parameters, the created attribute
           value list and the SDP continuation state */
-       uint16_t ParamLength = (sizeof(ResponsePacket.AttributeListByteCount) + 
-                               (3 + *TotalResponseSize) +
-                               sizeof(uint8_t));
-
+       uint16_t ParamLength = (sizeof(ResponsePacket.AttributeListByteCount) + TotalResponseSize + sizeof(uint8_t));
+       
        /* Fill in the response packet's header */
        ResponsePacket.SDPHeader.PDU             = SDP_PDU_SERVICEATTRIBUTERESPONSE;
        ResponsePacket.SDPHeader.TransactionID   = SDPHeader->TransactionID;
        ResponsePacket.SDPHeader.ParameterLength = SwapEndian_16(ParamLength);
 
-       /* Flip the endianness of the container's size */
-       *TotalResponseSize = SwapEndian_16(*TotalResponseSize);
-
        BT_SDP_DEBUG(1, ">> Service Attribute Response");
        BT_SDP_DEBUG(2, "-- Param Len 0x%04X", ParamLength);
 
@@ -278,7 +281,7 @@ static void SDP_ProcessServiceSearchAttribute(const SDP_PDUHeader_t* const SDPHe
        BT_SDP_DEBUG(2, "-- Max Return Attribute Bytes: 0x%04X", MaxAttributeSize);
        
        /* Retrieve the list of Attributes from the request */
-       uint16_t AttributeList[15][2];
+       uint16_t AttributeList[8][2];
        uint8_t  TotalAttributes = SDP_GetAttributeList(AttributeList, &CurrentParameter);
        BT_SDP_DEBUG(2, "-- Total Attributes: %d", TotalAttributes);
        
@@ -297,21 +300,21 @@ static void SDP_ProcessServiceSearchAttribute(const SDP_PDUHeader_t* const SDPHe
          MaxAttributeSize = sizeof(ResponsePacket.ResponseData);
 
        /* Add the outer Data Element Sequence header for all of the retrieved Attributes */
-       uint16_t* TotalResponseSize = SDP_AddDataElementHeader16(&CurrResponsePos, SDP_DATATYPE_Sequence);
+       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);
        }
        
@@ -327,14 +330,14 @@ static void SDP_ProcessServiceSearchAttribute(const SDP_PDUHeader_t* const SDPHe
                                (3 + *TotalResponseSize) +
                                sizeof(uint8_t));
 
+       /* Flip the endianness of the container's size */
+       *TotalResponseSize = SwapEndian_16(*TotalResponseSize);
+
        /* Fill in the response packet's header */
        ResponsePacket.SDPHeader.PDU             = SDP_PDU_SERVICESEARCHATTRIBUTERESPONSE;
        ResponsePacket.SDPHeader.TransactionID   = SDPHeader->TransactionID;
        ResponsePacket.SDPHeader.ParameterLength = SwapEndian_16(ParamLength);
 
-       /* Flip the endianness of the container's size */
-       *TotalResponseSize = SwapEndian_16(*TotalResponseSize);
-
        BT_SDP_DEBUG(1, ">> Service Search Attribute Response");
        BT_SDP_DEBUG(2, "-- Param Len 0x%04X", ParamLength);
 
@@ -354,10 +357,10 @@ static void SDP_ProcessServiceSearchAttribute(const SDP_PDUHeader_t* const SDPHe
 static uint16_t SDP_AddListedAttributesToResponse(const ServiceAttributeTable_t* AttributeTable, uint16_t AttributeList[][2],
                                                   const uint8_t TotalAttributes, void** const BufferPos)
 {
-       uint16_t TotalResponseSize = 0;
+       uint16_t TotalResponseSize;
 
        /* Add an inner Data Element Sequence header for the current services's found Attributes */
-       uint16_t* AttributeListSize = SDP_AddDataElementHeader16(BufferPos, SDP_DATATYPE_Sequence);
+       uint16_t* AttributeListSize = SDP_AddSequence16(BufferPos);
 
        /* Search through the list of Attributes one at a time looking for values in the current UUID's Attribute table */
        for (uint8_t CurrAttribute = 0; CurrAttribute < TotalAttributes; CurrAttribute++)
@@ -366,7 +369,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);
@@ -374,19 +377,17 @@ static uint16_t SDP_AddListedAttributesToResponse(const ServiceAttributeTable_t*
                        /* Check if the current Attribute's ID is within the current Attribute range */
                        if ((CurrAttributeID >= AttributeIDRange[0]) && (CurrAttributeID <= AttributeIDRange[1]))
                        {
-                               BT_SDP_DEBUG(2, " -- Add Attribute 0x%04X", CurrAttributeID);
-
                                /* Increment the current UUID's returned Attribute container size by the number of added bytes */
                                *AttributeListSize += SDP_AddAttributeToResponse(CurrAttributeID, AttributeValue, BufferPos);                   
                        }
                        
                        AttributeTable++;
                }
-
-               /* Increment the outer container size by the number of added bytes */
-               TotalResponseSize += 3 + *AttributeListSize;
        }
 
+       /* Record the total number of added bytes to the buffer */
+       TotalResponseSize = 3 + *AttributeListSize;
+
        /* Fix endianness of the added attribute data element sequence */
        *AttributeListSize = SwapEndian_16(*AttributeListSize);
 
@@ -405,8 +406,10 @@ static uint16_t SDP_AddAttributeToResponse(const uint16_t AttributeID, const voi
 {
        /* Retrieve the size of the attribute value from its container header */
        uint8_t  AttributeHeaderLength;
-       uint32_t AttributeValueLength = SDP_GetLocalAttributeContainerSize(AttributeValue, &AttributeHeaderLength);
+       uint16_t AttributeValueLength = SDP_GetLocalAttributeContainerSize(AttributeValue, &AttributeHeaderLength);
        
+       BT_SDP_DEBUG(2, " -- Add Attribute (0x%04X) 0x%04X", (AttributeHeaderLength + AttributeValueLength), AttributeID);
+
        /* Add a Data Element header to the response for the Attribute ID */
        SDP_WriteData8(ResponseBuffer, (SDP_DATATYPE_UnsignedInt | SDP_DATASIZE_16Bit));
        
@@ -432,7 +435,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)
@@ -444,49 +447,92 @@ 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;
+       /* 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++)
+               {
+                       /* Check if the current unmatched UUID is identical to the search UUID */
+                       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);
                
-               /* Retrieve the list of the service's Class UUIDs from its Attribute table */
-               void* ClassUUIDs = SDP_GetAttributeValue(CurrAttributeTable, SDP_ATTRIBUTE_ID_SERVICECLASSIDS);
+               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;
-               uint32_t ClassUUIDListSize = SDP_GetLocalAttributeContainerSize(ClassUUIDs, &ClassUUIDListHeaderSize);
-               ClassUUIDs += ClassUUIDListHeaderSize;
-               
-               /* 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 
@@ -553,19 +599,28 @@ static uint8_t SDP_GetUUIDList(uint8_t UUIDList[][UUID_SIZE_BYTES], const void**
                uint8_t* CurrentUUID = UUIDList[TotalUUIDs++];
                uint8_t  UUIDLength  = SDP_GetDataElementSize(CurrentParameter, &ElementHeaderSize);
                
-               /* Copy over the base UUID value to the free UUID slot in the list */
-               memcpy_P(CurrentUUID, &BaseUUID, sizeof(BaseUUID));
-
                /* Copy over UUID from the container to the free slot */
-               memcpy(&CurrentUUID[UUID_SIZE_BYTES - UUIDLength], *CurrentParameter, UUIDLength);
+               if (UUIDLength <= 4)
+               {
+                       /* Copy over the base UUID value to the free UUID slot in the list */
+                       memcpy_P(CurrentUUID, &BaseUUID, sizeof(BaseUUID));
+
+                       /* Copy over short UUID */
+                       memcpy(CurrentUUID + (4 - UUIDLength), *CurrentParameter, UUIDLength);
+               }
+               else
+               {
+                       /* Copy over full UUID */
+                       memcpy(CurrentUUID, *CurrentParameter, UUIDLength);             
+               }
                
                BT_SDP_DEBUG(2, "-- UUID (%d): %02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
                                UUIDLength,
                                CurrentUUID[0], CurrentUUID[1], CurrentUUID[2], CurrentUUID[3],
                                CurrentUUID[4], CurrentUUID[5],
-                                               CurrentUUID[6],  CurrentUUID[7],
-                               CurrentUUID[8],  CurrentUUID[9],
-                                               CurrentUUID[10],  CurrentUUID[11], CurrentUUID[12],  CurrentUUID[13],  CurrentUUID[14],  CurrentUUID[15]);
+                                               CurrentUUID[6], CurrentUUID[7],
+                               CurrentUUID[8], CurrentUUID[9],
+                                               CurrentUUID[10], CurrentUUID[11], CurrentUUID[12],  CurrentUUID[13],  CurrentUUID[14],  CurrentUUID[15]);
 
                ServicePatternLength -= (UUIDLength + ElementHeaderSize);
                *CurrentParameter    += UUIDLength;
@@ -631,20 +686,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;
        }