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