From patchwork Wed Nov 11 14:49:38 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Frank Praznik X-Patchwork-Id: 7596131 X-Patchwork-Delegate: jikos@jikos.cz Return-Path: X-Original-To: patchwork-linux-input@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 4E6249F1C2 for ; Wed, 11 Nov 2015 14:49:53 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 5E8A320675 for ; Wed, 11 Nov 2015 14:49:52 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 6BDE420656 for ; Wed, 11 Nov 2015 14:49:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752274AbbKKOtu (ORCPT ); Wed, 11 Nov 2015 09:49:50 -0500 Received: from mail-yk0-f177.google.com ([209.85.160.177]:36692 "EHLO mail-yk0-f177.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752229AbbKKOtt (ORCPT ); Wed, 11 Nov 2015 09:49:49 -0500 Received: by ykdr82 with SMTP id r82so51434740ykd.3 for ; Wed, 11 Nov 2015 06:49:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=pLFAVlSA5tLDlqxq0z7H30s5QIp+1Q4rrwDnSLSrphw=; b=d+JdzK/JzHaM+GxpiC/yhxy5lyHzfVYeWRhJpjgy/tBiJPzldpA819oGFJ8LkJ3XzQ TP6CiibsH+S753gh2+BMIiDCbfoRBHDEI6kICdfuJMpMjCdL67y7BNi4OstOmniZQSNG 2OBr29/N5uLAv1vQWHizfI/8MkBWVvBu8AEOENCTxpL1U37gsMGUvwCUC5xiLOdCdQ6L 8VcVN8W/ekcpKkaPcumR91pUe9+s6YdmaFLF7z7OoYSUSsMDfyxVwpi88N+lvLyXJTyQ pBKhYzk8j/xGmXmcUk3rR50C60mZ3fX1MN/qmCvqwk+Q6R7H/wAwDf2gAvnOpZ0wXcid 1mOA== X-Received: by 10.13.193.132 with SMTP id c126mr9960833ywd.310.1447253388663; Wed, 11 Nov 2015 06:49:48 -0800 (PST) Received: from localhost.localdomain.localdomain (cpe-104-231-99-148.neo.res.rr.com. [104.231.99.148]) by smtp.gmail.com with ESMTPSA id y7sm3074907ywc.36.2015.11.11.06.49.47 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 11 Nov 2015 06:49:48 -0800 (PST) From: Frank Praznik To: linux-input@vger.kernel.org Cc: jkosina@suse.cz, ao2@ao2.it, Frank Praznik 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 Message-Id: <1447253378-13939-3-git-send-email-frank.praznik@gmail.com> X-Mailer: git-send-email 2.4.3 In-Reply-To: <1447253378-13939-1-git-send-email-frank.praznik@gmail.com> References: <1447253378-13939-1-git-send-email-frank.praznik@gmail.com> Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org X-Spam-Status: No, score=-7.1 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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 --- 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)