Merge branch 'next-rebase' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci
[pandora-kernel.git] / net / nfc / nci / ntf.c
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 }