sink.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. *
  4. * BlueZ - Bluetooth protocol stack for Linux
  5. *
  6. * Copyright (C) 2006-2010 Nokia Corporation
  7. * Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
  8. *
  9. *
  10. */
  11. #ifdef HAVE_CONFIG_H
  12. #include <config.h>
  13. #endif
  14. #include <stdint.h>
  15. #include <stdbool.h>
  16. #include <errno.h>
  17. #include <glib.h>
  18. #include <dbus/dbus.h>
  19. #include "lib/bluetooth.h"
  20. #include "lib/sdp.h"
  21. #include "gdbus/gdbus.h"
  22. #include "src/log.h"
  23. #include "src/adapter.h"
  24. #include "src/device.h"
  25. #include "src/service.h"
  26. #include "src/error.h"
  27. #include "src/dbus-common.h"
  28. #include "src/shared/queue.h"
  29. #include "avdtp.h"
  30. #include "media.h"
  31. #include "a2dp.h"
  32. #include "sink.h"
  33. #define STREAM_SETUP_RETRY_TIMER 2
  34. struct sink {
  35. struct btd_service *service;
  36. struct avdtp *session;
  37. struct avdtp_stream *stream;
  38. unsigned int cb_id;
  39. avdtp_session_state_t session_state;
  40. avdtp_state_t stream_state;
  41. sink_state_t state;
  42. unsigned int connect_id;
  43. unsigned int disconnect_id;
  44. unsigned int avdtp_callback_id;
  45. };
  46. struct sink_state_callback {
  47. sink_state_cb cb;
  48. struct btd_service *service;
  49. void *user_data;
  50. unsigned int id;
  51. };
  52. static GSList *sink_callbacks = NULL;
  53. static char *str_state[] = {
  54. "SINK_STATE_DISCONNECTED",
  55. "SINK_STATE_CONNECTING",
  56. "SINK_STATE_CONNECTED",
  57. "SINK_STATE_PLAYING",
  58. };
  59. static void sink_set_state(struct sink *sink, sink_state_t new_state)
  60. {
  61. struct btd_service *service = sink->service;
  62. struct btd_device *dev = btd_service_get_device(service);
  63. sink_state_t old_state = sink->state;
  64. GSList *l;
  65. sink->state = new_state;
  66. DBG("State changed %s: %s -> %s", device_get_path(dev),
  67. str_state[old_state], str_state[new_state]);
  68. for (l = sink_callbacks; l != NULL; l = l->next) {
  69. struct sink_state_callback *cb = l->data;
  70. if (cb->service != service)
  71. continue;
  72. cb->cb(service, old_state, new_state, cb->user_data);
  73. }
  74. if (new_state != SINK_STATE_DISCONNECTED)
  75. return;
  76. if (sink->session) {
  77. avdtp_unref(sink->session);
  78. sink->session = NULL;
  79. }
  80. }
  81. static void avdtp_state_callback(struct btd_device *dev,
  82. struct avdtp *session,
  83. avdtp_session_state_t old_state,
  84. avdtp_session_state_t new_state,
  85. void *user_data)
  86. {
  87. struct sink *sink = user_data;
  88. switch (new_state) {
  89. case AVDTP_SESSION_STATE_DISCONNECTED:
  90. sink_set_state(sink, SINK_STATE_DISCONNECTED);
  91. break;
  92. case AVDTP_SESSION_STATE_CONNECTING:
  93. sink_set_state(sink, SINK_STATE_CONNECTING);
  94. break;
  95. case AVDTP_SESSION_STATE_CONNECTED:
  96. break;
  97. }
  98. sink->session_state = new_state;
  99. }
  100. static void stream_state_changed(struct avdtp_stream *stream,
  101. avdtp_state_t old_state,
  102. avdtp_state_t new_state,
  103. struct avdtp_error *err,
  104. void *user_data)
  105. {
  106. struct btd_service *service = user_data;
  107. struct sink *sink = btd_service_get_user_data(service);
  108. if (err)
  109. return;
  110. switch (new_state) {
  111. case AVDTP_STATE_IDLE:
  112. btd_service_disconnecting_complete(sink->service, 0);
  113. if (sink->disconnect_id > 0) {
  114. a2dp_cancel(sink->disconnect_id);
  115. sink->disconnect_id = 0;
  116. }
  117. if (sink->session) {
  118. avdtp_unref(sink->session);
  119. sink->session = NULL;
  120. }
  121. sink->stream = NULL;
  122. sink->cb_id = 0;
  123. break;
  124. case AVDTP_STATE_OPEN:
  125. btd_service_connecting_complete(sink->service, 0);
  126. sink_set_state(sink, SINK_STATE_CONNECTED);
  127. break;
  128. case AVDTP_STATE_STREAMING:
  129. sink_set_state(sink, SINK_STATE_PLAYING);
  130. break;
  131. case AVDTP_STATE_CONFIGURED:
  132. case AVDTP_STATE_CLOSING:
  133. case AVDTP_STATE_ABORTING:
  134. default:
  135. break;
  136. }
  137. sink->stream_state = new_state;
  138. }
  139. static void stream_setup_complete(struct avdtp *session, struct a2dp_sep *sep,
  140. struct avdtp_stream *stream, int err,
  141. void *user_data)
  142. {
  143. struct sink *sink = user_data;
  144. sink->connect_id = 0;
  145. if (stream)
  146. return;
  147. avdtp_unref(sink->session);
  148. sink->session = NULL;
  149. btd_service_connecting_complete(sink->service, err);
  150. }
  151. static void select_complete(struct avdtp *session, struct a2dp_sep *sep,
  152. GSList *caps, int err, void *user_data)
  153. {
  154. struct sink *sink = user_data;
  155. int id;
  156. sink->connect_id = 0;
  157. if (err)
  158. goto failed;
  159. id = a2dp_config(session, sep, stream_setup_complete, caps, sink);
  160. if (id == 0)
  161. goto failed;
  162. sink->connect_id = id;
  163. return;
  164. failed:
  165. btd_service_connecting_complete(sink->service, -EIO);
  166. avdtp_unref(sink->session);
  167. sink->session = NULL;
  168. }
  169. static void discovery_complete(struct avdtp *session, GSList *seps, int err,
  170. void *user_data)
  171. {
  172. struct sink *sink = user_data;
  173. int id;
  174. sink->connect_id = 0;
  175. if (err) {
  176. avdtp_unref(sink->session);
  177. sink->session = NULL;
  178. goto failed;
  179. }
  180. DBG("Discovery complete");
  181. id = a2dp_select_capabilities(sink->session, AVDTP_SEP_TYPE_SINK, NULL,
  182. select_complete, sink);
  183. if (id == 0) {
  184. err = -EIO;
  185. goto failed;
  186. }
  187. sink->connect_id = id;
  188. return;
  189. failed:
  190. btd_service_connecting_complete(sink->service, err);
  191. avdtp_unref(sink->session);
  192. sink->session = NULL;
  193. }
  194. gboolean sink_setup_stream(struct btd_service *service, struct avdtp *session)
  195. {
  196. struct sink *sink = btd_service_get_user_data(service);
  197. if (sink->connect_id > 0 || sink->disconnect_id > 0)
  198. return FALSE;
  199. if (!sink->session) {
  200. if (session)
  201. sink->session = avdtp_ref(session);
  202. else
  203. sink->session = a2dp_avdtp_get(
  204. btd_service_get_device(service));
  205. if (!sink->session) {
  206. DBG("Unable to get a session");
  207. return FALSE;
  208. }
  209. }
  210. sink->connect_id = a2dp_discover(sink->session, discovery_complete,
  211. sink);
  212. if (sink->connect_id == 0) {
  213. avdtp_unref(sink->session);
  214. sink->session = NULL;
  215. return FALSE;
  216. }
  217. return TRUE;
  218. }
  219. int sink_connect(struct btd_service *service)
  220. {
  221. struct sink *sink = btd_service_get_user_data(service);
  222. if (sink->connect_id > 0 || sink->disconnect_id > 0)
  223. return -EBUSY;
  224. if (sink->state == SINK_STATE_CONNECTING)
  225. return -EBUSY;
  226. if (sink->stream_state >= AVDTP_STATE_OPEN)
  227. return -EALREADY;
  228. if (!sink_setup_stream(service, NULL)) {
  229. DBG("Failed to create a stream");
  230. return -EIO;
  231. }
  232. DBG("stream creation in progress");
  233. return 0;
  234. }
  235. static void sink_free(struct btd_service *service)
  236. {
  237. struct sink *sink = btd_service_get_user_data(service);
  238. if (sink->cb_id)
  239. avdtp_stream_remove_cb(sink->session, sink->stream,
  240. sink->cb_id);
  241. if (sink->session) {
  242. avdtp_unref(sink->session);
  243. sink->session = NULL;
  244. }
  245. if (sink->connect_id > 0) {
  246. btd_service_connecting_complete(sink->service, -ECANCELED);
  247. a2dp_cancel(sink->connect_id);
  248. sink->connect_id = 0;
  249. }
  250. if (sink->disconnect_id > 0) {
  251. btd_service_disconnecting_complete(sink->service, -ECANCELED);
  252. a2dp_cancel(sink->disconnect_id);
  253. sink->disconnect_id = 0;
  254. }
  255. avdtp_remove_state_cb(sink->avdtp_callback_id);
  256. btd_service_unref(sink->service);
  257. g_free(sink);
  258. }
  259. void sink_unregister(struct btd_service *service)
  260. {
  261. struct btd_device *dev = btd_service_get_device(service);
  262. DBG("%s", device_get_path(dev));
  263. sink_free(service);
  264. }
  265. int sink_init(struct btd_service *service)
  266. {
  267. struct btd_device *dev = btd_service_get_device(service);
  268. struct sink *sink;
  269. DBG("%s", device_get_path(dev));
  270. sink = g_new0(struct sink, 1);
  271. sink->service = btd_service_ref(service);
  272. sink->avdtp_callback_id = avdtp_add_state_cb(dev, avdtp_state_callback,
  273. sink);
  274. btd_service_set_user_data(service, sink);
  275. return 0;
  276. }
  277. gboolean sink_is_active(struct btd_service *service)
  278. {
  279. struct sink *sink = btd_service_get_user_data(service);
  280. if (sink->session)
  281. return TRUE;
  282. return FALSE;
  283. }
  284. gboolean sink_new_stream(struct btd_service *service, struct avdtp *session,
  285. struct avdtp_stream *stream)
  286. {
  287. struct sink *sink = btd_service_get_user_data(service);
  288. if (sink->stream)
  289. return FALSE;
  290. if (!sink->session)
  291. sink->session = avdtp_ref(session);
  292. sink->stream = stream;
  293. sink->cb_id = avdtp_stream_add_cb(session, stream,
  294. stream_state_changed, service);
  295. return TRUE;
  296. }
  297. int sink_disconnect(struct btd_service *service)
  298. {
  299. struct sink *sink = btd_service_get_user_data(service);
  300. if (!sink->session)
  301. return -ENOTCONN;
  302. /* cancel pending connect */
  303. if (sink->connect_id > 0) {
  304. avdtp_unref(sink->session);
  305. sink->session = NULL;
  306. a2dp_cancel(sink->connect_id);
  307. sink->connect_id = 0;
  308. btd_service_disconnecting_complete(sink->service, 0);
  309. return 0;
  310. }
  311. /* disconnect already ongoing */
  312. if (sink->disconnect_id > 0)
  313. return -EBUSY;
  314. if (!sink->stream)
  315. return -ENOTCONN;
  316. return avdtp_close(sink->session, sink->stream, FALSE);
  317. }
  318. unsigned int sink_add_state_cb(struct btd_service *service, sink_state_cb cb,
  319. void *user_data)
  320. {
  321. struct sink_state_callback *state_cb;
  322. static unsigned int id = 0;
  323. state_cb = g_new(struct sink_state_callback, 1);
  324. state_cb->cb = cb;
  325. state_cb->service = service;
  326. state_cb->user_data = user_data;
  327. state_cb->id = ++id;
  328. sink_callbacks = g_slist_append(sink_callbacks, state_cb);
  329. return state_cb->id;
  330. }
  331. gboolean sink_remove_state_cb(unsigned int id)
  332. {
  333. GSList *l;
  334. for (l = sink_callbacks; l != NULL; l = l->next) {
  335. struct sink_state_callback *cb = l->data;
  336. if (cb && cb->id == id) {
  337. sink_callbacks = g_slist_remove(sink_callbacks, cb);
  338. g_free(cb);
  339. return TRUE;
  340. }
  341. }
  342. return FALSE;
  343. }