--- /dev/null
+INCLUDES = \
+ -I$(top_srcdir)/include
+
+noinst_LIBRARIES = libenigma_dvb_ci.a
+
+libenigma_dvb_ci_a_SOURCES = dvbci.cpp dvbci_session.cpp
+
--- /dev/null
+#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);
+ }
+}
+
--- /dev/null
+#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
--- /dev/null
+/* 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;
+ }
+ }
+}
--- /dev/null
+#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