صحبت کردن با کنترلر Stadia با WebHID

کنترلر فلش شده Stadia مانند یک گیم پد استاندارد عمل می کند، به این معنی که همه دکمه های آن با استفاده از Gamepad API قابل دسترسی نیستند. با WebHID، اکنون می توانید به دکمه های گم شده دسترسی داشته باشید.

از زمانی که Stadia تعطیل شد، بسیاری می ترسیدند که این کنترلر به عنوان یک قطعه سخت افزاری بی مصرف در محل دفن زباله تبدیل شود. خوشبختانه، تیم Stadia تصمیم گرفته است که در عوض کنترلر Stadia را با ارائه یک سیستم عامل سفارشی باز کند که می توانید با رفتن به صفحه حالت بلوتوث Stadia روی کنترلر خود فلش کنید. این باعث می شود که کنترلر Stadia شما به عنوان یک گیم پد استاندارد ظاهر شود که می توانید از طریق کابل USB یا به صورت بی سیم از طریق بلوتوث به آن متصل شوید. صفحه بلوتوث Stadia با افتخار در Project Fugu API Showcase از WebHID و WebUSB استفاده می کند، اما موضوع این مقاله نیست. در این پست می خواهم توضیح دهم که چگونه می توانید از طریق WebHID با کنترلر Stadia صحبت کنید.

کنترلر Stadia به عنوان یک گیم پد استاندارد

پس از فلش، کنترلر به عنوان یک گیم پد استاندارد برای سیستم عامل ظاهر می شود. برای چیدمان دکمه‌ها و محورهای رایج در یک گیم‌پد استاندارد، تصویر زیر را ببینید. همانطور که در مشخصات API Gamepad تعریف شده است، گیم پدهای استاندارد دارای دکمه هایی از 0 تا 16 هستند، بنابراین در مجموع 17 (د-پد به عنوان چهار دکمه محاسبه می شود). اگر کنترلر Stadia را در نسخه ی نمایشی تستر گیم پد امتحان کنید، متوجه خواهید شد که مانند یک جذابیت عمل می کند.

طرحی از یک گیم پد استاندارد با محورها و دکمه های مختلف برچسب گذاری شده است.

با این حال، اگر دکمه های روی کنترلر Stadia را بشمارید، 19 عدد وجود دارد. اگر آنها را به صورت سیستماتیک یکی یکی در تست کننده گیم پد امتحان کنید، متوجه خواهید شد که دکمه های Assistant و Capture کار نمی کنند. حتی اگر ویژگی buttons گیم‌پد همانطور که در مشخصات Gamepad تعریف شده است، باز باشد، از آنجایی که کنترل‌کننده Stadia به‌عنوان یک گیم‌پد استاندارد ظاهر می‌شود، فقط دکمه‌های 0-16 ترسیم می‌شوند. همچنان می‌توانید از دکمه‌های دیگر استفاده کنید، اما اکثر بازی‌ها انتظار وجود آن‌ها را ندارند.

WebHID برای نجات

به لطف WebHID API، می‌توانید با دکمه‌های گمشده 17 و 18 صحبت کنید. و اگر واقعاً می‌خواهید، حتی می‌توانید اطلاعات مربوط به همه دکمه‌ها و محورهای دیگری را که از قبل از طریق Gamepad API در دسترس هستند، دریافت کنید. اولین قدم این است که بفهمید چگونه کنترلر Stadia خود را به سیستم عامل گزارش می دهد. یکی از راه‌های انجام این کار، باز کردن Chrome DevTools Console در هر صفحه تصادفی و درخواست فهرست فیلتر نشده از دستگاه‌ها از WebHID API است. سپس به صورت دستی کنترلر Stadia را برای بازرسی بیشتر انتخاب کنید. به سادگی با عبور از یک آرایه گزینه های filters خالی، یک لیست فیلتر نشده از دستگاه ها را دریافت کنید.

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

در انتخابگر، ورودی ماقبل آخر شبیه کنترلر Stadia است.

انتخابگر دستگاه WebHID API که برخی از دستگاه‌های نامرتبط را نشان می‌دهد و کنترل‌کننده Stadia در موقعیت ماقبل آخر قرار دارد.

پس از انتخاب دستگاه «Stadia Controller rev. A»، شی HIDDevice حاصل را در کنسول ثبت کنید. این نشان می دهد productId کنترلر Stadia ( 37888 که 0x9400 در هگز) و vendorId ( 6353 که 0x18d1 در هگز است). اگر vendorID در جدول رسمی شناسه فروشنده USB جستجو کنید، خواهید دید که 6353 با آنچه شما انتظار دارید مطابقت دارد: Google Inc.

Chrome DevTools Console خروجی ثبت شی HIDDevice را نشان می دهد.

یک جایگزین برای جریان توضیح داده شده در بالا، پیمایش به chrome://device-log/ در نوار URL، فشار دادن دکمه Clear ، وصل کردن کنترلر Stadia و سپس فشار دادن Refresh است. این اطلاعات مشابهی را در اختیار شما قرار می دهد.

رابط اشکال‌زدایی chrome://device-log که اطلاعات مربوط به کنترلر Stadia را نشان می‌دهد.

گزینه دیگر استفاده از ابزار HID Explorer است که به شما امکان می دهد جزئیات بیشتری از دستگاه های HID متصل به رایانه خود را کشف کنید.

از این دو شناسه، vendorId و productId استفاده کنید تا با فیلتر کردن صحیح دستگاه WebHID مناسب، آنچه در انتخابگر نشان داده شده است را اصلاح کنید.

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

اکنون نویز تمام دستگاه های غیرمرتبط از بین رفته است و فقط کنترلر Stadia ظاهر می شود.

انتخابگر دستگاه WebHID API که فقط کنترلر Stadia را نشان می دهد.

در مرحله بعد، HIDDevice با فراخوانی متد open() باز کنید.

await stadiaController.open();

HIDDevice را دوباره وارد کنید و پرچم opened روی true تنظیم شود.

Chrome DevTools Console خروجی ثبت شیء HIDDevice را پس از باز کردن آن نشان می دهد.

با باز بودن دستگاه، با پیوست کردن شنونده رویداد، به رویدادهای inputreport ورودی گوش دهید.

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

وقتی دکمه Assistant را روی کنترلر فشار می دهید و رها می کنید، دو رویداد در کنسول ثبت می شود. می‌توانید آنها را به‌عنوان رویدادهای «دکمه پایین دستیار » و «دکمه دستیار بالا» در نظر بگیرید. جدا از timeStamp ، این دو رویداد در نگاه اول غیرقابل تشخیص به نظر می رسند.

کنسول Chrome DevTools که اشیاء HIDInputReportEvent را در حال ثبت نشان می دهد.

ویژگی reportId رابط HIDInputReportEvent پیشوند شناسایی یک بایتی را برای این گزارش برمی‌گرداند، یا اگر رابط HID از شناسه‌های گزارش استفاده نکند، 0 برمی‌گرداند. در این مورد 3 است. راز در ویژگی data است که به عنوان یک DataView با اندازه 10 نشان داده می شود. یک DataView یک رابط سطح پایین برای خواندن و نوشتن انواع اعداد متعدد در یک ArrayBuffer باینری فراهم می کند. راه برای به دست آوردن چیزی قابل هضم تر از این نمایش، ایجاد یک Uint8Array از ArrayBuffer است، بنابراین شما می توانید اعداد صحیح بدون علامت 8 بیتی را مشاهده کنید.

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

هنگامی که مجدداً داده‌های رویداد گزارش ورودی را ثبت می‌کنید، همه چیز معنادارتر می‌شود و رویدادهای «دکمه پایین دستیار » و «دکمه دستیار بالا» قابل رمزگشایی می‌شوند. به نظر می رسد عدد صحیح اول ( 8 در هر دو رویداد) مربوط به فشار دادن دکمه ها باشد و عدد صحیح دوم ( 2 و 0 ) به نظر می رسد که مربوط به فشار دادن دکمه Assistant باشد یا خیر.

کنسول Chrome DevTools که اشیاء Uint8Array را نشان می دهد که برای هر HIDInputReportEvent ثبت شده اند.

دکمه Capture را به جای دکمه Assistant فشار دهید و خواهید دید که عدد صحیح دوم از 1 با فشار دادن دکمه به 0 تغییر می کند. این به شما امکان می دهد یک "درایور" بسیار ساده بنویسید که به شما امکان می دهد از دو دکمه از دست رفته استفاده کنید.

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

با استفاده از یک رویکرد مهندسی معکوس مانند این، می توانید، دکمه به دکمه و محور به محور، نحوه صحبت کردن با کنترلر Stadia با WebHID را بیابید. وقتی به آن دست پیدا کردید، بقیه کار تقریباً مکانیکی نگاشت عدد صحیح است.

تنها چیزی که در حال حاضر از دست داده است، تجربه اتصال روانی است که Gamepad API در اختیار شما قرار می دهد. در حالی که به دلایل امنیتی، برای کار با یک دستگاه WebHID مانند کنترلر Stadia، همیشه باید یک بار تجربه انتخاب کننده اولیه را انجام دهید، برای اتصالات بعدی، می توانید دوباره به دستگاه های شناخته شده متصل شوید. این کار را با فراخوانی متد getDevices() انجام دهید.

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

نسخه ی نمایشی

می‌توانید کنترل‌کننده Stadia را که به طور مشترک توسط Gamepad API و WebHID API کنترل می‌شود، در نسخه‌ای که من ساخته‌ام مشاهده کنید. حتماً کد منبع را که بر اساس قطعات این مقاله است، بررسی کنید. برای سادگی، من فقط دکمه‌های A ، B ، X و Y (که توسط Gamepad API کنترل می‌شود)، و دکمه‌های Assistant و Capture (که توسط WebHID API کنترل می‌شوند) را نمایش می‌دهم. در زیر تصویر کنترلر، می‌توانید داده‌های خام WebHID را ببینید، بنابراین می‌توانید احساسی نسبت به تمام دکمه‌ها و محورهای روی کنترل‌کننده داشته باشید.

برنامه نمایشی در https://stadia-controller-webhid-gamepad.glitch.me/ نشان می دهد که دکمه های A، B، X و Y توسط Gamepad API کنترل می شوند و دکمه های Assistant و Capture توسط WebHID API.

نتیجه گیری

به لطف سیستم عامل جدید، کنترلر Stadia اکنون به عنوان یک گیم پد استاندارد با 17 دکمه قابل استفاده است که در اکثر موارد برای کنترل بازی های رایج وب کافی است. اگر به هر دلیلی به داده‌هایی از 19 دکمه روی کنترلر نیاز دارید، WebHID به شما امکان می‌دهد به گزارش‌های ورودی سطح پایین دسترسی داشته باشید که می‌توانید با مهندسی معکوس یک به یک آنها را رمزگشایی کنید. اگر بعد از خواندن این مقاله یک درایور WebHID کامل نوشتید، حتما با من تماس بگیرید و من با خوشحالی پروژه شما را در اینجا پیوند خواهم داد. WebHIDing مبارک!

قدردانی

این مقاله توسط فرانسوا بوفور بررسی شده است.