aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrank Praznik <frank.praznik@gmail.com>2016-09-22 20:18:09 -0400
committerJiri Kosina <jkosina@suse.cz>2016-09-26 09:32:48 -0400
commit2a2429327711558aa23fd73d770b6fd5e0d10de7 (patch)
treefd42dce5f1bcc1d6480da5dec1c9c16a0f9e67dc
parent0f3982308b5fc7373c8d4e6dcfc8a02ee5a3408d (diff)
HID: sony: Defer the initial USB Sixaxis output report
When initially connected via USB the Sixaxis isn't fully initialized until the PS logo button is pressed and won't send any input reports nor will any state set by output reports be retained. This adds a 'defer_initialization' flag to the sony_sc struct which, when set, will delay sending any output reports until the first input report has arrived. This flag is used with the USB Sixaxis to ensure that any state sent will persist since, until the PS button is pushed, any changes sent to the controller via an output report will be lost after a couple of seconds. The initial state of the controller is still configured at the time of the initial connection and won't be internally modified after that, so any state set by the user between that time and the recepit of the first input report won't be lost. Signed-off-by: Frank Praznik <frank.praznik@gmail.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r--drivers/hid/hid-sony.c29
1 files changed, 25 insertions, 4 deletions
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index 92f27b7d892a..9b96f9570531 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -1050,6 +1050,7 @@ struct sony_sc {
1050 1050
1051 u8 mac_address[6]; 1051 u8 mac_address[6];
1052 u8 worker_initialized; 1052 u8 worker_initialized;
1053 u8 defer_initialization;
1053 u8 cable_state; 1054 u8 cable_state;
1054 u8 battery_charging; 1055 u8 battery_charging;
1055 u8 battery_capacity; 1056 u8 battery_capacity;
@@ -1060,6 +1061,12 @@ struct sony_sc {
1060 u8 led_count; 1061 u8 led_count;
1061}; 1062};
1062 1063
1064static inline void sony_schedule_work(struct sony_sc *sc)
1065{
1066 if (!sc->defer_initialization)
1067 schedule_work(&sc->state_worker);
1068}
1069
1063static u8 *sixaxis_fixup(struct hid_device *hdev, u8 *rdesc, 1070static u8 *sixaxis_fixup(struct hid_device *hdev, u8 *rdesc,
1064 unsigned int *rsize) 1071 unsigned int *rsize)
1065{ 1072{
@@ -1319,6 +1326,11 @@ static int sony_raw_event(struct hid_device *hdev, struct hid_report *report,
1319 dualshock4_parse_report(sc, rd, size); 1326 dualshock4_parse_report(sc, rd, size);
1320 } 1327 }
1321 1328
1329 if (sc->defer_initialization) {
1330 sc->defer_initialization = 0;
1331 sony_schedule_work(sc);
1332 }
1333
1322 return 0; 1334 return 0;
1323} 1335}
1324 1336
@@ -1556,7 +1568,7 @@ static void buzz_set_leds(struct sony_sc *sc)
1556static void sony_set_leds(struct sony_sc *sc) 1568static void sony_set_leds(struct sony_sc *sc)
1557{ 1569{
1558 if (!(sc->quirks & BUZZ_CONTROLLER)) 1570 if (!(sc->quirks & BUZZ_CONTROLLER))
1559 schedule_work(&sc->state_worker); 1571 sony_schedule_work(sc);
1560 else 1572 else
1561 buzz_set_leds(sc); 1573 buzz_set_leds(sc);
1562} 1574}
@@ -1667,7 +1679,7 @@ static int sony_led_blink_set(struct led_classdev *led, unsigned long *delay_on,
1667 new_off != drv_data->led_delay_off[n]) { 1679 new_off != drv_data->led_delay_off[n]) {
1668 drv_data->led_delay_on[n] = new_on; 1680 drv_data->led_delay_on[n] = new_on;
1669 drv_data->led_delay_off[n] = new_off; 1681 drv_data->led_delay_off[n] = new_off;
1670 schedule_work(&drv_data->state_worker); 1682 sony_schedule_work(drv_data);
1671 } 1683 }
1672 1684
1673 return 0; 1685 return 0;
@@ -1978,7 +1990,7 @@ static int sony_play_effect(struct input_dev *dev, void *data,
1978 sc->left = effect->u.rumble.strong_magnitude / 256; 1990 sc->left = effect->u.rumble.strong_magnitude / 256;
1979 sc->right = effect->u.rumble.weak_magnitude / 256; 1991 sc->right = effect->u.rumble.weak_magnitude / 256;
1980 1992
1981 schedule_work(&sc->state_worker); 1993 sony_schedule_work(sc);
1982 return 0; 1994 return 0;
1983} 1995}
1984 1996
@@ -2365,9 +2377,16 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
2365 * the Sixaxis does not want the report_id as part of the data 2377 * the Sixaxis does not want the report_id as part of the data
2366 * packet, so we have to discard buf[0] when sending the actual 2378 * packet, so we have to discard buf[0] when sending the actual
2367 * control message, even for numbered reports, humpf! 2379 * control message, even for numbered reports, humpf!
2380 *
2381 * Additionally, the Sixaxis on USB isn't properly initialized
2382 * until the PS logo button is pressed and as such won't retain
2383 * any state set by an output report, so the initial
2384 * configuration report is deferred until the first input
2385 * report arrives.
2368 */ 2386 */
2369 hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP; 2387 hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP;
2370 hdev->quirks |= HID_QUIRK_SKIP_OUTPUT_REPORT_ID; 2388 hdev->quirks |= HID_QUIRK_SKIP_OUTPUT_REPORT_ID;
2389 sc->defer_initialization = 1;
2371 ret = sixaxis_set_operational_usb(hdev); 2390 ret = sixaxis_set_operational_usb(hdev);
2372 sony_init_output_report(sc, sixaxis_send_output_report); 2391 sony_init_output_report(sc, sixaxis_send_output_report);
2373 } else if ((sc->quirks & SIXAXIS_CONTROLLER_BT) || 2392 } else if ((sc->quirks & SIXAXIS_CONTROLLER_BT) ||
@@ -2510,8 +2529,10 @@ static int sony_resume(struct hid_device *hdev)
2510 * reinitialized on resume or they won't behave properly. 2529 * reinitialized on resume or they won't behave properly.
2511 */ 2530 */
2512 if ((sc->quirks & SIXAXIS_CONTROLLER_USB) || 2531 if ((sc->quirks & SIXAXIS_CONTROLLER_USB) ||
2513 (sc->quirks & NAVIGATION_CONTROLLER_USB)) 2532 (sc->quirks & NAVIGATION_CONTROLLER_USB)) {
2514 sixaxis_set_operational_usb(sc->hdev); 2533 sixaxis_set_operational_usb(sc->hdev);
2534 sc->defer_initialization = 1;
2535 }
2515 2536
2516 sony_set_leds(sc); 2537 sony_set_leds(sc);
2517 } 2538 }