drivers/nfc/pn533/i2c.c

Source file repositories/reference/linux-study-clean/drivers/nfc/pn533/i2c.c

File Facts

System
Linux kernel
Corpus path
drivers/nfc/pn533/i2c.c
Extension
.c
Size
6088 bytes
Lines
273
Domain
Driver Families
Bucket
drivers/nfc
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct pn533_i2c_phy {
	struct i2c_client *i2c_dev;
	struct pn533 *priv;

	bool aborted;

	int hard_fault;		/*
				 * < 0 if hardware error occurred (e.g. i2c err)
				 * and prevents normal operation.
				 */
};

static int pn533_i2c_send_ack(struct pn533 *dev, gfp_t flags)
{
	struct pn533_i2c_phy *phy = dev->phy;
	struct i2c_client *client = phy->i2c_dev;
	static const u8 ack[6] = {0x00, 0x00, 0xff, 0x00, 0xff, 0x00};
	/* spec 6.2.1.3:  Preamble, SoPC (2), ACK Code (2), Postamble */

	return i2c_master_send(client, ack, 6);
}

static int pn533_i2c_send_frame(struct pn533 *dev,
				struct sk_buff *out)
{
	struct pn533_i2c_phy *phy = dev->phy;
	struct i2c_client *client = phy->i2c_dev;
	int rc;

	if (phy->hard_fault != 0)
		return phy->hard_fault;

	if (phy->priv == NULL)
		phy->priv = dev;

	phy->aborted = false;

	print_hex_dump_debug("PN533_i2c TX: ", DUMP_PREFIX_NONE, 16, 1,
			     out->data, out->len, false);

	rc = i2c_master_send(client, out->data, out->len);

	if (rc == -EREMOTEIO) { /* Retry, chip was in power down */
		usleep_range(6000, 10000);
		rc = i2c_master_send(client, out->data, out->len);
	}

	if (rc >= 0) {
		if (rc != out->len)
			rc = -EREMOTEIO;
		else
			rc = 0;
	}

	return rc;
}

static void pn533_i2c_abort_cmd(struct pn533 *dev, gfp_t flags)
{
	struct pn533_i2c_phy *phy = dev->phy;

	phy->aborted = true;

	/* An ack will cancel the last issued command */
	pn533_i2c_send_ack(dev, flags);

	/* schedule cmd_complete_work to finish current command execution */
	pn533_recv_frame(phy->priv, NULL, -ENOENT);
}

static int pn533_i2c_read(struct pn533_i2c_phy *phy, struct sk_buff **skb)
{
	struct i2c_client *client = phy->i2c_dev;
	int len = PN533_EXT_FRAME_HEADER_LEN +
		  PN533_STD_FRAME_MAX_PAYLOAD_LEN +
		  PN533_STD_FRAME_TAIL_LEN + 1;
	int r;

	*skb = alloc_skb(len, GFP_KERNEL);
	if (*skb == NULL)
		return -ENOMEM;

	r = i2c_master_recv(client, skb_put(*skb, len), len);
	if (r != len) {
		nfc_err(&client->dev, "cannot read. r=%d len=%d\n", r, len);
		kfree_skb(*skb);
		return -EREMOTEIO;
	}

	if (!((*skb)->data[0] & 0x01)) {

Annotation

Implementation Notes