* [PATCH v2] Input: xpad - Poweroff XBOX360W on mode button long press
2021-11-14 1:52 ` Cameron Gutman
@ 2021-11-14 19:23 ` Benjamin Valentin
2021-11-16 16:23 ` [PATCH 1/2] Input: xpad - name unknown gamepads according to device type Benjamin Valentin
` (2 subsequent siblings)
3 siblings, 0 replies; 6+ messages in thread
From: Benjamin Valentin @ 2021-11-14 19:23 UTC (permalink / raw)
To: Cameron Gutman; +Cc: Dmitry Torokhov, linux-input, Lee Jones, lawl
Newer gamepads turn themselves off when the mode button is held down.
For XBOX360W gamepads we must do this in the driver.
Power off the gamepad after 5s of holding down the button.
Signed-off-by: lawl <github@dumbinter.net>
Signed-off-by: Benjamin Valentin <benpicco@googlemail.com>
---
Changed the timeout back to 5s
drivers/input/joystick/xpad.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index 18caaf436ed4..e36c4b0abd4b 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -619,11 +619,13 @@ struct usb_xpad {
int pad_nr; /* the order x360 pads were attached */
const char *name; /* name of the device */
struct work_struct work; /* init/remove device from callback */
+ time64_t mode_btn_down_ts; /* timestamp when mode button was pressed */
};
static int xpad_init_input(struct usb_xpad *xpad);
static void xpad_deinit_input(struct usb_xpad *xpad);
static void xpadone_ack_mode_report(struct usb_xpad *xpad, u8 seq_num);
+static void xpad360w_poweroff_controller(struct usb_xpad *xpad);
/*
* xpad_process_packet
@@ -775,6 +777,24 @@ static void xpad360_process_packet(struct usb_xpad *xpad, struct input_dev *dev,
}
input_sync(dev);
+
+ /* xbox360w controllers can't be turned off without driver assistance */
+ if (xpad->xtype == XTYPE_XBOX360W) {
+ if (xpad->mode_btn_down_ts > 0
+ && xpad->pad_present
+ /* send power off after 5s of holding the button */
+ && (ktime_get_seconds() - xpad->mode_btn_down_ts) >= 5) {
+ xpad360w_poweroff_controller(xpad);
+ xpad->mode_btn_down_ts = 0;
+ return;
+ }
+
+ /* mode button down/up */
+ if (data[3] & 0x04)
+ xpad->mode_btn_down_ts = ktime_get_seconds();
+ else
+ xpad->mode_btn_down_ts = 0;
+ }
}
static void xpad_presence_work(struct work_struct *work)
--
2.32.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 1/2] Input: xpad - name unknown gamepads according to device type
2021-11-14 1:52 ` Cameron Gutman
2021-11-14 19:23 ` [PATCH v2] " Benjamin Valentin
@ 2021-11-16 16:23 ` Benjamin Valentin
2021-11-16 16:25 ` [PATCH 2/2] Input: xpad - drop checks for XTYPE_UNKNOWN Benjamin Valentin
2022-01-05 11:53 ` [RESEND][PATCH v2] Input: xpad - Poweroff XBOX360W on mode button long press Benjamin Valentin
3 siblings, 0 replies; 6+ messages in thread
From: Benjamin Valentin @ 2021-11-16 16:23 UTC (permalink / raw)
To: Cameron Gutman; +Cc: Dmitry Torokhov, linux-input, Lee Jones
Calling any unknown device 'Generic X-Box pad' can lead to confusion
as a user might think the device type was not properly detected.
The different controller generations also have different button numbers
and mappings.
Instead use a device type specific name so it's immediately clear that
the device has been recognized.
This means we can now drop the "Generic X-Box pad" entry.
To allow the entire line to be 0, re-order the device types so that
'UNKNOWN' is 0 now too.
Signed-off-by: Benjamin Valentin <benpicco@googlemail.com>
---
drivers/input/joystick/xpad.c | 23 ++++++++++++++---------
1 file changed, 14 insertions(+), 9 deletions(-)
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index 4c914f75a902..31a268f43b5b 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -83,11 +83,11 @@
#define DANCEPAD_MAP_CONFIG (MAP_DPAD_TO_BUTTONS | \
MAP_TRIGGERS_TO_BUTTONS | MAP_STICKS_TO_NULL)
-#define XTYPE_XBOX 0
-#define XTYPE_XBOX360 1
-#define XTYPE_XBOX360W 2
-#define XTYPE_XBOXONE 3
-#define XTYPE_UNKNOWN 4
+#define XTYPE_UNKNOWN 0
+#define XTYPE_XBOX 1
+#define XTYPE_XBOX360 2
+#define XTYPE_XBOX360W 3
+#define XTYPE_XBOXONE 4
static bool dpad_to_buttons;
module_param(dpad_to_buttons, bool, S_IRUGO);
@@ -337,7 +337,7 @@ static const struct xpad_device {
{ 0x3285, 0x0607, "Nacon GC-100", 0, XTYPE_XBOX360 },
{ 0x3767, 0x0101, "Fanatec Speedster 3 Forceshock Wheel", 0, XTYPE_XBOX },
{ 0xffff, 0xffff, "Chinese-made Xbox Controller", 0, XTYPE_XBOX },
- { 0x0000, 0x0000, "Generic X-Box pad", 0, XTYPE_UNKNOWN }
+ { }
};
/* buttons shared with xbox and xbox360 */
@@ -1783,14 +1783,19 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
if (xpad->xtype == XTYPE_UNKNOWN) {
if (intf->cur_altsetting->desc.bInterfaceClass == USB_CLASS_VENDOR_SPEC) {
- if (intf->cur_altsetting->desc.bInterfaceProtocol == 129)
+ if (intf->cur_altsetting->desc.bInterfaceProtocol == 129) {
xpad->xtype = XTYPE_XBOX360W;
- else if (intf->cur_altsetting->desc.bInterfaceProtocol == 208)
+ xpad->name = "Xbox 360 wireless pad";
+ } else if (intf->cur_altsetting->desc.bInterfaceProtocol == 208) {
xpad->xtype = XTYPE_XBOXONE;
- else
+ xpad->name = "Xbox One pad";
+ } else {
xpad->xtype = XTYPE_XBOX360;
+ xpad->name = "Xbox 360 pad";
+ }
} else {
xpad->xtype = XTYPE_XBOX;
+ xpad->name = "Xbox classic pad";
}
if (dpad_to_buttons)
--
2.32.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 2/2] Input: xpad - drop checks for XTYPE_UNKNOWN
2021-11-14 1:52 ` Cameron Gutman
2021-11-14 19:23 ` [PATCH v2] " Benjamin Valentin
2021-11-16 16:23 ` [PATCH 1/2] Input: xpad - name unknown gamepads according to device type Benjamin Valentin
@ 2021-11-16 16:25 ` Benjamin Valentin
2022-01-05 11:53 ` [RESEND][PATCH v2] Input: xpad - Poweroff XBOX360W on mode button long press Benjamin Valentin
3 siblings, 0 replies; 6+ messages in thread
From: Benjamin Valentin @ 2021-11-16 16:25 UTC (permalink / raw)
To: Cameron Gutman; +Cc: Dmitry Torokhov, linux-input, Lee Jones
If xtype is XTYPE_UNKNOWN, it will *always* be replaced by the real
detected type in xpad_probe().
It is therefore not possible to encounter the xtype == XTYPE_UNKNOWN
condition anywhere at the run-time of the driver.
That means we can drop those checks.
Signed-off-by: Benjamin Valentin <benpicco@googlemail.com>
---
drivers/input/joystick/xpad.c | 28 +++++++++-------------------
1 file changed, 9 insertions(+), 19 deletions(-)
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index 31a268f43b5b..66a12da58619 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -1110,13 +1110,10 @@ 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)
+ struct usb_endpoint_descriptor *ep_irq_out)
{
int error;
- if (xpad->xtype == XTYPE_UNKNOWN)
- return 0;
-
init_usb_anchor(&xpad->irq_out_anchor);
xpad->odata = usb_alloc_coherent(xpad->udev, XPAD_PKT_LEN,
@@ -1148,23 +1145,19 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad,
static void xpad_stop_output(struct usb_xpad *xpad)
{
- if (xpad->xtype != XTYPE_UNKNOWN) {
- 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);
- }
+ 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)
{
- if (xpad->xtype != XTYPE_UNKNOWN) {
- usb_free_urb(xpad->irq_out);
- usb_free_coherent(xpad->udev, XPAD_PKT_LEN,
- xpad->odata, xpad->odata_dma);
- }
+ usb_free_urb(xpad->irq_out);
+ usb_free_coherent(xpad->udev, XPAD_PKT_LEN,
+ xpad->odata, xpad->odata_dma);
}
static int xpad_inquiry_pad_presence(struct usb_xpad *xpad)
@@ -1339,9 +1332,6 @@ 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)
- return 0;
-
input_set_capability(xpad->dev, EV_FF, FF_RUMBLE);
return input_ff_create_memless(xpad->dev, NULL, xpad_play_effect);
--
2.32.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [RESEND][PATCH v2] Input: xpad - Poweroff XBOX360W on mode button long press
2021-11-14 1:52 ` Cameron Gutman
` (2 preceding siblings ...)
2021-11-16 16:25 ` [PATCH 2/2] Input: xpad - drop checks for XTYPE_UNKNOWN Benjamin Valentin
@ 2022-01-05 11:53 ` Benjamin Valentin
3 siblings, 0 replies; 6+ messages in thread
From: Benjamin Valentin @ 2022-01-05 11:53 UTC (permalink / raw)
To: Cameron Gutman; +Cc: Dmitry Torokhov, linux-input, Lee Jones, lawl
Newer gamepads turn themselves off when the mode button is held down.
For XBOX360W gamepads we must do this in the driver.
Power off the gamepad after 5s of holding down the button.
Signed-off-by: lawl <github@dumbinter.net>
Signed-off-by: Benjamin Valentin <benpicco@googlemail.com>
---
Changed the timeout back to 5s
drivers/input/joystick/xpad.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index 18caaf436ed4..e36c4b0abd4b 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -619,11 +619,13 @@ struct usb_xpad {
int pad_nr; /* the order x360 pads were attached */
const char *name; /* name of the device */
struct work_struct work; /* init/remove device from callback */
+ time64_t mode_btn_down_ts; /* timestamp when mode button was pressed */
};
static int xpad_init_input(struct usb_xpad *xpad);
static void xpad_deinit_input(struct usb_xpad *xpad);
static void xpadone_ack_mode_report(struct usb_xpad *xpad, u8 seq_num);
+static void xpad360w_poweroff_controller(struct usb_xpad *xpad);
/*
* xpad_process_packet
@@ -775,6 +777,24 @@ static void xpad360_process_packet(struct usb_xpad *xpad, struct input_dev *dev,
}
input_sync(dev);
+
+ /* xbox360w controllers can't be turned off without driver assistance */
+ if (xpad->xtype == XTYPE_XBOX360W) {
+ if (xpad->mode_btn_down_ts > 0
+ && xpad->pad_present
+ /* send power off after 5s of holding the button */
+ && (ktime_get_seconds() - xpad->mode_btn_down_ts) >= 5) {
+ xpad360w_poweroff_controller(xpad);
+ xpad->mode_btn_down_ts = 0;
+ return;
+ }
+
+ /* mode button down/up */
+ if (data[3] & 0x04)
+ xpad->mode_btn_down_ts = ktime_get_seconds();
+ else
+ xpad->mode_btn_down_ts = 0;
+ }
}
static void xpad_presence_work(struct work_struct *work)
--
2.32.0
^ permalink raw reply related [flat|nested] 6+ messages in thread