drivers/input/touchscreen/resistive-adc-touch.c

Source file repositories/reference/linux-study-clean/drivers/input/touchscreen/resistive-adc-touch.c

File Facts

System
Linux kernel
Corpus path
drivers/input/touchscreen/resistive-adc-touch.c
Extension
.c
Size
7548 bytes
Lines
304
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 grts_state {
	u32				x_plate_ohms;
	u32				pressure_min;
	bool				pressure;
	struct iio_channel		*iio_chans;
	struct iio_cb_buffer		*iio_cb;
	struct input_dev		*input;
	struct touchscreen_properties	prop;
	u8				ch_map[GRTS_CH_MAX];
};

static int grts_cb(const void *data, void *private)
{
	const u16 *touch_info = data;
	struct grts_state *st = private;
	unsigned int x, y, press = 0;

	x = touch_info[st->ch_map[GRTS_CH_X]];
	y = touch_info[st->ch_map[GRTS_CH_Y]];

	if (st->ch_map[GRTS_CH_PRESSURE] < GRTS_MAX_CHANNELS) {
		press = touch_info[st->ch_map[GRTS_CH_PRESSURE]];
	} else if (st->ch_map[GRTS_CH_Z1] < GRTS_MAX_CHANNELS) {
		unsigned int z1 = touch_info[st->ch_map[GRTS_CH_Z1]];
		unsigned int z2 = touch_info[st->ch_map[GRTS_CH_Z2]];
		unsigned int Rt;

		if (likely(x && z1)) {
			Rt = z2;
			Rt -= z1;
			Rt *= st->x_plate_ohms;
			Rt = DIV_ROUND_CLOSEST(Rt, 16);
			Rt *= x;
			Rt /= z1;
			Rt = DIV_ROUND_CLOSEST(Rt, 256);
			/*
			 * On increased pressure the resistance (Rt) is
			 * decreasing so, convert values to make it looks as
			 * real pressure.
			 */
			if (Rt < GRTS_DEFAULT_PRESSURE_MAX)
				press = GRTS_DEFAULT_PRESSURE_MAX - Rt;
		}
	}

	if ((!x && !y) || (st->pressure && (press < st->pressure_min))) {
		/* report end of touch */
		input_report_key(st->input, BTN_TOUCH, 0);
		input_sync(st->input);
		return 0;
	}

	/* report proper touch to subsystem*/
	touchscreen_report_pos(st->input, &st->prop, x, y, false);
	if (st->pressure)
		input_report_abs(st->input, ABS_PRESSURE, press);
	input_report_key(st->input, BTN_TOUCH, 1);
	input_sync(st->input);

	return 0;
}

static int grts_open(struct input_dev *dev)
{
	int error;
	struct grts_state *st = input_get_drvdata(dev);

	error = iio_channel_start_all_cb(st->iio_cb);
	if (error) {
		dev_err(dev->dev.parent, "failed to start callback buffer.\n");
		return error;
	}
	return 0;
}

static void grts_close(struct input_dev *dev)
{
	struct grts_state *st = input_get_drvdata(dev);

	iio_channel_stop_all_cb(st->iio_cb);
}

static void grts_disable(void *data)
{
	iio_channel_release_all_cb(data);
}

static int grts_map_channel(struct grts_state *st, struct device *dev,
			    enum grts_ch_type type, const char *name,
			    bool optional)

Annotation

Implementation Notes