کنترلر فلش شده 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 است.
پس از انتخاب دستگاه «Stadia Controller rev. A»، شی HIDDevice
حاصل را در کنسول ثبت کنید. این نشان می دهد productId
کنترلر Stadia ( 37888
که 0x9400
در هگز) و vendorId
( 6353
که 0x18d1
در هگز است). اگر vendorID
در جدول رسمی شناسه فروشنده USB جستجو کنید، خواهید دید که 6353
با آنچه شما انتظار دارید مطابقت دارد: Google Inc.
یک جایگزین برای جریان توضیح داده شده در بالا، پیمایش به chrome://device-log/
در نوار URL، فشار دادن دکمه Clear ، وصل کردن کنترلر Stadia و سپس فشار دادن Refresh است. این اطلاعات مشابهی را در اختیار شما قرار می دهد.
گزینه دیگر استفاده از ابزار HID Explorer است که به شما امکان می دهد جزئیات بیشتری از دستگاه های HID متصل به رایانه خود را کشف کنید.
از این دو شناسه، vendorId
و productId
استفاده کنید تا با فیلتر کردن صحیح دستگاه WebHID مناسب، آنچه در انتخابگر نشان داده شده است را اصلاح کنید.
const [stadiaController] = await navigator.hid.requestDevice({filters: [{
vendorId: 6353,
productId: 37888,
}]});
اکنون نویز تمام دستگاه های غیرمرتبط از بین رفته است و فقط کنترلر Stadia ظاهر می شود.
در مرحله بعد، HIDDevice
با فراخوانی متد open()
باز کنید.
await stadiaController.open();
HIDDevice
را دوباره وارد کنید و پرچم opened
روی true
تنظیم شود.
با باز بودن دستگاه، با پیوست کردن شنونده رویداد، به رویدادهای inputreport
ورودی گوش دهید.
stadiaController.addEventListener('inputreport', (e) => {
console.log(e);
});
وقتی دکمه Assistant را روی کنترلر فشار می دهید و رها می کنید، دو رویداد در کنسول ثبت می شود. میتوانید آنها را بهعنوان رویدادهای «دکمه پایین دستیار » و «دکمه دستیار بالا» در نظر بگیرید. جدا از timeStamp
، این دو رویداد در نگاه اول غیرقابل تشخیص به نظر می رسند.
ویژگی reportId
رابط HIDInputReportEvent
پیشوند شناسایی یک بایتی را برای این گزارش برمیگرداند، یا اگر رابط HID از شناسههای گزارش استفاده نکند، 0
برمیگرداند. در این مورد 3
است. راز در ویژگی data
است که به عنوان یک DataView
با اندازه 10 نشان داده می شود. یک DataView
یک رابط سطح پایین برای خواندن و نوشتن انواع اعداد متعدد در یک ArrayBuffer
باینری فراهم می کند. راه برای به دست آوردن چیزی قابل هضم تر از این نمایش، ایجاد یک Uint8Array
از ArrayBuffer
است، بنابراین شما می توانید اعداد صحیح بدون علامت 8 بیتی را مشاهده کنید.
const data = new Uint8Array(event.data.buffer);
هنگامی که مجدداً دادههای رویداد گزارش ورودی را ثبت میکنید، همه چیز معنادارتر میشود و رویدادهای «دکمه پایین دستیار » و «دکمه دستیار بالا» قابل رمزگشایی میشوند. به نظر می رسد عدد صحیح اول ( 8
در هر دو رویداد) مربوط به فشار دادن دکمه ها باشد و عدد صحیح دوم ( 2
و 0
) به نظر می رسد که مربوط به فشار دادن دکمه Assistant باشد یا خیر.
دکمه 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 را ببینید، بنابراین میتوانید احساسی نسبت به تمام دکمهها و محورهای روی کنترلکننده داشته باشید.
نتیجه گیری
به لطف سیستم عامل جدید، کنترلر Stadia اکنون به عنوان یک گیم پد استاندارد با 17 دکمه قابل استفاده است که در اکثر موارد برای کنترل بازی های رایج وب کافی است. اگر به هر دلیلی به دادههایی از 19 دکمه روی کنترلر نیاز دارید، WebHID به شما امکان میدهد به گزارشهای ورودی سطح پایین دسترسی داشته باشید که میتوانید با مهندسی معکوس یک به یک آنها را رمزگشایی کنید. اگر بعد از خواندن این مقاله یک درایور WebHID کامل نوشتید، حتما با من تماس بگیرید و من با خوشحالی پروژه شما را در اینجا پیوند خواهم داد. WebHIDing مبارک!
قدردانی
این مقاله توسط فرانسوا بوفور بررسی شده است.