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
5099bc83
Commit
5099bc83
authored
Oct 23, 2018
by
Jiri Kosina
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'for-4.20/microsoft' into for-linus
Rumble support for Xbox One S
parents
276e7227
830e82aa
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
138 additions
and
5 deletions
+138
-5
drivers/hid/Kconfig
drivers/hid/Kconfig
+1
-0
drivers/hid/hid-ids.h
drivers/hid/hid-ids.h
+1
-0
drivers/hid/hid-microsoft.c
drivers/hid/hid-microsoft.c
+136
-5
No files found.
drivers/hid/Kconfig
View file @
5099bc83
...
...
@@ -609,6 +609,7 @@ config HID_MICROSOFT
tristate "Microsoft non-fully HID-compliant devices"
depends on HID
default !EXPERT
select INPUT_FF_MEMLESS
---help---
Support for Microsoft devices that are not fully compliant with HID standard.
...
...
drivers/hid/hid-ids.h
View file @
5099bc83
...
...
@@ -804,6 +804,7 @@
#define USB_DEVICE_ID_MS_TOUCH_COVER_2 0x07a7
#define USB_DEVICE_ID_MS_TYPE_COVER_2 0x07a9
#define USB_DEVICE_ID_MS_POWER_COVER 0x07da
#define USB_DEVICE_ID_MS_XBOX_ONE_S_CONTROLLER 0x02fd
#define USB_VENDOR_ID_MOJO 0x8282
#define USB_DEVICE_ID_RETRO_ADAPTER 0x3201
...
...
drivers/hid/hid-microsoft.c
View file @
5099bc83
...
...
@@ -29,11 +29,41 @@
#define MS_NOGET BIT(4)
#define MS_DUPLICATE_USAGES BIT(5)
#define MS_SURFACE_DIAL BIT(6)
#define MS_QUIRK_FF BIT(7)
struct
ms_data
{
unsigned
long
quirks
;
struct
hid_device
*
hdev
;
struct
work_struct
ff_worker
;
__u8
strong
;
__u8
weak
;
void
*
output_report_dmabuf
;
};
#define XB1S_FF_REPORT 3
#define ENABLE_WEAK BIT(0)
#define ENABLE_STRONG BIT(1)
enum
{
MAGNITUDE_STRONG
=
2
,
MAGNITUDE_WEAK
,
MAGNITUDE_NUM
};
struct
xb1s_ff_report
{
__u8
report_id
;
__u8
enable
;
__u8
magnitude
[
MAGNITUDE_NUM
];
__u8
duration_10ms
;
__u8
start_delay_10ms
;
__u8
loop_count
;
}
__packed
;
static
__u8
*
ms_report_fixup
(
struct
hid_device
*
hdev
,
__u8
*
rdesc
,
unsigned
int
*
rsize
)
{
unsigned
long
quirks
=
(
unsigned
long
)
hid_get_drvdata
(
hdev
);
struct
ms_data
*
ms
=
hid_get_drvdata
(
hdev
);
unsigned
long
quirks
=
ms
->
quirks
;
/*
* Microsoft Wireless Desktop Receiver (Model 1028) has
...
...
@@ -159,7 +189,8 @@ static int ms_input_mapping(struct hid_device *hdev, struct hid_input *hi,
struct
hid_field
*
field
,
struct
hid_usage
*
usage
,
unsigned
long
**
bit
,
int
*
max
)
{
unsigned
long
quirks
=
(
unsigned
long
)
hid_get_drvdata
(
hdev
);
struct
ms_data
*
ms
=
hid_get_drvdata
(
hdev
);
unsigned
long
quirks
=
ms
->
quirks
;
if
(
quirks
&
MS_ERGONOMY
)
{
int
ret
=
ms_ergonomy_kb_quirk
(
hi
,
usage
,
bit
,
max
);
...
...
@@ -185,7 +216,8 @@ static int ms_input_mapped(struct hid_device *hdev, struct hid_input *hi,
struct
hid_field
*
field
,
struct
hid_usage
*
usage
,
unsigned
long
**
bit
,
int
*
max
)
{
unsigned
long
quirks
=
(
unsigned
long
)
hid_get_drvdata
(
hdev
);
struct
ms_data
*
ms
=
hid_get_drvdata
(
hdev
);
unsigned
long
quirks
=
ms
->
quirks
;
if
(
quirks
&
MS_DUPLICATE_USAGES
)
clear_bit
(
usage
->
code
,
*
bit
);
...
...
@@ -196,7 +228,8 @@ static int ms_input_mapped(struct hid_device *hdev, struct hid_input *hi,
static
int
ms_event
(
struct
hid_device
*
hdev
,
struct
hid_field
*
field
,
struct
hid_usage
*
usage
,
__s32
value
)
{
unsigned
long
quirks
=
(
unsigned
long
)
hid_get_drvdata
(
hdev
);
struct
ms_data
*
ms
=
hid_get_drvdata
(
hdev
);
unsigned
long
quirks
=
ms
->
quirks
;
struct
input_dev
*
input
;
if
(
!
(
hdev
->
claimed
&
HID_CLAIMED_INPUT
)
||
!
field
->
hidinput
||
...
...
@@ -251,12 +284,97 @@ static int ms_event(struct hid_device *hdev, struct hid_field *field,
return
0
;
}
static
void
ms_ff_worker
(
struct
work_struct
*
work
)
{
struct
ms_data
*
ms
=
container_of
(
work
,
struct
ms_data
,
ff_worker
);
struct
hid_device
*
hdev
=
ms
->
hdev
;
struct
xb1s_ff_report
*
r
=
ms
->
output_report_dmabuf
;
int
ret
;
memset
(
r
,
0
,
sizeof
(
*
r
));
r
->
report_id
=
XB1S_FF_REPORT
;
r
->
enable
=
ENABLE_WEAK
|
ENABLE_STRONG
;
/*
* Specifying maximum duration and maximum loop count should
* cover maximum duration of a single effect, which is 65536
* ms
*/
r
->
duration_10ms
=
U8_MAX
;
r
->
loop_count
=
U8_MAX
;
r
->
magnitude
[
MAGNITUDE_STRONG
]
=
ms
->
strong
;
/* left actuator */
r
->
magnitude
[
MAGNITUDE_WEAK
]
=
ms
->
weak
;
/* right actuator */
ret
=
hid_hw_output_report
(
hdev
,
(
__u8
*
)
r
,
sizeof
(
*
r
));
if
(
ret
)
hid_warn
(
hdev
,
"failed to send FF report
\n
"
);
}
static
int
ms_play_effect
(
struct
input_dev
*
dev
,
void
*
data
,
struct
ff_effect
*
effect
)
{
struct
hid_device
*
hid
=
input_get_drvdata
(
dev
);
struct
ms_data
*
ms
=
hid_get_drvdata
(
hid
);
if
(
effect
->
type
!=
FF_RUMBLE
)
return
0
;
/*
* Magnitude is 0..100 so scale the 16-bit input here
*/
ms
->
strong
=
((
u32
)
effect
->
u
.
rumble
.
strong_magnitude
*
100
)
/
U16_MAX
;
ms
->
weak
=
((
u32
)
effect
->
u
.
rumble
.
weak_magnitude
*
100
)
/
U16_MAX
;
schedule_work
(
&
ms
->
ff_worker
);
return
0
;
}
static
int
ms_init_ff
(
struct
hid_device
*
hdev
)
{
struct
hid_input
*
hidinput
=
list_entry
(
hdev
->
inputs
.
next
,
struct
hid_input
,
list
);
struct
input_dev
*
input_dev
=
hidinput
->
input
;
struct
ms_data
*
ms
=
hid_get_drvdata
(
hdev
);
if
(
!
(
ms
->
quirks
&
MS_QUIRK_FF
))
return
0
;
ms
->
hdev
=
hdev
;
INIT_WORK
(
&
ms
->
ff_worker
,
ms_ff_worker
);
ms
->
output_report_dmabuf
=
devm_kzalloc
(
&
hdev
->
dev
,
sizeof
(
struct
xb1s_ff_report
),
GFP_KERNEL
);
if
(
ms
->
output_report_dmabuf
==
NULL
)
return
-
ENOMEM
;
input_set_capability
(
input_dev
,
EV_FF
,
FF_RUMBLE
);
return
input_ff_create_memless
(
input_dev
,
NULL
,
ms_play_effect
);
}
static
void
ms_remove_ff
(
struct
hid_device
*
hdev
)
{
struct
ms_data
*
ms
=
hid_get_drvdata
(
hdev
);
if
(
!
(
ms
->
quirks
&
MS_QUIRK_FF
))
return
;
cancel_work_sync
(
&
ms
->
ff_worker
);
}
static
int
ms_probe
(
struct
hid_device
*
hdev
,
const
struct
hid_device_id
*
id
)
{
unsigned
long
quirks
=
id
->
driver_data
;
struct
ms_data
*
ms
;
int
ret
;
hid_set_drvdata
(
hdev
,
(
void
*
)
quirks
);
ms
=
devm_kzalloc
(
&
hdev
->
dev
,
sizeof
(
*
ms
),
GFP_KERNEL
);
if
(
ms
==
NULL
)
return
-
ENOMEM
;
ms
->
quirks
=
quirks
;
hid_set_drvdata
(
hdev
,
ms
);
if
(
quirks
&
MS_NOGET
)
hdev
->
quirks
|=
HID_QUIRK_NOGET
;
...
...
@@ -277,11 +395,21 @@ static int ms_probe(struct hid_device *hdev, const struct hid_device_id *id)
goto
err_free
;
}
ret
=
ms_init_ff
(
hdev
);
if
(
ret
)
hid_err
(
hdev
,
"could not initialize ff, continuing anyway"
);
return
0
;
err_free:
return
ret
;
}
static
void
ms_remove
(
struct
hid_device
*
hdev
)
{
hid_hw_stop
(
hdev
);
ms_remove_ff
(
hdev
);
}
static
const
struct
hid_device_id
ms_devices
[]
=
{
{
HID_USB_DEVICE
(
USB_VENDOR_ID_MICROSOFT
,
USB_DEVICE_ID_SIDEWINDER_GV
),
.
driver_data
=
MS_HIDINPUT
},
...
...
@@ -318,6 +446,8 @@ static const struct hid_device_id ms_devices[] = {
.
driver_data
=
MS_PRESENTER
},
{
HID_BLUETOOTH_DEVICE
(
USB_VENDOR_ID_MICROSOFT
,
0x091B
),
.
driver_data
=
MS_SURFACE_DIAL
},
{
HID_BLUETOOTH_DEVICE
(
USB_VENDOR_ID_MICROSOFT
,
USB_DEVICE_ID_MS_XBOX_ONE_S_CONTROLLER
),
.
driver_data
=
MS_QUIRK_FF
},
{
}
};
MODULE_DEVICE_TABLE
(
hid
,
ms_devices
);
...
...
@@ -330,6 +460,7 @@ static struct hid_driver ms_driver = {
.
input_mapped
=
ms_input_mapped
,
.
event
=
ms_event
,
.
probe
=
ms_probe
,
.
remove
=
ms_remove
,
};
module_hid_driver
(
ms_driver
);
...
...
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