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
b26a95d4
Commit
b26a95d4
authored
Jan 21, 2016
by
Dmitry Torokhov
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'next' into for-linus
Prepare second round of input updates for 4.5 merge window.
parents
009f7738
809d9516
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
456 additions
and
210 deletions
+456
-210
Documentation/devicetree/bindings/input/gpio-keys.txt
Documentation/devicetree/bindings/input/gpio-keys.txt
+1
-0
drivers/input/joystick/xpad.c
drivers/input/joystick/xpad.c
+425
-166
drivers/input/keyboard/gpio_keys.c
drivers/input/keyboard/gpio_keys.c
+4
-2
drivers/input/touchscreen/atmel_mxt_ts.c
drivers/input/touchscreen/atmel_mxt_ts.c
+26
-42
No files found.
Documentation/devicetree/bindings/input/gpio-keys.txt
View file @
b26a95d4
...
@@ -6,6 +6,7 @@ Required properties:
...
@@ -6,6 +6,7 @@ Required properties:
Optional properties:
Optional properties:
- autorepeat: Boolean, Enable auto repeat feature of Linux input
- autorepeat: Boolean, Enable auto repeat feature of Linux input
subsystem.
subsystem.
- label: String, name of the input device.
Each button (key) is represented as a sub-node of "gpio-keys":
Each button (key) is represented as a sub-node of "gpio-keys":
Subnode properties:
Subnode properties:
...
...
drivers/input/joystick/xpad.c
View file @
b26a95d4
...
@@ -76,10 +76,13 @@
...
@@ -76,10 +76,13 @@
*/
*/
#include <linux/kernel.h>
#include <linux/kernel.h>
#include <linux/input.h>
#include <linux/rcupdate.h>
#include <linux/slab.h>
#include <linux/slab.h>
#include <linux/stat.h>
#include <linux/stat.h>
#include <linux/module.h>
#include <linux/module.h>
#include <linux/usb/input.h>
#include <linux/usb/input.h>
#include <linux/usb/quirks.h>
#define DRIVER_AUTHOR "Marko Friedemann <mfr@bmx-chemnitz.de>"
#define DRIVER_AUTHOR "Marko Friedemann <mfr@bmx-chemnitz.de>"
#define DRIVER_DESC "X-Box pad driver"
#define DRIVER_DESC "X-Box pad driver"
...
@@ -125,7 +128,7 @@ static const struct xpad_device {
...
@@ -125,7 +128,7 @@ static const struct xpad_device {
{
0x045e
,
0x0289
,
"Microsoft X-Box pad v2 (US)"
,
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
,
0x028e
,
"Microsoft X-Box 360 pad"
,
0
,
XTYPE_XBOX360
},
{
0x045e
,
0x02d1
,
"Microsoft X-Box One pad"
,
0
,
XTYPE_XBOXONE
},
{
0x045e
,
0x02d1
,
"Microsoft X-Box One pad"
,
0
,
XTYPE_XBOXONE
},
{
0x045e
,
0x02dd
,
"Microsoft X-Box One pad (
Covert Forces
)"
,
0
,
XTYPE_XBOXONE
},
{
0x045e
,
0x02dd
,
"Microsoft X-Box One pad (
Firmware 2015
)"
,
0
,
XTYPE_XBOXONE
},
{
0x045e
,
0x0291
,
"Xbox 360 Wireless Receiver (XBOX)"
,
MAP_DPAD_TO_BUTTONS
,
XTYPE_XBOX360W
},
{
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
},
{
0x045e
,
0x0719
,
"Xbox 360 Wireless Receiver"
,
MAP_DPAD_TO_BUTTONS
,
XTYPE_XBOX360W
},
{
0x044f
,
0x0f07
,
"Thrustmaster, Inc. Controller"
,
0
,
XTYPE_XBOX
},
{
0x044f
,
0x0f07
,
"Thrustmaster, Inc. Controller"
,
0
,
XTYPE_XBOX
},
...
@@ -317,21 +320,42 @@ static struct usb_device_id xpad_table[] = {
...
@@ -317,21 +320,42 @@ static struct usb_device_id xpad_table[] = {
MODULE_DEVICE_TABLE
(
usb
,
xpad_table
);
MODULE_DEVICE_TABLE
(
usb
,
xpad_table
);
struct
xpad_output_packet
{
u8
data
[
XPAD_PKT_LEN
];
u8
len
;
bool
pending
;
};
#define XPAD_OUT_CMD_IDX 0
#define XPAD_OUT_FF_IDX 1
#define XPAD_OUT_LED_IDX (1 + IS_ENABLED(CONFIG_JOYSTICK_XPAD_FF))
#define XPAD_NUM_OUT_PACKETS (1 + \
IS_ENABLED(CONFIG_JOYSTICK_XPAD_FF) + \
IS_ENABLED(CONFIG_JOYSTICK_XPAD_LEDS))
struct
usb_xpad
{
struct
usb_xpad
{
struct
input_dev
*
dev
;
/* input device interface */
struct
input_dev
*
dev
;
/* input device interface */
struct
input_dev
__rcu
*
x360w_dev
;
struct
usb_device
*
udev
;
/* usb device */
struct
usb_device
*
udev
;
/* usb device */
struct
usb_interface
*
intf
;
/* usb interface */
struct
usb_interface
*
intf
;
/* usb interface */
int
pad_present
;
bool
pad_present
;
bool
input_created
;
struct
urb
*
irq_in
;
/* urb for interrupt in report */
struct
urb
*
irq_in
;
/* urb for interrupt in report */
unsigned
char
*
idata
;
/* input data */
unsigned
char
*
idata
;
/* input data */
dma_addr_t
idata_dma
;
dma_addr_t
idata_dma
;
struct
urb
*
irq_out
;
/* urb for interrupt out report */
struct
urb
*
irq_out
;
/* urb for interrupt out report */
struct
usb_anchor
irq_out_anchor
;
bool
irq_out_active
;
/* we must not use an active URB */
u8
odata_serial
;
/* serial number for xbox one protocol */
unsigned
char
*
odata
;
/* output data */
unsigned
char
*
odata
;
/* output data */
dma_addr_t
odata_dma
;
dma_addr_t
odata_dma
;
struct
mutex
odata_mutex
;
spinlock_t
odata_lock
;
struct
xpad_output_packet
out_packets
[
XPAD_NUM_OUT_PACKETS
];
int
last_out_packet
;
#if defined(CONFIG_JOYSTICK_XPAD_LEDS)
#if defined(CONFIG_JOYSTICK_XPAD_LEDS)
struct
xpad_led
*
led
;
struct
xpad_led
*
led
;
...
@@ -343,8 +367,12 @@ struct usb_xpad {
...
@@ -343,8 +367,12 @@ struct usb_xpad {
int
xtype
;
/* type of xbox device */
int
xtype
;
/* type of xbox device */
int
pad_nr
;
/* the order x360 pads were attached */
int
pad_nr
;
/* the order x360 pads were attached */
const
char
*
name
;
/* name of the device */
const
char
*
name
;
/* name of the device */
struct
work_struct
work
;
/* init/remove device from callback */
};
};
static
int
xpad_init_input
(
struct
usb_xpad
*
xpad
);
static
void
xpad_deinit_input
(
struct
usb_xpad
*
xpad
);
/*
/*
* xpad_process_packet
* xpad_process_packet
*
*
...
@@ -424,11 +452,9 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d
...
@@ -424,11 +452,9 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d
* http://www.free60.org/wiki/Gamepad
* http://www.free60.org/wiki/Gamepad
*/
*/
static
void
xpad360_process_packet
(
struct
usb_xpad
*
xpad
,
static
void
xpad360_process_packet
(
struct
usb_xpad
*
xpad
,
struct
input_dev
*
dev
,
u16
cmd
,
unsigned
char
*
data
)
u16
cmd
,
unsigned
char
*
data
)
{
{
struct
input_dev
*
dev
=
xpad
->
dev
;
/* digital pad */
/* digital pad */
if
(
xpad
->
mapping
&
MAP_DPAD_TO_BUTTONS
)
{
if
(
xpad
->
mapping
&
MAP_DPAD_TO_BUTTONS
)
{
/* dpad as buttons (left, right, up, down) */
/* dpad as buttons (left, right, up, down) */
...
@@ -495,7 +521,30 @@ static void xpad360_process_packet(struct usb_xpad *xpad,
...
@@ -495,7 +521,30 @@ static void xpad360_process_packet(struct usb_xpad *xpad,
input_sync
(
dev
);
input_sync
(
dev
);
}
}
static
void
xpad_identify_controller
(
struct
usb_xpad
*
xpad
);
static
void
xpad_presence_work
(
struct
work_struct
*
work
)
{
struct
usb_xpad
*
xpad
=
container_of
(
work
,
struct
usb_xpad
,
work
);
int
error
;
if
(
xpad
->
pad_present
)
{
error
=
xpad_init_input
(
xpad
);
if
(
error
)
{
/* complain only, not much else we can do here */
dev_err
(
&
xpad
->
dev
->
dev
,
"unable to init device: %d
\n
"
,
error
);
}
else
{
rcu_assign_pointer
(
xpad
->
x360w_dev
,
xpad
->
dev
);
}
}
else
{
RCU_INIT_POINTER
(
xpad
->
x360w_dev
,
NULL
);
synchronize_rcu
();
/*
* Now that we are sure xpad360w_process_packet is not
* using input device we can get rid of it.
*/
xpad_deinit_input
(
xpad
);
}
}
/*
/*
* xpad360w_process_packet
* xpad360w_process_packet
...
@@ -513,24 +562,28 @@ static void xpad_identify_controller(struct usb_xpad *xpad);
...
@@ -513,24 +562,28 @@ static void xpad_identify_controller(struct usb_xpad *xpad);
*/
*/
static
void
xpad360w_process_packet
(
struct
usb_xpad
*
xpad
,
u16
cmd
,
unsigned
char
*
data
)
static
void
xpad360w_process_packet
(
struct
usb_xpad
*
xpad
,
u16
cmd
,
unsigned
char
*
data
)
{
{
struct
input_dev
*
dev
;
bool
present
;
/* Presence change */
/* Presence change */
if
(
data
[
0
]
&
0x08
)
{
if
(
data
[
0
]
&
0x08
)
{
if
(
data
[
1
]
&
0x80
)
{
present
=
(
data
[
1
]
&
0x80
)
!=
0
;
xpad
->
pad_present
=
1
;
/*
if
(
xpad
->
pad_present
!=
present
)
{
* Light up the segment corresponding to
xpad
->
pad_present
=
present
;
* controller number.
schedule_work
(
&
xpad
->
work
);
*/
}
xpad_identify_controller
(
xpad
);
}
else
xpad
->
pad_present
=
0
;
}
}
/* Valid pad data */
/* Valid pad data */
if
(
!
(
data
[
1
]
&
0x1
)
)
if
(
data
[
1
]
!=
0x1
)
return
;
return
;
xpad360_process_packet
(
xpad
,
cmd
,
&
data
[
4
]);
rcu_read_lock
();
dev
=
rcu_dereference
(
xpad
->
x360w_dev
);
if
(
dev
)
xpad360_process_packet
(
xpad
,
dev
,
cmd
,
&
data
[
4
]);
rcu_read_unlock
();
}
}
/*
/*
...
@@ -659,7 +712,7 @@ static void xpad_irq_in(struct urb *urb)
...
@@ -659,7 +712,7 @@ static void xpad_irq_in(struct urb *urb)
switch
(
xpad
->
xtype
)
{
switch
(
xpad
->
xtype
)
{
case
XTYPE_XBOX360
:
case
XTYPE_XBOX360
:
xpad360_process_packet
(
xpad
,
0
,
xpad
->
idata
);
xpad360_process_packet
(
xpad
,
xpad
->
dev
,
0
,
xpad
->
idata
);
break
;
break
;
case
XTYPE_XBOX360W
:
case
XTYPE_XBOX360W
:
xpad360w_process_packet
(
xpad
,
0
,
xpad
->
idata
);
xpad360w_process_packet
(
xpad
,
0
,
xpad
->
idata
);
...
@@ -678,18 +731,73 @@ static void xpad_irq_in(struct urb *urb)
...
@@ -678,18 +731,73 @@ static void xpad_irq_in(struct urb *urb)
__func__
,
retval
);
__func__
,
retval
);
}
}
/* Callers must hold xpad->odata_lock spinlock */
static
bool
xpad_prepare_next_out_packet
(
struct
usb_xpad
*
xpad
)
{
struct
xpad_output_packet
*
pkt
,
*
packet
=
NULL
;
int
i
;
for
(
i
=
0
;
i
<
XPAD_NUM_OUT_PACKETS
;
i
++
)
{
if
(
++
xpad
->
last_out_packet
>=
XPAD_NUM_OUT_PACKETS
)
xpad
->
last_out_packet
=
0
;
pkt
=
&
xpad
->
out_packets
[
xpad
->
last_out_packet
];
if
(
pkt
->
pending
)
{
dev_dbg
(
&
xpad
->
intf
->
dev
,
"%s - found pending output packet %d
\n
"
,
__func__
,
xpad
->
last_out_packet
);
packet
=
pkt
;
break
;
}
}
if
(
packet
)
{
memcpy
(
xpad
->
odata
,
packet
->
data
,
packet
->
len
);
xpad
->
irq_out
->
transfer_buffer_length
=
packet
->
len
;
return
true
;
}
return
false
;
}
/* Callers must hold xpad->odata_lock spinlock */
static
int
xpad_try_sending_next_out_packet
(
struct
usb_xpad
*
xpad
)
{
int
error
;
if
(
!
xpad
->
irq_out_active
&&
xpad_prepare_next_out_packet
(
xpad
))
{
usb_anchor_urb
(
xpad
->
irq_out
,
&
xpad
->
irq_out_anchor
);
error
=
usb_submit_urb
(
xpad
->
irq_out
,
GFP_ATOMIC
);
if
(
error
)
{
dev_err
(
&
xpad
->
intf
->
dev
,
"%s - usb_submit_urb failed with result %d
\n
"
,
__func__
,
error
);
usb_unanchor_urb
(
xpad
->
irq_out
);
return
-
EIO
;
}
xpad
->
irq_out_active
=
true
;
}
return
0
;
}
static
void
xpad_irq_out
(
struct
urb
*
urb
)
static
void
xpad_irq_out
(
struct
urb
*
urb
)
{
{
struct
usb_xpad
*
xpad
=
urb
->
context
;
struct
usb_xpad
*
xpad
=
urb
->
context
;
struct
device
*
dev
=
&
xpad
->
intf
->
dev
;
struct
device
*
dev
=
&
xpad
->
intf
->
dev
;
int
retval
,
status
;
int
status
=
urb
->
status
;
int
error
;
unsigned
long
flags
;
s
tatus
=
urb
->
status
;
s
pin_lock_irqsave
(
&
xpad
->
odata_lock
,
flags
)
;
switch
(
status
)
{
switch
(
status
)
{
case
0
:
case
0
:
/* success */
/* success */
return
;
xpad
->
out_packets
[
xpad
->
last_out_packet
].
pending
=
false
;
xpad
->
irq_out_active
=
xpad_prepare_next_out_packet
(
xpad
);
break
;
case
-
ECONNRESET
:
case
-
ECONNRESET
:
case
-
ENOENT
:
case
-
ENOENT
:
...
@@ -697,19 +805,28 @@ static void xpad_irq_out(struct urb *urb)
...
@@ -697,19 +805,28 @@ static void xpad_irq_out(struct urb *urb)
/* this urb is terminated, clean up */
/* this urb is terminated, clean up */
dev_dbg
(
dev
,
"%s - urb shutting down with status: %d
\n
"
,
dev_dbg
(
dev
,
"%s - urb shutting down with status: %d
\n
"
,
__func__
,
status
);
__func__
,
status
);
return
;
xpad
->
irq_out_active
=
false
;
break
;
default:
default:
dev_dbg
(
dev
,
"%s - nonzero urb status received: %d
\n
"
,
dev_dbg
(
dev
,
"%s - nonzero urb status received: %d
\n
"
,
__func__
,
status
);
__func__
,
status
);
goto
exit
;
break
;
}
}
exit:
if
(
xpad
->
irq_out_active
)
{
retval
=
usb_submit_urb
(
urb
,
GFP_ATOMIC
);
usb_anchor_urb
(
urb
,
&
xpad
->
irq_out_anchor
);
if
(
retval
)
error
=
usb_submit_urb
(
urb
,
GFP_ATOMIC
);
dev_err
(
dev
,
"%s - usb_submit_urb failed with result %d
\n
"
,
if
(
error
)
{
__func__
,
retval
);
dev_err
(
dev
,
"%s - usb_submit_urb failed with result %d
\n
"
,
__func__
,
error
);
usb_unanchor_urb
(
urb
);
xpad
->
irq_out_active
=
false
;
}
}
spin_unlock_irqrestore
(
&
xpad
->
odata_lock
,
flags
);
}
}
static
int
xpad_init_output
(
struct
usb_interface
*
intf
,
struct
usb_xpad
*
xpad
)
static
int
xpad_init_output
(
struct
usb_interface
*
intf
,
struct
usb_xpad
*
xpad
)
...
@@ -721,6 +838,8 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)
...
@@ -721,6 +838,8 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)
if
(
xpad
->
xtype
==
XTYPE_UNKNOWN
)
if
(
xpad
->
xtype
==
XTYPE_UNKNOWN
)
return
0
;
return
0
;
init_usb_anchor
(
&
xpad
->
irq_out_anchor
);
xpad
->
odata
=
usb_alloc_coherent
(
xpad
->
udev
,
XPAD_PKT_LEN
,
xpad
->
odata
=
usb_alloc_coherent
(
xpad
->
udev
,
XPAD_PKT_LEN
,
GFP_KERNEL
,
&
xpad
->
odata_dma
);
GFP_KERNEL
,
&
xpad
->
odata_dma
);
if
(
!
xpad
->
odata
)
{
if
(
!
xpad
->
odata
)
{
...
@@ -728,7 +847,7 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)
...
@@ -728,7 +847,7 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)
goto
fail1
;
goto
fail1
;
}
}
mutex_init
(
&
xpad
->
odata_mutex
);
spin_lock_init
(
&
xpad
->
odata_lock
);
xpad
->
irq_out
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
xpad
->
irq_out
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
if
(
!
xpad
->
irq_out
)
{
if
(
!
xpad
->
irq_out
)
{
...
@@ -755,8 +874,14 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)
...
@@ -755,8 +874,14 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)
static
void
xpad_stop_output
(
struct
usb_xpad
*
xpad
)
static
void
xpad_stop_output
(
struct
usb_xpad
*
xpad
)
{
{
if
(
xpad
->
xtype
!=
XTYPE_UNKNOWN
)
if
(
xpad
->
xtype
!=
XTYPE_UNKNOWN
)
{
usb_kill_urb
(
xpad
->
irq_out
);
if
(
!
usb_wait_anchor_empty_timeout
(
&
xpad
->
irq_out_anchor
,
5000
))
{
dev_warn
(
&
xpad
->
intf
->
dev
,
"timed out waiting for output URB to complete, killing
\n
"
);
usb_kill_anchored_urbs
(
&
xpad
->
irq_out_anchor
);
}
}
}
}
static
void
xpad_deinit_output
(
struct
usb_xpad
*
xpad
)
static
void
xpad_deinit_output
(
struct
usb_xpad
*
xpad
)
...
@@ -770,27 +895,60 @@ static void xpad_deinit_output(struct usb_xpad *xpad)
...
@@ -770,27 +895,60 @@ static void xpad_deinit_output(struct usb_xpad *xpad)
static
int
xpad_inquiry_pad_presence
(
struct
usb_xpad
*
xpad
)
static
int
xpad_inquiry_pad_presence
(
struct
usb_xpad
*
xpad
)
{
{
struct
xpad_output_packet
*
packet
=
&
xpad
->
out_packets
[
XPAD_OUT_CMD_IDX
];
unsigned
long
flags
;
int
retval
;
int
retval
;
mutex_lock
(
&
xpad
->
odata_mutex
);
spin_lock_irqsave
(
&
xpad
->
odata_lock
,
flags
);
packet
->
data
[
0
]
=
0x08
;
packet
->
data
[
1
]
=
0x00
;
packet
->
data
[
2
]
=
0x0F
;
packet
->
data
[
3
]
=
0xC0
;
packet
->
data
[
4
]
=
0x00
;
packet
->
data
[
5
]
=
0x00
;
packet
->
data
[
6
]
=
0x00
;
packet
->
data
[
7
]
=
0x00
;
packet
->
data
[
8
]
=
0x00
;
packet
->
data
[
9
]
=
0x00
;
packet
->
data
[
10
]
=
0x00
;
packet
->
data
[
11
]
=
0x00
;
packet
->
len
=
12
;
packet
->
pending
=
true
;
/* Reset the sequence so we send out presence first */
xpad
->
last_out_packet
=
-
1
;
retval
=
xpad_try_sending_next_out_packet
(
xpad
);
spin_unlock_irqrestore
(
&
xpad
->
odata_lock
,
flags
);
xpad
->
odata
[
0
]
=
0x08
;
return
retval
;
xpad
->
odata
[
1
]
=
0x00
;
}
xpad
->
odata
[
2
]
=
0x0F
;
xpad
->
odata
[
3
]
=
0xC0
;
static
int
xpad_start_xbox_one
(
struct
usb_xpad
*
xpad
)
xpad
->
odata
[
4
]
=
0x00
;
{
xpad
->
odata
[
5
]
=
0x00
;
struct
xpad_output_packet
*
packet
=
xpad
->
odata
[
6
]
=
0x00
;
&
xpad
->
out_packets
[
XPAD_OUT_CMD_IDX
];
xpad
->
odata
[
7
]
=
0x00
;
unsigned
long
flags
;
xpad
->
odata
[
8
]
=
0x00
;
int
retval
;
xpad
->
odata
[
9
]
=
0x00
;
xpad
->
odata
[
10
]
=
0x00
;
xpad
->
odata
[
11
]
=
0x00
;
xpad
->
irq_out
->
transfer_buffer_length
=
12
;
retval
=
usb_submit_urb
(
xpad
->
irq_out
,
GFP_KERNEL
);
spin_lock_irqsave
(
&
xpad
->
odata_lock
,
flags
);
mutex_unlock
(
&
xpad
->
odata_mutex
);
/* Xbox one controller needs to be initialized. */
packet
->
data
[
0
]
=
0x05
;
packet
->
data
[
1
]
=
0x20
;
packet
->
data
[
2
]
=
xpad
->
odata_serial
++
;
/* packet serial */
packet
->
data
[
3
]
=
0x01
;
/* rumble bit enable? */
packet
->
data
[
4
]
=
0x00
;
packet
->
len
=
5
;
packet
->
pending
=
true
;
/* Reset the sequence so we send out start packet first */
xpad
->
last_out_packet
=
-
1
;
retval
=
xpad_try_sending_next_out_packet
(
xpad
);
spin_unlock_irqrestore
(
&
xpad
->
odata_lock
,
flags
);
return
retval
;
return
retval
;
}
}
...
@@ -799,8 +957,11 @@ static int xpad_inquiry_pad_presence(struct usb_xpad *xpad)
...
@@ -799,8 +957,11 @@ static int xpad_inquiry_pad_presence(struct usb_xpad *xpad)
static
int
xpad_play_effect
(
struct
input_dev
*
dev
,
void
*
data
,
struct
ff_effect
*
effect
)
static
int
xpad_play_effect
(
struct
input_dev
*
dev
,
void
*
data
,
struct
ff_effect
*
effect
)
{
{
struct
usb_xpad
*
xpad
=
input_get_drvdata
(
dev
);
struct
usb_xpad
*
xpad
=
input_get_drvdata
(
dev
);
struct
xpad_output_packet
*
packet
=
&
xpad
->
out_packets
[
XPAD_OUT_FF_IDX
];
__u16
strong
;
__u16
strong
;
__u16
weak
;
__u16
weak
;
int
retval
;
unsigned
long
flags
;
if
(
effect
->
type
!=
FF_RUMBLE
)
if
(
effect
->
type
!=
FF_RUMBLE
)
return
0
;
return
0
;
...
@@ -808,69 +969,81 @@ static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect
...
@@ -808,69 +969,81 @@ static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect
strong
=
effect
->
u
.
rumble
.
strong_magnitude
;
strong
=
effect
->
u
.
rumble
.
strong_magnitude
;
weak
=
effect
->
u
.
rumble
.
weak_magnitude
;
weak
=
effect
->
u
.
rumble
.
weak_magnitude
;
spin_lock_irqsave
(
&
xpad
->
odata_lock
,
flags
);
switch
(
xpad
->
xtype
)
{
switch
(
xpad
->
xtype
)
{
case
XTYPE_XBOX
:
case
XTYPE_XBOX
:
xpad
->
odata
[
0
]
=
0x00
;
packet
->
data
[
0
]
=
0x00
;
xpad
->
odata
[
1
]
=
0x06
;
packet
->
data
[
1
]
=
0x06
;
xpad
->
odata
[
2
]
=
0x00
;
packet
->
data
[
2
]
=
0x00
;
xpad
->
odata
[
3
]
=
strong
/
256
;
/* left actuator */
packet
->
data
[
3
]
=
strong
/
256
;
/* left actuator */
xpad
->
odata
[
4
]
=
0x00
;
packet
->
data
[
4
]
=
0x00
;
xpad
->
odata
[
5
]
=
weak
/
256
;
/* right actuator */
packet
->
data
[
5
]
=
weak
/
256
;
/* right actuator */
xpad
->
irq_out
->
transfer_buffer_length
=
6
;
packet
->
len
=
6
;
packet
->
pending
=
true
;
break
;
break
;
case
XTYPE_XBOX360
:
case
XTYPE_XBOX360
:
xpad
->
odata
[
0
]
=
0x00
;
packet
->
data
[
0
]
=
0x00
;
xpad
->
odata
[
1
]
=
0x08
;
packet
->
data
[
1
]
=
0x08
;
xpad
->
odata
[
2
]
=
0x00
;
packet
->
data
[
2
]
=
0x00
;
xpad
->
odata
[
3
]
=
strong
/
256
;
/* left actuator? */
packet
->
data
[
3
]
=
strong
/
256
;
/* left actuator? */
xpad
->
odata
[
4
]
=
weak
/
256
;
/* right actuator? */
packet
->
data
[
4
]
=
weak
/
256
;
/* right actuator? */
xpad
->
odata
[
5
]
=
0x00
;
packet
->
data
[
5
]
=
0x00
;
xpad
->
odata
[
6
]
=
0x00
;
packet
->
data
[
6
]
=
0x00
;
xpad
->
odata
[
7
]
=
0x00
;
packet
->
data
[
7
]
=
0x00
;
xpad
->
irq_out
->
transfer_buffer_length
=
8
;
packet
->
len
=
8
;
packet
->
pending
=
true
;
break
;
break
;
case
XTYPE_XBOX360W
:
case
XTYPE_XBOX360W
:
xpad
->
odata
[
0
]
=
0x00
;
packet
->
data
[
0
]
=
0x00
;
xpad
->
odata
[
1
]
=
0x01
;
packet
->
data
[
1
]
=
0x01
;
xpad
->
odata
[
2
]
=
0x0F
;
packet
->
data
[
2
]
=
0x0F
;
xpad
->
odata
[
3
]
=
0xC0
;
packet
->
data
[
3
]
=
0xC0
;
xpad
->
odata
[
4
]
=
0x00
;
packet
->
data
[
4
]
=
0x00
;
xpad
->
odata
[
5
]
=
strong
/
256
;
packet
->
data
[
5
]
=
strong
/
256
;
xpad
->
odata
[
6
]
=
weak
/
256
;
packet
->
data
[
6
]
=
weak
/
256
;
xpad
->
odata
[
7
]
=
0x00
;
packet
->
data
[
7
]
=
0x00
;
xpad
->
odata
[
8
]
=
0x00
;
packet
->
data
[
8
]
=
0x00
;
xpad
->
odata
[
9
]
=
0x00
;
packet
->
data
[
9
]
=
0x00
;
xpad
->
odata
[
10
]
=
0x00
;
packet
->
data
[
10
]
=
0x00
;
xpad
->
odata
[
11
]
=
0x00
;
packet
->
data
[
11
]
=
0x00
;
xpad
->
irq_out
->
transfer_buffer_length
=
12
;
packet
->
len
=
12
;
packet
->
pending
=
true
;
break
;
break
;
case
XTYPE_XBOXONE
:
case
XTYPE_XBOXONE
:
xpad
->
odata
[
0
]
=
0x09
;
/* activate rumble */
packet
->
data
[
0
]
=
0x09
;
/* activate rumble */
xpad
->
odata
[
1
]
=
0x08
;
packet
->
data
[
1
]
=
0x08
;
xpad
->
odata
[
2
]
=
0x00
;
packet
->
data
[
2
]
=
xpad
->
odata_serial
++
;
xpad
->
odata
[
3
]
=
0x08
;
/* continuous effect */
packet
->
data
[
3
]
=
0x08
;
/* continuous effect */
xpad
->
odata
[
4
]
=
0x00
;
/* simple rumble mode */
packet
->
data
[
4
]
=
0x00
;
/* simple rumble mode */
xpad
->
odata
[
5
]
=
0x03
;
/* L and R actuator only */
packet
->
data
[
5
]
=
0x03
;
/* L and R actuator only */
xpad
->
odata
[
6
]
=
0x00
;
/* TODO: LT actuator */
packet
->
data
[
6
]
=
0x00
;
/* TODO: LT actuator */
xpad
->
odata
[
7
]
=
0x00
;
/* TODO: RT actuator */
packet
->
data
[
7
]
=
0x00
;
/* TODO: RT actuator */
xpad
->
odata
[
8
]
=
strong
/
256
;
/* left actuator */
packet
->
data
[
8
]
=
strong
/
512
;
/* left actuator */
xpad
->
odata
[
9
]
=
weak
/
256
;
/* right actuator */
packet
->
data
[
9
]
=
weak
/
512
;
/* right actuator */
xpad
->
odata
[
10
]
=
0x80
;
/* length of pulse */
packet
->
data
[
10
]
=
0x80
;
/* length of pulse */
xpad
->
odata
[
11
]
=
0x00
;
/* stop period of pulse */
packet
->
data
[
11
]
=
0x00
;
/* stop period of pulse */
xpad
->
irq_out
->
transfer_buffer_length
=
12
;
packet
->
data
[
12
]
=
0x00
;
packet
->
len
=
13
;
packet
->
pending
=
true
;
break
;
break
;
default:
default:
dev_dbg
(
&
xpad
->
dev
->
dev
,
dev_dbg
(
&
xpad
->
dev
->
dev
,
"%s - rumble command sent to unsupported xpad type: %d
\n
"
,
"%s - rumble command sent to unsupported xpad type: %d
\n
"
,
__func__
,
xpad
->
xtype
);
__func__
,
xpad
->
xtype
);
return
-
EINVAL
;
retval
=
-
EINVAL
;
goto
out
;
}
}
return
usb_submit_urb
(
xpad
->
irq_out
,
GFP_ATOMIC
);
retval
=
xpad_try_sending_next_out_packet
(
xpad
);
out:
spin_unlock_irqrestore
(
&
xpad
->
odata_lock
,
flags
);
return
retval
;
}
}
static
int
xpad_init_ff
(
struct
usb_xpad
*
xpad
)
static
int
xpad_init_ff
(
struct
usb_xpad
*
xpad
)
...
@@ -921,36 +1094,44 @@ struct xpad_led {
...
@@ -921,36 +1094,44 @@ struct xpad_led {
*/
*/
static
void
xpad_send_led_command
(
struct
usb_xpad
*
xpad
,
int
command
)
static
void
xpad_send_led_command
(
struct
usb_xpad
*
xpad
,
int
command
)
{
{
struct
xpad_output_packet
*
packet
=
&
xpad
->
out_packets
[
XPAD_OUT_LED_IDX
];
unsigned
long
flags
;
command
%=
16
;
command
%=
16
;
mutex_lock
(
&
xpad
->
odata_mutex
);
spin_lock_irqsave
(
&
xpad
->
odata_lock
,
flags
);
switch
(
xpad
->
xtype
)
{
switch
(
xpad
->
xtype
)
{
case
XTYPE_XBOX360
:
case
XTYPE_XBOX360
:
xpad
->
odata
[
0
]
=
0x01
;
packet
->
data
[
0
]
=
0x01
;
xpad
->
odata
[
1
]
=
0x03
;
packet
->
data
[
1
]
=
0x03
;
xpad
->
odata
[
2
]
=
command
;
packet
->
data
[
2
]
=
command
;
xpad
->
irq_out
->
transfer_buffer_length
=
3
;
packet
->
len
=
3
;
packet
->
pending
=
true
;
break
;
break
;
case
XTYPE_XBOX360W
:
case
XTYPE_XBOX360W
:
xpad
->
odata
[
0
]
=
0x00
;
packet
->
data
[
0
]
=
0x00
;
xpad
->
odata
[
1
]
=
0x00
;
packet
->
data
[
1
]
=
0x00
;
xpad
->
odata
[
2
]
=
0x08
;
packet
->
data
[
2
]
=
0x08
;
xpad
->
odata
[
3
]
=
0x40
+
command
;
packet
->
data
[
3
]
=
0x40
+
command
;
xpad
->
odata
[
4
]
=
0x00
;
packet
->
data
[
4
]
=
0x00
;
xpad
->
odata
[
5
]
=
0x00
;
packet
->
data
[
5
]
=
0x00
;
xpad
->
odata
[
6
]
=
0x00
;
packet
->
data
[
6
]
=
0x00
;
xpad
->
odata
[
7
]
=
0x00
;
packet
->
data
[
7
]
=
0x00
;
xpad
->
odata
[
8
]
=
0x00
;
packet
->
data
[
8
]
=
0x00
;
xpad
->
odata
[
9
]
=
0x00
;
packet
->
data
[
9
]
=
0x00
;
xpad
->
odata
[
10
]
=
0x00
;
packet
->
data
[
10
]
=
0x00
;
xpad
->
odata
[
11
]
=
0x00
;
packet
->
data
[
11
]
=
0x00
;
xpad
->
irq_out
->
transfer_buffer_length
=
12
;
packet
->
len
=
12
;
packet
->
pending
=
true
;
break
;
break
;
}
}
usb_submit_urb
(
xpad
->
irq_out
,
GFP_KERNEL
);
xpad_try_sending_next_out_packet
(
xpad
);
mutex_unlock
(
&
xpad
->
odata_mutex
);
spin_unlock_irqrestore
(
&
xpad
->
odata_lock
,
flags
);
}
}
/*
/*
...
@@ -959,7 +1140,7 @@ static void xpad_send_led_command(struct usb_xpad *xpad, int command)
...
@@ -959,7 +1140,7 @@ static void xpad_send_led_command(struct usb_xpad *xpad, int command)
*/
*/
static
void
xpad_identify_controller
(
struct
usb_xpad
*
xpad
)
static
void
xpad_identify_controller
(
struct
usb_xpad
*
xpad
)
{
{
xpad_send_led_command
(
xpad
,
(
xpad
->
pad_nr
%
4
)
+
2
);
led_set_brightness
(
&
xpad
->
led
->
led_cdev
,
(
xpad
->
pad_nr
%
4
)
+
2
);
}
}
static
void
xpad_led_set
(
struct
led_classdev
*
led_cdev
,
static
void
xpad_led_set
(
struct
led_classdev
*
led_cdev
,
...
@@ -1001,14 +1182,7 @@ static int xpad_led_probe(struct usb_xpad *xpad)
...
@@ -1001,14 +1182,7 @@ static int xpad_led_probe(struct usb_xpad *xpad)
if
(
error
)
if
(
error
)
goto
err_free_id
;
goto
err_free_id
;
if
(
xpad
->
xtype
==
XTYPE_XBOX360
)
{
xpad_identify_controller
(
xpad
);
/*
* Light up the segment corresponding to controller
* number on wired devices. On wireless we'll do that
* when they respond to "presence" packet.
*/
xpad_identify_controller
(
xpad
);
}
return
0
;
return
0
;
...
@@ -1036,37 +1210,73 @@ static void xpad_led_disconnect(struct usb_xpad *xpad) { }
...
@@ -1036,37 +1210,73 @@ static void xpad_led_disconnect(struct usb_xpad *xpad) { }
static
void
xpad_identify_controller
(
struct
usb_xpad
*
xpad
)
{
}
static
void
xpad_identify_controller
(
struct
usb_xpad
*
xpad
)
{
}
#endif
#endif
static
int
xpad_
open
(
struct
input_dev
*
dev
)
static
int
xpad_
start_input
(
struct
usb_xpad
*
xpad
)
{
{
struct
usb_xpad
*
xpad
=
input_get_drvdata
(
dev
);
int
error
;
/* URB was submitted in probe */
if
(
xpad
->
xtype
==
XTYPE_XBOX360W
)
return
0
;
xpad
->
irq_in
->
dev
=
xpad
->
udev
;
if
(
usb_submit_urb
(
xpad
->
irq_in
,
GFP_KERNEL
))
if
(
usb_submit_urb
(
xpad
->
irq_in
,
GFP_KERNEL
))
return
-
EIO
;
return
-
EIO
;
if
(
xpad
->
xtype
==
XTYPE_XBOXONE
)
{
if
(
xpad
->
xtype
==
XTYPE_XBOXONE
)
{
/* Xbox one controller needs to be initialized. */
error
=
xpad_start_xbox_one
(
xpad
);
xpad
->
odata
[
0
]
=
0x05
;
if
(
error
)
{
xpad
->
odata
[
1
]
=
0x20
;
usb_kill_urb
(
xpad
->
irq_in
)
;
xpad
->
irq_out
->
transfer_buffer_length
=
2
;
return
error
;
return
usb_submit_urb
(
xpad
->
irq_out
,
GFP_KERNEL
);
}
}
}
return
0
;
return
0
;
}
}
static
void
xpad_
close
(
struct
input_dev
*
dev
)
static
void
xpad_
stop_input
(
struct
usb_xpad
*
xpad
)
{
{
struct
usb_xpad
*
xpad
=
input_get_drvdata
(
dev
);
usb_kill_urb
(
xpad
->
irq_in
);
}
static
int
xpad360w_start_input
(
struct
usb_xpad
*
xpad
)
{
int
error
;
if
(
xpad
->
xtype
!=
XTYPE_XBOX360W
)
error
=
usb_submit_urb
(
xpad
->
irq_in
,
GFP_KERNEL
);
if
(
error
)
return
-
EIO
;
/*
* Send presence packet.
* This will force the controller to resend connection packets.
* This is useful in the case we activate the module after the
* adapter has been plugged in, as it won't automatically
* send us info about the controllers.
*/
error
=
xpad_inquiry_pad_presence
(
xpad
);
if
(
error
)
{
usb_kill_urb
(
xpad
->
irq_in
);
usb_kill_urb
(
xpad
->
irq_in
);
return
error
;
}
xpad_stop_output
(
xpad
);
return
0
;
}
static
void
xpad360w_stop_input
(
struct
usb_xpad
*
xpad
)
{
usb_kill_urb
(
xpad
->
irq_in
);
/* Make sure we are done with presence work if it was scheduled */
flush_work
(
&
xpad
->
work
);
}
static
int
xpad_open
(
struct
input_dev
*
dev
)
{
struct
usb_xpad
*
xpad
=
input_get_drvdata
(
dev
);
return
xpad_start_input
(
xpad
);
}
static
void
xpad_close
(
struct
input_dev
*
dev
)
{
struct
usb_xpad
*
xpad
=
input_get_drvdata
(
dev
);
xpad_stop_input
(
xpad
);
}
}
static
void
xpad_set_up_abs
(
struct
input_dev
*
input_dev
,
signed
short
abs
)
static
void
xpad_set_up_abs
(
struct
input_dev
*
input_dev
,
signed
short
abs
)
...
@@ -1097,8 +1307,11 @@ static void xpad_set_up_abs(struct input_dev *input_dev, signed short abs)
...
@@ -1097,8 +1307,11 @@ static void xpad_set_up_abs(struct input_dev *input_dev, signed short abs)
static
void
xpad_deinit_input
(
struct
usb_xpad
*
xpad
)
static
void
xpad_deinit_input
(
struct
usb_xpad
*
xpad
)
{
{
xpad_led_disconnect
(
xpad
);
if
(
xpad
->
input_created
)
{
input_unregister_device
(
xpad
->
dev
);
xpad
->
input_created
=
false
;
xpad_led_disconnect
(
xpad
);
input_unregister_device
(
xpad
->
dev
);
}
}
}
static
int
xpad_init_input
(
struct
usb_xpad
*
xpad
)
static
int
xpad_init_input
(
struct
usb_xpad
*
xpad
)
...
@@ -1118,8 +1331,10 @@ static int xpad_init_input(struct usb_xpad *xpad)
...
@@ -1118,8 +1331,10 @@ static int xpad_init_input(struct usb_xpad *xpad)
input_set_drvdata
(
input_dev
,
xpad
);
input_set_drvdata
(
input_dev
,
xpad
);
input_dev
->
open
=
xpad_open
;
if
(
xpad
->
xtype
!=
XTYPE_XBOX360W
)
{
input_dev
->
close
=
xpad_close
;
input_dev
->
open
=
xpad_open
;
input_dev
->
close
=
xpad_close
;
}
__set_bit
(
EV_KEY
,
input_dev
->
evbit
);
__set_bit
(
EV_KEY
,
input_dev
->
evbit
);
...
@@ -1181,6 +1396,7 @@ static int xpad_init_input(struct usb_xpad *xpad)
...
@@ -1181,6 +1396,7 @@ static int xpad_init_input(struct usb_xpad *xpad)
if
(
error
)
if
(
error
)
goto
err_disconnect_led
;
goto
err_disconnect_led
;
xpad
->
input_created
=
true
;
return
0
;
return
0
;
err_disconnect_led:
err_disconnect_led:
...
@@ -1241,6 +1457,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
...
@@ -1241,6 +1457,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
xpad
->
mapping
=
xpad_device
[
i
].
mapping
;
xpad
->
mapping
=
xpad_device
[
i
].
mapping
;
xpad
->
xtype
=
xpad_device
[
i
].
xtype
;
xpad
->
xtype
=
xpad_device
[
i
].
xtype
;
xpad
->
name
=
xpad_device
[
i
].
name
;
xpad
->
name
=
xpad_device
[
i
].
name
;
INIT_WORK
(
&
xpad
->
work
,
xpad_presence_work
);
if
(
xpad
->
xtype
==
XTYPE_UNKNOWN
)
{
if
(
xpad
->
xtype
==
XTYPE_UNKNOWN
)
{
if
(
intf
->
cur_altsetting
->
desc
.
bInterfaceClass
==
USB_CLASS_VENDOR_SPEC
)
{
if
(
intf
->
cur_altsetting
->
desc
.
bInterfaceClass
==
USB_CLASS_VENDOR_SPEC
)
{
...
@@ -1277,10 +1494,6 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
...
@@ -1277,10 +1494,6 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
usb_set_intfdata
(
intf
,
xpad
);
usb_set_intfdata
(
intf
,
xpad
);
error
=
xpad_init_input
(
xpad
);
if
(
error
)
goto
err_deinit_output
;
if
(
xpad
->
xtype
==
XTYPE_XBOX360W
)
{
if
(
xpad
->
xtype
==
XTYPE_XBOX360W
)
{
/*
/*
* Submit the int URB immediately rather than waiting for open
* Submit the int URB immediately rather than waiting for open
...
@@ -1289,28 +1502,24 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
...
@@ -1289,28 +1502,24 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
* exactly the message that a controller has arrived that
* exactly the message that a controller has arrived that
* we're waiting for.
* we're waiting for.
*/
*/
xpad
->
irq_in
->
dev
=
xpad
->
udev
;
error
=
xpad360w_start_input
(
xpad
);
error
=
usb_submit_urb
(
xpad
->
irq_in
,
GFP_KERNEL
);
if
(
error
)
if
(
error
)
goto
err_deinit_input
;
goto
err_deinit_output
;
/*
/*
*
Send presence packet.
*
Wireless controllers require RESET_RESUME to work properly
*
This will force the controller to resend connection packets.
*
after suspend. Ideally this quirk should be in usb core
*
This is useful in the case we activate the module after th
e
*
quirk list, but we have too many vendors producing thes
e
*
adapter has been plugged in, as it won't automatically
*
controllers and we'd need to maintain 2 identical lists
*
send us info about the controllers
.
*
here in this driver and in usb core
.
*/
*/
error
=
xpad_inquiry_pad_presence
(
xpad
);
udev
->
quirks
|=
USB_QUIRK_RESET_RESUME
;
}
else
{
error
=
xpad_init_input
(
xpad
);
if
(
error
)
if
(
error
)
goto
err_
kill_in_urb
;
goto
err_
deinit_output
;
}
}
return
0
;
return
0
;
err_kill_in_urb:
usb_kill_urb
(
xpad
->
irq_in
);
err_deinit_input:
xpad_deinit_input
(
xpad
);
err_deinit_output:
err_deinit_output:
xpad_deinit_output
(
xpad
);
xpad_deinit_output
(
xpad
);
err_free_in_urb:
err_free_in_urb:
...
@@ -1320,19 +1529,24 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
...
@@ -1320,19 +1529,24 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
err_free_mem:
err_free_mem:
kfree
(
xpad
);
kfree
(
xpad
);
return
error
;
return
error
;
}
}
static
void
xpad_disconnect
(
struct
usb_interface
*
intf
)
static
void
xpad_disconnect
(
struct
usb_interface
*
intf
)
{
{
struct
usb_xpad
*
xpad
=
usb_get_intfdata
(
intf
);
struct
usb_xpad
*
xpad
=
usb_get_intfdata
(
intf
);
if
(
xpad
->
xtype
==
XTYPE_XBOX360W
)
xpad360w_stop_input
(
xpad
);
xpad_deinit_input
(
xpad
);
xpad_deinit_input
(
xpad
);
xpad_deinit_output
(
xpad
);
if
(
xpad
->
xtype
==
XTYPE_XBOX360W
)
{
/*
usb_kill_urb
(
xpad
->
irq_in
);
* Now that both input device and LED device are gone we can
}
* stop output URB.
*/
xpad_stop_output
(
xpad
);
xpad_deinit_output
(
xpad
);
usb_free_urb
(
xpad
->
irq_in
);
usb_free_urb
(
xpad
->
irq_in
);
usb_free_coherent
(
xpad
->
udev
,
XPAD_PKT_LEN
,
usb_free_coherent
(
xpad
->
udev
,
XPAD_PKT_LEN
,
...
@@ -1343,10 +1557,55 @@ static void xpad_disconnect(struct usb_interface *intf)
...
@@ -1343,10 +1557,55 @@ static void xpad_disconnect(struct usb_interface *intf)
usb_set_intfdata
(
intf
,
NULL
);
usb_set_intfdata
(
intf
,
NULL
);
}
}
static
int
xpad_suspend
(
struct
usb_interface
*
intf
,
pm_message_t
message
)
{
struct
usb_xpad
*
xpad
=
usb_get_intfdata
(
intf
);
struct
input_dev
*
input
=
xpad
->
dev
;
if
(
xpad
->
xtype
==
XTYPE_XBOX360W
)
{
/*
* Wireless controllers always listen to input so
* they are notified when controller shows up
* or goes away.
*/
xpad360w_stop_input
(
xpad
);
}
else
{
mutex_lock
(
&
input
->
mutex
);
if
(
input
->
users
)
xpad_stop_input
(
xpad
);
mutex_unlock
(
&
input
->
mutex
);
}
xpad_stop_output
(
xpad
);
return
0
;
}
static
int
xpad_resume
(
struct
usb_interface
*
intf
)
{
struct
usb_xpad
*
xpad
=
usb_get_intfdata
(
intf
);
struct
input_dev
*
input
=
xpad
->
dev
;
int
retval
=
0
;
if
(
xpad
->
xtype
==
XTYPE_XBOX360W
)
{
retval
=
xpad360w_start_input
(
xpad
);
}
else
{
mutex_lock
(
&
input
->
mutex
);
if
(
input
->
users
)
retval
=
xpad_start_input
(
xpad
);
mutex_unlock
(
&
input
->
mutex
);
}
return
retval
;
}
static
struct
usb_driver
xpad_driver
=
{
static
struct
usb_driver
xpad_driver
=
{
.
name
=
"xpad"
,
.
name
=
"xpad"
,
.
probe
=
xpad_probe
,
.
probe
=
xpad_probe
,
.
disconnect
=
xpad_disconnect
,
.
disconnect
=
xpad_disconnect
,
.
suspend
=
xpad_suspend
,
.
resume
=
xpad_resume
,
.
reset_resume
=
xpad_resume
,
.
id_table
=
xpad_table
,
.
id_table
=
xpad_table
,
};
};
...
...
drivers/input/keyboard/gpio_keys.c
View file @
b26a95d4
...
@@ -630,7 +630,7 @@ gpio_keys_get_devtree_pdata(struct device *dev)
...
@@ -630,7 +630,7 @@ gpio_keys_get_devtree_pdata(struct device *dev)
if
(
!
node
)
if
(
!
node
)
return
ERR_PTR
(
-
ENODEV
);
return
ERR_PTR
(
-
ENODEV
);
nbuttons
=
of_get_child_count
(
node
);
nbuttons
=
of_get_
available_
child_count
(
node
);
if
(
nbuttons
==
0
)
if
(
nbuttons
==
0
)
return
ERR_PTR
(
-
ENODEV
);
return
ERR_PTR
(
-
ENODEV
);
...
@@ -645,8 +645,10 @@ gpio_keys_get_devtree_pdata(struct device *dev)
...
@@ -645,8 +645,10 @@ gpio_keys_get_devtree_pdata(struct device *dev)
pdata
->
rep
=
!!
of_get_property
(
node
,
"autorepeat"
,
NULL
);
pdata
->
rep
=
!!
of_get_property
(
node
,
"autorepeat"
,
NULL
);
of_property_read_string
(
node
,
"label"
,
&
pdata
->
name
);
i
=
0
;
i
=
0
;
for_each_child_of_node
(
node
,
pp
)
{
for_each_
available_
child_of_node
(
node
,
pp
)
{
enum
of_gpio_flags
flags
;
enum
of_gpio_flags
flags
;
button
=
&
pdata
->
buttons
[
i
++
];
button
=
&
pdata
->
buttons
[
i
++
];
...
...
drivers/input/touchscreen/atmel_mxt_ts.c
View file @
b26a95d4
...
@@ -113,8 +113,8 @@ struct t7_config {
...
@@ -113,8 +113,8 @@ struct t7_config {
#define MXT_T9_DETECT (1 << 7)
#define MXT_T9_DETECT (1 << 7)
struct
t9_range
{
struct
t9_range
{
u
16
x
;
__le
16
x
;
u
16
y
;
__le
16
y
;
}
__packed
;
}
__packed
;
/* MXT_TOUCH_MULTI_T9 orient */
/* MXT_TOUCH_MULTI_T9 orient */
...
@@ -216,6 +216,7 @@ struct mxt_data {
...
@@ -216,6 +216,7 @@ struct mxt_data {
unsigned
int
irq
;
unsigned
int
irq
;
unsigned
int
max_x
;
unsigned
int
max_x
;
unsigned
int
max_y
;
unsigned
int
max_y
;
bool
xy_switch
;
bool
in_bootloader
;
bool
in_bootloader
;
u16
mem_size
;
u16
mem_size
;
u8
t100_aux_ampl
;
u8
t100_aux_ampl
;
...
@@ -1665,8 +1666,8 @@ static int mxt_read_t9_resolution(struct mxt_data *data)
...
@@ -1665,8 +1666,8 @@ static int mxt_read_t9_resolution(struct mxt_data *data)
if
(
error
)
if
(
error
)
return
error
;
return
error
;
le16_to_cpus
(
&
range
.
x
);
data
->
max_x
=
get_unaligned_le16
(
&
range
.
x
);
le16_to_cpus
(
&
range
.
y
);
data
->
max_y
=
get_unaligned_le16
(
&
range
.
y
);
error
=
__mxt_read_reg
(
client
,
error
=
__mxt_read_reg
(
client
,
object
->
start_address
+
MXT_T9_ORIENT
,
object
->
start_address
+
MXT_T9_ORIENT
,
...
@@ -1674,23 +1675,7 @@ static int mxt_read_t9_resolution(struct mxt_data *data)
...
@@ -1674,23 +1675,7 @@ static int mxt_read_t9_resolution(struct mxt_data *data)
if
(
error
)
if
(
error
)
return
error
;
return
error
;
/* Handle default values */
data
->
xy_switch
=
orient
&
MXT_T9_ORIENT_SWITCH
;
if
(
range
.
x
==
0
)
range
.
x
=
1023
;
if
(
range
.
y
==
0
)
range
.
y
=
1023
;
if
(
orient
&
MXT_T9_ORIENT_SWITCH
)
{
data
->
max_x
=
range
.
y
;
data
->
max_y
=
range
.
x
;
}
else
{
data
->
max_x
=
range
.
x
;
data
->
max_y
=
range
.
y
;
}
dev_dbg
(
&
client
->
dev
,
"Touchscreen size X%uY%u
\n
"
,
data
->
max_x
,
data
->
max_y
);
return
0
;
return
0
;
}
}
...
@@ -1708,13 +1693,14 @@ static int mxt_read_t100_config(struct mxt_data *data)
...
@@ -1708,13 +1693,14 @@ static int mxt_read_t100_config(struct mxt_data *data)
if
(
!
object
)
if
(
!
object
)
return
-
EINVAL
;
return
-
EINVAL
;
/* read touchscreen dimensions */
error
=
__mxt_read_reg
(
client
,
error
=
__mxt_read_reg
(
client
,
object
->
start_address
+
MXT_T100_XRANGE
,
object
->
start_address
+
MXT_T100_XRANGE
,
sizeof
(
range_x
),
&
range_x
);
sizeof
(
range_x
),
&
range_x
);
if
(
error
)
if
(
error
)
return
error
;
return
error
;
le16_to_cpus
(
&
range_x
);
data
->
max_x
=
get_unaligned_le16
(
&
range_x
);
error
=
__mxt_read_reg
(
client
,
error
=
__mxt_read_reg
(
client
,
object
->
start_address
+
MXT_T100_YRANGE
,
object
->
start_address
+
MXT_T100_YRANGE
,
...
@@ -1722,36 +1708,24 @@ static int mxt_read_t100_config(struct mxt_data *data)
...
@@ -1722,36 +1708,24 @@ static int mxt_read_t100_config(struct mxt_data *data)
if
(
error
)
if
(
error
)
return
error
;
return
error
;
le16_to_cpus
(
&
range_y
);
data
->
max_y
=
get_unaligned_le16
(
&
range_y
);
/* read orientation config */
error
=
__mxt_read_reg
(
client
,
error
=
__mxt_read_reg
(
client
,
object
->
start_address
+
MXT_T100_CFG1
,
object
->
start_address
+
MXT_T100_CFG1
,
1
,
&
cfg
);
1
,
&
cfg
);
if
(
error
)
if
(
error
)
return
error
;
return
error
;
data
->
xy_switch
=
cfg
&
MXT_T100_CFG_SWITCHXY
;
/* allocate aux bytes */
error
=
__mxt_read_reg
(
client
,
error
=
__mxt_read_reg
(
client
,
object
->
start_address
+
MXT_T100_TCHAUX
,
object
->
start_address
+
MXT_T100_TCHAUX
,
1
,
&
tchaux
);
1
,
&
tchaux
);
if
(
error
)
if
(
error
)
return
error
;
return
error
;
/* Handle default values */
if
(
range_x
==
0
)
range_x
=
1023
;
if
(
range_y
==
0
)
range_y
=
1023
;
if
(
cfg
&
MXT_T100_CFG_SWITCHXY
)
{
data
->
max_x
=
range_y
;
data
->
max_y
=
range_x
;
}
else
{
data
->
max_x
=
range_x
;
data
->
max_y
=
range_y
;
}
/* allocate aux bytes */
aux
=
6
;
aux
=
6
;
if
(
tchaux
&
MXT_T100_TCHAUX_VECT
)
if
(
tchaux
&
MXT_T100_TCHAUX_VECT
)
...
@@ -1767,9 +1741,6 @@ static int mxt_read_t100_config(struct mxt_data *data)
...
@@ -1767,9 +1741,6 @@ static int mxt_read_t100_config(struct mxt_data *data)
"T100 aux mappings vect:%u ampl:%u area:%u
\n
"
,
"T100 aux mappings vect:%u ampl:%u area:%u
\n
"
,
data
->
t100_aux_vect
,
data
->
t100_aux_ampl
,
data
->
t100_aux_area
);
data
->
t100_aux_vect
,
data
->
t100_aux_ampl
,
data
->
t100_aux_area
);
dev_info
(
&
client
->
dev
,
"T100 Touchscreen size X%uY%u
\n
"
,
data
->
max_x
,
data
->
max_y
);
return
0
;
return
0
;
}
}
...
@@ -1828,6 +1799,19 @@ static int mxt_initialize_input_device(struct mxt_data *data)
...
@@ -1828,6 +1799,19 @@ static int mxt_initialize_input_device(struct mxt_data *data)
return
-
EINVAL
;
return
-
EINVAL
;
}
}
/* Handle default values and orientation switch */
if
(
data
->
max_x
==
0
)
data
->
max_x
=
1023
;
if
(
data
->
max_y
==
0
)
data
->
max_y
=
1023
;
if
(
data
->
xy_switch
)
swap
(
data
->
max_x
,
data
->
max_y
);
dev_info
(
dev
,
"Touchscreen size X%uY%u
\n
"
,
data
->
max_x
,
data
->
max_y
);
/* Register input device */
input_dev
=
input_allocate_device
();
input_dev
=
input_allocate_device
();
if
(
!
input_dev
)
{
if
(
!
input_dev
)
{
dev_err
(
dev
,
"Failed to allocate memory
\n
"
);
dev_err
(
dev
,
"Failed to allocate memory
\n
"
);
...
...
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