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);