mirror of
https://github.com/RoganDawes/P4wnP1_aloa.git
synced 2025-03-17 21:31:56 +01:00
190 lines
4.3 KiB
Go
190 lines
4.3 KiB
Go
// +build arm
|
|
|
|
package service
|
|
|
|
import (
|
|
"fmt"
|
|
"errors"
|
|
"github.com/mame82/P4wnP1_aloa/common_web"
|
|
|
|
genl "github.com/mame82/P4wnP1_aloa/mgenetlink"
|
|
nl "github.com/mame82/P4wnP1_aloa/mnetlink"
|
|
)
|
|
|
|
/*
|
|
Needs modified dwc2 kernel module, sending multicast generic netlink messages for genl family 'p4wnp1' on multicast group 'dwc2'
|
|
|
|
*/
|
|
|
|
const (
|
|
fam_name = "p4wnp1"
|
|
dwc2_group_name = "dwc2"
|
|
|
|
// commands
|
|
dwc2_cmd_connection_state = uint8(0)
|
|
|
|
// attributes
|
|
dwc2_attr_connection_dummy = uint16(0)
|
|
dwc2_attr_connection_state = uint16(1)
|
|
|
|
)
|
|
|
|
var (
|
|
EP4wnP1FamilyMissing = errors.New("Couldn't find generic netlink family for P4wnP1")
|
|
EDwc2GrpMissing = errors.New("Couldn't find generic netlink mcast group for P4wnP1 dwc2")
|
|
EDwc2GrpJoin = errors.New("Couldn't join generic netlink mcast group for P4wnP1 dwc2")
|
|
EWrongFamily = errors.New("Message not from generic netlink family P4wnP1")
|
|
)
|
|
|
|
|
|
type Dwc2ConnectWatcher struct {
|
|
rootSvc *Service
|
|
|
|
genl *genl.Client
|
|
fam *genl.Family
|
|
|
|
|
|
isRunning bool
|
|
connected bool
|
|
firstUpdateDone bool
|
|
}
|
|
|
|
|
|
func (d * Dwc2ConnectWatcher) update(newStateConnected bool) {
|
|
d.connected = newStateConnected
|
|
|
|
// --> here a event could be triggered (in case the event manager is registered)
|
|
if d.connected {
|
|
fmt.Println("Connected to USB host")
|
|
d.rootSvc.SubSysEvent.Emit(ConstructEventTrigger(common_web.TRIGGER_EVT_TYPE_USB_GADGET_CONNECTED))
|
|
//d.rootSvc.SubSysEvent.Emit(ConstructEventLog("USB watcher", 1, "Connected to USB host"))
|
|
|
|
} else {
|
|
fmt.Println("Disconnected from USB host")
|
|
d.rootSvc.SubSysEvent.Emit(ConstructEventTrigger(common_web.TRIGGER_EVT_TYPE_USB_GADGET_DISCONNECTED))
|
|
//d.rootSvc.SubSysEvent.Emit(ConstructEventLog("USB watcher", 1, "Disconnected from USB host"))
|
|
}
|
|
}
|
|
|
|
func (d * Dwc2ConnectWatcher) parseMsg(msg nl.Message) (cmd genl.Message, err error) {
|
|
if msg.Type != d.fam.ID {
|
|
// Multicast message from different familiy, ignore
|
|
err = EWrongFamily
|
|
return
|
|
}
|
|
|
|
err = cmd.UnmarshalBinary(msg.GetData())
|
|
if err != nil { return }
|
|
return
|
|
}
|
|
|
|
|
|
func (d * Dwc2ConnectWatcher) evt_loop() {
|
|
d.isRunning = true
|
|
// ToDo, make loop stoppable by non-blocking/interruptable socket read a.k.a select with timeout
|
|
for d.isRunning {
|
|
fmt.Println("\nWaiting for messages from P4wnP1 kernel mods...\n")
|
|
msgs,errm := d.genl.Receive()
|
|
if errm == nil {
|
|
for _,msg := range msgs {
|
|
if cmd,errp := d.parseMsg(msg); errp == nil {
|
|
switch cmd.Cmd {
|
|
case dwc2_cmd_connection_state:
|
|
fmt.Println("COMMAND_CONNECTION_STATE")
|
|
params,perr := cmd.AttributesFromData()
|
|
if perr != nil {
|
|
fmt.Println("Couldn't parse params for COMMAND_CONNECTION_STATE")
|
|
continue
|
|
}
|
|
// find
|
|
for _,param := range params {
|
|
if param.Type == dwc2_attr_connection_state {
|
|
fmt.Println("Connection State: ", param.GetDataUint8())
|
|
switch param.GetDataUint8() {
|
|
case 0: //disconnected
|
|
d.update(false)
|
|
case 1: //connected
|
|
d.update(true)
|
|
}
|
|
}
|
|
}
|
|
default:
|
|
fmt.Printf("Unknown command:\n%+v\n", cmd)
|
|
}
|
|
} else {
|
|
fmt.Printf("Message ignored:\n%+v\n", msg)
|
|
continue
|
|
}
|
|
|
|
}
|
|
} else {
|
|
fmt.Println("Receive error: ", errm)
|
|
}
|
|
}
|
|
|
|
fmt.Println("GenNl rcv loop ended")
|
|
|
|
|
|
}
|
|
|
|
func (d * Dwc2ConnectWatcher) IsConnected() bool {
|
|
return d.connected
|
|
}
|
|
|
|
|
|
func (d * Dwc2ConnectWatcher) Start() (err error){
|
|
d.genl,err = genl.NewGeNl() //genl client
|
|
if err != nil { return err }
|
|
|
|
err = d.genl.Open() //Connect to generic netlink
|
|
if err != nil { return }
|
|
|
|
// try to find GENL family for P4wnP1
|
|
d.fam,err = d.genl.GetFamily(fam_name)
|
|
if err != nil {
|
|
d.genl.Close()
|
|
return EP4wnP1FamilyMissing
|
|
}
|
|
|
|
// try to join group for dwc2
|
|
grpId,err := d.fam.GetGroupByName(dwc2_group_name)
|
|
if err != nil {
|
|
d.genl.Close()
|
|
return EDwc2GrpMissing
|
|
}
|
|
err = d.genl.AddGroupMembership(grpId)
|
|
if err != nil {
|
|
d.genl.Close()
|
|
return EDwc2GrpMissing
|
|
}
|
|
|
|
|
|
|
|
|
|
d.isRunning = true
|
|
go d.evt_loop()
|
|
|
|
return nil
|
|
}
|
|
|
|
func (d * Dwc2ConnectWatcher) Stop() error {
|
|
d.isRunning = false
|
|
|
|
// leave dwc2 group
|
|
if grpId,err := d.fam.GetGroupByName(dwc2_group_name); err == nil {
|
|
d.genl.DropGroupMembership(grpId)
|
|
}
|
|
// close soket
|
|
return d.genl.Close()
|
|
|
|
}
|
|
|
|
func NewDwc2ConnectWatcher(rootSvc *Service) (d *Dwc2ConnectWatcher) {
|
|
|
|
d = &Dwc2ConnectWatcher{
|
|
rootSvc: rootSvc,
|
|
}
|
|
return d
|
|
}
|
|
|