WebHID API อนุญาตให้เว็บไซต์เข้าถึงคีย์บอร์ดเสริมและเกมแพดที่แปลกใหม่
มีอุปกรณ์ที่โต้ตอบกับมนุษย์โดยตรง (HID) จำนวนมาก เช่น แป้นพิมพ์ทางเลือกหรือเกมแพดที่แปลกใหม่ ซึ่งใหม่เกินไป เก่าเกินไป หรือไม่ค่อยพบเห็น ทำให้ไดรเวอร์อุปกรณ์ของระบบเข้าถึงไม่ได้ WebHID API แก้ปัญหานี้ด้วยการ ให้วิธีใช้ตรรกะเฉพาะอุปกรณ์ใน JavaScript
กรณีการใช้งานที่แนะนำ
อุปกรณ์ HID รับอินพุตจากหรือแสดงเอาต์พุตต่อมนุษย์ ตัวอย่างอุปกรณ์ ได้แก่ แป้นพิมพ์ อุปกรณ์ชี้ (เมาส์ หน้าจอสัมผัส ฯลฯ) และเกมแพด โปรโตคอล HID ช่วยให้เข้าถึงอุปกรณ์เหล่านี้ในคอมพิวเตอร์เดสก์ท็อป ได้โดยใช้ไดรเวอร์ระบบปฏิบัติการ แพลตฟอร์มเว็บรองรับอุปกรณ์ HID โดยใช้ไดรเวอร์เหล่านี้
การเข้าถึงอุปกรณ์ HID ที่ไม่ใช่แบบที่ใช้กันทั่วไปไม่ได้เป็นปัญหาที่น่ากังวลอย่างยิ่งเมื่อพูดถึงแป้นพิมพ์เสริมทางเลือก (เช่น Elgato Stream Deck, ชุดหูฟัง Jabra, X-keys) และการรองรับเกมแพดที่แปลกใหม่ เกมแพดที่ออกแบบมาสำหรับเดสก์ท็อป มักใช้ HID สำหรับอินพุตเกมแพด (ปุ่ม จอยสติ๊ก ทริกเกอร์) และเอาต์พุต (LED การสั่น) อย่างไรก็ตาม อินพุตและเอาต์พุตของเกมแพดไม่ได้ เป็นมาตรฐานที่ดี และเว็บเบราว์เซอร์มักต้องใช้ตรรกะที่กำหนดเองสำหรับอุปกรณ์บางอย่าง ซึ่งเป็นสิ่งที่ยั่งยืนไม่ได้และส่งผลให้การสนับสนุนอุปกรณ์รุ่นเก่าและ อุปกรณ์ที่ไม่ค่อยพบนั้นไม่ดี นอกจากนี้ยังทำให้เบราว์เซอร์ต้องพึ่งพาข้อบกพร่องในลักษณะการทำงาน ของอุปกรณ์บางรุ่นด้วย
คำศัพท์
HID ประกอบด้วยแนวคิดพื้นฐาน 2 อย่าง ได้แก่ รายงานและตัวอธิบายรายงาน รายงานคือข้อมูลที่แลกเปลี่ยนระหว่างอุปกรณ์และไคลเอ็นต์ซอฟต์แวร์ ตัวอธิบายรายงานจะอธิบายรูปแบบและความหมายของข้อมูลที่อุปกรณ์รองรับ
HID (Human Interface Device) คืออุปกรณ์ประเภทหนึ่งที่รับอินพุตจากหรือ แสดงเอาต์พุตต่อมนุษย์ นอกจากนี้ยังหมายถึงโปรโตคอล HID ซึ่งเป็นมาตรฐานสำหรับการสื่อสารแบบ 2 ทางระหว่างโฮสต์กับอุปกรณ์ที่ออกแบบมาเพื่อลดความซับซ้อนของขั้นตอนการติดตั้ง เดิมทีโปรโตคอล HID ได้รับการพัฒนาขึ้น สำหรับอุปกรณ์ USB แต่ต่อมาได้มีการนำไปใช้กับโปรโตคอลอื่นๆ อีกมากมาย รวมถึงบลูทูธ
แอปพลิเคชันและอุปกรณ์ HID แลกเปลี่ยนข้อมูลไบนารีผ่านรายงาน 3 ประเภท ได้แก่
ประเภทรายงาน | คำอธิบาย |
---|---|
รายงานอินพุต | ข้อมูลที่ส่งจากอุปกรณ์ไปยังแอปพลิเคชัน (เช่น มีการกดปุ่ม) |
รายงานเอาต์พุต | ข้อมูลที่ส่งจากแอปพลิเคชันไปยังอุปกรณ์ (เช่น คำขอเปิดไฟแบ็กไลท์ของคีย์บอร์ด) |
รายงานฟีเจอร์ | ข้อมูลที่อาจส่งได้ทั้ง 2 ทาง รูปแบบนี้จะขึ้นอยู่กับอุปกรณ์ |
ตัวอธิบายรายงานจะอธิบายรูปแบบไบนารีของรายงานที่อุปกรณ์รองรับ โครงสร้างของรายงานเป็นแบบลำดับชั้นและสามารถจัดกลุ่มรายงานไว้ด้วยกันเป็นคอลเล็กชันที่แตกต่างกัน ภายในคอลเล็กชันระดับบนสุด รูปแบบของตัวอธิบายกำหนดโดยข้อกำหนด HID
การใช้งาน HID คือค่าตัวเลขที่อ้างอิงถึงอินพุตหรือเอาต์พุตมาตรฐาน ค่าการใช้งานช่วยให้อุปกรณ์อธิบายการใช้งานที่ตั้งใจไว้ของอุปกรณ์และ วัตถุประสงค์ของแต่ละฟิลด์ในรายงานได้ เช่น กำหนดไว้สำหรับปุ่มซ้ายของเมาส์ นอกจากนี้ ระบบยังจัดระเบียบการใช้งานเป็นหน้าการใช้งาน ซึ่งจะระบุหมวดหมู่ระดับสูงของอุปกรณ์หรือรายงาน
การใช้ WebHID API
การตรวจหาฟีเจอร์
หากต้องการตรวจสอบว่าระบบรองรับ WebHID API หรือไม่ ให้ใช้
if ("hid" in navigator) {
// The WebHID API is supported.
}
เปิดการเชื่อมต่อ HID
WebHID API ได้รับการออกแบบมาให้ทำงานแบบไม่พร้อมกันเพื่อป้องกันไม่ให้ UI ของเว็บไซต์ถูกบล็อกเมื่อรอรับอินพุต ซึ่งถือเป็นสิ่งสำคัญเนื่องจากสามารถรับข้อมูล HID ได้ทุกเมื่อ จึงต้องมีวิธีรับฟังข้อมูลดังกล่าว
หากต้องการเปิดการเชื่อมต่อ HID ให้เข้าถึงออบเจ็กต์ HIDDevice
ก่อน โดยคุณสามารถทำได้โดย
แจ้งให้ผู้ใช้เลือกอุปกรณ์โดยเรียกใช้
navigator.hid.requestDevice()
หรือเลือกอุปกรณ์จาก navigator.hid.getDevices()
ซึ่งจะแสดงรายการอุปกรณ์ที่เว็บไซต์ได้รับสิทธิ์เข้าถึง
ก่อนหน้านี้
navigator.hid.requestDevice()
ฟังก์ชันนี้ใช้ออบเจ็กต์ที่จำเป็นซึ่ง
กำหนดตัวกรอง ซึ่งใช้เพื่อจับคู่อุปกรณ์ที่เชื่อมต่อกับตัวระบุผู้ให้บริการ USB (vendorId
), ตัวระบุผลิตภัณฑ์ USB (productId
), ค่าหน้าการใช้งาน (usagePage
) และค่าการใช้งาน (usage
) คุณสามารถดูค่าดังกล่าวได้จากที่เก็บรหัส USB และเอกสารตารางการใช้งาน HID
ออบเจ็กต์ HIDDevice
หลายรายการที่ฟังก์ชันนี้แสดงผลแสดงถึงอินเทอร์เฟซ HID หลายรายการในอุปกรณ์จริงเดียวกัน
// Filter on devices with the Nintendo Switch Joy-Con USB Vendor/Product IDs.
const filters = [
{
vendorId: 0x057e, // Nintendo Co., Ltd
productId: 0x2006 // Joy-Con Left
},
{
vendorId: 0x057e, // Nintendo Co., Ltd
productId: 0x2007 // Joy-Con Right
}
];
// Prompt user to select a Joy-Con device.
const [device] = await navigator.hid.requestDevice({ filters });
// Get all devices the user has previously granted the website access to.
const devices = await navigator.hid.getDevices();

นอกจากนี้ คุณยังใช้คีย์ exclusionFilters
ที่ไม่บังคับใน
navigator.hid.requestDevice()
เพื่อยกเว้นอุปกรณ์บางอย่างจากตัวเลือกเบราว์เซอร์ได้
ซึ่งเป็นอุปกรณ์ที่ทราบว่าทำงานผิดปกติ เป็นต้น
// Request access to a device with vendor ID 0xABCD. The device must also have
// a collection with usage page Consumer (0x000C) and usage ID Consumer
// Control (0x0001). The device with product ID 0x1234 is malfunctioning.
const [device] = await navigator.hid.requestDevice({
filters: [{ vendorId: 0xabcd, usagePage: 0x000c, usage: 0x0001 }],
exclusionFilters: [{ vendorId: 0xabcd, productId: 0x1234 }],
});
ออบเจ็กต์ HIDDevice
มีตัวระบุผู้ให้บริการและผลิตภัณฑ์ USB สำหรับการระบุอุปกรณ์
collections
ของอุปกรณ์จะเริ่มต้นด้วยคำอธิบายแบบลำดับชั้น
ของรูปแบบรายงานของอุปกรณ์
for (let collection of device.collections) {
// An HID collection includes usage, usage page, reports, and subcollections.
console.log(`Usage: ${collection.usage}`);
console.log(`Usage page: ${collection.usagePage}`);
for (let inputReport of collection.inputReports) {
console.log(`Input report: ${inputReport.reportId}`);
// Loop through inputReport.items
}
for (let outputReport of collection.outputReports) {
console.log(`Output report: ${outputReport.reportId}`);
// Loop through outputReport.items
}
for (let featureReport of collection.featureReports) {
console.log(`Feature report: ${featureReport.reportId}`);
// Loop through featureReport.items
}
// Loop through subcollections with collection.children
}
โดยค่าเริ่มต้นแล้ว อุปกรณ์ HIDDevice
จะอยู่ในสถานะ "ปิด" และต้องเปิดโดยการโทรหา open()
ก่อนจึงจะส่งหรือรับข้อมูลได้
// Wait for the HID connection to open before sending/receiving data.
await device.open();
รับรายงานอินพุต
เมื่อสร้างการเชื่อมต่อ HID แล้ว คุณจะจัดการรายงานอินพุตที่เข้ามาได้โดยการฟังเหตุการณ์ "inputreport"
จากอุปกรณ์ เหตุการณ์เหล่านั้น
มีข้อมูล HID เป็นออบเจ็กต์ DataView
(data
), อุปกรณ์ HID ที่เป็นของเหตุการณ์ (device
) และรหัสรายงาน 8 บิตที่เชื่อมโยงกับรายงานอินพุต (reportId
)

จากตัวอย่างก่อนหน้า โค้ดด้านล่างจะแสดงวิธีตรวจหาปุ่มที่ผู้ใช้กดบนอุปกรณ์ Joy-Con Right เพื่อให้คุณลองใช้ที่บ้านได้
device.addEventListener("inputreport", event => {
const { data, device, reportId } = event;
// Handle only the Joy-Con Right device and a specific report ID.
if (device.productId !== 0x2007 && reportId !== 0x3f) return;
const value = data.getUint8(0);
if (value === 0) return;
const someButtons = { 1: "A", 2: "X", 4: "B", 8: "Y" };
console.log(`User pressed button ${someButtons[value]}.`);
});
ดูเดโม webhid-joycon-button ของปากกา
ส่งรายงานเอาต์พุต
หากต้องการส่งรายงานเอาต์พุตไปยังอุปกรณ์ HID ให้ส่งรหัสรายงาน 8 บิตที่เชื่อมโยง
กับรายงานเอาต์พุต (reportId
) และไบต์เป็น BufferSource
(data
) ไปยัง
device.sendReport()
Promise ที่ส่งคืนจะได้รับการแก้ไขเมื่อระบบส่งรายงานแล้ว
หากอุปกรณ์ HID ไม่ใช้รหัสรายงาน ให้ตั้งค่า reportId
เป็น 0
ตัวอย่างด้านล่างใช้กับอุปกรณ์ Joy-Con และแสดงวิธีทำให้ สั่นด้วยรายงานเอาต์พุต
// First, send a command to enable vibration.
// Magical bytes come from https://github.com/mzyy94/joycon-toolweb
const enableVibrationData = [1, 0, 1, 64, 64, 0, 1, 64, 64, 0x48, 0x01];
await device.sendReport(0x01, new Uint8Array(enableVibrationData));
// Then, send a command to make the Joy-Con device rumble.
// Actual bytes are available in the sample below.
const rumbleData = [ /* ... */ ];
await device.sendReport(0x10, new Uint8Array(rumbleData));
ดูเดโม webhid-joycon-rumble ของ Pen
ส่งและรับรายงานฟีเจอร์
รายงานฟีเจอร์เป็นรายงานข้อมูล HID ประเภทเดียวที่สามารถเดินทางได้ทั้ง 2 ทิศทาง ซึ่งช่วยให้อุปกรณ์และแอปพลิเคชัน HID แลกเปลี่ยนข้อมูล HID ที่ไม่ได้มาตรฐานได้ รายงานฟีเจอร์ไม่เหมือนกับรายงานอินพุตและเอาต์พุตตรงที่แอปพลิเคชันจะไม่ได้รับหรือส่งรายงานเป็นประจำ

หากต้องการส่งรายงานฟีเจอร์ไปยังอุปกรณ์ HID ให้ส่งรหัสรายงาน 8 บิตที่เชื่อมโยง
กับรายงานฟีเจอร์ (reportId
) และไบต์เป็น BufferSource
(data
) ไปยัง
device.sendFeatureReport()
Promise ที่ส่งคืนจะได้รับการแก้ไขเมื่อส่งรายงานแล้ว
หากอุปกรณ์ HID ไม่ใช้รหัสรายงาน ให้ตั้งค่า reportId
เป็น 0
ตัวอย่างด้านล่างแสดงการใช้รายงานฟีเจอร์โดยแสดงวิธี ขออุปกรณ์ไฟแบ็กไลท์ของคีย์บอร์ด Apple เปิดอุปกรณ์ และทำให้อุปกรณ์กะพริบ
const waitFor = duration => new Promise(r => setTimeout(r, duration));
// Prompt user to select an Apple Keyboard Backlight device.
const [device] = await navigator.hid.requestDevice({
filters: [{ vendorId: 0x05ac, usage: 0x0f, usagePage: 0xff00 }]
});
// Wait for the HID connection to open.
await device.open();
// Blink!
const reportId = 1;
for (let i = 0; i < 10; i++) {
// Turn off
await device.sendFeatureReport(reportId, Uint32Array.from([0, 0]));
await waitFor(100);
// Turn on
await device.sendFeatureReport(reportId, Uint32Array.from([512, 0]));
await waitFor(100);
}
ดูเดโม webhid-apple-keyboard-backlight ของปากกา
หากต้องการรับรายงานฟีเจอร์จากอุปกรณ์ HID ให้ส่งรหัสรายงาน 8 บิต
ที่เชื่อมโยงกับรายงานฟีเจอร์ (reportId
) ไปยัง
device.receiveFeatureReport()
Promise ที่ส่งคืนจะได้รับการแก้ไขด้วยออบเจ็กต์ DataView
ที่มีเนื้อหาของรายงานฟีเจอร์ หากอุปกรณ์ HID
ไม่ได้ใช้รหัสรายงาน ให้ตั้งค่า reportId
เป็น 0
// Request feature report.
const dataView = await device.receiveFeatureReport(/* reportId= */ 1);
// Read feature report contents with dataView.getInt8(), getUint8(), etc...
ฟังการเชื่อมต่อและการยกเลิกการเชื่อมต่อ
เมื่อได้รับสิทธิ์เข้าถึงอุปกรณ์ HID แล้ว เว็บไซต์จะ
รับเหตุการณ์การเชื่อมต่อและการยกเลิกการเชื่อมต่อได้อย่างต่อเนื่องโดยการฟังเหตุการณ์ "connect"
และ "disconnect"
navigator.hid.addEventListener("connect", event => {
// Automatically open event.device or warn user a device is available.
});
navigator.hid.addEventListener("disconnect", event => {
// Remove |event.device| from the UI.
});
เพิกถอนสิทธิ์เข้าถึงอุปกรณ์ HID
เว็บไซต์สามารถล้างสิทธิ์เข้าถึงอุปกรณ์ HID ที่ไม่ต้องการเก็บรักษาอีกต่อไปได้โดยการเรียกใช้ forget()
ในอินสแตนซ์ HIDDevice
ตัวอย่างเช่น สำหรับเว็บแอปพลิเคชันเพื่อการศึกษาที่ใช้ในคอมพิวเตอร์ที่ใช้ร่วมกันกับอุปกรณ์จำนวนมาก สิทธิ์ที่ผู้ใช้สร้างขึ้นจำนวนมากที่สะสมไว้จะทำให้ประสบการณ์ของผู้ใช้ไม่ดี
การเรียกใช้ forget()
ในอินสแตนซ์ HIDDevice
เดียวจะเป็นการเพิกถอนสิทธิ์เข้าถึงอินเทอร์เฟซ HID ทั้งหมดในอุปกรณ์จริงเดียวกัน
// Voluntarily revoke access to this HID device.
await device.forget();
เนื่องจาก forget()
พร้อมใช้งานใน Chrome 100 ขึ้นไป ให้ตรวจสอบว่าฟีเจอร์นี้
รองรับรายการต่อไปนี้หรือไม่
if ("hid" in navigator && "forget" in HIDDevice.prototype) {
// forget() is supported.
}
เคล็ดลับสำหรับนักพัฒนาแอป
การแก้ไขข้อบกพร่องของ HID ใน Chrome เป็นเรื่องง่ายด้วยหน้าภายใน about://device-log
ซึ่งคุณสามารถดูเหตุการณ์ทั้งหมดที่เกี่ยวข้องกับอุปกรณ์ HID และ USB ได้ในที่เดียว

ดูเครื่องมือสำรวจ HID เพื่อส่งข้อมูลอุปกรณ์ HID ไปยังรูปแบบที่มนุษย์อ่านได้ โดยจะแมปจากค่าการใช้งานไปยังชื่อสำหรับการใช้งาน HID แต่ละรายการ
ในระบบ Linux ส่วนใหญ่ อุปกรณ์ HID จะได้รับการแมปด้วยสิทธิ์แบบอ่านอย่างเดียวโดยค่าเริ่มต้น หากต้องการอนุญาตให้ Chrome เปิดอุปกรณ์ HID คุณจะต้องเพิ่มกฎ udev ใหม่ สร้างไฟล์ที่ /etc/udev/rules.d/50-yourdevicename.rules
โดยมีเนื้อหาต่อไปนี้
KERNEL=="hidraw*", ATTRS{idVendor}=="[yourdevicevendor]", MODE="0664", GROUP="plugdev"
ในบรรทัดด้านบน [yourdevicevendor]
คือ 057e
หากอุปกรณ์ของคุณเป็น Nintendo Switch
Joy-Con เป็นต้น ATTRS{idProduct}
ยังเพิ่มเพื่อกฎที่เจาะจงมากขึ้นได้ด้วย
ตรวจสอบว่า user
เป็นสมาชิกของกลุ่ม plugdev
จากนั้นเพียง
เชื่อมต่ออุปกรณ์อีกครั้ง
การสนับสนุนเบราว์เซอร์
WebHID API พร้อมใช้งานในแพลตฟอร์มเดสก์ท็อปทั้งหมด (ChromeOS, Linux, macOS และ Windows) ใน Chrome 89
การสาธิต
ตัวอย่าง WebHID บางส่วนแสดงอยู่ที่ web.dev/hid-examples ลองดูเลย
ความปลอดภัยและความเป็นส่วนตัว
ผู้เขียนข้อกำหนดได้ออกแบบและใช้ WebHID API โดยใช้หลักการหลักที่กำหนดไว้ในการควบคุมการเข้าถึงฟีเจอร์ที่มีประสิทธิภาพของแพลตฟอร์มเว็บ ซึ่งรวมถึงการควบคุมของผู้ใช้ ความโปร่งใส และการยศาสตร์ ความสามารถในการใช้ API นี้ส่วนใหญ่จะจำกัดด้วยโมเดลสิทธิ์ที่ให้สิทธิ์เข้าถึงอุปกรณ์ HID เพียงเครื่องเดียวในแต่ละครั้ง เพื่อตอบสนองต่อพรอมต์ของผู้ใช้ ผู้ใช้ต้องดำเนินการ อย่างกระตือรือร้นเพื่อเลือกอุปกรณ์ HID ที่ต้องการ
หากต้องการทำความเข้าใจข้อแลกเปลี่ยนด้านความปลอดภัย โปรดดูส่วนข้อควรพิจารณาด้านความปลอดภัยและความเป็นส่วนตัวของข้อกำหนด WebHID
นอกจากนี้ Chrome ยังตรวจสอบการใช้งานคอลเล็กชันระดับบนสุดแต่ละรายการ และหากคอลเล็กชันระดับบนสุดมีการใช้งานที่ได้รับการปกป้อง (เช่น คีย์บอร์ด เมาส์ทั่วไป) เว็บไซต์จะส่งและรับรายงานใดๆ ที่กำหนดไว้ในคอลเล็กชันนั้นไม่ได้ รายการการใช้งานที่ได้รับการคุ้มครองทั้งหมดพร้อมให้บริการแก่สาธารณะ
โปรดทราบว่าอุปกรณ์ HID ที่มีความละเอียดอ่อนด้านความปลอดภัย (เช่น อุปกรณ์ FIDO HID ที่ใช้สำหรับการ ตรวจสอบสิทธิ์ที่รัดกุมยิ่งขึ้น) จะถูกบล็อกใน Chrome ด้วย ดูไฟล์รายการที่บล็อก USB และ รายการที่บล็อก HID
ความคิดเห็น
ทีม Chrome อยากทราบความคิดเห็นและประสบการณ์ของคุณเกี่ยวกับ WebHID API
บอกเราเกี่ยวกับการออกแบบ API
มีอะไรเกี่ยวกับ API ที่ไม่ทำงานตามที่คาดไว้ไหม หรือมีเมธอดหรือพร็อพเพอร์ตี้ที่ขาดหายไปซึ่งคุณต้องใช้เพื่อนำไอเดียไปใช้ไหม
แจ้งปัญหาเกี่ยวกับข้อกำหนดในที่เก็บ GitHub ของ WebHID API หรือแสดงความคิดเห็น ในปัญหาที่มีอยู่
รายงานปัญหาเกี่ยวกับการติดตั้งใช้งาน
หากพบข้อบกพร่องในการใช้งาน Chrome หรือการติดตั้งใช้งาน แตกต่างจากข้อกำหนด
ดูวิธีรายงานข้อบกพร่องของ WebHID โปรดใส่รายละเอียดให้มากที่สุดเท่าที่จะเป็นไปได้ ระบุวิธีการง่ายๆ ในการจำลองข้อบกพร่อง และตั้งค่าคอมโพเนนต์เป็น Blink>HID
แสดงการสนับสนุน
คุณวางแผนที่จะใช้ WebHID API ใช่ไหม การสนับสนุนแบบสาธารณะของคุณจะช่วยให้ทีม Chrome จัดลําดับความสําคัญของฟีเจอร์และแสดงให้ผู้ให้บริการเบราว์เซอร์รายอื่นๆ เห็นว่าการรองรับฟีเจอร์เหล่านี้มีความสําคัญเพียงใด
ส่งทวีตถึง @ChromiumDev โดยใช้แฮชแท็ก
#WebHID
และแจ้งให้เราทราบ
ว่าคุณใช้ฟีเจอร์นี้ที่ไหนและอย่างไร
ลิงก์ที่มีประโยชน์
- ข้อกำหนด
- ข้อบกพร่องในการติดตาม
- รายการใน ChromeStatus.com
- คอมโพเนนต์ Blink:
Blink>HID
การรับทราบ
ขอขอบคุณ Matt Reynolds และ Joe Medley ที่รีวิวบทความนี้ ภาพ Nintendo Switch สีแดงและสีน้ำเงินโดย Sara Kurfeß และภาพคอมพิวเตอร์แล็ปท็อปสีดำและสีเงินโดย Athul Cyriac Ajay ใน Unsplash