mirror of
https://github.com/betaflight/betaflight-configurator.git
synced 2025-07-25 17:25:16 +03:00
Add DFU devices to the port handler (#3991)
* Add DFU devices to the port handler The firmware flasher ignores it, at this moment. Needs a future PR to use it in place of the actual code that asks permission each time. * Remove the DFU word in the displayName of the USB devices some devices contain it in the productName, so better to remove it to not duplicate the name.
This commit is contained in:
parent
617790b239
commit
d0599ae455
7 changed files with 151 additions and 54 deletions
|
@ -12,7 +12,8 @@
|
|||
/>
|
||||
<PortsInput
|
||||
:value="value"
|
||||
:connected-devices="connectedDevices"
|
||||
:connected-serial-devices="connectedSerialDevices"
|
||||
:connected-usb-devices="connectedUsbDevices"
|
||||
:disabled="disabled"
|
||||
:show-virtual-option="showVirtualOption"
|
||||
:show-manual-option="showManualOption"
|
||||
|
@ -43,7 +44,11 @@ export default {
|
|||
autoConnect: true,
|
||||
}),
|
||||
},
|
||||
connectedDevices: {
|
||||
connectedUsbDevices: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
connectedSerialDevices: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
|
|
|
@ -32,11 +32,18 @@
|
|||
{{ $t("portsSelectVirtual") }}
|
||||
</option>
|
||||
<option
|
||||
v-for="connectedDevice in connectedDevices"
|
||||
:key="connectedDevice.path"
|
||||
:value="connectedDevice.path"
|
||||
v-for="connectedSerialDevice in connectedSerialDevices"
|
||||
:key="connectedSerialDevice.path"
|
||||
:value="connectedSerialDevice.path"
|
||||
>
|
||||
{{ connectedDevice.displayName }}
|
||||
{{ connectedSerialDevice.displayName }}
|
||||
</option>
|
||||
<option
|
||||
v-for="connectedUsbDevice in connectedUsbDevices"
|
||||
:key="connectedUsbDevice.path"
|
||||
:value="connectedUsbDevice.path"
|
||||
>
|
||||
{{ connectedUsbDevice.displayName }}
|
||||
</option>
|
||||
<option value="requestpermission">
|
||||
{{ $t("portsSelectPermission") }}
|
||||
|
@ -100,7 +107,11 @@ export default {
|
|||
autoConnect: true,
|
||||
}),
|
||||
},
|
||||
connectedDevices: {
|
||||
connectedSerialDevices: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
connectedUsbDevices: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
|
|
|
@ -28,7 +28,8 @@
|
|||
></betaflight-logo>
|
||||
<port-picker
|
||||
v-model="PortHandler.portPicker"
|
||||
:connected-devices="PortHandler.currentPorts"
|
||||
:connected-serial-devices="PortHandler.currentSerialPorts"
|
||||
:connected-usb-devices="PortHandler.currentUsbPorts"
|
||||
:show-virtual-option="PortHandler.showVirtualMode"
|
||||
:show-manual-option="PortHandler.showManualMode"
|
||||
:disabled="PortHandler.portPickerDisabled"
|
||||
|
|
|
@ -5,15 +5,18 @@ import { get as getConfig } from "./ConfigStorage";
|
|||
import { isWeb } from "./utils/isWeb";
|
||||
import { usbDevices } from "./usb_devices";
|
||||
import { serialShim } from "./serial_shim.js";
|
||||
import { usbShim } from "./usb_shim.js";
|
||||
import { EventBus } from "../components/eventBus";
|
||||
|
||||
const serial = serialShim();
|
||||
const usb = usbShim();
|
||||
|
||||
const DEFAULT_PORT = 'noselection';
|
||||
const DEFAULT_BAUDS = 115200;
|
||||
|
||||
const PortHandler = new function () {
|
||||
this.currentPorts = [];
|
||||
this.currentSerialPorts = [];
|
||||
this.currentUsbPorts = [];
|
||||
this.portPicker = {
|
||||
selectedPort: DEFAULT_PORT,
|
||||
selectedBauds: DEFAULT_BAUDS,
|
||||
|
@ -38,13 +41,10 @@ PortHandler.initialize = function () {
|
|||
serial.addEventListener("addedDevice", (event) => this.addedSerialDevice(event.detail));
|
||||
serial.addEventListener("removedDevice", (event) => this.removedSerialDevice(event.detail));
|
||||
|
||||
if (!this.portAvailable) {
|
||||
this.check_usb_devices();
|
||||
}
|
||||
usb.addEventListener("addedDevice", (event) => this.addedUsbDevice(event.detail));
|
||||
|
||||
if (!this.dfuAvailable) {
|
||||
this.addedSerialDevice();
|
||||
}
|
||||
this.addedUsbDevice();
|
||||
this.addedSerialDevice();
|
||||
};
|
||||
|
||||
PortHandler.setShowVirtualMode = function (showVirtualMode) {
|
||||
|
@ -58,18 +58,18 @@ PortHandler.setShowManualMode = function (showManualMode) {
|
|||
};
|
||||
|
||||
PortHandler.addedSerialDevice = function (device) {
|
||||
this.updateCurrentPortsList()
|
||||
this.updateCurrentSerialPortsList()
|
||||
.then(() => {
|
||||
const selectedPort = this.selectActivePort(device);
|
||||
if (!device || selectedPort === device.path) {
|
||||
// Send this event when the port handler auto selects a new device
|
||||
EventBus.$emit('port-handler:auto-select-device', selectedPort);
|
||||
EventBus.$emit('port-handler:auto-select-serial-device', selectedPort);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
PortHandler.removedSerialDevice = function (device) {
|
||||
this.updateCurrentPortsList()
|
||||
this.updateCurrentSerialPortsList()
|
||||
.then(() => {
|
||||
if (this.portPicker.selectedPort === device.path) {
|
||||
this.selectActivePort();
|
||||
|
@ -77,15 +77,36 @@ PortHandler.removedSerialDevice = function (device) {
|
|||
});
|
||||
};
|
||||
|
||||
PortHandler.addedUsbDevice = function (device) {
|
||||
this.updateCurrentUsbPortsList()
|
||||
.then(() => {
|
||||
const selectedPort = this.selectActivePort(device);
|
||||
if (!device || selectedPort === device.path) {
|
||||
// Send this event when the port handler auto selects a new device
|
||||
EventBus.$emit('port-handler:auto-select-usb-device', selectedPort);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
PortHandler.onChangeSelectedPort = function(port) {
|
||||
this.portPicker.selectedPort = port;
|
||||
};
|
||||
|
||||
PortHandler.updateCurrentPortsList = function () {
|
||||
PortHandler.updateCurrentSerialPortsList = function () {
|
||||
return serial.getDevices()
|
||||
.then((ports) => {
|
||||
ports = this.sortPorts(ports);
|
||||
this.currentPorts = ports;
|
||||
const orderedPorts = this.sortPorts(ports);
|
||||
this.portAvailable = orderedPorts.length > 0;
|
||||
this.currentSerialPorts = orderedPorts;
|
||||
});
|
||||
};
|
||||
|
||||
PortHandler.updateCurrentUsbPortsList = function () {
|
||||
return usb.getDevices()
|
||||
.then((ports) => {
|
||||
const orderedPorts = this.sortPorts(ports);
|
||||
this.dfuAvailable = orderedPorts.length > 0;
|
||||
this.currentUsbPorts = orderedPorts;
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -110,43 +131,54 @@ PortHandler.askSerialPermissionPort = function() {
|
|||
|
||||
PortHandler.selectActivePort = function(suggestedDevice) {
|
||||
|
||||
// Return the same that is connected
|
||||
if (serial.connected) {
|
||||
return serial.getConnectedPort();
|
||||
}
|
||||
|
||||
let selectedPort;
|
||||
const deviceFilter = ['AT32', 'CP210', 'SPR', 'STM'];
|
||||
let selectedPort;
|
||||
|
||||
if (suggestedDevice) {
|
||||
// Return the same that is connected to serial
|
||||
if (serial.connected) {
|
||||
selectedPort = serial.getConnectedPort();
|
||||
}
|
||||
|
||||
// Return the same that is connected to usb (dfu mode)
|
||||
if (usb.usbDevice) {
|
||||
selectedPort = usb.getConnectedPort();
|
||||
}
|
||||
|
||||
// Return the suggested device (the new device that has been detected)
|
||||
if (!selectedPort && suggestedDevice) {
|
||||
selectedPort = suggestedDevice.path;
|
||||
this.portAvailable = true;
|
||||
} else {
|
||||
for (let port of this.currentPorts) {
|
||||
const portName = port.displayName;
|
||||
const pathSelect = port.path;
|
||||
const deviceRecognized = deviceFilter.some(device => portName.includes(device));
|
||||
const legacyDeviceRecognized = portName.includes('usb');
|
||||
if (deviceRecognized || legacyDeviceRecognized) {
|
||||
selectedPort = pathSelect;
|
||||
this.portAvailable = true;
|
||||
console.log(`Porthandler detected device ${portName} on port: ${pathSelect}`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!selectedPort) {
|
||||
this.portAvailable = false;
|
||||
if (this.showVirtualMode) {
|
||||
selectedPort = "virtual";
|
||||
} else if (this.showManualMode) {
|
||||
selectedPort = "manual";
|
||||
}
|
||||
// Return some serial port that is recognized by the filter
|
||||
if (!selectedPort) {
|
||||
selectedPort = this.currentUsbPorts.find(device => deviceFilter.some(filter => device.displayName.includes(filter)));
|
||||
if (selectedPort) {
|
||||
selectedPort = selectedPort.path;
|
||||
}
|
||||
}
|
||||
|
||||
// Return some usb port that is recognized by the filter
|
||||
if (!selectedPort) {
|
||||
selectedPort = this.currentSerialPorts.find(device => deviceFilter.some(filter => device.displayName.includes(filter)));
|
||||
if (selectedPort) {
|
||||
selectedPort = selectedPort.path;
|
||||
}
|
||||
}
|
||||
|
||||
// Return the virtual port
|
||||
if (!selectedPort && this.showVirtualMode) {
|
||||
selectedPort = "virtual";
|
||||
}
|
||||
|
||||
// Return the manual port
|
||||
if (!selectedPort && this.showManualMode) {
|
||||
selectedPort = "manual";
|
||||
}
|
||||
|
||||
// Return the default port if no other port was selected
|
||||
this.portPicker.selectedPort = selectedPort || DEFAULT_PORT;
|
||||
console.log(`Porthandler default device is '${this.portPicker.selectedPort}'`);
|
||||
|
||||
console.log(`Porthandler automatically selected device is '${this.portPicker.selectedPort}'`);
|
||||
return selectedPort;
|
||||
};
|
||||
|
||||
|
|
|
@ -18,8 +18,9 @@ import { i18n } from "../localization";
|
|||
import { gui_log } from "../gui_log";
|
||||
import { usbDevices } from "../usb_devices";
|
||||
|
||||
class WEBUSBDFU_protocol {
|
||||
class WEBUSBDFU_protocol extends EventTarget {
|
||||
constructor() {
|
||||
super();
|
||||
this.callback = null;
|
||||
this.hex = null;
|
||||
this.verify_hex = [];
|
||||
|
@ -70,6 +71,53 @@ class WEBUSBDFU_protocol {
|
|||
this.chipInfo = null; // information about chip's memory
|
||||
this.flash_layout = { 'start_address': 0, 'total_size': 0, 'sectors': [] };
|
||||
this.transferSize = 2048; // Default USB DFU transfer size for F3,F4 and F7
|
||||
|
||||
navigator.usb.addEventListener("connect", e => this.handleNewDevice(e.device));
|
||||
navigator.usb.addEventListener("disconnect", e => this.handleNewDevice(e.device));
|
||||
}
|
||||
handleNewDevice(device) {
|
||||
const added = this.createPort(device);
|
||||
this.dispatchEvent(new CustomEvent("addedDevice", { detail: added }));
|
||||
|
||||
return added;
|
||||
}
|
||||
handleRemovedDevice(device) {
|
||||
const removed = this.createPort(device);
|
||||
this.dispatchEvent(new CustomEvent("removedDevice", { detail: removed }));
|
||||
}
|
||||
createPort(port) {
|
||||
return {
|
||||
path: `usb_${port.serialNumber}`,
|
||||
displayName: `Betaflight ${port.productName}`,
|
||||
vendorId: port.manufacturerName,
|
||||
productId: port.productName,
|
||||
port: port,
|
||||
};
|
||||
}
|
||||
async getDevices() {
|
||||
const ports = await navigator.usb.getDevices(usbDevices);
|
||||
const customPorts = ports.map(function (port) {
|
||||
return this.createPort(port);
|
||||
}, this);
|
||||
|
||||
return customPorts;
|
||||
}
|
||||
async requestPermission() {
|
||||
let newPermissionPort = null;
|
||||
try {
|
||||
const userSelectedPort = await navigator.usb.requestDevice(usbDevices);
|
||||
console.info("User selected USB device from permissions:", userSelectedPort);
|
||||
console.log(`WebUSB Version: ${userSelectedPort.deviceVersionMajor}.${userSelectedPort.deviceVersionMinor}.${userSelectedPort.deviceVersionSubminor}`);
|
||||
|
||||
newPermissionPort = this.handleNewDevice(userSelectedPort);
|
||||
} catch (error) {
|
||||
console.error("User didn't select any USB device when requesting permission:", error);
|
||||
}
|
||||
return newPermissionPort;
|
||||
|
||||
}
|
||||
getConnectedPort() {
|
||||
return this.usbDevice ? `usb_${this.usbDevice.serialNumber}` : null;
|
||||
}
|
||||
connect(hex, options, callback) {
|
||||
this.hex = hex;
|
||||
|
|
|
@ -67,7 +67,7 @@ export function initializeSerialBackend() {
|
|||
|
||||
$("div.connect_controls a.connect").on('click', connectDisconnect);
|
||||
|
||||
EventBus.$on('port-handler:auto-select-device', function(device) {
|
||||
EventBus.$on('port-handler:auto-select-serial-device', function(device) {
|
||||
if (!GUI.connected_to && !GUI.connecting_to
|
||||
&& ((PortHandler.portPicker.autoConnect && !["manual", "virtual"].includes(device))
|
||||
|| Date.now() - rebootTimestamp < REBOOT_CONNECT_MAX_TIME_MS)) {
|
||||
|
|
|
@ -105,9 +105,9 @@ class WebSerial extends EventTarget {
|
|||
if (!newPermissionPort) {
|
||||
newPermissionPort = this.handleNewDevice(userSelectedPort);
|
||||
}
|
||||
console.info("User selected device from permissions:", newPermissionPort.path);
|
||||
console.info(`${this.logHead}User selected SERIAL device from permissions:`, newPermissionPort.path);
|
||||
} catch (error) {
|
||||
console.error("User didn't select any device when requesting permission:", error);
|
||||
console.error(`${this.logHead}User didn't select any SERIAL device when requesting permission:`, error);
|
||||
}
|
||||
return newPermissionPort;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue