drivers/input/touchscreen/surface3_spi.c

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

File Facts

System
Linux kernel
Corpus path
drivers/input/touchscreen/surface3_spi.c
Extension
.c
Size
9813 bytes
Lines
415
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 surface3_ts_data {
	struct spi_device *spi;
	struct gpio_desc *gpiod_rst[2];
	struct input_dev *input_dev;
	struct input_dev *pen_input_dev;
	int pen_tool;

	u8 rd_buf[SURFACE3_PACKET_SIZE]		____cacheline_aligned;
};

struct surface3_ts_data_finger {
	u8 status;
	__le16 tracking_id;
	__le16 x;
	__le16 cx;
	__le16 y;
	__le16 cy;
	__le16 width;
	__le16 height;
	u32 padding;
} __packed;

struct surface3_ts_data_pen {
	u8 status;
	__le16 x;
	__le16 y;
	__le16 pressure;
	u8 padding;
} __packed;

static int surface3_spi_read(struct surface3_ts_data *ts_data)
{
	struct spi_device *spi = ts_data->spi;

	memset(ts_data->rd_buf, 0, sizeof(ts_data->rd_buf));
	return spi_read(spi, ts_data->rd_buf, sizeof(ts_data->rd_buf));
}

static void surface3_spi_report_touch(struct surface3_ts_data *ts_data,
				   struct surface3_ts_data_finger *finger)
{
	int st = finger->status & 0x01;
	int slot;

	slot = input_mt_get_slot_by_key(ts_data->input_dev,
				get_unaligned_le16(&finger->tracking_id));
	if (slot < 0)
		return;

	input_mt_slot(ts_data->input_dev, slot);
	input_mt_report_slot_state(ts_data->input_dev, MT_TOOL_FINGER, st);
	if (st) {
		input_report_abs(ts_data->input_dev,
				 ABS_MT_POSITION_X,
				 get_unaligned_le16(&finger->x));
		input_report_abs(ts_data->input_dev,
				 ABS_MT_POSITION_Y,
				 get_unaligned_le16(&finger->y));
		input_report_abs(ts_data->input_dev,
				 ABS_MT_WIDTH_MAJOR,
				 get_unaligned_le16(&finger->width));
		input_report_abs(ts_data->input_dev,
				 ABS_MT_WIDTH_MINOR,
				 get_unaligned_le16(&finger->height));
	}
}

static void surface3_spi_process_touch(struct surface3_ts_data *ts_data, u8 *data)
{
	unsigned int i;

	for (i = 0; i < 13; i++) {
		struct surface3_ts_data_finger *finger;

		finger = (struct surface3_ts_data_finger *)&data[17 +
				i * sizeof(struct surface3_ts_data_finger)];

		/*
		 * When bit 5 of status is 1, it marks the end of the report:
		 * - touch present: 0xe7
		 * - touch released: 0xe4
		 * - nothing valuable: 0xff
		 */
		if (finger->status & 0x10)
			break;

		surface3_spi_report_touch(ts_data, finger);
	}

	input_mt_sync_frame(ts_data->input_dev);

Annotation

Implementation Notes