Cara mengirim permintaan transfer interupsi USB (aplikasi UWP)

Transfer interupsi terjadi ketika host melakukan polling perangkat. Artikel ini menunjukkan cara untuk:

API penting

Perangkat USB dapat mendukung titik akhir interupsi sehingga dapat mengirim atau menerima data secara berkala. Untuk mencapainya, host melakukan polling perangkat secara berkala dan data ditransmisikan setiap kali host melakukan polling perangkat. Transfer interupsi sebagian besar digunakan untuk mendapatkan data interupsi dari perangkat. Topik ini menjelaskan bagaimana aplikasi UWP bisa mendapatkan data interupsi berkelanjutan dari perangkat.

Informasi titik akhir interupsi

Untuk titik akhir interupsi, deskriptor mengekspos properti ini. Nilai-nilai tersebut hanya untuk informasi dan seharusnya tidak memengaruhi cara Anda mengelola buffer transfer buffer.

  • Seberapa sering data dapat ditransmisikan?

    Dapatkan informasi tersebut dengan mendapatkan nilai Interval deskriptor titik akhir (lihat UsbInterruptOutEndpointDescriptor.Interval atau UsbInterruptInEndpointDescriptor.Interval). Nilai itu menunjukkan seberapa sering data dikirim atau diterima dari perangkat di setiap bingkai di bus.

    Properti Interval bukan nilai bInterval (ditentukan dalam spesifikasi USB).

    Nilai itu menunjukkan seberapa sering data dikirimkan ke atau dari perangkat. Misalnya, untuk perangkat berkecepatan tinggi, jika Interval adalah 125 mikro detik, data ditransmisikan setiap 125 mikrosekon. Jika Interval adalah 1000 mikrosekon, maka data ditransmisikan setiap milidetik.

  • Berapa banyak data yang dapat dikirimkan di setiap interval layanan?

    Dapatkan jumlah byte yang dapat ditransmisikan dengan mendapatkan ukuran paket maksimum yang didukung oleh deskriptor titik akhir (lihat UsbInterruptOutEndpointDescriptor.MaxPacketSize atau UsbInterruptInEndpointDescriptor.MaxPacketSize). Ukuran paket maksimum yang dibatasi pada kecepatan perangkat. Untuk perangkat berkecepatan rendah hingga 8 byte. Untuk perangkat berkecepatan penuh, hingga 64 byte. Untuk perangkat bandwidth tinggi berkecepatan tinggi, aplikasi dapat mengirim atau menerima lebih dari ukuran paket maksimum hingga 3072 byte per mikroframe.

    Titik akhir interupsi pada perangkat SuperSpeed mampu mengirimkan lebih banyak byte. Nilai tersebut ditunjukkan oleh wBytesPerInterval dari USB_SUPERSPEED_ENDPOINT_COMPANION_DESCRIPTOR. Untuk mengambil deskriptor, dapatkan buffer deskriptor dengan menggunakan properti UsbEndpointDescriptor.AsByte lalu uraikan buffer tersebut dengan menggunakan metode DataReader .

Interupsi transfer OUT

Perangkat USB dapat mendukung titik akhir OUT interupsi yang menerima data dari host secara berkala. Setiap kali host melakukan polling perangkat, host mengirim data. Aplikasi UWP dapat memulai permintaan transfer OUT interupsi yang menentukan data yang akan dikirim. Permintaan tersebut selesai ketika perangkat mengakui data dari host. Aplikasi UWP dapat menulis data ke UsbInterruptOutPipe.

Interupsi transfer IN

Sebaliknya, perangkat USB dapat mendukung interupsi titik akhir IN sebagai cara untuk memberi tahu host tentang gangguan perangkat keras yang dihasilkan oleh perangkat. Biasanya Usb Human Interface Devices (HID) seperti keyboard dan perangkat penunjuk mendukung titik akhir OUT yang mengganggu. Ketika interupsi terjadi, titik akhir menyimpan data yang mengganggu tetapi data tersebut tidak segera mencapai host. Titik akhir harus menunggu pengontrol host melakukan polling pada perangkat. Karena harus ada penundaan minimal antara data waktu yang dihasilkan dan mencapai host, ia melakukan polling perangkat secara berkala. Aplikasi UWP bisa mendapatkan data yang diterima di UsbInterruptInPipe. Permintaan yang selesai ketika data dari perangkat diterima oleh host.

Sebelum memulai

Menulis ke titik akhir OUT interupsi

Cara aplikasi mengirim permintaan transfer OUT yang mengganggu identik dengan transfer OUT massal, kecuali targetnya adalah pipa OUT yang mengganggu, yang diwakili oleh UsbInterruptOutPipe. Untuk informasi selengkapnya, lihat Cara mengirim permintaan transfer massal USB (aplikasi UWP).

Langkah 1: Terapkan penanganan aktivitas interupsi (Interupsi IN)

Ketika data diterima dari perangkat ke dalam pipa interupsi, data tersebut akan memunculkan peristiwa DataReceived . Untuk mendapatkan data interupsi, aplikasi harus menerapkan penanganan aktivitas. Parameter eventArgs dari handler, menunjuk ke buffer data.

Contoh kode ini menunjukkan implementasi sederhana dari penanganan aktivitas. Handler mempertahankan jumlah interupsi yang diterima. Setiap kali handler dipanggil, penghandel akan menaikkan jumlah. Handler mendapatkan buffer data dari parameter eventArgs dan menampilkan jumlah interupsi dan panjang byte yang diterima.

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 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

    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);
        }));
}

Langkah 2: Dapatkan objek pipa interupsi (Interupsi IN)

Untuk mendaftarkan penanganan aktivitas untuk peristiwa DataReceived , dapatkan referensi ke UsbInterruptInPipe dengan menggunakan properti ini:

Catatan Hindari mendapatkan objek pipa dengan menghitung titik akhir interupsi dari pengaturan antarmuka yang saat ini tidak dipilih. Untuk mentransfer data, pipa harus dikaitkan dengan titik akhir dalam pengaturan aktif.

Langkah 3: Daftarkan penanganan aktivitas untuk mulai menerima data (Interupsi IN)

Selanjutnya, Anda harus mendaftarkan penanganan aktivitas pada objek UsbInterruptInPipe yang menaikkan peristiwa DataReceived .

Contoh kode ini menunjukkan cara mendaftarkan penanganan aktivitas. Dalam contoh ini, kelas melacak penanganan aktivitas, pipa tempat penanganan aktivitas terdaftar, dan apakah pipa saat ini menerima data. Semua informasi tersebut digunakan untuk membatalkan pendaftaran penanganan aktivitas, yang ditunjukkan pada langkah berikutnya.

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;    

}

Setelah penanganan aktivitas terdaftar, penanganan aktivitas dipanggil setiap kali data diterima dalam pipa interupsi terkait.

Langkah 4: Batalkan pendaftaran penanganan aktivitas untuk berhenti menerima data (Mengganggu IN)

Setelah Anda selesai menerima data, batalkan pendaftaran penanganan aktivitas.

Contoh kode ini menunjukkan cara membatalkan pendaftaran penanganan aktivitas. Dalam contoh ini, jika aplikasi memiliki penanganan aktivitas yang terdaftar sebelumnya, metode mendapatkan penanganan aktivitas yang dilacak, dan membatalkan pendaftarannya pada pipa interupsi.

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

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

        registeredInterrupt = false;
    }
}

Setelah penanganan aktivitas tidak terdaftar, aplikasi berhenti menerima data dari pipa interupsi karena penanganan aktivitas tidak dipanggil pada peristiwa gangguan. Ini tidak berarti bahwa pipa interupsi berhenti mendapatkan data.