You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (58 commits) Input: wacom_w8001 - support pen or touch only devices Input: wacom_w8001 - use __set_bit to set keybits Input: bu21013_ts - fix misuse of logical operation in place of bitop Input: i8042 - add Acer Aspire 5100 to the Dritek list Input: wacom - add support for digitizer in Lenovo W700 Input: psmouse - disable the synaptics extension on OLPC machines Input: psmouse - fix up Synaptics comment Input: synaptics - ignore bogus mt packet Input: synaptics - add multi-finger and semi-mt support Input: synaptics - report clickpad property input: mt: Document interface updates Input: fix double equality sign in uevent Input: introduce device properties hid: egalax: Add support for Wetab (726b) Input: include MT library as source for kerneldoc MAINTAINERS: Update input-mt entry hid: egalax: Add support for Samsung NB30 netbook hid: egalax: Document the new devices in Kconfig hid: egalax: Add support for Wetab hid: egalax: Convert to MT slots ... Fixed up trivial conflict in drivers/input/keyboard/Kconfig
This commit is contained in:
@@ -303,6 +303,10 @@ X!Idrivers/video/console/fonts.c
|
||||
!Edrivers/input/input.c
|
||||
!Edrivers/input/ff-core.c
|
||||
!Edrivers/input/ff-memless.c
|
||||
</sect1>
|
||||
<sect1><title>Multitouch Library</title>
|
||||
!Iinclude/linux/input/mt.h
|
||||
!Edrivers/input/input-mt.c
|
||||
</sect1>
|
||||
<sect1><title>Polled input devices</title>
|
||||
!Iinclude/linux/input-polldev.h
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
Kernel driver for CMA3000-D0x
|
||||
============================
|
||||
|
||||
Supported chips:
|
||||
* VTI CMA3000-D0x
|
||||
Datasheet:
|
||||
CMA3000-D0X Product Family Specification 8281000A.02.pdf
|
||||
<http://www.vti.fi/en/>
|
||||
|
||||
Author: Hemanth V <hemanthv@ti.com>
|
||||
|
||||
|
||||
Description
|
||||
-----------
|
||||
CMA3000 Tri-axis accelerometer supports Motion detect, Measurement and
|
||||
Free fall modes.
|
||||
|
||||
Motion Detect Mode: Its the low power mode where interrupts are generated only
|
||||
when motion exceeds the defined thresholds.
|
||||
|
||||
Measurement Mode: This mode is used to read the acceleration data on X,Y,Z
|
||||
axis and supports 400, 100, 40 Hz sample frequency.
|
||||
|
||||
Free fall Mode: This mode is intended to save system resources.
|
||||
|
||||
Threshold values: Chip supports defining threshold values for above modes
|
||||
which includes time and g value. Refer product specifications for more details.
|
||||
|
||||
CMA3000 chip supports mutually exclusive I2C and SPI interfaces for
|
||||
communication, currently the driver supports I2C based communication only.
|
||||
Initial configuration for bus mode is set in non volatile memory and can later
|
||||
be modified through bus interface command.
|
||||
|
||||
Driver reports acceleration data through input subsystem. It generates ABS_MISC
|
||||
event with value 1 when free fall is detected.
|
||||
|
||||
Platform data need to be configured for initial default values.
|
||||
|
||||
Platform Data
|
||||
-------------
|
||||
fuzz_x: Noise on X Axis
|
||||
|
||||
fuzz_y: Noise on Y Axis
|
||||
|
||||
fuzz_z: Noise on Z Axis
|
||||
|
||||
g_range: G range in milli g i.e 2000 or 8000
|
||||
|
||||
mode: Default Operating mode
|
||||
|
||||
mdthr: Motion detect g range threshold value
|
||||
|
||||
mdfftmr: Motion detect and free fall time threshold value
|
||||
|
||||
ffthr: Free fall g range threshold value
|
||||
|
||||
Input Interface
|
||||
--------------
|
||||
Input driver version is 1.0.0
|
||||
Input device ID: bus 0x18 vendor 0x0 product 0x0 version 0x0
|
||||
Input device name: "cma3000-accelerometer"
|
||||
Supported events:
|
||||
Event type 0 (Sync)
|
||||
Event type 3 (Absolute)
|
||||
Event code 0 (X)
|
||||
Value 47
|
||||
Min -8000
|
||||
Max 8000
|
||||
Fuzz 200
|
||||
Event code 1 (Y)
|
||||
Value -28
|
||||
Min -8000
|
||||
Max 8000
|
||||
Fuzz 200
|
||||
Event code 2 (Z)
|
||||
Value 905
|
||||
Min -8000
|
||||
Max 8000
|
||||
Fuzz 200
|
||||
Event code 40 (Misc)
|
||||
Value 0
|
||||
Min 0
|
||||
Max 1
|
||||
Event type 4 (Misc)
|
||||
|
||||
|
||||
Register/Platform parameters Description
|
||||
----------------------------------------
|
||||
|
||||
mode:
|
||||
0: power down mode
|
||||
1: 100 Hz Measurement mode
|
||||
2: 400 Hz Measurement mode
|
||||
3: 40 Hz Measurement mode
|
||||
4: Motion Detect mode (default)
|
||||
5: 100 Hz Free fall mode
|
||||
6: 40 Hz Free fall mode
|
||||
7: Power off mode
|
||||
|
||||
grange:
|
||||
2000: 2000 mg or 2G Range
|
||||
8000: 8000 mg or 8G Range
|
||||
|
||||
mdthr:
|
||||
X: X * 71mg (8G Range)
|
||||
X: X * 18mg (2G Range)
|
||||
|
||||
mdfftmr:
|
||||
X: (X & 0x70) * 100 ms (MDTMR)
|
||||
(X & 0x0F) * 2.5 ms (FFTMR 400 Hz)
|
||||
(X & 0x0F) * 10 ms (FFTMR 100 Hz)
|
||||
|
||||
ffthr:
|
||||
X: (X >> 2) * 18mg (2G Range)
|
||||
X: (X & 0x0F) * 71 mg (8G Range)
|
||||
@@ -1,6 +1,6 @@
|
||||
Multi-touch (MT) Protocol
|
||||
-------------------------
|
||||
Copyright (C) 2009 Henrik Rydberg <rydberg@euromail.se>
|
||||
Copyright (C) 2009-2010 Henrik Rydberg <rydberg@euromail.se>
|
||||
|
||||
|
||||
Introduction
|
||||
@@ -161,19 +161,24 @@ against the glass. The inner region will increase, and in general, the
|
||||
ratio ABS_MT_TOUCH_MAJOR / ABS_MT_WIDTH_MAJOR, which is always smaller than
|
||||
unity, is related to the contact pressure. For pressure-based devices,
|
||||
ABS_MT_PRESSURE may be used to provide the pressure on the contact area
|
||||
instead.
|
||||
instead. Devices capable of contact hovering can use ABS_MT_DISTANCE to
|
||||
indicate the distance between the contact and the surface.
|
||||
|
||||
In addition to the MAJOR parameters, the oval shape of the contact can be
|
||||
described by adding the MINOR parameters, such that MAJOR and MINOR are the
|
||||
major and minor axis of an ellipse. Finally, the orientation of the oval
|
||||
shape can be describe with the ORIENTATION parameter.
|
||||
|
||||
For type A devices, further specification of the touch shape is possible
|
||||
via ABS_MT_BLOB_ID.
|
||||
|
||||
The ABS_MT_TOOL_TYPE may be used to specify whether the touching tool is a
|
||||
contact or a pen or something else. Devices with more granular information
|
||||
may specify general shapes as blobs, i.e., as a sequence of rectangular
|
||||
shapes grouped together by an ABS_MT_BLOB_ID. Finally, for the few devices
|
||||
that currently support it, the ABS_MT_TRACKING_ID event may be used to
|
||||
report contact tracking from hardware [5].
|
||||
finger or a pen or something else. Finally, the ABS_MT_TRACKING_ID event
|
||||
may be used to track identified contacts over time [5].
|
||||
|
||||
In the type B protocol, ABS_MT_TOOL_TYPE and ABS_MT_TRACKING_ID are
|
||||
implicitly handled by input core; drivers should instead call
|
||||
input_mt_report_slot_state().
|
||||
|
||||
|
||||
Event Semantics
|
||||
@@ -213,6 +218,12 @@ The pressure, in arbitrary units, on the contact area. May be used instead
|
||||
of TOUCH and WIDTH for pressure-based devices or any device with a spatial
|
||||
signal intensity distribution.
|
||||
|
||||
ABS_MT_DISTANCE
|
||||
|
||||
The distance, in surface units, between the contact and the surface. Zero
|
||||
distance means the contact is touching the surface. A positive number means
|
||||
the contact is hovering above the surface.
|
||||
|
||||
ABS_MT_ORIENTATION
|
||||
|
||||
The orientation of the ellipse. The value should describe a signed quarter
|
||||
@@ -240,21 +251,24 @@ ABS_MT_TOOL_TYPE
|
||||
The type of approaching tool. A lot of kernel drivers cannot distinguish
|
||||
between different tool types, such as a finger or a pen. In such cases, the
|
||||
event should be omitted. The protocol currently supports MT_TOOL_FINGER and
|
||||
MT_TOOL_PEN [2].
|
||||
MT_TOOL_PEN [2]. For type B devices, this event is handled by input core;
|
||||
drivers should instead use input_mt_report_slot_state().
|
||||
|
||||
ABS_MT_BLOB_ID
|
||||
|
||||
The BLOB_ID groups several packets together into one arbitrarily shaped
|
||||
contact. This is a low-level anonymous grouping for type A devices, and
|
||||
contact. The sequence of points forms a polygon which defines the shape of
|
||||
the contact. This is a low-level anonymous grouping for type A devices, and
|
||||
should not be confused with the high-level trackingID [5]. Most type A
|
||||
devices do not have blob capability, so drivers can safely omit this event.
|
||||
|
||||
ABS_MT_TRACKING_ID
|
||||
|
||||
The TRACKING_ID identifies an initiated contact throughout its life cycle
|
||||
[5]. This event is mandatory for type B devices. The value range of the
|
||||
TRACKING_ID should be large enough to ensure unique identification of a
|
||||
contact maintained over an extended period of time.
|
||||
[5]. The value range of the TRACKING_ID should be large enough to ensure
|
||||
unique identification of a contact maintained over an extended period of
|
||||
time. For type B devices, this event is handled by input core; drivers
|
||||
should instead use input_mt_report_slot_state().
|
||||
|
||||
|
||||
Event Computation
|
||||
@@ -301,18 +315,19 @@ and with ORIENTATION, one can detect twisting of fingers.
|
||||
Notes
|
||||
-----
|
||||
|
||||
In order to stay compatible with existing applications, the data
|
||||
reported in a finger packet must not be recognized as single-touch
|
||||
events. In addition, all finger data must bypass input filtering,
|
||||
since subsequent events of the same type refer to different fingers.
|
||||
In order to stay compatible with existing applications, the data reported
|
||||
in a finger packet must not be recognized as single-touch events.
|
||||
|
||||
The first kernel driver to utilize the MT protocol is the bcm5974 driver,
|
||||
where examples can be found.
|
||||
For type A devices, all finger data bypasses input filtering, since
|
||||
subsequent events of the same type refer to different fingers.
|
||||
|
||||
For example usage of the type A protocol, see the bcm5974 driver. For
|
||||
example usage of the type B protocol, see the hid-egalax driver.
|
||||
|
||||
[1] With the extension ABS_MT_APPROACH_X and ABS_MT_APPROACH_Y, the
|
||||
difference between the contact position and the approaching tool position
|
||||
could be used to derive tilt.
|
||||
[2] The list can of course be extended.
|
||||
[3] Multitouch X driver project: http://bitmath.org/code/multitouch/.
|
||||
[3] The mtdev project: http://bitmath.org/code/mtdev/.
|
||||
[4] See the section on event computation.
|
||||
[5] See the section on finger tracking.
|
||||
|
||||
@@ -3065,8 +3065,10 @@ F: drivers/input/
|
||||
INPUT MULTITOUCH (MT) PROTOCOL
|
||||
M: Henrik Rydberg <rydberg@euromail.se>
|
||||
L: linux-input@vger.kernel.org
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/rydberg/input-mt.git
|
||||
S: Maintained
|
||||
F: Documentation/input/multi-touch-protocol.txt
|
||||
F: drivers/input/input-mt.c
|
||||
K: \b(ABS|SYN)_MT_
|
||||
|
||||
INTEL IDLE DRIVER
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright (C) 2010 ST Microelectronics
|
||||
* Rajeev Kumar<rajeev-dlh.kumar@st.com>
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public
|
||||
* License version 2. This program is licensed "as is" without any
|
||||
* warranty of any kind, whether express or implied.
|
||||
*/
|
||||
|
||||
#ifndef __PLAT_KEYBOARD_H
|
||||
#define __PLAT_KEYBOARD_H
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/input/matrix_keypad.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#define DECLARE_KEYMAP(_name) \
|
||||
int _name[] = { \
|
||||
KEY(0, 0, KEY_ESC), \
|
||||
KEY(0, 1, KEY_1), \
|
||||
KEY(0, 2, KEY_2), \
|
||||
KEY(0, 3, KEY_3), \
|
||||
KEY(0, 4, KEY_4), \
|
||||
KEY(0, 5, KEY_5), \
|
||||
KEY(0, 6, KEY_6), \
|
||||
KEY(0, 7, KEY_7), \
|
||||
KEY(0, 8, KEY_8), \
|
||||
KEY(1, 0, KEY_9), \
|
||||
KEY(1, 1, KEY_MINUS), \
|
||||
KEY(1, 2, KEY_EQUAL), \
|
||||
KEY(1, 3, KEY_BACKSPACE), \
|
||||
KEY(1, 4, KEY_TAB), \
|
||||
KEY(1, 5, KEY_Q), \
|
||||
KEY(1, 6, KEY_W), \
|
||||
KEY(1, 7, KEY_E), \
|
||||
KEY(1, 8, KEY_R), \
|
||||
KEY(2, 0, KEY_T), \
|
||||
KEY(2, 1, KEY_Y), \
|
||||
KEY(2, 2, KEY_U), \
|
||||
KEY(2, 3, KEY_I), \
|
||||
KEY(2, 4, KEY_O), \
|
||||
KEY(2, 5, KEY_P), \
|
||||
KEY(2, 6, KEY_LEFTBRACE), \
|
||||
KEY(2, 7, KEY_RIGHTBRACE), \
|
||||
KEY(2, 8, KEY_ENTER), \
|
||||
KEY(3, 0, KEY_LEFTCTRL), \
|
||||
KEY(3, 1, KEY_A), \
|
||||
KEY(3, 2, KEY_S), \
|
||||
KEY(3, 3, KEY_D), \
|
||||
KEY(3, 4, KEY_F), \
|
||||
KEY(3, 5, KEY_G), \
|
||||
KEY(3, 6, KEY_H), \
|
||||
KEY(3, 7, KEY_J), \
|
||||
KEY(3, 8, KEY_K), \
|
||||
KEY(4, 0, KEY_L), \
|
||||
KEY(4, 1, KEY_SEMICOLON), \
|
||||
KEY(4, 2, KEY_APOSTROPHE), \
|
||||
KEY(4, 3, KEY_GRAVE), \
|
||||
KEY(4, 4, KEY_LEFTSHIFT), \
|
||||
KEY(4, 5, KEY_BACKSLASH), \
|
||||
KEY(4, 6, KEY_Z), \
|
||||
KEY(4, 7, KEY_X), \
|
||||
KEY(4, 8, KEY_C), \
|
||||
KEY(4, 0, KEY_L), \
|
||||
KEY(4, 1, KEY_SEMICOLON), \
|
||||
KEY(4, 2, KEY_APOSTROPHE), \
|
||||
KEY(4, 3, KEY_GRAVE), \
|
||||
KEY(4, 4, KEY_LEFTSHIFT), \
|
||||
KEY(4, 5, KEY_BACKSLASH), \
|
||||
KEY(4, 6, KEY_Z), \
|
||||
KEY(4, 7, KEY_X), \
|
||||
KEY(4, 8, KEY_C), \
|
||||
KEY(4, 0, KEY_L), \
|
||||
KEY(4, 1, KEY_SEMICOLON), \
|
||||
KEY(4, 2, KEY_APOSTROPHE), \
|
||||
KEY(4, 3, KEY_GRAVE), \
|
||||
KEY(4, 4, KEY_LEFTSHIFT), \
|
||||
KEY(4, 5, KEY_BACKSLASH), \
|
||||
KEY(4, 6, KEY_Z), \
|
||||
KEY(4, 7, KEY_X), \
|
||||
KEY(4, 8, KEY_C), \
|
||||
KEY(5, 0, KEY_V), \
|
||||
KEY(5, 1, KEY_B), \
|
||||
KEY(5, 2, KEY_N), \
|
||||
KEY(5, 3, KEY_M), \
|
||||
KEY(5, 4, KEY_COMMA), \
|
||||
KEY(5, 5, KEY_DOT), \
|
||||
KEY(5, 6, KEY_SLASH), \
|
||||
KEY(5, 7, KEY_RIGHTSHIFT), \
|
||||
KEY(5, 8, KEY_KPASTERISK), \
|
||||
KEY(6, 0, KEY_LEFTALT), \
|
||||
KEY(6, 1, KEY_SPACE), \
|
||||
KEY(6, 2, KEY_CAPSLOCK), \
|
||||
KEY(6, 3, KEY_F1), \
|
||||
KEY(6, 4, KEY_F2), \
|
||||
KEY(6, 5, KEY_F3), \
|
||||
KEY(6, 6, KEY_F4), \
|
||||
KEY(6, 7, KEY_F5), \
|
||||
KEY(6, 8, KEY_F6), \
|
||||
KEY(7, 0, KEY_F7), \
|
||||
KEY(7, 1, KEY_F8), \
|
||||
KEY(7, 2, KEY_F9), \
|
||||
KEY(7, 3, KEY_F10), \
|
||||
KEY(7, 4, KEY_NUMLOCK), \
|
||||
KEY(7, 5, KEY_SCROLLLOCK), \
|
||||
KEY(7, 6, KEY_KP7), \
|
||||
KEY(7, 7, KEY_KP8), \
|
||||
KEY(7, 8, KEY_KP9), \
|
||||
KEY(8, 0, KEY_KPMINUS), \
|
||||
KEY(8, 1, KEY_KP4), \
|
||||
KEY(8, 2, KEY_KP5), \
|
||||
KEY(8, 3, KEY_KP6), \
|
||||
KEY(8, 4, KEY_KPPLUS), \
|
||||
KEY(8, 5, KEY_KP1), \
|
||||
KEY(8, 6, KEY_KP2), \
|
||||
KEY(8, 7, KEY_KP3), \
|
||||
KEY(8, 8, KEY_KP0), \
|
||||
}
|
||||
|
||||
/**
|
||||
* struct kbd_platform_data - spear keyboard platform data
|
||||
* keymap: pointer to keymap data (table and size)
|
||||
* rep: enables key autorepeat
|
||||
*
|
||||
* This structure is supposed to be used by platform code to supply
|
||||
* keymaps to drivers that implement keyboards.
|
||||
*/
|
||||
struct kbd_platform_data {
|
||||
const struct matrix_keymap_data *keymap;
|
||||
bool rep;
|
||||
};
|
||||
|
||||
/* This function is used to set platform data field of pdev->dev */
|
||||
static inline void
|
||||
kbd_set_plat_data(struct platform_device *pdev, struct kbd_platform_data *data)
|
||||
{
|
||||
pdev->dev.platform_data = data;
|
||||
}
|
||||
|
||||
#endif /* __PLAT_KEYBOARD_H */
|
||||
+2
-1
@@ -154,7 +154,8 @@ config HID_EGALAX
|
||||
tristate "eGalax multi-touch panel"
|
||||
depends on USB_HID
|
||||
---help---
|
||||
Support for the eGalax dual-touch panel.
|
||||
Support for the eGalax dual-touch panels, including the
|
||||
Joojoo and Wetab tablets.
|
||||
|
||||
config HID_ELECOM
|
||||
tristate "ELECOM BM084 bluetooth mouse"
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/input/mt.h>
|
||||
|
||||
MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
|
||||
MODULE_DESCRIPTION("3M PCT multitouch panels");
|
||||
@@ -27,8 +28,6 @@ MODULE_LICENSE("GPL");
|
||||
#include "hid-ids.h"
|
||||
|
||||
#define MAX_SLOTS 60
|
||||
#define MAX_TRKID USHRT_MAX
|
||||
#define MAX_EVENTS 360
|
||||
|
||||
/* estimated signal-to-noise ratios */
|
||||
#define SN_MOVE 2048
|
||||
@@ -36,14 +35,11 @@ MODULE_LICENSE("GPL");
|
||||
|
||||
struct mmm_finger {
|
||||
__s32 x, y, w, h;
|
||||
__u16 id;
|
||||
bool prev_touch;
|
||||
bool touch, valid;
|
||||
};
|
||||
|
||||
struct mmm_data {
|
||||
struct mmm_finger f[MAX_SLOTS];
|
||||
__u16 id;
|
||||
__u8 curid;
|
||||
__u8 nexp, nreal;
|
||||
bool touch, valid;
|
||||
@@ -117,14 +113,7 @@ static int mmm_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
||||
0, 1, 0, 0);
|
||||
return 1;
|
||||
case HID_DG_CONTACTID:
|
||||
field->logical_maximum = MAX_TRKID;
|
||||
hid_map_usage(hi, usage, bit, max,
|
||||
EV_ABS, ABS_MT_TRACKING_ID);
|
||||
input_set_abs_params(hi->input, ABS_MT_TRACKING_ID,
|
||||
0, MAX_TRKID, 0, 0);
|
||||
if (!hi->input->mt)
|
||||
input_mt_create_slots(hi->input, MAX_SLOTS);
|
||||
input_set_events_per_packet(hi->input, MAX_EVENTS);
|
||||
input_mt_init_slots(hi->input, MAX_SLOTS);
|
||||
return 1;
|
||||
}
|
||||
/* let hid-input decide for the others */
|
||||
@@ -154,7 +143,6 @@ static int mmm_input_mapped(struct hid_device *hdev, struct hid_input *hi,
|
||||
*/
|
||||
static void mmm_filter_event(struct mmm_data *md, struct input_dev *input)
|
||||
{
|
||||
struct mmm_finger *oldest = 0;
|
||||
int i;
|
||||
for (i = 0; i < MAX_SLOTS; ++i) {
|
||||
struct mmm_finger *f = &md->f[i];
|
||||
@@ -163,6 +151,7 @@ static void mmm_filter_event(struct mmm_data *md, struct input_dev *input)
|
||||
continue;
|
||||
}
|
||||
input_mt_slot(input, i);
|
||||
input_mt_report_slot_state(input, MT_TOOL_FINGER, f->touch);
|
||||
if (f->touch) {
|
||||
/* this finger is on the screen */
|
||||
int wide = (f->w > f->h);
|
||||
@@ -170,33 +159,16 @@ static void mmm_filter_event(struct mmm_data *md, struct input_dev *input)
|
||||
int major = max(f->w, f->h) >> 1;
|
||||
int minor = min(f->w, f->h) >> 1;
|
||||
|
||||
if (!f->prev_touch)
|
||||
f->id = md->id++;
|
||||
input_event(input, EV_ABS, ABS_MT_TRACKING_ID, f->id);
|
||||
input_event(input, EV_ABS, ABS_MT_POSITION_X, f->x);
|
||||
input_event(input, EV_ABS, ABS_MT_POSITION_Y, f->y);
|
||||
input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide);
|
||||
input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major);
|
||||
input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, minor);
|
||||
/* touchscreen emulation: pick the oldest contact */
|
||||
if (!oldest || ((f->id - oldest->id) & (SHRT_MAX + 1)))
|
||||
oldest = f;
|
||||
} else {
|
||||
/* this finger took off the screen */
|
||||
input_event(input, EV_ABS, ABS_MT_TRACKING_ID, -1);
|
||||
}
|
||||
f->prev_touch = f->touch;
|
||||
f->valid = 0;
|
||||
}
|
||||
|
||||
/* touchscreen emulation */
|
||||
if (oldest) {
|
||||
input_event(input, EV_KEY, BTN_TOUCH, 1);
|
||||
input_event(input, EV_ABS, ABS_X, oldest->x);
|
||||
input_event(input, EV_ABS, ABS_Y, oldest->y);
|
||||
} else {
|
||||
input_event(input, EV_KEY, BTN_TOUCH, 0);
|
||||
}
|
||||
input_mt_report_pointer_emulation(input, true);
|
||||
input_sync(input);
|
||||
}
|
||||
|
||||
|
||||
@@ -1300,6 +1300,9 @@ static const struct hid_device_id hid_blacklist[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH2) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH3) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH4) },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) },
|
||||
|
||||
+57
-74
@@ -2,6 +2,8 @@
|
||||
* HID driver for eGalax dual-touch panels
|
||||
*
|
||||
* Copyright (c) 2010 Stephane Chatty <chatty@enac.fr>
|
||||
* Copyright (c) 2010 Henrik Rydberg <rydberg@euromail.se>
|
||||
* Copyright (c) 2010 Canonical, Ltd.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -16,6 +18,7 @@
|
||||
#include <linux/hid.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/input/mt.h>
|
||||
#include <linux/slab.h>
|
||||
#include "usbhid/usbhid.h"
|
||||
|
||||
@@ -25,38 +28,53 @@ MODULE_LICENSE("GPL");
|
||||
|
||||
#include "hid-ids.h"
|
||||
|
||||
#define MAX_SLOTS 2
|
||||
|
||||
/* estimated signal-to-noise ratios */
|
||||
#define SN_MOVE 4096
|
||||
#define SN_PRESSURE 32
|
||||
|
||||
struct egalax_data {
|
||||
__u16 x, y, z;
|
||||
__u8 id;
|
||||
bool first; /* is this the first finger in the frame? */
|
||||
bool valid; /* valid finger data, or just placeholder? */
|
||||
bool activity; /* at least one active finger previously? */
|
||||
__u16 lastx, lasty, lastz; /* latest valid (x, y, z) in the frame */
|
||||
int valid;
|
||||
int slot;
|
||||
int touch;
|
||||
int x, y, z;
|
||||
};
|
||||
|
||||
static void set_abs(struct input_dev *input, unsigned int code,
|
||||
struct hid_field *field, int snratio)
|
||||
{
|
||||
int fmin = field->logical_minimum;
|
||||
int fmax = field->logical_maximum;
|
||||
int fuzz = snratio ? (fmax - fmin) / snratio : 0;
|
||||
input_set_abs_params(input, code, fmin, fmax, fuzz, 0);
|
||||
}
|
||||
|
||||
static int egalax_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
||||
struct hid_field *field, struct hid_usage *usage,
|
||||
unsigned long **bit, int *max)
|
||||
{
|
||||
struct input_dev *input = hi->input;
|
||||
|
||||
switch (usage->hid & HID_USAGE_PAGE) {
|
||||
|
||||
case HID_UP_GENDESK:
|
||||
switch (usage->hid) {
|
||||
case HID_GD_X:
|
||||
field->logical_maximum = 32760;
|
||||
hid_map_usage(hi, usage, bit, max,
|
||||
EV_ABS, ABS_MT_POSITION_X);
|
||||
set_abs(input, ABS_MT_POSITION_X, field, SN_MOVE);
|
||||
/* touchscreen emulation */
|
||||
input_set_abs_params(hi->input, ABS_X,
|
||||
field->logical_minimum,
|
||||
field->logical_maximum, 0, 0);
|
||||
set_abs(input, ABS_X, field, SN_MOVE);
|
||||
return 1;
|
||||
case HID_GD_Y:
|
||||
field->logical_maximum = 32760;
|
||||
hid_map_usage(hi, usage, bit, max,
|
||||
EV_ABS, ABS_MT_POSITION_Y);
|
||||
set_abs(input, ABS_MT_POSITION_Y, field, SN_MOVE);
|
||||
/* touchscreen emulation */
|
||||
input_set_abs_params(hi->input, ABS_Y,
|
||||
field->logical_minimum,
|
||||
field->logical_maximum, 0, 0);
|
||||
set_abs(input, ABS_Y, field, SN_MOVE);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@@ -66,6 +84,7 @@ static int egalax_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
||||
case HID_DG_TIPSWITCH:
|
||||
/* touchscreen emulation */
|
||||
hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
|
||||
input_set_capability(input, EV_KEY, BTN_TOUCH);
|
||||
return 1;
|
||||
case HID_DG_INRANGE:
|
||||
case HID_DG_CONFIDENCE:
|
||||
@@ -73,16 +92,15 @@ static int egalax_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
||||
case HID_DG_CONTACTMAX:
|
||||
return -1;
|
||||
case HID_DG_CONTACTID:
|
||||
hid_map_usage(hi, usage, bit, max,
|
||||
EV_ABS, ABS_MT_TRACKING_ID);
|
||||
input_mt_init_slots(input, MAX_SLOTS);
|
||||
return 1;
|
||||
case HID_DG_TIPPRESSURE:
|
||||
field->logical_minimum = 0;
|
||||
hid_map_usage(hi, usage, bit, max,
|
||||
EV_ABS, ABS_MT_PRESSURE);
|
||||
set_abs(input, ABS_MT_PRESSURE, field, SN_PRESSURE);
|
||||
/* touchscreen emulation */
|
||||
input_set_abs_params(hi->input, ABS_PRESSURE,
|
||||
field->logical_minimum,
|
||||
field->logical_maximum, 0, 0);
|
||||
set_abs(input, ABS_PRESSURE, field, SN_PRESSURE);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@@ -96,10 +114,10 @@ static int egalax_input_mapped(struct hid_device *hdev, struct hid_input *hi,
|
||||
struct hid_field *field, struct hid_usage *usage,
|
||||
unsigned long **bit, int *max)
|
||||
{
|
||||
/* tell hid-input to skip setup of these event types */
|
||||
if (usage->type == EV_KEY || usage->type == EV_ABS)
|
||||
clear_bit(usage->code, *bit);
|
||||
|
||||
return 0;
|
||||
set_bit(usage->type, hi->input->evbit);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -108,58 +126,16 @@ static int egalax_input_mapped(struct hid_device *hdev, struct hid_input *hi,
|
||||
*/
|
||||
static void egalax_filter_event(struct egalax_data *td, struct input_dev *input)
|
||||
{
|
||||
td->first = !td->first; /* touchscreen emulation */
|
||||
|
||||
if (td->valid) {
|
||||
/* emit multitouch events */
|
||||
input_event(input, EV_ABS, ABS_MT_TRACKING_ID, td->id);
|
||||
input_event(input, EV_ABS, ABS_MT_POSITION_X, td->x >> 3);
|
||||
input_event(input, EV_ABS, ABS_MT_POSITION_Y, td->y >> 3);
|
||||
input_mt_slot(input, td->slot);
|
||||
input_mt_report_slot_state(input, MT_TOOL_FINGER, td->touch);
|
||||
if (td->touch) {
|
||||
input_event(input, EV_ABS, ABS_MT_POSITION_X, td->x);
|
||||
input_event(input, EV_ABS, ABS_MT_POSITION_Y, td->y);
|
||||
input_event(input, EV_ABS, ABS_MT_PRESSURE, td->z);
|
||||
|
||||
input_mt_sync(input);
|
||||
|
||||
/*
|
||||
* touchscreen emulation: store (x, y) as
|
||||
* the last valid values in this frame
|
||||
*/
|
||||
td->lastx = td->x;
|
||||
td->lasty = td->y;
|
||||
td->lastz = td->z;
|
||||
}
|
||||
|
||||
/*
|
||||
* touchscreen emulation: if this is the second finger and at least
|
||||
* one in this frame is valid, the latest valid in the frame is
|
||||
* the oldest on the panel, the one we want for single touch
|
||||
*/
|
||||
if (!td->first && td->activity) {
|
||||
input_event(input, EV_ABS, ABS_X, td->lastx >> 3);
|
||||
input_event(input, EV_ABS, ABS_Y, td->lasty >> 3);
|
||||
input_event(input, EV_ABS, ABS_PRESSURE, td->lastz);
|
||||
}
|
||||
|
||||
if (!td->valid) {
|
||||
/*
|
||||
* touchscreen emulation: if the first finger is invalid
|
||||
* and there previously was finger activity, this is a release
|
||||
*/
|
||||
if (td->first && td->activity) {
|
||||
input_event(input, EV_KEY, BTN_TOUCH, 0);
|
||||
td->activity = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* touchscreen emulation: if no previous activity, emit touch event */
|
||||
if (!td->activity) {
|
||||
input_event(input, EV_KEY, BTN_TOUCH, 1);
|
||||
td->activity = true;
|
||||
}
|
||||
input_mt_report_pointer_emulation(input, true);
|
||||
}
|
||||
|
||||
|
||||
static int egalax_event(struct hid_device *hid, struct hid_field *field,
|
||||
struct hid_usage *usage, __s32 value)
|
||||
{
|
||||
@@ -169,25 +145,26 @@ static int egalax_event(struct hid_device *hid, struct hid_field *field,
|
||||
* uses a standard parallel multitouch protocol (product ID ==
|
||||
* 48xx). The second is capacitive and uses an unusual "serial"
|
||||
* protocol with a different message for each multitouch finger
|
||||
* (product ID == 72xx). We do not yet generate a correct event
|
||||
* sequence for the capacitive/serial protocol.
|
||||
* (product ID == 72xx).
|
||||
*/
|
||||
if (hid->claimed & HID_CLAIMED_INPUT) {
|
||||
struct input_dev *input = field->hidinput->input;
|
||||
|
||||
switch (usage->hid) {
|
||||
case HID_DG_INRANGE:
|
||||
td->valid = value;
|
||||
break;
|
||||
case HID_DG_CONFIDENCE:
|
||||
/* avoid interference from generic hidinput handling */
|
||||
break;
|
||||
case HID_DG_TIPSWITCH:
|
||||
td->valid = value;
|
||||
td->touch = value;
|
||||
break;
|
||||
case HID_DG_TIPPRESSURE:
|
||||
td->z = value;
|
||||
break;
|
||||
case HID_DG_CONTACTID:
|
||||
td->id = value;
|
||||
td->slot = clamp_val(value, 0, MAX_SLOTS - 1);
|
||||
break;
|
||||
case HID_GD_X:
|
||||
td->x = value;
|
||||
@@ -195,11 +172,11 @@ static int egalax_event(struct hid_device *hid, struct hid_field *field,
|
||||
case HID_GD_Y:
|
||||
td->y = value;
|
||||
/* this is the last field in a finger */
|
||||
egalax_filter_event(td, input);
|
||||
if (td->valid)
|
||||
egalax_filter_event(td, input);
|
||||
break;
|
||||
case HID_DG_CONTACTCOUNT:
|
||||
/* touch emulation: this is the last field in a frame */
|
||||
td->first = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -261,6 +238,12 @@ static const struct hid_device_id egalax_devices[] = {
|
||||
USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
|
||||
USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
|
||||
USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH2) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
|
||||
USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH3) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
|
||||
USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH4) },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(hid, egalax_devices);
|
||||
|
||||
@@ -196,6 +196,9 @@
|
||||
#define USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER 0x0001
|
||||
#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH 0x480d
|
||||
#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1 0x720c
|
||||
#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH2 0x72a1
|
||||
#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH3 0x480e
|
||||
#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH4 0x726b
|
||||
|
||||
#define USB_VENDOR_ID_ELECOM 0x056e
|
||||
#define USB_DEVICE_ID_ELECOM_BM084 0x0061
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
# Each configuration option enables a list of files.
|
||||
|
||||
obj-$(CONFIG_INPUT) += input-core.o
|
||||
input-core-objs := input.o input-compat.o ff-core.o
|
||||
input-core-y := input.o input-compat.o input-mt.o ff-core.o
|
||||
|
||||
obj-$(CONFIG_INPUT_FF_MEMLESS) += ff-memless.o
|
||||
obj-$(CONFIG_INPUT_POLLDEV) += input-polldev.o
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/slab.h>
|
||||
@@ -23,8 +25,7 @@ static void system_power_event(unsigned int keycode)
|
||||
switch (keycode) {
|
||||
case KEY_SUSPEND:
|
||||
apm_queue_event(APM_USER_SUSPEND);
|
||||
|
||||
printk(KERN_INFO "apm-power: Requesting system suspend...\n");
|
||||
pr_info("Requesting system suspend...\n");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -65,18 +66,15 @@ static int apmpower_connect(struct input_handler *handler,
|
||||
|
||||
error = input_register_handle(handle);
|
||||
if (error) {
|
||||
printk(KERN_ERR
|
||||
"apm-power: Failed to register input power handler, "
|
||||
"error %d\n", error);
|
||||
pr_err("Failed to register input power handler, error %d\n",
|
||||
error);
|
||||
kfree(handle);
|
||||
return error;
|
||||
}
|
||||
|
||||
error = input_open_device(handle);
|
||||
if (error) {
|
||||
printk(KERN_ERR
|
||||
"apm-power: Failed to open input power device, "
|
||||
"error %d\n", error);
|
||||
pr_err("Failed to open input power device, error %d\n", error);
|
||||
input_unregister_handle(handle);
|
||||
kfree(handle);
|
||||
return error;
|
||||
|
||||
+10
-8
@@ -26,6 +26,8 @@
|
||||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/input.h>
|
||||
@@ -38,8 +40,8 @@ MODULE_LICENSE("GPL");
|
||||
|
||||
static void evbug_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
|
||||
{
|
||||
printk(KERN_DEBUG "evbug.c: Event. Dev: %s, Type: %d, Code: %d, Value: %d\n",
|
||||
dev_name(&handle->dev->dev), type, code, value);
|
||||
printk(KERN_DEBUG pr_fmt("Event. Dev: %s, Type: %d, Code: %d, Value: %d\n"),
|
||||
dev_name(&handle->dev->dev), type, code, value);
|
||||
}
|
||||
|
||||
static int evbug_connect(struct input_handler *handler, struct input_dev *dev,
|
||||
@@ -64,10 +66,10 @@ static int evbug_connect(struct input_handler *handler, struct input_dev *dev,
|
||||
if (error)
|
||||
goto err_unregister_handle;
|
||||
|
||||
printk(KERN_DEBUG "evbug.c: Connected device: %s (%s at %s)\n",
|
||||
dev_name(&dev->dev),
|
||||
dev->name ?: "unknown",
|
||||
dev->phys ?: "unknown");
|
||||
printk(KERN_DEBUG pr_fmt("Connected device: %s (%s at %s)\n"),
|
||||
dev_name(&dev->dev),
|
||||
dev->name ?: "unknown",
|
||||
dev->phys ?: "unknown");
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -80,8 +82,8 @@ static int evbug_connect(struct input_handler *handler, struct input_dev *dev,
|
||||
|
||||
static void evbug_disconnect(struct input_handle *handle)
|
||||
{
|
||||
printk(KERN_DEBUG "evbug.c: Disconnected device: %s\n",
|
||||
dev_name(&handle->dev->dev));
|
||||
printk(KERN_DEBUG pr_fmt("Disconnected device: %s\n"),
|
||||
dev_name(&handle->dev->dev));
|
||||
|
||||
input_close_device(handle);
|
||||
input_unregister_handle(handle);
|
||||
|
||||
+12
-7
@@ -8,6 +8,8 @@
|
||||
* the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#define EVDEV_MINOR_BASE 64
|
||||
#define EVDEV_MINORS 32
|
||||
#define EVDEV_MIN_BUFFER_SIZE 64U
|
||||
@@ -522,12 +524,11 @@ static int handle_eviocgbit(struct input_dev *dev,
|
||||
if (type == EV_KEY && size == OLD_KEY_MAX) {
|
||||
len = OLD_KEY_MAX;
|
||||
if (printk_timed_ratelimit(&keymax_warn_time, 10 * 1000))
|
||||
printk(KERN_WARNING
|
||||
"evdev.c(EVIOCGBIT): Suspicious buffer size %u, "
|
||||
"limiting output to %zu bytes. See "
|
||||
"http://userweb.kernel.org/~dtor/eviocgbit-bug.html\n",
|
||||
OLD_KEY_MAX,
|
||||
BITS_TO_LONGS(OLD_KEY_MAX) * sizeof(long));
|
||||
pr_warning("(EVIOCGBIT): Suspicious buffer size %u, "
|
||||
"limiting output to %zu bytes. See "
|
||||
"http://userweb.kernel.org/~dtor/eviocgbit-bug.html\n",
|
||||
OLD_KEY_MAX,
|
||||
BITS_TO_LONGS(OLD_KEY_MAX) * sizeof(long));
|
||||
}
|
||||
|
||||
return bits_to_user(bits, len, size, p, compat_mode);
|
||||
@@ -686,6 +687,10 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
|
||||
#define EVIOC_MASK_SIZE(nr) ((nr) & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT))
|
||||
switch (EVIOC_MASK_SIZE(cmd)) {
|
||||
|
||||
case EVIOCGPROP(0):
|
||||
return bits_to_user(dev->propbit, INPUT_PROP_MAX,
|
||||
size, p, compat_mode);
|
||||
|
||||
case EVIOCGKEY(0):
|
||||
return bits_to_user(dev->key, KEY_MAX, size, p, compat_mode);
|
||||
|
||||
@@ -897,7 +902,7 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
|
||||
break;
|
||||
|
||||
if (minor == EVDEV_MINORS) {
|
||||
printk(KERN_ERR "evdev: no more free evdev devices\n");
|
||||
pr_err("no more free evdev devices\n");
|
||||
return -ENFILE;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
/* #define DEBUG */
|
||||
|
||||
#define debug(format, arg...) pr_debug("ff-core: " format "\n", ## arg)
|
||||
#define pr_fmt(fmt) KBUILD_BASENAME ": " fmt
|
||||
|
||||
#include <linux/input.h>
|
||||
#include <linux/module.h>
|
||||
@@ -116,7 +116,7 @@ int input_ff_upload(struct input_dev *dev, struct ff_effect *effect,
|
||||
|
||||
if (effect->type < FF_EFFECT_MIN || effect->type > FF_EFFECT_MAX ||
|
||||
!test_bit(effect->type, dev->ffbit)) {
|
||||
debug("invalid or not supported effect type in upload");
|
||||
pr_debug("invalid or not supported effect type in upload\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ int input_ff_upload(struct input_dev *dev, struct ff_effect *effect,
|
||||
(effect->u.periodic.waveform < FF_WAVEFORM_MIN ||
|
||||
effect->u.periodic.waveform > FF_WAVEFORM_MAX ||
|
||||
!test_bit(effect->u.periodic.waveform, dev->ffbit))) {
|
||||
debug("invalid or not supported wave form in upload");
|
||||
pr_debug("invalid or not supported wave form in upload\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -246,7 +246,7 @@ static int flush_effects(struct input_dev *dev, struct file *file)
|
||||
struct ff_device *ff = dev->ff;
|
||||
int i;
|
||||
|
||||
debug("flushing now");
|
||||
pr_debug("flushing now\n");
|
||||
|
||||
mutex_lock(&ff->mutex);
|
||||
|
||||
@@ -315,8 +315,7 @@ int input_ff_create(struct input_dev *dev, int max_effects)
|
||||
int i;
|
||||
|
||||
if (!max_effects) {
|
||||
printk(KERN_ERR
|
||||
"ff-core: cannot allocate device without any effects\n");
|
||||
pr_err("cannot allocate device without any effects\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
||||
+15
-16
@@ -23,7 +23,7 @@
|
||||
|
||||
/* #define DEBUG */
|
||||
|
||||
#define debug(format, arg...) pr_debug("ff-memless: " format "\n", ## arg)
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/input.h>
|
||||
@@ -129,7 +129,7 @@ static void ml_schedule_timer(struct ml_device *ml)
|
||||
int events = 0;
|
||||
int i;
|
||||
|
||||
debug("calculating next timer");
|
||||
pr_debug("calculating next timer\n");
|
||||
|
||||
for (i = 0; i < FF_MEMLESS_EFFECTS; i++) {
|
||||
|
||||
@@ -149,10 +149,10 @@ static void ml_schedule_timer(struct ml_device *ml)
|
||||
}
|
||||
|
||||
if (!events) {
|
||||
debug("no actions");
|
||||
pr_debug("no actions\n");
|
||||
del_timer(&ml->timer);
|
||||
} else {
|
||||
debug("timer set");
|
||||
pr_debug("timer set\n");
|
||||
mod_timer(&ml->timer, earliest);
|
||||
}
|
||||
}
|
||||
@@ -173,8 +173,8 @@ static int apply_envelope(struct ml_effect_state *state, int value,
|
||||
if (envelope->attack_length &&
|
||||
time_before(now,
|
||||
state->play_at + msecs_to_jiffies(envelope->attack_length))) {
|
||||
debug("value = 0x%x, attack_level = 0x%x", value,
|
||||
envelope->attack_level);
|
||||
pr_debug("value = 0x%x, attack_level = 0x%x\n",
|
||||
value, envelope->attack_level);
|
||||
time_from_level = jiffies_to_msecs(now - state->play_at);
|
||||
time_of_envelope = envelope->attack_length;
|
||||
envelope_level = min_t(__s16, envelope->attack_level, 0x7fff);
|
||||
@@ -191,13 +191,13 @@ static int apply_envelope(struct ml_effect_state *state, int value,
|
||||
|
||||
difference = abs(value) - envelope_level;
|
||||
|
||||
debug("difference = %d", difference);
|
||||
debug("time_from_level = 0x%x", time_from_level);
|
||||
debug("time_of_envelope = 0x%x", time_of_envelope);
|
||||
pr_debug("difference = %d\n", difference);
|
||||
pr_debug("time_from_level = 0x%x\n", time_from_level);
|
||||
pr_debug("time_of_envelope = 0x%x\n", time_of_envelope);
|
||||
|
||||
difference = difference * time_from_level / time_of_envelope;
|
||||
|
||||
debug("difference = %d", difference);
|
||||
pr_debug("difference = %d\n", difference);
|
||||
|
||||
return value < 0 ?
|
||||
-(difference + envelope_level) : (difference + envelope_level);
|
||||
@@ -215,8 +215,7 @@ static int get_compatible_type(struct ff_device *ff, int effect_type)
|
||||
if (effect_type == FF_PERIODIC && test_bit(FF_RUMBLE, ff->ffbit))
|
||||
return FF_RUMBLE;
|
||||
|
||||
printk(KERN_ERR
|
||||
"ff-memless: invalid type in get_compatible_type()\n");
|
||||
pr_err("invalid type in get_compatible_type()\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -312,7 +311,7 @@ static void ml_combine_effects(struct ff_effect *effect,
|
||||
break;
|
||||
|
||||
default:
|
||||
printk(KERN_ERR "ff-memless: invalid type in ml_combine_effects()\n");
|
||||
pr_err("invalid type in ml_combine_effects()\n");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -406,7 +405,7 @@ static void ml_effect_timer(unsigned long timer_data)
|
||||
struct ml_device *ml = dev->ff->private;
|
||||
unsigned long flags;
|
||||
|
||||
debug("timer: updating effects");
|
||||
pr_debug("timer: updating effects\n");
|
||||
|
||||
spin_lock_irqsave(&dev->event_lock, flags);
|
||||
ml_play_effects(ml);
|
||||
@@ -438,7 +437,7 @@ static int ml_ff_playback(struct input_dev *dev, int effect_id, int value)
|
||||
struct ml_effect_state *state = &ml->states[effect_id];
|
||||
|
||||
if (value > 0) {
|
||||
debug("initiated play");
|
||||
pr_debug("initiated play\n");
|
||||
|
||||
__set_bit(FF_EFFECT_STARTED, &state->flags);
|
||||
state->count = value;
|
||||
@@ -449,7 +448,7 @@ static int ml_ff_playback(struct input_dev *dev, int effect_id, int value)
|
||||
state->adj_at = state->play_at;
|
||||
|
||||
} else {
|
||||
debug("initiated stop");
|
||||
pr_debug("initiated stop\n");
|
||||
|
||||
if (test_bit(FF_EFFECT_PLAYING, &state->flags))
|
||||
__set_bit(FF_EFFECT_ABORTING, &state->flags);
|
||||
|
||||
@@ -18,13 +18,11 @@
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/gameport.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/sched.h> /* HZ */
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/freezer.h>
|
||||
|
||||
/*#include <asm/io.h>*/
|
||||
|
||||
@@ -234,58 +232,22 @@ struct gameport_event {
|
||||
|
||||
static DEFINE_SPINLOCK(gameport_event_lock); /* protects gameport_event_list */
|
||||
static LIST_HEAD(gameport_event_list);
|
||||
static DECLARE_WAIT_QUEUE_HEAD(gameport_wait);
|
||||
static struct task_struct *gameport_task;
|
||||
|
||||
static int gameport_queue_event(void *object, struct module *owner,
|
||||
enum gameport_event_type event_type)
|
||||
static struct gameport_event *gameport_get_event(void)
|
||||
{
|
||||
struct gameport_event *event = NULL;
|
||||
unsigned long flags;
|
||||
struct gameport_event *event;
|
||||
int retval = 0;
|
||||
|
||||
spin_lock_irqsave(&gameport_event_lock, flags);
|
||||
|
||||
/*
|
||||
* Scan event list for the other events for the same gameport port,
|
||||
* starting with the most recent one. If event is the same we
|
||||
* do not need add new one. If event is of different type we
|
||||
* need to add this event and should not look further because
|
||||
* we need to preseve sequence of distinct events.
|
||||
*/
|
||||
list_for_each_entry_reverse(event, &gameport_event_list, node) {
|
||||
if (event->object == object) {
|
||||
if (event->type == event_type)
|
||||
goto out;
|
||||
break;
|
||||
}
|
||||
if (!list_empty(&gameport_event_list)) {
|
||||
event = list_first_entry(&gameport_event_list,
|
||||
struct gameport_event, node);
|
||||
list_del_init(&event->node);
|
||||
}
|
||||
|
||||
event = kmalloc(sizeof(struct gameport_event), GFP_ATOMIC);
|
||||
if (!event) {
|
||||
pr_err("Not enough memory to queue event %d\n", event_type);
|
||||
retval = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!try_module_get(owner)) {
|
||||
pr_warning("Can't get module reference, dropping event %d\n",
|
||||
event_type);
|
||||
kfree(event);
|
||||
retval = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
event->type = event_type;
|
||||
event->object = object;
|
||||
event->owner = owner;
|
||||
|
||||
list_add_tail(&event->node, &gameport_event_list);
|
||||
wake_up(&gameport_wait);
|
||||
|
||||
out:
|
||||
spin_unlock_irqrestore(&gameport_event_lock, flags);
|
||||
return retval;
|
||||
return event;
|
||||
}
|
||||
|
||||
static void gameport_free_event(struct gameport_event *event)
|
||||
@@ -319,24 +281,8 @@ static void gameport_remove_duplicate_events(struct gameport_event *event)
|
||||
spin_unlock_irqrestore(&gameport_event_lock, flags);
|
||||
}
|
||||
|
||||
static struct gameport_event *gameport_get_event(void)
|
||||
{
|
||||
struct gameport_event *event = NULL;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&gameport_event_lock, flags);
|
||||
|
||||
if (!list_empty(&gameport_event_list)) {
|
||||
event = list_first_entry(&gameport_event_list,
|
||||
struct gameport_event, node);
|
||||
list_del_init(&event->node);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&gameport_event_lock, flags);
|
||||
return event;
|
||||
}
|
||||
|
||||
static void gameport_handle_event(void)
|
||||
static void gameport_handle_events(struct work_struct *work)
|
||||
{
|
||||
struct gameport_event *event;
|
||||
|
||||
@@ -368,6 +314,59 @@ static void gameport_handle_event(void)
|
||||
mutex_unlock(&gameport_mutex);
|
||||
}
|
||||
|
||||
static DECLARE_WORK(gameport_event_work, gameport_handle_events);
|
||||
|
||||
static int gameport_queue_event(void *object, struct module *owner,
|
||||
enum gameport_event_type event_type)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct gameport_event *event;
|
||||
int retval = 0;
|
||||
|
||||
spin_lock_irqsave(&gameport_event_lock, flags);
|
||||
|
||||
/*
|
||||
* Scan event list for the other events for the same gameport port,
|
||||
* starting with the most recent one. If event is the same we
|
||||
* do not need add new one. If event is of different type we
|
||||
* need to add this event and should not look further because
|
||||
* we need to preserve sequence of distinct events.
|
||||
*/
|
||||
list_for_each_entry_reverse(event, &gameport_event_list, node) {
|
||||
if (event->object == object) {
|
||||
if (event->type == event_type)
|
||||
goto out;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
event = kmalloc(sizeof(struct gameport_event), GFP_ATOMIC);
|
||||
if (!event) {
|
||||
pr_err("Not enough memory to queue event %d\n", event_type);
|
||||
retval = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!try_module_get(owner)) {
|
||||
pr_warning("Can't get module reference, dropping event %d\n",
|
||||
event_type);
|
||||
kfree(event);
|
||||
retval = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
event->type = event_type;
|
||||
event->object = object;
|
||||
event->owner = owner;
|
||||
|
||||
list_add_tail(&event->node, &gameport_event_list);
|
||||
schedule_work(&gameport_event_work);
|
||||
|
||||
out:
|
||||
spin_unlock_irqrestore(&gameport_event_lock, flags);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove all events that have been submitted for a given object,
|
||||
* be it a gameport port or a driver.
|
||||
@@ -419,19 +418,6 @@ static struct gameport *gameport_get_pending_child(struct gameport *parent)
|
||||
return child;
|
||||
}
|
||||
|
||||
static int gameport_thread(void *nothing)
|
||||
{
|
||||
set_freezable();
|
||||
do {
|
||||
gameport_handle_event();
|
||||
wait_event_freezable(gameport_wait,
|
||||
kthread_should_stop() || !list_empty(&gameport_event_list));
|
||||
} while (!kthread_should_stop());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Gameport port operations
|
||||
*/
|
||||
@@ -814,13 +800,6 @@ static int __init gameport_init(void)
|
||||
return error;
|
||||
}
|
||||
|
||||
gameport_task = kthread_run(gameport_thread, NULL, "kgameportd");
|
||||
if (IS_ERR(gameport_task)) {
|
||||
bus_unregister(&gameport_bus);
|
||||
error = PTR_ERR(gameport_task);
|
||||
pr_err("Failed to start kgameportd, error: %d\n", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -828,7 +807,12 @@ static int __init gameport_init(void)
|
||||
static void __exit gameport_exit(void)
|
||||
{
|
||||
bus_unregister(&gameport_bus);
|
||||
kthread_stop(gameport_task);
|
||||
|
||||
/*
|
||||
* There should not be any outstanding events but work may
|
||||
* still be scheduled so simply cancel it.
|
||||
*/
|
||||
cancel_work_sync(&gameport_event_work);
|
||||
}
|
||||
|
||||
subsys_initcall(gameport_init);
|
||||
|
||||
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* Input Multitouch Library
|
||||
*
|
||||
* Copyright (c) 2008-2010 Henrik Rydberg
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/input/mt.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#define TRKID_SGN ((TRKID_MAX + 1) >> 1)
|
||||
|
||||
/**
|
||||
* input_mt_init_slots() - initialize MT input slots
|
||||
* @dev: input device supporting MT events and finger tracking
|
||||
* @num_slots: number of slots used by the device
|
||||
*
|
||||
* This function allocates all necessary memory for MT slot handling
|
||||
* in the input device, prepares the ABS_MT_SLOT and
|
||||
* ABS_MT_TRACKING_ID events for use and sets up appropriate buffers.
|
||||
* May be called repeatedly. Returns -EINVAL if attempting to
|
||||
* reinitialize with a different number of slots.
|
||||
*/
|
||||
int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!num_slots)
|
||||
return 0;
|
||||
if (dev->mt)
|
||||
return dev->mtsize != num_slots ? -EINVAL : 0;
|
||||
|
||||
dev->mt = kcalloc(num_slots, sizeof(struct input_mt_slot), GFP_KERNEL);
|
||||
if (!dev->mt)
|
||||
return -ENOMEM;
|
||||
|
||||
dev->mtsize = num_slots;
|
||||
input_set_abs_params(dev, ABS_MT_SLOT, 0, num_slots - 1, 0, 0);
|
||||
input_set_abs_params(dev, ABS_MT_TRACKING_ID, 0, TRKID_MAX, 0, 0);
|
||||
input_set_events_per_packet(dev, 6 * num_slots);
|
||||
|
||||
/* Mark slots as 'unused' */
|
||||
for (i = 0; i < num_slots; i++)
|
||||
input_mt_set_value(&dev->mt[i], ABS_MT_TRACKING_ID, -1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(input_mt_init_slots);
|
||||
|
||||
/**
|
||||
* input_mt_destroy_slots() - frees the MT slots of the input device
|
||||
* @dev: input device with allocated MT slots
|
||||
*
|
||||
* This function is only needed in error path as the input core will
|
||||
* automatically free the MT slots when the device is destroyed.
|
||||
*/
|
||||
void input_mt_destroy_slots(struct input_dev *dev)
|
||||
{
|
||||
kfree(dev->mt);
|
||||
dev->mt = NULL;
|
||||
dev->mtsize = 0;
|
||||
dev->slot = 0;
|
||||
dev->trkid = 0;
|
||||
}
|
||||
EXPORT_SYMBOL(input_mt_destroy_slots);
|
||||
|
||||
/**
|
||||
* input_mt_report_slot_state() - report contact state
|
||||
* @dev: input device with allocated MT slots
|
||||
* @tool_type: the tool type to use in this slot
|
||||
* @active: true if contact is active, false otherwise
|
||||
*
|
||||
* Reports a contact via ABS_MT_TRACKING_ID, and optionally
|
||||
* ABS_MT_TOOL_TYPE. If active is true and the slot is currently
|
||||
* inactive, or if the tool type is changed, a new tracking id is
|
||||
* assigned to the slot. The tool type is only reported if the
|
||||
* corresponding absbit field is set.
|
||||
*/
|
||||
void input_mt_report_slot_state(struct input_dev *dev,
|
||||
unsigned int tool_type, bool active)
|
||||
{
|
||||
struct input_mt_slot *mt;
|
||||
int id;
|
||||
|
||||
if (!dev->mt || !active) {
|
||||
input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
|
||||
return;
|
||||
}
|
||||
|
||||
mt = &dev->mt[dev->slot];
|
||||
id = input_mt_get_value(mt, ABS_MT_TRACKING_ID);
|
||||
if (id < 0 || input_mt_get_value(mt, ABS_MT_TOOL_TYPE) != tool_type)
|
||||
id = input_mt_new_trkid(dev);
|
||||
|
||||
input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, id);
|
||||
input_event(dev, EV_ABS, ABS_MT_TOOL_TYPE, tool_type);
|
||||
}
|
||||
EXPORT_SYMBOL(input_mt_report_slot_state);
|
||||
|
||||
/**
|
||||
* input_mt_report_finger_count() - report contact count
|
||||
* @dev: input device with allocated MT slots
|
||||
* @count: the number of contacts
|
||||
*
|
||||
* Reports the contact count via BTN_TOOL_FINGER, BTN_TOOL_DOUBLETAP,
|
||||
* BTN_TOOL_TRIPLETAP and BTN_TOOL_QUADTAP.
|
||||
*
|
||||
* The input core ensures only the KEY events already setup for
|
||||
* this device will produce output.
|
||||
*/
|
||||
void input_mt_report_finger_count(struct input_dev *dev, int count)
|
||||
{
|
||||
input_event(dev, EV_KEY, BTN_TOOL_FINGER, count == 1);
|
||||
input_event(dev, EV_KEY, BTN_TOOL_DOUBLETAP, count == 2);
|
||||
input_event(dev, EV_KEY, BTN_TOOL_TRIPLETAP, count == 3);
|
||||
input_event(dev, EV_KEY, BTN_TOOL_QUADTAP, count == 4);
|
||||
}
|
||||
EXPORT_SYMBOL(input_mt_report_finger_count);
|
||||
|
||||
/**
|
||||
* input_mt_report_pointer_emulation() - common pointer emulation
|
||||
* @dev: input device with allocated MT slots
|
||||
* @use_count: report number of active contacts as finger count
|
||||
*
|
||||
* Performs legacy pointer emulation via BTN_TOUCH, ABS_X, ABS_Y and
|
||||
* ABS_PRESSURE. Touchpad finger count is emulated if use_count is true.
|
||||
*
|
||||
* The input core ensures only the KEY and ABS axes already setup for
|
||||
* this device will produce output.
|
||||
*/
|
||||
void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_count)
|
||||
{
|
||||
struct input_mt_slot *oldest = 0;
|
||||
int oldid = dev->trkid;
|
||||
int count = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < dev->mtsize; ++i) {
|
||||
struct input_mt_slot *ps = &dev->mt[i];
|
||||
int id = input_mt_get_value(ps, ABS_MT_TRACKING_ID);
|
||||
|
||||
if (id < 0)
|
||||
continue;
|
||||
if ((id - oldid) & TRKID_SGN) {
|
||||
oldest = ps;
|
||||
oldid = id;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
input_event(dev, EV_KEY, BTN_TOUCH, count > 0);
|
||||
if (use_count)
|
||||
input_mt_report_finger_count(dev, count);
|
||||
|
||||
if (oldest) {
|
||||
int x = input_mt_get_value(oldest, ABS_MT_POSITION_X);
|
||||
int y = input_mt_get_value(oldest, ABS_MT_POSITION_Y);
|
||||
int p = input_mt_get_value(oldest, ABS_MT_PRESSURE);
|
||||
|
||||
input_event(dev, EV_ABS, ABS_X, x);
|
||||
input_event(dev, EV_ABS, ABS_Y, y);
|
||||
input_event(dev, EV_ABS, ABS_PRESSURE, p);
|
||||
} else {
|
||||
input_event(dev, EV_ABS, ABS_PRESSURE, 0);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(input_mt_report_pointer_emulation);
|
||||
@@ -8,6 +8,8 @@
|
||||
* the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mutex.h>
|
||||
@@ -33,8 +35,7 @@ static int input_polldev_start_workqueue(void)
|
||||
if (!polldev_users) {
|
||||
polldev_wq = create_singlethread_workqueue("ipolldevd");
|
||||
if (!polldev_wq) {
|
||||
printk(KERN_ERR "input-polldev: failed to create "
|
||||
"ipolldevd workqueue\n");
|
||||
pr_err("failed to create ipolldevd workqueue\n");
|
||||
retval = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
+32
-59
@@ -10,9 +10,11 @@
|
||||
* the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_BASENAME ": " fmt
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/input/mt.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/random.h>
|
||||
@@ -958,10 +960,8 @@ static int input_attach_handler(struct input_dev *dev, struct input_handler *han
|
||||
|
||||
error = handler->connect(handler, dev, id);
|
||||
if (error && error != -ENODEV)
|
||||
printk(KERN_ERR
|
||||
"input: failed to attach handler %s to device %s, "
|
||||
"error: %d\n",
|
||||
handler->name, kobject_name(&dev->dev.kobj), error);
|
||||
pr_err("failed to attach handler %s to device %s, error: %d\n",
|
||||
handler->name, kobject_name(&dev->dev.kobj), error);
|
||||
|
||||
return error;
|
||||
}
|
||||
@@ -1109,6 +1109,8 @@ static int input_devices_seq_show(struct seq_file *seq, void *v)
|
||||
seq_printf(seq, "%s ", handle->name);
|
||||
seq_putc(seq, '\n');
|
||||
|
||||
input_seq_print_bitmap(seq, "PROP", dev->propbit, INPUT_PROP_MAX);
|
||||
|
||||
input_seq_print_bitmap(seq, "EV", dev->evbit, EV_MAX);
|
||||
if (test_bit(EV_KEY, dev->evbit))
|
||||
input_seq_print_bitmap(seq, "KEY", dev->keybit, KEY_MAX);
|
||||
@@ -1332,11 +1334,26 @@ static ssize_t input_dev_show_modalias(struct device *dev,
|
||||
}
|
||||
static DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL);
|
||||
|
||||
static int input_print_bitmap(char *buf, int buf_size, unsigned long *bitmap,
|
||||
int max, int add_cr);
|
||||
|
||||
static ssize_t input_dev_show_properties(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct input_dev *input_dev = to_input_dev(dev);
|
||||
int len = input_print_bitmap(buf, PAGE_SIZE, input_dev->propbit,
|
||||
INPUT_PROP_MAX, true);
|
||||
return min_t(int, len, PAGE_SIZE);
|
||||
}
|
||||
static DEVICE_ATTR(properties, S_IRUGO, input_dev_show_properties, NULL);
|
||||
|
||||
static struct attribute *input_dev_attrs[] = {
|
||||
&dev_attr_name.attr,
|
||||
&dev_attr_phys.attr,
|
||||
&dev_attr_uniq.attr,
|
||||
&dev_attr_modalias.attr,
|
||||
&dev_attr_properties.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -1470,7 +1487,7 @@ static int input_add_uevent_bm_var(struct kobj_uevent_env *env,
|
||||
{
|
||||
int len;
|
||||
|
||||
if (add_uevent_var(env, "%s=", name))
|
||||
if (add_uevent_var(env, "%s", name))
|
||||
return -ENOMEM;
|
||||
|
||||
len = input_print_bitmap(&env->buf[env->buflen - 1],
|
||||
@@ -1536,6 +1553,8 @@ static int input_dev_uevent(struct device *device, struct kobj_uevent_env *env)
|
||||
if (dev->uniq)
|
||||
INPUT_ADD_HOTPLUG_VAR("UNIQ=\"%s\"", dev->uniq);
|
||||
|
||||
INPUT_ADD_HOTPLUG_BM_VAR("PROP=", dev->propbit, INPUT_PROP_MAX);
|
||||
|
||||
INPUT_ADD_HOTPLUG_BM_VAR("EV=", dev->evbit, EV_MAX);
|
||||
if (test_bit(EV_KEY, dev->evbit))
|
||||
INPUT_ADD_HOTPLUG_BM_VAR("KEY=", dev->keybit, KEY_MAX);
|
||||
@@ -1724,52 +1743,6 @@ void input_free_device(struct input_dev *dev)
|
||||
}
|
||||
EXPORT_SYMBOL(input_free_device);
|
||||
|
||||
/**
|
||||
* input_mt_create_slots() - create MT input slots
|
||||
* @dev: input device supporting MT events and finger tracking
|
||||
* @num_slots: number of slots used by the device
|
||||
*
|
||||
* This function allocates all necessary memory for MT slot handling in the
|
||||
* input device, and adds ABS_MT_SLOT to the device capabilities. All slots
|
||||
* are initially marked as unused by setting ABS_MT_TRACKING_ID to -1.
|
||||
*/
|
||||
int input_mt_create_slots(struct input_dev *dev, unsigned int num_slots)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!num_slots)
|
||||
return 0;
|
||||
|
||||
dev->mt = kcalloc(num_slots, sizeof(struct input_mt_slot), GFP_KERNEL);
|
||||
if (!dev->mt)
|
||||
return -ENOMEM;
|
||||
|
||||
dev->mtsize = num_slots;
|
||||
input_set_abs_params(dev, ABS_MT_SLOT, 0, num_slots - 1, 0, 0);
|
||||
|
||||
/* Mark slots as 'unused' */
|
||||
for (i = 0; i < num_slots; i++)
|
||||
dev->mt[i].abs[ABS_MT_TRACKING_ID - ABS_MT_FIRST] = -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(input_mt_create_slots);
|
||||
|
||||
/**
|
||||
* input_mt_destroy_slots() - frees the MT slots of the input device
|
||||
* @dev: input device with allocated MT slots
|
||||
*
|
||||
* This function is only needed in error path as the input core will
|
||||
* automatically free the MT slots when the device is destroyed.
|
||||
*/
|
||||
void input_mt_destroy_slots(struct input_dev *dev)
|
||||
{
|
||||
kfree(dev->mt);
|
||||
dev->mt = NULL;
|
||||
dev->mtsize = 0;
|
||||
}
|
||||
EXPORT_SYMBOL(input_mt_destroy_slots);
|
||||
|
||||
/**
|
||||
* input_set_capability - mark device as capable of a certain event
|
||||
* @dev: device that is capable of emitting or accepting event
|
||||
@@ -1819,9 +1792,8 @@ void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int
|
||||
break;
|
||||
|
||||
default:
|
||||
printk(KERN_ERR
|
||||
"input_set_capability: unknown type %u (code %u)\n",
|
||||
type, code);
|
||||
pr_err("input_set_capability: unknown type %u (code %u)\n",
|
||||
type, code);
|
||||
dump_stack();
|
||||
return;
|
||||
}
|
||||
@@ -1903,8 +1875,9 @@ int input_register_device(struct input_dev *dev)
|
||||
return error;
|
||||
|
||||
path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);
|
||||
printk(KERN_INFO "input: %s as %s\n",
|
||||
dev->name ? dev->name : "Unspecified device", path ? path : "N/A");
|
||||
pr_info("%s as %s\n",
|
||||
dev->name ? dev->name : "Unspecified device",
|
||||
path ? path : "N/A");
|
||||
kfree(path);
|
||||
|
||||
error = mutex_lock_interruptible(&input_mutex);
|
||||
@@ -2186,7 +2159,7 @@ static int __init input_init(void)
|
||||
|
||||
err = class_register(&input_class);
|
||||
if (err) {
|
||||
printk(KERN_ERR "input: unable to register input_dev class\n");
|
||||
pr_err("unable to register input_dev class\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -2196,7 +2169,7 @@ static int __init input_init(void)
|
||||
|
||||
err = register_chrdev(INPUT_MAJOR, "input", &input_fops);
|
||||
if (err) {
|
||||
printk(KERN_ERR "input: unable to register char major %d", INPUT_MAJOR);
|
||||
pr_err("unable to register char major %d", INPUT_MAJOR);
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user