• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  *  BlueZ - Bluetooth protocol stack for Linux
4  *
5  *  Copyright (C) 2010 GSyC/LibreSoft, Universidad Rey Juan Carlos.
6  *  Authors:
7  *  Santiago Carot Nemesio <sancane at gmail.com>
8  *  Jose Antonio Santos-Cadenas <santoscadenas at gmail.com>
9  *
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2 of the License, or
13  *  (at your option) any later version.
14  *
15  *  This program is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU General Public License for more details.
19  *
20  *  You should have received a copy of the GNU General Public License
21  *  along with this program; if not, write to the Free Software
22  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
23  *
24  */
25 
26 #include <gdbus.h>
27 
28 #include <adapter.h>
29 #include <device.h>
30 #include <stdint.h>
31 #include <hdp_types.h>
32 #include <hdp_util.h>
33 #include <mcap.h>
34 #include <hdp.h>
35 
36 #include <sdpd.h>
37 #include <bluetooth/sdp_lib.h>
38 #include <glib-helper.h>
39 
40 #include <btio.h>
41 #include <mcap_lib.h>
42 
43 #include <log.h>
44 
45 typedef gboolean (*parse_item_f)(DBusMessageIter *iter, gpointer user_data,
46 								GError **err);
47 
48 struct dict_entry_func {
49 	char		*key;
50 	parse_item_f	func;
51 };
52 
53 struct get_mdep_data {
54 	struct hdp_application	*app;
55 	gpointer		data;
56 	hdp_continue_mdep_f	func;
57 	GDestroyNotify		destroy;
58 };
59 
60 struct conn_mcl_data {
61 	int			refs;
62 	gpointer		data;
63 	hdp_continue_proc_f	func;
64 	GDestroyNotify		destroy;
65 	struct hdp_device	*dev;
66 };
67 
68 struct get_dcpsm_data {
69 	gpointer		data;
70 	hdp_continue_dcpsm_f	func;
71 	GDestroyNotify		destroy;
72 };
73 
parse_dict_entry(struct dict_entry_func dict_context[],DBusMessageIter * iter,GError ** err,gpointer user_data)74 static gboolean parse_dict_entry(struct dict_entry_func dict_context[],
75 							DBusMessageIter *iter,
76 							GError **err,
77 							gpointer user_data)
78 {
79 	DBusMessageIter entry;
80 	char *key;
81 	int ctype, i;
82 	struct dict_entry_func df;
83 
84 	dbus_message_iter_recurse(iter, &entry);
85 	ctype = dbus_message_iter_get_arg_type(&entry);
86 	if (ctype != DBUS_TYPE_STRING) {
87 		g_set_error(err, HDP_ERROR, HDP_DIC_ENTRY_PARSE_ERROR,
88 			"Dictionary entries should have a string as key");
89 		return FALSE;
90 	}
91 
92 	dbus_message_iter_get_basic(&entry, &key);
93 	dbus_message_iter_next(&entry);
94 	/* Find function and call it */
95 	for (i = 0, df = dict_context[0]; df.key; i++, df = dict_context[i]) {
96 		if (g_ascii_strcasecmp(df.key, key) == 0)
97 			return df.func(&entry, user_data, err);
98 	}
99 
100 	g_set_error(err, HDP_ERROR, HDP_DIC_ENTRY_PARSE_ERROR,
101 			"No function found for parsing value for key %s", key);
102 	return FALSE;
103 }
104 
parse_dict(struct dict_entry_func dict_context[],DBusMessageIter * iter,GError ** err,gpointer user_data)105 static gboolean parse_dict(struct dict_entry_func dict_context[],
106 							DBusMessageIter *iter,
107 							GError **err,
108 							gpointer user_data)
109 {
110 	int ctype;
111 	DBusMessageIter dict;
112 
113 	ctype = dbus_message_iter_get_arg_type(iter);
114 	if (ctype != DBUS_TYPE_ARRAY) {
115 		g_set_error(err, HDP_ERROR, HDP_DIC_PARSE_ERROR,
116 					"Dictionary should be an array");
117 		return FALSE;
118 	}
119 
120 	dbus_message_iter_recurse(iter, &dict);
121 	while ((ctype = dbus_message_iter_get_arg_type(&dict)) !=
122 							DBUS_TYPE_INVALID) {
123 		if (ctype != DBUS_TYPE_DICT_ENTRY) {
124 			g_set_error(err, HDP_ERROR, HDP_DIC_PARSE_ERROR,
125 						"Dictionary array should "
126 						"contain dict entries");
127 			return FALSE;
128 		}
129 
130 		/* Start parsing entry */
131 		if (!parse_dict_entry(dict_context, &dict, err,
132 							user_data))
133 			return FALSE;
134 		/* Finish entry parsing */
135 
136 		dbus_message_iter_next(&dict);
137 	}
138 
139 	return TRUE;
140 }
141 
parse_data_type(DBusMessageIter * iter,gpointer data,GError ** err)142 static gboolean parse_data_type(DBusMessageIter *iter, gpointer data,
143 								GError **err)
144 {
145 	struct hdp_application *app = data;
146 	DBusMessageIter *value;
147 	int ctype;
148 
149 	ctype = dbus_message_iter_get_arg_type(iter);
150 	value = iter;
151 	if (ctype == DBUS_TYPE_VARIANT) {
152 		DBusMessageIter variant;
153 
154 		/* Get value inside the variable */
155 		dbus_message_iter_recurse(iter, &variant);
156 		ctype = dbus_message_iter_get_arg_type(&variant);
157 		value = &variant;
158 	}
159 
160 	if (ctype != DBUS_TYPE_UINT16) {
161 		g_set_error(err, HDP_ERROR, HDP_DIC_ENTRY_PARSE_ERROR,
162 			"Final value for data type should be uint16");
163 		return FALSE;
164 	}
165 
166 	dbus_message_iter_get_basic(value, &app->data_type);
167 	app->data_type_set = TRUE;
168 	return TRUE;
169 }
170 
parse_role(DBusMessageIter * iter,gpointer data,GError ** err)171 static gboolean parse_role(DBusMessageIter *iter, gpointer data, GError **err)
172 {
173 	struct hdp_application *app = data;
174 	DBusMessageIter *string;
175 	int ctype;
176 	const char *role;
177 
178 	ctype = dbus_message_iter_get_arg_type(iter);
179 	if (ctype == DBUS_TYPE_VARIANT) {
180 		DBusMessageIter value;
181 
182 		/* Get value inside the variable */
183 		dbus_message_iter_recurse(iter, &value);
184 		ctype = dbus_message_iter_get_arg_type(&value);
185 		string = &value;
186 	} else {
187 		string = iter;
188 	}
189 
190 	if (ctype != DBUS_TYPE_STRING) {
191 		g_set_error(err, HDP_ERROR, HDP_UNSPECIFIED_ERROR,
192 				"Value data spec should be variable or string");
193 		return FALSE;
194 	}
195 
196 	dbus_message_iter_get_basic(string, &role);
197 	if (g_ascii_strcasecmp(role, HDP_SINK_ROLE_AS_STRING) == 0) {
198 		app->role = HDP_SINK;
199 	} else if (g_ascii_strcasecmp(role, HDP_SOURCE_ROLE_AS_STRING) == 0) {
200 		app->role = HDP_SOURCE;
201 	} else {
202 		g_set_error(err, HDP_ERROR, HDP_UNSPECIFIED_ERROR,
203 			"Role value should be \"source\" or \"sink\"");
204 		return FALSE;
205 	}
206 
207 	app->role_set = TRUE;
208 
209 	return TRUE;
210 }
211 
parse_desc(DBusMessageIter * iter,gpointer data,GError ** err)212 static gboolean parse_desc(DBusMessageIter *iter, gpointer data, GError **err)
213 {
214 	struct hdp_application *app = data;
215 	DBusMessageIter *string;
216 	int ctype;
217 	const char *desc;
218 
219 	ctype = dbus_message_iter_get_arg_type(iter);
220 	if (ctype == DBUS_TYPE_VARIANT) {
221 		DBusMessageIter variant;
222 
223 		/* Get value inside the variable */
224 		dbus_message_iter_recurse(iter, &variant);
225 		ctype = dbus_message_iter_get_arg_type(&variant);
226 		string = &variant;
227 	} else {
228 		string = iter;
229 	}
230 
231 	if (ctype != DBUS_TYPE_STRING) {
232 		g_set_error(err, HDP_ERROR, HDP_DIC_ENTRY_PARSE_ERROR,
233 				"Value data spec should be variable or string");
234 		return FALSE;
235 	}
236 
237 	dbus_message_iter_get_basic(string, &desc);
238 	app->description = g_strdup(desc);
239 	return TRUE;
240 }
241 
parse_chan_type(DBusMessageIter * iter,gpointer data,GError ** err)242 static gboolean parse_chan_type(DBusMessageIter *iter, gpointer data,
243 								GError **err)
244 {
245 	struct hdp_application *app = data;
246 	DBusMessageIter *value;
247 	char *chan_type;
248 	int ctype;
249 
250 	ctype = dbus_message_iter_get_arg_type(iter);
251 	value = iter;
252 	if (ctype == DBUS_TYPE_VARIANT) {
253 		DBusMessageIter variant;
254 
255 		/* Get value inside the variable */
256 		dbus_message_iter_recurse(iter, &variant);
257 		ctype = dbus_message_iter_get_arg_type(&variant);
258 		value = &variant;
259 	}
260 
261 	if (ctype != DBUS_TYPE_STRING) {
262 		g_set_error(err, HDP_ERROR, HDP_DIC_ENTRY_PARSE_ERROR,
263 			"Final value for channel type should be an string");
264 		return FALSE;
265 	}
266 
267 	dbus_message_iter_get_basic(value, &chan_type);
268 
269 	if (g_ascii_strcasecmp("Reliable", chan_type) == 0)
270 		app->chan_type = HDP_RELIABLE_DC;
271 	else if (g_ascii_strcasecmp("Streaming", chan_type) == 0)
272 		app->chan_type = HDP_STREAMING_DC;
273 	else {
274 		g_set_error(err, HDP_ERROR, HDP_DIC_ENTRY_PARSE_ERROR,
275 						"Invalid value for data type");
276 		return FALSE;
277 	}
278 
279 	app->chan_type_set = TRUE;
280 
281 	return TRUE;
282 }
283 
284 static struct dict_entry_func dict_parser[] = {
285 	{"DataType",		parse_data_type},
286 	{"Role",		parse_role},
287 	{"Description",		parse_desc},
288 	{"ChannelType",		parse_chan_type},
289 	{NULL, NULL}
290 };
291 
hdp_get_app_config(DBusMessageIter * iter,GError ** err)292 struct hdp_application *hdp_get_app_config(DBusMessageIter *iter, GError **err)
293 {
294 	struct hdp_application *app;
295 
296 	app = g_new0(struct hdp_application, 1);
297 	app->ref = 1;
298 	if (!parse_dict(dict_parser, iter, err, app))
299 		goto fail;
300 	if (!app->data_type_set || !app->role_set) {
301 		g_set_error(err, HDP_ERROR, HDP_DIC_PARSE_ERROR,
302 						"Mandatory fields aren't set");
303 		goto fail;
304 	}
305 	return app;
306 
307 fail:
308 	hdp_application_unref(app);
309 	return NULL;
310 }
311 
is_app_role(GSList * app_list,HdpRole role)312 static gboolean is_app_role(GSList *app_list, HdpRole role)
313 {
314 	GSList *l;
315 
316 	for (l = app_list; l; l = l->next) {
317 		struct hdp_application *app = l->data;
318 
319 		if (app->role == role)
320 			return TRUE;
321 	}
322 
323 	return FALSE;
324 }
325 
set_sdp_services_uuid(sdp_record_t * record,HdpRole role)326 static gboolean set_sdp_services_uuid(sdp_record_t *record, HdpRole role)
327 {
328 	uuid_t svc_uuid_source, svc_uuid_sink;
329 	sdp_list_t *svc_list = NULL;
330 
331 	sdp_uuid16_create(&svc_uuid_sink, HDP_SINK_SVCLASS_ID);
332 	sdp_uuid16_create(&svc_uuid_source, HDP_SOURCE_SVCLASS_ID);
333 
334 	sdp_get_service_classes(record, &svc_list);
335 
336 	if (role == HDP_SOURCE) {
337 		if (!sdp_list_find(svc_list, &svc_uuid_source, sdp_uuid_cmp))
338 			svc_list = sdp_list_append(svc_list, &svc_uuid_source);
339 	} else if (role == HDP_SINK) {
340 		if (!sdp_list_find(svc_list, &svc_uuid_sink, sdp_uuid_cmp))
341 			svc_list = sdp_list_append(svc_list, &svc_uuid_sink);
342 	}
343 
344 	if (sdp_set_service_classes(record, svc_list) < 0) {
345 		sdp_list_free(svc_list, NULL);
346 		return FALSE;
347 	}
348 
349 	sdp_list_free(svc_list, NULL);
350 
351 	return TRUE;
352 }
353 
register_service_protocols(struct hdp_adapter * adapter,sdp_record_t * sdp_record)354 static gboolean register_service_protocols(struct hdp_adapter *adapter,
355 						sdp_record_t *sdp_record)
356 {
357 	gboolean ret;
358 	uuid_t l2cap_uuid, mcap_c_uuid;
359 	sdp_list_t *l2cap_list, *proto_list = NULL, *mcap_list = NULL;
360 	sdp_list_t *access_proto_list = NULL;
361 	sdp_data_t *psm = NULL, *mcap_ver = NULL;
362 	uint16_t version = MCAP_VERSION;
363 
364 	/* set l2cap information */
365 	sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
366 	l2cap_list = sdp_list_append(NULL, &l2cap_uuid);
367 	if (!l2cap_list) {
368 		ret = FALSE;
369 		goto end;
370 	}
371 
372 	psm = sdp_data_alloc(SDP_UINT16, &adapter->ccpsm);
373 	if (!psm) {
374 		ret = FALSE;
375 		goto end;
376 	}
377 
378 	if (!sdp_list_append(l2cap_list, psm)) {
379 		ret = FALSE;
380 		goto end;
381 	}
382 
383 	proto_list = sdp_list_append(NULL, l2cap_list);
384 	if (!proto_list) {
385 		ret = FALSE;
386 		goto end;
387 	}
388 
389 	/* set mcap information */
390 	sdp_uuid16_create(&mcap_c_uuid, MCAP_CTRL_UUID);
391 	mcap_list = sdp_list_append(NULL, &mcap_c_uuid);
392 	if (!mcap_list) {
393 		ret = FALSE;
394 		goto end;
395 	}
396 
397 	mcap_ver = sdp_data_alloc(SDP_UINT16, &version);
398 	if (!mcap_ver) {
399 		ret = FALSE;
400 		goto end;
401 	}
402 
403 	if (!sdp_list_append(mcap_list, mcap_ver)) {
404 		ret = FALSE;
405 		goto end;
406 	}
407 
408 	if (!sdp_list_append(proto_list, mcap_list)) {
409 		ret = FALSE;
410 		goto end;
411 	}
412 
413 	/* attach protocol information to service record */
414 	access_proto_list = sdp_list_append(NULL, proto_list);
415 	if (!access_proto_list) {
416 		ret = FALSE;
417 		goto end;
418 	}
419 
420 	if (sdp_set_access_protos(sdp_record, access_proto_list) < 0) {
421 		ret = FALSE;
422 		goto end;
423 	}
424 	ret = TRUE;
425 
426 end:
427 	if (l2cap_list)
428 		sdp_list_free(l2cap_list, NULL);
429 	if (mcap_list)
430 		sdp_list_free(mcap_list, NULL);
431 	if (proto_list)
432 		sdp_list_free(proto_list, NULL);
433 	if (access_proto_list)
434 		sdp_list_free(access_proto_list, NULL);
435 	if (psm)
436 		sdp_data_free(psm);
437 	if (mcap_ver)
438 		sdp_data_free(mcap_ver);
439 
440 	return ret;
441 }
442 
register_service_profiles(sdp_record_t * sdp_record)443 static gboolean register_service_profiles(sdp_record_t *sdp_record)
444 {
445 	gboolean ret;
446 	sdp_list_t *profile_list;
447 	sdp_profile_desc_t hdp_profile;
448 
449 	/* set hdp information */
450 	sdp_uuid16_create(&hdp_profile.uuid, HDP_SVCLASS_ID);
451 	hdp_profile.version = HDP_VERSION;
452 	profile_list = sdp_list_append(NULL, &hdp_profile);
453 	if (!profile_list)
454 		return FALSE;
455 
456 	/* set profile descriptor list */
457 	if (sdp_set_profile_descs(sdp_record, profile_list) < 0)
458 		ret = FALSE;
459 	else
460 		ret = TRUE;
461 
462 	sdp_list_free(profile_list, NULL);
463 
464 	return ret;
465 }
466 
register_service_additional_protocols(struct hdp_adapter * adapter,sdp_record_t * sdp_record)467 static gboolean register_service_additional_protocols(
468 						struct hdp_adapter *adapter,
469 						sdp_record_t *sdp_record)
470 {
471 	gboolean ret;
472 	uuid_t l2cap_uuid, mcap_d_uuid;
473 	sdp_list_t *l2cap_list, *proto_list = NULL, *mcap_list = NULL;
474 	sdp_list_t *access_proto_list = NULL;
475 	sdp_data_t *psm = NULL;
476 
477 	/* set l2cap information */
478 	sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
479 	l2cap_list = sdp_list_append(NULL, &l2cap_uuid);
480 	if (!l2cap_list) {
481 		ret = FALSE;
482 		goto end;
483 	}
484 
485 	psm = sdp_data_alloc(SDP_UINT16, &adapter->dcpsm);
486 	if (!psm) {
487 		ret = FALSE;
488 		goto end;
489 	}
490 
491 	if (!sdp_list_append(l2cap_list, psm)) {
492 		ret = FALSE;
493 		goto end;
494 	}
495 
496 	proto_list = sdp_list_append(NULL, l2cap_list);
497 	if (!proto_list) {
498 		ret = FALSE;
499 		goto end;
500 	}
501 
502 	/* set mcap information */
503 	sdp_uuid16_create(&mcap_d_uuid, MCAP_DATA_UUID);
504 	mcap_list = sdp_list_append(NULL, &mcap_d_uuid);
505 	if (!mcap_list) {
506 		ret = FALSE;
507 		goto end;
508 	}
509 
510 	if (!sdp_list_append(proto_list, mcap_list)) {
511 		ret = FALSE;
512 		goto end;
513 	}
514 
515 	/* attach protocol information to service record */
516 	access_proto_list = sdp_list_append(NULL, proto_list);
517 	if (!access_proto_list) {
518 		ret = FALSE;
519 		goto end;
520 	}
521 
522 	if (sdp_set_add_access_protos(sdp_record, access_proto_list) < 0)
523 		ret = FALSE;
524 	else
525 		ret = TRUE;
526 
527 end:
528 	if (l2cap_list)
529 		sdp_list_free(l2cap_list, NULL);
530 	if (mcap_list)
531 		sdp_list_free(mcap_list, NULL);
532 	if (proto_list)
533 		sdp_list_free(proto_list, NULL);
534 	if (access_proto_list)
535 		sdp_list_free(access_proto_list, NULL);
536 	if (psm)
537 		sdp_data_free(psm);
538 
539 	return ret;
540 }
541 
app_to_sdplist(struct hdp_application * app)542 static sdp_list_t *app_to_sdplist(struct hdp_application *app)
543 {
544 	sdp_data_t *mdepid,
545 		*dtype = NULL,
546 		*role = NULL,
547 		*desc = NULL;
548 	sdp_list_t *f_list = NULL;
549 
550 	mdepid = sdp_data_alloc(SDP_UINT8, &app->id);
551 	if (!mdepid)
552 		return NULL;
553 
554 	dtype = sdp_data_alloc(SDP_UINT16, &app->data_type);
555 	if (!dtype)
556 		goto fail;
557 
558 	role = sdp_data_alloc(SDP_UINT8, &app->role);
559 	if (!role)
560 		goto fail;
561 
562 	if (app->description) {
563 		desc = sdp_data_alloc(SDP_TEXT_STR8, app->description);
564 		if (!desc)
565 			goto fail;
566 	}
567 
568 	f_list = sdp_list_append(NULL, mdepid);
569 	if (!f_list)
570 		goto fail;
571 
572 	if (!sdp_list_append(f_list, dtype))
573 		goto fail;
574 
575 	if (!sdp_list_append(f_list, role))
576 		goto fail;
577 
578 	if (desc)
579 		if (!sdp_list_append(f_list, desc))
580 			goto fail;
581 
582 	return f_list;
583 
584 fail:
585 	if (f_list)
586 		sdp_list_free(f_list, NULL);
587 	if (mdepid)
588 		sdp_data_free(mdepid);
589 	if (dtype)
590 		sdp_data_free(dtype);
591 	if (role)
592 		sdp_data_free(role);
593 	if (desc)
594 		sdp_data_free(desc);
595 
596 	return NULL;
597 }
598 
register_features(struct hdp_application * app,sdp_list_t ** sup_features)599 static gboolean register_features(struct hdp_application *app,
600 						sdp_list_t **sup_features)
601 {
602 	sdp_list_t *hdp_feature;
603 
604 	hdp_feature = app_to_sdplist(app);
605 	if (!hdp_feature)
606 		goto fail;
607 
608 	if (!*sup_features) {
609 		*sup_features = sdp_list_append(NULL, hdp_feature);
610 		if (!*sup_features)
611 			goto fail;
612 	} else if (!sdp_list_append(*sup_features, hdp_feature)) {
613 		goto fail;
614 	}
615 
616 	return TRUE;
617 
618 fail:
619 	if (hdp_feature)
620 		sdp_list_free(hdp_feature, (sdp_free_func_t)sdp_data_free);
621 	return FALSE;
622 }
623 
free_hdp_list(void * list)624 static void free_hdp_list(void *list)
625 {
626 	sdp_list_t *hdp_list = list;
627 
628 	sdp_list_free(hdp_list, (sdp_free_func_t)sdp_data_free);
629 }
630 
register_service_sup_features(GSList * app_list,sdp_record_t * sdp_record)631 static gboolean register_service_sup_features(GSList *app_list,
632 						sdp_record_t *sdp_record)
633 {
634 	GSList *l;
635 	sdp_list_t *sup_features = NULL;
636 
637 	for (l = app_list; l; l = l->next) {
638 		if (!register_features(l->data, &sup_features))
639 			return FALSE;
640 	}
641 
642 	if (sdp_set_supp_feat(sdp_record, sup_features) < 0) {
643 		sdp_list_free(sup_features, free_hdp_list);
644 		return FALSE;
645 	}
646 
647 	return TRUE;
648 }
649 
register_data_exchange_spec(sdp_record_t * record)650 static gboolean register_data_exchange_spec(sdp_record_t *record)
651 {
652 	sdp_data_t *spec;
653 	uint8_t data_spec = DATA_EXCHANGE_SPEC_11073;
654 	/* As by now 11073 is the only supported we set it by default */
655 
656 	spec = sdp_data_alloc(SDP_UINT8, &data_spec);
657 	if (!spec)
658 		return FALSE;
659 
660 	if (sdp_attr_add(record, SDP_ATTR_DATA_EXCHANGE_SPEC, spec) < 0) {
661 		sdp_data_free(spec);
662 		return FALSE;
663 	}
664 
665 	return TRUE;
666 }
667 
register_mcap_features(sdp_record_t * sdp_record)668 static gboolean register_mcap_features(sdp_record_t *sdp_record)
669 {
670 	sdp_data_t *mcap_proc;
671 	uint8_t mcap_sup_proc = MCAP_SUP_PROC;
672 
673 	mcap_proc = sdp_data_alloc(SDP_UINT8, &mcap_sup_proc);
674 	if (!mcap_proc)
675 		return FALSE;
676 
677 	if (sdp_attr_add(sdp_record, SDP_ATTR_MCAP_SUPPORTED_PROCEDURES,
678 							mcap_proc) < 0) {
679 		sdp_data_free(mcap_proc);
680 		return FALSE;
681 	}
682 
683 	return TRUE;
684 }
685 
hdp_update_sdp_record(struct hdp_adapter * adapter,GSList * app_list)686 gboolean hdp_update_sdp_record(struct hdp_adapter *adapter, GSList *app_list)
687 {
688 	sdp_record_t *sdp_record;
689 	bdaddr_t addr;
690 
691 	if (adapter->sdp_handler)
692 		remove_record_from_server(adapter->sdp_handler);
693 
694 	if (!app_list) {
695 		adapter->sdp_handler = 0;
696 		return TRUE;
697 	}
698 
699 	sdp_record = sdp_record_alloc();
700 	if (!sdp_record)
701 		return FALSE;
702 
703 	if (adapter->sdp_handler)
704 		sdp_record->handle = adapter->sdp_handler;
705 	else
706 		sdp_record->handle = 0xffffffff; /* Set automatically */
707 
708 	if (is_app_role(app_list, HDP_SINK))
709 		set_sdp_services_uuid(sdp_record, HDP_SINK);
710 	if (is_app_role(app_list, HDP_SOURCE))
711 		set_sdp_services_uuid(sdp_record, HDP_SOURCE);
712 
713 	if (!register_service_protocols(adapter, sdp_record))
714 		goto fail;
715 	if (!register_service_profiles(sdp_record))
716 		goto fail;
717 	if (!register_service_additional_protocols(adapter, sdp_record))
718 		goto fail;
719 
720 	sdp_set_info_attr(sdp_record, HDP_SERVICE_NAME, HDP_SERVICE_PROVIDER,
721 							HDP_SERVICE_DSC);
722 	if (!register_service_sup_features(app_list, sdp_record))
723 		goto fail;
724 	if (!register_data_exchange_spec(sdp_record))
725 		goto fail;
726 
727 	register_mcap_features(sdp_record);
728 
729 	if (sdp_set_record_state(sdp_record, adapter->record_state++))
730 		goto fail;
731 
732 	adapter_get_address(adapter->btd_adapter, &addr);
733 
734 	if (add_record_to_server(&addr, sdp_record) < 0)
735 		goto fail;
736 	adapter->sdp_handler = sdp_record->handle;
737 	return TRUE;
738 
739 fail:
740 	if (sdp_record)
741 		sdp_record_free(sdp_record);
742 	return FALSE;
743 }
744 
check_role(uint8_t rec_role,uint8_t app_role)745 static gboolean check_role(uint8_t rec_role, uint8_t app_role)
746 {
747 	if ((rec_role == HDP_SINK && app_role == HDP_SOURCE) ||
748 			(rec_role == HDP_SOURCE && app_role == HDP_SINK))
749 		return TRUE;
750 
751 	return FALSE;
752 }
753 
get_mdep_from_rec(const sdp_record_t * rec,uint8_t role,uint16_t d_type,uint8_t * mdep,char ** desc)754 static gboolean get_mdep_from_rec(const sdp_record_t *rec, uint8_t role,
755 				uint16_t d_type, uint8_t *mdep, char **desc)
756 {
757 	sdp_data_t *list, *feat;
758 
759 	if (!desc && !mdep)
760 		return TRUE;
761 
762 	list = sdp_data_get(rec, SDP_ATTR_SUPPORTED_FEATURES_LIST);
763 
764 	if (list->dtd != SDP_SEQ8 && list->dtd != SDP_SEQ16 &&
765 							list->dtd != SDP_SEQ32)
766 		return FALSE;
767 
768 	for (feat = list->val.dataseq; feat; feat = feat->next) {
769 		sdp_data_t *data_type, *mdepid, *role_t, *desc_t;
770 
771 		if (feat->dtd != SDP_SEQ8 && feat->dtd != SDP_SEQ16 &&
772 						feat->dtd != SDP_SEQ32)
773 			continue;
774 
775 		mdepid = feat->val.dataseq;
776 		if (!mdepid)
777 			continue;
778 
779 		data_type = mdepid->next;
780 		if (!data_type)
781 			continue;
782 
783 		role_t = data_type->next;
784 		if (!role_t)
785 			continue;
786 
787 		desc_t = role_t->next;
788 
789 		if (data_type->dtd != SDP_UINT16 || mdepid->dtd != SDP_UINT8 ||
790 						role_t->dtd != SDP_UINT8)
791 			continue;
792 
793 		if (data_type->val.uint16 != d_type ||
794 					!check_role(role_t->val.uint8, role))
795 			continue;
796 
797 		if (mdep)
798 			*mdep = mdepid->val.uint8;
799 
800 		if (desc  && desc_t && (desc_t->dtd == SDP_TEXT_STR8 ||
801 					desc_t->dtd == SDP_TEXT_STR16  ||
802 					desc_t->dtd == SDP_TEXT_STR32))
803 			*desc = g_strdup(desc_t->val.str);
804 
805 		return TRUE;
806 	}
807 
808 	return FALSE;
809 }
810 
get_mdep_cb(sdp_list_t * recs,int err,gpointer user_data)811 static void get_mdep_cb(sdp_list_t *recs, int err, gpointer user_data)
812 {
813 	struct get_mdep_data *mdep_data = user_data;
814 	GError *gerr = NULL;
815 	uint8_t mdep;
816 
817 	if (err || !recs) {
818 		g_set_error(&gerr, HDP_ERROR, HDP_CONNECTION_ERROR,
819 					"Error getting remote SDP records");
820 		mdep_data->func(0, mdep_data->data, gerr);
821 		g_error_free(gerr);
822 		return;
823 	}
824 
825 	if (!get_mdep_from_rec(recs->data, mdep_data->app->role,
826 				mdep_data->app->data_type, &mdep, NULL)) {
827 		g_set_error(&gerr, HDP_ERROR, HDP_CONNECTION_ERROR,
828 					"No matching MDEP found");
829 		mdep_data->func(0, mdep_data->data, gerr);
830 		g_error_free(gerr);
831 		return;
832 	}
833 
834 	mdep_data->func(mdep, mdep_data->data, NULL);
835 }
836 
free_mdep_data(gpointer data)837 static void free_mdep_data(gpointer data)
838 {
839 	struct get_mdep_data *mdep_data = data;
840 
841 	if (mdep_data->destroy)
842 		mdep_data->destroy(mdep_data->data);
843 	hdp_application_unref(mdep_data->app);
844 
845 	g_free(mdep_data);
846 }
847 
hdp_get_mdep(struct hdp_device * device,struct hdp_application * app,hdp_continue_mdep_f func,gpointer data,GDestroyNotify destroy,GError ** err)848 gboolean hdp_get_mdep(struct hdp_device *device, struct hdp_application *app,
849 				hdp_continue_mdep_f func, gpointer data,
850 				GDestroyNotify destroy, GError **err)
851 {
852 	struct get_mdep_data *mdep_data;
853 	bdaddr_t dst, src;
854 	uuid_t uuid;
855 
856 	device_get_address(device->dev, &dst);
857 	adapter_get_address(device_get_adapter(device->dev), &src);
858 
859 	mdep_data = g_new0(struct get_mdep_data, 1);
860 	mdep_data->app = hdp_application_ref(app);
861 	mdep_data->func = func;
862 	mdep_data->data = data;
863 	mdep_data->destroy = destroy;
864 
865 	bt_string2uuid(&uuid, HDP_UUID);
866 	if (bt_search_service(&src, &dst, &uuid, get_mdep_cb, mdep_data,
867 							free_mdep_data)) {
868 		g_set_error(err, HDP_ERROR, HDP_CONNECTION_ERROR,
869 						"Can't get remote SDP record");
870 		g_free(mdep_data);
871 		return FALSE;
872 	}
873 
874 	return TRUE;
875 }
876 
get_prot_desc_entry(sdp_data_t * entry,int type,guint16 * val)877 static gboolean get_prot_desc_entry(sdp_data_t *entry, int type, guint16 *val)
878 {
879 	sdp_data_t *iter;
880 	int proto;
881 
882 	if (!entry || (entry->dtd != SDP_SEQ8 && entry->dtd != SDP_SEQ16 &&
883 						entry->dtd != SDP_SEQ32))
884 		return FALSE;
885 
886 	iter = entry->val.dataseq;
887 	if (!(iter->dtd & SDP_UUID_UNSPEC))
888 		return FALSE;
889 
890 	proto = sdp_uuid_to_proto(&iter->val.uuid);
891 	if (proto != type)
892 		return FALSE;
893 
894 	if (!val)
895 		return TRUE;
896 
897 	iter = iter->next;
898 	if (iter->dtd != SDP_UINT16)
899 		return FALSE;
900 
901 	*val = iter->val.uint16;
902 
903 	return TRUE;
904 }
905 
hdp_get_prot_desc_list(const sdp_record_t * rec,guint16 * psm,guint16 * version)906 static gboolean hdp_get_prot_desc_list(const sdp_record_t *rec, guint16 *psm,
907 							guint16 *version)
908 {
909 	sdp_data_t *pdl, *p0, *p1;
910 
911 	if (!psm && !version)
912 		return TRUE;
913 
914 	pdl = sdp_data_get(rec, SDP_ATTR_PROTO_DESC_LIST);
915 	if (pdl->dtd != SDP_SEQ8 && pdl->dtd != SDP_SEQ16 &&
916 							pdl->dtd != SDP_SEQ32)
917 		return FALSE;
918 
919 	p0 = pdl->val.dataseq;
920 	if (!get_prot_desc_entry(p0, L2CAP_UUID, psm))
921 		return FALSE;
922 
923 	p1 = p0->next;
924 	if (!get_prot_desc_entry(p1, MCAP_CTRL_UUID, version))
925 		return FALSE;
926 
927 	return TRUE;
928 }
929 
hdp_get_add_prot_desc_list(const sdp_record_t * rec,guint16 * psm)930 static gboolean hdp_get_add_prot_desc_list(const sdp_record_t *rec,
931 								guint16 *psm)
932 {
933 	sdp_data_t *pdl, *p0, *p1;
934 
935 	if (!psm)
936 		return TRUE;
937 
938 	pdl = sdp_data_get(rec, SDP_ATTR_ADD_PROTO_DESC_LIST);
939 	if (pdl->dtd != SDP_SEQ8)
940 		return FALSE;
941 	pdl = pdl->val.dataseq;
942 	if (pdl->dtd != SDP_SEQ8)
943 		return FALSE;
944 
945 	p0 = pdl->val.dataseq;
946 
947 	if (!get_prot_desc_entry(p0, L2CAP_UUID, psm))
948 		return FALSE;
949 	p1 = p0->next;
950 	if (!get_prot_desc_entry(p1, MCAP_DATA_UUID, NULL))
951 		return FALSE;
952 
953 	return TRUE;
954 }
955 
get_ccpsm(sdp_list_t * recs,uint16_t * ccpsm)956 static gboolean get_ccpsm(sdp_list_t *recs, uint16_t *ccpsm)
957 {
958 	sdp_list_t *l;
959 
960 	for (l = recs; l; l = l->next) {
961 		sdp_record_t *rec = l->data;
962 
963 		if (hdp_get_prot_desc_list(rec, ccpsm, NULL))
964 			return TRUE;
965 	}
966 
967 	return FALSE;
968 }
969 
get_dcpsm(sdp_list_t * recs,uint16_t * dcpsm)970 static gboolean get_dcpsm(sdp_list_t *recs, uint16_t *dcpsm)
971 {
972 	sdp_list_t *l;
973 
974 	for (l = recs; l; l = l->next) {
975 		sdp_record_t *rec = l->data;
976 
977 		if (hdp_get_add_prot_desc_list(rec, dcpsm))
978 			return TRUE;
979 	}
980 
981 	return FALSE;
982 }
983 
con_mcl_data_unref(struct conn_mcl_data * conn_data)984 static void con_mcl_data_unref(struct conn_mcl_data *conn_data)
985 {
986 	if (!conn_data)
987 		return;
988 
989 	if (--conn_data->refs > 0)
990 		return;
991 
992 	if (conn_data->destroy)
993 		conn_data->destroy(conn_data->data);
994 
995 	health_device_unref(conn_data->dev);
996 	g_free(conn_data);
997 }
998 
destroy_con_mcl_data(gpointer data)999 static void destroy_con_mcl_data(gpointer data)
1000 {
1001 	con_mcl_data_unref(data);
1002 }
1003 
con_mcl_data_ref(struct conn_mcl_data * conn_data)1004 static struct conn_mcl_data *con_mcl_data_ref(struct conn_mcl_data *conn_data)
1005 {
1006 	if (!conn_data)
1007 		return NULL;
1008 
1009 	conn_data->refs++;
1010 	return conn_data;
1011 }
1012 
create_mcl_cb(struct mcap_mcl * mcl,GError * err,gpointer data)1013 static void create_mcl_cb(struct mcap_mcl *mcl, GError *err, gpointer data)
1014 {
1015 	struct conn_mcl_data *conn_data = data;
1016 	struct hdp_device *device = conn_data->dev;
1017 	GError *gerr = NULL;
1018 
1019 	if (err) {
1020 		conn_data->func(conn_data->data, err);
1021 		return;
1022 	}
1023 
1024 	if (!device->mcl)
1025 		device->mcl = mcap_mcl_ref(mcl);
1026 	device->mcl_conn = TRUE;
1027 
1028 	hdp_set_mcl_cb(device, &gerr);
1029 
1030 	conn_data->func(conn_data->data, gerr);
1031 	if (gerr)
1032 		g_error_free(gerr);
1033 }
1034 
search_cb(sdp_list_t * recs,int err,gpointer user_data)1035 static void search_cb(sdp_list_t *recs, int err, gpointer user_data)
1036 {
1037 	struct conn_mcl_data *conn_data = user_data;
1038 	GError *gerr = NULL;
1039 	bdaddr_t dst;
1040 	uint16_t ccpsm;
1041 
1042 	if (!conn_data->dev->hdp_adapter->mi) {
1043 		g_set_error(&gerr, HDP_ERROR, HDP_CONNECTION_ERROR,
1044 						"Mcap instance released");
1045 		goto fail;
1046 	}
1047 
1048 	if (err || !recs) {
1049 		g_set_error(&gerr, HDP_ERROR, HDP_CONNECTION_ERROR,
1050 					"Error getting remote SDP records");
1051 		goto fail;
1052 	}
1053 
1054 	if (!get_ccpsm(recs, &ccpsm)) {
1055 		g_set_error(&gerr, HDP_ERROR, HDP_CONNECTION_ERROR,
1056 				"Can't get remote PSM for control channel");
1057 		goto fail;
1058 	}
1059 
1060 	conn_data = con_mcl_data_ref(conn_data);
1061 
1062 	device_get_address(conn_data->dev->dev, &dst);
1063 	if (!mcap_create_mcl(conn_data->dev->hdp_adapter->mi, &dst, ccpsm,
1064 						create_mcl_cb, conn_data,
1065 						destroy_con_mcl_data, &gerr)) {
1066 		con_mcl_data_unref(conn_data);
1067 		goto fail;
1068 	}
1069 	return;
1070 fail:
1071 	conn_data->func(conn_data->data, gerr);
1072 	g_error_free(gerr);
1073 }
1074 
hdp_establish_mcl(struct hdp_device * device,hdp_continue_proc_f func,gpointer data,GDestroyNotify destroy,GError ** err)1075 gboolean hdp_establish_mcl(struct hdp_device *device,
1076 						hdp_continue_proc_f func,
1077 						gpointer data,
1078 						GDestroyNotify destroy,
1079 						GError **err)
1080 {
1081 	struct conn_mcl_data *conn_data;
1082 	bdaddr_t dst, src;
1083 	uuid_t uuid;
1084 
1085 	device_get_address(device->dev, &dst);
1086 	adapter_get_address(device_get_adapter(device->dev), &src);
1087 
1088 	conn_data = g_new0(struct conn_mcl_data, 1);
1089 	conn_data->refs = 1;
1090 	conn_data->func = func;
1091 	conn_data->data = data;
1092 	conn_data->destroy = destroy;
1093 	conn_data->dev = health_device_ref(device);
1094 
1095 	bt_string2uuid(&uuid, HDP_UUID);
1096 	if (bt_search_service(&src, &dst, &uuid, search_cb, conn_data,
1097 						destroy_con_mcl_data)) {
1098 		g_set_error(err, HDP_ERROR, HDP_CONNECTION_ERROR,
1099 						"Can't get remote SDP record");
1100 		g_free(conn_data);
1101 		return FALSE;
1102 	}
1103 
1104 	return TRUE;
1105 }
1106 
get_dcpsm_cb(sdp_list_t * recs,int err,gpointer data)1107 static void get_dcpsm_cb(sdp_list_t *recs, int err, gpointer data)
1108 {
1109 	struct get_dcpsm_data *dcpsm_data = data;
1110 	GError *gerr = NULL;
1111 	uint16_t dcpsm;
1112 
1113 	if (err || !recs) {
1114 		g_set_error(&gerr, HDP_ERROR, HDP_CONNECTION_ERROR,
1115 					"Error getting remote SDP records");
1116 		goto fail;
1117 	}
1118 
1119 	if (!get_dcpsm(recs, &dcpsm)) {
1120 		g_set_error(&gerr, HDP_ERROR, HDP_CONNECTION_ERROR,
1121 				"Can't get remote PSM for data channel");
1122 		goto fail;
1123 	}
1124 
1125 	dcpsm_data->func(dcpsm, dcpsm_data->data, NULL);
1126 	return;
1127 
1128 fail:
1129 	dcpsm_data->func(0, dcpsm_data->data, gerr);
1130 	g_error_free(gerr);
1131 }
1132 
free_dcpsm_data(gpointer data)1133 static void free_dcpsm_data(gpointer data)
1134 {
1135 	struct get_dcpsm_data *dcpsm_data = data;
1136 
1137 	if (!dcpsm_data)
1138 		return;
1139 
1140 	if (dcpsm_data->destroy)
1141 		dcpsm_data->destroy(dcpsm_data->data);
1142 
1143 	g_free(dcpsm_data);
1144 }
1145 
hdp_get_dcpsm(struct hdp_device * device,hdp_continue_dcpsm_f func,gpointer data,GDestroyNotify destroy,GError ** err)1146 gboolean hdp_get_dcpsm(struct hdp_device *device, hdp_continue_dcpsm_f func,
1147 							gpointer data,
1148 							GDestroyNotify destroy,
1149 							GError **err)
1150 {
1151 	struct get_dcpsm_data *dcpsm_data;
1152 	bdaddr_t dst, src;
1153 	uuid_t uuid;
1154 
1155 	device_get_address(device->dev, &dst);
1156 	adapter_get_address(device_get_adapter(device->dev), &src);
1157 
1158 	dcpsm_data = g_new0(struct get_dcpsm_data, 1);
1159 	dcpsm_data->func = func;
1160 	dcpsm_data->data = data;
1161 	dcpsm_data->destroy = destroy;
1162 
1163 	bt_string2uuid(&uuid, HDP_UUID);
1164 	if (bt_search_service(&src, &dst, &uuid, get_dcpsm_cb, dcpsm_data,
1165 							free_dcpsm_data)) {
1166 		g_set_error(err, HDP_ERROR, HDP_CONNECTION_ERROR,
1167 						"Can't get remote SDP record");
1168 		g_free(dcpsm_data);
1169 		return FALSE;
1170 	}
1171 
1172 	return TRUE;
1173 }
1174 
hdp_free_application(struct hdp_application * app)1175 static void hdp_free_application(struct hdp_application *app)
1176 {
1177 	if (app->dbus_watcher)
1178 		g_dbus_remove_watch(app->conn, app->dbus_watcher);
1179 
1180 	if (app->conn)
1181 		dbus_connection_unref(app->conn);
1182 	g_free(app->oname);
1183 	g_free(app->description);
1184 	g_free(app->path);
1185 	g_free(app);
1186 }
1187 
hdp_application_ref(struct hdp_application * app)1188 struct hdp_application *hdp_application_ref(struct hdp_application *app)
1189 {
1190 	if (!app)
1191 		return NULL;
1192 
1193 	app->ref++;
1194 
1195 	DBG("health_application_ref(%p): ref=%d", app, app->ref);
1196 	return app;
1197 }
1198 
hdp_application_unref(struct hdp_application * app)1199 void hdp_application_unref(struct hdp_application *app)
1200 {
1201 	if (!app)
1202 		return;
1203 
1204 	app->ref --;
1205 
1206 	DBG("health_application_unref(%p): ref=%d", app, app->ref);
1207 	if (app->ref > 0)
1208 		return;
1209 
1210 	hdp_free_application(app);
1211 }
1212