Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
72c16d9a
Commit
72c16d9a
authored
Apr 30, 2013
by
Jiri Kosina
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'for-3.10/mt-hybrid-finger-pen' into for-linus
Conflicts: drivers/hid/hid-multitouch.c
parents
4f5a8104
fb4d8d98
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
255 additions
and
60 deletions
+255
-60
drivers/hid/hid-input.c
drivers/hid/hid-input.c
+77
-0
drivers/hid/hid-multitouch.c
drivers/hid/hid-multitouch.c
+177
-60
include/linux/hid.h
include/linux/hid.h
+1
-0
No files found.
drivers/hid/hid-input.c
View file @
72c16d9a
...
@@ -1198,6 +1198,67 @@ static struct hid_input *hidinput_allocate(struct hid_device *hid)
...
@@ -1198,6 +1198,67 @@ static struct hid_input *hidinput_allocate(struct hid_device *hid)
return
hidinput
;
return
hidinput
;
}
}
static
bool
hidinput_has_been_populated
(
struct
hid_input
*
hidinput
)
{
int
i
;
unsigned
long
r
=
0
;
for
(
i
=
0
;
i
<
BITS_TO_LONGS
(
EV_CNT
);
i
++
)
r
|=
hidinput
->
input
->
evbit
[
i
];
for
(
i
=
0
;
i
<
BITS_TO_LONGS
(
KEY_CNT
);
i
++
)
r
|=
hidinput
->
input
->
keybit
[
i
];
for
(
i
=
0
;
i
<
BITS_TO_LONGS
(
REL_CNT
);
i
++
)
r
|=
hidinput
->
input
->
relbit
[
i
];
for
(
i
=
0
;
i
<
BITS_TO_LONGS
(
ABS_CNT
);
i
++
)
r
|=
hidinput
->
input
->
absbit
[
i
];
for
(
i
=
0
;
i
<
BITS_TO_LONGS
(
MSC_CNT
);
i
++
)
r
|=
hidinput
->
input
->
mscbit
[
i
];
for
(
i
=
0
;
i
<
BITS_TO_LONGS
(
LED_CNT
);
i
++
)
r
|=
hidinput
->
input
->
ledbit
[
i
];
for
(
i
=
0
;
i
<
BITS_TO_LONGS
(
SND_CNT
);
i
++
)
r
|=
hidinput
->
input
->
sndbit
[
i
];
for
(
i
=
0
;
i
<
BITS_TO_LONGS
(
FF_CNT
);
i
++
)
r
|=
hidinput
->
input
->
ffbit
[
i
];
for
(
i
=
0
;
i
<
BITS_TO_LONGS
(
SW_CNT
);
i
++
)
r
|=
hidinput
->
input
->
swbit
[
i
];
return
!!
r
;
}
static
void
hidinput_cleanup_hidinput
(
struct
hid_device
*
hid
,
struct
hid_input
*
hidinput
)
{
struct
hid_report
*
report
;
int
i
,
k
;
list_del
(
&
hidinput
->
list
);
input_free_device
(
hidinput
->
input
);
for
(
k
=
HID_INPUT_REPORT
;
k
<=
HID_OUTPUT_REPORT
;
k
++
)
{
if
(
k
==
HID_OUTPUT_REPORT
&&
hid
->
quirks
&
HID_QUIRK_SKIP_OUTPUT_REPORTS
)
continue
;
list_for_each_entry
(
report
,
&
hid
->
report_enum
[
k
].
report_list
,
list
)
{
for
(
i
=
0
;
i
<
report
->
maxfield
;
i
++
)
if
(
report
->
field
[
i
]
->
hidinput
==
hidinput
)
report
->
field
[
i
]
->
hidinput
=
NULL
;
}
}
kfree
(
hidinput
);
}
/*
/*
* Register the input device; print a message.
* Register the input device; print a message.
* Configure the input layer interface
* Configure the input layer interface
...
@@ -1249,6 +1310,10 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
...
@@ -1249,6 +1310,10 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
hidinput_configure_usage
(
hidinput
,
report
->
field
[
i
],
hidinput_configure_usage
(
hidinput
,
report
->
field
[
i
],
report
->
field
[
i
]
->
usage
+
j
);
report
->
field
[
i
]
->
usage
+
j
);
if
((
hid
->
quirks
&
HID_QUIRK_NO_EMPTY_INPUT
)
&&
!
hidinput_has_been_populated
(
hidinput
))
continue
;
if
(
hid
->
quirks
&
HID_QUIRK_MULTI_INPUT
)
{
if
(
hid
->
quirks
&
HID_QUIRK_MULTI_INPUT
)
{
/* This will leave hidinput NULL, so that it
/* This will leave hidinput NULL, so that it
* allocates another one if we have more inputs on
* allocates another one if we have more inputs on
...
@@ -1265,6 +1330,18 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
...
@@ -1265,6 +1330,18 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
}
}
}
}
if
(
hidinput
&&
(
hid
->
quirks
&
HID_QUIRK_NO_EMPTY_INPUT
)
&&
!
hidinput_has_been_populated
(
hidinput
))
{
/* no need to register an input device not populated */
hidinput_cleanup_hidinput
(
hid
,
hidinput
);
hidinput
=
NULL
;
}
if
(
list_empty
(
&
hid
->
inputs
))
{
hid_err
(
hid
,
"No inputs registered, leaving
\n
"
);
goto
out_unwind
;
}
if
(
hidinput
)
{
if
(
hidinput
)
{
if
(
drv
->
input_configured
)
if
(
drv
->
input_configured
)
drv
->
input_configured
(
hid
,
hidinput
);
drv
->
input_configured
(
hid
,
hidinput
);
...
...
drivers/hid/hid-multitouch.c
View file @
72c16d9a
...
@@ -44,6 +44,7 @@
...
@@ -44,6 +44,7 @@
#include <linux/slab.h>
#include <linux/slab.h>
#include <linux/usb.h>
#include <linux/usb.h>
#include <linux/input/mt.h>
#include <linux/input/mt.h>
#include <linux/string.h>
MODULE_AUTHOR
(
"Stephane Chatty <chatty@enac.fr>"
);
MODULE_AUTHOR
(
"Stephane Chatty <chatty@enac.fr>"
);
...
@@ -97,9 +98,9 @@ struct mt_device {
...
@@ -97,9 +98,9 @@ struct mt_device {
multitouch fields */
multitouch fields */
int
cc_index
;
/* contact count field index in the report */
int
cc_index
;
/* contact count field index in the report */
int
cc_value_index
;
/* contact count value index in the field */
int
cc_value_index
;
/* contact count value index in the field */
unsigned
last_field_index
;
/* last field index of the report */
unsigned
last_slot_field
;
/* the last field of a slot */
unsigned
last_slot_field
;
/* the last field of a slot */
unsigned
mt_report_id
;
/* the report ID of the multitouch device */
unsigned
mt_report_id
;
/* the report ID of the multitouch device */
unsigned
pen_report_id
;
/* the report ID of the pen device */
__s8
inputmode
;
/* InputMode HID feature, -1 if non-existent */
__s8
inputmode
;
/* InputMode HID feature, -1 if non-existent */
__s8
inputmode_index
;
/* InputMode HID feature index in the report */
__s8
inputmode_index
;
/* InputMode HID feature index in the report */
__s8
maxcontact_report_id
;
/* Maximum Contact Number HID feature,
__s8
maxcontact_report_id
;
/* Maximum Contact Number HID feature,
...
@@ -115,6 +116,9 @@ struct mt_device {
...
@@ -115,6 +116,9 @@ struct mt_device {
unsigned
mt_flags
;
/* flags to pass to input-mt */
unsigned
mt_flags
;
/* flags to pass to input-mt */
};
};
static
void
mt_post_parse_default_settings
(
struct
mt_device
*
td
);
static
void
mt_post_parse
(
struct
mt_device
*
td
);
/* classes of device behavior */
/* classes of device behavior */
#define MT_CLS_DEFAULT 0x0001
#define MT_CLS_DEFAULT 0x0001
...
@@ -257,6 +261,14 @@ static struct mt_class mt_classes[] = {
...
@@ -257,6 +261,14 @@ static struct mt_class mt_classes[] = {
{
}
{
}
};
};
static
void
mt_free_input_name
(
struct
hid_input
*
hi
)
{
struct
hid_device
*
hdev
=
hi
->
report
->
device
;
if
(
hi
->
input
->
name
!=
hdev
->
name
)
kfree
(
hi
->
input
->
name
);
}
static
ssize_t
mt_show_quirks
(
struct
device
*
dev
,
static
ssize_t
mt_show_quirks
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
struct
device_attribute
*
attr
,
char
*
buf
)
char
*
buf
)
...
@@ -365,7 +377,53 @@ static void mt_store_field(struct hid_usage *usage, struct mt_device *td,
...
@@ -365,7 +377,53 @@ static void mt_store_field(struct hid_usage *usage, struct mt_device *td,
f
->
usages
[
f
->
length
++
]
=
usage
->
hid
;
f
->
usages
[
f
->
length
++
]
=
usage
->
hid
;
}
}
static
int
mt_input_mapping
(
struct
hid_device
*
hdev
,
struct
hid_input
*
hi
,
static
int
mt_pen_input_mapping
(
struct
hid_device
*
hdev
,
struct
hid_input
*
hi
,
struct
hid_field
*
field
,
struct
hid_usage
*
usage
,
unsigned
long
**
bit
,
int
*
max
)
{
struct
mt_device
*
td
=
hid_get_drvdata
(
hdev
);
td
->
pen_report_id
=
field
->
report
->
id
;
return
0
;
}
static
int
mt_pen_input_mapped
(
struct
hid_device
*
hdev
,
struct
hid_input
*
hi
,
struct
hid_field
*
field
,
struct
hid_usage
*
usage
,
unsigned
long
**
bit
,
int
*
max
)
{
return
0
;
}
static
int
mt_pen_event
(
struct
hid_device
*
hid
,
struct
hid_field
*
field
,
struct
hid_usage
*
usage
,
__s32
value
)
{
/* let hid-input handle it */
return
0
;
}
static
void
mt_pen_report
(
struct
hid_device
*
hid
,
struct
hid_report
*
report
)
{
struct
hid_field
*
field
=
report
->
field
[
0
];
input_sync
(
field
->
hidinput
->
input
);
}
static
void
mt_pen_input_configured
(
struct
hid_device
*
hdev
,
struct
hid_input
*
hi
)
{
char
*
name
=
kzalloc
(
strlen
(
hi
->
input
->
name
)
+
5
,
GFP_KERNEL
);
if
(
name
)
{
sprintf
(
name
,
"%s Pen"
,
hi
->
input
->
name
);
mt_free_input_name
(
hi
);
hi
->
input
->
name
=
name
;
}
/* force BTN_STYLUS to allow tablet matching in udev */
__set_bit
(
BTN_STYLUS
,
hi
->
input
->
keybit
);
}
static
int
mt_touch_input_mapping
(
struct
hid_device
*
hdev
,
struct
hid_input
*
hi
,
struct
hid_field
*
field
,
struct
hid_usage
*
usage
,
struct
hid_field
*
field
,
struct
hid_usage
*
usage
,
unsigned
long
**
bit
,
int
*
max
)
unsigned
long
**
bit
,
int
*
max
)
{
{
...
@@ -374,13 +432,8 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
...
@@ -374,13 +432,8 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
int
code
;
int
code
;
struct
hid_usage
*
prev_usage
=
NULL
;
struct
hid_usage
*
prev_usage
=
NULL
;
/* Only map fields from TouchScreen or TouchPad collections.
* We need to ignore fields that belong to other collections
* such as Mouse that might have the same GenericDesktop usages. */
if
(
field
->
application
==
HID_DG_TOUCHSCREEN
)
if
(
field
->
application
==
HID_DG_TOUCHSCREEN
)
td
->
mt_flags
|=
INPUT_MT_DIRECT
;
td
->
mt_flags
|=
INPUT_MT_DIRECT
;
else
if
(
field
->
application
!=
HID_DG_TOUCHPAD
)
return
0
;
/*
/*
* Model touchscreens providing buttons as touchpads.
* Model touchscreens providing buttons as touchpads.
...
@@ -389,12 +442,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
...
@@ -389,12 +442,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
(
usage
->
hid
&
HID_USAGE_PAGE
)
==
HID_UP_BUTTON
)
(
usage
->
hid
&
HID_USAGE_PAGE
)
==
HID_UP_BUTTON
)
td
->
mt_flags
|=
INPUT_MT_POINTER
;
td
->
mt_flags
|=
INPUT_MT_POINTER
;
/* eGalax devices provide a Digitizer.Stylus input which overrides
* the correct Digitizers.Finger X/Y ranges.
* Let's just ignore this input. */
if
(
field
->
physical
==
HID_DG_STYLUS
)
return
-
1
;
if
(
usage
->
usage_index
)
if
(
usage
->
usage_index
)
prev_usage
=
&
field
->
usage
[
usage
->
usage_index
-
1
];
prev_usage
=
&
field
->
usage
[
usage
->
usage_index
-
1
];
...
@@ -416,7 +463,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
...
@@ -416,7 +463,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
}
}
mt_store_field
(
usage
,
td
,
hi
);
mt_store_field
(
usage
,
td
,
hi
);
td
->
last_field_index
=
field
->
index
;
return
1
;
return
1
;
case
HID_GD_Y
:
case
HID_GD_Y
:
if
(
prev_usage
&&
(
prev_usage
->
hid
==
usage
->
hid
))
{
if
(
prev_usage
&&
(
prev_usage
->
hid
==
usage
->
hid
))
{
...
@@ -432,7 +478,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
...
@@ -432,7 +478,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
}
}
mt_store_field
(
usage
,
td
,
hi
);
mt_store_field
(
usage
,
td
,
hi
);
td
->
last_field_index
=
field
->
index
;
return
1
;
return
1
;
}
}
return
0
;
return
0
;
...
@@ -447,21 +492,17 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
...
@@ -447,21 +492,17 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
ABS_MT_DISTANCE
,
0
,
1
,
0
,
0
);
ABS_MT_DISTANCE
,
0
,
1
,
0
,
0
);
}
}
mt_store_field
(
usage
,
td
,
hi
);
mt_store_field
(
usage
,
td
,
hi
);
td
->
last_field_index
=
field
->
index
;
return
1
;
return
1
;
case
HID_DG_CONFIDENCE
:
case
HID_DG_CONFIDENCE
:
mt_store_field
(
usage
,
td
,
hi
);
mt_store_field
(
usage
,
td
,
hi
);
td
->
last_field_index
=
field
->
index
;
return
1
;
return
1
;
case
HID_DG_TIPSWITCH
:
case
HID_DG_TIPSWITCH
:
hid_map_usage
(
hi
,
usage
,
bit
,
max
,
EV_KEY
,
BTN_TOUCH
);
hid_map_usage
(
hi
,
usage
,
bit
,
max
,
EV_KEY
,
BTN_TOUCH
);
input_set_capability
(
hi
->
input
,
EV_KEY
,
BTN_TOUCH
);
input_set_capability
(
hi
->
input
,
EV_KEY
,
BTN_TOUCH
);
mt_store_field
(
usage
,
td
,
hi
);
mt_store_field
(
usage
,
td
,
hi
);
td
->
last_field_index
=
field
->
index
;
return
1
;
return
1
;
case
HID_DG_CONTACTID
:
case
HID_DG_CONTACTID
:
mt_store_field
(
usage
,
td
,
hi
);
mt_store_field
(
usage
,
td
,
hi
);
td
->
last_field_index
=
field
->
index
;
td
->
touches_by_report
++
;
td
->
touches_by_report
++
;
td
->
mt_report_id
=
field
->
report
->
id
;
td
->
mt_report_id
=
field
->
report
->
id
;
return
1
;
return
1
;
...
@@ -472,7 +513,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
...
@@ -472,7 +513,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
set_abs
(
hi
->
input
,
ABS_MT_TOUCH_MAJOR
,
field
,
set_abs
(
hi
->
input
,
ABS_MT_TOUCH_MAJOR
,
field
,
cls
->
sn_width
);
cls
->
sn_width
);
mt_store_field
(
usage
,
td
,
hi
);
mt_store_field
(
usage
,
td
,
hi
);
td
->
last_field_index
=
field
->
index
;
return
1
;
return
1
;
case
HID_DG_HEIGHT
:
case
HID_DG_HEIGHT
:
hid_map_usage
(
hi
,
usage
,
bit
,
max
,
hid_map_usage
(
hi
,
usage
,
bit
,
max
,
...
@@ -484,7 +524,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
...
@@ -484,7 +524,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
ABS_MT_ORIENTATION
,
0
,
1
,
0
,
0
);
ABS_MT_ORIENTATION
,
0
,
1
,
0
,
0
);
}
}
mt_store_field
(
usage
,
td
,
hi
);
mt_store_field
(
usage
,
td
,
hi
);
td
->
last_field_index
=
field
->
index
;
return
1
;
return
1
;
case
HID_DG_TIPPRESSURE
:
case
HID_DG_TIPPRESSURE
:
hid_map_usage
(
hi
,
usage
,
bit
,
max
,
hid_map_usage
(
hi
,
usage
,
bit
,
max
,
...
@@ -492,17 +531,14 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
...
@@ -492,17 +531,14 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
set_abs
(
hi
->
input
,
ABS_MT_PRESSURE
,
field
,
set_abs
(
hi
->
input
,
ABS_MT_PRESSURE
,
field
,
cls
->
sn_pressure
);
cls
->
sn_pressure
);
mt_store_field
(
usage
,
td
,
hi
);
mt_store_field
(
usage
,
td
,
hi
);
td
->
last_field_index
=
field
->
index
;
return
1
;
return
1
;
case
HID_DG_CONTACTCOUNT
:
case
HID_DG_CONTACTCOUNT
:
td
->
cc_index
=
field
->
index
;
td
->
cc_index
=
field
->
index
;
td
->
cc_value_index
=
usage
->
usage_index
;
td
->
cc_value_index
=
usage
->
usage_index
;
td
->
last_field_index
=
field
->
index
;
return
1
;
return
1
;
case
HID_DG_CONTACTMAX
:
case
HID_DG_CONTACTMAX
:
/* we don't set td->last_slot_field as contactcount and
/* we don't set td->last_slot_field as contactcount and
* contact max are global to the report */
* contact max are global to the report */
td
->
last_field_index
=
field
->
index
;
return
-
1
;
return
-
1
;
case
HID_DG_TOUCH
:
case
HID_DG_TOUCH
:
/* Legacy devices use TIPSWITCH and not TOUCH.
/* Legacy devices use TIPSWITCH and not TOUCH.
...
@@ -526,7 +562,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
...
@@ -526,7 +562,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
return
0
;
return
0
;
}
}
static
int
mt_input_mapped
(
struct
hid_device
*
hdev
,
struct
hid_input
*
hi
,
static
int
mt_
touch_
input_mapped
(
struct
hid_device
*
hdev
,
struct
hid_input
*
hi
,
struct
hid_field
*
field
,
struct
hid_usage
*
usage
,
struct
hid_field
*
field
,
struct
hid_usage
*
usage
,
unsigned
long
**
bit
,
int
*
max
)
unsigned
long
**
bit
,
int
*
max
)
{
{
...
@@ -617,7 +653,7 @@ static void mt_sync_frame(struct mt_device *td, struct input_dev *input)
...
@@ -617,7 +653,7 @@ static void mt_sync_frame(struct mt_device *td, struct input_dev *input)
td
->
num_received
=
0
;
td
->
num_received
=
0
;
}
}
static
int
mt_event
(
struct
hid_device
*
hid
,
struct
hid_field
*
field
,
static
int
mt_
touch_
event
(
struct
hid_device
*
hid
,
struct
hid_field
*
field
,
struct
hid_usage
*
usage
,
__s32
value
)
struct
hid_usage
*
usage
,
__s32
value
)
{
{
/* we will handle the hidinput part later, now remains hiddev */
/* we will handle the hidinput part later, now remains hiddev */
...
@@ -691,29 +727,19 @@ static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field,
...
@@ -691,29 +727,19 @@ static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field,
if
(
usage
->
usage_index
+
1
==
field
->
report_count
)
{
if
(
usage
->
usage_index
+
1
==
field
->
report_count
)
{
/* we only take into account the last report. */
/* we only take into account the last report. */
if
(
usage
->
hid
==
td
->
last_slot_field
)
if
(
usage
->
hid
==
td
->
last_slot_field
)
mt_complete_slot
(
td
,
input
);
mt_complete_slot
(
td
,
field
->
hidinput
->
input
);
if
(
field
->
index
==
td
->
last_field_index
&&
td
->
num_received
>=
td
->
num_expected
)
mt_sync_frame
(
td
,
field
->
hidinput
->
input
);
}
}
}
}
}
}
static
void
mt_report
(
struct
hid_device
*
hid
,
struct
hid_report
*
report
)
static
void
mt_
touch_
report
(
struct
hid_device
*
hid
,
struct
hid_report
*
report
)
{
{
struct
mt_device
*
td
=
hid_get_drvdata
(
hid
);
struct
mt_device
*
td
=
hid_get_drvdata
(
hid
);
struct
hid_field
*
field
;
struct
hid_field
*
field
;
unsigned
count
;
unsigned
count
;
int
r
,
n
;
int
r
,
n
;
if
(
report
->
id
!=
td
->
mt_report_id
)
return
;
if
(
!
(
hid
->
claimed
&
HID_CLAIMED_INPUT
))
return
;
/*
/*
* Includes multi-packet support where subsequent
* Includes multi-packet support where subsequent
* packets are sent with zero contactcount.
* packets are sent with zero contactcount.
...
@@ -736,6 +762,91 @@ static void mt_report(struct hid_device *hid, struct hid_report *report)
...
@@ -736,6 +762,91 @@ static void mt_report(struct hid_device *hid, struct hid_report *report)
mt_process_mt_event
(
hid
,
field
,
&
field
->
usage
[
n
],
mt_process_mt_event
(
hid
,
field
,
&
field
->
usage
[
n
],
field
->
value
[
n
]);
field
->
value
[
n
]);
}
}
if
(
td
->
num_received
>=
td
->
num_expected
)
mt_sync_frame
(
td
,
report
->
field
[
0
]
->
hidinput
->
input
);
}
static
void
mt_touch_input_configured
(
struct
hid_device
*
hdev
,
struct
hid_input
*
hi
)
{
struct
mt_device
*
td
=
hid_get_drvdata
(
hdev
);
struct
mt_class
*
cls
=
&
td
->
mtclass
;
struct
input_dev
*
input
=
hi
->
input
;
if
(
!
td
->
maxcontacts
)
td
->
maxcontacts
=
MT_DEFAULT_MAXCONTACT
;
mt_post_parse
(
td
);
if
(
td
->
serial_maybe
)
mt_post_parse_default_settings
(
td
);
if
(
cls
->
is_indirect
)
td
->
mt_flags
|=
INPUT_MT_POINTER
;
if
(
cls
->
quirks
&
MT_QUIRK_NOT_SEEN_MEANS_UP
)
td
->
mt_flags
|=
INPUT_MT_DROP_UNUSED
;
input_mt_init_slots
(
input
,
td
->
maxcontacts
,
td
->
mt_flags
);
td
->
mt_flags
=
0
;
}
static
int
mt_input_mapping
(
struct
hid_device
*
hdev
,
struct
hid_input
*
hi
,
struct
hid_field
*
field
,
struct
hid_usage
*
usage
,
unsigned
long
**
bit
,
int
*
max
)
{
/* Only map fields from TouchScreen or TouchPad collections.
* We need to ignore fields that belong to other collections
* such as Mouse that might have the same GenericDesktop usages. */
if
(
field
->
application
!=
HID_DG_TOUCHSCREEN
&&
field
->
application
!=
HID_DG_PEN
&&
field
->
application
!=
HID_DG_TOUCHPAD
)
return
-
1
;
if
(
field
->
physical
==
HID_DG_STYLUS
)
return
mt_pen_input_mapping
(
hdev
,
hi
,
field
,
usage
,
bit
,
max
);
return
mt_touch_input_mapping
(
hdev
,
hi
,
field
,
usage
,
bit
,
max
);
}
static
int
mt_input_mapped
(
struct
hid_device
*
hdev
,
struct
hid_input
*
hi
,
struct
hid_field
*
field
,
struct
hid_usage
*
usage
,
unsigned
long
**
bit
,
int
*
max
)
{
if
(
field
->
physical
==
HID_DG_STYLUS
)
return
mt_pen_input_mapped
(
hdev
,
hi
,
field
,
usage
,
bit
,
max
);
return
mt_touch_input_mapped
(
hdev
,
hi
,
field
,
usage
,
bit
,
max
);
}
static
int
mt_event
(
struct
hid_device
*
hid
,
struct
hid_field
*
field
,
struct
hid_usage
*
usage
,
__s32
value
)
{
struct
mt_device
*
td
=
hid_get_drvdata
(
hid
);
if
(
field
->
report
->
id
==
td
->
mt_report_id
)
return
mt_touch_event
(
hid
,
field
,
usage
,
value
);
if
(
field
->
report
->
id
==
td
->
pen_report_id
)
return
mt_pen_event
(
hid
,
field
,
usage
,
value
);
/* ignore other reports */
return
1
;
}
static
void
mt_report
(
struct
hid_device
*
hid
,
struct
hid_report
*
report
)
{
struct
mt_device
*
td
=
hid_get_drvdata
(
hid
);
if
(
!
(
hid
->
claimed
&
HID_CLAIMED_INPUT
))
return
;
if
(
report
->
id
==
td
->
mt_report_id
)
mt_touch_report
(
hid
,
report
);
if
(
report
->
id
==
td
->
pen_report_id
)
mt_pen_report
(
hid
,
report
);
}
}
static
void
mt_set_input_mode
(
struct
hid_device
*
hdev
)
static
void
mt_set_input_mode
(
struct
hid_device
*
hdev
)
...
@@ -812,32 +923,18 @@ static void mt_post_parse(struct mt_device *td)
...
@@ -812,32 +923,18 @@ static void mt_post_parse(struct mt_device *td)
}
}
static
void
mt_input_configured
(
struct
hid_device
*
hdev
,
struct
hid_input
*
hi
)
static
void
mt_input_configured
(
struct
hid_device
*
hdev
,
struct
hid_input
*
hi
)
{
{
struct
mt_device
*
td
=
hid_get_drvdata
(
hdev
);
struct
mt_device
*
td
=
hid_get_drvdata
(
hdev
);
struct
mt_class
*
cls
=
&
td
->
mtclass
;
char
*
name
=
kstrdup
(
hdev
->
name
,
GFP_KERNEL
);
struct
input_dev
*
input
=
hi
->
input
;
/* Only initialize slots for MT input devices */
if
(
name
)
if
(
!
test_bit
(
ABS_MT_POSITION_X
,
input
->
absbit
))
hi
->
input
->
name
=
name
;
return
;
if
(
!
td
->
maxcontacts
)
if
(
hi
->
report
->
id
==
td
->
mt_report_id
)
td
->
maxcontacts
=
MT_DEFAULT_MAXCONTACT
;
mt_touch_input_configured
(
hdev
,
hi
)
;
mt_post_parse
(
td
);
if
(
hi
->
report
->
id
==
td
->
pen_report_id
)
if
(
td
->
serial_maybe
)
mt_pen_input_configured
(
hdev
,
hi
);
mt_post_parse_default_settings
(
td
);
if
(
cls
->
is_indirect
)
td
->
mt_flags
|=
INPUT_MT_POINTER
;
if
(
cls
->
quirks
&
MT_QUIRK_NOT_SEEN_MEANS_UP
)
td
->
mt_flags
|=
INPUT_MT_DROP_UNUSED
;
input_mt_init_slots
(
input
,
td
->
maxcontacts
,
td
->
mt_flags
);
td
->
mt_flags
=
0
;
}
}
static
int
mt_probe
(
struct
hid_device
*
hdev
,
const
struct
hid_device_id
*
id
)
static
int
mt_probe
(
struct
hid_device
*
hdev
,
const
struct
hid_device_id
*
id
)
...
@@ -845,6 +942,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
...
@@ -845,6 +942,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
int
ret
,
i
;
int
ret
,
i
;
struct
mt_device
*
td
;
struct
mt_device
*
td
;
struct
mt_class
*
mtclass
=
mt_classes
;
/* MT_CLS_DEFAULT */
struct
mt_class
*
mtclass
=
mt_classes
;
/* MT_CLS_DEFAULT */
struct
hid_input
*
hi
;
for
(
i
=
0
;
mt_classes
[
i
].
name
;
i
++
)
{
for
(
i
=
0
;
mt_classes
[
i
].
name
;
i
++
)
{
if
(
id
->
driver_data
==
mt_classes
[
i
].
name
)
{
if
(
id
->
driver_data
==
mt_classes
[
i
].
name
)
{
...
@@ -858,6 +956,14 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
...
@@ -858,6 +956,14 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
*/
*/
hdev
->
quirks
|=
HID_QUIRK_NO_INPUT_SYNC
;
hdev
->
quirks
|=
HID_QUIRK_NO_INPUT_SYNC
;
/*
* This allows the driver to handle different input sensors
* that emits events through different reports on the same HID
* device.
*/
hdev
->
quirks
|=
HID_QUIRK_MULTI_INPUT
;
hdev
->
quirks
|=
HID_QUIRK_NO_EMPTY_INPUT
;
td
=
kzalloc
(
sizeof
(
struct
mt_device
),
GFP_KERNEL
);
td
=
kzalloc
(
sizeof
(
struct
mt_device
),
GFP_KERNEL
);
if
(
!
td
)
{
if
(
!
td
)
{
dev_err
(
&
hdev
->
dev
,
"cannot allocate multitouch data
\n
"
);
dev_err
(
&
hdev
->
dev
,
"cannot allocate multitouch data
\n
"
);
...
@@ -867,6 +973,8 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
...
@@ -867,6 +973,8 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
td
->
inputmode
=
-
1
;
td
->
inputmode
=
-
1
;
td
->
maxcontact_report_id
=
-
1
;
td
->
maxcontact_report_id
=
-
1
;
td
->
cc_index
=
-
1
;
td
->
cc_index
=
-
1
;
td
->
mt_report_id
=
-
1
;
td
->
pen_report_id
=
-
1
;
hid_set_drvdata
(
hdev
,
td
);
hid_set_drvdata
(
hdev
,
td
);
td
->
fields
=
kzalloc
(
sizeof
(
struct
mt_fields
),
GFP_KERNEL
);
td
->
fields
=
kzalloc
(
sizeof
(
struct
mt_fields
),
GFP_KERNEL
);
...
@@ -885,7 +993,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
...
@@ -885,7 +993,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
ret
=
hid_hw_start
(
hdev
,
HID_CONNECT_DEFAULT
);
ret
=
hid_hw_start
(
hdev
,
HID_CONNECT_DEFAULT
);
if
(
ret
)
if
(
ret
)
goto
fail
;
goto
hid_
fail
;
ret
=
sysfs_create_group
(
&
hdev
->
dev
.
kobj
,
&
mt_attribute_group
);
ret
=
sysfs_create_group
(
&
hdev
->
dev
.
kobj
,
&
mt_attribute_group
);
...
@@ -897,6 +1005,9 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
...
@@ -897,6 +1005,9 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
return
0
;
return
0
;
hid_fail:
list_for_each_entry
(
hi
,
&
hdev
->
inputs
,
list
)
mt_free_input_name
(
hi
);
fail:
fail:
kfree
(
td
->
fields
);
kfree
(
td
->
fields
);
kfree
(
td
);
kfree
(
td
);
...
@@ -926,8 +1037,14 @@ static int mt_resume(struct hid_device *hdev)
...
@@ -926,8 +1037,14 @@ static int mt_resume(struct hid_device *hdev)
static
void
mt_remove
(
struct
hid_device
*
hdev
)
static
void
mt_remove
(
struct
hid_device
*
hdev
)
{
{
struct
mt_device
*
td
=
hid_get_drvdata
(
hdev
);
struct
mt_device
*
td
=
hid_get_drvdata
(
hdev
);
struct
hid_input
*
hi
;
sysfs_remove_group
(
&
hdev
->
dev
.
kobj
,
&
mt_attribute_group
);
sysfs_remove_group
(
&
hdev
->
dev
.
kobj
,
&
mt_attribute_group
);
hid_hw_stop
(
hdev
);
hid_hw_stop
(
hdev
);
list_for_each_entry
(
hi
,
&
hdev
->
inputs
,
list
)
mt_free_input_name
(
hi
);
kfree
(
td
);
kfree
(
td
);
hid_set_drvdata
(
hdev
,
NULL
);
hid_set_drvdata
(
hdev
,
NULL
);
}
}
...
...
include/linux/hid.h
View file @
72c16d9a
...
@@ -282,6 +282,7 @@ struct hid_item {
...
@@ -282,6 +282,7 @@ struct hid_item {
#define HID_QUIRK_BADPAD 0x00000020
#define HID_QUIRK_BADPAD 0x00000020
#define HID_QUIRK_MULTI_INPUT 0x00000040
#define HID_QUIRK_MULTI_INPUT 0x00000040
#define HID_QUIRK_HIDINPUT_FORCE 0x00000080
#define HID_QUIRK_HIDINPUT_FORCE 0x00000080
#define HID_QUIRK_NO_EMPTY_INPUT 0x00000100
#define HID_QUIRK_SKIP_OUTPUT_REPORTS 0x00010000
#define HID_QUIRK_SKIP_OUTPUT_REPORTS 0x00010000
#define HID_QUIRK_FULLSPEED_INTERVAL 0x10000000
#define HID_QUIRK_FULLSPEED_INTERVAL 0x10000000
#define HID_QUIRK_NO_INIT_REPORTS 0x20000000
#define HID_QUIRK_NO_INIT_REPORTS 0x20000000
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment