drivers/media/usb/em28xx/em28xx-i2c.c

Source file repositories/reference/linux-study-clean/drivers/media/usb/em28xx/em28xx-i2c.c

File Facts

System
Linux kernel
Corpus path
drivers/media/usb/em28xx/em28xx-i2c.c
Extension
.c
Size
26400 bytes
Lines
1032
Domain
Driver Families
Bucket
drivers/media
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 (ret == 0x94 + len - 1) {
			dprintk(1, "R05 returned 0x%02x: I2C ACK error\n", ret);
			return -ENXIO;
		}
		if (ret < 0) {
			dev_warn(&dev->intf->dev,
				 "failed to get i2c transfer status from bridge register (error=%i)\n",
				ret);
			return ret;
		}
		usleep_range(5000, 6000);
	}
	dprintk(0, "write to i2c device at 0x%x timed out\n", addr);
	return -ETIMEDOUT;
}

/*
 * em2800_i2c_recv_bytes()
 * read up to 4 bytes from the em2800 i2c device
 */
static int em2800_i2c_recv_bytes(struct em28xx *dev, u8 addr, u8 *buf, u16 len)
{
	unsigned long timeout = jiffies + em28xx_i2c_timeout(dev);
	u8 buf2[4];
	int ret;
	int i;

	if (len < 1 || len > 4)
		return -EOPNOTSUPP;

	/* trigger read */
	buf2[1] = 0x84 + len - 1;
	buf2[0] = addr;
	ret = dev->em28xx_write_regs(dev, 0x04, buf2, 2);
	if (ret != 2) {
		dev_warn(&dev->intf->dev,
			 "failed to trigger read from i2c address 0x%x (error=%i)\n",
			 addr, ret);
		return (ret < 0) ? ret : -EIO;
	}

	/* wait for completion */
	while (time_is_after_jiffies(timeout)) {
		ret = dev->em28xx_read_reg(dev, 0x05);
		if (ret == 0x84 + len - 1)
			break;
		if (ret == 0x94 + len - 1) {
			dprintk(1, "R05 returned 0x%02x: I2C ACK error\n",
				ret);
			return -ENXIO;
		}
		if (ret < 0) {
			dev_warn(&dev->intf->dev,
				 "failed to get i2c transfer status from bridge register (error=%i)\n",
				 ret);
			return ret;
		}
		usleep_range(5000, 6000);
	}
	if (ret != 0x84 + len - 1)
		dprintk(0, "read from i2c device at 0x%x timed out\n", addr);

	/* get the received message */
	ret = dev->em28xx_read_reg_req_len(dev, 0x00, 4 - len, buf2, len);
	if (ret != len) {
		dev_warn(&dev->intf->dev,
			 "reading from i2c device at 0x%x failed: couldn't get the received message from the bridge (error=%i)\n",
			 addr, ret);
		return (ret < 0) ? ret : -EIO;
	}
	for (i = 0; i < len; i++)
		buf[i] = buf2[len - 1 - i];

	return ret;
}

/*
 * em2800_i2c_check_for_device()
 * check if there is an i2c device at the supplied address
 */
static int em2800_i2c_check_for_device(struct em28xx *dev, u8 addr)
{
	u8 buf;
	int ret;

	ret = em2800_i2c_recv_bytes(dev, addr, &buf, 1);
	if (ret == 1)
		return 0;
	return (ret < 0) ? ret : -EIO;
}

Annotation

Implementation Notes