Menggunakan Antarmuka Driver-Defined
Driver dapat menentukan antarmuka khusus perangkat yang dapat diakses driver lain. Antarmuka yang ditentukan driver ini dapat terdiri dari serangkaian rutinitas yang dapat dipanggil, sekumpulan struktur data, atau keduanya. Driver biasanya menyediakan pointer untuk rutinitas dan struktur ini dalam struktur antarmuka yang ditentukan driver, yang disediakan driver untuk driver lain.
Misalnya, driver bus mungkin menyediakan satu atau beberapa rutinitas yang dapat dipanggil driver tingkat yang lebih tinggi untuk mendapatkan informasi tentang perangkat anak, jika informasi tersebut tidak tersedia dalam daftar sumber daya perangkat anak.
Untuk contoh sekumpulan antarmuka yang ditentukan driver yang didokumentasikan dalam WDK, lihat Rutinitas USB. Selain itu, lihat versi berbasis kerangka kerja dari sampel pemangas roti.
Membuat Antarmuka
Setiap antarmuka yang ditentukan driver ditentukan oleh:
A GUID
Nomor versi
Struktur antarmuka yang ditentukan driver
Rutinitas referensi dan dereferensi
Untuk membuat antarmuka dan membuatnya tersedia untuk driver lain, driver berbasis kerangka kerja dapat menggunakan langkah-langkah berikut:
Tentukan struktur antarmuka.
Anggota pertama dari struktur yang ditentukan driver ini harus merupakan struktur header INTERFACE . Anggota tambahan mungkin menyertakan data antarmuka dan pointer ke struktur atau rutinitas tambahan yang dapat dipanggil driver lain.
Driver Anda harus menyediakan struktur WDF_QUERY_INTERFACE_CONFIG , yang menjelaskan antarmuka yang telah Anda tentukan.
Catatan
Saat menggunakan WDF_QUERY_INTERFACE_CONFIG, WDF tidak mendukung beberapa versi antarmuka tunggal yang menggunakan GUID antarmuka yang sama.
Akibatnya, saat memperkenalkan versi baru antarmuka yang ada, sebaiknya buat GUID baru alih-alih merevisi bidang Ukuran atau Versi dari struktur ANTARMUKA .
Jika driver Anda menggunakan kembali GUID antarmuka yang sama dengan bidang Ukuran atau Versi yang dimodifikasi, driver tidak boleh menyediakan WDF_QUERY_INTERFACE_CONFIG dan sebaliknya harus menyediakan rutinitas panggilan balik EvtDeviceWdmIrpPreprocess untuk IRP_MN_QUERY_INTERFACE.
Panggil WdfDeviceAddQueryInterface.
Metode WdfDeviceAddQueryInterface melakukan hal berikut:
- Menyimpan informasi tentang antarmuka, seperti GUID, nomor versi, dan ukuran strukturnya, sehingga kerangka kerja dapat mengenali permintaan driver lain untuk antarmuka.
- Mendaftarkan fungsi panggilan balik peristiwa EvtDeviceProcessQueryInterfaceRequest opsional, yang dipanggil kerangka kerja ketika driver lain meminta antarmuka.
Setiap instans antarmuka yang ditentukan driver dikaitkan dengan perangkat individual, sehingga driver biasanya memanggil fungsi panggilan balik WdfDeviceAddQueryInterface dari dalam fungsi panggilan balik EvtDriverDeviceAdd atau EvtChildListCreateDevice .
Mengakses Antarmuka
Jika driver Anda telah menentukan antarmuka, driver berbasis kerangka kerja lain dapat meminta akses ke antarmuka dengan memanggil WdfFdoQueryForInterface dan meneruskan GUID, nomor versi, penunjuk ke struktur, dan ukuran struktur. Kerangka kerja membuat permintaan I/O dan mengirimkannya ke bagian atas tumpukan driver.
Driver biasanya memanggil WdfFdoQueryForInterface dari dalam fungsi panggilan balik EvtDriverDeviceAdd . Atau, jika driver harus merilis antarmuka ketika perangkat tidak dalam keadaan kerjanya, driver dapat memanggil WdffdoQueryForInterface dari dalam fungsi panggilan balik EvtDevicePrepareHardware dan memanggil rutinitas dereferensi antarmuka dari dalam fungsi panggilan balik EvtDeviceReleaseHardware .
Jika driver A meminta driver B untuk antarmuka yang telah ditentukan driver B, kerangka kerja menangani permintaan driver B. Kerangka kerja memverifikasi bahwa GUID dan versi mewakili antarmuka yang didukung, dan bahwa ukuran struktur driver A yang disediakan cukup besar untuk menahan antarmuka.
Ketika driver memanggil WdfFdoQueryForInterface, permintaan I/O yang dibuat kerangka kerja berjalan sampai ke bagian bawah tumpukan driver. Jika tumpukan driver sederhana terdiri dari tiga driver - A, B, dan C - dan jika driver A meminta antarmuka, driver B dan driver C dapat mendukung antarmuka. Misalnya, driver B mungkin mengisi struktur antarmuka driver A sebelum meneruskan permintaan ke driver C. Driver C dapat menyediakan fungsi panggilan balik EvtDeviceProcessQueryInterfaceRequest yang memeriksa konten struktur antarmuka dan mungkin memodifikasinya.
Jika driver A perlu mengakses antarmuka driver B, dan driver B adalah target I/O jarak jauh (yaitu, driver yang berada di tumpukan driver yang berbeda), driver A harus memanggil WdfIoTargetQueryForInterface alih-alih WdfFdoQueryForInterface.
Menggunakan komunikasi One-Way atau Two-Way
Anda dapat menentukan antarmuka yang menyediakan komunikasi satu arah, atau antarmuka yang menyediakan komunikasi dua arah. Untuk menentukan komunikasi dua arah, driver Anda menetapkan anggota ImportInterface dari struktur WDF_QUERY_INTERFACE_CONFIG ke TRUE.
Jika antarmuka menyediakan komunikasi satu arah, dan jika driver A meminta antarmuka driver B, data antarmuka hanya mengalir dari driver B ke driver A. Ketika kerangka kerja menerima permintaan driver A untuk antarmuka yang mendukung komunikasi satu arah, kerangka kerja menyalin nilai antarmuka yang ditentukan driver ke dalam struktur antarmuka driver A. Kemudian memanggil fungsi panggilan balik EvtDeviceProcessQueryInterfaceRequest driver B, jika ada, sehingga dapat memeriksa dan mungkin memodifikasi nilai antarmuka.
Jika antarmuka menyediakan komunikasi dua arah, struktur antarmuka berisi beberapa anggota yang diisi driver A sebelum mengirim permintaan ke driver B. Driver B dapat membaca nilai parameter yang disediakan driver A dan membuat pilihan, berdasarkan nilai-nilai tersebut, tentang informasi mana yang akan diberikan kepada driver A. Ketika kerangka kerja menerima permintaan driver A untuk antarmuka yang mendukung komunikasi dua arah, kerangka kerja memanggil fungsi panggilan balik driver B EvtDeviceProcessQueryInterfaceRequest sehingga dapat memeriksa nilai yang diterima dan menyediakan nilai output. Untuk komunikasi dua arah, fungsi panggilan balik diperlukan karena kerangka kerja tidak menyalin nilai antarmuka apa pun ke struktur antarmuka driver A.
Mempertahankan Jumlah Referensi
Setiap antarmuka harus menyertakan fungsi referensi dan fungsi dereferensi, yang menaikkan dan mengurangi jumlah referensi untuk antarmuka. Driver yang menentukan antarmuka menentukan alamat fungsi-fungsi ini dalam struktur INTERFACE-nya .
Ketika driver A meminta antarmuka driver B, kerangka kerja memanggil fungsi referensi antarmuka sebelum membuat antarmuka tersedia untuk driver A. Ketika driver A telah selesai menggunakan antarmuka , itu harus memanggil fungsi dereferensi antarmuka.
Fungsi referensi dan dereferensi untuk sebagian besar antarmuka dapat menjadi fungsi tanpa operasi yang tidak melakukan apa pun. Kerangka kerja menyediakan fungsi jumlah referensi no-op, WdfDeviceInterfaceReferenceNoOp dan WdfDeviceInterfaceDereferenceNoOp, yang dapat digunakan sebagian besar driver.
Satu-satunya waktu driver harus melacak jumlah referensi antarmuka, dan memberikan fungsi referensi dan dereferensi nyata, adalah ketika driver A meminta antarmuka dari target I/O jarak jauh (yaitu, driver yang berada di tumpukan driver yang berbeda). Dalam hal ini, driver B (dalam tumpukan yang berbeda) harus menerapkan jumlah referensi sehingga dapat mencegah perangkatnya dihapus saat driver A menggunakan antarmuka driver B.
Jika Anda merancang driver B, yang menentukan antarmuka, Anda harus memutuskan apakah antarmuka driver Anda akan diakses dari tumpukan driver yang berbeda. (Driver B tidak dapat menentukan apakah permintaan antarmukanya berasal dari tumpukan driver lokal atau dari tumpukan jarak jauh.) Jika driver Anda akan mendukung permintaan antarmuka dari tumpukan jarak jauh, driver harus menerapkan jumlah referensi.
Jika Anda merancang driver A, yang mengakses antarmuka pada target I/O jarak jauh, driver harus menyediakan fungsi panggilan balik EvtIoTargetQueryRemove yang merilis antarmuka saat perangkat driver B akan dihapus, fungsi panggilan balik EvtIoTargetRemoveComplete yang merilis antarmuka saat perangkat driver B dihapus secara mendadak, dan EvtIoTargetRemoveCanceled fungsi panggilan balik yang memperoleh kembali antarmuka jika upaya untuk menghapus perangkat dibatalkan.