1 /** @file
2 * @brief Advance Audio Distribution Profile.
3 */
4
5 /*
6 * Copyright (c) 2015-2016 Intel Corporation
7 *
8 * SPDX-License-Identifier: Apache-2.0
9 */
10
11 #include <ble_os.h>
12 #include <string.h>
13 #include <bt_errno.h>
14 #include <atomic.h>
15 #include <misc/byteorder.h>
16 #include <misc/util.h>
17 #include <misc/printk.h>
18 #include <assert.h>
19
20 #include <bluetooth/bluetooth.h>
21 #include <bluetooth/l2cap.h>
22 #include <bluetooth/avdtp.h>
23 #include <bluetooth/a2dp.h>
24
25 #define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_A2DP)
26 #define LOG_MODULE_NAME bt_a2dp
27 #include "common/log.h"
28
29 #include "hci_core.h"
30 #include "conn_internal.h"
31 #include "avdtp_internal.h"
32 #include "a2dp_internal.h"
33
34 #define A2DP_NO_SPACE (-1)
35
36 struct bt_a2dp {
37 struct bt_avdtp session;
38 };
39
40 /* Connections */
41 static struct bt_a2dp connection[CONFIG_BT_MAX_CONN];
42
a2d_reset(struct bt_a2dp * a2dp_conn)43 void a2d_reset(struct bt_a2dp *a2dp_conn)
44 {
45 (void)memset(a2dp_conn, 0, sizeof(struct bt_a2dp));
46 }
47
get_new_connection(struct bt_conn * conn)48 struct bt_a2dp *get_new_connection(struct bt_conn *conn)
49 {
50 s8_t i, free;
51
52 free = A2DP_NO_SPACE;
53
54 if (!conn) {
55 BT_ERR("Invalid Input (err: %d)", -EINVAL);
56 return NULL;
57 }
58
59 /* Find a space */
60 for (i = 0; i < CONFIG_BT_MAX_CONN; i++) {
61 if (connection[i].session.br_chan.chan.conn == conn) {
62 BT_DBG("Conn already exists");
63 return NULL;
64 }
65
66 if (!connection[i].session.br_chan.chan.conn &&
67 free == A2DP_NO_SPACE) {
68 free = i;
69 }
70 }
71
72 if (free == A2DP_NO_SPACE) {
73 BT_DBG("More connection cannot be supported");
74 return NULL;
75 }
76
77 /* Clean the memory area before returning */
78 a2d_reset(&connection[free]);
79
80 return &connection[free];
81 }
82
a2dp_accept(struct bt_conn * conn,struct bt_avdtp ** session)83 int a2dp_accept(struct bt_conn *conn, struct bt_avdtp **session)
84 {
85 struct bt_a2dp *a2dp_conn;
86
87 a2dp_conn = get_new_connection(conn);
88 if (!a2dp_conn) {
89 return -ENOMEM;
90 }
91
92 *session = &(a2dp_conn->session);
93 BT_DBG("session: %p", &(a2dp_conn->session));
94
95 return 0;
96 }
97
98 /* Callback for incoming requests */
99 static struct bt_avdtp_ind_cb cb_ind = {
100 /*TODO*/
101 };
102
103 /* The above callback structures need to be packed and passed to AVDTP */
104 static struct bt_avdtp_event_cb avdtp_cb = {
105 .ind = &cb_ind,
106 .accept = a2dp_accept
107 };
108
bt_a2dp_init(void)109 int bt_a2dp_init(void)
110 {
111 int err;
112
113 /* Register event handlers with AVDTP */
114 err = bt_avdtp_register(&avdtp_cb);
115 if (err < 0) {
116 BT_ERR("A2DP registration failed");
117 return err;
118 }
119
120 BT_DBG("A2DP Initialized successfully.");
121 return 0;
122 }
123
bt_a2dp_connect(struct bt_conn * conn)124 struct bt_a2dp *bt_a2dp_connect(struct bt_conn *conn)
125 {
126 struct bt_a2dp *a2dp_conn;
127 int err;
128
129 a2dp_conn = get_new_connection(conn);
130 if (!a2dp_conn) {
131 BT_ERR("Cannot allocate memory");
132 return NULL;
133 }
134
135 err = bt_avdtp_connect(conn, &(a2dp_conn->session));
136 if (err < 0) {
137 /* If error occurs, undo the saving and return the error */
138 a2d_reset(a2dp_conn);
139 BT_DBG("AVDTP Connect failed");
140 return NULL;
141 }
142
143 BT_DBG("Connect request sent");
144 return a2dp_conn;
145 }
146
bt_a2dp_register_endpoint(struct bt_a2dp_endpoint * endpoint,u8_t media_type,u8_t role)147 int bt_a2dp_register_endpoint(struct bt_a2dp_endpoint *endpoint,
148 u8_t media_type, u8_t role)
149 {
150 int err;
151
152 BT_ASSERT(endpoint);
153
154 err = bt_avdtp_register_sep(media_type, role, &(endpoint->info));
155 if (err < 0) {
156 return err;
157 }
158
159 /* TODO: Register SDP record */
160
161 return 0;
162 }
163