Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / seabios / scripts / 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 #   scripts/readserial.py /dev/ttyUSB0 115200
10
11 import sys, os, time, select, optparse
12
13 from python23compat import as_bytes
14
15 # Reset time counter after this much idle time.
16 RESTARTINTERVAL = 60
17 # Number of bits in a transmitted byte - 8N1 is 1 start bit + 8 data
18 # bits + 1 stop bit.
19 BITSPERBYTE = 10
20
21 def calibrateserialwrite(outfile, byteadjust):
22     # Build 4000 bytes of dummy data.
23     data = "0123456789" * 4 + "012345678" + "\n"
24     data = data * 80
25     while 1:
26         st = time.time()
27         outfile.write(as_bytes(data))
28         outfile.flush()
29         et = time.time()
30         sys.stdout.write(
31             "Wrote %d - %.1fus per char (theory states %.1fus)\n" % (
32                 len(data), (et-st) / len(data) * 1000000, byteadjust * 1000000))
33         sys.stdout.flush()
34         time.sleep(3)
35
36 def calibrateserialread(infile, byteadjust):
37     starttime = lasttime = 0
38     totalchars = 0
39     while 1:
40         select.select([infile], [], [])
41         d = infile.read(4096)
42         curtime = time.time()
43         if curtime - lasttime > 1.0:
44             if starttime and totalchars:
45                 sys.stdout.write(
46                     "Calibrating on %d bytes - %.1fus per char"
47                     " (theory states %.1fus)\n" % (
48                         totalchars,
49                         float(lasttime - starttime) * 1000000 / totalchars,
50                         byteadjust * 1000000))
51             totalchars = 0
52             starttime = curtime
53         else:
54             totalchars += len(d)
55         lasttime = curtime
56
57 def readserial(infile, logfile, byteadjust):
58     lasttime = 0
59     while 1:
60         # Read data
61         try:
62             res = select.select([infile, sys.stdin], [], [])
63         except KeyboardInterrupt:
64             sys.stdout.write("\n")
65             return -1
66         if sys.stdin in res[0]:
67             # Got keyboard input - force reset on next serial input
68             sys.stdin.read(1)
69             lasttime = 0
70             if len(res[0]) == 1:
71                 continue
72         d = infile.read(4096)
73         if not d:
74             return 0
75         datatime = time.time()
76
77         datatime -= len(d) * byteadjust
78
79         # Reset start time if no data for some time
80         if datatime - lasttime > RESTARTINTERVAL:
81             starttime = datatime
82             charcount = 0
83             isnewline = 1
84             msg = "\n\n======= %s (adjust=%.1fus)\n" % (
85                 time.asctime(time.localtime(datatime)), byteadjust * 1000000)
86             sys.stdout.write(msg)
87             logfile.write(as_bytes(msg))
88         lasttime = datatime
89
90         # Translate unprintable chars; add timestamps
91         out = as_bytes("")
92         for c in d:
93             if isnewline:
94                 delta = datatime - starttime - (charcount * byteadjust)
95                 out += "%06.3f: " % delta
96                 isnewline = 0
97             oc = ord(c)
98             charcount += 1
99             datatime += byteadjust
100             if oc == 0x0d:
101                 continue
102             if oc == 0x00:
103                 out += "<00>\n"
104                 isnewline = 1
105                 continue
106             if oc == 0x0a:
107                 out += "\n"
108                 isnewline = 1
109                 continue
110             if oc < 0x20 or oc >= 0x7f and oc != 0x09:
111                 out += "<%02x>" % oc
112                 continue
113             out += c
114
115         if (sys.version_info > (3, 0)):
116             sys.stdout.buffer.write(out)
117         else:
118             sys.stdout.write(out)
119         sys.stdout.flush()
120         logfile.write(out)
121         logfile.flush()
122
123 def main():
124     usage = "%prog [options] [<serialdevice> [<baud>]]"
125     opts = optparse.OptionParser(usage)
126     opts.add_option("-f", "--file",
127                     action="store_false", dest="serial", default=True,
128                     help="read from unix named pipe instead of serialdevice")
129     opts.add_option("-n", "--no-adjust",
130                     action="store_false", dest="adjustbaud", default=True,
131                     help="don't adjust times by serial rate")
132     opts.add_option("-c", "--calibrate-read",
133                     action="store_true", dest="calibrate_read", default=False,
134                     help="read from serial port to calibrate it")
135     opts.add_option("-C", "--calibrate-write",
136                     action="store_true", dest="calibrate_write", default=False,
137                     help="write to serial port to calibrate it")
138     opts.add_option("-t", "--time",
139                     type="float", dest="time", default=None,
140                     help="time to write one byte on serial port (in us)")
141     options, args = opts.parse_args()
142     serialport = 0
143     baud = 115200
144     if len(args) > 2:
145         opts.error("Too many arguments")
146     if len(args) > 0:
147         serialport = args[0]
148     if len(args) > 1:
149         baud = int(args[1])
150     byteadjust = float(BITSPERBYTE) / baud
151     if options.time is not None:
152         byteadjust = options.time / 1000000.0
153     if not options.adjustbaud:
154         byteadjust = 0.0
155
156     if options.serial:
157         # Read from serial port
158         try:
159             import serial
160         except ImportError:
161             print("""
162 Unable to find pyserial package ( http://pyserial.sourceforge.net/ ).
163 On Linux machines try: yum install pyserial
164 Or: apt-get install python-serial
165 """)
166             sys.exit(1)
167         ser = serial.Serial(serialport, baud, timeout=0)
168
169     if options.calibrate_read:
170         calibrateserialread(ser, byteadjust)
171         return
172     if options.calibrate_write:
173         calibrateserialwrite(ser, byteadjust)
174         return
175
176     logname = time.strftime("seriallog-%Y%m%d_%H%M%S.log")
177     f = open(logname, 'wb')
178     if options.serial:
179         readserial(ser, f, byteadjust)
180     else:
181         # Read from a pipe
182         while 1:
183             ser = os.fdopen(os.open(serialport, os.O_RDONLY|os.O_NONBLOCK), 'rb')
184             res = readserial(ser, f, byteadjust)
185             ser.close()
186             if res < 0:
187                 break
188
189 if __name__ == '__main__':
190     main()