WebHID üzerinden Stadia Kumanda ile konuşma

Yanıp sönen Stadia kumanda, standart bir oyun kumandası gibi çalışır. Bu nedenle, Gamepad API'si kullanılarak düğmelerinin tümüne erişilemez. WebHID ile artık eksik düğmelere erişebilirsiniz.

Stadia'nın kapatılmasından sonra birçok kişi, kumandanın çöp sahasında işe yaramaz bir donanım parçası olarak son bulacağından korkuyordu. Neyse ki Stadia ekibi, Stadia Bluetooth modu sayfasına giderek kumandanıza yükleyebileceğiniz özel bir donanım yazılımı sağlayarak Stadia Kumanda'nın kilidini açmaya karar verdi. Bu işlem, Stadia Kumanda'nızı USB kablosuyla veya Bluetooth üzerinden kablosuz olarak bağlayabileceğiniz standart bir oyun kumandası olarak gösterir. Project Fugu API Showcase'ta yer alan Stadia Bluetooth sayfası WebHID ve WebUSB kullanıyor ancak bu makalenin konusu bu değil. Bu yayında, WebHID üzerinden Stadia kumandasıyla nasıl iletişim kurabileceğinizi açıklamak istiyorum.

Standart oyun kumandası olarak Stadia Kumanda

Yanıp sönme işleminden sonra, kontrol cihazı işletim sistemine standart bir gamepad olarak görünür. Standart bir gamepad'deki yaygın düğme ve eksen düzenlemesi için aşağıdaki ekran görüntüsüne bakın. Gamepad API spesifikasyonunda belirtildiği gibi, standart gamepad'lerde 0 ila 16 arasında düğme bulunur. Yani toplamda 17 düğme vardır (d-pad dört düğme olarak sayılır). Stadia Kumanda'yı oyun kumandası test cihazı demosunda denerseniz kusursuz çalıştığını göreceksiniz.

Çeşitli eksen ve düğmelerin etiketlendiği standart bir gamepad şeması.

Ancak Stadia kumandadaki düğmeleri sayarsanız 19 tane olduğunu görürsünüz. Oyun kumandası test cihazında düğmeleri tek tek sistematik bir şekilde denerseniz Asistan ve Kayıt düğmelerinin çalışmadığını fark edersiniz. Oyun kumandası spesifikasyonunda tanımlanan oyun kumandası buttons özelliği açık uçlu olsa bile Stadia kumanda standart bir oyun kumandası olarak göründüğü için yalnızca 0-16 arasındaki düğmeler eşlenir. Diğer düğmeleri kullanmaya devam edebilirsiniz ancak çoğu oyunda bu düğmelerin varlığı beklenmez.

WebHID'in yardımı

WebHID API sayesinde, eksik 17 ve 18 numaralı düğmelerle iletişim kurabilirsiniz. Gerçekten isterseniz Gamepad API üzerinden zaten mevcut olan diğer tüm düğmeler ve eksenler hakkında veri de alabilirsiniz. İlk adım, Stadia kumandasının kendisini işletim sistemine nasıl bildirdiğini bulmaktır. Bunu yapmanın bir yolu, herhangi bir sayfada Chrome Geliştirici Araçları Konsolu'nu açıp WebHID API'den filtrelenmemiş bir cihaz listesi istemektir. Daha ayrıntılı inceleme için Stadia kumandasını manuel olarak seçin. Boş bir filters seçenek dizisi ileterek filtrelenmemiş bir cihaz listesi alın.

const [device] = await navigator.hid.requestDevice({filters: []});

Seçicide, sondan bir önceki giriş Stadia kumandasına benzer.

Alakasız bazı cihazları ve sondan bir önceki konumda Stadia kumandasını gösteren WebHID API cihaz seçici.

"Stadia Kumanda rev. A" cihazını seçtikten sonra, ortaya çıkan HIDDevice nesnesini Console'a kaydedin. Bu işlem, Stadia kumandasının productId (37888, onaltılık sistemde 0x9400) ve vendorId (6353, onaltılık sistemde 0x18d1) değerlerini gösterir. Resmi USB tedarikçi firma kimliği tablosunda vendorID değerini ararsanız 6353 değerinin beklediğinizle eşleştiğini görürsünüz: Google Inc..

HIDDevice nesnesini günlüğe kaydetme işleminin çıktısını gösteren Chrome Geliştirici Araçları Konsolu.

Yukarıda açıklanan akışa alternatif olarak, URL çubuğunda chrome://device-log/ simgesine gidip Temizle düğmesine basabilir, Stadia kumandanızı takabilir ve ardından Yenile'ye basabilirsiniz. Bu sayede aynı bilgileri elde edebilirsiniz.

Takılı Stadia kumanda hakkında bilgi gösteren chrome://device-log hata ayıklama arayüzü.

Bilgisayarınıza bağlı HID cihazlarla ilgili daha fazla ayrıntıyı keşfetmenize olanak tanıyan HID Explorer aracını da kullanabilirsiniz.

Seçicide gösterilenleri hassaslaştırmak için bu iki kimliği (vendorId ve productId) kullanarak doğru WebHID cihazını doğru şekilde filtreleyin.

const [stadiaController] = await navigator.hid.requestDevice({filters: [{
  vendorId: 6353,
  productId: 37888,
}]});

Artık alakasız tüm cihazlardan gelen gürültü ortadan kalktı ve yalnızca Stadia kumanda gösteriliyor.

Yalnızca Stadia kumandasını gösteren WebHID API cihaz seçici.

Ardından, open() yöntemini çağırarak HIDDevice öğesini açın.

await stadiaController.open();

HIDDevice öğesini tekrar kaydedin. opened işareti true olarak ayarlanır.

HIDDevice nesnesini açtıktan sonra nesnesini günlüğe kaydetme işleminin çıktısını gösteren Chrome Geliştirici Araçları Konsolu.

Cihaz açıkken bir etkinlik işleyici ekleyerek gelen inputreport etkinliklerini dinleyin.

stadiaController.addEventListener('inputreport', (e) => {
  console.log(e);
});

Kumandadaki Asistan düğmesine basıp bıraktığınızda Console'a iki etkinlik kaydedilir. Bunları "Asistan düğmesi aşağı" ve "Asistan düğmesi yukarı" etkinlikleri olarak düşünebilirsiniz. timeStamp dışında, iki etkinlik ilk bakışta birbirinden ayırt edilemez.

Günlüğe kaydedilen HIDInputReportEvent nesnelerini gösteren Chrome Geliştirici Araçları Konsolu.

HIDInputReportEvent arayüzünün reportId mülkü, bu rapor için bir baytlık tanımlama ön ekini veya HID arayüzü rapor kimlikleri kullanmıyorsa 0 değerini döndürür. Bu durumda 3 olur. Gizli anahtar, 10 boyutunda bir DataView olarak temsil edilen data mülkünde bulunur. DataView, ikili ArrayBuffer içinde birden fazla sayı türünü okumak ve yazmak için düşük düzeyli bir arayüz sağlar. Bu temsilden daha kolay anlaşılır bir şey elde etmenin yolu, ArrayBuffer'tan bir Uint8Array oluşturmaktır. Böylece, 8 bitlik imzasız tam sayıları tek tek görebilirsiniz.

const data = new Uint8Array(event.data.buffer);

Ardından giriş raporu etkinlik verilerini tekrar günlüğe kaydettiğinizde işler daha anlamlı hale gelmeye başlar ve "Asistan düğmesi aşağı" ve "Asistan düğmesi yukarı" etkinlikleri anlaşılır hale gelir. İlk tam sayı (her iki etkinlikte de 8), düğmeye basmalarla ilgilidir. İkinci tam sayı (2 ve 0) ise Asistan düğmesine basılı olup olmadığıyla ilgilidir.

Her HIDInputReportEvent için günlüğe kaydedilen Uint8Array nesnelerini gösteren Chrome Geliştirici Araçları Konsolu.

Asistan düğmesi yerine Yakalama düğmesine basın. İkinci tam sayının, düğmeye basıldığında 1 değerinden, düğme bırakıldığında 0 değerine geçtiğini görürsünüz. Bu sayede, eksik iki düğmeyi kullanmanıza olanak tanıyan çok basit bir "sürücü" yazabilirsiniz.

stadia.addEventListener('inputreport', (event) => {
  if (!e.reportId === 3) {
    return;
  }
  const data = new Uint8Array(event.data.buffer);
  if (data[0] === 8) {
    if (data[1] === 1) {
      hidButtons[1].classList.add('highlight');
    } else if (data[1] === 2) {
      hidButtons[0].classList.add('highlight');
    } else if (data[1] === 3) {
      hidButtons[0].classList.add('highlight');
      hidButtons[1].classList.add('highlight');
    } else {
      hidButtons[0].classList.remove('highlight');
      hidButtons[1].classList.remove('highlight');
    }
  }
});

Bu tür bir tersine mühendislik yaklaşımı kullanarak, düğme düğme ve eksen eksen, WebHID ile Stadia kumandasıyla nasıl iletişim kuracağınızı anlayabilirsiniz. Bu konuyu anladıktan sonra geri kalanı neredeyse mekanik bir tam sayı eşleme çalışmasıdır.

Şimdilik eksik olan tek şey, Gamepad API'nin sunduğu sorunsuz bağlantı deneyimi. Stadia Kumanda gibi bir WebHID cihazıyla çalışmak için güvenlik nedeniyle her zaman ilk seçici deneyimini bir kez yaşamanız gerekir. Ancak sonraki bağlantılar için bilinen cihazlara yeniden bağlanabilirsiniz. Bunu getDevices() yöntemini çağırarak yapabilirsiniz.

let stadiaController;
const [device] = await navigator.hid.getDevices();
if (device && device.vendorId === 6353 && device.productId === 37888) {
  stadiaController = device;
}

Demo

Hazırladığım demo'da, Gamepad API ve WebHID API tarafından ortaklaşa kontrol edilen Stadia kumandasını görebilirsiniz. Bu makaledeki snippet'leri temel alan kaynak koda göz atın. Basitlik açısından yalnızca A, B, X ve Y düğmelerini (Gamepad API tarafından kontrol edilir) ve Asistan ile Kayıt düğmelerini (WebHID API tarafından kontrol edilir) göstereceğiz. Denetleyici resminin altında, ham WebHID verilerini görebilirsiniz. Böylece, denetleyicideki tüm düğmeleri ve eksenleri anlayabilirsiniz.

A, B, X ve Y düğmelerinin Gamepad API tarafından, Asistan ve Kayıt düğmelerinin ise WebHID API tarafından kontrol edildiğini gösteren https://stadia-controller-webhid-gamepad.glitch.me/ adresindeki demo uygulama.

Sonuçlar

Yeni donanım yazılımı sayesinde Stadia Kumanda artık 17 düğmeli standart bir oyun kumandası olarak kullanılabilir. Bu, çoğu durumda yaygın web oyunlarını kontrol etmek için fazlasıyla yeterlidir. Herhangi bir nedenle kumandadaki 19 düğmenin tümünün verilerine ihtiyacınız varsa WebHID, düşük düzey giriş raporlarına erişmenize olanak tanır. Bu raporları tek tek tersine mühendislik yaparak çözebilirsiniz. Bu makaleyi okuduktan sonra eksiksiz bir WebHID sürücüsü yazarsanız benimle iletişime geçmeyi unutmayın. Projenizi buradan memnuniyetle bağlayacağım. Web'de gizlilik için iyi günler dileriz.

Teşekkür ederiz

Bu makale François Beaufort tarafından incelenmiştir.