xref: /openbmc/linux/net/nfc/nci/ntf.c (revision 171f1bc7)
1 /*
2  *  The NFC Controller Interface is the communication protocol between an
3  *  NFC Controller (NFCC) and a Device Host (DH).
4  *
5  *  Copyright (C) 2011 Texas Instruments, Inc.
6  *
7  *  Written by Ilan Elias <ilane@ti.com>
8  *
9  *  Acknowledgements:
10  *  This file is based on hci_event.c, which was written
11  *  by Maxim Krasnyansky.
12  *
13  *  This program is free software; you can redistribute it and/or modify
14  *  it under the terms of the GNU General Public License version 2
15  *  as published by the Free Software Foundation
16  *
17  *  This program is distributed in the hope that it will be useful,
18  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  *  GNU General Public License for more details.
21  *
22  *  You should have received a copy of the GNU General Public License
23  *  along with this program; if not, write to the Free Software
24  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25  *
26  */
27 
28 #include <linux/types.h>
29 #include <linux/interrupt.h>
30 #include <linux/bitops.h>
31 #include <linux/skbuff.h>
32 
33 #include "../nfc.h"
34 #include <net/nfc/nci.h>
35 #include <net/nfc/nci_core.h>
36 #include <linux/nfc.h>
37 
38 /* Handle NCI Notification packets */
39 
40 static void nci_core_conn_credits_ntf_packet(struct nci_dev *ndev,
41 						struct sk_buff *skb)
42 {
43 	struct nci_core_conn_credit_ntf *ntf = (void *) skb->data;
44 	int i;
45 
46 	nfc_dbg("entry, num_entries %d", ntf->num_entries);
47 
48 	if (ntf->num_entries > NCI_MAX_NUM_CONN)
49 		ntf->num_entries = NCI_MAX_NUM_CONN;
50 
51 	/* update the credits */
52 	for (i = 0; i < ntf->num_entries; i++) {
53 		nfc_dbg("entry[%d]: conn_id %d, credits %d", i,
54 			ntf->conn_entries[i].conn_id,
55 			ntf->conn_entries[i].credits);
56 
57 		if (ntf->conn_entries[i].conn_id == ndev->conn_id) {
58 			/* found static rf connection */
59 			atomic_add(ntf->conn_entries[i].credits,
60 				&ndev->credits_cnt);
61 		}
62 	}
63 
64 	/* trigger the next tx */
65 	if (!skb_queue_empty(&ndev->tx_q))
66 		queue_work(ndev->tx_wq, &ndev->tx_work);
67 }
68 
69 static void nci_rf_field_info_ntf_packet(struct nci_dev *ndev,
70 					struct sk_buff *skb)
71 {
72 	struct nci_rf_field_info_ntf *ntf = (void *) skb->data;
73 
74 	nfc_dbg("entry, rf_field_status %d", ntf->rf_field_status);
75 }
76 
77 static int nci_rf_activate_nfca_passive_poll(struct nci_dev *ndev,
78 			struct nci_rf_activate_ntf *ntf, __u8 *data)
79 {
80 	struct rf_tech_specific_params_nfca_poll *nfca_poll;
81 	struct activation_params_nfca_poll_iso_dep *nfca_poll_iso_dep;
82 
83 	nfca_poll = &ntf->rf_tech_specific_params.nfca_poll;
84 	nfca_poll_iso_dep = &ntf->activation_params.nfca_poll_iso_dep;
85 
86 	nfca_poll->sens_res = __le16_to_cpu(*((__u16 *)data));
87 	data += 2;
88 
89 	nfca_poll->nfcid1_len = *data++;
90 
91 	nfc_dbg("sens_res 0x%x, nfcid1_len %d",
92 		nfca_poll->sens_res,
93 		nfca_poll->nfcid1_len);
94 
95 	memcpy(nfca_poll->nfcid1, data, nfca_poll->nfcid1_len);
96 	data += nfca_poll->nfcid1_len;
97 
98 	nfca_poll->sel_res_len = *data++;
99 
100 	if (nfca_poll->sel_res_len != 0)
101 		nfca_poll->sel_res = *data++;
102 
103 	ntf->rf_interface_type = *data++;
104 	ntf->activation_params_len = *data++;
105 
106 	nfc_dbg("sel_res_len %d, sel_res 0x%x, rf_interface_type %d, activation_params_len %d",
107 		nfca_poll->sel_res_len,
108 		nfca_poll->sel_res,
109 		ntf->rf_interface_type,
110 		ntf->activation_params_len);
111 
112 	switch (ntf->rf_interface_type) {
113 	case NCI_RF_INTERFACE_ISO_DEP:
114 		nfca_poll_iso_dep->rats_res_len = *data++;
115 		if (nfca_poll_iso_dep->rats_res_len > 0) {
116 			memcpy(nfca_poll_iso_dep->rats_res,
117 				data,
118 				nfca_poll_iso_dep->rats_res_len);
119 		}
120 		break;
121 
122 	case NCI_RF_INTERFACE_FRAME:
123 		/* no activation params */
124 		break;
125 
126 	default:
127 		nfc_err("unsupported rf_interface_type 0x%x",
128 			ntf->rf_interface_type);
129 		return -EPROTO;
130 	}
131 
132 	return 0;
133 }
134 
135 static void nci_target_found(struct nci_dev *ndev,
136 				struct nci_rf_activate_ntf *ntf)
137 {
138 	struct nfc_target nfc_tgt;
139 
140 	if (ntf->rf_protocol == NCI_RF_PROTOCOL_T2T)	/* T2T MifareUL */
141 		nfc_tgt.supported_protocols = NFC_PROTO_MIFARE_MASK;
142 	else if (ntf->rf_protocol == NCI_RF_PROTOCOL_ISO_DEP)	/* 4A */
143 		nfc_tgt.supported_protocols = NFC_PROTO_ISO14443_MASK;
144 
145 	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;
147 
148 	if (!(nfc_tgt.supported_protocols & ndev->poll_prots)) {
149 		nfc_dbg("the target found does not have the desired protocol");
150 		return;
151 	}
152 
153 	nfc_dbg("new target found,  supported_protocols 0x%x",
154 		nfc_tgt.supported_protocols);
155 
156 	ndev->target_available_prots = nfc_tgt.supported_protocols;
157 
158 	nfc_targets_found(ndev->nfc_dev, &nfc_tgt, 1);
159 }
160 
161 static void nci_rf_activate_ntf_packet(struct nci_dev *ndev,
162 					struct sk_buff *skb)
163 {
164 	struct nci_rf_activate_ntf ntf;
165 	__u8 *data = skb->data;
166 	int rc = -1;
167 
168 	clear_bit(NCI_DISCOVERY, &ndev->flags);
169 	set_bit(NCI_POLL_ACTIVE, &ndev->flags);
170 
171 	ntf.target_handle = *data++;
172 	ntf.rf_protocol = *data++;
173 	ntf.rf_tech_and_mode = *data++;
174 	ntf.rf_tech_specific_params_len = *data++;
175 
176 	nfc_dbg("target_handle %d, rf_protocol 0x%x, rf_tech_and_mode 0x%x, rf_tech_specific_params_len %d",
177 		ntf.target_handle,
178 		ntf.rf_protocol,
179 		ntf.rf_tech_and_mode,
180 		ntf.rf_tech_specific_params_len);
181 
182 	switch (ntf.rf_tech_and_mode) {
183 	case NCI_NFC_A_PASSIVE_POLL_MODE:
184 		rc = nci_rf_activate_nfca_passive_poll(ndev, &ntf,
185 			data);
186 		break;
187 
188 	default:
189 		nfc_err("unsupported rf_tech_and_mode 0x%x",
190 			ntf.rf_tech_and_mode);
191 		return;
192 	}
193 
194 	if (!rc)
195 		nci_target_found(ndev, &ntf);
196 }
197 
198 static void nci_rf_deactivate_ntf_packet(struct nci_dev *ndev,
199 					struct sk_buff *skb)
200 {
201 	__u8 type = skb->data[0];
202 
203 	nfc_dbg("entry, type 0x%x", type);
204 
205 	clear_bit(NCI_POLL_ACTIVE, &ndev->flags);
206 	ndev->target_active_prot = 0;
207 
208 	/* drop tx data queue */
209 	skb_queue_purge(&ndev->tx_q);
210 
211 	/* drop partial rx data packet */
212 	if (ndev->rx_data_reassembly) {
213 		kfree_skb(ndev->rx_data_reassembly);
214 		ndev->rx_data_reassembly = 0;
215 	}
216 
217 	/* complete the data exchange transaction, if exists */
218 	if (test_bit(NCI_DATA_EXCHANGE, &ndev->flags))
219 		nci_data_exchange_complete(ndev, NULL, -EIO);
220 }
221 
222 void nci_ntf_packet(struct nci_dev *ndev, struct sk_buff *skb)
223 {
224 	__u16 ntf_opcode = nci_opcode(skb->data);
225 
226 	nfc_dbg("NCI RX: MT=ntf, PBF=%d, GID=0x%x, OID=0x%x, plen=%d",
227 			nci_pbf(skb->data),
228 			nci_opcode_gid(ntf_opcode),
229 			nci_opcode_oid(ntf_opcode),
230 			nci_plen(skb->data));
231 
232 	/* strip the nci control header */
233 	skb_pull(skb, NCI_CTRL_HDR_SIZE);
234 
235 	switch (ntf_opcode) {
236 	case NCI_OP_CORE_CONN_CREDITS_NTF:
237 		nci_core_conn_credits_ntf_packet(ndev, skb);
238 		break;
239 
240 	case NCI_OP_RF_FIELD_INFO_NTF:
241 		nci_rf_field_info_ntf_packet(ndev, skb);
242 		break;
243 
244 	case NCI_OP_RF_ACTIVATE_NTF:
245 		nci_rf_activate_ntf_packet(ndev, skb);
246 		break;
247 
248 	case NCI_OP_RF_DEACTIVATE_NTF:
249 		nci_rf_deactivate_ntf_packet(ndev, skb);
250 		break;
251 
252 	default:
253 		nfc_err("unknown ntf opcode 0x%x", ntf_opcode);
254 		break;
255 	}
256 
257 	kfree_skb(skb);
258 }
259