1 // SPDX-License-Identifier: GPL-2.0-only
3 * Proprietary commands extension for STMicroelectronics NFC Chip
5 * Copyright (C) 2014-2015 STMicroelectronics SAS. All rights reserved.
8 #include <net/genetlink.h>
9 #include <linux/module.h>
10 #include <linux/nfc.h>
11 #include <net/nfc/hci.h>
12 #include <net/nfc/llc.h>
16 #define ST21NFCA_HCI_DM_GETDATA 0x10
17 #define ST21NFCA_HCI_DM_PUTDATA 0x11
18 #define ST21NFCA_HCI_DM_LOAD 0x12
19 #define ST21NFCA_HCI_DM_GETINFO 0x13
20 #define ST21NFCA_HCI_DM_UPDATE_AID 0x20
21 #define ST21NFCA_HCI_DM_RESET 0x3e
23 #define ST21NFCA_HCI_DM_FIELD_GENERATOR 0x32
25 #define ST21NFCA_FACTORY_MODE_ON 1
26 #define ST21NFCA_FACTORY_MODE_OFF 0
28 #define ST21NFCA_EVT_POST_DATA 0x02
30 struct get_param_data
{
35 static int st21nfca_factory_mode(struct nfc_dev
*dev
, void *data
,
38 struct nfc_hci_dev
*hdev
= nfc_get_drvdata(dev
);
43 pr_debug("factory mode: %x\n", ((u8
*)data
)[0]);
45 switch (((u8
*)data
)[0]) {
46 case ST21NFCA_FACTORY_MODE_ON
:
47 test_and_set_bit(ST21NFCA_FACTORY_MODE
, &hdev
->quirks
);
49 case ST21NFCA_FACTORY_MODE_OFF
:
50 clear_bit(ST21NFCA_FACTORY_MODE
, &hdev
->quirks
);
59 static int st21nfca_hci_clear_all_pipes(struct nfc_dev
*dev
, void *data
,
62 struct nfc_hci_dev
*hdev
= nfc_get_drvdata(dev
);
64 return nfc_hci_disconnect_all_gates(hdev
);
67 static int st21nfca_hci_dm_put_data(struct nfc_dev
*dev
, void *data
,
70 struct nfc_hci_dev
*hdev
= nfc_get_drvdata(dev
);
72 return nfc_hci_send_cmd(hdev
, ST21NFCA_DEVICE_MGNT_GATE
,
73 ST21NFCA_HCI_DM_PUTDATA
, data
,
77 static int st21nfca_hci_dm_update_aid(struct nfc_dev
*dev
, void *data
,
80 struct nfc_hci_dev
*hdev
= nfc_get_drvdata(dev
);
82 return nfc_hci_send_cmd(hdev
, ST21NFCA_DEVICE_MGNT_GATE
,
83 ST21NFCA_HCI_DM_UPDATE_AID
, data
, data_len
, NULL
);
86 static int st21nfca_hci_dm_get_info(struct nfc_dev
*dev
, void *data
,
90 struct sk_buff
*msg
, *skb
;
91 struct nfc_hci_dev
*hdev
= nfc_get_drvdata(dev
);
93 r
= nfc_hci_send_cmd(hdev
,
94 ST21NFCA_DEVICE_MGNT_GATE
,
95 ST21NFCA_HCI_DM_GETINFO
,
96 data
, data_len
, &skb
);
100 msg
= nfc_vendor_cmd_alloc_reply_skb(dev
, ST21NFCA_VENDOR_OUI
,
101 HCI_DM_GET_INFO
, skb
->len
);
107 if (nla_put(msg
, NFC_ATTR_VENDOR_DATA
, skb
->len
, skb
->data
)) {
113 r
= nfc_vendor_cmd_reply(msg
);
121 static int st21nfca_hci_dm_get_data(struct nfc_dev
*dev
, void *data
,
125 struct sk_buff
*msg
, *skb
;
126 struct nfc_hci_dev
*hdev
= nfc_get_drvdata(dev
);
128 r
= nfc_hci_send_cmd(hdev
,
129 ST21NFCA_DEVICE_MGNT_GATE
,
130 ST21NFCA_HCI_DM_GETDATA
,
131 data
, data_len
, &skb
);
135 msg
= nfc_vendor_cmd_alloc_reply_skb(dev
, ST21NFCA_VENDOR_OUI
,
136 HCI_DM_GET_DATA
, skb
->len
);
142 if (nla_put(msg
, NFC_ATTR_VENDOR_DATA
, skb
->len
, skb
->data
)) {
148 r
= nfc_vendor_cmd_reply(msg
);
156 static int st21nfca_hci_dm_load(struct nfc_dev
*dev
, void *data
,
159 struct nfc_hci_dev
*hdev
= nfc_get_drvdata(dev
);
161 return nfc_hci_send_cmd(hdev
, ST21NFCA_DEVICE_MGNT_GATE
,
162 ST21NFCA_HCI_DM_LOAD
, data
, data_len
, NULL
);
165 static int st21nfca_hci_dm_reset(struct nfc_dev
*dev
, void *data
,
169 struct nfc_hci_dev
*hdev
= nfc_get_drvdata(dev
);
171 r
= nfc_hci_send_cmd_async(hdev
, ST21NFCA_DEVICE_MGNT_GATE
,
172 ST21NFCA_HCI_DM_RESET
, data
, data_len
, NULL
, NULL
);
176 r
= nfc_llc_stop(hdev
->llc
);
180 return nfc_llc_start(hdev
->llc
);
183 static int st21nfca_hci_get_param(struct nfc_dev
*dev
, void *data
,
187 struct sk_buff
*msg
, *skb
;
188 struct nfc_hci_dev
*hdev
= nfc_get_drvdata(dev
);
189 struct get_param_data
*param
= (struct get_param_data
*)data
;
191 if (data_len
< sizeof(struct get_param_data
))
194 r
= nfc_hci_get_param(hdev
, param
->gate
, param
->data
, &skb
);
198 msg
= nfc_vendor_cmd_alloc_reply_skb(dev
, ST21NFCA_VENDOR_OUI
,
199 HCI_GET_PARAM
, skb
->len
);
205 if (nla_put(msg
, NFC_ATTR_VENDOR_DATA
, skb
->len
, skb
->data
)) {
211 r
= nfc_vendor_cmd_reply(msg
);
219 static int st21nfca_hci_dm_field_generator(struct nfc_dev
*dev
, void *data
,
222 struct nfc_hci_dev
*hdev
= nfc_get_drvdata(dev
);
224 return nfc_hci_send_cmd(hdev
,
225 ST21NFCA_DEVICE_MGNT_GATE
,
226 ST21NFCA_HCI_DM_FIELD_GENERATOR
,
227 data
, data_len
, NULL
);
230 int st21nfca_hci_loopback_event_received(struct nfc_hci_dev
*hdev
, u8 event
,
233 struct st21nfca_hci_info
*info
= nfc_hci_get_clientdata(hdev
);
236 case ST21NFCA_EVT_POST_DATA
:
237 info
->vendor_info
.rx_skb
= skb
;
240 nfc_err(&hdev
->ndev
->dev
, "Unexpected event on loopback gate\n");
242 complete(&info
->vendor_info
.req_completion
);
245 EXPORT_SYMBOL(st21nfca_hci_loopback_event_received
);
247 static int st21nfca_hci_loopback(struct nfc_dev
*dev
, void *data
,
252 struct nfc_hci_dev
*hdev
= nfc_get_drvdata(dev
);
253 struct st21nfca_hci_info
*info
= nfc_hci_get_clientdata(hdev
);
258 reinit_completion(&info
->vendor_info
.req_completion
);
259 info
->vendor_info
.rx_skb
= NULL
;
261 r
= nfc_hci_send_event(hdev
, NFC_HCI_LOOPBACK_GATE
,
262 ST21NFCA_EVT_POST_DATA
, data
, data_len
);
268 wait_for_completion_interruptible(&info
->vendor_info
.req_completion
);
269 if (!info
->vendor_info
.rx_skb
||
270 info
->vendor_info
.rx_skb
->len
!= data_len
) {
275 msg
= nfc_vendor_cmd_alloc_reply_skb(hdev
->ndev
,
278 info
->vendor_info
.rx_skb
->len
);
284 if (nla_put(msg
, NFC_ATTR_VENDOR_DATA
, info
->vendor_info
.rx_skb
->len
,
285 info
->vendor_info
.rx_skb
->data
)) {
291 r
= nfc_vendor_cmd_reply(msg
);
293 kfree_skb(info
->vendor_info
.rx_skb
);
298 static struct nfc_vendor_cmd st21nfca_vendor_cmds
[] = {
300 .vendor_id
= ST21NFCA_VENDOR_OUI
,
301 .subcmd
= FACTORY_MODE
,
302 .doit
= st21nfca_factory_mode
,
305 .vendor_id
= ST21NFCA_VENDOR_OUI
,
306 .subcmd
= HCI_CLEAR_ALL_PIPES
,
307 .doit
= st21nfca_hci_clear_all_pipes
,
310 .vendor_id
= ST21NFCA_VENDOR_OUI
,
311 .subcmd
= HCI_DM_PUT_DATA
,
312 .doit
= st21nfca_hci_dm_put_data
,
315 .vendor_id
= ST21NFCA_VENDOR_OUI
,
316 .subcmd
= HCI_DM_UPDATE_AID
,
317 .doit
= st21nfca_hci_dm_update_aid
,
320 .vendor_id
= ST21NFCA_VENDOR_OUI
,
321 .subcmd
= HCI_DM_GET_INFO
,
322 .doit
= st21nfca_hci_dm_get_info
,
325 .vendor_id
= ST21NFCA_VENDOR_OUI
,
326 .subcmd
= HCI_DM_GET_DATA
,
327 .doit
= st21nfca_hci_dm_get_data
,
330 .vendor_id
= ST21NFCA_VENDOR_OUI
,
331 .subcmd
= HCI_DM_LOAD
,
332 .doit
= st21nfca_hci_dm_load
,
335 .vendor_id
= ST21NFCA_VENDOR_OUI
,
336 .subcmd
= HCI_DM_RESET
,
337 .doit
= st21nfca_hci_dm_reset
,
340 .vendor_id
= ST21NFCA_VENDOR_OUI
,
341 .subcmd
= HCI_GET_PARAM
,
342 .doit
= st21nfca_hci_get_param
,
345 .vendor_id
= ST21NFCA_VENDOR_OUI
,
346 .subcmd
= HCI_DM_FIELD_GENERATOR
,
347 .doit
= st21nfca_hci_dm_field_generator
,
350 .vendor_id
= ST21NFCA_VENDOR_OUI
,
351 .subcmd
= HCI_LOOPBACK
,
352 .doit
= st21nfca_hci_loopback
,
356 int st21nfca_vendor_cmds_init(struct nfc_hci_dev
*hdev
)
358 struct st21nfca_hci_info
*info
= nfc_hci_get_clientdata(hdev
);
360 init_completion(&info
->vendor_info
.req_completion
);
361 return nfc_set_vendor_cmds(hdev
->ndev
, st21nfca_vendor_cmds
,
362 sizeof(st21nfca_vendor_cmds
));
364 EXPORT_SYMBOL(st21nfca_vendor_cmds_init
);