feat: 增加 OTG HID 远程唤醒和 OTG MSD 设备名称配置

- 在补丁内核上启用 HID 写入唤醒及 USB 远程唤醒描述符
  - 支持全局配置 Flash 和 CD-ROM INQUIRY 字符串
  - 兼容普通内核的通用 INQUIRY 属性
  - 调整 OTG 功能布局并更新大容量 DVD 镜像提示
This commit is contained in:
mofeng-git
2026-07-29 13:56:52 +08:00
parent e0bddc2faa
commit 887f29096f
12 changed files with 347 additions and 67 deletions

View File

@@ -409,7 +409,7 @@ export default {
download: 'Download',
downloadComplete: 'Download complete',
largeFileWarning: '>2.2GB',
largeFileTooltip: 'File is larger than 2.2GB, please use Flash mode to mount',
largeFileTooltip: 'If DVD image support is not enabled in the kernel, only the first 2.2 GB is accessible after mounting.',
operationInProgress: 'Operation in progress, please wait',
selectDriveSize: 'Select virtual drive size',
driveSpaceUnknown: 'Unable to read available space for the MSD directory filesystem',
@@ -644,6 +644,8 @@ export default {
username: 'Username',
password: 'Password',
msdDir: 'MSD directory',
msdFlashInquiryString: 'Flash device name',
msdCdromInquiryString: 'CD-ROM device name',
atxPowerButton: 'Power Button',
atxResetButton: 'Reset Button',
atxPowerManagement: 'Power Management',

View File

@@ -408,7 +408,7 @@ export default {
download: '下载',
downloadComplete: '下载完成',
largeFileWarning: '>2.2GB',
largeFileTooltip: '文件大于 2.2GB,请使用 Flash 模式挂载',
largeFileTooltip: '若内核未启用 DVD 镜像支持,挂载后仅前 2.2 GB 可访问。',
operationInProgress: '操作进行中,请稍候',
selectDriveSize: '选择虚拟驱动器大小',
driveSpaceUnknown: '无法读取 MSD 目录所在储存空间的剩余可用空间',
@@ -643,6 +643,8 @@ export default {
username: '用户名',
password: '密码',
msdDir: 'MSD 目录',
msdFlashInquiryString: 'Flash 设备名称',
msdCdromInquiryString: 'CD-ROM 设备名称',
atxPowerButton: '电源按钮',
atxResetButton: '重启按钮',
atxPowerManagement: '电源管理',

View File

@@ -86,6 +86,8 @@ export interface OtgNetworkConfig {
export interface MsdConfig {
enabled: boolean;
msd_dir: string;
flash_inquiry_string: string;
cdrom_inquiry_string: string;
}
export enum AtxDriverType {
@@ -546,6 +548,8 @@ export interface HidConfigUpdate {
export interface MsdConfigUpdate {
enabled?: boolean;
msd_dir?: string;
flash_inquiry_string?: string;
cdrom_inquiry_string?: string;
}
export interface NetworkInterfaceInfo {

View File

@@ -675,6 +675,8 @@ const config = ref({
hid_ch9329_hybrid_mouse: false,
msd_enabled: false,
msd_dir: '',
msd_flash_inquiry_string: 'One-KVM Virtual Flash',
msd_cdrom_inquiry_string: 'One-KVM Virtual CD-ROM',
otg_network_enabled: false,
otg_network_driver: 'ncm' as 'ncm' | 'ecm' | 'rndis',
otg_network_interface: '',
@@ -1013,6 +1015,18 @@ const isHidFunctionSelectionValid = computed(() => {
return !!(f.keyboard || f.mouse_relative || f.mouse_absolute || f.consumer)
})
function isValidInquiryString(value: string): boolean {
return /^[\x20-\x7e]{1,28}$/.test(value.trim())
}
const areMsdInquiryStringsValid = computed(() =>
!config.value.msd_enabled
|| (
isValidInquiryString(config.value.msd_flash_inquiry_string)
&& isValidInquiryString(config.value.msd_cdrom_inquiry_string)
)
)
const otgVendorIdHex = ref('1d6b')
const otgProductIdHex = ref('0104')
const otgManufacturer = ref('One-KVM')
@@ -1144,6 +1158,7 @@ const isCh9329DescriptorDirty = computed(() => {
const isHidSettingsValid = computed(() =>
isHidFunctionSelectionValid.value
&& isCh9329DescriptorValid.value
&& areMsdInquiryStringsValid.value
)
watch(bindMode, (mode) => {
@@ -1471,6 +1486,8 @@ async function saveConfig() {
msd: {
enabled: otgEnabled && config.value.msd_enabled,
msd_dir: config.value.msd_dir || undefined,
flash_inquiry_string: config.value.msd_flash_inquiry_string,
cdrom_inquiry_string: config.value.msd_cdrom_inquiry_string,
},
network: {
enabled: otgEnabled && config.value.otg_network_enabled,
@@ -1541,6 +1558,8 @@ async function loadConfig() {
hid_ch9329_hybrid_mouse: hid.ch9329_hybrid_mouse ?? false,
msd_enabled: msd.enabled || false,
msd_dir: msd.msd_dir || '',
msd_flash_inquiry_string: msd.flash_inquiry_string || 'One-KVM Virtual Flash',
msd_cdrom_inquiry_string: msd.cdrom_inquiry_string || 'One-KVM Virtual CD-ROM',
otg_network_enabled: otgNetwork.enabled,
otg_network_driver: otgNetwork.driver_mode,
uac_enabled: uac.enabled,
@@ -3299,41 +3318,48 @@ watch(isWindows, () => {
<h4 class="text-sm font-medium">{{ t('settings.otgHidProfile') }}</h4>
</div>
<div class="space-y-3">
<div class="space-y-3 rounded-md border border-border/60 p-3">
<div class="flex items-center justify-between gap-4">
<div>
<Label>{{ t('settings.otgFunctionMouseRelative') }}</Label>
<div class="grid gap-3 md:grid-cols-2">
<div class="space-y-3 rounded-md border border-border/60 p-3">
<div class="flex items-center justify-between gap-4">
<div>
<Label>{{ t('settings.otgFunctionKeyboard') }}</Label>
</div>
<Switch v-model="config.hid_otg_functions.keyboard" />
</div>
<Separator />
<div class="flex items-center justify-between gap-4">
<div>
<Label>{{ t('settings.otgFunctionConsumer') }}</Label>
</div>
<Switch v-model="config.hid_otg_functions.consumer" />
</div>
<Separator />
<div class="flex items-center justify-between gap-4">
<div>
<Label>{{ t('settings.otgKeyboardLeds') }}</Label>
</div>
<Switch v-model="config.hid_otg_keyboard_leds" :disabled="isKeyboardLedToggleDisabled" />
</div>
<Switch v-model="config.hid_otg_functions.mouse_relative" />
</div>
<Separator />
<div class="flex items-center justify-between gap-4">
<div>
<Label>{{ t('settings.otgFunctionMouseAbsolute') }}</Label>
<div class="space-y-3 rounded-md border border-border/60 p-3">
<div class="flex items-center justify-between gap-4">
<div>
<Label>{{ t('settings.otgFunctionMouseRelative') }}</Label>
</div>
<Switch v-model="config.hid_otg_functions.mouse_relative" />
</div>
<Switch v-model="config.hid_otg_functions.mouse_absolute" />
</div>
</div>
<div class="space-y-3 rounded-md border border-border/60 p-3">
<div class="flex items-center justify-between gap-4">
<div>
<Label>{{ t('settings.otgFunctionKeyboard') }}</Label>
<Separator />
<div class="flex items-center justify-between gap-4">
<div>
<Label>{{ t('settings.otgFunctionMouseAbsolute') }}</Label>
</div>
<Switch v-model="config.hid_otg_functions.mouse_absolute" />
</div>
<Switch v-model="config.hid_otg_functions.keyboard" />
</div>
<Separator />
<div class="flex items-center justify-between gap-4">
<div>
<Label>{{ t('settings.otgFunctionConsumer') }}</Label>
<Separator />
<div class="flex items-center justify-between gap-4">
<Label>{{ t('settings.uacMic') }}</Label>
<Switch v-model="config.uac_enabled" />
</div>
<Switch v-model="config.hid_otg_functions.consumer" />
</div>
<Separator />
<div class="flex items-center justify-between gap-4">
<div>
<Label>{{ t('settings.otgKeyboardLeds') }}</Label>
</div>
<Switch v-model="config.hid_otg_keyboard_leds" :disabled="isKeyboardLedToggleDisabled" />
</div>
</div>
<div class="space-y-3 rounded-md border border-border/60 p-3">
@@ -3349,6 +3375,24 @@ watch(isWindows, () => {
<Label for="msd-dir">{{ t('settings.msdDir') }}</Label>
<Input id="msd-dir" v-model="config.msd_dir" placeholder="/etc/one-kvm/msd" />
</div>
<div class="space-y-2">
<Label for="msd-flash-inquiry-string">{{ t('settings.msdFlashInquiryString') }}</Label>
<Input
id="msd-flash-inquiry-string"
v-model="config.msd_flash_inquiry_string"
placeholder="One-KVM Virtual Flash"
maxlength="28"
/>
</div>
<div class="space-y-2">
<Label for="msd-cdrom-inquiry-string">{{ t('settings.msdCdromInquiryString') }}</Label>
<Input
id="msd-cdrom-inquiry-string"
v-model="config.msd_cdrom_inquiry_string"
placeholder="One-KVM Virtual CD-ROM"
maxlength="28"
/>
</div>
</template>
</div>
<div class="space-y-3 rounded-md border border-border/60 p-3">
@@ -3412,12 +3456,6 @@ watch(isWindows, () => {
{{ t('settings.otgRuntimeDegraded') }}: {{ otgNetworkStatus.error || t('common.error') }}
</p>
</div>
<div class="space-y-3 rounded-md border border-border/60 p-3">
<div class="flex items-center justify-between gap-4">
<Label>{{ t('settings.uacMic') }}</Label>
<Switch v-model="config.uac_enabled" />
</div>
</div>
</div>
<p class="text-xs text-warning">
{{ t('settings.otgProfileWarning') }}