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