1 /******************************************************************************
2 *
3 * Copyright (C) 2002-2012 Broadcom Corporation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
19 /******************************************************************************
20 *
21 * ommon API for the Advanced Audio Distribution Profile (A2DP)
22 *
23 ******************************************************************************/
24 #include <string.h>
25 #include "bt_target.h"
26 #include "sdpdefs.h"
27 #include "a2d_api.h"
28 #include "a2d_int.h"
29 #include "avdt_api.h"
30
31 /*****************************************************************************
32 ** Global data
33 *****************************************************************************/
34 #if A2D_DYNAMIC_MEMORY == FALSE
35 tA2D_CB a2d_cb;
36 #endif
37
38
39 /******************************************************************************
40 **
41 ** Function a2d_sdp_cback
42 **
43 ** Description This is the SDP callback function used by A2D_FindService.
44 ** This function will be executed by SDP when the service
45 ** search is completed. If the search is successful, it
46 ** finds the first record in the database that matches the
47 ** UUID of the search. Then retrieves various parameters
48 ** from the record. When it is finished it calls the
49 ** application callback function.
50 **
51 ** Returns Nothing.
52 **
53 ******************************************************************************/
a2d_sdp_cback(UINT16 status)54 static void a2d_sdp_cback(UINT16 status)
55 {
56 tSDP_DISC_REC *p_rec = NULL;
57 tSDP_DISC_ATTR *p_attr;
58 BOOLEAN found = FALSE;
59 tA2D_Service a2d_svc;
60 tSDP_PROTOCOL_ELEM elem;
61
62 A2D_TRACE_API("a2d_sdp_cback status: %d", status);
63
64 if (status == SDP_SUCCESS)
65 {
66 /* loop through all records we found */
67 do
68 {
69 /* get next record; if none found, we're done */
70 if ((p_rec = SDP_FindServiceInDb(a2d_cb.find.p_db,
71 a2d_cb.find.service_uuid, p_rec)) == NULL)
72 {
73 break;
74 }
75 memset(&a2d_svc, 0, sizeof(tA2D_Service));
76
77 /* get service name */
78 if ((p_attr = SDP_FindAttributeInRec(p_rec,
79 ATTR_ID_SERVICE_NAME)) != NULL)
80 {
81 a2d_svc.p_service_name = (char *) p_attr->attr_value.v.array;
82 a2d_svc.service_len = SDP_DISC_ATTR_LEN(p_attr->attr_len_type);
83 }
84
85 /* get provider name */
86 if ((p_attr = SDP_FindAttributeInRec(p_rec,
87 ATTR_ID_PROVIDER_NAME)) != NULL)
88 {
89 a2d_svc.p_provider_name = (char *) p_attr->attr_value.v.array;
90 a2d_svc.provider_len = SDP_DISC_ATTR_LEN(p_attr->attr_len_type);
91 }
92
93 /* get supported features */
94 if ((p_attr = SDP_FindAttributeInRec(p_rec,
95 ATTR_ID_SUPPORTED_FEATURES)) != NULL)
96 {
97 a2d_svc.features = p_attr->attr_value.v.u16;
98 }
99
100 /* get AVDTP version */
101 if (SDP_FindProtocolListElemInRec(p_rec, UUID_PROTOCOL_AVDTP, &elem))
102 {
103 a2d_svc.avdt_version = elem.params[0];
104 A2D_TRACE_DEBUG("avdt_version: 0x%x", a2d_svc.avdt_version);
105 }
106
107 /* we've got everything, we're done */
108 found = TRUE;
109 break;
110
111 } while (TRUE);
112 }
113
114 a2d_cb.find.service_uuid = 0;
115 /* return info from sdp record in app callback function */
116 if (a2d_cb.find.p_cback != NULL)
117 {
118 (*a2d_cb.find.p_cback)(found, &a2d_svc);
119 }
120
121 return;
122 }
123
124 /*******************************************************************************
125 **
126 ** Function a2d_set_avdt_sdp_ver
127 **
128 ** Description This function allows the script wrapper to change the
129 ** avdt version of a2dp.
130 **
131 ** Returns None
132 **
133 *******************************************************************************/
a2d_set_avdt_sdp_ver(UINT16 avdt_sdp_ver)134 void a2d_set_avdt_sdp_ver (UINT16 avdt_sdp_ver)
135 {
136 a2d_cb.avdt_sdp_ver = avdt_sdp_ver;
137 }
138
139 /******************************************************************************
140 **
141 ** Function A2D_AddRecord
142 **
143 ** Description This function is called by a server application to add
144 ** SRC or SNK information to an SDP record. Prior to
145 ** calling this function the application must call
146 ** SDP_CreateRecord() to create an SDP record.
147 **
148 ** Input Parameters:
149 ** service_uuid: Indicates SRC or SNK.
150 **
151 ** p_service_name: Pointer to a null-terminated character
152 ** string containing the service name.
153 **
154 ** p_provider_name: Pointer to a null-terminated character
155 ** string containing the provider name.
156 **
157 ** features: Profile supported features.
158 **
159 ** sdp_handle: SDP handle returned by SDP_CreateRecord().
160 **
161 ** Output Parameters:
162 ** None.
163 **
164 ** Returns A2D_SUCCESS if function execution succeeded,
165 ** A2D_INVALID_PARAMS if bad parameters are given.
166 ** A2D_FAIL if function execution failed.
167 **
168 ******************************************************************************/
A2D_AddRecord(UINT16 service_uuid,char * p_service_name,char * p_provider_name,UINT16 features,UINT32 sdp_handle)169 tA2D_STATUS A2D_AddRecord(UINT16 service_uuid, char *p_service_name, char *p_provider_name,
170 UINT16 features, UINT32 sdp_handle)
171 {
172 UINT16 browse_list[1];
173 BOOLEAN result = TRUE;
174 UINT8 temp[8];
175 UINT8 *p;
176 tSDP_PROTOCOL_ELEM proto_list [A2D_NUM_PROTO_ELEMS];
177
178 A2D_TRACE_API("A2D_AddRecord uuid: %x", service_uuid);
179
180 if( (sdp_handle == 0) ||
181 (service_uuid != UUID_SERVCLASS_AUDIO_SOURCE && service_uuid != UUID_SERVCLASS_AUDIO_SINK) )
182 return A2D_INVALID_PARAMS;
183
184 /* add service class id list */
185 result &= SDP_AddServiceClassIdList(sdp_handle, 1, &service_uuid);
186
187 memset((void*) proto_list, 0 , A2D_NUM_PROTO_ELEMS*sizeof(tSDP_PROTOCOL_ELEM));
188
189 /* add protocol descriptor list */
190 proto_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
191 proto_list[0].num_params = 1;
192 proto_list[0].params[0] = AVDT_PSM;
193 proto_list[1].protocol_uuid = UUID_PROTOCOL_AVDTP;
194 proto_list[1].num_params = 1;
195 proto_list[1].params[0] = a2d_cb.avdt_sdp_ver;
196
197 result &= SDP_AddProtocolList(sdp_handle, A2D_NUM_PROTO_ELEMS, proto_list);
198
199 /* add profile descriptor list */
200 result &= SDP_AddProfileDescriptorList(sdp_handle, UUID_SERVCLASS_ADV_AUDIO_DISTRIBUTION, A2D_VERSION);
201
202 /* add supported feature */
203 if (features != 0)
204 {
205 p = temp;
206 UINT16_TO_BE_STREAM(p, features);
207 result &= SDP_AddAttribute(sdp_handle, ATTR_ID_SUPPORTED_FEATURES, UINT_DESC_TYPE,
208 (UINT32)2, (UINT8*)temp);
209 }
210
211 /* add provider name */
212 if (p_provider_name != NULL)
213 {
214 result &= SDP_AddAttribute(sdp_handle, ATTR_ID_PROVIDER_NAME, TEXT_STR_DESC_TYPE,
215 (UINT32)(strlen(p_provider_name)+1), (UINT8 *) p_provider_name);
216 }
217
218 /* add service name */
219 if (p_service_name != NULL)
220 {
221 result &= SDP_AddAttribute(sdp_handle, ATTR_ID_SERVICE_NAME, TEXT_STR_DESC_TYPE,
222 (UINT32)(strlen(p_service_name)+1), (UINT8 *) p_service_name);
223 }
224
225 /* add browse group list */
226 browse_list[0] = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
227 result &= SDP_AddUuidSequence(sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, browse_list);
228
229
230 return (result ? A2D_SUCCESS : A2D_FAIL);
231 }
232
233 /******************************************************************************
234 **
235 ** Function A2D_FindService
236 **
237 ** Description This function is called by a client application to
238 ** perform service discovery and retrieve SRC or SNK SDP
239 ** record information from a server. Information is
240 ** returned for the first service record found on the
241 ** server that matches the service UUID. The callback
242 ** function will be executed when service discovery is
243 ** complete. There can only be one outstanding call to
244 ** A2D_FindService() at a time; the application must wait
245 ** for the callback before it makes another call to
246 ** the function.
247 **
248 ** Input Parameters:
249 ** service_uuid: Indicates SRC or SNK.
250 **
251 ** bd_addr: BD address of the peer device.
252 **
253 ** p_db: Pointer to the information to initialize
254 ** the discovery database.
255 **
256 ** p_cback: Pointer to the A2D_FindService()
257 ** callback function.
258 **
259 ** Output Parameters:
260 ** None.
261 **
262 ** Returns A2D_SUCCESS if function execution succeeded,
263 ** A2D_INVALID_PARAMS if bad parameters are given.
264 ** A2D_BUSY if discovery is already in progress.
265 ** A2D_FAIL if function execution failed.
266 **
267 ******************************************************************************/
A2D_FindService(UINT16 service_uuid,BD_ADDR bd_addr,tA2D_SDP_DB_PARAMS * p_db,tA2D_FIND_CBACK * p_cback)268 tA2D_STATUS A2D_FindService(UINT16 service_uuid, BD_ADDR bd_addr,
269 tA2D_SDP_DB_PARAMS *p_db, tA2D_FIND_CBACK *p_cback)
270 {
271 tSDP_UUID uuid_list;
272 BOOLEAN result = TRUE;
273 UINT16 a2d_attr_list[] = {ATTR_ID_SERVICE_CLASS_ID_LIST, /* update A2D_NUM_ATTR, if changed */
274 ATTR_ID_BT_PROFILE_DESC_LIST,
275 ATTR_ID_SUPPORTED_FEATURES,
276 ATTR_ID_SERVICE_NAME,
277 ATTR_ID_PROTOCOL_DESC_LIST,
278 ATTR_ID_PROVIDER_NAME};
279
280 A2D_TRACE_API("A2D_FindService uuid: %x", service_uuid);
281 if( (service_uuid != UUID_SERVCLASS_AUDIO_SOURCE && service_uuid != UUID_SERVCLASS_AUDIO_SINK) ||
282 p_db == NULL || p_db->p_db == NULL || p_cback == NULL)
283 return A2D_INVALID_PARAMS;
284
285 if( a2d_cb.find.service_uuid == UUID_SERVCLASS_AUDIO_SOURCE ||
286 a2d_cb.find.service_uuid == UUID_SERVCLASS_AUDIO_SINK)
287 return A2D_BUSY;
288
289 /* set up discovery database */
290 uuid_list.len = LEN_UUID_16;
291 uuid_list.uu.uuid16 = service_uuid;
292
293 if(p_db->p_attrs == NULL || p_db->num_attr == 0)
294 {
295 p_db->p_attrs = a2d_attr_list;
296 p_db->num_attr = A2D_NUM_ATTR;
297 }
298
299 result = SDP_InitDiscoveryDb(p_db->p_db, p_db->db_len, 1, &uuid_list, p_db->num_attr,
300 p_db->p_attrs);
301
302 if (result == TRUE)
303 {
304 /* store service_uuid and discovery db pointer */
305 a2d_cb.find.p_db = p_db->p_db;
306 a2d_cb.find.service_uuid = service_uuid;
307 a2d_cb.find.p_cback = p_cback;
308
309 /* perform service search */
310 result = SDP_ServiceSearchAttributeRequest(bd_addr, p_db->p_db, a2d_sdp_cback);
311 if(FALSE == result)
312 {
313 a2d_cb.find.service_uuid = 0;
314 }
315 }
316
317 return (result ? A2D_SUCCESS : A2D_FAIL);
318 }
319
320 /******************************************************************************
321 **
322 ** Function A2D_SetTraceLevel
323 **
324 ** Description Sets the trace level for A2D. If 0xff is passed, the
325 ** current trace level is returned.
326 **
327 ** Input Parameters:
328 ** new_level: The level to set the A2D tracing to:
329 ** 0xff-returns the current setting.
330 ** 0-turns off tracing.
331 ** >= 1-Errors.
332 ** >= 2-Warnings.
333 ** >= 3-APIs.
334 ** >= 4-Events.
335 ** >= 5-Debug.
336 **
337 ** Returns The new trace level or current trace level if
338 ** the input parameter is 0xff.
339 **
340 ******************************************************************************/
A2D_SetTraceLevel(UINT8 new_level)341 UINT8 A2D_SetTraceLevel (UINT8 new_level)
342 {
343 if (new_level != 0xFF)
344 a2d_cb.trace_level = new_level;
345
346 return (a2d_cb.trace_level);
347 }
348
349 /******************************************************************************
350 ** Function A2D_BitsSet
351 **
352 ** Description Check the given num for the number of bits set
353 ** Returns A2D_SET_ONE_BIT, if one and only one bit is set
354 ** A2D_SET_ZERO_BIT, if all bits clear
355 ** A2D_SET_MULTL_BIT, if multiple bits are set
356 ******************************************************************************/
A2D_BitsSet(UINT8 num)357 UINT8 A2D_BitsSet(UINT8 num)
358 {
359 UINT8 count;
360 BOOLEAN res;
361 if(num == 0)
362 res = A2D_SET_ZERO_BIT;
363 else
364 {
365 count = (num & (num - 1));
366 res = ((count==0)?A2D_SET_ONE_BIT:A2D_SET_MULTL_BIT);
367 }
368 return res;
369 }
370
371 /*******************************************************************************
372 **
373 ** Function A2D_Init
374 **
375 ** Description This function is called to initialize the control block
376 ** for this layer. It must be called before accessing any
377 ** other API functions for this layer. It is typically called
378 ** once during the start up of the stack.
379 **
380 ** Returns void
381 **
382 *******************************************************************************/
A2D_Init(void)383 void A2D_Init(void)
384 {
385 memset(&a2d_cb, 0, sizeof(tA2D_CB));
386
387 a2d_cb.avdt_sdp_ver = AVDT_VERSION;
388
389 #if defined(A2D_INITIAL_TRACE_LEVEL)
390 a2d_cb.trace_level = A2D_INITIAL_TRACE_LEVEL;
391 #else
392 a2d_cb.trace_level = BT_TRACE_LEVEL_NONE;
393 #endif
394 }
395
396