bobajeff
bobajeff

Reputation: 141

WebHID API: How do I parse data from inputReport event?

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: devtools screenshot windows 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: enter image description here

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.

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.

Upvotes: 1

Views: 1159

Answers (1)

François Beaufort
François Beaufort

Reputation: 5659

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!

Upvotes: 2

Related Questions