3 * BlueZ - Bluetooth protocol stack for Linux
5 * Copyright (C) 2010 GSyC/LibreSoft, Universidad Rey Juan Carlos.
7 * Santiago Carot Nemesio <sancane at gmail.com>
8 * Jose Antonio Santos-Cadenas <santoscadenas at gmail.com>
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.
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.
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
31 #include <hdp_types.h>
38 #include <glib-helper.h>
45 typedef gboolean (*parse_item_f)(DBusMessageIter *iter, gpointer user_data,
48 struct dict_entry_func {
53 struct get_mdep_data {
54 struct hdp_application *app;
56 hdp_continue_mdep_f func;
57 GDestroyNotify destroy;
60 struct conn_mcl_data {
63 hdp_continue_proc_f func;
64 GDestroyNotify destroy;
65 struct hdp_device *dev;
68 struct get_dcpsm_data {
70 hdp_continue_dcpsm_f func;
71 GDestroyNotify destroy;
74 static gboolean parse_dict_entry(struct dict_entry_func dict_context[],
75 DBusMessageIter *iter,
79 DBusMessageIter entry;
82 struct dict_entry_func df;
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");
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);
100 g_set_error(err, HDP_ERROR, HDP_DIC_ENTRY_PARSE_ERROR,
101 "No function found for parsing value for key %s", key);
105 static gboolean parse_dict(struct dict_entry_func dict_context[],
106 DBusMessageIter *iter,
111 DBusMessageIter dict;
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");
120 dbus_message_iter_recurse(iter, &dict);
121 while ((ctype = dbus_message_iter_get_arg_type(&dict)) !=
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");
130 /* Start parsing entry */
131 if (!parse_dict_entry(dict_context, &dict, err,
134 /* Finish entry parsing */
136 dbus_message_iter_next(&dict);
142 static gboolean parse_data_type(DBusMessageIter *iter, gpointer data,
145 struct hdp_application *app = data;
146 DBusMessageIter *value;
149 ctype = dbus_message_iter_get_arg_type(iter);
151 if (ctype == DBUS_TYPE_VARIANT) {
152 DBusMessageIter variant;
154 /* Get value inside the variable */
155 dbus_message_iter_recurse(iter, &variant);
156 ctype = dbus_message_iter_get_arg_type(&variant);
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");
166 dbus_message_iter_get_basic(value, &app->data_type);
167 app->data_type_set = TRUE;
171 static gboolean parse_role(DBusMessageIter *iter, gpointer data, GError **err)
173 struct hdp_application *app = data;
174 DBusMessageIter *string;
178 ctype = dbus_message_iter_get_arg_type(iter);
179 if (ctype == DBUS_TYPE_VARIANT) {
180 DBusMessageIter value;
182 /* Get value inside the variable */
183 dbus_message_iter_recurse(iter, &value);
184 ctype = dbus_message_iter_get_arg_type(&value);
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");
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;
202 g_set_error(err, HDP_ERROR, HDP_UNSPECIFIED_ERROR,
203 "Role value should be \"source\" or \"sink\"");
207 app->role_set = TRUE;
212 static gboolean parse_desc(DBusMessageIter *iter, gpointer data, GError **err)
214 struct hdp_application *app = data;
215 DBusMessageIter *string;
219 ctype = dbus_message_iter_get_arg_type(iter);
220 if (ctype == DBUS_TYPE_VARIANT) {
221 DBusMessageIter variant;
223 /* Get value inside the variable */
224 dbus_message_iter_recurse(iter, &variant);
225 ctype = dbus_message_iter_get_arg_type(&variant);
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");
237 dbus_message_iter_get_basic(string, &desc);
238 app->description = g_strdup(desc);
242 static gboolean parse_chan_type(DBusMessageIter *iter, gpointer data,
245 struct hdp_application *app = data;
246 DBusMessageIter *value;
250 ctype = dbus_message_iter_get_arg_type(iter);
252 if (ctype == DBUS_TYPE_VARIANT) {
253 DBusMessageIter variant;
255 /* Get value inside the variable */
256 dbus_message_iter_recurse(iter, &variant);
257 ctype = dbus_message_iter_get_arg_type(&variant);
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");
267 dbus_message_iter_get_basic(value, &chan_type);
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;
274 g_set_error(err, HDP_ERROR, HDP_DIC_ENTRY_PARSE_ERROR,
275 "Invalid value for data type");
279 app->chan_type_set = TRUE;
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},
292 struct hdp_application *hdp_get_app_config(DBusMessageIter *iter, GError **err)
294 struct hdp_application *app;
296 app = g_new0(struct hdp_application, 1);
298 if (!parse_dict(dict_parser, iter, err, app))
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");
308 hdp_application_unref(app);
312 static gboolean is_app_role(GSList *app_list, HdpRole role)
316 for (l = app_list; l; l = l->next) {
317 struct hdp_application *app = l->data;
319 if (app->role == role)
326 static gboolean set_sdp_services_uuid(sdp_record_t *record, HdpRole role)
328 uuid_t svc_uuid_source, svc_uuid_sink;
329 sdp_list_t *svc_list = NULL;
331 sdp_uuid16_create(&svc_uuid_sink, HDP_SINK_SVCLASS_ID);
332 sdp_uuid16_create(&svc_uuid_source, HDP_SOURCE_SVCLASS_ID);
334 sdp_get_service_classes(record, &svc_list);
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);
344 if (sdp_set_service_classes(record, svc_list) < 0) {
345 sdp_list_free(svc_list, NULL);
349 sdp_list_free(svc_list, NULL);
354 static gboolean register_service_protocols(struct hdp_adapter *adapter,
355 sdp_record_t *sdp_record)
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;
364 /* set l2cap information */
365 sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
366 l2cap_list = sdp_list_append(NULL, &l2cap_uuid);
372 psm = sdp_data_alloc(SDP_UINT16, &adapter->ccpsm);
378 if (!sdp_list_append(l2cap_list, psm)) {
383 proto_list = sdp_list_append(NULL, l2cap_list);
389 /* set mcap information */
390 sdp_uuid16_create(&mcap_c_uuid, MCAP_CTRL_UUID);
391 mcap_list = sdp_list_append(NULL, &mcap_c_uuid);
397 mcap_ver = sdp_data_alloc(SDP_UINT16, &version);
403 if (!sdp_list_append(mcap_list, mcap_ver)) {
408 if (!sdp_list_append(proto_list, mcap_list)) {
413 /* attach protocol information to service record */
414 access_proto_list = sdp_list_append(NULL, proto_list);
415 if (!access_proto_list) {
420 if (sdp_set_access_protos(sdp_record, access_proto_list) < 0) {
428 sdp_list_free(l2cap_list, NULL);
430 sdp_list_free(mcap_list, NULL);
432 sdp_list_free(proto_list, NULL);
433 if (access_proto_list)
434 sdp_list_free(access_proto_list, NULL);
438 sdp_data_free(mcap_ver);
443 static gboolean register_service_profiles(sdp_record_t *sdp_record)
446 sdp_list_t *profile_list;
447 sdp_profile_desc_t hdp_profile;
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);
456 /* set profile descriptor list */
457 if (sdp_set_profile_descs(sdp_record, profile_list) < 0)
462 sdp_list_free(profile_list, NULL);
467 static gboolean register_service_additional_protocols(
468 struct hdp_adapter *adapter,
469 sdp_record_t *sdp_record)
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;
477 /* set l2cap information */
478 sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
479 l2cap_list = sdp_list_append(NULL, &l2cap_uuid);
485 psm = sdp_data_alloc(SDP_UINT16, &adapter->dcpsm);
491 if (!sdp_list_append(l2cap_list, psm)) {
496 proto_list = sdp_list_append(NULL, l2cap_list);
502 /* set mcap information */
503 sdp_uuid16_create(&mcap_d_uuid, MCAP_DATA_UUID);
504 mcap_list = sdp_list_append(NULL, &mcap_d_uuid);
510 if (!sdp_list_append(proto_list, mcap_list)) {
515 /* attach protocol information to service record */
516 access_proto_list = sdp_list_append(NULL, proto_list);
517 if (!access_proto_list) {
522 if (sdp_set_add_access_protos(sdp_record, access_proto_list) < 0)
529 sdp_list_free(l2cap_list, NULL);
531 sdp_list_free(mcap_list, NULL);
533 sdp_list_free(proto_list, NULL);
534 if (access_proto_list)
535 sdp_list_free(access_proto_list, NULL);
542 static sdp_list_t *app_to_sdplist(struct hdp_application *app)
548 sdp_list_t *f_list = NULL;
550 mdepid = sdp_data_alloc(SDP_UINT8, &app->id);
554 dtype = sdp_data_alloc(SDP_UINT16, &app->data_type);
558 role = sdp_data_alloc(SDP_UINT8, &app->role);
562 if (app->description) {
563 desc = sdp_data_alloc(SDP_TEXT_STR8, app->description);
568 f_list = sdp_list_append(NULL, mdepid);
572 if (!sdp_list_append(f_list, dtype))
575 if (!sdp_list_append(f_list, role))
579 if (!sdp_list_append(f_list, desc))
586 sdp_list_free(f_list, NULL);
588 sdp_data_free(mdepid);
590 sdp_data_free(dtype);
599 static gboolean register_features(struct hdp_application *app,
600 sdp_list_t **sup_features)
602 sdp_list_t *hdp_feature;
604 hdp_feature = app_to_sdplist(app);
608 if (!*sup_features) {
609 *sup_features = sdp_list_append(NULL, hdp_feature);
612 } else if (!sdp_list_append(*sup_features, hdp_feature)) {
620 sdp_list_free(hdp_feature, (sdp_free_func_t)sdp_data_free);
624 static void free_hdp_list(void *list)
626 sdp_list_t *hdp_list = list;
628 sdp_list_free(hdp_list, (sdp_free_func_t)sdp_data_free);
631 static gboolean register_service_sup_features(GSList *app_list,
632 sdp_record_t *sdp_record)
635 sdp_list_t *sup_features = NULL;
637 for (l = app_list; l; l = l->next) {
638 if (!register_features(l->data, &sup_features))
642 if (sdp_set_supp_feat(sdp_record, sup_features) < 0) {
643 sdp_list_free(sup_features, free_hdp_list);
650 static gboolean register_data_exchange_spec(sdp_record_t *record)
653 uint8_t data_spec = DATA_EXCHANGE_SPEC_11073;
654 /* As by now 11073 is the only supported we set it by default */
656 spec = sdp_data_alloc(SDP_UINT8, &data_spec);
660 if (sdp_attr_add(record, SDP_ATTR_DATA_EXCHANGE_SPEC, spec) < 0) {
668 static gboolean register_mcap_features(sdp_record_t *sdp_record)
670 sdp_data_t *mcap_proc;
671 uint8_t mcap_sup_proc = MCAP_SUP_PROC;
673 mcap_proc = sdp_data_alloc(SDP_UINT8, &mcap_sup_proc);
677 if (sdp_attr_add(sdp_record, SDP_ATTR_MCAP_SUPPORTED_PROCEDURES,
679 sdp_data_free(mcap_proc);
686 gboolean hdp_update_sdp_record(struct hdp_adapter *adapter, GSList *app_list)
688 sdp_record_t *sdp_record;
691 if (adapter->sdp_handler)
692 remove_record_from_server(adapter->sdp_handler);
695 adapter->sdp_handler = 0;
699 sdp_record = sdp_record_alloc();
703 if (adapter->sdp_handler)
704 sdp_record->handle = adapter->sdp_handler;
706 sdp_record->handle = 0xffffffff; /* Set automatically */
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);
713 if (!register_service_protocols(adapter, sdp_record))
715 if (!register_service_profiles(sdp_record))
717 if (!register_service_additional_protocols(adapter, sdp_record))
720 sdp_set_info_attr(sdp_record, HDP_SERVICE_NAME, HDP_SERVICE_PROVIDER,
722 if (!register_service_sup_features(app_list, sdp_record))
724 if (!register_data_exchange_spec(sdp_record))
727 register_mcap_features(sdp_record);
729 if (sdp_set_record_state(sdp_record, adapter->record_state++))
732 adapter_get_address(adapter->btd_adapter, &addr);
734 if (add_record_to_server(&addr, sdp_record) < 0)
736 adapter->sdp_handler = sdp_record->handle;
741 sdp_record_free(sdp_record);
745 static gboolean check_role(uint8_t rec_role, uint8_t app_role)
747 if ((rec_role == HDP_SINK && app_role == HDP_SOURCE) ||
748 (rec_role == HDP_SOURCE && app_role == HDP_SINK))
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)
757 sdp_data_t *list, *feat;
762 list = sdp_data_get(rec, SDP_ATTR_SUPPORTED_FEATURES_LIST);
764 if (list->dtd != SDP_SEQ8 && list->dtd != SDP_SEQ16 &&
765 list->dtd != SDP_SEQ32)
768 for (feat = list->val.dataseq; feat; feat = feat->next) {
769 sdp_data_t *data_type, *mdepid, *role_t, *desc_t;
771 if (feat->dtd != SDP_SEQ8 && feat->dtd != SDP_SEQ16 &&
772 feat->dtd != SDP_SEQ32)
775 mdepid = feat->val.dataseq;
779 data_type = mdepid->next;
783 role_t = data_type->next;
787 desc_t = role_t->next;
789 if (data_type->dtd != SDP_UINT16 || mdepid->dtd != SDP_UINT8 ||
790 role_t->dtd != SDP_UINT8)
793 if (data_type->val.uint16 != d_type ||
794 !check_role(role_t->val.uint8, role))
798 *mdep = mdepid->val.uint8;
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);
811 static void get_mdep_cb(sdp_list_t *recs, int err, gpointer user_data)
813 struct get_mdep_data *mdep_data = user_data;
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);
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);
834 mdep_data->func(mdep, mdep_data->data, NULL);
837 static void free_mdep_data(gpointer data)
839 struct get_mdep_data *mdep_data = data;
841 if (mdep_data->destroy)
842 mdep_data->destroy(mdep_data->data);
843 hdp_application_unref(mdep_data->app);
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)
852 struct get_mdep_data *mdep_data;
856 device_get_address(device->dev, &dst);
857 adapter_get_address(device_get_adapter(device->dev), &src);
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;
865 bt_string2uuid(&uuid, HDP_UUID);
866 if (bt_search_service(&src, &dst, &uuid, get_mdep_cb, mdep_data,
868 g_set_error(err, HDP_ERROR, HDP_CONNECTION_ERROR,
869 "Can't get remote SDP record");
877 static gboolean get_prot_desc_entry(sdp_data_t *entry, int type, guint16 *val)
882 if (!entry || (entry->dtd != SDP_SEQ8 && entry->dtd != SDP_SEQ16 &&
883 entry->dtd != SDP_SEQ32))
886 iter = entry->val.dataseq;
887 if (!(iter->dtd & SDP_UUID_UNSPEC))
890 proto = sdp_uuid_to_proto(&iter->val.uuid);
898 if (iter->dtd != SDP_UINT16)
901 *val = iter->val.uint16;
906 static gboolean hdp_get_prot_desc_list(const sdp_record_t *rec, guint16 *psm,
909 sdp_data_t *pdl, *p0, *p1;
911 if (!psm && !version)
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)
919 p0 = pdl->val.dataseq;
920 if (!get_prot_desc_entry(p0, L2CAP_UUID, psm))
924 if (!get_prot_desc_entry(p1, MCAP_CTRL_UUID, version))
930 static gboolean hdp_get_add_prot_desc_list(const sdp_record_t *rec,
933 sdp_data_t *pdl, *p0, *p1;
938 pdl = sdp_data_get(rec, SDP_ATTR_ADD_PROTO_DESC_LIST);
939 if (pdl->dtd != SDP_SEQ8)
941 pdl = pdl->val.dataseq;
942 if (pdl->dtd != SDP_SEQ8)
945 p0 = pdl->val.dataseq;
947 if (!get_prot_desc_entry(p0, L2CAP_UUID, psm))
950 if (!get_prot_desc_entry(p1, MCAP_DATA_UUID, NULL))
956 static gboolean get_ccpsm(sdp_list_t *recs, uint16_t *ccpsm)
960 for (l = recs; l; l = l->next) {
961 sdp_record_t *rec = l->data;
963 if (hdp_get_prot_desc_list(rec, ccpsm, NULL))
970 static gboolean get_dcpsm(sdp_list_t *recs, uint16_t *dcpsm)
974 for (l = recs; l; l = l->next) {
975 sdp_record_t *rec = l->data;
977 if (hdp_get_add_prot_desc_list(rec, dcpsm))
984 static void con_mcl_data_unref(struct conn_mcl_data *conn_data)
989 if (--conn_data->refs > 0)
992 if (conn_data->destroy)
993 conn_data->destroy(conn_data->data);
995 health_device_unref(conn_data->dev);
999 static void destroy_con_mcl_data(gpointer data)
1001 con_mcl_data_unref(data);
1004 static struct conn_mcl_data *con_mcl_data_ref(struct conn_mcl_data *conn_data)
1013 static void create_mcl_cb(struct mcap_mcl *mcl, GError *err, gpointer data)
1015 struct conn_mcl_data *conn_data = data;
1016 struct hdp_device *device = conn_data->dev;
1017 GError *gerr = NULL;
1020 conn_data->func(conn_data->data, err);
1025 device->mcl = mcap_mcl_ref(mcl);
1026 device->mcl_conn = TRUE;
1028 hdp_set_mcl_cb(device, &gerr);
1030 conn_data->func(conn_data->data, gerr);
1035 static void search_cb(sdp_list_t *recs, int err, gpointer user_data)
1037 struct conn_mcl_data *conn_data = user_data;
1038 GError *gerr = NULL;
1042 if (!conn_data->dev->hdp_adapter->mi) {
1043 g_set_error(&gerr, HDP_ERROR, HDP_CONNECTION_ERROR,
1044 "Mcap instance released");
1049 g_set_error(&gerr, HDP_ERROR, HDP_CONNECTION_ERROR,
1050 "Error getting remote SDP records");
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");
1060 conn_data = con_mcl_data_ref(conn_data);
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);
1071 conn_data->func(conn_data->data, gerr);
1075 gboolean hdp_establish_mcl(struct hdp_device *device,
1076 hdp_continue_proc_f func,
1078 GDestroyNotify destroy,
1081 struct conn_mcl_data *conn_data;
1085 device_get_address(device->dev, &dst);
1086 adapter_get_address(device_get_adapter(device->dev), &src);
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);
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");
1107 static void get_dcpsm_cb(sdp_list_t *recs, int err, gpointer data)
1109 struct get_dcpsm_data *dcpsm_data = data;
1110 GError *gerr = NULL;
1114 g_set_error(&gerr, HDP_ERROR, HDP_CONNECTION_ERROR,
1115 "Error getting remote SDP records");
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");
1125 dcpsm_data->func(dcpsm, dcpsm_data->data, NULL);
1129 dcpsm_data->func(0, dcpsm_data->data, gerr);
1133 static void free_dcpsm_data(gpointer data)
1135 struct get_dcpsm_data *dcpsm_data = data;
1140 if (dcpsm_data->destroy)
1141 dcpsm_data->destroy(dcpsm_data->data);
1146 gboolean hdp_get_dcpsm(struct hdp_device *device, hdp_continue_dcpsm_f func,
1148 GDestroyNotify destroy,
1151 struct get_dcpsm_data *dcpsm_data;
1155 device_get_address(device->dev, &dst);
1156 adapter_get_address(device_get_adapter(device->dev), &src);
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;
1163 bt_string2uuid(&uuid, HDP_UUID);
1164 if (bt_search_service(&src, &dst, &uuid, get_dcpsm_cb, dcpsm_data,
1166 g_set_error(err, HDP_ERROR, HDP_CONNECTION_ERROR,
1167 "Can't get remote SDP record");
1175 static void hdp_free_application(struct hdp_application *app)
1177 if (app->dbus_watcher)
1178 g_dbus_remove_watch(app->conn, app->dbus_watcher);
1181 dbus_connection_unref(app->conn);
1183 g_free(app->description);
1188 struct hdp_application *hdp_application_ref(struct hdp_application *app)
1195 DBG("health_application_ref(%p): ref=%d", app, app->ref);
1199 void hdp_application_unref(struct hdp_application *app)
1206 DBG("health_application_unref(%p): ref=%d", app, app->ref);
1210 hdp_free_application(app);