Bluetooth: Add mgmt command for fast connectable mode
authorAntti Julku <antti.julku@nokia.com>
Wed, 22 Jun 2011 10:11:56 +0000 (13:11 +0300)
committerGustavo F. Padovan <padovan@profusion.mobi>
Wed, 21 Sep 2011 15:58:12 +0000 (12:58 -0300)
Add command to management interface for enabling/disabling the
fast connectable mode.

Signed-off-by: Antti Julku <antti.julku@nokia.com>
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
include/net/bluetooth/hci.h
include/net/bluetooth/mgmt.h
net/bluetooth/mgmt.c

index be30aabe7b88b95825eab3e65dc606ae91d3ea83..aaf79af7243262592607924aa1e4dd609da7d2aa 100644 (file)
@@ -716,6 +716,16 @@ struct hci_rp_read_bd_addr {
        bdaddr_t bdaddr;
 } __packed;
 
+#define HCI_OP_WRITE_PAGE_SCAN_ACTIVITY        0x0c1c
+struct hci_cp_write_page_scan_activity {
+       __le16   interval;
+       __le16   window;
+} __packed;
+
+#define HCI_OP_WRITE_PAGE_SCAN_TYPE    0x0c47
+       #define PAGE_SCAN_TYPE_STANDARD         0x00
+       #define PAGE_SCAN_TYPE_INTERLACED       0x01
+
 #define HCI_OP_LE_SET_EVENT_MASK       0x2001
 struct hci_cp_le_set_event_mask {
        __u8     mask[8];
index 1c914ddc6d7a668ccf9f4aaaad2a73d6742d79fc..48522e6386bf8a1430984ee0fdc43411fb62c5b2 100644 (file)
@@ -211,6 +211,11 @@ struct mgmt_cp_unblock_device {
        bdaddr_t bdaddr;
 } __packed;
 
+#define MGMT_OP_SET_FAST_CONNECTABLE   0x001F
+struct mgmt_cp_set_fast_connectable {
+       __u8 enable;
+} __packed;
+
 #define MGMT_EV_CMD_COMPLETE           0x0001
 struct mgmt_ev_cmd_complete {
        __le16 opcode;
index dac7d39b810b90c8af539cab8f7fe4fb04ae74cd..545f84dbae85cb9fdb579e5d7f0a3d779183a075 100644 (file)
@@ -1760,6 +1760,62 @@ static int unblock_device(struct sock *sk, u16 index, unsigned char *data,
        return err;
 }
 
+static int set_fast_connectable(struct sock *sk, u16 index,
+                                       unsigned char *data, u16 len)
+{
+       struct hci_dev *hdev;
+       struct mgmt_cp_set_fast_connectable *cp = (void *) data;
+       struct hci_cp_write_page_scan_activity acp;
+       u8 type;
+       int err;
+
+       BT_DBG("hci%u", index);
+
+       if (len != sizeof(*cp))
+               return cmd_status(sk, index, MGMT_OP_SET_FAST_CONNECTABLE,
+                                                               EINVAL);
+
+       hdev = hci_dev_get(index);
+       if (!hdev)
+               return cmd_status(sk, index, MGMT_OP_SET_FAST_CONNECTABLE,
+                                                               ENODEV);
+
+       hci_dev_lock(hdev);
+
+       if (cp->enable) {
+               type = PAGE_SCAN_TYPE_INTERLACED;
+               acp.interval = 0x0024;  /* 22.5 msec page scan interval */
+       } else {
+               type = PAGE_SCAN_TYPE_STANDARD; /* default */
+               acp.interval = 0x0800;  /* default 1.28 sec page scan */
+       }
+
+       acp.window = 0x0012;    /* default 11.25 msec page scan window */
+
+       err = hci_send_cmd(hdev, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
+                                               sizeof(acp), &acp);
+       if (err < 0) {
+               err = cmd_status(sk, index, MGMT_OP_SET_FAST_CONNECTABLE,
+                                                               -err);
+               goto done;
+       }
+
+       err = hci_send_cmd(hdev, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
+       if (err < 0) {
+               err = cmd_status(sk, index, MGMT_OP_SET_FAST_CONNECTABLE,
+                                                               -err);
+               goto done;
+       }
+
+       err = cmd_complete(sk, index, MGMT_OP_SET_FAST_CONNECTABLE,
+                                                       NULL, 0);
+done:
+       hci_dev_unlock(hdev);
+       hci_dev_put(hdev);
+
+       return err;
+}
+
 int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
 {
        unsigned char *buf;
@@ -1880,6 +1936,10 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
        case MGMT_OP_UNBLOCK_DEVICE:
                err = unblock_device(sk, index, buf + sizeof(*hdr), len);
                break;
+       case MGMT_OP_SET_FAST_CONNECTABLE:
+               err = set_fast_connectable(sk, index, buf + sizeof(*hdr),
+                                                               len);
+               break;
        default:
                BT_DBG("Unknown op %u", opcode);
                err = cmd_status(sk, index, opcode, 0x01);