|
@@ -14,7 +14,8 @@ import "runtime"
|
|
|
|
|
|
|
|
|
|
|
|
-type Device struct {
|
|
|
+type Device struct {
|
|
|
+ FileName string
|
|
|
*os.File
|
|
|
}
|
|
|
|
|
@@ -33,7 +34,12 @@ func Open(name string) (*Device, error) {
|
|
|
if err = syscall.SetNonblock(int(f.Fd()), true); err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
- return &Device{File: f}, nil
|
|
|
+ flags, err := syscall.FcntlInt(f.Fd(), syscall.F_GETFL, 0);
|
|
|
+ if flags, err = syscall.FcntlInt(f.Fd(), syscall.F_SETFL, flags | syscall.O_NONBLOCK); err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+
|
|
|
+ return &Device{FileName: name, File: f}, nil
|
|
|
}
|
|
|
|
|
|
func List() ([]string, error) {
|
|
@@ -326,6 +332,76 @@ func (d * Device) RelativeAxes() ([]RelativeAxis, error) {
|
|
|
}
|
|
|
|
|
|
|
|
|
+type Manager struct {
|
|
|
+ Connect chan(*Device)
|
|
|
+ Disconnect chan(*Device)
|
|
|
+ Errors chan(error)
|
|
|
+ Done bool
|
|
|
+ Devices []*Device
|
|
|
+ DevicesByName map[string] *Device
|
|
|
+ DevicesByFd map[int] *Device
|
|
|
+ fds []syscall.PollFd
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+func NewManager(connect chan(*Device), disconnect chan(*Device), event chan(InputEvent), errors chan(error), done chan (struct{})) * Manager {
|
|
|
+ manager := &Manager{Connect: connect, Disconnect: disconnect, Errors: errors, Done: false}
|
|
|
+ manager.Devices = []*Device{}
|
|
|
+ manager.DevicesByName = make(map[string] *Device)
|
|
|
+ manager.DevicesByFd = make(map[int] *Device)
|
|
|
+ manager.fds = []syscall.PollFd{}
|
|
|
+ return manager
|
|
|
+}
|
|
|
+
|
|
|
+func (manager *Manager) connectDevice(device * Device) {
|
|
|
+ manager.DevicesByName[device.FileName] = device
|
|
|
+ manager.DevicesByFd[int(device.Fd())] = device
|
|
|
+ manager.Devices = append(manager.Devices, device)
|
|
|
+ pollfd := syscall.PollFd{Fd: int32(device.Fd()), Events : syscall.POLLIN}
|
|
|
+ manager.fds = append(manager.fds, pollfd)
|
|
|
+ manager.Connect <- device
|
|
|
+}
|
|
|
+
|
|
|
+func (manager *Manager) disconnectDevice(device * Device) {
|
|
|
+ delete(manager.DevicesByName, device.FileName)
|
|
|
+ delete(manager.DevicesByFd, int(device.Fd()))
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ manager.Disconnect <- device
|
|
|
+}
|
|
|
+
|
|
|
+func (manager * Manager) ManageNewDevicesOnce() {
|
|
|
+ names, err := List()
|
|
|
+ if err != nil {
|
|
|
+ manager.Errors <- err
|
|
|
+ } else {
|
|
|
+ for _, name := range names {
|
|
|
+ if _, found := manager.DevicesByName[name] ; !found {
|
|
|
+ device, err := Open(name)
|
|
|
+ if err != nil {
|
|
|
+ manager.connectDevice(device)
|
|
|
+ } else {
|
|
|
+ manager.Errors <- err
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func (manager *Manager) ManageInputOnce() {
|
|
|
+ res, err := syscall.Poll(manager.fds, 0)
|
|
|
+ if err != nil {
|
|
|
+ manager.Errors <- err
|
|
|
+ }
|
|
|
+ if res > 0 {
|
|
|
+ for _, fd := range manager.fds {
|
|
|
+ if (fd.Revents & syscall.POLLIN) != 0 {
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
|
|
|
|