示例#1
0
文件: core.c 项目: AllenDou/linux
static int nci_transceive(struct nfc_dev *nfc_dev, struct nfc_target *target,
			  struct sk_buff *skb,
			  data_exchange_cb_t cb, void *cb_context)
{
	struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
	int rc;

	pr_debug("target_idx %d, len %d\n", target->idx, skb->len);

	if (!ndev->target_active_prot) {
		pr_err("unable to exchange data, no active target\n");
		return -EINVAL;
	}

	if (test_and_set_bit(NCI_DATA_EXCHANGE, &ndev->flags))
		return -EBUSY;

	/* store cb and context to be used on receiving data */
	ndev->data_exchange_cb = cb;
	ndev->data_exchange_cb_context = cb_context;

	rc = nci_send_data(ndev, NCI_STATIC_RF_CONN_ID, skb);
	if (rc)
		clear_bit(NCI_DATA_EXCHANGE, &ndev->flags);

	return rc;
}
示例#2
0
文件: hci.c 项目: branderxero/linux
/* Fragment HCI data over NCI packet.
 * NFC Forum NCI 10.2.2 Data Exchange:
 * The payload of the Data Packets sent on the Logical Connection SHALL be
 * valid HCP packets, as defined within [ETSI_102622]. Each Data Packet SHALL
 * contain a single HCP packet. NCI Segmentation and Reassembly SHALL NOT be
 * applied to Data Messages in either direction. The HCI fragmentation mechanism
 * is used if required.
 */
static int nci_hci_send_data(struct nci_dev *ndev, u8 pipe,
			     const u8 data_type, const u8 *data,
			     size_t data_len)
{
	struct nci_conn_info    *conn_info;
	struct sk_buff *skb;
	int len, i, r;
	u8 cb = pipe;

	conn_info = ndev->hci_dev->conn_info;
	if (!conn_info)
		return -EPROTO;

	i = 0;
	skb = nci_skb_alloc(ndev, conn_info->max_pkt_payload_len +
			    NCI_DATA_HDR_SIZE, GFP_KERNEL);
	if (!skb)
		return -ENOMEM;

	skb_reserve(skb, NCI_DATA_HDR_SIZE + 2);
	*skb_push(skb, 1) = data_type;

	do {
		len = conn_info->max_pkt_payload_len;

		/* If last packet add NCI_HFP_NO_CHAINING */
		if (i + conn_info->max_pkt_payload_len -
		    (skb->len + 1) >= data_len) {
			cb |= NCI_HFP_NO_CHAINING;
			len = data_len - i;
		} else {
			len = conn_info->max_pkt_payload_len - skb->len - 1;
		}

		*skb_push(skb, 1) = cb;

		if (len > 0)
			memcpy(skb_put(skb, len), data + i, len);

		r = nci_send_data(ndev, conn_info->conn_id, skb);
		if (r < 0)
			return r;

		i += len;

		if (i < data_len) {
			skb = nci_skb_alloc(ndev,
					    conn_info->max_pkt_payload_len +
					    NCI_DATA_HDR_SIZE, GFP_KERNEL);
			if (!skb)
				return -ENOMEM;

			skb_reserve(skb, NCI_DATA_HDR_SIZE + 1);
		}
	} while (i < data_len);

	return i;
}
示例#3
0
static int nci_data_exchange(struct nfc_dev *nfc_dev, __u32 target_idx,
						struct sk_buff *skb,
						data_exchange_cb_t cb,
						void *cb_context)
{
	struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);

	nfc_dbg("entry, target_idx %d, len %d", target_idx, skb->len);

	if (!ndev->target_active_prot) {
		nfc_err("unable to exchange data, no active target");
		return -EINVAL;
	}

	/* store cb and context to be used on receiving data */
	ndev->data_exchange_cb = cb;
	ndev->data_exchange_cb_context = cb_context;

	return nci_send_data(ndev, ndev->conn_id, skb);
}