serialposix.py 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703
  1. #!/usr/bin/env python
  2. #
  3. # Python Serial Port Extension for Win32, Linux, BSD, Jython
  4. # module for serial IO for POSIX compatible systems, like Linux
  5. # see __init__.py
  6. #
  7. # (C) 2001-2010 Chris Liechti <cliechti@gmx.net>
  8. # this is distributed under a free software license, see license.txt
  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. import sys, os, fcntl, termios, struct, select, errno, time
  15. from serial.serialutil import *
  16. # Do check the Python version as some constants have moved.
  17. if (sys.hexversion < 0x020100f0):
  18. import TERMIOS
  19. else:
  20. TERMIOS = termios
  21. if (sys.hexversion < 0x020200f0):
  22. import FCNTL
  23. else:
  24. FCNTL = fcntl
  25. # try to detect the OS so that a device can be selected...
  26. # this code block should supply a device() and set_special_baudrate() function
  27. # for the platform
  28. plat = sys.platform.lower()
  29. if plat[:5] == 'linux': # Linux (confirmed)
  30. def device(port):
  31. return '/dev/ttyS%d' % port
  32. TCGETS2 = 0x802C542A
  33. TCSETS2 = 0x402C542B
  34. BOTHER = 0o010000
  35. def set_special_baudrate(port, baudrate):
  36. # right size is 44 on x86_64, allow for some growth
  37. import array
  38. buf = array.array('i', [0] * 64)
  39. try:
  40. # get serial_struct
  41. FCNTL.ioctl(port.fd, TCGETS2, buf)
  42. # set custom speed
  43. buf[2] &= ~TERMIOS.CBAUD
  44. buf[2] |= BOTHER
  45. buf[9] = buf[10] = baudrate
  46. # set serial_struct
  47. res = FCNTL.ioctl(port.fd, TCSETS2, buf)
  48. except IOError, e:
  49. raise ValueError('Failed to set custom baud rate (%s): %s' % (baudrate, e))
  50. baudrate_constants = {
  51. 0: 0000000, # hang up
  52. 50: 0000001,
  53. 75: 0000002,
  54. 110: 0000003,
  55. 134: 0000004,
  56. 150: 0000005,
  57. 200: 0000006,
  58. 300: 0000007,
  59. 600: 0000010,
  60. 1200: 0000011,
  61. 1800: 0000012,
  62. 2400: 0000013,
  63. 4800: 0000014,
  64. 9600: 0000015,
  65. 19200: 0000016,
  66. 38400: 0000017,
  67. 57600: 0010001,
  68. 115200: 0010002,
  69. 230400: 0010003,
  70. 460800: 0010004,
  71. 500000: 0010005,
  72. 576000: 0010006,
  73. 921600: 0010007,
  74. 1000000: 0010010,
  75. 1152000: 0010011,
  76. 1500000: 0010012,
  77. 2000000: 0010013,
  78. 2500000: 0010014,
  79. 3000000: 0010015,
  80. 3500000: 0010016,
  81. 4000000: 0010017
  82. }
  83. elif plat == 'cygwin': # cygwin/win32 (confirmed)
  84. def device(port):
  85. return '/dev/com%d' % (port + 1)
  86. def set_special_baudrate(port, baudrate):
  87. raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
  88. baudrate_constants = {
  89. 128000: 0x01003,
  90. 256000: 0x01005,
  91. 500000: 0x01007,
  92. 576000: 0x01008,
  93. 921600: 0x01009,
  94. 1000000: 0x0100a,
  95. 1152000: 0x0100b,
  96. 1500000: 0x0100c,
  97. 2000000: 0x0100d,
  98. 2500000: 0x0100e,
  99. 3000000: 0x0100f
  100. }
  101. elif plat[:7] == 'openbsd': # OpenBSD
  102. def device(port):
  103. return '/dev/cua%02d' % port
  104. def set_special_baudrate(port, baudrate):
  105. raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
  106. baudrate_constants = {}
  107. elif plat[:3] == 'bsd' or \
  108. plat[:7] == 'freebsd':
  109. def device(port):
  110. return '/dev/cuad%d' % port
  111. def set_special_baudrate(port, baudrate):
  112. raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
  113. baudrate_constants = {}
  114. elif plat[:6] == 'darwin': # OS X
  115. version = os.uname()[2].split('.')
  116. # Tiger or above can support arbitrary serial speeds
  117. if int(version[0]) >= 8:
  118. def set_special_baudrate(port, baudrate):
  119. # use IOKit-specific call to set up high speeds
  120. import array, fcntl
  121. buf = array.array('i', [baudrate])
  122. IOSSIOSPEED = 0x80045402 #_IOW('T', 2, speed_t)
  123. fcntl.ioctl(port.fd, IOSSIOSPEED, buf, 1)
  124. else: # version < 8
  125. def set_special_baudrate(port, baudrate):
  126. raise ValueError("baud rate not supported")
  127. def device(port):
  128. return '/dev/cuad%d' % port
  129. baudrate_constants = {}
  130. elif plat[:6] == 'netbsd': # NetBSD 1.6 testing by Erk
  131. def device(port):
  132. return '/dev/dty%02d' % port
  133. def set_special_baudrate(port, baudrate):
  134. raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
  135. baudrate_constants = {}
  136. elif plat[:4] == 'irix': # IRIX (partially tested)
  137. def device(port):
  138. return '/dev/ttyf%d' % (port+1) #XXX different device names depending on flow control
  139. def set_special_baudrate(port, baudrate):
  140. raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
  141. baudrate_constants = {}
  142. elif plat[:2] == 'hp': # HP-UX (not tested)
  143. def device(port):
  144. return '/dev/tty%dp0' % (port+1)
  145. def set_special_baudrate(port, baudrate):
  146. raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
  147. baudrate_constants = {}
  148. elif plat[:5] == 'sunos': # Solaris/SunOS (confirmed)
  149. def device(port):
  150. return '/dev/tty%c' % (ord('a')+port)
  151. def set_special_baudrate(port, baudrate):
  152. raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
  153. baudrate_constants = {}
  154. elif plat[:3] == 'aix': # AIX
  155. def device(port):
  156. return '/dev/tty%d' % (port)
  157. def set_special_baudrate(port, baudrate):
  158. raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
  159. baudrate_constants = {}
  160. else:
  161. # platform detection has failed...
  162. sys.stderr.write("""\
  163. don't know how to number ttys on this system.
  164. ! Use an explicit path (eg /dev/ttyS1) or send this information to
  165. ! the author of this module:
  166. sys.platform = %r
  167. os.name = %r
  168. serialposix.py version = %s
  169. also add the device name of the serial port and where the
  170. counting starts for the first serial port.
  171. e.g. 'first serial port: /dev/ttyS0'
  172. and with a bit luck you can get this module running...
  173. """ % (sys.platform, os.name, VERSION))
  174. # no exception, just continue with a brave attempt to build a device name
  175. # even if the device name is not correct for the platform it has chances
  176. # to work using a string with the real device name as port parameter.
  177. def device(portum):
  178. return '/dev/ttyS%d' % portnum
  179. def set_special_baudrate(port, baudrate):
  180. raise SerialException("sorry don't know how to handle non standard baud rate on this platform")
  181. baudrate_constants = {}
  182. #~ raise Exception, "this module does not run on this platform, sorry."
  183. # whats up with "aix", "beos", ....
  184. # they should work, just need to know the device names.
  185. # load some constants for later use.
  186. # try to use values from TERMIOS, use defaults from linux otherwise
  187. TIOCMGET = hasattr(TERMIOS, 'TIOCMGET') and TERMIOS.TIOCMGET or 0x5415
  188. TIOCMBIS = hasattr(TERMIOS, 'TIOCMBIS') and TERMIOS.TIOCMBIS or 0x5416
  189. TIOCMBIC = hasattr(TERMIOS, 'TIOCMBIC') and TERMIOS.TIOCMBIC or 0x5417
  190. TIOCMSET = hasattr(TERMIOS, 'TIOCMSET') and TERMIOS.TIOCMSET or 0x5418
  191. #TIOCM_LE = hasattr(TERMIOS, 'TIOCM_LE') and TERMIOS.TIOCM_LE or 0x001
  192. TIOCM_DTR = hasattr(TERMIOS, 'TIOCM_DTR') and TERMIOS.TIOCM_DTR or 0x002
  193. TIOCM_RTS = hasattr(TERMIOS, 'TIOCM_RTS') and TERMIOS.TIOCM_RTS or 0x004
  194. #TIOCM_ST = hasattr(TERMIOS, 'TIOCM_ST') and TERMIOS.TIOCM_ST or 0x008
  195. #TIOCM_SR = hasattr(TERMIOS, 'TIOCM_SR') and TERMIOS.TIOCM_SR or 0x010
  196. TIOCM_CTS = hasattr(TERMIOS, 'TIOCM_CTS') and TERMIOS.TIOCM_CTS or 0x020
  197. TIOCM_CAR = hasattr(TERMIOS, 'TIOCM_CAR') and TERMIOS.TIOCM_CAR or 0x040
  198. TIOCM_RNG = hasattr(TERMIOS, 'TIOCM_RNG') and TERMIOS.TIOCM_RNG or 0x080
  199. TIOCM_DSR = hasattr(TERMIOS, 'TIOCM_DSR') and TERMIOS.TIOCM_DSR or 0x100
  200. TIOCM_CD = hasattr(TERMIOS, 'TIOCM_CD') and TERMIOS.TIOCM_CD or TIOCM_CAR
  201. TIOCM_RI = hasattr(TERMIOS, 'TIOCM_RI') and TERMIOS.TIOCM_RI or TIOCM_RNG
  202. #TIOCM_OUT1 = hasattr(TERMIOS, 'TIOCM_OUT1') and TERMIOS.TIOCM_OUT1 or 0x2000
  203. #TIOCM_OUT2 = hasattr(TERMIOS, 'TIOCM_OUT2') and TERMIOS.TIOCM_OUT2 or 0x4000
  204. if hasattr(TERMIOS, 'TIOCINQ'):
  205. TIOCINQ = TERMIOS.TIOCINQ
  206. else:
  207. TIOCINQ = hasattr(TERMIOS, 'FIONREAD') and TERMIOS.FIONREAD or 0x541B
  208. TIOCOUTQ = hasattr(TERMIOS, 'TIOCOUTQ') and TERMIOS.TIOCOUTQ or 0x5411
  209. TIOCM_zero_str = struct.pack('I', 0)
  210. TIOCM_RTS_str = struct.pack('I', TIOCM_RTS)
  211. TIOCM_DTR_str = struct.pack('I', TIOCM_DTR)
  212. TIOCSBRK = hasattr(TERMIOS, 'TIOCSBRK') and TERMIOS.TIOCSBRK or 0x5427
  213. TIOCCBRK = hasattr(TERMIOS, 'TIOCCBRK') and TERMIOS.TIOCCBRK or 0x5428
  214. class PosixSerial(SerialBase):
  215. """Serial port class POSIX implementation. Serial port configuration is
  216. done with termios and fcntl. Runs on Linux and many other Un*x like
  217. systems."""
  218. def open(self):
  219. """Open port with current settings. This may throw a SerialException
  220. if the port cannot be opened."""
  221. if self._port is None:
  222. raise SerialException("Port must be configured before it can be used.")
  223. if self._isOpen:
  224. raise SerialException("Port is already open.")
  225. self.fd = None
  226. # open
  227. try:
  228. self.fd = os.open(self.portstr, os.O_RDWR|os.O_NOCTTY|os.O_NONBLOCK)
  229. except IOError, msg:
  230. self.fd = None
  231. raise SerialException(msg.errno, "could not open port %s: %s" % (self._port, msg))
  232. #~ fcntl.fcntl(self.fd, FCNTL.F_SETFL, 0) # set blocking
  233. try:
  234. self._reconfigurePort()
  235. except:
  236. try:
  237. os.close(self.fd)
  238. except:
  239. # ignore any exception when closing the port
  240. # also to keep original exception that happened when setting up
  241. pass
  242. self.fd = None
  243. raise
  244. else:
  245. self._isOpen = True
  246. self.flushInput()
  247. def _reconfigurePort(self):
  248. """Set communication parameters on opened port."""
  249. if self.fd is None:
  250. raise SerialException("Can only operate on a valid file descriptor")
  251. custom_baud = None
  252. vmin = vtime = 0 # timeout is done via select
  253. if self._interCharTimeout is not None:
  254. vmin = 1
  255. vtime = int(self._interCharTimeout * 10)
  256. try:
  257. orig_attr = termios.tcgetattr(self.fd)
  258. iflag, oflag, cflag, lflag, ispeed, ospeed, cc = orig_attr
  259. except termios.error, msg: # if a port is nonexistent but has a /dev file, it'll fail here
  260. raise SerialException("Could not configure port: %s" % msg)
  261. # set up raw mode / no echo / binary
  262. cflag |= (TERMIOS.CLOCAL|TERMIOS.CREAD)
  263. lflag &= ~(TERMIOS.ICANON|TERMIOS.ECHO|TERMIOS.ECHOE|TERMIOS.ECHOK|TERMIOS.ECHONL|
  264. TERMIOS.ISIG|TERMIOS.IEXTEN) #|TERMIOS.ECHOPRT
  265. for flag in ('ECHOCTL', 'ECHOKE'): # netbsd workaround for Erk
  266. if hasattr(TERMIOS, flag):
  267. lflag &= ~getattr(TERMIOS, flag)
  268. oflag &= ~(TERMIOS.OPOST)
  269. iflag &= ~(TERMIOS.INLCR|TERMIOS.IGNCR|TERMIOS.ICRNL|TERMIOS.IGNBRK)
  270. if hasattr(TERMIOS, 'IUCLC'):
  271. iflag &= ~TERMIOS.IUCLC
  272. if hasattr(TERMIOS, 'PARMRK'):
  273. iflag &= ~TERMIOS.PARMRK
  274. # setup baud rate
  275. try:
  276. ispeed = ospeed = getattr(TERMIOS, 'B%s' % (self._baudrate))
  277. except AttributeError:
  278. try:
  279. ispeed = ospeed = baudrate_constants[self._baudrate]
  280. except KeyError:
  281. #~ raise ValueError('Invalid baud rate: %r' % self._baudrate)
  282. # may need custom baud rate, it isn't in our list.
  283. ispeed = ospeed = getattr(TERMIOS, 'B38400')
  284. try:
  285. custom_baud = int(self._baudrate) # store for later
  286. except ValueError:
  287. raise ValueError('Invalid baud rate: %r' % self._baudrate)
  288. else:
  289. if custom_baud < 0:
  290. raise ValueError('Invalid baud rate: %r' % self._baudrate)
  291. # setup char len
  292. cflag &= ~TERMIOS.CSIZE
  293. if self._bytesize == 8:
  294. cflag |= TERMIOS.CS8
  295. elif self._bytesize == 7:
  296. cflag |= TERMIOS.CS7
  297. elif self._bytesize == 6:
  298. cflag |= TERMIOS.CS6
  299. elif self._bytesize == 5:
  300. cflag |= TERMIOS.CS5
  301. else:
  302. raise ValueError('Invalid char len: %r' % self._bytesize)
  303. # setup stopbits
  304. if self._stopbits == STOPBITS_ONE:
  305. cflag &= ~(TERMIOS.CSTOPB)
  306. elif self._stopbits == STOPBITS_ONE_POINT_FIVE:
  307. cflag |= (TERMIOS.CSTOPB) # XXX same as TWO.. there is no POSIX support for 1.5
  308. elif self._stopbits == STOPBITS_TWO:
  309. cflag |= (TERMIOS.CSTOPB)
  310. else:
  311. raise ValueError('Invalid stop bit specification: %r' % self._stopbits)
  312. # setup parity
  313. iflag &= ~(TERMIOS.INPCK|TERMIOS.ISTRIP)
  314. if self._parity == PARITY_NONE:
  315. cflag &= ~(TERMIOS.PARENB|TERMIOS.PARODD)
  316. elif self._parity == PARITY_EVEN:
  317. cflag &= ~(TERMIOS.PARODD)
  318. cflag |= (TERMIOS.PARENB)
  319. elif self._parity == PARITY_ODD:
  320. cflag |= (TERMIOS.PARENB|TERMIOS.PARODD)
  321. else:
  322. raise ValueError('Invalid parity: %r' % self._parity)
  323. # setup flow control
  324. # xonxoff
  325. if hasattr(TERMIOS, 'IXANY'):
  326. if self._xonxoff:
  327. iflag |= (TERMIOS.IXON|TERMIOS.IXOFF) #|TERMIOS.IXANY)
  328. else:
  329. iflag &= ~(TERMIOS.IXON|TERMIOS.IXOFF|TERMIOS.IXANY)
  330. else:
  331. if self._xonxoff:
  332. iflag |= (TERMIOS.IXON|TERMIOS.IXOFF)
  333. else:
  334. iflag &= ~(TERMIOS.IXON|TERMIOS.IXOFF)
  335. # rtscts
  336. if hasattr(TERMIOS, 'CRTSCTS'):
  337. if self._rtscts:
  338. cflag |= (TERMIOS.CRTSCTS)
  339. else:
  340. cflag &= ~(TERMIOS.CRTSCTS)
  341. elif hasattr(TERMIOS, 'CNEW_RTSCTS'): # try it with alternate constant name
  342. if self._rtscts:
  343. cflag |= (TERMIOS.CNEW_RTSCTS)
  344. else:
  345. cflag &= ~(TERMIOS.CNEW_RTSCTS)
  346. # XXX should there be a warning if setting up rtscts (and xonxoff etc) fails??
  347. # buffer
  348. # vmin "minimal number of characters to be read. = for non blocking"
  349. if vmin < 0 or vmin > 255:
  350. raise ValueError('Invalid vmin: %r ' % vmin)
  351. cc[TERMIOS.VMIN] = vmin
  352. # vtime
  353. if vtime < 0 or vtime > 255:
  354. raise ValueError('Invalid vtime: %r' % vtime)
  355. cc[TERMIOS.VTIME] = vtime
  356. # activate settings
  357. if [iflag, oflag, cflag, lflag, ispeed, ospeed, cc] != orig_attr:
  358. termios.tcsetattr(self.fd, TERMIOS.TCSANOW, [iflag, oflag, cflag, lflag, ispeed, ospeed, cc])
  359. # apply custom baud rate, if any
  360. if custom_baud is not None:
  361. set_special_baudrate(self, custom_baud)
  362. def close(self):
  363. """Close port"""
  364. if self._isOpen:
  365. if self.fd is not None:
  366. os.close(self.fd)
  367. self.fd = None
  368. self._isOpen = False
  369. def makeDeviceName(self, port):
  370. return device(port)
  371. # - - - - - - - - - - - - - - - - - - - - - - - -
  372. def inWaiting(self):
  373. """Return the number of characters currently in the input buffer."""
  374. #~ s = fcntl.ioctl(self.fd, TERMIOS.FIONREAD, TIOCM_zero_str)
  375. s = fcntl.ioctl(self.fd, TIOCINQ, TIOCM_zero_str)
  376. return struct.unpack('I',s)[0]
  377. # select based implementation, proved to work on many systems
  378. def read(self, size=1):
  379. """Read size bytes from the serial port. If a timeout is set it may
  380. return less characters as requested. With no timeout it will block
  381. until the requested number of bytes is read."""
  382. if not self._isOpen: raise portNotOpenError
  383. read = bytearray()
  384. while len(read) < size:
  385. try:
  386. ready,_,_ = select.select([self.fd],[],[], self._timeout)
  387. # If select was used with a timeout, and the timeout occurs, it
  388. # returns with empty lists -> thus abort read operation.
  389. # For timeout == 0 (non-blocking operation) also abort when there
  390. # is nothing to read.
  391. if not ready:
  392. break # timeout
  393. buf = os.read(self.fd, size-len(read))
  394. # read should always return some data as select reported it was
  395. # ready to read when we get to this point.
  396. if not buf:
  397. # Disconnected devices, at least on Linux, show the
  398. # behavior that they are always ready to read immediately
  399. # but reading returns nothing.
  400. raise SerialException('device reports readiness to read but returned no data (device disconnected or multiple access on port?)')
  401. read.extend(buf)
  402. except select.error, e:
  403. # ignore EAGAIN errors. all other errors are shown
  404. # see also http://www.python.org/dev/peps/pep-3151/#select
  405. if e[0] != errno.EAGAIN:
  406. raise SerialException('read failed: %s' % (e,))
  407. except OSError, e:
  408. # ignore EAGAIN errors. all other errors are shown
  409. if e.errno != errno.EAGAIN:
  410. raise SerialException('read failed: %s' % (e,))
  411. return bytes(read)
  412. def write(self, data):
  413. """Output the given string over the serial port."""
  414. if not self._isOpen: raise portNotOpenError
  415. d = to_bytes(data)
  416. tx_len = len(d)
  417. if self._writeTimeout is not None and self._writeTimeout > 0:
  418. timeout = time.time() + self._writeTimeout
  419. else:
  420. timeout = None
  421. while tx_len > 0:
  422. try:
  423. n = os.write(self.fd, d)
  424. if timeout:
  425. # when timeout is set, use select to wait for being ready
  426. # with the time left as timeout
  427. timeleft = timeout - time.time()
  428. if timeleft < 0:
  429. raise writeTimeoutError
  430. _, ready, _ = select.select([], [self.fd], [], timeleft)
  431. if not ready:
  432. raise writeTimeoutError
  433. else:
  434. # wait for write operation
  435. _, ready, _ = select.select([], [self.fd], [], None)
  436. if not ready:
  437. raise SerialException('write failed (select)')
  438. d = d[n:]
  439. tx_len -= n
  440. except OSError, v:
  441. if v.errno != errno.EAGAIN:
  442. raise SerialException('write failed: %s' % (v,))
  443. return len(data)
  444. def flush(self):
  445. """Flush of file like objects. In this case, wait until all data
  446. is written."""
  447. self.drainOutput()
  448. def flushInput(self):
  449. """Clear input buffer, discarding all that is in the buffer."""
  450. if not self._isOpen: raise portNotOpenError
  451. termios.tcflush(self.fd, TERMIOS.TCIFLUSH)
  452. def flushOutput(self):
  453. """Clear output buffer, aborting the current output and
  454. discarding all that is in the buffer."""
  455. if not self._isOpen: raise portNotOpenError
  456. termios.tcflush(self.fd, TERMIOS.TCOFLUSH)
  457. def sendBreak(self, duration=0.25):
  458. """Send break condition. Timed, returns to idle state after given duration."""
  459. if not self._isOpen: raise portNotOpenError
  460. termios.tcsendbreak(self.fd, int(duration/0.25))
  461. def setBreak(self, level=1):
  462. """Set break: Controls TXD. When active, no transmitting is possible."""
  463. if self.fd is None: raise portNotOpenError
  464. if level:
  465. fcntl.ioctl(self.fd, TIOCSBRK)
  466. else:
  467. fcntl.ioctl(self.fd, TIOCCBRK)
  468. def setRTS(self, level=1):
  469. """Set terminal status line: Request To Send"""
  470. if not self._isOpen: raise portNotOpenError
  471. if level:
  472. fcntl.ioctl(self.fd, TIOCMBIS, TIOCM_RTS_str)
  473. else:
  474. fcntl.ioctl(self.fd, TIOCMBIC, TIOCM_RTS_str)
  475. def setDTR(self, level=1):
  476. """Set terminal status line: Data Terminal Ready"""
  477. if not self._isOpen: raise portNotOpenError
  478. if level:
  479. fcntl.ioctl(self.fd, TIOCMBIS, TIOCM_DTR_str)
  480. else:
  481. fcntl.ioctl(self.fd, TIOCMBIC, TIOCM_DTR_str)
  482. def getCTS(self):
  483. """Read terminal status line: Clear To Send"""
  484. if not self._isOpen: raise portNotOpenError
  485. s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
  486. return struct.unpack('I',s)[0] & TIOCM_CTS != 0
  487. def getDSR(self):
  488. """Read terminal status line: Data Set Ready"""
  489. if not self._isOpen: raise portNotOpenError
  490. s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
  491. return struct.unpack('I',s)[0] & TIOCM_DSR != 0
  492. def getRI(self):
  493. """Read terminal status line: Ring Indicator"""
  494. if not self._isOpen: raise portNotOpenError
  495. s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
  496. return struct.unpack('I',s)[0] & TIOCM_RI != 0
  497. def getCD(self):
  498. """Read terminal status line: Carrier Detect"""
  499. if not self._isOpen: raise portNotOpenError
  500. s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
  501. return struct.unpack('I',s)[0] & TIOCM_CD != 0
  502. # - - platform specific - - - -
  503. def outWaiting(self):
  504. """Return the number of characters currently in the output buffer."""
  505. #~ s = fcntl.ioctl(self.fd, TERMIOS.FIONREAD, TIOCM_zero_str)
  506. s = fcntl.ioctl(self.fd, TIOCOUTQ, TIOCM_zero_str)
  507. return struct.unpack('I',s)[0]
  508. def drainOutput(self):
  509. """internal - not portable!"""
  510. if not self._isOpen: raise portNotOpenError
  511. termios.tcdrain(self.fd)
  512. def nonblocking(self):
  513. """internal - not portable!"""
  514. if not self._isOpen: raise portNotOpenError
  515. fcntl.fcntl(self.fd, FCNTL.F_SETFL, os.O_NONBLOCK)
  516. def fileno(self):
  517. """\
  518. For easier use of the serial port instance with select.
  519. WARNING: this function is not portable to different platforms!
  520. """
  521. if not self._isOpen: raise portNotOpenError
  522. return self.fd
  523. def setXON(self, level=True):
  524. """\
  525. Manually control flow - when software flow control is enabled.
  526. This will send XON (true) and XOFF (false) to the other device.
  527. WARNING: this function is not portable to different platforms!
  528. """
  529. if not self.hComPort: raise portNotOpenError
  530. if enable:
  531. termios.tcflow(self.fd, TERMIOS.TCION)
  532. else:
  533. termios.tcflow(self.fd, TERMIOS.TCIOFF)
  534. def flowControlOut(self, enable):
  535. """\
  536. Manually control flow of outgoing data - when hardware or software flow
  537. control is enabled.
  538. WARNING: this function is not portable to different platforms!
  539. """
  540. if not self._isOpen: raise portNotOpenError
  541. if enable:
  542. termios.tcflow(self.fd, TERMIOS.TCOON)
  543. else:
  544. termios.tcflow(self.fd, TERMIOS.TCOOFF)
  545. # assemble Serial class with the platform specifc implementation and the base
  546. # for file-like behavior. for Python 2.6 and newer, that provide the new I/O
  547. # library, derrive from io.RawIOBase
  548. try:
  549. import io
  550. except ImportError:
  551. # classic version with our own file-like emulation
  552. class Serial(PosixSerial, FileLike):
  553. pass
  554. else:
  555. # io library present
  556. class Serial(PosixSerial, io.RawIOBase):
  557. pass
  558. class PosixPollSerial(Serial):
  559. """poll based read implementation. not all systems support poll properly.
  560. however this one has better handling of errors, such as a device
  561. disconnecting while it's in use (e.g. USB-serial unplugged)"""
  562. def read(self, size=1):
  563. """Read size bytes from the serial port. If a timeout is set it may
  564. return less characters as requested. With no timeout it will block
  565. until the requested number of bytes is read."""
  566. if self.fd is None: raise portNotOpenError
  567. read = bytearray()
  568. poll = select.poll()
  569. poll.register(self.fd, select.POLLIN|select.POLLERR|select.POLLHUP|select.POLLNVAL)
  570. if size > 0:
  571. while len(read) < size:
  572. # print "\tread(): size",size, "have", len(read) #debug
  573. # wait until device becomes ready to read (or something fails)
  574. for fd, event in poll.poll(self._timeout*1000):
  575. if event & (select.POLLERR|select.POLLHUP|select.POLLNVAL):
  576. raise SerialException('device reports error (poll)')
  577. # we don't care if it is select.POLLIN or timeout, that's
  578. # handled below
  579. buf = os.read(self.fd, size - len(read))
  580. read.extend(buf)
  581. if ((self._timeout is not None and self._timeout >= 0) or
  582. (self._interCharTimeout is not None and self._interCharTimeout > 0)) and not buf:
  583. break # early abort on timeout
  584. return bytes(read)
  585. if __name__ == '__main__':
  586. s = Serial(0,
  587. baudrate=19200, # baud rate
  588. bytesize=EIGHTBITS, # number of data bits
  589. parity=PARITY_EVEN, # enable parity checking
  590. stopbits=STOPBITS_ONE, # number of stop bits
  591. timeout=3, # set a timeout value, None for waiting forever
  592. xonxoff=0, # enable software flow control
  593. rtscts=0, # enable RTS/CTS flow control
  594. )
  595. s.setRTS(1)
  596. s.setDTR(1)
  597. s.flushInput()
  598. s.flushOutput()
  599. s.write('hello')
  600. sys.stdout.write('%r\n' % s.read(5))
  601. sys.stdout.write('%s\n' % s.inWaiting())
  602. del s