Skip to content

Conversation

zuiki
Copy link

@zuiki zuiki commented Aug 20, 2025

This PR adds support for the Zuiki MascronPro controller.

Description

Support ZUIKI MasconPro

  • Enable rumble
  • Disable sensores

Existing Issue(s)

none

luoxing added 2 commits August 14, 2025 10:48
Support version:
MasconPro
Enable rumble
Disable sensores
@sezero sezero requested a review from slouken August 20, 2025 10:26
@zuiki
Copy link
Author

zuiki commented Aug 25, 2025

Hello
Regarding the several build failures we're experiencing, it seems they aren't directly related to the code we submitted. We don't have sufficient experience with this, and we'd appreciate any advice on how to resolve these build errors.

@sezero
Copy link
Contributor

sezero commented Aug 25, 2025

This patch adds new zuiki source to Visual Studio and Xcode project files. (Also inlined below.)
z.patch

diff --git a/VisualC-GDK/SDL/SDL.vcxproj b/VisualC-GDK/SDL/SDL.vcxproj
index a9024fc..e0f6b45 100644
--- a/VisualC-GDK/SDL/SDL.vcxproj
+++ b/VisualC-GDK/SDL/SDL.vcxproj
@@ -734,6 +734,7 @@
     <ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_xbox360w.c" />
     <ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_xboxone.c" />
     <ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_lg4ff.c" />
+    <ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_zuiki.c" />
     <ClCompile Include="..\..\src\joystick\SDL_gamepad.c" />
     <ClCompile Include="..\..\src\joystick\SDL_joystick.c" />
     <ClCompile Include="..\..\src\joystick\SDL_steam_virtual_gamepad.c" />
diff --git a/VisualC-GDK/SDL/SDL.vcxproj.filters b/VisualC-GDK/SDL/SDL.vcxproj.filters
index 9a0ce21..0b8e076 100644
--- a/VisualC-GDK/SDL/SDL.vcxproj.filters
+++ b/VisualC-GDK/SDL/SDL.vcxproj.filters
@@ -85,6 +85,7 @@
     <ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_xbox360w.c" />
     <ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_xboxone.c" />
     <ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_lg4ff.c" />
+    <ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_zuiki.c" />
     <ClCompile Include="..\..\src\joystick\SDL_gamepad.c" />
     <ClCompile Include="..\..\src\joystick\SDL_joystick.c" />
     <ClCompile Include="..\..\src\joystick\SDL_steam_virtual_gamepad.c" />
diff --git a/VisualC/SDL/SDL.vcxproj b/VisualC/SDL/SDL.vcxproj
index f59c31f..c57ca95 100644
--- a/VisualC/SDL/SDL.vcxproj
+++ b/VisualC/SDL/SDL.vcxproj
@@ -624,6 +624,7 @@
     <ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_xbox360w.c" />
     <ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_xboxone.c" />
     <ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_lg4ff.c" />
+    <ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_zuiki.c" />
     <ClCompile Include="..\..\src\joystick\SDL_gamepad.c" />
     <ClCompile Include="..\..\src\joystick\SDL_joystick.c" />
     <ClCompile Include="..\..\src\joystick\SDL_steam_virtual_gamepad.c" />
diff --git a/VisualC/SDL/SDL.vcxproj.filters b/VisualC/SDL/SDL.vcxproj.filters
index 4a1b31c..1c6854e 100644
--- a/VisualC/SDL/SDL.vcxproj.filters
+++ b/VisualC/SDL/SDL.vcxproj.filters
@@ -1248,6 +1248,9 @@
     <ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_lg4ff.c">
       <Filter>joystick\hidapi</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_zuiki.c">
+      <Filter>joystick\hidapi</Filter>
+    </ClCompile>
     <ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapijoystick.c">
       <Filter>joystick\hidapi</Filter>
     </ClCompile>
diff --git a/Xcode/SDL/SDL.xcodeproj/project.pbxproj b/Xcode/SDL/SDL.xcodeproj/project.pbxproj
index a6434e4..fcd3354 100644
--- a/Xcode/SDL/SDL.xcodeproj/project.pbxproj
+++ b/Xcode/SDL/SDL.xcodeproj/project.pbxproj
@@ -66,6 +66,7 @@
 		566E26D8246274CC00718109 /* SDL_locale.c in Sources */ = {isa = PBXBuildFile; fileRef = 566E26CD246274CB00718109 /* SDL_locale.c */; };
 		566E26E1246274CC00718109 /* SDL_syslocale.h in Headers */ = {isa = PBXBuildFile; fileRef = 566E26CE246274CC00718109 /* SDL_syslocale.h */; };
 		56A2373329F9C113003CCA5F /* SDL_sysrwlock.c in Sources */ = {isa = PBXBuildFile; fileRef = 56A2373229F9C113003CCA5F /* SDL_sysrwlock.c */; };
+		63124A422E5C357500A53610 /* SDL_hidapi_zuiki.c in Sources */ = {isa = PBXBuildFile; fileRef = 63124A412E5C357500A53610 /* SDL_hidapi_zuiki.c */; };
 		6312C66D2B42341400A7BB00 /* SDL_murmur3.c in Sources */ = {isa = PBXBuildFile; fileRef = 6312C66C2B42341400A7BB00 /* SDL_murmur3.c */; };
 		63134A252A7902FD0021E9A6 /* SDL_pen_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 63134A232A7902FD0021E9A6 /* SDL_pen_c.h */; };
 		63134A262A7902FD0021E9A6 /* SDL_pen.c in Sources */ = {isa = PBXBuildFile; fileRef = 63134A242A7902FD0021E9A6 /* SDL_pen.c */; };
@@ -611,6 +612,7 @@
 		566E26CD246274CB00718109 /* SDL_locale.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = SDL_locale.c; path = locale/SDL_locale.c; sourceTree = "<group>"; };
 		566E26CE246274CC00718109 /* SDL_syslocale.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_syslocale.h; path = locale/SDL_syslocale.h; sourceTree = "<group>"; };
 		56A2373229F9C113003CCA5F /* SDL_sysrwlock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_sysrwlock.c; sourceTree = "<group>"; };
+		63124A412E5C357500A53610 /* SDL_hidapi_zuiki.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_hidapi_zuiki.c; sourceTree = "<group>"; };
 		6312C66C2B42341400A7BB00 /* SDL_murmur3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_murmur3.c; sourceTree = "<group>"; };
 		63134A232A7902FD0021E9A6 /* SDL_pen_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_pen_c.h; sourceTree = "<group>"; };
 		63134A242A7902FD0021E9A6 /* SDL_pen.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_pen.c; sourceTree = "<group>"; };
@@ -1955,6 +1957,7 @@
 				A7D8A7C223E2513E00DCD162 /* SDL_hidapi_xbox360.c */,
 				A7D8A7C823E2513E00DCD162 /* SDL_hidapi_xbox360w.c */,
 				A7D8A7C523E2513E00DCD162 /* SDL_hidapi_xboxone.c */,
+				63124A412E5C357500A53610 /* SDL_hidapi_zuiki.c */,
 				A7D8A7C423E2513E00DCD162 /* SDL_hidapijoystick.c */,
 				A7D8A7C723E2513E00DCD162 /* SDL_hidapijoystick_c.h */,
 			);
@@ -3104,6 +3107,7 @@
 				00004D0B73767647AD550000 /* SDL_asyncio_generic.c in Sources */,
 				0000A03C0F32C43816F40000 /* SDL_asyncio_windows_ioring.c in Sources */,
 				0000A877C7DB9FA935FC0000 /* SDL_uikitpen.m in Sources */,
+				63124A422E5C357500A53610 /* SDL_hidapi_zuiki.c in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

@zuiki
Copy link
Author

zuiki commented Aug 25, 2025

Thank you for your answer, we will add it right away.

@@ -2834,7 +2846,7 @@ extern "C" {
*
* \since This hint is available since SDL 3.2.0.
*/
#define SDL_HINT_OPENVR_LIBRARY "SDL_OPENVR_LIBRARY"
#define SDL_HINT_OPENVR_LIBRARY "SDL_OPENVR_LIBRARY"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please revert the unrelated whitespace changes in this file.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please revert the unrelated whitespace changes in this file.

Uint8 last_state[USB_PACKET_LENGTH];
Uint64 sensor_timestamp; // Nanoseconds. Simulate onboard clock. Different models have different rates vs different connection styles.
Uint64 sensor_timestamp_interval;
} SDL_DriverZUIKI_Context;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove any unused structures and fields in this file.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove any unused structures and fields in this file.

@slouken
Copy link
Collaborator

slouken commented Aug 25, 2025

Looking at the controller description, it looks like this isn't a gamepad style controller, so I'm not sure it makes sense to add to the gamepad API.

Would it be possible to send me one of these controllers, so I can do testing here? You can reach me at slouken@libsdl.org.

@zuiki
Copy link
Author

zuiki commented Aug 27, 2025

Thank you very much for your reply.

Looking at the controller description, it looks like this isn't a gamepad-style controller, so I'm not sure it makes sense to add the > gamepad API.

Regarding the above question, since our product has LED lights, there are some accompanying games (released through Steam), such as
https://store.steampowered.com/app/2111630/JR/?l=japanese

These require LED control based on game scenarios, so we implemented a rumble interface in our driver to receive data from the game and use the rumble API to control the LEDs.

Regarding the controller for testing, we are currently preparing samples, and I will contact you by email later.

@slouken
Copy link
Collaborator

slouken commented Aug 27, 2025

SDL has a simple LED API, does it match your needs?
https://wiki.libsdl.org/SDL3/SDL_SetGamepadLED

@slouken slouken added this to the 3.x milestone Aug 27, 2025
@zuiki
Copy link
Author

zuiki commented Sep 1, 2025

Sorry for the late response.
We're currently using the vibration interface based on the game developer's suggestion. The LED interface should also meet our needs. However, the vibration interface is simpler than the LED interface and less prone to errors for game developers, so we're currently considering it. If SDL policy mandates that LED control must use the LED interface, we can also make this change.

@slouken
Copy link
Collaborator

slouken commented Sep 1, 2025

If the LED interface meets your needs, then I suggest using that for LED control, if your interface is simply setting a single color or rgb LED to a particular value. If your needs are more complex (setting LED patterns, etc.), another alternative is to implement the custom effect interface (SDL_SendGamepadEffect()), which allows sending raw packets to the device. This is more flexible for device control, but requires the application to know what data to send in the effect packet.

@zuiki
Copy link
Author

zuiki commented Sep 1, 2025

Thanks for your suggestion. For this MasconPro, we simply need to set a few single-color LEDs. We'll try implementing the API mentioned here and testing it.
https://wiki.libsdl.org/SDL3/SDL_SetGamepadLED

Also, I'd like to ask: Our supporting game requires the Steamworks API to control the controler. Is there any documentation on the correspondence between the SDL LED API and the Steamworks LED API?

@zuiki
Copy link
Author

zuiki commented Sep 1, 2025

Hello, I've re-examined the functionality of SDL_SetGamepadLED and our needs. Our controller has multiple LEDs, but as far as I understand, the SDL_SetGamepadLED interface doesn't allow for specifying an LED index. By default, each controller corresponds to only one LED, making it unsuitable for our current needs.

It seems the SDL_SendGamepadEffect interface you mentioned would meet our needs. So, our current question is,
Since our game requires calling a SteamWorks API to send and receive data between the controller and the console, could you please tell me which SteamWorks API SDL_SendGamepadEffect corresponds to?

@slouken
Copy link
Collaborator

slouken commented Sep 2, 2025

There is no direct equivalent. May I ask why the application can't open this device directly?

@zuiki
Copy link
Author

zuiki commented Sep 3, 2025

Hello, this is primarily from the perspective of game developers. Since we don't develop our own games, their developers are already accustomed to developing with the SteamWorks API. (We already have Steam-based games, and the next step is for game developers to adapt the new controller.)
For the MasconPro controller's LED control, can we use a method that is compatible with both the RumbleJoystick and SendJoystickEffect interfaces?
This way, game developers can control our two LEDs in upcoming games using the SteamWorks API's TriggerVibration API. Alternatively, they can directly use SDL's SDL_SendGamepadEffect interface.

@slouken
Copy link
Collaborator

slouken commented Sep 3, 2025

Given rumble is the only way to communicate through the Steamworks SDK, and your controller doesn’t have other rumble capabilities, this seems like a reasonable approach.

@zuiki
Copy link
Author

zuiki commented Sep 3, 2025

Given rumble is the only way to communicate through the Steamworks SDK, and your controller doesn’t have other rumble capabilities, this seems like a reasonable approach.

Thanks for your confirmation, we will add the implementation of SDL_SendGamepadEffect API.

@zuiki
Copy link
Author

zuiki commented Sep 8, 2025

Would it be possible to send me one of these controllers, so I can do testing here? You can reach me at slouken@libsdl.org.

Hello, regarding the provision of controller samples, since our product is scheduled for release in November of this year and hasn't yet been released, providing samples requires an Non-Disclosure Agreement.

In addition, our plan is to have our code merged into SDL and the relevant interfaces available in Steam before the product releases.

Is providing controller samples required before your code review and merging is complete?
If not, I think it would be simpler to send you samples after the product releases. If so, I'll send you the NDA for your confirmation.

@slouken
Copy link
Collaborator

slouken commented Sep 8, 2025

Is providing controller samples required before your code review and merging is complete? If not, I think it would be simpler to send you samples after the product releases. If so, I'll send you the NDA for your confirmation.

No, it's not required, but it's more likely to work correctly with Steam if I can verify behavior. If you can verify that everything looks good with SDL testcontroller, then Steam should work as well.

@zuiki
Copy link
Author

zuiki commented Sep 18, 2025

Hello, we have tested the current code using SDL testcontroller and confirmed that the relevant interfaces are working properly.

20250918-093310

20250918-093329


Also, regarding the compilation error we're currently encountering, we have no experience fixing it. Could you provide some information on how to fix it?

==> Fetching downloads for: ccache
==> Downloading https://raw.githubusercontent.com/Homebrew/homebrew-core/cbfe4800dd14914fc1f31f5dcbceef07f5f0a42a/Formula/c/ccache.rb
Error: ccache: no bottle available!
If you're feeling brave, you can try to install from source with:
  brew install --build-from-source ccache

Uint8 last_state[USB_PACKET_LENGTH];
Uint64 sensor_timestamp; // Nanoseconds. Simulate onboard clock. Different models have different rates vs different connection styles.
Uint64 sensor_timestamp_interval;
} SDL_DriverZUIKI_Context;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove any unused structures and fields in this file.

@@ -2834,7 +2846,7 @@ extern "C" {
*
* \since This hint is available since SDL 3.2.0.
*/
#define SDL_HINT_OPENVR_LIBRARY "SDL_OPENVR_LIBRARY"
#define SDL_HINT_OPENVR_LIBRARY "SDL_OPENVR_LIBRARY"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please revert the unrelated whitespace changes in this file.

@@ -170,7 +171,9 @@
#define USB_PRODUCT_HANDHELDLEGEND_SINPUT_GENERIC 0x10c6
#define USB_PRODUCT_HANDHELDLEGEND_PROGCC 0x10df
#define USB_PRODUCT_HANDHELDLEGEND_GCULTIMATE 0x10dd
#define USB_PRODUCT_BONZIRICHANNEL_FIREBIRD 0x10e0

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants