informasi kontak saya
Surat[email protected]
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Di USB 2.0 dan perangkat yang lebih lama, titik akhir massal dapat mengirim atau menerima aliran data tunggal melalui titik akhir. Pada perangkat USB 3.0, titik akhir massal mampu mengirim dan menerima beberapa aliran data melalui titik akhir.
Tumpukan driver USB yang disediakan oleh Microsoft di Windows mendukung banyak aliran. Hal ini memungkinkan driver klien mengirim permintaan I/O independen ke setiap aliran yang terkait dengan titik akhir massal di perangkat USB 3.0, tanpa membuat serial permintaan ke aliran berbeda.
Bagi driver klien, aliran mewakili beberapa titik akhir logis dengan serangkaian karakteristik yang sama. Untuk mengirim permintaan ke aliran tertentu, driver klien memerlukan pegangan untuk aliran tersebut (mirip dengan pegangan pipa titik akhir). URB untuk permintaan I/O streaming mirip dengan URB untuk permintaan I/O untuk titik akhir massal. Satu-satunya perbedaan adalah pegangan pipanya. Untuk mengirim permintaan I/O ke aliran, driver menentukan pegangan pipa di aliran.
Selama konfigurasi perangkat, driver klien mengirimkan permintaan konfigurasi pilihan dan permintaan antarmuka pilihan. Permintaan ini mengambil sekumpulan pegangan pipa untuk titik akhir yang ditentukan dalam pengaturan aktivitas antarmuka. Untuk titik akhir yang sadar aliran, pegangan pipa titik akhir dapat digunakan untuk mengirim permintaan I/O ke aliran default (aliran pertama) hingga driver membuka aliran tersebut.
Jika driver klien ingin mengirim permintaan ke aliran selain aliran default, pengemudi harus membuka dan mendapatkan pegangan untuk semua aliran. Untuk melakukan hal ini, driver klien mengirimkan permintaan aliran terbuka dengan menentukan jumlah aliran yang akan dibuka. Setelah driver klien selesai menggunakan stream, driver dapat memilih untuk menutupnya dengan mengirimkan permintaan penutupan stream.
Kerangka Pengandar Mode Kernel (KMDF) tidak mendukung aliran statis. Driver klien harus menggunakan Windows Driver Model (WDM) untuk membuka dan menutup stream. Driver klien Kerangka Pengandar mode pengguna (UMDF) tidak dapat menggunakan fitur streaming statis.
Berikut ini mungkin berisi beberapa komentar berlabel Driver WDM. Petunjuk ini menjelaskan rutinitas untuk driver klien USB berbasis WDM yang ingin mengirim permintaan streaming.
Sebelum driver klien dapat membuka atau menutup aliran, driver harus memiliki:
1. Panggil metode WdfUsbTargetDeviceCreateWithParameters. Metode memerlukan versi protokol klien USBD_CLIENT_CONTRACT_VERSION_602. Dengan menentukan versi ini, driver klien harus mematuhi serangkaian aturan.
Panggilan untuk mengambil pegangan WDFUSBDEVICE dari objek perangkat target USB kerangka kerja. Pegangan ini diperlukan untuk panggilan selanjutnya ke aliran terbuka. Biasanya, driver klien mendaftarkan dirinya dalam rutinitas panggilan balik kejadian EVT_WDF_DEVICE_PREPARE_HARDWARE driver.
Driver WDM: Panggil rutin USBD_CreateHandle dan dapatkan pegangan USBD yang didaftarkan oleh driver di tumpukan driver USB.
2. Mengonfigurasi perangkat dan memperoleh pegangan pipa WDFUSBPIPE untuk titik akhir massal yang mendukung streaming. Untuk mendapatkan pegangan pipa, panggil metode WdfUsbInterfaceGetConfiguredPipe pada pengaturan alternatif antarmuka saat ini dalam konfigurasi yang dipilih.
Driver WDM: Mendapatkan pegangan pipa USBD dengan mengirimkan permintaan konfigurasi-pilih atau antarmuka-pilih.
1. Tentukan apakah tumpukan driver USB dan pengontrol host yang mendasarinya mendukung fitur streaming statis dengan memanggil metode WdfUsbTargetDeviceQueryUsbCapability. Biasanya, driver klien memanggil rutinitas dalam rutinitas panggilan balik acara EVT_WDF_DEVICE_PREPARE_HARDWARE driver.
Driver WDM: Memanggil rutin USBD_QueryUsbCapability. Biasanya, driver menanyakan fungsi yang akan digunakan dalam rutinitas perangkat startup driver, (IRP_MN_START_DEVICE).
Berikan informasi berikut:
Driver WDM: Teruskan pegangan USBD yang diambil pada panggilan sebelumnya ke USBD_CreateHandle.
Jika driver klien ingin menggunakan fitur tertentu, driver harus terlebih dahulu menanyakan tumpukan driver USB yang mendasarinya untuk menentukan apakah tumpukan driver dan pengontrol host mendukung fitur tersebut. Jika fitur tersebut didukung, barulah pengemudi dapat mengirimkan permintaan untuk menggunakan fitur tersebut. Permintaan tertentu memerlukan URB, seperti fungsi streaming yang dibahas pada Langkah 5. Untuk permintaan ini, pastikan untuk menggunakan pegangan yang sama untuk menanyakan fungsi dan mengalokasikan URB. Hal ini karena tumpukan driver menggunakan pegangan untuk melacak fitur-fitur pendukung yang dapat digunakan driver.
Misalnya, jika USBD_HANDLE diperoleh dengan memanggil USBD_CreateHandle, tumpukan driver akan ditanyakan dengan memanggil USBD_QueryUsbCapability dan URB dialokasikan dengan memanggil USBD_UrbAllocation. Lewatkan USBD_HANDLE yang sama di kedua panggilan.
Jika Anda memanggil metode KMDF, WdfUsbTargetDeviceQueryUsbCapability, dan WdfUsbTargetDeviceCreateUrb, tentukan pegangan WDFUSBDEVICE yang sama untuk objek target kerangka kerja dalam pemanggilan metode ini.
2. Evaluasi nilai NTSTATUS yang dikembalikan. Jika rutinitas berhasil diselesaikan, STATUS_SUCCESS dikembalikan, dan fungsi streaming statis didukung. Jika tidak, metode ini akan mengembalikan kode kesalahan yang sesuai.
3. Tentukan jumlah aliran yang akan dibuka. Jumlah maksimum stream yang dapat dibuka dibatasi oleh:
Untuk menentukan jumlah aliran maksimum, pilih nilai yang lebih kecil dari dua nilai yang didukung oleh pengontrol host dan titik akhir.
4. Alokasikan array struktur USBD_STREAM_INFORMATION n-elemen, di mana n adalah jumlah aliran yang akan dibuka. Driver klien bertanggung jawab untuk membebaskan array ini setelah driver selesai menggunakan aliran.
5. Alokasikan URB untuk permintaan aliran terbuka dengan memanggil metode WdfUsbTargetDeviceCreateUrb. Jika panggilan berhasil diselesaikan, metode ini mengambil objek memori WDF dan alamat struktur URB yang dialokasikan oleh tumpukan driver USB.
Driver WDM: Memanggil rutin USBD_UrbAllocation.
6. Atur format URB dari permintaan aliran terbuka. URB menggunakan struktur _URB_OPEN_STATIC_STRREAMS untuk menentukan permintaan. Untuk memformat URB, Anda memerlukan:
Untuk memformat URB, panggil UsbBuildOpenStaticStreamsRequest dan teruskan informasi yang diperlukan sebagai nilai parameter. Pastikan jumlah aliran yang ditentukan ke UsbBuildOpenStaticStreamsRequest tidak melebihi jumlah maksimum aliran yang didukung.
7. Kirim URB sebagai objek permintaan WDF dengan memanggil metode WdfRequestSend. Untuk mengirim permintaan secara sinkron, panggil metode WdfUsbTargetDeviceSendUrbSynchronously.
Driver WDM: Mengaitkan URB dengan IRP dan mengirimkan IRP ke tumpukan driver USB.
8. Setelah permintaan selesai, periksa status permintaan.Jika permintaan tumpukan driver USB gagal, status URB berisi kode kesalahan yang relevan.
Jika status permintaan (objek permintaan IRP atau WDF) menunjukkan USBD_STATUS_SUCCESS, permintaan berhasil diselesaikan. Array struktur USBD_STREAM_INFORMATION diterima saat pemeriksaan selesai. Array diisi dengan informasi tentang aliran yang diminta. Tumpukan driver USB mengisi setiap struktur dalam array dengan informasi aliran, seperti pegangan yang diterima USBD_PIPE_HANDLE, pengidentifikasi aliran, dan ukuran transfer numerik maksimum. Aliran sekarang dapat mentransfer data.
Untuk permintaan aliran terbuka, URB dan array perlu dialokasikan. Setelah permintaan aliran terbuka selesai, driver klien harus melepaskan URB dengan memanggil metode WdfObjectDelete pada objek memori WDF terkait. Jika driver mengirimkan permintaan secara sinkron dengan memanggil WdfUsbTargetDeviceSendUrbSynchronously, objek memori WDF harus dilepaskan setelah metode kembali. Jika driver klien mengirimkan permintaan secara asinkron dengan memanggil WdfRequestSend, driver harus melepaskan objek memori WDF dalam rutinitas penyelesaian yang diimplementasikan driver yang terkait dengan permintaan tersebut.
Array aliran dapat dilepaskan setelah driver klien selesai menggunakan aliran, atau dapat disimpan untuk permintaan I/O. Dalam contoh kode yang disertakan di bawah, driver menyimpan array aliran dalam konteks perangkat. Driver melepaskan konteks perangkat sebelum melepaskan objek perangkat.
Cara mentransfer data ke aliran tertentu
Untuk mengirim permintaan transfer data ke aliran tertentu, diperlukan objek permintaan WDF. Biasanya, driver klien tidak perlu mengalokasikan objek permintaan WDF. Ketika manajer I/O menerima permintaan dari suatu aplikasi, manajer I/O membuat IRP untuk permintaan tersebut. IRP dicegat oleh kerangka kerja. Kerangka kerja kemudian mengalokasikan objek permintaan WDF untuk mewakili IRP. Setelah itu, kerangka kerja meneruskan objek permintaan WDF ke driver klien. Driver klien kemudian dapat mengaitkan objek permintaan dengan URB transfer data dan mengirimkannya ke tumpukan driver USB.
Jika driver klien tidak menerima objek permintaan WDF dari kerangka kerja dan ingin mengirim permintaan secara asinkron, driver harus mengalokasikan objek permintaan WDF dengan memanggil metode WdfRequestCreate. Format objek baru dengan memanggil WdfUsbTargetPipeFormatRequestForUrb dan kirim permintaan dengan memanggil WdfRequestSend.
Dalam kasus sinkron, meneruskan objek permintaan WDF adalah opsional.
Untuk mentransfer data ke aliran, URB harus digunakan. URB harus diformat dengan memanggil WdfUsbTargetPipeFormatRequestForUrb.
Streaming tidak mendukung metode WDF berikut:
Prosedur berikut mengasumsikan bahwa driver klien menerima objek permintaan dari kerangka kerja.
Driver WDM: Mengalokasikan URB dengan memanggil USBD_UrbAllocation dan memformatnya untuk transfer massal (lihat _URB_BULK_OR_INTERRUPT_TRANSFER). Untuk memformat URB, Anda dapat memanggil UsbBuildInterruptOrBulkTransferRequest atau memformat struktur URB secara manual. Tentukan pegangan aliran di anggota UrbBulkOrInterruptTransfer.PipeHandle dari URB.
Driver klien dapat menutup aliran setelah driver selesai menggunakannya. Namun, menutup permintaan streaming bersifat opsional. Tumpukan driver USB menutup semua aliran ketika titik akhir yang terkait dengan aliran tersebut tidak dikonfigurasi. Titik akhir tidak dikonfigurasi ketika memilih konfigurasi atau antarmuka alternatif, menghapus perangkat, dll. Jika driver klien ingin membuka sejumlah aliran yang berbeda, ia harus menutup aliran tersebut. Kirim permintaan penutupan streaming:
1. Alokasikan struktur URB dengan memanggil WdfUsbTargetDeviceCreateUrb.
2. Atur format URB untuk menutup permintaan streaming. Anggota UrbPipeRequest dari struktur URB adalah struktur _URB_PIPE_REQUEST. Isikan anggotanya sebagai berikut:
3. Kirim URB sebagai permintaan WDF dengan memanggil WdfRequestSend atau WdfUsbTargetDeviceSendUrbSynchronously.
Pegangan tutup meminta penutupan semua aliran yang sebelumnya dibuka oleh driver klien. Pengandar klien tidak dapat menggunakan permintaan untuk menutup aliran tertentu di titik akhir.
Tumpukan driver USB melakukan verifikasi pada URB yang diterima. Untuk menghindari kesalahan validasi, lakukan hal berikut:
Terkadang, transfer ke atau dari titik akhir mungkin gagal. Kegagalan tersebut mungkin disebabkan oleh kondisi kesalahan pada titik akhir atau pengontrol host, seperti kondisi terhenti atau berhenti. Untuk menghapus kondisi kesalahan, driver klien terlebih dahulu membatalkan transfer yang tertunda dan kemudian mengatur ulang pipa yang terkait dengan titik akhir. Untuk membatalkan transfer yang tertunda, driver klien dapat mengirimkan permintaan pembatalan pipa. Untuk mereset pipa, driver klien harus mengirimkan permintaan reset pipa.
Untuk streaming, permintaan batalkan pipa dan setel ulang pipa tidak didukung untuk aliran individual yang terkait dengan titik akhir massal. Jika transfer pada pipa aliran tertentu gagal, pengontrol host akan menghentikan transfer pada semua pipa lain untuk aliran lainnya. Untuk memulihkan kondisi kesalahan, driver klien harus membatalkan transfer ke setiap aliran secara manual pegangan pipa untuk mengirim permintaan reset pipa ke titik akhir massal. Untuk permintaan ini, driver klien harus menentukan pegangan pipa titik akhir dalam struktur _URB_PIPE_REQUEST dan mengatur fungsi URB (Hdr.Function) ke URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL.
Contoh kode berikut menunjukkan cara membuka aliran.
- NTSTATUS
- OpenStreams (
- _In_ WDFDEVICE Device,
- _In_ WDFUSBPIPE Pipe)
- {
- NTSTATUS status;
- PDEVICE_CONTEXT deviceContext;
- PPIPE_CONTEXT pipeContext;
- USHORT cStreams = 0;
- USBD_PIPE_HANDLE usbdPipeHandle;
- WDFMEMORY urbMemory = NULL;
- PURB urb = NULL;
-
- PAGED_CODE();
-
- deviceContext =GetDeviceContext(Device);
- pipeContext = GetPipeContext (Pipe);
-
- if (deviceContext->MaxStreamsController == 0)
- {
- TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE,
- "%!FUNC! Static streams are not supported.");
-
- status = STATUS_NOT_SUPPORTED;
- goto Exit;
- }
-
- // If static streams are not supported, number of streams supported is zero.
-
- if (pipeContext->MaxStreamsSupported == 0)
- {
- status = STATUS_DEVICE_CONFIGURATION_ERROR;
-
- TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE,
- "%!FUNC! Static streams are not supported by the endpoint.");
-
- goto Exit;
- }
-
- // Determine the number of streams to open.
- // Compare the number of streams supported by the endpoint with the
- // number of streams supported by the host controller, and choose the
- // lesser of the two values. The deviceContext->MaxStreams value was
- // obtained in a previous call to WdfUsbTargetDeviceQueryUsbCapability
- // that determined whether or not static streams is supported and
- // retrieved the maximum number of streams supported by the
- // host controller. The device context stores the values for IN and OUT
- // endpoints.
-
- // Allocate an array of USBD_STREAM_INFORMATION structures to store handles to streams.
- // The number of elements in the array is the number of streams to open.
- // The code snippet stores the array in its device context.
-
- cStreams = min(deviceContext->MaxStreamsController, pipeContext->MaxStreamsSupported);
-
- // Allocate an array of streams associated with the IN bulk endpoint
- // This array is released in CloseStreams.
-
- pipeContext->StreamInfo = (PUSBD_STREAM_INFORMATION) ExAllocatePoolWithTag (
- NonPagedPool,
- sizeof (USBD_STREAM_INFORMATION) * cStreams,
- USBCLIENT_TAG);
-
- if (pipeContext->StreamInfo == NULL)
- {
- status = STATUS_INSUFFICIENT_RESOURCES;
-
- TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE,
- "%!FUNC! Could not allocate stream information array.");
-
- goto Exit;
- }
-
- RtlZeroMemory (pipeContext->StreamInfo,
- sizeof (USBD_STREAM_INFORMATION) * cStreams);
-
- // Get USBD pipe handle from the WDF target pipe object. The client driver received the
- // endpoint pipe handles during device configuration.
-
- usbdPipeHandle = WdfUsbTargetPipeWdmGetPipeHandle (Pipe);
-
- // Allocate an URB for the open streams request.
- // WdfUsbTargetDeviceCreateUrb returns the address of the
- // newly allocated URB and the WDFMemory object that
- // contains the URB.
-
- status = WdfUsbTargetDeviceCreateUrb (
- deviceContext->UsbDevice,
- NULL,
- &urbMemory,
- &urb);
-
- if (status != STATUS_SUCCESS)
- {
- TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE,
- "%!FUNC! Could not allocate URB for an open-streams request.");
-
- goto Exit;
- }
-
- // Format the URB for the open-streams request.
- // The UsbBuildOpenStaticStreamsRequest inline function formats the URB by specifying the
- // pipe handle to the entire bulk endpoint, number of streams to open, and the array of stream structures.
-
- UsbBuildOpenStaticStreamsRequest (
- urb,
- usbdPipeHandle,
- (USHORT)cStreams,
- pipeContext->StreamInfo);
-
- // Send the request synchronously.
- // Upon completion, the USB driver stack populates the array of with handles to streams.
-
- status = WdfUsbTargetPipeSendUrbSynchronously (
- Pipe,
- NULL,
- NULL,
- urb);
-
- if (status != STATUS_SUCCESS)
- {
- goto Exit;
- }
-
- Exit:
- if (urbMemory)
- {
- WdfObjectDelete (urbMemory);
- }
-
- return status;
- }