mirror of
https://github.com/FEX-Emu/linux.git
synced 2024-12-14 21:01:29 +00:00
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid: (36 commits) HID: hid-multitouch: cosmetic changes, sort classes and devices HID: hid-multitouch: class MT_CLS_STANTUM is redundant with MT_CLS_CONFIDENCE HID: hid-multitouch: add support for Unitec panels HID: hid-multitouch: add support for Touch International panels HID: hid-multitouch: add support for GoodTouch panels HID: hid-multitouch: add support for CVTouch panels HID: hid-multitouch: add support for ActionStar panels HID: hiddev: fix race between hiddev_disconnect and hiddev_release HID: magicmouse: ignore 'ivalid report id' while switching modes HID: fix a crash in hid_report_raw_event() function. HID: hid-multitouch: add support for Elo TouchSystems 2515 IntelliTouch Plus HID: assorted usage updates from hut 1.12 HID: roccat: fix actual/startup profile sysfs attribute in koneplus HID: hid-multitouch: Add support for Lumio panels HID: 'name' and 'phys' in 'struct hid_device' can never be NULL HID: hid-multitouch: add support for Ilitek dual-touch panel HID: picolcd: Avoid compile warning/error triggered by copy_from_user() HID: add support for Logitech G27 wheel HID: hiddev: fix error path in hiddev_read when interrupted HID: add support for Sony Navigation Controller ...
This commit is contained in:
commit
ee9ec4f820
10
Documentation/ABI/obsolete/sysfs-driver-hid-roccat-koneplus
Normal file
10
Documentation/ABI/obsolete/sysfs-driver-hid-roccat-koneplus
Normal file
@ -0,0 +1,10 @@
|
||||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/startup_profile
|
||||
Date: October 2010
|
||||
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
|
||||
Description: The integer value of this attribute ranges from 0-4.
|
||||
When read, this attribute returns the number of the actual
|
||||
profile. This value is persistent, so its equivalent to the
|
||||
profile that's active when the mouse is powered on next time.
|
||||
When written, this file sets the number of the startup profile
|
||||
and the mouse activates this profile immediately.
|
||||
Please use actual_profile, it does the same thing.
|
@ -1,9 +1,12 @@
|
||||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/actual_profile
|
||||
Date: October 2010
|
||||
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
|
||||
Description: When read, this file returns the number of the actual profile in
|
||||
range 0-4.
|
||||
This file is readonly.
|
||||
Description: The integer value of this attribute ranges from 0-4.
|
||||
When read, this attribute returns the number of the actual
|
||||
profile. This value is persistent, so its equivalent to the
|
||||
profile that's active when the mouse is powered on next time.
|
||||
When written, this file sets the number of the startup profile
|
||||
and the mouse activates this profile immediately.
|
||||
Users: http://roccat.sourceforge.net
|
||||
|
||||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/firmware_version
|
||||
@ -89,16 +92,6 @@ Description: The mouse has a tracking- and a distance-control-unit. These
|
||||
This file is writeonly.
|
||||
Users: http://roccat.sourceforge.net
|
||||
|
||||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/startup_profile
|
||||
Date: October 2010
|
||||
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
|
||||
Description: The integer value of this attribute ranges from 0-4.
|
||||
When read, this attribute returns the number of the profile
|
||||
that's active when the mouse is powered on.
|
||||
When written, this file sets the number of the startup profile
|
||||
and the mouse activates this profile immediately.
|
||||
Users: http://roccat.sourceforge.net
|
||||
|
||||
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/tcu
|
||||
Date: October 2010
|
||||
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
|
||||
|
119
Documentation/hid/hidraw.txt
Normal file
119
Documentation/hid/hidraw.txt
Normal file
@ -0,0 +1,119 @@
|
||||
HIDRAW - Raw Access to USB and Bluetooth Human Interface Devices
|
||||
==================================================================
|
||||
|
||||
The hidraw driver provides a raw interface to USB and Bluetooth Human
|
||||
Interface Devices (HIDs). It differs from hiddev in that reports sent and
|
||||
received are not parsed by the HID parser, but are sent to and received from
|
||||
the device unmodified.
|
||||
|
||||
Hidraw should be used if the userspace application knows exactly how to
|
||||
communicate with the hardware device, and is able to construct the HID
|
||||
reports manually. This is often the case when making userspace drivers for
|
||||
custom HID devices.
|
||||
|
||||
Hidraw is also useful for communicating with non-conformant HID devices
|
||||
which send and receive data in a way that is inconsistent with their report
|
||||
descriptors. Because hiddev parses reports which are sent and received
|
||||
through it, checking them against the device's report descriptor, such
|
||||
communication with these non-conformant devices is impossible using hiddev.
|
||||
Hidraw is the only alternative, short of writing a custom kernel driver, for
|
||||
these non-conformant devices.
|
||||
|
||||
A benefit of hidraw is that its use by userspace applications is independent
|
||||
of the underlying hardware type. Currently, Hidraw is implemented for USB
|
||||
and Bluetooth. In the future, as new hardware bus types are developed which
|
||||
use the HID specification, hidraw will be expanded to add support for these
|
||||
new bus types.
|
||||
|
||||
Hidraw uses a dynamic major number, meaning that udev should be relied on to
|
||||
create hidraw device nodes. Udev will typically create the device nodes
|
||||
directly under /dev (eg: /dev/hidraw0). As this location is distribution-
|
||||
and udev rule-dependent, applications should use libudev to locate hidraw
|
||||
devices attached to the system. There is a tutorial on libudev with a
|
||||
working example at:
|
||||
http://www.signal11.us/oss/udev/
|
||||
|
||||
The HIDRAW API
|
||||
---------------
|
||||
|
||||
read()
|
||||
-------
|
||||
read() will read a queued report received from the HID device. On USB
|
||||
devices, the reports read using read() are the reports sent from the device
|
||||
on the INTERRUPT IN endpoint. By default, read() will block until there is
|
||||
a report available to be read. read() can be made non-blocking, by passing
|
||||
the O_NONBLOCK flag to open(), or by setting the O_NONBLOCK flag using
|
||||
fcntl().
|
||||
|
||||
On a device which uses numbered reports, the first byte of the returned data
|
||||
will be the report number; the report data follows, beginning in the second
|
||||
byte. For devices which do not use numbered reports, the report data
|
||||
will begin at the first byte.
|
||||
|
||||
write()
|
||||
--------
|
||||
The write() function will write a report to the device. For USB devices, if
|
||||
the device has an INTERRUPT OUT endpoint, the report will be sent on that
|
||||
endpoint. If it does not, the report will be sent over the control endpoint,
|
||||
using a SET_REPORT transfer.
|
||||
|
||||
The first byte of the buffer passed to write() should be set to the report
|
||||
number. If the device does not use numbered reports, the first byte should
|
||||
be set to 0. The report data itself should begin at the second byte.
|
||||
|
||||
ioctl()
|
||||
--------
|
||||
Hidraw supports the following ioctls:
|
||||
|
||||
HIDIOCGRDESCSIZE: Get Report Descriptor Size
|
||||
This ioctl will get the size of the device's report descriptor.
|
||||
|
||||
HIDIOCGRDESC: Get Report Descriptor
|
||||
This ioctl returns the device's report descriptor using a
|
||||
hidraw_report_descriptor struct. Make sure to set the size field of the
|
||||
hidraw_report_descriptor struct to the size returned from HIDIOCGRDESCSIZE.
|
||||
|
||||
HIDIOCGRAWINFO: Get Raw Info
|
||||
This ioctl will return a hidraw_devinfo struct containing the bus type, the
|
||||
vendor ID (VID), and product ID (PID) of the device. The bus type can be one
|
||||
of:
|
||||
BUS_USB
|
||||
BUS_HIL
|
||||
BUS_BLUETOOTH
|
||||
BUS_VIRTUAL
|
||||
which are defined in linux/input.h.
|
||||
|
||||
HIDIOCGRAWNAME(len): Get Raw Name
|
||||
This ioctl returns a string containing the vendor and product strings of
|
||||
the device. The returned string is Unicode, UTF-8 encoded.
|
||||
|
||||
HIDIOCGRAWPHYS(len): Get Physical Address
|
||||
This ioctl returns a string representing the physical address of the device.
|
||||
For USB devices, the string contains the physical path to the device (the
|
||||
USB controller, hubs, ports, etc). For Bluetooth devices, the string
|
||||
contains the hardware (MAC) address of the device.
|
||||
|
||||
HIDIOCSFEATURE(len): Send a Feature Report
|
||||
This ioctl will send a feature report to the device. Per the HID
|
||||
specification, feature reports are always sent using the control endpoint.
|
||||
Set the first byte of the supplied buffer to the report number. For devices
|
||||
which do not use numbered reports, set the first byte to 0. The report data
|
||||
begins in the second byte. Make sure to set len accordingly, to one more
|
||||
than the length of the report (to account for the report number).
|
||||
|
||||
HIDIOCGFEATURE(len): Get a Feature Report
|
||||
This ioctl will request a feature report from the device using the control
|
||||
endpoint. The first byte of the supplied buffer should be set to the report
|
||||
number of the requested report. For devices which do not use numbered
|
||||
reports, set the first byte to 0. The report will be returned starting at
|
||||
the first byte of the buffer (ie: the report number is not returned).
|
||||
|
||||
Example
|
||||
---------
|
||||
In samples/, find hid-example.c, which shows examples of read(), write(),
|
||||
and all the ioctls for hidraw. The code may be used by anyone for any
|
||||
purpose, and can serve as a starting point for developing applications using
|
||||
hidraw.
|
||||
|
||||
Document by:
|
||||
Alan Ott <alan@signal11.us>, Signal 11 Software
|
@ -55,12 +55,6 @@ source "drivers/hid/usbhid/Kconfig"
|
||||
menu "Special HID drivers"
|
||||
depends on HID
|
||||
|
||||
config HID_3M_PCT
|
||||
tristate "3M PCT touchscreen"
|
||||
depends on USB_HID
|
||||
---help---
|
||||
Support for 3M PCT touch screens.
|
||||
|
||||
config HID_A4TECH
|
||||
tristate "A4 tech mice" if EXPERT
|
||||
depends on USB_HID
|
||||
@ -100,12 +94,6 @@ config HID_BELKIN
|
||||
---help---
|
||||
Support for Belkin Flip KVM and Wireless keyboard.
|
||||
|
||||
config HID_CANDO
|
||||
tristate "Cando dual touch panel"
|
||||
depends on USB_HID
|
||||
---help---
|
||||
Support for Cando dual touch panel.
|
||||
|
||||
config HID_CHERRY
|
||||
tristate "Cherry Cymotion keyboard" if EXPERT
|
||||
depends on USB_HID
|
||||
@ -300,12 +288,6 @@ config HID_MICROSOFT
|
||||
---help---
|
||||
Support for Microsoft devices that are not fully compliant with HID standard.
|
||||
|
||||
config HID_MOSART
|
||||
tristate "MosArt dual-touch panels"
|
||||
depends on USB_HID
|
||||
---help---
|
||||
Support for MosArt dual-touch panels.
|
||||
|
||||
config HID_MONTEREY
|
||||
tristate "Monterey Genius KB29E keyboard" if EXPERT
|
||||
depends on USB_HID
|
||||
@ -320,13 +302,25 @@ config HID_MULTITOUCH
|
||||
Generic support for HID multitouch panels.
|
||||
|
||||
Say Y here if you have one of the following devices:
|
||||
- 3M PCT touch screens
|
||||
- ActionStar dual touch panels
|
||||
- Cando dual touch panels
|
||||
- CVTouch panels
|
||||
- Cypress TrueTouch panels
|
||||
- Elo TouchSystems IntelliTouch Plus panels
|
||||
- GeneralTouch 'Sensing Win7-TwoFinger' panels
|
||||
- GoodTouch panels
|
||||
- Hanvon dual touch panels
|
||||
- Ilitek dual touch panels
|
||||
- IrTouch Infrared USB panels
|
||||
- Lumio CrystalTouch panels
|
||||
- MosArt dual-touch panels
|
||||
- PenMount dual touch panels
|
||||
- Pixcir dual touch panels
|
||||
- 'Sensing Win7-TwoFinger' panel by GeneralTouch
|
||||
- eGalax dual-touch panels, including the
|
||||
Joojoo and Wetab tablets
|
||||
- eGalax dual-touch panels, including the Joojoo and Wetab tablets
|
||||
- Stantum multitouch panels
|
||||
- Touch International Panels
|
||||
- Unitec Panels
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
@ -500,12 +494,6 @@ config HID_SONY
|
||||
---help---
|
||||
Support for Sony PS3 controller.
|
||||
|
||||
config HID_STANTUM
|
||||
tristate "Stantum multitouch panel"
|
||||
depends on USB_HID
|
||||
---help---
|
||||
Support for Stantum multitouch panel.
|
||||
|
||||
config HID_SUNPLUS
|
||||
tristate "Sunplus wireless desktop"
|
||||
depends on USB_HID
|
||||
|
@ -25,12 +25,10 @@ ifdef CONFIG_LOGIWII_FF
|
||||
hid-logitech-y += hid-lg4ff.o
|
||||
endif
|
||||
|
||||
obj-$(CONFIG_HID_3M_PCT) += hid-3m-pct.o
|
||||
obj-$(CONFIG_HID_A4TECH) += hid-a4tech.o
|
||||
obj-$(CONFIG_HID_ACRUX) += hid-axff.o
|
||||
obj-$(CONFIG_HID_APPLE) += hid-apple.o
|
||||
obj-$(CONFIG_HID_BELKIN) += hid-belkin.o
|
||||
obj-$(CONFIG_HID_CANDO) += hid-cando.o
|
||||
obj-$(CONFIG_HID_CHERRY) += hid-cherry.o
|
||||
obj-$(CONFIG_HID_CHICONY) += hid-chicony.o
|
||||
obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o
|
||||
@ -47,7 +45,6 @@ obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o
|
||||
obj-$(CONFIG_HID_MAGICMOUSE) += hid-magicmouse.o
|
||||
obj-$(CONFIG_HID_MICROSOFT) += hid-microsoft.o
|
||||
obj-$(CONFIG_HID_MONTEREY) += hid-monterey.o
|
||||
obj-$(CONFIG_HID_MOSART) += hid-mosart.o
|
||||
obj-$(CONFIG_HID_MULTITOUCH) += hid-multitouch.o
|
||||
obj-$(CONFIG_HID_NTRIG) += hid-ntrig.o
|
||||
obj-$(CONFIG_HID_ORTEK) += hid-ortek.o
|
||||
@ -66,7 +63,6 @@ obj-$(CONFIG_HID_ROCCAT_PYRA) += hid-roccat-pyra.o
|
||||
obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o
|
||||
obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o
|
||||
obj-$(CONFIG_HID_SONY) += hid-sony.o
|
||||
obj-$(CONFIG_HID_STANTUM) += hid-stantum.o
|
||||
obj-$(CONFIG_HID_SUNPLUS) += hid-sunplus.o
|
||||
obj-$(CONFIG_HID_GREENASIA) += hid-gaff.o
|
||||
obj-$(CONFIG_HID_THRUSTMASTER) += hid-tmff.o
|
||||
|
@ -1,305 +0,0 @@
|
||||
/*
|
||||
* HID driver for 3M PCT multitouch panels
|
||||
*
|
||||
* Copyright (c) 2009-2010 Stephane Chatty <chatty@enac.fr>
|
||||
* Copyright (c) 2010 Henrik Rydberg <rydberg@euromail.se>
|
||||
* Copyright (c) 2010 Canonical, Ltd.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/hid.h>
|
||||
#include <linux/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");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
#include "hid-ids.h"
|
||||
|
||||
#define MAX_SLOTS 60
|
||||
|
||||
/* estimated signal-to-noise ratios */
|
||||
#define SN_MOVE 2048
|
||||
#define SN_WIDTH 128
|
||||
|
||||
struct mmm_finger {
|
||||
__s32 x, y, w, h;
|
||||
bool touch, valid;
|
||||
};
|
||||
|
||||
struct mmm_data {
|
||||
struct mmm_finger f[MAX_SLOTS];
|
||||
__u8 curid;
|
||||
__u8 nexp, nreal;
|
||||
bool touch, valid;
|
||||
};
|
||||
|
||||
static int mmm_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
||||
struct hid_field *field, struct hid_usage *usage,
|
||||
unsigned long **bit, int *max)
|
||||
{
|
||||
int f1 = field->logical_minimum;
|
||||
int f2 = field->logical_maximum;
|
||||
int df = f2 - f1;
|
||||
|
||||
switch (usage->hid & HID_USAGE_PAGE) {
|
||||
|
||||
case HID_UP_BUTTON:
|
||||
return -1;
|
||||
|
||||
case HID_UP_GENDESK:
|
||||
switch (usage->hid) {
|
||||
case HID_GD_X:
|
||||
hid_map_usage(hi, usage, bit, max,
|
||||
EV_ABS, ABS_MT_POSITION_X);
|
||||
input_set_abs_params(hi->input, ABS_MT_POSITION_X,
|
||||
f1, f2, df / SN_MOVE, 0);
|
||||
/* touchscreen emulation */
|
||||
input_set_abs_params(hi->input, ABS_X,
|
||||
f1, f2, df / SN_MOVE, 0);
|
||||
return 1;
|
||||
case HID_GD_Y:
|
||||
hid_map_usage(hi, usage, bit, max,
|
||||
EV_ABS, ABS_MT_POSITION_Y);
|
||||
input_set_abs_params(hi->input, ABS_MT_POSITION_Y,
|
||||
f1, f2, df / SN_MOVE, 0);
|
||||
/* touchscreen emulation */
|
||||
input_set_abs_params(hi->input, ABS_Y,
|
||||
f1, f2, df / SN_MOVE, 0);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
case HID_UP_DIGITIZER:
|
||||
switch (usage->hid) {
|
||||
/* we do not want to map these: no input-oriented meaning */
|
||||
case 0x14:
|
||||
case 0x23:
|
||||
case HID_DG_INPUTMODE:
|
||||
case HID_DG_DEVICEINDEX:
|
||||
case HID_DG_CONTACTCOUNT:
|
||||
case HID_DG_CONTACTMAX:
|
||||
case HID_DG_INRANGE:
|
||||
case HID_DG_CONFIDENCE:
|
||||
return -1;
|
||||
case HID_DG_TIPSWITCH:
|
||||
/* touchscreen emulation */
|
||||
hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
|
||||
input_set_capability(hi->input, EV_KEY, BTN_TOUCH);
|
||||
return 1;
|
||||
case HID_DG_WIDTH:
|
||||
hid_map_usage(hi, usage, bit, max,
|
||||
EV_ABS, ABS_MT_TOUCH_MAJOR);
|
||||
input_set_abs_params(hi->input, ABS_MT_TOUCH_MAJOR,
|
||||
f1, f2, df / SN_WIDTH, 0);
|
||||
return 1;
|
||||
case HID_DG_HEIGHT:
|
||||
hid_map_usage(hi, usage, bit, max,
|
||||
EV_ABS, ABS_MT_TOUCH_MINOR);
|
||||
input_set_abs_params(hi->input, ABS_MT_TOUCH_MINOR,
|
||||
f1, f2, df / SN_WIDTH, 0);
|
||||
input_set_abs_params(hi->input, ABS_MT_ORIENTATION,
|
||||
0, 1, 0, 0);
|
||||
return 1;
|
||||
case HID_DG_CONTACTID:
|
||||
input_mt_init_slots(hi->input, MAX_SLOTS);
|
||||
return 1;
|
||||
}
|
||||
/* let hid-input decide for the others */
|
||||
return 0;
|
||||
|
||||
case 0xff000000:
|
||||
/* we do not want to map these: no input-oriented meaning */
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mmm_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)
|
||||
set_bit(usage->type, hi->input->evbit);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 mmm_filter_event(struct mmm_data *md, struct input_dev *input)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_SLOTS; ++i) {
|
||||
struct mmm_finger *f = &md->f[i];
|
||||
if (!f->valid) {
|
||||
/* this finger is just placeholder data, ignore */
|
||||
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);
|
||||
/* divided by two to match visual scale of touch */
|
||||
int major = max(f->w, f->h) >> 1;
|
||||
int minor = min(f->w, f->h) >> 1;
|
||||
|
||||
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);
|
||||
}
|
||||
f->valid = 0;
|
||||
}
|
||||
|
||||
input_mt_report_pointer_emulation(input, true);
|
||||
input_sync(input);
|
||||
}
|
||||
|
||||
/*
|
||||
* this function is called upon all reports
|
||||
* so that we can accumulate contact point information,
|
||||
* and call input_mt_sync after each point.
|
||||
*/
|
||||
static int mmm_event(struct hid_device *hid, struct hid_field *field,
|
||||
struct hid_usage *usage, __s32 value)
|
||||
{
|
||||
struct mmm_data *md = hid_get_drvdata(hid);
|
||||
/*
|
||||
* strangely, this function can be called before
|
||||
* field->hidinput is initialized!
|
||||
*/
|
||||
if (hid->claimed & HID_CLAIMED_INPUT) {
|
||||
struct input_dev *input = field->hidinput->input;
|
||||
switch (usage->hid) {
|
||||
case HID_DG_TIPSWITCH:
|
||||
md->touch = value;
|
||||
break;
|
||||
case HID_DG_CONFIDENCE:
|
||||
md->valid = value;
|
||||
break;
|
||||
case HID_DG_WIDTH:
|
||||
if (md->valid)
|
||||
md->f[md->curid].w = value;
|
||||
break;
|
||||
case HID_DG_HEIGHT:
|
||||
if (md->valid)
|
||||
md->f[md->curid].h = value;
|
||||
break;
|
||||
case HID_DG_CONTACTID:
|
||||
value = clamp_val(value, 0, MAX_SLOTS - 1);
|
||||
if (md->valid) {
|
||||
md->curid = value;
|
||||
md->f[value].touch = md->touch;
|
||||
md->f[value].valid = 1;
|
||||
md->nreal++;
|
||||
}
|
||||
break;
|
||||
case HID_GD_X:
|
||||
if (md->valid)
|
||||
md->f[md->curid].x = value;
|
||||
break;
|
||||
case HID_GD_Y:
|
||||
if (md->valid)
|
||||
md->f[md->curid].y = value;
|
||||
break;
|
||||
case HID_DG_CONTACTCOUNT:
|
||||
if (value)
|
||||
md->nexp = value;
|
||||
if (md->nreal >= md->nexp) {
|
||||
mmm_filter_event(md, input);
|
||||
md->nreal = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* we have handled the hidinput part, now remains hiddev */
|
||||
if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
|
||||
hid->hiddev_hid_event(hid, field, usage, value);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int mmm_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
||||
{
|
||||
int ret;
|
||||
struct mmm_data *md;
|
||||
|
||||
hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC;
|
||||
|
||||
md = kzalloc(sizeof(struct mmm_data), GFP_KERNEL);
|
||||
if (!md) {
|
||||
hid_err(hdev, "cannot allocate 3M data\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
hid_set_drvdata(hdev, md);
|
||||
|
||||
ret = hid_parse(hdev);
|
||||
if (!ret)
|
||||
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
|
||||
|
||||
if (ret)
|
||||
kfree(md);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void mmm_remove(struct hid_device *hdev)
|
||||
{
|
||||
hid_hw_stop(hdev);
|
||||
kfree(hid_get_drvdata(hdev));
|
||||
hid_set_drvdata(hdev, NULL);
|
||||
}
|
||||
|
||||
static const struct hid_device_id mmm_devices[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_3M, USB_DEVICE_ID_3M1968) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_3M, USB_DEVICE_ID_3M2256) },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(hid, mmm_devices);
|
||||
|
||||
static const struct hid_usage_id mmm_grabbed_usages[] = {
|
||||
{ HID_ANY_ID, HID_ANY_ID, HID_ANY_ID },
|
||||
{ HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
|
||||
};
|
||||
|
||||
static struct hid_driver mmm_driver = {
|
||||
.name = "3m-pct",
|
||||
.id_table = mmm_devices,
|
||||
.probe = mmm_probe,
|
||||
.remove = mmm_remove,
|
||||
.input_mapping = mmm_input_mapping,
|
||||
.input_mapped = mmm_input_mapped,
|
||||
.usage_table = mmm_grabbed_usages,
|
||||
.event = mmm_event,
|
||||
};
|
||||
|
||||
static int __init mmm_init(void)
|
||||
{
|
||||
return hid_register_driver(&mmm_driver);
|
||||
}
|
||||
|
||||
static void __exit mmm_exit(void)
|
||||
{
|
||||
hid_unregister_driver(&mmm_driver);
|
||||
}
|
||||
|
||||
module_init(mmm_init);
|
||||
module_exit(mmm_exit);
|
||||
|
@ -1,276 +0,0 @@
|
||||
/*
|
||||
* HID driver for Cando dual-touch panels
|
||||
*
|
||||
* Copyright (c) 2010 Stephane Chatty <chatty@enac.fr>
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/hid.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
|
||||
MODULE_DESCRIPTION("Cando dual-touch panel");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
#include "hid-ids.h"
|
||||
|
||||
struct cando_data {
|
||||
__u16 x, y;
|
||||
__u8 id;
|
||||
__s8 oldest; /* id of the oldest finger in previous frame */
|
||||
bool valid; /* valid finger data, or just placeholder? */
|
||||
bool first; /* is this the first finger in this frame? */
|
||||
__s8 firstid; /* id of the first finger in the frame */
|
||||
__u16 firstx, firsty; /* (x, y) of the first finger in the frame */
|
||||
};
|
||||
|
||||
static int cando_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
||||
struct hid_field *field, struct hid_usage *usage,
|
||||
unsigned long **bit, int *max)
|
||||
{
|
||||
switch (usage->hid & HID_USAGE_PAGE) {
|
||||
|
||||
case HID_UP_GENDESK:
|
||||
switch (usage->hid) {
|
||||
case HID_GD_X:
|
||||
hid_map_usage(hi, usage, bit, max,
|
||||
EV_ABS, ABS_MT_POSITION_X);
|
||||
/* touchscreen emulation */
|
||||
input_set_abs_params(hi->input, ABS_X,
|
||||
field->logical_minimum,
|
||||
field->logical_maximum, 0, 0);
|
||||
return 1;
|
||||
case HID_GD_Y:
|
||||
hid_map_usage(hi, usage, bit, max,
|
||||
EV_ABS, ABS_MT_POSITION_Y);
|
||||
/* touchscreen emulation */
|
||||
input_set_abs_params(hi->input, ABS_Y,
|
||||
field->logical_minimum,
|
||||
field->logical_maximum, 0, 0);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
case HID_UP_DIGITIZER:
|
||||
switch (usage->hid) {
|
||||
case HID_DG_TIPSWITCH:
|
||||
case HID_DG_CONTACTMAX:
|
||||
return -1;
|
||||
case HID_DG_INRANGE:
|
||||
/* touchscreen emulation */
|
||||
hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
|
||||
return 1;
|
||||
case HID_DG_CONTACTID:
|
||||
hid_map_usage(hi, usage, bit, max,
|
||||
EV_ABS, ABS_MT_TRACKING_ID);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cando_input_mapped(struct hid_device *hdev, struct hid_input *hi,
|
||||
struct hid_field *field, struct hid_usage *usage,
|
||||
unsigned long **bit, int *max)
|
||||
{
|
||||
if (usage->type == EV_KEY || usage->type == EV_ABS)
|
||||
clear_bit(usage->code, *bit);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* this function is called when a whole finger has been parsed,
|
||||
* so that it can decide what to send to the input layer.
|
||||
*/
|
||||
static void cando_filter_event(struct cando_data *td, struct input_dev *input)
|
||||
{
|
||||
td->first = !td->first; /* touchscreen emulation */
|
||||
|
||||
if (!td->valid) {
|
||||
/*
|
||||
* touchscreen emulation: if this is the second finger and
|
||||
* the first was valid, the first was the oldest; if the
|
||||
* first was not valid and there was a valid finger in the
|
||||
* previous frame, this is a release.
|
||||
*/
|
||||
if (td->first) {
|
||||
td->firstid = -1;
|
||||
} else if (td->firstid >= 0) {
|
||||
input_event(input, EV_ABS, ABS_X, td->firstx);
|
||||
input_event(input, EV_ABS, ABS_Y, td->firsty);
|
||||
td->oldest = td->firstid;
|
||||
} else if (td->oldest >= 0) {
|
||||
input_event(input, EV_KEY, BTN_TOUCH, 0);
|
||||
td->oldest = -1;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
input_event(input, EV_ABS, ABS_MT_TRACKING_ID, td->id);
|
||||
input_event(input, EV_ABS, ABS_MT_POSITION_X, td->x);
|
||||
input_event(input, EV_ABS, ABS_MT_POSITION_Y, td->y);
|
||||
|
||||
input_mt_sync(input);
|
||||
|
||||
/*
|
||||
* touchscreen emulation: if there was no touching finger previously,
|
||||
* emit touch event
|
||||
*/
|
||||
if (td->oldest < 0) {
|
||||
input_event(input, EV_KEY, BTN_TOUCH, 1);
|
||||
td->oldest = td->id;
|
||||
}
|
||||
|
||||
/*
|
||||
* touchscreen emulation: if this is the first finger, wait for the
|
||||
* second; the oldest is then the second if it was the oldest already
|
||||
* or if there was no first, the first otherwise.
|
||||
*/
|
||||
if (td->first) {
|
||||
td->firstx = td->x;
|
||||
td->firsty = td->y;
|
||||
td->firstid = td->id;
|
||||
} else {
|
||||
int x, y, oldest;
|
||||
if (td->id == td->oldest || td->firstid < 0) {
|
||||
x = td->x;
|
||||
y = td->y;
|
||||
oldest = td->id;
|
||||
} else {
|
||||
x = td->firstx;
|
||||
y = td->firsty;
|
||||
oldest = td->firstid;
|
||||
}
|
||||
input_event(input, EV_ABS, ABS_X, x);
|
||||
input_event(input, EV_ABS, ABS_Y, y);
|
||||
td->oldest = oldest;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int cando_event(struct hid_device *hid, struct hid_field *field,
|
||||
struct hid_usage *usage, __s32 value)
|
||||
{
|
||||
struct cando_data *td = hid_get_drvdata(hid);
|
||||
|
||||
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_CONTACTID:
|
||||
td->id = value;
|
||||
break;
|
||||
case HID_GD_X:
|
||||
td->x = value;
|
||||
break;
|
||||
case HID_GD_Y:
|
||||
td->y = value;
|
||||
cando_filter_event(td, input);
|
||||
break;
|
||||
case HID_DG_TIPSWITCH:
|
||||
/* avoid interference from generic hidinput handling */
|
||||
break;
|
||||
|
||||
default:
|
||||
/* fallback to the generic hidinput handling */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* we have handled the hidinput part, now remains hiddev */
|
||||
if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
|
||||
hid->hiddev_hid_event(hid, field, usage, value);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int cando_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
||||
{
|
||||
int ret;
|
||||
struct cando_data *td;
|
||||
|
||||
td = kmalloc(sizeof(struct cando_data), GFP_KERNEL);
|
||||
if (!td) {
|
||||
hid_err(hdev, "cannot allocate Cando Touch data\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
hid_set_drvdata(hdev, td);
|
||||
td->first = false;
|
||||
td->oldest = -1;
|
||||
td->valid = false;
|
||||
|
||||
ret = hid_parse(hdev);
|
||||
if (!ret)
|
||||
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
|
||||
|
||||
if (ret)
|
||||
kfree(td);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void cando_remove(struct hid_device *hdev)
|
||||
{
|
||||
hid_hw_stop(hdev);
|
||||
kfree(hid_get_drvdata(hdev));
|
||||
hid_set_drvdata(hdev, NULL);
|
||||
}
|
||||
|
||||
static const struct hid_device_id cando_devices[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
|
||||
USB_DEVICE_ID_CANDO_MULTI_TOUCH) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
|
||||
USB_DEVICE_ID_CANDO_MULTI_TOUCH_10_1) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
|
||||
USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
|
||||
USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(hid, cando_devices);
|
||||
|
||||
static const struct hid_usage_id cando_grabbed_usages[] = {
|
||||
{ HID_ANY_ID, HID_ANY_ID, HID_ANY_ID },
|
||||
{ HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
|
||||
};
|
||||
|
||||
static struct hid_driver cando_driver = {
|
||||
.name = "cando-touch",
|
||||
.id_table = cando_devices,
|
||||
.probe = cando_probe,
|
||||
.remove = cando_remove,
|
||||
.input_mapping = cando_input_mapping,
|
||||
.input_mapped = cando_input_mapped,
|
||||
.usage_table = cando_grabbed_usages,
|
||||
.event = cando_event,
|
||||
};
|
||||
|
||||
static int __init cando_init(void)
|
||||
{
|
||||
return hid_register_driver(&cando_driver);
|
||||
}
|
||||
|
||||
static void __exit cando_exit(void)
|
||||
{
|
||||
hid_unregister_driver(&cando_driver);
|
||||
}
|
||||
|
||||
module_init(cando_init);
|
||||
module_exit(cando_exit);
|
||||
|
@ -1045,6 +1045,9 @@ void hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
|
||||
|
||||
rsize = ((report->size - 1) >> 3) + 1;
|
||||
|
||||
if (rsize > HID_MAX_BUFFER_SIZE)
|
||||
rsize = HID_MAX_BUFFER_SIZE;
|
||||
|
||||
if (csize < rsize) {
|
||||
dbg_hid("report %d is too short, (%d < %d)\n", report->id,
|
||||
csize, rsize);
|
||||
@ -1290,6 +1293,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_RP_649) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0x0802) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ACTIONSTAR, USB_DEVICE_ID_ACTIONSTAR_1011) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ATV_IRCONTROL) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE) },
|
||||
@ -1356,6 +1360,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CVTOUCH, USB_DEVICE_ID_CVTOUCH_SCREEN) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_3) },
|
||||
@ -1369,17 +1374,20 @@ static const struct hid_device_id hid_have_special_driver[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH3) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH4) },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2515) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_EMS, USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II) },
|
||||
{ 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) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_GOODTOUCH, USB_DEVICE_ID_GOODTOUCH_000f) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0012) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_HANVON, USB_DEVICE_ID_HANVON_MULTITOUCH) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ILITEK, USB_DEVICE_ID_ILITEK_MULTITOUCH) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_IRTOUCHSYSTEMS, USB_DEVICE_ID_IRTOUCH_INFRARED_USB) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_KEYTOUCH, USB_DEVICE_ID_KEYTOUCH_IEC) },
|
||||
@ -1408,10 +1416,12 @@ static const struct hid_device_id hid_have_special_driver[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFP_WHEEL) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G27_WHEEL) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WII_WHEEL) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACETRAVELLER) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACENAVIGATOR) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LUMIO, USB_DEVICE_ID_CRYSTALTOUCH) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD_BOOTLOADER) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV) },
|
||||
@ -1441,6 +1451,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_18) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_PKB1700) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_PCI) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN) },
|
||||
@ -1454,6 +1465,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SKYCABLE, USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER) },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_STANTUM, USB_DEVICE_ID_MTP) },
|
||||
@ -1470,12 +1482,15 @@ static const struct hid_device_id hid_have_special_driver[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb65a) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED2, USB_DEVICE_ID_TOPSEED2_RF_COMBO) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_TOUCH_INTL, USB_DEVICE_ID_TOUCH_INTL_MULTI_TOUCH) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_TWINHAN, USB_DEVICE_ID_TWINHAN_IR_REMOTE) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_UNITEC, USB_DEVICE_ID_UNITEC_USB_TOUCH_0709) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_UNITEC, USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH) },
|
||||
|
@ -37,6 +37,9 @@
|
||||
|
||||
#define USB_VENDOR_ID_ACRUX 0x1a34
|
||||
|
||||
#define USB_VENDOR_ID_ACTIONSTAR 0x2101
|
||||
#define USB_DEVICE_ID_ACTIONSTAR_1011 0x1011
|
||||
|
||||
#define USB_VENDOR_ID_ADS_TECH 0x06e1
|
||||
#define USB_DEVICE_ID_ADS_TECH_RADIO_SI470X 0xa155
|
||||
|
||||
@ -182,6 +185,9 @@
|
||||
#define USB_VENDOR_ID_CREATIVELABS 0x041e
|
||||
#define USB_DEVICE_ID_PRODIKEYS_PCMIDI 0x2801
|
||||
|
||||
#define USB_VENDOR_ID_CVTOUCH 0x1ff7
|
||||
#define USB_DEVICE_ID_CVTOUCH_SCREEN 0x0013
|
||||
|
||||
#define USB_VENDOR_ID_CYGNAL 0x10c4
|
||||
#define USB_DEVICE_ID_CYGNAL_RADIO_SI470X 0x818a
|
||||
|
||||
@ -220,6 +226,7 @@
|
||||
#define USB_VENDOR_ID_DREAM_CHEEKY 0x1d34
|
||||
|
||||
#define USB_VENDOR_ID_ELO 0x04E7
|
||||
#define USB_DEVICE_ID_ELO_TS2515 0x0022
|
||||
#define USB_DEVICE_ID_ELO_TS2700 0x0020
|
||||
|
||||
#define USB_VENDOR_ID_EMS 0x2006
|
||||
@ -255,6 +262,9 @@
|
||||
#define USB_DEVICE_ID_0_8_8_IF_KIT 0x0053
|
||||
#define USB_DEVICE_ID_PHIDGET_MOTORCONTROL 0x0058
|
||||
|
||||
#define USB_VENDOR_ID_GOODTOUCH 0x1aad
|
||||
#define USB_DEVICE_ID_GOODTOUCH_000f 0x000f
|
||||
|
||||
#define USB_VENDOR_ID_GOTOP 0x08f2
|
||||
#define USB_DEVICE_ID_SUPER_Q2 0x007f
|
||||
#define USB_DEVICE_ID_GOGOPEN 0x00ce
|
||||
@ -334,6 +344,9 @@
|
||||
#define USB_DEVICE_ID_UGCI_FLYING 0x0020
|
||||
#define USB_DEVICE_ID_UGCI_FIGHTING 0x0030
|
||||
|
||||
#define USB_VENDOR_ID_ILITEK 0x222a
|
||||
#define USB_DEVICE_ID_ILITEK_MULTITOUCH 0x0001
|
||||
|
||||
#define USB_VENDOR_ID_IMATION 0x0718
|
||||
#define USB_DEVICE_ID_DISC_STAKKA 0xd000
|
||||
|
||||
@ -398,6 +411,7 @@
|
||||
#define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL 0xc295
|
||||
#define USB_DEVICE_ID_LOGITECH_DFP_WHEEL 0xc298
|
||||
#define USB_DEVICE_ID_LOGITECH_G25_WHEEL 0xc299
|
||||
#define USB_DEVICE_ID_LOGITECH_G27_WHEEL 0xc29b
|
||||
#define USB_DEVICE_ID_LOGITECH_WII_WHEEL 0xc29c
|
||||
#define USB_DEVICE_ID_LOGITECH_ELITE_KBD 0xc30a
|
||||
#define USB_DEVICE_ID_S510_RECEIVER 0xc50c
|
||||
@ -411,6 +425,9 @@
|
||||
#define USB_DEVICE_ID_DINOVO_MINI 0xc71f
|
||||
#define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2 0xca03
|
||||
|
||||
#define USB_VENDOR_ID_LUMIO 0x202e
|
||||
#define USB_DEVICE_ID_CRYSTALTOUCH 0x0006
|
||||
|
||||
#define USB_VENDOR_ID_MCC 0x09db
|
||||
#define USB_DEVICE_ID_MCC_PMD1024LS 0x0076
|
||||
#define USB_DEVICE_ID_MCC_PMD1208LS 0x007a
|
||||
@ -488,6 +505,9 @@
|
||||
#define USB_VENDOR_ID_PANTHERLORD 0x0810
|
||||
#define USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK 0x0001
|
||||
|
||||
#define USB_VENDOR_ID_PENMOUNT 0x14e1
|
||||
#define USB_DEVICE_ID_PENMOUNT_PCI 0x3500
|
||||
|
||||
#define USB_VENDOR_ID_PETALYNX 0x18b1
|
||||
#define USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE 0x0037
|
||||
|
||||
@ -531,6 +551,7 @@
|
||||
#define USB_VENDOR_ID_SONY 0x054c
|
||||
#define USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE 0x024b
|
||||
#define USB_DEVICE_ID_SONY_PS3_CONTROLLER 0x0268
|
||||
#define USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER 0x042f
|
||||
|
||||
#define USB_VENDOR_ID_SOUNDGRAPH 0x15c2
|
||||
#define USB_DEVICE_ID_SOUNDGRAPH_IMON_FIRST 0x0034
|
||||
@ -551,6 +572,10 @@
|
||||
#define USB_VENDOR_ID_SUNPLUS 0x04fc
|
||||
#define USB_DEVICE_ID_SUNPLUS_WDESKTOP 0x05d8
|
||||
|
||||
#define USB_VENDOR_ID_SYMBOL 0x05e0
|
||||
#define USB_DEVICE_ID_SYMBOL_SCANNER_1 0x0800
|
||||
#define USB_DEVICE_ID_SYMBOL_SCANNER_2 0x1300
|
||||
|
||||
#define USB_VENDOR_ID_THRUSTMASTER 0x044f
|
||||
|
||||
#define USB_VENDOR_ID_TOPSEED 0x0766
|
||||
@ -562,6 +587,9 @@
|
||||
#define USB_VENDOR_ID_TOPMAX 0x0663
|
||||
#define USB_DEVICE_ID_TOPMAX_COBRAPAD 0x0103
|
||||
|
||||
#define USB_VENDOR_ID_TOUCH_INTL 0x1e5e
|
||||
#define USB_DEVICE_ID_TOUCH_INTL_MULTI_TOUCH 0x0313
|
||||
|
||||
#define USB_VENDOR_ID_TOUCHPACK 0x1bfd
|
||||
#define USB_DEVICE_ID_TOUCHPACK_RTS 0x1688
|
||||
|
||||
@ -579,6 +607,10 @@
|
||||
#define USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U 0x0004
|
||||
#define USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U 0x0005
|
||||
|
||||
#define USB_VENDOR_ID_UNITEC 0x227d
|
||||
#define USB_DEVICE_ID_UNITEC_USB_TOUCH_0709 0x0709
|
||||
#define USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19 0x0a19
|
||||
|
||||
#define USB_VENDOR_ID_VERNIER 0x08f7
|
||||
#define USB_DEVICE_ID_VERNIER_LABPRO 0x0001
|
||||
#define USB_DEVICE_ID_VERNIER_GOTEMP 0x0002
|
||||
|
@ -44,11 +44,11 @@ static const unsigned char hid_keyboard[256] = {
|
||||
72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190,
|
||||
191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113,
|
||||
115,114,unk,unk,unk,121,unk, 89, 93,124, 92, 94, 95,unk,unk,unk,
|
||||
122,123, 90, 91, 85,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
|
||||
122,123, 90, 91, 85,unk,unk,unk,unk,unk,unk,unk,111,unk,unk,unk,
|
||||
unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
|
||||
unk,unk,unk,unk,unk,unk,179,180,unk,unk,unk,unk,unk,unk,unk,unk,
|
||||
unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
|
||||
unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
|
||||
unk,unk,unk,unk,unk,unk,unk,unk,111,unk,unk,unk,unk,unk,unk,unk,
|
||||
29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,
|
||||
150,158,159,128,136,177,178,176,142,152,173,140,unk,unk,unk,unk
|
||||
};
|
||||
@ -357,6 +357,18 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
|
||||
case 0x1: map_key_clear(KEY_POWER); break;
|
||||
case 0x2: map_key_clear(KEY_SLEEP); break;
|
||||
case 0x3: map_key_clear(KEY_WAKEUP); break;
|
||||
case 0x4: map_key_clear(KEY_CONTEXT_MENU); break;
|
||||
case 0x5: map_key_clear(KEY_MENU); break;
|
||||
case 0x6: map_key_clear(KEY_PROG1); break;
|
||||
case 0x7: map_key_clear(KEY_HELP); break;
|
||||
case 0x8: map_key_clear(KEY_EXIT); break;
|
||||
case 0x9: map_key_clear(KEY_SELECT); break;
|
||||
case 0xa: map_key_clear(KEY_RIGHT); break;
|
||||
case 0xb: map_key_clear(KEY_LEFT); break;
|
||||
case 0xc: map_key_clear(KEY_UP); break;
|
||||
case 0xd: map_key_clear(KEY_DOWN); break;
|
||||
case 0xe: map_key_clear(KEY_POWER2); break;
|
||||
case 0xf: map_key_clear(KEY_RESTART); break;
|
||||
default: goto unknown;
|
||||
}
|
||||
break;
|
||||
@ -466,16 +478,39 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
|
||||
}
|
||||
break;
|
||||
|
||||
case HID_UP_CONSUMER: /* USB HUT v1.1, pages 56-62 */
|
||||
case HID_UP_CONSUMER: /* USB HUT v1.12, pages 75-84 */
|
||||
switch (usage->hid & HID_USAGE) {
|
||||
case 0x000: goto ignore;
|
||||
case 0x030: map_key_clear(KEY_POWER); break;
|
||||
case 0x031: map_key_clear(KEY_RESTART); break;
|
||||
case 0x032: map_key_clear(KEY_SLEEP); break;
|
||||
case 0x034: map_key_clear(KEY_SLEEP); break;
|
||||
case 0x035: map_key_clear(KEY_KBDILLUMTOGGLE); break;
|
||||
case 0x036: map_key_clear(BTN_MISC); break;
|
||||
|
||||
case 0x040: map_key_clear(KEY_MENU); break;
|
||||
case 0x045: map_key_clear(KEY_RADIO); break;
|
||||
case 0x040: map_key_clear(KEY_MENU); break; /* Menu */
|
||||
case 0x041: map_key_clear(KEY_SELECT); break; /* Menu Pick */
|
||||
case 0x042: map_key_clear(KEY_UP); break; /* Menu Up */
|
||||
case 0x043: map_key_clear(KEY_DOWN); break; /* Menu Down */
|
||||
case 0x044: map_key_clear(KEY_LEFT); break; /* Menu Left */
|
||||
case 0x045: map_key_clear(KEY_RIGHT); break; /* Menu Right */
|
||||
case 0x046: map_key_clear(KEY_ESC); break; /* Menu Escape */
|
||||
case 0x047: map_key_clear(KEY_KPPLUS); break; /* Menu Value Increase */
|
||||
case 0x048: map_key_clear(KEY_KPMINUS); break; /* Menu Value Decrease */
|
||||
|
||||
case 0x060: map_key_clear(KEY_INFO); break; /* Data On Screen */
|
||||
case 0x061: map_key_clear(KEY_SUBTITLE); break; /* Closed Caption */
|
||||
case 0x063: map_key_clear(KEY_VCR); break; /* VCR/TV */
|
||||
case 0x065: map_key_clear(KEY_CAMERA); break; /* Snapshot */
|
||||
case 0x069: map_key_clear(KEY_RED); break;
|
||||
case 0x06a: map_key_clear(KEY_GREEN); break;
|
||||
case 0x06b: map_key_clear(KEY_BLUE); break;
|
||||
case 0x06c: map_key_clear(KEY_YELLOW); break;
|
||||
case 0x06d: map_key_clear(KEY_ZOOM); break;
|
||||
|
||||
case 0x082: map_key_clear(KEY_VIDEO_NEXT); break;
|
||||
case 0x083: map_key_clear(KEY_LAST); break;
|
||||
case 0x084: map_key_clear(KEY_ENTER); break;
|
||||
case 0x088: map_key_clear(KEY_PC); break;
|
||||
case 0x089: map_key_clear(KEY_TV); break;
|
||||
case 0x08a: map_key_clear(KEY_WWW); break;
|
||||
@ -509,6 +544,8 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
|
||||
case 0x0b7: map_key_clear(KEY_STOPCD); break;
|
||||
case 0x0b8: map_key_clear(KEY_EJECTCD); break;
|
||||
case 0x0bc: map_key_clear(KEY_MEDIA_REPEAT); break;
|
||||
case 0x0b9: map_key_clear(KEY_SHUFFLE); break;
|
||||
case 0x0bf: map_key_clear(KEY_SLOW); break;
|
||||
|
||||
case 0x0cd: map_key_clear(KEY_PLAYPAUSE); break;
|
||||
case 0x0e0: map_abs_clear(ABS_VOLUME); break;
|
||||
@ -516,6 +553,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
|
||||
case 0x0e5: map_key_clear(KEY_BASSBOOST); break;
|
||||
case 0x0e9: map_key_clear(KEY_VOLUMEUP); break;
|
||||
case 0x0ea: map_key_clear(KEY_VOLUMEDOWN); break;
|
||||
case 0x0f5: map_key_clear(KEY_SLOW); break;
|
||||
|
||||
case 0x182: map_key_clear(KEY_BOOKMARKS); break;
|
||||
case 0x183: map_key_clear(KEY_CONFIG); break;
|
||||
@ -532,6 +570,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
|
||||
case 0x18e: map_key_clear(KEY_CALENDAR); break;
|
||||
case 0x191: map_key_clear(KEY_FINANCE); break;
|
||||
case 0x192: map_key_clear(KEY_CALC); break;
|
||||
case 0x193: map_key_clear(KEY_PLAYER); break;
|
||||
case 0x194: map_key_clear(KEY_FILE); break;
|
||||
case 0x196: map_key_clear(KEY_WWW); break;
|
||||
case 0x199: map_key_clear(KEY_CHAT); break;
|
||||
@ -540,8 +579,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
|
||||
case 0x1a6: map_key_clear(KEY_HELP); break;
|
||||
case 0x1a7: map_key_clear(KEY_DOCUMENTS); break;
|
||||
case 0x1ab: map_key_clear(KEY_SPELLCHECK); break;
|
||||
case 0x1b6: map_key_clear(KEY_MEDIA); break;
|
||||
case 0x1b7: map_key_clear(KEY_SOUND); break;
|
||||
case 0x1ae: map_key_clear(KEY_KEYBOARD); break;
|
||||
case 0x1b6: map_key_clear(KEY_IMAGES); break;
|
||||
case 0x1b7: map_key_clear(KEY_AUDIO); break;
|
||||
case 0x1b8: map_key_clear(KEY_VIDEO); break;
|
||||
case 0x1bc: map_key_clear(KEY_MESSENGER); break;
|
||||
case 0x1bd: map_key_clear(KEY_INFO); break;
|
||||
case 0x201: map_key_clear(KEY_NEW); break;
|
||||
@ -570,7 +611,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
|
||||
case 0x233: map_key_clear(KEY_SCROLLUP); break;
|
||||
case 0x234: map_key_clear(KEY_SCROLLDOWN); break;
|
||||
case 0x238: map_rel(REL_HWHEEL); break;
|
||||
case 0x23d: map_key_clear(KEY_EDIT); break;
|
||||
case 0x25f: map_key_clear(KEY_CANCEL); break;
|
||||
case 0x269: map_key_clear(KEY_INSERT); break;
|
||||
case 0x26a: map_key_clear(KEY_DELETE); break;
|
||||
case 0x279: map_key_clear(KEY_REDO); break;
|
||||
|
||||
case 0x289: map_key_clear(KEY_REPLY); break;
|
||||
|
@ -377,6 +377,8 @@ static const struct hid_device_id lg_devices[] = {
|
||||
.driver_data = LG_FF },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL),
|
||||
.driver_data = LG_FF },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G27_WHEEL),
|
||||
.driver_data = LG_FF },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFP_WHEEL),
|
||||
.driver_data = LG_FF },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WII_WHEEL),
|
||||
|
@ -72,6 +72,9 @@ static const struct dev_type devices[] = {
|
||||
{ 0x046d, 0xc287, ff_joystick_ac },
|
||||
{ 0x046d, 0xc293, ff_joystick },
|
||||
{ 0x046d, 0xc294, ff_wheel },
|
||||
{ 0x046d, 0xc298, ff_wheel },
|
||||
{ 0x046d, 0xc299, ff_wheel },
|
||||
{ 0x046d, 0xc29b, ff_wheel },
|
||||
{ 0x046d, 0xc295, ff_joystick },
|
||||
{ 0x046d, 0xc298, ff_wheel },
|
||||
{ 0x046d, 0xc299, ff_wheel },
|
||||
|
@ -501,9 +501,17 @@ static int magicmouse_probe(struct hid_device *hdev,
|
||||
}
|
||||
report->size = 6;
|
||||
|
||||
/*
|
||||
* The device reponds with 'invalid report id' when feature
|
||||
* report switching it into multitouch mode is sent to it.
|
||||
*
|
||||
* This results in -EIO from the _raw low-level transport callback,
|
||||
* but there seems to be no other way of switching the mode.
|
||||
* Thus the super-ugly hacky success check below.
|
||||
*/
|
||||
ret = hdev->hid_output_raw_report(hdev, feature, sizeof(feature),
|
||||
HID_FEATURE_REPORT);
|
||||
if (ret != sizeof(feature)) {
|
||||
if (ret != -EIO) {
|
||||
hid_err(hdev, "unable to request touch data (%d)\n", ret);
|
||||
goto err_stop_hw;
|
||||
}
|
||||
|
@ -1,296 +0,0 @@
|
||||
/*
|
||||
* HID driver for the multitouch panel on the ASUS EeePC T91MT
|
||||
*
|
||||
* Copyright (c) 2009-2010 Stephane Chatty <chatty@enac.fr>
|
||||
* Copyright (c) 2010 Teemu Tuominen <teemu.tuominen@cybercom.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/hid.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/usb.h>
|
||||
#include "usbhid/usbhid.h"
|
||||
|
||||
MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
|
||||
MODULE_DESCRIPTION("MosArt dual-touch panel");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
#include "hid-ids.h"
|
||||
|
||||
struct mosart_data {
|
||||
__u16 x, y;
|
||||
__u8 id;
|
||||
bool valid; /* valid finger data, or just placeholder? */
|
||||
bool first; /* is this the first finger in this frame? */
|
||||
bool activity_now; /* at least one active finger in this frame? */
|
||||
bool activity; /* at least one active finger previously? */
|
||||
};
|
||||
|
||||
static int mosart_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
||||
struct hid_field *field, struct hid_usage *usage,
|
||||
unsigned long **bit, int *max)
|
||||
{
|
||||
switch (usage->hid & HID_USAGE_PAGE) {
|
||||
|
||||
case HID_UP_GENDESK:
|
||||
switch (usage->hid) {
|
||||
case HID_GD_X:
|
||||
hid_map_usage(hi, usage, bit, max,
|
||||
EV_ABS, ABS_MT_POSITION_X);
|
||||
/* touchscreen emulation */
|
||||
input_set_abs_params(hi->input, ABS_X,
|
||||
field->logical_minimum,
|
||||
field->logical_maximum, 0, 0);
|
||||
return 1;
|
||||
case HID_GD_Y:
|
||||
hid_map_usage(hi, usage, bit, max,
|
||||
EV_ABS, ABS_MT_POSITION_Y);
|
||||
/* touchscreen emulation */
|
||||
input_set_abs_params(hi->input, ABS_Y,
|
||||
field->logical_minimum,
|
||||
field->logical_maximum, 0, 0);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
case HID_UP_DIGITIZER:
|
||||
switch (usage->hid) {
|
||||
case HID_DG_CONFIDENCE:
|
||||
case HID_DG_TIPSWITCH:
|
||||
case HID_DG_INPUTMODE:
|
||||
case HID_DG_DEVICEINDEX:
|
||||
case HID_DG_CONTACTCOUNT:
|
||||
case HID_DG_CONTACTMAX:
|
||||
case HID_DG_TIPPRESSURE:
|
||||
case HID_DG_WIDTH:
|
||||
case HID_DG_HEIGHT:
|
||||
return -1;
|
||||
case HID_DG_INRANGE:
|
||||
/* touchscreen emulation */
|
||||
hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
|
||||
return 1;
|
||||
|
||||
case HID_DG_CONTACTID:
|
||||
hid_map_usage(hi, usage, bit, max,
|
||||
EV_ABS, ABS_MT_TRACKING_ID);
|
||||
return 1;
|
||||
|
||||
}
|
||||
return 0;
|
||||
|
||||
case 0xff000000:
|
||||
/* ignore HID features */
|
||||
return -1;
|
||||
|
||||
case HID_UP_BUTTON:
|
||||
/* ignore buttons */
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mosart_input_mapped(struct hid_device *hdev, struct hid_input *hi,
|
||||
struct hid_field *field, struct hid_usage *usage,
|
||||
unsigned long **bit, int *max)
|
||||
{
|
||||
if (usage->type == EV_KEY || usage->type == EV_ABS)
|
||||
clear_bit(usage->code, *bit);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* this function is called when a whole finger has been parsed,
|
||||
* so that it can decide what to send to the input layer.
|
||||
*/
|
||||
static void mosart_filter_event(struct mosart_data *td, struct input_dev *input)
|
||||
{
|
||||
td->first = !td->first; /* touchscreen emulation */
|
||||
|
||||
if (!td->valid) {
|
||||
/*
|
||||
* touchscreen emulation: if no finger in this frame is valid
|
||||
* and there previously was finger activity, this is a release
|
||||
*/
|
||||
if (!td->first && !td->activity_now && td->activity) {
|
||||
input_event(input, EV_KEY, BTN_TOUCH, 0);
|
||||
td->activity = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
input_event(input, EV_ABS, ABS_MT_TRACKING_ID, td->id);
|
||||
input_event(input, EV_ABS, ABS_MT_POSITION_X, td->x);
|
||||
input_event(input, EV_ABS, ABS_MT_POSITION_Y, td->y);
|
||||
|
||||
input_mt_sync(input);
|
||||
td->valid = false;
|
||||
|
||||
/* touchscreen emulation: if first active finger in this frame... */
|
||||
if (!td->activity_now) {
|
||||
/* if there was no previous activity, emit touch event */
|
||||
if (!td->activity) {
|
||||
input_event(input, EV_KEY, BTN_TOUCH, 1);
|
||||
td->activity = true;
|
||||
}
|
||||
td->activity_now = true;
|
||||
/* and in any case this is our preferred finger */
|
||||
input_event(input, EV_ABS, ABS_X, td->x);
|
||||
input_event(input, EV_ABS, ABS_Y, td->y);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int mosart_event(struct hid_device *hid, struct hid_field *field,
|
||||
struct hid_usage *usage, __s32 value)
|
||||
{
|
||||
struct mosart_data *td = hid_get_drvdata(hid);
|
||||
|
||||
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_GD_X:
|
||||
td->x = value;
|
||||
break;
|
||||
case HID_GD_Y:
|
||||
td->y = value;
|
||||
mosart_filter_event(td, input);
|
||||
break;
|
||||
case HID_DG_CONTACTID:
|
||||
td->id = value;
|
||||
break;
|
||||
case HID_DG_CONTACTCOUNT:
|
||||
/* touch emulation: this is the last field in a frame */
|
||||
td->first = false;
|
||||
td->activity_now = false;
|
||||
break;
|
||||
case HID_DG_CONFIDENCE:
|
||||
case HID_DG_TIPSWITCH:
|
||||
/* avoid interference from generic hidinput handling */
|
||||
break;
|
||||
|
||||
default:
|
||||
/* fallback to the generic hidinput handling */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* we have handled the hidinput part, now remains hiddev */
|
||||
if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
|
||||
hid->hiddev_hid_event(hid, field, usage, value);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int mosart_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
||||
{
|
||||
int ret;
|
||||
struct mosart_data *td;
|
||||
|
||||
|
||||
td = kmalloc(sizeof(struct mosart_data), GFP_KERNEL);
|
||||
if (!td) {
|
||||
hid_err(hdev, "cannot allocate MosArt data\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
td->valid = false;
|
||||
td->activity = false;
|
||||
td->activity_now = false;
|
||||
td->first = false;
|
||||
hid_set_drvdata(hdev, td);
|
||||
|
||||
/* currently, it's better to have one evdev device only */
|
||||
#if 0
|
||||
hdev->quirks |= HID_QUIRK_MULTI_INPUT;
|
||||
#endif
|
||||
|
||||
ret = hid_parse(hdev);
|
||||
if (ret == 0)
|
||||
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
|
||||
|
||||
if (ret == 0) {
|
||||
struct hid_report_enum *re = hdev->report_enum
|
||||
+ HID_FEATURE_REPORT;
|
||||
struct hid_report *r = re->report_id_hash[7];
|
||||
|
||||
r->field[0]->value[0] = 0x02;
|
||||
usbhid_submit_report(hdev, r, USB_DIR_OUT);
|
||||
} else
|
||||
kfree(td);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int mosart_reset_resume(struct hid_device *hdev)
|
||||
{
|
||||
struct hid_report_enum *re = hdev->report_enum
|
||||
+ HID_FEATURE_REPORT;
|
||||
struct hid_report *r = re->report_id_hash[7];
|
||||
|
||||
r->field[0]->value[0] = 0x02;
|
||||
usbhid_submit_report(hdev, r, USB_DIR_OUT);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void mosart_remove(struct hid_device *hdev)
|
||||
{
|
||||
hid_hw_stop(hdev);
|
||||
kfree(hid_get_drvdata(hdev));
|
||||
hid_set_drvdata(hdev, NULL);
|
||||
}
|
||||
|
||||
static const struct hid_device_id mosart_devices[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_T91MT) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART) },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(hid, mosart_devices);
|
||||
|
||||
static const struct hid_usage_id mosart_grabbed_usages[] = {
|
||||
{ HID_ANY_ID, HID_ANY_ID, HID_ANY_ID },
|
||||
{ HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
|
||||
};
|
||||
|
||||
static struct hid_driver mosart_driver = {
|
||||
.name = "mosart",
|
||||
.id_table = mosart_devices,
|
||||
.probe = mosart_probe,
|
||||
.remove = mosart_remove,
|
||||
.input_mapping = mosart_input_mapping,
|
||||
.input_mapped = mosart_input_mapped,
|
||||
.usage_table = mosart_grabbed_usages,
|
||||
.event = mosart_event,
|
||||
#ifdef CONFIG_PM
|
||||
.reset_resume = mosart_reset_resume,
|
||||
#endif
|
||||
};
|
||||
|
||||
static int __init mosart_init(void)
|
||||
{
|
||||
return hid_register_driver(&mosart_driver);
|
||||
}
|
||||
|
||||
static void __exit mosart_exit(void)
|
||||
{
|
||||
hid_unregister_driver(&mosart_driver);
|
||||
}
|
||||
|
||||
module_init(mosart_init);
|
||||
module_exit(mosart_exit);
|
||||
|
@ -11,6 +11,12 @@
|
||||
* Copyright (c) 2010 Henrik Rydberg <rydberg@euromail.se>
|
||||
* Copyright (c) 2010 Canonical, Ltd.
|
||||
*
|
||||
* This code is partly based on hid-3m-pct.c:
|
||||
*
|
||||
* Copyright (c) 2009-2010 Stephane Chatty <chatty@enac.fr>
|
||||
* Copyright (c) 2010 Henrik Rydberg <rydberg@euromail.se>
|
||||
* Copyright (c) 2010 Canonical, Ltd.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -44,6 +50,7 @@ MODULE_LICENSE("GPL");
|
||||
#define MT_QUIRK_VALID_IS_INRANGE (1 << 4)
|
||||
#define MT_QUIRK_VALID_IS_CONFIDENCE (1 << 5)
|
||||
#define MT_QUIRK_EGALAX_XYZ_FIXUP (1 << 6)
|
||||
#define MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE (1 << 7)
|
||||
|
||||
struct mt_slot {
|
||||
__s32 x, y, p, w, h;
|
||||
@ -60,24 +67,36 @@ struct mt_device {
|
||||
__s8 inputmode; /* InputMode HID feature, -1 if non-existent */
|
||||
__u8 num_received; /* how many contacts we received */
|
||||
__u8 num_expected; /* expected last contact index */
|
||||
__u8 maxcontacts;
|
||||
bool curvalid; /* is the current contact valid? */
|
||||
struct mt_slot slots[0]; /* first slot */
|
||||
struct mt_slot *slots;
|
||||
};
|
||||
|
||||
struct mt_class {
|
||||
__s32 name; /* MT_CLS */
|
||||
__s32 quirks;
|
||||
__s32 sn_move; /* Signal/noise ratio for move events */
|
||||
__s32 sn_width; /* Signal/noise ratio for width events */
|
||||
__s32 sn_height; /* Signal/noise ratio for height events */
|
||||
__s32 sn_pressure; /* Signal/noise ratio for pressure events */
|
||||
__u8 maxcontacts;
|
||||
};
|
||||
|
||||
/* classes of device behavior */
|
||||
#define MT_CLS_DEFAULT 1
|
||||
#define MT_CLS_DUAL_INRANGE_CONTACTID 2
|
||||
#define MT_CLS_DUAL_INRANGE_CONTACTNUMBER 3
|
||||
#define MT_CLS_CYPRESS 4
|
||||
#define MT_CLS_EGALAX 5
|
||||
#define MT_CLS_DEFAULT 0x0001
|
||||
|
||||
#define MT_CLS_CONFIDENCE 0x0002
|
||||
#define MT_CLS_CONFIDENCE_MINUS_ONE 0x0003
|
||||
#define MT_CLS_DUAL_INRANGE_CONTACTID 0x0004
|
||||
#define MT_CLS_DUAL_INRANGE_CONTACTNUMBER 0x0005
|
||||
#define MT_CLS_DUAL_NSMU_CONTACTID 0x0006
|
||||
|
||||
/* vendor specific classes */
|
||||
#define MT_CLS_3M 0x0101
|
||||
#define MT_CLS_CYPRESS 0x0102
|
||||
#define MT_CLS_EGALAX 0x0103
|
||||
|
||||
#define MT_DEFAULT_MAXCONTACT 10
|
||||
|
||||
/*
|
||||
* these device-dependent functions determine what slot corresponds
|
||||
@ -95,12 +114,12 @@ static int cypress_compute_slot(struct mt_device *td)
|
||||
static int find_slot_from_contactid(struct mt_device *td)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < td->mtclass->maxcontacts; ++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->mtclass->maxcontacts; ++i) {
|
||||
for (i = 0; i < td->maxcontacts; ++i) {
|
||||
if (!td->slots[i].seen_in_this_frame &&
|
||||
!td->slots[i].touch_state)
|
||||
return i;
|
||||
@ -113,8 +132,12 @@ static int find_slot_from_contactid(struct mt_device *td)
|
||||
|
||||
struct mt_class mt_classes[] = {
|
||||
{ .name = MT_CLS_DEFAULT,
|
||||
.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP,
|
||||
.maxcontacts = 10 },
|
||||
.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP },
|
||||
{ .name = MT_CLS_CONFIDENCE,
|
||||
.quirks = MT_QUIRK_VALID_IS_CONFIDENCE },
|
||||
{ .name = MT_CLS_CONFIDENCE_MINUS_ONE,
|
||||
.quirks = MT_QUIRK_VALID_IS_CONFIDENCE |
|
||||
MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE },
|
||||
{ .name = MT_CLS_DUAL_INRANGE_CONTACTID,
|
||||
.quirks = MT_QUIRK_VALID_IS_INRANGE |
|
||||
MT_QUIRK_SLOT_IS_CONTACTID,
|
||||
@ -123,11 +146,24 @@ struct mt_class mt_classes[] = {
|
||||
.quirks = MT_QUIRK_VALID_IS_INRANGE |
|
||||
MT_QUIRK_SLOT_IS_CONTACTNUMBER,
|
||||
.maxcontacts = 2 },
|
||||
{ .name = MT_CLS_DUAL_NSMU_CONTACTID,
|
||||
.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP |
|
||||
MT_QUIRK_SLOT_IS_CONTACTID,
|
||||
.maxcontacts = 2 },
|
||||
|
||||
/*
|
||||
* vendor specific classes
|
||||
*/
|
||||
{ .name = MT_CLS_3M,
|
||||
.quirks = MT_QUIRK_VALID_IS_CONFIDENCE |
|
||||
MT_QUIRK_SLOT_IS_CONTACTID,
|
||||
.sn_move = 2048,
|
||||
.sn_width = 128,
|
||||
.sn_height = 128 },
|
||||
{ .name = MT_CLS_CYPRESS,
|
||||
.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP |
|
||||
MT_QUIRK_CYPRESS,
|
||||
.maxcontacts = 10 },
|
||||
|
||||
{ .name = MT_CLS_EGALAX,
|
||||
.quirks = MT_QUIRK_SLOT_IS_CONTACTID |
|
||||
MT_QUIRK_VALID_IS_INRANGE |
|
||||
@ -136,15 +172,26 @@ struct mt_class mt_classes[] = {
|
||||
.sn_move = 4096,
|
||||
.sn_pressure = 32,
|
||||
},
|
||||
|
||||
{ }
|
||||
};
|
||||
|
||||
static void mt_feature_mapping(struct hid_device *hdev,
|
||||
struct hid_field *field, struct hid_usage *usage)
|
||||
{
|
||||
if (usage->hid == HID_DG_INPUTMODE) {
|
||||
struct mt_device *td = hid_get_drvdata(hdev);
|
||||
struct mt_device *td = hid_get_drvdata(hdev);
|
||||
|
||||
switch (usage->hid) {
|
||||
case HID_DG_INPUTMODE:
|
||||
td->inputmode = field->report->id;
|
||||
break;
|
||||
case HID_DG_CONTACTMAX:
|
||||
td->maxcontacts = field->value[0];
|
||||
if (td->mtclass->maxcontacts)
|
||||
/* check if the maxcontacts is given by the class */
|
||||
td->maxcontacts = td->mtclass->maxcontacts;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -179,6 +226,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
||||
/* touchscreen emulation */
|
||||
set_abs(hi->input, ABS_X, field, cls->sn_move);
|
||||
td->last_slot_field = usage->hid;
|
||||
td->last_field_index = field->index;
|
||||
return 1;
|
||||
case HID_GD_Y:
|
||||
if (quirks & MT_QUIRK_EGALAX_XYZ_FIXUP)
|
||||
@ -190,6 +238,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
||||
/* touchscreen emulation */
|
||||
set_abs(hi->input, ABS_Y, field, cls->sn_move);
|
||||
td->last_slot_field = usage->hid;
|
||||
td->last_field_index = field->index;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@ -198,32 +247,40 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
||||
switch (usage->hid) {
|
||||
case HID_DG_INRANGE:
|
||||
td->last_slot_field = usage->hid;
|
||||
td->last_field_index = field->index;
|
||||
return 1;
|
||||
case HID_DG_CONFIDENCE:
|
||||
td->last_slot_field = usage->hid;
|
||||
td->last_field_index = field->index;
|
||||
return 1;
|
||||
case HID_DG_TIPSWITCH:
|
||||
hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
|
||||
input_set_capability(hi->input, EV_KEY, BTN_TOUCH);
|
||||
td->last_slot_field = usage->hid;
|
||||
td->last_field_index = field->index;
|
||||
return 1;
|
||||
case HID_DG_CONTACTID:
|
||||
input_mt_init_slots(hi->input,
|
||||
td->mtclass->maxcontacts);
|
||||
input_mt_init_slots(hi->input, td->maxcontacts);
|
||||
td->last_slot_field = usage->hid;
|
||||
td->last_field_index = field->index;
|
||||
return 1;
|
||||
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);
|
||||
td->last_slot_field = usage->hid;
|
||||
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);
|
||||
field->logical_maximum = 1;
|
||||
field->logical_minimum = 0;
|
||||
set_abs(hi->input, ABS_MT_ORIENTATION, field, 0);
|
||||
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);
|
||||
td->last_slot_field = usage->hid;
|
||||
td->last_field_index = field->index;
|
||||
return 1;
|
||||
case HID_DG_TIPPRESSURE:
|
||||
if (quirks & MT_QUIRK_EGALAX_XYZ_FIXUP)
|
||||
@ -236,13 +293,15 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
||||
set_abs(hi->input, ABS_PRESSURE, field,
|
||||
cls->sn_pressure);
|
||||
td->last_slot_field = usage->hid;
|
||||
td->last_field_index = field->index;
|
||||
return 1;
|
||||
case HID_DG_CONTACTCOUNT:
|
||||
td->last_field_index = field->report->maxfield - 1;
|
||||
td->last_field_index = field->index;
|
||||
return 1;
|
||||
case HID_DG_CONTACTMAX:
|
||||
/* we don't set td->last_slot_field as contactcount and
|
||||
* contact max are global to the report */
|
||||
td->last_field_index = field->index;
|
||||
return -1;
|
||||
}
|
||||
/* let hid-input decide for the others */
|
||||
@ -279,6 +338,9 @@ static int mt_compute_slot(struct mt_device *td)
|
||||
if (quirks & MT_QUIRK_SLOT_IS_CONTACTNUMBER)
|
||||
return td->num_received;
|
||||
|
||||
if (quirks & MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE)
|
||||
return td->curdata.contactid - 1;
|
||||
|
||||
return find_slot_from_contactid(td);
|
||||
}
|
||||
|
||||
@ -292,7 +354,7 @@ static void mt_complete_slot(struct mt_device *td)
|
||||
if (td->curvalid) {
|
||||
int slotnum = mt_compute_slot(td);
|
||||
|
||||
if (slotnum >= 0 && slotnum < td->mtclass->maxcontacts)
|
||||
if (slotnum >= 0 && slotnum < td->maxcontacts)
|
||||
td->slots[slotnum] = td->curdata;
|
||||
}
|
||||
td->num_received++;
|
||||
@ -307,7 +369,7 @@ static void mt_emit_event(struct mt_device *td, struct input_dev *input)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < td->mtclass->maxcontacts; ++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) {
|
||||
@ -318,11 +380,18 @@ static void mt_emit_event(struct mt_device *td, struct input_dev *input)
|
||||
input_mt_report_slot_state(input, MT_TOOL_FINGER,
|
||||
s->touch_state);
|
||||
if (s->touch_state) {
|
||||
/* this finger is on the screen */
|
||||
int wide = (s->w > s->h);
|
||||
/* divided by two to match visual scale of touch */
|
||||
int major = max(s->w, s->h) >> 1;
|
||||
int minor = min(s->w, s->h) >> 1;
|
||||
|
||||
input_event(input, EV_ABS, ABS_MT_POSITION_X, s->x);
|
||||
input_event(input, EV_ABS, ABS_MT_POSITION_Y, s->y);
|
||||
input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide);
|
||||
input_event(input, EV_ABS, ABS_MT_PRESSURE, s->p);
|
||||
input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, s->w);
|
||||
input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, s->h);
|
||||
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;
|
||||
|
||||
@ -341,7 +410,7 @@ static int mt_event(struct hid_device *hid, struct hid_field *field,
|
||||
struct mt_device *td = hid_get_drvdata(hid);
|
||||
__s32 quirks = td->mtclass->quirks;
|
||||
|
||||
if (hid->claimed & HID_CLAIMED_INPUT) {
|
||||
if (hid->claimed & HID_CLAIMED_INPUT && td->slots) {
|
||||
switch (usage->hid) {
|
||||
case HID_DG_INRANGE:
|
||||
if (quirks & MT_QUIRK_VALID_IS_INRANGE)
|
||||
@ -390,8 +459,6 @@ static int mt_event(struct hid_device *hid, struct hid_field *field,
|
||||
|
||||
if (usage->hid == td->last_slot_field) {
|
||||
mt_complete_slot(td);
|
||||
if (!td->last_field_index)
|
||||
mt_emit_event(td, field->hidinput->input);
|
||||
}
|
||||
|
||||
if (field->index == td->last_field_index
|
||||
@ -442,9 +509,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
||||
*/
|
||||
hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC;
|
||||
|
||||
td = kzalloc(sizeof(struct mt_device) +
|
||||
mtclass->maxcontacts * sizeof(struct mt_slot),
|
||||
GFP_KERNEL);
|
||||
td = kzalloc(sizeof(struct mt_device), GFP_KERNEL);
|
||||
if (!td) {
|
||||
dev_err(&hdev->dev, "cannot allocate multitouch data\n");
|
||||
return -ENOMEM;
|
||||
@ -461,6 +526,18 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
if (!td->maxcontacts)
|
||||
td->maxcontacts = MT_DEFAULT_MAXCONTACT;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
mt_set_input_mode(hdev);
|
||||
|
||||
return 0;
|
||||
@ -482,36 +559,51 @@ static void mt_remove(struct hid_device *hdev)
|
||||
{
|
||||
struct mt_device *td = hid_get_drvdata(hdev);
|
||||
hid_hw_stop(hdev);
|
||||
kfree(td->slots);
|
||||
kfree(td);
|
||||
hid_set_drvdata(hdev, NULL);
|
||||
}
|
||||
|
||||
static const struct hid_device_id mt_devices[] = {
|
||||
|
||||
/* 3M panels */
|
||||
{ .driver_data = MT_CLS_3M,
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_3M,
|
||||
USB_DEVICE_ID_3M1968) },
|
||||
{ .driver_data = MT_CLS_3M,
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_3M,
|
||||
USB_DEVICE_ID_3M2256) },
|
||||
|
||||
/* ActionStar panels */
|
||||
{ .driver_data = MT_CLS_DEFAULT,
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_ACTIONSTAR,
|
||||
USB_DEVICE_ID_ACTIONSTAR_1011) },
|
||||
|
||||
/* Cando panels */
|
||||
{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
|
||||
USB_DEVICE_ID_CANDO_MULTI_TOUCH) },
|
||||
{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
|
||||
USB_DEVICE_ID_CANDO_MULTI_TOUCH_10_1) },
|
||||
{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
|
||||
USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) },
|
||||
{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
|
||||
USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) },
|
||||
|
||||
/* CVTouch panels */
|
||||
{ .driver_data = MT_CLS_DEFAULT,
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_CVTOUCH,
|
||||
USB_DEVICE_ID_CVTOUCH_SCREEN) },
|
||||
|
||||
/* Cypress panel */
|
||||
{ .driver_data = MT_CLS_CYPRESS,
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS,
|
||||
USB_DEVICE_ID_CYPRESS_TRUETOUCH) },
|
||||
|
||||
/* GeneralTouch panel */
|
||||
{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
|
||||
USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS) },
|
||||
|
||||
/* IRTOUCH panels */
|
||||
{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID,
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_IRTOUCHSYSTEMS,
|
||||
USB_DEVICE_ID_IRTOUCH_INFRARED_USB) },
|
||||
|
||||
/* PixCir-based panels */
|
||||
{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID,
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_HANVON,
|
||||
USB_DEVICE_ID_HANVON_MULTITOUCH) },
|
||||
{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID,
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
|
||||
USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) },
|
||||
|
||||
/* Resistive eGalax devices */
|
||||
/* eGalax devices (resistive) */
|
||||
{ .driver_data = MT_CLS_EGALAX,
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
|
||||
USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH) },
|
||||
@ -519,7 +611,7 @@ static const struct hid_device_id mt_devices[] = {
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
|
||||
USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH3) },
|
||||
|
||||
/* Capacitive eGalax devices */
|
||||
/* eGalax devices (capacitive) */
|
||||
{ .driver_data = MT_CLS_EGALAX,
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
|
||||
USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1) },
|
||||
@ -530,6 +622,84 @@ static const struct hid_device_id mt_devices[] = {
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
|
||||
USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH4) },
|
||||
|
||||
/* Elo TouchSystems IntelliTouch Plus panel */
|
||||
{ .driver_data = MT_CLS_DUAL_NSMU_CONTACTID,
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_ELO,
|
||||
USB_DEVICE_ID_ELO_TS2515) },
|
||||
|
||||
/* GeneralTouch panel */
|
||||
{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
|
||||
USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS) },
|
||||
|
||||
/* GoodTouch panels */
|
||||
{ .driver_data = MT_CLS_DEFAULT,
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_GOODTOUCH,
|
||||
USB_DEVICE_ID_GOODTOUCH_000f) },
|
||||
|
||||
/* Ilitek dual touch panel */
|
||||
{ .driver_data = MT_CLS_DEFAULT,
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_ILITEK,
|
||||
USB_DEVICE_ID_ILITEK_MULTITOUCH) },
|
||||
|
||||
/* IRTOUCH panels */
|
||||
{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID,
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_IRTOUCHSYSTEMS,
|
||||
USB_DEVICE_ID_IRTOUCH_INFRARED_USB) },
|
||||
|
||||
/* Lumio panels */
|
||||
{ .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_LUMIO,
|
||||
USB_DEVICE_ID_CRYSTALTOUCH) },
|
||||
|
||||
/* MosArt panels */
|
||||
{ .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_ASUS,
|
||||
USB_DEVICE_ID_ASUS_T91MT)},
|
||||
{ .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_ASUS,
|
||||
USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO) },
|
||||
{ .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_TURBOX,
|
||||
USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART) },
|
||||
|
||||
/* PenMount panels */
|
||||
{ .driver_data = MT_CLS_CONFIDENCE,
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT,
|
||||
USB_DEVICE_ID_PENMOUNT_PCI) },
|
||||
|
||||
/* PixCir-based panels */
|
||||
{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID,
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_HANVON,
|
||||
USB_DEVICE_ID_HANVON_MULTITOUCH) },
|
||||
{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID,
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
|
||||
USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) },
|
||||
|
||||
/* Stantum panels */
|
||||
{ .driver_data = MT_CLS_CONFIDENCE,
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_STANTUM,
|
||||
USB_DEVICE_ID_MTP)},
|
||||
{ .driver_data = MT_CLS_CONFIDENCE,
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_STANTUM,
|
||||
USB_DEVICE_ID_MTP_STM)},
|
||||
{ .driver_data = MT_CLS_CONFIDENCE,
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_STANTUM,
|
||||
USB_DEVICE_ID_MTP_SITRONIX)},
|
||||
|
||||
/* Touch International panels */
|
||||
{ .driver_data = MT_CLS_DEFAULT,
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_TOUCH_INTL,
|
||||
USB_DEVICE_ID_TOUCH_INTL_MULTI_TOUCH) },
|
||||
|
||||
/* Unitec panels */
|
||||
{ .driver_data = MT_CLS_DEFAULT,
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_UNITEC,
|
||||
USB_DEVICE_ID_UNITEC_USB_TOUCH_0709) },
|
||||
{ .driver_data = MT_CLS_DEFAULT,
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_UNITEC,
|
||||
USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19) },
|
||||
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(hid, mt_devices);
|
||||
|
@ -1585,11 +1585,11 @@ static ssize_t picolcd_debug_eeprom_write(struct file *f, const char __user *u,
|
||||
memset(raw_data, 0, sizeof(raw_data));
|
||||
raw_data[0] = *off & 0xff;
|
||||
raw_data[1] = (*off >> 8) & 0xff;
|
||||
raw_data[2] = s < 20 ? s : 20;
|
||||
raw_data[2] = min((size_t)20, s);
|
||||
if (*off + raw_data[2] > 0xff)
|
||||
raw_data[2] = 0x100 - *off;
|
||||
|
||||
if (copy_from_user(raw_data+3, u, raw_data[2]))
|
||||
if (copy_from_user(raw_data+3, u, min((u8)20, raw_data[2])))
|
||||
return -EFAULT;
|
||||
resp = picolcd_send_and_wait(data->hdev, REPORT_EE_WRITE, raw_data,
|
||||
sizeof(raw_data));
|
||||
|
@ -167,28 +167,28 @@ static int koneplus_set_profile_buttons(struct usb_device *usb_dev,
|
||||
}
|
||||
|
||||
/* retval is 0-4 on success, < 0 on error */
|
||||
static int koneplus_get_startup_profile(struct usb_device *usb_dev)
|
||||
static int koneplus_get_actual_profile(struct usb_device *usb_dev)
|
||||
{
|
||||
struct koneplus_startup_profile buf;
|
||||
struct koneplus_actual_profile buf;
|
||||
int retval;
|
||||
|
||||
retval = roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_STARTUP_PROFILE,
|
||||
&buf, sizeof(struct koneplus_startup_profile));
|
||||
retval = roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_ACTUAL_PROFILE,
|
||||
&buf, sizeof(struct koneplus_actual_profile));
|
||||
|
||||
return retval ? retval : buf.startup_profile;
|
||||
return retval ? retval : buf.actual_profile;
|
||||
}
|
||||
|
||||
static int koneplus_set_startup_profile(struct usb_device *usb_dev,
|
||||
int startup_profile)
|
||||
static int koneplus_set_actual_profile(struct usb_device *usb_dev,
|
||||
int new_profile)
|
||||
{
|
||||
struct koneplus_startup_profile buf;
|
||||
struct koneplus_actual_profile buf;
|
||||
|
||||
buf.command = KONEPLUS_COMMAND_STARTUP_PROFILE;
|
||||
buf.size = sizeof(struct koneplus_startup_profile);
|
||||
buf.startup_profile = startup_profile;
|
||||
buf.command = KONEPLUS_COMMAND_ACTUAL_PROFILE;
|
||||
buf.size = sizeof(struct koneplus_actual_profile);
|
||||
buf.actual_profile = new_profile;
|
||||
|
||||
return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_STARTUP_PROFILE,
|
||||
&buf, sizeof(struct koneplus_profile_buttons));
|
||||
return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_ACTUAL_PROFILE,
|
||||
&buf, sizeof(struct koneplus_actual_profile));
|
||||
}
|
||||
|
||||
static ssize_t koneplus_sysfs_read(struct file *fp, struct kobject *kobj,
|
||||
@ -398,21 +398,22 @@ static ssize_t koneplus_sysfs_write_profile_buttons(struct file *fp,
|
||||
return sizeof(struct koneplus_profile_buttons);
|
||||
}
|
||||
|
||||
static ssize_t koneplus_sysfs_show_startup_profile(struct device *dev,
|
||||
static ssize_t koneplus_sysfs_show_actual_profile(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct koneplus_device *koneplus =
|
||||
hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", koneplus->startup_profile);
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", koneplus->actual_profile);
|
||||
}
|
||||
|
||||
static ssize_t koneplus_sysfs_set_startup_profile(struct device *dev,
|
||||
static ssize_t koneplus_sysfs_set_actual_profile(struct device *dev,
|
||||
struct device_attribute *attr, char const *buf, size_t size)
|
||||
{
|
||||
struct koneplus_device *koneplus;
|
||||
struct usb_device *usb_dev;
|
||||
unsigned long profile;
|
||||
int retval;
|
||||
struct koneplus_roccat_report roccat_report;
|
||||
|
||||
dev = dev->parent->parent;
|
||||
koneplus = hid_get_drvdata(dev_get_drvdata(dev));
|
||||
@ -423,22 +424,27 @@ static ssize_t koneplus_sysfs_set_startup_profile(struct device *dev,
|
||||
return retval;
|
||||
|
||||
mutex_lock(&koneplus->koneplus_lock);
|
||||
retval = koneplus_set_startup_profile(usb_dev, profile);
|
||||
mutex_unlock(&koneplus->koneplus_lock);
|
||||
if (retval)
|
||||
|
||||
retval = koneplus_set_actual_profile(usb_dev, profile);
|
||||
if (retval) {
|
||||
mutex_unlock(&koneplus->koneplus_lock);
|
||||
return retval;
|
||||
}
|
||||
|
||||
koneplus->actual_profile = profile;
|
||||
|
||||
roccat_report.type = KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE;
|
||||
roccat_report.data1 = profile + 1;
|
||||
roccat_report.data2 = 0;
|
||||
roccat_report.profile = profile + 1;
|
||||
roccat_report_event(koneplus->chrdev_minor,
|
||||
(uint8_t const *)&roccat_report);
|
||||
|
||||
mutex_unlock(&koneplus->koneplus_lock);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t koneplus_sysfs_show_actual_profile(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct koneplus_device *koneplus =
|
||||
hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", koneplus->actual_profile);
|
||||
}
|
||||
|
||||
static ssize_t koneplus_sysfs_show_firmware_version(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
@ -448,11 +454,12 @@ static ssize_t koneplus_sysfs_show_firmware_version(struct device *dev,
|
||||
}
|
||||
|
||||
static struct device_attribute koneplus_attributes[] = {
|
||||
__ATTR(actual_profile, 0660,
|
||||
koneplus_sysfs_show_actual_profile,
|
||||
koneplus_sysfs_set_actual_profile),
|
||||
__ATTR(startup_profile, 0660,
|
||||
koneplus_sysfs_show_startup_profile,
|
||||
koneplus_sysfs_set_startup_profile),
|
||||
__ATTR(actual_profile, 0440,
|
||||
koneplus_sysfs_show_actual_profile, NULL),
|
||||
koneplus_sysfs_show_actual_profile,
|
||||
koneplus_sysfs_set_actual_profile),
|
||||
__ATTR(firmware_version, 0440,
|
||||
koneplus_sysfs_show_firmware_version, NULL),
|
||||
__ATTR_NULL
|
||||
@ -557,15 +564,10 @@ static int koneplus_init_koneplus_device_struct(struct usb_device *usb_dev,
|
||||
struct koneplus_device *koneplus)
|
||||
{
|
||||
int retval, i;
|
||||
static uint wait = 100; /* device will freeze with just 60 */
|
||||
static uint wait = 200;
|
||||
|
||||
mutex_init(&koneplus->koneplus_lock);
|
||||
|
||||
koneplus->startup_profile = koneplus_get_startup_profile(usb_dev);
|
||||
if (koneplus->startup_profile < 0)
|
||||
return koneplus->startup_profile;
|
||||
|
||||
msleep(wait);
|
||||
retval = koneplus_get_info(usb_dev, &koneplus->info);
|
||||
if (retval)
|
||||
return retval;
|
||||
@ -584,7 +586,11 @@ static int koneplus_init_koneplus_device_struct(struct usb_device *usb_dev,
|
||||
return retval;
|
||||
}
|
||||
|
||||
koneplus_profile_activated(koneplus, koneplus->startup_profile);
|
||||
msleep(wait);
|
||||
retval = koneplus_get_actual_profile(usb_dev);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
koneplus_profile_activated(koneplus, retval);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -40,10 +40,10 @@ enum koneplus_control_values {
|
||||
KONEPLUS_CONTROL_REQUEST_STATUS_WAIT = 3,
|
||||
};
|
||||
|
||||
struct koneplus_startup_profile {
|
||||
uint8_t command; /* KONEPLUS_COMMAND_STARTUP_PROFILE */
|
||||
struct koneplus_actual_profile {
|
||||
uint8_t command; /* KONEPLUS_COMMAND_ACTUAL_PROFILE */
|
||||
uint8_t size; /* always 3 */
|
||||
uint8_t startup_profile; /* Range 0-4! */
|
||||
uint8_t actual_profile; /* Range 0-4! */
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
struct koneplus_profile_settings {
|
||||
@ -132,7 +132,7 @@ struct koneplus_tcu_image {
|
||||
|
||||
enum koneplus_commands {
|
||||
KONEPLUS_COMMAND_CONTROL = 0x4,
|
||||
KONEPLUS_COMMAND_STARTUP_PROFILE = 0x5,
|
||||
KONEPLUS_COMMAND_ACTUAL_PROFILE = 0x5,
|
||||
KONEPLUS_COMMAND_PROFILE_SETTINGS = 0x6,
|
||||
KONEPLUS_COMMAND_PROFILE_BUTTONS = 0x7,
|
||||
KONEPLUS_COMMAND_MACRO = 0x8,
|
||||
@ -145,7 +145,7 @@ enum koneplus_commands {
|
||||
|
||||
enum koneplus_usb_commands {
|
||||
KONEPLUS_USB_COMMAND_CONTROL = 0x304,
|
||||
KONEPLUS_USB_COMMAND_STARTUP_PROFILE = 0x305,
|
||||
KONEPLUS_USB_COMMAND_ACTUAL_PROFILE = 0x305,
|
||||
KONEPLUS_USB_COMMAND_PROFILE_SETTINGS = 0x306,
|
||||
KONEPLUS_USB_COMMAND_PROFILE_BUTTONS = 0x307,
|
||||
KONEPLUS_USB_COMMAND_MACRO = 0x308,
|
||||
@ -215,7 +215,6 @@ struct koneplus_device {
|
||||
|
||||
struct mutex koneplus_lock;
|
||||
|
||||
int startup_profile;
|
||||
struct koneplus_info info;
|
||||
struct koneplus_profile_settings profile_settings[5];
|
||||
struct koneplus_profile_buttons profile_buttons[5];
|
||||
|
@ -178,6 +178,8 @@ static void sony_remove(struct hid_device *hdev)
|
||||
static const struct hid_device_id sony_devices[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER),
|
||||
.driver_data = SIXAXIS_CONTROLLER_USB },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER),
|
||||
.driver_data = SIXAXIS_CONTROLLER_USB },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER),
|
||||
.driver_data = SIXAXIS_CONTROLLER_BT },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE),
|
||||
|
@ -1,286 +0,0 @@
|
||||
/*
|
||||
* HID driver for Stantum multitouch panels
|
||||
*
|
||||
* Copyright (c) 2009 Stephane Chatty <chatty@enac.fr>
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/hid.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
|
||||
MODULE_DESCRIPTION("Stantum HID multitouch panels");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
#include "hid-ids.h"
|
||||
|
||||
struct stantum_data {
|
||||
__s32 x, y, z, w, h; /* x, y, pressure, width, height */
|
||||
__u16 id; /* touch id */
|
||||
bool valid; /* valid finger data, or just placeholder? */
|
||||
bool first; /* first finger in the HID packet? */
|
||||
bool activity; /* at least one active finger so far? */
|
||||
};
|
||||
|
||||
static int stantum_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
||||
struct hid_field *field, struct hid_usage *usage,
|
||||
unsigned long **bit, int *max)
|
||||
{
|
||||
switch (usage->hid & HID_USAGE_PAGE) {
|
||||
|
||||
case HID_UP_GENDESK:
|
||||
switch (usage->hid) {
|
||||
case HID_GD_X:
|
||||
hid_map_usage(hi, usage, bit, max,
|
||||
EV_ABS, ABS_MT_POSITION_X);
|
||||
/* touchscreen emulation */
|
||||
input_set_abs_params(hi->input, ABS_X,
|
||||
field->logical_minimum,
|
||||
field->logical_maximum, 0, 0);
|
||||
return 1;
|
||||
case HID_GD_Y:
|
||||
hid_map_usage(hi, usage, bit, max,
|
||||
EV_ABS, ABS_MT_POSITION_Y);
|
||||
/* touchscreen emulation */
|
||||
input_set_abs_params(hi->input, ABS_Y,
|
||||
field->logical_minimum,
|
||||
field->logical_maximum, 0, 0);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
case HID_UP_DIGITIZER:
|
||||
switch (usage->hid) {
|
||||
case HID_DG_INRANGE:
|
||||
case HID_DG_CONFIDENCE:
|
||||
case HID_DG_INPUTMODE:
|
||||
case HID_DG_DEVICEINDEX:
|
||||
case HID_DG_CONTACTCOUNT:
|
||||
case HID_DG_CONTACTMAX:
|
||||
return -1;
|
||||
|
||||
case HID_DG_TIPSWITCH:
|
||||
/* touchscreen emulation */
|
||||
hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
|
||||
return 1;
|
||||
|
||||
case HID_DG_WIDTH:
|
||||
hid_map_usage(hi, usage, bit, max,
|
||||
EV_ABS, ABS_MT_TOUCH_MAJOR);
|
||||
return 1;
|
||||
case HID_DG_HEIGHT:
|
||||
hid_map_usage(hi, usage, bit, max,
|
||||
EV_ABS, ABS_MT_TOUCH_MINOR);
|
||||
input_set_abs_params(hi->input, ABS_MT_ORIENTATION,
|
||||
1, 1, 0, 0);
|
||||
return 1;
|
||||
case HID_DG_TIPPRESSURE:
|
||||
hid_map_usage(hi, usage, bit, max,
|
||||
EV_ABS, ABS_MT_PRESSURE);
|
||||
return 1;
|
||||
|
||||
case HID_DG_CONTACTID:
|
||||
hid_map_usage(hi, usage, bit, max,
|
||||
EV_ABS, ABS_MT_TRACKING_ID);
|
||||
return 1;
|
||||
|
||||
}
|
||||
return 0;
|
||||
|
||||
case 0xff000000:
|
||||
/* no input-oriented meaning */
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stantum_input_mapped(struct hid_device *hdev, struct hid_input *hi,
|
||||
struct hid_field *field, struct hid_usage *usage,
|
||||
unsigned long **bit, int *max)
|
||||
{
|
||||
if (usage->type == EV_KEY || usage->type == EV_ABS)
|
||||
clear_bit(usage->code, *bit);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* this function is called when a whole finger has been parsed,
|
||||
* so that it can decide what to send to the input layer.
|
||||
*/
|
||||
static void stantum_filter_event(struct stantum_data *sd,
|
||||
struct input_dev *input)
|
||||
{
|
||||
bool wide;
|
||||
|
||||
if (!sd->valid) {
|
||||
/*
|
||||
* touchscreen emulation: if the first finger is not valid and
|
||||
* there previously was finger activity, this is a release
|
||||
*/
|
||||
if (sd->first && sd->activity) {
|
||||
input_event(input, EV_KEY, BTN_TOUCH, 0);
|
||||
sd->activity = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
input_event(input, EV_ABS, ABS_MT_TRACKING_ID, sd->id);
|
||||
input_event(input, EV_ABS, ABS_MT_POSITION_X, sd->x);
|
||||
input_event(input, EV_ABS, ABS_MT_POSITION_Y, sd->y);
|
||||
|
||||
wide = (sd->w > sd->h);
|
||||
input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide);
|
||||
input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, wide ? sd->w : sd->h);
|
||||
input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, wide ? sd->h : sd->w);
|
||||
|
||||
input_event(input, EV_ABS, ABS_MT_PRESSURE, sd->z);
|
||||
|
||||
input_mt_sync(input);
|
||||
sd->valid = false;
|
||||
|
||||
/* touchscreen emulation */
|
||||
if (sd->first) {
|
||||
if (!sd->activity) {
|
||||
input_event(input, EV_KEY, BTN_TOUCH, 1);
|
||||
sd->activity = true;
|
||||
}
|
||||
input_event(input, EV_ABS, ABS_X, sd->x);
|
||||
input_event(input, EV_ABS, ABS_Y, sd->y);
|
||||
}
|
||||
sd->first = false;
|
||||
}
|
||||
|
||||
|
||||
static int stantum_event(struct hid_device *hid, struct hid_field *field,
|
||||
struct hid_usage *usage, __s32 value)
|
||||
{
|
||||
struct stantum_data *sd = hid_get_drvdata(hid);
|
||||
|
||||
if (hid->claimed & HID_CLAIMED_INPUT) {
|
||||
struct input_dev *input = field->hidinput->input;
|
||||
|
||||
switch (usage->hid) {
|
||||
case HID_DG_INRANGE:
|
||||
/* this is the last field in a finger */
|
||||
stantum_filter_event(sd, input);
|
||||
break;
|
||||
case HID_DG_WIDTH:
|
||||
sd->w = value;
|
||||
break;
|
||||
case HID_DG_HEIGHT:
|
||||
sd->h = value;
|
||||
break;
|
||||
case HID_GD_X:
|
||||
sd->x = value;
|
||||
break;
|
||||
case HID_GD_Y:
|
||||
sd->y = value;
|
||||
break;
|
||||
case HID_DG_TIPPRESSURE:
|
||||
sd->z = value;
|
||||
break;
|
||||
case HID_DG_CONTACTID:
|
||||
sd->id = value;
|
||||
break;
|
||||
case HID_DG_CONFIDENCE:
|
||||
sd->valid = !!value;
|
||||
break;
|
||||
case 0xff000002:
|
||||
/* this comes only before the first finger */
|
||||
sd->first = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* ignore the others */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* we have handled the hidinput part, now remains hiddev */
|
||||
if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
|
||||
hid->hiddev_hid_event(hid, field, usage, value);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int stantum_probe(struct hid_device *hdev,
|
||||
const struct hid_device_id *id)
|
||||
{
|
||||
int ret;
|
||||
struct stantum_data *sd;
|
||||
|
||||
sd = kmalloc(sizeof(struct stantum_data), GFP_KERNEL);
|
||||
if (!sd) {
|
||||
hid_err(hdev, "cannot allocate Stantum data\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
sd->valid = false;
|
||||
sd->first = false;
|
||||
sd->activity = false;
|
||||
hid_set_drvdata(hdev, sd);
|
||||
|
||||
ret = hid_parse(hdev);
|
||||
if (!ret)
|
||||
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
|
||||
|
||||
if (ret)
|
||||
kfree(sd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void stantum_remove(struct hid_device *hdev)
|
||||
{
|
||||
hid_hw_stop(hdev);
|
||||
kfree(hid_get_drvdata(hdev));
|
||||
hid_set_drvdata(hdev, NULL);
|
||||
}
|
||||
|
||||
static const struct hid_device_id stantum_devices[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_STANTUM, USB_DEVICE_ID_MTP) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_STM, USB_DEVICE_ID_MTP_STM) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_SITRONIX, USB_DEVICE_ID_MTP_SITRONIX) },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(hid, stantum_devices);
|
||||
|
||||
static const struct hid_usage_id stantum_grabbed_usages[] = {
|
||||
{ HID_ANY_ID, HID_ANY_ID, HID_ANY_ID },
|
||||
{ HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
|
||||
};
|
||||
|
||||
static struct hid_driver stantum_driver = {
|
||||
.name = "stantum",
|
||||
.id_table = stantum_devices,
|
||||
.probe = stantum_probe,
|
||||
.remove = stantum_remove,
|
||||
.input_mapping = stantum_input_mapping,
|
||||
.input_mapped = stantum_input_mapped,
|
||||
.usage_table = stantum_grabbed_usages,
|
||||
.event = stantum_event,
|
||||
};
|
||||
|
||||
static int __init stantum_init(void)
|
||||
{
|
||||
return hid_register_driver(&stantum_driver);
|
||||
}
|
||||
|
||||
static void __exit stantum_exit(void)
|
||||
{
|
||||
hid_unregister_driver(&stantum_driver);
|
||||
}
|
||||
|
||||
module_init(stantum_init);
|
||||
module_exit(stantum_exit);
|
||||
|
@ -101,8 +101,8 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* the first byte is expected to be a report number */
|
||||
/* This function is to be called with the minors_lock mutex held */
|
||||
/* The first byte is expected to be a report number.
|
||||
* This function is to be called with the minors_lock mutex held */
|
||||
static ssize_t hidraw_send_report(struct file *file, const char __user *buffer, size_t count, unsigned char report_type)
|
||||
{
|
||||
unsigned int minor = iminor(file->f_path.dentry->d_inode);
|
||||
@ -166,11 +166,11 @@ static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t
|
||||
|
||||
|
||||
/* This function performs a Get_Report transfer over the control endpoint
|
||||
per section 7.2.1 of the HID specification, version 1.1. The first byte
|
||||
of buffer is the report number to request, or 0x0 if the defice does not
|
||||
use numbered reports. The report_type parameter can be HID_FEATURE_REPORT
|
||||
or HID_INPUT_REPORT. This function is to be called with the minors_lock
|
||||
mutex held. */
|
||||
* per section 7.2.1 of the HID specification, version 1.1. The first byte
|
||||
* of buffer is the report number to request, or 0x0 if the defice does not
|
||||
* use numbered reports. The report_type parameter can be HID_FEATURE_REPORT
|
||||
* or HID_INPUT_REPORT. This function is to be called with the minors_lock
|
||||
* mutex held. */
|
||||
static ssize_t hidraw_get_report(struct file *file, char __user *buffer, size_t count, unsigned char report_type)
|
||||
{
|
||||
unsigned int minor = iminor(file->f_path.dentry->d_inode);
|
||||
@ -207,7 +207,7 @@ static ssize_t hidraw_get_report(struct file *file, char __user *buffer, size_t
|
||||
}
|
||||
|
||||
/* Read the first byte from the user. This is the report number,
|
||||
which is passed to dev->hid_get_raw_report(). */
|
||||
* which is passed to dev->hid_get_raw_report(). */
|
||||
if (copy_from_user(&report_number, buffer, 1)) {
|
||||
ret = -EFAULT;
|
||||
goto out_free;
|
||||
@ -395,12 +395,7 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd,
|
||||
}
|
||||
|
||||
if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWNAME(0))) {
|
||||
int len;
|
||||
if (!hid->name) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
len = strlen(hid->name) + 1;
|
||||
int len = strlen(hid->name) + 1;
|
||||
if (len > _IOC_SIZE(cmd))
|
||||
len = _IOC_SIZE(cmd);
|
||||
ret = copy_to_user(user_arg, hid->name, len) ?
|
||||
@ -409,12 +404,7 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd,
|
||||
}
|
||||
|
||||
if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWPHYS(0))) {
|
||||
int len;
|
||||
if (!hid->phys) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
len = strlen(hid->phys) + 1;
|
||||
int len = strlen(hid->phys) + 1;
|
||||
if (len > _IOC_SIZE(cmd))
|
||||
len = _IOC_SIZE(cmd);
|
||||
ret = copy_to_user(user_arg, hid->phys, len) ?
|
||||
|
@ -68,6 +68,8 @@ static const struct hid_blacklist {
|
||||
{ USB_VENDOR_ID_PRODIGE, USB_DEVICE_ID_PRODIGE_CORDLESS, HID_QUIRK_NOGET },
|
||||
{ USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NOGET },
|
||||
{ USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET },
|
||||
{ USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_1, HID_QUIRK_NOGET },
|
||||
{ USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_2, HID_QUIRK_NOGET },
|
||||
{ USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET },
|
||||
{ USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209, HID_QUIRK_MULTI_INPUT },
|
||||
{ USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U, HID_QUIRK_MULTI_INPUT },
|
||||
|
@ -242,6 +242,7 @@ static int hiddev_release(struct inode * inode, struct file * file)
|
||||
list_del(&list->node);
|
||||
spin_unlock_irqrestore(&list->hiddev->list_lock, flags);
|
||||
|
||||
mutex_lock(&list->hiddev->existancelock);
|
||||
if (!--list->hiddev->open) {
|
||||
if (list->hiddev->exist) {
|
||||
usbhid_close(list->hiddev->hid);
|
||||
@ -252,6 +253,7 @@ static int hiddev_release(struct inode * inode, struct file * file)
|
||||
}
|
||||
|
||||
kfree(list);
|
||||
mutex_unlock(&list->hiddev->existancelock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -300,17 +302,21 @@ static int hiddev_open(struct inode *inode, struct file *file)
|
||||
list_add_tail(&list->node, &hiddev->list);
|
||||
spin_unlock_irq(&list->hiddev->list_lock);
|
||||
|
||||
mutex_lock(&hiddev->existancelock);
|
||||
if (!list->hiddev->open++)
|
||||
if (list->hiddev->exist) {
|
||||
struct hid_device *hid = hiddev->hid;
|
||||
res = usbhid_get_power(hid);
|
||||
if (res < 0) {
|
||||
res = -EIO;
|
||||
goto bail;
|
||||
goto bail_unlock;
|
||||
}
|
||||
usbhid_open(hid);
|
||||
}
|
||||
mutex_unlock(&hiddev->existancelock);
|
||||
return 0;
|
||||
bail_unlock:
|
||||
mutex_unlock(&hiddev->existancelock);
|
||||
bail:
|
||||
file->private_data = NULL;
|
||||
kfree(list);
|
||||
@ -367,8 +373,10 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun
|
||||
/* let O_NONBLOCK tasks run */
|
||||
mutex_unlock(&list->thread_lock);
|
||||
schedule();
|
||||
if (mutex_lock_interruptible(&list->thread_lock))
|
||||
if (mutex_lock_interruptible(&list->thread_lock)) {
|
||||
finish_wait(&list->hiddev->wait, &wait);
|
||||
return -EINTR;
|
||||
}
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
}
|
||||
finish_wait(&list->hiddev->wait, &wait);
|
||||
@ -509,7 +517,7 @@ static noinline int hiddev_ioctl_usage(struct hiddev *hiddev, unsigned int cmd,
|
||||
(uref_multi->num_values > HID_MAX_MULTI_USAGES ||
|
||||
uref->usage_index + uref_multi->num_values > field->report_count))
|
||||
goto inval;
|
||||
}
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case HIDIOCGUSAGE:
|
||||
@ -801,14 +809,7 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
break;
|
||||
|
||||
if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGNAME(0))) {
|
||||
int len;
|
||||
|
||||
if (!hid->name) {
|
||||
r = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
len = strlen(hid->name) + 1;
|
||||
int len = strlen(hid->name) + 1;
|
||||
if (len > _IOC_SIZE(cmd))
|
||||
len = _IOC_SIZE(cmd);
|
||||
r = copy_to_user(user_arg, hid->name, len) ?
|
||||
@ -817,14 +818,7 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
}
|
||||
|
||||
if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGPHYS(0))) {
|
||||
int len;
|
||||
|
||||
if (!hid->phys) {
|
||||
r = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
len = strlen(hid->phys) + 1;
|
||||
int len = strlen(hid->phys) + 1;
|
||||
if (len > _IOC_SIZE(cmd))
|
||||
len = _IOC_SIZE(cmd);
|
||||
r = copy_to_user(user_arg, hid->phys, len) ?
|
||||
@ -925,7 +919,6 @@ void hiddev_disconnect(struct hid_device *hid)
|
||||
|
||||
mutex_lock(&hiddev->existancelock);
|
||||
hiddev->exist = 0;
|
||||
mutex_unlock(&hiddev->existancelock);
|
||||
|
||||
usb_deregister_dev(usbhid->intf, &hiddev_class);
|
||||
|
||||
@ -935,4 +928,5 @@ void hiddev_disconnect(struct hid_device *hid)
|
||||
} else {
|
||||
kfree(hiddev);
|
||||
}
|
||||
mutex_unlock(&hiddev->existancelock);
|
||||
}
|
||||
|
@ -80,7 +80,7 @@
|
||||
#define HIDP_VIRTUAL_CABLE_UNPLUG 0
|
||||
#define HIDP_BOOT_PROTOCOL_MODE 1
|
||||
#define HIDP_BLUETOOTH_VENDOR_ID 9
|
||||
#define HIDP_WAITING_FOR_RETURN 10
|
||||
#define HIDP_WAITING_FOR_RETURN 10
|
||||
#define HIDP_WAITING_FOR_SEND_ACK 11
|
||||
|
||||
struct hidp_connadd_req {
|
||||
|
@ -61,4 +61,10 @@ config SAMPLE_KDB
|
||||
Build an example of how to dynamically add the hello
|
||||
command to the kdb shell.
|
||||
|
||||
config SAMPLE_HIDRAW
|
||||
bool "Build simple hidraw example"
|
||||
depends on HIDRAW && HEADERS_CHECK
|
||||
help
|
||||
Build an example of how to use hidraw from userspace.
|
||||
|
||||
endif # SAMPLES
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Makefile for Linux samples code
|
||||
|
||||
obj-$(CONFIG_SAMPLES) += kobject/ kprobes/ tracepoints/ trace_events/ \
|
||||
hw_breakpoint/ kfifo/ kdb/
|
||||
hw_breakpoint/ kfifo/ kdb/ hidraw/
|
||||
|
10
samples/hidraw/Makefile
Normal file
10
samples/hidraw/Makefile
Normal file
@ -0,0 +1,10 @@
|
||||
# kbuild trick to avoid linker error. Can be omitted if a module is built.
|
||||
obj- := dummy.o
|
||||
|
||||
# List of programs to build
|
||||
hostprogs-y := hid-example
|
||||
|
||||
# Tell kbuild to always build the programs
|
||||
always := $(hostprogs-y)
|
||||
|
||||
HOSTCFLAGS_hid-example.o += -I$(objtree)/usr/include
|
178
samples/hidraw/hid-example.c
Normal file
178
samples/hidraw/hid-example.c
Normal file
@ -0,0 +1,178 @@
|
||||
/*
|
||||
* Hidraw Userspace Example
|
||||
*
|
||||
* Copyright (c) 2010 Alan Ott <alan@signal11.us>
|
||||
* Copyright (c) 2010 Signal 11 Software
|
||||
*
|
||||
* The code may be used by anyone for any purpose,
|
||||
* and can serve as a starting point for developing
|
||||
* applications using hidraw.
|
||||
*/
|
||||
|
||||
/* Linux */
|
||||
#include <linux/types.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/hidraw.h>
|
||||
|
||||
/*
|
||||
* Ugly hack to work around failing compilation on systems that don't
|
||||
* yet populate new version of hidraw.h to userspace.
|
||||
*
|
||||
* If you need this, please have your distro update the kernel headers.
|
||||
*/
|
||||
#ifndef HIDIOCSFEATURE
|
||||
#define HIDIOCSFEATURE(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x06, len)
|
||||
#define HIDIOCGFEATURE(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x07, len)
|
||||
#endif
|
||||
|
||||
/* Unix */
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* C */
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
const char *bus_str(int bus);
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int fd;
|
||||
int i, res, desc_size = 0;
|
||||
char buf[256];
|
||||
struct hidraw_report_descriptor rpt_desc;
|
||||
struct hidraw_devinfo info;
|
||||
|
||||
/* Open the Device with non-blocking reads. In real life,
|
||||
don't use a hard coded path; use libudev instead. */
|
||||
fd = open("/dev/hidraw0", O_RDWR|O_NONBLOCK);
|
||||
|
||||
if (fd < 0) {
|
||||
perror("Unable to open device");
|
||||
return 1;
|
||||
}
|
||||
|
||||
memset(&rpt_desc, 0x0, sizeof(rpt_desc));
|
||||
memset(&info, 0x0, sizeof(info));
|
||||
memset(buf, 0x0, sizeof(buf));
|
||||
|
||||
/* Get Report Descriptor Size */
|
||||
res = ioctl(fd, HIDIOCGRDESCSIZE, &desc_size);
|
||||
if (res < 0)
|
||||
perror("HIDIOCGRDESCSIZE");
|
||||
else
|
||||
printf("Report Descriptor Size: %d\n", desc_size);
|
||||
|
||||
/* Get Report Descriptor */
|
||||
rpt_desc.size = desc_size;
|
||||
res = ioctl(fd, HIDIOCGRDESC, &rpt_desc);
|
||||
if (res < 0) {
|
||||
perror("HIDIOCGRDESC");
|
||||
} else {
|
||||
printf("Report Descriptor:\n");
|
||||
for (i = 0; i < rpt_desc.size; i++)
|
||||
printf("%hhx ", rpt_desc.value[i]);
|
||||
puts("\n");
|
||||
}
|
||||
|
||||
/* Get Raw Name */
|
||||
res = ioctl(fd, HIDIOCGRAWNAME(256), buf);
|
||||
if (res < 0)
|
||||
perror("HIDIOCGRAWNAME");
|
||||
else
|
||||
printf("Raw Name: %s\n", buf);
|
||||
|
||||
/* Get Physical Location */
|
||||
res = ioctl(fd, HIDIOCGRAWPHYS(256), buf);
|
||||
if (res < 0)
|
||||
perror("HIDIOCGRAWPHYS");
|
||||
else
|
||||
printf("Raw Phys: %s\n", buf);
|
||||
|
||||
/* Get Raw Info */
|
||||
res = ioctl(fd, HIDIOCGRAWINFO, &info);
|
||||
if (res < 0) {
|
||||
perror("HIDIOCGRAWINFO");
|
||||
} else {
|
||||
printf("Raw Info:\n");
|
||||
printf("\tbustype: %d (%s)\n",
|
||||
info.bustype, bus_str(info.bustype));
|
||||
printf("\tvendor: 0x%04hx\n", info.vendor);
|
||||
printf("\tproduct: 0x%04hx\n", info.product);
|
||||
}
|
||||
|
||||
/* Set Feature */
|
||||
buf[0] = 0x9; /* Report Number */
|
||||
buf[1] = 0xff;
|
||||
buf[2] = 0xff;
|
||||
buf[3] = 0xff;
|
||||
res = ioctl(fd, HIDIOCSFEATURE(4), buf);
|
||||
if (res < 0)
|
||||
perror("HIDIOCSFEATURE");
|
||||
else
|
||||
printf("ioctl HIDIOCGFEATURE returned: %d\n", res);
|
||||
|
||||
/* Get Feature */
|
||||
buf[0] = 0x9; /* Report Number */
|
||||
res = ioctl(fd, HIDIOCGFEATURE(256), buf);
|
||||
if (res < 0) {
|
||||
perror("HIDIOCGFEATURE");
|
||||
} else {
|
||||
printf("ioctl HIDIOCGFEATURE returned: %d\n", res);
|
||||
printf("Report data (not containing the report number):\n\t");
|
||||
for (i = 0; i < res; i++)
|
||||
printf("%hhx ", buf[i]);
|
||||
puts("\n");
|
||||
}
|
||||
|
||||
/* Send a Report to the Device */
|
||||
buf[0] = 0x1; /* Report Number */
|
||||
buf[1] = 0x77;
|
||||
res = write(fd, buf, 2);
|
||||
if (res < 0) {
|
||||
printf("Error: %d\n", errno);
|
||||
perror("write");
|
||||
} else {
|
||||
printf("write() wrote %d bytes\n", res);
|
||||
}
|
||||
|
||||
/* Get a report from the device */
|
||||
res = read(fd, buf, 16);
|
||||
if (res < 0) {
|
||||
perror("read");
|
||||
} else {
|
||||
printf("read() read %d bytes:\n\t", res);
|
||||
for (i = 0; i < res; i++)
|
||||
printf("%hhx ", buf[i]);
|
||||
puts("\n");
|
||||
}
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *
|
||||
bus_str(int bus)
|
||||
{
|
||||
switch (bus) {
|
||||
case BUS_USB:
|
||||
return "USB";
|
||||
break;
|
||||
case BUS_HIL:
|
||||
return "HIL";
|
||||
break;
|
||||
case BUS_BLUETOOTH:
|
||||
return "Bluetooth";
|
||||
break;
|
||||
case BUS_VIRTUAL:
|
||||
return "Virtual";
|
||||
break;
|
||||
default:
|
||||
return "Other";
|
||||
break;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user