|
@@ -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;
|
|
@@ -1912,6 +1913,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);
|
|
@@ -2427,6 +2434,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 },
|
|
@@ -2476,7 +2533,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)
|