Поделиться через


Отправка запроса на передачу прерываний USB (приложение UWP)

Передача прерываний возникает, когда узел опрашивает устройство. В этой статье демонстрируются следующие возможности.

  • Реализация обработчика событий для UsbInterruptInPipe.DataReceived
  • Регистрация и отмена регистрации обработчика событий

Важные API

USB-устройство может поддерживать конечные точки прерывания, чтобы они могли отправлять или получать данные через регулярные интервалы. Для этого узел опрашивает устройство через регулярные интервалы и передает данные каждый раз, когда узел опрашивает устройство. Передача прерываний в основном используется для получения данных прерываний с устройства. В этом разделе описывается, как приложение UWP может получать данные о непрерывных прерываниях с устройства.

Сведения о конечной точке прерывания

Для конечных точек прерывания дескриптор предоставляет эти свойства. Эти значения предназначены только для сведений и не должны влиять на управление буфером передачи буфера.

  • Как часто можно передавать данные?

    Получите эти сведения, получив значение интервала дескриптора конечной точки (см. раздел UsbInterruptOutEndpointDescriptor.Interval или UsbInterruptInEndpointDescriptor.Interval). Это значение указывает, как часто данные отправляются или получают от устройства в каждом кадре на шине.

    Свойство Interval не является значением bInterval (определено в спецификации USB).

    Это значение указывает, как часто данные передаются на устройство или с устройства. Например, для устройства высокой скорости, если интервал составляет 125 микросекунд, данные передаются каждые 125 микросекунд. Если интервал равен 1000 микросекундам, данные передаются каждые миллисекунды.

  • Сколько данных можно передавать в каждом интервале обслуживания?

    Получите количество байтов, которые могут передаваться путем получения максимального размера пакета, поддерживаемого дескриптором конечной точки (см. раздел UsbInterruptOutEndpointDescriptor.MaxPacketSize или UsbInterruptInEndpointDescriptor.MaxPacketSize). Максимальный размер пакета, ограниченный скоростью устройства. Для устройств с низкой скоростью до 8 байт. Для устройств с полной скоростью до 64 байт. Для высокоскоростных устройств с высокой пропускной способностью приложение может отправлять или получать больше максимального размера пакета до 3072 байт на микрофрейм.

    Конечные точки прерывания на устройствах SuperSpeed могут передавать еще больше байтов. Это значение указывается wBytesPerInterval USB_SUPERSPEED_ENDPOINT_COMPANION_DESCRIPTOR. Чтобы получить дескриптор, получите буфер дескриптора с помощью свойства UsbEndpointDescriptor.AsByte, а затем синтаксический анализ этого буфера с помощью методов DataReader.

Прерывание передачи out

USB-устройство может поддерживать прерывание конечных точек OUT, получающих данные от узла через регулярные интервалы. Каждый раз, когда узел опрашивает устройство, узел отправляет данные. Приложение UWP может инициировать запрос на передачу прерываний OUT, указывающий данные для отправки. Этот запрос завершается, когда устройство подтверждает данные из узла. Приложение UWP может записывать данные в UsbInterruptOutPipe.

Прерывание передачи IN

И наоборот, USB-устройство может поддерживать прерывание конечных точек IN в качестве способа информирования узла о аппаратных прерываниях, созданных устройством. Как правило, устройства USB-пользовательского интерфейса (HID), такие как клавиатуры и указатели устройств, поддерживают прерывание конечных точек OUT. При прерывании конечная точка сохраняет данные прерывания, но эти данные не достигают узла немедленно. Конечная точка должна ждать, пока контроллер узла будет опрашивать устройство. Так как между данными времени создается и достигается минимальная задержка, она опрашивает устройство через регулярные интервалы. Приложение UWP может получить данные, полученные в UsbInterruptInPipe. Запрос, который завершается, когда данные с устройства получаются узлом.

Перед началом работы

Запись в конечную точку прерывания OUT

Способ отправки запроса на передачу прерываний out идентичен массовой передаче OUT, за исключением того, что целевой объект является каналом прерывания OUT, представленным UsbInterruptOutPipe. Дополнительные сведения см. в статье "Как отправить запрос на массовую передачу USB (приложение UWP)".

Шаг 1. Реализация обработчика событий прерывания (прерывание IN)

При получении данных от устройства в канал прерываний вызывается событие DataReceived . Чтобы получить данные прерывания, приложение должно реализовать обработчик событий. Параметр eventArgs обработчика указывает на буфер данных.

В этом примере кода показана простая реализация обработчика событий. Обработчик поддерживает количество полученных прерываний. При каждом вызове обработчика увеличивается число. Обработчик получает буфер данных из параметра eventArgs и отображает количество прерываний и длину полученных байтов.

private async void OnInterruptDataReceivedEvent(UsbInterruptInPipe sender, UsbInterruptInEventArgs eventArgs)
{
    numInterruptsReceived++;

    // The data from the interrupt
    IBuffer buffer = eventArgs.InterruptData;

    // Create a DispatchedHandler for the because we are interacting with the UI directly and the
    // thread that this function is running on may not be the UI thread; if a non-UI thread modifies
    // the UI, an exception is thrown

    await Dispatcher.RunAsync(
                       CoreDispatcherPriority.Normal,
                       new DispatchedHandler(() =>
    {
        ShowData(
        "Number of interrupt events received: " + numInterruptsReceived.ToString()
        + "\nReceived " + buffer.Length.ToString() + " bytes");
    }));
}
void OnInterruptDataReceivedEvent(UsbInterruptInPipe^ /* sender */, UsbInterruptInEventArgs^  eventArgs )
{
    numInterruptsReceived++;

    // The data from the interrupt
    IBuffer^ buffer = eventArgs->InterruptData;

    // Create a DispatchedHandler for the because we are interracting with the UI directly and the
    // thread that this function is running on may not be the UI thread; if a non-UI thread modifies
    // the UI, an exception is thrown

    MainPage::Current->Dispatcher->RunAsync(
        CoreDispatcherPriority::Normal,
        ref new DispatchedHandler([this, buffer]()
        {
            ShowData(
                "Number of interrupt events received: " + numInterruptsReceived.ToString()
                + "\nReceived " + buffer->Length.ToString() + " bytes",
                NotifyType::StatusMessage);
        }));
}

Шаг 2. Получение объекта канала прерывания (прерывание IN)

Чтобы зарегистрировать обработчик событий для события DataReceived, получите ссылку на UsbInterruptInPipe с помощью любых следующих свойств:

Обратите внимание , что не следует получать объект канала путем перечисления конечных точек прерываний параметра интерфейса, который в данный момент не выбран. Для передачи данных каналы должны быть связаны с конечными точками в активном параметре.

Шаг 3. Регистрация обработчика событий для начала получения данных (прерывание IN)

Затем необходимо зарегистрировать обработчик событий в объекте UsbInterruptInPipe, который вызывает событие DataReceived.

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

private void RegisterForInterruptEvent(TypedEventHandler<UsbInterruptInPipe, UsbInterruptInEventArgs> eventHandler)
{
    // Search for the correct pipe that has the specified endpoint number
    interruptPipe = usbDevice.DefaultInterface.InterruptInPipes[0];

    // Save the interrupt handler so we can use it to unregister
    interruptEventHandler = eventHandler;

    interruptPipe.DataReceived += interruptEventHandler;

    registeredInterruptHandler = true;
}
void RegisterForInterruptEvent(TypedEventHandler<UsbInterruptInPipe, UsbInterruptInEventArgs> eventHandler)
    // Search for the correct pipe that has the specified endpoint number
    interruptInPipe = usbDevice.DefaultInterface.InterruptInPipes.GetAt(pipeIndex);

    // Save the token so we can unregister from the event later
    interruptEventHandler = interruptInPipe.DataReceived += eventHandler;

    registeredInterrupt = true;    

}

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

Шаг 4. Отмена регистрации обработчика событий для остановки получения данных (прерывание IN)

После завершения получения данных отмените регистрацию обработчика событий.

В этом примере кода показано, как отменить регистрацию обработчика событий. В этом примере, если у приложения есть ранее зарегистрированный обработчик событий, метод получает отслеживаемый обработчик событий и отменяет регистрацию в канале прерываний.

private void UnregisterInterruptEventHandler()
{
    if (registeredInterruptHandler)
    {
        interruptPipe.DataReceived -= interruptEventHandler;

        registeredInterruptHandler = false;
    }
}
void UnregisterFromInterruptEvent(void)
{
    if (registeredInterrupt)
    {
        interruptInPipe.DataReceived -= eventHandler;

        registeredInterrupt = false;
    }
}

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