blob: 25ad435d6ac766e94e4568cd19ec24a5bb00fd65 [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);
Brian Gix80fb3a92012-01-31 13:15:20 -08001530 hci_conn_put(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03001531}
1532
Brian Gix6d5fb8a2011-09-09 14:53:04 -07001533static void pairing_security_complete_cb(struct hci_conn *conn, u8 status)
Brian Gixa68668b2011-08-11 15:49:36 -07001534{
1535 struct pending_cmd *cmd;
1536
1537 BT_DBG(" %u", status);
1538
1539 cmd = find_pairing(conn);
1540 if (!cmd) {
1541 BT_DBG("Unable to find a pending command");
1542 return;
1543 }
1544
1545 if (conn->type == LE_LINK)
1546 smp_link_encrypt_cmplt(conn->l2cap_data, status,
1547 status ? 0 : 1);
1548 else
1549 pairing_complete(cmd, status);
1550}
1551
Brian Gix6d5fb8a2011-09-09 14:53:04 -07001552static void pairing_connect_complete_cb(struct hci_conn *conn, u8 status)
Brian Gixa68668b2011-08-11 15:49:36 -07001553{
1554 struct pending_cmd *cmd;
1555
1556 BT_DBG("conn: %p %u", conn, status);
1557
1558 cmd = find_pairing(conn);
1559 if (!cmd) {
1560 BT_DBG("Unable to find a pending command");
1561 return;
1562 }
Brian Gix114f3a62011-09-27 14:02:20 -07001563
1564 if (status)
1565 pairing_complete(cmd, status);
1566
Brian Gix6d5fb8a2011-09-09 14:53:04 -07001567 hci_conn_put(conn);
Brian Gixa68668b2011-08-11 15:49:36 -07001568}
1569
1570static void discovery_terminated(struct pending_cmd *cmd, void *data)
1571{
Brian Gix6e349d02011-11-28 14:51:14 -08001572 struct hci_dev *hdev;
Brian Gixa68668b2011-08-11 15:49:36 -07001573 struct mgmt_mode ev = {0};
Brian Gixa68668b2011-08-11 15:49:36 -07001574
1575 BT_DBG("");
Brian Gix6e349d02011-11-28 14:51:14 -08001576 hdev = hci_dev_get(cmd->index);
1577 if (!hdev)
1578 goto not_found;
1579
Brian Gix568dde92012-01-11 16:18:04 -08001580 del_timer(&hdev->disco_le_timer);
1581 del_timer(&hdev->disco_timer);
Brian Gix6e349d02011-11-28 14:51:14 -08001582 hci_dev_put(hdev);
1583
1584not_found:
Brian Gixa68668b2011-08-11 15:49:36 -07001585 mgmt_event(MGMT_EV_DISCOVERING, cmd->index, &ev, sizeof(ev), NULL);
1586
1587 list_del(&cmd->list);
1588
1589 mgmt_pending_free(cmd);
1590}
1591
Szymon Janc4e51eae2011-02-25 19:05:48 +01001592static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03001593{
1594 struct hci_dev *hdev;
1595 struct mgmt_cp_pair_device *cp;
1596 struct pending_cmd *cmd;
Brian Gixa68668b2011-08-11 15:49:36 -07001597 u8 sec_level, auth_type, io_cap;
Johan Hedberge9a416b2011-02-19 12:05:56 -03001598 struct hci_conn *conn;
Brian Gixfdd38922011-09-28 16:23:48 -07001599 struct adv_entry *entry;
Johan Hedberge9a416b2011-02-19 12:05:56 -03001600 int err;
1601
1602 BT_DBG("");
1603
Brian Gix64bd5302011-09-08 11:35:48 -07001604 cp = (void *) data;
1605
1606 if (len != sizeof(*cp))
1607 return cmd_status(sk, index, MGMT_OP_PAIR_DEVICE, EINVAL);
1608
Szymon Janc4e51eae2011-02-25 19:05:48 +01001609 hdev = hci_dev_get(index);
Brian Gixa68668b2011-08-11 15:49:36 -07001610
Johan Hedberge9a416b2011-02-19 12:05:56 -03001611 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +01001612 return cmd_status(sk, index, MGMT_OP_PAIR_DEVICE, ENODEV);
Johan Hedberge9a416b2011-02-19 12:05:56 -03001613
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001614 hci_dev_lock_bh(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03001615
Prabhakaran Mc6001a712011-09-06 11:56:25 +05301616 BT_DBG("SSP Cap is %d", cp->ssp_cap);
1617 io_cap = cp->io_cap;
1618 if ((cp->ssp_cap == 0) || (io_cap == 0x03)) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03001619 sec_level = BT_SECURITY_MEDIUM;
1620 auth_type = HCI_AT_DEDICATED_BONDING;
1621 } else {
1622 sec_level = BT_SECURITY_HIGH;
1623 auth_type = HCI_AT_DEDICATED_BONDING_MITM;
1624 }
1625
Brian Gixfdd38922011-09-28 16:23:48 -07001626 entry = hci_find_adv_entry(hdev, &cp->bdaddr);
1627 if (entry && entry->flags & 0x04) {
Brian Gixa68668b2011-08-11 15:49:36 -07001628 conn = hci_connect(hdev, LE_LINK, 0, &cp->bdaddr, sec_level,
1629 auth_type);
Brian Gixa68668b2011-08-11 15:49:36 -07001630 } else {
1631 /* ACL-SSP does not support io_cap 0x04 (KeyboadDisplay) */
1632 if (io_cap == 0x04)
1633 io_cap = 0x01;
1634 conn = hci_connect(hdev, ACL_LINK, 0, &cp->bdaddr, sec_level,
1635 auth_type);
1636 }
1637
Ville Tervo30e76272011-02-22 16:10:53 -03001638 if (IS_ERR(conn)) {
1639 err = PTR_ERR(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03001640 goto unlock;
1641 }
1642
1643 if (conn->connect_cfm_cb) {
1644 hci_conn_put(conn);
Szymon Janc4e51eae2011-02-25 19:05:48 +01001645 err = cmd_status(sk, index, MGMT_OP_PAIR_DEVICE, EBUSY);
Johan Hedberge9a416b2011-02-19 12:05:56 -03001646 goto unlock;
1647 }
1648
Szymon Janc4e51eae2011-02-25 19:05:48 +01001649 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, index, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03001650 if (!cmd) {
1651 err = -ENOMEM;
1652 hci_conn_put(conn);
1653 goto unlock;
1654 }
1655
Brian Gix6d5fb8a2011-09-09 14:53:04 -07001656 conn->connect_cfm_cb = pairing_connect_complete_cb;
1657 conn->security_cfm_cb = pairing_security_complete_cb;
Johan Hedberge9a416b2011-02-19 12:05:56 -03001658 conn->disconn_cfm_cb = pairing_complete_cb;
Brian Gixa68668b2011-08-11 15:49:36 -07001659 conn->io_capability = io_cap;
Johan Hedberge9a416b2011-02-19 12:05:56 -03001660 cmd->user_data = conn;
1661
1662 if (conn->state == BT_CONNECTED &&
1663 hci_conn_security(conn, sec_level, auth_type))
1664 pairing_complete(cmd, 0);
1665
1666 err = 0;
1667
1668unlock:
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001669 hci_dev_unlock_bh(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03001670 hci_dev_put(hdev);
1671
1672 return err;
1673}
1674
Szymon Janc4e51eae2011-02-25 19:05:48 +01001675static int user_confirm_reply(struct sock *sk, u16 index, unsigned char *data,
Brian Gixa68668b2011-08-11 15:49:36 -07001676 u16 len, u16 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03001677{
1678 struct mgmt_cp_user_confirm_reply *cp = (void *) data;
Brian Gixa68668b2011-08-11 15:49:36 -07001679 u16 mgmt_op = opcode, hci_op;
Johan Hedberga5c29682011-02-19 12:05:57 -03001680 struct pending_cmd *cmd;
1681 struct hci_dev *hdev;
Brian Gixa68668b2011-08-11 15:49:36 -07001682 struct hci_conn *le_conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03001683 int err;
1684
Brian Gixa68668b2011-08-11 15:49:36 -07001685 BT_DBG("%d", mgmt_op);
Johan Hedberga5c29682011-02-19 12:05:57 -03001686
Brian Gixa68668b2011-08-11 15:49:36 -07001687 if (mgmt_op == MGMT_OP_USER_CONFIRM_NEG_REPLY)
Johan Hedberga5c29682011-02-19 12:05:57 -03001688 hci_op = HCI_OP_USER_CONFIRM_NEG_REPLY;
Brian Gixa68668b2011-08-11 15:49:36 -07001689 else
1690 hci_op = HCI_OP_USER_CONFIRM_REPLY;
Johan Hedberga5c29682011-02-19 12:05:57 -03001691
Brian Gixa68668b2011-08-11 15:49:36 -07001692 if (len < sizeof(*cp))
Szymon Jancbdce7ba2011-02-25 19:05:49 +01001693 return cmd_status(sk, index, mgmt_op, EINVAL);
1694
Szymon Janc4e51eae2011-02-25 19:05:48 +01001695 hdev = hci_dev_get(index);
Johan Hedberga5c29682011-02-19 12:05:57 -03001696 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +01001697 return cmd_status(sk, index, mgmt_op, ENODEV);
Johan Hedberga5c29682011-02-19 12:05:57 -03001698
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001699 hci_dev_lock_bh(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02001700
Johan Hedberga5c29682011-02-19 12:05:57 -03001701 if (!test_bit(HCI_UP, &hdev->flags)) {
Szymon Janc4e51eae2011-02-25 19:05:48 +01001702 err = cmd_status(sk, index, mgmt_op, ENETDOWN);
Brian Gixa68668b2011-08-11 15:49:36 -07001703 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03001704 }
1705
Brian Gixa68668b2011-08-11 15:49:36 -07001706 le_conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->bdaddr);
1707 if (le_conn) {
1708 err = le_user_confirm_reply(le_conn, mgmt_op, (void *) cp);
1709 goto done;
1710 }
1711 BT_DBG("BR/EDR: %s", mgmt_op == MGMT_OP_USER_CONFIRM_NEG_REPLY ?
1712 "Reject" : "Accept");
1713
Szymon Janc4e51eae2011-02-25 19:05:48 +01001714 cmd = mgmt_pending_add(sk, mgmt_op, index, data, len);
Johan Hedberga5c29682011-02-19 12:05:57 -03001715 if (!cmd) {
1716 err = -ENOMEM;
Brian Gixa68668b2011-08-11 15:49:36 -07001717 goto done;
1718 }
1719
1720 err = hci_send_cmd(hdev, hci_op, sizeof(cp->bdaddr), &cp->bdaddr);
1721 if (err < 0)
1722 mgmt_pending_remove(cmd);
1723
1724done:
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001725 hci_dev_unlock_bh(hdev);
Brian Gixa68668b2011-08-11 15:49:36 -07001726 hci_dev_put(hdev);
1727
1728 return err;
1729}
1730
1731static int resolve_name(struct sock *sk, u16 index, unsigned char *data,
1732 u16 len)
1733{
1734 struct mgmt_cp_resolve_name *mgmt_cp = (void *) data;
1735 struct hci_cp_remote_name_req hci_cp;
1736 struct hci_dev *hdev;
1737 struct pending_cmd *cmd;
1738 int err;
1739
1740 BT_DBG("");
1741
1742 if (len != sizeof(*mgmt_cp))
1743 return cmd_status(sk, index, MGMT_OP_RESOLVE_NAME, EINVAL);
1744
1745 hdev = hci_dev_get(index);
1746 if (!hdev)
1747 return cmd_status(sk, index, MGMT_OP_RESOLVE_NAME, ENODEV);
1748
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001749 hci_dev_lock_bh(hdev);
Brian Gixa68668b2011-08-11 15:49:36 -07001750
1751 cmd = mgmt_pending_add(sk, MGMT_OP_RESOLVE_NAME, index, data, len);
1752 if (!cmd) {
1753 err = -ENOMEM;
Johan Hedberga5c29682011-02-19 12:05:57 -03001754 goto failed;
1755 }
1756
Brian Gixa68668b2011-08-11 15:49:36 -07001757 memset(&hci_cp, 0, sizeof(hci_cp));
1758 bacpy(&hci_cp.bdaddr, &mgmt_cp->bdaddr);
1759 err = hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(hci_cp),
1760 &hci_cp);
Johan Hedberga664b5b2011-02-19 12:06:02 -03001761 if (err < 0)
1762 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03001763
1764failed:
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001765 hci_dev_unlock_bh(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03001766 hci_dev_put(hdev);
1767
1768 return err;
1769}
1770
Brian Gix7f7e16c2011-11-01 16:27:25 -07001771static int set_connection_params(struct sock *sk, u16 index,
1772 unsigned char *data, u16 len)
1773{
1774 struct mgmt_cp_set_connection_params *cp = (void *) data;
1775 struct hci_dev *hdev;
1776 struct hci_conn *conn;
1777 int err;
1778
1779 BT_DBG("");
1780
1781 if (len != sizeof(*cp))
1782 return cmd_status(sk, index, MGMT_OP_SET_CONNECTION_PARAMS,
1783 EINVAL);
1784
1785 hdev = hci_dev_get(index);
1786 if (!hdev)
1787 return cmd_status(sk, index, MGMT_OP_SET_CONNECTION_PARAMS,
1788 ENODEV);
1789
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001790 hci_dev_lock_bh(hdev);
Brian Gix7f7e16c2011-11-01 16:27:25 -07001791
1792 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->bdaddr);
1793 if (!conn) {
1794 err = cmd_status(sk, index, MGMT_OP_SET_CONNECTION_PARAMS,
1795 ENOTCONN);
1796 goto failed;
1797 }
1798
1799 hci_le_conn_update(conn, le16_to_cpu(cp->interval_min),
1800 le16_to_cpu(cp->interval_max),
1801 le16_to_cpu(cp->slave_latency),
1802 le16_to_cpu(cp->timeout_multiplier));
1803
1804 err = cmd_status(sk, index, MGMT_OP_SET_CONNECTION_PARAMS, 0);
1805
1806failed:
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001807 hci_dev_unlock_bh(hdev);
Brian Gix7f7e16c2011-11-01 16:27:25 -07001808 hci_dev_put(hdev);
1809
1810 return err;
1811}
1812
Johan Hedbergb312b1612011-03-16 14:29:37 +02001813static int set_local_name(struct sock *sk, u16 index, unsigned char *data,
1814 u16 len)
1815{
1816 struct mgmt_cp_set_local_name *mgmt_cp = (void *) data;
1817 struct hci_cp_write_local_name hci_cp;
1818 struct hci_dev *hdev;
1819 struct pending_cmd *cmd;
1820 int err;
1821
1822 BT_DBG("");
1823
1824 if (len != sizeof(*mgmt_cp))
1825 return cmd_status(sk, index, MGMT_OP_SET_LOCAL_NAME, EINVAL);
1826
1827 hdev = hci_dev_get(index);
1828 if (!hdev)
1829 return cmd_status(sk, index, MGMT_OP_SET_LOCAL_NAME, ENODEV);
1830
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001831 hci_dev_lock_bh(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02001832
1833 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, index, data, len);
1834 if (!cmd) {
1835 err = -ENOMEM;
1836 goto failed;
1837 }
1838
1839 memcpy(hci_cp.name, mgmt_cp->name, sizeof(hci_cp.name));
1840 err = hci_send_cmd(hdev, HCI_OP_WRITE_LOCAL_NAME, sizeof(hci_cp),
1841 &hci_cp);
1842 if (err < 0)
1843 mgmt_pending_remove(cmd);
1844
1845failed:
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001846 hci_dev_unlock_bh(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02001847 hci_dev_put(hdev);
1848
1849 return err;
1850}
1851
Brian Gixa68668b2011-08-11 15:49:36 -07001852static void discovery_rsp(struct pending_cmd *cmd, void *data)
1853{
1854 struct mgmt_mode ev;
1855
1856 BT_DBG("");
1857 if (cmd->opcode == MGMT_OP_START_DISCOVERY) {
1858 ev.val = 1;
1859 cmd_status(cmd->sk, cmd->index, MGMT_OP_START_DISCOVERY, 0);
1860 } else {
1861 ev.val = 0;
1862 cmd_complete(cmd->sk, cmd->index, MGMT_OP_STOP_DISCOVERY,
1863 NULL, 0);
1864 if (cmd->opcode == MGMT_OP_STOP_DISCOVERY) {
Brian Gix6e349d02011-11-28 14:51:14 -08001865 struct hci_dev *hdev = hci_dev_get(cmd->index);
1866 if (hdev) {
Brian Gix568dde92012-01-11 16:18:04 -08001867 del_timer(&hdev->disco_le_timer);
1868 del_timer(&hdev->disco_timer);
Brian Gix6e349d02011-11-28 14:51:14 -08001869 hci_dev_put(hdev);
1870 }
Brian Gixa68668b2011-08-11 15:49:36 -07001871 }
1872 }
1873
1874 mgmt_event(MGMT_EV_DISCOVERING, cmd->index, &ev, sizeof(ev), NULL);
1875
1876 list_del(&cmd->list);
1877
1878 mgmt_pending_free(cmd);
1879}
1880
1881void mgmt_inquiry_started(u16 index)
1882{
1883 BT_DBG("");
1884 mgmt_pending_foreach(MGMT_OP_START_DISCOVERY, index,
1885 discovery_rsp, NULL);
1886}
1887
1888void mgmt_inquiry_complete_evt(u16 index, u8 status)
1889{
1890 struct hci_dev *hdev;
1891 struct hci_cp_le_set_scan_enable le_cp = {1, 0};
Brian Gix568dde92012-01-11 16:18:04 -08001892 struct mgmt_mode cp = {0};
Brian Gixa68668b2011-08-11 15:49:36 -07001893 int err = -1;
1894
1895 BT_DBG("");
1896
1897 hdev = hci_dev_get(index);
Brian Gix64bd5302011-09-08 11:35:48 -07001898
Brian Gixa68668b2011-08-11 15:49:36 -07001899 if (!hdev || !lmp_le_capable(hdev)) {
Brian Gixa68668b2011-08-11 15:49:36 -07001900
1901 mgmt_pending_foreach(MGMT_OP_STOP_DISCOVERY, index,
1902 discovery_terminated, NULL);
1903
1904 mgmt_event(MGMT_EV_DISCOVERING, index, &cp, sizeof(cp), NULL);
Brian Gixa68668b2011-08-11 15:49:36 -07001905
Brian Gix64bd5302011-09-08 11:35:48 -07001906 if (hdev)
1907 goto done;
1908 else
1909 return;
1910 }
Brian Gixa68668b2011-08-11 15:49:36 -07001911
Brian Gix568dde92012-01-11 16:18:04 -08001912 if (hdev->disco_state != SCAN_IDLE) {
Brian Gixa68668b2011-08-11 15:49:36 -07001913 err = hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE,
1914 sizeof(le_cp), &le_cp);
Brian Gix568dde92012-01-11 16:18:04 -08001915 if (err >= 0) {
1916 mod_timer(&hdev->disco_le_timer, jiffies +
1917 msecs_to_jiffies(hdev->disco_int_phase * 1000));
1918 hdev->disco_state = SCAN_LE;
Brian Gixa68668b2011-08-11 15:49:36 -07001919 } else
Brian Gix568dde92012-01-11 16:18:04 -08001920 hdev->disco_state = SCAN_IDLE;
Brian Gixa68668b2011-08-11 15:49:36 -07001921 }
1922
Brian Gix568dde92012-01-11 16:18:04 -08001923 if (hdev->disco_state == SCAN_IDLE)
1924 mgmt_event(MGMT_EV_DISCOVERING, index, &cp, sizeof(cp), NULL);
1925
Brian Gixa68668b2011-08-11 15:49:36 -07001926 if (err < 0)
1927 mgmt_pending_foreach(MGMT_OP_STOP_DISCOVERY, index,
1928 discovery_terminated, NULL);
1929
Brian Gix64bd5302011-09-08 11:35:48 -07001930done:
Brian Gixa68668b2011-08-11 15:49:36 -07001931 hci_dev_put(hdev);
1932}
1933
Brian Gix568dde92012-01-11 16:18:04 -08001934void mgmt_disco_timeout(unsigned long data)
Brian Gixa68668b2011-08-11 15:49:36 -07001935{
Brian Gix568dde92012-01-11 16:18:04 -08001936 struct hci_dev *hdev = (void *) data;
Brian Gixa68668b2011-08-11 15:49:36 -07001937 struct pending_cmd *cmd;
Brian Gix568dde92012-01-11 16:18:04 -08001938 struct mgmt_mode cp = {0};
Brian Gixa68668b2011-08-11 15:49:36 -07001939
Brian Gix568dde92012-01-11 16:18:04 -08001940 BT_DBG("hci%d", hdev->id);
Brian Gixa68668b2011-08-11 15:49:36 -07001941
Brian Gix568dde92012-01-11 16:18:04 -08001942 hdev = hci_dev_get(hdev->id);
Brian Gixa68668b2011-08-11 15:49:36 -07001943
Brian Gix568dde92012-01-11 16:18:04 -08001944 if (!hdev)
1945 return;
Brian Gixa68668b2011-08-11 15:49:36 -07001946
Brian Gix568dde92012-01-11 16:18:04 -08001947 hci_dev_lock_bh(hdev);
1948 del_timer(&hdev->disco_le_timer);
Brian Gixa68668b2011-08-11 15:49:36 -07001949
Brian Gix568dde92012-01-11 16:18:04 -08001950 if (hdev->disco_state != SCAN_IDLE) {
1951 struct hci_cp_le_set_scan_enable le_cp = {0, 0};
Brian Gixa68668b2011-08-11 15:49:36 -07001952
Bhasker Netia6e6a4f2012-01-27 15:25:43 +05301953 if (test_bit(HCI_UP, &hdev->flags)) {
1954 if (hdev->disco_state == SCAN_LE)
1955 hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE,
Brian Gixa68668b2011-08-11 15:49:36 -07001956 sizeof(le_cp), &le_cp);
Bhasker Netia6e6a4f2012-01-27 15:25:43 +05301957 else
1958 hci_send_cmd(hdev, HCI_OP_INQUIRY_CANCEL, 0,
1959 NULL);
1960 }
Brian Gix568dde92012-01-11 16:18:04 -08001961 hdev->disco_state = SCAN_IDLE;
Brian Gixa68668b2011-08-11 15:49:36 -07001962 }
Brian Gix568dde92012-01-11 16:18:04 -08001963
1964 mgmt_event(MGMT_EV_DISCOVERING, hdev->id, &cp, sizeof(cp), NULL);
1965
1966 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev->id);
1967 if (cmd)
1968 mgmt_pending_remove(cmd);
1969
1970 hci_dev_unlock_bh(hdev);
1971 hci_dev_put(hdev);
1972}
1973
1974void mgmt_disco_le_timeout(unsigned long data)
1975{
1976 struct hci_dev *hdev = (void *)data;
1977 struct hci_cp_le_set_scan_enable le_cp = {0, 0};
1978
1979 BT_DBG("hci%d", hdev->id);
1980
1981 hdev = hci_dev_get(hdev->id);
1982
1983 if (!hdev)
1984 return;
1985
1986 hci_dev_lock_bh(hdev);
1987
Bhasker Netia6e6a4f2012-01-27 15:25:43 +05301988 if (test_bit(HCI_UP, &hdev->flags)) {
1989 if (hdev->disco_state == SCAN_LE)
1990 hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE,
1991 sizeof(le_cp), &le_cp);
Brian Gix568dde92012-01-11 16:18:04 -08001992
1993 /* re-start BR scan */
Bhasker Netia6e6a4f2012-01-27 15:25:43 +05301994 if (hdev->disco_state != SCAN_IDLE) {
1995 struct hci_cp_inquiry cp = {{0x33, 0x8b, 0x9e}, 4, 0};
1996 hdev->disco_int_phase *= 2;
1997 hdev->disco_int_count = 0;
1998 cp.num_rsp = (u8) hdev->disco_int_phase;
1999 hci_send_cmd(hdev, HCI_OP_INQUIRY, sizeof(cp), &cp);
2000 hdev->disco_state = SCAN_BR;
2001 }
Brian Gix568dde92012-01-11 16:18:04 -08002002 }
2003
2004 hci_dev_unlock_bh(hdev);
2005 hci_dev_put(hdev);
Brian Gixa68668b2011-08-11 15:49:36 -07002006}
2007
2008static int start_discovery(struct sock *sk, u16 index)
2009{
2010 struct hci_cp_inquiry cp = {{0x33, 0x8b, 0x9e}, 8, 0};
2011 struct hci_dev *hdev;
2012 struct pending_cmd *cmd;
2013 int err;
2014
2015 BT_DBG("");
2016
2017 hdev = hci_dev_get(index);
2018 if (!hdev)
2019 return cmd_status(sk, index, MGMT_OP_START_DISCOVERY, ENODEV);
2020
Subramanian Srinivasana727a492011-11-30 13:06:07 -08002021 hci_dev_lock_bh(hdev);
Brian Gixa68668b2011-08-11 15:49:36 -07002022
Brian Gix568dde92012-01-11 16:18:04 -08002023 if (hdev->disco_state && timer_pending(&hdev->disco_timer)) {
2024 err = -EBUSY;
2025 goto failed;
2026 }
2027
Brian Gixa68668b2011-08-11 15:49:36 -07002028 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, index, NULL, 0);
2029 if (!cmd) {
2030 err = -ENOMEM;
2031 goto failed;
2032 }
2033
2034 /* If LE Capable, we will alternate between BR/EDR and LE */
2035 if (lmp_le_capable(hdev)) {
2036 struct hci_cp_le_set_scan_parameters le_cp;
2037
2038 /* Shorten BR scan params */
2039 cp.num_rsp = 1;
2040 cp.length /= 2;
2041
2042 /* Setup LE scan params */
2043 memset(&le_cp, 0, sizeof(le_cp));
2044 le_cp.type = 0x01; /* Active scanning */
2045 /* The recommended value for scan interval and window is
2046 * 11.25 msec. It is calculated by: time = n * 0.625 msec */
2047 le_cp.interval = cpu_to_le16(0x0012);
2048 le_cp.window = cpu_to_le16(0x0012);
2049 le_cp.own_bdaddr_type = 0; /* Public address */
2050 le_cp.filter = 0; /* Accept all adv packets */
2051
2052 hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_PARAMETERS,
2053 sizeof(le_cp), &le_cp);
2054 }
2055
2056 err = hci_send_cmd(hdev, HCI_OP_INQUIRY, sizeof(cp), &cp);
2057
2058 if (err < 0)
2059 mgmt_pending_remove(cmd);
2060 else if (lmp_le_capable(hdev)) {
Brian Gix474e0f22012-01-14 20:21:55 -08002061 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, index);
2062 if (!cmd)
2063 mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, index,
2064 NULL, 0);
Brian Gix568dde92012-01-11 16:18:04 -08002065 hdev->disco_int_phase = 1;
2066 hdev->disco_int_count = 0;
2067 hdev->disco_state = SCAN_BR;
Brian Gix568dde92012-01-11 16:18:04 -08002068 del_timer(&hdev->disco_le_timer);
2069 del_timer(&hdev->disco_timer);
2070 mod_timer(&hdev->disco_timer,
2071 jiffies + msecs_to_jiffies(20000));
Brian Gixa68668b2011-08-11 15:49:36 -07002072 }
2073
2074failed:
Subramanian Srinivasana727a492011-11-30 13:06:07 -08002075 hci_dev_unlock_bh(hdev);
Brian Gixa68668b2011-08-11 15:49:36 -07002076 hci_dev_put(hdev);
2077
Brian Gix568dde92012-01-11 16:18:04 -08002078 if (err < 0)
2079 return cmd_status(sk, index, MGMT_OP_START_DISCOVERY, -err);
2080
Brian Gixa68668b2011-08-11 15:49:36 -07002081 return err;
2082}
2083
2084static int stop_discovery(struct sock *sk, u16 index)
2085{
2086 struct hci_cp_le_set_scan_enable le_cp = {0, 0};
2087 struct mgmt_mode mode_cp = {0};
Brian Gixa68668b2011-08-11 15:49:36 -07002088 struct hci_dev *hdev;
2089 struct pending_cmd *cmd = NULL;
2090 int err = -EPERM;
Brian Gix568dde92012-01-11 16:18:04 -08002091 u8 state;
Brian Gixa68668b2011-08-11 15:49:36 -07002092
2093 BT_DBG("");
2094
2095 hdev = hci_dev_get(index);
2096 if (!hdev)
2097 return cmd_status(sk, index, MGMT_OP_STOP_DISCOVERY, ENODEV);
2098
Subramanian Srinivasana727a492011-11-30 13:06:07 -08002099 hci_dev_lock_bh(hdev);
Brian Gixa68668b2011-08-11 15:49:36 -07002100
Brian Gix568dde92012-01-11 16:18:04 -08002101 state = hdev->disco_state;
2102 hdev->disco_state = SCAN_IDLE;
2103 del_timer(&hdev->disco_le_timer);
2104 del_timer(&hdev->disco_timer);
Brian Gixa68668b2011-08-11 15:49:36 -07002105
Brian Gix568dde92012-01-11 16:18:04 -08002106 if (state == SCAN_LE) {
Brian Gixa68668b2011-08-11 15:49:36 -07002107 err = hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE,
2108 sizeof(le_cp), &le_cp);
Brian Gix568dde92012-01-11 16:18:04 -08002109 if (err >= 0) {
2110 mgmt_pending_foreach(MGMT_OP_STOP_DISCOVERY, index,
2111 discovery_terminated, NULL);
Brian Gixa68668b2011-08-11 15:49:36 -07002112
Brian Gix568dde92012-01-11 16:18:04 -08002113 err = cmd_complete(sk, index, MGMT_OP_STOP_DISCOVERY,
2114 NULL, 0);
2115 }
Brian Gixa68668b2011-08-11 15:49:36 -07002116 }
2117
Brian Gix568dde92012-01-11 16:18:04 -08002118 if (err < 0)
2119 err = hci_send_cmd(hdev, HCI_OP_INQUIRY_CANCEL, 0, NULL);
Brian Gixa68668b2011-08-11 15:49:36 -07002120
Brian Gix568dde92012-01-11 16:18:04 -08002121 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, index);
Brian Gixa68668b2011-08-11 15:49:36 -07002122 if (err < 0 && cmd)
2123 mgmt_pending_remove(cmd);
2124
2125 mgmt_event(MGMT_EV_DISCOVERING, index, &mode_cp, sizeof(mode_cp), NULL);
2126
Subramanian Srinivasana727a492011-11-30 13:06:07 -08002127 hci_dev_unlock_bh(hdev);
Brian Gixa68668b2011-08-11 15:49:36 -07002128 hci_dev_put(hdev);
2129
2130 if (err < 0)
2131 return cmd_status(sk, index, MGMT_OP_STOP_DISCOVERY, -err);
2132 else
2133 return err;
2134}
2135
Szymon Jancc35938b2011-03-22 13:12:21 +01002136static int read_local_oob_data(struct sock *sk, u16 index)
2137{
2138 struct hci_dev *hdev;
2139 struct pending_cmd *cmd;
2140 int err;
2141
2142 BT_DBG("hci%u", index);
2143
2144 hdev = hci_dev_get(index);
2145 if (!hdev)
2146 return cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
2147 ENODEV);
2148
Subramanian Srinivasana727a492011-11-30 13:06:07 -08002149 hci_dev_lock_bh(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01002150
2151 if (!test_bit(HCI_UP, &hdev->flags)) {
2152 err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
2153 ENETDOWN);
2154 goto unlock;
2155 }
2156
2157 if (!(hdev->features[6] & LMP_SIMPLE_PAIR)) {
2158 err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
2159 EOPNOTSUPP);
2160 goto unlock;
2161 }
2162
2163 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, index)) {
2164 err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, EBUSY);
2165 goto unlock;
2166 }
2167
2168 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, index, NULL, 0);
2169 if (!cmd) {
2170 err = -ENOMEM;
2171 goto unlock;
2172 }
2173
2174 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
2175 if (err < 0)
2176 mgmt_pending_remove(cmd);
2177
2178unlock:
Subramanian Srinivasana727a492011-11-30 13:06:07 -08002179 hci_dev_unlock_bh(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01002180 hci_dev_put(hdev);
2181
2182 return err;
2183}
2184
Szymon Janc2763eda2011-03-22 13:12:22 +01002185static int add_remote_oob_data(struct sock *sk, u16 index, unsigned char *data,
2186 u16 len)
2187{
2188 struct hci_dev *hdev;
2189 struct mgmt_cp_add_remote_oob_data *cp = (void *) data;
2190 int err;
2191
2192 BT_DBG("hci%u ", index);
2193
2194 if (len != sizeof(*cp))
2195 return cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA,
2196 EINVAL);
2197
2198 hdev = hci_dev_get(index);
2199 if (!hdev)
2200 return cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA,
2201 ENODEV);
2202
Subramanian Srinivasana727a492011-11-30 13:06:07 -08002203 hci_dev_lock_bh(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01002204
2205 err = hci_add_remote_oob_data(hdev, &cp->bdaddr, cp->hash,
2206 cp->randomizer);
2207 if (err < 0)
2208 err = cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, -err);
2209 else
2210 err = cmd_complete(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, NULL,
2211 0);
2212
Subramanian Srinivasana727a492011-11-30 13:06:07 -08002213 hci_dev_unlock_bh(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01002214 hci_dev_put(hdev);
2215
2216 return err;
2217}
2218
2219static int remove_remote_oob_data(struct sock *sk, u16 index,
2220 unsigned char *data, u16 len)
2221{
2222 struct hci_dev *hdev;
2223 struct mgmt_cp_remove_remote_oob_data *cp = (void *) data;
2224 int err;
2225
2226 BT_DBG("hci%u ", index);
2227
2228 if (len != sizeof(*cp))
2229 return cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
2230 EINVAL);
2231
2232 hdev = hci_dev_get(index);
2233 if (!hdev)
2234 return cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
2235 ENODEV);
2236
Subramanian Srinivasana727a492011-11-30 13:06:07 -08002237 hci_dev_lock_bh(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01002238
2239 err = hci_remove_remote_oob_data(hdev, &cp->bdaddr);
2240 if (err < 0)
2241 err = cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
2242 -err);
2243 else
2244 err = cmd_complete(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
2245 NULL, 0);
2246
Subramanian Srinivasana727a492011-11-30 13:06:07 -08002247 hci_dev_unlock_bh(hdev);
Antti Julku58d19802011-06-15 12:01:15 +03002248 hci_dev_put(hdev);
2249
2250 return err;
2251}
2252
Johan Hedberg03811012010-12-08 00:21:06 +02002253int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
2254{
2255 unsigned char *buf;
2256 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01002257 u16 opcode, index, len;
Johan Hedberg03811012010-12-08 00:21:06 +02002258 int err;
2259
2260 BT_DBG("got %zu bytes", msglen);
2261
2262 if (msglen < sizeof(*hdr))
2263 return -EINVAL;
2264
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03002265 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02002266 if (!buf)
2267 return -ENOMEM;
2268
2269 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
2270 err = -EFAULT;
2271 goto done;
2272 }
2273
2274 hdr = (struct mgmt_hdr *) buf;
2275 opcode = get_unaligned_le16(&hdr->opcode);
Szymon Janc4e51eae2011-02-25 19:05:48 +01002276 index = get_unaligned_le16(&hdr->index);
Johan Hedberg03811012010-12-08 00:21:06 +02002277 len = get_unaligned_le16(&hdr->len);
2278
2279 if (len != msglen - sizeof(*hdr)) {
2280 err = -EINVAL;
2281 goto done;
2282 }
2283
Brian Gixa68668b2011-08-11 15:49:36 -07002284 BT_DBG("got opcode %x", opcode);
Johan Hedberg03811012010-12-08 00:21:06 +02002285 switch (opcode) {
Johan Hedberg02d98122010-12-13 21:07:04 +02002286 case MGMT_OP_READ_VERSION:
2287 err = read_version(sk);
2288 break;
Johan Hedbergfaba42e2010-12-13 21:07:05 +02002289 case MGMT_OP_READ_INDEX_LIST:
2290 err = read_index_list(sk);
2291 break;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02002292 case MGMT_OP_READ_INFO:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002293 err = read_controller_info(sk, index);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02002294 break;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002295 case MGMT_OP_SET_POWERED:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002296 err = set_powered(sk, index, buf + sizeof(*hdr), len);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002297 break;
Johan Hedberg73f22f62010-12-29 16:00:25 +02002298 case MGMT_OP_SET_DISCOVERABLE:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002299 err = set_discoverable(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg73f22f62010-12-29 16:00:25 +02002300 break;
Brian Gix8a7f1642011-10-17 17:39:46 -07002301 case MGMT_OP_SET_LIMIT_DISCOVERABLE:
2302 err = set_limited_discoverable(sk, index, buf + sizeof(*hdr),
2303 len);
2304 break;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02002305 case MGMT_OP_SET_CONNECTABLE:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002306 err = set_connectable(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02002307 break;
Johan Hedbergc542a062011-01-26 13:11:03 +02002308 case MGMT_OP_SET_PAIRABLE:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002309 err = set_pairable(sk, index, buf + sizeof(*hdr), len);
Johan Hedbergc542a062011-01-26 13:11:03 +02002310 break;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002311 case MGMT_OP_ADD_UUID:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002312 err = add_uuid(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002313 break;
2314 case MGMT_OP_REMOVE_UUID:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002315 err = remove_uuid(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002316 break;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002317 case MGMT_OP_SET_DEV_CLASS:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002318 err = set_dev_class(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002319 break;
2320 case MGMT_OP_SET_SERVICE_CACHE:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002321 err = set_service_cache(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002322 break;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002323 case MGMT_OP_LOAD_KEYS:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002324 err = load_keys(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002325 break;
2326 case MGMT_OP_REMOVE_KEY:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002327 err = remove_key(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002328 break;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002329 case MGMT_OP_DISCONNECT:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002330 err = disconnect(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002331 break;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002332 case MGMT_OP_GET_CONNECTIONS:
Szymon Janc8ce62842011-03-01 16:55:32 +01002333 err = get_connections(sk, index);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002334 break;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002335 case MGMT_OP_PIN_CODE_REPLY:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002336 err = pin_code_reply(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002337 break;
2338 case MGMT_OP_PIN_CODE_NEG_REPLY:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002339 err = pin_code_neg_reply(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002340 break;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002341 case MGMT_OP_SET_IO_CAPABILITY:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002342 err = set_io_capability(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002343 break;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002344 case MGMT_OP_PAIR_DEVICE:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002345 err = pair_device(sk, index, buf + sizeof(*hdr), len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002346 break;
Johan Hedberga5c29682011-02-19 12:05:57 -03002347 case MGMT_OP_USER_CONFIRM_REPLY:
Brian Gixa68668b2011-08-11 15:49:36 -07002348 case MGMT_OP_USER_PASSKEY_REPLY:
Johan Hedberga5c29682011-02-19 12:05:57 -03002349 case MGMT_OP_USER_CONFIRM_NEG_REPLY:
Brian Gixa68668b2011-08-11 15:49:36 -07002350 err = user_confirm_reply(sk, index, buf + sizeof(*hdr),
2351 len, opcode);
Johan Hedberga5c29682011-02-19 12:05:57 -03002352 break;
Johan Hedbergb312b1612011-03-16 14:29:37 +02002353 case MGMT_OP_SET_LOCAL_NAME:
2354 err = set_local_name(sk, index, buf + sizeof(*hdr), len);
2355 break;
Brian Gixa68668b2011-08-11 15:49:36 -07002356 case MGMT_OP_START_DISCOVERY:
2357 err = start_discovery(sk, index);
2358 break;
2359 case MGMT_OP_STOP_DISCOVERY:
2360 err = stop_discovery(sk, index);
2361 break;
2362 case MGMT_OP_RESOLVE_NAME:
2363 err = resolve_name(sk, index, buf + sizeof(*hdr), len);
2364 break;
Brian Gix7f7e16c2011-11-01 16:27:25 -07002365 case MGMT_OP_SET_CONNECTION_PARAMS:
2366 err = set_connection_params(sk, index, buf + sizeof(*hdr), len);
2367 break;
Szymon Jancc35938b2011-03-22 13:12:21 +01002368 case MGMT_OP_READ_LOCAL_OOB_DATA:
2369 err = read_local_oob_data(sk, index);
2370 break;
Szymon Janc2763eda2011-03-22 13:12:22 +01002371 case MGMT_OP_ADD_REMOTE_OOB_DATA:
2372 err = add_remote_oob_data(sk, index, buf + sizeof(*hdr), len);
2373 break;
2374 case MGMT_OP_REMOVE_REMOTE_OOB_DATA:
2375 err = remove_remote_oob_data(sk, index, buf + sizeof(*hdr),
2376 len);
2377 break;
Prabhakaran Mc46230fa2011-11-30 18:11:21 +05302378 case MGMT_OP_ENCRYPT_LINK:
2379 err = encrypt_link(sk, index, buf + sizeof(*hdr), len);
2380 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002381
Johan Hedberg03811012010-12-08 00:21:06 +02002382 default:
2383 BT_DBG("Unknown op %u", opcode);
Szymon Janc4e51eae2011-02-25 19:05:48 +01002384 err = cmd_status(sk, index, opcode, 0x01);
Johan Hedberg03811012010-12-08 00:21:06 +02002385 break;
2386 }
2387
Johan Hedberge41d8b42010-12-13 21:07:03 +02002388 if (err < 0)
2389 goto done;
2390
Johan Hedberg03811012010-12-08 00:21:06 +02002391 err = msglen;
2392
2393done:
2394 kfree(buf);
2395 return err;
2396}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02002397
Johan Hedbergc71e97b2010-12-13 21:07:07 +02002398int mgmt_index_added(u16 index)
2399{
Brian Gixa68668b2011-08-11 15:49:36 -07002400 BT_DBG("%d", index);
Szymon Janc4e51eae2011-02-25 19:05:48 +01002401 return mgmt_event(MGMT_EV_INDEX_ADDED, index, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02002402}
2403
2404int mgmt_index_removed(u16 index)
2405{
Brian Gixa68668b2011-08-11 15:49:36 -07002406 BT_DBG("%d", index);
Szymon Janc4e51eae2011-02-25 19:05:48 +01002407 return mgmt_event(MGMT_EV_INDEX_REMOVED, index, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002408}
2409
Johan Hedberg73f22f62010-12-29 16:00:25 +02002410struct cmd_lookup {
Johan Hedberg72a734e2010-12-30 00:38:22 +02002411 u8 val;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002412 struct sock *sk;
2413};
2414
Johan Hedberg72a734e2010-12-30 00:38:22 +02002415static void mode_rsp(struct pending_cmd *cmd, void *data)
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002416{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01002417 struct mgmt_mode *cp = cmd->param;
Johan Hedberg73f22f62010-12-29 16:00:25 +02002418 struct cmd_lookup *match = data;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002419
Johan Hedberg72a734e2010-12-30 00:38:22 +02002420 if (cp->val != match->val)
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002421 return;
2422
Johan Hedberg053f0212011-01-26 13:07:10 +02002423 send_mode_rsp(cmd->sk, cmd->opcode, cmd->index, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002424
2425 list_del(&cmd->list);
2426
2427 if (match->sk == NULL) {
2428 match->sk = cmd->sk;
2429 sock_hold(match->sk);
2430 }
2431
2432 mgmt_pending_free(cmd);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02002433}
Johan Hedberg5add6af2010-12-16 10:00:37 +02002434
2435int mgmt_powered(u16 index, u8 powered)
2436{
Johan Hedberg72a734e2010-12-30 00:38:22 +02002437 struct mgmt_mode ev;
Johan Hedberg73f22f62010-12-29 16:00:25 +02002438 struct cmd_lookup match = { powered, NULL };
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002439 int ret;
Johan Hedberg5add6af2010-12-16 10:00:37 +02002440
Brian Gixa68668b2011-08-11 15:49:36 -07002441 BT_DBG("hci%u %d", index, powered);
2442
Johan Hedberg72a734e2010-12-30 00:38:22 +02002443 mgmt_pending_foreach(MGMT_OP_SET_POWERED, index, mode_rsp, &match);
Johan Hedberg5add6af2010-12-16 10:00:37 +02002444
Johan Hedberg72a734e2010-12-30 00:38:22 +02002445 ev.val = powered;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002446
Szymon Janc4e51eae2011-02-25 19:05:48 +01002447 ret = mgmt_event(MGMT_EV_POWERED, index, &ev, sizeof(ev), match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002448
2449 if (match.sk)
2450 sock_put(match.sk);
2451
2452 return ret;
Johan Hedberg5add6af2010-12-16 10:00:37 +02002453}
Johan Hedberg73f22f62010-12-29 16:00:25 +02002454
Johan Hedberg73f22f62010-12-29 16:00:25 +02002455int mgmt_discoverable(u16 index, u8 discoverable)
2456{
Johan Hedberg72a734e2010-12-30 00:38:22 +02002457 struct mgmt_mode ev;
Johan Hedberg73f22f62010-12-29 16:00:25 +02002458 struct cmd_lookup match = { discoverable, NULL };
2459 int ret;
2460
Szymon Jancb8534e02011-03-01 16:55:34 +01002461 mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, index, mode_rsp, &match);
Johan Hedberg72a734e2010-12-30 00:38:22 +02002462
Johan Hedberg72a734e2010-12-30 00:38:22 +02002463 ev.val = discoverable;
Johan Hedberg73f22f62010-12-29 16:00:25 +02002464
Szymon Janc4e51eae2011-02-25 19:05:48 +01002465 ret = mgmt_event(MGMT_EV_DISCOVERABLE, index, &ev, sizeof(ev),
2466 match.sk);
Johan Hedberg73f22f62010-12-29 16:00:25 +02002467
2468 if (match.sk)
2469 sock_put(match.sk);
2470
2471 return ret;
2472}
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02002473
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02002474int mgmt_connectable(u16 index, u8 connectable)
2475{
Johan Hedberg72a734e2010-12-30 00:38:22 +02002476 struct mgmt_mode ev;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02002477 struct cmd_lookup match = { connectable, NULL };
2478 int ret;
2479
Johan Hedberg72a734e2010-12-30 00:38:22 +02002480 mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, index, mode_rsp, &match);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02002481
Johan Hedberg72a734e2010-12-30 00:38:22 +02002482 ev.val = connectable;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02002483
Szymon Janc4e51eae2011-02-25 19:05:48 +01002484 ret = mgmt_event(MGMT_EV_CONNECTABLE, index, &ev, sizeof(ev), match.sk);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02002485
2486 if (match.sk)
2487 sock_put(match.sk);
2488
2489 return ret;
2490}
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002491
Brian Gixa68668b2011-08-11 15:49:36 -07002492int mgmt_new_key(u16 index, struct link_key *key, u8 bonded)
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002493{
Vinicius Costa Gomesc00ddbf2011-07-08 18:31:44 -03002494 struct mgmt_ev_new_key *ev;
2495 int err, total;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002496
Vinicius Costa Gomesc00ddbf2011-07-08 18:31:44 -03002497 total = sizeof(struct mgmt_ev_new_key) + key->dlen;
2498 ev = kzalloc(total, GFP_ATOMIC);
2499 if (!ev)
2500 return -ENOMEM;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002501
Vinicius Costa Gomesc00ddbf2011-07-08 18:31:44 -03002502 bacpy(&ev->key.bdaddr, &key->bdaddr);
Brian Gixcf956772011-10-20 15:18:51 -07002503 ev->key.addr_type = key->addr_type;
2504 ev->key.key_type = key->key_type;
Vinicius Costa Gomesc00ddbf2011-07-08 18:31:44 -03002505 memcpy(ev->key.val, key->val, 16);
2506 ev->key.pin_len = key->pin_len;
Brian Gixa68668b2011-08-11 15:49:36 -07002507 ev->key.auth = key->auth;
2508 ev->store_hint = bonded;
Vinicius Costa Gomesc00ddbf2011-07-08 18:31:44 -03002509 ev->key.dlen = key->dlen;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002510
Vinicius Costa Gomesc00ddbf2011-07-08 18:31:44 -03002511 memcpy(ev->key.data, key->data, key->dlen);
2512
2513 err = mgmt_event(MGMT_EV_NEW_KEY, index, ev, total, NULL);
2514
2515 kfree(ev);
2516
2517 return err;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002518}
Johan Hedbergf7520542011-01-20 12:34:39 +02002519
Brian Gix2e2f50d2011-09-13 12:36:04 -07002520int mgmt_connected(u16 index, bdaddr_t *bdaddr, u8 le)
Johan Hedbergf7520542011-01-20 12:34:39 +02002521{
2522 struct mgmt_ev_connected ev;
2523
Johan Hedbergf7520542011-01-20 12:34:39 +02002524 bacpy(&ev.bdaddr, bdaddr);
Brian Gix2e2f50d2011-09-13 12:36:04 -07002525 ev.le = le;
Johan Hedbergf7520542011-01-20 12:34:39 +02002526
Szymon Janc4e51eae2011-02-25 19:05:48 +01002527 return mgmt_event(MGMT_EV_CONNECTED, index, &ev, sizeof(ev), NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02002528}
2529
Johan Hedberg8962ee72011-01-20 12:40:27 +02002530static void disconnect_rsp(struct pending_cmd *cmd, void *data)
2531{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01002532 struct mgmt_cp_disconnect *cp = cmd->param;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002533 struct sock **sk = data;
Johan Hedberga38528f2011-01-22 06:46:43 +02002534 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002535
Johan Hedberga38528f2011-01-22 06:46:43 +02002536 bacpy(&rp.bdaddr, &cp->bdaddr);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002537
Szymon Janc4e51eae2011-02-25 19:05:48 +01002538 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002539
2540 *sk = cmd->sk;
2541 sock_hold(*sk);
2542
Johan Hedberga664b5b2011-02-19 12:06:02 -03002543 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002544}
2545
Johan Hedbergf7520542011-01-20 12:34:39 +02002546int mgmt_disconnected(u16 index, bdaddr_t *bdaddr)
2547{
2548 struct mgmt_ev_disconnected ev;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002549 struct sock *sk = NULL;
2550 int err;
2551
2552 mgmt_pending_foreach(MGMT_OP_DISCONNECT, index, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02002553
Johan Hedbergf7520542011-01-20 12:34:39 +02002554 bacpy(&ev.bdaddr, bdaddr);
2555
Szymon Janc4e51eae2011-02-25 19:05:48 +01002556 err = mgmt_event(MGMT_EV_DISCONNECTED, index, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002557
2558 if (sk)
2559 sock_put(sk);
2560
2561 return err;
2562}
2563
2564int mgmt_disconnect_failed(u16 index)
2565{
2566 struct pending_cmd *cmd;
2567 int err;
2568
2569 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, index);
2570 if (!cmd)
2571 return -ENOENT;
2572
Szymon Janc4e51eae2011-02-25 19:05:48 +01002573 err = cmd_status(cmd->sk, index, MGMT_OP_DISCONNECT, EIO);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002574
Johan Hedberga664b5b2011-02-19 12:06:02 -03002575 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002576
2577 return err;
Johan Hedbergf7520542011-01-20 12:34:39 +02002578}
Johan Hedberg17d5c042011-01-22 06:09:08 +02002579
2580int mgmt_connect_failed(u16 index, bdaddr_t *bdaddr, u8 status)
2581{
2582 struct mgmt_ev_connect_failed ev;
2583
Johan Hedberg17d5c042011-01-22 06:09:08 +02002584 bacpy(&ev.bdaddr, bdaddr);
2585 ev.status = status;
2586
Szymon Janc4e51eae2011-02-25 19:05:48 +01002587 return mgmt_event(MGMT_EV_CONNECT_FAILED, index, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02002588}
Johan Hedberg980e1a52011-01-22 06:10:07 +02002589
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002590int mgmt_pin_code_request(u16 index, bdaddr_t *bdaddr)
Johan Hedberg980e1a52011-01-22 06:10:07 +02002591{
2592 struct mgmt_ev_pin_code_request ev;
2593
Brian Gixa68668b2011-08-11 15:49:36 -07002594 BT_DBG("hci%u", index);
2595
Johan Hedberg980e1a52011-01-22 06:10:07 +02002596 bacpy(&ev.bdaddr, bdaddr);
Brian Gixa68668b2011-08-11 15:49:36 -07002597 ev.secure = 0;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002598
Szymon Janc4e51eae2011-02-25 19:05:48 +01002599 return mgmt_event(MGMT_EV_PIN_CODE_REQUEST, index, &ev, sizeof(ev),
2600 NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002601}
2602
2603int mgmt_pin_code_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status)
2604{
2605 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03002606 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002607 int err;
2608
2609 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, index);
2610 if (!cmd)
2611 return -ENOENT;
2612
Johan Hedbergac56fb12011-02-19 12:05:59 -03002613 bacpy(&rp.bdaddr, bdaddr);
2614 rp.status = status;
2615
Szymon Janc4e51eae2011-02-25 19:05:48 +01002616 err = cmd_complete(cmd->sk, index, MGMT_OP_PIN_CODE_REPLY, &rp,
2617 sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02002618
Johan Hedberga664b5b2011-02-19 12:06:02 -03002619 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002620
2621 return err;
2622}
2623
2624int mgmt_pin_code_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status)
2625{
2626 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03002627 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002628 int err;
2629
2630 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, index);
2631 if (!cmd)
2632 return -ENOENT;
2633
Johan Hedbergac56fb12011-02-19 12:05:59 -03002634 bacpy(&rp.bdaddr, bdaddr);
2635 rp.status = status;
2636
Szymon Janc4e51eae2011-02-25 19:05:48 +01002637 err = cmd_complete(cmd->sk, index, MGMT_OP_PIN_CODE_NEG_REPLY, &rp,
2638 sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02002639
Johan Hedberga664b5b2011-02-19 12:06:02 -03002640 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002641
2642 return err;
2643}
Johan Hedberga5c29682011-02-19 12:05:57 -03002644
Brian Gixa68668b2011-08-11 15:49:36 -07002645int mgmt_user_confirm_request(u16 index, u8 event,
2646 bdaddr_t *bdaddr, __le32 value)
Johan Hedberga5c29682011-02-19 12:05:57 -03002647{
2648 struct mgmt_ev_user_confirm_request ev;
Brian Gixa68668b2011-08-11 15:49:36 -07002649 struct hci_conn *conn = NULL;
2650 struct hci_dev *hdev;
2651 u8 loc_cap, rem_cap, loc_mitm, rem_mitm;
2652
2653 BT_DBG("hci%u", index);
2654
2655 hdev = hci_dev_get(index);
2656
Brian Gix64bd5302011-09-08 11:35:48 -07002657 if (!hdev)
2658 return -ENODEV;
2659
Brian Gix64bd5302011-09-08 11:35:48 -07002660 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, bdaddr);
Brian Gixa68668b2011-08-11 15:49:36 -07002661
2662 ev.auto_confirm = 0;
2663
2664 if (!conn || event != HCI_EV_USER_CONFIRM_REQUEST)
2665 goto no_auto_confirm;
2666
2667 loc_cap = (conn->io_capability == 0x04) ? 0x01 : conn->io_capability;
2668 rem_cap = conn->remote_cap;
2669 loc_mitm = conn->auth_type & 0x01;
2670 rem_mitm = conn->remote_auth & 0x01;
2671
Brian Gixdbf59292011-11-11 15:45:17 -08002672 if ((conn->auth_type & HCI_AT_DEDICATED_BONDING) &&
2673 conn->auth_initiator && rem_cap == 0x03)
2674 ev.auto_confirm = 1;
AnubhavGupta07c2a0f2012-02-16 19:03:59 +05302675 else if (loc_cap == 0x01 && (rem_cap == 0x00 || rem_cap == 0x03)) {
2676 if (!loc_mitm && !rem_mitm)
2677 value = 0;
Brian Gixa68668b2011-08-11 15:49:36 -07002678 goto no_auto_confirm;
AnubhavGupta07c2a0f2012-02-16 19:03:59 +05302679 }
Brian Gixa68668b2011-08-11 15:49:36 -07002680
2681
2682 if ((!loc_mitm || rem_cap == 0x03) && (!rem_mitm || loc_cap == 0x03))
2683 ev.auto_confirm = 1;
2684
2685no_auto_confirm:
2686 bacpy(&ev.bdaddr, bdaddr);
2687 ev.event = event;
2688 put_unaligned_le32(value, &ev.value);
2689
Brian Gix64bd5302011-09-08 11:35:48 -07002690 hci_dev_put(hdev);
2691
Brian Gixa68668b2011-08-11 15:49:36 -07002692 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, index, &ev, sizeof(ev),
2693 NULL);
2694}
2695
2696int mgmt_user_passkey_request(u16 index, bdaddr_t *bdaddr)
2697{
2698 struct mgmt_ev_user_passkey_request ev;
Johan Hedberga5c29682011-02-19 12:05:57 -03002699
2700 BT_DBG("hci%u", index);
2701
Johan Hedberga5c29682011-02-19 12:05:57 -03002702 bacpy(&ev.bdaddr, bdaddr);
Johan Hedberga5c29682011-02-19 12:05:57 -03002703
Brian Gixa68668b2011-08-11 15:49:36 -07002704 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, index, &ev, sizeof(ev),
Szymon Janc4e51eae2011-02-25 19:05:48 +01002705 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03002706}
2707
2708static int confirm_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status,
2709 u8 opcode)
2710{
2711 struct pending_cmd *cmd;
2712 struct mgmt_rp_user_confirm_reply rp;
2713 int err;
2714
2715 cmd = mgmt_pending_find(opcode, index);
2716 if (!cmd)
2717 return -ENOENT;
2718
Johan Hedberga5c29682011-02-19 12:05:57 -03002719 bacpy(&rp.bdaddr, bdaddr);
2720 rp.status = status;
Szymon Janc4e51eae2011-02-25 19:05:48 +01002721 err = cmd_complete(cmd->sk, index, opcode, &rp, sizeof(rp));
Johan Hedberga5c29682011-02-19 12:05:57 -03002722
Johan Hedberga664b5b2011-02-19 12:06:02 -03002723 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03002724
2725 return err;
2726}
2727
2728int mgmt_user_confirm_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status)
2729{
2730 return confirm_reply_complete(index, bdaddr, status,
2731 MGMT_OP_USER_CONFIRM_REPLY);
2732}
2733
Szymon Jancb8534e02011-03-01 16:55:34 +01002734int mgmt_user_confirm_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03002735{
2736 return confirm_reply_complete(index, bdaddr, status,
2737 MGMT_OP_USER_CONFIRM_NEG_REPLY);
2738}
Johan Hedberg2a611692011-02-19 12:06:00 -03002739
2740int mgmt_auth_failed(u16 index, bdaddr_t *bdaddr, u8 status)
2741{
2742 struct mgmt_ev_auth_failed ev;
2743
Johan Hedberg2a611692011-02-19 12:06:00 -03002744 bacpy(&ev.bdaddr, bdaddr);
2745 ev.status = status;
2746
Szymon Janc4e51eae2011-02-25 19:05:48 +01002747 return mgmt_event(MGMT_EV_AUTH_FAILED, index, &ev, sizeof(ev), NULL);
Johan Hedberg2a611692011-02-19 12:06:00 -03002748}
Johan Hedbergb312b1612011-03-16 14:29:37 +02002749
2750int mgmt_set_local_name_complete(u16 index, u8 *name, u8 status)
2751{
2752 struct pending_cmd *cmd;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002753 struct hci_dev *hdev;
Johan Hedbergb312b1612011-03-16 14:29:37 +02002754 struct mgmt_cp_set_local_name ev;
2755 int err;
2756
2757 memset(&ev, 0, sizeof(ev));
2758 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
2759
2760 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, index);
2761 if (!cmd)
2762 goto send_event;
2763
2764 if (status) {
2765 err = cmd_status(cmd->sk, index, MGMT_OP_SET_LOCAL_NAME, EIO);
2766 goto failed;
2767 }
2768
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002769 hdev = hci_dev_get(index);
2770 if (hdev) {
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002771 update_eir(hdev);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002772 hci_dev_put(hdev);
2773 }
2774
Johan Hedbergb312b1612011-03-16 14:29:37 +02002775 err = cmd_complete(cmd->sk, index, MGMT_OP_SET_LOCAL_NAME, &ev,
2776 sizeof(ev));
2777 if (err < 0)
2778 goto failed;
2779
2780send_event:
2781 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, index, &ev, sizeof(ev),
2782 cmd ? cmd->sk : NULL);
2783
2784failed:
2785 if (cmd)
2786 mgmt_pending_remove(cmd);
2787 return err;
2788}
Szymon Jancc35938b2011-03-22 13:12:21 +01002789
2790int mgmt_read_local_oob_data_reply_complete(u16 index, u8 *hash, u8 *randomizer,
2791 u8 status)
2792{
2793 struct pending_cmd *cmd;
2794 int err;
2795
2796 BT_DBG("hci%u status %u", index, status);
2797
2798 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, index);
2799 if (!cmd)
2800 return -ENOENT;
2801
2802 if (status) {
2803 err = cmd_status(cmd->sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
2804 EIO);
2805 } else {
2806 struct mgmt_rp_read_local_oob_data rp;
2807
2808 memcpy(rp.hash, hash, sizeof(rp.hash));
2809 memcpy(rp.randomizer, randomizer, sizeof(rp.randomizer));
2810
2811 err = cmd_complete(cmd->sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
2812 &rp, sizeof(rp));
2813 }
2814
2815 mgmt_pending_remove(cmd);
2816
2817 return err;
2818}
Johan Hedberge17acd42011-03-30 23:57:16 +03002819
Brian Gixa68668b2011-08-11 15:49:36 -07002820int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 type, u8 le,
2821 u8 *dev_class, s8 rssi, u8 eir_len, u8 *eir)
Johan Hedberge17acd42011-03-30 23:57:16 +03002822{
2823 struct mgmt_ev_device_found ev;
Brian Gix568dde92012-01-11 16:18:04 -08002824 struct hci_dev *hdev;
Brian Gixa68668b2011-08-11 15:49:36 -07002825 int err;
2826
2827 BT_DBG("le: %d", le);
Johan Hedberge17acd42011-03-30 23:57:16 +03002828
2829 memset(&ev, 0, sizeof(ev));
2830
2831 bacpy(&ev.bdaddr, bdaddr);
Johan Hedberge17acd42011-03-30 23:57:16 +03002832 ev.rssi = rssi;
Brian Gixa68668b2011-08-11 15:49:36 -07002833 ev.type = type;
2834 ev.le = le;
Johan Hedberge17acd42011-03-30 23:57:16 +03002835
Brian Gixa68668b2011-08-11 15:49:36 -07002836 if (dev_class)
2837 memcpy(ev.dev_class, dev_class, sizeof(ev.dev_class));
Johan Hedberge17acd42011-03-30 23:57:16 +03002838
Brian Gixa68668b2011-08-11 15:49:36 -07002839 if (eir && eir_len)
2840 memcpy(ev.eir, eir, eir_len);
2841
2842 err = mgmt_event(MGMT_EV_DEVICE_FOUND, index, &ev, sizeof(ev), NULL);
2843
2844 if (err < 0)
2845 return err;
2846
Brian Gix568dde92012-01-11 16:18:04 -08002847 hdev = hci_dev_get(index);
Brian Gixa68668b2011-08-11 15:49:36 -07002848
Brian Gix568dde92012-01-11 16:18:04 -08002849 if (!hdev)
2850 return 0;
Brian Gix64bd5302011-09-08 11:35:48 -07002851
Brian Gix568dde92012-01-11 16:18:04 -08002852 if (hdev->disco_state == SCAN_IDLE)
2853 goto done;
2854
2855 hdev->disco_int_count++;
2856
2857 if (hdev->disco_int_count >= hdev->disco_int_phase) {
2858 /* Inquiry scan for General Discovery LAP */
2859 struct hci_cp_inquiry cp = {{0x33, 0x8b, 0x9e}, 4, 0};
2860 struct hci_cp_le_set_scan_enable le_cp = {0, 0};
2861
2862 hdev->disco_int_phase *= 2;
2863 hdev->disco_int_count = 0;
2864 if (hdev->disco_state == SCAN_LE) {
2865 /* cancel LE scan */
2866 hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE,
2867 sizeof(le_cp), &le_cp);
2868 /* start BR scan */
2869 cp.num_rsp = (u8) hdev->disco_int_phase;
2870 hci_send_cmd(hdev, HCI_OP_INQUIRY,
2871 sizeof(cp), &cp);
2872 hdev->disco_state = SCAN_BR;
2873 del_timer_sync(&hdev->disco_le_timer);
Brian Gixa68668b2011-08-11 15:49:36 -07002874 }
2875 }
2876
Brian Gix568dde92012-01-11 16:18:04 -08002877done:
2878 hci_dev_put(hdev);
Brian Gixa68668b2011-08-11 15:49:36 -07002879 return 0;
Johan Hedberge17acd42011-03-30 23:57:16 +03002880}
Johan Hedberga88a9652011-03-30 13:18:12 +03002881
Brian Gixa68668b2011-08-11 15:49:36 -07002882
2883int mgmt_remote_name(u16 index, bdaddr_t *bdaddr, u8 status, u8 *name)
Johan Hedberga88a9652011-03-30 13:18:12 +03002884{
2885 struct mgmt_ev_remote_name ev;
2886
2887 memset(&ev, 0, sizeof(ev));
2888
2889 bacpy(&ev.bdaddr, bdaddr);
Brian Gixa68668b2011-08-11 15:49:36 -07002890 ev.status = status;
Johan Hedberga88a9652011-03-30 13:18:12 +03002891 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
2892
2893 return mgmt_event(MGMT_EV_REMOTE_NAME, index, &ev, sizeof(ev), NULL);
2894}
Prabhakaran Mc46230fa2011-11-30 18:11:21 +05302895
2896int mgmt_encrypt_change(u16 index, bdaddr_t *bdaddr, u8 status)
2897{
2898 struct mgmt_ev_encrypt_change ev;
2899
2900 BT_DBG("hci%u", index);
2901
2902 bacpy(&ev.bdaddr, bdaddr);
2903 ev.status = status;
2904
2905 return mgmt_event(MGMT_EV_ENCRYPT_CHANGE, index, &ev, sizeof(ev),
2906 NULL);
2907}
2908
Srinivas Krovvidi0916aed2011-12-20 12:06:34 +05302909int mgmt_remote_class(u16 index, bdaddr_t *bdaddr, u8 dev_class[3])
2910{
2911 struct mgmt_ev_remote_class ev;
2912
2913 memset(&ev, 0, sizeof(ev));
2914
2915 bacpy(&ev.bdaddr, bdaddr);
2916 memcpy(ev.dev_class, dev_class, 3);
2917
2918 return mgmt_event(MGMT_EV_REMOTE_CLASS, index, &ev, sizeof(ev), NULL);
2919}
Srinivas Krovvidid352b262012-01-12 19:46:26 +05302920
2921int mgmt_remote_version(u16 index, bdaddr_t *bdaddr, u8 ver, u16 mnf,
2922 u16 sub_ver)
2923{
2924 struct mgmt_ev_remote_version ev;
2925
2926 memset(&ev, 0, sizeof(ev));
2927
2928 bacpy(&ev.bdaddr, bdaddr);
2929 ev.lmp_ver = ver;
2930 ev.manufacturer = mnf;
2931 ev.lmp_subver = sub_ver;
2932
2933 return mgmt_event(MGMT_EV_REMOTE_VERSION, index, &ev, sizeof(ev), NULL);
2934}