diff options
Diffstat (limited to 'net/bluetooth/hci_event.c')
| -rw-r--r-- | net/bluetooth/hci_event.c | 81 |
1 files changed, 66 insertions, 15 deletions
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 46367bd129c3..d6da0939216d 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
| @@ -484,14 +484,18 @@ static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff | |||
| 484 | /* Inquiry Result */ | 484 | /* Inquiry Result */ |
| 485 | static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) | 485 | static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) |
| 486 | { | 486 | { |
| 487 | struct inquiry_data data; | ||
| 487 | struct inquiry_info *info = (struct inquiry_info *) (skb->data + 1); | 488 | struct inquiry_info *info = (struct inquiry_info *) (skb->data + 1); |
| 488 | int num_rsp = *((__u8 *) skb->data); | 489 | int num_rsp = *((__u8 *) skb->data); |
| 489 | 490 | ||
| 490 | BT_DBG("%s num_rsp %d", hdev->name, num_rsp); | 491 | BT_DBG("%s num_rsp %d", hdev->name, num_rsp); |
| 491 | 492 | ||
| 493 | if (!num_rsp) | ||
| 494 | return; | ||
| 495 | |||
| 492 | hci_dev_lock(hdev); | 496 | hci_dev_lock(hdev); |
| 497 | |||
| 493 | for (; num_rsp; num_rsp--) { | 498 | for (; num_rsp; num_rsp--) { |
| 494 | struct inquiry_data data; | ||
| 495 | bacpy(&data.bdaddr, &info->bdaddr); | 499 | bacpy(&data.bdaddr, &info->bdaddr); |
| 496 | data.pscan_rep_mode = info->pscan_rep_mode; | 500 | data.pscan_rep_mode = info->pscan_rep_mode; |
| 497 | data.pscan_period_mode = info->pscan_period_mode; | 501 | data.pscan_period_mode = info->pscan_period_mode; |
| @@ -502,30 +506,55 @@ static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff * | |||
| 502 | info++; | 506 | info++; |
| 503 | hci_inquiry_cache_update(hdev, &data); | 507 | hci_inquiry_cache_update(hdev, &data); |
| 504 | } | 508 | } |
| 509 | |||
| 505 | hci_dev_unlock(hdev); | 510 | hci_dev_unlock(hdev); |
| 506 | } | 511 | } |
| 507 | 512 | ||
| 508 | /* Inquiry Result With RSSI */ | 513 | /* Inquiry Result With RSSI */ |
| 509 | static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb) | 514 | static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb) |
| 510 | { | 515 | { |
| 511 | struct inquiry_info_with_rssi *info = (struct inquiry_info_with_rssi *) (skb->data + 1); | 516 | struct inquiry_data data; |
| 512 | int num_rsp = *((__u8 *) skb->data); | 517 | int num_rsp = *((__u8 *) skb->data); |
| 513 | 518 | ||
| 514 | BT_DBG("%s num_rsp %d", hdev->name, num_rsp); | 519 | BT_DBG("%s num_rsp %d", hdev->name, num_rsp); |
| 515 | 520 | ||
| 521 | if (!num_rsp) | ||
| 522 | return; | ||
| 523 | |||
| 516 | hci_dev_lock(hdev); | 524 | hci_dev_lock(hdev); |
| 517 | for (; num_rsp; num_rsp--) { | 525 | |
| 518 | struct inquiry_data data; | 526 | if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) { |
| 519 | bacpy(&data.bdaddr, &info->bdaddr); | 527 | struct inquiry_info_with_rssi_and_pscan_mode *info = |
| 520 | data.pscan_rep_mode = info->pscan_rep_mode; | 528 | (struct inquiry_info_with_rssi_and_pscan_mode *) (skb->data + 1); |
| 521 | data.pscan_period_mode = info->pscan_period_mode; | 529 | |
| 522 | data.pscan_mode = 0x00; | 530 | for (; num_rsp; num_rsp--) { |
| 523 | memcpy(data.dev_class, info->dev_class, 3); | 531 | bacpy(&data.bdaddr, &info->bdaddr); |
| 524 | data.clock_offset = info->clock_offset; | 532 | data.pscan_rep_mode = info->pscan_rep_mode; |
| 525 | data.rssi = info->rssi; | 533 | data.pscan_period_mode = info->pscan_period_mode; |
| 526 | info++; | 534 | data.pscan_mode = info->pscan_mode; |
| 527 | hci_inquiry_cache_update(hdev, &data); | 535 | memcpy(data.dev_class, info->dev_class, 3); |
| 536 | data.clock_offset = info->clock_offset; | ||
| 537 | data.rssi = info->rssi; | ||
| 538 | info++; | ||
| 539 | hci_inquiry_cache_update(hdev, &data); | ||
| 540 | } | ||
| 541 | } else { | ||
| 542 | struct inquiry_info_with_rssi *info = | ||
| 543 | (struct inquiry_info_with_rssi *) (skb->data + 1); | ||
| 544 | |||
| 545 | for (; num_rsp; num_rsp--) { | ||
| 546 | bacpy(&data.bdaddr, &info->bdaddr); | ||
| 547 | data.pscan_rep_mode = info->pscan_rep_mode; | ||
| 548 | data.pscan_period_mode = info->pscan_period_mode; | ||
| 549 | data.pscan_mode = 0x00; | ||
| 550 | memcpy(data.dev_class, info->dev_class, 3); | ||
| 551 | data.clock_offset = info->clock_offset; | ||
| 552 | data.rssi = info->rssi; | ||
| 553 | info++; | ||
| 554 | hci_inquiry_cache_update(hdev, &data); | ||
| 555 | } | ||
| 528 | } | 556 | } |
| 557 | |||
| 529 | hci_dev_unlock(hdev); | 558 | hci_dev_unlock(hdev); |
| 530 | } | 559 | } |
| 531 | 560 | ||
| @@ -865,6 +894,24 @@ static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *sk | |||
| 865 | hci_dev_unlock(hdev); | 894 | hci_dev_unlock(hdev); |
| 866 | } | 895 | } |
| 867 | 896 | ||
| 897 | /* Page Scan Repetition Mode */ | ||
| 898 | static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb) | ||
| 899 | { | ||
| 900 | struct hci_ev_pscan_rep_mode *ev = (struct hci_ev_pscan_rep_mode *) skb->data; | ||
| 901 | struct inquiry_entry *ie; | ||
| 902 | |||
| 903 | BT_DBG("%s", hdev->name); | ||
| 904 | |||
| 905 | hci_dev_lock(hdev); | ||
| 906 | |||
| 907 | if ((ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr))) { | ||
| 908 | ie->data.pscan_rep_mode = ev->pscan_rep_mode; | ||
| 909 | ie->timestamp = jiffies; | ||
| 910 | } | ||
| 911 | |||
| 912 | hci_dev_unlock(hdev); | ||
| 913 | } | ||
| 914 | |||
| 868 | void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) | 915 | void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) |
| 869 | { | 916 | { |
| 870 | struct hci_event_hdr *hdr = (struct hci_event_hdr *) skb->data; | 917 | struct hci_event_hdr *hdr = (struct hci_event_hdr *) skb->data; |
| @@ -937,6 +984,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) | |||
| 937 | hci_clock_offset_evt(hdev, skb); | 984 | hci_clock_offset_evt(hdev, skb); |
| 938 | break; | 985 | break; |
| 939 | 986 | ||
| 987 | case HCI_EV_PSCAN_REP_MODE: | ||
| 988 | hci_pscan_rep_mode_evt(hdev, skb); | ||
| 989 | break; | ||
| 990 | |||
| 940 | case HCI_EV_CMD_STATUS: | 991 | case HCI_EV_CMD_STATUS: |
| 941 | cs = (struct hci_ev_cmd_status *) skb->data; | 992 | cs = (struct hci_ev_cmd_status *) skb->data; |
| 942 | skb_pull(skb, sizeof(cs)); | 993 | skb_pull(skb, sizeof(cs)); |
| @@ -1036,9 +1087,9 @@ void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data) | |||
| 1036 | memcpy(ev->data, data, dlen); | 1087 | memcpy(ev->data, data, dlen); |
| 1037 | 1088 | ||
| 1038 | bt_cb(skb)->incoming = 1; | 1089 | bt_cb(skb)->incoming = 1; |
| 1039 | do_gettimeofday(&skb->stamp); | 1090 | __net_timestamp(skb); |
| 1040 | 1091 | ||
| 1041 | skb->pkt_type = HCI_EVENT_PKT; | 1092 | bt_cb(skb)->pkt_type = HCI_EVENT_PKT; |
| 1042 | skb->dev = (void *) hdev; | 1093 | skb->dev = (void *) hdev; |
| 1043 | hci_send_to_sock(hdev, skb); | 1094 | hci_send_to_sock(hdev, skb); |
| 1044 | kfree_skb(skb); | 1095 | kfree_skb(skb); |
