Atlas - SDL_hidapi_zuiki.c

Home / ext / SDL / src / joystick / hidapi Lines: 1 | Size: 10334 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)]
[FILE BEGIN]
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2025 Sam Lantinga <[email protected]> 4 Copyright (C) 2025 Zuiki Inc. 5 6 This software is provided 'as-is', without any express or implied 7 warranty. In no event will the authors be held liable for any damages 8 arising from the use of this software. 9 10 Permission is granted to anyone to use this software for any purpose, 11 including commercial applications, and to alter it and redistribute it 12 freely, subject to the following restrictions: 13 14 1. The origin of this software must not be misrepresented; you must not 15 claim that you wrote the original software. If you use this software 16 in a product, an acknowledgment in the product documentation would be 17 appreciated but is not required. 18 2. Altered source versions must be plainly marked as such, and must not be 19 misrepresented as being the original software. 20 3. This notice may not be removed or altered from any source distribution. 21*/ 22#include "SDL_internal.h" 23 24#ifdef SDL_JOYSTICK_HIDAPI 25 26#include "../SDL_sysjoystick.h" 27#include "SDL_hidapijoystick_c.h" 28#include "SDL_hidapi_rumble.h" 29 30#ifdef SDL_JOYSTICK_HIDAPI_ZUIKI 31 32// Define this if you want to log all packets from the controller 33#if 0 34#define DEBUG_ZUIKI_PROTOCOL 35#endif 36 37typedef struct 38{ 39 Uint8 last_state[USB_PACKET_LENGTH]; 40} SDL_DriverZUIKI_Context; 41 42static void HIDAPI_DriverZUIKI_RegisterHints(SDL_HintCallback callback, void *userdata) 43{ 44 SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_ZUIKI, callback, userdata); 45} 46 47static void HIDAPI_DriverZUIKI_UnregisterHints(SDL_HintCallback callback, void *userdata) 48{ 49 SDL_RemoveHintCallback(SDL_HINT_JOYSTICK_HIDAPI_ZUIKI, callback, userdata); 50} 51 52static bool HIDAPI_DriverZUIKI_IsEnabled(void) 53{ 54 return SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_ZUIKI, SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI, SDL_HIDAPI_DEFAULT)); 55} 56 57static bool HIDAPI_DriverZUIKI_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *name, SDL_GamepadType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol) 58{ 59 if (vendor_id == USB_VENDOR_ZUIKI) { 60 switch (product_id) { 61 case USB_PRODUCT_ZUIKI_MASCON_PRO: 62 return true; 63 default: 64 break; 65 } 66 } 67 return false; 68} 69 70static bool HIDAPI_DriverZUIKI_InitDevice(SDL_HIDAPI_Device *device) 71{ 72 SDL_DriverZUIKI_Context *ctx = (SDL_DriverZUIKI_Context *)SDL_calloc(1, sizeof(*ctx)); 73 if (!ctx) { 74 return false; 75 } 76 device->context = ctx; 77 78 if (device->product_id == USB_PRODUCT_ZUIKI_MASCON_PRO) { 79 HIDAPI_SetDeviceName(device, "ZUIKI MASCON PRO"); 80 } 81 82 return HIDAPI_JoystickConnected(device, NULL); 83} 84 85static int HIDAPI_DriverZUIKI_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id) 86{ 87 return -1; 88} 89 90static void HIDAPI_DriverZUIKI_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index) 91{ 92} 93 94#ifndef DEG2RAD 95#define DEG2RAD(x) ((float)(x) * (float)(SDL_PI_F / 180.f)) 96#endif 97 98static bool HIDAPI_DriverZUIKI_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) 99{ 100 SDL_DriverZUIKI_Context *ctx = (SDL_DriverZUIKI_Context *)device->context; 101 102 SDL_AssertJoysticksLocked(); 103 104 SDL_zeroa(ctx->last_state); 105 106 joystick->nbuttons = 11; 107 joystick->naxes = SDL_GAMEPAD_AXIS_COUNT; 108 joystick->nhats = 1; 109 110 return true; 111} 112 113static bool HIDAPI_DriverZUIKI_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble) 114{ 115 Uint8 rumble_packet[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 116 rumble_packet[4] = low_frequency_rumble >> 8; 117 rumble_packet[5] = high_frequency_rumble >> 8; 118 if (SDL_HIDAPI_SendRumble(device, rumble_packet, sizeof(rumble_packet)) != sizeof(rumble_packet)) { 119 return SDL_SetError("Couldn't send rumble packet"); 120 } 121 return true; 122} 123 124static bool HIDAPI_DriverZUIKI_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble) 125{ 126 return SDL_Unsupported(); 127} 128 129static Uint32 HIDAPI_DriverZUIKI_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) 130{ 131 Uint32 caps = 0; 132 caps |= SDL_JOYSTICK_CAP_RUMBLE; 133 return caps; 134} 135 136static bool HIDAPI_DriverZUIKI_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) 137{ 138 return SDL_Unsupported(); 139} 140 141static bool HIDAPI_DriverZUIKI_SendJoystickEffect(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, const void *data, int size) 142{ 143 if (SDL_HIDAPI_SendRumble(device, data, size) != size) { 144 return SDL_SetError("Couldn't send rumble packet"); 145 } 146 return true; 147} 148 149static bool HIDAPI_DriverZUIKI_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, bool enabled) 150{ 151 return SDL_Unsupported(); 152} 153 154static void HIDAPI_DriverZUIKI_HandleOldStatePacket(SDL_Joystick *joystick, SDL_DriverZUIKI_Context *ctx, Uint8 *data, int size) 155{ 156 Sint16 axis; 157 Uint64 timestamp = SDL_GetTicksNS(); 158 159 if (ctx->last_state[2] != data[2]) { 160 Uint8 hat; 161 162 switch (data[2]) { 163 case 0: 164 hat = SDL_HAT_UP; 165 break; 166 case 1: 167 hat = SDL_HAT_RIGHTUP; 168 break; 169 case 2: 170 hat = SDL_HAT_RIGHT; 171 break; 172 case 3: 173 hat = SDL_HAT_RIGHTDOWN; 174 break; 175 case 4: 176 hat = SDL_HAT_DOWN; 177 break; 178 case 5: 179 hat = SDL_HAT_LEFTDOWN; 180 break; 181 case 6: 182 hat = SDL_HAT_LEFT; 183 break; 184 case 7: 185 hat = SDL_HAT_LEFTUP; 186 break; 187 default: 188 hat = SDL_HAT_CENTERED; 189 break; 190 } 191 SDL_SendJoystickHat(timestamp, joystick, 0, hat); 192 } 193 194 if (ctx->last_state[0] != data[0]) { 195 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, ((data[0] & 0x01) != 0)); 196 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, ((data[0] & 0x02) != 0)); 197 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, ((data[0] & 0x04) != 0)); 198 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, ((data[0] & 0x08) != 0)); 199 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, ((data[0] & 0x10) != 0)); 200 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, ((data[0] & 0x20) != 0)); 201 SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, (data[0] & 0x40) ? SDL_MAX_SINT16 : SDL_MIN_SINT16); 202 SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, (data[0] & 0x80) ? SDL_MAX_SINT16 : SDL_MIN_SINT16); 203 } 204 205 if (ctx->last_state[1] != data[1]) { 206 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK, ((data[1] & 0x01) != 0)); 207 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_START, ((data[1] & 0x02) != 0)); 208 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, ((data[1] & 0x04) != 0)); 209 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_STICK, ((data[1] & 0x08) != 0)); 210 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, ((data[1] & 0x10) != 0)); 211 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_MISC1, ((data[1] & 0x20) != 0)); 212 /* todo for switch C key */ 213 } 214 215#define READ_STICK_AXIS(offset) \ 216 (data[offset] == 0x7f ? 0 : (Sint16)HIDAPI_RemapVal((float)((int)data[offset] - 0x7f), -0x7f, 0xff - 0x7f, SDL_MIN_SINT16, SDL_MAX_SINT16)) 217 { 218 axis = READ_STICK_AXIS(3); 219 SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, axis); 220 axis = READ_STICK_AXIS(4); 221 SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, axis); 222 axis = READ_STICK_AXIS(5); 223 SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTX, axis); 224 axis = READ_STICK_AXIS(6); 225 SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTY, axis); 226 } 227#undef READ_STICK_AXIS 228 229 SDL_memcpy(ctx->last_state, data, SDL_min(size, sizeof(ctx->last_state))); 230} 231 232static bool HIDAPI_DriverZUIKI_UpdateDevice(SDL_HIDAPI_Device *device) 233{ 234 SDL_DriverZUIKI_Context *ctx = (SDL_DriverZUIKI_Context *)device->context; 235 SDL_Joystick *joystick = NULL; 236 Uint8 data[USB_PACKET_LENGTH]; 237 int size = 0; 238 239 if (device->num_joysticks > 0) { 240 joystick = SDL_GetJoystickFromID(device->joysticks[0]); 241 } else { 242 return false; 243 } 244 245 while ((size = SDL_hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) { 246#ifdef DEBUG_ZUIKI_PROTOCOL 247 HIDAPI_DumpPacket("ZUIKI packet: size = %d", data, size); 248#endif 249 if (!joystick) { 250 continue; 251 } 252 253 if (size == 8) { 254 HIDAPI_DriverZUIKI_HandleOldStatePacket(joystick, ctx, data, size); 255 } 256 } 257 258 if (size < 0) { 259 // Read error, device is disconnected 260 HIDAPI_JoystickDisconnected(device, device->joysticks[0]); 261 } 262 return (size >= 0); 263} 264 265static void HIDAPI_DriverZUIKI_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) 266{ 267} 268 269static void HIDAPI_DriverZUIKI_FreeDevice(SDL_HIDAPI_Device *device) 270{ 271} 272 273SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverZUIKI = { 274 SDL_HINT_JOYSTICK_HIDAPI_ZUIKI, 275 true, 276 HIDAPI_DriverZUIKI_RegisterHints, 277 HIDAPI_DriverZUIKI_UnregisterHints, 278 HIDAPI_DriverZUIKI_IsEnabled, 279 HIDAPI_DriverZUIKI_IsSupportedDevice, 280 HIDAPI_DriverZUIKI_InitDevice, 281 HIDAPI_DriverZUIKI_GetDevicePlayerIndex, 282 HIDAPI_DriverZUIKI_SetDevicePlayerIndex, 283 HIDAPI_DriverZUIKI_UpdateDevice, 284 HIDAPI_DriverZUIKI_OpenJoystick, 285 HIDAPI_DriverZUIKI_RumbleJoystick, 286 HIDAPI_DriverZUIKI_RumbleJoystickTriggers, 287 HIDAPI_DriverZUIKI_GetJoystickCapabilities, 288 HIDAPI_DriverZUIKI_SetJoystickLED, 289 HIDAPI_DriverZUIKI_SendJoystickEffect, 290 HIDAPI_DriverZUIKI_SetJoystickSensorsEnabled, 291 HIDAPI_DriverZUIKI_CloseJoystick, 292 HIDAPI_DriverZUIKI_FreeDevice, 293}; 294 295#endif // SDL_JOYSTICK_HIDAPI_ZUIKI 296 297#endif // SDL_JOYSTICK_HIDAPI 298
[FILE END]
(C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.