From: Ronny Strutz Date: Wed, 10 Aug 2005 18:40:32 +0000 (+0000) Subject: added ci X-Git-Url: http://code.vuplus.com/gitweb/?p=vuplus_dvbapp;a=commitdiff_plain;h=682b9158bbddde229a2559365aa108812b15de61 added ci --- diff --git a/lib/dvb_ci/Makefile.am b/lib/dvb_ci/Makefile.am new file mode 100644 index 0000000..8236cfd --- /dev/null +++ b/lib/dvb_ci/Makefile.am @@ -0,0 +1,7 @@ +INCLUDES = \ + -I$(top_srcdir)/include + +noinst_LIBRARIES = libenigma_dvb_ci.a + +libenigma_dvb_ci_a_SOURCES = dvbci.cpp dvbci_session.cpp + diff --git a/lib/dvb_ci/dvbci.cpp b/lib/dvb_ci/dvbci.cpp new file mode 100644 index 0000000..d76cd34 --- /dev/null +++ b/lib/dvb_ci/dvbci.cpp @@ -0,0 +1,92 @@ +#include + +#include +#include +#include + +eDVBCIInterfaces::eDVBCIInterfaces() +{ + int num_ci = 0; + + eDebug("scanning for common interfaces.."); + while (1) + { + struct stat s; + char filename[128]; + sprintf(filename, "/dev/ci%d", num_ci); + + if (stat(filename, &s)) + break; + + ePtr cislot; + + cislot = new eDVBCISlot(eApp, num_ci); + m_slots.push_back(cislot); + + ++num_ci; + } + + eDebug("done, found %d common interfaces"); +} + +int eDVBCISlot::write(const unsigned char *data, size_t len) +{ + return ::write(fd, data, len); +} + +void eDVBCISlot::data(int) +{ + eDebug("ci talks to us"); + + __u8 data[4096]; + int r; + r = ::read(fd, data, 4096); + if(r < 0) + eWarning("ERROR reading from CI - %m\n"); + + if(!se) { + eDebug("ci inserted"); + se = new eDVBCISession(this); + + /* enable HUP to detect removal or errors */ + notifier_event->start(); + } + + if(r > 0) + se->receiveData(data, r); +} + +void eDVBCISlot::event(int) +{ + eDebug("CI removed"); + + /* kill the TransportConnection */ + + /* we know about and disable HUP */ + notifier_event->stop(); +} + +eDVBCISlot::eDVBCISlot(eMainloop *context, int nr): se(0) +{ + char filename[128]; + + sprintf(filename, "/dev/ci%d", nr); + + fd = ::open(filename, O_RDWR | O_NONBLOCK); + + eDebug("eDVBCISlot has fd %d", fd); + + if (fd >= 0) + { + //read callback + notifier_data = new eSocketNotifier(context, fd, eSocketNotifier::Read); + CONNECT(notifier_data->activated, eDVBCISlot::data); + //remove callback + notifier_event = new eSocketNotifier(context, fd, eSocketNotifier::Hungup); + CONNECT(notifier_event->activated, eDVBCISlot::event); + } else + { + perror(filename); + } +} + diff --git a/lib/dvb_ci/dvbci.h b/lib/dvb_ci/dvbci.h new file mode 100644 index 0000000..961999e --- /dev/null +++ b/lib/dvb_ci/dvbci.h @@ -0,0 +1,35 @@ +#ifndef __dvbci_dvbci_h +#define __dvbci_dvbci_h + +#include + +class eDVBCISession; + +class eDVBCISlot: public Object +{ +DECLARE_REF(eDVBCISlot); +private: + int fd; + void data(int); + eSocketNotifier *notifier_data; + void event(int); + eSocketNotifier *notifier_event; + + eDVBCISession *se; +public: + eDVBCISlot(eMainloop *context, int nr); + virtual ~eDVBCISlot(); + + int eDVBCISlot::write(const unsigned char *data, size_t len); +}; + +class eDVBCIInterfaces +{ +private: + eSmartPtrList m_slots; +public: + eDVBCIInterfaces(); + virtual ~eDVBCIInterfaces(); +}; + +#endif diff --git a/lib/dvb_ci/dvbci_session.cpp b/lib/dvb_ci/dvbci_session.cpp new file mode 100644 index 0000000..1e59d2a --- /dev/null +++ b/lib/dvb_ci/dvbci_session.cpp @@ -0,0 +1,176 @@ +/* DVB CI Transport Connection */ + +#include + +eDVBCISession::eDVBCISession(eDVBCISlot *cislot) +{ + slot = cislot; +} + +int eDVBCISession::buildLengthField(unsigned char *pkt, int len) +{ + if (len < 127) + { + *pkt++=len; + return 1; + } else if (len < 256) + { + *pkt++=0x81; + *pkt++=len; + return 2; + } else if (len < 65535) + { + *pkt++=0x82; + *pkt++=len>>8; + *pkt++=len; + return 3; + } else + { + printf("too big length\n"); + exit(0); + } +} + +int eDVBCISession::parseLengthField(const unsigned char *pkt, int &len) +{ + len=0; + if (!(*pkt&0x80)) + { + len = *pkt; + return 1; + } + for (int i=0; i<(pkt[0]&0x7F); ++i) + { + len <<= 8; + len |= pkt[i + 1]; + } + return (pkt[0] & 0x7F) + 1; +} + +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]; + unsigned char *ptr=pkt; + *ptr++=tag; + ptr+=buildLengthField(ptr, len+2); + if (data) + memcpy(ptr, data, len); + ptr+=len; + *ptr++=session_nb>>8; + *ptr++=session_nb; + + if (apdu) + memcpy(ptr, apdu, alen); + + ptr+=alen; + slot->write(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"); + 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) +{ + 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; + } + + tag = resource_identifier[0] << 24; + tag|= resource_identifier[1] << 16; + tag|= resource_identifier[2] << 8; + tag|= resource_identifier[3]; + + switch (tag) + { + case 0x00010041: +// session=new eDVBCIResourceManagerSession; + printf("RESOURCE MANAGER\n"); + break; + case 0x00020041: +// session=eDVBCIModule::getInstance()->application_manager = new eDVBCIApplicationManagerSession; + printf("APPLICATION MANAGER\n"); + break; + case 0x00030041: +// session=eDVBCIModule::getInstance()->ca_manager=new eDVBCICAManagerSession; + printf("CA MANAGER\n"); + break; + case 0x00240041: +// session=new eDVBCIDateTimeSession; + printf("DATE-TIME\n"); + break; + case 0x00400041: +// session=new eDVBCIMMISession; + printf("MMI\n"); + break; + case 0x00100041: +// session=new eDVBCIAuthSession; + printf("AuthSession\n"); + 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]); + session=0; + status=0xF0; + } + + if (!session) + { + printf("unknown session.. expect crash\n"); + return 0; + } + printf("new session_nb: %d\n", session_nb); + 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; + } + session->state = stateInCreation; + return session; +} + +void eDVBCISession::receiveData(const unsigned char *ptr, size_t len) +{ + const unsigned char *pkt = (const unsigned char*)ptr; + unsigned char tag = *pkt++; + int llen, hlen; + + llen = parseLengthField(pkt, hlen); + pkt += llen; + + eDVBCISession *session = NULL; + + if(tag == 0x91) + { + unsigned char status; + session = createSession(slot, pkt, status); + sendOpenSessionResponse(slot, status, pkt, session?session->session_nb:0); + + if (session) + { + session->state=stateStarted; + session->action=1; + } + } +} diff --git a/lib/dvb_ci/dvbci_session.h b/lib/dvb_ci/dvbci_session.h new file mode 100644 index 0000000..426c7f8 --- /dev/null +++ b/lib/dvb_ci/dvbci_session.h @@ -0,0 +1,36 @@ +#ifndef __dvbci_dvbci_tc_h +#define __dvbci_dvbci_tc_h + +#include +#include + +#define SLMS 256 + +class eDVBCISession +{ + static eDVBCISession *sessions[SLMS]; + static eDVBCISession *eDVBCISession::createSession(eDVBCISlot *slot, const unsigned char *resource_identifier, unsigned char &status); + void eDVBCISession::sendSPDU(eDVBCISlot *slot, unsigned char tag,const void *data, int len, unsigned short session_nb, const void *apdu=0,int alen=0); + void sendOpenSessionResponse(eDVBCISlot *slot,unsigned char session_status, const unsigned char *resource_identifier,unsigned short session_nb); +protected: + int state; + int status; + int action; + eDVBCISlot *slot; //base only + unsigned short session_nb; +public: + eDVBCISession(eDVBCISlot *cislot); + ~eDVBCISession(); + + enum { stateInCreation, stateBusy, stateInDeletion, stateStarted, statePrivate}; + + int parseLengthField(const unsigned char *pkt, int &len); + int buildLengthField(unsigned char *pkt, int len); + + void receiveData(const unsigned char *ptr, size_t len); + + int getState() { return state; } + int getStatus() { return status; } +}; + +#endif