diff options
Diffstat (limited to 'net/bluetooth/hci_event.c')
-rw-r--r-- | net/bluetooth/hci_event.c | 127 |
1 files changed, 86 insertions, 41 deletions
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 918dc09164b..4221bd256bd 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -378,11 +378,8 @@ static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) | |||
378 | 378 | ||
379 | BT_DBG("%s voice setting 0x%04x", hdev->name, setting); | 379 | BT_DBG("%s voice setting 0x%04x", hdev->name, setting); |
380 | 380 | ||
381 | if (hdev->notify) { | 381 | if (hdev->notify) |
382 | tasklet_disable(&hdev->tx_task); | ||
383 | hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); | 382 | hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); |
384 | tasklet_enable(&hdev->tx_task); | ||
385 | } | ||
386 | } | 383 | } |
387 | 384 | ||
388 | static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) | 385 | static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) |
@@ -409,11 +406,8 @@ static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb | |||
409 | 406 | ||
410 | BT_DBG("%s voice setting 0x%04x", hdev->name, setting); | 407 | BT_DBG("%s voice setting 0x%04x", hdev->name, setting); |
411 | 408 | ||
412 | if (hdev->notify) { | 409 | if (hdev->notify) |
413 | tasklet_disable(&hdev->tx_task); | ||
414 | hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); | 410 | hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); |
415 | tasklet_enable(&hdev->tx_task); | ||
416 | } | ||
417 | } | 411 | } |
418 | 412 | ||
419 | static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) | 413 | static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) |
@@ -562,6 +556,9 @@ static void hci_set_le_support(struct hci_dev *hdev) | |||
562 | 556 | ||
563 | static void hci_setup(struct hci_dev *hdev) | 557 | static void hci_setup(struct hci_dev *hdev) |
564 | { | 558 | { |
559 | if (hdev->dev_type != HCI_BREDR) | ||
560 | return; | ||
561 | |||
565 | hci_setup_event_mask(hdev); | 562 | hci_setup_event_mask(hdev); |
566 | 563 | ||
567 | if (hdev->hci_ver > BLUETOOTH_VER_1_1) | 564 | if (hdev->hci_ver > BLUETOOTH_VER_1_1) |
@@ -773,6 +770,28 @@ static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb) | |||
773 | hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status); | 770 | hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status); |
774 | } | 771 | } |
775 | 772 | ||
773 | static void hci_cc_read_data_block_size(struct hci_dev *hdev, | ||
774 | struct sk_buff *skb) | ||
775 | { | ||
776 | struct hci_rp_read_data_block_size *rp = (void *) skb->data; | ||
777 | |||
778 | BT_DBG("%s status 0x%x", hdev->name, rp->status); | ||
779 | |||
780 | if (rp->status) | ||
781 | return; | ||
782 | |||
783 | hdev->block_mtu = __le16_to_cpu(rp->max_acl_len); | ||
784 | hdev->block_len = __le16_to_cpu(rp->block_len); | ||
785 | hdev->num_blocks = __le16_to_cpu(rp->num_blocks); | ||
786 | |||
787 | hdev->block_cnt = hdev->num_blocks; | ||
788 | |||
789 | BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu, | ||
790 | hdev->block_cnt, hdev->block_len); | ||
791 | |||
792 | hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status); | ||
793 | } | ||
794 | |||
776 | static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb) | 795 | static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb) |
777 | { | 796 | { |
778 | __u8 status = *((__u8 *) skb->data); | 797 | __u8 status = *((__u8 *) skb->data); |
@@ -1014,18 +1033,28 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, | |||
1014 | if (!cp) | 1033 | if (!cp) |
1015 | return; | 1034 | return; |
1016 | 1035 | ||
1017 | if (cp->enable == 0x01) { | 1036 | switch (cp->enable) { |
1037 | case LE_SCANNING_ENABLED: | ||
1018 | set_bit(HCI_LE_SCAN, &hdev->dev_flags); | 1038 | set_bit(HCI_LE_SCAN, &hdev->dev_flags); |
1019 | 1039 | ||
1020 | del_timer(&hdev->adv_timer); | 1040 | cancel_delayed_work_sync(&hdev->adv_work); |
1021 | 1041 | ||
1022 | hci_dev_lock(hdev); | 1042 | hci_dev_lock(hdev); |
1023 | hci_adv_entries_clear(hdev); | 1043 | hci_adv_entries_clear(hdev); |
1024 | hci_dev_unlock(hdev); | 1044 | hci_dev_unlock(hdev); |
1025 | } else if (cp->enable == 0x00) { | 1045 | break; |
1046 | |||
1047 | case LE_SCANNING_DISABLED: | ||
1026 | clear_bit(HCI_LE_SCAN, &hdev->dev_flags); | 1048 | clear_bit(HCI_LE_SCAN, &hdev->dev_flags); |
1027 | 1049 | ||
1028 | mod_timer(&hdev->adv_timer, jiffies + ADV_CLEAR_TIMEOUT); | 1050 | cancel_delayed_work_sync(&hdev->adv_work); |
1051 | queue_delayed_work(hdev->workqueue, &hdev->adv_work, | ||
1052 | jiffies + ADV_CLEAR_TIMEOUT); | ||
1053 | break; | ||
1054 | |||
1055 | default: | ||
1056 | BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable); | ||
1057 | break; | ||
1029 | } | 1058 | } |
1030 | } | 1059 | } |
1031 | 1060 | ||
@@ -2022,6 +2051,10 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk | |||
2022 | hci_cc_read_bd_addr(hdev, skb); | 2051 | hci_cc_read_bd_addr(hdev, skb); |
2023 | break; | 2052 | break; |
2024 | 2053 | ||
2054 | case HCI_OP_READ_DATA_BLOCK_SIZE: | ||
2055 | hci_cc_read_data_block_size(hdev, skb); | ||
2056 | break; | ||
2057 | |||
2025 | case HCI_OP_WRITE_CA_TIMEOUT: | 2058 | case HCI_OP_WRITE_CA_TIMEOUT: |
2026 | hci_cc_write_ca_timeout(hdev, skb); | 2059 | hci_cc_write_ca_timeout(hdev, skb); |
2027 | break; | 2060 | break; |
@@ -2116,7 +2149,7 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk | |||
2116 | if (ev->ncmd) { | 2149 | if (ev->ncmd) { |
2117 | atomic_set(&hdev->cmd_cnt, 1); | 2150 | atomic_set(&hdev->cmd_cnt, 1); |
2118 | if (!skb_queue_empty(&hdev->cmd_q)) | 2151 | if (!skb_queue_empty(&hdev->cmd_q)) |
2119 | tasklet_schedule(&hdev->cmd_task); | 2152 | queue_work(hdev->workqueue, &hdev->cmd_work); |
2120 | } | 2153 | } |
2121 | } | 2154 | } |
2122 | 2155 | ||
@@ -2198,7 +2231,7 @@ static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2198 | if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { | 2231 | if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { |
2199 | atomic_set(&hdev->cmd_cnt, 1); | 2232 | atomic_set(&hdev->cmd_cnt, 1); |
2200 | if (!skb_queue_empty(&hdev->cmd_q)) | 2233 | if (!skb_queue_empty(&hdev->cmd_q)) |
2201 | tasklet_schedule(&hdev->cmd_task); | 2234 | queue_work(hdev->workqueue, &hdev->cmd_work); |
2202 | } | 2235 | } |
2203 | } | 2236 | } |
2204 | 2237 | ||
@@ -2231,56 +2264,68 @@ static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb | |||
2231 | static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) | 2264 | static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) |
2232 | { | 2265 | { |
2233 | struct hci_ev_num_comp_pkts *ev = (void *) skb->data; | 2266 | struct hci_ev_num_comp_pkts *ev = (void *) skb->data; |
2234 | __le16 *ptr; | ||
2235 | int i; | 2267 | int i; |
2236 | 2268 | ||
2237 | skb_pull(skb, sizeof(*ev)); | 2269 | skb_pull(skb, sizeof(*ev)); |
2238 | 2270 | ||
2239 | BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl); | 2271 | BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl); |
2240 | 2272 | ||
2273 | if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) { | ||
2274 | BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode); | ||
2275 | return; | ||
2276 | } | ||
2277 | |||
2241 | if (skb->len < ev->num_hndl * 4) { | 2278 | if (skb->len < ev->num_hndl * 4) { |
2242 | BT_DBG("%s bad parameters", hdev->name); | 2279 | BT_DBG("%s bad parameters", hdev->name); |
2243 | return; | 2280 | return; |
2244 | } | 2281 | } |
2245 | 2282 | ||
2246 | tasklet_disable(&hdev->tx_task); | 2283 | for (i = 0; i < ev->num_hndl; i++) { |
2247 | 2284 | struct hci_comp_pkts_info *info = &ev->handles[i]; | |
2248 | for (i = 0, ptr = (__le16 *) skb->data; i < ev->num_hndl; i++) { | ||
2249 | struct hci_conn *conn; | 2285 | struct hci_conn *conn; |
2250 | __u16 handle, count; | 2286 | __u16 handle, count; |
2251 | 2287 | ||
2252 | handle = get_unaligned_le16(ptr++); | 2288 | handle = __le16_to_cpu(info->handle); |
2253 | count = get_unaligned_le16(ptr++); | 2289 | count = __le16_to_cpu(info->count); |
2254 | 2290 | ||
2255 | conn = hci_conn_hash_lookup_handle(hdev, handle); | 2291 | conn = hci_conn_hash_lookup_handle(hdev, handle); |
2256 | if (conn) { | 2292 | if (!conn) |
2257 | conn->sent -= count; | 2293 | continue; |
2258 | 2294 | ||
2259 | if (conn->type == ACL_LINK) { | 2295 | conn->sent -= count; |
2296 | |||
2297 | switch (conn->type) { | ||
2298 | case ACL_LINK: | ||
2299 | hdev->acl_cnt += count; | ||
2300 | if (hdev->acl_cnt > hdev->acl_pkts) | ||
2301 | hdev->acl_cnt = hdev->acl_pkts; | ||
2302 | break; | ||
2303 | |||
2304 | case LE_LINK: | ||
2305 | if (hdev->le_pkts) { | ||
2306 | hdev->le_cnt += count; | ||
2307 | if (hdev->le_cnt > hdev->le_pkts) | ||
2308 | hdev->le_cnt = hdev->le_pkts; | ||
2309 | } else { | ||
2260 | hdev->acl_cnt += count; | 2310 | hdev->acl_cnt += count; |
2261 | if (hdev->acl_cnt > hdev->acl_pkts) | 2311 | if (hdev->acl_cnt > hdev->acl_pkts) |
2262 | hdev->acl_cnt = hdev->acl_pkts; | 2312 | hdev->acl_cnt = hdev->acl_pkts; |
2263 | } else if (conn->type == LE_LINK) { | ||
2264 | if (hdev->le_pkts) { | ||
2265 | hdev->le_cnt += count; | ||
2266 | if (hdev->le_cnt > hdev->le_pkts) | ||
2267 | hdev->le_cnt = hdev->le_pkts; | ||
2268 | } else { | ||
2269 | hdev->acl_cnt += count; | ||
2270 | if (hdev->acl_cnt > hdev->acl_pkts) | ||
2271 | hdev->acl_cnt = hdev->acl_pkts; | ||
2272 | } | ||
2273 | } else { | ||
2274 | hdev->sco_cnt += count; | ||
2275 | if (hdev->sco_cnt > hdev->sco_pkts) | ||
2276 | hdev->sco_cnt = hdev->sco_pkts; | ||
2277 | } | 2313 | } |
2314 | break; | ||
2315 | |||
2316 | case SCO_LINK: | ||
2317 | hdev->sco_cnt += count; | ||
2318 | if (hdev->sco_cnt > hdev->sco_pkts) | ||
2319 | hdev->sco_cnt = hdev->sco_pkts; | ||
2320 | break; | ||
2321 | |||
2322 | default: | ||
2323 | BT_ERR("Unknown type %d conn %p", conn->type, conn); | ||
2324 | break; | ||
2278 | } | 2325 | } |
2279 | } | 2326 | } |
2280 | 2327 | ||
2281 | tasklet_schedule(&hdev->tx_task); | 2328 | queue_work(hdev->workqueue, &hdev->tx_work); |
2282 | |||
2283 | tasklet_enable(&hdev->tx_task); | ||
2284 | } | 2329 | } |
2285 | 2330 | ||
2286 | static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) | 2331 | static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) |