Exemple #1
0
static void nci_cmd_work(struct work_struct *work)
{
	struct nci_dev *ndev = container_of(work, struct nci_dev, cmd_work);
	struct sk_buff *skb;

	pr_debug("cmd_cnt %d\n", atomic_read(&ndev->cmd_cnt));

	/* Send queued command */
	if (atomic_read(&ndev->cmd_cnt)) {
		skb = skb_dequeue(&ndev->cmd_q);
		if (!skb)
			return;

		atomic_dec(&ndev->cmd_cnt);

		pr_debug("NCI TX: MT=cmd, PBF=%d, GID=0x%x, OID=0x%x, plen=%d\n",
			 nci_pbf(skb->data),
			 nci_opcode_gid(nci_opcode(skb->data)),
			 nci_opcode_oid(nci_opcode(skb->data)),
			 nci_plen(skb->data));

		nci_send_frame(skb);

		mod_timer(&ndev->cmd_timer,
			  jiffies + msecs_to_jiffies(NCI_CMD_TIMEOUT));
	}
}
Exemple #2
0
void nci_ntf_packet(struct nci_dev *ndev, struct sk_buff *skb)
{
	__u16 ntf_opcode = nci_opcode(skb->data);

	nfc_dbg("NCI RX: MT=ntf, PBF=%d, GID=0x%x, OID=0x%x, plen=%d",
			nci_pbf(skb->data),
			nci_opcode_gid(ntf_opcode),
			nci_opcode_oid(ntf_opcode),
			nci_plen(skb->data));

	/* strip the nci control header */
	skb_pull(skb, NCI_CTRL_HDR_SIZE);

	switch (ntf_opcode) {
	case NCI_OP_CORE_CONN_CREDITS_NTF:
		nci_core_conn_credits_ntf_packet(ndev, skb);
		break;

	case NCI_OP_RF_INTF_ACTIVATED_NTF:
		nci_rf_intf_activated_ntf_packet(ndev, skb);
		break;

	case NCI_OP_RF_DEACTIVATE_NTF:
		nci_rf_deactivate_ntf_packet(ndev, skb);
		break;

	default:
		nfc_err("unknown ntf opcode 0x%x", ntf_opcode);
		break;
	}

	kfree_skb(skb);
}
Exemple #3
0
static void nci_tx_work(struct work_struct *work)
{
	struct nci_dev *ndev = container_of(work, struct nci_dev, tx_work);
	struct sk_buff *skb;

	pr_debug("credits_cnt %d\n", atomic_read(&ndev->credits_cnt));

	/* Send queued tx data */
	while (atomic_read(&ndev->credits_cnt)) {
		skb = skb_dequeue(&ndev->tx_q);
		if (!skb)
			return;

		/* Check if data flow control is used */
		if (atomic_read(&ndev->credits_cnt) !=
		    NCI_DATA_FLOW_CONTROL_NOT_USED)
			atomic_dec(&ndev->credits_cnt);

		pr_debug("NCI TX: MT=data, PBF=%d, conn_id=%d, plen=%d\n",
			 nci_pbf(skb->data),
			 nci_conn_id(skb->data),
			 nci_plen(skb->data));

		nci_send_frame(skb);

		mod_timer(&ndev->data_timer,
			  jiffies + msecs_to_jiffies(NCI_DATA_TIMEOUT));
	}
}
Exemple #4
0
/* Rx Data packet */
void nci_rx_data_packet(struct nci_dev *ndev, struct sk_buff *skb)
{
	__u8 pbf = nci_pbf(skb->data);
	__u8 status = 0;
	__u8 conn_id = nci_conn_id(skb->data);
	struct nci_conn_info    *conn_info;

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

	pr_debug("NCI RX: MT=data, PBF=%d, conn_id=%d, plen=%d\n",
		 nci_pbf(skb->data),
		 nci_conn_id(skb->data),
		 nci_plen(skb->data));

	conn_info = nci_get_conn_info_by_conn_id(ndev, nci_conn_id(skb->data));
	if (!conn_info)
		return;

	/* strip the nci data header */
	skb_pull(skb, NCI_DATA_HDR_SIZE);

	if (ndev->target_active_prot == NFC_PROTO_MIFARE ||
	    ndev->target_active_prot == NFC_PROTO_JEWEL ||
	    ndev->target_active_prot == NFC_PROTO_FELICA ||
	    ndev->target_active_prot == NFC_PROTO_ISO15693) {
		/* frame I/F => remove the status byte */
		pr_debug("frame I/F => remove the status byte\n");
		status = skb->data[skb->len - 1];
		skb_trim(skb, (skb->len - 1));
	}

	nci_add_rx_data_frag(ndev, skb, pbf, conn_id, nci_to_errno(status));
}
Exemple #5
0
/* -- Default recv_buf handler --
 *
 * This handler supposes that NCI frames are sent over UART link without any
 * framing. It reads NCI header, retrieve the packet size and once all packet
 * bytes are received it passes it to nci_uart driver for processing.
 */
static int nci_uart_default_recv_buf(struct nci_uart *nu, const u8 *data,
				     char *flags, int count)
{
	int chunk_len;

	if (!nu->ndev) {
		nfc_err(nu->tty->dev,
			"receive data from tty but no NCI dev is attached yet, drop buffer\n");
		return 0;
	}

	/* Decode all incoming data in packets
	 * and enqueue then for processing.
	 */
	while (count > 0) {
		/* If this is the first data of a packet, allocate a buffer */
		if (!nu->rx_skb) {
			nu->rx_packet_len = -1;
			nu->rx_skb = nci_skb_alloc(nu->ndev,
						   NCI_MAX_PACKET_SIZE,
						   GFP_KERNEL);
			if (!nu->rx_skb)
				return -ENOMEM;
		}

		/* Eat byte after byte till full packet header is received */
		if (nu->rx_skb->len < NCI_CTRL_HDR_SIZE) {
			*skb_put(nu->rx_skb, 1) = *data++;
			--count;
			continue;
		}

		/* Header was received but packet len was not read */
		if (nu->rx_packet_len < 0)
			nu->rx_packet_len = NCI_CTRL_HDR_SIZE +
				nci_plen(nu->rx_skb->data);

		/* Compute how many bytes are missing and how many bytes can
		 * be consumed.
		 */
		chunk_len = nu->rx_packet_len - nu->rx_skb->len;
		if (count < chunk_len)
			chunk_len = count;
		memcpy(skb_put(nu->rx_skb, chunk_len), data, chunk_len);
		data += chunk_len;
		count -= chunk_len;

		/* Chcek if packet is fully received */
		if (nu->rx_packet_len == nu->rx_skb->len) {
			/* Pass RX packet to driver */
			if (nu->ops.recv(nu, nu->rx_skb) != 0)
				nfc_err(nu->tty->dev, "corrupted RX packet\n");
			/* Next packet will be a new one */
			nu->rx_skb = NULL;
		}
	}

	return 0;
}
Exemple #6
0
void nci_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb)
{
	__u16 rsp_opcode = nci_opcode(skb->data);

	/* we got a rsp, stop the cmd timer */
	del_timer(&ndev->cmd_timer);

	pr_debug("NCI RX: MT=rsp, PBF=%d, GID=0x%x, OID=0x%x, plen=%d\n",
		 nci_pbf(skb->data),
		 nci_opcode_gid(rsp_opcode),
		 nci_opcode_oid(rsp_opcode),
		 nci_plen(skb->data));

	/* strip the nci control header */
	skb_pull(skb, NCI_CTRL_HDR_SIZE);

	switch (rsp_opcode) {
	case NCI_OP_CORE_RESET_RSP:
		nci_core_reset_rsp_packet(ndev, skb);
		break;

	case NCI_OP_CORE_INIT_RSP:
		nci_core_init_rsp_packet(ndev, skb);
		break;

	case NCI_OP_CORE_SET_CONFIG_RSP:
		nci_core_set_config_rsp_packet(ndev, skb);
		break;

	case NCI_OP_RF_DISCOVER_MAP_RSP:
		nci_rf_disc_map_rsp_packet(ndev, skb);
		break;

	case NCI_OP_RF_DISCOVER_RSP:
		nci_rf_disc_rsp_packet(ndev, skb);
		break;

	case NCI_OP_RF_DISCOVER_SELECT_RSP:
		nci_rf_disc_select_rsp_packet(ndev, skb);
		break;

	case NCI_OP_RF_DEACTIVATE_RSP:
		nci_rf_deactivate_rsp_packet(ndev, skb);
		break;

	default:
		pr_err("unknown rsp opcode 0x%x\n", rsp_opcode);
		break;
	}

	kfree_skb(skb);

	/* trigger the next cmd */
	atomic_set(&ndev->cmd_cnt, 1);
	if (!skb_queue_empty(&ndev->cmd_q))
		queue_work(ndev->cmd_wq, &ndev->cmd_work);
}
Exemple #7
0
void nci_ntf_packet(struct nci_dev *ndev, struct sk_buff *skb)
{
	__u16 ntf_opcode = nci_opcode(skb->data);

	pr_debug("NCI RX: MT=ntf, PBF=%d, GID=0x%x, OID=0x%x, plen=%d\n",
		 nci_pbf(skb->data),
		 nci_opcode_gid(ntf_opcode),
		 nci_opcode_oid(ntf_opcode),
		 nci_plen(skb->data));

	
	skb_pull(skb, NCI_CTRL_HDR_SIZE);

	switch (ntf_opcode) {
	case NCI_OP_CORE_CONN_CREDITS_NTF:
		nci_core_conn_credits_ntf_packet(ndev, skb);
		break;

	case NCI_OP_CORE_GENERIC_ERROR_NTF:
		nci_core_generic_error_ntf_packet(ndev, skb);
		break;

	case NCI_OP_CORE_INTF_ERROR_NTF:
		nci_core_conn_intf_error_ntf_packet(ndev, skb);
		break;

	case NCI_OP_RF_DISCOVER_NTF:
		nci_rf_discover_ntf_packet(ndev, skb);
		break;

	case NCI_OP_RF_INTF_ACTIVATED_NTF:
		nci_rf_intf_activated_ntf_packet(ndev, skb);
		break;

	case NCI_OP_RF_DEACTIVATE_NTF:
		nci_rf_deactivate_ntf_packet(ndev, skb);
		break;

	default:
		pr_err("unknown ntf opcode 0x%x\n", ntf_opcode);
		break;
	}

	kfree_skb(skb);
}
Exemple #8
0
/* Rx Data packet */
void nci_rx_data_packet(struct nci_dev *ndev, struct sk_buff *skb)
{
	__u8 pbf = nci_pbf(skb->data);

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

	nfc_dbg("NCI RX: MT=data, PBF=%d, conn_id=%d, plen=%d",
			nci_pbf(skb->data),
			nci_conn_id(skb->data),
			nci_plen(skb->data));

	/* strip the nci data header */
	skb_pull(skb, NCI_DATA_HDR_SIZE);

	if (ndev->target_active_prot == NFC_PROTO_MIFARE) {
		/* frame I/F => remove the status byte */
		nfc_dbg("NFC_PROTO_MIFARE => remove the status byte");
		skb_trim(skb, (skb->len - 1));
	}

	nci_add_rx_data_frag(ndev, skb, pbf);
}
void nci_rx_data_packet(struct nci_dev *ndev, struct sk_buff *skb)
{
	__u8 pbf = nci_pbf(skb->data);

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

	pr_debug("NCI RX: MT=data, PBF=%d, conn_id=%d, plen=%d\n",
		 nci_pbf(skb->data),
		 nci_conn_id(skb->data),
		 nci_plen(skb->data));

	/*                           */
	skb_pull(skb, NCI_DATA_HDR_SIZE);

	if (ndev->target_active_prot == NFC_PROTO_MIFARE) {
		/*                                     */
		pr_debug("NFC_PROTO_MIFARE => remove the status byte\n");
		skb_trim(skb, (skb->len - 1));
	}

	nci_add_rx_data_frag(ndev, skb, pbf);
}
Exemple #10
0
static void nci_tx_work(struct work_struct *work)
{
	struct nci_dev *ndev = container_of(work, struct nci_dev, tx_work);
	struct sk_buff *skb;

	nfc_dbg("entry, credits_cnt %d", atomic_read(&ndev->credits_cnt));

	/* Send queued tx data */
	while (atomic_read(&ndev->credits_cnt)) {
		skb = skb_dequeue(&ndev->tx_q);
		if (!skb)
			return;

		atomic_dec(&ndev->credits_cnt);

		nfc_dbg("NCI TX: MT=data, PBF=%d, conn_id=%d, plen=%d",
				nci_pbf(skb->data),
				nci_conn_id(skb->data),
				nci_plen(skb->data));

		nci_send_frame(skb);
	}
}