WebHID API, web sitelerinin alternatif yardımcı klavyelere ve sıra dışı oyun kumandaları erişmesine olanak tanır.
Alternatif klavyeler veya egzotik oyun kumandası gibi çok yeni, çok eski veya sistemlerin cihaz sürücüleri tarafından erişilemeyecek kadar yaygın olmayan çok sayıda insan arayüz cihazı (HID) vardır. WebHID API, JavaScript'te cihaza özel mantığı 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 oyun kumandası bu cihazlara örnek olarak verilebilir. 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.
Özellikle alternatif yardımcı klavyeler (ör. Elgato Stream Deck, Jabra mikrofonlu kulaklıklar, X tuşları) ve egzotik oyun kumandası desteği olduğunda, yaygın olmayan HID cihazlarına erişememek çok zor oluyor. Masaüstü için tasarlanmış oyun kumandaları genellikle oyun kumandası girişleri (düğmeler, kontrol çubukları, tetikler) ve çıkışları (LED'ler, titreşim) için HID kullanır. Maalesef gamepad giriş ve çıkışları iyi 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 eski ve yaygın olmayan cihazların uzun kuyruğu için kötü bir destek sunar. Ayrıca, tarayıcının belirli cihazların davranışındaki tuhaflıklara bağlı olmasına neden olur.
Terminoloji
HID iki temel kavramdan oluşur: raporlar ve rapor tanımlayıcıları. Raporlar, bir cihaz ile yazılım istemcisi arasında gidip gelen verilerdir. Rapor açıklayıcı, cihazın desteklediği verilerin biçimini ve anlamını açıklar.
HID (İnsan Arabirim Cihazı), kullanıcılardan giriş alan veya kullanıcılara çıkış sağlayan bir cihaz türüdür. Aynı zamanda, ana makine ile cihaz arasında yükleme işlemini basitleştirmek için tasarlanmış iki yönlü iletişim standardı olan HID protokolünü ifade eder. HID protokolü başlangıçta USB cihazlar için geliştirilmiş olsa da o zamandan beri Bluetooth da dahil olmak üzere birçok başka protokolde uygulanmıştır.
Uygulamalar ve HID cihazlar, üç rapor türü aracılığıyla ikili veri alışverişinde bulunur:
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 | Her iki 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. Hiyerarşik bir yapıya sahiptir ve raporları üst düzey koleksiyondaki farklı 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ş veya çıkışı belirten sayısal bir değerdir. Kullanım değerleri, cihazın kullanım amacı ve raporlarındaki her bir alanın amacını açıklamasına olanak tanır. Örneğin, farenin sol düğmesi için bir tane tanımlanır. Kullanımlar, cihazın veya raporun üst düzey kategorisini gösteren kullanım sayfalarına da ayrılır.
WebHID API'yi kullanma
Özellik algılama
WebHID API'nin desteklenip desteklenmediğini kontrol etmek için:
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ş beklerken engellenmesini önlemek için tasarlandığından asenkrondur. HID verileri herhangi bir zamanda alınabileceğinden, bu verileri dinlemek için bir yönteme ihtiyaç vardır.
HID bağlantısını açmak için önce bir HIDDevice
nesnesine erişin. Bunun için navigator.hid.requestDevice()
işlevini çağırarak kullanıcıdan bir cihaz seçmesini isteyebilir veya web sitesinin daha önce erişmesine izin verilen cihazların listesini döndüren navigator.hid.getDevices()
işlevinden birini seçebilirsiniz.
navigator.hid.requestDevice()
işlevi, filtreleri tanımlayan zorunlu bir nesne alır. Bunlar, bağlı herhangi bir cihazı 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 eşleştirmek için kullanılır. Bu değerleri USB kimliği deposundan ve HID kullanım tabloları belgesinden edinebilirsiniz.
Bu işlev tarafından döndürülen birden fazla HIDDevice
nesnesi, aynı fiziksel cihazda birden çok 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();
Örneğin, düzgün çalışmadığı bilinen bazı cihazları tarayıcı seçiciden hariç tutmak için navigator.hid.requestDevice()
içinde isteğe bağlı exclusionFilters
anahtarını da kullanabilirsiniz.
// 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 firması ve ürün tanımlayıcıları 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önderilmeden veya alınmadan önce open()
çağrılarak açılmalıdır.
// Wait for the HID connection to open before sending/receiving data.
await device.open();
Giriş raporları alma
HID bağlantısı kurulduktan sonra cihazdaki "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 örneğe devam ediyoruz. Aşağıdaki kodda, kullanıcının Joy-Con sağ cihazda hangi düğmeye bastığını nasıl algılayacağınız gösterilmektedir. Böylece, bunu 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]}.`);
});
Çıkış raporları gönder
Bir HID cihazına çıkış raporu göndermek için çıkış raporuyla ilişkili 8 bitlik rapor kimliğini (reportId
) ve baytları device.sendReport()
'e BufferSource
(data
) olarak 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.
Aşağıdaki örnek, Joy-Con cihazı için geçerlidir ve çıkış raporlarıyla nasıl titretileceğini 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 below.
const rumbleData = [ /* ... */ ];
await device.sendReport(0x10, new Uint8Array(rumbleData));
Ö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 alışverişine olanak tanır. Giriş ve çıkış raporlarının aksine, özellik raporları uygulama tarafından düzenli olarak alınmaz veya gönderilmez.
Bir HID cihazına özellik raporu göndermek için özellik raporuyla ilişkili 8 bitlik rapor kimliğini (reportId
) ve baytları device.sendFeatureReport()
'e BufferSource
(data
) olarak 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.
Aşağıdaki örnekte, bir Apple klavye arka ışık cihazını nasıl isteyeceğinizi, açacağınızı ve yanıp söndüreceğinizi göstererek özellik raporlarının kullanımı açıklanmaktadır.
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);
}
HID cihazdan özellik raporu almak için özellik raporuyla ilişkili 8 bitlik rapor kimliğini (reportId
) device.receiveFeatureReport()
'e iletin. Döndürülen söz, özellik raporunun içeriğini içeren bir DataView
nesnesi ile çözülür. HID cihazı rapor kimlikleri 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 seslerini dinleme
Web sitesine HID cihazına erişim izni verildiğinde, "connect"
ve "disconnect"
etkinliklerini dinleyerek bağlantı ve bağlantı kesme etkinliklerini etkin bir şekilde 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()
çağrısını yaparak artık saklamak istemediği bir HID cihazına erişim izinlerini temizleyebilir. Örneğin, birçok cihazın bulunduğu paylaşılan bir bilgisayarda kullanılan eğitim amaçlı bir 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ısı yapı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ğıdaki sürümlerde desteklenip desteklenmediğini kontrol edin:
if ("hid" in navigator && "forget" in HIDDevice.prototype) {
// forget() is supported.
}
Geliştirici İpuçları
Chrome'da HID hatalarını ayıklamak, HID ve USB cihazıyla ilgili tüm etkinlikleri tek bir yerde görebileceğiniz dahili sayfa (about://device-log
) sayesinde kolaydır.
HID cihaz bilgilerini kullanıcı tarafından okunabilir bir biçime aktarmak için HID gezginine göz atın. Her HID kullanımı için kullanım değerlerini adlarla eşler.
Çoğu Linux sisteminde HID cihazları varsayılan olarak salt okuma izinleriyle eşlenir. Chrome'un HID cihazı açmasına izin vermek için yeni bir udev kuralı eklemeniz gerekir. /etc/udev/rules.d/50-yourdevicename.rules
adresinde aşağıdaki içeriğe sahip bir dosya oluşturun:
KERNEL=="hidraw*", ATTRS{idVendor}=="[yourdevicevendor]", MODE="0664", GROUP="plugdev"
Yukarıdaki satırda, cihazınız örneğin bir Nintendo Switch Joy-Con ise [yourdevicevendor]
, 057e
olur. Daha spesifik bir kural için ATTRS{idProduct}
da eklenebilir. user
kullanıcısının plugdev
grubunun üyesi olduğundan emin olun. Ardından cihazınızı tekrar bağlayın.
Tarayıcı desteği
WebHID API, Chrome 89'da tüm masaüstü platformlarında (ChromeOS, Linux, macOS ve Windows) kullanılabilir.
Demolar
Bazı WebHID demolar web.dev/hid-examples adresinde listelenmiştir. Göz atın.
Güvenlik ve gizlilik
Spesifikasyon yazarları, WebHID API'yi tasarlarken ve uygularken kullanıcı kontrolü, şeffaflık ve ergonomi gibi Güçlü Web Platformu Özelliklerine Erişimi Kontrol Etme başlıklı makalede tanımlanan temel ilkeleri temel almıştır. Bu API'nin kullanılabilmesi, temel olarak aynı anda yalnızca tek bir HID cihazına erişim izni veren bir izin modeliyle sınırlandırılmıştır. Kullanıcı istemlerine yanıt olarak kullanıcının belirli bir HID cihazı seçmek için etkin adımlar atması gerekir.
Güvenlikle ilgili avantajları ve dezavantajları anlamak için WebHID spesifikasyonunun Güvenlik ve Gizlilik Konusunda Dikkat Edilmesi Gerekenler bölümüne göz atın.
Bununla birlikte Chrome, her üst düzey koleksiyonun kullanımını inceler.Üst düzey bir koleksiyonun kullanımı korunuyorsa (ör. genel klavye, fare) web sitesi bu koleksiyonda tanımlanan raporları gönderip alamaz. Korunan kullanımların tam listesi herkese açıktır.
Güvenlik açısından hassas HID cihazları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'de beklendiği gibi çalışmayan bir şey mi var? Yoksa fikrinizi uygulamak için ihtiyaç duyduğunuz yöntemler veya özellikler eksik mi?
WebHID API GitHub deposunda spesifikasyon sorunu oluşturun veya mevcut bir soruna düşüncelerinizi ekleyin.
Uygulamayla ilgili bir sorunu bildirin
Chrome'un uygulamasında bir hata mı buldunuz? Yoksa uygulama, spesifikasyondan farklı mı?
WebHID hatalarını bildirme başlıklı makaleyi inceleyin. Olabildiğince fazla ayrıntı eklediğinizden, hatayı yeniden oluşturmayla ilgili basit talimatlar sağladığınızdan ve Bileşenler'in Blink>HID
olarak ayarlandığından emin olun. Glitch, hızlı ve kolay yeniden oluşturma işlemlerini paylaşmak için mükemmel bir araçtır.
Destek gösterme
WebHID API'yi kullanmayı planlıyor musunuz? Herkese açık desteğiniz, Chrome ekibinin özelliklere öncelik vermesine yardımcı olur ve diğer tarayıcı tedarikçi firmalarına bu özellikleri desteklemenin ne kadar önemli olduğunu gösterir.
#WebHID
hashtag'ini kullanarak @ChromiumDev hesabına tweet gönderin ve bu özelliği nerede ve nasıl kullandığınızı bize bildirin.
Faydalı bağlantılar
- Özellik
- İzleme hatası
- ChromeStatus.com girişi
- Blink Bileşeni:
Blink>HID
Teşekkür ederiz
Bu makaleyi inceleyen Matt Reynolds ve Joe Medley'e teşekkür ederiz. Sara Kurfeß'un kırmızı ve mavi Nintendo Switch fotoğrafı; Unsplash'te Athul Cyriac Ajay'in siyah ve gümüş dizüstü bilgisayar fotoğrafı.