drivers/input/touchscreen/cy8ctmg110_ts.c

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

File Facts

System
Linux kernel
Corpus path
drivers/input/touchscreen/cy8ctmg110_ts.c
Extension
.c
Size
6526 bytes
Lines
290
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 cy8ctmg110 {
	struct input_dev *input;
	char phys[32];
	struct i2c_client *client;
	struct gpio_desc *reset_gpio;
};

/*
 * cy8ctmg110_power is the routine that is called when touch hardware
 * is being powered off or on. When powering on this routine de-asserts
 * the RESET line, when powering off reset line is asserted.
 */
static void cy8ctmg110_power(struct cy8ctmg110 *ts, bool poweron)
{
	if (ts->reset_gpio)
		gpiod_set_value_cansleep(ts->reset_gpio, !poweron);
}

static int cy8ctmg110_write_regs(struct cy8ctmg110 *tsc, unsigned char reg,
		unsigned char len, unsigned char *value)
{
	struct i2c_client *client = tsc->client;
	int ret;
	unsigned char i2c_data[6];

	BUG_ON(len > 5);

	i2c_data[0] = reg;
	memcpy(i2c_data + 1, value, len);

	ret = i2c_master_send(client, i2c_data, len + 1);
	if (ret != len + 1) {
		dev_err(&client->dev, "i2c write data cmd failed\n");
		return ret < 0 ? ret : -EIO;
	}

	return 0;
}

static int cy8ctmg110_read_regs(struct cy8ctmg110 *tsc,
		unsigned char *data, unsigned char len, unsigned char cmd)
{
	struct i2c_client *client = tsc->client;
	int ret;
	struct i2c_msg msg[2] = {
		/* first write slave position to i2c devices */
		{
			.addr = client->addr,
			.len = 1,
			.buf = &cmd
		},
		/* Second read data from position */
		{
			.addr = client->addr,
			.flags = I2C_M_RD,
			.len = len,
			.buf = data
		}
	};

	ret = i2c_transfer(client->adapter, msg, 2);
	if (ret < 0)
		return ret;

	return 0;
}

static int cy8ctmg110_touch_pos(struct cy8ctmg110 *tsc)
{
	struct input_dev *input = tsc->input;
	unsigned char reg_p[CY8CTMG110_REG_MAX];

	memset(reg_p, 0, CY8CTMG110_REG_MAX);

	/* Reading coordinates */
	if (cy8ctmg110_read_regs(tsc, reg_p, 9, CY8CTMG110_TOUCH_X1) != 0)
		return -EIO;

	/* Number of touch */
	if (reg_p[8] == 0) {
		input_report_key(input, BTN_TOUCH, 0);
	} else  {
		input_report_key(input, BTN_TOUCH, 1);
		input_report_abs(input, ABS_X,
				 be16_to_cpup((__be16 *)(reg_p + 0)));
		input_report_abs(input, ABS_Y,
				 be16_to_cpup((__be16 *)(reg_p + 2)));
	}

	input_sync(input);

Annotation

Implementation Notes