From 27ac653dea3ebb218d915604a8fce4b0d34d9278 Mon Sep 17 00:00:00 2001 From: Andreas Monzner Date: Tue, 23 May 2006 12:29:43 +0000 Subject: [PATCH] CI mmi is now working every time (for support alphacrypt parental control or other messages from CI) --- lib/dvb_ci/dvbci_appmgr.cpp | 4 +- lib/dvb_ci/dvbci_mmi.cpp | 22 ++++- lib/dvb_ci/dvbci_session.cpp | 2 +- lib/dvb_ci/dvbci_ui.cpp | 34 ++++++- lib/dvb_ci/dvbci_ui.h | 6 +- lib/python/Screens/Ci.py | 205 ++++++++++++++++++++++++++---------------- lib/python/Screens/InfoBar.py | 3 + lib/python/enigma_python.i | 2 +- 8 files changed, 191 insertions(+), 87 deletions(-) diff --git a/lib/dvb_ci/dvbci_appmgr.cpp b/lib/dvb_ci/dvbci_appmgr.cpp index 201b36c..f815973 100644 --- a/lib/dvb_ci/dvbci_appmgr.cpp +++ b/lib/dvb_ci/dvbci_appmgr.cpp @@ -47,9 +47,9 @@ int eDVBCIApplicationManagerSession::receivedAPDU(const unsigned char *tag,const printf("%c", ((unsigned char*)data)[i+6]); printf("\n"); - eDVBCI_UI::getInstance()->setState(slot->getSlotID(), 2); - eDVBCI_UI::getInstance()->setAppName(slot->getSlotID(), str); + + eDVBCI_UI::getInstance()->setState(slot->getSlotID(), 2); break; } default: diff --git a/lib/dvb_ci/dvbci_mmi.cpp b/lib/dvb_ci/dvbci_mmi.cpp index d3f564d..2971066 100644 --- a/lib/dvb_ci/dvbci_mmi.cpp +++ b/lib/dvb_ci/dvbci_mmi.cpp @@ -25,6 +25,7 @@ eDVBCIMMISession::eDVBCIMMISession(eDVBCISlot *tslot) eDVBCIMMISession::~eDVBCIMMISession() { slot->setMMIManager(NULL); + eDVBCI_UI::getInstance()->mmiSessionDestroyed(slot->getSlotID()); } int eDVBCIMMISession::receivedAPDU(const unsigned char *tag, const void *data, int len) @@ -38,7 +39,26 @@ int eDVBCIMMISession::receivedAPDU(const unsigned char *tag, const void *data, i { switch (tag[2]) { - case 0x01: + case 0x00: //Tmmi_close + { + unsigned char *d=(unsigned char*)data; + int timeout=0; + if (d[3] == 1) + { + if (len > 4) + timeout = d[4]; + else + { + eDebug("mmi close tag incorrect.. no timeout given.. assume 5 seconds"); + timeout = 5; + } + } + else if (timeout>1) + eDebug("mmi close tag incorrect.. byte 4 should be 0 or 1"); + eDVBCI_UI::getInstance()->mmiScreenClose(slot->getSlotID(), timeout); + break; + } + case 0x01: printf("MMI display control\n"); if (((unsigned char*)data)[0] != 1) printf("kann ich nicht. aber das sag ich dem modul nicht.\n"); diff --git a/lib/dvb_ci/dvbci_session.cpp b/lib/dvb_ci/dvbci_session.cpp index 7156811..e0e64be 100644 --- a/lib/dvb_ci/dvbci_session.cpp +++ b/lib/dvb_ci/dvbci_session.cpp @@ -319,6 +319,6 @@ void eDVBCISession::receiveData(eDVBCISlot *slot, const unsigned char *ptr, size eDVBCISession::~eDVBCISession() { - printf("destroy %p\n", this); +// printf("destroy %p\n", this); } diff --git a/lib/dvb_ci/dvbci_ui.cpp b/lib/dvb_ci/dvbci_ui.cpp index 306bcd1..56ca25f 100644 --- a/lib/dvb_ci/dvbci_ui.cpp +++ b/lib/dvb_ci/dvbci_ui.cpp @@ -54,7 +54,10 @@ int eDVBCI_UI::getState(int slot) void eDVBCI_UI::setState(int slot, int newState) { if (slot < MAX_SLOTS) + { slotdata[slot].state = newState; + /*emit*/ ciStateChanged(slot); + } } std::string eDVBCI_UI::getAppName(int slot) @@ -117,6 +120,28 @@ int eDVBCI_UI::availableMMI(int slot) return false; } +int eDVBCI_UI::mmiScreenClose(int slot, int timeout) +{ + if (slot >= MAX_SLOTS) + return 0; + + slot_ui_data &data = slotdata[slot]; + + data.mmiScreenReady = 0; + + if (data.mmiScreen) + Py_DECREF(data.mmiScreen); + data.mmiScreen = PyList_New(1); + + PyObject *tuple = PyTuple_New(2); + PyTuple_SET_ITEM(tuple, 0, PyString_FromString("CLOSE")); + PyTuple_SET_ITEM(tuple, 1, PyLong_FromLong(timeout)); + PyList_SET_ITEM(data.mmiScreen, 0, tuple); + data.mmiScreenReady = 1; + /*emit*/ ciStateChanged(slot); + return 0; +} + int eDVBCI_UI::mmiScreenEnq(int slot, int blind, int answerLen, char *text) { if (slot >= MAX_SLOTS) @@ -144,6 +169,8 @@ int eDVBCI_UI::mmiScreenEnq(int slot, int blind, int answerLen, char *text) data.mmiScreenReady = 1; + /*emit*/ ciStateChanged(slot); + return 0; } @@ -217,11 +244,16 @@ int eDVBCI_UI::mmiScreenFinish(int slot) { printf("eDVBCI_UI::mmiScreenFinish\n"); slotdata[slot].mmiScreenReady = 1; - /*emit*/ mmiAvail(slot); + /*emit*/ ciStateChanged(slot); } return 0; } +void eDVBCI_UI::mmiSessionDestroyed(int slot) +{ + /*emit*/ ciStateChanged(slot); +} + int eDVBCI_UI::getMMIState(int slot) { return eDVBCIInterfaces::getInstance()->getMMIState(slot); diff --git a/lib/dvb_ci/dvbci_ui.h b/lib/dvb_ci/dvbci_ui.h index 640a3b9..b7922bb 100644 --- a/lib/dvb_ci/dvbci_ui.h +++ b/lib/dvb_ci/dvbci_ui.h @@ -28,7 +28,7 @@ class eDVBCI_UI ~eDVBCI_UI(); #endif public: - PSignal1 mmiAvail; + PSignal1 ciStateChanged; #ifndef SWIG eDVBCI_UI(); ~eDVBCI_UI(); @@ -45,17 +45,17 @@ public: int stopMMI(int slot); int availableMMI(int slot); int getMMIState(int slot); - int answerMenu(int slot, int answer); int answerEnq(int slot, char *val); int cancelEnq(int slot); PyObject *getMMIScreen(int slot); - + int mmiScreenClose(int slot, int timeout); int mmiScreenEnq(int slot, int blind, int answerLen, char *text); int mmiScreenBegin(int slot, int listmenu); int mmiScreenAddText(int slot, int type, char *value); int mmiScreenFinish(int slot); + void mmiSessionDestroyed(int slot); }; #endif diff --git a/lib/python/Screens/Ci.py b/lib/python/Screens/Ci.py index 9bf5b16..10e33cf 100644 --- a/lib/python/Screens/Ci.py +++ b/lib/python/Screens/Ci.py @@ -24,9 +24,8 @@ class CiMmi(Screen): self.slotid = slotid - self.Timer = eTimer() - self.Timer.timeout.get().append(self.TimerCheck) - self.Timer.start(1000) + self.timer = eTimer() + self.timer.timeout.get().append(self.keyCancel) #else the skins fails self["title"] = Label("") @@ -56,12 +55,7 @@ class CiMmi(Screen): self.action = action - if action == 0: #reset - eDVBCI_UI.getInstance().setReset(self.slotid) - self.showWait() - elif action == 1: #init - eDVBCI_UI.getInstance().setInit(self.slotid) - elif action == 2: #start MMI + if action == 2: #start MMI eDVBCI_UI.getInstance().startMMI(self.slotid) self.showWait() elif action == 3: #mmi already there (called from infobar) @@ -84,7 +78,7 @@ class CiMmi(Screen): self["bottom"].setText(_("please press OK when ready")) def okbuttonClick(self): - print "ok" + self.timer.stop() if self.tag == "WAIT": print "do nothing - wait" elif self.tag == "MENU": @@ -109,11 +103,11 @@ class CiMmi(Screen): self.showWait() def closeMmi(self): - self.Timer.stop() - self.close() + self.timer.stop() + self.close(self.slotid) def keyCancel(self): - print "keyCancel" + self.timer.stop() if self.tag == "WAIT": eDVBCI_UI.getInstance().stopMMI(self.slotid) self.closeMmi() @@ -129,18 +123,22 @@ class CiMmi(Screen): print "give cancel action to ci" def keyConfigEntry(self, key): + self.timer.stop() try: self["entries"].handleKey(key) - except AttributeError: + except: pass def keyNumberGlobal(self, number): + self.timer.stop() self.keyConfigEntry(config.key[str(number)]) def keyLeft(self): + self.timer.stop() self.keyConfigEntry(config.key["prevElement"]) def keyRight(self): + self.timer.stop() self.keyConfigEntry(config.key["nextElement"]) def updateList(self, list): @@ -180,23 +178,30 @@ class CiMmi(Screen): list = [ ] - self.tag = screen[0][0] - - for entry in screen: - if entry[0] == "PIN": - self.addEntry(list, entry) + self.timer.stop() + if len(screen) > 0 and screen[0][0] == "CLOSE": + timeout = screen[0][1] + if timeout > 0: + self.timer.start(timeout*1000, True) else: - if entry[0] == "TITLE": - self["title"].setText(entry[1]) - elif entry[0] == "SUBTITLE": - self["subtitle"].setText(entry[1]) - elif entry[0] == "BOTTOM": - self["bottom"].setText(entry[1]) - elif entry[0] == "TEXT": + self.keyCancel() + else: + self.tag = screen[0][0] + for entry in screen: + if entry[0] == "PIN": self.addEntry(list, entry) - self.updateList(list) - - def TimerCheck(self): + else: + if entry[0] == "TITLE": + self["title"].setText(entry[1]) + elif entry[0] == "SUBTITLE": + self["subtitle"].setText(entry[1]) + elif entry[0] == "BOTTOM": + self["bottom"].setText(entry[1]) + elif entry[0] == "TEXT": + self.addEntry(list, entry) + self.updateList(list) + + def ciStateChanged(self): if self.action == 0: #reset self.closeMmi() if self.action == 1: #init @@ -210,73 +215,117 @@ class CiMmi(Screen): if eDVBCI_UI.getInstance().getMMIState(self.slotid) != 1: self.closeMmi() - if eDVBCI_UI.getInstance().availableMMI(self.slotid) == 1: + if self.action > 1 and eDVBCI_UI.getInstance().availableMMI(self.slotid) == 1: self.showScreen() #FIXME: check for mmi-session closed -class CiSelection(Screen): - def createMenu(self): - self.list = [ ] - self.list.append( (_("Reset"), 0) ) - self.list.append( (_("Init"), 1) ) - - self.state = eDVBCI_UI.getInstance().getState(0) - if self.state == 0: #no module - self.list.append( (_("no module found"), 2) ) - elif self.state == 1: #module in init - self.list.append( (_("init module"), 2) ) - elif self.state == 2: #module ready - #get appname - appname = eDVBCI_UI.getInstance().getAppName(0) - self.list.append( (appname, 2) ) +class CiMessageHandler: + def __init__(self): + self.session = None + self.ci = { } + self.dlgs = { } + eDVBCI_UI.getInstance().ciStateChanged.get().append(self.ciStateChanged) - self["entries"].list = self.list - self["entries"].l.setList(self.list) + def setSession(self, session): + self.session = session - def TimerCheck(self): - state = eDVBCI_UI.getInstance().getState(0) - if self.state != state: - #print "something happens" - self.state = state - self.createMenu() - - def okbuttonClick(self): - self.slot = 0 - - if self.state == 2: - self.session.open(CiMmi, 0, self["entries"].getCurrent()[1]) + def ciStateChanged(self, slot): + if slot in self.ci: + self.ci[slot](slot) + else: + if slot in self.dlgs: + self.dlgs[slot].ciStateChanged() + elif eDVBCI_UI.getInstance().availableMMI(slot) == 1: + if self.session: + self.dlgs[slot] = self.session.openWithCallback(self.dlgClosed, CiMmi, slot, 3) + else: + print "no session" - #generate menu / list - #list = [ ] - #list.append( ("TEXT", "CA-Info") ) - #list.append( ("TEXT", "Card Status") ) - #list.append( ("PIN", 6, "Card Pin", 1) ) - #self.session.open(CiMmi, 0, 0, "Wichtiges CI", "Mainmenu", "Footer", list) + def dlgClosed(self, slot): + del self.dlgs[slot] - def cancel(self): - self.Timer.stop() - self.close() + def registerCIMessageHandler(self, slot, func): + self.unregisterCIMessageHandler(slot) + self.ci[slot] = func - def mmiAvail(self, slot): - print "mmi avail slot", slot + def unregisterCIMessageHandler(self, slot): + if slot in self.ci: + del self.ci[slot] +CiHandler = CiMessageHandler() + +class CiSelection(Screen): def __init__(self, session): - #FIXME support for one ci only Screen.__init__(self, session) - - self["actions"] = ActionMap(["OkCancelActions"], + + self["actions"] = ActionMap(["OkCancelActions"], { "ok": self.okbuttonClick, "cancel": self.cancel }) + self.dlg = None + self.state = { } self.list = [ ] self["entries"] = MenuList(list) - self.createMenu() + self.clearMenu() + self.createMenu(0) # FIXME more than one CI + CiHandler.registerCIMessageHandler(0, self.ciStateChanged) + + def clearMenu(self): + self.list = [ ] + + def createMenu(self, slot): + self.list.append( (_("Reset"), 0, slot) ) + self.list.append( (_("Init"), 1, slot) ) + + self.state[slot] = eDVBCI_UI.getInstance().getState(slot) + if self.state[slot] == 0: #no module + self.list.append( (_("no module found"), 2, slot) ) + elif self.state[slot] == 1: #module in init + self.list.append( (_("init module"), 2, slot) ) + elif self.state[slot] == 2: #module ready + #get appname + appname = eDVBCI_UI.getInstance().getAppName(slot) + self.list.append( (appname, 2, slot) ) + + self["entries"].list = self.list + self["entries"].l.setList(self.list) + + def ciStateChanged(self, slot): + if self.dlg: + self.dlg.ciStateChanged() + else: + state = eDVBCI_UI.getInstance().getState(slot) + if self.state[slot] != state: + #print "something happens" + self.state[slot] = state + self.clearMenu() + self.createMenu(slot) - self.Timer = eTimer() - self.Timer.timeout.get().append(self.TimerCheck) - self.Timer.start(1000) + def dlgClosed(self, slot): + self.dlg = None - eDVBCI_UI.getInstance().mmiAvail.get().append(self.mmiAvail) + def okbuttonClick(self): + cur = self["entries"].getCurrent() + if cur: + action = cur[1] + slot = cur[2] + if action == 0: #reset + eDVBCI_UI.getInstance().setReset(slot) + elif action == 1: #init + eDVBCI_UI.getInstance().setInit(slot) + elif self.state[slot] == 2: + self.dlg = self.session.openWithCallback(self.dlgClosed, CiMmi, slot, action) + + #generate menu / list + #list = [ ] + #list.append( ("TEXT", "CA-Info") ) + #list.append( ("TEXT", "Card Status") ) + #list.append( ("PIN", 6, "Card Pin", 1) ) + #self.session.open(CiMmi, 0, 0, "Wichtiges CI", "Mainmenu", "Footer", list) + + def cancel(self): + CiHandler.unregisterCIMessageHandler(0) + self.close() diff --git a/lib/python/Screens/InfoBar.py b/lib/python/Screens/InfoBar.py index a35ff3a..80ab0ef 100644 --- a/lib/python/Screens/InfoBar.py +++ b/lib/python/Screens/InfoBar.py @@ -3,6 +3,7 @@ from Screen import Screen from Screens.MovieSelection import MovieSelection from Screens.ChannelSelection import ChannelSelectionRadio from Screens.MessageBox import MessageBox +from Screens.Ci import CiHandler from ServiceReference import ServiceReference from Components.Clock import Clock @@ -35,6 +36,8 @@ class InfoBar(InfoBarShowHide, def __init__(self, session): Screen.__init__(self, session) + CiHandler.setSession(session) + self["actions"] = HelpableActionMap(self, "InfobarActions", { "showMovies": (self.showMovies, _("Play recorded movies...")), diff --git a/lib/python/enigma_python.i b/lib/python/enigma_python.i index 21f2b2e..ce77632 100644 --- a/lib/python/enigma_python.i +++ b/lib/python/enigma_python.i @@ -152,7 +152,7 @@ typedef long time_t; %immutable eComponentScan::newService; %immutable pNavigation::m_event; %immutable eListbox::selectionChanged; -%immutable eDVBCI_UI::mmiAvail; +%immutable eDVBCI_UI::ciStateChanged; %include %include -- 2.7.4