Ejemplo n.º 1
0
        public override void Flush()
        {
            int handle = _handle;

            if (handle >= 0)
            {
                NativeMethods.retry(() => NativeMethods.tcdrain(handle));
            }
        }
Ejemplo n.º 2
0
        internal MacSerialStream(MacSerialDevice device)
            : base(device)
        {
            string fileSystemName = device.GetFileSystemName();

            int ret;
            int handle = NativeMethods.retry(() => NativeMethods.open(fileSystemName, NativeMethods.oflag.RDWR | NativeMethods.oflag.NOCTTY | NativeMethods.oflag.NONBLOCK));

            if (handle < 0)
            {
                var error = (NativeMethods.error)Marshal.GetLastWin32Error();
                if (error == NativeMethods.error.EACCES)
                {
                    throw DeviceException.CreateUnauthorizedAccessException(device, "Not permitted to open serial device at " + fileSystemName + ".");
                }
                else
                {
                    throw DeviceException.CreateIOException(device, "Unable to open serial device (" + error.ToString() + ").");
                }
            }

            ret = NativeMethods.retry(() => NativeMethods.ioctl(handle, NativeMethods.TIOCEXCL));
            if (ret < 0)
            {
                NativeMethods.retry(() => NativeMethods.close(handle));
                throw new IOException("Unable to open serial device exclusively.");
            }

            /*
             * ret = NativeMethods.retry(() => NativeMethods.fcntl(handle, NativeMethods.F_SETFL, 0));
             * if (ret < 0)
             * {
             *  NativeMethods.retry(() => NativeMethods.ioctl(handle, NativeMethods.TIOCNXCL));
             *  NativeMethods.retry(() => NativeMethods.close(handle));
             *  throw new IOException("Unable to remove blocking from port.");
             * }
             */

            ret = NativeMethods.retry(() => NativeMethods.tcgetattr(handle, out _oldSettings));
            if (ret < 0)
            {
                NativeMethods.retry(() => NativeMethods.ioctl(handle, NativeMethods.TIOCNXCL));
                NativeMethods.retry(() => NativeMethods.close(handle));
                throw new IOException("Unable to get serial port settings.");
            }

            _newSettings = _oldSettings;
            NativeMethods.cfmakeraw(ref _newSettings);
            _handle = handle;
            InitSettings();
            UpdateSettings();
        }
Ejemplo n.º 3
0
        // TODO: Has close() race condition.
        public unsafe override void Write(byte[] buffer, int offset, int count)
        {
            Throw.If.OutOfRange(buffer, offset, count);
            UpdateSettings();
            if (count == 0)
            {
                return;
            }

            fixed(byte *buffer0 = buffer)
            {
                int startTime = Environment.TickCount, writeTimeout = WriteTimeout;

                for (int bytesWritten = 0; bytesWritten < count;)
                {
                    int handle = _handle;
                    if (handle < 0)
                    {
                        throw new IOException("Closed.");
                    }

                    var bufferPtr    = (IntPtr)(buffer0 + offset + bytesWritten);
                    int bytesToWrite = count - bytesWritten;

                    var fd = new NativeMethods.pollfd()
                    {
                        fd = handle, events = NativeMethods.pollev.OUT
                    };
                    int ret = NativeMethods.retry(() => NativeMethods.poll(ref fd, 1, GetTimeout(startTime, writeTimeout)));
                    if (ret < 0)
                    {
                        throw new IOException("Write failed (poll).");
                    }
                    if (ret == 1)
                    {
                        if (fd.revents != NativeMethods.pollev.OUT)
                        {
                            throw new IOException(string.Format("Closed during write ({0}).", fd.revents));
                        }

                        int writeCount = checked ((int)NativeMethods.retry(() => NativeMethods.write(handle, bufferPtr, (UIntPtr)bytesToWrite)));
                        if (writeCount <= 0 || writeCount > bytesToWrite)
                        {
                            throw new IOException("Write failed.");
                        }
                        bytesWritten += writeCount;
                    }
                }
            }
        }
Ejemplo n.º 4
0
        // TODO: Has close() race condition.
        public unsafe override int Read(byte[] buffer, int offset, int count)
        {
            Throw.If.OutOfRange(buffer, offset, count);
            UpdateSettings();
            if (count == 0)
            {
                return(0);
            }

            fixed(byte *buffer0 = buffer)
            {
                int startTime = Environment.TickCount, readTimeout = ReadTimeout;

                while (true)
                {
                    int handle = _handle;
                    if (handle < 0)
                    {
                        throw new IOException("Closed.");
                    }

                    var bufferPtr   = (IntPtr)(buffer0 + offset);
                    int bytesToRead = count;

                    var fd = new NativeMethods.pollfd()
                    {
                        fd = handle, events = NativeMethods.pollev.IN
                    };
                    int ret = NativeMethods.retry(() => NativeMethods.poll(ref fd, 1, GetTimeout(startTime, readTimeout)));
                    if (ret < 0)
                    {
                        throw new IOException("Read failed (poll).");
                    }
                    if (ret == 1)
                    {
                        if (fd.revents != NativeMethods.pollev.IN)
                        {
                            throw new IOException(string.Format("Closed during read ({0}).", fd.revents));
                        }

                        int readCount = checked ((int)NativeMethods.retry(() => NativeMethods.read(handle, bufferPtr, (UIntPtr)bytesToRead)));
                        if (readCount <= 0 || readCount > bytesToRead)
                        {
                            throw new IOException("Read failed.");
                        }
                        return(readCount);
                    }
                }
            }
        }
Ejemplo n.º 5
0
        protected override void Dispose(bool disposing)
        {
            try
            {
                lock (_lock)
                {
                    int handle = Interlocked.Exchange(ref _handle, -1);
                    if (handle >= 0)
                    {
                        NativeMethods.retry(() => NativeMethods.tcsetattr(handle, NativeMethods.TCSANOW, ref _oldSettings));
                        NativeMethods.retry(() => NativeMethods.ioctl(handle, NativeMethods.TIOCNXCL));
                        NativeMethods.retry(() => NativeMethods.close(handle));
                    }
                }
            }
            catch
            {
            }

            base.Dispose(disposing);
        }
Ejemplo n.º 6
0
        unsafe void UpdateSettings()
        {
            lock (_lock)
            {
                int ret;
                int handle = _handle;
                if (handle >= 0)
                {
                    if (_settingsChanged)
                    {
                        int baudRate = _ser.BaudRate;
                        int dataBits = _ser.DataBits;
                        var parity   = _ser.Parity;
                        int stopBits = _ser.StopBits;

                        ret = NativeMethods.retry(() => NativeMethods.cfsetspeed(ref _newSettings, (UIntPtr)Math.Max(1, baudRate)));
                        if (ret < 0)
                        {
                            throw new IOException("cfsetspeed failed.");
                        }

                        ulong cflag = (ulong)_newSettings.c_cflag;
                        // data bits
                        cflag &= ~NativeMethods.CSIZE;
                        if (dataBits == 7)
                        {
                            cflag |= NativeMethods.CS7;
                        }
                        else
                        {
                            cflag |= NativeMethods.CS8;
                        }
                        // parity bits
                        cflag &= ~NativeMethods.PARENB & ~NativeMethods.PARODD;
                        if (parity == SerialParity.Even)
                        {
                            cflag |= NativeMethods.PARENB;
                        }
                        else if (parity == SerialParity.Odd)
                        {
                            cflag |= NativeMethods.PARENB | NativeMethods.PARODD;
                        }
                        // stop bits
                        cflag &= ~NativeMethods.CSTOPB;
                        if (stopBits == 2)
                        {
                            cflag |= NativeMethods.CSTOPB;
                        }
                        _newSettings.c_cflag = (UIntPtr)cflag;

                        ret = NativeMethods.retry(() => NativeMethods.tcsetattr(handle, NativeMethods.TCSANOW, ref _newSettings));
                        if (ret < 0)
                        {
                            throw new IOException("tcsetattr failed.");
                        }

                        ret = NativeMethods.retry(() => NativeMethods.tcflush(handle, NativeMethods.TCIFLUSH));
                        if (ret < 0)
                        {
                            throw new IOException("tcflush failed.");
                        }

                        _settingsChanged = false;
                    }
                }
            }
        }