blob: 2e4c47a70a7fa1ffebdcd86cd108109dd0fd8c36 [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 Gix474e0f22012-01-14 20:21:55 -08002043 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, index);
2044 if (!cmd)
2045 mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, index,
2046 NULL, 0);
Brian Gix568dde92012-01-11 16:18:04 -08002047 hdev->disco_int_phase = 1;
2048 hdev->disco_int_count = 0;
2049 hdev->disco_state = SCAN_BR;
Brian Gix568dde92012-01-11 16:18:04 -08002050 del_timer(&hdev->disco_le_timer);
2051 del_timer(&hdev->disco_timer);
2052 mod_timer(&hdev->disco_timer,
2053 jiffies + msecs_to_jiffies(20000));
Brian Gixa68668b2011-08-11 15:49:36 -07002054 }
2055
2056failed:
Subramanian Srinivasana727a492011-11-30 13:06:07 -08002057 hci_dev_unlock_bh(hdev);
Brian Gixa68668b2011-08-11 15:49:36 -07002058 hci_dev_put(hdev);
2059
Brian Gix568dde92012-01-11 16:18:04 -08002060 if (err < 0)
2061 return cmd_status(sk, index, MGMT_OP_START_DISCOVERY, -err);
2062
Brian Gixa68668b2011-08-11 15:49:36 -07002063 return err;
2064}
2065
2066static int stop_discovery(struct sock *sk, u16 index)
2067{
2068 struct hci_cp_le_set_scan_enable le_cp = {0, 0};
2069 struct mgmt_mode mode_cp = {0};
Brian Gixa68668b2011-08-11 15:49:36 -07002070 struct hci_dev *hdev;
2071 struct pending_cmd *cmd = NULL;
2072 int err = -EPERM;
Brian Gix568dde92012-01-11 16:18:04 -08002073 u8 state;
Brian Gixa68668b2011-08-11 15:49:36 -07002074
2075 BT_DBG("");
2076
2077 hdev = hci_dev_get(index);
2078 if (!hdev)
2079 return cmd_status(sk, index, MGMT_OP_STOP_DISCOVERY, ENODEV);
2080
Subramanian Srinivasana727a492011-11-30 13:06:07 -08002081 hci_dev_lock_bh(hdev);
Brian Gixa68668b2011-08-11 15:49:36 -07002082
Brian Gix568dde92012-01-11 16:18:04 -08002083 state = hdev->disco_state;
2084 hdev->disco_state = SCAN_IDLE;
2085 del_timer(&hdev->disco_le_timer);
2086 del_timer(&hdev->disco_timer);
Brian Gixa68668b2011-08-11 15:49:36 -07002087
Brian Gix568dde92012-01-11 16:18:04 -08002088 if (state == SCAN_LE) {
Brian Gixa68668b2011-08-11 15:49:36 -07002089 err = hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE,
2090 sizeof(le_cp), &le_cp);
Brian Gix568dde92012-01-11 16:18:04 -08002091 if (err >= 0) {
2092 mgmt_pending_foreach(MGMT_OP_STOP_DISCOVERY, index,
2093 discovery_terminated, NULL);
Brian Gixa68668b2011-08-11 15:49:36 -07002094
Brian Gix568dde92012-01-11 16:18:04 -08002095 err = cmd_complete(sk, index, MGMT_OP_STOP_DISCOVERY,
2096 NULL, 0);
2097 }
Brian Gixa68668b2011-08-11 15:49:36 -07002098 }
2099
Brian Gix568dde92012-01-11 16:18:04 -08002100 if (err < 0)
2101 err = hci_send_cmd(hdev, HCI_OP_INQUIRY_CANCEL, 0, NULL);
Brian Gixa68668b2011-08-11 15:49:36 -07002102
Brian Gix568dde92012-01-11 16:18:04 -08002103 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, index);
Brian Gixa68668b2011-08-11 15:49:36 -07002104 if (err < 0 && cmd)
2105 mgmt_pending_remove(cmd);
2106
2107 mgmt_event(MGMT_EV_DISCOVERING, index, &mode_cp, sizeof(mode_cp), NULL);
2108
Subramanian Srinivasana727a492011-11-30 13:06:07 -08002109 hci_dev_unlock_bh(hdev);
Brian Gixa68668b2011-08-11 15:49:36 -07002110 hci_dev_put(hdev);
2111
2112 if (err < 0)
2113 return cmd_status(sk, index, MGMT_OP_STOP_DISCOVERY, -err);
2114 else
2115 return err;
2116}
2117
Szymon Jancc35938b2011-03-22 13:12:21 +01002118static int read_local_oob_data(struct sock *sk, u16 index)
2119{
2120 struct hci_dev *hdev;
2121 struct pending_cmd *cmd;
2122 int err;
2123
2124 BT_DBG("hci%u", index);
2125
2126 hdev = hci_dev_get(index);
2127 if (!hdev)
2128 return cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
2129 ENODEV);
2130
Subramanian Srinivasana727a492011-11-30 13:06:07 -08002131 hci_dev_lock_bh(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01002132
2133 if (!test_bit(HCI_UP, &hdev->flags)) {
2134 err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
2135 ENETDOWN);
2136 goto unlock;
2137 }
2138
2139 if (!(hdev->features[6] & LMP_SIMPLE_PAIR)) {
2140 err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
2141 EOPNOTSUPP);
2142 goto unlock;
2143 }
2144
2145 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, index)) {
2146 err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, EBUSY);
2147 goto unlock;
2148 }
2149
2150 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, index, NULL, 0);
2151 if (!cmd) {
2152 err = -ENOMEM;
2153 goto unlock;
2154 }
2155
2156 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
2157 if (err < 0)
2158 mgmt_pending_remove(cmd);
2159
2160unlock:
Subramanian Srinivasana727a492011-11-30 13:06:07 -08002161 hci_dev_unlock_bh(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01002162 hci_dev_put(hdev);
2163
2164 return err;
2165}
2166
Szymon Janc2763eda2011-03-22 13:12:22 +01002167static int add_remote_oob_data(struct sock *sk, u16 index, unsigned char *data,
2168 u16 len)
2169{
2170 struct hci_dev *hdev;
2171 struct mgmt_cp_add_remote_oob_data *cp = (void *) data;
2172 int err;
2173
2174 BT_DBG("hci%u ", index);
2175
2176 if (len != sizeof(*cp))
2177 return cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA,
2178 EINVAL);
2179
2180 hdev = hci_dev_get(index);
2181 if (!hdev)
2182 return cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA,
2183 ENODEV);
2184
Subramanian Srinivasana727a492011-11-30 13:06:07 -08002185 hci_dev_lock_bh(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01002186
2187 err = hci_add_remote_oob_data(hdev, &cp->bdaddr, cp->hash,
2188 cp->randomizer);
2189 if (err < 0)
2190 err = cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, -err);
2191 else
2192 err = cmd_complete(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, NULL,
2193 0);
2194
Subramanian Srinivasana727a492011-11-30 13:06:07 -08002195 hci_dev_unlock_bh(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01002196 hci_dev_put(hdev);
2197
2198 return err;
2199}
2200
2201static int remove_remote_oob_data(struct sock *sk, u16 index,
2202 unsigned char *data, u16 len)
2203{
2204 struct hci_dev *hdev;
2205 struct mgmt_cp_remove_remote_oob_data *cp = (void *) data;
2206 int err;
2207
2208 BT_DBG("hci%u ", index);
2209
2210 if (len != sizeof(*cp))
2211 return cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
2212 EINVAL);
2213
2214 hdev = hci_dev_get(index);
2215 if (!hdev)
2216 return cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
2217 ENODEV);
2218
Subramanian Srinivasana727a492011-11-30 13:06:07 -08002219 hci_dev_lock_bh(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01002220
2221 err = hci_remove_remote_oob_data(hdev, &cp->bdaddr);
2222 if (err < 0)
2223 err = cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
2224 -err);
2225 else
2226 err = cmd_complete(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
2227 NULL, 0);
2228
Subramanian Srinivasana727a492011-11-30 13:06:07 -08002229 hci_dev_unlock_bh(hdev);
Antti Julku58d19802011-06-15 12:01:15 +03002230 hci_dev_put(hdev);
2231
2232 return err;
2233}
2234
Johan Hedberg03811012010-12-08 00:21:06 +02002235int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
2236{
2237 unsigned char *buf;
2238 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01002239 u16 opcode, index, len;
Johan Hedberg03811012010-12-08 00:21:06 +02002240 int err;
2241
2242 BT_DBG("got %zu bytes", msglen);
2243
2244 if (msglen < sizeof(*hdr))
2245 return -EINVAL;
2246
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03002247 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02002248 if (!buf)
2249 return -ENOMEM;
2250
2251 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
2252 err = -EFAULT;
2253 goto done;
2254 }
2255
2256 hdr = (struct mgmt_hdr *) buf;
2257 opcode = get_unaligned_le16(&hdr->opcode);
Szymon Janc4e51eae2011-02-25 19:05:48 +01002258 index = get_unaligned_le16(&hdr->index);
Johan Hedberg03811012010-12-08 00:21:06 +02002259 len = get_unaligned_le16(&hdr->len);
2260
2261 if (len != msglen - sizeof(*hdr)) {
2262 err = -EINVAL;
2263 goto done;
2264 }
2265
Brian Gixa68668b2011-08-11 15:49:36 -07002266 BT_DBG("got opcode %x", opcode);
Johan Hedberg03811012010-12-08 00:21:06 +02002267 switch (opcode) {
Johan Hedberg02d98122010-12-13 21:07:04 +02002268 case MGMT_OP_READ_VERSION:
2269 err = read_version(sk);
2270 break;
Johan Hedbergfaba42e2010-12-13 21:07:05 +02002271 case MGMT_OP_READ_INDEX_LIST:
2272 err = read_index_list(sk);
2273 break;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02002274 case MGMT_OP_READ_INFO:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002275 err = read_controller_info(sk, index);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02002276 break;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002277 case MGMT_OP_SET_POWERED:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002278 err = set_powered(sk, index, buf + sizeof(*hdr), len);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002279 break;
Johan Hedberg73f22f62010-12-29 16:00:25 +02002280 case MGMT_OP_SET_DISCOVERABLE:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002281 err = set_discoverable(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg73f22f62010-12-29 16:00:25 +02002282 break;
Brian Gix8a7f1642011-10-17 17:39:46 -07002283 case MGMT_OP_SET_LIMIT_DISCOVERABLE:
2284 err = set_limited_discoverable(sk, index, buf + sizeof(*hdr),
2285 len);
2286 break;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02002287 case MGMT_OP_SET_CONNECTABLE:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002288 err = set_connectable(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02002289 break;
Johan Hedbergc542a062011-01-26 13:11:03 +02002290 case MGMT_OP_SET_PAIRABLE:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002291 err = set_pairable(sk, index, buf + sizeof(*hdr), len);
Johan Hedbergc542a062011-01-26 13:11:03 +02002292 break;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002293 case MGMT_OP_ADD_UUID:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002294 err = add_uuid(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002295 break;
2296 case MGMT_OP_REMOVE_UUID:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002297 err = remove_uuid(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002298 break;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002299 case MGMT_OP_SET_DEV_CLASS:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002300 err = set_dev_class(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002301 break;
2302 case MGMT_OP_SET_SERVICE_CACHE:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002303 err = set_service_cache(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002304 break;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002305 case MGMT_OP_LOAD_KEYS:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002306 err = load_keys(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002307 break;
2308 case MGMT_OP_REMOVE_KEY:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002309 err = remove_key(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002310 break;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002311 case MGMT_OP_DISCONNECT:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002312 err = disconnect(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002313 break;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002314 case MGMT_OP_GET_CONNECTIONS:
Szymon Janc8ce62842011-03-01 16:55:32 +01002315 err = get_connections(sk, index);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002316 break;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002317 case MGMT_OP_PIN_CODE_REPLY:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002318 err = pin_code_reply(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002319 break;
2320 case MGMT_OP_PIN_CODE_NEG_REPLY:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002321 err = pin_code_neg_reply(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002322 break;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002323 case MGMT_OP_SET_IO_CAPABILITY:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002324 err = set_io_capability(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002325 break;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002326 case MGMT_OP_PAIR_DEVICE:
Szymon Janc4e51eae2011-02-25 19:05:48 +01002327 err = pair_device(sk, index, buf + sizeof(*hdr), len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002328 break;
Johan Hedberga5c29682011-02-19 12:05:57 -03002329 case MGMT_OP_USER_CONFIRM_REPLY:
Brian Gixa68668b2011-08-11 15:49:36 -07002330 case MGMT_OP_USER_PASSKEY_REPLY:
Johan Hedberga5c29682011-02-19 12:05:57 -03002331 case MGMT_OP_USER_CONFIRM_NEG_REPLY:
Brian Gixa68668b2011-08-11 15:49:36 -07002332 err = user_confirm_reply(sk, index, buf + sizeof(*hdr),
2333 len, opcode);
Johan Hedberga5c29682011-02-19 12:05:57 -03002334 break;
Johan Hedbergb312b1612011-03-16 14:29:37 +02002335 case MGMT_OP_SET_LOCAL_NAME:
2336 err = set_local_name(sk, index, buf + sizeof(*hdr), len);
2337 break;
Brian Gixa68668b2011-08-11 15:49:36 -07002338 case MGMT_OP_START_DISCOVERY:
2339 err = start_discovery(sk, index);
2340 break;
2341 case MGMT_OP_STOP_DISCOVERY:
2342 err = stop_discovery(sk, index);
2343 break;
2344 case MGMT_OP_RESOLVE_NAME:
2345 err = resolve_name(sk, index, buf + sizeof(*hdr), len);
2346 break;
Brian Gix7f7e16c2011-11-01 16:27:25 -07002347 case MGMT_OP_SET_CONNECTION_PARAMS:
2348 err = set_connection_params(sk, index, buf + sizeof(*hdr), len);
2349 break;
Szymon Jancc35938b2011-03-22 13:12:21 +01002350 case MGMT_OP_READ_LOCAL_OOB_DATA:
2351 err = read_local_oob_data(sk, index);
2352 break;
Szymon Janc2763eda2011-03-22 13:12:22 +01002353 case MGMT_OP_ADD_REMOTE_OOB_DATA:
2354 err = add_remote_oob_data(sk, index, buf + sizeof(*hdr), len);
2355 break;
2356 case MGMT_OP_REMOVE_REMOTE_OOB_DATA:
2357 err = remove_remote_oob_data(sk, index, buf + sizeof(*hdr),
2358 len);
2359 break;
Prabhakaran Mc46230fa2011-11-30 18:11:21 +05302360 case MGMT_OP_ENCRYPT_LINK:
2361 err = encrypt_link(sk, index, buf + sizeof(*hdr), len);
2362 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002363
Johan Hedberg03811012010-12-08 00:21:06 +02002364 default:
2365 BT_DBG("Unknown op %u", opcode);
Szymon Janc4e51eae2011-02-25 19:05:48 +01002366 err = cmd_status(sk, index, opcode, 0x01);
Johan Hedberg03811012010-12-08 00:21:06 +02002367 break;
2368 }
2369
Johan Hedberge41d8b42010-12-13 21:07:03 +02002370 if (err < 0)
2371 goto done;
2372
Johan Hedberg03811012010-12-08 00:21:06 +02002373 err = msglen;
2374
2375done:
2376 kfree(buf);
2377 return err;
2378}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02002379
Johan Hedbergc71e97b2010-12-13 21:07:07 +02002380int mgmt_index_added(u16 index)
2381{
Brian Gixa68668b2011-08-11 15:49:36 -07002382 BT_DBG("%d", index);
Szymon Janc4e51eae2011-02-25 19:05:48 +01002383 return mgmt_event(MGMT_EV_INDEX_ADDED, index, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02002384}
2385
2386int mgmt_index_removed(u16 index)
2387{
Brian Gixa68668b2011-08-11 15:49:36 -07002388 BT_DBG("%d", index);
Szymon Janc4e51eae2011-02-25 19:05:48 +01002389 return mgmt_event(MGMT_EV_INDEX_REMOVED, index, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002390}
2391
Johan Hedberg73f22f62010-12-29 16:00:25 +02002392struct cmd_lookup {
Johan Hedberg72a734e2010-12-30 00:38:22 +02002393 u8 val;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002394 struct sock *sk;
2395};
2396
Johan Hedberg72a734e2010-12-30 00:38:22 +02002397static void mode_rsp(struct pending_cmd *cmd, void *data)
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002398{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01002399 struct mgmt_mode *cp = cmd->param;
Johan Hedberg73f22f62010-12-29 16:00:25 +02002400 struct cmd_lookup *match = data;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002401
Johan Hedberg72a734e2010-12-30 00:38:22 +02002402 if (cp->val != match->val)
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002403 return;
2404
Johan Hedberg053f0212011-01-26 13:07:10 +02002405 send_mode_rsp(cmd->sk, cmd->opcode, cmd->index, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002406
2407 list_del(&cmd->list);
2408
2409 if (match->sk == NULL) {
2410 match->sk = cmd->sk;
2411 sock_hold(match->sk);
2412 }
2413
2414 mgmt_pending_free(cmd);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02002415}
Johan Hedberg5add6af2010-12-16 10:00:37 +02002416
2417int mgmt_powered(u16 index, u8 powered)
2418{
Johan Hedberg72a734e2010-12-30 00:38:22 +02002419 struct mgmt_mode ev;
Johan Hedberg73f22f62010-12-29 16:00:25 +02002420 struct cmd_lookup match = { powered, NULL };
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002421 int ret;
Johan Hedberg5add6af2010-12-16 10:00:37 +02002422
Brian Gixa68668b2011-08-11 15:49:36 -07002423 BT_DBG("hci%u %d", index, powered);
2424
Johan Hedberg72a734e2010-12-30 00:38:22 +02002425 mgmt_pending_foreach(MGMT_OP_SET_POWERED, index, mode_rsp, &match);
Johan Hedberg5add6af2010-12-16 10:00:37 +02002426
Johan Hedberg72a734e2010-12-30 00:38:22 +02002427 ev.val = powered;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002428
Szymon Janc4e51eae2011-02-25 19:05:48 +01002429 ret = mgmt_event(MGMT_EV_POWERED, index, &ev, sizeof(ev), match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002430
2431 if (match.sk)
2432 sock_put(match.sk);
2433
2434 return ret;
Johan Hedberg5add6af2010-12-16 10:00:37 +02002435}
Johan Hedberg73f22f62010-12-29 16:00:25 +02002436
Johan Hedberg73f22f62010-12-29 16:00:25 +02002437int mgmt_discoverable(u16 index, u8 discoverable)
2438{
Johan Hedberg72a734e2010-12-30 00:38:22 +02002439 struct mgmt_mode ev;
Johan Hedberg73f22f62010-12-29 16:00:25 +02002440 struct cmd_lookup match = { discoverable, NULL };
2441 int ret;
2442
Szymon Jancb8534e02011-03-01 16:55:34 +01002443 mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, index, mode_rsp, &match);
Johan Hedberg72a734e2010-12-30 00:38:22 +02002444
Johan Hedberg72a734e2010-12-30 00:38:22 +02002445 ev.val = discoverable;
Johan Hedberg73f22f62010-12-29 16:00:25 +02002446
Szymon Janc4e51eae2011-02-25 19:05:48 +01002447 ret = mgmt_event(MGMT_EV_DISCOVERABLE, index, &ev, sizeof(ev),
2448 match.sk);
Johan Hedberg73f22f62010-12-29 16:00:25 +02002449
2450 if (match.sk)
2451 sock_put(match.sk);
2452
2453 return ret;
2454}
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02002455
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02002456int mgmt_connectable(u16 index, u8 connectable)
2457{
Johan Hedberg72a734e2010-12-30 00:38:22 +02002458 struct mgmt_mode ev;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02002459 struct cmd_lookup match = { connectable, NULL };
2460 int ret;
2461
Johan Hedberg72a734e2010-12-30 00:38:22 +02002462 mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, index, mode_rsp, &match);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02002463
Johan Hedberg72a734e2010-12-30 00:38:22 +02002464 ev.val = connectable;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02002465
Szymon Janc4e51eae2011-02-25 19:05:48 +01002466 ret = mgmt_event(MGMT_EV_CONNECTABLE, index, &ev, sizeof(ev), match.sk);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02002467
2468 if (match.sk)
2469 sock_put(match.sk);
2470
2471 return ret;
2472}
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002473
Brian Gixa68668b2011-08-11 15:49:36 -07002474int mgmt_new_key(u16 index, struct link_key *key, u8 bonded)
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002475{
Vinicius Costa Gomesc00ddbf2011-07-08 18:31:44 -03002476 struct mgmt_ev_new_key *ev;
2477 int err, total;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002478
Vinicius Costa Gomesc00ddbf2011-07-08 18:31:44 -03002479 total = sizeof(struct mgmt_ev_new_key) + key->dlen;
2480 ev = kzalloc(total, GFP_ATOMIC);
2481 if (!ev)
2482 return -ENOMEM;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002483
Vinicius Costa Gomesc00ddbf2011-07-08 18:31:44 -03002484 bacpy(&ev->key.bdaddr, &key->bdaddr);
Brian Gixcf956772011-10-20 15:18:51 -07002485 ev->key.addr_type = key->addr_type;
2486 ev->key.key_type = key->key_type;
Vinicius Costa Gomesc00ddbf2011-07-08 18:31:44 -03002487 memcpy(ev->key.val, key->val, 16);
2488 ev->key.pin_len = key->pin_len;
Brian Gixa68668b2011-08-11 15:49:36 -07002489 ev->key.auth = key->auth;
2490 ev->store_hint = bonded;
Vinicius Costa Gomesc00ddbf2011-07-08 18:31:44 -03002491 ev->key.dlen = key->dlen;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002492
Vinicius Costa Gomesc00ddbf2011-07-08 18:31:44 -03002493 memcpy(ev->key.data, key->data, key->dlen);
2494
2495 err = mgmt_event(MGMT_EV_NEW_KEY, index, ev, total, NULL);
2496
2497 kfree(ev);
2498
2499 return err;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002500}
Johan Hedbergf7520542011-01-20 12:34:39 +02002501
Brian Gix2e2f50d2011-09-13 12:36:04 -07002502int mgmt_connected(u16 index, bdaddr_t *bdaddr, u8 le)
Johan Hedbergf7520542011-01-20 12:34:39 +02002503{
2504 struct mgmt_ev_connected ev;
2505
Johan Hedbergf7520542011-01-20 12:34:39 +02002506 bacpy(&ev.bdaddr, bdaddr);
Brian Gix2e2f50d2011-09-13 12:36:04 -07002507 ev.le = le;
Johan Hedbergf7520542011-01-20 12:34:39 +02002508
Szymon Janc4e51eae2011-02-25 19:05:48 +01002509 return mgmt_event(MGMT_EV_CONNECTED, index, &ev, sizeof(ev), NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02002510}
2511
Johan Hedberg8962ee72011-01-20 12:40:27 +02002512static void disconnect_rsp(struct pending_cmd *cmd, void *data)
2513{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01002514 struct mgmt_cp_disconnect *cp = cmd->param;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002515 struct sock **sk = data;
Johan Hedberga38528f2011-01-22 06:46:43 +02002516 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002517
Johan Hedberga38528f2011-01-22 06:46:43 +02002518 bacpy(&rp.bdaddr, &cp->bdaddr);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002519
Szymon Janc4e51eae2011-02-25 19:05:48 +01002520 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002521
2522 *sk = cmd->sk;
2523 sock_hold(*sk);
2524
Johan Hedberga664b5b2011-02-19 12:06:02 -03002525 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002526}
2527
Johan Hedbergf7520542011-01-20 12:34:39 +02002528int mgmt_disconnected(u16 index, bdaddr_t *bdaddr)
2529{
2530 struct mgmt_ev_disconnected ev;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002531 struct sock *sk = NULL;
2532 int err;
2533
2534 mgmt_pending_foreach(MGMT_OP_DISCONNECT, index, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02002535
Johan Hedbergf7520542011-01-20 12:34:39 +02002536 bacpy(&ev.bdaddr, bdaddr);
2537
Szymon Janc4e51eae2011-02-25 19:05:48 +01002538 err = mgmt_event(MGMT_EV_DISCONNECTED, index, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002539
2540 if (sk)
2541 sock_put(sk);
2542
2543 return err;
2544}
2545
2546int mgmt_disconnect_failed(u16 index)
2547{
2548 struct pending_cmd *cmd;
2549 int err;
2550
2551 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, index);
2552 if (!cmd)
2553 return -ENOENT;
2554
Szymon Janc4e51eae2011-02-25 19:05:48 +01002555 err = cmd_status(cmd->sk, index, MGMT_OP_DISCONNECT, EIO);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002556
Johan Hedberga664b5b2011-02-19 12:06:02 -03002557 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002558
2559 return err;
Johan Hedbergf7520542011-01-20 12:34:39 +02002560}
Johan Hedberg17d5c042011-01-22 06:09:08 +02002561
2562int mgmt_connect_failed(u16 index, bdaddr_t *bdaddr, u8 status)
2563{
2564 struct mgmt_ev_connect_failed ev;
2565
Johan Hedberg17d5c042011-01-22 06:09:08 +02002566 bacpy(&ev.bdaddr, bdaddr);
2567 ev.status = status;
2568
Szymon Janc4e51eae2011-02-25 19:05:48 +01002569 return mgmt_event(MGMT_EV_CONNECT_FAILED, index, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02002570}
Johan Hedberg980e1a52011-01-22 06:10:07 +02002571
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002572int mgmt_pin_code_request(u16 index, bdaddr_t *bdaddr)
Johan Hedberg980e1a52011-01-22 06:10:07 +02002573{
2574 struct mgmt_ev_pin_code_request ev;
2575
Brian Gixa68668b2011-08-11 15:49:36 -07002576 BT_DBG("hci%u", index);
2577
Johan Hedberg980e1a52011-01-22 06:10:07 +02002578 bacpy(&ev.bdaddr, bdaddr);
Brian Gixa68668b2011-08-11 15:49:36 -07002579 ev.secure = 0;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002580
Szymon Janc4e51eae2011-02-25 19:05:48 +01002581 return mgmt_event(MGMT_EV_PIN_CODE_REQUEST, index, &ev, sizeof(ev),
2582 NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002583}
2584
2585int mgmt_pin_code_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status)
2586{
2587 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03002588 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002589 int err;
2590
2591 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, index);
2592 if (!cmd)
2593 return -ENOENT;
2594
Johan Hedbergac56fb12011-02-19 12:05:59 -03002595 bacpy(&rp.bdaddr, bdaddr);
2596 rp.status = status;
2597
Szymon Janc4e51eae2011-02-25 19:05:48 +01002598 err = cmd_complete(cmd->sk, index, MGMT_OP_PIN_CODE_REPLY, &rp,
2599 sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02002600
Johan Hedberga664b5b2011-02-19 12:06:02 -03002601 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002602
2603 return err;
2604}
2605
2606int mgmt_pin_code_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status)
2607{
2608 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03002609 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002610 int err;
2611
2612 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, index);
2613 if (!cmd)
2614 return -ENOENT;
2615
Johan Hedbergac56fb12011-02-19 12:05:59 -03002616 bacpy(&rp.bdaddr, bdaddr);
2617 rp.status = status;
2618
Szymon Janc4e51eae2011-02-25 19:05:48 +01002619 err = cmd_complete(cmd->sk, index, MGMT_OP_PIN_CODE_NEG_REPLY, &rp,
2620 sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02002621
Johan Hedberga664b5b2011-02-19 12:06:02 -03002622 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002623
2624 return err;
2625}
Johan Hedberga5c29682011-02-19 12:05:57 -03002626
Brian Gixa68668b2011-08-11 15:49:36 -07002627int mgmt_user_confirm_request(u16 index, u8 event,
2628 bdaddr_t *bdaddr, __le32 value)
Johan Hedberga5c29682011-02-19 12:05:57 -03002629{
2630 struct mgmt_ev_user_confirm_request ev;
Brian Gixa68668b2011-08-11 15:49:36 -07002631 struct hci_conn *conn = NULL;
2632 struct hci_dev *hdev;
2633 u8 loc_cap, rem_cap, loc_mitm, rem_mitm;
2634
2635 BT_DBG("hci%u", index);
2636
2637 hdev = hci_dev_get(index);
2638
Brian Gix64bd5302011-09-08 11:35:48 -07002639 if (!hdev)
2640 return -ENODEV;
2641
Brian Gix64bd5302011-09-08 11:35:48 -07002642 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, bdaddr);
Brian Gixa68668b2011-08-11 15:49:36 -07002643
2644 ev.auto_confirm = 0;
2645
2646 if (!conn || event != HCI_EV_USER_CONFIRM_REQUEST)
2647 goto no_auto_confirm;
2648
2649 loc_cap = (conn->io_capability == 0x04) ? 0x01 : conn->io_capability;
2650 rem_cap = conn->remote_cap;
2651 loc_mitm = conn->auth_type & 0x01;
2652 rem_mitm = conn->remote_auth & 0x01;
2653
Brian Gixdbf59292011-11-11 15:45:17 -08002654 if ((conn->auth_type & HCI_AT_DEDICATED_BONDING) &&
2655 conn->auth_initiator && rem_cap == 0x03)
2656 ev.auto_confirm = 1;
2657 else if (loc_cap == 0x01 && (rem_cap == 0x00 || rem_cap == 0x03))
Brian Gixa68668b2011-08-11 15:49:36 -07002658 goto no_auto_confirm;
2659
2660
2661 if ((!loc_mitm || rem_cap == 0x03) && (!rem_mitm || loc_cap == 0x03))
2662 ev.auto_confirm = 1;
2663
2664no_auto_confirm:
2665 bacpy(&ev.bdaddr, bdaddr);
2666 ev.event = event;
2667 put_unaligned_le32(value, &ev.value);
2668
Brian Gix64bd5302011-09-08 11:35:48 -07002669 hci_dev_put(hdev);
2670
Brian Gixa68668b2011-08-11 15:49:36 -07002671 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, index, &ev, sizeof(ev),
2672 NULL);
2673}
2674
2675int mgmt_user_passkey_request(u16 index, bdaddr_t *bdaddr)
2676{
2677 struct mgmt_ev_user_passkey_request ev;
Johan Hedberga5c29682011-02-19 12:05:57 -03002678
2679 BT_DBG("hci%u", index);
2680
Johan Hedberga5c29682011-02-19 12:05:57 -03002681 bacpy(&ev.bdaddr, bdaddr);
Johan Hedberga5c29682011-02-19 12:05:57 -03002682
Brian Gixa68668b2011-08-11 15:49:36 -07002683 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, index, &ev, sizeof(ev),
Szymon Janc4e51eae2011-02-25 19:05:48 +01002684 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03002685}
2686
2687static int confirm_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status,
2688 u8 opcode)
2689{
2690 struct pending_cmd *cmd;
2691 struct mgmt_rp_user_confirm_reply rp;
2692 int err;
2693
2694 cmd = mgmt_pending_find(opcode, index);
2695 if (!cmd)
2696 return -ENOENT;
2697
Johan Hedberga5c29682011-02-19 12:05:57 -03002698 bacpy(&rp.bdaddr, bdaddr);
2699 rp.status = status;
Szymon Janc4e51eae2011-02-25 19:05:48 +01002700 err = cmd_complete(cmd->sk, index, opcode, &rp, sizeof(rp));
Johan Hedberga5c29682011-02-19 12:05:57 -03002701
Johan Hedberga664b5b2011-02-19 12:06:02 -03002702 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03002703
2704 return err;
2705}
2706
2707int mgmt_user_confirm_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status)
2708{
2709 return confirm_reply_complete(index, bdaddr, status,
2710 MGMT_OP_USER_CONFIRM_REPLY);
2711}
2712
Szymon Jancb8534e02011-03-01 16:55:34 +01002713int mgmt_user_confirm_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03002714{
2715 return confirm_reply_complete(index, bdaddr, status,
2716 MGMT_OP_USER_CONFIRM_NEG_REPLY);
2717}
Johan Hedberg2a611692011-02-19 12:06:00 -03002718
2719int mgmt_auth_failed(u16 index, bdaddr_t *bdaddr, u8 status)
2720{
2721 struct mgmt_ev_auth_failed ev;
2722
Johan Hedberg2a611692011-02-19 12:06:00 -03002723 bacpy(&ev.bdaddr, bdaddr);
2724 ev.status = status;
2725
Szymon Janc4e51eae2011-02-25 19:05:48 +01002726 return mgmt_event(MGMT_EV_AUTH_FAILED, index, &ev, sizeof(ev), NULL);
Johan Hedberg2a611692011-02-19 12:06:00 -03002727}
Johan Hedbergb312b1612011-03-16 14:29:37 +02002728
2729int mgmt_set_local_name_complete(u16 index, u8 *name, u8 status)
2730{
2731 struct pending_cmd *cmd;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002732 struct hci_dev *hdev;
Johan Hedbergb312b1612011-03-16 14:29:37 +02002733 struct mgmt_cp_set_local_name ev;
2734 int err;
2735
2736 memset(&ev, 0, sizeof(ev));
2737 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
2738
2739 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, index);
2740 if (!cmd)
2741 goto send_event;
2742
2743 if (status) {
2744 err = cmd_status(cmd->sk, index, MGMT_OP_SET_LOCAL_NAME, EIO);
2745 goto failed;
2746 }
2747
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002748 hdev = hci_dev_get(index);
2749 if (hdev) {
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002750 update_eir(hdev);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002751 hci_dev_put(hdev);
2752 }
2753
Johan Hedbergb312b1612011-03-16 14:29:37 +02002754 err = cmd_complete(cmd->sk, index, MGMT_OP_SET_LOCAL_NAME, &ev,
2755 sizeof(ev));
2756 if (err < 0)
2757 goto failed;
2758
2759send_event:
2760 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, index, &ev, sizeof(ev),
2761 cmd ? cmd->sk : NULL);
2762
2763failed:
2764 if (cmd)
2765 mgmt_pending_remove(cmd);
2766 return err;
2767}
Szymon Jancc35938b2011-03-22 13:12:21 +01002768
2769int mgmt_read_local_oob_data_reply_complete(u16 index, u8 *hash, u8 *randomizer,
2770 u8 status)
2771{
2772 struct pending_cmd *cmd;
2773 int err;
2774
2775 BT_DBG("hci%u status %u", index, status);
2776
2777 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, index);
2778 if (!cmd)
2779 return -ENOENT;
2780
2781 if (status) {
2782 err = cmd_status(cmd->sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
2783 EIO);
2784 } else {
2785 struct mgmt_rp_read_local_oob_data rp;
2786
2787 memcpy(rp.hash, hash, sizeof(rp.hash));
2788 memcpy(rp.randomizer, randomizer, sizeof(rp.randomizer));
2789
2790 err = cmd_complete(cmd->sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
2791 &rp, sizeof(rp));
2792 }
2793
2794 mgmt_pending_remove(cmd);
2795
2796 return err;
2797}
Johan Hedberge17acd42011-03-30 23:57:16 +03002798
Brian Gixa68668b2011-08-11 15:49:36 -07002799int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 type, u8 le,
2800 u8 *dev_class, s8 rssi, u8 eir_len, u8 *eir)
Johan Hedberge17acd42011-03-30 23:57:16 +03002801{
2802 struct mgmt_ev_device_found ev;
Brian Gix568dde92012-01-11 16:18:04 -08002803 struct hci_dev *hdev;
Brian Gixa68668b2011-08-11 15:49:36 -07002804 int err;
2805
2806 BT_DBG("le: %d", le);
Johan Hedberge17acd42011-03-30 23:57:16 +03002807
2808 memset(&ev, 0, sizeof(ev));
2809
2810 bacpy(&ev.bdaddr, bdaddr);
Johan Hedberge17acd42011-03-30 23:57:16 +03002811 ev.rssi = rssi;
Brian Gixa68668b2011-08-11 15:49:36 -07002812 ev.type = type;
2813 ev.le = le;
Johan Hedberge17acd42011-03-30 23:57:16 +03002814
Brian Gixa68668b2011-08-11 15:49:36 -07002815 if (dev_class)
2816 memcpy(ev.dev_class, dev_class, sizeof(ev.dev_class));
Johan Hedberge17acd42011-03-30 23:57:16 +03002817
Brian Gixa68668b2011-08-11 15:49:36 -07002818 if (eir && eir_len)
2819 memcpy(ev.eir, eir, eir_len);
2820
2821 err = mgmt_event(MGMT_EV_DEVICE_FOUND, index, &ev, sizeof(ev), NULL);
2822
2823 if (err < 0)
2824 return err;
2825
Brian Gix568dde92012-01-11 16:18:04 -08002826 hdev = hci_dev_get(index);
Brian Gixa68668b2011-08-11 15:49:36 -07002827
Brian Gix568dde92012-01-11 16:18:04 -08002828 if (!hdev)
2829 return 0;
Brian Gix64bd5302011-09-08 11:35:48 -07002830
Brian Gix568dde92012-01-11 16:18:04 -08002831 if (hdev->disco_state == SCAN_IDLE)
2832 goto done;
2833
2834 hdev->disco_int_count++;
2835
2836 if (hdev->disco_int_count >= hdev->disco_int_phase) {
2837 /* Inquiry scan for General Discovery LAP */
2838 struct hci_cp_inquiry cp = {{0x33, 0x8b, 0x9e}, 4, 0};
2839 struct hci_cp_le_set_scan_enable le_cp = {0, 0};
2840
2841 hdev->disco_int_phase *= 2;
2842 hdev->disco_int_count = 0;
2843 if (hdev->disco_state == SCAN_LE) {
2844 /* cancel LE scan */
2845 hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE,
2846 sizeof(le_cp), &le_cp);
2847 /* start BR scan */
2848 cp.num_rsp = (u8) hdev->disco_int_phase;
2849 hci_send_cmd(hdev, HCI_OP_INQUIRY,
2850 sizeof(cp), &cp);
2851 hdev->disco_state = SCAN_BR;
2852 del_timer_sync(&hdev->disco_le_timer);
Brian Gixa68668b2011-08-11 15:49:36 -07002853 }
2854 }
2855
Brian Gix568dde92012-01-11 16:18:04 -08002856done:
2857 hci_dev_put(hdev);
Brian Gixa68668b2011-08-11 15:49:36 -07002858 return 0;
Johan Hedberge17acd42011-03-30 23:57:16 +03002859}
Johan Hedberga88a9652011-03-30 13:18:12 +03002860
Brian Gixa68668b2011-08-11 15:49:36 -07002861
2862int mgmt_remote_name(u16 index, bdaddr_t *bdaddr, u8 status, u8 *name)
Johan Hedberga88a9652011-03-30 13:18:12 +03002863{
2864 struct mgmt_ev_remote_name ev;
2865
2866 memset(&ev, 0, sizeof(ev));
2867
2868 bacpy(&ev.bdaddr, bdaddr);
Brian Gixa68668b2011-08-11 15:49:36 -07002869 ev.status = status;
Johan Hedberga88a9652011-03-30 13:18:12 +03002870 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
2871
2872 return mgmt_event(MGMT_EV_REMOTE_NAME, index, &ev, sizeof(ev), NULL);
2873}
Prabhakaran Mc46230fa2011-11-30 18:11:21 +05302874
2875int mgmt_encrypt_change(u16 index, bdaddr_t *bdaddr, u8 status)
2876{
2877 struct mgmt_ev_encrypt_change ev;
2878
2879 BT_DBG("hci%u", index);
2880
2881 bacpy(&ev.bdaddr, bdaddr);
2882 ev.status = status;
2883
2884 return mgmt_event(MGMT_EV_ENCRYPT_CHANGE, index, &ev, sizeof(ev),
2885 NULL);
2886}
2887
Srinivas Krovvidi0916aed2011-12-20 12:06:34 +05302888int mgmt_remote_class(u16 index, bdaddr_t *bdaddr, u8 dev_class[3])
2889{
2890 struct mgmt_ev_remote_class ev;
2891
2892 memset(&ev, 0, sizeof(ev));
2893
2894 bacpy(&ev.bdaddr, bdaddr);
2895 memcpy(ev.dev_class, dev_class, 3);
2896
2897 return mgmt_event(MGMT_EV_REMOTE_CLASS, index, &ev, sizeof(ev), NULL);
2898}
Srinivas Krovvidid352b262012-01-12 19:46:26 +05302899
2900int mgmt_remote_version(u16 index, bdaddr_t *bdaddr, u8 ver, u16 mnf,
2901 u16 sub_ver)
2902{
2903 struct mgmt_ev_remote_version ev;
2904
2905 memset(&ev, 0, sizeof(ev));
2906
2907 bacpy(&ev.bdaddr, bdaddr);
2908 ev.lmp_ver = ver;
2909 ev.manufacturer = mnf;
2910 ev.lmp_subver = sub_ver;
2911
2912 return mgmt_event(MGMT_EV_REMOTE_VERSION, index, &ev, sizeof(ev), NULL);
2913}