src/sysdep/windows/input.c
static void scan_rawinput_joysticks(void)
{
    sys_mutex_lock(joystick_mutex, -1);
    for (int i = 0; i < num_joysticks; i++) {
        if (joystick_info[i].connected && !joysticks[i].is_xinput) {
            RID_DEVICE_INFO device_info = {.cbSize = sizeof(device_info)};
            if (GetRawInputDeviceInfo(
                    joysticks[i].device, RIDI_DEVICEINFO, &device_info,
                    (UINT[]){sizeof(device_info)}) == (UINT)(-1)) {
                DLOG("%s (%04X/%04X): GetRawInputDeviceInfo() failed (%s),"
                     " assuming disconnected",
                     hidjoy_name(joysticks[i].hid_handle),
                     hidjoy_vendor_id(joysticks[i].hid_handle),
                     hidjoy_product_id(joysticks[i].hid_handle),
                     windows_strerror(GetLastError()));
                hidjoy_flush_events(joysticks[i].hid_handle);
                joystick_info[i].connected = 0;
                send_joystick_connect_event(i, INPUT_JOYSTICK_DISCONNECTED);
            }
        }
    }
    sys_mutex_unlock(joystick_mutex);

    /* In theory we could get the device list with a simple count-alloc-get
     * pattern, but there's always the chance that the system will add a
     * new device just as we're doing the second GRIDL call, so we loop
     * until GRIDL succeeds. */
    UINT num_devices = 1;
    RAWINPUTDEVICELIST *devices =
        mem_alloc(sizeof(*devices), 0, MEM_ALLOC_TEMP);
    if (UNLIKELY(!devices)) {
        DLOG("No memory for 1 device structure");
        return;
    }
    UINT last_num_devices = num_devices;
    while (GetRawInputDeviceList(devices, &num_devices,
                                 sizeof(*devices)) == (UINT)(-1)) {
        if (UNLIKELY(GetLastError() != ERROR_INSUFFICIENT_BUFFER)) {
            DLOG("GetRawInputDeviceList() failed: %s",
                 windows_strerror(GetLastError()));
            mem_free(devices);
            return;
        }
        if (UNLIKELY(num_devices <= last_num_devices)) {
            /* At least as of January 2018, the gameoverlayrenderer.dll
             * library injected by Valve's Steam client when starting a
             * game wraps GRIDL with a buggy function that does not update
             * num_devices, so we end up infinite-looping here. */
            DLOG("GRIDL returned INSUFFICIENT_BUFFER but did not update"
                 " num_devices (Steam bug?), assuming no rawinput devices");
            mem_free(devices);
            return;
        }
        RAWINPUTDEVICELIST *new_devices = mem_realloc(
            devices, sizeof(*devices) * num_devices, MEM_ALLOC_TEMP);
        if (UNLIKELY(!new_devices)) {
            DLOG("No memory for %u device structures", num_devices);
            mem_free(devices);
            return;
        }
        devices = new_devices;
        last_num_devices = num_devices;
    }

    for (UINT i = 0; i < num_devices; i++) {
        add_rawinput_joystick(devices[i].hDevice);
    }

    mem_free(devices);
}
/*************************************************************************/
/************** Local routines: Raw input joystick handling **************/
/*************************************************************************/
Local routines: Raw input joystick handling
Local routines : Raw input joystick handling
static void scan_rawinput_joysticks(void)
{
    sys_mutex_lock(joystick_mutex, -1);
    for (int i = 0; i < num_joysticks; i++) {
        if (joystick_info[i].connected && !joysticks[i].is_xinput) {
            RID_DEVICE_INFO device_info = {.cbSize = sizeof(device_info)};
            if (GetRawInputDeviceInfo(
                    joysticks[i].device, RIDI_DEVICEINFO, &device_info,
                    (UINT[]){sizeof(device_info)}) == (UINT)(-1)) {
                DLOG("%s (%04X/%04X): GetRawInputDeviceInfo() failed (%s),"
                     " assuming disconnected",
                     hidjoy_name(joysticks[i].hid_handle),
                     hidjoy_vendor_id(joysticks[i].hid_handle),
                     hidjoy_product_id(joysticks[i].hid_handle),
                     windows_strerror(GetLastError()));
                hidjoy_flush_events(joysticks[i].hid_handle);
                joystick_info[i].connected = 0;
                send_joystick_connect_event(i, INPUT_JOYSTICK_DISCONNECTED);
            }
        }
    }
    sys_mutex_unlock(joystick_mutex);
    UINT num_devices = 1;
    RAWINPUTDEVICELIST *devices =
        mem_alloc(sizeof(*devices), 0, MEM_ALLOC_TEMP);
    if (UNLIKELY(!devices)) {
        DLOG("No memory for 1 device structure");
        return;
    }
    UINT last_num_devices = num_devices;
    while (GetRawInputDeviceList(devices, &num_devices,
                                 sizeof(*devices)) == (UINT)(-1)) {
        if (UNLIKELY(GetLastError() != ERROR_INSUFFICIENT_BUFFER)) {
            DLOG("GetRawInputDeviceList() failed: %s",
                 windows_strerror(GetLastError()));
            mem_free(devices);
            return;
        }
        if (UNLIKELY(num_devices <= last_num_devices)) {
            DLOG("GRIDL returned INSUFFICIENT_BUFFER but did not update"
                 " num_devices (Steam bug?), assuming no rawinput devices");
            mem_free(devices);
            return;
        }
        RAWINPUTDEVICELIST *new_devices = mem_realloc(
            devices, sizeof(*devices) * num_devices, MEM_ALLOC_TEMP);
        if (UNLIKELY(!new_devices)) {
            DLOG("No memory for %u device structures", num_devices);
            mem_free(devices);
            return;
        }
        devices = new_devices;
        last_num_devices = num_devices;
    }
    for (UINT i = 0; i < num_devices; i++) {
        add_rawinput_joystick(devices[i].hDevice);
    }
    mem_free(devices);
}
static void scan_rawinput_joysticks ( void ) { sys_mutex_lock ( joystick_mutex , -1 ) ; for ( int i = 0 ; i < num_joysticks ; i ++ ) { if ( joystick_info [ i ] . connected && ! joysticks [ i ] . is_xinput ) { RID_DEVICE_INFO device_info = { . cbSize = sizeof ( device_info ) } ; if ( GetRawInputDeviceInfo ( joysticks [ i ] . device , RIDI_DEVICEINFO , & device_info , ( UINT [ ] ) { sizeof ( device_info ) } ) == ( UINT ) ( -1 ) ) { DLOG ( " " " " , hidjoy_name ( joysticks [ i ] . hid_handle ) , hidjoy_vendor_id ( joysticks [ i ] . hid_handle ) , hidjoy_product_id ( joysticks [ i ] . hid_handle ) , windows_strerror ( GetLastError ( ) ) ) ; hidjoy_flush_events ( joysticks [ i ] . hid_handle ) ; joystick_info [ i ] . connected = 0 ; send_joystick_connect_event ( i , INPUT_JOYSTICK_DISCONNECTED ) ; } } } sys_mutex_unlock ( joystick_mutex ) ; UINT num_devices = 1 ; RAWINPUTDEVICELIST * devices = mem_alloc ( sizeof ( * devices ) , 0 , MEM_ALLOC_TEMP ) ; if ( UNLIKELY ( ! devices ) ) { DLOG ( " " ) ; return ; } UINT last_num_devices = num_devices ; while ( GetRawInputDeviceList ( devices , & num_devices , sizeof ( * devices ) ) == ( UINT ) ( -1 ) ) { if ( UNLIKELY ( GetLastError ( ) != ERROR_INSUFFICIENT_BUFFER ) ) { DLOG ( " " , windows_strerror ( GetLastError ( ) ) ) ; mem_free ( devices ) ; return ; } if ( UNLIKELY ( num_devices <= last_num_devices ) ) { DLOG ( " " " " ) ; mem_free ( devices ) ; return ; } RAWINPUTDEVICELIST * new_devices = mem_realloc ( devices , sizeof ( * devices ) * num_devices , MEM_ALLOC_TEMP ) ; if ( UNLIKELY ( ! new_devices ) ) { DLOG ( " " , num_devices ) ; mem_free ( devices ) ; return ; } devices = new_devices ; last_num_devices = num_devices ; } for ( UINT i = 0 ; i < num_devices ; i ++ ) { add_rawinput_joystick ( devices [ i ] . hDevice ) ; } mem_free ( devices ) ; }
Local routines: Raw input joystick handling
Local routines : Raw input joystick handling
/* In theory we could get the device list with a simple count-alloc-get
     * pattern, but there's always the chance that the system will add a
     * new device just as we're doing the second GRIDL call, so we loop
     * until GRIDL succeeds. */ /* At least as of January 2018, the gameoverlayrenderer.dll
             * library injected by Valve's Steam client when starting a
             * game wraps GRIDL with a buggy function that does not update
             * num_devices, so we end up infinite-looping here. */