From fd96ce3403f0bf98c215152e0d8424673c9db7e6 Mon Sep 17 00:00:00 2001 From: Dmitrii Morozov Date: Wed, 27 Mar 2024 20:38:37 +0100 Subject: Refactoring --- Makefile | 10 ++ cmd/magic4linux/main.go | 188 --------------------------------- input/keycodes.go | 273 ++++++++++++++++++++++++++++++++++++++++++++++++ input/wrapper-empty.go | 49 +++++++++ input/wrapper-uinput.go | 74 +++++++++++++ input/wrapper.go | 49 +++++++++ main.go | 192 ++++++++++++++++++++++++++++++++++ 7 files changed, 647 insertions(+), 188 deletions(-) create mode 100644 Makefile delete mode 100644 cmd/magic4linux/main.go create mode 100644 input/keycodes.go create mode 100644 input/wrapper-empty.go create mode 100644 input/wrapper-uinput.go create mode 100644 input/wrapper.go create mode 100644 main.go diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..b2f9952 --- /dev/null +++ b/Makefile @@ -0,0 +1,10 @@ +BINARY_NAME:=magic4linux + +build: + GOOS=linux go build -o ${BINARY_NAME} main.go + +run: build + ./${BINARY_NAME} + +clean: + go clean \ No newline at end of file diff --git a/cmd/magic4linux/main.go b/cmd/magic4linux/main.go deleted file mode 100644 index fa98371..0000000 --- a/cmd/magic4linux/main.go +++ /dev/null @@ -1,188 +0,0 @@ -package main - -import ( - "bytes" - "context" - "encoding/binary" - "fmt" - "log" - "os" - "os/signal" - "syscall" - - "github.com/bendahl/uinput" - - "github.com/mafredri/magic4linux/m4p" -) - -const ( - broadcastPort = 42830 - subscriptionPort = 42831 -) - -func main() { - ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) - defer cancel() - - if err := run(ctx); err != nil { - panic(err) - } -} - -func run(ctx context.Context) error { - kbd, err := uinput.CreateKeyboard("/dev/uinput", []byte("magic4linux-keyboard")) - if err != nil { - return err - } - defer kbd.Close() - - mouse, err := uinput.CreateMouse("/dev/uinput", []byte("magic4linux-mouse")) - if err != nil { - return err - } - defer mouse.Close() - - tp, err := uinput.CreateTouchPad("/dev/uinput", []byte("magic4linux-touchpad"), 0, 1920, 0, 1080) - if err != nil { - return err - } - defer tp.Close() - - d, err := m4p.NewDiscoverer(broadcastPort) - if err != nil { - return err - } - defer d.Close() - - for { - select { - case <-ctx.Done(): - return nil - - case dev := <-d.NextDevice(): - err = connect(ctx, dev, kbd, mouse, tp) - if err != nil { - log.Printf("connect: %v", err) - } - } - } -} - -func connect(ctx context.Context, dev m4p.DeviceInfo, kbd uinput.Keyboard, mouse uinput.Mouse, tp uinput.TouchPad) error { - addr := fmt.Sprintf("%s:%d", dev.IPAddr, dev.Port) - log.Printf("connect: connecting to: %s", addr) - - client, err := m4p.Dial(ctx, addr) - if err != nil { - return err - } - defer client.Close() - - for { - m, err := client.Recv(ctx) - if err != nil { - return err - } - - switch m.Type { - case m4p.InputMessage: - log.Printf("connect: got %s: %v", m.Type, m.Input) - - // PoC Kodi keyboard mapping. - key := m.Input.Parameters.KeyCode - switch key { - case m4p.KeyWheelPressed: - key = uinput.KeyEnter - case m4p.KeyChannelUp: - key = uinput.KeyPageup - case m4p.KeyChannelDown: - key = uinput.KeyPagedown - case m4p.KeyLeft: - key = uinput.KeyLeft - case m4p.KeyUp: - key = uinput.KeyUp - case m4p.KeyRight: - key = uinput.KeyRight - case m4p.KeyDown: - key = uinput.KeyDown - case m4p.Key0: - key = uinput.Key0 - case m4p.Key1: - key = uinput.Key1 - case m4p.Key2: - key = uinput.Key2 - case m4p.Key3: - key = uinput.Key3 - case m4p.Key4: - key = uinput.Key4 - case m4p.Key5: - key = uinput.Key5 - case m4p.Key6: - key = uinput.Key6 - case m4p.Key7: - key = uinput.Key7 - case m4p.Key8: - key = uinput.Key8 - case m4p.Key9: - key = uinput.Key9 - case m4p.KeyRed: - key = uinput.KeyStop - case m4p.KeyGreen: - key = uinput.KeyPlaypause - case m4p.KeyYellow: - key = uinput.KeyZ - case m4p.KeyBlue: - key = uinput.KeyC - case m4p.KeyBack: - key = uinput.KeyBackspace - } - - if m.Input.Parameters.IsDown { - kbd.KeyDown(key) - } else { - kbd.KeyUp(key) - } - case m4p.RemoteUpdateMessage: - // log.Printf("connect: got %s: %s", m.Type, hex.EncodeToString(m.RemoteUpdate.Payload)) - - r := bytes.NewReader(m.RemoteUpdate.Payload) - var returnValue, deviceID uint8 - var coordinate [2]int32 - var gyroscope, acceleration [3]float32 - var quaternion [4]float32 - for _, fn := range []func() error{ - func() error { return binary.Read(r, binary.LittleEndian, &returnValue) }, - func() error { return binary.Read(r, binary.LittleEndian, &deviceID) }, - func() error { return binary.Read(r, binary.LittleEndian, coordinate[:]) }, - func() error { return binary.Read(r, binary.LittleEndian, gyroscope[:]) }, - func() error { return binary.Read(r, binary.LittleEndian, acceleration[:]) }, - func() error { return binary.Read(r, binary.LittleEndian, quaternion[:]) }, - } { - if err := fn(); err != nil { - log.Printf("connect: %s decode failed: %v", m.Type, err) - break - } - } - - x := coordinate[0] - y := coordinate[1] - // fmt.Println("Move mouse", x, y) - tp.MoveTo(x, y) - - // log.Printf("connect: %d %d %#v %#v %#v %#v", returnValue, deviceID, coordinate, gyroscope, acceleration, quaternion) - - case m4p.MouseMessage: - switch m.Mouse.Type { - case "mousedown": - tp.LeftPress() - case "mouseup": - tp.LeftRelease() - } - - case m4p.WheelMessage: - mouse.Wheel(false, m.Wheel.Delta) - - default: - } - } -} diff --git a/input/keycodes.go b/input/keycodes.go new file mode 100644 index 0000000..ede83c8 --- /dev/null +++ b/input/keycodes.go @@ -0,0 +1,273 @@ +package input + +// Inherited from uinput +const ( + keyReserved = 0 + KeyEsc = 1 + Key1 = 2 + Key2 = 3 + Key3 = 4 + Key4 = 5 + Key5 = 6 + Key6 = 7 + Key7 = 8 + Key8 = 9 + Key9 = 10 + Key0 = 11 + KeyMinus = 12 + KeyEqual = 13 + KeyBackspace = 14 + KeyTab = 15 + KeyQ = 16 + KeyW = 17 + KeyE = 18 + KeyR = 19 + KeyT = 20 + KeyY = 21 + KeyU = 22 + KeyI = 23 + KeyO = 24 + KeyP = 25 + KeyLeftbrace = 26 + KeyRightbrace = 27 + KeyEnter = 28 + KeyLeftctrl = 29 + KeyA = 30 + KeyS = 31 + KeyD = 32 + KeyF = 33 + KeyG = 34 + KeyH = 35 + KeyJ = 36 + KeyK = 37 + KeyL = 38 + KeySemicolon = 39 + KeyApostrophe = 40 + KeyGrave = 41 + KeyLeftshift = 42 + KeyBackslash = 43 + KeyZ = 44 + KeyX = 45 + KeyC = 46 + KeyV = 47 + KeyB = 48 + KeyN = 49 + KeyM = 50 + KeyComma = 51 + KeyDot = 52 + KeySlash = 53 + KeyRightshift = 54 + KeyKpasterisk = 55 + KeyLeftalt = 56 + KeySpace = 57 + KeyCapslock = 58 + KeyF1 = 59 + KeyF2 = 60 + KeyF3 = 61 + KeyF4 = 62 + KeyF5 = 63 + KeyF6 = 64 + KeyF7 = 65 + KeyF8 = 66 + KeyF9 = 67 + KeyF10 = 68 + KeyNumlock = 69 + KeyScrolllock = 70 + KeyKp7 = 71 + KeyKp8 = 72 + KeyKp9 = 73 + KeyKpminus = 74 + KeyKp4 = 75 + KeyKp5 = 76 + KeyKp6 = 77 + KeyKpplus = 78 + KeyKp1 = 79 + KeyKp2 = 80 + KeyKp3 = 81 + KeyKp0 = 82 + KeyKpdot = 83 + KeyZenkakuhankaku = 85 + Key102Nd = 86 + KeyF11 = 87 + KeyF12 = 88 + KeyRo = 89 + KeyKatakana = 90 + KeyHiragana = 91 + KeyHenkan = 92 + KeyKatakanahiragana = 93 + KeyMuhenkan = 94 + KeyKpjpcomma = 95 + KeyKpenter = 96 + KeyRightctrl = 97 + KeyKpslash = 98 + KeySysrq = 99 + KeyRightalt = 100 + KeyLinefeed = 101 + KeyHome = 102 + KeyUp = 103 + KeyPageup = 104 + KeyLeft = 105 + KeyRight = 106 + KeyEnd = 107 + KeyDown = 108 + KeyPagedown = 109 + KeyInsert = 110 + KeyDelete = 111 + KeyMacro = 112 + KeyMute = 113 + KeyVolumedown = 114 + KeyVolumeup = 115 + KeyPower = 116 /*ScSystemPowerDown*/ + KeyKpequal = 117 + KeyKpplusminus = 118 + KeyPause = 119 + KeyScale = 120 /*AlCompizScale(Expose)*/ + KeyKpcomma = 121 + KeyHangeul = 122 + KeyHanja = 123 + KeyYen = 124 + KeyLeftmeta = 125 + KeyRightmeta = 126 + KeyCompose = 127 + KeyStop = 128 /*AcStop*/ + KeyAgain = 129 + KeyProps = 130 /*AcProperties*/ + KeyUndo = 131 /*AcUndo*/ + KeyFront = 132 + KeyCopy = 133 /*AcCopy*/ + KeyOpen = 134 /*AcOpen*/ + KeyPaste = 135 /*AcPaste*/ + KeyFind = 136 /*AcSearch*/ + KeyCut = 137 /*AcCut*/ + KeyHelp = 138 /*AlIntegratedHelpCenter*/ + KeyMenu = 139 /*Menu(ShowMenu)*/ + KeyCalc = 140 /*AlCalculator*/ + KeySetup = 141 + KeySleep = 142 /*ScSystemSleep*/ + KeyWakeup = 143 /*SystemWakeUp*/ + KeyFile = 144 /*AlLocalMachineBrowser*/ + KeySendfile = 145 + KeyDeletefile = 146 + KeyXfer = 147 + KeyProg1 = 148 + KeyProg2 = 149 + KeyWww = 150 /*AlInternetBrowser*/ + KeyMsdos = 151 + KeyCoffee = 152 /*AlTerminalLock/Screensaver*/ + KeyDirection = 153 + KeyCyclewindows = 154 + KeyMail = 155 + KeyBookmarks = 156 /*AcBookmarks*/ + KeyComputer = 157 + KeyBack = 158 /*AcBack*/ + KeyForward = 159 /*AcForward*/ + KeyClosecd = 160 + KeyEjectcd = 161 + KeyEjectclosecd = 162 + KeyNextsong = 163 + KeyPlaypause = 164 + KeyPrevioussong = 165 + KeyStopcd = 166 + KeyRecord = 167 + KeyRewind = 168 + KeyPhone = 169 /*MediaSelectTelephone*/ + KeyIso = 170 + KeyConfig = 171 /*AlConsumerControlConfiguration*/ + KeyHomepage = 172 /*AcHome*/ + KeyRefresh = 173 /*AcRefresh*/ + KeyExit = 174 /*AcExit*/ + KeyMove = 175 + KeyEdit = 176 + KeyScrollup = 177 + KeyScrolldown = 178 + KeyKpleftparen = 179 + KeyKprightparen = 180 + KeyNew = 181 /*AcNew*/ + KeyRedo = 182 /*AcRedo/Repeat*/ + KeyF13 = 183 + KeyF14 = 184 + KeyF15 = 185 + KeyF16 = 186 + KeyF17 = 187 + KeyF18 = 188 + KeyF19 = 189 + KeyF20 = 190 + KeyF21 = 191 + KeyF22 = 192 + KeyF23 = 193 + KeyF24 = 194 + KeyPlaycd = 200 + KeyPausecd = 201 + KeyProg3 = 202 + KeyProg4 = 203 + KeyDashboard = 204 /*AlDashboard*/ + KeySuspend = 205 + KeyClose = 206 /*AcClose*/ + KeyPlay = 207 + KeyFastforward = 208 + KeyBassboost = 209 + KeyPrint = 210 /*AcPrint*/ + KeyHp = 211 + KeyCamera = 212 + KeySound = 213 + KeyQuestion = 214 + KeyEmail = 215 + KeyChat = 216 + KeySearch = 217 + KeyConnect = 218 + KeyFinance = 219 /*AlCheckbook/Finance*/ + KeySport = 220 + KeyShop = 221 + KeyAlterase = 222 + KeyCancel = 223 /*AcCancel*/ + KeyBrightnessdown = 224 + KeyBrightnessup = 225 + KeyMedia = 226 + KeySwitchvideomode = 227 /*CycleBetweenAvailableVideo */ + KeyKbdillumtoggle = 228 + KeyKbdillumdown = 229 + KeyKbdillumup = 230 + KeySend = 231 /*AcSend*/ + KeyReply = 232 /*AcReply*/ + KeyForwardmail = 233 /*AcForwardMsg*/ + KeySave = 234 /*AcSave*/ + KeyDocuments = 235 + KeyBattery = 236 + KeyBluetooth = 237 + KeyWlan = 238 + KeyUwb = 239 + KeyUnknown = 240 + KeyVideoNext = 241 /*DriveNextVideoSource*/ + KeyVideoPrev = 242 /*DrivePreviousVideoSource*/ + KeyBrightnessCycle = 243 /*BrightnessUp,AfterMaxIsMin*/ + KeyBrightnessZero = 244 /*BrightnessOff,UseAmbient*/ + KeyDisplayOff = 245 /*DisplayDeviceToOffState*/ + KeyWimax = 246 + KeyRfkill = 247 /*KeyThatControlsAllRadios*/ + KeyMicmute = 248 /*Mute/UnmuteTheMicrophone*/ + keyMax = 248 // highest key currently defined in this keyboard api + + ButtonGamepad = 0x130 + + ButtonSouth = 0x130 // A / X + ButtonEast = 0x131 // X / Square + ButtonNorth = 0x133 // Y / Triangle + ButtonWest = 0x134 // B / Circle + + ButtonBumperLeft = 0x136 // L1 + ButtonBumperRight = 0x137 // R1 + ButtonTriggerLeft = 0x138 // L2 + ButtonTriggerRight = 0x139 // R2 + ButtonThumbLeft = 0x13d // L3 + ButtonThumbRight = 0x13e // R3 + + ButtonSelect = 0x13a + ButtonStart = 0x13b + + ButtonDpadUp = 0x220 + ButtonDpadDown = 0x221 + ButtonDpadLeft = 0x222 + ButtonDpadRight = 0x223 + + ButtonMode = 0x13c // This is the special button that usually bears the Xbox or Playstation logo +) diff --git a/input/wrapper-empty.go b/input/wrapper-empty.go new file mode 100644 index 0000000..5459a20 --- /dev/null +++ b/input/wrapper-empty.go @@ -0,0 +1,49 @@ +package input + +import ( + "fmt" +) + +type KeyboardEmptyWrapper struct { +} + +type MouseEmptyWrapper struct { +} + +func (mockKeyboard KeyboardEmptyWrapper) KeyDown(key int) error { + fmt.Println("Key down") + return nil +} + +func (mockKeyboard KeyboardEmptyWrapper) KeyUp(key int) error { + fmt.Println("Key up") + return nil +} + +func (mockKeyboard KeyboardEmptyWrapper) Close() error { + return nil +} + +func (mockMouse MouseEmptyWrapper) Move(x, y int32) error { + //fmt.Println("Move") + return nil +} + +func (mockMouse MouseEmptyWrapper) LeftPress() error { + fmt.Println("Left press") + return nil +} + +func (mockMouse MouseEmptyWrapper) LeftRelease() error { + fmt.Println("Left release") + return nil +} + +func (mockMouse MouseEmptyWrapper) Wheel(horizontal bool, delta int32) error { + fmt.Println("Wheel") + return nil +} + +func (mockMouse MouseEmptyWrapper) Close() error { + return nil +} diff --git a/input/wrapper-uinput.go b/input/wrapper-uinput.go new file mode 100644 index 0000000..26877f2 --- /dev/null +++ b/input/wrapper-uinput.go @@ -0,0 +1,74 @@ +package input + +import ( + "fmt" + + "github.com/bendahl/uinput" +) + +type KeyboardUinputWrapper struct { + keyboard uinput.Keyboard +} + +type MouseUinputWrapper struct { + mouse uinput.Mouse + touchpad uinput.TouchPad +} + +func (uinputKeyboard *KeyboardUinputWrapper) Init() error { + kbd, err := uinput.CreateKeyboard("/dev/uinput", []byte("magic4linux-keyboard")) + if err != nil { + panic(err) + } + uinputKeyboard.keyboard = kbd + return nil +} + +func (uinputMouse *MouseUinputWrapper) Init() error { + mouse, err := uinput.CreateMouse("/dev/uinput", []byte("magic4linux-mouse")) + if err != nil { + panic(err) + } + uinputMouse.mouse = mouse + + // TODO resolution + tp, err := uinput.CreateTouchPad("/dev/uinput", []byte("magic4linux-touchpad"), 0, 1920, 0, 1080) + if err != nil { + panic(err) + } + uinputMouse.touchpad = tp + return nil +} + +func (uinputKeyboard KeyboardUinputWrapper) KeyDown(key int) error { + return uinputKeyboard.keyboard.KeyDown(key) +} + +func (uinputKeyboard KeyboardUinputWrapper) KeyUp(key int) error { + return uinputKeyboard.keyboard.KeyUp(key) +} + +func (uinputKeyboard KeyboardUinputWrapper) Close() error { + return uinputKeyboard.keyboard.Close() +} + +func (uinputMouse MouseUinputWrapper) Move(x, y int32) error { + return uinputMouse.touchpad.MoveTo(x, y) +} + +func (uinputMouse MouseUinputWrapper) LeftPress() error { + fmt.Println("Left!!!!") + return uinputMouse.mouse.LeftPress() +} + +func (uinputMouse MouseUinputWrapper) LeftRelease() error { + return uinputMouse.mouse.LeftRelease() +} + +func (uinputMouse MouseUinputWrapper) Wheel(horizontal bool, delta int32) error { + return uinputMouse.mouse.Wheel(horizontal, delta) +} + +func (uinputMouse MouseUinputWrapper) Close() error { + return uinputMouse.mouse.Close() +} diff --git a/input/wrapper.go b/input/wrapper.go new file mode 100644 index 0000000..d194f20 --- /dev/null +++ b/input/wrapper.go @@ -0,0 +1,49 @@ +package input + +import ( + "fmt" + "io" +) + +const ( + InputType_debug int = 0 + InputType_uinput int = 1 +) + +type Keyboard interface { + KeyDown(key int) error + KeyUp(key int) error + io.Closer +} + +type Mouse interface { + Move(x, y int32) error + LeftPress() error + LeftRelease() error + Wheel(horizontal bool, delta int32) error + io.Closer +} + +func CreateKeyboard(inputType int) (Keyboard, error) { + switch inputType { + case InputType_debug: + return KeyboardEmptyWrapper{}, nil + case InputType_uinput: + uinputKeyboard := new(KeyboardUinputWrapper) + uinputKeyboard.Init() + return uinputKeyboard, nil + } + return nil, fmt.Errorf("Unknown inputType: %d", inputType) +} + +func CreateMouse(inputType int) (Mouse, error) { + switch inputType { + case InputType_debug: + return MouseEmptyWrapper{}, nil + case InputType_uinput: + uinputMouse := new(MouseUinputWrapper) + uinputMouse.Init() + return uinputMouse, nil + } + return nil, fmt.Errorf("Unknown inputType: %d", inputType) +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..fad8c98 --- /dev/null +++ b/main.go @@ -0,0 +1,192 @@ +package main + +import ( + "bytes" + "context" + "encoding/binary" + "fmt" + "log" + "os" + "os/signal" + "syscall" + + "github.com/mafredri/magic4linux/input" + "github.com/mafredri/magic4linux/m4p" +) + +const ( + broadcastPort = 42830 +) + +func main() { + ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) + defer cancel() + + if err := run(ctx); err != nil { + panic(err) + } +} + +func createInputs() (input.Keyboard, input.Mouse) { + keyboard, err := input.CreateKeyboard(input.InputType_uinput) + if err != nil { + panic(err) + } + + mouse, err := input.CreateMouse(input.InputType_uinput) + if err != nil { + panic(err) + } + + return keyboard, mouse +} + +func discoverer() *m4p.Discoverer { + discoverer, err := m4p.NewDiscoverer(broadcastPort) + if err != nil { + panic(err) + } + return discoverer +} + +func run(ctx context.Context) error { + keyboard, mouse := createInputs() + discoverer := discoverer() + + defer discoverer.Close() + defer keyboard.Close() + defer mouse.Close() + + for { + select { + + case <-ctx.Done(): + return nil + + case device := <-discoverer.NextDevice(): + err := process(ctx, device, keyboard, mouse) + if err != nil { + log.Printf("Process failed with error: %v", err) + } + } + } +} + +func process(ctx context.Context, dev m4p.DeviceInfo, keyboard input.Keyboard, mouse input.Mouse) error { + addr := fmt.Sprintf("%s:%d", dev.IPAddr, dev.Port) + log.Printf("Starting processing with: %s", addr) + + client, err := m4p.Dial(ctx, addr) + if err != nil { + return err + } + defer client.Close() + + for { + message, err := client.Recv(ctx) + if err != nil { + return err + } + + switch message.Type { + case m4p.InputMessage: + processKey(message, keyboard) + case m4p.RemoteUpdateMessage: + processMouseMove(message, mouse) + case m4p.MouseMessage: + processMouseButtons(message, mouse) + case m4p.WheelMessage: + processMouseWheel(message, mouse) + + default: + } + } +} + +func processKey(message m4p.Message, keyboard input.Keyboard) { + key := message.Input.Parameters.KeyCode + switch key { + case m4p.KeyChannelUp: + key = input.KeyPageup + case m4p.KeyChannelDown: + key = input.KeyPagedown + case m4p.KeyLeft: + key = input.KeyLeft + case m4p.KeyUp: + key = input.KeyUp + case m4p.KeyRight: + key = input.KeyRight + case m4p.KeyDown: + key = input.KeyDown + case m4p.Key0: + key = input.Key0 + case m4p.Key1: + key = input.Key1 + case m4p.Key2: + key = input.Key2 + case m4p.Key3: + key = input.Key3 + case m4p.Key4: + key = input.Key4 + case m4p.Key5: + key = input.Key5 + case m4p.Key6: + key = input.Key6 + case m4p.Key7: + key = input.Key7 + case m4p.Key8: + key = input.Key8 + case m4p.Key9: + key = input.Key9 + case m4p.KeyRed: + key = input.KeyStop + case m4p.KeyGreen: + key = input.KeyPlaypause + case m4p.KeyBack: + key = input.KeyBackspace + } + + if message.Input.Parameters.IsDown { + keyboard.KeyDown(key) + } else { + keyboard.KeyUp(key) + } +} + +func processMouseButtons(message m4p.Message, mouse input.Mouse) { + switch message.Mouse.Type { + case "mousedown": + mouse.LeftPress() + case "mouseup": + mouse.LeftRelease() + } +} + +func processMouseWheel(message m4p.Message, mouse input.Mouse) { + mouse.Wheel(false, message.Wheel.Delta/100) +} + +func processMouseMove(message m4p.Message, mouse input.Mouse) { + r := bytes.NewReader(message.RemoteUpdate.Payload) + var returnValue, deviceID uint8 + var coordinate [2]int32 + var gyroscope, acceleration [3]float32 + var quaternion [4]float32 + for _, fn := range []func() error{ + func() error { return binary.Read(r, binary.LittleEndian, &returnValue) }, + func() error { return binary.Read(r, binary.LittleEndian, &deviceID) }, + func() error { return binary.Read(r, binary.LittleEndian, coordinate[:]) }, + func() error { return binary.Read(r, binary.LittleEndian, gyroscope[:]) }, + func() error { return binary.Read(r, binary.LittleEndian, acceleration[:]) }, + func() error { return binary.Read(r, binary.LittleEndian, quaternion[:]) }, + } { + if err := fn(); err != nil { + log.Printf("connect: %s decode failed: %v", message.Type, err) + break + } + } + + x := coordinate[0] + y := coordinate[1] + mouse.Move(x, y) +} -- cgit v1.2.3