2016-08-23 12 views
0

Я пытаюсь читать с моего контроллера XBox 360 без опроса. (Чтобы быть точным, я фактически использую Logitech F310, но мой ПК с Windows 10 видит его как контроллер XBox 360.) Я написал довольно неприятный HID-код, который использует перекрывающиеся ввода-вывода для блокировки в потоке на двух события, указывающие, что отчет готов к чтению с устройства HID, а другой, указывающий, что поток пользовательского интерфейса запросил выход HID-потока. Это работает отлично, но драйвер HID ведет себя несколько иначе, чем XInput. В частности, он объединяет два триггера в одно значение, только передавая их разницу (по любопытной заявке, что игры ожидают, что значения HID будут 0x80, когда палец игрока выключен). XInput рассматривает их как два разных значения, что является большим улучшением. Кроме того, XInput сообщает о переключателях шляп как четыре бита, что означает, что вы можете получить из него десять состояний: unpressed, N, NE, E, SE, S, SW, W, NW и all-down (последний может быть трудно использовать, но, по крайней мере, он есть, если вы этого хотите, я использовал его для выхода из цикла опроса).Любой способ блокировки при чтении контроллера XBox 360, отличного от HID API?

Недостатком для XInput является то, что, по-видимому, невозможно блокировать запрос на чтение, пока контроллер не изменит одно из своих значений или кнопок. Как HID-устройство, вызов ReadFile блокирует (точнее, блоки WaitForMultipleEvents до тех пор, пока не будут доступны данные). Предполагается, что XInput ожидает опроса. Для игры, которая, естественно, была бы записана, чтобы опросить контроллер так часто, как он обновил состояние игры (может быть, один раз для каждого нового видеокадра, отображаемого, например), что имеет смысл. Но если вы хотите использовать контроллер для какой-либо другой цели (я работаю над театральным приложением), вам может понадобиться чисто асинхронная система, такая как HID API. Но, опять же, API HID объединяет два триггера значения.

Теперь, когда вы читаете устройство с XInput, вы получаете не только состояние всех элементов управления, но и номер пакета. MSDN говорит, что номер пакета изменяется только при изменении состояния элемента управления. Таким образом, если последовательные номера пакетов совпадают, вам не нужно беспокоиться о какой-либо обработке после первой, потому что вы знаете, что состояние контроллера не изменилось. Но вы все еще проводите опрос, который для меня несколько вульгарен.

Что меня заинтриговало, так это то, что когда я ставил большую задержку между моими опросами (100 мс), я вижу, что номера пакетов увеличиваются более чем на один, когда контроль значений (триггеры или палки) переехал. Это, я думаю, предполагает, что устройство отправляет пакеты, не ожидая, что их будут опрошены, и что я получаю только последний пакет при каждом опросе. Если это так, кажется, что я должен блокировать до отправки пакета и реагировать только тогда, когда это происходит, а не на необходимость опроса вообще. Но я не могу найти никаких признаков того, что это вариант. Поскольку я могу блокировать HID API, я не хочу сдаваться без попытки (в том числе просить совета здесь).

Недостаточно написания моего собственного драйвера для контроллера (что я не уверен, что это даже вариант без проприетарной документации), кто-нибудь знает, как я могу использовать перекрывающиеся ввода-вывода (или любой другой метод блокировки) для чтения Контроллер XBox 360, как это делает XInput, с триггерами как отдельными значениями, а шляпа - четырьмя кнопками?

Ниже приведен код, я написал, что читает контроллер и показывает, что количество пакетов может подскочить более чем на один между чтениями:

#include <Windows.h> 
#include <Xinput.h> 
#include <stdio.h> 

#define MAX_CONTROLLERS 4 

int main() 
{ 
    DWORD userIndex; 

    XINPUT_STATE xs; 
    XINPUT_VIBRATION v; 

    XInputEnable(TRUE); 

    // Which one are we? 

    for (userIndex = 0; userIndex < XUSER_MAX_COUNT; ++userIndex) 
     if (XInputGetState(userIndex, &xs) == ERROR_SUCCESS) 
      break; 

    if (userIndex == XUSER_MAX_COUNT) 
    { 
     printf("Couldn't find an Xbox 360 controller.\n"); 
     getchar(); 
     return -1; 
    } 

    printf("Using controller #%1d.\n", userIndex); 

    while (TRUE) 
    { 
     DWORD res = XInputGetState(userIndex, &xs); 

     printf("%5d %6d: %3d %3d %3d %3d %3d %3d 0x%04X\n", 
       res, 
      xs.dwPacketNumber, 
      xs.Gamepad.bLeftTrigger & 0xFF, 
      xs.Gamepad.bRightTrigger & 0xFF, 
      xs.Gamepad.sThumbLX & 0xFF, 
      xs.Gamepad.sThumbLY & 0xFF, 
      xs.Gamepad.sThumbRX & 0xFF, 
      xs.Gamepad.sThumbRY & 0xFF, 
      xs.Gamepad.wButtons); 

     if (xs.Gamepad.wButtons == 0x000F) // mash down the hat 
      break; 

     Sleep(100); 
    } 

    getchar(); 
    return 0; 
} 

Пожалуйста, обратите внимание, что DirectInput не очень поможет, так как она также сочетает в себе триггеры в одно значение.

Спасибо!

ответ

1

Не уверен, что для этого есть какое-либо преимущество, но вы могли бы написать поток, который опросает регулярный интервал, а затем устанавливает семафор (или какой-либо другой сигнал), когда состояние изменилось. Тогда ваш основной поток может блокировать ожидание сигнала из потока опроса.Но потенциально не может быть никаких преимуществ для этой системы, потому что на некоторых контроллерах значения пальцев меняются несколько раз, независимо от того, перемещаете их или нет. (Шум) Вы могли бы, конечно, игнорировать небольшие изменения и только сигнализировать свой семафор, когда произошли большие изменения.

+0

Спасибо, чип. Вот где я ожидаю, что закончится. Microsoft на самом деле решительно говорит о том, что мы кодируем то, что они называют «мертвой зоной» вокруг идеального значения «руки» для контроля значений, именно из-за проблемы с шумом (и мои эксперименты подтверждают, что палочки не всегда возвращаются к точно таким же ценность каждый раз, когда я их отпущу, хотя, как это ни парадоксально, срабатывают триггеры). Нить, которая эмулирует асинхронный вызов ReadFile, будет работать нормально, и вызов XInputGetState займет только 20us на моей машине. Очень легкие накладные расходы. Просто вульгарно;). –

 Смежные вопросы

  • Нет связанных вопросов^_^