aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/hid/hid-sony.c65
1 files changed, 64 insertions, 1 deletions
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index 4ba904b02bc2..1041c44765e1 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -1045,6 +1045,7 @@ struct sony_sc {
1045 __u8 battery_charging; 1045 __u8 battery_charging;
1046 __u8 battery_capacity; 1046 __u8 battery_capacity;
1047 __u8 led_state[MAX_LEDS]; 1047 __u8 led_state[MAX_LEDS];
1048 __u8 resume_led_state[MAX_LEDS];
1048 __u8 led_delay_on[MAX_LEDS]; 1049 __u8 led_delay_on[MAX_LEDS];
1049 __u8 led_delay_off[MAX_LEDS]; 1050 __u8 led_delay_off[MAX_LEDS];
1050 __u8 led_count; 1051 __u8 led_count;
@@ -1912,6 +1913,12 @@ static void motion_send_output_report(struct sony_sc *sc)
1912 hid_hw_output_report(hdev, (__u8 *)report, MOTION_REPORT_0x02_SIZE); 1913 hid_hw_output_report(hdev, (__u8 *)report, MOTION_REPORT_0x02_SIZE);
1913} 1914}
1914 1915
1916static inline void sony_send_output_report(struct sony_sc *sc)
1917{
1918 if (sc->send_output_report)
1919 sc->send_output_report(sc);
1920}
1921
1915static void sony_state_worker(struct work_struct *work) 1922static void sony_state_worker(struct work_struct *work)
1916{ 1923{
1917 struct sony_sc *sc = container_of(work, struct sony_sc, state_worker); 1924 struct sony_sc *sc = container_of(work, struct sony_sc, state_worker);
@@ -2427,6 +2434,56 @@ static void sony_remove(struct hid_device *hdev)
2427 hid_hw_stop(hdev); 2434 hid_hw_stop(hdev);
2428} 2435}
2429 2436
2437#ifdef CONFIG_PM
2438
2439static int sony_suspend(struct hid_device *hdev, pm_message_t message)
2440{
2441 /*
2442 * On suspend save the current LED state,
2443 * stop running force-feedback and blank the LEDS.
2444 */
2445 if (SONY_LED_SUPPORT || SONY_FF_SUPPORT) {
2446 struct sony_sc *sc = hid_get_drvdata(hdev);
2447
2448#ifdef CONFIG_SONY_FF
2449 sc->left = sc->right = 0;
2450#endif
2451
2452 memcpy(sc->resume_led_state, sc->led_state,
2453 sizeof(sc->resume_led_state));
2454 memset(sc->led_state, 0, sizeof(sc->led_state));
2455
2456 sony_send_output_report(sc);
2457 }
2458
2459 return 0;
2460}
2461
2462static int sony_resume(struct hid_device *hdev)
2463{
2464 /* Restore the state of controller LEDs on resume */
2465 if (SONY_LED_SUPPORT) {
2466 struct sony_sc *sc = hid_get_drvdata(hdev);
2467
2468 memcpy(sc->led_state, sc->resume_led_state,
2469 sizeof(sc->led_state));
2470
2471 /*
2472 * The Sixaxis and navigation controllers on USB need to be
2473 * reinitialized on resume or they won't behave properly.
2474 */
2475 if ((sc->quirks & SIXAXIS_CONTROLLER_USB) ||
2476 (sc->quirks & NAVIGATION_CONTROLLER_USB))
2477 sixaxis_set_operational_usb(sc->hdev);
2478
2479 sony_set_leds(sc);
2480 }
2481
2482 return 0;
2483}
2484
2485#endif
2486
2430static const struct hid_device_id sony_devices[] = { 2487static const struct hid_device_id sony_devices[] = {
2431 { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER), 2488 { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER),
2432 .driver_data = SIXAXIS_CONTROLLER_USB }, 2489 .driver_data = SIXAXIS_CONTROLLER_USB },
@@ -2476,7 +2533,13 @@ static struct hid_driver sony_driver = {
2476 .probe = sony_probe, 2533 .probe = sony_probe,
2477 .remove = sony_remove, 2534 .remove = sony_remove,
2478 .report_fixup = sony_report_fixup, 2535 .report_fixup = sony_report_fixup,
2479 .raw_event = sony_raw_event 2536 .raw_event = sony_raw_event,
2537
2538#ifdef CONFIG_PM
2539 .suspend = sony_suspend,
2540 .resume = sony_resume,
2541 .reset_resume = sony_resume,
2542#endif
2480}; 2543};
2481 2544
2482static int __init sony_init(void) 2545static int __init sony_init(void)