From 9b75613346c1adcbf4da0733a39d735317458974 Mon Sep 17 00:00:00 2001
From: Daniel Lorch <dlorch@gmail.com>
Date: Wed, 14 May 2025 01:27:45 +0200
Subject: [PATCH] add USB gadget ethernet configurations

---
 config.go                       |  4 +++
 internal/usbgadget/config.go    | 15 +++++++++++
 internal/usbgadget/ethernet.go  | 45 +++++++++++++++++++++++++++++++++
 internal/usbgadget/usbgadget.go |  8 ++++++
 4 files changed, 72 insertions(+)
 create mode 100644 internal/usbgadget/ethernet.go

diff --git a/config.go b/config.go
index 23d4c84..9883356 100644
--- a/config.go
+++ b/config.go
@@ -123,6 +123,10 @@ var defaultConfig = &Config{
 		RelativeMouse: true,
 		Keyboard:      true,
 		MassStorage:   true,
+		EthernetEcm:   false,
+		EthernetEem:   false,
+		EthernetNcm:   false,
+		EthernetRndis: false,
 	},
 	NetworkConfig:   &network.NetworkConfig{},
 	DefaultLogLevel: "INFO",
diff --git a/internal/usbgadget/config.go b/internal/usbgadget/config.go
index b73d392..cd9e653 100644
--- a/internal/usbgadget/config.go
+++ b/internal/usbgadget/config.go
@@ -63,6 +63,11 @@ var defaultGadgetConfig = map[string]gadgetConfigItem{
 	// mass storage
 	"mass_storage_base": massStorageBaseConfig,
 	"mass_storage_lun0": massStorageLun0Config,
+	// ethernet
+	"ethernet_ecm":   ethernetEcmConfig,
+	"ethernet_eem":   ethernetEemConfig,
+	"ethernet_ncm":   ethernetNcmConfig,
+	"ethernet_rndis": ethernetRndisConfig,
 }
 
 func (u *UsbGadget) isGadgetConfigItemEnabled(itemKey string) bool {
@@ -77,6 +82,14 @@ func (u *UsbGadget) isGadgetConfigItemEnabled(itemKey string) bool {
 		return u.enabledDevices.MassStorage
 	case "mass_storage_lun0":
 		return u.enabledDevices.MassStorage
+	case "ethernet_ecm":
+		return u.enabledDevices.EthernetEcm
+	case "ethernet_eem":
+		return u.enabledDevices.EthernetEem
+	case "ethernet_ncm":
+		return u.enabledDevices.EthernetNcm
+	case "ethernet_rndis":
+		return u.enabledDevices.EthernetRndis
 	default:
 		return true
 	}
@@ -313,7 +326,9 @@ func (u *UsbGadget) writeGadgetItemConfig(item gadgetConfigItem) error {
 	}
 
 	// create symlink if configPath is set
+	fmt.Println("******", item.configPath, "*****")
 	if item.configPath != nil && item.configAttrs == nil {
+		fmt.Println("YES")
 		configPath := joinPath(u.configC1Path, item.configPath)
 		u.log.Trace().Str("source", configPath).Str("target", gadgetItemPath).Msg("creating symlink")
 		if err := ensureSymlink(configPath, gadgetItemPath); err != nil {
diff --git a/internal/usbgadget/ethernet.go b/internal/usbgadget/ethernet.go
new file mode 100644
index 0000000..f9a1f4c
--- /dev/null
+++ b/internal/usbgadget/ethernet.go
@@ -0,0 +1,45 @@
+package usbgadget
+
+// Ethernet Control Model (ECM)
+var ethernetEcmConfig = gadgetConfigItem{
+	order:      4000,
+	path:       []string{"functions", "ecm.usb0"},
+	configPath: []string{"ecm.usb0"},
+	attrs: gadgetAttributes{
+		"host_addr": "", // MAC address of target host (randomly select)
+		"dev_addr":  "", // MAC address of JetKVM (randomly select)
+	},
+}
+
+// Ethernet Emulation Model (EEM)
+var ethernetEemConfig = gadgetConfigItem{
+	order:      4001,
+	path:       []string{"functions", "eem.usb0"},
+	configPath: []string{"eem.usb0"},
+	attrs: gadgetAttributes{
+		"host_addr": "", // MAC address of target host (randomly select)
+		"dev_addr":  "", // MAC address of JetKVM (randomly select)
+	},
+}
+
+// Network Control Model (NCM)
+var ethernetNcmConfig = gadgetConfigItem{
+	order:      4001,
+	path:       []string{"functions", "ncm.usb0"},
+	configPath: []string{"ncm.usb0"},
+	attrs: gadgetAttributes{
+		"host_addr": "", // MAC address of target host (randomly select)
+		"dev_addr":  "", // MAC address of JetKVM (randomly select)
+	},
+}
+
+// Remote Network Driver Interface Specification (RNDIS)
+var ethernetRndisConfig = gadgetConfigItem{
+	order:      4001,
+	path:       []string{"functions", "rndis.usb0"},
+	configPath: []string{"rndis.usb0"},
+	attrs: gadgetAttributes{
+		"host_addr": "", // MAC address of target host (randomly select)
+		"dev_addr":  "", // MAC address of JetKVM (randomly select)
+	},
+}
diff --git a/internal/usbgadget/usbgadget.go b/internal/usbgadget/usbgadget.go
index 1dff2f3..ffd923a 100644
--- a/internal/usbgadget/usbgadget.go
+++ b/internal/usbgadget/usbgadget.go
@@ -17,6 +17,10 @@ type Devices struct {
 	RelativeMouse bool `json:"relative_mouse"`
 	Keyboard      bool `json:"keyboard"`
 	MassStorage   bool `json:"mass_storage"`
+	EthernetEcm   bool `json:"ethernet_ecm"`
+	EthernetEem   bool `json:"ethernet_eem"`
+	EthernetNcm   bool `json:"ethernet_ncm"`
+	EthernetRndis bool `json:"ethernet_rndis"`
 }
 
 // Config is a struct that represents the customizations for a USB gadget.
@@ -36,6 +40,10 @@ var defaultUsbGadgetDevices = Devices{
 	RelativeMouse: true,
 	Keyboard:      true,
 	MassStorage:   true,
+	EthernetEcm:   false,
+	EthernetEem:   false,
+	EthernetNcm:   false,
+	EthernetRndis: false,
 }
 
 // UsbGadget is a struct that represents a USB gadget.