Merge branch 'next' into for-linus

Prepare second set of updates for 3.7 merge window (Wacom driver update
and patches extending number of input minors).
This commit is contained in:
Dmitry Torokhov
2012-10-11 00:45:21 -07:00
29 changed files with 1272 additions and 854 deletions
+3
View File
@@ -283,6 +283,9 @@
#define USB_VENDOR_ID_EMS 0x2006
#define USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II 0x0118
#define USB_VENDOR_ID_FLATFROG 0x25b5
#define USB_DEVICE_ID_MULTITOUCH_3200 0x0002
#define USB_VENDOR_ID_ESSENTIAL_REALITY 0x0d7f
#define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100
+9 -2
View File
@@ -1154,6 +1154,7 @@ static void report_features(struct hid_device *hid)
int hidinput_connect(struct hid_device *hid, unsigned int force)
{
struct hid_driver *drv = hid->driver;
struct hid_report *report;
struct hid_input *hidinput = NULL;
struct input_dev *input_dev;
@@ -1228,6 +1229,8 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
* UGCI) cram a lot of unrelated inputs into the
* same interface. */
hidinput->report = report;
if (drv->input_configured)
drv->input_configured(hid, hidinput);
if (input_register_device(hidinput->input))
goto out_cleanup;
hidinput = NULL;
@@ -1235,8 +1238,12 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
}
}
if (hidinput && input_register_device(hidinput->input))
goto out_cleanup;
if (hidinput) {
if (drv->input_configured)
drv->input_configured(hid, hidinput);
if (input_register_device(hidinput->input))
goto out_cleanup;
}
return 0;
+1 -1
View File
@@ -392,7 +392,7 @@ static int magicmouse_setup_input(struct input_dev *input, struct hid_device *hd
__set_bit(EV_ABS, input->evbit);
error = input_mt_init_slots(input, 16);
error = input_mt_init_slots(input, 16, 0);
if (error)
return error;
input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, 255 << 2,
+85 -100
View File
@@ -51,12 +51,12 @@ MODULE_LICENSE("GPL");
#define MT_QUIRK_VALID_IS_INRANGE (1 << 5)
#define MT_QUIRK_VALID_IS_CONFIDENCE (1 << 6)
#define MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE (1 << 8)
#define MT_QUIRK_NO_AREA (1 << 9)
struct mt_slot {
__s32 x, y, p, w, h;
__s32 contactid; /* the device ContactID assigned to this slot */
bool touch_state; /* is the touch valid? */
bool seen_in_this_frame;/* has this slot been updated */
};
struct mt_class {
@@ -92,8 +92,9 @@ struct mt_device {
__u8 touches_by_report; /* how many touches are present in one report:
* 1 means we should use a serial protocol
* > 1 means hybrid (multitouch) protocol */
bool serial_maybe; /* need to check for serial protocol */
bool curvalid; /* is the current contact valid? */
struct mt_slot *slots;
unsigned mt_flags; /* flags to pass to input-mt */
};
/* classes of device behavior */
@@ -115,6 +116,7 @@ struct mt_device {
#define MT_CLS_EGALAX_SERIAL 0x0104
#define MT_CLS_TOPSEED 0x0105
#define MT_CLS_PANASONIC 0x0106
#define MT_CLS_FLATFROG 0x0107
#define MT_DEFAULT_MAXCONTACT 10
@@ -134,25 +136,6 @@ static int cypress_compute_slot(struct mt_device *td)
return -1;
}
static int find_slot_from_contactid(struct mt_device *td)
{
int i;
for (i = 0; i < td->maxcontacts; ++i) {
if (td->slots[i].contactid == td->curdata.contactid &&
td->slots[i].touch_state)
return i;
}
for (i = 0; i < td->maxcontacts; ++i) {
if (!td->slots[i].seen_in_this_frame &&
!td->slots[i].touch_state)
return i;
}
/* should not occurs. If this happens that means
* that the device sent more touches that it says
* in the report descriptor. It is ignored then. */
return -1;
}
static struct mt_class mt_classes[] = {
{ .name = MT_CLS_DEFAULT,
.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP },
@@ -190,7 +173,9 @@ static struct mt_class mt_classes[] = {
MT_QUIRK_SLOT_IS_CONTACTID,
.sn_move = 2048,
.sn_width = 128,
.sn_height = 128 },
.sn_height = 128,
.maxcontacts = 60,
},
{ .name = MT_CLS_CYPRESS,
.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP |
MT_QUIRK_CYPRESS,
@@ -216,6 +201,12 @@ static struct mt_class mt_classes[] = {
.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP,
.maxcontacts = 4 },
{ .name = MT_CLS_FLATFROG,
.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP |
MT_QUIRK_NO_AREA,
.sn_move = 2048,
.maxcontacts = 40,
},
{ }
};
@@ -319,24 +310,16 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
* We need to ignore fields that belong to other collections
* such as Mouse that might have the same GenericDesktop usages. */
if (field->application == HID_DG_TOUCHSCREEN)
set_bit(INPUT_PROP_DIRECT, hi->input->propbit);
td->mt_flags |= INPUT_MT_DIRECT;
else if (field->application != HID_DG_TOUCHPAD)
return 0;
/* In case of an indirect device (touchpad), we need to add
* specific BTN_TOOL_* to be handled by the synaptics xorg
* driver.
* We also consider that touchscreens providing buttons are touchpads.
/*
* Model touchscreens providing buttons as touchpads.
*/
if (field->application == HID_DG_TOUCHPAD ||
(usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON ||
cls->is_indirect) {
set_bit(INPUT_PROP_POINTER, hi->input->propbit);
set_bit(BTN_TOOL_FINGER, hi->input->keybit);
set_bit(BTN_TOOL_DOUBLETAP, hi->input->keybit);
set_bit(BTN_TOOL_TRIPLETAP, hi->input->keybit);
set_bit(BTN_TOOL_QUADTAP, hi->input->keybit);
}
(usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON)
td->mt_flags |= INPUT_MT_POINTER;
/* eGalax devices provide a Digitizer.Stylus input which overrides
* the correct Digitizers.Finger X/Y ranges.
@@ -353,8 +336,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
EV_ABS, ABS_MT_POSITION_X);
set_abs(hi->input, ABS_MT_POSITION_X, field,
cls->sn_move);
/* touchscreen emulation */
set_abs(hi->input, ABS_X, field, cls->sn_move);
mt_store_field(usage, td, hi);
td->last_field_index = field->index;
return 1;
@@ -363,8 +344,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
EV_ABS, ABS_MT_POSITION_Y);
set_abs(hi->input, ABS_MT_POSITION_Y, field,
cls->sn_move);
/* touchscreen emulation */
set_abs(hi->input, ABS_Y, field, cls->sn_move);
mt_store_field(usage, td, hi);
td->last_field_index = field->index;
return 1;
@@ -388,9 +367,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
td->last_field_index = field->index;
return 1;
case HID_DG_CONTACTID:
if (!td->maxcontacts)
td->maxcontacts = MT_DEFAULT_MAXCONTACT;
input_mt_init_slots(hi->input, td->maxcontacts);
mt_store_field(usage, td, hi);
td->last_field_index = field->index;
td->touches_by_report++;
@@ -398,18 +374,21 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
case HID_DG_WIDTH:
hid_map_usage(hi, usage, bit, max,
EV_ABS, ABS_MT_TOUCH_MAJOR);
set_abs(hi->input, ABS_MT_TOUCH_MAJOR, field,
cls->sn_width);
if (!(cls->quirks & MT_QUIRK_NO_AREA))
set_abs(hi->input, ABS_MT_TOUCH_MAJOR, field,
cls->sn_width);
mt_store_field(usage, td, hi);
td->last_field_index = field->index;
return 1;
case HID_DG_HEIGHT:
hid_map_usage(hi, usage, bit, max,
EV_ABS, ABS_MT_TOUCH_MINOR);
set_abs(hi->input, ABS_MT_TOUCH_MINOR, field,
cls->sn_height);
input_set_abs_params(hi->input,
if (!(cls->quirks & MT_QUIRK_NO_AREA)) {
set_abs(hi->input, ABS_MT_TOUCH_MINOR, field,
cls->sn_height);
input_set_abs_params(hi->input,
ABS_MT_ORIENTATION, 0, 1, 0, 0);
}
mt_store_field(usage, td, hi);
td->last_field_index = field->index;
return 1;
@@ -418,9 +397,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
EV_ABS, ABS_MT_PRESSURE);
set_abs(hi->input, ABS_MT_PRESSURE, field,
cls->sn_pressure);
/* touchscreen emulation */
set_abs(hi->input, ABS_PRESSURE, field,
cls->sn_pressure);
mt_store_field(usage, td, hi);
td->last_field_index = field->index;
return 1;
@@ -464,7 +440,7 @@ static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi,
return -1;
}
static int mt_compute_slot(struct mt_device *td)
static int mt_compute_slot(struct mt_device *td, struct input_dev *input)
{
__s32 quirks = td->mtclass.quirks;
@@ -480,42 +456,23 @@ static int mt_compute_slot(struct mt_device *td)
if (quirks & MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE)
return td->curdata.contactid - 1;
return find_slot_from_contactid(td);
return input_mt_get_slot_by_key(input, td->curdata.contactid);
}
/*
* this function is called when a whole contact has been processed,
* so that it can assign it to a slot and store the data there
*/
static void mt_complete_slot(struct mt_device *td)
static void mt_complete_slot(struct mt_device *td, struct input_dev *input)
{
td->curdata.seen_in_this_frame = true;
if (td->curvalid) {
int slotnum = mt_compute_slot(td);
int slotnum = mt_compute_slot(td, input);
struct mt_slot *s = &td->curdata;
if (slotnum >= 0 && slotnum < td->maxcontacts)
td->slots[slotnum] = td->curdata;
}
td->num_received++;
}
if (slotnum < 0 || slotnum >= td->maxcontacts)
return;
/*
* this function is called when a whole packet has been received and processed,
* so that it can decide what to send to the input layer.
*/
static void mt_emit_event(struct mt_device *td, struct input_dev *input)
{
int i;
for (i = 0; i < td->maxcontacts; ++i) {
struct mt_slot *s = &(td->slots[i]);
if ((td->mtclass.quirks & MT_QUIRK_NOT_SEEN_MEANS_UP) &&
!s->seen_in_this_frame) {
s->touch_state = false;
}
input_mt_slot(input, i);
input_mt_slot(input, slotnum);
input_mt_report_slot_state(input, MT_TOOL_FINGER,
s->touch_state);
if (s->touch_state) {
@@ -532,24 +489,29 @@ static void mt_emit_event(struct mt_device *td, struct input_dev *input)
input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major);
input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, minor);
}
s->seen_in_this_frame = false;
}
input_mt_report_pointer_emulation(input, true);
td->num_received++;
}
/*
* this function is called when a whole packet has been received and processed,
* so that it can decide what to send to the input layer.
*/
static void mt_sync_frame(struct mt_device *td, struct input_dev *input)
{
input_mt_sync_frame(input);
input_sync(input);
td->num_received = 0;
}
static int mt_event(struct hid_device *hid, struct hid_field *field,
struct hid_usage *usage, __s32 value)
{
struct mt_device *td = hid_get_drvdata(hid);
__s32 quirks = td->mtclass.quirks;
if (hid->claimed & HID_CLAIMED_INPUT && td->slots) {
if (hid->claimed & HID_CLAIMED_INPUT) {
switch (usage->hid) {
case HID_DG_INRANGE:
if (quirks & MT_QUIRK_ALWAYS_VALID)
@@ -602,11 +564,11 @@ static int mt_event(struct hid_device *hid, struct hid_field *field,
}
if (usage->hid == td->last_slot_field)
mt_complete_slot(td);
mt_complete_slot(td, field->hidinput->input);
if (field->index == td->last_field_index
&& td->num_received >= td->num_expected)
mt_emit_event(td, field->hidinput->input);
mt_sync_frame(td, field->hidinput->input);
}
@@ -685,6 +647,35 @@ static void mt_post_parse(struct mt_device *td)
}
}
static void mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
{
struct mt_device *td = hid_get_drvdata(hdev);
struct mt_class *cls = &td->mtclass;
struct input_dev *input = hi->input;
/* Only initialize slots for MT input devices */
if (!test_bit(ABS_MT_POSITION_X, input->absbit))
return;
if (!td->maxcontacts)
td->maxcontacts = MT_DEFAULT_MAXCONTACT;
mt_post_parse(td);
if (td->serial_maybe)
mt_post_parse_default_settings(td);
if (cls->is_indirect)
td->mt_flags |= INPUT_MT_POINTER;
if (cls->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP)
td->mt_flags |= INPUT_MT_DROP_UNUSED;
input_mt_init_slots(input, td->maxcontacts, td->mt_flags);
td->mt_flags = 0;
}
static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
{
int ret, i;
@@ -722,6 +713,9 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
goto fail;
}
if (id->vendor == HID_ANY_ID && id->product == HID_ANY_ID)
td->serial_maybe = true;
ret = hid_parse(hdev);
if (ret != 0)
goto fail;
@@ -730,20 +724,6 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
if (ret)
goto fail;
mt_post_parse(td);
if (id->vendor == HID_ANY_ID && id->product == HID_ANY_ID)
mt_post_parse_default_settings(td);
td->slots = kzalloc(td->maxcontacts * sizeof(struct mt_slot),
GFP_KERNEL);
if (!td->slots) {
dev_err(&hdev->dev, "cannot allocate multitouch slots\n");
hid_hw_stop(hdev);
ret = -ENOMEM;
goto fail;
}
ret = sysfs_create_group(&hdev->dev.kobj, &mt_attribute_group);
mt_set_maxcontacts(hdev);
@@ -774,7 +754,6 @@ static void mt_remove(struct hid_device *hdev)
struct mt_device *td = hid_get_drvdata(hdev);
sysfs_remove_group(&hdev->dev.kobj, &mt_attribute_group);
hid_hw_stop(hdev);
kfree(td->slots);
kfree(td);
hid_set_drvdata(hdev, NULL);
}
@@ -892,6 +871,11 @@ static const struct hid_device_id mt_devices[] = {
MT_USB_DEVICE(USB_VENDOR_ID_ELO,
USB_DEVICE_ID_ELO_TS2515) },
/* Flatfrog Panels */
{ .driver_data = MT_CLS_FLATFROG,
MT_USB_DEVICE(USB_VENDOR_ID_FLATFROG,
USB_DEVICE_ID_MULTITOUCH_3200) },
/* GeneralTouch panel */
{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
@@ -1087,6 +1071,7 @@ static struct hid_driver mt_driver = {
.remove = mt_remove,
.input_mapping = mt_input_mapping,
.input_mapped = mt_input_mapped,
.input_configured = mt_input_configured,
.feature_mapping = mt_feature_mapping,
.usage_table = mt_grabbed_usages,
.event = mt_event,
+99 -104
View File
@@ -23,11 +23,11 @@
#include <linux/input/mt.h>
#include <linux/major.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include "input-compat.h"
struct evdev {
int open;
int minor;
struct input_handle handle;
wait_queue_head_t wait;
struct evdev_client __rcu *grab;
@@ -35,6 +35,7 @@ struct evdev {
spinlock_t client_lock; /* protects client_list */
struct mutex mutex;
struct device dev;
struct cdev cdev;
bool exist;
};
@@ -51,19 +52,9 @@ struct evdev_client {
struct input_event buffer[];
};
static struct evdev *evdev_table[EVDEV_MINORS];
static DEFINE_MUTEX(evdev_table_mutex);
static void evdev_pass_event(struct evdev_client *client,
struct input_event *event,
ktime_t mono, ktime_t real)
static void __pass_event(struct evdev_client *client,
const struct input_event *event)
{
event->time = ktime_to_timeval(client->clkid == CLOCK_MONOTONIC ?
mono : real);
/* Interrupts are disabled, just acquire the lock. */
spin_lock(&client->buffer_lock);
client->buffer[client->head++] = *event;
client->head &= client->bufsize - 1;
@@ -86,8 +77,63 @@ static void evdev_pass_event(struct evdev_client *client,
client->packet_head = client->head;
kill_fasync(&client->fasync, SIGIO, POLL_IN);
}
}
static void evdev_pass_values(struct evdev_client *client,
const struct input_value *vals, unsigned int count,
ktime_t mono, ktime_t real)
{
struct evdev *evdev = client->evdev;
const struct input_value *v;
struct input_event event;
bool wakeup = false;
event.time = ktime_to_timeval(client->clkid == CLOCK_MONOTONIC ?
mono : real);
/* Interrupts are disabled, just acquire the lock. */
spin_lock(&client->buffer_lock);
for (v = vals; v != vals + count; v++) {
event.type = v->type;
event.code = v->code;
event.value = v->value;
__pass_event(client, &event);
if (v->type == EV_SYN && v->code == SYN_REPORT)
wakeup = true;
}
spin_unlock(&client->buffer_lock);
if (wakeup)
wake_up_interruptible(&evdev->wait);
}
/*
* Pass incoming events to all connected clients.
*/
static void evdev_events(struct input_handle *handle,
const struct input_value *vals, unsigned int count)
{
struct evdev *evdev = handle->private;
struct evdev_client *client;
ktime_t time_mono, time_real;
time_mono = ktime_get();
time_real = ktime_sub(time_mono, ktime_get_monotonic_offset());
rcu_read_lock();
client = rcu_dereference(evdev->grab);
if (client)
evdev_pass_values(client, vals, count, time_mono, time_real);
else
list_for_each_entry_rcu(client, &evdev->client_list, node)
evdev_pass_values(client, vals, count,
time_mono, time_real);
rcu_read_unlock();
}
/*
@@ -96,32 +142,9 @@ static void evdev_pass_event(struct evdev_client *client,
static void evdev_event(struct input_handle *handle,
unsigned int type, unsigned int code, int value)
{
struct evdev *evdev = handle->private;
struct evdev_client *client;
struct input_event event;
ktime_t time_mono, time_real;
struct input_value vals[] = { { type, code, value } };
time_mono = ktime_get();
time_real = ktime_sub(time_mono, ktime_get_monotonic_offset());
event.type = type;
event.code = code;
event.value = value;
rcu_read_lock();
client = rcu_dereference(evdev->grab);
if (client)
evdev_pass_event(client, &event, time_mono, time_real);
else
list_for_each_entry_rcu(client, &evdev->client_list, node)
evdev_pass_event(client, &event, time_mono, time_real);
rcu_read_unlock();
if (type == EV_SYN && code == SYN_REPORT)
wake_up_interruptible(&evdev->wait);
evdev_events(handle, vals, 1);
}
static int evdev_fasync(int fd, struct file *file, int on)
@@ -285,35 +308,16 @@ static unsigned int evdev_compute_buffer_size(struct input_dev *dev)
static int evdev_open(struct inode *inode, struct file *file)
{
struct evdev *evdev;
struct evdev *evdev = container_of(inode->i_cdev, struct evdev, cdev);
unsigned int bufsize = evdev_compute_buffer_size(evdev->handle.dev);
struct evdev_client *client;
int i = iminor(inode) - EVDEV_MINOR_BASE;
unsigned int bufsize;
int error;
if (i >= EVDEV_MINORS)
return -ENODEV;
error = mutex_lock_interruptible(&evdev_table_mutex);
if (error)
return error;
evdev = evdev_table[i];
if (evdev)
get_device(&evdev->dev);
mutex_unlock(&evdev_table_mutex);
if (!evdev)
return -ENODEV;
bufsize = evdev_compute_buffer_size(evdev->handle.dev);
client = kzalloc(sizeof(struct evdev_client) +
bufsize * sizeof(struct input_event),
GFP_KERNEL);
if (!client) {
error = -ENOMEM;
goto err_put_evdev;
}
if (!client)
return -ENOMEM;
client->bufsize = bufsize;
spin_lock_init(&client->buffer_lock);
@@ -327,13 +331,12 @@ static int evdev_open(struct inode *inode, struct file *file)
file->private_data = client;
nonseekable_open(inode, file);
get_device(&evdev->dev);
return 0;
err_free_client:
evdev_detach_client(evdev, client);
kfree(client);
err_put_evdev:
put_device(&evdev->dev);
return error;
}
@@ -653,20 +656,22 @@ static int evdev_handle_mt_request(struct input_dev *dev,
unsigned int size,
int __user *ip)
{
const struct input_mt_slot *mt = dev->mt;
const struct input_mt *mt = dev->mt;
unsigned int code;
int max_slots;
int i;
if (get_user(code, &ip[0]))
return -EFAULT;
if (!input_is_mt_value(code))
if (!mt || !input_is_mt_value(code))
return -EINVAL;
max_slots = (size - sizeof(__u32)) / sizeof(__s32);
for (i = 0; i < dev->mtsize && i < max_slots; i++)
if (put_user(input_mt_get_value(&mt[i], code), &ip[1 + i]))
for (i = 0; i < mt->num_slots && i < max_slots; i++) {
int value = input_mt_get_value(&mt->slots[i], code);
if (put_user(value, &ip[1 + i]))
return -EFAULT;
}
return 0;
}
@@ -915,26 +920,6 @@ static const struct file_operations evdev_fops = {
.llseek = no_llseek,
};
static int evdev_install_chrdev(struct evdev *evdev)
{
/*
* No need to do any locking here as calls to connect and
* disconnect are serialized by the input core
*/
evdev_table[evdev->minor] = evdev;
return 0;
}
static void evdev_remove_chrdev(struct evdev *evdev)
{
/*
* Lock evdev table to prevent race with evdev_open()
*/
mutex_lock(&evdev_table_mutex);
evdev_table[evdev->minor] = NULL;
mutex_unlock(&evdev_table_mutex);
}
/*
* Mark device non-existent. This disables writes, ioctls and
* prevents new users from opening the device. Already posted
@@ -953,7 +938,8 @@ static void evdev_cleanup(struct evdev *evdev)
evdev_mark_dead(evdev);
evdev_hangup(evdev);
evdev_remove_chrdev(evdev);
cdev_del(&evdev->cdev);
/* evdev is marked dead so no one else accesses evdev->open */
if (evdev->open) {
@@ -964,43 +950,47 @@ static void evdev_cleanup(struct evdev *evdev)
/*
* Create new evdev device. Note that input core serializes calls
* to connect and disconnect so we don't need to lock evdev_table here.
* to connect and disconnect.
*/
static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
const struct input_device_id *id)
{
struct evdev *evdev;
int minor;
int dev_no;
int error;
for (minor = 0; minor < EVDEV_MINORS; minor++)
if (!evdev_table[minor])
break;
if (minor == EVDEV_MINORS) {
pr_err("no more free evdev devices\n");
return -ENFILE;
minor = input_get_new_minor(EVDEV_MINOR_BASE, EVDEV_MINORS, true);
if (minor < 0) {
error = minor;
pr_err("failed to reserve new minor: %d\n", error);
return error;
}
evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL);
if (!evdev)
return -ENOMEM;
if (!evdev) {
error = -ENOMEM;
goto err_free_minor;
}
INIT_LIST_HEAD(&evdev->client_list);
spin_lock_init(&evdev->client_lock);
mutex_init(&evdev->mutex);
init_waitqueue_head(&evdev->wait);
dev_set_name(&evdev->dev, "event%d", minor);
evdev->exist = true;
evdev->minor = minor;
dev_no = minor;
/* Normalize device number if it falls into legacy range */
if (dev_no < EVDEV_MINOR_BASE + EVDEV_MINORS)
dev_no -= EVDEV_MINOR_BASE;
dev_set_name(&evdev->dev, "event%d", dev_no);
evdev->handle.dev = input_get_device(dev);
evdev->handle.name = dev_name(&evdev->dev);
evdev->handle.handler = handler;
evdev->handle.private = evdev;
evdev->dev.devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor);
evdev->dev.devt = MKDEV(INPUT_MAJOR, minor);
evdev->dev.class = &input_class;
evdev->dev.parent = &dev->dev;
evdev->dev.release = evdev_free;
@@ -1010,7 +1000,8 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
if (error)
goto err_free_evdev;
error = evdev_install_chrdev(evdev);
cdev_init(&evdev->cdev, &evdev_fops);
error = cdev_add(&evdev->cdev, evdev->dev.devt, 1);
if (error)
goto err_unregister_handle;
@@ -1026,6 +1017,8 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
input_unregister_handle(&evdev->handle);
err_free_evdev:
put_device(&evdev->dev);
err_free_minor:
input_free_minor(minor);
return error;
}
@@ -1035,6 +1028,7 @@ static void evdev_disconnect(struct input_handle *handle)
device_del(&evdev->dev);
evdev_cleanup(evdev);
input_free_minor(MINOR(evdev->dev.devt));
input_unregister_handle(handle);
put_device(&evdev->dev);
}
@@ -1048,9 +1042,10 @@ MODULE_DEVICE_TABLE(input, evdev_ids);
static struct input_handler evdev_handler = {
.event = evdev_event,
.events = evdev_events,
.connect = evdev_connect,
.disconnect = evdev_disconnect,
.fops = &evdev_fops,
.legacy_minors = true,
.minor = EVDEV_MINOR_BASE,
.name = "evdev",
.id_table = evdev_ids,
+277 -28
View File
@@ -14,6 +14,14 @@
#define TRKID_SGN ((TRKID_MAX + 1) >> 1)
static void copy_abs(struct input_dev *dev, unsigned int dst, unsigned int src)
{
if (dev->absinfo && test_bit(src, dev->absbit)) {
dev->absinfo[dst] = dev->absinfo[src];
dev->absbit[BIT_WORD(dst)] |= BIT_MASK(dst);
}
}
/**
* input_mt_init_slots() - initialize MT input slots
* @dev: input device supporting MT events and finger tracking
@@ -25,29 +33,63 @@
* 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 input_mt_init_slots(struct input_dev *dev, unsigned int num_slots,
unsigned int flags)
{
struct input_mt *mt = dev->mt;
int i;
if (!num_slots)
return 0;
if (dev->mt)
return dev->mtsize != num_slots ? -EINVAL : 0;
if (mt)
return mt->num_slots != num_slots ? -EINVAL : 0;
dev->mt = kcalloc(num_slots, sizeof(struct input_mt_slot), GFP_KERNEL);
if (!dev->mt)
return -ENOMEM;
mt = kzalloc(sizeof(*mt) + num_slots * sizeof(*mt->slots), GFP_KERNEL);
if (!mt)
goto err_mem;
dev->mtsize = num_slots;
mt->num_slots = num_slots;
mt->flags = flags;
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);
if (flags & (INPUT_MT_POINTER | INPUT_MT_DIRECT)) {
__set_bit(EV_KEY, dev->evbit);
__set_bit(BTN_TOUCH, dev->keybit);
copy_abs(dev, ABS_X, ABS_MT_POSITION_X);
copy_abs(dev, ABS_Y, ABS_MT_POSITION_Y);
copy_abs(dev, ABS_PRESSURE, ABS_MT_PRESSURE);
}
if (flags & INPUT_MT_POINTER) {
__set_bit(BTN_TOOL_FINGER, dev->keybit);
__set_bit(BTN_TOOL_DOUBLETAP, dev->keybit);
if (num_slots >= 3)
__set_bit(BTN_TOOL_TRIPLETAP, dev->keybit);
if (num_slots >= 4)
__set_bit(BTN_TOOL_QUADTAP, dev->keybit);
if (num_slots >= 5)
__set_bit(BTN_TOOL_QUINTTAP, dev->keybit);
__set_bit(INPUT_PROP_POINTER, dev->propbit);
}
if (flags & INPUT_MT_DIRECT)
__set_bit(INPUT_PROP_DIRECT, dev->propbit);
if (flags & INPUT_MT_TRACK) {
unsigned int n2 = num_slots * num_slots;
mt->red = kcalloc(n2, sizeof(*mt->red), GFP_KERNEL);
if (!mt->red)
goto err_mem;
}
/* Mark slots as 'unused' */
for (i = 0; i < num_slots; i++)
input_mt_set_value(&dev->mt[i], ABS_MT_TRACKING_ID, -1);
input_mt_set_value(&mt->slots[i], ABS_MT_TRACKING_ID, -1);
dev->mt = mt;
return 0;
err_mem:
kfree(mt);
return -ENOMEM;
}
EXPORT_SYMBOL(input_mt_init_slots);
@@ -60,11 +102,11 @@ EXPORT_SYMBOL(input_mt_init_slots);
*/
void input_mt_destroy_slots(struct input_dev *dev)
{
kfree(dev->mt);
if (dev->mt) {
kfree(dev->mt->red);
kfree(dev->mt);
}
dev->mt = NULL;
dev->mtsize = 0;
dev->slot = 0;
dev->trkid = 0;
}
EXPORT_SYMBOL(input_mt_destroy_slots);
@@ -83,18 +125,24 @@ EXPORT_SYMBOL(input_mt_destroy_slots);
void input_mt_report_slot_state(struct input_dev *dev,
unsigned int tool_type, bool active)
{
struct input_mt_slot *mt;
struct input_mt *mt = dev->mt;
struct input_mt_slot *slot;
int id;
if (!dev->mt || !active) {
if (!mt)
return;
slot = &mt->slots[mt->slot];
slot->frame = mt->frame;
if (!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);
id = input_mt_get_value(slot, ABS_MT_TRACKING_ID);
if (id < 0 || input_mt_get_value(slot, ABS_MT_TOOL_TYPE) != tool_type)
id = input_mt_new_trkid(mt);
input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, id);
input_event(dev, EV_ABS, ABS_MT_TOOL_TYPE, tool_type);
@@ -135,13 +183,19 @@ EXPORT_SYMBOL(input_mt_report_finger_count);
*/
void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_count)
{
struct input_mt_slot *oldest = NULL;
int oldid = dev->trkid;
int count = 0;
int i;
struct input_mt *mt = dev->mt;
struct input_mt_slot *oldest;
int oldid, count, i;
for (i = 0; i < dev->mtsize; ++i) {
struct input_mt_slot *ps = &dev->mt[i];
if (!mt)
return;
oldest = 0;
oldid = mt->trkid;
count = 0;
for (i = 0; i < mt->num_slots; ++i) {
struct input_mt_slot *ps = &mt->slots[i];
int id = input_mt_get_value(ps, ABS_MT_TRACKING_ID);
if (id < 0)
@@ -160,13 +214,208 @@ void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_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);
if (test_bit(ABS_MT_PRESSURE, dev->absbit)) {
int p = input_mt_get_value(oldest, ABS_MT_PRESSURE);
input_event(dev, EV_ABS, ABS_PRESSURE, p);
}
} else {
input_event(dev, EV_ABS, ABS_PRESSURE, 0);
if (test_bit(ABS_MT_PRESSURE, dev->absbit))
input_event(dev, EV_ABS, ABS_PRESSURE, 0);
}
}
EXPORT_SYMBOL(input_mt_report_pointer_emulation);
/**
* input_mt_sync_frame() - synchronize mt frame
* @dev: input device with allocated MT slots
*
* Close the frame and prepare the internal state for a new one.
* Depending on the flags, marks unused slots as inactive and performs
* pointer emulation.
*/
void input_mt_sync_frame(struct input_dev *dev)
{
struct input_mt *mt = dev->mt;
struct input_mt_slot *s;
if (!mt)
return;
if (mt->flags & INPUT_MT_DROP_UNUSED) {
for (s = mt->slots; s != mt->slots + mt->num_slots; s++) {
if (s->frame == mt->frame)
continue;
input_mt_slot(dev, s - mt->slots);
input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
}
}
input_mt_report_pointer_emulation(dev, (mt->flags & INPUT_MT_POINTER));
mt->frame++;
}
EXPORT_SYMBOL(input_mt_sync_frame);
static int adjust_dual(int *begin, int step, int *end, int eq)
{
int f, *p, s, c;
if (begin == end)
return 0;
f = *begin;
p = begin + step;
s = p == end ? f + 1 : *p;
for (; p != end; p += step)
if (*p < f)
s = f, f = *p;
else if (*p < s)
s = *p;
c = (f + s + 1) / 2;
if (c == 0 || (c > 0 && !eq))
return 0;
if (s < 0)
c *= 2;
for (p = begin; p != end; p += step)
*p -= c;
return (c < s && s <= 0) || (f >= 0 && f < c);
}
static void find_reduced_matrix(int *w, int nr, int nc, int nrc)
{
int i, k, sum;
for (k = 0; k < nrc; k++) {
for (i = 0; i < nr; i++)
adjust_dual(w + i, nr, w + i + nrc, nr <= nc);
sum = 0;
for (i = 0; i < nrc; i += nr)
sum += adjust_dual(w + i, 1, w + i + nr, nc <= nr);
if (!sum)
break;
}
}
static int input_mt_set_matrix(struct input_mt *mt,
const struct input_mt_pos *pos, int num_pos)
{
const struct input_mt_pos *p;
struct input_mt_slot *s;
int *w = mt->red;
int x, y;
for (s = mt->slots; s != mt->slots + mt->num_slots; s++) {
if (!input_mt_is_active(s))
continue;
x = input_mt_get_value(s, ABS_MT_POSITION_X);
y = input_mt_get_value(s, ABS_MT_POSITION_Y);
for (p = pos; p != pos + num_pos; p++) {
int dx = x - p->x, dy = y - p->y;
*w++ = dx * dx + dy * dy;
}
}
return w - mt->red;
}
static void input_mt_set_slots(struct input_mt *mt,
int *slots, int num_pos)
{
struct input_mt_slot *s;
int *w = mt->red, *p;
for (p = slots; p != slots + num_pos; p++)
*p = -1;
for (s = mt->slots; s != mt->slots + mt->num_slots; s++) {
if (!input_mt_is_active(s))
continue;
for (p = slots; p != slots + num_pos; p++)
if (*w++ < 0)
*p = s - mt->slots;
}
for (s = mt->slots; s != mt->slots + mt->num_slots; s++) {
if (input_mt_is_active(s))
continue;
for (p = slots; p != slots + num_pos; p++)
if (*p < 0) {
*p = s - mt->slots;
break;
}
}
}
/**
* input_mt_assign_slots() - perform a best-match assignment
* @dev: input device with allocated MT slots
* @slots: the slot assignment to be filled
* @pos: the position array to match
* @num_pos: number of positions
*
* Performs a best match against the current contacts and returns
* the slot assignment list. New contacts are assigned to unused
* slots.
*
* Returns zero on success, or negative error in case of failure.
*/
int input_mt_assign_slots(struct input_dev *dev, int *slots,
const struct input_mt_pos *pos, int num_pos)
{
struct input_mt *mt = dev->mt;
int nrc;
if (!mt || !mt->red)
return -ENXIO;
if (num_pos > mt->num_slots)
return -EINVAL;
if (num_pos < 1)
return 0;
nrc = input_mt_set_matrix(mt, pos, num_pos);
find_reduced_matrix(mt->red, num_pos, nrc / num_pos, nrc);
input_mt_set_slots(mt, slots, num_pos);
return 0;
}
EXPORT_SYMBOL(input_mt_assign_slots);
/**
* input_mt_get_slot_by_key() - return slot matching key
* @dev: input device with allocated MT slots
* @key: the key of the sought slot
*
* Returns the slot of the given key, if it exists, otherwise
* set the key on the first unused slot and return.
*
* If no available slot can be found, -1 is returned.
*/
int input_mt_get_slot_by_key(struct input_dev *dev, int key)
{
struct input_mt *mt = dev->mt;
struct input_mt_slot *s;
if (!mt)
return -1;
for (s = mt->slots; s != mt->slots + mt->num_slots; s++)
if (input_mt_is_active(s) && s->key == key)
return s - mt->slots;
for (s = mt->slots; s != mt->slots + mt->num_slots; s++)
if (!input_mt_is_active(s)) {
s->key = key;
return s - mt->slots;
}
return -1;
}
EXPORT_SYMBOL(input_mt_get_slot_by_key);
+248 -172
View File
File diff suppressed because it is too large Load Diff
+32 -56
View File
@@ -27,6 +27,7 @@
#include <linux/poll.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/cdev.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Joystick device interfaces");
@@ -39,13 +40,13 @@ MODULE_LICENSE("GPL");
struct joydev {
int open;
int minor;
struct input_handle handle;
wait_queue_head_t wait;
struct list_head client_list;
spinlock_t client_lock; /* protects client_list */
struct mutex mutex;
struct device dev;
struct cdev cdev;
bool exist;
struct js_corr corr[ABS_CNT];
@@ -70,9 +71,6 @@ struct joydev_client {
struct list_head node;
};
static struct joydev *joydev_table[JOYDEV_MINORS];
static DEFINE_MUTEX(joydev_table_mutex);
static int joydev_correct(int value, struct js_corr *corr)
{
switch (corr->type) {
@@ -252,30 +250,14 @@ static int joydev_release(struct inode *inode, struct file *file)
static int joydev_open(struct inode *inode, struct file *file)
{
struct joydev *joydev =
container_of(inode->i_cdev, struct joydev, cdev);
struct joydev_client *client;
struct joydev *joydev;
int i = iminor(inode) - JOYDEV_MINOR_BASE;
int error;
if (i >= JOYDEV_MINORS)
return -ENODEV;
error = mutex_lock_interruptible(&joydev_table_mutex);
if (error)
return error;
joydev = joydev_table[i];
if (joydev)
get_device(&joydev->dev);
mutex_unlock(&joydev_table_mutex);
if (!joydev)
return -ENODEV;
client = kzalloc(sizeof(struct joydev_client), GFP_KERNEL);
if (!client) {
error = -ENOMEM;
goto err_put_joydev;
}
if (!client)
return -ENOMEM;
spin_lock_init(&client->buffer_lock);
client->joydev = joydev;
@@ -288,13 +270,12 @@ static int joydev_open(struct inode *inode, struct file *file)
file->private_data = client;
nonseekable_open(inode, file);
get_device(&joydev->dev);
return 0;
err_free_client:
joydev_detach_client(joydev, client);
kfree(client);
err_put_joydev:
put_device(&joydev->dev);
return error;
}
@@ -742,19 +723,6 @@ static const struct file_operations joydev_fops = {
.llseek = no_llseek,
};
static int joydev_install_chrdev(struct joydev *joydev)
{
joydev_table[joydev->minor] = joydev;
return 0;
}
static void joydev_remove_chrdev(struct joydev *joydev)
{
mutex_lock(&joydev_table_mutex);
joydev_table[joydev->minor] = NULL;
mutex_unlock(&joydev_table_mutex);
}
/*
* Mark device non-existent. This disables writes, ioctls and
* prevents new users from opening the device. Already posted
@@ -773,7 +741,8 @@ static void joydev_cleanup(struct joydev *joydev)
joydev_mark_dead(joydev);
joydev_hangup(joydev);
joydev_remove_chrdev(joydev);
cdev_del(&joydev->cdev);
/* joydev is marked dead so no one else accesses joydev->open */
if (joydev->open)
@@ -798,30 +767,33 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
const struct input_device_id *id)
{
struct joydev *joydev;
int i, j, t, minor;
int i, j, t, minor, dev_no;
int error;
for (minor = 0; minor < JOYDEV_MINORS; minor++)
if (!joydev_table[minor])
break;
if (minor == JOYDEV_MINORS) {
pr_err("no more free joydev devices\n");
return -ENFILE;
minor = input_get_new_minor(JOYDEV_MINOR_BASE, JOYDEV_MINORS, true);
if (minor < 0) {
error = minor;
pr_err("failed to reserve new minor: %d\n", error);
return error;
}
joydev = kzalloc(sizeof(struct joydev), GFP_KERNEL);
if (!joydev)
return -ENOMEM;
if (!joydev) {
error = -ENOMEM;
goto err_free_minor;
}
INIT_LIST_HEAD(&joydev->client_list);
spin_lock_init(&joydev->client_lock);
mutex_init(&joydev->mutex);
init_waitqueue_head(&joydev->wait);
dev_set_name(&joydev->dev, "js%d", minor);
joydev->exist = true;
joydev->minor = minor;
dev_no = minor;
/* Normalize device number if it falls into legacy range */
if (dev_no < JOYDEV_MINOR_BASE + JOYDEV_MINORS)
dev_no -= JOYDEV_MINOR_BASE;
dev_set_name(&joydev->dev, "js%d", dev_no);
joydev->handle.dev = input_get_device(dev);
joydev->handle.name = dev_name(&joydev->dev);
@@ -875,7 +847,7 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
}
}
joydev->dev.devt = MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor);
joydev->dev.devt = MKDEV(INPUT_MAJOR, minor);
joydev->dev.class = &input_class;
joydev->dev.parent = &dev->dev;
joydev->dev.release = joydev_free;
@@ -885,7 +857,8 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
if (error)
goto err_free_joydev;
error = joydev_install_chrdev(joydev);
cdev_init(&joydev->cdev, &joydev_fops);
error = cdev_add(&joydev->cdev, joydev->dev.devt, 1);
if (error)
goto err_unregister_handle;
@@ -901,6 +874,8 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
input_unregister_handle(&joydev->handle);
err_free_joydev:
put_device(&joydev->dev);
err_free_minor:
input_free_minor(minor);
return error;
}
@@ -910,6 +885,7 @@ static void joydev_disconnect(struct input_handle *handle)
device_del(&joydev->dev);
joydev_cleanup(joydev);
input_free_minor(MINOR(joydev->dev.devt));
input_unregister_handle(handle);
put_device(&joydev->dev);
}
@@ -961,7 +937,7 @@ static struct input_handler joydev_handler = {
.match = joydev_match,
.connect = joydev_connect,
.disconnect = joydev_disconnect,
.fops = &joydev_fops,
.legacy_minors = true,
.minor = JOYDEV_MINOR_BASE,
.name = "joydev",
.id_table = joydev_ids,
+10 -1
View File
@@ -431,6 +431,12 @@ static int __devinit samsung_keypad_probe(struct platform_device *pdev)
goto err_unmap_base;
}
error = clk_prepare(keypad->clk);
if (error) {
dev_err(&pdev->dev, "keypad clock prepare failed\n");
goto err_put_clk;
}
keypad->input_dev = input_dev;
keypad->pdev = pdev;
keypad->row_shift = row_shift;
@@ -461,7 +467,7 @@ static int __devinit samsung_keypad_probe(struct platform_device *pdev)
keypad->keycodes, input_dev);
if (error) {
dev_err(&pdev->dev, "failed to build keymap\n");
goto err_put_clk;
goto err_unprepare_clk;
}
input_set_capability(input_dev, EV_MSC, MSC_SCAN);
@@ -503,6 +509,8 @@ err_free_irq:
pm_runtime_disable(&pdev->dev);
device_init_wakeup(&pdev->dev, 0);
platform_set_drvdata(pdev, NULL);
err_unprepare_clk:
clk_unprepare(keypad->clk);
err_put_clk:
clk_put(keypad->clk);
samsung_keypad_dt_gpio_free(keypad);
@@ -531,6 +539,7 @@ static int __devexit samsung_keypad_remove(struct platform_device *pdev)
*/
free_irq(keypad->irq, keypad);
clk_unprepare(keypad->clk);
clk_put(keypad->clk);
samsung_keypad_dt_gpio_free(keypad);
+1 -1
View File
@@ -416,7 +416,7 @@ static int uinput_setup_device(struct uinput_device *udev,
goto exit;
if (test_bit(ABS_MT_SLOT, dev->absbit)) {
int nslot = input_abs_get_max(dev, ABS_MT_SLOT) + 1;
input_mt_init_slots(dev, nslot);
input_mt_init_slots(dev, nslot, 0);
} else if (test_bit(ABS_MT_POSITION_X, dev->absbit)) {
input_set_events_per_packet(dev, 60);
}
+1 -1
View File
@@ -1620,7 +1620,7 @@ int alps_init(struct psmouse *psmouse)
case ALPS_PROTO_V3:
case ALPS_PROTO_V4:
set_bit(INPUT_PROP_SEMI_MT, dev1->propbit);
input_mt_init_slots(dev1, 2);
input_mt_init_slots(dev1, 2, 0);
input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, ALPS_V3_X_MAX, 0, 0);
input_set_abs_params(dev1, ABS_MT_POSITION_Y, 0, ALPS_V3_Y_MAX, 0, 0);
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -1004,7 +1004,7 @@ static int elantech_set_input_params(struct psmouse *psmouse)
input_set_abs_params(dev, ABS_TOOL_WIDTH, ETP_WMIN_V2,
ETP_WMAX_V2, 0, 0);
}
input_mt_init_slots(dev, 2);
input_mt_init_slots(dev, 2, 0);
input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0);
input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0);
break;
@@ -1035,7 +1035,7 @@ static int elantech_set_input_params(struct psmouse *psmouse)
input_set_abs_params(dev, ABS_TOOL_WIDTH, ETP_WMIN_V2,
ETP_WMAX_V2, 0, 0);
/* Multitouch capable pad, up to 5 fingers. */
input_mt_init_slots(dev, ETP_MAX_FINGERS);
input_mt_init_slots(dev, ETP_MAX_FINGERS, 0);
input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0);
input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0);
input_abs_set_res(dev, ABS_MT_POSITION_X, x_res);
+1 -1
View File
@@ -971,7 +971,7 @@ static int fsp_set_input_params(struct psmouse *psmouse)
input_set_abs_params(dev, ABS_X, 0, abs_x, 0, 0);
input_set_abs_params(dev, ABS_Y, 0, abs_y, 0, 0);
input_mt_init_slots(dev, 2);
input_mt_init_slots(dev, 2, 0);
input_set_abs_params(dev, ABS_MT_POSITION_X, 0, abs_x, 0, 0);
input_set_abs_params(dev, ABS_MT_POSITION_Y, 0, abs_y, 0, 0);
}
+2 -2
View File
@@ -1247,7 +1247,7 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0);
if (SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) {
input_mt_init_slots(dev, 2);
input_mt_init_slots(dev, 2, 0);
set_abs_position_params(dev, priv, ABS_MT_POSITION_X,
ABS_MT_POSITION_Y);
/* Image sensors can report per-contact pressure */
@@ -1259,7 +1259,7 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
} else if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) {
/* Non-image sensors with AGM use semi-mt */
__set_bit(INPUT_PROP_SEMI_MT, dev->propbit);
input_mt_init_slots(dev, 2);
input_mt_init_slots(dev, 2, 0);
set_abs_position_params(dev, priv, ABS_MT_POSITION_X,
ABS_MT_POSITION_Y);
}
+115 -109
View File
@@ -24,10 +24,8 @@
#include <linux/random.h>
#include <linux/major.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <linux/kernel.h>
#ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
#include <linux/miscdevice.h>
#endif
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Mouse (ExplorerPS/2) device interfaces");
@@ -61,17 +59,18 @@ struct mousedev_hw_data {
struct mousedev {
int open;
int minor;
struct input_handle handle;
wait_queue_head_t wait;
struct list_head client_list;
spinlock_t client_lock; /* protects client_list */
struct mutex mutex;
struct device dev;
struct cdev cdev;
bool exist;
bool is_mixdev;
struct list_head mixdev_node;
int mixdev_open;
bool opened_by_mixdev;
struct mousedev_hw_data packet;
unsigned int pkt_count;
@@ -114,10 +113,6 @@ struct mousedev_client {
static unsigned char mousedev_imps_seq[] = { 0xf3, 200, 0xf3, 100, 0xf3, 80 };
static unsigned char mousedev_imex_seq[] = { 0xf3, 200, 0xf3, 200, 0xf3, 80 };
static struct input_handler mousedev_handler;
static struct mousedev *mousedev_table[MOUSEDEV_MINORS];
static DEFINE_MUTEX(mousedev_table_mutex);
static struct mousedev *mousedev_mix;
static LIST_HEAD(mousedev_mix_list);
@@ -433,7 +428,7 @@ static int mousedev_open_device(struct mousedev *mousedev)
if (retval)
return retval;
if (mousedev->minor == MOUSEDEV_MIX)
if (mousedev->is_mixdev)
mixdev_open_devices();
else if (!mousedev->exist)
retval = -ENODEV;
@@ -451,7 +446,7 @@ static void mousedev_close_device(struct mousedev *mousedev)
{
mutex_lock(&mousedev->mutex);
if (mousedev->minor == MOUSEDEV_MIX)
if (mousedev->is_mixdev)
mixdev_close_devices();
else if (mousedev->exist && !--mousedev->open)
input_close_device(&mousedev->handle);
@@ -472,11 +467,11 @@ static void mixdev_open_devices(void)
return;
list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) {
if (!mousedev->mixdev_open) {
if (!mousedev->opened_by_mixdev) {
if (mousedev_open_device(mousedev))
continue;
mousedev->mixdev_open = 1;
mousedev->opened_by_mixdev = true;
}
}
}
@@ -494,8 +489,8 @@ static void mixdev_close_devices(void)
return;
list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) {
if (mousedev->mixdev_open) {
mousedev->mixdev_open = 0;
if (mousedev->opened_by_mixdev) {
mousedev->opened_by_mixdev = false;
mousedev_close_device(mousedev);
}
}
@@ -538,35 +533,17 @@ static int mousedev_open(struct inode *inode, struct file *file)
struct mousedev_client *client;
struct mousedev *mousedev;
int error;
int i;
#ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
if (imajor(inode) == MISC_MAJOR)
i = MOUSEDEV_MIX;
mousedev = mousedev_mix;
else
#endif
i = iminor(inode) - MOUSEDEV_MINOR_BASE;
if (i >= MOUSEDEV_MINORS)
return -ENODEV;
error = mutex_lock_interruptible(&mousedev_table_mutex);
if (error)
return error;
mousedev = mousedev_table[i];
if (mousedev)
get_device(&mousedev->dev);
mutex_unlock(&mousedev_table_mutex);
if (!mousedev)
return -ENODEV;
mousedev = container_of(inode->i_cdev, struct mousedev, cdev);
client = kzalloc(sizeof(struct mousedev_client), GFP_KERNEL);
if (!client) {
error = -ENOMEM;
goto err_put_mousedev;
}
if (!client)
return -ENOMEM;
spin_lock_init(&client->packet_lock);
client->pos_x = xres / 2;
@@ -579,13 +556,14 @@ static int mousedev_open(struct inode *inode, struct file *file)
goto err_free_client;
file->private_data = client;
nonseekable_open(inode, file);
get_device(&mousedev->dev);
return 0;
err_free_client:
mousedev_detach_client(mousedev, client);
kfree(client);
err_put_mousedev:
put_device(&mousedev->dev);
return error;
}
@@ -785,29 +763,16 @@ static unsigned int mousedev_poll(struct file *file, poll_table *wait)
}
static const struct file_operations mousedev_fops = {
.owner = THIS_MODULE,
.read = mousedev_read,
.write = mousedev_write,
.poll = mousedev_poll,
.open = mousedev_open,
.release = mousedev_release,
.fasync = mousedev_fasync,
.llseek = noop_llseek,
.owner = THIS_MODULE,
.read = mousedev_read,
.write = mousedev_write,
.poll = mousedev_poll,
.open = mousedev_open,
.release = mousedev_release,
.fasync = mousedev_fasync,
.llseek = noop_llseek,
};
static int mousedev_install_chrdev(struct mousedev *mousedev)
{
mousedev_table[mousedev->minor] = mousedev;
return 0;
}
static void mousedev_remove_chrdev(struct mousedev *mousedev)
{
mutex_lock(&mousedev_table_mutex);
mousedev_table[mousedev->minor] = NULL;
mutex_unlock(&mousedev_table_mutex);
}
/*
* Mark device non-existent. This disables writes, ioctls and
* prevents new users from opening the device. Already posted
@@ -842,24 +807,50 @@ static void mousedev_cleanup(struct mousedev *mousedev)
mousedev_mark_dead(mousedev);
mousedev_hangup(mousedev);
mousedev_remove_chrdev(mousedev);
cdev_del(&mousedev->cdev);
/* mousedev is marked dead so no one else accesses mousedev->open */
if (mousedev->open)
input_close_device(handle);
}
static int mousedev_reserve_minor(bool mixdev)
{
int minor;
if (mixdev) {
minor = input_get_new_minor(MOUSEDEV_MIX, 1, false);
if (minor < 0)
pr_err("failed to reserve mixdev minor: %d\n", minor);
} else {
minor = input_get_new_minor(MOUSEDEV_MINOR_BASE,
MOUSEDEV_MINORS, true);
if (minor < 0)
pr_err("failed to reserve new minor: %d\n", minor);
}
return minor;
}
static struct mousedev *mousedev_create(struct input_dev *dev,
struct input_handler *handler,
int minor)
bool mixdev)
{
struct mousedev *mousedev;
int minor;
int error;
minor = mousedev_reserve_minor(mixdev);
if (minor < 0) {
error = minor;
goto err_out;
}
mousedev = kzalloc(sizeof(struct mousedev), GFP_KERNEL);
if (!mousedev) {
error = -ENOMEM;
goto err_out;
goto err_free_minor;
}
INIT_LIST_HEAD(&mousedev->client_list);
@@ -867,16 +858,21 @@ static struct mousedev *mousedev_create(struct input_dev *dev,
spin_lock_init(&mousedev->client_lock);
mutex_init(&mousedev->mutex);
lockdep_set_subclass(&mousedev->mutex,
minor == MOUSEDEV_MIX ? SINGLE_DEPTH_NESTING : 0);
mixdev ? SINGLE_DEPTH_NESTING : 0);
init_waitqueue_head(&mousedev->wait);
if (minor == MOUSEDEV_MIX)
if (mixdev) {
dev_set_name(&mousedev->dev, "mice");
else
dev_set_name(&mousedev->dev, "mouse%d", minor);
} else {
int dev_no = minor;
/* Normalize device number if it falls into legacy range */
if (dev_no < MOUSEDEV_MINOR_BASE + MOUSEDEV_MINORS)
dev_no -= MOUSEDEV_MINOR_BASE;
dev_set_name(&mousedev->dev, "mouse%d", dev_no);
}
mousedev->minor = minor;
mousedev->exist = true;
mousedev->is_mixdev = mixdev;
mousedev->handle.dev = input_get_device(dev);
mousedev->handle.name = dev_name(&mousedev->dev);
mousedev->handle.handler = handler;
@@ -885,17 +881,18 @@ static struct mousedev *mousedev_create(struct input_dev *dev,
mousedev->dev.class = &input_class;
if (dev)
mousedev->dev.parent = &dev->dev;
mousedev->dev.devt = MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor);
mousedev->dev.devt = MKDEV(INPUT_MAJOR, minor);
mousedev->dev.release = mousedev_free;
device_initialize(&mousedev->dev);
if (minor != MOUSEDEV_MIX) {
if (!mixdev) {
error = input_register_handle(&mousedev->handle);
if (error)
goto err_free_mousedev;
}
error = mousedev_install_chrdev(mousedev);
cdev_init(&mousedev->cdev, &mousedev_fops);
error = cdev_add(&mousedev->cdev, mousedev->dev.devt, 1);
if (error)
goto err_unregister_handle;
@@ -908,10 +905,12 @@ static struct mousedev *mousedev_create(struct input_dev *dev,
err_cleanup_mousedev:
mousedev_cleanup(mousedev);
err_unregister_handle:
if (minor != MOUSEDEV_MIX)
if (!mixdev)
input_unregister_handle(&mousedev->handle);
err_free_mousedev:
put_device(&mousedev->dev);
err_free_minor:
input_free_minor(minor);
err_out:
return ERR_PTR(error);
}
@@ -920,7 +919,8 @@ static void mousedev_destroy(struct mousedev *mousedev)
{
device_del(&mousedev->dev);
mousedev_cleanup(mousedev);
if (mousedev->minor != MOUSEDEV_MIX)
input_free_minor(MINOR(mousedev->dev.devt));
if (!mousedev->is_mixdev)
input_unregister_handle(&mousedev->handle);
put_device(&mousedev->dev);
}
@@ -938,7 +938,7 @@ static int mixdev_add_device(struct mousedev *mousedev)
if (retval)
goto out;
mousedev->mixdev_open = 1;
mousedev->opened_by_mixdev = true;
}
get_device(&mousedev->dev);
@@ -953,8 +953,8 @@ static void mixdev_remove_device(struct mousedev *mousedev)
{
mutex_lock(&mousedev_mix->mutex);
if (mousedev->mixdev_open) {
mousedev->mixdev_open = 0;
if (mousedev->opened_by_mixdev) {
mousedev->opened_by_mixdev = false;
mousedev_close_device(mousedev);
}
@@ -969,19 +969,9 @@ static int mousedev_connect(struct input_handler *handler,
const struct input_device_id *id)
{
struct mousedev *mousedev;
int minor;
int error;
for (minor = 0; minor < MOUSEDEV_MINORS; minor++)
if (!mousedev_table[minor])
break;
if (minor == MOUSEDEV_MINORS) {
pr_err("no more free mousedev devices\n");
return -ENFILE;
}
mousedev = mousedev_create(dev, handler, minor);
mousedev = mousedev_create(dev, handler, false);
if (IS_ERR(mousedev))
return PTR_ERR(mousedev);
@@ -1054,27 +1044,53 @@ static const struct input_device_id mousedev_ids[] = {
MODULE_DEVICE_TABLE(input, mousedev_ids);
static struct input_handler mousedev_handler = {
.event = mousedev_event,
.connect = mousedev_connect,
.disconnect = mousedev_disconnect,
.fops = &mousedev_fops,
.minor = MOUSEDEV_MINOR_BASE,
.name = "mousedev",
.id_table = mousedev_ids,
.event = mousedev_event,
.connect = mousedev_connect,
.disconnect = mousedev_disconnect,
.legacy_minors = true,
.minor = MOUSEDEV_MINOR_BASE,
.name = "mousedev",
.id_table = mousedev_ids,
};
#ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
#include <linux/miscdevice.h>
static struct miscdevice psaux_mouse = {
PSMOUSE_MINOR, "psaux", &mousedev_fops
.minor = PSMOUSE_MINOR,
.name = "psaux",
.fops = &mousedev_fops,
};
static int psaux_registered;
static bool psaux_registered;
static void __init mousedev_psaux_register(void)
{
int error;
error = misc_register(&psaux_mouse);
if (error)
pr_warn("could not register psaux device, error: %d\n",
error);
else
psaux_registered = true;
}
static void __exit mousedev_psaux_unregister(void)
{
if (psaux_registered)
misc_deregister(&psaux_mouse);
}
#else
static inline void mousedev_psaux_register(void) { }
static inline void mousedev_psaux_unregister(void) { }
#endif
static int __init mousedev_init(void)
{
int error;
mousedev_mix = mousedev_create(NULL, &mousedev_handler, MOUSEDEV_MIX);
mousedev_mix = mousedev_create(NULL, &mousedev_handler, true);
if (IS_ERR(mousedev_mix))
return PTR_ERR(mousedev_mix);
@@ -1084,14 +1100,7 @@ static int __init mousedev_init(void)
return error;
}
#ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
error = misc_register(&psaux_mouse);
if (error)
pr_warn("could not register psaux device, error: %d\n",
error);
else
psaux_registered = 1;
#endif
mousedev_psaux_register();
pr_info("PS/2 mouse device common for all mice\n");
@@ -1100,10 +1109,7 @@ static int __init mousedev_init(void)
static void __exit mousedev_exit(void)
{
#ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
if (psaux_registered)
misc_deregister(&psaux_mouse);
#endif
mousedev_psaux_unregister();
input_unregister_handler(&mousedev_handler);
mousedev_destroy(mousedev_mix);
}
+107 -40
View File
@@ -171,6 +171,76 @@ static void wacom_close(struct input_dev *dev)
usb_autopm_put_interface(wacom->intf);
}
/*
* Calculate the resolution of the X or Y axis, given appropriate HID data.
* This function is little more than hidinput_calc_abs_res stripped down.
*/
static int wacom_calc_hid_res(int logical_extents, int physical_extents,
unsigned char unit, unsigned char exponent)
{
int prev, unit_exponent;
/* Check if the extents are sane */
if (logical_extents <= 0 || physical_extents <= 0)
return 0;
/* Get signed value of nybble-sized twos-compliment exponent */
unit_exponent = exponent;
if (unit_exponent > 7)
unit_exponent -= 16;
/* Convert physical_extents to millimeters */
if (unit == 0x11) { /* If centimeters */
unit_exponent += 1;
} else if (unit == 0x13) { /* If inches */
prev = physical_extents;
physical_extents *= 254;
if (physical_extents < prev)
return 0;
unit_exponent -= 1;
} else {
return 0;
}
/* Apply negative unit exponent */
for (; unit_exponent < 0; unit_exponent++) {
prev = logical_extents;
logical_extents *= 10;
if (logical_extents < prev)
return 0;
}
/* Apply positive unit exponent */
for (; unit_exponent > 0; unit_exponent--) {
prev = physical_extents;
physical_extents *= 10;
if (physical_extents < prev)
return 0;
}
/* Calculate resolution */
return logical_extents / physical_extents;
}
/*
* The physical dimension specified by the HID descriptor is likely not in
* the "100th of a mm" units expected by wacom_calculate_touch_res. This
* function adjusts the value of [xy]_phy based on the unit and exponent
* provided by the HID descriptor. If an error occurs durring conversion
* (e.g. from the unit being left unspecified) [xy]_phy is not modified.
*/
static void wacom_fix_phy_from_hid(struct wacom_features *features)
{
int xres = wacom_calc_hid_res(features->x_max, features->x_phy,
features->unit, features->unitExpo);
int yres = wacom_calc_hid_res(features->y_max, features->y_phy,
features->unit, features->unitExpo);
if (xres > 0 && yres > 0) {
features->x_phy = (100 * features->x_max) / xres;
features->y_phy = (100 * features->y_max) / yres;
}
}
/*
* Static values for max X/Y and resolution of Pen interface is stored in
* features. This mean physical size of active area can be computed.
@@ -432,58 +502,54 @@ static int wacom_parse_hid(struct usb_interface *intf,
return result;
}
static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_features *features)
static int wacom_set_device_mode(struct usb_interface *intf, int report_id, int length, int mode)
{
unsigned char *rep_data;
int limit = 0, report_id = 2;
int error = -ENOMEM;
int error = -ENOMEM, limit = 0;
rep_data = kmalloc(4, GFP_KERNEL);
rep_data = kzalloc(length, GFP_KERNEL);
if (!rep_data)
return error;
/* ask to report Wacom data */
if (features->device_type == BTN_TOOL_FINGER) {
/* if it is an MT Tablet PC touch */
if (features->type > TABLETPC) {
do {
rep_data[0] = 3;
rep_data[1] = 4;
rep_data[2] = 0;
rep_data[3] = 0;
report_id = 3;
error = wacom_set_report(intf,
WAC_HID_FEATURE_REPORT,
report_id,
rep_data, 4, 1);
if (error >= 0)
error = wacom_get_report(intf,
WAC_HID_FEATURE_REPORT,
report_id,
rep_data, 4, 1);
} while ((error < 0 || rep_data[1] != 4) &&
limit++ < WAC_MSG_RETRIES);
}
} else if (features->type <= BAMBOO_PT &&
features->type != WIRELESS &&
features->device_type == BTN_TOOL_PEN) {
do {
rep_data[0] = 2;
rep_data[1] = 2;
error = wacom_set_report(intf, WAC_HID_FEATURE_REPORT,
report_id, rep_data, 2, 1);
if (error >= 0)
error = wacom_get_report(intf,
WAC_HID_FEATURE_REPORT,
report_id, rep_data, 2, 1);
} while ((error < 0 || rep_data[1] != 2) && limit++ < WAC_MSG_RETRIES);
}
rep_data[0] = report_id;
rep_data[1] = mode;
do {
error = wacom_set_report(intf, WAC_HID_FEATURE_REPORT,
report_id, rep_data, length, 1);
if (error >= 0)
error = wacom_get_report(intf, WAC_HID_FEATURE_REPORT,
report_id, rep_data, length, 1);
} while ((error < 0 || rep_data[1] != mode) && limit++ < WAC_MSG_RETRIES);
kfree(rep_data);
return error < 0 ? error : 0;
}
/*
* Switch the tablet into its most-capable mode. Wacom tablets are
* typically configured to power-up in a mode which sends mouse-like
* reports to the OS. To get absolute position, pressure data, etc.
* from the tablet, it is necessary to switch the tablet out of this
* mode and into one which sends the full range of tablet data.
*/
static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_features *features)
{
if (features->device_type == BTN_TOOL_FINGER) {
if (features->type > TABLETPC) {
/* MT Tablet PC touch */
return wacom_set_device_mode(intf, 3, 4, 4);
}
} else if (features->device_type == BTN_TOOL_PEN) {
if (features->type <= BAMBOO_PT && features->type != WIRELESS) {
return wacom_set_device_mode(intf, 2, 2, 2);
}
}
return 0;
}
static int wacom_retrieve_hid_descriptor(struct usb_interface *intf,
struct wacom_features *features)
{
@@ -531,6 +597,7 @@ static int wacom_retrieve_hid_descriptor(struct usb_interface *intf,
error = wacom_parse_hid(intf, hid_desc, features);
if (error)
goto out;
wacom_fix_phy_from_hid(features);
out:
return error;
+27 -9
View File
@@ -25,6 +25,11 @@
#define WACOM_INTUOS_RES 100
#define WACOM_INTUOS3_RES 200
/* Scale factor relating reported contact size to logical contact area.
* 2^14/pi is a good approximation on Intuos5 and 3rd-gen Bamboo
*/
#define WACOM_CONTACT_AREA_SCALE 2607
static int wacom_penpartner_irq(struct wacom_wac *wacom)
{
unsigned char *data = wacom->data;
@@ -326,7 +331,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
/* Enter report */
if ((data[1] & 0xfc) == 0xc0) {
if (features->type >= INTUOS5S && features->type <= INTUOS5L)
if (features->quirks == WACOM_QUIRK_MULTI_INPUT)
wacom->shared->stylus_in_proximity = true;
/* serial number of the tool */
@@ -414,7 +419,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
/* Exit report */
if ((data[1] & 0xfe) == 0x80) {
if (features->type >= INTUOS5S && features->type <= INTUOS5L)
if (features->quirks == WACOM_QUIRK_MULTI_INPUT)
wacom->shared->stylus_in_proximity = false;
/*
@@ -1043,11 +1048,19 @@ static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data)
if (touch) {
int x = (data[2] << 4) | (data[4] >> 4);
int y = (data[3] << 4) | (data[4] & 0x0f);
int w = data[6];
int a = data[5];
// "a" is a scaled-down area which we assume is roughly
// circular and which can be described as: a=(pi*r^2)/C.
int x_res = input_abs_get_res(input, ABS_X);
int y_res = input_abs_get_res(input, ABS_Y);
int width = 2 * int_sqrt(a * WACOM_CONTACT_AREA_SCALE);
int height = width * y_res / x_res;
input_report_abs(input, ABS_MT_POSITION_X, x);
input_report_abs(input, ABS_MT_POSITION_Y, y);
input_report_abs(input, ABS_MT_TOUCH_MAJOR, w);
input_report_abs(input, ABS_MT_TOUCH_MAJOR, width);
input_report_abs(input, ABS_MT_TOUCH_MINOR, height);
}
}
@@ -1530,10 +1543,12 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
__set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit);
__set_bit(BTN_TOOL_QUADTAP, input_dev->keybit);
input_mt_init_slots(input_dev, features->touch_max);
input_mt_init_slots(input_dev, features->touch_max, 0);
input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
0, 255, 0, 0);
0, features->x_max, 0, 0);
input_set_abs_params(input_dev, ABS_MT_TOUCH_MINOR,
0, features->y_max, 0, 0);
input_set_abs_params(input_dev, ABS_MT_POSITION_X,
0, features->x_max,
@@ -1575,7 +1590,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
case TABLETPC2FG:
if (features->device_type == BTN_TOOL_FINGER) {
input_mt_init_slots(input_dev, features->touch_max);
input_mt_init_slots(input_dev, features->touch_max, 0);
input_set_abs_params(input_dev, ABS_MT_TOOL_TYPE,
0, MT_TOOL_MAX, 0, 0);
input_set_abs_params(input_dev, ABS_MT_POSITION_X,
@@ -1631,7 +1646,7 @@ int 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_init_slots(input_dev, features->touch_max);
input_mt_init_slots(input_dev, features->touch_max, 0);
if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) {
__set_bit(BTN_TOOL_TRIPLETAP,
@@ -1641,7 +1656,10 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
input_set_abs_params(input_dev,
ABS_MT_TOUCH_MAJOR,
0, 255, 0, 0);
0, features->x_max, 0, 0);
input_set_abs_params(input_dev,
ABS_MT_TOUCH_MINOR,
0, features->y_max, 0, 0);
}
input_set_abs_params(input_dev, ABS_MT_POSITION_X,
+3 -5
View File
@@ -320,10 +320,8 @@ static bool mxt_object_writable(unsigned int type)
static void mxt_dump_message(struct device *dev,
struct mxt_message *message)
{
dev_dbg(dev, "reportid: %u\tmessage: %02x %02x %02x %02x %02x %02x %02x\n",
message->reportid, message->message[0], message->message[1],
message->message[2], message->message[3], message->message[4],
message->message[5], message->message[6]);
dev_dbg(dev, "reportid: %u\tmessage: %*ph\n",
message->reportid, 7, message->message);
}
static int mxt_check_bootloader(struct i2c_client *client,
@@ -1152,7 +1150,7 @@ static int __devinit mxt_probe(struct i2c_client *client,
/* For multi touch */
num_mt_slots = data->T9_reportid_max - data->T9_reportid_min + 1;
error = input_mt_init_slots(input_dev, num_mt_slots);
error = input_mt_init_slots(input_dev, num_mt_slots, 0);
if (error)
goto err_free_object;
input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
+1 -1
View File
@@ -571,7 +571,7 @@ struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops,
input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
0, CY_MAXZ, 0, 0);
input_mt_init_slots(input_dev, CY_MAX_ID);
input_mt_init_slots(input_dev, CY_MAX_ID, 0);
error = request_threaded_irq(ts->irq, NULL, cyttsp_irq,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,

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