Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Artikel ini menjelaskan struktur transfer kontrol dan bagaimana driver klien harus mengirim permintaan kontrol ke perangkat.
Tentang titik akhir default
Semua perangkat USB harus mendukung setidaknya satu titik akhir yang disebut titik akhir default. Setiap transfer yang menargetkan titik akhir default disebut kontrol transfer. Tujuan transfer kontrol adalah untuk memungkinkan host mendapatkan informasi perangkat, mengonfigurasi perangkat, atau melakukan operasi kontrol yang unik untuk perangkat.
Mari kita mulai dengan mempelajari karakteristik titik akhir default ini.
- Alamat titik akhir default adalah 0.
- Titik akhir default adalah dua arah, yaitu, host dapat mengirim data ke titik akhir dan menerima data darinya dalam satu transfer.
- Titik akhir default tersedia di tingkat perangkat dan tidak ditentukan dalam antarmuka perangkat apa pun.
- Titik akhir default aktif segera setelah koneksi dibuat antara host dan perangkat. Ini aktif bahkan sebelum konfigurasi dipilih.
- Ukuran paket maksimum titik akhir default tergantung pada kecepatan bus perangkat. Kecepatan rendah, 8 byte; kecepatan penuh dan tinggi, 64 byte; SuperSpeed, 512 byte.
Tata letak pemindahan kendali
Karena transfer pengendalian merupakan transfer prioritas tinggi, host telah mencadangkan bandwidth tertentu di bus. Untuk perangkat berkecepatan rendah dan penuh, 10% bandwidth; 20% untuk perangkat transfer tinggi dan SuperSpeed. Sekarang, mari kita lihat tata letak transfer kontrol.
Transfer kontrol dibagi menjadi tiga transaksi: transaksi penyiapan, transaksi data, dan transaksi status. Setiap transaksi berisi tiga jenis paket: paket token, paket data, dan paket jabat tangan.
Bidang tertentu umum untuk semua paket. Bidang-bidang ini adalah:
- Bidang sinkronisasi yang menunjukkan awal paket.
- Pengidentifikasi paket (PID) yang menunjukkan jenis paket, arah transaksi, dan dalam kasus paket jabat tangan, itu menunjukkan keberhasilan atau kegagalan transaksi.
- Bidang EOP menunjukkan akhir paket.
Bidang lain tergantung pada jenis paket.
Paket token
Setiap transaksi penyiapan dimulai dengan paket token. Berikut adalah struktur paket. Host selalu mengirim paket token.
Nilai PID menunjukkan jenis paket token. Berikut adalah nilai yang mungkin:
- PENYIAPAN: Menunjukkan awal transaksi penyiapan dalam transfer kontrol.
- IN: Menunjukkan bahwa host meminta data dari perangkat (dalam konteks pembacaan).
- OUT: Menunjukkan bahwa host mengirim data ke perangkat (tulis kasus).
- SOF: Menunjukkan awal frame. Jenis paket token ini berisi nomor bingkai 11-bit. Host mengirimkan paket SOF. Frekuensi di mana paket ini dikirim tergantung pada kecepatan bus. Untuk kecepatan penuh, host mengirimkan paket setiap 1millisecond; setiap 125 microsecond pada bus berkecepatan tinggi.
Paket data
Segera setelah paket token adalah paket data yang berisi payload. Jumlah byte yang dapat dimuat setiap paket data tergantung pada ukuran paket maksimum titik akhir default. Paket data dapat dikirim oleh host atau perangkat, tergantung pada arah transfer.
Paket jabat tangan
Segera mengikuti paket data adalah paket jabat tangan. PID paket menunjukkan apakah paket diterima oleh host atau perangkat atau tidak. Paket jabat tangan dapat dikirim oleh host atau perangkat, tergantung pada arah transfer.
Anda dapat melihat struktur transaksi dan paket dengan menggunakan penganalisis USB apa pun, seperti Beagle, Ellisys, penganalisis protokol LECroy USB. Perangkat penganalisis menunjukkan bagaimana data dikirim ke atau diterima dari perangkat USB melalui kabel. Dalam contoh ini, mari kita periksa beberapa jejak yang ditangkap oleh penganalisis USB LeCroy. Contoh ini hanya untuk informasi. Ini bukan dukungan oleh Microsoft.
Menyiapkan transaksi
Host selalu memulai transfer kontrol. Ini dilakukan dengan mengirimkan transaksi pengaturan. Transaksi ini berisi paket token yang disebut token penyiapan diikuti oleh paket data 8-byte. Cuplikan layar ini menunjukkan contoh transaksi penyiapan.
Pada jejak sebelumnya, host memulai (ditunjukkan oleh H↓) transfer kontrol dengan mengirim paket token penyiapan #434. Perhatikan bahwa PID menandakan PENYIAPAN yang menunjukkan token penyiapan. PID diikuti oleh alamat perangkat dan alamat titik akhir. Untuk transfer kontrol, alamat titik akhir tersebut selalu 0.
Selanjutnya, host mengirimkan paket data #435. PID adalah DATA0 dan nilai tersebut digunakan untuk pengurutan paket (yang akan dibahas). PID diikuti oleh 8 byte yang berisi informasi utama tentang permintaan ini. 8 byte tersebut menunjukkan jenis permintaan dan ukuran buffer tempat perangkat akan menulis responsnya.
Semua byte diterima dalam urutan terbalik. Seperti yang dijelaskan di bagian 9.3, kita melihat bidang dan nilai ini:
| Bidang | Ukuran | Nilai | Deskripsi |
|---|---|---|---|
| bmRequestType (Lihat 9.3.1 bmRequestType) | 1 | 0x80 | Arah transfer data adalah dari perangkat ke host (D7 adalah 1) Permintaan adalah permintaan standar (D6... D5 adalah 0) Penerima permintaan adalah PERANGKAT (D4 adalah 0) |
| bRequest (Lihat bagian Lihat 9.3.2 dan Tabel 9-4) | 1 | 0x06 | Jenis permintaan adalah GET_DESCRIPTOR. |
| wValue (Lihat Tabel 9-5) | 2 | 0x0100 | Nilai permintaan menunjukkan bahwa jenis deskriptor adalah DEVICE. |
| wIndex (Lihat bagian 9.3.4) | 2 | 0x0000 | Arahnya adalah dari host ke perangkat (D7 adalah 1) Nomor titik akhir adalah 0. |
| wLength (Lihat bagian 9.3.5) | 2 | 0x0012 | Permintaannya adalah mengambil 18 byte. |
Dengan demikian, kita dapat menyimpulkan bahwa dalam transfer kontrol (baca) ini, host mengirim permintaan untuk mengambil deskriptor perangkat dan menentukan 18 byte sebagai panjang transfer untuk menahan deskriptor tersebut. Cara perangkat mengirim 18 byte tersebut tergantung pada berapa banyak data yang dapat dikirim titik akhir default dalam satu transaksi. Informasi tersebut disertakan dalam deskriptor perangkat yang dikembalikan oleh perangkat dalam transaksi data.
Sebagai respons, perangkat mengirimkan paket jabat tangan (#436 yang ditunjukkan oleh D↓). Perhatikan bahwa nilai PID adalah ACK (paket ACK). Ini menunjukkan bahwa perangkat mengakui transaksi.
Transaksi data
Sekarang, mari kita lihat apa yang dikembalikan perangkat sebagai respons terhadap permintaan. Data aktual ditransfer dalam transaksi data.
Berikut adalah jejak transaksi data.
Setelah menerima paket ACK, host memulai transaksi data. Untuk memulai transaksi, ia mengirim paket token (#450) dengan arah sebagai IN (disebut token IN).
Sebagai respons, perangkat mengirim paket data (#451) yang mengikuti token IN. Paket data ini berisi pendeskripsi perangkat yang sebenarnya. Byte pertama menunjukkan panjang deskriptor perangkat, 18 byte (0x12). Byte terakhir dalam paket data ini menunjukkan ukuran paket maksimum yang didukung oleh titik akhir default. Dalam hal ini, kita melihat bahwa perangkat dapat mengirim 8 byte pada satu waktu melalui titik akhir defaultnya.
Catatan
Ukuran paket maksimum titik akhir default tergantung pada kecepatan perangkat. Titik akhir default perangkat berkecepatan tinggi adalah 64 byte; Perangkat berkecepatan rendah adalah 8 byte.
Host mengakui transaksi data dengan mengirim paket ACK (#452) ke perangkat.
Mari kita hitung jumlah data yang dikembalikan. Di bidang wLength paket data (#435) dalam transaksi penyiapan, host meminta 18 byte. Dalam transaksi data, kita melihat bahwa hanya 8 byte pertama dari deskriptor perangkat yang diterima dari perangkat. Jadi, bagaimana host menerima informasi yang disimpan di sisa 10 byte? Perangkat melakukannya dalam dua transaksi: 8 byte dan kemudian 2 byte terakhir.
Sekarang setelah host mengetahui ukuran paket maksimum titik akhir default, host memulai transaksi data baru dan meminta bagian berikutnya berdasarkan ukuran paket.
Berikut adalah transaksi data berikutnya:
Host memulai transaksi data sebelumnya dengan mengirim token IN (#463) dan meminta 8 byte berikutnya dari perangkat. Perangkat merespons dengan paket data (#464) yang berisi 8 byte deskriptor perangkat berikutnya.
Setelah menerima 8 byte, host mengirimkan paket ACK (#465) ke perangkat.
Selanjutnya, host meminta 2 byte terakhir dalam transaksi data lain sebagai berikut:
Oleh karena itu, kami melihat bahwa untuk mentransfer 18 byte dari perangkat ke host, host melacak jumlah byte yang ditransfer dan memulai tiga transaksi data (8+8+2).
Catatan
Perhatikan PID paket data dalam transaksi data 19, 23, 26. PID bergantian antara DATA0 dan DATA1. Urutan ini disebut pengalihan data. Dalam kasus di mana ada beberapa transaksi data, pengalihan data digunakan untuk memverifikasi urutan paket. Metode ini memastikan bahwa paket data tidak diduplikasi atau hilang.
Dengan memetakan paket data terkonsolidasi ke struktur deskriptor perangkat (Lihat Tabel 9-8), kita melihat bidang dan nilai ini:
| Bidang | Ukuran | Nilai | Deskripsi |
|---|---|---|---|
| bLength | 1 | 0x12 | Panjang pendeskripsi perangkat, yaitu 18 byte. |
| bDescriptorType | 1 | 0x01 | Jenis deskriptor adalah perangkat. |
| bcdUSB | 2 | 0x0100 | Nomor versi spesifikasi adalah 1.00. |
| bDeviceClass | 1 | 0x00 | Kelas perangkat adalah 0. Setiap antarmuka dalam konfigurasi memiliki informasi kelas. |
| bDeviceSubClass | 1 | 0x00 | Subkelas adalah 0 karena kelas perangkat adalah 0. |
| bProtocol | 1 | 0x00 | Protokol adalah 0. Perangkat ini tidak menggunakan protokol khusus kelas. |
| bMaxPacketSize0 | 1 | 0x08 | Ukuran paket maksimum titik akhir adalah 8 byte. |
| idVendor | 2 | 0x0562 | Telex Communications. |
| idProduct | 2 | 0x0002 | Mikrofon USB. |
| bcdDevice | 2 | 0x0100 | Menunjukkan nomor rilis perangkat. |
| iManufacturer | 1 | 0x01 | Teks produsen |
| iProduct | 1 | 0x02 | String produk. |
| iSerialNumber | 1 | 0x03 | Nomor seri. |
| bNumConfigurations | 1 | 0x01 | Jumlah konfigurasi. |
Dengan memeriksa nilai-nilai tersebut, kami memiliki beberapa informasi awal tentang perangkat. Perangkat ini adalah mikrofon USB berkecepatan rendah. Ukuran paket maksimum titik akhir default adalah 8 byte. Perangkat mendukung satu konfigurasi.
Status transaksi
Terakhir, host menyelesaikan transfer kontrol dengan memulai transaksi terakhir: transaksi status.
Host memulai transaksi dengan paket token OUT (#481). Tujuan paket ini adalah untuk memverifikasi bahwa perangkat mengirim semua data yang diminta. Tidak ada paket data yang dikirim dalam transaksi status ini. Perangkat merespons dengan paket ACK. Jika terjadi kesalahan, PID bisa saja NAK atau STALL.
Model pengemudi
- Kerangka Kerja Driver Kernel Mode
- Kerangka Kerja Pengemudi Mode Pengguna
- Pengantar WinUSB untuk Pengembang
Prasyarat
Sebelum driver klien dapat menghitung pipa, pastikan bahwa persyaratan ini terpenuhi:
Driver klien harus telah membuat objek perangkat target USB dalam kerangka kerja.
Jika Anda menggunakan templat USB yang disediakan dengan Microsoft Visual Studio Professional 2012, kode templat melakukan tugas tersebut. Kode templat mendapatkan handle ke objek perangkat target dan menyimpannya dalam konteks perangkat.
Driver klien KMDF
Driver klien KMDF harus mendapatkan handle WDFUSBDEVICE dengan memanggil metode WdfUsbTargetDeviceCreateWithParameters. Untuk informasi selengkapnya, lihat "Kode sumber perangkat" di Memahami struktur kode driver klien USB (KMDF).
Driver klien UMDF
Driver klien UMDF harus mendapatkan pointer IWDFUsbTargetDevice dengan mengkueri objek perangkat target kerangka kerja. Untuk informasi selengkapnya, lihat "Implementasi IPnpCallbackHardware dan tugas khusus USB" dalam Memahami struktur kode driver klien USB (UMDF).
Aspek terpenting untuk transfer kontrol adalah memformat token penyiapan dengan tepat. Sebelum mengirim permintaan, kumpulkan sekumpulan informasi ini:
- Arah permintaan: dari host ke perangkat atau dari perangkat ke host.
- Penerima permintaan: perangkat, antarmuka, titik akhir, atau lainnya.
- Kategori permintaan: standar, kelas, atau vendor.
- Jenis permintaan, seperti permintaan GET_DESCRIPTPOR. Untuk informasi selengkapnya, lihat bagian 9.5 dalam spesifikasi USB.
- Nilai wValue dan wIndex. Nilai-nilai tersebut bergantung pada jenis permintaan.
Anda dapat memperoleh semua informasi tersebut dari spesifikasi USB resmi.
Jika Anda menulis driver UMDF, dapatkan file header, Usb_hw.h dari Contoh Driver UMDF untuk OSR USB Fx2 Learning Kit. File header ini berisi makro dan struktur yang berguna untuk memformat paket penyetelan untuk transfer kontrol.
Semua driver UMDF harus berkomunikasi dengan driver mode kernel untuk mengirim dan menerima data dari perangkat. Untuk driver USB UMDF, driver mode kernel selalu merupakan driver WinUSB (Winusb.sys) yang disediakan Microsoft.
Setiap kali driver UMDF membuat permintaan untuk tumpukan driver USB, manajer I/O Windows mengirimkan permintaan ke WinUSB. Setelah menerima permintaan, WinUSB memproses permintaan atau meneruskannya ke tumpukan driver USB.
Metode yang ditentukan Microsoft untuk mengirim permintaan transfer kontrol
Driver klien USB pada host memulai sebagian besar permintaan kontrol untuk mendapatkan informasi tentang perangkat, mengonfigurasi perangkat, atau mengirim perintah kontrol vendor. Semua permintaan tersebut dapat dikategorikan ke dalam:
Permintaan standar didefinisikan dalam spesifikasi USB. Tujuan pengiriman permintaan standar adalah untuk mendapatkan informasi tentang perangkat, konfigurasi, antarmuka, dan titik akhirnya. Penerima setiap permintaan tergantung pada jenis permintaan. Penerima dapat berupa perangkat, antarmuka, atau titik akhir.
Catatan
Target dari pemindahan kontrol apa pun selalu merupakan titik akhir default. Penerima adalah entitas perangkat yang informasinya (deskriptor, status, dan sebagainya) yang diminati host.
Permintaan dapat diklasifikasikan lebih lanjut ke: permintaan konfigurasi, permintaan fitur, dan permintaan status.
- Permintaan konfigurasi dikirim untuk mendapatkan informasi dari perangkat sehingga host dapat mengonfigurasinya, seperti permintaan GET_DESCRIPTOR. Permintaan ini juga dapat berupa permintaan tulis yang dikirim oleh host untuk mengatur konfigurasi tertentu atau pengaturan alternatif di perangkat.
- Permintaan fitur dikirim oleh driver klien untuk mengaktifkan atau menonaktifkan pengaturan perangkat Boolean tertentu yang didukung oleh perangkat, antarmuka, atau titik akhir.
- Permintaan status memungkinkan host mendapatkan atau mengatur bit status yang ditentukan USB dari perangkat, titik akhir, atau antarmuka.
Untuk informasi selengkapnya, lihat Bagian 9.4 dalam spesifikasi USB, versi 2.0. Jenis permintaan standar didefinisikan dalam file header, Usbspec.h.
Permintaan kelas ditentukan oleh spesifikasi kelas perangkat tertentu.
Permintaan vendor disediakan oleh vendor dan bergantung pada permintaan yang didukung oleh perangkat.
Tumpukan USB yang disediakan oleh Microsoft menangani semua komunikasi protokol dengan perangkat sebagaimana ditunjukkan pada pelacakan sebelumnya. Driver mengekspos antarmuka driver perangkat (DDI) yang memungkinkan driver klien mengirim transfer kontrol dalam banyak cara. Jika driver klien Anda adalah driver Windows Driver Foundation (WDF), driver tersebut dapat memanggil rutinitas secara langsung untuk mengirim jenis permintaan kontrol umum. WDF mendukung transfer kontrol secara intrinsik untuk KMDF dan UMDF.
Jenis permintaan kontrol tertentu tidak diekspos melalui WDF. Untuk permintaan tersebut, driver klien dapat menggunakan model WDF-hybrid. Model ini memungkinkan driver klien untuk membangun dan memformat permintaan gaya URB WDM dan kemudian mengirim permintaan tersebut dengan menggunakan objek kerangka kerja WDF. Model hibrid hanya berlaku untuk pengandar mode kernel.
Untuk driver UMDF:
Gunakan makro dan struktur pembantu yang ditentukan dalam usb_hw.h. Header ini disertakan dengan Driver Sampel UMDF untuk OSR USB Fx2 Learning Kit.
Gunakan tabel ini untuk menentukan cara terbaik untuk mengirim permintaan kontrol ke tumpukan driver USB.
| Jika Anda ingin mengirim permintaan kontrol ke... | Untuk pengandar KMDF... | Untuk sebuah driver UMDF... | Untuk driver WDM, bangun struktur URB (Rutinitas Pembantu) |
|---|---|---|---|
| CLEAR_FEATURE: Nonaktifkan pengaturan fitur tertentu di perangkat, konfigurasi, antarmuka, dan titik akhirnya. Lihat bagian 9.4.1 dalam spesifikasi USB. |
|
|
_URB_CONTROL_FEATURE_REQUEST (UsbBuildFeatureRequest) URB_FUNCTION_CLEAR_FEATURE_TO_DEVICE (Fungsi URB Hapus Fitur ke Perangkat) URB_FUNCTION_CLEAR_FEATURE_TO_INTERFACE FUNGSI_URB_CLEAR_FEATURE_KE_TITIK_AKHIR URB_FUNGSI_CLEAR_FITUR_KE_YANG_LAIN |
| GET_CONFIGURATION: Dapatkan konfigurasi USB saat ini. Lihat bagian 9.4.2 dalam spesifikasi USB. | KMDF memilih konfigurasi pertama secara default. Untuk mengambil nomor konfigurasi yang ditentukan perangkat:
|
UMDF memilih konfigurasi pertama secara default. Untuk mengambil nomor konfigurasi yang ditentukan perangkat:
|
_URB_CONTROL_GET_CONFIGURATION_REQUEST URB_FUNCTION_GET_CONFIGURATION |
| GET_DESCRIPTOR: Mendapatkan perangkat, konfigurasi, antarmuka, dan deskriptor titik akhir. Lihat bagian 9.4.3 dalam spesifikasi USB. Untuk informasi selengkapnya, lihat Deskriptor USB. |
Panggil metode-metode ini:
|
Panggil metode ini:
|
_URB_CONTROL_DESCRIPTOR_REQUEST (UsbBuildGetDescriptorRequest) URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE URB_FUNCTION_GET_DESCRIPTOR_FROM_ENDPOINT URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE |
| GET_INTERFACE: Dapatkan pengaturan alternatif saat ini untuk antarmuka. Lihat bagian 9.4.4 dalam spesifikasi USB. |
|
|
_URB_CONTROL_GET_INTERFACE_REQUEST URB_FUNCTION_GET_INTERFACE |
| GET_STATUS: Mendapatkan bit status dari perangkat, titik akhir, atau antarmuka. Lihat bagian 9.4.5. dalam spesifikasi USB. |
|
|
_URB_CONTROL_GET_STATUS_REQUEST (UsbBuildGetStatusRequest) URB_FUNCTION_GET_STATUS_FROM_DEVICE FUNGSI_URB_GET_STATUS_DARI_ANTAR_MUKA FUNGSI_URB_DAPATKAN_STATUS_DARI_ENDPOINT URB_FUNCTION_GET_STATUS_DARI_LAIN. |
| SET_ADDRESS: Lihat bagian 9.4.6 dalam spesifikasi USB. | Permintaan ini ditangani oleh tumpukan driver USB; driver klien tidak dapat melakukan operasi ini. | Permintaan ini ditangani oleh tumpukan driver USB; driver klien tidak dapat melakukan operasi ini. | Permintaan ini ditangani oleh tumpukan driver USB; driver klien tidak dapat melakukan operasi ini. |
| SET_CONFIGURATION: Tetapkan konfigurasi. Lihat bagian 9.4.7 dalam spesifikasi USB. Untuk informasi selengkapnya, lihat Cara memilih konfigurasi untuk perangkat USB. |
Secara default KMDF memilih konfigurasi default dan pengaturan alternatif pertama di setiap antarmuka. Driver klien dapat mengubah konfigurasi default dengan memanggil metode WdfUsbTargetDeviceSelectConfigType dan menentukan WdfUsbTargetDeviceSelectConfigTypeUrb sebagai opsi permintaan. Anda kemudian harus memformat URB untuk permintaan ini dan mengirimkannya ke tumpukan driver USB. | Secara default UMDF memilih konfigurasi default dan pengaturan alternatif pertama di setiap antarmuka. Driver klien tidak dapat mengubah konfigurasi. |
_URB_SELECT_CONFIGURATION (USBD_SelectConfigUrbAllocateAndBuild) Fungsi URB Pilih Konfigurasi |
| SET_DESCRIPTOR: Perbarui perangkat, konfigurasi, atau deskriptor string yang ada. Lihat bagian 9.4.8 dalam spesifikasi USB. Permintaan ini tidak umum digunakan. Namun, tumpukan driver USB menerima permintaan tersebut dari driver klien. |
|
|
_URB_CONTROL_DESCRIPTOR_REQUEST URB_FUNGSI_SET_DESCRIPTOR_KE_PERANGKAT URB_FUNGSI_ATUR_DESCRIPTOR_KE_ENDPOINT URB_FUNCTION_SET_DESCRIPTOR_TO_INTERFACE |
| SET_FEATURE: Aktifkan pengaturan fitur tertentu di perangkat, konfigurasi, antarmuka, dan titik akhirnya. Lihat bagian 9.4.9 dalam spesifikasi USB. |
|
|
_URB_CONTROL_FEATURE_REQUEST (UsbBuildFeatureRequest) URB_FUNGSI_SET_FITUR_KE_PERANGKAT Fungsi URB_SET_FEATURE_KE_ANTARMUKA Fungsi_URB_SET_FEATURE_KE_ENDPOINT Fungsi_URB_Set_Fitur_Ke_Lainnya |
| SET_INTERFACE: Mengubah pengaturan alternatif dalam antarmuka. Lihat bagian 9.4.9 dalam spesifikasi USB. Untuk informasi selengkapnya, lihat Cara memilih pengaturan alternatif di antarmuka USB. |
WdfUsbTargetDeviceSelectConfig
|
|
_URB_SELECT_INTERFACE (USBD_SelectInterfaceUrbAllocateAndBuild) Fungsi URB Memilih Antarmuka |
| SYNC_FRAME: Mengatur dan mendapatkan nomor bingkai sinkronisasi dari titik akhir. Lihat bagian 9.4.10 dalam spesifikasi USB. | Permintaan ini ditangani oleh tumpukan driver USB; driver klien tidak dapat melakukan operasi ini. | Permintaan ini ditangani oleh tumpukan driver USB; driver klien tidak dapat melakukan operasi ini. | Permintaan ini ditangani oleh tumpukan driver USB; driver klien tidak dapat melakukan operasi ini. |
| Untuk permintaan yang spesifik untuk kelas perangkat dan perintah vendor. |
|
|
_URB_CONTROL_VENDOR_OR_CLASS_REQUEST (UsbBuildVendorRequest) URB_FUNCTION_VENDOR_DEVICE (fungsi perangkat vendor URB) URB_FUNCTION_VENDOR_INTERFACE URB_FUNCTION_VENDOR_ENDPOINT FUNGSI_VENDOR_URB_LAINNYA URB_FUNCTION_CLASS_DEVICE Antarmuka_Kelas_Fungsi_URB URB_FUNCTION_CLASS_ENDPOINT KELAS_FUNGSI_URB_LAINNYA |
Cara mengirim transfer kontrol untuk perintah vendor - KMDF
Prosedur ini menunjukkan bagaimana driver klien dapat mengirim transfer kontrol. Dalam contoh ini, driver klien mengirim perintah vendor yang mengambil versi firmware dari perangkat.
Nyatakan konstanta untuk perintah vendor. Pelajari spesifikasi perangkat keras dan tentukan perintah vendor yang ingin Anda gunakan.
Deklarasikan struktur WDF_MEMORY_DESCRIPTOR dan inisialisasi dengan memanggil makro WDF_MEMORY_DESCRIPTOR_INIT_BUFFER . Struktur ini akan menerima respons dari perangkat setelah driver USB menyelesaikan permintaan.
Bergantung pada apakah Anda mengirim permintaan secara sinkron atau asinkron, tentukan opsi kirim Anda:
Jika Anda mengirim permintaan secara sinkron dengan memanggil WdfUsbTargetDeviceSendControlTransferSynchronously, tentukan nilai batas waktu. Nilai itu penting karena tanpa batas waktu, utas dapat terblokir untuk waktu yang tidak terbatas.
Untuk ini, deklarasikan struktur WDF_REQUEST_SEND_OPTIONS dan inisialisasi dengan memanggil makro WDF_REQUEST_SEND_OPTIONS_INIT . Tentukan opsi sebagai WDF_REQUEST_SEND_OPTION_TIMEOUT.
Selanjutnya, atur nilai batas waktu dengan memanggil makro WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT .
Jika Anda mengirim permintaan secara asinkron, terapkan rutinitas penyelesaian. Bebaskan semua sumber daya yang dialokasikan dalam rutinitas penyelesaian.
Deklarasikan struktur WDF_USB_CONTROL_SETUP_PACKET untuk berisi token penyiapan dan memformat struktur. Untuk melakukannya, panggil makro WDF_USB_CONTROL_SETUP_PACKET_INIT_VENDOR untuk memformat paket penyiapan. Dalam panggilan tentukan, arah permintaan, penerima, opsi permintaan terkirim (diinisialisasi di langkah3), dan konstanta untuk perintah vendor.
Kirim permintaan dengan memanggil WdfUsbTargetDeviceSendControlTransferSynchronously atau WdfUsbTargetDeviceFormatRequestForControlTransfer.
Periksa nilai NTSTATUS yang dikembalikan oleh kerangka kerja dan periksa nilai yang diterima.
Contoh kode ini mengirim permintaan transfer kontrol ke perangkat USB untuk mengambil versi firmware-nya. Permintaan dikirim secara sinkron dan driver klien menentukan nilai batas waktu relatif 5 detik (dalam unit 100-nanodetik). Driver menyimpan respons yang diterima dalam konteks perangkat yang ditentukan driver.
enum {
USBFX2_GET_FIRMWARE_VERSION = 0x1,
....
} USBFX2_VENDOR_COMMANDS;
#define WDF_TIMEOUT_TO_SEC ((LONGLONG) 1 * 10 * 1000 * 1000) // defined in wdfcore.h
const __declspec(selectany) LONGLONG
DEFAULT_CONTROL_TRANSFER_TIMEOUT = 5 * -1 * WDF_TIMEOUT_TO_SEC;
typedef struct _DEVICE_CONTEXT
{
...
union {
USHORT VersionAsUshort;
struct {
BYTE Minor;
BYTE Major;
} Version;
} Firmware; // Firmware version.
} DEVICE_CONTEXT, *PDEVICE_CONTEXT;
__drv_requiresIRQL(PASSIVE_LEVEL)
VOID GetFirmwareVersion(
__in PDEVICE_CONTEXT DeviceContext
)
{
NTSTATUS status;
WDF_USB_CONTROL_SETUP_PACKET controlSetupPacket;
WDF_REQUEST_SEND_OPTIONS sendOptions;
USHORT firmwareVersion;
WDF_MEMORY_DESCRIPTOR memoryDescriptor;
PAGED_CODE();
firmwareVersion = 0;
WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&memoryDescriptor, (PVOID) &firmwareVersion, sizeof(firmwareVersion));
WDF_REQUEST_SEND_OPTIONS_INIT(
&sendOptions,
WDF_REQUEST_SEND_OPTION_TIMEOUT
);
WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(
&sendOptions,
DEFAULT_CONTROL_TRANSFER_TIMEOUT
);
WDF_USB_CONTROL_SETUP_PACKET_INIT_VENDOR(&controlSetupPacket,
BmRequestDeviceToHost, // Direction of the request
BmRequestToDevice, // Recipient
USBFX2_GET_FIRMWARE_VERSION, // Vendor command
0, // Value
0); // Index
status = WdfUsbTargetDeviceSendControlTransferSynchronously(
DeviceContext->UsbDevice,
WDF_NO_HANDLE, // Optional WDFREQUEST
&sendOptions,
&controlSetupPacket,
&memoryDescriptor, // MemoryDescriptor
NULL); // BytesTransferred
if (!NT_SUCCESS(status))
{
KdPrint(("Device %d: Failed to get device firmware version 0x%x\n", DeviceContext->DeviceNumber, status));
TraceEvents(DeviceContext->DebugLog,
TRACE_LEVEL_ERROR,
DBG_RUN,
"Device %d: Failed to get device firmware version 0x%x\n",
DeviceContext->DeviceNumber,
status);
}
else
{
DeviceContext->Firmware.VersionAsUshort = firmwareVersion;
TraceEvents(DeviceContext->DebugLog,
TRACE_LEVEL_INFORMATION,
DBG_RUN,
"Device %d: Get device firmware version : 0x%x\n",
DeviceContext->DeviceNumber,
firmwareVersion);
}
return;
}
Cara mengirim transfer kontrol untuk GET_STATUS - UMDF
Prosedur ini menunjukkan bagaimana driver klien dapat mengirim transfer kontrol untuk perintah GET_STATUS. Penerima permintaan adalah perangkat dan permintaan mendapatkan informasi dalam bit D1-D0. Untuk informasi selengkapnya, lihat Gambar 9-4 dalam spesifikasi USB.
Sertakan file header Usb_hw.h yang tersedia dengan Contoh Driver UMDF untuk OSR USB Fx2 Learning Kit.
Deklarasikan struktur WINUSB_CONTROL_SETUP_PACKET.
Inisialisasi paket penyiapan dengan memanggil makro pembantu, WINUSB_CONTROL_SETUP_PACKET_INIT_GET_STATUS.
Tentukan BmRequestToDevice sebagai penerima.
Tentukan 0 dalam nilai Indeks .
Panggil metode pembantu SendControlTransferSynchronously untuk mengirim permintaan secara sinkron.
Metode pembantu membangun permintaan dengan mengaitkan paket penyiapan yang diinisialisasi dengan objek permintaan kerangka kerja dan buffer transfer dengan memanggil metode IWDFUsbTargetDevice::FormatRequestForControlTransfer . Metode pembantu kemudian mengirim permintaan dengan memanggil metode IWDFIoRequest::Send . Setelah metode kembali, periksa nilai yang dikembalikan.
Untuk menentukan apakah status menunjukkan dipasok daya sendiri atau bangun dari jarak jauh, gunakan nilai-nilai ini yang ditentukan dalam enumerasi WINUSB_DEVICE_TRAITS:
Contoh kode ini mengirimkan permintaan transfer kontrol untuk mendapatkan status perangkat. Contoh mengirim permintaan secara sinkron dengan memanggil metode pembantu bernama SendControlTransferSynchronously.
HRESULT
CDevice::GetDeviceStatus ()
{
HRESULT hr = S_OK;
USHORT deviceStatus;
ULONG bytesTransferred;
TraceEvents(TRACE_LEVEL_INFORMATION,
DRIVER_ALL_INFO,
"%!FUNC!: entry");
// Setup the control packet.
WINUSB_CONTROL_SETUP_PACKET setupPacket;
WINUSB_CONTROL_SETUP_PACKET_INIT_GET_STATUS(
&setupPacket,
BmRequestToDevice,
0);
hr = SendControlTransferSynchronously(
&(setupPacket.WinUsb),
& deviceStatus,
sizeof(USHORT),
&bytesReturned
);
if (SUCCEEDED(hr))
{
if (deviceStatus & USB_GETSTATUS_SELF_POWERED)
{
m_Self_Powered = true;
}
if (deviceStatus & USB_GETSTATUS_REMOTE_WAKEUP_ENABLED)
{
m_remote_wake-enabled = true;
}
}
return hr;
}
Contoh kode berikut menunjukkan implementasi metode pembantu bernama SendControlTransferSynchronously. Metode ini mengirimkan permintaan secara sinkron.
HRESULT
CDevice::SendControlTransferSynchronously(
_In_ PWINUSB_SETUP_PACKET SetupPacket,
_Inout_ PBYTE Buffer,
_In_ ULONG BufferLength,
_Out_ PULONG LengthTransferred
)
{
HRESULT hr = S_OK;
IWDFIoRequest *pWdfRequest = NULL;
IWDFDriver * FxDriver = NULL;
IWDFMemory * FxMemory = NULL;
IWDFRequestCompletionParams * FxComplParams = NULL;
IWDFUsbRequestCompletionParams * FxUsbComplParams = NULL;
*LengthTransferred = 0;
hr = m_FxDevice->CreateRequest( NULL, //pCallbackInterface
NULL, //pParentObject
&pWdfRequest);
if (SUCCEEDED(hr))
{
m_FxDevice->GetDriver(&FxDriver);
hr = FxDriver->CreatePreallocatedWdfMemory( Buffer,
BufferLength,
NULL, //pCallbackInterface
pWdfRequest, //pParetObject
&FxMemory );
}
if (SUCCEEDED(hr))
{
hr = m_pIUsbTargetDevice->FormatRequestForControlTransfer( pWdfRequest,
SetupPacket,
FxMemory,
NULL); //TransferOffset
}
if (SUCCEEDED(hr))
{
hr = pWdfRequest->Send( m_pIUsbTargetDevice,
WDF_REQUEST_SEND_OPTION_SYNCHRONOUS,
0); //Timeout
}
if (SUCCEEDED(hr))
{
pWdfRequest->GetCompletionParams(&FxComplParams);
hr = FxComplParams->GetCompletionStatus();
}
if (SUCCEEDED(hr))
{
HRESULT hrQI = FxComplParams->QueryInterface(IID_PPV_ARGS(&FxUsbComplParams));
WUDF_TEST_DRIVER_ASSERT(SUCCEEDED(hrQI));
WUDF_TEST_DRIVER_ASSERT( WdfUsbRequestTypeDeviceControlTransfer ==
FxUsbComplParams->GetCompletedUsbRequestType() );
FxUsbComplParams->GetDeviceControlTransferParameters( NULL,
LengthTransferred,
NULL,
NULL );
}
SAFE_RELEASE(FxUsbComplParams);
SAFE_RELEASE(FxComplParams);
SAFE_RELEASE(FxMemory);
pWdfRequest->DeleteWdfObject();
SAFE_RELEASE(pWdfRequest);
SAFE_RELEASE(FxDriver);
return hr;
}
Jika Anda menggunakan Winusb.sys sebagai driver fungsi untuk perangkat Anda, Anda dapat mengirim transfer kontrol dari aplikasi. Untuk memformat paket penyiapan di WinUSB, gunakan makro dan struktur pembantu UMDF, yang dijelaskan dalam tabel dalam artikel ini. Untuk mengirim permintaan, panggil fungsi WinUsb_ControlTransfer .