static int nfcwilink_send(struct sk_buff *skb)
{
	struct nci_dev *ndev = (struct nci_dev *)skb->dev;
	struct nfcwilink *drv = nci_get_drvdata(ndev);
	struct nfcwilink_hdr hdr = {NFCWILINK_CHNL, NFCWILINK_OPCODE, 0x0000};
	long len;

	nfc_dev_dbg(&drv->pdev->dev, "send entry, len %d", skb->len);

	if (!test_bit(NFCWILINK_RUNNING, &drv->flags)) {
		kfree_skb(skb);
		return -EINVAL;
	}

	hdr.len = cpu_to_le16(skb->len);
	memcpy(skb_push(skb, NFCWILINK_HDR_LEN), &hdr, NFCWILINK_HDR_LEN);

	/* Insert skb to shared transport layer's transmit queue.
	 * Freeing skb memory is taken care in shared transport layer,
	 * so don't free skb memory here.
	 */
	len = drv->st_write(skb);
	if (len < 0) {
		kfree_skb(skb);
		nfc_dev_err(&drv->pdev->dev, "st_write failed %ld", len);
		return -EFAULT;
	}

	return 0;
}
Пример #2
0
void st21nfcb_nci_remove(struct nci_dev *ndev)
{
	struct st21nfcb_nci_info *info = nci_get_drvdata(ndev);

	nci_unregister_device(ndev);
	nci_free_device(ndev);
	kfree(info);
}
Пример #3
0
int st_nci_vendor_cmds_init(struct nci_dev *ndev)
{
	struct st_nci_info *info = nci_get_drvdata(ndev);

	init_completion(&info->vendor_info.req_completion);
	return nfc_set_vendor_cmds(ndev->nfc_dev, st_nci_vendor_cmds,
				   sizeof(st_nci_vendor_cmds));
}
Пример #4
0
void st_nci_remove(struct nci_dev *ndev)
{
	struct st_nci_info *info = nci_get_drvdata(ndev);

	ndlc_close(info->ndlc);

	nci_unregister_device(ndev);
	nci_free_device(ndev);
}
Пример #5
0
static int st21nfcb_nci_close(struct nci_dev *ndev)
{
	struct st21nfcb_nci_info *info = nci_get_drvdata(ndev);

	if (!test_and_clear_bit(ST21NFCB_NCI_RUNNING, &info->flags))
		return 0;

	ndlc_close(info->ndlc);

	return 0;
}
Пример #6
0
static int st21nfcb_nci_send(struct nci_dev *ndev, struct sk_buff *skb)
{
	struct st21nfcb_nci_info *info = nci_get_drvdata(ndev);

	skb->dev = (void *)ndev;

	if (!test_bit(ST21NFCB_NCI_RUNNING, &info->flags))
		return -EBUSY;

	return ndlc_send(info->ndlc, skb);
}
Пример #7
0
static int nfcmrvl_nci_close(struct nci_dev *ndev)
{
	struct nfcmrvl_private *priv = nci_get_drvdata(ndev);

	if (!test_and_clear_bit(NFCMRVL_NCI_RUNNING, &priv->flags))
		return 0;

	priv->if_ops->nci_close(priv);

	return 0;
}
Пример #8
0
static int nfcmrvl_nci_send(struct nci_dev *ndev, struct sk_buff *skb)
{
	struct nfcmrvl_private *priv = nci_get_drvdata(ndev);

	nfc_info(priv->dev, "send entry, len %d\n", skb->len);

	skb->dev = (void *)ndev;

	if (!test_bit(NFCMRVL_NCI_RUNNING, &priv->flags))
		return -EBUSY;

	return priv->if_ops->nci_send(priv, skb);
}
Пример #9
0
static int st_nci_hci_loopback(struct nfc_dev *dev, void *data,
			       size_t data_len)
{
	int r;
	struct sk_buff *msg;
	struct nci_dev *ndev = nfc_get_drvdata(dev);
	struct st_nci_info *info = nci_get_drvdata(ndev);

	if (data_len <= 0)
		return -EPROTO;

	reinit_completion(&info->vendor_info.req_completion);
	info->vendor_info.rx_skb = NULL;

	r = nci_hci_send_event(ndev, NCI_HCI_LOOPBACK_GATE,
			       ST_NCI_EVT_POST_DATA, data, data_len);
	if (r != data_len) {
		r = -EPROTO;
		goto exit;
	}

	wait_for_completion_interruptible(&info->vendor_info.req_completion);

	if (!info->vendor_info.rx_skb ||
	    info->vendor_info.rx_skb->len != data_len) {
		r = -EPROTO;
		goto exit;
	}

	msg = nfc_vendor_cmd_alloc_reply_skb(ndev->nfc_dev,
					ST_NCI_VENDOR_OUI,
					HCI_LOOPBACK,
					info->vendor_info.rx_skb->len);
	if (!msg) {
		r = -ENOMEM;
		goto free_skb;
	}

	if (nla_put(msg, NFC_ATTR_VENDOR_DATA, info->vendor_info.rx_skb->len,
		    info->vendor_info.rx_skb->data)) {
		kfree_skb(msg);
		r = -ENOBUFS;
		goto free_skb;
	}

	r = nfc_vendor_cmd_reply(msg);
free_skb:
	kfree_skb(info->vendor_info.rx_skb);
exit:
	return r;
}
Пример #10
0
static int st21nfcb_nci_open(struct nci_dev *ndev)
{
	struct st21nfcb_nci_info *info = nci_get_drvdata(ndev);
	int r;

	if (test_and_set_bit(ST21NFCB_NCI_RUNNING, &info->flags))
		return 0;

	r = ndlc_open(info->ndlc);
	if (r)
		clear_bit(ST21NFCB_NCI_RUNNING, &info->flags);

	return r;
}
Пример #11
0
void st_nci_hci_loopback_event_received(struct nci_dev *ndev, u8 event,
					struct sk_buff *skb)
{
	struct st_nci_info *info = nci_get_drvdata(ndev);

	switch (event) {
	case ST_NCI_EVT_POST_DATA:
		info->vendor_info.rx_skb = skb;
	break;
	default:
		nfc_err(&ndev->nfc_dev->dev, "Unexpected event on loopback gate\n");
	}
	complete(&info->vendor_info.req_completion);
}
Пример #12
0
static int nfcmrvl_nci_open(struct nci_dev *ndev)
{
	struct nfcmrvl_private *priv = nci_get_drvdata(ndev);
	int err;

	if (test_and_set_bit(NFCMRVL_NCI_RUNNING, &priv->flags))
		return 0;

	err = priv->if_ops->nci_open(priv);

	if (err)
		clear_bit(NFCMRVL_NCI_RUNNING, &priv->flags);

	return err;
}
Пример #13
0
static int nfcwilink_close(struct nci_dev *ndev)
{
	struct nfcwilink *drv = nci_get_drvdata(ndev);
	int rc;

	if (!test_and_clear_bit(NFCWILINK_RUNNING, &drv->flags))
		return 0;

	rc = st_unregister(&nfcwilink_proto);
	if (rc)
		nfc_err(&drv->pdev->dev, "st_unregister failed %d\n", rc);

	drv->st_write = NULL;

	return rc;
}
Пример #14
0
static void nfcmrvl_tx_complete(struct urb *urb)
{
	struct sk_buff *skb = urb->context;
	struct nci_dev *ndev = (struct nci_dev *)skb->dev;
	struct nfcmrvl_private *priv = nci_get_drvdata(ndev);
	struct nfcmrvl_usb_drv_data *drv_data = priv->drv_data;

	nfc_info(priv->dev, "urb %p status %d count %d",
		 urb, urb->status, urb->actual_length);

	spin_lock(&drv_data->txlock);
	drv_data->tx_in_flight--;
	spin_unlock(&drv_data->txlock);

	kfree(urb->setup_packet);
	kfree_skb(skb);
}
Пример #15
0
static int st_nci_factory_mode(struct nfc_dev *dev, void *data,
			       size_t data_len)
{
	struct nci_dev *ndev = nfc_get_drvdata(dev);
	struct st_nci_info *info = nci_get_drvdata(ndev);

	if (data_len != 1)
		return -EINVAL;

	pr_debug("factory mode: %x\n", ((u8 *)data)[0]);

	switch (((u8 *)data)[0]) {
	case ST_NCI_FACTORY_MODE_ON:
		test_and_set_bit(ST_NCI_FACTORY_MODE, &info->flags);
	break;
	case ST_NCI_FACTORY_MODE_OFF:
		clear_bit(ST_NCI_FACTORY_MODE, &info->flags);
	break;
	default:
		return -EINVAL;
	}

	return 0;
}
Пример #16
0
static irqreturn_t nxp_nci_i2c_irq_thread_fn(int irq, void *phy_id)
{
	struct nxp_nci_i2c_phy *phy = phy_id;
	struct i2c_client *client;
	struct nxp_nci_info *info;

	struct sk_buff *skb = NULL;
	int r = 0;

	if (!phy || !phy->ndev)
		goto exit_irq_none;

	client = phy->i2c_dev;

	if (!client || irq != client->irq)
		goto exit_irq_none;

	info = nci_get_drvdata(phy->ndev);

	if (!info)
		goto exit_irq_none;

	mutex_lock(&info->info_lock);

	if (phy->hard_fault != 0)
		goto exit_irq_handled;

	switch (info->mode) {
	case NXP_NCI_MODE_NCI:
		r = nxp_nci_i2c_nci_read(phy, &skb);
		break;
	case NXP_NCI_MODE_FW:
		r = nxp_nci_i2c_fw_read(phy, &skb);
		break;
	case NXP_NCI_MODE_COLD:
		r = -EREMOTEIO;
		break;
	}

	if (r == -EREMOTEIO) {
		phy->hard_fault = r;
		skb = NULL;
	} else if (r < 0) {
		nfc_err(&client->dev, "Read failed with error %d\n", r);
		goto exit_irq_handled;
	}

	switch (info->mode) {
	case NXP_NCI_MODE_NCI:
		nci_recv_frame(phy->ndev, skb);
		break;
	case NXP_NCI_MODE_FW:
		nxp_nci_fw_recv_frame(phy->ndev, skb);
		break;
	case NXP_NCI_MODE_COLD:
		break;
	}

exit_irq_handled:
	mutex_unlock(&info->info_lock);
	return IRQ_HANDLED;
exit_irq_none:
	WARN_ON_ONCE(1);
	return IRQ_NONE;
}
static int nfcwilink_open(struct nci_dev *ndev)
{
	struct nfcwilink *drv = nci_get_drvdata(ndev);
	unsigned long comp_ret;
	int rc;

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

	if (test_and_set_bit(NFCWILINK_RUNNING, &drv->flags)) {
		rc = -EBUSY;
		goto exit;
	}

	nfcwilink_proto.priv_data = drv;

	init_completion(&drv->completed);
	drv->st_register_cb_status = -EINPROGRESS;

	rc = st_register(&nfcwilink_proto);
	if (rc < 0) {
		if (rc == -EINPROGRESS) {
			comp_ret = wait_for_completion_timeout(
			&drv->completed,
			msecs_to_jiffies(NFCWILINK_REGISTER_TIMEOUT));

			nfc_dev_dbg(&drv->pdev->dev,
			"wait_for_completion_timeout returned %ld",
			comp_ret);

			if (comp_ret == 0) {
				/* timeout */
				rc = -ETIMEDOUT;
				goto clear_exit;
			} else if (drv->st_register_cb_status != 0) {
				rc = drv->st_register_cb_status;
				nfc_dev_err(&drv->pdev->dev,
				"st_register_cb failed %d", rc);
				goto clear_exit;
			}
		} else {
			nfc_dev_err(&drv->pdev->dev,
				"st_register failed %d", rc);
			goto clear_exit;
		}
	}

	/* st_register MUST fill the write callback */
	BUG_ON(nfcwilink_proto.write == NULL);
	drv->st_write = nfcwilink_proto.write;

	if (nfcwilink_download_fw(drv)) {
		nfc_dev_err(&drv->pdev->dev, "nfcwilink_download_fw failed %d",
				rc);
		/* open should succeed, even if the FW download failed */
	}

	goto exit;

clear_exit:
	clear_bit(NFCWILINK_RUNNING, &drv->flags);

exit:
	return rc;
}