From patchwork Sat Jan 2 22:30:58 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roderick Colenbrander X-Patchwork-Id: 356023 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 73591C433E6 for ; Sat, 2 Jan 2021 22:32:17 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 48F25207A1 for ; Sat, 2 Jan 2021 22:32:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726785AbhABWcQ (ORCPT ); Sat, 2 Jan 2021 17:32:16 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59130 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726733AbhABWcQ (ORCPT ); Sat, 2 Jan 2021 17:32:16 -0500 Received: from mail-pj1-x1032.google.com (mail-pj1-x1032.google.com [IPv6:2607:f8b0:4864:20::1032]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0DDBBC0613CF for ; Sat, 2 Jan 2021 14:31:36 -0800 (PST) Received: by mail-pj1-x1032.google.com with SMTP id lb18so7606602pjb.5 for ; Sat, 02 Jan 2021 14:31:36 -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 :mime-version:content-transfer-encoding; bh=HPQz+QwfnJyzFbnRyga6cbDeTR0CM+5fgXx2r5TdQE4=; b=G5KeXsmgKi/9Uew52Mz7zqlOxuFn08avf7ndreNBzbKBfnNjvL4tMvvDr+Vs5RQXUN Hrmvi/U9fEi8sC4ds8TZxQKHv0M3oIaORT3YqtSdc8LFPwKVmDRN7KHYZ3MC1Y5G3RN0 7jNVNJEYjIpA9ci/NP26lUyvFRsemmJTn1irT/QvrVhQQZviqHgmMuW58AgLPrS2mfHs NsBrtY5AiKmUK64m+/supKU22TRytVQ3WsUcM0fOaVXQ3vBEMRUNH/eFWOH06Y8PhWJN +/rCemNR/DbnUz4KQdNXnx4hGQrfbEVOsFpJ0w8r2SqGht+ODTedPG5gXef+mKWBxFf8 jELQ== 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:mime-version:content-transfer-encoding; bh=HPQz+QwfnJyzFbnRyga6cbDeTR0CM+5fgXx2r5TdQE4=; b=TIuNE9J1GQ2mROxkYaJvoykzCsTwQwDxPYIGgdlT1p9551XBWZraK9EsZ27uUNKKAf odlIkgVdkF8d39N+WdGf5sSJ64ZotwGy5OQdM/4rlBwndRDYHaCS6Psc7Q1o3/yA96jD A3URpqht1SPCE70og/kf/55h9lNlMACqcR4tDye7LAAB21vq7J9RFjfSafRSHGyTy+vL LA1KlU7YmT4b+Rc3G9C5hqoA24iX9epZtczInP6WvMP18igXSJfxJxASgG131dF+XxSZ btoaw8dXhaNTglIRWYC/4pu22QAq+ic+c0909d7F/gb2zKh5RuL+8cPj/Vve2jfpAXic Mwfw== X-Gm-Message-State: AOAM533aawWddg27p0kJJcyxwvYmqFDjtwf4fXWUabchX1GR+VL/Njcv p9rF5lSAwA7mQJdzNLOs3hlpbw== X-Google-Smtp-Source: ABdhPJwILHGWq1+jMBg6z39gd56DLI7KQi4345qNTOhJQBYAlFIyzUiCvBcIuouvJh9d6nngQXqTPQ== X-Received: by 2002:a17:90a:fa81:: with SMTP id cu1mr23307965pjb.39.1609626695533; Sat, 02 Jan 2021 14:31:35 -0800 (PST) Received: from localhost.localdomain (cpe-76-87-77-78.socal.res.rr.com. [76.87.77.78]) by smtp.gmail.com with ESMTPSA id r20sm49537931pgb.3.2021.01.02.14.31.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 02 Jan 2021 14:31:35 -0800 (PST) From: Roderick Colenbrander To: Jiri Kosina , Benjamin Tissoires Cc: linux-input@vger.kernel.org, Chris Ye , Roderick Colenbrander Subject: [PATCH v2 02/13] HID: playstation: use DualSense MAC address as unique identifier. Date: Sat, 2 Jan 2021 14:30:58 -0800 Message-Id: <20210102223109.996781-3-roderick@gaikai.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210102223109.996781-1-roderick@gaikai.com> References: <20210102223109.996781-1-roderick@gaikai.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org From: Roderick Colenbrander Use the DualSense MAC address as a unique identifier for the HID device. Signed-off-by: Roderick Colenbrander --- drivers/hid/hid-playstation.c | 40 +++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/drivers/hid/hid-playstation.c b/drivers/hid/hid-playstation.c index 3d5fe9069c26..af4a635997bb 100644 --- a/drivers/hid/hid-playstation.c +++ b/drivers/hid/hid-playstation.c @@ -21,12 +21,16 @@ /* Base class for playstation devices. */ struct ps_device { struct hid_device *hdev; + uint8_t mac_address[6]; int (*parse_report)(struct ps_device *dev, struct hid_report *report, u8 *data, int size); }; #define DS_INPUT_REPORT_USB 0x01 +#define DS_FEATURE_REPORT_PAIRING_INFO 9 +#define DS_FEATURE_REPORT_PAIRING_INFO_SIZE 19 + /* Button masks for DualSense input report. */ #define DS_BUTTONS0_HAT_SWITCH GENMASK(3, 0) #define DS_BUTTONS0_SQUARE BIT(4) @@ -132,6 +136,7 @@ static struct input_dev *ps_allocate_input_dev(struct hid_device *hdev, const ch return input_dev; } + static struct input_dev *ps_gamepad_create(struct hid_device *hdev) { struct input_dev *gamepad; @@ -162,6 +167,34 @@ static struct input_dev *ps_gamepad_create(struct hid_device *hdev) return gamepad; } +static int dualsense_get_mac_address(struct dualsense *ds) +{ + uint8_t *buf; + int ret = 0; + + buf = kzalloc(DS_FEATURE_REPORT_PAIRING_INFO_SIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + ret = hid_hw_raw_request(ds->base.hdev, DS_FEATURE_REPORT_PAIRING_INFO, buf, + DS_FEATURE_REPORT_PAIRING_INFO_SIZE, HID_FEATURE_REPORT, + HID_REQ_GET_REPORT); + if (ret < 0) + goto err_free; + else if (ret != DS_FEATURE_REPORT_PAIRING_INFO_SIZE) { + hid_err(ds->base.hdev, "failed to retrieve DualSense pairing info\n"); + ret = -EINVAL; + goto err_free; + } + + /* Note MAC address is stored in little endian order. */ + memcpy(ds->base.mac_address, &buf[1], sizeof(ds->base.mac_address)); + +err_free: + kfree(buf); + return ret; +} + static int dualsense_parse_report(struct ps_device *ps_dev, struct hid_report *report, u8 *data, int size) { @@ -230,6 +263,13 @@ static struct ps_device *dualsense_create(struct hid_device *hdev) ds->base.parse_report = dualsense_parse_report; hid_set_drvdata(hdev, ds); + ret = dualsense_get_mac_address(ds); + if (ret < 0) { + hid_err(hdev, "Failed to get MAC address from DualSense\n"); + return ERR_PTR(ret); + } + snprintf(hdev->uniq, sizeof(hdev->uniq), "%pMR", ds->base.mac_address); + ds->gamepad = ps_gamepad_create(hdev); if (IS_ERR(ds->gamepad)) { ret = PTR_ERR(ds->gamepad); From patchwork Sat Jan 2 22:31:00 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roderick Colenbrander X-Patchwork-Id: 356022 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6D4DEC43381 for ; Sat, 2 Jan 2021 22:32:19 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 41012207A1 for ; Sat, 2 Jan 2021 22:32:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726822AbhABWcS (ORCPT ); Sat, 2 Jan 2021 17:32:18 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59138 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726733AbhABWcS (ORCPT ); Sat, 2 Jan 2021 17:32:18 -0500 Received: from mail-pj1-x1036.google.com (mail-pj1-x1036.google.com [IPv6:2607:f8b0:4864:20::1036]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E45B1C0613ED for ; Sat, 2 Jan 2021 14:31:37 -0800 (PST) Received: by mail-pj1-x1036.google.com with SMTP id n3so4115631pjm.1 for ; Sat, 02 Jan 2021 14:31:37 -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 :mime-version:content-transfer-encoding; bh=ZJ2TAMT9tEUax5Sl+5+xGLS93MsUJkzcH2wYIIGrKko=; b=zecV1JbAeJnFEAVwZkLhkMZOg0KZPW9Bgm8b3snwpzfmX5Fy+ScFjxQs/RbTDFEG/e 9GaJY6D1iCzB1LWJxaVulzzoeif46aIuswGJs7WQ58EqLxC28cySkxdQ81RieS4hp3bF fyIBiwUtb1b1PQ7WLqhNaB5NmSWJhRNdFmACj/rz/TW/ouskottQk0DtB0aq/71MqJue MG0DLo2GbVVO/MCfphFUO5FOGdMGm/jsKsD9Giqa/nGjEtu60hYukob8Py9/wd7gD+yF wEWz9CwW7ia3eXB2F/8B6abACF4xX/ZspF5UpVEjH0KHQeDHCz6OjAzsdS+fJGNLZupR NuiQ== 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:mime-version:content-transfer-encoding; bh=ZJ2TAMT9tEUax5Sl+5+xGLS93MsUJkzcH2wYIIGrKko=; b=bhTadqf7QAeiRadl3SL47OkIAZftd4gOyiFuOkwGsVp1rPkWDcze24qs3HsUy8q6x/ lunyr84uU6UbJnOxgnuFEIIJIyLQ975ofFlgjnb6FqNa0FiqknC9KgEbBy3xp9KCGsEn QTBOhoxqxkZmvTK3NPXAGYgsBDcf1fxRWWfqFJhzrlNxfgk+QBlTx5za0Tom76ob4YZ7 muyh8eDv4fEuWu+54QZXqeOs+GrZV+hR9TUNmmvN176MIM+XyQA0oHXbkA51pm/M9Pi2 1pKR70wROeAe03C9Jwg8/HcP8uMqxDlmHuyqmaNs4aW3GPuzokycp+/kRJ6ltJoG/lXy PLfQ== X-Gm-Message-State: AOAM532gqktFpb52Oix3Sf443qoUbQv4R/p802JJGTIBJLxt199hySZJ COmVBja8kqWZE9b0F4XpTJc3iA== X-Google-Smtp-Source: ABdhPJw2swgf8mSs7CB1v60PHI2ufyw6UtRgrFJcbbxwa2hor2xX3WxjDBQ85lDfKWEDu5fYq2iXxA== X-Received: by 2002:a17:90b:46ca:: with SMTP id jx10mr23582202pjb.208.1609626697527; Sat, 02 Jan 2021 14:31:37 -0800 (PST) Received: from localhost.localdomain (cpe-76-87-77-78.socal.res.rr.com. [76.87.77.78]) by smtp.gmail.com with ESMTPSA id r20sm49537931pgb.3.2021.01.02.14.31.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 02 Jan 2021 14:31:37 -0800 (PST) From: Roderick Colenbrander To: Jiri Kosina , Benjamin Tissoires Cc: linux-input@vger.kernel.org, Chris Ye , Roderick Colenbrander Subject: [PATCH v2 04/13] HID: playstation: add DualSense touchpad support. Date: Sat, 2 Jan 2021 14:31:00 -0800 Message-Id: <20210102223109.996781-5-roderick@gaikai.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210102223109.996781-1-roderick@gaikai.com> References: <20210102223109.996781-1-roderick@gaikai.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org From: Roderick Colenbrander Implement support for DualSense touchpad as a separate input device. Signed-off-by: Roderick Colenbrander --- drivers/hid/hid-playstation.c | 64 +++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/drivers/hid/hid-playstation.c b/drivers/hid/hid-playstation.c index 2fc798d2a8af..06e946c45c64 100644 --- a/drivers/hid/hid-playstation.c +++ b/drivers/hid/hid-playstation.c @@ -60,9 +60,20 @@ struct ps_device { #define DS_STATUS_CHARGING GENMASK(7, 4) #define DS_STATUS_CHARGING_SHIFT 4 +/* Status of a DualSense touch point contact. + * Contact IDs, with highest bit set are 'inactive' + * and any associated data is then invalid. + */ +#define DS_TOUCH_POINT_INACTIVE BIT(7) + +/* DualSense hardware limits */ +#define DS_TOUCHPAD_WIDTH 1920 +#define DS_TOUCHPAD_HEIGHT 1080 + struct dualsense { struct ps_device base; struct input_dev *gamepad; + struct input_dev *touchpad; }; struct dualsense_touch_point { @@ -244,6 +255,34 @@ static struct input_dev *ps_gamepad_create(struct hid_device *hdev) return gamepad; } +static struct input_dev *ps_touchpad_create(struct hid_device *hdev, int width, int height, + unsigned int num_contacts) +{ + struct input_dev *touchpad; + int ret; + + touchpad = ps_allocate_input_dev(hdev, "Touchpad"); + if (IS_ERR(touchpad)) + return ERR_PTR(-ENOMEM); + + /* Map button underneath touchpad to BTN_LEFT. */ + input_set_capability(touchpad, EV_KEY, BTN_LEFT); + __set_bit(INPUT_PROP_BUTTONPAD, touchpad->propbit); + + input_set_abs_params(touchpad, ABS_MT_POSITION_X, 0, width - 1, 0, 0); + input_set_abs_params(touchpad, ABS_MT_POSITION_Y, 0, height - 1, 0, 0); + + ret = input_mt_init_slots(touchpad, num_contacts, INPUT_MT_POINTER); + if (ret) + return ERR_PTR(ret); + + ret = input_register_device(touchpad); + if (ret) + return ERR_PTR(ret); + + return touchpad; +} + static int dualsense_get_mac_address(struct dualsense *ds) { uint8_t *buf; @@ -281,6 +320,7 @@ static int dualsense_parse_report(struct ps_device *ps_dev, struct hid_report *r uint8_t battery_data, battery_capacity, charging_status, value; int battery_status; unsigned long flags; + int i; /* DualSense in USB uses the full HID report for reportID 1, but * Bluetooth uses a minimal HID report for reportID 1 and reports @@ -321,6 +361,24 @@ static int dualsense_parse_report(struct ps_device *ps_dev, struct hid_report *r input_report_key(ds->gamepad, BTN_MODE, ds_report->buttons[2] & DS_BUTTONS2_PS_HOME); input_sync(ds->gamepad); + for (i = 0; i < 2; i++) { + bool active = (ds_report->points[i].contact & DS_TOUCH_POINT_INACTIVE) ? false : true; + + input_mt_slot(ds->touchpad, i); + input_mt_report_slot_state(ds->touchpad, MT_TOOL_FINGER, active); + + if (active) { + int x = (ds_report->points[i].x_hi << 8) | ds_report->points[i].x_lo; + int y = (ds_report->points[i].y_hi << 4) | ds_report->points[i].y_lo; + + input_report_abs(ds->touchpad, ABS_MT_POSITION_X, x); + input_report_abs(ds->touchpad, ABS_MT_POSITION_Y, y); + } + } + input_mt_sync_frame(ds->touchpad); + input_report_key(ds->touchpad, BTN_LEFT, ds_report->buttons[2] & DS_BUTTONS2_TOUCHPAD); + input_sync(ds->touchpad); + battery_data = ds_report->status & DS_STATUS_BATTERY_CAPACITY; charging_status = (ds_report->status & DS_STATUS_CHARGING) >> DS_STATUS_CHARGING_SHIFT; @@ -394,6 +452,12 @@ static struct ps_device *dualsense_create(struct hid_device *hdev) goto err; } + ds->touchpad = ps_touchpad_create(hdev, DS_TOUCHPAD_WIDTH, DS_TOUCHPAD_HEIGHT, 2); + if (IS_ERR(ds->touchpad)) { + ret = PTR_ERR(ds->touchpad); + goto err; + } + ret = ps_device_register_battery(ps_dev); if (ret < 0) goto err; From patchwork Sat Jan 2 22:31:02 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roderick Colenbrander X-Patchwork-Id: 356021 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0A173C433E0 for ; Sat, 2 Jan 2021 22:32:57 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id D79CD207A5 for ; Sat, 2 Jan 2021 22:32:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726837AbhABWc4 (ORCPT ); Sat, 2 Jan 2021 17:32:56 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59238 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726766AbhABWcz (ORCPT ); Sat, 2 Jan 2021 17:32:55 -0500 Received: from mail-pl1-x630.google.com (mail-pl1-x630.google.com [IPv6:2607:f8b0:4864:20::630]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CDD5BC061795 for ; Sat, 2 Jan 2021 14:31:39 -0800 (PST) Received: by mail-pl1-x630.google.com with SMTP id v3so12447223plz.13 for ; Sat, 02 Jan 2021 14:31:39 -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 :mime-version:content-transfer-encoding; bh=KCweL6Qig7RJ+65JoXarNe44zFqX3DH84uwrsxo8p88=; b=gQzKpQtRJd7vOemBwqgmYlGRzL5Bm+u785xzpea0ErGN8H0B15AqOWRsGpWOgLNyFo gL9P7lSCfOnWSoOwyCFswPWn1QP8+1fIHI9+L9dhFuTvZ9qmEY4eQvI5WFUy5iC2EXGX LjSdQBs16H5Yb3MTTrT+yjK9TGyTrcKDNe7IRIH55oVQppkTPScYgGgfdEJY2Td9yAnA wCu5VS9u6LjwIY4C5MBGpINNi0GcrZwqbBOlN6Z9YTVAwgQvRiRdSSJMwtOZsHrizfAv LY9j9saR6TG/FERTHSx3cLlfc0+aNK9T1ryY4+GF6npTvdL/kCyDrU9xfWfNCUufWrcb LcXA== 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:mime-version:content-transfer-encoding; bh=KCweL6Qig7RJ+65JoXarNe44zFqX3DH84uwrsxo8p88=; b=BJtJf1z+dWHvUBlrpzEpAKUagJwO2ocg95NoHQ/bvl57+kGaC/5suPy2Cy5U2Cpti6 Inp1YcsflI2jWpgYS+0PcL+cjHrBbC0K5qfZeCWbb/zzaG+5MZH755J4ryUpgk+7f7V+ XowcPILRvl4TkHWMU5tsowPgCsQbliC4TvjHlXeRAOejF7r9V4gkeTFYqC6eqLGSjq3t NaOdIm/HyD2jFbg281x9eYOb6TewroF/iZr/Yx+tfam2N1S0ii95j1HeLonwPZJa2y7L JUD7mfSsltNREajf3aw8A7wzpCCQoSIWIBEw9D49CtJu051PR/dI6xXrFGVASZsJNq8p tUsA== X-Gm-Message-State: AOAM533vhm/7fa/mm4Wjok3zmRq4EBXIdNnzxAcDdWjHz/xSex3fJBc+ FX7rpeJAEFhk6pasLbyw/L5il9hzB0kZpQ== X-Google-Smtp-Source: ABdhPJwlYyiYOUxtrMAoaHcG5wCQwTrGB8GzAZpxOnxVKIAbCqVw68u4RGbElOr/FOY/QcTWasDtQA== X-Received: by 2002:a17:90a:e60d:: with SMTP id j13mr23743628pjy.52.1609626699403; Sat, 02 Jan 2021 14:31:39 -0800 (PST) Received: from localhost.localdomain (cpe-76-87-77-78.socal.res.rr.com. [76.87.77.78]) by smtp.gmail.com with ESMTPSA id r20sm49537931pgb.3.2021.01.02.14.31.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 02 Jan 2021 14:31:39 -0800 (PST) From: Roderick Colenbrander To: Jiri Kosina , Benjamin Tissoires Cc: linux-input@vger.kernel.org, Chris Ye , Roderick Colenbrander Subject: [PATCH v2 06/13] HID: playstation: track devices in list. Date: Sat, 2 Jan 2021 14:31:02 -0800 Message-Id: <20210102223109.996781-7-roderick@gaikai.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210102223109.996781-1-roderick@gaikai.com> References: <20210102223109.996781-1-roderick@gaikai.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org From: Roderick Colenbrander Track devices in a list, so we can detect when a device is connected twice when using Bluetooth and USB. Signed-off-by: Roderick Colenbrander --- drivers/hid/hid-playstation.c | 45 +++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/drivers/hid/hid-playstation.c b/drivers/hid/hid-playstation.c index 80b0dcdbfe41..91f3ed005fce 100644 --- a/drivers/hid/hid-playstation.c +++ b/drivers/hid/hid-playstation.c @@ -16,10 +16,15 @@ #include "hid-ids.h" +/* List of connected playstation devices. */ +static DEFINE_MUTEX(ps_devices_lock); +static LIST_HEAD(ps_devices_list); + #define HID_PLAYSTATION_VERSION_PATCH 0x8000 /* Base class for playstation devices. */ struct ps_device { + struct list_head list; struct hid_device *hdev; spinlock_t lock; @@ -155,6 +160,37 @@ static const struct {int x; int y; } ps_gamepad_hat_mapping[] = { {0, 0} }; +/* Add a new ps_device to ps_devices if it doesn't exist. + * Return error on duplicate device, which can happen if the same + * device is connected using both Bluetooth and USB. + */ +static int ps_devices_list_add(struct ps_device *dev) +{ + struct ps_device *entry; + + mutex_lock(&ps_devices_lock); + list_for_each_entry(entry, &ps_devices_list, list) { + if (!memcmp(entry->mac_address, dev->mac_address, sizeof(dev->mac_address))) { + hid_err(dev->hdev, "Duplicate device found for MAC address %pMR\n", + dev->mac_address); + mutex_unlock(&ps_devices_lock); + return -EEXIST; + } + } + + list_add_tail(&dev->list, &ps_devices_list); + mutex_unlock(&ps_devices_lock); + return 0; +} + +static int ps_devices_list_remove(struct ps_device *dev) +{ + mutex_lock(&ps_devices_lock); + list_del(&dev->list); + mutex_unlock(&ps_devices_lock); + return 0; +} + static struct input_dev *ps_allocate_input_dev(struct hid_device *hdev, const char *name_suffix) { struct input_dev *input_dev; @@ -635,6 +671,10 @@ static struct ps_device *dualsense_create(struct hid_device *hdev) } snprintf(hdev->uniq, sizeof(hdev->uniq), "%pMR", ds->base.mac_address); + ret = ps_devices_list_add(ps_dev); + if (ret < 0) + return ERR_PTR(ret); + ret = dualsense_get_calibration_data(ds); if (ret < 0) { hid_err(hdev, "Failed to get calibration data from DualSense\n"); @@ -667,6 +707,7 @@ static struct ps_device *dualsense_create(struct hid_device *hdev) return &ds->base; err: + ps_devices_list_remove(ps_dev); return ERR_PTR(ret); } @@ -724,6 +765,10 @@ static int ps_probe(struct hid_device *hdev, const struct hid_device_id *id) static void ps_remove(struct hid_device *hdev) { + struct ps_device *dev = hid_get_drvdata(hdev); + + ps_devices_list_remove(dev); + hid_hw_close(hdev); hid_hw_stop(hdev); } From patchwork Sat Jan 2 22:31:03 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roderick Colenbrander X-Patchwork-Id: 356020 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A4BD7C433E6 for ; Sat, 2 Jan 2021 22:32:57 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 77BA520798 for ; Sat, 2 Jan 2021 22:32:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726847AbhABWc4 (ORCPT ); Sat, 2 Jan 2021 17:32:56 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59240 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726733AbhABWc4 (ORCPT ); Sat, 2 Jan 2021 17:32:56 -0500 Received: from mail-pl1-x62c.google.com (mail-pl1-x62c.google.com [IPv6:2607:f8b0:4864:20::62c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C832FC06179E for ; Sat, 2 Jan 2021 14:31:40 -0800 (PST) Received: by mail-pl1-x62c.google.com with SMTP id j1so12479476pld.3 for ; Sat, 02 Jan 2021 14:31:40 -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 :mime-version:content-transfer-encoding; bh=+TZH7FARanv5tE8EvnhPVt2+HZa+BTe5BQhTyk9nRBk=; b=bzCKrKZ7NtpN7TgAkNc6lElBCKLVAaSYs7IYzgtrYVnDUBUJbLRw7H4oN3NAj6Xftp WKnUU0FBJ1Ba4Q+XB08PKRlfB5Dvz8Brwe/it8oQ+8+fIiF9NPhyKcRr+Q066lk3SRer 2U2ewYRAlryZb2Vh99kpTrQgAdxgY8ynbFiunlxhytn3UAiJBFgm8+HMQtutp37YpL/3 19Bcl1NJS8QCWNWq2ZCYhHLU2le/NR83wCQtFGjIseHAfmhC2u7vkENPpfZfUcBw+SqX UffODI2lR1X+ahK5rSKuTbIyt5E4B/ewZI1TdF9r/x1nKR8Jyxe7wRRvH9guSLlvTgHM qGxg== 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:mime-version:content-transfer-encoding; bh=+TZH7FARanv5tE8EvnhPVt2+HZa+BTe5BQhTyk9nRBk=; b=qJyXj7GU2qBUdaQ9tr37HTUS36xMFo4EuT+YxDW3PwqAh36tRL0aiqwWxLZrwqsICm buE5rtOvPAVkzT2Nz6/PwhSeEROtxbhhn7+511fzfCYxEI1r/k+6u57XZaW4CtdR5vny welme01ltqi95P9is3zaXwlIGziyE78EL4bJL8Medt4sWhENVVoqi9GqI+lmlkTpKojp sgEUE9X5SiObhCkIkIC+C/R6LZm5uAscjDz9ynmF5yXa2EMQCOPh9uN1OjTAYwYuYBr3 y3afLJSs+v7WvlymoL68BVS4iJbkB060v2ApwJfYDkpJwWvZ/taqilmUr//gvMYb5QC0 OU4g== X-Gm-Message-State: AOAM531F0JKoHDWnsi9e872+G5slSNI27GIZCq1XJi4HOGn9FOgOPy32 7aHnaRPl7h+Ob7wJ4bUOub7Ez/U5eV+g8g== X-Google-Smtp-Source: ABdhPJyMsWuGTueN3Glh/AotTAGje1WxYREQVNqbgJoITmn77jbHio8NqEJlj3doU3Ytt3aflgwuGQ== X-Received: by 2002:a17:90a:6587:: with SMTP id k7mr23622546pjj.154.1609626700387; Sat, 02 Jan 2021 14:31:40 -0800 (PST) Received: from localhost.localdomain (cpe-76-87-77-78.socal.res.rr.com. [76.87.77.78]) by smtp.gmail.com with ESMTPSA id r20sm49537931pgb.3.2021.01.02.14.31.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 02 Jan 2021 14:31:40 -0800 (PST) From: Roderick Colenbrander To: Jiri Kosina , Benjamin Tissoires Cc: linux-input@vger.kernel.org, Chris Ye , Roderick Colenbrander Subject: [PATCH v2 07/13] HID: playstation: add DualSense Bluetooth support. Date: Sat, 2 Jan 2021 14:31:03 -0800 Message-Id: <20210102223109.996781-8-roderick@gaikai.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210102223109.996781-1-roderick@gaikai.com> References: <20210102223109.996781-1-roderick@gaikai.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org From: Roderick Colenbrander This patch adds support for the DualSense when operating in Bluetooth mode. The device has the same behavior as the DualShock 4 in that by default it sends a limited input report (0x1), but after requesting calibration data, it switches to an extended input report (report 49), which adds data for touchpad, motion sensors, battery and more. Signed-off-by: Roderick Colenbrander --- drivers/hid/hid-playstation.c | 35 +++++++++++++++++++++++++++++++++++ drivers/hid/hid-quirks.c | 1 + 2 files changed, 36 insertions(+) diff --git a/drivers/hid/hid-playstation.c b/drivers/hid/hid-playstation.c index 91f3ed005fce..552a52a50b78 100644 --- a/drivers/hid/hid-playstation.c +++ b/drivers/hid/hid-playstation.c @@ -47,6 +47,7 @@ struct ps_calibration_data { }; #define DS_INPUT_REPORT_USB 0x01 +#define DS_INPUT_REPORT_BT 0x31 #define DS_FEATURE_REPORT_CALIBRATION 5 #define DS_FEATURE_REPORT_CALIBRATION_SIZE 41 @@ -285,6 +286,17 @@ static int ps_device_register_battery(struct ps_device *dev) return 0; } +/* Compute crc32 of HID data and compare against expected CRC. */ +static bool ps_check_crc32(uint8_t seed, uint8_t *data, size_t len, uint32_t report_crc) +{ + uint32_t crc; + + crc = crc32_le(0xFFFFFFFF, &seed, 1); + crc = ~crc32_le(crc, data, len); + + return crc == report_crc; +} + static struct input_dev *ps_gamepad_create(struct hid_device *hdev) { struct input_dev *gamepad; @@ -406,6 +418,18 @@ static int dualsense_get_calibration_data(struct dualsense *ds) goto err_free; } + if (ds->base.hdev->bus == BUS_BLUETOOTH) { + /* Last 4 bytes contains crc32 */ + uint8_t crc_offset = DS_FEATURE_REPORT_CALIBRATION_SIZE - 4; + uint32_t report_crc = get_unaligned_le32(&buf[crc_offset]); + + if (!ps_check_crc32(0xa3, buf, crc_offset, report_crc)) { + hid_err(ds->base.hdev, "DualSense calibration report CRC's check failed\n"); + ret = -EILSEQ; + goto err_free; + } + } + gyro_pitch_bias = get_unaligned_le16(&buf[1]); gyro_yaw_bias = get_unaligned_le16(&buf[3]); gyro_roll_bias = get_unaligned_le16(&buf[5]); @@ -515,6 +539,16 @@ static int dualsense_parse_report(struct ps_device *ps_dev, struct hid_report *r */ if (report->id == DS_INPUT_REPORT_USB && hdev->bus == BUS_USB) { ds_report = (struct dualsense_input_report *)&data[1]; + } else if (report->id == DS_INPUT_REPORT_BT && hdev->bus == BUS_BLUETOOTH) { + /* Last 4 bytes of input report contain crc32 */ + uint32_t report_crc = get_unaligned_le32(&data[size - 4]); + + if (!ps_check_crc32(0xa1, data, size - 4, report_crc)) { + hid_err(hdev, "DualSense input CRC's check failed, size=%d\n", size); + return -EILSEQ; + } + + ds_report = (struct dualsense_input_report *)&data[2]; } else { hid_err(hdev, "Unhandled reportID=%d\n", report->id); return -1; @@ -774,6 +808,7 @@ static void ps_remove(struct hid_device *hdev) } static const struct hid_device_id ps_devices[] = { + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS5_CONTROLLER) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS5_CONTROLLER) }, { } }; diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c index 1ca46cb445be..541c8837debd 100644 --- a/drivers/hid/hid-quirks.c +++ b/drivers/hid/hid-quirks.c @@ -567,6 +567,7 @@ static const struct hid_device_id hid_have_special_driver[] = { #endif #if IS_ENABLED(CONFIG_HID_PLAYSTATION) { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS5_CONTROLLER) }, ++ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS5_CONTROLLER) }, #endif #if IS_ENABLED(CONFIG_HID_PRIMAX) { HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_KEYBOARD) }, From patchwork Sat Jan 2 22:31:05 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roderick Colenbrander X-Patchwork-Id: 356019 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 828DCC43381 for ; Sat, 2 Jan 2021 22:32:58 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 51387207A1 for ; Sat, 2 Jan 2021 22:32:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726867AbhABWc5 (ORCPT ); Sat, 2 Jan 2021 17:32:57 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59244 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726766AbhABWc4 (ORCPT ); Sat, 2 Jan 2021 17:32:56 -0500 Received: from mail-pg1-x52b.google.com (mail-pg1-x52b.google.com [IPv6:2607:f8b0:4864:20::52b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E2398C0617A0 for ; Sat, 2 Jan 2021 14:31:42 -0800 (PST) Received: by mail-pg1-x52b.google.com with SMTP id c132so5017483pga.3 for ; Sat, 02 Jan 2021 14:31:42 -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 :mime-version:content-transfer-encoding; bh=5BrCyT+8fFkoS+JIQh84I54mXrlbdOL3gkzfyxxuBuE=; b=P3j/QRF+HQShJPKHd417eHQYkJ5Ed2+xorSOb9tdku8YOeWbYayFXOGzwQ0yS4FXvD v2xlmxkMjZ6VmFj0k5Qsw/ogIe8VwxGRyzgqIazdaao3JquA4vj/kYuISichNAVOvQSU /tB5T8T+S6EEq2gzwqVQa4vB5PlfI7QAJ6ToqI960QllaG7ST9Qz3iim+OaGM4UxsU/1 wcVYmDgZ3sJ/7EmR5jQqf0mLocMMkhG/HvE7heooQVD3nHW0j0my1XJCRVSuqZImHRbE xPzeEzmnGS4jHPLxfFC1RGwvg/vF8Dab86zpt292Yk6p2CyF2MldbfY1R+UuAOvvkTCB g7AQ== 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:mime-version:content-transfer-encoding; bh=5BrCyT+8fFkoS+JIQh84I54mXrlbdOL3gkzfyxxuBuE=; b=V9z3UuLpkz59iBuIupEmQpfoQuXCiFTgeQvHvPC1De4f44TiH2WY23UjF5KsvekjYz tx3pNK2RlTbN5eoJSnhmVlN1bkst3WIppYg//DIq93mEzQAPq+rd+srEyHztmQlJqpdU U0tShe8Ar/sQ1BughkjGslZxKXzYGcnMDmnlwuVpd/FcN6tRTLreP+yvaPNrOp55074B tNeJ3wvJkqS9d0MRszd6fO7SpZpD3ZNKlbrJ20FUm78TyEp7eAKqXZHexAbGQaacxPRH zHio3Kk2TP8/YADSWBLrjAF9bezs9NqT/NDjRMXjZkH6HpVOd0uec+ej6377hJjT+AuY bcdg== X-Gm-Message-State: AOAM5326jW66A9/G466EDboiLcuP4DOTht8jmigFoTjGdms/oIqvPuh5 Brd6EFhSFjPNySzwbVCQcjtLzw== X-Google-Smtp-Source: ABdhPJwitystFTKV+ayOKJEDl6P7v3vYJU01ALxLGevmdB5KFIj/vYUcHHp0+oIPzzYuyOoH3Wonzg== X-Received: by 2002:a63:4e17:: with SMTP id c23mr23150559pgb.439.1609626702493; Sat, 02 Jan 2021 14:31:42 -0800 (PST) Received: from localhost.localdomain (cpe-76-87-77-78.socal.res.rr.com. [76.87.77.78]) by smtp.gmail.com with ESMTPSA id r20sm49537931pgb.3.2021.01.02.14.31.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 02 Jan 2021 14:31:42 -0800 (PST) From: Roderick Colenbrander To: Jiri Kosina , Benjamin Tissoires Cc: linux-input@vger.kernel.org, Chris Ye , Roderick Colenbrander Subject: [PATCH v2 09/13] HID: playstation: add DualSense lightbar support Date: Sat, 2 Jan 2021 14:31:05 -0800 Message-Id: <20210102223109.996781-10-roderick@gaikai.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210102223109.996781-1-roderick@gaikai.com> References: <20210102223109.996781-1-roderick@gaikai.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org From: Roderick Colenbrander Expose the DualSense its RGB lightbar using the new multicolor LED framework. Signed-off-by: Roderick Colenbrander --- drivers/hid/Kconfig | 1 + drivers/hid/hid-playstation.c | 117 ++++++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+) diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index e6c67aaa1a1a..c80c81916f4a 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -857,6 +857,7 @@ config HID_PLAYSTATION tristate "PlayStation HID Driver" default !EXPERT depends on HID + select LEDS_CLASS_MULTICOLOR select POWER_SUPPLY help Provides support for Sony PS5 controllers including support for diff --git a/drivers/hid/hid-playstation.c b/drivers/hid/hid-playstation.c index 36a904b2f93f..3b26445acbb9 100644 --- a/drivers/hid/hid-playstation.c +++ b/drivers/hid/hid-playstation.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -87,6 +88,10 @@ struct ps_calibration_data { /* Flags for DualSense output report. */ #define DS_OUTPUT_VALID_FLAG0_COMPATIBLE_VIBRATION BIT(0) #define DS_OUTPUT_VALID_FLAG0_HAPTICS_SELECT BIT(1) +#define DS_OUTPUT_VALID_FLAG1_LIGHTBAR_CONTROL_ENABLE BIT(2) +#define DS_OUTPUT_VALID_FLAG1_RELEASE_LEDS BIT(3) +#define DS_OUTPUT_VALID_FLAG2_LIGHTBAR_SETUP_CONTROL_ENABLE BIT(1) +#define DS_OUTPUT_LIGHTBAR_SETUP_LIGHT_OUT BIT(1) /* DualSense hardware limits */ #define DS_ACC_RES_PER_G 8192 @@ -116,6 +121,13 @@ struct dualsense { uint8_t motor_left; uint8_t motor_right; + /* RGB lightbar */ + struct led_classdev_mc lightbar; + bool update_lightbar; + uint8_t lightbar_red; + uint8_t lightbar_green; + uint8_t lightbar_blue; + struct work_struct output_worker; void *output_report_dmabuf; uint8_t output_seq; /* Sequence number for output report. */ @@ -407,6 +419,45 @@ static struct input_dev *ps_gamepad_create(struct hid_device *hdev, return gamepad; } +/* Register a DualSense/DualShock4 RGB lightbar represented by a multicolor LED. */ +static int ps_lightbar_register(struct ps_device *ps_dev, struct led_classdev_mc *lightbar_mc_dev, + int (*brightness_set)(struct led_classdev *, enum led_brightness)) +{ + struct hid_device *hdev = ps_dev->hdev; + struct mc_subled *mc_led_info; + struct led_classdev *led_cdev; + int ret; + + mc_led_info = devm_kzalloc(&hdev->dev, 3*sizeof(*mc_led_info), GFP_KERNEL); + if (!mc_led_info) + return -ENOMEM; + + mc_led_info[0].color_index = LED_COLOR_ID_RED; + mc_led_info[0].channel = 0; + mc_led_info[1].color_index = LED_COLOR_ID_GREEN; + mc_led_info[1].channel = 1; + mc_led_info[2].color_index = LED_COLOR_ID_BLUE; + mc_led_info[2].channel = 2; + + lightbar_mc_dev->subled_info = mc_led_info; + lightbar_mc_dev->num_colors = 3; + + led_cdev = &lightbar_mc_dev->led_cdev; + led_cdev->name = devm_kasprintf(&hdev->dev, GFP_KERNEL, "playstation::%pMR::rgb", + ps_dev->mac_address); + led_cdev->brightness = 255; + led_cdev->max_brightness = 255; + led_cdev->brightness_set_blocking = brightness_set; + + ret = devm_led_classdev_multicolor_register(&hdev->dev, lightbar_mc_dev); + if (ret < 0) { + hid_err(hdev, "Cannot register multicolor LED device\n"); + return ret; + } + + return 0; +} + static struct input_dev *ps_sensors_create(struct hid_device *hdev, int accel_range, int accel_res, int gyro_range, int gyro_res) { @@ -601,6 +652,27 @@ static int dualsense_get_mac_address(struct dualsense *ds) return ret; } +static int dualsense_lightbar_set_brightness(struct led_classdev *cdev, + enum led_brightness brightness) +{ + struct led_classdev_mc *mc_cdev = lcdev_to_mccdev(cdev); + struct hid_device *hdev = to_hid_device(cdev->dev->parent); + struct dualsense *ds = hid_get_drvdata(hdev); + unsigned long flags; + + led_mc_calc_color_components(mc_cdev, brightness); + + spin_lock_irqsave(&ds->base.lock, flags); + ds->update_lightbar = true; + ds->lightbar_red = mc_cdev->subled_info[0].brightness; + ds->lightbar_green = mc_cdev->subled_info[1].brightness; + ds->lightbar_blue = mc_cdev->subled_info[2].brightness; + spin_unlock_irqrestore(&ds->base.lock, flags); + + schedule_work(&ds->output_worker); + return 0; +} + static void dualsense_init_output_report(struct dualsense *ds, struct dualsense_output_report *rp, void *buf) { @@ -682,6 +754,15 @@ static void dualsense_output_worker(struct work_struct *work) ds->update_rumble = false; } + if (ds->update_lightbar) { + common->valid_flag1 |= DS_OUTPUT_VALID_FLAG1_LIGHTBAR_CONTROL_ENABLE; + common->lightbar_red = ds->lightbar_red; + common->lightbar_green = ds->lightbar_green; + common->lightbar_blue = ds->lightbar_blue; + + ds->update_lightbar = false; + } + spin_unlock_irqrestore(&ds->base.lock, flags); dualsense_send_output_report(ds, &report); @@ -861,6 +942,30 @@ static int dualsense_play_effect(struct input_dev *dev, void *data, struct ff_ef return 0; } +static int dualsense_reset_leds(struct dualsense *ds) +{ + struct dualsense_output_report report; + uint8_t *buf; + + buf = kzalloc(sizeof(struct dualsense_output_report_bt), GFP_KERNEL); + if (!buf) + return -ENOMEM; + + dualsense_init_output_report(ds, &report, buf); + /* On Bluetooth the DualSense outputs an animation on the lightbar + * during startup and maintains a color afterwards. We need to explicitly + * reconfigure the lightbar before we can do any programming later on. + * In USB the lightbar is not on by default, but redoing the setup there + * doesn't hurt. + */ + report.common->valid_flag2 = DS_OUTPUT_VALID_FLAG2_LIGHTBAR_SETUP_CONTROL_ENABLE; + report.common->lightbar_setup = DS_OUTPUT_LIGHTBAR_SETUP_LIGHT_OUT; /* Fade light out. */ + dualsense_send_output_report(ds, &report); + + kfree(buf); + return 0; +} + static struct ps_device *dualsense_create(struct hid_device *hdev) { struct dualsense *ds; @@ -930,6 +1035,18 @@ static struct ps_device *dualsense_create(struct hid_device *hdev) if (ret < 0) goto err; + /* The hardware may have control over the LEDs (e.g. in Bluetooth on startup). + * Reset the LEDs (lightbar, mute, player leds), so we can control them + * from software. + */ + ret = dualsense_reset_leds(ds); + if (ret < 0) + goto err; + + ret = ps_lightbar_register(ps_dev, &ds->lightbar, dualsense_lightbar_set_brightness); + if (ret < 0) + goto err; + return &ds->base; err: From patchwork Sat Jan 2 22:31:07 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roderick Colenbrander X-Patchwork-Id: 356018 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id F379EC4332B for ; Sat, 2 Jan 2021 22:32:58 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id CFA51207A4 for ; Sat, 2 Jan 2021 22:32:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726846AbhABWc6 (ORCPT ); Sat, 2 Jan 2021 17:32:58 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59252 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726844AbhABWc5 (ORCPT ); Sat, 2 Jan 2021 17:32:57 -0500 Received: from mail-pf1-x42b.google.com (mail-pf1-x42b.google.com [IPv6:2607:f8b0:4864:20::42b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B5D2BC0617A2 for ; Sat, 2 Jan 2021 14:31:44 -0800 (PST) Received: by mail-pf1-x42b.google.com with SMTP id s21so14048589pfu.13 for ; Sat, 02 Jan 2021 14:31:44 -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 :mime-version:content-transfer-encoding; bh=AnYnS6fYaMZEZl3GdLkbHCHM8C7felhMNNlV5fv5q8U=; b=OSFyIstW1mNN/d2BfF+XwxVJe5l16UpM3S8EzNOzdFKEdpy6JZyS6VhOfA4d7LuszG 7CMqThPO7PFYlA+qIc3yG3VFLdV3bYL9pkAKITFKY4GGLhwE5k1RjgmdIJ5f34RR8kYb 6NZMvLZCs/SARgWRO/ahp9Xzx9Zte68Q6jLAKP9BVxRAByxGLVIsjdDDAnvUMNcpqAmd EAoW2MSU/ZFvTnTC5/+CD1d04gl42I9h5hC0vjIRQL2hd/52ba2kb179Q+R9ng2zuKSo jUBWtI7EOkwnp27jUGv7RsnEXj+qCAei/hQhOKQi6U/O9STYDhhpwnsBu5Y+e6J9NxFH HokQ== 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:mime-version:content-transfer-encoding; bh=AnYnS6fYaMZEZl3GdLkbHCHM8C7felhMNNlV5fv5q8U=; b=XDYUrkiq2PR9t9R01cHdbH5cInWsbYS8nc05ac8wb85AQT8B3RlUguQDTi1bKmDgFO RKNq9/odpHPPlBIQpze52c/F2ADfZ9q2JMw7Gq6JYzZzMlrKDYl9/19rmiyXIGENTEmK HmItka6tIe1LktQNfQtxm5CaR0HBo2h+GF63Qh4c+8RTEnb2Va+u3I1JYXYdCxbW65ui 6AHY5dPCDDDZuBfg+J7/V+J0g3yaO74bX+xevOrtgH2jq9J27pGGYiSVghETgakBkym0 ErgVBwYblo7Pm4OHS9O2OWatyFLzlGbCxPmxsbhI1ZiXEr9pZApEvPyZXeovdIqY8gqR RFwA== X-Gm-Message-State: AOAM530AUoXdEF+J/sv+N0vA8jRQUWM1kqxUYHPYW3z8Lpv4TCgyaOrJ NRdeAr916rnSkoU+nbvvgVbt7w== X-Google-Smtp-Source: ABdhPJy2KgYDiFekNUe772y/1pcUX4fe0ZwhCy36mN6X6UTdYQEproPGBlwqJCxIP9p7Ac2bubyhnQ== X-Received: by 2002:a63:24c4:: with SMTP id k187mr18191808pgk.238.1609626704330; Sat, 02 Jan 2021 14:31:44 -0800 (PST) Received: from localhost.localdomain (cpe-76-87-77-78.socal.res.rr.com. [76.87.77.78]) by smtp.gmail.com with ESMTPSA id r20sm49537931pgb.3.2021.01.02.14.31.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 02 Jan 2021 14:31:44 -0800 (PST) From: Roderick Colenbrander To: Jiri Kosina , Benjamin Tissoires Cc: linux-input@vger.kernel.org, Chris Ye , Roderick Colenbrander Subject: [PATCH v2 11/13] HID: playstation: add DualSense player LEDs support. Date: Sat, 2 Jan 2021 14:31:07 -0800 Message-Id: <20210102223109.996781-12-roderick@gaikai.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210102223109.996781-1-roderick@gaikai.com> References: <20210102223109.996781-1-roderick@gaikai.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org From: Roderick Colenbrander The DualSense features 5 player LEDs below its touchpad, which are meant as player id indications. This patch exposes the player LEDs as individual LEDs. Signed-off-by: Roderick Colenbrander --- drivers/hid/hid-playstation.c | 60 ++++++++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/drivers/hid/hid-playstation.c b/drivers/hid/hid-playstation.c index ebf8a6550308..183f011f081b 100644 --- a/drivers/hid/hid-playstation.c +++ b/drivers/hid/hid-playstation.c @@ -100,6 +100,7 @@ struct ps_led_info { #define DS_OUTPUT_VALID_FLAG1_POWER_SAVE_CONTROL_ENABLE BIT(1) #define DS_OUTPUT_VALID_FLAG1_LIGHTBAR_CONTROL_ENABLE BIT(2) #define DS_OUTPUT_VALID_FLAG1_RELEASE_LEDS BIT(3) +#define DS_OUTPUT_VALID_FLAG1_PLAYER_INDICATOR_CONTROL_ENABLE BIT(4) #define DS_OUTPUT_VALID_FLAG2_LIGHTBAR_SETUP_CONTROL_ENABLE BIT(1) #define DS_OUTPUT_POWER_SAVE_CONTROL_MIC_MUTE BIT(4) #define DS_OUTPUT_LIGHTBAR_SETUP_LIGHT_OUT BIT(1) @@ -145,6 +146,11 @@ struct dualsense { bool last_btn_mic_state; struct led_classdev mute_led; + /* Player leds */ + bool update_player_leds; + uint8_t player_leds_state; + struct led_classdev player_leds[5]; + struct work_struct output_worker; void *output_report_dmabuf; uint8_t output_seq; /* Sequence number for output report. */ @@ -730,6 +736,35 @@ static void dualsense_mute_led_set_brightness(struct led_classdev *led, enum led } +static enum led_brightness dualsense_player_led_get_brightness(struct led_classdev *led) +{ + struct hid_device *hdev = to_hid_device(led->dev->parent); + struct dualsense *ds = hid_get_drvdata(hdev); + + return !!(ds->player_leds_state & BIT(led - ds->player_leds)); +} + +static void dualsense_player_led_set_brightness(struct led_classdev *led, enum led_brightness value) +{ + struct hid_device *hdev = to_hid_device(led->dev->parent); + struct dualsense *ds = hid_get_drvdata(hdev); + unsigned long flags; + unsigned int led_index; + + spin_lock_irqsave(&ds->base.lock, flags); + + led_index = led - ds->player_leds; + if (value == LED_OFF) + ds->player_leds_state &= ~(1 << led_index); + else + ds->player_leds_state |= (1 << led_index); + + ds->update_player_leds = true; + spin_unlock_irqrestore(&ds->base.lock, flags); + + schedule_work(&ds->output_worker); +} + static void dualsense_init_output_report(struct dualsense *ds, struct dualsense_output_report *rp, void *buf) { @@ -820,6 +855,13 @@ static void dualsense_output_worker(struct work_struct *work) ds->update_lightbar = false; } + if (ds->update_player_leds) { + common->valid_flag1 |= DS_OUTPUT_VALID_FLAG1_PLAYER_INDICATOR_CONTROL_ENABLE; + common->player_leds = ds->player_leds_state; + + ds->update_player_leds = false; + } + if (ds->update_mic_mute) { if (ds->mic_muted) { common->valid_flag1 |= DS_OUTPUT_VALID_FLAG1_MIC_MUTE_LED_CONTROL_ENABLE; @@ -1065,12 +1107,20 @@ static struct ps_device *dualsense_create(struct hid_device *hdev) struct dualsense *ds; struct ps_device *ps_dev; uint8_t max_output_report_size; - int ret; + int i, ret; struct ps_led_info mute_led_info = { "micmute", dualsense_mute_led_get_brightness, dualsense_mute_led_set_brightness }; + struct ps_led_info player_leds_info[] = { + { "led1", dualsense_player_led_get_brightness, dualsense_player_led_set_brightness }, + { "led2", dualsense_player_led_get_brightness, dualsense_player_led_set_brightness }, + { "led3", dualsense_player_led_get_brightness, dualsense_player_led_set_brightness }, + { "led4", dualsense_player_led_get_brightness, dualsense_player_led_set_brightness }, + { "led5", dualsense_player_led_get_brightness, dualsense_player_led_set_brightness } + }; + ds = devm_kzalloc(&hdev->dev, sizeof(*ds), GFP_KERNEL); if (!ds) return ERR_PTR(-ENOMEM); @@ -1149,6 +1199,14 @@ static struct ps_device *dualsense_create(struct hid_device *hdev) if (ret < 0) goto err; + for (i = 0; i < ARRAY_SIZE(player_leds_info); i++) { + struct ps_led_info *led_info = &player_leds_info[i]; + + ret = ps_led_register(ps_dev, &ds->player_leds[i], led_info); + if (ret < 0) + goto err; + } + return &ds->base; err: From patchwork Sat Jan 2 22:31:09 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roderick Colenbrander X-Patchwork-Id: 356017 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id EE716C433DB for ; Sat, 2 Jan 2021 22:32:59 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id CD4AA207A1 for ; Sat, 2 Jan 2021 22:32:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726877AbhABWc7 (ORCPT ); Sat, 2 Jan 2021 17:32:59 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59258 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726864AbhABWc6 (ORCPT ); Sat, 2 Jan 2021 17:32:58 -0500 Received: from mail-pg1-x52c.google.com (mail-pg1-x52c.google.com [IPv6:2607:f8b0:4864:20::52c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B334DC0617A4 for ; Sat, 2 Jan 2021 14:31:46 -0800 (PST) Received: by mail-pg1-x52c.google.com with SMTP id p18so16321881pgm.11 for ; Sat, 02 Jan 2021 14:31:46 -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 :mime-version:content-transfer-encoding; bh=oKjqCLTfmOvhIqyV2uqxkRwWE4dM09kjKsdXcVc91Ao=; b=uDOSY4vx2nk8fSM2DQcf7vd4xjgb3kaOAe/oK2r0QRsTEXK+ScQiTnm/Q6zzWUAbjW ClHlXymJAXlveJpb/Vtctq/lx9s11Sq8PdqKizHUxxXtgrR46K1HUF97kLYUWzdgYCPf kQcbvOGC6UW06N3VZ6Mb8R8Fi1Ui1iTK7gxc+OGc8A/XWpcgxAROL4hkFqlZTJke8wJI fPjQlUJqEB5ZJZdLSHsjURL98Abh5Habnd36F8gDPonVpRYW3am7iDcKYfL376tJT4bz INOLL/rDWTdc8FYSmUGcMSmDQPP7aXzfe4x190i9UgnYm7bYa6muK/1k4zZIvwJwhOkU E5nw== 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:mime-version:content-transfer-encoding; bh=oKjqCLTfmOvhIqyV2uqxkRwWE4dM09kjKsdXcVc91Ao=; b=peJBPezpDZ1Clfnfbqp1rfS7iUy6MwUR52BftTfYZSjxMxOs6Clq+4R9S7+pEZMWb6 wAoaz+NeoHAIFU5qnQkFh8XP3xrejxMvX6VCodh+vI9OtgWZN+EAgjqUb67HZjcyAaf3 x3p816cT3Ux/9LjyXiT6pSnzmkfFfygkhBH/gpkzSh2eHEvGJVcoEfhy4PevDr/amX6V Y6Qjx+kNW5FjAyS0NPg93/+Ih4XNU1Lxa3hNY2mqRipB2eBXOj3wu7twi4QWKfyX6Bcc l8T0lBP4//bViL5/pKZMS6qkdAO44XudnjPTd17rzP0rH+sZznP6OQh3yf0UORhJup19 VSog== X-Gm-Message-State: AOAM532qJR/2dKjkRiO4Jhd6JuuBfyhhPXJYjsIiyEMbbQDaRYX3XPO3 J+EMt/eW/IMFUXam6ql3z1KC7g== X-Google-Smtp-Source: ABdhPJyu/soWfe+zhAgCZcgoi3FlnDcemmbhxuHjFfP/uifYH+63sP9Ei1N7g6smZPltdJq3WXKl5A== X-Received: by 2002:a62:3002:0:b029:1aa:d858:cdd7 with SMTP id w2-20020a6230020000b02901aad858cdd7mr61235301pfw.1.1609626706284; Sat, 02 Jan 2021 14:31:46 -0800 (PST) Received: from localhost.localdomain (cpe-76-87-77-78.socal.res.rr.com. [76.87.77.78]) by smtp.gmail.com with ESMTPSA id r20sm49537931pgb.3.2021.01.02.14.31.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 02 Jan 2021 14:31:45 -0800 (PST) From: Roderick Colenbrander To: Jiri Kosina , Benjamin Tissoires Cc: linux-input@vger.kernel.org, Chris Ye , Roderick Colenbrander Subject: [PATCH v2 13/13] HID: playstation: report DualSense hardware and firmware version. Date: Sat, 2 Jan 2021 14:31:09 -0800 Message-Id: <20210102223109.996781-14-roderick@gaikai.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210102223109.996781-1-roderick@gaikai.com> References: <20210102223109.996781-1-roderick@gaikai.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org From: Roderick Colenbrander Retrieve DualSense hardware and firmware information using a vendor specific feature report. Report the data through sysfs and also report using hid_info as there can be signficant differences between versions. Signed-off-by: Roderick Colenbrander --- drivers/hid/hid-playstation.c | 84 +++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/drivers/hid/hid-playstation.c b/drivers/hid/hid-playstation.c index 1a95c81da8a3..8440af6d6cd7 100644 --- a/drivers/hid/hid-playstation.c +++ b/drivers/hid/hid-playstation.c @@ -41,6 +41,8 @@ struct ps_device { int battery_status; uint8_t mac_address[6]; + uint32_t hw_version; + uint32_t fw_version; int (*parse_report)(struct ps_device *dev, struct hid_report *report, u8 *data, int size); }; @@ -68,6 +70,8 @@ struct ps_led_info { #define DS_FEATURE_REPORT_CALIBRATION_SIZE 41 #define DS_FEATURE_REPORT_PAIRING_INFO 9 #define DS_FEATURE_REPORT_PAIRING_INFO_SIZE 19 +#define DS_FEATURE_REPORT_FIRMWARE_INFO 32 +#define DS_FEATURE_REPORT_FIRMWARE_INFO_SIZE 64 /* Button masks for DualSense input report. */ #define DS_BUTTONS0_HAT_SWITCH GENMASK(3, 0) @@ -593,6 +597,40 @@ static struct input_dev *ps_touchpad_create(struct hid_device *hdev, int width, return touchpad; } +static ssize_t ps_show_firmware_version(struct device *dev, + struct device_attribute + *attr, char *buf) +{ + struct hid_device *hdev = to_hid_device(dev); + struct ps_device *ps_dev = hid_get_drvdata(hdev); + + return sysfs_emit(buf, "0x%08x\n", ps_dev->fw_version); +} + +static DEVICE_ATTR(firmware_version, 0444, ps_show_firmware_version, NULL); + +static ssize_t ps_show_hardware_version(struct device *dev, + struct device_attribute + *attr, char *buf) +{ + struct hid_device *hdev = to_hid_device(dev); + struct ps_device *ps_dev = hid_get_drvdata(hdev); + + return sysfs_emit(buf, "0x%08x\n", ps_dev->hw_version); +} + +static DEVICE_ATTR(hardware_version, 0444, ps_show_hardware_version, NULL); + +static struct attribute *ps_device_attributes[] = { + &dev_attr_firmware_version.attr, + &dev_attr_hardware_version.attr, + NULL +}; + +static const struct attribute_group ps_device_attribute_group = { + .attrs = ps_device_attributes, +}; + static int dualsense_get_calibration_data(struct dualsense *ds) { short gyro_pitch_bias, gyro_pitch_plus, gyro_pitch_minus; @@ -696,6 +734,34 @@ static int dualsense_get_calibration_data(struct dualsense *ds) return ret; } +static int dualsense_get_firmware_info(struct dualsense *ds) +{ + uint8_t *buf; + int ret; + + buf = kzalloc(DS_FEATURE_REPORT_FIRMWARE_INFO_SIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + ret = hid_hw_raw_request(ds->base.hdev, DS_FEATURE_REPORT_FIRMWARE_INFO, buf, + DS_FEATURE_REPORT_FIRMWARE_INFO_SIZE, HID_FEATURE_REPORT, + HID_REQ_GET_REPORT); + if (ret < 0) + goto err_free; + else if (ret != DS_FEATURE_REPORT_FIRMWARE_INFO_SIZE) { + hid_err(ds->base.hdev, "failed to retrieve DualSense firmware info\n"); + ret = -EINVAL; + goto err_free; + } + + ds->base.hw_version = get_unaligned_le32(&buf[24]); + ds->base.fw_version = get_unaligned_le32(&buf[28]); + +err_free: + kfree(buf); + return ret; +} + static int dualsense_get_mac_address(struct dualsense *ds) { uint8_t *buf; @@ -1195,6 +1261,12 @@ static struct ps_device *dualsense_create(struct hid_device *hdev) } snprintf(hdev->uniq, sizeof(hdev->uniq), "%pMR", ds->base.mac_address); + ret = dualsense_get_firmware_info(ds); + if (ret < 0) { + hid_err(hdev, "Failed to get firmware info from DualSense\n"); + return ERR_PTR(ret); + } + ret = ps_devices_list_add(ps_dev); if (ret < 0) return ERR_PTR(ret); @@ -1261,6 +1333,12 @@ static struct ps_device *dualsense_create(struct hid_device *hdev) /* Set player LEDs to our player id. */ dualsense_set_player_leds(ds); + /* Reporting hardware and firmware is important as there are frequent updates, which + * can change behavior. + */ + hid_info(hdev, "Registered DualSense controller hw_version=%x fw_version=%x\n", + ds->base.hw_version, ds->base.fw_version); + return &ds->base; err: @@ -1311,6 +1389,12 @@ static int ps_probe(struct hid_device *hdev, const struct hid_device_id *id) } } + ret = devm_device_add_group(&hdev->dev, &ps_device_attribute_group); + if (ret < 0) { + hid_err(hdev, "Failed to register sysfs nodes.\n"); + goto err_close; + } + return ret; err_close: