コード例 #1
0
ファイル: serialposix.py プロジェクト: pts/stackmat-clock
 def write(self, data):
     """Output the given byte string over the serial port."""
     if not self.is_open:
         raise portNotOpenError
     d = to_bytes(data)
     tx_len = length = len(d)
     timeout = Timeout(self._write_timeout)
     while tx_len > 0:
         try:
             n = os.write(self.fd, d)
             if timeout.is_non_blocking:
                 # Zero timeout indicates non-blocking - simply return the
                 # number of bytes of data actually written
                 return n
             elif not timeout.is_infinite:
                 # when timeout is set, use select to wait for being ready
                 # with the time left as timeout
                 if timeout.expired():
                     raise writeTimeoutError
                 abort, ready, _ = select.select([self.pipe_abort_write_r],
                                                 [self.fd], [],
                                                 timeout.time_left())
                 if abort:
                     os.read(self.pipe_abort_write_r, 1000)
                     break
                 if not ready:
                     raise writeTimeoutError
             else:
                 assert timeout.time_left() is None
                 # wait for write operation
                 abort, ready, _ = select.select([self.pipe_abort_write_r],
                                                 [self.fd], [], None)
                 if abort:
                     os.read(self.pipe_abort_write_r, 1)
                     break
                 if not ready:
                     raise SerialException('write failed (select)')
             d = d[n:]
             tx_len -= n
         except SerialException:
             raise
         except OSError as e:
             # this is for Python 3.x where select.error is a subclass of
             # OSError ignore BlockingIOErrors and EINTR. other errors are shown
             # https://www.python.org/dev/peps/pep-0475.
             if e.errno not in (errno.EAGAIN, errno.EALREADY,
                                errno.EWOULDBLOCK, errno.EINPROGRESS,
                                errno.EINTR):
                 raise SerialException('write failed: {}'.format(e))
         except select.error as e:
             # this is for Python 2.x
             # ignore BlockingIOErrors and EINTR. all errors are shown
             # see also http://www.python.org/dev/peps/pep-3151/#select
             if e[0] not in (errno.EAGAIN, errno.EALREADY,
                             errno.EWOULDBLOCK, errno.EINPROGRESS,
                             errno.EINTR):
                 raise SerialException('write failed: {}'.format(e))
         if not timeout.is_non_blocking and timeout.expired():
             raise writeTimeoutError
     return length - len(d)
コード例 #2
0
ファイル: serialposix.py プロジェクト: pts/stackmat-clock
 def read(self, size=1):
     """\
     Read size bytes from the serial port. If a timeout is set it may
     return less characters as requested. With no timeout it will block
     until the requested number of bytes is read.
     """
     if not self.is_open:
         raise portNotOpenError
     read = bytearray()
     timeout = Timeout(self._timeout)
     while len(read) < size:
         try:
             ready, _, _ = select.select([self.fd, self.pipe_abort_read_r],
                                         [], [], timeout.time_left())
             if self.pipe_abort_read_r in ready:
                 os.read(self.pipe_abort_read_r, 1000)
                 break
             # If select was used with a timeout, and the timeout occurs, it
             # returns with empty lists -> thus abort read operation.
             # For timeout == 0 (non-blocking operation) also abort when
             # there is nothing to read.
             if not ready:
                 break  # timeout
             buf = os.read(self.fd, size - len(read))
             # read should always return some data as select reported it was
             # ready to read when we get to this point.
             if not buf:
                 # Disconnected devices, at least on Linux, show the
                 # behavior that they are always ready to read immediately
                 # but reading returns nothing.
                 raise SerialException(
                     'device reports readiness to read but returned no data '
                     '(device disconnected or multiple access on port?)')
             read.extend(buf)
         except OSError as e:
             # this is for Python 3.x where select.error is a subclass of
             # OSError ignore BlockingIOErrors and EINTR. other errors are shown
             # https://www.python.org/dev/peps/pep-0475.
             if e.errno not in (errno.EAGAIN, errno.EALREADY,
                                errno.EWOULDBLOCK, errno.EINPROGRESS,
                                errno.EINTR):
                 raise SerialException('read failed: {}'.format(e))
         except select.error as e:
             # this is for Python 2.x
             # ignore BlockingIOErrors and EINTR. all errors are shown
             # see also http://www.python.org/dev/peps/pep-3151/#select
             if e[0] not in (errno.EAGAIN, errno.EALREADY,
                             errno.EWOULDBLOCK, errno.EINPROGRESS,
                             errno.EINTR):
                 raise SerialException('read failed: {}'.format(e))
         if timeout.expired():
             break
     return bytes(read)
コード例 #3
0
ファイル: serialposix.py プロジェクト: pts/stackmat-clock
    def open(self):
        """\
        Open port with current settings. This may throw a SerialException
        if the port cannot be opened."""
        if self._port is None:
            raise SerialException(
                "Port must be configured before it can be used.")
        if self.is_open:
            raise SerialException("Port is already open.")
        self.fd = None
        # open
        try:
            self.fd = os.open(self.portstr,
                              os.O_RDWR | os.O_NOCTTY | os.O_NONBLOCK)
        except OSError as msg:
            self.fd = None
            raise SerialException(
                msg.errno,
                "could not open port {}: {}".format(self._port, msg))
        #~ fcntl.fcntl(self.fd, fcntl.F_SETFL, 0)  # set blocking

        try:
            self._reconfigure_port(force_update=True)
        except:
            try:
                os.close(self.fd)
            except:
                # ignore any exception when closing the port
                # also to keep original exception that happened when setting up
                pass
            self.fd = None
            raise
        else:
            self.is_open = True
        try:
            if not self._dsrdtr:
                self._update_dtr_state()
            if not self._rtscts:
                self._update_rts_state()
        except IOError as e:
            if e.errno in (errno.EINVAL, errno.ENOTTY):
                # ignore Invalid argument and Inappropriate ioctl
                pass
            else:
                raise
        self.reset_input_buffer()
        self.pipe_abort_read_r, self.pipe_abort_read_w = os.pipe()
        self.pipe_abort_write_r, self.pipe_abort_write_w = os.pipe()
        fcntl.fcntl(self.pipe_abort_read_r, fcntl.F_SETFL, os.O_NONBLOCK)
        fcntl.fcntl(self.pipe_abort_write_r, fcntl.F_SETFL, os.O_NONBLOCK)
コード例 #4
0
ファイル: serialposix.py プロジェクト: pts/stackmat-clock
    def _reconfigure_port(self, force_update=True):
        """Set communication parameters on opened port."""
        super(VTIMESerial, self)._reconfigure_port()
        fcntl.fcntl(self.fd, fcntl.F_SETFL, 0)  # clear O_NONBLOCK

        if self._inter_byte_timeout is not None:
            vmin = 1
            vtime = int(self._inter_byte_timeout * 10)
        elif self._timeout is None:
            vmin = 1
            vtime = 0
        else:
            vmin = 0
            vtime = int(self._timeout * 10)
        try:
            orig_attr = termios.tcgetattr(self.fd)
            iflag, oflag, cflag, lflag, ispeed, ospeed, cc = orig_attr
        except termios.error as msg:  # if a port is nonexistent but has a /dev file, it'll fail here
            raise SerialException("Could not configure port: {}".format(msg))

        if vtime < 0 or vtime > 255:
            raise ValueError('Invalid vtime: {!r}'.format(vtime))
        cc[termios.VTIME] = vtime
        cc[termios.VMIN] = vmin

        termios.tcsetattr(self.fd, termios.TCSANOW,
                          [iflag, oflag, cflag, lflag, ispeed, ospeed, cc])
コード例 #5
0
ファイル: serialposix.py プロジェクト: pts/stackmat-clock
 def read(self, size=1):
     """\
     Read size bytes from the serial port. If a timeout is set it may
     return less characters as requested. With no timeout it will block
     until the requested number of bytes is read.
     """
     if not self.is_open:
         raise portNotOpenError
     read = bytearray()
     poll = select.poll()
     poll.register(
         self.fd,
         select.POLLIN | select.POLLERR | select.POLLHUP | select.POLLNVAL)
     if size > 0:
         while len(read) < size:
             # print "\tread(): size",size, "have", len(read)    #debug
             # wait until device becomes ready to read (or something fails)
             for fd, event in poll.poll(self._timeout * 1000):
                 if event & (select.POLLERR | select.POLLHUP
                             | select.POLLNVAL):
                     raise SerialException('device reports error (poll)')
                 #  we don't care if it is select.POLLIN or timeout, that's
                 #  handled below
             buf = os.read(self.fd, size - len(read))
             read.extend(buf)
             if ((self._timeout is not None and self._timeout >= 0) or
                 (self._inter_byte_timeout is not None
                  and self._inter_byte_timeout > 0)) and not buf:
                 break  # early abort on timeout
     return bytes(read)
コード例 #6
0
ファイル: serialwin32.py プロジェクト: pts/stackmat-clock
    def write(self, data):
        """Output the given byte string over the serial port."""
        if not self.is_open:
            raise portNotOpenError
        #~ if not isinstance(data, (bytes, bytearray)):
        #~ raise TypeError('expected %s or bytearray, got %s' % (bytes, type(data)))
        # convert data (needed in case of memoryview instance: Py 3.1 io lib), ctypes doesn't like memoryview
        data = to_bytes(data)
        if data:
            #~ win32event.ResetEvent(self._overlapped_write.hEvent)
            n = win32.DWORD()
            success = win32.WriteFile(self._port_handle, data, len(data),
                                      ctypes.byref(n), self._overlapped_write)
            if self._write_timeout != 0:  # if blocking (None) or w/ write timeout (>0)
                if not success and win32.GetLastError() not in (
                        win32.ERROR_SUCCESS, win32.ERROR_IO_PENDING):
                    raise SerialException("WriteFile failed ({!r})".format(
                        ctypes.WinError()))

                # Wait for the write to complete.
                #~ win32.WaitForSingleObject(self._overlapped_write.hEvent, win32.INFINITE)
                win32.GetOverlappedResult(self._port_handle,
                                          self._overlapped_write,
                                          ctypes.byref(n), True)
                if win32.GetLastError() == win32.ERROR_OPERATION_ABORTED:
                    return n.value  # canceled IO is no error
                if n.value != len(data):
                    raise writeTimeoutError
                return n.value
            else:
                errorcode = win32.ERROR_SUCCESS if success else win32.GetLastError(
                )
                if errorcode in (win32.ERROR_INVALID_USER_BUFFER,
                                 win32.ERROR_NOT_ENOUGH_MEMORY,
                                 win32.ERROR_OPERATION_ABORTED):
                    return 0
                elif errorcode in (win32.ERROR_SUCCESS,
                                   win32.ERROR_IO_PENDING):
                    # no info on true length provided by OS function in async mode
                    return len(data)
                else:
                    raise SerialException("WriteFile failed ({!r})".format(
                        ctypes.WinError()))
        else:
            return 0
コード例 #7
0
ファイル: serialwin32.py プロジェクト: pts/stackmat-clock
 def out_waiting(self):
     """Return how many bytes the in the outgoing buffer"""
     flags = win32.DWORD()
     comstat = win32.COMSTAT()
     if not win32.ClearCommError(self._port_handle, ctypes.byref(flags),
                                 ctypes.byref(comstat)):
         raise SerialException("ClearCommError failed ({!r})".format(
             ctypes.WinError()))
     return comstat.cbOutQue
コード例 #8
0
ファイル: serialwin32.py プロジェクト: pts/stackmat-clock
 def in_waiting(self):
     """Return the number of bytes currently in the input buffer."""
     flags = win32.DWORD()
     comstat = win32.COMSTAT()
     if not win32.ClearCommError(self._port_handle, ctypes.byref(flags),
                                 ctypes.byref(comstat)):
         raise SerialException("ClearCommError failed ({!r})".format(
             ctypes.WinError()))
     return comstat.cbInQue
コード例 #9
0
ファイル: serialwin32.py プロジェクト: pts/stackmat-clock
 def read(self, size=1):
     """\
     Read size bytes from the serial port. If a timeout is set it may
     return less characters as requested. With no timeout it will block
     until the requested number of bytes is read.
     """
     if not self.is_open:
         raise portNotOpenError
     if size > 0:
         win32.ResetEvent(self._overlapped_read.hEvent)
         flags = win32.DWORD()
         comstat = win32.COMSTAT()
         if not win32.ClearCommError(self._port_handle, ctypes.byref(flags),
                                     ctypes.byref(comstat)):
             raise SerialException("ClearCommError failed ({!r})".format(
                 ctypes.WinError()))
         n = min(comstat.cbInQue, size) if self.timeout == 0 else size
         if n > 0:
             buf = ctypes.create_string_buffer(n)
             rc = win32.DWORD()
             read_ok = win32.ReadFile(self._port_handle, buf, n,
                                      ctypes.byref(rc),
                                      ctypes.byref(self._overlapped_read))
             if not read_ok and win32.GetLastError() not in (
                     win32.ERROR_SUCCESS, win32.ERROR_IO_PENDING):
                 raise SerialException("ReadFile failed ({!r})".format(
                     ctypes.WinError()))
             result_ok = win32.GetOverlappedResult(
                 self._port_handle, ctypes.byref(self._overlapped_read),
                 ctypes.byref(rc), True)
             if not result_ok:
                 if win32.GetLastError() != win32.ERROR_OPERATION_ABORTED:
                     raise SerialException(
                         "GetOverlappedResult failed ({!r})".format(
                             ctypes.WinError()))
             read = buf.raw[:rc.value]
         else:
             read = bytes()
     else:
         read = bytes()
     return bytes(read)
コード例 #10
0
    def open(self):
        """Open port with current settings. This may throw a SerialException
           if the port cannot be opened."""
        if self._port is None:
            raise SerialException(
                "Port must be configured before it can be used.")
        self.fd = None
        # open
        try:
            self.fd = os.open(self.portstr,
                              os.O_RDWR | os.O_NOCTTY | os.O_NONBLOCK)
        except Exception as msg:
            self.fd = None
            raise SerialException("could not open port %s: %s" %
                                  (self._port, msg))
        # ~ fcntl.fcntl(self.fd, FCNTL.F_SETFL, 0)  #set blocking

        try:
            self._reconfigurePort()
        except BaseException:
            os.close(self.fd)
            self.fd = None
        else:
            self._isOpen = True
コード例 #11
0
ファイル: serialwin32.py プロジェクト: pts/stackmat-clock
    def _reconfigure_port(self):
        """Set communication parameters on opened port."""
        if not self._port_handle:
            raise SerialException("Can only operate on a valid port handle")

        # Set Windows timeout values
        # timeouts is a tuple with the following items:
        # (ReadIntervalTimeout,ReadTotalTimeoutMultiplier,
        #  ReadTotalTimeoutConstant,WriteTotalTimeoutMultiplier,
        #  WriteTotalTimeoutConstant)
        timeouts = win32.COMMTIMEOUTS()
        if self._timeout is None:
            pass  # default of all zeros is OK
        elif self._timeout == 0:
            timeouts.ReadIntervalTimeout = win32.MAXDWORD
        else:
            timeouts.ReadTotalTimeoutConstant = max(int(self._timeout * 1000),
                                                    1)
        if self._timeout != 0 and self._inter_byte_timeout is not None:
            timeouts.ReadIntervalTimeout = max(
                int(self._inter_byte_timeout * 1000), 1)

        if self._write_timeout is None:
            pass
        elif self._write_timeout == 0:
            timeouts.WriteTotalTimeoutConstant = win32.MAXDWORD
        else:
            timeouts.WriteTotalTimeoutConstant = max(
                int(self._write_timeout * 1000), 1)
        win32.SetCommTimeouts(self._port_handle, ctypes.byref(timeouts))

        win32.SetCommMask(self._port_handle, win32.EV_ERR)

        # Setup the connection info.
        # Get state and modify it:
        comDCB = win32.DCB()
        win32.GetCommState(self._port_handle, ctypes.byref(comDCB))
        comDCB.BaudRate = self._baudrate

        if self._bytesize == serialutil.FIVEBITS:
            comDCB.ByteSize = 5
        elif self._bytesize == serialutil.SIXBITS:
            comDCB.ByteSize = 6
        elif self._bytesize == serialutil.SEVENBITS:
            comDCB.ByteSize = 7
        elif self._bytesize == serialutil.EIGHTBITS:
            comDCB.ByteSize = 8
        else:
            raise ValueError("Unsupported number of data bits: {!r}".format(
                self._bytesize))

        if self._parity == serialutil.PARITY_NONE:
            comDCB.Parity = win32.NOPARITY
            comDCB.fParity = 0  # Disable Parity Check
        elif self._parity == serialutil.PARITY_EVEN:
            comDCB.Parity = win32.EVENPARITY
            comDCB.fParity = 1  # Enable Parity Check
        elif self._parity == serialutil.PARITY_ODD:
            comDCB.Parity = win32.ODDPARITY
            comDCB.fParity = 1  # Enable Parity Check
        elif self._parity == serialutil.PARITY_MARK:
            comDCB.Parity = win32.MARKPARITY
            comDCB.fParity = 1  # Enable Parity Check
        elif self._parity == serialutil.PARITY_SPACE:
            comDCB.Parity = win32.SPACEPARITY
            comDCB.fParity = 1  # Enable Parity Check
        else:
            raise ValueError("Unsupported parity mode: {!r}".format(
                self._parity))

        if self._stopbits == serialutil.STOPBITS_ONE:
            comDCB.StopBits = win32.ONESTOPBIT
        elif self._stopbits == serialutil.STOPBITS_ONE_POINT_FIVE:
            comDCB.StopBits = win32.ONE5STOPBITS
        elif self._stopbits == serialutil.STOPBITS_TWO:
            comDCB.StopBits = win32.TWOSTOPBITS
        else:
            raise ValueError("Unsupported number of stop bits: {!r}".format(
                self._stopbits))

        comDCB.fBinary = 1  # Enable Binary Transmission
        # Char. w/ Parity-Err are replaced with 0xff (if fErrorChar is set to TRUE)
        if self._rs485_mode is None:
            if self._rtscts:
                comDCB.fRtsControl = win32.RTS_CONTROL_HANDSHAKE
            else:
                comDCB.fRtsControl = win32.RTS_CONTROL_ENABLE if self._rts_state else win32.RTS_CONTROL_DISABLE
            comDCB.fOutxCtsFlow = self._rtscts
        else:
            # checks for unsupported settings
            # XXX verify if platform really does not have a setting for those
            if not self._rs485_mode.rts_level_for_tx:
                raise ValueError(
                    'Unsupported value for RS485Settings.rts_level_for_tx: {!r}'
                    .format(self._rs485_mode.rts_level_for_tx, ))
            if self._rs485_mode.rts_level_for_rx:
                raise ValueError(
                    'Unsupported value for RS485Settings.rts_level_for_rx: {!r}'
                    .format(self._rs485_mode.rts_level_for_rx, ))
            if self._rs485_mode.delay_before_tx is not None:
                raise ValueError(
                    'Unsupported value for RS485Settings.delay_before_tx: {!r}'
                    .format(self._rs485_mode.delay_before_tx, ))
            if self._rs485_mode.delay_before_rx is not None:
                raise ValueError(
                    'Unsupported value for RS485Settings.delay_before_rx: {!r}'
                    .format(self._rs485_mode.delay_before_rx, ))
            if self._rs485_mode.loopback:
                raise ValueError(
                    'Unsupported value for RS485Settings.loopback: {!r}'.
                    format(self._rs485_mode.loopback, ))
            comDCB.fRtsControl = win32.RTS_CONTROL_TOGGLE
            comDCB.fOutxCtsFlow = 0

        if self._dsrdtr:
            comDCB.fDtrControl = win32.DTR_CONTROL_HANDSHAKE
        else:
            comDCB.fDtrControl = win32.DTR_CONTROL_ENABLE if self._dtr_state else win32.DTR_CONTROL_DISABLE
        comDCB.fOutxDsrFlow = self._dsrdtr
        comDCB.fOutX = self._xonxoff
        comDCB.fInX = self._xonxoff
        comDCB.fNull = 0
        comDCB.fErrorChar = 0
        comDCB.fAbortOnError = 0
        comDCB.XonChar = serialutil.XON
        comDCB.XoffChar = serialutil.XOFF

        if not win32.SetCommState(self._port_handle, ctypes.byref(comDCB)):
            raise SerialException(
                'Cannot configure port, something went wrong. '
                'Original message: {!r}'.format(ctypes.WinError()))
コード例 #12
0
ファイル: serialwin32.py プロジェクト: pts/stackmat-clock
    def open(self):
        """\
        Open port with current settings. This may throw a SerialException
        if the port cannot be opened.
        """
        if self._port is None:
            raise SerialException(
                "Port must be configured before it can be used.")
        if self.is_open:
            raise SerialException("Port is already open.")
        # the "\\.\COMx" format is required for devices other than COM1-COM8
        # not all versions of windows seem to support this properly
        # so that the first few ports are used with the DOS device name
        port = self.name
        try:
            if port.upper().startswith('COM') and int(port[3:]) > 8:
                port = '\\\\.\\' + port
        except ValueError:
            # for like COMnotanumber
            pass
        self._port_handle = win32.CreateFile(
            port,
            win32.GENERIC_READ | win32.GENERIC_WRITE,
            0,  # exclusive access
            None,  # no security
            win32.OPEN_EXISTING,
            win32.FILE_ATTRIBUTE_NORMAL | win32.FILE_FLAG_OVERLAPPED,
            0)
        if self._port_handle == win32.INVALID_HANDLE_VALUE:
            self._port_handle = None  # 'cause __del__ is called anyway
            raise SerialException("could not open port {!r}: {!r}".format(
                self.portstr, ctypes.WinError()))

        try:
            self._overlapped_read = win32.OVERLAPPED()
            self._overlapped_read.hEvent = win32.CreateEvent(None, 1, 0, None)
            self._overlapped_write = win32.OVERLAPPED()
            #~ self._overlapped_write.hEvent = win32.CreateEvent(None, 1, 0, None)
            self._overlapped_write.hEvent = win32.CreateEvent(None, 0, 0, None)

            # Setup a 4k buffer
            win32.SetupComm(self._port_handle, 4096, 4096)

            # Save original timeout values:
            self._orgTimeouts = win32.COMMTIMEOUTS()
            win32.GetCommTimeouts(self._port_handle,
                                  ctypes.byref(self._orgTimeouts))

            self._reconfigure_port()

            # Clear buffers:
            # Remove anything that was there
            win32.PurgeComm(
                self._port_handle, win32.PURGE_TXCLEAR | win32.PURGE_TXABORT
                | win32.PURGE_RXCLEAR | win32.PURGE_RXABORT)
        except:
            try:
                self._close()
            except:
                # ignore any exception when closing the port
                # also to keep original exception that happened when setting up
                pass
            self._port_handle = None
            raise
        else:
            self.is_open = True
コード例 #13
0
    def _reconfigurePort(self):
        """Set communication parameters on opened port."""
        if self.fd is None:
            raise SerialException("Can only operate on a valid port handle")
        custom_baud = None

        vmin = vtime = 0  # timeout is done via select
        if self._interCharTimeout is not None:
            vmin = 1
            vtime = int(self._interCharTimeout * 10)
        try:
            iflag, oflag, cflag, lflag, ispeed, ospeed, cc = termios.tcgetattr(
                self.fd)
        # if a port is nonexistent but has a /dev file, it'll fail here
        except termios.error as msg:
            raise SerialException("Could not configure port: %s" % msg)
        # set up raw mode / no echo / binary
        cflag |= (TERMIOS.CLOCAL | TERMIOS.CREAD)
        lflag &= ~(TERMIOS.ICANON | TERMIOS.ECHO | TERMIOS.ECHOE
                   | TERMIOS.ECHOK | TERMIOS.ECHONL | TERMIOS.ISIG
                   | TERMIOS.IEXTEN)  # |TERMIOS.ECHOPRT
        for flag in ('ECHOCTL', 'ECHOKE'):  # netbsd workaround for Erk
            if hasattr(TERMIOS, flag):
                lflag &= ~getattr(TERMIOS, flag)

        oflag &= ~(TERMIOS.OPOST)
        iflag &= ~(TERMIOS.INLCR | TERMIOS.IGNCR | TERMIOS.ICRNL
                   | TERMIOS.IGNBRK)
        if hasattr(TERMIOS, 'IUCLC'):
            iflag &= ~TERMIOS.IUCLC
        if hasattr(TERMIOS, 'PARMRK'):
            iflag &= ~TERMIOS.PARMRK

        # setup baudrate
        try:
            ispeed = ospeed = getattr(TERMIOS, 'B%s' % (self._baudrate))
        except AttributeError:
            try:
                ispeed = ospeed = baudrate_constants[self._baudrate]
            except KeyError:
                #~ raise ValueError('Invalid baud rate: %r' % self._baudrate)
                # may need custom baud rate, it isnt in our list.
                ispeed = ospeed = getattr(TERMIOS, 'B38400')
                custom_baud = int(self._baudrate)  # store for later

        # setup char len
        cflag &= ~TERMIOS.CSIZE
        if self._bytesize == 8:
            cflag |= TERMIOS.CS8
        elif self._bytesize == 7:
            cflag |= TERMIOS.CS7
        elif self._bytesize == 6:
            cflag |= TERMIOS.CS6
        elif self._bytesize == 5:
            cflag |= TERMIOS.CS5
        else:
            raise ValueError('Invalid char len: %r' % self._bytesize)
        # setup stopbits
        if self._stopbits == STOPBITS_ONE:
            cflag &= ~(TERMIOS.CSTOPB)
        elif self._stopbits == STOPBITS_TWO:
            cflag |= (TERMIOS.CSTOPB)
        else:
            raise ValueError('Invalid stopit specification: %r' %
                             self._stopbits)
        # setup parity
        iflag &= ~(TERMIOS.INPCK | TERMIOS.ISTRIP)
        if self._parity == PARITY_NONE:
            cflag &= ~(TERMIOS.PARENB | TERMIOS.PARODD)
        elif self._parity == PARITY_EVEN:
            cflag &= ~(TERMIOS.PARODD)
            cflag |= (TERMIOS.PARENB)
        elif self._parity == PARITY_ODD:
            cflag |= (TERMIOS.PARENB | TERMIOS.PARODD)
        else:
            raise ValueError('Invalid parity: %r' % self._parity)
        # setup flow control
        # xonxoff
        if hasattr(TERMIOS, 'IXANY'):
            if self._xonxoff:
                iflag |= (TERMIOS.IXON | TERMIOS.IXOFF)  # |TERMIOS.IXANY)
            else:
                iflag &= ~(TERMIOS.IXON | TERMIOS.IXOFF | TERMIOS.IXANY)
        else:
            if self._xonxoff:
                iflag |= (TERMIOS.IXON | TERMIOS.IXOFF)
            else:
                iflag &= ~(TERMIOS.IXON | TERMIOS.IXOFF)
        # rtscts
        if hasattr(TERMIOS, 'CRTSCTS'):
            if self._rtscts:
                cflag |= (TERMIOS.CRTSCTS)
            else:
                cflag &= ~(TERMIOS.CRTSCTS)
        # try it with alternate constant name
        elif hasattr(TERMIOS, 'CNEW_RTSCTS'):
            if self._rtscts:
                cflag |= (TERMIOS.CNEW_RTSCTS)
            else:
                cflag &= ~(TERMIOS.CNEW_RTSCTS)
        # XXX should there be a warning if setting up rtscts (and xonxoff etc)
        # fails??

        # buffer
        # vmin "minimal number of characters to be read. = for non blocking"
        if vmin < 0 or vmin > 255:
            raise ValueError('Invalid vmin: %r ' % vmin)
        cc[TERMIOS.VMIN] = vmin
        # vtime
        if vtime < 0 or vtime > 255:
            raise ValueError('Invalid vtime: %r' % vtime)
        cc[TERMIOS.VTIME] = vtime
        # activate settings
        termios.tcsetattr(self.fd, TERMIOS.TCSANOW,
                          [iflag, oflag, cflag, lflag, ispeed, ospeed, cc])

        # apply custom baud rate, if any
        if custom_baud is not None:
            import array
            buf = array.array('i', [0] * 32)

            # get serial_struct
            FCNTL.ioctl(self.fd, TERMIOS.TIOCGSERIAL, buf)

            # set custom divisor
            buf[6] = buf[7] / custom_baud

            # update flags
            buf[4] &= ~ASYNC_SPD_MASK
            buf[4] |= ASYNC_SPD_CUST

            # set serial_struct
            try:
                res = FCNTL.ioctl(self.fd, TERMIOS.TIOCSSERIAL, buf)
            except IOError:
                raise ValueError('Failed to set custom baud rate: %r' %
                                 self._baudrate)
コード例 #14
0
ファイル: serialposix.py プロジェクト: pts/stackmat-clock
    def _reconfigure_port(self, force_update=False):
        """Set communication parameters on opened port."""
        if self.fd is None:
            raise SerialException(
                "Can only operate on a valid file descriptor")

        # if exclusive lock is requested, create it before we modify anything else
        if self._exclusive is not None:
            if self._exclusive:
                try:
                    fcntl.flock(self.fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
                except IOError as msg:
                    raise SerialException(
                        msg.errno,
                        "Could not exclusively lock port {}: {}".format(
                            self._port, msg))
            else:
                fcntl.flock(self.fd, fcntl.LOCK_UN)

        custom_baud = None

        vmin = vtime = 0  # timeout is done via select
        if self._inter_byte_timeout is not None:
            vmin = 1
            vtime = int(self._inter_byte_timeout * 10)
        try:
            orig_attr = termios.tcgetattr(self.fd)
            iflag, oflag, cflag, lflag, ispeed, ospeed, cc = orig_attr
        except termios.error as msg:  # if a port is nonexistent but has a /dev file, it'll fail here
            raise SerialException("Could not configure port: {}".format(msg))
        # set up raw mode / no echo / binary
        cflag |= (termios.CLOCAL | termios.CREAD)
        lflag &= ~(termios.ICANON | termios.ECHO | termios.ECHOE
                   | termios.ECHOK | termios.ECHONL | termios.ISIG
                   | termios.IEXTEN)  # |termios.ECHOPRT
        for flag in ('ECHOCTL', 'ECHOKE'):  # netbsd workaround for Erk
            if hasattr(termios, flag):
                lflag &= ~getattr(termios, flag)

        oflag &= ~(termios.OPOST | termios.ONLCR | termios.OCRNL)
        iflag &= ~(termios.INLCR | termios.IGNCR | termios.ICRNL
                   | termios.IGNBRK)
        if hasattr(termios, 'IUCLC'):
            iflag &= ~termios.IUCLC
        if hasattr(termios, 'PARMRK'):
            iflag &= ~termios.PARMRK

        # setup baud rate
        try:
            ispeed = ospeed = getattr(termios, 'B{}'.format(self._baudrate))
        except AttributeError:
            try:
                ispeed = ospeed = self.BAUDRATE_CONSTANTS[self._baudrate]
            except KeyError:
                #~ raise ValueError('Invalid baud rate: %r' % self._baudrate)
                # may need custom baud rate, it isn't in our list.
                ispeed = ospeed = getattr(termios, 'B38400')
                try:
                    custom_baud = int(self._baudrate)  # store for later
                except ValueError:
                    raise ValueError('Invalid baud rate: {!r}'.format(
                        self._baudrate))
                else:
                    if custom_baud < 0:
                        raise ValueError('Invalid baud rate: {!r}'.format(
                            self._baudrate))

        # setup char len
        cflag &= ~termios.CSIZE
        if self._bytesize == 8:
            cflag |= termios.CS8
        elif self._bytesize == 7:
            cflag |= termios.CS7
        elif self._bytesize == 6:
            cflag |= termios.CS6
        elif self._bytesize == 5:
            cflag |= termios.CS5
        else:
            raise ValueError('Invalid char len: {!r}'.format(self._bytesize))
        # setup stop bits
        if self._stopbits == serialutil.STOPBITS_ONE:
            cflag &= ~(termios.CSTOPB)
        elif self._stopbits == serialutil.STOPBITS_ONE_POINT_FIVE:
            cflag |= (termios.CSTOPB
                      )  # XXX same as TWO.. there is no POSIX support for 1.5
        elif self._stopbits == serialutil.STOPBITS_TWO:
            cflag |= (termios.CSTOPB)
        else:
            raise ValueError('Invalid stop bit specification: {!r}'.format(
                self._stopbits))
        # setup parity
        iflag &= ~(termios.INPCK | termios.ISTRIP)
        if self._parity == serialutil.PARITY_NONE:
            cflag &= ~(termios.PARENB | termios.PARODD | CMSPAR)
        elif self._parity == serialutil.PARITY_EVEN:
            cflag &= ~(termios.PARODD | CMSPAR)
            cflag |= (termios.PARENB)
        elif self._parity == serialutil.PARITY_ODD:
            cflag &= ~CMSPAR
            cflag |= (termios.PARENB | termios.PARODD)
        elif self._parity == serialutil.PARITY_MARK and CMSPAR:
            cflag |= (termios.PARENB | CMSPAR | termios.PARODD)
        elif self._parity == serialutil.PARITY_SPACE and CMSPAR:
            cflag |= (termios.PARENB | CMSPAR)
            cflag &= ~(termios.PARODD)
        else:
            raise ValueError('Invalid parity: {!r}'.format(self._parity))
        # setup flow control
        # xonxoff
        if hasattr(termios, 'IXANY'):
            if self._xonxoff:
                iflag |= (termios.IXON | termios.IXOFF)  # |termios.IXANY)
            else:
                iflag &= ~(termios.IXON | termios.IXOFF | termios.IXANY)
        else:
            if self._xonxoff:
                iflag |= (termios.IXON | termios.IXOFF)
            else:
                iflag &= ~(termios.IXON | termios.IXOFF)
        # rtscts
        if hasattr(termios, 'CRTSCTS'):
            if self._rtscts:
                cflag |= (termios.CRTSCTS)
            else:
                cflag &= ~(termios.CRTSCTS)
        elif hasattr(termios,
                     'CNEW_RTSCTS'):  # try it with alternate constant name
            if self._rtscts:
                cflag |= (termios.CNEW_RTSCTS)
            else:
                cflag &= ~(termios.CNEW_RTSCTS)
        # XXX should there be a warning if setting up rtscts (and xonxoff etc) fails??

        # buffer
        # vmin "minimal number of characters to be read. 0 for non blocking"
        if vmin < 0 or vmin > 255:
            raise ValueError('Invalid vmin: {!r}'.format(vmin))
        cc[termios.VMIN] = vmin
        # vtime
        if vtime < 0 or vtime > 255:
            raise ValueError('Invalid vtime: {!r}'.format(vtime))
        cc[termios.VTIME] = vtime
        # activate settings
        if force_update or [iflag, oflag, cflag, lflag, ispeed, ospeed, cc
                            ] != orig_attr:
            termios.tcsetattr(self.fd, termios.TCSANOW,
                              [iflag, oflag, cflag, lflag, ispeed, ospeed, cc])

        # apply custom baud rate, if any
        if custom_baud is not None:
            self._set_special_baudrate(custom_baud)

        if self._rs485_mode is not None:
            self._set_rs485_mode(self._rs485_mode)