transport.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. *
  4. * BlueZ - Bluetooth protocol stack for Linux
  5. *
  6. * Copyright (C) 2006-2007 Nokia Corporation
  7. * Copyright (C) 2004-2009 Marcel Holtmann <marcel@holtmann.org>
  8. *
  9. *
  10. */
  11. #ifdef HAVE_CONFIG_H
  12. #include <config.h>
  13. #endif
  14. #define _GNU_SOURCE
  15. #include <errno.h>
  16. #include <glib.h>
  17. #include "lib/bluetooth.h"
  18. #include "lib/sdp.h"
  19. #include "lib/uuid.h"
  20. #include "gdbus/gdbus.h"
  21. #include "src/adapter.h"
  22. #include "src/device.h"
  23. #include "src/dbus-common.h"
  24. #include "src/log.h"
  25. #include "src/error.h"
  26. #include "src/shared/queue.h"
  27. #include "avdtp.h"
  28. #include "media.h"
  29. #include "transport.h"
  30. #include "a2dp.h"
  31. #include "sink.h"
  32. #include "source.h"
  33. #include "avrcp.h"
  34. #define MEDIA_TRANSPORT_INTERFACE "org.bluez.MediaTransport1"
  35. typedef enum {
  36. TRANSPORT_STATE_IDLE, /* Not acquired and suspended */
  37. TRANSPORT_STATE_PENDING, /* Playing but not acquired */
  38. TRANSPORT_STATE_REQUESTING, /* Acquire in progress */
  39. TRANSPORT_STATE_ACTIVE, /* Acquired and playing */
  40. TRANSPORT_STATE_SUSPENDING, /* Release in progress */
  41. } transport_state_t;
  42. static char *str_state[] = {
  43. "TRANSPORT_STATE_IDLE",
  44. "TRANSPORT_STATE_PENDING",
  45. "TRANSPORT_STATE_REQUESTING",
  46. "TRANSPORT_STATE_ACTIVE",
  47. "TRANSPORT_STATE_SUSPENDING",
  48. };
  49. struct media_request {
  50. DBusMessage *msg;
  51. guint id;
  52. };
  53. struct media_owner {
  54. struct media_transport *transport;
  55. struct media_request *pending;
  56. char *name;
  57. guint watch;
  58. };
  59. struct a2dp_transport {
  60. struct avdtp *session;
  61. uint16_t delay;
  62. int8_t volume;
  63. };
  64. struct media_transport {
  65. char *path; /* Transport object path */
  66. struct btd_device *device; /* Transport device */
  67. const char *remote_endpoint; /* Transport remote SEP */
  68. struct media_endpoint *endpoint; /* Transport endpoint */
  69. struct media_owner *owner; /* Transport owner */
  70. uint8_t *configuration; /* Transport configuration */
  71. int size; /* Transport configuration size */
  72. int fd; /* Transport file descriptor */
  73. uint16_t imtu; /* Transport input mtu */
  74. uint16_t omtu; /* Transport output mtu */
  75. transport_state_t state;
  76. guint hs_watch;
  77. guint source_watch;
  78. guint sink_watch;
  79. guint (*resume) (struct media_transport *transport,
  80. struct media_owner *owner);
  81. guint (*suspend) (struct media_transport *transport,
  82. struct media_owner *owner);
  83. void (*cancel) (struct media_transport *transport,
  84. guint id);
  85. GDestroyNotify destroy;
  86. void *data;
  87. };
  88. static GSList *transports = NULL;
  89. static const char *state2str(transport_state_t state)
  90. {
  91. switch (state) {
  92. case TRANSPORT_STATE_IDLE:
  93. case TRANSPORT_STATE_REQUESTING:
  94. return "idle";
  95. case TRANSPORT_STATE_PENDING:
  96. return "pending";
  97. case TRANSPORT_STATE_ACTIVE:
  98. case TRANSPORT_STATE_SUSPENDING:
  99. return "active";
  100. }
  101. return NULL;
  102. }
  103. static gboolean state_in_use(transport_state_t state)
  104. {
  105. switch (state) {
  106. case TRANSPORT_STATE_IDLE:
  107. case TRANSPORT_STATE_PENDING:
  108. return FALSE;
  109. case TRANSPORT_STATE_REQUESTING:
  110. case TRANSPORT_STATE_ACTIVE:
  111. case TRANSPORT_STATE_SUSPENDING:
  112. return TRUE;
  113. }
  114. return FALSE;
  115. }
  116. static void transport_set_state(struct media_transport *transport,
  117. transport_state_t state)
  118. {
  119. transport_state_t old_state = transport->state;
  120. const char *str;
  121. if (old_state == state)
  122. return;
  123. transport->state = state;
  124. DBG("State changed %s: %s -> %s", transport->path, str_state[old_state],
  125. str_state[state]);
  126. str = state2str(state);
  127. if (g_strcmp0(str, state2str(old_state)) != 0)
  128. g_dbus_emit_property_changed(btd_get_dbus_connection(),
  129. transport->path,
  130. MEDIA_TRANSPORT_INTERFACE,
  131. "State");
  132. }
  133. void media_transport_destroy(struct media_transport *transport)
  134. {
  135. char *path;
  136. if (transport->sink_watch)
  137. sink_remove_state_cb(transport->sink_watch);
  138. if (transport->source_watch)
  139. source_remove_state_cb(transport->source_watch);
  140. path = g_strdup(transport->path);
  141. g_dbus_unregister_interface(btd_get_dbus_connection(), path,
  142. MEDIA_TRANSPORT_INTERFACE);
  143. g_free(path);
  144. }
  145. static struct media_request *media_request_create(DBusMessage *msg, guint id)
  146. {
  147. struct media_request *req;
  148. req = g_new0(struct media_request, 1);
  149. req->msg = dbus_message_ref(msg);
  150. req->id = id;
  151. DBG("Request created: method=%s id=%u", dbus_message_get_member(msg),
  152. id);
  153. return req;
  154. }
  155. static void media_request_reply(struct media_request *req, int err)
  156. {
  157. DBusMessage *reply;
  158. DBG("Request %s Reply %s", dbus_message_get_member(req->msg),
  159. strerror(err));
  160. if (!err)
  161. reply = g_dbus_create_reply(req->msg, DBUS_TYPE_INVALID);
  162. else
  163. reply = g_dbus_create_error(req->msg,
  164. ERROR_INTERFACE ".Failed",
  165. "%s", strerror(err));
  166. g_dbus_send_message(btd_get_dbus_connection(), reply);
  167. }
  168. static void media_owner_remove(struct media_owner *owner)
  169. {
  170. struct media_transport *transport = owner->transport;
  171. struct media_request *req = owner->pending;
  172. if (!req)
  173. return;
  174. DBG("Owner %s Request %s", owner->name,
  175. dbus_message_get_member(req->msg));
  176. if (req->id)
  177. transport->cancel(transport, req->id);
  178. owner->pending = NULL;
  179. if (req->msg)
  180. dbus_message_unref(req->msg);
  181. g_free(req);
  182. }
  183. static void media_owner_free(struct media_owner *owner)
  184. {
  185. DBG("Owner %s", owner->name);
  186. media_owner_remove(owner);
  187. g_free(owner->name);
  188. g_free(owner);
  189. }
  190. static void media_transport_remove_owner(struct media_transport *transport)
  191. {
  192. struct media_owner *owner = transport->owner;
  193. DBG("Transport %s Owner %s", transport->path, owner->name);
  194. /* Reply if owner has a pending request */
  195. if (owner->pending)
  196. media_request_reply(owner->pending, EIO);
  197. transport->owner = NULL;
  198. if (owner->watch)
  199. g_dbus_remove_watch(btd_get_dbus_connection(), owner->watch);
  200. media_owner_free(owner);
  201. if (state_in_use(transport->state))
  202. transport->suspend(transport, NULL);
  203. }
  204. static gboolean media_transport_set_fd(struct media_transport *transport,
  205. int fd, uint16_t imtu, uint16_t omtu)
  206. {
  207. if (transport->fd == fd)
  208. return TRUE;
  209. transport->fd = fd;
  210. transport->imtu = imtu;
  211. transport->omtu = omtu;
  212. info("%s: fd(%d) ready", transport->path, fd);
  213. return TRUE;
  214. }
  215. static void a2dp_resume_complete(struct avdtp *session, int err,
  216. void *user_data)
  217. {
  218. struct media_owner *owner = user_data;
  219. struct media_request *req = owner->pending;
  220. struct media_transport *transport = owner->transport;
  221. struct a2dp_sep *sep = media_endpoint_get_sep(transport->endpoint);
  222. struct avdtp_stream *stream;
  223. int fd;
  224. uint16_t imtu, omtu;
  225. gboolean ret;
  226. req->id = 0;
  227. if (err)
  228. goto fail;
  229. stream = a2dp_sep_get_stream(sep);
  230. if (stream == NULL)
  231. goto fail;
  232. ret = avdtp_stream_get_transport(stream, &fd, &imtu, &omtu, NULL);
  233. if (ret == FALSE)
  234. goto fail;
  235. media_transport_set_fd(transport, fd, imtu, omtu);
  236. ret = g_dbus_send_reply(btd_get_dbus_connection(), req->msg,
  237. DBUS_TYPE_UNIX_FD, &fd,
  238. DBUS_TYPE_UINT16, &imtu,
  239. DBUS_TYPE_UINT16, &omtu,
  240. DBUS_TYPE_INVALID);
  241. if (ret == FALSE)
  242. goto fail;
  243. media_owner_remove(owner);
  244. transport_set_state(transport, TRANSPORT_STATE_ACTIVE);
  245. return;
  246. fail:
  247. media_transport_remove_owner(transport);
  248. }
  249. static guint resume_a2dp(struct media_transport *transport,
  250. struct media_owner *owner)
  251. {
  252. struct a2dp_transport *a2dp = transport->data;
  253. struct media_endpoint *endpoint = transport->endpoint;
  254. struct a2dp_sep *sep = media_endpoint_get_sep(endpoint);
  255. guint id;
  256. if (a2dp->session == NULL) {
  257. a2dp->session = a2dp_avdtp_get(transport->device);
  258. if (a2dp->session == NULL)
  259. return 0;
  260. }
  261. if (state_in_use(transport->state))
  262. return a2dp_resume(a2dp->session, sep, a2dp_resume_complete,
  263. owner);
  264. if (a2dp_sep_lock(sep, a2dp->session) == FALSE)
  265. return 0;
  266. id = a2dp_resume(a2dp->session, sep, a2dp_resume_complete, owner);
  267. if (id == 0) {
  268. a2dp_sep_unlock(sep, a2dp->session);
  269. return 0;
  270. }
  271. if (transport->state == TRANSPORT_STATE_IDLE)
  272. transport_set_state(transport, TRANSPORT_STATE_REQUESTING);
  273. return id;
  274. }
  275. static void a2dp_suspend_complete(struct avdtp *session, int err,
  276. void *user_data)
  277. {
  278. struct media_owner *owner = user_data;
  279. struct media_transport *transport = owner->transport;
  280. struct a2dp_transport *a2dp = transport->data;
  281. struct a2dp_sep *sep = media_endpoint_get_sep(transport->endpoint);
  282. /* Release always succeeds */
  283. if (owner->pending) {
  284. owner->pending->id = 0;
  285. media_request_reply(owner->pending, 0);
  286. media_owner_remove(owner);
  287. }
  288. a2dp_sep_unlock(sep, a2dp->session);
  289. transport_set_state(transport, TRANSPORT_STATE_IDLE);
  290. media_transport_remove_owner(transport);
  291. }
  292. static guint suspend_a2dp(struct media_transport *transport,
  293. struct media_owner *owner)
  294. {
  295. struct a2dp_transport *a2dp = transport->data;
  296. struct media_endpoint *endpoint = transport->endpoint;
  297. struct a2dp_sep *sep = media_endpoint_get_sep(endpoint);
  298. if (owner != NULL)
  299. return a2dp_suspend(a2dp->session, sep, a2dp_suspend_complete,
  300. owner);
  301. transport_set_state(transport, TRANSPORT_STATE_IDLE);
  302. a2dp_sep_unlock(sep, a2dp->session);
  303. return 0;
  304. }
  305. static void cancel_a2dp(struct media_transport *transport, guint id)
  306. {
  307. a2dp_cancel(id);
  308. }
  309. static void media_owner_exit(DBusConnection *connection, void *user_data)
  310. {
  311. struct media_owner *owner = user_data;
  312. owner->watch = 0;
  313. media_owner_remove(owner);
  314. media_transport_remove_owner(owner->transport);
  315. }
  316. static void media_transport_set_owner(struct media_transport *transport,
  317. struct media_owner *owner)
  318. {
  319. DBG("Transport %s Owner %s", transport->path, owner->name);
  320. transport->owner = owner;
  321. owner->transport = transport;
  322. owner->watch = g_dbus_add_disconnect_watch(btd_get_dbus_connection(),
  323. owner->name,
  324. media_owner_exit,
  325. owner, NULL);
  326. }
  327. static struct media_owner *media_owner_create(DBusMessage *msg)
  328. {
  329. struct media_owner *owner;
  330. owner = g_new0(struct media_owner, 1);
  331. owner->name = g_strdup(dbus_message_get_sender(msg));
  332. DBG("Owner created: sender=%s", owner->name);
  333. return owner;
  334. }
  335. static void media_owner_add(struct media_owner *owner,
  336. struct media_request *req)
  337. {
  338. DBG("Owner %s Request %s", owner->name,
  339. dbus_message_get_member(req->msg));
  340. owner->pending = req;
  341. }
  342. static DBusMessage *acquire(DBusConnection *conn, DBusMessage *msg,
  343. void *data)
  344. {
  345. struct media_transport *transport = data;
  346. struct media_owner *owner;
  347. struct media_request *req;
  348. guint id;
  349. if (transport->owner != NULL)
  350. return btd_error_not_authorized(msg);
  351. if (transport->state >= TRANSPORT_STATE_REQUESTING)
  352. return btd_error_not_authorized(msg);
  353. owner = media_owner_create(msg);
  354. id = transport->resume(transport, owner);
  355. if (id == 0) {
  356. media_owner_free(owner);
  357. return btd_error_not_authorized(msg);
  358. }
  359. req = media_request_create(msg, id);
  360. media_owner_add(owner, req);
  361. media_transport_set_owner(transport, owner);
  362. return NULL;
  363. }
  364. static DBusMessage *try_acquire(DBusConnection *conn, DBusMessage *msg,
  365. void *data)
  366. {
  367. struct media_transport *transport = data;
  368. struct media_owner *owner;
  369. struct media_request *req;
  370. guint id;
  371. if (transport->owner != NULL)
  372. return btd_error_not_authorized(msg);
  373. if (transport->state >= TRANSPORT_STATE_REQUESTING)
  374. return btd_error_not_authorized(msg);
  375. if (transport->state != TRANSPORT_STATE_PENDING)
  376. return btd_error_not_available(msg);
  377. owner = media_owner_create(msg);
  378. id = transport->resume(transport, owner);
  379. if (id == 0) {
  380. media_owner_free(owner);
  381. return btd_error_not_authorized(msg);
  382. }
  383. req = media_request_create(msg, id);
  384. media_owner_add(owner, req);
  385. media_transport_set_owner(transport, owner);
  386. return NULL;
  387. }
  388. static DBusMessage *release(DBusConnection *conn, DBusMessage *msg,
  389. void *data)
  390. {
  391. struct media_transport *transport = data;
  392. struct media_owner *owner = transport->owner;
  393. const char *sender;
  394. struct media_request *req;
  395. guint id;
  396. sender = dbus_message_get_sender(msg);
  397. if (owner == NULL || g_strcmp0(owner->name, sender) != 0)
  398. return btd_error_not_authorized(msg);
  399. if (owner->pending) {
  400. const char *member;
  401. member = dbus_message_get_member(owner->pending->msg);
  402. /* Cancel Acquire request if that exist */
  403. if (g_str_equal(member, "Acquire"))
  404. media_owner_remove(owner);
  405. else
  406. return btd_error_in_progress(msg);
  407. }
  408. transport_set_state(transport, TRANSPORT_STATE_SUSPENDING);
  409. id = transport->suspend(transport, owner);
  410. if (id == 0) {
  411. media_transport_remove_owner(transport);
  412. return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
  413. }
  414. req = media_request_create(msg, id);
  415. media_owner_add(owner, req);
  416. return NULL;
  417. }
  418. static gboolean get_device(const GDBusPropertyTable *property,
  419. DBusMessageIter *iter, void *data)
  420. {
  421. struct media_transport *transport = data;
  422. const char *path = device_get_path(transport->device);
  423. dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &path);
  424. return TRUE;
  425. }
  426. static gboolean get_uuid(const GDBusPropertyTable *property,
  427. DBusMessageIter *iter, void *data)
  428. {
  429. struct media_transport *transport = data;
  430. const char *uuid = media_endpoint_get_uuid(transport->endpoint);
  431. dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &uuid);
  432. return TRUE;
  433. }
  434. static gboolean get_codec(const GDBusPropertyTable *property,
  435. DBusMessageIter *iter, void *data)
  436. {
  437. struct media_transport *transport = data;
  438. uint8_t codec = media_endpoint_get_codec(transport->endpoint);
  439. dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE, &codec);
  440. return TRUE;
  441. }
  442. static gboolean get_configuration(const GDBusPropertyTable *property,
  443. DBusMessageIter *iter, void *data)
  444. {
  445. struct media_transport *transport = data;
  446. DBusMessageIter array;
  447. dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
  448. DBUS_TYPE_BYTE_AS_STRING, &array);
  449. dbus_message_iter_append_fixed_array(&array, DBUS_TYPE_BYTE,
  450. &transport->configuration,
  451. transport->size);
  452. dbus_message_iter_close_container(iter, &array);
  453. return TRUE;
  454. }
  455. static gboolean get_state(const GDBusPropertyTable *property,
  456. DBusMessageIter *iter, void *data)
  457. {
  458. struct media_transport *transport = data;
  459. const char *state = state2str(transport->state);
  460. dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &state);
  461. return TRUE;
  462. }
  463. static gboolean delay_exists(const GDBusPropertyTable *property, void *data)
  464. {
  465. struct media_transport *transport = data;
  466. struct a2dp_transport *a2dp = transport->data;
  467. return a2dp->delay != 0;
  468. }
  469. static gboolean get_delay(const GDBusPropertyTable *property,
  470. DBusMessageIter *iter, void *data)
  471. {
  472. struct media_transport *transport = data;
  473. struct a2dp_transport *a2dp = transport->data;
  474. dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16, &a2dp->delay);
  475. return TRUE;
  476. }
  477. static gboolean volume_exists(const GDBusPropertyTable *property, void *data)
  478. {
  479. struct media_transport *transport = data;
  480. struct a2dp_transport *a2dp = transport->data;
  481. return a2dp->volume >= 0;
  482. }
  483. static gboolean get_volume(const GDBusPropertyTable *property,
  484. DBusMessageIter *iter, void *data)
  485. {
  486. struct media_transport *transport = data;
  487. struct a2dp_transport *a2dp = transport->data;
  488. uint16_t volume = (uint16_t)a2dp->volume;
  489. dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16, &volume);
  490. return TRUE;
  491. }
  492. static void set_volume(const GDBusPropertyTable *property,
  493. DBusMessageIter *iter, GDBusPendingPropertySet id,
  494. void *data)
  495. {
  496. struct media_transport *transport = data;
  497. struct a2dp_transport *a2dp = transport->data;
  498. uint16_t arg;
  499. int8_t volume;
  500. bool notify;
  501. if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_UINT16)
  502. goto error;
  503. dbus_message_iter_get_basic(iter, &arg);
  504. if (arg > INT8_MAX)
  505. goto error;
  506. g_dbus_pending_property_success(id);
  507. volume = (int8_t)arg;
  508. if (a2dp->volume == volume)
  509. return;
  510. notify = transport->source_watch ? true : false;
  511. if (notify) {
  512. a2dp->volume = volume;
  513. g_dbus_emit_property_changed(btd_get_dbus_connection(),
  514. transport->path,
  515. MEDIA_TRANSPORT_INTERFACE,
  516. "Volume");
  517. }
  518. avrcp_set_volume(transport->device, volume, notify);
  519. return;
  520. error:
  521. g_dbus_pending_property_error(id, ERROR_INTERFACE ".InvalidArguments",
  522. "Invalid arguments in method call");
  523. }
  524. static gboolean endpoint_exists(const GDBusPropertyTable *property, void *data)
  525. {
  526. struct media_transport *transport = data;
  527. return transport->remote_endpoint != NULL;
  528. }
  529. static gboolean get_endpoint(const GDBusPropertyTable *property,
  530. DBusMessageIter *iter, void *data)
  531. {
  532. struct media_transport *transport = data;
  533. dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
  534. &transport->remote_endpoint);
  535. return TRUE;
  536. }
  537. static const GDBusMethodTable transport_methods[] = {
  538. { GDBUS_ASYNC_METHOD("Acquire",
  539. NULL,
  540. GDBUS_ARGS({ "fd", "h" }, { "mtu_r", "q" },
  541. { "mtu_w", "q" }),
  542. acquire) },
  543. { GDBUS_ASYNC_METHOD("TryAcquire",
  544. NULL,
  545. GDBUS_ARGS({ "fd", "h" }, { "mtu_r", "q" },
  546. { "mtu_w", "q" }),
  547. try_acquire) },
  548. { GDBUS_ASYNC_METHOD("Release", NULL, NULL, release) },
  549. { },
  550. };
  551. static const GDBusPropertyTable transport_properties[] = {
  552. { "Device", "o", get_device },
  553. { "UUID", "s", get_uuid },
  554. { "Codec", "y", get_codec },
  555. { "Configuration", "ay", get_configuration },
  556. { "State", "s", get_state },
  557. { "Delay", "q", get_delay, NULL, delay_exists },
  558. { "Volume", "q", get_volume, set_volume, volume_exists },
  559. { "Endpoint", "o", get_endpoint, NULL, endpoint_exists,
  560. G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
  561. { }
  562. };
  563. static void destroy_a2dp(void *data)
  564. {
  565. struct a2dp_transport *a2dp = data;
  566. if (a2dp->session)
  567. avdtp_unref(a2dp->session);
  568. g_free(a2dp);
  569. }
  570. static void media_transport_free(void *data)
  571. {
  572. struct media_transport *transport = data;
  573. transports = g_slist_remove(transports, transport);
  574. if (transport->owner)
  575. media_transport_remove_owner(transport);
  576. if (transport->destroy != NULL)
  577. transport->destroy(transport->data);
  578. g_free(transport->configuration);
  579. g_free(transport->path);
  580. g_free(transport);
  581. }
  582. static void transport_update_playing(struct media_transport *transport,
  583. gboolean playing)
  584. {
  585. DBG("%s State=%s Playing=%d", transport->path,
  586. str_state[transport->state], playing);
  587. if (playing == FALSE) {
  588. if (transport->state == TRANSPORT_STATE_PENDING)
  589. transport_set_state(transport, TRANSPORT_STATE_IDLE);
  590. else if (transport->state == TRANSPORT_STATE_ACTIVE) {
  591. /* Remove owner */
  592. if (transport->owner != NULL)
  593. media_transport_remove_owner(transport);
  594. }
  595. } else if (transport->state == TRANSPORT_STATE_IDLE)
  596. transport_set_state(transport, TRANSPORT_STATE_PENDING);
  597. }
  598. static void sink_state_changed(struct btd_service *service,
  599. sink_state_t old_state,
  600. sink_state_t new_state,
  601. void *user_data)
  602. {
  603. struct media_transport *transport = user_data;
  604. if (new_state == SINK_STATE_PLAYING)
  605. transport_update_playing(transport, TRUE);
  606. else
  607. transport_update_playing(transport, FALSE);
  608. }
  609. static void source_state_changed(struct btd_service *service,
  610. source_state_t old_state,
  611. source_state_t new_state,
  612. void *user_data)
  613. {
  614. struct media_transport *transport = user_data;
  615. if (new_state == SOURCE_STATE_PLAYING)
  616. transport_update_playing(transport, TRUE);
  617. else
  618. transport_update_playing(transport, FALSE);
  619. }
  620. static int media_transport_init_source(struct media_transport *transport)
  621. {
  622. struct btd_service *service;
  623. struct a2dp_transport *a2dp;
  624. service = btd_device_get_service(transport->device, A2DP_SINK_UUID);
  625. if (service == NULL)
  626. return -EINVAL;
  627. a2dp = g_new0(struct a2dp_transport, 1);
  628. transport->resume = resume_a2dp;
  629. transport->suspend = suspend_a2dp;
  630. transport->cancel = cancel_a2dp;
  631. transport->data = a2dp;
  632. transport->destroy = destroy_a2dp;
  633. a2dp->volume = -1;
  634. transport->sink_watch = sink_add_state_cb(service, sink_state_changed,
  635. transport);
  636. return 0;
  637. }
  638. static int media_transport_init_sink(struct media_transport *transport)
  639. {
  640. struct btd_service *service;
  641. struct a2dp_transport *a2dp;
  642. service = btd_device_get_service(transport->device, A2DP_SOURCE_UUID);
  643. if (service == NULL)
  644. return -EINVAL;
  645. a2dp = g_new0(struct a2dp_transport, 1);
  646. transport->resume = resume_a2dp;
  647. transport->suspend = suspend_a2dp;
  648. transport->cancel = cancel_a2dp;
  649. transport->data = a2dp;
  650. transport->destroy = destroy_a2dp;
  651. a2dp->volume = 127;
  652. transport->source_watch = source_add_state_cb(service,
  653. source_state_changed,
  654. transport);
  655. return 0;
  656. }
  657. struct media_transport *media_transport_create(struct btd_device *device,
  658. const char *remote_endpoint,
  659. uint8_t *configuration,
  660. size_t size, void *data)
  661. {
  662. struct media_endpoint *endpoint = data;
  663. struct media_transport *transport;
  664. const char *uuid;
  665. static int fd = 0;
  666. transport = g_new0(struct media_transport, 1);
  667. transport->device = device;
  668. transport->endpoint = endpoint;
  669. transport->configuration = g_new(uint8_t, size);
  670. memcpy(transport->configuration, configuration, size);
  671. transport->size = size;
  672. transport->remote_endpoint = remote_endpoint;
  673. transport->path = g_strdup_printf("%s/fd%d",
  674. remote_endpoint ? remote_endpoint :
  675. device_get_path(device), fd++);
  676. transport->fd = -1;
  677. uuid = media_endpoint_get_uuid(endpoint);
  678. if (strcasecmp(uuid, A2DP_SOURCE_UUID) == 0) {
  679. if (media_transport_init_source(transport) < 0)
  680. goto fail;
  681. } else if (strcasecmp(uuid, A2DP_SINK_UUID) == 0) {
  682. if (media_transport_init_sink(transport) < 0)
  683. goto fail;
  684. } else
  685. goto fail;
  686. if (g_dbus_register_interface(btd_get_dbus_connection(),
  687. transport->path, MEDIA_TRANSPORT_INTERFACE,
  688. transport_methods, NULL, transport_properties,
  689. transport, media_transport_free) == FALSE) {
  690. error("Could not register transport %s", transport->path);
  691. goto fail;
  692. }
  693. transports = g_slist_append(transports, transport);
  694. return transport;
  695. fail:
  696. media_transport_free(transport);
  697. return NULL;
  698. }
  699. const char *media_transport_get_path(struct media_transport *transport)
  700. {
  701. return transport->path;
  702. }
  703. void media_transport_update_delay(struct media_transport *transport,
  704. uint16_t delay)
  705. {
  706. struct a2dp_transport *a2dp = transport->data;
  707. /* Check if delay really changed */
  708. if (a2dp->delay == delay)
  709. return;
  710. a2dp->delay = delay;
  711. g_dbus_emit_property_changed(btd_get_dbus_connection(),
  712. transport->path,
  713. MEDIA_TRANSPORT_INTERFACE, "Delay");
  714. }
  715. struct btd_device *media_transport_get_dev(struct media_transport *transport)
  716. {
  717. return transport->device;
  718. }
  719. int8_t media_transport_get_volume(struct media_transport *transport)
  720. {
  721. struct a2dp_transport *a2dp = transport->data;
  722. return a2dp->volume;
  723. }
  724. void media_transport_update_volume(struct media_transport *transport,
  725. int8_t volume)
  726. {
  727. struct a2dp_transport *a2dp = transport->data;
  728. if (volume < 0)
  729. return;
  730. /* Check if volume really changed */
  731. if (a2dp->volume == volume)
  732. return;
  733. a2dp->volume = volume;
  734. g_dbus_emit_property_changed(btd_get_dbus_connection(),
  735. transport->path,
  736. MEDIA_TRANSPORT_INTERFACE, "Volume");
  737. }
  738. int8_t media_transport_get_device_volume(struct btd_device *dev)
  739. {
  740. GSList *l;
  741. if (dev == NULL)
  742. return -1;
  743. for (l = transports; l; l = l->next) {
  744. struct media_transport *transport = l->data;
  745. if (transport->device != dev)
  746. continue;
  747. /* Volume is A2DP only */
  748. if (media_endpoint_get_sep(transport->endpoint))
  749. return media_transport_get_volume(transport);
  750. }
  751. return 0;
  752. }
  753. void media_transport_update_device_volume(struct btd_device *dev,
  754. int8_t volume)
  755. {
  756. GSList *l;
  757. if (dev == NULL || volume < 0)
  758. return;
  759. for (l = transports; l; l = l->next) {
  760. struct media_transport *transport = l->data;
  761. if (transport->device != dev)
  762. continue;
  763. /* Volume is A2DP only */
  764. if (media_endpoint_get_sep(transport->endpoint))
  765. media_transport_update_volume(transport, volume);
  766. }
  767. }