Using WebUSB API to read data from a barcode scanner

2.2k views Asked by At

I'm trying to use WebUSB API to read data from a usb barcode device.

(Specifically I use a Datalogic QuickScan Lite qw2100. And I have configured the scanner to use the USB-COM-STD Interface.)

Using the code below I can actually read data from the device. But only char by char. Ie the transferIn call only returns 1 character. So to read the entire barcode I need to loop.

My questions:

  1. Is this the intended behavior of transferIn? Or could it be that I use the wrong interface? Or can the transfer-mode be configured using the controlTransferOut?

  2. Also, the other USB interface settings are all based on interfaceClass 10 (HID). But I have had no luck using WebHID with this device. I get a NotAllowedError: Failed to open the device. error when I try to call open() on the HIDDevice object.

  3. Last but not least, is using WebUSB (or WebHID) a practical path to build barcode apps. I have seen many examples of usb devices using WebUSB, but very few examples of barcode readers. This makes me think I'm on the wrong path.

Kind regards!


    try {

      const filters = [{
        vendorId: 1529,    // Datalogic ADC, Inc
        productId: 16900   // Handheld Barcode Scanner
      }];
      const device = await navigator.usb.requestDevice({ filters })

      const configuration_number = 1  // device.configuration.configurationValue
      const interface_number = 1      // device.configuration.interfaces[1].interfaceNumber
      const interface_class = 10      // device.configuration.interfaces[1].alternates[0].interfaceClass
      console.log(device);
      console.log(`configuration number :  ${configuration_number}`);
      console.log(`interface number : ${interface_number} `);
      console.log(`interface class : ${interface_class} `);

      await device.open();
      await device.selectConfiguration(configuration_number);
      await device.claimInterface(interface_number);
      await device.controlTransferOut({
        requestType: 'class',
        recipient: 'interface',
        request: 0x22,
        value: 0x10,
        index: interface_number
      });

      const read = async (device) => {
        const result = await device.transferIn(2, 64);
        const decoder = new TextDecoder();
        const message = decoder.decode(result.data);
        return message
      }

      var m
      do {
        m = await read(device)
        console.log(m);
      } while (m.charCodeAt(0) !== 13)

    } catch (error) {
      console.log(error);
    }
2

There are 2 answers

3
Herbert Lee On

I have not used the barcode scanner that you're using, but my experience with barcode scanners is that they are configured to work like keyboards, and don't require any USB-specific code to work.

Try putting your mouse cursor in a text editor and scanning a barcode - the number associated with the barcode should show up in the editor.

1
Reilly Grant On

How much data is sent from the device (barcode scanner) to the host (laptop) in each transfer is entirely controlled by the device. For a device that also has the option to emulate a keyboard it is unsurprising to me that it would send the data one character at a time. It is possible that this is configurable, as you suggested, by sending a control transfer. I would ask the manufacturer of the device for documentation of any control transfers it supports.

It is likely not practical to use WebHID to read data from the barcode scanner because in HID mode the device likely looks indistinguishable from a keyboard and these are not permitted by the API implementation.