Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
23ea5967
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看板
提交
23ea5967
编写于
5月 16, 2016
作者:
D
Dmitry Torokhov
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'next' into for-linus
Prepare first round of input updates for 4.7 merge window.
上级
c52c545e
d96caf8c
变更
15
隐藏空白更改
内联
并排
Showing
15 changed file
with
170 addition
and
182 deletion
+170
-182
Documentation/devicetree/bindings/input/gpio-keys.txt
Documentation/devicetree/bindings/input/gpio-keys.txt
+5
-5
Documentation/devicetree/bindings/input/touchscreen/brcm,iproc-touchscreen.txt
...ree/bindings/input/touchscreen/brcm,iproc-touchscreen.txt
+17
-6
arch/arm/boot/dts/bcm-cygnus.dtsi
arch/arm/boot/dts/bcm-cygnus.dtsi
+9
-2
drivers/input/keyboard/omap-keypad.c
drivers/input/keyboard/omap-keypad.c
+1
-51
drivers/input/keyboard/twl4030_keypad.c
drivers/input/keyboard/twl4030_keypad.c
+16
-12
drivers/input/misc/cm109.c
drivers/input/misc/cm109.c
+36
-11
drivers/input/misc/rotary_encoder.c
drivers/input/misc/rotary_encoder.c
+4
-4
drivers/input/misc/twl6040-vibra.c
drivers/input/misc/twl6040-vibra.c
+2
-13
drivers/input/mouse/byd.c
drivers/input/mouse/byd.c
+0
-1
drivers/input/tablet/acecad.c
drivers/input/tablet/acecad.c
+6
-6
drivers/input/tablet/aiptek.c
drivers/input/tablet/aiptek.c
+11
-9
drivers/input/tablet/gtco.c
drivers/input/tablet/gtco.c
+12
-12
drivers/input/tablet/kbtab.c
drivers/input/tablet/kbtab.c
+4
-4
drivers/input/touchscreen/bcm_iproc_tsc.c
drivers/input/touchscreen/bcm_iproc_tsc.c
+43
-34
drivers/input/touchscreen/ti_am335x_tsc.c
drivers/input/touchscreen/ti_am335x_tsc.c
+4
-12
未找到文件。
Documentation/devicetree/bindings/input/gpio-keys.txt
浏览文件 @
23ea5967
...
...
@@ -32,17 +32,17 @@ Optional subnode-properties:
Example nodes:
gpio
_
keys {
gpio
-
keys {
compatible = "gpio-keys";
#address-cells = <1>;
#size-cells = <0>;
autorepeat;
button@21 {
up {
label = "GPIO Key UP";
linux,code = <103>;
gpios = <&gpio1 0 1>;
};
button@22 {
down {
label = "GPIO Key DOWN";
linux,code = <108>;
interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
...
...
Documentation/devicetree/bindings/input/touchscreen/brcm,iproc-touchscreen.txt
浏览文件 @
23ea5967
...
...
@@ -2,11 +2,17 @@
Required properties:
- compatible: must be "brcm,iproc-touchscreen"
- reg: physical base address of the controller and length of memory mapped
region.
- ts_syscon: handler of syscon node defining physical base
address of the controller and length of memory mapped region.
If this property is selected please make sure MFD_SYSCON config
is enabled in the defconfig file.
- clocks: The clock provided by the SOC to driver the tsc
- clock-name: name for the clock
- clock-name
s
: name for the clock
- interrupts: The touchscreen controller's interrupt
- address-cells: Specify the number of u32 entries needed in child nodes.
Should set to 1.
- size-cells: Specify number of u32 entries needed to specify child nodes size
in reg property. Should set to 1.
Optional properties:
- scanning_period: Time between scans. Each step is 1024 us. Valid 1-256.
...
...
@@ -53,13 +59,18 @@ Optional properties:
- touchscreen-inverted-x: X axis is inverted (boolean)
- touchscreen-inverted-y: Y axis is inverted (boolean)
Example:
Example:
An example of touchscreen node
touchscreen: tsc@0x180A6000 {
ts_adc_syscon: ts_adc_syscon@180a6000 {
compatible = "brcm,iproc-ts-adc-syscon","syscon";
reg = <0x180a6000 0xc30>;
};
touchscreen: touchscreen@180A6000 {
compatible = "brcm,iproc-touchscreen";
#address-cells = <1>;
#size-cells = <1>;
reg = <0x180A6000 0x40
>;
ts_syscon = <&ts_adc_syscon
>;
clocks = <&adc_clk>;
clock-names = "tsc_clk";
interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>;
...
...
arch/arm/boot/dts/bcm-cygnus.dtsi
浏览文件 @
23ea5967
...
...
@@ -351,9 +351,16 @@
<&
pinctrl
142
10
1
>;
};
touchscreen
:
tsc
@
180
a6000
{
ts_adc_syscon
:
ts_adc_syscon
@
180
a6000
{
compatible
=
"brcm,iproc-ts-adc-syscon"
,
"syscon"
;
reg
=
<
0x180a6000
0xc30
>;
};
touchscreen
:
touchscreen
@
180
a6000
{
compatible
=
"brcm,iproc-touchscreen"
;
reg
=
<
0x180a6000
0x40
>;
#
address
-
cells
=
<
1
>;
#
size
-
cells
=
<
1
>;
ts_syscon
=
<&
ts_adc_syscon
>;
clocks
=
<&
asiu_clks
BCM_CYGNUS_ASIU_ADC_CLK
>;
clock
-
names
=
"tsc_clk"
;
interrupts
=
<
GIC_SPI
164
IRQ_TYPE_LEVEL_HIGH
>;
...
...
drivers/input/keyboard/omap-keypad.c
浏览文件 @
23ea5967
...
...
@@ -64,31 +64,6 @@ static DECLARE_TASKLET_DISABLED(kp_tasklet, omap_kp_tasklet, 0);
static
unsigned
int
*
row_gpios
;
static
unsigned
int
*
col_gpios
;
#ifdef CONFIG_ARCH_OMAP2
static
void
set_col_gpio_val
(
struct
omap_kp
*
omap_kp
,
u8
value
)
{
int
col
;
for
(
col
=
0
;
col
<
omap_kp
->
cols
;
col
++
)
gpio_set_value
(
col_gpios
[
col
],
value
&
(
1
<<
col
));
}
static
u8
get_row_gpio_val
(
struct
omap_kp
*
omap_kp
)
{
int
row
;
u8
value
=
0
;
for
(
row
=
0
;
row
<
omap_kp
->
rows
;
row
++
)
{
if
(
gpio_get_value
(
row_gpios
[
row
]))
value
|=
(
1
<<
row
);
}
return
value
;
}
#else
#define set_col_gpio_val(x, y) do {} while (0)
#define get_row_gpio_val(x) 0
#endif
static
irqreturn_t
omap_kp_interrupt
(
int
irq
,
void
*
dev_id
)
{
/* disable keyboard interrupt and schedule for handling */
...
...
@@ -133,7 +108,6 @@ static void omap_kp_tasklet(unsigned long data)
unsigned
int
row_shift
=
get_count_order
(
omap_kp_data
->
cols
);
unsigned
char
new_state
[
8
],
changed
,
key_down
=
0
;
int
col
,
row
;
int
spurious
=
0
;
/* check for any changes */
omap_kp_scan_keypad
(
omap_kp_data
,
new_state
);
...
...
@@ -170,12 +144,9 @@ static void omap_kp_tasklet(unsigned long data)
memcpy
(
keypad_state
,
new_state
,
sizeof
(
keypad_state
));
if
(
key_down
)
{
int
delay
=
HZ
/
20
;
/* some key is pressed - keep irq disabled and use timer
* to poll the keypad */
if
(
spurious
)
delay
=
2
*
HZ
;
mod_timer
(
&
omap_kp_data
->
timer
,
jiffies
+
delay
);
mod_timer
(
&
omap_kp_data
->
timer
,
jiffies
+
HZ
/
20
);
}
else
{
/* enable interrupts */
omap_writew
(
0
,
OMAP1_MPUIO_BASE
+
OMAP_MPUIO_KBD_MASKIT
);
...
...
@@ -216,25 +187,6 @@ static ssize_t omap_kp_enable_store(struct device *dev, struct device_attribute
static
DEVICE_ATTR
(
enable
,
S_IRUGO
|
S_IWUSR
,
omap_kp_enable_show
,
omap_kp_enable_store
);
#ifdef CONFIG_PM
static
int
omap_kp_suspend
(
struct
platform_device
*
dev
,
pm_message_t
state
)
{
/* Nothing yet */
return
0
;
}
static
int
omap_kp_resume
(
struct
platform_device
*
dev
)
{
/* Nothing yet */
return
0
;
}
#else
#define omap_kp_suspend NULL
#define omap_kp_resume NULL
#endif
static
int
omap_kp_probe
(
struct
platform_device
*
pdev
)
{
struct
omap_kp
*
omap_kp
;
...
...
@@ -371,8 +323,6 @@ static int omap_kp_remove(struct platform_device *pdev)
static
struct
platform_driver
omap_kp_driver
=
{
.
probe
=
omap_kp_probe
,
.
remove
=
omap_kp_remove
,
.
suspend
=
omap_kp_suspend
,
.
resume
=
omap_kp_resume
,
.
driver
=
{
.
name
=
"omap-keypad"
,
},
...
...
drivers/input/keyboard/twl4030_keypad.c
浏览文件 @
23ea5967
...
...
@@ -61,9 +61,9 @@ struct twl4030_keypad {
unsigned
short
keymap
[
TWL4030_KEYMAP_SIZE
];
u16
kp_state
[
TWL4030_MAX_ROWS
];
bool
autorepeat
;
unsigned
n_rows
;
unsigned
n_cols
;
unsigned
irq
;
unsigned
int
n_rows
;
unsigned
int
n_cols
;
unsigned
int
irq
;
struct
device
*
dbg_dev
;
struct
input_dev
*
input
;
...
...
@@ -110,7 +110,7 @@ struct twl4030_keypad {
#define KEYP_CTRL_KBD_ON BIT(6)
/* KEYP_DEB, KEYP_LONG_KEY, KEYP_TIMEOUT_x*/
#define KEYP_PERIOD_US(t, prescale) ((t) / (31 << (
prescale
+ 1)) - 1)
#define KEYP_PERIOD_US(t, prescale) ((t) / (31 << (
(prescale)
+ 1)) - 1)
/* KEYP_LK_PTV_REG Fields */
#define KEYP_LK_PTV_PTV_SHIFT 5
...
...
@@ -162,9 +162,10 @@ static int twl4030_kpwrite_u8(struct twl4030_keypad *kp, u8 data, u32 reg)
static
inline
u16
twl4030_col_xlate
(
struct
twl4030_keypad
*
kp
,
u8
col
)
{
/* If all bits in a row are active for all coloumns then
/*
* If all bits in a row are active for all columns then
* we have that row line connected to gnd. Mark this
* key on as if it was on matrix position n_cols (i
e
* key on as if it was on matrix position n_cols (i
.e.
* one higher than the size of the matrix).
*/
if
(
col
==
0xFF
)
...
...
@@ -209,9 +210,9 @@ static void twl4030_kp_scan(struct twl4030_keypad *kp, bool release_all)
u16
new_state
[
TWL4030_MAX_ROWS
];
int
col
,
row
;
if
(
release_all
)
if
(
release_all
)
{
memset
(
new_state
,
0
,
sizeof
(
new_state
));
else
{
}
else
{
/* check for any changes */
int
ret
=
twl4030_read_kp_matrix_state
(
kp
,
new_state
);
...
...
@@ -262,8 +263,10 @@ static irqreturn_t do_kp_irq(int irq, void *_kp)
/* Read & Clear TWL4030 pending interrupt */
ret
=
twl4030_kpread
(
kp
,
&
reg
,
KEYP_ISR1
,
1
);
/* Release all keys if I2C has gone bad or
* the KEYP has gone to idle state */
/*
* Release all keys if I2C has gone bad or
* the KEYP has gone to idle state.
*/
if
(
ret
>=
0
&&
(
reg
&
KEYP_IMR1_KP
))
twl4030_kp_scan
(
kp
,
false
);
else
...
...
@@ -283,7 +286,8 @@ static int twl4030_kp_program(struct twl4030_keypad *kp)
if
(
twl4030_kpwrite_u8
(
kp
,
reg
,
KEYP_CTRL
)
<
0
)
return
-
EIO
;
/* NOTE: we could use sih_setup() here to package keypad
/*
* NOTE: we could use sih_setup() here to package keypad
* event sources as four different IRQs ... but we don't.
*/
...
...
@@ -312,7 +316,7 @@ static int twl4030_kp_program(struct twl4030_keypad *kp)
/*
* Enable Clear-on-Read; disable remembering events that fire
* after the IRQ but before our handler acks (reads) them
,
* after the IRQ but before our handler acks (reads) them
.
*/
reg
=
TWL4030_SIH_CTRL_COR_MASK
|
TWL4030_SIH_CTRL_PENDDIS_MASK
;
if
(
twl4030_kpwrite_u8
(
kp
,
reg
,
KEYP_SIH_CTRL
)
<
0
)
...
...
drivers/input/misc/cm109.c
浏览文件 @
23ea5967
...
...
@@ -76,8 +76,8 @@ enum {
BUZZER_ON
=
1
<<
5
,
/* up to 256 normal keys, up to 1
6 special key
s */
KEYMAP_SIZE
=
256
+
1
6
,
/* up to 256 normal keys, up to 1
5 special key combination
s */
KEYMAP_SIZE
=
256
+
1
5
,
};
/* CM109 protocol packet */
...
...
@@ -139,7 +139,7 @@ static unsigned short special_keymap(int code)
{
if
(
code
>
0xff
)
{
switch
(
code
-
0xff
)
{
case
RECORD_MUTE
:
return
KEY_MUTE
;
case
RECORD_MUTE
:
return
KEY_M
ICM
UTE
;
case
PLAYBACK_MUTE
:
return
KEY_MUTE
;
case
VOLUME_DOWN
:
return
KEY_VOLUMEDOWN
;
case
VOLUME_UP
:
return
KEY_VOLUMEUP
;
...
...
@@ -312,6 +312,32 @@ static void report_key(struct cm109_dev *dev, int key)
input_sync
(
idev
);
}
/*
* Converts data of special key presses (volume, mute) into events
* for the input subsystem, sends press-n-release for mute keys.
*/
static
void
cm109_report_special
(
struct
cm109_dev
*
dev
)
{
static
const
u8
autorelease
=
RECORD_MUTE
|
PLAYBACK_MUTE
;
struct
input_dev
*
idev
=
dev
->
idev
;
u8
data
=
dev
->
irq_data
->
byte
[
HID_IR0
];
unsigned
short
keycode
;
int
i
;
for
(
i
=
0
;
i
<
4
;
i
++
)
{
keycode
=
dev
->
keymap
[
0xff
+
BIT
(
i
)];
if
(
keycode
==
KEY_RESERVED
)
continue
;
input_report_key
(
idev
,
keycode
,
data
&
BIT
(
i
));
if
(
data
&
autorelease
&
BIT
(
i
))
{
input_sync
(
idev
);
input_report_key
(
idev
,
keycode
,
0
);
}
}
input_sync
(
idev
);
}
/******************************************************************************
* CM109 usb communication interface
*****************************************************************************/
...
...
@@ -340,6 +366,7 @@ static void cm109_urb_irq_callback(struct urb *urb)
struct
cm109_dev
*
dev
=
urb
->
context
;
const
int
status
=
urb
->
status
;
int
error
;
unsigned
long
flags
;
dev_dbg
(
&
dev
->
intf
->
dev
,
"### URB IRQ: [0x%02x 0x%02x 0x%02x 0x%02x] keybit=0x%02x
\n
"
,
dev
->
irq_data
->
byte
[
0
],
...
...
@@ -357,10 +384,7 @@ static void cm109_urb_irq_callback(struct urb *urb)
}
/* Special keys */
if
(
dev
->
irq_data
->
byte
[
HID_IR0
]
&
0x0f
)
{
const
int
code
=
(
dev
->
irq_data
->
byte
[
HID_IR0
]
&
0x0f
);
report_key
(
dev
,
dev
->
keymap
[
0xff
+
code
]);
}
cm109_report_special
(
dev
);
/* Scan key column */
if
(
dev
->
keybit
==
0xf
)
{
...
...
@@ -381,7 +405,7 @@ static void cm109_urb_irq_callback(struct urb *urb)
out:
spin_lock
(
&
dev
->
ctl_submit_lock
);
spin_lock
_irqsave
(
&
dev
->
ctl_submit_lock
,
flags
);
dev
->
irq_urb_pending
=
0
;
...
...
@@ -405,7 +429,7 @@ static void cm109_urb_irq_callback(struct urb *urb)
__func__
,
error
);
}
spin_unlock
(
&
dev
->
ctl_submit_lock
);
spin_unlock
_irqrestore
(
&
dev
->
ctl_submit_lock
,
flags
);
}
static
void
cm109_urb_ctl_callback
(
struct
urb
*
urb
)
...
...
@@ -413,6 +437,7 @@ static void cm109_urb_ctl_callback(struct urb *urb)
struct
cm109_dev
*
dev
=
urb
->
context
;
const
int
status
=
urb
->
status
;
int
error
;
unsigned
long
flags
;
dev_dbg
(
&
dev
->
intf
->
dev
,
"### URB CTL: [0x%02x 0x%02x 0x%02x 0x%02x]
\n
"
,
dev
->
ctl_data
->
byte
[
0
],
...
...
@@ -427,7 +452,7 @@ static void cm109_urb_ctl_callback(struct urb *urb)
__func__
,
status
);
}
spin_lock
(
&
dev
->
ctl_submit_lock
);
spin_lock
_irqsave
(
&
dev
->
ctl_submit_lock
,
flags
);
dev
->
ctl_urb_pending
=
0
;
...
...
@@ -448,7 +473,7 @@ static void cm109_urb_ctl_callback(struct urb *urb)
}
}
spin_unlock
(
&
dev
->
ctl_submit_lock
);
spin_unlock
_irqrestore
(
&
dev
->
ctl_submit_lock
,
flags
);
}
static
void
cm109_toggle_buzzer_async
(
struct
cm109_dev
*
dev
)
...
...
drivers/input/misc/rotary_encoder.c
浏览文件 @
23ea5967
...
...
@@ -47,13 +47,13 @@ struct rotary_encoder {
bool
armed
;
signed
char
dir
;
/* 1 - clockwise, -1 - CCW */
unsigned
last_stable
;
unsigned
int
last_stable
;
};
static
unsigned
rotary_encoder_get_state
(
struct
rotary_encoder
*
encoder
)
static
unsigned
int
rotary_encoder_get_state
(
struct
rotary_encoder
*
encoder
)
{
int
i
;
unsigned
ret
=
0
;
unsigned
int
ret
=
0
;
for
(
i
=
0
;
i
<
encoder
->
gpios
->
ndescs
;
++
i
)
{
int
val
=
gpiod_get_value_cansleep
(
encoder
->
gpios
->
desc
[
i
]);
...
...
@@ -100,7 +100,7 @@ static void rotary_encoder_report_event(struct rotary_encoder *encoder)
static
irqreturn_t
rotary_encoder_irq
(
int
irq
,
void
*
dev_id
)
{
struct
rotary_encoder
*
encoder
=
dev_id
;
unsigned
state
;
unsigned
int
state
;
mutex_lock
(
&
encoder
->
access_mutex
);
...
...
drivers/input/misc/twl6040-vibra.c
浏览文件 @
23ea5967
...
...
@@ -46,7 +46,7 @@ struct vibra_info {
struct
device
*
dev
;
struct
input_dev
*
input_dev
;
struct
work_struct
play_work
;
struct
mutex
mutex
;
int
irq
;
bool
enabled
;
...
...
@@ -190,8 +190,6 @@ static void vibra_play_work(struct work_struct *work)
return
;
}
mutex_lock
(
&
info
->
mutex
);
if
(
info
->
weak_speed
||
info
->
strong_speed
)
{
if
(
!
info
->
enabled
)
twl6040_vibra_enable
(
info
);
...
...
@@ -200,7 +198,6 @@ static void vibra_play_work(struct work_struct *work)
}
else
if
(
info
->
enabled
)
twl6040_vibra_disable
(
info
);
mutex_unlock
(
&
info
->
mutex
);
}
static
int
vibra_play
(
struct
input_dev
*
input
,
void
*
data
,
...
...
@@ -223,12 +220,8 @@ static void twl6040_vibra_close(struct input_dev *input)
cancel_work_sync
(
&
info
->
play_work
);
mutex_lock
(
&
info
->
mutex
);
if
(
info
->
enabled
)
twl6040_vibra_disable
(
info
);
mutex_unlock
(
&
info
->
mutex
);
}
static
int
__maybe_unused
twl6040_vibra_suspend
(
struct
device
*
dev
)
...
...
@@ -236,13 +229,11 @@ static int __maybe_unused twl6040_vibra_suspend(struct device *dev)
struct
platform_device
*
pdev
=
to_platform_device
(
dev
);
struct
vibra_info
*
info
=
platform_get_drvdata
(
pdev
);
mutex_lock
(
&
info
->
mutex
);
cancel_work_sync
(
&
info
->
play_work
);
if
(
info
->
enabled
)
twl6040_vibra_disable
(
info
);
mutex_unlock
(
&
info
->
mutex
);
return
0
;
}
...
...
@@ -301,8 +292,6 @@ static int twl6040_vibra_probe(struct platform_device *pdev)
return
-
EINVAL
;
}
mutex_init
(
&
info
->
mutex
);
error
=
devm_request_threaded_irq
(
&
pdev
->
dev
,
info
->
irq
,
NULL
,
twl6040_vib_irq_handler
,
IRQF_ONESHOT
,
...
...
drivers/input/mouse/byd.c
浏览文件 @
23ea5967
...
...
@@ -478,7 +478,6 @@ int byd_init(struct psmouse *psmouse)
if
(
!
priv
)
return
-
ENOMEM
;
memset
(
priv
,
0
,
sizeof
(
*
priv
));
setup_timer
(
&
priv
->
timer
,
byd_clear_touch
,
(
unsigned
long
)
psmouse
);
psmouse
->
private
=
priv
;
...
...
drivers/input/tablet/acecad.c
浏览文件 @
23ea5967
...
...
@@ -49,7 +49,6 @@ MODULE_LICENSE(DRIVER_LICENSE);
struct
usb_acecad
{
char
name
[
128
];
char
phys
[
64
];
struct
usb_device
*
usbdev
;
struct
usb_interface
*
intf
;
struct
input_dev
*
input
;
struct
urb
*
irq
;
...
...
@@ -64,6 +63,7 @@ static void usb_acecad_irq(struct urb *urb)
unsigned
char
*
data
=
acecad
->
data
;
struct
input_dev
*
dev
=
acecad
->
input
;
struct
usb_interface
*
intf
=
acecad
->
intf
;
struct
usb_device
*
udev
=
interface_to_usbdev
(
intf
);
int
prox
,
status
;
switch
(
urb
->
status
)
{
...
...
@@ -110,15 +110,15 @@ static void usb_acecad_irq(struct urb *urb)
if
(
status
)
dev_err
(
&
intf
->
dev
,
"can't resubmit intr, %s-%s/input0, status %d
\n
"
,
acecad
->
usb
dev
->
bus
->
bus_name
,
acecad
->
usb
dev
->
devpath
,
status
);
u
dev
->
bus
->
bus_name
,
u
dev
->
devpath
,
status
);
}
static
int
usb_acecad_open
(
struct
input_dev
*
dev
)
{
struct
usb_acecad
*
acecad
=
input_get_drvdata
(
dev
);
acecad
->
irq
->
dev
=
acecad
->
usbdev
;
acecad
->
irq
->
dev
=
interface_to_usbdev
(
acecad
->
intf
)
;
if
(
usb_submit_urb
(
acecad
->
irq
,
GFP_KERNEL
))
return
-
EIO
;
...
...
@@ -172,7 +172,6 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_
goto
fail2
;
}
acecad
->
usbdev
=
dev
;
acecad
->
intf
=
intf
;
acecad
->
input
=
input_dev
;
...
...
@@ -251,12 +250,13 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_
static
void
usb_acecad_disconnect
(
struct
usb_interface
*
intf
)
{
struct
usb_acecad
*
acecad
=
usb_get_intfdata
(
intf
);
struct
usb_device
*
udev
=
interface_to_usbdev
(
intf
);
usb_set_intfdata
(
intf
,
NULL
);
input_unregister_device
(
acecad
->
input
);
usb_free_urb
(
acecad
->
irq
);
usb_free_coherent
(
acecad
->
usb
dev
,
8
,
acecad
->
data
,
acecad
->
data_dma
);
usb_free_coherent
(
u
dev
,
8
,
acecad
->
data
,
acecad
->
data_dma
);
kfree
(
acecad
);
}
...
...
drivers/input/tablet/aiptek.c
浏览文件 @
23ea5967
...
...
@@ -307,7 +307,6 @@ struct aiptek_settings {
struct
aiptek
{
struct
input_dev
*
inputdev
;
/* input device struct */
struct
usb_device
*
usbdev
;
/* usb device struct */
struct
usb_interface
*
intf
;
/* usb interface struct */
struct
urb
*
urb
;
/* urb for incoming reports */
dma_addr_t
data_dma
;
/* our dma stuffage */
...
...
@@ -847,7 +846,7 @@ static int aiptek_open(struct input_dev *inputdev)
{
struct
aiptek
*
aiptek
=
input_get_drvdata
(
inputdev
);
aiptek
->
urb
->
dev
=
aiptek
->
usbdev
;
aiptek
->
urb
->
dev
=
interface_to_usbdev
(
aiptek
->
intf
)
;
if
(
usb_submit_urb
(
aiptek
->
urb
,
GFP_KERNEL
)
!=
0
)
return
-
EIO
;
...
...
@@ -873,8 +872,10 @@ aiptek_set_report(struct aiptek *aiptek,
unsigned
char
report_type
,
unsigned
char
report_id
,
void
*
buffer
,
int
size
)
{
return
usb_control_msg
(
aiptek
->
usbdev
,
usb_sndctrlpipe
(
aiptek
->
usbdev
,
0
),
struct
usb_device
*
udev
=
interface_to_usbdev
(
aiptek
->
intf
);
return
usb_control_msg
(
udev
,
usb_sndctrlpipe
(
udev
,
0
),
USB_REQ_SET_REPORT
,
USB_TYPE_CLASS
|
USB_RECIP_INTERFACE
|
USB_DIR_OUT
,
(
report_type
<<
8
)
+
report_id
,
...
...
@@ -886,8 +887,10 @@ aiptek_get_report(struct aiptek *aiptek,
unsigned
char
report_type
,
unsigned
char
report_id
,
void
*
buffer
,
int
size
)
{
return
usb_control_msg
(
aiptek
->
usbdev
,
usb_rcvctrlpipe
(
aiptek
->
usbdev
,
0
),
struct
usb_device
*
udev
=
interface_to_usbdev
(
aiptek
->
intf
);
return
usb_control_msg
(
udev
,
usb_rcvctrlpipe
(
udev
,
0
),
USB_REQ_GET_REPORT
,
USB_TYPE_CLASS
|
USB_RECIP_INTERFACE
|
USB_DIR_IN
,
(
report_type
<<
8
)
+
report_id
,
...
...
@@ -1729,7 +1732,6 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
}
aiptek
->
inputdev
=
inputdev
;
aiptek
->
usbdev
=
usbdev
;
aiptek
->
intf
=
intf
;
aiptek
->
ifnum
=
intf
->
altsetting
[
0
].
desc
.
bInterfaceNumber
;
aiptek
->
inDelay
=
0
;
...
...
@@ -1833,8 +1835,8 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
* input.
*/
usb_fill_int_urb
(
aiptek
->
urb
,
aiptek
->
usbdev
,
usb_rcvintpipe
(
aiptek
->
usbdev
,
usbdev
,
usb_rcvintpipe
(
usbdev
,
endpoint
->
bEndpointAddress
),
aiptek
->
data
,
8
,
aiptek_irq
,
aiptek
,
endpoint
->
bInterval
);
...
...
drivers/input/tablet/gtco.c
浏览文件 @
23ea5967
...
...
@@ -104,7 +104,6 @@ MODULE_DEVICE_TABLE (usb, gtco_usbid_table);
struct
gtco
{
struct
input_dev
*
inputdevice
;
/* input device struct pointer */
struct
usb_device
*
usbdev
;
/* the usb device for this device */
struct
usb_interface
*
intf
;
/* the usb interface for this device */
struct
urb
*
urbinfo
;
/* urb for incoming reports */
dma_addr_t
buf_dma
;
/* dma addr of the data buffer*/
...
...
@@ -540,7 +539,7 @@ static int gtco_input_open(struct input_dev *inputdev)
{
struct
gtco
*
device
=
input_get_drvdata
(
inputdev
);
device
->
urbinfo
->
dev
=
device
->
usbdev
;
device
->
urbinfo
->
dev
=
interface_to_usbdev
(
device
->
intf
)
;
if
(
usb_submit_urb
(
device
->
urbinfo
,
GFP_KERNEL
))
return
-
EIO
;
...
...
@@ -824,6 +823,7 @@ static int gtco_probe(struct usb_interface *usbinterface,
int
result
=
0
,
retry
;
int
error
;
struct
usb_endpoint_descriptor
*
endpoint
;
struct
usb_device
*
udev
=
interface_to_usbdev
(
usbinterface
);
/* Allocate memory for device structure */
gtco
=
kzalloc
(
sizeof
(
struct
gtco
),
GFP_KERNEL
);
...
...
@@ -838,11 +838,10 @@ static int gtco_probe(struct usb_interface *usbinterface,
gtco
->
inputdevice
=
input_dev
;
/* Save interface information */
gtco
->
usbdev
=
interface_to_usbdev
(
usbinterface
);
gtco
->
intf
=
usbinterface
;
/* Allocate some data for incoming reports */
gtco
->
buffer
=
usb_alloc_coherent
(
gtco
->
usb
dev
,
REPORT_MAX_SIZE
,
gtco
->
buffer
=
usb_alloc_coherent
(
u
dev
,
REPORT_MAX_SIZE
,
GFP_KERNEL
,
&
gtco
->
buf_dma
);
if
(
!
gtco
->
buffer
)
{
dev_err
(
&
usbinterface
->
dev
,
"No more memory for us buffers
\n
"
);
...
...
@@ -907,8 +906,8 @@ static int gtco_probe(struct usb_interface *usbinterface,
/* Couple of tries to get reply */
for
(
retry
=
0
;
retry
<
3
;
retry
++
)
{
result
=
usb_control_msg
(
gtco
->
usb
dev
,
usb_rcvctrlpipe
(
gtco
->
usb
dev
,
0
),
result
=
usb_control_msg
(
u
dev
,
usb_rcvctrlpipe
(
u
dev
,
0
),
USB_REQ_GET_DESCRIPTOR
,
USB_RECIP_INTERFACE
|
USB_DIR_IN
,
REPORT_DEVICE_TYPE
<<
8
,
...
...
@@ -936,7 +935,7 @@ static int gtco_probe(struct usb_interface *usbinterface,
}
/* Create a device file node */
usb_make_path
(
gtco
->
usb
dev
,
gtco
->
usbpath
,
sizeof
(
gtco
->
usbpath
));
usb_make_path
(
u
dev
,
gtco
->
usbpath
,
sizeof
(
gtco
->
usbpath
));
strlcat
(
gtco
->
usbpath
,
"/input0"
,
sizeof
(
gtco
->
usbpath
));
/* Set Input device functions */
...
...
@@ -953,15 +952,15 @@ static int gtco_probe(struct usb_interface *usbinterface,
gtco_setup_caps
(
input_dev
);
/* Set input device required ID information */
usb_to_input_id
(
gtco
->
usb
dev
,
&
input_dev
->
id
);
usb_to_input_id
(
u
dev
,
&
input_dev
->
id
);
input_dev
->
dev
.
parent
=
&
usbinterface
->
dev
;
/* Setup the URB, it will be posted later on open of input device */
endpoint
=
&
usbinterface
->
altsetting
[
0
].
endpoint
[
0
].
desc
;
usb_fill_int_urb
(
gtco
->
urbinfo
,
gtco
->
usb
dev
,
usb_rcvintpipe
(
gtco
->
usb
dev
,
u
dev
,
usb_rcvintpipe
(
u
dev
,
endpoint
->
bEndpointAddress
),
gtco
->
buffer
,
REPORT_MAX_SIZE
,
...
...
@@ -985,7 +984,7 @@ static int gtco_probe(struct usb_interface *usbinterface,
err_free_urb:
usb_free_urb
(
gtco
->
urbinfo
);
err_free_buf:
usb_free_coherent
(
gtco
->
usb
dev
,
REPORT_MAX_SIZE
,
usb_free_coherent
(
u
dev
,
REPORT_MAX_SIZE
,
gtco
->
buffer
,
gtco
->
buf_dma
);
err_free_devs:
input_free_device
(
input_dev
);
...
...
@@ -1002,13 +1001,14 @@ static void gtco_disconnect(struct usb_interface *interface)
{
/* Grab private device ptr */
struct
gtco
*
gtco
=
usb_get_intfdata
(
interface
);
struct
usb_device
*
udev
=
interface_to_usbdev
(
interface
);
/* Now reverse all the registration stuff */
if
(
gtco
)
{
input_unregister_device
(
gtco
->
inputdevice
);
usb_kill_urb
(
gtco
->
urbinfo
);
usb_free_urb
(
gtco
->
urbinfo
);
usb_free_coherent
(
gtco
->
usb
dev
,
REPORT_MAX_SIZE
,
usb_free_coherent
(
u
dev
,
REPORT_MAX_SIZE
,
gtco
->
buffer
,
gtco
->
buf_dma
);
kfree
(
gtco
);
}
...
...
drivers/input/tablet/kbtab.c
浏览文件 @
23ea5967
...
...
@@ -31,7 +31,6 @@ struct kbtab {
unsigned
char
*
data
;
dma_addr_t
data_dma
;
struct
input_dev
*
dev
;
struct
usb_device
*
usbdev
;
struct
usb_interface
*
intf
;
struct
urb
*
irq
;
char
phys
[
32
];
...
...
@@ -99,8 +98,9 @@ MODULE_DEVICE_TABLE(usb, kbtab_ids);
static
int
kbtab_open
(
struct
input_dev
*
dev
)
{
struct
kbtab
*
kbtab
=
input_get_drvdata
(
dev
);
struct
usb_device
*
udev
=
interface_to_usbdev
(
kbtab
->
intf
);
kbtab
->
irq
->
dev
=
kbtab
->
usb
dev
;
kbtab
->
irq
->
dev
=
u
dev
;
if
(
usb_submit_urb
(
kbtab
->
irq
,
GFP_KERNEL
))
return
-
EIO
;
...
...
@@ -135,7 +135,6 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i
if
(
!
kbtab
->
irq
)
goto
fail2
;
kbtab
->
usbdev
=
dev
;
kbtab
->
intf
=
intf
;
kbtab
->
dev
=
input_dev
;
...
...
@@ -188,12 +187,13 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i
static
void
kbtab_disconnect
(
struct
usb_interface
*
intf
)
{
struct
kbtab
*
kbtab
=
usb_get_intfdata
(
intf
);
struct
usb_device
*
udev
=
interface_to_usbdev
(
intf
);
usb_set_intfdata
(
intf
,
NULL
);
input_unregister_device
(
kbtab
->
dev
);
usb_free_urb
(
kbtab
->
irq
);
usb_free_coherent
(
kbtab
->
usb
dev
,
8
,
kbtab
->
data
,
kbtab
->
data_dma
);
usb_free_coherent
(
u
dev
,
8
,
kbtab
->
data
,
kbtab
->
data_dma
);
kfree
(
kbtab
);
}
...
...
drivers/input/touchscreen/bcm_iproc_tsc.c
浏览文件 @
23ea5967
...
...
@@ -23,6 +23,8 @@
#include <linux/io.h>
#include <linux/clk.h>
#include <linux/serio.h>
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
#define IPROC_TS_NAME "iproc-ts"
...
...
@@ -88,7 +90,11 @@
#define TS_WIRE_MODE_BIT BIT(1)
#define dbg_reg(dev, priv, reg) \
dev_dbg(dev, "%20s= 0x%08x\n", #reg, readl((priv)->regs + reg))
do { \
u32 val; \
regmap_read(priv->regmap, reg, &val); \
dev_dbg(dev, "%20s= 0x%08x\n", #reg, val); \
} while (0)
struct
tsc_param
{
/* Each step is 1024 us. Valid 1-256 */
...
...
@@ -141,7 +147,7 @@ struct iproc_ts_priv {
struct
platform_device
*
pdev
;
struct
input_dev
*
idev
;
void
__iomem
*
regs
;
struct
regmap
*
regmap
;
struct
clk
*
tsc_clk
;
int
pen_status
;
...
...
@@ -196,22 +202,22 @@ static irqreturn_t iproc_touchscreen_interrupt(int irq, void *data)
int
i
;
bool
needs_sync
=
false
;
intr_status
=
readl
(
priv
->
regs
+
INTERRUPT_STATUS
);
regmap_read
(
priv
->
regmap
,
INTERRUPT_STATUS
,
&
intr_status
);
intr_status
&=
TS_PEN_INTR_MASK
|
TS_FIFO_INTR_MASK
;
if
(
intr_status
==
0
)
return
IRQ_NONE
;
/* Clear all interrupt status bits, write-1-clear */
writel
(
intr_status
,
priv
->
regs
+
INTERRUPT_STATUS
);
regmap_write
(
priv
->
regmap
,
INTERRUPT_STATUS
,
intr_status
);
/* Pen up/down */
if
(
intr_status
&
TS_PEN_INTR_MASK
)
{
if
(
readl
(
priv
->
regs
+
CONTROLLER_STATUS
)
&
TS_PEN_DOWN
)
regmap_read
(
priv
->
regmap
,
CONTROLLER_STATUS
,
&
priv
->
pen_status
);
if
(
priv
->
pen_status
&
TS_PEN_DOWN
)
priv
->
pen_status
=
PEN_DOWN_STATUS
;
else
priv
->
pen_status
=
PEN_UP_STATUS
;
input_report_key
(
priv
->
idev
,
BTN_TOUCH
,
priv
->
pen_status
);
input_report_key
(
priv
->
idev
,
BTN_TOUCH
,
priv
->
pen_status
);
needs_sync
=
true
;
dev_dbg
(
&
priv
->
pdev
->
dev
,
...
...
@@ -221,7 +227,7 @@ static irqreturn_t iproc_touchscreen_interrupt(int irq, void *data)
/* coordinates in FIFO exceed the theshold */
if
(
intr_status
&
TS_FIFO_INTR_MASK
)
{
for
(
i
=
0
;
i
<
priv
->
cfg_params
.
fifo_threshold
;
i
++
)
{
r
aw_coordinate
=
readl
(
priv
->
regs
+
FIFO_DATA
);
r
egmap_read
(
priv
->
regmap
,
FIFO_DATA
,
&
raw_coordinate
);
if
(
raw_coordinate
==
INVALID_COORD
)
continue
;
...
...
@@ -239,7 +245,7 @@ static irqreturn_t iproc_touchscreen_interrupt(int irq, void *data)
x
=
(
x
>>
4
)
&
0x0FFF
;
y
=
(
y
>>
4
)
&
0x0FFF
;
/*
adjust x y according to lcd tsc mount angle
*/
/*
Adjust x y according to LCD tsc mount angle.
*/
if
(
priv
->
cfg_params
.
invert_x
)
x
=
priv
->
cfg_params
.
max_x
-
x
;
...
...
@@ -262,9 +268,10 @@ static irqreturn_t iproc_touchscreen_interrupt(int irq, void *data)
static
int
iproc_ts_start
(
struct
input_dev
*
idev
)
{
struct
iproc_ts_priv
*
priv
=
input_get_drvdata
(
idev
);
u32
val
;
u32
mask
;
int
error
;
struct
iproc_ts_priv
*
priv
=
input_get_drvdata
(
idev
);
/* Enable clock */
error
=
clk_prepare_enable
(
priv
->
tsc_clk
);
...
...
@@ -279,9 +286,10 @@ static int iproc_ts_start(struct input_dev *idev)
* FIFO reaches the int_th value, and pen event(up/down)
*/
val
=
TS_PEN_INTR_MASK
|
TS_FIFO_INTR_MASK
;
writel
(
val
,
priv
->
regs
+
INTERRUPT_MASK
);
regmap_update_bits
(
priv
->
regmap
,
INTERRUPT_MASK
,
val
,
val
);
writel
(
priv
->
cfg_params
.
fifo_threshold
,
priv
->
regs
+
INTERRUPT_THRES
);
val
=
priv
->
cfg_params
.
fifo_threshold
;
regmap_write
(
priv
->
regmap
,
INTERRUPT_THRES
,
val
);
/* Initialize control reg1 */
val
=
0
;
...
...
@@ -289,26 +297,23 @@ static int iproc_ts_start(struct input_dev *idev)
val
|=
priv
->
cfg_params
.
debounce_timeout
<<
DEBOUNCE_TIMEOUT_SHIFT
;
val
|=
priv
->
cfg_params
.
settling_timeout
<<
SETTLING_TIMEOUT_SHIFT
;
val
|=
priv
->
cfg_params
.
touch_timeout
<<
TOUCH_TIMEOUT_SHIFT
;
writel
(
val
,
priv
->
regs
+
REGCTL1
);
regmap_write
(
priv
->
regmap
,
REGCTL1
,
val
);
/* Try to clear all interrupt status */
val
=
readl
(
priv
->
regs
+
INTERRUPT_STATUS
);
val
|=
TS_FIFO_INTR_MASK
|
TS_PEN_INTR_MASK
;
writel
(
val
,
priv
->
regs
+
INTERRUPT_STATUS
);
val
=
TS_FIFO_INTR_MASK
|
TS_PEN_INTR_MASK
;
regmap_update_bits
(
priv
->
regmap
,
INTERRUPT_STATUS
,
val
,
val
);
/* Initialize control reg2 */
val
=
readl
(
priv
->
regs
+
REGCTL2
);
val
|=
TS_CONTROLLER_EN_BIT
|
TS_WIRE_MODE_BIT
;
val
&=
~
TS_CONTROLLER_AVGDATA_MASK
;
val
=
TS_CONTROLLER_EN_BIT
|
TS_WIRE_MODE_BIT
;
val
|=
priv
->
cfg_params
.
average_data
<<
TS_CONTROLLER_AVGDATA_SHIFT
;
val
&=
~
(
TS_CONTROLLER_PWR_LDO
|
/* PWR up LDO */
mask
=
(
TS_CONTROLLER_AVGDATA_MASK
);
mask
|=
(
TS_CONTROLLER_PWR_LDO
|
/* PWR up LDO */
TS_CONTROLLER_PWR_ADC
|
/* PWR up ADC */
TS_CONTROLLER_PWR_BGP
|
/* PWR up BGP */
TS_CONTROLLER_PWR_TS
);
/* PWR up TS */
writel
(
val
,
priv
->
regs
+
REGCTL2
);
mask
|=
val
;
regmap_update_bits
(
priv
->
regmap
,
REGCTL2
,
mask
,
val
);
ts_reg_dump
(
priv
);
...
...
@@ -320,12 +325,17 @@ static void iproc_ts_stop(struct input_dev *dev)
u32
val
;
struct
iproc_ts_priv
*
priv
=
input_get_drvdata
(
dev
);
writel
(
0
,
priv
->
regs
+
INTERRUPT_MASK
);
/* Disable all interrupts */
/*
* Disable FIFO int_th and pen event(up/down)Interrupts only
* as the interrupt mask register is shared between ADC, TS and
* flextimer.
*/
val
=
TS_PEN_INTR_MASK
|
TS_FIFO_INTR_MASK
;
regmap_update_bits
(
priv
->
regmap
,
INTERRUPT_MASK
,
val
,
0
);
/* Only power down touch screen controller */
val
=
readl
(
priv
->
regs
+
REGCTL2
);
val
|=
TS_CONTROLLER_PWR_TS
;
writel
(
val
,
priv
->
regs
+
REGCTL2
);
val
=
TS_CONTROLLER_PWR_TS
;
regmap_update_bits
(
priv
->
regmap
,
REGCTL2
,
val
,
val
);
clk_disable
(
priv
->
tsc_clk
);
}
...
...
@@ -414,7 +424,6 @@ static int iproc_ts_probe(struct platform_device *pdev)
{
struct
iproc_ts_priv
*
priv
;
struct
input_dev
*
idev
;
struct
resource
*
res
;
int
irq
;
int
error
;
...
...
@@ -422,12 +431,12 @@ static int iproc_ts_probe(struct platform_device *pdev)
if
(
!
priv
)
return
-
ENOMEM
;
/* touchscreen controller memory mapped regs */
res
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
priv
->
regs
=
devm_ioremap_resource
(
&
pdev
->
dev
,
res
);
if
(
IS_ERR
(
priv
->
reg
s
))
{
error
=
PTR_ERR
(
priv
->
reg
s
);
dev_err
(
&
pdev
->
dev
,
"unable to map I/O memory:
%d
\n
"
,
error
);
/* touchscreen controller memory mapped regs
via syscon
*/
priv
->
regmap
=
syscon_regmap_lookup_by_phandle
(
pdev
->
dev
.
of_node
,
"ts_syscon"
);
if
(
IS_ERR
(
priv
->
reg
map
))
{
error
=
PTR_ERR
(
priv
->
reg
map
);
dev_err
(
&
pdev
->
dev
,
"unable to map I/O memory:%d
\n
"
,
error
);
return
error
;
}
...
...
drivers/input/touchscreen/ti_am335x_tsc.c
浏览文件 @
23ea5967
...
...
@@ -487,8 +487,7 @@ static int titsc_remove(struct platform_device *pdev)
return
0
;
}
#ifdef CONFIG_PM
static
int
titsc_suspend
(
struct
device
*
dev
)
static
int
__maybe_unused
titsc_suspend
(
struct
device
*
dev
)
{
struct
titsc
*
ts_dev
=
dev_get_drvdata
(
dev
);
struct
ti_tscadc_dev
*
tscadc_dev
;
...
...
@@ -504,7 +503,7 @@ static int titsc_suspend(struct device *dev)
return
0
;
}
static
int
titsc_resume
(
struct
device
*
dev
)
static
int
__maybe_unused
titsc_resume
(
struct
device
*
dev
)
{
struct
titsc
*
ts_dev
=
dev_get_drvdata
(
dev
);
struct
ti_tscadc_dev
*
tscadc_dev
;
...
...
@@ -521,14 +520,7 @@ static int titsc_resume(struct device *dev)
return
0
;
}
static
const
struct
dev_pm_ops
titsc_pm_ops
=
{
.
suspend
=
titsc_suspend
,
.
resume
=
titsc_resume
,
};
#define TITSC_PM_OPS (&titsc_pm_ops)
#else
#define TITSC_PM_OPS NULL
#endif
static
SIMPLE_DEV_PM_OPS
(
titsc_pm_ops
,
titsc_suspend
,
titsc_resume
);
static
const
struct
of_device_id
ti_tsc_dt_ids
[]
=
{
{
.
compatible
=
"ti,am3359-tsc"
,
},
...
...
@@ -541,7 +533,7 @@ static struct platform_driver ti_tsc_driver = {
.
remove
=
titsc_remove
,
.
driver
=
{
.
name
=
"TI-am335x-tsc"
,
.
pm
=
TITSC_PM_OPS
,
.
pm
=
&
titsc_pm_ops
,
.
of_match_table
=
ti_tsc_dt_ids
,
},
};
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录