blob: 886854a4ea91fa042f1c57bf3a6c81d9ca8f96a9 [file] [log] [blame]
Ilan Elias6a2968a2011-09-18 11:19:35 +03001/*
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.
Frederic Danis8a00a612013-05-29 15:35:02 +02006 * Copyright (C) 2013 Intel Corporation. All rights reserved.
Julien Lefriquea99903e2014-10-21 16:52:46 +02007 * Copyright (C) 2014 Marvell International Ltd.
Ilan Elias6a2968a2011-09-18 11:19:35 +03008 *
9 * Written by Ilan Elias <ilane@ti.com>
10 *
11 * Acknowledgements:
12 * This file is based on hci_core.h, which was written
13 * by Maxim Krasnyansky.
14 *
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License version 2
17 * as published by the Free Software Foundation
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
Jeff Kirshera6227e22013-12-06 09:13:40 -080025 * along with this program; if not, see <http://www.gnu.org/licenses/>.
Ilan Elias6a2968a2011-09-18 11:19:35 +030026 *
27 */
28
29#ifndef __NCI_CORE_H
30#define __NCI_CORE_H
31
32#include <linux/interrupt.h>
33#include <linux/skbuff.h>
34
35#include <net/nfc/nfc.h>
36#include <net/nfc/nci.h>
37
Ilan Elias8939e472012-01-18 13:16:12 +020038/* NCI device flags */
39enum nci_flag {
Ilan Elias6a2968a2011-09-18 11:19:35 +030040 NCI_INIT,
41 NCI_UP,
Ilan Elias38f04c62011-09-22 11:36:19 +030042 NCI_DATA_EXCHANGE,
Ilan Eliasc4bf98b2012-01-17 12:03:50 +020043 NCI_DATA_EXCHANGE_TO,
Ilan Elias6a2968a2011-09-18 11:19:35 +030044};
45
Ilan Elias8939e472012-01-18 13:16:12 +020046/* NCI device states */
47enum nci_state {
48 NCI_IDLE,
49 NCI_DISCOVERY,
Ilan Elias019c4fb2012-01-18 13:16:14 +020050 NCI_W4_ALL_DISCOVERIES,
51 NCI_W4_HOST_SELECT,
Ilan Elias8939e472012-01-18 13:16:12 +020052 NCI_POLL_ACTIVE,
Julien Lefriquea99903e2014-10-21 16:52:46 +020053 NCI_LISTEN_ACTIVE,
54 NCI_LISTEN_SLEEP,
Ilan Elias8939e472012-01-18 13:16:12 +020055};
56
Ilan Elias6a2968a2011-09-18 11:19:35 +030057/* NCI timeouts */
58#define NCI_RESET_TIMEOUT 5000
59#define NCI_INIT_TIMEOUT 5000
Ilan Elias7e035232012-08-15 11:46:22 +030060#define NCI_SET_CONFIG_TIMEOUT 5000
Ilan Elias6a2968a2011-09-18 11:19:35 +030061#define NCI_RF_DISC_TIMEOUT 5000
Ilan Elias019c4fb2012-01-18 13:16:14 +020062#define NCI_RF_DISC_SELECT_TIMEOUT 5000
Ilan Elias11ee5152012-01-08 13:43:02 +020063#define NCI_RF_DEACTIVATE_TIMEOUT 30000
Ilan Elias6a2968a2011-09-18 11:19:35 +030064#define NCI_CMD_TIMEOUT 5000
Ilan Eliasc4bf98b2012-01-17 12:03:50 +020065#define NCI_DATA_TIMEOUT 700
Ilan Elias6a2968a2011-09-18 11:19:35 +030066
67struct nci_dev;
68
Samuel Ortizb6355e92015-06-06 13:16:37 +020069struct nci_prop_ops {
70 __u16 opcode;
71 int (*rsp)(struct nci_dev *dev, struct sk_buff *skb);
72 int (*ntf)(struct nci_dev *dev, struct sk_buff *skb);
73};
74
Ilan Elias6a2968a2011-09-18 11:19:35 +030075struct nci_ops {
Christophe Ricardc39daee2015-06-06 13:16:40 +020076 int (*init)(struct nci_dev *ndev);
Christophe Ricard9e87f9a2014-09-13 10:28:49 +020077 int (*open)(struct nci_dev *ndev);
78 int (*close)(struct nci_dev *ndev);
79 int (*send)(struct nci_dev *ndev, struct sk_buff *skb);
80 int (*setup)(struct nci_dev *ndev);
Clément Perrochaud25af01e2015-03-09 11:12:03 +010081 int (*fw_download)(struct nci_dev *ndev, const char *firmware_name);
Christophe Ricard9e87f9a2014-09-13 10:28:49 +020082 __u32 (*get_rfprotocol)(struct nci_dev *ndev, __u8 rf_protocol);
Christophe Ricardba4db552014-11-13 00:30:35 +010083 int (*discover_se)(struct nci_dev *ndev);
Christophe Ricarde9ef9432014-11-13 00:30:37 +010084 int (*disable_se)(struct nci_dev *ndev, u32 se_idx);
Christophe Ricard93bca2b2014-11-13 00:30:36 +010085 int (*enable_se)(struct nci_dev *ndev, u32 se_idx);
Christophe Ricarda688bf52014-11-13 00:30:38 +010086 int (*se_io)(struct nci_dev *ndev, u32 se_idx,
87 u8 *apdu, size_t apdu_length,
88 se_io_cb_t cb, void *cb_context);
Christophe Ricard11f54f22015-02-01 22:26:14 +010089 int (*hci_load_session)(struct nci_dev *ndev);
90 void (*hci_event_received)(struct nci_dev *ndev, u8 pipe, u8 event,
91 struct sk_buff *skb);
92 void (*hci_cmd_received)(struct nci_dev *ndev, u8 pipe, u8 cmd,
93 struct sk_buff *skb);
Samuel Ortizb6355e92015-06-06 13:16:37 +020094
95 struct nci_prop_ops *prop_ops;
96 size_t n_prop_ops;
Ilan Elias6a2968a2011-09-18 11:19:35 +030097};
98
99#define NCI_MAX_SUPPORTED_RF_INTERFACES 4
Ilan Elias019c4fb2012-01-18 13:16:14 +0200100#define NCI_MAX_DISCOVERED_TARGETS 10
Christophe Ricard4aeee682015-02-01 22:26:08 +0100101#define NCI_MAX_NUM_NFCEE 255
102#define NCI_MAX_CONN_ID 7
Samuel Ortizb6355e92015-06-06 13:16:37 +0200103#define NCI_MAX_PROPRIETARY_CMD 64
Christophe Ricard4aeee682015-02-01 22:26:08 +0100104
105struct nci_conn_info {
106 struct list_head list;
107 __u8 id; /* can be an RF Discovery ID or an NFCEE ID */
108 __u8 conn_id;
109 __u8 max_pkt_payload_len;
110
111 atomic_t credits_cnt;
112 __u8 initial_num_credits;
113
114 data_exchange_cb_t data_exchange_cb;
115 void *data_exchange_cb_context;
116
117 struct sk_buff *rx_skb;
118};
Ilan Elias6a2968a2011-09-18 11:19:35 +0300119
Christophe Ricardaf9c8aa2015-02-01 22:26:10 +0100120#define NCI_INVALID_CONN_ID 0x80
121
Christophe Ricard11f54f22015-02-01 22:26:14 +0100122#define NCI_HCI_ANY_OPEN_PIPE 0x03
123
124/* Gates */
125#define NCI_HCI_ADMIN_GATE 0x00
126#define NCI_HCI_LINK_MGMT_GATE 0x06
127
128/* Pipes */
129#define NCI_HCI_LINK_MGMT_PIPE 0x00
130#define NCI_HCI_ADMIN_PIPE 0x01
131
132/* Generic responses */
133#define NCI_HCI_ANY_OK 0x00
134#define NCI_HCI_ANY_E_NOT_CONNECTED 0x01
135#define NCI_HCI_ANY_E_CMD_PAR_UNKNOWN 0x02
136#define NCI_HCI_ANY_E_NOK 0x03
137#define NCI_HCI_ANY_E_PIPES_FULL 0x04
138#define NCI_HCI_ANY_E_REG_PAR_UNKNOWN 0x05
139#define NCI_HCI_ANY_E_PIPE_NOT_OPENED 0x06
140#define NCI_HCI_ANY_E_CMD_NOT_SUPPORTED 0x07
141#define NCI_HCI_ANY_E_INHIBITED 0x08
142#define NCI_HCI_ANY_E_TIMEOUT 0x09
143#define NCI_HCI_ANY_E_REG_ACCESS_DENIED 0x0a
144#define NCI_HCI_ANY_E_PIPE_ACCESS_DENIED 0x0b
145
146#define NCI_HCI_DO_NOT_OPEN_PIPE 0x81
147#define NCI_HCI_INVALID_PIPE 0x80
148#define NCI_HCI_INVALID_GATE 0xFF
149#define NCI_HCI_INVALID_HOST 0x80
150
151#define NCI_HCI_MAX_CUSTOM_GATES 50
Christophe Ricard1f74f322015-03-31 08:02:21 +0200152/*
153 * According to specification 102 622 chapter 4.4 Pipes,
154 * the pipe identifier is 7 bits long.
155 */
Christophe Ricard11f54f22015-02-01 22:26:14 +0100156#define NCI_HCI_MAX_PIPES 127
157
158struct nci_hci_gate {
159 u8 gate;
160 u8 pipe;
161 u8 dest_host;
162} __packed;
163
164struct nci_hci_pipe {
165 u8 gate;
166 u8 host;
167} __packed;
168
169struct nci_hci_init_data {
170 u8 gate_count;
171 struct nci_hci_gate gates[NCI_HCI_MAX_CUSTOM_GATES];
172 char session_id[9];
173};
174
175#define NCI_HCI_MAX_GATES 256
176
177struct nci_hci_dev {
Christophe Ricard15d4a8d2015-02-03 19:48:07 +0100178 u8 nfcee_id;
Christophe Ricard11f54f22015-02-01 22:26:14 +0100179 struct nci_dev *ndev;
180 struct nci_conn_info *conn_info;
181
182 struct nci_hci_init_data init_data;
183 struct nci_hci_pipe pipes[NCI_HCI_MAX_PIPES];
184 u8 gate2pipe[NCI_HCI_MAX_GATES];
185 int expected_pipes;
186 int count_pipes;
187
188 struct sk_buff_head rx_hcp_frags;
189 struct work_struct msg_rx_work;
190 struct sk_buff_head msg_rx_queue;
191};
192
Ilan Elias6a2968a2011-09-18 11:19:35 +0300193/* NCI Core structures */
194struct nci_dev {
195 struct nfc_dev *nfc_dev;
196 struct nci_ops *ops;
Christophe Ricard11f54f22015-02-01 22:26:14 +0100197 struct nci_hci_dev *hci_dev;
Ilan Elias6a2968a2011-09-18 11:19:35 +0300198
199 int tx_headroom;
200 int tx_tailroom;
201
Ilan Elias8939e472012-01-18 13:16:12 +0200202 atomic_t state;
Ilan Elias6a2968a2011-09-18 11:19:35 +0300203 unsigned long flags;
204
205 atomic_t cmd_cnt;
Christophe Ricard4aeee682015-02-01 22:26:08 +0100206 __u8 cur_conn_id;
207
208 struct list_head conn_info_list;
Christophe Ricard12bdf272015-02-03 19:48:04 +0100209 struct nci_conn_info *rf_conn_info;
Ilan Elias6a2968a2011-09-18 11:19:35 +0300210
211 struct timer_list cmd_timer;
Ilan Eliasc4bf98b2012-01-17 12:03:50 +0200212 struct timer_list data_timer;
Ilan Elias6a2968a2011-09-18 11:19:35 +0300213
214 struct workqueue_struct *cmd_wq;
215 struct work_struct cmd_work;
216
217 struct workqueue_struct *rx_wq;
218 struct work_struct rx_work;
219
220 struct workqueue_struct *tx_wq;
221 struct work_struct tx_work;
222
223 struct sk_buff_head cmd_q;
224 struct sk_buff_head rx_q;
225 struct sk_buff_head tx_q;
226
227 struct mutex req_lock;
228 struct completion req_completion;
229 __u32 req_status;
230 __u32 req_result;
231
232 void *driver_data;
233
234 __u32 poll_prots;
Ilan Elias6a2968a2011-09-18 11:19:35 +0300235 __u32 target_active_prot;
236
Ilan Elias019c4fb2012-01-18 13:16:14 +0200237 struct nfc_target targets[NCI_MAX_DISCOVERED_TARGETS];
238 int n_targets;
239
Ilan Elias6a2968a2011-09-18 11:19:35 +0300240 /* received during NCI_OP_CORE_RESET_RSP */
241 __u8 nci_ver;
242
243 /* received during NCI_OP_CORE_INIT_RSP */
244 __u32 nfcc_features;
245 __u8 num_supported_rf_interfaces;
246 __u8 supported_rf_interfaces
247 [NCI_MAX_SUPPORTED_RF_INTERFACES];
248 __u8 max_logical_connections;
249 __u16 max_routing_table_size;
Ilan Eliase8c0dac2011-11-09 12:09:14 +0200250 __u8 max_ctrl_pkt_payload_len;
251 __u16 max_size_for_large_params;
Ilan Eliase8c0dac2011-11-09 12:09:14 +0200252 __u8 manufact_id;
253 __u32 manufact_specific_info;
Ilan Elias6a2968a2011-09-18 11:19:35 +0300254
Christophe Ricard4aeee682015-02-01 22:26:08 +0100255 /* Save RF Discovery ID or NFCEE ID under conn_create */
256 __u8 cur_id;
Ilan Elias637d85a2011-12-20 16:57:40 +0200257
Ilan Elias6a2968a2011-09-18 11:19:35 +0300258 /* stored during nci_data_exchange */
Ilan Elias6a2968a2011-09-18 11:19:35 +0300259 struct sk_buff *rx_data_reassembly;
Ilan Elias767f19a2012-08-15 11:46:24 +0300260
261 /* stored during intf_activated_ntf */
262 __u8 remote_gb[NFC_MAX_GT_LEN];
263 __u8 remote_gb_len;
Ilan Elias6a2968a2011-09-18 11:19:35 +0300264};
265
266/* ----- NCI Devices ----- */
267struct nci_dev *nci_allocate_device(struct nci_ops *ops,
Samuel Ortizeb9bc6e2012-03-05 01:03:54 +0100268 __u32 supported_protocols,
269 int tx_headroom,
270 int tx_tailroom);
Ilan Elias6a2968a2011-09-18 11:19:35 +0300271void nci_free_device(struct nci_dev *ndev);
272int nci_register_device(struct nci_dev *ndev);
273void nci_unregister_device(struct nci_dev *ndev);
Christophe Ricard11f54f22015-02-01 22:26:14 +0100274int nci_request(struct nci_dev *ndev,
275 void (*req)(struct nci_dev *ndev,
276 unsigned long opt),
277 unsigned long opt, __u32 timeout);
Frederic Danis1095e692013-05-22 11:36:17 +0200278int nci_recv_frame(struct nci_dev *ndev, struct sk_buff *skb);
Amitkumar Karwar22c15bf2014-01-06 12:58:18 -0800279int nci_set_config(struct nci_dev *ndev, __u8 id, size_t len, __u8 *val);
Ilan Elias6a2968a2011-09-18 11:19:35 +0300280
Christophe Ricardaf9c8aa2015-02-01 22:26:10 +0100281int nci_nfcee_discover(struct nci_dev *ndev, u8 action);
Christophe Ricardf7f793f2015-02-01 22:26:11 +0100282int nci_nfcee_mode_set(struct nci_dev *ndev, u8 nfcee_id, u8 nfcee_mode);
Christophe Ricardb16ae712015-02-03 19:48:05 +0100283int nci_core_conn_create(struct nci_dev *ndev, u8 destination_type,
284 u8 number_destination_params,
285 size_t params_len,
Christophe Ricard736bb952015-02-01 22:26:12 +0100286 struct core_conn_create_dest_spec_params *params);
287int nci_core_conn_close(struct nci_dev *ndev, u8 conn_id);
Christophe Ricardaf9c8aa2015-02-01 22:26:10 +0100288
Christophe Ricard11f54f22015-02-01 22:26:14 +0100289struct nci_hci_dev *nci_hci_allocate(struct nci_dev *ndev);
290int nci_hci_send_event(struct nci_dev *ndev, u8 gate, u8 event,
291 const u8 *param, size_t param_len);
292int nci_hci_send_cmd(struct nci_dev *ndev, u8 gate,
293 u8 cmd, const u8 *param, size_t param_len,
294 struct sk_buff **skb);
295int nci_hci_open_pipe(struct nci_dev *ndev, u8 pipe);
296int nci_hci_connect_gate(struct nci_dev *ndev, u8 dest_host,
297 u8 dest_gate, u8 pipe);
298int nci_hci_set_param(struct nci_dev *ndev, u8 gate, u8 idx,
299 const u8 *param, size_t param_len);
300int nci_hci_get_param(struct nci_dev *ndev, u8 gate, u8 idx,
301 struct sk_buff **skb);
302int nci_hci_dev_session_init(struct nci_dev *ndev);
303
Ilan Elias6a2968a2011-09-18 11:19:35 +0300304static inline struct sk_buff *nci_skb_alloc(struct nci_dev *ndev,
Samuel Ortizeb9bc6e2012-03-05 01:03:54 +0100305 unsigned int len,
306 gfp_t how)
Ilan Elias6a2968a2011-09-18 11:19:35 +0300307{
308 struct sk_buff *skb;
309
310 skb = alloc_skb(len + ndev->tx_headroom + ndev->tx_tailroom, how);
311 if (skb)
312 skb_reserve(skb, ndev->tx_headroom);
313
314 return skb;
315}
316
317static inline void nci_set_parent_dev(struct nci_dev *ndev, struct device *dev)
318{
319 nfc_set_parent_dev(ndev->nfc_dev, dev);
320}
321
322static inline void nci_set_drvdata(struct nci_dev *ndev, void *data)
323{
324 ndev->driver_data = data;
325}
326
327static inline void *nci_get_drvdata(struct nci_dev *ndev)
328{
329 return ndev->driver_data;
330}
331
332void nci_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb);
333void nci_ntf_packet(struct nci_dev *ndev, struct sk_buff *skb);
Samuel Ortizb6355e92015-06-06 13:16:37 +0200334int nci_prop_rsp_packet(struct nci_dev *ndev, __u16 opcode,
335 struct sk_buff *skb);
336int nci_prop_ntf_packet(struct nci_dev *ndev, __u16 opcode,
337 struct sk_buff *skb);
Ilan Elias6a2968a2011-09-18 11:19:35 +0300338void nci_rx_data_packet(struct nci_dev *ndev, struct sk_buff *skb);
339int nci_send_cmd(struct nci_dev *ndev, __u16 opcode, __u8 plen, void *payload);
340int nci_send_data(struct nci_dev *ndev, __u8 conn_id, struct sk_buff *skb);
341void nci_data_exchange_complete(struct nci_dev *ndev, struct sk_buff *skb,
Christophe Ricard4aeee682015-02-01 22:26:08 +0100342 __u8 conn_id, int err);
Christophe Ricard11f54f22015-02-01 22:26:14 +0100343void nci_hci_data_received_cb(void *context, struct sk_buff *skb, int err);
344
Ilan Elias019c4fb2012-01-18 13:16:14 +0200345void nci_clear_target_list(struct nci_dev *ndev);
Ilan Elias6a2968a2011-09-18 11:19:35 +0300346
347/* ----- NCI requests ----- */
348#define NCI_REQ_DONE 0
349#define NCI_REQ_PEND 1
350#define NCI_REQ_CANCELED 2
351
352void nci_req_complete(struct nci_dev *ndev, int result);
Christophe Ricard4aeee682015-02-01 22:26:08 +0100353struct nci_conn_info *nci_get_conn_info_by_conn_id(struct nci_dev *ndev,
354 int conn_id);
Ilan Elias6a2968a2011-09-18 11:19:35 +0300355
356/* ----- NCI status code ----- */
357int nci_to_errno(__u8 code);
358
Frederic Danis8a00a612013-05-29 15:35:02 +0200359/* ----- NCI over SPI acknowledge modes ----- */
360#define NCI_SPI_CRC_DISABLED 0x00
361#define NCI_SPI_CRC_ENABLED 0x01
362
363/* ----- NCI SPI structures ----- */
Eric Lapuyadefa544ff2013-09-05 11:02:21 +0200364struct nci_spi {
Eric Lapuyaded5937512013-09-02 12:35:39 +0200365 struct nci_dev *ndev;
Frederic Danis8a00a612013-05-29 15:35:02 +0200366 struct spi_device *spi;
Frederic Danis8a00a612013-05-29 15:35:02 +0200367
368 unsigned int xfer_udelay; /* microseconds delay between
369 transactions */
370 u8 acknowledge_mode;
371
Frederic Danisee9596d2013-05-29 15:35:03 +0200372 struct completion req_completion;
373 u8 req_result;
Frederic Danis8a00a612013-05-29 15:35:02 +0200374};
375
Eric Lapuyadefa544ff2013-09-05 11:02:21 +0200376/* ----- NCI SPI ----- */
377struct nci_spi *nci_spi_allocate_spi(struct spi_device *spi,
Eric Lapuyadefa544ff2013-09-05 11:02:21 +0200378 u8 acknowledge_mode, unsigned int delay,
379 struct nci_dev *ndev);
Eric Lapuyade2bed2782013-09-23 17:56:43 +0200380int nci_spi_send(struct nci_spi *nspi,
381 struct completion *write_handshake_completion,
382 struct sk_buff *skb);
Eric Lapuyade22d4aae2013-09-23 17:56:31 +0200383struct sk_buff *nci_spi_read(struct nci_spi *nspi);
Frederic Danis8a00a612013-05-29 15:35:02 +0200384
Ilan Elias6a2968a2011-09-18 11:19:35 +0300385#endif /* __NCI_CORE_H */