Cara mengirim permintaan transfer massal USB (aplikasi UWP)

Dalam topik ini, Anda akan mempelajari tentang transfer massal USB dan cara memulai permintaan transfer dari aplikasi UWP Anda yang berkomunikasi dengan perangkat USB.

Perangkat USB berkecepatan penuh, kecepatan tinggi, dan SuperSpeed dapat mendukung titik akhir massal. Titik akhir tersebut digunakan untuk mentransfer data dalam jumlah besar, seperti mentransfer data ke atau dari USB flash drive. Transfer massal dapat diandalkan karena memungkinkan deteksi kesalahan dan melibatkan percobaan ulang dalam jumlah terbatas untuk memastikan data diterima oleh host atau perangkat. Transfer massal digunakan untuk data yang tidak penting waktu. Data ditransfer hanya ketika ada bandwidth yang tidak digunakan yang tersedia di bus. Oleh karena itu, ketika bus sibuk dengan transfer lain, data massal dapat menunggu tanpa batas waktu.

Titik akhir massal tidak langsung dan dalam satu transfer, data dapat ditransfer baik dalam arah IN atau OUT. Untuk mendukung pembacaan dan penulisan data massal, perangkat harus mendukung titik akhir IN massal dan KELUAR massal. Titik akhir IN massal digunakan untuk membaca data dari perangkat ke host dan titik akhir OUT massal digunakan untuk mengirim data dari host ke perangkat.

Untuk memulai permintaan transfer massal, aplikasi Anda harus memiliki referensi ke pipa yang mewakili titik akhir. Pipa adalah saluran komunikasi yang dibuka oleh driver perangkat ketika perangkat dikonfigurasi. Untuk aplikasi, pipa adalah representasi logis dari titik akhir. Untuk membaca data dari titik akhir, aplikasi mendapatkan data dari pipa IN massal terkait. Untuk menulis data ke titik akhir, aplikasi mengirim data ke pipa OUT massal. Untuk membaca dan menulis pipa secara massal, gunakan kelas UsbBulkInPipe dan UsbBulkOutPipe .

Aplikasi Anda juga dapat mengubah perilaku pipa dengan mengatur bendera kebijakan tertentu. Misalnya untuk permintaan baca, Anda dapat mengatur bendera yang secara otomatis menghapus kondisi kios pada pipa. Untuk informasi tentang bendera tersebut, lihat UsbReadOptions dan UsbWriteOptions.

Sebelum memulai

Langkah 1: Dapatkan objek pipa massal

Untuk memulai permintaan transfer, Anda harus mendapatkan referensi ke objek pipa massal (UsbBulkOutPipe atau UsbBulkInPipe. Anda bisa mendapatkan pipa dengan menghitung semua pengaturan semua antarmuka. Namun, untuk transfer data, Anda hanya boleh menggunakan pipa pengaturan aktif. Jika objek pipa null jika titik akhir terkait tidak berada dalam pengaturan aktif.

Jika Anda ingin... Gunakan nilai properti ini
Kirim data ke pipa massal, dapatkan referensi ke UsbBulkOutPipe. UsbDevice.DefaultInterface.BulkOutPipes[n] jika konfigurasi perangkat Anda mengekspos satu antarmuka USB.

UsbDevice.Configuration.UsbInterfaces[m]. BulkOutPipes[n] untuk menghitung pipa OUT massal di beberapa antarmuka yang didukung oleh perangkat.

UsbInterface.InterfaceSettings[m]. BulkOutEndpoints[n]. Pipa untuk menghitung pipa OUT massal yang ditentukan oleh pengaturan dalam antarmuka.

UsbEndpointDescriptor.AsBulkOutEndpointDescriptor.Pipe untuk mendapatkan objek pipa dari deskriptor titik akhir untuk titik akhir OUT massal.
Menerima data dari pipa massal, Anda dapat memperoleh objek UsbBulkInPipe . UsbDevice.DefaultInterface.BulkInPipes[n] jika konfigurasi perangkat Anda mengekspos satu antarmuka USB.

UsbDevice.Configuration.UsbInterfaces[m]. BulkInPipes[n] untuk menghitung pipa IN massal di beberapa antarmuka yang didukung oleh perangkat.

UsbInterface.InterfaceSettings[m]. BulkInEndpoints[n]. Pipa untuk menghitung pipa IN massal yang ditentukan oleh pengaturan dalam antarmuka.

UsbEndpointDescriptor.AsBulkInEndpointDescriptor.Pipe untuk mendapatkan objek pipa dari deskriptor titik akhir untuk titik akhir IN massal.

Catatan

Harus dalam pengaturan aktif atau memerlukan pemeriksaan null.

Langkah 2: Mengonfigurasi pipa massal (Opsional)

Anda dapat mengubah perilaku operasi baca atau tulis dengan mengatur bendera tertentu pada pipa massal yang diambil.

Untuk membaca dari perangkat, atur properti UsbBulkInPipe.ReadOptions ke salah satu nilai yang ditentukan dalam UsbReadOptions. Dalam kasus penulisan, atur properti UsbBulkOutPipe.WriteOptions ke salah satu nilai yang ditentukan dalam UsbWriteOptions.

Jika Anda ingin... Atur bendera ini
Secara otomatis menghapus kondisi kesalahan apa pun di titik akhir tanpa menghentikan aliran data AutoClearStall

Untuk informasi selengkapnya, lihat Membersihkan kondisi kios.

Bendera ini berlaku untuk transfer baca dan tulis.
Kirim beberapa permintaan baca dengan efisiensi maksimum. Tingkatkan performa dengan melewati pemeriksaan kesalahan. OverrideAutomaticBufferManagement

Permintaan data dapat dibagi menjadi satu atau beberapa transfer, di mana setiap transfer berisi sejumlah byte tertentu yang disebut ukuran transfer maksimum. Untuk beberapa transfer, mungkin ada keterlambatan dalam mengantre dua transfer karena pemeriksaan kesalahan yang dilakukan oleh driver. Bendera ini melewati pemeriksaan kesalahan tersebut. Untuk mendapatkan ukuran transfer maksimum, gunakan properti UsbBulkInPipe.MaxTransferSizeBytes . Jika ukuran permintaan Anda adalah UsbBulkInPipe.MaxTransferSizeBytes, Anda harus mengatur bendera ini.

Penting: Jika Anda mengatur bendera ini, maka Anda harus meminta data dalam kelipatan ukuran paket maksimum pipa. Informasi tersebut disimpan di deskriptor titik akhir. Ukurannya tergantung pada kecepatan bus perangkat. Untuk kecepatan penuh, kecepatan tinggi, dan SuperSpeed; ukuran paket maksimum masing-masing adalah 64, 512, dan 1024 byte. Untuk mendapatkan nilai tersebut, gunakan properti UsbBulkInPipe.EndpointDescriptor.MaxPacketSize .

Bendera ini hanya berlaku untuk transfer baca.
Menghentikan permintaan tulis dengan paket panjang nol ShortPacketTerminate

Mengirim paket panjang nol untuk menunjukkan akhir transfer OUT.

Bendera ini hanya berlaku untuk transfer tulis.
Nonaktifkan membaca paket pendek (ukuran paket kurang dari maksimum yang didukung oleh titik akhir) IgnoreShortPacket

Secara default, jika perangkat mengirim byte kurang dari ukuran paket maksimum, aplikasi akan menerimanya. Jika Anda tidak ingin menerima paket pendek, atur bendera ini.

Bendera ini hanya berlaku untuk transfer baca.

Langkah 3: Menyiapkan aliran data

Saat data massal dikirim oleh perangkat, data diterima seperti dalam aliran input pada pipa massal. Berikut adalah langkah-langkah untuk mendapatkan aliran input:

  1. Dapatkan referensi ke aliran input dengan mendapatkan properti UsbBulkInPipe.InputStream .
  2. Buat objek DataReader dengan menentukan aliran input di konstruktor DataReader.

Untuk menulis data ke perangkat, aplikasi harus menulis ke aliran output pada pipa massal. Berikut adalah langkah-langkah untuk menyiapkan aliran output:

  1. Dapatkan referensi ke aliran output dengan mendapatkan properti UsbBulkOutPipe.OutputStream .
  2. Buat objek DataWriter dengan menentukan aliran output di konstruktor DataWriter .
  3. Isi buffer data yang terkait dengan aliran output.
  4. Bergantung pada jenis data, tulis data transfer ke aliran output dengan memanggil metode DataWriter, seperti WriteBytes.

Langkah 4: Memulai operasi transfer asinkron

Transfer massal dimulai melalui operasi asinkron.

Untuk membaca data massal, mulai operasi baca asinkron dengan memanggil DataReader.LoadAsync.

Untuk menulis data massal, mulai operasi penulisan asinkron dengan memanggil DataWriter.StoreAsync.

Langkah 5: Dapatkan hasil operasi transfer baca

Setelah operasi data asinkron selesai, Anda bisa mendapatkan jumlah byte yang dibaca atau ditulis dari objek tugas. Untuk operasi baca, panggil metode DataReader, seperti ReadBytes, untuk membaca data dari aliran input.

Membersihkan kondisi kios

Terkadang, aplikasi mungkin mengalami transfer data yang gagal. Transfer yang gagal dapat disebabkan oleh kondisi kios pada titik akhir. Selama titik akhir terhenti, data tidak dapat ditulis atau dibaca darinya. Untuk melanjutkan transfer data, aplikasi harus menghapus kondisi kios pada pipa terkait.

Aplikasi Anda dapat mengonfigurasi pipa untuk menghapus kondisi stall secara otomatis, saat terjadi. Untuk melakukannya, atur properti UsbBulkInPipe.ReadOptions ke UsbReadOptions.AutoClearStall atau properti UsbBulkOutPipe.WriteOptions ke UsbWriteOptions.AutoClearStall. Dengan konfigurasi otomatis tersebut, aplikasi tidak mengalami transfer yang gagal dan pengalaman transfer data mulus.

Untuk menghapus kondisi kios secara manual, panggil UsbBulkInPipe.ClearStallAsync untuk pipa IN massal; panggil UsbBulkOutPipe.ClearStallAsync untuk pipa OUT massal.

Catatan

Kondisi kios tidak menunjukkan titik akhir kosong. Jika tidak ada data di titik akhir, transfer selesai tetapi panjangnya nol byte.

Untuk operasi baca, Anda mungkin perlu menghapus data yang tertunda dalam pipa sebelum memulai permintaan transfer baru. Untuk melakukannya, panggil metode UsbBulkInPipe.FlushBuffer .

Contoh kode transfer massal USB

Contoh kode ini menunjukkan cara menulis ke pipa massal. Contoh mengirim data ke pipa OUT massal pertama pada antarmuka default. Ini mengonfigurasi pipa untuk mengirim paket panjang nol di akhir transfer. Ketika transfer selesai, jumlah byte ditampilkan.

    private async void BulkWrite()
    {
        String dataBuffer = "Hello World!";
        UInt32 bytesWritten = 0;

        UsbBulkOutPipe writePipe = usbDevice.DefaultInterface.BulkOutPipes[0];
        writePipe.WriteOptions |= UsbWriteOptions.ShortPacketTerminate;

        var stream = writePipe.OutputStream;

        DataWriter writer = new DataWriter(stream);

        writer.WriteString(dataBuffer);

        try
        {
            bytesWritten = await writer.StoreAsync();
        }
        catch (Exception exception)
        {
            ShowStatus(exception.Message.ToString());
        }
        finally
        {
            ShowStatus("Data written: " + bytesWritten + " bytes.");
        }
    }

Contoh kode ini menunjukkan cara membaca dari pipa massal. Contoh mengambil data dari pipa IN massal pertama pada antarmuka default. Ini mengonfigurasi pipa ke untuk efisiensi maksimum dan menerima data dalam potongan ukuran paket maksimum. Ketika transfer selesai, jumlah byte ditampilkan.

    private async void BulkRead()
    {
        UInt32 bytesRead = 0;

        UsbBulkInPipe readPipe = usbDevice.DefaultInterface.BulkInPipes[0];

        // Warning: Setting IgnoreShortPacket causes LoadAsync to block until you receive a number of packets >= readPipe.EndpointDescriptor.MaxPacketSize.
        // Remove the following line if you want to see messages that are less than the max transfer size, for example if you are communicating with a USBTMC device. 
        readPipe.ReadOptions |= UsbReadOptions.IgnoreShortPacket;

        var stream = readPipe.InputStream;
        DataReader reader = new DataReader(stream);

        try
        {
            bytesRead = await reader.LoadAsync(readPipe.EndpointDescriptor.MaxPacketSize);
        }
        catch (Exception exception)
        {
            ShowStatus(exception.Message.ToString());
        }
        finally
        {
            ShowStatus("Number of bytes: " + bytesRead);

            IBuffer buffer = reader.ReadBuffer(bytesRead);

            using (var dataReader = Windows.Storage.Streams.DataReader.FromBuffer(buffer))
            {
                dataReader.UnicodeEncoding = Windows.Storage.Streams.UnicodeEncoding.Utf8;
                ShowData(dataReader.ReadString(buffer.Length));
            }
        }
    }