1 /* DVB CI Transport Connection */
3 #include <lib/base/eerror.h>
4 #include <lib/dvb_ci/dvbci_session.h>
5 #include <lib/dvb_ci/dvbci_resmgr.h>
6 #include <lib/dvb_ci/dvbci_appmgr.h>
7 #include <lib/dvb_ci/dvbci_camgr.h>
8 #include <lib/dvb_ci/dvbci_datetimemgr.h>
9 #include <lib/dvb_ci/dvbci_mmi.h>
11 DEFINE_REF(eDVBCISession);
13 ePtr<eDVBCISession> eDVBCISession::sessions[SLMS];
15 int eDVBCISession::buildLengthField(unsigned char *pkt, int len)
26 } else if (len < 65535)
34 eDebug("too big length");
39 int eDVBCISession::parseLengthField(const unsigned char *pkt, int &len)
47 for (int i=0; i<(pkt[0]&0x7F); ++i)
52 return (pkt[0] & 0x7F) + 1;
55 void eDVBCISession::sendAPDU(const unsigned char *tag, const void *data, int len)
57 unsigned char pkt[len+3+4];
60 l=buildLengthField(pkt+3, len);
62 memcpy(pkt+3+l, data, len);
63 sendSPDU(0x90, 0, 0, pkt, len+3+l);
66 void eDVBCISession::sendSPDU(unsigned char tag, const void *data, int len, const void *apdu, int alen)
68 sendSPDU(slot, tag, data, len, session_nb, apdu, alen);
71 void eDVBCISession::sendSPDU(eDVBCISlot *slot, unsigned char tag, const void *data, int len, unsigned short session_nb, const void *apdu,int alen)
73 unsigned char pkt[4096];
74 unsigned char *ptr=pkt;
76 ptr+=buildLengthField(ptr, len+2);
78 memcpy(ptr, data, len);
84 memcpy(ptr, apdu, alen);
87 slot->send(pkt, ptr - pkt);
90 void eDVBCISession::sendOpenSessionResponse(eDVBCISlot *slot, unsigned char session_status, const unsigned char *resource_identifier, unsigned short session_nb)
93 pkt[0]=session_status;
94 eDebug("sendOpenSessionResponse");
95 memcpy(pkt + 1, resource_identifier, 4);
96 sendSPDU(slot, 0x92, pkt, 5, session_nb);
99 void eDVBCISession::recvCreateSessionResponse(const unsigned char *data)
102 state = stateStarted;
104 eDebug("create Session Response, status %x", status);
107 void eDVBCISession::recvCloseSessionRequest(const unsigned char *data)
109 state = stateInDeletion;
111 eDebug("close Session Request");
114 void eDVBCISession::deleteSessions(const eDVBCISlot *slot)
116 ePtr<eDVBCISession> ptr;
117 for (unsigned short session_nb=0; session_nb < SLMS; ++session_nb)
119 ptr = sessions[session_nb];
120 if (ptr && ptr->slot == slot)
121 sessions[session_nb]=0;
125 void eDVBCISession::createSession(eDVBCISlot *slot, const unsigned char *resource_identifier, unsigned char &status, ePtr<eDVBCISession> &session)
128 unsigned short session_nb;
130 for (session_nb=1; session_nb < SLMS; ++session_nb)
131 if (!sessions[session_nb-1])
133 if (session_nb == SLMS)
139 tag = resource_identifier[0] << 24;
140 tag|= resource_identifier[1] << 16;
141 tag|= resource_identifier[2] << 8;
142 tag|= resource_identifier[3];
147 session=new eDVBCIResourceManagerSession;
148 eDebug("RESOURCE MANAGER");
151 session=new eDVBCIApplicationManagerSession(slot);
152 eDebug("APPLICATION MANAGER");
155 session = new eDVBCICAManagerSession(slot);
156 eDebug("CA MANAGER");
159 session=new eDVBCIDateTimeSession;
163 session = new eDVBCIMMISession(slot);
164 eDebug("MMI - create session");
167 // session=new eDVBCIAuthSession;
168 eDebug("AuthSession");
172 eDebug("unknown resource type %02x %02x %02x %02x", resource_identifier[0], resource_identifier[1], resource_identifier[2],resource_identifier[3]);
179 eDebug("unknown session.. expect crash");
183 eDebug("new session nb %d %p", session_nb, &(*session));
184 session->session_nb = session_nb;
188 sessions[session_nb - 1] = session;
189 session->slot = slot;
192 session->state = stateInCreation;
195 void eDVBCISession::handleClose()
197 unsigned char data[1]={0x00};
198 sendSPDU(0x96, data, 1, 0, 0);
201 int eDVBCISession::pollAll()
203 for (int session_nb=1; session_nb < SLMS; ++session_nb)
204 if (sessions[session_nb-1])
208 if (sessions[session_nb-1]->state == stateInDeletion)
210 sessions[session_nb-1]->handleClose();
211 sessions[session_nb-1]=0;
214 r=sessions[session_nb-1]->poll();
222 void eDVBCISession::receiveData(eDVBCISlot *slot, const unsigned char *ptr, size_t len)
224 const unsigned char *pkt = (const unsigned char*)ptr;
225 unsigned char tag = *pkt++;
228 eDebug("slot: %p",slot);
230 for(unsigned int i=0;i<len;i++)
231 eDebugNoNewLine("%02x ",ptr[i]);
234 llen = parseLengthField(pkt, hlen);
237 ePtr<eDVBCISession> session;
241 unsigned char status;
242 createSession(slot, pkt, status, session);
243 sendOpenSessionResponse(slot, status, pkt, session?session->session_nb:0);
247 session->state=stateStarted;
254 session_nb=pkt[hlen-2]<<8;
255 session_nb|=pkt[hlen-1]&0xFF;
257 if ((!session_nb) || (session_nb >= SLMS))
259 eDebug("PROTOCOL: illegal session number %x", session_nb);
263 session=sessions[session_nb-1];
266 eDebug("PROTOCOL: data on closed session %x", session_nb);
275 session->recvCreateSessionResponse(pkt);
278 eDebug("recvCloseSessionRequest");
279 session->recvCloseSessionRequest(pkt);
282 eDebug("INTERNAL: nyi, tag %02x.", tag);
287 hlen += llen + 1; // lengthfield and tag
289 pkt = ((const unsigned char*)ptr) + hlen;
296 const unsigned char *tag=pkt;
299 hlen=parseLengthField(pkt, alen);
303 //if (eDVBCIModule::getInstance()->workarounds_active & eDVBCIModule::workaroundMagicAPDULength)
305 if (((len-alen) > 0) && ((len - alen) < 3))
307 eDebug("WORKAROUND: applying work around MagicAPDULength");
311 if (session->receivedAPDU(tag, pkt, alen))
318 eDebug("PROTOCOL: warning, TL-Data has invalid length");
321 eDVBCISession::~eDVBCISession()
323 // eDebug("destroy %p", this);