drivers/input/rmi4/rmi_f3a.c

Source file repositories/reference/linux-study-clean/drivers/input/rmi4/rmi_f3a.c

File Facts

System
Linux kernel
Corpus path
drivers/input/rmi4/rmi_f3a.c
Extension
.c
Size
6176 bytes
Lines
242
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 f3a_data {
	/* Query Data */
	u8 gpio_count;

	u8 register_count;

	u8 data_regs[RMI_F3A_DATA_REGS_MAX_SIZE];
	u16 *gpio_key_map;

	struct input_dev *input;

	struct rmi_function *f03;
	bool trackstick_buttons;
};

static void rmi_f3a_report_button(struct rmi_function *fn,
				  struct f3a_data *f3a, unsigned int button)
{
	u16 key_code = f3a->gpio_key_map[button];
	bool key_down = !(f3a->data_regs[0] & BIT(button));

	if (f3a->trackstick_buttons &&
		button >= TRACKSTICK_RANGE_START &&
		button <= TRACKSTICK_RANGE_END) {
		rmi_f03_overwrite_button(f3a->f03, key_code, key_down);
	} else {
		rmi_dbg(RMI_DEBUG_FN, &fn->dev,
			"%s: call input report key (0x%04x) value (0x%02x)",
			__func__, key_code, key_down);
		input_report_key(f3a->input, key_code, key_down);
	}
}

static irqreturn_t rmi_f3a_attention(int irq, void *ctx)
{
	struct rmi_function *fn = ctx;
	struct f3a_data *f3a = dev_get_drvdata(&fn->dev);
	struct rmi_driver_data *drvdata = dev_get_drvdata(&fn->rmi_dev->dev);
	int error;
	int i;

	if (drvdata->attn_data.data) {
		if (drvdata->attn_data.size < f3a->register_count) {
			dev_warn(&fn->dev,
				 "F3A interrupted, but data is missing\n");
			return IRQ_HANDLED;
		}
		memcpy(f3a->data_regs, drvdata->attn_data.data,
			f3a->register_count);
		drvdata->attn_data.data += f3a->register_count;
		drvdata->attn_data.size -= f3a->register_count;
	} else {
		error = rmi_read_block(fn->rmi_dev, fn->fd.data_base_addr,
					f3a->data_regs, f3a->register_count);
		if (error) {
			dev_err(&fn->dev,
				"%s: Failed to read F3a data registers: %d\n",
				__func__, error);
			return IRQ_RETVAL(error);
		}
	}

	for (i = 0; i < f3a->gpio_count; i++)
		if (f3a->gpio_key_map[i] != KEY_RESERVED)
			rmi_f3a_report_button(fn, f3a, i);
	if (f3a->trackstick_buttons)
		rmi_f03_commit_buttons(f3a->f03);

	return IRQ_HANDLED;
}

static int rmi_f3a_config(struct rmi_function *fn)
{
	struct f3a_data *f3a = dev_get_drvdata(&fn->dev);
	struct rmi_driver *drv = fn->rmi_dev->driver;
	const struct rmi_device_platform_data *pdata =
			rmi_get_platform_data(fn->rmi_dev);

	if (!f3a)
		return 0;

	if (pdata->gpio_data.trackstick_buttons) {
		/* Try [re-]establish link to F03. */
		f3a->f03 = rmi_find_function(fn->rmi_dev, 0x03);
		f3a->trackstick_buttons = f3a->f03 != NULL;
	}

	drv->set_irq_bits(fn->rmi_dev, fn->irq_mask);

	return 0;

Annotation

Implementation Notes