Report meaningful error if pyserial not present in tools/readserial.py
[seabios.git] / tools / readserial.py
1 #!/usr/bin/env python
2 # Script that can read from a serial device and show timestamps.
3 #
4 # Copyright (C) 2009  Kevin O'Connor <kevin@koconnor.net>
5 #
6 # This file may be distributed under the terms of the GNU GPLv3 license.
7
8 # Usage:
9 #   tools/readserial.py /dev/ttyUSB0 115200
10
11 import sys
12 import time
13 import select
14 import optparse
15
16 # Reset time counter after this much idle time.
17 RESTARTINTERVAL = 60
18 # Alter timing reports based on how much time would be spent writing
19 # to serial.
20 ADJUSTBAUD = 1
21 # Number of bits in a transmitted byte - 8N1 is 1 start bit + 8 data
22 # bits + 1 stop bit.
23 BITSPERBYTE = 10
24
25 def readserial(infile, logfile, baudrate):
26     lasttime = 0
27     byteadjust = 0.0
28     if ADJUSTBAUD:
29         byteadjust = float(BITSPERBYTE) / baudrate
30     while 1:
31         # Read data
32         try:
33             res = select.select([infile, sys.stdin], [], [])
34         except KeyboardInterrupt:
35             sys.stdout.write("\n")
36             break
37         if sys.stdin in res[0]:
38             # Got keyboard input - force reset on next serial input
39             sys.stdin.read(1)
40             lasttime = 0
41             if len(res[0]) == 1:
42                 continue
43         d = infile.read(4096)
44         if not d:
45             break
46         datatime = time.time()
47
48         datatime -= len(d) * byteadjust
49
50         # Reset start time if no data for some time
51         if datatime - lasttime > RESTARTINTERVAL:
52             starttime = datatime
53             charcount = 0
54             isnewline = 1
55             msg = "\n\n======= %s (adjust=%d)\n" % (
56                 time.asctime(time.localtime(datatime)), ADJUSTBAUD)
57             sys.stdout.write(msg)
58             logfile.write(msg)
59         lasttime = datatime
60
61         # Translate unprintable chars; add timestamps
62         out = ""
63         for c in d:
64             if isnewline:
65                 delta = datatime - starttime - (charcount * byteadjust)
66                 out += "%06.3f: " % delta
67                 isnewline = 0
68             oc = ord(c)
69             charcount += 1
70             datatime += byteadjust
71             if oc == 0x0d:
72                 continue
73             if oc == 0x00:
74                 out += "<00>\n"
75                 isnewline = 1
76                 continue
77             if oc == 0x0a:
78                 out += "\n"
79                 isnewline = 1
80                 continue
81             if oc < 0x20 or oc >= 0x7f and oc != 0x09:
82                 out += "<%02x>" % oc
83                 continue
84             out += c
85
86         sys.stdout.write(out)
87         sys.stdout.flush()
88         logfile.write(out)
89         logfile.flush()
90
91 def main():
92     usage = "%prog [options] [<serialdevice> [<baud>]]"
93     opts = optparse.OptionParser(usage)
94     opts.add_option("-f", "--file",
95                     action="store_false", dest="serial", default=True,
96                     help="read from file instead of serialdevice")
97     opts.add_option("-n", "--no-adjust",
98                     action="store_false", dest="adjustbaud", default=True,
99                     help="don't adjust times by serial rate")
100     options, args = opts.parse_args()
101     serialport = 0
102     baud = 115200
103     if len(args) > 2:
104         opts.error("Too many arguments")
105     if len(args) > 0:
106         serialport = args[0]
107     if len(args) > 1:
108         baud = int(args[1])
109     global ADJUSTBAUD
110     ADJUSTBAUD=options.adjustbaud
111
112     if options.serial:
113         # Read from serial port
114         try:
115             import serial
116         except ImportError:
117             print """
118 Unable to find pyserial package ( http://pyserial.sourceforge.net/ ).
119 On Linux machines try: yum install pyserial
120 Or: apt-get install python-serial
121 """
122             sys.exit(1)
123         ser = serial.Serial(serialport, baud, timeout=0)
124     else:
125         # Read from a file
126         ser = open(serialport, 'rb')
127         import fcntl
128         import os
129         fcntl.fcntl(ser, fcntl.F_SETFL
130                     , fcntl.fcntl(ser, fcntl.F_GETFL) | os.O_NONBLOCK)
131
132     logname = time.strftime("seriallog-%Y%m%d_%H%M%S.log")
133     f = open(logname, 'wb')
134     readserial(ser, f, baud)
135
136 if __name__ == '__main__':
137     main()