From bb546136cc0b07b3f4dc972a196650d50fe1aaaa Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Tue, 9 May 2017 17:48:45 -0700 Subject: Input: use seq_putc() in input_seq_print_bitmap() Switch to using seq_putc() when printing a single character '0'. Signed-off-by: Markus Elfring Signed-off-by: Dmitry Torokhov --- drivers/input/input.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/input') diff --git a/drivers/input/input.c b/drivers/input/input.c index 067d648028a2..0d204b841575 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -1126,7 +1126,7 @@ static void input_seq_print_bitmap(struct seq_file *seq, const char *name, * If no output was produced print a single 0. */ if (skip_empty) - seq_puts(seq, "0"); + seq_putc(seq, '0'); seq_putc(seq, '\n'); } -- cgit v1.2.3 From 63c9576544718a949460865588981b70bb717020 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Tue, 9 May 2017 17:49:59 -0700 Subject: Input: use seq_puts() in input_devices_seq_show() Use seq_puts() when printing a string which does not contain a data format specification. Signed-off-by: Markus Elfring Signed-off-by: Dmitry Torokhov --- drivers/input/input.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/input') diff --git a/drivers/input/input.c b/drivers/input/input.c index 0d204b841575..067a6edd643c 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -1144,7 +1144,7 @@ static int input_devices_seq_show(struct seq_file *seq, void *v) seq_printf(seq, "P: Phys=%s\n", dev->phys ? dev->phys : ""); seq_printf(seq, "S: Sysfs=%s\n", path ? path : ""); seq_printf(seq, "U: Uniq=%s\n", dev->uniq ? dev->uniq : ""); - seq_printf(seq, "H: Handlers="); + seq_puts(seq, "H: Handlers="); list_for_each_entry(handle, &dev->h_list, d_node) seq_printf(seq, "%s ", handle->name); -- cgit v1.2.3 From c3f6f8612bdab5959950a58291bd61d1d42d996b Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Tue, 9 May 2017 17:51:30 -0700 Subject: Input: switch to using sizeof(*type) when allocating memory Instead of specifying type explicitly, derive it from the type of pointer when allocating memory, which is considered safer practice. Signed-off-by: Markus Elfring Signed-off-by: Dmitry Torokhov --- drivers/input/input.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/input.c b/drivers/input/input.c index 067a6edd643c..7e6842bd525c 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -481,7 +481,7 @@ EXPORT_SYMBOL(input_inject_event); void input_alloc_absinfo(struct input_dev *dev) { if (!dev->absinfo) - dev->absinfo = kcalloc(ABS_CNT, sizeof(struct input_absinfo), + dev->absinfo = kcalloc(ABS_CNT, sizeof(*dev->absinfo), GFP_KERNEL); WARN(!dev->absinfo, "%s(): kcalloc() failed?\n", __func__); @@ -1783,7 +1783,7 @@ struct input_dev *input_allocate_device(void) static atomic_t input_no = ATOMIC_INIT(-1); struct input_dev *dev; - dev = kzalloc(sizeof(struct input_dev), GFP_KERNEL); + dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (dev) { dev->dev.type = &input_dev_type; dev->dev.class = &input_class; @@ -1849,7 +1849,7 @@ struct input_dev *devm_input_allocate_device(struct device *dev) struct input_devres *devres; devres = devres_alloc(devm_input_device_release, - sizeof(struct input_devres), GFP_KERNEL); + sizeof(*devres), GFP_KERNEL); if (!devres) return NULL; @@ -2099,7 +2099,7 @@ int input_register_device(struct input_dev *dev) if (dev->devres_managed) { devres = devres_alloc(devm_input_device_unregister, - sizeof(struct input_devres), GFP_KERNEL); + sizeof(*devres), GFP_KERNEL); if (!devres) return -ENOMEM; -- cgit v1.2.3 From c5928551fd41b2eecdad78fa2be2a4a13ed5fde9 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 19 Dec 2014 12:57:49 -0800 Subject: Input: elan_i2c - check if device is there before really probing Before trying to properly initialize the touchpad and generate bunch of errors, let's first see it there is anything at the given address. If we get error, fail silently with -ENXIO. Reviewed-by: Guenter Roeck Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/elan_i2c_core.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/input') diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c index d5ab9ddef3e3..551ad2934fa7 100644 --- a/drivers/input/mouse/elan_i2c_core.c +++ b/drivers/input/mouse/elan_i2c_core.c @@ -1077,6 +1077,13 @@ static int elan_probe(struct i2c_client *client, return error; } + /* Make sure there is something at this address */ + error = i2c_smbus_read_byte(client); + if (error < 0) { + dev_dbg(&client->dev, "nothing at this address: %d\n", error); + return -ENXIO; + } + /* Initialize the touchpad. */ error = elan_initialize(data); if (error) -- cgit v1.2.3 From a2eaf299d134cfe780c68c771f88d81516c1e70d Mon Sep 17 00:00:00 2001 From: KT Liao Date: Sun, 27 Nov 2016 20:59:29 -0800 Subject: Input: elan_i2c - add support for fetching chip type on newer hardware Newer Elantech hardware requires different way of fetching chip type and version data. Signed-off-by: KT Liao Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/elan_i2c.h | 3 +- drivers/input/mouse/elan_i2c_core.c | 33 +++++++++++++---- drivers/input/mouse/elan_i2c_i2c.c | 71 ++++++++++++++++++++++++++++++++---- drivers/input/mouse/elan_i2c_smbus.c | 9 ++++- 4 files changed, 99 insertions(+), 17 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/mouse/elan_i2c.h b/drivers/input/mouse/elan_i2c.h index c0ec26118732..61c202436250 100644 --- a/drivers/input/mouse/elan_i2c.h +++ b/drivers/input/mouse/elan_i2c.h @@ -58,7 +58,7 @@ struct elan_transport_ops { int (*get_version)(struct i2c_client *client, bool iap, u8 *version); int (*get_sm_version)(struct i2c_client *client, - u8* ic_type, u8 *version); + u16 *ic_type, u8 *version); int (*get_checksum)(struct i2c_client *client, bool iap, u16 *csum); int (*get_product_id)(struct i2c_client *client, u16 *id); @@ -82,6 +82,7 @@ struct elan_transport_ops { int (*get_report)(struct i2c_client *client, u8 *report); int (*get_pressure_adjustment)(struct i2c_client *client, int *adjustment); + int (*get_pattern)(struct i2c_client *client, u8 *pattern); }; extern const struct elan_transport_ops elan_smbus_ops, elan_i2c_ops; diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c index 551ad2934fa7..3b616cb7c67f 100644 --- a/drivers/input/mouse/elan_i2c_core.c +++ b/drivers/input/mouse/elan_i2c_core.c @@ -5,7 +5,7 @@ * * Author: 林政維 (Duson Lin) * Author: KT Liao - * Version: 1.6.2 + * Version: 1.6.3 * * Based on cyapa driver: * copyright (c) 2011-2012 Cypress Semiconductor, Inc. @@ -41,7 +41,7 @@ #include "elan_i2c.h" #define DRIVER_NAME "elan_i2c" -#define ELAN_DRIVER_VERSION "1.6.2" +#define ELAN_DRIVER_VERSION "1.6.3" #define ELAN_VENDOR_ID 0x04f3 #define ETP_MAX_PRESSURE 255 #define ETP_FWIDTH_REDUCE 90 @@ -78,6 +78,7 @@ struct elan_tp_data { unsigned int x_res; unsigned int y_res; + u8 pattern; u16 product_id; u8 fw_version; u8 sm_version; @@ -85,7 +86,7 @@ struct elan_tp_data { u16 fw_checksum; int pressure_adjustment; u8 mode; - u8 ic_type; + u16 ic_type; u16 fw_validpage_count; u16 fw_signature_address; @@ -96,10 +97,10 @@ struct elan_tp_data { bool baseline_ready; }; -static int elan_get_fwinfo(u8 iap_version, u16 *validpage_count, +static int elan_get_fwinfo(u16 ic_type, u16 *validpage_count, u16 *signature_address) { - switch (iap_version) { + switch (ic_type) { case 0x00: case 0x06: case 0x08: @@ -119,6 +120,9 @@ static int elan_get_fwinfo(u8 iap_version, u16 *validpage_count, case 0x0E: *validpage_count = 640; break; + case 0x10: + *validpage_count = 1024; + break; default: /* unknown ic type clear value */ *validpage_count = 0; @@ -305,6 +309,7 @@ static int elan_initialize(struct elan_tp_data *data) static int elan_query_device_info(struct elan_tp_data *data) { int error; + u16 ic_type; error = data->ops->get_version(data->client, false, &data->fw_version); if (error) @@ -324,7 +329,16 @@ static int elan_query_device_info(struct elan_tp_data *data) if (error) return error; - error = elan_get_fwinfo(data->iap_version, &data->fw_validpage_count, + error = data->ops->get_pattern(data->client, &data->pattern); + if (error) + return error; + + if (data->pattern == 0x01) + ic_type = data->ic_type; + else + ic_type = data->iap_version; + + error = elan_get_fwinfo(ic_type, &data->fw_validpage_count, &data->fw_signature_address); if (error) dev_warn(&data->client->dev, @@ -1108,10 +1122,13 @@ static int elan_probe(struct i2c_client *client, "Elan Touchpad Extra Information:\n" " Max ABS X,Y: %d,%d\n" " Width X,Y: %d,%d\n" - " Resolution X,Y: %d,%d (dots/mm)\n", + " Resolution X,Y: %d,%d (dots/mm)\n" + " ic type: 0x%x\n" + " info pattern: 0x%x\n", data->max_x, data->max_y, data->width_x, data->width_y, - data->x_res, data->y_res); + data->x_res, data->y_res, + data->ic_type, data->pattern); /* Set up input device properties based on queried parameters. */ error = elan_setup_input_device(data); diff --git a/drivers/input/mouse/elan_i2c_i2c.c b/drivers/input/mouse/elan_i2c_i2c.c index a679e56c44cd..3be75c6e8090 100644 --- a/drivers/input/mouse/elan_i2c_i2c.c +++ b/drivers/input/mouse/elan_i2c_i2c.c @@ -34,9 +34,12 @@ #define ETP_I2C_DESC_CMD 0x0001 #define ETP_I2C_REPORT_DESC_CMD 0x0002 #define ETP_I2C_STAND_CMD 0x0005 +#define ETP_I2C_PATTERN_CMD 0x0100 #define ETP_I2C_UNIQUEID_CMD 0x0101 #define ETP_I2C_FW_VERSION_CMD 0x0102 -#define ETP_I2C_SM_VERSION_CMD 0x0103 +#define ETP_I2C_IC_TYPE_CMD 0x0103 +#define ETP_I2C_OSM_VERSION_CMD 0x0103 +#define ETP_I2C_NSM_VERSION_CMD 0x0104 #define ETP_I2C_XY_TRACENUM_CMD 0x0105 #define ETP_I2C_MAX_X_AXIS_CMD 0x0106 #define ETP_I2C_MAX_Y_AXIS_CMD 0x0107 @@ -239,12 +242,34 @@ static int elan_i2c_get_baseline_data(struct i2c_client *client, return 0; } +static int elan_i2c_get_pattern(struct i2c_client *client, u8 *pattern) +{ + int error; + u8 val[3]; + + error = elan_i2c_read_cmd(client, ETP_I2C_PATTERN_CMD, val); + if (error) { + dev_err(&client->dev, "failed to get pattern: %d\n", error); + return error; + } + *pattern = val[1]; + + return 0; +} + static int elan_i2c_get_version(struct i2c_client *client, bool iap, u8 *version) { int error; + u8 pattern_ver; u8 val[3]; + error = elan_i2c_get_pattern(client, &pattern_ver); + if (error) { + dev_err(&client->dev, "failed to get pattern version\n"); + return error; + } + error = elan_i2c_read_cmd(client, iap ? ETP_I2C_IAP_VERSION_CMD : ETP_I2C_FW_VERSION_CMD, @@ -255,24 +280,54 @@ static int elan_i2c_get_version(struct i2c_client *client, return error; } - *version = val[0]; + if (pattern_ver == 0x01) + *version = iap ? val[1] : val[0]; + else + *version = val[0]; return 0; } static int elan_i2c_get_sm_version(struct i2c_client *client, - u8 *ic_type, u8 *version) + u16 *ic_type, u8 *version) { int error; + u8 pattern_ver; u8 val[3]; - error = elan_i2c_read_cmd(client, ETP_I2C_SM_VERSION_CMD, val); + error = elan_i2c_get_pattern(client, &pattern_ver); if (error) { - dev_err(&client->dev, "failed to get SM version: %d\n", error); + dev_err(&client->dev, "failed to get pattern version\n"); return error; } - *version = val[0]; - *ic_type = val[1]; + if (pattern_ver == 0x01) { + error = elan_i2c_read_cmd(client, ETP_I2C_IC_TYPE_CMD, val); + if (error) { + dev_err(&client->dev, "failed to get ic type: %d\n", + error); + return error; + } + *ic_type = be16_to_cpup((__be16 *)val); + + error = elan_i2c_read_cmd(client, ETP_I2C_NSM_VERSION_CMD, + val); + if (error) { + dev_err(&client->dev, "failed to get SM version: %d\n", + error); + return error; + } + *version = val[1]; + } else { + error = elan_i2c_read_cmd(client, ETP_I2C_OSM_VERSION_CMD, val); + if (error) { + dev_err(&client->dev, "failed to get SM version: %d\n", + error); + return error; + } + *version = val[0]; + *ic_type = val[1]; + } + return 0; } @@ -639,5 +694,7 @@ const struct elan_transport_ops elan_i2c_ops = { .write_fw_block = elan_i2c_write_fw_block, .finish_fw_update = elan_i2c_finish_fw_update, + .get_pattern = elan_i2c_get_pattern, + .get_report = elan_i2c_get_report, }; diff --git a/drivers/input/mouse/elan_i2c_smbus.c b/drivers/input/mouse/elan_i2c_smbus.c index e23b2495d52e..df7a57ca7331 100644 --- a/drivers/input/mouse/elan_i2c_smbus.c +++ b/drivers/input/mouse/elan_i2c_smbus.c @@ -166,7 +166,7 @@ static int elan_smbus_get_version(struct i2c_client *client, } static int elan_smbus_get_sm_version(struct i2c_client *client, - u8 *ic_type, u8 *version) + u16 *ic_type, u8 *version) { int error; u8 val[3]; @@ -495,6 +495,12 @@ static int elan_smbus_finish_fw_update(struct i2c_client *client, return 0; } +static int elan_smbus_get_pattern(struct i2c_client *client, u8 *pattern) +{ + *pattern = 0; + return 0; +} + const struct elan_transport_ops elan_smbus_ops = { .initialize = elan_smbus_initialize, .sleep_control = elan_smbus_sleep_control, @@ -524,4 +530,5 @@ const struct elan_transport_ops elan_smbus_ops = { .finish_fw_update = elan_smbus_finish_fw_update, .get_report = elan_smbus_get_report, + .get_pattern = elan_smbus_get_pattern, }; -- cgit v1.2.3 From d899520b0431e70279bfb5066ecb6dc91d0b7072 Mon Sep 17 00:00:00 2001 From: KT Liao Date: Mon, 12 Dec 2016 11:03:42 -0800 Subject: Input: elantech - force relative mode on a certain module One of Elan modules with sample version is 0x74 and hw_version is 0x03 has a bug in absolute mode implementation, so let it run in default PS/2 relative mode. Signed-off-by: KT Liao Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/elantech.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/input') diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index efc8ec342351..3dbab0727376 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c @@ -1687,6 +1687,17 @@ int elantech_init(struct psmouse *psmouse) etd->samples[0], etd->samples[1], etd->samples[2]); } + if (etd->samples[1] == 0x74 && etd->hw_version == 0x03) { + /* + * This module has a bug which makes absolute mode + * unusable, so let's abort so we'll be using standard + * PS/2 protocol. + */ + psmouse_info(psmouse, + "absolute mode broken, forcing standard PS/2 protocol\n"); + goto init_fail; + } + if (elantech_set_absolute_mode(psmouse)) { psmouse_err(psmouse, "failed to put touchpad into absolute mode.\n"); -- cgit v1.2.3 From f81126b0b67c864b0b3d614d8adadc3a37ba5209 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 22 May 2017 16:24:22 -0700 Subject: Input: lm8323 - move header file out of I2C realm include/linux/i2c is not for client devices. Move the header file to a more appropriate location. Signed-off-by: Wolfram Sang Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/lm8323.c | 2 +- include/linux/i2c/lm8323.h | 46 ------------------------------------ include/linux/platform_data/lm8323.h | 46 ++++++++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 47 deletions(-) delete mode 100644 include/linux/i2c/lm8323.h create mode 100644 include/linux/platform_data/lm8323.h (limited to 'drivers/input') diff --git a/drivers/input/keyboard/lm8323.c b/drivers/input/keyboard/lm8323.c index 21bea52d4365..04a5d7e134d7 100644 --- a/drivers/input/keyboard/lm8323.c +++ b/drivers/input/keyboard/lm8323.c @@ -30,8 +30,8 @@ #include #include #include +#include #include -#include #include /* Commands to send to the chip. */ diff --git a/include/linux/i2c/lm8323.h b/include/linux/i2c/lm8323.h deleted file mode 100644 index 478d668bc590..000000000000 --- a/include/linux/i2c/lm8323.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * lm8323.h - Configuration for LM8323 keypad driver. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation (version 2 of the License only). - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __LINUX_LM8323_H -#define __LINUX_LM8323_H - -#include - -/* - * Largest keycode that the chip can send, plus one, - * so keys can be mapped directly at the index of the - * LM8323 keycode instead of subtracting one. - */ -#define LM8323_KEYMAP_SIZE (0x7f + 1) - -#define LM8323_NUM_PWMS 3 - -struct lm8323_platform_data { - int debounce_time; /* Time to watch for key bouncing, in ms. */ - int active_time; /* Idle time until sleep, in ms. */ - - int size_x; - int size_y; - bool repeat; - const unsigned short *keymap; - - const char *pwm_names[LM8323_NUM_PWMS]; - - const char *name; /* Device name. */ -}; - -#endif /* __LINUX_LM8323_H */ diff --git a/include/linux/platform_data/lm8323.h b/include/linux/platform_data/lm8323.h new file mode 100644 index 000000000000..478d668bc590 --- /dev/null +++ b/include/linux/platform_data/lm8323.h @@ -0,0 +1,46 @@ +/* + * lm8323.h - Configuration for LM8323 keypad driver. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation (version 2 of the License only). + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __LINUX_LM8323_H +#define __LINUX_LM8323_H + +#include + +/* + * Largest keycode that the chip can send, plus one, + * so keys can be mapped directly at the index of the + * LM8323 keycode instead of subtracting one. + */ +#define LM8323_KEYMAP_SIZE (0x7f + 1) + +#define LM8323_NUM_PWMS 3 + +struct lm8323_platform_data { + int debounce_time; /* Time to watch for key bouncing, in ms. */ + int active_time; /* Idle time until sleep, in ms. */ + + int size_x; + int size_y; + bool repeat; + const unsigned short *keymap; + + const char *pwm_names[LM8323_NUM_PWMS]; + + const char *name; /* Device name. */ +}; + +#endif /* __LINUX_LM8323_H */ -- cgit v1.2.3 From 8cd9ab9e19b8cf23a7cae503af81ae70154e7956 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 22 May 2017 16:26:56 -0700 Subject: Input: mcs - move header file out of I2C realm include/linux/i2c is not for client devices. Move the header file to a more appropriate location. Signed-off-by: Wolfram Sang Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/mcs_touchkey.c | 2 +- drivers/input/touchscreen/mcs5000_ts.c | 2 +- include/linux/i2c/mcs.h | 35 ---------------------------------- include/linux/platform_data/mcs.h | 35 ++++++++++++++++++++++++++++++++++ 4 files changed, 37 insertions(+), 37 deletions(-) delete mode 100644 include/linux/i2c/mcs.h create mode 100644 include/linux/platform_data/mcs.h (limited to 'drivers/input') diff --git a/drivers/input/keyboard/mcs_touchkey.c b/drivers/input/keyboard/mcs_touchkey.c index 31090d71a685..be56d4f262a7 100644 --- a/drivers/input/keyboard/mcs_touchkey.c +++ b/drivers/input/keyboard/mcs_touchkey.c @@ -13,11 +13,11 @@ #include #include -#include #include #include #include #include +#include #include /* MCS5000 Touchkey */ diff --git a/drivers/input/touchscreen/mcs5000_ts.c b/drivers/input/touchscreen/mcs5000_ts.c index 90fc07dc98a6..8868573133ab 100644 --- a/drivers/input/touchscreen/mcs5000_ts.c +++ b/drivers/input/touchscreen/mcs5000_ts.c @@ -15,10 +15,10 @@ #include #include -#include #include #include #include +#include #include /* Registers */ diff --git a/include/linux/i2c/mcs.h b/include/linux/i2c/mcs.h deleted file mode 100644 index 61bb18a4fd3c..000000000000 --- a/include/linux/i2c/mcs.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2009 - 2010 Samsung Electronics Co.Ltd - * Author: Joonyoung Shim - * Author: HeungJun Kim - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - */ - -#ifndef __LINUX_MCS_H -#define __LINUX_MCS_H - -#define MCS_KEY_MAP(v, c) ((((v) & 0xff) << 16) | ((c) & 0xffff)) -#define MCS_KEY_VAL(v) (((v) >> 16) & 0xff) -#define MCS_KEY_CODE(v) ((v) & 0xffff) - -struct mcs_platform_data { - void (*poweron)(bool); - void (*cfg_pin)(void); - - /* touchscreen */ - unsigned int x_size; - unsigned int y_size; - - /* touchkey */ - const u32 *keymap; - unsigned int keymap_size; - unsigned int key_maxval; - bool no_autorepeat; -}; - -#endif /* __LINUX_MCS_H */ diff --git a/include/linux/platform_data/mcs.h b/include/linux/platform_data/mcs.h new file mode 100644 index 000000000000..61bb18a4fd3c --- /dev/null +++ b/include/linux/platform_data/mcs.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2009 - 2010 Samsung Electronics Co.Ltd + * Author: Joonyoung Shim + * Author: HeungJun Kim + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#ifndef __LINUX_MCS_H +#define __LINUX_MCS_H + +#define MCS_KEY_MAP(v, c) ((((v) & 0xff) << 16) | ((c) & 0xffff)) +#define MCS_KEY_VAL(v) (((v) >> 16) & 0xff) +#define MCS_KEY_CODE(v) ((v) & 0xffff) + +struct mcs_platform_data { + void (*poweron)(bool); + void (*cfg_pin)(void); + + /* touchscreen */ + unsigned int x_size; + unsigned int y_size; + + /* touchkey */ + const u32 *keymap; + unsigned int keymap_size; + unsigned int key_maxval; + bool no_autorepeat; +}; + +#endif /* __LINUX_MCS_H */ -- cgit v1.2.3 From 0d846a4cbbcbf81e527542d15e165b8f774bace5 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 22 May 2017 16:28:42 -0700 Subject: Input: mms114 - move header file out of I2C realm include/linux/i2c is not for client devices. Move the header file to a more appropriate location. Signed-off-by: Wolfram Sang Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/mms114.c | 2 +- include/linux/i2c/mms114.h | 24 ------------------------ include/linux/platform_data/mms114.h | 24 ++++++++++++++++++++++++ 3 files changed, 25 insertions(+), 25 deletions(-) delete mode 100644 include/linux/i2c/mms114.h create mode 100644 include/linux/platform_data/mms114.h (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/mms114.c b/drivers/input/touchscreen/mms114.c index 1fafc9f57af6..e5eeb6311f7d 100644 --- a/drivers/input/touchscreen/mms114.c +++ b/drivers/input/touchscreen/mms114.c @@ -11,9 +11,9 @@ #include #include #include -#include #include #include +#include #include #include diff --git a/include/linux/i2c/mms114.h b/include/linux/i2c/mms114.h deleted file mode 100644 index 5722ebfb2738..000000000000 --- a/include/linux/i2c/mms114.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2012 Samsung Electronics Co.Ltd - * Author: Joonyoung Shim - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundationr - */ - -#ifndef __LINUX_MMS114_H -#define __LINUX_MMS114_H - -struct mms114_platform_data { - unsigned int x_size; - unsigned int y_size; - unsigned int contact_threshold; - unsigned int moving_threshold; - bool x_invert; - bool y_invert; - - void (*cfg_pin)(bool); -}; - -#endif /* __LINUX_MMS114_H */ diff --git a/include/linux/platform_data/mms114.h b/include/linux/platform_data/mms114.h new file mode 100644 index 000000000000..5722ebfb2738 --- /dev/null +++ b/include/linux/platform_data/mms114.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2012 Samsung Electronics Co.Ltd + * Author: Joonyoung Shim + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundationr + */ + +#ifndef __LINUX_MMS114_H +#define __LINUX_MMS114_H + +struct mms114_platform_data { + unsigned int x_size; + unsigned int y_size; + unsigned int contact_threshold; + unsigned int moving_threshold; + bool x_invert; + bool y_invert; + + void (*cfg_pin)(bool); +}; + +#endif /* __LINUX_MMS114_H */ -- cgit v1.2.3 From 8fd708157a592a376c4d0b3b2ba23b9e9f79caa5 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 22 May 2017 16:30:04 -0700 Subject: Input: tsc2007 - move header file out of I2C realm include/linux/i2c is not for client devices. Move the header file to a more appropriate location. Signed-off-by: Wolfram Sang Acked-by: Lee Jones Signed-off-by: Dmitry Torokhov --- arch/sh/boards/mach-ecovec24/setup.c | 2 +- drivers/input/touchscreen/tsc2007_core.c | 2 +- drivers/mfd/timberdale.c | 2 +- include/linux/i2c/tsc2007.h | 22 ---------------------- include/linux/platform_data/tsc2007.h | 22 ++++++++++++++++++++++ 5 files changed, 25 insertions(+), 25 deletions(-) delete mode 100644 include/linux/i2c/tsc2007.h create mode 100644 include/linux/platform_data/tsc2007.h (limited to 'drivers/input') diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c index 6d612792f6b8..1faf6cb93dcb 100644 --- a/arch/sh/boards/mach-ecovec24/setup.c +++ b/arch/sh/boards/mach-ecovec24/setup.c @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/input/touchscreen/tsc2007_core.c b/drivers/input/touchscreen/tsc2007_core.c index fc7384936011..8342e0c48a53 100644 --- a/drivers/input/touchscreen/tsc2007_core.c +++ b/drivers/input/touchscreen/tsc2007_core.c @@ -25,9 +25,9 @@ #include #include #include -#include #include #include +#include #include "tsc2007.h" int tsc2007_xfer(struct tsc2007 *tsc, u8 cmd) diff --git a/drivers/mfd/timberdale.c b/drivers/mfd/timberdale.c index c9339f85359b..cd4a6d7d6750 100644 --- a/drivers/mfd/timberdale.c +++ b/drivers/mfd/timberdale.c @@ -32,13 +32,13 @@ #include #include #include -#include #include #include #include #include +#include #include #include diff --git a/include/linux/i2c/tsc2007.h b/include/linux/i2c/tsc2007.h deleted file mode 100644 index 4f35b6ad3889..000000000000 --- a/include/linux/i2c/tsc2007.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef __LINUX_I2C_TSC2007_H -#define __LINUX_I2C_TSC2007_H - -/* linux/i2c/tsc2007.h */ - -struct tsc2007_platform_data { - u16 model; /* 2007. */ - u16 x_plate_ohms; /* must be non-zero value */ - u16 max_rt; /* max. resistance above which samples are ignored */ - unsigned long poll_period; /* time (in ms) between samples */ - int fuzzx; /* fuzz factor for X, Y and pressure axes */ - int fuzzy; - int fuzzz; - - int (*get_pendown_state)(struct device *); - /* If needed, clear 2nd level interrupt source */ - void (*clear_penirq)(void); - int (*init_platform_hw)(void); - void (*exit_platform_hw)(void); -}; - -#endif diff --git a/include/linux/platform_data/tsc2007.h b/include/linux/platform_data/tsc2007.h new file mode 100644 index 000000000000..c2d3aa1dadd4 --- /dev/null +++ b/include/linux/platform_data/tsc2007.h @@ -0,0 +1,22 @@ +#ifndef __LINUX_I2C_TSC2007_H +#define __LINUX_I2C_TSC2007_H + +/* linux/platform_data/tsc2007.h */ + +struct tsc2007_platform_data { + u16 model; /* 2007. */ + u16 x_plate_ohms; /* must be non-zero value */ + u16 max_rt; /* max. resistance above which samples are ignored */ + unsigned long poll_period; /* time (in ms) between samples */ + int fuzzx; /* fuzz factor for X, Y and pressure axes */ + int fuzzy; + int fuzzz; + + int (*get_pendown_state)(struct device *); + /* If needed, clear 2nd level interrupt source */ + void (*clear_penirq)(void); + int (*init_platform_hw)(void); + void (*exit_platform_hw)(void); +}; + +#endif -- cgit v1.2.3 From 79ffd5f98c11572c004d52f7ecd270ab680a7f72 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 26 May 2017 16:55:10 -0700 Subject: Input: sparse-keymap - remove sparse_keymap_free() Now that all users of sparse_keymap_free() are gone we can remove the stub. Signed-off-by: Dmitry Torokhov --- drivers/input/sparse-keymap.c | 14 -------------- include/linux/input/sparse-keymap.h | 1 - 2 files changed, 15 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/sparse-keymap.c b/drivers/input/sparse-keymap.c index 12a3ad83296d..bb0349fa64bc 100644 --- a/drivers/input/sparse-keymap.c +++ b/drivers/input/sparse-keymap.c @@ -223,20 +223,6 @@ int sparse_keymap_setup(struct input_dev *dev, } EXPORT_SYMBOL(sparse_keymap_setup); -/** - * sparse_keymap_free - free memory allocated for sparse keymap - * @dev: Input device using sparse keymap - * - * This function used to free memory allocated by sparse keymap - * in an input device that was set up by sparse_keymap_setup(). - * Since sparse_keymap_setup() now uses a managed allocation for the - * keymap copy, use of this function is deprecated. - */ -void sparse_keymap_free(struct input_dev *dev) -{ -} -EXPORT_SYMBOL(sparse_keymap_free); - /** * sparse_keymap_report_entry - report event corresponding to given key entry * @dev: Input device for which event should be reported diff --git a/include/linux/input/sparse-keymap.h b/include/linux/input/sparse-keymap.h index 52db62064c6e..c7346e33d958 100644 --- a/include/linux/input/sparse-keymap.h +++ b/include/linux/input/sparse-keymap.h @@ -51,7 +51,6 @@ struct key_entry *sparse_keymap_entry_from_keycode(struct input_dev *dev, int sparse_keymap_setup(struct input_dev *dev, const struct key_entry *keymap, int (*setup)(struct input_dev *, struct key_entry *)); -void sparse_keymap_free(struct input_dev *dev); void sparse_keymap_report_entry(struct input_dev *dev, const struct key_entry *ke, unsigned int value, bool autorelease); -- cgit v1.2.3 From 32a62b9441d840e676d55b45468371c252a4fa01 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 29 May 2017 20:21:52 -0700 Subject: Input: synaptics-rmi4 - change a char type to u8 Smatch doesn't like when we use "%02X" to print char types because, what about if it's a negative? Signed-off-by: Dan Carpenter Signed-off-by: Dmitry Torokhov --- drivers/input/rmi4/rmi_f34v7.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/input') diff --git a/drivers/input/rmi4/rmi_f34v7.c b/drivers/input/rmi4/rmi_f34v7.c index 10c0d11b72c9..ae2db1c3aebf 100644 --- a/drivers/input/rmi4/rmi_f34v7.c +++ b/drivers/input/rmi4/rmi_f34v7.c @@ -518,7 +518,7 @@ static int rmi_f34v7_read_queries(struct f34_data *f34) query_1_7.partition_support[1] & HAS_GUEST_CODE; if (query_0 & HAS_CONFIG_ID) { - char f34_ctrl[CONFIG_ID_SIZE]; + u8 f34_ctrl[CONFIG_ID_SIZE]; int i = 0; u8 *p = f34->configuration_id; *p = '\0'; -- cgit v1.2.3 From 49bbbfa8d27a227521a9e07cb1612f60e8f0e8ff Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 29 May 2017 20:22:34 -0700 Subject: Input: synaptics-rmi4 - use %phN to form F34 configuration ID Instead of printing bytes one by one, let's use %phN to print the buffer in one go. Also use hweight8 to count number of partitions instead of inspecting it bit by bit. Reviewed-by: Benjamin Tissoires Tested-by: Nick Dyer Signed-off-by: Dmitry Torokhov --- drivers/input/rmi4/rmi_f34v7.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/rmi4/rmi_f34v7.c b/drivers/input/rmi4/rmi_f34v7.c index ae2db1c3aebf..3991d2943660 100644 --- a/drivers/input/rmi4/rmi_f34v7.c +++ b/drivers/input/rmi4/rmi_f34v7.c @@ -9,13 +9,14 @@ * the Free Software Foundation. */ +#include #include #include #include -#include #include #include #include +#include #include "rmi_driver.h" #include "rmi_f34.h" @@ -464,7 +465,7 @@ static int rmi_f34v7_read_queries_bl_version(struct f34_data *f34) static int rmi_f34v7_read_queries(struct f34_data *f34) { int ret; - int i, j; + int i; u8 base; int offset; u8 *ptable; @@ -519,9 +520,6 @@ static int rmi_f34v7_read_queries(struct f34_data *f34) if (query_0 & HAS_CONFIG_ID) { u8 f34_ctrl[CONFIG_ID_SIZE]; - int i = 0; - u8 *p = f34->configuration_id; - *p = '\0'; ret = rmi_read_block(f34->fn->rmi_dev, f34->fn->fd.control_base_addr, @@ -531,13 +529,11 @@ static int rmi_f34v7_read_queries(struct f34_data *f34) return ret; /* Eat leading zeros */ - while (i < sizeof(f34_ctrl) && !f34_ctrl[i]) - i++; + for (i = 0; i < sizeof(f34_ctrl) - 1 && !f34_ctrl[i]; i++) + /* Empty */; - for (; i < sizeof(f34_ctrl); i++) - p += snprintf(p, f34->configuration_id - + sizeof(f34->configuration_id) - p, - "%02X", f34_ctrl[i]); + snprintf(f34->configuration_id, sizeof(f34->configuration_id), + "%*phN", (int)sizeof(f34_ctrl) - i, f34_ctrl + i); rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev, "Configuration ID: %s\n", f34->configuration_id); @@ -545,9 +541,7 @@ static int rmi_f34v7_read_queries(struct f34_data *f34) f34->v7.partitions = 0; for (i = 0; i < sizeof(query_1_7.partition_support); i++) - for (j = 0; j < 8; j++) - if (query_1_7.partition_support[i] & (1 << j)) - f34->v7.partitions++; + f34->v7.partitions += hweight8(query_1_7.partition_support[i]); rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev, "%s: Supported partitions: %*ph\n", __func__, sizeof(query_1_7.partition_support), -- cgit v1.2.3 From 58be76896786b512e97cb743ec271648623a7107 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 2 Jun 2017 17:51:42 -0700 Subject: Input: axp20x-pek - add wakeup support At least on devices with the AXP288 PMIC the device is expected to wakeup from suspend when the power-button gets pressed, add support for this. Signed-off-by: Hans de Goede Signed-off-by: Dmitry Torokhov --- drivers/input/misc/axp20x-pek.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'drivers/input') diff --git a/drivers/input/misc/axp20x-pek.c b/drivers/input/misc/axp20x-pek.c index f11807db6979..d3e9ce27a2be 100644 --- a/drivers/input/misc/axp20x-pek.c +++ b/drivers/input/misc/axp20x-pek.c @@ -253,6 +253,9 @@ static int axp20x_pek_probe_input_device(struct axp20x_pek *axp20x_pek, return error; } + if (axp20x_pek->axp20x->variant == AXP288_ID) + enable_irq_wake(axp20x_pek->irq_dbr); + return 0; } @@ -301,10 +304,35 @@ static int axp20x_pek_probe(struct platform_device *pdev) return 0; } +static int __maybe_unused axp20x_pek_resume_noirq(struct device *dev) +{ + struct axp20x_pek *axp20x_pek = dev_get_drvdata(dev); + + if (axp20x_pek->axp20x->variant != AXP288_ID) + return 0; + + /* + * Clear interrupts from button presses during suspend, to avoid + * a wakeup power-button press getting reported to userspace. + */ + regmap_write(axp20x_pek->axp20x->regmap, + AXP20X_IRQ1_STATE + AXP288_IRQ_POKN / 8, + BIT(AXP288_IRQ_POKN % 8)); + + return 0; +} + +static const struct dev_pm_ops axp20x_pek_pm_ops = { +#ifdef CONFIG_PM_SLEEP + .resume_noirq = axp20x_pek_resume_noirq, +#endif +}; + static struct platform_driver axp20x_pek_driver = { .probe = axp20x_pek_probe, .driver = { .name = "axp20x-pek", + .pm = &axp20x_pek_pm_ops, }, }; module_platform_driver(axp20x_pek_driver); -- cgit v1.2.3 From 086cebfa72fa22e1e49f251d33fe1ceaab4af2d4 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Tue, 30 May 2017 09:44:28 -0700 Subject: Input: s3c2410_ts - handle return value of clk_prepare_enable clk_prepare_enable() can fail here and we must check its return value. Signed-off-by: Arvind Yadav Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/s3c2410_ts.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/s3c2410_ts.c b/drivers/input/touchscreen/s3c2410_ts.c index 41d58e88cc8a..3b3db8c868e0 100644 --- a/drivers/input/touchscreen/s3c2410_ts.c +++ b/drivers/input/touchscreen/s3c2410_ts.c @@ -264,7 +264,11 @@ static int s3c2410ts_probe(struct platform_device *pdev) return -ENOENT; } - clk_prepare_enable(ts.clock); + ret = clk_prepare_enable(ts.clock); + if (ret) { + dev_err(dev, "Failed! to enabled clocks\n"); + goto err_clk_get; + } dev_dbg(dev, "got and enabled clocks\n"); ts.irq_tc = ret = platform_get_irq(pdev, 0); @@ -353,7 +357,9 @@ static int s3c2410ts_probe(struct platform_device *pdev) err_iomap: iounmap(ts.io); err_clk: + clk_disable_unprepare(ts.clock); del_timer_sync(&touch_timer); + err_clk_get: clk_put(ts.clock); return ret; } -- cgit v1.2.3 From 131b3de7016b73fca1aba8ffb528217ac95b2505 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 5 Jun 2017 14:48:44 -0700 Subject: Input: add D-Link DIR-685 touchkeys driver This adds support for the D-Link DIR-685 touchkeys found in the router with this name. The vendor code calles this a "touchpad" but we are registering it here under its real name. Signed-off-by: Linus Walleij Acked-by: Rob Herring Signed-off-by: Dmitry Torokhov --- .../bindings/input/dlink,dir685-touchkeys.txt | 21 +++ MAINTAINERS | 6 + drivers/input/keyboard/Kconfig | 11 ++ drivers/input/keyboard/Makefile | 1 + drivers/input/keyboard/dlink-dir685-touchkeys.c | 155 +++++++++++++++++++++ 5 files changed, 194 insertions(+) create mode 100644 Documentation/devicetree/bindings/input/dlink,dir685-touchkeys.txt create mode 100644 drivers/input/keyboard/dlink-dir685-touchkeys.c (limited to 'drivers/input') diff --git a/Documentation/devicetree/bindings/input/dlink,dir685-touchkeys.txt b/Documentation/devicetree/bindings/input/dlink,dir685-touchkeys.txt new file mode 100644 index 000000000000..10dec1c57abf --- /dev/null +++ b/Documentation/devicetree/bindings/input/dlink,dir685-touchkeys.txt @@ -0,0 +1,21 @@ +* D-Link DIR-685 Touchkeys + +This is a I2C one-off touchkey controller based on the Cypress Semiconductor +CY8C214 MCU with some firmware in its internal 8KB flash. The circuit +board inside the router is named E119921. + +The touchkey device node should be placed inside an I2C bus node. + +Required properties: +- compatible: must be "dlink,dir685-touchkeys" +- reg: the I2C address of the touchkeys +- interrupts: reference to the interrupt number + +Example: + +touchkeys@26 { + compatible = "dlink,dir685-touchkeys"; + reg = <0x26>; + interrupt-parent = <&gpio0>; + interrupts = <17 IRQ_TYPE_EDGE_FALLING>; +}; diff --git a/MAINTAINERS b/MAINTAINERS index 053c3bdd1fe5..98861181fb2a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3786,6 +3786,12 @@ S: Supported F: drivers/input/touchscreen/cyttsp* F: include/linux/input/cyttsp.h +D-LINK DIR-685 TOUCHKEYS DRIVER +M: Linus Walleij +L: linux-input@vger.kernel.org +S: Supported +F: drivers/input/dlink-dir685-touchkeys.c + DALLAS/MAXIM DS1685-FAMILY REAL TIME CLOCK M: Joshua Kinard S: Maintained diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 97acd6524ad7..4c4ab1ced235 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -178,6 +178,17 @@ config KEYBOARD_CLPS711X To compile this driver as a module, choose M here: the module will be called clps711x-keypad. +config KEYBOARD_DLINK_DIR685 + tristate "D-Link DIR-685 touchkeys support" + depends on I2C + default ARCH_GEMINI + help + If you say yes here you get support for the D-Link DIR-685 + touchkeys. + + To compile this driver as a module, choose M here: the + module will be called dlink-dir685-touchkeys. + config KEYBOARD_LKKBD tristate "DECstation/VAXstation LK201/LK401 keyboard" select SERIO diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 7d9acff819a7..d2338bacdad1 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -17,6 +17,7 @@ obj-$(CONFIG_KEYBOARD_CAP11XX) += cap11xx.o obj-$(CONFIG_KEYBOARD_CLPS711X) += clps711x-keypad.o obj-$(CONFIG_KEYBOARD_CROS_EC) += cros_ec_keyb.o obj-$(CONFIG_KEYBOARD_DAVINCI) += davinci_keyscan.o +obj-$(CONFIG_KEYBOARD_DLINK_DIR685) += dlink-dir685-touchkeys.o obj-$(CONFIG_KEYBOARD_EP93XX) += ep93xx_keypad.o obj-$(CONFIG_KEYBOARD_GOLDFISH_EVENTS) += goldfish_events.o obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o diff --git a/drivers/input/keyboard/dlink-dir685-touchkeys.c b/drivers/input/keyboard/dlink-dir685-touchkeys.c new file mode 100644 index 000000000000..88e321b76397 --- /dev/null +++ b/drivers/input/keyboard/dlink-dir685-touchkeys.c @@ -0,0 +1,155 @@ +/* + * D-Link DIR-685 router I2C-based Touchkeys input driver + * Copyright (C) 2017 Linus Walleij + * + * This is a one-off touchkey controller based on the Cypress Semiconductor + * CY8C214 MCU with some firmware in its internal 8KB flash. The circuit + * board inside the router is named E119921 + */ + +#include +#include +#include +#include +#include +#include +#include + +struct dir685_touchkeys { + struct device *dev; + struct i2c_client *client; + struct input_dev *input; + unsigned long cur_key; + u16 codes[7]; +}; + +static irqreturn_t dir685_tk_irq_thread(int irq, void *data) +{ + struct dir685_touchkeys *tk = data; + const int num_bits = min_t(int, ARRAY_SIZE(tk->codes), 16); + unsigned long changed; + u8 buf[6]; + unsigned long key; + int i; + int err; + + memset(buf, 0, sizeof(buf)); + err = i2c_master_recv(tk->client, buf, sizeof(buf)); + if (err != sizeof(buf)) { + dev_err(tk->dev, "short read %d\n", err); + return IRQ_HANDLED; + } + + dev_dbg(tk->dev, "IN: %*ph\n", (int)sizeof(buf), buf); + key = be16_to_cpup((__be16 *) &buf[4]); + + /* Figure out if any bits went high or low since last message */ + changed = tk->cur_key ^ key; + for_each_set_bit(i, &changed, num_bits) { + dev_dbg(tk->dev, "key %d is %s\n", i, + test_bit(i, &key) ? "down" : "up"); + input_report_key(tk->input, tk->codes[i], test_bit(i, &key)); + } + + /* Store currently down keys */ + tk->cur_key = key; + input_sync(tk->input); + + return IRQ_HANDLED; +} + +static int dir685_tk_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct dir685_touchkeys *tk; + struct device *dev = &client->dev; + u8 bl_data[] = { 0xa7, 0x40 }; + int err; + int i; + + tk = devm_kzalloc(&client->dev, sizeof(*tk), GFP_KERNEL); + if (!tk) + return -ENOMEM; + + tk->input = devm_input_allocate_device(dev); + if (!tk->input) + return -ENOMEM; + + tk->client = client; + tk->dev = dev; + + tk->input->keycodesize = sizeof(u16); + tk->input->keycodemax = ARRAY_SIZE(tk->codes); + tk->input->keycode = tk->codes; + tk->codes[0] = KEY_UP; + tk->codes[1] = KEY_DOWN; + tk->codes[2] = KEY_LEFT; + tk->codes[3] = KEY_RIGHT; + tk->codes[4] = KEY_ENTER; + tk->codes[5] = KEY_WPS_BUTTON; + /* + * This key appears in the vendor driver, but I have + * not been able to activate it. + */ + tk->codes[6] = KEY_RESERVED; + + __set_bit(EV_KEY, tk->input->evbit); + for (i = 0; i < ARRAY_SIZE(tk->codes); i++) + __set_bit(tk->codes[i], tk->input->keybit); + __clear_bit(KEY_RESERVED, tk->input->keybit); + + tk->input->name = "D-Link DIR-685 touchkeys"; + tk->input->id.bustype = BUS_I2C; + + err = input_register_device(tk->input); + if (err) + return err; + + /* Set the brightness to max level */ + err = i2c_master_send(client, bl_data, sizeof(bl_data)); + if (err != sizeof(bl_data)) + dev_warn(tk->dev, "error setting brightness level\n"); + + if (!client->irq) { + dev_err(dev, "no IRQ on the I2C device\n"); + return -ENODEV; + } + err = devm_request_threaded_irq(dev, client->irq, + NULL, dir685_tk_irq_thread, + IRQF_ONESHOT, + "dir685-tk", tk); + if (err) { + dev_err(dev, "can't request IRQ\n"); + return err; + } + + return 0; +} + +static const struct i2c_device_id dir685_tk_id[] = { + { "dir685tk", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, dir685_tk_id); + +#ifdef CONFIG_OF +static const struct of_device_id dir685_tk_of_match[] = { + { .compatible = "dlink,dir685-touchkeys" }, + {}, +}; +MODULE_DEVICE_TABLE(of, dir685_tk_of_match); +#endif + +static struct i2c_driver dir685_tk_i2c_driver = { + .driver = { + .name = "dlin-dir685-touchkeys", + .of_match_table = of_match_ptr(dir685_tk_of_match), + }, + .probe = dir685_tk_probe, + .id_table = dir685_tk_id, +}; +module_i2c_driver(dir685_tk_i2c_driver); + +MODULE_AUTHOR("Linus Walleij "); +MODULE_DESCRIPTION("D-Link DIR-685 touchkeys driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 78bcac7b2ae1e4f6e96c68ff353c140669ea231c Mon Sep 17 00:00:00 2001 From: Andi Shyti Date: Mon, 5 Jun 2017 15:29:18 -0700 Subject: Input: add support for the STMicroelectronics FingerTip touchscreen The stmfts (ST-Microelectronics FingerTip S) touchscreen device is a capacitive multi-touch controller mainly for mobile use. It's connected through i2c bus at the address 0x49 and it interfaces with userspace through input event interface. At the current state it provides a touchscreen multitouch functionality up to 10 fingers. Each finger is enumerated with a distinctive id (from 0 to 9). If enabled the device can support single "touch" hovering, by providing three coordinates, x, y and distance. It is possible to select the touchkey functionality which provides a basic two keys interface for "home" and "back" menu, typical in mobile phones. Signed-off-by: Andi Shyti Reviewed-by: Javier Martinez Canillas Acked-by: Rob Herring Signed-off-by: Dmitry Torokhov --- .../bindings/input/touchscreen/st,stmfts.txt | 43 ++ drivers/input/touchscreen/Kconfig | 11 + drivers/input/touchscreen/Makefile | 1 + drivers/input/touchscreen/stmfts.c | 822 +++++++++++++++++++++ 4 files changed, 877 insertions(+) create mode 100644 Documentation/devicetree/bindings/input/touchscreen/st,stmfts.txt create mode 100644 drivers/input/touchscreen/stmfts.c (limited to 'drivers/input') diff --git a/Documentation/devicetree/bindings/input/touchscreen/st,stmfts.txt b/Documentation/devicetree/bindings/input/touchscreen/st,stmfts.txt new file mode 100644 index 000000000000..9683595cd0f5 --- /dev/null +++ b/Documentation/devicetree/bindings/input/touchscreen/st,stmfts.txt @@ -0,0 +1,43 @@ +* ST-Microelectronics FingerTip touchscreen controller + +The ST-Microelectronics FingerTip device provides a basic touchscreen +functionality. Along with it the user can enable the touchkey which can work as +a basic HOME and BACK key for phones. + +The driver supports also hovering as an absolute single touch event with x, y, z +coordinates. + +Required properties: +- compatible : must be "st,stmfts" +- reg : I2C slave address, (e.g. 0x49) +- interrupt-parent : the phandle to the interrupt controller which provides + the interrupt +- interrupts : interrupt specification +- avdd-supply : analogic power supply +- vdd-supply : power supply +- touchscreen-size-x : see touchscreen.txt +- touchscreen-size-y : see touchscreen.txt + +Optional properties: +- touch-key-connected : specifies whether the touchkey feature is connected +- ledvdd-supply : power supply to the touch key leds + +Example: + +i2c@00000000 { + + /* ... */ + + touchscreen@49 { + compatible = "st,stmfts"; + reg = <0x49>; + interrupt-parent = <&gpa1>; + interrupts = <1 IRQ_TYPE_NONE>; + touchscreen-size-x = <1599>; + touchscreen-size-y = <2559>; + touch-key-connected; + avdd-supply = <&ldo30_reg>; + vdd-supply = <&ldo31_reg>; + ledvdd-supply = <&ldo33_reg>; + }; +}; diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index cf26ca49ae6d..64b30fe273fd 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -1114,6 +1114,17 @@ config TOUCHSCREEN_ST1232 To compile this driver as a module, choose M here: the module will be called st1232_ts. +config TOUCHSCREEN_STMFTS + tristate "STMicroelectronics STMFTS touchscreen" + depends on I2C + depends on LEDS_CLASS + help + Say Y here if you want support for STMicroelectronics + STMFTS touchscreen. + + To compile this driver as a module, choose M here: the + module will be called stmfts. + config TOUCHSCREEN_STMPE tristate "STMicroelectronics STMPE touchscreens" depends on MFD_STMPE diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 18e476948e44..6badce87037b 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -67,6 +67,7 @@ obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o obj-$(CONFIG_TOUCHSCREEN_SILEAD) += silead.o obj-$(CONFIG_TOUCHSCREEN_SIS_I2C) += sis_i2c.o obj-$(CONFIG_TOUCHSCREEN_ST1232) += st1232.o +obj-$(CONFIG_TOUCHSCREEN_STMFTS) += stmfts.o obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o obj-$(CONFIG_TOUCHSCREEN_SUN4I) += sun4i-ts.o obj-$(CONFIG_TOUCHSCREEN_SUR40) += sur40.o diff --git a/drivers/input/touchscreen/stmfts.c b/drivers/input/touchscreen/stmfts.c new file mode 100644 index 000000000000..802d0e82d034 --- /dev/null +++ b/drivers/input/touchscreen/stmfts.c @@ -0,0 +1,822 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * Author: Andi Shyti + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * STMicroelectronics FTS Touchscreen device driver + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* I2C commands */ +#define STMFTS_READ_INFO 0x80 +#define STMFTS_READ_STATUS 0x84 +#define STMFTS_READ_ONE_EVENT 0x85 +#define STMFTS_READ_ALL_EVENT 0x86 +#define STMFTS_LATEST_EVENT 0x87 +#define STMFTS_SLEEP_IN 0x90 +#define STMFTS_SLEEP_OUT 0x91 +#define STMFTS_MS_MT_SENSE_OFF 0x92 +#define STMFTS_MS_MT_SENSE_ON 0x93 +#define STMFTS_SS_HOVER_SENSE_OFF 0x94 +#define STMFTS_SS_HOVER_SENSE_ON 0x95 +#define STMFTS_MS_KEY_SENSE_OFF 0x9a +#define STMFTS_MS_KEY_SENSE_ON 0x9b +#define STMFTS_SYSTEM_RESET 0xa0 +#define STMFTS_CLEAR_EVENT_STACK 0xa1 +#define STMFTS_FULL_FORCE_CALIBRATION 0xa2 +#define STMFTS_MS_CX_TUNING 0xa3 +#define STMFTS_SS_CX_TUNING 0xa4 + +/* events */ +#define STMFTS_EV_NO_EVENT 0x00 +#define STMFTS_EV_MULTI_TOUCH_DETECTED 0x02 +#define STMFTS_EV_MULTI_TOUCH_ENTER 0x03 +#define STMFTS_EV_MULTI_TOUCH_LEAVE 0x04 +#define STMFTS_EV_MULTI_TOUCH_MOTION 0x05 +#define STMFTS_EV_HOVER_ENTER 0x07 +#define STMFTS_EV_HOVER_LEAVE 0x08 +#define STMFTS_EV_HOVER_MOTION 0x09 +#define STMFTS_EV_KEY_STATUS 0x0e +#define STMFTS_EV_ERROR 0x0f +#define STMFTS_EV_CONTROLLER_READY 0x10 +#define STMFTS_EV_SLEEP_OUT_CONTROLLER_READY 0x11 +#define STMFTS_EV_STATUS 0x16 +#define STMFTS_EV_DEBUG 0xdb + +/* multi touch related event masks */ +#define STMFTS_MASK_EVENT_ID 0x0f +#define STMFTS_MASK_TOUCH_ID 0xf0 +#define STMFTS_MASK_LEFT_EVENT 0x0f +#define STMFTS_MASK_X_MSB 0x0f +#define STMFTS_MASK_Y_LSB 0xf0 + +/* key related event masks */ +#define STMFTS_MASK_KEY_NO_TOUCH 0x00 +#define STMFTS_MASK_KEY_MENU 0x01 +#define STMFTS_MASK_KEY_BACK 0x02 + +#define STMFTS_EVENT_SIZE 8 +#define STMFTS_STACK_DEPTH 32 +#define STMFTS_DATA_MAX_SIZE (STMFTS_EVENT_SIZE * STMFTS_STACK_DEPTH) +#define STMFTS_MAX_FINGERS 10 +#define STMFTS_DEV_NAME "stmfts" + +enum stmfts_regulators { + STMFTS_REGULATOR_VDD, + STMFTS_REGULATOR_AVDD, +}; + +struct stmfts_data { + struct i2c_client *client; + struct input_dev *input; + struct led_classdev led_cdev; + struct mutex mutex; + + struct touchscreen_properties prop; + + struct regulator_bulk_data regulators[2]; + + /* + * Presence of ledvdd will be used also to check + * whether the LED is supported. + */ + struct regulator *ledvdd; + + u16 chip_id; + u8 chip_ver; + u16 fw_ver; + u8 config_id; + u8 config_ver; + + u8 data[STMFTS_DATA_MAX_SIZE]; + + struct completion cmd_done; + + bool use_key; + bool led_status; + bool hover_enabled; + bool running; +}; + +static void stmfts_brightness_set(struct led_classdev *led_cdev, + enum led_brightness value) +{ + struct stmfts_data *sdata = container_of(led_cdev, + struct stmfts_data, led_cdev); + int err; + + if (value == sdata->led_status || !sdata->ledvdd) + return; + + if (!value) { + regulator_disable(sdata->ledvdd); + } else { + err = regulator_enable(sdata->ledvdd); + if (err) + dev_warn(&sdata->client->dev, + "failed to disable ledvdd regulator: %d\n", + err); + } + + sdata->led_status = value; +} + +static enum led_brightness stmfts_brightness_get(struct led_classdev *led_cdev) +{ + struct stmfts_data *sdata = container_of(led_cdev, + struct stmfts_data, led_cdev); + + return !!regulator_is_enabled(sdata->ledvdd); +} + +/* + * We can't simply use i2c_smbus_read_i2c_block_data because we + * need to read more than 255 bytes ( + */ +static int stmfts_read_events(struct stmfts_data *sdata) +{ + u8 cmd = STMFTS_READ_ALL_EVENT; + struct i2c_msg msgs[2] = { + { + .addr = sdata->client->addr, + .len = 1, + .buf = &cmd, + }, + { + .addr = sdata->client->addr, + .flags = I2C_M_RD, + .len = STMFTS_DATA_MAX_SIZE, + .buf = sdata->data, + }, + }; + int ret; + + ret = i2c_transfer(sdata->client->adapter, msgs, ARRAY_SIZE(msgs)); + if (ret < 0) + return ret; + + return ret == ARRAY_SIZE(msgs) ? 0 : -EIO; +} + +static void stmfts_report_contact_event(struct stmfts_data *sdata, + const u8 event[]) +{ + u8 slot_id = (event[0] & STMFTS_MASK_TOUCH_ID) >> 4; + u16 x = event[1] | ((event[2] & STMFTS_MASK_X_MSB) << 8); + u16 y = (event[2] >> 4) | (event[3] << 4); + u8 maj = event[4]; + u8 min = event[5]; + u8 orientation = event[6]; + u8 area = event[7]; + + input_mt_slot(sdata->input, slot_id); + + input_mt_report_slot_state(sdata->input, MT_TOOL_FINGER, true); + input_report_abs(sdata->input, ABS_MT_POSITION_X, x); + input_report_abs(sdata->input, ABS_MT_POSITION_Y, y); + input_report_abs(sdata->input, ABS_MT_TOUCH_MAJOR, maj); + input_report_abs(sdata->input, ABS_MT_TOUCH_MINOR, min); + input_report_abs(sdata->input, ABS_MT_PRESSURE, area); + input_report_abs(sdata->input, ABS_MT_ORIENTATION, orientation); + + input_sync(sdata->input); +} + +static void stmfts_report_contact_release(struct stmfts_data *sdata, + const u8 event[]) +{ + u8 slot_id = (event[0] & STMFTS_MASK_TOUCH_ID) >> 4; + + input_mt_slot(sdata->input, slot_id); + input_mt_report_slot_state(sdata->input, MT_TOOL_FINGER, false); + + input_sync(sdata->input); +} + +static void stmfts_report_hover_event(struct stmfts_data *sdata, + const u8 event[]) +{ + u16 x = (event[2] << 4) | (event[4] >> 4); + u16 y = (event[3] << 4) | (event[4] & STMFTS_MASK_Y_LSB); + u8 z = event[5]; + + input_report_abs(sdata->input, ABS_X, x); + input_report_abs(sdata->input, ABS_Y, y); + input_report_abs(sdata->input, ABS_DISTANCE, z); + + input_sync(sdata->input); +} + +static void stmfts_report_key_event(struct stmfts_data *sdata, const u8 event[]) +{ + switch (event[2]) { + case 0: + input_report_key(sdata->input, KEY_BACK, 0); + input_report_key(sdata->input, KEY_MENU, 0); + break; + + case STMFTS_MASK_KEY_BACK: + input_report_key(sdata->input, KEY_BACK, 1); + break; + + case STMFTS_MASK_KEY_MENU: + input_report_key(sdata->input, KEY_MENU, 1); + break; + + default: + dev_warn(&sdata->client->dev, + "unknown key event: %#02x\n", event[2]); + break; + } + + input_sync(sdata->input); +} + +static void stmfts_parse_events(struct stmfts_data *sdata) +{ + int i; + + for (i = 0; i < STMFTS_STACK_DEPTH; i++) { + u8 *event = &sdata->data[i * STMFTS_EVENT_SIZE]; + + switch (event[0]) { + + case STMFTS_EV_CONTROLLER_READY: + case STMFTS_EV_SLEEP_OUT_CONTROLLER_READY: + case STMFTS_EV_STATUS: + complete(&sdata->cmd_done); + /* fall through */ + + case STMFTS_EV_NO_EVENT: + case STMFTS_EV_DEBUG: + return; + } + + switch (event[0] & STMFTS_MASK_EVENT_ID) { + + case STMFTS_EV_MULTI_TOUCH_ENTER: + case STMFTS_EV_MULTI_TOUCH_MOTION: + stmfts_report_contact_event(sdata, event); + break; + + case STMFTS_EV_MULTI_TOUCH_LEAVE: + stmfts_report_contact_release(sdata, event); + break; + + case STMFTS_EV_HOVER_ENTER: + case STMFTS_EV_HOVER_LEAVE: + case STMFTS_EV_HOVER_MOTION: + stmfts_report_hover_event(sdata, event); + break; + + case STMFTS_EV_KEY_STATUS: + stmfts_report_key_event(sdata, event); + break; + + case STMFTS_EV_ERROR: + dev_warn(&sdata->client->dev, + "error code: 0x%x%x%x%x%x%x", + event[6], event[5], event[4], + event[3], event[2], event[1]); + break; + + default: + dev_err(&sdata->client->dev, + "unknown event %#02x\n", event[0]); + } + } +} + +static irqreturn_t stmfts_irq_handler(int irq, void *dev) +{ + struct stmfts_data *sdata = dev; + int err; + + mutex_lock(&sdata->mutex); + + err = stmfts_read_events(sdata); + if (unlikely(err)) + dev_err(&sdata->client->dev, + "failed to read events: %d\n", err); + else + stmfts_parse_events(sdata); + + mutex_unlock(&sdata->mutex); + return IRQ_HANDLED; +} + +static int stmfts_command(struct stmfts_data *sdata, const u8 cmd) +{ + int err; + + reinit_completion(&sdata->cmd_done); + + err = i2c_smbus_write_byte(sdata->client, cmd); + if (err) + return err; + + if (!wait_for_completion_timeout(&sdata->cmd_done, + msecs_to_jiffies(1000))) + return -ETIMEDOUT; + + return 0; +} + +static int stmfts_input_open(struct input_dev *dev) +{ + struct stmfts_data *sdata = input_get_drvdata(dev); + int err; + + err = pm_runtime_get_sync(&sdata->client->dev); + if (err < 0) + return err; + + err = i2c_smbus_write_byte(sdata->client, STMFTS_MS_MT_SENSE_ON); + if (err) + return err; + + mutex_lock(&sdata->mutex); + sdata->running = true; + + if (sdata->hover_enabled) { + err = i2c_smbus_write_byte(sdata->client, + STMFTS_SS_HOVER_SENSE_ON); + if (err) + dev_warn(&sdata->client->dev, + "failed to enable hover\n"); + } + mutex_unlock(&sdata->mutex); + + if (sdata->use_key) { + err = i2c_smbus_write_byte(sdata->client, + STMFTS_MS_KEY_SENSE_ON); + if (err) + /* I can still use only the touch screen */ + dev_warn(&sdata->client->dev, + "failed to enable touchkey\n"); + } + + return 0; +} + +static void stmfts_input_close(struct input_dev *dev) +{ + struct stmfts_data *sdata = input_get_drvdata(dev); + int err; + + err = i2c_smbus_write_byte(sdata->client, STMFTS_MS_MT_SENSE_OFF); + if (err) + dev_warn(&sdata->client->dev, + "failed to disable touchscreen: %d\n", err); + + mutex_lock(&sdata->mutex); + + sdata->running = false; + + if (sdata->hover_enabled) { + err = i2c_smbus_write_byte(sdata->client, + STMFTS_SS_HOVER_SENSE_OFF); + if (err) + dev_warn(&sdata->client->dev, + "failed to disable hover: %d\n", err); + } + mutex_unlock(&sdata->mutex); + + if (sdata->use_key) { + err = i2c_smbus_write_byte(sdata->client, + STMFTS_MS_KEY_SENSE_OFF); + if (err) + dev_warn(&sdata->client->dev, + "failed to disable touchkey: %d\n", err); + } + + pm_runtime_put_sync(&sdata->client->dev); +} + +static ssize_t stmfts_sysfs_chip_id(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct stmfts_data *sdata = dev_get_drvdata(dev); + + return sprintf(buf, "%#x\n", sdata->chip_id); +} + +static ssize_t stmfts_sysfs_chip_version(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct stmfts_data *sdata = dev_get_drvdata(dev); + + return sprintf(buf, "%u\n", sdata->chip_ver); +} + +static ssize_t stmfts_sysfs_fw_ver(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct stmfts_data *sdata = dev_get_drvdata(dev); + + return sprintf(buf, "%u\n", sdata->fw_ver); +} + +static ssize_t stmfts_sysfs_config_id(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct stmfts_data *sdata = dev_get_drvdata(dev); + + return sprintf(buf, "%#x\n", sdata->config_id); +} + +static ssize_t stmfts_sysfs_config_version(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct stmfts_data *sdata = dev_get_drvdata(dev); + + return sprintf(buf, "%u\n", sdata->config_ver); +} + +static ssize_t stmfts_sysfs_read_status(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct stmfts_data *sdata = dev_get_drvdata(dev); + u8 status[4]; + int err; + + err = i2c_smbus_read_i2c_block_data(sdata->client, STMFTS_READ_STATUS, + sizeof(status), status); + if (err) + return err; + + return sprintf(buf, "%#02x\n", status[0]); +} + +static ssize_t stmfts_sysfs_hover_enable_read(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct stmfts_data *sdata = dev_get_drvdata(dev); + + return sprintf(buf, "%u\n", sdata->hover_enabled); +} + +static ssize_t stmfts_sysfs_hover_enable_write(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct stmfts_data *sdata = dev_get_drvdata(dev); + unsigned long value; + int err = 0; + + if (kstrtoul(buf, 0, &value)) + return -EINVAL; + + mutex_lock(&sdata->mutex); + + if (value & sdata->hover_enabled) + goto out; + + if (sdata->running) + err = i2c_smbus_write_byte(sdata->client, + value ? STMFTS_SS_HOVER_SENSE_ON : + STMFTS_SS_HOVER_SENSE_OFF); + + if (!err) + sdata->hover_enabled = !!value; + +out: + mutex_unlock(&sdata->mutex); + + return len; +} + +static DEVICE_ATTR(chip_id, 0444, stmfts_sysfs_chip_id, NULL); +static DEVICE_ATTR(chip_version, 0444, stmfts_sysfs_chip_version, NULL); +static DEVICE_ATTR(fw_ver, 0444, stmfts_sysfs_fw_ver, NULL); +static DEVICE_ATTR(config_id, 0444, stmfts_sysfs_config_id, NULL); +static DEVICE_ATTR(config_version, 0444, stmfts_sysfs_config_version, NULL); +static DEVICE_ATTR(status, 0444, stmfts_sysfs_read_status, NULL); +static DEVICE_ATTR(hover_enable, 0644, stmfts_sysfs_hover_enable_read, + stmfts_sysfs_hover_enable_write); + +static struct attribute *stmfts_sysfs_attrs[] = { + &dev_attr_chip_id.attr, + &dev_attr_chip_version.attr, + &dev_attr_fw_ver.attr, + &dev_attr_config_id.attr, + &dev_attr_config_version.attr, + &dev_attr_status.attr, + &dev_attr_hover_enable.attr, + NULL +}; + +static struct attribute_group stmfts_attribute_group = { + .attrs = stmfts_sysfs_attrs +}; + +static int stmfts_power_on(struct stmfts_data *sdata) +{ + int err; + u8 reg[8]; + + err = regulator_bulk_enable(ARRAY_SIZE(sdata->regulators), + sdata->regulators); + if (err) + return err; + + /* + * The datasheet does not specify the power on time, but considering + * that the reset time is < 10ms, I sleep 20ms to be sure + */ + msleep(20); + + err = i2c_smbus_read_i2c_block_data(sdata->client, STMFTS_READ_INFO, + sizeof(reg), reg); + if (err < 0) + return err; + if (err != sizeof(reg)) + return -EIO; + + sdata->chip_id = be16_to_cpup((__be16 *)®[6]); + sdata->chip_ver = reg[0]; + sdata->fw_ver = be16_to_cpup((__be16 *)®[2]); + sdata->config_id = reg[4]; + sdata->config_ver = reg[5]; + + enable_irq(sdata->client->irq); + + msleep(50); + + err = stmfts_command(sdata, STMFTS_SYSTEM_RESET); + if (err) + return err; + + err = stmfts_command(sdata, STMFTS_SLEEP_OUT); + if (err) + return err; + + /* optional tuning */ + err = stmfts_command(sdata, STMFTS_MS_CX_TUNING); + if (err) + dev_warn(&sdata->client->dev, + "failed to perform mutual auto tune: %d\n", err); + + /* optional tuning */ + err = stmfts_command(sdata, STMFTS_SS_CX_TUNING); + if (err) + dev_warn(&sdata->client->dev, + "failed to perform self auto tune: %d\n", err); + + err = stmfts_command(sdata, STMFTS_FULL_FORCE_CALIBRATION); + if (err) + return err; + + /* + * At this point no one is using the touchscreen + * and I don't really care about the return value + */ + (void) i2c_smbus_write_byte(sdata->client, STMFTS_SLEEP_IN); + + return 0; +} + +static void stmfts_power_off(void *data) +{ + struct stmfts_data *sdata = data; + + disable_irq(sdata->client->irq); + regulator_bulk_disable(ARRAY_SIZE(sdata->regulators), + sdata->regulators); +} + +/* This function is void because I don't want to prevent using the touch key + * only because the LEDs don't get registered + */ +static int stmfts_enable_led(struct stmfts_data *sdata) +{ + int err; + + /* get the regulator for powering the leds on */ + sdata->ledvdd = devm_regulator_get(&sdata->client->dev, "ledvdd"); + if (IS_ERR(sdata->ledvdd)) + return PTR_ERR(sdata->ledvdd); + + sdata->led_cdev.name = STMFTS_DEV_NAME; + sdata->led_cdev.max_brightness = LED_ON; + sdata->led_cdev.brightness = LED_OFF; + sdata->led_cdev.brightness_set = stmfts_brightness_set; + sdata->led_cdev.brightness_get = stmfts_brightness_get; + + err = devm_led_classdev_register(&sdata->client->dev, &sdata->led_cdev); + if (err) { + devm_regulator_put(sdata->ledvdd); + return err; + } + + return 0; +} + +static int stmfts_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int err; + struct stmfts_data *sdata; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C | + I2C_FUNC_SMBUS_BYTE_DATA | + I2C_FUNC_SMBUS_I2C_BLOCK)) + return -ENODEV; + + sdata = devm_kzalloc(&client->dev, sizeof(*sdata), GFP_KERNEL); + if (!sdata) + return -ENOMEM; + + i2c_set_clientdata(client, sdata); + + sdata->client = client; + mutex_init(&sdata->mutex); + init_completion(&sdata->cmd_done); + + sdata->regulators[STMFTS_REGULATOR_VDD].supply = "vdd"; + sdata->regulators[STMFTS_REGULATOR_AVDD].supply = "avdd"; + err = devm_regulator_bulk_get(&client->dev, + ARRAY_SIZE(sdata->regulators), + sdata->regulators); + if (err) + return err; + + sdata->input = devm_input_allocate_device(&client->dev); + if (!sdata->input) + return -ENOMEM; + + sdata->input->name = STMFTS_DEV_NAME; + sdata->input->id.bustype = BUS_I2C; + sdata->input->open = stmfts_input_open; + sdata->input->close = stmfts_input_close; + + touchscreen_parse_properties(sdata->input, true, &sdata->prop); + + input_set_abs_params(sdata->input, ABS_MT_POSITION_X, 0, + sdata->prop.max_x, 0, 0); + input_set_abs_params(sdata->input, ABS_MT_POSITION_Y, 0, + sdata->prop.max_y, 0, 0); + input_set_abs_params(sdata->input, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0); + input_set_abs_params(sdata->input, ABS_MT_TOUCH_MINOR, 0, 255, 0, 0); + input_set_abs_params(sdata->input, ABS_MT_ORIENTATION, 0, 255, 0, 0); + input_set_abs_params(sdata->input, ABS_MT_PRESSURE, 0, 255, 0, 0); + input_set_abs_params(sdata->input, ABS_DISTANCE, 0, 255, 0, 0); + + sdata->use_key = device_property_read_bool(&client->dev, + "touch-key-connected"); + if (sdata->use_key) { + input_set_capability(sdata->input, EV_KEY, KEY_MENU); + input_set_capability(sdata->input, EV_KEY, KEY_BACK); + } + + err = input_mt_init_slots(sdata->input, + STMFTS_MAX_FINGERS, INPUT_MT_DIRECT); + if (err) + return err; + + input_set_drvdata(sdata->input, sdata); + + err = devm_request_threaded_irq(&client->dev, client->irq, + NULL, stmfts_irq_handler, + IRQF_ONESHOT, + "stmfts_irq", sdata); + if (err) + return err; + + /* stmfts_power_on expects interrupt to be disabled */ + disable_irq(client->irq); + + dev_dbg(&client->dev, "initializing ST-Microelectronics FTS...\n"); + + err = stmfts_power_on(sdata); + if (err) + return err; + + err = devm_add_action_or_reset(&client->dev, stmfts_power_off, sdata); + if (err) + return err; + + err = input_register_device(sdata->input); + if (err) + return err; + + if (sdata->use_key) { + err = stmfts_enable_led(sdata); + if (err) { + /* + * Even if the LEDs have failed to be initialized and + * used in the driver, I can still use the device even + * without LEDs. The ledvdd regulator pointer will be + * used as a flag. + */ + dev_warn(&client->dev, "unable to use touchkey leds\n"); + sdata->ledvdd = NULL; + } + } + + err = sysfs_create_group(&sdata->client->dev.kobj, + &stmfts_attribute_group); + if (err) + return err; + + pm_runtime_enable(&client->dev); + + return 0; +} + +static int stmfts_remove(struct i2c_client *client) +{ + pm_runtime_disable(&client->dev); + sysfs_remove_group(&client->dev.kobj, &stmfts_attribute_group); + + return 0; +} + +static int stmfts_runtime_suspend(struct device *dev) +{ + struct stmfts_data *sdata = dev_get_drvdata(dev); + int ret; + + ret = i2c_smbus_write_byte(sdata->client, STMFTS_SLEEP_IN); + if (ret) + dev_warn(dev, "failed to suspend device: %d\n", ret); + + return ret; +} + +static int stmfts_runtime_resume(struct device *dev) +{ + struct stmfts_data *sdata = dev_get_drvdata(dev); + int ret; + + ret = i2c_smbus_write_byte(sdata->client, STMFTS_SLEEP_OUT); + if (ret) + dev_err(dev, "failed to resume device: %d\n", ret); + + return ret; +} + +static int __maybe_unused stmfts_suspend(struct device *dev) +{ + struct stmfts_data *sdata = dev_get_drvdata(dev); + + stmfts_power_off(sdata); + + return 0; +} + +static int __maybe_unused stmfts_resume(struct device *dev) +{ + struct stmfts_data *sdata = dev_get_drvdata(dev); + + return stmfts_power_on(sdata); +} + +static const struct dev_pm_ops stmfts_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(stmfts_suspend, stmfts_resume) + SET_RUNTIME_PM_OPS(stmfts_runtime_suspend, stmfts_runtime_resume, NULL) +}; + +#ifdef CONFIG_OF +static const struct of_device_id stmfts_of_match[] = { + { .compatible = "st,stmfts", }, + { }, +}; +MODULE_DEVICE_TABLE(of, stmfts_of_match); +#endif + +static const struct i2c_device_id stmfts_id[] = { + { "stmfts", 0 }, + { }, +}; +MODULE_DEVICE_TABLE(i2c, stmfts_id); + +static struct i2c_driver stmfts_driver = { + .driver = { + .name = STMFTS_DEV_NAME, + .of_match_table = of_match_ptr(stmfts_of_match), + .pm = &stmfts_pm_ops, + }, + .probe = stmfts_probe, + .remove = stmfts_remove, + .id_table = stmfts_id, +}; + +module_i2c_driver(stmfts_driver); + +MODULE_AUTHOR("Andi Shyti "); +MODULE_DESCRIPTION("STMicroelectronics FTS Touch Screen"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From d4c9354b4015aa8d1b032c368682dd20a00f4e1f Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 9 Jun 2017 09:54:09 -0700 Subject: Input: stmfts - mark all PM functions as __maybe_unused We get a harmless warning when CONFIG_RUNTIME_PM is disabled: drivers/input/touchscreen/stmfts.c:760:12: error: 'stmfts_runtime_resume' defined but not used [-Werror=unused-function] static int stmfts_runtime_resume(struct device *dev) drivers/input/touchscreen/stmfts.c:748:12: error: 'stmfts_runtime_suspend' defined but not used [-Werror=unused-function] static int stmfts_runtime_suspend(struct device *dev) The regular PM functions are already marked as __maybe_unused, so let's do the same for the runtime-PM as well. Fixes: 78bcac7b2ae1 ("Input: add support for the STMicroelectronics FingerTip touchscreen") Signed-off-by: Arnd Bergmann Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/stmfts.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/stmfts.c b/drivers/input/touchscreen/stmfts.c index 802d0e82d034..157fdb4bb2e8 100644 --- a/drivers/input/touchscreen/stmfts.c +++ b/drivers/input/touchscreen/stmfts.c @@ -745,7 +745,7 @@ static int stmfts_remove(struct i2c_client *client) return 0; } -static int stmfts_runtime_suspend(struct device *dev) +static int __maybe_unused stmfts_runtime_suspend(struct device *dev) { struct stmfts_data *sdata = dev_get_drvdata(dev); int ret; @@ -757,7 +757,7 @@ static int stmfts_runtime_suspend(struct device *dev) return ret; } -static int stmfts_runtime_resume(struct device *dev) +static int __maybe_unused stmfts_runtime_resume(struct device *dev) { struct stmfts_data *sdata = dev_get_drvdata(dev); int ret; -- cgit v1.2.3 From ad2ee015245dfe22743a25d7245b3d6abd33c02e Mon Sep 17 00:00:00 2001 From: Oleksandr Andrushchenko Date: Sun, 28 May 2017 23:52:23 -0700 Subject: Input: xen-kbdfront - use string constants from PV protocol Xen input para-virtual protocol defines string constants used by both back and frontend. Use those instead of explicit strings in the frontend driver. Signed-off-by: Oleksandr Andrushchenko Signed-off-by: Dmitry Torokhov --- drivers/input/misc/xen-kbdfront.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/misc/xen-kbdfront.c b/drivers/input/misc/xen-kbdfront.c index 690148f9940e..eb770613a9bd 100644 --- a/drivers/input/misc/xen-kbdfront.c +++ b/drivers/input/misc/xen-kbdfront.c @@ -135,14 +135,17 @@ static int xenkbd_probe(struct xenbus_device *dev, goto error_nomem; /* Set input abs params to match backend screen res */ - abs = xenbus_read_unsigned(dev->otherend, "feature-abs-pointer", 0); - ptr_size[KPARAM_X] = xenbus_read_unsigned(dev->otherend, "width", + abs = xenbus_read_unsigned(dev->otherend, + XENKBD_FIELD_FEAT_ABS_POINTER, 0); + ptr_size[KPARAM_X] = xenbus_read_unsigned(dev->otherend, + XENKBD_FIELD_WIDTH, ptr_size[KPARAM_X]); - ptr_size[KPARAM_Y] = xenbus_read_unsigned(dev->otherend, "height", + ptr_size[KPARAM_Y] = xenbus_read_unsigned(dev->otherend, + XENKBD_FIELD_HEIGHT, ptr_size[KPARAM_Y]); if (abs) { ret = xenbus_write(XBT_NIL, dev->nodename, - "request-abs-pointer", "1"); + XENKBD_FIELD_REQ_ABS_POINTER, "1"); if (ret) { pr_warn("xenkbd: can't request abs-pointer\n"); abs = 0; @@ -271,14 +274,15 @@ static int xenkbd_connect_backend(struct xenbus_device *dev, xenbus_dev_fatal(dev, ret, "starting transaction"); goto error_irqh; } - ret = xenbus_printf(xbt, dev->nodename, "page-ref", "%lu", + ret = xenbus_printf(xbt, dev->nodename, XENKBD_FIELD_RING_REF, "%lu", virt_to_gfn(info->page)); if (ret) goto error_xenbus; - ret = xenbus_printf(xbt, dev->nodename, "page-gref", "%u", info->gref); + ret = xenbus_printf(xbt, dev->nodename, XENKBD_FIELD_RING_GREF, + "%u", info->gref); if (ret) goto error_xenbus; - ret = xenbus_printf(xbt, dev->nodename, "event-channel", "%u", + ret = xenbus_printf(xbt, dev->nodename, XENKBD_FIELD_EVT_CHANNEL, "%u", evtchn); if (ret) goto error_xenbus; @@ -353,7 +357,7 @@ static void xenkbd_backend_changed(struct xenbus_device *dev, } static const struct xenbus_device_id xenkbd_ids[] = { - { "vkbd" }, + { XENKBD_DRIVER_NAME }, { "" } }; @@ -390,4 +394,4 @@ module_exit(xenkbd_cleanup); MODULE_DESCRIPTION("Xen virtual keyboard/pointer device frontend"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("xen:vkbd"); +MODULE_ALIAS("xen:" XENKBD_DRIVER_NAME); -- cgit v1.2.3 From c225370e01b87d3c4ef40d98295ac0bb1e5a3116 Mon Sep 17 00:00:00 2001 From: Benjamin Valentin Date: Sun, 18 Jun 2017 15:40:37 -0700 Subject: Input: xpad - sync supported devices with 360Controller 360Controller [0] is an OpenSource driver for Xbox/Xbox360/XboxOne controllers on macOS. It contains a couple device IDs unknown to the Linux driver, so I wrote a small Python script [1] to extract them and feed them into my previous script [2] to compare them with the IDs known to Linux. For most devices, this information is not really needed as xpad is able to automatically detect the type of an unknown Xbox Controller at run-time. I've therefore stripped all the generic/vague entries. I've excluded the Logitech G920, it's handled by a HID driver already. I've also excluded the Scene It! Big Button IR, it's handled by an out-of-tree driver. [3] [0] https://github.com/360Controller/360Controller [1] http://codepad.org/v9GyLKMq [2] http://codepad.org/qh7jclpD [3] https://github.com/micolous/xbox360bb Reviewed-by: Cameron Gutman Signed-off-by: Benjamin Valentin Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/xpad.c | 57 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) (limited to 'drivers/input') diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index def96cd2479b..b8d08f2296ff 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -131,8 +131,10 @@ static const struct xpad_device { { 0x045e, 0x0202, "Microsoft X-Box pad v1 (US)", 0, XTYPE_XBOX }, { 0x045e, 0x0285, "Microsoft X-Box pad (Japan)", 0, XTYPE_XBOX }, { 0x045e, 0x0287, "Microsoft Xbox Controller S", 0, XTYPE_XBOX }, + { 0x045e, 0x0288, "Microsoft Xbox Controller S v2", 0, XTYPE_XBOX }, { 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", 0, XTYPE_XBOX }, { 0x045e, 0x028e, "Microsoft X-Box 360 pad", 0, XTYPE_XBOX360 }, + { 0x045e, 0x028f, "Microsoft X-Box 360 pad v2", 0, XTYPE_XBOX360 }, { 0x045e, 0x0291, "Xbox 360 Wireless Receiver (XBOX)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W }, { 0x045e, 0x02d1, "Microsoft X-Box One pad", 0, XTYPE_XBOXONE }, { 0x045e, 0x02dd, "Microsoft X-Box One pad (Firmware 2015)", 0, XTYPE_XBOXONE }, @@ -145,6 +147,7 @@ static const struct xpad_device { { 0x046d, 0xc242, "Logitech Chillstream Controller", 0, XTYPE_XBOX360 }, { 0x046d, 0xca84, "Logitech Xbox Cordless Controller", 0, XTYPE_XBOX }, { 0x046d, 0xca88, "Logitech Compact Controller for Xbox", 0, XTYPE_XBOX }, + { 0x046d, 0xcaa3, "Logitech DriveFx Racing Wheel", 0, XTYPE_XBOX360 }, { 0x056e, 0x2004, "Elecom JC-U3613M", 0, XTYPE_XBOX360 }, { 0x05fd, 0x1007, "Mad Catz Controller (unverified)", 0, XTYPE_XBOX }, { 0x05fd, 0x107a, "InterAct 'PowerPad Pro' X-Box pad (Germany)", 0, XTYPE_XBOX }, @@ -158,14 +161,19 @@ static const struct xpad_device { { 0x0738, 0x4718, "Mad Catz Street Fighter IV FightStick SE", 0, XTYPE_XBOX360 }, { 0x0738, 0x4726, "Mad Catz Xbox 360 Controller", 0, XTYPE_XBOX360 }, { 0x0738, 0x4728, "Mad Catz Street Fighter IV FightPad", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, + { 0x0738, 0x4736, "Mad Catz MicroCon Gamepad", 0, XTYPE_XBOX360 }, { 0x0738, 0x4738, "Mad Catz Wired Xbox 360 Controller (SFIV)", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, { 0x0738, 0x4740, "Mad Catz Beat Pad", 0, XTYPE_XBOX360 }, + { 0x0738, 0x4758, "Mad Catz Arcade Game Stick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, { 0x0738, 0x4a01, "Mad Catz FightStick TE 2", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOXONE }, { 0x0738, 0x6040, "Mad Catz Beat Pad Pro", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, + { 0x0738, 0x9871, "Mad Catz Portable Drum", 0, XTYPE_XBOX360 }, { 0x0738, 0xb726, "Mad Catz Xbox controller - MW2", 0, XTYPE_XBOX360 }, + { 0x0738, 0xb738, "Mad Catz MVC2TE Stick 2", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, { 0x0738, 0xbeef, "Mad Catz JOYTECH NEO SE Advanced GamePad", XTYPE_XBOX360 }, { 0x0738, 0xcb02, "Saitek Cyborg Rumble Pad - PC/Xbox 360", 0, XTYPE_XBOX360 }, { 0x0738, 0xcb03, "Saitek P3200 Rumble Pad - PC/Xbox 360", 0, XTYPE_XBOX360 }, + { 0x0738, 0xcb29, "Saitek Aviator Stick AV8R02", 0, XTYPE_XBOX360 }, { 0x0738, 0xf738, "Super SFIV FightStick TE S", 0, XTYPE_XBOX360 }, { 0x0c12, 0x8802, "Zeroplus Xbox Controller", 0, XTYPE_XBOX }, { 0x0c12, 0x8809, "RedOctane Xbox Dance Pad", DANCEPAD_MAP_CONFIG, XTYPE_XBOX }, @@ -181,30 +189,52 @@ static const struct xpad_device { { 0x0e6f, 0x0105, "HSM3 Xbox360 dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, { 0x0e6f, 0x0113, "Afterglow AX.1 Gamepad for Xbox 360", 0, XTYPE_XBOX360 }, { 0x0e6f, 0x011f, "Rock Candy Gamepad Wired Controller", 0, XTYPE_XBOX360 }, + { 0x0e6f, 0x0131, "PDP EA Sports Controller", 0, XTYPE_XBOX360 }, + { 0x0e6f, 0x0133, "Xbox 360 Wired Controller", 0, XTYPE_XBOX360 }, { 0x0e6f, 0x0139, "Afterglow Prismatic Wired Controller", 0, XTYPE_XBOXONE }, + { 0x0e6f, 0x013a, "PDP Xbox One Controller", 0, XTYPE_XBOXONE }, { 0x0e6f, 0x0146, "Rock Candy Wired Controller for Xbox One", 0, XTYPE_XBOXONE }, + { 0x0e6f, 0x0147, "PDP Marvel Xbox One Controller", 0, XTYPE_XBOXONE }, + { 0x0e6f, 0x015c, "PDP Xbox One Arcade Stick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOXONE }, + { 0x0e6f, 0x0161, "PDP Xbox One Controller", 0, XTYPE_XBOXONE }, + { 0x0e6f, 0x0162, "PDP Xbox One Controller", 0, XTYPE_XBOXONE }, + { 0x0e6f, 0x0163, "PDP Xbox One Controller", 0, XTYPE_XBOXONE }, + { 0x0e6f, 0x0164, "PDP Battlefield One", 0, XTYPE_XBOXONE }, + { 0x0e6f, 0x0165, "PDP Titanfall 2", 0, XTYPE_XBOXONE }, { 0x0e6f, 0x0201, "Pelican PL-3601 'TSZ' Wired Xbox 360 Controller", 0, XTYPE_XBOX360 }, { 0x0e6f, 0x0213, "Afterglow Gamepad for Xbox 360", 0, XTYPE_XBOX360 }, { 0x0e6f, 0x021f, "Rock Candy Gamepad for Xbox 360", 0, XTYPE_XBOX360 }, + { 0x0e6f, 0x0246, "Rock Candy Gamepad for Xbox One 2015", 0, XTYPE_XBOXONE }, { 0x0e6f, 0x0301, "Logic3 Controller", 0, XTYPE_XBOX360 }, + { 0x0e6f, 0x0346, "Rock Candy Gamepad for Xbox One 2016", 0, XTYPE_XBOXONE }, { 0x0e6f, 0x0401, "Logic3 Controller", 0, XTYPE_XBOX360 }, { 0x0e6f, 0x0413, "Afterglow AX.1 Gamepad for Xbox 360", 0, XTYPE_XBOX360 }, + { 0x0e6f, 0x0501, "PDP Xbox 360 Controller", 0, XTYPE_XBOX360 }, + { 0x0e6f, 0xf900, "PDP Afterglow AX.1", 0, XTYPE_XBOX360 }, { 0x0e8f, 0x0201, "SmartJoy Frag Xpad/PS2 adaptor", 0, XTYPE_XBOX }, { 0x0e8f, 0x3008, "Generic xbox control (dealextreme)", 0, XTYPE_XBOX }, { 0x0f0d, 0x000a, "Hori Co. DOA4 FightStick", 0, XTYPE_XBOX360 }, + { 0x0f0d, 0x000c, "Hori PadEX Turbo", 0, XTYPE_XBOX360 }, { 0x0f0d, 0x000d, "Hori Fighting Stick EX2", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, { 0x0f0d, 0x0016, "Hori Real Arcade Pro.EX", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, + { 0x0f0d, 0x001b, "Hori Real Arcade Pro VX", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, + { 0x0f0d, 0x0063, "Hori Real Arcade Pro Hayabusa (USA) Xbox One", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOXONE }, { 0x0f0d, 0x0067, "HORIPAD ONE", 0, XTYPE_XBOXONE }, + { 0x0f0d, 0x0078, "Hori Real Arcade Pro V Kai Xbox One", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOXONE }, { 0x0f30, 0x0202, "Joytech Advanced Controller", 0, XTYPE_XBOX }, { 0x0f30, 0x8888, "BigBen XBMiniPad Controller", 0, XTYPE_XBOX }, { 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", 0, XTYPE_XBOX }, + { 0x11c9, 0x55f0, "Nacon GC-100XF", 0, XTYPE_XBOX360 }, { 0x12ab, 0x0004, "Honey Bee Xbox360 dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, { 0x12ab, 0x0301, "PDP AFTERGLOW AX.1", 0, XTYPE_XBOX360 }, + { 0x12ab, 0x0303, "Mortal Kombat Klassic FightStick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, { 0x12ab, 0x8809, "Xbox DDR dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, { 0x1430, 0x4748, "RedOctane Guitar Hero X-plorer", 0, XTYPE_XBOX360 }, { 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, + { 0x1430, 0xf801, "RedOctane Controller", 0, XTYPE_XBOX360 }, { 0x146b, 0x0601, "BigBen Interactive XBOX 360 Controller", 0, XTYPE_XBOX360 }, { 0x1532, 0x0037, "Razer Sabertooth", 0, XTYPE_XBOX360 }, + { 0x1532, 0x0a00, "Razer Atrox Arcade Stick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOXONE }, { 0x1532, 0x0a03, "Razer Wildcat", 0, XTYPE_XBOXONE }, { 0x15e4, 0x3f00, "Power A Mini Pro Elite", 0, XTYPE_XBOX360 }, { 0x15e4, 0x3f0a, "Xbox Airflo wired controller", 0, XTYPE_XBOX360 }, @@ -215,22 +245,42 @@ static const struct xpad_device { { 0x1689, 0xfe00, "Razer Sabertooth", 0, XTYPE_XBOX360 }, { 0x1bad, 0x0002, "Harmonix Rock Band Guitar", 0, XTYPE_XBOX360 }, { 0x1bad, 0x0003, "Harmonix Rock Band Drumkit", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, + { 0x1bad, 0x0130, "Ion Drum Rocker", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, { 0x1bad, 0xf016, "Mad Catz Xbox 360 Controller", 0, XTYPE_XBOX360 }, { 0x1bad, 0xf018, "Mad Catz Street Fighter IV SE Fighting Stick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, { 0x1bad, 0xf019, "Mad Catz Brawlstick for Xbox 360", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, { 0x1bad, 0xf021, "Mad Cats Ghost Recon FS GamePad", 0, XTYPE_XBOX360 }, { 0x1bad, 0xf023, "MLG Pro Circuit Controller (Xbox)", 0, XTYPE_XBOX360 }, + { 0x1bad, 0xf025, "Mad Catz Call Of Duty", 0, XTYPE_XBOX360 }, + { 0x1bad, 0xf027, "Mad Catz FPS Pro", 0, XTYPE_XBOX360 }, { 0x1bad, 0xf028, "Street Fighter IV FightPad", 0, XTYPE_XBOX360 }, { 0x1bad, 0xf02e, "Mad Catz Fightpad", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, { 0x1bad, 0xf038, "Street Fighter IV FightStick TE", 0, XTYPE_XBOX360 }, + { 0x1bad, 0xf039, "Mad Catz MvC2 TE", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, { 0x1bad, 0xf03a, "Mad Catz SFxT Fightstick Pro", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, + { 0x1bad, 0xf03d, "Street Fighter IV Arcade Stick TE - Chun Li", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, + { 0x1bad, 0xf03e, "Mad Catz MLG FightStick TE", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, + { 0x1bad, 0xf03f, "Mad Catz FightStick SoulCaliber", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, + { 0x1bad, 0xf042, "Mad Catz FightStick TES+", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, + { 0x1bad, 0xf080, "Mad Catz FightStick TE2", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, + { 0x1bad, 0xf501, "HoriPad EX2 Turbo", 0, XTYPE_XBOX360 }, + { 0x1bad, 0xf502, "Hori Real Arcade Pro.VX SA", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, + { 0x1bad, 0xf503, "Hori Fighting Stick VX", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, + { 0x1bad, 0xf504, "Hori Real Arcade Pro. EX", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, + { 0x1bad, 0xf505, "Hori Fighting Stick EX2B", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, + { 0x1bad, 0xf506, "Hori Real Arcade Pro.EX Premium VLX", 0, XTYPE_XBOX360 }, { 0x1bad, 0xf900, "Harmonix Xbox 360 Controller", 0, XTYPE_XBOX360 }, { 0x1bad, 0xf901, "Gamestop Xbox 360 Controller", 0, XTYPE_XBOX360 }, { 0x1bad, 0xf903, "Tron Xbox 360 controller", 0, XTYPE_XBOX360 }, + { 0x1bad, 0xf904, "PDP Versus Fighting Pad", 0, XTYPE_XBOX360 }, + { 0x1bad, 0xf906, "MortalKombat FightStick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, { 0x1bad, 0xfa01, "MadCatz GamePad", 0, XTYPE_XBOX360 }, + { 0x1bad, 0xfd00, "Razer Onza TE", 0, XTYPE_XBOX360 }, + { 0x1bad, 0xfd01, "Razer Onza", 0, XTYPE_XBOX360 }, { 0x24c6, 0x5000, "Razer Atrox Arcade Stick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, { 0x24c6, 0x5300, "PowerA MINI PROEX Controller", 0, XTYPE_XBOX360 }, { 0x24c6, 0x5303, "Xbox Airflo wired controller", 0, XTYPE_XBOX360 }, + { 0x24c6, 0x530a, "Xbox 360 Pro EX Controller", 0, XTYPE_XBOX360 }, { 0x24c6, 0x531a, "PowerA Pro Ex", 0, XTYPE_XBOX360 }, { 0x24c6, 0x5397, "FUS1ON Tournament Controller", 0, XTYPE_XBOX360 }, { 0x24c6, 0x541a, "PowerA Xbox One Mini Wired Controller", 0, XTYPE_XBOXONE }, @@ -238,12 +288,18 @@ static const struct xpad_device { { 0x24c6, 0x543a, "PowerA Xbox One wired controller", 0, XTYPE_XBOXONE }, { 0x24c6, 0x5500, "Hori XBOX 360 EX 2 with Turbo", 0, XTYPE_XBOX360 }, { 0x24c6, 0x5501, "Hori Real Arcade Pro VX-SA", 0, XTYPE_XBOX360 }, + { 0x24c6, 0x5502, "Hori Fighting Stick VX Alt", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, { 0x24c6, 0x5503, "Hori Fighting Edge", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, { 0x24c6, 0x5506, "Hori SOULCALIBUR V Stick", 0, XTYPE_XBOX360 }, { 0x24c6, 0x550d, "Hori GEM Xbox controller", 0, XTYPE_XBOX360 }, + { 0x24c6, 0x550e, "Hori Real Arcade Pro V Kai 360", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, + { 0x24c6, 0x551a, "PowerA FUSION Pro Controller", 0, XTYPE_XBOXONE }, + { 0x24c6, 0x561a, "PowerA FUSION Controller", 0, XTYPE_XBOXONE }, + { 0x24c6, 0x5b00, "ThrustMaster Ferrari 458 Racing Wheel", 0, XTYPE_XBOX360 }, { 0x24c6, 0x5b02, "Thrustmaster, Inc. GPX Controller", 0, XTYPE_XBOX360 }, { 0x24c6, 0x5b03, "Thrustmaster Ferrari 458 Racing Wheel", 0, XTYPE_XBOX360 }, { 0x24c6, 0x5d04, "Razer Sabertooth", 0, XTYPE_XBOX360 }, + { 0x24c6, 0xfafe, "Rock Candy Gamepad for Xbox 360", 0, XTYPE_XBOX360 }, { 0xffff, 0xffff, "Chinese-made Xbox Controller", 0, XTYPE_XBOX }, { 0x0000, 0x0000, "Generic X-Box pad", 0, XTYPE_UNKNOWN } }; @@ -338,6 +394,7 @@ static struct usb_device_id xpad_table[] = { XPAD_XBOXONE_VENDOR(0x0e6f), /* 0x0e6f X-Box One controllers */ XPAD_XBOX360_VENDOR(0x0f0d), /* Hori Controllers */ XPAD_XBOXONE_VENDOR(0x0f0d), /* Hori Controllers */ + XPAD_XBOX360_VENDOR(0x11c9), /* Nacon GC100XF */ XPAD_XBOX360_VENDOR(0x12ab), /* X-Box 360 dance pads */ XPAD_XBOX360_VENDOR(0x1430), /* RedOctane X-Box 360 controllers */ XPAD_XBOX360_VENDOR(0x146b), /* BigBen Interactive Controllers */ -- cgit v1.2.3 From be19788c73d382f66dd3fba3c5ccef59cf12a126 Mon Sep 17 00:00:00 2001 From: Benjamin Valentin Date: Sun, 18 Jun 2017 15:41:20 -0700 Subject: Input: xpad - sync supported devices with XBCD XBCD [0][1] is an OpenSource driver for Xbox controllers on Windows. Later it also started supporting Xbox360 controllers (presumably before the official Windows driver was released). It contains a couple device IDs unknown to the Linux driver, so I extracted those from xbcd.inf and added them to our list. It has a special type for Wheels and I have the feeling they might need some extra handling. They all have 'Wheel' in their name, so that information is available for future improvements. [0] https://www.s-config.com/xbcd-original-xbox-controllers-win10/ [1] http://www.redcl0ud.com/xbcd.html Reviewed-by: Cameron Gutman Signed-off-by: Benjamin Valentin Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/xpad.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'drivers/input') diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index b8d08f2296ff..298a6ba51411 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -126,7 +126,10 @@ static const struct xpad_device { u8 mapping; u8 xtype; } xpad_device[] = { + { 0x044f, 0x0f00, "Thrustmaster Wheel", 0, XTYPE_XBOX }, + { 0x044f, 0x0f03, "Thrustmaster Wheel", 0, XTYPE_XBOX }, { 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", 0, XTYPE_XBOX }, + { 0x044f, 0x0f10, "Thrustmaster Modena GT Wheel", 0, XTYPE_XBOX }, { 0x044f, 0xb326, "Thrustmaster Gamepad GP XID", 0, XTYPE_XBOX360 }, { 0x045e, 0x0202, "Microsoft X-Box pad v1 (US)", 0, XTYPE_XBOX }, { 0x045e, 0x0285, "Microsoft X-Box pad (Japan)", 0, XTYPE_XBOX }, @@ -147,16 +150,30 @@ static const struct xpad_device { { 0x046d, 0xc242, "Logitech Chillstream Controller", 0, XTYPE_XBOX360 }, { 0x046d, 0xca84, "Logitech Xbox Cordless Controller", 0, XTYPE_XBOX }, { 0x046d, 0xca88, "Logitech Compact Controller for Xbox", 0, XTYPE_XBOX }, + { 0x046d, 0xca8a, "Logitech Precision Vibration Feedback Wheel", 0, XTYPE_XBOX }, { 0x046d, 0xcaa3, "Logitech DriveFx Racing Wheel", 0, XTYPE_XBOX360 }, { 0x056e, 0x2004, "Elecom JC-U3613M", 0, XTYPE_XBOX360 }, { 0x05fd, 0x1007, "Mad Catz Controller (unverified)", 0, XTYPE_XBOX }, { 0x05fd, 0x107a, "InterAct 'PowerPad Pro' X-Box pad (Germany)", 0, XTYPE_XBOX }, + { 0x05fe, 0x3030, "Chic Controller", 0, XTYPE_XBOX }, + { 0x05fe, 0x3031, "Chic Controller", 0, XTYPE_XBOX }, + { 0x062a, 0x0020, "Logic3 Xbox GamePad", 0, XTYPE_XBOX }, + { 0x062a, 0x0033, "Competition Pro Steering Wheel", 0, XTYPE_XBOX }, + { 0x06a3, 0x0200, "Saitek Racing Wheel", 0, XTYPE_XBOX }, + { 0x06a3, 0x0201, "Saitek Adrenalin", 0, XTYPE_XBOX }, + { 0x06a3, 0xf51a, "Saitek P3600", 0, XTYPE_XBOX360 }, + { 0x0738, 0x4506, "Mad Catz 4506 Wireless Controller", 0, XTYPE_XBOX }, { 0x0738, 0x4516, "Mad Catz Control Pad", 0, XTYPE_XBOX }, + { 0x0738, 0x4520, "Mad Catz Control Pad Pro", 0, XTYPE_XBOX }, { 0x0738, 0x4522, "Mad Catz LumiCON", 0, XTYPE_XBOX }, { 0x0738, 0x4526, "Mad Catz Control Pad Pro", 0, XTYPE_XBOX }, + { 0x0738, 0x4530, "Mad Catz Universal MC2 Racing Wheel and Pedals", 0, XTYPE_XBOX }, { 0x0738, 0x4536, "Mad Catz MicroCON", 0, XTYPE_XBOX }, { 0x0738, 0x4540, "Mad Catz Beat Pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, { 0x0738, 0x4556, "Mad Catz Lynx Wireless Controller", 0, XTYPE_XBOX }, + { 0x0738, 0x4586, "Mad Catz MicroCon Wireless Controller", 0, XTYPE_XBOX }, + { 0x0738, 0x4588, "Mad Catz Blaster", 0, XTYPE_XBOX }, + { 0x0738, 0x45ff, "Mad Catz Beat Pad (w/ Handle)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, { 0x0738, 0x4716, "Mad Catz Wired Xbox 360 Controller", 0, XTYPE_XBOX360 }, { 0x0738, 0x4718, "Mad Catz Street Fighter IV FightStick SE", 0, XTYPE_XBOX360 }, { 0x0738, 0x4726, "Mad Catz Xbox 360 Controller", 0, XTYPE_XBOX360 }, @@ -164,6 +181,7 @@ static const struct xpad_device { { 0x0738, 0x4736, "Mad Catz MicroCon Gamepad", 0, XTYPE_XBOX360 }, { 0x0738, 0x4738, "Mad Catz Wired Xbox 360 Controller (SFIV)", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, { 0x0738, 0x4740, "Mad Catz Beat Pad", 0, XTYPE_XBOX360 }, + { 0x0738, 0x4743, "Mad Catz Beat Pad Pro", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, { 0x0738, 0x4758, "Mad Catz Arcade Game Stick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, { 0x0738, 0x4a01, "Mad Catz FightStick TE 2", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOXONE }, { 0x0738, 0x6040, "Mad Catz Beat Pad Pro", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, @@ -175,6 +193,9 @@ static const struct xpad_device { { 0x0738, 0xcb03, "Saitek P3200 Rumble Pad - PC/Xbox 360", 0, XTYPE_XBOX360 }, { 0x0738, 0xcb29, "Saitek Aviator Stick AV8R02", 0, XTYPE_XBOX360 }, { 0x0738, 0xf738, "Super SFIV FightStick TE S", 0, XTYPE_XBOX360 }, + { 0x07ff, 0xffff, "Mad Catz GamePad", 0, XTYPE_XBOX360 }, + { 0x0c12, 0x0005, "Intec wireless", 0, XTYPE_XBOX }, + { 0x0c12, 0x8801, "Nyko Xbox Controller", 0, XTYPE_XBOX }, { 0x0c12, 0x8802, "Zeroplus Xbox Controller", 0, XTYPE_XBOX }, { 0x0c12, 0x8809, "RedOctane Xbox Dance Pad", DANCEPAD_MAP_CONFIG, XTYPE_XBOX }, { 0x0c12, 0x880a, "Pelican Eclipse PL-2023", 0, XTYPE_XBOX }, @@ -182,10 +203,13 @@ static const struct xpad_device { { 0x0c12, 0x9902, "HAMA VibraX - *FAULTY HARDWARE*", 0, XTYPE_XBOX }, { 0x0d2f, 0x0002, "Andamiro Pump It Up pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, { 0x0e4c, 0x1097, "Radica Gamester Controller", 0, XTYPE_XBOX }, + { 0x0e4c, 0x1103, "Radica Gamester Reflex", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX }, { 0x0e4c, 0x2390, "Radica Games Jtech Controller", 0, XTYPE_XBOX }, + { 0x0e4c, 0x3510, "Radica Gamester", 0, XTYPE_XBOX }, { 0x0e6f, 0x0003, "Logic3 Freebird wireless Controller", 0, XTYPE_XBOX }, { 0x0e6f, 0x0005, "Eclipse wireless Controller", 0, XTYPE_XBOX }, { 0x0e6f, 0x0006, "Edge wireless Controller", 0, XTYPE_XBOX }, + { 0x0e6f, 0x0008, "After Glow Pro Controller", 0, XTYPE_XBOX }, { 0x0e6f, 0x0105, "HSM3 Xbox360 dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, { 0x0e6f, 0x0113, "Afterglow AX.1 Gamepad for Xbox 360", 0, XTYPE_XBOX360 }, { 0x0e6f, 0x011f, "Rock Candy Gamepad Wired Controller", 0, XTYPE_XBOX360 }, @@ -221,6 +245,7 @@ static const struct xpad_device { { 0x0f0d, 0x0063, "Hori Real Arcade Pro Hayabusa (USA) Xbox One", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOXONE }, { 0x0f0d, 0x0067, "HORIPAD ONE", 0, XTYPE_XBOXONE }, { 0x0f0d, 0x0078, "Hori Real Arcade Pro V Kai Xbox One", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOXONE }, + { 0x0f30, 0x010b, "Philips Recoil", 0, XTYPE_XBOX }, { 0x0f30, 0x0202, "Joytech Advanced Controller", 0, XTYPE_XBOX }, { 0x0f30, 0x8888, "BigBen XBMiniPad Controller", 0, XTYPE_XBOX }, { 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", 0, XTYPE_XBOX }, @@ -255,6 +280,8 @@ static const struct xpad_device { { 0x1bad, 0xf027, "Mad Catz FPS Pro", 0, XTYPE_XBOX360 }, { 0x1bad, 0xf028, "Street Fighter IV FightPad", 0, XTYPE_XBOX360 }, { 0x1bad, 0xf02e, "Mad Catz Fightpad", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, + { 0x1bad, 0xf030, "Mad Catz Xbox 360 MC2 MicroCon Racing Wheel", 0, XTYPE_XBOX360 }, + { 0x1bad, 0xf036, "Mad Catz MicroCon GamePad Pro", 0, XTYPE_XBOX360 }, { 0x1bad, 0xf038, "Street Fighter IV FightStick TE", 0, XTYPE_XBOX360 }, { 0x1bad, 0xf039, "Mad Catz MvC2 TE", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, { 0x1bad, 0xf03a, "Mad Catz SFxT Fightstick Pro", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, @@ -300,6 +327,7 @@ static const struct xpad_device { { 0x24c6, 0x5b03, "Thrustmaster Ferrari 458 Racing Wheel", 0, XTYPE_XBOX360 }, { 0x24c6, 0x5d04, "Razer Sabertooth", 0, XTYPE_XBOX360 }, { 0x24c6, 0xfafe, "Rock Candy Gamepad for Xbox 360", 0, XTYPE_XBOX360 }, + { 0x3767, 0x0101, "Fanatec Speedster 3 Forceshock Wheel", 0, XTYPE_XBOX }, { 0xffff, 0xffff, "Chinese-made Xbox Controller", 0, XTYPE_XBOX }, { 0x0000, 0x0000, "Generic X-Box pad", 0, XTYPE_UNKNOWN } }; @@ -387,9 +415,11 @@ static struct usb_device_id xpad_table[] = { XPAD_XBOXONE_VENDOR(0x045e), /* Microsoft X-Box One controllers */ XPAD_XBOX360_VENDOR(0x046d), /* Logitech X-Box 360 style controllers */ XPAD_XBOX360_VENDOR(0x056e), /* Elecom JC-U3613M */ + XPAD_XBOX360_VENDOR(0x06a3), /* Saitek P3600 */ XPAD_XBOX360_VENDOR(0x0738), /* Mad Catz X-Box 360 controllers */ { USB_DEVICE(0x0738, 0x4540) }, /* Mad Catz Beat Pad */ XPAD_XBOXONE_VENDOR(0x0738), /* Mad Catz FightStick TE 2 */ + XPAD_XBOX360_VENDOR(0x07ff), /* Mad Catz GamePad */ XPAD_XBOX360_VENDOR(0x0e6f), /* 0x0e6f X-Box 360 controllers */ XPAD_XBOXONE_VENDOR(0x0e6f), /* 0x0e6f X-Box One controllers */ XPAD_XBOX360_VENDOR(0x0f0d), /* Hori Controllers */ -- cgit v1.2.3