Adding multi device support

This commit is contained in:
2025-12-06 22:26:03 +00:00
parent 9cab522c06
commit c23441908f
9 changed files with 188 additions and 4 deletions
+46
View File
@@ -3,6 +3,8 @@ package cmd
import (
"esdi/peripheral"
"esdi/repl"
"fmt"
"strconv"
"github.com/spf13/cobra"
)
@@ -37,8 +39,52 @@ func replCmdAction(cmd *cobra.Command, args []string) {
},
}
listDeviceAPIREPLCmd := repl.Command{
Name: "v-api",
Usage: "shows API of a device - pass its ID",
Action: func(r *repl.REPL, args []string) error {
// We should add this to the REPL instead
if len(args) < 1 {
return fmt.Errorf("requires at least on argument")
}
// First and only argument should be the ID of the device we want to use
targetID, err := strconv.ParseInt(args[0], 10, 0)
if err != nil {
return err
}
err = perClerk.ListDeviceAPI(uint8(targetID))
if err != nil {
fmt.Println("failed to view device API: ", err.Error())
}
return nil
},
}
// selectDeviceREPLCmd := repl.Command{
// Name: "select",
// Usage: "Selects a given device - pass its ID",
// Action: func(r *repl.REPL, args []string) error {
// // We should add this to the REPL instead
// if len(args) < 1 {
// return fmt.Errorf("requires at least on argument")
// }
//
// // First and only argument should be the ID of the device we want to use
// targetID, err := strconv.ParseInt(args[0], 10, 0)
// if err != nil {
// return err
// }
//
// return nil
// },
// }
r.RegisterCMD(discoverDevicesREPLCmd)
r.RegisterCMD(listDevicesREPLCmd)
// r.RegisterCMD(selectDeviceREPLCmd)
r.RegisterCMD(listDeviceAPIREPLCmd)
r.Start()
r.Close()
+8
View File
@@ -0,0 +1,8 @@
// Package helper
package helper
func B32(s string) [32]byte {
var b [32]byte
copy(b[:], s)
return b
}
+2
View File
@@ -1,6 +1,7 @@
package peripheral
import (
"esdi/peripheral/devices"
"time"
"github.com/tarm/serial"
@@ -39,6 +40,7 @@ type PeripheralDevice struct {
ID uint8
Name string
WT *WalkieTalkie
DeviceAPI *devices.Device
}
func NewPeripheralDevice(port string) *PeripheralDevice {
+35
View File
@@ -0,0 +1,35 @@
package devices
import helper "esdi/helpers"
const (
newWindowCMDID = iota
destroyWindowCMDID
)
var CDashDisplay = Device{
ID: CDashDisplayDevID,
Name: helper.B32("ESLabs CDashDisplay"),
API: map[string]DeviceCMD{
"new-window": {
Identifier: newWindowCMDID,
Name: "new-window",
Desc: "Creates a new window - pass the window name and dimensions",
Fn: createWindow,
},
"destroy-window": {
Identifier: destroyWindowCMDID,
Name: "destroy-window",
Desc: "Destroys a window by its ID",
Fn: destroyWindow,
},
},
}
func createWindow(data []byte) {
// Parse the command
}
func destroyWindow(data []byte) {
// Parse the command
}
+46
View File
@@ -0,0 +1,46 @@
// Package devices will define the available devices we can communicate with
package devices
import "esdi/peripheral/types"
// IDs for our devices. They need to be correctly mapped on the devices
// themselves so we can discover them
const (
CDashDisplayDevID = 0x01
ESBtnBoxDevID = 0x02
)
// DeviceMap maps the implemented devices
// When adding a new device we append it here too
var DeviceMap = map[int]Device{
CDashDisplayDevID: CDashDisplay,
ESBtnBoxDevID: ESBtnBox,
}
type Device struct {
ID uint8
Name [32]byte
API map[string]DeviceCMD
}
type DeviceCMDHeader struct {
Payload [64]byte
}
type DeviceCMDPayload struct {
Payload [64]byte
}
// DeviceCMDFn defines the basic type for the functions the devices can have
// The function will receive a []byte that should be the arguments the user
// types in the REPL - or however this will be used
type DeviceCMDFn func(data []byte)
type DeviceCMD struct {
Identifier types.CommandID
Name string
Desc string
Header DeviceCMDHeader
Data DeviceCMDPayload
Fn DeviceCMDFn
}
+9
View File
@@ -0,0 +1,9 @@
package devices
import helper "esdi/helpers"
var ESBtnBox = Device{
ID: ESBtnBoxDevID,
Name: helper.B32("ESLabs Button Box"),
API: map[string]DeviceCMD{},
}
+34 -4
View File
@@ -2,6 +2,7 @@
package peripheral
import (
"esdi/peripheral/devices"
"fmt"
"path/filepath"
)
@@ -14,12 +15,12 @@ const (
type PeripheralDeviceClerk struct {
// mu sync.RWMutex
Devices map[string]*PeripheralDevice
Devices map[uint8]*PeripheralDevice
}
func NewPeripheralDeviceClerk() *PeripheralDeviceClerk {
return &PeripheralDeviceClerk{
Devices: make(map[string]*PeripheralDevice),
Devices: make(map[uint8]*PeripheralDevice),
}
}
@@ -33,7 +34,17 @@ func (clerk *PeripheralDeviceClerk) listPorts() ([]string, error) {
}
func (clerk *PeripheralDeviceClerk) addDevice(dev *PeripheralDevice) {
clerk.Devices[string(dev.Name[:])] = dev
clerk.Devices[dev.ID] = dev
}
func (clerk *PeripheralDeviceClerk) FindDeviceAPI(ID uint8) *devices.Device {
for _, d := range devices.DeviceMap {
if d.ID == ID {
return &d
}
}
return nil
}
func (clerk *PeripheralDeviceClerk) FindDevices() error {
@@ -51,6 +62,13 @@ func (clerk *PeripheralDeviceClerk) FindDevices() error {
continue
}
// Look for the device on our device list - we need its API
newDevice.DeviceAPI = clerk.FindDeviceAPI(newDevice.ID)
if newDevice.DeviceAPI == nil {
fmt.Printf("Failed to acquire API for device: [%2d] %s\n",
newDevice.ID, newDevice.Name)
}
clerk.addDevice(newDevice)
fmt.Println(p, string(newDevice.Name[:]))
}
@@ -62,7 +80,19 @@ func (clerk *PeripheralDeviceClerk) FindDevices() error {
func (clerk *PeripheralDeviceClerk) ListDevices() error {
for _, d := range clerk.Devices {
fmt.Printf("[%d] %s\n", d.ID, d.Name)
fmt.Printf("[%2d] %s\n", d.ID, d.Name)
}
return nil
}
func (clerk *PeripheralDeviceClerk) ListDeviceAPI(ID uint8) error {
if _, ok := clerk.Devices[ID]; !ok {
return fmt.Errorf("device with ID %d not found", ID)
}
for _, f := range clerk.Devices[ID].DeviceAPI.API {
fmt.Printf("%s\t%s\n", f.Name, f.Desc)
}
return nil
+4
View File
@@ -0,0 +1,4 @@
// Package types defines the types necessary to handle peripherals
package types
type CommandID uint8
+4
View File
@@ -47,6 +47,10 @@ func (r *REPL) printPrompt() {
_, _ = os.Stdout.Write([]byte(r.Cfg.PS1))
}
func (r *REPL) SetPS1(s string) {
r.Cfg.PS1 = s
}
func (r *REPL) mainLoop() {
reader := bufio.NewReader(os.Stdin)
for {