Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 <aweber.kernel@gmail.com>
Link: https://lore.kernel.org/r/20230714100424.29798-3-aweber.kernel@gmail.com
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>

authored by

Artur Weber and committed by
Dmitry Torokhov
bf93349b 21c133be

+81 -7
+81 -7
drivers/input/touchscreen/mms114.c
··· 42 42 /* Touchscreen absolute values */ 43 43 #define MMS114_MAX_AREA 0xff 44 44 45 + #define MMS114_MAX_TOUCHKEYS 15 45 46 #define MMS114_MAX_TOUCH 10 46 47 #define MMS114_EVENT_SIZE 8 47 48 #define MMS136_EVENT_SIZE 6 ··· 69 68 enum mms_type type; 70 69 unsigned int contact_threshold; 71 70 unsigned int moving_threshold; 71 + 72 + u32 keycodes[MMS114_MAX_TOUCHKEYS]; 73 + int num_keycodes; 72 74 73 75 /* Use cache data for mode control register(write only) */ 74 76 u8 cache_mode_control; ··· 170 166 return; 171 167 } 172 168 173 - if (touch->type != MMS114_TYPE_TOUCHSCREEN) { 174 - dev_err(&client->dev, "Wrong touch type (%d)\n", touch->type); 175 - return; 176 - } 177 - 178 169 id = touch->id - 1; 179 170 x = touch->x_lo | touch->x_hi << 8; 180 171 y = touch->y_lo | touch->y_hi << 8; ··· 189 190 } 190 191 } 191 192 193 + static void mms114_process_touchkey(struct mms114_data *data, 194 + struct mms114_touch *touch) 195 + { 196 + struct i2c_client *client = data->client; 197 + struct input_dev *input_dev = data->input_dev; 198 + unsigned int keycode_id; 199 + 200 + if (touch->id == 0) 201 + return; 202 + 203 + if (touch->id > data->num_keycodes) { 204 + dev_err(&client->dev, "Wrong touch id for touchkey (%d)\n", 205 + touch->id); 206 + return; 207 + } 208 + 209 + keycode_id = touch->id - 1; 210 + dev_dbg(&client->dev, "keycode id: %d, pressed: %d\n", keycode_id, 211 + touch->pressed); 212 + 213 + input_report_key(input_dev, data->keycodes[keycode_id], touch->pressed); 214 + } 215 + 192 216 static irqreturn_t mms114_interrupt(int irq, void *dev_id) 193 217 { 194 218 struct mms114_data *data = dev_id; 219 + struct i2c_client *client = data->client; 195 220 struct input_dev *input_dev = data->input_dev; 196 221 struct mms114_touch touch[MMS114_MAX_TOUCH]; 197 222 int packet_size; ··· 245 222 if (error < 0) 246 223 goto out; 247 224 248 - for (index = 0; index < touch_size; index++) 249 - mms114_process_mt(data, touch + index); 225 + for (index = 0; index < touch_size; index++) { 226 + switch (touch[index].type) { 227 + case MMS114_TYPE_TOUCHSCREEN: 228 + mms114_process_mt(data, touch + index); 229 + break; 230 + 231 + case MMS114_TYPE_TOUCHKEY: 232 + mms114_process_touchkey(data, touch + index); 233 + break; 234 + 235 + default: 236 + dev_err(&client->dev, "Wrong touch type (%d)\n", 237 + touch[index].type); 238 + break; 239 + } 240 + } 250 241 251 242 input_mt_report_pointer_emulation(data->input_dev, true); 252 243 input_sync(data->input_dev); ··· 482 445 struct input_dev *input_dev; 483 446 const void *match_data; 484 447 int error; 448 + int i; 485 449 486 450 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { 487 451 dev_err(&client->dev, "Not supported I2C adapter\n"); ··· 505 467 return -EINVAL; 506 468 507 469 data->type = (enum mms_type)match_data; 470 + 471 + data->num_keycodes = device_property_count_u32(&client->dev, 472 + "linux,keycodes"); 473 + if (data->num_keycodes == -EINVAL) { 474 + data->num_keycodes = 0; 475 + } else if (data->num_keycodes < 0) { 476 + dev_err(&client->dev, 477 + "Unable to parse linux,keycodes property: %d\n", 478 + data->num_keycodes); 479 + return data->num_keycodes; 480 + } else if (data->num_keycodes > MMS114_MAX_TOUCHKEYS) { 481 + dev_warn(&client->dev, 482 + "Found %d linux,keycodes but max is %d, ignoring the rest\n", 483 + data->num_keycodes, MMS114_MAX_TOUCHKEYS); 484 + data->num_keycodes = MMS114_MAX_TOUCHKEYS; 485 + } 486 + 487 + if (data->num_keycodes > 0) { 488 + error = device_property_read_u32_array(&client->dev, 489 + "linux,keycodes", 490 + data->keycodes, 491 + data->num_keycodes); 492 + if (error) { 493 + dev_err(&client->dev, 494 + "Unable to read linux,keycodes values: %d\n", 495 + error); 496 + return error; 497 + } 498 + 499 + input_dev->keycode = data->keycodes; 500 + input_dev->keycodemax = data->num_keycodes; 501 + input_dev->keycodesize = sizeof(data->keycodes[0]); 502 + for (i = 0; i < data->num_keycodes; i++) 503 + input_set_capability(input_dev, 504 + EV_KEY, data->keycodes[i]); 505 + } 508 506 509 507 input_set_capability(input_dev, EV_ABS, ABS_MT_POSITION_X); 510 508 input_set_capability(input_dev, EV_ABS, ABS_MT_POSITION_Y);