60a64ddb1c4ff1a9c33b6360f192dd6069223feb
[vuplus_dvbapp] / lib / dvb_ci / dvbci.cpp
1 #include <fcntl.h>
2 #include <sys/ioctl.h>
3
4 #include <lib/base/init.h>
5 #include <lib/base/init_num.h>
6 #include <lib/base/ebase.h>
7
8 #include <lib/base/eerror.h>
9 #include <lib/base/nconfig.h> // access to python config
10 #include <lib/dvb/db.h>
11 #include <lib/dvb/pmt.h>
12 #include <lib/dvb_ci/dvbci.h>
13 #include <lib/dvb_ci/dvbci_session.h>
14 #include <lib/dvb_ci/dvbci_camgr.h>
15 #include <lib/dvb_ci/dvbci_ui.h>
16 #include <lib/dvb_ci/dvbci_appmgr.h>
17 #include <lib/dvb_ci/dvbci_mmi.h>
18
19 #include <dvbsi++/ca_program_map_section.h>
20
21 //#define CIDEBUG 1
22
23 #ifdef CIDEBUG
24         #define eDebugCI(x...) eDebug(x)
25 #else
26         #define eDebugCI(x...)
27 #endif
28
29 eDVBCIInterfaces *eDVBCIInterfaces::instance = 0;
30
31 eDVBCIInterfaces::eDVBCIInterfaces()
32 {
33         int num_ci = 0;
34         
35         instance = this;
36         
37         eDebug("scanning for common interfaces..");
38
39         while (1)
40         {
41                 struct stat s;
42                 char filename[128];
43                 sprintf(filename, "/dev/ci%d", num_ci);
44
45                 if (stat(filename, &s))
46                         break;
47
48                 ePtr<eDVBCISlot> cislot;
49
50                 cislot = new eDVBCISlot(eApp, num_ci);
51                 m_slots.push_back(cislot);
52
53                 ++num_ci;
54         }
55
56         for (eSmartPtrList<eDVBCISlot>::iterator it(m_slots.begin()); it != m_slots.end(); ++it)
57                 it->setSource(TUNER_A);
58
59         if (num_ci > 1) // // FIXME .. we force DM8000 when more than one CI Slot is avail
60         {
61                 setInputSource(0, TUNER_A);
62                 setInputSource(1, TUNER_B);
63                 setInputSource(2, TUNER_C);
64                 setInputSource(3, TUNER_D);
65         }
66         else
67         {
68                 setInputSource(0, TUNER_A);
69                 setInputSource(1, TUNER_B);
70         }
71
72         eDebug("done, found %d common interface slots", num_ci);
73 }
74
75 eDVBCIInterfaces::~eDVBCIInterfaces()
76 {
77 }
78
79 eDVBCIInterfaces *eDVBCIInterfaces::getInstance()
80 {
81         return instance;
82 }
83
84 eDVBCISlot *eDVBCIInterfaces::getSlot(int slotid)
85 {
86         for(eSmartPtrList<eDVBCISlot>::iterator i(m_slots.begin()); i != m_slots.end(); ++i)
87                 if(i->getSlotID() == slotid)
88                         return i;
89
90         eDebug("FIXME: request for unknown slot");
91                         
92         return 0;
93 }
94
95 int eDVBCIInterfaces::getSlotState(int slotid)
96 {
97         eDVBCISlot *slot;
98
99         if( (slot = getSlot(slotid)) == 0 )
100                 return eDVBCISlot::stateInvalid;
101
102         return slot->getState();
103 }
104
105 int eDVBCIInterfaces::reset(int slotid)
106 {
107         eDVBCISlot *slot;
108
109         if( (slot = getSlot(slotid)) == 0 )
110                 return -1;
111
112         return slot->reset();
113 }
114
115 int eDVBCIInterfaces::initialize(int slotid)
116 {
117         eDVBCISlot *slot;
118
119         if( (slot = getSlot(slotid)) == 0 )
120                 return -1;
121
122         slot->removeService();
123
124         return sendCAPMT(slotid);
125 }
126
127 int eDVBCIInterfaces::sendCAPMT(int slotid)
128 {
129         eDVBCISlot *slot;
130
131         if( (slot = getSlot(slotid)) == 0 )
132                 return -1;
133
134         PMTHandlerList::iterator it = m_pmt_handlers.begin();
135         while (it != m_pmt_handlers.end())
136         {
137                 eDVBCISlot *tmp = it->cislot;
138                 while (tmp && tmp != slot)
139                         tmp = tmp->linked_next;
140                 if (tmp)
141                 {
142                         tmp->sendCAPMT(it->pmthandler);  // send capmt
143                         break;
144                 }
145                 ++it;
146         }
147
148         return 0;
149 }
150
151 int eDVBCIInterfaces::startMMI(int slotid)
152 {
153         eDVBCISlot *slot;
154
155         if( (slot = getSlot(slotid)) == 0 )
156                 return -1;
157         
158         return slot->startMMI();
159 }
160
161 int eDVBCIInterfaces::stopMMI(int slotid)
162 {
163         eDVBCISlot *slot;
164
165         if( (slot = getSlot(slotid)) == 0 )
166                 return -1;
167         
168         return slot->stopMMI();
169 }
170
171 int eDVBCIInterfaces::answerText(int slotid, int answer)
172 {
173         eDVBCISlot *slot;
174
175         if( (slot = getSlot(slotid)) == 0 )
176                 return -1;
177         
178         return slot->answerText(answer);
179 }
180
181 int eDVBCIInterfaces::answerEnq(int slotid, char *value)
182 {
183         eDVBCISlot *slot;
184
185         if( (slot = getSlot(slotid)) == 0 )
186                 return -1;
187         
188         return slot->answerEnq(value);
189 }
190
191 int eDVBCIInterfaces::cancelEnq(int slotid)
192 {
193         eDVBCISlot *slot;
194
195         if( (slot = getSlot(slotid)) == 0 )
196                 return -1;
197         
198         return slot->cancelEnq();
199 }
200
201 void eDVBCIInterfaces::ciRemoved(eDVBCISlot *slot)
202 {
203         if (slot->use_count)
204         {
205                 eDebug("CI Slot %d: removed... usecount %d", slot->getSlotID(), slot->use_count);
206                 for (PMTHandlerList::iterator it(m_pmt_handlers.begin());
207                         it != m_pmt_handlers.end(); ++it)
208                 {
209                         if (it->cislot == slot) // remove the base slot
210                                 it->cislot = slot->linked_next;
211                         else if (it->cislot)
212                         {
213                                 eDVBCISlot *prevSlot = it->cislot, *hSlot = it->cislot->linked_next;
214                                 while (hSlot)
215                                 {
216                                         if (hSlot == slot) {
217                                                 prevSlot->linked_next = slot->linked_next;
218                                                 break;
219                                         }
220                                         prevSlot = hSlot;
221                                         hSlot = hSlot->linked_next;
222                                 }
223                         }
224                 }
225                 if (slot->linked_next)
226                         slot->linked_next->setSource(slot->current_source);
227                 else // last CI in chain
228                 {
229                         setInputSource(slot->current_tuner, slot->current_source);
230                         slot->removeVtunerPid();
231                 }
232                 slot->linked_next = 0;
233                 slot->use_count=0;
234                 slot->plugged=true;
235                 slot->user_mapped=false;
236                 slot->removeService(0xFFFF);
237                 recheckPMTHandlers();
238         }
239 }
240
241 static bool canDescrambleMultipleServices(int slotid)
242 {
243         char configStr[255];
244         snprintf(configStr, 255, "config.ci.%d.canDescrambleMultipleServices", slotid);
245         std::string str;
246         ePythonConfigQuery::getConfigValue(configStr, str);
247         if ( str == "auto" )
248         {
249                 std::string appname = eDVBCI_UI::getInstance()->getAppName(slotid);
250                 if (appname.find("AlphaCrypt") != std::string::npos)
251                         return true;
252         }
253         else if (str == "yes")
254                 return true;
255         return false;
256 }
257
258 void eDVBCIInterfaces::recheckPMTHandlers()
259 {
260         eDebugCI("recheckPMTHAndlers()");
261         for (PMTHandlerList::iterator it(m_pmt_handlers.begin());
262                 it != m_pmt_handlers.end(); ++it)
263         {
264                 CAID_LIST caids;
265                 ePtr<eDVBService> service;
266                 eServiceReferenceDVB ref;
267                 eDVBCISlot *tmp = it->cislot;
268                 eDVBServicePMTHandler *pmthandler = it->pmthandler;
269                 eDVBServicePMTHandler::program p;
270                 bool plugged_cis_exist = false;
271
272                 pmthandler->getServiceReference(ref);
273                 pmthandler->getService(service);
274
275                 eDebugCI("recheck %p %s", pmthandler, ref.toString().c_str());
276                 for (eSmartPtrList<eDVBCISlot>::iterator ci_it(m_slots.begin()); ci_it != m_slots.end(); ++ci_it)
277                         if (ci_it->plugged && ci_it->getCAManager())
278                         {
279                                 eDebug("Slot %d plugged", ci_it->getSlotID());
280                                 ci_it->plugged = false;
281                                 plugged_cis_exist = true;
282                         }
283
284                 // check if this pmt handler has already assigned CI(s) .. and this CI(s) are already running
285                 if (!plugged_cis_exist)
286                 {
287                         while(tmp)
288                         {
289                                 if (!tmp->running_services.empty())
290                                         break;
291                                 tmp=tmp->linked_next;
292                         }
293                         if (tmp) // we dont like to change tsmux for running services
294                         {
295                                 eDebugCI("already assigned and running CI!\n");
296                                 continue;
297                         }
298                 }
299
300                 if (!pmthandler->getProgramInfo(p))
301                 {
302                         int cnt=0;
303                         std::set<eDVBServicePMTHandler::program::capid_pair> set(p.caids.begin(), p.caids.end());
304                         for (std::set<eDVBServicePMTHandler::program::capid_pair>::reverse_iterator x(set.rbegin()); x != set.rend(); ++x, ++cnt)
305                                 caids.push_front(x->caid);
306                         if (service && cnt)
307                                 service->m_ca = caids;
308                 }
309
310                 if (service)
311                         caids = service->m_ca;
312
313                 if (caids.empty())
314                         continue; // unscrambled service
315
316                 for (eSmartPtrList<eDVBCISlot>::iterator ci_it(m_slots.begin()); ci_it != m_slots.end(); ++ci_it)
317                 {
318                         eDebugCI("check Slot %d", ci_it->getSlotID());
319                         bool useThis=false;
320                         bool user_mapped=true;
321                         eDVBCICAManagerSession *ca_manager = ci_it->getCAManager();
322
323                         if (ca_manager)
324                         {
325                                 int mask=0;
326                                 if (!ci_it->possible_services.empty())
327                                 {
328                                         mask |= 1;
329                                         serviceSet::iterator it = ci_it->possible_services.find(ref);
330                                         if (it != ci_it->possible_services.end())
331                                         {
332                                                 eDebug("'%s' is in service list of slot %d... so use it", ref.toString().c_str(), ci_it->getSlotID());
333                                                 useThis = true;
334                                         }
335                                         else // check parent
336                                         {
337                                                 eServiceReferenceDVB parent_ref = ref.getParentServiceReference();
338                                                 if (parent_ref)
339                                                 {
340                                                         it = ci_it->possible_services.find(ref);
341                                                         if (it != ci_it->possible_services.end())
342                                                         {
343                                                                 eDebug("parent '%s' of '%s' is in service list of slot %d... so use it",
344                                                                         parent_ref.toString().c_str(), ref.toString().c_str(), ci_it->getSlotID());
345                                                                 useThis = true;
346                                                         }
347                                                 }
348                                         }
349                                 }
350                                 if (!useThis && !ci_it->possible_providers.empty())
351                                 {
352                                         eDVBNamespace ns = ref.getDVBNamespace();
353                                         mask |= 2;
354                                         if (!service) // subservice?
355                                         {
356                                                 eServiceReferenceDVB parent_ref = ref.getParentServiceReference();
357                                                 eDVBDB::getInstance()->getService(parent_ref, service);
358                                         }
359                                         if (service)
360                                         {
361                                                 providerSet::iterator it = ci_it->possible_providers.find(providerPair(service->m_provider_name, ns.get()));
362                                                 if (it != ci_it->possible_providers.end())
363                                                 {
364                                                         eDebug("'%s/%08x' is in provider list of slot %d... so use it", service->m_provider_name.c_str(), ns.get(), ci_it->getSlotID());
365                                                         useThis = true;
366                                                 }
367                                         }
368                                 }
369                                 if (!useThis && !ci_it->possible_caids.empty())
370                                 {
371                                         mask |= 4;
372                                         for (CAID_LIST::iterator ca(caids.begin()); ca != caids.end(); ++ca)
373                                         {
374                                                 caidSet::iterator it = ci_it->possible_caids.find(*ca);
375                                                 if (it != ci_it->possible_caids.end())
376                                                 {
377                                                         eDebug("caid '%04x' is in caid list of slot %d... so use it", *ca, ci_it->getSlotID());
378                                                         useThis = true;
379                                                         break;
380                                                 }
381                                         }
382                                 }
383                                 if (!useThis && !mask)
384                                 {
385                                         const std::vector<uint16_t> &ci_caids = ca_manager->getCAIDs();
386                                         for (CAID_LIST::iterator ca(caids.begin()); ca != caids.end(); ++ca)
387                                         {
388                                                 std::vector<uint16_t>::const_iterator z =
389                                                         std::lower_bound(ci_caids.begin(), ci_caids.end(), *ca);
390                                                 if ( z != ci_caids.end() && *z == *ca )
391                                                 {
392                                                         eDebug("The CI in Slot %d has said it can handle caid %04x... so use it", ci_it->getSlotID(), *z);
393                                                         useThis = true;
394                                                         user_mapped = false;
395                                                         ci_it->addVtunerPid(pmthandler);
396                                                         break;
397                                                 }
398                                         }
399                                 }
400                         }
401
402                         if (useThis)
403                         {
404                                 // check if this CI is already assigned to this pmthandler
405                                 eDVBCISlot *tmp = it->cislot;
406                                 while(tmp)
407                                 {
408                                         if (tmp == ci_it)
409                                                 break;
410                                         tmp=tmp->linked_next;
411                                 }
412                                 if (tmp) // ignore already assigned cislots...
413                                 {
414                                         eDebugCI("already assigned!");
415                                         continue;
416                                 }
417                                 eDebugCI("current slot %d usecount %d", ci_it->getSlotID(), ci_it->use_count);
418                                 if (ci_it->use_count)  // check if this CI can descramble more than one service
419                                 {
420                                         bool found = false;
421                                         useThis = false;
422                                         PMTHandlerList::iterator tmp = m_pmt_handlers.begin();
423                                         while (!found && tmp != m_pmt_handlers.end())
424                                         {
425                                                 eDebugCI(".");
426                                                 eDVBCISlot *tmp_cislot = tmp->cislot;
427                                                 while (!found && tmp_cislot)
428                                                 {
429                                                         eDebugCI("..");
430                                                         eServiceReferenceDVB ref2;
431                                                         tmp->pmthandler->getServiceReference(ref2);
432                                                         if ( tmp_cislot == ci_it && it->pmthandler != tmp->pmthandler )
433                                                         {
434                                                                 eDebugCI("check pmthandler %s for same service/tp", ref2.toString().c_str());
435                                                                 eDVBChannelID s1, s2;
436                                                                 if (ref != ref2)
437                                                                 {
438                                                                         eDebugCI("different services!");
439                                                                         ref.getChannelID(s1);
440                                                                         ref2.getChannelID(s2);
441                                                                 }
442                                                                 if (ref == ref2 || (s1 == s2 && canDescrambleMultipleServices(tmp_cislot->getSlotID())))
443                                                                 {
444                                                                         found = true;
445                                                                         eDebugCI("found!");
446                                                                         eDVBCISlot *tmpci = it->cislot = tmp->cislot;
447                                                                         while(tmpci)
448                                                                         {
449                                                                                 ++tmpci->use_count;
450                                                                                 eDebug("(2)CISlot %d, usecount now %d", tmpci->getSlotID(), tmpci->use_count);
451                                                                                 tmpci=tmpci->linked_next;
452                                                                         }
453                                                                 }
454                                                         }
455                                                         tmp_cislot=tmp_cislot->linked_next;
456                                                 }
457                                                 eDebugCI("...");
458                                                 ++tmp;
459                                         }
460                                 }
461
462                                 if (useThis)
463                                 {
464                                         if (ci_it->user_mapped)  // we dont like to link user mapped CIs
465                                         {
466                                                 eDebugCI("user mapped CI already in use... dont link!");
467                                                 continue;
468                                         }
469
470                                         ++ci_it->use_count;
471                                         eDebug("(1)CISlot %d, usecount now %d", ci_it->getSlotID(), ci_it->use_count);
472
473                                         data_source ci_source=CI_A;
474                                         switch(ci_it->getSlotID())
475                                         {
476                                                 case 0: ci_source = CI_A; break;
477                                                 case 1: ci_source = CI_B; break;
478                                                 case 2: ci_source = CI_C; break;
479                                                 case 3: ci_source = CI_D; break;
480                                                 default:
481                                                         eDebug("try to get source for CI %d!!\n", ci_it->getSlotID());
482                                                         break;
483                                         }
484
485                                         if (!it->cislot)
486                                         {
487                                                 int tunernum = -1;
488                                                 eUsePtr<iDVBChannel> channel;
489                                                 if (!pmthandler->getChannel(channel))
490                                                 {
491                                                         ePtr<iDVBFrontend> frontend;
492                                                         if (!channel->getFrontend(frontend))
493                                                         {
494                                                                 eDVBFrontend *fe = (eDVBFrontend*) &(*frontend);
495                                                                 tunernum = fe->getSlotID();
496                                                         }
497                                                 }
498                                                 ASSERT(tunernum != -1);
499                                                 data_source tuner_source = TUNER_A;
500                                                 switch (tunernum)
501                                                 {
502                                                         case 0 ... 22:
503                                                                 tuner_source = (data_source)tunernum;
504                                                                 break;
505                                                         default:
506                                                                 eDebug("try to get source for tuner %d!!\n", tunernum);
507                                                                 break;
508                                                 }
509                                                 ci_it->current_tuner = tunernum;
510                                                 setInputSource(tunernum, ci_source);
511                                                 ci_it->setSource(tuner_source);
512                                         }
513                                         else
514                                         {
515                                                 ci_it->current_tuner = it->cislot->current_tuner;
516                                                 ci_it->linked_next = it->cislot;
517                                                 ci_it->setSource(ci_it->linked_next->current_source);
518                                                 ci_it->linked_next->setSource(ci_source);
519                                         }
520                                         it->cislot = ci_it;
521                                         eDebugCI("assigned!");
522                                         gotPMT(pmthandler);
523                                 }
524
525                                 if (it->cislot && user_mapped) // CI assigned to this pmthandler in this run.. and user mapped? then we break here.. we dont like to link other CIs to user mapped CIs
526                                 {
527                                         eDebugCI("user mapped CI assigned... dont link CIs!");
528                                         break;
529                                 }
530                         }
531                 }
532         }
533 }
534
535 void eDVBCIInterfaces::addPMTHandler(eDVBServicePMTHandler *pmthandler)
536 {
537         // check if this pmthandler is already registered
538         PMTHandlerList::iterator it = m_pmt_handlers.begin();
539         while (it != m_pmt_handlers.end())
540         {
541                 if ( *it++ == pmthandler )
542                         return;
543         }
544
545         eServiceReferenceDVB ref;
546         pmthandler->getServiceReference(ref);
547         eDebug("[eDVBCIInterfaces] addPMTHandler %s", ref.toString().c_str());
548
549         m_pmt_handlers.push_back(CIPmtHandler(pmthandler));
550         recheckPMTHandlers();
551 }
552
553 void eDVBCIInterfaces::removePMTHandler(eDVBServicePMTHandler *pmthandler)
554 {
555         PMTHandlerList::iterator it=std::find(m_pmt_handlers.begin(),m_pmt_handlers.end(),pmthandler);
556         if (it != m_pmt_handlers.end())
557         {
558                 eDVBCISlot *slot = it->cislot;
559                 eDVBCISlot *base_slot = slot;
560                 eDVBServicePMTHandler *pmthandler = it->pmthandler;
561                 m_pmt_handlers.erase(it);
562
563                 eServiceReferenceDVB service_to_remove;
564                 pmthandler->getServiceReference(service_to_remove);
565
566                 bool sameServiceExist=false;
567                 for (PMTHandlerList::iterator i=m_pmt_handlers.begin(); i != m_pmt_handlers.end(); ++i)
568                 {
569                         if (i->cislot)
570                         {
571                                 eServiceReferenceDVB ref;
572                                 i->pmthandler->getServiceReference(ref);
573                                 if ( ref == service_to_remove )
574                                 {
575                                         sameServiceExist=true;
576                                         break;
577                                 }
578                         }
579                 }
580
581                 while(slot)
582                 {
583                         eDVBCISlot *next = slot->linked_next;
584                         if (!sameServiceExist)
585                         {
586                                 eDebug("[eDVBCIInterfaces] remove last pmt handler for service %s send empty capmt",
587                                         service_to_remove.toString().c_str());
588                                 std::vector<uint16_t> caids;
589                                 caids.push_back(0xFFFF);
590                                 slot->sendCAPMT(pmthandler, caids);  // send a capmt without caids to remove a running service
591                                 slot->removeService(service_to_remove.getServiceID().get());
592                         }
593
594                         if (!--slot->use_count)
595                         {
596                                 if (slot->linked_next)
597                                         slot->linked_next->setSource(slot->current_source);
598                                 else
599                                 {
600                                         setInputSource(slot->current_tuner, slot->current_source);
601                                         slot->removeVtunerPid();
602                                 }
603
604                                 if (base_slot != slot)
605                                 {
606                                         eDVBCISlot *tmp = it->cislot;
607                                         while(tmp->linked_next != slot)
608                                                 tmp = tmp->linked_next;
609                                         ASSERT(tmp);
610                                         if (slot->linked_next)
611                                                 tmp->linked_next = slot->linked_next;
612                                         else
613                                                 tmp->linked_next = 0;
614                                 }
615                                 else // removed old base slot.. update ptr
616                                         base_slot = slot->linked_next;
617                                 slot->linked_next = 0;
618                                 slot->user_mapped = false;
619                         }
620                         eDebug("(3) slot %d usecount is now %d", slot->getSlotID(), slot->use_count);
621                         slot = next;
622                 }
623                 // check if another service is waiting for the CI
624                 recheckPMTHandlers();
625         }
626 }
627
628 void eDVBCIInterfaces::gotPMT(eDVBServicePMTHandler *pmthandler)
629 {
630         eDebug("[eDVBCIInterfaces] gotPMT");
631         PMTHandlerList::iterator it=std::find(m_pmt_handlers.begin(), m_pmt_handlers.end(), pmthandler);
632         if (it != m_pmt_handlers.end() && it->cislot)
633         {
634                 eDVBCISlot *tmp = it->cislot;
635                 while(tmp)
636                 {
637                         eDebugCI("check slot %d %d %d", tmp->getSlotID(), tmp->running_services.empty(), canDescrambleMultipleServices(tmp->getSlotID()));
638                         if (tmp->running_services.empty() || canDescrambleMultipleServices(tmp->getSlotID()))
639                                 tmp->sendCAPMT(pmthandler);
640                         tmp = tmp->linked_next;
641                 }
642         }
643 }
644
645 int eDVBCIInterfaces::getMMIState(int slotid)
646 {
647         eDVBCISlot *slot;
648
649         if( (slot = getSlot(slotid)) == 0 )
650                 return -1;
651
652         return slot->getMMIState();
653 }
654
655 static const char *tuner_source[] = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "CI0", "CI1", "CI2", "CI3"};
656
657 int eDVBCIInterfaces::setInputSource(int tuner_no, data_source source)
658 {
659 //      eDebug("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
660 //      eDebug("eDVBCIInterfaces::setInputSource(%d %d)", tuner_no, (int)source);
661         if (getNumOfSlots() > 1) // FIXME .. we force DM8000 when more than one CI Slot is avail
662         {
663                 char buf[64];
664                 snprintf(buf, 64, "/proc/stb/tsmux/input%d", tuner_no);
665
666                 FILE *input=0;
667                 if((input = fopen(buf, "wb")) == NULL) {
668                         eDebug("cannot open %s", buf);
669                         return 0;
670                 }
671
672                 if (tuner_no > 3)
673                         eDebug("setInputSource(%d, %d) failed... dm8000 just have four inputs", tuner_no, (int)source);
674
675                 switch(source)
676                 {
677                         case TUNER_A ... CI_D:
678                                 fprintf(input, tuner_source[(int)source]);
679                                 break;
680                         default:
681                                 eDebug("setInputSource for input %d failed!!!\n", (int)source);
682                                 break;
683                 }
684
685                 fclose(input);
686         }
687         else  // DM7025
688         {
689                 char buf[64];
690                 snprintf(buf, 64, "/proc/stb/tsmux/input%d", tuner_no);
691
692                 if (tuner_no > 1)
693                         eDebug("setInputSource(%d, %d) failed... dm7025 just have two inputs", tuner_no, (int)source);
694
695                 FILE *input=0;
696                 if((input = fopen(buf, "wb")) == NULL) {
697                         eDebug("cannot open %s", buf);
698                         return 0;
699                 }
700
701                 switch(source)
702                 {
703                         case CI_A:
704                                 fprintf(input, "CI");
705                                 break;
706                         case TUNER_A:
707                                 fprintf(input, "A");
708                                 break;
709                         case TUNER_B:
710                                 fprintf(input, "B");
711                                 break;
712                         default:
713                                 eDebug("setInputSource for input %d failed!!!\n", (int)source);
714                                 break;
715                 }
716
717                 fclose(input);
718         }
719         eDebug("eDVBCIInterfaces->setInputSource(%d, %d)", tuner_no, (int)source);
720         return 0;
721 }
722
723 PyObject *eDVBCIInterfaces::getDescrambleRules(int slotid)
724 {
725         eDVBCISlot *slot = getSlot(slotid);
726         if (!slot)
727         {
728                 char tmp[255];
729                 snprintf(tmp, 255, "eDVBCIInterfaces::getDescrambleRules try to get rules for CI Slot %d... but just %zd slots are available", slotid, m_slots.size());
730                 PyErr_SetString(PyExc_StandardError, tmp);
731                 return 0;
732         }
733         ePyObject tuple = PyTuple_New(3);
734         int caids = slot->possible_caids.size();
735         int services = slot->possible_services.size();
736         int providers = slot->possible_providers.size();
737         ePyObject caid_list = PyList_New(caids);
738         ePyObject service_list = PyList_New(services);
739         ePyObject provider_list = PyList_New(providers);
740         caidSet::iterator caid_it(slot->possible_caids.begin());
741         while(caids)
742         {
743                 --caids;
744                 PyList_SET_ITEM(caid_list, caids, PyLong_FromLong(*caid_it));
745                 ++caid_it;
746         }
747         serviceSet::iterator ref_it(slot->possible_services.begin());
748         while(services)
749         {
750                 --services;
751                 PyList_SET_ITEM(service_list, services, PyString_FromString(ref_it->toString().c_str()));
752                 ++ref_it;
753         }
754         providerSet::iterator provider_it(slot->possible_providers.begin());
755         while(providers)
756         {
757                 ePyObject tuple = PyTuple_New(2);
758                 PyTuple_SET_ITEM(tuple, 0, PyString_FromString(provider_it->first.c_str()));
759                 PyTuple_SET_ITEM(tuple, 1, PyLong_FromUnsignedLong(provider_it->second));
760                 --providers;
761                 PyList_SET_ITEM(provider_list, providers, tuple);
762                 ++provider_it;
763         }
764         PyTuple_SET_ITEM(tuple, 0, service_list);
765         PyTuple_SET_ITEM(tuple, 1, provider_list);
766         PyTuple_SET_ITEM(tuple, 2, caid_list);
767         return tuple;
768 }
769
770 const char *PyObject_TypeStr(PyObject *o)
771 {
772         return o->ob_type && o->ob_type->tp_name ? o->ob_type->tp_name : "unknown object type";
773 }
774
775 RESULT eDVBCIInterfaces::setDescrambleRules(int slotid, SWIG_PYOBJECT(ePyObject) obj )
776 {
777         eDVBCISlot *slot = getSlot(slotid);
778         if (!slot)
779         {
780                 char tmp[255];
781                 snprintf(tmp, 255, "eDVBCIInterfaces::setDescrambleRules try to set rules for CI Slot %d... but just %zd slots are available", slotid, m_slots.size());
782                 PyErr_SetString(PyExc_StandardError, tmp);
783                 return -1;
784         }
785         if (!PyTuple_Check(obj))
786         {
787                 char tmp[255];
788                 snprintf(tmp, 255, "2nd argument of setDescrambleRules is not a tuple.. it is a '%s'!!", PyObject_TypeStr(obj));
789                 PyErr_SetString(PyExc_StandardError, tmp);
790                 return -1;
791         }
792         if (PyTuple_Size(obj) != 3)
793         {
794                 const char *errstr = "eDVBCIInterfaces::setDescrambleRules not enough entrys in argument tuple!!\n"
795                         "first argument should be a pythonlist with possible services\n"
796                         "second argument should be a pythonlist with possible providers/dvbnamespace tuples\n"
797                         "third argument should be a pythonlist with possible caids";
798                 PyErr_SetString(PyExc_StandardError, errstr);
799                 return -1;
800         }
801         ePyObject service_list = PyTuple_GET_ITEM(obj, 0);
802         ePyObject provider_list = PyTuple_GET_ITEM(obj, 1);
803         ePyObject caid_list = PyTuple_GET_ITEM(obj, 2);
804         if (!PyList_Check(service_list) || !PyList_Check(provider_list) || !PyList_Check(caid_list))
805         {
806                 char errstr[512];
807                 snprintf(errstr, 512, "eDVBCIInterfaces::setDescrambleRules incorrect data types in argument tuple!!\n"
808                         "first argument(%s) should be a pythonlist with possible services (reference strings)\n"
809                         "second argument(%s) should be a pythonlist with possible providers (providername strings)\n"
810                         "third argument(%s) should be a pythonlist with possible caids (ints)",
811                         PyObject_TypeStr(service_list), PyObject_TypeStr(provider_list), PyObject_TypeStr(caid_list));
812                 PyErr_SetString(PyExc_StandardError, errstr);
813                 return -1;
814         }
815         slot->possible_caids.clear();
816         slot->possible_services.clear();
817         slot->possible_providers.clear();
818         int size = PyList_Size(service_list);
819         while(size)
820         {
821                 --size;
822                 ePyObject refstr = PyList_GET_ITEM(service_list, size);
823                 if (!PyString_Check(refstr))
824                 {
825                         char buf[255];
826                         snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in service list is not a string.. it is '%s'!!", PyObject_TypeStr(refstr));
827                         PyErr_SetString(PyExc_StandardError, buf);
828                         return -1;
829                 }
830                 char *tmpstr = PyString_AS_STRING(refstr);
831                 eServiceReference ref(tmpstr);
832                 if (ref.valid())
833                         slot->possible_services.insert(ref);
834                 else
835                         eDebug("eDVBCIInterfaces::setDescrambleRules '%s' is not a valid service reference... ignore!!", tmpstr);
836         };
837         size = PyList_Size(provider_list);
838         while(size)
839         {
840                 --size;
841                 ePyObject tuple = PyList_GET_ITEM(provider_list, size);
842                 if (!PyTuple_Check(tuple))
843                 {
844                         char buf[255];
845                         snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in provider list is not a tuple it is '%s'!!", PyObject_TypeStr(tuple));
846                         PyErr_SetString(PyExc_StandardError, buf);
847                         return -1;
848                 }
849                 if (PyTuple_Size(tuple) != 2)
850                 {
851                         char buf[255];
852                         snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules provider tuple has %zd instead of 2 entries!!", PyTuple_Size(tuple));
853                         PyErr_SetString(PyExc_StandardError, buf);
854                         return -1;
855                 }
856                 if (!PyString_Check(PyTuple_GET_ITEM(tuple, 0)))
857                 {
858                         char buf[255];
859                         snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules 1st entry in provider tuple is not a string it is '%s'", PyObject_TypeStr(PyTuple_GET_ITEM(tuple, 0)));
860                         PyErr_SetString(PyExc_StandardError, buf);
861                         return -1;
862                 }
863                 if (!PyLong_Check(PyTuple_GET_ITEM(tuple, 1)))
864                 {
865                         char buf[255];
866                         snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules 2nd entry in provider tuple is not a long it is '%s'", PyObject_TypeStr(PyTuple_GET_ITEM(tuple, 1)));
867                         PyErr_SetString(PyExc_StandardError, buf);
868                         return -1;
869                 }
870                 char *tmpstr = PyString_AS_STRING(PyTuple_GET_ITEM(tuple, 0));
871                 uint32_t orbpos = PyLong_AsUnsignedLong(PyTuple_GET_ITEM(tuple, 1));
872                 if (strlen(tmpstr))
873                         slot->possible_providers.insert(std::pair<std::string, uint32_t>(tmpstr, orbpos));
874                 else
875                         eDebug("eDVBCIInterfaces::setDescrambleRules ignore invalid entry in provider tuple (string is empty)!!");
876         };
877         size = PyList_Size(caid_list);
878         while(size)
879         {
880                 --size;
881                 ePyObject caid = PyList_GET_ITEM(caid_list, size);
882                 if (!PyLong_Check(caid))
883                 {
884                         char buf[255];
885                         snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in caid list is not a long it is '%s'!!", PyObject_TypeStr(caid));
886                         PyErr_SetString(PyExc_StandardError, buf);
887                         return -1;
888                 }
889                 int tmpcaid = PyLong_AsLong(caid);
890                 if (tmpcaid > 0 && tmpcaid < 0x10000)
891                         slot->possible_caids.insert(tmpcaid);
892                 else
893                         eDebug("eDVBCIInterfaces::setDescrambleRules %d is not a valid caid... ignore!!", tmpcaid);
894         };
895         return 0;
896 }
897
898 PyObject *eDVBCIInterfaces::readCICaIds(int slotid)
899 {
900         eDVBCISlot *slot = getSlot(slotid);
901         if (!slot)
902         {
903                 char tmp[255];
904                 snprintf(tmp, 255, "eDVBCIInterfaces::readCICaIds try to get CAIds for CI Slot %d... but just %zd slots are available", slotid, m_slots.size());
905                 PyErr_SetString(PyExc_StandardError, tmp);
906         }
907         else
908         {
909                 int idx=0;
910                 eDVBCICAManagerSession *ca_manager = slot->getCAManager();
911                 const std::vector<uint16_t> *ci_caids = ca_manager ? &ca_manager->getCAIDs() : 0;
912                 ePyObject list = PyList_New(ci_caids ? ci_caids->size() : 0);
913                 if (ci_caids)
914                 {
915                         for (std::vector<uint16_t>::const_iterator it = ci_caids->begin(); it != ci_caids->end(); ++it)
916                                 PyList_SET_ITEM(list, idx++, PyLong_FromLong(*it));
917                 }
918                 return list;
919         }
920         return 0;
921 }
922
923 int eDVBCIInterfaces::setCIClockRate(int slotid, int rate)
924 {
925         eDVBCISlot *slot = getSlot(slotid);
926         if (slot)
927                 return slot->setClockRate(rate);
928         return -1;
929 }
930
931 int eDVBCISlot::send(const unsigned char *data, size_t len)
932 {
933         int res=0;
934         //int i;
935         //eDebugNoNewLine("< ");
936         //for(i=0;i<len;i++)
937         //      eDebugNoNewLine("%02x ",data[i]);
938         //eDebug("");
939
940         if (sendqueue.empty())
941                 res = ::write(fd, data, len);
942
943         if (res < 0 || (unsigned int)res != len)
944         {
945                 unsigned char *d = new unsigned char[len];
946                 memcpy(d, data, len);
947                 sendqueue.push( queueData(d, len) );
948                 notifier->setRequested(eSocketNotifier::Read | eSocketNotifier::Priority | eSocketNotifier::Write);
949         }
950
951         return res;
952 }
953
954 void eDVBCISlot::data(int what)
955 {
956         eDebugCI("CISlot %d what %d\n", getSlotID(), what);
957         if(what == eSocketNotifier::Priority) {
958                 if(state != stateRemoved) {
959                         state = stateRemoved;
960                         while(sendqueue.size())
961                         {
962                                 delete [] sendqueue.top().data;
963                                 sendqueue.pop();
964                         }
965                         eDVBCISession::deleteSessions(this);
966                         eDVBCIInterfaces::getInstance()->ciRemoved(this);
967                         notifier->setRequested(eSocketNotifier::Read);
968                         eDVBCI_UI::getInstance()->setState(getSlotID(),0);
969                 }
970                 return;
971         }
972
973         if (state == stateInvalid)
974                 reset();
975
976         if(state != stateInserted) {
977                 eDebug("ci inserted in slot %d", getSlotID());
978                 state = stateInserted;
979                 eDVBCI_UI::getInstance()->setState(getSlotID(),1);
980                 notifier->setRequested(eSocketNotifier::Read|eSocketNotifier::Priority);
981                 /* enable PRI to detect removal or errors */
982         }
983
984         if (what & eSocketNotifier::Read) {
985                 __u8 data[4096];
986                 int r;
987                 r = ::read(fd, data, 4096);
988                 if(r > 0) {
989 //                      int i;
990 //                      eDebugNoNewLine("> ");
991 //                      for(i=0;i<r;i++)
992 //                              eDebugNoNewLine("%02x ",data[i]);
993 //                      eDebug("");
994                         eDVBCISession::receiveData(this, data, r);
995                         eDVBCISession::pollAll();
996                         return;
997                 }
998         }
999         else if (what & eSocketNotifier::Write) {
1000                 if (!sendqueue.empty()) {
1001                         const queueData &qe = sendqueue.top();
1002                         int res = ::write(fd, qe.data, qe.len);
1003                         if (res >= 0 && (unsigned int)res == qe.len)
1004                         {
1005                                 delete [] qe.data;
1006                                 sendqueue.pop();
1007                         }
1008                 }
1009                 else
1010                         notifier->setRequested(eSocketNotifier::Read|eSocketNotifier::Priority);
1011         }
1012 }
1013
1014 DEFINE_REF(eDVBCISlot);
1015
1016 eDVBCISlot::eDVBCISlot(eMainloop *context, int nr)
1017 {
1018         char filename[128];
1019
1020         application_manager = 0;
1021         mmi_session = 0;
1022         ca_manager = 0;
1023         use_count = 0;
1024         linked_next = 0;
1025         user_mapped = false;
1026         plugged = true;
1027         
1028         slotid = nr;
1029
1030         sprintf(filename, "/dev/ci%d", nr);
1031
1032 //      possible_caids.insert(0x1702);
1033 //      possible_providers.insert(providerPair("PREMIERE", 0xC00000));
1034 //      possible_services.insert(eServiceReference("1:0:1:2A:4:85:C00000:0:0:0:"));
1035
1036         fd = ::open(filename, O_RDWR | O_NONBLOCK);
1037
1038         eDebugCI("CI Slot %d has fd %d", getSlotID(), fd);
1039         state = stateInvalid;
1040
1041         if (fd >= 0)
1042         {
1043                 notifier = eSocketNotifier::create(context, fd, eSocketNotifier::Read | eSocketNotifier::Priority | eSocketNotifier::Write);
1044                 CONNECT(notifier->activated, eDVBCISlot::data);
1045         } else
1046         {
1047                 perror(filename);
1048         }
1049
1050         for(int i = 0; i < NUM_OF_ECM ; i++)
1051         {
1052                 m_ecm[i] = 0;
1053         }
1054         ecm_num = 0;
1055         
1056 }
1057
1058 eDVBCISlot::~eDVBCISlot()
1059 {
1060         eDVBCISession::deleteSessions(this);
1061 }
1062
1063 void eDVBCISlot::setAppManager( eDVBCIApplicationManagerSession *session )
1064 {
1065         application_manager=session;
1066 }
1067
1068 void eDVBCISlot::setMMIManager( eDVBCIMMISession *session )
1069 {
1070         mmi_session = session;
1071 }
1072
1073 void eDVBCISlot::setCAManager( eDVBCICAManagerSession *session )
1074 {
1075         ca_manager = session;
1076 }
1077
1078 int eDVBCISlot::getSlotID()
1079 {
1080         return slotid;
1081 }
1082
1083 int eDVBCISlot::reset()
1084 {
1085         eDebug("CI Slot %d: reset requested", getSlotID());
1086
1087         if (state == stateInvalid)
1088         {
1089                 unsigned char buf[256];
1090                 eDebug("ci flush");
1091                 while(::read(fd, buf, 256)>0);
1092                 state = stateResetted;
1093         }
1094
1095         while(sendqueue.size())
1096         {
1097                 delete [] sendqueue.top().data;
1098                 sendqueue.pop();
1099         }
1100
1101         ioctl(fd, 0);
1102
1103         return 0;
1104 }
1105
1106 int eDVBCISlot::startMMI()
1107 {
1108         eDebug("CI Slot %d: startMMI()", getSlotID());
1109         
1110         if(application_manager)
1111                 application_manager->startMMI();
1112         
1113         return 0;
1114 }
1115
1116 int eDVBCISlot::stopMMI()
1117 {
1118         eDebug("CI Slot %d: stopMMI()", getSlotID());
1119
1120         if(mmi_session)
1121                 mmi_session->stopMMI();
1122         
1123         return 0;
1124 }
1125
1126 int eDVBCISlot::answerText(int answer)
1127 {
1128         eDebug("CI Slot %d: answerText(%d)", getSlotID(), answer);
1129
1130         if(mmi_session)
1131                 mmi_session->answerText(answer);
1132
1133         return 0;
1134 }
1135
1136 int eDVBCISlot::getMMIState()
1137 {
1138         if(mmi_session)
1139                 return 1;
1140
1141         return 0;
1142 }
1143
1144 int eDVBCISlot::answerEnq(char *value)
1145 {
1146         eDebug("CI Slot %d: answerENQ(%s)", getSlotID(), value);
1147
1148         if(mmi_session)
1149                 mmi_session->answerEnq(value);
1150
1151         return 0;
1152 }
1153
1154 int eDVBCISlot::cancelEnq()
1155 {
1156         eDebug("CI Slot %d: cancelENQ", getSlotID());
1157
1158         if(mmi_session)
1159                 mmi_session->cancelEnq();
1160
1161         return 0;
1162 }
1163
1164 int eDVBCISlot::sendCAPMT(eDVBServicePMTHandler *pmthandler, const std::vector<uint16_t> &ids)
1165 {
1166         if (!ca_manager)
1167         {
1168                 eDebug("no ca_manager (no CI plugged?)");
1169                 return -1;
1170         }
1171         const std::vector<uint16_t> &caids = ids.empty() ? ca_manager->getCAIDs() : ids;
1172         ePtr<eTable<ProgramMapSection> > ptr;
1173         if (pmthandler->getPMT(ptr))
1174                 return -1;
1175         else
1176         {
1177                 eDVBTableSpec table_spec;
1178                 ptr->getSpec(table_spec);
1179                 int pmt_version = table_spec.version & 0x1F; // just 5 bits
1180
1181                 eServiceReferenceDVB ref;
1182                 pmthandler->getServiceReference(ref);
1183                 uint16_t program_number = ref.getServiceID().get();
1184                 std::map<uint16_t, uint8_t>::iterator it =
1185                         running_services.find(program_number);
1186                 bool sendEmpty = caids.size() == 1 && caids[0] == 0xFFFF;
1187
1188                 if ( it != running_services.end() &&
1189                         (pmt_version == it->second) &&
1190                         !sendEmpty )
1191                 {
1192                         eDebug("[eDVBCISlot] dont send self capmt version twice");
1193                         return -1;
1194                 }
1195
1196                 std::vector<ProgramMapSection*>::const_iterator i=ptr->getSections().begin();
1197                 if ( i == ptr->getSections().end() )
1198                         return -1;
1199                 else
1200                 {
1201                         unsigned char raw_data[2048];
1202
1203 //                      eDebug("send %s capmt for service %04x to slot %d",
1204 //                              it != running_services.end() ? "UPDATE" : running_services.empty() ? "ONLY" : "ADD",
1205 //                              program_number, slotid);
1206
1207                         CaProgramMapSection capmt(*i++,
1208                                 it != running_services.end() ? 0x05 /*update*/ : running_services.empty() ? 0x03 /*only*/ : 0x04 /*add*/, 0x01, caids );
1209                         while( i != ptr->getSections().end() )
1210                         {
1211                 //                      eDebug("append");
1212                                 capmt.append(*i++);
1213                         }
1214                         capmt.writeToBuffer(raw_data);
1215
1216 // begin calc capmt length
1217                         int wp=0;
1218                         int hlen;
1219                         if ( raw_data[3] & 0x80 )
1220                         {
1221                                 int i=0;
1222                                 int lenbytes = raw_data[3] & ~0x80;
1223                                 while(i < lenbytes)
1224                                         wp = (wp << 8) | raw_data[4 + i++];
1225                                 wp+=4;
1226                                 wp+=lenbytes;
1227                                 hlen = 4 + lenbytes;
1228                         }
1229                         else
1230                         {
1231                                 wp = raw_data[3];
1232                                 wp+=4;
1233                                 hlen = 4;
1234                         }
1235 // end calc capmt length
1236
1237                         if (sendEmpty)
1238                         {
1239 //                              eDebugNoNewLine("SEND EMPTY CAPMT.. old version is %02x", raw_data[hlen+3]);
1240                                 if (sendEmpty && running_services.size() == 1)  // check if this is the capmt for the last running service
1241                                         raw_data[hlen] = 0x03; // send only instead of update... because of strange effects with alphacrypt
1242                                 raw_data[hlen+3] &= ~0x3E;
1243                                 raw_data[hlen+3] |= ((pmt_version+1) & 0x1F) << 1;
1244 //                              eDebug(" new version is %02x", raw_data[hlen+3]);
1245                         }
1246
1247 //                      eDebug("ca_manager %p dump capmt:", ca_manager);
1248 //                      for(int i=0;i<wp;i++)
1249 //                              eDebugNoNewLine("%02x ", raw_data[i]);
1250 //                      eDebug("");
1251
1252                         //dont need tag and lenfield
1253                         ca_manager->sendCAPMT(raw_data + hlen, wp - hlen);
1254                         running_services[program_number] = pmt_version;
1255                 }
1256         }
1257         return 0;
1258 }
1259
1260 void eDVBCISlot::removeService(uint16_t program_number)
1261 {
1262         if (program_number == 0xFFFF)
1263                 running_services.clear();  // remove all
1264         else
1265                 running_services.erase(program_number);  // remove single service
1266 }
1267
1268 int eDVBCISlot::setSource(data_source source)
1269 {
1270         current_source = source;
1271         if (eDVBCIInterfaces::getInstance()->getNumOfSlots() > 1) // FIXME .. we force DM8000 when more than one CI Slot is avail
1272         {
1273                 char buf[64];
1274                 snprintf(buf, 64, "/proc/stb/tsmux/ci%d_input", slotid);
1275                 FILE *ci = fopen(buf, "wb");
1276                 switch(source)
1277                 {
1278                         case TUNER_A ... CI_D:
1279                                 fprintf(ci, tuner_source[(int)source]);
1280                                 break;
1281                         default:
1282                                 eDebug("CI Slot %d: setSource %d failed!!!\n", getSlotID(), (int)source);
1283                                 break;
1284                 }
1285                 fclose(ci);
1286         }
1287         else // DM7025
1288         {
1289 //              eDebug("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
1290 //              eDebug("eDVBCISlot::enableTS(%d %d)", enable, (int)source);
1291                 FILE *ci = fopen("/proc/stb/tsmux/input2", "wb");
1292                 if(ci == NULL) {
1293                         eDebug("cannot open /proc/stb/tsmux/input2");
1294                         return 0;
1295                 }
1296                 if (source != TUNER_A && source != TUNER_B)
1297                         eDebug("CI Slot %d: setSource %d failed!!!\n", getSlotID(), (int)source);
1298                 else
1299                         fprintf(ci, "%s", source==TUNER_A ? "A" : "B");  // configure CI data source (TunerA, TunerB)
1300                 fclose(ci);
1301         }
1302         eDebug("CI Slot %d setSource(%d)", getSlotID(), (int)source);
1303         return 0;
1304 }
1305
1306 int eDVBCISlot::setClockRate(int rate)
1307 {
1308         char buf[64];
1309         snprintf(buf, 64, "/proc/stb/tsmux/ci%d_tsclk", slotid);
1310         FILE *ci = fopen(buf, "wb");
1311         if (ci)
1312         {
1313                 if (rate)
1314                         fprintf(ci, "high");
1315                 else
1316                         fprintf(ci, "normal");
1317                 fclose(ci);
1318                 return 0;
1319         }
1320         return -1;
1321 }
1322
1323 void eDVBCISlot::addVtunerPid(eDVBServicePMTHandler *pmthandler)
1324 {
1325         ePtr<iDVBDemux> demux;
1326         eDVBServicePMTHandler::program p;
1327                 
1328         if (!pmthandler->getDataDemux(demux) && !ecm_num)
1329         {
1330         
1331                 if (!pmthandler->getProgramInfo(p))
1332                 {
1333                         for (std::list<eDVBServicePMTHandler::program::capid_pair>::const_iterator i(p.caids.begin());
1334                                                 i != p.caids.end(); ++i)
1335                         {
1336                                 if (i->capid >= 0)
1337                                 {
1338                                         eDebug("PES Start ECM PID = %d Caid = %d ecm_num=%d", i->capid, i->caid, ecm_num);
1339                                         m_ecm[ecm_num] = new eDVBECMParser(demux);
1340                                         m_ecm[ecm_num++]->start(i->capid);
1341                                 }
1342                         }
1343                 }
1344         }
1345
1346 }
1347
1348 void eDVBCISlot::removeVtunerPid(void)
1349 {
1350         for(int i = 0; i < ecm_num ; i++)
1351         {
1352                 if(m_ecm[i])
1353                 {
1354                         m_ecm[i]->stop();
1355                         m_ecm[i] = 0;
1356                 }
1357         }
1358         ecm_num = 0;
1359 }
1360
1361 eAutoInitP0<eDVBCIInterfaces> init_eDVBCIInterfaces(eAutoInitNumbers::dvb, "CI Slots");