Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (c) 2013, Intel Corporation.
0004  *
0005  * MEI Library for mei bus nfc device access
0006  */
0007 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0008 
0009 #include <linux/module.h>
0010 #include <linux/slab.h>
0011 #include <linux/nfc.h>
0012 
0013 #include "mei_phy.h"
0014 
0015 struct mei_nfc_hdr {
0016     u8 cmd;
0017     u8 status;
0018     u16 req_id;
0019     u32 reserved;
0020     u16 data_size;
0021 } __packed;
0022 
0023 struct mei_nfc_cmd {
0024     struct mei_nfc_hdr hdr;
0025     u8 sub_command;
0026     u8 data[];
0027 } __packed;
0028 
0029 struct mei_nfc_reply {
0030     struct mei_nfc_hdr hdr;
0031     u8 sub_command;
0032     u8 reply_status;
0033     u8 data[];
0034 } __packed;
0035 
0036 struct mei_nfc_if_version {
0037     u8 radio_version_sw[3];
0038     u8 reserved[3];
0039     u8 radio_version_hw[3];
0040     u8 i2c_addr;
0041     u8 fw_ivn;
0042     u8 vendor_id;
0043     u8 radio_type;
0044 } __packed;
0045 
0046 struct mei_nfc_connect {
0047     u8 fw_ivn;
0048     u8 vendor_id;
0049 } __packed;
0050 
0051 struct mei_nfc_connect_resp {
0052     u8 fw_ivn;
0053     u8 vendor_id;
0054     u16 me_major;
0055     u16 me_minor;
0056     u16 me_hotfix;
0057     u16 me_build;
0058 } __packed;
0059 
0060 
0061 #define MEI_NFC_CMD_MAINTENANCE 0x00
0062 #define MEI_NFC_CMD_HCI_SEND 0x01
0063 #define MEI_NFC_CMD_HCI_RECV 0x02
0064 
0065 #define MEI_NFC_SUBCMD_CONNECT    0x00
0066 #define MEI_NFC_SUBCMD_IF_VERSION 0x01
0067 
0068 #define MEI_NFC_MAX_READ (MEI_NFC_HEADER_SIZE + MEI_NFC_MAX_HCI_PAYLOAD)
0069 
0070 #define MEI_DUMP_SKB_IN(info, skb)              \
0071 do {                                \
0072     pr_debug("%s:\n", info);                \
0073     print_hex_dump_debug("mei in : ", DUMP_PREFIX_OFFSET,   \
0074             16, 1, (skb)->data, (skb)->len, false); \
0075 } while (0)
0076 
0077 #define MEI_DUMP_SKB_OUT(info, skb)             \
0078 do {                                \
0079     pr_debug("%s:\n", info);                \
0080     print_hex_dump_debug("mei out: ", DUMP_PREFIX_OFFSET,   \
0081             16, 1, (skb)->data, (skb)->len, false); \
0082 } while (0)
0083 
0084 #define MEI_DUMP_NFC_HDR(info, _hdr)                                \
0085 do {                                                                \
0086     pr_debug("%s:\n", info);                                    \
0087     pr_debug("cmd=%02d status=%d req_id=%d rsvd=%d size=%d\n",  \
0088          (_hdr)->cmd, (_hdr)->status, (_hdr)->req_id,       \
0089          (_hdr)->reserved, (_hdr)->data_size);              \
0090 } while (0)
0091 
0092 static int mei_nfc_if_version(struct nfc_mei_phy *phy)
0093 {
0094 
0095     struct mei_nfc_cmd cmd;
0096     struct mei_nfc_reply *reply = NULL;
0097     struct mei_nfc_if_version *version;
0098     size_t if_version_length;
0099     int bytes_recv, r;
0100 
0101     memset(&cmd, 0, sizeof(struct mei_nfc_cmd));
0102     cmd.hdr.cmd = MEI_NFC_CMD_MAINTENANCE;
0103     cmd.hdr.data_size = 1;
0104     cmd.sub_command = MEI_NFC_SUBCMD_IF_VERSION;
0105 
0106     MEI_DUMP_NFC_HDR("version", &cmd.hdr);
0107     r = mei_cldev_send(phy->cldev, (u8 *)&cmd, sizeof(struct mei_nfc_cmd));
0108     if (r < 0) {
0109         pr_err("Could not send IF version cmd\n");
0110         return r;
0111     }
0112 
0113     /* to be sure on the stack we alloc memory */
0114     if_version_length = sizeof(struct mei_nfc_reply) +
0115         sizeof(struct mei_nfc_if_version);
0116 
0117     reply = kzalloc(if_version_length, GFP_KERNEL);
0118     if (!reply)
0119         return -ENOMEM;
0120 
0121     bytes_recv = mei_cldev_recv(phy->cldev, (u8 *)reply, if_version_length);
0122     if (bytes_recv < 0 || bytes_recv < if_version_length) {
0123         pr_err("Could not read IF version\n");
0124         r = -EIO;
0125         goto err;
0126     }
0127 
0128     version = (struct mei_nfc_if_version *)reply->data;
0129 
0130     phy->fw_ivn = version->fw_ivn;
0131     phy->vendor_id = version->vendor_id;
0132     phy->radio_type = version->radio_type;
0133 
0134 err:
0135     kfree(reply);
0136     return r;
0137 }
0138 
0139 static int mei_nfc_connect(struct nfc_mei_phy *phy)
0140 {
0141     struct mei_nfc_cmd *cmd, *reply;
0142     struct mei_nfc_connect *connect;
0143     struct mei_nfc_connect_resp *connect_resp;
0144     size_t connect_length, connect_resp_length;
0145     int bytes_recv, r;
0146 
0147     connect_length = sizeof(struct mei_nfc_cmd) +
0148             sizeof(struct mei_nfc_connect);
0149 
0150     connect_resp_length = sizeof(struct mei_nfc_cmd) +
0151             sizeof(struct mei_nfc_connect_resp);
0152 
0153     cmd = kzalloc(connect_length, GFP_KERNEL);
0154     if (!cmd)
0155         return -ENOMEM;
0156     connect = (struct mei_nfc_connect *)cmd->data;
0157 
0158     reply = kzalloc(connect_resp_length, GFP_KERNEL);
0159     if (!reply) {
0160         kfree(cmd);
0161         return -ENOMEM;
0162     }
0163 
0164     connect_resp = (struct mei_nfc_connect_resp *)reply->data;
0165 
0166     cmd->hdr.cmd = MEI_NFC_CMD_MAINTENANCE;
0167     cmd->hdr.data_size = 3;
0168     cmd->sub_command = MEI_NFC_SUBCMD_CONNECT;
0169     connect->fw_ivn = phy->fw_ivn;
0170     connect->vendor_id = phy->vendor_id;
0171 
0172     MEI_DUMP_NFC_HDR("connect request", &cmd->hdr);
0173     r = mei_cldev_send(phy->cldev, (u8 *)cmd, connect_length);
0174     if (r < 0) {
0175         pr_err("Could not send connect cmd %d\n", r);
0176         goto err;
0177     }
0178 
0179     bytes_recv = mei_cldev_recv(phy->cldev, (u8 *)reply,
0180                     connect_resp_length);
0181     if (bytes_recv < 0) {
0182         r = bytes_recv;
0183         pr_err("Could not read connect response %d\n", r);
0184         goto err;
0185     }
0186 
0187     MEI_DUMP_NFC_HDR("connect reply", &reply->hdr);
0188 
0189     pr_info("IVN 0x%x Vendor ID 0x%x\n",
0190          connect_resp->fw_ivn, connect_resp->vendor_id);
0191 
0192     pr_info("ME FW %d.%d.%d.%d\n",
0193         connect_resp->me_major, connect_resp->me_minor,
0194         connect_resp->me_hotfix, connect_resp->me_build);
0195 
0196     r = 0;
0197 
0198 err:
0199     kfree(reply);
0200     kfree(cmd);
0201 
0202     return r;
0203 }
0204 
0205 static int mei_nfc_send(struct nfc_mei_phy *phy, const u8 *buf, size_t length)
0206 {
0207     struct mei_nfc_hdr *hdr;
0208     u8 *mei_buf;
0209     int err;
0210 
0211     err = -ENOMEM;
0212     mei_buf = kzalloc(length + MEI_NFC_HEADER_SIZE, GFP_KERNEL);
0213     if (!mei_buf)
0214         goto out;
0215 
0216     hdr = (struct mei_nfc_hdr *)mei_buf;
0217     hdr->cmd = MEI_NFC_CMD_HCI_SEND;
0218     hdr->status = 0;
0219     hdr->req_id = phy->req_id;
0220     hdr->reserved = 0;
0221     hdr->data_size = length;
0222 
0223     MEI_DUMP_NFC_HDR("send", hdr);
0224 
0225     memcpy(mei_buf + MEI_NFC_HEADER_SIZE, buf, length);
0226     err = mei_cldev_send(phy->cldev, mei_buf, length + MEI_NFC_HEADER_SIZE);
0227     if (err < 0)
0228         goto out;
0229 
0230     if (!wait_event_interruptible_timeout(phy->send_wq,
0231                 phy->recv_req_id == phy->req_id, HZ)) {
0232         pr_err("NFC MEI command timeout\n");
0233         err = -ETIME;
0234     } else {
0235         phy->req_id++;
0236     }
0237 out:
0238     kfree(mei_buf);
0239     return err;
0240 }
0241 
0242 /*
0243  * Writing a frame must not return the number of written bytes.
0244  * It must return either zero for success, or <0 for error.
0245  * In addition, it must not alter the skb
0246  */
0247 static int nfc_mei_phy_write(void *phy_id, struct sk_buff *skb)
0248 {
0249     struct nfc_mei_phy *phy = phy_id;
0250     int r;
0251 
0252     MEI_DUMP_SKB_OUT("mei frame sent", skb);
0253 
0254     r = mei_nfc_send(phy, skb->data, skb->len);
0255     if (r > 0)
0256         r = 0;
0257 
0258     return r;
0259 }
0260 
0261 static int mei_nfc_recv(struct nfc_mei_phy *phy, u8 *buf, size_t length)
0262 {
0263     struct mei_nfc_hdr *hdr;
0264     int received_length;
0265 
0266     received_length = mei_cldev_recv(phy->cldev, buf, length);
0267     if (received_length < 0)
0268         return received_length;
0269 
0270     hdr = (struct mei_nfc_hdr *) buf;
0271 
0272     MEI_DUMP_NFC_HDR("receive", hdr);
0273     if (hdr->cmd == MEI_NFC_CMD_HCI_SEND) {
0274         phy->recv_req_id = hdr->req_id;
0275         wake_up(&phy->send_wq);
0276 
0277         return 0;
0278     }
0279 
0280     return received_length;
0281 }
0282 
0283 
0284 static void nfc_mei_rx_cb(struct mei_cl_device *cldev)
0285 {
0286     struct nfc_mei_phy *phy = mei_cldev_get_drvdata(cldev);
0287     struct sk_buff *skb;
0288     int reply_size;
0289 
0290     if (!phy)
0291         return;
0292 
0293     if (phy->hard_fault != 0)
0294         return;
0295 
0296     skb = alloc_skb(MEI_NFC_MAX_READ, GFP_KERNEL);
0297     if (!skb)
0298         return;
0299 
0300     reply_size = mei_nfc_recv(phy, skb->data, MEI_NFC_MAX_READ);
0301     if (reply_size < MEI_NFC_HEADER_SIZE) {
0302         kfree_skb(skb);
0303         return;
0304     }
0305 
0306     skb_put(skb, reply_size);
0307     skb_pull(skb, MEI_NFC_HEADER_SIZE);
0308 
0309     MEI_DUMP_SKB_IN("mei frame read", skb);
0310 
0311     nfc_hci_recv_frame(phy->hdev, skb);
0312 }
0313 
0314 static int nfc_mei_phy_enable(void *phy_id)
0315 {
0316     int r;
0317     struct nfc_mei_phy *phy = phy_id;
0318 
0319     if (phy->powered == 1)
0320         return 0;
0321 
0322     r = mei_cldev_enable(phy->cldev);
0323     if (r < 0) {
0324         pr_err("Could not enable device %d\n", r);
0325         return r;
0326     }
0327 
0328     r = mei_nfc_if_version(phy);
0329     if (r < 0) {
0330         pr_err("Could not enable device %d\n", r);
0331         goto err;
0332     }
0333 
0334     r = mei_nfc_connect(phy);
0335     if (r < 0) {
0336         pr_err("Could not connect to device %d\n", r);
0337         goto err;
0338     }
0339 
0340     r = mei_cldev_register_rx_cb(phy->cldev, nfc_mei_rx_cb);
0341     if (r) {
0342         pr_err("Event cb registration failed %d\n", r);
0343         goto err;
0344     }
0345 
0346     phy->powered = 1;
0347 
0348     return 0;
0349 
0350 err:
0351     phy->powered = 0;
0352     mei_cldev_disable(phy->cldev);
0353     return r;
0354 }
0355 
0356 static void nfc_mei_phy_disable(void *phy_id)
0357 {
0358     struct nfc_mei_phy *phy = phy_id;
0359 
0360     mei_cldev_disable(phy->cldev);
0361 
0362     phy->powered = 0;
0363 }
0364 
0365 const struct nfc_phy_ops mei_phy_ops = {
0366     .write = nfc_mei_phy_write,
0367     .enable = nfc_mei_phy_enable,
0368     .disable = nfc_mei_phy_disable,
0369 };
0370 EXPORT_SYMBOL_GPL(mei_phy_ops);
0371 
0372 struct nfc_mei_phy *nfc_mei_phy_alloc(struct mei_cl_device *cldev)
0373 {
0374     struct nfc_mei_phy *phy;
0375 
0376     phy = kzalloc(sizeof(struct nfc_mei_phy), GFP_KERNEL);
0377     if (!phy)
0378         return NULL;
0379 
0380     phy->cldev = cldev;
0381     init_waitqueue_head(&phy->send_wq);
0382     mei_cldev_set_drvdata(cldev, phy);
0383 
0384     return phy;
0385 }
0386 EXPORT_SYMBOL_GPL(nfc_mei_phy_alloc);
0387 
0388 void nfc_mei_phy_free(struct nfc_mei_phy *phy)
0389 {
0390     mei_cldev_disable(phy->cldev);
0391     kfree(phy);
0392 }
0393 EXPORT_SYMBOL_GPL(nfc_mei_phy_free);
0394 
0395 MODULE_LICENSE("GPL");
0396 MODULE_DESCRIPTION("mei bus NFC device interface");