From patchwork Tue Mar 7 23:45:04 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roderick Colenbrander X-Patchwork-Id: 9609999 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 70A38604DD for ; Tue, 7 Mar 2017 23:46:59 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 610F125F31 for ; Tue, 7 Mar 2017 23:46:59 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 55D5228507; Tue, 7 Mar 2017 23:46:59 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A827527D0E for ; Tue, 7 Mar 2017 23:46:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933271AbdCGXq5 (ORCPT ); Tue, 7 Mar 2017 18:46:57 -0500 Received: from mail-pf0-f171.google.com ([209.85.192.171]:36060 "EHLO mail-pf0-f171.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933258AbdCGXqo (ORCPT ); Tue, 7 Mar 2017 18:46:44 -0500 Received: by mail-pf0-f171.google.com with SMTP id o126so6630226pfb.3 for ; Tue, 07 Mar 2017 15:45:20 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gaikai-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=RViCqleczogdmDhS/Y+Vzii/tld6CaELtVZcLRk64oc=; b=o/R5sXpm49okRC7UI9ag6+c+vebnFd5tJFVJ2j2rZNCPa03PiHL/NLuJ5d2qTStrVF GjG2Deei8C225ELTclawGfTOHLOvCIG+7ytATHMdlwDsJXnryfSC4y3Fi6pAPPsypOFD dDUO7x8kfEgbb3CHT0BcktlzXivJy+7ODJaRWzk9A3+l9Ks6bjF88UmZc0XIZ/c93/rE Z2SP2CYTaFfUWNEuRCvyD29XvLMhomanXRDdbt5TfT6Mm9QVJBM6rTRLo7/torb1/bLW 8Bn+WMgRsJN/t2qf7uHTzEGNCyBDc2Drst0ddW29RcClm93lKnpCAAJL7ws4EpD53ovi 9MFg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=RViCqleczogdmDhS/Y+Vzii/tld6CaELtVZcLRk64oc=; b=j5qFLWId1VJ6g2to14hmt2CCC4s3v2KPB4PeG8nJ07wWmEl5/zZRfy7hyUzNSGI2q7 xUslJgu/L+PuzsTJXpYOUlX7Tc00+crZN7mRl39CvFY2wNOiOGZQhUsF5pOAhK7nKRJG I8MCig65kRT8brw7BkteQgO2G246oxBrRExxVF+nbGsGPhsJl9r5oNlfBzi41hCsYQsb LxYDge/TVj2dHTgHwzikacQYh33iF2NTSle9On+gTTIWUyYGyR5AqBoSRM0cmqtBk9kX mkWtiH+QDByH80IhWSu0v6WODj0S06tPxAkdFaS3a3QHd8pj5zIYeUKYRdau8rrfafus FUeg== X-Gm-Message-State: AMke39kPOYsU+sFARts9zMvNnoEu24/JpU+UGPscNJb6lYq9kt4yugvo9hTigSYugFGZRBjs X-Received: by 10.99.52.79 with SMTP id b76mr3337656pga.131.1488930319754; Tue, 07 Mar 2017 15:45:19 -0800 (PST) Received: from roderick.ad.gaikai.biz ([100.42.98.197]) by smtp.gmail.com with ESMTPSA id e7sm1890993pgp.2.2017.03.07.15.45.18 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 07 Mar 2017 15:45:19 -0800 (PST) From: Roderick Colenbrander To: linux-input@vger.kernel.org Cc: Dmitry Torokhov , Jiri Kosina , Benjamin Tissoires , Simon Wood , Frank Praznik , Tim Bird , Roderick Colenbrander Subject: [PATCH v2 05/12] HID: sony: Treat the ds4 dongle as a separate device Date: Tue, 7 Mar 2017 15:45:04 -0800 Message-Id: <20170307234511.30380-6-roderick@gaikai.com> X-Mailer: git-send-email 2.9.3 In-Reply-To: <20170307234511.30380-1-roderick@gaikai.com> References: <20170307234511.30380-1-roderick@gaikai.com> Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Roderick Colenbrander This patch adds a new quirk, which allows us to differentiate between the DualShock 4 USB and the dongle. So far they have been treated the same, but handling of calibration data differs as the dongle behaves like Bluetooth, for other requests it behaves like USB. In addition this patches changes usb/dongle/bt handling in sony_raw_event, which makes the code cleaner to read. In addition another patch in this series will add more dongle logic, so this change paves the road for that. Signed-off-by: Roderick Colenbrander --- drivers/hid/hid-sony.c | 99 ++++++++++++++++++++++++++------------------------ 1 file changed, 51 insertions(+), 48 deletions(-) diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 7b7e7a8..eff08af 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -48,19 +48,21 @@ #define PS3REMOTE BIT(4) #define DUALSHOCK4_CONTROLLER_USB BIT(5) #define DUALSHOCK4_CONTROLLER_BT BIT(6) -#define MOTION_CONTROLLER_USB BIT(7) -#define MOTION_CONTROLLER_BT BIT(8) -#define NAVIGATION_CONTROLLER_USB BIT(9) -#define NAVIGATION_CONTROLLER_BT BIT(10) -#define SINO_LITE_CONTROLLER BIT(11) -#define FUTUREMAX_DANCE_MAT BIT(12) +#define DUALSHOCK4_DONGLE BIT(7) +#define MOTION_CONTROLLER_USB BIT(8) +#define MOTION_CONTROLLER_BT BIT(9) +#define NAVIGATION_CONTROLLER_USB BIT(10) +#define NAVIGATION_CONTROLLER_BT BIT(11) +#define SINO_LITE_CONTROLLER BIT(12) +#define FUTUREMAX_DANCE_MAT BIT(13) #define SIXAXIS_CONTROLLER (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT) #define MOTION_CONTROLLER (MOTION_CONTROLLER_USB | MOTION_CONTROLLER_BT) #define NAVIGATION_CONTROLLER (NAVIGATION_CONTROLLER_USB |\ NAVIGATION_CONTROLLER_BT) #define DUALSHOCK4_CONTROLLER (DUALSHOCK4_CONTROLLER_USB |\ - DUALSHOCK4_CONTROLLER_BT) + DUALSHOCK4_CONTROLLER_BT | \ + DUALSHOCK4_DONGLE) #define SONY_LED_SUPPORT (SIXAXIS_CONTROLLER | BUZZ_CONTROLLER |\ DUALSHOCK4_CONTROLLER | MOTION_CONTROLLER |\ NAVIGATION_CONTROLLER) @@ -846,7 +848,7 @@ static void dualshock4_parse_report(struct sony_sc *sc, u8 *rd, int size) u16 timestamp; /* When using Bluetooth the header is 2 bytes longer, so skip these. */ - int data_offset = (sc->quirks & DUALSHOCK4_CONTROLLER_USB) ? 0 : 2; + int data_offset = (sc->quirks & DUALSHOCK4_CONTROLLER_BT) ? 2 : 0; /* Second bit of third button byte is for the touchpad button. */ offset = data_offset + DS4_INPUT_REPORT_BUTTON_OFFSET; @@ -979,7 +981,7 @@ static void dualshock4_parse_report(struct sony_sc *sc, u8 *rd, int size) * Trackpad data starts 2 bytes later (e.g. 35 for USB). */ offset = data_offset + DS4_INPUT_REPORT_TOUCHPAD_OFFSET; - max_touch_data = (sc->quirks & DUALSHOCK4_CONTROLLER_USB) ? 3 : 4; + max_touch_data = (sc->quirks & DUALSHOCK4_CONTROLLER_BT) ? 4 : 3; if (rd[offset] > 0 && rd[offset] <= max_touch_data) num_touch_data = rd[offset]; else @@ -1053,47 +1055,47 @@ static int sony_raw_event(struct hid_device *hdev, struct hid_report *report, } else if ((sc->quirks & NAVIGATION_CONTROLLER) && rd[0] == 0x01 && size == 49) { sixaxis_parse_report(sc, rd, size); - } else if (((sc->quirks & DUALSHOCK4_CONTROLLER_USB) && rd[0] == 0x01 && - size == 64) || ((sc->quirks & DUALSHOCK4_CONTROLLER_BT) - && rd[0] == 0x11 && size == 78)) { - if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) { - /* CRC check */ - u8 bthdr = 0xA1; - u32 crc; - u32 report_crc; + } else if ((sc->quirks & DUALSHOCK4_CONTROLLER_USB) && rd[0] == 0x01 && + size == 64) { + dualshock4_parse_report(sc, rd, size); + } else if (((sc->quirks & DUALSHOCK4_CONTROLLER_BT) && rd[0] == 0x11 && + size == 78)) { + /* CRC check */ + u8 bthdr = 0xA1; + u32 crc; + u32 report_crc; - crc = crc32_le(0xFFFFFFFF, &bthdr, 1); - crc = ~crc32_le(crc, rd, DS4_INPUT_REPORT_0x11_SIZE-4); - report_crc = get_unaligned_le32(&rd[DS4_INPUT_REPORT_0x11_SIZE-4]); - if (crc != report_crc) { - hid_dbg(sc->hdev, "DualShock 4 input report's CRC check failed, received crc 0x%0x != 0x%0x\n", - report_crc, crc); - return -EILSEQ; - } + crc = crc32_le(0xFFFFFFFF, &bthdr, 1); + crc = ~crc32_le(crc, rd, DS4_INPUT_REPORT_0x11_SIZE-4); + report_crc = get_unaligned_le32(&rd[DS4_INPUT_REPORT_0x11_SIZE-4]); + if (crc != report_crc) { + hid_dbg(sc->hdev, "DualShock 4 input report's CRC check failed, received crc 0x%0x != 0x%0x\n", + report_crc, crc); + return -EILSEQ; } + dualshock4_parse_report(sc, rd, size); + } else if ((sc->quirks & DUALSHOCK4_DONGLE) && rd[0] == 0x01 && + size == 64) { /* * In the case of a DS4 USB dongle, bit[2] of byte 31 indicates * if a DS4 is actually connected (indicated by '0'). * For non-dongle, this bit is always 0 (connected). */ - if (sc->hdev->vendor == USB_VENDOR_ID_SONY && - sc->hdev->product == USB_DEVICE_ID_SONY_PS4_CONTROLLER_DONGLE) { - bool connected = (rd[31] & 0x04) ? false : true; - - if (!sc->ds4_dongle_connected && connected) { - hid_info(sc->hdev, "DualShock 4 USB dongle: controller connected\n"); - sony_set_leds(sc); - sc->ds4_dongle_connected = true; - } else if (sc->ds4_dongle_connected && !connected) { - hid_info(sc->hdev, "DualShock 4 USB dongle: controller disconnected\n"); - sc->ds4_dongle_connected = false; - /* Return 0, so hidraw can get the report. */ - return 0; - } else if (!sc->ds4_dongle_connected) { - /* Return 0, so hidraw can get the report. */ - return 0; - } + bool connected = (rd[31] & 0x04) ? false : true; + + if (!sc->ds4_dongle_connected && connected) { + hid_info(sc->hdev, "DualShock 4 USB dongle: controller connected\n"); + sony_set_leds(sc); + sc->ds4_dongle_connected = true; + } else if (sc->ds4_dongle_connected && !connected) { + hid_info(sc->hdev, "DualShock 4 USB dongle: controller disconnected\n"); + sc->ds4_dongle_connected = false; + /* Return 0, so hidraw can get the report. */ + return 0; + } else if (!sc->ds4_dongle_connected) { + /* Return 0, so hidraw can get the report. */ + return 0; } dualshock4_parse_report(sc, rd, size); @@ -1386,7 +1388,7 @@ static int dualshock4_get_calibration_data(struct sony_sc *sc) * Note: in Bluetooth mode feature report 0x02 also changes the state * of the controller, so that it sends input reports of type 0x11. */ - if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) { + if (sc->quirks & (DUALSHOCK4_CONTROLLER_USB | DUALSHOCK4_DONGLE)) { buf = kmalloc(DS4_FEATURE_REPORT_0x02_SIZE, GFP_KERNEL); if (!buf) return -ENOMEM; @@ -1446,6 +1448,7 @@ static int dualshock4_get_calibration_data(struct sony_sc *sc) gyro_roll_plus = get_unaligned_le16(&buf[15]); gyro_roll_minus = get_unaligned_le16(&buf[17]); } else { + /* BT + Dongle */ gyro_pitch_plus = get_unaligned_le16(&buf[7]); gyro_yaw_plus = get_unaligned_le16(&buf[9]); gyro_roll_plus = get_unaligned_le16(&buf[11]); @@ -1904,7 +1907,7 @@ static void dualshock4_send_output_report(struct sony_sc *sc) * 0xB0 - 20hz * 0xD0 - 66hz */ - if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) { + if (sc->quirks & (DUALSHOCK4_CONTROLLER_USB | DUALSHOCK4_DONGLE)) { memset(buf, 0, DS4_OUTPUT_REPORT_0x05_SIZE); buf[0] = 0x05; buf[1] = 0xFF; @@ -1937,7 +1940,7 @@ static void dualshock4_send_output_report(struct sony_sc *sc) buf[offset++] = sc->led_delay_on[3]; buf[offset++] = sc->led_delay_off[3]; - if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) + if (sc->quirks & (DUALSHOCK4_CONTROLLER_USB | DUALSHOCK4_DONGLE)) hid_hw_output_report(hdev, buf, DS4_OUTPUT_REPORT_0x05_SIZE); else { /* CRC generation */ @@ -1994,7 +1997,7 @@ static int sony_allocate_output_report(struct sony_sc *sc) else if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) sc->output_report_dmabuf = kmalloc(DS4_OUTPUT_REPORT_0x11_SIZE, GFP_KERNEL); - else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) + else if (sc->quirks & (DUALSHOCK4_CONTROLLER_USB | DUALSHOCK4_DONGLE)) sc->output_report_dmabuf = kmalloc(DS4_OUTPUT_REPORT_0x05_SIZE, GFP_KERNEL); else if (sc->quirks & MOTION_CONTROLLER) @@ -2239,7 +2242,7 @@ static int sony_check_add(struct sony_sc *sc) hid_warn(sc->hdev, "UNIQ does not contain a MAC address; duplicate check skipped\n"); return 0; } - } else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) { + } else if (sc->quirks & (DUALSHOCK4_CONTROLLER_USB | DUALSHOCK4_DONGLE)) { buf = kmalloc(DS4_FEATURE_REPORT_0x81_SIZE, GFP_KERNEL); if (!buf) return -ENOMEM; @@ -2666,7 +2669,7 @@ static const struct hid_device_id sony_devices[] = { { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER_2), .driver_data = DUALSHOCK4_CONTROLLER_BT }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER_DONGLE), - .driver_data = DUALSHOCK4_CONTROLLER_USB }, + .driver_data = DUALSHOCK4_DONGLE }, /* Nyko Core Controller for PS3 */ { HID_USB_DEVICE(USB_VENDOR_ID_SINO_LITE, USB_DEVICE_ID_SINO_LITE_CONTROLLER), .driver_data = SIXAXIS_CONTROLLER_USB | SINO_LITE_CONTROLLER },