aboutsummaryrefslogtreecommitdiffstats
path: root/include
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 /include
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 'include')
-rw-r--r--include/net/bluetooth/hci.h70
-rw-r--r--include/net/bluetooth/hci_core.h54
2 files changed, 86 insertions, 38 deletions
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 99c53f6b8252..b2bdb1aa0429 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -101,9 +101,10 @@ enum {
101#define HCIINQUIRY _IOR('H', 240, int) 101#define HCIINQUIRY _IOR('H', 240, int)
102 102
103/* HCI timeouts */ 103/* HCI timeouts */
104#define HCI_CONN_TIMEOUT (HZ * 40) 104#define HCI_CONNECT_TIMEOUT (40000) /* 40 seconds */
105#define HCI_DISCONN_TIMEOUT (HZ * 2) 105#define HCI_DISCONN_TIMEOUT (2000) /* 2 seconds */
106#define HCI_CONN_IDLE_TIMEOUT (HZ * 60) 106#define HCI_IDLE_TIMEOUT (6000) /* 6 seconds */
107#define HCI_INIT_TIMEOUT (10000) /* 10 seconds */
107 108
108/* HCI Packet types */ 109/* HCI Packet types */
109#define HCI_COMMAND_PKT 0x01 110#define HCI_COMMAND_PKT 0x01
@@ -145,7 +146,7 @@ enum {
145#define LMP_TACCURACY 0x10 146#define LMP_TACCURACY 0x10
146#define LMP_RSWITCH 0x20 147#define LMP_RSWITCH 0x20
147#define LMP_HOLD 0x40 148#define LMP_HOLD 0x40
148#define LMP_SNIF 0x80 149#define LMP_SNIFF 0x80
149 150
150#define LMP_PARK 0x01 151#define LMP_PARK 0x01
151#define LMP_RSSI 0x02 152#define LMP_RSSI 0x02
@@ -160,13 +161,21 @@ enum {
160#define LMP_PSCHEME 0x02 161#define LMP_PSCHEME 0x02
161#define LMP_PCONTROL 0x04 162#define LMP_PCONTROL 0x04
162 163
164#define LMP_SNIFF_SUBR 0x02
165
166/* Connection modes */
167#define HCI_CM_ACTIVE 0x0000
168#define HCI_CM_HOLD 0x0001
169#define HCI_CM_SNIFF 0x0002
170#define HCI_CM_PARK 0x0003
171
163/* Link policies */ 172/* Link policies */
164#define HCI_LP_RSWITCH 0x0001 173#define HCI_LP_RSWITCH 0x0001
165#define HCI_LP_HOLD 0x0002 174#define HCI_LP_HOLD 0x0002
166#define HCI_LP_SNIFF 0x0004 175#define HCI_LP_SNIFF 0x0004
167#define HCI_LP_PARK 0x0008 176#define HCI_LP_PARK 0x0008
168 177
169/* Link mode */ 178/* Link modes */
170#define HCI_LM_ACCEPT 0x8000 179#define HCI_LM_ACCEPT 0x8000
171#define HCI_LM_MASTER 0x0001 180#define HCI_LM_MASTER 0x0001
172#define HCI_LM_AUTH 0x0002 181#define HCI_LM_AUTH 0x0002
@@ -192,7 +201,7 @@ struct hci_rp_read_loc_version {
192} __attribute__ ((packed)); 201} __attribute__ ((packed));
193 202
194#define OCF_READ_LOCAL_FEATURES 0x0003 203#define OCF_READ_LOCAL_FEATURES 0x0003
195struct hci_rp_read_loc_features { 204struct hci_rp_read_local_features {
196 __u8 status; 205 __u8 status;
197 __u8 features[8]; 206 __u8 features[8];
198} __attribute__ ((packed)); 207} __attribute__ ((packed));
@@ -376,17 +385,32 @@ struct hci_cp_change_conn_link_key {
376} __attribute__ ((packed)); 385} __attribute__ ((packed));
377 386
378#define OCF_READ_REMOTE_FEATURES 0x001B 387#define OCF_READ_REMOTE_FEATURES 0x001B
379struct hci_cp_read_rmt_features { 388struct hci_cp_read_remote_features {
380 __le16 handle; 389 __le16 handle;
381} __attribute__ ((packed)); 390} __attribute__ ((packed));
382 391
383#define OCF_READ_REMOTE_VERSION 0x001D 392#define OCF_READ_REMOTE_VERSION 0x001D
384struct hci_cp_read_rmt_version { 393struct hci_cp_read_remote_version {
385 __le16 handle; 394 __le16 handle;
386} __attribute__ ((packed)); 395} __attribute__ ((packed));
387 396
388/* Link Policy */ 397/* Link Policy */
389#define OGF_LINK_POLICY 0x02 398#define OGF_LINK_POLICY 0x02
399
400#define OCF_SNIFF_MODE 0x0003
401struct hci_cp_sniff_mode {
402 __le16 handle;
403 __le16 max_interval;
404 __le16 min_interval;
405 __le16 attempt;
406 __le16 timeout;
407} __attribute__ ((packed));
408
409#define OCF_EXIT_SNIFF_MODE 0x0004
410struct hci_cp_exit_sniff_mode {
411 __le16 handle;
412} __attribute__ ((packed));
413
390#define OCF_ROLE_DISCOVERY 0x0009 414#define OCF_ROLE_DISCOVERY 0x0009
391struct hci_cp_role_discovery { 415struct hci_cp_role_discovery {
392 __le16 handle; 416 __le16 handle;
@@ -407,7 +431,7 @@ struct hci_rp_read_link_policy {
407 __le16 policy; 431 __le16 policy;
408} __attribute__ ((packed)); 432} __attribute__ ((packed));
409 433
410#define OCF_SWITCH_ROLE 0x000B 434#define OCF_SWITCH_ROLE 0x000B
411struct hci_cp_switch_role { 435struct hci_cp_switch_role {
412 bdaddr_t bdaddr; 436 bdaddr_t bdaddr;
413 __u8 role; 437 __u8 role;
@@ -423,6 +447,14 @@ struct hci_rp_write_link_policy {
423 __le16 handle; 447 __le16 handle;
424} __attribute__ ((packed)); 448} __attribute__ ((packed));
425 449
450#define OCF_SNIFF_SUBRATE 0x0011
451struct hci_cp_sniff_subrate {
452 __le16 handle;
453 __le16 max_latency;
454 __le16 min_remote_timeout;
455 __le16 min_local_timeout;
456} __attribute__ ((packed));
457
426/* Status params */ 458/* Status params */
427#define OGF_STATUS_PARAM 0x05 459#define OGF_STATUS_PARAM 0x05
428 460
@@ -582,15 +614,15 @@ struct hci_ev_link_key_notify {
582 __u8 key_type; 614 __u8 key_type;
583} __attribute__ ((packed)); 615} __attribute__ ((packed));
584 616
585#define HCI_EV_RMT_FEATURES 0x0B 617#define HCI_EV_REMOTE_FEATURES 0x0B
586struct hci_ev_rmt_features { 618struct hci_ev_remote_features {
587 __u8 status; 619 __u8 status;
588 __le16 handle; 620 __le16 handle;
589 __u8 features[8]; 621 __u8 features[8];
590} __attribute__ ((packed)); 622} __attribute__ ((packed));
591 623
592#define HCI_EV_RMT_VERSION 0x0C 624#define HCI_EV_REMOTE_VERSION 0x0C
593struct hci_ev_rmt_version { 625struct hci_ev_remote_version {
594 __u8 status; 626 __u8 status;
595 __le16 handle; 627 __le16 handle;
596 __u8 lmp_ver; 628 __u8 lmp_ver;
@@ -611,6 +643,16 @@ struct hci_ev_pscan_rep_mode {
611 __u8 pscan_rep_mode; 643 __u8 pscan_rep_mode;
612} __attribute__ ((packed)); 644} __attribute__ ((packed));
613 645
646#define HCI_EV_SNIFF_SUBRATE 0x2E
647struct hci_ev_sniff_subrate {
648 __u8 status;
649 __le16 handle;
650 __le16 max_tx_latency;
651 __le16 max_rx_latency;
652 __le16 max_remote_timeout;
653 __le16 max_local_timeout;
654} __attribute__ ((packed));
655
614/* Internal events generated by Bluetooth stack */ 656/* Internal events generated by Bluetooth stack */
615#define HCI_EV_STACK_INTERNAL 0xFD 657#define HCI_EV_STACK_INTERNAL 0xFD
616struct hci_ev_stack_internal { 658struct hci_ev_stack_internal {
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index bb9f81dc8723..f6852707bd64 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -31,10 +31,7 @@
31#define HCI_PROTO_L2CAP 0 31#define HCI_PROTO_L2CAP 0
32#define HCI_PROTO_SCO 1 32#define HCI_PROTO_SCO 1
33 33
34#define HCI_INIT_TIMEOUT (HZ * 10)
35
36/* HCI Core structures */ 34/* HCI Core structures */
37
38struct inquiry_data { 35struct inquiry_data {
39 bdaddr_t bdaddr; 36 bdaddr_t bdaddr;
40 __u8 pscan_rep_mode; 37 __u8 pscan_rep_mode;
@@ -81,6 +78,10 @@ struct hci_dev {
81 __u16 link_policy; 78 __u16 link_policy;
82 __u16 link_mode; 79 __u16 link_mode;
83 80
81 __u32 idle_timeout;
82 __u16 sniff_min_interval;
83 __u16 sniff_max_interval;
84
84 unsigned long quirks; 85 unsigned long quirks;
85 86
86 atomic_t cmd_cnt; 87 atomic_t cmd_cnt;
@@ -145,18 +146,24 @@ struct hci_conn {
145 bdaddr_t dst; 146 bdaddr_t dst;
146 __u16 handle; 147 __u16 handle;
147 __u16 state; 148 __u16 state;
149 __u8 mode;
148 __u8 type; 150 __u8 type;
149 __u8 out; 151 __u8 out;
150 __u8 dev_class[3]; 152 __u8 dev_class[3];
153 __u8 features[8];
154 __u16 interval;
155 __u16 link_policy;
151 __u32 link_mode; 156 __u32 link_mode;
157 __u8 power_save;
152 unsigned long pend; 158 unsigned long pend;
153 159
154 unsigned int sent; 160 unsigned int sent;
155 161
156 struct sk_buff_head data_q; 162 struct sk_buff_head data_q;
157 163
158 struct timer_list timer; 164 struct timer_list disc_timer;
159 165 struct timer_list idle_timer;
166
160 struct hci_dev *hdev; 167 struct hci_dev *hdev;
161 void *l2cap_data; 168 void *l2cap_data;
162 void *sco_data; 169 void *sco_data;
@@ -211,7 +218,8 @@ void hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data);
211enum { 218enum {
212 HCI_CONN_AUTH_PEND, 219 HCI_CONN_AUTH_PEND,
213 HCI_CONN_ENCRYPT_PEND, 220 HCI_CONN_ENCRYPT_PEND,
214 HCI_CONN_RSWITCH_PEND 221 HCI_CONN_RSWITCH_PEND,
222 HCI_CONN_MODE_CHANGE_PEND,
215}; 223};
216 224
217static inline void hci_conn_hash_init(struct hci_dev *hdev) 225static inline void hci_conn_hash_init(struct hci_dev *hdev)
@@ -286,31 +294,27 @@ int hci_conn_encrypt(struct hci_conn *conn);
286int hci_conn_change_link_key(struct hci_conn *conn); 294int hci_conn_change_link_key(struct hci_conn *conn);
287int hci_conn_switch_role(struct hci_conn *conn, uint8_t role); 295int hci_conn_switch_role(struct hci_conn *conn, uint8_t role);
288 296
289static inline void hci_conn_set_timer(struct hci_conn *conn, unsigned long timeout) 297void hci_conn_enter_active_mode(struct hci_conn *conn);
290{ 298void hci_conn_enter_sniff_mode(struct hci_conn *conn);
291 mod_timer(&conn->timer, jiffies + timeout);
292}
293
294static inline void hci_conn_del_timer(struct hci_conn *conn)
295{
296 del_timer(&conn->timer);
297}
298 299
299static inline void hci_conn_hold(struct hci_conn *conn) 300static inline void hci_conn_hold(struct hci_conn *conn)
300{ 301{
301 atomic_inc(&conn->refcnt); 302 atomic_inc(&conn->refcnt);
302 hci_conn_del_timer(conn); 303 del_timer(&conn->disc_timer);
303} 304}
304 305
305static inline void hci_conn_put(struct hci_conn *conn) 306static inline void hci_conn_put(struct hci_conn *conn)
306{ 307{
307 if (atomic_dec_and_test(&conn->refcnt)) { 308 if (atomic_dec_and_test(&conn->refcnt)) {
309 unsigned long timeo;
308 if (conn->type == ACL_LINK) { 310 if (conn->type == ACL_LINK) {
309 unsigned long timeo = (conn->out) ? 311 timeo = msecs_to_jiffies(HCI_DISCONN_TIMEOUT);
310 HCI_DISCONN_TIMEOUT : HCI_DISCONN_TIMEOUT * 2; 312 if (!conn->out)
311 hci_conn_set_timer(conn, timeo); 313 timeo *= 2;
314 del_timer(&conn->idle_timer);
312 } else 315 } else
313 hci_conn_set_timer(conn, HZ / 100); 316 timeo = msecs_to_jiffies(10);
317 mod_timer(&conn->disc_timer, jiffies + timeo);
314 } 318 }
315} 319}
316 320
@@ -411,8 +415,10 @@ void hci_unregister_sysfs(struct hci_dev *hdev);
411#define SET_HCIDEV_DEV(hdev, pdev) ((hdev)->class_dev.dev = (pdev)) 415#define SET_HCIDEV_DEV(hdev, pdev) ((hdev)->class_dev.dev = (pdev))
412 416
413/* ----- LMP capabilities ----- */ 417/* ----- LMP capabilities ----- */
414#define lmp_rswitch_capable(dev) (dev->features[0] & LMP_RSWITCH) 418#define lmp_rswitch_capable(dev) ((dev)->features[0] & LMP_RSWITCH)
415#define lmp_encrypt_capable(dev) (dev->features[0] & LMP_ENCRYPT) 419#define lmp_encrypt_capable(dev) ((dev)->features[0] & LMP_ENCRYPT)
420#define lmp_sniff_capable(dev) ((dev)->features[0] & LMP_SNIFF)
421#define lmp_sniffsubr_capable(dev) ((dev)->features[5] & LMP_SNIFF_SUBR)
416 422
417/* ----- HCI protocols ----- */ 423/* ----- HCI protocols ----- */
418struct hci_proto { 424struct hci_proto {