2 * Proprietary commands extension for STMicroelectronics NFC Chip
4 * Copyright (C) 2014-2015 STMicroelectronics SAS. All rights reserved.
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, see <http://www.gnu.org/licenses/>.
19 #include <net/genetlink.h>
20 #include <linux/module.h>
21 #include <linux/nfc.h>
22 #include <net/nfc/hci.h>
23 #include <net/nfc/llc.h>
27 #define ST21NFCA_HCI_DM_GETDATA 0x10
28 #define ST21NFCA_HCI_DM_PUTDATA 0x11
29 #define ST21NFCA_HCI_DM_LOAD 0x12
30 #define ST21NFCA_HCI_DM_GETINFO 0x13
31 #define ST21NFCA_HCI_DM_UPDATE_AID 0x20
32 #define ST21NFCA_HCI_DM_RESET 0x3e
34 #define ST21NFCA_HCI_DM_FIELD_GENERATOR 0x32
36 #define ST21NFCA_FACTORY_MODE_ON 1
37 #define ST21NFCA_FACTORY_MODE_OFF 0
39 #define ST21NFCA_EVT_POST_DATA 0x02
41 struct get_param_data
{
46 static int st21nfca_factory_mode(struct nfc_dev
*dev
, void *data
,
49 struct nfc_hci_dev
*hdev
= nfc_get_drvdata(dev
);
54 pr_debug("factory mode: %x\n", ((u8
*)data
)[0]);
56 switch (((u8
*)data
)[0]) {
57 case ST21NFCA_FACTORY_MODE_ON
:
58 test_and_set_bit(ST21NFCA_FACTORY_MODE
, &hdev
->quirks
);
60 case ST21NFCA_FACTORY_MODE_OFF
:
61 clear_bit(ST21NFCA_FACTORY_MODE
, &hdev
->quirks
);
70 static int st21nfca_hci_clear_all_pipes(struct nfc_dev
*dev
, void *data
,
73 struct nfc_hci_dev
*hdev
= nfc_get_drvdata(dev
);
75 return nfc_hci_disconnect_all_gates(hdev
);
78 static int st21nfca_hci_dm_put_data(struct nfc_dev
*dev
, void *data
,
81 struct nfc_hci_dev
*hdev
= nfc_get_drvdata(dev
);
83 return nfc_hci_send_cmd(hdev
, ST21NFCA_DEVICE_MGNT_GATE
,
84 ST21NFCA_HCI_DM_PUTDATA
, data
,
88 static int st21nfca_hci_dm_update_aid(struct nfc_dev
*dev
, void *data
,
91 struct nfc_hci_dev
*hdev
= nfc_get_drvdata(dev
);
93 return nfc_hci_send_cmd(hdev
, ST21NFCA_DEVICE_MGNT_GATE
,
94 ST21NFCA_HCI_DM_UPDATE_AID
, data
, data_len
, NULL
);
97 static int st21nfca_hci_dm_get_info(struct nfc_dev
*dev
, void *data
,
101 struct sk_buff
*msg
, *skb
;
102 struct nfc_hci_dev
*hdev
= nfc_get_drvdata(dev
);
104 r
= nfc_hci_send_cmd(hdev
,
105 ST21NFCA_DEVICE_MGNT_GATE
,
106 ST21NFCA_HCI_DM_GETINFO
,
107 data
, data_len
, &skb
);
111 msg
= nfc_vendor_cmd_alloc_reply_skb(dev
, ST21NFCA_VENDOR_OUI
,
112 HCI_DM_GET_INFO
, skb
->len
);
118 if (nla_put(msg
, NFC_ATTR_VENDOR_DATA
, skb
->len
, skb
->data
)) {
124 r
= nfc_vendor_cmd_reply(msg
);
132 static int st21nfca_hci_dm_get_data(struct nfc_dev
*dev
, void *data
,
136 struct sk_buff
*msg
, *skb
;
137 struct nfc_hci_dev
*hdev
= nfc_get_drvdata(dev
);
139 r
= nfc_hci_send_cmd(hdev
,
140 ST21NFCA_DEVICE_MGNT_GATE
,
141 ST21NFCA_HCI_DM_GETDATA
,
142 data
, data_len
, &skb
);
146 msg
= nfc_vendor_cmd_alloc_reply_skb(dev
, ST21NFCA_VENDOR_OUI
,
147 HCI_DM_GET_DATA
, skb
->len
);
153 if (nla_put(msg
, NFC_ATTR_VENDOR_DATA
, skb
->len
, skb
->data
)) {
159 r
= nfc_vendor_cmd_reply(msg
);
167 static int st21nfca_hci_dm_load(struct nfc_dev
*dev
, void *data
,
170 struct nfc_hci_dev
*hdev
= nfc_get_drvdata(dev
);
172 return nfc_hci_send_cmd(hdev
, ST21NFCA_DEVICE_MGNT_GATE
,
173 ST21NFCA_HCI_DM_LOAD
, data
, data_len
, NULL
);
176 static int st21nfca_hci_dm_reset(struct nfc_dev
*dev
, void *data
,
180 struct nfc_hci_dev
*hdev
= nfc_get_drvdata(dev
);
182 r
= nfc_hci_send_cmd_async(hdev
, ST21NFCA_DEVICE_MGNT_GATE
,
183 ST21NFCA_HCI_DM_RESET
, data
, data_len
, NULL
, NULL
);
187 r
= nfc_llc_stop(hdev
->llc
);
191 return nfc_llc_start(hdev
->llc
);
194 static int st21nfca_hci_get_param(struct nfc_dev
*dev
, void *data
,
198 struct sk_buff
*msg
, *skb
;
199 struct nfc_hci_dev
*hdev
= nfc_get_drvdata(dev
);
200 struct get_param_data
*param
= (struct get_param_data
*)data
;
202 if (data_len
< sizeof(struct get_param_data
))
205 r
= nfc_hci_get_param(hdev
, param
->gate
, param
->data
, &skb
);
209 msg
= nfc_vendor_cmd_alloc_reply_skb(dev
, ST21NFCA_VENDOR_OUI
,
210 HCI_GET_PARAM
, skb
->len
);
216 if (nla_put(msg
, NFC_ATTR_VENDOR_DATA
, skb
->len
, skb
->data
)) {
222 r
= nfc_vendor_cmd_reply(msg
);
230 static int st21nfca_hci_dm_field_generator(struct nfc_dev
*dev
, void *data
,
233 struct nfc_hci_dev
*hdev
= nfc_get_drvdata(dev
);
235 return nfc_hci_send_cmd(hdev
,
236 ST21NFCA_DEVICE_MGNT_GATE
,
237 ST21NFCA_HCI_DM_FIELD_GENERATOR
,
238 data
, data_len
, NULL
);
241 int st21nfca_hci_loopback_event_received(struct nfc_hci_dev
*hdev
, u8 event
,
244 struct st21nfca_hci_info
*info
= nfc_hci_get_clientdata(hdev
);
247 case ST21NFCA_EVT_POST_DATA
:
248 info
->vendor_info
.rx_skb
= skb
;
251 nfc_err(&hdev
->ndev
->dev
, "Unexpected event on loopback gate\n");
253 complete(&info
->vendor_info
.req_completion
);
256 EXPORT_SYMBOL(st21nfca_hci_loopback_event_received
);
258 static int st21nfca_hci_loopback(struct nfc_dev
*dev
, void *data
,
263 struct nfc_hci_dev
*hdev
= nfc_get_drvdata(dev
);
264 struct st21nfca_hci_info
*info
= nfc_hci_get_clientdata(hdev
);
269 reinit_completion(&info
->vendor_info
.req_completion
);
270 info
->vendor_info
.rx_skb
= NULL
;
272 r
= nfc_hci_send_event(hdev
, NFC_HCI_LOOPBACK_GATE
,
273 ST21NFCA_EVT_POST_DATA
, data
, data_len
);
279 wait_for_completion_interruptible(&info
->vendor_info
.req_completion
);
280 if (!info
->vendor_info
.rx_skb
||
281 info
->vendor_info
.rx_skb
->len
!= data_len
) {
286 msg
= nfc_vendor_cmd_alloc_reply_skb(hdev
->ndev
,
289 info
->vendor_info
.rx_skb
->len
);
295 if (nla_put(msg
, NFC_ATTR_VENDOR_DATA
, info
->vendor_info
.rx_skb
->len
,
296 info
->vendor_info
.rx_skb
->data
)) {
302 r
= nfc_vendor_cmd_reply(msg
);
304 kfree_skb(info
->vendor_info
.rx_skb
);
309 static struct nfc_vendor_cmd st21nfca_vendor_cmds
[] = {
311 .vendor_id
= ST21NFCA_VENDOR_OUI
,
312 .subcmd
= FACTORY_MODE
,
313 .doit
= st21nfca_factory_mode
,
316 .vendor_id
= ST21NFCA_VENDOR_OUI
,
317 .subcmd
= HCI_CLEAR_ALL_PIPES
,
318 .doit
= st21nfca_hci_clear_all_pipes
,
321 .vendor_id
= ST21NFCA_VENDOR_OUI
,
322 .subcmd
= HCI_DM_PUT_DATA
,
323 .doit
= st21nfca_hci_dm_put_data
,
326 .vendor_id
= ST21NFCA_VENDOR_OUI
,
327 .subcmd
= HCI_DM_UPDATE_AID
,
328 .doit
= st21nfca_hci_dm_update_aid
,
331 .vendor_id
= ST21NFCA_VENDOR_OUI
,
332 .subcmd
= HCI_DM_GET_INFO
,
333 .doit
= st21nfca_hci_dm_get_info
,
336 .vendor_id
= ST21NFCA_VENDOR_OUI
,
337 .subcmd
= HCI_DM_GET_DATA
,
338 .doit
= st21nfca_hci_dm_get_data
,
341 .vendor_id
= ST21NFCA_VENDOR_OUI
,
342 .subcmd
= HCI_DM_LOAD
,
343 .doit
= st21nfca_hci_dm_load
,
346 .vendor_id
= ST21NFCA_VENDOR_OUI
,
347 .subcmd
= HCI_DM_RESET
,
348 .doit
= st21nfca_hci_dm_reset
,
351 .vendor_id
= ST21NFCA_VENDOR_OUI
,
352 .subcmd
= HCI_GET_PARAM
,
353 .doit
= st21nfca_hci_get_param
,
356 .vendor_id
= ST21NFCA_VENDOR_OUI
,
357 .subcmd
= HCI_DM_FIELD_GENERATOR
,
358 .doit
= st21nfca_hci_dm_field_generator
,
361 .vendor_id
= ST21NFCA_VENDOR_OUI
,
362 .subcmd
= HCI_LOOPBACK
,
363 .doit
= st21nfca_hci_loopback
,
367 int st21nfca_vendor_cmds_init(struct nfc_hci_dev
*hdev
)
369 struct st21nfca_hci_info
*info
= nfc_hci_get_clientdata(hdev
);
371 init_completion(&info
->vendor_info
.req_completion
);
372 return nfc_set_vendor_cmds(hdev
->ndev
, st21nfca_vendor_cmds
,
373 sizeof(st21nfca_vendor_cmds
));
375 EXPORT_SYMBOL(st21nfca_vendor_cmds_init
);