Tay điều khiển Stadia đã được cài đặt ROM hoạt động như một tay điều khiển trò chơi tiêu chuẩn, tức là không phải tất cả các nút của tay điều khiển đều có thể truy cập được bằng Gamepad API. Giờ đây, với WebHID, bạn có thể truy cập vào các nút bị thiếu.
Kể từ khi Stadia ngừng hoạt động, nhiều người lo ngại rằng tay điều khiển này sẽ trở thành một phần cứng vô dụng trên bãi rác. May mắn thay, nhóm Stadia đã quyết định mở khoá tay điều khiển Stadia bằng cách cung cấp một phần mềm tuỳ chỉnh mà bạn có thể cài đặt trên tay điều khiển bằng cách truy cập vào trang Chế độ Bluetooth của Stadia. Thao tác này sẽ khiến tay điều khiển Stadia xuất hiện dưới dạng tay điều khiển trò chơi tiêu chuẩn mà bạn có thể kết nối qua cáp USB hoặc không dây qua Bluetooth. Tự hào nằm trong phần giới thiệu API của Project Fugu, trang Bluetooth của Stadia sử dụng WebHID và WebUSB, nhưng đây không phải là chủ đề của bài viết này. Trong bài đăng này, tôi muốn giải thích cách bạn có thể giao tiếp với tay điều khiển Stadia thông qua WebHID.
Tay điều khiển Stadia dưới dạng tay điều khiển trò chơi tiêu chuẩn
Sau khi cài đặt ROM, tay điều khiển sẽ xuất hiện dưới dạng tay điều khiển trò chơi tiêu chuẩn đối với hệ điều hành. Hãy xem ảnh chụp màn hình sau đây để biết cách sắp xếp nút và trục phổ biến trên tay điều khiển tiêu chuẩn. Như được xác định trong thông số kỹ thuật Gamepad API, tay điều khiển trò chơi tiêu chuẩn có các nút từ 0 đến 16, tổng cộng là 17 nút (d-pad được tính là 4 nút). Nếu thử tay điều khiển Stadia trên bản minh hoạ trình kiểm thử tay điều khiển, bạn sẽ thấy tay điều khiển hoạt động rất hiệu quả.
Tuy nhiên, nếu bạn đếm số nút trên tay điều khiển Stadia, thì có 19 nút. Nếu thử từng nút một một cách có hệ thống trong trình kiểm tra tay điều khiển trò chơi, bạn sẽ nhận thấy rằng các nút Trợ lý và Chụp không hoạt động. Ngay cả khi thuộc tính buttons
của tay điều khiển trò chơi như được xác định trong thông số kỹ thuật của Tay điều khiển trò chơi là mở, vì tay điều khiển Stadia xuất hiện dưới dạng tay điều khiển trò chơi tiêu chuẩn, nên chỉ các nút 0–16 mới được liên kết. Bạn vẫn có thể sử dụng các nút khác, nhưng hầu hết các trò chơi sẽ không mong đợi các nút đó tồn tại.
WebHID ra tay
Nhờ API WebHID, bạn có thể nói chuyện với các nút bị thiếu 17 và 18. Và nếu thực sự muốn, bạn thậm chí có thể nhận dữ liệu về tất cả các nút và trục khác hiện có thông qua API Tay điều khiển trò chơi. Bước đầu tiên là tìm hiểu cách tay điều khiển Stadia tự báo cáo cho hệ điều hành. Một cách để làm như vậy là mở Bảng điều khiển Công cụ của Chrome cho nhà phát triển trên bất kỳ trang nào ngẫu nhiên và yêu cầu danh sách thiết bị chưa được lọc từ API WebHID. Sau đó, bạn sẽ tự chọn tay điều khiển Stadia để kiểm tra thêm. Nhận danh sách thiết bị chưa được lọc bằng cách truyền một mảng tuỳ chọn filters
trống.
const [device] = await navigator.hid.requestDevice({filters: []});
Trong bộ chọn, mục cuối cùng có hình dạng giống như tay điều khiển Stadia.
Sau khi chọn thiết bị "Stadia Controller rev. A" (Bộ điều khiển Stadia phiên bản A), hãy ghi lại đối tượng HIDDevice
thu được vào Console. Thao tác này sẽ hiển thị productId
(37888
, là 0x9400
theo hệ thập lục phân) và vendorId
(6353
, là 0x18d1
theo hệ thập lục phân) của tay điều khiển Stadia. Nếu tra cứu vendorID
trong bảng mã nhà cung cấp USB chính thức, bạn sẽ thấy 6353
liên kết đến giá trị mà bạn mong đợi: Google Inc.
.
Một cách khác cho quy trình được mô tả ở trên là chuyển đến chrome://device-log/
trong thanh URL, nhấn nút Xoá, cắm tay điều khiển Stadia rồi nhấn Làm mới. Thao tác này cũng cung cấp cho bạn cùng một thông tin.
Một cách khác là sử dụng công cụ Trình khám phá HID để khám phá thêm thông tin chi tiết về các thiết bị HID được kết nối với máy tính.
Sử dụng hai mã nhận dạng này, vendorId
và productId
, để tinh chỉnh nội dung hiển thị trong bộ chọn bằng cách lọc chính xác thiết bị WebHID phù hợp.
const [stadiaController] = await navigator.hid.requestDevice({filters: [{
vendorId: 6353,
productId: 37888,
}]});
Giờ đây, tạp âm từ tất cả các thiết bị không liên quan đã biến mất và chỉ có tay điều khiển Stadia xuất hiện.
Tiếp theo, hãy mở HIDDevice
bằng cách gọi phương thức open()
.
await stadiaController.open();
Ghi lại lại HIDDevice
và đặt cờ opened
thành true
.
Khi thiết bị đang mở, hãy theo dõi các sự kiện inputreport
sắp tới bằng cách đính kèm trình nghe sự kiện.
stadiaController.addEventListener('inputreport', (e) => {
console.log(e);
});
Khi bạn nhấn và thả nút Trợ lý trên tay điều khiển, hai sự kiện sẽ được ghi lại vào Console. Bạn có thể coi đây là các sự kiện "Trợ lý nhấn nút" và "Trợ lý nhả nút". Ngoài timeStamp
, hai sự kiện này trông giống hệt nhau ngay từ cái nhìn đầu tiên.
Thuộc tính reportId
của giao diện HIDInputReportEvent
trả về tiền tố nhận dạng một byte cho báo cáo này hoặc 0
nếu giao diện HID không sử dụng mã báo cáo. Trong trường hợp này là 3
. Mã bí mật nằm trong thuộc tính data
, được biểu thị dưới dạng DataView
có kích thước 10. DataView
cung cấp một giao diện cấp thấp để đọc và ghi nhiều loại số trong tệp nhị phân ArrayBuffer
. Cách để có được nội dung dễ hiểu hơn từ cách trình bày này là tạo Uint8Array
từ ArrayBuffer
, nhờ đó bạn có thể xem các số nguyên 8 bit chưa ký riêng lẻ.
const data = new Uint8Array(event.data.buffer);
Sau đó, khi bạn ghi lại dữ liệu sự kiện báo cáo đầu vào một lần nữa, mọi thứ sẽ bắt đầu trở nên hợp lý hơn và các sự kiện "Trợ lý nhấn nút xuống" và "Trợ lý nhấn nút lên" bắt đầu có thể giải mã được. Số nguyên đầu tiên (8
trong cả hai sự kiện) có vẻ liên quan đến các lần nhấn nút và số nguyên thứ hai (2
và 0
) có vẻ liên quan đến việc nút Trợ lý có được nhấn hay không.
Nhấn vào nút Capture (Ghi lại) thay vì nút Assistant (Trợ lý) và bạn sẽ thấy số nguyên thứ hai chuyển đổi từ 1
khi nhấn nút thành 0
khi thả nút. Điều này cho phép bạn viết một "trình điều khiển" rất đơn giản để sử dụng hai nút còn thiếu.
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');
}
}
});
Bằng cách sử dụng phương pháp kỹ thuật đảo ngược như vậy, bạn có thể tìm hiểu cách giao tiếp với tay điều khiển Stadia bằng WebHID, theo từng nút và theo từng trục. Sau khi bạn nắm được cách làm, phần còn lại gần như là công việc ánh xạ số nguyên cơ học.
Hiện tại, bạn vẫn chưa có trải nghiệm kết nối mượt mà mà Gamepad API mang lại. Tuy nhiên, vì lý do bảo mật, bạn luôn phải trải qua trải nghiệm bộ chọn ban đầu một lần để làm việc với thiết bị WebHID như tay điều khiển Stadia. Đối với các kết nối trong tương lai, bạn có thể kết nối lại với các thiết bị đã biết. Thực hiện việc đó bằng cách gọi phương thức getDevices()
.
let stadiaController;
const [device] = await navigator.hid.getDevices();
if (device && device.vendorId === 6353 && device.productId === 37888) {
stadiaController = device;
}
Bản minh hoạ
Bạn có thể thấy tay điều khiển Stadia do Gamepad API và WebHID API kiểm soát chung trong một bản minh hoạ mà tôi đã tạo. Hãy nhớ xem mã nguồn dựa trên các đoạn mã trong bài viết này. Để đơn giản, tôi chỉ hiển thị các nút A, B, X và Y (do Gamepad API điều khiển) cũng như các nút Trợ lý và Chụp (do WebHID API điều khiển). Bên dưới hình ảnh tay điều khiển, bạn có thể thấy dữ liệu WebHID thô để có thể nắm được tất cả các nút và trục trên tay điều khiển.
Kết luận
Nhờ có phần mềm mới, tay điều khiển Stadia hiện có thể dùng làm tay điều khiển trò chơi tiêu chuẩn với 17 nút. Trong hầu hết trường hợp, số nút này là quá đủ để điều khiển các trò chơi phổ biến trên web. Nếu vì lý do nào đó mà bạn cần dữ liệu từ cả 19 nút trên tay điều khiển, thì WebHID cho phép bạn truy cập vào các báo cáo đầu vào cấp thấp mà bạn có thể giải mã bằng cách kỹ thuật đảo ngược từng báo cáo. Nếu bạn có viết một trình điều khiển WebHID hoàn chỉnh sau khi đọc bài viết này, hãy nhớ liên hệ với tôi. Tôi rất sẵn lòng liên kết dự án của bạn tại đây. Chúc bạn sử dụng WebHID vui vẻ!
Lời cảm ơn
Bài viết này được François Beaufort xem xét.