hdp_util.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. *
  4. * BlueZ - Bluetooth protocol stack for Linux
  5. *
  6. * Copyright (C) 2010 GSyC/LibreSoft, Universidad Rey Juan Carlos.
  7. *
  8. */
  9. #ifdef HAVE_CONFIG_H
  10. #include <config.h>
  11. #endif
  12. #define _GNU_SOURCE
  13. #include <stdint.h>
  14. #include <stdbool.h>
  15. #include <glib.h>
  16. #include "lib/bluetooth.h"
  17. #include "lib/sdp.h"
  18. #include "lib/sdp_lib.h"
  19. #include "lib/uuid.h"
  20. #include "gdbus/gdbus.h"
  21. #include "btio/btio.h"
  22. #include "src/adapter.h"
  23. #include "src/device.h"
  24. #include "src/sdpd.h"
  25. #include "src/sdp-client.h"
  26. #include "src/uuid-helper.h"
  27. #include "src/log.h"
  28. #include "src/dbus-common.h"
  29. #include "mcap.h"
  30. #include "hdp_types.h"
  31. #include "hdp.h"
  32. #include "hdp_util.h"
  33. typedef gboolean (*parse_item_f)(DBusMessageIter *iter, gpointer user_data,
  34. GError **err);
  35. struct dict_entry_func {
  36. char *key;
  37. parse_item_f func;
  38. };
  39. struct get_mdep_data {
  40. struct hdp_application *app;
  41. gpointer data;
  42. hdp_continue_mdep_f func;
  43. GDestroyNotify destroy;
  44. };
  45. struct conn_mcl_data {
  46. int refs;
  47. gpointer data;
  48. hdp_continue_proc_f func;
  49. GDestroyNotify destroy;
  50. struct hdp_device *dev;
  51. };
  52. struct get_dcpsm_data {
  53. gpointer data;
  54. hdp_continue_dcpsm_f func;
  55. GDestroyNotify destroy;
  56. };
  57. static gboolean parse_dict_entry(struct dict_entry_func dict_context[],
  58. DBusMessageIter *iter,
  59. GError **err,
  60. gpointer user_data)
  61. {
  62. DBusMessageIter entry;
  63. char *key;
  64. int ctype, i;
  65. struct dict_entry_func df;
  66. dbus_message_iter_recurse(iter, &entry);
  67. ctype = dbus_message_iter_get_arg_type(&entry);
  68. if (ctype != DBUS_TYPE_STRING) {
  69. g_set_error(err, HDP_ERROR, HDP_DIC_ENTRY_PARSE_ERROR,
  70. "Dictionary entries should have a string as key");
  71. return FALSE;
  72. }
  73. dbus_message_iter_get_basic(&entry, &key);
  74. dbus_message_iter_next(&entry);
  75. /* Find function and call it */
  76. for (i = 0, df = dict_context[0]; df.key; i++, df = dict_context[i]) {
  77. if (g_ascii_strcasecmp(df.key, key) == 0)
  78. return df.func(&entry, user_data, err);
  79. }
  80. g_set_error(err, HDP_ERROR, HDP_DIC_ENTRY_PARSE_ERROR,
  81. "No function found for parsing value for key %s", key);
  82. return FALSE;
  83. }
  84. static gboolean parse_dict(struct dict_entry_func dict_context[],
  85. DBusMessageIter *iter,
  86. GError **err,
  87. gpointer user_data)
  88. {
  89. int ctype;
  90. DBusMessageIter dict;
  91. ctype = dbus_message_iter_get_arg_type(iter);
  92. if (ctype != DBUS_TYPE_ARRAY) {
  93. g_set_error(err, HDP_ERROR, HDP_DIC_PARSE_ERROR,
  94. "Dictionary should be an array");
  95. return FALSE;
  96. }
  97. dbus_message_iter_recurse(iter, &dict);
  98. while ((ctype = dbus_message_iter_get_arg_type(&dict)) !=
  99. DBUS_TYPE_INVALID) {
  100. if (ctype != DBUS_TYPE_DICT_ENTRY) {
  101. g_set_error(err, HDP_ERROR, HDP_DIC_PARSE_ERROR,
  102. "Dictionary array should "
  103. "contain dict entries");
  104. return FALSE;
  105. }
  106. /* Start parsing entry */
  107. if (!parse_dict_entry(dict_context, &dict, err,
  108. user_data))
  109. return FALSE;
  110. /* Finish entry parsing */
  111. dbus_message_iter_next(&dict);
  112. }
  113. return TRUE;
  114. }
  115. static gboolean parse_data_type(DBusMessageIter *iter, gpointer data,
  116. GError **err)
  117. {
  118. struct hdp_application *app = data;
  119. DBusMessageIter *value;
  120. DBusMessageIter variant;
  121. int ctype;
  122. ctype = dbus_message_iter_get_arg_type(iter);
  123. value = iter;
  124. if (ctype == DBUS_TYPE_VARIANT) {
  125. /* Get value inside the variable */
  126. dbus_message_iter_recurse(iter, &variant);
  127. ctype = dbus_message_iter_get_arg_type(&variant);
  128. value = &variant;
  129. }
  130. if (ctype != DBUS_TYPE_UINT16) {
  131. g_set_error(err, HDP_ERROR, HDP_DIC_ENTRY_PARSE_ERROR,
  132. "Final value for data type should be uint16");
  133. return FALSE;
  134. }
  135. dbus_message_iter_get_basic(value, &app->data_type);
  136. app->data_type_set = TRUE;
  137. return TRUE;
  138. }
  139. static gboolean parse_role(DBusMessageIter *iter, gpointer data, GError **err)
  140. {
  141. struct hdp_application *app = data;
  142. DBusMessageIter *string;
  143. DBusMessageIter value;
  144. int ctype;
  145. const char *role;
  146. ctype = dbus_message_iter_get_arg_type(iter);
  147. if (ctype == DBUS_TYPE_VARIANT) {
  148. /* Get value inside the variable */
  149. dbus_message_iter_recurse(iter, &value);
  150. ctype = dbus_message_iter_get_arg_type(&value);
  151. string = &value;
  152. } else {
  153. string = iter;
  154. }
  155. if (ctype != DBUS_TYPE_STRING) {
  156. g_set_error(err, HDP_ERROR, HDP_UNSPECIFIED_ERROR,
  157. "Value data spec should be variable or string");
  158. return FALSE;
  159. }
  160. dbus_message_iter_get_basic(string, &role);
  161. if (g_ascii_strcasecmp(role, HDP_SINK_ROLE_AS_STRING) == 0) {
  162. app->role = HDP_SINK;
  163. } else if (g_ascii_strcasecmp(role, HDP_SOURCE_ROLE_AS_STRING) == 0) {
  164. app->role = HDP_SOURCE;
  165. } else {
  166. g_set_error(err, HDP_ERROR, HDP_UNSPECIFIED_ERROR,
  167. "Role value should be \"source\" or \"sink\"");
  168. return FALSE;
  169. }
  170. app->role_set = TRUE;
  171. return TRUE;
  172. }
  173. static gboolean parse_desc(DBusMessageIter *iter, gpointer data, GError **err)
  174. {
  175. struct hdp_application *app = data;
  176. DBusMessageIter *string;
  177. DBusMessageIter variant;
  178. int ctype;
  179. const char *desc;
  180. ctype = dbus_message_iter_get_arg_type(iter);
  181. if (ctype == DBUS_TYPE_VARIANT) {
  182. /* Get value inside the variable */
  183. dbus_message_iter_recurse(iter, &variant);
  184. ctype = dbus_message_iter_get_arg_type(&variant);
  185. string = &variant;
  186. } else {
  187. string = iter;
  188. }
  189. if (ctype != DBUS_TYPE_STRING) {
  190. g_set_error(err, HDP_ERROR, HDP_DIC_ENTRY_PARSE_ERROR,
  191. "Value data spec should be variable or string");
  192. return FALSE;
  193. }
  194. dbus_message_iter_get_basic(string, &desc);
  195. app->description = g_strdup(desc);
  196. return TRUE;
  197. }
  198. static gboolean parse_chan_type(DBusMessageIter *iter, gpointer data,
  199. GError **err)
  200. {
  201. struct hdp_application *app = data;
  202. DBusMessageIter *value;
  203. DBusMessageIter variant;
  204. char *chan_type;
  205. int ctype;
  206. ctype = dbus_message_iter_get_arg_type(iter);
  207. value = iter;
  208. if (ctype == DBUS_TYPE_VARIANT) {
  209. /* Get value inside the variable */
  210. dbus_message_iter_recurse(iter, &variant);
  211. ctype = dbus_message_iter_get_arg_type(&variant);
  212. value = &variant;
  213. }
  214. if (ctype != DBUS_TYPE_STRING) {
  215. g_set_error(err, HDP_ERROR, HDP_DIC_ENTRY_PARSE_ERROR,
  216. "Final value for channel type should be an string");
  217. return FALSE;
  218. }
  219. dbus_message_iter_get_basic(value, &chan_type);
  220. if (g_ascii_strcasecmp("reliable", chan_type) == 0)
  221. app->chan_type = HDP_RELIABLE_DC;
  222. else if (g_ascii_strcasecmp("streaming", chan_type) == 0)
  223. app->chan_type = HDP_STREAMING_DC;
  224. else {
  225. g_set_error(err, HDP_ERROR, HDP_DIC_ENTRY_PARSE_ERROR,
  226. "Invalid value for data type");
  227. return FALSE;
  228. }
  229. app->chan_type_set = TRUE;
  230. return TRUE;
  231. }
  232. static struct dict_entry_func dict_parser[] = {
  233. {"DataType", parse_data_type},
  234. {"Role", parse_role},
  235. {"Description", parse_desc},
  236. {"ChannelType", parse_chan_type},
  237. {NULL, NULL}
  238. };
  239. struct hdp_application *hdp_get_app_config(DBusMessageIter *iter, GError **err)
  240. {
  241. struct hdp_application *app;
  242. app = g_new0(struct hdp_application, 1);
  243. app->ref = 1;
  244. if (!parse_dict(dict_parser, iter, err, app))
  245. goto fail;
  246. if (!app->data_type_set || !app->role_set) {
  247. g_set_error(err, HDP_ERROR, HDP_DIC_PARSE_ERROR,
  248. "Mandatory fields aren't set");
  249. goto fail;
  250. }
  251. return app;
  252. fail:
  253. hdp_application_unref(app);
  254. return NULL;
  255. }
  256. static gboolean is_app_role(GSList *app_list, HdpRole role)
  257. {
  258. GSList *l;
  259. for (l = app_list; l; l = l->next) {
  260. struct hdp_application *app = l->data;
  261. if (app->role == role)
  262. return TRUE;
  263. }
  264. return FALSE;
  265. }
  266. static gboolean set_sdp_services_uuid(sdp_record_t *record, HdpRole role)
  267. {
  268. uuid_t svc_uuid_source, svc_uuid_sink;
  269. sdp_list_t *svc_list = NULL;
  270. sdp_uuid16_create(&svc_uuid_sink, HDP_SINK_SVCLASS_ID);
  271. sdp_uuid16_create(&svc_uuid_source, HDP_SOURCE_SVCLASS_ID);
  272. sdp_get_service_classes(record, &svc_list);
  273. if (role == HDP_SOURCE) {
  274. if (!sdp_list_find(svc_list, &svc_uuid_source, sdp_uuid_cmp))
  275. svc_list = sdp_list_append(svc_list, &svc_uuid_source);
  276. } else if (role == HDP_SINK) {
  277. if (!sdp_list_find(svc_list, &svc_uuid_sink, sdp_uuid_cmp))
  278. svc_list = sdp_list_append(svc_list, &svc_uuid_sink);
  279. }
  280. if (sdp_set_service_classes(record, svc_list) < 0) {
  281. sdp_list_free(svc_list, NULL);
  282. return FALSE;
  283. }
  284. sdp_list_free(svc_list, NULL);
  285. return TRUE;
  286. }
  287. static gboolean register_service_protocols(struct hdp_adapter *adapter,
  288. sdp_record_t *sdp_record)
  289. {
  290. gboolean ret;
  291. uuid_t l2cap_uuid, mcap_c_uuid;
  292. sdp_list_t *l2cap_list, *proto_list = NULL, *mcap_list = NULL;
  293. sdp_list_t *access_proto_list = NULL;
  294. sdp_data_t *psm = NULL, *mcap_ver = NULL;
  295. uint16_t version = MCAP_VERSION;
  296. /* set l2cap information */
  297. sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
  298. l2cap_list = sdp_list_append(NULL, &l2cap_uuid);
  299. if (l2cap_list == NULL) {
  300. ret = FALSE;
  301. goto end;
  302. }
  303. psm = sdp_data_alloc(SDP_UINT16, &adapter->ccpsm);
  304. if (psm == NULL) {
  305. ret = FALSE;
  306. goto end;
  307. }
  308. if (sdp_list_append(l2cap_list, psm) == NULL) {
  309. ret = FALSE;
  310. goto end;
  311. }
  312. proto_list = sdp_list_append(NULL, l2cap_list);
  313. if (proto_list == NULL) {
  314. ret = FALSE;
  315. goto end;
  316. }
  317. /* set mcap information */
  318. sdp_uuid16_create(&mcap_c_uuid, MCAP_CTRL_UUID);
  319. mcap_list = sdp_list_append(NULL, &mcap_c_uuid);
  320. if (mcap_list == NULL) {
  321. ret = FALSE;
  322. goto end;
  323. }
  324. mcap_ver = sdp_data_alloc(SDP_UINT16, &version);
  325. if (mcap_ver == NULL) {
  326. ret = FALSE;
  327. goto end;
  328. }
  329. if (sdp_list_append(mcap_list, mcap_ver) == NULL) {
  330. ret = FALSE;
  331. goto end;
  332. }
  333. if (sdp_list_append(proto_list, mcap_list) == NULL) {
  334. ret = FALSE;
  335. goto end;
  336. }
  337. /* attach protocol information to service record */
  338. access_proto_list = sdp_list_append(NULL, proto_list);
  339. if (access_proto_list == NULL) {
  340. ret = FALSE;
  341. goto end;
  342. }
  343. ret = TRUE;
  344. sdp_set_access_protos(sdp_record, access_proto_list);
  345. end:
  346. if (l2cap_list != NULL)
  347. sdp_list_free(l2cap_list, NULL);
  348. if (mcap_list != NULL)
  349. sdp_list_free(mcap_list, NULL);
  350. if (proto_list != NULL)
  351. sdp_list_free(proto_list, NULL);
  352. if (access_proto_list != NULL)
  353. sdp_list_free(access_proto_list, NULL);
  354. if (psm != NULL)
  355. sdp_data_free(psm);
  356. if (mcap_ver != NULL)
  357. sdp_data_free(mcap_ver);
  358. return ret;
  359. }
  360. static gboolean register_service_profiles(sdp_record_t *sdp_record)
  361. {
  362. gboolean ret;
  363. sdp_list_t *profile_list;
  364. sdp_profile_desc_t hdp_profile;
  365. /* set hdp information */
  366. sdp_uuid16_create(&hdp_profile.uuid, HDP_SVCLASS_ID);
  367. hdp_profile.version = HDP_VERSION;
  368. profile_list = sdp_list_append(NULL, &hdp_profile);
  369. if (profile_list == NULL)
  370. return FALSE;
  371. /* set profile descriptor list */
  372. if (sdp_set_profile_descs(sdp_record, profile_list) < 0)
  373. ret = FALSE;
  374. else
  375. ret = TRUE;
  376. sdp_list_free(profile_list, NULL);
  377. return ret;
  378. }
  379. static gboolean register_service_additional_protocols(
  380. struct hdp_adapter *adapter,
  381. sdp_record_t *sdp_record)
  382. {
  383. gboolean ret = TRUE;
  384. uuid_t l2cap_uuid, mcap_d_uuid;
  385. sdp_list_t *l2cap_list, *proto_list = NULL, *mcap_list = NULL;
  386. sdp_list_t *access_proto_list = NULL;
  387. sdp_data_t *psm = NULL;
  388. /* set l2cap information */
  389. sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
  390. l2cap_list = sdp_list_append(NULL, &l2cap_uuid);
  391. if (l2cap_list == NULL) {
  392. ret = FALSE;
  393. goto end;
  394. }
  395. psm = sdp_data_alloc(SDP_UINT16, &adapter->dcpsm);
  396. if (psm == NULL) {
  397. ret = FALSE;
  398. goto end;
  399. }
  400. if (sdp_list_append(l2cap_list, psm) == NULL) {
  401. ret = FALSE;
  402. goto end;
  403. }
  404. proto_list = sdp_list_append(NULL, l2cap_list);
  405. if (proto_list == NULL) {
  406. ret = FALSE;
  407. goto end;
  408. }
  409. /* set mcap information */
  410. sdp_uuid16_create(&mcap_d_uuid, MCAP_DATA_UUID);
  411. mcap_list = sdp_list_append(NULL, &mcap_d_uuid);
  412. if (mcap_list == NULL) {
  413. ret = FALSE;
  414. goto end;
  415. }
  416. if (sdp_list_append(proto_list, mcap_list) == NULL) {
  417. ret = FALSE;
  418. goto end;
  419. }
  420. /* attach protocol information to service record */
  421. access_proto_list = sdp_list_append(NULL, proto_list);
  422. if (access_proto_list == NULL) {
  423. ret = FALSE;
  424. goto end;
  425. }
  426. sdp_set_add_access_protos(sdp_record, access_proto_list);
  427. end:
  428. if (l2cap_list != NULL)
  429. sdp_list_free(l2cap_list, NULL);
  430. if (mcap_list != NULL)
  431. sdp_list_free(mcap_list, NULL);
  432. if (proto_list != NULL)
  433. sdp_list_free(proto_list, NULL);
  434. if (access_proto_list != NULL)
  435. sdp_list_free(access_proto_list, NULL);
  436. if (psm != NULL)
  437. sdp_data_free(psm);
  438. return ret;
  439. }
  440. static sdp_list_t *app_to_sdplist(struct hdp_application *app)
  441. {
  442. sdp_data_t *mdepid,
  443. *dtype = NULL,
  444. *role = NULL,
  445. *desc = NULL;
  446. sdp_list_t *f_list = NULL;
  447. mdepid = sdp_data_alloc(SDP_UINT8, &app->id);
  448. if (mdepid == NULL)
  449. return NULL;
  450. dtype = sdp_data_alloc(SDP_UINT16, &app->data_type);
  451. if (dtype == NULL)
  452. goto fail;
  453. role = sdp_data_alloc(SDP_UINT8, &app->role);
  454. if (role == NULL)
  455. goto fail;
  456. if (app->description != NULL) {
  457. desc = sdp_data_alloc(SDP_TEXT_STR8, app->description);
  458. if (desc == NULL)
  459. goto fail;
  460. }
  461. f_list = sdp_list_append(NULL, mdepid);
  462. if (f_list == NULL)
  463. goto fail;
  464. if (sdp_list_append(f_list, dtype) == NULL)
  465. goto fail;
  466. if (sdp_list_append(f_list, role) == NULL)
  467. goto fail;
  468. if (desc != NULL)
  469. if (sdp_list_append(f_list, desc) == NULL)
  470. goto fail;
  471. return f_list;
  472. fail:
  473. if (f_list != NULL)
  474. sdp_list_free(f_list, NULL);
  475. if (mdepid != NULL)
  476. sdp_data_free(mdepid);
  477. if (dtype != NULL)
  478. sdp_data_free(dtype);
  479. if (role != NULL)
  480. sdp_data_free(role);
  481. if (desc != NULL)
  482. sdp_data_free(desc);
  483. return NULL;
  484. }
  485. static void free_hdp_list(void *list)
  486. {
  487. sdp_list_t *hdp_list = list;
  488. sdp_list_free(hdp_list, (sdp_free_func_t)sdp_data_free);
  489. }
  490. static gboolean register_features(struct hdp_application *app,
  491. sdp_list_t **sup_features)
  492. {
  493. sdp_list_t *hdp_feature;
  494. hdp_feature = app_to_sdplist(app);
  495. if (hdp_feature == NULL)
  496. goto fail;
  497. if (*sup_features == NULL) {
  498. *sup_features = sdp_list_append(NULL, hdp_feature);
  499. if (*sup_features == NULL)
  500. goto fail;
  501. } else if (sdp_list_append(*sup_features, hdp_feature) == NULL) {
  502. goto fail;
  503. }
  504. return TRUE;
  505. fail:
  506. if (hdp_feature != NULL)
  507. sdp_list_free(hdp_feature, (sdp_free_func_t)sdp_data_free);
  508. if (*sup_features != NULL)
  509. sdp_list_free(*sup_features, free_hdp_list);
  510. return FALSE;
  511. }
  512. static gboolean register_service_sup_features(GSList *app_list,
  513. sdp_record_t *sdp_record)
  514. {
  515. GSList *l;
  516. sdp_list_t *sup_features = NULL;
  517. for (l = app_list; l; l = l->next) {
  518. if (!register_features(l->data, &sup_features))
  519. return FALSE;
  520. }
  521. if (sdp_set_supp_feat(sdp_record, sup_features) < 0) {
  522. sdp_list_free(sup_features, free_hdp_list);
  523. return FALSE;
  524. }
  525. sdp_list_free(sup_features, free_hdp_list);
  526. return TRUE;
  527. }
  528. static gboolean register_data_exchange_spec(sdp_record_t *record)
  529. {
  530. sdp_data_t *spec;
  531. uint8_t data_spec = DATA_EXCHANGE_SPEC_11073;
  532. /* As by now 11073 is the only supported we set it by default */
  533. spec = sdp_data_alloc(SDP_UINT8, &data_spec);
  534. if (spec == NULL)
  535. return FALSE;
  536. if (sdp_attr_add(record, SDP_ATTR_DATA_EXCHANGE_SPEC, spec) < 0) {
  537. sdp_data_free(spec);
  538. return FALSE;
  539. }
  540. return TRUE;
  541. }
  542. static gboolean register_mcap_features(sdp_record_t *sdp_record)
  543. {
  544. sdp_data_t *mcap_proc;
  545. uint8_t mcap_sup_proc = MCAP_SUP_PROC;
  546. mcap_proc = sdp_data_alloc(SDP_UINT8, &mcap_sup_proc);
  547. if (mcap_proc == NULL)
  548. return FALSE;
  549. if (sdp_attr_add(sdp_record, SDP_ATTR_MCAP_SUPPORTED_PROCEDURES,
  550. mcap_proc) < 0) {
  551. sdp_data_free(mcap_proc);
  552. return FALSE;
  553. }
  554. return TRUE;
  555. }
  556. gboolean hdp_update_sdp_record(struct hdp_adapter *adapter, GSList *app_list)
  557. {
  558. sdp_record_t *sdp_record;
  559. if (adapter->sdp_handler > 0)
  560. adapter_service_remove(adapter->btd_adapter,
  561. adapter->sdp_handler);
  562. if (app_list == NULL) {
  563. adapter->sdp_handler = 0;
  564. return TRUE;
  565. }
  566. sdp_record = sdp_record_alloc();
  567. if (sdp_record == NULL)
  568. return FALSE;
  569. if (adapter->sdp_handler > 0)
  570. sdp_record->handle = adapter->sdp_handler;
  571. else
  572. sdp_record->handle = 0xffffffff; /* Set automatically */
  573. if (is_app_role(app_list, HDP_SINK))
  574. set_sdp_services_uuid(sdp_record, HDP_SINK);
  575. if (is_app_role(app_list, HDP_SOURCE))
  576. set_sdp_services_uuid(sdp_record, HDP_SOURCE);
  577. if (!register_service_protocols(adapter, sdp_record))
  578. goto fail;
  579. if (!register_service_profiles(sdp_record))
  580. goto fail;
  581. if (!register_service_additional_protocols(adapter, sdp_record))
  582. goto fail;
  583. sdp_set_info_attr(sdp_record, HDP_SERVICE_NAME, HDP_SERVICE_PROVIDER,
  584. HDP_SERVICE_DSC);
  585. if (!register_service_sup_features(app_list, sdp_record))
  586. goto fail;
  587. if (!register_data_exchange_spec(sdp_record))
  588. goto fail;
  589. register_mcap_features(sdp_record);
  590. if (sdp_set_record_state(sdp_record, adapter->record_state++) < 0)
  591. goto fail;
  592. if (adapter_service_add(adapter->btd_adapter, sdp_record) < 0)
  593. goto fail;
  594. adapter->sdp_handler = sdp_record->handle;
  595. return TRUE;
  596. fail:
  597. if (sdp_record != NULL)
  598. sdp_record_free(sdp_record);
  599. return FALSE;
  600. }
  601. static gboolean check_role(uint8_t rec_role, uint8_t app_role)
  602. {
  603. if ((rec_role == HDP_SINK && app_role == HDP_SOURCE) ||
  604. (rec_role == HDP_SOURCE && app_role == HDP_SINK))
  605. return TRUE;
  606. return FALSE;
  607. }
  608. static gboolean get_mdep_from_rec(const sdp_record_t *rec, uint8_t role,
  609. uint16_t d_type, uint8_t *mdep, char **desc)
  610. {
  611. sdp_data_t *list, *feat;
  612. if (desc == NULL && mdep == NULL)
  613. return TRUE;
  614. list = sdp_data_get(rec, SDP_ATTR_SUPPORTED_FEATURES_LIST);
  615. if (list == NULL || !SDP_IS_SEQ(list->dtd))
  616. return FALSE;
  617. for (feat = list->val.dataseq; feat; feat = feat->next) {
  618. sdp_data_t *data_type, *mdepid, *role_t, *desc_t;
  619. if (!SDP_IS_SEQ(feat->dtd))
  620. continue;
  621. mdepid = feat->val.dataseq;
  622. if (mdepid == NULL)
  623. continue;
  624. data_type = mdepid->next;
  625. if (data_type == NULL)
  626. continue;
  627. role_t = data_type->next;
  628. if (role_t == NULL)
  629. continue;
  630. desc_t = role_t->next;
  631. if (data_type->dtd != SDP_UINT16 || mdepid->dtd != SDP_UINT8 ||
  632. role_t->dtd != SDP_UINT8)
  633. continue;
  634. if (data_type->val.uint16 != d_type ||
  635. !check_role(role_t->val.uint8, role))
  636. continue;
  637. if (mdep != NULL)
  638. *mdep = mdepid->val.uint8;
  639. if (desc != NULL && desc_t != NULL &&
  640. SDP_IS_TEXT_STR(desc_t->dtd))
  641. *desc = g_strdup(desc_t->val.str);
  642. return TRUE;
  643. }
  644. return FALSE;
  645. }
  646. static void get_mdep_cb(sdp_list_t *recs, int err, gpointer user_data)
  647. {
  648. struct get_mdep_data *mdep_data = user_data;
  649. GError *gerr = NULL;
  650. uint8_t mdep;
  651. if (err < 0 || recs == NULL) {
  652. g_set_error(&gerr, HDP_ERROR, HDP_CONNECTION_ERROR,
  653. "Error getting remote SDP records");
  654. mdep_data->func(0, mdep_data->data, gerr);
  655. g_error_free(gerr);
  656. return;
  657. }
  658. if (!get_mdep_from_rec(recs->data, mdep_data->app->role,
  659. mdep_data->app->data_type, &mdep, NULL)) {
  660. g_set_error(&gerr, HDP_ERROR, HDP_CONNECTION_ERROR,
  661. "No matching MDEP found");
  662. mdep_data->func(0, mdep_data->data, gerr);
  663. g_error_free(gerr);
  664. return;
  665. }
  666. mdep_data->func(mdep, mdep_data->data, NULL);
  667. }
  668. static void free_mdep_data(gpointer data)
  669. {
  670. struct get_mdep_data *mdep_data = data;
  671. if (mdep_data->destroy)
  672. mdep_data->destroy(mdep_data->data);
  673. hdp_application_unref(mdep_data->app);
  674. g_free(mdep_data);
  675. }
  676. gboolean hdp_get_mdep(struct hdp_device *device, struct hdp_application *app,
  677. hdp_continue_mdep_f func, gpointer data,
  678. GDestroyNotify destroy, GError **err)
  679. {
  680. struct get_mdep_data *mdep_data;
  681. const bdaddr_t *src;
  682. const bdaddr_t *dst;
  683. uuid_t uuid;
  684. src = btd_adapter_get_address(device_get_adapter(device->dev));
  685. dst = device_get_address(device->dev);
  686. mdep_data = g_new0(struct get_mdep_data, 1);
  687. mdep_data->app = hdp_application_ref(app);
  688. mdep_data->func = func;
  689. mdep_data->data = data;
  690. mdep_data->destroy = destroy;
  691. bt_string2uuid(&uuid, HDP_UUID);
  692. if (bt_search_service(src, dst, &uuid, get_mdep_cb, mdep_data,
  693. free_mdep_data, 0) < 0) {
  694. g_set_error(err, HDP_ERROR, HDP_CONNECTION_ERROR,
  695. "Can't get remote SDP record");
  696. g_free(mdep_data);
  697. return FALSE;
  698. }
  699. return TRUE;
  700. }
  701. static gboolean get_prot_desc_entry(sdp_data_t *entry, int type, guint16 *val)
  702. {
  703. sdp_data_t *iter;
  704. int proto;
  705. if (entry == NULL || !SDP_IS_SEQ(entry->dtd))
  706. return FALSE;
  707. iter = entry->val.dataseq;
  708. if (!(iter->dtd & SDP_UUID_UNSPEC))
  709. return FALSE;
  710. proto = sdp_uuid_to_proto(&iter->val.uuid);
  711. if (proto != type)
  712. return FALSE;
  713. if (val == NULL)
  714. return TRUE;
  715. iter = iter->next;
  716. if (iter->dtd != SDP_UINT16)
  717. return FALSE;
  718. *val = iter->val.uint16;
  719. return TRUE;
  720. }
  721. static gboolean hdp_get_prot_desc_list(const sdp_record_t *rec, guint16 *psm,
  722. guint16 *version)
  723. {
  724. sdp_data_t *pdl, *p0, *p1;
  725. if (psm == NULL && version == NULL)
  726. return TRUE;
  727. pdl = sdp_data_get(rec, SDP_ATTR_PROTO_DESC_LIST);
  728. if (pdl == NULL || !SDP_IS_SEQ(pdl->dtd))
  729. return FALSE;
  730. p0 = pdl->val.dataseq;
  731. if (!get_prot_desc_entry(p0, L2CAP_UUID, psm))
  732. return FALSE;
  733. p1 = p0->next;
  734. if (!get_prot_desc_entry(p1, MCAP_CTRL_UUID, version))
  735. return FALSE;
  736. return TRUE;
  737. }
  738. static gboolean hdp_get_add_prot_desc_list(const sdp_record_t *rec,
  739. guint16 *psm)
  740. {
  741. sdp_data_t *pdl, *p0, *p1;
  742. if (psm == NULL)
  743. return TRUE;
  744. pdl = sdp_data_get(rec, SDP_ATTR_ADD_PROTO_DESC_LIST);
  745. if (pdl == NULL || pdl->dtd != SDP_SEQ8)
  746. return FALSE;
  747. pdl = pdl->val.dataseq;
  748. if (pdl->dtd != SDP_SEQ8)
  749. return FALSE;
  750. p0 = pdl->val.dataseq;
  751. if (!get_prot_desc_entry(p0, L2CAP_UUID, psm))
  752. return FALSE;
  753. p1 = p0->next;
  754. if (!get_prot_desc_entry(p1, MCAP_DATA_UUID, NULL))
  755. return FALSE;
  756. return TRUE;
  757. }
  758. static gboolean get_ccpsm(sdp_list_t *recs, uint16_t *ccpsm)
  759. {
  760. sdp_list_t *l;
  761. for (l = recs; l; l = l->next) {
  762. sdp_record_t *rec = l->data;
  763. if (hdp_get_prot_desc_list(rec, ccpsm, NULL))
  764. return TRUE;
  765. }
  766. return FALSE;
  767. }
  768. static gboolean get_dcpsm(sdp_list_t *recs, uint16_t *dcpsm)
  769. {
  770. sdp_list_t *l;
  771. for (l = recs; l; l = l->next) {
  772. sdp_record_t *rec = l->data;
  773. if (hdp_get_add_prot_desc_list(rec, dcpsm))
  774. return TRUE;
  775. }
  776. return FALSE;
  777. }
  778. static void con_mcl_data_unref(struct conn_mcl_data *conn_data)
  779. {
  780. if (conn_data == NULL)
  781. return;
  782. if (--conn_data->refs > 0)
  783. return;
  784. if (conn_data->destroy)
  785. conn_data->destroy(conn_data->data);
  786. health_device_unref(conn_data->dev);
  787. g_free(conn_data);
  788. }
  789. static void destroy_con_mcl_data(gpointer data)
  790. {
  791. con_mcl_data_unref(data);
  792. }
  793. static struct conn_mcl_data *con_mcl_data_ref(struct conn_mcl_data *conn_data)
  794. {
  795. if (conn_data == NULL)
  796. return NULL;
  797. conn_data->refs++;
  798. return conn_data;
  799. }
  800. static void create_mcl_cb(struct mcap_mcl *mcl, GError *err, gpointer data)
  801. {
  802. struct conn_mcl_data *conn_data = data;
  803. struct hdp_device *device = conn_data->dev;
  804. GError *gerr = NULL;
  805. if (err != NULL) {
  806. conn_data->func(conn_data->data, err);
  807. return;
  808. }
  809. if (device->mcl == NULL)
  810. device->mcl = mcap_mcl_ref(mcl);
  811. device->mcl_conn = TRUE;
  812. hdp_set_mcl_cb(device, &gerr);
  813. conn_data->func(conn_data->data, gerr);
  814. if (gerr != NULL)
  815. g_error_free(gerr);
  816. }
  817. static void search_cb(sdp_list_t *recs, int err, gpointer user_data)
  818. {
  819. struct conn_mcl_data *conn_data = user_data;
  820. GError *gerr = NULL;
  821. uint16_t ccpsm;
  822. if (conn_data->dev->hdp_adapter->mi == NULL) {
  823. g_set_error(&gerr, HDP_ERROR, HDP_CONNECTION_ERROR,
  824. "Mcap instance released");
  825. goto fail;
  826. }
  827. if (err < 0 || recs == NULL) {
  828. g_set_error(&gerr, HDP_ERROR, HDP_CONNECTION_ERROR,
  829. "Error getting remote SDP records");
  830. goto fail;
  831. }
  832. if (!get_ccpsm(recs, &ccpsm)) {
  833. g_set_error(&gerr, HDP_ERROR, HDP_CONNECTION_ERROR,
  834. "Can't get remote PSM for control channel");
  835. goto fail;
  836. }
  837. conn_data = con_mcl_data_ref(conn_data);
  838. if (!mcap_create_mcl(conn_data->dev->hdp_adapter->mi,
  839. device_get_address(conn_data->dev->dev),
  840. ccpsm, create_mcl_cb, conn_data,
  841. destroy_con_mcl_data, &gerr)) {
  842. con_mcl_data_unref(conn_data);
  843. goto fail;
  844. }
  845. return;
  846. fail:
  847. conn_data->func(conn_data->data, gerr);
  848. g_error_free(gerr);
  849. }
  850. gboolean hdp_establish_mcl(struct hdp_device *device,
  851. hdp_continue_proc_f func,
  852. gpointer data,
  853. GDestroyNotify destroy,
  854. GError **err)
  855. {
  856. struct conn_mcl_data *conn_data;
  857. const bdaddr_t *src;
  858. const bdaddr_t *dst;
  859. uuid_t uuid;
  860. src = btd_adapter_get_address(device_get_adapter(device->dev));
  861. dst = device_get_address(device->dev);
  862. conn_data = g_new0(struct conn_mcl_data, 1);
  863. conn_data->refs = 1;
  864. conn_data->func = func;
  865. conn_data->data = data;
  866. conn_data->destroy = destroy;
  867. conn_data->dev = health_device_ref(device);
  868. bt_string2uuid(&uuid, HDP_UUID);
  869. if (bt_search_service(src, dst, &uuid, search_cb, conn_data,
  870. destroy_con_mcl_data, 0) < 0) {
  871. g_set_error(err, HDP_ERROR, HDP_CONNECTION_ERROR,
  872. "Can't get remote SDP record");
  873. g_free(conn_data);
  874. return FALSE;
  875. }
  876. return TRUE;
  877. }
  878. static void get_dcpsm_cb(sdp_list_t *recs, int err, gpointer data)
  879. {
  880. struct get_dcpsm_data *dcpsm_data = data;
  881. GError *gerr = NULL;
  882. uint16_t dcpsm;
  883. if (err < 0 || recs == NULL) {
  884. g_set_error(&gerr, HDP_ERROR, HDP_CONNECTION_ERROR,
  885. "Error getting remote SDP records");
  886. goto fail;
  887. }
  888. if (!get_dcpsm(recs, &dcpsm)) {
  889. g_set_error(&gerr, HDP_ERROR, HDP_CONNECTION_ERROR,
  890. "Can't get remote PSM for data channel");
  891. goto fail;
  892. }
  893. dcpsm_data->func(dcpsm, dcpsm_data->data, NULL);
  894. return;
  895. fail:
  896. dcpsm_data->func(0, dcpsm_data->data, gerr);
  897. g_error_free(gerr);
  898. }
  899. static void free_dcpsm_data(gpointer data)
  900. {
  901. struct get_dcpsm_data *dcpsm_data = data;
  902. if (dcpsm_data == NULL)
  903. return;
  904. if (dcpsm_data->destroy)
  905. dcpsm_data->destroy(dcpsm_data->data);
  906. g_free(dcpsm_data);
  907. }
  908. gboolean hdp_get_dcpsm(struct hdp_device *device, hdp_continue_dcpsm_f func,
  909. gpointer data,
  910. GDestroyNotify destroy,
  911. GError **err)
  912. {
  913. struct get_dcpsm_data *dcpsm_data;
  914. const bdaddr_t *src;
  915. const bdaddr_t *dst;
  916. uuid_t uuid;
  917. src = btd_adapter_get_address(device_get_adapter(device->dev));
  918. dst = device_get_address(device->dev);
  919. dcpsm_data = g_new0(struct get_dcpsm_data, 1);
  920. dcpsm_data->func = func;
  921. dcpsm_data->data = data;
  922. dcpsm_data->destroy = destroy;
  923. bt_string2uuid(&uuid, HDP_UUID);
  924. if (bt_search_service(src, dst, &uuid, get_dcpsm_cb, dcpsm_data,
  925. free_dcpsm_data, 0) < 0) {
  926. g_set_error(err, HDP_ERROR, HDP_CONNECTION_ERROR,
  927. "Can't get remote SDP record");
  928. g_free(dcpsm_data);
  929. return FALSE;
  930. }
  931. return TRUE;
  932. }
  933. static void hdp_free_application(struct hdp_application *app)
  934. {
  935. if (app->dbus_watcher > 0)
  936. g_dbus_remove_watch(btd_get_dbus_connection(),
  937. app->dbus_watcher);
  938. g_free(app->oname);
  939. g_free(app->description);
  940. g_free(app->path);
  941. g_free(app);
  942. }
  943. struct hdp_application *hdp_application_ref(struct hdp_application *app)
  944. {
  945. if (app == NULL)
  946. return NULL;
  947. app->ref++;
  948. DBG("health_application_ref(%p): ref=%d", app, app->ref);
  949. return app;
  950. }
  951. void hdp_application_unref(struct hdp_application *app)
  952. {
  953. if (app == NULL)
  954. return;
  955. app->ref--;
  956. DBG("health_application_unref(%p): ref=%d", app, app->ref);
  957. if (app->ref > 0)
  958. return;
  959. hdp_free_application(app);
  960. }