4eb2621031030f29d9594efaac773c52d50b486f
[pub/USBasp.git] / Demos / Host / Incomplete / BluetoothHost / Lib / ServiceDiscoveryProtocol.c
1 /*
2 LUFA Library
3 Copyright (C) Dean Camera, 2010.
4
5 dean [at] fourwalledcubicle [dot] com
6 www.fourwalledcubicle.com
7 */
8
9 /*
10 Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
11
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.
20
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
28 this software.
29 */
30
31 #define INCLUDE_FROM_SERVICEDISCOVERYPROTOCOL_C
32 #include "ServiceDiscoveryProtocol.h"
33
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 =
42 {
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
47 };
48
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 =
57 {
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
62 };
63
64 /** Master service table, listing all supported services (and their attribute tables) of the device, including
65 * each service's UUID.
66 */
67 const ServiceTable_t SDP_Services_Table[] =
68 {
69 { // 128-bit UUID for the SDP service
70 .UUID = {BASE_96BIT_UUID, 0x01, 0x00, 0x00, 0x00},
71 .AttributeTable = &SDP_Attribute_Table,
72 },
73 { // 128-bit UUID for the RFCOMM service
74 .UUID = {BASE_96BIT_UUID, 0x03, 0x00, 0x00, 0x00},
75 .AttributeTable = &RFCOMM_Attribute_Table,
76 },
77 };
78
79 /* Base UUID value common to all standardized Bluetooth services */
80 const uint8_t BaseUUID[] = {BASE_96BIT_UUID, 0x00, 0x00, 0x00, 0x00};
81
82
83 void ServiceDiscovery_ProcessPacket(void* Data, Bluetooth_Channel_t* Channel)
84 {
85 SDP_PDUHeader_t* SDPHeader = (SDP_PDUHeader_t*)Data;
86 SDPHeader->ParameterLength = SwapEndian_16(SDPHeader->ParameterLength);
87
88 BT_SDP_DEBUG(1, "SDP Packet Received");
89 BT_SDP_DEBUG(2, "-- PDU ID: 0x%02X", SDPHeader->PDU);
90 BT_SDP_DEBUG(2, "-- Param Length: 0x%04X", SDPHeader->ParameterLength);
91
92 switch (SDPHeader->PDU)
93 {
94 case SDP_PDU_SERVICESEARCHREQUEST:
95 ServiceDiscovery_ProcessServiceSearch(SDPHeader, Channel);
96 break;
97 case SDP_PDU_SERVICEATTRIBUTEREQUEST:
98 ServiceDiscovery_ProcessServiceAttribute(SDPHeader, Channel);
99 break;
100 case SDP_PDU_SERVICESEARCHATTRIBUTEREQUEST:
101 ServiceDiscovery_ProcessServiceSearchAttribute(SDPHeader, Channel);
102 break;
103 }
104 }
105
106 static void ServiceDiscovery_ProcessServiceSearch(SDP_PDUHeader_t* SDPHeader, Bluetooth_Channel_t* Channel)
107 {
108 BT_SDP_DEBUG(1, "<< Service Search");
109 }
110
111 static void ServiceDiscovery_ProcessServiceAttribute(SDP_PDUHeader_t* SDPHeader, Bluetooth_Channel_t* Channel)
112 {
113 BT_SDP_DEBUG(1, "<< Service Attribute");
114 }
115
116 static void ServiceDiscovery_ProcessServiceSearchAttribute(SDP_PDUHeader_t* SDPHeader, Bluetooth_Channel_t* Channel)
117 {
118 const void* CurrentParameter = ((void*)SDPHeader + sizeof(SDP_PDUHeader_t));
119
120 BT_SDP_DEBUG(1, "<< Service Search Attribute");
121
122 uint8_t UUIDList[12][UUID_SIZE_BYTES];
123 uint8_t TotalUUIDs = ServiceDiscovery_GetUUIDList(UUIDList, &CurrentParameter);
124 BT_SDP_DEBUG(2, "-- Total UUIDs: %d", TotalUUIDs);
125
126 uint16_t MaxAttributeSize = ServiceDiscovery_Read16BitParameter(&CurrentParameter);
127 BT_SDP_DEBUG(2, "-- Max Return Attribute Bytes: 0x%04X", MaxAttributeSize);
128
129 struct
130 {
131 SDP_PDUHeader_t SDPHeader;
132 uint16_t AttributeListByteCount;
133 uint8_t ResponseData[100];
134 } ResponsePacket;
135
136 if (MaxAttributeSize > sizeof(ResponsePacket.ResponseData))
137 MaxAttributeSize = sizeof(ResponsePacket.ResponseData);
138
139 ResponsePacket.AttributeListByteCount = ServiceDiscovery_ProcessAttributes(UUIDList, TotalUUIDs,
140 ResponsePacket.ResponseData,
141 MaxAttributeSize, &CurrentParameter);
142 ResponsePacket.SDPHeader.PDU = SDP_PDU_SERVICESEARCHATTRIBUTERESPONSE;
143 ResponsePacket.SDPHeader.TransactionID = SDPHeader->TransactionID;
144 ResponsePacket.SDPHeader.ParameterLength = (ResponsePacket.AttributeListByteCount + sizeof(ResponsePacket.AttributeListByteCount));
145
146 Bluetooth_SendPacket(&ResponsePacket, (sizeof(ResponsePacket.SDPHeader) + ResponsePacket.SDPHeader.ParameterLength),
147 Channel);
148 }
149
150 static uint8_t ServiceDiscovery_ProcessAttributes(uint8_t UUIDList[][UUID_SIZE_BYTES], const uint8_t TotalUUIDs, uint8_t* ResponseBuffer,
151 uint8_t MaxResponseSize, const void** CurrentParameter)
152 {
153 uint16_t* AttributeResponseSize = ServiceDiscovery_AddDataElementHeader(&ResponseBuffer, SDP_DATATYPE_UnsignedInt);
154 uint8_t ElementHeaderSize;
155
156 uint16_t AttributeIDListLength = ServiceDiscovery_GetDataElementSize(CurrentParameter, &ElementHeaderSize);
157 BT_SDP_DEBUG(2, "-- Total Attribute Length: 0x%04X", AttributeIDListLength);
158 while (AttributeIDListLength)
159 {
160 uint8_t AttributeLength = ServiceDiscovery_GetDataElementSize(CurrentParameter, &ElementHeaderSize);
161 uint32_t Attribute = 0;
162
163 memcpy(&((char*)&Attribute)[sizeof(uint32_t) - AttributeLength], *CurrentParameter, AttributeLength);
164
165 BT_SDP_DEBUG(2, "-- Attribute(%d): 0x%08lX", AttributeLength, Attribute);
166
167 *AttributeResponseSize += ServiceDiscovery_GetAttribute(UUIDList, TotalUUIDs, Attribute, &ResponseBuffer,
168 (MaxResponseSize - *AttributeResponseSize));
169
170 AttributeIDListLength -= (AttributeLength + ElementHeaderSize);
171 *CurrentParameter += AttributeLength;
172 }
173
174 return *AttributeResponseSize;
175 }
176
177 static uint8_t ServiceDiscovery_GetAttribute(uint8_t UUIDList[][UUID_SIZE_BYTES], const uint8_t TotalUUIDs, const uint32_t Attribute,
178 uint8_t** DataBuffer, uint8_t BufferLen)
179 {
180 for (uint8_t CurrTableItem = 0; CurrTableItem < (sizeof(SDP_Services_Table) / sizeof(ServiceTable_t)); CurrTableItem++)
181 {
182 for (uint8_t CurrUUIDIndex = 0; CurrUUIDIndex < TotalUUIDs; CurrUUIDIndex++)
183 {
184 if (!(memcmp(SDP_Services_Table[CurrTableItem].UUID, UUIDList[CurrUUIDIndex], UUID_SIZE_BYTES)))
185 {
186 const ServiceAttributeTable_t* AttributeTable = SDP_Services_Table[CurrTableItem].AttributeTable;
187
188 // TODO: Process attribute table
189 BT_SDP_DEBUG(2, "FOUND UUID IN TABLE");
190
191 break;
192 }
193 }
194 }
195
196 return 0;
197 }
198
199 static uint8_t ServiceDiscovery_GetUUIDList(uint8_t UUIDList[][UUID_SIZE_BYTES], const void** CurrentParameter)
200 {
201 uint8_t ElementHeaderSize;
202 uint8_t TotalUUIDs = 0;
203
204 uint16_t ServicePatternLength = ServiceDiscovery_GetDataElementSize(CurrentParameter, &ElementHeaderSize);
205 BT_SDP_DEBUG(2, "-- Total UUID Length: 0x%04X", ServicePatternLength);
206 while (ServicePatternLength)
207 {
208 uint8_t* CurrentUUID = UUIDList[TotalUUIDs++];
209 uint8_t UUIDLength = ServiceDiscovery_GetDataElementSize(CurrentParameter, &ElementHeaderSize);
210
211 memcpy(CurrentUUID, BaseUUID, sizeof(BaseUUID));
212 memcpy(&CurrentUUID[(UUIDLength <= 32) ? (sizeof(BaseUUID) - 32) : 0], *CurrentParameter, UUIDLength);
213
214 BT_SDP_DEBUG(2, "-- UUID (%d): 0x%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
215 UUIDLength,
216 CurrentUUID[15], CurrentUUID[14], CurrentUUID[13], CurrentUUID[12],
217 CurrentUUID[11], CurrentUUID[10], CurrentUUID[9], CurrentUUID[8],
218 CurrentUUID[7], CurrentUUID[6], CurrentUUID[5], CurrentUUID[4],
219 CurrentUUID[3], CurrentUUID[2], CurrentUUID[1], CurrentUUID[0]);
220
221 ServicePatternLength -= (UUIDLength + ElementHeaderSize);
222 *CurrentParameter += UUIDLength;
223 }
224
225 return TotalUUIDs;
226 }
227
228 static uint32_t ServiceDiscovery_GetDataElementSize(const void** DataElementHeader, uint8_t* ElementHeaderSize)
229 {
230 /* Fetch the size of the Data Element structure from the header, increment the current buffer pos */
231 uint8_t SizeIndex = (*((uint8_t*)*DataElementHeader) & 0x07);
232 *DataElementHeader += sizeof(uint8_t);
233
234 uint32_t ElementValue;
235
236 /* Convert the Data Element size index into a size in bytes */
237 switch (SizeIndex)
238 {
239 case 5:
240 ElementValue = *((uint8_t*)*DataElementHeader);
241 *DataElementHeader += sizeof(uint8_t);
242 *ElementHeaderSize = (1 + sizeof(uint8_t));
243 break;
244 case 6:
245 ElementValue = *((uint16_t*)*DataElementHeader);
246 *DataElementHeader += sizeof(uint16_t);
247 *ElementHeaderSize = (1 + sizeof(uint16_t));
248 break;
249 case 7:
250 ElementValue = *((uint32_t*)*DataElementHeader);
251 *DataElementHeader += sizeof(uint32_t);
252 *ElementHeaderSize = (1 + sizeof(uint32_t));
253 break;
254 default:
255 ElementValue = (1 << SizeIndex);
256 *ElementHeaderSize = 1;
257 break;
258 }
259
260 return ElementValue;
261 }