added ci
authorRonny Strutz <ronny.strutz@multimedia-labs.de>
Wed, 10 Aug 2005 18:40:32 +0000 (18:40 +0000)
committerRonny Strutz <ronny.strutz@multimedia-labs.de>
Wed, 10 Aug 2005 18:40:32 +0000 (18:40 +0000)
lib/dvb_ci/Makefile.am [new file with mode: 0644]
lib/dvb_ci/dvbci.cpp [new file with mode: 0644]
lib/dvb_ci/dvbci.h [new file with mode: 0644]
lib/dvb_ci/dvbci_session.cpp [new file with mode: 0644]
lib/dvb_ci/dvbci_session.h [new file with mode: 0644]

diff --git a/lib/dvb_ci/Makefile.am b/lib/dvb_ci/Makefile.am
new file mode 100644 (file)
index 0000000..8236cfd
--- /dev/null
@@ -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 (file)
index 0000000..d76cd34
--- /dev/null
@@ -0,0 +1,92 @@
+#include <fcntl.h>
+
+#include <lib/base/eerror.h>
+#include <lib/dvb_ci/dvbci.h>
+#include <lib/dvb_ci/dvbci_session.h>
+
+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<eDVBCISlot> 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 (file)
index 0000000..961999e
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef __dvbci_dvbci_h
+#define __dvbci_dvbci_h
+
+#include <lib/base/ebase.h>
+
+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<eDVBCISlot>       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 (file)
index 0000000..1e59d2a
--- /dev/null
@@ -0,0 +1,176 @@
+/* DVB CI Transport Connection */
+
+#include <lib/dvb_ci/dvbci_session.h>
+
+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 (file)
index 0000000..426c7f8
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef __dvbci_dvbci_tc_h
+#define __dvbci_dvbci_tc_h
+
+#include <lib/base/ebase.h>
+#include <lib/dvb_ci/dvbci.h>
+
+#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