Skip to content

Commit 5d67940

Browse files
authored
input: xpad - Switch to workqueue for xpad360w button poweroff
This allows to turn off the pad without having to release the Xbox (mode) button Signed-off-by: Davide Garberi <dade.garberi@gmail.com>
1 parent 2c087f9 commit 5d67940

File tree

1 file changed

+24
-11
lines changed

1 file changed

+24
-11
lines changed

xpad.c

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -710,6 +710,7 @@ struct usb_xpad {
710710
int quirks;
711711
const char *name; /* name of the device */
712712
struct work_struct work; /* init/remove device from callback */
713+
struct delayed_work poweroff_work; /* work struct for poweroff on mode long press */
713714
time64_t mode_btn_down_ts;
714715
};
715716

@@ -871,20 +872,29 @@ static void xpad360_process_packet(struct usb_xpad *xpad, struct input_dev *dev,
871872

872873
/* XBOX360W controllers can't be turned off without driver assistance */
873874
if (xpad->xtype == XTYPE_XBOX360W) {
874-
if (xpad->mode_btn_down_ts > 0 && xpad->pad_present &&
875-
((ktime_get_seconds() - xpad->mode_btn_down_ts) >=
876-
XPAD360W_POWEROFF_TIMEOUT)) {
877-
xpad360w_poweroff_controller(xpad);
878-
xpad->mode_btn_down_ts = 0;
879-
return;
875+
if (data[3] & BIT(2)) {
876+
if (xpad->mode_btn_down_ts == 0)
877+
xpad->mode_btn_down_ts = ktime_get_seconds();
878+
schedule_delayed_work(&xpad->poweroff_work, msecs_to_jiffies(0));
879+
} else {
880+
xpad->mode_btn_down_ts = 0;
880881
}
882+
}
883+
}
881884

882-
/* mode button down/up */
883-
if (data[3] & BIT(2))
884-
xpad->mode_btn_down_ts = ktime_get_seconds();
885-
else
886-
xpad->mode_btn_down_ts = 0;
885+
static void xpad360w_poweroff_work(struct work_struct *work) {
886+
struct usb_xpad *xpad = container_of(to_delayed_work(work), struct usb_xpad, poweroff_work);
887+
888+
if (xpad->mode_btn_down_ts == 0)
889+
return;
890+
891+
if ((ktime_get_seconds() - xpad->mode_btn_down_ts) >= XPAD360W_POWEROFF_TIMEOUT) {
892+
xpad360w_poweroff_controller(xpad);
893+
xpad->mode_btn_down_ts = 0;
894+
return;
887895
}
896+
897+
schedule_delayed_work(&xpad->poweroff_work, msecs_to_jiffies(200));
888898
}
889899

890900
static void xpad_presence_work(struct work_struct *work)
@@ -1864,6 +1874,8 @@ static int xpad360w_start_input(struct usb_xpad *xpad)
18641874
return error;
18651875
}
18661876

1877+
INIT_DELAYED_WORK(&xpad->poweroff_work, xpad360w_poweroff_work);
1878+
18671879
return 0;
18681880
}
18691881

@@ -1873,6 +1885,7 @@ static void xpad360w_stop_input(struct usb_xpad *xpad)
18731885

18741886
/* Make sure we are done with presence work if it was scheduled */
18751887
flush_work(&xpad->work);
1888+
flush_delayed_work(&xpad->poweroff_work);
18761889
}
18771890

18781891
static int xpad_open(struct input_dev *dev)

0 commit comments

Comments
 (0)