File Index
Files and directories
Sign in
FILE

rmi_f1a.c

File preview with syntax highlighting.

linux-6.19.14/drivers/input/rmi4/rmi_f1a.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Copyright (c) 2025 André Apitzsch <git@apitzsch.eu>
  4 */
  5
  6#include <linux/input.h>
  7#include <linux/property.h>
  8#include "rmi_driver.h"
  9
 10struct f1a_data {
 11	struct input_dev *input;
 12
 13	u32 *keymap;
 14	unsigned int num_keys;
 15};
 16
 17static int rmi_f1a_parse_device_properties(struct rmi_function *fn, struct f1a_data *f1a)
 18{
 19	static const char buttons_property[] = "linux,keycodes";
 20	struct device *dev = &fn->dev;
 21	u32 *buttonmap;
 22	int n_keys;
 23	int error;
 24
 25	if (!device_property_present(dev, buttons_property))
 26		return 0;
 27
 28	n_keys = device_property_count_u32(dev, buttons_property);
 29	if (n_keys <= 0) {
 30		error = n_keys < 0 ? n_keys : -EINVAL;
 31		dev_err(dev, "Invalid/malformed '%s' property: %d\n",
 32			buttons_property, error);
 33		return error;
 34	}
 35
 36	buttonmap = devm_kmalloc_array(dev, n_keys, sizeof(*buttonmap),
 37				       GFP_KERNEL);
 38	if (!buttonmap)
 39		return -ENOMEM;
 40
 41	error = device_property_read_u32_array(dev, buttons_property,
 42					       buttonmap, n_keys);
 43	if (error) {
 44		dev_err(dev, "Failed to parse '%s' property: %d\n",
 45			buttons_property, error);
 46		return error;
 47	}
 48
 49	f1a->keymap = buttonmap;
 50	f1a->num_keys = n_keys;
 51
 52	return 0;
 53}
 54
 55static irqreturn_t rmi_f1a_attention(int irq, void *ctx)
 56{
 57	struct rmi_function *fn = ctx;
 58	struct f1a_data *f1a = dev_get_drvdata(&fn->dev);
 59	char button_bitmask;
 60	int key;
 61	int error;
 62
 63	error = rmi_read_block(fn->rmi_dev, fn->fd.data_base_addr,
 64			       &button_bitmask, sizeof(button_bitmask));
 65	if (error) {
 66		dev_err(&fn->dev, "Failed to read object data. Code: %d.\n",
 67			error);
 68		return IRQ_RETVAL(error);
 69	}
 70
 71	for (key = 0; key < f1a->num_keys; key++)
 72		input_report_key(f1a->input, f1a->keymap[key],
 73				 button_bitmask & BIT(key));
 74
 75	return IRQ_HANDLED;
 76}
 77
 78static int rmi_f1a_config(struct rmi_function *fn)
 79{
 80	struct f1a_data *f1a = dev_get_drvdata(&fn->dev);
 81	struct rmi_driver *drv = fn->rmi_dev->driver;
 82
 83	if (f1a->num_keys)
 84		drv->set_irq_bits(fn->rmi_dev, fn->irq_mask);
 85
 86	return 0;
 87}
 88
 89static int rmi_f1a_initialize(struct rmi_function *fn, struct f1a_data *f1a)
 90{
 91	int error;
 92	int i;
 93
 94	error = rmi_f1a_parse_device_properties(fn, f1a);
 95	if (error)
 96		return error;
 97
 98	for (i = 0; i < f1a->num_keys; i++)
 99		input_set_capability(f1a->input, EV_KEY, f1a->keymap[i]);
100
101	f1a->input->keycode = f1a->keymap;
102	f1a->input->keycodemax = f1a->num_keys;
103	f1a->input->keycodesize = sizeof(f1a->keymap[0]);
104
105	return 0;
106}
107
108static int rmi_f1a_probe(struct rmi_function *fn)
109{
110	struct rmi_device *rmi_dev = fn->rmi_dev;
111	struct rmi_driver_data *drv_data = dev_get_drvdata(&rmi_dev->dev);
112	struct f1a_data *f1a;
113	int error;
114
115	if (!drv_data->input) {
116		dev_info(&fn->dev, "F1A: no input device found, ignoring\n");
117		return -ENXIO;
118	}
119
120	f1a = devm_kzalloc(&fn->dev, sizeof(*f1a), GFP_KERNEL);
121	if (!f1a)
122		return -ENOMEM;
123
124	f1a->input = drv_data->input;
125
126	error = rmi_f1a_initialize(fn, f1a);
127	if (error)
128		return error;
129
130	dev_set_drvdata(&fn->dev, f1a);
131
132	return 0;
133}
134
135struct rmi_function_handler rmi_f1a_handler = {
136	.driver = {
137		.name = "rmi4_f1a",
138	},
139	.func = 0x1a,
140	.probe = rmi_f1a_probe,
141	.config = rmi_f1a_config,
142	.attention = rmi_f1a_attention,
143};
~/ Read-only file preview.