drivers/input/misc/max7360-rotary.c

Source file repositories/reference/linux-study-clean/drivers/input/misc/max7360-rotary.c

File Facts

System
Linux kernel
Corpus path
drivers/input/misc/max7360-rotary.c
Extension
.c
Size
5340 bytes
Lines
193
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 max7360_rotary {
	struct input_dev *input;
	struct regmap *regmap;
	unsigned int debounce_ms;

	unsigned int pos;

	u32 steps;
	u32 axis;
	bool relative_axis;
	bool rollover;
};

static void max7360_rotary_report_event(struct max7360_rotary *max7360_rotary, int steps)
{
	if (max7360_rotary->relative_axis) {
		input_report_rel(max7360_rotary->input, max7360_rotary->axis, steps);
	} else {
		int pos = max7360_rotary->pos;
		int maxval = max7360_rotary->steps;

		/*
		 * Add steps to the position.
		 * Make sure added steps are always in ]-maxval; maxval[
		 * interval, so (pos + maxval) is always >= 0.
		 * Then set back pos to the [0; maxval[ interval.
		 */
		pos += steps % maxval;
		if (max7360_rotary->rollover)
			pos = (pos + maxval) % maxval;
		else
			pos = clamp(pos, 0, maxval - 1);

		max7360_rotary->pos = pos;
		input_report_abs(max7360_rotary->input, max7360_rotary->axis, max7360_rotary->pos);
	}

	input_sync(max7360_rotary->input);
}

static irqreturn_t max7360_rotary_irq(int irq, void *data)
{
	struct max7360_rotary *max7360_rotary = data;
	struct device *dev = max7360_rotary->input->dev.parent;
	unsigned int val;
	int error;

	error = regmap_read(max7360_rotary->regmap, MAX7360_REG_RTR_CNT, &val);
	if (error < 0) {
		dev_err(dev, "Failed to read rotary counter\n");
		return IRQ_NONE;
	}

	if (val == 0)
		return IRQ_NONE;

	max7360_rotary_report_event(max7360_rotary, sign_extend32(val, 7));

	return IRQ_HANDLED;
}

static int max7360_rotary_hw_init(struct max7360_rotary *max7360_rotary)
{
	struct device *dev = max7360_rotary->input->dev.parent;
	int val;
	int error;

	val = FIELD_PREP(MAX7360_ROT_DEBOUNCE, max7360_rotary->debounce_ms) |
	      FIELD_PREP(MAX7360_ROT_INTCNT, 1) | MAX7360_ROT_INTCNT_DLY;
	error = regmap_write(max7360_rotary->regmap, MAX7360_REG_RTRCFG, val);
	if (error)
		dev_err(dev, "Failed to set max7360 rotary encoder configuration\n");

	return error;
}

static int max7360_rotary_probe(struct platform_device *pdev)
{
	struct max7360_rotary *max7360_rotary;
	struct device *dev = &pdev->dev;
	struct input_dev *input;
	struct regmap *regmap;
	int irq;
	int error;

	regmap = dev_get_regmap(dev->parent, NULL);
	if (!regmap)
		return dev_err_probe(dev, -ENODEV, "Could not get parent regmap\n");

	irq = fwnode_irq_get_byname(dev_fwnode(dev->parent), "inti");

Annotation

Implementation Notes