mirror of https://github.com/jetkvm/kvm.git
				
				
				
			created feature branch
This commit is contained in:
		
							parent
							
								
									8ffe66a1bc
								
							
						
					
					
						commit
						7361289b68
					
				|  | @ -11,6 +11,14 @@ type WakeOnLanDevice struct { | ||||||
| 	MacAddress string `json:"macAddress"` | 	MacAddress string `json:"macAddress"` | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | type UsbConfig struct { | ||||||
|  | 	UsbVendorId     string `json:"usb_vendor_id"` | ||||||
|  | 	UsbProductId    string `json:"usb_product_id"` | ||||||
|  | 	UsbSerialNumber string `json:"usb_serial_number"` | ||||||
|  | 	UsbName         string `json:"usb_name"` | ||||||
|  | 	UsbManufacturer string `json:"usb_manufacturer"` | ||||||
|  | } | ||||||
|  | 
 | ||||||
| type Config struct { | type Config struct { | ||||||
| 	CloudURL          string            `json:"cloud_url"` | 	CloudURL          string            `json:"cloud_url"` | ||||||
| 	CloudToken        string            `json:"cloud_token"` | 	CloudToken        string            `json:"cloud_token"` | ||||||
|  | @ -22,6 +30,7 @@ type Config struct { | ||||||
| 	LocalAuthToken    string            `json:"local_auth_token"` | 	LocalAuthToken    string            `json:"local_auth_token"` | ||||||
| 	LocalAuthMode     string            `json:"localAuthMode"` //TODO: fix it with migration
 | 	LocalAuthMode     string            `json:"localAuthMode"` //TODO: fix it with migration
 | ||||||
| 	WakeOnLanDevices  []WakeOnLanDevice `json:"wake_on_lan_devices"` | 	WakeOnLanDevices  []WakeOnLanDevice `json:"wake_on_lan_devices"` | ||||||
|  | 	UsbConfig         UsbConfig         `json:"usb_config"` | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| const configPath = "/userdata/kvm_config.json" | const configPath = "/userdata/kvm_config.json" | ||||||
|  |  | ||||||
|  | @ -36,17 +36,17 @@ func switchToScreenIfDifferent(screenName string) { | ||||||
| func updateDisplay() { | func updateDisplay() { | ||||||
| 	updateLabelIfChanged("ui_Home_Content_Ip", networkState.IPv4) | 	updateLabelIfChanged("ui_Home_Content_Ip", networkState.IPv4) | ||||||
| 	if usbState == "configured" { | 	if usbState == "configured" { | ||||||
| 		updateLabelIfChanged("ui_Home_Footer_Usb_Status_Label", "Connected") | 		updateLabelIfChanged("ui_Home_Footer_Usb_Status_Label", "Connected*") | ||||||
| 		_, _ = CallCtrlAction("lv_obj_set_state", map[string]interface{}{"obj": "ui_Home_Footer_Usb_Status_Label", "state": "LV_STATE_DEFAULT"}) | 		_, _ = CallCtrlAction("lv_obj_set_state", map[string]interface{}{"obj": "ui_Home_Footer_Usb_Status_Label", "state": "LV_STATE_DEFAULT"}) | ||||||
| 	} else { | 	} else { | ||||||
| 		updateLabelIfChanged("ui_Home_Footer_Usb_Status_Label", "Disconnected") | 		updateLabelIfChanged("ui_Home_Footer_Usb_Status_Label", "Disconnected*") | ||||||
| 		_, _ = CallCtrlAction("lv_obj_set_state", map[string]interface{}{"obj": "ui_Home_Footer_Usb_Status_Label", "state": "LV_STATE_USER_2"}) | 		_, _ = CallCtrlAction("lv_obj_set_state", map[string]interface{}{"obj": "ui_Home_Footer_Usb_Status_Label", "state": "LV_STATE_USER_2"}) | ||||||
| 	} | 	} | ||||||
| 	if lastVideoState.Ready { | 	if lastVideoState.Ready { | ||||||
| 		updateLabelIfChanged("ui_Home_Footer_Hdmi_Status_Label", "Connected") | 		updateLabelIfChanged("ui_Home_Footer_Hdmi_Status_Label", "Connected*") | ||||||
| 		_, _ = CallCtrlAction("lv_obj_set_state", map[string]interface{}{"obj": "ui_Home_Footer_Hdmi_Status_Label", "state": "LV_STATE_DEFAULT"}) | 		_, _ = CallCtrlAction("lv_obj_set_state", map[string]interface{}{"obj": "ui_Home_Footer_Hdmi_Status_Label", "state": "LV_STATE_DEFAULT"}) | ||||||
| 	} else { | 	} else { | ||||||
| 		updateLabelIfChanged("ui_Home_Footer_Hdmi_Status_Label", "Disconnected") | 		updateLabelIfChanged("ui_Home_Footer_Hdmi_Status_Label", "Disconnected*") | ||||||
| 		_, _ = CallCtrlAction("lv_obj_set_state", map[string]interface{}{"obj": "ui_Home_Footer_Hdmi_Status_Label", "state": "LV_STATE_USER_2"}) | 		_, _ = CallCtrlAction("lv_obj_set_state", map[string]interface{}{"obj": "ui_Home_Footer_Hdmi_Status_Label", "state": "LV_STATE_USER_2"}) | ||||||
| 	} | 	} | ||||||
| 	updateLabelIfChanged("ui_Home_Header_Cloud_Status_Label", fmt.Sprintf("%d active", actionSessions)) | 	updateLabelIfChanged("ui_Home_Header_Cloud_Status_Label", fmt.Sprintf("%d active", actionSessions)) | ||||||
|  |  | ||||||
							
								
								
									
										21
									
								
								jsonrpc.go
								
								
								
								
							
							
						
						
									
										21
									
								
								jsonrpc.go
								
								
								
								
							|  | @ -478,6 +478,26 @@ func rpcSetUsbEmulationState(enabled bool) error { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func rpcSetUsbConfig(usbConfig UsbConfig) error { | ||||||
|  | 	log.Printf("[jsonrpc.go:rpcSetUsbConfig] called") | ||||||
|  | 
 | ||||||
|  | 	LoadConfig() | ||||||
|  | 	config.UsbConfig = usbConfig | ||||||
|  | 
 | ||||||
|  | 	err2 := UpdateGadgetConfig() | ||||||
|  | 	if err2 != nil { | ||||||
|  | 		return fmt.Errorf("failed to write gadget config: %w", err2) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err := SaveConfig() | ||||||
|  | 	if err != nil { | ||||||
|  | 		return fmt.Errorf("failed to save usb config: %w", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	log.Printf("[jsonrpc.go:rpcSetUsbConfig] usb config set to %s", usbConfig) | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func rpcGetWakeOnLanDevices() ([]WakeOnLanDevice, error) { | func rpcGetWakeOnLanDevices() ([]WakeOnLanDevice, error) { | ||||||
| 	LoadConfig() | 	LoadConfig() | ||||||
| 	if config.WakeOnLanDevices == nil { | 	if config.WakeOnLanDevices == nil { | ||||||
|  | @ -542,6 +562,7 @@ var rpcHandlers = map[string]RPCHandler{ | ||||||
| 	"isUpdatePending":        {Func: rpcIsUpdatePending}, | 	"isUpdatePending":        {Func: rpcIsUpdatePending}, | ||||||
| 	"getUsbEmulationState":   {Func: rpcGetUsbEmulationState}, | 	"getUsbEmulationState":   {Func: rpcGetUsbEmulationState}, | ||||||
| 	"setUsbEmulationState":   {Func: rpcSetUsbEmulationState, Params: []string{"enabled"}}, | 	"setUsbEmulationState":   {Func: rpcSetUsbEmulationState, Params: []string{"enabled"}}, | ||||||
|  | 	"setUsbConfig":           {Func: rpcSetUsbConfig, Params: []string{"usbConfig"}}, | ||||||
| 	"checkMountUrl":          {Func: rpcCheckMountUrl, Params: []string{"url"}}, | 	"checkMountUrl":          {Func: rpcCheckMountUrl, Params: []string{"url"}}, | ||||||
| 	"getVirtualMediaState":   {Func: rpcGetVirtualMediaState}, | 	"getVirtualMediaState":   {Func: rpcGetVirtualMediaState}, | ||||||
| 	"getStorageSpace":        {Func: rpcGetStorageSpace}, | 	"getStorageSpace":        {Func: rpcGetStorageSpace}, | ||||||
|  |  | ||||||
|  | @ -10,6 +10,7 @@ import { Button, LinkButton } from "@components/Button"; | ||||||
| import { TextAreaWithLabel } from "@components/TextArea"; | import { TextAreaWithLabel } from "@components/TextArea"; | ||||||
| import { SectionHeader } from "@components/SectionHeader"; | import { SectionHeader } from "@components/SectionHeader"; | ||||||
| import { GridCard } from "@components/Card"; | import { GridCard } from "@components/Card"; | ||||||
|  | import { InputFieldWithLabel } from "@components/InputField"; | ||||||
| import { CheckCircleIcon } from "@heroicons/react/20/solid"; | import { CheckCircleIcon } from "@heroicons/react/20/solid"; | ||||||
| import { cx } from "@/cva.config"; | import { cx } from "@/cva.config"; | ||||||
| import React, { useCallback, useEffect, useRef, useState } from "react"; | import React, { useCallback, useEffect, useRef, useState } from "react"; | ||||||
|  | @ -31,7 +32,7 @@ export function SettingsItem({ | ||||||
|                                description, |                                description, | ||||||
|                                children, |                                children, | ||||||
|                                className, |                                className, | ||||||
| }: { |                              }: { | ||||||
|   title: string; |   title: string; | ||||||
|   description: string | React.ReactNode; |   description: string | React.ReactNode; | ||||||
|   children?: React.ReactNode; |   children?: React.ReactNode; | ||||||
|  | @ -102,6 +103,15 @@ export default function SettingsSidebar() { | ||||||
|   } | null>(null); |   } | null>(null); | ||||||
| 
 | 
 | ||||||
|   const [usbEmulationEnabled, setUsbEmulationEnabled] = useState(false); |   const [usbEmulationEnabled, setUsbEmulationEnabled] = useState(false); | ||||||
|  | 
 | ||||||
|  |   const [usbConfig, setUsbConfig] = useState({ | ||||||
|  |     usb_product_id: '', | ||||||
|  |     usb_vendor_id: '', | ||||||
|  |     usb_serial_number: '', | ||||||
|  |     usb_manufacturer: '', | ||||||
|  |     usb_name: '', | ||||||
|  |   }) | ||||||
|  | 
 | ||||||
|   const getUsbEmulationState = useCallback(() => { |   const getUsbEmulationState = useCallback(() => { | ||||||
|     send("getUsbEmulationState", {}, resp => { |     send("getUsbEmulationState", {}, resp => { | ||||||
|       if ("error" in resp) return; |       if ("error" in resp) return; | ||||||
|  | @ -206,6 +216,17 @@ export default function SettingsSidebar() { | ||||||
|     }); |     }); | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|  |   const handleUsbConfigChange = useCallback((usbConfig: object) => { | ||||||
|  |     send("setUsbConfig", { usbConfig }, resp => { | ||||||
|  |       if ("error" in resp) { | ||||||
|  |         notifications.error( | ||||||
|  |             `Failed to update USB Config: ${resp.error.data || "Unknown error"}`, | ||||||
|  |         ); | ||||||
|  |         return; | ||||||
|  |       } | ||||||
|  |     }); | ||||||
|  |   }, [send, usbConfig]); | ||||||
|  | 
 | ||||||
|   const handleSSHKeyChange = (newKey: string) => { |   const handleSSHKeyChange = (newKey: string) => { | ||||||
|     setSSHKey(newKey); |     setSSHKey(newKey); | ||||||
|   }; |   }; | ||||||
|  | @ -240,6 +261,26 @@ export default function SettingsSidebar() { | ||||||
|     }); |     }); | ||||||
|   }, [send, sshKey]); |   }, [send, sshKey]); | ||||||
| 
 | 
 | ||||||
|  |   const handleUsbProductIdChange = (productId: string) => { | ||||||
|  |     setUsbConfig({... usbConfig, usb_product_id: productId}) | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   const handleUsbVendorIdChange = (vendorId: string) => { | ||||||
|  |     setUsbConfig({... usbConfig, usb_vendor_id: vendorId}) | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   const handleUsbSerialChange = (serialNumber: string) => { | ||||||
|  |     setUsbConfig({... usbConfig, usb_serial_number: serialNumber}) | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   const handleUsbName = (name: string) => { | ||||||
|  |     setUsbConfig({... usbConfig, usb_name: name}) | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   const handleUsbManufacturer = (manufacturer: string) => { | ||||||
|  |     setUsbConfig({... usbConfig, usb_manufacturer: manufacturer}) | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|   const { setIsUpdateDialogOpen, setModalView, otaState } = useUpdateStore(); |   const { setIsUpdateDialogOpen, setModalView, otaState } = useUpdateStore(); | ||||||
|   const handleCheckForUpdates = () => { |   const handleCheckForUpdates = () => { | ||||||
|     if (otaState.updating) { |     if (otaState.updating) { | ||||||
|  | @ -836,6 +877,55 @@ export default function SettingsSidebar() { | ||||||
|                     </div> |                     </div> | ||||||
|                   </div> |                   </div> | ||||||
|               )} |               )} | ||||||
|  |               {settings.developerMode && ( | ||||||
|  |                   <div className="space-y-4"> | ||||||
|  |                     <InputFieldWithLabel | ||||||
|  |                         label="USB Vendor Id" | ||||||
|  |                         value={usbConfig.usb_vendor_id || ""} | ||||||
|  |                         onChange={e => handleUsbVendorIdChange(e.target.value)} | ||||||
|  |                         placeholder="Enter USB Vendor Id" | ||||||
|  |                     /> | ||||||
|  |                     <InputFieldWithLabel | ||||||
|  |                         label="USB Product Id" | ||||||
|  |                         value={usbConfig.usb_product_id || ""} | ||||||
|  |                         onChange={e => handleUsbProductIdChange(e.target.value)} | ||||||
|  |                         placeholder="Enter USB Product Id" | ||||||
|  |                     /> | ||||||
|  |                     <InputFieldWithLabel | ||||||
|  |                         label="USB Serial Number" | ||||||
|  |                         value={usbConfig.usb_serial_number || ""} | ||||||
|  |                         onChange={e => handleUsbSerialChange(e.target.value)} | ||||||
|  |                         placeholder="Enter USB Serial Number" | ||||||
|  |                     /> | ||||||
|  |                     <InputFieldWithLabel | ||||||
|  |                         label="USB Name" | ||||||
|  |                         value={usbConfig.usb_name || ""} | ||||||
|  |                         onChange={e => handleUsbName(e.target.value)} | ||||||
|  |                         placeholder="Enter USB Name" | ||||||
|  |                     /> | ||||||
|  |                     <InputFieldWithLabel | ||||||
|  |                         label="USB Manufacturer" | ||||||
|  |                         value={usbConfig.usb_manufacturer || ""} | ||||||
|  |                         onChange={e => handleUsbManufacturer(e.target.value)} | ||||||
|  |                         placeholder="Enter USB Manufacturer" | ||||||
|  |                     /> | ||||||
|  |                     <div className="flex items-center gap-x-2"> | ||||||
|  |                       <Button | ||||||
|  |                           size="SM" | ||||||
|  |                           theme="primary" | ||||||
|  |                           text="Update USB Config" | ||||||
|  |                           onClick={() => { | ||||||
|  |                             if (Object.values(usbConfig).every(function(i) { return Boolean(i); })) { | ||||||
|  |                               handleUsbConfigChange(usbConfig); | ||||||
|  |                               notifications.success("Successfully updated USB Config") | ||||||
|  |                             } else { | ||||||
|  |                               notifications.error("Failed to update USB config"); | ||||||
|  |                             } | ||||||
|  |                           }} | ||||||
|  |                       /> | ||||||
|  |                     </div> | ||||||
|  |                   </div> | ||||||
|  |               )} | ||||||
|               <SettingsItem |               <SettingsItem | ||||||
|                   title="Troubleshooting Mode" |                   title="Troubleshooting Mode" | ||||||
|                   description="Diagnostic tools and additional controls for troubleshooting and development purposes" |                   description="Diagnostic tools and additional controls for troubleshooting and development purposes" | ||||||
|  |  | ||||||
							
								
								
									
										111
									
								
								usb.go
								
								
								
								
							
							
						
						
									
										111
									
								
								usb.go
								
								
								
								
							|  | @ -3,6 +3,7 @@ package kvm | ||||||
| import ( | import ( | ||||||
| 	"errors" | 	"errors" | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  | 	gadget "github.com/openstadia/go-usb-gadget" | ||||||
| 	"log" | 	"log" | ||||||
| 	"os" | 	"os" | ||||||
| 	"os/exec" | 	"os/exec" | ||||||
|  | @ -11,8 +12,6 @@ import ( | ||||||
| 	"strings" | 	"strings" | ||||||
| 	"sync" | 	"sync" | ||||||
| 	"time" | 	"time" | ||||||
| 
 |  | ||||||
| 	gadget "github.com/openstadia/go-usb-gadget" |  | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| const configFSPath = "/sys/kernel/config" | const configFSPath = "/sys/kernel/config" | ||||||
|  | @ -20,19 +19,6 @@ const gadgetPath = "/sys/kernel/config/usb_gadget" | ||||||
| const kvmGadgetPath = "/sys/kernel/config/usb_gadget/jetkvm" | const kvmGadgetPath = "/sys/kernel/config/usb_gadget/jetkvm" | ||||||
| const configC1Path = "/sys/kernel/config/usb_gadget/jetkvm/configs/c.1" | const configC1Path = "/sys/kernel/config/usb_gadget/jetkvm/configs/c.1" | ||||||
| 
 | 
 | ||||||
| func mountConfigFS() error { |  | ||||||
| 	_, err := os.Stat(gadgetPath) |  | ||||||
| 	if os.IsNotExist(err) { |  | ||||||
| 		err = exec.Command("mount", "-t", "configfs", "none", configFSPath).Run() |  | ||||||
| 		if err != nil { |  | ||||||
| 			return fmt.Errorf("failed to mount configfs: %w", err) |  | ||||||
| 		} |  | ||||||
| 	} else { |  | ||||||
| 		return fmt.Errorf("unable to access usb gadget path: %w", err) |  | ||||||
| 	} |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func init() { | func init() { | ||||||
| 	_ = os.MkdirAll(imagesFolder, 0755) | 	_ = os.MkdirAll(imagesFolder, 0755) | ||||||
| 	udcs := gadget.GetUdcs() | 	udcs := gadget.GetUdcs() | ||||||
|  | @ -58,6 +44,60 @@ func init() { | ||||||
| 	//TODO: read hid reports(capslock, numlock, etc) from keyboardHidFile
 | 	//TODO: read hid reports(capslock, numlock, etc) from keyboardHidFile
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func UpdateGadgetConfig() error { | ||||||
|  | 	LoadConfig() | ||||||
|  | 	gadgetAttrs := [][]string{ | ||||||
|  | 		{"idVendor", config.UsbConfig.UsbVendorId}, | ||||||
|  | 		{"idProduct", config.UsbConfig.UsbProductId}, | ||||||
|  | 	} | ||||||
|  | 	err := writeGadgetAttrs(kvmGadgetPath, gadgetAttrs) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	log.Printf("Successfully updated usb gadget attributes: %v", gadgetAttrs) | ||||||
|  | 
 | ||||||
|  | 	strAttrs := [][]string{ | ||||||
|  | 		{"serialnumber", config.UsbConfig.UsbSerialNumber}, | ||||||
|  | 		{"manufacturer", config.UsbConfig.UsbManufacturer}, | ||||||
|  | 		{"product", config.UsbConfig.UsbName}, | ||||||
|  | 	} | ||||||
|  | 	gadgetStringsPath := filepath.Join(kvmGadgetPath, "strings", "0x409") | ||||||
|  | 	err = os.MkdirAll(gadgetStringsPath, 0755) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	err = writeGadgetAttrs(gadgetStringsPath, strAttrs) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	log.Printf("Successfully updated string attributes: %s", strAttrs) | ||||||
|  | 
 | ||||||
|  | 	err = rebindUsb() | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func mountConfigFS() error { | ||||||
|  | 	logger.Infof("Checking for gadgetPath: %s ...", gadgetPath) | ||||||
|  | 	_, err := os.Stat(gadgetPath) | ||||||
|  | 	if os.IsNotExist(err) { | ||||||
|  | 		logger.Infof("running mount command...") | ||||||
|  | 		err = exec.Command("mount", "-t", "configfs", "none", configFSPath).Run() | ||||||
|  | 		if err != nil { | ||||||
|  | 			return fmt.Errorf("failed to mount configfs: %w", err) | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		return fmt.Errorf("unable to access usb gadget path: %w", err) | ||||||
|  | 	} | ||||||
|  | 	logger.Infof("Successfully mounted usb gadget at %s", gadgetPath) | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func writeGadgetAttrs(basePath string, attrs [][]string) error { | func writeGadgetAttrs(basePath string, attrs [][]string) error { | ||||||
| 	for _, item := range attrs { | 	for _, item := range attrs { | ||||||
| 		filePath := filepath.Join(basePath, item[0]) | 		filePath := filepath.Join(basePath, item[0]) | ||||||
|  | @ -79,30 +119,35 @@ func writeGadgetConfig() error { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	err = writeGadgetAttrs(kvmGadgetPath, [][]string{ | 	LoadConfig() | ||||||
|  | 	gadgetAttrs := [][]string{ | ||||||
| 		{"bcdUSB", "0x0200"}, //USB 2.0
 | 		{"bcdUSB", "0x0200"}, //USB 2.0
 | ||||||
| 		{"idVendor", "0x1d6b"}, //The Linux Foundation
 | 		{"idVendor", config.UsbConfig.UsbVendorId}, | ||||||
| 		{"idProduct", "0104"},  //Multifunction Composite Gadget¬
 | 		{"idProduct", config.UsbConfig.UsbProductId}, | ||||||
| 		{"bcdDevice", "0100"}, | 		{"bcdDevice", "0100"}, | ||||||
| 	}) | 	} | ||||||
|  | 	err = writeGadgetAttrs(kvmGadgetPath, gadgetAttrs) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	logger.Infof("Successfully wrote gadget attributes: %s", gadgetAttrs) | ||||||
| 	gadgetStringsPath := filepath.Join(kvmGadgetPath, "strings", "0x409") | 	gadgetStringsPath := filepath.Join(kvmGadgetPath, "strings", "0x409") | ||||||
| 	err = os.MkdirAll(gadgetStringsPath, 0755) | 	err = os.MkdirAll(gadgetStringsPath, 0755) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	err = writeGadgetAttrs(gadgetStringsPath, [][]string{ | 	strAttrs := [][]string{ | ||||||
| 		{"serialnumber", GetDeviceID()}, | 		{"serialnumber", config.UsbConfig.UsbSerialNumber}, | ||||||
| 		{"manufacturer", "JetKVM"}, | 		{"manufacturer", config.UsbConfig.UsbManufacturer}, | ||||||
| 		{"product", "JetKVM USB Emulation Device"}, | 		{"product", config.UsbConfig.UsbName}, | ||||||
| 	}) | 	} | ||||||
|  | 	err = writeGadgetAttrs(gadgetStringsPath, strAttrs) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  | 	logger.Infof("Successfully wrote string attributes: %s", strAttrs) | ||||||
| 
 | 
 | ||||||
| 	configC1StringsPath := path.Join(configC1Path, "strings", "0x409") | 	configC1StringsPath := path.Join(configC1Path, "strings", "0x409") | ||||||
| 	err = os.MkdirAll(configC1StringsPath, 0755) | 	err = os.MkdirAll(configC1StringsPath, 0755) | ||||||
|  | @ -216,11 +261,27 @@ func writeGadgetConfig() error { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func rebindUsb() error { | func rebindUsb() error { | ||||||
|  | 	unbindErr := unbindUsb() | ||||||
|  | 	if unbindErr != nil { | ||||||
|  | 		return unbindErr | ||||||
|  | 	} | ||||||
|  | 	bindErr := bindUsb() | ||||||
|  | 	if bindErr != nil { | ||||||
|  | 		return bindErr | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func unbindUsb() error { | ||||||
| 	err := os.WriteFile("/sys/bus/platform/drivers/dwc3/unbind", []byte(udc), 0644) | 	err := os.WriteFile("/sys/bus/platform/drivers/dwc3/unbind", []byte(udc), 0644) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 	err = os.WriteFile("/sys/bus/platform/drivers/dwc3/bind", []byte(udc), 0644) | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func bindUsb() error { | ||||||
|  | 	err := os.WriteFile("/sys/bus/platform/drivers/dwc3/bind", []byte(udc), 0644) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue