drivers/input/touchscreen/imagis.c

Source file repositories/reference/linux-study-clean/drivers/input/touchscreen/imagis.c

File Facts

System
Linux kernel
Corpus path
drivers/input/touchscreen/imagis.c
Extension
.c
Size
11824 bytes
Lines
466
Domain
Driver Families
Bucket
drivers/input
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 imagis_properties {
	unsigned int interrupt_msg_cmd;
	unsigned int touch_coord_cmd;
	unsigned int whoami_cmd;
	unsigned int whoami_val;
	bool protocol_b;
	bool touch_keys_supported;
};

struct imagis_ts {
	struct i2c_client *client;
	const struct imagis_properties *tdata;
	struct input_dev *input_dev;
	struct touchscreen_properties prop;
	struct regulator_bulk_data supplies[2];
	u32 keycodes[5];
	int num_keycodes;
};

static int imagis_i2c_read_reg(struct imagis_ts *ts,
			       unsigned int reg, u32 *data)
{
	__be32 ret_be;
	__be32 reg_be = cpu_to_be32(reg);
	struct i2c_msg msg[] = {
		{
			.addr = ts->client->addr,
			.flags = 0,
			.buf = (unsigned char *)&reg_be,
			.len = sizeof(reg_be),
		}, {
			.addr = ts->client->addr,
			.flags = I2C_M_RD,
			.buf = (unsigned char *)&ret_be,
			.len = sizeof(ret_be),
		},
	};
	int ret, error;
	int retry = IST3038C_I2C_RETRY_COUNT;

	/* Retry in case the controller fails to respond */
	do {
		ret = i2c_transfer(ts->client->adapter, msg, ARRAY_SIZE(msg));
		if (ret == ARRAY_SIZE(msg)) {
			*data = be32_to_cpu(ret_be);
			return 0;
		}

		error = ret < 0 ? ret : -EIO;
		dev_err(&ts->client->dev,
			"%s - i2c_transfer failed: %d (%d)\n",
			__func__, error, ret);
	} while (--retry);

	return error;
}

static irqreturn_t imagis_interrupt(int irq, void *dev_id)
{
	struct imagis_ts *ts = dev_id;
	u32 intr_message, finger_status;
	unsigned int finger_count, finger_pressed, key_pressed;
	int i;
	int error;

	error = imagis_i2c_read_reg(ts, ts->tdata->interrupt_msg_cmd, &intr_message);
	if (error) {
		dev_err(&ts->client->dev,
			"failed to read the interrupt message: %d\n", error);
		goto out;
	}

	finger_count = FIELD_GET(IST3038C_FINGER_COUNT_MASK, intr_message);
	if (finger_count > IST3038C_MAX_FINGER_NUM) {
		dev_err(&ts->client->dev,
			"finger count %d is more than maximum supported\n",
			finger_count);
		goto out;
	}

	finger_pressed = FIELD_GET(IST3038C_FINGER_STATUS_MASK, intr_message);

	for (i = 0; i < finger_count; i++) {
		if (ts->tdata->protocol_b)
			error = imagis_i2c_read_reg(ts,
						    ts->tdata->touch_coord_cmd + (i * 4),
						    &finger_status);
		else
			error = imagis_i2c_read_reg(ts,
						    ts->tdata->touch_coord_cmd, &finger_status);

Annotation

Implementation Notes