aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristophe Ricard <christophe.ricard@gmail.com>2015-02-01 16:26:14 -0500
committerSamuel Ortiz <sameo@linux.intel.com>2015-02-02 15:50:40 -0500
commit11f54f228643d0248ec00ce8c9fb8d872f87e7b8 (patch)
tree5cf467e89367c99bff3565669ee777dc8d5cad8f
parent736bb9577407d3556d81c3c3cd57581cd3ae10ea (diff)
NFC: nci: Add HCI over NCI protocol support
According to the NCI specification, one can use HCI over NCI to talk with specific NFCEE. The HCI network is viewed as one logical NFCEE. This is needed to support secure element running HCI only firmwares embedded on an NCI capable chipset, like e.g. the st21nfcb. There is some duplication between this piece of code and the HCI core code, but the latter would need to be abstracted even more to be able to use NCI as a logical transport for HCP packets. Signed-off-by: Christophe Ricard <christophe-h.ricard@st.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
-rw-r--r--include/net/nfc/nci_core.h93
-rw-r--r--net/nfc/nci/Makefile2
-rw-r--r--net/nfc/nci/core.c20
-rw-r--r--net/nfc/nci/hci.c686
-rw-r--r--net/nfc/nci/ntf.c32
5 files changed, 815 insertions, 18 deletions
diff --git a/include/net/nfc/nci_core.h b/include/net/nfc/nci_core.h
index 8ba3e38e4167..be858870dace 100644
--- a/include/net/nfc/nci_core.h
+++ b/include/net/nfc/nci_core.h
@@ -78,6 +78,11 @@ struct nci_ops {
78 int (*se_io)(struct nci_dev *ndev, u32 se_idx, 78 int (*se_io)(struct nci_dev *ndev, u32 se_idx,
79 u8 *apdu, size_t apdu_length, 79 u8 *apdu, size_t apdu_length,
80 se_io_cb_t cb, void *cb_context); 80 se_io_cb_t cb, void *cb_context);
81 int (*hci_load_session)(struct nci_dev *ndev);
82 void (*hci_event_received)(struct nci_dev *ndev, u8 pipe, u8 event,
83 struct sk_buff *skb);
84 void (*hci_cmd_received)(struct nci_dev *ndev, u8 pipe, u8 cmd,
85 struct sk_buff *skb);
81}; 86};
82 87
83#define NCI_MAX_SUPPORTED_RF_INTERFACES 4 88#define NCI_MAX_SUPPORTED_RF_INTERFACES 4
@@ -102,10 +107,77 @@ struct nci_conn_info {
102 107
103#define NCI_INVALID_CONN_ID 0x80 108#define NCI_INVALID_CONN_ID 0x80
104 109
110#define NCI_HCI_ANY_OPEN_PIPE 0x03
111
112/* Gates */
113#define NCI_HCI_ADMIN_GATE 0x00
114#define NCI_HCI_LINK_MGMT_GATE 0x06
115
116/* Pipes */
117#define NCI_HCI_LINK_MGMT_PIPE 0x00
118#define NCI_HCI_ADMIN_PIPE 0x01
119
120/* Generic responses */
121#define NCI_HCI_ANY_OK 0x00
122#define NCI_HCI_ANY_E_NOT_CONNECTED 0x01
123#define NCI_HCI_ANY_E_CMD_PAR_UNKNOWN 0x02
124#define NCI_HCI_ANY_E_NOK 0x03
125#define NCI_HCI_ANY_E_PIPES_FULL 0x04
126#define NCI_HCI_ANY_E_REG_PAR_UNKNOWN 0x05
127#define NCI_HCI_ANY_E_PIPE_NOT_OPENED 0x06
128#define NCI_HCI_ANY_E_CMD_NOT_SUPPORTED 0x07
129#define NCI_HCI_ANY_E_INHIBITED 0x08
130#define NCI_HCI_ANY_E_TIMEOUT 0x09
131#define NCI_HCI_ANY_E_REG_ACCESS_DENIED 0x0a
132#define NCI_HCI_ANY_E_PIPE_ACCESS_DENIED 0x0b
133
134#define NCI_HCI_DO_NOT_OPEN_PIPE 0x81
135#define NCI_HCI_INVALID_PIPE 0x80
136#define NCI_HCI_INVALID_GATE 0xFF
137#define NCI_HCI_INVALID_HOST 0x80
138
139#define NCI_HCI_MAX_CUSTOM_GATES 50
140#define NCI_HCI_MAX_PIPES 127
141
142struct nci_hci_gate {
143 u8 gate;
144 u8 pipe;
145 u8 dest_host;
146} __packed;
147
148struct nci_hci_pipe {
149 u8 gate;
150 u8 host;
151} __packed;
152
153struct nci_hci_init_data {
154 u8 gate_count;
155 struct nci_hci_gate gates[NCI_HCI_MAX_CUSTOM_GATES];
156 char session_id[9];
157};
158
159#define NCI_HCI_MAX_GATES 256
160
161struct nci_hci_dev {
162 struct nci_dev *ndev;
163 struct nci_conn_info *conn_info;
164
165 struct nci_hci_init_data init_data;
166 struct nci_hci_pipe pipes[NCI_HCI_MAX_PIPES];
167 u8 gate2pipe[NCI_HCI_MAX_GATES];
168 int expected_pipes;
169 int count_pipes;
170
171 struct sk_buff_head rx_hcp_frags;
172 struct work_struct msg_rx_work;
173 struct sk_buff_head msg_rx_queue;
174};
175
105/* NCI Core structures */ 176/* NCI Core structures */
106struct nci_dev { 177struct nci_dev {
107 struct nfc_dev *nfc_dev; 178 struct nfc_dev *nfc_dev;
108 struct nci_ops *ops; 179 struct nci_ops *ops;
180 struct nci_hci_dev *hci_dev;
109 181
110 int tx_headroom; 182 int tx_headroom;
111 int tx_tailroom; 183 int tx_tailroom;
@@ -181,6 +253,10 @@ struct nci_dev *nci_allocate_device(struct nci_ops *ops,
181void nci_free_device(struct nci_dev *ndev); 253void nci_free_device(struct nci_dev *ndev);
182int nci_register_device(struct nci_dev *ndev); 254int nci_register_device(struct nci_dev *ndev);
183void nci_unregister_device(struct nci_dev *ndev); 255void nci_unregister_device(struct nci_dev *ndev);
256int nci_request(struct nci_dev *ndev,
257 void (*req)(struct nci_dev *ndev,
258 unsigned long opt),
259 unsigned long opt, __u32 timeout);
184int nci_recv_frame(struct nci_dev *ndev, struct sk_buff *skb); 260int nci_recv_frame(struct nci_dev *ndev, struct sk_buff *skb);
185int nci_set_config(struct nci_dev *ndev, __u8 id, size_t len, __u8 *val); 261int nci_set_config(struct nci_dev *ndev, __u8 id, size_t len, __u8 *val);
186 262
@@ -190,6 +266,21 @@ int nci_core_conn_create(struct nci_dev *ndev,
190 struct core_conn_create_dest_spec_params *params); 266 struct core_conn_create_dest_spec_params *params);
191int nci_core_conn_close(struct nci_dev *ndev, u8 conn_id); 267int nci_core_conn_close(struct nci_dev *ndev, u8 conn_id);
192 268
269struct nci_hci_dev *nci_hci_allocate(struct nci_dev *ndev);
270int nci_hci_send_event(struct nci_dev *ndev, u8 gate, u8 event,
271 const u8 *param, size_t param_len);
272int nci_hci_send_cmd(struct nci_dev *ndev, u8 gate,
273 u8 cmd, const u8 *param, size_t param_len,
274 struct sk_buff **skb);
275int nci_hci_open_pipe(struct nci_dev *ndev, u8 pipe);
276int nci_hci_connect_gate(struct nci_dev *ndev, u8 dest_host,
277 u8 dest_gate, u8 pipe);
278int nci_hci_set_param(struct nci_dev *ndev, u8 gate, u8 idx,
279 const u8 *param, size_t param_len);
280int nci_hci_get_param(struct nci_dev *ndev, u8 gate, u8 idx,
281 struct sk_buff **skb);
282int nci_hci_dev_session_init(struct nci_dev *ndev);
283
193static inline struct sk_buff *nci_skb_alloc(struct nci_dev *ndev, 284static inline struct sk_buff *nci_skb_alloc(struct nci_dev *ndev,
194 unsigned int len, 285 unsigned int len,
195 gfp_t how) 286 gfp_t how)
@@ -225,6 +316,8 @@ int nci_send_cmd(struct nci_dev *ndev, __u16 opcode, __u8 plen, void *payload);
225int nci_send_data(struct nci_dev *ndev, __u8 conn_id, struct sk_buff *skb); 316int nci_send_data(struct nci_dev *ndev, __u8 conn_id, struct sk_buff *skb);
226void nci_data_exchange_complete(struct nci_dev *ndev, struct sk_buff *skb, 317void nci_data_exchange_complete(struct nci_dev *ndev, struct sk_buff *skb,
227 __u8 conn_id, int err); 318 __u8 conn_id, int err);
319void nci_hci_data_received_cb(void *context, struct sk_buff *skb, int err);
320
228void nci_clear_target_list(struct nci_dev *ndev); 321void nci_clear_target_list(struct nci_dev *ndev);
229 322
230/* ----- NCI requests ----- */ 323/* ----- NCI requests ----- */
diff --git a/net/nfc/nci/Makefile b/net/nfc/nci/Makefile
index 7aeedc43187d..7ed8949266cc 100644
--- a/net/nfc/nci/Makefile
+++ b/net/nfc/nci/Makefile
@@ -4,6 +4,6 @@
4 4
5obj-$(CONFIG_NFC_NCI) += nci.o 5obj-$(CONFIG_NFC_NCI) += nci.o
6 6
7nci-objs := core.o data.o lib.o ntf.o rsp.o 7nci-objs := core.o data.o lib.o ntf.o rsp.o hci.o
8 8
9nci-$(CONFIG_NFC_NCI_SPI) += spi.o 9nci-$(CONFIG_NFC_NCI_SPI) += spi.o
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c
index 2a96ed68c7bb..f74d420e2ead 100644
--- a/net/nfc/nci/core.c
+++ b/net/nfc/nci/core.c
@@ -122,10 +122,10 @@ static int __nci_request(struct nci_dev *ndev,
122 return rc; 122 return rc;
123} 123}
124 124
125static inline int nci_request(struct nci_dev *ndev, 125inline int nci_request(struct nci_dev *ndev,
126 void (*req)(struct nci_dev *ndev, 126 void (*req)(struct nci_dev *ndev,
127 unsigned long opt), 127 unsigned long opt),
128 unsigned long opt, __u32 timeout) 128 unsigned long opt, __u32 timeout)
129{ 129{
130 int rc; 130 int rc;
131 131
@@ -901,7 +901,6 @@ static struct nfc_ops nci_nfc_ops = {
901}; 901};
902 902
903/* ---- Interface to NCI drivers ---- */ 903/* ---- Interface to NCI drivers ---- */
904
905/** 904/**
906 * nci_allocate_device - allocate a new nci device 905 * nci_allocate_device - allocate a new nci device
907 * 906 *
@@ -936,13 +935,20 @@ struct nci_dev *nci_allocate_device(struct nci_ops *ops,
936 tx_headroom + NCI_DATA_HDR_SIZE, 935 tx_headroom + NCI_DATA_HDR_SIZE,
937 tx_tailroom); 936 tx_tailroom);
938 if (!ndev->nfc_dev) 937 if (!ndev->nfc_dev)
939 goto free_exit; 938 goto free_nci;
939
940 ndev->hci_dev = nci_hci_allocate(ndev);
941 if (!ndev->hci_dev)
942 goto free_nfc;
940 943
941 nfc_set_drvdata(ndev->nfc_dev, ndev); 944 nfc_set_drvdata(ndev->nfc_dev, ndev);
942 945
943 return ndev; 946 return ndev;
944 947
945free_exit: 948free_nfc:
949 kfree(ndev->nfc_dev);
950
951free_nci:
946 kfree(ndev); 952 kfree(ndev);
947 return NULL; 953 return NULL;
948} 954}
diff --git a/net/nfc/nci/hci.c b/net/nfc/nci/hci.c
new file mode 100644
index 000000000000..ecf253942606
--- /dev/null
+++ b/net/nfc/nci/hci.c
@@ -0,0 +1,686 @@
1/*
2 * The NFC Controller Interface is the communication protocol between an
3 * NFC Controller (NFCC) and a Device Host (DH).
4 * This is the HCI over NCI implementation, as specified in the 10.2
5 * section of the NCI 1.1 specification.
6 *
7 * Copyright (C) 2014 STMicroelectronics SAS. All rights reserved.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2
11 * as published by the Free Software Foundation
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 *
21 */
22
23#include <linux/skbuff.h>
24
25#include "../nfc.h"
26#include <net/nfc/nci.h>
27#include <net/nfc/nci_core.h>
28#include <linux/nfc.h>
29
30struct nci_data {
31 u8 conn_id;
32 u8 pipe;
33 u8 cmd;
34 const u8 *data;
35 u32 data_len;
36} __packed;
37
38struct nci_hci_create_pipe_params {
39 u8 src_gate;
40 u8 dest_host;
41 u8 dest_gate;
42} __packed;
43
44struct nci_hci_create_pipe_resp {
45 u8 src_host;
46 u8 src_gate;
47 u8 dest_host;
48 u8 dest_gate;
49 u8 pipe;
50} __packed;
51
52struct nci_hci_delete_pipe_noti {
53 u8 pipe;
54} __packed;
55
56struct nci_hci_all_pipe_cleared_noti {
57 u8 host;
58} __packed;
59
60struct nci_hcp_message {
61 u8 header; /* type -cmd,evt,rsp- + instruction */
62 u8 data[];
63} __packed;
64
65struct nci_hcp_packet {
66 u8 header; /* cbit+pipe */
67 struct nci_hcp_message message;
68} __packed;
69
70#define NCI_HCI_ANY_SET_PARAMETER 0x01
71#define NCI_HCI_ANY_GET_PARAMETER 0x02
72#define NCI_HCI_ANY_CLOSE_PIPE 0x04
73
74#define NCI_HFP_NO_CHAINING 0x80
75
76#define NCI_NFCEE_ID_HCI 0x80
77
78#define NCI_EVT_HOT_PLUG 0x03
79
80#define NCI_HCI_ADMIN_PARAM_SESSION_IDENTITY 0x01
81
82/* HCP headers */
83#define NCI_HCI_HCP_PACKET_HEADER_LEN 1
84#define NCI_HCI_HCP_MESSAGE_HEADER_LEN 1
85#define NCI_HCI_HCP_HEADER_LEN 2
86
87/* HCP types */
88#define NCI_HCI_HCP_COMMAND 0x00
89#define NCI_HCI_HCP_EVENT 0x01
90#define NCI_HCI_HCP_RESPONSE 0x02
91
92#define NCI_HCI_ADM_NOTIFY_PIPE_CREATED 0x12
93#define NCI_HCI_ADM_NOTIFY_PIPE_DELETED 0x13
94#define NCI_HCI_ADM_NOTIFY_ALL_PIPE_CLEARED 0x15
95
96#define NCI_HCI_FRAGMENT 0x7f
97#define NCI_HCP_HEADER(type, instr) ((((type) & 0x03) << 6) |\
98 ((instr) & 0x3f))
99
100#define NCI_HCP_MSG_GET_TYPE(header) ((header & 0xc0) >> 6)
101#define NCI_HCP_MSG_GET_CMD(header) (header & 0x3f)
102#define NCI_HCP_MSG_GET_PIPE(header) (header & 0x7f)
103
104/* HCI core */
105static void nci_hci_reset_pipes(struct nci_hci_dev *hdev)
106{
107 int i;
108
109 for (i = 0; i < NCI_HCI_MAX_PIPES; i++) {
110 hdev->pipes[i].gate = NCI_HCI_INVALID_GATE;
111 hdev->pipes[i].host = NCI_HCI_INVALID_HOST;
112 }
113 memset(hdev->gate2pipe, NCI_HCI_INVALID_PIPE, sizeof(hdev->gate2pipe));
114}
115
116static void nci_hci_reset_pipes_per_host(struct nci_dev *ndev, u8 host)
117{
118 int i;
119
120 for (i = 0; i < NCI_HCI_MAX_PIPES; i++) {
121 if (ndev->hci_dev->pipes[i].host == host) {
122 ndev->hci_dev->pipes[i].gate = NCI_HCI_INVALID_GATE;
123 ndev->hci_dev->pipes[i].host = NCI_HCI_INVALID_HOST;
124 }
125 }
126}
127
128/* Fragment HCI data over NCI packet.
129 * NFC Forum NCI 10.2.2 Data Exchange:
130 * The payload of the Data Packets sent on the Logical Connection SHALL be
131 * valid HCP packets, as defined within [ETSI_102622]. Each Data Packet SHALL
132 * contain a single HCP packet. NCI Segmentation and Reassembly SHALL NOT be
133 * applied to Data Messages in either direction. The HCI fragmentation mechanism
134 * is used if required.
135 */
136static int nci_hci_send_data(struct nci_dev *ndev, u8 pipe,
137 const u8 data_type, const u8 *data,
138 size_t data_len)
139{
140 struct nci_conn_info *conn_info;
141 struct sk_buff *skb;
142 int len, i, r;
143 u8 cb = pipe;
144
145 conn_info = ndev->hci_dev->conn_info;
146 if (!conn_info)
147 return -EPROTO;
148
149 skb = nci_skb_alloc(ndev, 2 + conn_info->max_pkt_payload_len +
150 NCI_DATA_HDR_SIZE, GFP_KERNEL);
151 if (!skb)
152 return -ENOMEM;
153
154 skb_reserve(skb, 2 + NCI_DATA_HDR_SIZE);
155 *skb_push(skb, 1) = data_type;
156
157 i = 0;
158 len = conn_info->max_pkt_payload_len;
159
160 do {
161 /* If last packet add NCI_HFP_NO_CHAINING */
162 if (i + conn_info->max_pkt_payload_len -
163 (skb->len + 1) >= data_len) {
164 cb |= NCI_HFP_NO_CHAINING;
165 len = data_len - i;
166 } else {
167 len = conn_info->max_pkt_payload_len - skb->len - 1;
168 }
169
170 *skb_push(skb, 1) = cb;
171
172 if (len > 0)
173 memcpy(skb_put(skb, len), data + i, len);
174
175 r = nci_send_data(ndev, conn_info->conn_id, skb);
176 if (r < 0)
177 return r;
178
179 i += len;
180 if (i < data_len) {
181 skb_trim(skb, 0);
182 skb_pull(skb, len);
183 }
184 } while (i < data_len);
185
186 return i;
187}
188
189static void nci_hci_send_data_req(struct nci_dev *ndev, unsigned long opt)
190{
191 struct nci_data *data = (struct nci_data *)opt;
192
193 nci_hci_send_data(ndev, data->pipe, data->cmd,
194 data->data, data->data_len);
195}
196
197int nci_hci_send_event(struct nci_dev *ndev, u8 gate, u8 event,
198 const u8 *param, size_t param_len)
199{
200 u8 pipe = ndev->hci_dev->gate2pipe[gate];
201
202 if (pipe == NCI_HCI_INVALID_PIPE)
203 return -EADDRNOTAVAIL;
204
205 return nci_hci_send_data(ndev, pipe,
206 NCI_HCP_HEADER(NCI_HCI_HCP_EVENT, event),
207 param, param_len);
208}
209EXPORT_SYMBOL(nci_hci_send_event);
210
211int nci_hci_send_cmd(struct nci_dev *ndev, u8 gate, u8 cmd,
212 const u8 *param, size_t param_len,
213 struct sk_buff **skb)
214{
215 struct nci_conn_info *conn_info;
216 struct nci_data data;
217 int r;
218 u8 pipe = ndev->hci_dev->gate2pipe[gate];
219
220 if (pipe == NCI_HCI_INVALID_PIPE)
221 return -EADDRNOTAVAIL;
222
223 conn_info = ndev->hci_dev->conn_info;
224 if (!conn_info)
225 return -EPROTO;
226
227 data.conn_id = conn_info->conn_id;
228 data.pipe = pipe;
229 data.cmd = NCI_HCP_HEADER(NCI_HCI_HCP_COMMAND, cmd);
230 data.data = param;
231 data.data_len = param_len;
232
233 r = nci_request(ndev, nci_hci_send_data_req, (unsigned long)&data,
234 msecs_to_jiffies(NCI_DATA_TIMEOUT));
235
236 if (r == NCI_STATUS_OK)
237 *skb = conn_info->rx_skb;
238
239 return r;
240}
241EXPORT_SYMBOL(nci_hci_send_cmd);
242
243static void nci_hci_event_received(struct nci_dev *ndev, u8 pipe,
244 u8 event, struct sk_buff *skb)
245{
246 if (ndev->ops->hci_event_received)
247 ndev->ops->hci_event_received(ndev, pipe, event, skb);
248}
249
250static void nci_hci_cmd_received(struct nci_dev *ndev, u8 pipe,
251 u8 cmd, struct sk_buff *skb)
252{
253 u8 gate = ndev->hci_dev->pipes[pipe].gate;
254 u8 status = NCI_HCI_ANY_OK | ~NCI_HCI_FRAGMENT;
255 u8 dest_gate, new_pipe;
256 struct nci_hci_create_pipe_resp *create_info;
257 struct nci_hci_delete_pipe_noti *delete_info;
258 struct nci_hci_all_pipe_cleared_noti *cleared_info;
259
260 pr_debug("from gate %x pipe %x cmd %x\n", gate, pipe, cmd);
261
262 switch (cmd) {
263 case NCI_HCI_ADM_NOTIFY_PIPE_CREATED:
264 if (skb->len != 5) {
265 status = NCI_HCI_ANY_E_NOK;
266 goto exit;
267 }
268 create_info = (struct nci_hci_create_pipe_resp *)skb->data;
269 dest_gate = create_info->dest_gate;
270 new_pipe = create_info->pipe;
271
272 /* Save the new created pipe and bind with local gate,
273 * the description for skb->data[3] is destination gate id
274 * but since we received this cmd from host controller, we
275 * are the destination and it is our local gate
276 */
277 ndev->hci_dev->gate2pipe[dest_gate] = new_pipe;
278 ndev->hci_dev->pipes[new_pipe].gate = dest_gate;
279 ndev->hci_dev->pipes[new_pipe].host =
280 create_info->src_host;
281 break;
282 case NCI_HCI_ANY_OPEN_PIPE:
283 /* If the pipe is not created report an error */
284 if (gate == NCI_HCI_INVALID_GATE) {
285 status = NCI_HCI_ANY_E_NOK;
286 goto exit;
287 }
288 break;
289 case NCI_HCI_ADM_NOTIFY_PIPE_DELETED:
290 if (skb->len != 1) {
291 status = NCI_HCI_ANY_E_NOK;
292 goto exit;
293 }
294 delete_info = (struct nci_hci_delete_pipe_noti *)skb->data;
295
296 ndev->hci_dev->pipes[delete_info->pipe].gate =
297 NCI_HCI_INVALID_GATE;
298 ndev->hci_dev->pipes[delete_info->pipe].host =
299 NCI_HCI_INVALID_HOST;
300 break;
301 case NCI_HCI_ADM_NOTIFY_ALL_PIPE_CLEARED:
302 if (skb->len != 1) {
303 status = NCI_HCI_ANY_E_NOK;
304 goto exit;
305 }
306
307 cleared_info =
308 (struct nci_hci_all_pipe_cleared_noti *)skb->data;
309 nci_hci_reset_pipes_per_host(ndev, cleared_info->host);
310 break;
311 default:
312 pr_debug("Discarded unknown cmd %x to gate %x\n", cmd, gate);
313 break;
314 }
315
316 if (ndev->ops->hci_cmd_received)
317 ndev->ops->hci_cmd_received(ndev, pipe, cmd, skb);
318
319exit:
320 nci_hci_send_data(ndev, pipe, status, NULL, 0);
321
322 kfree_skb(skb);
323}
324
325static void nci_hci_resp_received(struct nci_dev *ndev, u8 pipe,
326 u8 result, struct sk_buff *skb)
327{
328 struct nci_conn_info *conn_info;
329 u8 status = result;
330
331 if (result != NCI_HCI_ANY_OK)
332 goto exit;
333
334 conn_info = ndev->hci_dev->conn_info;
335 if (!conn_info) {
336 status = NCI_STATUS_REJECTED;
337 goto exit;
338 }
339
340 conn_info->rx_skb = skb;
341
342exit:
343 nci_req_complete(ndev, status);
344}
345
346/* Receive hcp message for pipe, with type and cmd.
347 * skb contains optional message data only.
348 */
349static void nci_hci_hcp_message_rx(struct nci_dev *ndev, u8 pipe,
350 u8 type, u8 instruction, struct sk_buff *skb)
351{
352 switch (type) {
353 case NCI_HCI_HCP_RESPONSE:
354 nci_hci_resp_received(ndev, pipe, instruction, skb);
355 break;
356 case NCI_HCI_HCP_COMMAND:
357 nci_hci_cmd_received(ndev, pipe, instruction, skb);
358 break;
359 case NCI_HCI_HCP_EVENT:
360 nci_hci_event_received(ndev, pipe, instruction, skb);
361 break;
362 default:
363 pr_err("UNKNOWN MSG Type %d, instruction=%d\n",
364 type, instruction);
365 kfree_skb(skb);
366 break;
367 }
368
369 nci_req_complete(ndev, 0);
370}
371
372static void nci_hci_msg_rx_work(struct work_struct *work)
373{
374 struct nci_hci_dev *hdev =
375 container_of(work, struct nci_hci_dev, msg_rx_work);
376 struct sk_buff *skb;
377 struct nci_hcp_message *message;
378 u8 pipe, type, instruction;
379
380 while ((skb = skb_dequeue(&hdev->msg_rx_queue)) != NULL) {
381 pipe = skb->data[0];
382 skb_pull(skb, NCI_HCI_HCP_PACKET_HEADER_LEN);
383 message = (struct nci_hcp_message *)skb->data;
384 type = NCI_HCP_MSG_GET_TYPE(message->header);
385 instruction = NCI_HCP_MSG_GET_CMD(message->header);
386 skb_pull(skb, NCI_HCI_HCP_MESSAGE_HEADER_LEN);
387
388 nci_hci_hcp_message_rx(hdev->ndev, pipe,
389 type, instruction, skb);
390 }
391}
392
393void nci_hci_data_received_cb(void *context,
394 struct sk_buff *skb, int err)
395{
396 struct nci_dev *ndev = (struct nci_dev *)context;
397 struct nci_hcp_packet *packet;
398 u8 pipe, type, instruction;
399 struct sk_buff *hcp_skb;
400 struct sk_buff *frag_skb;
401 int msg_len;
402
403 pr_debug("\n");
404
405 if (err) {
406 nci_req_complete(ndev, err);
407 return;
408 }
409
410 packet = (struct nci_hcp_packet *)skb->data;
411 if ((packet->header & ~NCI_HCI_FRAGMENT) == 0) {
412 skb_queue_tail(&ndev->hci_dev->rx_hcp_frags, skb);
413 return;
414 }
415
416 /* it's the last fragment. Does it need re-aggregation? */
417 if (skb_queue_len(&ndev->hci_dev->rx_hcp_frags)) {
418 pipe = packet->header & NCI_HCI_FRAGMENT;
419 skb_queue_tail(&ndev->hci_dev->rx_hcp_frags, skb);
420
421 msg_len = 0;
422 skb_queue_walk(&ndev->hci_dev->rx_hcp_frags, frag_skb) {
423 msg_len += (frag_skb->len -
424 NCI_HCI_HCP_PACKET_HEADER_LEN);
425 }
426
427 hcp_skb = nfc_alloc_recv_skb(NCI_HCI_HCP_PACKET_HEADER_LEN +
428 msg_len, GFP_KERNEL);
429 if (!hcp_skb) {
430 nci_req_complete(ndev, -ENOMEM);
431 return;
432 }
433
434 *skb_put(hcp_skb, NCI_HCI_HCP_PACKET_HEADER_LEN) = pipe;
435
436 skb_queue_walk(&ndev->hci_dev->rx_hcp_frags, frag_skb) {
437 msg_len = frag_skb->len - NCI_HCI_HCP_PACKET_HEADER_LEN;
438 memcpy(skb_put(hcp_skb, msg_len), frag_skb->data +
439 NCI_HCI_HCP_PACKET_HEADER_LEN, msg_len);
440 }
441
442 skb_queue_purge(&ndev->hci_dev->rx_hcp_frags);
443 } else {
444 packet->header &= NCI_HCI_FRAGMENT;
445 hcp_skb = skb;
446 }
447
448 /* if this is a response, dispatch immediately to
449 * unblock waiting cmd context. Otherwise, enqueue to dispatch
450 * in separate context where handler can also execute command.
451 */
452 packet = (struct nci_hcp_packet *)hcp_skb->data;
453 type = NCI_HCP_MSG_GET_TYPE(packet->message.header);
454 if (type == NCI_HCI_HCP_RESPONSE) {
455 pipe = packet->header;
456 instruction = NCI_HCP_MSG_GET_CMD(packet->message.header);
457 skb_pull(hcp_skb, NCI_HCI_HCP_PACKET_HEADER_LEN +
458 NCI_HCI_HCP_MESSAGE_HEADER_LEN);
459 nci_hci_hcp_message_rx(ndev, pipe, type, instruction, hcp_skb);
460 } else {
461 skb_queue_tail(&ndev->hci_dev->msg_rx_queue, hcp_skb);
462 schedule_work(&ndev->hci_dev->msg_rx_work);
463 }
464}
465
466int nci_hci_open_pipe(struct nci_dev *ndev, u8 pipe)
467{
468 struct nci_data data;
469 struct nci_conn_info *conn_info;
470
471 conn_info = ndev->hci_dev->conn_info;
472 if (!conn_info)
473 return -EPROTO;
474
475 data.conn_id = conn_info->conn_id;
476 data.pipe = pipe;
477 data.cmd = NCI_HCP_HEADER(NCI_HCI_HCP_COMMAND,
478 NCI_HCI_ANY_OPEN_PIPE);
479 data.data = NULL;
480 data.data_len = 0;
481
482 return nci_request(ndev, nci_hci_send_data_req,
483 (unsigned long)&data,
484 msecs_to_jiffies(NCI_DATA_TIMEOUT));
485}
486EXPORT_SYMBOL(nci_hci_open_pipe);
487
488int nci_hci_set_param(struct nci_dev *ndev, u8 gate, u8 idx,
489 const u8 *param, size_t param_len)
490{
491 struct nci_conn_info *conn_info;
492 struct nci_data data;
493 int r;
494 u8 *tmp;
495 u8 pipe = ndev->hci_dev->gate2pipe[gate];
496
497 pr_debug("idx=%d to gate %d\n", idx, gate);
498
499 if (pipe == NCI_HCI_INVALID_PIPE)
500 return -EADDRNOTAVAIL;
501
502 conn_info = ndev->hci_dev->conn_info;
503 if (!conn_info)
504 return -EPROTO;
505
506 tmp = kmalloc(1 + param_len, GFP_KERNEL);
507 if (!tmp)
508 return -ENOMEM;
509
510 *tmp = idx;
511 memcpy(tmp + 1, param, param_len);
512
513 data.conn_id = conn_info->conn_id;
514 data.pipe = pipe;
515 data.cmd = NCI_HCP_HEADER(NCI_HCI_HCP_COMMAND,
516 NCI_HCI_ANY_SET_PARAMETER);
517 data.data = tmp;
518 data.data_len = param_len + 1;
519
520 r = nci_request(ndev, nci_hci_send_data_req,
521 (unsigned long)&data,
522 msecs_to_jiffies(NCI_DATA_TIMEOUT));
523
524 kfree(tmp);
525 return r;
526}
527EXPORT_SYMBOL(nci_hci_set_param);
528
529int nci_hci_get_param(struct nci_dev *ndev, u8 gate, u8 idx,
530 struct sk_buff **skb)
531{
532 struct nci_conn_info *conn_info;
533 struct nci_data data;
534 int r;
535 u8 pipe = ndev->hci_dev->gate2pipe[gate];
536
537 pr_debug("idx=%d to gate %d\n", idx, gate);
538
539 if (pipe == NCI_HCI_INVALID_PIPE)
540 return -EADDRNOTAVAIL;
541
542 conn_info = ndev->hci_dev->conn_info;
543 if (!conn_info)
544 return -EPROTO;
545
546 data.conn_id = conn_info->conn_id;
547 data.pipe = pipe;
548 data.cmd = NCI_HCP_HEADER(NCI_HCI_HCP_COMMAND,
549 NCI_HCI_ANY_GET_PARAMETER);
550 data.data = &idx;
551 data.data_len = 1;
552
553 r = nci_request(ndev, nci_hci_send_data_req, (unsigned long)&data,
554 msecs_to_jiffies(NCI_DATA_TIMEOUT));
555
556 if (r == NCI_STATUS_OK)
557 *skb = conn_info->rx_skb;
558
559 return r;
560}
561EXPORT_SYMBOL(nci_hci_get_param);
562
563int nci_hci_connect_gate(struct nci_dev *ndev,
564 u8 dest_host, u8 dest_gate, u8 pipe)
565{
566 int r;
567
568 if (pipe == NCI_HCI_DO_NOT_OPEN_PIPE)
569 return 0;
570
571 if (ndev->hci_dev->gate2pipe[dest_gate] != NCI_HCI_INVALID_PIPE)
572 return -EADDRINUSE;
573
574 if (pipe != NCI_HCI_INVALID_PIPE)
575 goto open_pipe;
576
577 switch (dest_gate) {
578 case NCI_HCI_LINK_MGMT_GATE:
579 pipe = NCI_HCI_LINK_MGMT_PIPE;
580 break;
581 case NCI_HCI_ADMIN_GATE:
582 pipe = NCI_HCI_ADMIN_PIPE;
583 break;
584 }
585
586open_pipe:
587 r = nci_hci_open_pipe(ndev, pipe);
588 if (r < 0)
589 return r;
590
591 ndev->hci_dev->pipes[pipe].gate = dest_gate;
592 ndev->hci_dev->pipes[pipe].host = dest_host;
593 ndev->hci_dev->gate2pipe[dest_gate] = pipe;
594
595 return 0;
596}
597EXPORT_SYMBOL(nci_hci_connect_gate);
598
599static int nci_hci_dev_connect_gates(struct nci_dev *ndev,
600 u8 gate_count,
601 struct nci_hci_gate *gates)
602{
603 int r;
604
605 while (gate_count--) {
606 r = nci_hci_connect_gate(ndev, gates->dest_host,
607 gates->gate, gates->pipe);
608 if (r < 0)
609 return r;
610 gates++;
611 }
612
613 return 0;
614}
615
616int nci_hci_dev_session_init(struct nci_dev *ndev)
617{
618 struct sk_buff *skb;
619 int r;
620
621 ndev->hci_dev->count_pipes = 0;
622 ndev->hci_dev->expected_pipes = 0;
623
624 nci_hci_reset_pipes(ndev->hci_dev);
625
626 if (ndev->hci_dev->init_data.gates[0].gate != NCI_HCI_ADMIN_GATE)
627 return -EPROTO;
628
629 r = nci_hci_connect_gate(ndev,
630 ndev->hci_dev->init_data.gates[0].dest_host,
631 ndev->hci_dev->init_data.gates[0].gate,
632 ndev->hci_dev->init_data.gates[0].pipe);
633 if (r < 0)
634 goto exit;
635
636 r = nci_hci_get_param(ndev, NCI_HCI_ADMIN_GATE,
637 NCI_HCI_ADMIN_PARAM_SESSION_IDENTITY, &skb);
638 if (r < 0)
639 goto exit;
640
641 if (skb->len &&
642 skb->len == strlen(ndev->hci_dev->init_data.session_id) &&
643 memcmp(ndev->hci_dev->init_data.session_id,
644 skb->data, skb->len) == 0 &&
645 ndev->ops->hci_load_session) {
646 /* Restore gate<->pipe table from some proprietary location. */
647 r = ndev->ops->hci_load_session(ndev);
648 if (r < 0)
649 goto exit;
650 } else {
651 r = nci_hci_dev_connect_gates(ndev,
652 ndev->hci_dev->init_data.gate_count,
653 ndev->hci_dev->init_data.gates);
654 if (r < 0)
655 goto exit;
656
657 r = nci_hci_set_param(ndev, NCI_HCI_ADMIN_GATE,
658 NCI_HCI_ADMIN_PARAM_SESSION_IDENTITY,
659 ndev->hci_dev->init_data.session_id,
660 strlen(ndev->hci_dev->init_data.session_id));
661 }
662 if (r == 0)
663 goto exit;
664
665exit:
666 kfree_skb(skb);
667
668 return r;
669}
670EXPORT_SYMBOL(nci_hci_dev_session_init);
671
672struct nci_hci_dev *nci_hci_allocate(struct nci_dev *ndev)
673{
674 struct nci_hci_dev *hdev;
675
676 hdev = kzalloc(sizeof(*hdev), GFP_KERNEL);
677 if (!hdev)
678 return NULL;
679
680 skb_queue_head_init(&hdev->rx_hcp_frags);
681 INIT_WORK(&hdev->msg_rx_work, nci_hci_msg_rx_work);
682 skb_queue_head_init(&hdev->msg_rx_queue);
683 hdev->ndev = ndev;
684
685 return hdev;
686}
diff --git a/net/nfc/nci/ntf.c b/net/nfc/nci/ntf.c
index 4c0be7e82d29..6e041ac49e17 100644
--- a/net/nfc/nci/ntf.c
+++ b/net/nfc/nci/ntf.c
@@ -723,18 +723,30 @@ static void nci_nfcee_discover_ntf_packet(struct nci_dev *ndev,
723 723
724 pr_debug("\n"); 724 pr_debug("\n");
725 725
726 conn_info = devm_kzalloc(&ndev->nfc_dev->dev, 726 /* NFCForum NCI 9.2.1 HCI Network Specific Handling
727 sizeof(struct nci_conn_info), GFP_KERNEL); 727 * If the NFCC supports the HCI Network, it SHALL return one,
728 if (!conn_info) { 728 * and only one, NFCEE_DISCOVER_NTF with a Protocol type of
729 status = NCI_STATUS_REJECTED; 729 * “HCI Access”, even if the HCI Network contains multiple NFCEEs.
730 goto exit; 730 */
731 } 731 if (!ndev->hci_dev->conn_info) {
732 conn_info = devm_kzalloc(&ndev->nfc_dev->dev,
733 sizeof(*conn_info), GFP_KERNEL);
734 if (!conn_info) {
735 status = NCI_STATUS_REJECTED;
736 goto exit;
737 }
732 738
733 conn_info->id = nfcee_ntf->nfcee_id; 739 conn_info->id = nfcee_ntf->nfcee_id;
734 conn_info->conn_id = NCI_INVALID_CONN_ID; 740 conn_info->conn_id = NCI_INVALID_CONN_ID;
735 741
736 INIT_LIST_HEAD(&conn_info->list); 742 conn_info->data_exchange_cb = nci_hci_data_received_cb;
737 list_add(&conn_info->list, &ndev->conn_info_list); 743 conn_info->data_exchange_cb_context = ndev;
744
745 INIT_LIST_HEAD(&conn_info->list);
746 list_add(&conn_info->list, &ndev->conn_info_list);
747
748 ndev->hci_dev->conn_info = conn_info;
749 }
738 750
739exit: 751exit:
740 nci_req_complete(ndev, status); 752 nci_req_complete(ndev, status);