diff options
author | Jan Luebbe <jlu@pengutronix.de> | 2015-06-08 12:09:34 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2016-01-18 09:25:50 +0100 |
commit | 80caf8ac4300c36f21479f38699ac665082d9b39 (patch) | |
tree | a31d9e5ddb6fbff66af56768bcdaba7721a833e2 /scripts/serial/tools | |
parent | ec95d547e721d2762c3cb66572528028f2a56483 (diff) | |
download | barebox-80caf8ac4300c36f21479f38699ac665082d9b39.tar.gz barebox-80caf8ac4300c36f21479f38699ac665082d9b39.tar.xz |
include pyserial trunk
The current pyserial is broken, this version contains the fix for:
http://sourceforge.net/p/pyserial/bugs/166/
Signed-off-by: Jan Luebbe <jlu@pengutronix.de>
Diffstat (limited to 'scripts/serial/tools')
-rw-r--r-- | scripts/serial/tools/__init__.py | 0 | ||||
-rw-r--r-- | scripts/serial/tools/list_ports.py | 103 | ||||
-rw-r--r-- | scripts/serial/tools/list_ports_linux.py | 152 |
3 files changed, 255 insertions, 0 deletions
diff --git a/scripts/serial/tools/__init__.py b/scripts/serial/tools/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/scripts/serial/tools/__init__.py diff --git a/scripts/serial/tools/list_ports.py b/scripts/serial/tools/list_ports.py new file mode 100644 index 0000000000..d373a5566d --- /dev/null +++ b/scripts/serial/tools/list_ports.py @@ -0,0 +1,103 @@ +#!/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-2013 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 serial.tools.list_ports_windows import * +elif os.name == 'posix': + from serial.tools.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. + """ + r = re.compile(regexp, re.I) + for port, desc, hwid in comports(): + if r.search(port) or r.search(desc) or r.search(hwid): + yield port, desc, hwid + + +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +def main(): + import optparse + + parser = optparse.OptionParser( + usage = "%prog [options] [<regexp>]", + description = "Miniterm - A simple terminal program for the serial port." + ) + + parser.add_option("--debug", + help="print debug messages and tracebacks (development mode)", + dest="debug", + default=False, + action='store_true') + + parser.add_option("-v", "--verbose", + help="show more messages (can be given multiple times)", + dest="verbose", + default=1, + action='count') + + parser.add_option("-q", "--quiet", + help="suppress all messages", + dest="verbose", + action='store_const', + const=0) + + (options, args) = parser.parse_args() + + + hits = 0 + # get iteraror w/ or w/o filter + if args: + if len(args) > 1: + parser.error('more than one regexp not supported') + print "Filtered list with regexp: %r" % (args[0],) + iterator = sorted(grep(args[0])) + else: + iterator = sorted(comports()) + # list them + for port, desc, hwid in iterator: + print("%-20s" % (port,)) + if options.verbose > 1: + print(" desc: %s" % (desc,)) + print(" hwid: %s" % (hwid,)) + hits += 1 + if options.verbose: + if hits: + print("%d ports found" % (hits,)) + else: + print("no ports found") + +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +# test +if __name__ == '__main__': + main() diff --git a/scripts/serial/tools/list_ports_linux.py b/scripts/serial/tools/list_ports_linux.py new file mode 100644 index 0000000000..955761eaa4 --- /dev/null +++ b/scripts/serial/tools/list_ports_linux.py @@ -0,0 +1,152 @@ +#!/usr/bin/env python
+
+# portable serial port access with python
+#
+# This is a module that gathers a list of serial ports including details on
+# GNU/Linux systems
+#
+# (C) 2011-2013 Chris Liechti <cliechti@gmx.net>
+# this is distributed under a free software license, see license.txt
+
+import glob
+import sys
+import os
+import re
+
+try:
+ import subprocess
+except ImportError:
+ def popen(argv):
+ try:
+ si, so = os.popen4(' '.join(argv))
+ return so.read().strip()
+ except:
+ raise IOError('lsusb failed')
+else:
+ def popen(argv):
+ try:
+ return subprocess.check_output(argv, stderr=subprocess.STDOUT).strip()
+ except:
+ raise IOError('lsusb failed')
+
+
+# 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()
+
+def read_line(filename):
+ """\
+ Helper function to read a single line from a file.
+ Returns None on errors..
+ """
+ try:
+ f = open(filename)
+ line = f.readline().strip()
+ f.close()
+ return line
+ except IOError:
+ return None
+
+def re_group(regexp, text):
+ """search for regexp in text, return 1st group on match"""
+ if sys.version < '3':
+ m = re.search(regexp, text)
+ else:
+ # text is bytes-like
+ m = re.search(regexp, text.decode('ascii', 'replace'))
+ if m: return m.group(1)
+
+
+# try to extract descriptions from sysfs. this was done by experimenting,
+# no guarantee that it works for all devices or in the future...
+
+def usb_sysfs_hw_string(sysfs_path):
+ """given a path to a usb device in sysfs, return a string describing it"""
+ bus, dev = os.path.basename(os.path.realpath(sysfs_path)).split('-')
+ snr = read_line(sysfs_path+'/serial')
+ if snr:
+ snr_txt = ' SNR=%s' % (snr,)
+ else:
+ snr_txt = ''
+ return 'USB VID:PID=%s:%s%s' % (
+ read_line(sysfs_path+'/idVendor'),
+ read_line(sysfs_path+'/idProduct'),
+ snr_txt
+ )
+
+def usb_lsusb_string(sysfs_path):
+ base = os.path.basename(os.path.realpath(sysfs_path))
+ bus = base.split('-')[0]
+ try:
+ dev = int(read_line(os.path.join(sysfs_path, 'devnum')))
+ desc = popen(['lsusb', '-v', '-s', '%s:%s' % (bus, dev)])
+ # descriptions from device
+ iManufacturer = re_group('iManufacturer\s+\w+ (.+)', desc)
+ iProduct = re_group('iProduct\s+\w+ (.+)', desc)
+ iSerial = re_group('iSerial\s+\w+ (.+)', desc) or ''
+ # descriptions from kernel
+ idVendor = re_group('idVendor\s+0x\w+ (.+)', desc)
+ idProduct = re_group('idProduct\s+0x\w+ (.+)', desc)
+ # create descriptions. prefer text from device, fall back to the others
+ return '%s %s %s' % (iManufacturer or idVendor, iProduct or idProduct, iSerial)
+ except IOError:
+ return base
+
+def describe(device):
+ """\
+ Get a human readable description.
+ For USB-Serial devices try to run lsusb to get a human readable description.
+ For USB-CDC devices read the description from sysfs.
+ """
+ base = os.path.basename(device)
+ # USB-Serial devices
+ sys_dev_path = '/sys/class/tty/%s/device/driver/%s' % (base, base)
+ if os.path.exists(sys_dev_path):
+ sys_usb = os.path.dirname(os.path.dirname(os.path.realpath(sys_dev_path)))
+ return usb_lsusb_string(sys_usb)
+ # USB-CDC devices
+ sys_dev_path = '/sys/class/tty/%s/device/interface' % (base,)
+ if os.path.exists(sys_dev_path):
+ return read_line(sys_dev_path)
+ # USB Product Information
+ sys_dev_path = '/sys/class/tty/%s/device' % (base,)
+ if os.path.exists(sys_dev_path):
+ product_name_file = os.path.dirname(os.path.realpath(sys_dev_path)) + "/product"
+ if os.path.exists(product_name_file):
+ return read_line(product_name_file)
+ return base
+
+def hwinfo(device):
+ """Try to get a HW identification using sysfs"""
+ base = os.path.basename(device)
+ if os.path.exists('/sys/class/tty/%s/device' % (base,)):
+ # PCI based devices
+ sys_id_path = '/sys/class/tty/%s/device/id' % (base,)
+ if os.path.exists(sys_id_path):
+ return read_line(sys_id_path)
+ # USB-Serial devices
+ sys_dev_path = '/sys/class/tty/%s/device/driver/%s' % (base, base)
+ if os.path.exists(sys_dev_path):
+ sys_usb = os.path.dirname(os.path.dirname(os.path.realpath(sys_dev_path)))
+ return usb_sysfs_hw_string(sys_usb)
+ # USB-CDC devices
+ if base.startswith('ttyACM'):
+ sys_dev_path = '/sys/class/tty/%s/device' % (base,)
+ if os.path.exists(sys_dev_path):
+ return usb_sysfs_hw_string(sys_dev_path + '/..')
+ return 'n/a' # XXX directly remove these from the list?
+
+def comports():
+ devices = glob.glob('/dev/ttyS*') + glob.glob('/dev/ttyUSB*') + glob.glob('/dev/ttyACM*')
+ return [(d, describe(d), hwinfo(d)) for d in devices]
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# test
+if __name__ == '__main__':
+ for port, desc, hwid in sorted(comports()):
+ print "%s: %s [%s]" % (port, desc, hwid)
|