xref: /linux/include/net/nfc/nci_core.h (revision 03ab8e6297acd1bc0eedaa050e2a1635c576fd11)
1caab277bSThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-only */
26a2968aaSIlan Elias /*
36a2968aaSIlan Elias  *  The NFC Controller Interface is the communication protocol between an
46a2968aaSIlan Elias  *  NFC Controller (NFCC) and a Device Host (DH).
56a2968aaSIlan Elias  *
66a2968aaSIlan Elias  *  Copyright (C) 2011 Texas Instruments, Inc.
78a00a61bSFrederic Danis  *  Copyright (C) 2013 Intel Corporation. All rights reserved.
8a99903ecSJulien Lefrique  *  Copyright (C) 2014 Marvell International Ltd.
96a2968aaSIlan Elias  *
106a2968aaSIlan Elias  *  Written by Ilan Elias <ilane@ti.com>
116a2968aaSIlan Elias  *
126a2968aaSIlan Elias  *  Acknowledgements:
136a2968aaSIlan Elias  *  This file is based on hci_core.h, which was written
146a2968aaSIlan Elias  *  by Maxim Krasnyansky.
156a2968aaSIlan Elias  */
166a2968aaSIlan Elias 
176a2968aaSIlan Elias #ifndef __NCI_CORE_H
186a2968aaSIlan Elias #define __NCI_CORE_H
196a2968aaSIlan Elias 
206a2968aaSIlan Elias #include <linux/interrupt.h>
216a2968aaSIlan Elias #include <linux/skbuff.h>
229961127dSVincent Cuissard #include <linux/tty.h>
236a2968aaSIlan Elias 
246a2968aaSIlan Elias #include <net/nfc/nfc.h>
256a2968aaSIlan Elias #include <net/nfc/nci.h>
266a2968aaSIlan Elias 
278939e47fSIlan Elias /* NCI device flags */
288939e47fSIlan Elias enum nci_flag {
296a2968aaSIlan Elias 	NCI_INIT,
306a2968aaSIlan Elias 	NCI_UP,
3138f04c6bSIlan Elias 	NCI_DATA_EXCHANGE,
32c4bf98b2SIlan Elias 	NCI_DATA_EXCHANGE_TO,
33*48b71a9eSLin Ma 	NCI_UNREG,
346a2968aaSIlan Elias };
356a2968aaSIlan Elias 
368939e47fSIlan Elias /* NCI device states */
378939e47fSIlan Elias enum nci_state {
388939e47fSIlan Elias 	NCI_IDLE,
398939e47fSIlan Elias 	NCI_DISCOVERY,
40019c4fbaSIlan Elias 	NCI_W4_ALL_DISCOVERIES,
41019c4fbaSIlan Elias 	NCI_W4_HOST_SELECT,
428939e47fSIlan Elias 	NCI_POLL_ACTIVE,
43a99903ecSJulien Lefrique 	NCI_LISTEN_ACTIVE,
44a99903ecSJulien Lefrique 	NCI_LISTEN_SLEEP,
458939e47fSIlan Elias };
468939e47fSIlan Elias 
476a2968aaSIlan Elias /* NCI timeouts */
486a2968aaSIlan Elias #define NCI_RESET_TIMEOUT			5000
496a2968aaSIlan Elias #define NCI_INIT_TIMEOUT			5000
507e035230SIlan Elias #define NCI_SET_CONFIG_TIMEOUT			5000
516a2968aaSIlan Elias #define NCI_RF_DISC_TIMEOUT			5000
52019c4fbaSIlan Elias #define NCI_RF_DISC_SELECT_TIMEOUT		5000
5311ee5158SIlan Elias #define NCI_RF_DEACTIVATE_TIMEOUT		30000
546a2968aaSIlan Elias #define NCI_CMD_TIMEOUT				5000
55c4bf98b2SIlan Elias #define NCI_DATA_TIMEOUT			700
566a2968aaSIlan Elias 
576a2968aaSIlan Elias struct nci_dev;
586a2968aaSIlan Elias 
5922e4bd09SRobert Dolca struct nci_driver_ops {
60b6355e97SSamuel Ortiz 	__u16 opcode;
61b6355e97SSamuel Ortiz 	int (*rsp)(struct nci_dev *dev, struct sk_buff *skb);
62b6355e97SSamuel Ortiz 	int (*ntf)(struct nci_dev *dev, struct sk_buff *skb);
63b6355e97SSamuel Ortiz };
64b6355e97SSamuel Ortiz 
656a2968aaSIlan Elias struct nci_ops {
66c39daeeeSChristophe Ricard 	int   (*init)(struct nci_dev *ndev);
676a2968aaSIlan Elias 	int   (*open)(struct nci_dev *ndev);
686a2968aaSIlan Elias 	int   (*close)(struct nci_dev *ndev);
691095e69fSFrederic Danis 	int   (*send)(struct nci_dev *ndev, struct sk_buff *skb);
7086e8586eSAmitkumar Karwar 	int   (*setup)(struct nci_dev *ndev);
71fdf79bd4SRobert Baldyga 	int   (*post_setup)(struct nci_dev *ndev);
7225af01edSClément Perrochaud 	int   (*fw_download)(struct nci_dev *ndev, const char *firmware_name);
739e87f9a9SChristophe Ricard 	__u32 (*get_rfprotocol)(struct nci_dev *ndev, __u8 rf_protocol);
74ba4db551SChristophe Ricard 	int   (*discover_se)(struct nci_dev *ndev);
75e9ef9431SChristophe Ricard 	int   (*disable_se)(struct nci_dev *ndev, u32 se_idx);
7693bca2bfSChristophe Ricard 	int   (*enable_se)(struct nci_dev *ndev, u32 se_idx);
77a688bf55SChristophe Ricard 	int   (*se_io)(struct nci_dev *ndev, u32 se_idx,
78a688bf55SChristophe Ricard 				u8 *apdu, size_t apdu_length,
79a688bf55SChristophe Ricard 				se_io_cb_t cb, void *cb_context);
8011f54f22SChristophe Ricard 	int   (*hci_load_session)(struct nci_dev *ndev);
8111f54f22SChristophe Ricard 	void  (*hci_event_received)(struct nci_dev *ndev, u8 pipe, u8 event,
8211f54f22SChristophe Ricard 				    struct sk_buff *skb);
8311f54f22SChristophe Ricard 	void  (*hci_cmd_received)(struct nci_dev *ndev, u8 pipe, u8 cmd,
8411f54f22SChristophe Ricard 				  struct sk_buff *skb);
85b6355e97SSamuel Ortiz 
86cb8caa3cSKrzysztof Kozlowski 	const struct nci_driver_ops *prop_ops;
87b6355e97SSamuel Ortiz 	size_t n_prop_ops;
880a97a3cbSRobert Dolca 
89cb8caa3cSKrzysztof Kozlowski 	const struct nci_driver_ops *core_ops;
900a97a3cbSRobert Dolca 	size_t n_core_ops;
916a2968aaSIlan Elias };
926a2968aaSIlan Elias 
936a2968aaSIlan Elias #define NCI_MAX_SUPPORTED_RF_INTERFACES		4
94019c4fbaSIlan Elias #define NCI_MAX_DISCOVERED_TARGETS		10
954aeee687SChristophe Ricard #define NCI_MAX_NUM_NFCEE   255
964aeee687SChristophe Ricard #define NCI_MAX_CONN_ID		7
97b6355e97SSamuel Ortiz #define NCI_MAX_PROPRIETARY_CMD 64
984aeee687SChristophe Ricard 
994aeee687SChristophe Ricard struct nci_conn_info {
1004aeee687SChristophe Ricard 	struct list_head list;
1019b8d1a4cSChristophe Ricard 	/* NCI specification 4.4.2 Connection Creation
1029b8d1a4cSChristophe Ricard 	 * The combination of destination type and destination specific
1039b8d1a4cSChristophe Ricard 	 * parameters shall uniquely identify a single destination for the
1049b8d1a4cSChristophe Ricard 	 * Logical Connection
1059b8d1a4cSChristophe Ricard 	 */
1069b8d1a4cSChristophe Ricard 	struct dest_spec_params *dest_params;
1079b8d1a4cSChristophe Ricard 	__u8	dest_type;
1084aeee687SChristophe Ricard 	__u8	conn_id;
1094aeee687SChristophe Ricard 	__u8	max_pkt_payload_len;
1104aeee687SChristophe Ricard 
1114aeee687SChristophe Ricard 	atomic_t credits_cnt;
1124aeee687SChristophe Ricard 	__u8	 initial_num_credits;
1134aeee687SChristophe Ricard 
1144aeee687SChristophe Ricard 	data_exchange_cb_t	data_exchange_cb;
1154aeee687SChristophe Ricard 	void *data_exchange_cb_context;
1164aeee687SChristophe Ricard 
1174aeee687SChristophe Ricard 	struct sk_buff *rx_skb;
1184aeee687SChristophe Ricard };
1196a2968aaSIlan Elias 
120af9c8aa6SChristophe Ricard #define NCI_INVALID_CONN_ID 0x80
121af9c8aa6SChristophe Ricard 
12211f54f22SChristophe Ricard #define NCI_HCI_ANY_OPEN_PIPE      0x03
12311f54f22SChristophe Ricard 
12411f54f22SChristophe Ricard /* Gates */
12511f54f22SChristophe Ricard #define NCI_HCI_ADMIN_GATE         0x00
126b1fa4dc4SChristophe Ricard #define NCI_HCI_LOOPBACK_GATE	   0x04
1277e357404SChristophe Ricard #define NCI_HCI_IDENTITY_MGMT_GATE 0x05
12811f54f22SChristophe Ricard #define NCI_HCI_LINK_MGMT_GATE     0x06
12911f54f22SChristophe Ricard 
13011f54f22SChristophe Ricard /* Pipes */
13111f54f22SChristophe Ricard #define NCI_HCI_LINK_MGMT_PIPE             0x00
13211f54f22SChristophe Ricard #define NCI_HCI_ADMIN_PIPE                 0x01
13311f54f22SChristophe Ricard 
13411f54f22SChristophe Ricard /* Generic responses */
13511f54f22SChristophe Ricard #define NCI_HCI_ANY_OK                     0x00
13611f54f22SChristophe Ricard #define NCI_HCI_ANY_E_NOT_CONNECTED        0x01
13711f54f22SChristophe Ricard #define NCI_HCI_ANY_E_CMD_PAR_UNKNOWN      0x02
13811f54f22SChristophe Ricard #define NCI_HCI_ANY_E_NOK                  0x03
13911f54f22SChristophe Ricard #define NCI_HCI_ANY_E_PIPES_FULL           0x04
14011f54f22SChristophe Ricard #define NCI_HCI_ANY_E_REG_PAR_UNKNOWN      0x05
14111f54f22SChristophe Ricard #define NCI_HCI_ANY_E_PIPE_NOT_OPENED      0x06
14211f54f22SChristophe Ricard #define NCI_HCI_ANY_E_CMD_NOT_SUPPORTED    0x07
14311f54f22SChristophe Ricard #define NCI_HCI_ANY_E_INHIBITED            0x08
14411f54f22SChristophe Ricard #define NCI_HCI_ANY_E_TIMEOUT              0x09
14511f54f22SChristophe Ricard #define NCI_HCI_ANY_E_REG_ACCESS_DENIED    0x0a
14611f54f22SChristophe Ricard #define NCI_HCI_ANY_E_PIPE_ACCESS_DENIED   0x0b
14711f54f22SChristophe Ricard 
14811f54f22SChristophe Ricard #define NCI_HCI_DO_NOT_OPEN_PIPE           0x81
14911f54f22SChristophe Ricard #define NCI_HCI_INVALID_PIPE               0x80
15011f54f22SChristophe Ricard #define NCI_HCI_INVALID_GATE               0xFF
15111f54f22SChristophe Ricard #define NCI_HCI_INVALID_HOST               0x80
15211f54f22SChristophe Ricard 
15311f54f22SChristophe Ricard #define NCI_HCI_MAX_CUSTOM_GATES   50
1541f74f323SChristophe Ricard /*
1551f74f323SChristophe Ricard  * According to specification 102 622 chapter 4.4 Pipes,
1561f74f323SChristophe Ricard  * the pipe identifier is 7 bits long.
1571f74f323SChristophe Ricard  */
1586491d698SDan Carpenter #define NCI_HCI_MAX_PIPES          128
15911f54f22SChristophe Ricard 
16011f54f22SChristophe Ricard struct nci_hci_gate {
16111f54f22SChristophe Ricard 	u8 gate;
16211f54f22SChristophe Ricard 	u8 pipe;
16311f54f22SChristophe Ricard 	u8 dest_host;
16411f54f22SChristophe Ricard } __packed;
16511f54f22SChristophe Ricard 
16611f54f22SChristophe Ricard struct nci_hci_pipe {
16711f54f22SChristophe Ricard 	u8 gate;
16811f54f22SChristophe Ricard 	u8 host;
16911f54f22SChristophe Ricard } __packed;
17011f54f22SChristophe Ricard 
17111f54f22SChristophe Ricard struct nci_hci_init_data {
17211f54f22SChristophe Ricard 	u8 gate_count;
17311f54f22SChristophe Ricard 	struct nci_hci_gate gates[NCI_HCI_MAX_CUSTOM_GATES];
17411f54f22SChristophe Ricard 	char session_id[9];
17511f54f22SChristophe Ricard };
17611f54f22SChristophe Ricard 
17711f54f22SChristophe Ricard #define NCI_HCI_MAX_GATES          256
17811f54f22SChristophe Ricard 
17911f54f22SChristophe Ricard struct nci_hci_dev {
18015d4a8daSChristophe Ricard 	u8 nfcee_id;
18111f54f22SChristophe Ricard 	struct nci_dev *ndev;
18211f54f22SChristophe Ricard 	struct nci_conn_info *conn_info;
18311f54f22SChristophe Ricard 
18411f54f22SChristophe Ricard 	struct nci_hci_init_data init_data;
18511f54f22SChristophe Ricard 	struct nci_hci_pipe pipes[NCI_HCI_MAX_PIPES];
18611f54f22SChristophe Ricard 	u8 gate2pipe[NCI_HCI_MAX_GATES];
18711f54f22SChristophe Ricard 	int expected_pipes;
18811f54f22SChristophe Ricard 	int count_pipes;
18911f54f22SChristophe Ricard 
19011f54f22SChristophe Ricard 	struct sk_buff_head rx_hcp_frags;
19111f54f22SChristophe Ricard 	struct work_struct msg_rx_work;
19211f54f22SChristophe Ricard 	struct sk_buff_head msg_rx_queue;
19311f54f22SChristophe Ricard };
19411f54f22SChristophe Ricard 
1956a2968aaSIlan Elias /* NCI Core structures */
1966a2968aaSIlan Elias struct nci_dev {
1976a2968aaSIlan Elias 	struct nfc_dev		*nfc_dev;
198b9c28286SKrzysztof Kozlowski 	const struct nci_ops	*ops;
19911f54f22SChristophe Ricard 	struct nci_hci_dev	*hci_dev;
2006a2968aaSIlan Elias 
2016a2968aaSIlan Elias 	int			tx_headroom;
2026a2968aaSIlan Elias 	int			tx_tailroom;
2036a2968aaSIlan Elias 
2048939e47fSIlan Elias 	atomic_t		state;
2056a2968aaSIlan Elias 	unsigned long		flags;
2066a2968aaSIlan Elias 
2076a2968aaSIlan Elias 	atomic_t		cmd_cnt;
2084aeee687SChristophe Ricard 	__u8			cur_conn_id;
2094aeee687SChristophe Ricard 
2104aeee687SChristophe Ricard 	struct list_head	conn_info_list;
21112bdf27dSChristophe Ricard 	struct nci_conn_info	*rf_conn_info;
2126a2968aaSIlan Elias 
2136a2968aaSIlan Elias 	struct timer_list	cmd_timer;
214c4bf98b2SIlan Elias 	struct timer_list	data_timer;
2156a2968aaSIlan Elias 
2166a2968aaSIlan Elias 	struct workqueue_struct	*cmd_wq;
2176a2968aaSIlan Elias 	struct work_struct	cmd_work;
2186a2968aaSIlan Elias 
2196a2968aaSIlan Elias 	struct workqueue_struct	*rx_wq;
2206a2968aaSIlan Elias 	struct work_struct	rx_work;
2216a2968aaSIlan Elias 
2226a2968aaSIlan Elias 	struct workqueue_struct	*tx_wq;
2236a2968aaSIlan Elias 	struct work_struct	tx_work;
2246a2968aaSIlan Elias 
2256a2968aaSIlan Elias 	struct sk_buff_head	cmd_q;
2266a2968aaSIlan Elias 	struct sk_buff_head	rx_q;
2276a2968aaSIlan Elias 	struct sk_buff_head	tx_q;
2286a2968aaSIlan Elias 
2296a2968aaSIlan Elias 	struct mutex		req_lock;
2306a2968aaSIlan Elias 	struct completion	req_completion;
2316a2968aaSIlan Elias 	__u32			req_status;
2326a2968aaSIlan Elias 	__u32			req_result;
2336a2968aaSIlan Elias 
2346a2968aaSIlan Elias 	void			*driver_data;
2356a2968aaSIlan Elias 
2366a2968aaSIlan Elias 	__u32			poll_prots;
2376a2968aaSIlan Elias 	__u32			target_active_prot;
2386a2968aaSIlan Elias 
239019c4fbaSIlan Elias 	struct nfc_target	targets[NCI_MAX_DISCOVERED_TARGETS];
240019c4fbaSIlan Elias 	int			n_targets;
241019c4fbaSIlan Elias 
2426a2968aaSIlan Elias 	/* received during NCI_OP_CORE_RESET_RSP */
2436a2968aaSIlan Elias 	__u8			nci_ver;
2446a2968aaSIlan Elias 
2456a2968aaSIlan Elias 	/* received during NCI_OP_CORE_INIT_RSP */
2466a2968aaSIlan Elias 	__u32			nfcc_features;
2476a2968aaSIlan Elias 	__u8			num_supported_rf_interfaces;
2486a2968aaSIlan Elias 	__u8			supported_rf_interfaces
2496a2968aaSIlan Elias 				[NCI_MAX_SUPPORTED_RF_INTERFACES];
2506a2968aaSIlan Elias 	__u8			max_logical_connections;
2516a2968aaSIlan Elias 	__u16			max_routing_table_size;
252e8c0dacdSIlan Elias 	__u8			max_ctrl_pkt_payload_len;
253e8c0dacdSIlan Elias 	__u16			max_size_for_large_params;
254e8c0dacdSIlan Elias 	__u8			manufact_id;
255e8c0dacdSIlan Elias 	__u32			manufact_specific_info;
2566a2968aaSIlan Elias 
2574aeee687SChristophe Ricard 	/* Save RF Discovery ID or NFCEE ID under conn_create */
2589b8d1a4cSChristophe Ricard 	struct dest_spec_params cur_params;
2599b8d1a4cSChristophe Ricard 	/* Save destination type under conn_create */
2609b8d1a4cSChristophe Ricard 	__u8			cur_dest_type;
261637d85a7SIlan Elias 
2626a2968aaSIlan Elias 	/* stored during nci_data_exchange */
2636a2968aaSIlan Elias 	struct sk_buff		*rx_data_reassembly;
264767f19aeSIlan Elias 
265767f19aeSIlan Elias 	/* stored during intf_activated_ntf */
266767f19aeSIlan Elias 	__u8 remote_gb[NFC_MAX_GT_LEN];
267767f19aeSIlan Elias 	__u8 remote_gb_len;
2686a2968aaSIlan Elias };
2696a2968aaSIlan Elias 
2706a2968aaSIlan Elias /* ----- NCI Devices ----- */
271b9c28286SKrzysztof Kozlowski struct nci_dev *nci_allocate_device(const struct nci_ops *ops,
2726a2968aaSIlan Elias 				    __u32 supported_protocols,
2736a2968aaSIlan Elias 				    int tx_headroom,
2746a2968aaSIlan Elias 				    int tx_tailroom);
2756a2968aaSIlan Elias void nci_free_device(struct nci_dev *ndev);
2766a2968aaSIlan Elias int nci_register_device(struct nci_dev *ndev);
2776a2968aaSIlan Elias void nci_unregister_device(struct nci_dev *ndev);
27811f54f22SChristophe Ricard int nci_request(struct nci_dev *ndev,
27911f54f22SChristophe Ricard 		void (*req)(struct nci_dev *ndev,
28035d7a6f1SKrzysztof Kozlowski 			    const void *opt),
28135d7a6f1SKrzysztof Kozlowski 		const void *opt, __u32 timeout);
282ddecf555SKrzysztof Kozlowski int nci_prop_cmd(struct nci_dev *ndev, __u8 oid, size_t len,
283ddecf555SKrzysztof Kozlowski 		 const __u8 *payload);
284ddecf555SKrzysztof Kozlowski int nci_core_cmd(struct nci_dev *ndev, __u16 opcode, size_t len,
285ddecf555SKrzysztof Kozlowski 		 const __u8 *payload);
286025a0cb8SRobert Baldyga int nci_core_reset(struct nci_dev *ndev);
287025a0cb8SRobert Baldyga int nci_core_init(struct nci_dev *ndev);
288759afb8dSChristophe Ricard 
2891095e69fSFrederic Danis int nci_recv_frame(struct nci_dev *ndev, struct sk_buff *skb);
290e5629d29SVincent Cuissard int nci_send_frame(struct nci_dev *ndev, struct sk_buff *skb);
291ddecf555SKrzysztof Kozlowski int nci_set_config(struct nci_dev *ndev, __u8 id, size_t len, const __u8 *val);
2926a2968aaSIlan Elias 
293af9c8aa6SChristophe Ricard int nci_nfcee_discover(struct nci_dev *ndev, u8 action);
294f7f793f3SChristophe Ricard int nci_nfcee_mode_set(struct nci_dev *ndev, u8 nfcee_id, u8 nfcee_mode);
295b16ae716SChristophe Ricard int nci_core_conn_create(struct nci_dev *ndev, u8 destination_type,
296b16ae716SChristophe Ricard 			 u8 number_destination_params,
297b16ae716SChristophe Ricard 			 size_t params_len,
298ddecf555SKrzysztof Kozlowski 			 const struct core_conn_create_dest_spec_params *params);
299736bb957SChristophe Ricard int nci_core_conn_close(struct nci_dev *ndev, u8 conn_id);
300ddecf555SKrzysztof Kozlowski int nci_nfcc_loopback(struct nci_dev *ndev, const void *data, size_t data_len,
3011c53855fSChristophe Ricard 		      struct sk_buff **resp);
302af9c8aa6SChristophe Ricard 
30311f54f22SChristophe Ricard struct nci_hci_dev *nci_hci_allocate(struct nci_dev *ndev);
304e0652f8bSDongliang Mu void nci_hci_deallocate(struct nci_dev *ndev);
30511f54f22SChristophe Ricard int nci_hci_send_event(struct nci_dev *ndev, u8 gate, u8 event,
30611f54f22SChristophe Ricard 		       const u8 *param, size_t param_len);
30711f54f22SChristophe Ricard int nci_hci_send_cmd(struct nci_dev *ndev, u8 gate,
30811f54f22SChristophe Ricard 		     u8 cmd, const u8 *param, size_t param_len,
30911f54f22SChristophe Ricard 		     struct sk_buff **skb);
31011f54f22SChristophe Ricard int nci_hci_open_pipe(struct nci_dev *ndev, u8 pipe);
31111f54f22SChristophe Ricard int nci_hci_connect_gate(struct nci_dev *ndev, u8 dest_host,
31211f54f22SChristophe Ricard 			 u8 dest_gate, u8 pipe);
31311f54f22SChristophe Ricard int nci_hci_set_param(struct nci_dev *ndev, u8 gate, u8 idx,
31411f54f22SChristophe Ricard 		      const u8 *param, size_t param_len);
31511f54f22SChristophe Ricard int nci_hci_get_param(struct nci_dev *ndev, u8 gate, u8 idx,
31611f54f22SChristophe Ricard 		      struct sk_buff **skb);
317fa6fbadeSChristophe Ricard int nci_hci_clear_all_pipes(struct nci_dev *ndev);
31811f54f22SChristophe Ricard int nci_hci_dev_session_init(struct nci_dev *ndev);
31911f54f22SChristophe Ricard 
nci_skb_alloc(struct nci_dev * ndev,unsigned int len,gfp_t how)3206a2968aaSIlan Elias static inline struct sk_buff *nci_skb_alloc(struct nci_dev *ndev,
3216a2968aaSIlan Elias 					    unsigned int len,
3226a2968aaSIlan Elias 					    gfp_t how)
3236a2968aaSIlan Elias {
3246a2968aaSIlan Elias 	struct sk_buff *skb;
3256a2968aaSIlan Elias 
3266a2968aaSIlan Elias 	skb = alloc_skb(len + ndev->tx_headroom + ndev->tx_tailroom, how);
3276a2968aaSIlan Elias 	if (skb)
3286a2968aaSIlan Elias 		skb_reserve(skb, ndev->tx_headroom);
3296a2968aaSIlan Elias 
3306a2968aaSIlan Elias 	return skb;
3316a2968aaSIlan Elias }
3326a2968aaSIlan Elias 
nci_set_parent_dev(struct nci_dev * ndev,struct device * dev)3336a2968aaSIlan Elias static inline void nci_set_parent_dev(struct nci_dev *ndev, struct device *dev)
3346a2968aaSIlan Elias {
3356a2968aaSIlan Elias 	nfc_set_parent_dev(ndev->nfc_dev, dev);
3366a2968aaSIlan Elias }
3376a2968aaSIlan Elias 
nci_set_drvdata(struct nci_dev * ndev,void * data)3386a2968aaSIlan Elias static inline void nci_set_drvdata(struct nci_dev *ndev, void *data)
3396a2968aaSIlan Elias {
3406a2968aaSIlan Elias 	ndev->driver_data = data;
3416a2968aaSIlan Elias }
3426a2968aaSIlan Elias 
nci_get_drvdata(struct nci_dev * ndev)3436a2968aaSIlan Elias static inline void *nci_get_drvdata(struct nci_dev *ndev)
3446a2968aaSIlan Elias {
3456a2968aaSIlan Elias 	return ndev->driver_data;
3466a2968aaSIlan Elias }
3476a2968aaSIlan Elias 
nci_set_vendor_cmds(struct nci_dev * ndev,const struct nfc_vendor_cmd * cmds,int n_cmds)3488115dd59SSamuel Ortiz static inline int nci_set_vendor_cmds(struct nci_dev *ndev,
34915944ad2SKrzysztof Kozlowski 				      const struct nfc_vendor_cmd *cmds,
3508115dd59SSamuel Ortiz 				      int n_cmds)
3518115dd59SSamuel Ortiz {
3528115dd59SSamuel Ortiz 	return nfc_set_vendor_cmds(ndev->nfc_dev, cmds, n_cmds);
3538115dd59SSamuel Ortiz }
3548115dd59SSamuel Ortiz 
3556a2968aaSIlan Elias void nci_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb);
3566a2968aaSIlan Elias void nci_ntf_packet(struct nci_dev *ndev, struct sk_buff *skb);
357f1163174SRobert Dolca int nci_prop_rsp_packet(struct nci_dev *ndev, __u16 opcode,
358b6355e97SSamuel Ortiz 			struct sk_buff *skb);
359f1163174SRobert Dolca int nci_prop_ntf_packet(struct nci_dev *ndev, __u16 opcode,
3600a97a3cbSRobert Dolca 			struct sk_buff *skb);
361f1163174SRobert Dolca int nci_core_rsp_packet(struct nci_dev *ndev, __u16 opcode,
3620a97a3cbSRobert Dolca 			struct sk_buff *skb);
363f1163174SRobert Dolca int nci_core_ntf_packet(struct nci_dev *ndev, __u16 opcode,
364b6355e97SSamuel Ortiz 			struct sk_buff *skb);
3656a2968aaSIlan Elias void nci_rx_data_packet(struct nci_dev *ndev, struct sk_buff *skb);
36648d54403SKrzysztof Kozlowski int nci_send_cmd(struct nci_dev *ndev, __u16 opcode, __u8 plen, const void *payload);
3676a2968aaSIlan Elias int nci_send_data(struct nci_dev *ndev, __u8 conn_id, struct sk_buff *skb);
3682663589cSRobert Dolca int nci_conn_max_data_pkt_payload_size(struct nci_dev *ndev, __u8 conn_id);
3696a2968aaSIlan Elias void nci_data_exchange_complete(struct nci_dev *ndev, struct sk_buff *skb,
3704aeee687SChristophe Ricard 				__u8 conn_id, int err);
37111f54f22SChristophe Ricard void nci_hci_data_received_cb(void *context, struct sk_buff *skb, int err);
37211f54f22SChristophe Ricard 
373019c4fbaSIlan Elias void nci_clear_target_list(struct nci_dev *ndev);
3746a2968aaSIlan Elias 
3756a2968aaSIlan Elias /* ----- NCI requests ----- */
3766a2968aaSIlan Elias #define NCI_REQ_DONE		0
3776a2968aaSIlan Elias #define NCI_REQ_PEND		1
3786a2968aaSIlan Elias #define NCI_REQ_CANCELED	2
3796a2968aaSIlan Elias 
3806a2968aaSIlan Elias void nci_req_complete(struct nci_dev *ndev, int result);
3814aeee687SChristophe Ricard struct nci_conn_info *nci_get_conn_info_by_conn_id(struct nci_dev *ndev,
3824aeee687SChristophe Ricard 						   int conn_id);
3839b8d1a4cSChristophe Ricard int nci_get_conn_info_by_dest_type_params(struct nci_dev *ndev, u8 dest_type,
384ddecf555SKrzysztof Kozlowski 					  const struct dest_spec_params *params);
3856a2968aaSIlan Elias 
3866a2968aaSIlan Elias /* ----- NCI status code ----- */
3876a2968aaSIlan Elias int nci_to_errno(__u8 code);
3886a2968aaSIlan Elias 
3898a00a61bSFrederic Danis /* ----- NCI over SPI acknowledge modes ----- */
3908a00a61bSFrederic Danis #define NCI_SPI_CRC_DISABLED	0x00
3918a00a61bSFrederic Danis #define NCI_SPI_CRC_ENABLED	0x01
3928a00a61bSFrederic Danis 
3938a00a61bSFrederic Danis /* ----- NCI SPI structures ----- */
394fa544fffSEric Lapuyade struct nci_spi {
395d5937511SEric Lapuyade 	struct nci_dev		*ndev;
3968a00a61bSFrederic Danis 	struct spi_device	*spi;
3978a00a61bSFrederic Danis 
3988a00a61bSFrederic Danis 	unsigned int		xfer_udelay;	/* microseconds delay between
3998a00a61bSFrederic Danis 						  transactions */
4002bd83245SVincent Cuissard 
4012bd83245SVincent Cuissard 	unsigned int		xfer_speed_hz; /*
4022bd83245SVincent Cuissard 						* SPI clock frequency
4032bd83245SVincent Cuissard 						* 0 => default clock
4042bd83245SVincent Cuissard 						*/
4052bd83245SVincent Cuissard 
4068a00a61bSFrederic Danis 	u8			acknowledge_mode;
4078a00a61bSFrederic Danis 
408ee9596d4SFrederic Danis 	struct completion	req_completion;
409ee9596d4SFrederic Danis 	u8			req_result;
4108a00a61bSFrederic Danis };
4118a00a61bSFrederic Danis 
412fa544fffSEric Lapuyade /* ----- NCI SPI ----- */
413fa544fffSEric Lapuyade struct nci_spi *nci_spi_allocate_spi(struct spi_device *spi,
414fa544fffSEric Lapuyade 				     u8 acknowledge_mode, unsigned int delay,
415fa544fffSEric Lapuyade 				     struct nci_dev *ndev);
4162bed2785SEric Lapuyade int nci_spi_send(struct nci_spi *nspi,
4172bed2785SEric Lapuyade 		 struct completion *write_handshake_completion,
4182bed2785SEric Lapuyade 		 struct sk_buff *skb);
41922d4aae5SEric Lapuyade struct sk_buff *nci_spi_read(struct nci_spi *nspi);
4208a00a61bSFrederic Danis 
4219961127dSVincent Cuissard /* ----- NCI UART ---- */
4229961127dSVincent Cuissard 
4239961127dSVincent Cuissard /* Ioctl */
4249961127dSVincent Cuissard #define NCIUARTSETDRIVER	_IOW('U', 0, char *)
4259961127dSVincent Cuissard 
4269961127dSVincent Cuissard enum nci_uart_driver {
4279961127dSVincent Cuissard 	NCI_UART_DRIVER_MARVELL = 0,
4289961127dSVincent Cuissard 	NCI_UART_DRIVER_MAX
4299961127dSVincent Cuissard };
4309961127dSVincent Cuissard 
4319961127dSVincent Cuissard struct nci_uart;
4329961127dSVincent Cuissard 
4339961127dSVincent Cuissard struct nci_uart_ops {
4349961127dSVincent Cuissard 	int (*open)(struct nci_uart *nci_uart);
4359961127dSVincent Cuissard 	void (*close)(struct nci_uart *nci_uart);
4369961127dSVincent Cuissard 	int (*recv)(struct nci_uart *nci_uart, struct sk_buff *skb);
4379961127dSVincent Cuissard 	int (*send)(struct nci_uart *nci_uart, struct sk_buff *skb);
4389961127dSVincent Cuissard 	void (*tx_start)(struct nci_uart *nci_uart);
4399961127dSVincent Cuissard 	void (*tx_done)(struct nci_uart *nci_uart);
4409961127dSVincent Cuissard };
4419961127dSVincent Cuissard 
4429961127dSVincent Cuissard struct nci_uart {
4439961127dSVincent Cuissard 	struct module		*owner;
4449961127dSVincent Cuissard 	struct nci_uart_ops	ops;
4459961127dSVincent Cuissard 	const char		*name;
4469961127dSVincent Cuissard 	enum nci_uart_driver	driver;
4479961127dSVincent Cuissard 
4489961127dSVincent Cuissard 	/* Dynamic data */
4499961127dSVincent Cuissard 	struct nci_dev		*ndev;
4509961127dSVincent Cuissard 	spinlock_t		rx_lock;
4519961127dSVincent Cuissard 	struct work_struct	write_work;
4529961127dSVincent Cuissard 	struct tty_struct	*tty;
4539961127dSVincent Cuissard 	unsigned long		tx_state;
4549961127dSVincent Cuissard 	struct sk_buff_head	tx_q;
4559961127dSVincent Cuissard 	struct sk_buff		*tx_skb;
4569961127dSVincent Cuissard 	struct sk_buff		*rx_skb;
4579961127dSVincent Cuissard 	int			rx_packet_len;
4589961127dSVincent Cuissard 	void			*drv_data;
4599961127dSVincent Cuissard };
4609961127dSVincent Cuissard 
4619961127dSVincent Cuissard int nci_uart_register(struct nci_uart *nu);
4629961127dSVincent Cuissard void nci_uart_unregister(struct nci_uart *nu);
4639961127dSVincent Cuissard void nci_uart_set_config(struct nci_uart *nu, int baudrate, int flow_ctrl);
4649961127dSVincent Cuissard 
4656a2968aaSIlan Elias #endif /* __NCI_CORE_H */
466