summaryrefslogtreecommitdiffstats
path: root/drivers/input/rmi4/rmi_f30.c
diff options
context:
space:
mode:
authorBenjamin Tissoires <benjamin.tissoires@redhat.com>2017-02-08 00:26:45 -0800
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2017-02-09 13:01:34 -0800
commit81dec809aa728798c3ebff18c3d2d678237273aa (patch)
treea60e4a786645739776741b2f2b6b37082e1edee4 /drivers/input/rmi4/rmi_f30.c
parentbf3e8502eefdbb7ac1b8163e5c3acdcb505ae745 (diff)
downloadlinux-81dec809aa728798c3ebff18c3d2d678237273aa.tar.bz2
Input: synaptics-rmi4 - forward upper mechanical buttons to PS/2 guest
On the latest series of ThinkPads, the button events for the TrackPoint are reported through the touchpad itself as opposed to the TrackPoint device. In order to report these buttons properly, we need to forward them to the TrackPoint device and notify psmouse to send the button presses/releases. Signed-off-by: Lyude Paul <thatslyude@gmail.com> Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Diffstat (limited to 'drivers/input/rmi4/rmi_f30.c')
-rw-r--r--drivers/input/rmi4/rmi_f30.c60
1 files changed, 44 insertions, 16 deletions
diff --git a/drivers/input/rmi4/rmi_f30.c b/drivers/input/rmi4/rmi_f30.c
index c5eb4d034e84..3422464af229 100644
--- a/drivers/input/rmi4/rmi_f30.c
+++ b/drivers/input/rmi4/rmi_f30.c
@@ -48,6 +48,9 @@
+ 1 \
+ 1)
+#define TRACKSTICK_RANGE_START 3
+#define TRACKSTICK_RANGE_END 6
+
struct rmi_f30_ctrl_data {
int address;
int length;
@@ -76,6 +79,9 @@ struct f30_data {
u16 *gpioled_key_map;
struct input_dev *input;
+
+ struct rmi_function *f03;
+ bool trackstick_buttons;
};
static int rmi_f30_read_control_parameters(struct rmi_function *fn,
@@ -100,13 +106,20 @@ static void rmi_f30_report_button(struct rmi_function *fn,
{
unsigned int reg_num = button >> 3;
unsigned int bit_num = button & 0x07;
+ u16 key_code = f30->gpioled_key_map[button];
bool key_down = !(f30->data_regs[reg_num] & BIT(bit_num));
- rmi_dbg(RMI_DEBUG_FN, &fn->dev,
- "%s: call input report key (0x%04x) value (0x%02x)",
- __func__, f30->gpioled_key_map[button], key_down);
+ if (f30->trackstick_buttons &&
+ button >= TRACKSTICK_RANGE_START &&
+ button <= TRACKSTICK_RANGE_END) {
+ rmi_f03_overwrite_button(f30->f03, key_code, key_down);
+ } else {
+ rmi_dbg(RMI_DEBUG_FN, &fn->dev,
+ "%s: call input report key (0x%04x) value (0x%02x)",
+ __func__, key_code, key_down);
- input_report_key(f30->input, f30->gpioled_key_map[button], key_down);
+ input_report_key(f30->input, key_code, key_down);
+ }
}
static int rmi_f30_attention(struct rmi_function *fn, unsigned long *irq_bits)
@@ -138,10 +151,13 @@ static int rmi_f30_attention(struct rmi_function *fn, unsigned long *irq_bits)
}
}
- if (f30->has_gpio)
+ if (f30->has_gpio) {
for (i = 0; i < f30->gpioled_count; i++)
if (f30->gpioled_key_map[i] != KEY_RESERVED)
rmi_f30_report_button(fn, f30, i);
+ if (f30->trackstick_buttons)
+ rmi_f03_commit_buttons(f30->f03);
+ }
return 0;
}
@@ -154,6 +170,12 @@ static int rmi_f30_config(struct rmi_function *fn)
rmi_get_platform_data(fn->rmi_dev);
int error;
+ if (pdata->f30_data.trackstick_buttons) {
+ /* Try [re-]establish link to F03. */
+ f30->f03 = rmi_find_function(fn->rmi_dev, 0x03);
+ f30->trackstick_buttons = f30->f03 != NULL;
+ }
+
if (pdata->f30_data.disable) {
drv->clear_irq_bits(fn->rmi_dev, fn->irq_mask);
} else {
@@ -203,6 +225,8 @@ static int rmi_f30_map_gpios(struct rmi_function *fn,
rmi_get_platform_data(fn->rmi_dev);
struct input_dev *input = f30->input;
unsigned int button = BTN_LEFT;
+ unsigned int trackstick_button = BTN_LEFT;
+ bool button_mapped = false;
int i;
f30->gpioled_key_map = devm_kcalloc(&fn->dev,
@@ -215,19 +239,16 @@ static int rmi_f30_map_gpios(struct rmi_function *fn,
}
for (i = 0; i < f30->gpioled_count; i++) {
- if (rmi_f30_is_valid_button(i, f30->ctrl)) {
+ if (!rmi_f30_is_valid_button(i, f30->ctrl))
+ continue;
+
+ if (pdata->f30_data.trackstick_buttons &&
+ i >= TRACKSTICK_RANGE_START && i < TRACKSTICK_RANGE_END) {
+ f30->gpioled_key_map[i] = trackstick_button++;
+ } else if (!pdata->f30_data.buttonpad || !button_mapped) {
f30->gpioled_key_map[i] = button;
input_set_capability(input, EV_KEY, button++);
-
- /*
- * buttonpad might be given by
- * f30->has_mech_mouse_btns, but I am
- * not sure, so use only the pdata info
- */
- if (pdata->f30_data.buttonpad) {
- __set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
- break;
- }
+ button_mapped = true;
}
}
@@ -235,6 +256,13 @@ static int rmi_f30_map_gpios(struct rmi_function *fn,
input->keycodesize = sizeof(f30->gpioled_key_map[0]);
input->keycodemax = f30->gpioled_count;
+ /*
+ * Buttonpad could be also inferred from f30->has_mech_mouse_btns,
+ * but I am not sure, so use only the pdata info.
+ */
+ if (pdata->f30_data.buttonpad)
+ __set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
+
return 0;
}