Commit 7981e0d0 authored by simon's avatar simon
Browse files

comment

parent 37822be0
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -23,4 +23,3 @@ handle all events directly using the returned HID's OSEvent channel.

*/
package joysticks
+21 −20
Original line number Diff line number Diff line
@@ -20,9 +20,9 @@ type button struct {

//HID holds the in-coming event channel, mappings, and registered events for a joystick, and has methods to control and adjust behaviour.
type HID struct {
	OSEvent               chan osEventRecord
	buttons               map[uint8]button
	hatAxes               map[uint8]hatAxis
	OSEvents              chan osEventRecord
	Buttons               map[uint8]button
	HatAxes               map[uint8]hatAxis
	buttonCloseEvents     map[uint8]chan event
	buttonOpenEvents      map[uint8]chan event
	buttonLongPressEvents map[uint8]chan event
@@ -50,6 +50,7 @@ type HatPositionEvent struct {
	X, Y float32
}

// Button changed event
type ButtonChangeEvent struct {
	when
}
@@ -75,10 +76,10 @@ type HatAngleEvent struct {
// ParcelOutEvents interprets waits on the HID.OSEvent channel (so is blocking), then puts the required event(s), on any registered channel(s).
func (d HID) ParcelOutEvents() {
	for {
		if evt, ok := <-d.OSEvent; ok {
		if evt, ok := <-d.OSEvents; ok {
			switch evt.Type {
			case 1:
				b:=d.buttons[evt.Index]
				b := d.Buttons[evt.Index]
				if evt.Value == 0 {
					if c, ok := d.buttonOpenEvents[b.number]; ok {
						c <- ButtonChangeEvent{when{toDuration(evt.Time)}}
@@ -94,9 +95,9 @@ func (d HID) ParcelOutEvents() {
						c <- ButtonChangeEvent{when{toDuration(evt.Time)}}
					}
				}
				d.buttons[evt.Index] = button{b.number, toDuration(evt.Time), evt.Value != 0}
				d.Buttons[evt.Index] = button{b.number, toDuration(evt.Time), evt.Value != 0}
			case 2:
				h:=d.hatAxes[evt.Index]
				h := d.HatAxes[evt.Index]
				v := float32(evt.Value) / maxValue
				switch h.axis {
				case 1:
@@ -109,22 +110,22 @@ func (d HID) ParcelOutEvents() {
					}
				}
				if c, ok := d.hatPositionEvents[h.number]; ok {
					switch d.hatAxes[evt.Index].axis {
					switch d.HatAxes[evt.Index].axis {
					case 1:
						c <- HatPositionEvent{when{toDuration(evt.Time)}, v, d.hatAxes[evt.Index+1].value}
						c <- HatPositionEvent{when{toDuration(evt.Time)}, v, d.HatAxes[evt.Index+1].value}
					case 2:
						c <- HatPositionEvent{when{toDuration(evt.Time)}, d.hatAxes[evt.Index-1].value, v}
						c <- HatPositionEvent{when{toDuration(evt.Time)}, d.HatAxes[evt.Index-1].value, v}
					}
				}
				if c, ok := d.hatAngleEvents[h.number]; ok {
					switch d.hatAxes[evt.Index].axis {
					switch d.HatAxes[evt.Index].axis {
					case 1:
						c <- HatAngleEvent{when{toDuration(evt.Time)}, float32(math.Atan2(float64(v), float64(d.hatAxes[evt.Index+1].value)))}
						c <- HatAngleEvent{when{toDuration(evt.Time)}, float32(math.Atan2(float64(v), float64(d.HatAxes[evt.Index+1].value)))}
					case 2:
						c <- HatAngleEvent{when{toDuration(evt.Time)}, float32(math.Atan2(float64(d.hatAxes[evt.Index-1].value), float64(v)))}
						c <- HatAngleEvent{when{toDuration(evt.Time)}, float32(math.Atan2(float64(d.HatAxes[evt.Index-1].value), float64(v)))}
					}
				}
				d.hatAxes[evt.Index] = hatAxis{h.number, h.axis, toDuration(evt.Time), v}
				d.HatAxes[evt.Index] = hatAxis{h.number, h.axis, toDuration(evt.Time), v}
			default:
				// log.Println("unknown input type. ",evt.Type & 0x7f)
			}
@@ -190,7 +191,7 @@ func (d HID) OnRotate(hat uint8) chan event {
}

func (d HID) ButtonExists(button uint8) (ok bool) {
	for _, v := range d.buttons {
	for _, v := range d.Buttons {
		if v.number == button {
			return true
		}
@@ -199,7 +200,7 @@ func (d HID) ButtonExists(button uint8) (ok bool) {
}

func (d HID) HatExists(hat uint8) (ok bool) {
	for _, v := range d.hatAxes {
	for _, v := range d.HatAxes {
		if v.number == hat {
			return true
		}
@@ -208,5 +209,5 @@ func (d HID) HatExists(hat uint8) (ok bool) {
}

func (d HID) InsertSyntheticEvent(v int16, t uint8, i uint8) {
	d.OSEvent <- osEventRecord{Value: v, Type: t, Index: i}
	d.OSEvents <- osEventRecord{Value: v, Type: t, Index: i}
}
+17 −18
Original line number Diff line number Diff line
@@ -4,9 +4,9 @@ package joysticks

import (
	"encoding/binary"
	"strconv"
	"io"
	"os"
	"strconv"
	"time"
)

@@ -24,17 +24,17 @@ const maxValue = 1<<15 - 1
// Finds the first unused joystick, from a max of 4.
// Intended for bacic use since doesn't return state object.
func Capture(registrees ...Channel) []chan event {
	js := Connect(1)
	for i := 2; js == nil && i < 5; i++ {
		js = Connect(i)
	d := Connect(1)
	for i := 2; d == nil && i < 5; i++ {
		d = Connect(i)
	}
	if js == nil {
	if d == nil {
		return nil
	}
	go js.ParcelOutEvents()
	go d.ParcelOutEvents()
	chans := make([]chan event, len(registrees))
	for i, fns := range registrees {
		chans[i] = fns.Method(*js, fns.Number)
		chans[i] = fns.Method(*d, fns.Number)
	}
	return chans
}
@@ -45,35 +45,35 @@ var inputPathSlice = []byte("/dev/input/js ")[0:13]
// register channels by using the returned state object's On<xxx>(index) methods.
// Note: only one event, of each type '<xxx>', for each 'index', re-registering stops events going on the old channel.
// then activate using state objects ParcelOutEvents() method.(usually in a go routine.)
func Connect(index int) (js *HID) {
func Connect(index int) (d *HID) {
	r, e := os.OpenFile(string(strconv.AppendUint(inputPathSlice, uint64(index-1), 10)), os.O_RDWR, 0)
	if e != nil {
		return nil
	}
	js = &HID{make(chan osEventRecord), make(map[uint8]button), make(map[uint8]hatAxis), make(map[uint8]chan event), make(map[uint8]chan event), make(map[uint8]chan event), make(map[uint8]chan event), make(map[uint8]chan event), make(map[uint8]chan event), make(map[uint8]chan event)}
	d = &HID{make(chan osEventRecord), make(map[uint8]button), make(map[uint8]hatAxis),make(map[uint8]chan event),make(map[uint8]chan event),make(map[uint8]chan event),make(map[uint8]chan event),make(map[uint8]chan event),make(map[uint8]chan event),make(map[uint8]chan event)}
	// start thread to read joystick events to the joystick.state osEvent channel
	go eventPipe(r, js.OSEvent)
	js.populate()
	return js
	go eventPipe(r, d.OSEvents)
	d.populate()
	return d
}

// fill in the joysticks available events from the synthetic state events burst produced initially by the driver.
func (d HID) populate() {
	for buttonNumber, hatNumber, axisNumber := 1, 1, 1; ; {
		evt := <-d.OSEvent
		evt := <-d.OSEvents
		switch evt.Type {
		case 0x81:
			d.buttons[evt.Index] = button{uint8(buttonNumber), toDuration(evt.Time), evt.Value != 0}
			d.Buttons[evt.Index] = button{uint8(buttonNumber), toDuration(evt.Time), evt.Value != 0}
			buttonNumber += 1
		case 0x82:
			d.hatAxes[evt.Index] = hatAxis{uint8(hatNumber), uint8(axisNumber), toDuration(evt.Time), float32(evt.Value) / maxValue}
			d.HatAxes[evt.Index] = hatAxis{uint8(hatNumber), uint8(axisNumber), toDuration(evt.Time), float32(evt.Value) / maxValue}
			axisNumber += 1
			if axisNumber > 2 {
				axisNumber = 1
				hatNumber += 1
			}
		default:
			go func() { d.OSEvent <- evt }() // put the consumed, first, after end of synthetic burst, real event, back on channel.
			go func() { d.OSEvents <- evt }() // put the consumed, first, after end of synthetic burst, real event, back on channel.
			return
		}
	}
@@ -98,4 +98,3 @@ func toDuration(m uint32) time.Duration {


+2 −3
Original line number Diff line number Diff line
@@ -77,8 +77,8 @@ func TestHIDsAdvanced(t *testing.T) {
	if js1 == nil {
		panic("no HIDs")
	}
	if len(js1.buttons) < 10 || len(js1.hatAxes) < 6 {
		t.Errorf("HID#1, available buttons %d, Hats %d\n", len(js1.buttons), len(js1.hatAxes)/2)
	if len(js1.Buttons) < 10 || len(js1.HatAxes) < 6 {
		t.Errorf("HID#1, available buttons %d, Hats %d\n", len(js1.Buttons), len(js1.HatAxes)/2)
	}

	b1 := js1.OnClose(1)
@@ -130,4 +130,3 @@ func play(s Sound) {
		panic(err)
	}
}