hdp.c 51 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253
  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 <stdlib.h>
  14. #include <stdint.h>
  15. #include <stdbool.h>
  16. #include <unistd.h>
  17. #include <glib.h>
  18. #include "lib/bluetooth.h"
  19. #include "lib/l2cap.h"
  20. #include "lib/sdp.h"
  21. #include "gdbus/gdbus.h"
  22. #include "src/dbus-common.h"
  23. #include "src/log.h"
  24. #include "src/error.h"
  25. #include "src/adapter.h"
  26. #include "src/device.h"
  27. #include "src/sdpd.h"
  28. #include "src/shared/timeout.h"
  29. #include "btio/btio.h"
  30. #include "hdp_types.h"
  31. #include "hdp_util.h"
  32. #include "hdp.h"
  33. #include "mcap.h"
  34. #define ECHO_TIMEOUT 1 /* second */
  35. #define HDP_ECHO_LEN 15
  36. static GSList *applications = NULL;
  37. static GSList *devices = NULL;
  38. static uint8_t next_app_id = HDP_MDEP_INITIAL;
  39. static GSList *adapters;
  40. static struct hdp_device *create_health_device(struct btd_device *device);
  41. static void free_echo_data(struct hdp_echo_data *edata);
  42. struct hdp_create_dc {
  43. DBusMessage *msg;
  44. struct hdp_application *app;
  45. struct hdp_device *dev;
  46. uint8_t config;
  47. uint8_t mdep;
  48. guint ref;
  49. mcap_mdl_operation_cb cb;
  50. };
  51. struct hdp_tmp_dc_data {
  52. DBusMessage *msg;
  53. struct hdp_channel *hdp_chann;
  54. guint ref;
  55. mcap_mdl_operation_cb cb;
  56. };
  57. struct hdp_echo_data {
  58. gboolean echo_done; /* Is a echo was already done */
  59. gpointer buf; /* echo packet sent */
  60. unsigned int tid; /* echo timeout */
  61. };
  62. static struct hdp_channel *hdp_channel_ref(struct hdp_channel *chan)
  63. {
  64. if (chan == NULL)
  65. return NULL;
  66. chan->ref++;
  67. DBG("(%p): ref=%d", chan, chan->ref);
  68. return chan;
  69. }
  70. static void free_health_channel(struct hdp_channel *chan)
  71. {
  72. if (chan->mdep == HDP_MDEP_ECHO) {
  73. free_echo_data(chan->edata);
  74. chan->edata = NULL;
  75. }
  76. mcap_mdl_unref(chan->mdl);
  77. hdp_application_unref(chan->app);
  78. health_device_unref(chan->dev);
  79. g_free(chan->path);
  80. g_free(chan);
  81. }
  82. static void hdp_channel_unref(struct hdp_channel *chan)
  83. {
  84. if (chan == NULL)
  85. return;
  86. chan->ref --;
  87. DBG("(%p): ref=%d", chan, chan->ref);
  88. if (chan->ref > 0)
  89. return;
  90. free_health_channel(chan);
  91. }
  92. static void free_hdp_create_dc(struct hdp_create_dc *dc_data)
  93. {
  94. dbus_message_unref(dc_data->msg);
  95. hdp_application_unref(dc_data->app);
  96. health_device_unref(dc_data->dev);
  97. g_free(dc_data);
  98. }
  99. static struct hdp_create_dc *hdp_create_data_ref(struct hdp_create_dc *dc_data)
  100. {
  101. dc_data->ref++;
  102. DBG("(%p): ref=%d", dc_data, dc_data->ref);
  103. return dc_data;
  104. }
  105. static void hdp_create_data_unref(struct hdp_create_dc *dc_data)
  106. {
  107. dc_data->ref--;
  108. DBG("(%p): ref=%d", dc_data, dc_data->ref);
  109. if (dc_data->ref > 0)
  110. return;
  111. free_hdp_create_dc(dc_data);
  112. }
  113. static void free_hdp_conn_dc(struct hdp_tmp_dc_data *data)
  114. {
  115. dbus_message_unref(data->msg);
  116. hdp_channel_unref(data->hdp_chann);
  117. g_free(data);
  118. }
  119. static struct hdp_tmp_dc_data *hdp_tmp_dc_data_ref(struct hdp_tmp_dc_data *data)
  120. {
  121. data->ref++;
  122. DBG("hdp_conn_data_ref(%p): ref=%d", data, data->ref);
  123. return data;
  124. }
  125. static void hdp_tmp_dc_data_unref(struct hdp_tmp_dc_data *data)
  126. {
  127. data->ref--;
  128. DBG("hdp_conn_data_unref(%p): ref=%d", data, data->ref);
  129. if (data->ref > 0)
  130. return;
  131. free_hdp_conn_dc(data);
  132. }
  133. static int cmp_app_id(gconstpointer a, gconstpointer b)
  134. {
  135. const struct hdp_application *app = a;
  136. const uint8_t *id = b;
  137. return app->id - *id;
  138. }
  139. static int cmp_adapter(gconstpointer a, gconstpointer b)
  140. {
  141. const struct hdp_adapter *hdp_adapter = a;
  142. const struct btd_adapter *adapter = b;
  143. if (hdp_adapter->btd_adapter == adapter)
  144. return 0;
  145. return -1;
  146. }
  147. static int cmp_device(gconstpointer a, gconstpointer b)
  148. {
  149. const struct hdp_device *hdp_device = a;
  150. const struct btd_device *device = b;
  151. if (hdp_device->dev == device)
  152. return 0;
  153. return -1;
  154. }
  155. static int cmp_dev_addr(gconstpointer a, gconstpointer dst)
  156. {
  157. const struct hdp_device *device = a;
  158. return bacmp(device_get_address(device->dev), dst);
  159. }
  160. static int cmp_dev_mcl(gconstpointer a, gconstpointer mcl)
  161. {
  162. const struct hdp_device *device = a;
  163. if (mcl == device->mcl)
  164. return 0;
  165. return -1;
  166. }
  167. static int cmp_chan_mdlid(gconstpointer a, gconstpointer b)
  168. {
  169. const struct hdp_channel *chan = a;
  170. const uint16_t *mdlid = b;
  171. return chan->mdlid - *mdlid;
  172. }
  173. static int cmp_chan_path(gconstpointer a, gconstpointer b)
  174. {
  175. const struct hdp_channel *chan = a;
  176. const char *path = b;
  177. return g_ascii_strcasecmp(chan->path, path);
  178. }
  179. static int cmp_chan_mdl(gconstpointer a, gconstpointer mdl)
  180. {
  181. const struct hdp_channel *chan = a;
  182. if (chan->mdl == mdl)
  183. return 0;
  184. return -1;
  185. }
  186. static uint8_t get_app_id(void)
  187. {
  188. uint8_t id = next_app_id;
  189. do {
  190. GSList *l = g_slist_find_custom(applications, &id, cmp_app_id);
  191. if (l == NULL) {
  192. next_app_id = (id % HDP_MDEP_FINAL) + 1;
  193. return id;
  194. } else
  195. id = (id % HDP_MDEP_FINAL) + 1;
  196. } while (id != next_app_id);
  197. /* No more ids available */
  198. return 0;
  199. }
  200. static int cmp_app(gconstpointer a, gconstpointer b)
  201. {
  202. const struct hdp_application *app = a;
  203. return g_strcmp0(app->path, b);
  204. }
  205. static gboolean set_app_path(struct hdp_application *app)
  206. {
  207. app->id = get_app_id();
  208. if (app->id == 0)
  209. return FALSE;
  210. app->path = g_strdup_printf(MANAGER_PATH "/health_app_%d", app->id);
  211. return TRUE;
  212. };
  213. static void device_unref_mcl(struct hdp_device *hdp_device)
  214. {
  215. if (hdp_device->mcl == NULL)
  216. return;
  217. mcap_close_mcl(hdp_device->mcl, FALSE);
  218. mcap_mcl_unref(hdp_device->mcl);
  219. hdp_device->mcl = NULL;
  220. hdp_device->mcl_conn = FALSE;
  221. }
  222. static void free_health_device(struct hdp_device *device)
  223. {
  224. if (device->dev != NULL) {
  225. btd_device_unref(device->dev);
  226. device->dev = NULL;
  227. }
  228. device_unref_mcl(device);
  229. g_free(device);
  230. }
  231. static void update_adapter_cb(void *data, void *user_data);
  232. static void remove_application(struct hdp_application *app)
  233. {
  234. DBG("Application %s deleted", app->path);
  235. hdp_application_unref(app);
  236. g_slist_foreach(adapters, update_adapter_cb, NULL);
  237. }
  238. static void client_disconnected(DBusConnection *conn, void *user_data)
  239. {
  240. struct hdp_application *app = user_data;
  241. DBG("Client disconnected from the bus, deleting hdp application");
  242. applications = g_slist_remove(applications, app);
  243. app->dbus_watcher = 0; /* Watcher shouldn't be freed in this case */
  244. remove_application(app);
  245. }
  246. static DBusMessage *manager_create_application(DBusConnection *conn,
  247. DBusMessage *msg, void *user_data)
  248. {
  249. struct hdp_application *app;
  250. const char *name;
  251. DBusMessageIter iter;
  252. GError *err = NULL;
  253. dbus_message_iter_init(msg, &iter);
  254. app = hdp_get_app_config(&iter, &err);
  255. if (err != NULL) {
  256. g_error_free(err);
  257. return btd_error_invalid_args(msg);
  258. }
  259. name = dbus_message_get_sender(msg);
  260. if (name == NULL) {
  261. hdp_application_unref(app);
  262. return g_dbus_create_error(msg,
  263. ERROR_INTERFACE ".HealthError",
  264. "Can't get sender name");
  265. }
  266. if (!set_app_path(app)) {
  267. hdp_application_unref(app);
  268. return g_dbus_create_error(msg,
  269. ERROR_INTERFACE ".HealthError",
  270. "Can't get a valid id for the application");
  271. }
  272. app->oname = g_strdup(name);
  273. applications = g_slist_prepend(applications, app);
  274. app->dbus_watcher =
  275. g_dbus_add_disconnect_watch(btd_get_dbus_connection(),
  276. name, client_disconnected, app, NULL);
  277. g_slist_foreach(adapters, update_adapter_cb, NULL);
  278. DBG("Health application created with id %s", app->path);
  279. return g_dbus_create_reply(msg, DBUS_TYPE_OBJECT_PATH, &app->path,
  280. DBUS_TYPE_INVALID);
  281. }
  282. static DBusMessage *manager_destroy_application(DBusConnection *conn,
  283. DBusMessage *msg, void *user_data)
  284. {
  285. const char *path;
  286. struct hdp_application *app;
  287. GSList *l;
  288. if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
  289. DBUS_TYPE_INVALID))
  290. return btd_error_invalid_args(msg);
  291. l = g_slist_find_custom(applications, path, cmp_app);
  292. if (l == NULL)
  293. return g_dbus_create_error(msg,
  294. ERROR_INTERFACE ".InvalidArguments",
  295. "Invalid arguments in method call, "
  296. "no such application");
  297. app = l->data;
  298. applications = g_slist_remove(applications, app);
  299. remove_application(app);
  300. return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
  301. }
  302. static void application_unref(void *data, void *user_data)
  303. {
  304. hdp_application_unref(data);
  305. }
  306. static void manager_path_unregister(gpointer data)
  307. {
  308. g_slist_foreach(applications, application_unref, NULL);
  309. g_slist_free(applications);
  310. applications = NULL;
  311. g_slist_foreach(adapters, update_adapter_cb, NULL);
  312. }
  313. static const GDBusMethodTable health_manager_methods[] = {
  314. { GDBUS_METHOD("CreateApplication",
  315. GDBUS_ARGS({ "config", "a{sv}" }),
  316. GDBUS_ARGS({ "application", "o" }),
  317. manager_create_application) },
  318. { GDBUS_METHOD("DestroyApplication",
  319. GDBUS_ARGS({ "application", "o" }), NULL,
  320. manager_destroy_application) },
  321. { }
  322. };
  323. static gboolean channel_property_get_device(const GDBusPropertyTable *property,
  324. DBusMessageIter *iter, void *data)
  325. {
  326. struct hdp_channel *chan = data;
  327. const char *path = device_get_path(chan->dev->dev);
  328. dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &path);
  329. return TRUE;
  330. }
  331. static gboolean channel_property_get_application(
  332. const GDBusPropertyTable *property,
  333. DBusMessageIter *iter, void *data)
  334. {
  335. struct hdp_channel *chan = data;
  336. const char *path = chan->app->path;
  337. dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &path);
  338. return TRUE;
  339. }
  340. static gboolean channel_property_get_type(const GDBusPropertyTable *property,
  341. DBusMessageIter *iter, void *data)
  342. {
  343. struct hdp_channel *chan = data;
  344. const char *type;
  345. if (chan->config == HDP_RELIABLE_DC)
  346. type = "reliable";
  347. else
  348. type = "streaming";
  349. dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &type);
  350. return TRUE;
  351. }
  352. static void hdp_tmp_dc_data_destroy(gpointer data)
  353. {
  354. struct hdp_tmp_dc_data *hdp_conn = data;
  355. hdp_tmp_dc_data_unref(hdp_conn);
  356. }
  357. static void abort_mdl_cb(GError *err, gpointer data)
  358. {
  359. if (err != NULL)
  360. error("Aborting error: %s", err->message);
  361. }
  362. static void hdp_mdl_reconn_cb(struct mcap_mdl *mdl, GError *err, gpointer data)
  363. {
  364. DBusConnection *conn = btd_get_dbus_connection();
  365. struct hdp_tmp_dc_data *dc_data = data;
  366. DBusMessage *reply;
  367. int fd;
  368. if (err != NULL) {
  369. struct hdp_channel *chan = dc_data->hdp_chann;
  370. GError *gerr = NULL;
  371. error("%s", err->message);
  372. reply = g_dbus_create_error(dc_data->msg,
  373. ERROR_INTERFACE ".HealthError",
  374. "Cannot reconnect: %s", err->message);
  375. g_dbus_send_message(conn, reply);
  376. /* Send abort request because remote side */
  377. /* is now in PENDING state */
  378. if (!mcap_mdl_abort(chan->mdl, abort_mdl_cb, NULL, NULL,
  379. &gerr)) {
  380. error("%s", gerr->message);
  381. g_error_free(gerr);
  382. }
  383. return;
  384. }
  385. fd = mcap_mdl_get_fd(dc_data->hdp_chann->mdl);
  386. if (fd < 0) {
  387. reply = g_dbus_create_error(dc_data->msg,
  388. ERROR_INTERFACE ".HealthError",
  389. "Cannot get file descriptor");
  390. g_dbus_send_message(conn, reply);
  391. return;
  392. }
  393. reply = g_dbus_create_reply(dc_data->msg, DBUS_TYPE_UNIX_FD,
  394. &fd, DBUS_TYPE_INVALID);
  395. g_dbus_send_message(conn, reply);
  396. g_dbus_emit_signal(conn, device_get_path(dc_data->hdp_chann->dev->dev),
  397. HEALTH_DEVICE, "ChannelConnected",
  398. DBUS_TYPE_OBJECT_PATH, &dc_data->hdp_chann->path,
  399. DBUS_TYPE_INVALID);
  400. }
  401. static void hdp_get_dcpsm_cb(uint16_t dcpsm, gpointer user_data, GError *err)
  402. {
  403. struct hdp_tmp_dc_data *hdp_conn = user_data;
  404. struct hdp_channel *hdp_chann = hdp_conn->hdp_chann;
  405. GError *gerr = NULL;
  406. uint8_t mode;
  407. if (err != NULL) {
  408. hdp_conn->cb(hdp_chann->mdl, err, hdp_conn);
  409. return;
  410. }
  411. if (hdp_chann->config == HDP_RELIABLE_DC)
  412. mode = BT_IO_MODE_ERTM;
  413. else
  414. mode = BT_IO_MODE_STREAMING;
  415. if (mcap_connect_mdl(hdp_chann->mdl, mode, dcpsm, hdp_conn->cb,
  416. hdp_tmp_dc_data_ref(hdp_conn),
  417. hdp_tmp_dc_data_destroy, &gerr))
  418. return;
  419. hdp_conn->cb(hdp_chann->mdl, err, hdp_conn);
  420. g_error_free(gerr);
  421. hdp_tmp_dc_data_unref(hdp_conn);
  422. }
  423. static void device_reconnect_mdl_cb(struct mcap_mdl *mdl, GError *err,
  424. gpointer data)
  425. {
  426. DBusConnection *conn = btd_get_dbus_connection();
  427. struct hdp_tmp_dc_data *dc_data = data;
  428. GError *gerr = NULL;
  429. DBusMessage *reply;
  430. if (err != NULL) {
  431. reply = g_dbus_create_error(dc_data->msg,
  432. ERROR_INTERFACE ".HealthError",
  433. "Cannot reconnect: %s", err->message);
  434. g_dbus_send_message(conn, reply);
  435. return;
  436. }
  437. dc_data->cb = hdp_mdl_reconn_cb;
  438. if (hdp_get_dcpsm(dc_data->hdp_chann->dev, hdp_get_dcpsm_cb,
  439. hdp_tmp_dc_data_ref(dc_data),
  440. hdp_tmp_dc_data_destroy, &gerr))
  441. return;
  442. error("%s", gerr->message);
  443. reply = g_dbus_create_error(dc_data->msg,
  444. ERROR_INTERFACE ".HealthError",
  445. "Cannot reconnect: %s", gerr->message);
  446. g_dbus_send_message(conn, reply);
  447. hdp_tmp_dc_data_unref(dc_data);
  448. g_error_free(gerr);
  449. /* Send abort request because remote side is now in PENDING state */
  450. if (!mcap_mdl_abort(mdl, abort_mdl_cb, NULL, NULL, &gerr)) {
  451. error("%s", gerr->message);
  452. g_error_free(gerr);
  453. }
  454. }
  455. static DBusMessage *channel_acquire_continue(struct hdp_tmp_dc_data *data,
  456. GError *err)
  457. {
  458. DBusMessage *reply;
  459. GError *gerr = NULL;
  460. int fd;
  461. if (err != NULL) {
  462. return g_dbus_create_error(data->msg,
  463. ERROR_INTERFACE ".HealthError",
  464. "%s", err->message);
  465. }
  466. fd = mcap_mdl_get_fd(data->hdp_chann->mdl);
  467. if (fd >= 0)
  468. return g_dbus_create_reply(data->msg, DBUS_TYPE_UNIX_FD, &fd,
  469. DBUS_TYPE_INVALID);
  470. hdp_tmp_dc_data_ref(data);
  471. if (mcap_reconnect_mdl(data->hdp_chann->mdl, device_reconnect_mdl_cb,
  472. data, hdp_tmp_dc_data_destroy, &gerr))
  473. return NULL;
  474. reply = g_dbus_create_error(data->msg, ERROR_INTERFACE ".HealthError",
  475. "Cannot reconnect: %s", gerr->message);
  476. g_error_free(gerr);
  477. hdp_tmp_dc_data_unref(data);
  478. return reply;
  479. }
  480. static void channel_acquire_cb(gpointer data, GError *err)
  481. {
  482. DBusMessage *reply;
  483. reply = channel_acquire_continue(data, err);
  484. if (reply != NULL)
  485. g_dbus_send_message(btd_get_dbus_connection(), reply);
  486. }
  487. static DBusMessage *channel_acquire(DBusConnection *conn,
  488. DBusMessage *msg, void *user_data)
  489. {
  490. struct hdp_channel *chan = user_data;
  491. struct hdp_tmp_dc_data *dc_data;
  492. GError *gerr = NULL;
  493. DBusMessage *reply;
  494. dc_data = g_new0(struct hdp_tmp_dc_data, 1);
  495. dc_data->msg = dbus_message_ref(msg);
  496. dc_data->hdp_chann = hdp_channel_ref(chan);
  497. if (chan->dev->mcl_conn) {
  498. reply = channel_acquire_continue(hdp_tmp_dc_data_ref(dc_data),
  499. NULL);
  500. hdp_tmp_dc_data_unref(dc_data);
  501. return reply;
  502. }
  503. if (hdp_establish_mcl(chan->dev, channel_acquire_cb,
  504. hdp_tmp_dc_data_ref(dc_data),
  505. hdp_tmp_dc_data_destroy, &gerr))
  506. return NULL;
  507. reply = g_dbus_create_error(msg, ERROR_INTERFACE ".HealthError",
  508. "%s", gerr->message);
  509. hdp_tmp_dc_data_unref(dc_data);
  510. g_error_free(gerr);
  511. return reply;
  512. }
  513. static void close_mdl(struct hdp_channel *hdp_chann)
  514. {
  515. int fd;
  516. fd = mcap_mdl_get_fd(hdp_chann->mdl);
  517. if (fd < 0)
  518. return;
  519. close(fd);
  520. }
  521. static DBusMessage *channel_release(DBusConnection *conn,
  522. DBusMessage *msg, void *user_data)
  523. {
  524. struct hdp_channel *hdp_chann = user_data;
  525. close_mdl(hdp_chann);
  526. return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
  527. }
  528. static void free_echo_data(struct hdp_echo_data *edata)
  529. {
  530. if (edata == NULL)
  531. return;
  532. if (edata->tid > 0)
  533. timeout_remove(edata->tid);
  534. if (edata->buf != NULL)
  535. g_free(edata->buf);
  536. g_free(edata);
  537. }
  538. static void health_channel_destroy(void *data)
  539. {
  540. struct hdp_channel *hdp_chan = data;
  541. struct hdp_device *dev = hdp_chan->dev;
  542. DBG("Destroy Health Channel %s", hdp_chan->path);
  543. if (g_slist_find(dev->channels, hdp_chan) == NULL)
  544. goto end;
  545. dev->channels = g_slist_remove(dev->channels, hdp_chan);
  546. if (hdp_chan->mdep != HDP_MDEP_ECHO)
  547. g_dbus_emit_signal(btd_get_dbus_connection(),
  548. device_get_path(dev->dev),
  549. HEALTH_DEVICE, "ChannelDeleted",
  550. DBUS_TYPE_OBJECT_PATH, &hdp_chan->path,
  551. DBUS_TYPE_INVALID);
  552. if (hdp_chan == dev->fr) {
  553. hdp_channel_unref(dev->fr);
  554. dev->fr = NULL;
  555. }
  556. end:
  557. hdp_channel_unref(hdp_chan);
  558. }
  559. static const GDBusMethodTable health_channels_methods[] = {
  560. { GDBUS_ASYNC_METHOD("Acquire",
  561. NULL, GDBUS_ARGS({ "fd", "h" }),
  562. channel_acquire) },
  563. { GDBUS_METHOD("Release", NULL, NULL, channel_release) },
  564. { }
  565. };
  566. static const GDBusPropertyTable health_channels_properties[] = {
  567. { "Device", "o", channel_property_get_device },
  568. { "Application", "o", channel_property_get_application },
  569. { "Type", "s", channel_property_get_type },
  570. { }
  571. };
  572. static struct hdp_channel *create_channel(struct hdp_device *dev,
  573. uint8_t config,
  574. struct mcap_mdl *mdl,
  575. uint16_t mdlid,
  576. struct hdp_application *app,
  577. GError **err)
  578. {
  579. struct hdp_channel *hdp_chann;
  580. if (dev == NULL) {
  581. g_set_error(err, HDP_ERROR, HDP_UNSPECIFIED_ERROR,
  582. "HDP device uninitialized");
  583. return NULL;
  584. }
  585. hdp_chann = g_new0(struct hdp_channel, 1);
  586. hdp_chann->config = config;
  587. hdp_chann->dev = health_device_ref(dev);
  588. hdp_chann->mdlid = mdlid;
  589. if (mdl != NULL)
  590. hdp_chann->mdl = mcap_mdl_ref(mdl);
  591. if (app != NULL) {
  592. hdp_chann->mdep = app->id;
  593. hdp_chann->app = hdp_application_ref(app);
  594. } else
  595. hdp_chann->edata = g_new0(struct hdp_echo_data, 1);
  596. hdp_chann->path = g_strdup_printf("%s/chan%d",
  597. device_get_path(hdp_chann->dev->dev),
  598. hdp_chann->mdlid);
  599. dev->channels = g_slist_append(dev->channels,
  600. hdp_channel_ref(hdp_chann));
  601. if (hdp_chann->mdep == HDP_MDEP_ECHO)
  602. return hdp_channel_ref(hdp_chann);
  603. if (!g_dbus_register_interface(btd_get_dbus_connection(),
  604. hdp_chann->path, HEALTH_CHANNEL,
  605. health_channels_methods, NULL,
  606. health_channels_properties, hdp_chann,
  607. health_channel_destroy)) {
  608. g_set_error(err, HDP_ERROR, HDP_UNSPECIFIED_ERROR,
  609. "Can't register the channel interface");
  610. health_channel_destroy(hdp_chann);
  611. return NULL;
  612. }
  613. return hdp_channel_ref(hdp_chann);
  614. }
  615. static void remove_channels(struct hdp_device *dev)
  616. {
  617. struct hdp_channel *chan;
  618. char *path;
  619. while (dev->channels != NULL) {
  620. chan = dev->channels->data;
  621. path = g_strdup(chan->path);
  622. if (!g_dbus_unregister_interface(btd_get_dbus_connection(),
  623. path, HEALTH_CHANNEL))
  624. health_channel_destroy(chan);
  625. g_free(path);
  626. }
  627. }
  628. static void close_device_con(struct hdp_device *dev, gboolean cache)
  629. {
  630. if (dev->mcl == NULL)
  631. return;
  632. mcap_close_mcl(dev->mcl, cache);
  633. dev->mcl_conn = FALSE;
  634. if (cache)
  635. return;
  636. device_unref_mcl(dev);
  637. remove_channels(dev);
  638. if (!dev->sdp_present) {
  639. const char *path;
  640. path = device_get_path(dev->dev);
  641. g_dbus_unregister_interface(btd_get_dbus_connection(),
  642. path, HEALTH_DEVICE);
  643. }
  644. }
  645. static int send_echo_data(int sock, const void *buf, uint32_t size)
  646. {
  647. const uint8_t *buf_b = buf;
  648. uint32_t sent = 0;
  649. while (sent < size) {
  650. int n = write(sock, buf_b + sent, size - sent);
  651. if (n < 0)
  652. return -1;
  653. sent += n;
  654. }
  655. return 0;
  656. }
  657. static gboolean serve_echo(GIOChannel *io_chan, GIOCondition cond,
  658. gpointer data)
  659. {
  660. struct hdp_channel *chan = data;
  661. uint8_t buf[MCAP_DC_MTU];
  662. int fd, len;
  663. if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) {
  664. hdp_channel_unref(chan);
  665. return FALSE;
  666. }
  667. if (chan->edata->echo_done)
  668. goto fail;
  669. chan->edata->echo_done = TRUE;
  670. fd = g_io_channel_unix_get_fd(io_chan);
  671. len = read(fd, buf, sizeof(buf));
  672. if (len < 0)
  673. goto fail;
  674. if (send_echo_data(fd, buf, len) >= 0)
  675. return TRUE;
  676. fail:
  677. close_device_con(chan->dev, FALSE);
  678. hdp_channel_unref(chan);
  679. return FALSE;
  680. }
  681. static gboolean check_channel_conf(struct hdp_channel *chan)
  682. {
  683. GError *err = NULL;
  684. GIOChannel *io;
  685. uint8_t mode;
  686. uint16_t imtu, omtu;
  687. int fd;
  688. fd = mcap_mdl_get_fd(chan->mdl);
  689. if (fd < 0)
  690. return FALSE;
  691. io = g_io_channel_unix_new(fd);
  692. if (!bt_io_get(io, &err,
  693. BT_IO_OPT_MODE, &mode,
  694. BT_IO_OPT_IMTU, &imtu,
  695. BT_IO_OPT_OMTU, &omtu,
  696. BT_IO_OPT_INVALID)) {
  697. error("Error: %s", err->message);
  698. g_io_channel_unref(io);
  699. g_error_free(err);
  700. return FALSE;
  701. }
  702. g_io_channel_unref(io);
  703. switch (chan->config) {
  704. case HDP_RELIABLE_DC:
  705. if (mode != BT_IO_MODE_ERTM)
  706. return FALSE;
  707. break;
  708. case HDP_STREAMING_DC:
  709. if (mode != BT_IO_MODE_STREAMING)
  710. return FALSE;
  711. break;
  712. default:
  713. error("Error: Connected with unknown configuration");
  714. return FALSE;
  715. }
  716. DBG("MDL imtu %d omtu %d Channel imtu %d omtu %d", imtu, omtu,
  717. chan->imtu, chan->omtu);
  718. if (chan->imtu == 0)
  719. chan->imtu = imtu;
  720. if (chan->omtu == 0)
  721. chan->omtu = omtu;
  722. if (chan->imtu != imtu || chan->omtu != omtu)
  723. return FALSE;
  724. return TRUE;
  725. }
  726. static void hdp_mcap_mdl_connected_cb(struct mcap_mdl *mdl, void *data)
  727. {
  728. struct hdp_device *dev = data;
  729. struct hdp_channel *chan;
  730. DBG("");
  731. if (dev->ndc == NULL)
  732. return;
  733. chan = dev->ndc;
  734. if (chan->mdl == NULL)
  735. chan->mdl = mcap_mdl_ref(mdl);
  736. if (g_slist_find(dev->channels, chan) == NULL)
  737. dev->channels = g_slist_prepend(dev->channels,
  738. hdp_channel_ref(chan));
  739. if (!check_channel_conf(chan)) {
  740. close_mdl(chan);
  741. goto end;
  742. }
  743. if (chan->mdep == HDP_MDEP_ECHO) {
  744. GIOChannel *io;
  745. int fd;
  746. fd = mcap_mdl_get_fd(chan->mdl);
  747. if (fd < 0)
  748. goto end;
  749. chan->edata->echo_done = FALSE;
  750. io = g_io_channel_unix_new(fd);
  751. g_io_add_watch(io, G_IO_ERR | G_IO_HUP | G_IO_NVAL | G_IO_IN,
  752. serve_echo, hdp_channel_ref(chan));
  753. g_io_channel_unref(io);
  754. goto end;
  755. }
  756. g_dbus_emit_signal(btd_get_dbus_connection(), device_get_path(dev->dev),
  757. HEALTH_DEVICE, "ChannelConnected",
  758. DBUS_TYPE_OBJECT_PATH, &chan->path,
  759. DBUS_TYPE_INVALID);
  760. if (dev->fr != NULL)
  761. goto end;
  762. dev->fr = hdp_channel_ref(chan);
  763. g_dbus_emit_property_changed(btd_get_dbus_connection(),
  764. device_get_path(dev->dev), HEALTH_DEVICE,
  765. "MainChannel");
  766. end:
  767. hdp_channel_unref(dev->ndc);
  768. dev->ndc = NULL;
  769. }
  770. static void hdp_mcap_mdl_closed_cb(struct mcap_mdl *mdl, void *data)
  771. {
  772. /* struct hdp_device *dev = data; */
  773. DBG("");
  774. /* Nothing to do */
  775. }
  776. static void hdp_mcap_mdl_deleted_cb(struct mcap_mdl *mdl, void *data)
  777. {
  778. struct hdp_device *dev = data;
  779. struct hdp_channel *chan;
  780. char *path;
  781. GSList *l;
  782. DBG("");
  783. l = g_slist_find_custom(dev->channels, mdl, cmp_chan_mdl);
  784. if (l == NULL)
  785. return;
  786. chan = l->data;
  787. path = g_strdup(chan->path);
  788. if (!g_dbus_unregister_interface(btd_get_dbus_connection(),
  789. path, HEALTH_CHANNEL))
  790. health_channel_destroy(chan);
  791. g_free(path);
  792. }
  793. static void hdp_mcap_mdl_aborted_cb(struct mcap_mdl *mdl, void *data)
  794. {
  795. struct hdp_device *dev = data;
  796. DBG("");
  797. if (dev->ndc == NULL)
  798. return;
  799. dev->ndc->mdl = mcap_mdl_ref(mdl);
  800. if (g_slist_find(dev->channels, dev->ndc) == NULL)
  801. dev->channels = g_slist_prepend(dev->channels,
  802. hdp_channel_ref(dev->ndc));
  803. if (dev->ndc->mdep != HDP_MDEP_ECHO)
  804. g_dbus_emit_signal(btd_get_dbus_connection(),
  805. device_get_path(dev->dev),
  806. HEALTH_DEVICE, "ChannelConnected",
  807. DBUS_TYPE_OBJECT_PATH, &dev->ndc->path,
  808. DBUS_TYPE_INVALID);
  809. hdp_channel_unref(dev->ndc);
  810. dev->ndc = NULL;
  811. }
  812. static uint8_t hdp2l2cap_mode(uint8_t hdp_mode)
  813. {
  814. return hdp_mode == HDP_STREAMING_DC ? BT_IO_MODE_STREAMING :
  815. BT_IO_MODE_ERTM;
  816. }
  817. static uint8_t hdp_mcap_mdl_conn_req_cb(struct mcap_mcl *mcl, uint8_t mdepid,
  818. uint16_t mdlid, uint8_t *conf, void *data)
  819. {
  820. struct hdp_device *dev = data;
  821. struct hdp_application *app;
  822. GError *err = NULL;
  823. GSList *l;
  824. DBG("Data channel request");
  825. if (mdepid == HDP_MDEP_ECHO) {
  826. switch (*conf) {
  827. case HDP_NO_PREFERENCE_DC:
  828. *conf = HDP_RELIABLE_DC;
  829. break;
  830. case HDP_RELIABLE_DC:
  831. break;
  832. case HDP_STREAMING_DC:
  833. return MCAP_CONFIGURATION_REJECTED;
  834. default:
  835. /* Special case defined in HDP spec 3.4. When an invalid
  836. * configuration is received we shall close the MCL when
  837. * we are still processing the callback. */
  838. close_device_con(dev, FALSE);
  839. return MCAP_CONFIGURATION_REJECTED; /* not processed */
  840. }
  841. if (!mcap_set_data_chan_mode(dev->hdp_adapter->mi,
  842. BT_IO_MODE_ERTM, &err)) {
  843. error("Error: %s", err->message);
  844. g_error_free(err);
  845. return MCAP_MDL_BUSY;
  846. }
  847. dev->ndc = create_channel(dev, *conf, NULL, mdlid, NULL, NULL);
  848. if (dev->ndc == NULL)
  849. return MCAP_MDL_BUSY;
  850. return MCAP_SUCCESS;
  851. }
  852. l = g_slist_find_custom(applications, &mdepid, cmp_app_id);
  853. if (l == NULL)
  854. return MCAP_INVALID_MDEP;
  855. app = l->data;
  856. /* Check if is the first dc if so,
  857. * only reliable configuration is allowed */
  858. switch (*conf) {
  859. case HDP_NO_PREFERENCE_DC:
  860. if (app->role == HDP_SINK)
  861. return MCAP_CONFIGURATION_REJECTED;
  862. else if (dev->fr && app->chan_type_set)
  863. *conf = app->chan_type;
  864. else
  865. *conf = HDP_RELIABLE_DC;
  866. break;
  867. case HDP_STREAMING_DC:
  868. if (!dev->fr || app->role == HDP_SOURCE)
  869. return MCAP_CONFIGURATION_REJECTED;
  870. break;
  871. case HDP_RELIABLE_DC:
  872. if (app->role == HDP_SOURCE)
  873. return MCAP_CONFIGURATION_REJECTED;
  874. break;
  875. default:
  876. /* Special case defined in HDP spec 3.4. When an invalid
  877. * configuration is received we shall close the MCL when
  878. * we are still processing the callback. */
  879. close_device_con(dev, FALSE);
  880. return MCAP_CONFIGURATION_REJECTED; /* not processed */
  881. }
  882. l = g_slist_find_custom(dev->channels, &mdlid, cmp_chan_mdlid);
  883. if (l != NULL) {
  884. struct hdp_channel *chan = l->data;
  885. char *path;
  886. path = g_strdup(chan->path);
  887. g_dbus_unregister_interface(btd_get_dbus_connection(),
  888. path, HEALTH_CHANNEL);
  889. g_free(path);
  890. }
  891. if (!mcap_set_data_chan_mode(dev->hdp_adapter->mi,
  892. hdp2l2cap_mode(*conf), &err)) {
  893. error("Error: %s", err->message);
  894. g_error_free(err);
  895. return MCAP_MDL_BUSY;
  896. }
  897. dev->ndc = create_channel(dev, *conf, NULL, mdlid, app, NULL);
  898. if (dev->ndc == NULL)
  899. return MCAP_MDL_BUSY;
  900. return MCAP_SUCCESS;
  901. }
  902. static uint8_t hdp_mcap_mdl_reconn_req_cb(struct mcap_mdl *mdl, void *data)
  903. {
  904. struct hdp_device *dev = data;
  905. struct hdp_channel *chan;
  906. GError *err = NULL;
  907. GSList *l;
  908. l = g_slist_find_custom(dev->channels, mdl, cmp_chan_mdl);
  909. if (l == NULL)
  910. return MCAP_INVALID_MDL;
  911. chan = l->data;
  912. if (dev->fr == NULL && chan->config != HDP_RELIABLE_DC &&
  913. chan->mdep != HDP_MDEP_ECHO)
  914. return MCAP_UNSPECIFIED_ERROR;
  915. if (!mcap_set_data_chan_mode(dev->hdp_adapter->mi,
  916. hdp2l2cap_mode(chan->config), &err)) {
  917. error("Error: %s", err->message);
  918. g_error_free(err);
  919. return MCAP_MDL_BUSY;
  920. }
  921. dev->ndc = hdp_channel_ref(chan);
  922. return MCAP_SUCCESS;
  923. }
  924. gboolean hdp_set_mcl_cb(struct hdp_device *device, GError **err)
  925. {
  926. gboolean ret;
  927. if (device->mcl == NULL)
  928. return FALSE;
  929. ret = mcap_mcl_set_cb(device->mcl, device, err,
  930. MCAP_MDL_CB_CONNECTED, hdp_mcap_mdl_connected_cb,
  931. MCAP_MDL_CB_CLOSED, hdp_mcap_mdl_closed_cb,
  932. MCAP_MDL_CB_DELETED, hdp_mcap_mdl_deleted_cb,
  933. MCAP_MDL_CB_ABORTED, hdp_mcap_mdl_aborted_cb,
  934. MCAP_MDL_CB_REMOTE_CONN_REQ, hdp_mcap_mdl_conn_req_cb,
  935. MCAP_MDL_CB_REMOTE_RECONN_REQ, hdp_mcap_mdl_reconn_req_cb,
  936. MCAP_MDL_CB_INVALID);
  937. if (ret)
  938. return TRUE;
  939. error("Can't set mcl callbacks, closing mcl");
  940. close_device_con(device, TRUE);
  941. return FALSE;
  942. }
  943. static void mcl_connected(struct mcap_mcl *mcl, gpointer data)
  944. {
  945. struct hdp_device *hdp_device;
  946. bdaddr_t addr;
  947. GSList *l;
  948. mcap_mcl_get_addr(mcl, &addr);
  949. l = g_slist_find_custom(devices, &addr, cmp_dev_addr);
  950. if (l == NULL) {
  951. struct hdp_adapter *hdp_adapter = data;
  952. struct btd_device *device;
  953. device = btd_adapter_get_device(hdp_adapter->btd_adapter,
  954. &addr, BDADDR_BREDR);
  955. if (!device)
  956. return;
  957. hdp_device = create_health_device(device);
  958. if (!hdp_device)
  959. return;
  960. devices = g_slist_append(devices, hdp_device);
  961. } else
  962. hdp_device = l->data;
  963. hdp_device->mcl = mcap_mcl_ref(mcl);
  964. hdp_device->mcl_conn = TRUE;
  965. DBG("New mcl connected from %s", device_get_path(hdp_device->dev));
  966. hdp_set_mcl_cb(hdp_device, NULL);
  967. }
  968. static void mcl_reconnected(struct mcap_mcl *mcl, gpointer data)
  969. {
  970. struct hdp_device *hdp_device;
  971. GSList *l;
  972. l = g_slist_find_custom(devices, mcl, cmp_dev_mcl);
  973. if (l == NULL)
  974. return;
  975. hdp_device = l->data;
  976. hdp_device->mcl_conn = TRUE;
  977. DBG("MCL reconnected %s", device_get_path(hdp_device->dev));
  978. hdp_set_mcl_cb(hdp_device, NULL);
  979. }
  980. static void mcl_disconnected(struct mcap_mcl *mcl, gpointer data)
  981. {
  982. struct hdp_device *hdp_device;
  983. GSList *l;
  984. l = g_slist_find_custom(devices, mcl, cmp_dev_mcl);
  985. if (l == NULL)
  986. return;
  987. hdp_device = l->data;
  988. hdp_device->mcl_conn = FALSE;
  989. DBG("Mcl disconnected %s", device_get_path(hdp_device->dev));
  990. }
  991. static void mcl_uncached(struct mcap_mcl *mcl, gpointer data)
  992. {
  993. struct hdp_device *hdp_device;
  994. const char *path;
  995. GSList *l;
  996. l = g_slist_find_custom(devices, mcl, cmp_dev_mcl);
  997. if (l == NULL)
  998. return;
  999. hdp_device = l->data;
  1000. device_unref_mcl(hdp_device);
  1001. if (hdp_device->sdp_present)
  1002. return;
  1003. /* Because remote device hasn't announced an HDP record */
  1004. /* the Bluetooth daemon won't notify when the device shall */
  1005. /* be removed. Then we have to remove the HealthDevice */
  1006. /* interface manually */
  1007. path = device_get_path(hdp_device->dev);
  1008. g_dbus_unregister_interface(btd_get_dbus_connection(),
  1009. path, HEALTH_DEVICE);
  1010. DBG("Mcl uncached %s", path);
  1011. }
  1012. static void check_devices_mcl(void)
  1013. {
  1014. struct hdp_device *dev;
  1015. GSList *l, *to_delete = NULL;
  1016. for (l = devices; l; l = l->next) {
  1017. dev = l->data;
  1018. device_unref_mcl(dev);
  1019. if (!dev->sdp_present)
  1020. to_delete = g_slist_append(to_delete, dev);
  1021. else
  1022. remove_channels(dev);
  1023. }
  1024. for (l = to_delete; l; l = l->next) {
  1025. const char *path;
  1026. path = device_get_path(dev->dev);
  1027. g_dbus_unregister_interface(btd_get_dbus_connection(),
  1028. path, HEALTH_DEVICE);
  1029. }
  1030. g_slist_free(to_delete);
  1031. }
  1032. static void release_adapter_instance(struct hdp_adapter *hdp_adapter)
  1033. {
  1034. if (hdp_adapter->mi == NULL)
  1035. return;
  1036. check_devices_mcl();
  1037. mcap_release_instance(hdp_adapter->mi);
  1038. mcap_instance_unref(hdp_adapter->mi);
  1039. hdp_adapter->mi = NULL;
  1040. }
  1041. static gboolean update_adapter(struct hdp_adapter *hdp_adapter)
  1042. {
  1043. GError *err = NULL;
  1044. const bdaddr_t *src;
  1045. if (applications == NULL) {
  1046. release_adapter_instance(hdp_adapter);
  1047. goto update;
  1048. }
  1049. if (hdp_adapter->mi != NULL)
  1050. goto update;
  1051. src = btd_adapter_get_address(hdp_adapter->btd_adapter);
  1052. hdp_adapter->mi = mcap_create_instance(src,
  1053. BT_IO_SEC_MEDIUM, 0, 0,
  1054. mcl_connected, mcl_reconnected,
  1055. mcl_disconnected, mcl_uncached,
  1056. NULL, /* CSP is not used by now */
  1057. hdp_adapter, &err);
  1058. if (hdp_adapter->mi == NULL) {
  1059. error("Error creating the MCAP instance: %s", err->message);
  1060. g_error_free(err);
  1061. return FALSE;
  1062. }
  1063. hdp_adapter->ccpsm = mcap_get_ctrl_psm(hdp_adapter->mi, &err);
  1064. if (err != NULL) {
  1065. error("Error getting MCAP control PSM: %s", err->message);
  1066. goto fail;
  1067. }
  1068. hdp_adapter->dcpsm = mcap_get_data_psm(hdp_adapter->mi, &err);
  1069. if (err != NULL) {
  1070. error("Error getting MCAP data PSM: %s", err->message);
  1071. goto fail;
  1072. }
  1073. update:
  1074. if (hdp_update_sdp_record(hdp_adapter, applications))
  1075. return TRUE;
  1076. error("Error updating the SDP record");
  1077. fail:
  1078. release_adapter_instance(hdp_adapter);
  1079. if (err != NULL)
  1080. g_error_free(err);
  1081. return FALSE;
  1082. }
  1083. static void update_adapter_cb(void *data, void *user_data)
  1084. {
  1085. update_adapter(data);
  1086. }
  1087. int hdp_adapter_register(struct btd_adapter *adapter)
  1088. {
  1089. struct hdp_adapter *hdp_adapter;
  1090. hdp_adapter = g_new0(struct hdp_adapter, 1);
  1091. hdp_adapter->btd_adapter = btd_adapter_ref(adapter);
  1092. if(!update_adapter(hdp_adapter))
  1093. goto fail;
  1094. adapters = g_slist_append(adapters, hdp_adapter);
  1095. return 0;
  1096. fail:
  1097. btd_adapter_unref(hdp_adapter->btd_adapter);
  1098. g_free(hdp_adapter);
  1099. return -1;
  1100. }
  1101. void hdp_adapter_unregister(struct btd_adapter *adapter)
  1102. {
  1103. struct hdp_adapter *hdp_adapter;
  1104. GSList *l;
  1105. l = g_slist_find_custom(adapters, adapter, cmp_adapter);
  1106. if (l == NULL)
  1107. return;
  1108. hdp_adapter = l->data;
  1109. adapters = g_slist_remove(adapters, hdp_adapter);
  1110. if (hdp_adapter->sdp_handler > 0)
  1111. adapter_service_remove(adapter, hdp_adapter->sdp_handler);
  1112. release_adapter_instance(hdp_adapter);
  1113. btd_adapter_unref(hdp_adapter->btd_adapter);
  1114. g_free(hdp_adapter);
  1115. }
  1116. static void delete_echo_channel_cb(GError *err, gpointer chan)
  1117. {
  1118. if (err != NULL && err->code != MCAP_INVALID_MDL) {
  1119. /* TODO: Decide if more action is required here */
  1120. error("Error deleting echo channel: %s", err->message);
  1121. return;
  1122. }
  1123. health_channel_destroy(chan);
  1124. }
  1125. static void delete_echo_channel(struct hdp_channel *chan)
  1126. {
  1127. GError *err = NULL;
  1128. if (!chan->dev->mcl_conn) {
  1129. error("Echo channel cannot be deleted: mcl closed");
  1130. return;
  1131. }
  1132. if (mcap_delete_mdl(chan->mdl, delete_echo_channel_cb,
  1133. hdp_channel_ref(chan),
  1134. (GDestroyNotify) hdp_channel_unref, &err))
  1135. return;
  1136. hdp_channel_unref(chan);
  1137. error("Error deleting the echo channel: %s", err->message);
  1138. g_error_free(err);
  1139. /* TODO: Decide if more action is required here */
  1140. }
  1141. static void abort_echo_channel_cb(GError *err, gpointer data)
  1142. {
  1143. struct hdp_channel *chan = data;
  1144. if (err != NULL && err->code != MCAP_ERROR_INVALID_OPERATION) {
  1145. error("Aborting error: %s", err->message);
  1146. if (err->code == MCAP_INVALID_MDL) {
  1147. /* MDL is removed from MCAP so we can */
  1148. /* free the data channel without sending */
  1149. /* a MD_DELETE_MDL_REQ */
  1150. /* TODO review the above comment */
  1151. /* hdp_channel_unref(chan); */
  1152. }
  1153. return;
  1154. }
  1155. delete_echo_channel(chan);
  1156. }
  1157. static void destroy_create_dc_data(gpointer data)
  1158. {
  1159. struct hdp_create_dc *dc_data = data;
  1160. hdp_create_data_unref(dc_data);
  1161. }
  1162. static void *generate_echo_packet(void)
  1163. {
  1164. uint8_t *buf;
  1165. int i;
  1166. buf = g_malloc(HDP_ECHO_LEN);
  1167. srand(time(NULL));
  1168. for(i = 0; i < HDP_ECHO_LEN; i++)
  1169. buf[i] = rand() % UINT8_MAX;
  1170. return buf;
  1171. }
  1172. static gboolean check_echo(GIOChannel *io_chan, GIOCondition cond,
  1173. gpointer data)
  1174. {
  1175. struct hdp_tmp_dc_data *hdp_conn = data;
  1176. struct hdp_echo_data *edata = hdp_conn->hdp_chann->edata;
  1177. struct hdp_channel *chan = hdp_conn->hdp_chann;
  1178. uint8_t buf[MCAP_DC_MTU];
  1179. DBusMessage *reply;
  1180. gboolean value;
  1181. int fd, len;
  1182. if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) {
  1183. value = FALSE;
  1184. goto end;
  1185. }
  1186. fd = g_io_channel_unix_get_fd(io_chan);
  1187. len = read(fd, buf, sizeof(buf));
  1188. if (len != HDP_ECHO_LEN) {
  1189. value = FALSE;
  1190. goto end;
  1191. }
  1192. value = (memcmp(buf, edata->buf, len) == 0);
  1193. end:
  1194. reply = g_dbus_create_reply(hdp_conn->msg, DBUS_TYPE_BOOLEAN, &value,
  1195. DBUS_TYPE_INVALID);
  1196. g_dbus_send_message(btd_get_dbus_connection(), reply);
  1197. timeout_remove(edata->tid);
  1198. edata->tid = 0;
  1199. g_free(edata->buf);
  1200. edata->buf = NULL;
  1201. if (!value)
  1202. close_device_con(chan->dev, FALSE);
  1203. else
  1204. delete_echo_channel(chan);
  1205. hdp_tmp_dc_data_unref(hdp_conn);
  1206. return FALSE;
  1207. }
  1208. static bool echo_timeout(gpointer data)
  1209. {
  1210. struct hdp_channel *chan = data;
  1211. GIOChannel *io;
  1212. int fd;
  1213. error("Error: Echo request timeout");
  1214. chan->edata->tid = 0;
  1215. fd = mcap_mdl_get_fd(chan->mdl);
  1216. if (fd < 0)
  1217. return FALSE;
  1218. io = g_io_channel_unix_new(fd);
  1219. g_io_channel_shutdown(io, TRUE, NULL);
  1220. return FALSE;
  1221. }
  1222. static void hdp_echo_connect_cb(struct mcap_mdl *mdl, GError *err,
  1223. gpointer data)
  1224. {
  1225. DBusConnection *conn = btd_get_dbus_connection();
  1226. struct hdp_tmp_dc_data *hdp_conn = data;
  1227. struct hdp_echo_data *edata;
  1228. GError *gerr = NULL;
  1229. DBusMessage *reply;
  1230. GIOChannel *io;
  1231. int fd;
  1232. if (err != NULL) {
  1233. reply = g_dbus_create_error(hdp_conn->msg,
  1234. ERROR_INTERFACE ".HealthError",
  1235. "%s", err->message);
  1236. g_dbus_send_message(conn, reply);
  1237. /* Send abort request because remote */
  1238. /* side is now in PENDING state. */
  1239. if (!mcap_mdl_abort(hdp_conn->hdp_chann->mdl,
  1240. abort_echo_channel_cb,
  1241. hdp_channel_ref(hdp_conn->hdp_chann),
  1242. (GDestroyNotify) hdp_channel_unref,
  1243. &gerr)) {
  1244. error("%s", gerr->message);
  1245. g_error_free(gerr);
  1246. hdp_channel_unref(hdp_conn->hdp_chann);
  1247. }
  1248. return;
  1249. }
  1250. fd = mcap_mdl_get_fd(hdp_conn->hdp_chann->mdl);
  1251. if (fd < 0) {
  1252. reply = g_dbus_create_error(hdp_conn->msg,
  1253. ERROR_INTERFACE ".HealthError",
  1254. "Can't write in echo channel");
  1255. g_dbus_send_message(conn, reply);
  1256. delete_echo_channel(hdp_conn->hdp_chann);
  1257. return;
  1258. }
  1259. edata = hdp_conn->hdp_chann->edata;
  1260. edata->buf = generate_echo_packet();
  1261. send_echo_data(fd, edata->buf, HDP_ECHO_LEN);
  1262. io = g_io_channel_unix_new(fd);
  1263. g_io_add_watch(io, G_IO_ERR | G_IO_HUP | G_IO_NVAL | G_IO_IN,
  1264. check_echo, hdp_tmp_dc_data_ref(hdp_conn));
  1265. edata->tid = timeout_add_seconds(ECHO_TIMEOUT, echo_timeout,
  1266. hdp_channel_ref(hdp_conn->hdp_chann),
  1267. (timeout_destroy_func_t) hdp_channel_unref);
  1268. g_io_channel_unref(io);
  1269. }
  1270. static void delete_mdl_cb(GError *err, gpointer data)
  1271. {
  1272. if (err != NULL)
  1273. error("Deleting error: %s", err->message);
  1274. }
  1275. static void abort_and_del_mdl_cb(GError *err, gpointer data)
  1276. {
  1277. struct mcap_mdl *mdl = data;
  1278. GError *gerr = NULL;
  1279. if (err != NULL) {
  1280. error("%s", err->message);
  1281. if (err->code == MCAP_INVALID_MDL) {
  1282. /* MDL is removed from MCAP so we don't */
  1283. /* need to delete it. */
  1284. return;
  1285. }
  1286. }
  1287. if (!mcap_delete_mdl(mdl, delete_mdl_cb, NULL, NULL, &gerr)) {
  1288. error("%s", gerr->message);
  1289. g_error_free(gerr);
  1290. }
  1291. }
  1292. static void abort_mdl_connection_cb(GError *err, gpointer data)
  1293. {
  1294. struct hdp_tmp_dc_data *hdp_conn = data;
  1295. struct hdp_channel *hdp_chann = hdp_conn->hdp_chann;
  1296. if (err != NULL)
  1297. error("Aborting error: %s", err->message);
  1298. /* Connection operation has failed but we have to */
  1299. /* notify the channel created at MCAP level */
  1300. if (hdp_chann->mdep != HDP_MDEP_ECHO)
  1301. g_dbus_emit_signal(btd_get_dbus_connection(),
  1302. device_get_path(hdp_chann->dev->dev),
  1303. HEALTH_DEVICE, "ChannelConnected",
  1304. DBUS_TYPE_OBJECT_PATH, &hdp_chann->path,
  1305. DBUS_TYPE_INVALID);
  1306. }
  1307. static void hdp_mdl_conn_cb(struct mcap_mdl *mdl, GError *err, gpointer data)
  1308. {
  1309. DBusConnection *conn = btd_get_dbus_connection();
  1310. struct hdp_tmp_dc_data *hdp_conn = data;
  1311. struct hdp_channel *hdp_chann = hdp_conn->hdp_chann;
  1312. struct hdp_device *dev = hdp_chann->dev;
  1313. DBusMessage *reply;
  1314. GError *gerr = NULL;
  1315. if (err != NULL) {
  1316. error("%s", err->message);
  1317. reply = g_dbus_create_reply(hdp_conn->msg,
  1318. DBUS_TYPE_OBJECT_PATH, &hdp_chann->path,
  1319. DBUS_TYPE_INVALID);
  1320. g_dbus_send_message(conn, reply);
  1321. /* Send abort request because remote side */
  1322. /* is now in PENDING state */
  1323. if (!mcap_mdl_abort(hdp_chann->mdl, abort_mdl_connection_cb,
  1324. hdp_tmp_dc_data_ref(hdp_conn),
  1325. hdp_tmp_dc_data_destroy, &gerr)) {
  1326. hdp_tmp_dc_data_unref(hdp_conn);
  1327. error("%s", gerr->message);
  1328. g_error_free(gerr);
  1329. }
  1330. return;
  1331. }
  1332. reply = g_dbus_create_reply(hdp_conn->msg,
  1333. DBUS_TYPE_OBJECT_PATH, &hdp_chann->path,
  1334. DBUS_TYPE_INVALID);
  1335. g_dbus_send_message(conn, reply);
  1336. g_dbus_emit_signal(conn, device_get_path(hdp_chann->dev->dev),
  1337. HEALTH_DEVICE, "ChannelConnected",
  1338. DBUS_TYPE_OBJECT_PATH, &hdp_chann->path,
  1339. DBUS_TYPE_INVALID);
  1340. if (!check_channel_conf(hdp_chann)) {
  1341. close_mdl(hdp_chann);
  1342. return;
  1343. }
  1344. if (dev->fr != NULL)
  1345. return;
  1346. dev->fr = hdp_channel_ref(hdp_chann);
  1347. g_dbus_emit_property_changed(btd_get_dbus_connection(),
  1348. device_get_path(dev->dev), HEALTH_DEVICE,
  1349. "MainChannel");
  1350. }
  1351. static void device_create_mdl_cb(struct mcap_mdl *mdl, uint8_t conf,
  1352. GError *err, gpointer data)
  1353. {
  1354. DBusConnection *conn = btd_get_dbus_connection();
  1355. struct hdp_create_dc *user_data = data;
  1356. struct hdp_tmp_dc_data *hdp_conn;
  1357. struct hdp_channel *hdp_chan;
  1358. GError *gerr = NULL;
  1359. DBusMessage *reply;
  1360. if (err != NULL) {
  1361. reply = g_dbus_create_error(user_data->msg,
  1362. ERROR_INTERFACE ".HealthError",
  1363. "%s", err->message);
  1364. g_dbus_send_message(conn, reply);
  1365. return;
  1366. }
  1367. if (user_data->mdep != HDP_MDEP_ECHO &&
  1368. user_data->config == HDP_NO_PREFERENCE_DC) {
  1369. if (user_data->dev->fr == NULL && conf != HDP_RELIABLE_DC) {
  1370. g_set_error(&gerr, HDP_ERROR, HDP_CONNECTION_ERROR,
  1371. "Data channel aborted, first data "
  1372. "channel should be reliable");
  1373. goto fail;
  1374. } else if (conf == HDP_NO_PREFERENCE_DC ||
  1375. conf > HDP_STREAMING_DC) {
  1376. g_set_error(&gerr, HDP_ERROR, HDP_CONNECTION_ERROR,
  1377. "Data channel aborted, "
  1378. "configuration error");
  1379. goto fail;
  1380. }
  1381. }
  1382. hdp_chan = create_channel(user_data->dev, conf, mdl,
  1383. mcap_mdl_get_mdlid(mdl),
  1384. user_data->app, &gerr);
  1385. if (hdp_chan == NULL)
  1386. goto fail;
  1387. hdp_conn = g_new0(struct hdp_tmp_dc_data, 1);
  1388. hdp_conn->msg = dbus_message_ref(user_data->msg);
  1389. hdp_conn->hdp_chann = hdp_chan;
  1390. hdp_conn->cb = user_data->cb;
  1391. hdp_chan->mdep = user_data->mdep;
  1392. if (hdp_get_dcpsm(hdp_chan->dev, hdp_get_dcpsm_cb,
  1393. hdp_tmp_dc_data_ref(hdp_conn),
  1394. hdp_tmp_dc_data_destroy, &gerr))
  1395. return;
  1396. error("%s", gerr->message);
  1397. g_error_free(gerr);
  1398. reply = g_dbus_create_reply(hdp_conn->msg,
  1399. DBUS_TYPE_OBJECT_PATH, &hdp_chan->path,
  1400. DBUS_TYPE_INVALID);
  1401. g_dbus_send_message(conn, reply);
  1402. hdp_tmp_dc_data_unref(hdp_conn);
  1403. /* Send abort request because remote side is now in PENDING state */
  1404. if (!mcap_mdl_abort(hdp_chan->mdl, abort_mdl_connection_cb,
  1405. hdp_tmp_dc_data_ref(hdp_conn),
  1406. hdp_tmp_dc_data_destroy, &gerr)) {
  1407. hdp_tmp_dc_data_unref(hdp_conn);
  1408. error("%s", gerr->message);
  1409. g_error_free(gerr);
  1410. }
  1411. return;
  1412. fail:
  1413. reply = g_dbus_create_error(user_data->msg,
  1414. ERROR_INTERFACE ".HealthError",
  1415. "%s", gerr->message);
  1416. g_dbus_send_message(conn, reply);
  1417. g_error_free(gerr);
  1418. /* Send abort request because remote side is now in PENDING */
  1419. /* state. Then we have to delete it because we couldn't */
  1420. /* register the HealthChannel interface */
  1421. if (!mcap_mdl_abort(mdl, abort_and_del_mdl_cb, mcap_mdl_ref(mdl),
  1422. (GDestroyNotify) mcap_mdl_unref, &gerr)) {
  1423. error("%s", gerr->message);
  1424. g_error_free(gerr);
  1425. mcap_mdl_unref(mdl);
  1426. }
  1427. }
  1428. static void device_create_dc_cb(gpointer user_data, GError *err)
  1429. {
  1430. DBusConnection *conn = btd_get_dbus_connection();
  1431. struct hdp_create_dc *data = user_data;
  1432. DBusMessage *reply;
  1433. GError *gerr = NULL;
  1434. if (err != NULL) {
  1435. reply = g_dbus_create_error(data->msg,
  1436. ERROR_INTERFACE ".HealthError",
  1437. "%s", err->message);
  1438. g_dbus_send_message(conn, reply);
  1439. return;
  1440. }
  1441. if (data->dev->mcl == NULL) {
  1442. g_set_error(&gerr, HDP_ERROR, HDP_CONNECTION_ERROR,
  1443. "Mcl was closed");
  1444. goto fail;
  1445. }
  1446. hdp_create_data_ref(data);
  1447. if (mcap_create_mdl(data->dev->mcl, data->mdep, data->config,
  1448. device_create_mdl_cb, data,
  1449. destroy_create_dc_data, &gerr))
  1450. return;
  1451. hdp_create_data_unref(data);
  1452. fail:
  1453. reply = g_dbus_create_error(data->msg, ERROR_INTERFACE ".HealthError",
  1454. "%s", gerr->message);
  1455. g_error_free(gerr);
  1456. g_dbus_send_message(conn, reply);
  1457. }
  1458. static DBusMessage *device_echo(DBusConnection *conn,
  1459. DBusMessage *msg, void *user_data)
  1460. {
  1461. struct hdp_device *device = user_data;
  1462. struct hdp_create_dc *data;
  1463. DBusMessage *reply;
  1464. GError *err = NULL;
  1465. data = g_new0(struct hdp_create_dc, 1);
  1466. data->dev = health_device_ref(device);
  1467. data->mdep = HDP_MDEP_ECHO;
  1468. data->config = HDP_RELIABLE_DC;
  1469. data->msg = dbus_message_ref(msg);
  1470. data->cb = hdp_echo_connect_cb;
  1471. hdp_create_data_ref(data);
  1472. if (device->mcl_conn && device->mcl) {
  1473. if (mcap_create_mdl(device->mcl, data->mdep, data->config,
  1474. device_create_mdl_cb, data,
  1475. destroy_create_dc_data, &err))
  1476. return NULL;
  1477. goto fail;
  1478. }
  1479. if (hdp_establish_mcl(data->dev, device_create_dc_cb,
  1480. data, destroy_create_dc_data, &err))
  1481. return NULL;
  1482. fail:
  1483. reply = g_dbus_create_error(msg, ERROR_INTERFACE ".HealthError",
  1484. "%s", err->message);
  1485. g_error_free(err);
  1486. hdp_create_data_unref(data);
  1487. return reply;
  1488. }
  1489. static void device_get_mdep_cb(uint8_t mdep, gpointer data, GError *err)
  1490. {
  1491. DBusConnection *conn = btd_get_dbus_connection();
  1492. struct hdp_create_dc *dc_data, *user_data = data;
  1493. DBusMessage *reply;
  1494. GError *gerr = NULL;
  1495. if (err != NULL) {
  1496. reply = g_dbus_create_error(user_data->msg,
  1497. ERROR_INTERFACE ".HealthError",
  1498. "%s", err->message);
  1499. g_dbus_send_message(conn, reply);
  1500. return;
  1501. }
  1502. dc_data = hdp_create_data_ref(user_data);
  1503. dc_data->mdep = mdep;
  1504. if (user_data->dev->mcl_conn) {
  1505. device_create_dc_cb(dc_data, NULL);
  1506. hdp_create_data_unref(dc_data);
  1507. return;
  1508. }
  1509. if (hdp_establish_mcl(dc_data->dev, device_create_dc_cb,
  1510. dc_data, destroy_create_dc_data, &gerr))
  1511. return;
  1512. reply = g_dbus_create_error(user_data->msg,
  1513. ERROR_INTERFACE ".HealthError",
  1514. "%s", gerr->message);
  1515. hdp_create_data_unref(dc_data);
  1516. g_error_free(gerr);
  1517. g_dbus_send_message(conn, reply);
  1518. }
  1519. static DBusMessage *device_create_channel(DBusConnection *conn,
  1520. DBusMessage *msg, void *user_data)
  1521. {
  1522. struct hdp_device *device = user_data;
  1523. struct hdp_application *app;
  1524. struct hdp_create_dc *data;
  1525. char *app_path, *conf;
  1526. DBusMessage *reply;
  1527. GError *err = NULL;
  1528. uint8_t config;
  1529. GSList *l;
  1530. if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &app_path,
  1531. DBUS_TYPE_STRING, &conf,
  1532. DBUS_TYPE_INVALID))
  1533. return btd_error_invalid_args(msg);
  1534. l = g_slist_find_custom(applications, app_path, cmp_app);
  1535. if (l == NULL)
  1536. return btd_error_invalid_args(msg);
  1537. app = l->data;
  1538. if (g_ascii_strcasecmp("reliable", conf) == 0)
  1539. config = HDP_RELIABLE_DC;
  1540. else if (g_ascii_strcasecmp("streaming", conf) == 0)
  1541. config = HDP_STREAMING_DC;
  1542. else if (g_ascii_strcasecmp("any", conf) == 0)
  1543. config = HDP_NO_PREFERENCE_DC;
  1544. else
  1545. return btd_error_invalid_args(msg);
  1546. if (app->role == HDP_SINK && config != HDP_NO_PREFERENCE_DC)
  1547. return btd_error_invalid_args(msg);
  1548. if (app->role == HDP_SOURCE && config == HDP_NO_PREFERENCE_DC)
  1549. return btd_error_invalid_args(msg);
  1550. if (!device->fr && config == HDP_STREAMING_DC)
  1551. return btd_error_invalid_args(msg);
  1552. data = g_new0(struct hdp_create_dc, 1);
  1553. data->dev = health_device_ref(device);
  1554. data->config = config;
  1555. data->app = hdp_application_ref(app);
  1556. data->msg = dbus_message_ref(msg);
  1557. data->cb = hdp_mdl_conn_cb;
  1558. if (hdp_get_mdep(device, l->data, device_get_mdep_cb,
  1559. hdp_create_data_ref(data),
  1560. destroy_create_dc_data, &err))
  1561. return NULL;
  1562. reply = g_dbus_create_error(msg, ERROR_INTERFACE ".HealthError",
  1563. "%s", err->message);
  1564. g_error_free(err);
  1565. hdp_create_data_unref(data);
  1566. return reply;
  1567. }
  1568. static void hdp_mdl_delete_cb(GError *err, gpointer data)
  1569. {
  1570. DBusConnection *conn = btd_get_dbus_connection();
  1571. struct hdp_tmp_dc_data *del_data = data;
  1572. DBusMessage *reply;
  1573. char *path;
  1574. if (err != NULL && err->code != MCAP_INVALID_MDL) {
  1575. reply = g_dbus_create_error(del_data->msg,
  1576. ERROR_INTERFACE ".HealthError",
  1577. "%s", err->message);
  1578. g_dbus_send_message(conn, reply);
  1579. return;
  1580. }
  1581. path = g_strdup(del_data->hdp_chann->path);
  1582. g_dbus_unregister_interface(conn, path, HEALTH_CHANNEL);
  1583. g_free(path);
  1584. reply = g_dbus_create_reply(del_data->msg, DBUS_TYPE_INVALID);
  1585. g_dbus_send_message(conn, reply);
  1586. }
  1587. static void hdp_continue_del_cb(gpointer user_data, GError *err)
  1588. {
  1589. DBusConnection *conn = btd_get_dbus_connection();
  1590. struct hdp_tmp_dc_data *del_data = user_data;
  1591. GError *gerr = NULL;
  1592. DBusMessage *reply;
  1593. if (err != NULL) {
  1594. reply = g_dbus_create_error(del_data->msg,
  1595. ERROR_INTERFACE ".HealthError",
  1596. "%s", err->message);
  1597. g_dbus_send_message(conn, reply);
  1598. return;
  1599. }
  1600. if (mcap_delete_mdl(del_data->hdp_chann->mdl, hdp_mdl_delete_cb,
  1601. hdp_tmp_dc_data_ref(del_data),
  1602. hdp_tmp_dc_data_destroy, &gerr))
  1603. return;
  1604. reply = g_dbus_create_error(del_data->msg,
  1605. ERROR_INTERFACE ".HealthError",
  1606. "%s", gerr->message);
  1607. hdp_tmp_dc_data_unref(del_data);
  1608. g_error_free(gerr);
  1609. g_dbus_send_message(conn, reply);
  1610. }
  1611. static DBusMessage *device_destroy_channel(DBusConnection *conn,
  1612. DBusMessage *msg, void *user_data)
  1613. {
  1614. struct hdp_device *device = user_data;
  1615. struct hdp_tmp_dc_data *del_data;
  1616. struct hdp_channel *hdp_chan;
  1617. DBusMessage *reply;
  1618. GError *err = NULL;
  1619. char *path;
  1620. GSList *l;
  1621. if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
  1622. DBUS_TYPE_INVALID)){
  1623. return btd_error_invalid_args(msg);
  1624. }
  1625. l = g_slist_find_custom(device->channels, path, cmp_chan_path);
  1626. if (l == NULL)
  1627. return btd_error_invalid_args(msg);
  1628. hdp_chan = l->data;
  1629. del_data = g_new0(struct hdp_tmp_dc_data, 1);
  1630. del_data->msg = dbus_message_ref(msg);
  1631. del_data->hdp_chann = hdp_channel_ref(hdp_chan);
  1632. if (device->mcl_conn) {
  1633. if (mcap_delete_mdl(hdp_chan->mdl, hdp_mdl_delete_cb,
  1634. hdp_tmp_dc_data_ref(del_data),
  1635. hdp_tmp_dc_data_destroy, &err))
  1636. return NULL;
  1637. goto fail;
  1638. }
  1639. if (hdp_establish_mcl(device, hdp_continue_del_cb,
  1640. hdp_tmp_dc_data_ref(del_data),
  1641. hdp_tmp_dc_data_destroy, &err))
  1642. return NULL;
  1643. fail:
  1644. reply = g_dbus_create_error(msg, ERROR_INTERFACE ".HealthError",
  1645. "%s", err->message);
  1646. hdp_tmp_dc_data_unref(del_data);
  1647. g_error_free(err);
  1648. return reply;
  1649. }
  1650. static gboolean dev_property_exists_main_channel(
  1651. const GDBusPropertyTable *property, void *data)
  1652. {
  1653. struct hdp_device *device = data;
  1654. return device->fr != NULL;
  1655. }
  1656. static gboolean dev_property_get_main_channel(
  1657. const GDBusPropertyTable *property,
  1658. DBusMessageIter *iter, void *data)
  1659. {
  1660. struct hdp_device *device = data;
  1661. if (device->fr == NULL)
  1662. return FALSE;
  1663. dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
  1664. &device->fr->path);
  1665. return TRUE;
  1666. }
  1667. static void health_device_destroy(void *data)
  1668. {
  1669. struct hdp_device *device = data;
  1670. DBG("Unregistered interface %s on path %s", HEALTH_DEVICE,
  1671. device_get_path(device->dev));
  1672. remove_channels(device);
  1673. if (device->ndc != NULL) {
  1674. hdp_channel_unref(device->ndc);
  1675. device->ndc = NULL;
  1676. }
  1677. devices = g_slist_remove(devices, device);
  1678. health_device_unref(device);
  1679. }
  1680. static const GDBusMethodTable health_device_methods[] = {
  1681. { GDBUS_ASYNC_METHOD("Echo",
  1682. NULL, GDBUS_ARGS({ "value", "b" }), device_echo) },
  1683. { GDBUS_ASYNC_METHOD("CreateChannel",
  1684. GDBUS_ARGS({ "application", "o" },
  1685. { "configuration", "s" }),
  1686. GDBUS_ARGS({ "channel", "o" }),
  1687. device_create_channel) },
  1688. { GDBUS_ASYNC_METHOD("DestroyChannel",
  1689. GDBUS_ARGS({ "channel", "o" }), NULL,
  1690. device_destroy_channel) },
  1691. { }
  1692. };
  1693. static const GDBusSignalTable health_device_signals[] = {
  1694. { GDBUS_SIGNAL("ChannelConnected",
  1695. GDBUS_ARGS({ "channel", "o" })) },
  1696. { GDBUS_SIGNAL("ChannelDeleted",
  1697. GDBUS_ARGS({ "channel", "o" })) },
  1698. { }
  1699. };
  1700. static const GDBusPropertyTable health_device_properties[] = {
  1701. { "MainChannel", "o", dev_property_get_main_channel, NULL,
  1702. dev_property_exists_main_channel },
  1703. { }
  1704. };
  1705. static struct hdp_device *create_health_device(struct btd_device *device)
  1706. {
  1707. struct btd_adapter *adapter = device_get_adapter(device);
  1708. const char *path = device_get_path(device);
  1709. struct hdp_device *dev;
  1710. GSList *l;
  1711. if (device == NULL)
  1712. return NULL;
  1713. dev = g_new0(struct hdp_device, 1);
  1714. dev->dev = btd_device_ref(device);
  1715. health_device_ref(dev);
  1716. l = g_slist_find_custom(adapters, adapter, cmp_adapter);
  1717. if (l == NULL)
  1718. goto fail;
  1719. dev->hdp_adapter = l->data;
  1720. if (!g_dbus_register_interface(btd_get_dbus_connection(),
  1721. path, HEALTH_DEVICE,
  1722. health_device_methods,
  1723. health_device_signals,
  1724. health_device_properties,
  1725. dev, health_device_destroy)) {
  1726. error("D-Bus failed to register %s interface", HEALTH_DEVICE);
  1727. goto fail;
  1728. }
  1729. DBG("Registered interface %s on path %s", HEALTH_DEVICE, path);
  1730. return dev;
  1731. fail:
  1732. health_device_unref(dev);
  1733. return NULL;
  1734. }
  1735. int hdp_device_register(struct btd_device *device)
  1736. {
  1737. struct hdp_device *hdev;
  1738. GSList *l;
  1739. l = g_slist_find_custom(devices, device, cmp_device);
  1740. if (l != NULL) {
  1741. hdev = l->data;
  1742. hdev->sdp_present = TRUE;
  1743. return 0;
  1744. }
  1745. hdev = create_health_device(device);
  1746. if (hdev == NULL)
  1747. return -1;
  1748. hdev->sdp_present = TRUE;
  1749. devices = g_slist_prepend(devices, hdev);
  1750. return 0;
  1751. }
  1752. void hdp_device_unregister(struct btd_device *device)
  1753. {
  1754. struct hdp_device *hdp_dev;
  1755. const char *path;
  1756. GSList *l;
  1757. l = g_slist_find_custom(devices, device, cmp_device);
  1758. if (l == NULL)
  1759. return;
  1760. hdp_dev = l->data;
  1761. path = device_get_path(hdp_dev->dev);
  1762. g_dbus_unregister_interface(btd_get_dbus_connection(),
  1763. path, HEALTH_DEVICE);
  1764. }
  1765. int hdp_manager_start(void)
  1766. {
  1767. DBG("Starting Health manager");
  1768. if (!g_dbus_register_interface(btd_get_dbus_connection(),
  1769. MANAGER_PATH, HEALTH_MANAGER,
  1770. health_manager_methods, NULL, NULL,
  1771. NULL, manager_path_unregister)) {
  1772. error("D-Bus failed to register %s interface", HEALTH_MANAGER);
  1773. return -1;
  1774. }
  1775. return 0;
  1776. }
  1777. void hdp_manager_stop(void)
  1778. {
  1779. g_dbus_unregister_interface(btd_get_dbus_connection(),
  1780. MANAGER_PATH, HEALTH_MANAGER);
  1781. DBG("Stopped Health manager");
  1782. }
  1783. struct hdp_device *health_device_ref(struct hdp_device *hdp_dev)
  1784. {
  1785. hdp_dev->ref++;
  1786. DBG("(%p): ref=%d", hdp_dev, hdp_dev->ref);
  1787. return hdp_dev;
  1788. }
  1789. void health_device_unref(struct hdp_device *hdp_dev)
  1790. {
  1791. hdp_dev->ref--;
  1792. DBG("(%p): ref=%d", hdp_dev, hdp_dev->ref);
  1793. if (hdp_dev->ref > 0)
  1794. return;
  1795. free_health_device(hdp_dev);
  1796. }