1ccf74f23SLuiz Augusto von Dentz // SPDX-License-Identifier: GPL-2.0
2ccf74f23SLuiz Augusto von Dentz /*
3ccf74f23SLuiz Augusto von Dentz * BlueZ - Bluetooth protocol stack for Linux
4ccf74f23SLuiz Augusto von Dentz *
5ccf74f23SLuiz Augusto von Dentz * Copyright (C) 2022 Intel Corporation
60fe8c8d0SIulia Tanasescu * Copyright 2023 NXP
7ccf74f23SLuiz Augusto von Dentz */
8ccf74f23SLuiz Augusto von Dentz
9ccf74f23SLuiz Augusto von Dentz #include <linux/module.h>
10ccf74f23SLuiz Augusto von Dentz #include <linux/debugfs.h>
11ccf74f23SLuiz Augusto von Dentz #include <linux/seq_file.h>
12ccf74f23SLuiz Augusto von Dentz #include <linux/sched/signal.h>
13ccf74f23SLuiz Augusto von Dentz
14ccf74f23SLuiz Augusto von Dentz #include <net/bluetooth/bluetooth.h>
15ccf74f23SLuiz Augusto von Dentz #include <net/bluetooth/hci_core.h>
16ccf74f23SLuiz Augusto von Dentz #include <net/bluetooth/iso.h>
17ccf74f23SLuiz Augusto von Dentz
18ccf74f23SLuiz Augusto von Dentz static const struct proto_ops iso_sock_ops;
19ccf74f23SLuiz Augusto von Dentz
20ccf74f23SLuiz Augusto von Dentz static struct bt_sock_list iso_sk_list = {
21ccf74f23SLuiz Augusto von Dentz .lock = __RW_LOCK_UNLOCKED(iso_sk_list.lock)
22ccf74f23SLuiz Augusto von Dentz };
23ccf74f23SLuiz Augusto von Dentz
24ccf74f23SLuiz Augusto von Dentz /* ---- ISO connections ---- */
25ccf74f23SLuiz Augusto von Dentz struct iso_conn {
26ccf74f23SLuiz Augusto von Dentz struct hci_conn *hcon;
27ccf74f23SLuiz Augusto von Dentz
28ccf74f23SLuiz Augusto von Dentz /* @lock: spinlock protecting changes to iso_conn fields */
29ccf74f23SLuiz Augusto von Dentz spinlock_t lock;
30ccf74f23SLuiz Augusto von Dentz struct sock *sk;
31ccf74f23SLuiz Augusto von Dentz
32ccf74f23SLuiz Augusto von Dentz struct delayed_work timeout_work;
33ccf74f23SLuiz Augusto von Dentz
34ccf74f23SLuiz Augusto von Dentz struct sk_buff *rx_skb;
35ccf74f23SLuiz Augusto von Dentz __u32 rx_len;
36ccf74f23SLuiz Augusto von Dentz __u16 tx_sn;
37ccf74f23SLuiz Augusto von Dentz };
38ccf74f23SLuiz Augusto von Dentz
39ccf74f23SLuiz Augusto von Dentz #define iso_conn_lock(c) spin_lock(&(c)->lock)
40ccf74f23SLuiz Augusto von Dentz #define iso_conn_unlock(c) spin_unlock(&(c)->lock)
41ccf74f23SLuiz Augusto von Dentz
42ccf74f23SLuiz Augusto von Dentz static void iso_sock_close(struct sock *sk);
43ccf74f23SLuiz Augusto von Dentz static void iso_sock_kill(struct sock *sk);
44ccf74f23SLuiz Augusto von Dentz
45ccf74f23SLuiz Augusto von Dentz /* ----- ISO socket info ----- */
46ccf74f23SLuiz Augusto von Dentz #define iso_pi(sk) ((struct iso_pinfo *)sk)
47ccf74f23SLuiz Augusto von Dentz
48b4443423SLuiz Augusto von Dentz #define EIR_SERVICE_DATA_LENGTH 4
49b4443423SLuiz Augusto von Dentz #define BASE_MAX_LENGTH (HCI_MAX_PER_AD_LENGTH - EIR_SERVICE_DATA_LENGTH)
50b4443423SLuiz Augusto von Dentz
51f777d882SIulia Tanasescu /* iso_pinfo flags values */
52f777d882SIulia Tanasescu enum {
53f777d882SIulia Tanasescu BT_SK_BIG_SYNC,
54fbdc4bc4SIulia Tanasescu BT_SK_PA_SYNC,
5514410544SIulia Tanasescu BT_SK_PA_SYNC_TERM,
56f777d882SIulia Tanasescu };
57f777d882SIulia Tanasescu
58ccf74f23SLuiz Augusto von Dentz struct iso_pinfo {
59ccf74f23SLuiz Augusto von Dentz struct bt_sock bt;
60ccf74f23SLuiz Augusto von Dentz bdaddr_t src;
61ccf74f23SLuiz Augusto von Dentz __u8 src_type;
62ccf74f23SLuiz Augusto von Dentz bdaddr_t dst;
63ccf74f23SLuiz Augusto von Dentz __u8 dst_type;
64f764a6c2SLuiz Augusto von Dentz __u8 bc_sid;
65f764a6c2SLuiz Augusto von Dentz __u8 bc_num_bis;
66f764a6c2SLuiz Augusto von Dentz __u8 bc_bis[ISO_MAX_NUM_BIS];
67f764a6c2SLuiz Augusto von Dentz __u16 sync_handle;
68f777d882SIulia Tanasescu unsigned long flags;
69ccf74f23SLuiz Augusto von Dentz struct bt_iso_qos qos;
700fe8c8d0SIulia Tanasescu bool qos_user_set;
71f764a6c2SLuiz Augusto von Dentz __u8 base_len;
72b4443423SLuiz Augusto von Dentz __u8 base[BASE_MAX_LENGTH];
73ccf74f23SLuiz Augusto von Dentz struct iso_conn *conn;
74ccf74f23SLuiz Augusto von Dentz };
75ccf74f23SLuiz Augusto von Dentz
760fe8c8d0SIulia Tanasescu static struct bt_iso_qos default_qos;
770fe8c8d0SIulia Tanasescu
780fe8c8d0SIulia Tanasescu static bool check_ucast_qos(struct bt_iso_qos *qos);
790fe8c8d0SIulia Tanasescu static bool check_bcast_qos(struct bt_iso_qos *qos);
80fbdc4bc4SIulia Tanasescu static bool iso_match_sid(struct sock *sk, void *data);
8123417475SIulia Tanasescu static bool iso_match_sync_handle(struct sock *sk, void *data);
82fbdc4bc4SIulia Tanasescu static void iso_sock_disconn(struct sock *sk);
830fe8c8d0SIulia Tanasescu
8414410544SIulia Tanasescu typedef bool (*iso_sock_match_t)(struct sock *sk, void *data);
8514410544SIulia Tanasescu
8614410544SIulia Tanasescu static struct sock *iso_get_sock_listen(bdaddr_t *src, bdaddr_t *dst,
8714410544SIulia Tanasescu iso_sock_match_t match, void *data);
8814410544SIulia Tanasescu
89ccf74f23SLuiz Augusto von Dentz /* ---- ISO timers ---- */
90ccf74f23SLuiz Augusto von Dentz #define ISO_CONN_TIMEOUT (HZ * 40)
91ccf74f23SLuiz Augusto von Dentz #define ISO_DISCONN_TIMEOUT (HZ * 2)
92ccf74f23SLuiz Augusto von Dentz
iso_sock_timeout(struct work_struct * work)93ccf74f23SLuiz Augusto von Dentz static void iso_sock_timeout(struct work_struct *work)
94ccf74f23SLuiz Augusto von Dentz {
95ccf74f23SLuiz Augusto von Dentz struct iso_conn *conn = container_of(work, struct iso_conn,
96ccf74f23SLuiz Augusto von Dentz timeout_work.work);
97ccf74f23SLuiz Augusto von Dentz struct sock *sk;
98ccf74f23SLuiz Augusto von Dentz
99ccf74f23SLuiz Augusto von Dentz iso_conn_lock(conn);
100ccf74f23SLuiz Augusto von Dentz sk = conn->sk;
101ccf74f23SLuiz Augusto von Dentz if (sk)
102ccf74f23SLuiz Augusto von Dentz sock_hold(sk);
103ccf74f23SLuiz Augusto von Dentz iso_conn_unlock(conn);
104ccf74f23SLuiz Augusto von Dentz
105ccf74f23SLuiz Augusto von Dentz if (!sk)
106ccf74f23SLuiz Augusto von Dentz return;
107ccf74f23SLuiz Augusto von Dentz
108ccf74f23SLuiz Augusto von Dentz BT_DBG("sock %p state %d", sk, sk->sk_state);
109ccf74f23SLuiz Augusto von Dentz
110ccf74f23SLuiz Augusto von Dentz lock_sock(sk);
111ccf74f23SLuiz Augusto von Dentz sk->sk_err = ETIMEDOUT;
112ccf74f23SLuiz Augusto von Dentz sk->sk_state_change(sk);
113ccf74f23SLuiz Augusto von Dentz release_sock(sk);
114ccf74f23SLuiz Augusto von Dentz sock_put(sk);
115ccf74f23SLuiz Augusto von Dentz }
116ccf74f23SLuiz Augusto von Dentz
iso_sock_set_timer(struct sock * sk,long timeout)117ccf74f23SLuiz Augusto von Dentz static void iso_sock_set_timer(struct sock *sk, long timeout)
118ccf74f23SLuiz Augusto von Dentz {
119ccf74f23SLuiz Augusto von Dentz if (!iso_pi(sk)->conn)
120ccf74f23SLuiz Augusto von Dentz return;
121ccf74f23SLuiz Augusto von Dentz
122ccf74f23SLuiz Augusto von Dentz BT_DBG("sock %p state %d timeout %ld", sk, sk->sk_state, timeout);
123ccf74f23SLuiz Augusto von Dentz cancel_delayed_work(&iso_pi(sk)->conn->timeout_work);
124ccf74f23SLuiz Augusto von Dentz schedule_delayed_work(&iso_pi(sk)->conn->timeout_work, timeout);
125ccf74f23SLuiz Augusto von Dentz }
126ccf74f23SLuiz Augusto von Dentz
iso_sock_clear_timer(struct sock * sk)127ccf74f23SLuiz Augusto von Dentz static void iso_sock_clear_timer(struct sock *sk)
128ccf74f23SLuiz Augusto von Dentz {
129ccf74f23SLuiz Augusto von Dentz if (!iso_pi(sk)->conn)
130ccf74f23SLuiz Augusto von Dentz return;
131ccf74f23SLuiz Augusto von Dentz
132ccf74f23SLuiz Augusto von Dentz BT_DBG("sock %p state %d", sk, sk->sk_state);
133ccf74f23SLuiz Augusto von Dentz cancel_delayed_work(&iso_pi(sk)->conn->timeout_work);
134ccf74f23SLuiz Augusto von Dentz }
135ccf74f23SLuiz Augusto von Dentz
136ccf74f23SLuiz Augusto von Dentz /* ---- ISO connections ---- */
iso_conn_add(struct hci_conn * hcon)137ccf74f23SLuiz Augusto von Dentz static struct iso_conn *iso_conn_add(struct hci_conn *hcon)
138ccf74f23SLuiz Augusto von Dentz {
139ccf74f23SLuiz Augusto von Dentz struct iso_conn *conn = hcon->iso_data;
140ccf74f23SLuiz Augusto von Dentz
141d40ae85eSPauli Virtanen if (conn) {
142d40ae85eSPauli Virtanen if (!conn->hcon)
143d40ae85eSPauli Virtanen conn->hcon = hcon;
144ccf74f23SLuiz Augusto von Dentz return conn;
145d40ae85eSPauli Virtanen }
146ccf74f23SLuiz Augusto von Dentz
147ccf74f23SLuiz Augusto von Dentz conn = kzalloc(sizeof(*conn), GFP_KERNEL);
148ccf74f23SLuiz Augusto von Dentz if (!conn)
149ccf74f23SLuiz Augusto von Dentz return NULL;
150ccf74f23SLuiz Augusto von Dentz
151ccf74f23SLuiz Augusto von Dentz spin_lock_init(&conn->lock);
152ccf74f23SLuiz Augusto von Dentz INIT_DELAYED_WORK(&conn->timeout_work, iso_sock_timeout);
153ccf74f23SLuiz Augusto von Dentz
154ccf74f23SLuiz Augusto von Dentz hcon->iso_data = conn;
155ccf74f23SLuiz Augusto von Dentz conn->hcon = hcon;
156ccf74f23SLuiz Augusto von Dentz conn->tx_sn = 0;
157ccf74f23SLuiz Augusto von Dentz
158ccf74f23SLuiz Augusto von Dentz BT_DBG("hcon %p conn %p", hcon, conn);
159ccf74f23SLuiz Augusto von Dentz
160ccf74f23SLuiz Augusto von Dentz return conn;
161ccf74f23SLuiz Augusto von Dentz }
162ccf74f23SLuiz Augusto von Dentz
163ccf74f23SLuiz Augusto von Dentz /* Delete channel. Must be called on the locked socket. */
iso_chan_del(struct sock * sk,int err)164ccf74f23SLuiz Augusto von Dentz static void iso_chan_del(struct sock *sk, int err)
165ccf74f23SLuiz Augusto von Dentz {
166ccf74f23SLuiz Augusto von Dentz struct iso_conn *conn;
167f764a6c2SLuiz Augusto von Dentz struct sock *parent;
168ccf74f23SLuiz Augusto von Dentz
169ccf74f23SLuiz Augusto von Dentz conn = iso_pi(sk)->conn;
170ccf74f23SLuiz Augusto von Dentz
171ccf74f23SLuiz Augusto von Dentz BT_DBG("sk %p, conn %p, err %d", sk, conn, err);
172ccf74f23SLuiz Augusto von Dentz
173ccf74f23SLuiz Augusto von Dentz if (conn) {
174ccf74f23SLuiz Augusto von Dentz iso_conn_lock(conn);
175ccf74f23SLuiz Augusto von Dentz conn->sk = NULL;
176ccf74f23SLuiz Augusto von Dentz iso_pi(sk)->conn = NULL;
177ccf74f23SLuiz Augusto von Dentz iso_conn_unlock(conn);
178ccf74f23SLuiz Augusto von Dentz
179ccf74f23SLuiz Augusto von Dentz if (conn->hcon)
180ccf74f23SLuiz Augusto von Dentz hci_conn_drop(conn->hcon);
181ccf74f23SLuiz Augusto von Dentz }
182ccf74f23SLuiz Augusto von Dentz
183ccf74f23SLuiz Augusto von Dentz sk->sk_state = BT_CLOSED;
184ccf74f23SLuiz Augusto von Dentz sk->sk_err = err;
185f764a6c2SLuiz Augusto von Dentz
186f764a6c2SLuiz Augusto von Dentz parent = bt_sk(sk)->parent;
187f764a6c2SLuiz Augusto von Dentz if (parent) {
188f764a6c2SLuiz Augusto von Dentz bt_accept_unlink(sk);
189f764a6c2SLuiz Augusto von Dentz parent->sk_data_ready(parent);
190f764a6c2SLuiz Augusto von Dentz } else {
191ccf74f23SLuiz Augusto von Dentz sk->sk_state_change(sk);
192f764a6c2SLuiz Augusto von Dentz }
193ccf74f23SLuiz Augusto von Dentz
194ccf74f23SLuiz Augusto von Dentz sock_set_flag(sk, SOCK_ZAPPED);
195ccf74f23SLuiz Augusto von Dentz }
196ccf74f23SLuiz Augusto von Dentz
iso_match_conn_sync_handle(struct sock * sk,void * data)19714410544SIulia Tanasescu static bool iso_match_conn_sync_handle(struct sock *sk, void *data)
19814410544SIulia Tanasescu {
19914410544SIulia Tanasescu struct hci_conn *hcon = data;
20014410544SIulia Tanasescu
20114410544SIulia Tanasescu if (test_bit(BT_SK_PA_SYNC, &iso_pi(sk)->flags))
20214410544SIulia Tanasescu return false;
20314410544SIulia Tanasescu
20414410544SIulia Tanasescu return hcon->sync_handle == iso_pi(sk)->sync_handle;
20514410544SIulia Tanasescu }
20614410544SIulia Tanasescu
iso_conn_del(struct hci_conn * hcon,int err)207ccf74f23SLuiz Augusto von Dentz static void iso_conn_del(struct hci_conn *hcon, int err)
208ccf74f23SLuiz Augusto von Dentz {
209ccf74f23SLuiz Augusto von Dentz struct iso_conn *conn = hcon->iso_data;
210ccf74f23SLuiz Augusto von Dentz struct sock *sk;
21114410544SIulia Tanasescu struct sock *parent;
212ccf74f23SLuiz Augusto von Dentz
213ccf74f23SLuiz Augusto von Dentz if (!conn)
214ccf74f23SLuiz Augusto von Dentz return;
215ccf74f23SLuiz Augusto von Dentz
216ccf74f23SLuiz Augusto von Dentz BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
217ccf74f23SLuiz Augusto von Dentz
218ccf74f23SLuiz Augusto von Dentz /* Kill socket */
219ccf74f23SLuiz Augusto von Dentz iso_conn_lock(conn);
220ccf74f23SLuiz Augusto von Dentz sk = conn->sk;
221ccf74f23SLuiz Augusto von Dentz if (sk)
222ccf74f23SLuiz Augusto von Dentz sock_hold(sk);
223ccf74f23SLuiz Augusto von Dentz iso_conn_unlock(conn);
224ccf74f23SLuiz Augusto von Dentz
225ccf74f23SLuiz Augusto von Dentz if (sk) {
226ccf74f23SLuiz Augusto von Dentz lock_sock(sk);
22714410544SIulia Tanasescu
22814410544SIulia Tanasescu /* While a PA sync hcon is in the process of closing,
22914410544SIulia Tanasescu * mark parent socket with a flag, so that any residual
23014410544SIulia Tanasescu * BIGInfo adv reports that arrive before PA sync is
23114410544SIulia Tanasescu * terminated are not processed anymore.
23214410544SIulia Tanasescu */
23314410544SIulia Tanasescu if (test_bit(BT_SK_PA_SYNC, &iso_pi(sk)->flags)) {
23414410544SIulia Tanasescu parent = iso_get_sock_listen(&hcon->src,
23514410544SIulia Tanasescu &hcon->dst,
23614410544SIulia Tanasescu iso_match_conn_sync_handle,
23714410544SIulia Tanasescu hcon);
23814410544SIulia Tanasescu
23914410544SIulia Tanasescu if (parent) {
24014410544SIulia Tanasescu set_bit(BT_SK_PA_SYNC_TERM,
24114410544SIulia Tanasescu &iso_pi(parent)->flags);
24214410544SIulia Tanasescu sock_put(parent);
24314410544SIulia Tanasescu }
24414410544SIulia Tanasescu }
24514410544SIulia Tanasescu
246ccf74f23SLuiz Augusto von Dentz iso_sock_clear_timer(sk);
247ccf74f23SLuiz Augusto von Dentz iso_chan_del(sk, err);
248ccf74f23SLuiz Augusto von Dentz release_sock(sk);
249ccf74f23SLuiz Augusto von Dentz sock_put(sk);
250ccf74f23SLuiz Augusto von Dentz }
251ccf74f23SLuiz Augusto von Dentz
252ccf74f23SLuiz Augusto von Dentz /* Ensure no more work items will run before freeing conn. */
253ccf74f23SLuiz Augusto von Dentz cancel_delayed_work_sync(&conn->timeout_work);
254ccf74f23SLuiz Augusto von Dentz
255ccf74f23SLuiz Augusto von Dentz hcon->iso_data = NULL;
256ccf74f23SLuiz Augusto von Dentz kfree(conn);
257ccf74f23SLuiz Augusto von Dentz }
258ccf74f23SLuiz Augusto von Dentz
__iso_chan_add(struct iso_conn * conn,struct sock * sk,struct sock * parent)259ccf74f23SLuiz Augusto von Dentz static int __iso_chan_add(struct iso_conn *conn, struct sock *sk,
260ccf74f23SLuiz Augusto von Dentz struct sock *parent)
261ccf74f23SLuiz Augusto von Dentz {
262ccf74f23SLuiz Augusto von Dentz BT_DBG("conn %p", conn);
263ccf74f23SLuiz Augusto von Dentz
264ccf74f23SLuiz Augusto von Dentz if (iso_pi(sk)->conn == conn && conn->sk == sk)
265ccf74f23SLuiz Augusto von Dentz return 0;
266ccf74f23SLuiz Augusto von Dentz
267ccf74f23SLuiz Augusto von Dentz if (conn->sk) {
268ccf74f23SLuiz Augusto von Dentz BT_ERR("conn->sk already set");
269ccf74f23SLuiz Augusto von Dentz return -EBUSY;
270ccf74f23SLuiz Augusto von Dentz }
271ccf74f23SLuiz Augusto von Dentz
272ccf74f23SLuiz Augusto von Dentz iso_pi(sk)->conn = conn;
273ccf74f23SLuiz Augusto von Dentz conn->sk = sk;
274ccf74f23SLuiz Augusto von Dentz
275ccf74f23SLuiz Augusto von Dentz if (parent)
276ccf74f23SLuiz Augusto von Dentz bt_accept_enqueue(parent, sk, true);
277ccf74f23SLuiz Augusto von Dentz
278ccf74f23SLuiz Augusto von Dentz return 0;
279ccf74f23SLuiz Augusto von Dentz }
280ccf74f23SLuiz Augusto von Dentz
iso_chan_add(struct iso_conn * conn,struct sock * sk,struct sock * parent)281ccf74f23SLuiz Augusto von Dentz static int iso_chan_add(struct iso_conn *conn, struct sock *sk,
282ccf74f23SLuiz Augusto von Dentz struct sock *parent)
283ccf74f23SLuiz Augusto von Dentz {
284ccf74f23SLuiz Augusto von Dentz int err;
285ccf74f23SLuiz Augusto von Dentz
286ccf74f23SLuiz Augusto von Dentz iso_conn_lock(conn);
287ccf74f23SLuiz Augusto von Dentz err = __iso_chan_add(conn, sk, parent);
288ccf74f23SLuiz Augusto von Dentz iso_conn_unlock(conn);
289ccf74f23SLuiz Augusto von Dentz
290ccf74f23SLuiz Augusto von Dentz return err;
291ccf74f23SLuiz Augusto von Dentz }
292ccf74f23SLuiz Augusto von Dentz
le_addr_type(u8 bdaddr_type)293b36a234dSPauli Virtanen static inline u8 le_addr_type(u8 bdaddr_type)
294b36a234dSPauli Virtanen {
295b36a234dSPauli Virtanen if (bdaddr_type == BDADDR_LE_PUBLIC)
296b36a234dSPauli Virtanen return ADDR_LE_DEV_PUBLIC;
297b36a234dSPauli Virtanen else
298b36a234dSPauli Virtanen return ADDR_LE_DEV_RANDOM;
299b36a234dSPauli Virtanen }
300b36a234dSPauli Virtanen
iso_connect_bis(struct sock * sk)301f764a6c2SLuiz Augusto von Dentz static int iso_connect_bis(struct sock *sk)
302f764a6c2SLuiz Augusto von Dentz {
303f764a6c2SLuiz Augusto von Dentz struct iso_conn *conn;
304f764a6c2SLuiz Augusto von Dentz struct hci_conn *hcon;
305f764a6c2SLuiz Augusto von Dentz struct hci_dev *hdev;
306f764a6c2SLuiz Augusto von Dentz int err;
307f764a6c2SLuiz Augusto von Dentz
308f764a6c2SLuiz Augusto von Dentz BT_DBG("%pMR", &iso_pi(sk)->src);
309f764a6c2SLuiz Augusto von Dentz
310f764a6c2SLuiz Augusto von Dentz hdev = hci_get_route(&iso_pi(sk)->dst, &iso_pi(sk)->src,
311f764a6c2SLuiz Augusto von Dentz iso_pi(sk)->src_type);
312f764a6c2SLuiz Augusto von Dentz if (!hdev)
313f764a6c2SLuiz Augusto von Dentz return -EHOSTUNREACH;
314f764a6c2SLuiz Augusto von Dentz
315f764a6c2SLuiz Augusto von Dentz hci_dev_lock(hdev);
316f764a6c2SLuiz Augusto von Dentz
317f764a6c2SLuiz Augusto von Dentz if (!bis_capable(hdev)) {
318f764a6c2SLuiz Augusto von Dentz err = -EOPNOTSUPP;
319241f5193SLuiz Augusto von Dentz goto unlock;
320f764a6c2SLuiz Augusto von Dentz }
321f764a6c2SLuiz Augusto von Dentz
3220fe8c8d0SIulia Tanasescu /* Fail if user set invalid QoS */
3230fe8c8d0SIulia Tanasescu if (iso_pi(sk)->qos_user_set && !check_bcast_qos(&iso_pi(sk)->qos)) {
3240fe8c8d0SIulia Tanasescu iso_pi(sk)->qos = default_qos;
3250fe8c8d0SIulia Tanasescu err = -EINVAL;
3260fe8c8d0SIulia Tanasescu goto unlock;
3270fe8c8d0SIulia Tanasescu }
3280fe8c8d0SIulia Tanasescu
329f764a6c2SLuiz Augusto von Dentz /* Fail if out PHYs are marked as disabled */
3300fe8c8d0SIulia Tanasescu if (!iso_pi(sk)->qos.bcast.out.phy) {
331f764a6c2SLuiz Augusto von Dentz err = -EINVAL;
332241f5193SLuiz Augusto von Dentz goto unlock;
333f764a6c2SLuiz Augusto von Dentz }
334f764a6c2SLuiz Augusto von Dentz
335a0bfde16SIulia Tanasescu /* Just bind if DEFER_SETUP has been set */
336a0bfde16SIulia Tanasescu if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) {
337a0bfde16SIulia Tanasescu hcon = hci_bind_bis(hdev, &iso_pi(sk)->dst,
338a0bfde16SIulia Tanasescu &iso_pi(sk)->qos, iso_pi(sk)->base_len,
339a0bfde16SIulia Tanasescu iso_pi(sk)->base);
340a0bfde16SIulia Tanasescu if (IS_ERR(hcon)) {
341a0bfde16SIulia Tanasescu err = PTR_ERR(hcon);
342a0bfde16SIulia Tanasescu goto unlock;
343a0bfde16SIulia Tanasescu }
344a0bfde16SIulia Tanasescu } else {
345d11ab690SPauli Virtanen hcon = hci_connect_bis(hdev, &iso_pi(sk)->dst,
346d11ab690SPauli Virtanen le_addr_type(iso_pi(sk)->dst_type),
347f764a6c2SLuiz Augusto von Dentz &iso_pi(sk)->qos, iso_pi(sk)->base_len,
348f764a6c2SLuiz Augusto von Dentz iso_pi(sk)->base);
349f764a6c2SLuiz Augusto von Dentz if (IS_ERR(hcon)) {
350f764a6c2SLuiz Augusto von Dentz err = PTR_ERR(hcon);
351241f5193SLuiz Augusto von Dentz goto unlock;
352f764a6c2SLuiz Augusto von Dentz }
353a0bfde16SIulia Tanasescu }
354f764a6c2SLuiz Augusto von Dentz
355f764a6c2SLuiz Augusto von Dentz conn = iso_conn_add(hcon);
356f764a6c2SLuiz Augusto von Dentz if (!conn) {
357f764a6c2SLuiz Augusto von Dentz hci_conn_drop(hcon);
358f764a6c2SLuiz Augusto von Dentz err = -ENOMEM;
359241f5193SLuiz Augusto von Dentz goto unlock;
360f764a6c2SLuiz Augusto von Dentz }
361f764a6c2SLuiz Augusto von Dentz
362d40ae85eSPauli Virtanen lock_sock(sk);
363241f5193SLuiz Augusto von Dentz
3646a5ad251SLuiz Augusto von Dentz err = iso_chan_add(conn, sk, NULL);
365d40ae85eSPauli Virtanen if (err) {
366d40ae85eSPauli Virtanen release_sock(sk);
367d40ae85eSPauli Virtanen goto unlock;
368d40ae85eSPauli Virtanen }
369241f5193SLuiz Augusto von Dentz
370f764a6c2SLuiz Augusto von Dentz /* Update source addr of the socket */
371f764a6c2SLuiz Augusto von Dentz bacpy(&iso_pi(sk)->src, &hcon->src);
372f764a6c2SLuiz Augusto von Dentz
373f764a6c2SLuiz Augusto von Dentz if (hcon->state == BT_CONNECTED) {
374f764a6c2SLuiz Augusto von Dentz iso_sock_clear_timer(sk);
375f764a6c2SLuiz Augusto von Dentz sk->sk_state = BT_CONNECTED;
376a0bfde16SIulia Tanasescu } else if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) {
377a0bfde16SIulia Tanasescu iso_sock_clear_timer(sk);
378a0bfde16SIulia Tanasescu sk->sk_state = BT_CONNECT;
379f764a6c2SLuiz Augusto von Dentz } else {
380f764a6c2SLuiz Augusto von Dentz sk->sk_state = BT_CONNECT;
381f764a6c2SLuiz Augusto von Dentz iso_sock_set_timer(sk, sk->sk_sndtimeo);
382f764a6c2SLuiz Augusto von Dentz }
383f764a6c2SLuiz Augusto von Dentz
384241f5193SLuiz Augusto von Dentz release_sock(sk);
385241f5193SLuiz Augusto von Dentz
386241f5193SLuiz Augusto von Dentz unlock:
387f764a6c2SLuiz Augusto von Dentz hci_dev_unlock(hdev);
388f764a6c2SLuiz Augusto von Dentz hci_dev_put(hdev);
389f764a6c2SLuiz Augusto von Dentz return err;
390f764a6c2SLuiz Augusto von Dentz }
391f764a6c2SLuiz Augusto von Dentz
iso_connect_cis(struct sock * sk)392f764a6c2SLuiz Augusto von Dentz static int iso_connect_cis(struct sock *sk)
393ccf74f23SLuiz Augusto von Dentz {
394ccf74f23SLuiz Augusto von Dentz struct iso_conn *conn;
395ccf74f23SLuiz Augusto von Dentz struct hci_conn *hcon;
396ccf74f23SLuiz Augusto von Dentz struct hci_dev *hdev;
397ccf74f23SLuiz Augusto von Dentz int err;
398ccf74f23SLuiz Augusto von Dentz
399ccf74f23SLuiz Augusto von Dentz BT_DBG("%pMR -> %pMR", &iso_pi(sk)->src, &iso_pi(sk)->dst);
400ccf74f23SLuiz Augusto von Dentz
401ccf74f23SLuiz Augusto von Dentz hdev = hci_get_route(&iso_pi(sk)->dst, &iso_pi(sk)->src,
402ccf74f23SLuiz Augusto von Dentz iso_pi(sk)->src_type);
403ccf74f23SLuiz Augusto von Dentz if (!hdev)
404ccf74f23SLuiz Augusto von Dentz return -EHOSTUNREACH;
405ccf74f23SLuiz Augusto von Dentz
406ccf74f23SLuiz Augusto von Dentz hci_dev_lock(hdev);
407ccf74f23SLuiz Augusto von Dentz
408ccf74f23SLuiz Augusto von Dentz if (!cis_central_capable(hdev)) {
409ccf74f23SLuiz Augusto von Dentz err = -EOPNOTSUPP;
410241f5193SLuiz Augusto von Dentz goto unlock;
411ccf74f23SLuiz Augusto von Dentz }
412ccf74f23SLuiz Augusto von Dentz
4130fe8c8d0SIulia Tanasescu /* Fail if user set invalid QoS */
4140fe8c8d0SIulia Tanasescu if (iso_pi(sk)->qos_user_set && !check_ucast_qos(&iso_pi(sk)->qos)) {
4150fe8c8d0SIulia Tanasescu iso_pi(sk)->qos = default_qos;
4160fe8c8d0SIulia Tanasescu err = -EINVAL;
4170fe8c8d0SIulia Tanasescu goto unlock;
4180fe8c8d0SIulia Tanasescu }
4190fe8c8d0SIulia Tanasescu
420ccf74f23SLuiz Augusto von Dentz /* Fail if either PHYs are marked as disabled */
4210fe8c8d0SIulia Tanasescu if (!iso_pi(sk)->qos.ucast.in.phy && !iso_pi(sk)->qos.ucast.out.phy) {
422ccf74f23SLuiz Augusto von Dentz err = -EINVAL;
423241f5193SLuiz Augusto von Dentz goto unlock;
424ccf74f23SLuiz Augusto von Dentz }
425ccf74f23SLuiz Augusto von Dentz
426ccf74f23SLuiz Augusto von Dentz /* Just bind if DEFER_SETUP has been set */
427ccf74f23SLuiz Augusto von Dentz if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) {
428ccf74f23SLuiz Augusto von Dentz hcon = hci_bind_cis(hdev, &iso_pi(sk)->dst,
429b36a234dSPauli Virtanen le_addr_type(iso_pi(sk)->dst_type),
430b36a234dSPauli Virtanen &iso_pi(sk)->qos);
431ccf74f23SLuiz Augusto von Dentz if (IS_ERR(hcon)) {
432ccf74f23SLuiz Augusto von Dentz err = PTR_ERR(hcon);
433241f5193SLuiz Augusto von Dentz goto unlock;
434ccf74f23SLuiz Augusto von Dentz }
435ccf74f23SLuiz Augusto von Dentz } else {
436ccf74f23SLuiz Augusto von Dentz hcon = hci_connect_cis(hdev, &iso_pi(sk)->dst,
437b36a234dSPauli Virtanen le_addr_type(iso_pi(sk)->dst_type),
438b36a234dSPauli Virtanen &iso_pi(sk)->qos);
439ccf74f23SLuiz Augusto von Dentz if (IS_ERR(hcon)) {
440ccf74f23SLuiz Augusto von Dentz err = PTR_ERR(hcon);
441241f5193SLuiz Augusto von Dentz goto unlock;
442ccf74f23SLuiz Augusto von Dentz }
443ccf74f23SLuiz Augusto von Dentz }
444ccf74f23SLuiz Augusto von Dentz
445ccf74f23SLuiz Augusto von Dentz conn = iso_conn_add(hcon);
446ccf74f23SLuiz Augusto von Dentz if (!conn) {
447ccf74f23SLuiz Augusto von Dentz hci_conn_drop(hcon);
448ccf74f23SLuiz Augusto von Dentz err = -ENOMEM;
449241f5193SLuiz Augusto von Dentz goto unlock;
450ccf74f23SLuiz Augusto von Dentz }
451ccf74f23SLuiz Augusto von Dentz
452d40ae85eSPauli Virtanen lock_sock(sk);
453241f5193SLuiz Augusto von Dentz
4546a5ad251SLuiz Augusto von Dentz err = iso_chan_add(conn, sk, NULL);
455d40ae85eSPauli Virtanen if (err) {
456d40ae85eSPauli Virtanen release_sock(sk);
457d40ae85eSPauli Virtanen goto unlock;
458d40ae85eSPauli Virtanen }
459241f5193SLuiz Augusto von Dentz
460ccf74f23SLuiz Augusto von Dentz /* Update source addr of the socket */
461ccf74f23SLuiz Augusto von Dentz bacpy(&iso_pi(sk)->src, &hcon->src);
462ccf74f23SLuiz Augusto von Dentz
463ccf74f23SLuiz Augusto von Dentz if (hcon->state == BT_CONNECTED) {
464ccf74f23SLuiz Augusto von Dentz iso_sock_clear_timer(sk);
465ccf74f23SLuiz Augusto von Dentz sk->sk_state = BT_CONNECTED;
466ccf74f23SLuiz Augusto von Dentz } else if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) {
467ccf74f23SLuiz Augusto von Dentz iso_sock_clear_timer(sk);
468ccf74f23SLuiz Augusto von Dentz sk->sk_state = BT_CONNECT;
469ccf74f23SLuiz Augusto von Dentz } else {
470ccf74f23SLuiz Augusto von Dentz sk->sk_state = BT_CONNECT;
471ccf74f23SLuiz Augusto von Dentz iso_sock_set_timer(sk, sk->sk_sndtimeo);
472ccf74f23SLuiz Augusto von Dentz }
473ccf74f23SLuiz Augusto von Dentz
474241f5193SLuiz Augusto von Dentz release_sock(sk);
475241f5193SLuiz Augusto von Dentz
476241f5193SLuiz Augusto von Dentz unlock:
477ccf74f23SLuiz Augusto von Dentz hci_dev_unlock(hdev);
478ccf74f23SLuiz Augusto von Dentz hci_dev_put(hdev);
479ccf74f23SLuiz Augusto von Dentz return err;
480ccf74f23SLuiz Augusto von Dentz }
481ccf74f23SLuiz Augusto von Dentz
iso_sock_get_qos(struct sock * sk)4821d1ab5d3SLuiz Augusto von Dentz static struct bt_iso_qos *iso_sock_get_qos(struct sock *sk)
4831d1ab5d3SLuiz Augusto von Dentz {
4841d1ab5d3SLuiz Augusto von Dentz if (sk->sk_state == BT_CONNECTED || sk->sk_state == BT_CONNECT2)
4851d1ab5d3SLuiz Augusto von Dentz return &iso_pi(sk)->conn->hcon->iso_qos;
4861d1ab5d3SLuiz Augusto von Dentz
4871d1ab5d3SLuiz Augusto von Dentz return &iso_pi(sk)->qos;
4881d1ab5d3SLuiz Augusto von Dentz }
4891d1ab5d3SLuiz Augusto von Dentz
iso_send_frame(struct sock * sk,struct sk_buff * skb)490ccf74f23SLuiz Augusto von Dentz static int iso_send_frame(struct sock *sk, struct sk_buff *skb)
491ccf74f23SLuiz Augusto von Dentz {
492ccf74f23SLuiz Augusto von Dentz struct iso_conn *conn = iso_pi(sk)->conn;
4931d1ab5d3SLuiz Augusto von Dentz struct bt_iso_qos *qos = iso_sock_get_qos(sk);
494ccf74f23SLuiz Augusto von Dentz struct hci_iso_data_hdr *hdr;
495ccf74f23SLuiz Augusto von Dentz int len = 0;
496ccf74f23SLuiz Augusto von Dentz
497ccf74f23SLuiz Augusto von Dentz BT_DBG("sk %p len %d", sk, skb->len);
498ccf74f23SLuiz Augusto von Dentz
4990fe8c8d0SIulia Tanasescu if (skb->len > qos->ucast.out.sdu)
500ccf74f23SLuiz Augusto von Dentz return -EMSGSIZE;
501ccf74f23SLuiz Augusto von Dentz
502ccf74f23SLuiz Augusto von Dentz len = skb->len;
503ccf74f23SLuiz Augusto von Dentz
504ccf74f23SLuiz Augusto von Dentz /* Push ISO data header */
505ccf74f23SLuiz Augusto von Dentz hdr = skb_push(skb, HCI_ISO_DATA_HDR_SIZE);
506ccf74f23SLuiz Augusto von Dentz hdr->sn = cpu_to_le16(conn->tx_sn++);
507ccf74f23SLuiz Augusto von Dentz hdr->slen = cpu_to_le16(hci_iso_data_len_pack(len,
508ccf74f23SLuiz Augusto von Dentz HCI_ISO_STATUS_VALID));
509ccf74f23SLuiz Augusto von Dentz
510ccf74f23SLuiz Augusto von Dentz if (sk->sk_state == BT_CONNECTED)
511ccf74f23SLuiz Augusto von Dentz hci_send_iso(conn->hcon, skb);
512ccf74f23SLuiz Augusto von Dentz else
513ccf74f23SLuiz Augusto von Dentz len = -ENOTCONN;
514ccf74f23SLuiz Augusto von Dentz
515ccf74f23SLuiz Augusto von Dentz return len;
516ccf74f23SLuiz Augusto von Dentz }
517ccf74f23SLuiz Augusto von Dentz
iso_recv_frame(struct iso_conn * conn,struct sk_buff * skb)518ccf74f23SLuiz Augusto von Dentz static void iso_recv_frame(struct iso_conn *conn, struct sk_buff *skb)
519ccf74f23SLuiz Augusto von Dentz {
520ccf74f23SLuiz Augusto von Dentz struct sock *sk;
521ccf74f23SLuiz Augusto von Dentz
522ccf74f23SLuiz Augusto von Dentz iso_conn_lock(conn);
523ccf74f23SLuiz Augusto von Dentz sk = conn->sk;
524ccf74f23SLuiz Augusto von Dentz iso_conn_unlock(conn);
525ccf74f23SLuiz Augusto von Dentz
526ccf74f23SLuiz Augusto von Dentz if (!sk)
527ccf74f23SLuiz Augusto von Dentz goto drop;
528ccf74f23SLuiz Augusto von Dentz
529ccf74f23SLuiz Augusto von Dentz BT_DBG("sk %p len %d", sk, skb->len);
530ccf74f23SLuiz Augusto von Dentz
531ccf74f23SLuiz Augusto von Dentz if (sk->sk_state != BT_CONNECTED)
532ccf74f23SLuiz Augusto von Dentz goto drop;
533ccf74f23SLuiz Augusto von Dentz
534ccf74f23SLuiz Augusto von Dentz if (!sock_queue_rcv_skb(sk, skb))
535ccf74f23SLuiz Augusto von Dentz return;
536ccf74f23SLuiz Augusto von Dentz
537ccf74f23SLuiz Augusto von Dentz drop:
538ccf74f23SLuiz Augusto von Dentz kfree_skb(skb);
539ccf74f23SLuiz Augusto von Dentz }
540ccf74f23SLuiz Augusto von Dentz
541ccf74f23SLuiz Augusto von Dentz /* -------- Socket interface ---------- */
__iso_get_sock_listen_by_addr(bdaddr_t * src,bdaddr_t * dst)542e0275ea5SLuiz Augusto von Dentz static struct sock *__iso_get_sock_listen_by_addr(bdaddr_t *src, bdaddr_t *dst)
543ccf74f23SLuiz Augusto von Dentz {
544ccf74f23SLuiz Augusto von Dentz struct sock *sk;
545ccf74f23SLuiz Augusto von Dentz
546ccf74f23SLuiz Augusto von Dentz sk_for_each(sk, &iso_sk_list.head) {
547ccf74f23SLuiz Augusto von Dentz if (sk->sk_state != BT_LISTEN)
548ccf74f23SLuiz Augusto von Dentz continue;
549ccf74f23SLuiz Augusto von Dentz
550e0275ea5SLuiz Augusto von Dentz if (bacmp(&iso_pi(sk)->dst, dst))
551e0275ea5SLuiz Augusto von Dentz continue;
552e0275ea5SLuiz Augusto von Dentz
553e0275ea5SLuiz Augusto von Dentz if (!bacmp(&iso_pi(sk)->src, src))
554ccf74f23SLuiz Augusto von Dentz return sk;
555ccf74f23SLuiz Augusto von Dentz }
556ccf74f23SLuiz Augusto von Dentz
557ccf74f23SLuiz Augusto von Dentz return NULL;
558ccf74f23SLuiz Augusto von Dentz }
559ccf74f23SLuiz Augusto von Dentz
__iso_get_sock_listen_by_sid(bdaddr_t * ba,bdaddr_t * bc,__u8 sid)560f764a6c2SLuiz Augusto von Dentz static struct sock *__iso_get_sock_listen_by_sid(bdaddr_t *ba, bdaddr_t *bc,
561f764a6c2SLuiz Augusto von Dentz __u8 sid)
562f764a6c2SLuiz Augusto von Dentz {
563f764a6c2SLuiz Augusto von Dentz struct sock *sk;
564f764a6c2SLuiz Augusto von Dentz
565f764a6c2SLuiz Augusto von Dentz sk_for_each(sk, &iso_sk_list.head) {
566f764a6c2SLuiz Augusto von Dentz if (sk->sk_state != BT_LISTEN)
567f764a6c2SLuiz Augusto von Dentz continue;
568f764a6c2SLuiz Augusto von Dentz
569f764a6c2SLuiz Augusto von Dentz if (bacmp(&iso_pi(sk)->src, ba))
570f764a6c2SLuiz Augusto von Dentz continue;
571f764a6c2SLuiz Augusto von Dentz
572f764a6c2SLuiz Augusto von Dentz if (bacmp(&iso_pi(sk)->dst, bc))
573f764a6c2SLuiz Augusto von Dentz continue;
574f764a6c2SLuiz Augusto von Dentz
575f764a6c2SLuiz Augusto von Dentz if (iso_pi(sk)->bc_sid == sid)
576f764a6c2SLuiz Augusto von Dentz return sk;
577f764a6c2SLuiz Augusto von Dentz }
578f764a6c2SLuiz Augusto von Dentz
579f764a6c2SLuiz Augusto von Dentz return NULL;
580f764a6c2SLuiz Augusto von Dentz }
581f764a6c2SLuiz Augusto von Dentz
582f764a6c2SLuiz Augusto von Dentz /* Find socket listening:
583f764a6c2SLuiz Augusto von Dentz * source bdaddr (Unicast)
584f764a6c2SLuiz Augusto von Dentz * destination bdaddr (Broadcast only)
585f764a6c2SLuiz Augusto von Dentz * match func - pass NULL to ignore
586f764a6c2SLuiz Augusto von Dentz * match func data - pass -1 to ignore
587ccf74f23SLuiz Augusto von Dentz * Returns closest match.
588ccf74f23SLuiz Augusto von Dentz */
iso_get_sock_listen(bdaddr_t * src,bdaddr_t * dst,iso_sock_match_t match,void * data)589f764a6c2SLuiz Augusto von Dentz static struct sock *iso_get_sock_listen(bdaddr_t *src, bdaddr_t *dst,
590f764a6c2SLuiz Augusto von Dentz iso_sock_match_t match, void *data)
591ccf74f23SLuiz Augusto von Dentz {
592ccf74f23SLuiz Augusto von Dentz struct sock *sk = NULL, *sk1 = NULL;
593ccf74f23SLuiz Augusto von Dentz
594ccf74f23SLuiz Augusto von Dentz read_lock(&iso_sk_list.lock);
595ccf74f23SLuiz Augusto von Dentz
596ccf74f23SLuiz Augusto von Dentz sk_for_each(sk, &iso_sk_list.head) {
597ccf74f23SLuiz Augusto von Dentz if (sk->sk_state != BT_LISTEN)
598ccf74f23SLuiz Augusto von Dentz continue;
599ccf74f23SLuiz Augusto von Dentz
600f764a6c2SLuiz Augusto von Dentz /* Match Broadcast destination */
601f764a6c2SLuiz Augusto von Dentz if (bacmp(dst, BDADDR_ANY) && bacmp(&iso_pi(sk)->dst, dst))
602f764a6c2SLuiz Augusto von Dentz continue;
603f764a6c2SLuiz Augusto von Dentz
604f764a6c2SLuiz Augusto von Dentz /* Use Match function if provided */
605f764a6c2SLuiz Augusto von Dentz if (match && !match(sk, data))
606f764a6c2SLuiz Augusto von Dentz continue;
607f764a6c2SLuiz Augusto von Dentz
608ccf74f23SLuiz Augusto von Dentz /* Exact match. */
609ccf74f23SLuiz Augusto von Dentz if (!bacmp(&iso_pi(sk)->src, src))
610ccf74f23SLuiz Augusto von Dentz break;
611ccf74f23SLuiz Augusto von Dentz
612ccf74f23SLuiz Augusto von Dentz /* Closest match */
613ccf74f23SLuiz Augusto von Dentz if (!bacmp(&iso_pi(sk)->src, BDADDR_ANY))
614ccf74f23SLuiz Augusto von Dentz sk1 = sk;
615ccf74f23SLuiz Augusto von Dentz }
616ccf74f23SLuiz Augusto von Dentz
617ccf74f23SLuiz Augusto von Dentz read_unlock(&iso_sk_list.lock);
618ccf74f23SLuiz Augusto von Dentz
619ccf74f23SLuiz Augusto von Dentz return sk ? sk : sk1;
620ccf74f23SLuiz Augusto von Dentz }
621ccf74f23SLuiz Augusto von Dentz
iso_sock_destruct(struct sock * sk)622ccf74f23SLuiz Augusto von Dentz static void iso_sock_destruct(struct sock *sk)
623ccf74f23SLuiz Augusto von Dentz {
624ccf74f23SLuiz Augusto von Dentz BT_DBG("sk %p", sk);
625ccf74f23SLuiz Augusto von Dentz
626ccf74f23SLuiz Augusto von Dentz skb_queue_purge(&sk->sk_receive_queue);
627ccf74f23SLuiz Augusto von Dentz skb_queue_purge(&sk->sk_write_queue);
628ccf74f23SLuiz Augusto von Dentz }
629ccf74f23SLuiz Augusto von Dentz
iso_sock_cleanup_listen(struct sock * parent)630ccf74f23SLuiz Augusto von Dentz static void iso_sock_cleanup_listen(struct sock *parent)
631ccf74f23SLuiz Augusto von Dentz {
632ccf74f23SLuiz Augusto von Dentz struct sock *sk;
633ccf74f23SLuiz Augusto von Dentz
634ccf74f23SLuiz Augusto von Dentz BT_DBG("parent %p", parent);
635ccf74f23SLuiz Augusto von Dentz
636ccf74f23SLuiz Augusto von Dentz /* Close not yet accepted channels */
637ccf74f23SLuiz Augusto von Dentz while ((sk = bt_accept_dequeue(parent, NULL))) {
638ccf74f23SLuiz Augusto von Dentz iso_sock_close(sk);
639ccf74f23SLuiz Augusto von Dentz iso_sock_kill(sk);
640ccf74f23SLuiz Augusto von Dentz }
641ccf74f23SLuiz Augusto von Dentz
642fbdc4bc4SIulia Tanasescu /* If listening socket stands for a PA sync connection,
643fbdc4bc4SIulia Tanasescu * properly disconnect the hcon and socket.
644fbdc4bc4SIulia Tanasescu */
645fbdc4bc4SIulia Tanasescu if (iso_pi(parent)->conn && iso_pi(parent)->conn->hcon &&
646fbdc4bc4SIulia Tanasescu test_bit(HCI_CONN_PA_SYNC, &iso_pi(parent)->conn->hcon->flags)) {
647fbdc4bc4SIulia Tanasescu iso_sock_disconn(parent);
648fbdc4bc4SIulia Tanasescu return;
649fbdc4bc4SIulia Tanasescu }
650fbdc4bc4SIulia Tanasescu
651ccf74f23SLuiz Augusto von Dentz parent->sk_state = BT_CLOSED;
652ccf74f23SLuiz Augusto von Dentz sock_set_flag(parent, SOCK_ZAPPED);
653ccf74f23SLuiz Augusto von Dentz }
654ccf74f23SLuiz Augusto von Dentz
655ccf74f23SLuiz Augusto von Dentz /* Kill socket (only if zapped and orphan)
656ccf74f23SLuiz Augusto von Dentz * Must be called on unlocked socket.
657ccf74f23SLuiz Augusto von Dentz */
iso_sock_kill(struct sock * sk)658ccf74f23SLuiz Augusto von Dentz static void iso_sock_kill(struct sock *sk)
659ccf74f23SLuiz Augusto von Dentz {
660ccf74f23SLuiz Augusto von Dentz if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket ||
661ccf74f23SLuiz Augusto von Dentz sock_flag(sk, SOCK_DEAD))
662ccf74f23SLuiz Augusto von Dentz return;
663ccf74f23SLuiz Augusto von Dentz
664ccf74f23SLuiz Augusto von Dentz BT_DBG("sk %p state %d", sk, sk->sk_state);
665ccf74f23SLuiz Augusto von Dentz
666ccf74f23SLuiz Augusto von Dentz /* Kill poor orphan */
667ccf74f23SLuiz Augusto von Dentz bt_sock_unlink(&iso_sk_list, sk);
668ccf74f23SLuiz Augusto von Dentz sock_set_flag(sk, SOCK_DEAD);
669ccf74f23SLuiz Augusto von Dentz sock_put(sk);
670ccf74f23SLuiz Augusto von Dentz }
671ccf74f23SLuiz Augusto von Dentz
iso_sock_disconn(struct sock * sk)672fbdc4bc4SIulia Tanasescu static void iso_sock_disconn(struct sock *sk)
673fbdc4bc4SIulia Tanasescu {
674fbdc4bc4SIulia Tanasescu sk->sk_state = BT_DISCONN;
675fbdc4bc4SIulia Tanasescu iso_sock_set_timer(sk, ISO_DISCONN_TIMEOUT);
676fbdc4bc4SIulia Tanasescu iso_conn_lock(iso_pi(sk)->conn);
677fbdc4bc4SIulia Tanasescu hci_conn_drop(iso_pi(sk)->conn->hcon);
678fbdc4bc4SIulia Tanasescu iso_pi(sk)->conn->hcon = NULL;
679fbdc4bc4SIulia Tanasescu iso_conn_unlock(iso_pi(sk)->conn);
680fbdc4bc4SIulia Tanasescu }
681fbdc4bc4SIulia Tanasescu
__iso_sock_close(struct sock * sk)682ccf74f23SLuiz Augusto von Dentz static void __iso_sock_close(struct sock *sk)
683ccf74f23SLuiz Augusto von Dentz {
684ccf74f23SLuiz Augusto von Dentz BT_DBG("sk %p state %d socket %p", sk, sk->sk_state, sk->sk_socket);
685ccf74f23SLuiz Augusto von Dentz
686ccf74f23SLuiz Augusto von Dentz switch (sk->sk_state) {
687ccf74f23SLuiz Augusto von Dentz case BT_LISTEN:
688ccf74f23SLuiz Augusto von Dentz iso_sock_cleanup_listen(sk);
689ccf74f23SLuiz Augusto von Dentz break;
690ccf74f23SLuiz Augusto von Dentz
69169997d50SPauli Virtanen case BT_CONNECT:
692ccf74f23SLuiz Augusto von Dentz case BT_CONNECTED:
693ccf74f23SLuiz Augusto von Dentz case BT_CONFIG:
694fbdc4bc4SIulia Tanasescu if (iso_pi(sk)->conn->hcon)
695fbdc4bc4SIulia Tanasescu iso_sock_disconn(sk);
696fbdc4bc4SIulia Tanasescu else
697ccf74f23SLuiz Augusto von Dentz iso_chan_del(sk, ECONNRESET);
698ccf74f23SLuiz Augusto von Dentz break;
699ccf74f23SLuiz Augusto von Dentz
700ccf74f23SLuiz Augusto von Dentz case BT_CONNECT2:
701fbdc4bc4SIulia Tanasescu if (iso_pi(sk)->conn->hcon &&
702fbdc4bc4SIulia Tanasescu (test_bit(HCI_CONN_PA_SYNC, &iso_pi(sk)->conn->hcon->flags) ||
703fbdc4bc4SIulia Tanasescu test_bit(HCI_CONN_PA_SYNC_FAILED, &iso_pi(sk)->conn->hcon->flags)))
704fbdc4bc4SIulia Tanasescu iso_sock_disconn(sk);
705fbdc4bc4SIulia Tanasescu else
706ccf74f23SLuiz Augusto von Dentz iso_chan_del(sk, ECONNRESET);
707ccf74f23SLuiz Augusto von Dentz break;
708ccf74f23SLuiz Augusto von Dentz case BT_DISCONN:
709ccf74f23SLuiz Augusto von Dentz iso_chan_del(sk, ECONNRESET);
710ccf74f23SLuiz Augusto von Dentz break;
711ccf74f23SLuiz Augusto von Dentz
712ccf74f23SLuiz Augusto von Dentz default:
713ccf74f23SLuiz Augusto von Dentz sock_set_flag(sk, SOCK_ZAPPED);
714ccf74f23SLuiz Augusto von Dentz break;
715ccf74f23SLuiz Augusto von Dentz }
716ccf74f23SLuiz Augusto von Dentz }
717ccf74f23SLuiz Augusto von Dentz
718ccf74f23SLuiz Augusto von Dentz /* Must be called on unlocked socket. */
iso_sock_close(struct sock * sk)719ccf74f23SLuiz Augusto von Dentz static void iso_sock_close(struct sock *sk)
720ccf74f23SLuiz Augusto von Dentz {
721ccf74f23SLuiz Augusto von Dentz iso_sock_clear_timer(sk);
722ccf74f23SLuiz Augusto von Dentz lock_sock(sk);
723ccf74f23SLuiz Augusto von Dentz __iso_sock_close(sk);
724ccf74f23SLuiz Augusto von Dentz release_sock(sk);
725ccf74f23SLuiz Augusto von Dentz iso_sock_kill(sk);
726ccf74f23SLuiz Augusto von Dentz }
727ccf74f23SLuiz Augusto von Dentz
iso_sock_init(struct sock * sk,struct sock * parent)728ccf74f23SLuiz Augusto von Dentz static void iso_sock_init(struct sock *sk, struct sock *parent)
729ccf74f23SLuiz Augusto von Dentz {
730ccf74f23SLuiz Augusto von Dentz BT_DBG("sk %p", sk);
731ccf74f23SLuiz Augusto von Dentz
732ccf74f23SLuiz Augusto von Dentz if (parent) {
733ccf74f23SLuiz Augusto von Dentz sk->sk_type = parent->sk_type;
734ccf74f23SLuiz Augusto von Dentz bt_sk(sk)->flags = bt_sk(parent)->flags;
735ccf74f23SLuiz Augusto von Dentz security_sk_clone(parent, sk);
736ccf74f23SLuiz Augusto von Dentz }
737ccf74f23SLuiz Augusto von Dentz }
738ccf74f23SLuiz Augusto von Dentz
739ccf74f23SLuiz Augusto von Dentz static struct proto iso_proto = {
740ccf74f23SLuiz Augusto von Dentz .name = "ISO",
741ccf74f23SLuiz Augusto von Dentz .owner = THIS_MODULE,
742ccf74f23SLuiz Augusto von Dentz .obj_size = sizeof(struct iso_pinfo)
743ccf74f23SLuiz Augusto von Dentz };
744ccf74f23SLuiz Augusto von Dentz
745ccf74f23SLuiz Augusto von Dentz #define DEFAULT_IO_QOS \
746ccf74f23SLuiz Augusto von Dentz { \
747ccf74f23SLuiz Augusto von Dentz .interval = 10000u, \
748ccf74f23SLuiz Augusto von Dentz .latency = 10u, \
749ccf74f23SLuiz Augusto von Dentz .sdu = 40u, \
750ccf74f23SLuiz Augusto von Dentz .phy = BT_ISO_PHY_2M, \
751ccf74f23SLuiz Augusto von Dentz .rtn = 2u, \
752ccf74f23SLuiz Augusto von Dentz }
753ccf74f23SLuiz Augusto von Dentz
754ccf74f23SLuiz Augusto von Dentz static struct bt_iso_qos default_qos = {
7550fe8c8d0SIulia Tanasescu .bcast = {
7560fe8c8d0SIulia Tanasescu .big = BT_ISO_QOS_BIG_UNSET,
7570fe8c8d0SIulia Tanasescu .bis = BT_ISO_QOS_BIS_UNSET,
75814f0dcecSLuiz Augusto von Dentz .sync_factor = 0x01,
759ccf74f23SLuiz Augusto von Dentz .packing = 0x00,
760ccf74f23SLuiz Augusto von Dentz .framing = 0x00,
761ccf74f23SLuiz Augusto von Dentz .in = DEFAULT_IO_QOS,
762ccf74f23SLuiz Augusto von Dentz .out = DEFAULT_IO_QOS,
7630fe8c8d0SIulia Tanasescu .encryption = 0x00,
7640fe8c8d0SIulia Tanasescu .bcode = {0x00},
7650fe8c8d0SIulia Tanasescu .options = 0x00,
7660fe8c8d0SIulia Tanasescu .skip = 0x0000,
767c8321645SLuiz Augusto von Dentz .sync_timeout = BT_ISO_SYNC_TIMEOUT,
7680fe8c8d0SIulia Tanasescu .sync_cte_type = 0x00,
7690fe8c8d0SIulia Tanasescu .mse = 0x00,
770c8321645SLuiz Augusto von Dentz .timeout = BT_ISO_SYNC_TIMEOUT,
7710fe8c8d0SIulia Tanasescu },
772ccf74f23SLuiz Augusto von Dentz };
773ccf74f23SLuiz Augusto von Dentz
iso_sock_alloc(struct net * net,struct socket * sock,int proto,gfp_t prio,int kern)774ccf74f23SLuiz Augusto von Dentz static struct sock *iso_sock_alloc(struct net *net, struct socket *sock,
775ccf74f23SLuiz Augusto von Dentz int proto, gfp_t prio, int kern)
776ccf74f23SLuiz Augusto von Dentz {
777ccf74f23SLuiz Augusto von Dentz struct sock *sk;
778ccf74f23SLuiz Augusto von Dentz
7796bfa273eSLuiz Augusto von Dentz sk = bt_sock_alloc(net, sock, &iso_proto, proto, prio, kern);
780ccf74f23SLuiz Augusto von Dentz if (!sk)
781ccf74f23SLuiz Augusto von Dentz return NULL;
782ccf74f23SLuiz Augusto von Dentz
783ccf74f23SLuiz Augusto von Dentz sk->sk_destruct = iso_sock_destruct;
784ccf74f23SLuiz Augusto von Dentz sk->sk_sndtimeo = ISO_CONN_TIMEOUT;
785ccf74f23SLuiz Augusto von Dentz
786ccf74f23SLuiz Augusto von Dentz /* Set address type as public as default src address is BDADDR_ANY */
787ccf74f23SLuiz Augusto von Dentz iso_pi(sk)->src_type = BDADDR_LE_PUBLIC;
788ccf74f23SLuiz Augusto von Dentz
789ccf74f23SLuiz Augusto von Dentz iso_pi(sk)->qos = default_qos;
790ccf74f23SLuiz Augusto von Dentz
791ccf74f23SLuiz Augusto von Dentz bt_sock_link(&iso_sk_list, sk);
792ccf74f23SLuiz Augusto von Dentz return sk;
793ccf74f23SLuiz Augusto von Dentz }
794ccf74f23SLuiz Augusto von Dentz
iso_sock_create(struct net * net,struct socket * sock,int protocol,int kern)795ccf74f23SLuiz Augusto von Dentz static int iso_sock_create(struct net *net, struct socket *sock, int protocol,
796ccf74f23SLuiz Augusto von Dentz int kern)
797ccf74f23SLuiz Augusto von Dentz {
798ccf74f23SLuiz Augusto von Dentz struct sock *sk;
799ccf74f23SLuiz Augusto von Dentz
800ccf74f23SLuiz Augusto von Dentz BT_DBG("sock %p", sock);
801ccf74f23SLuiz Augusto von Dentz
802ccf74f23SLuiz Augusto von Dentz sock->state = SS_UNCONNECTED;
803ccf74f23SLuiz Augusto von Dentz
804ccf74f23SLuiz Augusto von Dentz if (sock->type != SOCK_SEQPACKET)
805ccf74f23SLuiz Augusto von Dentz return -ESOCKTNOSUPPORT;
806ccf74f23SLuiz Augusto von Dentz
807ccf74f23SLuiz Augusto von Dentz sock->ops = &iso_sock_ops;
808ccf74f23SLuiz Augusto von Dentz
809ccf74f23SLuiz Augusto von Dentz sk = iso_sock_alloc(net, sock, protocol, GFP_ATOMIC, kern);
810ccf74f23SLuiz Augusto von Dentz if (!sk)
811ccf74f23SLuiz Augusto von Dentz return -ENOMEM;
812ccf74f23SLuiz Augusto von Dentz
813ccf74f23SLuiz Augusto von Dentz iso_sock_init(sk, NULL);
814ccf74f23SLuiz Augusto von Dentz return 0;
815ccf74f23SLuiz Augusto von Dentz }
816ccf74f23SLuiz Augusto von Dentz
iso_sock_bind_bc(struct socket * sock,struct sockaddr * addr,int addr_len)817f764a6c2SLuiz Augusto von Dentz static int iso_sock_bind_bc(struct socket *sock, struct sockaddr *addr,
818f764a6c2SLuiz Augusto von Dentz int addr_len)
819f764a6c2SLuiz Augusto von Dentz {
820f764a6c2SLuiz Augusto von Dentz struct sockaddr_iso *sa = (struct sockaddr_iso *)addr;
821f764a6c2SLuiz Augusto von Dentz struct sock *sk = sock->sk;
822f764a6c2SLuiz Augusto von Dentz int i;
823f764a6c2SLuiz Augusto von Dentz
824f764a6c2SLuiz Augusto von Dentz BT_DBG("sk %p bc_sid %u bc_num_bis %u", sk, sa->iso_bc->bc_sid,
825f764a6c2SLuiz Augusto von Dentz sa->iso_bc->bc_num_bis);
826f764a6c2SLuiz Augusto von Dentz
827f764a6c2SLuiz Augusto von Dentz if (addr_len > sizeof(*sa) + sizeof(*sa->iso_bc) ||
828f764a6c2SLuiz Augusto von Dentz sa->iso_bc->bc_num_bis < 0x01 || sa->iso_bc->bc_num_bis > 0x1f)
829f764a6c2SLuiz Augusto von Dentz return -EINVAL;
830f764a6c2SLuiz Augusto von Dentz
831f764a6c2SLuiz Augusto von Dentz bacpy(&iso_pi(sk)->dst, &sa->iso_bc->bc_bdaddr);
832f764a6c2SLuiz Augusto von Dentz iso_pi(sk)->dst_type = sa->iso_bc->bc_bdaddr_type;
833f764a6c2SLuiz Augusto von Dentz iso_pi(sk)->sync_handle = -1;
834f764a6c2SLuiz Augusto von Dentz iso_pi(sk)->bc_sid = sa->iso_bc->bc_sid;
835f764a6c2SLuiz Augusto von Dentz iso_pi(sk)->bc_num_bis = sa->iso_bc->bc_num_bis;
836f764a6c2SLuiz Augusto von Dentz
837f764a6c2SLuiz Augusto von Dentz for (i = 0; i < iso_pi(sk)->bc_num_bis; i++) {
838f764a6c2SLuiz Augusto von Dentz if (sa->iso_bc->bc_bis[i] < 0x01 ||
839f764a6c2SLuiz Augusto von Dentz sa->iso_bc->bc_bis[i] > 0x1f)
840f764a6c2SLuiz Augusto von Dentz return -EINVAL;
841f764a6c2SLuiz Augusto von Dentz
842f764a6c2SLuiz Augusto von Dentz memcpy(iso_pi(sk)->bc_bis, sa->iso_bc->bc_bis,
843f764a6c2SLuiz Augusto von Dentz iso_pi(sk)->bc_num_bis);
844f764a6c2SLuiz Augusto von Dentz }
845f764a6c2SLuiz Augusto von Dentz
846f764a6c2SLuiz Augusto von Dentz return 0;
847f764a6c2SLuiz Augusto von Dentz }
848f764a6c2SLuiz Augusto von Dentz
iso_sock_bind(struct socket * sock,struct sockaddr * addr,int addr_len)849ccf74f23SLuiz Augusto von Dentz static int iso_sock_bind(struct socket *sock, struct sockaddr *addr,
850ccf74f23SLuiz Augusto von Dentz int addr_len)
851ccf74f23SLuiz Augusto von Dentz {
852ccf74f23SLuiz Augusto von Dentz struct sockaddr_iso *sa = (struct sockaddr_iso *)addr;
853ccf74f23SLuiz Augusto von Dentz struct sock *sk = sock->sk;
854ccf74f23SLuiz Augusto von Dentz int err = 0;
855ccf74f23SLuiz Augusto von Dentz
856ccf74f23SLuiz Augusto von Dentz BT_DBG("sk %p %pMR type %u", sk, &sa->iso_bdaddr, sa->iso_bdaddr_type);
857ccf74f23SLuiz Augusto von Dentz
858ccf74f23SLuiz Augusto von Dentz if (!addr || addr_len < sizeof(struct sockaddr_iso) ||
859ccf74f23SLuiz Augusto von Dentz addr->sa_family != AF_BLUETOOTH)
860ccf74f23SLuiz Augusto von Dentz return -EINVAL;
861ccf74f23SLuiz Augusto von Dentz
862ccf74f23SLuiz Augusto von Dentz lock_sock(sk);
863ccf74f23SLuiz Augusto von Dentz
864ccf74f23SLuiz Augusto von Dentz if (sk->sk_state != BT_OPEN) {
865ccf74f23SLuiz Augusto von Dentz err = -EBADFD;
866ccf74f23SLuiz Augusto von Dentz goto done;
867ccf74f23SLuiz Augusto von Dentz }
868ccf74f23SLuiz Augusto von Dentz
869ccf74f23SLuiz Augusto von Dentz if (sk->sk_type != SOCK_SEQPACKET) {
870ccf74f23SLuiz Augusto von Dentz err = -EINVAL;
871ccf74f23SLuiz Augusto von Dentz goto done;
872ccf74f23SLuiz Augusto von Dentz }
873ccf74f23SLuiz Augusto von Dentz
874ccf74f23SLuiz Augusto von Dentz /* Check if the address type is of LE type */
875ccf74f23SLuiz Augusto von Dentz if (!bdaddr_type_is_le(sa->iso_bdaddr_type)) {
876ccf74f23SLuiz Augusto von Dentz err = -EINVAL;
877ccf74f23SLuiz Augusto von Dentz goto done;
878ccf74f23SLuiz Augusto von Dentz }
879ccf74f23SLuiz Augusto von Dentz
880ccf74f23SLuiz Augusto von Dentz bacpy(&iso_pi(sk)->src, &sa->iso_bdaddr);
881ccf74f23SLuiz Augusto von Dentz iso_pi(sk)->src_type = sa->iso_bdaddr_type;
882ccf74f23SLuiz Augusto von Dentz
883f764a6c2SLuiz Augusto von Dentz /* Check for Broadcast address */
884f764a6c2SLuiz Augusto von Dentz if (addr_len > sizeof(*sa)) {
885f764a6c2SLuiz Augusto von Dentz err = iso_sock_bind_bc(sock, addr, addr_len);
886f764a6c2SLuiz Augusto von Dentz if (err)
887f764a6c2SLuiz Augusto von Dentz goto done;
888f764a6c2SLuiz Augusto von Dentz }
889f764a6c2SLuiz Augusto von Dentz
890ccf74f23SLuiz Augusto von Dentz sk->sk_state = BT_BOUND;
891ccf74f23SLuiz Augusto von Dentz
892ccf74f23SLuiz Augusto von Dentz done:
893ccf74f23SLuiz Augusto von Dentz release_sock(sk);
894ccf74f23SLuiz Augusto von Dentz return err;
895ccf74f23SLuiz Augusto von Dentz }
896ccf74f23SLuiz Augusto von Dentz
iso_sock_connect(struct socket * sock,struct sockaddr * addr,int alen,int flags)897ccf74f23SLuiz Augusto von Dentz static int iso_sock_connect(struct socket *sock, struct sockaddr *addr,
898ccf74f23SLuiz Augusto von Dentz int alen, int flags)
899ccf74f23SLuiz Augusto von Dentz {
900ccf74f23SLuiz Augusto von Dentz struct sockaddr_iso *sa = (struct sockaddr_iso *)addr;
901ccf74f23SLuiz Augusto von Dentz struct sock *sk = sock->sk;
902ccf74f23SLuiz Augusto von Dentz int err;
903ccf74f23SLuiz Augusto von Dentz
904ccf74f23SLuiz Augusto von Dentz BT_DBG("sk %p", sk);
905ccf74f23SLuiz Augusto von Dentz
906ccf74f23SLuiz Augusto von Dentz if (alen < sizeof(struct sockaddr_iso) ||
907ccf74f23SLuiz Augusto von Dentz addr->sa_family != AF_BLUETOOTH)
908ccf74f23SLuiz Augusto von Dentz return -EINVAL;
909ccf74f23SLuiz Augusto von Dentz
910ccf74f23SLuiz Augusto von Dentz if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND)
911ccf74f23SLuiz Augusto von Dentz return -EBADFD;
912ccf74f23SLuiz Augusto von Dentz
913ccf74f23SLuiz Augusto von Dentz if (sk->sk_type != SOCK_SEQPACKET)
914ccf74f23SLuiz Augusto von Dentz return -EINVAL;
915ccf74f23SLuiz Augusto von Dentz
916ccf74f23SLuiz Augusto von Dentz /* Check if the address type is of LE type */
917ccf74f23SLuiz Augusto von Dentz if (!bdaddr_type_is_le(sa->iso_bdaddr_type))
918ccf74f23SLuiz Augusto von Dentz return -EINVAL;
919ccf74f23SLuiz Augusto von Dentz
920ccf74f23SLuiz Augusto von Dentz lock_sock(sk);
921ccf74f23SLuiz Augusto von Dentz
922ccf74f23SLuiz Augusto von Dentz bacpy(&iso_pi(sk)->dst, &sa->iso_bdaddr);
923ccf74f23SLuiz Augusto von Dentz iso_pi(sk)->dst_type = sa->iso_bdaddr_type;
924ccf74f23SLuiz Augusto von Dentz
925241f5193SLuiz Augusto von Dentz release_sock(sk);
926241f5193SLuiz Augusto von Dentz
927f764a6c2SLuiz Augusto von Dentz if (bacmp(&iso_pi(sk)->dst, BDADDR_ANY))
928f764a6c2SLuiz Augusto von Dentz err = iso_connect_cis(sk);
929f764a6c2SLuiz Augusto von Dentz else
930f764a6c2SLuiz Augusto von Dentz err = iso_connect_bis(sk);
931f764a6c2SLuiz Augusto von Dentz
932ccf74f23SLuiz Augusto von Dentz if (err)
933241f5193SLuiz Augusto von Dentz return err;
934241f5193SLuiz Augusto von Dentz
935241f5193SLuiz Augusto von Dentz lock_sock(sk);
936ccf74f23SLuiz Augusto von Dentz
937ccf74f23SLuiz Augusto von Dentz if (!test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) {
938ccf74f23SLuiz Augusto von Dentz err = bt_sock_wait_state(sk, BT_CONNECTED,
939ccf74f23SLuiz Augusto von Dentz sock_sndtimeo(sk, flags & O_NONBLOCK));
940ccf74f23SLuiz Augusto von Dentz }
941ccf74f23SLuiz Augusto von Dentz
942ccf74f23SLuiz Augusto von Dentz release_sock(sk);
943ccf74f23SLuiz Augusto von Dentz return err;
944ccf74f23SLuiz Augusto von Dentz }
945ccf74f23SLuiz Augusto von Dentz
iso_listen_bis(struct sock * sk)946f764a6c2SLuiz Augusto von Dentz static int iso_listen_bis(struct sock *sk)
947f764a6c2SLuiz Augusto von Dentz {
948f764a6c2SLuiz Augusto von Dentz struct hci_dev *hdev;
949f764a6c2SLuiz Augusto von Dentz int err = 0;
950f764a6c2SLuiz Augusto von Dentz
951f764a6c2SLuiz Augusto von Dentz BT_DBG("%pMR -> %pMR (SID 0x%2.2x)", &iso_pi(sk)->src,
952f764a6c2SLuiz Augusto von Dentz &iso_pi(sk)->dst, iso_pi(sk)->bc_sid);
953f764a6c2SLuiz Augusto von Dentz
954f764a6c2SLuiz Augusto von Dentz write_lock(&iso_sk_list.lock);
955f764a6c2SLuiz Augusto von Dentz
956f764a6c2SLuiz Augusto von Dentz if (__iso_get_sock_listen_by_sid(&iso_pi(sk)->src, &iso_pi(sk)->dst,
957f764a6c2SLuiz Augusto von Dentz iso_pi(sk)->bc_sid))
958f764a6c2SLuiz Augusto von Dentz err = -EADDRINUSE;
959f764a6c2SLuiz Augusto von Dentz
960f764a6c2SLuiz Augusto von Dentz write_unlock(&iso_sk_list.lock);
961f764a6c2SLuiz Augusto von Dentz
962f764a6c2SLuiz Augusto von Dentz if (err)
963f764a6c2SLuiz Augusto von Dentz return err;
964f764a6c2SLuiz Augusto von Dentz
965f764a6c2SLuiz Augusto von Dentz hdev = hci_get_route(&iso_pi(sk)->dst, &iso_pi(sk)->src,
966f764a6c2SLuiz Augusto von Dentz iso_pi(sk)->src_type);
967f764a6c2SLuiz Augusto von Dentz if (!hdev)
968f764a6c2SLuiz Augusto von Dentz return -EHOSTUNREACH;
969f764a6c2SLuiz Augusto von Dentz
9700fe8c8d0SIulia Tanasescu /* Fail if user set invalid QoS */
9710fe8c8d0SIulia Tanasescu if (iso_pi(sk)->qos_user_set && !check_bcast_qos(&iso_pi(sk)->qos)) {
9720fe8c8d0SIulia Tanasescu iso_pi(sk)->qos = default_qos;
9730fe8c8d0SIulia Tanasescu return -EINVAL;
9740fe8c8d0SIulia Tanasescu }
9750fe8c8d0SIulia Tanasescu
976d11ab690SPauli Virtanen err = hci_pa_create_sync(hdev, &iso_pi(sk)->dst,
977d11ab690SPauli Virtanen le_addr_type(iso_pi(sk)->dst_type),
9780fe8c8d0SIulia Tanasescu iso_pi(sk)->bc_sid, &iso_pi(sk)->qos);
979f764a6c2SLuiz Augusto von Dentz
9807e7df2c1SWang ShaoBo hci_dev_put(hdev);
981f764a6c2SLuiz Augusto von Dentz
982f764a6c2SLuiz Augusto von Dentz return err;
983f764a6c2SLuiz Augusto von Dentz }
984f764a6c2SLuiz Augusto von Dentz
iso_listen_cis(struct sock * sk)985f764a6c2SLuiz Augusto von Dentz static int iso_listen_cis(struct sock *sk)
986f764a6c2SLuiz Augusto von Dentz {
987f764a6c2SLuiz Augusto von Dentz int err = 0;
988f764a6c2SLuiz Augusto von Dentz
989f764a6c2SLuiz Augusto von Dentz BT_DBG("%pMR", &iso_pi(sk)->src);
990f764a6c2SLuiz Augusto von Dentz
991f764a6c2SLuiz Augusto von Dentz write_lock(&iso_sk_list.lock);
992f764a6c2SLuiz Augusto von Dentz
993e0275ea5SLuiz Augusto von Dentz if (__iso_get_sock_listen_by_addr(&iso_pi(sk)->src, &iso_pi(sk)->dst))
994f764a6c2SLuiz Augusto von Dentz err = -EADDRINUSE;
995f764a6c2SLuiz Augusto von Dentz
996f764a6c2SLuiz Augusto von Dentz write_unlock(&iso_sk_list.lock);
997f764a6c2SLuiz Augusto von Dentz
998f764a6c2SLuiz Augusto von Dentz return err;
999f764a6c2SLuiz Augusto von Dentz }
1000f764a6c2SLuiz Augusto von Dentz
iso_sock_listen(struct socket * sock,int backlog)1001ccf74f23SLuiz Augusto von Dentz static int iso_sock_listen(struct socket *sock, int backlog)
1002ccf74f23SLuiz Augusto von Dentz {
1003ccf74f23SLuiz Augusto von Dentz struct sock *sk = sock->sk;
1004ccf74f23SLuiz Augusto von Dentz int err = 0;
1005ccf74f23SLuiz Augusto von Dentz
1006ccf74f23SLuiz Augusto von Dentz BT_DBG("sk %p backlog %d", sk, backlog);
1007ccf74f23SLuiz Augusto von Dentz
1008ccf74f23SLuiz Augusto von Dentz lock_sock(sk);
1009ccf74f23SLuiz Augusto von Dentz
1010ccf74f23SLuiz Augusto von Dentz if (sk->sk_state != BT_BOUND) {
1011ccf74f23SLuiz Augusto von Dentz err = -EBADFD;
1012ccf74f23SLuiz Augusto von Dentz goto done;
1013ccf74f23SLuiz Augusto von Dentz }
1014ccf74f23SLuiz Augusto von Dentz
1015ccf74f23SLuiz Augusto von Dentz if (sk->sk_type != SOCK_SEQPACKET) {
1016ccf74f23SLuiz Augusto von Dentz err = -EINVAL;
1017ccf74f23SLuiz Augusto von Dentz goto done;
1018ccf74f23SLuiz Augusto von Dentz }
1019ccf74f23SLuiz Augusto von Dentz
1020f764a6c2SLuiz Augusto von Dentz if (!bacmp(&iso_pi(sk)->dst, BDADDR_ANY))
1021f764a6c2SLuiz Augusto von Dentz err = iso_listen_cis(sk);
1022f764a6c2SLuiz Augusto von Dentz else
1023f764a6c2SLuiz Augusto von Dentz err = iso_listen_bis(sk);
1024ccf74f23SLuiz Augusto von Dentz
1025f764a6c2SLuiz Augusto von Dentz if (err)
1026f764a6c2SLuiz Augusto von Dentz goto done;
1027ccf74f23SLuiz Augusto von Dentz
1028ccf74f23SLuiz Augusto von Dentz sk->sk_max_ack_backlog = backlog;
1029ccf74f23SLuiz Augusto von Dentz sk->sk_ack_backlog = 0;
1030ccf74f23SLuiz Augusto von Dentz
1031ccf74f23SLuiz Augusto von Dentz sk->sk_state = BT_LISTEN;
1032ccf74f23SLuiz Augusto von Dentz
1033ccf74f23SLuiz Augusto von Dentz done:
1034ccf74f23SLuiz Augusto von Dentz release_sock(sk);
1035ccf74f23SLuiz Augusto von Dentz return err;
1036ccf74f23SLuiz Augusto von Dentz }
1037ccf74f23SLuiz Augusto von Dentz
iso_sock_accept(struct socket * sock,struct socket * newsock,int flags,bool kern)1038ccf74f23SLuiz Augusto von Dentz static int iso_sock_accept(struct socket *sock, struct socket *newsock,
1039ccf74f23SLuiz Augusto von Dentz int flags, bool kern)
1040ccf74f23SLuiz Augusto von Dentz {
1041ccf74f23SLuiz Augusto von Dentz DEFINE_WAIT_FUNC(wait, woken_wake_function);
1042ccf74f23SLuiz Augusto von Dentz struct sock *sk = sock->sk, *ch;
1043ccf74f23SLuiz Augusto von Dentz long timeo;
1044ccf74f23SLuiz Augusto von Dentz int err = 0;
1045ccf74f23SLuiz Augusto von Dentz
1046ccf74f23SLuiz Augusto von Dentz lock_sock(sk);
1047ccf74f23SLuiz Augusto von Dentz
1048ccf74f23SLuiz Augusto von Dentz timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
1049ccf74f23SLuiz Augusto von Dentz
1050ccf74f23SLuiz Augusto von Dentz BT_DBG("sk %p timeo %ld", sk, timeo);
1051ccf74f23SLuiz Augusto von Dentz
1052ccf74f23SLuiz Augusto von Dentz /* Wait for an incoming connection. (wake-one). */
1053ccf74f23SLuiz Augusto von Dentz add_wait_queue_exclusive(sk_sleep(sk), &wait);
1054ccf74f23SLuiz Augusto von Dentz while (1) {
1055ccf74f23SLuiz Augusto von Dentz if (sk->sk_state != BT_LISTEN) {
1056ccf74f23SLuiz Augusto von Dentz err = -EBADFD;
1057ccf74f23SLuiz Augusto von Dentz break;
1058ccf74f23SLuiz Augusto von Dentz }
1059ccf74f23SLuiz Augusto von Dentz
1060ccf74f23SLuiz Augusto von Dentz ch = bt_accept_dequeue(sk, newsock);
1061ccf74f23SLuiz Augusto von Dentz if (ch)
1062ccf74f23SLuiz Augusto von Dentz break;
1063ccf74f23SLuiz Augusto von Dentz
1064ccf74f23SLuiz Augusto von Dentz if (!timeo) {
1065ccf74f23SLuiz Augusto von Dentz err = -EAGAIN;
1066ccf74f23SLuiz Augusto von Dentz break;
1067ccf74f23SLuiz Augusto von Dentz }
1068ccf74f23SLuiz Augusto von Dentz
1069ccf74f23SLuiz Augusto von Dentz if (signal_pending(current)) {
1070ccf74f23SLuiz Augusto von Dentz err = sock_intr_errno(timeo);
1071ccf74f23SLuiz Augusto von Dentz break;
1072ccf74f23SLuiz Augusto von Dentz }
1073ccf74f23SLuiz Augusto von Dentz
1074ccf74f23SLuiz Augusto von Dentz release_sock(sk);
1075ccf74f23SLuiz Augusto von Dentz
1076ccf74f23SLuiz Augusto von Dentz timeo = wait_woken(&wait, TASK_INTERRUPTIBLE, timeo);
1077ccf74f23SLuiz Augusto von Dentz lock_sock(sk);
1078ccf74f23SLuiz Augusto von Dentz }
1079ccf74f23SLuiz Augusto von Dentz remove_wait_queue(sk_sleep(sk), &wait);
1080ccf74f23SLuiz Augusto von Dentz
1081ccf74f23SLuiz Augusto von Dentz if (err)
1082ccf74f23SLuiz Augusto von Dentz goto done;
1083ccf74f23SLuiz Augusto von Dentz
1084ccf74f23SLuiz Augusto von Dentz newsock->state = SS_CONNECTED;
1085ccf74f23SLuiz Augusto von Dentz
1086ccf74f23SLuiz Augusto von Dentz BT_DBG("new socket %p", ch);
1087ccf74f23SLuiz Augusto von Dentz
1088ccf74f23SLuiz Augusto von Dentz done:
1089ccf74f23SLuiz Augusto von Dentz release_sock(sk);
1090ccf74f23SLuiz Augusto von Dentz return err;
1091ccf74f23SLuiz Augusto von Dentz }
1092ccf74f23SLuiz Augusto von Dentz
iso_sock_getname(struct socket * sock,struct sockaddr * addr,int peer)1093ccf74f23SLuiz Augusto von Dentz static int iso_sock_getname(struct socket *sock, struct sockaddr *addr,
1094ccf74f23SLuiz Augusto von Dentz int peer)
1095ccf74f23SLuiz Augusto von Dentz {
1096ccf74f23SLuiz Augusto von Dentz struct sockaddr_iso *sa = (struct sockaddr_iso *)addr;
1097ccf74f23SLuiz Augusto von Dentz struct sock *sk = sock->sk;
1098ccf74f23SLuiz Augusto von Dentz
1099ccf74f23SLuiz Augusto von Dentz BT_DBG("sock %p, sk %p", sock, sk);
1100ccf74f23SLuiz Augusto von Dentz
1101ccf74f23SLuiz Augusto von Dentz addr->sa_family = AF_BLUETOOTH;
1102ccf74f23SLuiz Augusto von Dentz
1103ccf74f23SLuiz Augusto von Dentz if (peer) {
1104ccf74f23SLuiz Augusto von Dentz bacpy(&sa->iso_bdaddr, &iso_pi(sk)->dst);
1105ccf74f23SLuiz Augusto von Dentz sa->iso_bdaddr_type = iso_pi(sk)->dst_type;
1106ccf74f23SLuiz Augusto von Dentz } else {
1107ccf74f23SLuiz Augusto von Dentz bacpy(&sa->iso_bdaddr, &iso_pi(sk)->src);
1108ccf74f23SLuiz Augusto von Dentz sa->iso_bdaddr_type = iso_pi(sk)->src_type;
1109ccf74f23SLuiz Augusto von Dentz }
1110ccf74f23SLuiz Augusto von Dentz
1111ccf74f23SLuiz Augusto von Dentz return sizeof(struct sockaddr_iso);
1112ccf74f23SLuiz Augusto von Dentz }
1113ccf74f23SLuiz Augusto von Dentz
iso_sock_sendmsg(struct socket * sock,struct msghdr * msg,size_t len)1114ccf74f23SLuiz Augusto von Dentz static int iso_sock_sendmsg(struct socket *sock, struct msghdr *msg,
1115ccf74f23SLuiz Augusto von Dentz size_t len)
1116ccf74f23SLuiz Augusto von Dentz {
1117ccf74f23SLuiz Augusto von Dentz struct sock *sk = sock->sk;
1118ccf74f23SLuiz Augusto von Dentz struct sk_buff *skb, **frag;
1119d40ae85eSPauli Virtanen size_t mtu;
1120ccf74f23SLuiz Augusto von Dentz int err;
1121ccf74f23SLuiz Augusto von Dentz
1122ccf74f23SLuiz Augusto von Dentz BT_DBG("sock %p, sk %p", sock, sk);
1123ccf74f23SLuiz Augusto von Dentz
1124ccf74f23SLuiz Augusto von Dentz err = sock_error(sk);
1125ccf74f23SLuiz Augusto von Dentz if (err)
1126ccf74f23SLuiz Augusto von Dentz return err;
1127ccf74f23SLuiz Augusto von Dentz
1128ccf74f23SLuiz Augusto von Dentz if (msg->msg_flags & MSG_OOB)
1129ccf74f23SLuiz Augusto von Dentz return -EOPNOTSUPP;
1130ccf74f23SLuiz Augusto von Dentz
1131d40ae85eSPauli Virtanen lock_sock(sk);
1132ccf74f23SLuiz Augusto von Dentz
1133d40ae85eSPauli Virtanen if (sk->sk_state != BT_CONNECTED) {
1134d40ae85eSPauli Virtanen release_sock(sk);
1135d40ae85eSPauli Virtanen return -ENOTCONN;
1136d40ae85eSPauli Virtanen }
1137d40ae85eSPauli Virtanen
1138ad3f7986SSungwoo Kim mtu = iso_pi(sk)->conn->hcon->mtu;
1139d40ae85eSPauli Virtanen
1140d40ae85eSPauli Virtanen release_sock(sk);
1141d40ae85eSPauli Virtanen
1142d40ae85eSPauli Virtanen skb = bt_skb_sendmsg(sk, msg, len, mtu, HCI_ISO_DATA_HDR_SIZE, 0);
1143ccf74f23SLuiz Augusto von Dentz if (IS_ERR(skb))
1144ccf74f23SLuiz Augusto von Dentz return PTR_ERR(skb);
1145ccf74f23SLuiz Augusto von Dentz
1146ccf74f23SLuiz Augusto von Dentz len -= skb->len;
1147ccf74f23SLuiz Augusto von Dentz
1148ccf74f23SLuiz Augusto von Dentz BT_DBG("skb %p len %d", sk, skb->len);
1149ccf74f23SLuiz Augusto von Dentz
1150ccf74f23SLuiz Augusto von Dentz /* Continuation fragments */
1151ccf74f23SLuiz Augusto von Dentz frag = &skb_shinfo(skb)->frag_list;
1152ccf74f23SLuiz Augusto von Dentz while (len) {
1153ccf74f23SLuiz Augusto von Dentz struct sk_buff *tmp;
1154ccf74f23SLuiz Augusto von Dentz
1155d40ae85eSPauli Virtanen tmp = bt_skb_sendmsg(sk, msg, len, mtu, 0, 0);
1156ccf74f23SLuiz Augusto von Dentz if (IS_ERR(tmp)) {
1157ccf74f23SLuiz Augusto von Dentz kfree_skb(skb);
1158ccf74f23SLuiz Augusto von Dentz return PTR_ERR(tmp);
1159ccf74f23SLuiz Augusto von Dentz }
1160ccf74f23SLuiz Augusto von Dentz
1161ccf74f23SLuiz Augusto von Dentz *frag = tmp;
1162ccf74f23SLuiz Augusto von Dentz
1163ccf74f23SLuiz Augusto von Dentz len -= tmp->len;
1164ccf74f23SLuiz Augusto von Dentz
1165ccf74f23SLuiz Augusto von Dentz skb->len += tmp->len;
1166ccf74f23SLuiz Augusto von Dentz skb->data_len += tmp->len;
1167ccf74f23SLuiz Augusto von Dentz
1168ccf74f23SLuiz Augusto von Dentz BT_DBG("frag %p len %d", *frag, tmp->len);
1169ccf74f23SLuiz Augusto von Dentz
1170ccf74f23SLuiz Augusto von Dentz frag = &(*frag)->next;
1171ccf74f23SLuiz Augusto von Dentz }
1172ccf74f23SLuiz Augusto von Dentz
1173ccf74f23SLuiz Augusto von Dentz lock_sock(sk);
1174ccf74f23SLuiz Augusto von Dentz
1175ccf74f23SLuiz Augusto von Dentz if (sk->sk_state == BT_CONNECTED)
1176ccf74f23SLuiz Augusto von Dentz err = iso_send_frame(sk, skb);
1177ccf74f23SLuiz Augusto von Dentz else
1178ccf74f23SLuiz Augusto von Dentz err = -ENOTCONN;
1179ccf74f23SLuiz Augusto von Dentz
1180ccf74f23SLuiz Augusto von Dentz release_sock(sk);
1181ccf74f23SLuiz Augusto von Dentz
1182ccf74f23SLuiz Augusto von Dentz if (err < 0)
1183ccf74f23SLuiz Augusto von Dentz kfree_skb(skb);
1184ccf74f23SLuiz Augusto von Dentz return err;
1185ccf74f23SLuiz Augusto von Dentz }
1186ccf74f23SLuiz Augusto von Dentz
iso_conn_defer_accept(struct hci_conn * conn)1187ccf74f23SLuiz Augusto von Dentz static void iso_conn_defer_accept(struct hci_conn *conn)
1188ccf74f23SLuiz Augusto von Dentz {
1189ccf74f23SLuiz Augusto von Dentz struct hci_cp_le_accept_cis cp;
1190ccf74f23SLuiz Augusto von Dentz struct hci_dev *hdev = conn->hdev;
1191ccf74f23SLuiz Augusto von Dentz
1192ccf74f23SLuiz Augusto von Dentz BT_DBG("conn %p", conn);
1193ccf74f23SLuiz Augusto von Dentz
1194ccf74f23SLuiz Augusto von Dentz conn->state = BT_CONFIG;
1195ccf74f23SLuiz Augusto von Dentz
1196ccf74f23SLuiz Augusto von Dentz cp.handle = cpu_to_le16(conn->handle);
1197ccf74f23SLuiz Augusto von Dentz
1198ccf74f23SLuiz Augusto von Dentz hci_send_cmd(hdev, HCI_OP_LE_ACCEPT_CIS, sizeof(cp), &cp);
1199ccf74f23SLuiz Augusto von Dentz }
1200ccf74f23SLuiz Augusto von Dentz
iso_conn_big_sync(struct sock * sk)1201fbdc4bc4SIulia Tanasescu static void iso_conn_big_sync(struct sock *sk)
1202fbdc4bc4SIulia Tanasescu {
1203fbdc4bc4SIulia Tanasescu int err;
1204fbdc4bc4SIulia Tanasescu struct hci_dev *hdev;
1205fbdc4bc4SIulia Tanasescu
1206fbdc4bc4SIulia Tanasescu hdev = hci_get_route(&iso_pi(sk)->dst, &iso_pi(sk)->src,
1207fbdc4bc4SIulia Tanasescu iso_pi(sk)->src_type);
1208fbdc4bc4SIulia Tanasescu
1209fbdc4bc4SIulia Tanasescu if (!hdev)
1210fbdc4bc4SIulia Tanasescu return;
1211fbdc4bc4SIulia Tanasescu
1212fbdc4bc4SIulia Tanasescu if (!test_and_set_bit(BT_SK_BIG_SYNC, &iso_pi(sk)->flags)) {
1213fbdc4bc4SIulia Tanasescu err = hci_le_big_create_sync(hdev, iso_pi(sk)->conn->hcon,
1214fbdc4bc4SIulia Tanasescu &iso_pi(sk)->qos,
1215fbdc4bc4SIulia Tanasescu iso_pi(sk)->sync_handle,
1216fbdc4bc4SIulia Tanasescu iso_pi(sk)->bc_num_bis,
1217fbdc4bc4SIulia Tanasescu iso_pi(sk)->bc_bis);
1218fbdc4bc4SIulia Tanasescu if (err)
1219fbdc4bc4SIulia Tanasescu bt_dev_err(hdev, "hci_le_big_create_sync: %d",
1220fbdc4bc4SIulia Tanasescu err);
1221fbdc4bc4SIulia Tanasescu }
1222fbdc4bc4SIulia Tanasescu }
1223fbdc4bc4SIulia Tanasescu
iso_sock_recvmsg(struct socket * sock,struct msghdr * msg,size_t len,int flags)1224ccf74f23SLuiz Augusto von Dentz static int iso_sock_recvmsg(struct socket *sock, struct msghdr *msg,
1225ccf74f23SLuiz Augusto von Dentz size_t len, int flags)
1226ccf74f23SLuiz Augusto von Dentz {
1227ccf74f23SLuiz Augusto von Dentz struct sock *sk = sock->sk;
1228ccf74f23SLuiz Augusto von Dentz struct iso_pinfo *pi = iso_pi(sk);
1229ccf74f23SLuiz Augusto von Dentz
1230ccf74f23SLuiz Augusto von Dentz BT_DBG("sk %p", sk);
1231ccf74f23SLuiz Augusto von Dentz
1232ccf74f23SLuiz Augusto von Dentz if (test_and_clear_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) {
1233d40ae85eSPauli Virtanen lock_sock(sk);
1234ccf74f23SLuiz Augusto von Dentz switch (sk->sk_state) {
1235ccf74f23SLuiz Augusto von Dentz case BT_CONNECT2:
1236*04566971SIulia Tanasescu if (test_bit(BT_SK_PA_SYNC, &pi->flags)) {
1237fbdc4bc4SIulia Tanasescu iso_conn_big_sync(sk);
1238fbdc4bc4SIulia Tanasescu sk->sk_state = BT_LISTEN;
1239fbdc4bc4SIulia Tanasescu } else {
1240ccf74f23SLuiz Augusto von Dentz iso_conn_defer_accept(pi->conn->hcon);
1241ccf74f23SLuiz Augusto von Dentz sk->sk_state = BT_CONFIG;
1242fbdc4bc4SIulia Tanasescu }
1243ccf74f23SLuiz Augusto von Dentz release_sock(sk);
1244ccf74f23SLuiz Augusto von Dentz return 0;
1245ccf74f23SLuiz Augusto von Dentz case BT_CONNECT:
1246d40ae85eSPauli Virtanen release_sock(sk);
1247241f5193SLuiz Augusto von Dentz return iso_connect_cis(sk);
1248d40ae85eSPauli Virtanen default:
1249d40ae85eSPauli Virtanen release_sock(sk);
1250d40ae85eSPauli Virtanen break;
1251ccf74f23SLuiz Augusto von Dentz }
1252ccf74f23SLuiz Augusto von Dentz }
1253ccf74f23SLuiz Augusto von Dentz
1254ccf74f23SLuiz Augusto von Dentz return bt_sock_recvmsg(sock, msg, len, flags);
1255ccf74f23SLuiz Augusto von Dentz }
1256ccf74f23SLuiz Augusto von Dentz
check_io_qos(struct bt_iso_io_qos * qos)1257ccf74f23SLuiz Augusto von Dentz static bool check_io_qos(struct bt_iso_io_qos *qos)
1258ccf74f23SLuiz Augusto von Dentz {
1259ccf74f23SLuiz Augusto von Dentz /* If no PHY is enable SDU must be 0 */
1260ccf74f23SLuiz Augusto von Dentz if (!qos->phy && qos->sdu)
1261ccf74f23SLuiz Augusto von Dentz return false;
1262ccf74f23SLuiz Augusto von Dentz
1263ccf74f23SLuiz Augusto von Dentz if (qos->interval && (qos->interval < 0xff || qos->interval > 0xfffff))
1264ccf74f23SLuiz Augusto von Dentz return false;
1265ccf74f23SLuiz Augusto von Dentz
1266ccf74f23SLuiz Augusto von Dentz if (qos->latency && (qos->latency < 0x05 || qos->latency > 0xfa0))
1267ccf74f23SLuiz Augusto von Dentz return false;
1268ccf74f23SLuiz Augusto von Dentz
1269ccf74f23SLuiz Augusto von Dentz if (qos->phy > BT_ISO_PHY_ANY)
1270ccf74f23SLuiz Augusto von Dentz return false;
1271ccf74f23SLuiz Augusto von Dentz
1272ccf74f23SLuiz Augusto von Dentz return true;
1273ccf74f23SLuiz Augusto von Dentz }
1274ccf74f23SLuiz Augusto von Dentz
check_ucast_qos(struct bt_iso_qos * qos)12750fe8c8d0SIulia Tanasescu static bool check_ucast_qos(struct bt_iso_qos *qos)
1276ccf74f23SLuiz Augusto von Dentz {
1277b7f923b1SLuiz Augusto von Dentz if (qos->ucast.cig > 0xef && qos->ucast.cig != BT_ISO_QOS_CIG_UNSET)
1278b7f923b1SLuiz Augusto von Dentz return false;
1279b7f923b1SLuiz Augusto von Dentz
1280b7f923b1SLuiz Augusto von Dentz if (qos->ucast.cis > 0xef && qos->ucast.cis != BT_ISO_QOS_CIS_UNSET)
1281b7f923b1SLuiz Augusto von Dentz return false;
1282b7f923b1SLuiz Augusto von Dentz
12830fe8c8d0SIulia Tanasescu if (qos->ucast.sca > 0x07)
1284ccf74f23SLuiz Augusto von Dentz return false;
1285ccf74f23SLuiz Augusto von Dentz
12860fe8c8d0SIulia Tanasescu if (qos->ucast.packing > 0x01)
1287ccf74f23SLuiz Augusto von Dentz return false;
1288ccf74f23SLuiz Augusto von Dentz
12890fe8c8d0SIulia Tanasescu if (qos->ucast.framing > 0x01)
1290ccf74f23SLuiz Augusto von Dentz return false;
1291ccf74f23SLuiz Augusto von Dentz
12920fe8c8d0SIulia Tanasescu if (!check_io_qos(&qos->ucast.in))
1293ccf74f23SLuiz Augusto von Dentz return false;
1294ccf74f23SLuiz Augusto von Dentz
12950fe8c8d0SIulia Tanasescu if (!check_io_qos(&qos->ucast.out))
12960fe8c8d0SIulia Tanasescu return false;
12970fe8c8d0SIulia Tanasescu
12980fe8c8d0SIulia Tanasescu return true;
12990fe8c8d0SIulia Tanasescu }
13000fe8c8d0SIulia Tanasescu
check_bcast_qos(struct bt_iso_qos * qos)13010fe8c8d0SIulia Tanasescu static bool check_bcast_qos(struct bt_iso_qos *qos)
13020fe8c8d0SIulia Tanasescu {
1303a39cc8d0SLuiz Augusto von Dentz if (!qos->bcast.sync_factor)
1304a39cc8d0SLuiz Augusto von Dentz qos->bcast.sync_factor = 0x01;
13050fe8c8d0SIulia Tanasescu
13060fe8c8d0SIulia Tanasescu if (qos->bcast.packing > 0x01)
13070fe8c8d0SIulia Tanasescu return false;
13080fe8c8d0SIulia Tanasescu
13090fe8c8d0SIulia Tanasescu if (qos->bcast.framing > 0x01)
13100fe8c8d0SIulia Tanasescu return false;
13110fe8c8d0SIulia Tanasescu
13120fe8c8d0SIulia Tanasescu if (!check_io_qos(&qos->bcast.in))
13130fe8c8d0SIulia Tanasescu return false;
13140fe8c8d0SIulia Tanasescu
13150fe8c8d0SIulia Tanasescu if (!check_io_qos(&qos->bcast.out))
13160fe8c8d0SIulia Tanasescu return false;
13170fe8c8d0SIulia Tanasescu
13180fe8c8d0SIulia Tanasescu if (qos->bcast.encryption > 0x01)
13190fe8c8d0SIulia Tanasescu return false;
13200fe8c8d0SIulia Tanasescu
13210fe8c8d0SIulia Tanasescu if (qos->bcast.options > 0x07)
13220fe8c8d0SIulia Tanasescu return false;
13230fe8c8d0SIulia Tanasescu
13240fe8c8d0SIulia Tanasescu if (qos->bcast.skip > 0x01f3)
13250fe8c8d0SIulia Tanasescu return false;
13260fe8c8d0SIulia Tanasescu
1327a39cc8d0SLuiz Augusto von Dentz if (!qos->bcast.sync_timeout)
1328a39cc8d0SLuiz Augusto von Dentz qos->bcast.sync_timeout = BT_ISO_SYNC_TIMEOUT;
1329a39cc8d0SLuiz Augusto von Dentz
13300fe8c8d0SIulia Tanasescu if (qos->bcast.sync_timeout < 0x000a || qos->bcast.sync_timeout > 0x4000)
13310fe8c8d0SIulia Tanasescu return false;
13320fe8c8d0SIulia Tanasescu
13330fe8c8d0SIulia Tanasescu if (qos->bcast.sync_cte_type > 0x1f)
13340fe8c8d0SIulia Tanasescu return false;
13350fe8c8d0SIulia Tanasescu
13360fe8c8d0SIulia Tanasescu if (qos->bcast.mse > 0x1f)
13370fe8c8d0SIulia Tanasescu return false;
13380fe8c8d0SIulia Tanasescu
1339a39cc8d0SLuiz Augusto von Dentz if (!qos->bcast.timeout)
1340a39cc8d0SLuiz Augusto von Dentz qos->bcast.sync_timeout = BT_ISO_SYNC_TIMEOUT;
1341a39cc8d0SLuiz Augusto von Dentz
13420fe8c8d0SIulia Tanasescu if (qos->bcast.timeout < 0x000a || qos->bcast.timeout > 0x4000)
1343ccf74f23SLuiz Augusto von Dentz return false;
1344ccf74f23SLuiz Augusto von Dentz
1345ccf74f23SLuiz Augusto von Dentz return true;
1346ccf74f23SLuiz Augusto von Dentz }
1347ccf74f23SLuiz Augusto von Dentz
iso_sock_setsockopt(struct socket * sock,int level,int optname,sockptr_t optval,unsigned int optlen)1348ccf74f23SLuiz Augusto von Dentz static int iso_sock_setsockopt(struct socket *sock, int level, int optname,
1349ccf74f23SLuiz Augusto von Dentz sockptr_t optval, unsigned int optlen)
1350ccf74f23SLuiz Augusto von Dentz {
1351ccf74f23SLuiz Augusto von Dentz struct sock *sk = sock->sk;
1352ccf74f23SLuiz Augusto von Dentz int len, err = 0;
13530fe8c8d0SIulia Tanasescu struct bt_iso_qos qos = default_qos;
1354ccf74f23SLuiz Augusto von Dentz u32 opt;
1355ccf74f23SLuiz Augusto von Dentz
1356ccf74f23SLuiz Augusto von Dentz BT_DBG("sk %p", sk);
1357ccf74f23SLuiz Augusto von Dentz
1358ccf74f23SLuiz Augusto von Dentz lock_sock(sk);
1359ccf74f23SLuiz Augusto von Dentz
1360ccf74f23SLuiz Augusto von Dentz switch (optname) {
1361ccf74f23SLuiz Augusto von Dentz case BT_DEFER_SETUP:
1362ccf74f23SLuiz Augusto von Dentz if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
1363ccf74f23SLuiz Augusto von Dentz err = -EINVAL;
1364ccf74f23SLuiz Augusto von Dentz break;
1365ccf74f23SLuiz Augusto von Dentz }
1366ccf74f23SLuiz Augusto von Dentz
1367ccf74f23SLuiz Augusto von Dentz if (copy_from_sockptr(&opt, optval, sizeof(u32))) {
1368ccf74f23SLuiz Augusto von Dentz err = -EFAULT;
1369ccf74f23SLuiz Augusto von Dentz break;
1370ccf74f23SLuiz Augusto von Dentz }
1371ccf74f23SLuiz Augusto von Dentz
1372ccf74f23SLuiz Augusto von Dentz if (opt)
1373ccf74f23SLuiz Augusto von Dentz set_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags);
1374ccf74f23SLuiz Augusto von Dentz else
1375ccf74f23SLuiz Augusto von Dentz clear_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags);
1376ccf74f23SLuiz Augusto von Dentz break;
1377ccf74f23SLuiz Augusto von Dentz
13780731c5abSLuiz Augusto von Dentz case BT_PKT_STATUS:
13790731c5abSLuiz Augusto von Dentz if (copy_from_sockptr(&opt, optval, sizeof(u32))) {
13800731c5abSLuiz Augusto von Dentz err = -EFAULT;
13810731c5abSLuiz Augusto von Dentz break;
13820731c5abSLuiz Augusto von Dentz }
13830731c5abSLuiz Augusto von Dentz
13840731c5abSLuiz Augusto von Dentz if (opt)
13850731c5abSLuiz Augusto von Dentz set_bit(BT_SK_PKT_STATUS, &bt_sk(sk)->flags);
13860731c5abSLuiz Augusto von Dentz else
13870731c5abSLuiz Augusto von Dentz clear_bit(BT_SK_PKT_STATUS, &bt_sk(sk)->flags);
13880731c5abSLuiz Augusto von Dentz break;
13890731c5abSLuiz Augusto von Dentz
1390ccf74f23SLuiz Augusto von Dentz case BT_ISO_QOS:
1391ccf74f23SLuiz Augusto von Dentz if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND &&
1392ccf74f23SLuiz Augusto von Dentz sk->sk_state != BT_CONNECT2) {
1393ccf74f23SLuiz Augusto von Dentz err = -EINVAL;
1394ccf74f23SLuiz Augusto von Dentz break;
1395ccf74f23SLuiz Augusto von Dentz }
1396ccf74f23SLuiz Augusto von Dentz
1397ccf74f23SLuiz Augusto von Dentz len = min_t(unsigned int, sizeof(qos), optlen);
1398ccf74f23SLuiz Augusto von Dentz
1399ccf74f23SLuiz Augusto von Dentz if (copy_from_sockptr(&qos, optval, len)) {
1400ccf74f23SLuiz Augusto von Dentz err = -EFAULT;
1401ccf74f23SLuiz Augusto von Dentz break;
1402ccf74f23SLuiz Augusto von Dentz }
1403ccf74f23SLuiz Augusto von Dentz
14040fe8c8d0SIulia Tanasescu if (len == sizeof(qos.ucast) && !check_ucast_qos(&qos)) {
1405ccf74f23SLuiz Augusto von Dentz err = -EINVAL;
1406ccf74f23SLuiz Augusto von Dentz break;
1407ccf74f23SLuiz Augusto von Dentz }
1408ccf74f23SLuiz Augusto von Dentz
1409ccf74f23SLuiz Augusto von Dentz iso_pi(sk)->qos = qos;
14100fe8c8d0SIulia Tanasescu iso_pi(sk)->qos_user_set = true;
1411ccf74f23SLuiz Augusto von Dentz
1412ccf74f23SLuiz Augusto von Dentz break;
1413ccf74f23SLuiz Augusto von Dentz
1414f764a6c2SLuiz Augusto von Dentz case BT_ISO_BASE:
1415f764a6c2SLuiz Augusto von Dentz if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND &&
1416f764a6c2SLuiz Augusto von Dentz sk->sk_state != BT_CONNECT2) {
1417f764a6c2SLuiz Augusto von Dentz err = -EINVAL;
1418f764a6c2SLuiz Augusto von Dentz break;
1419f764a6c2SLuiz Augusto von Dentz }
1420f764a6c2SLuiz Augusto von Dentz
1421f764a6c2SLuiz Augusto von Dentz if (optlen > sizeof(iso_pi(sk)->base)) {
1422f764a6c2SLuiz Augusto von Dentz err = -EOVERFLOW;
1423f764a6c2SLuiz Augusto von Dentz break;
1424f764a6c2SLuiz Augusto von Dentz }
1425f764a6c2SLuiz Augusto von Dentz
1426f764a6c2SLuiz Augusto von Dentz len = min_t(unsigned int, sizeof(iso_pi(sk)->base), optlen);
1427f764a6c2SLuiz Augusto von Dentz
1428f764a6c2SLuiz Augusto von Dentz if (copy_from_sockptr(iso_pi(sk)->base, optval, len)) {
1429f764a6c2SLuiz Augusto von Dentz err = -EFAULT;
1430f764a6c2SLuiz Augusto von Dentz break;
1431f764a6c2SLuiz Augusto von Dentz }
1432f764a6c2SLuiz Augusto von Dentz
1433f764a6c2SLuiz Augusto von Dentz iso_pi(sk)->base_len = len;
1434f764a6c2SLuiz Augusto von Dentz
1435f764a6c2SLuiz Augusto von Dentz break;
1436f764a6c2SLuiz Augusto von Dentz
1437ccf74f23SLuiz Augusto von Dentz default:
1438ccf74f23SLuiz Augusto von Dentz err = -ENOPROTOOPT;
1439ccf74f23SLuiz Augusto von Dentz break;
1440ccf74f23SLuiz Augusto von Dentz }
1441ccf74f23SLuiz Augusto von Dentz
1442ccf74f23SLuiz Augusto von Dentz release_sock(sk);
1443ccf74f23SLuiz Augusto von Dentz return err;
1444ccf74f23SLuiz Augusto von Dentz }
1445ccf74f23SLuiz Augusto von Dentz
iso_sock_getsockopt(struct socket * sock,int level,int optname,char __user * optval,int __user * optlen)1446ccf74f23SLuiz Augusto von Dentz static int iso_sock_getsockopt(struct socket *sock, int level, int optname,
1447ccf74f23SLuiz Augusto von Dentz char __user *optval, int __user *optlen)
1448ccf74f23SLuiz Augusto von Dentz {
1449ccf74f23SLuiz Augusto von Dentz struct sock *sk = sock->sk;
1450ccf74f23SLuiz Augusto von Dentz int len, err = 0;
14510eee4995SLuiz Augusto von Dentz struct bt_iso_qos *qos;
1452f764a6c2SLuiz Augusto von Dentz u8 base_len;
1453f764a6c2SLuiz Augusto von Dentz u8 *base;
1454ccf74f23SLuiz Augusto von Dentz
1455ccf74f23SLuiz Augusto von Dentz BT_DBG("sk %p", sk);
1456ccf74f23SLuiz Augusto von Dentz
1457ccf74f23SLuiz Augusto von Dentz if (get_user(len, optlen))
1458ccf74f23SLuiz Augusto von Dentz return -EFAULT;
1459ccf74f23SLuiz Augusto von Dentz
1460ccf74f23SLuiz Augusto von Dentz lock_sock(sk);
1461ccf74f23SLuiz Augusto von Dentz
1462ccf74f23SLuiz Augusto von Dentz switch (optname) {
1463ccf74f23SLuiz Augusto von Dentz case BT_DEFER_SETUP:
14649dfe1727SLuiz Augusto von Dentz if (sk->sk_state == BT_CONNECTED) {
1465ccf74f23SLuiz Augusto von Dentz err = -EINVAL;
1466ccf74f23SLuiz Augusto von Dentz break;
1467ccf74f23SLuiz Augusto von Dentz }
1468ccf74f23SLuiz Augusto von Dentz
1469ccf74f23SLuiz Augusto von Dentz if (put_user(test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags),
1470ccf74f23SLuiz Augusto von Dentz (u32 __user *)optval))
1471ccf74f23SLuiz Augusto von Dentz err = -EFAULT;
1472ccf74f23SLuiz Augusto von Dentz
1473ccf74f23SLuiz Augusto von Dentz break;
1474ccf74f23SLuiz Augusto von Dentz
14750731c5abSLuiz Augusto von Dentz case BT_PKT_STATUS:
14760731c5abSLuiz Augusto von Dentz if (put_user(test_bit(BT_SK_PKT_STATUS, &bt_sk(sk)->flags),
14770731c5abSLuiz Augusto von Dentz (int __user *)optval))
14780731c5abSLuiz Augusto von Dentz err = -EFAULT;
14790731c5abSLuiz Augusto von Dentz break;
14800731c5abSLuiz Augusto von Dentz
1481ccf74f23SLuiz Augusto von Dentz case BT_ISO_QOS:
14821d1ab5d3SLuiz Augusto von Dentz qos = iso_sock_get_qos(sk);
1483ccf74f23SLuiz Augusto von Dentz
14840eee4995SLuiz Augusto von Dentz len = min_t(unsigned int, len, sizeof(*qos));
14850eee4995SLuiz Augusto von Dentz if (copy_to_user(optval, qos, len))
1486ccf74f23SLuiz Augusto von Dentz err = -EFAULT;
1487ccf74f23SLuiz Augusto von Dentz
1488ccf74f23SLuiz Augusto von Dentz break;
1489ccf74f23SLuiz Augusto von Dentz
1490f764a6c2SLuiz Augusto von Dentz case BT_ISO_BASE:
14919c082631SClaudia Draghicescu if (sk->sk_state == BT_CONNECTED &&
14929c082631SClaudia Draghicescu !bacmp(&iso_pi(sk)->dst, BDADDR_ANY)) {
1493f764a6c2SLuiz Augusto von Dentz base_len = iso_pi(sk)->conn->hcon->le_per_adv_data_len;
1494f764a6c2SLuiz Augusto von Dentz base = iso_pi(sk)->conn->hcon->le_per_adv_data;
1495f764a6c2SLuiz Augusto von Dentz } else {
1496f764a6c2SLuiz Augusto von Dentz base_len = iso_pi(sk)->base_len;
1497f764a6c2SLuiz Augusto von Dentz base = iso_pi(sk)->base;
1498f764a6c2SLuiz Augusto von Dentz }
1499f764a6c2SLuiz Augusto von Dentz
1500f764a6c2SLuiz Augusto von Dentz len = min_t(unsigned int, len, base_len);
1501f764a6c2SLuiz Augusto von Dentz if (copy_to_user(optval, base, len))
1502f764a6c2SLuiz Augusto von Dentz err = -EFAULT;
1503f764a6c2SLuiz Augusto von Dentz
1504f764a6c2SLuiz Augusto von Dentz break;
1505f764a6c2SLuiz Augusto von Dentz
1506ccf74f23SLuiz Augusto von Dentz default:
1507ccf74f23SLuiz Augusto von Dentz err = -ENOPROTOOPT;
1508ccf74f23SLuiz Augusto von Dentz break;
1509ccf74f23SLuiz Augusto von Dentz }
1510ccf74f23SLuiz Augusto von Dentz
1511ccf74f23SLuiz Augusto von Dentz release_sock(sk);
1512ccf74f23SLuiz Augusto von Dentz return err;
1513ccf74f23SLuiz Augusto von Dentz }
1514ccf74f23SLuiz Augusto von Dentz
iso_sock_shutdown(struct socket * sock,int how)1515ccf74f23SLuiz Augusto von Dentz static int iso_sock_shutdown(struct socket *sock, int how)
1516ccf74f23SLuiz Augusto von Dentz {
1517ccf74f23SLuiz Augusto von Dentz struct sock *sk = sock->sk;
1518ccf74f23SLuiz Augusto von Dentz int err = 0;
1519ccf74f23SLuiz Augusto von Dentz
1520c5729093SLuiz Augusto von Dentz BT_DBG("sock %p, sk %p, how %d", sock, sk, how);
1521ccf74f23SLuiz Augusto von Dentz
1522ccf74f23SLuiz Augusto von Dentz if (!sk)
1523ccf74f23SLuiz Augusto von Dentz return 0;
1524ccf74f23SLuiz Augusto von Dentz
1525ccf74f23SLuiz Augusto von Dentz sock_hold(sk);
1526ccf74f23SLuiz Augusto von Dentz lock_sock(sk);
1527ccf74f23SLuiz Augusto von Dentz
1528c5729093SLuiz Augusto von Dentz switch (how) {
1529c5729093SLuiz Augusto von Dentz case SHUT_RD:
1530c5729093SLuiz Augusto von Dentz if (sk->sk_shutdown & RCV_SHUTDOWN)
1531c5729093SLuiz Augusto von Dentz goto unlock;
1532c5729093SLuiz Augusto von Dentz sk->sk_shutdown |= RCV_SHUTDOWN;
1533c5729093SLuiz Augusto von Dentz break;
1534c5729093SLuiz Augusto von Dentz case SHUT_WR:
1535c5729093SLuiz Augusto von Dentz if (sk->sk_shutdown & SEND_SHUTDOWN)
1536c5729093SLuiz Augusto von Dentz goto unlock;
1537c5729093SLuiz Augusto von Dentz sk->sk_shutdown |= SEND_SHUTDOWN;
1538c5729093SLuiz Augusto von Dentz break;
1539c5729093SLuiz Augusto von Dentz case SHUT_RDWR:
1540c5729093SLuiz Augusto von Dentz if (sk->sk_shutdown & SHUTDOWN_MASK)
1541c5729093SLuiz Augusto von Dentz goto unlock;
1542c5729093SLuiz Augusto von Dentz sk->sk_shutdown |= SHUTDOWN_MASK;
1543c5729093SLuiz Augusto von Dentz break;
1544c5729093SLuiz Augusto von Dentz }
1545c5729093SLuiz Augusto von Dentz
1546ccf74f23SLuiz Augusto von Dentz iso_sock_clear_timer(sk);
1547ccf74f23SLuiz Augusto von Dentz __iso_sock_close(sk);
1548ccf74f23SLuiz Augusto von Dentz
1549ccf74f23SLuiz Augusto von Dentz if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime &&
1550ccf74f23SLuiz Augusto von Dentz !(current->flags & PF_EXITING))
1551c5729093SLuiz Augusto von Dentz err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime);
1552ccf74f23SLuiz Augusto von Dentz
1553c5729093SLuiz Augusto von Dentz unlock:
1554ccf74f23SLuiz Augusto von Dentz release_sock(sk);
1555ccf74f23SLuiz Augusto von Dentz sock_put(sk);
1556ccf74f23SLuiz Augusto von Dentz
1557ccf74f23SLuiz Augusto von Dentz return err;
1558ccf74f23SLuiz Augusto von Dentz }
1559ccf74f23SLuiz Augusto von Dentz
iso_sock_release(struct socket * sock)1560ccf74f23SLuiz Augusto von Dentz static int iso_sock_release(struct socket *sock)
1561ccf74f23SLuiz Augusto von Dentz {
1562ccf74f23SLuiz Augusto von Dentz struct sock *sk = sock->sk;
1563ccf74f23SLuiz Augusto von Dentz int err = 0;
1564ccf74f23SLuiz Augusto von Dentz
1565ccf74f23SLuiz Augusto von Dentz BT_DBG("sock %p, sk %p", sock, sk);
1566ccf74f23SLuiz Augusto von Dentz
1567ccf74f23SLuiz Augusto von Dentz if (!sk)
1568ccf74f23SLuiz Augusto von Dentz return 0;
1569ccf74f23SLuiz Augusto von Dentz
1570ccf74f23SLuiz Augusto von Dentz iso_sock_close(sk);
1571ccf74f23SLuiz Augusto von Dentz
1572bc1fb82aSEric Dumazet if (sock_flag(sk, SOCK_LINGER) && READ_ONCE(sk->sk_lingertime) &&
1573ccf74f23SLuiz Augusto von Dentz !(current->flags & PF_EXITING)) {
1574ccf74f23SLuiz Augusto von Dentz lock_sock(sk);
1575ccf74f23SLuiz Augusto von Dentz err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime);
1576ccf74f23SLuiz Augusto von Dentz release_sock(sk);
1577ccf74f23SLuiz Augusto von Dentz }
1578ccf74f23SLuiz Augusto von Dentz
1579ccf74f23SLuiz Augusto von Dentz sock_orphan(sk);
1580ccf74f23SLuiz Augusto von Dentz iso_sock_kill(sk);
1581ccf74f23SLuiz Augusto von Dentz return err;
1582ccf74f23SLuiz Augusto von Dentz }
1583ccf74f23SLuiz Augusto von Dentz
iso_sock_ready(struct sock * sk)1584ccf74f23SLuiz Augusto von Dentz static void iso_sock_ready(struct sock *sk)
1585ccf74f23SLuiz Augusto von Dentz {
1586ccf74f23SLuiz Augusto von Dentz BT_DBG("sk %p", sk);
1587ccf74f23SLuiz Augusto von Dentz
1588ccf74f23SLuiz Augusto von Dentz if (!sk)
1589ccf74f23SLuiz Augusto von Dentz return;
1590ccf74f23SLuiz Augusto von Dentz
1591ccf74f23SLuiz Augusto von Dentz lock_sock(sk);
1592ccf74f23SLuiz Augusto von Dentz iso_sock_clear_timer(sk);
1593ccf74f23SLuiz Augusto von Dentz sk->sk_state = BT_CONNECTED;
1594ccf74f23SLuiz Augusto von Dentz sk->sk_state_change(sk);
1595ccf74f23SLuiz Augusto von Dentz release_sock(sk);
1596ccf74f23SLuiz Augusto von Dentz }
1597ccf74f23SLuiz Augusto von Dentz
1598ccf74f23SLuiz Augusto von Dentz struct iso_list_data {
1599ccf74f23SLuiz Augusto von Dentz struct hci_conn *hcon;
1600ccf74f23SLuiz Augusto von Dentz int count;
1601ccf74f23SLuiz Augusto von Dentz };
1602ccf74f23SLuiz Augusto von Dentz
iso_match_big(struct sock * sk,void * data)1603f764a6c2SLuiz Augusto von Dentz static bool iso_match_big(struct sock *sk, void *data)
1604f764a6c2SLuiz Augusto von Dentz {
1605f764a6c2SLuiz Augusto von Dentz struct hci_evt_le_big_sync_estabilished *ev = data;
1606f764a6c2SLuiz Augusto von Dentz
16070fe8c8d0SIulia Tanasescu return ev->handle == iso_pi(sk)->qos.bcast.big;
1608f764a6c2SLuiz Augusto von Dentz }
1609f764a6c2SLuiz Augusto von Dentz
iso_match_pa_sync_flag(struct sock * sk,void * data)1610fbdc4bc4SIulia Tanasescu static bool iso_match_pa_sync_flag(struct sock *sk, void *data)
1611fbdc4bc4SIulia Tanasescu {
1612fbdc4bc4SIulia Tanasescu return test_bit(BT_SK_PA_SYNC, &iso_pi(sk)->flags);
1613fbdc4bc4SIulia Tanasescu }
1614fbdc4bc4SIulia Tanasescu
iso_conn_ready(struct iso_conn * conn)1615ccf74f23SLuiz Augusto von Dentz static void iso_conn_ready(struct iso_conn *conn)
1616ccf74f23SLuiz Augusto von Dentz {
1617fbdc4bc4SIulia Tanasescu struct sock *parent = NULL;
1618ccf74f23SLuiz Augusto von Dentz struct sock *sk = conn->sk;
1619fbdc4bc4SIulia Tanasescu struct hci_ev_le_big_sync_estabilished *ev = NULL;
1620fbdc4bc4SIulia Tanasescu struct hci_ev_le_pa_sync_established *ev2 = NULL;
162123417475SIulia Tanasescu struct hci_evt_le_big_info_adv_report *ev3 = NULL;
16226a5ad251SLuiz Augusto von Dentz struct hci_conn *hcon;
1623ccf74f23SLuiz Augusto von Dentz
1624ccf74f23SLuiz Augusto von Dentz BT_DBG("conn %p", conn);
1625ccf74f23SLuiz Augusto von Dentz
1626ccf74f23SLuiz Augusto von Dentz if (sk) {
1627ccf74f23SLuiz Augusto von Dentz iso_sock_ready(conn->sk);
1628ccf74f23SLuiz Augusto von Dentz } else {
16296a5ad251SLuiz Augusto von Dentz hcon = conn->hcon;
16306a5ad251SLuiz Augusto von Dentz if (!hcon)
1631ccf74f23SLuiz Augusto von Dentz return;
1632ccf74f23SLuiz Augusto von Dentz
1633fbdc4bc4SIulia Tanasescu if (test_bit(HCI_CONN_BIG_SYNC, &hcon->flags) ||
1634fbdc4bc4SIulia Tanasescu test_bit(HCI_CONN_BIG_SYNC_FAILED, &hcon->flags)) {
16356a5ad251SLuiz Augusto von Dentz ev = hci_recv_event_data(hcon->hdev,
1636f764a6c2SLuiz Augusto von Dentz HCI_EVT_LE_BIG_SYNC_ESTABILISHED);
1637fbdc4bc4SIulia Tanasescu
1638fbdc4bc4SIulia Tanasescu /* Get reference to PA sync parent socket, if it exists */
1639fbdc4bc4SIulia Tanasescu parent = iso_get_sock_listen(&hcon->src,
1640fbdc4bc4SIulia Tanasescu &hcon->dst,
1641fbdc4bc4SIulia Tanasescu iso_match_pa_sync_flag, NULL);
1642fbdc4bc4SIulia Tanasescu if (!parent && ev)
16436a5ad251SLuiz Augusto von Dentz parent = iso_get_sock_listen(&hcon->src,
16446a5ad251SLuiz Augusto von Dentz &hcon->dst,
1645f764a6c2SLuiz Augusto von Dentz iso_match_big, ev);
164623417475SIulia Tanasescu } else if (test_bit(HCI_CONN_PA_SYNC_FAILED, &hcon->flags)) {
1647fbdc4bc4SIulia Tanasescu ev2 = hci_recv_event_data(hcon->hdev,
1648fbdc4bc4SIulia Tanasescu HCI_EV_LE_PA_SYNC_ESTABLISHED);
1649fbdc4bc4SIulia Tanasescu if (ev2)
1650fbdc4bc4SIulia Tanasescu parent = iso_get_sock_listen(&hcon->src,
1651fbdc4bc4SIulia Tanasescu &hcon->dst,
1652fbdc4bc4SIulia Tanasescu iso_match_sid, ev2);
165323417475SIulia Tanasescu } else if (test_bit(HCI_CONN_PA_SYNC, &hcon->flags)) {
165423417475SIulia Tanasescu ev3 = hci_recv_event_data(hcon->hdev,
165523417475SIulia Tanasescu HCI_EVT_LE_BIG_INFO_ADV_REPORT);
165623417475SIulia Tanasescu if (ev3)
165723417475SIulia Tanasescu parent = iso_get_sock_listen(&hcon->src,
165823417475SIulia Tanasescu &hcon->dst,
165923417475SIulia Tanasescu iso_match_sync_handle, ev3);
1660fbdc4bc4SIulia Tanasescu }
1661fbdc4bc4SIulia Tanasescu
1662fbdc4bc4SIulia Tanasescu if (!parent)
16636a5ad251SLuiz Augusto von Dentz parent = iso_get_sock_listen(&hcon->src,
1664f764a6c2SLuiz Augusto von Dentz BDADDR_ANY, NULL, NULL);
1665f764a6c2SLuiz Augusto von Dentz
16666a5ad251SLuiz Augusto von Dentz if (!parent)
1667ccf74f23SLuiz Augusto von Dentz return;
1668ccf74f23SLuiz Augusto von Dentz
1669ccf74f23SLuiz Augusto von Dentz lock_sock(parent);
1670ccf74f23SLuiz Augusto von Dentz
1671ccf74f23SLuiz Augusto von Dentz sk = iso_sock_alloc(sock_net(parent), NULL,
1672ccf74f23SLuiz Augusto von Dentz BTPROTO_ISO, GFP_ATOMIC, 0);
1673ccf74f23SLuiz Augusto von Dentz if (!sk) {
1674ccf74f23SLuiz Augusto von Dentz release_sock(parent);
1675ccf74f23SLuiz Augusto von Dentz return;
1676ccf74f23SLuiz Augusto von Dentz }
1677ccf74f23SLuiz Augusto von Dentz
1678ccf74f23SLuiz Augusto von Dentz iso_sock_init(sk, parent);
1679ccf74f23SLuiz Augusto von Dentz
16806a5ad251SLuiz Augusto von Dentz bacpy(&iso_pi(sk)->src, &hcon->src);
1681fbdc4bc4SIulia Tanasescu
1682fbdc4bc4SIulia Tanasescu /* Convert from HCI to three-value type */
1683fbdc4bc4SIulia Tanasescu if (hcon->src_type == ADDR_LE_DEV_PUBLIC)
1684fbdc4bc4SIulia Tanasescu iso_pi(sk)->src_type = BDADDR_LE_PUBLIC;
1685fbdc4bc4SIulia Tanasescu else
1686fbdc4bc4SIulia Tanasescu iso_pi(sk)->src_type = BDADDR_LE_RANDOM;
1687f764a6c2SLuiz Augusto von Dentz
1688f764a6c2SLuiz Augusto von Dentz /* If hcon has no destination address (BDADDR_ANY) it means it
1689fbdc4bc4SIulia Tanasescu * was created by HCI_EV_LE_BIG_SYNC_ESTABILISHED or
1690fbdc4bc4SIulia Tanasescu * HCI_EV_LE_PA_SYNC_ESTABLISHED so we need to initialize using
1691fbdc4bc4SIulia Tanasescu * the parent socket destination address.
1692f764a6c2SLuiz Augusto von Dentz */
16936a5ad251SLuiz Augusto von Dentz if (!bacmp(&hcon->dst, BDADDR_ANY)) {
16946a5ad251SLuiz Augusto von Dentz bacpy(&hcon->dst, &iso_pi(parent)->dst);
16956a5ad251SLuiz Augusto von Dentz hcon->dst_type = iso_pi(parent)->dst_type;
16966a5ad251SLuiz Augusto von Dentz hcon->sync_handle = iso_pi(parent)->sync_handle;
1697f764a6c2SLuiz Augusto von Dentz }
1698f764a6c2SLuiz Augusto von Dentz
169923417475SIulia Tanasescu if (ev3) {
1700fbdc4bc4SIulia Tanasescu iso_pi(sk)->qos = iso_pi(parent)->qos;
170123417475SIulia Tanasescu iso_pi(sk)->qos.bcast.encryption = ev3->encryption;
170223417475SIulia Tanasescu hcon->iso_qos = iso_pi(sk)->qos;
1703fbdc4bc4SIulia Tanasescu iso_pi(sk)->bc_num_bis = iso_pi(parent)->bc_num_bis;
1704fbdc4bc4SIulia Tanasescu memcpy(iso_pi(sk)->bc_bis, iso_pi(parent)->bc_bis, ISO_MAX_NUM_BIS);
170523417475SIulia Tanasescu set_bit(BT_SK_PA_SYNC, &iso_pi(sk)->flags);
1706fbdc4bc4SIulia Tanasescu }
1707fbdc4bc4SIulia Tanasescu
17086a5ad251SLuiz Augusto von Dentz bacpy(&iso_pi(sk)->dst, &hcon->dst);
17096a5ad251SLuiz Augusto von Dentz iso_pi(sk)->dst_type = hcon->dst_type;
17109c082631SClaudia Draghicescu iso_pi(sk)->sync_handle = iso_pi(parent)->sync_handle;
17119c082631SClaudia Draghicescu memcpy(iso_pi(sk)->base, iso_pi(parent)->base, iso_pi(parent)->base_len);
17129c082631SClaudia Draghicescu iso_pi(sk)->base_len = iso_pi(parent)->base_len;
1713ccf74f23SLuiz Augusto von Dentz
17146a5ad251SLuiz Augusto von Dentz hci_conn_hold(hcon);
17156a5ad251SLuiz Augusto von Dentz iso_chan_add(conn, sk, parent);
1716ccf74f23SLuiz Augusto von Dentz
1717fbdc4bc4SIulia Tanasescu if ((ev && ((struct hci_evt_le_big_sync_estabilished *)ev)->status) ||
1718fbdc4bc4SIulia Tanasescu (ev2 && ev2->status)) {
1719f777d882SIulia Tanasescu /* Trigger error signal on child socket */
1720f777d882SIulia Tanasescu sk->sk_err = ECONNREFUSED;
1721f777d882SIulia Tanasescu sk->sk_error_report(sk);
1722f777d882SIulia Tanasescu }
1723f777d882SIulia Tanasescu
1724ccf74f23SLuiz Augusto von Dentz if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags))
1725ccf74f23SLuiz Augusto von Dentz sk->sk_state = BT_CONNECT2;
1726ccf74f23SLuiz Augusto von Dentz else
1727ccf74f23SLuiz Augusto von Dentz sk->sk_state = BT_CONNECTED;
1728ccf74f23SLuiz Augusto von Dentz
1729ccf74f23SLuiz Augusto von Dentz /* Wake up parent */
1730ccf74f23SLuiz Augusto von Dentz parent->sk_data_ready(parent);
1731ccf74f23SLuiz Augusto von Dentz
1732ccf74f23SLuiz Augusto von Dentz release_sock(parent);
1733ccf74f23SLuiz Augusto von Dentz }
1734ccf74f23SLuiz Augusto von Dentz }
1735ccf74f23SLuiz Augusto von Dentz
iso_match_sid(struct sock * sk,void * data)1736f764a6c2SLuiz Augusto von Dentz static bool iso_match_sid(struct sock *sk, void *data)
1737f764a6c2SLuiz Augusto von Dentz {
1738f764a6c2SLuiz Augusto von Dentz struct hci_ev_le_pa_sync_established *ev = data;
1739f764a6c2SLuiz Augusto von Dentz
1740f764a6c2SLuiz Augusto von Dentz return ev->sid == iso_pi(sk)->bc_sid;
1741f764a6c2SLuiz Augusto von Dentz }
1742f764a6c2SLuiz Augusto von Dentz
iso_match_sync_handle(struct sock * sk,void * data)1743f764a6c2SLuiz Augusto von Dentz static bool iso_match_sync_handle(struct sock *sk, void *data)
1744f764a6c2SLuiz Augusto von Dentz {
1745f764a6c2SLuiz Augusto von Dentz struct hci_evt_le_big_info_adv_report *ev = data;
1746f764a6c2SLuiz Augusto von Dentz
1747f764a6c2SLuiz Augusto von Dentz return le16_to_cpu(ev->sync_handle) == iso_pi(sk)->sync_handle;
1748f764a6c2SLuiz Augusto von Dentz }
1749f764a6c2SLuiz Augusto von Dentz
iso_match_sync_handle_pa_report(struct sock * sk,void * data)17509c082631SClaudia Draghicescu static bool iso_match_sync_handle_pa_report(struct sock *sk, void *data)
17519c082631SClaudia Draghicescu {
17529c082631SClaudia Draghicescu struct hci_ev_le_per_adv_report *ev = data;
17539c082631SClaudia Draghicescu
17549c082631SClaudia Draghicescu return le16_to_cpu(ev->sync_handle) == iso_pi(sk)->sync_handle;
17559c082631SClaudia Draghicescu }
17569c082631SClaudia Draghicescu
1757ccf74f23SLuiz Augusto von Dentz /* ----- ISO interface with lower layer (HCI) ----- */
1758f764a6c2SLuiz Augusto von Dentz
iso_connect_ind(struct hci_dev * hdev,bdaddr_t * bdaddr,__u8 * flags)1759ccf74f23SLuiz Augusto von Dentz int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)
1760ccf74f23SLuiz Augusto von Dentz {
1761f764a6c2SLuiz Augusto von Dentz struct hci_ev_le_pa_sync_established *ev1;
1762f764a6c2SLuiz Augusto von Dentz struct hci_evt_le_big_info_adv_report *ev2;
17639c082631SClaudia Draghicescu struct hci_ev_le_per_adv_report *ev3;
1764ccf74f23SLuiz Augusto von Dentz struct sock *sk;
1765ccf74f23SLuiz Augusto von Dentz int lm = 0;
1766ccf74f23SLuiz Augusto von Dentz
1767f764a6c2SLuiz Augusto von Dentz bt_dev_dbg(hdev, "bdaddr %pMR", bdaddr);
1768ccf74f23SLuiz Augusto von Dentz
1769f764a6c2SLuiz Augusto von Dentz /* Broadcast receiver requires handling of some events before it can
1770f764a6c2SLuiz Augusto von Dentz * proceed to establishing a BIG sync:
1771f764a6c2SLuiz Augusto von Dentz *
1772f764a6c2SLuiz Augusto von Dentz * 1. HCI_EV_LE_PA_SYNC_ESTABLISHED: The socket may specify a specific
1773f764a6c2SLuiz Augusto von Dentz * SID to listen to and once sync is estabilished its handle needs to
1774f764a6c2SLuiz Augusto von Dentz * be stored in iso_pi(sk)->sync_handle so it can be matched once
1775f764a6c2SLuiz Augusto von Dentz * receiving the BIG Info.
1776f764a6c2SLuiz Augusto von Dentz * 2. HCI_EVT_LE_BIG_INFO_ADV_REPORT: When connect_ind is triggered by a
1777f764a6c2SLuiz Augusto von Dentz * a BIG Info it attempts to check if there any listening socket with
1778f764a6c2SLuiz Augusto von Dentz * the same sync_handle and if it does then attempt to create a sync.
17799c082631SClaudia Draghicescu * 3. HCI_EV_LE_PER_ADV_REPORT: When a PA report is received, it is stored
17809c082631SClaudia Draghicescu * in iso_pi(sk)->base so it can be passed up to user, in the case of a
17819c082631SClaudia Draghicescu * broadcast sink.
1782f764a6c2SLuiz Augusto von Dentz */
1783f764a6c2SLuiz Augusto von Dentz ev1 = hci_recv_event_data(hdev, HCI_EV_LE_PA_SYNC_ESTABLISHED);
1784f764a6c2SLuiz Augusto von Dentz if (ev1) {
1785f764a6c2SLuiz Augusto von Dentz sk = iso_get_sock_listen(&hdev->bdaddr, bdaddr, iso_match_sid,
1786f764a6c2SLuiz Augusto von Dentz ev1);
1787fbdc4bc4SIulia Tanasescu if (sk && !ev1->status)
1788f764a6c2SLuiz Augusto von Dentz iso_pi(sk)->sync_handle = le16_to_cpu(ev1->handle);
1789ccf74f23SLuiz Augusto von Dentz
1790f764a6c2SLuiz Augusto von Dentz goto done;
1791f764a6c2SLuiz Augusto von Dentz }
1792f764a6c2SLuiz Augusto von Dentz
1793f764a6c2SLuiz Augusto von Dentz ev2 = hci_recv_event_data(hdev, HCI_EVT_LE_BIG_INFO_ADV_REPORT);
1794f764a6c2SLuiz Augusto von Dentz if (ev2) {
1795fbdc4bc4SIulia Tanasescu /* Try to get PA sync listening socket, if it exists */
1796fbdc4bc4SIulia Tanasescu sk = iso_get_sock_listen(&hdev->bdaddr, bdaddr,
1797fbdc4bc4SIulia Tanasescu iso_match_pa_sync_flag, NULL);
179814410544SIulia Tanasescu
179914410544SIulia Tanasescu if (!sk) {
1800f764a6c2SLuiz Augusto von Dentz sk = iso_get_sock_listen(&hdev->bdaddr, bdaddr,
1801f764a6c2SLuiz Augusto von Dentz iso_match_sync_handle, ev2);
180214410544SIulia Tanasescu
180314410544SIulia Tanasescu /* If PA Sync is in process of terminating,
180414410544SIulia Tanasescu * do not handle any more BIGInfo adv reports.
180514410544SIulia Tanasescu */
180614410544SIulia Tanasescu
180714410544SIulia Tanasescu if (sk && test_bit(BT_SK_PA_SYNC_TERM,
180814410544SIulia Tanasescu &iso_pi(sk)->flags))
180914410544SIulia Tanasescu return lm;
181014410544SIulia Tanasescu }
181114410544SIulia Tanasescu
1812f764a6c2SLuiz Augusto von Dentz if (sk) {
1813f764a6c2SLuiz Augusto von Dentz int err;
1814f764a6c2SLuiz Augusto von Dentz
1815f764a6c2SLuiz Augusto von Dentz if (ev2->num_bis < iso_pi(sk)->bc_num_bis)
1816f764a6c2SLuiz Augusto von Dentz iso_pi(sk)->bc_num_bis = ev2->num_bis;
1817f764a6c2SLuiz Augusto von Dentz
1818fbdc4bc4SIulia Tanasescu if (!test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags) &&
1819fbdc4bc4SIulia Tanasescu !test_and_set_bit(BT_SK_BIG_SYNC, &iso_pi(sk)->flags)) {
1820fbdc4bc4SIulia Tanasescu err = hci_le_big_create_sync(hdev, NULL,
1821f764a6c2SLuiz Augusto von Dentz &iso_pi(sk)->qos,
1822f764a6c2SLuiz Augusto von Dentz iso_pi(sk)->sync_handle,
1823f764a6c2SLuiz Augusto von Dentz iso_pi(sk)->bc_num_bis,
1824f764a6c2SLuiz Augusto von Dentz iso_pi(sk)->bc_bis);
1825f764a6c2SLuiz Augusto von Dentz if (err) {
1826f764a6c2SLuiz Augusto von Dentz bt_dev_err(hdev, "hci_le_big_create_sync: %d",
1827f764a6c2SLuiz Augusto von Dentz err);
1828f764a6c2SLuiz Augusto von Dentz sk = NULL;
1829f764a6c2SLuiz Augusto von Dentz }
1830f764a6c2SLuiz Augusto von Dentz }
1831f777d882SIulia Tanasescu }
18329c082631SClaudia Draghicescu }
18339c082631SClaudia Draghicescu
18349c082631SClaudia Draghicescu ev3 = hci_recv_event_data(hdev, HCI_EV_LE_PER_ADV_REPORT);
18359c082631SClaudia Draghicescu if (ev3) {
18369c082631SClaudia Draghicescu sk = iso_get_sock_listen(&hdev->bdaddr, bdaddr,
18379c082631SClaudia Draghicescu iso_match_sync_handle_pa_report, ev3);
18389c082631SClaudia Draghicescu
18399c082631SClaudia Draghicescu if (sk) {
18409c082631SClaudia Draghicescu memcpy(iso_pi(sk)->base, ev3->data, ev3->length);
18419c082631SClaudia Draghicescu iso_pi(sk)->base_len = ev3->length;
18429c082631SClaudia Draghicescu }
1843f764a6c2SLuiz Augusto von Dentz } else {
1844f764a6c2SLuiz Augusto von Dentz sk = iso_get_sock_listen(&hdev->bdaddr, BDADDR_ANY, NULL, NULL);
1845f764a6c2SLuiz Augusto von Dentz }
1846f764a6c2SLuiz Augusto von Dentz
1847f764a6c2SLuiz Augusto von Dentz done:
1848f764a6c2SLuiz Augusto von Dentz if (!sk)
1849f764a6c2SLuiz Augusto von Dentz return lm;
1850f764a6c2SLuiz Augusto von Dentz
1851ccf74f23SLuiz Augusto von Dentz lm |= HCI_LM_ACCEPT;
1852ccf74f23SLuiz Augusto von Dentz
1853ccf74f23SLuiz Augusto von Dentz if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags))
1854ccf74f23SLuiz Augusto von Dentz *flags |= HCI_PROTO_DEFER;
1855ccf74f23SLuiz Augusto von Dentz
1856ccf74f23SLuiz Augusto von Dentz return lm;
1857ccf74f23SLuiz Augusto von Dentz }
1858ccf74f23SLuiz Augusto von Dentz
iso_connect_cfm(struct hci_conn * hcon,__u8 status)1859ccf74f23SLuiz Augusto von Dentz static void iso_connect_cfm(struct hci_conn *hcon, __u8 status)
1860ccf74f23SLuiz Augusto von Dentz {
1861ccf74f23SLuiz Augusto von Dentz if (hcon->type != ISO_LINK) {
1862ccf74f23SLuiz Augusto von Dentz if (hcon->type != LE_LINK)
1863ccf74f23SLuiz Augusto von Dentz return;
1864ccf74f23SLuiz Augusto von Dentz
1865ccf74f23SLuiz Augusto von Dentz /* Check if LE link has failed */
1866ccf74f23SLuiz Augusto von Dentz if (status) {
186706149746SLuiz Augusto von Dentz struct hci_link *link, *t;
186806149746SLuiz Augusto von Dentz
186906149746SLuiz Augusto von Dentz list_for_each_entry_safe(link, t, &hcon->link_list,
187006149746SLuiz Augusto von Dentz list)
187106149746SLuiz Augusto von Dentz iso_conn_del(link->conn, bt_to_errno(status));
187206149746SLuiz Augusto von Dentz
1873ccf74f23SLuiz Augusto von Dentz return;
1874ccf74f23SLuiz Augusto von Dentz }
1875ccf74f23SLuiz Augusto von Dentz
1876ccf74f23SLuiz Augusto von Dentz /* Create CIS if pending */
18777f74563eSPauli Virtanen hci_le_create_cis_pending(hcon->hdev);
1878ccf74f23SLuiz Augusto von Dentz return;
1879ccf74f23SLuiz Augusto von Dentz }
1880ccf74f23SLuiz Augusto von Dentz
1881ccf74f23SLuiz Augusto von Dentz BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status);
1882ccf74f23SLuiz Augusto von Dentz
1883fbdc4bc4SIulia Tanasescu /* Similar to the success case, if HCI_CONN_BIG_SYNC_FAILED or
1884fbdc4bc4SIulia Tanasescu * HCI_CONN_PA_SYNC_FAILED is set, queue the failed connection
1885fbdc4bc4SIulia Tanasescu * into the accept queue of the listening socket and wake up
1886fbdc4bc4SIulia Tanasescu * userspace, to inform the user about the event.
1887f777d882SIulia Tanasescu */
1888fbdc4bc4SIulia Tanasescu if (!status || test_bit(HCI_CONN_BIG_SYNC_FAILED, &hcon->flags) ||
1889fbdc4bc4SIulia Tanasescu test_bit(HCI_CONN_PA_SYNC_FAILED, &hcon->flags)) {
1890ccf74f23SLuiz Augusto von Dentz struct iso_conn *conn;
1891ccf74f23SLuiz Augusto von Dentz
1892ccf74f23SLuiz Augusto von Dentz conn = iso_conn_add(hcon);
1893ccf74f23SLuiz Augusto von Dentz if (conn)
1894ccf74f23SLuiz Augusto von Dentz iso_conn_ready(conn);
1895ccf74f23SLuiz Augusto von Dentz } else {
1896ccf74f23SLuiz Augusto von Dentz iso_conn_del(hcon, bt_to_errno(status));
1897ccf74f23SLuiz Augusto von Dentz }
1898ccf74f23SLuiz Augusto von Dentz }
1899ccf74f23SLuiz Augusto von Dentz
iso_disconn_cfm(struct hci_conn * hcon,__u8 reason)1900ccf74f23SLuiz Augusto von Dentz static void iso_disconn_cfm(struct hci_conn *hcon, __u8 reason)
1901ccf74f23SLuiz Augusto von Dentz {
1902ccf74f23SLuiz Augusto von Dentz if (hcon->type != ISO_LINK)
1903ccf74f23SLuiz Augusto von Dentz return;
1904ccf74f23SLuiz Augusto von Dentz
1905ccf74f23SLuiz Augusto von Dentz BT_DBG("hcon %p reason %d", hcon, reason);
1906ccf74f23SLuiz Augusto von Dentz
1907ccf74f23SLuiz Augusto von Dentz iso_conn_del(hcon, bt_to_errno(reason));
1908ccf74f23SLuiz Augusto von Dentz }
1909ccf74f23SLuiz Augusto von Dentz
iso_recv(struct hci_conn * hcon,struct sk_buff * skb,u16 flags)1910ccf74f23SLuiz Augusto von Dentz void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
1911ccf74f23SLuiz Augusto von Dentz {
1912ccf74f23SLuiz Augusto von Dentz struct iso_conn *conn = hcon->iso_data;
1913ccf74f23SLuiz Augusto von Dentz __u16 pb, ts, len;
1914ccf74f23SLuiz Augusto von Dentz
1915ccf74f23SLuiz Augusto von Dentz if (!conn)
1916ccf74f23SLuiz Augusto von Dentz goto drop;
1917ccf74f23SLuiz Augusto von Dentz
1918ccf74f23SLuiz Augusto von Dentz pb = hci_iso_flags_pb(flags);
1919ccf74f23SLuiz Augusto von Dentz ts = hci_iso_flags_ts(flags);
1920ccf74f23SLuiz Augusto von Dentz
1921ccf74f23SLuiz Augusto von Dentz BT_DBG("conn %p len %d pb 0x%x ts 0x%x", conn, skb->len, pb, ts);
1922ccf74f23SLuiz Augusto von Dentz
1923ccf74f23SLuiz Augusto von Dentz switch (pb) {
1924ccf74f23SLuiz Augusto von Dentz case ISO_START:
1925ccf74f23SLuiz Augusto von Dentz case ISO_SINGLE:
1926ccf74f23SLuiz Augusto von Dentz if (conn->rx_len) {
1927ccf74f23SLuiz Augusto von Dentz BT_ERR("Unexpected start frame (len %d)", skb->len);
1928ccf74f23SLuiz Augusto von Dentz kfree_skb(conn->rx_skb);
1929ccf74f23SLuiz Augusto von Dentz conn->rx_skb = NULL;
1930ccf74f23SLuiz Augusto von Dentz conn->rx_len = 0;
1931ccf74f23SLuiz Augusto von Dentz }
1932ccf74f23SLuiz Augusto von Dentz
1933ccf74f23SLuiz Augusto von Dentz if (ts) {
19342f10e40aSPauli Virtanen struct hci_iso_ts_data_hdr *hdr;
19352f10e40aSPauli Virtanen
1936ccf74f23SLuiz Augusto von Dentz /* TODO: add timestamp to the packet? */
1937ccf74f23SLuiz Augusto von Dentz hdr = skb_pull_data(skb, HCI_ISO_TS_DATA_HDR_SIZE);
1938ccf74f23SLuiz Augusto von Dentz if (!hdr) {
1939ccf74f23SLuiz Augusto von Dentz BT_ERR("Frame is too short (len %d)", skb->len);
1940ccf74f23SLuiz Augusto von Dentz goto drop;
1941ccf74f23SLuiz Augusto von Dentz }
1942ccf74f23SLuiz Augusto von Dentz
19432f10e40aSPauli Virtanen len = __le16_to_cpu(hdr->slen);
1944ccf74f23SLuiz Augusto von Dentz } else {
19452f10e40aSPauli Virtanen struct hci_iso_data_hdr *hdr;
19462f10e40aSPauli Virtanen
1947ccf74f23SLuiz Augusto von Dentz hdr = skb_pull_data(skb, HCI_ISO_DATA_HDR_SIZE);
1948ccf74f23SLuiz Augusto von Dentz if (!hdr) {
1949ccf74f23SLuiz Augusto von Dentz BT_ERR("Frame is too short (len %d)", skb->len);
1950ccf74f23SLuiz Augusto von Dentz goto drop;
1951ccf74f23SLuiz Augusto von Dentz }
1952ccf74f23SLuiz Augusto von Dentz
1953ccf74f23SLuiz Augusto von Dentz len = __le16_to_cpu(hdr->slen);
19542f10e40aSPauli Virtanen }
19552f10e40aSPauli Virtanen
1956ccf74f23SLuiz Augusto von Dentz flags = hci_iso_data_flags(len);
1957ccf74f23SLuiz Augusto von Dentz len = hci_iso_data_len(len);
1958ccf74f23SLuiz Augusto von Dentz
1959ccf74f23SLuiz Augusto von Dentz BT_DBG("Start: total len %d, frag len %d flags 0x%4.4x", len,
1960ccf74f23SLuiz Augusto von Dentz skb->len, flags);
1961ccf74f23SLuiz Augusto von Dentz
1962ccf74f23SLuiz Augusto von Dentz if (len == skb->len) {
1963ccf74f23SLuiz Augusto von Dentz /* Complete frame received */
19640731c5abSLuiz Augusto von Dentz hci_skb_pkt_status(skb) = flags & 0x03;
1965ccf74f23SLuiz Augusto von Dentz iso_recv_frame(conn, skb);
1966ccf74f23SLuiz Augusto von Dentz return;
1967ccf74f23SLuiz Augusto von Dentz }
1968ccf74f23SLuiz Augusto von Dentz
1969ccf74f23SLuiz Augusto von Dentz if (pb == ISO_SINGLE) {
1970ccf74f23SLuiz Augusto von Dentz BT_ERR("Frame malformed (len %d, expected len %d)",
1971ccf74f23SLuiz Augusto von Dentz skb->len, len);
1972ccf74f23SLuiz Augusto von Dentz goto drop;
1973ccf74f23SLuiz Augusto von Dentz }
1974ccf74f23SLuiz Augusto von Dentz
1975ccf74f23SLuiz Augusto von Dentz if (skb->len > len) {
1976ccf74f23SLuiz Augusto von Dentz BT_ERR("Frame is too long (len %d, expected len %d)",
1977ccf74f23SLuiz Augusto von Dentz skb->len, len);
1978ccf74f23SLuiz Augusto von Dentz goto drop;
1979ccf74f23SLuiz Augusto von Dentz }
1980ccf74f23SLuiz Augusto von Dentz
1981ccf74f23SLuiz Augusto von Dentz /* Allocate skb for the complete frame (with header) */
1982ccf74f23SLuiz Augusto von Dentz conn->rx_skb = bt_skb_alloc(len, GFP_KERNEL);
1983ccf74f23SLuiz Augusto von Dentz if (!conn->rx_skb)
1984ccf74f23SLuiz Augusto von Dentz goto drop;
1985ccf74f23SLuiz Augusto von Dentz
19860731c5abSLuiz Augusto von Dentz hci_skb_pkt_status(conn->rx_skb) = flags & 0x03;
1987ccf74f23SLuiz Augusto von Dentz skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
1988ccf74f23SLuiz Augusto von Dentz skb->len);
1989ccf74f23SLuiz Augusto von Dentz conn->rx_len = len - skb->len;
1990ccf74f23SLuiz Augusto von Dentz break;
1991ccf74f23SLuiz Augusto von Dentz
1992ccf74f23SLuiz Augusto von Dentz case ISO_CONT:
1993ccf74f23SLuiz Augusto von Dentz BT_DBG("Cont: frag len %d (expecting %d)", skb->len,
1994ccf74f23SLuiz Augusto von Dentz conn->rx_len);
1995ccf74f23SLuiz Augusto von Dentz
1996ccf74f23SLuiz Augusto von Dentz if (!conn->rx_len) {
1997ccf74f23SLuiz Augusto von Dentz BT_ERR("Unexpected continuation frame (len %d)",
1998ccf74f23SLuiz Augusto von Dentz skb->len);
1999ccf74f23SLuiz Augusto von Dentz goto drop;
2000ccf74f23SLuiz Augusto von Dentz }
2001ccf74f23SLuiz Augusto von Dentz
2002ccf74f23SLuiz Augusto von Dentz if (skb->len > conn->rx_len) {
2003ccf74f23SLuiz Augusto von Dentz BT_ERR("Fragment is too long (len %d, expected %d)",
2004ccf74f23SLuiz Augusto von Dentz skb->len, conn->rx_len);
2005ccf74f23SLuiz Augusto von Dentz kfree_skb(conn->rx_skb);
2006ccf74f23SLuiz Augusto von Dentz conn->rx_skb = NULL;
2007ccf74f23SLuiz Augusto von Dentz conn->rx_len = 0;
2008ccf74f23SLuiz Augusto von Dentz goto drop;
2009ccf74f23SLuiz Augusto von Dentz }
2010ccf74f23SLuiz Augusto von Dentz
2011ccf74f23SLuiz Augusto von Dentz skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
2012ccf74f23SLuiz Augusto von Dentz skb->len);
2013ccf74f23SLuiz Augusto von Dentz conn->rx_len -= skb->len;
2014ccf74f23SLuiz Augusto von Dentz return;
2015ccf74f23SLuiz Augusto von Dentz
2016ccf74f23SLuiz Augusto von Dentz case ISO_END:
2017ccf74f23SLuiz Augusto von Dentz skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
2018ccf74f23SLuiz Augusto von Dentz skb->len);
2019ccf74f23SLuiz Augusto von Dentz conn->rx_len -= skb->len;
2020ccf74f23SLuiz Augusto von Dentz
2021ccf74f23SLuiz Augusto von Dentz if (!conn->rx_len) {
2022ccf74f23SLuiz Augusto von Dentz struct sk_buff *rx_skb = conn->rx_skb;
2023ccf74f23SLuiz Augusto von Dentz
2024ccf74f23SLuiz Augusto von Dentz /* Complete frame received. iso_recv_frame
2025ccf74f23SLuiz Augusto von Dentz * takes ownership of the skb so set the global
2026ccf74f23SLuiz Augusto von Dentz * rx_skb pointer to NULL first.
2027ccf74f23SLuiz Augusto von Dentz */
2028ccf74f23SLuiz Augusto von Dentz conn->rx_skb = NULL;
2029ccf74f23SLuiz Augusto von Dentz iso_recv_frame(conn, rx_skb);
2030ccf74f23SLuiz Augusto von Dentz }
2031ccf74f23SLuiz Augusto von Dentz break;
2032ccf74f23SLuiz Augusto von Dentz }
2033ccf74f23SLuiz Augusto von Dentz
2034ccf74f23SLuiz Augusto von Dentz drop:
2035ccf74f23SLuiz Augusto von Dentz kfree_skb(skb);
2036ccf74f23SLuiz Augusto von Dentz }
2037ccf74f23SLuiz Augusto von Dentz
2038ccf74f23SLuiz Augusto von Dentz static struct hci_cb iso_cb = {
2039ccf74f23SLuiz Augusto von Dentz .name = "ISO",
2040ccf74f23SLuiz Augusto von Dentz .connect_cfm = iso_connect_cfm,
2041ccf74f23SLuiz Augusto von Dentz .disconn_cfm = iso_disconn_cfm,
2042ccf74f23SLuiz Augusto von Dentz };
2043ccf74f23SLuiz Augusto von Dentz
iso_debugfs_show(struct seq_file * f,void * p)2044ccf74f23SLuiz Augusto von Dentz static int iso_debugfs_show(struct seq_file *f, void *p)
2045ccf74f23SLuiz Augusto von Dentz {
2046ccf74f23SLuiz Augusto von Dentz struct sock *sk;
2047ccf74f23SLuiz Augusto von Dentz
2048ccf74f23SLuiz Augusto von Dentz read_lock(&iso_sk_list.lock);
2049ccf74f23SLuiz Augusto von Dentz
2050ccf74f23SLuiz Augusto von Dentz sk_for_each(sk, &iso_sk_list.head) {
2051ccf74f23SLuiz Augusto von Dentz seq_printf(f, "%pMR %pMR %d\n", &iso_pi(sk)->src,
2052ccf74f23SLuiz Augusto von Dentz &iso_pi(sk)->dst, sk->sk_state);
2053ccf74f23SLuiz Augusto von Dentz }
2054ccf74f23SLuiz Augusto von Dentz
2055ccf74f23SLuiz Augusto von Dentz read_unlock(&iso_sk_list.lock);
2056ccf74f23SLuiz Augusto von Dentz
2057ccf74f23SLuiz Augusto von Dentz return 0;
2058ccf74f23SLuiz Augusto von Dentz }
2059ccf74f23SLuiz Augusto von Dentz
2060ccf74f23SLuiz Augusto von Dentz DEFINE_SHOW_ATTRIBUTE(iso_debugfs);
2061ccf74f23SLuiz Augusto von Dentz
2062ccf74f23SLuiz Augusto von Dentz static struct dentry *iso_debugfs;
2063ccf74f23SLuiz Augusto von Dentz
2064ccf74f23SLuiz Augusto von Dentz static const struct proto_ops iso_sock_ops = {
2065ccf74f23SLuiz Augusto von Dentz .family = PF_BLUETOOTH,
2066ccf74f23SLuiz Augusto von Dentz .owner = THIS_MODULE,
2067ccf74f23SLuiz Augusto von Dentz .release = iso_sock_release,
2068ccf74f23SLuiz Augusto von Dentz .bind = iso_sock_bind,
2069ccf74f23SLuiz Augusto von Dentz .connect = iso_sock_connect,
2070ccf74f23SLuiz Augusto von Dentz .listen = iso_sock_listen,
2071ccf74f23SLuiz Augusto von Dentz .accept = iso_sock_accept,
2072ccf74f23SLuiz Augusto von Dentz .getname = iso_sock_getname,
2073ccf74f23SLuiz Augusto von Dentz .sendmsg = iso_sock_sendmsg,
2074ccf74f23SLuiz Augusto von Dentz .recvmsg = iso_sock_recvmsg,
2075ccf74f23SLuiz Augusto von Dentz .poll = bt_sock_poll,
2076ccf74f23SLuiz Augusto von Dentz .ioctl = bt_sock_ioctl,
2077ccf74f23SLuiz Augusto von Dentz .mmap = sock_no_mmap,
2078ccf74f23SLuiz Augusto von Dentz .socketpair = sock_no_socketpair,
2079ccf74f23SLuiz Augusto von Dentz .shutdown = iso_sock_shutdown,
2080ccf74f23SLuiz Augusto von Dentz .setsockopt = iso_sock_setsockopt,
2081ccf74f23SLuiz Augusto von Dentz .getsockopt = iso_sock_getsockopt
2082ccf74f23SLuiz Augusto von Dentz };
2083ccf74f23SLuiz Augusto von Dentz
2084ccf74f23SLuiz Augusto von Dentz static const struct net_proto_family iso_sock_family_ops = {
2085ccf74f23SLuiz Augusto von Dentz .family = PF_BLUETOOTH,
2086ccf74f23SLuiz Augusto von Dentz .owner = THIS_MODULE,
2087ccf74f23SLuiz Augusto von Dentz .create = iso_sock_create,
2088ccf74f23SLuiz Augusto von Dentz };
2089ccf74f23SLuiz Augusto von Dentz
2090ccf74f23SLuiz Augusto von Dentz static bool iso_inited;
2091ccf74f23SLuiz Augusto von Dentz
iso_enabled(void)2092ccf74f23SLuiz Augusto von Dentz bool iso_enabled(void)
2093ccf74f23SLuiz Augusto von Dentz {
2094ccf74f23SLuiz Augusto von Dentz return iso_inited;
2095ccf74f23SLuiz Augusto von Dentz }
2096ccf74f23SLuiz Augusto von Dentz
iso_init(void)2097ccf74f23SLuiz Augusto von Dentz int iso_init(void)
2098ccf74f23SLuiz Augusto von Dentz {
2099ccf74f23SLuiz Augusto von Dentz int err;
2100ccf74f23SLuiz Augusto von Dentz
2101ccf74f23SLuiz Augusto von Dentz BUILD_BUG_ON(sizeof(struct sockaddr_iso) > sizeof(struct sockaddr));
2102ccf74f23SLuiz Augusto von Dentz
2103ccf74f23SLuiz Augusto von Dentz if (iso_inited)
2104ccf74f23SLuiz Augusto von Dentz return -EALREADY;
2105ccf74f23SLuiz Augusto von Dentz
2106ccf74f23SLuiz Augusto von Dentz err = proto_register(&iso_proto, 0);
2107ccf74f23SLuiz Augusto von Dentz if (err < 0)
2108ccf74f23SLuiz Augusto von Dentz return err;
2109ccf74f23SLuiz Augusto von Dentz
2110ccf74f23SLuiz Augusto von Dentz err = bt_sock_register(BTPROTO_ISO, &iso_sock_family_ops);
2111ccf74f23SLuiz Augusto von Dentz if (err < 0) {
2112ccf74f23SLuiz Augusto von Dentz BT_ERR("ISO socket registration failed");
2113ccf74f23SLuiz Augusto von Dentz goto error;
2114ccf74f23SLuiz Augusto von Dentz }
2115ccf74f23SLuiz Augusto von Dentz
2116ccf74f23SLuiz Augusto von Dentz err = bt_procfs_init(&init_net, "iso", &iso_sk_list, NULL);
2117ccf74f23SLuiz Augusto von Dentz if (err < 0) {
2118ccf74f23SLuiz Augusto von Dentz BT_ERR("Failed to create ISO proc file");
2119ccf74f23SLuiz Augusto von Dentz bt_sock_unregister(BTPROTO_ISO);
2120ccf74f23SLuiz Augusto von Dentz goto error;
2121ccf74f23SLuiz Augusto von Dentz }
2122ccf74f23SLuiz Augusto von Dentz
2123ccf74f23SLuiz Augusto von Dentz BT_INFO("ISO socket layer initialized");
2124ccf74f23SLuiz Augusto von Dentz
2125ccf74f23SLuiz Augusto von Dentz hci_register_cb(&iso_cb);
2126ccf74f23SLuiz Augusto von Dentz
2127ccf74f23SLuiz Augusto von Dentz if (IS_ERR_OR_NULL(bt_debugfs))
2128ccf74f23SLuiz Augusto von Dentz return 0;
2129ccf74f23SLuiz Augusto von Dentz
2130ccf74f23SLuiz Augusto von Dentz if (!iso_debugfs) {
2131ccf74f23SLuiz Augusto von Dentz iso_debugfs = debugfs_create_file("iso", 0444, bt_debugfs,
2132ccf74f23SLuiz Augusto von Dentz NULL, &iso_debugfs_fops);
2133ccf74f23SLuiz Augusto von Dentz }
2134ccf74f23SLuiz Augusto von Dentz
2135ccf74f23SLuiz Augusto von Dentz iso_inited = true;
2136ccf74f23SLuiz Augusto von Dentz
2137ccf74f23SLuiz Augusto von Dentz return 0;
2138ccf74f23SLuiz Augusto von Dentz
2139ccf74f23SLuiz Augusto von Dentz error:
2140ccf74f23SLuiz Augusto von Dentz proto_unregister(&iso_proto);
2141ccf74f23SLuiz Augusto von Dentz return err;
2142ccf74f23SLuiz Augusto von Dentz }
2143ccf74f23SLuiz Augusto von Dentz
iso_exit(void)2144ccf74f23SLuiz Augusto von Dentz int iso_exit(void)
2145ccf74f23SLuiz Augusto von Dentz {
2146ccf74f23SLuiz Augusto von Dentz if (!iso_inited)
2147ccf74f23SLuiz Augusto von Dentz return -EALREADY;
2148ccf74f23SLuiz Augusto von Dentz
2149ccf74f23SLuiz Augusto von Dentz bt_procfs_cleanup(&init_net, "iso");
2150ccf74f23SLuiz Augusto von Dentz
2151ccf74f23SLuiz Augusto von Dentz debugfs_remove(iso_debugfs);
2152ccf74f23SLuiz Augusto von Dentz iso_debugfs = NULL;
2153ccf74f23SLuiz Augusto von Dentz
2154ccf74f23SLuiz Augusto von Dentz hci_unregister_cb(&iso_cb);
2155ccf74f23SLuiz Augusto von Dentz
2156ccf74f23SLuiz Augusto von Dentz bt_sock_unregister(BTPROTO_ISO);
2157ccf74f23SLuiz Augusto von Dentz
2158ccf74f23SLuiz Augusto von Dentz proto_unregister(&iso_proto);
2159ccf74f23SLuiz Augusto von Dentz
2160ccf74f23SLuiz Augusto von Dentz iso_inited = false;
2161ccf74f23SLuiz Augusto von Dentz
2162ccf74f23SLuiz Augusto von Dentz return 0;
2163ccf74f23SLuiz Augusto von Dentz }
2164