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
91167e19
Commit
91167e19
authored
Aug 14, 2014
by
Dmitry Torokhov
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'next' into for-linus
Prepare second round of input updates for 3.17.
parents
a6b48699
3361a976
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
459 additions
and
201 deletions
+459
-201
drivers/input/input-mt.c
drivers/input/input-mt.c
+27
-11
drivers/input/joystick/xpad.c
drivers/input/joystick/xpad.c
+157
-17
drivers/input/keyboard/cap1106.c
drivers/input/keyboard/cap1106.c
+7
-1
drivers/input/mouse/synaptics.c
drivers/input/mouse/synaptics.c
+69
-3
drivers/input/touchscreen/atmel_mxt_ts.c
drivers/input/touchscreen/atmel_mxt_ts.c
+198
-168
drivers/input/touchscreen/edt-ft5x06.c
drivers/input/touchscreen/edt-ft5x06.c
+0
-1
include/linux/input/mt.h
include/linux/input/mt.h
+1
-0
No files found.
drivers/input/input-mt.c
View file @
91167e19
...
...
@@ -236,6 +236,31 @@ void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_count)
}
EXPORT_SYMBOL
(
input_mt_report_pointer_emulation
);
/**
* input_mt_drop_unused() - Inactivate slots not seen in this frame
* @dev: input device with allocated MT slots
*
* Lift all slots not seen since the last call to this function.
*/
void
input_mt_drop_unused
(
struct
input_dev
*
dev
)
{
struct
input_mt
*
mt
=
dev
->
mt
;
int
i
;
if
(
!
mt
)
return
;
for
(
i
=
0
;
i
<
mt
->
num_slots
;
i
++
)
{
if
(
!
input_mt_is_used
(
mt
,
&
mt
->
slots
[
i
]))
{
input_mt_slot
(
dev
,
i
);
input_event
(
dev
,
EV_ABS
,
ABS_MT_TRACKING_ID
,
-
1
);
}
}
mt
->
frame
++
;
}
EXPORT_SYMBOL
(
input_mt_drop_unused
);
/**
* input_mt_sync_frame() - synchronize mt frame
* @dev: input device with allocated MT slots
...
...
@@ -247,27 +272,18 @@ EXPORT_SYMBOL(input_mt_report_pointer_emulation);
void
input_mt_sync_frame
(
struct
input_dev
*
dev
)
{
struct
input_mt
*
mt
=
dev
->
mt
;
struct
input_mt_slot
*
s
;
bool
use_count
=
false
;
if
(
!
mt
)
return
;
if
(
mt
->
flags
&
INPUT_MT_DROP_UNUSED
)
{
for
(
s
=
mt
->
slots
;
s
!=
mt
->
slots
+
mt
->
num_slots
;
s
++
)
{
if
(
input_mt_is_used
(
mt
,
s
))
continue
;
input_mt_slot
(
dev
,
s
-
mt
->
slots
);
input_event
(
dev
,
EV_ABS
,
ABS_MT_TRACKING_ID
,
-
1
);
}
}
if
(
mt
->
flags
&
INPUT_MT_DROP_UNUSED
)
input_mt_drop_unused
(
dev
);
if
((
mt
->
flags
&
INPUT_MT_POINTER
)
&&
!
(
mt
->
flags
&
INPUT_MT_SEMI_MT
))
use_count
=
true
;
input_mt_report_pointer_emulation
(
dev
,
use_count
);
mt
->
frame
++
;
}
EXPORT_SYMBOL
(
input_mt_sync_frame
);
...
...
drivers/input/joystick/xpad.c
View file @
91167e19
...
...
@@ -95,7 +95,8 @@
#define XTYPE_XBOX 0
#define XTYPE_XBOX360 1
#define XTYPE_XBOX360W 2
#define XTYPE_UNKNOWN 3
#define XTYPE_XBOXONE 3
#define XTYPE_UNKNOWN 4
static
bool
dpad_to_buttons
;
module_param
(
dpad_to_buttons
,
bool
,
S_IRUGO
);
...
...
@@ -121,6 +122,7 @@ static const struct xpad_device {
{
0x045e
,
0x0287
,
"Microsoft Xbox Controller S"
,
0
,
XTYPE_XBOX
},
{
0x045e
,
0x0289
,
"Microsoft X-Box pad v2 (US)"
,
0
,
XTYPE_XBOX
},
{
0x045e
,
0x028e
,
"Microsoft X-Box 360 pad"
,
0
,
XTYPE_XBOX360
},
{
0x045e
,
0x02d1
,
"Microsoft X-Box One pad"
,
0
,
XTYPE_XBOXONE
},
{
0x045e
,
0x0291
,
"Xbox 360 Wireless Receiver (XBOX)"
,
MAP_DPAD_TO_BUTTONS
,
XTYPE_XBOX360W
},
{
0x045e
,
0x0719
,
"Xbox 360 Wireless Receiver"
,
MAP_DPAD_TO_BUTTONS
,
XTYPE_XBOX360W
},
{
0x044f
,
0x0f07
,
"Thrustmaster, Inc. Controller"
,
0
,
XTYPE_XBOX
},
...
...
@@ -231,10 +233,12 @@ static const signed short xpad_abs_triggers[] = {
-
1
};
/* Xbox 360 has a vendor-specific class, so we cannot match it with only
/*
* Xbox 360 has a vendor-specific class, so we cannot match it with only
* USB_INTERFACE_INFO (also specifically refused by USB subsystem), so we
* match against vendor id as well. Wired Xbox 360 devices have protocol 1,
* wireless controllers have protocol 129. */
* wireless controllers have protocol 129.
*/
#define XPAD_XBOX360_VENDOR_PROTOCOL(vend,pr) \
.match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, \
.idVendor = (vend), \
...
...
@@ -245,9 +249,20 @@ static const signed short xpad_abs_triggers[] = {
{ XPAD_XBOX360_VENDOR_PROTOCOL(vend,1) }, \
{ XPAD_XBOX360_VENDOR_PROTOCOL(vend,129) }
/* The Xbox One controller uses subclass 71 and protocol 208. */
#define XPAD_XBOXONE_VENDOR_PROTOCOL(vend, pr) \
.match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, \
.idVendor = (vend), \
.bInterfaceClass = USB_CLASS_VENDOR_SPEC, \
.bInterfaceSubClass = 71, \
.bInterfaceProtocol = (pr)
#define XPAD_XBOXONE_VENDOR(vend) \
{ XPAD_XBOXONE_VENDOR_PROTOCOL(vend, 208) }
static
struct
usb_device_id
xpad_table
[]
=
{
{
USB_INTERFACE_INFO
(
'X'
,
'B'
,
0
)
},
/* X-Box USB-IF not approved class */
XPAD_XBOX360_VENDOR
(
0x045e
),
/* Microsoft X-Box 360 controllers */
XPAD_XBOXONE_VENDOR
(
0x045e
),
/* Microsoft X-Box One controllers */
XPAD_XBOX360_VENDOR
(
0x046d
),
/* Logitech X-Box 360 style controllers */
XPAD_XBOX360_VENDOR
(
0x0738
),
/* Mad Catz X-Box 360 controllers */
{
USB_DEVICE
(
0x0738
,
0x4540
)
},
/* Mad Catz Beat Pad */
...
...
@@ -278,12 +293,10 @@ struct usb_xpad {
struct
urb
*
bulk_out
;
unsigned
char
*
bdata
;
#if defined(CONFIG_JOYSTICK_XPAD_FF) || defined(CONFIG_JOYSTICK_XPAD_LEDS)
struct
urb
*
irq_out
;
/* urb for interrupt out report */
unsigned
char
*
odata
;
/* output data */
dma_addr_t
odata_dma
;
struct
mutex
odata_mutex
;
#endif
#if defined(CONFIG_JOYSTICK_XPAD_LEDS)
struct
xpad_led
*
led
;
...
...
@@ -470,6 +483,105 @@ static void xpad360w_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned cha
xpad360_process_packet
(
xpad
,
cmd
,
&
data
[
4
]);
}
/*
* xpadone_process_buttons
*
* Process a button update packet from an Xbox one controller.
*/
static
void
xpadone_process_buttons
(
struct
usb_xpad
*
xpad
,
struct
input_dev
*
dev
,
unsigned
char
*
data
)
{
/* menu/view buttons */
input_report_key
(
dev
,
BTN_START
,
data
[
4
]
&
0x04
);
input_report_key
(
dev
,
BTN_SELECT
,
data
[
4
]
&
0x08
);
/* buttons A,B,X,Y */
input_report_key
(
dev
,
BTN_A
,
data
[
4
]
&
0x10
);
input_report_key
(
dev
,
BTN_B
,
data
[
4
]
&
0x20
);
input_report_key
(
dev
,
BTN_X
,
data
[
4
]
&
0x40
);
input_report_key
(
dev
,
BTN_Y
,
data
[
4
]
&
0x80
);
/* digital pad */
if
(
xpad
->
mapping
&
MAP_DPAD_TO_BUTTONS
)
{
/* dpad as buttons (left, right, up, down) */
input_report_key
(
dev
,
BTN_TRIGGER_HAPPY1
,
data
[
5
]
&
0x04
);
input_report_key
(
dev
,
BTN_TRIGGER_HAPPY2
,
data
[
5
]
&
0x08
);
input_report_key
(
dev
,
BTN_TRIGGER_HAPPY3
,
data
[
5
]
&
0x01
);
input_report_key
(
dev
,
BTN_TRIGGER_HAPPY4
,
data
[
5
]
&
0x02
);
}
else
{
input_report_abs
(
dev
,
ABS_HAT0X
,
!!
(
data
[
5
]
&
0x08
)
-
!!
(
data
[
5
]
&
0x04
));
input_report_abs
(
dev
,
ABS_HAT0Y
,
!!
(
data
[
5
]
&
0x02
)
-
!!
(
data
[
5
]
&
0x01
));
}
/* TL/TR */
input_report_key
(
dev
,
BTN_TL
,
data
[
5
]
&
0x10
);
input_report_key
(
dev
,
BTN_TR
,
data
[
5
]
&
0x20
);
/* stick press left/right */
input_report_key
(
dev
,
BTN_THUMBL
,
data
[
5
]
&
0x40
);
input_report_key
(
dev
,
BTN_THUMBR
,
data
[
5
]
&
0x80
);
if
(
!
(
xpad
->
mapping
&
MAP_STICKS_TO_NULL
))
{
/* left stick */
input_report_abs
(
dev
,
ABS_X
,
(
__s16
)
le16_to_cpup
((
__le16
*
)(
data
+
10
)));
input_report_abs
(
dev
,
ABS_Y
,
~
(
__s16
)
le16_to_cpup
((
__le16
*
)(
data
+
12
)));
/* right stick */
input_report_abs
(
dev
,
ABS_RX
,
(
__s16
)
le16_to_cpup
((
__le16
*
)(
data
+
14
)));
input_report_abs
(
dev
,
ABS_RY
,
~
(
__s16
)
le16_to_cpup
((
__le16
*
)(
data
+
16
)));
}
/* triggers left/right */
if
(
xpad
->
mapping
&
MAP_TRIGGERS_TO_BUTTONS
)
{
input_report_key
(
dev
,
BTN_TL2
,
(
__u16
)
le16_to_cpup
((
__le16
*
)(
data
+
6
)));
input_report_key
(
dev
,
BTN_TR2
,
(
__u16
)
le16_to_cpup
((
__le16
*
)(
data
+
8
)));
}
else
{
input_report_abs
(
dev
,
ABS_Z
,
(
__u16
)
le16_to_cpup
((
__le16
*
)(
data
+
6
)));
input_report_abs
(
dev
,
ABS_RZ
,
(
__u16
)
le16_to_cpup
((
__le16
*
)(
data
+
8
)));
}
input_sync
(
dev
);
}
/*
* xpadone_process_packet
*
* Completes a request by converting the data into events for the
* input subsystem. This version is for the Xbox One controller.
*
* The report format was gleaned from
* https://github.com/kylelemons/xbox/blob/master/xbox.go
*/
static
void
xpadone_process_packet
(
struct
usb_xpad
*
xpad
,
u16
cmd
,
unsigned
char
*
data
)
{
struct
input_dev
*
dev
=
xpad
->
dev
;
switch
(
data
[
0
])
{
case
0x20
:
xpadone_process_buttons
(
xpad
,
dev
,
data
);
break
;
case
0x07
:
/* the xbox button has its own special report */
input_report_key
(
dev
,
BTN_MODE
,
data
[
4
]
&
0x01
);
input_sync
(
dev
);
break
;
}
}
static
void
xpad_irq_in
(
struct
urb
*
urb
)
{
struct
usb_xpad
*
xpad
=
urb
->
context
;
...
...
@@ -502,6 +614,9 @@ static void xpad_irq_in(struct urb *urb)
case
XTYPE_XBOX360W
:
xpad360w_process_packet
(
xpad
,
0
,
xpad
->
idata
);
break
;
case
XTYPE_XBOXONE
:
xpadone_process_packet
(
xpad
,
0
,
xpad
->
idata
);
break
;
default:
xpad_process_packet
(
xpad
,
0
,
xpad
->
idata
);
}
...
...
@@ -535,7 +650,6 @@ static void xpad_bulk_out(struct urb *urb)
}
}
#if defined(CONFIG_JOYSTICK_XPAD_FF) || defined(CONFIG_JOYSTICK_XPAD_LEDS)
static
void
xpad_irq_out
(
struct
urb
*
urb
)
{
struct
usb_xpad
*
xpad
=
urb
->
context
;
...
...
@@ -573,6 +687,7 @@ static void xpad_irq_out(struct urb *urb)
static
int
xpad_init_output
(
struct
usb_interface
*
intf
,
struct
usb_xpad
*
xpad
)
{
struct
usb_endpoint_descriptor
*
ep_irq_out
;
int
ep_irq_out_idx
;
int
error
;
if
(
xpad
->
xtype
==
XTYPE_UNKNOWN
)
...
...
@@ -593,7 +708,10 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)
goto
fail2
;
}
ep_irq_out
=
&
intf
->
cur_altsetting
->
endpoint
[
1
].
desc
;
/* Xbox One controller has in/out endpoints swapped. */
ep_irq_out_idx
=
xpad
->
xtype
==
XTYPE_XBOXONE
?
0
:
1
;
ep_irq_out
=
&
intf
->
cur_altsetting
->
endpoint
[
ep_irq_out_idx
].
desc
;
usb_fill_int_urb
(
xpad
->
irq_out
,
xpad
->
udev
,
usb_sndintpipe
(
xpad
->
udev
,
ep_irq_out
->
bEndpointAddress
),
xpad
->
odata
,
XPAD_PKT_LEN
,
...
...
@@ -621,11 +739,6 @@ static void xpad_deinit_output(struct usb_xpad *xpad)
xpad
->
odata
,
xpad
->
odata_dma
);
}
}
#else
static
int
xpad_init_output
(
struct
usb_interface
*
intf
,
struct
usb_xpad
*
xpad
)
{
return
0
;
}
static
void
xpad_deinit_output
(
struct
usb_xpad
*
xpad
)
{}
static
void
xpad_stop_output
(
struct
usb_xpad
*
xpad
)
{}
#endif
#ifdef CONFIG_JOYSTICK_XPAD_FF
static
int
xpad_play_effect
(
struct
input_dev
*
dev
,
void
*
data
,
struct
ff_effect
*
effect
)
...
...
@@ -692,7 +805,7 @@ static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect
static
int
xpad_init_ff
(
struct
usb_xpad
*
xpad
)
{
if
(
xpad
->
xtype
==
XTYPE_UNKNOWN
)
if
(
xpad
->
xtype
==
XTYPE_UNKNOWN
||
xpad
->
xtype
==
XTYPE_XBOXONE
)
return
0
;
input_set_capability
(
xpad
->
dev
,
EV_FF
,
FF_RUMBLE
);
...
...
@@ -801,6 +914,14 @@ static int xpad_open(struct input_dev *dev)
if
(
usb_submit_urb
(
xpad
->
irq_in
,
GFP_KERNEL
))
return
-
EIO
;
if
(
xpad
->
xtype
==
XTYPE_XBOXONE
)
{
/* Xbox one controller needs to be initialized. */
xpad
->
odata
[
0
]
=
0x05
;
xpad
->
odata
[
1
]
=
0x20
;
xpad
->
irq_out
->
transfer_buffer_length
=
2
;
return
usb_submit_urb
(
xpad
->
irq_out
,
GFP_KERNEL
);
}
return
0
;
}
...
...
@@ -816,6 +937,7 @@ static void xpad_close(struct input_dev *dev)
static
void
xpad_set_up_abs
(
struct
input_dev
*
input_dev
,
signed
short
abs
)
{
struct
usb_xpad
*
xpad
=
input_get_drvdata
(
input_dev
);
set_bit
(
abs
,
input_dev
->
absbit
);
switch
(
abs
)
{
...
...
@@ -827,7 +949,10 @@ static void xpad_set_up_abs(struct input_dev *input_dev, signed short abs)
break
;
case
ABS_Z
:
case
ABS_RZ
:
/* the triggers (if mapped to axes) */
input_set_abs_params
(
input_dev
,
abs
,
0
,
255
,
0
,
0
);
if
(
xpad
->
xtype
==
XTYPE_XBOXONE
)
input_set_abs_params
(
input_dev
,
abs
,
0
,
1023
,
0
,
0
);
else
input_set_abs_params
(
input_dev
,
abs
,
0
,
255
,
0
,
0
);
break
;
case
ABS_HAT0X
:
case
ABS_HAT0Y
:
/* the d-pad (only if dpad is mapped to axes */
...
...
@@ -842,6 +967,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
struct
usb_xpad
*
xpad
;
struct
input_dev
*
input_dev
;
struct
usb_endpoint_descriptor
*
ep_irq_in
;
int
ep_irq_in_idx
;
int
i
,
error
;
for
(
i
=
0
;
xpad_device
[
i
].
idVendor
;
i
++
)
{
...
...
@@ -850,6 +976,16 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
break
;
}
if
(
xpad_device
[
i
].
xtype
==
XTYPE_XBOXONE
&&
intf
->
cur_altsetting
->
desc
.
bInterfaceNumber
!=
0
)
{
/*
* The Xbox One controller lists three interfaces all with the
* same interface class, subclass and protocol. Differentiate by
* interface number.
*/
return
-
ENODEV
;
}
xpad
=
kzalloc
(
sizeof
(
struct
usb_xpad
),
GFP_KERNEL
);
input_dev
=
input_allocate_device
();
if
(
!
xpad
||
!
input_dev
)
{
...
...
@@ -920,7 +1056,8 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
__set_bit
(
xpad_common_btn
[
i
],
input_dev
->
keybit
);
/* set up model-specific ones */
if
(
xpad
->
xtype
==
XTYPE_XBOX360
||
xpad
->
xtype
==
XTYPE_XBOX360W
)
{
if
(
xpad
->
xtype
==
XTYPE_XBOX360
||
xpad
->
xtype
==
XTYPE_XBOX360W
||
xpad
->
xtype
==
XTYPE_XBOXONE
)
{
for
(
i
=
0
;
xpad360_btn
[
i
]
>=
0
;
i
++
)
__set_bit
(
xpad360_btn
[
i
],
input_dev
->
keybit
);
}
else
{
...
...
@@ -933,7 +1070,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
__set_bit
(
xpad_btn_pad
[
i
],
input_dev
->
keybit
);
}
else
{
for
(
i
=
0
;
xpad_abs_pad
[
i
]
>=
0
;
i
++
)
xpad_set_up_abs
(
input_dev
,
xpad_abs_pad
[
i
]);
xpad_set_up_abs
(
input_dev
,
xpad_abs_pad
[
i
]);
}
if
(
xpad
->
mapping
&
MAP_TRIGGERS_TO_BUTTONS
)
{
...
...
@@ -956,7 +1093,10 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
if
(
error
)
goto
fail5
;
ep_irq_in
=
&
intf
->
cur_altsetting
->
endpoint
[
0
].
desc
;
/* Xbox One controller has in/out endpoints swapped. */
ep_irq_in_idx
=
xpad
->
xtype
==
XTYPE_XBOXONE
?
1
:
0
;
ep_irq_in
=
&
intf
->
cur_altsetting
->
endpoint
[
ep_irq_in_idx
].
desc
;
usb_fill_int_urb
(
xpad
->
irq_in
,
udev
,
usb_rcvintpipe
(
udev
,
ep_irq_in
->
bEndpointAddress
),
xpad
->
idata
,
XPAD_PKT_LEN
,
xpad_irq_in
,
...
...
drivers/input/keyboard/cap1106.c
View file @
91167e19
...
...
@@ -64,7 +64,7 @@ struct cap1106_priv {
struct
input_dev
*
idev
;
/* config */
unsigned
in
t
keycodes
[
CAP1106_NUM_CHN
];
unsigned
shor
t
keycodes
[
CAP1106_NUM_CHN
];
};
static
const
struct
reg_default
cap1106_reg_defaults
[]
=
{
...
...
@@ -272,6 +272,12 @@ static int cap1106_i2c_probe(struct i2c_client *i2c_client,
for
(
i
=
0
;
i
<
CAP1106_NUM_CHN
;
i
++
)
__set_bit
(
priv
->
keycodes
[
i
],
priv
->
idev
->
keybit
);
__clear_bit
(
KEY_RESERVED
,
priv
->
idev
->
keybit
);
priv
->
idev
->
keycode
=
priv
->
keycodes
;
priv
->
idev
->
keycodesize
=
sizeof
(
priv
->
keycodes
[
0
]);
priv
->
idev
->
keycodemax
=
ARRAY_SIZE
(
priv
->
keycodes
);
priv
->
idev
->
id
.
vendor
=
CAP1106_MANUFACTURER_ID
;
priv
->
idev
->
id
.
product
=
CAP1106_PRODUCT_ID
;
priv
->
idev
->
id
.
version
=
rev
;
...
...
drivers/input/mouse/synaptics.c
View file @
91167e19
...
...
@@ -117,6 +117,9 @@ void synaptics_reset(struct psmouse *psmouse)
}
#ifdef CONFIG_MOUSE_PS2_SYNAPTICS
static
bool
cr48_profile_sensor
;
struct
min_max_quirk
{
const
char
*
const
*
pnp_ids
;
int
x_min
,
x_max
,
y_min
,
y_max
;
...
...
@@ -1152,6 +1155,42 @@ static void synaptics_image_sensor_process(struct psmouse *psmouse,
priv
->
agm_pending
=
false
;
}
static
void
synaptics_profile_sensor_process
(
struct
psmouse
*
psmouse
,
struct
synaptics_hw_state
*
sgm
,
int
num_fingers
)
{
struct
input_dev
*
dev
=
psmouse
->
dev
;
struct
synaptics_data
*
priv
=
psmouse
->
private
;
struct
synaptics_hw_state
*
hw
[
2
]
=
{
sgm
,
&
priv
->
agm
};
struct
input_mt_pos
pos
[
2
];
int
slot
[
2
],
nsemi
,
i
;
nsemi
=
clamp_val
(
num_fingers
,
0
,
2
);
for
(
i
=
0
;
i
<
nsemi
;
i
++
)
{
pos
[
i
].
x
=
hw
[
i
]
->
x
;
pos
[
i
].
y
=
synaptics_invert_y
(
hw
[
i
]
->
y
);
}
input_mt_assign_slots
(
dev
,
slot
,
pos
,
nsemi
);
for
(
i
=
0
;
i
<
nsemi
;
i
++
)
{
input_mt_slot
(
dev
,
slot
[
i
]);
input_mt_report_slot_state
(
dev
,
MT_TOOL_FINGER
,
true
);
input_report_abs
(
dev
,
ABS_MT_POSITION_X
,
pos
[
i
].
x
);
input_report_abs
(
dev
,
ABS_MT_POSITION_Y
,
pos
[
i
].
y
);
input_report_abs
(
dev
,
ABS_MT_PRESSURE
,
hw
[
i
]
->
z
);
}
input_mt_drop_unused
(
dev
);
input_mt_report_pointer_emulation
(
dev
,
false
);
input_mt_report_finger_count
(
dev
,
num_fingers
);
synaptics_report_buttons
(
psmouse
,
sgm
);
input_sync
(
dev
);
}
/*
* called for each full received packet from the touchpad
*/
...
...
@@ -1215,6 +1254,11 @@ static void synaptics_process_packet(struct psmouse *psmouse)
finger_width
=
0
;
}
if
(
cr48_profile_sensor
)
{
synaptics_profile_sensor_process
(
psmouse
,
&
hw
,
num_fingers
);
return
;
}
if
(
SYN_CAP_ADV_GESTURE
(
priv
->
ext_cap_0c
))
synaptics_report_semi_mt_data
(
dev
,
&
hw
,
&
priv
->
agm
,
num_fingers
);
...
...
@@ -1360,6 +1404,9 @@ static void set_input_params(struct psmouse *psmouse,
set_abs_position_params
(
dev
,
priv
,
ABS_X
,
ABS_Y
);
input_set_abs_params
(
dev
,
ABS_PRESSURE
,
0
,
255
,
0
,
0
);
if
(
cr48_profile_sensor
)
input_set_abs_params
(
dev
,
ABS_MT_PRESSURE
,
0
,
255
,
0
,
0
);
if
(
SYN_CAP_IMAGE_SENSOR
(
priv
->
ext_cap_0c
))
{
set_abs_position_params
(
dev
,
priv
,
ABS_MT_POSITION_X
,
ABS_MT_POSITION_Y
);
...
...
@@ -1371,11 +1418,16 @@ static void set_input_params(struct psmouse *psmouse,
__set_bit
(
BTN_TOOL_QUADTAP
,
dev
->
keybit
);
__set_bit
(
BTN_TOOL_QUINTTAP
,
dev
->
keybit
);
}
else
if
(
SYN_CAP_ADV_GESTURE
(
priv
->
ext_cap_0c
))
{
/* Non-image sensors with AGM use semi-mt */
__set_bit
(
INPUT_PROP_SEMI_MT
,
dev
->
propbit
);
input_mt_init_slots
(
dev
,
2
,
0
);
set_abs_position_params
(
dev
,
priv
,
ABS_MT_POSITION_X
,
ABS_MT_POSITION_Y
);
/*
* Profile sensor in CR-48 tracks contacts reasonably well,
* other non-image sensors with AGM use semi-mt.
*/
input_mt_init_slots
(
dev
,
2
,
INPUT_MT_POINTER
|
(
cr48_profile_sensor
?
INPUT_MT_TRACK
:
INPUT_MT_SEMI_MT
));
}
if
(
SYN_CAP_PALMDETECT
(
priv
->
capabilities
))
...
...
@@ -1577,10 +1629,24 @@ static const struct dmi_system_id olpc_dmi_table[] __initconst = {
{
}
};
static
const
struct
dmi_system_id
__initconst
cr48_dmi_table
[]
=
{
#if defined(CONFIG_DMI) && defined(CONFIG_X86)
{
/* Cr-48 Chromebook (Codename Mario) */
.
matches
=
{
DMI_MATCH
(
DMI_SYS_VENDOR
,
"IEC"
),
DMI_MATCH
(
DMI_PRODUCT_NAME
,
"Mario"
),
},
},
#endif
{
}
};
void
__init
synaptics_module_init
(
void
)
{
impaired_toshiba_kbc
=
dmi_check_system
(
toshiba_dmi_table
);
broken_olpc_ec
=
dmi_check_system
(
olpc_dmi_table
);
cr48_profile_sensor
=
dmi_check_system
(
cr48_dmi_table
);
}
static
int
__synaptics_init
(
struct
psmouse
*
psmouse
,
bool
absolute_mode
)
...
...
drivers/input/touchscreen/atmel_mxt_ts.c
View file @
91167e19
...
...
@@ -359,7 +359,6 @@ static int mxt_bootloader_read(struct mxt_data *data,
msg
.
buf
=
val
;
ret
=
i2c_transfer
(
data
->
client
->
adapter
,
&
msg
,
1
);
if
(
ret
==
1
)
{
ret
=
0
;
}
else
{
...
...
@@ -414,6 +413,7 @@ static int mxt_lookup_bootloader_address(struct mxt_data *data, bool retry)
case
0x5b
:
bootloader
=
appmode
-
0x26
;
break
;
default:
dev_err
(
&
data
->
client
->
dev
,
"Appmode i2c address 0x%02x not found
\n
"
,
...
...
@@ -425,20 +425,20 @@ static int mxt_lookup_bootloader_address(struct mxt_data *data, bool retry)
return
0
;
}
static
int
mxt_probe_bootloader
(
struct
mxt_data
*
data
,
bool
retry
)
static
int
mxt_probe_bootloader
(
struct
mxt_data
*
data
,
bool
alt_address
)
{
struct
device
*
dev
=
&
data
->
client
->
dev
;
int
ret
;
int
error
;
u8
val
;
bool
crc_failure
;
ret
=
mxt_lookup_bootloader_address
(
data
,
retry
);
if
(
ret
)
return
ret
;
error
=
mxt_lookup_bootloader_address
(
data
,
alt_address
);
if
(
error
)
return
error
;
ret
=
mxt_bootloader_read
(
data
,
&
val
,
1
);
if
(
ret
)
return
ret
;
error
=
mxt_bootloader_read
(
data
,
&
val
,
1
);
if
(
error
)
return
error
;
/* Check app crc fail mode */
crc_failure
=
(
val
&
~
MXT_BOOT_STATUS_MASK
)
==
MXT_APP_CRC_FAIL
;
...
...
@@ -1064,6 +1064,137 @@ static u32 mxt_calculate_crc(u8 *base, off_t start_off, off_t end_off)
return
crc
;
}
static
int
mxt_prepare_cfg_mem
(
struct
mxt_data
*
data
,
const
struct
firmware
*
cfg
,
unsigned
int
data_pos
,
unsigned
int
cfg_start_ofs
,
u8
*
config_mem
,
size_t
config_mem_size
)
{
struct
device
*
dev
=
&
data
->
client
->
dev
;
struct
mxt_object
*
object
;
unsigned
int
type
,
instance
,
size
,
byte_offset
;
int
offset
;
int
ret
;
int
i
;
u16
reg
;
u8
val
;
while
(
data_pos
<
cfg
->
size
)
{
/* Read type, instance, length */
ret
=
sscanf
(
cfg
->
data
+
data_pos
,
"%x %x %x%n"
,
&
type
,
&
instance
,
&
size
,
&
offset
);
if
(
ret
==
0
)
{
/* EOF */
break
;
}
else
if
(
ret
!=
3
)
{
dev_err
(
dev
,
"Bad format: failed to parse object
\n
"
);
return
-
EINVAL
;
}
data_pos
+=
offset
;
object
=
mxt_get_object
(
data
,
type
);
if
(
!
object
)
{
/* Skip object */
for
(
i
=
0
;
i
<
size
;
i
++
)
{
ret
=
sscanf
(
cfg
->
data
+
data_pos
,
"%hhx%n"
,
&
val
,
&
offset
);
if
(
ret
!=
1
)
{
dev_err
(
dev
,
"Bad format in T%d at %d
\n
"
,
type
,
i
);
return
-
EINVAL
;
}
data_pos
+=
offset
;
}
continue
;
}
if
(
size
>
mxt_obj_size
(
object
))
{
/*
* Either we are in fallback mode due to wrong
* config or config from a later fw version,
* or the file is corrupt or hand-edited.
*/
dev_warn
(
dev
,
"Discarding %zu byte(s) in T%u
\n
"
,
size
-
mxt_obj_size
(
object
),
type
);
}
else
if
(
mxt_obj_size
(
object
)
>
size
)
{
/*
* If firmware is upgraded, new bytes may be added to
* end of objects. It is generally forward compatible
* to zero these bytes - previous behaviour will be
* retained. However this does invalidate the CRC and
* will force fallback mode until the configuration is
* updated. We warn here but do nothing else - the
* malloc has zeroed the entire configuration.
*/
dev_warn
(
dev
,
"Zeroing %zu byte(s) in T%d
\n
"
,
mxt_obj_size
(
object
)
-
size
,
type
);
}
if
(
instance
>=
mxt_obj_instances
(
object
))
{
dev_err
(
dev
,
"Object instances exceeded!
\n
"
);
return
-
EINVAL
;
}
reg
=
object
->
start_address
+
mxt_obj_size
(
object
)
*
instance
;
for
(
i
=
0
;
i
<
size
;
i
++
)
{
ret
=
sscanf
(
cfg
->
data
+
data_pos
,
"%hhx%n"
,
&
val
,
&
offset
);
if
(
ret
!=
1
)
{
dev_err
(
dev
,
"Bad format in T%d at %d
\n
"
,
type
,
i
);
return
-
EINVAL
;
}
data_pos
+=
offset
;
if
(
i
>
mxt_obj_size
(
object
))
continue
;
byte_offset
=
reg
+
i
-
cfg_start_ofs
;
if
(
byte_offset
>=
0
&&
byte_offset
<
config_mem_size
)
{
*
(
config_mem
+
byte_offset
)
=
val
;
}
else
{
dev_err
(
dev
,
"Bad object: reg:%d, T%d, ofs=%d
\n
"
,
reg
,
object
->
type
,
byte_offset
);
return
-
EINVAL
;
}
}
}
return
0
;
}
static
int
mxt_upload_cfg_mem
(
struct
mxt_data
*
data
,
unsigned
int
cfg_start
,
u8
*
config_mem
,
size_t
config_mem_size
)
{
unsigned
int
byte_offset
=
0
;
int
error
;
/* Write configuration as blocks */
while
(
byte_offset
<
config_mem_size
)
{
unsigned
int
size
=
config_mem_size
-
byte_offset
;
if
(
size
>
MXT_MAX_BLOCK_WRITE
)
size
=
MXT_MAX_BLOCK_WRITE
;
error
=
__mxt_write_reg
(
data
->
client
,
cfg_start
+
byte_offset
,
size
,
config_mem
+
byte_offset
);
if
(
error
)
{
dev_err
(
&
data
->
client
->
dev
,
"Config write error, ret=%d
\n
"
,
error
);
return
error
;
}
byte_offset
+=
size
;
}
return
0
;
}
/*
* mxt_update_cfg - download configuration to chip
*
...
...
@@ -1087,26 +1218,20 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *cfg)
{
struct
device
*
dev
=
&
data
->
client
->
dev
;
struct
mxt_info
cfg_info
;
struct
mxt_object
*
object
;
int
ret
;
int
offset
;
int
data_pos
;
int
byte_offset
;
int
i
;
int
cfg_start_ofs
;
u32
info_crc
,
config_crc
,
calculated_crc
;
u8
*
config_mem
;
size_t
config_mem_size
;
unsigned
int
type
,
instance
,
size
;
u8
val
;
u16
reg
;
mxt_update_crc
(
data
,
MXT_COMMAND_REPORTALL
,
1
);
if
(
strncmp
(
cfg
->
data
,
MXT_CFG_MAGIC
,
strlen
(
MXT_CFG_MAGIC
)))
{
dev_err
(
dev
,
"Unrecognised config file
\n
"
);
ret
=
-
EINVAL
;
goto
release
;
return
-
EINVAL
;
}
data_pos
=
strlen
(
MXT_CFG_MAGIC
);
...
...
@@ -1118,8 +1243,7 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *cfg)
&
offset
);
if
(
ret
!=
1
)
{
dev_err
(
dev
,
"Bad format
\n
"
);
ret
=
-
EINVAL
;
goto
release
;
return
-
EINVAL
;
}
data_pos
+=
offset
;
...
...
@@ -1127,30 +1251,26 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *cfg)
if
(
cfg_info
.
family_id
!=
data
->
info
.
family_id
)
{
dev_err
(
dev
,
"Family ID mismatch!
\n
"
);
ret
=
-
EINVAL
;
goto
release
;
return
-
EINVAL
;
}
if
(
cfg_info
.
variant_id
!=
data
->
info
.
variant_id
)
{
dev_err
(
dev
,
"Variant ID mismatch!
\n
"
);
ret
=
-
EINVAL
;
goto
release
;
return
-
EINVAL
;
}
/* Read CRCs */
ret
=
sscanf
(
cfg
->
data
+
data_pos
,
"%x%n"
,
&
info_crc
,
&
offset
);
if
(
ret
!=
1
)
{
dev_err
(
dev
,
"Bad format: failed to parse Info CRC
\n
"
);
ret
=
-
EINVAL
;
goto
release
;
return
-
EINVAL
;
}
data_pos
+=
offset
;
ret
=
sscanf
(
cfg
->
data
+
data_pos
,
"%x%n"
,
&
config_crc
,
&
offset
);
if
(
ret
!=
1
)
{
dev_err
(
dev
,
"Bad format: failed to parse Config CRC
\n
"
);
ret
=
-
EINVAL
;
goto
release
;
return
-
EINVAL
;
}
data_pos
+=
offset
;
...
...
@@ -1166,8 +1286,7 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *cfg)
}
else
if
(
config_crc
==
data
->
config_crc
)
{
dev_dbg
(
dev
,
"Config CRC 0x%06X: OK
\n
"
,
data
->
config_crc
);
ret
=
0
;
goto
release
;
return
0
;
}
else
{
dev_info
(
dev
,
"Config CRC 0x%06X: does not match file 0x%06X
\n
"
,
data
->
config_crc
,
config_crc
);
...
...
@@ -1186,93 +1305,13 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *cfg)
config_mem
=
kzalloc
(
config_mem_size
,
GFP_KERNEL
);
if
(
!
config_mem
)
{
dev_err
(
dev
,
"Failed to allocate memory
\n
"
);
ret
=
-
ENOMEM
;
goto
release
;
return
-
ENOMEM
;
}
while
(
data_pos
<
cfg
->
size
)
{
/* Read type, instance, length */
ret
=
sscanf
(
cfg
->
data
+
data_pos
,
"%x %x %x%n"
,
&
type
,
&
instance
,
&
size
,
&
offset
);
if
(
ret
==
0
)
{
/* EOF */
break
;
}
else
if
(
ret
!=
3
)
{
dev_err
(
dev
,
"Bad format: failed to parse object
\n
"
);
ret
=
-
EINVAL
;
goto
release_mem
;
}
data_pos
+=
offset
;
object
=
mxt_get_object
(
data
,
type
);
if
(
!
object
)
{
/* Skip object */
for
(
i
=
0
;
i
<
size
;
i
++
)
{
ret
=
sscanf
(
cfg
->
data
+
data_pos
,
"%hhx%n"
,
&
val
,
&
offset
);
data_pos
+=
offset
;
}
continue
;
}
if
(
size
>
mxt_obj_size
(
object
))
{
/*
* Either we are in fallback mode due to wrong
* config or config from a later fw version,
* or the file is corrupt or hand-edited.
*/
dev_warn
(
dev
,
"Discarding %zu byte(s) in T%u
\n
"
,
size
-
mxt_obj_size
(
object
),
type
);
}
else
if
(
mxt_obj_size
(
object
)
>
size
)
{
/*
* If firmware is upgraded, new bytes may be added to
* end of objects. It is generally forward compatible
* to zero these bytes - previous behaviour will be
* retained. However this does invalidate the CRC and
* will force fallback mode until the configuration is
* updated. We warn here but do nothing else - the
* malloc has zeroed the entire configuration.
*/
dev_warn
(
dev
,
"Zeroing %zu byte(s) in T%d
\n
"
,
mxt_obj_size
(
object
)
-
size
,
type
);
}
if
(
instance
>=
mxt_obj_instances
(
object
))
{
dev_err
(
dev
,
"Object instances exceeded!
\n
"
);
ret
=
-
EINVAL
;
goto
release_mem
;
}
reg
=
object
->
start_address
+
mxt_obj_size
(
object
)
*
instance
;
for
(
i
=
0
;
i
<
size
;
i
++
)
{
ret
=
sscanf
(
cfg
->
data
+
data_pos
,
"%hhx%n"
,
&
val
,
&
offset
);
if
(
ret
!=
1
)
{
dev_err
(
dev
,
"Bad format in T%d
\n
"
,
type
);
ret
=
-
EINVAL
;
goto
release_mem
;
}
data_pos
+=
offset
;
if
(
i
>
mxt_obj_size
(
object
))
continue
;
byte_offset
=
reg
+
i
-
cfg_start_ofs
;
if
((
byte_offset
>=
0
)
&&
(
byte_offset
<=
config_mem_size
))
{
*
(
config_mem
+
byte_offset
)
=
val
;
}
else
{
dev_err
(
dev
,
"Bad object: reg:%d, T%d, ofs=%d
\n
"
,
reg
,
object
->
type
,
byte_offset
);
ret
=
-
EINVAL
;
goto
release_mem
;
}
}
}
ret
=
mxt_prepare_cfg_mem
(
data
,
cfg
,
data_pos
,
cfg_start_ofs
,
config_mem
,
config_mem_size
);
if
(
ret
)
goto
release_mem
;
/* Calculate crc of the received configs (not the raw config file) */
if
(
data
->
T7_address
<
cfg_start_ofs
)
{
...
...
@@ -1286,28 +1325,14 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *cfg)
data
->
T7_address
-
cfg_start_ofs
,
config_mem_size
);
if
(
config_crc
>
0
&&
(
config_crc
!=
calculated_crc
)
)
if
(
config_crc
>
0
&&
config_crc
!=
calculated_crc
)
dev_warn
(
dev
,
"Config CRC error, calculated=%06X, file=%06X
\n
"
,
calculated_crc
,
config_crc
);
/* Write configuration as blocks */
byte_offset
=
0
;
while
(
byte_offset
<
config_mem_size
)
{
size
=
config_mem_size
-
byte_offset
;
if
(
size
>
MXT_MAX_BLOCK_WRITE
)
size
=
MXT_MAX_BLOCK_WRITE
;
ret
=
__mxt_write_reg
(
data
->
client
,
cfg_start_ofs
+
byte_offset
,
size
,
config_mem
+
byte_offset
);
if
(
ret
!=
0
)
{
dev_err
(
dev
,
"Config write error, ret=%d
\n
"
,
ret
);
goto
release_mem
;
}
byte_offset
+=
size
;
}
ret
=
mxt_upload_cfg_mem
(
data
,
cfg_start_ofs
,
config_mem
,
config_mem_size
);
if
(
ret
)
goto
release_mem
;
mxt_update_crc
(
data
,
MXT_COMMAND_BACKUPNV
,
MXT_BACKUP_VALUE
);
...
...
@@ -1319,8 +1344,6 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *cfg)
release_mem:
kfree
(
config_mem
);
release:
release_firmware
(
cfg
);
return
ret
;
}
...
...
@@ -1422,10 +1445,12 @@ static int mxt_get_object_table(struct mxt_data *data)
switch
(
object
->
type
)
{
case
MXT_GEN_MESSAGE_T5
:
if
(
data
->
info
.
family_id
==
0x80
)
{
if
(
data
->
info
.
family_id
==
0x80
&&
data
->
info
.
version
<
0x20
)
{
/*
* On mXT224 read and discard unused CRC byte
* otherwise DMA reads are misaligned
* On mXT224 firmware versions prior to V2.0
* read and discard unused CRC byte otherwise
* DMA reads are misaligned.
*/
data
->
T5_msg_size
=
mxt_obj_size
(
object
);
}
else
{
...
...
@@ -1433,6 +1458,7 @@ static int mxt_get_object_table(struct mxt_data *data)
data
->
T5_msg_size
=
mxt_obj_size
(
object
)
-
1
;
}
data
->
T5_address
=
object
->
start_address
;
break
;
case
MXT_GEN_COMMAND_T6
:
data
->
T6_reportid
=
min_id
;
data
->
T6_address
=
object
->
start_address
;
...
...
@@ -1638,46 +1664,45 @@ static int mxt_configure_objects(struct mxt_data *data,
static
void
mxt_config_cb
(
const
struct
firmware
*
cfg
,
void
*
ctx
)
{
mxt_configure_objects
(
ctx
,
cfg
);
release_firmware
(
cfg
);
}
static
int
mxt_initialize
(
struct
mxt_data
*
data
)
{
struct
i2c_client
*
client
=
data
->
client
;
int
recovery_attempts
=
0
;
int
error
;
bool
alt_bootloader_addr
=
false
;
bool
retry
=
false
;
retry_info:
error
=
mxt_get_info
(
data
);
if
(
error
)
{
retry_bootloader:
error
=
mxt_probe_bootloader
(
data
,
alt_bootloader_addr
);
while
(
1
)
{
error
=
mxt_get_info
(
data
);
if
(
!
error
)
break
;
/* Check bootloader state */
error
=
mxt_probe_bootloader
(
data
,
false
);
if
(
error
)
{
if
(
alt_bootloader_addr
)
{
dev_info
(
&
client
->
dev
,
"Trying alternate bootloader address
\n
"
);
error
=
mxt_probe_bootloader
(
data
,
true
);
if
(
error
)
{
/* Chip is not in appmode or bootloader mode */
return
error
;
}
}
dev_info
(
&
client
->
dev
,
"Trying alternate bootloader address
\n
"
);
alt_bootloader_addr
=
true
;
goto
retry_bootloader
;
}
else
{
if
(
retry
)
{
dev_err
(
&
client
->
dev
,
"Could not recover from bootloader mode
\n
"
);
/*
* We can reflash from this state, so do not
* abort init
*/
data
->
in_bootloader
=
true
;
return
0
;
}
/* Attempt to exit bootloader into app mode */
mxt_send_bootloader_cmd
(
data
,
false
);
msleep
(
MXT_FW_RESET_TIME
);
retry
=
true
;
goto
retry_info
;
/* OK, we are in bootloader, see if we can recover */
if
(
++
recovery_attempts
>
1
)
{
dev_err
(
&
client
->
dev
,
"Could not recover from bootloader mode
\n
"
);
/*
* We can reflash from this state, so do not
* abort initialization.
*/
data
->
in_bootloader
=
true
;
return
0
;
}
/* Attempt to exit bootloader into app mode */
mxt_send_bootloader_cmd
(
data
,
false
);
msleep
(
MXT_FW_RESET_TIME
);
}
/* Get object table information */
...
...
@@ -1687,13 +1712,18 @@ static int mxt_initialize(struct mxt_data *data)
return
error
;
}
mxt_acquire_irq
(
data
);
error
=
mxt_acquire_irq
(
data
);
if
(
error
)
goto
err_free_object_table
;
request_firmware_nowait
(
THIS_MODULE
,
true
,
MXT_CFG_NAME
,
&
data
->
client
->
dev
,
GFP_KERNEL
,
data
,
mxt_config_cb
);
error
=
request_firmware_nowait
(
THIS_MODULE
,
true
,
MXT_CFG_NAME
,
&
client
->
dev
,
GFP_KERNEL
,
data
,
mxt_config_cb
);
if
(
error
)
{
dev_err
(
&
client
->
dev
,
"Failed to invoke firmware loader: %d
\n
"
,
error
);
goto
err_free_object_table
;
}
return
0
;
...
...
drivers/input/touchscreen/edt-ft5x06.c
View file @
91167e19
...
...
@@ -262,7 +262,6 @@ static int edt_ft5x06_register_write(struct edt_ft5x06_ts_data *tsdata,
case
M06
:
wrbuf
[
0
]
=
tsdata
->
factory_mode
?
0xf3
:
0xfc
;
wrbuf
[
1
]
=
tsdata
->
factory_mode
?
addr
&
0x7f
:
addr
&
0x3f
;
wrbuf
[
1
]
=
tsdata
->
factory_mode
?
addr
&
0x7f
:
addr
&
0x3f
;
wrbuf
[
2
]
=
value
;
wrbuf
[
3
]
=
wrbuf
[
0
]
^
wrbuf
[
1
]
^
wrbuf
[
2
];
return
edt_ft5x06_ts_readwrite
(
tsdata
->
client
,
4
,
...
...
include/linux/input/mt.h
View file @
91167e19
...
...
@@ -105,6 +105,7 @@ void input_mt_report_slot_state(struct input_dev *dev,
void
input_mt_report_finger_count
(
struct
input_dev
*
dev
,
int
count
);
void
input_mt_report_pointer_emulation
(
struct
input_dev
*
dev
,
bool
use_count
);
void
input_mt_drop_unused
(
struct
input_dev
*
dev
);
void
input_mt_sync_frame
(
struct
input_dev
*
dev
);
...
...
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