aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@intel.com>2011-12-14 17:47:35 -0500
committerGustavo F. Padovan <padovan@profusion.mobi>2011-12-18 14:34:04 -0500
commit69ab39ea5da03e632a51b31534da713aff8d1e3b (patch)
tree3f10083b2ed1bd186f0f38b513453c68954dac45
parent590051de5ce54f7ae02997ed0a2532f08c7b7866 (diff)
Bluetooth: Update mgmt_read_info and related mgmt messages
This patch updates the mgmt_read_info and related messages to the latest management API which uses a bitfield of settings instead of individual boolean values. Signed-off-by: Johan Hedberg <johan.hedberg@intel.com> Acked-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
-rw-r--r--include/net/bluetooth/hci.h1
-rw-r--r--include/net/bluetooth/mgmt.h29
-rw-r--r--net/bluetooth/mgmt.c146
3 files changed, 113 insertions, 63 deletions
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 67ad98430348..c9ad56fe58f4 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -210,6 +210,7 @@ enum {
210 210
211#define LMP_EV4 0x01 211#define LMP_EV4 0x01
212#define LMP_EV5 0x02 212#define LMP_EV5 0x02
213#define LMP_NO_BREDR 0x20
213#define LMP_LE 0x40 214#define LMP_LE 0x40
214 215
215#define LMP_SNIFF_SUBR 0x02 216#define LMP_SNIFF_SUBR 0x02
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 3b6880690a78..85e9c6e9d221 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -61,22 +61,29 @@ struct mgmt_rp_read_index_list {
61/* Reserve one extra byte for names in management messages so that they 61/* Reserve one extra byte for names in management messages so that they
62 * are always guaranteed to be nul-terminated */ 62 * are always guaranteed to be nul-terminated */
63#define MGMT_MAX_NAME_LENGTH (HCI_MAX_NAME_LENGTH + 1) 63#define MGMT_MAX_NAME_LENGTH (HCI_MAX_NAME_LENGTH + 1)
64#define MGMT_MAX_SHORT_NAME_LENGTH (10 + 1)
65
66#define MGMT_SETTING_POWERED 0x00000001
67#define MGMT_SETTING_CONNECTABLE 0x00000002
68#define MGMT_SETTING_FAST_CONNECTABLE 0x00000004
69#define MGMT_SETTING_DISCOVERABLE 0x00000008
70#define MGMT_SETTING_PAIRABLE 0x00000010
71#define MGMT_SETTING_LINK_SECURITY 0x00000020
72#define MGMT_SETTING_SSP 0x00000040
73#define MGMT_SETTING_BREDR 0x00000080
74#define MGMT_SETTING_HS 0x00000100
75#define MGMT_SETTING_LE 0x00000200
64 76
65#define MGMT_OP_READ_INFO 0x0004 77#define MGMT_OP_READ_INFO 0x0004
66struct mgmt_rp_read_info { 78struct mgmt_rp_read_info {
67 __u8 type;
68 __u8 powered;
69 __u8 connectable;
70 __u8 discoverable;
71 __u8 pairable;
72 __u8 sec_mode;
73 bdaddr_t bdaddr; 79 bdaddr_t bdaddr;
80 __u8 version;
81 __le16 manufacturer;
82 __le32 supported_settings;
83 __le32 current_settings;
74 __u8 dev_class[3]; 84 __u8 dev_class[3];
75 __u8 features[8];
76 __u16 manufacturer;
77 __u8 hci_ver;
78 __u16 hci_rev;
79 __u8 name[MGMT_MAX_NAME_LENGTH]; 85 __u8 name[MGMT_MAX_NAME_LENGTH];
86 __u8 short_name[MGMT_MAX_SHORT_NAME_LENGTH];
80} __packed; 87} __packed;
81 88
82struct mgmt_mode { 89struct mgmt_mode {
@@ -285,7 +292,7 @@ struct mgmt_ev_controller_error {
285 292
286#define MGMT_EV_INDEX_REMOVED 0x0005 293#define MGMT_EV_INDEX_REMOVED 0x0005
287 294
288#define MGMT_EV_POWERED 0x0006 295#define MGMT_EV_NEW_SETTINGS 0x0006
289 296
290#define MGMT_EV_DISCOVERABLE 0x0007 297#define MGMT_EV_DISCOVERABLE 0x0007
291 298
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index ffd1c01c7d0e..087cf00a443d 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -242,6 +242,63 @@ static int read_index_list(struct sock *sk)
242 return err; 242 return err;
243} 243}
244 244
245static u32 get_supported_settings(struct hci_dev *hdev)
246{
247 u32 settings = 0;
248
249 settings |= MGMT_SETTING_POWERED;
250 settings |= MGMT_SETTING_CONNECTABLE;
251 settings |= MGMT_SETTING_FAST_CONNECTABLE;
252 settings |= MGMT_SETTING_DISCOVERABLE;
253 settings |= MGMT_SETTING_PAIRABLE;
254
255 if (hdev->features[6] & LMP_SIMPLE_PAIR)
256 settings |= MGMT_SETTING_SSP;
257
258 if (!(hdev->features[4] & LMP_NO_BREDR)) {
259 settings |= MGMT_SETTING_BREDR;
260 settings |= MGMT_SETTING_LINK_SECURITY;
261 }
262
263 if (hdev->features[4] & LMP_LE)
264 settings |= MGMT_SETTING_LE;
265
266 return settings;
267}
268
269static u32 get_current_settings(struct hci_dev *hdev)
270{
271 u32 settings = 0;
272
273 if (test_bit(HCI_UP, &hdev->flags))
274 settings |= MGMT_SETTING_POWERED;
275 else
276 return settings;
277
278 if (test_bit(HCI_PSCAN, &hdev->flags))
279 settings |= MGMT_SETTING_CONNECTABLE;
280
281 if (test_bit(HCI_ISCAN, &hdev->flags))
282 settings |= MGMT_SETTING_DISCOVERABLE;
283
284 if (test_bit(HCI_PAIRABLE, &hdev->flags))
285 settings |= MGMT_SETTING_PAIRABLE;
286
287 if (!(hdev->features[4] & LMP_NO_BREDR))
288 settings |= MGMT_SETTING_BREDR;
289
290 if (hdev->extfeatures[0] & LMP_HOST_LE)
291 settings |= MGMT_SETTING_LE;
292
293 if (test_bit(HCI_AUTH, &hdev->flags))
294 settings |= MGMT_SETTING_LINK_SECURITY;
295
296 if (hdev->ssp_mode > 0)
297 settings |= MGMT_SETTING_SSP;
298
299 return settings;
300}
301
245static int read_controller_info(struct sock *sk, u16 index) 302static int read_controller_info(struct sock *sk, u16 index)
246{ 303{
247 struct mgmt_rp_read_info rp; 304 struct mgmt_rp_read_info rp;
@@ -263,26 +320,16 @@ static int read_controller_info(struct sock *sk, u16 index)
263 320
264 memset(&rp, 0, sizeof(rp)); 321 memset(&rp, 0, sizeof(rp));
265 322
266 rp.type = hdev->dev_type; 323 bacpy(&rp.bdaddr, &hdev->bdaddr);
267 324
268 rp.powered = test_bit(HCI_UP, &hdev->flags); 325 rp.version = hdev->hci_ver;
269 rp.connectable = test_bit(HCI_PSCAN, &hdev->flags);
270 rp.discoverable = test_bit(HCI_ISCAN, &hdev->flags);
271 rp.pairable = test_bit(HCI_PSCAN, &hdev->flags);
272 326
273 if (test_bit(HCI_AUTH, &hdev->flags)) 327 put_unaligned_le16(hdev->manufacturer, &rp.manufacturer);
274 rp.sec_mode = 3; 328
275 else if (hdev->ssp_mode > 0) 329 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
276 rp.sec_mode = 4; 330 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
277 else
278 rp.sec_mode = 2;
279 331
280 bacpy(&rp.bdaddr, &hdev->bdaddr);
281 memcpy(rp.features, hdev->features, 8);
282 memcpy(rp.dev_class, hdev->dev_class, 3); 332 memcpy(rp.dev_class, hdev->dev_class, 3);
283 put_unaligned_le16(hdev->manufacturer, &rp.manufacturer);
284 rp.hci_ver = hdev->hci_ver;
285 put_unaligned_le16(hdev->hci_rev, &rp.hci_rev);
286 333
287 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name)); 334 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
288 335
@@ -365,13 +412,11 @@ static void mgmt_pending_remove(struct pending_cmd *cmd)
365 mgmt_pending_free(cmd); 412 mgmt_pending_free(cmd);
366} 413}
367 414
368static int send_mode_rsp(struct sock *sk, u16 opcode, u16 index, u8 val) 415static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
369{ 416{
370 struct mgmt_mode rp; 417 __le32 settings = cpu_to_le32(get_current_settings(hdev));
371 418
372 rp.val = val; 419 return cmd_complete(sk, hdev->id, opcode, &settings, sizeof(settings));
373
374 return cmd_complete(sk, index, opcode, &rp, sizeof(rp));
375} 420}
376 421
377static int set_powered(struct sock *sk, u16 index, unsigned char *data, u16 len) 422static int set_powered(struct sock *sk, u16 index, unsigned char *data, u16 len)
@@ -398,7 +443,7 @@ static int set_powered(struct sock *sk, u16 index, unsigned char *data, u16 len)
398 443
399 up = test_bit(HCI_UP, &hdev->flags); 444 up = test_bit(HCI_UP, &hdev->flags);
400 if ((cp->val && up) || (!cp->val && !up)) { 445 if ((cp->val && up) || (!cp->val && !up)) {
401 err = send_mode_rsp(sk, index, MGMT_OP_SET_POWERED, cp->val); 446 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
402 goto failed; 447 goto failed;
403 } 448 }
404 449
@@ -466,8 +511,7 @@ static int set_discoverable(struct sock *sk, u16 index, unsigned char *data,
466 511
467 if (cp->val == test_bit(HCI_ISCAN, &hdev->flags) && 512 if (cp->val == test_bit(HCI_ISCAN, &hdev->flags) &&
468 test_bit(HCI_PSCAN, &hdev->flags)) { 513 test_bit(HCI_PSCAN, &hdev->flags)) {
469 err = send_mode_rsp(sk, index, MGMT_OP_SET_DISCOVERABLE, 514 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
470 cp->val);
471 goto failed; 515 goto failed;
472 } 516 }
473 517
@@ -536,8 +580,7 @@ static int set_connectable(struct sock *sk, u16 index, unsigned char *data,
536 } 580 }
537 581
538 if (cp->val == test_bit(HCI_PSCAN, &hdev->flags)) { 582 if (cp->val == test_bit(HCI_PSCAN, &hdev->flags)) {
539 err = send_mode_rsp(sk, index, MGMT_OP_SET_CONNECTABLE, 583 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
540 cp->val);
541 goto failed; 584 goto failed;
542 } 585 }
543 586
@@ -595,8 +638,9 @@ static int mgmt_event(u16 event, struct hci_dev *hdev, void *data,
595static int set_pairable(struct sock *sk, u16 index, unsigned char *data, 638static int set_pairable(struct sock *sk, u16 index, unsigned char *data,
596 u16 len) 639 u16 len)
597{ 640{
598 struct mgmt_mode *cp, ev; 641 struct mgmt_mode *cp;
599 struct hci_dev *hdev; 642 struct hci_dev *hdev;
643 __le32 ev;
600 int err; 644 int err;
601 645
602 cp = (void *) data; 646 cp = (void *) data;
@@ -619,13 +663,13 @@ static int set_pairable(struct sock *sk, u16 index, unsigned char *data,
619 else 663 else
620 clear_bit(HCI_PAIRABLE, &hdev->flags); 664 clear_bit(HCI_PAIRABLE, &hdev->flags);
621 665
622 err = send_mode_rsp(sk, MGMT_OP_SET_PAIRABLE, index, cp->val); 666 err = send_settings_rsp(sk, MGMT_OP_SET_PAIRABLE, hdev);
623 if (err < 0) 667 if (err < 0)
624 goto failed; 668 goto failed;
625 669
626 ev.val = cp->val; 670 ev = cpu_to_le32(get_current_settings(hdev));
627 671
628 err = mgmt_event(MGMT_EV_PAIRABLE, hdev, &ev, sizeof(ev), sk); 672 err = mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), sk);
629 673
630failed: 674failed:
631 hci_dev_unlock(hdev); 675 hci_dev_unlock(hdev);
@@ -2234,17 +2278,14 @@ int mgmt_index_removed(struct hci_dev *hdev)
2234struct cmd_lookup { 2278struct cmd_lookup {
2235 u8 val; 2279 u8 val;
2236 struct sock *sk; 2280 struct sock *sk;
2281 struct hci_dev *hdev;
2237}; 2282};
2238 2283
2239static void mode_rsp(struct pending_cmd *cmd, void *data) 2284static void settings_rsp(struct pending_cmd *cmd, void *data)
2240{ 2285{
2241 struct mgmt_mode *cp = cmd->param;
2242 struct cmd_lookup *match = data; 2286 struct cmd_lookup *match = data;
2243 2287
2244 if (cp->val != match->val) 2288 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
2245 return;
2246
2247 send_mode_rsp(cmd->sk, cmd->opcode, cmd->index, cp->val);
2248 2289
2249 list_del(&cmd->list); 2290 list_del(&cmd->list);
2250 2291
@@ -2258,20 +2299,21 @@ static void mode_rsp(struct pending_cmd *cmd, void *data)
2258 2299
2259int mgmt_powered(struct hci_dev *hdev, u8 powered) 2300int mgmt_powered(struct hci_dev *hdev, u8 powered)
2260{ 2301{
2261 struct mgmt_mode ev; 2302 struct cmd_lookup match = { powered, NULL, hdev };
2262 struct cmd_lookup match = { powered, NULL }; 2303 __le32 ev;
2263 int ret; 2304 int ret;
2264 2305
2265 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, mode_rsp, &match); 2306 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
2266 2307
2267 if (!powered) { 2308 if (!powered) {
2268 u8 status = ENETDOWN; 2309 u8 status = ENETDOWN;
2269 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status); 2310 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
2270 } 2311 }
2271 2312
2272 ev.val = powered; 2313 ev = cpu_to_le32(get_current_settings(hdev));
2273 2314
2274 ret = mgmt_event(MGMT_EV_POWERED, hdev, &ev, sizeof(ev), match.sk); 2315 ret = mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev),
2316 match.sk);
2275 2317
2276 if (match.sk) 2318 if (match.sk)
2277 sock_put(match.sk); 2319 sock_put(match.sk);
@@ -2281,17 +2323,16 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered)
2281 2323
2282int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable) 2324int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable)
2283{ 2325{
2284 struct mgmt_mode ev; 2326 struct cmd_lookup match = { discoverable, NULL, hdev };
2285 struct cmd_lookup match = { discoverable, NULL }; 2327 __le32 ev;
2286 int ret; 2328 int ret;
2287 2329
2288 mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev, mode_rsp, &match); 2330 mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev, settings_rsp, &match);
2289 2331
2290 ev.val = discoverable; 2332 ev = cpu_to_le32(get_current_settings(hdev));
2291 2333
2292 ret = mgmt_event(MGMT_EV_DISCOVERABLE, hdev, &ev, sizeof(ev), 2334 ret = mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev),
2293 match.sk); 2335 match.sk);
2294
2295 if (match.sk) 2336 if (match.sk)
2296 sock_put(match.sk); 2337 sock_put(match.sk);
2297 2338
@@ -2300,15 +2341,16 @@ int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable)
2300 2341
2301int mgmt_connectable(struct hci_dev *hdev, u8 connectable) 2342int mgmt_connectable(struct hci_dev *hdev, u8 connectable)
2302{ 2343{
2303 struct mgmt_mode ev; 2344 __le32 ev;
2304 struct cmd_lookup match = { connectable, NULL }; 2345 struct cmd_lookup match = { connectable, NULL, hdev };
2305 int ret; 2346 int ret;
2306 2347
2307 mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev, mode_rsp, &match); 2348 mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev, settings_rsp,
2349 &match);
2308 2350
2309 ev.val = connectable; 2351 ev = cpu_to_le32(get_current_settings(hdev));
2310 2352
2311 ret = mgmt_event(MGMT_EV_CONNECTABLE, hdev, &ev, sizeof(ev), match.sk); 2353 ret = mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), match.sk);
2312 2354
2313 if (match.sk) 2355 if (match.sk)
2314 sock_put(match.sk); 2356 sock_put(match.sk);