예제 #1
0
        public static DateTime GetPreciseLastWriteTimeUtc(string path)
        {
            if (string.IsNullOrWhiteSpace(path))
            {
                throw new ArgumentNullException("path");
            }

            var statOut = new Stat();
            int statRet = Syscall.stat(path, out statOut);

            if (statRet == -1)
            {
                var errno = Syscall.GetLastError();
                if (errno == Errno.ESRCH || errno == Errno.ENOTDIR || errno == Errno.ENOENT)
                {
                    return(DateTime.MinValue);
                }

                UnixMarshal.ThrowExceptionForError(errno);
            }

            var result = NativeConvert.UnixEpoch.AddSeconds(statOut.st_mtime);

            // If this platform supports nanosecs
            // precision, take it into account.
            if (statOut.st_mtime_nsec != default(long))
            {
                var ns = (double)statOut.st_mtime_nsec;
                result = result.AddSeconds(ns / 1000000000d);
            }

            return(result);
        }
예제 #2
0
        int getReportDescriptorSize()
        {
            var ret = ioctl(fd, HIDIOCGRDESCSIZE, out int size);

            if (ret < 0)
            {
                var err = (Errno)(-ret);
                UnixMarshal.ThrowExceptionForError(err);
            }
            return(size);
        }
예제 #3
0
        unsafe string getPhysicalLocation()
        {
            const int size = 256;

            byte *buf = stackalloc byte[size];

            var ret = ioctl(fd, HIDIOCGRAWPHYS(size), (IntPtr)buf);

            if (ret < 0)
            {
                var err = (Errno)(-ret);
                UnixMarshal.ThrowExceptionForError(err);
            }

            return(Marshal.PtrToStringAnsi((IntPtr)buf));
        }
예제 #4
0
        public unsafe byte[] getReportDescriptor()
        {
            hidraw_report_descriptor *descriptor = stackalloc hidraw_report_descriptor[1];

            descriptor->size = (uint)ReportDescriptorSize;

            var ret = ioctl(fd, HIDIOCGRDESC, (IntPtr)descriptor);

            if (ret < 0)
            {
                var err = (Errno)(-ret);
                UnixMarshal.ThrowExceptionForError(err);
            }

            var bytes = new byte[descriptor->size];

            Marshal.Copy((IntPtr)descriptor->value, bytes, 0, ReportDescriptorSize);
            return(bytes);
        }
예제 #5
0
        static int Open(string path)
        {
            if (path == null)
            {
                throw new ArgumentNullException(nameof(path));
            }
            while (true)
            {
                var ret = open(path, OpenFlags.O_RDWR);
                if (ret == -1)
                {
                    var err = Stdlib.GetLastError();
                    if (err == Errno.EINTR)
                    {
                        continue;
                    }
                    UnixMarshal.ThrowExceptionForError(err);
                }

                return(ret);
            }
        }
예제 #6
0
 public void ThrowExceptionForError_Throws()
 {
     Assert.Throws <ArgumentException>(() => UnixMarshal.ThrowExceptionForError(UnixError.EBADF));
     Assert.Throws <ArgumentException>(() => UnixMarshal.ThrowExceptionForError(UnixError.EINVAL));
     Assert.Throws <ArgumentOutOfRangeException>(() => UnixMarshal.ThrowExceptionForError(UnixError.ERANGE));
     Assert.Throws <DirectoryNotFoundException>(() => UnixMarshal.ThrowExceptionForError(UnixError.ENOTDIR));
     Assert.Throws <FileNotFoundException>(() => UnixMarshal.ThrowExceptionForError(UnixError.ENOENT));
     Assert.Throws <InvalidOperationException>(() => UnixMarshal.ThrowExceptionForError(UnixError.EOPNOTSUPP));
     Assert.Throws <InvalidOperationException>(() => UnixMarshal.ThrowExceptionForError(UnixError.EOPNOTSUPP));
     Assert.Throws <InvalidOperationException>(() => UnixMarshal.ThrowExceptionForError(UnixError.EPERM));
     Assert.Throws <InvalidProgramException>(() => UnixMarshal.ThrowExceptionForError(UnixError.ENOEXEC));
     Assert.Throws <IOException>(() => UnixMarshal.ThrowExceptionForError(UnixError.EIO));
     Assert.Throws <IOException>(() => UnixMarshal.ThrowExceptionForError(UnixError.ENOSPC));
     Assert.Throws <IOException>(() => UnixMarshal.ThrowExceptionForError(UnixError.ENOTEMPTY));
     Assert.Throws <IOException>(() => UnixMarshal.ThrowExceptionForError(UnixError.ENXIO));
     Assert.Throws <IOException>(() => UnixMarshal.ThrowExceptionForError(UnixError.EROFS));
     Assert.Throws <IOException>(() => UnixMarshal.ThrowExceptionForError(UnixError.ESPIPE));
     Assert.Throws <NullReferenceException>(() => UnixMarshal.ThrowExceptionForError(UnixError.EFAULT));
     Assert.Throws <OverflowException>(() => UnixMarshal.ThrowExceptionForError(UnixError.EOVERFLOW));
     Assert.Throws <PathTooLongException>(() => UnixMarshal.ThrowExceptionForError(UnixError.ENAMETOOLONG));
     Assert.Throws <UnauthorizedAccessException>(() => UnixMarshal.ThrowExceptionForError(UnixError.EACCES));
     Assert.Throws <UnauthorizedAccessException>(() => UnixMarshal.ThrowExceptionForError(UnixError.EISDIR));
     Assert.Throws <Exception>(() => UnixMarshal.ThrowExceptionForError((UnixError)1234));
 }
예제 #7
0
        public IDisposable Connect()
        {
            if (monitor != null)
            {
                throw new InvalidOperationException("already connected");
            }
            monitor = new Monitor(udev);
            monitor.AddMatchSubsystem("hidraw");
            monitor.EnableReceiving();
            var tokenSource = new CancellationTokenSource();
            var token       = tokenSource.Token;

            Task.Run(() => {
                try {
                    var enumerator = new Enumerator(udev);
                    enumerator.AddMatchSubsystem("hidraw");
                    enumerator.ScanDevices();
                    foreach (var device in enumerator)
                    {
                        if (token.IsCancellationRequested)
                        {
                            break;
                        }
                        var hids = TryGetHidDevices(device);
                        if (hids == null)
                        {
                            continue;
                        }
                        foreach (var hid in hids)
                        {
                            subject.OnNext(hid);
                        }
                    }
                    var pollfds = new Pollfd[] {
                        new Pollfd {
                            fd = monitor.Fd, events = PollEvents.POLLIN
                        }
                    };
                    while (!token.IsCancellationRequested)
                    {
                        // FIXME: it would be nice if we didn't wake up every 100ms
                        // not sure how to interrupt a system call though
                        // pinvoke pthread_kill() maybe?
                        var ret = Syscall.poll(pollfds, 100);
                        if (ret == -1)
                        {
                            var err = Stdlib.GetLastError();
                            if (err == Errno.EINTR)
                            {
                                continue;
                            }
                            UnixMarshal.ThrowExceptionForError(err);
                        }
                        if (token.IsCancellationRequested)
                        {
                            break;
                        }
                        if (ret == 0)
                        {
                            // timed out
                            continue;
                        }
                        if (pollfds[0].revents.HasFlag(PollEvents.POLLNVAL))
                        {
                            // monitor file descriptor is closed, monitor must
                            // have been disposed, so complete gracefully
                            break;
                        }
                        var device = monitor.TryReceiveDevice();
                        var hids   = TryGetHidDevices(device);
                        if (hids == null)
                        {
                            continue;
                        }
                        foreach (var hid in hids)
                        {
                            subject.OnNext(hid);
                        }
                    }
                    subject.OnCompleted();
                }
                catch (Exception ex) {
                    subject.OnError(ex);
                }
                finally {
                    monitor.Dispose();
                    monitor = null;
                }
            }, token);

            return(Disposable.Create(() => tokenSource.Cancel()));
        }