Commit 69ab39ea5da03e632a51b31534da713aff8d1e3b

Authored by Johan Hedberg
Committed by Gustavo F. Padovan
1 parent 590051de5c

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>

Showing 3 changed files with 113 additions and 63 deletions Side-by-side Diff

include/net/bluetooth/hci.h
... ... @@ -210,6 +210,7 @@
210 210  
211 211 #define LMP_EV4 0x01
212 212 #define LMP_EV5 0x02
  213 +#define LMP_NO_BREDR 0x20
213 214 #define LMP_LE 0x40
214 215  
215 216 #define LMP_SNIFF_SUBR 0x02
include/net/bluetooth/mgmt.h
... ... @@ -61,22 +61,29 @@
61 61 /* Reserve one extra byte for names in management messages so that they
62 62 * are always guaranteed to be nul-terminated */
63 63 #define MGMT_MAX_NAME_LENGTH (HCI_MAX_NAME_LENGTH + 1)
  64 +#define MGMT_MAX_SHORT_NAME_LENGTH (10 + 1)
64 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
  76 +
65 77 #define MGMT_OP_READ_INFO 0x0004
66 78 struct mgmt_rp_read_info {
67   - __u8 type;
68   - __u8 powered;
69   - __u8 connectable;
70   - __u8 discoverable;
71   - __u8 pairable;
72   - __u8 sec_mode;
73 79 bdaddr_t bdaddr;
  80 + __u8 version;
  81 + __le16 manufacturer;
  82 + __le32 supported_settings;
  83 + __le32 current_settings;
74 84 __u8 dev_class[3];
75   - __u8 features[8];
76   - __u16 manufacturer;
77   - __u8 hci_ver;
78   - __u16 hci_rev;
79 85 __u8 name[MGMT_MAX_NAME_LENGTH];
  86 + __u8 short_name[MGMT_MAX_SHORT_NAME_LENGTH];
80 87 } __packed;
81 88  
82 89 struct mgmt_mode {
... ... @@ -285,7 +292,7 @@
285 292  
286 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 297 #define MGMT_EV_DISCOVERABLE 0x0007
291 298  
net/bluetooth/mgmt.c
... ... @@ -242,6 +242,63 @@
242 242 return err;
243 243 }
244 244  
  245 +static 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 +
  269 +static 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 +
245 302 static int read_controller_info(struct sock *sk, u16 index)
246 303 {
247 304 struct mgmt_rp_read_info rp;
248 305  
249 306  
250 307  
251 308  
... ... @@ -263,26 +320,16 @@
263 320  
264 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);
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);
  325 + rp.version = hdev->hci_ver;
272 326  
273   - if (test_bit(HCI_AUTH, &hdev->flags))
274   - rp.sec_mode = 3;
275   - else if (hdev->ssp_mode > 0)
276   - rp.sec_mode = 4;
277   - else
278   - rp.sec_mode = 2;
  327 + put_unaligned_le16(hdev->manufacturer, &rp.manufacturer);
279 328  
280   - bacpy(&rp.bdaddr, &hdev->bdaddr);
281   - memcpy(rp.features, hdev->features, 8);
  329 + rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
  330 + rp.current_settings = cpu_to_le32(get_current_settings(hdev));
  331 +
282 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 334 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
288 335  
289 336  
290 337  
... ... @@ -365,13 +412,11 @@
365 412 mgmt_pending_free(cmd);
366 413 }
367 414  
368   -static int send_mode_rsp(struct sock *sk, u16 opcode, u16 index, u8 val)
  415 +static 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;
373   -
374   - return cmd_complete(sk, index, opcode, &rp, sizeof(rp));
  419 + return cmd_complete(sk, hdev->id, opcode, &settings, sizeof(settings));
375 420 }
376 421  
377 422 static int set_powered(struct sock *sk, u16 index, unsigned char *data, u16 len)
... ... @@ -398,7 +443,7 @@
398 443  
399 444 up = test_bit(HCI_UP, &hdev->flags);
400 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 447 goto failed;
403 448 }
404 449  
... ... @@ -466,8 +511,7 @@
466 511  
467 512 if (cp->val == test_bit(HCI_ISCAN, &hdev->flags) &&
468 513 test_bit(HCI_PSCAN, &hdev->flags)) {
469   - err = send_mode_rsp(sk, index, MGMT_OP_SET_DISCOVERABLE,
470   - cp->val);
  514 + err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
471 515 goto failed;
472 516 }
473 517  
... ... @@ -536,8 +580,7 @@
536 580 }
537 581  
538 582 if (cp->val == test_bit(HCI_PSCAN, &hdev->flags)) {
539   - err = send_mode_rsp(sk, index, MGMT_OP_SET_CONNECTABLE,
540   - cp->val);
  583 + err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
541 584 goto failed;
542 585 }
543 586  
544 587  
... ... @@ -595,8 +638,9 @@
595 638 static int set_pairable(struct sock *sk, u16 index, unsigned char *data,
596 639 u16 len)
597 640 {
598   - struct mgmt_mode *cp, ev;
  641 + struct mgmt_mode *cp;
599 642 struct hci_dev *hdev;
  643 + __le32 ev;
600 644 int err;
601 645  
602 646 cp = (void *) data;
603 647  
604 648  
... ... @@ -619,13 +663,13 @@
619 663 else
620 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 667 if (err < 0)
624 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  
630 674 failed:
631 675 hci_dev_unlock(hdev);
632 676  
633 677  
634 678  
635 679  
... ... @@ -2234,18 +2278,15 @@
2234 2278 struct cmd_lookup {
2235 2279 u8 val;
2236 2280 struct sock *sk;
  2281 + struct hci_dev *hdev;
2237 2282 };
2238 2283  
2239   -static void mode_rsp(struct pending_cmd *cmd, void *data)
  2284 +static void settings_rsp(struct pending_cmd *cmd, void *data)
2240 2285 {
2241   - struct mgmt_mode *cp = cmd->param;
2242 2286 struct cmd_lookup *match = data;
2243 2287  
2244   - if (cp->val != match->val)
2245   - return;
  2288 + send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
2246 2289  
2247   - send_mode_rsp(cmd->sk, cmd->opcode, cmd->index, cp->val);
2248   -
2249 2290 list_del(&cmd->list);
2250 2291  
2251 2292 if (match->sk == NULL) {
2252 2293  
2253 2294  
2254 2295  
... ... @@ -2258,20 +2299,21 @@
2258 2299  
2259 2300 int mgmt_powered(struct hci_dev *hdev, u8 powered)
2260 2301 {
2261   - struct mgmt_mode ev;
2262   - struct cmd_lookup match = { powered, NULL };
  2302 + struct cmd_lookup match = { powered, NULL, hdev };
  2303 + __le32 ev;
2263 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 2308 if (!powered) {
2268 2309 u8 status = ENETDOWN;
2269 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 2318 if (match.sk)
2277 2319 sock_put(match.sk);
2278 2320  
2279 2321  
2280 2322  
2281 2323  
... ... @@ -2281,17 +2323,16 @@
2281 2323  
2282 2324 int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable)
2283 2325 {
2284   - struct mgmt_mode ev;
2285   - struct cmd_lookup match = { discoverable, NULL };
  2326 + struct cmd_lookup match = { discoverable, NULL, hdev };
  2327 + __le32 ev;
2286 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 2335 match.sk);
2294   -
2295 2336 if (match.sk)
2296 2337 sock_put(match.sk);
2297 2338  
2298 2339  
2299 2340  
2300 2341  
... ... @@ -2300,15 +2341,16 @@
2300 2341  
2301 2342 int mgmt_connectable(struct hci_dev *hdev, u8 connectable)
2302 2343 {
2303   - struct mgmt_mode ev;
2304   - struct cmd_lookup match = { connectable, NULL };
  2344 + __le32 ev;
  2345 + struct cmd_lookup match = { connectable, NULL, hdev };
2305 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 2355 if (match.sk)
2314 2356 sock_put(match.sk);