2 * Proprietary commands extension for STMicroelectronics NFC NCI 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 <linux/delay.h>
23 #include <net/nfc/nci_core.h>
27 #define ST_NCI_HCI_DM_GETDATA 0x10
28 #define ST_NCI_HCI_DM_PUTDATA 0x11
29 #define ST_NCI_HCI_DM_LOAD 0x12
30 #define ST_NCI_HCI_DM_GETINFO 0x13
31 #define ST_NCI_HCI_DM_FWUPD_START 0x14
32 #define ST_NCI_HCI_DM_FWUPD_STOP 0x15
33 #define ST_NCI_HCI_DM_UPDATE_AID 0x20
34 #define ST_NCI_HCI_DM_RESET 0x3e
36 #define ST_NCI_HCI_DM_FIELD_GENERATOR 0x32
37 #define ST_NCI_HCI_DM_VDC_MEASUREMENT_VALUE 0x33
38 #define ST_NCI_HCI_DM_VDC_VALUE_COMPARISON 0x34
40 #define ST_NCI_FACTORY_MODE_ON 1
41 #define ST_NCI_FACTORY_MODE_OFF 0
43 #define ST_NCI_EVT_POST_DATA 0x02
45 struct get_param_data
{
50 static int st_nci_factory_mode(struct nfc_dev
*dev
, void *data
,
53 struct nci_dev
*ndev
= nfc_get_drvdata(dev
);
54 struct st_nci_info
*info
= nci_get_drvdata(ndev
);
59 pr_debug("factory mode: %x\n", ((u8
*)data
)[0]);
61 switch (((u8
*)data
)[0]) {
62 case ST_NCI_FACTORY_MODE_ON
:
63 test_and_set_bit(ST_NCI_FACTORY_MODE
, &info
->flags
);
65 case ST_NCI_FACTORY_MODE_OFF
:
66 clear_bit(ST_NCI_FACTORY_MODE
, &info
->flags
);
75 static int st_nci_hci_clear_all_pipes(struct nfc_dev
*dev
, void *data
,
78 struct nci_dev
*ndev
= nfc_get_drvdata(dev
);
80 return nci_hci_clear_all_pipes(ndev
);
83 static int st_nci_hci_dm_put_data(struct nfc_dev
*dev
, void *data
,
86 struct nci_dev
*ndev
= nfc_get_drvdata(dev
);
88 return nci_hci_send_cmd(ndev
, ST_NCI_DEVICE_MGNT_GATE
,
89 ST_NCI_HCI_DM_PUTDATA
, data
,
93 static int st_nci_hci_dm_update_aid(struct nfc_dev
*dev
, void *data
,
96 struct nci_dev
*ndev
= nfc_get_drvdata(dev
);
98 return nci_hci_send_cmd(ndev
, ST_NCI_DEVICE_MGNT_GATE
,
99 ST_NCI_HCI_DM_UPDATE_AID
, data
, data_len
, NULL
);
102 static int st_nci_hci_dm_get_info(struct nfc_dev
*dev
, void *data
,
106 struct sk_buff
*msg
, *skb
;
107 struct nci_dev
*ndev
= nfc_get_drvdata(dev
);
109 r
= nci_hci_send_cmd(ndev
, ST_NCI_DEVICE_MGNT_GATE
, ST_NCI_HCI_DM_GETINFO
,
110 data
, data_len
, &skb
);
114 msg
= nfc_vendor_cmd_alloc_reply_skb(dev
, ST_NCI_VENDOR_OUI
,
115 HCI_DM_GET_INFO
, skb
->len
);
121 if (nla_put(msg
, NFC_ATTR_VENDOR_DATA
, skb
->len
, skb
->data
)) {
127 r
= nfc_vendor_cmd_reply(msg
);
135 static int st_nci_hci_dm_get_data(struct nfc_dev
*dev
, void *data
,
139 struct sk_buff
*msg
, *skb
;
140 struct nci_dev
*ndev
= nfc_get_drvdata(dev
);
142 r
= nci_hci_send_cmd(ndev
, ST_NCI_DEVICE_MGNT_GATE
, ST_NCI_HCI_DM_GETDATA
,
143 data
, data_len
, &skb
);
147 msg
= nfc_vendor_cmd_alloc_reply_skb(dev
, ST_NCI_VENDOR_OUI
,
148 HCI_DM_GET_DATA
, skb
->len
);
154 if (nla_put(msg
, NFC_ATTR_VENDOR_DATA
, skb
->len
, skb
->data
)) {
160 r
= nfc_vendor_cmd_reply(msg
);
168 static int st_nci_hci_dm_fwupd_start(struct nfc_dev
*dev
, void *data
,
172 struct nci_dev
*ndev
= nfc_get_drvdata(dev
);
174 dev
->fw_download_in_progress
= true;
175 r
= nci_hci_send_cmd(ndev
, ST_NCI_DEVICE_MGNT_GATE
,
176 ST_NCI_HCI_DM_FWUPD_START
, data
, data_len
, NULL
);
178 dev
->fw_download_in_progress
= false;
183 static int st_nci_hci_dm_fwupd_end(struct nfc_dev
*dev
, void *data
,
186 struct nci_dev
*ndev
= nfc_get_drvdata(dev
);
188 return nci_hci_send_cmd(ndev
, ST_NCI_DEVICE_MGNT_GATE
,
189 ST_NCI_HCI_DM_FWUPD_STOP
, data
, data_len
, NULL
);
192 static int st_nci_hci_dm_direct_load(struct nfc_dev
*dev
, void *data
,
195 struct nci_dev
*ndev
= nfc_get_drvdata(dev
);
197 if (dev
->fw_download_in_progress
) {
198 dev
->fw_download_in_progress
= false;
199 return nci_hci_send_cmd(ndev
, ST_NCI_DEVICE_MGNT_GATE
,
200 ST_NCI_HCI_DM_LOAD
, data
, data_len
, NULL
);
205 static int st_nci_hci_dm_reset(struct nfc_dev
*dev
, void *data
,
208 struct nci_dev
*ndev
= nfc_get_drvdata(dev
);
210 nci_hci_send_cmd(ndev
, ST_NCI_DEVICE_MGNT_GATE
,
211 ST_NCI_HCI_DM_RESET
, data
, data_len
, NULL
);
217 static int st_nci_hci_get_param(struct nfc_dev
*dev
, void *data
,
221 struct sk_buff
*msg
, *skb
;
222 struct nci_dev
*ndev
= nfc_get_drvdata(dev
);
223 struct get_param_data
*param
= (struct get_param_data
*)data
;
225 if (data_len
< sizeof(struct get_param_data
))
228 r
= nci_hci_get_param(ndev
, param
->gate
, param
->data
, &skb
);
232 msg
= nfc_vendor_cmd_alloc_reply_skb(dev
, ST_NCI_VENDOR_OUI
,
233 HCI_GET_PARAM
, skb
->len
);
239 if (nla_put(msg
, NFC_ATTR_VENDOR_DATA
, skb
->len
, skb
->data
)) {
245 r
= nfc_vendor_cmd_reply(msg
);
253 static int st_nci_hci_dm_field_generator(struct nfc_dev
*dev
, void *data
,
256 struct nci_dev
*ndev
= nfc_get_drvdata(dev
);
258 return nci_hci_send_cmd(ndev
, ST_NCI_DEVICE_MGNT_GATE
,
259 ST_NCI_HCI_DM_FIELD_GENERATOR
, data
, data_len
, NULL
);
262 static int st_nci_hci_dm_vdc_measurement_value(struct nfc_dev
*dev
, void *data
,
266 struct sk_buff
*msg
, *skb
;
267 struct nci_dev
*ndev
= nfc_get_drvdata(dev
);
272 r
= nci_hci_send_cmd(ndev
, ST_NCI_DEVICE_MGNT_GATE
,
273 ST_NCI_HCI_DM_VDC_MEASUREMENT_VALUE
,
274 data
, data_len
, &skb
);
278 msg
= nfc_vendor_cmd_alloc_reply_skb(dev
, ST_NCI_VENDOR_OUI
,
279 HCI_DM_VDC_MEASUREMENT_VALUE
, skb
->len
);
285 if (nla_put(msg
, NFC_ATTR_VENDOR_DATA
, skb
->len
, skb
->data
)) {
291 r
= nfc_vendor_cmd_reply(msg
);
299 static int st_nci_hci_dm_vdc_value_comparison(struct nfc_dev
*dev
, void *data
,
303 struct sk_buff
*msg
, *skb
;
304 struct nci_dev
*ndev
= nfc_get_drvdata(dev
);
309 r
= nci_hci_send_cmd(ndev
, ST_NCI_DEVICE_MGNT_GATE
,
310 ST_NCI_HCI_DM_VDC_VALUE_COMPARISON
,
311 data
, data_len
, &skb
);
315 msg
= nfc_vendor_cmd_alloc_reply_skb(dev
, ST_NCI_VENDOR_OUI
,
316 HCI_DM_VDC_VALUE_COMPARISON
, skb
->len
);
322 if (nla_put(msg
, NFC_ATTR_VENDOR_DATA
, skb
->len
, skb
->data
)) {
328 r
= nfc_vendor_cmd_reply(msg
);
336 static int st_nci_loopback(struct nfc_dev
*dev
, void *data
,
340 struct sk_buff
*msg
, *skb
;
341 struct nci_dev
*ndev
= nfc_get_drvdata(dev
);
346 r
= nci_nfcc_loopback(ndev
, data
, data_len
, &skb
);
350 msg
= nfc_vendor_cmd_alloc_reply_skb(dev
, ST_NCI_VENDOR_OUI
,
357 if (nla_put(msg
, NFC_ATTR_VENDOR_DATA
, skb
->len
, skb
->data
)) {
363 r
= nfc_vendor_cmd_reply(msg
);
369 static int st_nci_manufacturer_specific(struct nfc_dev
*dev
, void *data
,
373 struct nci_dev
*ndev
= nfc_get_drvdata(dev
);
375 msg
= nfc_vendor_cmd_alloc_reply_skb(dev
, ST_NCI_VENDOR_OUI
,
376 MANUFACTURER_SPECIFIC
,
377 sizeof(ndev
->manufact_specific_info
));
381 if (nla_put(msg
, NFC_ATTR_VENDOR_DATA
, sizeof(ndev
->manufact_specific_info
),
382 &ndev
->manufact_specific_info
)) {
387 return nfc_vendor_cmd_reply(msg
);
390 static struct nfc_vendor_cmd st_nci_vendor_cmds
[] = {
392 .vendor_id
= ST_NCI_VENDOR_OUI
,
393 .subcmd
= FACTORY_MODE
,
394 .doit
= st_nci_factory_mode
,
397 .vendor_id
= ST_NCI_VENDOR_OUI
,
398 .subcmd
= HCI_CLEAR_ALL_PIPES
,
399 .doit
= st_nci_hci_clear_all_pipes
,
402 .vendor_id
= ST_NCI_VENDOR_OUI
,
403 .subcmd
= HCI_DM_PUT_DATA
,
404 .doit
= st_nci_hci_dm_put_data
,
407 .vendor_id
= ST_NCI_VENDOR_OUI
,
408 .subcmd
= HCI_DM_UPDATE_AID
,
409 .doit
= st_nci_hci_dm_update_aid
,
412 .vendor_id
= ST_NCI_VENDOR_OUI
,
413 .subcmd
= HCI_DM_GET_INFO
,
414 .doit
= st_nci_hci_dm_get_info
,
417 .vendor_id
= ST_NCI_VENDOR_OUI
,
418 .subcmd
= HCI_DM_GET_DATA
,
419 .doit
= st_nci_hci_dm_get_data
,
422 .vendor_id
= ST_NCI_VENDOR_OUI
,
423 .subcmd
= HCI_DM_DIRECT_LOAD
,
424 .doit
= st_nci_hci_dm_direct_load
,
427 .vendor_id
= ST_NCI_VENDOR_OUI
,
428 .subcmd
= HCI_DM_RESET
,
429 .doit
= st_nci_hci_dm_reset
,
432 .vendor_id
= ST_NCI_VENDOR_OUI
,
433 .subcmd
= HCI_GET_PARAM
,
434 .doit
= st_nci_hci_get_param
,
437 .vendor_id
= ST_NCI_VENDOR_OUI
,
438 .subcmd
= HCI_DM_FIELD_GENERATOR
,
439 .doit
= st_nci_hci_dm_field_generator
,
442 .vendor_id
= ST_NCI_VENDOR_OUI
,
443 .subcmd
= HCI_DM_FWUPD_START
,
444 .doit
= st_nci_hci_dm_fwupd_start
,
447 .vendor_id
= ST_NCI_VENDOR_OUI
,
448 .subcmd
= HCI_DM_FWUPD_END
,
449 .doit
= st_nci_hci_dm_fwupd_end
,
452 .vendor_id
= ST_NCI_VENDOR_OUI
,
454 .doit
= st_nci_loopback
,
457 .vendor_id
= ST_NCI_VENDOR_OUI
,
458 .subcmd
= HCI_DM_VDC_MEASUREMENT_VALUE
,
459 .doit
= st_nci_hci_dm_vdc_measurement_value
,
462 .vendor_id
= ST_NCI_VENDOR_OUI
,
463 .subcmd
= HCI_DM_VDC_VALUE_COMPARISON
,
464 .doit
= st_nci_hci_dm_vdc_value_comparison
,
467 .vendor_id
= ST_NCI_VENDOR_OUI
,
468 .subcmd
= MANUFACTURER_SPECIFIC
,
469 .doit
= st_nci_manufacturer_specific
,
473 int st_nci_vendor_cmds_init(struct nci_dev
*ndev
)
475 return nfc_set_vendor_cmds(ndev
->nfc_dev
, st_nci_vendor_cmds
,
476 sizeof(st_nci_vendor_cmds
));
478 EXPORT_SYMBOL(st_nci_vendor_cmds_init
);