I'm trying to grab sensor input from my digitizer ( X Tilt, Y Tilt, Tip Pressure, Tip Switch, Eraser, Pen, Puck .etc) using the WebHID API. This is what I've gotten so far:
index.js:
page_log = text => {
let p = document.createElement("p");
p.textContent = text;
log.appendChild(p);
};
let device;
if (!("hid" in navigator)) {
page_log("WebHID is not available yet.");
}
navigator.hid.getDevices().then(devices => {
if (devices.length == 0) {
page_log(`No HID devices selected. Press the "request device" button.`);
return;
}
if (devices.length > 1) {
page_log(`You have multiple devices.`);
}
device = devices[0];
page_log(`User previously selected "${device.productName}" HID device.`);
page_log(`Now press "open device" button to receive input reports.`);
});
requestDeviceButton.onclick = async event => {
document.body.style.display = "none";
try {
const filters = [
{
vendorId: 0x056a, // Wacom Co., Ltd
productId: 0x00b1 //PTZ-630 [Intuos3 (6x8)]
},
{
vendorId: 0x056a, // Wacom Co., Ltd
productId: 0x00b2 //PTZ-930 [Intuos3 (9x12)]
},
{
vendorId: 0x056a, // Wacom Co., Ltd
productId: 0x00b3 //PTZ-1230 [Intuos3 (12x12)]
},
{
vendorId: 0x056a, // Wacom Co., Ltd
productId: 0x00b4 //PTZ-1231W [Intuos3 (12x19)]
},
];
[device] = await navigator.hid.requestDevice({ filters });
if (!device) return;
page_log(`User selected "${device.productName}" HID device.`);
page_log(`Now press "open device" button to receive input reports.`);
} finally {
document.body.style.display = "";
}
};
openButton.onclick = async event => {
if (!device) return;
await device.open().catch(console.error);
page_log(`Waiting for user to press button...`);
device.addEventListener("inputreport", event => {
const { data, device, reportId } = event;
let buffArray = new Uint8Array(data.buffer);
console.log(buffArray);
// console.log(device);
});
};
console output:
index.js:72 Uint8Array(9) [224, 49, 125, 58, 74, 0, 35, 195, 85]
index.js:72 Uint8Array(9) [224, 49, 109, 58, 64, 0, 35, 194, 94]
index.js:72 Uint8Array(9) [224, 49, 94, 58, 43, 0, 35, 194, 102]
index.js:72 Uint8Array(9) [224, 49, 82, 58, 22, 0, 35, 193, 113]
index.js:72 Uint8Array(9) [224, 49, 52, 58, 1, 0, 35, 193, 123]
index.js:72 Uint8Array(9) [224, 49, 26, 57, 228, 0, 35, 192, 128]
index.js:72 Uint8Array(9) [224, 48, 253, 57, 190, 0, 35, 64, 141]
index.js:72 Uint8Array(9) [224, 48, 223, 57, 137, 0, 35, 65, 148]
index.js:72 Uint8Array(9) [224, 48, 203, 57, 90, 0, 35, 66, 159]
index.js:72 Uint8Array(9) [224, 48, 186, 57, 36, 0, 35, 66, 167]
index.js:72 Uint8Array(9) [224, 48, 177, 56, 242, 0, 35, 67, 174]
index.js:72 Uint8Array(9) [224, 48, 166, 56, 208, 0, 35, 196, 178]
How do I find out which sensor each number corresponds to?
I've tried reading WebHID spec and HID Usage Tables but I've so far been unable to locate the information I need to decipher the output.
Update:
I've tested in Windows after installing Wacom's official driver I get more data from the InputReport.
output: (Windows w/ wacom driver)
index.js:73 reportId: 15
index.js:76 Uint8Array(10) [2, 224, 55, 229, 45, 137, 0, 30, 176, 195]
index.js:73 reportId: 15
index.js:76 Uint8Array(21) [2, 224, 55, 163, 45, 99, 0, 31, 49, 189, 15, 2, 224, 55, 98, 45, 69, 0, 31, 49, 190]
index.js:73 reportId: 7
index.js:76 Uint8Array(37) [32, 29, 90, 238, 97, 50, 3, 0, 0, 34, 8, 16, 0, 87, 126, 112, 8, 34, 8, 16, 0, 0, 0, 0, 0, 0, 0, 212, 254, 192, 249, 232, 28, 184, 136, 0, 0]
index.js:73 reportId: 7
index.js:76 Uint8Array(37) [32, 241, 89, 197, 97, 30, 3, 0, 0, 34, 8, 16, 0, 87, 126, 112, 8, 34, 8, 16, 0, 0, 0, 0, 0, 0, 0, 56, 255, 36, 250, 76, 29, 228, 137, 0, 0]
index.js:73 reportId: 7
index.js:76 Uint8Array(37) [32, 162, 89, 144, 97, 30, 3, 0, 0, 34, 8, 16, 0, 87, 126, 112, 8, 34, 8, 16, 0, 0, 0, 0, 0, 0, 0, 56, 255, 36, 250, 76, 29, 228, 137, 0, 0]
index.js:73 reportId: 7
index.js:76 Uint8Array(37) [32, 136, 89, 123, 97, 22, 3, 0, 0, 34, 8, 16, 0, 87, 126, 112, 8, 34, 8, 16, 0, 0, 0, 0, 0, 0, 0, 56, 255, 36, 250, 76, 29, 228, 137, 0, 0]
index.js:73 reportId: 15
index.js:76 Uint8Array(10) [2, 224, 55, 34, 45, 31, 0, 31, 178, 185]
index.js:73 reportId: 15
index.js:76 Uint8Array(32) [2, 224, 54, 215, 45, 2, 0, 32, 50, 183, 15, 2, 224, 54, 139, 44, 226, 0, 32, 179, 183, 15, 2, 224, 54, 62, 44, 187, 0, 33, 52, 178]
index.js:73 reportId: 7
index.js:76 Uint8Array(37) [32, 27, 89, 51, 97, 14, 3, 0, 0, 34, 8, 16, 0, 87, 126, 112, 8, 34, 8, 16, 0, 0, 0, 0, 0, 0, 0, 156, 255, 136, 250, 176, 29, 16, 139, 0, 0]
index.js:73 reportId: 7
index.js:76 Uint8Array(37) [32, 171, 88, 237, 96, 6, 3, 0, 0, 34, 8, 16, 0, 87, 126, 112, 8, 34, 8, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136, 250, 176, 29, 0, 0, 0, 0]
index.js:73 reportId: 7
index.js:76 Uint8Array(37) [32, 53, 88, 163, 96, 254, 2, 0, 0, 34, 8, 16, 0, 87, 126, 112, 8, 34, 8, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 236, 250, 20, 30, 0, 0, 0, 0]
index.js:73 reportId: 15
index.js:76 Uint8Array(10) [2, 224, 53, 239, 44, 147, 0, 34, 54, 175]
Note: I've logged the reportId
this time because I'm now getting 2 different ones.
I'm also noticing different data in the HIDDevice.collections
object:
This time I'm getting something in one of my outputReports
.
output: (Linux for comparison)
index.js:73 reportId: 2
index.js:74 Uint8Array(9) [224, 31, 174, 22, 67, 0, 38, 203, 177]
index.js:73 reportId: 2
index.js:74 Uint8Array(9) [224, 31, 33, 21, 8, 0, 39, 204, 180]
index.js:73 reportId: 2
index.js:74 Uint8Array(9) [224, 30, 165, 20, 8, 0, 40, 77, 183]
index.js:73 reportId: 2
index.js:74 Uint8Array(9) [224, 30, 16, 19, 51, 0, 40, 206, 182]
index.js:73 reportId: 2
index.js:74 Uint8Array(9) [224, 29, 134, 18, 97, 0, 41, 80, 181]
index.js:73 reportId: 2
index.js:74 Uint8Array(9) [224, 29, 9, 17, 191, 0, 39, 80, 183]
index.js:73 reportId: 2
index.js:74 Uint8Array(9) [224, 28, 210, 17, 27, 0, 36, 215, 184]
index.js:73 reportId: 2
index.js:74 Uint8Array(9) [224, 28, 225, 16, 150, 0, 35, 86, 186]
index.js:73 reportId: 2
index.js:74 Uint8Array(9) [224, 29, 45, 16, 15, 0, 33, 83, 184]
index.js:73 reportId: 2
index.js:74 Uint8Array(9) [224, 29, 162, 15, 153, 0, 32, 83, 190]
index.js:73 reportId: 2
index.js:74 Uint8Array(9) [224, 30, 110, 15, 51, 0, 32, 86, 195]
index.js:73 reportId: 2
index.js:74 Uint8Array(9) [224, 31, 96, 14, 214, 0, 31, 87, 199]
index.js:73 reportId: 2
index.js:74 Uint8Array(9) [160, 32, 212, 14, 142, 0, 26, 216, 202]
Also the HIDDevice.collections
I get on linux:
So I still don't understand how to map the data using either the featureReports
, InputReports
or OutputReports
. So all I've figured out I get more HID data from Wacom's driver on Windows than linux.
Update 2:
I have been looking at the HIDDevice.collection
Object on the Windows output and comparing it to Report Descriptors
I get from running usbhid-dump
with hidrd-convert
(for making them human readable) on Linux. This is what I've found out so far.
It looks like all I need to look at is the
inputReports
element with the appropriatereportID
as I'm only trying to read the sensor data being sent to the host.I look at the array of
items
to see what data being sent by the report.- I look at the index number of the item in
items
to know the order to extract the data from the DataView (mydata
variable). - I look at
reportCount
andreportSize
to know the shape of the data for that item in the DataView. - I look at the "Usage" each item to know what the data is for.
- Unfortunately WebHID doesn't seem to expose "Usage" on a per item bases (Like my "Report Descriptors" from
usbhid-dump
shows). Instead it only exposes it on a per collection basis. - The "Usage" (if it was available) could be looked up in the HID Usage Tables by looking up the "Usage Page" by the hex value of
usagePage
for thecollection
, then doing the same for the givenusage
hex value.
- Unfortunately WebHID doesn't seem to expose "Usage" on a per item bases (Like my "Report Descriptors" from
- I look at the index number of the item in
Example:
if (reportId !== 7) return;
console.log('reportId: ' + reportId);
let zero_through_six = data.getUint8(0);
let report_data = [
(zero_through_six & 128) == 128, //0 (1-bit)
(zero_through_six & 64) == 64, //1 (1-bit)
(zero_through_six & 32) == 32, //2 (1-bit)
(zero_through_six & 16) == 16, //3 (1-bit)
(zero_through_six & 8) == 8, //4 (1-bit)
(zero_through_six & 4) == 4, //5 (1-bit)
zero_through_six & 3, //6 (2-bits)
data.getUint16(1), //7
data.getUint16(3), //8
data.getUint16(5), //9
data.getUint16(7), //10
data.getUint32(9), //11
data.getBigUint64(13), //12
data.getUint32(21), //13
data.getUint16(23), //14
data.getUint16(25), //15
data.getUint16(27), //16
data.getUint16(29), //17
data.getUint16(31), //18
data.getUint16(33), //19
];
console.log(report_data);
});
This is something I did on the to split the data I was getting into and array on the Windows version. The first items[1-6] were 1-bit, items[7] 2-bits, items[7-10] 16-bits and so on.
Again, because WebHID doesn't expose "Usage" on a per item basis, the sensor/button each item is mapped to is still unknown. At least outside of simple testing each one individually, which is hard to do on such a complex device.
Update 3:
Turns out that I don't really need the WebHID API
for my use case (getting sensor input from my digitizer). Looks like PointerEvent
and MouseEvent
properties cover my needs. (Really, should've look at that first actually (;一_一)) Atleast, I learned somewhat how to use the WebHID API.
I guess https://web.dev/devices-introduction/ would have been useful as it explains how to pick the appropriate API to communicate with a hardware device of your choice.
Glad you figured it out!