aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/hci_conn.c
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2006-07-03 04:02:33 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-07-03 22:53:58 -0400
commit04837f6447c7f3ef114cda1ad761822dedbff8cf (patch)
tree66dbb53e82550723191ffe54f0457eafc3a92d32 /net/bluetooth/hci_conn.c
parentda1f519851d1c66331363253f364bdb5d924ea96 (diff)
[Bluetooth] Add automatic sniff mode support
This patch introduces the automatic sniff mode feature. This allows the host to switch idle connections into sniff mode to safe power. Signed-off-by: Ulisses Furquim <ulissesf@gmail.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth/hci_conn.c')
-rw-r--r--net/bluetooth/hci_conn.c100
1 files changed, 89 insertions, 11 deletions
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 5c0c2b1ef34a..420ed4d7e57e 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -115,8 +115,8 @@ void hci_add_sco(struct hci_conn *conn, __u16 handle)
115 115
116static void hci_conn_timeout(unsigned long arg) 116static void hci_conn_timeout(unsigned long arg)
117{ 117{
118 struct hci_conn *conn = (void *)arg; 118 struct hci_conn *conn = (void *) arg;
119 struct hci_dev *hdev = conn->hdev; 119 struct hci_dev *hdev = conn->hdev;
120 120
121 BT_DBG("conn %p state %d", conn, conn->state); 121 BT_DBG("conn %p state %d", conn, conn->state);
122 122
@@ -132,11 +132,13 @@ static void hci_conn_timeout(unsigned long arg)
132 return; 132 return;
133} 133}
134 134
135static void hci_conn_init_timer(struct hci_conn *conn) 135static void hci_conn_idle(unsigned long arg)
136{ 136{
137 init_timer(&conn->timer); 137 struct hci_conn *conn = (void *) arg;
138 conn->timer.function = hci_conn_timeout; 138
139 conn->timer.data = (unsigned long)conn; 139 BT_DBG("conn %p mode %d", conn, conn->mode);
140
141 hci_conn_enter_sniff_mode(conn);
140} 142}
141 143
142struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) 144struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
@@ -145,17 +147,27 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
145 147
146 BT_DBG("%s dst %s", hdev->name, batostr(dst)); 148 BT_DBG("%s dst %s", hdev->name, batostr(dst));
147 149
148 if (!(conn = kmalloc(sizeof(struct hci_conn), GFP_ATOMIC))) 150 conn = kzalloc(sizeof(struct hci_conn), GFP_ATOMIC);
151 if (!conn)
149 return NULL; 152 return NULL;
150 memset(conn, 0, sizeof(struct hci_conn));
151 153
152 bacpy(&conn->dst, dst); 154 bacpy(&conn->dst, dst);
153 conn->type = type;
154 conn->hdev = hdev; 155 conn->hdev = hdev;
156 conn->type = type;
157 conn->mode = HCI_CM_ACTIVE;
155 conn->state = BT_OPEN; 158 conn->state = BT_OPEN;
156 159
160 conn->power_save = 1;
161
157 skb_queue_head_init(&conn->data_q); 162 skb_queue_head_init(&conn->data_q);
158 hci_conn_init_timer(conn); 163
164 init_timer(&conn->disc_timer);
165 conn->disc_timer.function = hci_conn_timeout;
166 conn->disc_timer.data = (unsigned long) conn;
167
168 init_timer(&conn->idle_timer);
169 conn->idle_timer.function = hci_conn_idle;
170 conn->idle_timer.data = (unsigned long) conn;
159 171
160 atomic_set(&conn->refcnt, 0); 172 atomic_set(&conn->refcnt, 0);
161 173
@@ -178,7 +190,9 @@ int hci_conn_del(struct hci_conn *conn)
178 190
179 BT_DBG("%s conn %p handle %d", hdev->name, conn, conn->handle); 191 BT_DBG("%s conn %p handle %d", hdev->name, conn, conn->handle);
180 192
181 hci_conn_del_timer(conn); 193 del_timer(&conn->idle_timer);
194
195 del_timer(&conn->disc_timer);
182 196
183 if (conn->type == SCO_LINK) { 197 if (conn->type == SCO_LINK) {
184 struct hci_conn *acl = conn->link; 198 struct hci_conn *acl = conn->link;
@@ -364,6 +378,70 @@ int hci_conn_switch_role(struct hci_conn *conn, uint8_t role)
364} 378}
365EXPORT_SYMBOL(hci_conn_switch_role); 379EXPORT_SYMBOL(hci_conn_switch_role);
366 380
381/* Enter active mode */
382void hci_conn_enter_active_mode(struct hci_conn *conn)
383{
384 struct hci_dev *hdev = conn->hdev;
385
386 BT_DBG("conn %p mode %d", conn, conn->mode);
387
388 if (test_bit(HCI_RAW, &hdev->flags))
389 return;
390
391 if (conn->mode != HCI_CM_SNIFF || !conn->power_save)
392 goto timer;
393
394 if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
395 struct hci_cp_exit_sniff_mode cp;
396 cp.handle = __cpu_to_le16(conn->handle);
397 hci_send_cmd(hdev, OGF_LINK_POLICY,
398 OCF_EXIT_SNIFF_MODE, sizeof(cp), &cp);
399 }
400
401timer:
402 if (hdev->idle_timeout > 0)
403 mod_timer(&conn->idle_timer,
404 jiffies + msecs_to_jiffies(hdev->idle_timeout));
405}
406
407/* Enter sniff mode */
408void hci_conn_enter_sniff_mode(struct hci_conn *conn)
409{
410 struct hci_dev *hdev = conn->hdev;
411
412 BT_DBG("conn %p mode %d", conn, conn->mode);
413
414 if (test_bit(HCI_RAW, &hdev->flags))
415 return;
416
417 if (!lmp_sniff_capable(hdev) || !lmp_sniff_capable(conn))
418 return;
419
420 if (conn->mode != HCI_CM_ACTIVE || !(conn->link_policy & HCI_LP_SNIFF))
421 return;
422
423 if (lmp_sniffsubr_capable(hdev) && lmp_sniffsubr_capable(conn)) {
424 struct hci_cp_sniff_subrate cp;
425 cp.handle = __cpu_to_le16(conn->handle);
426 cp.max_latency = __constant_cpu_to_le16(0);
427 cp.min_remote_timeout = __constant_cpu_to_le16(0);
428 cp.min_local_timeout = __constant_cpu_to_le16(0);
429 hci_send_cmd(hdev, OGF_LINK_POLICY,
430 OCF_SNIFF_SUBRATE, sizeof(cp), &cp);
431 }
432
433 if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
434 struct hci_cp_sniff_mode cp;
435 cp.handle = __cpu_to_le16(conn->handle);
436 cp.max_interval = __cpu_to_le16(hdev->sniff_max_interval);
437 cp.min_interval = __cpu_to_le16(hdev->sniff_min_interval);
438 cp.attempt = __constant_cpu_to_le16(4);
439 cp.timeout = __constant_cpu_to_le16(1);
440 hci_send_cmd(hdev, OGF_LINK_POLICY,
441 OCF_SNIFF_MODE, sizeof(cp), &cp);
442 }
443}
444
367/* Drop all connection on the device */ 445/* Drop all connection on the device */
368void hci_conn_hash_flush(struct hci_dev *hdev) 446void hci_conn_hash_flush(struct hci_dev *hdev)
369{ 447{