<pre>Here is my code for Plug &#39;n Play detection of serial devices. It&#39;s not yet ready for showtime, but it works with my serial attached Wacom.<br><br>Best regards,<br>eulores<br><br><br># -*- coding: utf-8 -*-<br>
<br>import sys<br>if sys.platform == &#39;win32&#39;:<br>    from twisted.internet import win32eventreactor<br>    win32eventreactor.install()<br>from twisted.internet import reactor, protocol<br>from twisted.internet.task import deferLater, LoopingCall<br>
from twisted.internet.defer import Deferred, inlineCallbacks, returnValue<br>from twisted.internet.serialport import *<br>import re<br><br>def wait(seconds):<br>    return deferLater(reactor, seconds, lambda:None)<br><br>
class StructuredPnP(object):<br>    &#39;&#39;&#39; The structured PnP field is available with these fields:<br>            data:    string, required. Original unformatted string.<br>            other:   string, optional<br>
            rev:     integer, required. Revision of the PnP standard. 100 is standard version 1.00<br>            eisa:    string, required<br>            product: string, required<br>            serial:  string, optional<br>
            klass:   string, optional<br>            compat:  string, optional. Other older products with similar functionality<br>            user:    string, optional. Free flowing field useful for the end-user<br>    &#39;&#39;&#39;<br>
    def __init__(self, data):<br>        #data = &#39;\\96,N,8,1(\x01$WAC0608\\\\PEN\\WAC0000\\WACOM UD\r\nUD-0608-R,V1.4-4\r\nF4)&#39;<br>        # test string for a 7-bit character string<br>        #data = &#39;aaa(bbcccdddd\\eeeeeeee\\fff\\gggg\\hhhhii)&#39;<br>
        # test string for a 6-bit character string<br>        #data = &#39;AAA\x08BBCCCDDDD&lt;EEEEEEEE&lt;FFF&lt;GGGG&lt;HHHHII\x09&#39;<br>        self.data = data<br>        for key in &quot;other eisa product serial klass compat user&quot;.split():<br>
            setattr(self, key, &#39;&#39;)<br>        self.rev = &#39;\0\0&#39;<br>        prologue = r&#39;(?P&lt;other&gt;[^(]{,16}?)&#39;<br>        matrix = r&#39;(?P&lt;rev&gt;..)(?P&lt;eisa&gt;...)(?P&lt;product&gt;....)(?:@(?P&lt;serial&gt;[^@]{,8}))?(?:@(?P&lt;klass&gt;[^@]{,32}))?(?:@(?P&lt;compat&gt;[^@]{,40}))?(?:@(?P&lt;user&gt;.{,40}?))?(?:..)?&#39;<br>
        needle1 = prologue + &#39;\\(&#39; + matrix.replace(&#39;@&#39;,&#39;\\\\&#39;) + &#39;\\)&#39;<br>        needle2 = prologue + &#39;\\\x08&#39; + matrix.replace(&#39;@&#39;,&#39;\\\x3C&#39;) + &#39;\\\x09&#39;<br>
        dct = dict()<br>        mo = re.match(needle1, data, re.S)<br>        if mo:<br>            dct = mo.groupdict()<br>        else:<br>            mo = re.match(needle2, data, re.S)<br>            if mo:<br>                dct = mo.groupdict()<br>
                for k in &quot;eisa product serial klass compat user&quot;.split():<br>                    v = dct[k]<br>                    dct[k] = &#39;&#39;.join([chr(ord(ch)+0x20) for ch in list(v)])<br>        for k,v in dct.items():<br>
            setattr(self, k, v)<br>        self.rev = ((ord(self.rev[0])&amp;0x3f)&lt;&lt;6) + (ord(self.rev[1])&amp;0x3f)<br>    def __str__(self):<br>        return self.data<br>    def __repr__(self):<br>        l = [&#39;&lt;StructuredPnP object&gt; %r&#39; % self.data]<br>
        for k in &quot;other rev eisa product serial klass compat user&quot;.split():<br>            l.append(&#39;  %-8s %r&#39; % (k, getattr(self,k,False)))<br>        return &#39;\n&#39;.join(l)<br><br>class PnPProtocol(protocol.Protocol):<br>
    &quot;&quot;&quot; See Plug and Play External COM device Specification, rev 1.00 from Microsoft &amp; Hayes, 1994-1995&quot;&quot;&quot;<br>    def __init__(self, deferred):<br>        self.deferred = deferred<br>        self.data = &#39;&#39;<br>
        self.timeout = 1.4<br>        self.T5 = reactor.callLater(self.timeout, self.deliverPnP)<br>    def deliverPnP(self):<br>        self.transport.loseConnection()<br>        if self.deferred is not None:<br>            d, self.deferred = self.deferred, None<br>
            d.callback(StructuredPnP(self.data))<br>    def dataReceived(self, data):<br>        self.T5.reset(self.timeout)<br>        self.data += data<br>        if len(self.data)&gt;=256:<br>            self.T5.reset(0)<br>
    @inlineCallbacks<br>    def connectionMade(self):<br>        while 1:<br>            # print &quot;2.1.1&quot;<br>            self.transport.setDTR(1)<br>            self.transport.setRTS(0)<br>            yield wait(0.2)<br>
            if not self.transport.getDSR():<br>                break<br>            # print &quot;2.1.3 part A&quot;<br>            self.transport.setDTR(0)<br>            yield wait(0.2)<br>            # print &quot;2.1.3 part B&quot;<br>
            self.transport.setDTR(1)<br>            yield wait(0.2)<br>            # print &quot;2.1.4&quot;<br>            self.transport.setRTS(1)<br>            # timer T5 is now used for per-character timeout<br>            self.timeout = 0.2<br>
            yield wait(0.2)<br>            if self.data:<br>                break<br>            # print &quot;2.1.5&quot;<br>            self.transport.setDTR(0)<br>            self.transport.setRTS(0)<br>            yield wait(0.2)<br>
            # print &quot;2.1.6&quot;<br>            self.transport.setDTR(1)<br>            self.transport.setRTS(1)<br>            yield wait(0.2)<br>            break<br>        if not self.data:<br>            self.T5.reset(0)<br>
        returnValue(None)<br>    def connectionLost(self, reason=&#39;connectionDone&#39;):<br>        print &quot;Connection lost:&quot;, reason<br><br>def pnpString(port=0):<br>    d = Deferred()<br>    protocol = PnPProtocol(d)<br>
    try:<br>        #SerialPort(protocol, port, reactor, baudrate=1200, bytesize=SEVENBITS, parity=PARITY_NONE, stopbits=STOPBITS_ONE, timeout=0, xonxoff=0, rtscts=0)<br>        SerialPort(protocol, port, reactor, baudrate=1200, bytesize=SEVENBITS, parity=PARITY_NONE, stopbits=STOPBITS_ONE, xonxoff=0, rtscts=0)<br>
    except serial.SerialException:<br>        d.callback(StructuredPnP(&#39;&#39;))<br>    return d<br><br>@inlineCallbacks<br>def imRunning():<br>    print &quot;PnP string: %r&quot; % (yield pnpString(3))<br>    reactor.stop()<br>
<br>if __name__ == &quot;__main__&quot;:<br>    reactor.callWhenRunning(imRunning)<br>    reactor.run()</pre><br><br>On Tue, Sep 14, 2010 at 11:24 AM, Markus Hubig &lt;<a href="mailto:mhubig@imko.de">mhubig@imko.de</a>&gt; wrote:<br>
&gt; Hi @all!<br>&gt; I&#39;m trying to write a python library module for a special<br>&gt; serial communication protocol called IMPBUS. To use the serial<br>&gt; interface for sending and receiving packets as for now I&#39;m<br>
&gt; sub-classing pyserial. My code looks like this:<br>&gt;<br>&gt; But the problem is that I can&#39;t use select with pyserial on Windows,<br>&gt; because it don&#39;t provide the fileno() methode. So after some googling<br>
&gt; I found twisted.internet.serialport &quot;A select()able serial device, acting<br>&gt; as a transport.&quot; <br>&gt; I never used twisted before so I&#39;m a little overwhelmed by how I can<br>&gt; replace pyserial with twisted in the code above ... maybe someone can<br>
&gt; point me to the right direction. It seems I need a &quot;Protocol&quot; and a<br>&gt; &quot;receiver&quot; ... <br>&gt; - Markus<br>&gt; --<br><br>