Initial import to Tizen
[profile/ivi/python-twisted.git] / twisted / internet / _win32serialport.py
1 # Copyright (c) Twisted Matrix Laboratories.
2 # See LICENSE for details.
3
4 """
5 Serial port support for Windows.
6
7 Requires PySerial and pywin32.
8 """
9
10 # system imports
11 import serial
12 from serial import PARITY_NONE, PARITY_EVEN, PARITY_ODD
13 from serial import STOPBITS_ONE, STOPBITS_TWO
14 from serial import FIVEBITS, SIXBITS, SEVENBITS, EIGHTBITS
15 import win32file, win32event
16
17 # twisted imports
18 from twisted.internet import abstract
19
20 # sibling imports
21 from serialport import BaseSerialPort
22
23
24 class SerialPort(BaseSerialPort, abstract.FileDescriptor):
25     """A serial device, acting as a transport, that uses a win32 event."""
26
27     connected = 1
28
29     def __init__(self, protocol, deviceNameOrPortNumber, reactor, 
30         baudrate = 9600, bytesize = EIGHTBITS, parity = PARITY_NONE,
31         stopbits = STOPBITS_ONE, xonxoff = 0, rtscts = 0):
32         self._serial = self._serialFactory(
33             deviceNameOrPortNumber, baudrate=baudrate, bytesize=bytesize,
34             parity=parity, stopbits=stopbits, timeout=None,
35             xonxoff=xonxoff, rtscts=rtscts)
36         self.flushInput()
37         self.flushOutput()
38         self.reactor = reactor
39         self.protocol = protocol
40         self.outQueue = []
41         self.closed = 0
42         self.closedNotifies = 0
43         self.writeInProgress = 0
44
45         self.protocol = protocol
46         self._overlappedRead = win32file.OVERLAPPED()
47         self._overlappedRead.hEvent = win32event.CreateEvent(None, 1, 0, None)
48         self._overlappedWrite = win32file.OVERLAPPED()
49         self._overlappedWrite.hEvent = win32event.CreateEvent(None, 0, 0, None)
50
51         self.reactor.addEvent(self._overlappedRead.hEvent, self, 'serialReadEvent')
52         self.reactor.addEvent(self._overlappedWrite.hEvent, self, 'serialWriteEvent')
53
54         self.protocol.makeConnection(self)
55         self._finishPortSetup()
56
57
58     def _finishPortSetup(self):
59         """
60         Finish setting up the serial port.
61
62         This is a separate method to facilitate testing.
63         """
64         flags, comstat = win32file.ClearCommError(self._serial.hComPort)
65         rc, self.read_buf = win32file.ReadFile(self._serial.hComPort,
66                                                win32file.AllocateReadBuffer(1),
67                                                self._overlappedRead)
68
69
70     def serialReadEvent(self):
71         #get that character we set up
72         n = win32file.GetOverlappedResult(self._serial.hComPort, self._overlappedRead, 0)
73         if n:
74             first = str(self.read_buf[:n])
75             #now we should get everything that is already in the buffer
76             flags, comstat = win32file.ClearCommError(self._serial.hComPort)
77             if comstat.cbInQue:
78                 win32event.ResetEvent(self._overlappedRead.hEvent)
79                 rc, buf = win32file.ReadFile(self._serial.hComPort,
80                                              win32file.AllocateReadBuffer(comstat.cbInQue),
81                                              self._overlappedRead)
82                 n = win32file.GetOverlappedResult(self._serial.hComPort, self._overlappedRead, 1)
83                 #handle all the received data:
84                 self.protocol.dataReceived(first + str(buf[:n]))
85             else:
86                 #handle all the received data:
87                 self.protocol.dataReceived(first)
88
89         #set up next one
90         win32event.ResetEvent(self._overlappedRead.hEvent)
91         rc, self.read_buf = win32file.ReadFile(self._serial.hComPort,
92                                                win32file.AllocateReadBuffer(1),
93                                                self._overlappedRead)
94
95
96     def write(self, data):
97         if data:
98             if self.writeInProgress:
99                 self.outQueue.append(data)
100             else:
101                 self.writeInProgress = 1
102                 win32file.WriteFile(self._serial.hComPort, data, self._overlappedWrite)
103
104
105     def serialWriteEvent(self):
106         try:
107             dataToWrite = self.outQueue.pop(0)
108         except IndexError:
109             self.writeInProgress = 0
110             return
111         else:
112             win32file.WriteFile(self._serial.hComPort, dataToWrite, self._overlappedWrite)
113
114
115     def connectionLost(self, reason):
116         """
117         Called when the serial port disconnects.
118
119         Will call C{connectionLost} on the protocol that is handling the
120         serial data.
121         """
122         self.reactor.removeEvent(self._overlappedRead.hEvent)
123         self.reactor.removeEvent(self._overlappedWrite.hEvent)
124         abstract.FileDescriptor.connectionLost(self, reason)
125         self._serial.close()
126         self.protocol.connectionLost(reason)