1
0
Fork 0
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:
Míguel Ángel Mulero Martínez 2024-05-31 17:59:46 +02:00 committed by GitHub
parent 617790b239
commit d0599ae455
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 151 additions and 54 deletions

View file

@ -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: () => [],
},

View file

@ -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: () => [],
},

View file

@ -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"

View file

@ -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;
};

View file

@ -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;

View file

@ -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)) {

View file

@ -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;
}