Skip to content

Commit

Permalink
✨ Implement Razer DeathAdder 3.5G support over the legacy driver. 🎉
Browse files Browse the repository at this point in the history
Spent way too much time on this device, but at least the annoying part is done.
  • Loading branch information
hexawyz committed Sep 17, 2024
1 parent dc22358 commit 84be046
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 2 deletions.
2 changes: 2 additions & 0 deletions Docs/Razer DeathAdder 3.5G.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ Thankfully, this time, the driver is very lean compared to the mess of the newer
What appears obvious from the get-go is that this driver can actually read the firmware version, something that I never observed with Synapse.
This is done via a get report URB.

From a quick search through the driver, the IOCTL to use to send report `10` should be `222528`. A naive test sending only the raw 4 byte payload yielded the correct results, so… it works.

### Synapse 2 Driver

Razer, as always, installs a lot of system drivers for their devices. This made things a bit more complicated to find out, but one driver was seemingly "pre-installed" on my computer, presumably from an connection of the mouse a few years ago.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,9 @@ CancellationToken cancellationToken
throw new InvalidOperationException("The devices interface for the device were not found.");
}

var transport = driverType switch
DeathAdderTransport transport = driverType switch
{
KernelDriverType.DeathAdderNew => throw new NotImplementedException("Legacy driver is not implemented yet."),
KernelDriverType.DeathAdderNew => new DeathAdderNewTransport(),
KernelDriverType.RzUdd => await RzUddTransport.CreateAsync(productId, cancellationToken).ConfigureAwait(false),
_ => throw new NotImplementedException("This device requires a kernel driver to work."),
};
Expand Down Expand Up @@ -358,6 +358,27 @@ internal abstract class DeathAdderTransport : IAsyncDisposable
public abstract Task UpdateSettingsAsync(byte pollingRate, byte dpiIndex, byte profileIndex, byte lightingState, CancellationToken cancellationToken);
}

internal sealed class DeathAdderNewTransport : DeathAdderTransport
{
private const int UpdateSettingsIoControlCode = 0x222528;

private readonly byte[] _buffer;

public DeathAdderNewTransport() : base(new(Device.OpenHandle(@"\\.\DANew", DeviceAccess.None, FileShare.ReadWrite), FileAccess.ReadWrite, 0, true))
{
_buffer = GC.AllocateUninitializedArray<byte>(4, true);
}

public override async Task UpdateSettingsAsync(byte pollingRate, byte dpiIndex, byte profileIndex, byte lightingState, CancellationToken cancellationToken)
{
_buffer[0] = pollingRate;
_buffer[1] = dpiIndex;
_buffer[2] = profileIndex;
_buffer[3] = lightingState;
await ControlDevice.IoControlAsync(UpdateSettingsIoControlCode, (ReadOnlyMemory<byte>)MemoryMarshal.CreateFromPinnedArray(_buffer, 0, 4), cancellationToken).ConfigureAwait(false);
}
}

internal sealed class RzUddTransport : DeathAdderTransport
{
private const int RazerDeviceEnumerationIoControlCode = unchecked((int)0x88883000);
Expand Down

0 comments on commit 84be046

Please sign in to comment.