aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/hci_event.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/bluetooth/hci_event.c')
-rw-r--r--net/bluetooth/hci_event.c127
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
388static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) 385static 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
419static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 413static 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
563static void hci_setup(struct hci_dev *hdev) 557static 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
773static 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
776static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb) 795static 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
2231static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) 2264static 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
2286static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2331static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)