License GNU General Public License, version 3
Lines 472
Keywords
pocket pc (1) serial (1)
Included in this Library
Permissions
Owner: wildintellect
Viewable by Everyone
Editable by All Siafoo Users
Hide
Siafoo – the intersection of pastebin, help desk, version control, and social networking Join Siafoo Now or Learn More

ceserial.py Atom Feed 0

# 's
  1"""Provide serial port access to Windows CE devices.
2
3Copyright:
4Ben McBride
5benjamin.mcbrideATgmail.com
6
7Readline section ported from pyserial by Alex Mandel
8techATwildintellect.com
9
10Pyserial under the Python License
11http://pyserial.svn.sourceforge.net/viewvc/pyserial/trunk/pyserial/LICENSE.txt
12"""
13import sys
14
15import winbase
16from ctypes import *
17
18#-----------------------------------------------------------
19# CONSTANTS
20#-----------------------------------------------------------
21PARITY_NONE = winbase.NOPARITY
22PARITY_EVEN = winbase.EVENPARITY
23PARITY_ODD = winbase.ODDPARITY
24
25STOPBITS_ONE = winbase.ONESTOPBIT
26STOPBITS_TWO = winbase.TWOSTOPBITS
27
28FIVEBITS = 5
29SIXBITS = 6
30SEVENBITS = 7
31EIGHTBITS = 8
32
33XON = chr(17)
34XOFF = chr(19)
35
36#-----------------------------------------------------------
37# Helper functions
38#-----------------------------------------------------------
39def bitmask(b):
40 """Return a mask for setting a bit"""
41 return (1 << b)
42
43def bitset(value, b):
44 """Set the specified bit of value"""
45 return (value | bitmask(b))
46
47def bitclear(value, b):
48 """Clear the specified bit of value"""
49 return (value & ~(bitmask(b)))
50
51def bittest(value, b):
52 """Return True if the bit of value is 1, False otherwise"""
53 return 1 == ((value >> 1) & 1)
54
55#-----------------------------------------------------------
56# Windows Comm Structures
57#-----------------------------------------------------------
58class DCB(Structure):
59 """Device Control Block structure"""
60 _fields_ = [
61 ("DCBlength", c_uint),
62 ("BaudRate", c_uint),
63 ("flags", c_uint),
64# codervw:bdm :1 ("fBinary", c_uint),
65# codervw:bdm :1 ("fParity", c_uint),
66# codervw:bdm :1 ("fOutxCtsFlow", c_uint),
67# codervw:bdm :1 ("fOutxDsrFlow", c_uint),
68# codervw:bdm :2 ("fDtrControl", c_uint),
69# codervw:bdm :1 ("fDsrSensitivity", c_uint),
70# codervw:bdm :1 ("fTXContinueOnXoff", c_uint),
71# codervw:bdm :1 ("fOutX", c_uint),
72# codervw:bdm :1 ("fInX", c_uint),
73# codervw:bdm :1 ("fErrorChar", c_uint),
74# codervw:bdm :1 ("fNull", c_uint),
75# codervw:bdm :2 ("fRtsControl", c_uint),
76# codervw:bdm :1 ("fAbortOnError", c_uint),
77# codervw:bdm :17("fDummy2", c_uint),
78 ("wReserved", c_ushort),
79 ("XonLim", c_ushort),
80 ("XoffLim", c_ushort),
81 ("ByteSize", c_byte),
82 ("Parity", c_byte),
83 ("StopBits", c_byte),
84 ("XonChar", c_char),
85 ("XoffChar", c_char),
86 ("ErrorChar", c_char),
87 ("EofChar", c_char),
88 ("EvtChar", c_char),
89 ("wReserved1", c_ushort)
90 ]
91
92class COMMTIMEOUTS(Structure):
93 """Comm timeout structure"""
94 _fields_ = [
95 ("ReadIntervalTimeout", c_uint),
96 ("ReadTotalTimeoutMultiplier", c_uint),
97 ("ReadTotalTimeoutConstant", c_uint),
98 ("WriteTotalTimeoutMultiplier", c_uint),
99 ("WriteTotalTimeoutConstant", c_uint)
100 ]
101
102class COMSTAT(Structure):
103 """Communication device data"""
104 _fields_ = [
105 ("flags", c_uint),
106 ("cbInQue", c_uint),
107 ("cbOutQue", c_uint)
108 ]
109
110#-----------------------------------------------------------
111# Classes
112#-----------------------------------------------------------
113class SerialException(Exception):
114 pass
115
116class FileLike(object):
117 """An abstract file like class.
118
119 This class implements readline and readlines based on read and
120 writelines based on write.
121 This class is used to provide the above functions for to Serial
122 port objects.
123
124 Note that when the serial port was opened with _NO_ timeout that
125 readline blocks until it sees a newline (or the specified size is
126 reached) and that readlines would never return and therefore
127 refuses to work (it raises an exception in this case)!
128 """
129
130 def read(self, size): raise NotImplementedError
131 def write(self, s): raise NotImplementedError
132
133 def readline(self, size=None, eol='\n'):
134 """read a line which is terminated with end-of-line (eol) character
135 ('\n' by default) or until timeout"""
136 line = ''
137 while 1:
138 c = self.read(1)
139 if c:
140 line += c #not very efficient but lines are usually not that long
141 if c == eol:
142 break
143 if size is not None and len(line) >= size:
144 break
145 else:
146 break
147 return line
148
149 def readlines(self, sizehint=None, eol='\n'):
150 """read a list of lines, until timeout
151 sizehint is ignored"""
152 if self.timeout is None:
153 raise ValueError, "Serial port MUST have enabled timeout for this function!"
154 lines = []
155 while 1:
156 line = self.readline(eol=eol)
157 if line:
158 lines.append(line)
159 if line[-1] != eol: #was the line received with a timeout?
160 break
161 else:
162 break
163 return lines
164
165 def xreadlines(self, sizehint=None):
166 """just call readlines - here for compatibility"""
167 return self.readlines()
168
169 def writelines(self, sequence):
170 for line in sequence:
171 self.write(line)
172
173 def flush(self):
174 """flush of file like objects"""
175 pass
176
177 # iterator for e.g. "for line in Serial(0): ..." usage
178 def next(self):
179 line = self.readline()
180 if not line: raise StopIteration
181 return line
182
183 def __iter__(self):
184 return self
185
186class Serial(FileLike):
187 """Serial port class"""
188 _baudrates = {
189 110 : winbase.CBR_110,
190 300 : winbase.CBR_300,
191 600 : winbase.CBR_600,
192 1200 : winbase.CBR_1200,
193 2400 : winbase.CBR_2400,
194 4800 : winbase.CBR_4800,
195 9600 : winbase.CBR_9600,
196 14400 : winbase.CBR_14400,
197 19200 : winbase.CBR_19200,
198 38400 : winbase.CBR_38400,
199 56000 : winbase.CBR_56000,
200 57600 : winbase.CBR_57600,
201 115200 : winbase.CBR_115200,
202 128000 : winbase.CBR_128000,
203 256000 : winbase.CBR_256000
204 }
205
206 def __init__(self,
207 port='COM7:',
208 baudrate=4800,
209 bytesize=8,
210 stopbits=STOPBITS_ONE,
211 parity=PARITY_NONE,
212 timeout=5,
213 xonxoff=0,
214 rtscts=False
215 ):
216 self.__handle = winbase.INVALID_HANDLE_VALUE
217 self._port = unicode(port) #CreateFileW requires wide character data
218 self._baudrate = self._baudrates[baudrate]
219 self._bytesize = bytesize
220 self._stopbits = stopbits
221 self._parity = parity
222 self._timeout = timeout
223 self._xonxoff = xonxoff
224 self._rtscts = rtscts
225
226 def open(self):
227 """Try to open the serial port.
228
229 Raises a SerialException exception if there are problems.
230 """
231 #check to see if the port is already open
232 if self.isOpen(): return
233 #get file handle for the COMM port
234 self.__handle = windll.coredll.CreateFileW(
235 self._port,
236 winbase.GENERIC_READ | winbase.GENERIC_WRITE,
237 None,
238 None,
239 winbase.OPEN_ALWAYS,
240 None,
241 None
242 )
243 if self.__handle == winbase.INVALID_HANDLE_VALUE:
244 raise SerialException, windll.coredll.GetLastError()
245 #---------------------------------------------------
246 # set COMM port attributes
247 #---------------------------------------------------
248 #set input and output buffer sizes
249 if not(windll.coredll.SetupComm(self.__handle, 4096, 4096)):
250 raise SerialException, windll.coredll.GetLastError()
251 try:
252 self._configurePort()
253 except SerialException, e:
254 self.close() #try to close the already open port
255 raise SerialException, e
256
257 def close(self):
258 """Close the serial port.
259
260 Raises a SerialException exception if there are problems.
261 """
262 if not(self.isOpen()): return
263 if not(windll.coredll.CloseHandle(self.__handle)):
264 raise SerialException, windll.coredll.GetLastError()
265 self.__handle = winbase.INVALID_HANDLE_VALUE
266
267 def read(self, size=1):
268 """Read bytes from the serial port. The port needs to be opened
269 before this function is called.
270
271 Raises a SerialException exception if there are problems.
272 """
273 #clear error flags
274 stats, err = self.getCommStats()
275 #read data
276 data = ''
277 nmbr_of_bytes_to_read = c_uint(size)
278 nmbr_of_bytes_read = c_uint()
279 buffer = create_string_buffer(nmbr_of_bytes_to_read.value)
280 if not(windll.coredll.ReadFile(
281 self.__handle,
282 buffer,
283 nmbr_of_bytes_to_read,
284 byref(nmbr_of_bytes_read),
285 None
286 )):
287 raise SerialException, windll.coredll.GetLastError()
288 data += buffer.raw[0:nmbr_of_bytes_read.value]
289 return data
290
291 def write(self, data):
292 """Write data to the serial port. The port needs to be opened
293 before this function is called.
294
295 Raises a SerialException exception if there are problems.
296 """
297 nmbr_of_bytes = c_uint(len(data))
298 bytes_written = c_uint()
299 success = windll.coredll.WriteFile(
300 self.__handle,
301 data,
302 nmbr_of_bytes,
303 byref(bytes_written),
304 None
305 )
306 if not(success):
307 raise SerialException, windll.coredll.GetLastError()
308
309 def isOpen(self):
310 """Return True if the serial port is open"""
311 return (self.__handle != winbase.INVALID_HANDLE_VALUE)
312
313 def inWaiting(self):
314 """Return the number of characters in the received queue"""
315 comstats, err = self.getCommStats()
316 return comstats.cbInQue
317
318 def flushInput(self):
319 """Flush input buffer, discarding contents"""
320 flags = winbase.PURGE_RXABORT | winbase.PURGE_RXCLEAR
321 if not(windll.coredll.PurgeComm(self.__handle, flags)):
322 raise SerialException, windll.coredll.GetLastError()
323
324 def flushOutput(self):
325 """Flush output buffer, abort output"""
326 flags = winbase.PURGE_TXABORT | winbase.PURGE_TXCLEAR
327 if not(windll.coredll.PurgeComm(self.__handle, flags)):
328 raise SerialException, windll.coredll.GetLastError()
329
330 #-------------------------------------------------------
331 # Non PySerial methods
332 #-------------------------------------------------------
333 def getDCB(self):
334 """Get the DCB structure"""
335 dcb = DCB()
336 if not(windll.coredll.GetCommState(self.__handle, byref(dcb))):
337 raise SerialException, windll.coredll.GetLastError()
338 return dcb
339
340 def getCommTimeouts(self):
341 """Get the comm timeouts."""
342 timeouts = COMMTIMEOUTS()
343 if not(windll.coredll.GetCommTimeouts(self.__handle, byref(timeouts))):
344 raise SerialException, windll.coredll.GetLastError()
345 return timeouts
346
347 def getCommStats(self):
348 """Get the comm stats function as well as error flags"""
349 comstats = COMSTAT()
350 errors = c_uint()
351 if not(windll.coredll.ClearCommError(
352 self.__handle,
353 byref(errors),
354 byref(comstats),
355 )):
356 raise SerialException, windll.coredll.GetLastError()
357 return comstats, errors.value
358
359 def _configurePort(self):
360 """Configure the port properties and set timeouts."""
361 #set comm port timeout
362 timeouts = self.getCommTimeouts()
363 if self._timeout is None:
364 timeouts.ReadIntervalTimeout = 0
365 timeouts.ReadTotalTimeoutMultiplier = 0
366 timeouts.ReadTotalTimeoutConstant = 0
367 elif self._timeout == 0:
368 timeouts.ReadIntervalTimeout = winbase.MAXDWORD
369 timeouts.ReadTotalTimeoutMultiplier = 0
370 timeouts.ReadTotalTimeoutConstant = 0
371 else:
372 timeouts.ReadIntervalTimeout = 0
373 timeouts.ReadTotalTimeoutMultiplier = 0
374 timeouts.ReadTotalTimeoutConstant = int(self._timeout*1000)
375 timeouts.WriteTotalTimeoutMultiplier = 0
376 timeouts.WriteTotalTimeoutConstant = 0
377 if not(windll.coredll.SetCommTimeouts(self.__handle, byref(timeouts))):
378 raise SerialException, windll.coredll.GetLastError()
379 #get current port attributes
380 dcb = self.getDCB()
381 #set attributes
382 dcb.BaudRate = self._baudrate
383 dcb.ByteSize = self._bytesize
384 dcb.StopBits = self._stopbits
385 #these fields need flags (in the bitfield) to be set
386 dcb.Parity = self._parity
387 if self._parity == PARITY_NONE:
388 dcb.flags = bitclear(dcb.flags, 1)
389 else:
390 dcb.flags = bitset(dcb.flags, 1)
391 if self._xonxoff:
392 dcb.flags = bitset(dcb.flags, 8)
393 dcb.flags = bitset(dcb.flags, 9)
394 dcb.XonChar = XON
395 dcb.XoffChar = XOFF
396 else:
397 dcb.flags = bitclear(dcb.flags, 8)
398 dcb.flags = bitclear(dcb.flags, 9)
399 if self._rtscts:
400 #set fRTSControl to winbase.RTS_CONTROL_HANDSHAKE
401 dcb.flags = bitclear(dcb.flags, 12)
402 dcb.flags = bitset(dcb.flags, 13)
403 dcb.flags = bitset(dcb.flags, 2)
404 else:
405 dcb.flags = bitclear(dcb.flags, 2)
406 #set new attributes
407 if not(windll.coredll.SetCommState(self.__handle, byref(dcb))):
408 raise SerialException, windll.coredll.GetLastError()
409
410 #-------------------------------------------------------
411 # Property methods
412 #-------------------------------------------------------
413#BDM TODO -- what happens when you set the port? PySerial changes on the fly
414 def _getPort(self):
415 return self._port
416
417 def _setPort(self, p):
418 self._port = unicode(p)
419 port = property(_getPort, _setPort)
420
421 def _getBaudrate(self):
422 return self._baudrate
423
424 def setBaudrate(self, baudrate):
425 """Named this on purpose because PySerial makes this
426 function public, the same thing can be accomplished
427 through setting the baudrate attribute though.
428 """
429 self._baudrate = self._baudrates[baudrate]
430 if self.isOpen():
431 self._configurePort()
432 baudrate = property(_getBaudrate, setBaudrate)
433
434 def _getBytesize(self):
435 return self._bytesize
436
437 def _setBytesize(self, size):
438 self._bytesize = size
439 if self.isOpen():
440 self._configurePort()
441 bytesize = property(_getBytesize, _setBytesize)
442
443 def _getParity(self):
444 return self._parity
445
446 def _setParity(self, parity):
447 self._parity = parity
448 if self.isOpen():
449 self._configurePort()
450 parity = property(_getParity, _setParity)
451
452 def _getStopbits(self):
453 return self._stopbits
454
455 def _setStopbits(self, stopbits):
456 self._stopbits = stopbits
457 if self.isOpen():
458 self._configurePort()
459 stopbits = property(_getStopbits, _setStopbits)
460
461 def _getTimeout(self):
462 return self._timeout
463
464 def _setTimeout(self, t):
465 if self._timeout != t:
466 self._timeout = t
467 if self.isOpen():
468 self._configurePort()
469 timeout = property(_getTimeout, _setTimeout)
470
471 def _getXonXoff(self):
472 return self._xonxoff
473
474 def _setXonXoff(self, x):
475 self._xonxoff = x
476 if self.isOpen():
477 self._configurePort()
478 xonxoff = property(_getXonXoff, _setXonXoff)
479
480 def _getRtsCts(self):
481 return self._rtscts
482
483 def _setRtsCts(self, rtscts):
484 self._rtscts = rtscts
485 if self.isOpen():
486 self._configurePort()
487 rtscts = property(_getRtsCts, _setRtsCts)
488
489 #-------------------------------------------------------
490 # Read only attributes
491 #-------------------------------------------------------
492 def _getPortstr(self):
493 return str(self.port)
494 portstr = property(_getPortstr)
495
496 def _getBaudrates(self):
497 return Serial._baudrates.keys()
498 BAUDRATES = property(_getBaudrates)
499
500 def _getParities(self):
501 return [PARITY_NONE, PARITY_EVEN, PARITY_ODD]
502 PARITIES = property(_getParities)
503
504 def _getBytesizes(self):
505 return [FIVEBITS, SIXBITS, SEVENBITS, EIGHTBITS ]
506 BYTESIZES = property(_getBytesizes)
507
508 def _getStopbits(self):
509 return [STOPBITS_ONE, STOPBITS_TWO]
510 STOPBITS = property(_getStopbits)
511
512 #-------------------------------------------------------
513 # XXX these functions are not implemented,
514 # but are defined by pySerial
515 #-------------------------------------------------------
516
517 def sendBreak(self):
518 raise NotImplementedError
519
520 def setRTS(self, level=1):
521 raise NotImplementedError
522
523 def setDTR(self, level=1):
524 raise NotImplementedError
525
526 def getCTS(self):
527 raise NotImplementedError
528
529 def getDSR(self):
530 raise NotImplementedError
531
532 def getRI(self):
533 raise NotImplementedError
534
535 def getCD(self):
536 raise NotImplementedError