Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input

Pull input updates from Dmitry Torokhov:

 - new driver for PhoenixRC Flight Controller Adapter

 - new driver for RAVE SP Power button

 - fixes for autosuspend-related deadlocks in a few unput USB dirvers

 - support for 2nd wheel in ATech PS/2 mouse

 - fix for ALPS trackpoint detection on Thinkpad L570 and Latitude 7370

 - bunch of cleanups in various in PS/2 protocols

 - other assorted changes and fixes

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (35 commits)
  Input: i8042 - enable MUX on Sony VAIO VGN-CS series to fix touchpad
  Input: stmfts, s6sy761 - update my e-mail
  Input: stmfts - use async probe & suspend/resume to avoid 2s delay
  Input: ALPS - fix TrackStick detection on Thinkpad L570 and Latitude 7370
  Input: xpad - add PDP device id 0x02a4
  Input: alps - report pressure of v3 and v7 trackstick
  Input: pxrc - new driver for PhoenixRC Flight Controller Adapter
  Input: usbtouchscreen - do not rely on input_dev->users
  Input: usbtouchscreen - fix deadlock in autosuspend
  Input: pegasus_notetaker - do not rely on input_dev->users
  Input: pagasus_notetaker - fix deadlock in autosuspend
  Input: synaptics_usb - do not rely on input_dev->users
  Input: synaptics_usb - fix deadlock in autosuspend
  Input: gpio-keys - add support for wakeup event action
  Input: appletouch - use true and false for boolean values
  Input: silead - add Chuwi Hi8 support
  Input: analog - use get_cycles() on PPC
  Input: stmpe-keypad - remove VLA usage
  Input: i8042 - add Lenovo ThinkPad L460 to i8042 reset list
  Input: add RAVE SP Powerbutton driver
  ...
This commit is contained in:
Linus Torvalds
2018-04-05 13:21:57 -07:00
34 changed files with 1359 additions and 492 deletions
@@ -26,6 +26,14 @@ Optional subnode-properties:
If not specified defaults to 5.
- wakeup-source: Boolean, button can wake-up the system.
(Legacy property supported: "gpio-key,wakeup")
- wakeup-event-action: Specifies whether the key should wake the
system when asserted, when deasserted, or both. This property is
only valid for keys that wake up the system (e.g., when the
"wakeup-source" property is also provided).
Supported values are defined in linux-event-codes.h:
EV_ACT_ASSERTED - asserted
EV_ACT_DEASSERTED - deasserted
EV_ACT_ANY - both asserted and deasserted
- linux,can-disable: Boolean, indicates that button is connected
to dedicated (not shared) interrupt which can be disabled to
suppress events from the button.
@@ -0,0 +1,22 @@
Zodiac Inflight Innovations RAVE Supervisory Processor Power Button Bindings
RAVE SP input device is a "MFD cell" device corresponding to power
button functionality of RAVE Supervisory Processor. It is expected
that its Device Tree node is specified as a child of the node
corresponding to the parent RAVE SP device (as documented in
Documentation/devicetree/bindings/mfd/zii,rave-sp.txt)
Required properties:
- compatible: Should be "zii,rave-sp-pwrbutton"
Example:
rave-sp {
compatible = "zii,rave-sp-rdu1";
current-speed = <38400>;
pwrbutton {
compatible = "zii,rave-sp-pwrbutton";
};
}
+57
View File
@@ -0,0 +1,57 @@
=======================================================
pxrc - PhoenixRC Flight Controller Adapter
=======================================================
:Author: Marcus Folkesson <marcus.folkesson@gmail.com>
This driver let you use your own RC controller plugged into the
adapter that comes with PhoenixRC [1]_ or other compatible adapters.
The adapter supports 7 analog channels and 1 digital input switch.
Notes
=====
Many RC controllers is able to configure which stick goes to which channel.
This is also configurable in most simulators, so a matching is not necessary.
The driver is generating the following input event for analog channels:
+---------+----------------+
| Channel | Event |
+=========+================+
| 1 | ABS_X |
+---------+----------------+
| 2 | ABS_Y |
+---------+----------------+
| 3 | ABS_RX |
+---------+----------------+
| 4 | ABS_RY |
+---------+----------------+
| 5 | ABS_RUDDER |
+---------+----------------+
| 6 | ABS_THROTTLE |
+---------+----------------+
| 7 | ABS_MISC |
+---------+----------------+
The digital input switch is generated as an `BTN_A` event.
Manual Testing
==============
To test this driver's functionality you may use `input-event` which is part of
the `input layer utilities` suite [2]_.
For example::
> modprobe pxrc
> input-events <devnr>
To print all input events from input `devnr`.
References
==========
.. [1] http://www.phoenix-sim.com/
.. [2] https://www.kraxel.org/cgit/input/
+10
View File
@@ -351,4 +351,14 @@ config JOYSTICK_PSXPAD_SPI_FF
To drive rumble motor a dedicated power supply is required.
config JOYSTICK_PXRC
tristate "PhoenixRC Flight Controller Adapter"
depends on USB_ARCH_HAS_HCD
select USB
help
Say Y here if you want to use the PhoenixRC Flight Controller Adapter.
To compile this driver as a module, choose M here: the
module will be called pxrc.
endif
+1
View File
@@ -23,6 +23,7 @@ obj-$(CONFIG_JOYSTICK_JOYDUMP) += joydump.o
obj-$(CONFIG_JOYSTICK_MAGELLAN) += magellan.o
obj-$(CONFIG_JOYSTICK_MAPLE) += maplecontrol.o
obj-$(CONFIG_JOYSTICK_PSXPAD_SPI) += psxpad-spi.o
obj-$(CONFIG_JOYSTICK_PXRC) += pxrc.o
obj-$(CONFIG_JOYSTICK_SIDEWINDER) += sidewinder.o
obj-$(CONFIG_JOYSTICK_SPACEBALL) += spaceball.o
obj-$(CONFIG_JOYSTICK_SPACEORB) += spaceorb.o
+1 -1
View File
@@ -163,7 +163,7 @@ static unsigned int get_time_pit(void)
#define GET_TIME(x) do { x = (unsigned int)rdtsc(); } while (0)
#define DELTA(x,y) ((y)-(x))
#define TIME_NAME "TSC"
#elif defined(__alpha__) || defined(CONFIG_ARM) || defined(CONFIG_ARM64) || defined(CONFIG_RISCV)
#elif defined(__alpha__) || defined(CONFIG_ARM) || defined(CONFIG_ARM64) || defined(CONFIG_PPC) || defined(CONFIG_RISCV)
#define GET_TIME(x) do { x = get_cycles(); } while (0)
#define DELTA(x,y) ((y)-(x))
#define TIME_NAME "get_cycles"
+303
View File
@@ -0,0 +1,303 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Driver for Phoenix RC Flight Controller Adapter
*
* Copyright (C) 2018 Marcus Folkesson <marcus.folkesson@gmail.com>
*
*/
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/usb/input.h>
#include <linux/mutex.h>
#include <linux/input.h>
#define PXRC_VENDOR_ID (0x1781)
#define PXRC_PRODUCT_ID (0x0898)
static const struct usb_device_id pxrc_table[] = {
{ USB_DEVICE(PXRC_VENDOR_ID, PXRC_PRODUCT_ID) },
{ }
};
MODULE_DEVICE_TABLE(usb, pxrc_table);
struct pxrc {
struct input_dev *input;
struct usb_device *udev;
struct usb_interface *intf;
struct urb *urb;
struct mutex pm_mutex;
bool is_open;
__u8 epaddr;
char phys[64];
unsigned char *data;
size_t bsize;
};
static void pxrc_usb_irq(struct urb *urb)
{
struct pxrc *pxrc = urb->context;
int error;
switch (urb->status) {
case 0:
/* success */
break;
case -ETIME:
/* this urb is timing out */
dev_dbg(&pxrc->intf->dev,
"%s - urb timed out - was the device unplugged?\n",
__func__);
return;
case -ECONNRESET:
case -ENOENT:
case -ESHUTDOWN:
case -EPIPE:
/* this urb is terminated, clean up */
dev_dbg(&pxrc->intf->dev, "%s - urb shutting down with status: %d\n",
__func__, urb->status);
return;
default:
dev_dbg(&pxrc->intf->dev, "%s - nonzero urb status received: %d\n",
__func__, urb->status);
goto exit;
}
if (urb->actual_length == 8) {
input_report_abs(pxrc->input, ABS_X, pxrc->data[0]);
input_report_abs(pxrc->input, ABS_Y, pxrc->data[2]);
input_report_abs(pxrc->input, ABS_RX, pxrc->data[3]);
input_report_abs(pxrc->input, ABS_RY, pxrc->data[4]);
input_report_abs(pxrc->input, ABS_RUDDER, pxrc->data[5]);
input_report_abs(pxrc->input, ABS_THROTTLE, pxrc->data[6]);
input_report_abs(pxrc->input, ABS_MISC, pxrc->data[7]);
input_report_key(pxrc->input, BTN_A, pxrc->data[1]);
}
exit:
/* Resubmit to fetch new fresh URBs */
error = usb_submit_urb(urb, GFP_ATOMIC);
if (error && error != -EPERM)
dev_err(&pxrc->intf->dev,
"%s - usb_submit_urb failed with result: %d",
__func__, error);
}
static int pxrc_open(struct input_dev *input)
{
struct pxrc *pxrc = input_get_drvdata(input);
int retval;
mutex_lock(&pxrc->pm_mutex);
retval = usb_submit_urb(pxrc->urb, GFP_KERNEL);
if (retval) {
dev_err(&pxrc->intf->dev,
"%s - usb_submit_urb failed, error: %d\n",
__func__, retval);
retval = -EIO;
goto out;
}
pxrc->is_open = true;
out:
mutex_unlock(&pxrc->pm_mutex);
return retval;
}
static void pxrc_close(struct input_dev *input)
{
struct pxrc *pxrc = input_get_drvdata(input);
mutex_lock(&pxrc->pm_mutex);
usb_kill_urb(pxrc->urb);
pxrc->is_open = false;
mutex_unlock(&pxrc->pm_mutex);
}
static int pxrc_usb_init(struct pxrc *pxrc)
{
struct usb_endpoint_descriptor *epirq;
unsigned int pipe;
int retval;
/* Set up the endpoint information */
/* This device only has an interrupt endpoint */
retval = usb_find_common_endpoints(pxrc->intf->cur_altsetting,
NULL, NULL, &epirq, NULL);
if (retval) {
dev_err(&pxrc->intf->dev,
"Could not find endpoint\n");
goto error;
}
pxrc->bsize = usb_endpoint_maxp(epirq);
pxrc->epaddr = epirq->bEndpointAddress;
pxrc->data = devm_kmalloc(&pxrc->intf->dev, pxrc->bsize, GFP_KERNEL);
if (!pxrc->data) {
retval = -ENOMEM;
goto error;
}
usb_set_intfdata(pxrc->intf, pxrc);
usb_make_path(pxrc->udev, pxrc->phys, sizeof(pxrc->phys));
strlcat(pxrc->phys, "/input0", sizeof(pxrc->phys));
pxrc->urb = usb_alloc_urb(0, GFP_KERNEL);
if (!pxrc->urb) {
retval = -ENOMEM;
goto error;
}
pipe = usb_rcvintpipe(pxrc->udev, pxrc->epaddr),
usb_fill_int_urb(pxrc->urb, pxrc->udev, pipe, pxrc->data, pxrc->bsize,
pxrc_usb_irq, pxrc, 1);
error:
return retval;
}
static int pxrc_input_init(struct pxrc *pxrc)
{
pxrc->input = devm_input_allocate_device(&pxrc->intf->dev);
if (pxrc->input == NULL) {
dev_err(&pxrc->intf->dev, "couldn't allocate input device\n");
return -ENOMEM;
}
pxrc->input->name = "PXRC Flight Controller Adapter";
pxrc->input->phys = pxrc->phys;
usb_to_input_id(pxrc->udev, &pxrc->input->id);
pxrc->input->open = pxrc_open;
pxrc->input->close = pxrc_close;
input_set_capability(pxrc->input, EV_KEY, BTN_A);
input_set_abs_params(pxrc->input, ABS_X, 0, 255, 0, 0);
input_set_abs_params(pxrc->input, ABS_Y, 0, 255, 0, 0);
input_set_abs_params(pxrc->input, ABS_RX, 0, 255, 0, 0);
input_set_abs_params(pxrc->input, ABS_RY, 0, 255, 0, 0);
input_set_abs_params(pxrc->input, ABS_RUDDER, 0, 255, 0, 0);
input_set_abs_params(pxrc->input, ABS_THROTTLE, 0, 255, 0, 0);
input_set_abs_params(pxrc->input, ABS_MISC, 0, 255, 0, 0);
input_set_drvdata(pxrc->input, pxrc);
return input_register_device(pxrc->input);
}
static int pxrc_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
struct pxrc *pxrc;
int retval;
pxrc = devm_kzalloc(&intf->dev, sizeof(*pxrc), GFP_KERNEL);
if (!pxrc)
return -ENOMEM;
mutex_init(&pxrc->pm_mutex);
pxrc->udev = usb_get_dev(interface_to_usbdev(intf));
pxrc->intf = intf;
retval = pxrc_usb_init(pxrc);
if (retval)
goto error;
retval = pxrc_input_init(pxrc);
if (retval)
goto err_free_urb;
return 0;
err_free_urb:
usb_free_urb(pxrc->urb);
error:
return retval;
}
static void pxrc_disconnect(struct usb_interface *intf)
{
struct pxrc *pxrc = usb_get_intfdata(intf);
usb_free_urb(pxrc->urb);
usb_set_intfdata(intf, NULL);
}
static int pxrc_suspend(struct usb_interface *intf, pm_message_t message)
{
struct pxrc *pxrc = usb_get_intfdata(intf);
mutex_lock(&pxrc->pm_mutex);
if (pxrc->is_open)
usb_kill_urb(pxrc->urb);
mutex_unlock(&pxrc->pm_mutex);
return 0;
}
static int pxrc_resume(struct usb_interface *intf)
{
struct pxrc *pxrc = usb_get_intfdata(intf);
int retval = 0;
mutex_lock(&pxrc->pm_mutex);
if (pxrc->is_open && usb_submit_urb(pxrc->urb, GFP_KERNEL) < 0)
retval = -EIO;
mutex_unlock(&pxrc->pm_mutex);
return retval;
}
static int pxrc_pre_reset(struct usb_interface *intf)
{
struct pxrc *pxrc = usb_get_intfdata(intf);
mutex_lock(&pxrc->pm_mutex);
usb_kill_urb(pxrc->urb);
return 0;
}
static int pxrc_post_reset(struct usb_interface *intf)
{
struct pxrc *pxrc = usb_get_intfdata(intf);
int retval = 0;
if (pxrc->is_open && usb_submit_urb(pxrc->urb, GFP_KERNEL) < 0)
retval = -EIO;
mutex_unlock(&pxrc->pm_mutex);
return retval;
}
static int pxrc_reset_resume(struct usb_interface *intf)
{
return pxrc_resume(intf);
}
static struct usb_driver pxrc_driver = {
.name = "pxrc",
.probe = pxrc_probe,
.disconnect = pxrc_disconnect,
.id_table = pxrc_table,
.suspend = pxrc_suspend,
.resume = pxrc_resume,
.pre_reset = pxrc_pre_reset,
.post_reset = pxrc_post_reset,
.reset_resume = pxrc_reset_resume,
};
module_usb_driver(pxrc_driver);
MODULE_AUTHOR("Marcus Folkesson <marcus.folkesson@gmail.com>");
MODULE_DESCRIPTION("PhoenixRC Flight Controller Adapter");
MODULE_LICENSE("GPL v2");
+7 -2
View File
@@ -227,6 +227,7 @@ static const struct xpad_device {
{ 0x0e6f, 0x021f, "Rock Candy Gamepad for Xbox 360", 0, XTYPE_XBOX360 },
{ 0x0e6f, 0x0246, "Rock Candy Gamepad for Xbox One 2015", 0, XTYPE_XBOXONE },
{ 0x0e6f, 0x02ab, "PDP Controller for Xbox One", 0, XTYPE_XBOXONE },
{ 0x0e6f, 0x02a4, "PDP Wired Controller for Xbox One - Stealth Series", 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 },
@@ -475,7 +476,8 @@ static const u8 xboxone_hori_init[] = {
/*
* This packet is required for some of the PDP pads to start
* sending input reports. One of those pads is (0x0e6f:0x02ab).
* sending input reports. These pads include: (0x0e6f:0x02ab),
* (0x0e6f:0x02a4).
*/
static const u8 xboxone_pdp_init1[] = {
0x0a, 0x20, 0x00, 0x03, 0x00, 0x01, 0x14
@@ -483,7 +485,8 @@ static const u8 xboxone_pdp_init1[] = {
/*
* This packet is required for some of the PDP pads to start
* sending input reports. One of those pads is (0x0e6f:0x02ab).
* sending input reports. These pads include: (0x0e6f:0x02ab),
* (0x0e6f:0x02a4).
*/
static const u8 xboxone_pdp_init2[] = {
0x06, 0x20, 0x00, 0x02, 0x01, 0x00
@@ -521,6 +524,8 @@ static const struct xboxone_init_packet xboxone_init_packets[] = {
XBOXONE_INIT_PKT(0x0000, 0x0000, xboxone_fw2015_init),
XBOXONE_INIT_PKT(0x0e6f, 0x02ab, xboxone_pdp_init1),
XBOXONE_INIT_PKT(0x0e6f, 0x02ab, xboxone_pdp_init2),
XBOXONE_INIT_PKT(0x0e6f, 0x02a4, xboxone_pdp_init1),
XBOXONE_INIT_PKT(0x0e6f, 0x02a4, xboxone_pdp_init2),
XBOXONE_INIT_PKT(0x24c6, 0x541a, xboxone_rumblebegin_init),
XBOXONE_INIT_PKT(0x24c6, 0x542a, xboxone_rumblebegin_init),
XBOXONE_INIT_PKT(0x24c6, 0x543a, xboxone_rumblebegin_init),
+131 -14
View File
@@ -30,6 +30,7 @@
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/spinlock.h>
#include <dt-bindings/input/gpio-keys.h>
struct gpio_button_data {
const struct gpio_keys_button *button;
@@ -45,6 +46,7 @@ struct gpio_button_data {
unsigned int software_debounce; /* in msecs, for GPIO-driven buttons */
unsigned int irq;
unsigned int wakeup_trigger_type;
spinlock_t lock;
bool disabled;
bool key_pressed;
@@ -540,6 +542,8 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
}
if (bdata->gpiod) {
bool active_low = gpiod_is_active_low(bdata->gpiod);
if (button->debounce_interval) {
error = gpiod_set_debounce(bdata->gpiod,
button->debounce_interval * 1000);
@@ -568,6 +572,24 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
isr = gpio_keys_gpio_isr;
irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING;
switch (button->wakeup_event_action) {
case EV_ACT_ASSERTED:
bdata->wakeup_trigger_type = active_low ?
IRQ_TYPE_EDGE_FALLING : IRQ_TYPE_EDGE_RISING;
break;
case EV_ACT_DEASSERTED:
bdata->wakeup_trigger_type = active_low ?
IRQ_TYPE_EDGE_RISING : IRQ_TYPE_EDGE_FALLING;
break;
case EV_ACT_ANY:
/* fall through */
default:
/*
* For other cases, we are OK letting suspend/resume
* not reconfigure the trigger type.
*/
break;
}
} else {
if (!button->irq) {
dev_err(dev, "Found button without gpio or irq\n");
@@ -586,6 +608,11 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
isr = gpio_keys_irq_isr;
irqflags = 0;
/*
* For IRQ buttons, there is no interrupt for release.
* So we don't need to reconfigure the trigger type for wakeup.
*/
}
bdata->code = &ddata->keymap[idx];
@@ -718,6 +745,9 @@ gpio_keys_get_devtree_pdata(struct device *dev)
/* legacy name */
fwnode_property_read_bool(child, "gpio-key,wakeup");
fwnode_property_read_u32(child, "wakeup-event-action",
&button->wakeup_event_action);
button->can_disable =
fwnode_property_read_bool(child, "linux,can-disable");
@@ -845,19 +875,112 @@ static int gpio_keys_probe(struct platform_device *pdev)
return 0;
}
static int __maybe_unused
gpio_keys_button_enable_wakeup(struct gpio_button_data *bdata)
{
int error;
error = enable_irq_wake(bdata->irq);
if (error) {
dev_err(bdata->input->dev.parent,
"failed to configure IRQ %d as wakeup source: %d\n",
bdata->irq, error);
return error;
}
if (bdata->wakeup_trigger_type) {
error = irq_set_irq_type(bdata->irq,
bdata->wakeup_trigger_type);
if (error) {
dev_err(bdata->input->dev.parent,
"failed to set wakeup trigger %08x for IRQ %d: %d\n",
bdata->wakeup_trigger_type, bdata->irq, error);
disable_irq_wake(bdata->irq);
return error;
}
}
return 0;
}
static void __maybe_unused
gpio_keys_button_disable_wakeup(struct gpio_button_data *bdata)
{
int error;
/*
* The trigger type is always both edges for gpio-based keys and we do
* not support changing wakeup trigger for interrupt-based keys.
*/
if (bdata->wakeup_trigger_type) {
error = irq_set_irq_type(bdata->irq, IRQ_TYPE_EDGE_BOTH);
if (error)
dev_warn(bdata->input->dev.parent,
"failed to restore interrupt trigger for IRQ %d: %d\n",
bdata->irq, error);
}
error = disable_irq_wake(bdata->irq);
if (error)
dev_warn(bdata->input->dev.parent,
"failed to disable IRQ %d as wake source: %d\n",
bdata->irq, error);
}
static int __maybe_unused
gpio_keys_enable_wakeup(struct gpio_keys_drvdata *ddata)
{
struct gpio_button_data *bdata;
int error;
int i;
for (i = 0; i < ddata->pdata->nbuttons; i++) {
bdata = &ddata->data[i];
if (bdata->button->wakeup) {
error = gpio_keys_button_enable_wakeup(bdata);
if (error)
goto err_out;
}
bdata->suspended = true;
}
return 0;
err_out:
while (i--) {
bdata = &ddata->data[i];
if (bdata->button->wakeup)
gpio_keys_button_disable_wakeup(bdata);
bdata->suspended = false;
}
return error;
}
static void __maybe_unused
gpio_keys_disable_wakeup(struct gpio_keys_drvdata *ddata)
{
struct gpio_button_data *bdata;
int i;
for (i = 0; i < ddata->pdata->nbuttons; i++) {
bdata = &ddata->data[i];
bdata->suspended = false;
if (irqd_is_wakeup_set(irq_get_irq_data(bdata->irq)))
gpio_keys_button_disable_wakeup(bdata);
}
}
static int __maybe_unused gpio_keys_suspend(struct device *dev)
{
struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev);
struct input_dev *input = ddata->input;
int i;
int error;
if (device_may_wakeup(dev)) {
for (i = 0; i < ddata->pdata->nbuttons; i++) {
struct gpio_button_data *bdata = &ddata->data[i];
if (bdata->button->wakeup)
enable_irq_wake(bdata->irq);
bdata->suspended = true;
}
error = gpio_keys_enable_wakeup(ddata);
if (error)
return error;
} else {
mutex_lock(&input->mutex);
if (input->users)
@@ -873,15 +996,9 @@ static int __maybe_unused gpio_keys_resume(struct device *dev)
struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev);
struct input_dev *input = ddata->input;
int error = 0;
int i;
if (device_may_wakeup(dev)) {
for (i = 0; i < ddata->pdata->nbuttons; i++) {
struct gpio_button_data *bdata = &ddata->data[i];
if (bdata->button->wakeup)
disable_irq_wake(bdata->irq);
bdata->suspended = false;
}
gpio_keys_disable_wakeup(ddata);
} else {
mutex_lock(&input->mutex);
if (input->users)
+12 -4
View File
@@ -48,6 +48,14 @@
#define STMPE_KEYPAD_KEYMAP_MAX_SIZE \
(STMPE_KEYPAD_MAX_ROWS * STMPE_KEYPAD_MAX_COLS)
#define STMPE1601_NUM_DATA 5
#define STMPE2401_NUM_DATA 3
#define STMPE2403_NUM_DATA 5
/* Make sure it covers all cases above */
#define MAX_NUM_DATA 5
/**
* struct stmpe_keypad_variant - model-specific attributes
* @auto_increment: whether the KPC_DATA_BYTE register address
@@ -74,7 +82,7 @@ struct stmpe_keypad_variant {
static const struct stmpe_keypad_variant stmpe_keypad_variants[] = {
[STMPE1601] = {
.auto_increment = true,
.num_data = 5,
.num_data = STMPE1601_NUM_DATA,
.num_normal_data = 3,
.max_cols = 8,
.max_rows = 8,
@@ -84,7 +92,7 @@ static const struct stmpe_keypad_variant stmpe_keypad_variants[] = {
[STMPE2401] = {
.auto_increment = false,
.set_pullup = true,
.num_data = 3,
.num_data = STMPE2401_NUM_DATA,
.num_normal_data = 2,
.max_cols = 8,
.max_rows = 12,
@@ -94,7 +102,7 @@ static const struct stmpe_keypad_variant stmpe_keypad_variants[] = {
[STMPE2403] = {
.auto_increment = true,
.set_pullup = true,
.num_data = 5,
.num_data = STMPE2403_NUM_DATA,
.num_normal_data = 3,
.max_cols = 8,
.max_rows = 12,
@@ -156,7 +164,7 @@ static irqreturn_t stmpe_keypad_irq(int irq, void *dev)
struct stmpe_keypad *keypad = dev;
struct input_dev *input = keypad->input;
const struct stmpe_keypad_variant *variant = keypad->variant;
u8 fifo[variant->num_data];
u8 fifo[MAX_NUM_DATA];
int ret;
int i;
+9
View File
@@ -832,4 +832,13 @@ config INPUT_HISI_POWERKEY
To compile this driver as a module, choose M here: the
module will be called hisi_powerkey.
config INPUT_RAVE_SP_PWRBUTTON
tristate "RAVE SP Power button Driver"
depends on RAVE_SP_CORE
help
Say Y here if you want to enable power key reporting from RAVE SP
To compile this driver as a module, choose M here: the
module will be called rave-sp-pwrbutton.
endif
+1
View File
@@ -59,6 +59,7 @@ obj-$(CONFIG_INPUT_PMIC8XXX_PWRKEY) += pmic8xxx-pwrkey.o
obj-$(CONFIG_INPUT_POWERMATE) += powermate.o
obj-$(CONFIG_INPUT_PWM_BEEPER) += pwm-beeper.o
obj-$(CONFIG_INPUT_PWM_VIBRA) += pwm-vibra.o
obj-$(CONFIG_INPUT_RAVE_SP_PWRBUTTON) += rave-sp-pwrbutton.o
obj-$(CONFIG_INPUT_RB532_BUTTON) += rb532_button.o
obj-$(CONFIG_INPUT_REGULATOR_HAPTIC) += regulator-haptic.o
obj-$(CONFIG_INPUT_RETU_PWRBUTTON) += retu-pwrbutton.o
+94
View File
@@ -0,0 +1,94 @@
// SPDX-License-Identifier: GPL-2.0+
//
// Power Button driver for RAVE SP
//
// Copyright (C) 2017 Zodiac Inflight Innovations
//
//
#include <linux/input.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mfd/rave-sp.h>
#include <linux/platform_device.h>
#define RAVE_SP_EVNT_BUTTON_PRESS (RAVE_SP_EVNT_BASE + 0x00)
struct rave_sp_power_button {
struct input_dev *idev;
struct notifier_block nb;
};
static int rave_sp_power_button_event(struct notifier_block *nb,
unsigned long action, void *data)
{
struct rave_sp_power_button *pb =
container_of(nb, struct rave_sp_power_button, nb);
const u8 event = rave_sp_action_unpack_event(action);
const u8 value = rave_sp_action_unpack_value(action);
struct input_dev *idev = pb->idev;
if (event == RAVE_SP_EVNT_BUTTON_PRESS) {
input_report_key(idev, KEY_POWER, value);
input_sync(idev);
return NOTIFY_STOP;
}
return NOTIFY_DONE;
}
static int rave_sp_pwrbutton_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct rave_sp_power_button *pb;
struct input_dev *idev;
int error;
pb = devm_kzalloc(dev, sizeof(*pb), GFP_KERNEL);
if (!pb)
return -ENOMEM;
idev = devm_input_allocate_device(dev);
if (!idev)
return -ENOMEM;
idev->name = pdev->name;
input_set_capability(idev, EV_KEY, KEY_POWER);
error = input_register_device(idev);
if (error)
return error;
pb->idev = idev;
pb->nb.notifier_call = rave_sp_power_button_event;
pb->nb.priority = 128;
error = devm_rave_sp_register_event_notifier(dev, &pb->nb);
if (error)
return error;
return 0;
}
static const struct of_device_id rave_sp_pwrbutton_of_match[] = {
{ .compatible = "zii,rave-sp-pwrbutton" },
{}
};
static struct platform_driver rave_sp_pwrbutton_driver = {
.probe = rave_sp_pwrbutton_probe,
.driver = {
.name = KBUILD_MODNAME,
.of_match_table = rave_sp_pwrbutton_of_match,
},
};
module_platform_driver(rave_sp_pwrbutton_driver);
MODULE_DEVICE_TABLE(of, rave_sp_pwrbutton_of_match);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Andrey Vostrikov <andrey.vostrikov@cogentembedded.com>");
MODULE_AUTHOR("Nikita Yushchenko <nikita.yoush@cogentembedded.com>");
MODULE_AUTHOR("Andrey Smirnov <andrew.smirnov@gmail.com>");
MODULE_DESCRIPTION("RAVE SP Power Button driver");
+34 -30
View File
@@ -139,11 +139,11 @@ static const struct alps_model_info alps_model_data[] = {
};
static const struct alps_protocol_info alps_v3_protocol_data = {
ALPS_PROTO_V3, 0x8f, 0x8f, ALPS_DUALPOINT
ALPS_PROTO_V3, 0x8f, 0x8f, ALPS_DUALPOINT | ALPS_DUALPOINT_WITH_PRESSURE
};
static const struct alps_protocol_info alps_v3_rushmore_data = {
ALPS_PROTO_V3_RUSHMORE, 0x8f, 0x8f, ALPS_DUALPOINT
ALPS_PROTO_V3_RUSHMORE, 0x8f, 0x8f, ALPS_DUALPOINT | ALPS_DUALPOINT_WITH_PRESSURE
};
static const struct alps_protocol_info alps_v4_protocol_data = {
@@ -155,7 +155,7 @@ static const struct alps_protocol_info alps_v5_protocol_data = {
};
static const struct alps_protocol_info alps_v7_protocol_data = {
ALPS_PROTO_V7, 0x48, 0x48, ALPS_DUALPOINT
ALPS_PROTO_V7, 0x48, 0x48, ALPS_DUALPOINT | ALPS_DUALPOINT_WITH_PRESSURE
};
static const struct alps_protocol_info alps_v8_protocol_data = {
@@ -583,7 +583,7 @@ static void alps_process_trackstick_packet_v3(struct psmouse *psmouse)
x = (s8)(((packet[0] & 0x20) << 2) | (packet[1] & 0x7f));
y = (s8)(((packet[0] & 0x10) << 3) | (packet[2] & 0x7f));
z = (packet[4] & 0x7c) >> 2;
z = packet[4] & 0x7c;
/*
* The x and y values tend to be quite large, and when used
@@ -595,6 +595,7 @@ static void alps_process_trackstick_packet_v3(struct psmouse *psmouse)
input_report_rel(dev, REL_X, x);
input_report_rel(dev, REL_Y, -y);
input_report_abs(dev, ABS_PRESSURE, z);
/*
* Most ALPS models report the trackstick buttons in the touchpad
@@ -827,7 +828,7 @@ static void alps_process_packet_v6(struct psmouse *psmouse)
unsigned char *packet = psmouse->packet;
struct input_dev *dev = psmouse->dev;
struct input_dev *dev2 = priv->dev2;
int x, y, z, left, right, middle;
int x, y, z;
/*
* We can use Byte5 to distinguish if the packet is from Touchpad
@@ -847,9 +848,6 @@ static void alps_process_packet_v6(struct psmouse *psmouse)
x = packet[1] | ((packet[3] & 0x20) << 2);
y = packet[2] | ((packet[3] & 0x40) << 1);
z = packet[4];
left = packet[3] & 0x01;
right = packet[3] & 0x02;
middle = packet[3] & 0x04;
/* To prevent the cursor jump when finger lifted */
if (x == 0x7F && y == 0x7F && z == 0x7F)
@@ -859,9 +857,7 @@ static void alps_process_packet_v6(struct psmouse *psmouse)
input_report_rel(dev2, REL_X, (char)x / 4);
input_report_rel(dev2, REL_Y, -((char)y / 4));
input_report_key(dev2, BTN_LEFT, left);
input_report_key(dev2, BTN_RIGHT, right);
input_report_key(dev2, BTN_MIDDLE, middle);
psmouse_report_standard_buttons(dev2, packet[3]);
input_sync(dev2);
return;
@@ -871,8 +867,6 @@ static void alps_process_packet_v6(struct psmouse *psmouse)
x = packet[1] | ((packet[3] & 0x78) << 4);
y = packet[2] | ((packet[4] & 0x78) << 4);
z = packet[5];
left = packet[3] & 0x01;
right = packet[3] & 0x02;
if (z > 30)
input_report_key(dev, BTN_TOUCH, 1);
@@ -888,8 +882,8 @@ static void alps_process_packet_v6(struct psmouse *psmouse)
input_report_key(dev, BTN_TOOL_FINGER, z > 0);
/* v6 touchpad does not have middle button */
input_report_key(dev, BTN_LEFT, left);
input_report_key(dev, BTN_RIGHT, right);
packet[3] &= ~BIT(2);
psmouse_report_standard_buttons(dev2, packet[3]);
input_sync(dev);
}
@@ -1098,7 +1092,7 @@ static void alps_process_trackstick_packet_v7(struct psmouse *psmouse)
struct alps_data *priv = psmouse->private;
unsigned char *packet = psmouse->packet;
struct input_dev *dev2 = priv->dev2;
int x, y, z, left, right, middle;
int x, y, z;
/* It should be a DualPoint when received trackstick packet */
if (!(priv->flags & ALPS_DUALPOINT)) {
@@ -1112,16 +1106,11 @@ static void alps_process_trackstick_packet_v7(struct psmouse *psmouse)
((packet[3] & 0x20) << 1);
z = (packet[5] & 0x3f) | ((packet[3] & 0x80) >> 1);
left = (packet[1] & 0x01);
right = (packet[1] & 0x02) >> 1;
middle = (packet[1] & 0x04) >> 2;
input_report_rel(dev2, REL_X, (char)x);
input_report_rel(dev2, REL_Y, -((char)y));
input_report_abs(dev2, ABS_PRESSURE, z);
input_report_key(dev2, BTN_LEFT, left);
input_report_key(dev2, BTN_RIGHT, right);
input_report_key(dev2, BTN_MIDDLE, middle);
psmouse_report_standard_buttons(dev2, packet[1]);
input_sync(dev2);
}
@@ -1503,10 +1492,7 @@ static void alps_report_bare_ps2_packet(struct psmouse *psmouse,
alps_report_buttons(dev, dev2,
packet[0] & 1, packet[0] & 2, packet[0] & 4);
input_report_rel(dev, REL_X,
packet[1] ? packet[1] - ((packet[0] << 4) & 0x100) : 0);
input_report_rel(dev, REL_Y,
packet[2] ? ((packet[0] << 3) & 0x100) - packet[2] : 0);
psmouse_report_standard_motion(dev, packet);
input_sync(dev);
}
@@ -2544,13 +2530,31 @@ static int alps_update_btn_info_ss4_v2(unsigned char otp[][4],
}
static int alps_update_dual_info_ss4_v2(unsigned char otp[][4],
struct alps_data *priv)
struct alps_data *priv,
struct psmouse *psmouse)
{
bool is_dual = false;
int reg_val = 0;
struct ps2dev *ps2dev = &psmouse->ps2dev;
if (IS_SS4PLUS_DEV(priv->dev_id))
if (IS_SS4PLUS_DEV(priv->dev_id)) {
is_dual = (otp[0][0] >> 4) & 0x01;
if (!is_dual) {
/* For support TrackStick of Thinkpad L/E series */
if (alps_exit_command_mode(psmouse) == 0 &&
alps_enter_command_mode(psmouse) == 0) {
reg_val = alps_command_mode_read_reg(psmouse,
0xD7);
}
alps_exit_command_mode(psmouse);
ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE);
if (reg_val == 0x0C || reg_val == 0x1D)
is_dual = true;
}
}
if (is_dual)
priv->flags |= ALPS_DUALPOINT |
ALPS_DUALPOINT_WITH_PRESSURE;
@@ -2573,7 +2577,7 @@ static int alps_set_defaults_ss4_v2(struct psmouse *psmouse,
alps_update_btn_info_ss4_v2(otp, priv);
alps_update_dual_info_ss4_v2(otp, priv);
alps_update_dual_info_ss4_v2(otp, priv, psmouse);
return 0;
}
+3 -3
View File
@@ -587,7 +587,7 @@ static void atp_complete_geyser_1_2(struct urb *urb)
/* Perform size detection, if not done already */
if (unlikely(!dev->size_detect_done)) {
atp_detect_size(dev);
dev->size_detect_done = 1;
dev->size_detect_done = true;
goto exit;
}
}
@@ -813,7 +813,7 @@ static int atp_open(struct input_dev *input)
if (usb_submit_urb(dev->urb, GFP_ATOMIC))
return -EIO;
dev->open = 1;
dev->open = true;
return 0;
}
@@ -823,7 +823,7 @@ static void atp_close(struct input_dev *input)
usb_kill_urb(dev->urb);
cancel_work_sync(&dev->work);
dev->open = 0;
dev->open = false;
}
static int atp_handle_geyser(struct atp *dev)
+16 -24
View File
@@ -35,7 +35,7 @@
static int synaptics_send_cmd(struct psmouse *psmouse, unsigned char c,
unsigned char *param)
{
if (psmouse_sliced_command(psmouse, c) ||
if (ps2_sliced_command(&psmouse->ps2dev, c) ||
ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_GETINFO)) {
psmouse_err(psmouse, "%s query 0x%02x failed.\n", __func__, c);
return -1;
@@ -107,8 +107,8 @@ static int elantech_read_reg(struct psmouse *psmouse, unsigned char reg,
switch (etd->hw_version) {
case 1:
if (psmouse_sliced_command(psmouse, ETP_REGISTER_READ) ||
psmouse_sliced_command(psmouse, reg) ||
if (ps2_sliced_command(&psmouse->ps2dev, ETP_REGISTER_READ) ||
ps2_sliced_command(&psmouse->ps2dev, reg) ||
ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_GETINFO)) {
rc = -1;
}
@@ -162,9 +162,9 @@ static int elantech_write_reg(struct psmouse *psmouse, unsigned char reg,
switch (etd->hw_version) {
case 1:
if (psmouse_sliced_command(psmouse, ETP_REGISTER_WRITE) ||
psmouse_sliced_command(psmouse, reg) ||
psmouse_sliced_command(psmouse, val) ||
if (ps2_sliced_command(&psmouse->ps2dev, ETP_REGISTER_WRITE) ||
ps2_sliced_command(&psmouse->ps2dev, reg) ||
ps2_sliced_command(&psmouse->ps2dev, val) ||
ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11)) {
rc = -1;
}
@@ -279,8 +279,8 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse)
input_report_key(dev, BTN_TOOL_FINGER, fingers == 1);
input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2);
input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3);
input_report_key(dev, BTN_LEFT, packet[0] & 0x01);
input_report_key(dev, BTN_RIGHT, packet[0] & 0x02);
psmouse_report_standard_buttons(dev, packet[0]);
if (etd->fw_version < 0x020000 &&
(etd->capabilities[0] & ETP_CAP_HAS_ROCKER)) {
@@ -390,8 +390,7 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse)
input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2);
input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3);
input_report_key(dev, BTN_TOOL_QUADTAP, fingers == 4);
input_report_key(dev, BTN_LEFT, packet[0] & 0x01);
input_report_key(dev, BTN_RIGHT, packet[0] & 0x02);
psmouse_report_standard_buttons(dev, packet[0]);
if (etd->reports_pressure) {
input_report_abs(dev, ABS_PRESSURE, pres);
input_report_abs(dev, ABS_TOOL_WIDTH, width);
@@ -434,9 +433,7 @@ static void elantech_report_trackpoint(struct psmouse *psmouse,
x = packet[4] - (int)((packet[1]^0x80) << 1);
y = (int)((packet[2]^0x80) << 1) - packet[5];
input_report_key(tp_dev, BTN_LEFT, packet[0] & 0x01);
input_report_key(tp_dev, BTN_RIGHT, packet[0] & 0x02);
input_report_key(tp_dev, BTN_MIDDLE, packet[0] & 0x04);
psmouse_report_standard_buttons(tp_dev, packet[0]);
input_report_rel(tp_dev, REL_X, x);
input_report_rel(tp_dev, REL_Y, y);
@@ -526,12 +523,10 @@ static void elantech_report_absolute_v3(struct psmouse *psmouse,
input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3);
/* For clickpads map both buttons to BTN_LEFT */
if (etd->fw_version & 0x001000) {
if (etd->fw_version & 0x001000)
input_report_key(dev, BTN_LEFT, packet[0] & 0x03);
} else {
input_report_key(dev, BTN_LEFT, packet[0] & 0x01);
input_report_key(dev, BTN_RIGHT, packet[0] & 0x02);
}
else
psmouse_report_standard_buttons(dev, packet[0]);
input_report_abs(dev, ABS_PRESSURE, pres);
input_report_abs(dev, ABS_TOOL_WIDTH, width);
@@ -546,13 +541,10 @@ static void elantech_input_sync_v4(struct psmouse *psmouse)
unsigned char *packet = psmouse->packet;
/* For clickpads map both buttons to BTN_LEFT */
if (etd->fw_version & 0x001000) {
if (etd->fw_version & 0x001000)
input_report_key(dev, BTN_LEFT, packet[0] & 0x03);
} else {
input_report_key(dev, BTN_LEFT, packet[0] & 0x01);
input_report_key(dev, BTN_RIGHT, packet[0] & 0x02);
input_report_key(dev, BTN_MIDDLE, packet[0] & 0x04);
}
else
psmouse_report_standard_buttons(dev, packet[0]);
input_mt_report_pointer_emulation(dev, true);
input_sync(dev);
+33 -29
View File
@@ -17,6 +17,7 @@
#include <linux/libps2.h>
#include <linux/dmi.h>
#include <linux/slab.h>
#include <linux/types.h>
#include "psmouse.h"
#include "lifebook.h"
@@ -136,7 +137,7 @@ static psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse)
struct lifebook_data *priv = psmouse->private;
struct input_dev *dev1 = psmouse->dev;
struct input_dev *dev2 = priv ? priv->dev2 : NULL;
unsigned char *packet = psmouse->packet;
u8 *packet = psmouse->packet;
bool relative_packet = packet[0] & 0x08;
if (relative_packet || !lifebook_use_6byte_proto) {
@@ -188,14 +189,10 @@ static psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse)
}
if (dev2) {
if (relative_packet) {
input_report_rel(dev2, REL_X,
((packet[0] & 0x10) ? packet[1] - 256 : packet[1]));
input_report_rel(dev2, REL_Y,
-(int)((packet[0] & 0x20) ? packet[2] - 256 : packet[2]));
}
input_report_key(dev2, BTN_LEFT, packet[0] & 0x01);
input_report_key(dev2, BTN_RIGHT, packet[0] & 0x02);
if (relative_packet)
psmouse_report_standard_motion(dev2, packet);
psmouse_report_standard_buttons(dev2, packet[0]);
input_sync(dev2);
}
@@ -205,10 +202,12 @@ static psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse)
static int lifebook_absolute_mode(struct psmouse *psmouse)
{
struct ps2dev *ps2dev = &psmouse->ps2dev;
unsigned char param;
u8 param;
int error;
if (psmouse_reset(psmouse))
return -1;
error = psmouse_reset(psmouse);
if (error)
return error;
/*
* Enable absolute output -- ps2_command fails always but if
@@ -224,15 +223,15 @@ static int lifebook_absolute_mode(struct psmouse *psmouse)
static void lifebook_relative_mode(struct psmouse *psmouse)
{
struct ps2dev *ps2dev = &psmouse->ps2dev;
unsigned char param = 0x06;
u8 param = 0x06;
ps2_command(ps2dev, &param, PSMOUSE_CMD_SETRES);
}
static void lifebook_set_resolution(struct psmouse *psmouse, unsigned int resolution)
{
static const unsigned char params[] = { 0, 1, 2, 2, 3 };
unsigned char p;
static const u8 params[] = { 0, 1, 2, 2, 3 };
u8 p;
if (resolution == 0 || resolution > 400)
resolution = 400;
@@ -257,11 +256,11 @@ static void lifebook_disconnect(struct psmouse *psmouse)
int lifebook_detect(struct psmouse *psmouse, bool set_properties)
{
if (!lifebook_present)
return -1;
return -ENXIO;
if (desired_serio_phys &&
strcmp(psmouse->ps2dev.serio->phys, desired_serio_phys))
return -1;
return -ENXIO;
if (set_properties) {
psmouse->vendor = "Fujitsu";
@@ -294,10 +293,10 @@ static int lifebook_create_relative_device(struct psmouse *psmouse)
dev2->id.version = 0x0000;
dev2->dev.parent = &psmouse->ps2dev.serio->dev;
dev2->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
dev2->relbit[BIT_WORD(REL_X)] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
dev2->keybit[BIT_WORD(BTN_LEFT)] =
BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT);
input_set_capability(dev2, EV_REL, REL_X);
input_set_capability(dev2, EV_REL, REL_Y);
input_set_capability(dev2, EV_KEY, BTN_LEFT);
input_set_capability(dev2, EV_KEY, BTN_RIGHT);
error = input_register_device(priv->dev2);
if (error)
@@ -316,21 +315,26 @@ int lifebook_init(struct psmouse *psmouse)
{
struct input_dev *dev1 = psmouse->dev;
int max_coord = lifebook_use_6byte_proto ? 4096 : 1024;
int error;
if (lifebook_absolute_mode(psmouse))
return -1;
error = lifebook_absolute_mode(psmouse);
if (error)
return error;
dev1->evbit[0] = BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY);
dev1->relbit[0] = 0;
dev1->keybit[BIT_WORD(BTN_MOUSE)] = 0;
dev1->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
/* Clear default capabilities */
bitmap_zero(dev1->evbit, EV_CNT);
bitmap_zero(dev1->relbit, REL_CNT);
bitmap_zero(dev1->keybit, KEY_CNT);
input_set_capability(dev1, EV_KEY, BTN_TOUCH);
input_set_abs_params(dev1, ABS_X, 0, max_coord, 0, 0);
input_set_abs_params(dev1, ABS_Y, 0, max_coord, 0, 0);
if (!desired_serio_phys) {
if (lifebook_create_relative_device(psmouse)) {
error = lifebook_create_relative_device(psmouse);
if (error) {
lifebook_relative_mode(psmouse);
return -1;
return error;
}
}
+87 -65
View File
@@ -9,9 +9,11 @@
* the Free Software Foundation.
*/
#include <linux/bitops.h>
#include <linux/input.h>
#include <linux/serio.h>
#include <linux/libps2.h>
#include <linux/types.h>
#include "psmouse.h"
#include "logips2pp.h"
@@ -22,12 +24,12 @@
#define PS2PP_KIND_TRACKMAN 4
/* Logitech mouse features */
#define PS2PP_WHEEL 0x01
#define PS2PP_HWHEEL 0x02
#define PS2PP_SIDE_BTN 0x04
#define PS2PP_EXTRA_BTN 0x08
#define PS2PP_TASK_BTN 0x10
#define PS2PP_NAV_BTN 0x20
#define PS2PP_WHEEL BIT(0)
#define PS2PP_HWHEEL BIT(1)
#define PS2PP_SIDE_BTN BIT(2)
#define PS2PP_EXTRA_BTN BIT(3)
#define PS2PP_TASK_BTN BIT(4)
#define PS2PP_NAV_BTN BIT(5)
struct ps2pp_info {
u8 model;
@@ -42,7 +44,7 @@ struct ps2pp_info {
static psmouse_ret_t ps2pp_process_byte(struct psmouse *psmouse)
{
struct input_dev *dev = psmouse->dev;
unsigned char *packet = psmouse->packet;
u8 *packet = psmouse->packet;
if (psmouse->pktcnt < 3)
return PSMOUSE_GOOD_DATA;
@@ -58,28 +60,30 @@ static psmouse_ret_t ps2pp_process_byte(struct psmouse *psmouse)
case 0x0d: /* Mouse extra info */
input_report_rel(dev, packet[2] & 0x80 ? REL_HWHEEL : REL_WHEEL,
(int) (packet[2] & 8) - (int) (packet[2] & 7));
input_report_key(dev, BTN_SIDE, (packet[2] >> 4) & 1);
input_report_key(dev, BTN_EXTRA, (packet[2] >> 5) & 1);
input_report_rel(dev,
packet[2] & 0x80 ? REL_HWHEEL : REL_WHEEL,
-sign_extend32(packet[2], 3));
input_report_key(dev, BTN_SIDE, packet[2] & BIT(4));
input_report_key(dev, BTN_EXTRA, packet[2] & BIT(5));
break;
case 0x0e: /* buttons 4, 5, 6, 7, 8, 9, 10 info */
input_report_key(dev, BTN_SIDE, (packet[2]) & 1);
input_report_key(dev, BTN_EXTRA, (packet[2] >> 1) & 1);
input_report_key(dev, BTN_BACK, (packet[2] >> 3) & 1);
input_report_key(dev, BTN_FORWARD, (packet[2] >> 4) & 1);
input_report_key(dev, BTN_TASK, (packet[2] >> 2) & 1);
input_report_key(dev, BTN_SIDE, packet[2] & BIT(0));
input_report_key(dev, BTN_EXTRA, packet[2] & BIT(1));
input_report_key(dev, BTN_TASK, packet[2] & BIT(2));
input_report_key(dev, BTN_BACK, packet[2] & BIT(3));
input_report_key(dev, BTN_FORWARD, packet[2] & BIT(4));
break;
case 0x0f: /* TouchPad extra info */
input_report_rel(dev, packet[2] & 0x08 ? REL_HWHEEL : REL_WHEEL,
(int) ((packet[2] >> 4) & 8) - (int) ((packet[2] >> 4) & 7));
packet[0] = packet[2] | 0x08;
input_report_rel(dev,
packet[2] & 0x08 ? REL_HWHEEL : REL_WHEEL,
-sign_extend32(packet[2] >> 4, 3));
packet[0] = packet[2] | BIT(3);
break;
default:
@@ -88,16 +92,14 @@ static psmouse_ret_t ps2pp_process_byte(struct psmouse *psmouse)
(packet[1] >> 4) | (packet[0] & 0x30));
break;
}
psmouse_report_standard_buttons(dev, packet[0]);
} else {
/* Standard PS/2 motion data */
input_report_rel(dev, REL_X, packet[1] ? (int) packet[1] - (int) ((packet[0] << 4) & 0x100) : 0);
input_report_rel(dev, REL_Y, packet[2] ? (int) ((packet[0] << 3) & 0x100) - (int) packet[2] : 0);
psmouse_report_standard_packet(dev, packet);
}
input_report_key(dev, BTN_LEFT, packet[0] & 1);
input_report_key(dev, BTN_MIDDLE, (packet[0] >> 2) & 1);
input_report_key(dev, BTN_RIGHT, (packet[0] >> 1) & 1);
input_sync(dev);
return PSMOUSE_FULL_PACKET;
@@ -111,13 +113,17 @@ static psmouse_ret_t ps2pp_process_byte(struct psmouse *psmouse)
* Ugly.
*/
static int ps2pp_cmd(struct psmouse *psmouse, unsigned char *param, unsigned char command)
static int ps2pp_cmd(struct psmouse *psmouse, u8 *param, u8 command)
{
if (psmouse_sliced_command(psmouse, command))
return -1;
int error;
if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_POLL | 0x0300))
return -1;
error = ps2_sliced_command(&psmouse->ps2dev, command);
if (error)
return error;
error = ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_POLL | 0x0300);
if (error)
return error;
return 0;
}
@@ -133,7 +139,7 @@ static int ps2pp_cmd(struct psmouse *psmouse, unsigned char *param, unsigned cha
static void ps2pp_set_smartscroll(struct psmouse *psmouse, bool smartscroll)
{
struct ps2dev *ps2dev = &psmouse->ps2dev;
unsigned char param[4];
u8 param[4];
ps2pp_cmd(psmouse, param, 0x32);
@@ -171,7 +177,7 @@ static ssize_t ps2pp_attr_set_smartscroll(struct psmouse *psmouse, void *data,
}
PSMOUSE_DEFINE_ATTR(smartscroll, S_IWUSR | S_IRUGO, NULL,
ps2pp_attr_show_smartscroll, ps2pp_attr_set_smartscroll);
ps2pp_attr_show_smartscroll, ps2pp_attr_set_smartscroll);
/*
* Support 800 dpi resolution _only_ if the user wants it (there are good
@@ -179,11 +185,12 @@ PSMOUSE_DEFINE_ATTR(smartscroll, S_IWUSR | S_IRUGO, NULL,
* also good reasons to use it, let the user decide).
*/
static void ps2pp_set_resolution(struct psmouse *psmouse, unsigned int resolution)
static void ps2pp_set_resolution(struct psmouse *psmouse,
unsigned int resolution)
{
if (resolution > 400) {
struct ps2dev *ps2dev = &psmouse->ps2dev;
unsigned char param = 3;
u8 param = 3;
ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11);
ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11);
@@ -196,7 +203,8 @@ static void ps2pp_set_resolution(struct psmouse *psmouse, unsigned int resolutio
static void ps2pp_disconnect(struct psmouse *psmouse)
{
device_remove_file(&psmouse->ps2dev.serio->dev, &psmouse_attr_smartscroll.dattr);
device_remove_file(&psmouse->ps2dev.serio->dev,
&psmouse_attr_smartscroll.dattr);
}
static const struct ps2pp_info *get_model_info(unsigned char model)
@@ -269,24 +277,24 @@ static void ps2pp_set_model_properties(struct psmouse *psmouse,
struct input_dev *input_dev = psmouse->dev;
if (model_info->features & PS2PP_SIDE_BTN)
__set_bit(BTN_SIDE, input_dev->keybit);
input_set_capability(input_dev, EV_KEY, BTN_SIDE);
if (model_info->features & PS2PP_EXTRA_BTN)
__set_bit(BTN_EXTRA, input_dev->keybit);
input_set_capability(input_dev, EV_KEY, BTN_EXTRA);
if (model_info->features & PS2PP_TASK_BTN)
__set_bit(BTN_TASK, input_dev->keybit);
input_set_capability(input_dev, EV_KEY, BTN_TASK);
if (model_info->features & PS2PP_NAV_BTN) {
__set_bit(BTN_FORWARD, input_dev->keybit);
__set_bit(BTN_BACK, input_dev->keybit);
input_set_capability(input_dev, EV_KEY, BTN_FORWARD);
input_set_capability(input_dev, EV_KEY, BTN_BACK);
}
if (model_info->features & PS2PP_WHEEL)
__set_bit(REL_WHEEL, input_dev->relbit);
input_set_capability(input_dev, EV_REL, REL_WHEEL);
if (model_info->features & PS2PP_HWHEEL)
__set_bit(REL_HWHEEL, input_dev->relbit);
input_set_capability(input_dev, EV_REL, REL_HWHEEL);
switch (model_info->kind) {
@@ -318,6 +326,30 @@ static void ps2pp_set_model_properties(struct psmouse *psmouse,
}
}
static int ps2pp_setup_protocol(struct psmouse *psmouse,
const struct ps2pp_info *model_info)
{
int error;
psmouse->protocol_handler = ps2pp_process_byte;
psmouse->pktsize = 3;
if (model_info->kind != PS2PP_KIND_TP3) {
psmouse->set_resolution = ps2pp_set_resolution;
psmouse->disconnect = ps2pp_disconnect;
error = device_create_file(&psmouse->ps2dev.serio->dev,
&psmouse_attr_smartscroll.dattr);
if (error) {
psmouse_err(psmouse,
"failed to create smartscroll sysfs attribute, error: %d\n",
error);
return error;
}
}
return 0;
}
/*
* Logitech magic init. Detect whether the mouse is a Logitech one
@@ -328,9 +360,9 @@ static void ps2pp_set_model_properties(struct psmouse *psmouse,
int ps2pp_detect(struct psmouse *psmouse, bool set_properties)
{
struct ps2dev *ps2dev = &psmouse->ps2dev;
unsigned char param[4];
unsigned char model, buttons;
const struct ps2pp_info *model_info;
u8 param[4];
u8 model, buttons;
bool use_ps2pp = false;
int error;
@@ -346,7 +378,7 @@ int ps2pp_detect(struct psmouse *psmouse, bool set_properties)
buttons = param[1];
if (!model || !buttons)
return -1;
return -ENXIO;
model_info = get_model_info(model);
if (model_info) {
@@ -368,7 +400,8 @@ int ps2pp_detect(struct psmouse *psmouse, bool set_properties)
param[0] = 0;
if (!ps2_command(ps2dev, param, 0x13d1) &&
param[0] == 0x06 && param[1] == 0x00 && param[2] == 0x14) {
param[0] == 0x06 && param[1] == 0x00 &&
param[2] == 0x14) {
use_ps2pp = true;
}
@@ -387,7 +420,9 @@ int ps2pp_detect(struct psmouse *psmouse, bool set_properties)
}
} else {
psmouse_warn(psmouse, "Detected unknown Logitech mouse model %d\n", model);
psmouse_warn(psmouse,
"Detected unknown Logitech mouse model %d\n",
model);
}
if (set_properties) {
@@ -395,31 +430,18 @@ int ps2pp_detect(struct psmouse *psmouse, bool set_properties)
psmouse->model = model;
if (use_ps2pp) {
psmouse->protocol_handler = ps2pp_process_byte;
psmouse->pktsize = 3;
if (model_info->kind != PS2PP_KIND_TP3) {
psmouse->set_resolution = ps2pp_set_resolution;
psmouse->disconnect = ps2pp_disconnect;
error = device_create_file(&ps2dev->serio->dev,
&psmouse_attr_smartscroll.dattr);
if (error) {
psmouse_err(psmouse,
"failed to create smartscroll sysfs attribute, error: %d\n",
error);
return -1;
}
}
error = ps2pp_setup_protocol(psmouse, model_info);
if (error)
return error;
}
if (buttons >= 3)
__set_bit(BTN_MIDDLE, psmouse->dev->keybit);
input_set_capability(psmouse->dev, EV_KEY, BTN_MIDDLE);
if (model_info)
ps2pp_set_model_properties(psmouse, model_info, use_ps2pp);
}
return use_ps2pp ? 0 : -1;
return use_ps2pp ? 0 : -ENXIO;
}
+103 -86
View File
@@ -14,6 +14,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#define psmouse_fmt(fmt) fmt
#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/slab.h>
@@ -23,6 +24,7 @@
#include <linux/init.h>
#include <linux/libps2.h>
#include <linux/mutex.h>
#include <linux/types.h>
#include "psmouse.h"
#include "synaptics.h"
@@ -68,6 +70,10 @@ static bool psmouse_smartscroll = true;
module_param_named(smartscroll, psmouse_smartscroll, bool, 0644);
MODULE_PARM_DESC(smartscroll, "Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled.");
static bool psmouse_a4tech_2wheels;
module_param_named(a4tech_workaround, psmouse_a4tech_2wheels, bool, 0644);
MODULE_PARM_DESC(a4tech_workaround, "A4Tech second scroll wheel workaround, 1 = enabled, 0 = disabled (default).");
static unsigned int psmouse_resetafter = 5;
module_param_named(resetafter, psmouse_resetafter, uint, 0644);
MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never).");
@@ -116,13 +122,30 @@ static DEFINE_MUTEX(psmouse_mutex);
static struct workqueue_struct *kpsmoused_wq;
static void psmouse_report_standard_buttons(struct input_dev *dev, u8 buttons)
void psmouse_report_standard_buttons(struct input_dev *dev, u8 buttons)
{
input_report_key(dev, BTN_LEFT, buttons & BIT(0));
input_report_key(dev, BTN_MIDDLE, buttons & BIT(2));
input_report_key(dev, BTN_RIGHT, buttons & BIT(1));
}
void psmouse_report_standard_motion(struct input_dev *dev, u8 *packet)
{
int x, y;
x = packet[1] ? packet[1] - ((packet[0] << 4) & 0x100) : 0;
y = packet[2] ? packet[2] - ((packet[0] << 3) & 0x100) : 0;
input_report_rel(dev, REL_X, x);
input_report_rel(dev, REL_Y, -y);
}
void psmouse_report_standard_packet(struct input_dev *dev, u8 *packet)
{
psmouse_report_standard_buttons(dev, packet[0]);
psmouse_report_standard_motion(dev, packet);
}
/*
* psmouse_process_byte() analyzes the PS/2 data stream and reports
* relevant events to the input module once full packet has arrived.
@@ -130,7 +153,8 @@ static void psmouse_report_standard_buttons(struct input_dev *dev, u8 buttons)
psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse)
{
struct input_dev *dev = psmouse->dev;
unsigned char *packet = psmouse->packet;
u8 *packet = psmouse->packet;
int wheel;
if (psmouse->pktcnt < psmouse->pktsize)
return PSMOUSE_GOOD_DATA;
@@ -140,39 +164,52 @@ psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse)
switch (psmouse->protocol->type) {
case PSMOUSE_IMPS:
/* IntelliMouse has scroll wheel */
input_report_rel(dev, REL_WHEEL, -(signed char) packet[3]);
input_report_rel(dev, REL_WHEEL, -(s8) packet[3]);
break;
case PSMOUSE_IMEX:
/* Scroll wheel and buttons on IntelliMouse Explorer */
switch (packet[3] & 0xC0) {
case 0x80: /* vertical scroll on IntelliMouse Explorer 4.0 */
input_report_rel(dev, REL_WHEEL, (int) (packet[3] & 32) - (int) (packet[3] & 31));
input_report_rel(dev, REL_WHEEL,
-sign_extend32(packet[3], 5));
break;
case 0x40: /* horizontal scroll on IntelliMouse Explorer 4.0 */
input_report_rel(dev, REL_HWHEEL, (int) (packet[3] & 32) - (int) (packet[3] & 31));
input_report_rel(dev, REL_HWHEEL,
-sign_extend32(packet[3], 5));
break;
case 0x00:
case 0xC0:
input_report_rel(dev, REL_WHEEL, (int) (packet[3] & 8) - (int) (packet[3] & 7));
input_report_key(dev, BTN_SIDE, (packet[3] >> 4) & 1);
input_report_key(dev, BTN_EXTRA, (packet[3] >> 5) & 1);
wheel = sign_extend32(packet[3], 3);
/*
* Some A4Tech mice have two scroll wheels, with first
* one reporting +/-1 in the lower nibble, and second
* one reporting +/-2.
*/
if (psmouse_a4tech_2wheels && abs(wheel) > 1)
input_report_rel(dev, REL_HWHEEL, wheel / 2);
else
input_report_rel(dev, REL_WHEEL, -wheel);
input_report_key(dev, BTN_SIDE, BIT(4));
input_report_key(dev, BTN_EXTRA, BIT(5));
break;
}
break;
case PSMOUSE_GENPS:
/* Report scroll buttons on NetMice */
input_report_rel(dev, REL_WHEEL, -(signed char) packet[3]);
input_report_rel(dev, REL_WHEEL, -(s8) packet[3]);
/* Extra buttons on Genius NewNet 3D */
input_report_key(dev, BTN_SIDE, (packet[0] >> 6) & 1);
input_report_key(dev, BTN_EXTRA, (packet[0] >> 7) & 1);
input_report_key(dev, BTN_SIDE, BIT(6));
input_report_key(dev, BTN_EXTRA, BIT(7));
break;
case PSMOUSE_THINKPS:
/* Extra button on ThinkingMouse */
input_report_key(dev, BTN_EXTRA, (packet[0] >> 3) & 1);
input_report_key(dev, BTN_EXTRA, BIT(3));
/*
* Without this bit of weirdness moving up gives wildly
@@ -186,8 +223,8 @@ psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse)
* Cortron PS2 Trackball reports SIDE button in the
* 4th bit of the first byte.
*/
input_report_key(dev, BTN_SIDE, (packet[0] >> 3) & 1);
packet[0] |= 0x08;
input_report_key(dev, BTN_SIDE, BIT(3));
packet[0] |= BIT(3);
break;
default:
@@ -195,11 +232,8 @@ psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse)
}
/* Generic PS/2 Mouse */
psmouse_report_standard_buttons(dev,
packet[0] | psmouse->extra_buttons);
input_report_rel(dev, REL_X, packet[1] ? (int) packet[1] - (int) ((packet[0] << 4) & 0x100) : 0);
input_report_rel(dev, REL_Y, packet[2] ? (int) ((packet[0] << 3) & 0x100) - (int) packet[2] : 0);
packet[0] |= psmouse->extra_buttons;
psmouse_report_standard_packet(dev, packet);
input_sync(dev);
@@ -255,7 +289,7 @@ static int psmouse_handle_byte(struct psmouse *psmouse)
psmouse_notice(psmouse,
"issuing reconnect request\n");
serio_reconnect(psmouse->ps2dev.serio);
return -1;
return -EIO;
}
}
psmouse->pktcnt = 0;
@@ -306,7 +340,7 @@ static void psmouse_handle_oob_data(struct psmouse *psmouse, u8 data)
* for normal processing or gathering them as command response.
*/
static irqreturn_t psmouse_interrupt(struct serio *serio,
unsigned char data, unsigned int flags)
u8 data, unsigned int flags)
{
struct psmouse *psmouse = serio_get_drvdata(serio);
@@ -397,41 +431,20 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
return IRQ_HANDLED;
}
/*
* psmouse_sliced_command() sends an extended PS/2 command to the mouse
* using sliced syntax, understood by advanced devices, such as Logitech
* or Synaptics touchpads. The command is encoded as:
* 0xE6 0xE8 rr 0xE8 ss 0xE8 tt 0xE8 uu where (rr*64)+(ss*16)+(tt*4)+uu
* is the command.
*/
int psmouse_sliced_command(struct psmouse *psmouse, unsigned char command)
{
int i;
if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11))
return -1;
for (i = 6; i >= 0; i -= 2) {
unsigned char d = (command >> i) & 3;
if (ps2_command(&psmouse->ps2dev, &d, PSMOUSE_CMD_SETRES))
return -1;
}
return 0;
}
/*
* psmouse_reset() resets the mouse into power-on state.
*/
int psmouse_reset(struct psmouse *psmouse)
{
unsigned char param[2];
u8 param[2];
int error;
if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_RESET_BAT))
return -1;
error = ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_RESET_BAT);
if (error)
return error;
if (param[0] != PSMOUSE_RET_BAT && param[1] != PSMOUSE_RET_ID)
return -1;
return -EIO;
return 0;
}
@@ -441,8 +454,8 @@ int psmouse_reset(struct psmouse *psmouse)
*/
void psmouse_set_resolution(struct psmouse *psmouse, unsigned int resolution)
{
static const unsigned char params[] = { 0, 1, 2, 2, 3 };
unsigned char p;
static const u8 params[] = { 0, 1, 2, 2, 3 };
u8 p;
if (resolution == 0 || resolution > 200)
resolution = 200;
@@ -457,11 +470,12 @@ void psmouse_set_resolution(struct psmouse *psmouse, unsigned int resolution)
*/
static void psmouse_set_rate(struct psmouse *psmouse, unsigned int rate)
{
static const unsigned char rates[] = { 200, 100, 80, 60, 40, 20, 10, 0 };
unsigned char r;
static const u8 rates[] = { 200, 100, 80, 60, 40, 20, 10, 0 };
u8 r;
int i = 0;
while (rates[i] > rate) i++;
while (rates[i] > rate)
i++;
r = rates[i];
ps2_command(&psmouse->ps2dev, &r, PSMOUSE_CMD_SETRATE);
psmouse->rate = r;
@@ -533,7 +547,7 @@ bool psmouse_matches_pnp_id(struct psmouse *psmouse, const char * const ids[])
static int genius_detect(struct psmouse *psmouse, bool set_properties)
{
struct ps2dev *ps2dev = &psmouse->ps2dev;
unsigned char param[4];
u8 param[4];
param[0] = 3;
ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
@@ -543,7 +557,7 @@ static int genius_detect(struct psmouse *psmouse, bool set_properties)
ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO);
if (param[0] != 0x00 || param[1] != 0x33 || param[2] != 0x55)
return -1;
return -ENODEV;
if (set_properties) {
__set_bit(BTN_MIDDLE, psmouse->dev->keybit);
@@ -565,7 +579,7 @@ static int genius_detect(struct psmouse *psmouse, bool set_properties)
static int intellimouse_detect(struct psmouse *psmouse, bool set_properties)
{
struct ps2dev *ps2dev = &psmouse->ps2dev;
unsigned char param[2];
u8 param[2];
param[0] = 200;
ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE);
@@ -576,7 +590,7 @@ static int intellimouse_detect(struct psmouse *psmouse, bool set_properties)
ps2_command(ps2dev, param, PSMOUSE_CMD_GETID);
if (param[0] != 3)
return -1;
return -ENODEV;
if (set_properties) {
__set_bit(BTN_MIDDLE, psmouse->dev->keybit);
@@ -598,7 +612,7 @@ static int intellimouse_detect(struct psmouse *psmouse, bool set_properties)
static int im_explorer_detect(struct psmouse *psmouse, bool set_properties)
{
struct ps2dev *ps2dev = &psmouse->ps2dev;
unsigned char param[2];
u8 param[2];
intellimouse_detect(psmouse, 0);
@@ -611,7 +625,7 @@ static int im_explorer_detect(struct psmouse *psmouse, bool set_properties)
ps2_command(ps2dev, param, PSMOUSE_CMD_GETID);
if (param[0] != 4)
return -1;
return -ENODEV;
/* Magic to enable horizontal scrolling on IntelliMouse 4.0 */
param[0] = 200;
@@ -644,8 +658,8 @@ static int im_explorer_detect(struct psmouse *psmouse, bool set_properties)
static int thinking_detect(struct psmouse *psmouse, bool set_properties)
{
struct ps2dev *ps2dev = &psmouse->ps2dev;
unsigned char param[2];
static const unsigned char seq[] = { 20, 60, 40, 20, 20, 60, 40, 20, 20 };
u8 param[2];
static const u8 seq[] = { 20, 60, 40, 20, 20, 60, 40, 20, 20 };
int i;
param[0] = 10;
@@ -659,7 +673,7 @@ static int thinking_detect(struct psmouse *psmouse, bool set_properties)
ps2_command(ps2dev, param, PSMOUSE_CMD_GETID);
if (param[0] != 2)
return -1;
return -ENODEV;
if (set_properties) {
__set_bit(BTN_MIDDLE, psmouse->dev->keybit);
@@ -687,7 +701,7 @@ static int ps2bare_detect(struct psmouse *psmouse, bool set_properties)
* We have no way of figuring true number of buttons so let's
* assume that the device has 3.
*/
__set_bit(BTN_MIDDLE, psmouse->dev->keybit);
input_set_capability(psmouse->dev, EV_KEY, BTN_MIDDLE);
}
return 0;
@@ -942,20 +956,17 @@ static void psmouse_apply_defaults(struct psmouse *psmouse)
{
struct input_dev *input_dev = psmouse->dev;
memset(input_dev->evbit, 0, sizeof(input_dev->evbit));
memset(input_dev->keybit, 0, sizeof(input_dev->keybit));
memset(input_dev->relbit, 0, sizeof(input_dev->relbit));
memset(input_dev->absbit, 0, sizeof(input_dev->absbit));
memset(input_dev->mscbit, 0, sizeof(input_dev->mscbit));
bitmap_zero(input_dev->evbit, EV_CNT);
bitmap_zero(input_dev->keybit, KEY_CNT);
bitmap_zero(input_dev->relbit, REL_CNT);
bitmap_zero(input_dev->absbit, ABS_CNT);
bitmap_zero(input_dev->mscbit, MSC_CNT);
__set_bit(EV_KEY, input_dev->evbit);
__set_bit(EV_REL, input_dev->evbit);
input_set_capability(input_dev, EV_KEY, BTN_LEFT);
input_set_capability(input_dev, EV_KEY, BTN_RIGHT);
__set_bit(BTN_LEFT, input_dev->keybit);
__set_bit(BTN_RIGHT, input_dev->keybit);
__set_bit(REL_X, input_dev->relbit);
__set_bit(REL_Y, input_dev->relbit);
input_set_capability(input_dev, EV_REL, REL_X);
input_set_capability(input_dev, EV_REL, REL_Y);
__set_bit(INPUT_PROP_POINTER, input_dev->propbit);
@@ -1225,7 +1236,8 @@ static int psmouse_extensions(struct psmouse *psmouse,
static int psmouse_probe(struct psmouse *psmouse)
{
struct ps2dev *ps2dev = &psmouse->ps2dev;
unsigned char param[2];
u8 param[2];
int error;
/*
* First, we check if it's a mouse. It should send 0x00 or 0x03 in
@@ -1234,20 +1246,22 @@ static int psmouse_probe(struct psmouse *psmouse)
* subsequent ID queries, probably due to a firmware bug.
*/
param[0] = 0xa5;
if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETID))
return -1;
error = ps2_command(ps2dev, param, PSMOUSE_CMD_GETID);
if (error)
return error;
if (param[0] != 0x00 && param[0] != 0x03 &&
param[0] != 0x04 && param[0] != 0xff)
return -1;
return -ENODEV;
/*
* Then we reset and disable the mouse so that it doesn't generate
* events.
*/
if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_DIS))
psmouse_warn(psmouse, "Failed to reset mouse on %s\n",
ps2dev->serio->phys);
error = ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_DIS);
if (error)
psmouse_warn(psmouse, "Failed to reset mouse on %s: %d\n",
ps2dev->serio->phys, error);
return 0;
}
@@ -1288,10 +1302,13 @@ int psmouse_activate(struct psmouse *psmouse)
*/
int psmouse_deactivate(struct psmouse *psmouse)
{
if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_DISABLE)) {
psmouse_warn(psmouse, "Failed to deactivate mouse on %s\n",
psmouse->ps2dev.serio->phys);
return -1;
int error;
error = ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_DISABLE);
if (error) {
psmouse_warn(psmouse, "Failed to deactivate mouse on %s: %d\n",
psmouse->ps2dev.serio->phys, error);
return error;
}
psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
+4 -1
View File
@@ -131,7 +131,6 @@ struct psmouse {
void psmouse_queue_work(struct psmouse *psmouse, struct delayed_work *work,
unsigned long delay);
int psmouse_sliced_command(struct psmouse *psmouse, unsigned char command);
int psmouse_reset(struct psmouse *psmouse);
void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state);
void psmouse_set_resolution(struct psmouse *psmouse, unsigned int resolution);
@@ -140,6 +139,10 @@ int psmouse_activate(struct psmouse *psmouse);
int psmouse_deactivate(struct psmouse *psmouse);
bool psmouse_matches_pnp_id(struct psmouse *psmouse, const char * const ids[]);
void psmouse_report_standard_buttons(struct input_dev *, u8 buttons);
void psmouse_report_standard_motion(struct input_dev *, u8 *packet);
void psmouse_report_standard_packet(struct input_dev *, u8 *packet);
struct psmouse_attribute {
struct device_attribute dattr;
void *data;

Some files were not shown because too many files have changed in this diff Show More