poll static method

Future<String> poll(
  1. int timeout,
  2. bool probeMagic
)

Try to poll a WebUSB device according to our protocol.

Implementation

static Future<String> poll(int timeout, bool probeMagic) async {
  // request WebUSB device with custom classcode
  if (!_deviceAvailable()) {
    var devicePromise = _USB.requestDevice(_USBDeviceRequestOptions(
        filters: [_USBDeviceFilter(classCode: USB_CLASS_CODE_VENDOR_SPECIFIC)]
            .toJS));
    dynamic device = await promiseToFuture(devicePromise);
    try {
      await promiseToFuture(callMethod(device, 'open', List.empty()))
          .then((_) =>
              promiseToFuture(callMethod(device, 'claimInterface', [1])))
          .timeout(Duration(milliseconds: timeout));
      _device = device;
      _USB.ondisconnect = () {
        _device = null;
        onDisconnect?.call();
      }.toJS;
      log.info("WebUSB device opened", _device);
    } on TimeoutException catch (_) {
      log.severe("Polling tag timeout");
      throw PlatformException(code: "408", message: "Polling tag timeout");
    } on Exception catch (e) {
      log.severe("Poll error", e);
      throw PlatformException(
          code: "500", message: "WebUSB API error", details: e);
    }

    if (probeMagic) {
      try {
        // PROBE request
        var promise = callMethod(_device, 'controlTransferIn', [
          _USBControlTransferParameters(
              requestType: 'vendor',
              recipient: 'interface',
              request: 0xff,
              value: 0,
              index: 1),
          1
        ]);
        var resp = await promiseToFuture(promise);
        if (getProperty(resp, 'status') == 'stalled') {
          throw PlatformException(
              code: "500", message: "Device error: transfer stalled");
        }
        var result =
            (getProperty(resp, 'data').buffer as ByteBuffer).asUint8List();
        if (result.length < USB_PROBE_MAGIC.length ||
            result.sublist(0, USB_PROBE_MAGIC.length) !=
                Uint8List.fromList(USB_PROBE_MAGIC.codeUnits)) {
          throw PlatformException(
              code: "500",
              message:
                  "Device error: invalid probe response: ${hex.encode(result)}, should begin with $USB_PROBE_MAGIC");
        }
        customProbeData = hex.encode(result.sublist(USB_PROBE_MAGIC.length));
      } on Exception catch (e) {
        log.severe("Probe error", e);
        throw PlatformException(
            code: "500", message: "WebUSB API error", details: e);
      }
    } else {
      customProbeData = "";
    }
  }
  // get VID & PID
  int vendorId = getProperty(_device, 'vendorId');
  int productId = getProperty(_device, 'productId');
  String id =
      '${vendorId.toRadixString(16).padLeft(4, '0')}:${productId.toRadixString(16).padLeft(4, '0')}';
  return json.encode({
    'type': 'webusb',
    'id': id,
    'standard': 'nfc-im-webusb-protocol',
    'customProbeData': customProbeData
  });
}