Chrome.hid.send Doesn't work on PCs, but works on Macs

I have the same basic test running on both Mac and PC, but it seems to fail when I try to run on PC. This is a CONTINUOUS DISCOUNT because the whole reason I am building on top of chrome is what I thought was a cross platform HID API . Is there a bug in the windows port of this API?

  COMMS.transmitting = true;
  console.log("Sending...");
  chrome.hid.send(connection_, REPORT_ID, arrayBuffer, function() {
    if (chrome.runtime.lastError) {
      throw chrome.runtime.lastError.message;
      COMMS.transmitting = false;
      return;
    }

    console.log("done sending.");
    COMMS.transmitting = false;
    console.log("Receiving...");
    COMMS.receiving = true;
    chrome.hid.receive(connection_, function(reportId, data) {
      if (chrome.runtime.lastError) {
        throw chrome.runtime.lastError.message;
        COMMS.receiving = false;
        return;
      }

      console.log("done receiving.");
      COMMS.receiving = false;
      responseHandler(data);
    });
  });

      

Complete comms.js file:

//
// Description: Communication abstractions.  This is currently built on the 
// chrome.hid API.
//
var COMMS = (function() {
  // -------------------------------------------------------------------------------------------------------------------
  // Private Constants
  // -------------------------------------------------------------------------------------------------------------------
  var REPORT_ID = 0;
  var MAX_NUM_RX_BYTES = 64;
  var MAX_NUM_TX_BYTES = 64;

  // -------------------------------------------------------------------------------------------------------------------
  // Private Properties
  // -------------------------------------------------------------------------------------------------------------------
  var connection_;
  var onDeviceConnected_;

  // -------------------------------------------------------------------------------------------------------------------
  // Private Methods
  // -------------------------------------------------------------------------------------------------------------------
  var enumerateDevices = function() {
    var deviceIds = [];
    var permissions = chrome.runtime.getManifest().permissions;
    for (var i = 0; i < permissions.length; i++) {
      var p = permissions[i];
      if (p.hasOwnProperty('usbDevices')) {
        deviceIds = deviceIds.concat(p.usbDevices);
      }
    }

    // REMOVE AFTER TESING
    deviceFilter = {
      vendorId: 1234, // replace with your own VID/PID combo, should match permissions values
      productId: 5678
    };
    // Only search for the first VID/PID device specified in the permissions
    //chrome.hid.getDevices(deviceIds[0], onDevicesEnumerated);
    chrome.hid.getDevices(deviceFilter, onDevicesEnumerated);
  };

  var onDevicesEnumerated = function(devices) {
    if (chrome.runtime.lastError) {
      console.log(chrome.runtime.lastError.message);
      return;
    }

    if (1 !== devices.length) {
      console.log("Ensure one (and only one) device is inserted.");
      // Schedule the next attempt
      window.setTimeout(enumerateDevices, 2000);
    } else {
      console.log("Found a device");
      connectDevice(devices[0].deviceId);
    }
  };

  var connectDevice = function(deviceId) {
    chrome.hid.connect(deviceId, function(connectInfo) {
      if (chrome.runtime.lastError) {
        console.log(chrome.runtime.lastError.message);
        return;
      }

      if (!connectInfo) {
        console.log("Failed to connect to device.");
        this.transmitting = false;
        this.receiving = false;
        return;
      }

      connection_ = connectInfo.connectionId;
      console.log("connection: " + connection_);
      onDeviceConnected_();
    });
  };

  var byteToHex = function(value) {
    if (value < 16) {
      return '0' + value.toString(16);
    }

    return value.toString(16);
  };

  return {
    // -----------------------------------------------------------------------------------------------------------------
    // Public Properties
    // -----------------------------------------------------------------------------------------------------------------
    transmitting: false,
    receiving: false,

    // -----------------------------------------------------------------------------------------------------------------
    // Public Methods
    // -----------------------------------------------------------------------------------------------------------------
    init: function(onConnectedHandler) {
      // Initialize module memory
      connection_ = -1;
      onDeviceConnected_ = onConnectedHandler;
      // Begin the search for a single, predetermined device
      enumerateDevices();
    },

    isConnected: function() {
      return (-1 !== connection_);
    },

    send: function(arrayBuffer, responseHandler) {      
      if (-1 === connection_) {
        throw "Attempted to send data with no device connected.";
        return;
      }
      if (true === COMMS.receiving) {
        throw "Waiting for a response to a previous message.  Aborting.";
        return;
      }
      if (true === COMMS.transmitting) {
        throw "Still waiting to finish sending a previous message.";
        return;
      }
      if (-1 === connection_) {
        throw "Attempted to send without a device connected.";
        return;
      }
      if (MAX_NUM_TX_BYTES < arrayBuffer.byteLength) {
        throw "Given data is too long to send as a single message.";
        return;
      }
      if (0 === arrayBuffer.byteLength) {
        throw "Given data to transmit is empty";
        return;
      }

      COMMS.transmitting = true;
      console.log("Sending...");

      chrome.hid.send(connection_, REPORT_ID, arrayBuffer, function() {
        if (chrome.runtime.lastError) {
          throw chrome.runtime.lastError.message;
          COMMS.transmitting = false;
          return;
        }

        console.log("done sending.");
        COMMS.transmitting = false;
        console.log("Receiving...");
        COMMS.receiving = true;
        chrome.hid.receive(connection_, function(reportId, data) {
          if (chrome.runtime.lastError) {
            throw chrome.runtime.lastError.message;
            COMMS.receiving = false;
            return;
          }

          console.log("done receiving.");
          COMMS.receiving = false;
          responseHandler(data);
        });
      });
    },

    disconnectDevice: function() {
      if (-1 === connection_) {
        console.log("Attempted to disconnect device with no device connected");
        COMMS.transmitting = false;
        COMMS.receiving = false;
        return;
      }

      chrome.hid.disconnect(connection_, function() {
        if (chrome.runtime.lastError) {
          console.log(chrome.runtime.lastError.message);
          return;
        }

        // TODO: how to check that successfully disconnected?
        console.log("Finished disconnecting device.  Success?");
        COMMS.transmitting = false;
        COMMS.receiving = false;
      });
    },

    hexStringToArrayBuffer: function(s) {
      var bytes = new Uint8Array(s.length);
      for (var i = 0; i < s.length; i += 3) {
        if (' ' === s[i]) {
          console.log('Error parsing hex string');
          return;
        }

        bytes[i] = parseInt(s.substring(i, (i + 2)), 16);
      }

      return bytes.buffer;
    },

    byteArrayToFormattedString: function(byteArray) {
      var s = '';
      for (var i = 0; i < byteArray.length; i += 16) {
        var sliceLength = Math.min(byteArray.length - i, 16);
        var lineBytes = new Uint8Array(byteArray.buffer, i, sliceLength);
        for (var j = 0; j < lineBytes.length; ++j) {
          s += byteToHex(lineBytes[j]) + ' ';
        }
        for (var j = 0; j < lineBytes.length; ++j) {
          var ch = String.fromCharCode(lineBytes[j]);
          if (lineBytes[j] < 32 || lineBytes[j] > 126)
            ch = '.';
          s += ch;
        }
        s += '\n';
      }
      return s;
    }
  }
})();

      

+3


source to share


1 answer


The OP asked this question again here . Sorry I didn't notice the answer to my initial questions and have followed through here. The problem is that Windows requires the buffers to be the maximum report size expected by the device. I have filed a bug against Chromium to keep track of adding a workaround, or at least a better bug report to pinpoint the problem.



In general, you can get more verbose error messages from the chrome.hid API by enabling verbose logging using command line parameters --enable-logging --v=1

. Full documentation on Chrome registration is here .

+2


source







All Articles