drivers/input/rmi4/rmi_f30.c

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

File Facts

System
Linux kernel
Corpus path
drivers/input/rmi4/rmi_f30.c
Extension
.c
Size
10773 bytes
Lines
406
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 rmi_f30_ctrl_data {
	int address;
	int length;
	u8 *regs;
};

struct f30_data {
	/* Query Data */
	bool has_extended_pattern;
	bool has_mappable_buttons;
	bool has_led;
	bool has_gpio;
	bool has_haptic;
	bool has_gpio_driver_control;
	bool has_mech_mouse_btns;
	u8 gpioled_count;

	u8 register_count;

	/* Control Register Data */
	struct rmi_f30_ctrl_data ctrl[RMI_F30_CTRL_MAX_REG_BLOCKS];
	u8 ctrl_regs[RMI_F30_CTRL_REGS_MAX_SIZE];
	u32 ctrl_regs_size;

	u8 data_regs[RMI_F30_CTRL_MAX_BYTES];
	u16 *gpioled_key_map;

	struct input_dev *input;

	struct rmi_function *f03;
	bool trackstick_buttons;
};

static int rmi_f30_read_control_parameters(struct rmi_function *fn,
						struct f30_data *f30)
{
	int error;

	error = rmi_read_block(fn->rmi_dev, fn->fd.control_base_addr,
			       f30->ctrl_regs, f30->ctrl_regs_size);
	if (error) {
		dev_err(&fn->dev,
			"%s: Could not read control registers at 0x%x: %d\n",
			__func__, fn->fd.control_base_addr, error);
		return error;
	}

	return 0;
}

static void rmi_f30_report_button(struct rmi_function *fn,
				  struct f30_data *f30, unsigned int button)
{
	unsigned int reg_num = button >> 3;
	unsigned int bit_num = button & 0x07;
	u16 key_code = f30->gpioled_key_map[button];
	bool key_down = !(f30->data_regs[reg_num] & BIT(bit_num));

	if (f30->trackstick_buttons &&
	    button >= TRACKSTICK_RANGE_START &&
	    button <= TRACKSTICK_RANGE_END) {
		rmi_f03_overwrite_button(f30->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(f30->input, key_code, key_down);
	}
}

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

	/* Read the gpi led data. */
	if (drvdata->attn_data.data) {
		if (drvdata->attn_data.size < f30->register_count) {
			dev_warn(&fn->dev,
				 "F30 interrupted, but data is missing\n");
			return IRQ_HANDLED;
		}
		memcpy(f30->data_regs, drvdata->attn_data.data,
			f30->register_count);
		drvdata->attn_data.data += f30->register_count;
		drvdata->attn_data.size -= f30->register_count;

Annotation

Implementation Notes