Membuat perangkat untuk WebUSB

Buat perangkat untuk memanfaatkan WebUSB API sepenuhnya.

Reilly Grant
Reilly Grant

Artikel ini menjelaskan cara membuat perangkat untuk memanfaatkan sepenuhnya WebUSB API. Untuk pengantar singkat tentang API itu sendiri, lihat Mengakses Perangkat USB di Web.

Latar belakang

Universal Serial Bus (USB) telah menjadi antarmuka fisik yang paling umum untuk menghubungkan periferal ke perangkat komputasi desktop dan seluler. Selain menentukan karakteristik listrik bus dan model umum untuk berkomunikasi dengan perangkat, spesifikasi USB menyertakan serangkaian spesifikasi class perangkat. Ini adalah model umum untuk kelas perangkat tertentu seperti penyimpanan, audio, video, jaringan, dll. yang dapat diterapkan oleh produsen perangkat. Keuntungan dari spesifikasi class perangkat ini adalah vendor sistem operasi dapat mengimplementasikan satu driver berdasarkan spesifikasi class ("driver class") dan perangkat apa pun yang mengimplementasikan class tersebut akan didukung. Ini adalah peningkatan yang luar biasa dari setiap produsen yang perlu menulis driver perangkat mereka sendiri.

Namun, beberapa perangkat tidak sesuai dengan salah satu kelas perangkat standar tersebut. Sebagai gantinya, produsen dapat memilih untuk memberi label perangkatnya sebagai menerapkan class khusus vendor. Dalam hal ini, sistem operasi memilih driver perangkat yang akan dimuat berdasarkan informasi yang diberikan dalam paket driver vendor, biasanya sekumpulan ID vendor dan produk yang diketahui menerapkan protokol khusus vendor tertentu.

Fitur USB lain adalah perangkat dapat menyediakan beberapa antarmuka ke host yang terhubung dengannya. Setiap antarmuka dapat mengimplementasikan class standar atau khusus vendor. Saat sistem operasi memilih driver yang tepat untuk menangani perangkat, setiap antarmuka dapat diklaim oleh driver yang berbeda. Misalnya, webcam USB biasanya menyediakan dua antarmuka, satu mengimplementasikan class video USB (untuk kamera) dan satu lagi yang mengimplementasikan class audio USB (untuk mikrofon). Sistem operasi tidak memuat satu "driver webcam" tunggal tetapi memuat driver class video dan audio independen yang bertanggung jawab atas fungsi perangkat yang terpisah. Komposisi class antarmuka ini memberikan fleksibilitas yang lebih besar.

Dasar-dasar API

Banyak class USB standar memiliki API web yang sesuai. Misalnya, halaman dapat merekam video dari perangkat class video menggunakan getUserMedia() atau menerima peristiwa input dari perangkat class antarmuka manusia (HID) dengan memproses KeyboardEvents atau PointerEvents, atau dengan menggunakan Gamepad atau WebHID API. Sama seperti tidak semua perangkat menerapkan definisi class terstandardisasi, tidak semua perangkat mengimplementasikan fitur yang sesuai dengan API platform web yang ada. Jika demikian, WebUSB API dapat mengisi kekurangan tersebut dengan menyediakan cara bagi situs untuk mengklaim antarmuka khusus vendor dan menerapkan dukungan untuk antarmuka tersebut langsung dari dalam halaman mereka.

Persyaratan khusus agar perangkat dapat diakses melalui WebUSB sedikit berbeda dari platform ke platform karena perbedaan cara sistem operasi mengelola perangkat USB. Namun, persyaratan dasarnya adalah perangkat tidak boleh sudah memiliki driver yang mengklaim antarmuka yang ingin dikontrol halaman. Driver ini dapat berupa driver class umum yang disediakan oleh vendor OS atau driver perangkat yang disediakan oleh vendor. Karena perangkat USB dapat menyediakan beberapa antarmuka, yang masing-masing mungkin memiliki driver sendiri, perangkat dapat dibuat dengan beberapa antarmuka yang diklaim oleh driver dan antarmuka lainnya dibiarkan dapat diakses oleh browser.

Misalnya, keyboard USB kelas atas dapat menyediakan antarmuka class HID yang akan diklaim oleh subsistem input sistem operasi dan antarmuka khusus vendor yang tetap tersedia bagi WebUSB untuk digunakan oleh alat konfigurasi. Alat ini dapat ditayangkan di situs produsen yang memungkinkan pengguna mengubah aspek perilaku perangkat seperti tombol makro dan efek pencahayaan tanpa menginstal software khusus platform apa pun. Deskriptor konfigurasi perangkat tersebut akan terlihat seperti ini:

Nilai Kolom Deskripsi
Deskriptor konfigurasi
0x09 bLength Ukuran deskriptor ini
0x02 bDescriptorType Deskriptor konfigurasi
0x0039 wTotalLength Panjang total rangkaian deskripsi ini
0x02 bNumInterfaces Jumlah antarmuka
0x01 bConfigurationValue Konfigurasi 1
0x00 iConfiguration Nama konfigurasi (tidak ada)
0b1010000 bmAttributes Perangkat bertenaga sendiri dengan fitur bangun jarak jauh
0x32 bMaxPower Daya Maksimal dinyatakan dalam kelipatan 2 mA
Deskripsi antarmuka
0x09 bLength Ukuran deskriptor ini
0x04 bDescriptorType Deskripsi antarmuka
0x00 bInterfaceNumber Antarmuka 0
0x00 bAlternateSetting Setelan alternatif 0 (default)
0x01 bNumEndpoints 1 endpoint
0x03 bInterfaceClass Class antarmuka HID
0x01 bInterfaceSubClass Subclass antarmuka booting
0x01 bInterfaceProtocol Keyboard
0x00 iInterface Nama antarmuka (tidak ada)
Deskriptor HID
0x09 bLength Ukuran deskriptor ini
0x21 bDescriptorType Deskriptor HID
0x0101 bcdHID HID versi 1.1
0x00 bCountryCode Negara target hardware
0x01 bNumDescriptors Jumlah deskripsi class HID yang akan diikuti
0x22 bDescriptorType Jenis deskriptor laporan
0x003F wDescriptorLength Panjang total deskriptor laporan
Deskriptor endpoint
0x07 bLength Ukuran deskriptor ini
0x05 bDescriptorType Deskriptor endpoint
0b10000001 bEndpointAddress Endpoint 1 (IN)
0b00000011 bmAttributes Interupsi
0x0008 wMaxPacketSize Paket 8 byte
0x0A bInterval Interval 10 md
Deskripsi antarmuka
0x09 bLength Ukuran deskriptor ini
0x04 bDescriptorType Deskripsi antarmuka
0x01 bInterfaceNumber Antarmuka 1
0x00 bAlternateSetting Setelan alternatif 0 (default)
0x02 bNumEndpoints 2 endpoint
0xFF bInterfaceClass Class antarmuka khusus vendor
0x00 bInterfaceSubClass
0x00 bInterfaceProtocol
0x00 iInterface Nama antarmuka (tidak ada)
Deskriptor endpoint
0x07 bLength Ukuran deskriptor ini
0x05 bDescriptorType Deskriptor endpoint
0b10000010 bEndpointAddress Endpoint 1 (IN)
0b00000010 bmAttributes Massal
0x0040 wMaxPacketSize Paket 64 byte
0x00 bInterval T/A untuk endpoint massal
Deskriptor endpoint
0x07 bLength Ukuran deskriptor ini
0x05 bDescriptorType Deskriptor endpoint
0b00000011 bEndpointAddress Endpoint 3 (KELUAR)
0b00000010 bmAttributes Massal
0x0040 wMaxPacketSize Paket 64 byte
0x00 bInterval T/A untuk endpoint massal

Deskripsi konfigurasi terdiri dari beberapa deskripsi yang digabungkan. Masing-masing diawali dengan kolom bLength dan bDescriptorType sehingga dapat diidentifikasi. Antarmuka pertama adalah antarmuka HID dengan deskriptor HID terkait dan endpoint tunggal yang digunakan untuk mengirimkan peristiwa input ke sistem operasi. Antarmuka kedua adalah antarmuka khusus vendor dengan dua endpoint yang dapat digunakan untuk mengirim perintah ke perangkat dan menerima respons sebagai balasannya.

Deskriptor WebUSB

Meskipun WebUSB dapat berfungsi dengan banyak perangkat tanpa modifikasi firmware, fungsi tambahan diaktifkan dengan menandai perangkat dengan deskriptor tertentu yang menunjukkan dukungan untuk WebUSB. Misalnya, Anda dapat menentukan URL halaman landing tempat browser dapat mengarahkan pengguna saat perangkat Anda dicolokkan.

Screenshot notifikasi WebUSB di Chrome
Notifikasi WebUSB.

Perangkat biner Object Store (BOS) adalah konsep yang diperkenalkan di USB 3.0, tetapi juga telah di-backport ke perangkat USB 2.0 sebagai bagian dari versi 2.1. Deklarasi dukungan untuk WebUSB dimulai dengan menyertakan Deskripsi Kemampuan Platform berikut dalam deskripsi BOS:

Nilai Kolom Deskripsi
Deskriptor Penyimpanan Objek perangkat biner
0x05 bLength Ukuran deskriptor ini
0x0F bDescriptorType Deskriptor Penyimpanan Objek perangkat biner
0x001D wTotalLength Panjang total rangkaian deskripsi ini
0x01 bNumDeviceCaps Jumlah deskriptor kemampuan perangkat di BOS
Deskriptor kemampuan platform WebUSB
0x18 bLength Ukuran deskriptor ini
0x10 bDescriptorType Deskriptor kemampuan perangkat
0x05 bDevCapabilityType Deskripsi kemampuan platform
0x00 bReserved
{0x38, 0xB6, 0x08, 0x34, 0xA9, 0x09, 0xA0, 0x47, 0x8B, 0xFD, 0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65} PlatformCapablityUUID GUID deskripsi kemampuan platform WebUSB dalam format little-endian
0x0100 bcdVersion Deskriptor WebUSB versi 1.0
0x01 bVendorCode Nilai bRequest untuk WebUSB
0x01 iLandingPage URL untuk halaman landing

UUID kemampuan platform mengidentifikasi ini sebagai deskriptor Kemampuan Platform WebUSB, yang memberikan informasi dasar tentang perangkat. Agar browser dapat mengambil informasi lainnya tentang perangkat, browser menggunakan nilai bVendorCode untuk mengeluarkan permintaan tambahan ke perangkat. Satu-satunya permintaan yang saat ini ditentukan adalah GET_URL yang menampilkan deskripsi URL. Deskriptor ini mirip dengan deskriptor string, tetapi didesain untuk mengenkode URL dalam byte paling sedikit. Dekriptor URL untuk "https://google.com" akan terlihat seperti ini:

Nilai Kolom Deskripsi
Deskripsi URL
0x0D bLength Ukuran deskriptor ini
0x03 bDescriptorType Deskripsi URL
0x01 bScheme https://
"google.com" URL Konten URL berenkode UTF-8

Saat perangkat pertama kali dicolokkan, browser akan membaca deskriptor BOS dengan mengeluarkan transfer kontrol GET_DESCRIPTOR standar ini:

bmRequestType bRequest wValue wIndex wLength Data (respons)
0b10000000 0x06 0x0F00 0x0000 * Deskriptor BOS

Permintaan ini biasanya dibuat dua kali, pertama kalinya dengan wLength yang cukup besar sehingga host mengetahui nilai kolom wTotalLength tanpa melakukan transfer besar, lalu dibuat lagi saat panjang deskriptor lengkap dapat diketahui.

Jika deskripsi Kemampuan Platform WebUSB memiliki kolom iLandingPage yang ditetapkan ke nilai bukan nol, browser akan melakukan permintaan GET_URL khusus WebUSB dengan mengeluarkan transfer kontrol dengan bRequest yang disetel ke nilai bVendorCode dari deskripsi kemampuan platform dan wValue ditetapkan ke nilai iLandingPage. Kode permintaan untuk GET_URL (0x02) ada di wIndex:

bmRequestType bRequest wValue wIndex wLength Data (respons)
0b11000000 0x01 0x0001 0x0002 * Deskripsi URL

Sekali lagi, permintaan ini dapat dikeluarkan dua kali untuk menyelidiki terlebih dahulu panjang deskripsi yang dibaca.

Pertimbangan khusus platform

Meskipun WebUSB API berupaya memberikan antarmuka yang konsisten untuk mengakses perangkat USB, developer harus tetap mengetahui persyaratan yang diberlakukan pada aplikasi seperti persyaratan browser web untuk mengakses perangkat.

macOS

Tidak ada hal khusus yang diperlukan untuk macOS. Situs yang menggunakan WebUSB dapat terhubung ke perangkat dan mengklaim antarmuka apa pun yang tidak diklaim oleh driver kernel atau aplikasi lain.

Linux

Linux mirip dengan macOS, tetapi secara default sebagian besar distribusi tidak menyiapkan akun pengguna dengan izin untuk membuka perangkat USB. {i>Daemon<i} sistem yang disebut {i>udev<i} bertanggung jawab untuk menetapkan pengguna dan grup yang diizinkan untuk mengakses perangkat. Aturan seperti ini akan menetapkan kepemilikan perangkat yang cocok dengan ID vendor dan ID produk tertentu ke grup plugdev yang merupakan grup umum bagi pengguna yang memiliki akses ke periferal:

SUBSYSTEM=="usb", ATTR{idVendor}=="XXXX", ATTR{idProduct}=="XXXX", GROUP="plugdev"

Ganti XXXX dengan vendor heksadesimal dan ID produk untuk perangkat Anda, misalnya, ATTR{idVendor}=="18d1", ATTR{idProduct}=="4e11" akan cocok dengan ponsel Nexus One. Dukungan ini harus ditulis tanpa awalan "0x" yang biasa dan semua huruf kecil agar dapat dikenali dengan benar. Untuk menemukan ID perangkat Anda, jalankan alat command line lsusb.

Aturan ini harus ditempatkan pada file di direktori /etc/udev/rules.d dan akan diterapkan segera setelah perangkat dicolokkan. Tidak perlu memulai ulang udev.

Android

Platform Android didasarkan pada Linux, tetapi tidak memerlukan modifikasi apa pun pada konfigurasi sistem. Secara default, perangkat apa pun yang tidak memiliki driver yang terpasang ke dalam sistem operasi akan tersedia untuk browser. Namun, developer harus mengetahui bahwa pengguna akan mengalami langkah tambahan saat terhubung ke perangkat. Setelah pengguna memilih perangkat sebagai respons terhadap panggilan ke requestDevice(), Android akan menampilkan perintah yang menanyakan apakah akan mengizinkan Chrome untuk mengaksesnya. Permintaan ini juga akan muncul kembali jika pengguna kembali ke situs yang sudah memiliki izin untuk terhubung ke perangkat dan situs tersebut memanggil open().

Selain itu, lebih banyak perangkat yang dapat diakses di Android dibandingkan di desktop, Linux karena lebih sedikit driver yang disertakan secara default. Kelalaian yang perlu diperhatikan, misalnya, adalah class USB CDC-ACM yang biasanya diimplementasikan oleh adaptor USB-ke-serial karena tidak ada API di Android SDK untuk berkomunikasi dengan perangkat serial.

ChromeOS

ChromeOS juga berbasis pada Linux dan juga tidak memerlukan modifikasi pada konfigurasi sistem. Layanan permissions_broker mengontrol akses ke perangkat USB dan akan mengizinkan browser untuk mengaksesnya selama ada setidaknya satu antarmuka yang belum diklaim.

Windows

Model {i>driver<i} Windows memperkenalkan persyaratan tambahan. Berbeda dengan platform di atas, kemampuan untuk membuka perangkat USB dari aplikasi pengguna bukanlah default, meskipun tidak ada driver yang dimuat. Sebagai gantinya, terdapat driver khusus, WinUSB, yang perlu dimuat guna menyediakan antarmuka yang digunakan aplikasi untuk mengakses perangkat. Hal ini dapat dilakukan dengan file informasi driver kustom (INF) yang diinstal pada sistem atau dengan memodifikasi firmware perangkat untuk menyediakan Deskripsi Kompatibilitas Microsoft OS selama enumerasi.

File Informasi Pengemudi (INF)

File informasi driver memberi tahu Windows apa yang harus dilakukan saat menemukan perangkat untuk pertama kalinya. Karena sistem pengguna sudah menyertakan driver WinUSB, semua yang diperlukan adalah agar file INF dapat mengaitkan vendor dan ID produk Anda dengan aturan penginstalan baru ini. File di bawah ini adalah contoh dasarnya. Simpan ke file dengan ekstensi .inf, ubah bagian yang ditandai dengan "X", lalu klik kanan dan pilih "Instal" dari menu konteks.

[Version]
Signature   = "$Windows NT$"
Class       = USBDevice
ClassGUID   = {88BAE032-5A81-49f0-BC3D-A4FF138216D6}
Provider    = %ManufacturerName%
CatalogFile = WinUSBInstallation.cat
DriverVer   = 09/04/2012,13.54.20.543

; ========== Manufacturer/Models sections ===========

[Manufacturer]
%ManufacturerName% = Standard,NTx86,NTia64,NTamd64

[Standard.NTx86]
%USB\MyCustomDevice.DeviceDesc% = USB_Install,USB\VID_XXXX&PID_XXXX

[Standard.NTia64]
%USB\MyCustomDevice.DeviceDesc% = USB_Install,USB\VID_XXXX&PID_XXXX

[Standard.NTamd64]
%USB\MyCustomDevice.DeviceDesc% = USB_Install,USB\VID_XXXX&PID_XXXX

; ========== Class definition ===========

[ClassInstall32]
AddReg = ClassInstall_AddReg

[ClassInstall_AddReg]
HKR,,,,%ClassName%
HKR,,NoInstallClass,,1
HKR,,IconPath,%REG_MULTI_SZ%,"%systemroot%\system32\setupapi.dll,-20"
HKR,,LowerLogoVersion,,5.2

; =================== Installation ===================

[USB_Install]
Include = winusb.inf
Needs   = WINUSB.NT

[USB_Install.Services]
Include = winusb.inf
Needs   = WINUSB.NT.Services

[USB_Install.HW]
AddReg = Dev_AddReg

[Dev_AddReg]
HKR,,DeviceInterfaceGUIDs,0x10000,"{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}"

; =================== Strings ===================

[Strings]
ManufacturerName              = "Your Company Name Here"
ClassName                     = "Your Company Devices"
USB\MyCustomDevice.DeviceDesc = "Your Device Name Here"

Bagian [Dev_AddReg] mengonfigurasi kumpulan DeviceInterfaceGUID untuk perangkat. Setiap antarmuka perangkat harus memiliki GUID agar aplikasi dapat menemukan dan menghubungkannya melalui Windows API. Gunakan cmdlet PowerShell New-Guid atau alat online untuk membuat GUID acak.

Untuk tujuan pengembangan, alat Zadig menyediakan antarmuka yang mudah untuk mengganti driver yang dimuat untuk antarmuka USB dengan driver WinUSB.

Deskriptor kompatibilitas Microsoft OS

Pendekatan file INF di atas rumit karena memerlukan konfigurasi setiap komputer pengguna terlebih dahulu. Windows 8.1 dan yang lebih tinggi menawarkan alternatif melalui penggunaan deskriptor USB kustom. Deskriptor ini memberikan informasi ke sistem operasi Windows saat perangkat pertama kali dicolokkan yang biasanya akan disertakan dalam file INF.

Setelah Anda menyiapkan deskripsi WebUSB, Anda juga dapat menambahkan deskripsi kompatibilitas OS Microsoft dengan mudah. Pertama-tama, perluas deskriptor BOS dengan deskriptor kemampuan platform tambahan ini. Pastikan untuk memperbarui wTotalLength dan bNumDeviceCaps untuk memperhitungkannya.

Nilai Kolom Deskripsi
Deskriptor kemampuan platform Microsoft OS 2.0
0x1C bLength Ukuran deskriptor ini
0x10 bDescriptorType Deskriptor kemampuan perangkat
0x05 bDevCapabilityType Deskripsi kemampuan platform
0x00 bReserved
{0xDF, 0x60, 0xDD, 0xD8, 0x89, 0x45, 0xC7, 0x4C, 0x9C, 0xD2, 0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F} PlatformCapablityUUID GUID deskripsi kompatibilitas platform Microsoft OS 2.0 dalam format sedikit-endian
0x06030000 dwWindowsVersion Versi Windows minimum yang kompatibel (Windows 8.1)
0x00B2 wMSOSDescriptorSetTotalLength Panjang total kumpulan deskriptor
0x02 bMS_VendorCode Nilai bRequest untuk mengambil deskriptor Microsoft lebih lanjut
0x00 bAltEnumCode Perangkat tidak mendukung enumerasi alternatif

Seperti halnya deskripsi WebUSB, Anda harus memilih nilai bRequest untuk digunakan oleh transfer kontrol yang terkait dengan deskripsi ini. Dalam contoh ini saya memilih 0x02. 0x07, ditempatkan di wIndex, adalah perintah untuk mengambil Set Deskripsi Microsoft OS 2.0 dari perangkat.

bmRequestType bRequest wValue wIndex wLength Data (respons)
0b11000000 0x02 0x0000 0x0007 * Set Deskripsi MS OS 2.0

Perangkat USB dapat memiliki beberapa fungsi sehingga bagian pertama kumpulan deskriptor menjelaskan fungsi mana yang dikaitkan dengan properti berikutnya. Contoh di bawah ini mengonfigurasi antarmuka 1 dari perangkat gabungan. Deskripsi memberi OS dua informasi penting tentang antarmuka ini. Deskripsi ID yang kompatibel memberi tahu Windows bahwa perangkat ini kompatibel dengan driver WinUSB. Fungsi deskriptor properti registry mirip dengan bagian [Dev_AddReg] pada contoh INF di atas, yang menetapkan properti registry untuk menetapkan fungsi ini GUID antarmuka perangkat.

Nilai Kolom Deskripsi
Header set deskriptor Microsoft OS 2.0
0x000A wLength Ukuran deskriptor ini
0x0000 wDescriptorType Deskriptor header set deskriptor
0x06030000 dwWindowsVersion Versi Windows minimum yang kompatibel (Windows 8.1)
0x00B2 wTotalLength Panjang total kumpulan deskriptor
Header subset konfigurasi Microsoft OS 2.0
0x0008 wLength Ukuran deskriptor ini
0x0001 wDescriptorType Deskripsi header subset konfigurasi
0x00 bConfigurationValue Berlaku untuk konfigurasi 1 (diindeks dari 0 meskipun konfigurasi biasanya diindeks dari 1)
0x00 bReserved Harus ditetapkan ke 0
0x00A8 wTotalLength Panjang total subset termasuk header ini
Header subset fungsi Microsoft OS 2.0
0x0008 wLength Ukuran deskriptor ini
0x0002 wDescriptorType Deskriptor header subset fungsi
0x01 bFirstInterface Antarmuka pertama fungsi
0x00 bReserved Harus ditetapkan ke 0
0x00A0 wSubsetLength Panjang total subset termasuk header ini
Deskriptor ID yang kompatibel dengan Microsoft OS 2.0
0x0014 wLength Ukuran deskriptor ini
0x0003 wDescriptorType Deskripsi ID yang kompatibel
"WINUSB\0\0" CompatibileID String ASCII ditambahkan ke 8 byte
"\0\0\0\0\0\0\0\0" SubCompatibleID String ASCII ditambahkan ke 8 byte
Deskriptor properti registry Microsoft OS 2.0
0x0084 wLength Ukuran deskriptor ini
0x0004 wDescriptorType Deskriptor properti registry
0x0007 wPropertyDataType REG_MULTI_SZ
0x002A wPropertyNameLength Panjang nama properti
"DeviceInterfaceGUIDs\0" PropertyName Nama properti dengan terminator null yang dienkode dalam UTF-16LE
0x0050 wPropertyDataLength Panjang nilai properti
"{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}\0\0" PropertyData GUID plus dua penutup null yang dienkode dalam UTF-16LE

Windows hanya akan mengkueri perangkat untuk informasi ini sekali. Jika perangkat tidak merespons dengan deskripsi yang valid, perangkat tidak akan bertanya lagi saat perangkat terhubung lagi. Microsoft telah menyediakan daftar Entri Registry Perangkat USB yang menjelaskan entri registry yang dibuat saat melakukan enumerasi perangkat. Saat menguji, hapus entri yang dibuat untuk perangkat agar memaksa Windows mencoba membaca deskripsi lagi.

Untuk informasi selengkapnya, lihat postingan blog Microsoft tentang cara menggunakan deskriptor ini.

Contoh

Contoh kode yang menerapkan perangkat berbasis WebUSB yang menyertakan deskriptor WebUSB dan deskriptor Microsoft OS dapat ditemukan dalam project berikut: