Example #1
0
static int nfcwilink_get_bts_file_name(struct nfcwilink *drv, char *file_name)
{
	struct nci_vs_nfcc_info_cmd *cmd;
	struct sk_buff *skb;
	unsigned long comp_ret;
	int rc;

	nfc_dev_dbg(&drv->pdev->dev, "get_bts_file_name entry");

	skb = nfcwilink_skb_alloc(sizeof(struct nci_vs_nfcc_info_cmd),
					GFP_KERNEL);
	if (!skb) {
		nfc_dev_err(&drv->pdev->dev,
				"no memory for nci_vs_nfcc_info_cmd");
		return -ENOMEM;
	}

	cmd = (struct nci_vs_nfcc_info_cmd *)
			skb_put(skb, sizeof(struct nci_vs_nfcc_info_cmd));
	cmd->gid = NCI_VS_NFCC_INFO_CMD_GID;
	cmd->oid = NCI_VS_NFCC_INFO_CMD_OID;
	cmd->plen = 0;

	drv->nfcc_info.plen = 0;

	rc = nfcwilink_send(drv->ndev, skb);
	if (rc)
		return rc;

	comp_ret = wait_for_completion_timeout(&drv->completed,
				msecs_to_jiffies(NFCWILINK_CMD_TIMEOUT));
	nfc_dev_dbg(&drv->pdev->dev, "wait_for_completion_timeout returned %ld",
			comp_ret);
	if (comp_ret == 0) {
		nfc_dev_err(&drv->pdev->dev,
				"timeout on wait_for_completion_timeout");
		return -ETIMEDOUT;
	}

	nfc_dev_dbg(&drv->pdev->dev, "nci_vs_nfcc_info_rsp: plen %d, status %d",
			drv->nfcc_info.plen,
			drv->nfcc_info.status);

	if ((drv->nfcc_info.plen != 5) || (drv->nfcc_info.status != 0)) {
		nfc_dev_err(&drv->pdev->dev,
				"invalid nci_vs_nfcc_info_rsp");
		return -EINVAL;
	}

	snprintf(file_name, BTS_FILE_NAME_MAX_SIZE,
			"TINfcInit_%d.%d.%d.%d.bts",
			drv->nfcc_info.hw_id,
			drv->nfcc_info.sw_ver_x,
			drv->nfcc_info.sw_ver_z,
			drv->nfcc_info.patch_id);

	nfc_dev_info(&drv->pdev->dev, "nfcwilink FW file name: %s", file_name);

	return 0;
}
static int nfcwilink_send_bts_cmd(struct nfcwilink *drv, __u8 *data, int len)
{
	struct nfcwilink_hdr *hdr = (struct nfcwilink_hdr *)data;
	struct sk_buff *skb;
	unsigned long comp_ret;
	int rc;

	nfc_dev_dbg(&drv->pdev->dev, "send_bts_cmd entry");

	/* verify valid cmd for the NFC channel */
	if ((len <= sizeof(struct nfcwilink_hdr)) ||
		(len > BTS_FILE_CMD_MAX_LEN) ||
		(hdr->chnl != NFCWILINK_CHNL) ||
		(hdr->opcode != NFCWILINK_OPCODE)) {
		nfc_dev_err(&drv->pdev->dev,
			"ignoring invalid bts cmd, len %d, chnl %d, opcode %d",
			len, hdr->chnl, hdr->opcode);
		return 0;
	}

	/* remove the ST header */
	len -= sizeof(struct nfcwilink_hdr);
	data += sizeof(struct nfcwilink_hdr);

	skb = nfcwilink_skb_alloc(len, GFP_KERNEL);
	if (!skb) {
		nfc_dev_err(&drv->pdev->dev, "no memory for bts cmd");
		return -ENOMEM;
	}

	skb->dev = (void *)drv->ndev;

	memcpy(skb_put(skb, len), data, len);

	rc = nfcwilink_send(skb);
	if (rc)
		return rc;

	comp_ret = wait_for_completion_timeout(&drv->completed,
				msecs_to_jiffies(NFCWILINK_CMD_TIMEOUT));
	nfc_dev_dbg(&drv->pdev->dev, "wait_for_completion_timeout returned %ld",
			comp_ret);
	if (comp_ret == 0) {
		nfc_dev_err(&drv->pdev->dev,
				"timeout on wait_for_completion_timeout");
		return -ETIMEDOUT;
	}

	return 0;
}