refactoring

This commit is contained in:
MaMe82 2018-07-28 04:49:25 +02:00
parent c0b5b5ba26
commit c188e1f5c1
9 changed files with 278 additions and 102 deletions

View File

@ -7,13 +7,16 @@ import (
"context"
"sync"
"time"
"log"
"strconv"
)
/*
var (
EvMgr *EventManager
evmMutex = &sync.Mutex{}
)
*/
func pDEBUG(message string) {
fmt.Println("EVENT DEBUG: " + message)
}
@ -30,6 +33,31 @@ type EventManager struct {
receiverRegListMutex *sync.Mutex
}
func NewEventManager(queueSize int) *EventManager {
EvMgr := &EventManager{
eventQueue: make(chan *pb.Event, queueSize),
receiverDelListMutex: &sync.Mutex{},
receiverRegListMutex: &sync.Mutex{},
receiverRegisterList: make(map[*EventReceiver]bool),
registeredReceivers: make(map[*EventReceiver]bool),
receiverDeleteList: make(map[*EventReceiver]bool),
}
EvMgr.ctx, EvMgr.cancel = context.WithCancel(context.Background())
return EvMgr
}
func (evm *EventManager) Start() {
log.Println("Event Manager: Starting event dispatcher")
go evm.dispatch()
}
func (evm *EventManager) Stop() {
log.Println("Event Manager: Stopping ...")
evm.cancel()
close(evm.eventQueue)
}
/*
func StartEventManager(queueSize int) *EventManager {
if EvMgr != nil { StopEventManager() }
@ -61,10 +89,11 @@ func StopEventManager() {
close(EvMgr.eventQueue)
}
*/
func (em *EventManager) Emit(event *pb.Event) {
em.eventQueue <-event
// fmt.Println("Event enqueued")
//fmt.Println("Event enqueued")
}
func (em *EventManager) Write(p []byte) (n int, err error) {
@ -75,6 +104,8 @@ func (em *EventManager) Write(p []byte) (n int, err error) {
func (em *EventManager) RegisterReceiver(filterEventType int64) *EventReceiver {
fmt.Println("!!!Event listener registered for " + strconv.Itoa(int(filterEventType)))
ctx,cancel := context.WithCancel(context.Background())
er := &EventReceiver{
EventQueue: make(chan *pb.Event, 10), //allow buffering 10 events per receiver

View File

@ -4,6 +4,15 @@ import (
pb "../proto"
)
const (
DEFAULT_CDC_ECM_HOST_ADDR = "42:63:66:12:34:56"
DEFAULT_CDC_ECM_DEV_ADDR = "42:63:66:56:34:12"
DEFAULT_RNDIS_HOST_ADDR = "42:63:65:12:34:56"
DEFAULT_RNDIS_DEV_ADDR = "42:63:65:56:34:12"
USB_ETHERNET_BRIDGE_MAC = "24:22:26:12:14:16"
USB_ETHERNET_BRIDGE_NAME = "usbeth"
)
func GetDefaultNetworkSettingsUSB() (*pb.EthernetInterfaceSettings) {
//configure 172.24.0.1/255.255.255.252 for usbeth
ifSettings := &pb.EthernetInterfaceSettings {
@ -70,8 +79,8 @@ func GetDefaultDHCPConfigWiFi() (settings *pb.DHCPServerSettings) {
return
}
func GetDefaultLEDSettings() (res pb.LEDSettings) {
return pb.LEDSettings{
func GetDefaultLEDSettings() (res *pb.LEDSettings) {
return &pb.LEDSettings{
BlinkCount: 254,
}
}
@ -93,12 +102,12 @@ func GetDefaultGadgetSettings() (res pb.GadgetSettings) {
Use_UMS: false,
Use_SERIAL: false,
RndisSettings: &pb.GadgetSettingsEthernet{
HostAddr: "42:63:65:12:34:56",
DevAddr: "42:63:65:56:34:12",
HostAddr: DEFAULT_RNDIS_HOST_ADDR,
DevAddr: DEFAULT_RNDIS_DEV_ADDR,
},
CdcEcmSettings: &pb.GadgetSettingsEthernet{
HostAddr: "42:63:66:12:34:56",
DevAddr: "42:63:66:56:34:12",
HostAddr: DEFAULT_CDC_ECM_HOST_ADDR,
DevAddr: DEFAULT_CDC_ECM_DEV_ADDR,
},
UmsSettings: &pb.GadgetSettingsUMS{
File:"", //we don't supply an image file, which is no problem as it could be applied later on (removable media)

View File

@ -21,11 +21,19 @@ const (
LED_DELAY_PAUSE = 500 * time.Millisecond
)
type LedState struct {
blink_count *uint32
}
/*
var (
blink_count uint32 = 0
)
*/
func NewLed(led_on bool) (ledState *LedState, err error) {
blinkCount := uint32(0)
ledState = &LedState{ &blinkCount }
func InitLed(led_on bool) (error) {
//set trigger of LED to manual
log.Println("Setting LED to manual trigger ...")
ioutil.WriteFile(LED_TRIGGER_PATH, []byte(LED_TRIGGER_MANUAL), os.ModePerm)
@ -36,22 +44,22 @@ func InitLed(led_on bool) (error) {
log.Println("Setting LED to OFF ...")
ioutil.WriteFile(LED_BRIGHTNESS_PATH, []byte(LED_OFF), os.ModePerm)
}
atomic.StoreUint32(&blink_count, 0)
go led_loop()
return nil
go ledState.led_loop() // watcher loop
ledState.SetLed(GetDefaultLEDSettings()) //set default setting
return ledState,nil
}
func led_loop() {
func (leds *LedState) led_loop() {
for {
for i := uint32(0); i < atomic.LoadUint32(&blink_count); i++ {
for i := uint32(0); i < atomic.LoadUint32(leds.blink_count); i++ {
ioutil.WriteFile(LED_BRIGHTNESS_PATH, []byte(LED_ON), os.ModePerm)
time.Sleep(LED_DELAY_ON)
//Don't turn off led if blink_count >= 255 (solid)
if 255 > atomic.LoadUint32(&blink_count) {
if 255 > atomic.LoadUint32(leds.blink_count) {
ioutil.WriteFile(LED_BRIGHTNESS_PATH, []byte(LED_OFF), os.ModePerm)
time.Sleep(LED_DELAY_OFF)
}
@ -60,18 +68,15 @@ func led_loop() {
}
}
func SetLed(s pb.LEDSettings) (error) {
func (leds *LedState) SetLed(s *pb.LEDSettings) (error) {
//log.Printf("setLED called with %+v", s)
atomic.StoreUint32(&blink_count, s.BlinkCount)
atomic.StoreUint32(leds.blink_count, s.BlinkCount)
return nil
}
func GetLed() (res *pb.LEDSettings, err error) {
return &pb.LEDSettings{BlinkCount: atomic.LoadUint32(&blink_count)}, nil
func (leds *LedState) GetLed() (res *pb.LEDSettings, err error) {
return &pb.LEDSettings{BlinkCount: atomic.LoadUint32(leds.blink_count)}, nil
}
func InitDefaultLEDSettings() {
SetLed(GetDefaultLEDSettings())
}

View File

@ -13,18 +13,10 @@ import (
"errors"
)
var (
StoredNetworkSetting map[string]*pb.EthernetInterfaceSettings = make(map[string]*pb.EthernetInterfaceSettings)
)
func init() {
//preinitialize Default settings for "wlan0" and USB_ETHERNET_BRIDGE_NAME ("usbeth")
StoredNetworkSetting[USB_ETHERNET_BRIDGE_NAME] = GetDefaultNetworkSettingsUSB()
StoredNetworkSetting["wlan0"] = GetDefaultNetworkSettingsWiFi()
}
func ReInitNetworkInterface(ifName string) (err error) {
if settings, existing := StoredNetworkSetting[ifName]; existing {
if settings, existing := ServiceState.StoredNetworkSetting[ifName]; existing {
log.Printf("Redeploying stored Network settings for interface '%s' ...\n", ifName)
return ConfigureInterface(settings)
} else {
@ -208,7 +200,7 @@ func ConfigureInterface(settings *pb.EthernetInterfaceSettings) (err error) {
}
//Store latest settings
StoredNetworkSetting[settings.Name] = settings
ServiceState.StoredNetworkSetting[settings.Name] = settings
return nil
}

View File

@ -30,7 +30,8 @@ var (
type server struct {}
func (s *server) EventListen(eReq *pb.EventRequest, eStream pb.P4WNP1_EventListenServer) (err error) {
rcv := EvMgr.RegisterReceiver(eReq.ListenType)
//ToDo: check dependency from state (EvMgr initialized)
rcv := ServiceState.EvMgr.RegisterReceiver(eReq.ListenType)
for {
@ -96,9 +97,9 @@ func (s *server) FSCreateTempDirOrFile(ctx context.Context, req *pb.TempDirOrFil
}
func (s *server) HIDGetRunningScriptJobs(ctx context.Context, rEmpty *pb.Empty) (jobs *pb.HIDScriptJobList, err error) {
if HidCtl == nil { return nil, rpcErrNoHid}
if ServiceState.HidCtl == nil { return nil, rpcErrNoHid}
retJobs,err := HidCtl.GetAllBackgroundJobs()
retJobs,err := ServiceState.HidCtl.GetAllBackgroundJobs()
if err != nil { return nil, err }
jobs = &pb.HIDScriptJobList{}
jobs.Ids = retJobs
@ -107,10 +108,10 @@ func (s *server) HIDGetRunningScriptJobs(ctx context.Context, rEmpty *pb.Empty)
func (s *server) HIDCancelAllScriptJobs(ctx context.Context, rEmpty *pb.Empty) (empty *pb.Empty, err error) {
empty = &pb.Empty{}
if HidCtl == nil { return empty, rpcErrNoHid}
if ServiceState.HidCtl == nil { return empty, rpcErrNoHid}
// Try to find script
HidCtl.CancelAllBackgroundJobs()
ServiceState.HidCtl.CancelAllBackgroundJobs()
return
}
@ -118,10 +119,10 @@ func (s *server) HIDCancelAllScriptJobs(ctx context.Context, rEmpty *pb.Empty) (
func (s *server) HIDCancelScriptJob(ctx context.Context, sJob *pb.HIDScriptJob) (empty *pb.Empty, err error) {
empty = &pb.Empty{}
if HidCtl == nil { return empty, rpcErrNoHid}
if ServiceState.HidCtl == nil { return empty, rpcErrNoHid}
// Try to find script
job,err := HidCtl.GetBackgroundJobByID(int(sJob.Id))
job,err := ServiceState.HidCtl.GetBackgroundJobByID(int(sJob.Id))
if err != nil { return empty, err }
job.Cancel()
@ -129,7 +130,7 @@ func (s *server) HIDCancelScriptJob(ctx context.Context, sJob *pb.HIDScriptJob)
}
func (s *server) HIDRunScript(ctx context.Context, scriptReq *pb.HIDScriptRequest) (scriptRes *pb.HIDScriptResult, err error) {
if HidCtl == nil { return nil, rpcErrNoHid}
if ServiceState.HidCtl == nil { return nil, rpcErrNoHid}
@ -142,7 +143,7 @@ func (s *server) HIDRunScript(ctx context.Context, scriptReq *pb.HIDScriptReques
if scriptReq.TimeoutSeconds > 0 { jobCtx,_ = context.WithTimeout(jobCtx, time.Second * time.Duration(scriptReq.TimeoutSeconds))}
scriptVal,err := HidCtl.RunScript(jobCtx, string(scriptFile))
scriptVal,err := ServiceState.HidCtl.RunScript(jobCtx, string(scriptFile))
if err != nil { return nil,err }
val,_ := scriptVal.Export() //Convert to Go representation, error is always nil
jsonVal,err := json.Marshal(val)
@ -159,7 +160,7 @@ func (s *server) HIDRunScript(ctx context.Context, scriptReq *pb.HIDScriptReques
}
func (s *server) HIDRunScriptJob(ctx context.Context, scriptReq *pb.HIDScriptRequest) (rJob *pb.HIDScriptJob, err error) {
if HidCtl == nil { return nil, rpcErrNoHid}
if ServiceState.HidCtl == nil { return nil, rpcErrNoHid}
if scriptFile, err := ioutil.ReadFile(scriptReq.ScriptPath); err != nil {
return nil, errors.New(fmt.Sprintf("Couldn't load HIDScript '%s': %v\n", scriptReq.ScriptPath, err))
@ -168,7 +169,7 @@ func (s *server) HIDRunScriptJob(ctx context.Context, scriptReq *pb.HIDScriptReq
jobCtx := context.Background()
// ToDo: we don't retrieve the cancelFunc which should be called to free resources. Solution: use withCancel context and call cancel by go routine on timeout
if scriptReq.TimeoutSeconds > 0 { jobCtx,_ = context.WithTimeout(jobCtx, time.Second * time.Duration(scriptReq.TimeoutSeconds))}
job,err := HidCtl.StartScriptAsBackgroundJob(jobCtx, string(scriptFile))
job,err := ServiceState.HidCtl.StartScriptAsBackgroundJob(jobCtx, string(scriptFile))
if err != nil { return nil,err }
rJob = &pb.HIDScriptJob{
@ -180,15 +181,15 @@ func (s *server) HIDRunScriptJob(ctx context.Context, scriptReq *pb.HIDScriptReq
}
func (s *server) HIDGetScriptJobResult(ctx context.Context, sJob *pb.HIDScriptJob) (scriptRes *pb.HIDScriptResult, err error) {
if HidCtl == nil { return nil, rpcErrNoHid}
if ServiceState.HidCtl == nil { return nil, rpcErrNoHid}
// Try to find script
job,err := HidCtl.GetBackgroundJobByID(int(sJob.Id))
job,err := ServiceState.HidCtl.GetBackgroundJobByID(int(sJob.Id))
if err != nil { return scriptRes, err }
//ToDo: check impact/behavior, because ctx is provided by gRPC server
scriptVal,err := HidCtl.WaitBackgroundJobResult(ctx, job)
scriptVal,err := ServiceState.HidCtl.WaitBackgroundJobResult(ctx, job)
if err != nil { return nil,err }
val,_ := scriptVal.Export() //Convert to Go representation, error is always nil
jsonVal,err := json.Marshal(val)
@ -250,11 +251,11 @@ func (s *server) DeployGadgetSetting(context.Context, *pb.Empty) (gs *pb.GadgetS
//ToDo: Former gadgets are destroyed without testing if there're changes, this should be aborted if GadgetSettingsState == GetDeployedGadgetSettings()
DestroyGadget(USB_GADGET_NAME)
errg := DeployGadgetSettings(GadgetSettingsState)
errg := ServiceState.UsbGM.DeployGadgetSettings(ServiceState.UsbGM.UndeployedGadgetSettings)
err = nil
if errg != nil {
err = errors.New(fmt.Sprintf("Deploying new gadget settings failed, reverted to old ones: %v", errg))
DeployGadgetSettings(*gs_backup) //We don't catch the error, as the old settings should have been working
ServiceState.UsbGM.DeployGadgetSettings(gs_backup) //We don't catch the error, as the old settings should have been working
}
gs, _ = ParseGadgetState(USB_GADGET_NAME) //Return settings from deployed gadget
@ -262,29 +263,29 @@ func (s *server) DeployGadgetSetting(context.Context, *pb.Empty) (gs *pb.GadgetS
}
func (s *server) GetGadgetSettings(context.Context, *pb.Empty) (*pb.GadgetSettings, error) {
return &GadgetSettingsState, nil
return ServiceState.UsbGM.UndeployedGadgetSettings, nil
}
func (s *server) SetGadgetSettings(ctx context.Context, gs *pb.GadgetSettings) (res *pb.GadgetSettings, err error) {
if err = ValidateGadgetSetting(*gs); err != nil {
//We return the validation error and the current (unchanged) GadgetSettingsState
res = &GadgetSettingsState
res = ServiceState.UsbGM.UndeployedGadgetSettings
return
}
GadgetSettingsState = *gs
res = &GadgetSettingsState
ServiceState.UsbGM.UndeployedGadgetSettings = gs
res = ServiceState.UsbGM.UndeployedGadgetSettings
return
}
func (s *server) GetLEDSettings(context.Context, *pb.Empty) (res *pb.LEDSettings, err error) {
res, err = GetLed()
res, err = ServiceState.Led.GetLed()
log.Printf("GetLEDSettings, result: %+v", res)
return
}
func (s *server) SetLEDSettings(ctx context.Context, ls *pb.LEDSettings) (*pb.Empty, error) {
log.Printf("SetLEDSettings %+v", ls)
SetLed(*ls)
ServiceState.Led.SetLed(ls)
return &pb.Empty{}, nil
}

47
service/state.go Normal file
View File

@ -0,0 +1,47 @@
package service
import (
"../hid"
pb "../proto"
)
var ServiceState *GlobalServiceState
type GlobalServiceState struct {
EvMgr *EventManager
HidCtl *hid.HIDController
UsbGM *UsbGadgetManager
Led *LedState
HidDevPath map[string]string //stores device path for HID devices
StoredNetworkSetting map[string]*pb.EthernetInterfaceSettings
}
func InitGlobalServiceState() (err error) {
state := &GlobalServiceState{}
ServiceState = state // store state in global variable
state.StoredNetworkSetting = make(map[string]*pb.EthernetInterfaceSettings)
//preinitialize Default settings for "wlan0" and USB_ETHERNET_BRIDGE_NAME ("usbeth")
state.StoredNetworkSetting[USB_ETHERNET_BRIDGE_NAME] = GetDefaultNetworkSettingsUSB()
state.StoredNetworkSetting["wlan0"] = GetDefaultNetworkSettingsWiFi()
state.HidDevPath = make(map[string]string) //should be initialized BEFORE UsbGadgetManager uses it
state.EvMgr = NewEventManager(20)
state.UsbGM,err = NewUSBGadgetManager()
if err != nil { return }
ledState, err := NewLed(false)
if err != nil { return }
state.Led = ledState
return nil
}
func (state *GlobalServiceState) StartService() {
state.EvMgr.Start()
}
func (state *GlobalServiceState) StopService() {
state.EvMgr.Stop()
}

View File

@ -31,9 +31,6 @@ const (
USB_GADGET_DIR_BASE = "/sys/kernel/config/usb_gadget"
USB_GADGET_DIR = USB_GADGET_DIR_BASE + "/" + USB_GADGET_NAME
USB_ETHERNET_BRIDGE_NAME = "usbeth"
USB_ETHERNET_BRIDGE_MAC = "24:22:26:12:14:16"
USB_bcdDevice = "0x0100" //Version 1.00
USB_bcdUSB = "0x0200" //mode: USB 2.0
@ -77,12 +74,24 @@ const (
)
var (
GadgetSettingsState pb.GadgetSettings = pb.GadgetSettings{}
rp_usbHidDevName = regexp.MustCompile("(?m)DEVNAME=(.*)\n")
HidDevPath = make(map[string]string) //stores device path for HID devices
HidCtl *hid.HIDController
)
var rp_usbHidDevName = regexp.MustCompile("(?m)DEVNAME=(.*)\n")
type UsbGadgetManager struct {
// ToDo: variable, indicating if HIDScript is usable
HidCtl *hid.HIDController // Points to an HID controller instance only if keyboard and/or mouse are enabled, nil otherwise
UndeployedGadgetSettings *pb.GadgetSettings
}
func NewUSBGadgetManager() (newUGM *UsbGadgetManager, err error) {
newUGM = &UsbGadgetManager{}
defGS := GetDefaultGadgetSettings()
newUGM.UndeployedGadgetSettings = &defGS //preload state with default settings
err = newUGM.DeployGadgetSettings(newUGM.UndeployedGadgetSettings)
if err != nil { return nil, err }
return
}
func ValidateGadgetSetting(gs pb.GadgetSettings) error {
/* ToDo: validations
@ -91,7 +100,7 @@ func ValidateGadgetSetting(gs pb.GadgetSettings) error {
- check EP consumption to be not more than 7 (ECM 2 EP, RNDIS 2 EP, HID Mouse 1 EP, HID Keyboard 1 EP, HID Raw 1 EP, Serial 2 EP ??, UMS 2 EP ?)
- check serial, product, Manufacturer to not be empty
- check Pid, Vid with regex (Note: we don't check if Vid+Pid have been used for another composite function setup, yet)
- If the gadget is enabled, at least one function has to be enabled
- Done: If the gadget is enabled, at least one function has to be enabled
*/
log.Println("Validating gadget settings ...")
@ -126,6 +135,18 @@ func ValidateGadgetSetting(gs pb.GadgetSettings) error {
log.Print(strConsumption)
if sum_ep > USB_EP_USAGE_MAX { return errors.New(strConsumption)}
//check if composite gadget is enabled without functions
if gs.Enabled &&
!gs.Use_CDC_ECM &&
!gs.Use_RNDIS &&
!gs.Use_HID_KEYBOARD &&
!gs.Use_HID_MOUSE &&
!gs.Use_HID_RAW &&
!gs.Use_UMS &&
!gs.Use_SERIAL {
return errors.New("If the composite gadget isn't disabled, as least one function has to be enabled")
}
return nil
}
@ -175,12 +196,6 @@ func pollForUSBEthernet(timeout time.Duration) error {
return errors.New(fmt.Sprintf("Timeout %v reached before usb0 or usb1 became ready"))
}
func InitDefaultGadgetSettings() (err error) {
err = DeployGadgetSettings(GetDefaultGadgetSettings()) //Deploy default settings to ConfigFS
if err != nil { return }
GadgetSettingsState = GetDefaultGadgetSettings() //populate settings state with same values
return nil
}
@ -291,6 +306,12 @@ func ParseGadgetState(gadgetName string) (result *pb.GadgetSettings, err error)
} else {
result.RndisSettings.DevAddr = strings.TrimSuffix(string(res), "\000\n")
}
} else {
// we provide GadgetSettingsEthernet with default MAC adresses anyway, to have defaults in case RNDIS should be enabled
result.RndisSettings = &pb.GadgetSettingsEthernet{
HostAddr: DEFAULT_RNDIS_HOST_ADDR,
DevAddr: DEFAULT_RNDIS_DEV_ADDR,
}
}
//USB CDC ECM
@ -313,6 +334,12 @@ func ParseGadgetState(gadgetName string) (result *pb.GadgetSettings, err error)
result.CdcEcmSettings.DevAddr = strings.TrimSuffix(string(res), "\000\n")
}
} else {
// we provide GadgetSettingsEthernet with default MAC adresses anyway, to have defaults in case CDC ECM should be enabled
result.CdcEcmSettings = &pb.GadgetSettingsEthernet{
HostAddr: DEFAULT_CDC_ECM_HOST_ADDR,
DevAddr: DEFAULT_CDC_ECM_DEV_ADDR,
}
}
//USB serial
@ -388,7 +415,7 @@ func MountUMSFile(filename string) error {
return nil
}
func DeployGadgetSettings(settings pb.GadgetSettings) error {
func (gm *UsbGadgetManager) DeployGadgetSettings(settings *pb.GadgetSettings) error {
var usesUSBEthernet bool
//gadget_root := "./test"
@ -576,11 +603,10 @@ func DeployGadgetSettings(settings pb.GadgetSettings) error {
}
}
//clear device path for HID devices
HidDevPath[USB_FUNCTION_HID_KEYBOARD_name] = ""
HidDevPath[USB_FUNCTION_HID_MOUSE_name] = ""
HidDevPath[USB_FUNCTION_HID_RAW_name] = ""
ServiceState.HidDevPath[USB_FUNCTION_HID_KEYBOARD_name] = ""
ServiceState.HidDevPath[USB_FUNCTION_HID_MOUSE_name] = ""
ServiceState.HidDevPath[USB_FUNCTION_HID_RAW_name] = ""
//get UDC driver name and bind to gadget
if settings.Enabled {
@ -594,25 +620,25 @@ func DeployGadgetSettings(settings pb.GadgetSettings) error {
}
//update device path'
if devPath,errF := enumDevicePath(USB_FUNCTION_HID_KEYBOARD_name); errF == nil { HidDevPath[USB_FUNCTION_HID_KEYBOARD_name] = devPath }
if devPath,errF := enumDevicePath(USB_FUNCTION_HID_MOUSE_name); errF == nil { HidDevPath[USB_FUNCTION_HID_MOUSE_name] = devPath }
if devPath,errF := enumDevicePath(USB_FUNCTION_HID_RAW_name); errF == nil { HidDevPath[USB_FUNCTION_HID_RAW_name] = devPath }
if devPath,errF := enumDevicePath(USB_FUNCTION_HID_KEYBOARD_name); errF == nil { ServiceState.HidDevPath[USB_FUNCTION_HID_KEYBOARD_name] = devPath }
if devPath,errF := enumDevicePath(USB_FUNCTION_HID_MOUSE_name); errF == nil { ServiceState.HidDevPath[USB_FUNCTION_HID_MOUSE_name] = devPath }
if devPath,errF := enumDevicePath(USB_FUNCTION_HID_RAW_name); errF == nil { ServiceState.HidDevPath[USB_FUNCTION_HID_RAW_name] = devPath }
//if Keyboard or Mouse are deployed, grab a HIDController Instance else set it to nil (the old HIDController object won't be destroyed)
if settings.Use_HID_KEYBOARD || settings.Use_HID_MOUSE {
devPathKeyboard := HidDevPath[USB_FUNCTION_HID_KEYBOARD_name]
devPathMouse := HidDevPath[USB_FUNCTION_HID_MOUSE_name]
devPathKeyboard := ServiceState.HidDevPath[USB_FUNCTION_HID_KEYBOARD_name]
devPathMouse := ServiceState.HidDevPath[USB_FUNCTION_HID_MOUSE_name]
var errH error
HidCtl, errH = hid.NewHIDController(context.Background(), devPathKeyboard, USB_KEYBOARD_LANGUAGE_MAP_PATH, devPathMouse)
gm.HidCtl, errH = hid.NewHIDController(context.Background(), devPathKeyboard, USB_KEYBOARD_LANGUAGE_MAP_PATH, devPathMouse)
if errH != nil {
log.Printf("ERROR: Couldn't bring up an instance of HIDController for keyboard: '%s', mouse: '%s' and mapping path '%s'\nReason: %v\n", devPathKeyboard, devPathMouse, USB_KEYBOARD_LANGUAGE_MAP_PATH, errH)
} else {
log.Printf("HIDController for keyboard: '%s', mouse: '%s' and mapping path '%s' initialized\n", devPathKeyboard, devPathMouse, USB_KEYBOARD_LANGUAGE_MAP_PATH)
}
} else {
if HidCtl != nil { HidCtl.Abort() }
HidCtl = nil
if gm.HidCtl != nil { gm.HidCtl.Abort() }
gm.HidCtl = nil
log.Printf("HIDController for keyboard / mouse disabled\n")
}
}
@ -667,7 +693,7 @@ func enumDevicePath(funcName string) (devPath string, err error){
return
}
func DestroyAllGadgets() error {
func (gm *UsbGadgetManager) DestroyAllGadgets() error {
//gadget_root := "./test"
gadget_root := USB_GADGET_DIR_BASE
@ -690,8 +716,8 @@ func DestroyAllGadgets() error {
}
}
if HidCtl != nil { HidCtl.Abort() }
HidCtl = nil
if gm.HidCtl != nil { gm.HidCtl.Abort() }
gm.HidCtl = nil
log.Printf("HIDController for keyboard / mouse disabled\n")
return nil

View File

@ -0,0 +1 @@
package main

View File

@ -1,15 +1,19 @@
package main
import (
"./mvuex"
"github.com/gopherjs/gopherjs/js"
"time"
"context"
pb "../proto/gopherjs"
"./mvuex"
)
const (
maxLogEntries = 500
VUEX_ACTION_DEPLOY_CURRENT_GADGET_SETTINGS = "deployCurrentGadgetSettings"
VUEX_ACTION_UPDATE_GADGET_SETTINGS_FROM_DEPLOYED = "updateCurrentGadgetSettingsFromDeployed"
VUEX_MUTATION_SET_CURRENT_GADGET_SETTINGS_TO = "setCurrentGadgetSettings"
VUEX_MUTATION_SET_CURRENT_HID_SCRIPT_SOURCE_TO = "setCurrentHIDScriptSource"
initHIDScript = `layout('us'); // US keyboard layout
typingSpeed(100,150) // Wait 100ms between key strokes + an additional random value between 0ms and 150ms (natural)
@ -42,15 +46,19 @@ type GlobalState struct {
CurrentHIDScriptSource string `js:"currentHIDScriptSource"`
CurrentGadgetSettings *jsGadgetSettings `js:"currentGadgetSettings"`
EventLog *jsLoggerData `js:"eventLog"`
IsModalEnabled bool `js:"isModalEnabled"`
Counter int `js:"count"`
Text string `js:"text"`
}
func UpdateGadgetSettingsFromDeployed(jsGS *jsGadgetSettings) {
/*
func (state *GlobalState) UpdateGadgetSettingsFromDeployed(jsGS *jsGadgetSettings) {
//gs := vue.GetVM(c).Get("gadgetSettings")
println("UpdateGadgetSettingsFromDeployed called")
ctx,cancel := context.WithTimeout(context.Background(), time.Second*3)
defer cancel()
@ -61,20 +69,74 @@ func UpdateGadgetSettingsFromDeployed(jsGS *jsGadgetSettings) {
jsGS.fromGS(deployedGs)
return
}
*/
func createGlobalStateStruct() GlobalState {
state := GlobalState{Object:O()}
state.Title = "P4wnP1 by MaMe82"
state.CurrentHIDScriptSource = initHIDScript
state.CurrentGadgetSettings = NewUSBGadgetSettings()
UpdateGadgetSettingsFromDeployed(state.CurrentGadgetSettings)
//UpdateGadgetSettingsFromDeployed(state.CurrentGadgetSettings)
state.EventLog = NewLogger(maxLogEntries)
state.IsModalEnabled = true
state.Counter = 1337
state.Text = "Hi there says MaMe82"
return state
}
func actionUpdateGadgetSettingsFromDeployed(store *mvuex.Store, context *mvuex.ActionContext, state *GlobalState) {
go func() {
//fetch deployed gadget settings
dGS,err := RpcGetDeployedGadgetSettings(time.Second * 3)
if err != nil {
println("Couldn't retrieve deployed gadget settings")
return
}
//convert to JS version
jsGS := &jsGadgetSettings{Object:O()}
jsGS.fromGS(dGS)
//commit to current
context.Commit("setCurrentGadgetSettings", jsGS)
}()
return
}
func actionDeployCurrentGadgetSettings(store *mvuex.Store, context *mvuex.ActionContext, state *GlobalState) {
go func() {
// ToDo: Indicate deployment process via global state
//get current GadgetSettings
curGS := state.CurrentGadgetSettings.toGS()
//try to set them via gRPC (the server holds an internal state, setting != deploying)
err := RpcSetRemoteGadgetSettings(curGS, time.Second)
if err != nil {
//ToDo: use global store to return something, or allow actions to return promises (latter is too much JavaScript)
Alert(err)
return
}
//try to deploy the, now set, remote GadgetSettings via gRPC
_,err = RpcDeployRemoteGadgetSettings(time.Second*10)
if err != nil {
//ToDo: use global store to return something, or allow actions to return promises (latter is too much JavaScript)
Alert(err)
return
}
//ToDo: If we're here, we succeeded and should indicate this via global state
Alert("GadgetSettings deployed successfully")
}()
return
}
func initMVuex() {
state := createGlobalStateStruct()
store := mvuex.NewStore(
@ -90,6 +152,10 @@ func initMVuex() {
}()
}),
mvuex.Mutation("setModalEnabled", func (store *mvuex.Store, state *GlobalState, enabled bool) {
state.IsModalEnabled = enabled
return
}),
mvuex.Mutation("increment", func (store *mvuex.Store, state *GlobalState, add int) {
state.Counter += add
return
@ -102,18 +168,12 @@ func initMVuex() {
state.Text = newText
return
}),
mvuex.Mutation("setCurrentHIDScriptSource", func (store *mvuex.Store, state *GlobalState, newText string) {
mvuex.Mutation(VUEX_MUTATION_SET_CURRENT_HID_SCRIPT_SOURCE_TO, func (store *mvuex.Store, state *GlobalState, newText string) {
state.CurrentHIDScriptSource = newText
return
}),
mvuex.Mutation("setCurrentGadgetSettings", func (store *mvuex.Store, state *GlobalState, newSettings *jsGadgetSettings) {
state.CurrentGadgetSettings = newSettings
return
}),
mvuex.Mutation("setCurrentGadgetSettingsFromDeployed", func (store *mvuex.Store, state *GlobalState) {
//ToDo: check if this is valid for synchronous run, has to be dispatched to action otherwise
println("Store: commit setCurrentGadgetSettingsFromDeployed")
go UpdateGadgetSettingsFromDeployed(state.CurrentGadgetSettings)
mvuex.Mutation(VUEX_MUTATION_SET_CURRENT_GADGET_SETTINGS_TO, func (store *mvuex.Store, state *GlobalState, settings *jsGadgetSettings) {
state.CurrentGadgetSettings = settings
return
}),
mvuex.Mutation("startLogListening", func (store *mvuex.Store, state *GlobalState) {
@ -124,8 +184,12 @@ func initMVuex() {
state.EventLog.StopListening()
return
}),
mvuex.Action(VUEX_ACTION_UPDATE_GADGET_SETTINGS_FROM_DEPLOYED, actionUpdateGadgetSettingsFromDeployed),
mvuex.Action(VUEX_ACTION_DEPLOY_CURRENT_GADGET_SETTINGS, actionDeployCurrentGadgetSettings),
)
// fetch deployed gadget settings
store.Dispatch("updateCurrentGadgetSettingsFromDeployed")
// propagate Vuex store to global scope to allow injecting it to Vue by setting the "store" option
js.Global.Set("store", store)