diff --git a/www/manager6/Utils.js b/www/manager6/Utils.js index 7ca6a271..adcf082f 100644 --- a/www/manager6/Utils.js +++ b/www/manager6/Utils.js @@ -1569,7 +1569,58 @@ Ext.define('PVE.Utils', { } }, - hardware_counts: { net: 32, usb: 5, hostpci: 16, audio: 1, efidisk: 1, serial: 4, rng: 1, tpmstate: 1 }, + hardware_counts: { + net: 32, + usb: 14, + usb_old: 5, + hostpci: 16, + audio: 1, + efidisk: 1, + serial: 4, + rng: 1, + tpmstate: 1, + }, + + // we can have usb6 and up only for specific machine/ostypes + get_max_usb_count: function(ostype, machine) { + if (!ostype) { + return PVE.Utils.hardware_counts.usb_old; + } + + let match = /-(\d+).(\d+)/.exec(machine ?? ''); + if (!match || PVE.Utils.qemu_min_version([match[1], match[2]], [7, 1])) { + if (ostype === 'l26') { + return PVE.Utils.hardware_counts.usb; + } + let os_match = /^win(\d+)$/.exec(ostype); + if (os_match && os_match[1] > 7) { + return PVE.Utils.hardware_counts.usb; + } + } + + return PVE.Utils.hardware_counts.usb_old; + }, + + // parameters are expected to be arrays, e.g. [7,1], [4,0,1] + // returns true if toCheck is equal or greater than minVersion + qemu_min_version: function(toCheck, minVersion) { + let i; + for (i = 0; i < toCheck.length && i < minVersion.length; i++) { + if (toCheck[i] < minVersion[i]) { + return false; + } + } + + if (minVersion.length > toCheck.length) { + for (; i < minVersion.length; i++) { + if (minVersion[i] !== 0) { + return false; + } + } + } + + return true; + }, cleanEmptyObjectKeys: function(obj) { for (const propName of Object.keys(obj)) { diff --git a/www/manager6/qemu/HardwareView.js b/www/manager6/qemu/HardwareView.js index 6e9d03b4..96fd37e9 100644 --- a/www/manager6/qemu/HardwareView.js +++ b/www/manager6/qemu/HardwareView.js @@ -544,6 +544,11 @@ Ext.define('PVE.qemu.HardwareView', { let counts = {}; let isAtLimit = (type) => counts[type] >= PVE.Utils.hardware_counts[type]; + let isAtUsbLimit = () => { + let ostype = me.getObjectValue('ostype'); + let machine = me.getObjectValue('machine'); + return counts.usb >= PVE.Utils.get_max_usb_count(ostype, machine); + }; let set_button_status = function() { let selection_model = me.getSelectionModel(); @@ -570,7 +575,7 @@ Ext.define('PVE.qemu.HardwareView', { const noVMConfigNetPerm = !caps.vms['VM.Config.Network']; const noVMConfigDiskPerm = !caps.vms['VM.Config.Disk']; - me.down('#addUsb').setDisabled(noSysConsolePerm || isAtLimit('usb')); + me.down('#addUsb').setDisabled(noSysConsolePerm || isAtUsbLimit()); me.down('#addPci').setDisabled(noSysConsolePerm || isAtLimit('hostpci')); me.down('#addAudio').setDisabled(noVMConfigHWTypePerm || isAtLimit('audio')); me.down('#addSerial').setDisabled(noVMConfigHWTypePerm || isAtLimit('serial')); diff --git a/www/manager6/qemu/USBEdit.js b/www/manager6/qemu/USBEdit.js index 4373f82c..fe51d186 100644 --- a/www/manager6/qemu/USBEdit.js +++ b/www/manager6/qemu/USBEdit.js @@ -12,12 +12,17 @@ Ext.define('PVE.qemu.USBInputPanel', { setVMConfig: function(vmconfig) { var me = this; me.vmconfig = vmconfig; + let max_usb = PVE.Utils.get_max_usb_count(me.vmconfig.ostype, me.vmconfig.machine); + if (max_usb > PVE.Utils.hardware_counts.usb_old) { + me.down('field[name=usb3]').setDisabled(true); + } }, onGetValues: function(values) { var me = this; if (!me.confid) { - for (let i = 0; i < PVE.Utils.hardware_counts.usb; i++) { + let max_usb = PVE.Utils.get_max_usb_count(me.vmconfig.ostype, me.vmconfig.machine); + for (let i = 0; i < max_usb; i++) { let id = 'usb' + i.toString(); if (!me.vmconfig[id]) { me.confid = id;