Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
a6be4c6c
K
Kernel
项目概览
openeuler
/
Kernel
1 年多 前同步成功
通知
8
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
Kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
a6be4c6c
编写于
11月 05, 2021
作者:
J
Jiri Kosina
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'for-5.16/playstation' into for-linus
- LED handling improvements (Roderick Colenbrander)
上级
b026277a
d7f1f9fe
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
180 addition
and
1 deletion
+180
-1
Documentation/leds/well-known-leds.txt
Documentation/leds/well-known-leds.txt
+14
-0
drivers/hid/Kconfig
drivers/hid/Kconfig
+1
-0
drivers/hid/hid-playstation.c
drivers/hid/hid-playstation.c
+158
-1
include/dt-bindings/leds/common.h
include/dt-bindings/leds/common.h
+7
-0
未找到文件。
Documentation/leds/well-known-leds.txt
浏览文件 @
a6be4c6c
...
...
@@ -16,6 +16,20 @@ but then try the legacy ones, too.
Notice there's a list of functions in include/dt-bindings/leds/common.h .
* Gamepads and joysticks
Game controllers may feature LEDs to indicate a player number. This is commonly
used on game consoles in which multiple controllers can be connected to a system.
The "player LEDs" are then programmed with a pattern to indicate a particular
player. For example, a game controller with 4 LEDs, may be programmed with "x---"
to indicate player 1, "-x--" to indicate player 2 etcetera where "x" means on.
Input drivers can utilize the LED class to expose the individual player LEDs
of a game controller using the function "player".
Note: tracking and management of Player IDs is the responsibility of user space,
though drivers may pick a default value.
Good: "input*:*:player-{1,2,3,4,5}
* Keyboards
Good: "input*:*:capslock"
...
...
drivers/hid/Kconfig
浏览文件 @
a6be4c6c
...
...
@@ -868,6 +868,7 @@ config HID_PLANTRONICS
config HID_PLAYSTATION
tristate "PlayStation HID Driver"
depends on HID
depends on LEDS_CLASS_MULTICOLOR
select CRC32
select POWER_SUPPLY
help
...
...
drivers/hid/hid-playstation.c
浏览文件 @
a6be4c6c
...
...
@@ -11,6 +11,8 @@
#include <linux/hid.h>
#include <linux/idr.h>
#include <linux/input/mt.h>
#include <linux/leds.h>
#include <linux/led-class-multicolor.h>
#include <linux/module.h>
#include <asm/unaligned.h>
...
...
@@ -38,6 +40,7 @@ struct ps_device {
uint8_t
battery_capacity
;
int
battery_status
;
const
char
*
input_dev_name
;
/* Name of primary input device. */
uint8_t
mac_address
[
6
];
/* Note: stored in little endian order. */
uint32_t
hw_version
;
uint32_t
fw_version
;
...
...
@@ -53,6 +56,13 @@ struct ps_calibration_data {
int
sens_denom
;
};
struct
ps_led_info
{
const
char
*
name
;
const
char
*
color
;
enum
led_brightness
(
*
brightness_get
)(
struct
led_classdev
*
cdev
);
int
(
*
brightness_set
)(
struct
led_classdev
*
cdev
,
enum
led_brightness
);
};
/* Seed values for DualShock4 / DualSense CRC32 for different report types. */
#define PS_INPUT_CRC32_SEED 0xA1
#define PS_OUTPUT_CRC32_SEED 0xA2
...
...
@@ -147,6 +157,7 @@ struct dualsense {
uint8_t
motor_right
;
/* RGB lightbar */
struct
led_classdev_mc
lightbar
;
bool
update_lightbar
;
uint8_t
lightbar_red
;
uint8_t
lightbar_green
;
...
...
@@ -288,6 +299,8 @@ static const struct {int x; int y; } ps_gamepad_hat_mapping[] = {
{
0
,
0
},
};
static
void
dualsense_set_lightbar
(
struct
dualsense
*
ds
,
uint8_t
red
,
uint8_t
green
,
uint8_t
blue
);
/*
* Add a new ps_device to ps_devices if it doesn't exist.
* Return error on duplicate device, which can happen if the same
...
...
@@ -525,6 +538,71 @@ static int ps_get_report(struct hid_device *hdev, uint8_t report_id, uint8_t *bu
return
0
;
}
static
int
ps_led_register
(
struct
ps_device
*
ps_dev
,
struct
led_classdev
*
led
,
const
struct
ps_led_info
*
led_info
)
{
int
ret
;
led
->
name
=
devm_kasprintf
(
&
ps_dev
->
hdev
->
dev
,
GFP_KERNEL
,
"%s:%s:%s"
,
ps_dev
->
input_dev_name
,
led_info
->
color
,
led_info
->
name
);
if
(
!
led
->
name
)
return
-
ENOMEM
;
led
->
brightness
=
0
;
led
->
max_brightness
=
1
;
led
->
flags
=
LED_CORE_SUSPENDRESUME
;
led
->
brightness_get
=
led_info
->
brightness_get
;
led
->
brightness_set_blocking
=
led_info
->
brightness_set
;
ret
=
devm_led_classdev_register
(
&
ps_dev
->
hdev
->
dev
,
led
);
if
(
ret
)
{
hid_err
(
ps_dev
->
hdev
,
"Failed to register LED %s: %d
\n
"
,
led_info
->
name
,
ret
);
return
ret
;
}
return
0
;
}
/* Register a DualSense/DualShock4 RGB lightbar represented by a multicolor LED. */
static
int
ps_lightbar_register
(
struct
ps_device
*
ps_dev
,
struct
led_classdev_mc
*
lightbar_mc_dev
,
int
(
*
brightness_set
)(
struct
led_classdev
*
,
enum
led_brightness
))
{
struct
hid_device
*
hdev
=
ps_dev
->
hdev
;
struct
mc_subled
*
mc_led_info
;
struct
led_classdev
*
led_cdev
;
int
ret
;
mc_led_info
=
devm_kmalloc_array
(
&
hdev
->
dev
,
3
,
sizeof
(
*
mc_led_info
),
GFP_KERNEL
|
__GFP_ZERO
);
if
(
!
mc_led_info
)
return
-
ENOMEM
;
mc_led_info
[
0
].
color_index
=
LED_COLOR_ID_RED
;
mc_led_info
[
1
].
color_index
=
LED_COLOR_ID_GREEN
;
mc_led_info
[
2
].
color_index
=
LED_COLOR_ID_BLUE
;
lightbar_mc_dev
->
subled_info
=
mc_led_info
;
lightbar_mc_dev
->
num_colors
=
3
;
led_cdev
=
&
lightbar_mc_dev
->
led_cdev
;
led_cdev
->
name
=
devm_kasprintf
(
&
hdev
->
dev
,
GFP_KERNEL
,
"%s:rgb:indicator"
,
ps_dev
->
input_dev_name
);
if
(
!
led_cdev
->
name
)
return
-
ENOMEM
;
led_cdev
->
brightness
=
255
;
led_cdev
->
max_brightness
=
255
;
led_cdev
->
brightness_set_blocking
=
brightness_set
;
ret
=
devm_led_classdev_multicolor_register
(
&
hdev
->
dev
,
lightbar_mc_dev
);
if
(
ret
<
0
)
{
hid_err
(
hdev
,
"Cannot register multicolor LED device
\n
"
);
return
ret
;
}
return
0
;
}
static
struct
input_dev
*
ps_sensors_create
(
struct
hid_device
*
hdev
,
int
accel_range
,
int
accel_res
,
int
gyro_range
,
int
gyro_res
)
{
...
...
@@ -761,6 +839,53 @@ static int dualsense_get_mac_address(struct dualsense *ds)
return
ret
;
}
static
int
dualsense_lightbar_set_brightness
(
struct
led_classdev
*
cdev
,
enum
led_brightness
brightness
)
{
struct
led_classdev_mc
*
mc_cdev
=
lcdev_to_mccdev
(
cdev
);
struct
dualsense
*
ds
=
container_of
(
mc_cdev
,
struct
dualsense
,
lightbar
);
uint8_t
red
,
green
,
blue
;
led_mc_calc_color_components
(
mc_cdev
,
brightness
);
red
=
mc_cdev
->
subled_info
[
0
].
brightness
;
green
=
mc_cdev
->
subled_info
[
1
].
brightness
;
blue
=
mc_cdev
->
subled_info
[
2
].
brightness
;
dualsense_set_lightbar
(
ds
,
red
,
green
,
blue
);
return
0
;
}
static
enum
led_brightness
dualsense_player_led_get_brightness
(
struct
led_classdev
*
led
)
{
struct
hid_device
*
hdev
=
to_hid_device
(
led
->
dev
->
parent
);
struct
dualsense
*
ds
=
hid_get_drvdata
(
hdev
);
return
!!
(
ds
->
player_leds_state
&
BIT
(
led
-
ds
->
player_leds
));
}
static
int
dualsense_player_led_set_brightness
(
struct
led_classdev
*
led
,
enum
led_brightness
value
)
{
struct
hid_device
*
hdev
=
to_hid_device
(
led
->
dev
->
parent
);
struct
dualsense
*
ds
=
hid_get_drvdata
(
hdev
);
unsigned
long
flags
;
unsigned
int
led_index
;
spin_lock_irqsave
(
&
ds
->
base
.
lock
,
flags
);
led_index
=
led
-
ds
->
player_leds
;
if
(
value
==
LED_OFF
)
ds
->
player_leds_state
&=
~
BIT
(
led_index
);
else
ds
->
player_leds_state
|=
BIT
(
led_index
);
ds
->
update_player_leds
=
true
;
spin_unlock_irqrestore
(
&
ds
->
base
.
lock
,
flags
);
schedule_work
(
&
ds
->
output_worker
);
return
0
;
}
static
void
dualsense_init_output_report
(
struct
dualsense
*
ds
,
struct
dualsense_output_report
*
rp
,
void
*
buf
)
{
...
...
@@ -1106,10 +1231,14 @@ static int dualsense_reset_leds(struct dualsense *ds)
static
void
dualsense_set_lightbar
(
struct
dualsense
*
ds
,
uint8_t
red
,
uint8_t
green
,
uint8_t
blue
)
{
unsigned
long
flags
;
spin_lock_irqsave
(
&
ds
->
base
.
lock
,
flags
);
ds
->
update_lightbar
=
true
;
ds
->
lightbar_red
=
red
;
ds
->
lightbar_green
=
green
;
ds
->
lightbar_blue
=
blue
;
spin_unlock_irqrestore
(
&
ds
->
base
.
lock
,
flags
);
schedule_work
(
&
ds
->
output_worker
);
}
...
...
@@ -1142,7 +1271,20 @@ static struct ps_device *dualsense_create(struct hid_device *hdev)
struct
dualsense
*
ds
;
struct
ps_device
*
ps_dev
;
uint8_t
max_output_report_size
;
int
ret
;
int
i
,
ret
;
static
const
struct
ps_led_info
player_leds_info
[]
=
{
{
LED_FUNCTION_PLAYER1
,
"white"
,
dualsense_player_led_get_brightness
,
dualsense_player_led_set_brightness
},
{
LED_FUNCTION_PLAYER2
,
"white"
,
dualsense_player_led_get_brightness
,
dualsense_player_led_set_brightness
},
{
LED_FUNCTION_PLAYER3
,
"white"
,
dualsense_player_led_get_brightness
,
dualsense_player_led_set_brightness
},
{
LED_FUNCTION_PLAYER4
,
"white"
,
dualsense_player_led_get_brightness
,
dualsense_player_led_set_brightness
},
{
LED_FUNCTION_PLAYER5
,
"white"
,
dualsense_player_led_get_brightness
,
dualsense_player_led_set_brightness
}
};
ds
=
devm_kzalloc
(
&
hdev
->
dev
,
sizeof
(
*
ds
),
GFP_KERNEL
);
if
(
!
ds
)
...
...
@@ -1196,6 +1338,8 @@ static struct ps_device *dualsense_create(struct hid_device *hdev)
ret
=
PTR_ERR
(
ds
->
gamepad
);
goto
err
;
}
/* Use gamepad input device name as primary device name for e.g. LEDs */
ps_dev
->
input_dev_name
=
dev_name
(
&
ds
->
gamepad
->
dev
);
ds
->
sensors
=
ps_sensors_create
(
hdev
,
DS_ACC_RANGE
,
DS_ACC_RES_PER_G
,
DS_GYRO_RANGE
,
DS_GYRO_RES_PER_DEG_S
);
...
...
@@ -1223,8 +1367,21 @@ static struct ps_device *dualsense_create(struct hid_device *hdev)
if
(
ret
)
goto
err
;
ret
=
ps_lightbar_register
(
ps_dev
,
&
ds
->
lightbar
,
dualsense_lightbar_set_brightness
);
if
(
ret
)
goto
err
;
/* Set default lightbar color. */
dualsense_set_lightbar
(
ds
,
0
,
0
,
128
);
/* blue */
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
player_leds_info
);
i
++
)
{
const
struct
ps_led_info
*
led_info
=
&
player_leds_info
[
i
];
ret
=
ps_led_register
(
ps_dev
,
&
ds
->
player_leds
[
i
],
led_info
);
if
(
ret
<
0
)
goto
err
;
}
ret
=
ps_device_set_player_id
(
ps_dev
);
if
(
ret
)
{
hid_err
(
hdev
,
"Failed to assign player id for DualSense: %d
\n
"
,
ret
);
...
...
include/dt-bindings/leds/common.h
浏览文件 @
a6be4c6c
...
...
@@ -60,6 +60,13 @@
#define LED_FUNCTION_MICMUTE "micmute"
#define LED_FUNCTION_MUTE "mute"
/* Used for player LEDs as found on game controllers from e.g. Nintendo, Sony. */
#define LED_FUNCTION_PLAYER1 "player-1"
#define LED_FUNCTION_PLAYER2 "player-2"
#define LED_FUNCTION_PLAYER3 "player-3"
#define LED_FUNCTION_PLAYER4 "player-4"
#define LED_FUNCTION_PLAYER5 "player-5"
/* Miscelleaus functions. Use functions above if you can. */
#define LED_FUNCTION_ACTIVITY "activity"
#define LED_FUNCTION_ALARM "alarm"
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录