blob: 62055c9a80842e56f57a7a926692f8f1909e7af7 [file] [log] [blame]
Johan Hedberg03811012010-12-08 00:21:06 +02001/*
2 BlueZ - Bluetooth protocol stack for Linux
3 Copyright (C) 2010 Nokia Corporation
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License version 2 as
7 published by the Free Software Foundation;
8
9 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
10 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
11 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
12 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
13 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
18 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
19 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
20 SOFTWARE IS DISCLAIMED.
21*/
22
23/* Bluetooth HCI Management interface */
24
Szymon Janc72359752011-02-17 14:16:32 +010025#include <linux/uaccess.h>
Johan Hedberg03811012010-12-08 00:21:06 +020026#include <asm/unaligned.h>
27
28#include <net/bluetooth/bluetooth.h>
29#include <net/bluetooth/hci_core.h>
30#include <net/bluetooth/mgmt.h>
31
Johan Hedberg02d98122010-12-13 21:07:04 +020032#define MGMT_VERSION 0
33#define MGMT_REVISION 1
34
Johan Hedbergeec8d2b2010-12-16 10:17:38 +020035struct pending_cmd {
36 struct list_head list;
37 __u16 opcode;
38 int index;
Szymon Jancc68fb7f2011-03-22 13:12:19 +010039 void *param;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +020040 struct sock *sk;
Johan Hedberge9a416b2011-02-19 12:05:56 -030041 void *user_data;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +020042};
43
44LIST_HEAD(cmd_list);
45
Szymon Janc4e51eae2011-02-25 19:05:48 +010046static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
Johan Hedbergf7b64e62010-12-13 21:07:06 +020047{
48 struct sk_buff *skb;
49 struct mgmt_hdr *hdr;
50 struct mgmt_ev_cmd_status *ev;
51
Szymon Janc34eb5252011-02-28 14:10:08 +010052 BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status);
Johan Hedbergf7b64e62010-12-13 21:07:06 +020053
54 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_ATOMIC);
55 if (!skb)
56 return -ENOMEM;
57
58 hdr = (void *) skb_put(skb, sizeof(*hdr));
59
60 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
Szymon Janc4e51eae2011-02-25 19:05:48 +010061 hdr->index = cpu_to_le16(index);
Johan Hedbergf7b64e62010-12-13 21:07:06 +020062 hdr->len = cpu_to_le16(sizeof(*ev));
63
64 ev = (void *) skb_put(skb, sizeof(*ev));
65 ev->status = status;
66 put_unaligned_le16(cmd, &ev->opcode);
67
68 if (sock_queue_rcv_skb(sk, skb) < 0)
69 kfree_skb(skb);
70
71 return 0;
72}
73
Szymon Janc4e51eae2011-02-25 19:05:48 +010074static int cmd_complete(struct sock *sk, u16 index, u16 cmd, void *rp,
75 size_t rp_len)
Johan Hedberg02d98122010-12-13 21:07:04 +020076{
77 struct sk_buff *skb;
78 struct mgmt_hdr *hdr;
79 struct mgmt_ev_cmd_complete *ev;
Johan Hedberg02d98122010-12-13 21:07:04 +020080
81 BT_DBG("sock %p", sk);
82
Johan Hedberga38528f2011-01-22 06:46:43 +020083 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + rp_len, GFP_ATOMIC);
Johan Hedberg02d98122010-12-13 21:07:04 +020084 if (!skb)
85 return -ENOMEM;
86
87 hdr = (void *) skb_put(skb, sizeof(*hdr));
Johan Hedberga38528f2011-01-22 06:46:43 +020088
Johan Hedberg02d98122010-12-13 21:07:04 +020089 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
Szymon Janc4e51eae2011-02-25 19:05:48 +010090 hdr->index = cpu_to_le16(index);
Johan Hedberga38528f2011-01-22 06:46:43 +020091 hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +020092
Johan Hedberga38528f2011-01-22 06:46:43 +020093 ev = (void *) skb_put(skb, sizeof(*ev) + rp_len);
94 put_unaligned_le16(cmd, &ev->opcode);
Szymon Janc8020c162011-02-28 14:09:50 +010095
96 if (rp)
97 memcpy(ev->data, rp, rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +020098
99 if (sock_queue_rcv_skb(sk, skb) < 0)
100 kfree_skb(skb);
101
102 return 0;
103}
104
Johan Hedberga38528f2011-01-22 06:46:43 +0200105static int read_version(struct sock *sk)
106{
107 struct mgmt_rp_read_version rp;
108
109 BT_DBG("sock %p", sk);
110
111 rp.version = MGMT_VERSION;
112 put_unaligned_le16(MGMT_REVISION, &rp.revision);
113
Szymon Janc4e51eae2011-02-25 19:05:48 +0100114 return cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, &rp,
115 sizeof(rp));
Johan Hedberga38528f2011-01-22 06:46:43 +0200116}
117
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200118static int read_index_list(struct sock *sk)
119{
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200120 struct mgmt_rp_read_index_list *rp;
121 struct list_head *p;
Johan Hedberga38528f2011-01-22 06:46:43 +0200122 size_t rp_len;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200123 u16 count;
Johan Hedberga38528f2011-01-22 06:46:43 +0200124 int i, err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200125
126 BT_DBG("sock %p", sk);
127
128 read_lock(&hci_dev_list_lock);
129
130 count = 0;
131 list_for_each(p, &hci_dev_list) {
132 count++;
133 }
134
Johan Hedberga38528f2011-01-22 06:46:43 +0200135 rp_len = sizeof(*rp) + (2 * count);
136 rp = kmalloc(rp_len, GFP_ATOMIC);
137 if (!rp) {
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100138 read_unlock(&hci_dev_list_lock);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200139 return -ENOMEM;
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100140 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200141
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200142 put_unaligned_le16(count, &rp->num_controllers);
143
144 i = 0;
145 list_for_each(p, &hci_dev_list) {
146 struct hci_dev *d = list_entry(p, struct hci_dev, list);
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200147
148 hci_del_off_timer(d);
149
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200150 set_bit(HCI_MGMT, &d->flags);
151
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200152 if (test_bit(HCI_SETUP, &d->flags))
153 continue;
154
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200155 put_unaligned_le16(d->id, &rp->index[i++]);
156 BT_DBG("Added hci%u", d->id);
157 }
158
159 read_unlock(&hci_dev_list_lock);
160
Szymon Janc4e51eae2011-02-25 19:05:48 +0100161 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST, rp,
162 rp_len);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200163
Johan Hedberga38528f2011-01-22 06:46:43 +0200164 kfree(rp);
165
166 return err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200167}
168
Szymon Janc4e51eae2011-02-25 19:05:48 +0100169static int read_controller_info(struct sock *sk, u16 index)
Johan Hedberg03811012010-12-08 00:21:06 +0200170{
Johan Hedberga38528f2011-01-22 06:46:43 +0200171 struct mgmt_rp_read_info rp;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200172 struct hci_dev *hdev;
Johan Hedberg03811012010-12-08 00:21:06 +0200173
Szymon Janc4e51eae2011-02-25 19:05:48 +0100174 BT_DBG("sock %p hci%u", sk, index);
Johan Hedberg03811012010-12-08 00:21:06 +0200175
Szymon Janc4e51eae2011-02-25 19:05:48 +0100176 hdev = hci_dev_get(index);
Johan Hedberga38528f2011-01-22 06:46:43 +0200177 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +0100178 return cmd_status(sk, index, MGMT_OP_READ_INFO, ENODEV);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200179
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200180 hci_del_off_timer(hdev);
181
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200182 hci_dev_lock_bh(hdev);
183
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200184 set_bit(HCI_MGMT, &hdev->flags);
185
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200186 memset(&rp, 0, sizeof(rp));
187
Johan Hedberga38528f2011-01-22 06:46:43 +0200188 rp.type = hdev->dev_type;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200189
Johan Hedberga38528f2011-01-22 06:46:43 +0200190 rp.powered = test_bit(HCI_UP, &hdev->flags);
191 rp.connectable = test_bit(HCI_PSCAN, &hdev->flags);
192 rp.discoverable = test_bit(HCI_ISCAN, &hdev->flags);
193 rp.pairable = test_bit(HCI_PSCAN, &hdev->flags);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200194
195 if (test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberga38528f2011-01-22 06:46:43 +0200196 rp.sec_mode = 3;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200197 else if (hdev->ssp_mode > 0)
Johan Hedberga38528f2011-01-22 06:46:43 +0200198 rp.sec_mode = 4;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200199 else
Johan Hedberga38528f2011-01-22 06:46:43 +0200200 rp.sec_mode = 2;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200201
Johan Hedberga38528f2011-01-22 06:46:43 +0200202 bacpy(&rp.bdaddr, &hdev->bdaddr);
203 memcpy(rp.features, hdev->features, 8);
204 memcpy(rp.dev_class, hdev->dev_class, 3);
205 put_unaligned_le16(hdev->manufacturer, &rp.manufacturer);
206 rp.hci_ver = hdev->hci_ver;
207 put_unaligned_le16(hdev->hci_rev, &rp.hci_rev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200208
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200209 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
210
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200211 hci_dev_unlock_bh(hdev);
212 hci_dev_put(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +0200213
Szymon Janc4e51eae2011-02-25 19:05:48 +0100214 return cmd_complete(sk, index, MGMT_OP_READ_INFO, &rp, sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +0200215}
216
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200217static void mgmt_pending_free(struct pending_cmd *cmd)
218{
219 sock_put(cmd->sk);
Szymon Jancc68fb7f2011-03-22 13:12:19 +0100220 kfree(cmd->param);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200221 kfree(cmd);
222}
223
Johan Hedberg366a0332011-02-19 12:05:55 -0300224static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
225 u16 index, void *data, u16 len)
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200226{
227 struct pending_cmd *cmd;
228
229 cmd = kmalloc(sizeof(*cmd), GFP_ATOMIC);
230 if (!cmd)
Johan Hedberg366a0332011-02-19 12:05:55 -0300231 return NULL;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200232
233 cmd->opcode = opcode;
234 cmd->index = index;
235
Szymon Jancc68fb7f2011-03-22 13:12:19 +0100236 cmd->param = kmalloc(len, GFP_ATOMIC);
237 if (!cmd->param) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200238 kfree(cmd);
Johan Hedberg366a0332011-02-19 12:05:55 -0300239 return NULL;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200240 }
241
Szymon Janc8fce6352011-03-22 13:12:20 +0100242 if (data)
243 memcpy(cmd->param, data, len);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200244
245 cmd->sk = sk;
246 sock_hold(sk);
247
248 list_add(&cmd->list, &cmd_list);
249
Johan Hedberg366a0332011-02-19 12:05:55 -0300250 return cmd;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200251}
252
253static void mgmt_pending_foreach(u16 opcode, int index,
254 void (*cb)(struct pending_cmd *cmd, void *data),
255 void *data)
256{
257 struct list_head *p, *n;
258
259 list_for_each_safe(p, n, &cmd_list) {
260 struct pending_cmd *cmd;
261
262 cmd = list_entry(p, struct pending_cmd, list);
263
264 if (cmd->opcode != opcode)
265 continue;
266
267 if (index >= 0 && cmd->index != index)
268 continue;
269
270 cb(cmd, data);
271 }
272}
273
274static struct pending_cmd *mgmt_pending_find(u16 opcode, int index)
275{
276 struct list_head *p;
277
278 list_for_each(p, &cmd_list) {
279 struct pending_cmd *cmd;
280
281 cmd = list_entry(p, struct pending_cmd, list);
282
283 if (cmd->opcode != opcode)
284 continue;
285
286 if (index >= 0 && cmd->index != index)
287 continue;
288
289 return cmd;
290 }
291
292 return NULL;
293}
294
Johan Hedberga664b5b2011-02-19 12:06:02 -0300295static void mgmt_pending_remove(struct pending_cmd *cmd)
Johan Hedberg73f22f62010-12-29 16:00:25 +0200296{
Johan Hedberg73f22f62010-12-29 16:00:25 +0200297 list_del(&cmd->list);
298 mgmt_pending_free(cmd);
299}
300
Szymon Janc4e51eae2011-02-25 19:05:48 +0100301static int set_powered(struct sock *sk, u16 index, unsigned char *data, u16 len)
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200302{
Johan Hedberg72a734e2010-12-30 00:38:22 +0200303 struct mgmt_mode *cp;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200304 struct hci_dev *hdev;
Johan Hedberg366a0332011-02-19 12:05:55 -0300305 struct pending_cmd *cmd;
Johan Hedberg366a0332011-02-19 12:05:55 -0300306 int err, up;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200307
308 cp = (void *) data;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200309
Szymon Janc4e51eae2011-02-25 19:05:48 +0100310 BT_DBG("request for hci%u", index);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200311
Szymon Jancbdce7ba2011-02-25 19:05:49 +0100312 if (len != sizeof(*cp))
313 return cmd_status(sk, index, MGMT_OP_SET_POWERED, EINVAL);
314
Szymon Janc4e51eae2011-02-25 19:05:48 +0100315 hdev = hci_dev_get(index);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200316 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +0100317 return cmd_status(sk, index, MGMT_OP_SET_POWERED, ENODEV);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200318
319 hci_dev_lock_bh(hdev);
320
321 up = test_bit(HCI_UP, &hdev->flags);
Johan Hedberg72a734e2010-12-30 00:38:22 +0200322 if ((cp->val && up) || (!cp->val && !up)) {
Szymon Janc4e51eae2011-02-25 19:05:48 +0100323 err = cmd_status(sk, index, MGMT_OP_SET_POWERED, EALREADY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200324 goto failed;
325 }
326
Szymon Janc4e51eae2011-02-25 19:05:48 +0100327 if (mgmt_pending_find(MGMT_OP_SET_POWERED, index)) {
328 err = cmd_status(sk, index, MGMT_OP_SET_POWERED, EBUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200329 goto failed;
330 }
331
Szymon Janc4e51eae2011-02-25 19:05:48 +0100332 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, index, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -0300333 if (!cmd) {
334 err = -ENOMEM;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200335 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -0300336 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200337
Johan Hedberg72a734e2010-12-30 00:38:22 +0200338 if (cp->val)
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200339 queue_work(hdev->workqueue, &hdev->power_on);
340 else
341 queue_work(hdev->workqueue, &hdev->power_off);
342
Johan Hedberg366a0332011-02-19 12:05:55 -0300343 err = 0;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200344
345failed:
346 hci_dev_unlock_bh(hdev);
347 hci_dev_put(hdev);
Johan Hedberg366a0332011-02-19 12:05:55 -0300348 return err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200349}
350
Szymon Janc4e51eae2011-02-25 19:05:48 +0100351static int set_discoverable(struct sock *sk, u16 index, unsigned char *data,
352 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +0200353{
Johan Hedberg72a734e2010-12-30 00:38:22 +0200354 struct mgmt_mode *cp;
Johan Hedberg73f22f62010-12-29 16:00:25 +0200355 struct hci_dev *hdev;
Johan Hedberg366a0332011-02-19 12:05:55 -0300356 struct pending_cmd *cmd;
Johan Hedberg73f22f62010-12-29 16:00:25 +0200357 u8 scan;
358 int err;
359
360 cp = (void *) data;
Johan Hedberg73f22f62010-12-29 16:00:25 +0200361
Szymon Janc4e51eae2011-02-25 19:05:48 +0100362 BT_DBG("request for hci%u", index);
Johan Hedberg73f22f62010-12-29 16:00:25 +0200363
Szymon Jancbdce7ba2011-02-25 19:05:49 +0100364 if (len != sizeof(*cp))
365 return cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, EINVAL);
366
Szymon Janc4e51eae2011-02-25 19:05:48 +0100367 hdev = hci_dev_get(index);
Johan Hedberg73f22f62010-12-29 16:00:25 +0200368 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +0100369 return cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, ENODEV);
Johan Hedberg73f22f62010-12-29 16:00:25 +0200370
371 hci_dev_lock_bh(hdev);
372
373 if (!test_bit(HCI_UP, &hdev->flags)) {
Szymon Janc4e51eae2011-02-25 19:05:48 +0100374 err = cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, ENETDOWN);
Johan Hedberg73f22f62010-12-29 16:00:25 +0200375 goto failed;
376 }
377
Szymon Janc4e51eae2011-02-25 19:05:48 +0100378 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, index) ||
379 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, index)) {
380 err = cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, EBUSY);
Johan Hedberg73f22f62010-12-29 16:00:25 +0200381 goto failed;
382 }
383
Johan Hedberg72a734e2010-12-30 00:38:22 +0200384 if (cp->val == test_bit(HCI_ISCAN, &hdev->flags) &&
Johan Hedberg73f22f62010-12-29 16:00:25 +0200385 test_bit(HCI_PSCAN, &hdev->flags)) {
Szymon Janc4e51eae2011-02-25 19:05:48 +0100386 err = cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, EALREADY);
Johan Hedberg73f22f62010-12-29 16:00:25 +0200387 goto failed;
388 }
389
Szymon Janc4e51eae2011-02-25 19:05:48 +0100390 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, index, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -0300391 if (!cmd) {
392 err = -ENOMEM;
Johan Hedberg73f22f62010-12-29 16:00:25 +0200393 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -0300394 }
Johan Hedberg73f22f62010-12-29 16:00:25 +0200395
396 scan = SCAN_PAGE;
397
Johan Hedberg72a734e2010-12-30 00:38:22 +0200398 if (cp->val)
Johan Hedberg73f22f62010-12-29 16:00:25 +0200399 scan |= SCAN_INQUIRY;
400
401 err = hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
402 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -0300403 mgmt_pending_remove(cmd);
Johan Hedberg73f22f62010-12-29 16:00:25 +0200404
405failed:
406 hci_dev_unlock_bh(hdev);
407 hci_dev_put(hdev);
408
409 return err;
410}
411
Szymon Janc4e51eae2011-02-25 19:05:48 +0100412static int set_connectable(struct sock *sk, u16 index, unsigned char *data,
413 u16 len)
Johan Hedberg9fbcbb42010-12-30 00:18:33 +0200414{
Johan Hedberg72a734e2010-12-30 00:38:22 +0200415 struct mgmt_mode *cp;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +0200416 struct hci_dev *hdev;
Johan Hedberg366a0332011-02-19 12:05:55 -0300417 struct pending_cmd *cmd;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +0200418 u8 scan;
419 int err;
420
421 cp = (void *) data;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +0200422
Szymon Janc4e51eae2011-02-25 19:05:48 +0100423 BT_DBG("request for hci%u", index);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +0200424
Szymon Jancbdce7ba2011-02-25 19:05:49 +0100425 if (len != sizeof(*cp))
426 return cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, EINVAL);
427
Szymon Janc4e51eae2011-02-25 19:05:48 +0100428 hdev = hci_dev_get(index);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +0200429 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +0100430 return cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, ENODEV);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +0200431
432 hci_dev_lock_bh(hdev);
433
434 if (!test_bit(HCI_UP, &hdev->flags)) {
Szymon Janc4e51eae2011-02-25 19:05:48 +0100435 err = cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, ENETDOWN);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +0200436 goto failed;
437 }
438
Szymon Janc4e51eae2011-02-25 19:05:48 +0100439 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, index) ||
440 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, index)) {
441 err = cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, EBUSY);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +0200442 goto failed;
443 }
444
Johan Hedberg72a734e2010-12-30 00:38:22 +0200445 if (cp->val == test_bit(HCI_PSCAN, &hdev->flags)) {
Szymon Janc4e51eae2011-02-25 19:05:48 +0100446 err = cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, EALREADY);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +0200447 goto failed;
448 }
449
Szymon Janc4e51eae2011-02-25 19:05:48 +0100450 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, index, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -0300451 if (!cmd) {
452 err = -ENOMEM;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +0200453 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -0300454 }
Johan Hedberg9fbcbb42010-12-30 00:18:33 +0200455
Johan Hedberg72a734e2010-12-30 00:38:22 +0200456 if (cp->val)
Johan Hedberg9fbcbb42010-12-30 00:18:33 +0200457 scan = SCAN_PAGE;
458 else
459 scan = 0;
460
461 err = hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
462 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -0300463 mgmt_pending_remove(cmd);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +0200464
465failed:
466 hci_dev_unlock_bh(hdev);
467 hci_dev_put(hdev);
468
469 return err;
470}
471
Szymon Janc4e51eae2011-02-25 19:05:48 +0100472static int mgmt_event(u16 event, u16 index, void *data, u16 data_len,
473 struct sock *skip_sk)
Johan Hedbergc542a062011-01-26 13:11:03 +0200474{
475 struct sk_buff *skb;
476 struct mgmt_hdr *hdr;
477
478 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_ATOMIC);
479 if (!skb)
480 return -ENOMEM;
481
482 bt_cb(skb)->channel = HCI_CHANNEL_CONTROL;
483
484 hdr = (void *) skb_put(skb, sizeof(*hdr));
485 hdr->opcode = cpu_to_le16(event);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100486 hdr->index = cpu_to_le16(index);
Johan Hedbergc542a062011-01-26 13:11:03 +0200487 hdr->len = cpu_to_le16(data_len);
488
Szymon Janc4e51eae2011-02-25 19:05:48 +0100489 if (data)
490 memcpy(skb_put(skb, data_len), data, data_len);
Johan Hedbergc542a062011-01-26 13:11:03 +0200491
492 hci_send_to_sock(NULL, skb, skip_sk);
493 kfree_skb(skb);
494
495 return 0;
496}
497
Johan Hedberg053f0212011-01-26 13:07:10 +0200498static int send_mode_rsp(struct sock *sk, u16 opcode, u16 index, u8 val)
499{
Johan Hedberga38528f2011-01-22 06:46:43 +0200500 struct mgmt_mode rp;
Johan Hedberg053f0212011-01-26 13:07:10 +0200501
Johan Hedberga38528f2011-01-22 06:46:43 +0200502 rp.val = val;
Johan Hedberg053f0212011-01-26 13:07:10 +0200503
Szymon Janc4e51eae2011-02-25 19:05:48 +0100504 return cmd_complete(sk, index, opcode, &rp, sizeof(rp));
Johan Hedberg053f0212011-01-26 13:07:10 +0200505}
506
Szymon Janc4e51eae2011-02-25 19:05:48 +0100507static int set_pairable(struct sock *sk, u16 index, unsigned char *data,
508 u16 len)
Johan Hedbergc542a062011-01-26 13:11:03 +0200509{
510 struct mgmt_mode *cp, ev;
511 struct hci_dev *hdev;
Johan Hedbergc542a062011-01-26 13:11:03 +0200512 int err;
513
514 cp = (void *) data;
Johan Hedbergc542a062011-01-26 13:11:03 +0200515
Szymon Janc4e51eae2011-02-25 19:05:48 +0100516 BT_DBG("request for hci%u", index);
Johan Hedbergc542a062011-01-26 13:11:03 +0200517
Szymon Jancbdce7ba2011-02-25 19:05:49 +0100518 if (len != sizeof(*cp))
519 return cmd_status(sk, index, MGMT_OP_SET_PAIRABLE, EINVAL);
520
Szymon Janc4e51eae2011-02-25 19:05:48 +0100521 hdev = hci_dev_get(index);
Johan Hedbergc542a062011-01-26 13:11:03 +0200522 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +0100523 return cmd_status(sk, index, MGMT_OP_SET_PAIRABLE, ENODEV);
Johan Hedbergc542a062011-01-26 13:11:03 +0200524
525 hci_dev_lock_bh(hdev);
526
527 if (cp->val)
528 set_bit(HCI_PAIRABLE, &hdev->flags);
529 else
530 clear_bit(HCI_PAIRABLE, &hdev->flags);
531
Szymon Janc4e51eae2011-02-25 19:05:48 +0100532 err = send_mode_rsp(sk, MGMT_OP_SET_PAIRABLE, index, cp->val);
Johan Hedbergc542a062011-01-26 13:11:03 +0200533 if (err < 0)
534 goto failed;
535
Johan Hedbergc542a062011-01-26 13:11:03 +0200536 ev.val = cp->val;
537
Szymon Janc4e51eae2011-02-25 19:05:48 +0100538 err = mgmt_event(MGMT_EV_PAIRABLE, index, &ev, sizeof(ev), sk);
Johan Hedbergc542a062011-01-26 13:11:03 +0200539
540failed:
541 hci_dev_unlock_bh(hdev);
542 hci_dev_put(hdev);
543
544 return err;
545}
546
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300547#define EIR_FLAGS 0x01 /* flags */
548#define EIR_UUID16_SOME 0x02 /* 16-bit UUID, more available */
549#define EIR_UUID16_ALL 0x03 /* 16-bit UUID, all listed */
550#define EIR_UUID32_SOME 0x04 /* 32-bit UUID, more available */
551#define EIR_UUID32_ALL 0x05 /* 32-bit UUID, all listed */
552#define EIR_UUID128_SOME 0x06 /* 128-bit UUID, more available */
553#define EIR_UUID128_ALL 0x07 /* 128-bit UUID, all listed */
554#define EIR_NAME_SHORT 0x08 /* shortened local name */
555#define EIR_NAME_COMPLETE 0x09 /* complete local name */
556#define EIR_TX_POWER 0x0A /* transmit power level */
557#define EIR_DEVICE_ID 0x10 /* device ID */
558
559#define PNP_INFO_SVCLASS_ID 0x1200
560
561static u8 bluetooth_base_uuid[] = {
562 0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80,
563 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
564};
565
566static u16 get_uuid16(u8 *uuid128)
567{
568 u32 val;
569 int i;
570
571 for (i = 0; i < 12; i++) {
572 if (bluetooth_base_uuid[i] != uuid128[i])
573 return 0;
574 }
575
576 memcpy(&val, &uuid128[12], 4);
577
578 val = le32_to_cpu(val);
579 if (val > 0xffff)
580 return 0;
581
582 return (u16) val;
583}
584
585static void create_eir(struct hci_dev *hdev, u8 *data)
586{
587 u8 *ptr = data;
588 u16 eir_len = 0;
589 u16 uuid16_list[HCI_MAX_EIR_LENGTH / sizeof(u16)];
590 int i, truncated = 0;
591 struct list_head *p;
592 size_t name_len;
593
594 name_len = strlen(hdev->dev_name);
595
596 if (name_len > 0) {
597 /* EIR Data type */
598 if (name_len > 48) {
599 name_len = 48;
600 ptr[1] = EIR_NAME_SHORT;
601 } else
602 ptr[1] = EIR_NAME_COMPLETE;
603
604 /* EIR Data length */
605 ptr[0] = name_len + 1;
606
607 memcpy(ptr + 2, hdev->dev_name, name_len);
608
609 eir_len += (name_len + 2);
610 ptr += (name_len + 2);
611 }
612
613 memset(uuid16_list, 0, sizeof(uuid16_list));
614
615 /* Group all UUID16 types */
616 list_for_each(p, &hdev->uuids) {
617 struct bt_uuid *uuid = list_entry(p, struct bt_uuid, list);
618 u16 uuid16;
619
620 uuid16 = get_uuid16(uuid->uuid);
621 if (uuid16 == 0)
622 return;
623
624 if (uuid16 < 0x1100)
625 continue;
626
627 if (uuid16 == PNP_INFO_SVCLASS_ID)
628 continue;
629
630 /* Stop if not enough space to put next UUID */
631 if (eir_len + 2 + sizeof(u16) > HCI_MAX_EIR_LENGTH) {
632 truncated = 1;
633 break;
634 }
635
636 /* Check for duplicates */
637 for (i = 0; uuid16_list[i] != 0; i++)
638 if (uuid16_list[i] == uuid16)
639 break;
640
641 if (uuid16_list[i] == 0) {
642 uuid16_list[i] = uuid16;
643 eir_len += sizeof(u16);
644 }
645 }
646
647 if (uuid16_list[0] != 0) {
648 u8 *length = ptr;
649
650 /* EIR Data type */
651 ptr[1] = truncated ? EIR_UUID16_SOME : EIR_UUID16_ALL;
652
653 ptr += 2;
654 eir_len += 2;
655
656 for (i = 0; uuid16_list[i] != 0; i++) {
657 *ptr++ = (uuid16_list[i] & 0x00ff);
658 *ptr++ = (uuid16_list[i] & 0xff00) >> 8;
659 }
660
661 /* EIR Data length */
662 *length = (i * sizeof(u16)) + 1;
663 }
664}
665
666static int update_eir(struct hci_dev *hdev)
667{
668 struct hci_cp_write_eir cp;
669
670 if (!(hdev->features[6] & LMP_EXT_INQ))
671 return 0;
672
673 if (hdev->ssp_mode == 0)
674 return 0;
675
676 if (test_bit(HCI_SERVICE_CACHE, &hdev->flags))
677 return 0;
678
679 memset(&cp, 0, sizeof(cp));
680
681 create_eir(hdev, cp.data);
682
683 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
684 return 0;
685
686 memcpy(hdev->eir, cp.data, sizeof(cp.data));
687
688 return hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
689}
690
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200691static u8 get_service_classes(struct hci_dev *hdev)
692{
693 struct list_head *p;
694 u8 val = 0;
695
696 list_for_each(p, &hdev->uuids) {
697 struct bt_uuid *uuid = list_entry(p, struct bt_uuid, list);
698
699 val |= uuid->svc_hint;
700 }
701
702 return val;
703}
704
705static int update_class(struct hci_dev *hdev)
706{
707 u8 cod[3];
708
709 BT_DBG("%s", hdev->name);
710
711 if (test_bit(HCI_SERVICE_CACHE, &hdev->flags))
712 return 0;
713
714 cod[0] = hdev->minor_class;
715 cod[1] = hdev->major_class;
716 cod[2] = get_service_classes(hdev);
717
718 if (memcmp(cod, hdev->dev_class, 3) == 0)
719 return 0;
720
721 return hci_send_cmd(hdev, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
722}
723
Szymon Janc4e51eae2011-02-25 19:05:48 +0100724static int add_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +0200725{
726 struct mgmt_cp_add_uuid *cp;
727 struct hci_dev *hdev;
728 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +0200729 int err;
730
731 cp = (void *) data;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +0200732
Szymon Janc4e51eae2011-02-25 19:05:48 +0100733 BT_DBG("request for hci%u", index);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +0200734
Szymon Jancbdce7ba2011-02-25 19:05:49 +0100735 if (len != sizeof(*cp))
736 return cmd_status(sk, index, MGMT_OP_ADD_UUID, EINVAL);
737
Szymon Janc4e51eae2011-02-25 19:05:48 +0100738 hdev = hci_dev_get(index);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +0200739 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +0100740 return cmd_status(sk, index, MGMT_OP_ADD_UUID, ENODEV);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +0200741
742 hci_dev_lock_bh(hdev);
743
744 uuid = kmalloc(sizeof(*uuid), GFP_ATOMIC);
745 if (!uuid) {
746 err = -ENOMEM;
747 goto failed;
748 }
749
750 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200751 uuid->svc_hint = cp->svc_hint;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +0200752
753 list_add(&uuid->list, &hdev->uuids);
754
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200755 err = update_class(hdev);
756 if (err < 0)
757 goto failed;
758
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300759 err = update_eir(hdev);
760 if (err < 0)
761 goto failed;
762
Szymon Janc4e51eae2011-02-25 19:05:48 +0100763 err = cmd_complete(sk, index, MGMT_OP_ADD_UUID, NULL, 0);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +0200764
765failed:
766 hci_dev_unlock_bh(hdev);
767 hci_dev_put(hdev);
768
769 return err;
770}
771
Szymon Janc4e51eae2011-02-25 19:05:48 +0100772static int remove_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +0200773{
774 struct list_head *p, *n;
Szymon Janc779cb852011-02-25 19:05:47 +0100775 struct mgmt_cp_remove_uuid *cp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +0200776 struct hci_dev *hdev;
777 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 +0200778 int err, found;
779
780 cp = (void *) data;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +0200781
Szymon Janc4e51eae2011-02-25 19:05:48 +0100782 BT_DBG("request for hci%u", index);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +0200783
Szymon Jancbdce7ba2011-02-25 19:05:49 +0100784 if (len != sizeof(*cp))
785 return cmd_status(sk, index, MGMT_OP_REMOVE_UUID, EINVAL);
786
Szymon Janc4e51eae2011-02-25 19:05:48 +0100787 hdev = hci_dev_get(index);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +0200788 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +0100789 return cmd_status(sk, index, MGMT_OP_REMOVE_UUID, ENODEV);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +0200790
791 hci_dev_lock_bh(hdev);
792
793 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
794 err = hci_uuids_clear(hdev);
795 goto unlock;
796 }
797
798 found = 0;
799
800 list_for_each_safe(p, n, &hdev->uuids) {
801 struct bt_uuid *match = list_entry(p, struct bt_uuid, list);
802
803 if (memcmp(match->uuid, cp->uuid, 16) != 0)
804 continue;
805
806 list_del(&match->list);
807 found++;
808 }
809
810 if (found == 0) {
Szymon Janc4e51eae2011-02-25 19:05:48 +0100811 err = cmd_status(sk, index, MGMT_OP_REMOVE_UUID, ENOENT);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +0200812 goto unlock;
813 }
814
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200815 err = update_class(hdev);
816 if (err < 0)
817 goto unlock;
818
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300819 err = update_eir(hdev);
820 if (err < 0)
821 goto unlock;
822
Szymon Janc4e51eae2011-02-25 19:05:48 +0100823 err = cmd_complete(sk, index, MGMT_OP_REMOVE_UUID, NULL, 0);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +0200824
825unlock:
826 hci_dev_unlock_bh(hdev);
827 hci_dev_put(hdev);
828
829 return err;
830}
831
Szymon Janc4e51eae2011-02-25 19:05:48 +0100832static int set_dev_class(struct sock *sk, u16 index, unsigned char *data,
833 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200834{
835 struct hci_dev *hdev;
836 struct mgmt_cp_set_dev_class *cp;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200837 int err;
838
839 cp = (void *) data;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200840
Szymon Janc4e51eae2011-02-25 19:05:48 +0100841 BT_DBG("request for hci%u", index);
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200842
Szymon Jancbdce7ba2011-02-25 19:05:49 +0100843 if (len != sizeof(*cp))
844 return cmd_status(sk, index, MGMT_OP_SET_DEV_CLASS, EINVAL);
845
Szymon Janc4e51eae2011-02-25 19:05:48 +0100846 hdev = hci_dev_get(index);
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200847 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +0100848 return cmd_status(sk, index, MGMT_OP_SET_DEV_CLASS, ENODEV);
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200849
850 hci_dev_lock_bh(hdev);
851
852 hdev->major_class = cp->major;
853 hdev->minor_class = cp->minor;
854
855 err = update_class(hdev);
856
857 if (err == 0)
Szymon Janc4e51eae2011-02-25 19:05:48 +0100858 err = cmd_complete(sk, index, MGMT_OP_SET_DEV_CLASS, NULL, 0);
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200859
860 hci_dev_unlock_bh(hdev);
861 hci_dev_put(hdev);
862
863 return err;
864}
865
Szymon Janc4e51eae2011-02-25 19:05:48 +0100866static int set_service_cache(struct sock *sk, u16 index, unsigned char *data,
867 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200868{
869 struct hci_dev *hdev;
870 struct mgmt_cp_set_service_cache *cp;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200871 int err;
872
873 cp = (void *) data;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200874
Szymon Jancbdce7ba2011-02-25 19:05:49 +0100875 if (len != sizeof(*cp))
Szymon Jancb8534e0f2011-03-01 16:55:34 +0100876 return cmd_status(sk, index, MGMT_OP_SET_SERVICE_CACHE, EINVAL);
Szymon Jancbdce7ba2011-02-25 19:05:49 +0100877
Szymon Janc4e51eae2011-02-25 19:05:48 +0100878 hdev = hci_dev_get(index);
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200879 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +0100880 return cmd_status(sk, index, MGMT_OP_SET_SERVICE_CACHE, ENODEV);
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200881
882 hci_dev_lock_bh(hdev);
883
Szymon Janc4e51eae2011-02-25 19:05:48 +0100884 BT_DBG("hci%u enable %d", index, cp->enable);
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200885
886 if (cp->enable) {
887 set_bit(HCI_SERVICE_CACHE, &hdev->flags);
888 err = 0;
889 } else {
890 clear_bit(HCI_SERVICE_CACHE, &hdev->flags);
891 err = update_class(hdev);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300892 if (err == 0)
893 err = update_eir(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200894 }
895
896 if (err == 0)
Szymon Janc4e51eae2011-02-25 19:05:48 +0100897 err = cmd_complete(sk, index, MGMT_OP_SET_SERVICE_CACHE, NULL,
898 0);
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200899
900 hci_dev_unlock_bh(hdev);
901 hci_dev_put(hdev);
902
903 return err;
904}
905
Szymon Janc4e51eae2011-02-25 19:05:48 +0100906static int load_keys(struct sock *sk, u16 index, unsigned char *data, u16 len)
Johan Hedberg55ed8ca2011-01-17 14:41:05 +0200907{
908 struct hci_dev *hdev;
909 struct mgmt_cp_load_keys *cp;
Szymon Janc4e51eae2011-02-25 19:05:48 +0100910 u16 key_count, expected_len;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +0200911 int i;
912
913 cp = (void *) data;
Szymon Jancbdce7ba2011-02-25 19:05:49 +0100914
915 if (len < sizeof(*cp))
916 return -EINVAL;
917
Johan Hedberg55ed8ca2011-01-17 14:41:05 +0200918 key_count = get_unaligned_le16(&cp->key_count);
919
920 expected_len = sizeof(*cp) + key_count * sizeof(struct mgmt_key_info);
921 if (expected_len != len) {
922 BT_ERR("load_keys: expected %u bytes, got %u bytes",
923 len, expected_len);
924 return -EINVAL;
925 }
926
Szymon Janc4e51eae2011-02-25 19:05:48 +0100927 hdev = hci_dev_get(index);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +0200928 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +0100929 return cmd_status(sk, index, MGMT_OP_LOAD_KEYS, ENODEV);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +0200930
Szymon Janc4e51eae2011-02-25 19:05:48 +0100931 BT_DBG("hci%u debug_keys %u key_count %u", index, cp->debug_keys,
Johan Hedberg55ed8ca2011-01-17 14:41:05 +0200932 key_count);
933
934 hci_dev_lock_bh(hdev);
935
936 hci_link_keys_clear(hdev);
937
938 set_bit(HCI_LINK_KEYS, &hdev->flags);
939
940 if (cp->debug_keys)
941 set_bit(HCI_DEBUG_KEYS, &hdev->flags);
942 else
943 clear_bit(HCI_DEBUG_KEYS, &hdev->flags);
944
945 for (i = 0; i < key_count; i++) {
946 struct mgmt_key_info *key = &cp->keys[i];
947
948 hci_add_link_key(hdev, 0, &key->bdaddr, key->val, key->type,
949 key->pin_len);
950 }
951
952 hci_dev_unlock_bh(hdev);
953 hci_dev_put(hdev);
954
955 return 0;
956}
957
Szymon Janc4e51eae2011-02-25 19:05:48 +0100958static int remove_key(struct sock *sk, u16 index, unsigned char *data, u16 len)
Johan Hedberg55ed8ca2011-01-17 14:41:05 +0200959{
960 struct hci_dev *hdev;
961 struct mgmt_cp_remove_key *cp;
962 struct hci_conn *conn;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +0200963 int err;
964
965 cp = (void *) data;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +0200966
Szymon Jancbdce7ba2011-02-25 19:05:49 +0100967 if (len != sizeof(*cp))
968 return cmd_status(sk, index, MGMT_OP_REMOVE_KEY, EINVAL);
969
Szymon Janc4e51eae2011-02-25 19:05:48 +0100970 hdev = hci_dev_get(index);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +0200971 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +0100972 return cmd_status(sk, index, MGMT_OP_REMOVE_KEY, ENODEV);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +0200973
974 hci_dev_lock_bh(hdev);
975
976 err = hci_remove_link_key(hdev, &cp->bdaddr);
977 if (err < 0) {
Szymon Janc4e51eae2011-02-25 19:05:48 +0100978 err = cmd_status(sk, index, MGMT_OP_REMOVE_KEY, -err);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +0200979 goto unlock;
980 }
981
982 err = 0;
983
984 if (!test_bit(HCI_UP, &hdev->flags) || !cp->disconnect)
985 goto unlock;
986
987 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
988 if (conn) {
989 struct hci_cp_disconnect dc;
990
991 put_unaligned_le16(conn->handle, &dc.handle);
992 dc.reason = 0x13; /* Remote User Terminated Connection */
993 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, 0, NULL);
994 }
995
996unlock:
997 hci_dev_unlock_bh(hdev);
998 hci_dev_put(hdev);
999
1000 return err;
1001}
1002
Szymon Janc4e51eae2011-02-25 19:05:48 +01001003static int disconnect(struct sock *sk, u16 index, unsigned char *data, u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02001004{
1005 struct hci_dev *hdev;
1006 struct mgmt_cp_disconnect *cp;
1007 struct hci_cp_disconnect dc;
Johan Hedberg366a0332011-02-19 12:05:55 -03001008 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02001009 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02001010 int err;
1011
1012 BT_DBG("");
1013
1014 cp = (void *) data;
Johan Hedberg8962ee72011-01-20 12:40:27 +02001015
Szymon Jancbdce7ba2011-02-25 19:05:49 +01001016 if (len != sizeof(*cp))
1017 return cmd_status(sk, index, MGMT_OP_DISCONNECT, EINVAL);
1018
Szymon Janc4e51eae2011-02-25 19:05:48 +01001019 hdev = hci_dev_get(index);
Johan Hedberg8962ee72011-01-20 12:40:27 +02001020 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +01001021 return cmd_status(sk, index, MGMT_OP_DISCONNECT, ENODEV);
Johan Hedberg8962ee72011-01-20 12:40:27 +02001022
1023 hci_dev_lock_bh(hdev);
1024
1025 if (!test_bit(HCI_UP, &hdev->flags)) {
Szymon Janc4e51eae2011-02-25 19:05:48 +01001026 err = cmd_status(sk, index, MGMT_OP_DISCONNECT, ENETDOWN);
Johan Hedberg8962ee72011-01-20 12:40:27 +02001027 goto failed;
1028 }
1029
Szymon Janc4e51eae2011-02-25 19:05:48 +01001030 if (mgmt_pending_find(MGMT_OP_DISCONNECT, index)) {
1031 err = cmd_status(sk, index, MGMT_OP_DISCONNECT, EBUSY);
Johan Hedberg8962ee72011-01-20 12:40:27 +02001032 goto failed;
1033 }
1034
1035 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
1036 if (!conn) {
Szymon Janc4e51eae2011-02-25 19:05:48 +01001037 err = cmd_status(sk, index, MGMT_OP_DISCONNECT, ENOTCONN);
Johan Hedberg8962ee72011-01-20 12:40:27 +02001038 goto failed;
1039 }
1040
Szymon Janc4e51eae2011-02-25 19:05:48 +01001041 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, index, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03001042 if (!cmd) {
1043 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02001044 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03001045 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02001046
1047 put_unaligned_le16(conn->handle, &dc.handle);
1048 dc.reason = 0x13; /* Remote User Terminated Connection */
1049
1050 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1051 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03001052 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02001053
1054failed:
1055 hci_dev_unlock_bh(hdev);
1056 hci_dev_put(hdev);
1057
1058 return err;
1059}
1060
Szymon Janc8ce62842011-03-01 16:55:32 +01001061static int get_connections(struct sock *sk, u16 index)
Johan Hedberg2784eb42011-01-21 13:56:35 +02001062{
Johan Hedberg2784eb42011-01-21 13:56:35 +02001063 struct mgmt_rp_get_connections *rp;
1064 struct hci_dev *hdev;
1065 struct list_head *p;
Johan Hedberga38528f2011-01-22 06:46:43 +02001066 size_t rp_len;
Szymon Janc4e51eae2011-02-25 19:05:48 +01001067 u16 count;
Johan Hedberg2784eb42011-01-21 13:56:35 +02001068 int i, err;
1069
1070 BT_DBG("");
1071
Szymon Janc4e51eae2011-02-25 19:05:48 +01001072 hdev = hci_dev_get(index);
Johan Hedberg2784eb42011-01-21 13:56:35 +02001073 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +01001074 return cmd_status(sk, index, MGMT_OP_GET_CONNECTIONS, ENODEV);
Johan Hedberg2784eb42011-01-21 13:56:35 +02001075
1076 hci_dev_lock_bh(hdev);
1077
1078 count = 0;
1079 list_for_each(p, &hdev->conn_hash.list) {
1080 count++;
1081 }
1082
Johan Hedberga38528f2011-01-22 06:46:43 +02001083 rp_len = sizeof(*rp) + (count * sizeof(bdaddr_t));
1084 rp = kmalloc(rp_len, GFP_ATOMIC);
1085 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02001086 err = -ENOMEM;
1087 goto unlock;
1088 }
1089
Johan Hedberg2784eb42011-01-21 13:56:35 +02001090 put_unaligned_le16(count, &rp->conn_count);
1091
1092 read_lock(&hci_dev_list_lock);
1093
1094 i = 0;
1095 list_for_each(p, &hdev->conn_hash.list) {
1096 struct hci_conn *c = list_entry(p, struct hci_conn, list);
1097
1098 bacpy(&rp->conn[i++], &c->dst);
1099 }
1100
1101 read_unlock(&hci_dev_list_lock);
1102
Szymon Janc4e51eae2011-02-25 19:05:48 +01001103 err = cmd_complete(sk, index, MGMT_OP_GET_CONNECTIONS, rp, rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02001104
1105unlock:
Johan Hedberga38528f2011-01-22 06:46:43 +02001106 kfree(rp);
Johan Hedberg2784eb42011-01-21 13:56:35 +02001107 hci_dev_unlock_bh(hdev);
1108 hci_dev_put(hdev);
1109 return err;
1110}
1111
Szymon Janc4e51eae2011-02-25 19:05:48 +01001112static int pin_code_reply(struct sock *sk, u16 index, unsigned char *data,
1113 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02001114{
1115 struct hci_dev *hdev;
1116 struct mgmt_cp_pin_code_reply *cp;
1117 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03001118 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02001119 int err;
1120
1121 BT_DBG("");
1122
1123 cp = (void *) data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02001124
Szymon Jancbdce7ba2011-02-25 19:05:49 +01001125 if (len != sizeof(*cp))
1126 return cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, EINVAL);
1127
Szymon Janc4e51eae2011-02-25 19:05:48 +01001128 hdev = hci_dev_get(index);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001129 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +01001130 return cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, ENODEV);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001131
1132 hci_dev_lock_bh(hdev);
1133
1134 if (!test_bit(HCI_UP, &hdev->flags)) {
Szymon Janc4e51eae2011-02-25 19:05:48 +01001135 err = cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, ENETDOWN);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001136 goto failed;
1137 }
1138
Szymon Janc4e51eae2011-02-25 19:05:48 +01001139 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, index, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03001140 if (!cmd) {
1141 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02001142 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03001143 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02001144
1145 bacpy(&reply.bdaddr, &cp->bdaddr);
1146 reply.pin_len = cp->pin_len;
1147 memcpy(reply.pin_code, cp->pin_code, 16);
1148
1149 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
1150 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03001151 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001152
1153failed:
1154 hci_dev_unlock_bh(hdev);
1155 hci_dev_put(hdev);
1156
1157 return err;
1158}
1159
Szymon Janc4e51eae2011-02-25 19:05:48 +01001160static int pin_code_neg_reply(struct sock *sk, u16 index, unsigned char *data,
1161 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02001162{
1163 struct hci_dev *hdev;
1164 struct mgmt_cp_pin_code_neg_reply *cp;
Johan Hedberg366a0332011-02-19 12:05:55 -03001165 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02001166 int err;
1167
1168 BT_DBG("");
1169
1170 cp = (void *) data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02001171
Szymon Jancbdce7ba2011-02-25 19:05:49 +01001172 if (len != sizeof(*cp))
1173 return cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY,
1174 EINVAL);
1175
Szymon Janc4e51eae2011-02-25 19:05:48 +01001176 hdev = hci_dev_get(index);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001177 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +01001178 return cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY,
1179 ENODEV);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001180
1181 hci_dev_lock_bh(hdev);
1182
1183 if (!test_bit(HCI_UP, &hdev->flags)) {
Szymon Janc4e51eae2011-02-25 19:05:48 +01001184 err = cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY,
1185 ENETDOWN);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001186 goto failed;
1187 }
1188
Szymon Janc4e51eae2011-02-25 19:05:48 +01001189 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, index,
Johan Hedberg980e1a52011-01-22 06:10:07 +02001190 data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03001191 if (!cmd) {
1192 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02001193 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03001194 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02001195
Szymon Janc3cf2a4f2011-03-01 16:55:33 +01001196 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, sizeof(cp->bdaddr),
Johan Hedberg980e1a52011-01-22 06:10:07 +02001197 &cp->bdaddr);
1198 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03001199 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001200
1201failed:
1202 hci_dev_unlock_bh(hdev);
1203 hci_dev_put(hdev);
1204
1205 return err;
1206}
1207
Szymon Janc4e51eae2011-02-25 19:05:48 +01001208static int set_io_capability(struct sock *sk, u16 index, unsigned char *data,
1209 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02001210{
1211 struct hci_dev *hdev;
1212 struct mgmt_cp_set_io_capability *cp;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02001213
1214 BT_DBG("");
1215
1216 cp = (void *) data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02001217
Szymon Jancbdce7ba2011-02-25 19:05:49 +01001218 if (len != sizeof(*cp))
Szymon Jancb8534e0f2011-03-01 16:55:34 +01001219 return cmd_status(sk, index, MGMT_OP_SET_IO_CAPABILITY, EINVAL);
Szymon Jancbdce7ba2011-02-25 19:05:49 +01001220
Szymon Janc4e51eae2011-02-25 19:05:48 +01001221 hdev = hci_dev_get(index);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02001222 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +01001223 return cmd_status(sk, index, MGMT_OP_SET_IO_CAPABILITY, ENODEV);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02001224
1225 hci_dev_lock_bh(hdev);
1226
1227 hdev->io_capability = cp->io_capability;
1228
1229 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Szymon Jancb8534e0f2011-03-01 16:55:34 +01001230 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02001231
1232 hci_dev_unlock_bh(hdev);
1233 hci_dev_put(hdev);
1234
Szymon Janc4e51eae2011-02-25 19:05:48 +01001235 return cmd_complete(sk, index, MGMT_OP_SET_IO_CAPABILITY, NULL, 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02001236}
1237
Johan Hedberge9a416b2011-02-19 12:05:56 -03001238static inline struct pending_cmd *find_pairing(struct hci_conn *conn)
1239{
1240 struct hci_dev *hdev = conn->hdev;
1241 struct list_head *p;
1242
1243 list_for_each(p, &cmd_list) {
1244 struct pending_cmd *cmd;
1245
1246 cmd = list_entry(p, struct pending_cmd, list);
1247
1248 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
1249 continue;
1250
1251 if (cmd->index != hdev->id)
1252 continue;
1253
1254 if (cmd->user_data != conn)
1255 continue;
1256
1257 return cmd;
1258 }
1259
1260 return NULL;
1261}
1262
1263static void pairing_complete(struct pending_cmd *cmd, u8 status)
1264{
1265 struct mgmt_rp_pair_device rp;
1266 struct hci_conn *conn = cmd->user_data;
1267
Johan Hedberge9a416b2011-02-19 12:05:56 -03001268 bacpy(&rp.bdaddr, &conn->dst);
1269 rp.status = status;
1270
Szymon Janc4e51eae2011-02-25 19:05:48 +01001271 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03001272
1273 /* So we don't get further callbacks for this connection */
1274 conn->connect_cfm_cb = NULL;
1275 conn->security_cfm_cb = NULL;
1276 conn->disconn_cfm_cb = NULL;
1277
1278 hci_conn_put(conn);
1279
Johan Hedberga664b5b2011-02-19 12:06:02 -03001280 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03001281}
1282
1283static void pairing_complete_cb(struct hci_conn *conn, u8 status)
1284{
1285 struct pending_cmd *cmd;
1286
1287 BT_DBG("status %u", status);
1288
1289 cmd = find_pairing(conn);
1290 if (!cmd) {
1291 BT_DBG("Unable to find a pending command");
1292 return;
1293 }
1294
1295 pairing_complete(cmd, status);
1296}
1297
Szymon Janc4e51eae2011-02-25 19:05:48 +01001298static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03001299{
1300 struct hci_dev *hdev;
1301 struct mgmt_cp_pair_device *cp;
1302 struct pending_cmd *cmd;
1303 u8 sec_level, auth_type;
1304 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03001305 int err;
1306
1307 BT_DBG("");
1308
1309 cp = (void *) data;
Johan Hedberge9a416b2011-02-19 12:05:56 -03001310
Szymon Jancbdce7ba2011-02-25 19:05:49 +01001311 if (len != sizeof(*cp))
1312 return cmd_status(sk, index, MGMT_OP_PAIR_DEVICE, EINVAL);
1313
Szymon Janc4e51eae2011-02-25 19:05:48 +01001314 hdev = hci_dev_get(index);
Johan Hedberge9a416b2011-02-19 12:05:56 -03001315 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +01001316 return cmd_status(sk, index, MGMT_OP_PAIR_DEVICE, ENODEV);
Johan Hedberge9a416b2011-02-19 12:05:56 -03001317
1318 hci_dev_lock_bh(hdev);
1319
1320 if (cp->io_cap == 0x03) {
1321 sec_level = BT_SECURITY_MEDIUM;
1322 auth_type = HCI_AT_DEDICATED_BONDING;
1323 } else {
1324 sec_level = BT_SECURITY_HIGH;
1325 auth_type = HCI_AT_DEDICATED_BONDING_MITM;
1326 }
1327
1328 conn = hci_connect(hdev, ACL_LINK, &cp->bdaddr, sec_level, auth_type);
Ville Tervo30e76272011-02-22 16:10:53 -03001329 if (IS_ERR(conn)) {
1330 err = PTR_ERR(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03001331 goto unlock;
1332 }
1333
1334 if (conn->connect_cfm_cb) {
1335 hci_conn_put(conn);
Szymon Janc4e51eae2011-02-25 19:05:48 +01001336 err = cmd_status(sk, index, MGMT_OP_PAIR_DEVICE, EBUSY);
Johan Hedberge9a416b2011-02-19 12:05:56 -03001337 goto unlock;
1338 }
1339
Szymon Janc4e51eae2011-02-25 19:05:48 +01001340 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, index, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03001341 if (!cmd) {
1342 err = -ENOMEM;
1343 hci_conn_put(conn);
1344 goto unlock;
1345 }
1346
1347 conn->connect_cfm_cb = pairing_complete_cb;
1348 conn->security_cfm_cb = pairing_complete_cb;
1349 conn->disconn_cfm_cb = pairing_complete_cb;
1350 conn->io_capability = cp->io_cap;
1351 cmd->user_data = conn;
1352
1353 if (conn->state == BT_CONNECTED &&
1354 hci_conn_security(conn, sec_level, auth_type))
1355 pairing_complete(cmd, 0);
1356
1357 err = 0;
1358
1359unlock:
1360 hci_dev_unlock_bh(hdev);
1361 hci_dev_put(hdev);
1362
1363 return err;
1364}
1365
Szymon Janc4e51eae2011-02-25 19:05:48 +01001366static int user_confirm_reply(struct sock *sk, u16 index, unsigned char *data,
1367 u16 len, int success)
Johan Hedberga5c29682011-02-19 12:05:57 -03001368{
1369 struct mgmt_cp_user_confirm_reply *cp = (void *) data;
Szymon Janc4e51eae2011-02-25 19:05:48 +01001370 u16 mgmt_op, hci_op;
Johan Hedberga5c29682011-02-19 12:05:57 -03001371 struct pending_cmd *cmd;
1372 struct hci_dev *hdev;
1373 int err;
1374
1375 BT_DBG("");
1376
Johan Hedberga5c29682011-02-19 12:05:57 -03001377 if (success) {
1378 mgmt_op = MGMT_OP_USER_CONFIRM_REPLY;
1379 hci_op = HCI_OP_USER_CONFIRM_REPLY;
1380 } else {
1381 mgmt_op = MGMT_OP_USER_CONFIRM_NEG_REPLY;
1382 hci_op = HCI_OP_USER_CONFIRM_NEG_REPLY;
1383 }
1384
Szymon Jancbdce7ba2011-02-25 19:05:49 +01001385 if (len != sizeof(*cp))
1386 return cmd_status(sk, index, mgmt_op, EINVAL);
1387
Szymon Janc4e51eae2011-02-25 19:05:48 +01001388 hdev = hci_dev_get(index);
Johan Hedberga5c29682011-02-19 12:05:57 -03001389 if (!hdev)
Szymon Janc4e51eae2011-02-25 19:05:48 +01001390 return cmd_status(sk, index, mgmt_op, ENODEV);
Johan Hedberga5c29682011-02-19 12:05:57 -03001391
1392 if (!test_bit(HCI_UP, &hdev->flags)) {
Szymon Janc4e51eae2011-02-25 19:05:48 +01001393 err = cmd_status(sk, index, mgmt_op, ENETDOWN);
Johan Hedberga5c29682011-02-19 12:05:57 -03001394 goto failed;
1395 }
1396
Szymon Janc4e51eae2011-02-25 19:05:48 +01001397 cmd = mgmt_pending_add(sk, mgmt_op, index, data, len);
Johan Hedberga5c29682011-02-19 12:05:57 -03001398 if (!cmd) {
1399 err = -ENOMEM;
1400 goto failed;
1401 }
1402
1403 err = hci_send_cmd(hdev, hci_op, sizeof(cp->bdaddr), &cp->bdaddr);
Johan Hedberga664b5b2011-02-19 12:06:02 -03001404 if (err < 0)
1405 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03001406
1407failed:
1408 hci_dev_unlock_bh(hdev);
1409 hci_dev_put(hdev);
1410
1411 return err;
1412}
1413
Johan Hedbergb312b1612011-03-16 14:29:37 +02001414static int set_local_name(struct sock *sk, u16 index, unsigned char *data,
1415 u16 len)
1416{
1417 struct mgmt_cp_set_local_name *mgmt_cp = (void *) data;
1418 struct hci_cp_write_local_name hci_cp;
1419 struct hci_dev *hdev;
1420 struct pending_cmd *cmd;
1421 int err;
1422
1423 BT_DBG("");
1424
1425 if (len != sizeof(*mgmt_cp))
1426 return cmd_status(sk, index, MGMT_OP_SET_LOCAL_NAME, EINVAL);
1427
1428 hdev = hci_dev_get(index);
1429 if (!hdev)
1430 return cmd_status(sk, index, MGMT_OP_SET_LOCAL_NAME, ENODEV);
1431
1432 hci_dev_lock_bh(hdev);
1433
1434 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, index, data, len);
1435 if (!cmd) {
1436 err = -ENOMEM;
1437 goto failed;
1438 }
1439
1440 memcpy(hci_cp.name, mgmt_cp->name, sizeof(hci_cp.name));
1441 err = hci_send_cmd(hdev, HCI_OP_WRITE_LOCAL_NAME, sizeof(hci_cp),
1442 &hci_cp);
1443 if (err < 0)
1444 mgmt_pending_remove(cmd);
1445
1446failed:
1447 hci_dev_unlock_bh(hdev);
1448 hci_dev_put(hdev);
1449
1450 return err;
1451}
1452
Szymon Jancc35938b2011-03-22 13:12:21 +01001453static int read_local_oob_data(struct sock *sk, u16 index)
1454{
1455 struct hci_dev *hdev;
1456 struct pending_cmd *cmd;
1457 int err;
1458
1459 BT_DBG("hci%u", index);
1460
1461 hdev = hci_dev_get(index);
1462 if (!hdev)
1463 return cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
1464 ENODEV);
1465
1466 hci_dev_lock_bh(hdev);
1467
1468 if (!test_bit(HCI_UP, &hdev->flags)) {
1469 err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
1470 ENETDOWN);
1471 goto unlock;
1472 }
1473
1474 if (!(hdev->features[6] & LMP_SIMPLE_PAIR)) {
1475 err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
1476 EOPNOTSUPP);
1477 goto unlock;
1478 }
1479
1480 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, index)) {
1481 err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, EBUSY);
1482 goto unlock;
1483 }
1484
1485 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, index, NULL, 0);
1486 if (!cmd) {
1487 err = -ENOMEM;
1488 goto unlock;
1489 }
1490
1491 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
1492 if (err < 0)
1493 mgmt_pending_remove(cmd);
1494
1495unlock:
1496 hci_dev_unlock_bh(hdev);
1497 hci_dev_put(hdev);
1498
1499 return err;
1500}
1501
Szymon Janc2763eda2011-03-22 13:12:22 +01001502static int add_remote_oob_data(struct sock *sk, u16 index, unsigned char *data,
1503 u16 len)
1504{
1505 struct hci_dev *hdev;
1506 struct mgmt_cp_add_remote_oob_data *cp = (void *) data;
1507 int err;
1508
1509 BT_DBG("hci%u ", index);
1510
1511 if (len != sizeof(*cp))
1512 return cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA,
1513 EINVAL);
1514
1515 hdev = hci_dev_get(index);
1516 if (!hdev)
1517 return cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA,
1518 ENODEV);
1519
1520 hci_dev_lock_bh(hdev);
1521
1522 err = hci_add_remote_oob_data(hdev, &cp->bdaddr, cp->hash,
1523 cp->randomizer);
1524 if (err < 0)
1525 err = cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, -err);
1526 else
1527 err = cmd_complete(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, NULL,
1528 0);
1529
1530 hci_dev_unlock_bh(hdev);
1531 hci_dev_put(hdev);
1532
1533 return err;
1534}
1535
1536static int remove_remote_oob_data(struct sock *sk, u16 index,
1537 unsigned char *data, u16 len)
1538{
1539 struct hci_dev *hdev;
1540 struct mgmt_cp_remove_remote_oob_data *cp = (void *) data;
1541 int err;
1542
1543 BT_DBG("hci%u ", index);
1544
1545 if (len != sizeof(*cp))
1546 return cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
1547 EINVAL);
1548
1549 hdev = hci_dev_get(index);
1550 if (!hdev)
1551 return cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
1552 ENODEV);
1553
1554 hci_dev_lock_bh(hdev);
1555
1556 err = hci_remove_remote_oob_data(hdev, &cp->bdaddr);
1557 if (err < 0)
1558 err = cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
1559 -err);
1560 else
1561 err = cmd_complete(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
1562 NULL, 0);
1563
1564 hci_dev_unlock_bh(hdev);
1565 hci_dev_put(hdev);
1566
1567 return err;
1568}
1569
Johan Hedberg03811012010-12-08 00:21:06 +02001570int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
1571{
1572 unsigned char *buf;
1573 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01001574 u16 opcode, index, len;
Johan Hedberg03811012010-12-08 00:21:06 +02001575 int err;
1576
1577 BT_DBG("got %zu bytes", msglen);
1578
1579 if (msglen < sizeof(*hdr))
1580 return -EINVAL;
1581
1582 buf = kmalloc(msglen, GFP_ATOMIC);
1583 if (!buf)
1584 return -ENOMEM;
1585
1586 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
1587 err = -EFAULT;
1588 goto done;
1589 }
1590
1591 hdr = (struct mgmt_hdr *) buf;
1592 opcode = get_unaligned_le16(&hdr->opcode);
Szymon Janc4e51eae2011-02-25 19:05:48 +01001593 index = get_unaligned_le16(&hdr->index);
Johan Hedberg03811012010-12-08 00:21:06 +02001594 len = get_unaligned_le16(&hdr->len);
1595
1596 if (len != msglen - sizeof(*hdr)) {
1597 err = -EINVAL;
1598 goto done;
1599 }
1600
1601 switch (opcode) {
Johan Hedberg02d98122010-12-13 21:07:04 +02001602 case MGMT_OP_READ_VERSION:
1603 err = read_version(sk);
1604 break;
Johan Hedbergfaba42e2010-12-13 21:07:05 +02001605 case MGMT_OP_READ_INDEX_LIST:
1606 err = read_index_list(sk);
1607 break;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001608 case MGMT_OP_READ_INFO:
Szymon Janc4e51eae2011-02-25 19:05:48 +01001609 err = read_controller_info(sk, index);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001610 break;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001611 case MGMT_OP_SET_POWERED:
Szymon Janc4e51eae2011-02-25 19:05:48 +01001612 err = set_powered(sk, index, buf + sizeof(*hdr), len);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001613 break;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001614 case MGMT_OP_SET_DISCOVERABLE:
Szymon Janc4e51eae2011-02-25 19:05:48 +01001615 err = set_discoverable(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg73f22f62010-12-29 16:00:25 +02001616 break;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02001617 case MGMT_OP_SET_CONNECTABLE:
Szymon Janc4e51eae2011-02-25 19:05:48 +01001618 err = set_connectable(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02001619 break;
Johan Hedbergc542a062011-01-26 13:11:03 +02001620 case MGMT_OP_SET_PAIRABLE:
Szymon Janc4e51eae2011-02-25 19:05:48 +01001621 err = set_pairable(sk, index, buf + sizeof(*hdr), len);
Johan Hedbergc542a062011-01-26 13:11:03 +02001622 break;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02001623 case MGMT_OP_ADD_UUID:
Szymon Janc4e51eae2011-02-25 19:05:48 +01001624 err = add_uuid(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02001625 break;
1626 case MGMT_OP_REMOVE_UUID:
Szymon Janc4e51eae2011-02-25 19:05:48 +01001627 err = remove_uuid(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02001628 break;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001629 case MGMT_OP_SET_DEV_CLASS:
Szymon Janc4e51eae2011-02-25 19:05:48 +01001630 err = set_dev_class(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001631 break;
1632 case MGMT_OP_SET_SERVICE_CACHE:
Szymon Janc4e51eae2011-02-25 19:05:48 +01001633 err = set_service_cache(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001634 break;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02001635 case MGMT_OP_LOAD_KEYS:
Szymon Janc4e51eae2011-02-25 19:05:48 +01001636 err = load_keys(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02001637 break;
1638 case MGMT_OP_REMOVE_KEY:
Szymon Janc4e51eae2011-02-25 19:05:48 +01001639 err = remove_key(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02001640 break;
Johan Hedberg8962ee72011-01-20 12:40:27 +02001641 case MGMT_OP_DISCONNECT:
Szymon Janc4e51eae2011-02-25 19:05:48 +01001642 err = disconnect(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg8962ee72011-01-20 12:40:27 +02001643 break;
Johan Hedberg2784eb42011-01-21 13:56:35 +02001644 case MGMT_OP_GET_CONNECTIONS:
Szymon Janc8ce62842011-03-01 16:55:32 +01001645 err = get_connections(sk, index);
Johan Hedberg2784eb42011-01-21 13:56:35 +02001646 break;
Johan Hedberg980e1a52011-01-22 06:10:07 +02001647 case MGMT_OP_PIN_CODE_REPLY:
Szymon Janc4e51eae2011-02-25 19:05:48 +01001648 err = pin_code_reply(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001649 break;
1650 case MGMT_OP_PIN_CODE_NEG_REPLY:
Szymon Janc4e51eae2011-02-25 19:05:48 +01001651 err = pin_code_neg_reply(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001652 break;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02001653 case MGMT_OP_SET_IO_CAPABILITY:
Szymon Janc4e51eae2011-02-25 19:05:48 +01001654 err = set_io_capability(sk, index, buf + sizeof(*hdr), len);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02001655 break;
Johan Hedberge9a416b2011-02-19 12:05:56 -03001656 case MGMT_OP_PAIR_DEVICE:
Szymon Janc4e51eae2011-02-25 19:05:48 +01001657 err = pair_device(sk, index, buf + sizeof(*hdr), len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03001658 break;
Johan Hedberga5c29682011-02-19 12:05:57 -03001659 case MGMT_OP_USER_CONFIRM_REPLY:
Szymon Janc4e51eae2011-02-25 19:05:48 +01001660 err = user_confirm_reply(sk, index, buf + sizeof(*hdr), len, 1);
Johan Hedberga5c29682011-02-19 12:05:57 -03001661 break;
1662 case MGMT_OP_USER_CONFIRM_NEG_REPLY:
Szymon Janc4e51eae2011-02-25 19:05:48 +01001663 err = user_confirm_reply(sk, index, buf + sizeof(*hdr), len, 0);
Johan Hedberga5c29682011-02-19 12:05:57 -03001664 break;
Johan Hedbergb312b1612011-03-16 14:29:37 +02001665 case MGMT_OP_SET_LOCAL_NAME:
1666 err = set_local_name(sk, index, buf + sizeof(*hdr), len);
1667 break;
Szymon Jancc35938b2011-03-22 13:12:21 +01001668 case MGMT_OP_READ_LOCAL_OOB_DATA:
1669 err = read_local_oob_data(sk, index);
1670 break;
Szymon Janc2763eda2011-03-22 13:12:22 +01001671 case MGMT_OP_ADD_REMOTE_OOB_DATA:
1672 err = add_remote_oob_data(sk, index, buf + sizeof(*hdr), len);
1673 break;
1674 case MGMT_OP_REMOVE_REMOTE_OOB_DATA:
1675 err = remove_remote_oob_data(sk, index, buf + sizeof(*hdr),
1676 len);
1677 break;
Szymon Jancc35938b2011-03-22 13:12:21 +01001678
Johan Hedberg03811012010-12-08 00:21:06 +02001679 default:
1680 BT_DBG("Unknown op %u", opcode);
Szymon Janc4e51eae2011-02-25 19:05:48 +01001681 err = cmd_status(sk, index, opcode, 0x01);
Johan Hedberg03811012010-12-08 00:21:06 +02001682 break;
1683 }
1684
Johan Hedberge41d8b42010-12-13 21:07:03 +02001685 if (err < 0)
1686 goto done;
1687
Johan Hedberg03811012010-12-08 00:21:06 +02001688 err = msglen;
1689
1690done:
1691 kfree(buf);
1692 return err;
1693}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02001694
Johan Hedbergc71e97b2010-12-13 21:07:07 +02001695int mgmt_index_added(u16 index)
1696{
Szymon Janc4e51eae2011-02-25 19:05:48 +01001697 return mgmt_event(MGMT_EV_INDEX_ADDED, index, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02001698}
1699
1700int mgmt_index_removed(u16 index)
1701{
Szymon Janc4e51eae2011-02-25 19:05:48 +01001702 return mgmt_event(MGMT_EV_INDEX_REMOVED, index, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001703}
1704
Johan Hedberg73f22f62010-12-29 16:00:25 +02001705struct cmd_lookup {
Johan Hedberg72a734e2010-12-30 00:38:22 +02001706 u8 val;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001707 struct sock *sk;
1708};
1709
Johan Hedberg72a734e2010-12-30 00:38:22 +02001710static void mode_rsp(struct pending_cmd *cmd, void *data)
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001711{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01001712 struct mgmt_mode *cp = cmd->param;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001713 struct cmd_lookup *match = data;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001714
Johan Hedberg72a734e2010-12-30 00:38:22 +02001715 if (cp->val != match->val)
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001716 return;
1717
Johan Hedberg053f0212011-01-26 13:07:10 +02001718 send_mode_rsp(cmd->sk, cmd->opcode, cmd->index, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001719
1720 list_del(&cmd->list);
1721
1722 if (match->sk == NULL) {
1723 match->sk = cmd->sk;
1724 sock_hold(match->sk);
1725 }
1726
1727 mgmt_pending_free(cmd);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02001728}
Johan Hedberg5add6af2010-12-16 10:00:37 +02001729
1730int mgmt_powered(u16 index, u8 powered)
1731{
Johan Hedberg72a734e2010-12-30 00:38:22 +02001732 struct mgmt_mode ev;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001733 struct cmd_lookup match = { powered, NULL };
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001734 int ret;
Johan Hedberg5add6af2010-12-16 10:00:37 +02001735
Johan Hedberg72a734e2010-12-30 00:38:22 +02001736 mgmt_pending_foreach(MGMT_OP_SET_POWERED, index, mode_rsp, &match);
Johan Hedberg5add6af2010-12-16 10:00:37 +02001737
Johan Hedberg72a734e2010-12-30 00:38:22 +02001738 ev.val = powered;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001739
Szymon Janc4e51eae2011-02-25 19:05:48 +01001740 ret = mgmt_event(MGMT_EV_POWERED, index, &ev, sizeof(ev), match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001741
1742 if (match.sk)
1743 sock_put(match.sk);
1744
1745 return ret;
Johan Hedberg5add6af2010-12-16 10:00:37 +02001746}
Johan Hedberg73f22f62010-12-29 16:00:25 +02001747
Johan Hedberg73f22f62010-12-29 16:00:25 +02001748int mgmt_discoverable(u16 index, u8 discoverable)
1749{
Johan Hedberg72a734e2010-12-30 00:38:22 +02001750 struct mgmt_mode ev;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001751 struct cmd_lookup match = { discoverable, NULL };
1752 int ret;
1753
Szymon Jancb8534e0f2011-03-01 16:55:34 +01001754 mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, index, mode_rsp, &match);
Johan Hedberg72a734e2010-12-30 00:38:22 +02001755
Johan Hedberg72a734e2010-12-30 00:38:22 +02001756 ev.val = discoverable;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001757
Szymon Janc4e51eae2011-02-25 19:05:48 +01001758 ret = mgmt_event(MGMT_EV_DISCOVERABLE, index, &ev, sizeof(ev),
1759 match.sk);
Johan Hedberg73f22f62010-12-29 16:00:25 +02001760
1761 if (match.sk)
1762 sock_put(match.sk);
1763
1764 return ret;
1765}
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02001766
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02001767int mgmt_connectable(u16 index, u8 connectable)
1768{
Johan Hedberg72a734e2010-12-30 00:38:22 +02001769 struct mgmt_mode ev;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02001770 struct cmd_lookup match = { connectable, NULL };
1771 int ret;
1772
Johan Hedberg72a734e2010-12-30 00:38:22 +02001773 mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, index, mode_rsp, &match);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02001774
Johan Hedberg72a734e2010-12-30 00:38:22 +02001775 ev.val = connectable;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02001776
Szymon Janc4e51eae2011-02-25 19:05:48 +01001777 ret = mgmt_event(MGMT_EV_CONNECTABLE, index, &ev, sizeof(ev), match.sk);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02001778
1779 if (match.sk)
1780 sock_put(match.sk);
1781
1782 return ret;
1783}
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02001784
1785int mgmt_new_key(u16 index, struct link_key *key, u8 old_key_type)
1786{
1787 struct mgmt_ev_new_key ev;
1788
1789 memset(&ev, 0, sizeof(ev));
1790
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02001791 bacpy(&ev.key.bdaddr, &key->bdaddr);
1792 ev.key.type = key->type;
1793 memcpy(ev.key.val, key->val, 16);
1794 ev.key.pin_len = key->pin_len;
1795 ev.old_key_type = old_key_type;
1796
Szymon Janc4e51eae2011-02-25 19:05:48 +01001797 return mgmt_event(MGMT_EV_NEW_KEY, index, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02001798}
Johan Hedbergf7520542011-01-20 12:34:39 +02001799
1800int mgmt_connected(u16 index, bdaddr_t *bdaddr)
1801{
1802 struct mgmt_ev_connected ev;
1803
Johan Hedbergf7520542011-01-20 12:34:39 +02001804 bacpy(&ev.bdaddr, bdaddr);
1805
Szymon Janc4e51eae2011-02-25 19:05:48 +01001806 return mgmt_event(MGMT_EV_CONNECTED, index, &ev, sizeof(ev), NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02001807}
1808
Johan Hedberg8962ee72011-01-20 12:40:27 +02001809static void disconnect_rsp(struct pending_cmd *cmd, void *data)
1810{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01001811 struct mgmt_cp_disconnect *cp = cmd->param;
Johan Hedberg8962ee72011-01-20 12:40:27 +02001812 struct sock **sk = data;
Johan Hedberga38528f2011-01-22 06:46:43 +02001813 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02001814
Johan Hedberga38528f2011-01-22 06:46:43 +02001815 bacpy(&rp.bdaddr, &cp->bdaddr);
Johan Hedberg8962ee72011-01-20 12:40:27 +02001816
Szymon Janc4e51eae2011-02-25 19:05:48 +01001817 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02001818
1819 *sk = cmd->sk;
1820 sock_hold(*sk);
1821
Johan Hedberga664b5b2011-02-19 12:06:02 -03001822 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02001823}
1824
Johan Hedbergf7520542011-01-20 12:34:39 +02001825int mgmt_disconnected(u16 index, bdaddr_t *bdaddr)
1826{
1827 struct mgmt_ev_disconnected ev;
Johan Hedberg8962ee72011-01-20 12:40:27 +02001828 struct sock *sk = NULL;
1829 int err;
1830
1831 mgmt_pending_foreach(MGMT_OP_DISCONNECT, index, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02001832
Johan Hedbergf7520542011-01-20 12:34:39 +02001833 bacpy(&ev.bdaddr, bdaddr);
1834
Szymon Janc4e51eae2011-02-25 19:05:48 +01001835 err = mgmt_event(MGMT_EV_DISCONNECTED, index, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02001836
1837 if (sk)
1838 sock_put(sk);
1839
1840 return err;
1841}
1842
1843int mgmt_disconnect_failed(u16 index)
1844{
1845 struct pending_cmd *cmd;
1846 int err;
1847
1848 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, index);
1849 if (!cmd)
1850 return -ENOENT;
1851
Szymon Janc4e51eae2011-02-25 19:05:48 +01001852 err = cmd_status(cmd->sk, index, MGMT_OP_DISCONNECT, EIO);
Johan Hedberg8962ee72011-01-20 12:40:27 +02001853
Johan Hedberga664b5b2011-02-19 12:06:02 -03001854 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02001855
1856 return err;
Johan Hedbergf7520542011-01-20 12:34:39 +02001857}
Johan Hedberg17d5c042011-01-22 06:09:08 +02001858
1859int mgmt_connect_failed(u16 index, bdaddr_t *bdaddr, u8 status)
1860{
1861 struct mgmt_ev_connect_failed ev;
1862
Johan Hedberg17d5c042011-01-22 06:09:08 +02001863 bacpy(&ev.bdaddr, bdaddr);
1864 ev.status = status;
1865
Szymon Janc4e51eae2011-02-25 19:05:48 +01001866 return mgmt_event(MGMT_EV_CONNECT_FAILED, index, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02001867}
Johan Hedberg980e1a52011-01-22 06:10:07 +02001868
1869int mgmt_pin_code_request(u16 index, bdaddr_t *bdaddr)
1870{
1871 struct mgmt_ev_pin_code_request ev;
1872
Johan Hedberg980e1a52011-01-22 06:10:07 +02001873 bacpy(&ev.bdaddr, bdaddr);
1874
Szymon Janc4e51eae2011-02-25 19:05:48 +01001875 return mgmt_event(MGMT_EV_PIN_CODE_REQUEST, index, &ev, sizeof(ev),
1876 NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001877}
1878
1879int mgmt_pin_code_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status)
1880{
1881 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03001882 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02001883 int err;
1884
1885 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, index);
1886 if (!cmd)
1887 return -ENOENT;
1888
Johan Hedbergac56fb12011-02-19 12:05:59 -03001889 bacpy(&rp.bdaddr, bdaddr);
1890 rp.status = status;
1891
Szymon Janc4e51eae2011-02-25 19:05:48 +01001892 err = cmd_complete(cmd->sk, index, MGMT_OP_PIN_CODE_REPLY, &rp,
1893 sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02001894
Johan Hedberga664b5b2011-02-19 12:06:02 -03001895 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001896
1897 return err;
1898}
1899
1900int mgmt_pin_code_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status)
1901{
1902 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03001903 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02001904 int err;
1905
1906 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, index);
1907 if (!cmd)
1908 return -ENOENT;
1909
Johan Hedbergac56fb12011-02-19 12:05:59 -03001910 bacpy(&rp.bdaddr, bdaddr);
1911 rp.status = status;
1912
Szymon Janc4e51eae2011-02-25 19:05:48 +01001913 err = cmd_complete(cmd->sk, index, MGMT_OP_PIN_CODE_NEG_REPLY, &rp,
1914 sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02001915
Johan Hedberga664b5b2011-02-19 12:06:02 -03001916 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02001917
1918 return err;
1919}
Johan Hedberga5c29682011-02-19 12:05:57 -03001920
1921int mgmt_user_confirm_request(u16 index, bdaddr_t *bdaddr, __le32 value)
1922{
1923 struct mgmt_ev_user_confirm_request ev;
1924
1925 BT_DBG("hci%u", index);
1926
Johan Hedberga5c29682011-02-19 12:05:57 -03001927 bacpy(&ev.bdaddr, bdaddr);
1928 put_unaligned_le32(value, &ev.value);
1929
Szymon Janc4e51eae2011-02-25 19:05:48 +01001930 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, index, &ev, sizeof(ev),
1931 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03001932}
1933
1934static int confirm_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status,
1935 u8 opcode)
1936{
1937 struct pending_cmd *cmd;
1938 struct mgmt_rp_user_confirm_reply rp;
1939 int err;
1940
1941 cmd = mgmt_pending_find(opcode, index);
1942 if (!cmd)
1943 return -ENOENT;
1944
Johan Hedberga5c29682011-02-19 12:05:57 -03001945 bacpy(&rp.bdaddr, bdaddr);
1946 rp.status = status;
Szymon Janc4e51eae2011-02-25 19:05:48 +01001947 err = cmd_complete(cmd->sk, index, opcode, &rp, sizeof(rp));
Johan Hedberga5c29682011-02-19 12:05:57 -03001948
Johan Hedberga664b5b2011-02-19 12:06:02 -03001949 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03001950
1951 return err;
1952}
1953
1954int mgmt_user_confirm_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status)
1955{
1956 return confirm_reply_complete(index, bdaddr, status,
1957 MGMT_OP_USER_CONFIRM_REPLY);
1958}
1959
Szymon Jancb8534e0f2011-03-01 16:55:34 +01001960int mgmt_user_confirm_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03001961{
1962 return confirm_reply_complete(index, bdaddr, status,
1963 MGMT_OP_USER_CONFIRM_NEG_REPLY);
1964}
Johan Hedberg2a611692011-02-19 12:06:00 -03001965
1966int mgmt_auth_failed(u16 index, bdaddr_t *bdaddr, u8 status)
1967{
1968 struct mgmt_ev_auth_failed ev;
1969
Johan Hedberg2a611692011-02-19 12:06:00 -03001970 bacpy(&ev.bdaddr, bdaddr);
1971 ev.status = status;
1972
Szymon Janc4e51eae2011-02-25 19:05:48 +01001973 return mgmt_event(MGMT_EV_AUTH_FAILED, index, &ev, sizeof(ev), NULL);
Johan Hedberg2a611692011-02-19 12:06:00 -03001974}
Johan Hedbergb312b1612011-03-16 14:29:37 +02001975
1976int mgmt_set_local_name_complete(u16 index, u8 *name, u8 status)
1977{
1978 struct pending_cmd *cmd;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001979 struct hci_dev *hdev;
Johan Hedbergb312b1612011-03-16 14:29:37 +02001980 struct mgmt_cp_set_local_name ev;
1981 int err;
1982
1983 memset(&ev, 0, sizeof(ev));
1984 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
1985
1986 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, index);
1987 if (!cmd)
1988 goto send_event;
1989
1990 if (status) {
1991 err = cmd_status(cmd->sk, index, MGMT_OP_SET_LOCAL_NAME, EIO);
1992 goto failed;
1993 }
1994
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001995 hdev = hci_dev_get(index);
1996 if (hdev) {
1997 hci_dev_lock_bh(hdev);
1998 update_eir(hdev);
1999 hci_dev_unlock_bh(hdev);
2000 hci_dev_put(hdev);
2001 }
2002
Johan Hedbergb312b1612011-03-16 14:29:37 +02002003 err = cmd_complete(cmd->sk, index, MGMT_OP_SET_LOCAL_NAME, &ev,
2004 sizeof(ev));
2005 if (err < 0)
2006 goto failed;
2007
2008send_event:
2009 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, index, &ev, sizeof(ev),
2010 cmd ? cmd->sk : NULL);
2011
2012failed:
2013 if (cmd)
2014 mgmt_pending_remove(cmd);
2015 return err;
2016}
Szymon Jancc35938b2011-03-22 13:12:21 +01002017
2018int mgmt_read_local_oob_data_reply_complete(u16 index, u8 *hash, u8 *randomizer,
2019 u8 status)
2020{
2021 struct pending_cmd *cmd;
2022 int err;
2023
2024 BT_DBG("hci%u status %u", index, status);
2025
2026 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, index);
2027 if (!cmd)
2028 return -ENOENT;
2029
2030 if (status) {
2031 err = cmd_status(cmd->sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
2032 EIO);
2033 } else {
2034 struct mgmt_rp_read_local_oob_data rp;
2035
2036 memcpy(rp.hash, hash, sizeof(rp.hash));
2037 memcpy(rp.randomizer, randomizer, sizeof(rp.randomizer));
2038
2039 err = cmd_complete(cmd->sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
2040 &rp, sizeof(rp));
2041 }
2042
2043 mgmt_pending_remove(cmd);
2044
2045 return err;
2046}