diff options
| author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-07-05 13:13:03 -0400 |
|---|---|---|
| committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-07-05 13:13:03 -0400 |
| commit | 5e66dd6d66ffe758b39b6dcadf2330753ee1159b (patch) | |
| tree | a72cdcff4448e4af9425cc213ddf56ab23e697fe /net/bluetooth/hci_conn.c | |
| parent | 026477c1141b67e98e3bd8bdedb7d4b88a3ecd09 (diff) | |
| parent | ca78f6baca863afe2e6a244a0fe94b3a70211d46 (diff) | |
Merge branch 'master' of /home/trondmy/kernel/linux-2.6/
Diffstat (limited to 'net/bluetooth/hci_conn.c')
| -rw-r--r-- | net/bluetooth/hci_conn.c | 100 |
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 | ||
| 116 | static void hci_conn_timeout(unsigned long arg) | 116 | static 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 | ||
| 135 | static void hci_conn_init_timer(struct hci_conn *conn) | 135 | static 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 | ||
| 142 | struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) | 144 | struct 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 | } |
| 365 | EXPORT_SYMBOL(hci_conn_switch_role); | 379 | EXPORT_SYMBOL(hci_conn_switch_role); |
| 366 | 380 | ||
| 381 | /* Enter active mode */ | ||
| 382 | void 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 | |||
| 401 | timer: | ||
| 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 */ | ||
| 408 | void 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 */ |
| 368 | void hci_conn_hash_flush(struct hci_dev *hdev) | 446 | void hci_conn_hash_flush(struct hci_dev *hdev) |
| 369 | { | 447 | { |
