Skip to content

Commit bf93349

Browse files
refractionwaredtor
authored andcommitted
Input: mms114 - add support for touch keys
MELFAS MMS114 and similar touchscreens have support for touch keys. Enable support of them in the driver. The keycodes to emit can be controlled by the linux,keycodes DT property. Sidenote - the MAX_TOUCHKEYS value is set to 15, as that's the maximum value that the ID field can contain. I don't have access to any datasheets that could confirm or deny whether this is accurate. Most downstream drivers I've been able to find only use up to 2 keys (though I did find a driver that mentioned up to 4, but only 2 were used). They don't have any checks for a maximum keycode value, it is just extracted from the ID bits (0xf mask). The drivers I've been able to find also don't use touch ID 0; I assume that it is never used, so the keycodes provided in the DT start from touch ID 1. I suppose this is in-line with the regular behavior for touch IDs in touchscreen events, as there the provided touch ID is always lowered by 1, which would cause an overflow if it was 0... Just in case, we quietly return if the touch ID is set to 0 here. The implementation of the linux,keycodes property handling code was adapted from the msg2638 driver. Signed-off-by: Artur Weber <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Dmitry Torokhov <[email protected]>
1 parent 21c133b commit bf93349

File tree

1 file changed

+81
-7
lines changed

1 file changed

+81
-7
lines changed

drivers/input/touchscreen/mms114.c

Lines changed: 81 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
/* Touchscreen absolute values */
4343
#define MMS114_MAX_AREA 0xff
4444

45+
#define MMS114_MAX_TOUCHKEYS 15
4546
#define MMS114_MAX_TOUCH 10
4647
#define MMS114_EVENT_SIZE 8
4748
#define MMS136_EVENT_SIZE 6
@@ -69,6 +70,9 @@ struct mms114_data {
6970
unsigned int contact_threshold;
7071
unsigned int moving_threshold;
7172

73+
u32 keycodes[MMS114_MAX_TOUCHKEYS];
74+
int num_keycodes;
75+
7276
/* Use cache data for mode control register(write only) */
7377
u8 cache_mode_control;
7478
};
@@ -166,11 +170,6 @@ static void mms114_process_mt(struct mms114_data *data, struct mms114_touch *tou
166170
return;
167171
}
168172

169-
if (touch->type != MMS114_TYPE_TOUCHSCREEN) {
170-
dev_err(&client->dev, "Wrong touch type (%d)\n", touch->type);
171-
return;
172-
}
173-
174173
id = touch->id - 1;
175174
x = touch->x_lo | touch->x_hi << 8;
176175
y = touch->y_lo | touch->y_hi << 8;
@@ -190,9 +189,33 @@ static void mms114_process_mt(struct mms114_data *data, struct mms114_touch *tou
190189
}
191190
}
192191

192+
static void mms114_process_touchkey(struct mms114_data *data,
193+
struct mms114_touch *touch)
194+
{
195+
struct i2c_client *client = data->client;
196+
struct input_dev *input_dev = data->input_dev;
197+
unsigned int keycode_id;
198+
199+
if (touch->id == 0)
200+
return;
201+
202+
if (touch->id > data->num_keycodes) {
203+
dev_err(&client->dev, "Wrong touch id for touchkey (%d)\n",
204+
touch->id);
205+
return;
206+
}
207+
208+
keycode_id = touch->id - 1;
209+
dev_dbg(&client->dev, "keycode id: %d, pressed: %d\n", keycode_id,
210+
touch->pressed);
211+
212+
input_report_key(input_dev, data->keycodes[keycode_id], touch->pressed);
213+
}
214+
193215
static irqreturn_t mms114_interrupt(int irq, void *dev_id)
194216
{
195217
struct mms114_data *data = dev_id;
218+
struct i2c_client *client = data->client;
196219
struct input_dev *input_dev = data->input_dev;
197220
struct mms114_touch touch[MMS114_MAX_TOUCH];
198221
int packet_size;
@@ -222,8 +245,22 @@ static irqreturn_t mms114_interrupt(int irq, void *dev_id)
222245
if (error < 0)
223246
goto out;
224247

225-
for (index = 0; index < touch_size; index++)
226-
mms114_process_mt(data, touch + index);
248+
for (index = 0; index < touch_size; index++) {
249+
switch (touch[index].type) {
250+
case MMS114_TYPE_TOUCHSCREEN:
251+
mms114_process_mt(data, touch + index);
252+
break;
253+
254+
case MMS114_TYPE_TOUCHKEY:
255+
mms114_process_touchkey(data, touch + index);
256+
break;
257+
258+
default:
259+
dev_err(&client->dev, "Wrong touch type (%d)\n",
260+
touch[index].type);
261+
break;
262+
}
263+
}
227264

228265
input_mt_report_pointer_emulation(data->input_dev, true);
229266
input_sync(data->input_dev);
@@ -445,6 +482,7 @@ static int mms114_probe(struct i2c_client *client)
445482
struct input_dev *input_dev;
446483
const void *match_data;
447484
int error;
485+
int i;
448486

449487
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
450488
dev_err(&client->dev, "Not supported I2C adapter\n");
@@ -468,6 +506,42 @@ static int mms114_probe(struct i2c_client *client)
468506

469507
data->type = (enum mms_type)match_data;
470508

509+
data->num_keycodes = device_property_count_u32(&client->dev,
510+
"linux,keycodes");
511+
if (data->num_keycodes == -EINVAL) {
512+
data->num_keycodes = 0;
513+
} else if (data->num_keycodes < 0) {
514+
dev_err(&client->dev,
515+
"Unable to parse linux,keycodes property: %d\n",
516+
data->num_keycodes);
517+
return data->num_keycodes;
518+
} else if (data->num_keycodes > MMS114_MAX_TOUCHKEYS) {
519+
dev_warn(&client->dev,
520+
"Found %d linux,keycodes but max is %d, ignoring the rest\n",
521+
data->num_keycodes, MMS114_MAX_TOUCHKEYS);
522+
data->num_keycodes = MMS114_MAX_TOUCHKEYS;
523+
}
524+
525+
if (data->num_keycodes > 0) {
526+
error = device_property_read_u32_array(&client->dev,
527+
"linux,keycodes",
528+
data->keycodes,
529+
data->num_keycodes);
530+
if (error) {
531+
dev_err(&client->dev,
532+
"Unable to read linux,keycodes values: %d\n",
533+
error);
534+
return error;
535+
}
536+
537+
input_dev->keycode = data->keycodes;
538+
input_dev->keycodemax = data->num_keycodes;
539+
input_dev->keycodesize = sizeof(data->keycodes[0]);
540+
for (i = 0; i < data->num_keycodes; i++)
541+
input_set_capability(input_dev,
542+
EV_KEY, data->keycodes[i]);
543+
}
544+
471545
input_set_capability(input_dev, EV_ABS, ABS_MT_POSITION_X);
472546
input_set_capability(input_dev, EV_ABS, ABS_MT_POSITION_Y);
473547
input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, 255, 0, 0);

0 commit comments

Comments
 (0)