blob: 67a2900e92288cc5d67cd4726174e16472ba501f [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
765 name_len = strlen(hdev->dev_name);
766
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
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200893 err = update_class(hdev);
894 if (err < 0)
895 goto failed;
896
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300897 err = update_eir(hdev);
898 if (err < 0)
899 goto failed;
900
Szymon Janc4e51eae2011-02-25 19:05:48 +0100901 err = cmd_complete(sk, index, MGMT_OP_ADD_UUID, NULL, 0);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +0200902
903failed:
Subramanian Srinivasana727a492011-11-30 13:06:07 -0800904 hci_dev_unlock_bh(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +0200905 hci_dev_put(hdev);
906
907 return err;
908}
909
Szymon Janc4e51eae2011-02-25 19:05:48 +0100910static int remove_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +0200911{
912 struct list_head *p, *n;
Szymon Janc779cb852011-02-25 19:05:47 +0100913 struct mgmt_cp_remove_uuid *cp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +0200914 struct hci_dev *hdev;
915 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 +0200916 int err, found;
917
918 cp = (void *) data;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +0200919
Szymon Janc4e51eae2011-02-25 19:05:48 +0100920 BT_DBG("request for hci%u", index);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +0200921
Szymon Jancbdce7ba2011-02-25 19:05:49 +0100922 if (len != sizeof(*cp))
923 return cmd_status(sk, index, MGMT_OP_REMOVE_UUID, EINVAL);
924
Szymon Janc4e51eae2011-02-25 19:05:48 +0100925 hdev = hci_dev_get(index);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +0200926 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +0100927 return cmd_status(sk, index, MGMT_OP_REMOVE_UUID, ENODEV);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +0200928
Subramanian Srinivasana727a492011-11-30 13:06:07 -0800929 hci_dev_lock_bh(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +0200930
931 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
932 err = hci_uuids_clear(hdev);
933 goto unlock;
934 }
935
936 found = 0;
937
938 list_for_each_safe(p, n, &hdev->uuids) {
939 struct bt_uuid *match = list_entry(p, struct bt_uuid, list);
940
941 if (memcmp(match->uuid, cp->uuid, 16) != 0)
942 continue;
943
944 list_del(&match->list);
945 found++;
946 }
947
948 if (found == 0) {
Szymon Janc4e51eae2011-02-25 19:05:48 +0100949 err = cmd_status(sk, index, MGMT_OP_REMOVE_UUID, ENOENT);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +0200950 goto unlock;
951 }
952
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200953 err = update_class(hdev);
954 if (err < 0)
955 goto unlock;
956
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300957 err = update_eir(hdev);
958 if (err < 0)
959 goto unlock;
960
Szymon Janc4e51eae2011-02-25 19:05:48 +0100961 err = cmd_complete(sk, index, MGMT_OP_REMOVE_UUID, NULL, 0);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +0200962
963unlock:
Subramanian Srinivasana727a492011-11-30 13:06:07 -0800964 hci_dev_unlock_bh(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +0200965 hci_dev_put(hdev);
966
967 return err;
968}
969
Szymon Janc4e51eae2011-02-25 19:05:48 +0100970static int set_dev_class(struct sock *sk, u16 index, unsigned char *data,
971 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200972{
973 struct hci_dev *hdev;
974 struct mgmt_cp_set_dev_class *cp;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200975 int err;
976
977 cp = (void *) data;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200978
Szymon Janc4e51eae2011-02-25 19:05:48 +0100979 BT_DBG("request for hci%u", index);
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200980
Szymon Jancbdce7ba2011-02-25 19:05:49 +0100981 if (len != sizeof(*cp))
982 return cmd_status(sk, index, MGMT_OP_SET_DEV_CLASS, EINVAL);
983
Szymon Janc4e51eae2011-02-25 19:05:48 +0100984 hdev = hci_dev_get(index);
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200985 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +0100986 return cmd_status(sk, index, MGMT_OP_SET_DEV_CLASS, ENODEV);
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200987
Subramanian Srinivasana727a492011-11-30 13:06:07 -0800988 hci_dev_lock_bh(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200989
Brian Gix8a7f1642011-10-17 17:39:46 -0700990 hdev->major_class &= ~MGMT_MAJOR_CLASS_MASK;
991 hdev->major_class |= cp->major & MGMT_MAJOR_CLASS_MASK;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200992 hdev->minor_class = cp->minor;
993
994 err = update_class(hdev);
995
996 if (err == 0)
Szymon Janc4e51eae2011-02-25 19:05:48 +0100997 err = cmd_complete(sk, index, MGMT_OP_SET_DEV_CLASS, NULL, 0);
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200998
Subramanian Srinivasana727a492011-11-30 13:06:07 -0800999 hci_dev_unlock_bh(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001000 hci_dev_put(hdev);
1001
1002 return err;
1003}
1004
Szymon Janc4e51eae2011-02-25 19:05:48 +01001005static int set_service_cache(struct sock *sk, u16 index, unsigned char *data,
1006 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001007{
1008 struct hci_dev *hdev;
1009 struct mgmt_cp_set_service_cache *cp;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001010 int err;
1011
1012 cp = (void *) data;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001013
Szymon Jancbdce7ba2011-02-25 19:05:49 +01001014 if (len != sizeof(*cp))
Szymon Jancb8534e02011-03-01 16:55:34 +01001015 return cmd_status(sk, index, MGMT_OP_SET_SERVICE_CACHE, EINVAL);
Szymon Jancbdce7ba2011-02-25 19:05:49 +01001016
Szymon Janc4e51eae2011-02-25 19:05:48 +01001017 hdev = hci_dev_get(index);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001018 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +01001019 return cmd_status(sk, index, MGMT_OP_SET_SERVICE_CACHE, ENODEV);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001020
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001021 hci_dev_lock_bh(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001022
Szymon Janc4e51eae2011-02-25 19:05:48 +01001023 BT_DBG("hci%u enable %d", index, cp->enable);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001024
1025 if (cp->enable) {
1026 set_bit(HCI_SERVICE_CACHE, &hdev->flags);
1027 err = 0;
1028 } else {
1029 clear_bit(HCI_SERVICE_CACHE, &hdev->flags);
1030 err = update_class(hdev);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001031 if (err == 0)
1032 err = update_eir(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001033 }
1034
1035 if (err == 0)
Szymon Janc4e51eae2011-02-25 19:05:48 +01001036 err = cmd_complete(sk, index, MGMT_OP_SET_SERVICE_CACHE, NULL,
1037 0);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001038
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001039 hci_dev_unlock_bh(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001040 hci_dev_put(hdev);
1041
1042 return err;
1043}
1044
Szymon Janc4e51eae2011-02-25 19:05:48 +01001045static int load_keys(struct sock *sk, u16 index, unsigned char *data, u16 len)
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02001046{
1047 struct hci_dev *hdev;
1048 struct mgmt_cp_load_keys *cp;
Szymon Janc4e51eae2011-02-25 19:05:48 +01001049 u16 key_count, expected_len;
Vinicius Costa Gomesc00ddbf2011-07-08 18:31:44 -03001050 int i, err;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02001051
1052 cp = (void *) data;
Szymon Jancbdce7ba2011-02-25 19:05:49 +01001053
1054 if (len < sizeof(*cp))
1055 return -EINVAL;
1056
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02001057 key_count = get_unaligned_le16(&cp->key_count);
1058
1059 expected_len = sizeof(*cp) + key_count * sizeof(struct mgmt_key_info);
Vinicius Costa Gomesc00ddbf2011-07-08 18:31:44 -03001060 if (expected_len > len) {
1061 BT_ERR("load_keys: expected at least %u bytes, got %u bytes",
1062 expected_len, len);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02001063 return -EINVAL;
1064 }
1065
Szymon Janc4e51eae2011-02-25 19:05:48 +01001066 hdev = hci_dev_get(index);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02001067 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +01001068 return cmd_status(sk, index, MGMT_OP_LOAD_KEYS, ENODEV);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02001069
Szymon Janc4e51eae2011-02-25 19:05:48 +01001070 BT_DBG("hci%u debug_keys %u key_count %u", index, cp->debug_keys,
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02001071 key_count);
1072
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001073 hci_dev_lock_bh(hdev);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02001074
1075 hci_link_keys_clear(hdev);
1076
1077 set_bit(HCI_LINK_KEYS, &hdev->flags);
1078
1079 if (cp->debug_keys)
1080 set_bit(HCI_DEBUG_KEYS, &hdev->flags);
1081 else
1082 clear_bit(HCI_DEBUG_KEYS, &hdev->flags);
1083
Vinicius Costa Gomesc00ddbf2011-07-08 18:31:44 -03001084 len -= sizeof(*cp);
1085 i = 0;
1086
1087 while (i < len) {
1088 struct mgmt_key_info *key = (void *) cp->keys + i;
1089
Brian Gixa68668b2011-08-11 15:49:36 -07001090 i += sizeof(*key);
Vinicius Costa Gomesc00ddbf2011-07-08 18:31:44 -03001091
Brian Gixcf956772011-10-20 15:18:51 -07001092 if (key->key_type == KEY_TYPE_LTK) {
Vinicius Costa Gomesc00ddbf2011-07-08 18:31:44 -03001093 struct key_master_id *id = (void *) key->data;
1094
1095 if (key->dlen != sizeof(struct key_master_id))
1096 continue;
1097
Brian Gixcf956772011-10-20 15:18:51 -07001098 hci_add_ltk(hdev, 0, &key->bdaddr, key->addr_type,
1099 key->pin_len, key->auth, id->ediv,
1100 id->rand, key->val);
Vinicius Costa Gomesc00ddbf2011-07-08 18:31:44 -03001101
1102 continue;
1103 }
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02001104
Brian Gixcf956772011-10-20 15:18:51 -07001105 hci_add_link_key(hdev, 0, &key->bdaddr, key->val, key->key_type,
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02001106 key->pin_len);
1107 }
1108
Vinicius Costa Gomesc00ddbf2011-07-08 18:31:44 -03001109 err = cmd_complete(sk, index, MGMT_OP_LOAD_KEYS, NULL, 0);
1110
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001111 hci_dev_unlock_bh(hdev);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02001112 hci_dev_put(hdev);
1113
Vinicius Costa Gomesc00ddbf2011-07-08 18:31:44 -03001114 return err;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02001115}
1116
Szymon Janc4e51eae2011-02-25 19:05:48 +01001117static int remove_key(struct sock *sk, u16 index, unsigned char *data, u16 len)
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02001118{
1119 struct hci_dev *hdev;
1120 struct mgmt_cp_remove_key *cp;
1121 struct hci_conn *conn;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02001122 int err;
1123
1124 cp = (void *) data;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02001125
Szymon Jancbdce7ba2011-02-25 19:05:49 +01001126 if (len != sizeof(*cp))
1127 return cmd_status(sk, index, MGMT_OP_REMOVE_KEY, EINVAL);
1128
Szymon Janc4e51eae2011-02-25 19:05:48 +01001129 hdev = hci_dev_get(index);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02001130 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +01001131 return cmd_status(sk, index, MGMT_OP_REMOVE_KEY, ENODEV);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02001132
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001133 hci_dev_lock_bh(hdev);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02001134
1135 err = hci_remove_link_key(hdev, &cp->bdaddr);
1136 if (err < 0) {
Szymon Janc4e51eae2011-02-25 19:05:48 +01001137 err = cmd_status(sk, index, MGMT_OP_REMOVE_KEY, -err);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02001138 goto unlock;
1139 }
1140
1141 err = 0;
1142
1143 if (!test_bit(HCI_UP, &hdev->flags) || !cp->disconnect)
1144 goto unlock;
1145
1146 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1147 if (conn) {
1148 struct hci_cp_disconnect dc;
1149
1150 put_unaligned_le16(conn->handle, &dc.handle);
1151 dc.reason = 0x13; /* Remote User Terminated Connection */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001152 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, 0, NULL);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02001153 }
1154
1155unlock:
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001156 hci_dev_unlock_bh(hdev);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02001157 hci_dev_put(hdev);
1158
1159 return err;
1160}
1161
Szymon Janc4e51eae2011-02-25 19:05:48 +01001162static int disconnect(struct sock *sk, u16 index, unsigned char *data, u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02001163{
1164 struct hci_dev *hdev;
1165 struct mgmt_cp_disconnect *cp;
1166 struct hci_cp_disconnect dc;
Johan Hedberg366a0332011-02-19 12:05:55 -03001167 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02001168 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02001169 int err;
1170
1171 BT_DBG("");
1172
1173 cp = (void *) data;
Johan Hedberg8962ee72011-01-20 12:40:27 +02001174
Szymon Jancbdce7ba2011-02-25 19:05:49 +01001175 if (len != sizeof(*cp))
1176 return cmd_status(sk, index, MGMT_OP_DISCONNECT, EINVAL);
1177
Szymon Janc4e51eae2011-02-25 19:05:48 +01001178 hdev = hci_dev_get(index);
Johan Hedberg8962ee72011-01-20 12:40:27 +02001179 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +01001180 return cmd_status(sk, index, MGMT_OP_DISCONNECT, ENODEV);
Johan Hedberg8962ee72011-01-20 12:40:27 +02001181
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001182 hci_dev_lock_bh(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02001183
1184 if (!test_bit(HCI_UP, &hdev->flags)) {
Szymon Janc4e51eae2011-02-25 19:05:48 +01001185 err = cmd_status(sk, index, MGMT_OP_DISCONNECT, ENETDOWN);
Johan Hedberg8962ee72011-01-20 12:40:27 +02001186 goto failed;
1187 }
1188
Szymon Janc4e51eae2011-02-25 19:05:48 +01001189 if (mgmt_pending_find(MGMT_OP_DISCONNECT, index)) {
1190 err = cmd_status(sk, index, MGMT_OP_DISCONNECT, EBUSY);
Johan Hedberg8962ee72011-01-20 12:40:27 +02001191 goto failed;
1192 }
1193
1194 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1195 if (!conn) {
Inga Stotlandbd6a49a2011-08-23 16:13:39 -07001196 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->bdaddr);
1197 if (!conn) {
1198 err = cmd_status(sk, index, MGMT_OP_DISCONNECT,
1199 ENOTCONN);
1200 goto failed;
1201 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02001202 }
1203
Szymon Janc4e51eae2011-02-25 19:05:48 +01001204 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, index, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03001205 if (!cmd) {
1206 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02001207 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03001208 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02001209
1210 put_unaligned_le16(conn->handle, &dc.handle);
1211 dc.reason = 0x13; /* Remote User Terminated Connection */
1212
1213 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1214 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03001215 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02001216
1217failed:
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001218 hci_dev_unlock_bh(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02001219 hci_dev_put(hdev);
1220
1221 return err;
1222}
1223
Szymon Janc8ce62842011-03-01 16:55:32 +01001224static int get_connections(struct sock *sk, u16 index)
Johan Hedberg2784eb42011-01-21 13:56:35 +02001225{
Johan Hedberg2784eb42011-01-21 13:56:35 +02001226 struct mgmt_rp_get_connections *rp;
1227 struct hci_dev *hdev;
1228 struct list_head *p;
Johan Hedberga38528f2011-01-22 06:46:43 +02001229 size_t rp_len;
Szymon Janc4e51eae2011-02-25 19:05:48 +01001230 u16 count;
Johan Hedberg2784eb42011-01-21 13:56:35 +02001231 int i, err;
1232
1233 BT_DBG("");
1234
Szymon Janc4e51eae2011-02-25 19:05:48 +01001235 hdev = hci_dev_get(index);
Johan Hedberg2784eb42011-01-21 13:56:35 +02001236 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +01001237 return cmd_status(sk, index, MGMT_OP_GET_CONNECTIONS, ENODEV);
Johan Hedberg2784eb42011-01-21 13:56:35 +02001238
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001239 hci_dev_lock_bh(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02001240
1241 count = 0;
1242 list_for_each(p, &hdev->conn_hash.list) {
1243 count++;
1244 }
1245
Johan Hedberga38528f2011-01-22 06:46:43 +02001246 rp_len = sizeof(*rp) + (count * sizeof(bdaddr_t));
1247 rp = kmalloc(rp_len, GFP_ATOMIC);
1248 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02001249 err = -ENOMEM;
1250 goto unlock;
1251 }
1252
Johan Hedberg2784eb42011-01-21 13:56:35 +02001253 put_unaligned_le16(count, &rp->conn_count);
1254
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001255 read_lock(&hci_dev_list_lock);
1256
Johan Hedberg2784eb42011-01-21 13:56:35 +02001257 i = 0;
1258 list_for_each(p, &hdev->conn_hash.list) {
1259 struct hci_conn *c = list_entry(p, struct hci_conn, list);
1260
1261 bacpy(&rp->conn[i++], &c->dst);
1262 }
1263
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001264 read_unlock(&hci_dev_list_lock);
1265
Szymon Janc4e51eae2011-02-25 19:05:48 +01001266 err = cmd_complete(sk, index, MGMT_OP_GET_CONNECTIONS, rp, rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02001267
1268unlock:
Johan Hedberga38528f2011-01-22 06:46:43 +02001269 kfree(rp);
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001270 hci_dev_unlock_bh(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02001271 hci_dev_put(hdev);
1272 return err;
1273}
1274
Szymon Janc4e51eae2011-02-25 19:05:48 +01001275static int pin_code_reply(struct sock *sk, u16 index, unsigned char *data,
1276 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02001277{
1278 struct hci_dev *hdev;
1279 struct mgmt_cp_pin_code_reply *cp;
1280 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03001281 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02001282 int err;
1283
1284 BT_DBG("");
1285
1286 cp = (void *) data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02001287
Szymon Jancbdce7ba2011-02-25 19:05:49 +01001288 if (len != sizeof(*cp))
1289 return cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, EINVAL);
1290
Szymon Janc4e51eae2011-02-25 19:05:48 +01001291 hdev = hci_dev_get(index);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001292 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +01001293 return cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, ENODEV);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001294
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001295 hci_dev_lock_bh(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001296
1297 if (!test_bit(HCI_UP, &hdev->flags)) {
Szymon Janc4e51eae2011-02-25 19:05:48 +01001298 err = cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, ENETDOWN);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001299 goto failed;
1300 }
1301
Szymon Janc4e51eae2011-02-25 19:05:48 +01001302 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, index, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03001303 if (!cmd) {
1304 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02001305 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03001306 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02001307
1308 bacpy(&reply.bdaddr, &cp->bdaddr);
1309 reply.pin_len = cp->pin_len;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001310 memcpy(reply.pin_code, cp->pin_code, 16);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001311
1312 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
1313 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03001314 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001315
1316failed:
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001317 hci_dev_unlock_bh(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001318 hci_dev_put(hdev);
1319
1320 return err;
1321}
1322
Prabhakaran Mc46230fa2011-11-30 18:11:21 +05301323static int encrypt_link(struct sock *sk, u16 index, unsigned char *data,
1324 u16 len)
1325{
1326 struct hci_dev *hdev;
1327 struct mgmt_cp_encrypt_link *cp;
1328 struct hci_cp_set_conn_encrypt enc;
1329 struct hci_conn *conn;
1330 int err = 0;
1331
1332 BT_DBG("");
1333
1334 cp = (void *) data;
1335
1336 if (len != sizeof(*cp))
1337 return cmd_status(sk, index, MGMT_OP_ENCRYPT_LINK, EINVAL);
1338
1339 hdev = hci_dev_get(index);
1340 if (!hdev)
1341 return cmd_status(sk, index, MGMT_OP_ENCRYPT_LINK, ENODEV);
1342
1343 hci_dev_lock(hdev);
1344
1345 if (!test_bit(HCI_UP, &hdev->flags)) {
1346 err = cmd_status(sk, index, MGMT_OP_ENCRYPT_LINK, ENETDOWN);
1347 goto failed;
1348 }
1349
1350 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
1351 &cp->bdaddr);
1352 if (!conn)
1353 return cmd_status(sk, index, MGMT_OP_ENCRYPT_LINK, ENOTCONN);
1354
1355 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend))
1356 return cmd_status(sk, index, MGMT_OP_ENCRYPT_LINK, EINPROGRESS);
1357
1358 if (conn->link_mode & HCI_LM_AUTH) {
1359 enc.handle = cpu_to_le16(conn->handle);
1360 enc.encrypt = cp->enable;
1361 err = hci_send_cmd(hdev,
1362 HCI_OP_SET_CONN_ENCRYPT, sizeof(enc), &enc);
1363 } else {
1364 conn->auth_initiator = 1;
1365 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
1366 struct hci_cp_auth_requested cp;
1367 cp.handle = cpu_to_le16(conn->handle);
1368 err = hci_send_cmd(conn->hdev,
1369 HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
1370 }
1371 }
1372
1373failed:
1374 hci_dev_unlock(hdev);
1375 hci_dev_put(hdev);
1376
1377 return err;
1378}
1379
1380
Szymon Janc4e51eae2011-02-25 19:05:48 +01001381static int pin_code_neg_reply(struct sock *sk, u16 index, unsigned char *data,
1382 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02001383{
1384 struct hci_dev *hdev;
1385 struct mgmt_cp_pin_code_neg_reply *cp;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001386 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02001387 int err;
1388
1389 BT_DBG("");
1390
1391 cp = (void *) data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02001392
Szymon Jancbdce7ba2011-02-25 19:05:49 +01001393 if (len != sizeof(*cp))
1394 return cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY,
1395 EINVAL);
1396
Szymon Janc4e51eae2011-02-25 19:05:48 +01001397 hdev = hci_dev_get(index);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001398 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +01001399 return cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY,
1400 ENODEV);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001401
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001402 hci_dev_lock_bh(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001403
1404 if (!test_bit(HCI_UP, &hdev->flags)) {
Szymon Janc4e51eae2011-02-25 19:05:48 +01001405 err = cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY,
1406 ENETDOWN);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001407 goto failed;
1408 }
1409
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001410 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, index,
1411 data, len);
1412 if (!cmd) {
1413 err = -ENOMEM;
1414 goto failed;
1415 }
1416
1417 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, sizeof(cp->bdaddr),
1418 &cp->bdaddr);
1419 if (err < 0)
1420 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001421
1422failed:
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001423 hci_dev_unlock_bh(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001424 hci_dev_put(hdev);
1425
1426 return err;
1427}
1428
Szymon Janc4e51eae2011-02-25 19:05:48 +01001429static int set_io_capability(struct sock *sk, u16 index, unsigned char *data,
1430 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02001431{
1432 struct hci_dev *hdev;
1433 struct mgmt_cp_set_io_capability *cp;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02001434
1435 BT_DBG("");
1436
1437 cp = (void *) data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02001438
Szymon Jancbdce7ba2011-02-25 19:05:49 +01001439 if (len != sizeof(*cp))
Szymon Jancb8534e02011-03-01 16:55:34 +01001440 return cmd_status(sk, index, MGMT_OP_SET_IO_CAPABILITY, EINVAL);
Szymon Jancbdce7ba2011-02-25 19:05:49 +01001441
Szymon Janc4e51eae2011-02-25 19:05:48 +01001442 hdev = hci_dev_get(index);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02001443 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +01001444 return cmd_status(sk, index, MGMT_OP_SET_IO_CAPABILITY, ENODEV);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02001445
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001446 hci_dev_lock_bh(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02001447
1448 hdev->io_capability = cp->io_capability;
1449
1450 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Szymon Jancb8534e02011-03-01 16:55:34 +01001451 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02001452
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001453 hci_dev_unlock_bh(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02001454 hci_dev_put(hdev);
1455
Szymon Janc4e51eae2011-02-25 19:05:48 +01001456 return cmd_complete(sk, index, MGMT_OP_SET_IO_CAPABILITY, NULL, 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02001457}
1458
Johan Hedberge9a416b2011-02-19 12:05:56 -03001459static inline struct pending_cmd *find_pairing(struct hci_conn *conn)
1460{
1461 struct hci_dev *hdev = conn->hdev;
1462 struct list_head *p;
1463
1464 list_for_each(p, &cmd_list) {
1465 struct pending_cmd *cmd;
1466
1467 cmd = list_entry(p, struct pending_cmd, list);
1468
1469 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
1470 continue;
1471
1472 if (cmd->index != hdev->id)
1473 continue;
1474
1475 if (cmd->user_data != conn)
1476 continue;
1477
1478 return cmd;
1479 }
1480
1481 return NULL;
1482}
1483
1484static void pairing_complete(struct pending_cmd *cmd, u8 status)
1485{
1486 struct mgmt_rp_pair_device rp;
1487 struct hci_conn *conn = cmd->user_data;
1488
Brian Gixa68668b2011-08-11 15:49:36 -07001489 BT_DBG(" %u", status);
1490
Johan Hedberge9a416b2011-02-19 12:05:56 -03001491 bacpy(&rp.bdaddr, &conn->dst);
1492 rp.status = status;
1493
Szymon Janc4e51eae2011-02-25 19:05:48 +01001494 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03001495
1496 /* So we don't get further callbacks for this connection */
1497 conn->connect_cfm_cb = NULL;
1498 conn->security_cfm_cb = NULL;
1499 conn->disconn_cfm_cb = NULL;
1500
Johan Hedberga664b5b2011-02-19 12:06:02 -03001501 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03001502}
1503
1504static void pairing_complete_cb(struct hci_conn *conn, u8 status)
1505{
1506 struct pending_cmd *cmd;
1507
Brian Gixa68668b2011-08-11 15:49:36 -07001508 BT_DBG(" %u", status);
Johan Hedberge9a416b2011-02-19 12:05:56 -03001509
1510 cmd = find_pairing(conn);
1511 if (!cmd) {
1512 BT_DBG("Unable to find a pending command");
1513 return;
1514 }
1515
1516 pairing_complete(cmd, status);
1517}
1518
Brian Gix6d5fb8a2011-09-09 14:53:04 -07001519static void pairing_security_complete_cb(struct hci_conn *conn, u8 status)
Brian Gixa68668b2011-08-11 15:49:36 -07001520{
1521 struct pending_cmd *cmd;
1522
1523 BT_DBG(" %u", status);
1524
1525 cmd = find_pairing(conn);
1526 if (!cmd) {
1527 BT_DBG("Unable to find a pending command");
1528 return;
1529 }
1530
1531 if (conn->type == LE_LINK)
1532 smp_link_encrypt_cmplt(conn->l2cap_data, status,
1533 status ? 0 : 1);
1534 else
1535 pairing_complete(cmd, status);
1536}
1537
Brian Gix6d5fb8a2011-09-09 14:53:04 -07001538static void pairing_connect_complete_cb(struct hci_conn *conn, u8 status)
Brian Gixa68668b2011-08-11 15:49:36 -07001539{
1540 struct pending_cmd *cmd;
1541
1542 BT_DBG("conn: %p %u", conn, status);
1543
1544 cmd = find_pairing(conn);
1545 if (!cmd) {
1546 BT_DBG("Unable to find a pending command");
1547 return;
1548 }
Brian Gix114f3a62011-09-27 14:02:20 -07001549
1550 if (status)
1551 pairing_complete(cmd, status);
1552
Brian Gix6d5fb8a2011-09-09 14:53:04 -07001553 hci_conn_put(conn);
Brian Gixa68668b2011-08-11 15:49:36 -07001554}
1555
1556static void discovery_terminated(struct pending_cmd *cmd, void *data)
1557{
Brian Gix6e349d02011-11-28 14:51:14 -08001558 struct hci_dev *hdev;
Brian Gixa68668b2011-08-11 15:49:36 -07001559 struct mgmt_mode ev = {0};
Brian Gixa68668b2011-08-11 15:49:36 -07001560
1561 BT_DBG("");
Brian Gix6e349d02011-11-28 14:51:14 -08001562 hdev = hci_dev_get(cmd->index);
1563 if (!hdev)
1564 goto not_found;
1565
Brian Gix568dde92012-01-11 16:18:04 -08001566 del_timer(&hdev->disco_le_timer);
1567 del_timer(&hdev->disco_timer);
Brian Gix6e349d02011-11-28 14:51:14 -08001568 hci_dev_put(hdev);
1569
1570not_found:
Brian Gixa68668b2011-08-11 15:49:36 -07001571 mgmt_event(MGMT_EV_DISCOVERING, cmd->index, &ev, sizeof(ev), NULL);
1572
1573 list_del(&cmd->list);
1574
1575 mgmt_pending_free(cmd);
1576}
1577
Szymon Janc4e51eae2011-02-25 19:05:48 +01001578static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03001579{
1580 struct hci_dev *hdev;
1581 struct mgmt_cp_pair_device *cp;
1582 struct pending_cmd *cmd;
Brian Gixa68668b2011-08-11 15:49:36 -07001583 u8 sec_level, auth_type, io_cap;
Johan Hedberge9a416b2011-02-19 12:05:56 -03001584 struct hci_conn *conn;
Brian Gixfdd38922011-09-28 16:23:48 -07001585 struct adv_entry *entry;
Johan Hedberge9a416b2011-02-19 12:05:56 -03001586 int err;
1587
1588 BT_DBG("");
1589
Brian Gix64bd5302011-09-08 11:35:48 -07001590 cp = (void *) data;
1591
1592 if (len != sizeof(*cp))
1593 return cmd_status(sk, index, MGMT_OP_PAIR_DEVICE, EINVAL);
1594
Szymon Janc4e51eae2011-02-25 19:05:48 +01001595 hdev = hci_dev_get(index);
Brian Gixa68668b2011-08-11 15:49:36 -07001596
Johan Hedberge9a416b2011-02-19 12:05:56 -03001597 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +01001598 return cmd_status(sk, index, MGMT_OP_PAIR_DEVICE, ENODEV);
Johan Hedberge9a416b2011-02-19 12:05:56 -03001599
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001600 hci_dev_lock_bh(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03001601
Prabhakaran Mc6001a712011-09-06 11:56:25 +05301602 BT_DBG("SSP Cap is %d", cp->ssp_cap);
1603 io_cap = cp->io_cap;
1604 if ((cp->ssp_cap == 0) || (io_cap == 0x03)) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03001605 sec_level = BT_SECURITY_MEDIUM;
1606 auth_type = HCI_AT_DEDICATED_BONDING;
1607 } else {
1608 sec_level = BT_SECURITY_HIGH;
1609 auth_type = HCI_AT_DEDICATED_BONDING_MITM;
1610 }
1611
Brian Gixfdd38922011-09-28 16:23:48 -07001612 entry = hci_find_adv_entry(hdev, &cp->bdaddr);
1613 if (entry && entry->flags & 0x04) {
Brian Gixa68668b2011-08-11 15:49:36 -07001614 conn = hci_connect(hdev, LE_LINK, 0, &cp->bdaddr, sec_level,
1615 auth_type);
Brian Gixa68668b2011-08-11 15:49:36 -07001616 } else {
1617 /* ACL-SSP does not support io_cap 0x04 (KeyboadDisplay) */
1618 if (io_cap == 0x04)
1619 io_cap = 0x01;
1620 conn = hci_connect(hdev, ACL_LINK, 0, &cp->bdaddr, sec_level,
1621 auth_type);
1622 }
1623
Ville Tervo30e76272011-02-22 16:10:53 -03001624 if (IS_ERR(conn)) {
1625 err = PTR_ERR(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03001626 goto unlock;
1627 }
1628
1629 if (conn->connect_cfm_cb) {
1630 hci_conn_put(conn);
Szymon Janc4e51eae2011-02-25 19:05:48 +01001631 err = cmd_status(sk, index, MGMT_OP_PAIR_DEVICE, EBUSY);
Johan Hedberge9a416b2011-02-19 12:05:56 -03001632 goto unlock;
1633 }
1634
Szymon Janc4e51eae2011-02-25 19:05:48 +01001635 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, index, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03001636 if (!cmd) {
1637 err = -ENOMEM;
1638 hci_conn_put(conn);
1639 goto unlock;
1640 }
1641
Brian Gix6d5fb8a2011-09-09 14:53:04 -07001642 conn->connect_cfm_cb = pairing_connect_complete_cb;
1643 conn->security_cfm_cb = pairing_security_complete_cb;
Johan Hedberge9a416b2011-02-19 12:05:56 -03001644 conn->disconn_cfm_cb = pairing_complete_cb;
Brian Gixa68668b2011-08-11 15:49:36 -07001645 conn->io_capability = io_cap;
Johan Hedberge9a416b2011-02-19 12:05:56 -03001646 cmd->user_data = conn;
1647
1648 if (conn->state == BT_CONNECTED &&
1649 hci_conn_security(conn, sec_level, auth_type))
1650 pairing_complete(cmd, 0);
1651
1652 err = 0;
1653
1654unlock:
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001655 hci_dev_unlock_bh(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03001656 hci_dev_put(hdev);
1657
1658 return err;
1659}
1660
Szymon Janc4e51eae2011-02-25 19:05:48 +01001661static int user_confirm_reply(struct sock *sk, u16 index, unsigned char *data,
Brian Gixa68668b2011-08-11 15:49:36 -07001662 u16 len, u16 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03001663{
1664 struct mgmt_cp_user_confirm_reply *cp = (void *) data;
Brian Gixa68668b2011-08-11 15:49:36 -07001665 u16 mgmt_op = opcode, hci_op;
Johan Hedberga5c29682011-02-19 12:05:57 -03001666 struct pending_cmd *cmd;
1667 struct hci_dev *hdev;
Brian Gixa68668b2011-08-11 15:49:36 -07001668 struct hci_conn *le_conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03001669 int err;
1670
Brian Gixa68668b2011-08-11 15:49:36 -07001671 BT_DBG("%d", mgmt_op);
Johan Hedberga5c29682011-02-19 12:05:57 -03001672
Brian Gixa68668b2011-08-11 15:49:36 -07001673 if (mgmt_op == MGMT_OP_USER_CONFIRM_NEG_REPLY)
Johan Hedberga5c29682011-02-19 12:05:57 -03001674 hci_op = HCI_OP_USER_CONFIRM_NEG_REPLY;
Brian Gixa68668b2011-08-11 15:49:36 -07001675 else
1676 hci_op = HCI_OP_USER_CONFIRM_REPLY;
Johan Hedberga5c29682011-02-19 12:05:57 -03001677
Brian Gixa68668b2011-08-11 15:49:36 -07001678 if (len < sizeof(*cp))
Szymon Jancbdce7ba2011-02-25 19:05:49 +01001679 return cmd_status(sk, index, mgmt_op, EINVAL);
1680
Szymon Janc4e51eae2011-02-25 19:05:48 +01001681 hdev = hci_dev_get(index);
Johan Hedberga5c29682011-02-19 12:05:57 -03001682 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +01001683 return cmd_status(sk, index, mgmt_op, ENODEV);
Johan Hedberga5c29682011-02-19 12:05:57 -03001684
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001685 hci_dev_lock_bh(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02001686
Johan Hedberga5c29682011-02-19 12:05:57 -03001687 if (!test_bit(HCI_UP, &hdev->flags)) {
Szymon Janc4e51eae2011-02-25 19:05:48 +01001688 err = cmd_status(sk, index, mgmt_op, ENETDOWN);
Brian Gixa68668b2011-08-11 15:49:36 -07001689 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03001690 }
1691
Brian Gixa68668b2011-08-11 15:49:36 -07001692 le_conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->bdaddr);
1693 if (le_conn) {
1694 err = le_user_confirm_reply(le_conn, mgmt_op, (void *) cp);
1695 goto done;
1696 }
1697 BT_DBG("BR/EDR: %s", mgmt_op == MGMT_OP_USER_CONFIRM_NEG_REPLY ?
1698 "Reject" : "Accept");
1699
Szymon Janc4e51eae2011-02-25 19:05:48 +01001700 cmd = mgmt_pending_add(sk, mgmt_op, index, data, len);
Johan Hedberga5c29682011-02-19 12:05:57 -03001701 if (!cmd) {
1702 err = -ENOMEM;
Brian Gixa68668b2011-08-11 15:49:36 -07001703 goto done;
1704 }
1705
1706 err = hci_send_cmd(hdev, hci_op, sizeof(cp->bdaddr), &cp->bdaddr);
1707 if (err < 0)
1708 mgmt_pending_remove(cmd);
1709
1710done:
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001711 hci_dev_unlock_bh(hdev);
Brian Gixa68668b2011-08-11 15:49:36 -07001712 hci_dev_put(hdev);
1713
1714 return err;
1715}
1716
1717static int resolve_name(struct sock *sk, u16 index, unsigned char *data,
1718 u16 len)
1719{
1720 struct mgmt_cp_resolve_name *mgmt_cp = (void *) data;
1721 struct hci_cp_remote_name_req hci_cp;
1722 struct hci_dev *hdev;
1723 struct pending_cmd *cmd;
1724 int err;
1725
1726 BT_DBG("");
1727
1728 if (len != sizeof(*mgmt_cp))
1729 return cmd_status(sk, index, MGMT_OP_RESOLVE_NAME, EINVAL);
1730
1731 hdev = hci_dev_get(index);
1732 if (!hdev)
1733 return cmd_status(sk, index, MGMT_OP_RESOLVE_NAME, ENODEV);
1734
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001735 hci_dev_lock_bh(hdev);
Brian Gixa68668b2011-08-11 15:49:36 -07001736
1737 cmd = mgmt_pending_add(sk, MGMT_OP_RESOLVE_NAME, index, data, len);
1738 if (!cmd) {
1739 err = -ENOMEM;
Johan Hedberga5c29682011-02-19 12:05:57 -03001740 goto failed;
1741 }
1742
Brian Gixa68668b2011-08-11 15:49:36 -07001743 memset(&hci_cp, 0, sizeof(hci_cp));
1744 bacpy(&hci_cp.bdaddr, &mgmt_cp->bdaddr);
1745 err = hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(hci_cp),
1746 &hci_cp);
Johan Hedberga664b5b2011-02-19 12:06:02 -03001747 if (err < 0)
1748 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03001749
1750failed:
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001751 hci_dev_unlock_bh(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03001752 hci_dev_put(hdev);
1753
1754 return err;
1755}
1756
Brian Gix7f7e16c2011-11-01 16:27:25 -07001757static int set_connection_params(struct sock *sk, u16 index,
1758 unsigned char *data, u16 len)
1759{
1760 struct mgmt_cp_set_connection_params *cp = (void *) data;
1761 struct hci_dev *hdev;
1762 struct hci_conn *conn;
1763 int err;
1764
1765 BT_DBG("");
1766
1767 if (len != sizeof(*cp))
1768 return cmd_status(sk, index, MGMT_OP_SET_CONNECTION_PARAMS,
1769 EINVAL);
1770
1771 hdev = hci_dev_get(index);
1772 if (!hdev)
1773 return cmd_status(sk, index, MGMT_OP_SET_CONNECTION_PARAMS,
1774 ENODEV);
1775
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001776 hci_dev_lock_bh(hdev);
Brian Gix7f7e16c2011-11-01 16:27:25 -07001777
1778 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->bdaddr);
1779 if (!conn) {
1780 err = cmd_status(sk, index, MGMT_OP_SET_CONNECTION_PARAMS,
1781 ENOTCONN);
1782 goto failed;
1783 }
1784
1785 hci_le_conn_update(conn, le16_to_cpu(cp->interval_min),
1786 le16_to_cpu(cp->interval_max),
1787 le16_to_cpu(cp->slave_latency),
1788 le16_to_cpu(cp->timeout_multiplier));
1789
1790 err = cmd_status(sk, index, MGMT_OP_SET_CONNECTION_PARAMS, 0);
1791
1792failed:
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001793 hci_dev_unlock_bh(hdev);
Brian Gix7f7e16c2011-11-01 16:27:25 -07001794 hci_dev_put(hdev);
1795
1796 return err;
1797}
1798
Johan Hedbergb312b1612011-03-16 14:29:37 +02001799static int set_local_name(struct sock *sk, u16 index, unsigned char *data,
1800 u16 len)
1801{
1802 struct mgmt_cp_set_local_name *mgmt_cp = (void *) data;
1803 struct hci_cp_write_local_name hci_cp;
1804 struct hci_dev *hdev;
1805 struct pending_cmd *cmd;
1806 int err;
1807
1808 BT_DBG("");
1809
1810 if (len != sizeof(*mgmt_cp))
1811 return cmd_status(sk, index, MGMT_OP_SET_LOCAL_NAME, EINVAL);
1812
1813 hdev = hci_dev_get(index);
1814 if (!hdev)
1815 return cmd_status(sk, index, MGMT_OP_SET_LOCAL_NAME, ENODEV);
1816
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001817 hci_dev_lock_bh(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02001818
1819 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, index, data, len);
1820 if (!cmd) {
1821 err = -ENOMEM;
1822 goto failed;
1823 }
1824
1825 memcpy(hci_cp.name, mgmt_cp->name, sizeof(hci_cp.name));
1826 err = hci_send_cmd(hdev, HCI_OP_WRITE_LOCAL_NAME, sizeof(hci_cp),
1827 &hci_cp);
1828 if (err < 0)
1829 mgmt_pending_remove(cmd);
1830
1831failed:
Subramanian Srinivasana727a492011-11-30 13:06:07 -08001832 hci_dev_unlock_bh(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02001833 hci_dev_put(hdev);
1834
1835 return err;
1836}
1837
Brian Gixa68668b2011-08-11 15:49:36 -07001838static void discovery_rsp(struct pending_cmd *cmd, void *data)
1839{
1840 struct mgmt_mode ev;
1841
1842 BT_DBG("");
1843 if (cmd->opcode == MGMT_OP_START_DISCOVERY) {
1844 ev.val = 1;
1845 cmd_status(cmd->sk, cmd->index, MGMT_OP_START_DISCOVERY, 0);
1846 } else {
1847 ev.val = 0;
1848 cmd_complete(cmd->sk, cmd->index, MGMT_OP_STOP_DISCOVERY,
1849 NULL, 0);
1850 if (cmd->opcode == MGMT_OP_STOP_DISCOVERY) {
Brian Gix6e349d02011-11-28 14:51:14 -08001851 struct hci_dev *hdev = hci_dev_get(cmd->index);
1852 if (hdev) {
Brian Gix568dde92012-01-11 16:18:04 -08001853 del_timer(&hdev->disco_le_timer);
1854 del_timer(&hdev->disco_timer);
Brian Gix6e349d02011-11-28 14:51:14 -08001855 hci_dev_put(hdev);
1856 }
Brian Gixa68668b2011-08-11 15:49:36 -07001857 }
1858 }
1859
1860 mgmt_event(MGMT_EV_DISCOVERING, cmd->index, &ev, sizeof(ev), NULL);
1861
1862 list_del(&cmd->list);
1863
1864 mgmt_pending_free(cmd);
1865}
1866
1867void mgmt_inquiry_started(u16 index)
1868{
1869 BT_DBG("");
1870 mgmt_pending_foreach(MGMT_OP_START_DISCOVERY, index,
1871 discovery_rsp, NULL);
1872}
1873
1874void mgmt_inquiry_complete_evt(u16 index, u8 status)
1875{
1876 struct hci_dev *hdev;
1877 struct hci_cp_le_set_scan_enable le_cp = {1, 0};
Brian Gix568dde92012-01-11 16:18:04 -08001878 struct mgmt_mode cp = {0};
Brian Gixa68668b2011-08-11 15:49:36 -07001879 int err = -1;
1880
1881 BT_DBG("");
1882
1883 hdev = hci_dev_get(index);
Brian Gix64bd5302011-09-08 11:35:48 -07001884
Brian Gixa68668b2011-08-11 15:49:36 -07001885 if (!hdev || !lmp_le_capable(hdev)) {
Brian Gixa68668b2011-08-11 15:49:36 -07001886
1887 mgmt_pending_foreach(MGMT_OP_STOP_DISCOVERY, index,
1888 discovery_terminated, NULL);
1889
1890 mgmt_event(MGMT_EV_DISCOVERING, index, &cp, sizeof(cp), NULL);
Brian Gixa68668b2011-08-11 15:49:36 -07001891
Brian Gix64bd5302011-09-08 11:35:48 -07001892 if (hdev)
1893 goto done;
1894 else
1895 return;
1896 }
Brian Gixa68668b2011-08-11 15:49:36 -07001897
Brian Gix568dde92012-01-11 16:18:04 -08001898 if (hdev->disco_state != SCAN_IDLE) {
Brian Gixa68668b2011-08-11 15:49:36 -07001899 err = hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE,
1900 sizeof(le_cp), &le_cp);
Brian Gix568dde92012-01-11 16:18:04 -08001901 if (err >= 0) {
1902 mod_timer(&hdev->disco_le_timer, jiffies +
1903 msecs_to_jiffies(hdev->disco_int_phase * 1000));
1904 hdev->disco_state = SCAN_LE;
Brian Gixa68668b2011-08-11 15:49:36 -07001905 } else
Brian Gix568dde92012-01-11 16:18:04 -08001906 hdev->disco_state = SCAN_IDLE;
Brian Gixa68668b2011-08-11 15:49:36 -07001907 }
1908
Brian Gix568dde92012-01-11 16:18:04 -08001909 if (hdev->disco_state == SCAN_IDLE)
1910 mgmt_event(MGMT_EV_DISCOVERING, index, &cp, sizeof(cp), NULL);
1911
Brian Gixa68668b2011-08-11 15:49:36 -07001912 if (err < 0)
1913 mgmt_pending_foreach(MGMT_OP_STOP_DISCOVERY, index,
1914 discovery_terminated, NULL);
1915
Brian Gix64bd5302011-09-08 11:35:48 -07001916done:
Brian Gixa68668b2011-08-11 15:49:36 -07001917 hci_dev_put(hdev);
1918}
1919
Brian Gix568dde92012-01-11 16:18:04 -08001920void mgmt_disco_timeout(unsigned long data)
Brian Gixa68668b2011-08-11 15:49:36 -07001921{
Brian Gix568dde92012-01-11 16:18:04 -08001922 struct hci_dev *hdev = (void *) data;
Brian Gixa68668b2011-08-11 15:49:36 -07001923 struct pending_cmd *cmd;
Brian Gix568dde92012-01-11 16:18:04 -08001924 struct mgmt_mode cp = {0};
Brian Gixa68668b2011-08-11 15:49:36 -07001925
Brian Gix568dde92012-01-11 16:18:04 -08001926 BT_DBG("hci%d", hdev->id);
Brian Gixa68668b2011-08-11 15:49:36 -07001927
Brian Gix568dde92012-01-11 16:18:04 -08001928 hdev = hci_dev_get(hdev->id);
Brian Gixa68668b2011-08-11 15:49:36 -07001929
Brian Gix568dde92012-01-11 16:18:04 -08001930 if (!hdev)
1931 return;
Brian Gixa68668b2011-08-11 15:49:36 -07001932
Brian Gix568dde92012-01-11 16:18:04 -08001933 hci_dev_lock_bh(hdev);
1934 del_timer(&hdev->disco_le_timer);
Brian Gixa68668b2011-08-11 15:49:36 -07001935
Brian Gix568dde92012-01-11 16:18:04 -08001936 if (hdev->disco_state != SCAN_IDLE) {
1937 struct hci_cp_le_set_scan_enable le_cp = {0, 0};
Brian Gixa68668b2011-08-11 15:49:36 -07001938
Brian Gix568dde92012-01-11 16:18:04 -08001939 if (hdev->disco_state == SCAN_LE)
Brian Gixa68668b2011-08-11 15:49:36 -07001940 hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE,
1941 sizeof(le_cp), &le_cp);
Brian Gix568dde92012-01-11 16:18:04 -08001942 else
1943 hci_send_cmd(hdev, HCI_OP_INQUIRY_CANCEL, 0, NULL);
Brian Gixa68668b2011-08-11 15:49:36 -07001944
Brian Gix568dde92012-01-11 16:18:04 -08001945 hdev->disco_state = SCAN_IDLE;
Brian Gixa68668b2011-08-11 15:49:36 -07001946 }
Brian Gix568dde92012-01-11 16:18:04 -08001947
1948 mgmt_event(MGMT_EV_DISCOVERING, hdev->id, &cp, sizeof(cp), NULL);
1949
1950 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev->id);
1951 if (cmd)
1952 mgmt_pending_remove(cmd);
1953
1954 hci_dev_unlock_bh(hdev);
1955 hci_dev_put(hdev);
1956}
1957
1958void mgmt_disco_le_timeout(unsigned long data)
1959{
1960 struct hci_dev *hdev = (void *)data;
1961 struct hci_cp_le_set_scan_enable le_cp = {0, 0};
1962
1963 BT_DBG("hci%d", hdev->id);
1964
1965 hdev = hci_dev_get(hdev->id);
1966
1967 if (!hdev)
1968 return;
1969
1970 hci_dev_lock_bh(hdev);
1971
1972 if (hdev->disco_state == SCAN_LE)
1973 hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE,
1974 sizeof(le_cp), &le_cp);
1975
1976 /* re-start BR scan */
1977 if (hdev->disco_state != SCAN_IDLE) {
1978 struct hci_cp_inquiry cp = {{0x33, 0x8b, 0x9e}, 4, 0};
1979 hdev->disco_int_phase *= 2;
1980 hdev->disco_int_count = 0;
1981 cp.num_rsp = (u8) hdev->disco_int_phase;
1982 hci_send_cmd(hdev, HCI_OP_INQUIRY, sizeof(cp), &cp);
1983 hdev->disco_state = SCAN_BR;
1984 }
1985
1986 hci_dev_unlock_bh(hdev);
1987 hci_dev_put(hdev);
Brian Gixa68668b2011-08-11 15:49:36 -07001988}
1989
1990static int start_discovery(struct sock *sk, u16 index)
1991{
1992 struct hci_cp_inquiry cp = {{0x33, 0x8b, 0x9e}, 8, 0};
1993 struct hci_dev *hdev;
1994 struct pending_cmd *cmd;
1995 int err;
1996
1997 BT_DBG("");
1998
1999 hdev = hci_dev_get(index);
2000 if (!hdev)
2001 return cmd_status(sk, index, MGMT_OP_START_DISCOVERY, ENODEV);
2002
Subramanian Srinivasana727a492011-11-30 13:06:07 -08002003 hci_dev_lock_bh(hdev);
Brian Gixa68668b2011-08-11 15:49:36 -07002004
Brian Gix568dde92012-01-11 16:18:04 -08002005 if (hdev->disco_state && timer_pending(&hdev->disco_timer)) {
2006 err = -EBUSY;
2007 goto failed;
2008 }
2009
Brian Gixa68668b2011-08-11 15:49:36 -07002010 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, index, NULL, 0);
2011 if (!cmd) {
2012 err = -ENOMEM;
2013 goto failed;
2014 }
2015
2016 /* If LE Capable, we will alternate between BR/EDR and LE */
2017 if (lmp_le_capable(hdev)) {
2018 struct hci_cp_le_set_scan_parameters le_cp;
2019
2020 /* Shorten BR scan params */
2021 cp.num_rsp = 1;
2022 cp.length /= 2;
2023
2024 /* Setup LE scan params */
2025 memset(&le_cp, 0, sizeof(le_cp));
2026 le_cp.type = 0x01; /* Active scanning */
2027 /* The recommended value for scan interval and window is
2028 * 11.25 msec. It is calculated by: time = n * 0.625 msec */
2029 le_cp.interval = cpu_to_le16(0x0012);
2030 le_cp.window = cpu_to_le16(0x0012);
2031 le_cp.own_bdaddr_type = 0; /* Public address */
2032 le_cp.filter = 0; /* Accept all adv packets */
2033
2034 hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_PARAMETERS,
2035 sizeof(le_cp), &le_cp);
2036 }
2037
2038 err = hci_send_cmd(hdev, HCI_OP_INQUIRY, sizeof(cp), &cp);
2039
2040 if (err < 0)
2041 mgmt_pending_remove(cmd);
2042 else if (lmp_le_capable(hdev)) {
Brian Gix568dde92012-01-11 16:18:04 -08002043 hdev->disco_int_phase = 1;
2044 hdev->disco_int_count = 0;
2045 hdev->disco_state = SCAN_BR;
2046 mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, index, NULL, 0);
2047 del_timer(&hdev->disco_le_timer);
2048 del_timer(&hdev->disco_timer);
2049 mod_timer(&hdev->disco_timer,
2050 jiffies + msecs_to_jiffies(20000));
Brian Gixa68668b2011-08-11 15:49:36 -07002051 }
2052
2053failed:
Subramanian Srinivasana727a492011-11-30 13:06:07 -08002054 hci_dev_unlock_bh(hdev);
Brian Gixa68668b2011-08-11 15:49:36 -07002055 hci_dev_put(hdev);
2056
Brian Gix568dde92012-01-11 16:18:04 -08002057 if (err < 0)
2058 return cmd_status(sk, index, MGMT_OP_START_DISCOVERY, -err);
2059
Brian Gixa68668b2011-08-11 15:49:36 -07002060 return err;
2061}
2062
2063static int stop_discovery(struct sock *sk, u16 index)
2064{
2065 struct hci_cp_le_set_scan_enable le_cp = {0, 0};
2066 struct mgmt_mode mode_cp = {0};
Brian Gixa68668b2011-08-11 15:49:36 -07002067 struct hci_dev *hdev;
2068 struct pending_cmd *cmd = NULL;
2069 int err = -EPERM;
Brian Gix568dde92012-01-11 16:18:04 -08002070 u8 state;
Brian Gixa68668b2011-08-11 15:49:36 -07002071
2072 BT_DBG("");
2073
2074 hdev = hci_dev_get(index);
2075 if (!hdev)
2076 return cmd_status(sk, index, MGMT_OP_STOP_DISCOVERY, ENODEV);
2077
Subramanian Srinivasana727a492011-11-30 13:06:07 -08002078 hci_dev_lock_bh(hdev);
Brian Gixa68668b2011-08-11 15:49:36 -07002079
Brian Gix568dde92012-01-11 16:18:04 -08002080 state = hdev->disco_state;
2081 hdev->disco_state = SCAN_IDLE;
2082 del_timer(&hdev->disco_le_timer);
2083 del_timer(&hdev->disco_timer);
Brian Gixa68668b2011-08-11 15:49:36 -07002084
Brian Gix568dde92012-01-11 16:18:04 -08002085 if (state == SCAN_LE) {
Brian Gixa68668b2011-08-11 15:49:36 -07002086 err = hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE,
2087 sizeof(le_cp), &le_cp);
Brian Gix568dde92012-01-11 16:18:04 -08002088 if (err >= 0) {
2089 mgmt_pending_foreach(MGMT_OP_STOP_DISCOVERY, index,
2090 discovery_terminated, NULL);
Brian Gixa68668b2011-08-11 15:49:36 -07002091
Brian Gix568dde92012-01-11 16:18:04 -08002092 err = cmd_complete(sk, index, MGMT_OP_STOP_DISCOVERY,
2093 NULL, 0);
2094 }
Brian Gixa68668b2011-08-11 15:49:36 -07002095 }
2096
Brian Gix568dde92012-01-11 16:18:04 -08002097 if (err < 0)
2098 err = hci_send_cmd(hdev, HCI_OP_INQUIRY_CANCEL, 0, NULL);
Brian Gixa68668b2011-08-11 15:49:36 -07002099
Brian Gix568dde92012-01-11 16:18:04 -08002100 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, index);
Brian Gixa68668b2011-08-11 15:49:36 -07002101 if (err < 0 && cmd)
2102 mgmt_pending_remove(cmd);
2103
2104 mgmt_event(MGMT_EV_DISCOVERING, index, &mode_cp, sizeof(mode_cp), NULL);
2105
Subramanian Srinivasana727a492011-11-30 13:06:07 -08002106 hci_dev_unlock_bh(hdev);
Brian Gixa68668b2011-08-11 15:49:36 -07002107 hci_dev_put(hdev);
2108
2109 if (err < 0)
2110 return cmd_status(sk, index, MGMT_OP_STOP_DISCOVERY, -err);
2111 else
2112 return err;
2113}
2114
Szymon Jancc35938b2011-03-22 13:12:21 +01002115static int read_local_oob_data(struct sock *sk, u16 index)
2116{
2117 struct hci_dev *hdev;
2118 struct pending_cmd *cmd;
2119 int err;
2120
2121 BT_DBG("hci%u", index);
2122
2123 hdev = hci_dev_get(index);
2124 if (!hdev)
2125 return cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
2126 ENODEV);
2127
Subramanian Srinivasana727a492011-11-30 13:06:07 -08002128 hci_dev_lock_bh(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01002129
2130 if (!test_bit(HCI_UP, &hdev->flags)) {
2131 err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
2132 ENETDOWN);
2133 goto unlock;
2134 }
2135
2136 if (!(hdev->features[6] & LMP_SIMPLE_PAIR)) {
2137 err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
2138 EOPNOTSUPP);
2139 goto unlock;
2140 }
2141
2142 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, index)) {
2143 err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, EBUSY);
2144 goto unlock;
2145 }
2146
2147 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, index, NULL, 0);
2148 if (!cmd) {
2149 err = -ENOMEM;
2150 goto unlock;
2151 }
2152
2153 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
2154 if (err < 0)
2155 mgmt_pending_remove(cmd);
2156
2157unlock:
Subramanian Srinivasana727a492011-11-30 13:06:07 -08002158 hci_dev_unlock_bh(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01002159 hci_dev_put(hdev);
2160
2161 return err;
2162}
2163
Szymon Janc2763eda2011-03-22 13:12:22 +01002164static int add_remote_oob_data(struct sock *sk, u16 index, unsigned char *data,
2165 u16 len)
2166{
2167 struct hci_dev *hdev;
2168 struct mgmt_cp_add_remote_oob_data *cp = (void *) data;
2169 int err;
2170
2171 BT_DBG("hci%u ", index);
2172
2173 if (len != sizeof(*cp))
2174 return cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA,
2175 EINVAL);
2176
2177 hdev = hci_dev_get(index);
2178 if (!hdev)
2179 return cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA,
2180 ENODEV);
2181
Subramanian Srinivasana727a492011-11-30 13:06:07 -08002182 hci_dev_lock_bh(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01002183
2184 err = hci_add_remote_oob_data(hdev, &cp->bdaddr, cp->hash,
2185 cp->randomizer);
2186 if (err < 0)
2187 err = cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, -err);
2188 else
2189 err = cmd_complete(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, NULL,
2190 0);
2191
Subramanian Srinivasana727a492011-11-30 13:06:07 -08002192 hci_dev_unlock_bh(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01002193 hci_dev_put(hdev);
2194
2195 return err;
2196}
2197
2198static int remove_remote_oob_data(struct sock *sk, u16 index,
2199 unsigned char *data, u16 len)
2200{
2201 struct hci_dev *hdev;
2202 struct mgmt_cp_remove_remote_oob_data *cp = (void *) data;
2203 int err;
2204
2205 BT_DBG("hci%u ", index);
2206
2207 if (len != sizeof(*cp))
2208 return cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
2209 EINVAL);
2210
2211 hdev = hci_dev_get(index);
2212 if (!hdev)
2213 return cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
2214 ENODEV);
2215
Subramanian Srinivasana727a492011-11-30 13:06:07 -08002216 hci_dev_lock_bh(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01002217
2218 err = hci_remove_remote_oob_data(hdev, &cp->bdaddr);
2219 if (err < 0)
2220 err = cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
2221 -err);
2222 else
2223 err = cmd_complete(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
2224 NULL, 0);
2225
Subramanian Srinivasana727a492011-11-30 13:06:07 -08002226 hci_dev_unlock_bh(hdev);
Antti Julku58d19802011-06-15 12:01:15 +03002227 hci_dev_put(hdev);
2228
2229 return err;
2230}
2231
Johan Hedberg03811012010-12-08 00:21:06 +02002232int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
2233{
2234 unsigned char *buf;
2235 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01002236 u16 opcode, index, len;
Johan Hedberg03811012010-12-08 00:21:06 +02002237 int err;
2238
2239 BT_DBG("got %zu bytes", msglen);
2240
2241 if (msglen < sizeof(*hdr))
2242 return -EINVAL;
2243
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03002244 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02002245 if (!buf)
2246 return -ENOMEM;
2247
2248 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
2249 err = -EFAULT;
2250 goto done;
2251 }
2252
2253 hdr = (struct mgmt_hdr *) buf;
2254 opcode = get_unaligned_le16(&hdr->opcode);
Szymon Janc4e51eae2011-02-25 19:05:48 +01002255 index = get_unaligned_le16(&hdr->index);
Johan Hedberg03811012010-12-08 00:21:06 +02002256 len = get_unaligned_le16(&hdr->len);
2257
2258 if (len != msglen - sizeof(*hdr)) {
2259 err = -EINVAL;
2260 goto done;
2261 }
2262
Brian Gixa68668b2011-08-11 15:49:36 -07002263 BT_DBG("got opcode %x", opcode);
Johan Hedberg03811012010-12-08 00:21:06 +02002264 switch (opcode) {
Johan Hedberg02d98122010-12-13 21:07:04 +02002265 case MGMT_OP_READ_VERSION:
2266 err = read_version(sk);
2267 break;
Johan Hedbergfaba42e2010-12-13 21:07:05 +02002268 case MGMT_OP_READ_INDEX_LIST:
2269 err = read_index_list(sk);
2270 break;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02002271 case MGMT_OP_READ_INFO:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002272 err = read_controller_info(sk, index);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02002273 break;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002274 case MGMT_OP_SET_POWERED:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002275 err = set_powered(sk, index, buf + sizeof(*hdr), len);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002276 break;
Johan Hedberg73f22f62010-12-29 16:00:25 +02002277 case MGMT_OP_SET_DISCOVERABLE:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002278 err = set_discoverable(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg73f22f62010-12-29 16:00:25 +02002279 break;
Brian Gix8a7f1642011-10-17 17:39:46 -07002280 case MGMT_OP_SET_LIMIT_DISCOVERABLE:
2281 err = set_limited_discoverable(sk, index, buf + sizeof(*hdr),
2282 len);
2283 break;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02002284 case MGMT_OP_SET_CONNECTABLE:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002285 err = set_connectable(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02002286 break;
Johan Hedbergc542a062011-01-26 13:11:03 +02002287 case MGMT_OP_SET_PAIRABLE:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002288 err = set_pairable(sk, index, buf + sizeof(*hdr), len);
Johan Hedbergc542a062011-01-26 13:11:03 +02002289 break;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002290 case MGMT_OP_ADD_UUID:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002291 err = add_uuid(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002292 break;
2293 case MGMT_OP_REMOVE_UUID:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002294 err = remove_uuid(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002295 break;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002296 case MGMT_OP_SET_DEV_CLASS:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002297 err = set_dev_class(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002298 break;
2299 case MGMT_OP_SET_SERVICE_CACHE:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002300 err = set_service_cache(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002301 break;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002302 case MGMT_OP_LOAD_KEYS:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002303 err = load_keys(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002304 break;
2305 case MGMT_OP_REMOVE_KEY:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002306 err = remove_key(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002307 break;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002308 case MGMT_OP_DISCONNECT:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002309 err = disconnect(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002310 break;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002311 case MGMT_OP_GET_CONNECTIONS:
Szymon Janc8ce62842011-03-01 16:55:32 +01002312 err = get_connections(sk, index);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002313 break;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002314 case MGMT_OP_PIN_CODE_REPLY:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002315 err = pin_code_reply(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002316 break;
2317 case MGMT_OP_PIN_CODE_NEG_REPLY:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002318 err = pin_code_neg_reply(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002319 break;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002320 case MGMT_OP_SET_IO_CAPABILITY:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002321 err = set_io_capability(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002322 break;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002323 case MGMT_OP_PAIR_DEVICE:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002324 err = pair_device(sk, index, buf + sizeof(*hdr), len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002325 break;
Johan Hedberga5c29682011-02-19 12:05:57 -03002326 case MGMT_OP_USER_CONFIRM_REPLY:
Brian Gixa68668b2011-08-11 15:49:36 -07002327 case MGMT_OP_USER_PASSKEY_REPLY:
Johan Hedberga5c29682011-02-19 12:05:57 -03002328 case MGMT_OP_USER_CONFIRM_NEG_REPLY:
Brian Gixa68668b2011-08-11 15:49:36 -07002329 err = user_confirm_reply(sk, index, buf + sizeof(*hdr),
2330 len, opcode);
Johan Hedberga5c29682011-02-19 12:05:57 -03002331 break;
Johan Hedbergb312b1612011-03-16 14:29:37 +02002332 case MGMT_OP_SET_LOCAL_NAME:
2333 err = set_local_name(sk, index, buf + sizeof(*hdr), len);
2334 break;
Brian Gixa68668b2011-08-11 15:49:36 -07002335 case MGMT_OP_START_DISCOVERY:
2336 err = start_discovery(sk, index);
2337 break;
2338 case MGMT_OP_STOP_DISCOVERY:
2339 err = stop_discovery(sk, index);
2340 break;
2341 case MGMT_OP_RESOLVE_NAME:
2342 err = resolve_name(sk, index, buf + sizeof(*hdr), len);
2343 break;
Brian Gix7f7e16c2011-11-01 16:27:25 -07002344 case MGMT_OP_SET_CONNECTION_PARAMS:
2345 err = set_connection_params(sk, index, buf + sizeof(*hdr), len);
2346 break;
Szymon Jancc35938b2011-03-22 13:12:21 +01002347 case MGMT_OP_READ_LOCAL_OOB_DATA:
2348 err = read_local_oob_data(sk, index);
2349 break;
Szymon Janc2763eda2011-03-22 13:12:22 +01002350 case MGMT_OP_ADD_REMOTE_OOB_DATA:
2351 err = add_remote_oob_data(sk, index, buf + sizeof(*hdr), len);
2352 break;
2353 case MGMT_OP_REMOVE_REMOTE_OOB_DATA:
2354 err = remove_remote_oob_data(sk, index, buf + sizeof(*hdr),
2355 len);
2356 break;
Prabhakaran Mc46230fa2011-11-30 18:11:21 +05302357 case MGMT_OP_ENCRYPT_LINK:
2358 err = encrypt_link(sk, index, buf + sizeof(*hdr), len);
2359 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002360
Johan Hedberg03811012010-12-08 00:21:06 +02002361 default:
2362 BT_DBG("Unknown op %u", opcode);
Szymon Janc4e51eae2011-02-25 19:05:48 +01002363 err = cmd_status(sk, index, opcode, 0x01);
Johan Hedberg03811012010-12-08 00:21:06 +02002364 break;
2365 }
2366
Johan Hedberge41d8b42010-12-13 21:07:03 +02002367 if (err < 0)
2368 goto done;
2369
Johan Hedberg03811012010-12-08 00:21:06 +02002370 err = msglen;
2371
2372done:
2373 kfree(buf);
2374 return err;
2375}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02002376
Johan Hedbergc71e97b2010-12-13 21:07:07 +02002377int mgmt_index_added(u16 index)
2378{
Brian Gixa68668b2011-08-11 15:49:36 -07002379 BT_DBG("%d", index);
Szymon Janc4e51eae2011-02-25 19:05:48 +01002380 return mgmt_event(MGMT_EV_INDEX_ADDED, index, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02002381}
2382
2383int mgmt_index_removed(u16 index)
2384{
Brian Gixa68668b2011-08-11 15:49:36 -07002385 BT_DBG("%d", index);
Szymon Janc4e51eae2011-02-25 19:05:48 +01002386 return mgmt_event(MGMT_EV_INDEX_REMOVED, index, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002387}
2388
Johan Hedberg73f22f62010-12-29 16:00:25 +02002389struct cmd_lookup {
Johan Hedberg72a734e2010-12-30 00:38:22 +02002390 u8 val;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002391 struct sock *sk;
2392};
2393
Johan Hedberg72a734e2010-12-30 00:38:22 +02002394static void mode_rsp(struct pending_cmd *cmd, void *data)
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002395{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01002396 struct mgmt_mode *cp = cmd->param;
Johan Hedberg73f22f62010-12-29 16:00:25 +02002397 struct cmd_lookup *match = data;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002398
Johan Hedberg72a734e2010-12-30 00:38:22 +02002399 if (cp->val != match->val)
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002400 return;
2401
Johan Hedberg053f0212011-01-26 13:07:10 +02002402 send_mode_rsp(cmd->sk, cmd->opcode, cmd->index, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002403
2404 list_del(&cmd->list);
2405
2406 if (match->sk == NULL) {
2407 match->sk = cmd->sk;
2408 sock_hold(match->sk);
2409 }
2410
2411 mgmt_pending_free(cmd);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02002412}
Johan Hedberg5add6af2010-12-16 10:00:37 +02002413
2414int mgmt_powered(u16 index, u8 powered)
2415{
Johan Hedberg72a734e2010-12-30 00:38:22 +02002416 struct mgmt_mode ev;
Johan Hedberg73f22f62010-12-29 16:00:25 +02002417 struct cmd_lookup match = { powered, NULL };
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002418 int ret;
Johan Hedberg5add6af2010-12-16 10:00:37 +02002419
Brian Gixa68668b2011-08-11 15:49:36 -07002420 BT_DBG("hci%u %d", index, powered);
2421
Johan Hedberg72a734e2010-12-30 00:38:22 +02002422 mgmt_pending_foreach(MGMT_OP_SET_POWERED, index, mode_rsp, &match);
Johan Hedberg5add6af2010-12-16 10:00:37 +02002423
Johan Hedberg72a734e2010-12-30 00:38:22 +02002424 ev.val = powered;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002425
Szymon Janc4e51eae2011-02-25 19:05:48 +01002426 ret = mgmt_event(MGMT_EV_POWERED, index, &ev, sizeof(ev), match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002427
2428 if (match.sk)
2429 sock_put(match.sk);
2430
2431 return ret;
Johan Hedberg5add6af2010-12-16 10:00:37 +02002432}
Johan Hedberg73f22f62010-12-29 16:00:25 +02002433
Johan Hedberg73f22f62010-12-29 16:00:25 +02002434int mgmt_discoverable(u16 index, u8 discoverable)
2435{
Johan Hedberg72a734e2010-12-30 00:38:22 +02002436 struct mgmt_mode ev;
Johan Hedberg73f22f62010-12-29 16:00:25 +02002437 struct cmd_lookup match = { discoverable, NULL };
2438 int ret;
2439
Szymon Jancb8534e02011-03-01 16:55:34 +01002440 mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, index, mode_rsp, &match);
Johan Hedberg72a734e2010-12-30 00:38:22 +02002441
Johan Hedberg72a734e2010-12-30 00:38:22 +02002442 ev.val = discoverable;
Johan Hedberg73f22f62010-12-29 16:00:25 +02002443
Szymon Janc4e51eae2011-02-25 19:05:48 +01002444 ret = mgmt_event(MGMT_EV_DISCOVERABLE, index, &ev, sizeof(ev),
2445 match.sk);
Johan Hedberg73f22f62010-12-29 16:00:25 +02002446
2447 if (match.sk)
2448 sock_put(match.sk);
2449
2450 return ret;
2451}
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02002452
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02002453int mgmt_connectable(u16 index, u8 connectable)
2454{
Johan Hedberg72a734e2010-12-30 00:38:22 +02002455 struct mgmt_mode ev;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02002456 struct cmd_lookup match = { connectable, NULL };
2457 int ret;
2458
Johan Hedberg72a734e2010-12-30 00:38:22 +02002459 mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, index, mode_rsp, &match);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02002460
Johan Hedberg72a734e2010-12-30 00:38:22 +02002461 ev.val = connectable;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02002462
Szymon Janc4e51eae2011-02-25 19:05:48 +01002463 ret = mgmt_event(MGMT_EV_CONNECTABLE, index, &ev, sizeof(ev), match.sk);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02002464
2465 if (match.sk)
2466 sock_put(match.sk);
2467
2468 return ret;
2469}
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002470
Brian Gixa68668b2011-08-11 15:49:36 -07002471int mgmt_new_key(u16 index, struct link_key *key, u8 bonded)
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002472{
Vinicius Costa Gomesc00ddbf2011-07-08 18:31:44 -03002473 struct mgmt_ev_new_key *ev;
2474 int err, total;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002475
Vinicius Costa Gomesc00ddbf2011-07-08 18:31:44 -03002476 total = sizeof(struct mgmt_ev_new_key) + key->dlen;
2477 ev = kzalloc(total, GFP_ATOMIC);
2478 if (!ev)
2479 return -ENOMEM;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002480
Vinicius Costa Gomesc00ddbf2011-07-08 18:31:44 -03002481 bacpy(&ev->key.bdaddr, &key->bdaddr);
Brian Gixcf956772011-10-20 15:18:51 -07002482 ev->key.addr_type = key->addr_type;
2483 ev->key.key_type = key->key_type;
Vinicius Costa Gomesc00ddbf2011-07-08 18:31:44 -03002484 memcpy(ev->key.val, key->val, 16);
2485 ev->key.pin_len = key->pin_len;
Brian Gixa68668b2011-08-11 15:49:36 -07002486 ev->key.auth = key->auth;
2487 ev->store_hint = bonded;
Vinicius Costa Gomesc00ddbf2011-07-08 18:31:44 -03002488 ev->key.dlen = key->dlen;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002489
Vinicius Costa Gomesc00ddbf2011-07-08 18:31:44 -03002490 memcpy(ev->key.data, key->data, key->dlen);
2491
2492 err = mgmt_event(MGMT_EV_NEW_KEY, index, ev, total, NULL);
2493
2494 kfree(ev);
2495
2496 return err;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002497}
Johan Hedbergf7520542011-01-20 12:34:39 +02002498
Brian Gix2e2f50d2011-09-13 12:36:04 -07002499int mgmt_connected(u16 index, bdaddr_t *bdaddr, u8 le)
Johan Hedbergf7520542011-01-20 12:34:39 +02002500{
2501 struct mgmt_ev_connected ev;
2502
Johan Hedbergf7520542011-01-20 12:34:39 +02002503 bacpy(&ev.bdaddr, bdaddr);
Brian Gix2e2f50d2011-09-13 12:36:04 -07002504 ev.le = le;
Johan Hedbergf7520542011-01-20 12:34:39 +02002505
Szymon Janc4e51eae2011-02-25 19:05:48 +01002506 return mgmt_event(MGMT_EV_CONNECTED, index, &ev, sizeof(ev), NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02002507}
2508
Johan Hedberg8962ee72011-01-20 12:40:27 +02002509static void disconnect_rsp(struct pending_cmd *cmd, void *data)
2510{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01002511 struct mgmt_cp_disconnect *cp = cmd->param;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002512 struct sock **sk = data;
Johan Hedberga38528f2011-01-22 06:46:43 +02002513 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002514
Johan Hedberga38528f2011-01-22 06:46:43 +02002515 bacpy(&rp.bdaddr, &cp->bdaddr);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002516
Szymon Janc4e51eae2011-02-25 19:05:48 +01002517 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002518
2519 *sk = cmd->sk;
2520 sock_hold(*sk);
2521
Johan Hedberga664b5b2011-02-19 12:06:02 -03002522 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002523}
2524
Johan Hedbergf7520542011-01-20 12:34:39 +02002525int mgmt_disconnected(u16 index, bdaddr_t *bdaddr)
2526{
2527 struct mgmt_ev_disconnected ev;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002528 struct sock *sk = NULL;
2529 int err;
2530
2531 mgmt_pending_foreach(MGMT_OP_DISCONNECT, index, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02002532
Johan Hedbergf7520542011-01-20 12:34:39 +02002533 bacpy(&ev.bdaddr, bdaddr);
2534
Szymon Janc4e51eae2011-02-25 19:05:48 +01002535 err = mgmt_event(MGMT_EV_DISCONNECTED, index, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002536
2537 if (sk)
2538 sock_put(sk);
2539
2540 return err;
2541}
2542
2543int mgmt_disconnect_failed(u16 index)
2544{
2545 struct pending_cmd *cmd;
2546 int err;
2547
2548 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, index);
2549 if (!cmd)
2550 return -ENOENT;
2551
Szymon Janc4e51eae2011-02-25 19:05:48 +01002552 err = cmd_status(cmd->sk, index, MGMT_OP_DISCONNECT, EIO);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002553
Johan Hedberga664b5b2011-02-19 12:06:02 -03002554 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002555
2556 return err;
Johan Hedbergf7520542011-01-20 12:34:39 +02002557}
Johan Hedberg17d5c042011-01-22 06:09:08 +02002558
2559int mgmt_connect_failed(u16 index, bdaddr_t *bdaddr, u8 status)
2560{
2561 struct mgmt_ev_connect_failed ev;
2562
Johan Hedberg17d5c042011-01-22 06:09:08 +02002563 bacpy(&ev.bdaddr, bdaddr);
2564 ev.status = status;
2565
Szymon Janc4e51eae2011-02-25 19:05:48 +01002566 return mgmt_event(MGMT_EV_CONNECT_FAILED, index, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02002567}
Johan Hedberg980e1a52011-01-22 06:10:07 +02002568
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002569int mgmt_pin_code_request(u16 index, bdaddr_t *bdaddr)
Johan Hedberg980e1a52011-01-22 06:10:07 +02002570{
2571 struct mgmt_ev_pin_code_request ev;
2572
Brian Gixa68668b2011-08-11 15:49:36 -07002573 BT_DBG("hci%u", index);
2574
Johan Hedberg980e1a52011-01-22 06:10:07 +02002575 bacpy(&ev.bdaddr, bdaddr);
Brian Gixa68668b2011-08-11 15:49:36 -07002576 ev.secure = 0;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002577
Szymon Janc4e51eae2011-02-25 19:05:48 +01002578 return mgmt_event(MGMT_EV_PIN_CODE_REQUEST, index, &ev, sizeof(ev),
2579 NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002580}
2581
2582int mgmt_pin_code_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status)
2583{
2584 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03002585 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002586 int err;
2587
2588 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, index);
2589 if (!cmd)
2590 return -ENOENT;
2591
Johan Hedbergac56fb12011-02-19 12:05:59 -03002592 bacpy(&rp.bdaddr, bdaddr);
2593 rp.status = status;
2594
Szymon Janc4e51eae2011-02-25 19:05:48 +01002595 err = cmd_complete(cmd->sk, index, MGMT_OP_PIN_CODE_REPLY, &rp,
2596 sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02002597
Johan Hedberga664b5b2011-02-19 12:06:02 -03002598 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002599
2600 return err;
2601}
2602
2603int mgmt_pin_code_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status)
2604{
2605 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03002606 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002607 int err;
2608
2609 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, index);
2610 if (!cmd)
2611 return -ENOENT;
2612
Johan Hedbergac56fb12011-02-19 12:05:59 -03002613 bacpy(&rp.bdaddr, bdaddr);
2614 rp.status = status;
2615
Szymon Janc4e51eae2011-02-25 19:05:48 +01002616 err = cmd_complete(cmd->sk, index, MGMT_OP_PIN_CODE_NEG_REPLY, &rp,
2617 sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02002618
Johan Hedberga664b5b2011-02-19 12:06:02 -03002619 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002620
2621 return err;
2622}
Johan Hedberga5c29682011-02-19 12:05:57 -03002623
Brian Gixa68668b2011-08-11 15:49:36 -07002624int mgmt_user_confirm_request(u16 index, u8 event,
2625 bdaddr_t *bdaddr, __le32 value)
Johan Hedberga5c29682011-02-19 12:05:57 -03002626{
2627 struct mgmt_ev_user_confirm_request ev;
Brian Gixa68668b2011-08-11 15:49:36 -07002628 struct hci_conn *conn = NULL;
2629 struct hci_dev *hdev;
2630 u8 loc_cap, rem_cap, loc_mitm, rem_mitm;
2631
2632 BT_DBG("hci%u", index);
2633
2634 hdev = hci_dev_get(index);
2635
Brian Gix64bd5302011-09-08 11:35:48 -07002636 if (!hdev)
2637 return -ENODEV;
2638
Brian Gix64bd5302011-09-08 11:35:48 -07002639 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, bdaddr);
Brian Gixa68668b2011-08-11 15:49:36 -07002640
2641 ev.auto_confirm = 0;
2642
2643 if (!conn || event != HCI_EV_USER_CONFIRM_REQUEST)
2644 goto no_auto_confirm;
2645
2646 loc_cap = (conn->io_capability == 0x04) ? 0x01 : conn->io_capability;
2647 rem_cap = conn->remote_cap;
2648 loc_mitm = conn->auth_type & 0x01;
2649 rem_mitm = conn->remote_auth & 0x01;
2650
Brian Gixdbf59292011-11-11 15:45:17 -08002651 if ((conn->auth_type & HCI_AT_DEDICATED_BONDING) &&
2652 conn->auth_initiator && rem_cap == 0x03)
2653 ev.auto_confirm = 1;
2654 else if (loc_cap == 0x01 && (rem_cap == 0x00 || rem_cap == 0x03))
Brian Gixa68668b2011-08-11 15:49:36 -07002655 goto no_auto_confirm;
2656
2657
2658 if ((!loc_mitm || rem_cap == 0x03) && (!rem_mitm || loc_cap == 0x03))
2659 ev.auto_confirm = 1;
2660
2661no_auto_confirm:
2662 bacpy(&ev.bdaddr, bdaddr);
2663 ev.event = event;
2664 put_unaligned_le32(value, &ev.value);
2665
Brian Gix64bd5302011-09-08 11:35:48 -07002666 hci_dev_put(hdev);
2667
Brian Gixa68668b2011-08-11 15:49:36 -07002668 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, index, &ev, sizeof(ev),
2669 NULL);
2670}
2671
2672int mgmt_user_passkey_request(u16 index, bdaddr_t *bdaddr)
2673{
2674 struct mgmt_ev_user_passkey_request ev;
Johan Hedberga5c29682011-02-19 12:05:57 -03002675
2676 BT_DBG("hci%u", index);
2677
Johan Hedberga5c29682011-02-19 12:05:57 -03002678 bacpy(&ev.bdaddr, bdaddr);
Johan Hedberga5c29682011-02-19 12:05:57 -03002679
Brian Gixa68668b2011-08-11 15:49:36 -07002680 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, index, &ev, sizeof(ev),
Szymon Janc4e51eae2011-02-25 19:05:48 +01002681 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03002682}
2683
2684static int confirm_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status,
2685 u8 opcode)
2686{
2687 struct pending_cmd *cmd;
2688 struct mgmt_rp_user_confirm_reply rp;
2689 int err;
2690
2691 cmd = mgmt_pending_find(opcode, index);
2692 if (!cmd)
2693 return -ENOENT;
2694
Johan Hedberga5c29682011-02-19 12:05:57 -03002695 bacpy(&rp.bdaddr, bdaddr);
2696 rp.status = status;
Szymon Janc4e51eae2011-02-25 19:05:48 +01002697 err = cmd_complete(cmd->sk, index, opcode, &rp, sizeof(rp));
Johan Hedberga5c29682011-02-19 12:05:57 -03002698
Johan Hedberga664b5b2011-02-19 12:06:02 -03002699 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03002700
2701 return err;
2702}
2703
2704int mgmt_user_confirm_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status)
2705{
2706 return confirm_reply_complete(index, bdaddr, status,
2707 MGMT_OP_USER_CONFIRM_REPLY);
2708}
2709
Szymon Jancb8534e02011-03-01 16:55:34 +01002710int mgmt_user_confirm_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03002711{
2712 return confirm_reply_complete(index, bdaddr, status,
2713 MGMT_OP_USER_CONFIRM_NEG_REPLY);
2714}
Johan Hedberg2a611692011-02-19 12:06:00 -03002715
2716int mgmt_auth_failed(u16 index, bdaddr_t *bdaddr, u8 status)
2717{
2718 struct mgmt_ev_auth_failed ev;
2719
Johan Hedberg2a611692011-02-19 12:06:00 -03002720 bacpy(&ev.bdaddr, bdaddr);
2721 ev.status = status;
2722
Szymon Janc4e51eae2011-02-25 19:05:48 +01002723 return mgmt_event(MGMT_EV_AUTH_FAILED, index, &ev, sizeof(ev), NULL);
Johan Hedberg2a611692011-02-19 12:06:00 -03002724}
Johan Hedbergb312b1612011-03-16 14:29:37 +02002725
2726int mgmt_set_local_name_complete(u16 index, u8 *name, u8 status)
2727{
2728 struct pending_cmd *cmd;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002729 struct hci_dev *hdev;
Johan Hedbergb312b1612011-03-16 14:29:37 +02002730 struct mgmt_cp_set_local_name ev;
2731 int err;
2732
2733 memset(&ev, 0, sizeof(ev));
2734 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
2735
2736 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, index);
2737 if (!cmd)
2738 goto send_event;
2739
2740 if (status) {
2741 err = cmd_status(cmd->sk, index, MGMT_OP_SET_LOCAL_NAME, EIO);
2742 goto failed;
2743 }
2744
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002745 hdev = hci_dev_get(index);
2746 if (hdev) {
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002747 update_eir(hdev);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002748 hci_dev_put(hdev);
2749 }
2750
Johan Hedbergb312b1612011-03-16 14:29:37 +02002751 err = cmd_complete(cmd->sk, index, MGMT_OP_SET_LOCAL_NAME, &ev,
2752 sizeof(ev));
2753 if (err < 0)
2754 goto failed;
2755
2756send_event:
2757 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, index, &ev, sizeof(ev),
2758 cmd ? cmd->sk : NULL);
2759
2760failed:
2761 if (cmd)
2762 mgmt_pending_remove(cmd);
2763 return err;
2764}
Szymon Jancc35938b2011-03-22 13:12:21 +01002765
2766int mgmt_read_local_oob_data_reply_complete(u16 index, u8 *hash, u8 *randomizer,
2767 u8 status)
2768{
2769 struct pending_cmd *cmd;
2770 int err;
2771
2772 BT_DBG("hci%u status %u", index, status);
2773
2774 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, index);
2775 if (!cmd)
2776 return -ENOENT;
2777
2778 if (status) {
2779 err = cmd_status(cmd->sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
2780 EIO);
2781 } else {
2782 struct mgmt_rp_read_local_oob_data rp;
2783
2784 memcpy(rp.hash, hash, sizeof(rp.hash));
2785 memcpy(rp.randomizer, randomizer, sizeof(rp.randomizer));
2786
2787 err = cmd_complete(cmd->sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
2788 &rp, sizeof(rp));
2789 }
2790
2791 mgmt_pending_remove(cmd);
2792
2793 return err;
2794}
Johan Hedberge17acd42011-03-30 23:57:16 +03002795
Brian Gixa68668b2011-08-11 15:49:36 -07002796int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 type, u8 le,
2797 u8 *dev_class, s8 rssi, u8 eir_len, u8 *eir)
Johan Hedberge17acd42011-03-30 23:57:16 +03002798{
2799 struct mgmt_ev_device_found ev;
Brian Gix568dde92012-01-11 16:18:04 -08002800 struct hci_dev *hdev;
Brian Gixa68668b2011-08-11 15:49:36 -07002801 int err;
2802
2803 BT_DBG("le: %d", le);
Johan Hedberge17acd42011-03-30 23:57:16 +03002804
2805 memset(&ev, 0, sizeof(ev));
2806
2807 bacpy(&ev.bdaddr, bdaddr);
Johan Hedberge17acd42011-03-30 23:57:16 +03002808 ev.rssi = rssi;
Brian Gixa68668b2011-08-11 15:49:36 -07002809 ev.type = type;
2810 ev.le = le;
Johan Hedberge17acd42011-03-30 23:57:16 +03002811
Brian Gixa68668b2011-08-11 15:49:36 -07002812 if (dev_class)
2813 memcpy(ev.dev_class, dev_class, sizeof(ev.dev_class));
Johan Hedberge17acd42011-03-30 23:57:16 +03002814
Brian Gixa68668b2011-08-11 15:49:36 -07002815 if (eir && eir_len)
2816 memcpy(ev.eir, eir, eir_len);
2817
2818 err = mgmt_event(MGMT_EV_DEVICE_FOUND, index, &ev, sizeof(ev), NULL);
2819
2820 if (err < 0)
2821 return err;
2822
Brian Gix568dde92012-01-11 16:18:04 -08002823 hdev = hci_dev_get(index);
Brian Gixa68668b2011-08-11 15:49:36 -07002824
Brian Gix568dde92012-01-11 16:18:04 -08002825 if (!hdev)
2826 return 0;
Brian Gix64bd5302011-09-08 11:35:48 -07002827
Brian Gix568dde92012-01-11 16:18:04 -08002828 if (hdev->disco_state == SCAN_IDLE)
2829 goto done;
2830
2831 hdev->disco_int_count++;
2832
2833 if (hdev->disco_int_count >= hdev->disco_int_phase) {
2834 /* Inquiry scan for General Discovery LAP */
2835 struct hci_cp_inquiry cp = {{0x33, 0x8b, 0x9e}, 4, 0};
2836 struct hci_cp_le_set_scan_enable le_cp = {0, 0};
2837
2838 hdev->disco_int_phase *= 2;
2839 hdev->disco_int_count = 0;
2840 if (hdev->disco_state == SCAN_LE) {
2841 /* cancel LE scan */
2842 hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE,
2843 sizeof(le_cp), &le_cp);
2844 /* start BR scan */
2845 cp.num_rsp = (u8) hdev->disco_int_phase;
2846 hci_send_cmd(hdev, HCI_OP_INQUIRY,
2847 sizeof(cp), &cp);
2848 hdev->disco_state = SCAN_BR;
2849 del_timer_sync(&hdev->disco_le_timer);
Brian Gixa68668b2011-08-11 15:49:36 -07002850 }
2851 }
2852
Brian Gix568dde92012-01-11 16:18:04 -08002853done:
2854 hci_dev_put(hdev);
Brian Gixa68668b2011-08-11 15:49:36 -07002855 return 0;
Johan Hedberge17acd42011-03-30 23:57:16 +03002856}
Johan Hedberga88a9652011-03-30 13:18:12 +03002857
Brian Gixa68668b2011-08-11 15:49:36 -07002858
2859int mgmt_remote_name(u16 index, bdaddr_t *bdaddr, u8 status, u8 *name)
Johan Hedberga88a9652011-03-30 13:18:12 +03002860{
2861 struct mgmt_ev_remote_name ev;
2862
2863 memset(&ev, 0, sizeof(ev));
2864
2865 bacpy(&ev.bdaddr, bdaddr);
Brian Gixa68668b2011-08-11 15:49:36 -07002866 ev.status = status;
Johan Hedberga88a9652011-03-30 13:18:12 +03002867 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
2868
2869 return mgmt_event(MGMT_EV_REMOTE_NAME, index, &ev, sizeof(ev), NULL);
2870}
Prabhakaran Mc46230fa2011-11-30 18:11:21 +05302871
2872int mgmt_encrypt_change(u16 index, bdaddr_t *bdaddr, u8 status)
2873{
2874 struct mgmt_ev_encrypt_change ev;
2875
2876 BT_DBG("hci%u", index);
2877
2878 bacpy(&ev.bdaddr, bdaddr);
2879 ev.status = status;
2880
2881 return mgmt_event(MGMT_EV_ENCRYPT_CHANGE, index, &ev, sizeof(ev),
2882 NULL);
2883}
2884
Srinivas Krovvidi0916aed2011-12-20 12:06:34 +05302885int mgmt_remote_class(u16 index, bdaddr_t *bdaddr, u8 dev_class[3])
2886{
2887 struct mgmt_ev_remote_class ev;
2888
2889 memset(&ev, 0, sizeof(ev));
2890
2891 bacpy(&ev.bdaddr, bdaddr);
2892 memcpy(ev.dev_class, dev_class, 3);
2893
2894 return mgmt_event(MGMT_EV_REMOTE_CLASS, index, &ev, sizeof(ev), NULL);
2895}