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_ATTRIBUTE_TEXT(SDP_Attribute_Name
, "SDP");
35 SERVICE_ATTRIBUTE_TEXT(SDP_Attribute_Description
, "BT Service Discovery");
36 SERVICE_ATTRIBUTE_LEN8(SDP_Attribute_Availability
, SDP_DATATYPE_UNSIGNED_INT
, 1, {0xFF});
37 const ServiceAttributeTable_t SDP_Attribute_Table
[] PROGMEM
=
39 {.AttributeID
= SDP_ATTRIBUTE_NAME
, .Data
= &SDP_Attribute_Name
},
40 {.AttributeID
= SDP_ATTRIBUTE_DESCRIPTION
, .Data
= &SDP_Attribute_Description
},
41 {.AttributeID
= SDP_ATTRIBUTE_AVAILABILITY
, .Data
= &SDP_Attribute_Availability
},
42 SERVICE_ATTRIBUTE_TABLE_TERMINATOR
45 SERVICE_ATTRIBUTE_TEXT(RFCOMM_Attribute_Name
, "RFCOMM");
46 SERVICE_ATTRIBUTE_TEXT(RFCOMM_Attribute_Description
, "Virtual Serial");
47 SERVICE_ATTRIBUTE_LEN8(RFCOMM_Attribute_Availability
, SDP_DATATYPE_UNSIGNED_INT
, 1, {0xFF});
48 const ServiceAttributeTable_t RFCOMM_Attribute_Table
[] PROGMEM
=
50 {.AttributeID
= SDP_ATTRIBUTE_NAME
, .Data
= &RFCOMM_Attribute_Name
},
51 {.AttributeID
= SDP_ATTRIBUTE_DESCRIPTION
, .Data
= &RFCOMM_Attribute_Description
},
52 {.AttributeID
= SDP_ATTRIBUTE_AVAILABILITY
, .Data
= &RFCOMM_Attribute_Availability
},
53 SERVICE_ATTRIBUTE_TABLE_TERMINATOR
56 const ServiceTable_t SDP_Services_Table
[] =
58 { // 128-bit UUID for the SDP service
59 .UUID
= {BASE_96BIT_UUID
, 0x01, 0x00, 0x00, 0x00},
60 .AttributeTable
= &SDP_Attribute_Table
,
62 { // 128-bit UUID for the RFCOMM service
63 .UUID
= {BASE_96BIT_UUID
, 0x03, 0x00, 0x00, 0x00},
64 .AttributeTable
= &RFCOMM_Attribute_Table
,
68 const uint8_t BaseUUID
[] = {BASE_96BIT_UUID
, 0x00, 0x00, 0x00, 0x00};
71 void ServiceDiscovery_ProcessPacket(void* Data
, Bluetooth_Channel_t
* Channel
)
73 SDP_PDUHeader_t
* SDPHeader
= (SDP_PDUHeader_t
*)Data
;
74 SDPHeader
->ParameterLength
= SwapEndian_16(SDPHeader
->ParameterLength
);
76 BT_SDP_DEBUG(1, "SDP Packet Received");
77 BT_SDP_DEBUG(2, "-- PDU ID: 0x%02X", SDPHeader
->PDU
);
78 BT_SDP_DEBUG(2, "-- Param Length: 0x%04X", SDPHeader
->ParameterLength
);
80 switch (SDPHeader
->PDU
)
82 case SDP_PDU_SERVICESEARCHREQUEST
:
83 ServiceDiscovery_ProcessServiceSearch(SDPHeader
, Channel
);
85 case SDP_PDU_SERVICEATTRIBUTEREQUEST
:
86 ServiceDiscovery_ProcessServiceAttribute(SDPHeader
, Channel
);
88 case SDP_PDU_SERVICESEARCHATTRIBUTEREQUEST
:
89 ServiceDiscovery_ProcessServiceSearchAttribute(SDPHeader
, Channel
);
94 static void ServiceDiscovery_ProcessServiceSearch(SDP_PDUHeader_t
* SDPHeader
, Bluetooth_Channel_t
* Channel
)
96 BT_SDP_DEBUG(1, "<< Service Search");
99 static void ServiceDiscovery_ProcessServiceAttribute(SDP_PDUHeader_t
* SDPHeader
, Bluetooth_Channel_t
* Channel
)
101 BT_SDP_DEBUG(1, "<< Service Attribute");
104 static void ServiceDiscovery_ProcessServiceSearchAttribute(SDP_PDUHeader_t
* SDPHeader
, Bluetooth_Channel_t
* Channel
)
106 const void* CurrentParameter
= ((void*)SDPHeader
+ sizeof(SDP_PDUHeader_t
));
108 BT_SDP_DEBUG(1, "<< Service Search Attribute");
110 uint8_t UUIDList
[12][UUID_SIZE_BYTES
];
111 uint8_t TotalUUIDs
= ServiceDiscovery_GetUUIDList(UUIDList
, &CurrentParameter
);
112 BT_SDP_DEBUG(2, "-- Total UUIDs: %d", TotalUUIDs
);
114 uint16_t MaxAttributeSize
= ServiceDiscovery_Read16BitParameter(&CurrentParameter
);
115 BT_SDP_DEBUG(2, "-- Max Return Attribute Bytes: 0x%04X", MaxAttributeSize
);
119 SDP_PDUHeader_t SDPHeader
;
120 uint8_t ResponseData
[100];
123 ResponsePacket
.SDPHeader
.PDU
= SDP_PDU_SERVICESEARCHATTRIBUTERESPONSE
;
124 ResponsePacket
.SDPHeader
.TransactionID
= SDPHeader
->TransactionID
;
126 if (MaxAttributeSize
> sizeof(ResponsePacket
.ResponseData
))
127 MaxAttributeSize
= sizeof(ResponsePacket
.ResponseData
);
129 ResponsePacket
.SDPHeader
.ParameterLength
= ServiceDiscovery_ProcessAttributes(UUIDList
, TotalUUIDs
,
130 ResponsePacket
.ResponseData
,
131 MaxAttributeSize
, &CurrentParameter
);
133 Bluetooth_SendPacket(&ResponsePacket
, (sizeof(ResponsePacket
.SDPHeader
) + ResponsePacket
.SDPHeader
.ParameterLength
),
137 static uint8_t ServiceDiscovery_ProcessAttributes(uint8_t UUIDList
[][UUID_SIZE_BYTES
], const uint8_t TotalUUIDs
, uint8_t* ResponseBuffer
,
138 uint8_t MaxResponseSize
, const void** CurrentParameter
)
140 uint8_t ElementHeaderSize
;
141 uint8_t TotalResponseSize
= 0;
143 uint16_t AttributeIDListLength
= ServiceDiscovery_GetDataElementSize(CurrentParameter
, &ElementHeaderSize
);
144 BT_SDP_DEBUG(2, "-- Total Attribute Length: 0x%04X", AttributeIDListLength
);
145 while (AttributeIDListLength
)
147 uint8_t AttributeLength
= ServiceDiscovery_GetDataElementSize(CurrentParameter
, &ElementHeaderSize
);
148 uint32_t Attribute
= 0;
150 memcpy(&Attribute
, CurrentParameter
, AttributeLength
);
152 BT_SDP_DEBUG(2, "-- Attribute(%d): 0x%08lX", AttributeLength
, Attribute
);
154 uint8_t TotalBytesAdded
= ServiceDiscovery_GetAttribute(UUIDList
, TotalUUIDs
, Attribute
, &ResponseBuffer
,
156 TotalResponseSize
+= TotalBytesAdded
;
157 MaxResponseSize
-= TotalBytesAdded
;
159 AttributeIDListLength
-= (AttributeLength
+ ElementHeaderSize
);
160 CurrentParameter
+= AttributeLength
;
163 return TotalResponseSize
;
166 static uint8_t ServiceDiscovery_GetAttribute(uint8_t UUIDList
[][UUID_SIZE_BYTES
], const uint8_t TotalUUIDs
, const uint32_t Attribute
,
167 uint8_t** DataBuffer
, uint8_t BufferLen
)
169 for (uint8_t CurrTableItem
= 0; CurrTableItem
< (sizeof(SDP_Services_Table
) / sizeof(ServiceTable_t
)); CurrTableItem
++)
171 for (uint8_t CurrUUIDIndex
= 0; CurrUUIDIndex
< TotalUUIDs
; CurrUUIDIndex
++)
173 if (!(memcmp(SDP_Services_Table
[CurrTableItem
].UUID
, UUIDList
[CurrUUIDIndex
], UUID_SIZE_BYTES
)))
175 const ServiceAttributeTable_t
* AttributeTable
= SDP_Services_Table
[CurrTableItem
].AttributeTable
;
177 // Process attribute table
178 BT_SDP_DEBUG(2, "FOUND UUID IN TABLE");
188 static uint8_t ServiceDiscovery_GetUUIDList(uint8_t UUIDList
[][UUID_SIZE_BYTES
], const void** CurrentParameter
)
190 uint8_t ElementHeaderSize
;
191 uint8_t TotalUUIDs
= 0;
193 uint16_t ServicePatternLength
= ServiceDiscovery_GetDataElementSize(CurrentParameter
, &ElementHeaderSize
);
194 BT_SDP_DEBUG(2, "-- Total UUID Length: 0x%04X", ServicePatternLength
);
195 while (ServicePatternLength
)
197 uint8_t* CurrentUUID
= UUIDList
[TotalUUIDs
++];
198 uint8_t UUIDLength
= ServiceDiscovery_GetDataElementSize(CurrentParameter
, &ElementHeaderSize
);
200 memcpy(CurrentUUID
, BaseUUID
, sizeof(BaseUUID
));
201 memcpy(&CurrentUUID
[(UUIDLength
<= 32) ?
(sizeof(BaseUUID
) - 32) : 0], *CurrentParameter
, UUIDLength
);
203 BT_SDP_DEBUG(2, "-- UUID (%d): 0x%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
205 CurrentUUID
[15], CurrentUUID
[14], CurrentUUID
[13], CurrentUUID
[12],
206 CurrentUUID
[11], CurrentUUID
[10], CurrentUUID
[9], CurrentUUID
[8],
207 CurrentUUID
[7], CurrentUUID
[6], CurrentUUID
[5], CurrentUUID
[4],
208 CurrentUUID
[3], CurrentUUID
[2], CurrentUUID
[1], CurrentUUID
[0]);
210 ServicePatternLength
-= (UUIDLength
+ ElementHeaderSize
);
211 *CurrentParameter
+= UUIDLength
;
217 static uint32_t ServiceDiscovery_GetDataElementSize(const void** DataElementHeader
, uint8_t* ElementHeaderSize
)
219 /* Fetch the size of the Data Element structure from the header, increment the current buffer pos */
220 uint8_t SizeIndex
= (*((uint8_t*)*DataElementHeader
) & 0x07);
221 *DataElementHeader
+= sizeof(uint8_t);
223 uint32_t ElementValue
;
225 /* Convert the Data Element size index into a size in bytes */
229 ElementValue
= *((uint8_t*)*DataElementHeader
);
230 *DataElementHeader
+= sizeof(uint8_t);
231 *ElementHeaderSize
= (1 + sizeof(uint8_t));
234 ElementValue
= *((uint16_t*)*DataElementHeader
);
235 *DataElementHeader
+= sizeof(uint16_t);
236 *ElementHeaderSize
= (1 + sizeof(uint16_t));
239 ElementValue
= *((uint32_t*)*DataElementHeader
);
240 *DataElementHeader
+= sizeof(uint32_t);
241 *ElementHeaderSize
= (1 + sizeof(uint32_t));
244 ElementValue
= (1 << SizeIndex
);
245 *ElementHeaderSize
= 1;