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));
    var device = await devicePromise.toDart;
    try {
      var openPromise = device.callMethod('open'.toJS) as JSPromise;
      await openPromise.toDart
          .then((_) =>
              (device.callMethod('claimInterface'.toJS, 1.toJS) as JSPromise)
                  .toDart)
          .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 = device.callMethod(
            'controlTransferIn'.toJS,
            _USBControlTransferParameters(
                requestType: 'vendor',
                recipient: 'interface',
                request: 0xff,
                value: 0,
                index: 1),
            1.toJS) as JSPromise<JSObject>;
        var resp = await promise.toDart;
        if (resp.getProperty<JSString>('status'.toJS).toDart == 'stalled') {
          throw PlatformException(
              code: "500", message: "Device error: transfer stalled");
        }
        var result = _getDataBufferFromResponse(resp);
        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 = "";
    }
  }
  assert(_device != null);
  // get VID & PID
  var vendorId = _device!.getProperty<JSNumber>('vendorId'.toJS).toDartInt;
  var productId = _device!.getProperty<JSNumber>('productId'.toJS).toDartInt;
  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
  });
}