summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcliechti <cliechti@f19166aa-fa4f-0410-85c2-fa1106f25c8a>2011-08-05 03:55:12 +0000
committercliechti <cliechti@f19166aa-fa4f-0410-85c2-fa1106f25c8a>2011-08-05 03:55:12 +0000
commitccdafe22ec795997484d2ccfaa7e3a5b60a5b80d (patch)
treef4260feaa6c8a63e735049f413e4b965fc1eec5e
parentf3e5077d7a47ad81132c7864656a632a2ab787a3 (diff)
downloadpyserial-ccdafe22ec795997484d2ccfaa7e3a5b60a5b80d.tar.gz
- add serial.tools.list_ports, implement platform detection code and a main routine
- add code from 2912349 (scan for mac) git-svn-id: http://svn.code.sf.net/p/pyserial/code/trunk/pyserial@408 f19166aa-fa4f-0410-85c2-fa1106f25c8a
-rw-r--r--CHANGES.txt2
-rw-r--r--documentation/shortintro.rst23
-rw-r--r--serial/tools/list_ports.py60
-rw-r--r--serial/tools/list_ports_posix.py89
-rw-r--r--serial/tools/list_ports_windows.py2
5 files changed, 170 insertions, 6 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index fef89f1..77bfe58 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -404,6 +404,7 @@ New Features:
- Moved some of the examples to serial.tools so that they can be used
with ``python -m``
+- serial port enumeration now included as ``serial.tools.list_ports``
- URL handers for ``serial_for_url`` are now imported dynamically. This allows
to add protocols w/o editing files. The list
``serial.protocol_handler_packages`` can be used to add or remove user
@@ -418,6 +419,7 @@ Bugfixes:
Bugfixes (posix):
- [Patch 3316943] Avoid unneeded termios.tcsetattr calls in serialposix.py
+- [Patch 2912349] Serial Scan as a Module with Mac Support
Bugfixes (win32):
diff --git a/documentation/shortintro.rst b/documentation/shortintro.rst
index 01d9943..b9a8a8c 100644
--- a/documentation/shortintro.rst
+++ b/documentation/shortintro.rst
@@ -79,3 +79,26 @@ mode, it is advised to use io.TextIOWrapper_::
.. _io.TextIOWrapper: http://docs.python.org/library/io.html#io.TextIOWrapper
+
+
+Testing ports
+=============
+Listing ports
+-------------
+``python -m serial.tools.list_ports`` will print a list of available ports. It
+is also possible to add a regexp as first argument and the list will only
+include entries that matched.
+
+.. note::
+
+ The enumeration may not work on all operating systems. It may be
+ incomplete, list unavailable ports or may lack detailed descriptions of the
+ ports.
+
+.. versionadded: 2.6
+
+Accessing ports
+---------------
+pySerial includes a small terminal console based terminal program called
+:ref:`miniterm`. It ca be started with ``python -m serial.tools.miniterm <port name>``
+(use option ``-h`` to get a listing of all options).
diff --git a/serial/tools/list_ports.py b/serial/tools/list_ports.py
new file mode 100644
index 0000000..1eb0478
--- /dev/null
+++ b/serial/tools/list_ports.py
@@ -0,0 +1,60 @@
+#!/usr/bin/env python
+
+# portable serial port access with python
+# this is a wrapper module for different platform implementations of the
+# port enumeration feature
+#
+# (C) 2011 Chris Liechti <cliechti@gmx.net>
+# this is distributed under a free software license, see license.txt
+
+"""\
+This module will provide a function called comports that returns an
+iterable (generator or list) that will enumerate available com ports. Note that
+on some systems non-existent ports may be listed.
+
+Additionally a grep function is supplied that can be used to search for ports
+based on their descriptions or hardware ID.
+"""
+
+import sys, os, re
+
+# chose an implementation, depending on os
+#~ if sys.platform == 'cli':
+#~ else:
+import os
+# chose an implementation, depending on os
+if os.name == 'nt': #sys.platform == 'win32':
+ from list_ports_windows import *
+elif os.name == 'posix':
+ from list_ports_posix import *
+#~ elif os.name == 'java':
+else:
+ raise ImportError("Sorry: no implementation for your platform ('%s') available" % (os.name,))
+
+
+def grep(regexp):
+ """\
+ Search for ports using a regular expression. Port name, description and
+ hardware ID are searched. The function returns an iterable that returns the
+ same tuples as comport() would do.
+ """
+ for port, desc, hwid in comports():
+ if re.search(regexp, port) or re.search(regexp, desc) or re.search(regexp, hwid):
+ yield port, desc, hwid
+
+# test
+if __name__ == '__main__':
+ hits = 0
+ if len(sys.argv) > 1:
+ print "Filtered list with regexp: %r" % (sys.argv[1],)
+ for port, desc, hwid in sorted(grep(sys.argv[1])):
+ print "%-20s: %s [%s]" % (port, desc, hwid)
+ hits += 1
+ else:
+ for port, desc, hwid in sorted(comports()):
+ print "%-20s: %s [%s]" % (port, desc, hwid)
+ hits += 1
+ if hits:
+ print "%d ports found" % (hits,)
+ else:
+ print "no ports found"
diff --git a/serial/tools/list_ports_posix.py b/serial/tools/list_ports_posix.py
index be25b03..2fb655b 100644
--- a/serial/tools/list_ports_posix.py
+++ b/serial/tools/list_ports_posix.py
@@ -1,12 +1,91 @@
import glob
+import sys
-def comports():
- devices = glob.glob('/dev/ttyS*') + glob.glob('/dev/ttyUSB*') + glob.glob('/dev/ttyACM*')
- return [(d, d, d) for d in devices]
+# The comports function is expected to return an iterable that yields tuples of
+# 3 strings: port name, human readable description and a hardware ID.
+#
+# as currently no method is known to get the second two strings easily, they
+# are currently just identical to the port name.
+# try to detect the OS so that a device can be selected...
+plat = sys.platform.lower()
-if __name__ == '__main__':
- import serial
+if plat[:5] == 'linux': # Linux (confirmed)
+ def comports():
+ devices = glob.glob('/dev/ttyS*') + glob.glob('/dev/ttyUSB*') + glob.glob('/dev/ttyACM*')
+ return [(d, d, d) for d in devices]
+
+elif plat == 'cygwin': # cygwin/win32
+ def comports():
+ devices = glob.glob('/dev/com*')
+ return [(d, d, d) for d in devices]
+
+elif plat == 'openbsd3': # BSD
+ def comports():
+ devices = glob.glob('/dev/ttyp*')
+ return [(d, d, d) for d in devices]
+
+elif plat[:3] == 'bsd' or \
+ plat[:7] == 'freebsd' or \
+ plat[:7] == 'openbsd': # BSD
+
+ def comports():
+ devices = glob.glob('/dev/cuad*')
+ return [(d, d, d) for d in devices]
+
+elif plat[:6] == 'darwin': # OS X (confirmed)
+ def comports():
+ """scan for available ports. return a list of device names."""
+ devices = glob.glob('/dev/tty.*')
+ return [(d, d, d) for d in devices]
+
+elif plat[:6] == 'netbsd': # NetBSD
+ def comports():
+ """scan for available ports. return a list of device names."""
+ devices = glob.glob('/dev/dty*')
+ return [(d, d, d) for d in devices]
+
+elif plat[:4] == 'irix': # IRIX
+ def comports():
+ """scan for available ports. return a list of device names."""
+ devices = glob.glob('/dev/ttyf*')
+ return [(d, d, d) for d in devices]
+elif plat[:2] == 'hp': # HP-UX (not tested)
+ def comports():
+ """scan for available ports. return a list of device names."""
+ devices = glob.glob('/dev/tty*p0')
+ return [(d, d, d) for d in devices]
+
+elif plat[:5] == 'sunos': # Solaris/SunOS
+ def comports():
+ """scan for available ports. return a list of device names."""
+ devices = glob.glob('/dev/tty*c')
+ return [(d, d, d) for d in devices]
+
+elif plat[:3] == 'aix': # AIX
+ def comports():
+ """scan for available ports. return a list of device names."""
+ devices = glob.glob('/dev/tty*')
+ return [(d, d, d) for d in devices]
+
+else:
+ # platform detection has failed...
+ sys.stderr.write("""\
+don't know how to enumerate ttys on this system.
+! I you know how the serial ports are named send this information to
+! the author of this module:
+
+sys.platform = %r
+os.name = %r
+pySerial version = %s
+
+also add the naming scheme of the serial ports and with a bit luck you can get
+this module running...
+""" % (sys.platform, os.name, serial.VERSION))
+ raise ImportError("Sorry: no implementation for your platform ('%s') available" % (os.name,))
+
+# test
+if __name__ == '__main__':
for port, desc, hwid in sorted(comports()):
print "%s: %s [%s]" % (port, desc, hwid)
diff --git a/serial/tools/list_ports_windows.py b/serial/tools/list_ports_windows.py
index 60fed5f..8f1e3fe 100644
--- a/serial/tools/list_ports_windows.py
+++ b/serial/tools/list_ports_windows.py
@@ -179,7 +179,7 @@ def comports():
SetupDiDestroyDeviceInfoList(g_hdi)
-
+# test
if __name__ == '__main__':
import serial