1
# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
2
# See LICENSE for details.
6
Serial port support for Windows.
8
Requires PySerial and win32all, and needs to be used with win32event
15
from serial import PARITY_NONE, PARITY_EVEN, PARITY_ODD
16
from serial import STOPBITS_ONE, STOPBITS_TWO
17
from serial import FIVEBITS, SIXBITS, SEVENBITS, EIGHTBITS
18
import win32file, win32event
21
from twisted.protocols import basic
22
from twisted.internet import abstract
23
from twisted.python import log
26
from serialport import BaseSerialPort
29
class SerialPort(BaseSerialPort, abstract.FileDescriptor):
30
"""A select()able serial device, acting as a transport."""
34
def __init__(self, protocol, deviceNameOrPortNumber, reactor,
35
baudrate = 9600, bytesize = EIGHTBITS, parity = PARITY_NONE,
36
stopbits = STOPBITS_ONE, xonxoff = 0, rtscts = 0):
37
self._serial = serial.Serial(deviceNameOrPortNumber, baudrate=baudrate,
38
bytesize=bytesize, parity=parity,
39
stopbits=stopbits, timeout=None,
40
xonxoff=xonxoff, rtscts=rtscts)
43
self.reactor = reactor
44
self.protocol = protocol
47
self.closedNotifies = 0
48
self.writeInProgress = 0
50
self.protocol = protocol
51
self._overlappedRead = win32file.OVERLAPPED()
52
self._overlappedRead.hEvent = win32event.CreateEvent(None, 1, 0, None)
53
self._overlappedWrite = win32file.OVERLAPPED()
54
self._overlappedWrite.hEvent = win32event.CreateEvent(None, 0, 0, None)
56
self.reactor.addEvent(self._overlappedRead.hEvent, self, 'serialReadEvent')
57
self.reactor.addEvent(self._overlappedWrite.hEvent, self, 'serialWriteEvent')
59
self.protocol.makeConnection(self)
61
flags, comstat = win32file.ClearCommError(self._serial.hComPort)
62
rc, self.read_buf = win32file.ReadFile(self._serial.hComPort,
63
win32file.AllocateReadBuffer(1),
66
def serialReadEvent(self):
67
#get that character we set up
68
n = win32file.GetOverlappedResult(self._serial.hComPort, self._overlappedRead, 0)
70
first = str(self.read_buf[:n])
71
#now we should get everything that is already in the buffer
72
flags, comstat = win32file.ClearCommError(self._serial.hComPort)
74
win32event.ResetEvent(self._overlappedRead.hEvent)
75
rc, buf = win32file.ReadFile(self._serial.hComPort,
76
win32file.AllocateReadBuffer(comstat.cbInQue),
78
n = win32file.GetOverlappedResult(self._serial.hComPort, self._overlappedRead, 1)
79
#handle all the received data:
80
self.protocol.dataReceived(first + str(buf[:n]))
82
#handle all the received data:
83
self.protocol.dataReceived(first)
86
win32event.ResetEvent(self._overlappedRead.hEvent)
87
rc, self.read_buf = win32file.ReadFile(self._serial.hComPort,
88
win32file.AllocateReadBuffer(1),
91
def write(self, data):
93
if self.writeInProgress:
94
self.outQueue.append(data)
96
self.writeInProgress = 1
97
win32file.WriteFile(self._serial.hComPort, data, self._overlappedWrite)
99
def serialWriteEvent(self):
101
dataToWrite = self.outQueue.pop(0)
103
self.writeInProgress = 0
106
win32file.WriteFile(self._serial.hComPort, dataToWrite, self._overlappedWrite)
108
def connectionLost(self, reason):
109
self.reactor.removeEvent(self._overlappedRead.hEvent)
110
self.reactor.removeEvent(self._overlappedWrite.hEvent)
111
abstract.FileDescriptor.connectionLost(self, reason)