|
@@ -18,9 +18,7 @@ import "syscall"
|
|
|
|
|
|
type Device struct {
|
|
|
FileName string
|
|
|
- *os.File
|
|
|
- syscall.RawConn
|
|
|
- FD uintptr
|
|
|
+ fd int
|
|
|
|
|
|
Info struct {
|
|
|
Events []SupportedEvent
|
|
@@ -45,7 +43,7 @@ func LogDebug(format string, args...interface{}) {
|
|
|
|
|
|
|
|
|
func (d * Device) KeepAlive() {
|
|
|
- runtime.KeepAlive(d.File)
|
|
|
+ runtime.KeepAlive(d)
|
|
|
}
|
|
|
|
|
|
func (d * Device) String() string {
|
|
@@ -56,44 +54,25 @@ func (d * Device) String() string {
|
|
|
}
|
|
|
|
|
|
func (d *Device) SetNonblock(nonblocking bool) error {
|
|
|
- var err error = nil
|
|
|
- setnonblock := func(fd uintptr) {
|
|
|
- err = unix.SetNonblock(int(fd), nonblocking)
|
|
|
- }
|
|
|
- err2 := d.Control(setnonblock)
|
|
|
- if err2 != nil {
|
|
|
- return err2
|
|
|
- }
|
|
|
+ err := unix.SetNonblock(int(d.fd), nonblocking)
|
|
|
return err
|
|
|
}
|
|
|
|
|
|
func Open(name string) (*Device, error) {
|
|
|
- f, err := os.OpenFile(filepath.Join(Directory, name),
|
|
|
- unix.O_ASYNC|unix.O_NONBLOCK|os.O_RDWR, 0666)
|
|
|
+ path := filepath.Join(Directory, name)
|
|
|
+ fd, err := unix.Open(path, unix.O_ASYNC|unix.O_NONBLOCK|unix.O_RDWR, 0666)
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
-
|
|
|
- rawConn, err := f.SyscallConn()
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- var FD uintptr
|
|
|
- err = rawConn.Control(func(fd uintptr) {
|
|
|
- FD = fd
|
|
|
- })
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
|
|
|
- device := &Device{FileName: name, File: f, RawConn: rawConn, FD: FD}
|
|
|
+ device := &Device{FileName: name, fd: fd}
|
|
|
|
|
|
if err = device.SetNonblock(true) ; err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
|
|
|
+ runtime.SetFinalizer(device, (*Device).Close)
|
|
|
+
|
|
|
return device, nil
|
|
|
}
|
|
|
|
|
@@ -154,42 +133,32 @@ func List() ([]string, error) {
|
|
|
|
|
|
func (d * Device) Ioctl(code uint32, pointer unsafe.Pointer) error {
|
|
|
var errno syscall.Errno = 0
|
|
|
- ioctler := func (fd uintptr) {
|
|
|
- LogDebug("ioctl: %d %d %d\n", uintptr(fd), uintptr(code), uintptr(pointer))
|
|
|
+ LogDebug("ioctl: %d %d %d\n", uintptr(d.fd), uintptr(code), uintptr(pointer))
|
|
|
_, _, errno = unix.Syscall(
|
|
|
unix.SYS_IOCTL,
|
|
|
- uintptr(fd),
|
|
|
+ uintptr(d.fd),
|
|
|
uintptr(code),
|
|
|
uintptr(pointer))
|
|
|
- }
|
|
|
- err2 := d.Control(ioctler)
|
|
|
- if err2 != nil {
|
|
|
- return err2
|
|
|
- }
|
|
|
- if errno == 0 {
|
|
|
- return nil
|
|
|
- }
|
|
|
- return errno
|
|
|
+ if errno != 0 {
|
|
|
+ return errno
|
|
|
+ }
|
|
|
+ return nil
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (d * Device) Read(pointer unsafe.Pointer, size uintptr) (uintptr, error) {
|
|
|
+ if d.IsClosed() {
|
|
|
+ return 0, syscall.EINVAL
|
|
|
+ }
|
|
|
var errno syscall.Errno = 0
|
|
|
var read uintptr = 0
|
|
|
- reader := func (fd uintptr) bool {
|
|
|
- LogDebug("read: %d %d %d\n", uintptr(fd), uintptr(pointer), uintptr(size))
|
|
|
- read, _, errno = unix.Syscall(
|
|
|
+ LogDebug("read: %d %d %d\n", uintptr(d.fd), uintptr(pointer), uintptr(size))
|
|
|
+ read, _, errno = unix.Syscall(
|
|
|
unix.SYS_READ,
|
|
|
- uintptr(fd),
|
|
|
+ uintptr(d.fd),
|
|
|
uintptr(pointer),
|
|
|
uintptr(size))
|
|
|
- return true
|
|
|
- }
|
|
|
- err2 := d.RawConn.Read(reader)
|
|
|
- if err2 != nil {
|
|
|
- return read, err2
|
|
|
- }
|
|
|
if errno == 0 {
|
|
|
return read, nil
|
|
|
}
|
|
@@ -201,50 +170,53 @@ func (d * Device) Read(pointer unsafe.Pointer, size uintptr) (uintptr, error) {
|
|
|
|
|
|
|
|
|
func (d * Device) ReadBlock(pointer unsafe.Pointer, size uintptr) (uintptr, error) {
|
|
|
- var errno syscall.Errno = 0
|
|
|
- var read uintptr = 0
|
|
|
- reader := func (fd uintptr) bool {
|
|
|
- LogDebug("read: %d %d %d\n", uintptr(fd), uintptr(pointer), uintptr(size))
|
|
|
- read, _, errno = unix.Syscall(
|
|
|
- unix.SYS_READ,
|
|
|
- uintptr(fd),
|
|
|
- uintptr(pointer),
|
|
|
- uintptr(size))
|
|
|
- return errno != syscall.EAGAIN
|
|
|
- }
|
|
|
- err2 := d.RawConn.Read(reader)
|
|
|
- if err2 != nil {
|
|
|
- return read, err2
|
|
|
- }
|
|
|
- if errno == 0 {
|
|
|
- return read, nil
|
|
|
- }
|
|
|
- return read, errno
|
|
|
+ read, err := d.Read(pointer, size)
|
|
|
+ for read < 1 {
|
|
|
+ if err != nil {
|
|
|
+ return 0, err
|
|
|
+ }
|
|
|
+ read, err = d.Read(pointer, size)
|
|
|
+ }
|
|
|
+ return read, err
|
|
|
}
|
|
|
|
|
|
|
|
|
func (d * Device) Write(pointer unsafe.Pointer, size uintptr) (uintptr, error) {
|
|
|
- var errno syscall.Errno = 0
|
|
|
+ if d.IsClosed() {
|
|
|
+ return 0, syscall.EINVAL
|
|
|
+ }
|
|
|
+
|
|
|
+ var errno syscall.Errno = syscall.EAGAIN
|
|
|
var wrote uintptr = 0
|
|
|
- writer := func(fd uintptr) bool {
|
|
|
- LogDebug("write: %d %d %d\n", uintptr(fd), uintptr(pointer), uintptr(size))
|
|
|
- wrote, _, errno = unix.Syscall(
|
|
|
+ for errno == syscall.EAGAIN {
|
|
|
+ LogDebug("write: %d %d %d\n", uintptr(d.fd), uintptr(pointer), uintptr(size))
|
|
|
+ wrote, _, errno = unix.Syscall(
|
|
|
unix.SYS_WRITE,
|
|
|
- uintptr(fd),
|
|
|
+ uintptr(d.fd),
|
|
|
uintptr(pointer),
|
|
|
uintptr(size))
|
|
|
- return errno != syscall.EAGAIN
|
|
|
- }
|
|
|
- err2 := d.RawConn.Write(writer)
|
|
|
- if err2 != nil {
|
|
|
- return wrote, err2
|
|
|
- }
|
|
|
+ }
|
|
|
if errno == 0 {
|
|
|
return wrote, nil
|
|
|
}
|
|
|
return wrote, errno
|
|
|
}
|
|
|
|
|
|
+func (d * Device) IsClosed() bool {
|
|
|
+ return d.fd < 0
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+func (d * Device) Close() error {
|
|
|
+ if d.IsClosed() {
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+ err := unix.Close(d.fd)
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ return nil
|
|
|
+}
|
|
|
|
|
|
|
|
|
func (d * Device) DriverVersion() (int32, error) {
|
|
@@ -521,9 +493,9 @@ func (driver *Driver) connectDevice(device * Device) {
|
|
|
driver.Lock()
|
|
|
defer driver.Unlock()
|
|
|
driver.DevicesByName[device.FileName] = device
|
|
|
- driver.DevicesByFd[int(device.FD)] = device
|
|
|
+ driver.DevicesByFd[int(device.fd)] = device
|
|
|
driver.Devices = append(driver.Devices, device)
|
|
|
- pollfd := unix.PollFd{Fd: int32(device.FD), Events : unix.POLLIN}
|
|
|
+ pollfd := unix.PollFd{Fd: int32(device.fd), Events : unix.POLLIN}
|
|
|
driver.fds = append(driver.fds, pollfd)
|
|
|
driver.Connect <- device
|
|
|
}
|
|
@@ -532,12 +504,12 @@ func (driver *Driver) disconnectDevice(device * Device) {
|
|
|
driver.Lock()
|
|
|
defer driver.Unlock()
|
|
|
delete(driver.DevicesByName, device.FileName)
|
|
|
- delete(driver.DevicesByFd, int(device.FD))
|
|
|
+ delete(driver.DevicesByFd, int(device.fd))
|
|
|
found := false
|
|
|
var i int
|
|
|
var pollfd unix.PollFd
|
|
|
for i, pollfd = range driver.fds {
|
|
|
- if pollfd.Fd == int32(device.FD) {
|
|
|
+ if pollfd.Fd == int32(device.fd) {
|
|
|
found = true
|
|
|
break
|
|
|
}
|
|
@@ -628,49 +600,3 @@ func (driver *Driver) Stop() {
|
|
|
}
|
|
|
|
|
|
|
|
|
-
|
|
|
- printf("Supported events:\n");
|
|
|
- for (i = 0; i < EV_MAX; i++)
|
|
|
- if (TestBit(i, bit[0])) {
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- printf("Testing ... (interrupt to exit)\n");
|
|
|
-
|
|
|
- while (1) {
|
|
|
- rd = read(fd, ev, sizeof(struct input_event) * 64);
|
|
|
-
|
|
|
- if (rd < (int) sizeof(struct input_event)) {
|
|
|
- printf("yyy\n");
|
|
|
- perror("\nevtest: error reading");
|
|
|
- return 1;
|
|
|
- }
|
|
|
-
|
|
|
- for (i = 0; i < rd / sizeof(struct input_event); i++)
|
|
|
-
|
|
|
- if (ev[i].type == EV_SYN) {
|
|
|
- printf("Event: time %ld.%06ld, -------------- %s ------------\n",
|
|
|
- ev[i].time.tv_sec, ev[i].time.tv_usec, ev[i].code ? "Config Sync" : "Report Sync" );
|
|
|
- } else if (ev[i].type == EV_MSC && (ev[i].code == MSC_RAW || ev[i].code == MSC_SCAN)) {
|
|
|
- printf("Event: time %ld.%06ld, type %d (%s), code %d (%s), value %02x\n",
|
|
|
- ev[i].time.tv_sec, ev[i].time.tv_usec, ev[i].type,
|
|
|
- events[ev[i].type] ? events[ev[i].type] : "?",
|
|
|
- ev[i].code,
|
|
|
- names[ev[i].type] ? (names[ev[i].type][ev[i].code] ? names[ev[i].type][ev[i].code] : "?") : "?",
|
|
|
- ev[i].value);
|
|
|
- } else {
|
|
|
- printf("Event: time %ld.%06ld, type %d (%s), code %d (%s), value %d\n",
|
|
|
- ev[i].time.tv_sec, ev[i].time.tv_usec, ev[i].type,
|
|
|
- events[ev[i].type] ? events[ev[i].type] : "?",
|
|
|
- ev[i].code,
|
|
|
- names[ev[i].type] ? (names[ev[i].type][ev[i].code] ? names[ev[i].type][ev[i].code] : "?") : "?",
|
|
|
- ev[i].value);
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-}
|
|
|
-*/
|
|
|
-
|
|
|
-
|
|
|
-
|