Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rydberg/input-mt into next
Conflicts: drivers/input/Makefile
This commit is contained in:
commit
67b989a0c1
|
@ -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
|
||||
|
|
|
@ -161,7 +161,8 @@ 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
|
||||
|
@ -213,6 +214,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
|
||||
|
|
|
@ -3020,8 +3020,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
|
||||
|
|
|
@ -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,8 @@ 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_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) },
|
||||
|
|
|
@ -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,10 @@ 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) },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(hid, egalax_devices);
|
||||
|
|
|
@ -196,6 +196,8 @@
|
|||
#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_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-y := 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
|
||||
|
|
|
@ -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);
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
#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>
|
||||
|
@ -1725,52 +1725,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
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include <linux/fs.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/uinput.h>
|
||||
#include <linux/input/mt.h>
|
||||
#include "../input-compat.h"
|
||||
|
||||
static int uinput_dev_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
|
||||
|
@ -406,8 +407,7 @@ static int uinput_setup_device(struct uinput_device *udev, const char __user *bu
|
|||
goto exit;
|
||||
if (test_bit(ABS_MT_SLOT, dev->absbit)) {
|
||||
int nslot = input_abs_get_max(dev, ABS_MT_SLOT) + 1;
|
||||
input_mt_create_slots(dev, nslot);
|
||||
input_set_events_per_packet(dev, 6 * nslot);
|
||||
input_mt_init_slots(dev, nslot);
|
||||
} else if (test_bit(ABS_MT_POSITION_X, dev->absbit)) {
|
||||
input_set_events_per_packet(dev, 60);
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#include "wacom_wac.h"
|
||||
#include "wacom.h"
|
||||
#include <linux/input/mt.h>
|
||||
|
||||
static int wacom_penpartner_irq(struct wacom_wac *wacom)
|
||||
{
|
||||
|
@ -862,19 +863,21 @@ static int wacom_bpt_touch(struct wacom_wac *wacom)
|
|||
struct wacom_features *features = &wacom->features;
|
||||
struct input_dev *input = wacom->input;
|
||||
unsigned char *data = wacom->data;
|
||||
int sp = 0, sx = 0, sy = 0, count = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
int p = data[9 * i + 2];
|
||||
bool touch = p && !wacom->shared->stylus_in_proximity;
|
||||
|
||||
input_mt_slot(input, i);
|
||||
input_mt_report_slot_state(input, MT_TOOL_FINGER, touch);
|
||||
/*
|
||||
* Touch events need to be disabled while stylus is
|
||||
* in proximity because user's hand is resting on touchpad
|
||||
* and sending unwanted events. User expects tablet buttons
|
||||
* to continue working though.
|
||||
*/
|
||||
if (p && !wacom->shared->stylus_in_proximity) {
|
||||
if (touch) {
|
||||
int x = get_unaligned_be16(&data[9 * i + 3]) & 0x7ff;
|
||||
int y = get_unaligned_be16(&data[9 * i + 5]) & 0x7ff;
|
||||
if (features->quirks & WACOM_QUIRK_BBTOUCH_LOWRES) {
|
||||
|
@ -884,23 +887,10 @@ static int wacom_bpt_touch(struct wacom_wac *wacom)
|
|||
input_report_abs(input, ABS_MT_PRESSURE, p);
|
||||
input_report_abs(input, ABS_MT_POSITION_X, x);
|
||||
input_report_abs(input, ABS_MT_POSITION_Y, y);
|
||||
if (wacom->id[i] < 0)
|
||||
wacom->id[i] = wacom->trk_id++ & MAX_TRACKING_ID;
|
||||
if (!count++)
|
||||
sp = p, sx = x, sy = y;
|
||||
} else {
|
||||
wacom->id[i] = -1;
|
||||
}
|
||||
input_report_abs(input, ABS_MT_TRACKING_ID, wacom->id[i]);
|
||||
}
|
||||
|
||||
input_report_key(input, BTN_TOUCH, count > 0);
|
||||
input_report_key(input, BTN_TOOL_FINGER, count == 1);
|
||||
input_report_key(input, BTN_TOOL_DOUBLETAP, count == 2);
|
||||
|
||||
input_report_abs(input, ABS_PRESSURE, sp);
|
||||
input_report_abs(input, ABS_X, sx);
|
||||
input_report_abs(input, ABS_Y, sy);
|
||||
input_mt_report_pointer_emulation(input, true);
|
||||
|
||||
input_report_key(input, BTN_LEFT, (data[1] & 0x08) != 0);
|
||||
input_report_key(input, BTN_FORWARD, (data[1] & 0x04) != 0);
|
||||
|
@ -1272,7 +1262,7 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
|
|||
__set_bit(BTN_TOOL_FINGER, input_dev->keybit);
|
||||
__set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit);
|
||||
|
||||
input_mt_create_slots(input_dev, 2);
|
||||
input_mt_init_slots(input_dev, 2);
|
||||
input_set_abs_params(input_dev, ABS_MT_POSITION_X,
|
||||
0, features->x_max,
|
||||
features->x_fuzz, 0);
|
||||
|
@ -1282,8 +1272,6 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
|
|||
input_set_abs_params(input_dev, ABS_MT_PRESSURE,
|
||||
0, features->pressure_max,
|
||||
features->pressure_fuzz, 0);
|
||||
input_set_abs_params(input_dev, ABS_MT_TRACKING_ID, 0,
|
||||
MAX_TRACKING_ID, 0, 0);
|
||||
} else if (features->device_type == BTN_TOOL_PEN) {
|
||||
__set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
|
||||
__set_bit(BTN_TOOL_PEN, input_dev->keybit);
|
||||
|
|
|
@ -42,9 +42,6 @@
|
|||
#define WACOM_QUIRK_MULTI_INPUT 0x0001
|
||||
#define WACOM_QUIRK_BBTOUCH_LOWRES 0x0002
|
||||
|
||||
/* largest reported tracking id */
|
||||
#define MAX_TRACKING_ID 0xfff
|
||||
|
||||
enum {
|
||||
PENPARTNER = 0,
|
||||
GRAPHIRE,
|
||||
|
@ -100,7 +97,6 @@ struct wacom_wac {
|
|||
int id[3];
|
||||
__u32 serial[2];
|
||||
int last_finger;
|
||||
int trk_id;
|
||||
struct wacom_features features;
|
||||
struct wacom_shared *shared;
|
||||
struct input_dev *input;
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/input/mt.h>
|
||||
#include <linux/serio.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/ctype.h>
|
||||
|
@ -48,8 +48,6 @@ MODULE_LICENSE("GPL");
|
|||
#define W8001_PKTLEN_TPCCTL 11 /* control packet */
|
||||
#define W8001_PKTLEN_TOUCH2FG 13
|
||||
|
||||
#define MAX_TRACKING_ID 0xFF /* arbitrarily chosen */
|
||||
|
||||
struct w8001_coord {
|
||||
u8 rdy;
|
||||
u8 tsw;
|
||||
|
@ -87,7 +85,6 @@ struct w8001 {
|
|||
char phys[32];
|
||||
int type;
|
||||
unsigned int pktlen;
|
||||
int trkid[2];
|
||||
};
|
||||
|
||||
static void parse_data(u8 *data, struct w8001_coord *coord)
|
||||
|
@ -116,28 +113,23 @@ static void parse_data(u8 *data, struct w8001_coord *coord)
|
|||
|
||||
static void parse_touch(struct w8001 *w8001)
|
||||
{
|
||||
static int trkid;
|
||||
struct input_dev *dev = w8001->dev;
|
||||
unsigned char *data = w8001->data;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
input_mt_slot(dev, i);
|
||||
bool touch = data[0] & (1 << i);
|
||||
|
||||
if (data[0] & (1 << i)) {
|
||||
input_mt_slot(dev, i);
|
||||
input_mt_report_slot_state(dev, MT_TOOL_FINGER, touch);
|
||||
if (touch) {
|
||||
int x = (data[6 * i + 1] << 7) | (data[6 * i + 2]);
|
||||
int y = (data[6 * i + 3] << 7) | (data[6 * i + 4]);
|
||||
/* data[5,6] and [11,12] is finger capacity */
|
||||
|
||||
input_report_abs(dev, ABS_MT_POSITION_X, x);
|
||||
input_report_abs(dev, ABS_MT_POSITION_Y, y);
|
||||
input_report_abs(dev, ABS_MT_TOOL_TYPE, MT_TOOL_FINGER);
|
||||
if (w8001->trkid[i] < 0)
|
||||
w8001->trkid[i] = trkid++ & MAX_TRACKING_ID;
|
||||
} else {
|
||||
w8001->trkid[i] = -1;
|
||||
}
|
||||
input_report_abs(dev, ABS_MT_TRACKING_ID, w8001->trkid[i]);
|
||||
}
|
||||
|
||||
input_sync(dev);
|
||||
|
@ -318,15 +310,13 @@ static int w8001_setup(struct w8001 *w8001)
|
|||
case 5:
|
||||
w8001->pktlen = W8001_PKTLEN_TOUCH2FG;
|
||||
|
||||
input_mt_create_slots(dev, 2);
|
||||
input_set_abs_params(dev, ABS_MT_TRACKING_ID,
|
||||
0, MAX_TRACKING_ID, 0, 0);
|
||||
input_mt_init_slots(dev, 2);
|
||||
input_set_abs_params(dev, ABS_MT_POSITION_X,
|
||||
0, touch.x, 0, 0);
|
||||
input_set_abs_params(dev, ABS_MT_POSITION_Y,
|
||||
0, touch.y, 0, 0);
|
||||
input_set_abs_params(dev, ABS_MT_TOOL_TYPE,
|
||||
0, 0, 0, 0);
|
||||
0, MT_TOOL_MAX, 0, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -372,7 +362,6 @@ static int w8001_connect(struct serio *serio, struct serio_driver *drv)
|
|||
w8001->serio = serio;
|
||||
w8001->id = serio->id.id;
|
||||
w8001->dev = input_dev;
|
||||
w8001->trkid[0] = w8001->trkid[1] = -1;
|
||||
init_completion(&w8001->cmd_done);
|
||||
snprintf(w8001->phys, sizeof(w8001->phys), "%s/input0", serio->phys);
|
||||
|
||||
|
|
|
@ -733,11 +733,12 @@ struct input_keymap_entry {
|
|||
#define ABS_MT_BLOB_ID 0x38 /* Group a set of packets as a blob */
|
||||
#define ABS_MT_TRACKING_ID 0x39 /* Unique ID of initiated contact */
|
||||
#define ABS_MT_PRESSURE 0x3a /* Pressure on contact area */
|
||||
#define ABS_MT_DISTANCE 0x3b /* Contact hover distance */
|
||||
|
||||
#ifdef __KERNEL__
|
||||
/* Implementation details, userspace should not care about these */
|
||||
#define ABS_MT_FIRST ABS_MT_TOUCH_MAJOR
|
||||
#define ABS_MT_LAST ABS_MT_PRESSURE
|
||||
#define ABS_MT_LAST ABS_MT_DISTANCE
|
||||
#endif
|
||||
|
||||
#define ABS_MAX 0x3f
|
||||
|
@ -848,6 +849,7 @@ struct input_keymap_entry {
|
|||
*/
|
||||
#define MT_TOOL_FINGER 0
|
||||
#define MT_TOOL_PEN 1
|
||||
#define MT_TOOL_MAX 1
|
||||
|
||||
/*
|
||||
* Values describing the status of a force-feedback effect
|
||||
|
@ -1082,14 +1084,6 @@ struct ff_effect {
|
|||
#include <linux/timer.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
|
||||
/**
|
||||
* struct input_mt_slot - represents the state of an input MT slot
|
||||
* @abs: holds current values of ABS_MT axes for this slot
|
||||
*/
|
||||
struct input_mt_slot {
|
||||
int abs[ABS_MT_LAST - ABS_MT_FIRST + 1];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct input_dev - represents an input device
|
||||
* @name: name of the device
|
||||
|
@ -1130,6 +1124,7 @@ struct input_mt_slot {
|
|||
* of tracked contacts
|
||||
* @mtsize: number of MT slots the device uses
|
||||
* @slot: MT slot currently being transmitted
|
||||
* @trkid: stores MT tracking ID for the current contact
|
||||
* @absinfo: array of &struct absinfo elements holding information
|
||||
* about absolute axes (current value, min, max, flat, fuzz,
|
||||
* resolution)
|
||||
|
@ -1214,6 +1209,7 @@ struct input_dev {
|
|||
struct input_mt_slot *mt;
|
||||
int mtsize;
|
||||
int slot;
|
||||
int trkid;
|
||||
|
||||
struct input_absinfo *absinfo;
|
||||
|
||||
|
@ -1463,11 +1459,6 @@ static inline void input_mt_sync(struct input_dev *dev)
|
|||
input_event(dev, EV_SYN, SYN_MT_REPORT, 0);
|
||||
}
|
||||
|
||||
static inline void input_mt_slot(struct input_dev *dev, int slot)
|
||||
{
|
||||
input_event(dev, EV_ABS, ABS_MT_SLOT, slot);
|
||||
}
|
||||
|
||||
void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int code);
|
||||
|
||||
/**
|
||||
|
@ -1580,8 +1571,5 @@ int input_ff_erase(struct input_dev *dev, int effect_id, struct file *file);
|
|||
int input_ff_create_memless(struct input_dev *dev, void *data,
|
||||
int (*play_effect)(struct input_dev *, void *, struct ff_effect *));
|
||||
|
||||
int input_mt_create_slots(struct input_dev *dev, unsigned int num_slots);
|
||||
void input_mt_destroy_slots(struct input_dev *dev);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
#ifndef _INPUT_MT_H
|
||||
#define _INPUT_MT_H
|
||||
|
||||
/*
|
||||
* Input Multitouch Library
|
||||
*
|
||||
* Copyright (c) 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.h>
|
||||
|
||||
#define TRKID_MAX 0xffff
|
||||
|
||||
/**
|
||||
* struct input_mt_slot - represents the state of an input MT slot
|
||||
* @abs: holds current values of ABS_MT axes for this slot
|
||||
*/
|
||||
struct input_mt_slot {
|
||||
int abs[ABS_MT_LAST - ABS_MT_FIRST + 1];
|
||||
};
|
||||
|
||||
static inline void input_mt_set_value(struct input_mt_slot *slot,
|
||||
unsigned code, int value)
|
||||
{
|
||||
slot->abs[code - ABS_MT_FIRST] = value;
|
||||
}
|
||||
|
||||
static inline int input_mt_get_value(const struct input_mt_slot *slot,
|
||||
unsigned code)
|
||||
{
|
||||
return slot->abs[code - ABS_MT_FIRST];
|
||||
}
|
||||
|
||||
int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots);
|
||||
void input_mt_destroy_slots(struct input_dev *dev);
|
||||
|
||||
static inline int input_mt_new_trkid(struct input_dev *dev)
|
||||
{
|
||||
return dev->trkid++ & TRKID_MAX;
|
||||
}
|
||||
|
||||
static inline void input_mt_slot(struct input_dev *dev, int slot)
|
||||
{
|
||||
input_event(dev, EV_ABS, ABS_MT_SLOT, slot);
|
||||
}
|
||||
|
||||
void input_mt_report_slot_state(struct input_dev *dev,
|
||||
unsigned int tool_type, bool active);
|
||||
|
||||
void input_mt_report_finger_count(struct input_dev *dev, int count);
|
||||
void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_count);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue