Skip to content

Commit 191c031

Browse files
committed
simplified usb management using HID
1 parent 7cb4f3c commit 191c031

File tree

4 files changed

+28
-77
lines changed

4 files changed

+28
-77
lines changed

gcadapter.go

Lines changed: 24 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -5,82 +5,54 @@ import (
55
"log"
66
"sync"
77

8-
"github.com/google/gousb"
8+
// "github.com/google/gousb"
9+
"github.com/karalabe/hid"
910
)
1011

1112
const (
12-
gcAdapterVendorID gousb.ID = 0x057E
13-
gcAdapterProductID gousb.ID = 0x0337
14-
startEndpoint int = 0x02
15-
readEndpoint int = 0x81
13+
vendorID uint16 = 0x057E
14+
productID uint16 = 0x0337
1615
)
1716

1817
var startPayload = []byte{0x13}
1918

2019
// GCAdapter represents a Gamecube controller usb adapter
2120
type GCAdapter struct {
22-
ctx *gousb.Context
23-
dev *gousb.Device
24-
cfg *gousb.Config
25-
intf *gousb.Interface
26-
endpoint *gousb.InEndpoint
2721
controllers map[uint8]*rawGCInput
2822
offsets map[uint8]*Offsets
2923
mutex sync.RWMutex
24+
device *hid.Device
3025
}
3126

3227
// NewGCAdapter connects to a Gamecube controller usb adapter and returns a pointer to it.
3328
// An adapter should be closed with adapter.Close() once it's not required anymore or when the program closes.
3429
// The best way of achieving that is calling defer adapter.Close() right after adapter, err := NewGCAdapter()
3530
func NewGCAdapter() (*GCAdapter, error) {
36-
var adapter *GCAdapter = nil
37-
ctx := gousb.NewContext()
38-
dev, err := ctx.OpenDeviceWithVIDPID(gcAdapterVendorID, gcAdapterProductID)
39-
if dev == nil {
40-
err = errors.New("GC Adapter: no adapter found")
41-
}
42-
if err != nil {
43-
// log.Fatalf("list: %s", err)
44-
return adapter, err
45-
}
31+
var adapter = &GCAdapter{}
4632

47-
dev.SetAutoDetach(true)
48-
49-
cfg, err := dev.Config(1)
50-
if err != nil {
51-
// log.Fatalf("%s.Config(1): %v", dev, err)
52-
return adapter, err
33+
if !hid.Supported() {
34+
return adapter, errors.New("HID is not supported on this device")
5335
}
5436

55-
intf, err := cfg.Interface(0, 0)
56-
if err != nil {
57-
// log.Fatalf("%s.Interface(0, 0): %v", cfg, err)
58-
return adapter, err
37+
devices := hid.Enumerate(vendorID, productID)
38+
var deviceInfo hid.DeviceInfo
39+
if len(devices) > 0 {
40+
deviceInfo = devices[0]
41+
} else {
42+
return adapter, errors.New("GC Adapter: no adapter found")
5943
}
60-
61-
outep, err := intf.OutEndpoint(startEndpoint)
44+
device, err := deviceInfo.Open()
6245
if err != nil {
63-
// log.Fatalf("%s.OutEndpoint(%d): %v", outep, startEndpoint, err)
6446
return adapter, err
6547
}
6648

67-
_, err = outep.Write(startPayload)
49+
_, err = device.Write(startPayload)
6850
if err != nil {
69-
// log.Fatalf("Can't write payload %d: %v", out, err)
7051
return adapter, err
7152
}
7253

73-
inep, err := intf.InEndpoint(readEndpoint)
74-
if err != nil {
75-
// log.Fatalf("%s.InEndpoint(%d): %v", inep, readEndpoint, err)
76-
return adapter, err
77-
}
54+
adapter.device = device
7855

79-
adapter = newGCAdapterFromEndpoint(inep)
80-
adapter.ctx = ctx
81-
adapter.dev = dev
82-
adapter.cfg = cfg
83-
adapter.intf = intf
8456
adapter.mutex.Lock()
8557
adapter.controllers = make(map[uint8]*rawGCInput)
8658
adapter.offsets = make(map[uint8]*Offsets)
@@ -92,12 +64,6 @@ func NewGCAdapter() (*GCAdapter, error) {
9264
return adapter, nil
9365
}
9466

95-
func newGCAdapterFromEndpoint(endpoint *gousb.InEndpoint) *GCAdapter {
96-
adapter := &GCAdapter{}
97-
adapter.endpoint = endpoint
98-
return adapter
99-
}
100-
10167
// Poll polls the Gamecube usb adapter once
10268
func (adapter *GCAdapter) Poll() error {
10369
return adapter.step()
@@ -118,21 +84,7 @@ func (adapter *GCAdapter) StartPolling() {
11884

11985
// Close properly closes the adapter once it's not required anymore
12086
func (adapter *GCAdapter) Close() error {
121-
var err error
122-
err = adapter.ctx.Close()
123-
if err != nil {
124-
return err
125-
}
126-
err = adapter.dev.Close()
127-
if err != nil {
128-
return err
129-
}
130-
err = adapter.cfg.Close()
131-
if err != nil {
132-
return err
133-
}
134-
adapter.intf.Close()
135-
return nil
87+
return adapter.device.Close()
13688
}
13789

13890
// Buttons represents the Gamecube controller buttons
@@ -188,7 +140,7 @@ type Offsets struct {
188140
}
189141

190142
func (adapter *GCAdapter) step() error {
191-
controllers, err := readGCAdapter(adapter.endpoint)
143+
controllers, err := readGCAdapter(adapter.device)
192144
if err != nil {
193145
return err
194146
}
@@ -284,7 +236,7 @@ func processRawController(rawInput *rawGCInput, offsets *Offsets) *GCInputs {
284236
return &gcinput
285237
}
286238

287-
func deserializeGCControllers(data []byte) map[uint8]*rawGCInput {
239+
func DeserializeGCControllers(data []byte) map[uint8]*rawGCInput {
288240
gcInputs := make(map[uint8]*rawGCInput)
289241
for _, PORT := range []uint8{0, 1, 2, 3} {
290242
gcInput := &rawGCInput{}
@@ -316,15 +268,15 @@ func deserializeGCControllers(data []byte) map[uint8]*rawGCInput {
316268
return gcInputs
317269
}
318270

319-
func readGCAdapter(adapterEndpoint *gousb.InEndpoint) (map[uint8]*rawGCInput, error) {
271+
func readGCAdapter(device *hid.Device) (map[uint8]*rawGCInput, error) {
320272
rawGcInputs := make(map[uint8]*rawGCInput)
321273

322-
data := make([]byte, adapterEndpoint.Desc.MaxPacketSize)
323-
_, err := adapterEndpoint.Read(data)
274+
data := make([]byte, 37)
275+
_, err := device.Read(data)
324276
if err != nil {
325277
// fmt.Printf("Couldn't read adapter. Error: %v\n", err)
326278
return rawGcInputs, err
327279
}
328-
rawGcInputs = deserializeGCControllers(data)
280+
rawGcInputs = DeserializeGCControllers(data)
329281
return rawGcInputs, nil
330282
}

gcadapter_test.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ func TestAdapter(t *testing.T) {
1616
ticker := time.NewTicker(time.Second / time.Duration(60))
1717
go func() {
1818
for range ticker.C {
19-
t.Logf("%v", time.Now())
19+
// t.Logf("%v", time.Now())
2020
inputs := adapter.Controllers()
2121
for k := range inputs {
2222
t.Logf("Controller %d start pressed: %v", k, inputs[k].Button.START)
@@ -25,5 +25,4 @@ func TestAdapter(t *testing.T) {
2525
}()
2626
time.Sleep(3 * time.Second)
2727
ticker.Stop()
28-
t.FailNow()
2928
}

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ module github.com/Gurvan/go-gc-adapter
22

33
go 1.15
44

5-
require github.com/google/gousb v1.1.1
5+
require github.com/karalabe/hid v1.0.0

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
github.com/google/gousb v1.1.1 h1:2sjwXlc0PIBgDnXtNxUrHcD/RRFOmAtRq4QgnFBE6xc=
2-
github.com/google/gousb v1.1.1/go.mod h1:b3uU8itc6dHElt063KJobuVtcKHWEfFOysOqBNzHhLY=
1+
github.com/karalabe/hid v1.0.0 h1:+/CIMNXhSU/zIJgnIvBD2nKHxS/bnRHhhs9xBryLpPo=
2+
github.com/karalabe/hid v1.0.0/go.mod h1:Vr51f8rUOLYrfrWDFlV12GGQgM5AT8sVh+2fY4MPeu8=

0 commit comments

Comments
 (0)