drivers/input/touchscreen/cy8ctma140.c

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

File Facts

System
Linux kernel
Corpus path
drivers/input/touchscreen/cy8ctma140.c
Extension
.c
Size
8627 bytes
Lines
350
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 cy8ctma140 {
	struct input_dev *input;
	struct touchscreen_properties props;
	struct device *dev;
	struct i2c_client *client;
	struct regulator_bulk_data regulators[2];
	u8 prev_fingers;
	u8 prev_f1id;
	u8 prev_f2id;
};

static void cy8ctma140_report(struct cy8ctma140 *ts, u8 *data, int n_fingers)
{
	static const u8 contact_offsets[] = { 0x03, 0x09, 0x10, 0x16 };
	u8 *buf;
	u16 x, y;
	u8 w;
	u8 id;
	int slot;
	int i;

	for (i = 0; i < n_fingers; i++) {
		buf = &data[contact_offsets[i]];

		/*
		 * Odd contacts have contact ID in the lower nibble of
		 * the preceding byte, whereas even contacts have it in
		 * the upper nibble of the following byte.
		 */
		id = i % 2 ? buf[-1] & 0x0f : buf[5] >> 4;
		slot = input_mt_get_slot_by_key(ts->input, id);
		if (slot < 0)
			continue;

		x = get_unaligned_be16(buf);
		y = get_unaligned_be16(buf + 2);
		w = buf[4];

		dev_dbg(ts->dev, "finger %d: ID %02x (%d, %d) w: %d\n",
			slot, id, x, y, w);

		input_mt_slot(ts->input, slot);
		input_mt_report_slot_state(ts->input, MT_TOOL_FINGER, true);
		touchscreen_report_pos(ts->input, &ts->props, x, y, true);
		input_report_abs(ts->input, ABS_MT_TOUCH_MAJOR, w);
	}

	input_mt_sync_frame(ts->input);
	input_sync(ts->input);
}

static irqreturn_t cy8ctma140_irq_thread(int irq, void *d)
{
	struct cy8ctma140 *ts = d;
	u8 cmdbuf[] = { CY8CTMA140_GET_FINGERS };
	u8 buf[CY8CTMA140_PACKET_SIZE];
	struct i2c_msg msg[] = {
		{
			.addr = ts->client->addr,
			.flags = 0,
			.len = sizeof(cmdbuf),
			.buf = cmdbuf,
		}, {
			.addr = ts->client->addr,
			.flags = I2C_M_RD,
			.len = sizeof(buf),
			.buf = buf,
		},
	};
	u8 n_fingers;
	int ret;

	ret = i2c_transfer(ts->client->adapter, msg, ARRAY_SIZE(msg));
	if (ret != ARRAY_SIZE(msg)) {
		if (ret < 0)
			dev_err(ts->dev, "error reading message: %d\n", ret);
		else
			dev_err(ts->dev, "wrong number of messages\n");
		goto out;
	}

	if (buf[1] & BIT(CY8CTMA140_INVALID_BUFFER_BIT)) {
		dev_dbg(ts->dev, "invalid event\n");
		goto out;
	}

	n_fingers = buf[2] & 0x0f;
	if (n_fingers > CY8CTMA140_MAX_FINGERS) {
		dev_err(ts->dev, "unexpected number of fingers: %d\n",
			n_fingers);

Annotation

Implementation Notes