diff options
Diffstat (limited to 'net/bluetooth')
-rw-r--r-- | net/bluetooth/hci_conn.c | 2 | ||||
-rw-r--r-- | net/bluetooth/hci_core.c | 35 | ||||
-rw-r--r-- | net/bluetooth/hci_event.c | 75 |
3 files changed, 89 insertions, 23 deletions
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 69c64ce054fb..6175ce841e9e 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c | |||
@@ -65,6 +65,8 @@ void hci_acl_connect(struct hci_conn *conn) | |||
65 | 65 | ||
66 | conn->attempt++; | 66 | conn->attempt++; |
67 | 67 | ||
68 | conn->link_policy = hdev->link_policy; | ||
69 | |||
68 | memset(&cp, 0, sizeof(cp)); | 70 | memset(&cp, 0, sizeof(cp)); |
69 | bacpy(&cp.bdaddr, &conn->dst); | 71 | bacpy(&cp.bdaddr, &conn->dst); |
70 | cp.pscan_rep_mode = 0x02; | 72 | cp.pscan_rep_mode = 0x02; |
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index aec6929f5c16..69b2c1aac08a 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -279,10 +279,20 @@ static void hci_encrypt_req(struct hci_dev *hdev, unsigned long opt) | |||
279 | 279 | ||
280 | BT_DBG("%s %x", hdev->name, encrypt); | 280 | BT_DBG("%s %x", hdev->name, encrypt); |
281 | 281 | ||
282 | /* Authentication */ | 282 | /* Encryption */ |
283 | hci_send_cmd(hdev, HCI_OP_WRITE_ENCRYPT_MODE, 1, &encrypt); | 283 | hci_send_cmd(hdev, HCI_OP_WRITE_ENCRYPT_MODE, 1, &encrypt); |
284 | } | 284 | } |
285 | 285 | ||
286 | static void hci_linkpol_req(struct hci_dev *hdev, unsigned long opt) | ||
287 | { | ||
288 | __le16 policy = cpu_to_le16(opt); | ||
289 | |||
290 | BT_DBG("%s %x", hdev->name, opt); | ||
291 | |||
292 | /* Default link policy */ | ||
293 | hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, 2, &policy); | ||
294 | } | ||
295 | |||
286 | /* Get HCI device by index. | 296 | /* Get HCI device by index. |
287 | * Device is held on return. */ | 297 | * Device is held on return. */ |
288 | struct hci_dev *hci_dev_get(int index) | 298 | struct hci_dev *hci_dev_get(int index) |
@@ -694,32 +704,35 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg) | |||
694 | msecs_to_jiffies(HCI_INIT_TIMEOUT)); | 704 | msecs_to_jiffies(HCI_INIT_TIMEOUT)); |
695 | break; | 705 | break; |
696 | 706 | ||
697 | case HCISETPTYPE: | ||
698 | hdev->pkt_type = (__u16) dr.dev_opt; | ||
699 | break; | ||
700 | |||
701 | case HCISETLINKPOL: | 707 | case HCISETLINKPOL: |
702 | hdev->link_policy = (__u16) dr.dev_opt; | 708 | err = hci_request(hdev, hci_linkpol_req, dr.dev_opt, |
709 | msecs_to_jiffies(HCI_INIT_TIMEOUT)); | ||
703 | break; | 710 | break; |
704 | 711 | ||
705 | case HCISETLINKMODE: | 712 | case HCISETLINKMODE: |
706 | hdev->link_mode = ((__u16) dr.dev_opt) & (HCI_LM_MASTER | HCI_LM_ACCEPT); | 713 | hdev->link_mode = ((__u16) dr.dev_opt) & |
714 | (HCI_LM_MASTER | HCI_LM_ACCEPT); | ||
715 | break; | ||
716 | |||
717 | case HCISETPTYPE: | ||
718 | hdev->pkt_type = (__u16) dr.dev_opt; | ||
707 | break; | 719 | break; |
708 | 720 | ||
709 | case HCISETACLMTU: | 721 | case HCISETACLMTU: |
710 | hdev->acl_mtu = *((__u16 *)&dr.dev_opt + 1); | 722 | hdev->acl_mtu = *((__u16 *) &dr.dev_opt + 1); |
711 | hdev->acl_pkts = *((__u16 *)&dr.dev_opt + 0); | 723 | hdev->acl_pkts = *((__u16 *) &dr.dev_opt + 0); |
712 | break; | 724 | break; |
713 | 725 | ||
714 | case HCISETSCOMTU: | 726 | case HCISETSCOMTU: |
715 | hdev->sco_mtu = *((__u16 *)&dr.dev_opt + 1); | 727 | hdev->sco_mtu = *((__u16 *) &dr.dev_opt + 1); |
716 | hdev->sco_pkts = *((__u16 *)&dr.dev_opt + 0); | 728 | hdev->sco_pkts = *((__u16 *) &dr.dev_opt + 0); |
717 | break; | 729 | break; |
718 | 730 | ||
719 | default: | 731 | default: |
720 | err = -EINVAL; | 732 | err = -EINVAL; |
721 | break; | 733 | break; |
722 | } | 734 | } |
735 | |||
723 | hci_dev_put(hdev); | 736 | hci_dev_put(hdev); |
724 | return err; | 737 | return err; |
725 | } | 738 | } |
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index d4d2dcc40fc7..9af181a61650 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -110,6 +110,25 @@ static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb) | |||
110 | hci_dev_unlock(hdev); | 110 | hci_dev_unlock(hdev); |
111 | } | 111 | } |
112 | 112 | ||
113 | static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb) | ||
114 | { | ||
115 | struct hci_rp_read_link_policy *rp = (void *) skb->data; | ||
116 | struct hci_conn *conn; | ||
117 | |||
118 | BT_DBG("%s status 0x%x", hdev->name, rp->status); | ||
119 | |||
120 | if (rp->status) | ||
121 | return; | ||
122 | |||
123 | hci_dev_lock(hdev); | ||
124 | |||
125 | conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); | ||
126 | if (conn) | ||
127 | conn->link_policy = __le16_to_cpu(rp->policy); | ||
128 | |||
129 | hci_dev_unlock(hdev); | ||
130 | } | ||
131 | |||
113 | static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb) | 132 | static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb) |
114 | { | 133 | { |
115 | struct hci_rp_write_link_policy *rp = (void *) skb->data; | 134 | struct hci_rp_write_link_policy *rp = (void *) skb->data; |
@@ -128,13 +147,41 @@ static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb) | |||
128 | hci_dev_lock(hdev); | 147 | hci_dev_lock(hdev); |
129 | 148 | ||
130 | conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); | 149 | conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); |
131 | if (conn) { | 150 | if (conn) |
132 | conn->link_policy = get_unaligned_le16(sent + 2); | 151 | conn->link_policy = get_unaligned_le16(sent + 2); |
133 | } | ||
134 | 152 | ||
135 | hci_dev_unlock(hdev); | 153 | hci_dev_unlock(hdev); |
136 | } | 154 | } |
137 | 155 | ||
156 | static void hci_cc_read_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb) | ||
157 | { | ||
158 | struct hci_rp_read_def_link_policy *rp = (void *) skb->data; | ||
159 | |||
160 | BT_DBG("%s status 0x%x", hdev->name, rp->status); | ||
161 | |||
162 | if (rp->status) | ||
163 | return; | ||
164 | |||
165 | hdev->link_policy = __le16_to_cpu(rp->policy); | ||
166 | } | ||
167 | |||
168 | static void hci_cc_write_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb) | ||
169 | { | ||
170 | __u8 status = *((__u8 *) skb->data); | ||
171 | void *sent; | ||
172 | |||
173 | BT_DBG("%s status 0x%x", hdev->name, status); | ||
174 | |||
175 | sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY); | ||
176 | if (!sent) | ||
177 | return; | ||
178 | |||
179 | if (!status) | ||
180 | hdev->link_policy = get_unaligned_le16(sent); | ||
181 | |||
182 | hci_req_complete(hdev, status); | ||
183 | } | ||
184 | |||
138 | static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) | 185 | static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) |
139 | { | 186 | { |
140 | __u8 status = *((__u8 *) skb->data); | 187 | __u8 status = *((__u8 *) skb->data); |
@@ -347,8 +394,8 @@ static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) | |||
347 | return; | 394 | return; |
348 | 395 | ||
349 | hdev->hci_ver = rp->hci_ver; | 396 | hdev->hci_ver = rp->hci_ver; |
350 | hdev->hci_rev = btohs(rp->hci_rev); | 397 | hdev->hci_rev = __le16_to_cpu(rp->hci_rev); |
351 | hdev->manufacturer = btohs(rp->manufacturer); | 398 | hdev->manufacturer = __le16_to_cpu(rp->manufacturer); |
352 | 399 | ||
353 | BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name, | 400 | BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name, |
354 | hdev->manufacturer, | 401 | hdev->manufacturer, |
@@ -690,14 +737,6 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s | |||
690 | hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES, sizeof(cp), &cp); | 737 | hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES, sizeof(cp), &cp); |
691 | } | 738 | } |
692 | 739 | ||
693 | /* Set link policy */ | ||
694 | if (conn->type == ACL_LINK && hdev->link_policy) { | ||
695 | struct hci_cp_write_link_policy cp; | ||
696 | cp.handle = ev->handle; | ||
697 | cp.policy = cpu_to_le16(hdev->link_policy); | ||
698 | hci_send_cmd(hdev, HCI_OP_WRITE_LINK_POLICY, sizeof(cp), &cp); | ||
699 | } | ||
700 | |||
701 | /* Set packet type for incoming connection */ | 740 | /* Set packet type for incoming connection */ |
702 | if (!conn->out && hdev->hci_ver < 3) { | 741 | if (!conn->out && hdev->hci_ver < 3) { |
703 | struct hci_cp_change_conn_ptype cp; | 742 | struct hci_cp_change_conn_ptype cp; |
@@ -974,10 +1013,22 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk | |||
974 | hci_cc_role_discovery(hdev, skb); | 1013 | hci_cc_role_discovery(hdev, skb); |
975 | break; | 1014 | break; |
976 | 1015 | ||
1016 | case HCI_OP_READ_LINK_POLICY: | ||
1017 | hci_cc_read_link_policy(hdev, skb); | ||
1018 | break; | ||
1019 | |||
977 | case HCI_OP_WRITE_LINK_POLICY: | 1020 | case HCI_OP_WRITE_LINK_POLICY: |
978 | hci_cc_write_link_policy(hdev, skb); | 1021 | hci_cc_write_link_policy(hdev, skb); |
979 | break; | 1022 | break; |
980 | 1023 | ||
1024 | case HCI_OP_READ_DEF_LINK_POLICY: | ||
1025 | hci_cc_read_def_link_policy(hdev, skb); | ||
1026 | break; | ||
1027 | |||
1028 | case HCI_OP_WRITE_DEF_LINK_POLICY: | ||
1029 | hci_cc_write_def_link_policy(hdev, skb); | ||
1030 | break; | ||
1031 | |||
981 | case HCI_OP_RESET: | 1032 | case HCI_OP_RESET: |
982 | hci_cc_reset(hdev, skb); | 1033 | hci_cc_reset(hdev, skb); |
983 | break; | 1034 | break; |