1
2
3
4
5
6
7
8
9
10 """Encapsulates the serial port device"""
11
12 import serial
13 import sys
14 import common
15 import time
16 import threading
17 import data_recording
18
19 try:
20 import native.usb as usb
21 except:
22 usb=None
23
24
25 try:
26 import pywintypes
27 except:
28 pywintypes=None
29
31 - def __init__(self, str=None, partial=None):
34
36 - def __init__(self, str=None, partial=None):
39
41 usbwhine=0
42 - def __init__(self, logtarget, port, baud=115200, timeout=3, hardwareflow=0,
43 softwareflow=0, autolistfunc=None, autolistargs=None, configparameters=None):
44 self._brokennotifications=0
45 self.ser=None
46 self.port=port
47 self.logtarget=logtarget
48 self.clearcounters()
49 if usb is None and self.usbwhine<1:
50 self.log("USB support is not available")
51 self.success=False
52 self.shouldloop=False
53 self.ports=None
54 self.autolistfunc=autolistfunc
55 self.autolistargs=autolistargs
56 self.configparameters=configparameters
57 self.params=(baud,timeout,hardwareflow,softwareflow)
58 self.readahead=""
59 assert port!="auto" or (port=="auto" and autolistfunc is not None)
60 if autolistfunc is not None:
61 self._isauto=True
62 else:
63 self._isauto=False
64 if port=="auto":
65 self.log("Auto detected port requested")
66 self.NextAutoPort()
67 else:
68 self._openport(self.port, *self.params)
69
72
74 if self.ser is not None:
75 try:
76
77 self.ser.close()
78 except:
79 pass
80 self.ser=None
81
82 - def _openport(self, port, baud, timeout, hardwareflow, softwareflow, description=None):
83 if data_recording.DR_Play:
84
85 self.log('Open of comm port ignored')
86 return
87 self.close()
88 self.log("Opening port %s, %d baud, timeout %f, hardwareflow %d, softwareflow %d" %
89 (port, baud, float(timeout), hardwareflow, softwareflow) )
90 if description is not None:
91 self.log(description)
92
93 for dummy in range(2):
94 try:
95 self.close()
96 if port.startswith("usb::"):
97 self.ser=self._openusb(port, timeout)
98 else:
99 useport=port
100 if sys.platform=='win32' and port.lower().startswith("com"): useport="\\\\?\\"+port
101 self.ser=serial.Serial(useport, baud, timeout=timeout, rtscts=hardwareflow, xonxoff=softwareflow)
102 self.log("Open of comm port suceeded")
103 self.port=port
104 self.clearcounters()
105 return
106 except serial.serialutil.SerialException,e:
107 if dummy:
108 self.log('Open of comm port failed')
109 raise common.CommsOpenFailure(e.__str__(), port)
110 time.sleep(2)
111
113 self.close()
114 if usb is None:
115 self.log("USB module not available - unable to open "+name)
116 raise Exception("USB module not available - unable to open "+name)
117 _,wantedbus,wanteddev,wantediface=name.split("::")
118 wantediface=int(wantediface)
119 usb.UpdateLists()
120 for bus in usb.AllBusses():
121 if bus.name()!=wantedbus:
122 continue
123 for device in bus.devices():
124 if device.name()!=wanteddev:
125 continue
126 for iface in device.interfaces():
127 if iface.number()!=wantediface:
128 continue
129 return _usbdevicewrapper(iface.openbulk(), timeout)
130 self.log("Failed to find "+name+". You may need to rescan.")
131 raise common.CommsOpenFailure("Failed to find usb device "+name)
132
133
136
138
139 self.close()
140 self.ports=self.autolistfunc(*self.autolistargs)
141 assert self.ports is not None
142 self.success=False
143 self.portstried=self.ports
144
164
166 self.readbytes=0
167 self.readrequests=0
168 self.writebytes=0
169 self.writerequests=0
170
171 - def log(self, str):
172 if self.logtarget:
173 self.logtarget.log(self.port+": "+str)
174
175 - def logdata(self, str, data, data_type=None):
176 if self.logtarget:
177 self.logtarget.logdata(self.port+": "+str, data,
178 None, data_type)
179
181 """Change to the specified baud rate
182
183 @rtype: Boolean
184 @returns: True on success, False on failure
185 """
186 try:
187 self.ser.setBaudrate(rate)
188 self.log("Changed port speed to "+`rate`)
189 time.sleep(.5)
190 return True
191 except SilentException:
192 return False
193 except Exception,e:
194 self.log("Port speed "+`rate`+" not supported")
195 return False
196
198 """Set or Clear DTR
199
200 @rtype: Boolean
201 @returns: True on success, False on failure
202 """
203 try:
204 self.ser.setDTR(dtr)
205 self.log("DTR set to "+`dtr`)
206 return True
207 except SilentException:
208 return False
209
211 """Set or Clear RTS
212
213 @rtype: Boolean
214 @returns: True on success, False on failure
215 """
216 try:
217 self.ser.setRTS(rts)
218 self.log("RTS set to "+`rts`)
219 return True
220 except SilentException:
221 return False
222
223 - def _write(self, data, log=True):
232
234 try:
235 self._write(data, log)
236 self._write_res=True
237 except Exception,e:
238 self.log('Write Exception: '+str(e))
239 - def write(self, data, log=True):
240 _t=threading.Thread(target=self.write_thread, args=(data, log))
241 self._write_res=False
242 _t.start()
243 _t.join(self.params[1]+1)
244 if _t.isAlive():
245 _t._Thread__stop()
246 if not self._write_res:
247 raise CommTimeout()
248
249 - def sendatcommand(self, atcommand, ignoreerror=False, retry=False):
284
287
289 i=0
290 sbuf=self.readahead
291 if len(sbuf)==0:
292 return ""
293 while sbuf[i]!='\n' and sbuf[i]!='\r':
294 i+=1
295 firstline=sbuf[0:i]
296 if not peek:
297 i+=1
298 while i<len(sbuf):
299 if sbuf[i]!='\n' and sbuf[i]!='\r':
300 break
301 i+=1
302 self.readahead=self.readahead[i:]
303 return firstline
304
343
346
348 if pywintypes is None or not isinstance(e, pywintypes.error) or e[0]!=121:
349 return False
350 return True
351
353
354 self._brokennotifications+=1
355 if self._brokennotifications==3:
356 self.log("This driver is broken - enabling workaround")
357 basetime=time.time()
358 while time.time()-basetime<self.params[1]:
359 try:
360 res=self.ser.read(numchars)
361 return res
362 except Exception,e:
363 if not self._isbrokendriver(e):
364 raise
365 raise CommTimeout()
366
367 - def _read(self, numchars=1, log=True):
382
384 try:
385 self._read_res=self._read(numchars, log)
386 except Exception,e:
387 self.log('Read Exception: '+str(e))
388
389 - def read(self, numchars=1, log=True):
390 _t=threading.Thread(target=self.read_thread, args=(numchars, log))
391 self._read_res=None
392 _t.start()
393 _t.join(self.params[1]+1)
394 if _t.isAlive():
395 _t._Thread__stop()
396 if self._read_res is None:
397 raise CommTimeout()
398 return self._read_res
399
400 - def readsome(self, log=True, numchars=None):
424
425 - def readuntil(self, char, log=True, logsuccess=True, numfailures=0):
426
427 self.readrequests+=1
428 if data_recording.DR_Play:
429 return data_recording.get_data(data_recording.DR_Type_Read_Until)
430 if False:
431 self.logdata("Begin reading until 0x%02x" % (ord(char),), None)
432
433
434 res=''
435 while len(res)==0 or res[-1]!=char:
436 if hasattr(self.ser, 'readuntil'):
437
438 res2=self.ser.readuntil(char)
439 b=-99999
440 else:
441 b=self.ser.inWaiting()
442 if b<1: b=1
443 res2=self.read(b,0)
444 if len(res2)<1:
445 if numfailures==0:
446 if log:
447 self.log("Timed out waiting for %02x, requested bytes %d - %d bytes read" %
448 (ord(char), b, len(res)))
449 self.logdata("Incomplete read was", res)
450 self.readbytes+=len(res)
451 raise CommTimeout(partial=res)
452 else:
453 numfailures-=1
454 self.log("Timed out - flushing and trying again")
455 res=res+res2
456
457 self.readbytes+=len(res)
458 if logsuccess or data_recording.DR_On:
459 self.logdata("Read completed", res,
460 data_recording.DR_Type_Read_Until)
461 return res
462
463
464
465 - def writethenreaduntil(self, data, logwrite, char, logreaduntil=True, logreaduntilsuccess=True, numfailures=1):
466 self.write(data, logwrite)
467 return self.readuntil(char, logreaduntil, logreaduntilsuccess, numfailures)
468
470
472
474 self.dev=dev
475 self.timeout=int(timeout*1000)
476
482
483 - def read(self, numchars=1):
484 return self.dev.read(numchars, self.timeout)
485
488
491
494
517