linux-input.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Frank Praznik <frank.praznik@gmail.com>
To: linux-input@vger.kernel.org
Cc: jkosina@suse.cz, ao2@ao2.it, Frank Praznik <frank.praznik@gmail.com>
Subject: [PATCH v2 2/2] hid: sony: Save and restore the controller state on suspend and resume
Date: Wed, 11 Nov 2015 09:49:38 -0500	[thread overview]
Message-ID: <1447253378-13939-3-git-send-email-frank.praznik@gmail.com> (raw)
In-Reply-To: <1447253378-13939-1-git-send-email-frank.praznik@gmail.com>

On hardware which provides standby power for charging devices the state of the
LEDs and force-feedback on controllers can persist even when the system is in
standby.  Additionally, the state of the controllers on resume may be different
from the state they were in at the time when they were suspended (ie. LEDs are
cleared on resume).

This implements the suspend and resume callbacks which saves and clears the
state of the LEDs on suspend and restores them on resume.  Force-feedback is
stopped on suspend but not automatically restored on resume until a new event is
received to avoid potentially damaging hardware.

USB Sixaxis and navigation controllers must be reinitialized when the hardware
is reset on resume or they won't send any input reports.

Signed-off-by: Frank Praznik <frank.praznik@gmail.com>
---

 v2: Add reinitialization for the USB Sixaxis and navigation controllers in the
     resume function.

 drivers/hid/hid-sony.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 64 insertions(+), 1 deletion(-)

diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index fb67839..04e328d 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -1045,6 +1045,7 @@ struct sony_sc {
 	__u8 battery_charging;
 	__u8 battery_capacity;
 	__u8 led_state[MAX_LEDS];
+	__u8 resume_led_state[MAX_LEDS];
 	__u8 led_delay_on[MAX_LEDS];
 	__u8 led_delay_off[MAX_LEDS];
 	__u8 led_count;
@@ -1905,6 +1906,12 @@ static void motion_send_output_report(struct sony_sc *sc)
 	hid_hw_output_report(hdev, (__u8 *)report, MOTION_REPORT_0x02_SIZE);
 }
 
+static inline void sony_send_output_report(struct sony_sc *sc)
+{
+	if (sc->send_output_report)
+		sc->send_output_report(sc);
+}
+
 static void sony_state_worker(struct work_struct *work)
 {
 	struct sony_sc *sc = container_of(work, struct sony_sc, state_worker);
@@ -2420,6 +2427,56 @@ static void sony_remove(struct hid_device *hdev)
 	hid_hw_stop(hdev);
 }
 
+#ifdef CONFIG_PM
+
+static int sony_suspend(struct hid_device *hdev, pm_message_t message)
+{
+	/*
+	 * On suspend save the current LED state,
+	 * stop running force-feedback and blank the LEDS.
+         */
+	if (SONY_LED_SUPPORT || SONY_FF_SUPPORT) {
+		struct sony_sc *sc = hid_get_drvdata(hdev);
+
+#ifdef CONFIG_SONY_FF
+		sc->left = sc->right = 0;
+#endif
+
+		memcpy(sc->resume_led_state, sc->led_state,
+			sizeof(sc->resume_led_state));
+		memset(sc->led_state, 0, sizeof(sc->led_state));
+
+		sony_send_output_report(sc);
+	}
+
+	return 0;
+}
+
+static int sony_resume(struct hid_device *hdev)
+{
+	/* Restore the state of controller LEDs on resume */
+	if (SONY_LED_SUPPORT) {
+		struct sony_sc *sc = hid_get_drvdata(hdev);
+
+		memcpy(sc->led_state, sc->resume_led_state,
+			sizeof(sc->led_state));
+
+		/*
+		 * The Sixaxis and navigation controllers on USB need to be
+		 * reinitialized on resume or they won't behave properly.
+		 */
+		if ((sc->quirks & SIXAXIS_CONTROLLER_USB) ||
+			(sc->quirks & NAVIGATION_CONTROLLER_USB))
+			sixaxis_set_operational_usb(sc->hdev);
+
+		sony_set_leds(sc);
+	}
+
+	return 0;
+}
+
+#endif
+
 static const struct hid_device_id sony_devices[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER),
 		.driver_data = SIXAXIS_CONTROLLER_USB },
@@ -2469,7 +2526,13 @@ static struct hid_driver sony_driver = {
 	.probe            = sony_probe,
 	.remove           = sony_remove,
 	.report_fixup     = sony_report_fixup,
-	.raw_event        = sony_raw_event
+	.raw_event        = sony_raw_event,
+
+#ifdef CONFIG_PM
+	.suspend          = sony_suspend,
+	.resume	          = sony_resume,
+	.reset_resume     = sony_resume,
+#endif
 };
 
 static int __init sony_init(void)
-- 
2.4.3


  parent reply	other threads:[~2015-11-11 14:49 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-11-11 14:49 [PATCH v2 0/2] hid: sony: Clear and restore controller state on suspend and resume Frank Praznik
2015-11-11 14:49 ` [PATCH v2 1/2] hid: sony: Refactor the output report sending functions Frank Praznik
2015-11-11 14:49 ` Frank Praznik [this message]
2015-11-15 15:30 ` [PATCH v2 0/2] hid: sony: Clear and restore controller state on suspend and resume Antonio Ospite
2015-11-17 13:57   ` Frank Praznik
2015-11-19 10:39     ` Antonio Ospite
2015-11-19 10:51       ` Antonio Ospite
2015-11-19 10:17 ` Jiri Kosina

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1447253378-13939-3-git-send-email-frank.praznik@gmail.com \
    --to=frank.praznik@gmail.com \
    --cc=ao2@ao2.it \
    --cc=jkosina@suse.cz \
    --cc=linux-input@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).