Switch over the BluetoothHost demo's Service Discovery code to pass around more gener...
[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_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 =
38 {
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
43 };
44
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 =
49 {
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
54 };
55
56 const ServiceTable_t SDP_Services_Table[] =
57 {
58 { // 128-bit UUID for the SDP service
59 .UUID = {BASE_96BIT_UUID, 0x01, 0x00, 0x00, 0x00},
60 .AttributeTable = &SDP_Attribute_Table,
61 },
62 { // 128-bit UUID for the RFCOMM service
63 .UUID = {BASE_96BIT_UUID, 0x03, 0x00, 0x00, 0x00},
64 .AttributeTable = &RFCOMM_Attribute_Table,
65 },
66 };
67
68 const uint8_t BaseUUID[] = {BASE_96BIT_UUID, 0x00, 0x00, 0x00, 0x00};
69
70
71 void ServiceDiscovery_ProcessPacket(void* Data, Bluetooth_Channel_t* Channel)
72 {
73 SDP_PDUHeader_t* SDPHeader = (SDP_PDUHeader_t*)Data;
74 SDPHeader->ParameterLength = SwapEndian_16(SDPHeader->ParameterLength);
75
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);
79
80 switch (SDPHeader->PDU)
81 {
82 case SDP_PDU_SERVICESEARCHREQUEST:
83 ServiceDiscovery_ProcessServiceSearch(SDPHeader, Channel);
84 break;
85 case SDP_PDU_SERVICEATTRIBUTEREQUEST:
86 ServiceDiscovery_ProcessServiceAttribute(SDPHeader, Channel);
87 break;
88 case SDP_PDU_SERVICESEARCHATTRIBUTEREQUEST:
89 ServiceDiscovery_ProcessServiceSearchAttribute(SDPHeader, Channel);
90 break;
91 }
92 }
93
94 static void ServiceDiscovery_ProcessServiceSearch(SDP_PDUHeader_t* SDPHeader, Bluetooth_Channel_t* Channel)
95 {
96 BT_SDP_DEBUG(1, "<< Service Search");
97 }
98
99 static void ServiceDiscovery_ProcessServiceAttribute(SDP_PDUHeader_t* SDPHeader, Bluetooth_Channel_t* Channel)
100 {
101 BT_SDP_DEBUG(1, "<< Service Attribute");
102 }
103
104 static void ServiceDiscovery_ProcessServiceSearchAttribute(SDP_PDUHeader_t* SDPHeader, Bluetooth_Channel_t* Channel)
105 {
106 const void* CurrentParameter = ((void*)SDPHeader + sizeof(SDP_PDUHeader_t));
107
108 BT_SDP_DEBUG(1, "<< Service Search Attribute");
109
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);
113
114 uint16_t MaxAttributeSize = ServiceDiscovery_Read16BitParameter(&CurrentParameter);
115 BT_SDP_DEBUG(2, "-- Max Return Attribute Bytes: 0x%04X", MaxAttributeSize);
116
117 struct
118 {
119 SDP_PDUHeader_t SDPHeader;
120 uint8_t ResponseData[100];
121 } ResponsePacket;
122
123 ResponsePacket.SDPHeader.PDU = SDP_PDU_SERVICESEARCHATTRIBUTERESPONSE;
124 ResponsePacket.SDPHeader.TransactionID = SDPHeader->TransactionID;
125
126 if (MaxAttributeSize > sizeof(ResponsePacket.ResponseData))
127 MaxAttributeSize = sizeof(ResponsePacket.ResponseData);
128
129 ResponsePacket.SDPHeader.ParameterLength = ServiceDiscovery_ProcessAttributes(UUIDList, TotalUUIDs,
130 ResponsePacket.ResponseData,
131 MaxAttributeSize, &CurrentParameter);
132
133 Bluetooth_SendPacket(&ResponsePacket, (sizeof(ResponsePacket.SDPHeader) + ResponsePacket.SDPHeader.ParameterLength),
134 Channel);
135 }
136
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)
139 {
140 uint8_t ElementHeaderSize;
141 uint8_t TotalResponseSize = 0;
142
143 uint16_t AttributeIDListLength = ServiceDiscovery_GetDataElementSize(CurrentParameter, &ElementHeaderSize);
144 BT_SDP_DEBUG(2, "-- Total Attribute Length: 0x%04X", AttributeIDListLength);
145 while (AttributeIDListLength)
146 {
147 uint8_t AttributeLength = ServiceDiscovery_GetDataElementSize(CurrentParameter, &ElementHeaderSize);
148 uint32_t Attribute = 0;
149
150 memcpy(&Attribute, CurrentParameter, AttributeLength);
151
152 BT_SDP_DEBUG(2, "-- Attribute(%d): 0x%08lX", AttributeLength, Attribute);
153
154 uint8_t TotalBytesAdded = ServiceDiscovery_GetAttribute(UUIDList, TotalUUIDs, Attribute, &ResponseBuffer,
155 MaxResponseSize);
156 TotalResponseSize += TotalBytesAdded;
157 MaxResponseSize -= TotalBytesAdded;
158
159 AttributeIDListLength -= (AttributeLength + ElementHeaderSize);
160 CurrentParameter += AttributeLength;
161 }
162
163 return TotalResponseSize;
164 }
165
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)
168 {
169 for (uint8_t CurrTableItem = 0; CurrTableItem < (sizeof(SDP_Services_Table) / sizeof(ServiceTable_t)); CurrTableItem++)
170 {
171 for (uint8_t CurrUUIDIndex = 0; CurrUUIDIndex < TotalUUIDs; CurrUUIDIndex++)
172 {
173 if (!(memcmp(SDP_Services_Table[CurrTableItem].UUID, UUIDList[CurrUUIDIndex], UUID_SIZE_BYTES)))
174 {
175 const ServiceAttributeTable_t* AttributeTable = SDP_Services_Table[CurrTableItem].AttributeTable;
176
177 // Process attribute table
178 BT_SDP_DEBUG(2, "FOUND UUID IN TABLE");
179
180 break;
181 }
182 }
183 }
184
185 return 0;
186 }
187
188 static uint8_t ServiceDiscovery_GetUUIDList(uint8_t UUIDList[][UUID_SIZE_BYTES], const void** CurrentParameter)
189 {
190 uint8_t ElementHeaderSize;
191 uint8_t TotalUUIDs = 0;
192
193 uint16_t ServicePatternLength = ServiceDiscovery_GetDataElementSize(CurrentParameter, &ElementHeaderSize);
194 BT_SDP_DEBUG(2, "-- Total UUID Length: 0x%04X", ServicePatternLength);
195 while (ServicePatternLength)
196 {
197 uint8_t* CurrentUUID = UUIDList[TotalUUIDs++];
198 uint8_t UUIDLength = ServiceDiscovery_GetDataElementSize(CurrentParameter, &ElementHeaderSize);
199
200 memcpy(CurrentUUID, BaseUUID, sizeof(BaseUUID));
201 memcpy(&CurrentUUID[(UUIDLength <= 32) ? (sizeof(BaseUUID) - 32) : 0], *CurrentParameter, UUIDLength);
202
203 BT_SDP_DEBUG(2, "-- UUID (%d): 0x%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
204 UUIDLength,
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]);
209
210 ServicePatternLength -= (UUIDLength + ElementHeaderSize);
211 *CurrentParameter += UUIDLength;
212 }
213
214 return TotalUUIDs;
215 }
216
217 static uint32_t ServiceDiscovery_GetDataElementSize(const void** DataElementHeader, uint8_t* ElementHeaderSize)
218 {
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);
222
223 uint32_t ElementValue;
224
225 /* Convert the Data Element size index into a size in bytes */
226 switch (SizeIndex)
227 {
228 case 5:
229 ElementValue = *((uint8_t*)*DataElementHeader);
230 *DataElementHeader += sizeof(uint8_t);
231 *ElementHeaderSize = (1 + sizeof(uint8_t));
232 break;
233 case 6:
234 ElementValue = *((uint16_t*)*DataElementHeader);
235 *DataElementHeader += sizeof(uint16_t);
236 *ElementHeaderSize = (1 + sizeof(uint16_t));
237 break;
238 case 7:
239 ElementValue = *((uint32_t*)*DataElementHeader);
240 *DataElementHeader += sizeof(uint32_t);
241 *ElementHeaderSize = (1 + sizeof(uint32_t));
242 break;
243 default:
244 ElementValue = (1 << SizeIndex);
245 *ElementHeaderSize = 1;
246 break;
247 }
248
249 return ElementValue;
250 }