Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * NCI based Driver for STMicroelectronics NFC Chip
0004  *
0005  * Copyright (C) 2014-2015  STMicroelectronics SAS. All rights reserved.
0006  */
0007 
0008 #include <linux/module.h>
0009 #include <linux/nfc.h>
0010 #include <net/nfc/nci.h>
0011 #include <net/nfc/nci_core.h>
0012 
0013 #include "st-nci.h"
0014 
0015 #define DRIVER_DESC "NCI NFC driver for ST_NCI"
0016 
0017 #define ST_NCI1_X_PROPRIETARY_ISO15693 0x83
0018 
0019 static int st_nci_init(struct nci_dev *ndev)
0020 {
0021     struct nci_mode_set_cmd cmd;
0022 
0023     cmd.cmd_type = ST_NCI_SET_NFC_MODE;
0024     cmd.mode = 1;
0025 
0026     return nci_prop_cmd(ndev, ST_NCI_CORE_PROP,
0027             sizeof(struct nci_mode_set_cmd), (__u8 *)&cmd);
0028 }
0029 
0030 static int st_nci_open(struct nci_dev *ndev)
0031 {
0032     struct st_nci_info *info = nci_get_drvdata(ndev);
0033     int r;
0034 
0035     if (test_and_set_bit(ST_NCI_RUNNING, &info->flags))
0036         return 0;
0037 
0038     r = ndlc_open(info->ndlc);
0039     if (r)
0040         clear_bit(ST_NCI_RUNNING, &info->flags);
0041 
0042     return r;
0043 }
0044 
0045 static int st_nci_close(struct nci_dev *ndev)
0046 {
0047     struct st_nci_info *info = nci_get_drvdata(ndev);
0048 
0049     if (!test_bit(ST_NCI_RUNNING, &info->flags))
0050         return 0;
0051 
0052     ndlc_close(info->ndlc);
0053 
0054     clear_bit(ST_NCI_RUNNING, &info->flags);
0055 
0056     return 0;
0057 }
0058 
0059 static int st_nci_send(struct nci_dev *ndev, struct sk_buff *skb)
0060 {
0061     struct st_nci_info *info = nci_get_drvdata(ndev);
0062 
0063     skb->dev = (void *)ndev;
0064 
0065     if (!test_bit(ST_NCI_RUNNING, &info->flags))
0066         return -EBUSY;
0067 
0068     return ndlc_send(info->ndlc, skb);
0069 }
0070 
0071 static __u32 st_nci_get_rfprotocol(struct nci_dev *ndev,
0072                      __u8 rf_protocol)
0073 {
0074     return rf_protocol == ST_NCI1_X_PROPRIETARY_ISO15693 ?
0075         NFC_PROTO_ISO15693_MASK : 0;
0076 }
0077 
0078 static int st_nci_prop_rsp_packet(struct nci_dev *ndev,
0079                     struct sk_buff *skb)
0080 {
0081     __u8 status = skb->data[0];
0082 
0083     nci_req_complete(ndev, status);
0084     return 0;
0085 }
0086 
0087 static const struct nci_driver_ops st_nci_prop_ops[] = {
0088     {
0089         .opcode = nci_opcode_pack(NCI_GID_PROPRIETARY,
0090                       ST_NCI_CORE_PROP),
0091         .rsp = st_nci_prop_rsp_packet,
0092     },
0093 };
0094 
0095 static const struct nci_ops st_nci_ops = {
0096     .init = st_nci_init,
0097     .open = st_nci_open,
0098     .close = st_nci_close,
0099     .send = st_nci_send,
0100     .get_rfprotocol = st_nci_get_rfprotocol,
0101     .discover_se = st_nci_discover_se,
0102     .enable_se = st_nci_enable_se,
0103     .disable_se = st_nci_disable_se,
0104     .se_io = st_nci_se_io,
0105     .hci_load_session = st_nci_hci_load_session,
0106     .hci_event_received = st_nci_hci_event_received,
0107     .hci_cmd_received = st_nci_hci_cmd_received,
0108     .prop_ops = st_nci_prop_ops,
0109     .n_prop_ops = ARRAY_SIZE(st_nci_prop_ops),
0110 };
0111 
0112 int st_nci_probe(struct llt_ndlc *ndlc, int phy_headroom,
0113          int phy_tailroom, struct st_nci_se_status *se_status)
0114 {
0115     struct st_nci_info *info;
0116     int r;
0117     u32 protocols;
0118 
0119     info = devm_kzalloc(ndlc->dev,
0120             sizeof(struct st_nci_info), GFP_KERNEL);
0121     if (!info)
0122         return -ENOMEM;
0123 
0124     protocols = NFC_PROTO_JEWEL_MASK
0125         | NFC_PROTO_MIFARE_MASK
0126         | NFC_PROTO_FELICA_MASK
0127         | NFC_PROTO_ISO14443_MASK
0128         | NFC_PROTO_ISO14443_B_MASK
0129         | NFC_PROTO_ISO15693_MASK
0130         | NFC_PROTO_NFC_DEP_MASK;
0131 
0132     BUILD_BUG_ON(ARRAY_SIZE(st_nci_prop_ops) > NCI_MAX_PROPRIETARY_CMD);
0133     ndlc->ndev = nci_allocate_device(&st_nci_ops, protocols,
0134                     phy_headroom, phy_tailroom);
0135     if (!ndlc->ndev) {
0136         pr_err("Cannot allocate nfc ndev\n");
0137         return -ENOMEM;
0138     }
0139     info->ndlc = ndlc;
0140 
0141     nci_set_drvdata(ndlc->ndev, info);
0142 
0143     r = st_nci_vendor_cmds_init(ndlc->ndev);
0144     if (r) {
0145         pr_err("Cannot register proprietary vendor cmds\n");
0146         goto err_reg_dev;
0147     }
0148 
0149     r = nci_register_device(ndlc->ndev);
0150     if (r) {
0151         pr_err("Cannot register nfc device to nci core\n");
0152         goto err_reg_dev;
0153     }
0154 
0155     return st_nci_se_init(ndlc->ndev, se_status);
0156 
0157 err_reg_dev:
0158     nci_free_device(ndlc->ndev);
0159     return r;
0160 }
0161 EXPORT_SYMBOL_GPL(st_nci_probe);
0162 
0163 void st_nci_remove(struct nci_dev *ndev)
0164 {
0165     struct st_nci_info *info = nci_get_drvdata(ndev);
0166 
0167     ndlc_close(info->ndlc);
0168 
0169     nci_unregister_device(ndev);
0170     nci_free_device(ndev);
0171 }
0172 EXPORT_SYMBOL_GPL(st_nci_remove);
0173 
0174 MODULE_LICENSE("GPL");
0175 MODULE_DESCRIPTION(DRIVER_DESC);