drivers/nfc/fdp/i2c.c

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

File Facts

System
Linux kernel
Corpus path
drivers/nfc/fdp/i2c.c
Extension
.c
Size
8551 bytes
Lines
370
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

if (r != skb->len) {
			phy->hard_fault = r;
			r = -EREMOTEIO;
		} else {
			r = 0;
		}
	}

	fdp_nci_i2c_remove_len_lrc(skb);

	return r;
}

static const struct nfc_phy_ops i2c_phy_ops = {
	.write = fdp_nci_i2c_write,
	.enable = fdp_nci_i2c_enable,
	.disable = fdp_nci_i2c_disable,
};

static int fdp_nci_i2c_read(struct fdp_i2c_phy *phy, struct sk_buff **skb)
{
	int r, len;
	u8 tmp[FDP_NCI_I2C_MAX_PAYLOAD], lrc, k;
	u16 i;
	struct i2c_client *client = phy->i2c_dev;

	*skb = NULL;

	/* Read the length packet and the data packet */
	for (k = 0; k < 2; k++) {

		len = phy->next_read_size;

		r = i2c_master_recv(client, tmp, len);
		if (r != len) {
			dev_dbg(&client->dev, "%s: i2c recv err: %d\n",
				__func__, r);
			goto flush;
		}

		/* Check packet integruty */
		for (lrc = i = 0; i < r; i++)
			lrc ^= tmp[i];

		/*
		 * LRC check failed. This may due to transmission error or
		 * desynchronization between driver and FDP. Drop the packet
		 * and force resynchronization
		 */
		if (lrc) {
			dev_dbg(&client->dev, "%s: corrupted packet\n",
				__func__);
			phy->next_read_size = 5;
			goto flush;
		}

		/* Packet that contains a length */
		if (tmp[0] == 0 && tmp[1] == 0) {
			phy->next_read_size = (tmp[2] << 8) + tmp[3] + 3;
		} else {
			phy->next_read_size = FDP_NCI_I2C_MIN_PAYLOAD;

			*skb = alloc_skb(len, GFP_KERNEL);
			if (*skb == NULL) {
				r = -ENOMEM;
				goto flush;
			}

			skb_put_data(*skb, tmp, len);
			fdp_nci_i2c_dump_skb(&client->dev, "fdp_rd", *skb);

			fdp_nci_i2c_remove_len_lrc(*skb);
		}
	}

	return 0;

flush:
	/* Flush the remaining data */
	if (i2c_master_recv(client, tmp, sizeof(tmp)) < 0)
		r = -EREMOTEIO;

	return r;
}

static irqreturn_t fdp_nci_i2c_irq_thread_fn(int irq, void *phy_id)
{
	struct fdp_i2c_phy *phy = phy_id;
	struct sk_buff *skb;
	int r;

Annotation

Implementation Notes