diff --git a/cli/hid.go b/cli/hid.go deleted file mode 100644 index 100f413..0000000 --- a/cli/hid.go +++ /dev/null @@ -1,41 +0,0 @@ -package main - -import ( - "os" - - "github.com/sstallion/go-hid" - "errors" -) - -func SearchDevice(foundHandler func(info *hid.DeviceInfo) error) error { - return hid.Enumerate(uint16(CLI.VID), uint16(CLI.PID), func(info *hid.DeviceInfo) error { - if CLI.Serial != "" && info.SerialNbr != CLI.Serial { - return nil - } - if CLI.RawPath != "" && info.Path != CLI.RawPath { - return nil - } - - return foundHandler(info) - }) -} - -func OpenDevice() (*hid.Device, error) { - var dev *hid.Device - err := SearchDevice(func(info *hid.DeviceInfo) error { - d, err := hid.Open(info.VendorID, info.ProductID, info.SerialNbr) - if err == nil { - dev = d - return errors.New("Done") - } - return err - }) - if dev != nil { - return dev, nil - } - if err == nil { - err = os.ErrNotExist - } - - return nil, err -} diff --git a/cli/hid_cgo.go b/cli/hid_cgo.go new file mode 100644 index 0000000..67e3c9a --- /dev/null +++ b/cli/hid_cgo.go @@ -0,0 +1,71 @@ +// +build !puregohid + +package main + +import ( + "fmt" + "os" + + "errors" + + "github.com/BertoldVdb/ms-tools/gohid" + "github.com/sstallion/go-hid" +) + +func SearchDevice(foundHandler func(info *hid.DeviceInfo) error) error { + return hid.Enumerate(uint16(CLI.VID), uint16(CLI.PID), func(info *hid.DeviceInfo) error { + if CLI.Serial != "" && info.SerialNbr != CLI.Serial { + return nil + } + if CLI.RawPath != "" && info.Path != CLI.RawPath { + return nil + } + + return foundHandler(info) + }) +} + +func OpenDevice() (gohid.HIDDevice, error) { + var dev *hid.Device + err := SearchDevice(func(info *hid.DeviceInfo) error { + d, err := hid.Open(info.VendorID, info.ProductID, info.SerialNbr) + if err == nil { + dev = d + return errors.New("Done") + } + return err + }) + if dev != nil { + return dev, nil + } + if err == nil { + err = os.ErrNotExist + } + + return nil, err +} + +type ListHIDCmd struct { +} + +func (l *ListHIDCmd) Run(c *Context) error { + return SearchDevice(func(info *hid.DeviceInfo) error { + fmt.Printf("%s: ID %04x:%04x %s %s\n", + info.Path, info.VendorID, info.ProductID, info.MfrStr, info.ProductStr) + fmt.Println("Device Information:") + fmt.Printf("\tPath %s\n", info.Path) + fmt.Printf("\tVendorID %04x\n", info.VendorID) + fmt.Printf("\tProductID %04x\n", info.ProductID) + fmt.Printf("\tSerialNbr %s\n", info.SerialNbr) + fmt.Printf("\tReleaseNbr %x.%x\n", info.ReleaseNbr>>8, info.ReleaseNbr&0xff) + fmt.Printf("\tMfrStr %s\n", info.MfrStr) + fmt.Printf("\tProductStr %s\n", info.ProductStr) + fmt.Printf("\tUsagePage %#x\n", info.UsagePage) + fmt.Printf("\tUsage %#x\n", info.Usage) + fmt.Printf("\tInterfaceNbr %d\n", info.InterfaceNbr) + fmt.Println() + + return nil + }) + return nil +} diff --git a/cli/hid_pure.go b/cli/hid_pure.go new file mode 100644 index 0000000..0824345 --- /dev/null +++ b/cli/hid_pure.go @@ -0,0 +1,24 @@ +// +build puregohid + +package main + +import ( + "errors" + + "github.com/BertoldVdb/ms-tools/gohid" +) + +func OpenDevice() (gohid.HIDDevice, error) { + if CLI.RawPath == "" { + return nil, errors.New("RawPath must be specified when using pure GO HID") + } + + return gohid.OpenHID(CLI.RawPath) +} + +type ListHIDCmd struct { +} + +func (l *ListHIDCmd) Run(c *Context) error { + return errors.New("This command is not supported using pure GO HID") +} diff --git a/cli/listhid.go b/cli/listhid.go index d4e1ef8..06ab7d0 100644 --- a/cli/listhid.go +++ b/cli/listhid.go @@ -1,31 +1 @@ package main - -import ( - "fmt" - - "github.com/sstallion/go-hid" -) - -type ListHIDCmd struct { -} - -func (l *ListHIDCmd) Run(c *Context) error { - return SearchDevice(func(info *hid.DeviceInfo) error { - fmt.Printf("%s: ID %04x:%04x %s %s\n", - info.Path, info.VendorID, info.ProductID, info.MfrStr, info.ProductStr) - fmt.Println("Device Information:") - fmt.Printf("\tPath %s\n", info.Path) - fmt.Printf("\tVendorID %04x\n", info.VendorID) - fmt.Printf("\tProductID %04x\n", info.ProductID) - fmt.Printf("\tSerialNbr %s\n", info.SerialNbr) - fmt.Printf("\tReleaseNbr %x.%x\n", info.ReleaseNbr>>8, info.ReleaseNbr&0xff) - fmt.Printf("\tMfrStr %s\n", info.MfrStr) - fmt.Printf("\tProductStr %s\n", info.ProductStr) - fmt.Printf("\tUsagePage %#x\n", info.UsagePage) - fmt.Printf("\tUsage %#x\n", info.Usage) - fmt.Printf("\tInterfaceNbr %d\n", info.InterfaceNbr) - fmt.Println() - - return nil - }) -} diff --git a/cli/main.go b/cli/main.go index ca252b0..3b252d1 100644 --- a/cli/main.go +++ b/cli/main.go @@ -4,13 +4,13 @@ import ( "fmt" "os" + "github.com/BertoldVdb/ms-tools/gohid" "github.com/BertoldVdb/ms-tools/mshal" "github.com/alecthomas/kong" - "github.com/sstallion/go-hid" ) type Context struct { - dev *hid.Device + dev gohid.HIDDevice hal *mshal.HAL } @@ -56,8 +56,8 @@ func main() { return } - hid.Init() - defer hid.Exit() + // hid.Init() + // defer hid.Exit() c := &Context{} if ctx.Command() != "list-dev" { diff --git a/cli/tmp/patch_sr.txt b/cli/tmp/patch_sr.txt new file mode 100644 index 0000000..43ade47 --- /dev/null +++ b/cli/tmp/patch_sr.txt @@ -0,0 +1,4 @@ +sudo ./cli write RAM 0xc190 77 +sudo ./cli write RAM 0xc191 01 +sudo ./cli write RAM 0xc190 0x77 + diff --git a/go.mod b/go.mod index c6e4950..9e3f2b4 100644 --- a/go.mod +++ b/go.mod @@ -8,4 +8,5 @@ require ( github.com/inancgumus/screen v0.0.0-20190314163918-06e984b86ed3 github.com/sstallion/go-hid v0.0.0-20190621001400-1cf4630be9f4 golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 // indirect + golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 ) diff --git a/gohid/gohid.go b/gohid/gohid.go new file mode 100644 index 0000000..c977f32 --- /dev/null +++ b/gohid/gohid.go @@ -0,0 +1,11 @@ +package gohid + +type HIDDevice interface { + GetFeatureReport(b []byte) (int, error) + SendFeatureReport(b []byte) (int, error) + Close() error +} + +func OpenHID(path string) (HIDDevice, error) { + return openHIDInternal(path) +} diff --git a/gohid/gohid_default.go b/gohid/gohid_default.go new file mode 100644 index 0000000..3a71f1f --- /dev/null +++ b/gohid/gohid_default.go @@ -0,0 +1,9 @@ +// +build !linux + +package gohid + +import "errors" + +func openHIDInternal(path string) (HIDDevice, error) { + return nil, errors.New("Platform is not supported") +} diff --git a/gohid/gohid_linux.go b/gohid/gohid_linux.go new file mode 100644 index 0000000..59ec521 --- /dev/null +++ b/gohid/gohid_linux.go @@ -0,0 +1,90 @@ +// +build linux + +package gohid + +import ( + "errors" + "fmt" + "os" + "runtime" + "syscall" + "unsafe" + + "golang.org/x/sys/unix" +) + +type HIDRaw struct { + dev *os.File +} + +func openHIDInternal(path string) (HIDDevice, error) { + dev, err := os.Open(path) + if err != nil { + return nil, err + } + + return &HIDRaw{ + dev: dev, + }, nil +} + +var ErrorTooLong = errors.New("Transfer is too long") + +/* + HIDIOCSFEATURE(0) = C0004806 + HIDIOCSFEATURE(9) = C0094806 + HIDIOCGFEATURE(0) = C0004807 + HIDIOCGFEATURE(9) = C0094807 +*/ + +func (h *HIDRaw) SendFeatureReport(b []byte) (int, error) { + var tmp [1024]byte + + if len(b) > len(tmp) { + return 0, ErrorTooLong + } + + copy(tmp[:], b) + + _, _, errno := unix.Syscall( + syscall.SYS_IOCTL, + uintptr(h.dev.Fd()), + uintptr(uint32(0xC0004806)|uint32(len(b)<<16)), + uintptr(unsafe.Pointer(&tmp)), + ) + + runtime.KeepAlive(tmp) + + if errno != 0 { + return 0, os.NewSyscallError("SendFeatureReport", fmt.Errorf("%d", int(errno))) + } + + return len(b), nil +} + +func (h *HIDRaw) GetFeatureReport(b []byte) (int, error) { + var tmp [256]byte + + if len(b) > len(tmp) { + return 0, ErrorTooLong + } + + _, _, errno := unix.Syscall( + syscall.SYS_IOCTL, + uintptr(h.dev.Fd()), + uintptr(uint32(0xC0004807)|uint32(len(b)<<16)), + uintptr(unsafe.Pointer(&tmp)), + ) + + if errno != 0 { + return 0, os.NewSyscallError("GetFeatureReport", fmt.Errorf("%d", int(errno))) + } + + copy(b, tmp[:]) + + return len(b), nil +} + +func (h *HIDRaw) Close() error { + return h.dev.Close() +} diff --git a/gohid/ioctl_resolve.c.txt b/gohid/ioctl_resolve.c.txt new file mode 100644 index 0000000..6192259 --- /dev/null +++ b/gohid/ioctl_resolve.c.txt @@ -0,0 +1,12 @@ +#include +#include +#include +#include + +int main(){ + printf("HIDIOCSFEATURE(0) = %08X\n", HIDIOCSFEATURE(0)); + printf("HIDIOCSFEATURE(9) = %08X\n", HIDIOCSFEATURE(9)); + printf("HIDIOCGFEATURE(0) = %08X\n", HIDIOCGFEATURE(0)); + printf("HIDIOCGFEATURE(9) = %08X\n", HIDIOCGFEATURE(9)); + return 0; +} diff --git a/mshal/hal.go b/mshal/hal.go index 73587aa..8bbfa8b 100644 --- a/mshal/hal.go +++ b/mshal/hal.go @@ -1,11 +1,11 @@ package mshal import ( - "github.com/sstallion/go-hid" + "github.com/BertoldVdb/ms-tools/gohid" ) type HAL struct { - dev *hid.Device + dev gohid.HIDDevice deviceType int deviceTypeExtra int @@ -33,7 +33,7 @@ type HALConfig struct { LogFunc LogFunc } -func New(dev *hid.Device, config HALConfig) (*HAL, error) { +func New(dev gohid.HIDDevice, config HALConfig) (*HAL, error) { h := &HAL{ dev: dev, config: config,