drivers/input/touchscreen/chipone_icn8318.c

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

File Facts

System
Linux kernel
Corpus path
drivers/input/touchscreen/chipone_icn8318.c
Extension
.c
Size
6690 bytes
Lines
272
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 icn8318_touch {
	__u8 slot;
	__be16 x;
	__be16 y;
	__u8 pressure;	/* Seems more like finger width then pressure really */
	__u8 event;
/* The difference between 2 and 3 is unclear */
#define ICN8318_EVENT_NO_DATA	1 /* No finger seen yet since wakeup */
#define ICN8318_EVENT_UPDATE1	2 /* New or updated coordinates */
#define ICN8318_EVENT_UPDATE2	3 /* New or updated coordinates */
#define ICN8318_EVENT_END	4 /* Finger lifted */
} __packed;

struct icn8318_touch_data {
	__u8 softbutton;
	__u8 touch_count;
	struct icn8318_touch touches[ICN8318_MAX_TOUCHES];
} __packed;

struct icn8318_data {
	struct i2c_client *client;
	struct input_dev *input;
	struct gpio_desc *wake_gpio;
	struct touchscreen_properties prop;
};

static int icn8318_read_touch_data(struct i2c_client *client,
				   struct icn8318_touch_data *touch_data)
{
	u8 reg = ICN8318_REG_TOUCHDATA;
	struct i2c_msg msg[2] = {
		{
			.addr = client->addr,
			.len = 1,
			.buf = &reg
		},
		{
			.addr = client->addr,
			.flags = I2C_M_RD,
			.len = sizeof(struct icn8318_touch_data),
			.buf = (u8 *)touch_data
		}
	};

	return i2c_transfer(client->adapter, msg, 2);
}

static inline bool icn8318_touch_active(u8 event)
{
	return (event == ICN8318_EVENT_UPDATE1) ||
	       (event == ICN8318_EVENT_UPDATE2);
}

static irqreturn_t icn8318_irq(int irq, void *dev_id)
{
	struct icn8318_data *data = dev_id;
	struct device *dev = &data->client->dev;
	struct icn8318_touch_data touch_data;
	int i, ret;

	ret = icn8318_read_touch_data(data->client, &touch_data);
	if (ret < 0) {
		dev_err(dev, "Error reading touch data: %d\n", ret);
		return IRQ_HANDLED;
	}

	if (touch_data.softbutton) {
		/*
		 * Other data is invalid when a softbutton is pressed.
		 * This needs some extra devicetree bindings to map the icn8318
		 * softbutton codes to evdev codes. Currently no known devices
		 * use this.
		 */
		return IRQ_HANDLED;
	}

	if (touch_data.touch_count > ICN8318_MAX_TOUCHES) {
		dev_warn(dev, "Too much touches %d > %d\n",
			 touch_data.touch_count, ICN8318_MAX_TOUCHES);
		touch_data.touch_count = ICN8318_MAX_TOUCHES;
	}

	for (i = 0; i < touch_data.touch_count; i++) {
		struct icn8318_touch *touch = &touch_data.touches[i];
		bool act = icn8318_touch_active(touch->event);

		input_mt_slot(data->input, touch->slot);
		input_mt_report_slot_state(data->input, MT_TOOL_FINGER, act);
		if (!act)
			continue;

Annotation

Implementation Notes