Atlas - SDL_hidapi_zuiki.c

Home / ext / SDL / src / joystick / hidapi Lines: 1 | Size: 19946 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)]
[FILE BEGIN]
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2026 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 GYRO_SCALE (1024.0f / 32768.0f * SDL_PI_F / 180.0f) // Calculate scaling factor based on gyroscope data range and radians 33#define ACCEL_SCALE (8.0f / 32768.0f * SDL_STANDARD_GRAVITY) // Calculate acceleration scaling factor based on gyroscope data range and standard gravity 34#define FILTER_SIZE 11 // Must be an odd number 35#define MAX_RETRY_COUNT 10 // zuiki device initialization retry count 36 37// Define this if you want to log all packets from the controller 38#if 0 39#define DEBUG_ZUIKI_PROTOCOL 40#endif 41 42typedef struct { 43 float buffer[FILTER_SIZE]; 44 uint8_t index; 45 uint8_t count; 46} MedianFilter_t; 47 48typedef struct 49{ 50 Uint8 last_state[USB_PACKET_LENGTH]; 51 bool sensors_supported; // Sensor enabled status flag 52 Uint64 sensor_timestamp_ns; // Sensor timestamp (nanoseconds, cumulative update) 53 float sensor_rate; 54 MedianFilter_t filter_gyro_x; 55 MedianFilter_t filter_gyro_y; 56 MedianFilter_t filter_gyro_z; 57} SDL_DriverZUIKI_Context; 58 59static float median_filter_update(MedianFilter_t* mf, float input) { 60 mf->buffer[mf->index] = input; 61 mf->index = (mf->index + 1) % FILTER_SIZE; 62 if (mf->count < FILTER_SIZE) mf->count++; 63 float temp[FILTER_SIZE]; 64 SDL_memcpy(temp, mf->buffer, sizeof(temp)); 65 for (int i = 0; i < mf->count - 1; i++) { 66 for (int j = i + 1; j < mf->count; j++) { 67 if (temp[i] > temp[j]) { 68 float t = temp[i]; 69 temp[i] = temp[j]; 70 temp[j] = t; 71 } 72 } 73 } 74 return temp[mf->count / 2]; 75} 76 77 78static void HIDAPI_DriverZUIKI_RegisterHints(SDL_HintCallback callback, void *userdata) 79{ 80 SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_ZUIKI, callback, userdata); 81} 82 83static void HIDAPI_DriverZUIKI_UnregisterHints(SDL_HintCallback callback, void *userdata) 84{ 85 SDL_RemoveHintCallback(SDL_HINT_JOYSTICK_HIDAPI_ZUIKI, callback, userdata); 86} 87 88static bool HIDAPI_DriverZUIKI_IsEnabled(void) 89{ 90 return SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_ZUIKI, SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI, SDL_HIDAPI_DEFAULT)); 91} 92 93static 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) 94{ 95 if (vendor_id == USB_VENDOR_ZUIKI) { 96 switch (product_id) { 97 case USB_PRODUCT_ZUIKI_MASCON_PRO: 98 case USB_PRODUCT_ZUIKI_EVOTOP_UWB_DINPUT: 99 case USB_PRODUCT_ZUIKI_EVOTOP_PC_DINPUT: 100 case USB_PRODUCT_ZUIKI_EVOTOP_PC_BT: 101 return true; 102 default: 103 break; 104 } 105 } 106 return false; 107} 108 109static bool HIDAPI_DriverZUIKI_InitDevice(SDL_HIDAPI_Device *device) 110{ 111 Uint8 data[USB_PACKET_LENGTH * 2]; 112 SDL_DriverZUIKI_Context *ctx = (SDL_DriverZUIKI_Context *)SDL_calloc(1, sizeof(*ctx)); 113 if (!ctx) { 114 return false; 115 } 116 device->context = ctx; 117 ctx->sensors_supported = false; 118 119 // Read report data once for device initialization 120 int size = -1; 121 Uint8 retry_count = 0; 122 while (retry_count < MAX_RETRY_COUNT) { 123 size = SDL_hid_read_timeout(device->dev, data, sizeof(data), 10); 124 if (size > 0) { 125 break; 126 } 127 retry_count++; 128 } 129 if (size <= 0) { 130 return false; 131 } 132 133 switch (device->product_id) { 134 case USB_PRODUCT_ZUIKI_MASCON_PRO: 135 HIDAPI_SetDeviceName(device, "ZUIKI MASCON PRO"); 136 break; 137 case USB_PRODUCT_ZUIKI_EVOTOP_PC_DINPUT: 138 ctx->sensors_supported = true; 139 ctx->sensor_rate = 200.0f; 140 break; 141 case USB_PRODUCT_ZUIKI_EVOTOP_UWB_DINPUT: 142 ctx->sensors_supported = true; 143 ctx->sensor_rate = 100.0f; 144 break; 145 case USB_PRODUCT_ZUIKI_EVOTOP_PC_BT: 146 if (size > 0 && data[16] != 0) { 147 ctx->sensors_supported = true; 148 ctx->sensor_rate = 50.0f; 149 } 150 HIDAPI_SetDeviceName(device, "ZUIKI EVOTOP"); 151 break; 152 default: 153 break; 154 } 155 156 return HIDAPI_JoystickConnected(device, NULL); 157} 158 159static int HIDAPI_DriverZUIKI_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id) 160{ 161 return -1; 162} 163 164static void HIDAPI_DriverZUIKI_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index) 165{ 166} 167 168#ifndef DEG2RAD 169#define DEG2RAD(x) ((float)(x) * (float)(SDL_PI_F / 180.f)) 170#endif 171 172static bool HIDAPI_DriverZUIKI_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) 173{ 174 SDL_DriverZUIKI_Context *ctx = (SDL_DriverZUIKI_Context *)device->context; 175 176 SDL_AssertJoysticksLocked(); 177 178 SDL_zeroa(ctx->last_state); 179 180 joystick->nbuttons = 11; 181 joystick->naxes = SDL_GAMEPAD_AXIS_COUNT; 182 joystick->nhats = 1; 183 if (ctx->sensors_supported) { 184 SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO, ctx->sensor_rate); 185 SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL, ctx->sensor_rate); 186 } 187 188 return true; 189} 190 191static bool HIDAPI_DriverZUIKI_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble) 192{ 193 Uint8 rumble_packet[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 194 rumble_packet[4] = low_frequency_rumble >> 8; 195 rumble_packet[5] = high_frequency_rumble >> 8; 196 if (SDL_HIDAPI_SendRumble(device, rumble_packet, sizeof(rumble_packet)) != sizeof(rumble_packet)) { 197 return SDL_SetError("Couldn't send rumble packet"); 198 } 199 return true; 200} 201 202static bool HIDAPI_DriverZUIKI_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble) 203{ 204 return SDL_Unsupported(); 205} 206 207static Uint32 HIDAPI_DriverZUIKI_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) 208{ 209 Uint32 caps = 0; 210 caps |= SDL_JOYSTICK_CAP_RUMBLE; 211 return caps; 212} 213 214static bool HIDAPI_DriverZUIKI_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) 215{ 216 return SDL_Unsupported(); 217} 218 219static bool HIDAPI_DriverZUIKI_SendJoystickEffect(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, const void *data, int size) 220{ 221 if (SDL_HIDAPI_SendRumble(device, data, size) != size) { 222 return SDL_SetError("Couldn't send rumble packet"); 223 } 224 return true; 225} 226 227static bool HIDAPI_DriverZUIKI_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, bool enabled) 228{ 229 SDL_DriverZUIKI_Context *ctx = (SDL_DriverZUIKI_Context *)device->context; 230 if (ctx->sensors_supported) { 231 return true; 232 } 233 return SDL_Unsupported(); 234} 235 236static void HIDAPI_DriverZUIKI_HandleOldStatePacket(SDL_Joystick *joystick, SDL_DriverZUIKI_Context *ctx, Uint8 *data, int size) 237{ 238 Sint16 axis; 239 Uint64 timestamp = SDL_GetTicksNS(); 240 241 if (ctx->last_state[2] != data[2]) { 242 Uint8 hat; 243 244 switch (data[2]) { 245 case 0: 246 hat = SDL_HAT_UP; 247 break; 248 case 1: 249 hat = SDL_HAT_RIGHTUP; 250 break; 251 case 2: 252 hat = SDL_HAT_RIGHT; 253 break; 254 case 3: 255 hat = SDL_HAT_RIGHTDOWN; 256 break; 257 case 4: 258 hat = SDL_HAT_DOWN; 259 break; 260 case 5: 261 hat = SDL_HAT_LEFTDOWN; 262 break; 263 case 6: 264 hat = SDL_HAT_LEFT; 265 break; 266 case 7: 267 hat = SDL_HAT_LEFTUP; 268 break; 269 default: 270 hat = SDL_HAT_CENTERED; 271 break; 272 } 273 SDL_SendJoystickHat(timestamp, joystick, 0, hat); 274 } 275 276 if (ctx->last_state[0] != data[0]) { 277 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, ((data[0] & 0x01) != 0)); 278 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, ((data[0] & 0x02) != 0)); 279 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, ((data[0] & 0x04) != 0)); 280 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, ((data[0] & 0x08) != 0)); 281 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, ((data[0] & 0x10) != 0)); 282 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, ((data[0] & 0x20) != 0)); 283 SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, (data[0] & 0x40) ? SDL_MAX_SINT16 : SDL_MIN_SINT16); 284 SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, (data[0] & 0x80) ? SDL_MAX_SINT16 : SDL_MIN_SINT16); 285 } 286 287 if (ctx->last_state[1] != data[1]) { 288 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK, ((data[1] & 0x01) != 0)); 289 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_START, ((data[1] & 0x02) != 0)); 290 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, ((data[1] & 0x04) != 0)); 291 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_STICK, ((data[1] & 0x08) != 0)); 292 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, ((data[1] & 0x10) != 0)); 293 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_MISC1, ((data[1] & 0x20) != 0)); 294 /* todo for switch C key */ 295 } 296 297#define READ_STICK_AXIS(offset) \ 298 (data[offset] == 0x7f ? 0 : (Sint16)HIDAPI_RemapVal((float)((int)data[offset] - 0x7f), -0x7f, 0xff - 0x7f, SDL_MIN_SINT16, SDL_MAX_SINT16)) 299 { 300 axis = READ_STICK_AXIS(3); 301 SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, axis); 302 axis = READ_STICK_AXIS(4); 303 SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, axis); 304 axis = READ_STICK_AXIS(5); 305 SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTX, axis); 306 axis = READ_STICK_AXIS(6); 307 SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTY, axis); 308 } 309#undef READ_STICK_AXIS 310 311 if (ctx->sensors_supported) { 312 Uint64 sensor_timestamp = timestamp; 313 float gyro_values[3]; 314 gyro_values[0] = median_filter_update(&ctx->filter_gyro_x, LOAD16(data[8], data[9]) * GYRO_SCALE); 315 gyro_values[1] = median_filter_update(&ctx->filter_gyro_y, LOAD16(data[12], data[13]) * GYRO_SCALE); 316 gyro_values[2] = median_filter_update(&ctx->filter_gyro_z, -LOAD16(data[10], data[11]) * GYRO_SCALE); 317 float accel_values[3]; 318 accel_values[0] = LOAD16(data[14], data[15]) * ACCEL_SCALE; 319 accel_values[2] = -LOAD16(data[16], data[17]) * ACCEL_SCALE; 320 accel_values[1] = LOAD16(data[18], data[19]) * ACCEL_SCALE; 321#ifdef DEBUG_ZUIKI_PROTOCOL 322 SDL_Log("Gyro raw: %d, %d, %d -> scaled: %.2f, %.2f, %.2f rad/s", 323 LOAD16(data[8], data[9]), LOAD16(data[10], data[11]), LOAD16(data[12], data[13]), 324 gyro_values[0], gyro_values[1], gyro_values[2]); 325 SDL_Log("Accel raw: %d, %d, %d -> scaled: %.2f, %.2f, %.2f m/s²", 326 LOAD16(data[14], data[15]), LOAD16(data[16], data[17]), LOAD16(data[18], data[19]), 327 accel_values[0], accel_values[1], accel_values[2]); 328#endif 329 330 SDL_SendJoystickSensor(timestamp, joystick, SDL_SENSOR_GYRO, sensor_timestamp, gyro_values, 3); 331 SDL_SendJoystickSensor(timestamp, joystick, SDL_SENSOR_ACCEL, sensor_timestamp, accel_values, 3); 332 } 333 334 SDL_memcpy(ctx->last_state, data, SDL_min(size, sizeof(ctx->last_state))); 335} 336 337static void HIDAPI_DriverZUIKI_Handle_EVOTOP_PCBT_StatePacket(SDL_Joystick *joystick, SDL_DriverZUIKI_Context *ctx, Uint8 *data, int size) 338{ 339 Sint16 axis; 340 Uint64 timestamp = SDL_GetTicksNS(); 341 342 axis = (Sint16)HIDAPI_RemapVal((float)(data[2] << 8 | data[1]), 0x0000, 0xffff, SDL_MIN_SINT16, SDL_MAX_SINT16); 343 SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, axis); 344 axis = (Sint16)HIDAPI_RemapVal((float)(data[4] << 8 | data[3]), 0x0000, 0xffff, SDL_MIN_SINT16, SDL_MAX_SINT16); 345 SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, axis); 346 axis = (Sint16)HIDAPI_RemapVal((float)(data[6] << 8 | data[5]), 0x0000, 0xffff, SDL_MIN_SINT16, SDL_MAX_SINT16); 347 SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTX, axis); 348 axis = (Sint16)HIDAPI_RemapVal((float)(data[8] << 8 | data[7]), 0x0000, 0xffff, SDL_MIN_SINT16, SDL_MAX_SINT16); 349 SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTY, axis); 350 351 axis = (Sint16)HIDAPI_RemapVal((float)(data[10] << 8 | data[9]), 0x0000, 0x03ff, SDL_MIN_SINT16, SDL_MAX_SINT16); 352 SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, axis); 353 axis = (Sint16)HIDAPI_RemapVal((float)(data[12] << 8 | data[11]), 0x0000, 0x03ff, SDL_MIN_SINT16, SDL_MAX_SINT16); 354 SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, axis); 355 356 if (ctx->last_state[13] != data[13]) { 357 Uint8 hat; 358 switch (data[13]) { 359 case 1: 360 hat = SDL_HAT_UP; 361 break; 362 case 2: 363 hat = SDL_HAT_RIGHTUP; 364 break; 365 case 3: 366 hat = SDL_HAT_RIGHT; 367 break; 368 case 4: 369 hat = SDL_HAT_RIGHTDOWN; 370 break; 371 case 5: 372 hat = SDL_HAT_DOWN; 373 break; 374 case 6: 375 hat = SDL_HAT_LEFTDOWN; 376 break; 377 case 7: 378 hat = SDL_HAT_LEFT; 379 break; 380 case 8: 381 hat = SDL_HAT_LEFTUP; 382 break; 383 default: 384 hat = SDL_HAT_CENTERED; 385 break; 386 } 387 SDL_SendJoystickHat(timestamp, joystick, 0, hat); 388 } 389 if (ctx->last_state[14] != data[14]) { 390 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, ((data[14] & 0x01) != 0)); 391 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, ((data[14] & 0x02) != 0)); 392 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, ((data[14] & 0x08) != 0)); 393 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, ((data[14] & 0x10) != 0)); 394 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, ((data[14] & 0x40) != 0)); 395 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, ((data[14] & 0x80) != 0)); 396 } 397 398 if (ctx->last_state[15] != data[15]) { 399 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK, ((data[15] & 0x04) != 0)); 400 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_START, ((data[15] & 0x08) != 0)); 401 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, ((data[15] & 0x10) != 0)); 402 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, ((data[15] & 0x20) != 0)); 403 SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_STICK, ((data[15] & 0x40) != 0)); 404 } 405 406 if (ctx->sensors_supported) { 407 Uint64 sensor_timestamp = timestamp; 408 float gyro_values[3]; 409 gyro_values[0] = median_filter_update(&ctx->filter_gyro_x, LOAD16(data[17], data[18]) * GYRO_SCALE); 410 gyro_values[1] = median_filter_update(&ctx->filter_gyro_y, LOAD16(data[21], data[22]) * GYRO_SCALE); 411 gyro_values[2] = median_filter_update(&ctx->filter_gyro_z, -LOAD16(data[19], data[20]) * GYRO_SCALE); 412 SDL_SendJoystickSensor(timestamp, joystick, SDL_SENSOR_GYRO, sensor_timestamp, gyro_values, 3); 413 float accel_values[3]; 414 accel_values[0] = LOAD16(data[23], data[24]) * ACCEL_SCALE; 415 accel_values[2] = -LOAD16(data[25], data[26]) * ACCEL_SCALE; 416 accel_values[1] = LOAD16(data[27], data[28]) * ACCEL_SCALE; 417 SDL_SendJoystickSensor(timestamp, joystick, SDL_SENSOR_ACCEL, sensor_timestamp, accel_values, 3); 418#ifdef DEBUG_ZUIKI_PROTOCOL 419 SDL_Log("Gyro raw: %d, %d, %d -> scaled: %.2f, %.2f, %.2f rad/s", 420 LOAD16(data[17], data[18]), LOAD16(data[19], data[20]), LOAD16(data[21], data[22]), 421 gyro_values[0], gyro_values[1], gyro_values[2]); 422 SDL_Log("Accel raw: %d, %d, %d -> scaled: %.2f, %.2f, %.2f m/s²", 423 LOAD16(data[23], data[24]), LOAD16(data[25], data[26]), LOAD16(data[27], data[28]), 424 accel_values[0], accel_values[1], accel_values[2]); 425#endif 426 } 427 428 SDL_memcpy(ctx->last_state, data, SDL_min(size, sizeof(ctx->last_state))); 429} 430 431static bool HIDAPI_DriverZUIKI_UpdateDevice(SDL_HIDAPI_Device *device) 432{ 433 SDL_DriverZUIKI_Context *ctx = (SDL_DriverZUIKI_Context *)device->context; 434 SDL_Joystick *joystick = NULL; 435 Uint8 data[USB_PACKET_LENGTH]; 436 int size = 0; 437 438 if (device->num_joysticks > 0) { 439 joystick = SDL_GetJoystickFromID(device->joysticks[0]); 440 } else { 441 return false; 442 } 443 444 while ((size = SDL_hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) { 445#ifdef DEBUG_ZUIKI_PROTOCOL 446 HIDAPI_DumpPacket("ZUIKI packet: size = %d", data, size); 447#endif 448 if (!joystick) { 449 continue; 450 } 451 452 if (device->product_id == USB_PRODUCT_ZUIKI_EVOTOP_PC_BT) { 453 HIDAPI_DriverZUIKI_Handle_EVOTOP_PCBT_StatePacket(joystick, ctx, data, size); 454 } else if (device->product_id == USB_PRODUCT_ZUIKI_EVOTOP_PC_DINPUT 455 || device->product_id == USB_PRODUCT_ZUIKI_MASCON_PRO 456 || device->product_id == USB_PRODUCT_ZUIKI_EVOTOP_UWB_DINPUT) { 457 HIDAPI_DriverZUIKI_HandleOldStatePacket(joystick, ctx, data, size); 458 } 459 } 460 461 if (size < 0) { 462 // Read error, device is disconnected 463 HIDAPI_JoystickDisconnected(device, device->joysticks[0]); 464 } 465 return (size >= 0); 466} 467 468static void HIDAPI_DriverZUIKI_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) 469{ 470} 471 472static void HIDAPI_DriverZUIKI_FreeDevice(SDL_HIDAPI_Device *device) 473{ 474} 475 476SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverZUIKI = { 477 SDL_HINT_JOYSTICK_HIDAPI_ZUIKI, 478 true, 479 HIDAPI_DriverZUIKI_RegisterHints, 480 HIDAPI_DriverZUIKI_UnregisterHints, 481 HIDAPI_DriverZUIKI_IsEnabled, 482 HIDAPI_DriverZUIKI_IsSupportedDevice, 483 HIDAPI_DriverZUIKI_InitDevice, 484 HIDAPI_DriverZUIKI_GetDevicePlayerIndex, 485 HIDAPI_DriverZUIKI_SetDevicePlayerIndex, 486 HIDAPI_DriverZUIKI_UpdateDevice, 487 HIDAPI_DriverZUIKI_OpenJoystick, 488 HIDAPI_DriverZUIKI_RumbleJoystick, 489 HIDAPI_DriverZUIKI_RumbleJoystickTriggers, 490 HIDAPI_DriverZUIKI_GetJoystickCapabilities, 491 HIDAPI_DriverZUIKI_SetJoystickLED, 492 HIDAPI_DriverZUIKI_SendJoystickEffect, 493 HIDAPI_DriverZUIKI_SetJoystickSensorsEnabled, 494 HIDAPI_DriverZUIKI_CloseJoystick, 495 HIDAPI_DriverZUIKI_FreeDevice, 496}; 497 498#endif // SDL_JOYSTICK_HIDAPI_ZUIKI 499 500#endif // SDL_JOYSTICK_HIDAPI 501
[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.