|
@@ -18,6 +18,15 @@ import "runtime"
|
|
type Device struct {
|
|
type Device struct {
|
|
FileName string
|
|
FileName string
|
|
*os.File
|
|
*os.File
|
|
|
|
+ // Cached device information
|
|
|
|
+ Info struct {
|
|
|
|
+ Events []SupportedEvent
|
|
|
|
+ Keys []SupportedKey
|
|
|
|
+ Axes []AbsoluteAxis
|
|
|
|
+ Rolls []RelativeAxis
|
|
|
|
+ Name string
|
|
|
|
+ ID string
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
const Directory = "/dev/input"
|
|
const Directory = "/dev/input"
|
|
@@ -26,6 +35,13 @@ func (d * Device) KeepAlive() {
|
|
runtime.KeepAlive(d.File)
|
|
runtime.KeepAlive(d.File)
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+func (d * Device) String() string {
|
|
|
|
+ return fmt.Sprintf("%s: %s (%s):%v,%v,%v,%v",
|
|
|
|
+ d.FileName, d.Info.Name, d.Info.ID,
|
|
|
|
+ d.Info.Events, d.Info.Axes, d.Info.Keys,
|
|
|
|
+ d.Info.Rolls)
|
|
|
|
+}
|
|
|
|
+
|
|
func Open(name string) (*Device, error) {
|
|
func Open(name string) (*Device, error) {
|
|
f, err := os.OpenFile(filepath.Join(Directory, name),
|
|
f, err := os.OpenFile(filepath.Join(Directory, name),
|
|
syscall.O_ASYNC|syscall.O_NONBLOCK|os.O_RDWR, 0666)
|
|
syscall.O_ASYNC|syscall.O_NONBLOCK|os.O_RDWR, 0666)
|
|
@@ -41,6 +57,40 @@ func Open(name string) (*Device, error) {
|
|
}
|
|
}
|
|
|
|
|
|
return &Device{FileName: name, File: f}, nil
|
|
return &Device{FileName: name, File: f}, nil
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (d *Device) GatherInfo() error {
|
|
|
|
+ var err error
|
|
|
|
+ if d.Info.Events, err = d.SupportedEvents(); err != nil {
|
|
|
|
+ return err
|
|
|
|
+ }
|
|
|
|
+ if d.Info.Keys, err = d.SupportedKeys(); err != nil {
|
|
|
|
+ return err
|
|
|
|
+ }
|
|
|
|
+ if d.Info.Axes, err = d.SupportedAxes(); err != nil {
|
|
|
|
+ return err
|
|
|
|
+ }
|
|
|
|
+ if d.Info.Rolls, err = d.SupportedRelatives(); err != nil {
|
|
|
|
+ return err
|
|
|
|
+ }
|
|
|
|
+ if id, err := d.Id(); err != nil {
|
|
|
|
+ return err
|
|
|
|
+ } else {
|
|
|
|
+ d.Info.ID = fmt.Sprintf("%v", id)
|
|
|
|
+ }
|
|
|
|
+ if d.Info.Name, err = d.Name(); err != nil {
|
|
|
|
+ return err
|
|
|
|
+ }
|
|
|
|
+ return nil
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func OpenAndGatherInfo(name string) (*Device, error) {
|
|
|
|
+ dev, err := Open(name)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return dev, err
|
|
|
|
+ }
|
|
|
|
+ err = dev.GatherInfo()
|
|
|
|
+ return dev, err
|
|
}
|
|
}
|
|
|
|
|
|
func List() ([]string, error) {
|
|
func List() ([]string, error) {
|
|
@@ -315,7 +365,7 @@ func (se RelativeAxis) String() string {
|
|
return se.Name()
|
|
return se.Name()
|
|
}
|
|
}
|
|
|
|
|
|
-func (d * Device) RelativeAxes() ([]RelativeAxis, error) {
|
|
|
|
|
|
+func (d * Device) SupportedRelatives() ([]RelativeAxis, error) {
|
|
var bits [linux.REL_MAX / 8 + 1]uint8
|
|
var bits [linux.REL_MAX / 8 + 1]uint8
|
|
size := unsafe.Sizeof(bits)
|
|
size := unsafe.Sizeof(bits)
|
|
err := d.Ioctl(linux.EVIOCGBIT(linux.EV_REL, uintptr(size)), unsafe.Pointer(&bits));
|
|
err := d.Ioctl(linux.EVIOCGBIT(linux.EV_REL, uintptr(size)), unsafe.Pointer(&bits));
|
|
@@ -333,6 +383,8 @@ func (d * Device) RelativeAxes() ([]RelativeAxis, error) {
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
+
|
|
|
|
+
|
|
// MANAGER_DEVICE_SCAN_DELAY is the delay between device scans for the device manager.
|
|
// MANAGER_DEVICE_SCAN_DELAY is the delay between device scans for the device manager.
|
|
const MANAGER_DEVICE_SCAN_DELAY = 3 * time.Second
|
|
const MANAGER_DEVICE_SCAN_DELAY = 3 * time.Second
|
|
|
|
|
|
@@ -401,7 +453,7 @@ func (manager * Manager) ManageNewDevicesOnce() {
|
|
} else {
|
|
} else {
|
|
for _, name := range names {
|
|
for _, name := range names {
|
|
if _, found := manager.DevicesByName[name] ; !found {
|
|
if _, found := manager.DevicesByName[name] ; !found {
|
|
- device, err := Open(name)
|
|
|
|
|
|
+ device, err := OpenAndGatherInfo(name)
|
|
if err == nil {
|
|
if err == nil {
|
|
manager.connectDevice(device)
|
|
manager.connectDevice(device)
|
|
} else if manager.Verbose {
|
|
} else if manager.Verbose {
|