Using user-space USB drivers: Part 3

Feature image

Yesterday I mentioned starting on a Silicon Labs CP2102 user-space driver for Node.js. Well, I just managed to successfully read data from the device! The source code for the driver is already on GitHub, but I still need to write up usage instructions and do some testing.

I wrote it as a kind of WebUSB to node-usb interface, so that I can re-use parts of the code to easily port WebUSB drivers over to Node.js, or maybe I could even package the interface up as an NPM package? Then you can re-use your WebUSB drivers in Node.js by just by adding one line of code to import this package.

One thing that I found non-intuitive was that after sending a request for data as a USB bulk out transfer, you then either need to create another USB bulk in transfer to read data, or use node-usb's startPoll() function, which essentially starts polling for data on the IN endpoint. Also, if you're using endpoint 1, 0x01 is OUT and 0x81 is IN. You may find this code useful if you're trying to create a USB request type:

function getRequestType(direction, requestType, recipient) {
  const TYPES = {
    standard: 0x00,
    class: 0x01,
    vendor: 0x02,
    reserved: 0x03,

  const RECIPIENTS = {
    device: 0x00,
    interface: 0x01,
    endpoint: 0x02,
    other: 0x03,

  const DIRECTION = {
    'host-to-device': 0x00,
    'device-to-host': 0x01,

  return (DIRECTION[direction] << 7) || (TYPES[requestType] << 5) || RECIPIENTS[recipient];

I hope the stuff I learned today will help me when I continue my project to getting a USB host shield working on Espruino...