drivers/input/keyboard/adp5585-keys.c

Source file repositories/reference/linux-study-clean/drivers/input/keyboard/adp5585-keys.c

File Facts

System
Linux kernel
Corpus path
drivers/input/keyboard/adp5585-keys.c
Extension
.c
Size
10054 bytes
Lines
372
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 adp5585_kpad_chip {
	u8 key_ev_min;
	u8 key_ev_max;
	u8 max_rows;
	u8 max_cols;
};

struct adp5585_kpad {
	const struct adp5585_kpad_chip *info;
	struct notifier_block nb;
	struct input_dev *input;
	unsigned short keycode[ADP5589_MAX_KEYMAPSIZE];
	struct device *dev;
	unsigned long keypad;
	int row_shift;
};

static int adp5585_keys_validate_events(const struct adp5585_kpad *kpad,
					const u32 *events, u32 n_events)
{
	unsigned int ev;
	u32 row, col;

	for (ev = 0; ev < n_events; ev++) {
		if (events[ev] < kpad->info->key_ev_min ||
		    events[ev] > kpad->info->key_ev_max)
			continue;

		/*
		 * if the event is to be generated by the keymap, we need to make
		 * sure that the pins are part of it!
		 */
		row = (events[ev] - 1) / kpad->info->max_cols;
		col = (events[ev] - 1) % kpad->info->max_cols;

		if (test_bit(row, &kpad->keypad) &&
		    test_bit(col + kpad->info->max_rows, &kpad->keypad))
			continue;

		return dev_err_probe(kpad->dev, -EINVAL,
				     "Invalid unlock/reset event(%u) not used in the keypad\n",
				     events[ev]);
	}

	return 0;
}

static int adp5585_keys_check_special_events(const struct adp5585_dev *adp5585,
					     const struct adp5585_kpad *kpad)
{
	int error;

	error = adp5585_keys_validate_events(kpad, adp5585->unlock_keys,
					     adp5585->nkeys_unlock);
	if (error)
		return error;

	error = adp5585_keys_validate_events(kpad, adp5585->reset1_keys,
					     adp5585->nkeys_reset1);
	if (error)
		return error;

	return adp5585_keys_validate_events(kpad, adp5585->reset2_keys,
					    adp5585->nkeys_reset2);
}

static void adp5585_keys_pins_free(void *data)
{
	struct adp5585_kpad *kpad = data;
	struct adp5585_dev *adp5585 = dev_get_drvdata(kpad->dev->parent);
	unsigned int pin;

	for_each_set_bit(pin, &kpad->keypad, adp5585->n_pins)
		clear_bit(pin, adp5585->pin_usage);
}

static int adp5585_keys_parse_fw(const struct adp5585_dev *adp5585,
				 struct adp5585_kpad *kpad)
{
	struct device *dev = kpad->dev;
	u32 cols = 0, rows = 0, pin;
	int error, n_pins;

	/*
	 * We do not check for errors (or no value) since the input device is
	 * only added if this property is present in the first place.
	 */
	n_pins = device_property_count_u32(dev, "adi,keypad-pins");
	if (n_pins > adp5585->n_pins)
		return dev_err_probe(dev, -EINVAL,

Annotation

Implementation Notes