drivers/media/usb/au0828/au0828-input.c

Source file repositories/reference/linux-study-clean/drivers/media/usb/au0828/au0828-input.c

File Facts

System
Linux kernel
Corpus path
drivers/media/usb/au0828/au0828-input.c
Extension
.c
Size
8695 bytes
Lines
401
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

struct au0828_rc {
	struct au0828_dev *dev;
	struct rc_dev *rc;
	char name[32];
	char phys[32];

	/* poll decoder */
	int polling;
	struct delayed_work work;

	/* i2c slave address of external device (if used) */
	u16 i2c_dev_addr;

	int  (*get_key_i2c)(struct au0828_rc *ir);
};

/*
 * AU8522 has a builtin IR receiver. Add functions to get IR from it
 */

static int au8522_rc_write(struct au0828_rc *ir, u16 reg, u8 data)
{
	int rc;
	char buf[] = { (reg >> 8) | 0x80, reg & 0xff, data };
	struct i2c_msg msg = { .addr = ir->i2c_dev_addr, .flags = 0,
			       .buf = buf, .len = sizeof(buf) };

	rc = i2c_transfer(ir->dev->i2c_client.adapter, &msg, 1);

	if (rc < 0)
		return rc;

	return (rc == 1) ? 0 : -EIO;
}

static int au8522_rc_read(struct au0828_rc *ir, u16 reg, int val,
				 char *buf, int size)
{
	int rc;
	char obuf[3];
	struct i2c_msg msg[2] = { { .addr = ir->i2c_dev_addr, .flags = 0,
				    .buf = obuf, .len = 2 },
				  { .addr = ir->i2c_dev_addr, .flags = I2C_M_RD,
				    .buf = buf, .len = size } };

	obuf[0] = 0x40 | reg >> 8;
	obuf[1] = reg & 0xff;
	if (val >= 0) {
		obuf[2] = val;
		msg[0].len++;
	}

	rc = i2c_transfer(ir->dev->i2c_client.adapter, msg, 2);

	if (rc < 0)
		return rc;

	return (rc == 2) ? 0 : -EIO;
}

static int au8522_rc_andor(struct au0828_rc *ir, u16 reg, u8 mask, u8 value)
{
	int rc;
	char buf, oldbuf;

	rc = au8522_rc_read(ir, reg, -1, &buf, 1);
	if (rc < 0)
		return rc;

	oldbuf = buf;
	buf = (buf & ~mask) | (value & mask);

	/* Nothing to do, just return */
	if (buf == oldbuf)
		return 0;

	return au8522_rc_write(ir, reg, buf);
}

#define au8522_rc_set(ir, reg, bit) au8522_rc_andor(ir, (reg), (bit), (bit))
#define au8522_rc_clear(ir, reg, bit) au8522_rc_andor(ir, (reg), (bit), 0)

/* Remote Controller time units */

#define AU8522_UNIT		200 /* us */
#define NEC_START_SPACE		(4500 / AU8522_UNIT)
#define NEC_START_PULSE		(563 * 16)
#define RC5_START_SPACE		(4 * AU8522_UNIT)
#define RC5_START_PULSE		889

Annotation

Implementation Notes