diff --git a/pkg/tools/i2c.go b/pkg/tools/i2c.go index cf3439ad6..8ff157316 100644 --- a/pkg/tools/i2c.go +++ b/pkg/tools/i2c.go @@ -114,3 +114,42 @@ func (t *I2CTool) detect() *ToolResult { result, _ := json.MarshalIndent(buses, "", " ") return SilentResult(fmt.Sprintf("Found %d I2C bus(es):\n%s", len(buses), string(result))) } + +// Helper functions for I2C operations (used by platform-specific implementations) + +// isValidBusID checks that a bus identifier is a simple number (prevents path injection) +// +//nolint:unused // Used by i2c_linux.go +func isValidBusID(id string) bool { + matched, _ := regexp.MatchString(`^\d+$`, id) + return matched +} + +// parseI2CAddress extracts and validates an I2C address from args +// +//nolint:unused // Used by i2c_linux.go +func parseI2CAddress(args map[string]interface{}) (int, *ToolResult) { + addrFloat, ok := args["address"].(float64) + if !ok { + return 0, ErrorResult("address is required (e.g. 0x38 for AHT20)") + } + addr := int(addrFloat) + if addr < 0x03 || addr > 0x77 { + return 0, ErrorResult("address must be in valid 7-bit range (0x03-0x77)") + } + return addr, nil +} + +// parseI2CBus extracts and validates an I2C bus from args +// +//nolint:unused // Used by i2c_linux.go +func parseI2CBus(args map[string]interface{}) (string, *ToolResult) { + bus, ok := args["bus"].(string) + if !ok || bus == "" { + return "", ErrorResult("bus is required (e.g. \"1\" for /dev/i2c-1)") + } + if !isValidBusID(bus) { + return "", ErrorResult("invalid bus identifier: must be a number (e.g. \"1\")") + } + return bus, nil +} diff --git a/pkg/tools/spi.go b/pkg/tools/spi.go index 91ed2d2d2..311a322e7 100644 --- a/pkg/tools/spi.go +++ b/pkg/tools/spi.go @@ -116,3 +116,45 @@ func (t *SPITool) list() *ToolResult { result, _ := json.MarshalIndent(devices, "", " ") return SilentResult(fmt.Sprintf("Found %d SPI device(s):\n%s", len(devices), string(result))) } + +// Helper function for SPI operations (used by platform-specific implementations) + +// parseSPIArgs extracts and validates common SPI parameters +// +//nolint:unused // Used by spi_linux.go +func parseSPIArgs(args map[string]interface{}) (device string, speed uint32, mode uint8, bits uint8, errMsg string) { + dev, ok := args["device"].(string) + if !ok || dev == "" { + return "", 0, 0, 0, "device is required (e.g. \"2.0\" for /dev/spidev2.0)" + } + matched, _ := regexp.MatchString(`^\d+\.\d+$`, dev) + if !matched { + return "", 0, 0, 0, "invalid device identifier: must be in format \"X.Y\" (e.g. \"2.0\")" + } + + speed = 1000000 // default 1 MHz + if s, ok := args["speed"].(float64); ok { + if s < 1 || s > 125000000 { + return "", 0, 0, 0, "speed must be between 1 Hz and 125 MHz" + } + speed = uint32(s) + } + + mode = 0 + if m, ok := args["mode"].(float64); ok { + if int(m) < 0 || int(m) > 3 { + return "", 0, 0, 0, "mode must be 0-3" + } + mode = uint8(m) + } + + bits = 8 + if b, ok := args["bits"].(float64); ok { + if int(b) < 1 || int(b) > 32 { + return "", 0, 0, 0, "bits must be between 1 and 32" + } + bits = uint8(b) + } + + return dev, speed, mode, bits, "" +}