third_party/libusb/webport/src/libusb-to-webusb-adaptor.js
/**
 * Fills the extraData fields of the passed configuration by fetching and
 * parsing USB descriptors from the device.
 * @param {!Object} webusbDevice The WebUSB USBDevice value.
 * @param {!LibusbJsConfigurationDescriptor} libusbJsConfiguration
 */
Fills the extraData fields of the passed configuration by fetching and
parsing USB descriptors from the device.
@param {!Object} webusbDevice The WebUSB USBDevice value.
Fills the extraData fields of the passed configuration by fetching and parsing USB descriptors from the device . @param { !Object } webusbDevice The WebUSB USBDevice value .
async function fetchAndFillConfigurationExtraDataForOpenedDevice(
    webusbDevice, libusbJsConfiguration) {
  const GET_DESCRIPTOR_REQUEST = 0x06;
  const CONFIGURATION_DESCRIPTOR_TYPE = 0x02;
  const INTERFACE_DESCRIPTOR_TYPE = 0x04;
  const ENDPOINT_DESCRIPTOR_TYPE = 0x05;
  const CONFIGURATION_DESCRIPTOR_LENGTH = 9;
  const INTERFACE_DESCRIPTOR_LENGTH = 9;
  const ENDPOINT_DESCRIPTOR_LENGTH = 7;
  const controlRequestValue = (CONFIGURATION_DESCRIPTOR_TYPE << 8) |
      (libusbJsConfiguration['configurationValue'] - 1);
  const controlTransferParameters = {
    'requestType': 'standard',
    'recipient': 'device',
    'request': GET_DESCRIPTOR_REQUEST,
    'value': controlRequestValue,
    'index': 0
  };
  let transferResult = await webusbDevice['controlTransferIn'](
      controlTransferParameters, CONFIGURATION_DESCRIPTOR_LENGTH);
  if (transferResult['status'] !== 'ok' || !transferResult['data'])
    return;
  const initialData =  (transferResult['data']);
  const totalLength = initialData.getUint16(2,  true);
  transferResult = await webusbDevice['controlTransferIn'](
      controlTransferParameters, totalLength);
  if (transferResult['status'] !== 'ok' || !transferResult['data'])
    return;
  const descriptors =  (transferResult['data']);
  if (descriptors.byteLength !== totalLength)
    return;
  let currentInterface = undefined;
  let currentEndpoint = undefined;
  for (let offset = 0; offset < totalLength;) {
    const descriptorLength = descriptors.getUint8(offset);
    if (descriptorLength < 2) {
      return;
    }
    if (offset + descriptorLength > totalLength) {
      break;
    }
    const descriptorType = descriptors.getUint8(offset + 1);
    switch (descriptorType) {
      case CONFIGURATION_DESCRIPTOR_TYPE: {
        if (descriptorLength < CONFIGURATION_DESCRIPTOR_LENGTH) {
          break;
        }
        break;
      }
      case INTERFACE_DESCRIPTOR_TYPE: {
        if (descriptorLength < INTERFACE_DESCRIPTOR_LENGTH) {
          break;
        }
        const interfaceNumber = descriptors.getUint8(offset + 2);
        currentInterface = libusbJsConfiguration['interfaces'].find(
            libusbJsInterface =>
                libusbJsInterface['interfaceNumber'] === interfaceNumber);
        currentEndpoint = undefined;
        break;
      }
      case ENDPOINT_DESCRIPTOR_TYPE: {
        if (descriptorLength < ENDPOINT_DESCRIPTOR_LENGTH) {
          break;
        }
        const endpointAddress = descriptors.getUint8(offset + 2);
        if (currentInterface) {
          currentEndpoint = currentInterface['endpoints'].find(
              libusbJsEndpoint =>
                  libusbJsEndpoint['endpointAddress'] === endpointAddress);
        } else {
          currentEndpoint = undefined;
        }
        break;
      }
      default: {
        const targetObject =
            currentEndpoint || currentInterface || libusbJsConfiguration;
        if (targetObject) {
          appendExtraData(
              new Uint8Array(
                  descriptors.buffer, descriptors.byteOffset + offset,
                  descriptorLength),
              targetObject);
        }
        break;
      }
    }
    offset += descriptorLength;
  }
}
async function fetchAndFillConfigurationExtraDataForOpenedDevice ( webusbDevice , libusbJsConfiguration ) { const GET_DESCRIPTOR_REQUEST = 0x06 ; const CONFIGURATION_DESCRIPTOR_TYPE = 0x02 ; const INTERFACE_DESCRIPTOR_TYPE = 0x04 ; const ENDPOINT_DESCRIPTOR_TYPE = 0x05 ; const CONFIGURATION_DESCRIPTOR_LENGTH = 9 ; const INTERFACE_DESCRIPTOR_LENGTH = 9 ; const ENDPOINT_DESCRIPTOR_LENGTH = 7 ; const controlRequestValue = ( CONFIGURATION_DESCRIPTOR_TYPE << 8 ) | ( libusbJsConfiguration [ 'configurationValue' ] - 1 ) ; const controlTransferParameters = { 'requestType' : 'standard' , 'recipient' : 'device' , 'request' : GET_DESCRIPTOR_REQUEST , 'value' : controlRequestValue , 'index' : 0 } ; let transferResult = await webusbDevice [ 'controlTransferIn' ] ( controlTransferParameters , CONFIGURATION_DESCRIPTOR_LENGTH ) ; if ( transferResult [ 'status' ] !== 'ok' || ! transferResult [ 'data' ] ) return ; const initialData = ( transferResult [ 'data' ] ) ; const totalLength = initialData . getUint16 ( 2 , true ) ; transferResult = await webusbDevice [ 'controlTransferIn' ] ( controlTransferParameters , totalLength ) ; if ( transferResult [ 'status' ] !== 'ok' || ! transferResult [ 'data' ] ) return ; const descriptors = ( transferResult [ 'data' ] ) ; if ( descriptors . byteLength !== totalLength ) return ; let currentInterface = undefined ; let currentEndpoint = undefined ; for ( let offset = 0 ; offset < totalLength ; ) { const descriptorLength = descriptors . getUint8 ( offset ) ; if ( descriptorLength < 2 ) { return ; } if ( offset + descriptorLength > totalLength ) { break ; } const descriptorType = descriptors . getUint8 ( offset + 1 ) ; switch ( descriptorType ) { case CONFIGURATION_DESCRIPTOR_TYPE : { if ( descriptorLength < CONFIGURATION_DESCRIPTOR_LENGTH ) { break ; } break ; } case INTERFACE_DESCRIPTOR_TYPE : { if ( descriptorLength < INTERFACE_DESCRIPTOR_LENGTH ) { break ; } const interfaceNumber = descriptors . getUint8 ( offset + 2 ) ; currentInterface = libusbJsConfiguration [ 'interfaces' ] . find ( libusbJsInterface => libusbJsInterface [ 'interfaceNumber' ] === interfaceNumber ) ; currentEndpoint = undefined ; break ; } case ENDPOINT_DESCRIPTOR_TYPE : { if ( descriptorLength < ENDPOINT_DESCRIPTOR_LENGTH ) { break ; } const endpointAddress = descriptors . getUint8 ( offset + 2 ) ; if ( currentInterface ) { currentEndpoint = currentInterface [ 'endpoints' ] . find ( libusbJsEndpoint => libusbJsEndpoint [ 'endpointAddress' ] === endpointAddress ) ; } else { currentEndpoint = undefined ; } break ; } default : { const targetObject = currentEndpoint || currentInterface || libusbJsConfiguration ; if ( targetObject ) { appendExtraData ( new Uint8Array ( descriptors . buffer , descriptors . byteOffset + offset , descriptorLength ) , targetObject ) ; } break ; } } offset += descriptorLength ; } }
Fills the extraData fields of the passed configuration by fetching and
 parsing USB descriptors from the device.
Fills the extraData fields of the passed configuration by fetching and parsing USB descriptors from the device .
// Determine the size of the whole descriptor hierarchy ("wTotalLength"). /** @type {!DataView} */ /*littleEndian=*/ // Read the whole descriptor hierarchy. /** @type {!DataView} */ // Parse descriptors one-by-one from the fetched concatenated blob. Maintain // pointers to the LibusbJs objects that correspond to the currently parsed // interface/endpoint descriptor. /** @type {!LibusbJsInterfaceDescriptor|undefined} */ /** @type {!LibusbJsEndpointDescriptor|undefined} */ // This is a malformed descriptor - bail out immediately (so that, for // example, we don't hang because of a zero in the descriptor length // field). // Ignore the truncated descriptor. // Ignore the invalid (too short) descriptor. // The current item is the configuration descriptor. There should be // only one such item returned and it should refer to // `libusbJsConfiguration`, so nothing needs to be done here. // Ignore the invalid (too short) descriptor. // The current item is the interface descriptor. Parse the interface // number and switch the pointer to the corresponding // `LibusbJsInterfaceDescriptor`. // Ignore the invalid (too short) descriptor. // The current item is the endpoint descriptor. Parse the endpoint // address and switch the pointer to the corresponding // `LibusbJsEndpointDescriptor`. // The current item is an unknown descriptor, so add it as extraData to // the current (the most nested one) LibusbJs object. // Jump to the next descriptor in the blob.