WebUSB API vs Serial API

2.5k views Asked by At

Both WebUSB and Web Serial API can be used to communicate with devices connected to your computer with a USB plug trough a Web browser.

I am totally new to programming with hardware/microcontrollers (only web development before), but I have tried extensively to find out what determines if a device can be read by which of the two API-s. Universial Serial Bus is serial after all, isn't it?! So my questions are as follows:

  • What determines if a device that is connected with a USB plug is compatible with the Serial API or WebUSB API?
  • Can this depend on which drivers I have on my computer? E.g. can this have something to do with USB CDC (which I frequently seem to stumble upon in my research) and a driver for this?
  • Can the same device be compatible with WebUSB on one computer, but Serial API on another? E.g. depending on available drivers or the host OS?
  • If I had used another programming environment, e.g. used C to write a native program, could I then choose freely to communicate with a particular device with either the "serial way" to do it or the USB protocol?

If it can enlighten the previous questions, here is my story of the USB exploration:

I have two different types of devices from the same manufacturer (both used to read electronic tags used for timing in running races), where in Chrome browser one appears in the popup for Serial API and the other appears in the popup for WebUSB when implemented basic functionality for both APIs. The one in Serial API I can communicate with by sending and receiving bytes trough the Streams API, but the WebUSB I need to communicate trough bulk transfers. In the Serial API transfer I never seems to lose data, but on bulk transfers in WebUSB I seem to lose data if I don't pull fast enough (i.e. does to much processing on the already pulled data before pulling again). So they both seem pretty "serial" to me, and it bothers my that I can't use SerialAPI for both (and that I don't understand why), which seems to be more reliable and uses the convenient Streams API.

I'm on OSX (10.14.6).

When I do ioreg -l -p IOUSB for the two devices, this is the result:

  • Serial API compatible device:
    +-o USB <-> Serial@14200000  <class AppleUSBDevice, id 0x10000d0b3, registered, matched, active, busy 0 (10 ms), retain 28>
        {
          "sessionID" = 210143274448224
          "iManufacturer" = 1
          "bNumConfigurations" = 1
          "idProduct" = 24577
          "bcdDevice" = 1024
          "Bus Power Available" = 250
          "USB Address" = 30
          "bMaxPacketSize0" = 8
          "iProduct" = 2
          "iSerialNumber" = 0
          "bDeviceClass" = 0
          "Built-In" = No
          "locationID" = 337641472
          "bDeviceSubClass" = 0
          "bcdUSB" = 272
          "USB Product Name" = "USB <-> Serial"
          "PortNum" = 1
          "non-removable" = "no"
          "IOCFPlugInTypes" = {"9dc7b780-9ec0-11d4-a54f-000a27052861"="IOUSBFamily.kext/Contents/PlugIns/IOUSBLib.bundle"}
          "bDeviceProtocol" = 0
          "IOUserClientClass" = "IOUSBDeviceUserClientV2"
          "IOPowerManagement" = {"DevicePowerState"=0,"CurrentPowerState"=4,"CapabilityFlags"=32768,"MaxPowerState"=4,"DriverPowerState"=4}
          "IOBusyInterest" = "IOCommand is not serializable"
          "Device Speed" = 1
          "USB Vendor Name" = "FTDI"
          "idVendor" = 1027
          "kUSBCurrentConfiguration" = 1
          "IOGeneralInterest" = "IOCommand is not serializable"
          "IOClassNameOverride" = "IOUSBDevice"
        }
  • WebUSB compatible device:
    +-o Emit eScan@14200000  <class AppleUSBDevice, id 0x10000d0d8, registered, matched, active, busy 0 (10 ms), retain 23>
        {
          "sessionID" = 210198267509902
          "iManufacturer" = 1
          "bNumConfigurations" = 1
          "idProduct" = 768
          "bcdDevice" = 274
          "Bus Power Available" = 250
          "USB Address" = 31
          "bMaxPacketSize0" = 8
          "iProduct" = 2
          "iSerialNumber" = 3
          "bDeviceClass" = 2
          "Built-In" = No
          "locationID" = 337641472
          "bDeviceSubClass" = 0
          "bcdUSB" = 512
          "USB Product Name" = "Emit eScan"
          "PortNum" = 2
          "non-removable" = "no"
          "IOCFPlugInTypes" = {"9dc7b780-9ec0-11d4-a54f-000a27052861"="IOUSBFamily.kext/Contents/PlugIns/IOUSBLib.bundle"}
          "bDeviceProtocol" = 0
          "IOUserClientClass" = "IOUSBDeviceUserClientV2"
          "IOPowerManagement" = {"DevicePowerState"=0,"CurrentPowerState"=4,"CapabilityFlags"=32768,"MaxPowerState"=4,"DriverPowerState"=4}
          "IOBusyInterest" = "IOCommand is not serializable"
          "Device Speed" = 1
          "USB Vendor Name" = "EMIT AS"
          "idVendor" = 8263
          "kUSBCurrentConfiguration" = 1
          "IOGeneralInterest" = "IOCommand is not serializable"
          "USB Serial Number" = "0969395112001500"
          "IOClassNameOverride" = "IOUSBDevice"
        }
1

There are 1 answers

5
Gerrit On BEST ANSWER

What determines if a device that is connected with a USB plug is compatible with the Serial API or WebUSB API?

It depends both on the driver and the device used. Some devices communicate over USB, while others use a serial protocol on top of USB.

On MacOS, if there's no driver (i.e, kernel/driver extension) installed for the device, the default USB driver will be used and you can access it using WebUSB (but not Web Serial). If the device uses a serial protocol on top of USB, you can write your own user-space serial driver.

On Windows, the default USB driver will not load if the special Microsoft OS descriptors are not specified by the device, so in most cases you have to install a driver to communicate with the device.

Can this depend on which drivers I have on my computer? E.g. can this have something to do with USB CDC (which I frequently seem to stumble upon in my research) and a driver for this?

Yes, CDC-ACM is one type of driver. There's also various other USB-serial chips (e.g. FTDI, Prolific, SiLabs, TI) that each have their own USB serial driver.

You also have some devices that uses HID over USB, in which you need to use the WebHID API to talk to them.

Can the same device be compatible with WebUSB on one computer, but Serial API on another? E.g. depending on available drivers or the host OS?

Yes, exactly. If you know that your target device has a specific chip, e.g. Prolific PL2303, you can first attempt to connect to it over Web Serial. If that fails, you can fall back to WebUSB and connect to it using a user-space serial driver that runs on top of WebUSB.

If I had used another programming environment, e.g. used C to write a native program, could I then choose freely to communicate with a particular device with either the "serial way" to do it or the USB protocol?

Not really. Your native program would also depend on the drivers that are installed. The difference is that the installer used to install your native program could also install the necessary drivers.