X-Git-Url: https://git.cweiske.de/enigma2.git/blobdiff_plain/682b9158bbddde229a2559365aa108812b15de61..f0c5ac102ddaf0bfbf86743a5aec0ea4accc605c:/lib/dvb_ci/dvbci_session.cpp diff --git a/lib/dvb_ci/dvbci_session.cpp b/lib/dvb_ci/dvbci_session.cpp index 1e59d2ad..e5a669f2 100644 --- a/lib/dvb_ci/dvbci_session.cpp +++ b/lib/dvb_ci/dvbci_session.cpp @@ -1,11 +1,16 @@ /* DVB CI Transport Connection */ +#include #include +#include +#include +#include +#include +#include -eDVBCISession::eDVBCISession(eDVBCISlot *cislot) -{ - slot = cislot; -} +DEFINE_REF(eDVBCISession); + +ePtr eDVBCISession::sessions[SLMS]; int eDVBCISession::buildLengthField(unsigned char *pkt, int len) { @@ -26,7 +31,7 @@ int eDVBCISession::buildLengthField(unsigned char *pkt, int len) return 3; } else { - printf("too big length\n"); + eDebug("too big length"); exit(0); } } @@ -47,6 +52,22 @@ int eDVBCISession::parseLengthField(const unsigned char *pkt, int &len) return (pkt[0] & 0x7F) + 1; } +void eDVBCISession::sendAPDU(const unsigned char *tag, const void *data, int len) +{ + unsigned char pkt[len+3+4]; + int l; + memcpy(pkt, tag, 3); + l=buildLengthField(pkt+3, len); + if (data) + memcpy(pkt+3+l, data, len); + sendSPDU(0x90, 0, 0, pkt, len+3+l); +} + +void eDVBCISession::sendSPDU(unsigned char tag, const void *data, int len, const void *apdu, int alen) +{ + sendSPDU(slot, tag, data, len, session_nb, apdu, alen); +} + void eDVBCISession::sendSPDU(eDVBCISlot *slot, unsigned char tag, const void *data, int len, unsigned short session_nb, const void *apdu,int alen) { unsigned char pkt[4096]; @@ -63,30 +84,56 @@ void eDVBCISession::sendSPDU(eDVBCISlot *slot, unsigned char tag, const void *da memcpy(ptr, apdu, alen); ptr+=alen; - slot->write(pkt, ptr - pkt); + slot->send(pkt, ptr - pkt); } void eDVBCISession::sendOpenSessionResponse(eDVBCISlot *slot, unsigned char session_status, const unsigned char *resource_identifier, unsigned short session_nb) { char pkt[6]; pkt[0]=session_status; - printf("sendOpenSessionResponse\n"); + eDebug("sendOpenSessionResponse"); memcpy(pkt + 1, resource_identifier, 4); sendSPDU(slot, 0x92, pkt, 5, session_nb); } -eDVBCISession *eDVBCISession::createSession(eDVBCISlot *slot, const unsigned char *resource_identifier, unsigned char &status) +void eDVBCISession::recvCreateSessionResponse(const unsigned char *data) +{ + status = data[0]; + state = stateStarted; + action = 1; + eDebug("create Session Response, status %x", status); +} + +void eDVBCISession::recvCloseSessionRequest(const unsigned char *data) +{ + state = stateInDeletion; + action = 1; + eDebug("close Session Request"); +} + +void eDVBCISession::deleteSessions(const eDVBCISlot *slot) +{ + ePtr ptr; + for (unsigned short session_nb=0; session_nb < SLMS; ++session_nb) + { + ptr = sessions[session_nb]; + if (ptr && ptr->slot == slot) + sessions[session_nb]=0; + } +} + +void eDVBCISession::createSession(eDVBCISlot *slot, const unsigned char *resource_identifier, unsigned char &status, ePtr &session) { - eDVBCISession *session; unsigned long tag; unsigned short session_nb; + for (session_nb=1; session_nb < SLMS; ++session_nb) if (!sessions[session_nb-1]) break; if (session_nb == SLMS) { status=0xF3; - return 0; + return; } tag = resource_identifier[0] << 24; @@ -97,80 +144,182 @@ eDVBCISession *eDVBCISession::createSession(eDVBCISlot *slot, const unsigned cha switch (tag) { case 0x00010041: -// session=new eDVBCIResourceManagerSession; - printf("RESOURCE MANAGER\n"); + session=new eDVBCIResourceManagerSession; + eDebug("RESOURCE MANAGER"); break; case 0x00020041: -// session=eDVBCIModule::getInstance()->application_manager = new eDVBCIApplicationManagerSession; - printf("APPLICATION MANAGER\n"); + session=new eDVBCIApplicationManagerSession(slot); + eDebug("APPLICATION MANAGER"); break; case 0x00030041: -// session=eDVBCIModule::getInstance()->ca_manager=new eDVBCICAManagerSession; - printf("CA MANAGER\n"); + session = new eDVBCICAManagerSession(slot); + eDebug("CA MANAGER"); break; case 0x00240041: -// session=new eDVBCIDateTimeSession; - printf("DATE-TIME\n"); + session=new eDVBCIDateTimeSession; + eDebug("DATE-TIME"); break; case 0x00400041: -// session=new eDVBCIMMISession; - printf("MMI\n"); + session = new eDVBCIMMISession(slot); + eDebug("MMI - create session"); break; case 0x00100041: // session=new eDVBCIAuthSession; - printf("AuthSession\n"); - break; + eDebug("AuthSession"); +// break; case 0x00200041: default: - printf("unknown resource type %02x %02x %02x %02x\n", resource_identifier[0], resource_identifier[1], resource_identifier[2],resource_identifier[3]); + eDebug("unknown resource type %02x %02x %02x %02x", resource_identifier[0], resource_identifier[1], resource_identifier[2],resource_identifier[3]); session=0; status=0xF0; } if (!session) { - printf("unknown session.. expect crash\n"); - return 0; + eDebug("unknown session.. expect crash"); + return; } - printf("new session_nb: %d\n", session_nb); + + eDebug("new session nb %d %p", session_nb, &(*session)); session->session_nb = session_nb; + if (session) { - printf("session ok, status %02x\n", session->status); - status = session->getStatus(); - if (status) - { - delete session; - session = 0; - } sessions[session_nb - 1] = session; session->slot = slot; + status = 0; } session->state = stateInCreation; - return session; } -void eDVBCISession::receiveData(const unsigned char *ptr, size_t len) +void eDVBCISession::handleClose() +{ + unsigned char data[1]={0x00}; + sendSPDU(0x96, data, 1, 0, 0); +} + +int eDVBCISession::pollAll() +{ + for (int session_nb=1; session_nb < SLMS; ++session_nb) + if (sessions[session_nb-1]) + { + int r; + + if (sessions[session_nb-1]->state == stateInDeletion) + { + sessions[session_nb-1]->handleClose(); + sessions[session_nb-1]=0; + r=1; + } else + r=sessions[session_nb-1]->poll(); + + if (r) + return 1; + } + return 0; +} + +void eDVBCISession::receiveData(eDVBCISlot *slot, const unsigned char *ptr, size_t len) { const unsigned char *pkt = (const unsigned char*)ptr; unsigned char tag = *pkt++; int llen, hlen; + + eDebug("slot: %p",slot); + + for(unsigned int i=0;i session; if(tag == 0x91) { unsigned char status; - session = createSession(slot, pkt, status); + createSession(slot, pkt, status, session); sendOpenSessionResponse(slot, status, pkt, session?session->session_nb:0); - + if (session) { session->state=stateStarted; session->action=1; } } + else + { + unsigned session_nb; + session_nb=pkt[hlen-2]<<8; + session_nb|=pkt[hlen-1]&0xFF; + + if ((!session_nb) || (session_nb >= SLMS)) + { + eDebug("PROTOCOL: illegal session number %x", session_nb); + return; + } + + session=sessions[session_nb-1]; + if (!session) + { + eDebug("PROTOCOL: data on closed session %x", session_nb); + return; + } + + switch (tag) + { + case 0x90: + break; + case 0x94: + session->recvCreateSessionResponse(pkt); + break; + case 0x95: + eDebug("recvCloseSessionRequest"); + session->recvCloseSessionRequest(pkt); + break; + default: + eDebug("INTERNAL: nyi, tag %02x.", tag); + return; + } + } + + hlen += llen + 1; // lengthfield and tag + + pkt = ((const unsigned char*)ptr) + hlen; + len -= hlen; + + if (session) + while (len > 0) + { + int alen; + const unsigned char *tag=pkt; + pkt+=3; // tag + len-=3; + hlen=parseLengthField(pkt, alen); + pkt+=hlen; + len-=hlen; + + //if (eDVBCIModule::getInstance()->workarounds_active & eDVBCIModule::workaroundMagicAPDULength) + { + if (((len-alen) > 0) && ((len - alen) < 3)) + { + eDebug("WORKAROUND: applying work around MagicAPDULength"); + alen=len; + } + } + if (session->receivedAPDU(tag, pkt, alen)) + session->action = 1; + pkt+=alen; + len-=alen; + } + + if (len) + eDebug("PROTOCOL: warning, TL-Data has invalid length"); } + +eDVBCISession::~eDVBCISession() +{ +// eDebug("destroy %p", this); +} +