#include "stk/stk.h" #include #include #include #include #include // GUID_DEVINTERFACE_HID from devguid.h static const GUID GUID_DEVINTERFACE_HID = { 0x4d1e55b2, 0xf16f, 0x11cf, { 0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30 } }; // --------------------------------------------------------------------------- // Internal state // --------------------------------------------------------------------------- static HANDLE g_handle = INVALID_HANDLE_VALUE; // --------------------------------------------------------------------------- // Platform backend // --------------------------------------------------------------------------- int stk_open(stk_config_t const* config) { if (!config) return -1; HDEVINFO info = SetupDiGetClassDevsW(&GUID_DEVINTERFACE_HID, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); if (info == INVALID_HANDLE_VALUE) return -1; for (DWORD i = 0; ; i++) { SP_DEVICE_INTERFACE_DATA iface = { .cbSize = sizeof(iface) }; if (!SetupDiEnumDeviceInterfaces(info, NULL, &GUID_DEVINTERFACE_HID, i, &iface)) break; DWORD buflen = 0; SetupDiGetDeviceInterfaceDetailW(info, &iface, NULL, 0, &buflen, NULL); if (buflen == 0) continue; PSP_DEVICE_INTERFACE_DETAIL_DATA_W detail = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)HeapAlloc(GetProcessHeap(), 0, buflen); detail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W); if (!SetupDiGetDeviceInterfaceDetailW(info, &iface, detail, buflen, &buflen, NULL)) { HeapFree(GetProcessHeap(), 0, detail); continue; } HANDLE handle = CreateFileW(detail->DevicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); HeapFree(GetProcessHeap(), 0, detail); if (handle == INVALID_HANDLE_VALUE) continue; HIDD_ATTRIBUTES attrs = { .Size = sizeof(attrs) }; if (!HidD_GetAttributes(handle, &attrs)) { CloseHandle(handle); continue; } if (attrs.VendorID == config->vendor_id && attrs.ProductID == config->product_id) { g_handle = handle; SetupDiDestroyDeviceInfoList(info); return 0; } CloseHandle(handle); } SetupDiDestroyDeviceInfoList(info); fprintf(stderr, "stk: device 0x%04X:0x%04X not found\n", config->vendor_id, config->product_id); return -1; } int stk_read(stk_state_t* state) { if (g_handle == INVALID_HANDLE_VALUE) return -1; uint8_t buf[64]; DWORD bytes = 0; if (!ReadFile(g_handle, buf, sizeof(buf), &bytes, NULL)) return -1; if (bytes < 20) return -1; // Parse axes (little-endian 16-bit values, offset by 2 bytes) for (int i = 0; i < STK_NUM_AXES; i++) { size_t off = 2 + (size_t)i * 2; uint16_t val = (uint16_t)buf[off] | ((uint16_t)buf[off + 1] << 8); state->axes[i] = (int16_t)val; } // Parse buttons (byte 1 + bytes 18-19 = 24 bits) state->buttons = (uint32_t)buf[1] | ((uint32_t)buf[18] << 8) | ((uint32_t)buf[19] << 16); return 0; } void stk_close(void) { if (g_handle != INVALID_HANDLE_VALUE) { CloseHandle(g_handle); g_handle = INVALID_HANDLE_VALUE; } }