Yaygın olmayan HID cihazlarına bağlanılıyor

WebHID API, web sitelerinin alternatif yardımcı klavyelere ve egzotik oyun kumandalarına erişmesine olanak tanır.

François Beaufort
François Beaufort

İnsan arayüzü cihazları (HID'ler) çok sayıdadır. Örneğin, çok yeni, çok eski veya alışılmadık şekilde nadir görülen klavyeler veya egzotik oyun kumandaları sistemlerinin erişebildiği cihaz sürücüleridir. WebHID API, bu sorunu çözmek için özel mantığı JavaScript'te uygulamanın en kolay yoludur.

Önerilen kullanım alanları

HID cihazı, insanlardan giriş alır veya insanlara çıkış sağlar. Cihaz örnekleri klavyeler, işaretleme cihazları (mikrofon, dokunmatik ekranlar vb.) ve oyun kumandaları da dahildir. HID protokolü, bu cihazlara masaüstünden erişilmesini sağlar işletim sistemi sürücülerini kullanarak karşılaştırabilirsiniz. Web platformu, HID cihazlarını destekler bu sürücülere güvenerek.

Yaygın olmayan HID cihazlarına erişememek alternatif yardımcı klavyelerle uyumludur (ör. Elgato Stream Deck, Jabra) mikrofonlu kulaklıklar, X tuşları) ve egzotik oyun kumandası desteğine sahiptir. Masaüstü için tasarlanmış oyun kumandaları oyun kumandası girişleri (düğmeler, kontrol çubukları, tetikleyiciler) ve çıkışları için genellikle HID'yi kullanırlar (LED'ler, gürültü). Maalesef oyun kumandası giriş ve çıkışları iyi değil ve web tarayıcıları genellikle belirli cihazlar için özel mantık gerektirir. Bu sürdürülebilir bir durum ve yaşlı ve geniş kitlelerinin yaygın olmayan cihazlardır. Ayrıca, tarayıcının davranıştaki tuhaflıklara cihazlar.

Terminoloji

HID, raporlar ve rapor tanımlayıcıları olmak üzere iki temel kavramdan oluşur. Raporlar, bir cihaz ile yazılım istemcisi arasında gidip gelen verilerdir. Rapor açıklayıcısı, cihazın kaydettiği verilerin biçimini ve anlamını destekler.

HID (İnsan Arayüzü Cihazı), insana çıkış sağlar. Aynı zamanda, Gantt şemaları için bir standart olan bir ana makine ile cihaz arasında iki yönlü iletişim kurulmasını kurulum işlemini kolaylaştırır. HID protokolü ilk olarak kullanıma sunuldu ancak o zamandan beri diğer pek çok protokol üzerinden Bluetooth dahil.

Uygulamalar ve insan arabirim cihazları üç rapor türü aracılığıyla ikili program verisi alışverişi yapar:

Rapor türü Açıklama
Giriş raporu Cihazdan uygulamaya gönderilen veriler (ör. bir düğmeye basıldığında).
Çı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.

Bir rapor açıklayıcısı, olanak tanır. Yapısı hiyerarşiktir ve raporları ayrı ayrı gruplayabilir üst düzey koleksiyondaki koleksiyonları içerir. Açıklayıcının biçimi: (HID spesifikasyonu tarafından tanımlanmıştır.

HID kullanımı, standartlaştırılmış bir girişi veya çıkışı ifade eden sayısal bir değerdir. Kullanım değerleri, cihazın kullanım amacına ve her alanın amacına odaklanmasını ifade eder. Örneğin sol bir fare düğmesi. Kullanımlar ayrıca, kullanım sayfaları şeklinde düzenlenir. cihazın veya raporun üst düzey kategorisini gösterir.

WebHID API'yi kullanma

Özellik algılama

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 engelleme işlemi yapılır. HID verileri alınabildiği için bu önemlidir dinlemek için bir yol gerekecektir.

HID bağlantısını açmak için önce bir HIDDevice nesnesine erişin. Bunun için ya da telefon araması yaparak kullanıcıdan cihaz seçmesini iste navigator.hid.requestDevice() veya navigator.hid.getDevices() arasından bir seçim yapın web sitesinin erişmesine izin verilen cihazların listesini döndürür öğrendi.

navigator.hid.requestDevice() işlevi, şu koşulları karşılayan zorunlu bir nesne alır: , filtreleri tanımlar. Bunlar, bir USB tedarikçisine bağlı herhangi bir cihazı eşleştirmek için kullanılır tanımlayıcı (vendorId), USB ürün tanımlayıcısı (productId), kullanım sayfası değer (usagePage) ve kullanım değeri (usage). Bunları USB Kimliği Deposu ve HID kullanım tabloları dokümanı.

Bu işlev tarafından döndürülen birden çok HIDDevice nesnesi, birden çok öğeyi temsil eder Aynı fiziksel cihazdaki HID arayüzleri.

// 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();
Bir web sitesindeki HID cihaz isteminin ekran görüntüsü.
Nintendo Switch Joy-Con seçmesi için kullanıcı istemi.

İsteğe bağlı exclusionFilters anahtarını Bazı cihazları tarayıcı seçiciden hariç tutmak için navigator.hid.requestDevice() cihazlar arası yeniden kullanılabilir.

// 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 }],
});

Bir HIDDevice nesnesi, cihazın USB tedarikçi firması ve ürün tanımlayıcıları içeriyor çok önemlidir. collections özelliği, hiyerarşik bir cihazın rapor biçimlerinin açıklaması.

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 "closed" durumunda döndürülür. durum ve veri gönderilmeden veya alınmadan önce open() aranarak açıldı.

// Wait for the HID connection to open before sending/receiving data.
await device.open();

Giriş raporlarını al

HID bağlantısı kurulduktan sonra gelen girişi işleyebilirsiniz cihazdaki "inputreport" etkinliklerini dinleyerek raporlar. Söz konusu etkinlikler HID verilerini DataView nesnesi (data) olarak ve ait olduğu HID cihazını içermelidir. - (device) ve giriş raporuyla ilişkili 8 bit rapor kimliği (reportId).

Kırmızı ve mavi Nintendo Switch fotoğrafı.
Nintendo Switch Joy-Con cihazlar.

Önceki örnekten devam edelim. Aşağıdaki kod, Joy-Con Right cihazda hangi düğmeye bastığını evde deneyebilmeyi umuyoruz.

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 ilişkilendirilmiş 8 bit rapor kimliğini iletin çıkış raporunu (reportId) ve baytları BufferSource (data) biçiminde device.sendReport(). Bildirim yapıldıktan sonra, iade edilen vaat sona erer. gönderilir. HID cihazı rapor kimlikleri kullanmıyorsa reportId değerini 0 olarak ayarlayın.

Aşağıdaki örnek bir Joy-Con cihazı için geçerlidir ve nasıl yapıldığını gösterir zihinsel çıkarımlar yapın.

// 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 ikisinde de gidebilen tek HID veri raporu türüdür yol tarifleri alın. HID cihazlarının ve uygulamalarının standart olmayan HID verileri. Giriş ve çıkış raporlarının aksine, özellik raporları düzenli olarak gönderilir.

Siyah ve gümüş renkli dizüstü bilgisayar fotoğrafı.
Dizüstü bilgisayar klavyesi

Bir HID cihazına özellik raporu göndermek için ilişkilendirilmiş 8 bit rapor kimliğini iletin. özellik raporunu (reportId) ve baytları BufferSource (data) olarak device.sendFeatureReport(). Bildirimde bulunulduktan sonra, iade edilen vaat sona erer. gönderildi. HID cihazı rapor kimlikleri kullanmıyorsa reportId değerini 0 olarak ayarlayın.

Aşağıdaki örnekte, özellik raporlarının kullanımı, bir Apple klavye arka aydınlatma cihazı isteğinde bulunun, cihazı açın ve yanıp sönmesini sağlayın.

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);
}

Bir HID cihazından özellik raporu almak için 8 bit rapor kimliğini iletin özellik raporu (reportId) ile ilişkilendirilen device.receiveFeatureReport(). İade edilen vaat Özellik raporunun içeriğini içeren DataView nesnesi. HID cihaz rapor kimlikleri kullanmıyor, 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ıyı ve bağlantıyı kesmeyi dinleyin

Web sitesinin bir HID cihazına erişmesine izin verildiğinde "connect" dinleyerek bağlantı ve bağlantı kesintileriyle ilgili etkinlikleri aktif olarak al ve "disconnect" etkinlik.

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.
});

Bir HID cihazına erişimi iptal etme

Web sitesi, artık kullanılmayan bir HID cihaza erişim izinlerini temizleyebilir HIDDevice örneğinde forget() çağırarak elde tutmayı düşünebilir. Örneğin, Örneğin, birçok kullanıcıyla paylaşılan bir bilgisayarda kullanılan eğitsel bir web uygulaması kullanıcı tarafından oluşturulmuş çok sayıda izin, kötü performansa neden olur. en iyi uygulamaları paylaşacağız.

Tek bir HIDDevice örneğinde forget() çağrısı yapıldığında tüm aynı fiziksel cihazdaki HID arayüzleridir.

// Voluntarily revoke access to this HID device.
await device.forget();

forget(), Chrome 100 veya sonraki sürümlerde kullanılabildiğinden, bu özelliğin şunlar tarafından desteklenir:

if ("hid" in navigator && "forget" in HIDDevice.prototype) {
  // forget() is supported.
}

Geliştiriciler İpuçları

Chrome'daki HID'de hata ayıklama işlemi, about://device-log dahili sayfasını kullanarak kolaydır. Burada, HID ve USB cihazıyla ilgili tüm etkinlikleri tek bir yerden görebilirsiniz.

HID hatalarını ayıklamak için kullanılan dahili sayfanın ekran görüntüsü.
HID'de hata ayıklamak için Chrome'daki dahili sayfa.

HID cihazını döküm için HID gezgini'ne göz atın okunabilen bir biçime dönüştürmenizi sağlar. Kullanım değerlerinden her bir öğenin adı ile eşlenir. HID kullanımı.

Çoğu Linux sisteminde HID cihazları, salt okuma izinleriyle varsayılandır. Chrome'un bir HID cihazını açmasına izin vermek için yeni bir udev eklemeniz gerekir. kuralı ekleyin. /etc/udev/rules.d/50-yourdevicename.rules adresinde takip eden içerik:

KERNEL=="hidraw*", ATTRS{idVendor}=="[yourdevicevendor]", MODE="0664", GROUP="plugdev"

Yukarıdaki satırda, cihazınız Nintendo Switch ise [yourdevicevendor] değeri 057e olur Joy-Con örneğine bakalım. Daha spesifik bir hedef için ATTRS{idProduct} eklenebilir kuralı. user kullanıcısının plugdev grubunun üyesi olduğundan emin olun. Daha sonra cihazınızı yeniden bağlayın.

Tarayıcı desteği

WebHID API tüm masaüstü platformlarında (ChromeOS, Linux, macOS, ve Windows) - Chrome 89'da kullanılabilir.

Demolar

Bazı WebHID demoları web.dev/hid-examples adresinde listelenmiştir. Bir göz atın!

Güvenlik ve gizlilik

Bu spesifikasyonun yazarları, çekirdek API'yi kullanarak WebHID API'yi tasarlayıp uyguladılar Güçlü Web Platformu Özelliklerine Erişimi Kontrol Etme'de açıklanan ilkeleri, dahil olmak üzere tüm bunları kapsar. Bunu kullanma imkanı API, esas olarak yalnızca tek bir kullanıcıya erişim veren bir izin modeliyle denetlenir. Bir defada HID cihazı. Kullanıcı istemine yanıt olarak kullanıcının etkin olması gerekir adımları uygulayın.

Güvenlikle ilgili dengeleri anlamak için Güvenlik ve Gizlilik WebHID spesifikasyonunun Dikkat edilmesi gereken noktalar bölümüne bakın.

Ayrıca, Chrome her üst düzey koleksiyonun kullanımını inceler ve bir üst düzey koleksiyonda korunan bir kullanım (ör. genel klavye, fare) varsa web sitesi, teklifte tanımlanmış raporları gönderip alamaz. koleksiyonudur. Korunan kullanımların tam listesi herkese açıktır.

Güvenlik açısından hassas HID cihazlarının (ör. şu işlemler için kullanılan FIDO HID cihazları) daha güçlü kimlik doğrulama) Chrome'da da engellenir. USB engellenenler listesine bakın ve HID engellenenler listesi dosyaları.

Geri bildirim

Chrome ekibi WebHID API.

Bize API tasarımı hakkında bilgi verin

API'de beklendiği gibi çalışmayan bir şey mi var? Yoksa fikrinizi uygulamak için ihtiyacınız olan yöntem veya özelliklerden yoksun mu?

WebHID API GitHub deposunda spesifikasyon sorunu bildirin veya düşüncelerinizi ekleyin bir sorundur.

Uygulamayla ilgili bir sorunu bildirin

Chrome'un uygulanmasıyla ilgili bir hata buldunuz mu? Yoksa ve spesifikasyondan farklı mı?

WebHID hatalarını bildirme başlıklı makaleye göz atın. Olabildiğince çok sayıda mümkün olduğunca ayrıntı verin, hatayı yeniden oluşturmak için basit talimatlar sağlayın ve Bileşenler Blink>HID olarak ayarlandı. Glitch mükemmel bir yöntemdir hızlı ve kolay yenidenler paylaşabilirsiniz.

Desteğinizi gösterin

WebHID API'yi kullanmayı planlıyor musunuz? Herkese açık desteğiniz Chrome'un ekibinin öncelikle özelliklerin ne kadar önemli olduğunu gösterir ve diğer tarayıcı tedarikçilerine destek olmak.

Hashtag'i kullanarak @ChromiumDev hesabına tweet gönderin #WebHID ve bunu bize bildirin bir şablon görevi görür.

Faydalı bağlantılar

Teşekkür

Bu makaleyle ilgili yorumları için Matt Reynolds ve Joe Medley'e teşekkür ederiz. Sara Kurfeß'un kırmızı ve mavi Nintendo Switch fotoğrafı ile siyah ve gümüş dizüstü bilgisayar Athul Cyriac Ajay'in Unsplash'teki bilgisayar fotoğrafı.