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