3 Copyright (C) Dean Camera, 2010.
5 dean [at] fourwalledcubicle [dot] com
6 www.fourwalledcubicle.com
10 Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
12 Permission to use, copy, modify, distribute, and sell this
13 software and its documentation for any purpose is hereby granted
14 without fee, provided that the above copyright notice appear in
15 all copies and that both that the copyright notice and this
16 permission notice and warranty disclaimer appear in supporting
17 documentation, and that the name of the author not be used in
18 advertising or publicity pertaining to distribution of the
19 software without specific, written prior permission.
21 The author disclaim all warranties with regard to this
22 software, including all implied warranties of merchantability
23 and fitness. In no event shall the author be liable for any
24 special, indirect or consequential damages or any damages
25 whatsoever resulting from loss of use, data or profits, whether
26 in an action of contract, negligence or other tortious action,
27 arising out of or in connection with the use or performance of
31 #define INCLUDE_FROM_SERVICEDISCOVERYPROTOCOL_C
32 #include "ServiceDiscoveryProtocol.h"
34 /** Service Discovery Protocol attribute, indicationg the service's name. */
35 SERVICE_ATTRIBUTE_TEXT(SDP_Attribute_Name
, "SDP");
36 /** Service Discovery Protocol attribute, indicationg the service's description. */
37 SERVICE_ATTRIBUTE_TEXT(SDP_Attribute_Description
, "BT Service Discovery");
38 /** Service Discovery Protocol attribute, indicationg the service's availability. */
39 SERVICE_ATTRIBUTE_LEN8(SDP_Attribute_Availability
, SDP_DATATYPE_UnsignedInt
, 1, {0xFF});
40 /** Service Discovery Protocol attribute table, listing all supported attributes of the service. */
41 const ServiceAttributeTable_t SDP_Attribute_Table
[] PROGMEM
=
43 {.AttributeID
= SDP_ATTRIBUTE_NAME
, .Data
= &SDP_Attribute_Name
},
44 {.AttributeID
= SDP_ATTRIBUTE_DESCRIPTION
, .Data
= &SDP_Attribute_Description
},
45 {.AttributeID
= SDP_ATTRIBUTE_AVAILABILITY
, .Data
= &SDP_Attribute_Availability
},
46 SERVICE_ATTRIBUTE_TABLE_TERMINATOR
49 /** RFCOMM Service attribute, indicationg the service's name. */
50 SERVICE_ATTRIBUTE_TEXT(RFCOMM_Attribute_Name
, "RFCOMM");
51 /** RFCOMM Service attribute, indicationg the service's description. */
52 SERVICE_ATTRIBUTE_TEXT(RFCOMM_Attribute_Description
, "Virtual Serial");
53 /** RFCOMM Service attribute, indicationg the service's availability. */
54 SERVICE_ATTRIBUTE_LEN8(RFCOMM_Attribute_Availability
, SDP_DATATYPE_UnsignedInt
, 1, {0xFF});
55 /** RFCOMM Service attribute table, listing all supported attributes of the service. */
56 const ServiceAttributeTable_t RFCOMM_Attribute_Table
[] PROGMEM
=
58 {.AttributeID
= SDP_ATTRIBUTE_NAME
, .Data
= &RFCOMM_Attribute_Name
},
59 {.AttributeID
= SDP_ATTRIBUTE_DESCRIPTION
, .Data
= &RFCOMM_Attribute_Description
},
60 {.AttributeID
= SDP_ATTRIBUTE_AVAILABILITY
, .Data
= &RFCOMM_Attribute_Availability
},
61 SERVICE_ATTRIBUTE_TABLE_TERMINATOR
64 /** Master service table, listing all supported services (and their attribute tables) of the device, including
65 * each service's UUID.
67 const ServiceTable_t SDP_Services_Table
[] =
69 { // 128-bit UUID for the SDP service
70 .UUID
= {BASE_96BIT_UUID
, 0x01, 0x00, 0x00, 0x00},
71 .AttributeTable
= &SDP_Attribute_Table
,
73 { // 128-bit UUID for the RFCOMM service
74 .UUID
= {BASE_96BIT_UUID
, 0x03, 0x00, 0x00, 0x00},
75 .AttributeTable
= &RFCOMM_Attribute_Table
,
79 /** Base UUID value common to all standardized Bluetooth services */
80 const uint8_t BaseUUID
[] = {BASE_96BIT_UUID
, 0x00, 0x00, 0x00, 0x00};
83 /** Main Service Discovery Protocol packet processing routine. This function processes incomming SDP packets from
84 * a connected Bluetooth device, and sends back appropriate responses to allow other devices to determine the
85 * services the local device exposes.
87 * \param[in] Data Incomming packet data containing the SDP request
88 * \param[in] Channel Channel the request was issued to by the remote device
90 void ServiceDiscovery_ProcessPacket(void* Data
, Bluetooth_Channel_t
* Channel
)
92 SDP_PDUHeader_t
* SDPHeader
= (SDP_PDUHeader_t
*)Data
;
93 SDPHeader
->ParameterLength
= SwapEndian_16(SDPHeader
->ParameterLength
);
95 BT_SDP_DEBUG(1, "SDP Packet Received");
96 BT_SDP_DEBUG(2, "-- PDU ID: 0x%02X", SDPHeader
->PDU
);
97 BT_SDP_DEBUG(2, "-- Param Length: 0x%04X", SDPHeader
->ParameterLength
);
99 switch (SDPHeader
->PDU
)
101 case SDP_PDU_SERVICESEARCHREQUEST
:
102 ServiceDiscovery_ProcessServiceSearch(SDPHeader
, Channel
);
104 case SDP_PDU_SERVICEATTRIBUTEREQUEST
:
105 ServiceDiscovery_ProcessServiceAttribute(SDPHeader
, Channel
);
107 case SDP_PDU_SERVICESEARCHATTRIBUTEREQUEST
:
108 ServiceDiscovery_ProcessServiceSearchAttribute(SDPHeader
, Channel
);
113 static void ServiceDiscovery_ProcessServiceSearch(SDP_PDUHeader_t
* SDPHeader
, Bluetooth_Channel_t
* Channel
)
115 BT_SDP_DEBUG(1, "<< Service Search");
118 static void ServiceDiscovery_ProcessServiceAttribute(SDP_PDUHeader_t
* SDPHeader
, Bluetooth_Channel_t
* Channel
)
120 BT_SDP_DEBUG(1, "<< Service Attribute");
123 static void ServiceDiscovery_ProcessServiceSearchAttribute(SDP_PDUHeader_t
* SDPHeader
, Bluetooth_Channel_t
* Channel
)
125 const void* CurrentParameter
= ((void*)SDPHeader
+ sizeof(SDP_PDUHeader_t
));
127 BT_SDP_DEBUG(1, "<< Service Search Attribute");
129 uint8_t UUIDList
[12][UUID_SIZE_BYTES
];
130 uint8_t TotalUUIDs
= ServiceDiscovery_GetUUIDList(UUIDList
, &CurrentParameter
);
131 BT_SDP_DEBUG(2, "-- Total UUIDs: %d", TotalUUIDs
);
133 uint16_t MaxAttributeSize
= ServiceDiscovery_Read16BitParameter(&CurrentParameter
);
134 BT_SDP_DEBUG(2, "-- Max Return Attribute Bytes: 0x%04X", MaxAttributeSize
);
138 SDP_PDUHeader_t SDPHeader
;
139 uint16_t AttributeListByteCount
;
140 uint8_t ResponseData
[100];
143 if (MaxAttributeSize
> sizeof(ResponsePacket
.ResponseData
))
144 MaxAttributeSize
= sizeof(ResponsePacket
.ResponseData
);
146 ResponsePacket
.AttributeListByteCount
= ServiceDiscovery_ProcessAttributes(UUIDList
, TotalUUIDs
,
147 ResponsePacket
.ResponseData
,
148 MaxAttributeSize
, &CurrentParameter
);
149 ResponsePacket
.SDPHeader
.PDU
= SDP_PDU_SERVICESEARCHATTRIBUTERESPONSE
;
150 ResponsePacket
.SDPHeader
.TransactionID
= SDPHeader
->TransactionID
;
151 ResponsePacket
.SDPHeader
.ParameterLength
= (ResponsePacket
.AttributeListByteCount
+ sizeof(ResponsePacket
.AttributeListByteCount
));
153 Bluetooth_SendPacket(&ResponsePacket
, (sizeof(ResponsePacket
.SDPHeader
) + ResponsePacket
.SDPHeader
.ParameterLength
),
157 static uint8_t ServiceDiscovery_ProcessAttributes(uint8_t UUIDList
[][UUID_SIZE_BYTES
], const uint8_t TotalUUIDs
, uint8_t* ResponseBuffer
,
158 uint8_t MaxResponseSize
, const void** CurrentParameter
)
160 uint16_t* AttributeResponseSize
= ServiceDiscovery_AddDataElementHeader(&ResponseBuffer
, SDP_DATATYPE_UnsignedInt
);
161 uint8_t ElementHeaderSize
;
163 uint16_t AttributeIDListLength
= ServiceDiscovery_GetDataElementSize(CurrentParameter
, &ElementHeaderSize
);
164 BT_SDP_DEBUG(2, "-- Total Attribute Length: 0x%04X", AttributeIDListLength
);
165 while (AttributeIDListLength
)
167 uint8_t AttributeLength
= ServiceDiscovery_GetDataElementSize(CurrentParameter
, &ElementHeaderSize
);
168 uint32_t Attribute
= 0;
170 memcpy(&((char*)&Attribute
)[sizeof(uint32_t) - AttributeLength
], *CurrentParameter
, AttributeLength
);
172 BT_SDP_DEBUG(2, "-- Attribute(%d): 0x%08lX", AttributeLength
, Attribute
);
174 *AttributeResponseSize
+= ServiceDiscovery_GetAttribute(UUIDList
, TotalUUIDs
, Attribute
, &ResponseBuffer
,
175 (MaxResponseSize
- *AttributeResponseSize
));
177 AttributeIDListLength
-= (AttributeLength
+ ElementHeaderSize
);
178 *CurrentParameter
+= AttributeLength
;
181 return *AttributeResponseSize
;
184 static uint8_t ServiceDiscovery_GetAttribute(uint8_t UUIDList
[][UUID_SIZE_BYTES
], const uint8_t TotalUUIDs
, const uint32_t Attribute
,
185 uint8_t** DataBuffer
, uint8_t BufferLen
)
187 for (uint8_t CurrTableItem
= 0; CurrTableItem
< (sizeof(SDP_Services_Table
) / sizeof(ServiceTable_t
)); CurrTableItem
++)
189 for (uint8_t CurrUUIDIndex
= 0; CurrUUIDIndex
< TotalUUIDs
; CurrUUIDIndex
++)
191 if (!(memcmp(SDP_Services_Table
[CurrTableItem
].UUID
, UUIDList
[CurrUUIDIndex
], UUID_SIZE_BYTES
)))
193 const ServiceAttributeTable_t
* AttributeTable
= SDP_Services_Table
[CurrTableItem
].AttributeTable
;
195 // TODO: Process attribute table
196 BT_SDP_DEBUG(2, "FOUND UUID IN TABLE");
206 static uint8_t ServiceDiscovery_GetUUIDList(uint8_t UUIDList
[][UUID_SIZE_BYTES
], const void** CurrentParameter
)
208 uint8_t ElementHeaderSize
;
209 uint8_t TotalUUIDs
= 0;
211 uint16_t ServicePatternLength
= ServiceDiscovery_GetDataElementSize(CurrentParameter
, &ElementHeaderSize
);
212 BT_SDP_DEBUG(2, "-- Total UUID Length: 0x%04X", ServicePatternLength
);
213 while (ServicePatternLength
)
215 uint8_t* CurrentUUID
= UUIDList
[TotalUUIDs
++];
216 uint8_t UUIDLength
= ServiceDiscovery_GetDataElementSize(CurrentParameter
, &ElementHeaderSize
);
218 memcpy(CurrentUUID
, BaseUUID
, sizeof(BaseUUID
));
219 memcpy(&CurrentUUID
[(UUIDLength
<= 4) ?
(UUID_SIZE_BYTES
- 4) : 0], *CurrentParameter
, UUIDLength
);
221 BT_SDP_DEBUG(2, "-- UUID (%d): 0x%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
223 CurrentUUID
[15], CurrentUUID
[14], CurrentUUID
[13], CurrentUUID
[12],
224 CurrentUUID
[11], CurrentUUID
[10], CurrentUUID
[9], CurrentUUID
[8],
225 CurrentUUID
[7], CurrentUUID
[6], CurrentUUID
[5], CurrentUUID
[4],
226 CurrentUUID
[3], CurrentUUID
[2], CurrentUUID
[1], CurrentUUID
[0]);
228 ServicePatternLength
-= (UUIDLength
+ ElementHeaderSize
);
229 *CurrentParameter
+= UUIDLength
;
235 static uint32_t ServiceDiscovery_GetDataElementSize(const void** DataElementHeader
, uint8_t* ElementHeaderSize
)
237 /* Fetch the size of the Data Element structure from the header, increment the current buffer pos */
238 uint8_t SizeIndex
= (*((uint8_t*)*DataElementHeader
) & 0x07);
239 *DataElementHeader
+= sizeof(uint8_t);
241 uint32_t ElementValue
;
243 /* Convert the Data Element size index into a size in bytes */
247 ElementValue
= *((uint8_t*)*DataElementHeader
);
248 *DataElementHeader
+= sizeof(uint8_t);
249 *ElementHeaderSize
= (1 + sizeof(uint8_t));
252 ElementValue
= *((uint16_t*)*DataElementHeader
);
253 *DataElementHeader
+= sizeof(uint16_t);
254 *ElementHeaderSize
= (1 + sizeof(uint16_t));
257 ElementValue
= *((uint32_t*)*DataElementHeader
);
258 *DataElementHeader
+= sizeof(uint32_t);
259 *ElementHeaderSize
= (1 + sizeof(uint32_t));
262 ElementValue
= (1 << SizeIndex
);
263 *ElementHeaderSize
= 1;