+/* 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;
+ }
+ }
+}