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
nexedi
linux
Commits
9931753b
Commit
9931753b
authored
Apr 05, 2018
by
Jiri Kosina
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'for-4.17/wacom' into for-linus
Pull support for 3rd generation Intuos BT device
parents
e2d39e0f
7ba8fc09
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
179 additions
and
48 deletions
+179
-48
drivers/hid/wacom_wac.c
drivers/hid/wacom_wac.c
+176
-47
drivers/hid/wacom_wac.h
drivers/hid/wacom_wac.h
+3
-1
No files found.
drivers/hid/wacom_wac.c
View file @
9931753b
...
...
@@ -1202,15 +1202,24 @@ static int wacom_wac_finger_count_touches(struct wacom_wac *wacom)
static
void
wacom_intuos_pro2_bt_pen
(
struct
wacom_wac
*
wacom
)
{
const
int
pen_frame_len
=
14
;
const
int
pen_frames
=
7
;
int
pen_frame_len
,
pen_frames
;
struct
input_dev
*
pen_input
=
wacom
->
pen_input
;
unsigned
char
*
data
=
wacom
->
data
;
int
i
;
wacom
->
serial
[
0
]
=
get_unaligned_le64
(
&
data
[
99
]);
wacom
->
id
[
0
]
=
get_unaligned_le16
(
&
data
[
107
]);
if
(
wacom
->
features
.
type
==
INTUOSP2_BT
)
{
wacom
->
serial
[
0
]
=
get_unaligned_le64
(
&
data
[
99
]);
wacom
->
id
[
0
]
=
get_unaligned_le16
(
&
data
[
107
]);
pen_frame_len
=
14
;
pen_frames
=
7
;
}
else
{
wacom
->
serial
[
0
]
=
get_unaligned_le64
(
&
data
[
33
]);
wacom
->
id
[
0
]
=
get_unaligned_le16
(
&
data
[
41
]);
pen_frame_len
=
8
;
pen_frames
=
4
;
}
if
(
wacom
->
serial
[
0
]
>>
52
==
1
)
{
/* Add back in missing bits of ID for non-USI pens */
wacom
->
id
[
0
]
|=
(
wacom
->
serial
[
0
]
>>
32
)
&
0xFFFFF
;
...
...
@@ -1227,21 +1236,35 @@ static void wacom_intuos_pro2_bt_pen(struct wacom_wac *wacom)
continue
;
if
(
range
)
{
/* Fix rotation alignment: userspace expects zero at left */
int16_t
rotation
=
(
int16_t
)
get_unaligned_le16
(
&
frame
[
9
]);
rotation
+=
1800
/
4
;
if
(
rotation
>
899
)
rotation
-=
1800
;
input_report_abs
(
pen_input
,
ABS_X
,
get_unaligned_le16
(
&
frame
[
1
]));
input_report_abs
(
pen_input
,
ABS_Y
,
get_unaligned_le16
(
&
frame
[
3
]));
input_report_abs
(
pen_input
,
ABS_TILT_X
,
(
char
)
frame
[
7
]);
input_report_abs
(
pen_input
,
ABS_TILT_Y
,
(
char
)
frame
[
8
]);
input_report_abs
(
pen_input
,
ABS_Z
,
rotation
);
input_report_abs
(
pen_input
,
ABS_WHEEL
,
get_unaligned_le16
(
&
frame
[
11
]));
if
(
wacom
->
features
.
type
==
INTUOSP2_BT
)
{
/* Fix rotation alignment: userspace expects zero at left */
int16_t
rotation
=
(
int16_t
)
get_unaligned_le16
(
&
frame
[
9
]);
rotation
+=
1800
/
4
;
if
(
rotation
>
899
)
rotation
-=
1800
;
input_report_abs
(
pen_input
,
ABS_TILT_X
,
(
char
)
frame
[
7
]);
input_report_abs
(
pen_input
,
ABS_TILT_Y
,
(
char
)
frame
[
8
]);
input_report_abs
(
pen_input
,
ABS_Z
,
rotation
);
input_report_abs
(
pen_input
,
ABS_WHEEL
,
get_unaligned_le16
(
&
frame
[
11
]));
}
}
input_report_abs
(
pen_input
,
ABS_PRESSURE
,
get_unaligned_le16
(
&
frame
[
5
]));
input_report_abs
(
pen_input
,
ABS_DISTANCE
,
range
?
frame
[
13
]
:
wacom
->
features
.
distance_max
);
if
(
wacom
->
features
.
type
==
INTUOSP2_BT
)
{
input_report_abs
(
pen_input
,
ABS_DISTANCE
,
range
?
frame
[
13
]
:
wacom
->
features
.
distance_max
);
}
else
{
input_report_abs
(
pen_input
,
ABS_DISTANCE
,
range
?
frame
[
7
]
:
wacom
->
features
.
distance_max
);
}
input_report_key
(
pen_input
,
BTN_TOUCH
,
frame
[
0
]
&
0x01
);
input_report_key
(
pen_input
,
BTN_STYLUS
,
frame
[
0
]
&
0x02
);
...
...
@@ -1357,20 +1380,52 @@ static void wacom_intuos_pro2_bt_battery(struct wacom_wac *wacom)
battery_status
,
chg
,
1
,
chg
);
}
static
void
wacom_intuos_gen3_bt_pad
(
struct
wacom_wac
*
wacom
)
{
struct
input_dev
*
pad_input
=
wacom
->
pad_input
;
unsigned
char
*
data
=
wacom
->
data
;
int
buttons
=
data
[
44
];
wacom_report_numbered_buttons
(
pad_input
,
4
,
buttons
);
input_report_key
(
pad_input
,
wacom
->
tool
[
1
],
buttons
?
1
:
0
);
input_report_abs
(
pad_input
,
ABS_MISC
,
buttons
?
PAD_DEVICE_ID
:
0
);
input_event
(
pad_input
,
EV_MSC
,
MSC_SERIAL
,
0xffffffff
);
input_sync
(
pad_input
);
}
static
void
wacom_intuos_gen3_bt_battery
(
struct
wacom_wac
*
wacom
)
{
unsigned
char
*
data
=
wacom
->
data
;
bool
chg
=
data
[
45
]
&
0x80
;
int
battery_status
=
data
[
45
]
&
0x7F
;
wacom_notify_battery
(
wacom
,
WACOM_POWER_SUPPLY_STATUS_AUTO
,
battery_status
,
chg
,
1
,
chg
);
}
static
int
wacom_intuos_pro2_bt_irq
(
struct
wacom_wac
*
wacom
,
size_t
len
)
{
unsigned
char
*
data
=
wacom
->
data
;
if
(
data
[
0
]
!=
0x80
)
{
if
(
data
[
0
]
!=
0x80
&&
data
[
0
]
!=
0x81
)
{
dev_dbg
(
wacom
->
pen_input
->
dev
.
parent
,
"%s: received unknown report #%d
\n
"
,
__func__
,
data
[
0
]);
return
0
;
}
wacom_intuos_pro2_bt_pen
(
wacom
);
wacom_intuos_pro2_bt_touch
(
wacom
);
wacom_intuos_pro2_bt_pad
(
wacom
);
wacom_intuos_pro2_bt_battery
(
wacom
);
if
(
wacom
->
features
.
type
==
INTUOSP2_BT
)
{
wacom_intuos_pro2_bt_touch
(
wacom
);
wacom_intuos_pro2_bt_pad
(
wacom
);
wacom_intuos_pro2_bt_battery
(
wacom
);
}
else
{
wacom_intuos_gen3_bt_pad
(
wacom
);
wacom_intuos_gen3_bt_battery
(
wacom
);
}
return
0
;
}
...
...
@@ -1660,7 +1715,8 @@ int wacom_equivalent_usage(int usage)
usage
==
WACOM_HID_WD_TOUCHSTRIP
||
usage
==
WACOM_HID_WD_TOUCHSTRIP2
||
usage
==
WACOM_HID_WD_TOUCHRING
||
usage
==
WACOM_HID_WD_TOUCHRINGSTATUS
)
{
usage
==
WACOM_HID_WD_TOUCHRINGSTATUS
||
usage
==
WACOM_HID_WD_REPORT_VALID
)
{
return
usage
;
}
...
...
@@ -2017,7 +2073,7 @@ static void wacom_wac_pad_pre_report(struct hid_device *hdev,
}
static
void
wacom_wac_pad_report
(
struct
hid_device
*
hdev
,
struct
hid_report
*
report
)
struct
hid_report
*
report
,
struct
hid_field
*
field
)
{
struct
wacom
*
wacom
=
hid_get_drvdata
(
hdev
);
struct
wacom_wac
*
wacom_wac
=
&
wacom
->
wacom_wac
;
...
...
@@ -2025,7 +2081,7 @@ static void wacom_wac_pad_report(struct hid_device *hdev,
bool
active
=
wacom_wac
->
hid_data
.
inrange_state
!=
0
;
/* report prox for expresskey events */
if
((
wacom_equivalent_usage
(
report
->
field
[
0
]
->
physical
)
==
HID_DG_TABLETFUNCTIONKEY
)
&&
if
((
wacom_equivalent_usage
(
field
->
physical
)
==
HID_DG_TABLETFUNCTIONKEY
)
&&
wacom_wac
->
hid_data
.
pad_input_event_flag
)
{
input_event
(
input
,
EV_ABS
,
ABS_MISC
,
active
?
PAD_DEVICE_ID
:
0
);
input_sync
(
input
);
...
...
@@ -2144,6 +2200,9 @@ static void wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field
struct
input_dev
*
input
=
wacom_wac
->
pen_input
;
unsigned
equivalent_usage
=
wacom_equivalent_usage
(
usage
->
hid
);
if
(
wacom_wac
->
is_invalid_bt_frame
)
return
;
switch
(
equivalent_usage
)
{
case
HID_GD_Z
:
/*
...
...
@@ -2240,6 +2299,9 @@ static void wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field
features
->
offset_bottom
);
features
->
offset_bottom
=
value
;
return
;
case
WACOM_HID_WD_REPORT_VALID
:
wacom_wac
->
is_invalid_bt_frame
=
!
value
;
return
;
}
/* send pen events only when touch is up or forced out
...
...
@@ -2258,6 +2320,10 @@ static void wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field
static
void
wacom_wac_pen_pre_report
(
struct
hid_device
*
hdev
,
struct
hid_report
*
report
)
{
struct
wacom
*
wacom
=
hid_get_drvdata
(
hdev
);
struct
wacom_wac
*
wacom_wac
=
&
wacom
->
wacom_wac
;
wacom_wac
->
is_invalid_bt_frame
=
false
;
return
;
}
...
...
@@ -2270,6 +2336,9 @@ static void wacom_wac_pen_report(struct hid_device *hdev,
bool
range
=
wacom_wac
->
hid_data
.
inrange_state
;
bool
sense
=
wacom_wac
->
hid_data
.
sense_state
;
if
(
wacom_wac
->
is_invalid_bt_frame
)
return
;
if
(
!
wacom_wac
->
tool
[
0
]
&&
range
)
{
/* first in range */
/* Going into range select tool */
if
(
wacom_wac
->
hid_data
.
invert_state
)
...
...
@@ -2572,11 +2641,13 @@ void wacom_wac_event(struct hid_device *hdev, struct hid_field *field,
wacom_wac_finger_event
(
hdev
,
field
,
usage
,
value
);
}
static
void
wacom_report_events
(
struct
hid_device
*
hdev
,
struct
hid_report
*
report
)
static
void
wacom_report_events
(
struct
hid_device
*
hdev
,
struct
hid_report
*
report
,
int
collection_index
,
int
field_index
)
{
int
r
;
for
(
r
=
0
;
r
<
report
->
maxfield
;
r
++
)
{
for
(
r
=
field_index
;
r
<
report
->
maxfield
;
r
++
)
{
struct
hid_field
*
field
;
unsigned
count
,
n
;
...
...
@@ -2586,30 +2657,23 @@ static void wacom_report_events(struct hid_device *hdev, struct hid_report *repo
if
(
!
(
HID_MAIN_ITEM_VARIABLE
&
field
->
flags
))
continue
;
for
(
n
=
0
;
n
<
count
;
n
++
)
wacom_wac_event
(
hdev
,
field
,
&
field
->
usage
[
n
],
field
->
value
[
n
]);
for
(
n
=
0
;
n
<
count
;
n
++
)
{
if
(
field
->
usage
[
n
].
collection_index
==
collection_index
)
wacom_wac_event
(
hdev
,
field
,
&
field
->
usage
[
n
],
field
->
value
[
n
]);
else
return
;
}
}
}
void
wacom_wac_report
(
struct
hid_device
*
hdev
,
struct
hid_report
*
report
)
static
int
wacom_wac_collection
(
struct
hid_device
*
hdev
,
struct
hid_report
*
report
,
int
collection_index
,
struct
hid_field
*
field
,
int
field_index
)
{
struct
wacom
*
wacom
=
hid_get_drvdata
(
hdev
);
struct
wacom_wac
*
wacom_wac
=
&
wacom
->
wacom_wac
;
struct
hid_field
*
field
=
report
->
field
[
0
];
if
(
wacom_wac
->
features
.
type
!=
HID_GENERIC
)
return
;
wacom_wac_battery_pre_report
(
hdev
,
report
);
if
(
WACOM_PAD_FIELD
(
field
)
&&
wacom
->
wacom_wac
.
pad_input
)
wacom_wac_pad_pre_report
(
hdev
,
report
);
else
if
(
WACOM_PEN_FIELD
(
field
)
&&
wacom
->
wacom_wac
.
pen_input
)
wacom_wac_pen_pre_report
(
hdev
,
report
);
else
if
(
WACOM_FINGER_FIELD
(
field
)
&&
wacom
->
wacom_wac
.
touch_input
)
wacom_wac_finger_pre_report
(
hdev
,
report
);
wacom_report_events
(
hdev
,
report
);
wacom_report_events
(
hdev
,
report
,
collection_index
,
field_index
);
/*
* Non-input reports may be sent prior to the device being
...
...
@@ -2619,16 +2683,63 @@ void wacom_wac_report(struct hid_device *hdev, struct hid_report *report)
* processing functions.
*/
if
(
report
->
type
!=
HID_INPUT_REPORT
)
return
;
wacom_wac_battery_report
(
hdev
,
report
);
return
-
1
;
if
(
WACOM_PAD_FIELD
(
field
)
&&
wacom
->
wacom_wac
.
pad_input
)
wacom_wac_pad_report
(
hdev
,
report
);
wacom_wac_pad_report
(
hdev
,
report
,
field
);
else
if
(
WACOM_PEN_FIELD
(
field
)
&&
wacom
->
wacom_wac
.
pen_input
)
wacom_wac_pen_report
(
hdev
,
report
);
else
if
(
WACOM_FINGER_FIELD
(
field
)
&&
wacom
->
wacom_wac
.
touch_input
)
wacom_wac_finger_report
(
hdev
,
report
);
return
0
;
}
void
wacom_wac_report
(
struct
hid_device
*
hdev
,
struct
hid_report
*
report
)
{
struct
wacom
*
wacom
=
hid_get_drvdata
(
hdev
);
struct
wacom_wac
*
wacom_wac
=
&
wacom
->
wacom_wac
;
struct
hid_field
*
field
;
bool
pad_in_hid_field
=
false
,
pen_in_hid_field
=
false
,
finger_in_hid_field
=
false
;
int
r
;
int
prev_collection
=
-
1
;
if
(
wacom_wac
->
features
.
type
!=
HID_GENERIC
)
return
;
for
(
r
=
0
;
r
<
report
->
maxfield
;
r
++
)
{
field
=
report
->
field
[
r
];
if
(
WACOM_PAD_FIELD
(
field
))
pad_in_hid_field
=
true
;
if
(
WACOM_PEN_FIELD
(
field
))
pen_in_hid_field
=
true
;
if
(
WACOM_FINGER_FIELD
(
field
))
finger_in_hid_field
=
true
;
}
wacom_wac_battery_pre_report
(
hdev
,
report
);
if
(
pad_in_hid_field
&&
wacom
->
wacom_wac
.
pad_input
)
wacom_wac_pad_pre_report
(
hdev
,
report
);
if
(
pen_in_hid_field
&&
wacom
->
wacom_wac
.
pen_input
)
wacom_wac_pen_pre_report
(
hdev
,
report
);
if
(
finger_in_hid_field
&&
wacom
->
wacom_wac
.
touch_input
)
wacom_wac_finger_pre_report
(
hdev
,
report
);
for
(
r
=
0
;
r
<
report
->
maxfield
;
r
++
)
{
field
=
report
->
field
[
r
];
if
(
field
->
usage
[
0
].
collection_index
!=
prev_collection
)
{
if
(
wacom_wac_collection
(
hdev
,
report
,
field
->
usage
[
0
].
collection_index
,
field
,
r
)
<
0
)
return
;
prev_collection
=
field
->
usage
[
0
].
collection_index
;
}
}
wacom_wac_battery_report
(
hdev
,
report
);
}
static
int
wacom_bpt_touch
(
struct
wacom_wac
*
wacom
)
...
...
@@ -3093,6 +3204,7 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
break
;
case
INTUOSP2_BT
:
case
INTUOSHT3_BT
:
sync
=
wacom_intuos_pro2_bt_irq
(
wacom_wac
,
len
);
break
;
...
...
@@ -3272,6 +3384,12 @@ void wacom_setup_device_quirks(struct wacom *wacom)
features
->
quirks
|=
WACOM_QUIRK_BATTERY
;
}
if
(
features
->
type
==
INTUOSHT3_BT
)
{
features
->
device_type
|=
WACOM_DEVICETYPE_PEN
|
WACOM_DEVICETYPE_PAD
;
features
->
quirks
|=
WACOM_QUIRK_BATTERY
;
}
switch
(
features
->
type
)
{
case
PL
:
case
DTU
:
...
...
@@ -3466,7 +3584,9 @@ int wacom_setup_pen_input_capabilities(struct input_dev *input_dev,
case
BAMBOO_PT
:
case
BAMBOO_PEN
:
case
INTUOSHT2
:
if
(
features
->
type
==
INTUOSHT2
)
{
case
INTUOSHT3_BT
:
if
(
features
->
type
==
INTUOSHT2
||
features
->
type
==
INTUOSHT3_BT
)
{
wacom_setup_basic_pro_pen
(
wacom_wac
);
}
else
{
__clear_bit
(
ABS_MISC
,
input_dev
->
absbit
);
...
...
@@ -3887,6 +4007,7 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
input_set_abs_params
(
input_dev
,
ABS_WHEEL
,
0
,
71
,
0
,
0
);
break
;
case
INTUOSHT3_BT
:
case
HID_GENERIC
:
break
;
...
...
@@ -4415,6 +4536,12 @@ static const struct wacom_features wacom_features_0x360 =
static
const
struct
wacom_features
wacom_features_0x361
=
{
"Wacom Intuos Pro L"
,
62200
,
43200
,
8191
,
63
,
INTUOSP2_BT
,
WACOM_INTUOS3_RES
,
WACOM_INTUOS3_RES
,
9
,
.
touch_max
=
10
};
static
const
struct
wacom_features
wacom_features_0x377
=
{
"Wacom Intuos BT S"
,
15200
,
9500
,
4095
,
63
,
INTUOSHT3_BT
,
WACOM_INTUOS_RES
,
WACOM_INTUOS_RES
,
4
};
static
const
struct
wacom_features
wacom_features_0x379
=
{
"Wacom Intuos BT M"
,
21600
,
13500
,
4095
,
63
,
INTUOSHT3_BT
,
WACOM_INTUOS_RES
,
WACOM_INTUOS_RES
,
4
};
static
const
struct
wacom_features
wacom_features_0x37A
=
{
"Wacom One by Wacom S"
,
15200
,
9500
,
2047
,
63
,
BAMBOO_PEN
,
WACOM_INTUOS_RES
,
WACOM_INTUOS_RES
};
...
...
@@ -4589,6 +4716,8 @@ const struct hid_device_id wacom_ids[] = {
{
USB_DEVICE_WACOM
(
0x343
)
},
{
BT_DEVICE_WACOM
(
0x360
)
},
{
BT_DEVICE_WACOM
(
0x361
)
},
{
BT_DEVICE_WACOM
(
0x377
)
},
{
BT_DEVICE_WACOM
(
0x379
)
},
{
USB_DEVICE_WACOM
(
0x37A
)
},
{
USB_DEVICE_WACOM
(
0x37B
)
},
{
USB_DEVICE_WACOM
(
0x4001
)
},
...
...
drivers/hid/wacom_wac.h
View file @
9931753b
...
...
@@ -118,6 +118,7 @@
#define WACOM_HID_WD_TOUCHSTRIP2 (WACOM_HID_UP_WACOMDIGITIZER | 0x0137)
#define WACOM_HID_WD_TOUCHRING (WACOM_HID_UP_WACOMDIGITIZER | 0x0138)
#define WACOM_HID_WD_TOUCHRINGSTATUS (WACOM_HID_UP_WACOMDIGITIZER | 0x0139)
#define WACOM_HID_WD_REPORT_VALID (WACOM_HID_UP_WACOMDIGITIZER | 0x01d0)
#define WACOM_HID_WD_ACCELEROMETER_X (WACOM_HID_UP_WACOMDIGITIZER | 0x0401)
#define WACOM_HID_WD_ACCELEROMETER_Y (WACOM_HID_UP_WACOMDIGITIZER | 0x0402)
#define WACOM_HID_WD_ACCELEROMETER_Z (WACOM_HID_UP_WACOMDIGITIZER | 0x0403)
...
...
@@ -213,6 +214,7 @@ enum {
INTUOSPM
,
INTUOSPL
,
INTUOSP2_BT
,
INTUOSHT3_BT
,
WACOM_21UX2
,
WACOM_22HD
,
DTK
,
...
...
@@ -352,7 +354,7 @@ struct wacom_wac {
bool
has_mute_touch_switch
;
bool
has_mode_change
;
bool
is_direct_mode
;
bool
is_invalid_bt_frame
;
};
#endif
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