Support Nereid Steam Controller receiver

This commit is contained in:
Dan Bosscher committed 2026-08-03 11:25:58 +01:00
1 parent 0245f7f406
commit af7182f6a0
5 files changed
+18 -13

No files matched your search

+3 -3
View File
@@ -32,7 +32,7 @@ When **Steamless Mode** is active, the app disables the controller's built-in ke
### To run
- Windows 10 or later (64-bit)
- [ViGEmBus](https://github.com/nefarius/ViGEmBus/releases/latest) driver installed
- Steam Controller — wired USB (PID `0x1302`), wireless dongle (PID `0x1304`), or Bluetooth LE (PID `0x1303`, pair via Windows Bluetooth settings)
- 2026 Steam Controller (Triton) — wired USB (PID `0x1302`), Bluetooth LE (PID `0x1303`, pair via Windows Bluetooth settings), Proteus/Puck receiver (PID `0x1304`), or Nereid receiver (PID `0x1305`)
- Steam **closed**, or a coexistence strategy selected from the tray's debug menu
### To build
@@ -79,13 +79,13 @@ Steam normally opens the physical Steam Controller even while the client is idle
The tray's **Debug: Steam coexistence** submenu can apply one of three strategies. Hover an option to see its tradeoffs; selecting one safely releases the controller, closes Steam, applies the setting, and relaunches Steam immediately. If a Steam game is running, the app asks before closing it.
- **Restore Steam's original controller settings** is the explicit off switch. It restores the Valve PID blacklist and `-nojoy` state recorded before SteamlessController first changed them, then SteamlessController yields whenever Steam can see the physical controller.
- **Reserve Steam Controller for Steamless** is recommended for Game Pass. It adds only the three Steam Controller product IDs to Steam's per-device blacklist, leaving Steam Input available for other controller types. Steam Controller-specific layouts, gyro, and touch menus are unavailable in Steam.
- **Reserve Steam Controller for Steamless** is recommended for Game Pass. It adds only the four supported 2026 Steam Controller product IDs to Steam's per-device blacklist, leaving Steam Input available for other controller types. Steam Controller-specific layouts, gyro, and touch menus are unavailable in Steam.
- **Disable all Steam controller support (`-nojoy`)** disables all Steam client controller support, including Steam Input and Big Picture controller navigation. The app adds the flag to Steam's existing Windows startup entry; launching Steam another way without the flag is detected and SteamlessController safely yields.
The blacklist option backs up `config/config.vdf` to `config/config.vdf.steamlesscontroller.bak`, preserves unrelated blacklist entries, and manages this property inside the outer `InstallConfigStore` object:
```vdf
"controller_blacklist" "28de/1302,28de/1303,28de/1304"
"controller_blacklist" "28de/1302,28de/1303,28de/1304,28de/1305"
```
SteamlessController verifies both the setting and Steam's current `logs/controller.txt` session before treating the blacklist as safe. For `-nojoy`, it verifies the running `steam.exe` command line through Windows Management Instrumentation. Missing or stale evidence always makes SteamlessController yield rather than risk duplicate input.
+2 -2
View File
@@ -20,8 +20,8 @@ constexpr wchar_t STRATEGY_VALUE[] = L"SteamStrategy";
constexpr wchar_t BASELINE_CAPTURED_VALUE[] = L"SteamBaselineCaptured";
constexpr wchar_t BASELINE_BLACKLIST_VALUE[] = L"SteamBaselineBlacklistMask";
constexpr wchar_t BASELINE_NOJOY_VALUE[] = L"SteamBaselineNoJoy";
constexpr std::array<const char*, 3> STEAM_CONTROLLER_IDS = {
"28de/1302", "28de/1303", "28de/1304"
constexpr std::array<const char*, 4> STEAM_CONTROLLER_IDS = {
"28de/1302", "28de/1303", "28de/1304", "28de/1305"
};
constexpr DWORD ALL_STEAM_CONTROLLER_IDS =
(1u << STEAM_CONTROLLER_IDS.size()) - 1u;
+3 -1
View File
@@ -244,7 +244,9 @@ static bool IsControllerHiddenFromSteam(const SteamProcess& steam) {
return ReportControllerHidden(false, "current controller session unavailable");
const std::string session = log.substr(sessionPos);
constexpr const char* ids[] = {"28de/1302", "28de/1303", "28de/1304"};
constexpr const char* ids[] = {
"28de/1302", "28de/1303", "28de/1304", "28de/1305"
};
bool hidden = false;
for (const char* id : ids) {
std::string type(id);
+6 -4
View File
@@ -54,7 +54,8 @@ static constexpr uint8_t HAPTIC_COMMAND_CLICK = 2;
std::vector<std::wstring> SteamController::EnumerateAll() {
std::vector<std::wstring> result;
for (uint16_t pid : { SC2026_PID, SC2026_BT_PID, SC2026_DONGLE_PID })
for (uint16_t pid : { SC2026_PID, SC2026_BT_PID, SC2026_DONGLE_PID,
SC2026_NEREID_DONGLE_PID })
for (auto const& path : HidDevice::Enumerate(
VALVE_VID, pid, VENDOR_USAGE_PAGE, CONTROLLER_USAGE))
result.push_back(path);
@@ -72,7 +73,8 @@ SteamController::Transport SteamController::TransportFromPath(const std::wstring
p.find(L"bthledevice") != std::wstring::npos ||
p.find(L"bthenum") != std::wstring::npos)
return Transport::Bluetooth;
if (p.find(L"pid_1304") != std::wstring::npos)
if (p.find(L"pid_1304") != std::wstring::npos ||
p.find(L"pid_1305") != std::wstring::npos)
return Transport::Dongle;
if (p.find(L"pid_1302") != std::wstring::npos ||
p.find(L"pid_1303") != std::wstring::npos)
@@ -92,8 +94,8 @@ const char* SteamController::TransportName(Transport t) {
bool SteamController::Open() {
auto paths = EnumerateAll();
if (paths.empty()) {
printf("No Steam Controller found (wired PID=%04X or dongle PID=%04X).\n",
SC2026_PID, SC2026_DONGLE_PID);
printf("No Steam Controller found (wired PID=%04X or dongle PIDs=%04X/%04X).\n",
SC2026_PID, SC2026_DONGLE_PID, SC2026_NEREID_DONGLE_PID);
return false;
}
+4 -3
View File
@@ -9,9 +9,10 @@
class SteamController {
public:
static constexpr uint16_t VALVE_VID = 0x28DE;
static constexpr uint16_t SC2026_PID = 0x1302; // wired USB
static constexpr uint16_t SC2026_BT_PID = 0x1303; // Bluetooth LE (HID over GATT)
static constexpr uint16_t SC2026_DONGLE_PID = 0x1304; // wireless dongle ("Steam Controller Puck")
static constexpr uint16_t SC2026_PID = 0x1302; // wired USB
static constexpr uint16_t SC2026_BT_PID = 0x1303; // Bluetooth LE (HID over GATT)
static constexpr uint16_t SC2026_DONGLE_PID = 0x1304; // Proteus dongle ("Steam Controller Puck")
static constexpr uint16_t SC2026_NEREID_DONGLE_PID = 0x1305; // Nereid receiver
// How the controller is linked to the PC. Bluetooth is detected from the
// device interface path (HOGP service GUID / bthenum), the other two by PID.