146fe7771SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 215d17170SChristophe Ricard /* 315d17170SChristophe Ricard * Proprietary commands extension for STMicroelectronics NFC Chip 415d17170SChristophe Ricard * 515d17170SChristophe Ricard * Copyright (C) 2014-2015 STMicroelectronics SAS. All rights reserved. 615d17170SChristophe Ricard */ 715d17170SChristophe Ricard 815d17170SChristophe Ricard #include <net/genetlink.h> 915d17170SChristophe Ricard #include <linux/module.h> 1015d17170SChristophe Ricard #include <linux/nfc.h> 1115d17170SChristophe Ricard #include <net/nfc/hci.h> 1215d17170SChristophe Ricard #include <net/nfc/llc.h> 1315d17170SChristophe Ricard 1415d17170SChristophe Ricard #include "st21nfca.h" 1515d17170SChristophe Ricard 1615d17170SChristophe Ricard #define ST21NFCA_HCI_DM_GETDATA 0x10 1715d17170SChristophe Ricard #define ST21NFCA_HCI_DM_PUTDATA 0x11 1815d17170SChristophe Ricard #define ST21NFCA_HCI_DM_LOAD 0x12 1915d17170SChristophe Ricard #define ST21NFCA_HCI_DM_GETINFO 0x13 2015d17170SChristophe Ricard #define ST21NFCA_HCI_DM_UPDATE_AID 0x20 2115d17170SChristophe Ricard #define ST21NFCA_HCI_DM_RESET 0x3e 2215d17170SChristophe Ricard 2315d17170SChristophe Ricard #define ST21NFCA_HCI_DM_FIELD_GENERATOR 0x32 2415d17170SChristophe Ricard 2515d17170SChristophe Ricard #define ST21NFCA_FACTORY_MODE_ON 1 2615d17170SChristophe Ricard #define ST21NFCA_FACTORY_MODE_OFF 0 2715d17170SChristophe Ricard 2815d17170SChristophe Ricard #define ST21NFCA_EVT_POST_DATA 0x02 2915d17170SChristophe Ricard 3015d17170SChristophe Ricard struct get_param_data { 3115d17170SChristophe Ricard u8 gate; 3215d17170SChristophe Ricard u8 data; 3315d17170SChristophe Ricard } __packed; 3415d17170SChristophe Ricard 3515d17170SChristophe Ricard static int st21nfca_factory_mode(struct nfc_dev *dev, void *data, 3615d17170SChristophe Ricard size_t data_len) 3715d17170SChristophe Ricard { 3815d17170SChristophe Ricard struct nfc_hci_dev *hdev = nfc_get_drvdata(dev); 3915d17170SChristophe Ricard 4015d17170SChristophe Ricard if (data_len != 1) 4115d17170SChristophe Ricard return -EINVAL; 4215d17170SChristophe Ricard 4315d17170SChristophe Ricard pr_debug("factory mode: %x\n", ((u8 *)data)[0]); 4415d17170SChristophe Ricard 4515d17170SChristophe Ricard switch (((u8 *)data)[0]) { 4615d17170SChristophe Ricard case ST21NFCA_FACTORY_MODE_ON: 4715d17170SChristophe Ricard test_and_set_bit(ST21NFCA_FACTORY_MODE, &hdev->quirks); 4815d17170SChristophe Ricard break; 4915d17170SChristophe Ricard case ST21NFCA_FACTORY_MODE_OFF: 5015d17170SChristophe Ricard clear_bit(ST21NFCA_FACTORY_MODE, &hdev->quirks); 5115d17170SChristophe Ricard break; 5215d17170SChristophe Ricard default: 5315d17170SChristophe Ricard return -EINVAL; 5415d17170SChristophe Ricard } 5515d17170SChristophe Ricard 5615d17170SChristophe Ricard return 0; 5715d17170SChristophe Ricard } 5815d17170SChristophe Ricard 5915d17170SChristophe Ricard static int st21nfca_hci_clear_all_pipes(struct nfc_dev *dev, void *data, 6015d17170SChristophe Ricard size_t data_len) 6115d17170SChristophe Ricard { 6215d17170SChristophe Ricard struct nfc_hci_dev *hdev = nfc_get_drvdata(dev); 6315d17170SChristophe Ricard 6415d17170SChristophe Ricard return nfc_hci_disconnect_all_gates(hdev); 6515d17170SChristophe Ricard } 6615d17170SChristophe Ricard 6715d17170SChristophe Ricard static int st21nfca_hci_dm_put_data(struct nfc_dev *dev, void *data, 6815d17170SChristophe Ricard size_t data_len) 6915d17170SChristophe Ricard { 7015d17170SChristophe Ricard struct nfc_hci_dev *hdev = nfc_get_drvdata(dev); 7115d17170SChristophe Ricard 7215d17170SChristophe Ricard return nfc_hci_send_cmd(hdev, ST21NFCA_DEVICE_MGNT_GATE, 7315d17170SChristophe Ricard ST21NFCA_HCI_DM_PUTDATA, data, 7415d17170SChristophe Ricard data_len, NULL); 7515d17170SChristophe Ricard } 7615d17170SChristophe Ricard 7715d17170SChristophe Ricard static int st21nfca_hci_dm_update_aid(struct nfc_dev *dev, void *data, 7815d17170SChristophe Ricard size_t data_len) 7915d17170SChristophe Ricard { 8015d17170SChristophe Ricard struct nfc_hci_dev *hdev = nfc_get_drvdata(dev); 8115d17170SChristophe Ricard 8215d17170SChristophe Ricard return nfc_hci_send_cmd(hdev, ST21NFCA_DEVICE_MGNT_GATE, 8315d17170SChristophe Ricard ST21NFCA_HCI_DM_UPDATE_AID, data, data_len, NULL); 8415d17170SChristophe Ricard } 8515d17170SChristophe Ricard 8615d17170SChristophe Ricard static int st21nfca_hci_dm_get_info(struct nfc_dev *dev, void *data, 8715d17170SChristophe Ricard size_t data_len) 8815d17170SChristophe Ricard { 8915d17170SChristophe Ricard int r; 9015d17170SChristophe Ricard struct sk_buff *msg, *skb; 9115d17170SChristophe Ricard struct nfc_hci_dev *hdev = nfc_get_drvdata(dev); 9215d17170SChristophe Ricard 9315d17170SChristophe Ricard r = nfc_hci_send_cmd(hdev, 9415d17170SChristophe Ricard ST21NFCA_DEVICE_MGNT_GATE, 9515d17170SChristophe Ricard ST21NFCA_HCI_DM_GETINFO, 9615d17170SChristophe Ricard data, data_len, &skb); 9715d17170SChristophe Ricard if (r) 9815d17170SChristophe Ricard goto exit; 9915d17170SChristophe Ricard 10015d17170SChristophe Ricard msg = nfc_vendor_cmd_alloc_reply_skb(dev, ST21NFCA_VENDOR_OUI, 10115d17170SChristophe Ricard HCI_DM_GET_INFO, skb->len); 10215d17170SChristophe Ricard if (!msg) { 10315d17170SChristophe Ricard r = -ENOMEM; 10415d17170SChristophe Ricard goto free_skb; 10515d17170SChristophe Ricard } 10615d17170SChristophe Ricard 10715d17170SChristophe Ricard if (nla_put(msg, NFC_ATTR_VENDOR_DATA, skb->len, skb->data)) { 10815d17170SChristophe Ricard kfree_skb(msg); 10915d17170SChristophe Ricard r = -ENOBUFS; 11015d17170SChristophe Ricard goto free_skb; 11115d17170SChristophe Ricard } 11215d17170SChristophe Ricard 11315d17170SChristophe Ricard r = nfc_vendor_cmd_reply(msg); 11415d17170SChristophe Ricard 11515d17170SChristophe Ricard free_skb: 11615d17170SChristophe Ricard kfree_skb(skb); 11715d17170SChristophe Ricard exit: 11815d17170SChristophe Ricard return r; 11915d17170SChristophe Ricard } 12015d17170SChristophe Ricard 12115d17170SChristophe Ricard static int st21nfca_hci_dm_get_data(struct nfc_dev *dev, void *data, 12215d17170SChristophe Ricard size_t data_len) 12315d17170SChristophe Ricard { 12415d17170SChristophe Ricard int r; 12515d17170SChristophe Ricard struct sk_buff *msg, *skb; 12615d17170SChristophe Ricard struct nfc_hci_dev *hdev = nfc_get_drvdata(dev); 12715d17170SChristophe Ricard 12815d17170SChristophe Ricard r = nfc_hci_send_cmd(hdev, 12915d17170SChristophe Ricard ST21NFCA_DEVICE_MGNT_GATE, 13015d17170SChristophe Ricard ST21NFCA_HCI_DM_GETDATA, 13115d17170SChristophe Ricard data, data_len, &skb); 13215d17170SChristophe Ricard if (r) 13315d17170SChristophe Ricard goto exit; 13415d17170SChristophe Ricard 13515d17170SChristophe Ricard msg = nfc_vendor_cmd_alloc_reply_skb(dev, ST21NFCA_VENDOR_OUI, 13615d17170SChristophe Ricard HCI_DM_GET_DATA, skb->len); 13715d17170SChristophe Ricard if (!msg) { 13815d17170SChristophe Ricard r = -ENOMEM; 13915d17170SChristophe Ricard goto free_skb; 14015d17170SChristophe Ricard } 14115d17170SChristophe Ricard 14215d17170SChristophe Ricard if (nla_put(msg, NFC_ATTR_VENDOR_DATA, skb->len, skb->data)) { 14315d17170SChristophe Ricard kfree_skb(msg); 14415d17170SChristophe Ricard r = -ENOBUFS; 14515d17170SChristophe Ricard goto free_skb; 14615d17170SChristophe Ricard } 14715d17170SChristophe Ricard 14815d17170SChristophe Ricard r = nfc_vendor_cmd_reply(msg); 14915d17170SChristophe Ricard 15015d17170SChristophe Ricard free_skb: 15115d17170SChristophe Ricard kfree_skb(skb); 15215d17170SChristophe Ricard exit: 15315d17170SChristophe Ricard return r; 15415d17170SChristophe Ricard } 15515d17170SChristophe Ricard 15615d17170SChristophe Ricard static int st21nfca_hci_dm_load(struct nfc_dev *dev, void *data, 15715d17170SChristophe Ricard size_t data_len) 15815d17170SChristophe Ricard { 15915d17170SChristophe Ricard struct nfc_hci_dev *hdev = nfc_get_drvdata(dev); 16015d17170SChristophe Ricard 16115d17170SChristophe Ricard return nfc_hci_send_cmd(hdev, ST21NFCA_DEVICE_MGNT_GATE, 16215d17170SChristophe Ricard ST21NFCA_HCI_DM_LOAD, data, data_len, NULL); 16315d17170SChristophe Ricard } 16415d17170SChristophe Ricard 16515d17170SChristophe Ricard static int st21nfca_hci_dm_reset(struct nfc_dev *dev, void *data, 16615d17170SChristophe Ricard size_t data_len) 16715d17170SChristophe Ricard { 16815d17170SChristophe Ricard int r; 16915d17170SChristophe Ricard struct nfc_hci_dev *hdev = nfc_get_drvdata(dev); 17015d17170SChristophe Ricard 17115d17170SChristophe Ricard r = nfc_hci_send_cmd_async(hdev, ST21NFCA_DEVICE_MGNT_GATE, 17215d17170SChristophe Ricard ST21NFCA_HCI_DM_RESET, data, data_len, NULL, NULL); 17315d17170SChristophe Ricard if (r < 0) 17415d17170SChristophe Ricard return r; 17515d17170SChristophe Ricard 17615d17170SChristophe Ricard r = nfc_llc_stop(hdev->llc); 17715d17170SChristophe Ricard if (r < 0) 17815d17170SChristophe Ricard return r; 17915d17170SChristophe Ricard 18015d17170SChristophe Ricard return nfc_llc_start(hdev->llc); 18115d17170SChristophe Ricard } 18215d17170SChristophe Ricard 18315d17170SChristophe Ricard static int st21nfca_hci_get_param(struct nfc_dev *dev, void *data, 18415d17170SChristophe Ricard size_t data_len) 18515d17170SChristophe Ricard { 18615d17170SChristophe Ricard int r; 18715d17170SChristophe Ricard struct sk_buff *msg, *skb; 18815d17170SChristophe Ricard struct nfc_hci_dev *hdev = nfc_get_drvdata(dev); 18915d17170SChristophe Ricard struct get_param_data *param = (struct get_param_data *)data; 19015d17170SChristophe Ricard 19115d17170SChristophe Ricard if (data_len < sizeof(struct get_param_data)) 19215d17170SChristophe Ricard return -EPROTO; 19315d17170SChristophe Ricard 19415d17170SChristophe Ricard r = nfc_hci_get_param(hdev, param->gate, param->data, &skb); 19515d17170SChristophe Ricard if (r) 19615d17170SChristophe Ricard goto exit; 19715d17170SChristophe Ricard 19815d17170SChristophe Ricard msg = nfc_vendor_cmd_alloc_reply_skb(dev, ST21NFCA_VENDOR_OUI, 19915d17170SChristophe Ricard HCI_GET_PARAM, skb->len); 20015d17170SChristophe Ricard if (!msg) { 20115d17170SChristophe Ricard r = -ENOMEM; 20215d17170SChristophe Ricard goto free_skb; 20315d17170SChristophe Ricard } 20415d17170SChristophe Ricard 20515d17170SChristophe Ricard if (nla_put(msg, NFC_ATTR_VENDOR_DATA, skb->len, skb->data)) { 20615d17170SChristophe Ricard kfree_skb(msg); 20715d17170SChristophe Ricard r = -ENOBUFS; 20815d17170SChristophe Ricard goto free_skb; 20915d17170SChristophe Ricard } 21015d17170SChristophe Ricard 21115d17170SChristophe Ricard r = nfc_vendor_cmd_reply(msg); 21215d17170SChristophe Ricard 21315d17170SChristophe Ricard free_skb: 21415d17170SChristophe Ricard kfree_skb(skb); 21515d17170SChristophe Ricard exit: 21615d17170SChristophe Ricard return r; 21715d17170SChristophe Ricard } 21815d17170SChristophe Ricard 21915d17170SChristophe Ricard static int st21nfca_hci_dm_field_generator(struct nfc_dev *dev, void *data, 22015d17170SChristophe Ricard size_t data_len) 22115d17170SChristophe Ricard { 22215d17170SChristophe Ricard struct nfc_hci_dev *hdev = nfc_get_drvdata(dev); 22315d17170SChristophe Ricard 22415d17170SChristophe Ricard return nfc_hci_send_cmd(hdev, 22515d17170SChristophe Ricard ST21NFCA_DEVICE_MGNT_GATE, 22615d17170SChristophe Ricard ST21NFCA_HCI_DM_FIELD_GENERATOR, 22715d17170SChristophe Ricard data, data_len, NULL); 22815d17170SChristophe Ricard } 22915d17170SChristophe Ricard 23015d17170SChristophe Ricard int st21nfca_hci_loopback_event_received(struct nfc_hci_dev *hdev, u8 event, 23115d17170SChristophe Ricard struct sk_buff *skb) 23215d17170SChristophe Ricard { 23315d17170SChristophe Ricard struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); 23415d17170SChristophe Ricard 23515d17170SChristophe Ricard switch (event) { 23615d17170SChristophe Ricard case ST21NFCA_EVT_POST_DATA: 23715d17170SChristophe Ricard info->vendor_info.rx_skb = skb; 23815d17170SChristophe Ricard break; 23915d17170SChristophe Ricard default: 24015d17170SChristophe Ricard nfc_err(&hdev->ndev->dev, "Unexpected event on loopback gate\n"); 24115d17170SChristophe Ricard } 24215d17170SChristophe Ricard complete(&info->vendor_info.req_completion); 24315d17170SChristophe Ricard return 0; 24415d17170SChristophe Ricard } 24515d17170SChristophe Ricard EXPORT_SYMBOL(st21nfca_hci_loopback_event_received); 24615d17170SChristophe Ricard 24715d17170SChristophe Ricard static int st21nfca_hci_loopback(struct nfc_dev *dev, void *data, 24815d17170SChristophe Ricard size_t data_len) 24915d17170SChristophe Ricard { 25015d17170SChristophe Ricard int r; 25115d17170SChristophe Ricard struct sk_buff *msg; 25215d17170SChristophe Ricard struct nfc_hci_dev *hdev = nfc_get_drvdata(dev); 25315d17170SChristophe Ricard struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); 25415d17170SChristophe Ricard 25515d17170SChristophe Ricard if (data_len <= 0) 25615d17170SChristophe Ricard return -EPROTO; 25715d17170SChristophe Ricard 25815d17170SChristophe Ricard reinit_completion(&info->vendor_info.req_completion); 25915d17170SChristophe Ricard info->vendor_info.rx_skb = NULL; 26015d17170SChristophe Ricard 26115d17170SChristophe Ricard r = nfc_hci_send_event(hdev, NFC_HCI_LOOPBACK_GATE, 26215d17170SChristophe Ricard ST21NFCA_EVT_POST_DATA, data, data_len); 26315d17170SChristophe Ricard if (r < 0) { 26415d17170SChristophe Ricard r = -EPROTO; 26515d17170SChristophe Ricard goto exit; 26615d17170SChristophe Ricard } 26715d17170SChristophe Ricard 26815d17170SChristophe Ricard wait_for_completion_interruptible(&info->vendor_info.req_completion); 26915d17170SChristophe Ricard if (!info->vendor_info.rx_skb || 27015d17170SChristophe Ricard info->vendor_info.rx_skb->len != data_len) { 27115d17170SChristophe Ricard r = -EPROTO; 27215d17170SChristophe Ricard goto exit; 27315d17170SChristophe Ricard } 27415d17170SChristophe Ricard 27515d17170SChristophe Ricard msg = nfc_vendor_cmd_alloc_reply_skb(hdev->ndev, 27615d17170SChristophe Ricard ST21NFCA_VENDOR_OUI, 27715d17170SChristophe Ricard HCI_LOOPBACK, 27815d17170SChristophe Ricard info->vendor_info.rx_skb->len); 27915d17170SChristophe Ricard if (!msg) { 28015d17170SChristophe Ricard r = -ENOMEM; 28115d17170SChristophe Ricard goto free_skb; 28215d17170SChristophe Ricard } 28315d17170SChristophe Ricard 28415d17170SChristophe Ricard if (nla_put(msg, NFC_ATTR_VENDOR_DATA, info->vendor_info.rx_skb->len, 28515d17170SChristophe Ricard info->vendor_info.rx_skb->data)) { 28615d17170SChristophe Ricard kfree_skb(msg); 28715d17170SChristophe Ricard r = -ENOBUFS; 28815d17170SChristophe Ricard goto free_skb; 28915d17170SChristophe Ricard } 29015d17170SChristophe Ricard 29115d17170SChristophe Ricard r = nfc_vendor_cmd_reply(msg); 29215d17170SChristophe Ricard free_skb: 29315d17170SChristophe Ricard kfree_skb(info->vendor_info.rx_skb); 29415d17170SChristophe Ricard exit: 29515d17170SChristophe Ricard return r; 29615d17170SChristophe Ricard } 29715d17170SChristophe Ricard 29815d17170SChristophe Ricard static struct nfc_vendor_cmd st21nfca_vendor_cmds[] = { 29915d17170SChristophe Ricard { 30015d17170SChristophe Ricard .vendor_id = ST21NFCA_VENDOR_OUI, 30115d17170SChristophe Ricard .subcmd = FACTORY_MODE, 30215d17170SChristophe Ricard .doit = st21nfca_factory_mode, 30315d17170SChristophe Ricard }, 30415d17170SChristophe Ricard { 30515d17170SChristophe Ricard .vendor_id = ST21NFCA_VENDOR_OUI, 30615d17170SChristophe Ricard .subcmd = HCI_CLEAR_ALL_PIPES, 30715d17170SChristophe Ricard .doit = st21nfca_hci_clear_all_pipes, 30815d17170SChristophe Ricard }, 30915d17170SChristophe Ricard { 31015d17170SChristophe Ricard .vendor_id = ST21NFCA_VENDOR_OUI, 31115d17170SChristophe Ricard .subcmd = HCI_DM_PUT_DATA, 31215d17170SChristophe Ricard .doit = st21nfca_hci_dm_put_data, 31315d17170SChristophe Ricard }, 31415d17170SChristophe Ricard { 31515d17170SChristophe Ricard .vendor_id = ST21NFCA_VENDOR_OUI, 31615d17170SChristophe Ricard .subcmd = HCI_DM_UPDATE_AID, 31715d17170SChristophe Ricard .doit = st21nfca_hci_dm_update_aid, 31815d17170SChristophe Ricard }, 31915d17170SChristophe Ricard { 32015d17170SChristophe Ricard .vendor_id = ST21NFCA_VENDOR_OUI, 32115d17170SChristophe Ricard .subcmd = HCI_DM_GET_INFO, 32215d17170SChristophe Ricard .doit = st21nfca_hci_dm_get_info, 32315d17170SChristophe Ricard }, 32415d17170SChristophe Ricard { 32515d17170SChristophe Ricard .vendor_id = ST21NFCA_VENDOR_OUI, 32615d17170SChristophe Ricard .subcmd = HCI_DM_GET_DATA, 32715d17170SChristophe Ricard .doit = st21nfca_hci_dm_get_data, 32815d17170SChristophe Ricard }, 32915d17170SChristophe Ricard { 33015d17170SChristophe Ricard .vendor_id = ST21NFCA_VENDOR_OUI, 33115d17170SChristophe Ricard .subcmd = HCI_DM_LOAD, 33215d17170SChristophe Ricard .doit = st21nfca_hci_dm_load, 33315d17170SChristophe Ricard }, 33415d17170SChristophe Ricard { 33515d17170SChristophe Ricard .vendor_id = ST21NFCA_VENDOR_OUI, 33615d17170SChristophe Ricard .subcmd = HCI_DM_RESET, 33715d17170SChristophe Ricard .doit = st21nfca_hci_dm_reset, 33815d17170SChristophe Ricard }, 33915d17170SChristophe Ricard { 34015d17170SChristophe Ricard .vendor_id = ST21NFCA_VENDOR_OUI, 34115d17170SChristophe Ricard .subcmd = HCI_GET_PARAM, 34215d17170SChristophe Ricard .doit = st21nfca_hci_get_param, 34315d17170SChristophe Ricard }, 34415d17170SChristophe Ricard { 34515d17170SChristophe Ricard .vendor_id = ST21NFCA_VENDOR_OUI, 34615d17170SChristophe Ricard .subcmd = HCI_DM_FIELD_GENERATOR, 34715d17170SChristophe Ricard .doit = st21nfca_hci_dm_field_generator, 34815d17170SChristophe Ricard }, 34915d17170SChristophe Ricard { 35015d17170SChristophe Ricard .vendor_id = ST21NFCA_VENDOR_OUI, 35115d17170SChristophe Ricard .subcmd = HCI_LOOPBACK, 35215d17170SChristophe Ricard .doit = st21nfca_hci_loopback, 35315d17170SChristophe Ricard }, 35415d17170SChristophe Ricard }; 35515d17170SChristophe Ricard 35615d17170SChristophe Ricard int st21nfca_vendor_cmds_init(struct nfc_hci_dev *hdev) 35715d17170SChristophe Ricard { 35815d17170SChristophe Ricard struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); 35915d17170SChristophe Ricard 36015d17170SChristophe Ricard init_completion(&info->vendor_info.req_completion); 36115d17170SChristophe Ricard return nfc_set_vendor_cmds(hdev->ndev, st21nfca_vendor_cmds, 36215d17170SChristophe Ricard sizeof(st21nfca_vendor_cmds)); 36315d17170SChristophe Ricard } 36415d17170SChristophe Ricard EXPORT_SYMBOL(st21nfca_vendor_cmds_init); 365