serialposix.py 34 KB

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