Stadia Controller ที่กะพริบจะทำหน้าที่เหมือนเกมแพดมาตรฐาน ซึ่งหมายความว่าคุณจะใช้ Gamepad API เข้าถึงปุ่มบางปุ่มไม่ได้ ตอนนี้คุณจะเข้าถึงปุ่มที่หายไปได้แล้วโดยใช้ WebHID
นับตั้งแต่ที่ Stadia ปิดตัวลง หลายคนกลัวว่าตัวควบคุมจะกลายเป็นชิ้นส่วนของฮาร์ดแวร์ที่ไร้ประโยชน์ในหลุมฝังกลบ โชคดีที่ทีม Stadia ตัดสินใจเปิด Stadia Controller แทนโดยให้มีเฟิร์มแวร์แบบกำหนดเอง ซึ่งคุณจะแฟลชในคอนโทรลเลอร์ได้โดยไปที่หน้าโหมดบลูทูธ Stadia ซึ่งจะทำให้ Stadia Controller มีลักษณะเหมือนเกมแพดมาตรฐาน ซึ่งคุณจะเชื่อมต่อผ่านสาย USB หรือแบบไร้สายผ่านบลูทูธได้ หน้าบลูทูธของ Stadia ได้นำเสนออย่างภาคภูมิใจใน Project Fugu API Showcase โดยใช้ WebHID และ WebUSB แต่ไม่ใช่หัวข้อของบทความนี้ ในโพสต์นี้ ฉันจะอธิบายวิธีพูดคุยกับ Stadia Controller ผ่าน WebHID
Stadia Controller เป็นเกมแพดมาตรฐาน
หลังจากกะพริบ ตัวควบคุมจะปรากฏเป็นเกมแพดมาตรฐานในระบบปฏิบัติการ ดูภาพหน้าจอต่อไปนี้สำหรับการจัดเรียงปุ่มและแกนทั่วไปบนเกมแพดมาตรฐาน ตามที่ระบุไว้ในข้อมูลจำเพาะของ Gamepad API เกมแพดมาตรฐานจะมีปุ่มตั้งแต่ 0 ถึง 16 ดังนั้นทั้งหมดจะมี 17 ปุ่ม (D-pad จะนับเป็น 4 ปุ่ม) หากลองใช้ Stadia Controller ในการสาธิตเกมแพด คุณจะสังเกตได้ว่าเครื่องมือนี้ใช้งานได้ราวกับมีเสน่ห์
แต่ถ้านับปุ่มบน Stadia Controller จะมีทั้งหมด 19 ปุ่ม หากลองใช้การทดสอบเกมแพดทีละรายการ คุณจะพบว่าปุ่ม Assistant และปุ่มจับภาพจะไม่ทำงาน แม้ว่าแอตทริบิวต์ buttons
ของเกมแพดที่ระบุไว้ในข้อกำหนดของเกมแพดจะเป็นแบบปลายเปิด เนื่องจาก Stadia Controller มีลักษณะเป็นเกมแพดมาตรฐาน ระบบจะแมปเฉพาะปุ่ม 0–16 เท่านั้น คุณยังคงใช้ปุ่มอื่นๆ ได้ แต่เกมส่วนใหญ่จะไม่คิดว่าจะมีปุ่มเหล่านั้นอยู่
WebHID ช่วยเหลือคุณได้
WebHID API ช่วยให้คุณทราบถึงปุ่ม 17 และ 18 ที่ขาดหายไป และหากต้องการจริงๆ คุณสามารถดูข้อมูลเกี่ยวกับปุ่มและแกนอื่นๆ ทั้งหมดที่มีผ่าน Gamepad API ได้แล้ว ขั้นตอนแรกคือดูว่า Stadia Controller รายงานตัวเองไปยังระบบปฏิบัติการอย่างไร วิธีหนึ่งคือการเปิดคอนโซลเครื่องมือสำหรับนักพัฒนาเว็บใน Chrome ในหน้าใดก็ได้แบบสุ่ม แล้วขอรายการอุปกรณ์ที่ไม่มีการกรองจาก WebHID API จากนั้นเลือก Stadia Controller ด้วยตนเองเพื่อตรวจสอบเพิ่มเติม ดูรายการอุปกรณ์ที่ไม่มีการกรองได้โดยส่งอาร์เรย์ตัวเลือก filters
ที่ว่างเปล่า
const [device] = await navigator.hid.requestDevice({filters: []});
ในเครื่องมือเลือก รายการสุดท้ายจะมีลักษณะคล้ายกับ Stadia Controller
หลังจากเลือกอุปกรณ์ "Stadia Controller rev. A" แล้ว ให้บันทึกออบเจ็กต์ HIDDevice
ที่ได้ไปยังคอนโซล ซึ่งจะแสดง productId
(37888
ซึ่งเป็น 0x9400
ในเลขฐาน 16) และ vendorId
(6353
ซึ่ง 0x18d1
ในเลขฐานสิบหก) ของ Stadia Controller หากค้นหา vendorID
ในตารางรหัสผู้ให้บริการ USB อย่างเป็นทางการ คุณจะเห็นว่า 6353
จับคู่กับสิ่งที่คุณคาดหวัง ได้แก่ Google Inc.
อีกทางเลือกหนึ่งนอกเหนือจากขั้นตอนที่อธิบายไว้ข้างต้นคือการไปที่ chrome://device-log/
ในแถบ URL การกดปุ่มล้าง เสียบปลั๊ก Stadia Controller แล้วกดรีเฟรช วิธีการนี้จะให้ข้อมูลเดียวกันแก่คุณ
อีกวิธีหนึ่งคือการใช้เครื่องมือ HID Explorer ซึ่งจะช่วยให้คุณสำรวจรายละเอียดเพิ่มเติมของอุปกรณ์ HID ที่เชื่อมต่อกับคอมพิวเตอร์ได้
ใช้รหัส 2 รายการนี้ ได้แก่ vendorId
และ productId
เพื่อปรับแต่งสิ่งที่แสดงในเครื่องมือเลือกด้วยการกรองอุปกรณ์ WebHID ที่เหมาะสมได้อย่างถูกต้องแล้ว
const [stadiaController] = await navigator.hid.requestDevice({filters: [{
vendorId: 6353,
productId: 37888,
}]});
ตอนนี้เสียงจากอุปกรณ์ที่ไม่เกี่ยวข้องทั้งหมดจะหายไป และมีเพียง Stadia Controller เท่านั้นที่แสดงขึ้น
ถัดไป ให้เปิด HIDDevice
โดยเรียกใช้เมธอด open()
await stadiaController.open();
บันทึก HIDDevice
อีกครั้งและตั้งค่าแฟล็ก opened
เป็น true
เมื่ออุปกรณ์เปิดอยู่ ให้คอยฟังเหตุการณ์ inputreport
ที่เข้ามาใหม่โดยแนบ Listener เหตุการณ์
stadiaController.addEventListener('inputreport', (e) => {
console.log(e);
});
เมื่อคุณกดปุ่ม Assistant บนตัวควบคุมแล้วปล่อย ระบบจะบันทึก 2 เหตุการณ์ลงในคอนโซล กล่าวคือเป็นเหตุการณ์ "ปุ่ม Assistant" และ "ปุ่ม Assistant ขึ้น" นอกจาก timeStamp
แล้ว ทั้ง 2 เหตุการณ์ดูกลมกลืนกันอย่างไม่น่าเชื่อเมื่ออ่านครั้งแรก
พร็อพเพอร์ตี้ reportId
ของอินเทอร์เฟซ HIDInputReportEvent
จะแสดงคำนำหน้าการระบุไบต์แบบ 1 ไบต์สำหรับรายงานนี้ หรือ 0
หากอินเทอร์เฟซ HID ไม่ได้ใช้รหัสรายงาน ในกรณีนี้คือ 3
ข้อมูลลับอยู่ในพร็อพเพอร์ตี้ data
ซึ่งแสดงเป็น DataView
ขนาด 10 DataView
มีอินเทอร์เฟซระดับต่ำสำหรับการอ่านและเขียนประเภทตัวเลขหลายประเภทในไบนารี ArrayBuffer
วิธีที่จะทำให้เข้าใจมากขึ้นจากการนำเสนอนี้คือการสร้าง Uint8Array
จาก ArrayBuffer
เพื่อให้คุณดูจำนวนเต็มที่ไม่มีเครื่องหมาย 8 บิตได้ทีละตัว
const data = new Uint8Array(event.data.buffer);
เมื่อบันทึกข้อมูลเหตุการณ์ของรายงานอินพุตอีกครั้ง เหตุการณ์จะเริ่มสมเหตุสมผลมากขึ้น เหตุการณ์ของปุ่ม "Assistant" และปุ่ม "Assistant ขึ้น" จะเริ่มถอดรหัสได้ ดูเหมือนว่าจำนวนเต็มแรก (8
ในทั้ง 2 เหตุการณ์) จะเกี่ยวข้องกับการกดปุ่ม และจำนวนเต็มที่ 2 (2
และ 0
) ดูเหมือนจะเกี่ยวข้องกับการกดปุ่ม Assistant หรือไม่
กดปุ่มจับภาพแทนปุ่ม Assistant คุณจะเห็นเลขจำนวนเต็มที่ 2 สลับจาก 1
เมื่อกดปุ่มเป็น 0
เมื่อปล่อยปุ่ม วิธีนี้ช่วยให้คุณเขียน "ไดรเวอร์" ที่เรียบง่ายมากๆ ซึ่งจะช่วยให้คุณใช้ปุ่มที่หายไป 2 ปุ่มได้
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 Controller ด้วย WebHID ได้ เมื่อเข้าใจแล้ว ส่วนที่เหลือจะเป็นการจับคู่จำนวนเต็มทางกลแบบเชิงกล
สิ่งหนึ่งที่หายไปในตอนนี้คือประสบการณ์การเชื่อมต่อที่ราบรื่นจาก Gamepad API ให้คุณ แม้ว่าคุณจะต้องดำเนินการผ่านเครื่องมือเลือกเริ่มต้น 1 ครั้งเพื่อการใช้งานอุปกรณ์ WebHID เช่น Stadia Controller สำหรับการเชื่อมต่อในอนาคต คุณจะเชื่อมต่อกับอุปกรณ์ที่รู้จักได้อีกครั้งเนื่องด้วยเหตุผลด้านความปลอดภัย ซึ่งทำได้โดยเรียกใช้เมธอด getDevices()
let stadiaController;
const [device] = await navigator.hid.getDevices();
if (device && device.vendorId === 6353 && device.productId === 37888) {
stadiaController = device;
}
ข้อมูลประชากร
คุณดู Stadia Controller ที่ควบคุมร่วมกันโดย Gamepad API และ WebHID API ได้ในการสาธิตที่สร้างขึ้น อย่าลืมดูซอร์สโค้ด ซึ่งต่อยอดมาจากข้อมูลโค้ดจากบทความนี้ เพื่อให้เข้าใจง่าย เราจะแสดงเฉพาะปุ่ม A, B, X และ Y (ควบคุมโดย Gamepad API) รวมถึงปุ่ม Assistant และปุ่มจับภาพ (ควบคุมโดย WebHID API) ใต้รูปภาพตัวควบคุม คุณจะเห็นข้อมูลดิบ WebHID ที่จะช่วยให้คุณเห็นปุ่มและแกนทั้งหมดในตัวควบคุมได้
บทสรุป
เฟิร์มแวร์ใหม่ทำให้ Stadia Controller ใช้เป็นเกมแพดแบบมาตรฐานที่มี 17 ปุ่มได้ ซึ่งในกรณีส่วนใหญ่ก็เกินพอที่จะควบคุมเกมในเว็บทั่วไปได้แล้ว ไม่ว่าคุณจะต้องการข้อมูลจากปุ่มทั้ง 19 ปุ่มบนตัวควบคุมไม่ว่าด้วยเหตุผลใดก็ตาม WebHID จะช่วยให้คุณเข้าถึงรายงานอินพุตระดับต่ำซึ่งถอดรหัสได้ด้วยการทำวิศวกรรมย้อนกลับทีละรายการ หากคุณบังเอิญเขียนไดรเวอร์ WebHID ที่สมบูรณ์หลังจากอ่านบทความนี้ โปรดติดต่อฉัน และเรายินดีที่จะลิงก์โปรเจ็กต์ของคุณที่นี่ ขอให้สนุกกับ WebHIDing!
ข้อความแสดงการยอมรับ
บทความนี้ได้รับการตรวจสอบโดย François Beaufort