mirror of https://github.com/jetkvm/kvm.git
Compare commits
3 Commits
15baf9323b
...
557aa5891a
| Author | SHA1 | Date |
|---|---|---|
|
|
557aa5891a | |
|
|
49d62f8eb0 | |
|
|
9e4392127e |
34
Makefile
34
Makefile
|
|
@ -17,6 +17,7 @@ dev_env: build_audio_deps
|
||||||
JETKVM_HOME ?= $(HOME)/.jetkvm
|
JETKVM_HOME ?= $(HOME)/.jetkvm
|
||||||
TOOLCHAIN_DIR ?= $(JETKVM_HOME)/rv1106-system
|
TOOLCHAIN_DIR ?= $(JETKVM_HOME)/rv1106-system
|
||||||
AUDIO_LIBS_DIR ?= $(JETKVM_HOME)/audio-libs
|
AUDIO_LIBS_DIR ?= $(JETKVM_HOME)/audio-libs
|
||||||
|
|
||||||
BRANCH ?= $(shell git rev-parse --abbrev-ref HEAD)
|
BRANCH ?= $(shell git rev-parse --abbrev-ref HEAD)
|
||||||
BUILDDATE ?= $(shell date -u +%FT%T%z)
|
BUILDDATE ?= $(shell date -u +%FT%T%z)
|
||||||
BUILDTS ?= $(shell date -u +%s)
|
BUILDTS ?= $(shell date -u +%s)
|
||||||
|
|
@ -28,9 +29,21 @@ VERSION ?= 0.4.6
|
||||||
ALSA_VERSION ?= 1.2.14
|
ALSA_VERSION ?= 1.2.14
|
||||||
OPUS_VERSION ?= 1.5.2
|
OPUS_VERSION ?= 1.5.2
|
||||||
|
|
||||||
|
# Set PKG_CONFIG_PATH globally for all targets that use CGO with audio libraries
|
||||||
|
export PKG_CONFIG_PATH := $(AUDIO_LIBS_DIR)/alsa-lib-$(ALSA_VERSION)/utils:$(AUDIO_LIBS_DIR)/opus-$(OPUS_VERSION)
|
||||||
|
|
||||||
# Optimization flags for ARM Cortex-A7 with NEON
|
# Optimization flags for ARM Cortex-A7 with NEON
|
||||||
OPTIM_CFLAGS := -O3 -mfpu=neon -mtune=cortex-a7 -mfloat-abi=hard -ftree-vectorize -ffast-math -funroll-loops
|
OPTIM_CFLAGS := -O3 -mfpu=neon -mtune=cortex-a7 -mfloat-abi=hard -ftree-vectorize -ffast-math -funroll-loops
|
||||||
|
|
||||||
|
# Cross-compilation environment for ARM - exported globally
|
||||||
|
export GOOS := linux
|
||||||
|
export GOARCH := arm
|
||||||
|
export GOARM := 7
|
||||||
|
export CC := $(TOOLCHAIN_DIR)/tools/linux/toolchain/arm-rockchip830-linux-uclibcgnueabihf/bin/arm-rockchip830-linux-uclibcgnueabihf-gcc
|
||||||
|
export CGO_ENABLED := 1
|
||||||
|
export CGO_CFLAGS := $(OPTIM_CFLAGS) -I$(AUDIO_LIBS_DIR)/alsa-lib-$(ALSA_VERSION)/include -I$(AUDIO_LIBS_DIR)/opus-$(OPUS_VERSION)/include -I$(AUDIO_LIBS_DIR)/opus-$(OPUS_VERSION)/celt
|
||||||
|
export CGO_LDFLAGS := -L$(AUDIO_LIBS_DIR)/alsa-lib-$(ALSA_VERSION)/src/.libs -lasound -L$(AUDIO_LIBS_DIR)/opus-$(OPUS_VERSION)/.libs -lopus -lm -ldl -static
|
||||||
|
|
||||||
PROMETHEUS_TAG := github.com/prometheus/common/version
|
PROMETHEUS_TAG := github.com/prometheus/common/version
|
||||||
KVM_PKG_NAME := github.com/jetkvm/kvm
|
KVM_PKG_NAME := github.com/jetkvm/kvm
|
||||||
|
|
||||||
|
|
@ -53,11 +66,6 @@ hash_resource:
|
||||||
|
|
||||||
build_dev: build_audio_deps hash_resource
|
build_dev: build_audio_deps hash_resource
|
||||||
@echo "Building..."
|
@echo "Building..."
|
||||||
GOOS=linux GOARCH=arm GOARM=7 \
|
|
||||||
CC=$(TOOLCHAIN_DIR)/tools/linux/toolchain/arm-rockchip830-linux-uclibcgnueabihf/bin/arm-rockchip830-linux-uclibcgnueabihf-gcc \
|
|
||||||
CGO_ENABLED=1 \
|
|
||||||
CGO_CFLAGS="$(OPTIM_CFLAGS) -I$(AUDIO_LIBS_DIR)/alsa-lib-$(ALSA_VERSION)/include -I$(AUDIO_LIBS_DIR)/opus-$(OPUS_VERSION)/include -I$(AUDIO_LIBS_DIR)/opus-$(OPUS_VERSION)/celt" \
|
|
||||||
CGO_LDFLAGS="-L$(AUDIO_LIBS_DIR)/alsa-lib-$(ALSA_VERSION)/src/.libs -lasound -L$(AUDIO_LIBS_DIR)/opus-$(OPUS_VERSION)/.libs -lopus -lm -ldl -static" \
|
|
||||||
go build \
|
go build \
|
||||||
-ldflags="$(GO_LDFLAGS) -X $(KVM_PKG_NAME).builtAppVersion=$(VERSION_DEV)" \
|
-ldflags="$(GO_LDFLAGS) -X $(KVM_PKG_NAME).builtAppVersion=$(VERSION_DEV)" \
|
||||||
$(GO_RELEASE_BUILD_ARGS) \
|
$(GO_RELEASE_BUILD_ARGS) \
|
||||||
|
|
@ -81,11 +89,6 @@ build_dev_test: build_audio_deps build_test2json build_gotestsum
|
||||||
test_pkg_name=$$(echo $$test | sed 's/^.\///g'); \
|
test_pkg_name=$$(echo $$test | sed 's/^.\///g'); \
|
||||||
test_pkg_full_name=$(KVM_PKG_NAME)/$$(echo $$test | sed 's/^.\///g'); \
|
test_pkg_full_name=$(KVM_PKG_NAME)/$$(echo $$test | sed 's/^.\///g'); \
|
||||||
test_filename=$$(echo $$test_pkg_name | sed 's/\//__/g')_test; \
|
test_filename=$$(echo $$test_pkg_name | sed 's/\//__/g')_test; \
|
||||||
GOOS=linux GOARCH=arm GOARM=7 \
|
|
||||||
CC=$(TOOLCHAIN_DIR)/tools/linux/toolchain/arm-rockchip830-linux-uclibcgnueabihf/bin/arm-rockchip830-linux-uclibcgnueabihf-gcc \
|
|
||||||
CGO_ENABLED=1 \
|
|
||||||
CGO_CFLAGS="$(OPTIM_CFLAGS) -I$(AUDIO_LIBS_DIR)/alsa-lib-$(ALSA_VERSION)/include -I$(AUDIO_LIBS_DIR)/opus-$(OPUS_VERSION)/include -I$(AUDIO_LIBS_DIR)/opus-$(OPUS_VERSION)/celt" \
|
|
||||||
CGO_LDFLAGS="-L$(AUDIO_LIBS_DIR)/alsa-lib-$(ALSA_VERSION)/src/.libs -lasound -L$(AUDIO_LIBS_DIR)/opus-$(OPUS_VERSION)/.libs -lopus -lm -ldl -static" \
|
|
||||||
go test -v \
|
go test -v \
|
||||||
-ldflags="$(GO_LDFLAGS) -X $(KVM_PKG_NAME).builtAppVersion=$(VERSION_DEV)" \
|
-ldflags="$(GO_LDFLAGS) -X $(KVM_PKG_NAME).builtAppVersion=$(VERSION_DEV)" \
|
||||||
$(GO_BUILD_ARGS) \
|
$(GO_BUILD_ARGS) \
|
||||||
|
|
@ -120,11 +123,6 @@ dev_release: frontend build_dev
|
||||||
|
|
||||||
build_release: frontend build_audio_deps hash_resource
|
build_release: frontend build_audio_deps hash_resource
|
||||||
@echo "Building release..."
|
@echo "Building release..."
|
||||||
GOOS=linux GOARCH=arm GOARM=7 \
|
|
||||||
CC=$(TOOLCHAIN_DIR)/tools/linux/toolchain/arm-rockchip830-linux-uclibcgnueabihf/bin/arm-rockchip830-linux-uclibcgnueabihf-gcc \
|
|
||||||
CGO_ENABLED=1 \
|
|
||||||
CGO_CFLAGS="$(OPTIM_CFLAGS) -I$(AUDIO_LIBS_DIR)/alsa-lib-$(ALSA_VERSION)/include -I$(AUDIO_LIBS_DIR)/opus-$(OPUS_VERSION)/include -I$(AUDIO_LIBS_DIR)/opus-$(OPUS_VERSION)/celt" \
|
|
||||||
CGO_LDFLAGS="-L$(AUDIO_LIBS_DIR)/alsa-lib-$(ALSA_VERSION)/src/.libs -lasound -L$(AUDIO_LIBS_DIR)/opus-$(OPUS_VERSION)/.libs -lopus -lm -ldl -static" \
|
|
||||||
go build \
|
go build \
|
||||||
-ldflags="$(GO_LDFLAGS) -X $(KVM_PKG_NAME).builtAppVersion=$(VERSION)" \
|
-ldflags="$(GO_LDFLAGS) -X $(KVM_PKG_NAME).builtAppVersion=$(VERSION)" \
|
||||||
$(GO_RELEASE_BUILD_ARGS) \
|
$(GO_RELEASE_BUILD_ARGS) \
|
||||||
|
|
@ -149,9 +147,6 @@ lint: lint-go lint-ui
|
||||||
lint-go: build_audio_deps
|
lint-go: build_audio_deps
|
||||||
@echo "Running golangci-lint..."
|
@echo "Running golangci-lint..."
|
||||||
@mkdir -p static && touch static/.gitkeep
|
@mkdir -p static && touch static/.gitkeep
|
||||||
CGO_ENABLED=1 \
|
|
||||||
CGO_CFLAGS="-I$(AUDIO_LIBS_DIR)/alsa-lib-$(ALSA_VERSION)/include -I$(AUDIO_LIBS_DIR)/opus-$(OPUS_VERSION)/include -I$(AUDIO_LIBS_DIR)/opus-$(OPUS_VERSION)/celt" \
|
|
||||||
CGO_LDFLAGS="-L$(AUDIO_LIBS_DIR)/alsa-lib-$(ALSA_VERSION)/src/.libs -lasound -L$(AUDIO_LIBS_DIR)/opus-$(OPUS_VERSION)/.libs -lopus -lm -ldl -static" \
|
|
||||||
golangci-lint run --verbose
|
golangci-lint run --verbose
|
||||||
|
|
||||||
# Run both Go and UI linting with auto-fix
|
# Run both Go and UI linting with auto-fix
|
||||||
|
|
@ -162,9 +157,6 @@ lint-fix: lint-go-fix lint-ui-fix
|
||||||
lint-go-fix: build_audio_deps
|
lint-go-fix: build_audio_deps
|
||||||
@echo "Running golangci-lint with auto-fix..."
|
@echo "Running golangci-lint with auto-fix..."
|
||||||
@mkdir -p static && touch static/.gitkeep
|
@mkdir -p static && touch static/.gitkeep
|
||||||
CGO_ENABLED=1 \
|
|
||||||
CGO_CFLAGS="-I$(AUDIO_LIBS_DIR)/alsa-lib-$(ALSA_VERSION)/include -I$(AUDIO_LIBS_DIR)/opus-$(OPUS_VERSION)/include -I$(AUDIO_LIBS_DIR)/opus-$(OPUS_VERSION)/celt" \
|
|
||||||
CGO_LDFLAGS="-L$(AUDIO_LIBS_DIR)/alsa-lib-$(ALSA_VERSION)/src/.libs -lasound -L$(AUDIO_LIBS_DIR)/opus-$(OPUS_VERSION)/.libs -lopus -lm -ldl -static" \
|
|
||||||
golangci-lint run --fix --verbose
|
golangci-lint run --fix --verbose
|
||||||
|
|
||||||
# Run UI linting locally (mirrors GitHub workflow ui-lint.yml)
|
# Run UI linting locally (mirrors GitHub workflow ui-lint.yml)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,115 @@
|
||||||
|
//go:build arm && linux
|
||||||
|
|
||||||
|
package usbgadget
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
usbConfig = &Config{
|
||||||
|
VendorId: "0x1d6b", //The Linux Foundation
|
||||||
|
ProductId: "0x0104", //Multifunction Composite Gadget
|
||||||
|
SerialNumber: "",
|
||||||
|
Manufacturer: "JetKVM",
|
||||||
|
Product: "USB Emulation Device",
|
||||||
|
strictMode: true,
|
||||||
|
}
|
||||||
|
usbDevices = &Devices{
|
||||||
|
AbsoluteMouse: true,
|
||||||
|
RelativeMouse: true,
|
||||||
|
Keyboard: true,
|
||||||
|
MassStorage: true,
|
||||||
|
}
|
||||||
|
usbGadgetName = "jetkvm"
|
||||||
|
usbGadget *UsbGadget
|
||||||
|
)
|
||||||
|
|
||||||
|
var oldAbsoluteMouseCombinedReportDesc = []byte{
|
||||||
|
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
|
||||||
|
0x09, 0x02, // Usage (Mouse)
|
||||||
|
0xA1, 0x01, // Collection (Application)
|
||||||
|
|
||||||
|
// Report ID 1: Absolute Mouse Movement
|
||||||
|
0x85, 0x01, // Report ID (1)
|
||||||
|
0x09, 0x01, // Usage (Pointer)
|
||||||
|
0xA1, 0x00, // Collection (Physical)
|
||||||
|
0x05, 0x09, // Usage Page (Button)
|
||||||
|
0x19, 0x01, // Usage Minimum (0x01)
|
||||||
|
0x29, 0x03, // Usage Maximum (0x03)
|
||||||
|
0x15, 0x00, // Logical Minimum (0)
|
||||||
|
0x25, 0x01, // Logical Maximum (1)
|
||||||
|
0x75, 0x01, // Report Size (1)
|
||||||
|
0x95, 0x03, // Report Count (3)
|
||||||
|
0x81, 0x02, // Input (Data, Var, Abs)
|
||||||
|
0x95, 0x01, // Report Count (1)
|
||||||
|
0x75, 0x05, // Report Size (5)
|
||||||
|
0x81, 0x03, // Input (Cnst, Var, Abs)
|
||||||
|
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
|
||||||
|
0x09, 0x30, // Usage (X)
|
||||||
|
0x09, 0x31, // Usage (Y)
|
||||||
|
0x16, 0x00, 0x00, // Logical Minimum (0)
|
||||||
|
0x26, 0xFF, 0x7F, // Logical Maximum (32767)
|
||||||
|
0x36, 0x00, 0x00, // Physical Minimum (0)
|
||||||
|
0x46, 0xFF, 0x7F, // Physical Maximum (32767)
|
||||||
|
0x75, 0x10, // Report Size (16)
|
||||||
|
0x95, 0x02, // Report Count (2)
|
||||||
|
0x81, 0x02, // Input (Data, Var, Abs)
|
||||||
|
0xC0, // End Collection
|
||||||
|
|
||||||
|
// Report ID 2: Relative Wheel Movement
|
||||||
|
0x85, 0x02, // Report ID (2)
|
||||||
|
0x09, 0x38, // Usage (Wheel)
|
||||||
|
0x15, 0x81, // Logical Minimum (-127)
|
||||||
|
0x25, 0x7F, // Logical Maximum (127)
|
||||||
|
0x75, 0x08, // Report Size (8)
|
||||||
|
0x95, 0x01, // Report Count (1)
|
||||||
|
0x81, 0x06, // Input (Data, Var, Rel)
|
||||||
|
|
||||||
|
0xC0, // End Collection
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUsbGadgetInit(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
usbGadget = NewUsbGadget(usbGadgetName, usbDevices, usbConfig, nil)
|
||||||
|
|
||||||
|
assert.NotNil(usbGadget)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUsbGadgetStrictModeInitFail(t *testing.T) {
|
||||||
|
usbConfig.strictMode = true
|
||||||
|
u := NewUsbGadget("test", usbDevices, usbConfig, nil)
|
||||||
|
assert.Nil(t, u, "should be nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUsbGadgetUDCNotBoundAfterReportDescrChanged(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
usbGadget = NewUsbGadget(usbGadgetName, usbDevices, usbConfig, nil)
|
||||||
|
assert.NotNil(usbGadget)
|
||||||
|
|
||||||
|
// release the usb gadget and create a new one
|
||||||
|
usbGadget = nil
|
||||||
|
|
||||||
|
altGadgetConfig := defaultGadgetConfig
|
||||||
|
|
||||||
|
oldAbsoluteMouseConfig := altGadgetConfig["absolute_mouse"]
|
||||||
|
oldAbsoluteMouseConfig.reportDesc = oldAbsoluteMouseCombinedReportDesc
|
||||||
|
altGadgetConfig["absolute_mouse"] = oldAbsoluteMouseConfig
|
||||||
|
|
||||||
|
usbGadget = newUsbGadget(usbGadgetName, altGadgetConfig, usbDevices, usbConfig, nil)
|
||||||
|
assert.NotNil(usbGadget)
|
||||||
|
|
||||||
|
udcs := getUdcs()
|
||||||
|
assert.Equal(1, len(udcs), "should be only one UDC")
|
||||||
|
// check if the UDC is bound
|
||||||
|
udc := udcs[0]
|
||||||
|
assert.NotNil(udc, "UDC should exist")
|
||||||
|
|
||||||
|
udcStr, err := os.ReadFile("/sys/kernel/config/usb_gadget/jetkvm/UDC")
|
||||||
|
assert.Nil(err, "usb_gadget/UDC should exist")
|
||||||
|
assert.Equal(strings.TrimSpace(udc), strings.TrimSpace(string(udcStr)), "UDC should be the same")
|
||||||
|
}
|
||||||
|
|
@ -86,6 +86,7 @@ func TestUsbGadgetHardwareInit(t *testing.T) {
|
||||||
|
|
||||||
// Validate gadget state
|
// Validate gadget state
|
||||||
assert.NotNil(t, gadget, "USB gadget should not be nil")
|
assert.NotNil(t, gadget, "USB gadget should not be nil")
|
||||||
|
validateHardwareState(t, gadget)
|
||||||
|
|
||||||
// Test UDC binding state
|
// Test UDC binding state
|
||||||
bound, err := gadget.IsUDCBound()
|
bound, err := gadget.IsUDCBound()
|
||||||
|
|
@ -144,6 +145,7 @@ func TestUsbGadgetHardwareReconfiguration(t *testing.T) {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
assert.NotNil(t, gadget2, "Second USB gadget should be initialized")
|
assert.NotNil(t, gadget2, "Second USB gadget should be initialized")
|
||||||
|
validateHardwareState(t, gadget2)
|
||||||
|
|
||||||
// Validate UDC binding after reconfiguration
|
// Validate UDC binding after reconfiguration
|
||||||
udcs := getUdcs()
|
udcs := getUdcs()
|
||||||
|
|
@ -187,6 +189,7 @@ func TestUsbGadgetHardwareStressTest(t *testing.T) {
|
||||||
|
|
||||||
// Validate gadget
|
// Validate gadget
|
||||||
assert.NotNil(t, gadget, "USB gadget should be created in iteration %d", i+1)
|
assert.NotNil(t, gadget, "USB gadget should be created in iteration %d", i+1)
|
||||||
|
validateHardwareState(t, gadget)
|
||||||
|
|
||||||
// Test basic operations
|
// Test basic operations
|
||||||
bound, err := gadget.IsUDCBound()
|
bound, err := gadget.IsUDCBound()
|
||||||
|
|
@ -327,4 +330,4 @@ func validateHardwareState(t *testing.T, gadget *UsbGadget) {
|
||||||
} else {
|
} else {
|
||||||
t.Logf("configfs is available")
|
t.Logf("configfs is available")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue