1#!/usr/bin/env python 2# 3# backend for serial IO for POSIX compatible systems, like Linux, OSX 4# 5# This file is part of pySerial. https://github.com/pyserial/pyserial 6# (C) 2001-2020 Chris Liechti <[email protected]> 7# 8# SPDX-License-Identifier: BSD-3-Clause 9# 10# parts based on code from Grant B. Edwards <[email protected]>: 11# ftp://ftp.visi.com/users/grante/python/PosixSerial.py 12# 13# references: http://www.easysw.com/~mike/serial/serial.html 14 15# Collection of port names (was previously used by number_to_device which was 16# removed. 17# - Linux /dev/ttyS%d (confirmed) 18# - cygwin/win32 /dev/com%d (confirmed) 19# - openbsd (OpenBSD) /dev/cua%02d 20# - bsd*, freebsd* /dev/cuad%d 21# - darwin (OS X) /dev/cuad%d 22# - netbsd /dev/dty%02d (NetBSD 1.6 testing by Erk) 23# - irix (IRIX) /dev/ttyf%d (partially tested) names depending on flow control 24# - hp (HP-UX) /dev/tty%dp0 (not tested) 25# - sunos (Solaris/SunOS) /dev/tty%c (letters, 'a'..'z') (confirmed) 26# - aix (AIX) /dev/tty%d 27 28 29from __future__ import absolute_import 30 31# pylint: disable=abstract-method 32import errno 33import fcntl 34import os 35import select 36import struct 37import sys 38import termios 39 40import serial 41from serial.serialutil import SerialBase, SerialException, to_bytes, \ 42 PortNotOpenError, SerialTimeoutException, Timeout 43 44 45class PlatformSpecificBase(object): 46 BAUDRATE_CONSTANTS = {} 47 48 def _set_special_baudrate(self, baudrate): 49 raise NotImplementedError('non-standard baudrates are not supported on this platform') 50 51 def _set_rs485_mode(self, rs485_settings): 52 raise NotImplementedError('RS485 not supported on this platform') 53 54 def set_low_latency_mode(self, low_latency_settings): 55 raise NotImplementedError('Low latency not supported on this platform') 56 57 def _update_break_state(self): 58 """\ 59 Set break: Controls TXD. When active, no transmitting is possible. 60 """ 61 if self._break_state: 62 fcntl.ioctl(self.fd, TIOCSBRK) 63 else: 64 fcntl.ioctl(self.fd, TIOCCBRK) 65 66 67# some systems support an extra flag to enable the two in POSIX unsupported 68# paritiy settings for MARK and SPACE 69CMSPAR = 0 # default, for unsupported platforms, override below 70 71# try to detect the OS so that a device can be selected... 72# this code block should supply a device() and set_special_baudrate() function 73# for the platform 74plat = sys.platform.lower() 75 76if plat[:5] == 'linux': # Linux (confirmed) # noqa 77 import array 78 79 # extra termios flags 80 CMSPAR = 0o10000000000 # Use "stick" (mark/space) parity 81 82 # baudrate ioctls 83 TCGETS2 = 0x802C542A 84 TCSETS2 = 0x402C542B 85 BOTHER = 0o010000 86 87 # RS485 ioctls 88 TIOCGRS485 = 0x542E 89 TIOCSRS485 = 0x542F 90 SER_RS485_ENABLED = 0b00000001 91 SER_RS485_RTS_ON_SEND = 0b00000010 92 SER_RS485_RTS_AFTER_SEND = 0b00000100 93 SER_RS485_RX_DURING_TX = 0b00010000 94 95 class PlatformSpecific(PlatformSpecificBase): 96 BAUDRATE_CONSTANTS = { 97 0: 0o000000, # hang up 98 50: 0o000001, 99 75: 0o000002, 100 110: 0o000003, 101 134: 0o000004, 102 150: 0o000005, 103 200: 0o000006, 104 300: 0o000007, 105 600: 0o000010, 106 1200: 0o000011, 107 1800: 0o000012, 108 2400: 0o000013, 109 4800: 0o000014, 110 9600: 0o000015, 111 19200: 0o000016, 112 38400: 0o000017, 113 57600: 0o010001, 114 115200: 0o010002, 115 230400: 0o010003, 116 460800: 0o010004, 117 500000: 0o010005, 118 576000: 0o010006, 119 921600: 0o010007, 120 1000000: 0o010010, 121 1152000: 0o010011, 122 1500000: 0o010012, 123 2000000: 0o010013, 124 2500000: 0o010014, 125 3000000: 0o010015, 126 3500000: 0o010016, 127 4000000: 0o010017 128 } 129 130 def set_low_latency_mode(self, low_latency_settings): 131 buf = array.array('i', [0] * 32) 132 133 try: 134 # get serial_struct 135 fcntl.ioctl(self.fd, termios.TIOCGSERIAL, buf) 136 137 # set or unset ASYNC_LOW_LATENCY flag 138 if low_latency_settings: 139 buf[4] |= 0x2000 140 else: 141 buf[4] &= ~0x2000 142 143 # set serial_struct 144 fcntl.ioctl(self.fd, termios.TIOCSSERIAL, buf) 145 except IOError as e: 146 raise ValueError('Failed to update ASYNC_LOW_LATENCY flag to {}: {}'.format(low_latency_settings, e)) 147 148 def _set_special_baudrate(self, baudrate): 149 # right size is 44 on x86_64, allow for some growth 150 buf = array.array('i', [0] * 64) 151 try: 152 # get serial_struct 153 fcntl.ioctl(self.fd, TCGETS2, buf) 154 # set custom speed 155 buf[2] &= ~termios.CBAUD 156 buf[2] |= BOTHER 157 buf[9] = buf[10] = baudrate 158 159 # set serial_struct 160 fcntl.ioctl(self.fd, TCSETS2, buf) 161 except IOError as e: 162 raise ValueError('Failed to set custom baud rate ({}): {}'.format(baudrate, e)) 163 164 def _set_rs485_mode(self, rs485_settings): 165 buf = array.array('i', [0] * 8) # flags, delaytx, delayrx, padding 166 try: 167 fcntl.ioctl(self.fd, TIOCGRS485, buf) 168 buf[0] |= SER_RS485_ENABLED 169 if rs485_settings is not None: 170 if rs485_settings.loopback: 171 buf[0] |= SER_RS485_RX_DURING_TX 172 else: 173 buf[0] &= ~SER_RS485_RX_DURING_TX 174 if rs485_settings.rts_level_for_tx: 175 buf[0] |= SER_RS485_RTS_ON_SEND 176 else: 177 buf[0] &= ~SER_RS485_RTS_ON_SEND 178 if rs485_settings.rts_level_for_rx: 179 buf[0] |= SER_RS485_RTS_AFTER_SEND 180 else: 181 buf[0] &= ~SER_RS485_RTS_AFTER_SEND 182 if rs485_settings.delay_before_tx is not None: 183 buf[1] = int(rs485_settings.delay_before_tx * 1000) 184 if rs485_settings.delay_before_rx is not None: 185 buf[2] = int(rs485_settings.delay_before_rx * 1000) 186 else: 187 buf[0] = 0 # clear SER_RS485_ENABLED 188 fcntl.ioctl(self.fd, TIOCSRS485, buf) 189 except IOError as e: 190 raise ValueError('Failed to set RS485 mode: {}'.format(e)) 191 192 193elif plat == 'cygwin': # cygwin/win32 (confirmed) 194 195 class PlatformSpecific(PlatformSpecificBase): 196 BAUDRATE_CONSTANTS = { 197 128000: 0x01003, 198 256000: 0x01005, 199 500000: 0x01007, 200 576000: 0x01008, 201 921600: 0x01009, 202 1000000: 0x0100a, 203 1152000: 0x0100b, 204 1500000: 0x0100c, 205 2000000: 0x0100d, 206 2500000: 0x0100e, 207 3000000: 0x0100f 208 } 209 210 211elif plat[:6] == 'darwin': # OS X 212 import array 213 IOSSIOSPEED = 0x80045402 # _IOW('T', 2, speed_t) 214 215 class PlatformSpecific(PlatformSpecificBase): 216 osx_version = os.uname()[2].split('.') 217 TIOCSBRK = 0x2000747B # _IO('t', 123) 218 TIOCCBRK = 0x2000747A # _IO('t', 122) 219 220 # Tiger or above can support arbitrary serial speeds 221 if int(osx_version[0]) >= 8: 222 def _set_special_baudrate(self, baudrate): 223 # use IOKit-specific call to set up high speeds 224 buf = array.array('i', [baudrate]) 225 fcntl.ioctl(self.fd, IOSSIOSPEED, buf, 1) 226 227 def _update_break_state(self): 228 """\ 229 Set break: Controls TXD. When active, no transmitting is possible. 230 """ 231 if self._break_state: 232 fcntl.ioctl(self.fd, PlatformSpecific.TIOCSBRK) 233 else: 234 fcntl.ioctl(self.fd, PlatformSpecific.TIOCCBRK) 235 236elif plat[:3] == 'bsd' or \ 237 plat[:7] == 'freebsd' or \ 238 plat[:6] == 'netbsd' or \ 239 plat[:7] == 'openbsd': 240 241 class ReturnBaudrate(object): 242 def __getitem__(self, key): 243 return key 244 245 class PlatformSpecific(PlatformSpecificBase): 246 # Only tested on FreeBSD: 247 # The baud rate may be passed in as 248 # a literal value. 249 BAUDRATE_CONSTANTS = ReturnBaudrate() 250 251 TIOCSBRK = 0x2000747B # _IO('t', 123) 252 TIOCCBRK = 0x2000747A # _IO('t', 122) 253 254 255 def _update_break_state(self): 256 """\ 257 Set break: Controls TXD. When active, no transmitting is possible. 258 """ 259 if self._break_state: 260 fcntl.ioctl(self.fd, PlatformSpecific.TIOCSBRK) 261 else: 262 fcntl.ioctl(self.fd, PlatformSpecific.TIOCCBRK) 263 264else: 265 class PlatformSpecific(PlatformSpecificBase): 266 pass 267 268 269# load some constants for later use. 270# try to use values from termios, use defaults from linux otherwise 271TIOCMGET = getattr(termios, 'TIOCMGET', 0x5415) 272TIOCMBIS = getattr(termios, 'TIOCMBIS', 0x5416) 273TIOCMBIC = getattr(termios, 'TIOCMBIC', 0x5417) 274TIOCMSET = getattr(termios, 'TIOCMSET', 0x5418) 275 276# TIOCM_LE = getattr(termios, 'TIOCM_LE', 0x001) 277TIOCM_DTR = getattr(termios, 'TIOCM_DTR', 0x002) 278TIOCM_RTS = getattr(termios, 'TIOCM_RTS', 0x004) 279# TIOCM_ST = getattr(termios, 'TIOCM_ST', 0x008) 280# TIOCM_SR = getattr(termios, 'TIOCM_SR', 0x010) 281 282TIOCM_CTS = getattr(termios, 'TIOCM_CTS', 0x020) 283TIOCM_CAR = getattr(termios, 'TIOCM_CAR', 0x040) 284TIOCM_RNG = getattr(termios, 'TIOCM_RNG', 0x080) 285TIOCM_DSR = getattr(termios, 'TIOCM_DSR', 0x100) 286TIOCM_CD = getattr(termios, 'TIOCM_CD', TIOCM_CAR) 287TIOCM_RI = getattr(termios, 'TIOCM_RI', TIOCM_RNG) 288# TIOCM_OUT1 = getattr(termios, 'TIOCM_OUT1', 0x2000) 289# TIOCM_OUT2 = getattr(termios, 'TIOCM_OUT2', 0x4000) 290if hasattr(termios, 'TIOCINQ'): 291 TIOCINQ = termios.TIOCINQ 292else: 293 TIOCINQ = getattr(termios, 'FIONREAD', 0x541B) 294TIOCOUTQ = getattr(termios, 'TIOCOUTQ', 0x5411) 295 296TIOCM_zero_str = struct.pack('I', 0) 297TIOCM_RTS_str = struct.pack('I', TIOCM_RTS) 298TIOCM_DTR_str = struct.pack('I', TIOCM_DTR) 299 300TIOCSBRK = getattr(termios, 'TIOCSBRK', 0x5427) 301TIOCCBRK = getattr(termios, 'TIOCCBRK', 0x5428) 302 303 304class Serial(SerialBase, PlatformSpecific): 305 """\ 306 Serial port class POSIX implementation. Serial port configuration is 307 done with termios and fcntl. Runs on Linux and many other Un*x like 308 systems. 309 """ 310 311 def open(self): 312 """\ 313 Open port with current settings. This may throw a SerialException 314 if the port cannot be opened.""" 315 if self._port is None: 316 raise SerialException("Port must be configured before it can be used.") 317 if self.is_open: 318 raise SerialException("Port is already open.") 319 self.fd = None 320 # open 321 try: 322 self.fd = os.open(self.portstr, os.O_RDWR | os.O_NOCTTY | os.O_NONBLOCK) 323 except OSError as msg: 324 self.fd = None 325 raise SerialException(msg.errno, "could not open port {}: {}".format(self._port, msg)) 326 #~ fcntl.fcntl(self.fd, fcntl.F_SETFL, 0) # set blocking 327 328 self.pipe_abort_read_r, self.pipe_abort_read_w = None, None 329 self.pipe_abort_write_r, self.pipe_abort_write_w = None, None 330 331 try: 332 self._reconfigure_port(force_update=True) 333 334 try: 335 if not self._dsrdtr: 336 self._update_dtr_state() 337 if not self._rtscts: 338 self._update_rts_state() 339 except IOError as e: 340 # ignore Invalid argument and Inappropriate ioctl 341 if e.errno not in (errno.EINVAL, errno.ENOTTY): 342 raise 343 344 self._reset_input_buffer() 345 346 self.pipe_abort_read_r, self.pipe_abort_read_w = os.pipe() 347 self.pipe_abort_write_r, self.pipe_abort_write_w = os.pipe() 348 fcntl.fcntl(self.pipe_abort_read_r, fcntl.F_SETFL, os.O_NONBLOCK) 349 fcntl.fcntl(self.pipe_abort_write_r, fcntl.F_SETFL, os.O_NONBLOCK) 350 except BaseException: 351 try: 352 os.close(self.fd) 353 except Exception: 354 # ignore any exception when closing the port 355 # also to keep original exception that happened when setting up 356 pass 357 self.fd = None 358 359 if self.pipe_abort_read_w is not None: 360 os.close(self.pipe_abort_read_w) 361 self.pipe_abort_read_w = None 362 if self.pipe_abort_read_r is not None: 363 os.close(self.pipe_abort_read_r) 364 self.pipe_abort_read_r = None 365 if self.pipe_abort_write_w is not None: 366 os.close(self.pipe_abort_write_w) 367 self.pipe_abort_write_w = None 368 if self.pipe_abort_write_r is not None: 369 os.close(self.pipe_abort_write_r) 370 self.pipe_abort_write_r = None 371 372 raise 373 374 self.is_open = True 375 376 def _reconfigure_port(self, force_update=False): 377 """Set communication parameters on opened port.""" 378 if self.fd is None: 379 raise SerialException("Can only operate on a valid file descriptor") 380 381 # if exclusive lock is requested, create it before we modify anything else 382 if self._exclusive is not None: 383 if self._exclusive: 384 try: 385 fcntl.flock(self.fd, fcntl.LOCK_EX | fcntl.LOCK_NB) 386 except IOError as msg: 387 raise SerialException(msg.errno, "Could not exclusively lock port {}: {}".format(self._port, msg)) 388 else: 389 fcntl.flock(self.fd, fcntl.LOCK_UN) 390 391 custom_baud = None 392 393 vmin = vtime = 0 # timeout is done via select 394 if self._inter_byte_timeout is not None: 395 vmin = 1 396 vtime = int(self._inter_byte_timeout * 10) 397 try: 398 orig_attr = termios.tcgetattr(self.fd) 399 iflag, oflag, cflag, lflag, ispeed, ospeed, cc = orig_attr 400 except termios.error as msg: # if a port is nonexistent but has a /dev file, it'll fail here 401 raise SerialException("Could not configure port: {}".format(msg)) 402 # set up raw mode / no echo / binary 403 cflag |= (termios.CLOCAL | termios.CREAD) 404 lflag &= ~(termios.ICANON | termios.ECHO | termios.ECHOE | 405 termios.ECHOK | termios.ECHONL | 406 termios.ISIG | termios.IEXTEN) # |termios.ECHOPRT 407 for flag in ('ECHOCTL', 'ECHOKE'): # netbsd workaround for Erk 408 if hasattr(termios, flag): 409 lflag &= ~getattr(termios, flag) 410 411 oflag &= ~(termios.OPOST | termios.ONLCR | termios.OCRNL) 412 iflag &= ~(termios.INLCR | termios.IGNCR | termios.ICRNL | termios.IGNBRK) 413 if hasattr(termios, 'IUCLC'): 414 iflag &= ~termios.IUCLC 415 if hasattr(termios, 'PARMRK'): 416 iflag &= ~termios.PARMRK 417 418 # setup baud rate 419 try: 420 ispeed = ospeed = getattr(termios, 'B{}'.format(self._baudrate)) 421 except AttributeError: 422 try: 423 ispeed = ospeed = self.BAUDRATE_CONSTANTS[self._baudrate] 424 except KeyError: 425 #~ raise ValueError('Invalid baud rate: %r' % self._baudrate) 426 427 # See if BOTHER is defined for this platform; if it is, use 428 # this for a speed not defined in the baudrate constants list. 429 try: 430 ispeed = ospeed = BOTHER 431 except NameError: 432 # may need custom baud rate, it isn't in our list. 433 ispeed = ospeed = getattr(termios, 'B38400') 434 435 try: 436 custom_baud = int(self._baudrate) # store for later 437 except ValueError: 438 raise ValueError('Invalid baud rate: {!r}'.format(self._baudrate)) 439 else: 440 if custom_baud < 0: 441 raise ValueError('Invalid baud rate: {!r}'.format(self._baudrate)) 442 443 # setup char len 444 cflag &= ~termios.CSIZE 445 if self._bytesize == 8: 446 cflag |= termios.CS8 447 elif self._bytesize == 7: 448 cflag |= termios.CS7 449 elif self._bytesize == 6: 450 cflag |= termios.CS6 451 elif self._bytesize == 5: 452 cflag |= termios.CS5 453 else: 454 raise ValueError('Invalid char len: {!r}'.format(self._bytesize)) 455 # setup stop bits 456 if self._stopbits == serial.STOPBITS_ONE: 457 cflag &= ~(termios.CSTOPB) 458 elif self._stopbits == serial.STOPBITS_ONE_POINT_FIVE: 459 cflag |= (termios.CSTOPB) # XXX same as TWO.. there is no POSIX support for 1.5 460 elif self._stopbits == serial.STOPBITS_TWO: 461 cflag |= (termios.CSTOPB) 462 else: 463 raise ValueError('Invalid stop bit specification: {!r}'.format(self._stopbits)) 464 # setup parity 465 iflag &= ~(termios.INPCK | termios.ISTRIP) 466 if self._parity == serial.PARITY_NONE: 467 cflag &= ~(termios.PARENB | termios.PARODD | CMSPAR) 468 elif self._parity == serial.PARITY_EVEN: 469 cflag &= ~(termios.PARODD | CMSPAR) 470 cflag |= (termios.PARENB) 471 elif self._parity == serial.PARITY_ODD: 472 cflag &= ~CMSPAR 473 cflag |= (termios.PARENB | termios.PARODD) 474 elif self._parity == serial.PARITY_MARK and CMSPAR: 475 cflag |= (termios.PARENB | CMSPAR | termios.PARODD) 476 elif self._parity == serial.PARITY_SPACE and CMSPAR: 477 cflag |= (termios.PARENB | CMSPAR) 478 cflag &= ~(termios.PARODD) 479 else: 480 raise ValueError('Invalid parity: {!r}'.format(self._parity)) 481 # setup flow control 482 # xonxoff 483 if hasattr(termios, 'IXANY'): 484 if self._xonxoff: 485 iflag |= (termios.IXON | termios.IXOFF) # |termios.IXANY) 486 else: 487 iflag &= ~(termios.IXON | termios.IXOFF | termios.IXANY) 488 else: 489 if self._xonxoff: 490 iflag |= (termios.IXON | termios.IXOFF) 491 else: 492 iflag &= ~(termios.IXON | termios.IXOFF) 493 # rtscts 494 if hasattr(termios, 'CRTSCTS'): 495 if self._rtscts: 496 cflag |= (termios.CRTSCTS) 497 else: 498 cflag &= ~(termios.CRTSCTS) 499 elif hasattr(termios, 'CNEW_RTSCTS'): # try it with alternate constant name 500 if self._rtscts: 501 cflag |= (termios.CNEW_RTSCTS) 502 else: 503 cflag &= ~(termios.CNEW_RTSCTS) 504 # XXX should there be a warning if setting up rtscts (and xonxoff etc) fails?? 505 506 # buffer 507 # vmin "minimal number of characters to be read. 0 for non blocking" 508 if vmin < 0 or vmin > 255: 509 raise ValueError('Invalid vmin: {!r}'.format(vmin)) 510 cc[termios.VMIN] = vmin 511 # vtime 512 if vtime < 0 or vtime > 255: 513 raise ValueError('Invalid vtime: {!r}'.format(vtime)) 514 cc[termios.VTIME] = vtime 515 # activate settings 516 if force_update or [iflag, oflag, cflag, lflag, ispeed, ospeed, cc] != orig_attr: 517 termios.tcsetattr( 518 self.fd, 519 termios.TCSANOW, 520 [iflag, oflag, cflag, lflag, ispeed, ospeed, cc]) 521 522 # apply custom baud rate, if any 523 if custom_baud is not None: 524 self._set_special_baudrate(custom_baud) 525 526 if self._rs485_mode is not None: 527 self._set_rs485_mode(self._rs485_mode) 528 529 def close(self): 530 """Close port""" 531 if self.is_open: 532 if self.fd is not None: 533 os.close(self.fd) 534 self.fd = None 535 os.close(self.pipe_abort_read_w) 536 os.close(self.pipe_abort_read_r) 537 os.close(self.pipe_abort_write_w) 538 os.close(self.pipe_abort_write_r) 539 self.pipe_abort_read_r, self.pipe_abort_read_w = None, None 540 self.pipe_abort_write_r, self.pipe_abort_write_w = None, None 541 self.is_open = False 542 543 # - - - - - - - - - - - - - - - - - - - - - - - - 544 545 @property 546 def in_waiting(self): 547 """Return the number of bytes currently in the input buffer.""" 548 #~ s = fcntl.ioctl(self.fd, termios.FIONREAD, TIOCM_zero_str) 549 s = fcntl.ioctl(self.fd, TIOCINQ, TIOCM_zero_str) 550 return struct.unpack('I', s)[0] 551 552 # select based implementation, proved to work on many systems 553 def read(self, size=1): 554 """\ 555 Read size bytes from the serial port. If a timeout is set it may 556 return less characters as requested. With no timeout it will block 557 until the requested number of bytes is read. 558 """ 559 if not self.is_open: 560 raise PortNotOpenError() 561 read = bytearray() 562 timeout = Timeout(self._timeout) 563 while len(read) < size: 564 try: 565 ready, _, _ = select.select([self.fd, self.pipe_abort_read_r], [], [], timeout.time_left()) 566 if self.pipe_abort_read_r in ready: 567 os.read(self.pipe_abort_read_r, 1000) 568 break 569 # If select was used with a timeout, and the timeout occurs, it 570 # returns with empty lists -> thus abort read operation. 571 # For timeout == 0 (non-blocking operation) also abort when 572 # there is nothing to read. 573 if not ready: 574 break # timeout 575 buf = os.read(self.fd, size - len(read)) 576 except OSError as e: 577 # this is for Python 3.x where select.error is a subclass of 578 # OSError ignore BlockingIOErrors and EINTR. other errors are shown 579 # https://www.python.org/dev/peps/pep-0475. 580 if e.errno not in (errno.EAGAIN, errno.EALREADY, errno.EWOULDBLOCK, errno.EINPROGRESS, errno.EINTR): 581 raise SerialException('read failed: {}'.format(e)) 582 except select.error as e: 583 # this is for Python 2.x 584 # ignore BlockingIOErrors and EINTR. all errors are shown 585 # see also http://www.python.org/dev/peps/pep-3151/#select 586 if e[0] not in (errno.EAGAIN, errno.EALREADY, errno.EWOULDBLOCK, errno.EINPROGRESS, errno.EINTR): 587 raise SerialException('read failed: {}'.format(e)) 588 else: 589 # read should always return some data as select reported it was 590 # ready to read when we get to this point. 591 if not buf: 592 # Disconnected devices, at least on Linux, show the 593 # behavior that they are always ready to read immediately 594 # but reading returns nothing. 595 raise SerialException( 596 'device reports readiness to read but returned no data ' 597 '(device disconnected or multiple access on port?)') 598 read.extend(buf) 599 600 if timeout.expired(): 601 break 602 return bytes(read) 603 604 def cancel_read(self): 605 if self.is_open: 606 os.write(self.pipe_abort_read_w, b"x") 607 608 def cancel_write(self): 609 if self.is_open: 610 os.write(self.pipe_abort_write_w, b"x") 611 612 def write(self, data): 613 """Output the given byte string over the serial port.""" 614 if not self.is_open: 615 raise PortNotOpenError() 616 d = to_bytes(data) 617 tx_len = length = len(d) 618 timeout = Timeout(self._write_timeout) 619 while tx_len > 0: 620 try: 621 n = os.write(self.fd, d) 622 if timeout.is_non_blocking: 623 # Zero timeout indicates non-blocking - simply return the 624 # number of bytes of data actually written 625 return n 626 elif not timeout.is_infinite: 627 # when timeout is set, use select to wait for being ready 628 # with the time left as timeout 629 if timeout.expired(): 630 raise SerialTimeoutException('Write timeout') 631 abort, ready, _ = select.select([self.pipe_abort_write_r], [self.fd], [], timeout.time_left()) 632 if abort: 633 os.read(self.pipe_abort_write_r, 1000) 634 break 635 if not ready: 636 raise SerialTimeoutException('Write timeout') 637 else: 638 assert timeout.time_left() is None 639 # wait for write operation 640 abort, ready, _ = select.select([self.pipe_abort_write_r], [self.fd], [], None) 641 if abort: 642 os.read(self.pipe_abort_write_r, 1) 643 break 644 if not ready: 645 raise SerialException('write failed (select)') 646 d = d[n:] 647 tx_len -= n 648 except SerialException: 649 raise 650 except OSError as e: 651 # this is for Python 3.x where select.error is a subclass of 652 # OSError ignore BlockingIOErrors and EINTR. other errors are shown 653 # https://www.python.org/dev/peps/pep-0475. 654 if e.errno not in (errno.EAGAIN, errno.EALREADY, errno.EWOULDBLOCK, errno.EINPROGRESS, errno.EINTR): 655 raise SerialException('write failed: {}'.format(e)) 656 except select.error as e: 657 # this is for Python 2.x 658 # ignore BlockingIOErrors and EINTR. all errors are shown 659 # see also http://www.python.org/dev/peps/pep-3151/#select 660 if e[0] not in (errno.EAGAIN, errno.EALREADY, errno.EWOULDBLOCK, errno.EINPROGRESS, errno.EINTR): 661 raise SerialException('write failed: {}'.format(e)) 662 if not timeout.is_non_blocking and timeout.expired(): 663 raise SerialTimeoutException('Write timeout') 664 return length - len(d) 665 666 def flush(self): 667 """\ 668 Flush of file like objects. In this case, wait until all data 669 is written. 670 """ 671 if not self.is_open: 672 raise PortNotOpenError() 673 termios.tcdrain(self.fd) 674 675 def _reset_input_buffer(self): 676 """Clear input buffer, discarding all that is in the buffer.""" 677 termios.tcflush(self.fd, termios.TCIFLUSH) 678 679 def reset_input_buffer(self): 680 """Clear input buffer, discarding all that is in the buffer.""" 681 if not self.is_open: 682 raise PortNotOpenError() 683 self._reset_input_buffer() 684 685 def reset_output_buffer(self): 686 """\ 687 Clear output buffer, aborting the current output and discarding all 688 that is in the buffer. 689 """ 690 if not self.is_open: 691 raise PortNotOpenError() 692 termios.tcflush(self.fd, termios.TCOFLUSH) 693 694 def send_break(self, duration=0.25): 695 """\ 696 Send break condition. Timed, returns to idle state after given 697 duration. 698 """ 699 if not self.is_open: 700 raise PortNotOpenError() 701 termios.tcsendbreak(self.fd, int(duration / 0.25)) 702 703 def _update_rts_state(self): 704 """Set terminal status line: Request To Send""" 705 if self._rts_state: 706 fcntl.ioctl(self.fd, TIOCMBIS, TIOCM_RTS_str) 707 else: 708 fcntl.ioctl(self.fd, TIOCMBIC, TIOCM_RTS_str) 709 710 def _update_dtr_state(self): 711 """Set terminal status line: Data Terminal Ready""" 712 if self._dtr_state: 713 fcntl.ioctl(self.fd, TIOCMBIS, TIOCM_DTR_str) 714 else: 715 fcntl.ioctl(self.fd, TIOCMBIC, TIOCM_DTR_str) 716 717 @property 718 def cts(self): 719 """Read terminal status line: Clear To Send""" 720 if not self.is_open: 721 raise PortNotOpenError() 722 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str) 723 return struct.unpack('I', s)[0] & TIOCM_CTS != 0 724 725 @property 726 def dsr(self): 727 """Read terminal status line: Data Set Ready""" 728 if not self.is_open: 729 raise PortNotOpenError() 730 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str) 731 return struct.unpack('I', s)[0] & TIOCM_DSR != 0 732 733 @property 734 def ri(self): 735 """Read terminal status line: Ring Indicator""" 736 if not self.is_open: 737 raise PortNotOpenError() 738 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str) 739 return struct.unpack('I', s)[0] & TIOCM_RI != 0 740 741 @property 742 def cd(self): 743 """Read terminal status line: Carrier Detect""" 744 if not self.is_open: 745 raise PortNotOpenError() 746 s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str) 747 return struct.unpack('I', s)[0] & TIOCM_CD != 0 748 749 # - - platform specific - - - - 750 751 @property 752 def out_waiting(self): 753 """Return the number of bytes currently in the output buffer.""" 754 #~ s = fcntl.ioctl(self.fd, termios.FIONREAD, TIOCM_zero_str) 755 s = fcntl.ioctl(self.fd, TIOCOUTQ, TIOCM_zero_str) 756 return struct.unpack('I', s)[0] 757 758 def fileno(self): 759 """\ 760 For easier use of the serial port instance with select. 761 WARNING: this function is not portable to different platforms! 762 """ 763 if not self.is_open: 764 raise PortNotOpenError() 765 return self.fd 766 767 def set_input_flow_control(self, enable=True): 768 """\ 769 Manually control flow - when software flow control is enabled. 770 This will send XON (true) or XOFF (false) to the other device. 771 WARNING: this function is not portable to different platforms! 772 """ 773 if not self.is_open: 774 raise PortNotOpenError() 775 if enable: 776 termios.tcflow(self.fd, termios.TCION) 777 else: 778 termios.tcflow(self.fd, termios.TCIOFF) 779 780 def set_output_flow_control(self, enable=True): 781 """\ 782 Manually control flow of outgoing data - when hardware or software flow 783 control is enabled. 784 WARNING: this function is not portable to different platforms! 785 """ 786 if not self.is_open: 787 raise PortNotOpenError() 788 if enable: 789 termios.tcflow(self.fd, termios.TCOON) 790 else: 791 termios.tcflow(self.fd, termios.TCOOFF) 792 793 def nonblocking(self): 794 """DEPRECATED - has no use""" 795 import warnings 796 warnings.warn("nonblocking() has no effect, already nonblocking", DeprecationWarning) 797 798 799class PosixPollSerial(Serial): 800 """\ 801 Poll based read implementation. Not all systems support poll properly. 802 However this one has better handling of errors, such as a device 803 disconnecting while it's in use (e.g. USB-serial unplugged). 804 """ 805 806 def read(self, size=1): 807 """\ 808 Read size bytes from the serial port. If a timeout is set it may 809 return less characters as requested. With no timeout it will block 810 until the requested number of bytes is read. 811 """ 812 if not self.is_open: 813 raise PortNotOpenError() 814 read = bytearray() 815 timeout = Timeout(self._timeout) 816 poll = select.poll() 817 poll.register(self.fd, select.POLLIN | select.POLLERR | select.POLLHUP | select.POLLNVAL) 818 poll.register(self.pipe_abort_read_r, select.POLLIN | select.POLLERR | select.POLLHUP | select.POLLNVAL) 819 if size > 0: 820 while len(read) < size: 821 # print "\tread(): size",size, "have", len(read) #debug 822 # wait until device becomes ready to read (or something fails) 823 for fd, event in poll.poll(None if timeout.is_infinite else (timeout.time_left() * 1000)): 824 if fd == self.pipe_abort_read_r: 825 break 826 if event & (select.POLLERR | select.POLLHUP | select.POLLNVAL): 827 raise SerialException('device reports error (poll)') 828 # we don't care if it is select.POLLIN or timeout, that's 829 # handled below 830 if fd == self.pipe_abort_read_r: 831 os.read(self.pipe_abort_read_r, 1000) 832 break 833 buf = os.read(self.fd, size - len(read)) 834 read.extend(buf) 835 if timeout.expired() \ 836 or (self._inter_byte_timeout is not None and self._inter_byte_timeout > 0) and not buf: 837 break # early abort on timeout 838 return bytes(read) 839 840 841class VTIMESerial(Serial): 842 """\ 843 Implement timeout using vtime of tty device instead of using select. 844 This means that no inter character timeout can be specified and that 845 the error handling is degraded. 846 847 Overall timeout is disabled when inter-character timeout is used. 848 849 Note that this implementation does NOT support cancel_read(), it will 850 just ignore that. 851 """ 852 853 def _reconfigure_port(self, force_update=True): 854 """Set communication parameters on opened port.""" 855 super(VTIMESerial, self)._reconfigure_port() 856 fcntl.fcntl(self.fd, fcntl.F_SETFL, 0) # clear O_NONBLOCK 857 858 if self._inter_byte_timeout is not None: 859 vmin = 1 860 vtime = int(self._inter_byte_timeout * 10) 861 elif self._timeout is None: 862 vmin = 1 863 vtime = 0 864 else: 865 vmin = 0 866 vtime = int(self._timeout * 10) 867 try: 868 orig_attr = termios.tcgetattr(self.fd) 869 iflag, oflag, cflag, lflag, ispeed, ospeed, cc = orig_attr 870 except termios.error as msg: # if a port is nonexistent but has a /dev file, it'll fail here 871 raise serial.SerialException("Could not configure port: {}".format(msg)) 872 873 if vtime < 0 or vtime > 255: 874 raise ValueError('Invalid vtime: {!r}'.format(vtime)) 875 cc[termios.VTIME] = vtime 876 cc[termios.VMIN] = vmin 877 878 termios.tcsetattr( 879 self.fd, 880 termios.TCSANOW, 881 [iflag, oflag, cflag, lflag, ispeed, ospeed, cc]) 882 883 def read(self, size=1): 884 """\ 885 Read size bytes from the serial port. If a timeout is set it may 886 return less characters as requested. With no timeout it will block 887 until the requested number of bytes is read. 888 """ 889 if not self.is_open: 890 raise PortNotOpenError() 891 read = bytearray() 892 while len(read) < size: 893 buf = os.read(self.fd, size - len(read)) 894 if not buf: 895 break 896 read.extend(buf) 897 return bytes(read) 898 899 # hack to make hasattr return false 900 cancel_read = property() 901