From patchwork Wed Dec 20 03:38:31 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vicki Pfau X-Patchwork-Id: 756665 Received: from endrift.com (endrift.com [173.255.198.10]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9B87D8BF6 for ; Wed, 20 Dec 2023 03:38:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=endrift.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=endrift.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=endrift.com header.i=@endrift.com header.b="XnRLODCK" Received: from nebulosa.vulpes.eutheria.net (71-212-26-68.tukw.qwest.net [71.212.26.68]) by endrift.com (Postfix) with ESMTPSA id 8F0ABA080; Tue, 19 Dec 2023 19:38:49 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=endrift.com; s=2020; t=1703043529; bh=jOy6Oq/EDgiJ3iuPU4rQfen1ZSuyujYUA9R32NeUF4E=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=XnRLODCKQILv/ixiVHh4oYa3iJO7THrIDtRItewP5ClyVmG0kA7UvLRSYWt7uaeUg W+6rXBanXgiGOOfkGzD+OyWaipuqSubhEXuDz+hMaxAbDcmJPM6fmXGZXka50ush/A ISzL9YvYApYEb+X0LsW3v60cSUo/b5tA8xVHB+Ifi7B0Z+7vNAFo2BQzD/RJ2V6lVG gq0d9e5L59rnKUsL1lVUmloPG0KebVyg6kmVkn/pBPNKPlVMi0x5gtU0JQVqp5H5qi AZDdZqePs3H/6wZ6EVHKTCc1srsqMw8SyH6PKQcmieZyMfZqFOlsRhsjLSa6u6jhYj /78Pv6EgK9oqA== From: Vicki Pfau To: Jiri Kosina , Benjamin Tissoires , linux-input@vger.kernel.org Cc: Vicki Pfau Subject: [PATCH 1/7] HID: hid-steam: Avoid overwriting smoothing parameter Date: Tue, 19 Dec 2023 19:38:31 -0800 Message-ID: <20231220033837.2135194-1-vi@endrift.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231220033609.2132033-1-vi@endrift.com> References: <20231220033609.2132033-1-vi@endrift.com> Precedence: bulk X-Mailing-List: linux-input@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The original implementation of this driver incorrectly guessed the function of this register. It's not only unnecessary to write to this register for lizard mode but actually counter-productive since it overwrites whatever previous value was intentionally set, for example by Steam. Signed-off-by: Vicki Pfau --- drivers/hid/hid-steam.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/hid/hid-steam.c b/drivers/hid/hid-steam.c index b110818fc945..7aefd52e945a 100644 --- a/drivers/hid/hid-steam.c +++ b/drivers/hid/hid-steam.c @@ -340,9 +340,6 @@ static void steam_set_lizard_mode(struct steam_device *steam, bool enable) steam_send_report_byte(steam, STEAM_CMD_DEFAULT_MAPPINGS); /* enable mouse */ steam_send_report_byte(steam, STEAM_CMD_DEFAULT_MOUSE); - steam_write_registers(steam, - STEAM_REG_RPAD_MARGIN, 0x01, /* enable margin */ - 0); cancel_delayed_work_sync(&steam->heartbeat); } else { @@ -351,7 +348,6 @@ static void steam_set_lizard_mode(struct steam_device *steam, bool enable) if (steam->quirks & STEAM_QUIRK_DECK) { steam_write_registers(steam, - STEAM_REG_RPAD_MARGIN, 0x00, /* disable margin */ STEAM_REG_LPAD_MODE, 0x07, /* disable mouse */ STEAM_REG_RPAD_MODE, 0x07, /* disable mouse */ STEAM_REG_LPAD_CLICK_PRESSURE, 0xFFFF, /* disable clicky pad */ @@ -365,7 +361,6 @@ static void steam_set_lizard_mode(struct steam_device *steam, bool enable) schedule_delayed_work(&steam->heartbeat, 5 * HZ); } else { steam_write_registers(steam, - STEAM_REG_RPAD_MARGIN, 0x00, /* disable margin */ STEAM_REG_LPAD_MODE, 0x07, /* disable mouse */ STEAM_REG_RPAD_MODE, 0x07, /* disable mouse */ 0); From patchwork Wed Dec 20 03:38:32 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vicki Pfau X-Patchwork-Id: 757711 Received: from endrift.com (endrift.com [173.255.198.10]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 114E78C02 for ; Wed, 20 Dec 2023 03:38:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=endrift.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=endrift.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=endrift.com header.i=@endrift.com header.b="ITv4uo7u" Received: from nebulosa.vulpes.eutheria.net (71-212-26-68.tukw.qwest.net [71.212.26.68]) by endrift.com (Postfix) with ESMTPSA id 0341EA26C; Tue, 19 Dec 2023 19:38:49 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=endrift.com; s=2020; t=1703043530; bh=JulwiXNYhSEXOn2RaM3vPCuIKxVKkWxTmLm5LSiCvGs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ITv4uo7uk+TbESQ0eOQBTde59cACqWZ+aFg5RMkJ5atLSQ/FOTdiDxLLyCJLo7VNv c+Fo4r7Xf+zrE2bWV3ZS0IVsjsifPxq7yGkALjFgrsKTnSk1wQzqeFWpSM/eDu7vLt osFX18XW7sWSQS4KHZBL1TE1xh8Ds5h7CiBdjFUtNpE1pm+XHa8wbzOxNaEX9QclWP CxoxWWuDRhtMtuZnO5N0mng+F+ULqgrkE+u5NvMgjRgvefLjN69S1Rp+xvYT4xRORC VAUp8i0jsXXNwqoRDVF0MCREK0U/qc8JTj7xGKyh8RrEB+sY2WCMlyD+ajq5t8JKKK qPUNAwVCRXydA== From: Vicki Pfau To: Jiri Kosina , Benjamin Tissoires , linux-input@vger.kernel.org Cc: Vicki Pfau Subject: [PATCH 2/7] HID: hid-steam: Disable watchdog instead of using a heartbeat Date: Tue, 19 Dec 2023 19:38:32 -0800 Message-ID: <20231220033837.2135194-2-vi@endrift.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231220033837.2135194-1-vi@endrift.com> References: <20231220033609.2132033-1-vi@endrift.com> <20231220033837.2135194-1-vi@endrift.com> Precedence: bulk X-Mailing-List: linux-input@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The Steam Deck has a setting that controls whether or not the watchdog is enabled, so instead of using a heartbeat to keep the watchdog from triggering, this commit changes the behavior to simply disable the watchdog instead. --- drivers/hid/hid-steam.c | 30 ++---------------------------- 1 file changed, 2 insertions(+), 28 deletions(-) diff --git a/drivers/hid/hid-steam.c b/drivers/hid/hid-steam.c index 7aefd52e945a..efd297e0ea8c 100644 --- a/drivers/hid/hid-steam.c +++ b/drivers/hid/hid-steam.c @@ -101,6 +101,7 @@ static LIST_HEAD(steam_devices); #define STEAM_REG_GYRO_MODE 0x30 #define STEAM_REG_LPAD_CLICK_PRESSURE 0x34 #define STEAM_REG_RPAD_CLICK_PRESSURE 0x35 +#define STEAM_REG_WATCHDOG_ENABLE 0x47 /* Raw event identifiers */ #define STEAM_EV_INPUT_DATA 0x01 @@ -134,7 +135,6 @@ struct steam_device { struct power_supply __rcu *battery; u8 battery_charge; u16 voltage; - struct delayed_work heartbeat; struct work_struct rumble_work; u16 rumble_left; u16 rumble_right; @@ -340,8 +340,6 @@ static void steam_set_lizard_mode(struct steam_device *steam, bool enable) steam_send_report_byte(steam, STEAM_CMD_DEFAULT_MAPPINGS); /* enable mouse */ steam_send_report_byte(steam, STEAM_CMD_DEFAULT_MOUSE); - - cancel_delayed_work_sync(&steam->heartbeat); } else { /* disable esc, enter, cursor */ steam_send_report_byte(steam, STEAM_CMD_CLEAR_MAPPINGS); @@ -352,13 +350,8 @@ static void steam_set_lizard_mode(struct steam_device *steam, bool enable) STEAM_REG_RPAD_MODE, 0x07, /* disable mouse */ STEAM_REG_LPAD_CLICK_PRESSURE, 0xFFFF, /* disable clicky pad */ STEAM_REG_RPAD_CLICK_PRESSURE, 0xFFFF, /* disable clicky pad */ + STEAM_REG_WATCHDOG_ENABLE, 0, /* disable watchdog that tests if Steam is active */ 0); - /* - * The Steam Deck has a watchdog that automatically enables - * lizard mode if it doesn't see any traffic for too long - */ - if (!work_busy(&steam->heartbeat.work)) - schedule_delayed_work(&steam->heartbeat, 5 * HZ); } else { steam_write_registers(steam, STEAM_REG_LPAD_MODE, 0x07, /* disable mouse */ @@ -733,22 +726,6 @@ static bool steam_is_valve_interface(struct hid_device *hdev) return !list_empty(&rep_enum->report_list); } -static void steam_lizard_mode_heartbeat(struct work_struct *work) -{ - struct steam_device *steam = container_of(work, struct steam_device, - heartbeat.work); - - mutex_lock(&steam->mutex); - if (!steam->client_opened && steam->client_hdev) { - steam_send_report_byte(steam, STEAM_CMD_CLEAR_MAPPINGS); - steam_write_registers(steam, - STEAM_REG_RPAD_MODE, 0x07, /* disable mouse */ - 0); - schedule_delayed_work(&steam->heartbeat, 5 * HZ); - } - mutex_unlock(&steam->mutex); -} - static int steam_client_ll_parse(struct hid_device *hdev) { struct steam_device *steam = hdev->driver_data; @@ -887,7 +864,6 @@ static int steam_probe(struct hid_device *hdev, steam->quirks = id->driver_data; INIT_WORK(&steam->work_connect, steam_work_connect_cb); INIT_LIST_HEAD(&steam->list); - INIT_DEFERRABLE_WORK(&steam->heartbeat, steam_lizard_mode_heartbeat); INIT_WORK(&steam->rumble_work, steam_haptic_rumble_cb); steam->client_hdev = steam_create_client_hid(hdev); @@ -944,7 +920,6 @@ static int steam_probe(struct hid_device *hdev, hid_destroy_device(steam->client_hdev); client_hdev_fail: cancel_work_sync(&steam->work_connect); - cancel_delayed_work_sync(&steam->heartbeat); cancel_work_sync(&steam->rumble_work); steam_alloc_fail: hid_err(hdev, "%s: failed with error %d\n", @@ -965,7 +940,6 @@ static void steam_remove(struct hid_device *hdev) mutex_lock(&steam->mutex); steam->client_hdev = NULL; steam->client_opened = false; - cancel_delayed_work_sync(&steam->heartbeat); mutex_unlock(&steam->mutex); cancel_work_sync(&steam->work_connect); if (steam->quirks & STEAM_QUIRK_WIRELESS) { From patchwork Wed Dec 20 03:38:33 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vicki Pfau X-Patchwork-Id: 756664 Received: from endrift.com (endrift.com [173.255.198.10]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5034F8C09 for ; Wed, 20 Dec 2023 03:38:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=endrift.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=endrift.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=endrift.com header.i=@endrift.com header.b="Dss19jZd" Received: from nebulosa.vulpes.eutheria.net (71-212-26-68.tukw.qwest.net [71.212.26.68]) by endrift.com (Postfix) with ESMTPSA id 696CAA290; Tue, 19 Dec 2023 19:38:50 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=endrift.com; s=2020; t=1703043530; bh=Uh9xbde44dEpW4JpaEscxJm6qdr1LNjogvTqKM5OUww=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Dss19jZdjsAhpEvpslc7yDCgNd11ySHKRwwGgXW+1yPgKDCcxFPNw1fWSjCm6zcZd HtbbVav3+WyjvaifrmgbxgB5NWXYJEJIZqMo1wRicg3oONj2+IjUpuSpSXV2aI0puN LWCQFyFl8TWSBJzV/F5UN1ubmoZmtvOTmRySOvvUgAMDuVpP48ZV3t57e4nKOU3HNv XBs5h1KIh1peznrhVbvsD1OrBvZuX2UiBYIvM7eSZgejrqiJMF0Nql7VXtVxvso6Ds T2eECS+w0AH4RXXqydPtl65jVlA/vUz8ov92uIiTJsowuvjFvdo3M6W20i01BKdFvV mSwMA6yPtcdwQ== From: Vicki Pfau To: Jiri Kosina , Benjamin Tissoires , linux-input@vger.kernel.org Cc: Vicki Pfau Subject: [PATCH 3/7] HID: hid-steam: Clean up locking Date: Tue, 19 Dec 2023 19:38:33 -0800 Message-ID: <20231220033837.2135194-3-vi@endrift.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231220033837.2135194-1-vi@endrift.com> References: <20231220033609.2132033-1-vi@endrift.com> <20231220033837.2135194-1-vi@endrift.com> Precedence: bulk X-Mailing-List: linux-input@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 This cleans up the locking logic so that the spinlock is consistently used for access to a small handful of struct variables, and the mutex is exclusively and consistently used for ensuring that mutliple threads aren't trying to send/receive reports at the same time. Previously, only some report transactions were guarded by this mutex, potentially breaking atomicity. The mutex has been renamed to reflect this usage. Signed-off-by: Vicki Pfau --- drivers/hid/hid-steam.c | 122 +++++++++++++++++++++++----------------- 1 file changed, 69 insertions(+), 53 deletions(-) diff --git a/drivers/hid/hid-steam.c b/drivers/hid/hid-steam.c index efd297e0ea8c..57cb58941c9f 100644 --- a/drivers/hid/hid-steam.c +++ b/drivers/hid/hid-steam.c @@ -124,7 +124,7 @@ struct steam_device { struct list_head list; spinlock_t lock; struct hid_device *hdev, *client_hdev; - struct mutex mutex; + struct mutex report_mutex; bool client_opened; struct input_dev __rcu *input; unsigned long quirks; @@ -267,21 +267,26 @@ static int steam_get_serial(struct steam_device *steam) * Send: 0xae 0x15 0x01 * Recv: 0xae 0x15 0x01 serialnumber (10 chars) */ - int ret; + int ret = 0; u8 cmd[] = {STEAM_CMD_GET_SERIAL, 0x15, 0x01}; u8 reply[3 + STEAM_SERIAL_LEN + 1]; + mutex_lock(&steam->report_mutex); ret = steam_send_report(steam, cmd, sizeof(cmd)); if (ret < 0) - return ret; + goto out; ret = steam_recv_report(steam, reply, sizeof(reply)); if (ret < 0) - return ret; - if (reply[0] != 0xae || reply[1] != 0x15 || reply[2] != 0x01) - return -EIO; + goto out; + if (reply[0] != 0xae || reply[1] != 0x15 || reply[2] != 0x01) { + ret = -EIO; + goto out; + } reply[3 + STEAM_SERIAL_LEN] = 0; strscpy(steam->serial_no, reply + 3, sizeof(steam->serial_no)); - return 0; +out: + mutex_unlock(&steam->report_mutex); + return ret; } /* @@ -291,13 +296,18 @@ static int steam_get_serial(struct steam_device *steam) */ static inline int steam_request_conn_status(struct steam_device *steam) { - return steam_send_report_byte(steam, STEAM_CMD_REQUEST_COMM_STATUS); + int ret; + mutex_lock(&steam->report_mutex); + ret = steam_send_report_byte(steam, STEAM_CMD_REQUEST_COMM_STATUS); + mutex_unlock(&steam->report_mutex); + return ret; } static inline int steam_haptic_rumble(struct steam_device *steam, u16 intensity, u16 left_speed, u16 right_speed, u8 left_gain, u8 right_gain) { + int ret; u8 report[11] = {STEAM_CMD_HAPTIC_RUMBLE, 9}; report[3] = intensity & 0xFF; @@ -309,7 +319,10 @@ static inline int steam_haptic_rumble(struct steam_device *steam, report[9] = left_gain; report[10] = right_gain; - return steam_send_report(steam, report, sizeof(report)); + mutex_lock(&steam->report_mutex); + ret = steam_send_report(steam, report, sizeof(report)); + mutex_unlock(&steam->report_mutex); + return ret; } static void steam_haptic_rumble_cb(struct work_struct *work) @@ -336,11 +349,14 @@ static int steam_play_effect(struct input_dev *dev, void *data, static void steam_set_lizard_mode(struct steam_device *steam, bool enable) { if (enable) { + mutex_lock(&steam->report_mutex); /* enable esc, enter, cursors */ steam_send_report_byte(steam, STEAM_CMD_DEFAULT_MAPPINGS); /* enable mouse */ steam_send_report_byte(steam, STEAM_CMD_DEFAULT_MOUSE); + mutex_unlock(&steam->report_mutex); } else { + mutex_lock(&steam->report_mutex); /* disable esc, enter, cursor */ steam_send_report_byte(steam, STEAM_CMD_CLEAR_MAPPINGS); @@ -352,11 +368,13 @@ static void steam_set_lizard_mode(struct steam_device *steam, bool enable) STEAM_REG_RPAD_CLICK_PRESSURE, 0xFFFF, /* disable clicky pad */ STEAM_REG_WATCHDOG_ENABLE, 0, /* disable watchdog that tests if Steam is active */ 0); + mutex_unlock(&steam->report_mutex); } else { steam_write_registers(steam, STEAM_REG_LPAD_MODE, 0x07, /* disable mouse */ STEAM_REG_RPAD_MODE, 0x07, /* disable mouse */ 0); + mutex_unlock(&steam->report_mutex); } } } @@ -364,22 +382,29 @@ static void steam_set_lizard_mode(struct steam_device *steam, bool enable) static int steam_input_open(struct input_dev *dev) { struct steam_device *steam = input_get_drvdata(dev); + unsigned long flags; + bool set_lizard_mode; - mutex_lock(&steam->mutex); - if (!steam->client_opened && lizard_mode) + spin_lock_irqsave(&steam->lock, flags); + set_lizard_mode = !steam->client_opened && lizard_mode; + spin_unlock_irqrestore(&steam->lock, flags); + if (set_lizard_mode) steam_set_lizard_mode(steam, false); - mutex_unlock(&steam->mutex); + return 0; } static void steam_input_close(struct input_dev *dev) { struct steam_device *steam = input_get_drvdata(dev); + unsigned long flags; + bool set_lizard_mode; - mutex_lock(&steam->mutex); - if (!steam->client_opened && lizard_mode) + spin_lock_irqsave(&steam->lock, flags); + set_lizard_mode = !steam->client_opened && lizard_mode; + spin_unlock_irqrestore(&steam->lock, flags); + if (set_lizard_mode) steam_set_lizard_mode(steam, true); - mutex_unlock(&steam->mutex); } static enum power_supply_property steam_battery_props[] = { @@ -624,6 +649,7 @@ static int steam_register(struct steam_device *steam) { int ret; bool client_opened; + unsigned long flags; /* * This function can be called several times in a row with the @@ -636,11 +662,9 @@ static int steam_register(struct steam_device *steam) * Unlikely, but getting the serial could fail, and it is not so * important, so make up a serial number and go on. */ - mutex_lock(&steam->mutex); if (steam_get_serial(steam) < 0) strscpy(steam->serial_no, "XXXXXXXXXX", sizeof(steam->serial_no)); - mutex_unlock(&steam->mutex); hid_info(steam->hdev, "Steam Controller '%s' connected", steam->serial_no); @@ -655,15 +679,13 @@ static int steam_register(struct steam_device *steam) mutex_unlock(&steam_devices_lock); } - mutex_lock(&steam->mutex); + spin_lock_irqsave(&steam->lock, flags); client_opened = steam->client_opened; - if (!client_opened) + spin_unlock_irqrestore(&steam->lock, flags); + if (!client_opened) { steam_set_lizard_mode(steam, lizard_mode); - mutex_unlock(&steam->mutex); - - if (!client_opened) ret = steam_input_register(steam); - else + } else ret = 0; return ret; @@ -746,10 +768,11 @@ static void steam_client_ll_stop(struct hid_device *hdev) static int steam_client_ll_open(struct hid_device *hdev) { struct steam_device *steam = hdev->driver_data; + unsigned long flags; - mutex_lock(&steam->mutex); + spin_lock_irqsave(&steam->lock, flags); steam->client_opened = true; - mutex_unlock(&steam->mutex); + spin_unlock_irqrestore(&steam->lock, flags); steam_input_unregister(steam); @@ -764,17 +787,14 @@ static void steam_client_ll_close(struct hid_device *hdev) bool connected; spin_lock_irqsave(&steam->lock, flags); - connected = steam->connected; + steam->client_opened = false; + connected = steam->connected && !steam->client_opened; spin_unlock_irqrestore(&steam->lock, flags); - mutex_lock(&steam->mutex); - steam->client_opened = false; - if (connected) + if (connected) { steam_set_lizard_mode(steam, lizard_mode); - mutex_unlock(&steam->mutex); - - if (connected) steam_input_register(steam); + } } static int steam_client_ll_raw_request(struct hid_device *hdev, @@ -860,19 +880,12 @@ static int steam_probe(struct hid_device *hdev, steam->hdev = hdev; hid_set_drvdata(hdev, steam); spin_lock_init(&steam->lock); - mutex_init(&steam->mutex); + mutex_init(&steam->report_mutex); steam->quirks = id->driver_data; INIT_WORK(&steam->work_connect, steam_work_connect_cb); INIT_LIST_HEAD(&steam->list); INIT_WORK(&steam->rumble_work, steam_haptic_rumble_cb); - steam->client_hdev = steam_create_client_hid(hdev); - if (IS_ERR(steam->client_hdev)) { - ret = PTR_ERR(steam->client_hdev); - goto client_hdev_fail; - } - steam->client_hdev->driver_data = steam; - /* * With the real steam controller interface, do not connect hidraw. * Instead, create the client_hid and connect that. @@ -881,10 +894,6 @@ static int steam_probe(struct hid_device *hdev, if (ret) goto hid_hw_start_fail; - ret = hid_add_device(steam->client_hdev); - if (ret) - goto client_hdev_add_fail; - ret = hid_hw_open(hdev); if (ret) { hid_err(hdev, @@ -910,15 +919,26 @@ static int steam_probe(struct hid_device *hdev, } } + steam->client_hdev = steam_create_client_hid(hdev); + if (IS_ERR(steam->client_hdev)) { + ret = PTR_ERR(steam->client_hdev); + goto client_hdev_fail; + } + steam->client_hdev->driver_data = steam; + + ret = hid_add_device(steam->client_hdev); + if (ret) + goto client_hdev_add_fail; + return 0; -input_register_fail: -hid_hw_open_fail: client_hdev_add_fail: hid_hw_stop(hdev); -hid_hw_start_fail: - hid_destroy_device(steam->client_hdev); client_hdev_fail: + hid_destroy_device(steam->client_hdev); +input_register_fail: +hid_hw_open_fail: +hid_hw_start_fail: cancel_work_sync(&steam->work_connect); cancel_work_sync(&steam->rumble_work); steam_alloc_fail: @@ -936,12 +956,10 @@ static void steam_remove(struct hid_device *hdev) return; } + cancel_work_sync(&steam->work_connect); hid_destroy_device(steam->client_hdev); - mutex_lock(&steam->mutex); steam->client_hdev = NULL; steam->client_opened = false; - mutex_unlock(&steam->mutex); - cancel_work_sync(&steam->work_connect); if (steam->quirks & STEAM_QUIRK_WIRELESS) { hid_info(hdev, "Steam wireless receiver disconnected"); } @@ -1408,10 +1426,8 @@ static int steam_param_set_lizard_mode(const char *val, mutex_lock(&steam_devices_lock); list_for_each_entry(steam, &steam_devices, list) { - mutex_lock(&steam->mutex); if (!steam->client_opened) steam_set_lizard_mode(steam, lizard_mode); - mutex_unlock(&steam->mutex); } mutex_unlock(&steam_devices_lock); return 0; From patchwork Wed Dec 20 03:38:34 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vicki Pfau X-Patchwork-Id: 757710 Received: from endrift.com (endrift.com [173.255.198.10]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DC6098BF9 for ; Wed, 20 Dec 2023 03:38:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=endrift.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=endrift.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=endrift.com header.i=@endrift.com header.b="Xa6KUwrT" Received: from nebulosa.vulpes.eutheria.net (71-212-26-68.tukw.qwest.net [71.212.26.68]) by endrift.com (Postfix) with ESMTPSA id D417EA29D; Tue, 19 Dec 2023 19:38:50 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=endrift.com; s=2020; t=1703043531; bh=BWZfCq6ssUrNrzaQBXJB148FNo+Xz6aBeXcLwTvg/LE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Xa6KUwrTAzsLvLvv9FLGwY3in86QypyrOZOH33Z9BCue8v3dJ7Rl1H6pXUB2U2YrF njJGHxEVVqdfKEzRvCBJGIZJbye4f8IwW1x6l+KvuUIb0kD4fPNDC22hAZ9ABevv/Y NvgMdFJpeN8t75PNkdKXDBP5MqEbNdjuIK2asZ7jJR21YDBiA4GcRP5UA0ywVJDvOt mxa0wQ71uw20+rAjk2kp7bJ08wuM7McRw9gIfi/sKiX+CPkgA8grRJCMiNG4mYnEZ9 MD7YJRu7HDjHyXktQRPyhkdNupOjOOzjzjQ0ezgxZckW1GhdQ3Nye5L25Y2ENeWb3R 3A7pIbk24fxBg== From: Vicki Pfau To: Jiri Kosina , Benjamin Tissoires , linux-input@vger.kernel.org Cc: Vicki Pfau Subject: [PATCH 4/7] HID: hid-steam: Make client_opened a counter Date: Tue, 19 Dec 2023 19:38:34 -0800 Message-ID: <20231220033837.2135194-4-vi@endrift.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231220033837.2135194-1-vi@endrift.com> References: <20231220033609.2132033-1-vi@endrift.com> <20231220033837.2135194-1-vi@endrift.com> Precedence: bulk X-Mailing-List: linux-input@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The client_opened variable was used to track if the hidraw was opened by any clients to silence keyboard/mouse events while opened. However, there was no counting of how many clients were opened, so opening two at the same time and then closing one would fool the driver into thinking it had no remaining opened clients. Signed-off-by: Vicki Pfau --- drivers/hid/hid-steam.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/hid/hid-steam.c b/drivers/hid/hid-steam.c index 57cb58941c9f..667b5b09f931 100644 --- a/drivers/hid/hid-steam.c +++ b/drivers/hid/hid-steam.c @@ -125,7 +125,7 @@ struct steam_device { spinlock_t lock; struct hid_device *hdev, *client_hdev; struct mutex report_mutex; - bool client_opened; + unsigned long client_opened; struct input_dev __rcu *input; unsigned long quirks; struct work_struct work_connect; @@ -648,7 +648,7 @@ static void steam_battery_unregister(struct steam_device *steam) static int steam_register(struct steam_device *steam) { int ret; - bool client_opened; + unsigned long client_opened; unsigned long flags; /* @@ -771,7 +771,7 @@ static int steam_client_ll_open(struct hid_device *hdev) unsigned long flags; spin_lock_irqsave(&steam->lock, flags); - steam->client_opened = true; + steam->client_opened++; spin_unlock_irqrestore(&steam->lock, flags); steam_input_unregister(steam); @@ -787,7 +787,7 @@ static void steam_client_ll_close(struct hid_device *hdev) bool connected; spin_lock_irqsave(&steam->lock, flags); - steam->client_opened = false; + steam->client_opened--; connected = steam->connected && !steam->client_opened; spin_unlock_irqrestore(&steam->lock, flags); @@ -959,7 +959,7 @@ static void steam_remove(struct hid_device *hdev) cancel_work_sync(&steam->work_connect); hid_destroy_device(steam->client_hdev); steam->client_hdev = NULL; - steam->client_opened = false; + steam->client_opened = 0; if (steam->quirks & STEAM_QUIRK_WIRELESS) { hid_info(hdev, "Steam wireless receiver disconnected"); } From patchwork Wed Dec 20 03:38:35 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vicki Pfau X-Patchwork-Id: 756663 Received: from endrift.com (endrift.com [173.255.198.10]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 309BE8F42 for ; Wed, 20 Dec 2023 03:38:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=endrift.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=endrift.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=endrift.com header.i=@endrift.com header.b="ZIO6f7mb" Received: from nebulosa.vulpes.eutheria.net (71-212-26-68.tukw.qwest.net [71.212.26.68]) by endrift.com (Postfix) with ESMTPSA id 444F5A3BE; Tue, 19 Dec 2023 19:38:51 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=endrift.com; s=2020; t=1703043531; bh=+acOlb6AZaPXYTOzeRFR57zOtMIWVroentMWoDfyprI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ZIO6f7mb1IwpHUDV+Tzgf/yFRNX3kmZ8JTL6rXVXPC4i1QoKp3R+QYiqo8VqTVsJV MXAuwYZz2X3rDkERPbCN24h+VfvpVJoWFpKsaWR+VKEDol6yqiCg7traG4Oav/Er8F m87ats9otw0+FeFR0lZblriSUxy9xqW6wfAGcCMqLKmif/H6qGoUVIWOwAAsPilyxJ SXUyDNR2VI2etHtgucyT+XyDbjIxkVqQP8XAThSFVXW6izq41zTdbJD84K9d4+6tVN sol9T2Hus2uFRS56Mcpa+CG/DDNETABDnUzpMynncYNKqe4ZcsbbZ77uFDMkzqG/5c OyJ9sEjM/z/zw== From: Vicki Pfau To: Jiri Kosina , Benjamin Tissoires , linux-input@vger.kernel.org Cc: Vicki Pfau Subject: [PATCH 5/7] HID: hid-steam: Update list of identifiers from SDL Date: Tue, 19 Dec 2023 19:38:35 -0800 Message-ID: <20231220033837.2135194-5-vi@endrift.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231220033837.2135194-1-vi@endrift.com> References: <20231220033609.2132033-1-vi@endrift.com> <20231220033837.2135194-1-vi@endrift.com> Precedence: bulk X-Mailing-List: linux-input@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 SDL includes a list of settings (formerly called registers in this driver), reports (formerly cmds), and various other identifiers that were provided by Valve. This commit imports a significant chunk of that list as well as replacing most of the guessed names and a handful of magic constants. It also replaces bitmask definitions that used hex with the BIT macro. Signed-off-by: Vicki Pfau --- drivers/hid/hid-steam.c | 286 +++++++++++++++++++++++++++++++--------- 1 file changed, 221 insertions(+), 65 deletions(-) diff --git a/drivers/hid/hid-steam.c b/drivers/hid/hid-steam.c index 667b5b09f931..4f5c647f04dd 100644 --- a/drivers/hid/hid-steam.c +++ b/drivers/hid/hid-steam.c @@ -71,51 +71,207 @@ static LIST_HEAD(steam_devices); /* * Commands that can be sent in a feature report. - * Thanks to Valve for some valuable hints. + * Thanks to Valve and SDL for the names. */ -#define STEAM_CMD_SET_MAPPINGS 0x80 -#define STEAM_CMD_CLEAR_MAPPINGS 0x81 -#define STEAM_CMD_GET_MAPPINGS 0x82 -#define STEAM_CMD_GET_ATTRIB 0x83 -#define STEAM_CMD_GET_ATTRIB_LABEL 0x84 -#define STEAM_CMD_DEFAULT_MAPPINGS 0x85 -#define STEAM_CMD_FACTORY_RESET 0x86 -#define STEAM_CMD_WRITE_REGISTER 0x87 -#define STEAM_CMD_CLEAR_REGISTER 0x88 -#define STEAM_CMD_READ_REGISTER 0x89 -#define STEAM_CMD_GET_REGISTER_LABEL 0x8a -#define STEAM_CMD_GET_REGISTER_MAX 0x8b -#define STEAM_CMD_GET_REGISTER_DEFAULT 0x8c -#define STEAM_CMD_SET_MODE 0x8d -#define STEAM_CMD_DEFAULT_MOUSE 0x8e -#define STEAM_CMD_FORCEFEEDBAK 0x8f -#define STEAM_CMD_REQUEST_COMM_STATUS 0xb4 -#define STEAM_CMD_GET_SERIAL 0xae -#define STEAM_CMD_HAPTIC_RUMBLE 0xeb - -/* Some useful register ids */ -#define STEAM_REG_LPAD_MODE 0x07 -#define STEAM_REG_RPAD_MODE 0x08 -#define STEAM_REG_RPAD_MARGIN 0x18 -#define STEAM_REG_LED 0x2d -#define STEAM_REG_GYRO_MODE 0x30 -#define STEAM_REG_LPAD_CLICK_PRESSURE 0x34 -#define STEAM_REG_RPAD_CLICK_PRESSURE 0x35 -#define STEAM_REG_WATCHDOG_ENABLE 0x47 - -/* Raw event identifiers */ -#define STEAM_EV_INPUT_DATA 0x01 -#define STEAM_EV_CONNECT 0x03 -#define STEAM_EV_BATTERY 0x04 -#define STEAM_EV_DECK_INPUT_DATA 0x09 +enum { + ID_SET_DIGITAL_MAPPINGS = 0x80, + ID_CLEAR_DIGITAL_MAPPINGS = 0x81, + ID_GET_DIGITAL_MAPPINGS = 0x82, + ID_GET_ATTRIBUTES_VALUES = 0x83, + ID_GET_ATTRIBUTE_LABEL = 0x84, + ID_SET_DEFAULT_DIGITAL_MAPPINGS = 0x85, + ID_FACTORY_RESET = 0x86, + ID_SET_SETTINGS_VALUES = 0x87, + ID_CLEAR_SETTINGS_VALUES = 0x88, + ID_GET_SETTINGS_VALUES = 0x89, + ID_GET_SETTING_LABEL = 0x8A, + ID_GET_SETTINGS_MAXS = 0x8B, + ID_GET_SETTINGS_DEFAULTS = 0x8C, + ID_SET_CONTROLLER_MODE = 0x8D, + ID_LOAD_DEFAULT_SETTINGS = 0x8E, + ID_TRIGGER_HAPTIC_PULSE = 0x8F, + ID_TURN_OFF_CONTROLLER = 0x9F, + + ID_GET_DEVICE_INFO = 0xA1, + + ID_CALIBRATE_TRACKPADS = 0xA7, + ID_RESERVED_0 = 0xA8, + ID_SET_SERIAL_NUMBER = 0xA9, + ID_GET_TRACKPAD_CALIBRATION = 0xAA, + ID_GET_TRACKPAD_FACTORY_CALIBRATION = 0xAB, + ID_GET_TRACKPAD_RAW_DATA = 0xAC, + ID_ENABLE_PAIRING = 0xAD, + ID_GET_STRING_ATTRIBUTE = 0xAE, + ID_RADIO_ERASE_RECORDS = 0xAF, + ID_RADIO_WRITE_RECORD = 0xB0, + ID_SET_DONGLE_SETTING = 0xB1, + ID_DONGLE_DISCONNECT_DEVICE = 0xB2, + ID_DONGLE_COMMIT_DEVICE = 0xB3, + ID_DONGLE_GET_WIRELESS_STATE = 0xB4, + ID_CALIBRATE_GYRO = 0xB5, + ID_PLAY_AUDIO = 0xB6, + ID_AUDIO_UPDATE_START = 0xB7, + ID_AUDIO_UPDATE_DATA = 0xB8, + ID_AUDIO_UPDATE_COMPLETE = 0xB9, + ID_GET_CHIPID = 0xBA, + + ID_CALIBRATE_JOYSTICK = 0xBF, + ID_CALIBRATE_ANALOG_TRIGGERS = 0xC0, + ID_SET_AUDIO_MAPPING = 0xC1, + ID_CHECK_GYRO_FW_LOAD = 0xC2, + ID_CALIBRATE_ANALOG = 0xC3, + ID_DONGLE_GET_CONNECTED_SLOTS = 0xC4, + + ID_RESET_IMU = 0xCE, + + ID_TRIGGER_HAPTIC_CMD = 0xEA, + ID_TRIGGER_RUMBLE_CMD = 0xEB, +}; + +/* Settings IDs */ +enum { + /* 0 */ + SETTING_MOUSE_SENSITIVITY, + SETTING_MOUSE_ACCELERATION, + SETTING_TRACKBALL_ROTATION_ANGLE, + SETTING_HAPTIC_INTENSITY_UNUSED, + SETTING_LEFT_GAMEPAD_STICK_ENABLED, + SETTING_RIGHT_GAMEPAD_STICK_ENABLED, + SETTING_USB_DEBUG_MODE, + SETTING_LEFT_TRACKPAD_MODE, + SETTING_RIGHT_TRACKPAD_MODE, + SETTING_MOUSE_POINTER_ENABLED, + + /* 10 */ + SETTING_DPAD_DEADZONE, + SETTING_MINIMUM_MOMENTUM_VEL, + SETTING_MOMENTUM_DECAY_AMMOUNT, + SETTING_TRACKPAD_RELATIVE_MODE_TICKS_PER_PIXEL, + SETTING_HAPTIC_INCREMENT, + SETTING_DPAD_ANGLE_SIN, + SETTING_DPAD_ANGLE_COS, + SETTING_MOMENTUM_VERTICAL_DIVISOR, + SETTING_MOMENTUM_MAXIMUM_VELOCITY, + SETTING_TRACKPAD_Z_ON, + + /* 20 */ + SETTING_TRACKPAD_Z_OFF, + SETTING_SENSITIVY_SCALE_AMMOUNT, + SETTING_LEFT_TRACKPAD_SECONDARY_MODE, + SETTING_RIGHT_TRACKPAD_SECONDARY_MODE, + SETTING_SMOOTH_ABSOLUTE_MOUSE, + SETTING_STEAMBUTTON_POWEROFF_TIME, + SETTING_UNUSED_1, + SETTING_TRACKPAD_OUTER_RADIUS, + SETTING_TRACKPAD_Z_ON_LEFT, + SETTING_TRACKPAD_Z_OFF_LEFT, + + /* 30 */ + SETTING_TRACKPAD_OUTER_SPIN_VEL, + SETTING_TRACKPAD_OUTER_SPIN_RADIUS, + SETTING_TRACKPAD_OUTER_SPIN_HORIZONTAL_ONLY, + SETTING_TRACKPAD_RELATIVE_MODE_DEADZONE, + SETTING_TRACKPAD_RELATIVE_MODE_MAX_VEL, + SETTING_TRACKPAD_RELATIVE_MODE_INVERT_Y, + SETTING_TRACKPAD_DOUBLE_TAP_BEEP_ENABLED, + SETTING_TRACKPAD_DOUBLE_TAP_BEEP_PERIOD, + SETTING_TRACKPAD_DOUBLE_TAP_BEEP_COUNT, + SETTING_TRACKPAD_OUTER_RADIUS_RELEASE_ON_TRANSITION, + + /* 40 */ + SETTING_RADIAL_MODE_ANGLE, + SETTING_HAPTIC_INTENSITY_MOUSE_MODE, + SETTING_LEFT_DPAD_REQUIRES_CLICK, + SETTING_RIGHT_DPAD_REQUIRES_CLICK, + SETTING_LED_BASELINE_BRIGHTNESS, + SETTING_LED_USER_BRIGHTNESS, + SETTING_ENABLE_RAW_JOYSTICK, + SETTING_ENABLE_FAST_SCAN, + SETTING_IMU_MODE, + SETTING_WIRELESS_PACKET_VERSION, + + /* 50 */ + SETTING_SLEEP_INACTIVITY_TIMEOUT, + SETTING_TRACKPAD_NOISE_THRESHOLD, + SETTING_LEFT_TRACKPAD_CLICK_PRESSURE, + SETTING_RIGHT_TRACKPAD_CLICK_PRESSURE, + SETTING_LEFT_BUMPER_CLICK_PRESSURE, + SETTING_RIGHT_BUMPER_CLICK_PRESSURE, + SETTING_LEFT_GRIP_CLICK_PRESSURE, + SETTING_RIGHT_GRIP_CLICK_PRESSURE, + SETTING_LEFT_GRIP2_CLICK_PRESSURE, + SETTING_RIGHT_GRIP2_CLICK_PRESSURE, + + /* 60 */ + SETTING_PRESSURE_MODE, + SETTING_CONTROLLER_TEST_MODE, + SETTING_TRIGGER_MODE, + SETTING_TRACKPAD_Z_THRESHOLD, + SETTING_FRAME_RATE, + SETTING_TRACKPAD_FILT_CTRL, + SETTING_TRACKPAD_CLIP, + SETTING_DEBUG_OUTPUT_SELECT, + SETTING_TRIGGER_THRESHOLD_PERCENT, + SETTING_TRACKPAD_FREQUENCY_HOPPING, + + /* 70 */ + SETTING_HAPTICS_ENABLED, + SETTING_STEAM_WATCHDOG_ENABLE, + SETTING_TIMP_TOUCH_THRESHOLD_ON, + SETTING_TIMP_TOUCH_THRESHOLD_OFF, + SETTING_FREQ_HOPPING, + SETTING_TEST_CONTROL, + SETTING_HAPTIC_MASTER_GAIN_DB, + SETTING_THUMB_TOUCH_THRESH, + SETTING_DEVICE_POWER_STATUS, + SETTING_HAPTIC_INTENSITY, + + /* 80 */ + SETTING_STABILIZER_ENABLED, + SETTING_TIMP_MODE_MTE, +}; + +/* Input report identifiers */ +enum +{ + ID_CONTROLLER_STATE = 1, + ID_CONTROLLER_DEBUG = 2, + ID_CONTROLLER_WIRELESS = 3, + ID_CONTROLLER_STATUS = 4, + ID_CONTROLLER_DEBUG2 = 5, + ID_CONTROLLER_SECONDARY_STATE = 6, + ID_CONTROLLER_BLE_STATE = 7, + ID_CONTROLLER_DECK_STATE = 9 +}; + +/* String attribute idenitifiers */ +enum { + ATTRIB_STR_BOARD_SERIAL, + ATTRIB_STR_UNIT_SERIAL, +}; /* Values for GYRO_MODE (bitmask) */ -#define STEAM_GYRO_MODE_OFF 0x0000 -#define STEAM_GYRO_MODE_STEERING 0x0001 -#define STEAM_GYRO_MODE_TILT 0x0002 -#define STEAM_GYRO_MODE_SEND_ORIENTATION 0x0004 -#define STEAM_GYRO_MODE_SEND_RAW_ACCEL 0x0008 -#define STEAM_GYRO_MODE_SEND_RAW_GYRO 0x0010 +enum { + SETTING_GYRO_MODE_OFF = 0, + SETTING_GYRO_MODE_STEERING = BIT(0), + SETTING_GYRO_MODE_TILT = BIT(1), + SETTING_GYRO_MODE_SEND_ORIENTATION = BIT(2), + SETTING_GYRO_MODE_SEND_RAW_ACCEL = BIT(3), + SETTING_GYRO_MODE_SEND_RAW_GYRO = BIT(4), +}; + +/* Trackpad modes */ +enum { + TRACKPAD_ABSOLUTE_MOUSE, + TRACKPAD_RELATIVE_MOUSE, + TRACKPAD_DPAD_FOUR_WAY_DISCRETE, + TRACKPAD_DPAD_FOUR_WAY_OVERLAP, + TRACKPAD_DPAD_EIGHT_WAY, + TRACKPAD_RADIAL_MODE, + TRACKPAD_ABSOLUTE_DPAD, + TRACKPAD_NONE, + TRACKPAD_GESTURE_KEYBOARD, +}; /* Other random constants */ #define STEAM_SERIAL_LEN 10 @@ -226,13 +382,13 @@ static inline int steam_send_report_byte(struct steam_device *steam, u8 cmd) return steam_send_report(steam, &cmd, 1); } -static int steam_write_registers(struct steam_device *steam, +static int steam_write_settings(struct steam_device *steam, /* u8 reg, u16 val */...) { /* Send: 0x87 len (reg valLo valHi)* */ u8 reg; u16 val; - u8 cmd[64] = {STEAM_CMD_WRITE_REGISTER, 0x00}; + u8 cmd[64] = {ID_SET_SETTINGS_VALUES, 0x00}; int ret; va_list args; @@ -268,7 +424,7 @@ static int steam_get_serial(struct steam_device *steam) * Recv: 0xae 0x15 0x01 serialnumber (10 chars) */ int ret = 0; - u8 cmd[] = {STEAM_CMD_GET_SERIAL, 0x15, 0x01}; + u8 cmd[] = {ID_GET_STRING_ATTRIBUTE, 0x15, ATTRIB_STR_UNIT_SERIAL}; u8 reply[3 + STEAM_SERIAL_LEN + 1]; mutex_lock(&steam->report_mutex); @@ -278,7 +434,7 @@ static int steam_get_serial(struct steam_device *steam) ret = steam_recv_report(steam, reply, sizeof(reply)); if (ret < 0) goto out; - if (reply[0] != 0xae || reply[1] != 0x15 || reply[2] != 0x01) { + if (reply[0] != ID_GET_STRING_ATTRIBUTE || reply[1] != 0x15 || reply[2] != ATTRIB_STR_UNIT_SERIAL) { ret = -EIO; goto out; } @@ -298,7 +454,7 @@ static inline int steam_request_conn_status(struct steam_device *steam) { int ret; mutex_lock(&steam->report_mutex); - ret = steam_send_report_byte(steam, STEAM_CMD_REQUEST_COMM_STATUS); + ret = steam_send_report_byte(steam, ID_DONGLE_GET_WIRELESS_STATE); mutex_unlock(&steam->report_mutex); return ret; } @@ -308,7 +464,7 @@ static inline int steam_haptic_rumble(struct steam_device *steam, u8 left_gain, u8 right_gain) { int ret; - u8 report[11] = {STEAM_CMD_HAPTIC_RUMBLE, 9}; + u8 report[11] = {ID_TRIGGER_RUMBLE_CMD, 9}; report[3] = intensity & 0xFF; report[4] = intensity >> 8; @@ -351,28 +507,28 @@ static void steam_set_lizard_mode(struct steam_device *steam, bool enable) if (enable) { mutex_lock(&steam->report_mutex); /* enable esc, enter, cursors */ - steam_send_report_byte(steam, STEAM_CMD_DEFAULT_MAPPINGS); - /* enable mouse */ - steam_send_report_byte(steam, STEAM_CMD_DEFAULT_MOUSE); + steam_send_report_byte(steam, ID_SET_DEFAULT_DIGITAL_MAPPINGS); + /* reset settings */ + steam_send_report_byte(steam, ID_LOAD_DEFAULT_SETTINGS); mutex_unlock(&steam->report_mutex); } else { mutex_lock(&steam->report_mutex); /* disable esc, enter, cursor */ - steam_send_report_byte(steam, STEAM_CMD_CLEAR_MAPPINGS); + steam_send_report_byte(steam, ID_CLEAR_DIGITAL_MAPPINGS); if (steam->quirks & STEAM_QUIRK_DECK) { - steam_write_registers(steam, - STEAM_REG_LPAD_MODE, 0x07, /* disable mouse */ - STEAM_REG_RPAD_MODE, 0x07, /* disable mouse */ - STEAM_REG_LPAD_CLICK_PRESSURE, 0xFFFF, /* disable clicky pad */ - STEAM_REG_RPAD_CLICK_PRESSURE, 0xFFFF, /* disable clicky pad */ - STEAM_REG_WATCHDOG_ENABLE, 0, /* disable watchdog that tests if Steam is active */ + steam_write_settings(steam, + SETTING_LEFT_TRACKPAD_MODE, TRACKPAD_NONE, /* disable mouse */ + SETTING_RIGHT_TRACKPAD_MODE, TRACKPAD_NONE, /* disable mouse */ + SETTING_LEFT_TRACKPAD_CLICK_PRESSURE, 0xFFFF, /* disable haptic click */ + SETTING_RIGHT_TRACKPAD_CLICK_PRESSURE, 0xFFFF, /* disable haptic click */ + SETTING_STEAM_WATCHDOG_ENABLE, 0, /* disable watchdog that tests if Steam is active */ 0); mutex_unlock(&steam->report_mutex); } else { - steam_write_registers(steam, - STEAM_REG_LPAD_MODE, 0x07, /* disable mouse */ - STEAM_REG_RPAD_MODE, 0x07, /* disable mouse */ + steam_write_settings(steam, + SETTING_LEFT_TRACKPAD_MODE, TRACKPAD_NONE, /* disable mouse */ + SETTING_RIGHT_TRACKPAD_MODE, TRACKPAD_NONE, /* disable mouse */ 0); mutex_unlock(&steam->report_mutex); } @@ -1362,7 +1518,7 @@ static int steam_raw_event(struct hid_device *hdev, return 0; switch (data[2]) { - case STEAM_EV_INPUT_DATA: + case ID_CONTROLLER_STATE: if (steam->client_opened) return 0; rcu_read_lock(); @@ -1371,7 +1527,7 @@ static int steam_raw_event(struct hid_device *hdev, steam_do_input_event(steam, input, data); rcu_read_unlock(); break; - case STEAM_EV_DECK_INPUT_DATA: + case ID_CONTROLLER_DECK_STATE: if (steam->client_opened) return 0; rcu_read_lock(); @@ -1380,7 +1536,7 @@ static int steam_raw_event(struct hid_device *hdev, steam_do_deck_input_event(steam, input, data); rcu_read_unlock(); break; - case STEAM_EV_CONNECT: + case ID_CONTROLLER_WIRELESS: /* * The payload of this event is a single byte: * 0x01: disconnected. @@ -1395,7 +1551,7 @@ static int steam_raw_event(struct hid_device *hdev, break; } break; - case STEAM_EV_BATTERY: + case ID_CONTROLLER_STATUS: if (steam->quirks & STEAM_QUIRK_WIRELESS) { rcu_read_lock(); battery = rcu_dereference(steam->battery); From patchwork Wed Dec 20 03:38:36 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vicki Pfau X-Patchwork-Id: 756662 Received: from endrift.com (endrift.com [173.255.198.10]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8D26E8F51 for ; Wed, 20 Dec 2023 03:38:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=endrift.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=endrift.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=endrift.com header.i=@endrift.com header.b="RbP3X1Mk" Received: from nebulosa.vulpes.eutheria.net (71-212-26-68.tukw.qwest.net [71.212.26.68]) by endrift.com (Postfix) with ESMTPSA id A7909A42D; Tue, 19 Dec 2023 19:38:51 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=endrift.com; s=2020; t=1703043531; bh=1BVG6U844bDtSFQD7eJ/tqwdyFj5F6N7Pc+v7DEzXLM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=RbP3X1MksO46lUEkXbUcYl2cK9W5oL3PPcR4JGBKwCjPLtWs0EGcsylhUtgEnx5h1 YugfxkopZ8tb1akDOdBjzrpCbbVdn5SWvT62XTO4Rc1CLu9mHEGh0ksPc/gEe5dq2f 6LlZCULyxO4Nu0vYfiQ/Ger9j+hnT6H7wt/nvyGPKFPlqK1FlWfnjQIvJ/co/MGEXx abLkIRqjBL91qNgCp4IP/uglcBYzgwJHPsKwSd+QVApX5bEIJNlozp8w6MN41e9SCd 0Kcmd8Nx37bOHvWfEyj+ON3GsmxbVnlG+hT6TchoLBAXVBqIqRoN9Gc5j8xhN4QQnq Pcle/TK4xOdWw== From: Vicki Pfau To: Jiri Kosina , Benjamin Tissoires , linux-input@vger.kernel.org Cc: Vicki Pfau Subject: [PATCH 6/7] HID: hid-steam: Better handling of serial number length Date: Tue, 19 Dec 2023 19:38:36 -0800 Message-ID: <20231220033837.2135194-6-vi@endrift.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231220033837.2135194-1-vi@endrift.com> References: <20231220033609.2132033-1-vi@endrift.com> <20231220033837.2135194-1-vi@endrift.com> Precedence: bulk X-Mailing-List: linux-input@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The second byte of the GET_STRING_ATTRIB report is a length, so we should set the size of the buffer to be the size we're actually requesting, and only reject the reply if the length out is nonsensical. Signed-off-by: Vicki Pfau --- drivers/hid/hid-steam.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/hid/hid-steam.c b/drivers/hid/hid-steam.c index 4f5c647f04dd..a0ed8812e7ea 100644 --- a/drivers/hid/hid-steam.c +++ b/drivers/hid/hid-steam.c @@ -274,7 +274,7 @@ enum { }; /* Other random constants */ -#define STEAM_SERIAL_LEN 10 +#define STEAM_SERIAL_LEN 0x15 struct steam_device { struct list_head list; @@ -421,10 +421,10 @@ static int steam_get_serial(struct steam_device *steam) { /* * Send: 0xae 0x15 0x01 - * Recv: 0xae 0x15 0x01 serialnumber (10 chars) + * Recv: 0xae 0x15 0x01 serialnumber */ int ret = 0; - u8 cmd[] = {ID_GET_STRING_ATTRIBUTE, 0x15, ATTRIB_STR_UNIT_SERIAL}; + u8 cmd[] = {ID_GET_STRING_ATTRIBUTE, sizeof(steam->serial_no), ATTRIB_STR_UNIT_SERIAL}; u8 reply[3 + STEAM_SERIAL_LEN + 1]; mutex_lock(&steam->report_mutex); @@ -434,12 +434,13 @@ static int steam_get_serial(struct steam_device *steam) ret = steam_recv_report(steam, reply, sizeof(reply)); if (ret < 0) goto out; - if (reply[0] != ID_GET_STRING_ATTRIBUTE || reply[1] != 0x15 || reply[2] != ATTRIB_STR_UNIT_SERIAL) { + if (reply[0] != ID_GET_STRING_ATTRIBUTE || reply[1] < 1 || + reply[1] > sizeof(steam->serial_no) || reply[2] != ATTRIB_STR_UNIT_SERIAL) { ret = -EIO; goto out; } reply[3 + STEAM_SERIAL_LEN] = 0; - strscpy(steam->serial_no, reply + 3, sizeof(steam->serial_no)); + strscpy(steam->serial_no, reply + 3, reply[1]); out: mutex_unlock(&steam->report_mutex); return ret; From patchwork Wed Dec 20 03:38:37 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vicki Pfau X-Patchwork-Id: 757709 Received: from endrift.com (endrift.com [173.255.198.10]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F33D18F71 for ; Wed, 20 Dec 2023 03:38:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=endrift.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=endrift.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=endrift.com header.i=@endrift.com header.b="K/xWmKdE" Received: from nebulosa.vulpes.eutheria.net (71-212-26-68.tukw.qwest.net [71.212.26.68]) by endrift.com (Postfix) with ESMTPSA id 165E6A44F; Tue, 19 Dec 2023 19:38:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=endrift.com; s=2020; t=1703043532; bh=8bCOUzUrQg9elX2FEtn+dfNwylvEX/QEcxzQDCLy9YM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=K/xWmKdEFtVq68G2Pa4O53H0lOsZ7P5KL7g9U3aNmjptqn3s39+oG7IsTN8vWvN3K 60MIjAt7kA/jKsD0uWZUIKV6OtYzo4pCW0w+rhzOBXRDKUuva5HdWVLTSXfsX151s2 UcxlPkmDT0XafHTMxIzZYsi8oRR2rMT33Nvi7hkhqEVS950B/7oely67rI0x7gP+ai eUPARqodhqbNHVO6GPFowj/jj2HNJZ/hju0u+ja9rHADMn+aMw8g+6VcGEthFxQTsc eFohiflUu42Jf6YFAkw6YSjvlTcLaWE4a375y1A/Mm1cj7Y9/aHmup3yUWW5rt8368 yDebWzDopSwvw== From: Vicki Pfau To: Jiri Kosina , Benjamin Tissoires , linux-input@vger.kernel.org Cc: Vicki Pfau Subject: [PATCH 7/7] HID: hid-steam: Add gamepad-only mode switched to by holding options Date: Tue, 19 Dec 2023 19:38:37 -0800 Message-ID: <20231220033837.2135194-7-vi@endrift.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231220033837.2135194-1-vi@endrift.com> References: <20231220033609.2132033-1-vi@endrift.com> <20231220033837.2135194-1-vi@endrift.com> Precedence: bulk X-Mailing-List: linux-input@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 This commit adds a hotkey to switch between "gamepad" mode (mouse and keyboard disabled) and "desktop" mode (gamepad disabled) by holding down the options button (mapped here as the start button). This mirrors the behavior of the official Steam client. This also adds and uses a function for generating haptic pulses, as Steam also does when engaging this hotkey. Signed-off-by: Vicki Pfau --- drivers/hid/hid-steam.c | 113 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 103 insertions(+), 10 deletions(-) diff --git a/drivers/hid/hid-steam.c b/drivers/hid/hid-steam.c index a0ed8812e7ea..b3c4e50e248a 100644 --- a/drivers/hid/hid-steam.c +++ b/drivers/hid/hid-steam.c @@ -273,6 +273,11 @@ enum { TRACKPAD_GESTURE_KEYBOARD, }; +/* Pad identifiers for the deck */ +#define STEAM_PAD_LEFT 0 +#define STEAM_PAD_RIGHT 1 +#define STEAM_PAD_BOTH 2 + /* Other random constants */ #define STEAM_SERIAL_LEN 0x15 @@ -291,6 +296,9 @@ struct steam_device { struct power_supply __rcu *battery; u8 battery_charge; u16 voltage; + struct delayed_work mode_switch; + bool did_mode_switch; + bool gamepad_mode; struct work_struct rumble_work; u16 rumble_left; u16 rumble_right; @@ -460,6 +468,37 @@ static inline int steam_request_conn_status(struct steam_device *steam) return ret; } +/* + * Send a haptic pulse to the trackpads + * Duration and interval are measured in microseconds, count is the number + * of pulses to send for duration time with interval microseconds between them + * and gain is measured in decibels, ranging from -24 to +6 + */ +static inline int steam_haptic_pulse(struct steam_device *steam, u8 pad, + u16 duration, u16 interval, u16 count, u8 gain) +{ + int ret; + u8 report[10] = {ID_TRIGGER_HAPTIC_PULSE, 8}; + + /* Left and right are swapped on this report for legacy reasons */ + if (pad < STEAM_PAD_BOTH) + pad ^= 1; + + report[2] = pad; + report[3] = duration & 0xFF; + report[4] = duration >> 8; + report[5] = interval & 0xFF; + report[6] = interval >> 8; + report[7] = count & 0xFF; + report[8] = count >> 8; + report[9] = gain; + + mutex_lock(&steam->report_mutex); + ret = steam_send_report(steam, report, sizeof(report)); + mutex_unlock(&steam->report_mutex); + return ret; +} + static inline int steam_haptic_rumble(struct steam_device *steam, u16 intensity, u16 left_speed, u16 right_speed, u8 left_gain, u8 right_gain) @@ -505,6 +544,9 @@ static int steam_play_effect(struct input_dev *dev, void *data, static void steam_set_lizard_mode(struct steam_device *steam, bool enable) { + if (steam->gamepad_mode) + enable = false; + if (enable) { mutex_lock(&steam->report_mutex); /* enable esc, enter, cursors */ @@ -542,11 +584,18 @@ static int steam_input_open(struct input_dev *dev) unsigned long flags; bool set_lizard_mode; - spin_lock_irqsave(&steam->lock, flags); - set_lizard_mode = !steam->client_opened && lizard_mode; - spin_unlock_irqrestore(&steam->lock, flags); - if (set_lizard_mode) - steam_set_lizard_mode(steam, false); + /* + * Disabling lizard mode automatically is only done on the Steam + * Controller. On the Steam Deck, this is toggled manually by holding + * the options button instead, handled by steam_mode_switch_cb. + */ + if (!(steam->quirks & STEAM_QUIRK_DECK)) { + spin_lock_irqsave(&steam->lock, flags); + set_lizard_mode = !steam->client_opened && lizard_mode; + spin_unlock_irqrestore(&steam->lock, flags); + if (set_lizard_mode) + steam_set_lizard_mode(steam, false); + } return 0; } @@ -557,11 +606,13 @@ static void steam_input_close(struct input_dev *dev) unsigned long flags; bool set_lizard_mode; - spin_lock_irqsave(&steam->lock, flags); - set_lizard_mode = !steam->client_opened && lizard_mode; - spin_unlock_irqrestore(&steam->lock, flags); - if (set_lizard_mode) - steam_set_lizard_mode(steam, true); + if (!(steam->quirks & STEAM_QUIRK_DECK)) { + spin_lock_irqsave(&steam->lock, flags); + set_lizard_mode = !steam->client_opened && lizard_mode; + spin_unlock_irqrestore(&steam->lock, flags); + if (set_lizard_mode) + steam_set_lizard_mode(steam, true); + } } static enum power_supply_property steam_battery_props[] = { @@ -886,6 +937,34 @@ static void steam_work_connect_cb(struct work_struct *work) } } +static void steam_mode_switch_cb(struct work_struct *work) +{ + struct steam_device *steam = container_of(to_delayed_work(work), + struct steam_device, mode_switch); + unsigned long flags; + bool client_opened; + steam->gamepad_mode = !steam->gamepad_mode; + if (!lizard_mode) + return; + + if (steam->gamepad_mode) + steam_set_lizard_mode(steam, false); + else { + spin_lock_irqsave(&steam->lock, flags); + client_opened = steam->client_opened; + spin_unlock_irqrestore(&steam->lock, flags); + if (!client_opened) + steam_set_lizard_mode(steam, lizard_mode); + } + + steam_haptic_pulse(steam, STEAM_PAD_RIGHT, 0x190, 0, 1, 0); + if (steam->gamepad_mode) { + steam_haptic_pulse(steam, STEAM_PAD_LEFT, 0x14D, 0x14D, 0x2D, 0); + } else { + steam_haptic_pulse(steam, STEAM_PAD_LEFT, 0x1F4, 0x1F4, 0x1E, 0); + } +} + static bool steam_is_valve_interface(struct hid_device *hdev) { struct hid_report_enum *rep_enum; @@ -1040,6 +1119,7 @@ static int steam_probe(struct hid_device *hdev, mutex_init(&steam->report_mutex); steam->quirks = id->driver_data; INIT_WORK(&steam->work_connect, steam_work_connect_cb); + INIT_DELAYED_WORK(&steam->mode_switch, steam_mode_switch_cb); INIT_LIST_HEAD(&steam->list); INIT_WORK(&steam->rumble_work, steam_haptic_rumble_cb); @@ -1097,6 +1177,7 @@ static int steam_probe(struct hid_device *hdev, hid_hw_open_fail: hid_hw_start_fail: cancel_work_sync(&steam->work_connect); + cancel_delayed_work_sync(&steam->mode_switch); cancel_work_sync(&steam->rumble_work); steam_alloc_fail: hid_err(hdev, "%s: failed with error %d\n", @@ -1113,6 +1194,7 @@ static void steam_remove(struct hid_device *hdev) return; } + cancel_delayed_work_sync(&steam->mode_switch); cancel_work_sync(&steam->work_connect); hid_destroy_device(steam->client_hdev); steam->client_hdev = NULL; @@ -1398,6 +1480,17 @@ static void steam_do_deck_input_event(struct steam_device *steam, b13 = data[13]; b14 = data[14]; + if (!(b9 & BIT(6)) && steam->did_mode_switch) { + steam->did_mode_switch = false; + cancel_delayed_work_sync(&steam->mode_switch); + } else if (!steam->client_opened && (b9 & BIT(6)) && !steam->did_mode_switch) { + steam->did_mode_switch = true; + schedule_delayed_work(&steam->mode_switch, 45 * HZ / 100); + } + + if (!steam->gamepad_mode) + return; + lpad_touched = b10 & BIT(3); rpad_touched = b10 & BIT(4);