Skip to content

Commit

Permalink
Rework wiimote event path finding
Browse files Browse the repository at this point in the history
  • Loading branch information
Pippadi committed Jun 4, 2023
1 parent 6376ba4 commit 6dff268
Show file tree
Hide file tree
Showing 9 changed files with 54 additions and 90 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@
# Go workspace file
go.work
WiiWill
fyne-cross
11 changes: 11 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.PHONY: clean

WiiWill:
go build

tar:
fyne-cross linux -name "WiiWill" -icon "assets/Icon.svg" -release -app-id "com.github.Pippadi.WiiWill"

clean:
go clean
go clean --cache
14 changes: 6 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ A simple Wii remote gamepad mapper for Linux.
3. Start program
4. Connect Wii remote from system's bluetooth settings

Steps 3 and 4 *must* be done in order for WiiWill to recognize the remote.

## Motivations

Other similar programs seem to be ancient, unmaintained, and difficult to use.
Expand All @@ -24,14 +26,10 @@ My hope with this is to be able to distribute a single package or binary that wo
> That said, suggestions and contributions are welcome.
1. Monitors `udev` for `uevent`s in which files under `/dev/input` (specified by `DEVNAME`) are created
2. Finds `DEVNAME` for `uevent` satisfying `MAJOR="13"`, `MINOR!="0", and `ID_INPUT_KEY=1`
3. Reads events from this file
4. Writes mapped key event to `/dev/uinput`

Of the several `/dev/input/eventX` files created, only one registers all the buttons (including the D-pad).
The `uevent` which reports this file also reports that it is created by the `input` driver (`MAJOR="13"`), has a `MINOR` not equal to `"0"`, and has `ID_INPUT_KEY` set to `"1"`.
I am not sure what exactly these mean. These are just patterns I've observed.
Time for some `grep`ping in the Linux source code.
2. Finds `DEVPATH` for `uevent` where `NAME` is specified as `"Nintendo Wii Remote"`
3. Combs through contents of `/sys/$DEVPATH` for a folder called `eventX`
4. Reads events from `/dev/input/eventX`
5. Generates mapped event through `uinput`

## Acknowledgements

Expand Down
File renamed without changes
7 changes: 0 additions & 7 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,35 +8,28 @@ require (
github.com/bendahl/uinput v1.6.2
github.com/pilebones/go-udev v0.9.0
gitlab.com/prithvivishak/goactor v0.1.5
tinygo.org/x/bluetooth v0.6.0
)

require (
fyne.io/systray v1.10.1-0.20230403195833-7dc3c09283d6 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/fatih/structs v1.1.0 // indirect
github.com/fredbi/uri v0.1.0 // indirect
github.com/fsnotify/fsnotify v1.5.4 // indirect
github.com/fyne-io/gl-js v0.0.0-20220119005834-d2da28d9ccfe // indirect
github.com/fyne-io/glfw-js v0.0.0-20220120001248-ee7290d23504 // indirect
github.com/fyne-io/image v0.0.0-20220602074514-4956b0afb3d2 // indirect
github.com/go-gl/gl v0.0.0-20211210172815-726fda9656d6 // indirect
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20221017161538-93cebf72946b // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-text/typesetting v0.0.0-20230405155246-bf9c697c6e16 // indirect
github.com/godbus/dbus/v5 v5.1.0 // indirect
github.com/goki/freetype v0.0.0-20220119013949-7a161fd3728c // indirect
github.com/gopherjs/gopherjs v1.17.2 // indirect
github.com/jsummers/gobmp v0.0.0-20151104160322-e2ba15ffa76e // indirect
github.com/muka/go-bluetooth v0.0.0-20220830075246-0746e3a1ea53 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/saltosystems/winrt-go v0.0.0-20220826130236-ddc8202da421 // indirect
github.com/sirupsen/logrus v1.9.0 // indirect
github.com/srwiley/oksvg v0.0.0-20220731023508-a61f04f16b76 // indirect
github.com/srwiley/rasterx v0.0.0-20210519020934-456a8d69b780 // indirect
github.com/stretchr/testify v1.8.0 // indirect
github.com/tevino/abool v1.2.0 // indirect
github.com/tinygo-org/cbgo v0.0.4 // indirect
github.com/yuin/goldmark v1.4.13 // indirect
golang.org/x/image v0.3.0 // indirect
golang.org/x/mobile v0.0.0-20211207041440-4e6c2922fdee // indirect
Expand Down
57 changes: 0 additions & 57 deletions go.sum

Large diffs are not rendered by default.

7 changes: 5 additions & 2 deletions ui/ui.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package ui

import (
"time"

"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/container"
Expand Down Expand Up @@ -74,8 +76,9 @@ func (u *UI) SetEventPath(eventPath string) {
u.statusLbl.SetText("Listening for events on " + eventPath)
u.activityBar.Stop()
u.activityBar.Hide()
actor.SendStopMsg(u.finderInbox)

// Wait for permissions to be applied on /dev/eventX
time.Sleep(250 * time.Millisecond)
var err error
u.listenerInbox, err = u.SpawnNested(wiimote.NewEventReader(eventPath), "EventReader")
if err != nil {
Expand All @@ -100,7 +103,7 @@ func (u *UI) HandleKeyEvent(key wiimote.Keycode, state wiimote.KeyState) {
}

func (u *UI) HandleLastMsg(a actor.Actor, err error) error {
if a.Inbox() == u.listenerInbox {
if a == nil || a.ID() == "EventReader" {
u.startFinder()
}
return nil
Expand Down
43 changes: 30 additions & 13 deletions wiimote/finder.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
package wiimote

import (
"errors"
"io/ioutil"
"path"
"strings"

"github.com/pilebones/go-udev/netlink"
actor "gitlab.com/prithvivishak/goactor"
)

const wiimoteName = "RVL-CNT-01"

type Finder struct {
actor.Base
}
Expand All @@ -20,17 +21,18 @@ func NewFinder() *Finder {
func (f *Finder) Initialize() error {
go func() {
for {
devname, err := getDevicePathFromUdev()
eventPath, err := getEventPathFromUdev()
if err == nil {
sendEventPath(f.CreatorInbox(), devname)
sendEventPath(f.CreatorInbox(), eventPath)
actor.SendStopMsg(f.Inbox())
return
}
}
}()
return nil
}

func getDevicePathFromUdev() (string, error) {
func getSysfsPathFromUdev() (string, error) {
conn := new(netlink.UEventConn)
err := conn.Connect(netlink.UdevEvent)
if err != nil {
Expand All @@ -49,17 +51,32 @@ func getDevicePathFromUdev() (string, error) {
case event := <-eventQ:
if event.Action == "add" &&
strings.Contains(event.KObj, "bluetooth") {
maj, majOk := event.Env["MAJOR"]
min, minOk := event.Env["MINOR"]
keyIn, keyInOk := event.Env["ID_INPUT_KEY"]
dev, devOk := event.Env["DEVNAME"]
// min="0" gives us /dev/input/jsX, which doesn't register D-pad events
if majOk && minOk && keyInOk && devOk &&
maj == "13" && min != "0" && keyIn == "1" {
return dev, nil
name, nameOk := event.Env["NAME"]
devpath, devpathOk := event.Env["DEVPATH"]
if nameOk && devpathOk && name == `"Nintendo Wii Remote"` {
return path.Join("/sys", devpath), nil
}
}
}
}
return "", nil
}

func getEventPathFromUdev() (string, error) {
sysfsPath, err := getSysfsPathFromUdev()
if err != nil {
return "", err
}

files, err := ioutil.ReadDir(sysfsPath)
if err != nil {
return "", err
}
for _, f := range files {
if strings.HasPrefix(f.Name(), "event") {
return path.Join("/dev/input", f.Name()), nil
}
}

return "", errors.New("Event file not found")
}
4 changes: 1 addition & 3 deletions wiimote/messages.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package wiimote

import (
actor "gitlab.com/prithvivishak/goactor"
)
import actor "gitlab.com/prithvivishak/goactor"

type Manager interface {
SetEventPath(eventPath string)
Expand Down

0 comments on commit 6dff268

Please sign in to comment.