blob: 93026687cbe766e4c346b40f944a4c6c480838d6 [file] [log] [blame]
Johan Hedberg03811012010-12-08 00:21:06 +02001/*
2 BlueZ - Bluetooth protocol stack for Linux
3 Copyright (C) 2010 Nokia Corporation
Brian Gix568dde92012-01-11 16:18:04 -08004 Copyright (c) 2011-2012 Code Aurora Forum. All rights reserved.
Johan Hedberg03811012010-12-08 00:21:06 +02005
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License version 2 as
8 published by the Free Software Foundation;
9
10 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
11 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
12 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
13 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
14 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
15 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
19 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
20 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
21 SOFTWARE IS DISCLAIMED.
22*/
23
24/* Bluetooth HCI Management interface */
25
Szymon Janc72359752011-02-17 14:16:32 +010026#include <linux/uaccess.h>
Johan Hedberg03811012010-12-08 00:21:06 +020027#include <asm/unaligned.h>
28
29#include <net/bluetooth/bluetooth.h>
30#include <net/bluetooth/hci_core.h>
Brian Gixa68668b2011-08-11 15:49:36 -070031#include <net/bluetooth/l2cap.h>
Johan Hedberg03811012010-12-08 00:21:06 +020032#include <net/bluetooth/mgmt.h>
Brian Gixa68668b2011-08-11 15:49:36 -070033#include <net/bluetooth/smp.h>
Johan Hedberg03811012010-12-08 00:21:06 +020034
Johan Hedberg02d98122010-12-13 21:07:04 +020035#define MGMT_VERSION 0
36#define MGMT_REVISION 1
37
Brian Gix568dde92012-01-11 16:18:04 -080038#define SCAN_IDLE 0x00
39#define SCAN_LE 0x01
40#define SCAN_BR 0x02
Brian Gixa68668b2011-08-11 15:49:36 -070041
Johan Hedbergeec8d2b2010-12-16 10:17:38 +020042struct pending_cmd {
43 struct list_head list;
44 __u16 opcode;
45 int index;
Szymon Jancc68fb7f2011-03-22 13:12:19 +010046 void *param;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +020047 struct sock *sk;
Johan Hedberge9a416b2011-02-19 12:05:56 -030048 void *user_data;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +020049};
50
Mat Martineau8cd0df02011-08-23 16:23:36 -070051struct mgmt_pending_free_work {
52 struct work_struct work;
53 struct sock *sk;
54};
55
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070056LIST_HEAD(cmd_list);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +020057
Szymon Janc4e51eae2011-02-25 19:05:48 +010058static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
Johan Hedbergf7b64e62010-12-13 21:07:06 +020059{
60 struct sk_buff *skb;
61 struct mgmt_hdr *hdr;
62 struct mgmt_ev_cmd_status *ev;
63
Szymon Janc34eb5252011-02-28 14:10:08 +010064 BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status);
Johan Hedbergf7b64e62010-12-13 21:07:06 +020065
66 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_ATOMIC);
67 if (!skb)
68 return -ENOMEM;
69
70 hdr = (void *) skb_put(skb, sizeof(*hdr));
71
72 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
Szymon Janc4e51eae2011-02-25 19:05:48 +010073 hdr->index = cpu_to_le16(index);
Johan Hedbergf7b64e62010-12-13 21:07:06 +020074 hdr->len = cpu_to_le16(sizeof(*ev));
75
76 ev = (void *) skb_put(skb, sizeof(*ev));
77 ev->status = status;
78 put_unaligned_le16(cmd, &ev->opcode);
79
80 if (sock_queue_rcv_skb(sk, skb) < 0)
81 kfree_skb(skb);
82
83 return 0;
84}
85
Szymon Janc4e51eae2011-02-25 19:05:48 +010086static int cmd_complete(struct sock *sk, u16 index, u16 cmd, void *rp,
87 size_t rp_len)
Johan Hedberg02d98122010-12-13 21:07:04 +020088{
89 struct sk_buff *skb;
90 struct mgmt_hdr *hdr;
91 struct mgmt_ev_cmd_complete *ev;
Johan Hedberg02d98122010-12-13 21:07:04 +020092
93 BT_DBG("sock %p", sk);
94
Johan Hedberga38528f2011-01-22 06:46:43 +020095 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + rp_len, GFP_ATOMIC);
Johan Hedberg02d98122010-12-13 21:07:04 +020096 if (!skb)
97 return -ENOMEM;
98
99 hdr = (void *) skb_put(skb, sizeof(*hdr));
Johan Hedberga38528f2011-01-22 06:46:43 +0200100
Johan Hedberg02d98122010-12-13 21:07:04 +0200101 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100102 hdr->index = cpu_to_le16(index);
Johan Hedberga38528f2011-01-22 06:46:43 +0200103 hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200104
Johan Hedberga38528f2011-01-22 06:46:43 +0200105 ev = (void *) skb_put(skb, sizeof(*ev) + rp_len);
106 put_unaligned_le16(cmd, &ev->opcode);
Szymon Janc8020c162011-02-28 14:09:50 +0100107
108 if (rp)
109 memcpy(ev->data, rp, rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200110
111 if (sock_queue_rcv_skb(sk, skb) < 0)
112 kfree_skb(skb);
113
114 return 0;
115}
116
Johan Hedberga38528f2011-01-22 06:46:43 +0200117static int read_version(struct sock *sk)
118{
119 struct mgmt_rp_read_version rp;
120
121 BT_DBG("sock %p", sk);
122
123 rp.version = MGMT_VERSION;
124 put_unaligned_le16(MGMT_REVISION, &rp.revision);
125
Szymon Janc4e51eae2011-02-25 19:05:48 +0100126 return cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, &rp,
127 sizeof(rp));
Johan Hedberga38528f2011-01-22 06:46:43 +0200128}
129
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200130static int read_index_list(struct sock *sk)
131{
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200132 struct mgmt_rp_read_index_list *rp;
133 struct list_head *p;
Johan Hedberga38528f2011-01-22 06:46:43 +0200134 size_t rp_len;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200135 u16 count;
Johan Hedberga38528f2011-01-22 06:46:43 +0200136 int i, err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200137
138 BT_DBG("sock %p", sk);
139
140 read_lock(&hci_dev_list_lock);
141
142 count = 0;
143 list_for_each(p, &hci_dev_list) {
Peter Krystad1fc44072011-08-30 15:38:12 -0700144 struct hci_dev *d = list_entry(p, struct hci_dev, list);
145 if (d->dev_type != HCI_BREDR)
146 continue;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200147 count++;
148 }
149
Johan Hedberga38528f2011-01-22 06:46:43 +0200150 rp_len = sizeof(*rp) + (2 * count);
151 rp = kmalloc(rp_len, GFP_ATOMIC);
152 if (!rp) {
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100153 read_unlock(&hci_dev_list_lock);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200154 return -ENOMEM;
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100155 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200156
Brian Gixa68668b2011-08-11 15:49:36 -0700157 put_unaligned_le16(0, &rp->num_controllers);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200158
159 i = 0;
160 list_for_each(p, &hci_dev_list) {
161 struct hci_dev *d = list_entry(p, struct hci_dev, list);
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200162
163 hci_del_off_timer(d);
164
Peter Krystad1fc44072011-08-30 15:38:12 -0700165 if (d->dev_type != HCI_BREDR)
166 continue;
167
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200168 set_bit(HCI_MGMT, &d->flags);
169
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200170 if (test_bit(HCI_SETUP, &d->flags))
171 continue;
172
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200173 put_unaligned_le16(d->id, &rp->index[i++]);
Brian Gixa68668b2011-08-11 15:49:36 -0700174 put_unaligned_le16((u16)i, &rp->num_controllers);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200175 BT_DBG("Added hci%u", d->id);
176 }
177
178 read_unlock(&hci_dev_list_lock);
179
Szymon Janc4e51eae2011-02-25 19:05:48 +0100180 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST, rp,
181 rp_len);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200182
Johan Hedberga38528f2011-01-22 06:46:43 +0200183 kfree(rp);
184
185 return err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200186}
187
Szymon Janc4e51eae2011-02-25 19:05:48 +0100188static int read_controller_info(struct sock *sk, u16 index)
Johan Hedberg03811012010-12-08 00:21:06 +0200189{
Johan Hedberga38528f2011-01-22 06:46:43 +0200190 struct mgmt_rp_read_info rp;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200191 struct hci_dev *hdev;
Johan Hedberg03811012010-12-08 00:21:06 +0200192
Szymon Janc4e51eae2011-02-25 19:05:48 +0100193 BT_DBG("sock %p hci%u", sk, index);
Johan Hedberg03811012010-12-08 00:21:06 +0200194
Szymon Janc4e51eae2011-02-25 19:05:48 +0100195 hdev = hci_dev_get(index);
Johan Hedberga38528f2011-01-22 06:46:43 +0200196 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +0100197 return cmd_status(sk, index, MGMT_OP_READ_INFO, ENODEV);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200198
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200199 hci_del_off_timer(hdev);
200
Subramanian Srinivasana727a492011-11-30 13:06:07 -0800201 hci_dev_lock_bh(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200202
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200203 set_bit(HCI_MGMT, &hdev->flags);
204
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200205 memset(&rp, 0, sizeof(rp));
206
Johan Hedberga38528f2011-01-22 06:46:43 +0200207 rp.type = hdev->dev_type;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200208
Johan Hedberga38528f2011-01-22 06:46:43 +0200209 rp.powered = test_bit(HCI_UP, &hdev->flags);
210 rp.connectable = test_bit(HCI_PSCAN, &hdev->flags);
211 rp.discoverable = test_bit(HCI_ISCAN, &hdev->flags);
212 rp.pairable = test_bit(HCI_PSCAN, &hdev->flags);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200213
214 if (test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberga38528f2011-01-22 06:46:43 +0200215 rp.sec_mode = 3;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200216 else if (hdev->ssp_mode > 0)
Johan Hedberga38528f2011-01-22 06:46:43 +0200217 rp.sec_mode = 4;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200218 else
Johan Hedberga38528f2011-01-22 06:46:43 +0200219 rp.sec_mode = 2;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200220
Johan Hedberga38528f2011-01-22 06:46:43 +0200221 bacpy(&rp.bdaddr, &hdev->bdaddr);
222 memcpy(rp.features, hdev->features, 8);
223 memcpy(rp.dev_class, hdev->dev_class, 3);
224 put_unaligned_le16(hdev->manufacturer, &rp.manufacturer);
225 rp.hci_ver = hdev->hci_ver;
226 put_unaligned_le16(hdev->hci_rev, &rp.hci_rev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200227
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200228 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
229
Subramanian Srinivasana727a492011-11-30 13:06:07 -0800230 hci_dev_unlock_bh(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200231 hci_dev_put(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +0200232
Szymon Janc4e51eae2011-02-25 19:05:48 +0100233 return cmd_complete(sk, index, MGMT_OP_READ_INFO, &rp, sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +0200234}
235
Mat Martineau8cd0df02011-08-23 16:23:36 -0700236static void mgmt_pending_free_worker(struct work_struct *work)
237{
238 struct mgmt_pending_free_work *free_work =
239 container_of(work, struct mgmt_pending_free_work, work);
240
241 BT_DBG("sk %p", free_work->sk);
242
243 sock_put(free_work->sk);
244 kfree(free_work);
245}
246
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200247static void mgmt_pending_free(struct pending_cmd *cmd)
248{
Mat Martineau8cd0df02011-08-23 16:23:36 -0700249 struct mgmt_pending_free_work *free_work;
250 struct sock *sk = cmd->sk;
Brian Gixa68668b2011-08-11 15:49:36 -0700251
Mat Martineau8cd0df02011-08-23 16:23:36 -0700252 BT_DBG("opcode %d, sk %p", cmd->opcode, sk);
253
Szymon Jancc68fb7f2011-03-22 13:12:19 +0100254 kfree(cmd->param);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200255 kfree(cmd);
Mat Martineau8cd0df02011-08-23 16:23:36 -0700256
257 free_work = kzalloc(sizeof(*free_work), GFP_ATOMIC);
258 if (free_work) {
259 INIT_WORK(&free_work->work, mgmt_pending_free_worker);
260 free_work->sk = sk;
261
262 if (!schedule_work(&free_work->work))
263 kfree(free_work);
264 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200265}
266
Johan Hedberg366a0332011-02-19 12:05:55 -0300267static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
268 u16 index, void *data, u16 len)
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200269{
270 struct pending_cmd *cmd;
271
Brian Gixa68668b2011-08-11 15:49:36 -0700272 BT_DBG("%d", opcode);
273
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200274 cmd = kmalloc(sizeof(*cmd), GFP_ATOMIC);
275 if (!cmd)
Johan Hedberg366a0332011-02-19 12:05:55 -0300276 return NULL;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200277
278 cmd->opcode = opcode;
279 cmd->index = index;
280
Szymon Jancc68fb7f2011-03-22 13:12:19 +0100281 cmd->param = kmalloc(len, GFP_ATOMIC);
282 if (!cmd->param) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200283 kfree(cmd);
Johan Hedberg366a0332011-02-19 12:05:55 -0300284 return NULL;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200285 }
286
Szymon Janc8fce6352011-03-22 13:12:20 +0100287 if (data)
288 memcpy(cmd->param, data, len);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200289
290 cmd->sk = sk;
291 sock_hold(sk);
292
293 list_add(&cmd->list, &cmd_list);
294
Johan Hedberg366a0332011-02-19 12:05:55 -0300295 return cmd;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200296}
297
298static void mgmt_pending_foreach(u16 opcode, int index,
299 void (*cb)(struct pending_cmd *cmd, void *data),
300 void *data)
301{
302 struct list_head *p, *n;
303
Brian Gixa68668b2011-08-11 15:49:36 -0700304 BT_DBG(" %d", opcode);
305
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200306 list_for_each_safe(p, n, &cmd_list) {
307 struct pending_cmd *cmd;
308
309 cmd = list_entry(p, struct pending_cmd, list);
310
311 if (cmd->opcode != opcode)
312 continue;
313
314 if (index >= 0 && cmd->index != index)
315 continue;
316
317 cb(cmd, data);
318 }
319}
320
321static struct pending_cmd *mgmt_pending_find(u16 opcode, int index)
322{
323 struct list_head *p;
324
Brian Gixa68668b2011-08-11 15:49:36 -0700325 BT_DBG(" %d", opcode);
326
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200327 list_for_each(p, &cmd_list) {
328 struct pending_cmd *cmd;
329
330 cmd = list_entry(p, struct pending_cmd, list);
331
332 if (cmd->opcode != opcode)
333 continue;
334
335 if (index >= 0 && cmd->index != index)
336 continue;
337
338 return cmd;
339 }
340
341 return NULL;
342}
343
Johan Hedberga664b5b2011-02-19 12:06:02 -0300344static void mgmt_pending_remove(struct pending_cmd *cmd)
Johan Hedberg73f22f62010-12-29 16:00:25 +0200345{
Brian Gixa68668b2011-08-11 15:49:36 -0700346 BT_DBG(" %d", cmd->opcode);
347
Johan Hedberg73f22f62010-12-29 16:00:25 +0200348 list_del(&cmd->list);
349 mgmt_pending_free(cmd);
350}
351
Szymon Janc4e51eae2011-02-25 19:05:48 +0100352static int set_powered(struct sock *sk, u16 index, unsigned char *data, u16 len)
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200353{
Johan Hedberg72a734e2010-12-30 00:38:22 +0200354 struct mgmt_mode *cp;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200355 struct hci_dev *hdev;
Johan Hedberg366a0332011-02-19 12:05:55 -0300356 struct pending_cmd *cmd;
Johan Hedberg366a0332011-02-19 12:05:55 -0300357 int err, up;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200358
359 cp = (void *) data;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200360
Szymon Janc4e51eae2011-02-25 19:05:48 +0100361 BT_DBG("request for hci%u", index);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200362
Szymon Jancbdce7ba2011-02-25 19:05:49 +0100363 if (len != sizeof(*cp))
364 return cmd_status(sk, index, MGMT_OP_SET_POWERED, EINVAL);
365
Szymon Janc4e51eae2011-02-25 19:05:48 +0100366 hdev = hci_dev_get(index);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200367 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +0100368 return cmd_status(sk, index, MGMT_OP_SET_POWERED, ENODEV);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200369
Subramanian Srinivasana727a492011-11-30 13:06:07 -0800370 hci_dev_lock_bh(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200371
372 up = test_bit(HCI_UP, &hdev->flags);
Johan Hedberg72a734e2010-12-30 00:38:22 +0200373 if ((cp->val && up) || (!cp->val && !up)) {
Szymon Janc4e51eae2011-02-25 19:05:48 +0100374 err = cmd_status(sk, index, MGMT_OP_SET_POWERED, EALREADY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200375 goto failed;
376 }
377
Szymon Janc4e51eae2011-02-25 19:05:48 +0100378 if (mgmt_pending_find(MGMT_OP_SET_POWERED, index)) {
379 err = cmd_status(sk, index, MGMT_OP_SET_POWERED, EBUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200380 goto failed;
381 }
382
Szymon Janc4e51eae2011-02-25 19:05:48 +0100383 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, index, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -0300384 if (!cmd) {
385 err = -ENOMEM;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200386 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -0300387 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200388
Johan Hedberg72a734e2010-12-30 00:38:22 +0200389 if (cp->val)
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200390 queue_work(hdev->workqueue, &hdev->power_on);
391 else
392 queue_work(hdev->workqueue, &hdev->power_off);
393
Johan Hedberg366a0332011-02-19 12:05:55 -0300394 err = 0;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200395
396failed:
Subramanian Srinivasana727a492011-11-30 13:06:07 -0800397 hci_dev_unlock_bh(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200398 hci_dev_put(hdev);
Johan Hedberg366a0332011-02-19 12:05:55 -0300399 return err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200400}
401
Brian Gix8a7f1642011-10-17 17:39:46 -0700402static u8 get_service_classes(struct hci_dev *hdev)
403{
404 struct list_head *p;
405 u8 val = 0;
406
407 list_for_each(p, &hdev->uuids) {
408 struct bt_uuid *uuid = list_entry(p, struct bt_uuid, list);
409
410 val |= uuid->svc_hint;
411 }
412
413 return val;
414}
415
416static int update_class(struct hci_dev *hdev)
417{
418 u8 cod[3];
419
420 BT_DBG("%s", hdev->name);
421
422 if (test_bit(HCI_SERVICE_CACHE, &hdev->flags))
423 return 0;
424
425 cod[0] = hdev->minor_class;
426 cod[1] = hdev->major_class;
427 cod[2] = get_service_classes(hdev);
428
429 if (memcmp(cod, hdev->dev_class, 3) == 0)
430 return 0;
431
432 return hci_send_cmd(hdev, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
433}
434
435static int set_limited_discoverable(struct sock *sk, u16 index,
436 unsigned char *data, u16 len)
437{
438 struct mgmt_mode *cp;
439 struct hci_dev *hdev;
440 struct pending_cmd *cmd;
441 struct hci_cp_write_current_iac_lap dcp;
442 int update_cod;
443 int err = 0;
444 /* General Inquiry LAP: 0x9E8B33, Limited Inquiry LAP: 0x9E8B00 */
445 u8 lap[] = { 0x33, 0x8b, 0x9e, 0x00, 0x8b, 0x9e };
446
447 cp = (void *) data;
448
449 BT_DBG("hci%u discoverable: %d", index, cp->val);
450
451 if (!cp || len != sizeof(*cp))
452 return cmd_status(sk, index, MGMT_OP_SET_LIMIT_DISCOVERABLE,
453 EINVAL);
454
455 hdev = hci_dev_get(index);
456 if (!hdev)
457 return cmd_status(sk, index, MGMT_OP_SET_LIMIT_DISCOVERABLE,
458 ENODEV);
459
Subramanian Srinivasana727a492011-11-30 13:06:07 -0800460 hci_dev_lock_bh(hdev);
Brian Gix8a7f1642011-10-17 17:39:46 -0700461
462 if (!test_bit(HCI_UP, &hdev->flags)) {
463 err = cmd_status(sk, index, MGMT_OP_SET_LIMIT_DISCOVERABLE,
464 ENETDOWN);
465 goto failed;
466 }
467
468 if (mgmt_pending_find(MGMT_OP_SET_LIMIT_DISCOVERABLE, index)) {
469 err = cmd_status(sk, index, MGMT_OP_SET_LIMIT_DISCOVERABLE,
470 EBUSY);
471 goto failed;
472 }
473
474 if (cp->val == test_bit(HCI_ISCAN, &hdev->flags) &&
475 test_bit(HCI_PSCAN, &hdev->flags)) {
476 err = cmd_status(sk, index, MGMT_OP_SET_LIMIT_DISCOVERABLE,
477 EALREADY);
478 goto failed;
479 }
480
481 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LIMIT_DISCOVERABLE, index, data,
482 len);
483 if (!cmd) {
484 err = -ENOMEM;
485 goto failed;
486 }
487
488 memset(&dcp, 0, sizeof(dcp));
489 dcp.num_current_iac = cp->val ? 2 : 1;
490 memcpy(&dcp.lap, lap, dcp.num_current_iac * 3);
491 update_cod = 1;
492
493 if (cp->val) {
494 if (hdev->major_class & MGMT_MAJOR_CLASS_LIMITED)
495 update_cod = 0;
496 hdev->major_class |= MGMT_MAJOR_CLASS_LIMITED;
497 } else {
498 if (!(hdev->major_class & MGMT_MAJOR_CLASS_LIMITED))
499 update_cod = 0;
500 hdev->major_class &= ~MGMT_MAJOR_CLASS_LIMITED;
501 }
502
503 if (update_cod)
504 err = update_class(hdev);
505
506 if (err >= 0)
507 err = hci_send_cmd(hdev, HCI_OP_WRITE_CURRENT_IAC_LAP,
508 sizeof(dcp), &dcp);
509
510 if (err < 0)
511 mgmt_pending_remove(cmd);
512
513failed:
Subramanian Srinivasana727a492011-11-30 13:06:07 -0800514 hci_dev_unlock_bh(hdev);
Brian Gix8a7f1642011-10-17 17:39:46 -0700515 hci_dev_put(hdev);
516
517 return err;
518}
519
Szymon Janc4e51eae2011-02-25 19:05:48 +0100520static int set_discoverable(struct sock *sk, u16 index, unsigned char *data,
521 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +0200522{
Johan Hedberg72a734e2010-12-30 00:38:22 +0200523 struct mgmt_mode *cp;
Johan Hedberg73f22f62010-12-29 16:00:25 +0200524 struct hci_dev *hdev;
Johan Hedberg366a0332011-02-19 12:05:55 -0300525 struct pending_cmd *cmd;
Johan Hedberg73f22f62010-12-29 16:00:25 +0200526 u8 scan;
527 int err;
528
529 cp = (void *) data;
Johan Hedberg73f22f62010-12-29 16:00:25 +0200530
Szymon Janc4e51eae2011-02-25 19:05:48 +0100531 BT_DBG("request for hci%u", index);
Johan Hedberg73f22f62010-12-29 16:00:25 +0200532
Szymon Jancbdce7ba2011-02-25 19:05:49 +0100533 if (len != sizeof(*cp))
534 return cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, EINVAL);
535
Szymon Janc4e51eae2011-02-25 19:05:48 +0100536 hdev = hci_dev_get(index);
Johan Hedberg73f22f62010-12-29 16:00:25 +0200537 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +0100538 return cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, ENODEV);
Johan Hedberg73f22f62010-12-29 16:00:25 +0200539
Subramanian Srinivasana727a492011-11-30 13:06:07 -0800540 hci_dev_lock_bh(hdev);
Johan Hedberg73f22f62010-12-29 16:00:25 +0200541
542 if (!test_bit(HCI_UP, &hdev->flags)) {
Szymon Janc4e51eae2011-02-25 19:05:48 +0100543 err = cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, ENETDOWN);
Johan Hedberg73f22f62010-12-29 16:00:25 +0200544 goto failed;
545 }
546
Szymon Janc4e51eae2011-02-25 19:05:48 +0100547 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, index) ||
548 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, index)) {
549 err = cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, EBUSY);
Johan Hedberg73f22f62010-12-29 16:00:25 +0200550 goto failed;
551 }
552
Johan Hedberg72a734e2010-12-30 00:38:22 +0200553 if (cp->val == test_bit(HCI_ISCAN, &hdev->flags) &&
Johan Hedberg73f22f62010-12-29 16:00:25 +0200554 test_bit(HCI_PSCAN, &hdev->flags)) {
Szymon Janc4e51eae2011-02-25 19:05:48 +0100555 err = cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, EALREADY);
Johan Hedberg73f22f62010-12-29 16:00:25 +0200556 goto failed;
557 }
558
Szymon Janc4e51eae2011-02-25 19:05:48 +0100559 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, index, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -0300560 if (!cmd) {
561 err = -ENOMEM;
Johan Hedberg73f22f62010-12-29 16:00:25 +0200562 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -0300563 }
Johan Hedberg73f22f62010-12-29 16:00:25 +0200564
565 scan = SCAN_PAGE;
566
Johan Hedberg72a734e2010-12-30 00:38:22 +0200567 if (cp->val)
Johan Hedberg73f22f62010-12-29 16:00:25 +0200568 scan |= SCAN_INQUIRY;
569
570 err = hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
571 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -0300572 mgmt_pending_remove(cmd);
Johan Hedberg73f22f62010-12-29 16:00:25 +0200573
574failed:
Subramanian Srinivasana727a492011-11-30 13:06:07 -0800575 hci_dev_unlock_bh(hdev);
Johan Hedberg73f22f62010-12-29 16:00:25 +0200576 hci_dev_put(hdev);
577
578 return err;
579}
580
Szymon Janc4e51eae2011-02-25 19:05:48 +0100581static int set_connectable(struct sock *sk, u16 index, unsigned char *data,
582 u16 len)
Johan Hedberg9fbcbb42010-12-30 00:18:33 +0200583{
Johan Hedberg72a734e2010-12-30 00:38:22 +0200584 struct mgmt_mode *cp;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +0200585 struct hci_dev *hdev;
Johan Hedberg366a0332011-02-19 12:05:55 -0300586 struct pending_cmd *cmd;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +0200587 u8 scan;
588 int err;
589
590 cp = (void *) data;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +0200591
Szymon Janc4e51eae2011-02-25 19:05:48 +0100592 BT_DBG("request for hci%u", index);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +0200593
Szymon Jancbdce7ba2011-02-25 19:05:49 +0100594 if (len != sizeof(*cp))
595 return cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, EINVAL);
596
Szymon Janc4e51eae2011-02-25 19:05:48 +0100597 hdev = hci_dev_get(index);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +0200598 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +0100599 return cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, ENODEV);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +0200600
Subramanian Srinivasana727a492011-11-30 13:06:07 -0800601 hci_dev_lock_bh(hdev);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +0200602
603 if (!test_bit(HCI_UP, &hdev->flags)) {
Szymon Janc4e51eae2011-02-25 19:05:48 +0100604 err = cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, ENETDOWN);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +0200605 goto failed;
606 }
607
Szymon Janc4e51eae2011-02-25 19:05:48 +0100608 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, index) ||
609 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, index)) {
610 err = cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, EBUSY);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +0200611 goto failed;
612 }
613
Johan Hedberg72a734e2010-12-30 00:38:22 +0200614 if (cp->val == test_bit(HCI_PSCAN, &hdev->flags)) {
Szymon Janc4e51eae2011-02-25 19:05:48 +0100615 err = cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, EALREADY);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +0200616 goto failed;
617 }
618
Szymon Janc4e51eae2011-02-25 19:05:48 +0100619 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, index, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -0300620 if (!cmd) {
621 err = -ENOMEM;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +0200622 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -0300623 }
Johan Hedberg9fbcbb42010-12-30 00:18:33 +0200624
Johan Hedberg72a734e2010-12-30 00:38:22 +0200625 if (cp->val)
Johan Hedberg9fbcbb42010-12-30 00:18:33 +0200626 scan = SCAN_PAGE;
627 else
628 scan = 0;
629
630 err = hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
631 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -0300632 mgmt_pending_remove(cmd);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +0200633
634failed:
Subramanian Srinivasana727a492011-11-30 13:06:07 -0800635 hci_dev_unlock_bh(hdev);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +0200636 hci_dev_put(hdev);
637
638 return err;
639}
640
Szymon Janc4e51eae2011-02-25 19:05:48 +0100641static int mgmt_event(u16 event, u16 index, void *data, u16 data_len,
642 struct sock *skip_sk)
Johan Hedbergc542a062011-01-26 13:11:03 +0200643{
644 struct sk_buff *skb;
645 struct mgmt_hdr *hdr;
646
Brian Gixa68668b2011-08-11 15:49:36 -0700647 BT_DBG("hci%d %d", index, event);
648
Johan Hedbergc542a062011-01-26 13:11:03 +0200649 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_ATOMIC);
650 if (!skb)
651 return -ENOMEM;
652
653 bt_cb(skb)->channel = HCI_CHANNEL_CONTROL;
654
655 hdr = (void *) skb_put(skb, sizeof(*hdr));
656 hdr->opcode = cpu_to_le16(event);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100657 hdr->index = cpu_to_le16(index);
Johan Hedbergc542a062011-01-26 13:11:03 +0200658 hdr->len = cpu_to_le16(data_len);
659
Szymon Janc4e51eae2011-02-25 19:05:48 +0100660 if (data)
661 memcpy(skb_put(skb, data_len), data, data_len);
Johan Hedbergc542a062011-01-26 13:11:03 +0200662
663 hci_send_to_sock(NULL, skb, skip_sk);
664 kfree_skb(skb);
665
666 return 0;
667}
668
Johan Hedberg053f0212011-01-26 13:07:10 +0200669static int send_mode_rsp(struct sock *sk, u16 opcode, u16 index, u8 val)
670{
Johan Hedberga38528f2011-01-22 06:46:43 +0200671 struct mgmt_mode rp;
Johan Hedberg053f0212011-01-26 13:07:10 +0200672
Johan Hedberga38528f2011-01-22 06:46:43 +0200673 rp.val = val;
Johan Hedberg053f0212011-01-26 13:07:10 +0200674
Szymon Janc4e51eae2011-02-25 19:05:48 +0100675 return cmd_complete(sk, index, opcode, &rp, sizeof(rp));
Johan Hedberg053f0212011-01-26 13:07:10 +0200676}
677
Szymon Janc4e51eae2011-02-25 19:05:48 +0100678static int set_pairable(struct sock *sk, u16 index, unsigned char *data,
679 u16 len)
Johan Hedbergc542a062011-01-26 13:11:03 +0200680{
681 struct mgmt_mode *cp, ev;
682 struct hci_dev *hdev;
Johan Hedbergc542a062011-01-26 13:11:03 +0200683 int err;
684
685 cp = (void *) data;
Johan Hedbergc542a062011-01-26 13:11:03 +0200686
Szymon Janc4e51eae2011-02-25 19:05:48 +0100687 BT_DBG("request for hci%u", index);
Johan Hedbergc542a062011-01-26 13:11:03 +0200688
Szymon Jancbdce7ba2011-02-25 19:05:49 +0100689 if (len != sizeof(*cp))
690 return cmd_status(sk, index, MGMT_OP_SET_PAIRABLE, EINVAL);
691
Szymon Janc4e51eae2011-02-25 19:05:48 +0100692 hdev = hci_dev_get(index);
Johan Hedbergc542a062011-01-26 13:11:03 +0200693 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +0100694 return cmd_status(sk, index, MGMT_OP_SET_PAIRABLE, ENODEV);
Johan Hedbergc542a062011-01-26 13:11:03 +0200695
Subramanian Srinivasana727a492011-11-30 13:06:07 -0800696 hci_dev_lock_bh(hdev);
Johan Hedbergc542a062011-01-26 13:11:03 +0200697
698 if (cp->val)
699 set_bit(HCI_PAIRABLE, &hdev->flags);
700 else
701 clear_bit(HCI_PAIRABLE, &hdev->flags);
702
Szymon Janc4e51eae2011-02-25 19:05:48 +0100703 err = send_mode_rsp(sk, MGMT_OP_SET_PAIRABLE, index, cp->val);
Johan Hedbergc542a062011-01-26 13:11:03 +0200704 if (err < 0)
705 goto failed;
706
Johan Hedbergc542a062011-01-26 13:11:03 +0200707 ev.val = cp->val;
708
Szymon Janc4e51eae2011-02-25 19:05:48 +0100709 err = mgmt_event(MGMT_EV_PAIRABLE, index, &ev, sizeof(ev), sk);
Johan Hedbergc542a062011-01-26 13:11:03 +0200710
711failed:
Subramanian Srinivasana727a492011-11-30 13:06:07 -0800712 hci_dev_unlock_bh(hdev);
Johan Hedbergc542a062011-01-26 13:11:03 +0200713 hci_dev_put(hdev);
714
715 return err;
716}
717
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300718#define EIR_FLAGS 0x01 /* flags */
719#define EIR_UUID16_SOME 0x02 /* 16-bit UUID, more available */
720#define EIR_UUID16_ALL 0x03 /* 16-bit UUID, all listed */
721#define EIR_UUID32_SOME 0x04 /* 32-bit UUID, more available */
722#define EIR_UUID32_ALL 0x05 /* 32-bit UUID, all listed */
723#define EIR_UUID128_SOME 0x06 /* 128-bit UUID, more available */
724#define EIR_UUID128_ALL 0x07 /* 128-bit UUID, all listed */
725#define EIR_NAME_SHORT 0x08 /* shortened local name */
726#define EIR_NAME_COMPLETE 0x09 /* complete local name */
727#define EIR_TX_POWER 0x0A /* transmit power level */
728#define EIR_DEVICE_ID 0x10 /* device ID */
729
730#define PNP_INFO_SVCLASS_ID 0x1200
731
732static u8 bluetooth_base_uuid[] = {
733 0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80,
734 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
735};
736
737static u16 get_uuid16(u8 *uuid128)
738{
739 u32 val;
740 int i;
741
742 for (i = 0; i < 12; i++) {
743 if (bluetooth_base_uuid[i] != uuid128[i])
744 return 0;
745 }
746
747 memcpy(&val, &uuid128[12], 4);
748
749 val = le32_to_cpu(val);
750 if (val > 0xffff)
751 return 0;
752
753 return (u16) val;
754}
755
756static void create_eir(struct hci_dev *hdev, u8 *data)
757{
758 u8 *ptr = data;
759 u16 eir_len = 0;
760 u16 uuid16_list[HCI_MAX_EIR_LENGTH / sizeof(u16)];
761 int i, truncated = 0;
762 struct list_head *p;
763 size_t name_len;
764
Bhasker Netia6e6a4f2012-01-27 15:25:43 +0530765 name_len = strnlen(hdev->dev_name, HCI_MAX_EIR_LENGTH);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300766
767 if (name_len > 0) {
768 /* EIR Data type */
769 if (name_len > 48) {
770 name_len = 48;
771 ptr[1] = EIR_NAME_SHORT;
772 } else
773 ptr[1] = EIR_NAME_COMPLETE;
774
775 /* EIR Data length */
776 ptr[0] = name_len + 1;
777
778 memcpy(ptr + 2, hdev->dev_name, name_len);
779
780 eir_len += (name_len + 2);
781 ptr += (name_len + 2);
782 }
783
784 memset(uuid16_list, 0, sizeof(uuid16_list));
785
786 /* Group all UUID16 types */
787 list_for_each(p, &hdev->uuids) {
788 struct bt_uuid *uuid = list_entry(p, struct bt_uuid, list);
789 u16 uuid16;
790
791 uuid16 = get_uuid16(uuid->uuid);
792 if (uuid16 == 0)
793 return;
794
795 if (uuid16 < 0x1100)
796 continue;
797
798 if (uuid16 == PNP_INFO_SVCLASS_ID)
799 continue;
800
801 /* Stop if not enough space to put next UUID */
802 if (eir_len + 2 + sizeof(u16) > HCI_MAX_EIR_LENGTH) {
803 truncated = 1;
804 break;
805 }
806
807 /* Check for duplicates */
808 for (i = 0; uuid16_list[i] != 0; i++)
809 if (uuid16_list[i] == uuid16)
810 break;
811
812 if (uuid16_list[i] == 0) {
813 uuid16_list[i] = uuid16;
814 eir_len += sizeof(u16);
815 }
816 }
817
818 if (uuid16_list[0] != 0) {
819 u8 *length = ptr;
820
821 /* EIR Data type */
822 ptr[1] = truncated ? EIR_UUID16_SOME : EIR_UUID16_ALL;
823
824 ptr += 2;
825 eir_len += 2;
826
827 for (i = 0; uuid16_list[i] != 0; i++) {
828 *ptr++ = (uuid16_list[i] & 0x00ff);
829 *ptr++ = (uuid16_list[i] & 0xff00) >> 8;
830 }
831
832 /* EIR Data length */
833 *length = (i * sizeof(u16)) + 1;
834 }
835}
836
837static int update_eir(struct hci_dev *hdev)
838{
839 struct hci_cp_write_eir cp;
840
841 if (!(hdev->features[6] & LMP_EXT_INQ))
842 return 0;
843
844 if (hdev->ssp_mode == 0)
845 return 0;
846
847 if (test_bit(HCI_SERVICE_CACHE, &hdev->flags))
848 return 0;
849
850 memset(&cp, 0, sizeof(cp));
851
852 create_eir(hdev, cp.data);
853
854 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
855 return 0;
856
857 memcpy(hdev->eir, cp.data, sizeof(cp.data));
858
859 return hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
860}
861
Szymon Janc4e51eae2011-02-25 19:05:48 +0100862static int add_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +0200863{
864 struct mgmt_cp_add_uuid *cp;
865 struct hci_dev *hdev;
866 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +0200867 int err;
868
869 cp = (void *) data;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +0200870
Szymon Janc4e51eae2011-02-25 19:05:48 +0100871 BT_DBG("request for hci%u", index);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +0200872
Szymon Jancbdce7ba2011-02-25 19:05:49 +0100873 if (len != sizeof(*cp))
874 return cmd_status(sk, index, MGMT_OP_ADD_UUID, EINVAL);
875
Szymon Janc4e51eae2011-02-25 19:05:48 +0100876 hdev = hci_dev_get(index);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +0200877 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +0100878 return cmd_status(sk, index, MGMT_OP_ADD_UUID, ENODEV);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +0200879
Subramanian Srinivasana727a492011-11-30 13:06:07 -0800880 hci_dev_lock_bh(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +0200881
882 uuid = kmalloc(sizeof(*uuid), GFP_ATOMIC);
883 if (!uuid) {
884 err = -ENOMEM;
885 goto failed;
886 }
887
888 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200889 uuid->svc_hint = cp->svc_hint;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +0200890
891 list_add(&uuid->list, &hdev->uuids);
892
Bhasker Netia6e6a4f2012-01-27 15:25:43 +0530893 if (test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200894
Bhasker Netia6e6a4f2012-01-27 15:25:43 +0530895 err = update_class(hdev);
896 if (err < 0)
897 goto failed;
898
899 err = update_eir(hdev);
900 if (err < 0)
901 goto failed;
902 } else
903 err = 0;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300904
Szymon Janc4e51eae2011-02-25 19:05:48 +0100905 err = cmd_complete(sk, index, MGMT_OP_ADD_UUID, NULL, 0);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +0200906
907failed:
Subramanian Srinivasana727a492011-11-30 13:06:07 -0800908 hci_dev_unlock_bh(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +0200909 hci_dev_put(hdev);
910
911 return err;
912}
913
Szymon Janc4e51eae2011-02-25 19:05:48 +0100914static int remove_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +0200915{
916 struct list_head *p, *n;
Szymon Janc779cb852011-02-25 19:05:47 +0100917 struct mgmt_cp_remove_uuid *cp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +0200918 struct hci_dev *hdev;
919 u8 bt_uuid_any[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
Johan Hedberg2aeb9a12011-01-04 12:08:51 +0200920 int err, found;
921
922 cp = (void *) data;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +0200923
Szymon Janc4e51eae2011-02-25 19:05:48 +0100924 BT_DBG("request for hci%u", index);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +0200925
Szymon Jancbdce7ba2011-02-25 19:05:49 +0100926 if (len != sizeof(*cp))
927 return cmd_status(sk, index, MGMT_OP_REMOVE_UUID, EINVAL);
928
Szymon Janc4e51eae2011-02-25 19:05:48 +0100929 hdev = hci_dev_get(index);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +0200930 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +0100931 return cmd_status(sk, index, MGMT_OP_REMOVE_UUID, ENODEV);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +0200932
Subramanian Srinivasana727a492011-11-30 13:06:07 -0800933 hci_dev_lock_bh(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +0200934
935 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
936 err = hci_uuids_clear(hdev);
937 goto unlock;
938 }
939
940 found = 0;
941
942 list_for_each_safe(p, n, &hdev->uuids) {
943 struct bt_uuid *match = list_entry(p, struct bt_uuid, list);
944
945 if (memcmp(match->uuid, cp->uuid, 16) != 0)
946 continue;
947
948 list_del(&match->list);
949 found++;
950 }
951
952 if (found == 0) {
Szymon Janc4e51eae2011-02-25 19:05:48 +0100953 err = cmd_status(sk, index, MGMT_OP_REMOVE_UUID, ENOENT);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +0200954 goto unlock;
955 }
956
Bhasker Netia6e6a4f2012-01-27 15:25:43 +0530957 if (test_bit(HCI_UP, &hdev->flags)) {
958 err = update_class(hdev);
959 if (err < 0)
960 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200961
Bhasker Netia6e6a4f2012-01-27 15:25:43 +0530962 err = update_eir(hdev);
963 if (err < 0)
964 goto unlock;
965 } else
966 err = 0;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300967
Szymon Janc4e51eae2011-02-25 19:05:48 +0100968 err = cmd_complete(sk, index, MGMT_OP_REMOVE_UUID, NULL, 0);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +0200969
970unlock:
Subramanian Srinivasana727a492011-11-30 13:06:07 -0800971 hci_dev_unlock_bh(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +0200972 hci_dev_put(hdev);
973
974 return err;
975}
976
Szymon Janc4e51eae2011-02-25 19:05:48 +0100977static int set_dev_class(struct sock *sk, u16 index, unsigned char *data,
978 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200979{
980 struct hci_dev *hdev;
981 struct mgmt_cp_set_dev_class *cp;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200982 int err;
983
984 cp = (void *) data;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200985
Szymon Janc4e51eae2011-02-25 19:05:48 +0100986 BT_DBG("request for hci%u", index);
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200987
Szymon Jancbdce7ba2011-02-25 19:05:49 +0100988 if (len != sizeof(*cp))
989 return cmd_status(sk, index, MGMT_OP_SET_DEV_CLASS, EINVAL);
990
Szymon Janc4e51eae2011-02-25 19:05:48 +0100991 hdev = hci_dev_get(index);
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200992 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +0100993 return cmd_status(sk, index, MGMT_OP_SET_DEV_CLASS, ENODEV);
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200994
Subramanian Srinivasana727a492011-11-30 13:06:07 -0800995 hci_dev_lock_bh(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200996
Brian Gix8a7f1642011-10-17 17:39:46 -0700997 hdev->major_class &= ~MGMT_MAJOR_CLASS_MASK;
998 hdev->major_class |= cp->major & MGMT_MAJOR_CLASS_MASK;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200999 hdev->minor_class = cp->minor;
1000
Bhasker Netia6e6a4f2012-01-27 15:25:43 +05301001 if (test_bit(HCI_UP, &hdev->flags))
1002 err = update_class(hdev);
1003 else
1004 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001005
1006 if (err == 0)
Szymon Janc4e51eae2011-02-25 19:05:48 +01001007 err = cmd_complete(sk, index, MGMT_OP_SET_DEV_CLASS, NULL, 0);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001008
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001009 hci_dev_unlock_bh(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001010 hci_dev_put(hdev);
1011
1012 return err;
1013}
1014
Szymon Janc4e51eae2011-02-25 19:05:48 +01001015static int set_service_cache(struct sock *sk, u16 index, unsigned char *data,
1016 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001017{
1018 struct hci_dev *hdev;
1019 struct mgmt_cp_set_service_cache *cp;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001020 int err;
1021
1022 cp = (void *) data;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001023
Szymon Jancbdce7ba2011-02-25 19:05:49 +01001024 if (len != sizeof(*cp))
Szymon Jancb8534e02011-03-01 16:55:34 +01001025 return cmd_status(sk, index, MGMT_OP_SET_SERVICE_CACHE, EINVAL);
Szymon Jancbdce7ba2011-02-25 19:05:49 +01001026
Szymon Janc4e51eae2011-02-25 19:05:48 +01001027 hdev = hci_dev_get(index);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001028 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +01001029 return cmd_status(sk, index, MGMT_OP_SET_SERVICE_CACHE, ENODEV);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001030
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001031 hci_dev_lock_bh(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001032
Szymon Janc4e51eae2011-02-25 19:05:48 +01001033 BT_DBG("hci%u enable %d", index, cp->enable);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001034
1035 if (cp->enable) {
1036 set_bit(HCI_SERVICE_CACHE, &hdev->flags);
1037 err = 0;
1038 } else {
1039 clear_bit(HCI_SERVICE_CACHE, &hdev->flags);
Bhasker Netia6e6a4f2012-01-27 15:25:43 +05301040 if (test_bit(HCI_UP, &hdev->flags)) {
1041 err = update_class(hdev);
1042 if (err == 0)
1043 err = update_eir(hdev);
1044 } else
1045 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001046 }
1047
1048 if (err == 0)
Szymon Janc4e51eae2011-02-25 19:05:48 +01001049 err = cmd_complete(sk, index, MGMT_OP_SET_SERVICE_CACHE, NULL,
1050 0);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001051
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001052 hci_dev_unlock_bh(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001053 hci_dev_put(hdev);
1054
1055 return err;
1056}
1057
Szymon Janc4e51eae2011-02-25 19:05:48 +01001058static int load_keys(struct sock *sk, u16 index, unsigned char *data, u16 len)
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02001059{
1060 struct hci_dev *hdev;
1061 struct mgmt_cp_load_keys *cp;
Szymon Janc4e51eae2011-02-25 19:05:48 +01001062 u16 key_count, expected_len;
Vinicius Costa Gomesc00ddbf2011-07-08 18:31:44 -03001063 int i, err;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02001064
1065 cp = (void *) data;
Szymon Jancbdce7ba2011-02-25 19:05:49 +01001066
1067 if (len < sizeof(*cp))
1068 return -EINVAL;
1069
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02001070 key_count = get_unaligned_le16(&cp->key_count);
1071
1072 expected_len = sizeof(*cp) + key_count * sizeof(struct mgmt_key_info);
Vinicius Costa Gomesc00ddbf2011-07-08 18:31:44 -03001073 if (expected_len > len) {
1074 BT_ERR("load_keys: expected at least %u bytes, got %u bytes",
1075 expected_len, len);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02001076 return -EINVAL;
1077 }
1078
Szymon Janc4e51eae2011-02-25 19:05:48 +01001079 hdev = hci_dev_get(index);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02001080 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +01001081 return cmd_status(sk, index, MGMT_OP_LOAD_KEYS, ENODEV);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02001082
Szymon Janc4e51eae2011-02-25 19:05:48 +01001083 BT_DBG("hci%u debug_keys %u key_count %u", index, cp->debug_keys,
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02001084 key_count);
1085
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001086 hci_dev_lock_bh(hdev);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02001087
1088 hci_link_keys_clear(hdev);
1089
1090 set_bit(HCI_LINK_KEYS, &hdev->flags);
1091
1092 if (cp->debug_keys)
1093 set_bit(HCI_DEBUG_KEYS, &hdev->flags);
1094 else
1095 clear_bit(HCI_DEBUG_KEYS, &hdev->flags);
1096
Vinicius Costa Gomesc00ddbf2011-07-08 18:31:44 -03001097 len -= sizeof(*cp);
1098 i = 0;
1099
1100 while (i < len) {
1101 struct mgmt_key_info *key = (void *) cp->keys + i;
1102
Brian Gixa68668b2011-08-11 15:49:36 -07001103 i += sizeof(*key);
Vinicius Costa Gomesc00ddbf2011-07-08 18:31:44 -03001104
Brian Gixcf956772011-10-20 15:18:51 -07001105 if (key->key_type == KEY_TYPE_LTK) {
Vinicius Costa Gomesc00ddbf2011-07-08 18:31:44 -03001106 struct key_master_id *id = (void *) key->data;
1107
1108 if (key->dlen != sizeof(struct key_master_id))
1109 continue;
1110
Brian Gixcf956772011-10-20 15:18:51 -07001111 hci_add_ltk(hdev, 0, &key->bdaddr, key->addr_type,
1112 key->pin_len, key->auth, id->ediv,
1113 id->rand, key->val);
Vinicius Costa Gomesc00ddbf2011-07-08 18:31:44 -03001114
1115 continue;
1116 }
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02001117
Brian Gixcf956772011-10-20 15:18:51 -07001118 hci_add_link_key(hdev, 0, &key->bdaddr, key->val, key->key_type,
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02001119 key->pin_len);
1120 }
1121
Vinicius Costa Gomesc00ddbf2011-07-08 18:31:44 -03001122 err = cmd_complete(sk, index, MGMT_OP_LOAD_KEYS, NULL, 0);
1123
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001124 hci_dev_unlock_bh(hdev);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02001125 hci_dev_put(hdev);
1126
Vinicius Costa Gomesc00ddbf2011-07-08 18:31:44 -03001127 return err;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02001128}
1129
Szymon Janc4e51eae2011-02-25 19:05:48 +01001130static int remove_key(struct sock *sk, u16 index, unsigned char *data, u16 len)
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02001131{
1132 struct hci_dev *hdev;
1133 struct mgmt_cp_remove_key *cp;
1134 struct hci_conn *conn;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02001135 int err;
1136
1137 cp = (void *) data;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02001138
Szymon Jancbdce7ba2011-02-25 19:05:49 +01001139 if (len != sizeof(*cp))
1140 return cmd_status(sk, index, MGMT_OP_REMOVE_KEY, EINVAL);
1141
Szymon Janc4e51eae2011-02-25 19:05:48 +01001142 hdev = hci_dev_get(index);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02001143 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +01001144 return cmd_status(sk, index, MGMT_OP_REMOVE_KEY, ENODEV);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02001145
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001146 hci_dev_lock_bh(hdev);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02001147
1148 err = hci_remove_link_key(hdev, &cp->bdaddr);
1149 if (err < 0) {
Szymon Janc4e51eae2011-02-25 19:05:48 +01001150 err = cmd_status(sk, index, MGMT_OP_REMOVE_KEY, -err);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02001151 goto unlock;
1152 }
1153
1154 err = 0;
1155
1156 if (!test_bit(HCI_UP, &hdev->flags) || !cp->disconnect)
1157 goto unlock;
1158
1159 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1160 if (conn) {
1161 struct hci_cp_disconnect dc;
1162
1163 put_unaligned_le16(conn->handle, &dc.handle);
1164 dc.reason = 0x13; /* Remote User Terminated Connection */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001165 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, 0, NULL);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02001166 }
1167
1168unlock:
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001169 hci_dev_unlock_bh(hdev);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02001170 hci_dev_put(hdev);
1171
1172 return err;
1173}
1174
Szymon Janc4e51eae2011-02-25 19:05:48 +01001175static int disconnect(struct sock *sk, u16 index, unsigned char *data, u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02001176{
1177 struct hci_dev *hdev;
1178 struct mgmt_cp_disconnect *cp;
1179 struct hci_cp_disconnect dc;
Johan Hedberg366a0332011-02-19 12:05:55 -03001180 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02001181 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02001182 int err;
1183
1184 BT_DBG("");
1185
1186 cp = (void *) data;
Johan Hedberg8962ee72011-01-20 12:40:27 +02001187
Szymon Jancbdce7ba2011-02-25 19:05:49 +01001188 if (len != sizeof(*cp))
1189 return cmd_status(sk, index, MGMT_OP_DISCONNECT, EINVAL);
1190
Szymon Janc4e51eae2011-02-25 19:05:48 +01001191 hdev = hci_dev_get(index);
Johan Hedberg8962ee72011-01-20 12:40:27 +02001192 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +01001193 return cmd_status(sk, index, MGMT_OP_DISCONNECT, ENODEV);
Johan Hedberg8962ee72011-01-20 12:40:27 +02001194
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001195 hci_dev_lock_bh(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02001196
1197 if (!test_bit(HCI_UP, &hdev->flags)) {
Szymon Janc4e51eae2011-02-25 19:05:48 +01001198 err = cmd_status(sk, index, MGMT_OP_DISCONNECT, ENETDOWN);
Johan Hedberg8962ee72011-01-20 12:40:27 +02001199 goto failed;
1200 }
1201
Szymon Janc4e51eae2011-02-25 19:05:48 +01001202 if (mgmt_pending_find(MGMT_OP_DISCONNECT, index)) {
1203 err = cmd_status(sk, index, MGMT_OP_DISCONNECT, EBUSY);
Johan Hedberg8962ee72011-01-20 12:40:27 +02001204 goto failed;
1205 }
1206
1207 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1208 if (!conn) {
Inga Stotlandbd6a49a2011-08-23 16:13:39 -07001209 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->bdaddr);
1210 if (!conn) {
1211 err = cmd_status(sk, index, MGMT_OP_DISCONNECT,
1212 ENOTCONN);
1213 goto failed;
1214 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02001215 }
1216
Szymon Janc4e51eae2011-02-25 19:05:48 +01001217 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, index, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03001218 if (!cmd) {
1219 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02001220 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03001221 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02001222
1223 put_unaligned_le16(conn->handle, &dc.handle);
1224 dc.reason = 0x13; /* Remote User Terminated Connection */
1225
1226 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1227 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03001228 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02001229
1230failed:
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001231 hci_dev_unlock_bh(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02001232 hci_dev_put(hdev);
1233
1234 return err;
1235}
1236
Szymon Janc8ce62842011-03-01 16:55:32 +01001237static int get_connections(struct sock *sk, u16 index)
Johan Hedberg2784eb42011-01-21 13:56:35 +02001238{
Johan Hedberg2784eb42011-01-21 13:56:35 +02001239 struct mgmt_rp_get_connections *rp;
1240 struct hci_dev *hdev;
1241 struct list_head *p;
Johan Hedberga38528f2011-01-22 06:46:43 +02001242 size_t rp_len;
Szymon Janc4e51eae2011-02-25 19:05:48 +01001243 u16 count;
Johan Hedberg2784eb42011-01-21 13:56:35 +02001244 int i, err;
1245
1246 BT_DBG("");
1247
Szymon Janc4e51eae2011-02-25 19:05:48 +01001248 hdev = hci_dev_get(index);
Johan Hedberg2784eb42011-01-21 13:56:35 +02001249 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +01001250 return cmd_status(sk, index, MGMT_OP_GET_CONNECTIONS, ENODEV);
Johan Hedberg2784eb42011-01-21 13:56:35 +02001251
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001252 hci_dev_lock_bh(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02001253
1254 count = 0;
1255 list_for_each(p, &hdev->conn_hash.list) {
1256 count++;
1257 }
1258
Johan Hedberga38528f2011-01-22 06:46:43 +02001259 rp_len = sizeof(*rp) + (count * sizeof(bdaddr_t));
1260 rp = kmalloc(rp_len, GFP_ATOMIC);
1261 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02001262 err = -ENOMEM;
1263 goto unlock;
1264 }
1265
Johan Hedberg2784eb42011-01-21 13:56:35 +02001266 put_unaligned_le16(count, &rp->conn_count);
1267
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001268 read_lock(&hci_dev_list_lock);
1269
Johan Hedberg2784eb42011-01-21 13:56:35 +02001270 i = 0;
1271 list_for_each(p, &hdev->conn_hash.list) {
1272 struct hci_conn *c = list_entry(p, struct hci_conn, list);
1273
1274 bacpy(&rp->conn[i++], &c->dst);
1275 }
1276
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001277 read_unlock(&hci_dev_list_lock);
1278
Szymon Janc4e51eae2011-02-25 19:05:48 +01001279 err = cmd_complete(sk, index, MGMT_OP_GET_CONNECTIONS, rp, rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02001280
1281unlock:
Johan Hedberga38528f2011-01-22 06:46:43 +02001282 kfree(rp);
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001283 hci_dev_unlock_bh(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02001284 hci_dev_put(hdev);
1285 return err;
1286}
1287
Szymon Janc4e51eae2011-02-25 19:05:48 +01001288static int pin_code_reply(struct sock *sk, u16 index, unsigned char *data,
1289 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02001290{
1291 struct hci_dev *hdev;
1292 struct mgmt_cp_pin_code_reply *cp;
1293 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03001294 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02001295 int err;
1296
1297 BT_DBG("");
1298
1299 cp = (void *) data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02001300
Szymon Jancbdce7ba2011-02-25 19:05:49 +01001301 if (len != sizeof(*cp))
1302 return cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, EINVAL);
1303
Szymon Janc4e51eae2011-02-25 19:05:48 +01001304 hdev = hci_dev_get(index);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001305 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +01001306 return cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, ENODEV);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001307
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001308 hci_dev_lock_bh(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001309
1310 if (!test_bit(HCI_UP, &hdev->flags)) {
Szymon Janc4e51eae2011-02-25 19:05:48 +01001311 err = cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, ENETDOWN);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001312 goto failed;
1313 }
1314
Szymon Janc4e51eae2011-02-25 19:05:48 +01001315 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, index, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03001316 if (!cmd) {
1317 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02001318 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03001319 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02001320
1321 bacpy(&reply.bdaddr, &cp->bdaddr);
1322 reply.pin_len = cp->pin_len;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001323 memcpy(reply.pin_code, cp->pin_code, 16);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001324
1325 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
1326 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03001327 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001328
1329failed:
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001330 hci_dev_unlock_bh(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001331 hci_dev_put(hdev);
1332
1333 return err;
1334}
1335
Prabhakaran Mc46230fa2011-11-30 18:11:21 +05301336static int encrypt_link(struct sock *sk, u16 index, unsigned char *data,
1337 u16 len)
1338{
1339 struct hci_dev *hdev;
1340 struct mgmt_cp_encrypt_link *cp;
1341 struct hci_cp_set_conn_encrypt enc;
1342 struct hci_conn *conn;
1343 int err = 0;
1344
1345 BT_DBG("");
1346
1347 cp = (void *) data;
1348
1349 if (len != sizeof(*cp))
1350 return cmd_status(sk, index, MGMT_OP_ENCRYPT_LINK, EINVAL);
1351
1352 hdev = hci_dev_get(index);
1353 if (!hdev)
1354 return cmd_status(sk, index, MGMT_OP_ENCRYPT_LINK, ENODEV);
1355
1356 hci_dev_lock(hdev);
1357
1358 if (!test_bit(HCI_UP, &hdev->flags)) {
1359 err = cmd_status(sk, index, MGMT_OP_ENCRYPT_LINK, ENETDOWN);
1360 goto failed;
1361 }
1362
1363 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
1364 &cp->bdaddr);
1365 if (!conn)
1366 return cmd_status(sk, index, MGMT_OP_ENCRYPT_LINK, ENOTCONN);
1367
1368 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend))
1369 return cmd_status(sk, index, MGMT_OP_ENCRYPT_LINK, EINPROGRESS);
1370
1371 if (conn->link_mode & HCI_LM_AUTH) {
1372 enc.handle = cpu_to_le16(conn->handle);
1373 enc.encrypt = cp->enable;
1374 err = hci_send_cmd(hdev,
1375 HCI_OP_SET_CONN_ENCRYPT, sizeof(enc), &enc);
1376 } else {
1377 conn->auth_initiator = 1;
1378 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
1379 struct hci_cp_auth_requested cp;
1380 cp.handle = cpu_to_le16(conn->handle);
1381 err = hci_send_cmd(conn->hdev,
1382 HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1383 }
1384 }
1385
1386failed:
1387 hci_dev_unlock(hdev);
1388 hci_dev_put(hdev);
1389
1390 return err;
1391}
1392
1393
Szymon Janc4e51eae2011-02-25 19:05:48 +01001394static int pin_code_neg_reply(struct sock *sk, u16 index, unsigned char *data,
1395 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02001396{
1397 struct hci_dev *hdev;
1398 struct mgmt_cp_pin_code_neg_reply *cp;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001399 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02001400 int err;
1401
1402 BT_DBG("");
1403
1404 cp = (void *) data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02001405
Szymon Jancbdce7ba2011-02-25 19:05:49 +01001406 if (len != sizeof(*cp))
1407 return cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY,
1408 EINVAL);
1409
Szymon Janc4e51eae2011-02-25 19:05:48 +01001410 hdev = hci_dev_get(index);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001411 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +01001412 return cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY,
1413 ENODEV);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001414
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001415 hci_dev_lock_bh(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001416
1417 if (!test_bit(HCI_UP, &hdev->flags)) {
Szymon Janc4e51eae2011-02-25 19:05:48 +01001418 err = cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY,
1419 ENETDOWN);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001420 goto failed;
1421 }
1422
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001423 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, index,
1424 data, len);
1425 if (!cmd) {
1426 err = -ENOMEM;
1427 goto failed;
1428 }
1429
1430 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, sizeof(cp->bdaddr),
1431 &cp->bdaddr);
1432 if (err < 0)
1433 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001434
1435failed:
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001436 hci_dev_unlock_bh(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001437 hci_dev_put(hdev);
1438
1439 return err;
1440}
1441
Szymon Janc4e51eae2011-02-25 19:05:48 +01001442static int set_io_capability(struct sock *sk, u16 index, unsigned char *data,
1443 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02001444{
1445 struct hci_dev *hdev;
1446 struct mgmt_cp_set_io_capability *cp;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02001447
1448 BT_DBG("");
1449
1450 cp = (void *) data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02001451
Szymon Jancbdce7ba2011-02-25 19:05:49 +01001452 if (len != sizeof(*cp))
Szymon Jancb8534e02011-03-01 16:55:34 +01001453 return cmd_status(sk, index, MGMT_OP_SET_IO_CAPABILITY, EINVAL);
Szymon Jancbdce7ba2011-02-25 19:05:49 +01001454
Szymon Janc4e51eae2011-02-25 19:05:48 +01001455 hdev = hci_dev_get(index);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02001456 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +01001457 return cmd_status(sk, index, MGMT_OP_SET_IO_CAPABILITY, ENODEV);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02001458
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001459 hci_dev_lock_bh(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02001460
1461 hdev->io_capability = cp->io_capability;
1462
1463 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Szymon Jancb8534e02011-03-01 16:55:34 +01001464 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02001465
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001466 hci_dev_unlock_bh(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02001467 hci_dev_put(hdev);
1468
Szymon Janc4e51eae2011-02-25 19:05:48 +01001469 return cmd_complete(sk, index, MGMT_OP_SET_IO_CAPABILITY, NULL, 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02001470}
1471
Johan Hedberge9a416b2011-02-19 12:05:56 -03001472static inline struct pending_cmd *find_pairing(struct hci_conn *conn)
1473{
1474 struct hci_dev *hdev = conn->hdev;
1475 struct list_head *p;
1476
1477 list_for_each(p, &cmd_list) {
1478 struct pending_cmd *cmd;
1479
1480 cmd = list_entry(p, struct pending_cmd, list);
1481
1482 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
1483 continue;
1484
1485 if (cmd->index != hdev->id)
1486 continue;
1487
1488 if (cmd->user_data != conn)
1489 continue;
1490
1491 return cmd;
1492 }
1493
1494 return NULL;
1495}
1496
1497static void pairing_complete(struct pending_cmd *cmd, u8 status)
1498{
1499 struct mgmt_rp_pair_device rp;
1500 struct hci_conn *conn = cmd->user_data;
1501
Brian Gixa68668b2011-08-11 15:49:36 -07001502 BT_DBG(" %u", status);
1503
Johan Hedberge9a416b2011-02-19 12:05:56 -03001504 bacpy(&rp.bdaddr, &conn->dst);
1505 rp.status = status;
1506
Szymon Janc4e51eae2011-02-25 19:05:48 +01001507 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03001508
1509 /* So we don't get further callbacks for this connection */
1510 conn->connect_cfm_cb = NULL;
1511 conn->security_cfm_cb = NULL;
1512 conn->disconn_cfm_cb = NULL;
1513
Johan Hedberga664b5b2011-02-19 12:06:02 -03001514 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03001515}
1516
1517static void pairing_complete_cb(struct hci_conn *conn, u8 status)
1518{
1519 struct pending_cmd *cmd;
1520
Brian Gixa68668b2011-08-11 15:49:36 -07001521 BT_DBG(" %u", status);
Johan Hedberge9a416b2011-02-19 12:05:56 -03001522
1523 cmd = find_pairing(conn);
1524 if (!cmd) {
1525 BT_DBG("Unable to find a pending command");
1526 return;
1527 }
1528
1529 pairing_complete(cmd, status);
1530}
1531
Brian Gix6d5fb8a2011-09-09 14:53:04 -07001532static void pairing_security_complete_cb(struct hci_conn *conn, u8 status)
Brian Gixa68668b2011-08-11 15:49:36 -07001533{
1534 struct pending_cmd *cmd;
1535
1536 BT_DBG(" %u", status);
1537
1538 cmd = find_pairing(conn);
1539 if (!cmd) {
1540 BT_DBG("Unable to find a pending command");
1541 return;
1542 }
1543
1544 if (conn->type == LE_LINK)
1545 smp_link_encrypt_cmplt(conn->l2cap_data, status,
1546 status ? 0 : 1);
1547 else
1548 pairing_complete(cmd, status);
1549}
1550
Brian Gix6d5fb8a2011-09-09 14:53:04 -07001551static void pairing_connect_complete_cb(struct hci_conn *conn, u8 status)
Brian Gixa68668b2011-08-11 15:49:36 -07001552{
1553 struct pending_cmd *cmd;
1554
1555 BT_DBG("conn: %p %u", conn, status);
1556
1557 cmd = find_pairing(conn);
1558 if (!cmd) {
1559 BT_DBG("Unable to find a pending command");
1560 return;
1561 }
Brian Gix114f3a62011-09-27 14:02:20 -07001562
1563 if (status)
1564 pairing_complete(cmd, status);
1565
Brian Gix6d5fb8a2011-09-09 14:53:04 -07001566 hci_conn_put(conn);
Brian Gixa68668b2011-08-11 15:49:36 -07001567}
1568
1569static void discovery_terminated(struct pending_cmd *cmd, void *data)
1570{
Brian Gix6e349d02011-11-28 14:51:14 -08001571 struct hci_dev *hdev;
Brian Gixa68668b2011-08-11 15:49:36 -07001572 struct mgmt_mode ev = {0};
Brian Gixa68668b2011-08-11 15:49:36 -07001573
1574 BT_DBG("");
Brian Gix6e349d02011-11-28 14:51:14 -08001575 hdev = hci_dev_get(cmd->index);
1576 if (!hdev)
1577 goto not_found;
1578
Brian Gix568dde92012-01-11 16:18:04 -08001579 del_timer(&hdev->disco_le_timer);
1580 del_timer(&hdev->disco_timer);
Brian Gix6e349d02011-11-28 14:51:14 -08001581 hci_dev_put(hdev);
1582
1583not_found:
Brian Gixa68668b2011-08-11 15:49:36 -07001584 mgmt_event(MGMT_EV_DISCOVERING, cmd->index, &ev, sizeof(ev), NULL);
1585
1586 list_del(&cmd->list);
1587
1588 mgmt_pending_free(cmd);
1589}
1590
Szymon Janc4e51eae2011-02-25 19:05:48 +01001591static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03001592{
1593 struct hci_dev *hdev;
1594 struct mgmt_cp_pair_device *cp;
1595 struct pending_cmd *cmd;
Brian Gixa68668b2011-08-11 15:49:36 -07001596 u8 sec_level, auth_type, io_cap;
Johan Hedberge9a416b2011-02-19 12:05:56 -03001597 struct hci_conn *conn;
Brian Gixfdd38922011-09-28 16:23:48 -07001598 struct adv_entry *entry;
Johan Hedberge9a416b2011-02-19 12:05:56 -03001599 int err;
1600
1601 BT_DBG("");
1602
Brian Gix64bd5302011-09-08 11:35:48 -07001603 cp = (void *) data;
1604
1605 if (len != sizeof(*cp))
1606 return cmd_status(sk, index, MGMT_OP_PAIR_DEVICE, EINVAL);
1607
Szymon Janc4e51eae2011-02-25 19:05:48 +01001608 hdev = hci_dev_get(index);
Brian Gixa68668b2011-08-11 15:49:36 -07001609
Johan Hedberge9a416b2011-02-19 12:05:56 -03001610 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +01001611 return cmd_status(sk, index, MGMT_OP_PAIR_DEVICE, ENODEV);
Johan Hedberge9a416b2011-02-19 12:05:56 -03001612
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001613 hci_dev_lock_bh(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03001614
Prabhakaran Mc6001a712011-09-06 11:56:25 +05301615 BT_DBG("SSP Cap is %d", cp->ssp_cap);
1616 io_cap = cp->io_cap;
1617 if ((cp->ssp_cap == 0) || (io_cap == 0x03)) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03001618 sec_level = BT_SECURITY_MEDIUM;
1619 auth_type = HCI_AT_DEDICATED_BONDING;
1620 } else {
1621 sec_level = BT_SECURITY_HIGH;
1622 auth_type = HCI_AT_DEDICATED_BONDING_MITM;
1623 }
1624
Brian Gixfdd38922011-09-28 16:23:48 -07001625 entry = hci_find_adv_entry(hdev, &cp->bdaddr);
1626 if (entry && entry->flags & 0x04) {
Brian Gixa68668b2011-08-11 15:49:36 -07001627 conn = hci_connect(hdev, LE_LINK, 0, &cp->bdaddr, sec_level,
1628 auth_type);
Brian Gixa68668b2011-08-11 15:49:36 -07001629 } else {
1630 /* ACL-SSP does not support io_cap 0x04 (KeyboadDisplay) */
1631 if (io_cap == 0x04)
1632 io_cap = 0x01;
1633 conn = hci_connect(hdev, ACL_LINK, 0, &cp->bdaddr, sec_level,
1634 auth_type);
1635 }
1636
Ville Tervo30e76272011-02-22 16:10:53 -03001637 if (IS_ERR(conn)) {
1638 err = PTR_ERR(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03001639 goto unlock;
1640 }
1641
1642 if (conn->connect_cfm_cb) {
1643 hci_conn_put(conn);
Szymon Janc4e51eae2011-02-25 19:05:48 +01001644 err = cmd_status(sk, index, MGMT_OP_PAIR_DEVICE, EBUSY);
Johan Hedberge9a416b2011-02-19 12:05:56 -03001645 goto unlock;
1646 }
1647
Szymon Janc4e51eae2011-02-25 19:05:48 +01001648 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, index, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03001649 if (!cmd) {
1650 err = -ENOMEM;
1651 hci_conn_put(conn);
1652 goto unlock;
1653 }
1654
Brian Gix6d5fb8a2011-09-09 14:53:04 -07001655 conn->connect_cfm_cb = pairing_connect_complete_cb;
1656 conn->security_cfm_cb = pairing_security_complete_cb;
Johan Hedberge9a416b2011-02-19 12:05:56 -03001657 conn->disconn_cfm_cb = pairing_complete_cb;
Brian Gixa68668b2011-08-11 15:49:36 -07001658 conn->io_capability = io_cap;
Johan Hedberge9a416b2011-02-19 12:05:56 -03001659 cmd->user_data = conn;
1660
1661 if (conn->state == BT_CONNECTED &&
1662 hci_conn_security(conn, sec_level, auth_type))
1663 pairing_complete(cmd, 0);
1664
1665 err = 0;
1666
1667unlock:
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001668 hci_dev_unlock_bh(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03001669 hci_dev_put(hdev);
1670
1671 return err;
1672}
1673
Szymon Janc4e51eae2011-02-25 19:05:48 +01001674static int user_confirm_reply(struct sock *sk, u16 index, unsigned char *data,
Brian Gixa68668b2011-08-11 15:49:36 -07001675 u16 len, u16 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03001676{
1677 struct mgmt_cp_user_confirm_reply *cp = (void *) data;
Brian Gixa68668b2011-08-11 15:49:36 -07001678 u16 mgmt_op = opcode, hci_op;
Johan Hedberga5c29682011-02-19 12:05:57 -03001679 struct pending_cmd *cmd;
1680 struct hci_dev *hdev;
Brian Gixa68668b2011-08-11 15:49:36 -07001681 struct hci_conn *le_conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03001682 int err;
1683
Brian Gixa68668b2011-08-11 15:49:36 -07001684 BT_DBG("%d", mgmt_op);
Johan Hedberga5c29682011-02-19 12:05:57 -03001685
Brian Gixa68668b2011-08-11 15:49:36 -07001686 if (mgmt_op == MGMT_OP_USER_CONFIRM_NEG_REPLY)
Johan Hedberga5c29682011-02-19 12:05:57 -03001687 hci_op = HCI_OP_USER_CONFIRM_NEG_REPLY;
Brian Gixa68668b2011-08-11 15:49:36 -07001688 else
1689 hci_op = HCI_OP_USER_CONFIRM_REPLY;
Johan Hedberga5c29682011-02-19 12:05:57 -03001690
Brian Gixa68668b2011-08-11 15:49:36 -07001691 if (len < sizeof(*cp))
Szymon Jancbdce7ba2011-02-25 19:05:49 +01001692 return cmd_status(sk, index, mgmt_op, EINVAL);
1693
Szymon Janc4e51eae2011-02-25 19:05:48 +01001694 hdev = hci_dev_get(index);
Johan Hedberga5c29682011-02-19 12:05:57 -03001695 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +01001696 return cmd_status(sk, index, mgmt_op, ENODEV);
Johan Hedberga5c29682011-02-19 12:05:57 -03001697
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001698 hci_dev_lock_bh(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02001699
Johan Hedberga5c29682011-02-19 12:05:57 -03001700 if (!test_bit(HCI_UP, &hdev->flags)) {
Szymon Janc4e51eae2011-02-25 19:05:48 +01001701 err = cmd_status(sk, index, mgmt_op, ENETDOWN);
Brian Gixa68668b2011-08-11 15:49:36 -07001702 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03001703 }
1704
Brian Gixa68668b2011-08-11 15:49:36 -07001705 le_conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->bdaddr);
1706 if (le_conn) {
1707 err = le_user_confirm_reply(le_conn, mgmt_op, (void *) cp);
1708 goto done;
1709 }
1710 BT_DBG("BR/EDR: %s", mgmt_op == MGMT_OP_USER_CONFIRM_NEG_REPLY ?
1711 "Reject" : "Accept");
1712
Szymon Janc4e51eae2011-02-25 19:05:48 +01001713 cmd = mgmt_pending_add(sk, mgmt_op, index, data, len);
Johan Hedberga5c29682011-02-19 12:05:57 -03001714 if (!cmd) {
1715 err = -ENOMEM;
Brian Gixa68668b2011-08-11 15:49:36 -07001716 goto done;
1717 }
1718
1719 err = hci_send_cmd(hdev, hci_op, sizeof(cp->bdaddr), &cp->bdaddr);
1720 if (err < 0)
1721 mgmt_pending_remove(cmd);
1722
1723done:
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001724 hci_dev_unlock_bh(hdev);
Brian Gixa68668b2011-08-11 15:49:36 -07001725 hci_dev_put(hdev);
1726
1727 return err;
1728}
1729
1730static int resolve_name(struct sock *sk, u16 index, unsigned char *data,
1731 u16 len)
1732{
1733 struct mgmt_cp_resolve_name *mgmt_cp = (void *) data;
1734 struct hci_cp_remote_name_req hci_cp;
1735 struct hci_dev *hdev;
1736 struct pending_cmd *cmd;
1737 int err;
1738
1739 BT_DBG("");
1740
1741 if (len != sizeof(*mgmt_cp))
1742 return cmd_status(sk, index, MGMT_OP_RESOLVE_NAME, EINVAL);
1743
1744 hdev = hci_dev_get(index);
1745 if (!hdev)
1746 return cmd_status(sk, index, MGMT_OP_RESOLVE_NAME, ENODEV);
1747
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001748 hci_dev_lock_bh(hdev);
Brian Gixa68668b2011-08-11 15:49:36 -07001749
1750 cmd = mgmt_pending_add(sk, MGMT_OP_RESOLVE_NAME, index, data, len);
1751 if (!cmd) {
1752 err = -ENOMEM;
Johan Hedberga5c29682011-02-19 12:05:57 -03001753 goto failed;
1754 }
1755
Brian Gixa68668b2011-08-11 15:49:36 -07001756 memset(&hci_cp, 0, sizeof(hci_cp));
1757 bacpy(&hci_cp.bdaddr, &mgmt_cp->bdaddr);
1758 err = hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(hci_cp),
1759 &hci_cp);
Johan Hedberga664b5b2011-02-19 12:06:02 -03001760 if (err < 0)
1761 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03001762
1763failed:
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001764 hci_dev_unlock_bh(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03001765 hci_dev_put(hdev);
1766
1767 return err;
1768}
1769
Brian Gix7f7e16c2011-11-01 16:27:25 -07001770static int set_connection_params(struct sock *sk, u16 index,
1771 unsigned char *data, u16 len)
1772{
1773 struct mgmt_cp_set_connection_params *cp = (void *) data;
1774 struct hci_dev *hdev;
1775 struct hci_conn *conn;
1776 int err;
1777
1778 BT_DBG("");
1779
1780 if (len != sizeof(*cp))
1781 return cmd_status(sk, index, MGMT_OP_SET_CONNECTION_PARAMS,
1782 EINVAL);
1783
1784 hdev = hci_dev_get(index);
1785 if (!hdev)
1786 return cmd_status(sk, index, MGMT_OP_SET_CONNECTION_PARAMS,
1787 ENODEV);
1788
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001789 hci_dev_lock_bh(hdev);
Brian Gix7f7e16c2011-11-01 16:27:25 -07001790
1791 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->bdaddr);
1792 if (!conn) {
1793 err = cmd_status(sk, index, MGMT_OP_SET_CONNECTION_PARAMS,
1794 ENOTCONN);
1795 goto failed;
1796 }
1797
1798 hci_le_conn_update(conn, le16_to_cpu(cp->interval_min),
1799 le16_to_cpu(cp->interval_max),
1800 le16_to_cpu(cp->slave_latency),
1801 le16_to_cpu(cp->timeout_multiplier));
1802
1803 err = cmd_status(sk, index, MGMT_OP_SET_CONNECTION_PARAMS, 0);
1804
1805failed:
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001806 hci_dev_unlock_bh(hdev);
Brian Gix7f7e16c2011-11-01 16:27:25 -07001807 hci_dev_put(hdev);
1808
1809 return err;
1810}
1811
Johan Hedbergb312b1612011-03-16 14:29:37 +02001812static int set_local_name(struct sock *sk, u16 index, unsigned char *data,
1813 u16 len)
1814{
1815 struct mgmt_cp_set_local_name *mgmt_cp = (void *) data;
1816 struct hci_cp_write_local_name hci_cp;
1817 struct hci_dev *hdev;
1818 struct pending_cmd *cmd;
1819 int err;
1820
1821 BT_DBG("");
1822
1823 if (len != sizeof(*mgmt_cp))
1824 return cmd_status(sk, index, MGMT_OP_SET_LOCAL_NAME, EINVAL);
1825
1826 hdev = hci_dev_get(index);
1827 if (!hdev)
1828 return cmd_status(sk, index, MGMT_OP_SET_LOCAL_NAME, ENODEV);
1829
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001830 hci_dev_lock_bh(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02001831
1832 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, index, data, len);
1833 if (!cmd) {
1834 err = -ENOMEM;
1835 goto failed;
1836 }
1837
1838 memcpy(hci_cp.name, mgmt_cp->name, sizeof(hci_cp.name));
1839 err = hci_send_cmd(hdev, HCI_OP_WRITE_LOCAL_NAME, sizeof(hci_cp),
1840 &hci_cp);
1841 if (err < 0)
1842 mgmt_pending_remove(cmd);
1843
1844failed:
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001845 hci_dev_unlock_bh(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02001846 hci_dev_put(hdev);
1847
1848 return err;
1849}
1850
Brian Gixa68668b2011-08-11 15:49:36 -07001851static void discovery_rsp(struct pending_cmd *cmd, void *data)
1852{
1853 struct mgmt_mode ev;
1854
1855 BT_DBG("");
1856 if (cmd->opcode == MGMT_OP_START_DISCOVERY) {
1857 ev.val = 1;
1858 cmd_status(cmd->sk, cmd->index, MGMT_OP_START_DISCOVERY, 0);
1859 } else {
1860 ev.val = 0;
1861 cmd_complete(cmd->sk, cmd->index, MGMT_OP_STOP_DISCOVERY,
1862 NULL, 0);
1863 if (cmd->opcode == MGMT_OP_STOP_DISCOVERY) {
Brian Gix6e349d02011-11-28 14:51:14 -08001864 struct hci_dev *hdev = hci_dev_get(cmd->index);
1865 if (hdev) {
Brian Gix568dde92012-01-11 16:18:04 -08001866 del_timer(&hdev->disco_le_timer);
1867 del_timer(&hdev->disco_timer);
Brian Gix6e349d02011-11-28 14:51:14 -08001868 hci_dev_put(hdev);
1869 }
Brian Gixa68668b2011-08-11 15:49:36 -07001870 }
1871 }
1872
1873 mgmt_event(MGMT_EV_DISCOVERING, cmd->index, &ev, sizeof(ev), NULL);
1874
1875 list_del(&cmd->list);
1876
1877 mgmt_pending_free(cmd);
1878}
1879
1880void mgmt_inquiry_started(u16 index)
1881{
1882 BT_DBG("");
1883 mgmt_pending_foreach(MGMT_OP_START_DISCOVERY, index,
1884 discovery_rsp, NULL);
1885}
1886
1887void mgmt_inquiry_complete_evt(u16 index, u8 status)
1888{
1889 struct hci_dev *hdev;
1890 struct hci_cp_le_set_scan_enable le_cp = {1, 0};
Brian Gix568dde92012-01-11 16:18:04 -08001891 struct mgmt_mode cp = {0};
Brian Gixa68668b2011-08-11 15:49:36 -07001892 int err = -1;
1893
1894 BT_DBG("");
1895
1896 hdev = hci_dev_get(index);
Brian Gix64bd5302011-09-08 11:35:48 -07001897
Brian Gixa68668b2011-08-11 15:49:36 -07001898 if (!hdev || !lmp_le_capable(hdev)) {
Brian Gixa68668b2011-08-11 15:49:36 -07001899
1900 mgmt_pending_foreach(MGMT_OP_STOP_DISCOVERY, index,
1901 discovery_terminated, NULL);
1902
1903 mgmt_event(MGMT_EV_DISCOVERING, index, &cp, sizeof(cp), NULL);
Brian Gixa68668b2011-08-11 15:49:36 -07001904
Brian Gix64bd5302011-09-08 11:35:48 -07001905 if (hdev)
1906 goto done;
1907 else
1908 return;
1909 }
Brian Gixa68668b2011-08-11 15:49:36 -07001910
Brian Gix568dde92012-01-11 16:18:04 -08001911 if (hdev->disco_state != SCAN_IDLE) {
Brian Gixa68668b2011-08-11 15:49:36 -07001912 err = hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE,
1913 sizeof(le_cp), &le_cp);
Brian Gix568dde92012-01-11 16:18:04 -08001914 if (err >= 0) {
1915 mod_timer(&hdev->disco_le_timer, jiffies +
1916 msecs_to_jiffies(hdev->disco_int_phase * 1000));
1917 hdev->disco_state = SCAN_LE;
Brian Gixa68668b2011-08-11 15:49:36 -07001918 } else
Brian Gix568dde92012-01-11 16:18:04 -08001919 hdev->disco_state = SCAN_IDLE;
Brian Gixa68668b2011-08-11 15:49:36 -07001920 }
1921
Brian Gix568dde92012-01-11 16:18:04 -08001922 if (hdev->disco_state == SCAN_IDLE)
1923 mgmt_event(MGMT_EV_DISCOVERING, index, &cp, sizeof(cp), NULL);
1924
Brian Gixa68668b2011-08-11 15:49:36 -07001925 if (err < 0)
1926 mgmt_pending_foreach(MGMT_OP_STOP_DISCOVERY, index,
1927 discovery_terminated, NULL);
1928
Brian Gix64bd5302011-09-08 11:35:48 -07001929done:
Brian Gixa68668b2011-08-11 15:49:36 -07001930 hci_dev_put(hdev);
1931}
1932
Brian Gix568dde92012-01-11 16:18:04 -08001933void mgmt_disco_timeout(unsigned long data)
Brian Gixa68668b2011-08-11 15:49:36 -07001934{
Brian Gix568dde92012-01-11 16:18:04 -08001935 struct hci_dev *hdev = (void *) data;
Brian Gixa68668b2011-08-11 15:49:36 -07001936 struct pending_cmd *cmd;
Brian Gix568dde92012-01-11 16:18:04 -08001937 struct mgmt_mode cp = {0};
Brian Gixa68668b2011-08-11 15:49:36 -07001938
Brian Gix568dde92012-01-11 16:18:04 -08001939 BT_DBG("hci%d", hdev->id);
Brian Gixa68668b2011-08-11 15:49:36 -07001940
Brian Gix568dde92012-01-11 16:18:04 -08001941 hdev = hci_dev_get(hdev->id);
Brian Gixa68668b2011-08-11 15:49:36 -07001942
Brian Gix568dde92012-01-11 16:18:04 -08001943 if (!hdev)
1944 return;
Brian Gixa68668b2011-08-11 15:49:36 -07001945
Brian Gix568dde92012-01-11 16:18:04 -08001946 hci_dev_lock_bh(hdev);
1947 del_timer(&hdev->disco_le_timer);
Brian Gixa68668b2011-08-11 15:49:36 -07001948
Brian Gix568dde92012-01-11 16:18:04 -08001949 if (hdev->disco_state != SCAN_IDLE) {
1950 struct hci_cp_le_set_scan_enable le_cp = {0, 0};
Brian Gixa68668b2011-08-11 15:49:36 -07001951
Bhasker Netia6e6a4f2012-01-27 15:25:43 +05301952 if (test_bit(HCI_UP, &hdev->flags)) {
1953 if (hdev->disco_state == SCAN_LE)
1954 hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE,
Brian Gixa68668b2011-08-11 15:49:36 -07001955 sizeof(le_cp), &le_cp);
Bhasker Netia6e6a4f2012-01-27 15:25:43 +05301956 else
1957 hci_send_cmd(hdev, HCI_OP_INQUIRY_CANCEL, 0,
1958 NULL);
1959 }
Brian Gix568dde92012-01-11 16:18:04 -08001960 hdev->disco_state = SCAN_IDLE;
Brian Gixa68668b2011-08-11 15:49:36 -07001961 }
Brian Gix568dde92012-01-11 16:18:04 -08001962
1963 mgmt_event(MGMT_EV_DISCOVERING, hdev->id, &cp, sizeof(cp), NULL);
1964
1965 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev->id);
1966 if (cmd)
1967 mgmt_pending_remove(cmd);
1968
1969 hci_dev_unlock_bh(hdev);
1970 hci_dev_put(hdev);
1971}
1972
1973void mgmt_disco_le_timeout(unsigned long data)
1974{
1975 struct hci_dev *hdev = (void *)data;
1976 struct hci_cp_le_set_scan_enable le_cp = {0, 0};
1977
1978 BT_DBG("hci%d", hdev->id);
1979
1980 hdev = hci_dev_get(hdev->id);
1981
1982 if (!hdev)
1983 return;
1984
1985 hci_dev_lock_bh(hdev);
1986
Bhasker Netia6e6a4f2012-01-27 15:25:43 +05301987 if (test_bit(HCI_UP, &hdev->flags)) {
1988 if (hdev->disco_state == SCAN_LE)
1989 hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE,
1990 sizeof(le_cp), &le_cp);
Brian Gix568dde92012-01-11 16:18:04 -08001991
1992 /* re-start BR scan */
Bhasker Netia6e6a4f2012-01-27 15:25:43 +05301993 if (hdev->disco_state != SCAN_IDLE) {
1994 struct hci_cp_inquiry cp = {{0x33, 0x8b, 0x9e}, 4, 0};
1995 hdev->disco_int_phase *= 2;
1996 hdev->disco_int_count = 0;
1997 cp.num_rsp = (u8) hdev->disco_int_phase;
1998 hci_send_cmd(hdev, HCI_OP_INQUIRY, sizeof(cp), &cp);
1999 hdev->disco_state = SCAN_BR;
2000 }
Brian Gix568dde92012-01-11 16:18:04 -08002001 }
2002
2003 hci_dev_unlock_bh(hdev);
2004 hci_dev_put(hdev);
Brian Gixa68668b2011-08-11 15:49:36 -07002005}
2006
2007static int start_discovery(struct sock *sk, u16 index)
2008{
2009 struct hci_cp_inquiry cp = {{0x33, 0x8b, 0x9e}, 8, 0};
2010 struct hci_dev *hdev;
2011 struct pending_cmd *cmd;
2012 int err;
2013
2014 BT_DBG("");
2015
2016 hdev = hci_dev_get(index);
2017 if (!hdev)
2018 return cmd_status(sk, index, MGMT_OP_START_DISCOVERY, ENODEV);
2019
Subramanian Srinivasana727a492011-11-30 13:06:07 -08002020 hci_dev_lock_bh(hdev);
Brian Gixa68668b2011-08-11 15:49:36 -07002021
Brian Gix568dde92012-01-11 16:18:04 -08002022 if (hdev->disco_state && timer_pending(&hdev->disco_timer)) {
2023 err = -EBUSY;
2024 goto failed;
2025 }
2026
Brian Gixa68668b2011-08-11 15:49:36 -07002027 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, index, NULL, 0);
2028 if (!cmd) {
2029 err = -ENOMEM;
2030 goto failed;
2031 }
2032
2033 /* If LE Capable, we will alternate between BR/EDR and LE */
2034 if (lmp_le_capable(hdev)) {
2035 struct hci_cp_le_set_scan_parameters le_cp;
2036
2037 /* Shorten BR scan params */
2038 cp.num_rsp = 1;
2039 cp.length /= 2;
2040
2041 /* Setup LE scan params */
2042 memset(&le_cp, 0, sizeof(le_cp));
2043 le_cp.type = 0x01; /* Active scanning */
2044 /* The recommended value for scan interval and window is
2045 * 11.25 msec. It is calculated by: time = n * 0.625 msec */
2046 le_cp.interval = cpu_to_le16(0x0012);
2047 le_cp.window = cpu_to_le16(0x0012);
2048 le_cp.own_bdaddr_type = 0; /* Public address */
2049 le_cp.filter = 0; /* Accept all adv packets */
2050
2051 hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_PARAMETERS,
2052 sizeof(le_cp), &le_cp);
2053 }
2054
2055 err = hci_send_cmd(hdev, HCI_OP_INQUIRY, sizeof(cp), &cp);
2056
2057 if (err < 0)
2058 mgmt_pending_remove(cmd);
2059 else if (lmp_le_capable(hdev)) {
Brian Gix474e0f22012-01-14 20:21:55 -08002060 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, index);
2061 if (!cmd)
2062 mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, index,
2063 NULL, 0);
Brian Gix568dde92012-01-11 16:18:04 -08002064 hdev->disco_int_phase = 1;
2065 hdev->disco_int_count = 0;
2066 hdev->disco_state = SCAN_BR;
Brian Gix568dde92012-01-11 16:18:04 -08002067 del_timer(&hdev->disco_le_timer);
2068 del_timer(&hdev->disco_timer);
2069 mod_timer(&hdev->disco_timer,
2070 jiffies + msecs_to_jiffies(20000));
Brian Gixa68668b2011-08-11 15:49:36 -07002071 }
2072
2073failed:
Subramanian Srinivasana727a492011-11-30 13:06:07 -08002074 hci_dev_unlock_bh(hdev);
Brian Gixa68668b2011-08-11 15:49:36 -07002075 hci_dev_put(hdev);
2076
Brian Gix568dde92012-01-11 16:18:04 -08002077 if (err < 0)
2078 return cmd_status(sk, index, MGMT_OP_START_DISCOVERY, -err);
2079
Brian Gixa68668b2011-08-11 15:49:36 -07002080 return err;
2081}
2082
2083static int stop_discovery(struct sock *sk, u16 index)
2084{
2085 struct hci_cp_le_set_scan_enable le_cp = {0, 0};
2086 struct mgmt_mode mode_cp = {0};
Brian Gixa68668b2011-08-11 15:49:36 -07002087 struct hci_dev *hdev;
2088 struct pending_cmd *cmd = NULL;
2089 int err = -EPERM;
Brian Gix568dde92012-01-11 16:18:04 -08002090 u8 state;
Brian Gixa68668b2011-08-11 15:49:36 -07002091
2092 BT_DBG("");
2093
2094 hdev = hci_dev_get(index);
2095 if (!hdev)
2096 return cmd_status(sk, index, MGMT_OP_STOP_DISCOVERY, ENODEV);
2097
Subramanian Srinivasana727a492011-11-30 13:06:07 -08002098 hci_dev_lock_bh(hdev);
Brian Gixa68668b2011-08-11 15:49:36 -07002099
Brian Gix568dde92012-01-11 16:18:04 -08002100 state = hdev->disco_state;
2101 hdev->disco_state = SCAN_IDLE;
2102 del_timer(&hdev->disco_le_timer);
2103 del_timer(&hdev->disco_timer);
Brian Gixa68668b2011-08-11 15:49:36 -07002104
Brian Gix568dde92012-01-11 16:18:04 -08002105 if (state == SCAN_LE) {
Brian Gixa68668b2011-08-11 15:49:36 -07002106 err = hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE,
2107 sizeof(le_cp), &le_cp);
Brian Gix568dde92012-01-11 16:18:04 -08002108 if (err >= 0) {
2109 mgmt_pending_foreach(MGMT_OP_STOP_DISCOVERY, index,
2110 discovery_terminated, NULL);
Brian Gixa68668b2011-08-11 15:49:36 -07002111
Brian Gix568dde92012-01-11 16:18:04 -08002112 err = cmd_complete(sk, index, MGMT_OP_STOP_DISCOVERY,
2113 NULL, 0);
2114 }
Brian Gixa68668b2011-08-11 15:49:36 -07002115 }
2116
Brian Gix568dde92012-01-11 16:18:04 -08002117 if (err < 0)
2118 err = hci_send_cmd(hdev, HCI_OP_INQUIRY_CANCEL, 0, NULL);
Brian Gixa68668b2011-08-11 15:49:36 -07002119
Brian Gix568dde92012-01-11 16:18:04 -08002120 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, index);
Brian Gixa68668b2011-08-11 15:49:36 -07002121 if (err < 0 && cmd)
2122 mgmt_pending_remove(cmd);
2123
2124 mgmt_event(MGMT_EV_DISCOVERING, index, &mode_cp, sizeof(mode_cp), NULL);
2125
Subramanian Srinivasana727a492011-11-30 13:06:07 -08002126 hci_dev_unlock_bh(hdev);
Brian Gixa68668b2011-08-11 15:49:36 -07002127 hci_dev_put(hdev);
2128
2129 if (err < 0)
2130 return cmd_status(sk, index, MGMT_OP_STOP_DISCOVERY, -err);
2131 else
2132 return err;
2133}
2134
Szymon Jancc35938b2011-03-22 13:12:21 +01002135static int read_local_oob_data(struct sock *sk, u16 index)
2136{
2137 struct hci_dev *hdev;
2138 struct pending_cmd *cmd;
2139 int err;
2140
2141 BT_DBG("hci%u", index);
2142
2143 hdev = hci_dev_get(index);
2144 if (!hdev)
2145 return cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
2146 ENODEV);
2147
Subramanian Srinivasana727a492011-11-30 13:06:07 -08002148 hci_dev_lock_bh(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01002149
2150 if (!test_bit(HCI_UP, &hdev->flags)) {
2151 err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
2152 ENETDOWN);
2153 goto unlock;
2154 }
2155
2156 if (!(hdev->features[6] & LMP_SIMPLE_PAIR)) {
2157 err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
2158 EOPNOTSUPP);
2159 goto unlock;
2160 }
2161
2162 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, index)) {
2163 err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, EBUSY);
2164 goto unlock;
2165 }
2166
2167 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, index, NULL, 0);
2168 if (!cmd) {
2169 err = -ENOMEM;
2170 goto unlock;
2171 }
2172
2173 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
2174 if (err < 0)
2175 mgmt_pending_remove(cmd);
2176
2177unlock:
Subramanian Srinivasana727a492011-11-30 13:06:07 -08002178 hci_dev_unlock_bh(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01002179 hci_dev_put(hdev);
2180
2181 return err;
2182}
2183
Szymon Janc2763eda2011-03-22 13:12:22 +01002184static int add_remote_oob_data(struct sock *sk, u16 index, unsigned char *data,
2185 u16 len)
2186{
2187 struct hci_dev *hdev;
2188 struct mgmt_cp_add_remote_oob_data *cp = (void *) data;
2189 int err;
2190
2191 BT_DBG("hci%u ", index);
2192
2193 if (len != sizeof(*cp))
2194 return cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA,
2195 EINVAL);
2196
2197 hdev = hci_dev_get(index);
2198 if (!hdev)
2199 return cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA,
2200 ENODEV);
2201
Subramanian Srinivasana727a492011-11-30 13:06:07 -08002202 hci_dev_lock_bh(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01002203
2204 err = hci_add_remote_oob_data(hdev, &cp->bdaddr, cp->hash,
2205 cp->randomizer);
2206 if (err < 0)
2207 err = cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, -err);
2208 else
2209 err = cmd_complete(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, NULL,
2210 0);
2211
Subramanian Srinivasana727a492011-11-30 13:06:07 -08002212 hci_dev_unlock_bh(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01002213 hci_dev_put(hdev);
2214
2215 return err;
2216}
2217
2218static int remove_remote_oob_data(struct sock *sk, u16 index,
2219 unsigned char *data, u16 len)
2220{
2221 struct hci_dev *hdev;
2222 struct mgmt_cp_remove_remote_oob_data *cp = (void *) data;
2223 int err;
2224
2225 BT_DBG("hci%u ", index);
2226
2227 if (len != sizeof(*cp))
2228 return cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
2229 EINVAL);
2230
2231 hdev = hci_dev_get(index);
2232 if (!hdev)
2233 return cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
2234 ENODEV);
2235
Subramanian Srinivasana727a492011-11-30 13:06:07 -08002236 hci_dev_lock_bh(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01002237
2238 err = hci_remove_remote_oob_data(hdev, &cp->bdaddr);
2239 if (err < 0)
2240 err = cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
2241 -err);
2242 else
2243 err = cmd_complete(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
2244 NULL, 0);
2245
Subramanian Srinivasana727a492011-11-30 13:06:07 -08002246 hci_dev_unlock_bh(hdev);
Antti Julku58d19802011-06-15 12:01:15 +03002247 hci_dev_put(hdev);
2248
2249 return err;
2250}
2251
Johan Hedberg03811012010-12-08 00:21:06 +02002252int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
2253{
2254 unsigned char *buf;
2255 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01002256 u16 opcode, index, len;
Johan Hedberg03811012010-12-08 00:21:06 +02002257 int err;
2258
2259 BT_DBG("got %zu bytes", msglen);
2260
2261 if (msglen < sizeof(*hdr))
2262 return -EINVAL;
2263
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03002264 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02002265 if (!buf)
2266 return -ENOMEM;
2267
2268 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
2269 err = -EFAULT;
2270 goto done;
2271 }
2272
2273 hdr = (struct mgmt_hdr *) buf;
2274 opcode = get_unaligned_le16(&hdr->opcode);
Szymon Janc4e51eae2011-02-25 19:05:48 +01002275 index = get_unaligned_le16(&hdr->index);
Johan Hedberg03811012010-12-08 00:21:06 +02002276 len = get_unaligned_le16(&hdr->len);
2277
2278 if (len != msglen - sizeof(*hdr)) {
2279 err = -EINVAL;
2280 goto done;
2281 }
2282
Brian Gixa68668b2011-08-11 15:49:36 -07002283 BT_DBG("got opcode %x", opcode);
Johan Hedberg03811012010-12-08 00:21:06 +02002284 switch (opcode) {
Johan Hedberg02d98122010-12-13 21:07:04 +02002285 case MGMT_OP_READ_VERSION:
2286 err = read_version(sk);
2287 break;
Johan Hedbergfaba42e2010-12-13 21:07:05 +02002288 case MGMT_OP_READ_INDEX_LIST:
2289 err = read_index_list(sk);
2290 break;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02002291 case MGMT_OP_READ_INFO:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002292 err = read_controller_info(sk, index);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02002293 break;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002294 case MGMT_OP_SET_POWERED:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002295 err = set_powered(sk, index, buf + sizeof(*hdr), len);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002296 break;
Johan Hedberg73f22f62010-12-29 16:00:25 +02002297 case MGMT_OP_SET_DISCOVERABLE:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002298 err = set_discoverable(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg73f22f62010-12-29 16:00:25 +02002299 break;
Brian Gix8a7f1642011-10-17 17:39:46 -07002300 case MGMT_OP_SET_LIMIT_DISCOVERABLE:
2301 err = set_limited_discoverable(sk, index, buf + sizeof(*hdr),
2302 len);
2303 break;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02002304 case MGMT_OP_SET_CONNECTABLE:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002305 err = set_connectable(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02002306 break;
Johan Hedbergc542a062011-01-26 13:11:03 +02002307 case MGMT_OP_SET_PAIRABLE:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002308 err = set_pairable(sk, index, buf + sizeof(*hdr), len);
Johan Hedbergc542a062011-01-26 13:11:03 +02002309 break;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002310 case MGMT_OP_ADD_UUID:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002311 err = add_uuid(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002312 break;
2313 case MGMT_OP_REMOVE_UUID:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002314 err = remove_uuid(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002315 break;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002316 case MGMT_OP_SET_DEV_CLASS:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002317 err = set_dev_class(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002318 break;
2319 case MGMT_OP_SET_SERVICE_CACHE:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002320 err = set_service_cache(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002321 break;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002322 case MGMT_OP_LOAD_KEYS:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002323 err = load_keys(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002324 break;
2325 case MGMT_OP_REMOVE_KEY:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002326 err = remove_key(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002327 break;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002328 case MGMT_OP_DISCONNECT:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002329 err = disconnect(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002330 break;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002331 case MGMT_OP_GET_CONNECTIONS:
Szymon Janc8ce62842011-03-01 16:55:32 +01002332 err = get_connections(sk, index);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002333 break;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002334 case MGMT_OP_PIN_CODE_REPLY:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002335 err = pin_code_reply(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002336 break;
2337 case MGMT_OP_PIN_CODE_NEG_REPLY:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002338 err = pin_code_neg_reply(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002339 break;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002340 case MGMT_OP_SET_IO_CAPABILITY:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002341 err = set_io_capability(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002342 break;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002343 case MGMT_OP_PAIR_DEVICE:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002344 err = pair_device(sk, index, buf + sizeof(*hdr), len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002345 break;
Johan Hedberga5c29682011-02-19 12:05:57 -03002346 case MGMT_OP_USER_CONFIRM_REPLY:
Brian Gixa68668b2011-08-11 15:49:36 -07002347 case MGMT_OP_USER_PASSKEY_REPLY:
Johan Hedberga5c29682011-02-19 12:05:57 -03002348 case MGMT_OP_USER_CONFIRM_NEG_REPLY:
Brian Gixa68668b2011-08-11 15:49:36 -07002349 err = user_confirm_reply(sk, index, buf + sizeof(*hdr),
2350 len, opcode);
Johan Hedberga5c29682011-02-19 12:05:57 -03002351 break;
Johan Hedbergb312b1612011-03-16 14:29:37 +02002352 case MGMT_OP_SET_LOCAL_NAME:
2353 err = set_local_name(sk, index, buf + sizeof(*hdr), len);
2354 break;
Brian Gixa68668b2011-08-11 15:49:36 -07002355 case MGMT_OP_START_DISCOVERY:
2356 err = start_discovery(sk, index);
2357 break;
2358 case MGMT_OP_STOP_DISCOVERY:
2359 err = stop_discovery(sk, index);
2360 break;
2361 case MGMT_OP_RESOLVE_NAME:
2362 err = resolve_name(sk, index, buf + sizeof(*hdr), len);
2363 break;
Brian Gix7f7e16c2011-11-01 16:27:25 -07002364 case MGMT_OP_SET_CONNECTION_PARAMS:
2365 err = set_connection_params(sk, index, buf + sizeof(*hdr), len);
2366 break;
Szymon Jancc35938b2011-03-22 13:12:21 +01002367 case MGMT_OP_READ_LOCAL_OOB_DATA:
2368 err = read_local_oob_data(sk, index);
2369 break;
Szymon Janc2763eda2011-03-22 13:12:22 +01002370 case MGMT_OP_ADD_REMOTE_OOB_DATA:
2371 err = add_remote_oob_data(sk, index, buf + sizeof(*hdr), len);
2372 break;
2373 case MGMT_OP_REMOVE_REMOTE_OOB_DATA:
2374 err = remove_remote_oob_data(sk, index, buf + sizeof(*hdr),
2375 len);
2376 break;
Prabhakaran Mc46230fa2011-11-30 18:11:21 +05302377 case MGMT_OP_ENCRYPT_LINK:
2378 err = encrypt_link(sk, index, buf + sizeof(*hdr), len);
2379 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002380
Johan Hedberg03811012010-12-08 00:21:06 +02002381 default:
2382 BT_DBG("Unknown op %u", opcode);
Szymon Janc4e51eae2011-02-25 19:05:48 +01002383 err = cmd_status(sk, index, opcode, 0x01);
Johan Hedberg03811012010-12-08 00:21:06 +02002384 break;
2385 }
2386
Johan Hedberge41d8b42010-12-13 21:07:03 +02002387 if (err < 0)
2388 goto done;
2389
Johan Hedberg03811012010-12-08 00:21:06 +02002390 err = msglen;
2391
2392done:
2393 kfree(buf);
2394 return err;
2395}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02002396
Johan Hedbergc71e97b2010-12-13 21:07:07 +02002397int mgmt_index_added(u16 index)
2398{
Brian Gixa68668b2011-08-11 15:49:36 -07002399 BT_DBG("%d", index);
Szymon Janc4e51eae2011-02-25 19:05:48 +01002400 return mgmt_event(MGMT_EV_INDEX_ADDED, index, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02002401}
2402
2403int mgmt_index_removed(u16 index)
2404{
Brian Gixa68668b2011-08-11 15:49:36 -07002405 BT_DBG("%d", index);
Szymon Janc4e51eae2011-02-25 19:05:48 +01002406 return mgmt_event(MGMT_EV_INDEX_REMOVED, index, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002407}
2408
Johan Hedberg73f22f62010-12-29 16:00:25 +02002409struct cmd_lookup {
Johan Hedberg72a734e2010-12-30 00:38:22 +02002410 u8 val;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002411 struct sock *sk;
2412};
2413
Johan Hedberg72a734e2010-12-30 00:38:22 +02002414static void mode_rsp(struct pending_cmd *cmd, void *data)
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002415{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01002416 struct mgmt_mode *cp = cmd->param;
Johan Hedberg73f22f62010-12-29 16:00:25 +02002417 struct cmd_lookup *match = data;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002418
Johan Hedberg72a734e2010-12-30 00:38:22 +02002419 if (cp->val != match->val)
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002420 return;
2421
Johan Hedberg053f0212011-01-26 13:07:10 +02002422 send_mode_rsp(cmd->sk, cmd->opcode, cmd->index, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002423
2424 list_del(&cmd->list);
2425
2426 if (match->sk == NULL) {
2427 match->sk = cmd->sk;
2428 sock_hold(match->sk);
2429 }
2430
2431 mgmt_pending_free(cmd);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02002432}
Johan Hedberg5add6af2010-12-16 10:00:37 +02002433
2434int mgmt_powered(u16 index, u8 powered)
2435{
Johan Hedberg72a734e2010-12-30 00:38:22 +02002436 struct mgmt_mode ev;
Johan Hedberg73f22f62010-12-29 16:00:25 +02002437 struct cmd_lookup match = { powered, NULL };
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002438 int ret;
Johan Hedberg5add6af2010-12-16 10:00:37 +02002439
Brian Gixa68668b2011-08-11 15:49:36 -07002440 BT_DBG("hci%u %d", index, powered);
2441
Johan Hedberg72a734e2010-12-30 00:38:22 +02002442 mgmt_pending_foreach(MGMT_OP_SET_POWERED, index, mode_rsp, &match);
Johan Hedberg5add6af2010-12-16 10:00:37 +02002443
Johan Hedberg72a734e2010-12-30 00:38:22 +02002444 ev.val = powered;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002445
Szymon Janc4e51eae2011-02-25 19:05:48 +01002446 ret = mgmt_event(MGMT_EV_POWERED, index, &ev, sizeof(ev), match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002447
2448 if (match.sk)
2449 sock_put(match.sk);
2450
2451 return ret;
Johan Hedberg5add6af2010-12-16 10:00:37 +02002452}
Johan Hedberg73f22f62010-12-29 16:00:25 +02002453
Johan Hedberg73f22f62010-12-29 16:00:25 +02002454int mgmt_discoverable(u16 index, u8 discoverable)
2455{
Johan Hedberg72a734e2010-12-30 00:38:22 +02002456 struct mgmt_mode ev;
Johan Hedberg73f22f62010-12-29 16:00:25 +02002457 struct cmd_lookup match = { discoverable, NULL };
2458 int ret;
2459
Szymon Jancb8534e02011-03-01 16:55:34 +01002460 mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, index, mode_rsp, &match);
Johan Hedberg72a734e2010-12-30 00:38:22 +02002461
Johan Hedberg72a734e2010-12-30 00:38:22 +02002462 ev.val = discoverable;
Johan Hedberg73f22f62010-12-29 16:00:25 +02002463
Szymon Janc4e51eae2011-02-25 19:05:48 +01002464 ret = mgmt_event(MGMT_EV_DISCOVERABLE, index, &ev, sizeof(ev),
2465 match.sk);
Johan Hedberg73f22f62010-12-29 16:00:25 +02002466
2467 if (match.sk)
2468 sock_put(match.sk);
2469
2470 return ret;
2471}
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02002472
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02002473int mgmt_connectable(u16 index, u8 connectable)
2474{
Johan Hedberg72a734e2010-12-30 00:38:22 +02002475 struct mgmt_mode ev;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02002476 struct cmd_lookup match = { connectable, NULL };
2477 int ret;
2478
Johan Hedberg72a734e2010-12-30 00:38:22 +02002479 mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, index, mode_rsp, &match);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02002480
Johan Hedberg72a734e2010-12-30 00:38:22 +02002481 ev.val = connectable;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02002482
Szymon Janc4e51eae2011-02-25 19:05:48 +01002483 ret = mgmt_event(MGMT_EV_CONNECTABLE, index, &ev, sizeof(ev), match.sk);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02002484
2485 if (match.sk)
2486 sock_put(match.sk);
2487
2488 return ret;
2489}
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002490
Brian Gixa68668b2011-08-11 15:49:36 -07002491int mgmt_new_key(u16 index, struct link_key *key, u8 bonded)
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002492{
Vinicius Costa Gomesc00ddbf2011-07-08 18:31:44 -03002493 struct mgmt_ev_new_key *ev;
2494 int err, total;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002495
Vinicius Costa Gomesc00ddbf2011-07-08 18:31:44 -03002496 total = sizeof(struct mgmt_ev_new_key) + key->dlen;
2497 ev = kzalloc(total, GFP_ATOMIC);
2498 if (!ev)
2499 return -ENOMEM;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002500
Vinicius Costa Gomesc00ddbf2011-07-08 18:31:44 -03002501 bacpy(&ev->key.bdaddr, &key->bdaddr);
Brian Gixcf956772011-10-20 15:18:51 -07002502 ev->key.addr_type = key->addr_type;
2503 ev->key.key_type = key->key_type;
Vinicius Costa Gomesc00ddbf2011-07-08 18:31:44 -03002504 memcpy(ev->key.val, key->val, 16);
2505 ev->key.pin_len = key->pin_len;
Brian Gixa68668b2011-08-11 15:49:36 -07002506 ev->key.auth = key->auth;
2507 ev->store_hint = bonded;
Vinicius Costa Gomesc00ddbf2011-07-08 18:31:44 -03002508 ev->key.dlen = key->dlen;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002509
Vinicius Costa Gomesc00ddbf2011-07-08 18:31:44 -03002510 memcpy(ev->key.data, key->data, key->dlen);
2511
2512 err = mgmt_event(MGMT_EV_NEW_KEY, index, ev, total, NULL);
2513
2514 kfree(ev);
2515
2516 return err;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002517}
Johan Hedbergf7520542011-01-20 12:34:39 +02002518
Brian Gix2e2f50d2011-09-13 12:36:04 -07002519int mgmt_connected(u16 index, bdaddr_t *bdaddr, u8 le)
Johan Hedbergf7520542011-01-20 12:34:39 +02002520{
2521 struct mgmt_ev_connected ev;
2522
Johan Hedbergf7520542011-01-20 12:34:39 +02002523 bacpy(&ev.bdaddr, bdaddr);
Brian Gix2e2f50d2011-09-13 12:36:04 -07002524 ev.le = le;
Johan Hedbergf7520542011-01-20 12:34:39 +02002525
Szymon Janc4e51eae2011-02-25 19:05:48 +01002526 return mgmt_event(MGMT_EV_CONNECTED, index, &ev, sizeof(ev), NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02002527}
2528
Johan Hedberg8962ee72011-01-20 12:40:27 +02002529static void disconnect_rsp(struct pending_cmd *cmd, void *data)
2530{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01002531 struct mgmt_cp_disconnect *cp = cmd->param;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002532 struct sock **sk = data;
Johan Hedberga38528f2011-01-22 06:46:43 +02002533 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002534
Johan Hedberga38528f2011-01-22 06:46:43 +02002535 bacpy(&rp.bdaddr, &cp->bdaddr);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002536
Szymon Janc4e51eae2011-02-25 19:05:48 +01002537 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002538
2539 *sk = cmd->sk;
2540 sock_hold(*sk);
2541
Johan Hedberga664b5b2011-02-19 12:06:02 -03002542 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002543}
2544
Johan Hedbergf7520542011-01-20 12:34:39 +02002545int mgmt_disconnected(u16 index, bdaddr_t *bdaddr)
2546{
2547 struct mgmt_ev_disconnected ev;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002548 struct sock *sk = NULL;
2549 int err;
2550
2551 mgmt_pending_foreach(MGMT_OP_DISCONNECT, index, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02002552
Johan Hedbergf7520542011-01-20 12:34:39 +02002553 bacpy(&ev.bdaddr, bdaddr);
2554
Szymon Janc4e51eae2011-02-25 19:05:48 +01002555 err = mgmt_event(MGMT_EV_DISCONNECTED, index, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002556
2557 if (sk)
2558 sock_put(sk);
2559
2560 return err;
2561}
2562
2563int mgmt_disconnect_failed(u16 index)
2564{
2565 struct pending_cmd *cmd;
2566 int err;
2567
2568 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, index);
2569 if (!cmd)
2570 return -ENOENT;
2571
Szymon Janc4e51eae2011-02-25 19:05:48 +01002572 err = cmd_status(cmd->sk, index, MGMT_OP_DISCONNECT, EIO);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002573
Johan Hedberga664b5b2011-02-19 12:06:02 -03002574 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002575
2576 return err;
Johan Hedbergf7520542011-01-20 12:34:39 +02002577}
Johan Hedberg17d5c042011-01-22 06:09:08 +02002578
2579int mgmt_connect_failed(u16 index, bdaddr_t *bdaddr, u8 status)
2580{
2581 struct mgmt_ev_connect_failed ev;
2582
Johan Hedberg17d5c042011-01-22 06:09:08 +02002583 bacpy(&ev.bdaddr, bdaddr);
2584 ev.status = status;
2585
Szymon Janc4e51eae2011-02-25 19:05:48 +01002586 return mgmt_event(MGMT_EV_CONNECT_FAILED, index, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02002587}
Johan Hedberg980e1a52011-01-22 06:10:07 +02002588
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002589int mgmt_pin_code_request(u16 index, bdaddr_t *bdaddr)
Johan Hedberg980e1a52011-01-22 06:10:07 +02002590{
2591 struct mgmt_ev_pin_code_request ev;
2592
Brian Gixa68668b2011-08-11 15:49:36 -07002593 BT_DBG("hci%u", index);
2594
Johan Hedberg980e1a52011-01-22 06:10:07 +02002595 bacpy(&ev.bdaddr, bdaddr);
Brian Gixa68668b2011-08-11 15:49:36 -07002596 ev.secure = 0;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002597
Szymon Janc4e51eae2011-02-25 19:05:48 +01002598 return mgmt_event(MGMT_EV_PIN_CODE_REQUEST, index, &ev, sizeof(ev),
2599 NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002600}
2601
2602int mgmt_pin_code_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status)
2603{
2604 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03002605 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002606 int err;
2607
2608 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, index);
2609 if (!cmd)
2610 return -ENOENT;
2611
Johan Hedbergac56fb12011-02-19 12:05:59 -03002612 bacpy(&rp.bdaddr, bdaddr);
2613 rp.status = status;
2614
Szymon Janc4e51eae2011-02-25 19:05:48 +01002615 err = cmd_complete(cmd->sk, index, MGMT_OP_PIN_CODE_REPLY, &rp,
2616 sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02002617
Johan Hedberga664b5b2011-02-19 12:06:02 -03002618 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002619
2620 return err;
2621}
2622
2623int mgmt_pin_code_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status)
2624{
2625 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03002626 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002627 int err;
2628
2629 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, index);
2630 if (!cmd)
2631 return -ENOENT;
2632
Johan Hedbergac56fb12011-02-19 12:05:59 -03002633 bacpy(&rp.bdaddr, bdaddr);
2634 rp.status = status;
2635
Szymon Janc4e51eae2011-02-25 19:05:48 +01002636 err = cmd_complete(cmd->sk, index, MGMT_OP_PIN_CODE_NEG_REPLY, &rp,
2637 sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02002638
Johan Hedberga664b5b2011-02-19 12:06:02 -03002639 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002640
2641 return err;
2642}
Johan Hedberga5c29682011-02-19 12:05:57 -03002643
Brian Gixa68668b2011-08-11 15:49:36 -07002644int mgmt_user_confirm_request(u16 index, u8 event,
2645 bdaddr_t *bdaddr, __le32 value)
Johan Hedberga5c29682011-02-19 12:05:57 -03002646{
2647 struct mgmt_ev_user_confirm_request ev;
Brian Gixa68668b2011-08-11 15:49:36 -07002648 struct hci_conn *conn = NULL;
2649 struct hci_dev *hdev;
2650 u8 loc_cap, rem_cap, loc_mitm, rem_mitm;
2651
2652 BT_DBG("hci%u", index);
2653
2654 hdev = hci_dev_get(index);
2655
Brian Gix64bd5302011-09-08 11:35:48 -07002656 if (!hdev)
2657 return -ENODEV;
2658
Brian Gix64bd5302011-09-08 11:35:48 -07002659 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, bdaddr);
Brian Gixa68668b2011-08-11 15:49:36 -07002660
2661 ev.auto_confirm = 0;
2662
2663 if (!conn || event != HCI_EV_USER_CONFIRM_REQUEST)
2664 goto no_auto_confirm;
2665
2666 loc_cap = (conn->io_capability == 0x04) ? 0x01 : conn->io_capability;
2667 rem_cap = conn->remote_cap;
2668 loc_mitm = conn->auth_type & 0x01;
2669 rem_mitm = conn->remote_auth & 0x01;
2670
Brian Gixdbf59292011-11-11 15:45:17 -08002671 if ((conn->auth_type & HCI_AT_DEDICATED_BONDING) &&
2672 conn->auth_initiator && rem_cap == 0x03)
2673 ev.auto_confirm = 1;
2674 else if (loc_cap == 0x01 && (rem_cap == 0x00 || rem_cap == 0x03))
Brian Gixa68668b2011-08-11 15:49:36 -07002675 goto no_auto_confirm;
2676
2677
2678 if ((!loc_mitm || rem_cap == 0x03) && (!rem_mitm || loc_cap == 0x03))
2679 ev.auto_confirm = 1;
2680
2681no_auto_confirm:
2682 bacpy(&ev.bdaddr, bdaddr);
2683 ev.event = event;
2684 put_unaligned_le32(value, &ev.value);
2685
Brian Gix64bd5302011-09-08 11:35:48 -07002686 hci_dev_put(hdev);
2687
Brian Gixa68668b2011-08-11 15:49:36 -07002688 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, index, &ev, sizeof(ev),
2689 NULL);
2690}
2691
2692int mgmt_user_passkey_request(u16 index, bdaddr_t *bdaddr)
2693{
2694 struct mgmt_ev_user_passkey_request ev;
Johan Hedberga5c29682011-02-19 12:05:57 -03002695
2696 BT_DBG("hci%u", index);
2697
Johan Hedberga5c29682011-02-19 12:05:57 -03002698 bacpy(&ev.bdaddr, bdaddr);
Johan Hedberga5c29682011-02-19 12:05:57 -03002699
Brian Gixa68668b2011-08-11 15:49:36 -07002700 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, index, &ev, sizeof(ev),
Szymon Janc4e51eae2011-02-25 19:05:48 +01002701 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03002702}
2703
2704static int confirm_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status,
2705 u8 opcode)
2706{
2707 struct pending_cmd *cmd;
2708 struct mgmt_rp_user_confirm_reply rp;
2709 int err;
2710
2711 cmd = mgmt_pending_find(opcode, index);
2712 if (!cmd)
2713 return -ENOENT;
2714
Johan Hedberga5c29682011-02-19 12:05:57 -03002715 bacpy(&rp.bdaddr, bdaddr);
2716 rp.status = status;
Szymon Janc4e51eae2011-02-25 19:05:48 +01002717 err = cmd_complete(cmd->sk, index, opcode, &rp, sizeof(rp));
Johan Hedberga5c29682011-02-19 12:05:57 -03002718
Johan Hedberga664b5b2011-02-19 12:06:02 -03002719 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03002720
2721 return err;
2722}
2723
2724int mgmt_user_confirm_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status)
2725{
2726 return confirm_reply_complete(index, bdaddr, status,
2727 MGMT_OP_USER_CONFIRM_REPLY);
2728}
2729
Szymon Jancb8534e02011-03-01 16:55:34 +01002730int mgmt_user_confirm_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03002731{
2732 return confirm_reply_complete(index, bdaddr, status,
2733 MGMT_OP_USER_CONFIRM_NEG_REPLY);
2734}
Johan Hedberg2a611692011-02-19 12:06:00 -03002735
2736int mgmt_auth_failed(u16 index, bdaddr_t *bdaddr, u8 status)
2737{
2738 struct mgmt_ev_auth_failed ev;
2739
Johan Hedberg2a611692011-02-19 12:06:00 -03002740 bacpy(&ev.bdaddr, bdaddr);
2741 ev.status = status;
2742
Szymon Janc4e51eae2011-02-25 19:05:48 +01002743 return mgmt_event(MGMT_EV_AUTH_FAILED, index, &ev, sizeof(ev), NULL);
Johan Hedberg2a611692011-02-19 12:06:00 -03002744}
Johan Hedbergb312b1612011-03-16 14:29:37 +02002745
2746int mgmt_set_local_name_complete(u16 index, u8 *name, u8 status)
2747{
2748 struct pending_cmd *cmd;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002749 struct hci_dev *hdev;
Johan Hedbergb312b1612011-03-16 14:29:37 +02002750 struct mgmt_cp_set_local_name ev;
2751 int err;
2752
2753 memset(&ev, 0, sizeof(ev));
2754 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
2755
2756 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, index);
2757 if (!cmd)
2758 goto send_event;
2759
2760 if (status) {
2761 err = cmd_status(cmd->sk, index, MGMT_OP_SET_LOCAL_NAME, EIO);
2762 goto failed;
2763 }
2764
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002765 hdev = hci_dev_get(index);
2766 if (hdev) {
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002767 update_eir(hdev);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002768 hci_dev_put(hdev);
2769 }
2770
Johan Hedbergb312b1612011-03-16 14:29:37 +02002771 err = cmd_complete(cmd->sk, index, MGMT_OP_SET_LOCAL_NAME, &ev,
2772 sizeof(ev));
2773 if (err < 0)
2774 goto failed;
2775
2776send_event:
2777 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, index, &ev, sizeof(ev),
2778 cmd ? cmd->sk : NULL);
2779
2780failed:
2781 if (cmd)
2782 mgmt_pending_remove(cmd);
2783 return err;
2784}
Szymon Jancc35938b2011-03-22 13:12:21 +01002785
2786int mgmt_read_local_oob_data_reply_complete(u16 index, u8 *hash, u8 *randomizer,
2787 u8 status)
2788{
2789 struct pending_cmd *cmd;
2790 int err;
2791
2792 BT_DBG("hci%u status %u", index, status);
2793
2794 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, index);
2795 if (!cmd)
2796 return -ENOENT;
2797
2798 if (status) {
2799 err = cmd_status(cmd->sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
2800 EIO);
2801 } else {
2802 struct mgmt_rp_read_local_oob_data rp;
2803
2804 memcpy(rp.hash, hash, sizeof(rp.hash));
2805 memcpy(rp.randomizer, randomizer, sizeof(rp.randomizer));
2806
2807 err = cmd_complete(cmd->sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
2808 &rp, sizeof(rp));
2809 }
2810
2811 mgmt_pending_remove(cmd);
2812
2813 return err;
2814}
Johan Hedberge17acd42011-03-30 23:57:16 +03002815
Brian Gixa68668b2011-08-11 15:49:36 -07002816int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 type, u8 le,
2817 u8 *dev_class, s8 rssi, u8 eir_len, u8 *eir)
Johan Hedberge17acd42011-03-30 23:57:16 +03002818{
2819 struct mgmt_ev_device_found ev;
Brian Gix568dde92012-01-11 16:18:04 -08002820 struct hci_dev *hdev;
Brian Gixa68668b2011-08-11 15:49:36 -07002821 int err;
2822
2823 BT_DBG("le: %d", le);
Johan Hedberge17acd42011-03-30 23:57:16 +03002824
2825 memset(&ev, 0, sizeof(ev));
2826
2827 bacpy(&ev.bdaddr, bdaddr);
Johan Hedberge17acd42011-03-30 23:57:16 +03002828 ev.rssi = rssi;
Brian Gixa68668b2011-08-11 15:49:36 -07002829 ev.type = type;
2830 ev.le = le;
Johan Hedberge17acd42011-03-30 23:57:16 +03002831
Brian Gixa68668b2011-08-11 15:49:36 -07002832 if (dev_class)
2833 memcpy(ev.dev_class, dev_class, sizeof(ev.dev_class));
Johan Hedberge17acd42011-03-30 23:57:16 +03002834
Brian Gixa68668b2011-08-11 15:49:36 -07002835 if (eir && eir_len)
2836 memcpy(ev.eir, eir, eir_len);
2837
2838 err = mgmt_event(MGMT_EV_DEVICE_FOUND, index, &ev, sizeof(ev), NULL);
2839
2840 if (err < 0)
2841 return err;
2842
Brian Gix568dde92012-01-11 16:18:04 -08002843 hdev = hci_dev_get(index);
Brian Gixa68668b2011-08-11 15:49:36 -07002844
Brian Gix568dde92012-01-11 16:18:04 -08002845 if (!hdev)
2846 return 0;
Brian Gix64bd5302011-09-08 11:35:48 -07002847
Brian Gix568dde92012-01-11 16:18:04 -08002848 if (hdev->disco_state == SCAN_IDLE)
2849 goto done;
2850
2851 hdev->disco_int_count++;
2852
2853 if (hdev->disco_int_count >= hdev->disco_int_phase) {
2854 /* Inquiry scan for General Discovery LAP */
2855 struct hci_cp_inquiry cp = {{0x33, 0x8b, 0x9e}, 4, 0};
2856 struct hci_cp_le_set_scan_enable le_cp = {0, 0};
2857
2858 hdev->disco_int_phase *= 2;
2859 hdev->disco_int_count = 0;
2860 if (hdev->disco_state == SCAN_LE) {
2861 /* cancel LE scan */
2862 hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE,
2863 sizeof(le_cp), &le_cp);
2864 /* start BR scan */
2865 cp.num_rsp = (u8) hdev->disco_int_phase;
2866 hci_send_cmd(hdev, HCI_OP_INQUIRY,
2867 sizeof(cp), &cp);
2868 hdev->disco_state = SCAN_BR;
2869 del_timer_sync(&hdev->disco_le_timer);
Brian Gixa68668b2011-08-11 15:49:36 -07002870 }
2871 }
2872
Brian Gix568dde92012-01-11 16:18:04 -08002873done:
2874 hci_dev_put(hdev);
Brian Gixa68668b2011-08-11 15:49:36 -07002875 return 0;
Johan Hedberge17acd42011-03-30 23:57:16 +03002876}
Johan Hedberga88a9652011-03-30 13:18:12 +03002877
Brian Gixa68668b2011-08-11 15:49:36 -07002878
2879int mgmt_remote_name(u16 index, bdaddr_t *bdaddr, u8 status, u8 *name)
Johan Hedberga88a9652011-03-30 13:18:12 +03002880{
2881 struct mgmt_ev_remote_name ev;
2882
2883 memset(&ev, 0, sizeof(ev));
2884
2885 bacpy(&ev.bdaddr, bdaddr);
Brian Gixa68668b2011-08-11 15:49:36 -07002886 ev.status = status;
Johan Hedberga88a9652011-03-30 13:18:12 +03002887 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
2888
2889 return mgmt_event(MGMT_EV_REMOTE_NAME, index, &ev, sizeof(ev), NULL);
2890}
Prabhakaran Mc46230fa2011-11-30 18:11:21 +05302891
2892int mgmt_encrypt_change(u16 index, bdaddr_t *bdaddr, u8 status)
2893{
2894 struct mgmt_ev_encrypt_change ev;
2895
2896 BT_DBG("hci%u", index);
2897
2898 bacpy(&ev.bdaddr, bdaddr);
2899 ev.status = status;
2900
2901 return mgmt_event(MGMT_EV_ENCRYPT_CHANGE, index, &ev, sizeof(ev),
2902 NULL);
2903}
2904
Srinivas Krovvidi0916aed2011-12-20 12:06:34 +05302905int mgmt_remote_class(u16 index, bdaddr_t *bdaddr, u8 dev_class[3])
2906{
2907 struct mgmt_ev_remote_class ev;
2908
2909 memset(&ev, 0, sizeof(ev));
2910
2911 bacpy(&ev.bdaddr, bdaddr);
2912 memcpy(ev.dev_class, dev_class, 3);
2913
2914 return mgmt_event(MGMT_EV_REMOTE_CLASS, index, &ev, sizeof(ev), NULL);
2915}
Srinivas Krovvidid352b262012-01-12 19:46:26 +05302916
2917int mgmt_remote_version(u16 index, bdaddr_t *bdaddr, u8 ver, u16 mnf,
2918 u16 sub_ver)
2919{
2920 struct mgmt_ev_remote_version ev;
2921
2922 memset(&ev, 0, sizeof(ev));
2923
2924 bacpy(&ev.bdaddr, bdaddr);
2925 ev.lmp_ver = ver;
2926 ev.manufacturer = mnf;
2927 ev.lmp_subver = sub_ver;
2928
2929 return mgmt_event(MGMT_EV_REMOTE_VERSION, index, &ev, sizeof(ev), NULL);
2930}