blob: 80f4bd6d3fa63665ad92a6f6d8d663f002929321 [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
Brian Gix384ec672012-03-08 18:41:15 -08001356 hci_dev_lock_bh(hdev);
Prabhakaran Mc46230fa2011-11-30 18:11:21 +05301357
1358 if (!test_bit(HCI_UP, &hdev->flags)) {
1359 err = cmd_status(sk, index, MGMT_OP_ENCRYPT_LINK, ENETDOWN);
Brian Gix384ec672012-03-08 18:41:15 -08001360 goto done;
Prabhakaran Mc46230fa2011-11-30 18:11:21 +05301361 }
1362
Brian Gix384ec672012-03-08 18:41:15 -08001363 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1364 if (!conn) {
1365 err = cmd_status(sk, index, MGMT_OP_ENCRYPT_LINK, ENOTCONN);
1366 goto done;
1367 }
Prabhakaran Mc46230fa2011-11-30 18:11:21 +05301368
Brian Gix384ec672012-03-08 18:41:15 -08001369 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
1370 err = cmd_status(sk, index, MGMT_OP_ENCRYPT_LINK, EINPROGRESS);
1371 goto done;
1372 }
Prabhakaran Mc46230fa2011-11-30 18:11:21 +05301373
1374 if (conn->link_mode & HCI_LM_AUTH) {
1375 enc.handle = cpu_to_le16(conn->handle);
1376 enc.encrypt = cp->enable;
1377 err = hci_send_cmd(hdev,
1378 HCI_OP_SET_CONN_ENCRYPT, sizeof(enc), &enc);
1379 } else {
1380 conn->auth_initiator = 1;
1381 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
1382 struct hci_cp_auth_requested cp;
1383 cp.handle = cpu_to_le16(conn->handle);
1384 err = hci_send_cmd(conn->hdev,
1385 HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1386 }
1387 }
1388
Brian Gix384ec672012-03-08 18:41:15 -08001389done:
1390 hci_dev_unlock_bh(hdev);
Prabhakaran Mc46230fa2011-11-30 18:11:21 +05301391 hci_dev_put(hdev);
1392
1393 return err;
1394}
1395
1396
Szymon Janc4e51eae2011-02-25 19:05:48 +01001397static int pin_code_neg_reply(struct sock *sk, u16 index, unsigned char *data,
1398 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02001399{
1400 struct hci_dev *hdev;
1401 struct mgmt_cp_pin_code_neg_reply *cp;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001402 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02001403 int err;
1404
1405 BT_DBG("");
1406
1407 cp = (void *) data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02001408
Szymon Jancbdce7ba2011-02-25 19:05:49 +01001409 if (len != sizeof(*cp))
1410 return cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY,
1411 EINVAL);
1412
Szymon Janc4e51eae2011-02-25 19:05:48 +01001413 hdev = hci_dev_get(index);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001414 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +01001415 return cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY,
1416 ENODEV);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001417
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001418 hci_dev_lock_bh(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001419
1420 if (!test_bit(HCI_UP, &hdev->flags)) {
Szymon Janc4e51eae2011-02-25 19:05:48 +01001421 err = cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY,
1422 ENETDOWN);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001423 goto failed;
1424 }
1425
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001426 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, index,
1427 data, len);
1428 if (!cmd) {
1429 err = -ENOMEM;
1430 goto failed;
1431 }
1432
1433 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, sizeof(cp->bdaddr),
1434 &cp->bdaddr);
1435 if (err < 0)
1436 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001437
1438failed:
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001439 hci_dev_unlock_bh(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001440 hci_dev_put(hdev);
1441
1442 return err;
1443}
1444
Szymon Janc4e51eae2011-02-25 19:05:48 +01001445static int set_io_capability(struct sock *sk, u16 index, unsigned char *data,
1446 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02001447{
1448 struct hci_dev *hdev;
1449 struct mgmt_cp_set_io_capability *cp;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02001450
1451 BT_DBG("");
1452
1453 cp = (void *) data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02001454
Szymon Jancbdce7ba2011-02-25 19:05:49 +01001455 if (len != sizeof(*cp))
Szymon Jancb8534e02011-03-01 16:55:34 +01001456 return cmd_status(sk, index, MGMT_OP_SET_IO_CAPABILITY, EINVAL);
Szymon Jancbdce7ba2011-02-25 19:05:49 +01001457
Szymon Janc4e51eae2011-02-25 19:05:48 +01001458 hdev = hci_dev_get(index);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02001459 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +01001460 return cmd_status(sk, index, MGMT_OP_SET_IO_CAPABILITY, ENODEV);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02001461
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001462 hci_dev_lock_bh(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02001463
1464 hdev->io_capability = cp->io_capability;
1465
1466 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Szymon Jancb8534e02011-03-01 16:55:34 +01001467 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02001468
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001469 hci_dev_unlock_bh(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02001470 hci_dev_put(hdev);
1471
Szymon Janc4e51eae2011-02-25 19:05:48 +01001472 return cmd_complete(sk, index, MGMT_OP_SET_IO_CAPABILITY, NULL, 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02001473}
1474
Johan Hedberge9a416b2011-02-19 12:05:56 -03001475static inline struct pending_cmd *find_pairing(struct hci_conn *conn)
1476{
1477 struct hci_dev *hdev = conn->hdev;
1478 struct list_head *p;
1479
1480 list_for_each(p, &cmd_list) {
1481 struct pending_cmd *cmd;
1482
1483 cmd = list_entry(p, struct pending_cmd, list);
1484
1485 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
1486 continue;
1487
1488 if (cmd->index != hdev->id)
1489 continue;
1490
1491 if (cmd->user_data != conn)
1492 continue;
1493
1494 return cmd;
1495 }
1496
1497 return NULL;
1498}
1499
1500static void pairing_complete(struct pending_cmd *cmd, u8 status)
1501{
1502 struct mgmt_rp_pair_device rp;
1503 struct hci_conn *conn = cmd->user_data;
1504
Brian Gixa68668b2011-08-11 15:49:36 -07001505 BT_DBG(" %u", status);
1506
Johan Hedberge9a416b2011-02-19 12:05:56 -03001507 bacpy(&rp.bdaddr, &conn->dst);
1508 rp.status = status;
1509
Szymon Janc4e51eae2011-02-25 19:05:48 +01001510 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03001511
1512 /* So we don't get further callbacks for this connection */
1513 conn->connect_cfm_cb = NULL;
1514 conn->security_cfm_cb = NULL;
1515 conn->disconn_cfm_cb = NULL;
1516
Johan Hedberga664b5b2011-02-19 12:06:02 -03001517 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03001518}
1519
1520static void pairing_complete_cb(struct hci_conn *conn, u8 status)
1521{
1522 struct pending_cmd *cmd;
1523
Brian Gixa68668b2011-08-11 15:49:36 -07001524 BT_DBG(" %u", status);
Johan Hedberge9a416b2011-02-19 12:05:56 -03001525
1526 cmd = find_pairing(conn);
1527 if (!cmd) {
1528 BT_DBG("Unable to find a pending command");
1529 return;
1530 }
1531
1532 pairing_complete(cmd, status);
Brian Gix80fb3a92012-01-31 13:15:20 -08001533 hci_conn_put(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03001534}
1535
Brian Gix6d5fb8a2011-09-09 14:53:04 -07001536static void pairing_security_complete_cb(struct hci_conn *conn, u8 status)
Brian Gixa68668b2011-08-11 15:49:36 -07001537{
1538 struct pending_cmd *cmd;
1539
1540 BT_DBG(" %u", status);
1541
1542 cmd = find_pairing(conn);
1543 if (!cmd) {
1544 BT_DBG("Unable to find a pending command");
1545 return;
1546 }
1547
1548 if (conn->type == LE_LINK)
1549 smp_link_encrypt_cmplt(conn->l2cap_data, status,
1550 status ? 0 : 1);
1551 else
1552 pairing_complete(cmd, status);
1553}
1554
Brian Gix6d5fb8a2011-09-09 14:53:04 -07001555static void pairing_connect_complete_cb(struct hci_conn *conn, u8 status)
Brian Gixa68668b2011-08-11 15:49:36 -07001556{
1557 struct pending_cmd *cmd;
1558
1559 BT_DBG("conn: %p %u", conn, status);
1560
1561 cmd = find_pairing(conn);
1562 if (!cmd) {
1563 BT_DBG("Unable to find a pending command");
1564 return;
1565 }
Brian Gix114f3a62011-09-27 14:02:20 -07001566
1567 if (status)
1568 pairing_complete(cmd, status);
1569
Brian Gix6d5fb8a2011-09-09 14:53:04 -07001570 hci_conn_put(conn);
Brian Gixa68668b2011-08-11 15:49:36 -07001571}
1572
1573static void discovery_terminated(struct pending_cmd *cmd, void *data)
1574{
Brian Gix6e349d02011-11-28 14:51:14 -08001575 struct hci_dev *hdev;
Brian Gixa68668b2011-08-11 15:49:36 -07001576 struct mgmt_mode ev = {0};
Brian Gixa68668b2011-08-11 15:49:36 -07001577
1578 BT_DBG("");
Brian Gix6e349d02011-11-28 14:51:14 -08001579 hdev = hci_dev_get(cmd->index);
1580 if (!hdev)
1581 goto not_found;
1582
Brian Gix568dde92012-01-11 16:18:04 -08001583 del_timer(&hdev->disco_le_timer);
1584 del_timer(&hdev->disco_timer);
Brian Gix6e349d02011-11-28 14:51:14 -08001585 hci_dev_put(hdev);
1586
1587not_found:
Brian Gixa68668b2011-08-11 15:49:36 -07001588 mgmt_event(MGMT_EV_DISCOVERING, cmd->index, &ev, sizeof(ev), NULL);
1589
1590 list_del(&cmd->list);
1591
1592 mgmt_pending_free(cmd);
1593}
1594
Szymon Janc4e51eae2011-02-25 19:05:48 +01001595static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03001596{
1597 struct hci_dev *hdev;
1598 struct mgmt_cp_pair_device *cp;
1599 struct pending_cmd *cmd;
Brian Gixa68668b2011-08-11 15:49:36 -07001600 u8 sec_level, auth_type, io_cap;
Johan Hedberge9a416b2011-02-19 12:05:56 -03001601 struct hci_conn *conn;
Brian Gixfdd38922011-09-28 16:23:48 -07001602 struct adv_entry *entry;
Johan Hedberge9a416b2011-02-19 12:05:56 -03001603 int err;
1604
1605 BT_DBG("");
1606
Brian Gix64bd5302011-09-08 11:35:48 -07001607 cp = (void *) data;
1608
1609 if (len != sizeof(*cp))
1610 return cmd_status(sk, index, MGMT_OP_PAIR_DEVICE, EINVAL);
1611
Szymon Janc4e51eae2011-02-25 19:05:48 +01001612 hdev = hci_dev_get(index);
Brian Gixa68668b2011-08-11 15:49:36 -07001613
Johan Hedberge9a416b2011-02-19 12:05:56 -03001614 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +01001615 return cmd_status(sk, index, MGMT_OP_PAIR_DEVICE, ENODEV);
Johan Hedberge9a416b2011-02-19 12:05:56 -03001616
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001617 hci_dev_lock_bh(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03001618
Prabhakaran Mc6001a712011-09-06 11:56:25 +05301619 io_cap = cp->io_cap;
Prabhakaran Mc76a83552012-04-09 14:43:18 +05301620
1621 sec_level = BT_SECURITY_MEDIUM;
1622 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03001623
Brian Gixfdd38922011-09-28 16:23:48 -07001624 entry = hci_find_adv_entry(hdev, &cp->bdaddr);
1625 if (entry && entry->flags & 0x04) {
Brian Gixa94b6122012-02-23 16:07:10 -08001626 conn = hci_le_connect(hdev, 0, &cp->bdaddr, sec_level,
1627 auth_type, NULL);
Brian Gixa68668b2011-08-11 15:49:36 -07001628 } else {
1629 /* ACL-SSP does not support io_cap 0x04 (KeyboadDisplay) */
1630 if (io_cap == 0x04)
1631 io_cap = 0x01;
1632 conn = hci_connect(hdev, ACL_LINK, 0, &cp->bdaddr, sec_level,
1633 auth_type);
Prabhakaran Mc453651c2012-03-02 11:55:59 +05301634 conn->auth_initiator = 1;
Brian Gixa68668b2011-08-11 15:49:36 -07001635 }
1636
Ville Tervo30e76272011-02-22 16:10:53 -03001637 if (IS_ERR(conn)) {
1638 err = PTR_ERR(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03001639 goto unlock;
1640 }
1641
1642 if (conn->connect_cfm_cb) {
1643 hci_conn_put(conn);
Szymon Janc4e51eae2011-02-25 19:05:48 +01001644 err = cmd_status(sk, index, MGMT_OP_PAIR_DEVICE, EBUSY);
Johan Hedberge9a416b2011-02-19 12:05:56 -03001645 goto unlock;
1646 }
1647
Szymon Janc4e51eae2011-02-25 19:05:48 +01001648 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, index, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03001649 if (!cmd) {
1650 err = -ENOMEM;
1651 hci_conn_put(conn);
1652 goto unlock;
1653 }
1654
Brian Gix6d5fb8a2011-09-09 14:53:04 -07001655 conn->connect_cfm_cb = pairing_connect_complete_cb;
1656 conn->security_cfm_cb = pairing_security_complete_cb;
Johan Hedberge9a416b2011-02-19 12:05:56 -03001657 conn->disconn_cfm_cb = pairing_complete_cb;
Brian Gixa68668b2011-08-11 15:49:36 -07001658 conn->io_capability = io_cap;
Johan Hedberge9a416b2011-02-19 12:05:56 -03001659 cmd->user_data = conn;
1660
1661 if (conn->state == BT_CONNECTED &&
1662 hci_conn_security(conn, sec_level, auth_type))
1663 pairing_complete(cmd, 0);
1664
1665 err = 0;
1666
1667unlock:
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001668 hci_dev_unlock_bh(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03001669 hci_dev_put(hdev);
1670
1671 return err;
1672}
1673
Szymon Janc4e51eae2011-02-25 19:05:48 +01001674static int user_confirm_reply(struct sock *sk, u16 index, unsigned char *data,
Brian Gixa68668b2011-08-11 15:49:36 -07001675 u16 len, u16 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03001676{
1677 struct mgmt_cp_user_confirm_reply *cp = (void *) data;
Brian Gixa68668b2011-08-11 15:49:36 -07001678 u16 mgmt_op = opcode, hci_op;
Johan Hedberga5c29682011-02-19 12:05:57 -03001679 struct pending_cmd *cmd;
1680 struct hci_dev *hdev;
Brian Gixa68668b2011-08-11 15:49:36 -07001681 struct hci_conn *le_conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03001682 int err;
1683
Brian Gixa68668b2011-08-11 15:49:36 -07001684 BT_DBG("%d", mgmt_op);
Johan Hedberga5c29682011-02-19 12:05:57 -03001685
Brian Gixa68668b2011-08-11 15:49:36 -07001686 if (mgmt_op == MGMT_OP_USER_CONFIRM_NEG_REPLY)
Johan Hedberga5c29682011-02-19 12:05:57 -03001687 hci_op = HCI_OP_USER_CONFIRM_NEG_REPLY;
Brian Gixa68668b2011-08-11 15:49:36 -07001688 else
1689 hci_op = HCI_OP_USER_CONFIRM_REPLY;
Johan Hedberga5c29682011-02-19 12:05:57 -03001690
Brian Gixa68668b2011-08-11 15:49:36 -07001691 if (len < sizeof(*cp))
Szymon Jancbdce7ba2011-02-25 19:05:49 +01001692 return cmd_status(sk, index, mgmt_op, EINVAL);
1693
Szymon Janc4e51eae2011-02-25 19:05:48 +01001694 hdev = hci_dev_get(index);
Johan Hedberga5c29682011-02-19 12:05:57 -03001695 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +01001696 return cmd_status(sk, index, mgmt_op, ENODEV);
Johan Hedberga5c29682011-02-19 12:05:57 -03001697
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001698 hci_dev_lock_bh(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02001699
Johan Hedberga5c29682011-02-19 12:05:57 -03001700 if (!test_bit(HCI_UP, &hdev->flags)) {
Szymon Janc4e51eae2011-02-25 19:05:48 +01001701 err = cmd_status(sk, index, mgmt_op, ENETDOWN);
Brian Gixa68668b2011-08-11 15:49:36 -07001702 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03001703 }
1704
Brian Gixa68668b2011-08-11 15:49:36 -07001705 le_conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->bdaddr);
1706 if (le_conn) {
1707 err = le_user_confirm_reply(le_conn, mgmt_op, (void *) cp);
1708 goto done;
1709 }
1710 BT_DBG("BR/EDR: %s", mgmt_op == MGMT_OP_USER_CONFIRM_NEG_REPLY ?
1711 "Reject" : "Accept");
1712
Szymon Janc4e51eae2011-02-25 19:05:48 +01001713 cmd = mgmt_pending_add(sk, mgmt_op, index, data, len);
Johan Hedberga5c29682011-02-19 12:05:57 -03001714 if (!cmd) {
1715 err = -ENOMEM;
Brian Gixa68668b2011-08-11 15:49:36 -07001716 goto done;
1717 }
1718
1719 err = hci_send_cmd(hdev, hci_op, sizeof(cp->bdaddr), &cp->bdaddr);
1720 if (err < 0)
1721 mgmt_pending_remove(cmd);
1722
1723done:
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001724 hci_dev_unlock_bh(hdev);
Brian Gixa68668b2011-08-11 15:49:36 -07001725 hci_dev_put(hdev);
1726
1727 return err;
1728}
1729
1730static int resolve_name(struct sock *sk, u16 index, unsigned char *data,
1731 u16 len)
1732{
1733 struct mgmt_cp_resolve_name *mgmt_cp = (void *) data;
1734 struct hci_cp_remote_name_req hci_cp;
1735 struct hci_dev *hdev;
1736 struct pending_cmd *cmd;
1737 int err;
1738
1739 BT_DBG("");
1740
1741 if (len != sizeof(*mgmt_cp))
1742 return cmd_status(sk, index, MGMT_OP_RESOLVE_NAME, EINVAL);
1743
1744 hdev = hci_dev_get(index);
1745 if (!hdev)
1746 return cmd_status(sk, index, MGMT_OP_RESOLVE_NAME, ENODEV);
1747
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001748 hci_dev_lock_bh(hdev);
Brian Gixa68668b2011-08-11 15:49:36 -07001749
1750 cmd = mgmt_pending_add(sk, MGMT_OP_RESOLVE_NAME, index, data, len);
1751 if (!cmd) {
1752 err = -ENOMEM;
Johan Hedberga5c29682011-02-19 12:05:57 -03001753 goto failed;
1754 }
1755
Brian Gixa68668b2011-08-11 15:49:36 -07001756 memset(&hci_cp, 0, sizeof(hci_cp));
1757 bacpy(&hci_cp.bdaddr, &mgmt_cp->bdaddr);
1758 err = hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(hci_cp),
1759 &hci_cp);
Johan Hedberga664b5b2011-02-19 12:06:02 -03001760 if (err < 0)
1761 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03001762
1763failed:
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001764 hci_dev_unlock_bh(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03001765 hci_dev_put(hdev);
1766
1767 return err;
1768}
1769
Brian Gix7f7e16c2011-11-01 16:27:25 -07001770static int set_connection_params(struct sock *sk, u16 index,
1771 unsigned char *data, u16 len)
1772{
1773 struct mgmt_cp_set_connection_params *cp = (void *) data;
1774 struct hci_dev *hdev;
1775 struct hci_conn *conn;
1776 int err;
1777
1778 BT_DBG("");
1779
1780 if (len != sizeof(*cp))
1781 return cmd_status(sk, index, MGMT_OP_SET_CONNECTION_PARAMS,
1782 EINVAL);
1783
1784 hdev = hci_dev_get(index);
1785 if (!hdev)
1786 return cmd_status(sk, index, MGMT_OP_SET_CONNECTION_PARAMS,
1787 ENODEV);
1788
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001789 hci_dev_lock_bh(hdev);
Brian Gix7f7e16c2011-11-01 16:27:25 -07001790
1791 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->bdaddr);
1792 if (!conn) {
1793 err = cmd_status(sk, index, MGMT_OP_SET_CONNECTION_PARAMS,
1794 ENOTCONN);
1795 goto failed;
1796 }
1797
1798 hci_le_conn_update(conn, le16_to_cpu(cp->interval_min),
1799 le16_to_cpu(cp->interval_max),
1800 le16_to_cpu(cp->slave_latency),
1801 le16_to_cpu(cp->timeout_multiplier));
1802
1803 err = cmd_status(sk, index, MGMT_OP_SET_CONNECTION_PARAMS, 0);
1804
1805failed:
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001806 hci_dev_unlock_bh(hdev);
Brian Gix7f7e16c2011-11-01 16:27:25 -07001807 hci_dev_put(hdev);
1808
1809 return err;
1810}
1811
Archana Ramachandran26a752b2011-12-20 11:27:40 -08001812static int set_rssi_reporter(struct sock *sk, u16 index,
1813 unsigned char *data, u16 len)
1814{
1815 struct mgmt_cp_set_rssi_reporter *cp = (void *) data;
1816 struct hci_dev *hdev;
1817 struct hci_conn *conn;
1818 int err = 0;
1819
1820 if (len != sizeof(*cp))
1821 return cmd_status(sk, index, MGMT_OP_SET_RSSI_REPORTER,
1822 EINVAL);
1823
1824 hdev = hci_dev_get(index);
1825 if (!hdev)
1826 return cmd_status(sk, index, MGMT_OP_SET_RSSI_REPORTER,
1827 ENODEV);
1828
Archana Ramachandranf32d9822012-04-09 17:52:01 -07001829 hci_dev_lock_bh(hdev);
Archana Ramachandran26a752b2011-12-20 11:27:40 -08001830
1831 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->bdaddr);
1832
1833 if (!conn) {
1834 err = cmd_status(sk, index, MGMT_OP_SET_RSSI_REPORTER,
1835 ENOTCONN);
1836 goto failed;
1837 }
1838
1839 BT_DBG("updateOnThreshExceed %d ", cp->updateOnThreshExceed);
1840 hci_conn_set_rssi_reporter(conn, cp->rssi_threshold,
1841 __le16_to_cpu(cp->interval), cp->updateOnThreshExceed);
1842
1843failed:
Archana Ramachandranf32d9822012-04-09 17:52:01 -07001844 hci_dev_unlock_bh(hdev);
Archana Ramachandran26a752b2011-12-20 11:27:40 -08001845 hci_dev_put(hdev);
1846
1847 return err;
1848}
1849
1850static int unset_rssi_reporter(struct sock *sk, u16 index,
1851 unsigned char *data, u16 len)
1852{
1853 struct mgmt_cp_unset_rssi_reporter *cp = (void *) data;
1854 struct hci_dev *hdev;
1855 struct hci_conn *conn;
1856 int err = 0;
1857
1858 if (len != sizeof(*cp))
1859 return cmd_status(sk, index, MGMT_OP_UNSET_RSSI_REPORTER,
1860 EINVAL);
1861
1862 hdev = hci_dev_get(index);
1863
1864 if (!hdev)
1865 return cmd_status(sk, index, MGMT_OP_UNSET_RSSI_REPORTER,
1866 ENODEV);
1867
Archana Ramachandranf32d9822012-04-09 17:52:01 -07001868 hci_dev_lock_bh(hdev);
Archana Ramachandran26a752b2011-12-20 11:27:40 -08001869
1870 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->bdaddr);
1871
1872 if (!conn) {
1873 err = cmd_status(sk, index, MGMT_OP_UNSET_RSSI_REPORTER,
1874 ENOTCONN);
1875 goto failed;
1876 }
1877
1878 hci_conn_unset_rssi_reporter(conn);
1879
1880failed:
Archana Ramachandranf32d9822012-04-09 17:52:01 -07001881 hci_dev_unlock_bh(hdev);
Archana Ramachandran26a752b2011-12-20 11:27:40 -08001882 hci_dev_put(hdev);
1883
1884 return err;
1885}
1886
Johan Hedbergb312b1612011-03-16 14:29:37 +02001887static int set_local_name(struct sock *sk, u16 index, unsigned char *data,
1888 u16 len)
1889{
1890 struct mgmt_cp_set_local_name *mgmt_cp = (void *) data;
1891 struct hci_cp_write_local_name hci_cp;
1892 struct hci_dev *hdev;
1893 struct pending_cmd *cmd;
1894 int err;
1895
1896 BT_DBG("");
1897
1898 if (len != sizeof(*mgmt_cp))
1899 return cmd_status(sk, index, MGMT_OP_SET_LOCAL_NAME, EINVAL);
1900
1901 hdev = hci_dev_get(index);
1902 if (!hdev)
1903 return cmd_status(sk, index, MGMT_OP_SET_LOCAL_NAME, ENODEV);
1904
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001905 hci_dev_lock_bh(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02001906
1907 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, index, data, len);
1908 if (!cmd) {
1909 err = -ENOMEM;
1910 goto failed;
1911 }
1912
1913 memcpy(hci_cp.name, mgmt_cp->name, sizeof(hci_cp.name));
1914 err = hci_send_cmd(hdev, HCI_OP_WRITE_LOCAL_NAME, sizeof(hci_cp),
1915 &hci_cp);
1916 if (err < 0)
1917 mgmt_pending_remove(cmd);
1918
1919failed:
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001920 hci_dev_unlock_bh(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02001921 hci_dev_put(hdev);
1922
1923 return err;
1924}
1925
Brian Gixa68668b2011-08-11 15:49:36 -07001926static void discovery_rsp(struct pending_cmd *cmd, void *data)
1927{
1928 struct mgmt_mode ev;
1929
1930 BT_DBG("");
1931 if (cmd->opcode == MGMT_OP_START_DISCOVERY) {
1932 ev.val = 1;
1933 cmd_status(cmd->sk, cmd->index, MGMT_OP_START_DISCOVERY, 0);
1934 } else {
1935 ev.val = 0;
1936 cmd_complete(cmd->sk, cmd->index, MGMT_OP_STOP_DISCOVERY,
1937 NULL, 0);
1938 if (cmd->opcode == MGMT_OP_STOP_DISCOVERY) {
Brian Gix6e349d02011-11-28 14:51:14 -08001939 struct hci_dev *hdev = hci_dev_get(cmd->index);
1940 if (hdev) {
Brian Gix568dde92012-01-11 16:18:04 -08001941 del_timer(&hdev->disco_le_timer);
1942 del_timer(&hdev->disco_timer);
Brian Gix6e349d02011-11-28 14:51:14 -08001943 hci_dev_put(hdev);
1944 }
Brian Gixa68668b2011-08-11 15:49:36 -07001945 }
1946 }
1947
1948 mgmt_event(MGMT_EV_DISCOVERING, cmd->index, &ev, sizeof(ev), NULL);
1949
1950 list_del(&cmd->list);
1951
1952 mgmt_pending_free(cmd);
1953}
1954
1955void mgmt_inquiry_started(u16 index)
1956{
1957 BT_DBG("");
1958 mgmt_pending_foreach(MGMT_OP_START_DISCOVERY, index,
1959 discovery_rsp, NULL);
1960}
1961
1962void mgmt_inquiry_complete_evt(u16 index, u8 status)
1963{
1964 struct hci_dev *hdev;
1965 struct hci_cp_le_set_scan_enable le_cp = {1, 0};
Brian Gix568dde92012-01-11 16:18:04 -08001966 struct mgmt_mode cp = {0};
Brian Gixa68668b2011-08-11 15:49:36 -07001967 int err = -1;
1968
1969 BT_DBG("");
1970
1971 hdev = hci_dev_get(index);
Brian Gix64bd5302011-09-08 11:35:48 -07001972
Brian Gixa68668b2011-08-11 15:49:36 -07001973 if (!hdev || !lmp_le_capable(hdev)) {
Brian Gixa68668b2011-08-11 15:49:36 -07001974
1975 mgmt_pending_foreach(MGMT_OP_STOP_DISCOVERY, index,
1976 discovery_terminated, NULL);
1977
1978 mgmt_event(MGMT_EV_DISCOVERING, index, &cp, sizeof(cp), NULL);
Brian Gixa68668b2011-08-11 15:49:36 -07001979
Brian Gix64bd5302011-09-08 11:35:48 -07001980 if (hdev)
1981 goto done;
1982 else
1983 return;
1984 }
Brian Gixa68668b2011-08-11 15:49:36 -07001985
Brian Gix568dde92012-01-11 16:18:04 -08001986 if (hdev->disco_state != SCAN_IDLE) {
Brian Gixa68668b2011-08-11 15:49:36 -07001987 err = hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE,
1988 sizeof(le_cp), &le_cp);
Brian Gix568dde92012-01-11 16:18:04 -08001989 if (err >= 0) {
1990 mod_timer(&hdev->disco_le_timer, jiffies +
1991 msecs_to_jiffies(hdev->disco_int_phase * 1000));
1992 hdev->disco_state = SCAN_LE;
Brian Gixa68668b2011-08-11 15:49:36 -07001993 } else
Brian Gix568dde92012-01-11 16:18:04 -08001994 hdev->disco_state = SCAN_IDLE;
Brian Gixa68668b2011-08-11 15:49:36 -07001995 }
1996
Brian Gix568dde92012-01-11 16:18:04 -08001997 if (hdev->disco_state == SCAN_IDLE)
1998 mgmt_event(MGMT_EV_DISCOVERING, index, &cp, sizeof(cp), NULL);
1999
Brian Gixa68668b2011-08-11 15:49:36 -07002000 if (err < 0)
2001 mgmt_pending_foreach(MGMT_OP_STOP_DISCOVERY, index,
2002 discovery_terminated, NULL);
2003
Brian Gix64bd5302011-09-08 11:35:48 -07002004done:
Brian Gixa68668b2011-08-11 15:49:36 -07002005 hci_dev_put(hdev);
2006}
2007
Brian Gix568dde92012-01-11 16:18:04 -08002008void mgmt_disco_timeout(unsigned long data)
Brian Gixa68668b2011-08-11 15:49:36 -07002009{
Brian Gix568dde92012-01-11 16:18:04 -08002010 struct hci_dev *hdev = (void *) data;
Brian Gixa68668b2011-08-11 15:49:36 -07002011 struct pending_cmd *cmd;
Brian Gix568dde92012-01-11 16:18:04 -08002012 struct mgmt_mode cp = {0};
Brian Gixa68668b2011-08-11 15:49:36 -07002013
Brian Gix568dde92012-01-11 16:18:04 -08002014 BT_DBG("hci%d", hdev->id);
Brian Gixa68668b2011-08-11 15:49:36 -07002015
Brian Gix568dde92012-01-11 16:18:04 -08002016 hdev = hci_dev_get(hdev->id);
Brian Gixa68668b2011-08-11 15:49:36 -07002017
Brian Gix568dde92012-01-11 16:18:04 -08002018 if (!hdev)
2019 return;
Brian Gixa68668b2011-08-11 15:49:36 -07002020
Brian Gix568dde92012-01-11 16:18:04 -08002021 hci_dev_lock_bh(hdev);
2022 del_timer(&hdev->disco_le_timer);
Brian Gixa68668b2011-08-11 15:49:36 -07002023
Brian Gix568dde92012-01-11 16:18:04 -08002024 if (hdev->disco_state != SCAN_IDLE) {
2025 struct hci_cp_le_set_scan_enable le_cp = {0, 0};
Brian Gixa68668b2011-08-11 15:49:36 -07002026
Bhasker Netia6e6a4f2012-01-27 15:25:43 +05302027 if (test_bit(HCI_UP, &hdev->flags)) {
2028 if (hdev->disco_state == SCAN_LE)
2029 hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE,
Brian Gixa68668b2011-08-11 15:49:36 -07002030 sizeof(le_cp), &le_cp);
Bhasker Netia6e6a4f2012-01-27 15:25:43 +05302031 else
2032 hci_send_cmd(hdev, HCI_OP_INQUIRY_CANCEL, 0,
2033 NULL);
2034 }
Brian Gix568dde92012-01-11 16:18:04 -08002035 hdev->disco_state = SCAN_IDLE;
Brian Gixa68668b2011-08-11 15:49:36 -07002036 }
Brian Gix568dde92012-01-11 16:18:04 -08002037
2038 mgmt_event(MGMT_EV_DISCOVERING, hdev->id, &cp, sizeof(cp), NULL);
2039
2040 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev->id);
2041 if (cmd)
2042 mgmt_pending_remove(cmd);
2043
2044 hci_dev_unlock_bh(hdev);
2045 hci_dev_put(hdev);
2046}
2047
2048void mgmt_disco_le_timeout(unsigned long data)
2049{
2050 struct hci_dev *hdev = (void *)data;
2051 struct hci_cp_le_set_scan_enable le_cp = {0, 0};
2052
2053 BT_DBG("hci%d", hdev->id);
2054
2055 hdev = hci_dev_get(hdev->id);
2056
2057 if (!hdev)
2058 return;
2059
2060 hci_dev_lock_bh(hdev);
2061
Bhasker Netia6e6a4f2012-01-27 15:25:43 +05302062 if (test_bit(HCI_UP, &hdev->flags)) {
2063 if (hdev->disco_state == SCAN_LE)
2064 hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE,
2065 sizeof(le_cp), &le_cp);
Brian Gix568dde92012-01-11 16:18:04 -08002066
2067 /* re-start BR scan */
Bhasker Netia6e6a4f2012-01-27 15:25:43 +05302068 if (hdev->disco_state != SCAN_IDLE) {
2069 struct hci_cp_inquiry cp = {{0x33, 0x8b, 0x9e}, 4, 0};
2070 hdev->disco_int_phase *= 2;
2071 hdev->disco_int_count = 0;
2072 cp.num_rsp = (u8) hdev->disco_int_phase;
2073 hci_send_cmd(hdev, HCI_OP_INQUIRY, sizeof(cp), &cp);
2074 hdev->disco_state = SCAN_BR;
2075 }
Brian Gix568dde92012-01-11 16:18:04 -08002076 }
2077
2078 hci_dev_unlock_bh(hdev);
2079 hci_dev_put(hdev);
Brian Gixa68668b2011-08-11 15:49:36 -07002080}
2081
2082static int start_discovery(struct sock *sk, u16 index)
2083{
2084 struct hci_cp_inquiry cp = {{0x33, 0x8b, 0x9e}, 8, 0};
2085 struct hci_dev *hdev;
2086 struct pending_cmd *cmd;
2087 int err;
2088
2089 BT_DBG("");
2090
2091 hdev = hci_dev_get(index);
2092 if (!hdev)
2093 return cmd_status(sk, index, MGMT_OP_START_DISCOVERY, ENODEV);
2094
Subramanian Srinivasana727a492011-11-30 13:06:07 -08002095 hci_dev_lock_bh(hdev);
Brian Gixa68668b2011-08-11 15:49:36 -07002096
Brian Gix568dde92012-01-11 16:18:04 -08002097 if (hdev->disco_state && timer_pending(&hdev->disco_timer)) {
2098 err = -EBUSY;
2099 goto failed;
2100 }
2101
Brian Gixa68668b2011-08-11 15:49:36 -07002102 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, index, NULL, 0);
2103 if (!cmd) {
2104 err = -ENOMEM;
2105 goto failed;
2106 }
2107
2108 /* If LE Capable, we will alternate between BR/EDR and LE */
2109 if (lmp_le_capable(hdev)) {
2110 struct hci_cp_le_set_scan_parameters le_cp;
2111
2112 /* Shorten BR scan params */
2113 cp.num_rsp = 1;
2114 cp.length /= 2;
2115
2116 /* Setup LE scan params */
2117 memset(&le_cp, 0, sizeof(le_cp));
2118 le_cp.type = 0x01; /* Active scanning */
2119 /* The recommended value for scan interval and window is
2120 * 11.25 msec. It is calculated by: time = n * 0.625 msec */
2121 le_cp.interval = cpu_to_le16(0x0012);
2122 le_cp.window = cpu_to_le16(0x0012);
2123 le_cp.own_bdaddr_type = 0; /* Public address */
2124 le_cp.filter = 0; /* Accept all adv packets */
2125
2126 hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_PARAMETERS,
2127 sizeof(le_cp), &le_cp);
2128 }
2129
2130 err = hci_send_cmd(hdev, HCI_OP_INQUIRY, sizeof(cp), &cp);
2131
2132 if (err < 0)
2133 mgmt_pending_remove(cmd);
2134 else if (lmp_le_capable(hdev)) {
Brian Gix474e0f22012-01-14 20:21:55 -08002135 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, index);
2136 if (!cmd)
2137 mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, index,
2138 NULL, 0);
Brian Gix568dde92012-01-11 16:18:04 -08002139 hdev->disco_int_phase = 1;
2140 hdev->disco_int_count = 0;
2141 hdev->disco_state = SCAN_BR;
Brian Gix568dde92012-01-11 16:18:04 -08002142 del_timer(&hdev->disco_le_timer);
2143 del_timer(&hdev->disco_timer);
2144 mod_timer(&hdev->disco_timer,
2145 jiffies + msecs_to_jiffies(20000));
Brian Gixa68668b2011-08-11 15:49:36 -07002146 }
2147
2148failed:
Subramanian Srinivasana727a492011-11-30 13:06:07 -08002149 hci_dev_unlock_bh(hdev);
Brian Gixa68668b2011-08-11 15:49:36 -07002150 hci_dev_put(hdev);
2151
Brian Gix568dde92012-01-11 16:18:04 -08002152 if (err < 0)
2153 return cmd_status(sk, index, MGMT_OP_START_DISCOVERY, -err);
2154
Brian Gixa68668b2011-08-11 15:49:36 -07002155 return err;
2156}
2157
2158static int stop_discovery(struct sock *sk, u16 index)
2159{
2160 struct hci_cp_le_set_scan_enable le_cp = {0, 0};
2161 struct mgmt_mode mode_cp = {0};
Brian Gixa68668b2011-08-11 15:49:36 -07002162 struct hci_dev *hdev;
2163 struct pending_cmd *cmd = NULL;
2164 int err = -EPERM;
Brian Gix568dde92012-01-11 16:18:04 -08002165 u8 state;
Brian Gixa68668b2011-08-11 15:49:36 -07002166
2167 BT_DBG("");
2168
2169 hdev = hci_dev_get(index);
2170 if (!hdev)
2171 return cmd_status(sk, index, MGMT_OP_STOP_DISCOVERY, ENODEV);
2172
Subramanian Srinivasana727a492011-11-30 13:06:07 -08002173 hci_dev_lock_bh(hdev);
Brian Gixa68668b2011-08-11 15:49:36 -07002174
Brian Gix568dde92012-01-11 16:18:04 -08002175 state = hdev->disco_state;
2176 hdev->disco_state = SCAN_IDLE;
2177 del_timer(&hdev->disco_le_timer);
2178 del_timer(&hdev->disco_timer);
Brian Gixa68668b2011-08-11 15:49:36 -07002179
Brian Gix568dde92012-01-11 16:18:04 -08002180 if (state == SCAN_LE) {
Brian Gixa68668b2011-08-11 15:49:36 -07002181 err = hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE,
2182 sizeof(le_cp), &le_cp);
Brian Gix568dde92012-01-11 16:18:04 -08002183 if (err >= 0) {
2184 mgmt_pending_foreach(MGMT_OP_STOP_DISCOVERY, index,
2185 discovery_terminated, NULL);
Brian Gixa68668b2011-08-11 15:49:36 -07002186
Brian Gix568dde92012-01-11 16:18:04 -08002187 err = cmd_complete(sk, index, MGMT_OP_STOP_DISCOVERY,
2188 NULL, 0);
2189 }
Brian Gixa68668b2011-08-11 15:49:36 -07002190 }
2191
Brian Gix568dde92012-01-11 16:18:04 -08002192 if (err < 0)
2193 err = hci_send_cmd(hdev, HCI_OP_INQUIRY_CANCEL, 0, NULL);
Brian Gixa68668b2011-08-11 15:49:36 -07002194
Brian Gix568dde92012-01-11 16:18:04 -08002195 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, index);
Brian Gixa68668b2011-08-11 15:49:36 -07002196 if (err < 0 && cmd)
2197 mgmt_pending_remove(cmd);
2198
2199 mgmt_event(MGMT_EV_DISCOVERING, index, &mode_cp, sizeof(mode_cp), NULL);
2200
Subramanian Srinivasana727a492011-11-30 13:06:07 -08002201 hci_dev_unlock_bh(hdev);
Brian Gixa68668b2011-08-11 15:49:36 -07002202 hci_dev_put(hdev);
2203
2204 if (err < 0)
2205 return cmd_status(sk, index, MGMT_OP_STOP_DISCOVERY, -err);
2206 else
2207 return err;
2208}
2209
Szymon Jancc35938b2011-03-22 13:12:21 +01002210static int read_local_oob_data(struct sock *sk, u16 index)
2211{
2212 struct hci_dev *hdev;
2213 struct pending_cmd *cmd;
2214 int err;
2215
2216 BT_DBG("hci%u", index);
2217
2218 hdev = hci_dev_get(index);
2219 if (!hdev)
2220 return cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
2221 ENODEV);
2222
Subramanian Srinivasana727a492011-11-30 13:06:07 -08002223 hci_dev_lock_bh(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01002224
2225 if (!test_bit(HCI_UP, &hdev->flags)) {
2226 err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
2227 ENETDOWN);
2228 goto unlock;
2229 }
2230
2231 if (!(hdev->features[6] & LMP_SIMPLE_PAIR)) {
2232 err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
2233 EOPNOTSUPP);
2234 goto unlock;
2235 }
2236
2237 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, index)) {
2238 err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, EBUSY);
2239 goto unlock;
2240 }
2241
2242 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, index, NULL, 0);
2243 if (!cmd) {
2244 err = -ENOMEM;
2245 goto unlock;
2246 }
2247
2248 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
2249 if (err < 0)
2250 mgmt_pending_remove(cmd);
2251
2252unlock:
Subramanian Srinivasana727a492011-11-30 13:06:07 -08002253 hci_dev_unlock_bh(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01002254 hci_dev_put(hdev);
2255
2256 return err;
2257}
2258
Szymon Janc2763eda2011-03-22 13:12:22 +01002259static int add_remote_oob_data(struct sock *sk, u16 index, unsigned char *data,
2260 u16 len)
2261{
2262 struct hci_dev *hdev;
2263 struct mgmt_cp_add_remote_oob_data *cp = (void *) data;
2264 int err;
2265
2266 BT_DBG("hci%u ", index);
2267
2268 if (len != sizeof(*cp))
2269 return cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA,
2270 EINVAL);
2271
2272 hdev = hci_dev_get(index);
2273 if (!hdev)
2274 return cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA,
2275 ENODEV);
2276
Subramanian Srinivasana727a492011-11-30 13:06:07 -08002277 hci_dev_lock_bh(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01002278
2279 err = hci_add_remote_oob_data(hdev, &cp->bdaddr, cp->hash,
2280 cp->randomizer);
2281 if (err < 0)
2282 err = cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, -err);
2283 else
2284 err = cmd_complete(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, NULL,
2285 0);
2286
Subramanian Srinivasana727a492011-11-30 13:06:07 -08002287 hci_dev_unlock_bh(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01002288 hci_dev_put(hdev);
2289
2290 return err;
2291}
2292
2293static int remove_remote_oob_data(struct sock *sk, u16 index,
2294 unsigned char *data, u16 len)
2295{
2296 struct hci_dev *hdev;
2297 struct mgmt_cp_remove_remote_oob_data *cp = (void *) data;
2298 int err;
2299
2300 BT_DBG("hci%u ", index);
2301
2302 if (len != sizeof(*cp))
2303 return cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
2304 EINVAL);
2305
2306 hdev = hci_dev_get(index);
2307 if (!hdev)
2308 return cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
2309 ENODEV);
2310
Subramanian Srinivasana727a492011-11-30 13:06:07 -08002311 hci_dev_lock_bh(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01002312
2313 err = hci_remove_remote_oob_data(hdev, &cp->bdaddr);
2314 if (err < 0)
2315 err = cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
2316 -err);
2317 else
2318 err = cmd_complete(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
2319 NULL, 0);
2320
Subramanian Srinivasana727a492011-11-30 13:06:07 -08002321 hci_dev_unlock_bh(hdev);
Antti Julku58d19802011-06-15 12:01:15 +03002322 hci_dev_put(hdev);
2323
2324 return err;
2325}
2326
Johan Hedberg03811012010-12-08 00:21:06 +02002327int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
2328{
2329 unsigned char *buf;
2330 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01002331 u16 opcode, index, len;
Johan Hedberg03811012010-12-08 00:21:06 +02002332 int err;
2333
2334 BT_DBG("got %zu bytes", msglen);
2335
2336 if (msglen < sizeof(*hdr))
2337 return -EINVAL;
2338
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03002339 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02002340 if (!buf)
2341 return -ENOMEM;
2342
2343 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
2344 err = -EFAULT;
2345 goto done;
2346 }
2347
2348 hdr = (struct mgmt_hdr *) buf;
2349 opcode = get_unaligned_le16(&hdr->opcode);
Szymon Janc4e51eae2011-02-25 19:05:48 +01002350 index = get_unaligned_le16(&hdr->index);
Johan Hedberg03811012010-12-08 00:21:06 +02002351 len = get_unaligned_le16(&hdr->len);
2352
2353 if (len != msglen - sizeof(*hdr)) {
2354 err = -EINVAL;
2355 goto done;
2356 }
2357
Brian Gixa68668b2011-08-11 15:49:36 -07002358 BT_DBG("got opcode %x", opcode);
Johan Hedberg03811012010-12-08 00:21:06 +02002359 switch (opcode) {
Johan Hedberg02d98122010-12-13 21:07:04 +02002360 case MGMT_OP_READ_VERSION:
2361 err = read_version(sk);
2362 break;
Johan Hedbergfaba42e2010-12-13 21:07:05 +02002363 case MGMT_OP_READ_INDEX_LIST:
2364 err = read_index_list(sk);
2365 break;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02002366 case MGMT_OP_READ_INFO:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002367 err = read_controller_info(sk, index);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02002368 break;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002369 case MGMT_OP_SET_POWERED:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002370 err = set_powered(sk, index, buf + sizeof(*hdr), len);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002371 break;
Johan Hedberg73f22f62010-12-29 16:00:25 +02002372 case MGMT_OP_SET_DISCOVERABLE:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002373 err = set_discoverable(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg73f22f62010-12-29 16:00:25 +02002374 break;
Brian Gix8a7f1642011-10-17 17:39:46 -07002375 case MGMT_OP_SET_LIMIT_DISCOVERABLE:
2376 err = set_limited_discoverable(sk, index, buf + sizeof(*hdr),
2377 len);
2378 break;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02002379 case MGMT_OP_SET_CONNECTABLE:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002380 err = set_connectable(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02002381 break;
Johan Hedbergc542a062011-01-26 13:11:03 +02002382 case MGMT_OP_SET_PAIRABLE:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002383 err = set_pairable(sk, index, buf + sizeof(*hdr), len);
Johan Hedbergc542a062011-01-26 13:11:03 +02002384 break;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002385 case MGMT_OP_ADD_UUID:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002386 err = add_uuid(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002387 break;
2388 case MGMT_OP_REMOVE_UUID:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002389 err = remove_uuid(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002390 break;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002391 case MGMT_OP_SET_DEV_CLASS:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002392 err = set_dev_class(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002393 break;
2394 case MGMT_OP_SET_SERVICE_CACHE:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002395 err = set_service_cache(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002396 break;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002397 case MGMT_OP_LOAD_KEYS:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002398 err = load_keys(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002399 break;
2400 case MGMT_OP_REMOVE_KEY:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002401 err = remove_key(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002402 break;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002403 case MGMT_OP_DISCONNECT:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002404 err = disconnect(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002405 break;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002406 case MGMT_OP_GET_CONNECTIONS:
Szymon Janc8ce62842011-03-01 16:55:32 +01002407 err = get_connections(sk, index);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002408 break;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002409 case MGMT_OP_PIN_CODE_REPLY:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002410 err = pin_code_reply(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002411 break;
2412 case MGMT_OP_PIN_CODE_NEG_REPLY:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002413 err = pin_code_neg_reply(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002414 break;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002415 case MGMT_OP_SET_IO_CAPABILITY:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002416 err = set_io_capability(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002417 break;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002418 case MGMT_OP_PAIR_DEVICE:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002419 err = pair_device(sk, index, buf + sizeof(*hdr), len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002420 break;
Johan Hedberga5c29682011-02-19 12:05:57 -03002421 case MGMT_OP_USER_CONFIRM_REPLY:
Brian Gixa68668b2011-08-11 15:49:36 -07002422 case MGMT_OP_USER_PASSKEY_REPLY:
Johan Hedberga5c29682011-02-19 12:05:57 -03002423 case MGMT_OP_USER_CONFIRM_NEG_REPLY:
Brian Gixa68668b2011-08-11 15:49:36 -07002424 err = user_confirm_reply(sk, index, buf + sizeof(*hdr),
2425 len, opcode);
Johan Hedberga5c29682011-02-19 12:05:57 -03002426 break;
Johan Hedbergb312b1612011-03-16 14:29:37 +02002427 case MGMT_OP_SET_LOCAL_NAME:
2428 err = set_local_name(sk, index, buf + sizeof(*hdr), len);
2429 break;
Brian Gixa68668b2011-08-11 15:49:36 -07002430 case MGMT_OP_START_DISCOVERY:
2431 err = start_discovery(sk, index);
2432 break;
2433 case MGMT_OP_STOP_DISCOVERY:
2434 err = stop_discovery(sk, index);
2435 break;
2436 case MGMT_OP_RESOLVE_NAME:
2437 err = resolve_name(sk, index, buf + sizeof(*hdr), len);
2438 break;
Brian Gix7f7e16c2011-11-01 16:27:25 -07002439 case MGMT_OP_SET_CONNECTION_PARAMS:
2440 err = set_connection_params(sk, index, buf + sizeof(*hdr), len);
2441 break;
Archana Ramachandran26a752b2011-12-20 11:27:40 -08002442 case MGMT_OP_SET_RSSI_REPORTER:
2443 err = set_rssi_reporter(sk, index, buf + sizeof(*hdr), len);
2444 break;
2445 case MGMT_OP_UNSET_RSSI_REPORTER:
2446 err = unset_rssi_reporter(sk, index, buf + sizeof(*hdr), len);
2447 break;
Szymon Jancc35938b2011-03-22 13:12:21 +01002448 case MGMT_OP_READ_LOCAL_OOB_DATA:
2449 err = read_local_oob_data(sk, index);
2450 break;
Szymon Janc2763eda2011-03-22 13:12:22 +01002451 case MGMT_OP_ADD_REMOTE_OOB_DATA:
2452 err = add_remote_oob_data(sk, index, buf + sizeof(*hdr), len);
2453 break;
2454 case MGMT_OP_REMOVE_REMOTE_OOB_DATA:
2455 err = remove_remote_oob_data(sk, index, buf + sizeof(*hdr),
2456 len);
2457 break;
Prabhakaran Mc46230fa2011-11-30 18:11:21 +05302458 case MGMT_OP_ENCRYPT_LINK:
2459 err = encrypt_link(sk, index, buf + sizeof(*hdr), len);
2460 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002461
Johan Hedberg03811012010-12-08 00:21:06 +02002462 default:
2463 BT_DBG("Unknown op %u", opcode);
Szymon Janc4e51eae2011-02-25 19:05:48 +01002464 err = cmd_status(sk, index, opcode, 0x01);
Johan Hedberg03811012010-12-08 00:21:06 +02002465 break;
2466 }
2467
Johan Hedberge41d8b42010-12-13 21:07:03 +02002468 if (err < 0)
2469 goto done;
2470
Johan Hedberg03811012010-12-08 00:21:06 +02002471 err = msglen;
2472
2473done:
2474 kfree(buf);
2475 return err;
2476}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02002477
Johan Hedbergc71e97b2010-12-13 21:07:07 +02002478int mgmt_index_added(u16 index)
2479{
Brian Gixa68668b2011-08-11 15:49:36 -07002480 BT_DBG("%d", index);
Szymon Janc4e51eae2011-02-25 19:05:48 +01002481 return mgmt_event(MGMT_EV_INDEX_ADDED, index, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02002482}
2483
2484int mgmt_index_removed(u16 index)
2485{
Brian Gixa68668b2011-08-11 15:49:36 -07002486 BT_DBG("%d", index);
Szymon Janc4e51eae2011-02-25 19:05:48 +01002487 return mgmt_event(MGMT_EV_INDEX_REMOVED, index, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002488}
2489
Johan Hedberg73f22f62010-12-29 16:00:25 +02002490struct cmd_lookup {
Johan Hedberg72a734e2010-12-30 00:38:22 +02002491 u8 val;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002492 struct sock *sk;
2493};
2494
Johan Hedberg72a734e2010-12-30 00:38:22 +02002495static void mode_rsp(struct pending_cmd *cmd, void *data)
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002496{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01002497 struct mgmt_mode *cp = cmd->param;
Johan Hedberg73f22f62010-12-29 16:00:25 +02002498 struct cmd_lookup *match = data;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002499
Johan Hedberg72a734e2010-12-30 00:38:22 +02002500 if (cp->val != match->val)
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002501 return;
2502
Johan Hedberg053f0212011-01-26 13:07:10 +02002503 send_mode_rsp(cmd->sk, cmd->opcode, cmd->index, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002504
2505 list_del(&cmd->list);
2506
2507 if (match->sk == NULL) {
2508 match->sk = cmd->sk;
2509 sock_hold(match->sk);
2510 }
2511
2512 mgmt_pending_free(cmd);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02002513}
Johan Hedberg5add6af2010-12-16 10:00:37 +02002514
2515int mgmt_powered(u16 index, u8 powered)
2516{
Johan Hedberg72a734e2010-12-30 00:38:22 +02002517 struct mgmt_mode ev;
Johan Hedberg73f22f62010-12-29 16:00:25 +02002518 struct cmd_lookup match = { powered, NULL };
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002519 int ret;
Johan Hedberg5add6af2010-12-16 10:00:37 +02002520
Brian Gixa68668b2011-08-11 15:49:36 -07002521 BT_DBG("hci%u %d", index, powered);
2522
Johan Hedberg72a734e2010-12-30 00:38:22 +02002523 mgmt_pending_foreach(MGMT_OP_SET_POWERED, index, mode_rsp, &match);
Johan Hedberg5add6af2010-12-16 10:00:37 +02002524
Johan Hedberg72a734e2010-12-30 00:38:22 +02002525 ev.val = powered;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002526
Szymon Janc4e51eae2011-02-25 19:05:48 +01002527 ret = mgmt_event(MGMT_EV_POWERED, index, &ev, sizeof(ev), match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002528
2529 if (match.sk)
2530 sock_put(match.sk);
2531
2532 return ret;
Johan Hedberg5add6af2010-12-16 10:00:37 +02002533}
Johan Hedberg73f22f62010-12-29 16:00:25 +02002534
Johan Hedberg73f22f62010-12-29 16:00:25 +02002535int mgmt_discoverable(u16 index, u8 discoverable)
2536{
Johan Hedberg72a734e2010-12-30 00:38:22 +02002537 struct mgmt_mode ev;
Johan Hedberg73f22f62010-12-29 16:00:25 +02002538 struct cmd_lookup match = { discoverable, NULL };
2539 int ret;
2540
Szymon Jancb8534e02011-03-01 16:55:34 +01002541 mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, index, mode_rsp, &match);
Johan Hedberg72a734e2010-12-30 00:38:22 +02002542
Johan Hedberg72a734e2010-12-30 00:38:22 +02002543 ev.val = discoverable;
Johan Hedberg73f22f62010-12-29 16:00:25 +02002544
Szymon Janc4e51eae2011-02-25 19:05:48 +01002545 ret = mgmt_event(MGMT_EV_DISCOVERABLE, index, &ev, sizeof(ev),
2546 match.sk);
Johan Hedberg73f22f62010-12-29 16:00:25 +02002547
2548 if (match.sk)
2549 sock_put(match.sk);
2550
2551 return ret;
2552}
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02002553
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02002554int mgmt_connectable(u16 index, u8 connectable)
2555{
Johan Hedberg72a734e2010-12-30 00:38:22 +02002556 struct mgmt_mode ev;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02002557 struct cmd_lookup match = { connectable, NULL };
2558 int ret;
2559
Johan Hedberg72a734e2010-12-30 00:38:22 +02002560 mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, index, mode_rsp, &match);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02002561
Johan Hedberg72a734e2010-12-30 00:38:22 +02002562 ev.val = connectable;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02002563
Szymon Janc4e51eae2011-02-25 19:05:48 +01002564 ret = mgmt_event(MGMT_EV_CONNECTABLE, index, &ev, sizeof(ev), match.sk);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02002565
2566 if (match.sk)
2567 sock_put(match.sk);
2568
2569 return ret;
2570}
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002571
Brian Gixa68668b2011-08-11 15:49:36 -07002572int mgmt_new_key(u16 index, struct link_key *key, u8 bonded)
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002573{
Vinicius Costa Gomesc00ddbf2011-07-08 18:31:44 -03002574 struct mgmt_ev_new_key *ev;
2575 int err, total;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002576
Vinicius Costa Gomesc00ddbf2011-07-08 18:31:44 -03002577 total = sizeof(struct mgmt_ev_new_key) + key->dlen;
2578 ev = kzalloc(total, GFP_ATOMIC);
2579 if (!ev)
2580 return -ENOMEM;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002581
Vinicius Costa Gomesc00ddbf2011-07-08 18:31:44 -03002582 bacpy(&ev->key.bdaddr, &key->bdaddr);
Brian Gixcf956772011-10-20 15:18:51 -07002583 ev->key.addr_type = key->addr_type;
2584 ev->key.key_type = key->key_type;
Vinicius Costa Gomesc00ddbf2011-07-08 18:31:44 -03002585 memcpy(ev->key.val, key->val, 16);
2586 ev->key.pin_len = key->pin_len;
Brian Gixa68668b2011-08-11 15:49:36 -07002587 ev->key.auth = key->auth;
2588 ev->store_hint = bonded;
Vinicius Costa Gomesc00ddbf2011-07-08 18:31:44 -03002589 ev->key.dlen = key->dlen;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002590
Vinicius Costa Gomesc00ddbf2011-07-08 18:31:44 -03002591 memcpy(ev->key.data, key->data, key->dlen);
2592
2593 err = mgmt_event(MGMT_EV_NEW_KEY, index, ev, total, NULL);
2594
2595 kfree(ev);
2596
2597 return err;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002598}
Johan Hedbergf7520542011-01-20 12:34:39 +02002599
Brian Gix2e2f50d2011-09-13 12:36:04 -07002600int mgmt_connected(u16 index, bdaddr_t *bdaddr, u8 le)
Johan Hedbergf7520542011-01-20 12:34:39 +02002601{
2602 struct mgmt_ev_connected ev;
2603
Johan Hedbergf7520542011-01-20 12:34:39 +02002604 bacpy(&ev.bdaddr, bdaddr);
Brian Gix2e2f50d2011-09-13 12:36:04 -07002605 ev.le = le;
Johan Hedbergf7520542011-01-20 12:34:39 +02002606
Szymon Janc4e51eae2011-02-25 19:05:48 +01002607 return mgmt_event(MGMT_EV_CONNECTED, index, &ev, sizeof(ev), NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02002608}
2609
Johan Hedberg8962ee72011-01-20 12:40:27 +02002610static void disconnect_rsp(struct pending_cmd *cmd, void *data)
2611{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01002612 struct mgmt_cp_disconnect *cp = cmd->param;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002613 struct sock **sk = data;
Johan Hedberga38528f2011-01-22 06:46:43 +02002614 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002615
Johan Hedberga38528f2011-01-22 06:46:43 +02002616 bacpy(&rp.bdaddr, &cp->bdaddr);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002617
Szymon Janc4e51eae2011-02-25 19:05:48 +01002618 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002619
2620 *sk = cmd->sk;
2621 sock_hold(*sk);
2622
Johan Hedberga664b5b2011-02-19 12:06:02 -03002623 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002624}
2625
Johan Hedbergf7520542011-01-20 12:34:39 +02002626int mgmt_disconnected(u16 index, bdaddr_t *bdaddr)
2627{
2628 struct mgmt_ev_disconnected ev;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002629 struct sock *sk = NULL;
2630 int err;
2631
2632 mgmt_pending_foreach(MGMT_OP_DISCONNECT, index, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02002633
Johan Hedbergf7520542011-01-20 12:34:39 +02002634 bacpy(&ev.bdaddr, bdaddr);
2635
Szymon Janc4e51eae2011-02-25 19:05:48 +01002636 err = mgmt_event(MGMT_EV_DISCONNECTED, index, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002637
2638 if (sk)
2639 sock_put(sk);
2640
2641 return err;
2642}
2643
2644int mgmt_disconnect_failed(u16 index)
2645{
2646 struct pending_cmd *cmd;
2647 int err;
2648
2649 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, index);
2650 if (!cmd)
2651 return -ENOENT;
2652
Szymon Janc4e51eae2011-02-25 19:05:48 +01002653 err = cmd_status(cmd->sk, index, MGMT_OP_DISCONNECT, EIO);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002654
Johan Hedberga664b5b2011-02-19 12:06:02 -03002655 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002656
2657 return err;
Johan Hedbergf7520542011-01-20 12:34:39 +02002658}
Johan Hedberg17d5c042011-01-22 06:09:08 +02002659
2660int mgmt_connect_failed(u16 index, bdaddr_t *bdaddr, u8 status)
2661{
2662 struct mgmt_ev_connect_failed ev;
2663
Johan Hedberg17d5c042011-01-22 06:09:08 +02002664 bacpy(&ev.bdaddr, bdaddr);
2665 ev.status = status;
2666
Szymon Janc4e51eae2011-02-25 19:05:48 +01002667 return mgmt_event(MGMT_EV_CONNECT_FAILED, index, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02002668}
Johan Hedberg980e1a52011-01-22 06:10:07 +02002669
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002670int mgmt_pin_code_request(u16 index, bdaddr_t *bdaddr)
Johan Hedberg980e1a52011-01-22 06:10:07 +02002671{
2672 struct mgmt_ev_pin_code_request ev;
2673
Brian Gixa68668b2011-08-11 15:49:36 -07002674 BT_DBG("hci%u", index);
2675
Johan Hedberg980e1a52011-01-22 06:10:07 +02002676 bacpy(&ev.bdaddr, bdaddr);
Brian Gixa68668b2011-08-11 15:49:36 -07002677 ev.secure = 0;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002678
Szymon Janc4e51eae2011-02-25 19:05:48 +01002679 return mgmt_event(MGMT_EV_PIN_CODE_REQUEST, index, &ev, sizeof(ev),
2680 NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002681}
2682
2683int mgmt_pin_code_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status)
2684{
2685 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03002686 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002687 int err;
2688
2689 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, index);
2690 if (!cmd)
2691 return -ENOENT;
2692
Johan Hedbergac56fb12011-02-19 12:05:59 -03002693 bacpy(&rp.bdaddr, bdaddr);
2694 rp.status = status;
2695
Szymon Janc4e51eae2011-02-25 19:05:48 +01002696 err = cmd_complete(cmd->sk, index, MGMT_OP_PIN_CODE_REPLY, &rp,
2697 sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02002698
Johan Hedberga664b5b2011-02-19 12:06:02 -03002699 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002700
2701 return err;
2702}
2703
2704int mgmt_pin_code_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status)
2705{
2706 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03002707 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002708 int err;
2709
2710 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, index);
2711 if (!cmd)
2712 return -ENOENT;
2713
Johan Hedbergac56fb12011-02-19 12:05:59 -03002714 bacpy(&rp.bdaddr, bdaddr);
2715 rp.status = status;
2716
Szymon Janc4e51eae2011-02-25 19:05:48 +01002717 err = cmd_complete(cmd->sk, index, MGMT_OP_PIN_CODE_NEG_REPLY, &rp,
2718 sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02002719
Johan Hedberga664b5b2011-02-19 12:06:02 -03002720 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002721
2722 return err;
2723}
Johan Hedberga5c29682011-02-19 12:05:57 -03002724
Brian Gixa68668b2011-08-11 15:49:36 -07002725int mgmt_user_confirm_request(u16 index, u8 event,
2726 bdaddr_t *bdaddr, __le32 value)
Johan Hedberga5c29682011-02-19 12:05:57 -03002727{
2728 struct mgmt_ev_user_confirm_request ev;
Brian Gixa68668b2011-08-11 15:49:36 -07002729 struct hci_conn *conn = NULL;
2730 struct hci_dev *hdev;
2731 u8 loc_cap, rem_cap, loc_mitm, rem_mitm;
2732
2733 BT_DBG("hci%u", index);
2734
2735 hdev = hci_dev_get(index);
2736
Brian Gix64bd5302011-09-08 11:35:48 -07002737 if (!hdev)
2738 return -ENODEV;
2739
Brian Gix64bd5302011-09-08 11:35:48 -07002740 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, bdaddr);
Brian Gixa68668b2011-08-11 15:49:36 -07002741
2742 ev.auto_confirm = 0;
2743
2744 if (!conn || event != HCI_EV_USER_CONFIRM_REQUEST)
2745 goto no_auto_confirm;
2746
2747 loc_cap = (conn->io_capability == 0x04) ? 0x01 : conn->io_capability;
2748 rem_cap = conn->remote_cap;
2749 loc_mitm = conn->auth_type & 0x01;
2750 rem_mitm = conn->remote_auth & 0x01;
2751
Brian Gixdbf59292011-11-11 15:45:17 -08002752 if ((conn->auth_type & HCI_AT_DEDICATED_BONDING) &&
2753 conn->auth_initiator && rem_cap == 0x03)
2754 ev.auto_confirm = 1;
AnubhavGupta07c2a0f2012-02-16 19:03:59 +05302755 else if (loc_cap == 0x01 && (rem_cap == 0x00 || rem_cap == 0x03)) {
2756 if (!loc_mitm && !rem_mitm)
2757 value = 0;
Brian Gixa68668b2011-08-11 15:49:36 -07002758 goto no_auto_confirm;
AnubhavGupta07c2a0f2012-02-16 19:03:59 +05302759 }
Brian Gixa68668b2011-08-11 15:49:36 -07002760
2761
2762 if ((!loc_mitm || rem_cap == 0x03) && (!rem_mitm || loc_cap == 0x03))
2763 ev.auto_confirm = 1;
2764
2765no_auto_confirm:
2766 bacpy(&ev.bdaddr, bdaddr);
2767 ev.event = event;
2768 put_unaligned_le32(value, &ev.value);
2769
Brian Gix64bd5302011-09-08 11:35:48 -07002770 hci_dev_put(hdev);
2771
Brian Gixa68668b2011-08-11 15:49:36 -07002772 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, index, &ev, sizeof(ev),
2773 NULL);
2774}
2775
2776int mgmt_user_passkey_request(u16 index, bdaddr_t *bdaddr)
2777{
2778 struct mgmt_ev_user_passkey_request ev;
Johan Hedberga5c29682011-02-19 12:05:57 -03002779
2780 BT_DBG("hci%u", index);
2781
Johan Hedberga5c29682011-02-19 12:05:57 -03002782 bacpy(&ev.bdaddr, bdaddr);
Johan Hedberga5c29682011-02-19 12:05:57 -03002783
Brian Gixa68668b2011-08-11 15:49:36 -07002784 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, index, &ev, sizeof(ev),
Szymon Janc4e51eae2011-02-25 19:05:48 +01002785 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03002786}
2787
2788static int confirm_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status,
2789 u8 opcode)
2790{
2791 struct pending_cmd *cmd;
2792 struct mgmt_rp_user_confirm_reply rp;
2793 int err;
2794
2795 cmd = mgmt_pending_find(opcode, index);
2796 if (!cmd)
2797 return -ENOENT;
2798
Johan Hedberga5c29682011-02-19 12:05:57 -03002799 bacpy(&rp.bdaddr, bdaddr);
2800 rp.status = status;
Szymon Janc4e51eae2011-02-25 19:05:48 +01002801 err = cmd_complete(cmd->sk, index, opcode, &rp, sizeof(rp));
Johan Hedberga5c29682011-02-19 12:05:57 -03002802
Johan Hedberga664b5b2011-02-19 12:06:02 -03002803 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03002804
2805 return err;
2806}
2807
2808int mgmt_user_confirm_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status)
2809{
2810 return confirm_reply_complete(index, bdaddr, status,
2811 MGMT_OP_USER_CONFIRM_REPLY);
2812}
2813
Szymon Jancb8534e02011-03-01 16:55:34 +01002814int mgmt_user_confirm_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03002815{
2816 return confirm_reply_complete(index, bdaddr, status,
2817 MGMT_OP_USER_CONFIRM_NEG_REPLY);
2818}
Johan Hedberg2a611692011-02-19 12:06:00 -03002819
2820int mgmt_auth_failed(u16 index, bdaddr_t *bdaddr, u8 status)
2821{
2822 struct mgmt_ev_auth_failed ev;
2823
Johan Hedberg2a611692011-02-19 12:06:00 -03002824 bacpy(&ev.bdaddr, bdaddr);
2825 ev.status = status;
2826
Szymon Janc4e51eae2011-02-25 19:05:48 +01002827 return mgmt_event(MGMT_EV_AUTH_FAILED, index, &ev, sizeof(ev), NULL);
Johan Hedberg2a611692011-02-19 12:06:00 -03002828}
Johan Hedbergb312b1612011-03-16 14:29:37 +02002829
2830int mgmt_set_local_name_complete(u16 index, u8 *name, u8 status)
2831{
2832 struct pending_cmd *cmd;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002833 struct hci_dev *hdev;
Johan Hedbergb312b1612011-03-16 14:29:37 +02002834 struct mgmt_cp_set_local_name ev;
2835 int err;
2836
2837 memset(&ev, 0, sizeof(ev));
2838 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
2839
2840 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, index);
2841 if (!cmd)
2842 goto send_event;
2843
2844 if (status) {
2845 err = cmd_status(cmd->sk, index, MGMT_OP_SET_LOCAL_NAME, EIO);
2846 goto failed;
2847 }
2848
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002849 hdev = hci_dev_get(index);
2850 if (hdev) {
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002851 update_eir(hdev);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002852 hci_dev_put(hdev);
2853 }
2854
Johan Hedbergb312b1612011-03-16 14:29:37 +02002855 err = cmd_complete(cmd->sk, index, MGMT_OP_SET_LOCAL_NAME, &ev,
2856 sizeof(ev));
2857 if (err < 0)
2858 goto failed;
2859
2860send_event:
2861 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, index, &ev, sizeof(ev),
2862 cmd ? cmd->sk : NULL);
2863
2864failed:
2865 if (cmd)
2866 mgmt_pending_remove(cmd);
2867 return err;
2868}
Szymon Jancc35938b2011-03-22 13:12:21 +01002869
2870int mgmt_read_local_oob_data_reply_complete(u16 index, u8 *hash, u8 *randomizer,
2871 u8 status)
2872{
2873 struct pending_cmd *cmd;
2874 int err;
2875
2876 BT_DBG("hci%u status %u", index, status);
2877
2878 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, index);
2879 if (!cmd)
2880 return -ENOENT;
2881
2882 if (status) {
2883 err = cmd_status(cmd->sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
2884 EIO);
2885 } else {
2886 struct mgmt_rp_read_local_oob_data rp;
2887
2888 memcpy(rp.hash, hash, sizeof(rp.hash));
2889 memcpy(rp.randomizer, randomizer, sizeof(rp.randomizer));
2890
2891 err = cmd_complete(cmd->sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
2892 &rp, sizeof(rp));
2893 }
2894
2895 mgmt_pending_remove(cmd);
2896
2897 return err;
2898}
Johan Hedberge17acd42011-03-30 23:57:16 +03002899
Archana Ramachandran26a752b2011-12-20 11:27:40 -08002900void mgmt_read_rssi_complete(u16 index, s8 rssi, bdaddr_t *bdaddr,
2901 u16 handle, u8 status)
2902{
2903 struct mgmt_ev_rssi_update ev;
2904 struct hci_conn *conn;
2905 struct hci_dev *hdev;
2906
2907 if (status)
2908 return;
2909
2910 hdev = hci_dev_get(index);
2911 conn = hci_conn_hash_lookup_handle(hdev, handle);
2912
2913 if (!conn)
2914 return;
2915
2916 BT_DBG("rssi_update_thresh_exceed : %d ",
2917 conn->rssi_update_thresh_exceed);
2918 BT_DBG("RSSI Threshold : %d , recvd RSSI : %d ",
2919 conn->rssi_threshold, rssi);
2920
2921 if (conn->rssi_update_thresh_exceed == 1) {
2922 BT_DBG("rssi_update_thresh_exceed == 1");
Archana Ramachandran5d332a42012-03-22 15:35:34 -07002923 if (rssi > conn->rssi_threshold) {
Archana Ramachandran26a752b2011-12-20 11:27:40 -08002924 memset(&ev, 0, sizeof(ev));
2925 bacpy(&ev.bdaddr, bdaddr);
2926 ev.rssi = rssi;
2927 mgmt_event(MGMT_EV_RSSI_UPDATE, index, &ev,
2928 sizeof(ev), NULL);
2929 } else {
2930 hci_conn_set_rssi_reporter(conn, conn->rssi_threshold,
2931 conn->rssi_update_interval,
2932 conn->rssi_update_thresh_exceed);
2933 }
2934 } else {
2935 BT_DBG("rssi_update_thresh_exceed == 0");
Archana Ramachandran5d332a42012-03-22 15:35:34 -07002936 if (rssi < conn->rssi_threshold) {
Archana Ramachandran26a752b2011-12-20 11:27:40 -08002937 memset(&ev, 0, sizeof(ev));
2938 bacpy(&ev.bdaddr, bdaddr);
2939 ev.rssi = rssi;
2940 mgmt_event(MGMT_EV_RSSI_UPDATE, index, &ev,
2941 sizeof(ev), NULL);
2942 } else {
2943 hci_conn_set_rssi_reporter(conn, conn->rssi_threshold,
2944 conn->rssi_update_interval,
2945 conn->rssi_update_thresh_exceed);
2946 }
2947 }
2948}
2949
2950
Brian Gixa68668b2011-08-11 15:49:36 -07002951int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 type, u8 le,
2952 u8 *dev_class, s8 rssi, u8 eir_len, u8 *eir)
Johan Hedberge17acd42011-03-30 23:57:16 +03002953{
2954 struct mgmt_ev_device_found ev;
Brian Gix568dde92012-01-11 16:18:04 -08002955 struct hci_dev *hdev;
Brian Gixa68668b2011-08-11 15:49:36 -07002956 int err;
2957
2958 BT_DBG("le: %d", le);
Johan Hedberge17acd42011-03-30 23:57:16 +03002959
2960 memset(&ev, 0, sizeof(ev));
2961
2962 bacpy(&ev.bdaddr, bdaddr);
Johan Hedberge17acd42011-03-30 23:57:16 +03002963 ev.rssi = rssi;
Brian Gixa68668b2011-08-11 15:49:36 -07002964 ev.type = type;
2965 ev.le = le;
Johan Hedberge17acd42011-03-30 23:57:16 +03002966
Brian Gixa68668b2011-08-11 15:49:36 -07002967 if (dev_class)
2968 memcpy(ev.dev_class, dev_class, sizeof(ev.dev_class));
Johan Hedberge17acd42011-03-30 23:57:16 +03002969
Brian Gixa68668b2011-08-11 15:49:36 -07002970 if (eir && eir_len)
2971 memcpy(ev.eir, eir, eir_len);
2972
2973 err = mgmt_event(MGMT_EV_DEVICE_FOUND, index, &ev, sizeof(ev), NULL);
2974
2975 if (err < 0)
2976 return err;
2977
Brian Gix568dde92012-01-11 16:18:04 -08002978 hdev = hci_dev_get(index);
Brian Gixa68668b2011-08-11 15:49:36 -07002979
Brian Gix568dde92012-01-11 16:18:04 -08002980 if (!hdev)
2981 return 0;
Brian Gix64bd5302011-09-08 11:35:48 -07002982
Brian Gix568dde92012-01-11 16:18:04 -08002983 if (hdev->disco_state == SCAN_IDLE)
2984 goto done;
2985
2986 hdev->disco_int_count++;
2987
2988 if (hdev->disco_int_count >= hdev->disco_int_phase) {
2989 /* Inquiry scan for General Discovery LAP */
2990 struct hci_cp_inquiry cp = {{0x33, 0x8b, 0x9e}, 4, 0};
2991 struct hci_cp_le_set_scan_enable le_cp = {0, 0};
2992
2993 hdev->disco_int_phase *= 2;
2994 hdev->disco_int_count = 0;
2995 if (hdev->disco_state == SCAN_LE) {
2996 /* cancel LE scan */
2997 hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE,
2998 sizeof(le_cp), &le_cp);
2999 /* start BR scan */
3000 cp.num_rsp = (u8) hdev->disco_int_phase;
3001 hci_send_cmd(hdev, HCI_OP_INQUIRY,
3002 sizeof(cp), &cp);
3003 hdev->disco_state = SCAN_BR;
3004 del_timer_sync(&hdev->disco_le_timer);
Brian Gixa68668b2011-08-11 15:49:36 -07003005 }
3006 }
3007
Brian Gix568dde92012-01-11 16:18:04 -08003008done:
3009 hci_dev_put(hdev);
Brian Gixa68668b2011-08-11 15:49:36 -07003010 return 0;
Johan Hedberge17acd42011-03-30 23:57:16 +03003011}
Johan Hedberga88a9652011-03-30 13:18:12 +03003012
Brian Gixa68668b2011-08-11 15:49:36 -07003013
3014int mgmt_remote_name(u16 index, bdaddr_t *bdaddr, u8 status, u8 *name)
Johan Hedberga88a9652011-03-30 13:18:12 +03003015{
3016 struct mgmt_ev_remote_name ev;
3017
3018 memset(&ev, 0, sizeof(ev));
3019
3020 bacpy(&ev.bdaddr, bdaddr);
Brian Gixa68668b2011-08-11 15:49:36 -07003021 ev.status = status;
Johan Hedberga88a9652011-03-30 13:18:12 +03003022 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
3023
3024 return mgmt_event(MGMT_EV_REMOTE_NAME, index, &ev, sizeof(ev), NULL);
3025}
Prabhakaran Mc46230fa2011-11-30 18:11:21 +05303026
3027int mgmt_encrypt_change(u16 index, bdaddr_t *bdaddr, u8 status)
3028{
3029 struct mgmt_ev_encrypt_change ev;
3030
3031 BT_DBG("hci%u", index);
3032
3033 bacpy(&ev.bdaddr, bdaddr);
3034 ev.status = status;
3035
3036 return mgmt_event(MGMT_EV_ENCRYPT_CHANGE, index, &ev, sizeof(ev),
3037 NULL);
3038}
3039
Srinivas Krovvidi0916aed2011-12-20 12:06:34 +05303040int mgmt_remote_class(u16 index, bdaddr_t *bdaddr, u8 dev_class[3])
3041{
3042 struct mgmt_ev_remote_class ev;
3043
3044 memset(&ev, 0, sizeof(ev));
3045
3046 bacpy(&ev.bdaddr, bdaddr);
3047 memcpy(ev.dev_class, dev_class, 3);
3048
3049 return mgmt_event(MGMT_EV_REMOTE_CLASS, index, &ev, sizeof(ev), NULL);
3050}
Srinivas Krovvidid352b262012-01-12 19:46:26 +05303051
3052int mgmt_remote_version(u16 index, bdaddr_t *bdaddr, u8 ver, u16 mnf,
3053 u16 sub_ver)
3054{
3055 struct mgmt_ev_remote_version ev;
3056
3057 memset(&ev, 0, sizeof(ev));
3058
3059 bacpy(&ev.bdaddr, bdaddr);
3060 ev.lmp_ver = ver;
3061 ev.manufacturer = mnf;
3062 ev.lmp_subver = sub_ver;
3063
3064 return mgmt_event(MGMT_EV_REMOTE_VERSION, index, &ev, sizeof(ev), NULL);
3065}
Sunny Kapdif3caf882012-02-25 19:27:09 -08003066
3067int mgmt_remote_features(u16 index, bdaddr_t *bdaddr, u8 features[8])
3068{
3069 struct mgmt_ev_remote_features ev;
3070
3071 memset(&ev, 0, sizeof(ev));
3072
3073 bacpy(&ev.bdaddr, bdaddr);
3074 memcpy(ev.features, features, sizeof(ev.features));
3075
3076 return mgmt_event(MGMT_EV_REMOTE_FEATURES, index, &ev, sizeof(ev),
3077 NULL);
3078}