project structure refactoring
This commit is contained in:
64
hid/hid.go
Normal file
64
hid/hid.go
Normal file
@@ -0,0 +1,64 @@
|
||||
package hid
|
||||
|
||||
import (
|
||||
"os"
|
||||
"sync"
|
||||
)
|
||||
|
||||
const (
|
||||
MouseUp = iota
|
||||
MouseDown
|
||||
MouseMoveAbsolute
|
||||
MouseMoveRelative
|
||||
MouseScroll
|
||||
)
|
||||
|
||||
const (
|
||||
MouseLeft = 1
|
||||
MouseRight = 2
|
||||
MouseWheel = 3
|
||||
)
|
||||
|
||||
const (
|
||||
HidMouseLeft byte = 0x01
|
||||
HidMouseRight byte = 0x02
|
||||
HidMouseWheel byte = 0x04
|
||||
)
|
||||
|
||||
const (
|
||||
ModifierLCtrl byte = 0x01
|
||||
ModifierLShift byte = 0x02
|
||||
ModifierLAlt byte = 0x04
|
||||
ModifierLGUI byte = 0x08
|
||||
ModifierRAlt byte = 0x40
|
||||
)
|
||||
|
||||
var (
|
||||
hid *Hid
|
||||
hidOnce sync.Once
|
||||
)
|
||||
|
||||
type Hid struct {
|
||||
g0 *os.File
|
||||
g1 *os.File
|
||||
g2 *os.File
|
||||
kbMutex sync.Mutex
|
||||
mouseMutex sync.Mutex
|
||||
}
|
||||
|
||||
func (h *Hid) Lock() {
|
||||
h.kbMutex.Lock()
|
||||
h.mouseMutex.Lock()
|
||||
}
|
||||
|
||||
func (h *Hid) Unlock() {
|
||||
h.kbMutex.Unlock()
|
||||
h.mouseMutex.Unlock()
|
||||
}
|
||||
|
||||
func GetHid() *Hid {
|
||||
hidOnce.Do(func() {
|
||||
hid = &Hid{}
|
||||
})
|
||||
return hid
|
||||
}
|
||||
47
hid/keyboard.go
Normal file
47
hid/keyboard.go
Normal file
@@ -0,0 +1,47 @@
|
||||
package hid
|
||||
|
||||
func (h *Hid) Keyboard(queue <-chan []int) {
|
||||
for event := range queue {
|
||||
h.kbMutex.Lock()
|
||||
h.writeKeyboard(event)
|
||||
h.kbMutex.Unlock()
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Hid) writeKeyboard(event []int) {
|
||||
var data []byte
|
||||
|
||||
if event[0] > 0 {
|
||||
code := byte(event[0])
|
||||
modifier := getModifier(event)
|
||||
data = []byte{modifier, 0x00, code, 0x00, 0x00, 0x00, 0x00, 0x00}
|
||||
} else {
|
||||
data = []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
|
||||
}
|
||||
|
||||
h.Write(h.g0, data)
|
||||
}
|
||||
|
||||
func getModifier(event []int) byte {
|
||||
var modifier byte = 0x00
|
||||
|
||||
if event[1] == 1 {
|
||||
modifier |= ModifierLCtrl
|
||||
}
|
||||
|
||||
if event[2] == 1 {
|
||||
modifier |= ModifierLShift
|
||||
}
|
||||
|
||||
if event[3] == 1 {
|
||||
modifier |= ModifierLAlt
|
||||
} else if event[3] == 2 {
|
||||
modifier |= ModifierRAlt
|
||||
}
|
||||
|
||||
if event[4] == 1 {
|
||||
modifier |= ModifierLGUI
|
||||
}
|
||||
|
||||
return modifier
|
||||
}
|
||||
102
hid/mouse.go
Normal file
102
hid/mouse.go
Normal file
@@ -0,0 +1,102 @@
|
||||
package hid
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func (h *Hid) Mouse(queue <-chan []int) {
|
||||
for event := range queue {
|
||||
h.mouseMutex.Lock()
|
||||
switch event[0] {
|
||||
case MouseDown:
|
||||
h.mouseDown(event)
|
||||
case MouseUp:
|
||||
h.mouseUp()
|
||||
case MouseMoveAbsolute:
|
||||
h.mouseMoveAbsolute(event)
|
||||
case MouseMoveRelative:
|
||||
h.mouseMoveRelative(event)
|
||||
case MouseScroll:
|
||||
h.scroll(event)
|
||||
default:
|
||||
log.Debugf("invalid mouse event: %+v", event)
|
||||
}
|
||||
h.mouseMutex.Unlock()
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Hid) mouseDown(event []int) {
|
||||
var button byte
|
||||
|
||||
switch event[1] {
|
||||
case MouseLeft:
|
||||
button = HidMouseLeft
|
||||
case MouseRight:
|
||||
button = HidMouseRight
|
||||
case MouseWheel:
|
||||
button = HidMouseWheel
|
||||
default:
|
||||
log.Debugf("invalid mouse button: %+v", event)
|
||||
return
|
||||
}
|
||||
|
||||
data := []byte{button, 0, 0, 0}
|
||||
h.writeWithTimeout(h.g1, data)
|
||||
}
|
||||
|
||||
func (h *Hid) mouseUp() {
|
||||
data := []byte{0, 0, 0, 0}
|
||||
h.writeWithTimeout(h.g1, data)
|
||||
}
|
||||
|
||||
func (h *Hid) scroll(event []int) {
|
||||
direction := 0x01
|
||||
if event[3] > 0 {
|
||||
direction = -0x1
|
||||
}
|
||||
|
||||
data := []byte{0, 0, 0, byte(direction)}
|
||||
h.writeWithTimeout(h.g1, data)
|
||||
}
|
||||
|
||||
func (h *Hid) mouseMoveAbsolute(event []int) {
|
||||
x := make([]byte, 2)
|
||||
y := make([]byte, 2)
|
||||
binary.LittleEndian.PutUint16(x, uint16(event[2]))
|
||||
binary.LittleEndian.PutUint16(y, uint16(event[3]))
|
||||
|
||||
data := []byte{0, x[0], x[1], y[0], y[1], 0}
|
||||
h.writeWithTimeout(h.g2, data)
|
||||
}
|
||||
|
||||
func (h *Hid) mouseMoveRelative(event []int) {
|
||||
data := []byte{byte(event[1]), byte(event[2]), byte(event[3]), 0}
|
||||
h.writeWithTimeout(h.g1, data)
|
||||
}
|
||||
|
||||
func (h *Hid) writeWithTimeout(file *os.File, data []byte) {
|
||||
deadline := time.Now().Add(8 * time.Millisecond)
|
||||
_ = file.SetWriteDeadline(deadline)
|
||||
|
||||
_, err := file.Write(data)
|
||||
if err != nil {
|
||||
switch {
|
||||
case errors.Is(err, os.ErrClosed):
|
||||
log.Tracef("hid already closed, reopen it...")
|
||||
h.OpenNoLock()
|
||||
case errors.Is(err, os.ErrDeadlineExceeded):
|
||||
log.Tracef("write to hid timeout")
|
||||
default:
|
||||
log.Errorf("write to hid failed: %s", err)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
log.Tracef("write to hid: %+v", data)
|
||||
}
|
||||
75
hid/op.go
Normal file
75
hid/op.go
Normal file
@@ -0,0 +1,75 @@
|
||||
package hid
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func (h *Hid) OpenNoLock() {
|
||||
log.Debug("OpenNoLock hid")
|
||||
var err error
|
||||
h.CloseNoLock()
|
||||
|
||||
h.g0, err = os.OpenFile("/dev/hidg0", os.O_WRONLY, 0o666)
|
||||
if err != nil {
|
||||
log.Errorf("open /dev/hidg0 failed: %s", err)
|
||||
}
|
||||
|
||||
h.g1, err = os.OpenFile("/dev/hidg1", os.O_WRONLY, 0o666)
|
||||
if err != nil {
|
||||
log.Errorf("open /dev/hidg1 failed: %s", err)
|
||||
}
|
||||
|
||||
h.g2, err = os.OpenFile("/dev/hidg2", os.O_WRONLY, 0o666)
|
||||
if err != nil {
|
||||
log.Errorf("open /dev/hidg2 failed: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Hid) Open() {
|
||||
h.kbMutex.Lock()
|
||||
defer h.kbMutex.Unlock()
|
||||
h.mouseMutex.Lock()
|
||||
defer h.mouseMutex.Unlock()
|
||||
|
||||
h.CloseNoLock()
|
||||
|
||||
h.OpenNoLock()
|
||||
}
|
||||
|
||||
func (h *Hid) CloseNoLock() {
|
||||
log.Debug("CloseNoLock")
|
||||
for _, file := range []*os.File{h.g0, h.g1, h.g2} {
|
||||
if file != nil {
|
||||
_ = file.Sync()
|
||||
_ = file.Close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Hid) Close() {
|
||||
h.kbMutex.Lock()
|
||||
defer h.kbMutex.Unlock()
|
||||
h.mouseMutex.Lock()
|
||||
defer h.mouseMutex.Unlock()
|
||||
|
||||
h.CloseNoLock()
|
||||
}
|
||||
|
||||
func (h *Hid) Write(file *os.File, data []byte) {
|
||||
_, err := file.Write(data)
|
||||
if err != nil {
|
||||
if errors.Is(err, os.ErrClosed) {
|
||||
log.Debugf("hid already closed, reopen it...")
|
||||
h.OpenNoLock()
|
||||
} else {
|
||||
log.Errorf("write to hid failed: %s", err)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
log.Tracef("write to hid: %+v", data)
|
||||
}
|
||||
Reference in New Issue
Block a user