جارٍ التحدّث إلى وحدة تحكّم Stadia باستخدام WebHID

تعمل وحدة تحكّم Stadia التي تم فلاشها مثل ذراع تحكم عادي في الألعاب، ما يعني أنّه لا يمكن الوصول إلى جميع أزرارها باستخدام Gamepad API. باستخدام WebHID، يمكنك الآن الوصول إلى الأزرار غير المتوفّرة.

منذ إيقاف Stadia، خشى الكثيرون أن تنتهي وحدة التحكّم كقطعة أجهزة غير مفيدة في مكبّر النفايات. لحسن الحظ، قرّر فريق Stadia فتح وحدة تحكّم Stadia من خلال توفير برنامج ثابت مخصّص يمكنك تثبيته على وحدة التحكّم من خلال الانتقال إلى صفحة وضع البلوتوث في Stadia. يؤدي ذلك إلى ظهور وحدة تحكّم Stadia كوحدة تحكّم عادية في الألعاب يمكنك ربطها عبر كابل USB أو لاسلكيًا عبر البلوتوث. إنّ صفحة Stadia Bluetooth التي تم عرضها بفخر في Project Fugu API Showcase تستخدم WebHID وWebUSB، ولكنّ هذا ليس موضوع هذه المقالة. في هذه المشاركة، سأشرح كيفية التحدّث إلى وحدة تحكّم Stadia عبر WebHID.

استخدام وحدة تحكّم Stadia كجهاز تحكّم عادي في الألعاب

بعد الفلاش، ستظهر وحدة التحكّم لنظام التشغيل على أنّها وحدة تحكّم ألعاب عادية. اطّلِع على لقطة الشاشة التالية لمعرفة ترتيب الأزرار والمحاور الشائع على جهاز تحكم ألعاب عادي. وفقًا لما هو محدّد في مواصفات Gamepad API، تحتوي أجهزة التحكّم في الألعاب العادية على أزرار من 0 إلى 16، أي 17 زرًا في المجمل (يُحتسَب لوحة التوجيه على أنّها أربعة أزرار). إذا جرّبت وحدة تحكّم Stadia في الإصدار التجريبي من أداة اختبار لوحات الألعاب، ستلاحظ أنّها تعمل على أكمل وجه.

مخطّط لوحدة تحكم ألعاب عادية مع تصنيف المحاور والأزرار المختلفة

ومع ذلك، إذا احتسبت عدد الأزرار على وحدة تحكّم Stadia، ستجد أنّها 19 زرًا. إذا جرّبت الأزرار بشكل منهجي واحدًا تلو الآخر في أداة اختبار لوحة الألعاب، ستلاحظ أنّ زرَّي المساعد والتقاط لا يعملان. حتى إذا كانت سمة جهاز التحكّم في الألعاب buttons كما هو محدّد في مواصفات جهاز التحكّم في الألعاب مفتوحة، يتمّ ربط الأزرار من 0 إلى 16 فقط لأنّ وحدة تحكّم Stadia تظهر كجهاز تحكّم عادي في الألعاب. سيظل بإمكانك استخدام الأزرار الأخرى، ولكن لن تتوقع معظم الألعاب وجودها.

استخدام WebHID لتقديم المساعدة

بفضل WebHID API، يمكنك التحدث إلى الزرَّين 17 و18 غير المتوفّرين. وإذا أردت، يمكنك أيضًا الحصول على بيانات عن جميع الأزرار والمحاور الأخرى المتاحة حاليًا من خلال Gamepad API. الخطوة الأولى هي معرفة كيفية إبلاغ وحدة تحكّم Stadia ببياناتها لنظام التشغيل. وتتوفّر طريقة واحدة لإجراء ذلك وهي فتح "وحدة تحكّم أدوات مطوّري البرامج في Chrome" على أي صفحة عشوائية وطلب قائمة غير مفلتَرة بالأجهزة من WebHID API. يمكنك بعد ذلك اختيار وحدة تحكّم Stadia يدويًا لإجراء مزيد من الفحص. يمكنك الحصول على قائمة غير مفلتَرة بالأجهزة من خلال تمرير صفيف خيارات filters فارغ.

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

في أداة الاختيار، يبدو الإدخال قبل الأخير مثل وحدة تحكّم Stadia.

أداة اختيار الأجهزة في WebHID API تعرِض بعض الأجهزة غير ذات الصلة، ووحدة تحكّم Stadia في الموضع قبل الأخير

بعد اختيار جهاز "Stadia Controller rev. A"، سجِّل عنصر HIDDevice الناتج في وحدة التحكّم. يكشف ذلك عن productId (37888، أي 0x9400 في نظام الترميز الست عشري) وvendorId (6353، أي 0x18d1 في نظام الترميز الست عشري) لوحدة تحكّم Stadia. إذا بحثت عن vendorID في جدول معرّفات مورّدي USB الرسمي، ستلاحظ أنّ 6353 يرتبط بما تتوقّعه: Google Inc..

وحدة تحكّم أدوات مطوري البرامج في Chrome تعرض نتيجة تسجيل عنصر HIDDevice

يمكنك اتّباع مسار بديل للخطوات الموضّحة أعلاه، وهو الانتقال إلى chrome://device-log/ في شريط عنوان URL، والضغط على الزر محو، ثم توصيل وحدة تحكّم Stadia، ثم الضغط على تحديث. يوفّر لك هذا الإجراء المعلومات نفسها.

واجهة تصحيح الأخطاء 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 تعرض نتيجة تسجيل عنصر HIDDevice بعد فتحه.

مع فتح الجهاز، انتظِر وصول أحداث inputreport من خلال إرفاق أداة معالجة أحداث.

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

عند الضغط على زر مساعد Google في وحدة التحكّم ثم رفع إصبعك عنه، يتم تسجيل حدثَين في وحدة التحكّم. يمكنك اعتبارهما حدثَي "ضغطة زر مساعد Google" و "رفع الضغط عن زر مساعد Google". باستثناء timeStamp، يبدو أنّ الحدثَين متطابقَين للوهلة الأولى.

وحدة تحكّم "أدوات مطوّري البرامج في Chrome" تعرض كائنات HIDInputReportEvent التي يتم تسجيلها

تعرض سمة reportId لواجهة HIDInputReportEvent بادئة التعريف التي تبلغ بايتة واحدة لهذا التقرير، أو 0 إذا كانت واجهة HID لا تستخدِم أرقام تعريف التقارير. في هذه الحالة، يكون 3. يكمن السر في السمة data، والتي يتم تمثيلها على شكل DataView بحجم 10. يوفّر DataView واجهة من المستوى الأدنى لقراءة وكتابة أنواع أرقام متعددة في ArrayBuffer ثنائي. للحصول على تمثيل أكثر سهولة من هذا التمثيل، يمكنك إنشاء Uint8Array من ArrayBuffer، حتى تتمكّن من الاطّلاع على الأعداد الصحيحة الفردية التي تبلغ 8 بت وغير الموقّعة.

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

عند تسجيل بيانات أحداث تقارير الإدخال مرة أخرى، تبدأ الأمور في الوضوح أكثر ويصبح من الممكن فك ترميز أحداث "زرّ المساعِد مطبوع" و "زرّ المساعِد مرفوع". يبدو أنّ الرقم الصحيح الأول (8 في كلا الحدثَين) مرتبط بالضغط على الأزرار، ويبدو أنّ الرقم الصحيح الثاني (2 و0) مرتبط بما إذا تم الضغط على زر مساعد Google أم لا.

وحدة تحكّم "أدوات مطوّري البرامج في Chrome" تعرض عناصر Uint8Array التي يتم تسجيلها لكل حدث HIDInputReportEvent.

اضغط على زر التقاط بدلاً من زر مساعد Google، وستلاحظ أنّ الرقم الصحيح الثاني ينتقل من 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) والأزرار مساعِد والتقاط (التي يتم التحكّم فيها من خلال WebHID API). أسفل صورة جهاز التحكّم، يمكنك الاطّلاع على بيانات WebHID الأوّلية، ما يتيح لك التعرّف على جميع الأزرار والمحاور في جهاز التحكّم.

يعرض التطبيق التجريبي على الرابط https://stadia-controller-webhid-gamepad.glitch.me/ أزرار A وB وX وY التي يتم التحكّم فيها من خلال Gamepad API، وزرَّي "مساعد Google" و"تسجيل" اللذَين يتم التحكّم فيهما من خلال WebHID API.

الاستنتاجات

بفضل البرامج الثابتة الجديدة، يمكن الآن استخدام وحدة تحكّم Stadia كوحدة تحكّم ألعاب عادية تتضمّن 17 زرًا، وهو عدد كافٍ في معظم الحالات للتحكّم في ألعاب الويب الشائعة. إذا كنت بحاجة إلى بيانات من جميع الأزرار الـ 19 على وحدة التحكّم لأي سبب، يتيح لك WebHID الوصول إلى تقارير الإدخال من المستوى الأدنى التي يمكنك فك ترميزها من خلال الهندسة العكسية لها واحدًا تلو الآخر. إذا كتبت برنامج تشغيل WebHID كاملاً بعد قراءة هذه المقالة، يُرجى التواصل معي، وسيسرّني ربط مشروعك هنا. مع أطيب التحيّات،

الشكر والتقدير

راجع فاروق فريد هذه المقالة.