added ci
[enigma2.git] / lib / dvb_ci / dvbci_session.cpp
1 /* DVB CI Transport Connection */
2
3 #include <lib/dvb_ci/dvbci_session.h>
4
5 eDVBCISession::eDVBCISession(eDVBCISlot *cislot)
6 {
7         slot = cislot;
8 }
9
10 int eDVBCISession::buildLengthField(unsigned char *pkt, int len)
11 {
12         if (len < 127)
13         {
14                 *pkt++=len;
15                 return 1;
16         } else if (len < 256)
17         {
18                 *pkt++=0x81;
19                 *pkt++=len;
20                 return 2;
21         } else if (len < 65535)
22         {
23                 *pkt++=0x82;
24                 *pkt++=len>>8;
25                 *pkt++=len;
26                 return 3;
27         } else
28         {
29                 printf("too big length\n");
30                 exit(0);
31         }
32 }
33
34 int eDVBCISession::parseLengthField(const unsigned char *pkt, int &len)
35 {
36         len=0;
37         if (!(*pkt&0x80)) 
38         {
39                 len = *pkt;
40                 return 1;
41         }
42         for (int i=0; i<(pkt[0]&0x7F); ++i)
43         {
44                 len <<= 8;
45                 len |= pkt[i + 1];
46         }
47         return (pkt[0] & 0x7F) + 1;
48 }
49
50 void eDVBCISession::sendSPDU(eDVBCISlot *slot, unsigned char tag, const void *data, int len, unsigned short session_nb, const void *apdu,int alen)
51 {
52         unsigned char pkt[4096];
53         unsigned char *ptr=pkt;
54         *ptr++=tag;
55         ptr+=buildLengthField(ptr, len+2);
56         if (data)
57                 memcpy(ptr, data, len);
58         ptr+=len;
59         *ptr++=session_nb>>8;
60         *ptr++=session_nb;
61
62         if (apdu)
63                 memcpy(ptr, apdu, alen);
64
65         ptr+=alen;
66         slot->write(pkt, ptr - pkt);
67 }
68
69 void eDVBCISession::sendOpenSessionResponse(eDVBCISlot *slot, unsigned char session_status, const unsigned char *resource_identifier, unsigned short session_nb)
70 {
71         char pkt[6];
72         pkt[0]=session_status;
73         printf("sendOpenSessionResponse\n");
74         memcpy(pkt + 1, resource_identifier, 4);
75         sendSPDU(slot, 0x92, pkt, 5, session_nb);
76 }
77
78 eDVBCISession *eDVBCISession::createSession(eDVBCISlot *slot, const unsigned char *resource_identifier, unsigned char &status)
79 {
80         eDVBCISession *session;
81         unsigned long tag;
82         unsigned short session_nb;
83         for (session_nb=1; session_nb < SLMS; ++session_nb)
84                 if (!sessions[session_nb-1])
85                         break;
86         if (session_nb == SLMS)
87         {
88                 status=0xF3;
89                 return 0;
90         }
91
92         tag = resource_identifier[0] << 24;
93         tag|= resource_identifier[1] << 16;
94         tag|= resource_identifier[2] << 8;
95         tag|= resource_identifier[3];
96
97         switch (tag)
98         {
99         case 0x00010041:
100 //              session=new eDVBCIResourceManagerSession;
101                 printf("RESOURCE MANAGER\n");
102                 break;
103         case 0x00020041:
104 //              session=eDVBCIModule::getInstance()->application_manager = new eDVBCIApplicationManagerSession;
105                 printf("APPLICATION MANAGER\n");
106                 break;
107         case 0x00030041:
108 //              session=eDVBCIModule::getInstance()->ca_manager=new eDVBCICAManagerSession;
109                 printf("CA MANAGER\n");
110                 break;
111         case 0x00240041:
112 //              session=new eDVBCIDateTimeSession;
113                 printf("DATE-TIME\n");
114                 break;
115         case 0x00400041:
116 //              session=new eDVBCIMMISession;
117                 printf("MMI\n");
118                 break;
119         case 0x00100041:
120 //              session=new eDVBCIAuthSession;
121                 printf("AuthSession\n");
122                 break;
123         case 0x00200041:
124         default:
125                 printf("unknown resource type %02x %02x %02x %02x\n", resource_identifier[0], resource_identifier[1], resource_identifier[2],resource_identifier[3]);
126                 session=0;
127                 status=0xF0;
128         }
129
130         if (!session)
131         {
132                 printf("unknown session.. expect crash\n");
133                 return 0;
134         }
135         printf("new session_nb: %d\n", session_nb);
136         session->session_nb = session_nb;
137         if (session)
138         {
139                 printf("session ok, status %02x\n", session->status);
140                 status = session->getStatus();
141                 if (status)
142                 {
143                         delete session;
144                         session = 0;
145                 }
146                 sessions[session_nb - 1] = session;
147                 session->slot = slot;
148         }
149         session->state = stateInCreation;
150         return session;
151 }
152
153 void eDVBCISession::receiveData(const unsigned char *ptr, size_t len)
154 {
155         const unsigned char *pkt = (const unsigned char*)ptr;
156         unsigned char tag = *pkt++;
157         int llen, hlen;
158         
159         llen = parseLengthField(pkt, hlen);
160         pkt += llen;
161         
162         eDVBCISession *session = NULL;
163         
164         if(tag == 0x91)
165         {
166                 unsigned char status;
167                 session = createSession(slot, pkt, status);
168                 sendOpenSessionResponse(slot, status, pkt, session?session->session_nb:0);
169
170                 if (session)
171                 {
172                         session->state=stateStarted;
173                         session->action=1;
174                 }
175         }
176 }