#!/usr/bin/env python # This program connects to a Nokia Phone using Symbian 9 and tries to set the flag to allow all permissions # it needs MetroTRK driver to be running on mobile, and a connection between PC and phone # Read instructions.txt for details # History: 2008.03.08 v0.2 Doesn't need to run HelloCarbide.exe because now uses the ekern thread. # Also includes an example to dump memory into a file # Also tries to read memory using DS_MSG_MEMORY_PROTECTED+DS_MSG_MEMORY_SEGMENTED . With and without a process. Let's see if it works # History: 2008.03.10 v0.1 Includes a memory scan to try to find the address in FP1 (N95, N82, ...) # History: 2008.03.08 v0.0 # License: GPL. Please contact me if you make corrections # Author: FCA00000-at-yahoo-dot-es import serial debug=0 def decodeFrame(myBytes): # [01 01 fd] sindex=0 nack=-1 ack=-1 for i in myBytes: if (sindex==1): if (debug>=0): print "received message number %02X"%i if (i!=-1): if (debug>3): print "decodeFrame-i:%i"%i if (nack==2): nack=-1 ack=-1 if (i==0x00): print " kDSReplyNoError" if (i==0x01): print " kDSReplyError" if (i==0x02): print " kDSReplyPacketSizeError" if (i==0x03): print " kDSReplyCWDSError" if (i==0x04): print " kDSReplyEscapeError" if (i==0x05): print " kDSReplyBadFCS" if (i==0x06): print " kDSReplyOverflow" if (i==0x07): print " kDSReplySequenceMissing" if (i==0x10): print " kDSReplyUnsupportedCommandError" if (i==0x11): print " kDSReplyParameterError" if (i==0x12): print " kDSReplyUnsupportedOptionError" if (i==0x13): print " kDSReplyInvalidMemoryRange" if (i==0x14): print " kDSReplyInvalidRegisterRange" if (i==0x15): print " kDSReplyCWDSException" if (i==0x16): print " kDSReplyNotStopped" if (i==0x17): print " kDSReplyBreakpointsFull" if (i==0x18): print " kDSReplyBreakpointConflict" if (i==0x20): print " kDSReplyOsError" if (i==0x21): print " kDSReplyInvalidProcessId" if (i==0x22): print " kDSReplyInvalidThreadId" if (nack==1): nack=2 if (ack==1): nack=2 if (sindex==0): if (i==0x00): print "3): print "not 1st byte %02X"%i sindex=sindex+1 previ=i def showFrameChecksum(myBytes): # [01 01 fd] ck = 0 previ=-1 for i in myBytes: # print "showFrameChecksum-i:%i"%i if (i==-1): if (debug>4): print "showFrameChecksum-ck=%02X previ=%02X"%(ck,previ) if (ck!=0xFF): print "showFrameChecksum-incorrect:%i"%i else: if (debug>1): print "showFrameChecksum-correct:%i"%i break else: ck=ck+i if (ck>255): ck=ck-256 previ=i def makeFrameChecksum(myBytes): # [01 01 ??] ck = 0 for i in myBytes: # print "makeFrameChecksum-i:%i"%(i) if (i>=32 and i<127): if (debug>2): print "makeFrameChecksum-i: %c"%(chr(i)) if (i==-1): if (debug>2): print "makeFrameChecksum-ck=%02X return=%02X"%(ck,0xFF-ck) return 0xFF-ck else: ck=ck+i if (ck>255): ck=ck-256 if (debug>2): print "makeFrameChecksum-end-ck=%02X return=%02X"%(ck,0xFF-ck) return 0xFF-ck def sendFrame(ser,myBytes): for i in myBytes: if (i!=-1): if (debug>3): print "sendFrame=%02X"%(i) ser.write(chr(i)) def encodeHeaderCKFrame(myBytes): # [01 01] -> [7e 01 01 fd 7e] ck = makeFrameChecksum(myBytes) sindex=0 myBytes2=[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1] myBytes2=myBytes2+myBytes2+myBytes2+myBytes2 myBytes2=myBytes2+myBytes2+myBytes2+myBytes2 myBytes2[sindex]=0x7e if (debug>=0): print "sending message number %02X"%(myBytes[1]) for i in myBytes: if (i==-1): if (debug>2): print "encodeHeaderCKFrame-ck=%02X"%(ck) if (ck==0x7e or ck==0x7d): myBytes2[sindex+1]=0x7d sindex=sindex+1 ck=ck^0x20 myBytes2[sindex+1]=ck myBytes2[sindex+2]=0x7e myBytes2[sindex+3]=-1 if (debug>2): print myBytes2 return myBytes2 else: if (i==0x7e or i==0x7d): myBytes2[sindex+1]=0x7d sindex=sindex+1 i=i^0x20 myBytes2[sindex+1]=i sindex=sindex+1 # this never happens because the message ends with -1 print "encodeHeaderCKFrame-this message does not finish with -1 !!!!!!!!!!1" return [0] def showFrameBytes(myBytes): # [7e, 01, 01, fd, 7e] if (debug>2): print "showFrameBytes:%s"%myBytes sindex=-1 previ=-1 escaped=-1 myBytes2=[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1] myBytes2=myBytes2+myBytes2+myBytes2+myBytes2 myBytes2=myBytes2+myBytes2+myBytes2+myBytes2 for i in myBytes: if (debug>3): print "showFrameBytes-i:%i"%i if (i==-1): if (previ!=0x7e): print "Frame does not end with 0x7E:%02X"%previ myBytes2[sindex-1]=-1 break; if (previ==-1): if (i!=0x7e): print "Frame does not start with 0x7E:%02X"%i break; if (sindex>0 and (previ==0x7e or previ==0x7d)): escaped=1 if (debug>2): print "XOR: i=%02X previ=%02X xor=%02X "%(i, previ, i^0x20) i=i^0x20 sindex=sindex-1 previ=1 # anything if (sindex>=0): myBytes2[sindex]=i if (escaped==-1): previ=i sindex=sindex+1 escaped=-1 if (debug>3): print myBytes2 showFrameChecksum(myBytes2) decodeFrame(myBytes2) return myBytes2 def showFrameHex(myString): # "[7e 01 01 fd 7e]" if (debug>3): print "showFrameHex:%s"%myString vh=-1 sindex=-1 myBytes=[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1] myBytes=myBytes+myBytes+myBytes+myBytes myBytes=myBytes+myBytes+myBytes+myBytes for i in range(0, len(myString)): if (debug>2): print "showFrameHex-i:%c"%myString[i] c = myString[i] if (c=='a'): c='A' if (c=='b'): c='B' if (c=='c'): c='C' if (c=='d'): c='D' if (c=='e'): c='E' if (c=='f'): c='F' v=-1 if (c=='0'): v=0 if (c=='1'): v=1 if (c=='2'): v=2 if (c=='3'): v=3 if (c=='4'): v=4 if (c=='5'): v=5 if (c=='6'): v=6 if (c=='7'): v=7 if (c=='8'): v=8 if (c=='9'): v=9 if (c=='A'): v=10 if (c=='B'): v=11 if (c=='C'): v=12 if (c=='D'): v=13 if (c=='E'): v=14 if (c=='F'): v=15 if (debug>3): print "showFrameHex-c=v:%c=%i"%(c,v) if (vh>-1): vh=vh+v if (debug>3): print "showFrameHex-b:%02X"%(vh) sindex=sindex+1 myBytes[sindex]=vh vh=-1 else: vh=v*16 if (debug>5): print "showFrameHex-myBytes:%s"%(myBytes) return showFrameBytes(myBytes) def showFrameBin(myString): # [7e 01 01 fd 7e] # print "showFrameBin:%s"%myString # It is binary, so expect weird characters sindex=0 myBytes=[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1] myBytes=myBytes+myBytes+myBytes+myBytes myBytes=myBytes+myBytes+myBytes+myBytes for i in range(0, len(myString)): if (debug>3): print "showFrameHex-i at sindex=%i:%02X"%(sindex,ord(myString[i])) myBytes[sindex] = ord(myString[i]) sindex=sindex+1 myBytes[sindex] = -1 return showFrameBytes(myBytes) # This is the port minus 1. If you have COM4, then use Serial(3) ser = serial.Serial(5) # I have COM6 ser.timeout = 1 print "Using port:" print ser.portstr iCommand=0 iSendFullMessages=0 # by default, use process=ekern.exe[100041af]0001 and thread called 'Supervisor'; unless c:\HelloCarbide.exe is started ProcessIDh=0x00 ProcessIDl=0x01 ThreadIDh=0x00 ThreadIDl=0x1 candidateAddress=0 print ">Ping" sendFrame(ser,encodeHeaderCKFrame([0x00,iCommand,-1])) s = ser.read(10) # Ping get myBytes=showFrameBin(s) if (debug>2): print myBytes iCommand=iCommand+1 print ">Connect" sendFrame(ser,encodeHeaderCKFrame([0x01,iCommand,-1])) # Connect s = ser.read(10) # Connect get myBytes=showFrameBin(s) if (debug>2): print myBytes iCommand=iCommand+1 DS_PROTOCOL=3 # by default, although can be read and verified if (1==1): print ">SupportMask" sendFrame(ser,encodeHeaderCKFrame([0x05,iCommand,-1])) # SupportMask s = ser.read(40) # SupportMask get myBytes=showFrameBin(s) if (debug>2): print myBytes iCommand=iCommand+1 DS_PROTOCOL=myBytes[0+32+3] if (myBytes[0+32+3]==1): print "Level=DS_PROTOCOL_MIN. (required)" if (myBytes[0+32+3]==2): print "Level=DS_PROTOCOL_BOARD. (extended board-level debugger)" if (myBytes[0+32+3]==3): print "Level=DS_PROTOCOL_RTOS. (OS-level debugger)" if (iSendFullMessages==1): print ">CPUType" sendFrame(ser,encodeHeaderCKFrame([0x06,iCommand,-1])) # CPUType s = ser.read(40) # CPUType get myBytes=showFrameBin(s) if (debug>2): print myBytes iCommand=iCommand+1 kDSOSProcessList = 0x0000 kDSOSProcessState = 0x0001 kDSOSThreadList = 0x0002 kDSOSThreadState = 0x0003 kDSOSDLLList = 0x0004 # This gives error kDSReplyUnsupportedOptionError kDSOSDLLState = 0x0005 if (iSendFullMessages==1): print ">Read Info: list threads for process:%02X %02X"%(ProcessIDh,ProcessIDl) sendFrame(ser,encodeHeaderCKFrame([0x42,iCommand,0x00,kDSOSThreadList,0x00,0x00,0x00,0x00,0x00,0x00,0x00,ProcessIDh,ProcessIDl,-1])) # Read Info s = ser.read(1400) myBytes=showFrameBin(s) thisListItem="" for j in myBytes: if (j>=32 and j<=128): # print "Info: %c"%(chr(j)) thisListItem=thisListItem+chr(j) if (j==0): if (len(thisListItem)>1): print "List item: %s"%(thisListItem) thisListItem="" if (debug>2): print myBytes iCommand=iCommand+1 s = ser.read(1400) # there might be more processes/threads/DLLs but I don't care. Just clean the rubbish s = ser.read(1400) s = ser.read(1400) if (iSendFullMessages==1): print ">Open File" # C:\HelloCarbide.exe sendFrame(ser,encodeHeaderCKFrame([0x4A,iCommand,0x10,0x00,0x13,0x43,0x3A,0x5C,0x48,0x65,0x6C,0x6C,0x6F,0x43,0x61,0x72,0x62,0x69,0x64,0x65,0x2E,0x65,0x78,0x65,-1])) # Open File s = ser.read(40) # Open File get myBytes=showFrameBin(s) if (debug>2): print myBytes iCommand=iCommand+1 someData0=myBytes[7] someData1=myBytes[8] someData2=myBytes[9] someData3=myBytes[10] someData4=myBytes[11] if (iSendFullMessages==1): print ">Close File" sendFrame(ser,encodeHeaderCKFrame([0x4B,iCommand,0x00,0x00,0x00,someData0,someData1,someData2,someData3,someData4,-1])) # Close File s = ser.read(40) # Close File get myBytes=showFrameBin(s) if (debug>2): print myBytes iCommand=iCommand+1 if (iSendFullMessages==1): print ">Create Item" # C:\sys\bin\HelloCarbide.exe # sendFrame(ser,encodeHeaderCKFrame([0x4a,iCommand,0x10,0x00,0x1B,0x43 ,0x3A ,0x5C ,0x73 ,0x79 ,0x73 ,0x5C ,0x62 ,0x69 ,0x6E ,0x5C,0x48,0x65,0x6C,0x6C,0x6F,0x43,0x61,0x72,0x62,0x69,0x64,0x65,0x2E,0x65,0x78,0x65, -1])) # Create Item # C:\HelloCarbide.exe sendFrame(ser,encodeHeaderCKFrame([0x40,iCommand,0x00,0x00,0x00,0x00,0x15,0x43,0x3A,0x5C,0x48,0x65,0x6C,0x6C,0x6F,0x43,0x61,0x72,0x62,0x69,0x64,0x65,0x2E,0x65,0x78,0x65,0x00,0x00,-1])) # Create Item s = ser.read(40) # Create Item get myBytes=showFrameBin(s) if (debug>2): print myBytes iCommand=iCommand+1 ProcessIDh=myBytes[5] ProcessIDl=myBytes[6] ThreadIDh=myBytes[9] ThreadIDl=myBytes[10] print "ProcessID=%02X%02X ThreadID=%02X%02X "%(ProcessIDh,ProcessIDl,ThreadIDh,ThreadIDl) if (iSendFullMessages==1): print ">Continue" sendFrame(ser,encodeHeaderCKFrame([0x18,iCommand,0x00,0x00,ProcessIDh,ProcessIDl,0x00 ,0x00,ThreadIDh,ThreadIDl,-1])) # Continue s = ser.read(400) # Ack get + Notify Created get ... size=(3)+(>40) ... should extract messageID and ack it myBytes=showFrameBin(s) if (debug>2): print myBytes iCommand=iCommand+1 print ">Ack Notify Created" sendFrame(ser,encodeHeaderCKFrame([0x80,0x01,0x00,-1])) # Ack Notify Created s = ser.read(40) # There is no answer, but clean buffer # myBytes=showFrameBin(s) # print myBytes # iCommand=iCommand+1 if (iSendFullMessages==1): print ">Read Info 0x60000000" sendFrame(ser,encodeHeaderCKFrame([0x42,iCommand,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x16,-1])) # Read Info s = ser.read(1400) # Read Info get myBytes=showFrameBin(s) if (debug>2): print myBytes s = ser.read(1400) # Read Info get myBytes=showFrameBin(s) if (debug>2): print myBytes s = ser.read(1400) # Read Info get myBytes=showFrameBin(s) if (debug>2): print myBytes s = ser.read(1400) # Read Info get myBytes=showFrameBin(s) if (debug>2): print myBytes iCommand=iCommand+1 DS_MSG_MEMORY_SEGMENTED =0x01 # non-flat addr space DS_MSG_MEMORY_EXTENDED =0x02 # > 32-bit data addr DS_MSG_MEMORY_PROTECTED =0x04 # non-user memory DS_MSG_MEMORY_USERVIEW =0x08 # breakpoints are invisible readSize=0x1 # *256 if (1==1): print "Read memory without process. Only when DS_PROTOCOL<3 . In this case, DS_PROTOCOL=%02X"%(DS_PROTOCOL) readAddress=0x60 sendFrame(ser,encodeHeaderCKFrame([0x1A,iCommand,DS_MSG_MEMORY_PROTECTED,0x00,readSize,0x00,0x00,0,readAddress,-1])) # Stop s = ser.read(400) myBytes=showFrameBin(s) if (debug>2): print myBytes iCommand=iCommand+1 if (1==1): print "Read Memory SEGMENTED without process. Only when DS_PROTOCOL<3 . In this case, DS_PROTOCOL=%02X"%(DS_PROTOCOL) readAddress=0x60 sendFrame(ser,encodeHeaderCKFrame([0x1A,iCommand,DS_MSG_MEMORY_SEGMENTED,0x00,readSize,0x00,0x00,0,readAddress,-1])) # Stop s = ser.read(400) myBytes=showFrameBin(s) if (debug>2): print myBytes iCommand=iCommand+1 if (1==0): print ">Dump memory " readAddressStart=0x60000000 readAddressEnd=readAddressStart+0x300 dumpFile=open('file.dmp', 'wb') for randomAddressBase in range(0,(readAddressEnd-readAddressStart)/256): randomAddressOffset=0 if (1==1): if (randomAddressBase>=0 and randomAddressOffset>=0): readAddress=readAddressStart+randomAddressBase*256 readAddress0=readAddress/(256*256*256) readAddress1=(readAddress-readAddress0*256*256*256)/(256*256) readAddress2=(readAddress-readAddress0*256*256*256-readAddress1*256*256)/(256) readAddress3=(readAddress-readAddress0*256*256*256-readAddress1*256*256-readAddress2*256)/(1) sendFrame(ser,encodeHeaderCKFrame([0x10,iCommand,DS_MSG_MEMORY_PROTECTED+DS_MSG_MEMORY_SEGMENTED,readSize, 0x00, readAddress0,readAddress1,readAddress2,readAddress3 ,0x00,0x00, ProcessIDh,ProcessIDl ,0x00,0x00, ThreadIDh,ThreadIDl,-1])) # Read Memory s = ser.read(400) # Read Memory get myBytes=showFrameBin(s) if (debug>2): print myBytes iCommand=iCommand+1 if (myBytes[2]==0x20): # kDSReplyOsError print "The OS reported an error :-(" else: for i in range(0,readSize*256/4): data0=myBytes[5+i*4+0] data1=myBytes[5+i*4+1] data2=myBytes[5+i*4+2] data3=myBytes[5+i*4+3] print "Read Memory %08X=%02X %02X %02X %02X"%(readAddress+i*4,data0,data1,data2,data3) dumpFile.write(chr(data0)) dumpFile.write(chr(data1)) dumpFile.write(chr(data2)) dumpFile.write(chr(data3)) dumpFile.close() if (1==1): print ">Scanning memory" for randomAddressBase in (0x60000000,0xC2000000,0xC8000000,-1): for randomAddressOffset in (0x00000000,0x00000100,-1): if (randomAddressBase>=0 and randomAddressOffset>=0): readAddress=randomAddressBase+randomAddressOffset readAddress0=readAddress/(256*256*256) readAddress1=(readAddress-readAddress0*256*256*256)/(256*256) readAddress2=(readAddress-readAddress0*256*256*256-readAddress1*256*256)/(256) readAddress3=(readAddress-readAddress0*256*256*256-readAddress1*256*256-readAddress2*256)/(1) print "Read Memory at %08X=%02X %02X %02X %02X"%(readAddress,readAddress0,readAddress1,readAddress2,readAddress3) sendFrame(ser,encodeHeaderCKFrame([0x10,iCommand,DS_MSG_MEMORY_PROTECTED+DS_MSG_MEMORY_SEGMENTED,readSize, 0x00, readAddress0,readAddress1,readAddress2,readAddress3 ,0x00,0x00, ProcessIDh,ProcessIDl ,0x00,0x00, ThreadIDh,ThreadIDl,-1])) # Read Memory s = ser.read(400) # Read Memory get myBytes=showFrameBin(s) if (debug>2): print myBytes iCommand=iCommand+1 if (myBytes[2]==0x20): # kDSReplyOsError print "The OS reported an error :-(" else: mistakes=0 for i in range(0,readSize*256/4): data0=myBytes[5+i*4+0] data1=myBytes[5+i*4+1] data2=myBytes[5+i*4+2] data3=myBytes[5+i*4+3] print "Read Memory %08X=%02X %02X %02X %02X"%(readAddress+i*4,data0,data1,data2,data3) if (i<=7 and data0==-1 and data1==-1 and data2==-1 and data3==-1): mistakes=mistakes+1 if (mistakes>5): print "base address %08X doesn't look correct"%(readAddress) break; if ((data0==0x1F or data0==0x1E or data0==0x1C or data0==0x1A or data0==0x10 ) and data1==0x00 and data2==0x00 and data3==0x00): print "!!!!!!!!!!!!!!!!!!!!!!!!!!!candidate!!!!!!!!!!!!!!!!!" candidateAddress=readAddress+i*4 break; # nevertheless will continue scanning if (candidateAddress>0): print ">Write Memory %08X"%(candidateAddress) writeAddress=candidateAddress writeAddress0=writeAddress/(256*256*256) writeAddress1=(writeAddress-writeAddress0*256*256*256)/(256*256) writeAddress2=(writeAddress-writeAddress0*256*256*256-writeAddress1*256*256)/(256) writeAddress3=(writeAddress-writeAddress0*256*256*256-writeAddress1*256*256-writeAddress2*256)/(1) print "write Memory at %08X=%02X %02X %02X %02X"%(writeAddress,writeAddress0,writeAddress1,writeAddress2,writeAddress3) writeSize=0x4 dataWrite0=0x10 sendFrame(ser,encodeHeaderCKFrame([0x11,iCommand,0x08,0x00,writeSize,writeAddress0,writeAddress1,writeAddress2,writeAddress3,0x00,0x00,ProcessIDh,ProcessIDl,0x00,0x00,ThreadIDh,ThreadIDl,dataWrite0,0x00,0x00,0x00,-1])) # write Memory s = ser.read(400) # Write Memory get myBytes=showFrameBin(s) if (debug>2): print myBytes iCommand=iCommand+1 print ">Stop" sendFrame(ser,encodeHeaderCKFrame([0x1A,iCommand,0x02,0x00,0x00,ProcessIDh,ProcessIDl,0x00,0x00,ThreadIDh,ThreadIDl,-1])) # Stop s = ser.read(1400) # Stop get + Notify Stopped ... should extract messageID and ack it myBytes=showFrameBin(s) if (debug>2): print myBytes iCommand=iCommand+1 print ">Ack Notify Stopped" sendFrame(ser,encodeHeaderCKFrame([0x80,0x02,0x00,-1])) # Ack Notify Stopped s = ser.read(40) # There is no answer, but clean buffer # myBytes=showFrameBin(s) # print myBytes # iCommand=iCommand+1 print ">Disconnect" sendFrame(ser,encodeHeaderCKFrame([0x02,iCommand,-1])) # Disconnect s = ser.read(40) # Disconnect get myBytes=showFrameBin(s) if (debug>2): print myBytes iCommand=iCommand+1 print ">Close" ser.close() print ">End+Exit"