diff options
Diffstat (limited to 'net/nfc/nci/ntf.c')
-rw-r--r-- | net/nfc/nci/ntf.c | 209 |
1 files changed, 136 insertions, 73 deletions
diff --git a/net/nfc/nci/ntf.c b/net/nfc/nci/ntf.c index 96633f5cda4f..b16a8dc2afbe 100644 --- a/net/nfc/nci/ntf.c +++ b/net/nfc/nci/ntf.c | |||
@@ -25,6 +25,8 @@ | |||
25 | * | 25 | * |
26 | */ | 26 | */ |
27 | 27 | ||
28 | #define pr_fmt(fmt) KBUILD_MODNAME ": %s: " fmt, __func__ | ||
29 | |||
28 | #include <linux/types.h> | 30 | #include <linux/types.h> |
29 | #include <linux/interrupt.h> | 31 | #include <linux/interrupt.h> |
30 | #include <linux/bitops.h> | 32 | #include <linux/bitops.h> |
@@ -43,18 +45,21 @@ static void nci_core_conn_credits_ntf_packet(struct nci_dev *ndev, | |||
43 | struct nci_core_conn_credit_ntf *ntf = (void *) skb->data; | 45 | struct nci_core_conn_credit_ntf *ntf = (void *) skb->data; |
44 | int i; | 46 | int i; |
45 | 47 | ||
46 | nfc_dbg("entry, num_entries %d", ntf->num_entries); | 48 | pr_debug("num_entries %d\n", ntf->num_entries); |
47 | 49 | ||
48 | if (ntf->num_entries > NCI_MAX_NUM_CONN) | 50 | if (ntf->num_entries > NCI_MAX_NUM_CONN) |
49 | ntf->num_entries = NCI_MAX_NUM_CONN; | 51 | ntf->num_entries = NCI_MAX_NUM_CONN; |
50 | 52 | ||
51 | /* update the credits */ | 53 | /* update the credits */ |
52 | for (i = 0; i < ntf->num_entries; i++) { | 54 | for (i = 0; i < ntf->num_entries; i++) { |
53 | nfc_dbg("entry[%d]: conn_id %d, credits %d", i, | 55 | ntf->conn_entries[i].conn_id = |
54 | ntf->conn_entries[i].conn_id, | 56 | nci_conn_id(&ntf->conn_entries[i].conn_id); |
55 | ntf->conn_entries[i].credits); | 57 | |
58 | pr_debug("entry[%d]: conn_id %d, credits %d\n", | ||
59 | i, ntf->conn_entries[i].conn_id, | ||
60 | ntf->conn_entries[i].credits); | ||
56 | 61 | ||
57 | if (ntf->conn_entries[i].conn_id == ndev->conn_id) { | 62 | if (ntf->conn_entries[i].conn_id == NCI_STATIC_RF_CONN_ID) { |
58 | /* found static rf connection */ | 63 | /* found static rf connection */ |
59 | atomic_add(ntf->conn_entries[i].credits, | 64 | atomic_add(ntf->conn_entries[i].credits, |
60 | &ndev->credits_cnt); | 65 | &ndev->credits_cnt); |
@@ -66,31 +71,34 @@ static void nci_core_conn_credits_ntf_packet(struct nci_dev *ndev, | |||
66 | queue_work(ndev->tx_wq, &ndev->tx_work); | 71 | queue_work(ndev->tx_wq, &ndev->tx_work); |
67 | } | 72 | } |
68 | 73 | ||
69 | static void nci_rf_field_info_ntf_packet(struct nci_dev *ndev, | 74 | static void nci_core_conn_intf_error_ntf_packet(struct nci_dev *ndev, |
70 | struct sk_buff *skb) | 75 | struct sk_buff *skb) |
71 | { | 76 | { |
72 | struct nci_rf_field_info_ntf *ntf = (void *) skb->data; | 77 | struct nci_core_intf_error_ntf *ntf = (void *) skb->data; |
73 | 78 | ||
74 | nfc_dbg("entry, rf_field_status %d", ntf->rf_field_status); | 79 | ntf->conn_id = nci_conn_id(&ntf->conn_id); |
80 | |||
81 | pr_debug("status 0x%x, conn_id %d\n", ntf->status, ntf->conn_id); | ||
82 | |||
83 | /* complete the data exchange transaction, if exists */ | ||
84 | if (test_bit(NCI_DATA_EXCHANGE, &ndev->flags)) | ||
85 | nci_data_exchange_complete(ndev, NULL, -EIO); | ||
75 | } | 86 | } |
76 | 87 | ||
77 | static int nci_rf_activate_nfca_passive_poll(struct nci_dev *ndev, | 88 | static __u8 *nci_extract_rf_params_nfca_passive_poll(struct nci_dev *ndev, |
78 | struct nci_rf_activate_ntf *ntf, __u8 *data) | 89 | struct nci_rf_intf_activated_ntf *ntf, __u8 *data) |
79 | { | 90 | { |
80 | struct rf_tech_specific_params_nfca_poll *nfca_poll; | 91 | struct rf_tech_specific_params_nfca_poll *nfca_poll; |
81 | struct activation_params_nfca_poll_iso_dep *nfca_poll_iso_dep; | ||
82 | 92 | ||
83 | nfca_poll = &ntf->rf_tech_specific_params.nfca_poll; | 93 | nfca_poll = &ntf->rf_tech_specific_params.nfca_poll; |
84 | nfca_poll_iso_dep = &ntf->activation_params.nfca_poll_iso_dep; | ||
85 | 94 | ||
86 | nfca_poll->sens_res = __le16_to_cpu(*((__u16 *)data)); | 95 | nfca_poll->sens_res = __le16_to_cpu(*((__u16 *)data)); |
87 | data += 2; | 96 | data += 2; |
88 | 97 | ||
89 | nfca_poll->nfcid1_len = *data++; | 98 | nfca_poll->nfcid1_len = *data++; |
90 | 99 | ||
91 | nfc_dbg("sens_res 0x%x, nfcid1_len %d", | 100 | pr_debug("sens_res 0x%x, nfcid1_len %d\n", |
92 | nfca_poll->sens_res, | 101 | nfca_poll->sens_res, nfca_poll->nfcid1_len); |
93 | nfca_poll->nfcid1_len); | ||
94 | 102 | ||
95 | memcpy(nfca_poll->nfcid1, data, nfca_poll->nfcid1_len); | 103 | memcpy(nfca_poll->nfcid1, data, nfca_poll->nfcid1_len); |
96 | data += nfca_poll->nfcid1_len; | 104 | data += nfca_poll->nfcid1_len; |
@@ -100,32 +108,32 @@ static int nci_rf_activate_nfca_passive_poll(struct nci_dev *ndev, | |||
100 | if (nfca_poll->sel_res_len != 0) | 108 | if (nfca_poll->sel_res_len != 0) |
101 | nfca_poll->sel_res = *data++; | 109 | nfca_poll->sel_res = *data++; |
102 | 110 | ||
103 | ntf->rf_interface_type = *data++; | 111 | pr_debug("sel_res_len %d, sel_res 0x%x\n", |
104 | ntf->activation_params_len = *data++; | 112 | nfca_poll->sel_res_len, |
113 | nfca_poll->sel_res); | ||
105 | 114 | ||
106 | nfc_dbg("sel_res_len %d, sel_res 0x%x, rf_interface_type %d, activation_params_len %d", | 115 | return data; |
107 | nfca_poll->sel_res_len, | 116 | } |
108 | nfca_poll->sel_res, | ||
109 | ntf->rf_interface_type, | ||
110 | ntf->activation_params_len); | ||
111 | 117 | ||
112 | switch (ntf->rf_interface_type) { | 118 | static int nci_extract_activation_params_iso_dep(struct nci_dev *ndev, |
113 | case NCI_RF_INTERFACE_ISO_DEP: | 119 | struct nci_rf_intf_activated_ntf *ntf, __u8 *data) |
114 | nfca_poll_iso_dep->rats_res_len = *data++; | 120 | { |
115 | if (nfca_poll_iso_dep->rats_res_len > 0) { | 121 | struct activation_params_nfca_poll_iso_dep *nfca_poll; |
116 | memcpy(nfca_poll_iso_dep->rats_res, | 122 | |
123 | switch (ntf->activation_rf_tech_and_mode) { | ||
124 | case NCI_NFC_A_PASSIVE_POLL_MODE: | ||
125 | nfca_poll = &ntf->activation_params.nfca_poll_iso_dep; | ||
126 | nfca_poll->rats_res_len = *data++; | ||
127 | if (nfca_poll->rats_res_len > 0) { | ||
128 | memcpy(nfca_poll->rats_res, | ||
117 | data, | 129 | data, |
118 | nfca_poll_iso_dep->rats_res_len); | 130 | nfca_poll->rats_res_len); |
119 | } | 131 | } |
120 | break; | 132 | break; |
121 | 133 | ||
122 | case NCI_RF_INTERFACE_FRAME: | ||
123 | /* no activation params */ | ||
124 | break; | ||
125 | |||
126 | default: | 134 | default: |
127 | nfc_err("unsupported rf_interface_type 0x%x", | 135 | pr_err("unsupported activation_rf_tech_and_mode 0x%x\n", |
128 | ntf->rf_interface_type); | 136 | ntf->activation_rf_tech_and_mode); |
129 | return -EPROTO; | 137 | return -EPROTO; |
130 | } | 138 | } |
131 | 139 | ||
@@ -133,7 +141,7 @@ static int nci_rf_activate_nfca_passive_poll(struct nci_dev *ndev, | |||
133 | } | 141 | } |
134 | 142 | ||
135 | static void nci_target_found(struct nci_dev *ndev, | 143 | static void nci_target_found(struct nci_dev *ndev, |
136 | struct nci_rf_activate_ntf *ntf) | 144 | struct nci_rf_intf_activated_ntf *ntf) |
137 | { | 145 | { |
138 | struct nfc_target nfc_tgt; | 146 | struct nfc_target nfc_tgt; |
139 | 147 | ||
@@ -141,66 +149,121 @@ static void nci_target_found(struct nci_dev *ndev, | |||
141 | nfc_tgt.supported_protocols = NFC_PROTO_MIFARE_MASK; | 149 | nfc_tgt.supported_protocols = NFC_PROTO_MIFARE_MASK; |
142 | else if (ntf->rf_protocol == NCI_RF_PROTOCOL_ISO_DEP) /* 4A */ | 150 | else if (ntf->rf_protocol == NCI_RF_PROTOCOL_ISO_DEP) /* 4A */ |
143 | nfc_tgt.supported_protocols = NFC_PROTO_ISO14443_MASK; | 151 | nfc_tgt.supported_protocols = NFC_PROTO_ISO14443_MASK; |
152 | else | ||
153 | nfc_tgt.supported_protocols = 0; | ||
144 | 154 | ||
145 | nfc_tgt.sens_res = ntf->rf_tech_specific_params.nfca_poll.sens_res; | 155 | nfc_tgt.sens_res = ntf->rf_tech_specific_params.nfca_poll.sens_res; |
146 | nfc_tgt.sel_res = ntf->rf_tech_specific_params.nfca_poll.sel_res; | 156 | nfc_tgt.sel_res = ntf->rf_tech_specific_params.nfca_poll.sel_res; |
157 | nfc_tgt.nfcid1_len = ntf->rf_tech_specific_params.nfca_poll.nfcid1_len; | ||
158 | if (nfc_tgt.nfcid1_len > 0) { | ||
159 | memcpy(nfc_tgt.nfcid1, | ||
160 | ntf->rf_tech_specific_params.nfca_poll.nfcid1, | ||
161 | nfc_tgt.nfcid1_len); | ||
162 | } | ||
147 | 163 | ||
148 | if (!(nfc_tgt.supported_protocols & ndev->poll_prots)) { | 164 | if (!(nfc_tgt.supported_protocols & ndev->poll_prots)) { |
149 | nfc_dbg("the target found does not have the desired protocol"); | 165 | pr_debug("the target found does not have the desired protocol\n"); |
150 | return; | 166 | return; |
151 | } | 167 | } |
152 | 168 | ||
153 | nfc_dbg("new target found, supported_protocols 0x%x", | 169 | pr_debug("new target found, supported_protocols 0x%x\n", |
154 | nfc_tgt.supported_protocols); | 170 | nfc_tgt.supported_protocols); |
155 | 171 | ||
156 | ndev->target_available_prots = nfc_tgt.supported_protocols; | 172 | ndev->target_available_prots = nfc_tgt.supported_protocols; |
173 | ndev->max_data_pkt_payload_size = ntf->max_data_pkt_payload_size; | ||
174 | ndev->initial_num_credits = ntf->initial_num_credits; | ||
175 | |||
176 | /* set the available credits to initial value */ | ||
177 | atomic_set(&ndev->credits_cnt, ndev->initial_num_credits); | ||
157 | 178 | ||
158 | nfc_targets_found(ndev->nfc_dev, &nfc_tgt, 1); | 179 | nfc_targets_found(ndev->nfc_dev, &nfc_tgt, 1); |
159 | } | 180 | } |
160 | 181 | ||
161 | static void nci_rf_activate_ntf_packet(struct nci_dev *ndev, | 182 | static void nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev, |
162 | struct sk_buff *skb) | 183 | struct sk_buff *skb) |
163 | { | 184 | { |
164 | struct nci_rf_activate_ntf ntf; | 185 | struct nci_rf_intf_activated_ntf ntf; |
165 | __u8 *data = skb->data; | 186 | __u8 *data = skb->data; |
166 | int rc = -1; | 187 | int err = 0; |
167 | 188 | ||
168 | clear_bit(NCI_DISCOVERY, &ndev->flags); | 189 | clear_bit(NCI_DISCOVERY, &ndev->flags); |
169 | set_bit(NCI_POLL_ACTIVE, &ndev->flags); | 190 | set_bit(NCI_POLL_ACTIVE, &ndev->flags); |
170 | 191 | ||
171 | ntf.target_handle = *data++; | 192 | ntf.rf_discovery_id = *data++; |
193 | ntf.rf_interface = *data++; | ||
172 | ntf.rf_protocol = *data++; | 194 | ntf.rf_protocol = *data++; |
173 | ntf.rf_tech_and_mode = *data++; | 195 | ntf.activation_rf_tech_and_mode = *data++; |
196 | ntf.max_data_pkt_payload_size = *data++; | ||
197 | ntf.initial_num_credits = *data++; | ||
174 | ntf.rf_tech_specific_params_len = *data++; | 198 | ntf.rf_tech_specific_params_len = *data++; |
175 | 199 | ||
176 | nfc_dbg("target_handle %d, rf_protocol 0x%x, rf_tech_and_mode 0x%x, rf_tech_specific_params_len %d", | 200 | pr_debug("rf_discovery_id %d\n", ntf.rf_discovery_id); |
177 | ntf.target_handle, | 201 | pr_debug("rf_interface 0x%x\n", ntf.rf_interface); |
178 | ntf.rf_protocol, | 202 | pr_debug("rf_protocol 0x%x\n", ntf.rf_protocol); |
179 | ntf.rf_tech_and_mode, | 203 | pr_debug("activation_rf_tech_and_mode 0x%x\n", |
180 | ntf.rf_tech_specific_params_len); | 204 | ntf.activation_rf_tech_and_mode); |
181 | 205 | pr_debug("max_data_pkt_payload_size 0x%x\n", | |
182 | switch (ntf.rf_tech_and_mode) { | 206 | ntf.max_data_pkt_payload_size); |
183 | case NCI_NFC_A_PASSIVE_POLL_MODE: | 207 | pr_debug("initial_num_credits 0x%x\n", ntf.initial_num_credits); |
184 | rc = nci_rf_activate_nfca_passive_poll(ndev, &ntf, | 208 | pr_debug("rf_tech_specific_params_len %d\n", |
185 | data); | 209 | ntf.rf_tech_specific_params_len); |
186 | break; | 210 | |
211 | if (ntf.rf_tech_specific_params_len > 0) { | ||
212 | switch (ntf.activation_rf_tech_and_mode) { | ||
213 | case NCI_NFC_A_PASSIVE_POLL_MODE: | ||
214 | data = nci_extract_rf_params_nfca_passive_poll(ndev, | ||
215 | &ntf, data); | ||
216 | break; | ||
217 | |||
218 | default: | ||
219 | pr_err("unsupported activation_rf_tech_and_mode 0x%x\n", | ||
220 | ntf.activation_rf_tech_and_mode); | ||
221 | return; | ||
222 | } | ||
223 | } | ||
187 | 224 | ||
188 | default: | 225 | ntf.data_exch_rf_tech_and_mode = *data++; |
189 | nfc_err("unsupported rf_tech_and_mode 0x%x", | 226 | ntf.data_exch_tx_bit_rate = *data++; |
190 | ntf.rf_tech_and_mode); | 227 | ntf.data_exch_rx_bit_rate = *data++; |
191 | return; | 228 | ntf.activation_params_len = *data++; |
229 | |||
230 | pr_debug("data_exch_rf_tech_and_mode 0x%x\n", | ||
231 | ntf.data_exch_rf_tech_and_mode); | ||
232 | pr_debug("data_exch_tx_bit_rate 0x%x\n", | ||
233 | ntf.data_exch_tx_bit_rate); | ||
234 | pr_debug("data_exch_rx_bit_rate 0x%x\n", | ||
235 | ntf.data_exch_rx_bit_rate); | ||
236 | pr_debug("activation_params_len %d\n", | ||
237 | ntf.activation_params_len); | ||
238 | |||
239 | if (ntf.activation_params_len > 0) { | ||
240 | switch (ntf.rf_interface) { | ||
241 | case NCI_RF_INTERFACE_ISO_DEP: | ||
242 | err = nci_extract_activation_params_iso_dep(ndev, | ||
243 | &ntf, data); | ||
244 | break; | ||
245 | |||
246 | case NCI_RF_INTERFACE_FRAME: | ||
247 | /* no activation params */ | ||
248 | break; | ||
249 | |||
250 | default: | ||
251 | pr_err("unsupported rf_interface 0x%x\n", | ||
252 | ntf.rf_interface); | ||
253 | return; | ||
254 | } | ||
192 | } | 255 | } |
193 | 256 | ||
194 | if (!rc) | 257 | if (!err) |
195 | nci_target_found(ndev, &ntf); | 258 | nci_target_found(ndev, &ntf); |
196 | } | 259 | } |
197 | 260 | ||
198 | static void nci_rf_deactivate_ntf_packet(struct nci_dev *ndev, | 261 | static void nci_rf_deactivate_ntf_packet(struct nci_dev *ndev, |
199 | struct sk_buff *skb) | 262 | struct sk_buff *skb) |
200 | { | 263 | { |
201 | __u8 type = skb->data[0]; | 264 | struct nci_rf_deactivate_ntf *ntf = (void *) skb->data; |
202 | 265 | ||
203 | nfc_dbg("entry, type 0x%x", type); | 266 | pr_debug("entry, type 0x%x, reason 0x%x\n", ntf->type, ntf->reason); |
204 | 267 | ||
205 | clear_bit(NCI_POLL_ACTIVE, &ndev->flags); | 268 | clear_bit(NCI_POLL_ACTIVE, &ndev->flags); |
206 | ndev->target_active_prot = 0; | 269 | ndev->target_active_prot = 0; |
@@ -223,11 +286,11 @@ void nci_ntf_packet(struct nci_dev *ndev, struct sk_buff *skb) | |||
223 | { | 286 | { |
224 | __u16 ntf_opcode = nci_opcode(skb->data); | 287 | __u16 ntf_opcode = nci_opcode(skb->data); |
225 | 288 | ||
226 | nfc_dbg("NCI RX: MT=ntf, PBF=%d, GID=0x%x, OID=0x%x, plen=%d", | 289 | pr_debug("NCI RX: MT=ntf, PBF=%d, GID=0x%x, OID=0x%x, plen=%d\n", |
227 | nci_pbf(skb->data), | 290 | nci_pbf(skb->data), |
228 | nci_opcode_gid(ntf_opcode), | 291 | nci_opcode_gid(ntf_opcode), |
229 | nci_opcode_oid(ntf_opcode), | 292 | nci_opcode_oid(ntf_opcode), |
230 | nci_plen(skb->data)); | 293 | nci_plen(skb->data)); |
231 | 294 | ||
232 | /* strip the nci control header */ | 295 | /* strip the nci control header */ |
233 | skb_pull(skb, NCI_CTRL_HDR_SIZE); | 296 | skb_pull(skb, NCI_CTRL_HDR_SIZE); |
@@ -237,12 +300,12 @@ void nci_ntf_packet(struct nci_dev *ndev, struct sk_buff *skb) | |||
237 | nci_core_conn_credits_ntf_packet(ndev, skb); | 300 | nci_core_conn_credits_ntf_packet(ndev, skb); |
238 | break; | 301 | break; |
239 | 302 | ||
240 | case NCI_OP_RF_FIELD_INFO_NTF: | 303 | case NCI_OP_CORE_INTF_ERROR_NTF: |
241 | nci_rf_field_info_ntf_packet(ndev, skb); | 304 | nci_core_conn_intf_error_ntf_packet(ndev, skb); |
242 | break; | 305 | break; |
243 | 306 | ||
244 | case NCI_OP_RF_ACTIVATE_NTF: | 307 | case NCI_OP_RF_INTF_ACTIVATED_NTF: |
245 | nci_rf_activate_ntf_packet(ndev, skb); | 308 | nci_rf_intf_activated_ntf_packet(ndev, skb); |
246 | break; | 309 | break; |
247 | 310 | ||
248 | case NCI_OP_RF_DEACTIVATE_NTF: | 311 | case NCI_OP_RF_DEACTIVATE_NTF: |
@@ -250,7 +313,7 @@ void nci_ntf_packet(struct nci_dev *ndev, struct sk_buff *skb) | |||
250 | break; | 313 | break; |
251 | 314 | ||
252 | default: | 315 | default: |
253 | nfc_err("unknown ntf opcode 0x%x", ntf_opcode); | 316 | pr_err("unknown ntf opcode 0x%x\n", ntf_opcode); |
254 | break; | 317 | break; |
255 | } | 318 | } |
256 | 319 | ||