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