Commit 3e069ada authored by Linus Torvalds's avatar Linus Torvalds

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

Pull input updates from Dmitry Torokhov:
 "Items of note:

   - evdev users can now limit or mask the kind of events they will
     receive.  This will allow applications such as power manager or
     network manager to only be woken when user presses special keys
     such as KEY_POWER or KEY_WIFI and not be bothered with ordinary
     key presses coming from keyboard

   - support for FocalTech FT6236 touchscreen controller

   - support for ROHM BU21023/24 touchscreen controller

   - edt-ft5x06 touchscreen driver got a face lift and can now be used
     with FT5506

   - support for Google Fiber TV Box remote controls

   - improvements in xpad driver (with more to come)

   - several parport-based drivers have been switched to the new device
     model

   - other miscellaneous driver improvements"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (70 commits)
  HID: hid-gfrm: avoid warning for input_configured API change
  HID: hid-input: allow input_configured callback return errors
  Input: evdev - fix bug in checking duplicate clock change request
  Input: add userio module
  Input: evdev - add event-mask API
  Input: snvs_pwrkey - remove duplicated semicolon
  HID: hid-gfrm: Google Fiber TV Box remote controls
  Input: e3x0-button - update Kconfig description
  Input: tegra-kbc - drop use of IRQF_NO_SUSPEND flag
  Input: tegra-kbc - enable support for the standard "wakeup-source" property
  Input: xen - check return value of xenbus_printf
  Input: hp_sdc_rtc - fix y2038 problem in proc_show
  Input: nomadik-ske-keypad - fix a trivial typo
  Input: xpad - fix clash of presence handling with LED setting
  Input: edt-ft5x06 - work around FT5506 firmware bug
  Input: edt-ft5x06 - add support for FT5506
  Input: edt-ft5x06 - add support for different max support points
  Input: edt-ft5x06 - use max support points to determine how much to read
  Input: rotary-encoder - add support for quarter-period mode
  Input: rotary-encoder - use of_property_read_bool
  ...
parents 02f0d3f7 e60e063c
* Dialog DA9062/63 OnKey Module
This module is part of the DA9062/DA9063. For more details about entire
chips see Documentation/devicetree/bindings/mfd/da9062.txt and
Documentation/devicetree/bindings/mfd/da9063.txt
This module provides KEY_POWER, KEY_SLEEP and events.
Required properties:
- compatible: should be one of:
dlg,da9062-onkey
dlg,da9063-onkey
Optional properties:
- dlg,disable-key-power : Disable power-down using a long key-press. If this
entry exists the OnKey driver will remove support for the KEY_POWER key
press. If this entry does not exist then by default the key-press
triggered power down is enabled and the OnKey will support both KEY_POWER
and KEY_SLEEP.
Example:
pmic0: da9062@58 {
onkey {
compatible = "dlg,da9063-onkey";
dlg,disable-key-power;
};
};
......@@ -13,11 +13,18 @@ Subnode properties:
- gpios: OF device-tree gpio specification.
- label: Descriptive name of the key.
- linux,code: Keycode to emit.
- linux,code: Key / Axis code to emit.
Optional subnode-properties:
- linux,input-type: Specify event type this button/key generates.
If not specified defaults to <1> == EV_KEY.
- linux,input-value: If linux,input-type is EV_ABS or EV_REL then this
value is sent for events this button generates when pressed.
EV_ABS/EV_REL axis will generate an event with a value of 0 when
all buttons with linux,input-type == type and linux,code == axis
are released. This value is interpreted as a signed 32 bit value,
e.g. to make a button generate a value of -1 use:
linux,input-value = <0xffffffff>; /* -1 */
- debounce-interval: Debouncing interval time in milliseconds.
If not specified defaults to 5.
- wakeup-source: Boolean, button can wake-up the system.
......
......@@ -14,7 +14,17 @@ Optional properties:
device, hence no steps need to be passed.
- rotary-encoder,rollover: Automatic rollove when the rotary value becomes
greater than the specified steps or smaller than 0. For absolute axis only.
- rotary-encoder,steps-per-period: Number of steps (stable states) per period.
The values have the following meaning:
1: Full-period mode (default)
2: Half-period mode
4: Quarter-period mode
- wakeup-source: Boolean, rotary encoder can wake up the system.
Deprecated properties:
- rotary-encoder,half-period: Makes the driver work on half-period mode.
This property is deprecated. Instead, a 'steps-per-period ' value should
be used, such as "rotary-encoder,steps-per-period = <2>".
See Documentation/input/rotary-encoder.txt for more information.
......
......@@ -5,6 +5,7 @@ There are 3 variants of the chip for various touch panel sizes
FT5206GE1 2.8" .. 3.8"
FT5306DE4 4.3" .. 7"
FT5406EE8 7" .. 8.9"
FT5506EEG 7" .. 8.9"
The software interface is identical for all those chips, so that
currently there is no need for the driver to distinguish between the
......@@ -17,6 +18,7 @@ Required properties:
- compatible: "edt,edt-ft5206"
or: "edt,edt-ft5306"
or: "edt,edt-ft5406"
or: "edt,edt-ft5506"
- reg: I2C slave address of the chip (0x38)
- interrupt-parent: a phandle pointing to the interrupt controller
......@@ -49,7 +51,7 @@ Example:
pinctrl-names = "default";
pinctrl-0 = <&edt_ft5x06_pins>;
interrupt-parent = <&gpio2>;
interrupts = <5 0>;
reset-gpios = <&gpio2 6 1>;
wake-gpios = <&gpio4 9 0>;
interrupts = <5 IRQ_TYPE_EDGE_FALLING>;
reset-gpios = <&gpio2 6 GPIO_ACTIVE_LOW>;
wake-gpios = <&gpio4 9 GPIO_ACTIVE_HIGH>;
};
* FocalTech FT6236 I2C touchscreen controller
Required properties:
- compatible : "focaltech,ft6236"
- reg : I2C slave address of the chip (0x38)
- interrupt-parent : a phandle pointing to the interrupt controller
serving the interrupt for this chip
- interrupts : interrupt specification for the touch controller
interrupt
- reset-gpios : GPIO specification for the RSTN input
- touchscreen-size-x : horizontal resolution of touchscreen (in pixels)
- touchscreen-size-y : vertical resolution of touchscreen (in pixels)
Optional properties:
- touchscreen-fuzz-x : horizontal noise value of the absolute input
device (in pixels)
- touchscreen-fuzz-y : vertical noise value of the absolute input
device (in pixels)
- touchscreen-inverted-x : X axis is inverted (boolean)
- touchscreen-inverted-y : Y axis is inverted (boolean)
- touchscreen-swapped-x-y: X and Y axis are swapped (boolean)
Swapping is done after inverting the axis
Example:
ft6x06@38 {
compatible = "focaltech,ft6236";
reg = <0x38>;
interrupt-parent = <&gpio>;
interrupts = <23 2>;
touchscreen-size-x = <320>;
touchscreen-size-y = <480>;
touchscreen-inverted-x;
touchscreen-swapped-x-y;
};
......@@ -82,6 +82,7 @@ everspin Everspin Technologies, Inc.
excito Excito
fcs Fairchild Semiconductor
firefly Firefly
focaltech FocalTech Systems Co.,Ltd
fsl Freescale Semiconductor
GEFanuc GE Fanuc Intelligent Platforms Embedded Systems, Inc.
gef GE Fanuc Intelligent Platforms Embedded Systems, Inc.
......
......@@ -9,8 +9,9 @@ peripherals with two wires. The outputs are phase-shifted by 90 degrees
and by triggering on falling and rising edges, the turn direction can
be determined.
Some encoders have both outputs low in stable states, whereas others also have
a stable state with both outputs high (half-period mode).
Some encoders have both outputs low in stable states, others also have
a stable state with both outputs high (half-period mode) and some have
a stable state in all steps (quarter-period mode).
The phase diagram of these two outputs look like this:
......@@ -32,6 +33,9 @@ The phase diagram of these two outputs look like this:
|<-->|
one step (half-period mode)
|<>|
one step (quarter-period mode)
For more information, please see
https://en.wikipedia.org/wiki/Rotary_encoder
......@@ -109,6 +113,7 @@ static struct rotary_encoder_platform_data my_rotary_encoder_info = {
.inverted_a = 0,
.inverted_b = 0,
.half_period = false,
.wakeup_source = false,
};
static struct platform_device rotary_encoder_device = {
......
The userio Protocol
(c) 2015 Stephen Chandler Paul <thatslyude@gmail.com>
Sponsored by Red Hat
--------------------------------------------------------------------------------
1. Introduction
~~~~~~~~~~~~~~~
This module is intended to try to make the lives of input driver developers
easier by allowing them to test various serio devices (mainly the various
touchpads found on laptops) without having to have the physical device in front
of them. userio accomplishes this by allowing any privileged userspace program
to directly interact with the kernel's serio driver and control a virtual serio
port from there.
2. Usage overview
~~~~~~~~~~~~~~~~~
In order to interact with the userio kernel module, one simply opens the
/dev/userio character device in their applications. Commands are sent to the
kernel module by writing to the device, and any data received from the serio
driver is read as-is from the /dev/userio device. All of the structures and
macros you need to interact with the device are defined in <linux/userio.h> and
<linux/serio.h>.
3. Command Structure
~~~~~~~~~~~~~~~~~~~~
The struct used for sending commands to /dev/userio is as follows:
struct userio_cmd {
__u8 type;
__u8 data;
};
"type" describes the type of command that is being sent. This can be any one
of the USERIO_CMD macros defined in <linux/userio.h>. "data" is the argument
that goes along with the command. In the event that the command doesn't have an
argument, this field can be left untouched and will be ignored by the kernel.
Each command should be sent by writing the struct directly to the character
device. In the event that the command you send is invalid, an error will be
returned by the character device and a more descriptive error will be printed
to the kernel log. Only one command can be sent at a time, any additional data
written to the character device after the initial command will be ignored.
To close the virtual serio port, just close /dev/userio.
4. Commands
~~~~~~~~~~~
4.1 USERIO_CMD_REGISTER
~~~~~~~~~~~~~~~~~~~~~~~
Registers the port with the serio driver and begins transmitting data back and
forth. Registration can only be performed once a port type is set with
USERIO_CMD_SET_PORT_TYPE. Has no argument.
4.2 USERIO_CMD_SET_PORT_TYPE
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Sets the type of port we're emulating, where "data" is the port type being
set. Can be any of the macros from <linux/serio.h>. For example: SERIO_8042
would set the port type to be a normal PS/2 port.
4.3 USERIO_CMD_SEND_INTERRUPT
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Sends an interrupt through the virtual serio port to the serio driver, where
"data" is the interrupt data being sent.
5. Userspace tools
~~~~~~~~~~~~~~~~~~
The userio userspace tools are able to record PS/2 devices using some of the
debugging information from i8042, and play back the devices on /dev/userio. The
latest version of these tools can be found at:
https://github.com/Lyude/ps2emu
......@@ -11306,6 +11306,12 @@ S: Maintained
F: drivers/media/v4l2-core/videobuf2-*
F: include/media/videobuf2-*
VIRTUAL SERIO DEVICE DRIVER
M: Stephen Chandler Paul <thatslyude@gmail.com>
S: Maintained
F: drivers/input/serio/userio.c
F: include/uapi/linux/userio.h
VIRTIO CONSOLE DRIVER
M: Amit Shah <amit.shah@redhat.com>
L: virtualization@lists.linux-foundation.org
......
......@@ -502,7 +502,7 @@ edt-ft5306@38 {
reg = <0x38>;
interrupt-parent = <&gpio0>;
interrupts = <31 0>;
interrupts = <31 IRQ_TYPE_EDGE_FALLING>;
reset-gpios = <&gpio1 28 GPIO_ACTIVE_LOW>;
......
......@@ -13,6 +13,7 @@
/dts-v1/;
#include "imx28.dtsi"
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/irq.h>
/ {
model = "Ka-Ro electronics TX28 module";
......@@ -324,7 +325,7 @@ polytouch: edt-ft5x06@38 {
pinctrl-names = "default";
pinctrl-0 = <&tx28_edt_ft5x06_pins>;
interrupt-parent = <&gpio2>;
interrupts = <5 0>;
interrupts = <5 IRQ_TYPE_EDGE_FALLING>;
reset-gpios = <&gpio2 6 GPIO_ACTIVE_LOW>;
wake-gpios = <&gpio4 9 GPIO_ACTIVE_HIGH>;
};
......
......@@ -12,6 +12,7 @@
/dts-v1/;
#include "imx53-tx53.dtsi"
#include <dt-bindings/input/input.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/pwm/pwm.h>
/ {
......@@ -216,7 +217,7 @@ polytouch: edt-ft5x06@38 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_edt_ft5x06_1>;
interrupt-parent = <&gpio6>;
interrupts = <15 0>;
interrupts = <15 IRQ_TYPE_EDGE_FALLING>;
reset-gpios = <&gpio2 22 GPIO_ACTIVE_LOW>;
wake-gpios = <&gpio2 21 GPIO_ACTIVE_HIGH>;
};
......
......@@ -11,6 +11,7 @@
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/pwm/pwm.h>
/ {
......@@ -272,7 +273,7 @@ polytouch: edt-ft5x06@38 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_edt_ft5x06>;
interrupt-parent = <&gpio6>;
interrupts = <15 0>;
interrupts = <15 IRQ_TYPE_EDGE_FALLING>;
reset-gpios = <&gpio2 22 GPIO_ACTIVE_LOW>;
wake-gpios = <&gpio2 21 GPIO_ACTIVE_HIGH>;
linux,wakeup;
......
......@@ -257,6 +257,12 @@ config HID_GEMBIRD
---help---
Support for Gembird JPD-DualForce 2.
config HID_GFRM
tristate "Google Fiber TV Box remote control support"
depends on HID
---help---
Support for Google Fiber TV Box remote controls
config HID_HOLTEK
tristate "Holtek HID devices"
depends on USB_HID
......
......@@ -37,6 +37,7 @@ obj-$(CONFIG_HID_ELECOM) += hid-elecom.o
obj-$(CONFIG_HID_ELO) += hid-elo.o
obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o
obj-$(CONFIG_HID_GEMBIRD) += hid-gembird.o
obj-$(CONFIG_HID_GFRM) += hid-gfrm.o
obj-$(CONFIG_HID_GT683R) += hid-gt683r.o
obj-$(CONFIG_HID_GYRATION) += hid-gyration.o
obj-$(CONFIG_HID_HOLTEK) += hid-holtek-kbd.o
......
......@@ -256,7 +256,7 @@ static int appleir_raw_event(struct hid_device *hid, struct hid_report *report,
return 0;
}
static void appleir_input_configured(struct hid_device *hid,
static int appleir_input_configured(struct hid_device *hid,
struct hid_input *hidinput)
{
struct input_dev *input_dev = hidinput->input;
......@@ -275,6 +275,8 @@ static void appleir_input_configured(struct hid_device *hid,
for (i = 0; i < ARRAY_SIZE(appleir_key_table); i++)
set_bit(appleir->keymap[i], input_dev->keybit);
clear_bit(KEY_RESERVED, input_dev->keybit);
return 0;
}
static int appleir_input_mapping(struct hid_device *hid,
......
......@@ -37,7 +37,7 @@ static bool use_fw_quirk = true;
module_param(use_fw_quirk, bool, S_IRUGO);
MODULE_PARM_DESC(use_fw_quirk, "Do periodic pokes for broken M firmwares (default = true)");
static void elo_input_configured(struct hid_device *hdev,
static int elo_input_configured(struct hid_device *hdev,
struct hid_input *hidinput)
{
struct input_dev *input = hidinput->input;
......@@ -45,6 +45,8 @@ static void elo_input_configured(struct hid_device *hdev,
set_bit(BTN_TOUCH, input->keybit);
set_bit(ABS_PRESSURE, input->absbit);
input_set_abs_params(input, ABS_PRESSURE, 0, 256, 0, 0);
return 0;
}
static void elo_process_data(struct input_dev *input, const u8 *data, int size)
......
/*
* HID driver for Google Fiber TV Box remote controls
*
* Copyright (c) 2014-2015 Google Inc.
*
* Author: Petri Gynther <pgynther@google.com>
*
* 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.
*/
#include <linux/device.h>
#include <linux/hid.h>
#include <linux/input.h>
#include <linux/module.h>
#include "hid-ids.h"
#define GFRM100 1 /* Google Fiber GFRM100 (Bluetooth classic) */
#define GFRM200 2 /* Google Fiber GFRM200 (Bluetooth LE) */
#define GFRM100_SEARCH_KEY_REPORT_ID 0xF7
#define GFRM100_SEARCH_KEY_DOWN 0x0
#define GFRM100_SEARCH_KEY_AUDIO_DATA 0x1
#define GFRM100_SEARCH_KEY_UP 0x2
static u8 search_key_dn[3] = {0x40, 0x21, 0x02};
static u8 search_key_up[3] = {0x40, 0x00, 0x00};
static int gfrm_input_mapping(struct hid_device *hdev, struct hid_input *hi,
struct hid_field *field, struct hid_usage *usage,
unsigned long **bit, int *max)
{
unsigned long hdev_type = (unsigned long) hid_get_drvdata(hdev);
if (hdev_type == GFRM100) {
if (usage->hid == (HID_UP_CONSUMER | 0x4)) {
/* Consumer.0004 -> KEY_INFO */
hid_map_usage_clear(hi, usage, bit, max, EV_KEY, KEY_INFO);
return 1;
}
if (usage->hid == (HID_UP_CONSUMER | 0x41)) {
/* Consumer.0041 -> KEY_OK */
hid_map_usage_clear(hi, usage, bit, max, EV_KEY, KEY_OK);
return 1;
}
}
return 0;
}
static int gfrm_raw_event(struct hid_device *hdev, struct hid_report *report,
u8 *data, int size)
{
unsigned long hdev_type = (unsigned long) hid_get_drvdata(hdev);
int ret = 0;
if (hdev_type != GFRM100)
return 0;
if (size < 2 || data[0] != GFRM100_SEARCH_KEY_REPORT_ID)
return 0;
/*
* Convert GFRM100 Search key reports into Consumer.0221 (Key.Search)
* reports. Ignore audio data.
*/
switch (data[1]) {
case GFRM100_SEARCH_KEY_DOWN:
ret = hid_report_raw_event(hdev, HID_INPUT_REPORT, search_key_dn,
sizeof(search_key_dn), 1);
break;
case GFRM100_SEARCH_KEY_AUDIO_DATA:
break;
case GFRM100_SEARCH_KEY_UP:
ret = hid_report_raw_event(hdev, HID_INPUT_REPORT, search_key_up,
sizeof(search_key_up), 1);
break;
default:
break;
}
return (ret < 0) ? ret : -1;
}
static int gfrm_input_configured(struct hid_device *hid, struct hid_input *hidinput)
{
/*
* Enable software autorepeat with:
* - repeat delay: 400 msec
* - repeat period: 100 msec
*/
input_enable_softrepeat(hidinput->input, 400, 100);
return 0;
}
static int gfrm_probe(struct hid_device *hdev, const struct hid_device_id *id)
{
int ret;
hid_set_drvdata(hdev, (void *) id->driver_data);
ret = hid_parse(hdev);
if (ret)
goto done;
if (id->driver_data == GFRM100) {
/*
* GFRM100 HID Report Descriptor does not describe the Search
* key reports. Thus, we need to add it manually here, so that
* those reports reach gfrm_raw_event() from hid_input_report().
*/
if (!hid_register_report(hdev, HID_INPUT_REPORT,
GFRM100_SEARCH_KEY_REPORT_ID)) {
ret = -ENOMEM;
goto done;
}
}
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
done:
return ret;
}
static void gfrm_remove(struct hid_device *hdev)
{
hid_hw_stop(hdev);
hid_set_drvdata(hdev, NULL);
}
static const struct hid_device_id gfrm_devices[] = {
{ HID_BLUETOOTH_DEVICE(0x58, 0x2000),
.driver_data = GFRM100 },
{ HID_BLUETOOTH_DEVICE(0x471, 0x2210),
.driver_data = GFRM200 },
{ }
};
MODULE_DEVICE_TABLE(hid, gfrm_devices);
static struct hid_driver gfrm_driver = {
.name = "gfrm",
.id_table = gfrm_devices,
.probe = gfrm_probe,
.remove = gfrm_remove,
.input_mapping = gfrm_input_mapping,
.raw_event = gfrm_raw_event,
.input_configured = gfrm_input_configured,
};
module_hid_driver(gfrm_driver);
MODULE_AUTHOR("Petri Gynther <pgynther@google.com>");
MODULE_DESCRIPTION("Google Fiber TV Box remote control driver");
MODULE_LICENSE("GPL");
......@@ -1510,8 +1510,9 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
* UGCI) cram a lot of unrelated inputs into the
* same interface. */
hidinput->report = report;
if (drv->input_configured)
drv->input_configured(hid, hidinput);
if (drv->input_configured &&
drv->input_configured(hid, hidinput))
goto out_cleanup;
if (input_register_device(hidinput->input))
goto out_cleanup;
hidinput = NULL;
......@@ -1532,8 +1533,9 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
}
if (hidinput) {
if (drv->input_configured)
drv->input_configured(hid, hidinput);
if (drv->input_configured &&
drv->input_configured(hid, hidinput))
goto out_cleanup;
if (input_register_device(hidinput->input))
goto out_cleanup;
}
......
......@@ -848,7 +848,7 @@ static void lenovo_remove(struct hid_device *hdev)
hid_hw_stop(hdev);
}
static void lenovo_input_configured(struct hid_device *hdev,
static int lenovo_input_configured(struct hid_device *hdev,
struct hid_input *hi)
{
switch (hdev->product) {
......@@ -863,6 +863,8 @@ static void lenovo_input_configured(struct hid_device *hdev,
}
break;
}
return 0;
}
......
......@@ -1160,13 +1160,15 @@ static void hidpp_populate_input(struct hidpp_device *hidpp,
m560_populate_input(hidpp, input, origin_is_hid_core);
}
static void hidpp_input_configured(struct hid_device *hdev,
static int hidpp_input_configured(struct hid_device *hdev,
struct hid_input *hidinput)
{
struct hidpp_device *hidpp = hid_get_drvdata(hdev);
struct input_dev *input = hidinput->input;
hidpp_populate_input(hidpp, input, true);
return 0;
}
static int hidpp_raw_hidpp_event(struct hidpp_device *hidpp, u8 *data,
......
......@@ -471,18 +471,22 @@ static int magicmouse_input_mapping(struct hid_device *hdev,
return 0;
}
static void magicmouse_input_configured(struct hid_device *hdev,
static int magicmouse_input_configured(struct hid_device *hdev,
struct hid_input *hi)
{
struct magicmouse_sc *msc = hid_get_drvdata(hdev);
int ret;
int ret = magicmouse_setup_input(msc->input, hdev);
ret = magicmouse_setup_input(msc->input, hdev);
if (ret) {
hid_err(hdev, "magicmouse setup input failed (%d)\n", ret);
/* clean msc->input to notify probe() of the failure */
msc->input = NULL;
return ret;
}
return 0;
}
......
......@@ -725,12 +725,13 @@ static void mt_touch_report(struct hid_device *hid, struct hid_report *report)
mt_sync_frame(td, report->field[0]->hidinput->input);
}
static void mt_touch_input_configured(struct hid_device *hdev,
static int mt_touch_input_configured(struct hid_device *hdev,
struct hid_input *hi)
{
struct mt_device *td = hid_get_drvdata(hdev);
struct mt_class *cls = &td->mtclass;
struct input_dev *input = hi->input;
int ret;
if (!td->maxcontacts)
td->maxcontacts = MT_DEFAULT_MAXCONTACT;
......@@ -752,9 +753,12 @@ static void mt_touch_input_configured(struct hid_device *hdev,
if (td->is_buttonpad)
__set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
input_mt_init_slots(input, td->maxcontacts, td->mt_flags);
ret = input_mt_init_slots(input, td->maxcontacts, td->mt_flags);
if (ret)
return ret;
td->mt_flags = 0;
return 0;
}
static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
......@@ -930,15 +934,19 @@ static void mt_post_parse(struct mt_device *td)
cls->quirks &= ~MT_QUIRK_CONTACT_CNT_ACCURATE;
}
static void mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
{
struct mt_device *td = hid_get_drvdata(hdev);
char *name;
const char *suffix = NULL;
struct hid_field *field = hi->report->field[0];
int ret;
if (hi->report->id == td->mt_report_id)
mt_touch_input_configured(hdev, hi);
if (hi->report->id == td->mt_report_id) {
ret = mt_touch_input_configured(hdev, hi);
if (ret)
return ret;
}
/*
* some egalax touchscreens have "application == HID_DG_TOUCHSCREEN"
......@@ -989,6 +997,8 @@ static void mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
hi->input->name = name;
}
}
return 0;
}
static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
......
......@@ -859,14 +859,14 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field,
return 1;
}
static void ntrig_input_configured(struct hid_device *hid,
static int ntrig_input_configured(struct hid_device *hid,
struct hid_input *hidinput)
{
struct input_dev *input = hidinput->input;
if (hidinput->report->maxfield < 1)
return;
return 0;
switch (hidinput->report->field[0]->application) {
case HID_DG_PEN:
......@@ -890,6 +890,8 @@ static void ntrig_input_configured(struct hid_device *hid,
"N-Trig MultiTouch";
break;
}
return 0;
}
static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id)
......
......@@ -1173,7 +1173,7 @@ static int rmi_populate(struct hid_device *hdev)
return 0;
}
static void rmi_input_configured(struct hid_device *hdev, struct hid_input *hi)
static int rmi_input_configured(struct hid_device *hdev, struct hid_input *hi)
{
struct rmi_data *data = hid_get_drvdata(hdev);
struct input_dev *input = hi->input;
......@@ -1185,10 +1185,10 @@ static void rmi_input_configured(struct hid_device *hdev, struct hid_input *hi)
hid_dbg(hdev, "Opening low level driver\n");
ret = hid_hw_open(hdev);
if (ret)
return;
return ret;
if (!(data->device_flags & RMI_DEVICE))
return;
return 0;
/* Allow incoming hid reports */
hid_device_io_start(hdev);
......@@ -1228,7 +1228,9 @@ static void rmi_input_configured(struct hid_device *hdev, struct hid_input *hi)
input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, 0x0f, 0, 0);
input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0, 0x0f, 0, 0);
input_mt_init_slots(input, data->max_fingers, INPUT_MT_POINTER);
ret = input_mt_init_slots(input, data->max_fingers, INPUT_MT_POINTER);
if (ret < 0)
goto exit;
if (data->button_count) {
__set_bit(EV_KEY, input->evbit);
......@@ -1244,6 +1246,7 @@ static void rmi_input_configured(struct hid_device *hdev, struct hid_input *hi)
exit:
hid_device_io_stop(hdev);
hid_hw_close(hdev);
return ret;
}
static int rmi_input_mapping(struct hid_device *hdev,
......
......@@ -1360,20 +1360,27 @@ static int sony_register_touchpad(struct hid_input *hi, int touch_count,
return 0;
}
static void sony_input_configured(struct hid_device *hdev,
static int sony_input_configured(struct hid_device *hdev,
struct hid_input *hidinput)
{
struct sony_sc *sc = hid_get_drvdata(hdev);
int ret;
/*
* The Dualshock 4 touchpad supports 2 touches and has a
* resolution of 1920x942 (44.86 dots/mm).
*/
if (sc->quirks & DUALSHOCK4_CONTROLLER) {
if (sony_register_touchpad(hidinput, 2, 1920, 942) != 0)
ret = sony_register_touchpad(hidinput, 2, 1920, 942);
if (ret) {
hid_err(sc->hdev,
"Unable to initialize multi-touch slots\n");
"Unable to initialize multi-touch slots: %d\n",
ret);
return ret;
}
}
return 0;
}
/*
......
......@@ -731,7 +731,7 @@ static int uclogic_input_mapping(struct hid_device *hdev, struct hid_input *hi,
return 0;
}
static void uclogic_input_configured(struct hid_device *hdev,
static int uclogic_input_configured(struct hid_device *hdev,
struct hid_input *hi)
{
char *name;
......@@ -741,7 +741,7 @@ static void uclogic_input_configured(struct hid_device *hdev,
/* no report associated (HID_QUIRK_MULTI_INPUT not set) */
if (!hi->report)
return;
return 0;
field = hi->report->field[0];
......@@ -774,6 +774,8 @@ static void uclogic_input_configured(struct hid_device *hdev,
hi->input->name = name;
}
}
return 0;
}
/**
......
......@@ -56,12 +56,57 @@ struct evdev_client {
struct fasync_struct *fasync;
struct evdev *evdev;
struct list_head node;
int clk_type;
unsigned int clk_type;
bool revoked;
unsigned long *evmasks[EV_CNT];
unsigned int bufsize;
struct input_event buffer[];
};
static size_t evdev_get_mask_cnt(unsigned int type)
{
static const size_t counts[EV_CNT] = {
/* EV_SYN==0 is EV_CNT, _not_ SYN_CNT, see EVIOCGBIT */
[EV_SYN] = EV_CNT,
[EV_KEY] = KEY_CNT,
[EV_REL] = REL_CNT,
[EV_ABS] = ABS_CNT,
[EV_MSC] = MSC_CNT,
[EV_SW] = SW_CNT,
[EV_LED] = LED_CNT,
[EV_SND] = SND_CNT,
[EV_FF] = FF_CNT,
};
return (type < EV_CNT) ? counts[type] : 0;
}
/* requires the buffer lock to be held */
static bool __evdev_is_filtered(struct evdev_client *client,
unsigned int type,
unsigned int code)
{
unsigned long *mask;
size_t cnt;
/* EV_SYN and unknown codes are never filtered */
if (type == EV_SYN || type >= EV_CNT)
return false;
/* first test whether the type is filtered */
mask = client->evmasks[0];
if (mask && !test_bit(type, mask))
return true;
/* unknown values are never filtered */
cnt = evdev_get_mask_cnt(type);
if (!cnt || code >= cnt)
return false;
mask = client->evmasks[type];
return mask && !test_bit(code, mask);
}
/* flush queued events of type @type, caller must hold client->buffer_lock */
static void __evdev_flush_queue(struct evdev_client *client, unsigned int type)
{
......@@ -146,37 +191,39 @@ static void evdev_queue_syn_dropped(struct evdev_client *client)
static int evdev_set_clk_type(struct evdev_client *client, unsigned int clkid)
{
unsigned long flags;
if (client->clk_type == clkid)
return 0;
unsigned int clk_type;
switch (clkid) {
case CLOCK_REALTIME:
client->clk_type = EV_CLK_REAL;
clk_type = EV_CLK_REAL;
break;
case CLOCK_MONOTONIC:
client->clk_type = EV_CLK_MONO;
clk_type = EV_CLK_MONO;
break;
case CLOCK_BOOTTIME:
client->clk_type = EV_CLK_BOOT;
clk_type = EV_CLK_BOOT;
break;
default:
return -EINVAL;
}
/*
* Flush pending events and queue SYN_DROPPED event,
* but only if the queue is not empty.
*/
spin_lock_irqsave(&client->buffer_lock, flags);
if (client->clk_type != clk_type) {
client->clk_type = clk_type;
if (client->head != client->tail) {
client->packet_head = client->head = client->tail;
__evdev_queue_syn_dropped(client);
}
/*
* Flush pending events and queue SYN_DROPPED event,
* but only if the queue is not empty.
*/
spin_lock_irqsave(&client->buffer_lock, flags);
spin_unlock_irqrestore(&client->buffer_lock, flags);
if (client->head != client->tail) {
client->packet_head = client->head = client->tail;
__evdev_queue_syn_dropped(client);
}
spin_unlock_irqrestore(&client->buffer_lock, flags);
}
return 0;
}
......@@ -226,12 +273,21 @@ static void evdev_pass_values(struct evdev_client *client,
spin_lock(&client->buffer_lock);
for (v = vals; v != vals + count; v++) {
if (__evdev_is_filtered(client, v->type, v->code))
continue;
if (v->type == EV_SYN && v->code == SYN_REPORT) {
/* drop empty SYN_REPORT */
if (client->packet_head == client->head)
continue;
wakeup = true;
}
event.type = v->type;
event.code = v->code;
event.value = v->value;
__pass_event(client, &event);
if (v->type == EV_SYN && v->code == SYN_REPORT)
wakeup = true;
}
spin_unlock(&client->buffer_lock);
......@@ -410,6 +466,7 @@ static int evdev_release(struct inode *inode, struct file *file)
{
struct evdev_client *client = file->private_data;
struct evdev *evdev = client->evdev;
unsigned int i;
mutex_lock(&evdev->mutex);
evdev_ungrab(evdev, client);
......@@ -417,6 +474,9 @@ static int evdev_release(struct inode *inode, struct file *file)
evdev_detach_client(evdev, client);
for (i = 0; i < EV_CNT; ++i)
kfree(client->evmasks[i]);
kvfree(client);
evdev_close_device(evdev);
......@@ -627,7 +687,46 @@ static int bits_to_user(unsigned long *bits, unsigned int maxbit,
return len;
}
static int bits_from_user(unsigned long *bits, unsigned int maxbit,
unsigned int maxlen, const void __user *p, int compat)
{
int len, i;
if (compat) {
if (maxlen % sizeof(compat_long_t))
return -EINVAL;
len = BITS_TO_LONGS_COMPAT(maxbit) * sizeof(compat_long_t);
if (len > maxlen)
len = maxlen;
for (i = 0; i < len / sizeof(compat_long_t); i++)
if (copy_from_user((compat_long_t *) bits +
i + 1 - ((i % 2) << 1),
(compat_long_t __user *) p + i,
sizeof(compat_long_t)))
return -EFAULT;
if (i % 2)
*((compat_long_t *) bits + i - 1) = 0;
} else {
if (maxlen % sizeof(long))
return -EINVAL;
len = BITS_TO_LONGS(maxbit) * sizeof(long);
if (len > maxlen)
len = maxlen;
if (copy_from_user(bits, p, len))
return -EFAULT;
}
return len;
}
#else
static int bits_to_user(unsigned long *bits, unsigned int maxbit,
unsigned int maxlen, void __user *p, int compat)
{
......@@ -640,6 +739,24 @@ static int bits_to_user(unsigned long *bits, unsigned int maxbit,
return copy_to_user(p, bits, len) ? -EFAULT : len;
}
static int bits_from_user(unsigned long *bits, unsigned int maxbit,
unsigned int maxlen, const void __user *p, int compat)
{
size_t chunk_size = compat ? sizeof(compat_long_t) : sizeof(long);
int len;
if (maxlen % chunk_size)
return -EINVAL;
len = compat ? BITS_TO_LONGS_COMPAT(maxbit) : BITS_TO_LONGS(maxbit);
len *= chunk_size;
if (len > maxlen)
len = maxlen;
return copy_from_user(bits, p, len) ? -EFAULT : len;
}
#endif /* __BIG_ENDIAN */
#else
......@@ -655,6 +772,21 @@ static int bits_to_user(unsigned long *bits, unsigned int maxbit,
return copy_to_user(p, bits, len) ? -EFAULT : len;
}
static int bits_from_user(unsigned long *bits, unsigned int maxbit,
unsigned int maxlen, const void __user *p, int compat)
{
int len;
if (maxlen % sizeof(long))
return -EINVAL;
len = BITS_TO_LONGS(maxbit) * sizeof(long);
if (len > maxlen)
len = maxlen;
return copy_from_user(bits, p, len) ? -EFAULT : len;
}
#endif /* CONFIG_COMPAT */
static int str_to_user(const char *str, unsigned int maxlen, void __user *p)
......@@ -849,6 +981,81 @@ static int evdev_revoke(struct evdev *evdev, struct evdev_client *client,
return 0;
}
/* must be called with evdev-mutex held */
static int evdev_set_mask(struct evdev_client *client,
unsigned int type,
const void __user *codes,
u32 codes_size,
int compat)
{
unsigned long flags, *mask, *oldmask;
size_t cnt;
int error;
/* we allow unknown types and 'codes_size > size' for forward-compat */
cnt = evdev_get_mask_cnt(type);
if (!cnt)
return 0;
mask = kcalloc(sizeof(unsigned long), BITS_TO_LONGS(cnt), GFP_KERNEL);
if (!mask)
return -ENOMEM;
error = bits_from_user(mask, cnt - 1, codes_size, codes, compat);
if (error < 0) {
kfree(mask);
return error;
}
spin_lock_irqsave(&client->buffer_lock, flags);
oldmask = client->evmasks[type];
client->evmasks[type] = mask;
spin_unlock_irqrestore(&client->buffer_lock, flags);
kfree(oldmask);
return 0;
}
/* must be called with evdev-mutex held */
static int evdev_get_mask(struct evdev_client *client,
unsigned int type,
void __user *codes,
u32 codes_size,
int compat)
{
unsigned long *mask;
size_t cnt, size, xfer_size;
int i;
int error;
/* we allow unknown types and 'codes_size > size' for forward-compat */
cnt = evdev_get_mask_cnt(type);
size = sizeof(unsigned long) * BITS_TO_LONGS(cnt);
xfer_size = min_t(size_t, codes_size, size);
if (cnt > 0) {
mask = client->evmasks[type];
if (mask) {
error = bits_to_user(mask, cnt - 1,
xfer_size, codes, compat);
if (error < 0)
return error;
} else {
/* fake mask with all bits set */
for (i = 0; i < xfer_size; i++)
if (put_user(0xffU, (u8 __user *)codes + i))
return -EFAULT;
}
}
if (xfer_size < codes_size)
if (clear_user(codes + xfer_size, codes_size - xfer_size))
return -EFAULT;
return 0;
}
static long evdev_do_ioctl(struct file *file, unsigned int cmd,
void __user *p, int compat_mode)
{
......@@ -856,6 +1063,7 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
struct evdev *evdev = client->evdev;
struct input_dev *dev = evdev->handle.dev;
struct input_absinfo abs;
struct input_mask mask;
struct ff_effect effect;
int __user *ip = (int __user *)p;
unsigned int i, t, u, v;
......@@ -917,6 +1125,30 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
else
return evdev_revoke(evdev, client, file);
case EVIOCGMASK: {
void __user *codes_ptr;
if (copy_from_user(&mask, p, sizeof(mask)))
return -EFAULT;
codes_ptr = (void __user *)(unsigned long)mask.codes_ptr;
return evdev_get_mask(client,
mask.type, codes_ptr, mask.codes_size,
compat_mode);
}
case EVIOCSMASK: {
const void __user *codes_ptr;
if (copy_from_user(&mask, p, sizeof(mask)))
return -EFAULT;
codes_ptr = (const void __user *)(unsigned long)mask.codes_ptr;
return evdev_set_mask(client,
mask.type, codes_ptr, mask.codes_size,
compat_mode);
}
case EVIOCSCLOCKID:
if (copy_from_user(&i, p, sizeof(unsigned int)))
return -EFAULT;
......
......@@ -273,14 +273,14 @@ int input_ff_event(struct input_dev *dev, unsigned int type,
switch (code) {
case FF_GAIN:
if (!test_bit(FF_GAIN, dev->ffbit) || value > 0xffff)
if (!test_bit(FF_GAIN, dev->ffbit) || value > 0xffffU)
break;
ff->set_gain(dev, value);
break;
case FF_AUTOCENTER:
if (!test_bit(FF_AUTOCENTER, dev->ffbit) || value > 0xffff)
if (!test_bit(FF_AUTOCENTER, dev->ffbit) || value > 0xffffU)
break;
ff->set_autocenter(dev, value);
......@@ -318,6 +318,11 @@ int input_ff_create(struct input_dev *dev, unsigned int max_effects)
return -EINVAL;
}
if (max_effects > FF_MAX_EFFECTS) {
dev_err(&dev->dev, "cannot allocate more than FF_MAX_EFFECTS effects\n");
return -EINVAL;
}
ff_dev_size = sizeof(struct ff_device) +
max_effects * sizeof(struct file *);
if (ff_dev_size < max_effects) /* overflow */
......
......@@ -2044,6 +2044,23 @@ static void devm_input_device_unregister(struct device *dev, void *res)
__input_unregister_device(input);
}
/**
* input_enable_softrepeat - enable software autorepeat
* @dev: input device
* @delay: repeat delay
* @period: repeat period
*
* Enable software autorepeat on the input device.
*/
void input_enable_softrepeat(struct input_dev *dev, int delay, int period)
{
dev->timer.data = (unsigned long) dev;
dev->timer.function = input_repeat_key;
dev->rep[REP_DELAY] = delay;
dev->rep[REP_PERIOD] = period;
}
EXPORT_SYMBOL(input_enable_softrepeat);
/**
* input_register_device - register device with input core
* @dev: device to be registered
......@@ -2108,12 +2125,8 @@ int input_register_device(struct input_dev *dev)
* If delay and period are pre-set by the driver, then autorepeating
* is handled by the driver itself and we don't do it in input.c.
*/
if (!dev->rep[REP_DELAY] && !dev->rep[REP_PERIOD]) {
dev->timer.data = (long) dev;
dev->timer.function = input_repeat_key;
dev->rep[REP_DELAY] = 250;
dev->rep[REP_PERIOD] = 33;
}
if (!dev->rep[REP_DELAY] && !dev->rep[REP_PERIOD])
input_enable_softrepeat(dev, 250, 33);
if (!dev->getkeycode)
dev->getkeycode = input_default_getkeycode;
......
......@@ -444,14 +444,9 @@ static int joydev_handle_JSIOCSAXMAP(struct joydev *joydev,
len = min(len, sizeof(joydev->abspam));
/* Validate the map. */
abspam = kmalloc(len, GFP_KERNEL);
if (!abspam)
return -ENOMEM;
if (copy_from_user(abspam, argp, len)) {
retval = -EFAULT;
goto out;
}
abspam = memdup_user(argp, len);
if (IS_ERR(abspam))
return PTR_ERR(abspam);
for (i = 0; i < joydev->nabs; i++) {
if (abspam[i] > ABS_MAX) {
......@@ -480,14 +475,9 @@ static int joydev_handle_JSIOCSBTNMAP(struct joydev *joydev,
len = min(len, sizeof(joydev->keypam));
/* Validate the map. */
keypam = kmalloc(len, GFP_KERNEL);
if (!keypam)
return -ENOMEM;
if (copy_from_user(keypam, argp, len)) {
retval = -EFAULT;
goto out;
}
keypam = memdup_user(argp, len);
if (IS_ERR(keypam))
return PTR_ERR(keypam);
for (i = 0; i < joydev->nkey; i++) {
if (keypam[i] > KEY_MAX || keypam[i] < BTN_MISC) {
......
......@@ -48,7 +48,7 @@ struct db9_config {
};
#define DB9_MAX_PORTS 3
static struct db9_config db9_cfg[DB9_MAX_PORTS] __initdata;
static struct db9_config db9_cfg[DB9_MAX_PORTS];
module_param_array_named(dev, db9_cfg[0].args, int, &db9_cfg[0].nargs, 0);
MODULE_PARM_DESC(dev, "Describes first attached device (<parport#>,<type>)");
......@@ -106,6 +106,7 @@ struct db9 {
struct pardevice *pd;
int mode;
int used;
int parportno;
struct mutex mutex;
char phys[DB9_MAX_DEVICES][32];
};
......@@ -553,54 +554,60 @@ static void db9_close(struct input_dev *dev)
mutex_unlock(&db9->mutex);
}
static struct db9 __init *db9_probe(int parport, int mode)
static void db9_attach(struct parport *pp)
{
struct db9 *db9;
const struct db9_mode_data *db9_mode;
struct parport *pp;
struct pardevice *pd;
struct input_dev *input_dev;
int i, j;
int err;
int i, j, port_idx;
int mode;
struct pardev_cb db9_parport_cb;
for (port_idx = 0; port_idx < DB9_MAX_PORTS; port_idx++) {
if (db9_cfg[port_idx].nargs == 0 ||
db9_cfg[port_idx].args[DB9_ARG_PARPORT] < 0)
continue;
if (db9_cfg[port_idx].args[DB9_ARG_PARPORT] == pp->number)
break;
}
if (port_idx == DB9_MAX_PORTS) {
pr_debug("Not using parport%d.\n", pp->number);
return;
}
mode = db9_cfg[port_idx].args[DB9_ARG_MODE];
if (mode < 1 || mode >= DB9_MAX_PAD || !db9_modes[mode].n_buttons) {
printk(KERN_ERR "db9.c: Bad device type %d\n", mode);
err = -EINVAL;
goto err_out;
return;
}
db9_mode = &db9_modes[mode];
pp = parport_find_number(parport);
if (!pp) {
printk(KERN_ERR "db9.c: no such parport\n");
err = -ENODEV;
goto err_out;
}
if (db9_mode->bidirectional && !(pp->modes & PARPORT_MODE_TRISTATE)) {
printk(KERN_ERR "db9.c: specified parport is not bidirectional\n");
err = -EINVAL;
goto err_put_pp;
return;
}
pd = parport_register_device(pp, "db9", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
db9_parport_cb.flags = PARPORT_FLAG_EXCL;
pd = parport_register_dev_model(pp, "db9", &db9_parport_cb, port_idx);
if (!pd) {
printk(KERN_ERR "db9.c: parport busy already - lp.o loaded?\n");
err = -EBUSY;
goto err_put_pp;
return;
}
db9 = kzalloc(sizeof(struct db9), GFP_KERNEL);
if (!db9) {
printk(KERN_ERR "db9.c: Not enough memory\n");
err = -ENOMEM;
if (!db9)
goto err_unreg_pardev;
}
mutex_init(&db9->mutex);
db9->pd = pd;
db9->mode = mode;
db9->parportno = pp->number;
init_timer(&db9->timer);
db9->timer.data = (long) db9;
db9->timer.function = db9_timer;
......@@ -610,7 +617,6 @@ static struct db9 __init *db9_probe(int parport, int mode)
db9->dev[i] = input_dev = input_allocate_device();
if (!input_dev) {
printk(KERN_ERR "db9.c: Not enough memory for input device\n");
err = -ENOMEM;
goto err_unreg_devs;
}
......@@ -639,13 +645,12 @@ static struct db9 __init *db9_probe(int parport, int mode)
input_set_abs_params(input_dev, db9_abs[j], 1, 255, 0, 0);
}
err = input_register_device(input_dev);
if (err)
if (input_register_device(input_dev))
goto err_free_dev;
}
parport_put_port(pp);
return db9;
db9_base[port_idx] = db9;
return;
err_free_dev:
input_free_device(db9->dev[i]);
......@@ -655,15 +660,23 @@ static struct db9 __init *db9_probe(int parport, int mode)
kfree(db9);
err_unreg_pardev:
parport_unregister_device(pd);
err_put_pp:
parport_put_port(pp);
err_out:
return ERR_PTR(err);
}
static void db9_remove(struct db9 *db9)
static void db9_detach(struct parport *port)
{
int i;
struct db9 *db9;
for (i = 0; i < DB9_MAX_PORTS; i++) {
if (db9_base[i] && db9_base[i]->parportno == port->number)
break;
}
if (i == DB9_MAX_PORTS)
return;
db9 = db9_base[i];
db9_base[i] = NULL;
for (i = 0; i < min(db9_modes[db9->mode].n_pads, DB9_MAX_DEVICES); i++)
input_unregister_device(db9->dev[i]);
......@@ -671,11 +684,17 @@ static void db9_remove(struct db9 *db9)
kfree(db9);
}
static struct parport_driver db9_parport_driver = {
.name = "db9",
.match_port = db9_attach,
.detach = db9_detach,
.devmodel = true,
};
static int __init db9_init(void)
{
int i;
int have_dev = 0;
int err = 0;
for (i = 0; i < DB9_MAX_PORTS; i++) {
if (db9_cfg[i].nargs == 0 || db9_cfg[i].args[DB9_ARG_PARPORT] < 0)
......@@ -683,37 +702,21 @@ static int __init db9_init(void)
if (db9_cfg[i].nargs < 2) {
printk(KERN_ERR "db9.c: Device type must be specified.\n");
err = -EINVAL;
break;
}
db9_base[i] = db9_probe(db9_cfg[i].args[DB9_ARG_PARPORT],
db9_cfg[i].args[DB9_ARG_MODE]);
if (IS_ERR(db9_base[i])) {
err = PTR_ERR(db9_base[i]);
break;
return -EINVAL;
}
have_dev = 1;
}
if (err) {
while (--i >= 0)
if (db9_base[i])
db9_remove(db9_base[i]);
return err;
}
if (!have_dev)
return -ENODEV;
return have_dev ? 0 : -ENODEV;
return parport_register_driver(&db9_parport_driver);
}
static void __exit db9_exit(void)
{
int i;
for (i = 0; i < DB9_MAX_PORTS; i++)
if (db9_base[i])
db9_remove(db9_base[i]);
parport_unregister_driver(&db9_parport_driver);
}
module_init(db9_init);
......
......@@ -53,7 +53,7 @@ struct gc_config {
unsigned int nargs;
};
static struct gc_config gc_cfg[GC_MAX_PORTS] __initdata;
static struct gc_config gc_cfg[GC_MAX_PORTS];
module_param_array_named(map, gc_cfg[0].args, int, &gc_cfg[0].nargs, 0);
MODULE_PARM_DESC(map, "Describes first set of devices (<parport#>,<pad1>,<pad2>,..<pad5>)");
......@@ -92,6 +92,7 @@ struct gc {
struct timer_list timer;
int pad_count[GC_MAX];
int used;
int parportno;
struct mutex mutex;
};
......@@ -304,7 +305,7 @@ static int gc_n64_play_effect(struct input_dev *dev, void *data,
return 0;
}
static int __init gc_n64_init_ff(struct input_dev *dev, int i)
static int gc_n64_init_ff(struct input_dev *dev, int i)
{
struct gc_subdev *sdev;
int err;
......@@ -811,7 +812,7 @@ static void gc_close(struct input_dev *dev)
mutex_unlock(&gc->mutex);
}
static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type)
static int gc_setup_pad(struct gc *gc, int idx, int pad_type)
{
struct gc_pad *pad = &gc->pads[idx];
struct input_dev *input_dev;
......@@ -926,46 +927,55 @@ static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type)
return err;
}
static struct gc __init *gc_probe(int parport, int *pads, int n_pads)
static void gc_attach(struct parport *pp)
{
struct gc *gc;
struct parport *pp;
struct pardevice *pd;
int i;
int i, port_idx;
int count = 0;
int err;
int *pads, n_pads;
struct pardev_cb gc_parport_cb;
for (port_idx = 0; port_idx < GC_MAX_PORTS; port_idx++) {
if (gc_cfg[port_idx].nargs == 0 || gc_cfg[port_idx].args[0] < 0)
continue;
if (gc_cfg[port_idx].args[0] == pp->number)
break;
}
pp = parport_find_number(parport);
if (!pp) {
pr_err("no such parport %d\n", parport);
err = -EINVAL;
goto err_out;
if (port_idx == GC_MAX_PORTS) {
pr_debug("Not using parport%d.\n", pp->number);
return;
}
pads = gc_cfg[port_idx].args + 1;
n_pads = gc_cfg[port_idx].nargs - 1;
pd = parport_register_device(pp, "gamecon", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
gc_parport_cb.flags = PARPORT_FLAG_EXCL;
pd = parport_register_dev_model(pp, "gamecon", &gc_parport_cb,
port_idx);
if (!pd) {
pr_err("parport busy already - lp.o loaded?\n");
err = -EBUSY;
goto err_put_pp;
return;
}
gc = kzalloc(sizeof(struct gc), GFP_KERNEL);
if (!gc) {
pr_err("Not enough memory\n");
err = -ENOMEM;
goto err_unreg_pardev;
}
mutex_init(&gc->mutex);
gc->pd = pd;
gc->parportno = pp->number;
setup_timer(&gc->timer, gc_timer, (long) gc);
for (i = 0; i < n_pads && i < GC_MAX_DEVICES; i++) {
if (!pads[i])
continue;
err = gc_setup_pad(gc, i, pads[i]);
if (err)
if (gc_setup_pad(gc, i, pads[i]))
goto err_unreg_devs;
count++;
......@@ -973,12 +983,11 @@ static struct gc __init *gc_probe(int parport, int *pads, int n_pads)
if (count == 0) {
pr_err("No valid devices specified\n");
err = -EINVAL;
goto err_free_gc;
}
parport_put_port(pp);
return gc;
gc_base[port_idx] = gc;
return;
err_unreg_devs:
while (--i >= 0)
......@@ -988,15 +997,23 @@ static struct gc __init *gc_probe(int parport, int *pads, int n_pads)
kfree(gc);
err_unreg_pardev:
parport_unregister_device(pd);
err_put_pp:
parport_put_port(pp);
err_out:
return ERR_PTR(err);
}
static void gc_remove(struct gc *gc)
static void gc_detach(struct parport *port)
{
int i;
struct gc *gc;
for (i = 0; i < GC_MAX_PORTS; i++) {
if (gc_base[i] && gc_base[i]->parportno == port->number)
break;
}
if (i == GC_MAX_PORTS)
return;
gc = gc_base[i];
gc_base[i] = NULL;
for (i = 0; i < GC_MAX_DEVICES; i++)
if (gc->pads[i].dev)
......@@ -1005,11 +1022,17 @@ static void gc_remove(struct gc *gc)
kfree(gc);
}
static struct parport_driver gc_parport_driver = {
.name = "gamecon",
.match_port = gc_attach,
.detach = gc_detach,
.devmodel = true,
};
static int __init gc_init(void)
{
int i;
int have_dev = 0;
int err = 0;
for (i = 0; i < GC_MAX_PORTS; i++) {
if (gc_cfg[i].nargs == 0 || gc_cfg[i].args[0] < 0)
......@@ -1017,37 +1040,21 @@ static int __init gc_init(void)
if (gc_cfg[i].nargs < 2) {
pr_err("at least one device must be specified\n");
err = -EINVAL;
break;
}
gc_base[i] = gc_probe(gc_cfg[i].args[0],
gc_cfg[i].args + 1, gc_cfg[i].nargs - 1);
if (IS_ERR(gc_base[i])) {
err = PTR_ERR(gc_base[i]);
break;
return -EINVAL;
}
have_dev = 1;
}
if (err) {
while (--i >= 0)
if (gc_base[i])
gc_remove(gc_base[i]);
return err;
}
if (!have_dev)
return -ENODEV;
return have_dev ? 0 : -ENODEV;
return parport_register_driver(&gc_parport_driver);
}
static void __exit gc_exit(void)
{
int i;
for (i = 0; i < GC_MAX_PORTS; i++)
if (gc_base[i])
gc_remove(gc_base[i]);
parport_unregister_driver(&gc_parport_driver);
}
module_init(gc_init);
......
......@@ -49,7 +49,7 @@ struct tgfx_config {
unsigned int nargs;
};
static struct tgfx_config tgfx_cfg[TGFX_MAX_PORTS] __initdata;
static struct tgfx_config tgfx_cfg[TGFX_MAX_PORTS];
module_param_array_named(map, tgfx_cfg[0].args, int, &tgfx_cfg[0].nargs, 0);
MODULE_PARM_DESC(map, "Describes first set of devices (<parport#>,<js1>,<js2>,..<js7>");
......@@ -81,6 +81,7 @@ static struct tgfx {
char phys[TGFX_MAX_DEVICES][32];
int sticks;
int used;
int parportno;
struct mutex sem;
} *tgfx_base[TGFX_MAX_PORTS];
......@@ -156,38 +157,48 @@ static void tgfx_close(struct input_dev *dev)
* tgfx_probe() probes for tg gamepads.
*/
static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs)
static void tgfx_attach(struct parport *pp)
{
struct tgfx *tgfx;
struct input_dev *input_dev;
struct parport *pp;
struct pardevice *pd;
int i, j;
int err;
int i, j, port_idx;
int *n_buttons, n_devs;
struct pardev_cb tgfx_parport_cb;
for (port_idx = 0; port_idx < TGFX_MAX_PORTS; port_idx++) {
if (tgfx_cfg[port_idx].nargs == 0 ||
tgfx_cfg[port_idx].args[0] < 0)
continue;
if (tgfx_cfg[port_idx].args[0] == pp->number)
break;
}
pp = parport_find_number(parport);
if (!pp) {
printk(KERN_ERR "turbografx.c: no such parport\n");
err = -EINVAL;
goto err_out;
if (port_idx == TGFX_MAX_PORTS) {
pr_debug("Not using parport%d.\n", pp->number);
return;
}
n_buttons = tgfx_cfg[port_idx].args + 1;
n_devs = tgfx_cfg[port_idx].nargs - 1;
tgfx_parport_cb.flags = PARPORT_FLAG_EXCL;
pd = parport_register_device(pp, "turbografx", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
pd = parport_register_dev_model(pp, "turbografx", &tgfx_parport_cb,
port_idx);
if (!pd) {
printk(KERN_ERR "turbografx.c: parport busy already - lp.o loaded?\n");
err = -EBUSY;
goto err_put_pp;
pr_err("parport busy already - lp.o loaded?\n");
return;
}
tgfx = kzalloc(sizeof(struct tgfx), GFP_KERNEL);
if (!tgfx) {
printk(KERN_ERR "turbografx.c: Not enough memory\n");
err = -ENOMEM;
goto err_unreg_pardev;
}
mutex_init(&tgfx->sem);
tgfx->pd = pd;
tgfx->parportno = pp->number;
init_timer(&tgfx->timer);
tgfx->timer.data = (long) tgfx;
tgfx->timer.function = tgfx_timer;
......@@ -198,14 +209,12 @@ static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs)
if (n_buttons[i] > ARRAY_SIZE(tgfx_buttons)) {
printk(KERN_ERR "turbografx.c: Invalid number of buttons %d\n", n_buttons[i]);
err = -EINVAL;
goto err_unreg_devs;
}
tgfx->dev[i] = input_dev = input_allocate_device();
if (!input_dev) {
printk(KERN_ERR "turbografx.c: Not enough memory for input device\n");
err = -ENOMEM;
goto err_unreg_devs;
}
......@@ -234,19 +243,17 @@ static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs)
for (j = 0; j < n_buttons[i]; j++)
set_bit(tgfx_buttons[j], input_dev->keybit);
err = input_register_device(tgfx->dev[i]);
if (err)
if (input_register_device(tgfx->dev[i]))
goto err_free_dev;
}
if (!tgfx->sticks) {
printk(KERN_ERR "turbografx.c: No valid devices specified\n");
err = -EINVAL;
goto err_free_tgfx;
}
parport_put_port(pp);
return tgfx;
tgfx_base[port_idx] = tgfx;
return;
err_free_dev:
input_free_device(tgfx->dev[i]);
......@@ -258,15 +265,23 @@ static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs)
kfree(tgfx);
err_unreg_pardev:
parport_unregister_device(pd);
err_put_pp:
parport_put_port(pp);
err_out:
return ERR_PTR(err);
}
static void tgfx_remove(struct tgfx *tgfx)
static void tgfx_detach(struct parport *port)
{
int i;
struct tgfx *tgfx;
for (i = 0; i < TGFX_MAX_PORTS; i++) {
if (tgfx_base[i] && tgfx_base[i]->parportno == port->number)
break;
}
if (i == TGFX_MAX_PORTS)
return;
tgfx = tgfx_base[i];
tgfx_base[i] = NULL;
for (i = 0; i < TGFX_MAX_DEVICES; i++)
if (tgfx->dev[i])
......@@ -275,11 +290,17 @@ static void tgfx_remove(struct tgfx *tgfx)
kfree(tgfx);
}
static struct parport_driver tgfx_parport_driver = {
.name = "turbografx",
.match_port = tgfx_attach,
.detach = tgfx_detach,
.devmodel = true,
};
static int __init tgfx_init(void)
{
int i;
int have_dev = 0;
int err = 0;
for (i = 0; i < TGFX_MAX_PORTS; i++) {
if (tgfx_cfg[i].nargs == 0 || tgfx_cfg[i].args[0] < 0)
......@@ -287,38 +308,21 @@ static int __init tgfx_init(void)
if (tgfx_cfg[i].nargs < 2) {
printk(KERN_ERR "turbografx.c: at least one joystick must be specified\n");
err = -EINVAL;
break;
}
tgfx_base[i] = tgfx_probe(tgfx_cfg[i].args[0],
tgfx_cfg[i].args + 1,
tgfx_cfg[i].nargs - 1);
if (IS_ERR(tgfx_base[i])) {
err = PTR_ERR(tgfx_base[i]);
break;
return -EINVAL;
}
have_dev = 1;
}
if (err) {
while (--i >= 0)
if (tgfx_base[i])
tgfx_remove(tgfx_base[i]);
return err;
}
if (!have_dev)
return -ENODEV;
return have_dev ? 0 : -ENODEV;
return parport_register_driver(&tgfx_parport_driver);
}
static void __exit tgfx_exit(void)
{
int i;
for (i = 0; i < TGFX_MAX_PORTS; i++)
if (tgfx_base[i])
tgfx_remove(tgfx_base[i]);
parport_unregister_driver(&tgfx_parport_driver);
}
module_init(tgfx_init);
......
......@@ -200,35 +200,38 @@ static void walkera0701_close(struct input_dev *dev)
parport_release(w->pardevice);
}
static int walkera0701_connect(struct walkera_dev *w, int parport)
static void walkera0701_attach(struct parport *pp)
{
int error;
struct pardev_cb walkera0701_parport_cb;
struct walkera_dev *w = &w_dev;
w->parport = parport_find_number(parport);
if (!w->parport) {
pr_err("parport %d does not exist\n", parport);
return -ENODEV;
if (pp->number != walkera0701_pp_no) {
pr_debug("Not using parport%d.\n", pp->number);
return;
}
if (w->parport->irq == -1) {
if (pp->irq == -1) {
pr_err("parport %d does not have interrupt assigned\n",
parport);
error = -EINVAL;
goto err_put_parport;
pp->number);
return;
}
w->pardevice = parport_register_device(w->parport, "walkera0701",
NULL, NULL, walkera0701_irq_handler,
PARPORT_DEV_EXCL, w);
w->parport = pp;
walkera0701_parport_cb.flags = PARPORT_FLAG_EXCL;
walkera0701_parport_cb.irq_func = walkera0701_irq_handler;
walkera0701_parport_cb.private = w;
w->pardevice = parport_register_dev_model(pp, "walkera0701",
&walkera0701_parport_cb, 0);
if (!w->pardevice) {
pr_err("failed to register parport device\n");
error = -EIO;
goto err_put_parport;
return;
}
if (parport_negotiate(w->pardevice->port, IEEE1284_MODE_COMPAT)) {
pr_err("failed to negotiate parport mode\n");
error = -EIO;
goto err_unregister_device;
}
......@@ -238,7 +241,6 @@ static int walkera0701_connect(struct walkera_dev *w, int parport)
w->input_dev = input_allocate_device();
if (!w->input_dev) {
pr_err("failed to allocate input device\n");
error = -ENOMEM;
goto err_unregister_device;
}
......@@ -265,38 +267,46 @@ static int walkera0701_connect(struct walkera_dev *w, int parport)
input_set_abs_params(w->input_dev, ABS_RUDDER, -512, 512, 0, 0);
input_set_abs_params(w->input_dev, ABS_MISC, -512, 512, 0, 0);
error = input_register_device(w->input_dev);
if (error) {
if (input_register_device(w->input_dev)) {
pr_err("failed to register input device\n");
goto err_free_input_dev;
}
return 0;
return;
err_free_input_dev:
input_free_device(w->input_dev);
err_unregister_device:
parport_unregister_device(w->pardevice);
err_put_parport:
parport_put_port(w->parport);
return error;
}
static void walkera0701_disconnect(struct walkera_dev *w)
static void walkera0701_detach(struct parport *port)
{
struct walkera_dev *w = &w_dev;
if (!w->pardevice || w->parport->number != port->number)
return;
input_unregister_device(w->input_dev);
parport_unregister_device(w->pardevice);
parport_put_port(w->parport);
w->parport = NULL;
}
static struct parport_driver walkera0701_parport_driver = {
.name = "walkera0701",
.match_port = walkera0701_attach,
.detach = walkera0701_detach,
.devmodel = true,
};
static int __init walkera0701_init(void)
{
return walkera0701_connect(&w_dev, walkera0701_pp_no);
return parport_register_driver(&walkera0701_parport_driver);
}
static void __exit walkera0701_exit(void)
{
walkera0701_disconnect(&w_dev);
parport_unregister_driver(&walkera0701_parport_driver);
}
module_init(walkera0701_init);
......
This diff is collapsed.
......@@ -516,7 +516,7 @@ config KEYBOARD_SAMSUNG
module will be called samsung-keypad.
config KEYBOARD_GOLDFISH_EVENTS
depends on GOLDFISH
depends on GOLDFISH || COMPILE_TEST
tristate "Generic Input Event device for Goldfish"
help
Say Y here to get an input event device for the Goldfish virtual
......
......@@ -341,8 +341,14 @@ static void gpio_keys_gpio_report_event(struct gpio_button_data *bdata)
const struct gpio_keys_button *button = bdata->button;
struct input_dev *input = bdata->input;
unsigned int type = button->type ?: EV_KEY;
int state = (gpio_get_value_cansleep(button->gpio) ? 1 : 0) ^ button->active_low;
int state = gpio_get_value_cansleep(button->gpio);
if (state < 0) {
dev_err(input->dev.parent, "failed to get gpio state\n");
return;
}
state = (state ? 1 : 0) ^ button->active_low;
if (type == EV_ABS) {
if (state)
input_event(input, type, button->code, button->value);
......
......@@ -40,10 +40,36 @@ struct gpio_keys_polled_dev {
struct input_polled_dev *poll_dev;
struct device *dev;
const struct gpio_keys_platform_data *pdata;
unsigned long rel_axis_seen[BITS_TO_LONGS(REL_CNT)];
unsigned long abs_axis_seen[BITS_TO_LONGS(ABS_CNT)];
struct gpio_keys_button_data data[0];
};
static void gpio_keys_polled_check_state(struct input_dev *input,
static void gpio_keys_button_event(struct input_polled_dev *dev,
struct gpio_keys_button *button,
int state)
{
struct gpio_keys_polled_dev *bdev = dev->private;
struct input_dev *input = dev->input;
unsigned int type = button->type ?: EV_KEY;
if (type == EV_REL) {
if (state) {
input_event(input, type, button->code, button->value);
__set_bit(button->code, bdev->rel_axis_seen);
}
} else if (type == EV_ABS) {
if (state) {
input_event(input, type, button->code, button->value);
__set_bit(button->code, bdev->abs_axis_seen);
}
} else {
input_event(input, type, button->code, state);
input_sync(input);
}
}
static void gpio_keys_polled_check_state(struct input_polled_dev *dev,
struct gpio_keys_button *button,
struct gpio_keys_button_data *bdata)
{
......@@ -54,11 +80,9 @@ static void gpio_keys_polled_check_state(struct input_dev *input,
else
state = !!gpiod_get_value(button->gpiod);
if (state != bdata->last_state) {
unsigned int type = button->type ?: EV_KEY;
gpio_keys_button_event(dev, button, state);
input_event(input, type, button->code, state);
input_sync(input);
if (state != bdata->last_state) {
bdata->count = 0;
bdata->last_state = state;
}
......@@ -71,15 +95,33 @@ static void gpio_keys_polled_poll(struct input_polled_dev *dev)
struct input_dev *input = dev->input;
int i;
memset(bdev->rel_axis_seen, 0, sizeof(bdev->rel_axis_seen));
memset(bdev->abs_axis_seen, 0, sizeof(bdev->abs_axis_seen));
for (i = 0; i < pdata->nbuttons; i++) {
struct gpio_keys_button_data *bdata = &bdev->data[i];
if (bdata->count < bdata->threshold)
if (bdata->count < bdata->threshold) {
bdata->count++;
else
gpio_keys_polled_check_state(input, &pdata->buttons[i],
gpio_keys_button_event(dev, &pdata->buttons[i],
bdata->last_state);
} else {
gpio_keys_polled_check_state(dev, &pdata->buttons[i],
bdata);
}
}
for_each_set_bit(i, input->relbit, REL_CNT) {
if (!test_bit(i, bdev->rel_axis_seen))
input_event(input, EV_REL, i, 0);
}
for_each_set_bit(i, input->absbit, ABS_CNT) {
if (!test_bit(i, bdev->abs_axis_seen))
input_event(input, EV_ABS, i, 0);
}
input_sync(input);
}
static void gpio_keys_polled_open(struct input_polled_dev *dev)
......@@ -152,6 +194,10 @@ static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct
&button->type))
button->type = EV_KEY;
if (fwnode_property_read_u32(child, "linux,input-value",
(u32 *)&button->value))
button->value = 1;
button->wakeup =
fwnode_property_read_bool(child, "wakeup-source") ||
/* legacy name */
......@@ -168,6 +214,25 @@ static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct
return pdata;
}
static void gpio_keys_polled_set_abs_params(struct input_dev *input,
const struct gpio_keys_platform_data *pdata, unsigned int code)
{
int i, min = 0, max = 0;
for (i = 0; i < pdata->nbuttons; i++) {
struct gpio_keys_button *button = &pdata->buttons[i];
if (button->type != EV_ABS || button->code != code)
continue;
if (button->value < min)
min = button->value;
if (button->value > max)
max = button->value;
}
input_set_abs_params(input, code, min, max, 0, 0);
}
static const struct of_device_id gpio_keys_polled_of_match[] = {
{ .compatible = "gpio-keys-polled", },
{ },
......@@ -274,6 +339,9 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
pdata->poll_interval);
input_set_capability(input, type, button->code);
if (type == EV_ABS)
gpio_keys_polled_set_abs_params(input, pdata,
button->code);
}
bdev->poll_dev = poll_dev;
......@@ -290,9 +358,11 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
/* report initial state of the buttons */
for (i = 0; i < pdata->nbuttons; i++)
gpio_keys_polled_check_state(input, &pdata->buttons[i],
gpio_keys_polled_check_state(poll_dev, &pdata->buttons[i],
&bdev->data[i]);
input_sync(input);
return 0;
}
......
......@@ -54,7 +54,7 @@
/**
* struct ske_keypad - data structure used by keypad driver
* @irq: irq no
* @reg_base: ske regsiters base address
* @reg_base: ske registers base address
* @input: pointer to input device object
* @board: keypad platform device
* @keymap: matrix scan code table for keycodes
......
......@@ -110,8 +110,7 @@ static int imx_snvs_pwrkey_probe(struct platform_device *pdev)
if (!pdata)
return -ENOMEM;
pdata->snvs = syscon_regmap_lookup_by_phandle(np, "regmap");;
pdata->snvs = syscon_regmap_lookup_by_phandle(np, "regmap");
if (!pdata->snvs) {
dev_err(&pdev->dev, "Can't get snvs syscon\n");
return -ENODEV;
......
......@@ -517,7 +517,8 @@ static int tegra_kbc_parse_dt(struct tegra_kbc *kbc)
if (of_find_property(np, "nvidia,needs-ghost-filter", NULL))
kbc->use_ghost_filter = true;
if (of_find_property(np, "nvidia,wakeup-source", NULL))
if (of_property_read_bool(np, "wakeup-source") ||
of_property_read_bool(np, "nvidia,wakeup-source")) /* legacy */
kbc->wakeup = true;
if (!of_get_property(np, "nvidia,kbc-row-pins", &proplen)) {
......@@ -705,7 +706,7 @@ static int tegra_kbc_probe(struct platform_device *pdev)
input_set_drvdata(kbc->idev, kbc);
err = devm_request_irq(&pdev->dev, kbc->irq, tegra_kbc_isr,
IRQF_NO_SUSPEND | IRQF_TRIGGER_HIGH, pdev->name, kbc);
IRQF_TRIGGER_HIGH, pdev->name, kbc);
if (err) {
dev_err(&pdev->dev, "failed to request keyboard IRQ\n");
return err;
......
......@@ -94,11 +94,11 @@ config INPUT_BMA150
module will be called bma150.
config INPUT_E3X0_BUTTON
tristate "NI Ettus Research USRP E3x0 Button support."
tristate "NI Ettus Research USRP E3xx Button support."
default n
help
Say Y here to enable support for the NI Ettus Research
USRP E3x0 Button.
USRP E3xx Button.
To compile this driver as a module, choose M here: the
module will be called e3x0_button.
......@@ -599,11 +599,11 @@ config INPUT_DA9055_ONKEY
will be called da9055_onkey.
config INPUT_DA9063_ONKEY
tristate "Dialog DA9063 OnKey"
depends on MFD_DA9063
tristate "Dialog DA9062/63 OnKey"
depends on MFD_DA9063 || MFD_DA9062
help
Support the ONKEY of Dialog DA9063 Power Management IC as an
input device reporting power button statue.
Support the ONKEY of Dialog DA9063 and DA9062 Power Management ICs
as an input device capable of reporting the power button status.
To compile this driver as a module, choose M here: the module
will be called da9063_onkey.
......
......@@ -85,15 +85,6 @@ static int ad714x_i2c_probe(struct i2c_client *client,
return 0;
}
static int ad714x_i2c_remove(struct i2c_client *client)
{
struct ad714x_chip *chip = i2c_get_clientdata(client);
ad714x_remove(chip);
return 0;
}
static const struct i2c_device_id ad714x_id[] = {
{ "ad7142_captouch", 0 },
{ "ad7143_captouch", 0 },
......@@ -110,7 +101,6 @@ static struct i2c_driver ad714x_i2c_driver = {
.pm = &ad714x_i2c_pm,
},
.probe = ad714x_i2c_probe,
.remove = ad714x_i2c_remove,
.id_table = ad714x_id,
};
......
......@@ -101,22 +101,12 @@ static int ad714x_spi_probe(struct spi_device *spi)
return 0;
}
static int ad714x_spi_remove(struct spi_device *spi)
{
struct ad714x_chip *chip = spi_get_drvdata(spi);
ad714x_remove(chip);
return 0;
}
static struct spi_driver ad714x_spi_driver = {
.driver = {
.name = "ad714x_captouch",
.pm = &ad714x_spi_pm,
},
.probe = ad714x_spi_probe,
.remove = ad714x_spi_remove,
};
module_spi_driver(ad714x_spi_driver);
......
......@@ -960,13 +960,12 @@ static irqreturn_t ad714x_interrupt_thread(int irq, void *data)
return IRQ_HANDLED;
}
#define MAX_DEVICE_NUM 8
struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq,
ad714x_read_t read, ad714x_write_t write)
{
int i, alloc_idx;
int i;
int error;
struct input_dev *input[MAX_DEVICE_NUM];
struct input_dev *input;
struct ad714x_platform_data *plat_data = dev_get_platdata(dev);
struct ad714x_chip *ad714x;
......@@ -982,25 +981,25 @@ struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq,
if (irq <= 0) {
dev_err(dev, "IRQ not configured!\n");
error = -EINVAL;
goto err_out;
return ERR_PTR(error);
}
if (dev_get_platdata(dev) == NULL) {
dev_err(dev, "platform data for ad714x doesn't exist\n");
error = -EINVAL;
goto err_out;
return ERR_PTR(error);
}
ad714x = kzalloc(sizeof(*ad714x) + sizeof(*ad714x->sw) +
sizeof(*sd_drv) * plat_data->slider_num +
sizeof(*wl_drv) * plat_data->wheel_num +
sizeof(*tp_drv) * plat_data->touchpad_num +
sizeof(*bt_drv) * plat_data->button_num, GFP_KERNEL);
ad714x = devm_kzalloc(dev, sizeof(*ad714x) + sizeof(*ad714x->sw) +
sizeof(*sd_drv) * plat_data->slider_num +
sizeof(*wl_drv) * plat_data->wheel_num +
sizeof(*tp_drv) * plat_data->touchpad_num +
sizeof(*bt_drv) * plat_data->button_num,
GFP_KERNEL);
if (!ad714x) {
error = -ENOMEM;
goto err_out;
return ERR_PTR(error);
}
ad714x->hw = plat_data;
drv_mem = ad714x + 1;
......@@ -1022,47 +1021,40 @@ struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq,
error = ad714x_hw_detect(ad714x);
if (error)
goto err_free_mem;
return ERR_PTR(error);
/* initialize and request sw/hw resources */
ad714x_hw_init(ad714x);
mutex_init(&ad714x->mutex);
/*
* Allocate and register AD714X input device
*/
alloc_idx = 0;
/* a slider uses one input_dev instance */
if (ad714x->hw->slider_num > 0) {
struct ad714x_slider_plat *sd_plat = ad714x->hw->slider;
for (i = 0; i < ad714x->hw->slider_num; i++) {
sd_drv[i].input = input[alloc_idx] = input_allocate_device();
if (!input[alloc_idx]) {
error = -ENOMEM;
goto err_free_dev;
}
__set_bit(EV_ABS, input[alloc_idx]->evbit);
__set_bit(EV_KEY, input[alloc_idx]->evbit);
__set_bit(ABS_X, input[alloc_idx]->absbit);
__set_bit(BTN_TOUCH, input[alloc_idx]->keybit);
input_set_abs_params(input[alloc_idx],
input = devm_input_allocate_device(dev);
if (!input)
return ERR_PTR(-ENOMEM);
__set_bit(EV_ABS, input->evbit);
__set_bit(EV_KEY, input->evbit);
__set_bit(ABS_X, input->absbit);
__set_bit(BTN_TOUCH, input->keybit);
input_set_abs_params(input,
ABS_X, 0, sd_plat->max_coord, 0, 0);
input[alloc_idx]->id.bustype = bus_type;
input[alloc_idx]->id.product = ad714x->product;
input[alloc_idx]->id.version = ad714x->version;
input[alloc_idx]->name = "ad714x_captouch_slider";
input[alloc_idx]->dev.parent = dev;
input->id.bustype = bus_type;
input->id.product = ad714x->product;
input->id.version = ad714x->version;
input->name = "ad714x_captouch_slider";
input->dev.parent = dev;
error = input_register_device(input[alloc_idx]);
error = input_register_device(input);
if (error)
goto err_free_dev;
return ERR_PTR(error);
alloc_idx++;
sd_drv[i].input = input;
}
}
......@@ -1071,30 +1063,28 @@ struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq,
struct ad714x_wheel_plat *wl_plat = ad714x->hw->wheel;
for (i = 0; i < ad714x->hw->wheel_num; i++) {
wl_drv[i].input = input[alloc_idx] = input_allocate_device();
if (!input[alloc_idx]) {
error = -ENOMEM;
goto err_free_dev;
}
__set_bit(EV_KEY, input[alloc_idx]->evbit);
__set_bit(EV_ABS, input[alloc_idx]->evbit);
__set_bit(ABS_WHEEL, input[alloc_idx]->absbit);
__set_bit(BTN_TOUCH, input[alloc_idx]->keybit);
input_set_abs_params(input[alloc_idx],
input = devm_input_allocate_device(dev);
if (!input)
return ERR_PTR(-ENOMEM);
__set_bit(EV_KEY, input->evbit);
__set_bit(EV_ABS, input->evbit);
__set_bit(ABS_WHEEL, input->absbit);
__set_bit(BTN_TOUCH, input->keybit);
input_set_abs_params(input,
ABS_WHEEL, 0, wl_plat->max_coord, 0, 0);
input[alloc_idx]->id.bustype = bus_type;
input[alloc_idx]->id.product = ad714x->product;
input[alloc_idx]->id.version = ad714x->version;
input[alloc_idx]->name = "ad714x_captouch_wheel";
input[alloc_idx]->dev.parent = dev;
input->id.bustype = bus_type;
input->id.product = ad714x->product;
input->id.version = ad714x->version;
input->name = "ad714x_captouch_wheel";
input->dev.parent = dev;
error = input_register_device(input[alloc_idx]);
error = input_register_device(input);
if (error)
goto err_free_dev;
return ERR_PTR(error);
alloc_idx++;
wl_drv[i].input = input;
}
}
......@@ -1103,33 +1093,31 @@ struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq,
struct ad714x_touchpad_plat *tp_plat = ad714x->hw->touchpad;
for (i = 0; i < ad714x->hw->touchpad_num; i++) {
tp_drv[i].input = input[alloc_idx] = input_allocate_device();
if (!input[alloc_idx]) {
error = -ENOMEM;
goto err_free_dev;
}
__set_bit(EV_ABS, input[alloc_idx]->evbit);
__set_bit(EV_KEY, input[alloc_idx]->evbit);
__set_bit(ABS_X, input[alloc_idx]->absbit);
__set_bit(ABS_Y, input[alloc_idx]->absbit);
__set_bit(BTN_TOUCH, input[alloc_idx]->keybit);
input_set_abs_params(input[alloc_idx],
input = devm_input_allocate_device(dev);
if (!input)
return ERR_PTR(-ENOMEM);
__set_bit(EV_ABS, input->evbit);
__set_bit(EV_KEY, input->evbit);
__set_bit(ABS_X, input->absbit);
__set_bit(ABS_Y, input->absbit);
__set_bit(BTN_TOUCH, input->keybit);
input_set_abs_params(input,
ABS_X, 0, tp_plat->x_max_coord, 0, 0);
input_set_abs_params(input[alloc_idx],
input_set_abs_params(input,
ABS_Y, 0, tp_plat->y_max_coord, 0, 0);
input[alloc_idx]->id.bustype = bus_type;
input[alloc_idx]->id.product = ad714x->product;
input[alloc_idx]->id.version = ad714x->version;
input[alloc_idx]->name = "ad714x_captouch_pad";
input[alloc_idx]->dev.parent = dev;
input->id.bustype = bus_type;
input->id.product = ad714x->product;
input->id.version = ad714x->version;
input->name = "ad714x_captouch_pad";
input->dev.parent = dev;
error = input_register_device(input[alloc_idx]);
error = input_register_device(input);
if (error)
goto err_free_dev;
return ERR_PTR(error);
alloc_idx++;
tp_drv[i].input = input;
}
}
......@@ -1137,82 +1125,44 @@ struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq,
if (ad714x->hw->button_num > 0) {
struct ad714x_button_plat *bt_plat = ad714x->hw->button;
input[alloc_idx] = input_allocate_device();
if (!input[alloc_idx]) {
input = devm_input_allocate_device(dev);
if (!input) {
error = -ENOMEM;
goto err_free_dev;
return ERR_PTR(error);
}
__set_bit(EV_KEY, input[alloc_idx]->evbit);
__set_bit(EV_KEY, input->evbit);
for (i = 0; i < ad714x->hw->button_num; i++) {
bt_drv[i].input = input[alloc_idx];
__set_bit(bt_plat[i].keycode, input[alloc_idx]->keybit);
bt_drv[i].input = input;
__set_bit(bt_plat[i].keycode, input->keybit);
}
input[alloc_idx]->id.bustype = bus_type;
input[alloc_idx]->id.product = ad714x->product;
input[alloc_idx]->id.version = ad714x->version;
input[alloc_idx]->name = "ad714x_captouch_button";
input[alloc_idx]->dev.parent = dev;
input->id.bustype = bus_type;
input->id.product = ad714x->product;
input->id.version = ad714x->version;
input->name = "ad714x_captouch_button";
input->dev.parent = dev;
error = input_register_device(input[alloc_idx]);
error = input_register_device(input);
if (error)
goto err_free_dev;
alloc_idx++;
return ERR_PTR(error);
}
irqflags = plat_data->irqflags ?: IRQF_TRIGGER_FALLING;
irqflags |= IRQF_ONESHOT;
error = request_threaded_irq(ad714x->irq, NULL, ad714x_interrupt_thread,
irqflags, "ad714x_captouch", ad714x);
error = devm_request_threaded_irq(dev, ad714x->irq, NULL,
ad714x_interrupt_thread,
irqflags, "ad714x_captouch", ad714x);
if (error) {
dev_err(dev, "can't allocate irq %d\n", ad714x->irq);
goto err_unreg_dev;
return ERR_PTR(error);
}
return ad714x;
err_free_dev:
dev_err(dev, "failed to setup AD714x input device %i\n", alloc_idx);
input_free_device(input[alloc_idx]);
err_unreg_dev:
while (--alloc_idx >= 0)
input_unregister_device(input[alloc_idx]);
err_free_mem:
kfree(ad714x);
err_out:
return ERR_PTR(error);
}
EXPORT_SYMBOL(ad714x_probe);
void ad714x_remove(struct ad714x_chip *ad714x)
{
struct ad714x_platform_data *hw = ad714x->hw;
struct ad714x_driver_data *sw = ad714x->sw;
int i;
free_irq(ad714x->irq, ad714x);
/* unregister and free all input devices */
for (i = 0; i < hw->slider_num; i++)
input_unregister_device(sw->slider[i].input);
for (i = 0; i < hw->wheel_num; i++)
input_unregister_device(sw->wheel[i].input);
for (i = 0; i < hw->touchpad_num; i++)
input_unregister_device(sw->touchpad[i].input);
if (hw->button_num)
input_unregister_device(sw->button[0].input);
kfree(ad714x);
}
EXPORT_SYMBOL(ad714x_remove);
#ifdef CONFIG_PM
int ad714x_disable(struct ad714x_chip *ad714x)
{
......
......@@ -50,6 +50,5 @@ int ad714x_disable(struct ad714x_chip *ad714x);
int ad714x_enable(struct ad714x_chip *ad714x);
struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq,
ad714x_read_t read, ad714x_write_t write);
void ad714x_remove(struct ad714x_chip *ad714x);
#endif
/*
* OnKey device driver for DA9063
* OnKey device driver for DA9063 and DA9062 PMICs
* Copyright (C) 2015 Dialog Semiconductor Ltd.
*
* This program is free software; you can redistribute it and/or
......@@ -24,36 +24,96 @@
#include <linux/mfd/da9063/core.h>
#include <linux/mfd/da9063/pdata.h>
#include <linux/mfd/da9063/registers.h>
#include <linux/mfd/da9062/core.h>
#include <linux/mfd/da9062/registers.h>
struct da906x_chip_config {
/* REGS */
int onkey_status;
int onkey_pwr_signalling;
int onkey_fault_log;
int onkey_shutdown;
/* MASKS */
int onkey_nonkey_mask;
int onkey_nonkey_lock_mask;
int onkey_key_reset_mask;
int onkey_shutdown_mask;
/* NAMES */
const char *name;
};
struct da9063_onkey {
struct da9063 *hw;
struct delayed_work work;
struct input_dev *input;
struct device *dev;
struct regmap *regmap;
const struct da906x_chip_config *config;
char phys[32];
bool key_power;
};
static const struct da906x_chip_config da9063_regs = {
/* REGS */
.onkey_status = DA9063_REG_STATUS_A,
.onkey_pwr_signalling = DA9063_REG_CONTROL_B,
.onkey_fault_log = DA9063_REG_FAULT_LOG,
.onkey_shutdown = DA9063_REG_CONTROL_F,
/* MASKS */
.onkey_nonkey_mask = DA9063_NONKEY,
.onkey_nonkey_lock_mask = DA9063_NONKEY_LOCK,
.onkey_key_reset_mask = DA9063_KEY_RESET,
.onkey_shutdown_mask = DA9063_SHUTDOWN,
/* NAMES */
.name = DA9063_DRVNAME_ONKEY,
};
static const struct da906x_chip_config da9062_regs = {
/* REGS */
.onkey_status = DA9062AA_STATUS_A,
.onkey_pwr_signalling = DA9062AA_CONTROL_B,
.onkey_fault_log = DA9062AA_FAULT_LOG,
.onkey_shutdown = DA9062AA_CONTROL_F,
/* MASKS */
.onkey_nonkey_mask = DA9062AA_NONKEY_MASK,
.onkey_nonkey_lock_mask = DA9062AA_NONKEY_LOCK_MASK,
.onkey_key_reset_mask = DA9062AA_KEY_RESET_MASK,
.onkey_shutdown_mask = DA9062AA_SHUTDOWN_MASK,
/* NAMES */
.name = "da9062-onkey",
};
static const struct of_device_id da9063_compatible_reg_id_table[] = {
{ .compatible = "dlg,da9063-onkey", .data = &da9063_regs },
{ .compatible = "dlg,da9062-onkey", .data = &da9062_regs },
{ },
};
static void da9063_poll_on(struct work_struct *work)
{
struct da9063_onkey *onkey = container_of(work, struct da9063_onkey,
work.work);
struct da9063_onkey *onkey = container_of(work,
struct da9063_onkey,
work.work);
const struct da906x_chip_config *config = onkey->config;
unsigned int val;
int fault_log = 0;
bool poll = true;
int error;
/* Poll to see when the pin is released */
error = regmap_read(onkey->hw->regmap, DA9063_REG_STATUS_A, &val);
error = regmap_read(onkey->regmap,
config->onkey_status,
&val);
if (error) {
dev_err(onkey->dev,
"Failed to read ON status: %d\n", error);
goto err_poll;
}
if (!(val & DA9063_NONKEY)) {
error = regmap_update_bits(onkey->hw->regmap,
DA9063_REG_CONTROL_B,
DA9063_NONKEY_LOCK, 0);
if (!(val & config->onkey_nonkey_mask)) {
error = regmap_update_bits(onkey->regmap,
config->onkey_pwr_signalling,
config->onkey_nonkey_lock_mask,
0);
if (error) {
dev_err(onkey->dev,
"Failed to reset the Key Delay %d\n", error);
......@@ -70,15 +130,16 @@ static void da9063_poll_on(struct work_struct *work)
* If the fault log KEY_RESET is detected, then clear it
* and shut down the system.
*/
error = regmap_read(onkey->hw->regmap,
DA9063_REG_FAULT_LOG, &fault_log);
error = regmap_read(onkey->regmap,
config->onkey_fault_log,
&fault_log);
if (error) {
dev_warn(&onkey->input->dev,
"Cannot read FAULT_LOG: %d\n", error);
} else if (fault_log & DA9063_KEY_RESET) {
error = regmap_write(onkey->hw->regmap,
DA9063_REG_FAULT_LOG,
DA9063_KEY_RESET);
} else if (fault_log & config->onkey_key_reset_mask) {
error = regmap_write(onkey->regmap,
config->onkey_fault_log,
config->onkey_key_reset_mask);
if (error) {
dev_warn(&onkey->input->dev,
"Cannot reset KEY_RESET fault log: %d\n",
......@@ -88,10 +149,10 @@ static void da9063_poll_on(struct work_struct *work)
* and then send shutdown command
*/
dev_dbg(&onkey->input->dev,
"Sending SHUTDOWN to DA9063 ...\n");
error = regmap_write(onkey->hw->regmap,
DA9063_REG_CONTROL_F,
DA9063_SHUTDOWN);
"Sending SHUTDOWN to DA9063 ...\n");
error = regmap_write(onkey->regmap,
config->onkey_shutdown,
config->onkey_shutdown_mask);
if (error)
dev_err(&onkey->input->dev,
"Cannot SHUTDOWN DA9063: %d\n",
......@@ -107,11 +168,14 @@ static void da9063_poll_on(struct work_struct *work)
static irqreturn_t da9063_onkey_irq_handler(int irq, void *data)
{
struct da9063_onkey *onkey = data;
const struct da906x_chip_config *config = onkey->config;
unsigned int val;
int error;
error = regmap_read(onkey->hw->regmap, DA9063_REG_STATUS_A, &val);
if (onkey->key_power && !error && (val & DA9063_NONKEY)) {
error = regmap_read(onkey->regmap,
config->onkey_status,
&val);
if (onkey->key_power && !error && (val & config->onkey_nonkey_mask)) {
input_report_key(onkey->input, KEY_POWER, 1);
input_sync(onkey->input);
schedule_delayed_work(&onkey->work, 0);
......@@ -139,9 +203,15 @@ static int da9063_onkey_probe(struct platform_device *pdev)
struct da9063 *da9063 = dev_get_drvdata(pdev->dev.parent);
struct da9063_pdata *pdata = dev_get_platdata(da9063->dev);
struct da9063_onkey *onkey;
const struct of_device_id *match;
int irq;
int error;
match = of_match_node(da9063_compatible_reg_id_table,
pdev->dev.of_node);
if (!match)
return -ENXIO;
onkey = devm_kzalloc(&pdev->dev, sizeof(struct da9063_onkey),
GFP_KERNEL);
if (!onkey) {
......@@ -149,8 +219,14 @@ static int da9063_onkey_probe(struct platform_device *pdev)
return -ENOMEM;
}
onkey->config = match->data;
onkey->dev = &pdev->dev;
onkey->hw = da9063;
onkey->regmap = dev_get_regmap(pdev->dev.parent, NULL);
if (!onkey->regmap) {
dev_err(&pdev->dev, "Parent regmap unavailable.\n");
return -ENXIO;
}
if (pdata)
onkey->key_power = pdata->key_power;
......@@ -165,8 +241,10 @@ static int da9063_onkey_probe(struct platform_device *pdev)
return -ENOMEM;
}
onkey->input->name = DA9063_DRVNAME_ONKEY;
onkey->input->phys = DA9063_DRVNAME_ONKEY "/input0";
onkey->input->name = onkey->config->name;
snprintf(onkey->phys, sizeof(onkey->phys), "%s/input0",
onkey->config->name);
onkey->input->phys = onkey->phys;
onkey->input->dev.parent = &pdev->dev;
if (onkey->key_power)
......@@ -216,11 +294,12 @@ static struct platform_driver da9063_onkey_driver = {
.probe = da9063_onkey_probe,
.driver = {
.name = DA9063_DRVNAME_ONKEY,
.of_match_table = da9063_compatible_reg_id_table,
},
};
module_platform_driver(da9063_onkey_driver);
MODULE_AUTHOR("S Twiss <stwiss.opensource@diasemi.com>");
MODULE_DESCRIPTION("Onkey device driver for Dialog DA9063");
MODULE_DESCRIPTION("Onkey device driver for Dialog DA9063 and DA9062");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" DA9063_DRVNAME_ONKEY);
......@@ -198,7 +198,7 @@ static int64_t hp_sdc_rtc_read_i8042timer (uint8_t loadcmd, int numreg)
/* Read the i8042 real-time clock */
static inline int hp_sdc_rtc_read_rt(struct timeval *res) {
static inline int hp_sdc_rtc_read_rt(struct timespec64 *res) {
int64_t raw;
uint32_t tenms;
unsigned int days;
......@@ -209,15 +209,15 @@ static inline int hp_sdc_rtc_read_rt(struct timeval *res) {
tenms = (uint32_t)raw & 0xffffff;
days = (unsigned int)(raw >> 24) & 0xffff;
res->tv_usec = (suseconds_t)(tenms % 100) * 10000;
res->tv_sec = (time_t)(tenms / 100) + days * 86400;
res->tv_nsec = (long)(tenms % 100) * 10000 * 1000;
res->tv_sec = (tenms / 100) + (time64_t)days * 86400;
return 0;
}
/* Read the i8042 fast handshake timer */
static inline int hp_sdc_rtc_read_fhs(struct timeval *res) {
static inline int hp_sdc_rtc_read_fhs(struct timespec64 *res) {
int64_t raw;
unsigned int tenms;
......@@ -226,15 +226,15 @@ static inline int hp_sdc_rtc_read_fhs(struct timeval *res) {
tenms = (unsigned int)raw & 0xffff;
res->tv_usec = (suseconds_t)(tenms % 100) * 10000;
res->tv_sec = (time_t)(tenms / 100);
res->tv_nsec = (long)(tenms % 100) * 10000 * 1000;
res->tv_sec = (time64_t)(tenms / 100);
return 0;
}
/* Read the i8042 match timer (a.k.a. alarm) */
static inline int hp_sdc_rtc_read_mt(struct timeval *res) {
static inline int hp_sdc_rtc_read_mt(struct timespec64 *res) {
int64_t raw;
uint32_t tenms;
......@@ -243,15 +243,15 @@ static inline int hp_sdc_rtc_read_mt(struct timeval *res) {
tenms = (uint32_t)raw & 0xffffff;
res->tv_usec = (suseconds_t)(tenms % 100) * 10000;
res->tv_sec = (time_t)(tenms / 100);
res->tv_nsec = (long)(tenms % 100) * 10000 * 1000;
res->tv_sec = (time64_t)(tenms / 100);
return 0;
}
/* Read the i8042 delay timer */
static inline int hp_sdc_rtc_read_dt(struct timeval *res) {
static inline int hp_sdc_rtc_read_dt(struct timespec64 *res) {
int64_t raw;
uint32_t tenms;
......@@ -260,15 +260,15 @@ static inline int hp_sdc_rtc_read_dt(struct timeval *res) {
tenms = (uint32_t)raw & 0xffffff;
res->tv_usec = (suseconds_t)(tenms % 100) * 10000;
res->tv_sec = (time_t)(tenms / 100);
res->tv_nsec = (long)(tenms % 100) * 10000 * 1000;
res->tv_sec = (time64_t)(tenms / 100);
return 0;
}
/* Read the i8042 cycle timer (a.k.a. periodic) */
static inline int hp_sdc_rtc_read_ct(struct timeval *res) {
static inline int hp_sdc_rtc_read_ct(struct timespec64 *res) {
int64_t raw;
uint32_t tenms;
......@@ -277,8 +277,8 @@ static inline int hp_sdc_rtc_read_ct(struct timeval *res) {
tenms = (uint32_t)raw & 0xffffff;
res->tv_usec = (suseconds_t)(tenms % 100) * 10000;
res->tv_sec = (time_t)(tenms / 100);
res->tv_nsec = (long)(tenms % 100) * 10000 * 1000;
res->tv_sec = (time64_t)(tenms / 100);
return 0;
}
......@@ -433,7 +433,7 @@ static int hp_sdc_rtc_proc_show(struct seq_file *m, void *v)
#define YN(bit) ("no")
#define NY(bit) ("yes")
struct rtc_time tm;
struct timeval tv;
struct timespec64 tv;
memset(&tm, 0, sizeof(struct rtc_time));
......@@ -452,36 +452,36 @@ static int hp_sdc_rtc_proc_show(struct seq_file *m, void *v)
if (hp_sdc_rtc_read_rt(&tv)) {
seq_puts(m, "i8042 rtc\t: READ FAILED!\n");
} else {
seq_printf(m, "i8042 rtc\t: %ld.%02d seconds\n",
tv.tv_sec, (int)tv.tv_usec/1000);
seq_printf(m, "i8042 rtc\t: %lld.%02ld seconds\n",
(s64)tv.tv_sec, (long)tv.tv_nsec/1000000L);
}
if (hp_sdc_rtc_read_fhs(&tv)) {
seq_puts(m, "handshake\t: READ FAILED!\n");
} else {
seq_printf(m, "handshake\t: %ld.%02d seconds\n",
tv.tv_sec, (int)tv.tv_usec/1000);
seq_printf(m, "handshake\t: %lld.%02ld seconds\n",
(s64)tv.tv_sec, (long)tv.tv_nsec/1000000L);
}
if (hp_sdc_rtc_read_mt(&tv)) {
seq_puts(m, "alarm\t\t: READ FAILED!\n");
} else {
seq_printf(m, "alarm\t\t: %ld.%02d seconds\n",
tv.tv_sec, (int)tv.tv_usec/1000);
seq_printf(m, "alarm\t\t: %lld.%02ld seconds\n",
(s64)tv.tv_sec, (long)tv.tv_nsec/1000000L);
}
if (hp_sdc_rtc_read_dt(&tv)) {
seq_puts(m, "delay\t\t: READ FAILED!\n");
} else {
seq_printf(m, "delay\t\t: %ld.%02d seconds\n",
tv.tv_sec, (int)tv.tv_usec/1000);
seq_printf(m, "delay\t\t: %lld.%02ld seconds\n",
(s64)tv.tv_sec, (long)tv.tv_nsec/1000000L);
}
if (hp_sdc_rtc_read_ct(&tv)) {
seq_puts(m, "periodic\t: READ FAILED!\n");
} else {
seq_printf(m, "periodic\t: %ld.%02d seconds\n",
tv.tv_sec, (int)tv.tv_usec/1000);
seq_printf(m, "periodic\t: %lld.%02ld seconds\n",
(s64)tv.tv_sec, (long)tv.tv_nsec/1000000L);
}
seq_printf(m,
......
......@@ -635,7 +635,6 @@ static int __maybe_unused kxtj9_resume(struct device *dev)
struct i2c_client *client = to_i2c_client(dev);
struct kxtj9_data *tj9 = i2c_get_clientdata(client);
struct input_dev *input_dev = tj9->input_dev;
int retval = 0;
mutex_lock(&input_dev->mutex);
......@@ -643,7 +642,7 @@ static int __maybe_unused kxtj9_resume(struct device *dev)
kxtj9_enable(tj9);
mutex_unlock(&input_dev->mutex);
return retval;
return 0;
}
static SIMPLE_DEV_PM_OPS(kxtj9_pm_ops, kxtj9_suspend, kxtj9_resume);
......
......@@ -26,6 +26,7 @@
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/of_gpio.h>
#include <linux/pm.h>
#define DRV_NAME "rotary-encoder"
......@@ -142,6 +143,55 @@ static irqreturn_t rotary_encoder_half_period_irq(int irq, void *dev_id)
return IRQ_HANDLED;
}
static irqreturn_t rotary_encoder_quarter_period_irq(int irq, void *dev_id)
{
struct rotary_encoder *encoder = dev_id;
unsigned char sum;
int state;
state = rotary_encoder_get_state(encoder->pdata);
/*
* We encode the previous and the current state using a byte.
* The previous state in the MSB nibble, the current state in the LSB
* nibble. Then use a table to decide the direction of the turn.
*/
sum = (encoder->last_stable << 4) + state;
switch (sum) {
case 0x31:
case 0x10:
case 0x02:
case 0x23:
encoder->dir = 0; /* clockwise */
break;
case 0x13:
case 0x01:
case 0x20:
case 0x32:
encoder->dir = 1; /* counter-clockwise */
break;
default:
/*
* Ignore all other values. This covers the case when the
* state didn't change (a spurious interrupt) and the
* cases where the state changed by two steps, making it
* impossible to tell the direction.
*
* In either case, don't report any event and save the
* state for later.
*/
goto out;
}
rotary_encoder_report_event(encoder);
out:
encoder->last_stable = state;
return IRQ_HANDLED;
}
#ifdef CONFIG_OF
static const struct of_device_id rotary_encoder_of_match[] = {
{ .compatible = "rotary-encoder", },
......@@ -156,6 +206,7 @@ static struct rotary_encoder_platform_data *rotary_encoder_parse_dt(struct devic
struct device_node *np = dev->of_node;
struct rotary_encoder_platform_data *pdata;
enum of_gpio_flags flags;
int error;
if (!of_id || !np)
return NULL;
......@@ -174,12 +225,27 @@ static struct rotary_encoder_platform_data *rotary_encoder_parse_dt(struct devic
pdata->gpio_b = of_get_gpio_flags(np, 1, &flags);
pdata->inverted_b = flags & OF_GPIO_ACTIVE_LOW;
pdata->relative_axis = !!of_get_property(np,
"rotary-encoder,relative-axis", NULL);
pdata->rollover = !!of_get_property(np,
"rotary-encoder,rollover", NULL);
pdata->half_period = !!of_get_property(np,
"rotary-encoder,half-period", NULL);
pdata->relative_axis =
of_property_read_bool(np, "rotary-encoder,relative-axis");
pdata->rollover = of_property_read_bool(np, "rotary-encoder,rollover");
error = of_property_read_u32(np, "rotary-encoder,steps-per-period",
&pdata->steps_per_period);
if (error) {
/*
* The 'half-period' property has been deprecated, you must use
* 'steps-per-period' and set an appropriate value, but we still
* need to parse it to maintain compatibility.
*/
if (of_property_read_bool(np, "rotary-encoder,half-period")) {
pdata->steps_per_period = 2;
} else {
/* Fallback to one step per period behavior */
pdata->steps_per_period = 1;
}
}
pdata->wakeup_source = of_property_read_bool(np, "wakeup-source");
return pdata;
}
......@@ -250,12 +316,23 @@ static int rotary_encoder_probe(struct platform_device *pdev)
encoder->irq_a = gpio_to_irq(pdata->gpio_a);
encoder->irq_b = gpio_to_irq(pdata->gpio_b);
/* request the IRQs */
if (pdata->half_period) {
switch (pdata->steps_per_period) {
case 4:
handler = &rotary_encoder_quarter_period_irq;
encoder->last_stable = rotary_encoder_get_state(pdata);
break;
case 2:
handler = &rotary_encoder_half_period_irq;
encoder->last_stable = rotary_encoder_get_state(pdata);
} else {
break;
case 1:
handler = &rotary_encoder_irq;
break;
default:
dev_err(dev, "'%d' is not a valid steps-per-period value\n",
pdata->steps_per_period);
err = -EINVAL;
goto exit_free_gpio_b;
}
err = request_irq(encoder->irq_a, handler,
......@@ -280,6 +357,8 @@ static int rotary_encoder_probe(struct platform_device *pdev)
goto exit_free_irq_b;
}
device_init_wakeup(&pdev->dev, pdata->wakeup_source);
platform_set_drvdata(pdev, encoder);
return 0;
......@@ -306,6 +385,8 @@ static int rotary_encoder_remove(struct platform_device *pdev)
struct rotary_encoder *encoder = platform_get_drvdata(pdev);
const struct rotary_encoder_platform_data *pdata = encoder->pdata;
device_init_wakeup(&pdev->dev, false);
free_irq(encoder->irq_a, encoder);
free_irq(encoder->irq_b, encoder);
gpio_free(pdata->gpio_a);
......@@ -320,11 +401,41 @@ static int rotary_encoder_remove(struct platform_device *pdev)
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int rotary_encoder_suspend(struct device *dev)
{
struct rotary_encoder *encoder = dev_get_drvdata(dev);
if (device_may_wakeup(dev)) {
enable_irq_wake(encoder->irq_a);
enable_irq_wake(encoder->irq_b);
}
return 0;
}
static int rotary_encoder_resume(struct device *dev)
{
struct rotary_encoder *encoder = dev_get_drvdata(dev);
if (device_may_wakeup(dev)) {
disable_irq_wake(encoder->irq_a);
disable_irq_wake(encoder->irq_b);
}
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(rotary_encoder_pm_ops,
rotary_encoder_suspend, rotary_encoder_resume);
static struct platform_driver rotary_encoder_driver = {
.probe = rotary_encoder_probe,
.remove = rotary_encoder_remove,
.driver = {
.name = DRV_NAME,
.pm = &rotary_encoder_pm_ops,
.of_match_table = of_match_ptr(rotary_encoder_of_match),
}
};
......
......@@ -129,8 +129,14 @@ static int xenkbd_probe(struct xenbus_device *dev,
if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-abs-pointer", "%d", &abs) < 0)
abs = 0;
if (abs)
xenbus_printf(XBT_NIL, dev->nodename, "request-abs-pointer", "1");
if (abs) {
ret = xenbus_printf(XBT_NIL, dev->nodename,
"request-abs-pointer", "1");
if (ret) {
pr_warning("xenkbd: can't request abs-pointer");
abs = 0;
}
}
/* keyboard */
kbd = input_allocate_device();
......
......@@ -292,4 +292,18 @@ config SERIO_SUN4I_PS2
To compile this driver as a module, choose M here: the
module will be called sun4i-ps2.
config USERIO
tristate "User space serio port driver support"
help
Say Y here if you want to support user level drivers for serio
subsystem accessible under char device 10:240 - /dev/userio. Using
this facility userspace programs can implement serio ports that
will be used by the standard in-kernel serio consumer drivers,
such as psmouse and atkbd.
To compile this driver as a module, choose M here: the module will be
called userio.
If you are unsure, say N.
endif
......@@ -30,3 +30,4 @@ obj-$(CONFIG_SERIO_APBPS2) += apbps2.o
obj-$(CONFIG_SERIO_OLPC_APSP) += olpc_apsp.o
obj-$(CONFIG_HYPERV_KEYBOARD) += hyperv-keyboard.o
obj-$(CONFIG_SERIO_SUN4I_PS2) += sun4i-ps2.o
obj-$(CONFIG_USERIO) += userio.o
......@@ -141,19 +141,15 @@ static void parkbd_interrupt(void *dev_id)
parkbd_last = jiffies;
}
static int parkbd_getport(void)
static int parkbd_getport(struct parport *pp)
{
struct parport *pp;
struct pardev_cb parkbd_parport_cb;
pp = parport_find_number(parkbd_pp_no);
parkbd_parport_cb.irq_func = parkbd_interrupt;
parkbd_parport_cb.flags = PARPORT_FLAG_EXCL;
if (pp == NULL) {
printk(KERN_ERR "parkbd: no such parport\n");
return -ENODEV;
}
parkbd_dev = parport_register_device(pp, "parkbd", NULL, NULL, parkbd_interrupt, PARPORT_DEV_EXCL, NULL);
parport_put_port(pp);
parkbd_dev = parport_register_dev_model(pp, "parkbd",
&parkbd_parport_cb, 0);
if (!parkbd_dev)
return -ENODEV;
......@@ -183,19 +179,21 @@ static struct serio * __init parkbd_allocate_serio(void)
return serio;
}
static int __init parkbd_init(void)
static void parkbd_attach(struct parport *pp)
{
int err;
if (pp->number != parkbd_pp_no) {
pr_debug("Not using parport%d.\n", pp->number);
return;
}
err = parkbd_getport();
if (err)
return err;
if (parkbd_getport(pp))
return;
parkbd_port = parkbd_allocate_serio();
if (!parkbd_port) {
parport_release(parkbd_dev);
parport_unregister_device(parkbd_dev);
return -ENOMEM;
return;
}
parkbd_writelines(3);
......@@ -205,14 +203,35 @@ static int __init parkbd_init(void)
printk(KERN_INFO "serio: PARKBD %s adapter on %s\n",
parkbd_mode ? "AT" : "XT", parkbd_dev->port->name);
return 0;
return;
}
static void __exit parkbd_exit(void)
static void parkbd_detach(struct parport *port)
{
if (!parkbd_port || port->number != parkbd_pp_no)
return;
parport_release(parkbd_dev);
serio_unregister_port(parkbd_port);
parport_unregister_device(parkbd_dev);
parkbd_port = NULL;
}
static struct parport_driver parkbd_parport_driver = {
.name = "parkbd",
.match_port = parkbd_attach,
.detach = parkbd_detach,
.devmodel = true,
};
static int __init parkbd_init(void)
{
return parport_register_driver(&parkbd_parport_driver);
}
static void __exit parkbd_exit(void)
{
parport_unregister_driver(&parkbd_parport_driver);
}
module_init(parkbd_init);
......
/*
* userio kernel serio device emulation module
* Copyright (C) 2015 Red Hat
* Copyright (C) 2015 Stephen Chandler Paul <thatslyude@gmail.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* 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 Lesser
* General Public License for more details.
*/
#include <linux/circ_buf.h>
#include <linux/mutex.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/serio.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/sched.h>
#include <linux/poll.h>
#include <uapi/linux/userio.h>
#define USERIO_NAME "userio"
#define USERIO_BUFSIZE 16
static struct miscdevice userio_misc;
struct userio_device {
struct serio *serio;
struct mutex mutex;
bool running;
u8 head;
u8 tail;
spinlock_t buf_lock;
unsigned char buf[USERIO_BUFSIZE];
wait_queue_head_t waitq;
};
/**
* userio_device_write - Write data from serio to a userio device in userspace
* @id: The serio port for the userio device
* @val: The data to write to the device
*/
static int userio_device_write(struct serio *id, unsigned char val)
{
struct userio_device *userio = id->port_data;
unsigned long flags;
spin_lock_irqsave(&userio->buf_lock, flags);
userio->buf[userio->head] = val;
userio->head = (userio->head + 1) % USERIO_BUFSIZE;
if (userio->head == userio->tail)
dev_warn(userio_misc.this_device,
"Buffer overflowed, userio client isn't keeping up");
spin_unlock_irqrestore(&userio->buf_lock, flags);
wake_up_interruptible(&userio->waitq);
return 0;
}
static int userio_char_open(struct inode *inode, struct file *file)
{
struct userio_device *userio;
userio = kzalloc(sizeof(struct userio_device), GFP_KERNEL);
if (!userio)
return -ENOMEM;
mutex_init(&userio->mutex);
spin_lock_init(&userio->buf_lock);
init_waitqueue_head(&userio->waitq);
userio->serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
if (!userio->serio) {
kfree(userio);
return -ENOMEM;
}
userio->serio->write = userio_device_write;
userio->serio->port_data = userio;
file->private_data = userio;
return 0;
}
static int userio_char_release(struct inode *inode, struct file *file)
{
struct userio_device *userio = file->private_data;
if (userio->running) {
/*
* Don't free the serio port here, serio_unregister_port()
* does it for us.
*/
serio_unregister_port(userio->serio);
} else {
kfree(userio->serio);
}
kfree(userio);
return 0;
}
static ssize_t userio_char_read(struct file *file, char __user *user_buffer,
size_t count, loff_t *ppos)
{
struct userio_device *userio = file->private_data;
int error;
size_t nonwrap_len, copylen;
unsigned char buf[USERIO_BUFSIZE];
unsigned long flags;
/*
* By the time we get here, the data that was waiting might have
* been taken by another thread. Grab the buffer lock and check if
* there's still any data waiting, otherwise repeat this process
* until we have data (unless the file descriptor is non-blocking
* of course).
*/
for (;;) {
spin_lock_irqsave(&userio->buf_lock, flags);
nonwrap_len = CIRC_CNT_TO_END(userio->head,
userio->tail,
USERIO_BUFSIZE);
copylen = min(nonwrap_len, count);
if (copylen) {
memcpy(buf, &userio->buf[userio->tail], copylen);
userio->tail = (userio->tail + copylen) %
USERIO_BUFSIZE;
}
spin_unlock_irqrestore(&userio->buf_lock, flags);
if (nonwrap_len)
break;
/* buffer was/is empty */
if (file->f_flags & O_NONBLOCK)
return -EAGAIN;
/*
* count == 0 is special - no IO is done but we check
* for error conditions (see above).
*/
if (count == 0)
return 0;
error = wait_event_interruptible(userio->waitq,
userio->head != userio->tail);
if (error)
return error;
}
if (copylen)
if (copy_to_user(user_buffer, buf, copylen))
return -EFAULT;
return copylen;
}
static ssize_t userio_char_write(struct file *file, const char __user *buffer,
size_t count, loff_t *ppos)
{
struct userio_device *userio = file->private_data;
struct userio_cmd cmd;
int error;
if (count != sizeof(cmd)) {
dev_warn(userio_misc.this_device, "Invalid payload size\n");
return -EINVAL;
}
if (copy_from_user(&cmd, buffer, sizeof(cmd)))
return -EFAULT;
error = mutex_lock_interruptible(&userio->mutex);
if (error)
return error;
switch (cmd.type) {
case USERIO_CMD_REGISTER:
if (!userio->serio->id.type) {
dev_warn(userio_misc.this_device,
"No port type given on /dev/userio\n");
error = -EINVAL;
goto out;
}
if (userio->running) {
dev_warn(userio_misc.this_device,
"Begin command sent, but we're already running\n");
error = -EBUSY;
goto out;
}
userio->running = true;
serio_register_port(userio->serio);
break;
case USERIO_CMD_SET_PORT_TYPE:
if (userio->running) {
dev_warn(userio_misc.this_device,
"Can't change port type on an already running userio instance\n");
error = -EBUSY;
goto out;
}
userio->serio->id.type = cmd.data;
break;
case USERIO_CMD_SEND_INTERRUPT:
if (!userio->running) {
dev_warn(userio_misc.this_device,
"The device must be registered before sending interrupts\n");
error = -ENODEV;
goto out;
}
serio_interrupt(userio->serio, cmd.data, 0);
break;
default:
error = -EOPNOTSUPP;
goto out;
}
out:
mutex_unlock(&userio->mutex);
return error ?: count;
}
static unsigned int userio_char_poll(struct file *file, poll_table *wait)
{
struct userio_device *userio = file->private_data;
poll_wait(file, &userio->waitq, wait);
if (userio->head != userio->tail)
return POLLIN | POLLRDNORM;
return 0;
}
static const struct file_operations userio_fops = {
.owner = THIS_MODULE,
.open = userio_char_open,
.release = userio_char_release,
.read = userio_char_read,
.write = userio_char_write,
.poll = userio_char_poll,
.llseek = no_llseek,
};
static struct miscdevice userio_misc = {
.fops = &userio_fops,
.minor = USERIO_MINOR,
.name = USERIO_NAME,
};
module_driver(userio_misc, misc_register, misc_deregister);
MODULE_ALIAS_MISCDEV(USERIO_MINOR);
MODULE_ALIAS("devname:" USERIO_NAME);
MODULE_AUTHOR("Stephen Chandler Paul <thatslyude@gmail.com>");
MODULE_DESCRIPTION("Virtual Serio Device Support");
MODULE_LICENSE("GPL");
......@@ -295,6 +295,19 @@ config TOUCHSCREEN_EGALAX
To compile this driver as a module, choose M here: the
module will be called egalax_ts.
config TOUCHSCREEN_FT6236
tristate "FT6236 I2C touchscreen"
depends on I2C
depends on GPIOLIB || COMPILE_TEST
help
Say Y here to enable support for the I2C connected FT6x06 and
FT6x36 family of capacitive touchscreen drivers.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called ft6236.
config TOUCHSCREEN_FUJITSU
tristate "Fujitsu serial touchscreen"
select SERIO
......@@ -1065,4 +1078,15 @@ config TOUCHSCREEN_COLIBRI_VF50
To compile this driver as a module, choose M here: the
module will be called colibri_vf50_ts.
config TOUCHSCREEN_ROHM_BU21023
tristate "ROHM BU21023/24 Dual touch support resistive touchscreens"
depends on I2C
help
Say Y here if you have a touchscreen using ROHM BU21023/24.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called bu21023_ts.
endif
......@@ -35,6 +35,7 @@ obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o
obj-$(CONFIG_TOUCHSCREEN_ELAN) += elants_i2c.o
obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o
obj-$(CONFIG_TOUCHSCREEN_EGALAX) += egalax_ts.o
obj-$(CONFIG_TOUCHSCREEN_FT6236) += ft6236.o
obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o
obj-$(CONFIG_TOUCHSCREEN_GOODIX) += goodix.o
obj-$(CONFIG_TOUCHSCREEN_ILI210X) += ili210x.o
......@@ -87,3 +88,4 @@ obj-$(CONFIG_TOUCHSCREEN_SX8654) += sx8654.o
obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o
obj-$(CONFIG_TOUCHSCREEN_ZFORCE) += zforce_ts.o
obj-$(CONFIG_TOUCHSCREEN_COLIBRI_VF50) += colibri-vf50-ts.o
obj-$(CONFIG_TOUCHSCREEN_ROHM_BU21023) += rohm_bu21023.o
......@@ -529,10 +529,8 @@ static int ads784x_hwmon_register(struct spi_device *spi, struct ads7846 *ts)
ts->hwmon = hwmon_device_register_with_groups(&spi->dev, spi->modalias,
ts, ads7846_attr_groups);
if (IS_ERR(ts->hwmon))
return PTR_ERR(ts->hwmon);
return 0;
return PTR_ERR_OR_ZERO(ts->hwmon);
}
static void ads784x_hwmon_unregister(struct spi_device *spi,
......
......@@ -399,13 +399,8 @@ static int auo_pixcir_stop(struct auo_pixcir_ts *ts)
static int auo_pixcir_input_open(struct input_dev *dev)
{
struct auo_pixcir_ts *ts = input_get_drvdata(dev);
int ret;
ret = auo_pixcir_start(ts);
if (ret)
return ret;
return 0;
return auo_pixcir_start(ts);
}
static void auo_pixcir_input_close(struct input_dev *dev)
......
......@@ -50,10 +50,7 @@ static int cyttsp4_i2c_probe(struct i2c_client *client,
ts = cyttsp4_probe(&cyttsp4_i2c_bus_ops, &client->dev, client->irq,
CYTTSP4_I2C_DATA_SIZE);
if (IS_ERR(ts))
return PTR_ERR(ts);
return 0;
return PTR_ERR_OR_ZERO(ts);
}
static int cyttsp4_i2c_remove(struct i2c_client *client)
......
This diff is collapsed.
This diff is collapsed.
......@@ -377,8 +377,6 @@ static int __maybe_unused pixcir_i2c_ts_suspend(struct device *dev)
goto unlock;
}
}
enable_irq_wake(client->irq);
} else if (input->users) {
ret = pixcir_stop(ts);
}
......@@ -399,7 +397,6 @@ static int __maybe_unused pixcir_i2c_ts_resume(struct device *dev)
mutex_lock(&input->mutex);
if (device_may_wakeup(&client->dev)) {
disable_irq_wake(client->irq);
if (!input->users) {
ret = pixcir_stop(ts);
......@@ -564,14 +561,6 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
return error;
i2c_set_clientdata(client, tsdata);
device_init_wakeup(&client->dev, 1);
return 0;
}
static int pixcir_i2c_ts_remove(struct i2c_client *client)
{
device_init_wakeup(&client->dev, 0);
return 0;
}
......@@ -609,7 +598,6 @@ static struct i2c_driver pixcir_i2c_ts_driver = {
.of_match_table = of_match_ptr(pixcir_of_match),
},
.probe = pixcir_i2c_ts_probe,
.remove = pixcir_i2c_ts_remove,
.id_table = pixcir_i2c_ts_id,
};
......
This diff is collapsed.
......@@ -50,14 +50,7 @@ struct tps6507x_ts {
static int tps6507x_read_u8(struct tps6507x_ts *tsc, u8 reg, u8 *data)
{
int err;
err = tsc->mfd->read_dev(tsc->mfd, reg, 1, data);
if (err)
return err;
return 0;
return tsc->mfd->read_dev(tsc->mfd, reg, 1, data);
}
static int tps6507x_write_u8(struct tps6507x_ts *tsc, u8 reg, u8 data)
......
......@@ -599,13 +599,8 @@ static irqreturn_t zforce_irq_thread(int irq, void *dev_id)
static int zforce_input_open(struct input_dev *dev)
{
struct zforce_ts *ts = input_get_drvdata(dev);
int ret;
ret = zforce_start(ts);
if (ret)
return ret;
return 0;
return zforce_start(ts);
}
static void zforce_input_close(struct input_dev *dev)
......
This diff is collapsed.
../../uapi/linux/input-event-codes.h
\ No newline at end of file
......@@ -698,8 +698,8 @@ struct hid_driver {
int (*input_mapped)(struct hid_device *hdev,
struct hid_input *hidinput, struct hid_field *field,
struct hid_usage *usage, unsigned long **bit, int *max);
void (*input_configured)(struct hid_device *hdev,
struct hid_input *hidinput);
int (*input_configured)(struct hid_device *hdev,
struct hid_input *hidinput);
void (*feature_mapping)(struct hid_device *hdev,
struct hid_field *field,
struct hid_usage *usage);
......
......@@ -469,6 +469,8 @@ int input_get_keycode(struct input_dev *dev, struct input_keymap_entry *ke);
int input_set_keycode(struct input_dev *dev,
const struct input_keymap_entry *ke);
void input_enable_softrepeat(struct input_dev *dev, int delay, int period);
extern struct class input_class;
/**
......
#ifndef _EDT_FT5X06_H
#define _EDT_FT5X06_H
/*
* Copyright (c) 2012 Simon Budig, <simon.budig@kernelconcepts.de>
*
* 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.
*/
struct edt_ft5x06_platform_data {
int irq_pin;
int reset_pin;
/* startup defaults for operational parameters */
bool use_parameters;
u8 gain;
u8 threshold;
u8 offset;
u8 report_rate;
};
#endif /* _EDT_FT5X06_H */
......@@ -49,6 +49,7 @@
#define LOOP_CTRL_MINOR 237
#define VHOST_NET_MINOR 238
#define UHID_MINOR 239
#define USERIO_MINOR 240
#define MISC_DYNAMIC_MINOR 255
struct device;
......
......@@ -8,9 +8,10 @@ struct rotary_encoder_platform_data {
unsigned int gpio_b;
unsigned int inverted_a;
unsigned int inverted_b;
unsigned int steps_per_period;
bool relative_axis;
bool rollover;
bool half_period;
bool wakeup_source;
};
#endif /* __ROTARY_ENCODER_H__ */
......@@ -191,6 +191,7 @@ header-y += inet_diag.h
header-y += in.h
header-y += inotify.h
header-y += input.h
header-y += input-event-codes.h
header-y += in_route.h
header-y += ioctl.h
header-y += ip6_tunnel.h
......
This diff is collapsed.
This diff is collapsed.
/*
* userio: virtual serio device support
* Copyright (C) 2015 Red Hat
* Copyright (C) 2015 Lyude (Stephen Chandler Paul) <cpaul@redhat.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* 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 Lesser General Public License for more
* details.
*
* This is the public header used for user-space communication with the userio
* driver. __attribute__((__packed__)) is used for all structs to keep ABI
* compatibility between all architectures.
*/
#ifndef _USERIO_H
#define _USERIO_H
#include <linux/types.h>
enum userio_cmd_type {
USERIO_CMD_REGISTER = 0,
USERIO_CMD_SET_PORT_TYPE = 1,
USERIO_CMD_SEND_INTERRUPT = 2
};
/*
* userio Commands
* All commands sent to /dev/userio are encoded using this structure. The type
* field should contain a USERIO_CMD* value that indicates what kind of command
* is being sent to userio. The data field should contain the accompanying
* argument for the command, if there is one.
*/
struct userio_cmd {
__u8 type;
__u8 data;
} __attribute__((__packed__));
#endif /* !_USERIO_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment