drivers/input/touchscreen/edt-ft5x06.c

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

File Facts

System
Linux kernel
Corpus path
drivers/input/touchscreen/edt-ft5x06.c
Extension
.c
Size
40573 bytes
Lines
1535
Domain
Driver Families
Bucket
drivers/input
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern 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

static const struct file_operations debugfs_raw_data_fops = {
	.open = simple_open,
	.read = edt_ft5x06_debugfs_raw_data_read,
};

static void edt_ft5x06_ts_prepare_debugfs(struct edt_ft5x06_ts_data *tsdata)
{
	struct dentry *debug_dir = tsdata->client->debugfs;

	debugfs_create_u16("num_x", S_IRUSR, debug_dir, &tsdata->num_x);
	debugfs_create_u16("num_y", S_IRUSR, debug_dir, &tsdata->num_y);

	debugfs_create_file("mode", S_IRUSR | S_IWUSR,
			    debug_dir, tsdata, &debugfs_mode_fops);
	debugfs_create_file("raw_data", S_IRUSR,
			    debug_dir, tsdata, &debugfs_raw_data_fops);
}

static void edt_ft5x06_ts_teardown_debugfs(struct edt_ft5x06_ts_data *tsdata)
{
	guard(mutex)(&tsdata->mutex);

	kfree(tsdata->raw_buffer);
	tsdata->raw_buffer = NULL;
}

#else

static int edt_ft5x06_factory_mode(struct edt_ft5x06_ts_data *tsdata)
{
	return -ENOSYS;
}

static void edt_ft5x06_ts_prepare_debugfs(struct edt_ft5x06_ts_data *tsdata)
{
}

static void edt_ft5x06_ts_teardown_debugfs(struct edt_ft5x06_ts_data *tsdata)
{
}

#endif /* CONFIG_DEBUGFS */

static int edt_ft5x06_ts_identify(struct i2c_client *client,
				  struct edt_ft5x06_ts_data *tsdata)
{
	u8 rdbuf[EDT_NAME_LEN];
	char *p;
	int error;
	char *model_name = tsdata->name;
	char *fw_version = tsdata->fw_version;

	/* see what we find if we assume it is a M06 *
	 * if we get less than EDT_NAME_LEN, we don't want
	 * to have garbage in there
	 */
	memset(rdbuf, 0, sizeof(rdbuf));
	error = regmap_bulk_read(tsdata->regmap, 0xBB, rdbuf, EDT_NAME_LEN - 1);
	if (error)
		return error;

	/* Probe content for something consistent.
	 * M06 starts with a response byte, M12 gives the data directly.
	 * M09/Generic does not provide model number information.
	 */
	if (!strncasecmp(rdbuf + 1, "EP0", 3)) {
		tsdata->version = EDT_M06;

		/* remove last '$' end marker */
		rdbuf[EDT_NAME_LEN - 1] = '\0';
		if (rdbuf[EDT_NAME_LEN - 2] == '$')
			rdbuf[EDT_NAME_LEN - 2] = '\0';

		/* look for Model/Version separator */
		p = strchr(rdbuf, '*');
		if (p)
			*p++ = '\0';
		strscpy(model_name, rdbuf + 1, EDT_NAME_LEN);
		strscpy(fw_version, p ? p : "", EDT_NAME_LEN);

		regmap_exit(tsdata->regmap);
		tsdata->regmap = regmap_init_i2c(client,
						 &edt_M06_i2c_regmap_config);
		if (IS_ERR(tsdata->regmap)) {
			dev_err(&client->dev, "regmap allocation failed\n");
			return PTR_ERR(tsdata->regmap);
		}
	} else if (!strncasecmp(rdbuf, "EP0", 3)) {
		tsdata->version = EDT_M12;

Annotation

Implementation Notes