WebHID API, web sitelerinin alternatif yardımcı klavyelere ve sıra dışı gamepad'lere erişmesine olanak tanır.
Yayınlanma tarihi: 15 Eylül 2020
Alternatif klavyeler veya egzotik oyun kumandaları gibi, sistemlerin cihaz sürücüleri tarafından erişilemeyecek kadar yeni, eski veya nadir olan birçok insan arayüzü cihazı (HID) vardır. WebHID API, cihaza özel mantığı JavaScript'te uygulamanın bir yolunu sağlayarak bu sorunu çözer.
Önerilen kullanım alanları
HID cihaz, insanlardan giriş alır veya insanlara çıkış sağlar. Klavye, işaretleme cihazları (fare, dokunmatik ekran vb.) ve gamepad'ler, cihaz örnekleri arasındadır. HID protokolü, işletim sistemi sürücülerini kullanarak masaüstü bilgisayarlarda bu cihazlara erişmeyi mümkün kılar. Web platformu, bu sürücüleri kullanarak HID cihazlarını destekler.
Yaygın olmayan HID cihazlara erişilememesi, özellikle alternatif yardımcı klavyeler (ör. Elgato Stream Deck, Jabra kulaklıklar, X-keys) ve egzotik gamepad desteği söz konusu olduğunda can sıkıcıdır. Masaüstü için tasarlanan oyun kumandaları, oyun kumandası girişleri (düğmeler, kontrol çubukları, tetikler) ve çıkışları (LED'ler, titreşim) için genellikle HID'yi kullanır.
Maalesef gamepad giriş ve çıkışları iyi bir şekilde standartlaştırılmamıştır ve web tarayıcılar genellikle belirli cihazlar için özel mantık gerektirir. Bu durum sürdürülebilir değildir ve daha eski ve nadir cihazların uzun kuyruğu için yetersiz destek sunulmasına neden olur. Bu durum, tarayıcının belirli cihazların davranışındaki tuhaflıklara bağlı olmasına da neden olur.
Terminoloji
İnsan arayüz cihazı (HID), insanlardan giriş alabilir veya onlara çıkış sunabilir. Kurulum prosedürünü basitleştirmek için tasarlanmış, bir ana makine ile bir cihaz arasında çift yönlü iletişimi sağlayan standart bir HID protokolü vardır.
HID iki temel kavramdan oluşur: raporlar ve rapor tanımlayıcıları. Raporlar, bir cihaz ile bir yazılım istemcisi arasında değiştirilen verilerdir. Rapor tanımlayıcısı, cihazın desteklediği verilerin biçimini ve anlamını açıklar.
Uygulamalar ve HID cihazları, üç rapor türü aracılığıyla ikili verileri değiştirir:
| Rapor türü | Açıklama |
|---|---|
| Giriş raporu | Cihazdan uygulamaya gönderilen veriler (ör. bir düğmeye basılması) |
| Çıkış raporu | Uygulamadan cihaza gönderilen veriler (ör. klavye arka ışığını açma isteği) |
| Özellik raporu | İki yönde de gönderilebilecek veriler. Biçim cihaza özeldir. |
Rapor tanımlayıcısı, cihaz tarafından desteklenen raporların ikili biçimini tanımlar. Yapısı hiyerarşiktir ve raporları üst düzey koleksiyonda ayrı koleksiyonlar olarak gruplandırabilir. Tanımlayıcının biçimi, HID spesifikasyonu tarafından tanımlanır.
HID kullanımı, standartlaştırılmış bir girişi veya çıkışı ifade eden sayısal bir değerdir. Kullanım değerleri, bir cihazın kullanım amacını ve raporlarındaki her alanın amacını tanımlamasına olanak tanır. Örneğin, bir fare düğmesinin sol tarafı için tanımlanır. Kullanımlar, cihazın veya raporun üst düzey kategorisi hakkında bilgi veren kullanım sayfalarında da düzenlenir.
WebHID API'yi kullanma
WebHID API'nin desteklenip desteklenmediğini kontrol etmek için şunu kullanın:
if ("hid" in navigator) {
// The WebHID API is supported.
}
HID bağlantısı açma
WebHID API, web sitesi kullanıcı arayüzünün giriş beklenirken engellenmesini önlemek için tasarımdan itibaren eşzamansızdır. HID verileri herhangi bir zamanda alınabildiğinden ve bu verileri dinlemenin bir yolu gerektiğinden bu önemlidir.
Bir HID bağlantısı açmak için önce bir HIDDevice nesnesine erişin. Bunun için kullanıcıya navigator.hid.requestDevice() işlevini çağırarak bir cihaz seçmesini isteyebilir veya navigator.hid.getDevices() işlevini kullanarak daha önce web sitesine erişim izni verilen cihazların listesini döndüren bir cihaz seçebilirsiniz.
navigator.hid.requestDevice() işlevi, filtreleri tanımlayan zorunlu bir nesne alır. Bunlar, USB tedarikçi tanımlayıcısı (vendorId), USB ürün tanımlayıcısı (productId), kullanım sayfası değeri (usagePage) ve kullanım değeri (usage) ile bağlı cihazları eşleştirmek için kullanılır. Bu değerleri USB ID Repository ve HID kullanım tabloları dokümanından alabilirsiniz.
Bu işlev tarafından döndürülen birden fazla HIDDevice nesnesi, aynı fiziksel cihazdaki birden fazla HID arayüzünü temsil eder.
// Filter on devices with the Nintendo Switch Joy-Con USB Vendor/Product IDs.
const filters = [
{
vendorId: 0x057e, // Nintendo Co., Ltd
productId: 0x2006 // Joy-Con Left
},
{
vendorId: 0x057e, // Nintendo Co., Ltd
productId: 0x2007 // Joy-Con Right
}
];
// Prompt user to select a Joy-Con device.
const [device] = await navigator.hid.requestDevice({ filters });
// Get all devices the user has previously granted the website access to.
const devices = await navigator.hid.getDevices();
Ayrıca, tarayıcı seçiciden bazı cihazları hariç tutmak için exclusionFilters anahtarını da kullanabilirsiniz.navigator.hid.requestDevice()
// Request access to a device with vendor ID 0xABCD. The device must also have
// a collection with usage page Consumer (0x000C) and usage ID Consumer
// Control (0x0001). The device with product ID 0x1234 is malfunctioning.
const [device] = await navigator.hid.requestDevice({
filters: [{ vendorId: 0xabcd, usagePage: 0x000c, usage: 0x0001 }],
exclusionFilters: [{ vendorId: 0xabcd, productId: 0x1234 }],
});
HIDDevice nesnesi, cihaz tanımlama için USB tedarikçi ve ürün tanımlayıcılarını içerir. collections özelliği, cihazın rapor biçimlerinin hiyerarşik bir açıklamasıyla başlatılır.
for (let collection of device.collections) {
// An HID collection includes usage, usage page, reports, and subcollections.
console.log(`Usage: ${collection.usage}`);
console.log(`Usage page: ${collection.usagePage}`);
for (let inputReport of collection.inputReports) {
console.log(`Input report: ${inputReport.reportId}`);
// Loop through inputReport.items
}
for (let outputReport of collection.outputReports) {
console.log(`Output report: ${outputReport.reportId}`);
// Loop through outputReport.items
}
for (let featureReport of collection.featureReports) {
console.log(`Feature report: ${featureReport.reportId}`);
// Loop through featureReport.items
}
// Loop through subcollections with collection.children
}
HIDDevice cihazlar varsayılan olarak "kapalı" durumda iade edilir ve veri gönderilip alınabilmesi için open() numarası aranarak açılması gerekir.
// Wait for the HID connection to open before sending/receiving data.
await device.open();
Giriş raporları alma

HID bağlantısı kurulduktan sonra, cihazdan gelen "inputreport" etkinliklerini dinleyerek gelen giriş raporlarını işleyebilirsiniz. Bu etkinlikler, HID verilerini DataView nesnesi (data), ait olduğu HID cihazı (device) ve giriş raporuyla ilişkili 8 bitlik rapor kimliği (reportId) olarak içerir.
Önceki örnekten devam edersek bu kod, kullanıcının Joy-Con Right cihazında hangi düğmeye bastığını algılamanıza yardımcı olur. Böylece, kodu evde deneyebilirsiniz.
device.addEventListener("inputreport", event => {
const { data, device, reportId } = event;
// Handle only the Joy-Con Right device and a specific report ID.
if (device.productId !== 0x2007 && reportId !== 0x3f) return;
const value = data.getUint8(0);
if (value === 0) return;
const someButtons = { 1: "A", 2: "X", 4: "B", 8: "Y" };
console.log(`User pressed button ${someButtons[value]}.`);
});
CodePen'deki demoya bakın.
Çıkış raporları gönderme
Bir çıkış raporunu HID cihazına göndermek için çıkış raporuyla (reportId) ilişkili 8 bitlik rapor kimliğini ve baytları BufferSource (data) olarak device.sendReport()'a iletin. Döndürülen söz, rapor gönderildikten sonra çözülür. HID cihazı rapor kimlikleri kullanmıyorsa reportId değerini 0 olarak ayarlayın.
Bir sonraki örnek, Joy-Con cihazı için geçerlidir ve çıkış raporlarıyla nasıl titreşim oluşturacağınızı gösterir.
// First, send a command to enable vibration.
// Magical bytes come from https://github.com/mzyy94/joycon-toolweb
const enableVibrationData = [1, 0, 1, 64, 64, 0, 1, 64, 64, 0x48, 0x01];
await device.sendReport(0x01, new Uint8Array(enableVibrationData));
// Then, send a command to make the Joy-Con device rumble.
// Actual bytes are available in the sample.
const rumbleData = [ /* ... */ ];
await device.sendReport(0x10, new Uint8Array(rumbleData));
CodePen'deki demoya bakın.
Özellik raporları gönderme ve alma

Özellik raporları, her iki yönde de aktarılabilen tek HID veri raporu türüdür. HID cihazlarının ve uygulamalarının standartlaştırılmamış HID verilerini değiştirmesine olanak tanır. Giriş ve çıkış raporlarının aksine, özellik raporları uygulama tarafından düzenli olarak alınmaz veya gönderilmez.
Bir özellik raporunu HID cihazına göndermek için özellik raporuyla (reportId) ilişkili 8 bitlik rapor kimliğini ve baytları BufferSource (data) olarak device.sendFeatureReport()'a iletin. Rapor gönderildikten sonra döndürülen söz çözülür. HID cihazı rapor kimlikleri kullanmıyorsa reportId değerini 0 olarak ayarlayın.
Bu örnekte, Apple klavye arka ışığı cihazı isteyip açarak ve yanıp söndürerek özellik raporlarının nasıl kullanılacağı gösterilmektedir.
const waitFor = duration => new Promise(r => setTimeout(r, duration));
// Prompt user to select an Apple Keyboard Backlight device.
const [device] = await navigator.hid.requestDevice({
filters: [{ vendorId: 0x05ac, usage: 0x0f, usagePage: 0xff00 }]
});
// Wait for the HID connection to open.
await device.open();
// Blink!
const reportId = 1;
for (let i = 0; i < 10; i++) {
// Turn off
await device.sendFeatureReport(reportId, Uint32Array.from([0, 0]));
await waitFor(100);
// Turn on
await device.sendFeatureReport(reportId, Uint32Array.from([512, 0]));
await waitFor(100);
}
CodePen'deki demoya bakın.
Bir HID cihazından özellik raporu almak için özellik raporuyla (reportId) ilişkili 8 bitlik rapor kimliğini device.receiveFeatureReport()'ye iletin. Döndürülen söz, özellik raporunun içeriğini içeren bir DataView nesnesiyle çözümlenir. HID cihazı rapor kimliklerini kullanmıyorsa reportId değerini 0 olarak ayarlayın.
// Request feature report.
const dataView = await device.receiveFeatureReport(/* reportId= */ 1);
// Read feature report contents with dataView.getInt8(), getUint8(), etc...
Bağlantı ve bağlantı kesme işlemlerini dinleme
Bir web sitesine HID cihazına erişim izni verildiğinde, "connect" ve "disconnect" etkinliklerini dinleyerek bağlantı ve bağlantı kesme etkinliklerini aktif olarak alabilir.
navigator.hid.addEventListener("connect", event => {
// Automatically open event.device or warn user a device is available.
});
navigator.hid.addEventListener("disconnect", event => {
// Remove |event.device| from the UI.
});
HID cihazına erişimi iptal etme
Web sitesi, HIDDevice örneğinde forget() işlevini çağırarak artık tutmak istemediği HID cihazlara erişim izinlerini temizleyebilir. Örneğin, birçok cihazla paylaşılan bir bilgisayarda kullanılan bir eğitim web uygulamasında, kullanıcı tarafından oluşturulan çok sayıda izin birikmesi kötü bir kullanıcı deneyimi oluşturur.
Tek bir HIDDevice örneğinde forget() çağrıldığında aynı fiziksel cihazdaki tüm HID arayüzlerine erişim iptal edilir.
// Voluntarily revoke access to this HID device.
await device.forget();
forget(), Chrome 100 veya sonraki sürümlerde kullanılabildiğinden bu özelliğin aşağıdakilerle desteklenip desteklenmediğini kontrol edin:
if ("hid" in navigator && "forget" in HIDDevice.prototype) {
// forget() is supported.
}
Geliştiriciler için ipuçları

Chrome'da HID'yi dahili sayfa about://device-log ile hata ayıklayın. Bu sayfada, HID ve USB cihazlarıyla ilgili tüm etkinlikleri tek bir yerde görebilirsiniz.
HID cihaz bilgilerini insanlar tarafından okunabilir bir biçime aktarmak için HID Explorer'a göz atın. Her HID kullanımı için kullanım değerlerinden adlara eşleme yapar.
Çoğu Linux sisteminde, HID cihazları varsayılan olarak salt okuma izinleriyle eşlenir. Chrome'un bir HID cihazı açmasına izin vermek için yeni bir udev
kuralı eklemeniz gerekir. /etc/udev/rules.d/50-yourdevicename.rules konumunda aşağıdaki içeriğe sahip bir dosya oluşturun:
KERNEL=="hidraw*", ATTRS{idVendor}=="[yourdevicevendor]", MODE="0664", GROUP="plugdev"
Bu kodda, [yourdevicevendor], 057e'dir. Örneğin, cihazınız Nintendo Switch Joy-Con ise. Daha ayrıntılı bir kural için ATTRS{idProduct} eklenebilir. user hesabınızın plugdev grubunun üyesi olduğundan emin olun. Ardından, cihazınızı yeniden bağlamanız yeterlidir.
Demolar
Bazı WebHID demoları web.dev/hid-examples adresinde listelenmiştir.
Güvenlik ve gizlilik
Spesifikasyon yazarları, WebHID API'yi Güçlü Web Platformu Özelliklerine Erişimi Kontrol Etme'de tanımlanan temel ilkeleri (kullanıcı kontrolü, şeffaflık ve ergonomi dahil) kullanarak tasarlayıp uygulamıştır. Bu API'yi kullanma özelliği, öncelikle aynı anda yalnızca tek bir HID cihazına erişim izni veren bir izin modeliyle sınırlıdır. Kullanıcının, bir kullanıcı istemine yanıt olarak belirli bir HID cihazı seçmek için aktif adımlar atması gerekir.
Güvenlikle ilgili ödünleri anlamak için WebHID spesifikasyonunun Güvenlik ve Gizlilikle İlgili Hususlar bölümüne göz atın.
Bunun yanı sıra Chrome, her üst düzey koleksiyonun kullanımını inceler.Bir üst düzey koleksiyonun korumalı kullanımı varsa (ör. genel klavye, fare) web sitesi, bu koleksiyonda tanımlanan raporları gönderemez ve alamaz. Koruma altındaki kullanımların tam listesi herkese açıktır.
Güvenlik açısından hassas HID cihazlarının (ör. daha güçlü kimlik doğrulama için kullanılan FIDO HID cihazları) Chrome'da da engellendiğini unutmayın. USB engellenenler listesi ve HID engellenenler listesi dosyalarına bakın.
Geri bildirim
Chrome ekibi, WebHID API ile ilgili düşüncelerinizi ve deneyimlerinizi öğrenmekten memnuniyet duyar.
API tasarımı hakkında bilgi verin
API ile ilgili beklendiği gibi çalışmayan bir durum var mı? Yoksa fikrinizi uygulamak için eksik yöntemler veya özellikler mi var?
WebHID API GitHub deposunda bir spesifikasyon sorunu bildirin veya düşüncelerinizi mevcut bir soruna ekleyin.
Uygulamayla ilgili sorun bildirme
Chrome'un uygulamasında bir hata mı buldunuz? Yoksa uygulama, spesifikasyondan farklı mı?
WebHID hatalarını bildirme başlıklı makaleye göz atın. Mümkün olduğunca fazla ayrıntı eklediğinizden, hatanın yeniden üretilmesiyle ilgili talimatlar verdiğinizden ve Bileşenler'i Blink>HID olarak ayarladığınızdan emin olun.
Faydalı bağlantılar
- Spesifikasyon
- İzleme hatası
- ChromeStatus.com girişi
- Blink Bileşeni:
Blink>HID
Teşekkür
Yorumları için Matt Reynolds ve Joe Medley'e teşekkür ederiz.