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