Controller Name
Redragon Juno G818 (DualShock 4 clone)
Current Controller Behaviour
Controller is not successful in pairing with the console
Controller vendor and product ID
054c:09cc
Supported Features
Input Report Format
Report descriptor parsed via WebHID. Input report 0x01:
byte 0 usage 0x00010030 X left stick X
byte 1 usage 0x00010031 Y left stick Y
byte 2 usage 0x00010032 Z right stick X
byte 3 usage 0x00010035 Rz right stick Y
byte 4 (low) usage 0x00010039 Hat dpad, 0-7, 8 = released
byte 4 (high) + byte 5 + byte 6:2 Buttons 1-14
byte 7 usage 0x00010033 Rx L2 analog
byte 8 usage 0x00010034 Ry R2 analog
Idle state: 80 80 80 80 08 00 00 00 00
This is byte-for-byte identical to Dualshock4InputReport0x01, so no new mapping
is needed. The controller also declares input reports 0x11-0x19 and feature
reports 0x02/0x05/0x06/0xa3 exactly like a real DS4.
Additional Details
TL;DR: A DS4 clone that is byte-for-byte indistinguishable from a genuine DualShock 4 at every layer MissionControl inspects. It is detected and renamed correctly, but SSP authentication never completes, so it never bonds and the HID channels are never opened. Because it shares 054c:09cc with the real DS4, it cannot be handled by adding a new controller class.
Identity
|
|
| Product |
Redragon Juno G818 |
| BT name |
Wireless Controller |
| VID:PID |
054c:09cc (identical to official DualShock 4 v2) |
| Class of Device |
0x002508 (Peripheral / Gamepad) |
| HID descriptor |
Byte-identical to a genuine DS4 |
Identify() returns ControllerType_Dualshock4 and IsAllowedDeviceClass() passes, so the device is correctly renamed to Pro Controller in the inquiry results. The mapping would be correct if it ever connected.
Environment
- HOS 22.5.0 / Atmosphère 1.11.2 / emuMMC
- MissionControl built from
master @ d3941d4, with added logging (see below)
- A genuine DualShock 4 pairs and works normally on the same console and SD card
Instrumented trace
I patched bluetooth_core.cpp / bluetooth_hid.cpp to log every btdrv core and HID event to the SD card. Every pairing attempt produces exactly this sequence, repeated identically:
EVT 0 InquiryDevice 8c:41:f2:4e:83:38
INQ 8c:41:f2:4e:83:38 cod=002508 allowed=1 name=Wireless Controller
EVT 1 InquiryStatus status=0
EVT 4 Connection subtype=1 8c:41:f2:4e:83:38 <- SspConfirmRequest
EVT 3 SspRequest just_works=1 passkey=191053 cod=002508 name=Wireless Controller
... 5-8 seconds ...
EVT 4 Connection subtype=3 8c:41:f2:4e:83:38 <- undocumented subtype
btdrvGetPairedDeviceInfo -> rc=0x0000d671 <- never bonds
Observed across ~60 attempts. Notes:
just_works is always 1, and a fresh 6-digit passkey is generated on each attempt.
- The delay before the failing event is 5-8 s, i.e. an authentication timeout, not an immediate rejection.
- No
BtdrvHidEventType_Connection is ever delivered. HandleConnectionStateEventV12 never runs.
BtdrvConnectionEventType subtype 3 is not in libnx's enum (only 0/1/2 are defined). It appears to be the failure indicator on 12.0.0+, and carries no status payload — connection.v12.reserved is all zeros for it.
Two incidental libnx documentation notes
While dumping raw event bytes I noticed two things that may be worth correcting upstream:
-
For BtdrvEventType_Connection with subtype 1, connection.v12.reserved is not reserved — it contains the device name as ASCII:
01 00 00 00 | 8c 41 f2 4e 83 38 | 57 69 72 65 6c 65 73 73 20 43 6f 6e 74 72 6f 6c 6c 65 72
W i r e l e s s C o n t r o l l e r
-
btdrvGetPairedDeviceInfo reports link_key_present = 0 even for devices where setsysGetBluetoothDevicesSettings reports 1 with a valid key present. It appears to mask that field.
Ruled out
- Not the exefs patches or the install — a genuine DS4 pairs fine on the same setup.
- Not
IsAllowedDeviceClass — logged, returns 1, CoD is 0x002508.
- Not the SSP response. I intercepted
BtdrvEventType_SspRequest and called btdrvRespondToSspRequest(addr, 0, true, passkey) directly. It returns rc=0x00000000, and the outcome is identical to letting btm answer. I alternated both behaviours within a single run — same 5-8 s timeout either way.
- Not the report mapping — the descriptor and the report
0x01 layout match Dualshock4InputReport0x01 exactly.
Workarounds attempted, both unsuccessful
1. DS3-style trust injection. Following Dualshock3Controller::UsbPair, I called btdrvAddPairedDeviceInfo() and faked a BtdrvConnectionEventType_Suspended event. The record is written successfully (rc=0) and persists, but the controller keeps issuing SSP requests — having no key of its own, it never attempts a bonded reconnect. No HID connection ever follows.
2. Link key transplant + host spoofing. I paired the controller to a Windows PC (where it works fine), extracted the link key from BTHPORT\Parameters\Keys, wrote it into the pairing database via setsysSetBluetoothDevicesSettings (verified link_key_present=1, and the resulting record is byte-identical to the working DS4 entry apart from address and key), and set host_address/host_name to the PC's adapter. The controller reached the console once — PendingConnections count=1 held for 4.5 s — but the link dropped, and subsequent attempts produced no activity at all.
I also tried driving the connection from the console side with btdrvTriggerConnection / btdrvOpenHidConnection. These return status=2 (Failed) within ~20 ms, but a genuine DS4 that was not even physically present produced an identical result, so that path only reports "peer not reachable" and isn't informative here.
Question
Have you seen this pattern before with DS4 clones? My reading is that the failure is in the controller's own SSP implementation, below the layer the mitm can reach, and therefore not fixable from the sysmodule — but you know this stack far better than I do, so I would rather ask than assume.
Happy to run further instrumented builds if there is something specific worth logging.
Controller Name
Redragon Juno G818 (DualShock 4 clone)
Current Controller Behaviour
Controller is not successful in pairing with the console
Controller vendor and product ID
054c:09cc
Supported Features
Input Report Format
Report descriptor parsed via WebHID. Input report 0x01:
byte 0 usage 0x00010030 X left stick X
byte 1 usage 0x00010031 Y left stick Y
byte 2 usage 0x00010032 Z right stick X
byte 3 usage 0x00010035 Rz right stick Y
byte 4 (low) usage 0x00010039 Hat dpad, 0-7, 8 = released
byte 4 (high) + byte 5 + byte 6:2 Buttons 1-14
byte 7 usage 0x00010033 Rx L2 analog
byte 8 usage 0x00010034 Ry R2 analog
Idle state: 80 80 80 80 08 00 00 00 00
This is byte-for-byte identical to Dualshock4InputReport0x01, so no new mapping
is needed. The controller also declares input reports 0x11-0x19 and feature
reports 0x02/0x05/0x06/0xa3 exactly like a real DS4.
Additional Details
TL;DR: A DS4 clone that is byte-for-byte indistinguishable from a genuine DualShock 4 at every layer MissionControl inspects. It is detected and renamed correctly, but SSP authentication never completes, so it never bonds and the HID channels are never opened. Because it shares
054c:09ccwith the real DS4, it cannot be handled by adding a new controller class.Identity
Wireless Controller054c:09cc(identical to official DualShock 4 v2)0x002508(Peripheral / Gamepad)Identify()returnsControllerType_Dualshock4andIsAllowedDeviceClass()passes, so the device is correctly renamed toPro Controllerin the inquiry results. The mapping would be correct if it ever connected.Environment
master@d3941d4, with added logging (see below)Instrumented trace
I patched
bluetooth_core.cpp/bluetooth_hid.cppto log every btdrv core and HID event to the SD card. Every pairing attempt produces exactly this sequence, repeated identically:Observed across ~60 attempts. Notes:
just_worksis always1, and a fresh 6-digit passkey is generated on each attempt.BtdrvHidEventType_Connectionis ever delivered.HandleConnectionStateEventV12never runs.BtdrvConnectionEventTypesubtype3is not in libnx's enum (only0/1/2are defined). It appears to be the failure indicator on 12.0.0+, and carries no status payload —connection.v12.reservedis all zeros for it.Two incidental libnx documentation notes
While dumping raw event bytes I noticed two things that may be worth correcting upstream:
For
BtdrvEventType_Connectionwith subtype1,connection.v12.reservedis not reserved — it contains the device name as ASCII:btdrvGetPairedDeviceInforeportslink_key_present = 0even for devices wheresetsysGetBluetoothDevicesSettingsreports1with a valid key present. It appears to mask that field.Ruled out
IsAllowedDeviceClass— logged, returns1, CoD is0x002508.BtdrvEventType_SspRequestand calledbtdrvRespondToSspRequest(addr, 0, true, passkey)directly. It returnsrc=0x00000000, and the outcome is identical to letting btm answer. I alternated both behaviours within a single run — same 5-8 s timeout either way.0x01layout matchDualshock4InputReport0x01exactly.Workarounds attempted, both unsuccessful
1. DS3-style trust injection. Following
Dualshock3Controller::UsbPair, I calledbtdrvAddPairedDeviceInfo()and faked aBtdrvConnectionEventType_Suspendedevent. The record is written successfully (rc=0) and persists, but the controller keeps issuing SSP requests — having no key of its own, it never attempts a bonded reconnect. No HID connection ever follows.2. Link key transplant + host spoofing. I paired the controller to a Windows PC (where it works fine), extracted the link key from
BTHPORT\Parameters\Keys, wrote it into the pairing database viasetsysSetBluetoothDevicesSettings(verifiedlink_key_present=1, and the resulting record is byte-identical to the working DS4 entry apart from address and key), and sethost_address/host_nameto the PC's adapter. The controller reached the console once —PendingConnections count=1held for 4.5 s — but the link dropped, and subsequent attempts produced no activity at all.I also tried driving the connection from the console side with
btdrvTriggerConnection/btdrvOpenHidConnection. These returnstatus=2 (Failed)within ~20 ms, but a genuine DS4 that was not even physically present produced an identical result, so that path only reports "peer not reachable" and isn't informative here.Question
Have you seen this pattern before with DS4 clones? My reading is that the failure is in the controller's own SSP implementation, below the layer the mitm can reach, and therefore not fixable from the sysmodule — but you know this stack far better than I do, so I would rather ask than assume.
Happy to run further instrumented builds if there is something specific worth logging.