Hello Dennis and Bryan! You were absolutely right. I should show you real code instead of brain fucking. I am very sorry. Please find below real code. Sorry for amount of sources. Main aspect of program is all process should be in one determined sequence containing 3 stages. They are defined as stage1(), stage2() and stage3() in appMainFrame() Execution started when Start button presses (handler def OnStart() in appMainFrame() ). At the same time CardsObserver calls appMainFrame.addCards() to increment counter and in each stages wait this counter. All other code from library.
Kind regards, /Gelios #######################Main application:################################ #exception class class NotASIMCardException: def __init__( self, message ): self.message = message def __str__(self): return repr( self.message ) class SmartCardOperations: def getATR( self, readerDescr ): atr="" self.attachedReaders = readers() for reader in self.attachedReaders: if readerDescr == str( reader ): connection=reader.createConnection() try: connection.connect() atr=toHexString( connection.getATR() ) connection.disconnect() except NoCardException: atr="no card inserted" return atr def decodeICCID( self, iccidBytes ): resIccid = [] #swap bytes i = 0 while i < len(iccidBytes): strTmp = str( hex( iccidBytes[i] ) ) if len(strTmp) == 3: strTmp = strTmp[0] + strTmp[1] + "0" + strTmp[2] resIccid += [strTmp[3] + strTmp[2]] i += 1 #remove last 2 bytes resIccid = resIccid[:-2] #remove first last digit strTmp = str( resIccid[i-3] ) if len(strTmp) == 1: strTmp += "0" resIccid[i-3] = strTmp[0] return resIccid def getICCID(self, readerDescr): self.attachedReaders = readers() for reader in self.attachedReaders: if readerDescr == str( reader ): session = smartcard.Session( reader ) try: data, sw1, sw2 = session.sendCommandAPDU( SELECT + DF_ROOT ) data, sw1, sw2 = session.sendCommandAPDU( SELECT + EF_ICCID ) data, sw1, sw2 = session.sendCommandAPDU( READ_BINARY + [0x0A]) if sw1 == 0x90 or sw1 == 0x91: msg = "Ok" else: msg = "ICCID read error. Error code: " + str(hex(sw1)) + str(hex(sw2)) session.close() except NoCardException: msg = "ICCID read error. Error code: " + str(hex(sw1)) + str(hex(sw2)) return msg, self.decodeICCID(data), data def getADM0( self, readerDescr, iccid ): self.attachedReaders = readers() for reader in self.attachedReaders: if readerDescr == str( reader ): session = smartcard.Session( reader ) try: data, sw1, sw2 = session.sendCommandAPDU( SAM_SEND_ICCID + iccid ) resBytesStr = str(sw1) + ' ' + str(sw2) if resBytesStr != "61 08": msg = "?????? ?????? ? SAM ??????" return msg, None data, sw1, sw2 = session. sendCommandAPDU( SAM_GET_ADM0 ) except NoCardException: msg = "ADM0 getting error. Error code: " + str(hex(sw1)) + str(hex(sw2)) msg = "Ok" return msg, data def chgEfLnd( self, iccid, adm0 ): self.attachedReaders = readers() for reader in self.attachedReaders: if readerDescr == str( reader ): session = smartcard.Session( reader ) try: data, sw1, sw2 = session.sendCommandAPDU( VERIFY_KEY_SIMERA3 + adm0 ) resBytesStr = str(sw1) + ' ' + str(sw2) if resBytesStr == "98 04" or resBytesStr == "98 40": msg = "?????? ??????? ? ?????" return msg data, sw1, sw2 = session.sendCommandAPDU( SELECT + DF_ROOT ) data, sw1, sw2 = session.sendCommandAPDU( SELECT + DF_GSM ) data, sw1, sw2 = session.sendCommandAPDU( DELETE_FILE ) if sw1 != 0x90 or sw1 != 0x91: msg = "?????? ??????? ? ?????" return msg data, sw1, sw2 = session.sendCommandAPDU( SELECT + DF_GSM ) data, sw1, sw2 = session.sendCommandAPDU( smartcard.util.toBytes(CREATE_FILE_APDU) if sw1 != 0x90 or sw1 != 0x91: msg = "?????? ??????? ? ?????" return msg except NoCardException: msg = "ADM0 getting error. Error code: " + str(hex(sw1)) + str(hex(sw2)) msg = "Ok" return msg class appMainFrame(wx.Frame): def __init__(self, parent, title): wx.Frame.__init__(self, parent, -1, title, pos=(150,150), size=(640,400), style = wx.CAPTION | wx.MINIMIZE_BOX | wx.CLOSE_BOX | wx.SYSTEM_MENU) self.panel = wx.Panel(self) # select reader controls self.selectReaderTxt = wx.StaticText(self.panel, -1, "?????????? ???????? reader: ", pos = (10, 12), size = (170, 21)) self.readerChoice = wx.Choice(self.panel, 120, pos = (180, 10), size = (230,21), choices=['?? ??????']) self.readerChoice.Select( 0 ) EVT_CHOICE( self, 120, self.selectReader) self.cardDescr = wx.TextCtrl(self.panel, -1, "????? ?? ?????????", pos = (415, 10), size = (205,21), style = wx.TE_READONLY ) self.staticLine2 = wx.StaticLine( self.panel, 210, pos = (10, 40), size = (610, 2) ) #Log self.logAreaTxt = wx.StaticText(self.panel, -1, "??????: ", pos = (10, 50), size = (105, 21)) self.logArea = wx.TextCtrl( self.panel, 301, "", pos = (10, 72), size = (610, 260), style=wx.TE_MULTILINE | wx.TE_READONLY ) self.saveLogButton = wx.Button( self.panel, -1, "?????? ??????? ? ????", pos = (20, 345) ) EVT_BUTTON( self, self.saveLogButton.GetId(), self.OnSaveLog ) #Buttons self.resetButton = wx.Button( self.panel, -1, "?????", pos = (300, 345) ) self.startButton = wx.Button( self. panel, -1, "?????", pos = (380, 345) ) self.closeButton = wx.Button( self.panel, -1, "?????", pos = (460, 345) ) EVT_BUTTON( self, self.resetButton.GetId(), self.OnReset ) EVT_BUTTON( self, self.startButton.GetId(), self.OnStart ) EVT_BUTTON( self, self.closeButton.GetId(), self.OnClose ) # Set properties self.SetTitle(title) self.Layout() #Smart card operations self.scOps = SmartCardOperations() self.START = False self.step = None self.cardEvent = threading.Event() def selectReader(self, event): self.selectedReader = event.GetString() self.cardDescr.SetValue( self.scOps.getATR(self.selectedReader) ) def removeReaders( self, removedreaders ): for readerToRemove in removedreaders: self.readerChoice.Delete( self.readerChoice.FindString( str( readerToRemove ) ) ) def addReaders( self, addedreaders ): for readerToAdd in addedreaders: self.readerChoice.Append( str ( readerToAdd ) ) def removeCards( self, removedcards ): if self.readerChoice.GetSelection() != 0: self.cardDescr.SetValue("????? ?? ?????????.") else: self.cardDescr.SetValue("?? ?????? reader.") def addCards( self, cardsToAdd ): if self.readerChoice.GetSelection() != 0: self.cardDescr.SetValue( self.scOps.getATR(self.selectedReader) ) if self.START == True: rpdb2.settrace() if self.step != None: self.step.release() #self.cardEvent.set() def OnReset( self, event ): if self.step != None: self.step = None self.START = False self.logArea.AppendText("????? ????????. ??? ?????? ??????? ?????\n") event.Skip() def OnClose( self, event ): sys.exit() event.Skip() def OnStart( self, event ): self.START = True self.step = threading.Semaphore(0) if self.step == 0: #start process #STAGE 1 self.logArea.AppendText( "1. ?????????? ???????? ?????????????? ????? ? reader\n" ) iccid, plainIccid = self.stage1() if iccid == None: event.Skip() return None self.logArea.AppendText( "?????????? ?????? ?????????????? ?????\n" ) #STAGE 2 self.logArea.AppendText( "2. ?????????? ???????? SAM ????? ? reader\n" ) adm0 = self.stage2( plainIccid ) if adm0 == None: event.Skip() return None self.logArea.AppendText( "?????????? ?????? SAM ?????\n" ) #STAGE 3 self.logArea.AppendText( "3. ?????????? ???????? ?????????????? ????? ? reader\n" ) result = self.stage3(iccid, adm0) if result == True: self.logArea.AppendText( "????? ??????? ??????????\n" ) else: self.logArea.AppendText( "?????? ????????? ?????.\n" ) else: self.logArea.AppendText( "??????? ??? ???????? ? ???????????? ??????????????????. ??????? ????? ? ??????? ??????\n" ) self.step = None self.START = False def stage1( self ): #wait SIM card insertion while self.step != 1: pass rpdb2.settrace() ###########################BLOCKING HERE################################## if not self.cardEvent.isSet(): self.cardEvent.wait() self.cardEvent.clear() #check inserted card is a SIM card msg, atr = self.scOps.getATR( self.selectedReader ) while atr == SAM_ATR: self.logArea.AppendText( "??????????? ????? ???????? SAM ??????. ?????????? ???????? SIM ????? ? reader\n" ) ########## Decrement semaphore value############## self.step.acquire() msg, atr = self.scOps.getATR( self.selectedReader ) if msg != "Ok": self.logArea.AppendText( "?????? ?????? ?????. ??????? ????? ? ??????? ??????\n" ) return None, None #read iccid of sim card msg, iccid, plainIccid = self.scOps.getICCID( self.selectedReader ) if msg != "Ok": self.logArea.AppendText( "?????? ?????? ?????. ??????? ????? ? ??????? ??????\n" ) return None, None return iccid, plainIccid def stage2( self, iccid ): #wait SAM card insertion while self.step != 2: pass #while not self.cardEvent.isSet(): # self.cardEvent.wait() #self.cardEvent.clear() #check is it SAM card msg, atr = self.scOps.getATR( self.selectedReader ) while atr != SAM_ATR: self.logArea.AppendText( "??????????? ????? ???????? ?? SAM ??????. ?????????? ???????? SAM ????? ? reader\n" ) ########## Decrement semaphore value############## self.step.acquire() msg, atr = self.scOps.getATR( self.selectedReader ) if msg != "Ok": self.logArea.AppendText( "?????? ?????? ?????. ??????? ????? ? ??????? ??????\n" ) return None #get ADM0 key msg, adm0 = self.scOps.getADM0( self.selectedReader, iccid ) if msg != "Ok": self.logArea.AppendText( "?????? ?????? ? SAM ??????. ??????? ????? ? ??????? ??????\n" ) return None return adm0 def stage3( self, old_iccid, adm0 ): #wait SIM card insertion while self.step != 3: pass #while not self.cardEvent.isSet(): # self.cardEvent.wait() #self.cardEvent.clear() #check ATR msg, atr = self.scOps.getATR( self.selectedReader ) while atr == SAM_ATR: self.logArea.AppendText( "??????????? ????? ???????? ?? SAM ??????. ?????????? ???????? SAM ????? ? reader\n" ) ########## Decrement semaphore value############## self.step.acquire() msg, atr = self.scOps.getATR( self.selectedReader ) if msg != "Ok": return False #check iccid msg, new_iccid, plain_new_iccid = self.scOps.getICCID( self.selectedReader ) if msg != "Ok": return False while old_iccid != new_iccid: if old_iccid != new_iccid: self.logArea.AppendText( "? reader ????????? ????? ? ICCID=" + str(new_iccid) + ". ????????? ??????? ????? ? ICCID=" + str(old_iccid)) msg = self.scOps.chgEfLnd(plain_new_iccid, adm0) if msg != "Ok": return False return True def OnSaveLog(self, event): dlg = wx.FileDialog(self, "Choose a file", ".", "", "*.*", wx.OPEN) try: if dlg.ShowModal() == wx.ID_OK: filename = dlg.GetPath() logfile = open(filename, 'w') logfile.write(self.logArea.GetValue()) logfile.close() finally: dlg.Destroy() def showMessage( self, message, title): msgWin = wxMessageDialog ( None, message, title, wxOK ) msgWin.ShowModal() msgWin.Destroy() class ReadersObserver: def __init__ ( self, frame ): self.mainFrame = frame def update( self, observable, ( addedreaders, removedreaders ) ): self.mainFrame.removeReaders( removedreaders ) self.mainFrame.addReaders( addedreaders ) class CardsObserver: def __init__( self, frame ): self.mainFrame = frame def update( self, observable, ( addedcards, removedcards ) ): self.mainFrame.removeCards( removedcards ) self.mainFrame.addCards( addedcards ) class appChgLnd(wx.PySimpleApp): def OnInit(self): #create frame self.appFrame = appMainFrame(None, "SimUpdate") self.SetTopWindow( self.appFrame ) #create observer class instances readersObserver = ReadersObserver( self.appFrame ) cardsObserver = CardsObserver( self.appFrame ) #subscribe to readers monitor and card monitor self.cardsMonitor = CardMonitor() self.cardsMonitor.addObserver( cardsObserver ) self.readersMonitor = ReaderMonitor() self.readersMonitor.addObserver( readersObserver ) #show frame self.appFrame.Show(True) return True if __name__ == '__main__': try: app = appChgLnd(0) app.MainLoop() except: traceback.print_exc( file=open('errors.log', 'w')) ########################################## CARD OBSERVER################################### from sys import exc_info from threading import Thread, Event from time import sleep from smartcard.System import readers from smartcard.Exceptions import CardRequestTimeoutException from smartcard.Observer import Observer from smartcard.Observer import Observable from smartcard.CardType import AnyCardType from smartcard.CardRequest import CardRequest # CardObserver interface class CardObserver(Observer): """ CardObserver is a base abstract class for objects that are to be notified upon smartcard reader insertion/removal. """ def __init__(self): pass def update( self, observable, (addedcards, removedcards) ): """Called upon reader insertion/removal. observable: addedcards: list of added readers causing notification removedcards: list of removed readers causing notification """ pass class CardMonitor: """Class that monitors smart card insertion/removal. and notify observers """ class __CardMonitorSingleton( Observable ): """The real smartcard monitor class. A single instance of this class is created by the public CardMonitor class. """ def __init__(self): Observable.__init__(self) self.rmthread=None def addObserver(self, observer): """Add an observer. We only start the card monitoring thread when there are observers. """ Observable.addObserver( self, observer ) if self.countObservers()>0 and self.rmthread==None: self.rmthread = CardMonitoringThread( self ) def deleteObserver(self, observer): """Remove an observer. We delete the CardMonitoringThread reference when there are no more observers. """ Observable.deleteObserver( self, observer ) if self.countObservers()==0: if self.rmthread!=None: self.rmthread=None # the singleton instance = None def __init__(self): if not CardMonitor.instance: CardMonitor.instance = CardMonitor.__CardMonitorSingleton() def __getattr__(self, name): return getattr(self.instance, name) class CardMonitoringThread: """Card insertion thread. This thread waits for card insertion. """ class __CardMonitoringThreadSingleton( Thread ): """The real card monitoring thread class. A single instance of this class is created by the public CardMonitoringThread class. """ def __init__(self, observable): Thread.__init__(self) self.observable=observable self.stopEvent = Event() self.stopEvent.clear() self.cards = [] self.cardrequest = CardRequest( timeout=2 ) self.setDaemon(True) # the actual monitoring thread def run(self): """Runs until stopEvent is notified, and notify observers of all card insertion/removal. """ while self.stopEvent.isSet()!=1: try: currentcards = self.cardrequest.waitforcardevent() addedcards=[] for card in currentcards: if not self.cards.__contains__( card ): addedcards.append( card ) removedcards=[] for card in self.cards: if not currentcards.__contains__( card ): removedcards.append( card ) if addedcards!=[] or removedcards!=[]: self.cards=currentcards self.observable.setChanged() self.observable.notifyObservers( (addedcards, removedcards) ) except: import sys print sys.exc_info()[1] print sys.exc_info()[2] print sys.exc_info()[0] # stop the thread by signaling stopEvent def stop(self): self.stopEvent.set() # the singleton instance = None def __init__(self, observable): if not CardMonitoringThread.instance: CardMonitoringThread.instance = CardMonitoringThread.__CardMonitoringThreadSingleton( observable ) CardMonitoringThread.instance.start() def __getattr__(self, name): return getattr(self.instance, name) def __del__(self): if CardMonitoringThread.instance!=None: CardMonitoringThread.instance.stop() CardMonitoringThread.instance = None ##################################### GENERAL OBSERVER############################## Class support for "observer" pattern. The observer class is the base class for all smartcard package observers. """ from smartcard.Synchronization import * class Observer: def update(observable, arg): '''Called when the observed object is modified. You call an Observable object's notifyObservers method to notify all the object's observers of the change.''' pass class Observable(Synchronization): def __init__(self): self.obs = [] self.changed = 0 Synchronization.__init__(self) def addObserver(self, observer): if observer not in self.obs: self.obs.append(observer) def deleteObserver(self, observer): self.obs.remove(observer) def notifyObservers(self, arg = None): '''If 'changed' indicates that this object has changed, notify all its observers, then call clearChanged(). Each observer has its update() called with two arguments: this observable object and the generic 'arg'.''' self.mutex.acquire() try: if not self.changed: return # Make a local copy in case of synchronous # additions of observers: localArray = self.obs[:] self.clearChanged() finally: self.mutex.release() # Updating is not required to be synchronized: for observer in localArray: observer.update(self, arg) def deleteObservers(self): self.obs = [] def setChanged(self): self.changed = 1 def clearChanged(self): self.changed = 0 def hasChanged(self): return self.changed def countObservers(self): return len(self.obs) synchronize(Observable, "addObserver deleteObserver deleteObservers " + "setChanged clearChanged hasChanged " + "countObservers") #:~ ############################ SYNC###################### Simple emulation of Java's 'synchronized' keyword, from Peter Norvig. """ from threading import RLock def synchronized(method): def f(*args): self = args[0] self.mutex.acquire(); # print method.__name__, 'acquired' try: return apply(method, args) finally: self.mutex.release(); # print method.__name__, 'released' return f def synchronize(klass, names=None): """Synchronize methods in the given class. Only synchronize the methods whose names are given, or all methods if names=None.""" if type(names)==type(''): names = names.split() for (name, val) in klass.__dict__.items(): if callable(val) and name != '__init__' and \ (names == None or name in names): # print "synchronizing", name klass.__dict__[name] = synchronized(val) # You can create your own self.mutex, or inherit # from this class: class Synchronization: def __init__(self): self.mutex = RLock() #:~ -- http://mail.python.org/mailman/listinfo/python-list