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