2 #include <lib/dvb/dvbci.h>
3 #include <lib/dvb/dvbservice.h>
4 #include <lib/dvb/si.h>
5 #include <lib/base/i18n.h>
6 #include <lib/system/init.h>
10 #include <sys/ioctl.h>
13 //external defines (because missing dreambox header-files in cvs)
15 #define CI_SOFTRESET 1
16 #define CI_GET_BUFFERSIZE 2
17 #define CI_GET_STATUS 3
18 #define CI_TS_ACTIVATE 6
19 #define CI_TS_DEACTIVATE 7
21 #define MAX_SESSIONS 32
25 int eDVBCI::instance_count
=0;
28 :pollTimer(this), caidcount(0), ml_bufferlen(0), messages(this, 1)
34 eDebug("[DVBCI] start");
36 if (instance_count
== 1)
37 fd
=::open("/dev/ci",O_RDWR
|O_NONBLOCK
);
39 fd
=::open("/dev/ci1",O_RDWR
|O_NONBLOCK
);
43 if (instance_count
== 1)
44 eDebug("[DVBCI] error opening /dev/ci");
46 eDebug("[DVBCI] error opening /dev/ci1");
53 ci
=new eSocketNotifier(this, fd
, eSocketNotifier::Read
, 0);
54 CONNECT(ci
->activated
, eDVBCI::dataAvailable
);
57 CONNECT(pollTimer
.timeout
,eDVBCI::poll
);
59 CONNECT(messages
.recv_msg
, eDVBCI::gotMessage
);
61 strcpy(appName
, _("no module"));
64 for (int i
=0; i
< MAXTRANSPORTSESSIONS
; ++i
)
66 lpduReceiveQueues
[i
].numLPDUS
=0;
67 lpduReceiveQueues
[i
].firstLPDU
=NULL
;
81 messages
.send(eDVBCIMessage(eDVBCIMessage::exit
));
89 void eDVBCI::gotMessage(const eDVBCIMessage
&message
)
93 case eDVBCIMessage::start
:
94 if (state
== stateInit
)
101 case eDVBCIMessage::reset
:
102 // eDebug("[DVBCI] got reset message..");
103 while(sendqueue
.size())
105 delete [] sendqueue
.top().data
;
110 strcpy(appName
,_("no module"));
111 ci_progress(appName
);
115 // if (::ioctl(fd,CI_RESET)<0 )
116 // eDebug("CI_RESET failed (%m)");
117 dataAvailable(1000); // force reset
119 case eDVBCIMessage::init
:
120 // eDebug("[DVBCI] got init message..");
128 strcpy(appName
,_("no module"));
129 ci_progress(appName
);
132 case eDVBCIMessage::go
:
135 case eDVBCIMessage::mmi_begin
:
136 // eDebug("[DVBCI] got mmi_begin message..");
139 case eDVBCIMessage::mmi_end
:
140 // eDebug("[DVBCI] got mmi_end message..");
143 case eDVBCIMessage::mmi_enqansw
:
144 // eDebug("[DVBCI] got mmi_answ message..");
145 mmi_enqansw(message
.data
);
146 delete[] message
.data
;
148 case eDVBCIMessage::mmi_menuansw
:
149 // eDebug("[DVBCI] got mmi_menu_answ message..");
150 mmi_menuansw((int)message
.sid
);
152 case eDVBCIMessage::exit
:
153 // eDebug("[DVBCI] got exit message..");
156 case eDVBCIMessage::getcaids
:
157 // eDebug("[DVBCI] got getcaids message..");
160 case eDVBCIMessage::PMTflush
:
161 // eDebug("[DVBCI] got PMTflush message..");
162 PMTflush(message
.sid
);
164 case eDVBCIMessage::PMTaddPID
:
165 // eDebug("[DVBCI] got PMTaddPID message..");
166 // eDebug("addPID %04x, type %02x", message.pid, message.streamtype );
167 PMTaddPID(message
.sid
,message
.pid
,message
.streamtype
);
169 case eDVBCIMessage::PMTsetVersion
:
170 PMTsetVersion(message
.sid
, message
.pid
);
172 case eDVBCIMessage::PMTaddDescriptor
:
173 // eDebug("[DVBCI] got PMTaddDescriptor message..");
174 // eDebug("addDescr len %02x", message.data[1]+2);
175 // for (int i=0; i < message.data[1]+2; ++i)
176 // eDebugNoNewLine("%02x ", message.data[i]);
178 PMTaddDescriptor(message
.sid
, message
.data
);
180 case eDVBCIMessage::getAppName
:
181 ci_progress(appName
);
184 // disabled... see dvbservice.cpp for more info
186 case eDVBCIMessage::enable_ts:
192 if (::ioctl(fd,CI_GET_STATUS,&present)<0)
194 eDebug("CI_GET_STATUS failed (%m)");
200 if ( ::ioctl(fd, CI_TS_ACTIVATE) < 0 )
201 eDebug("CI_TS_ACTIVATE failed (%m)");
205 case eDVBCIMessage::disable_ts:
206 if ( ::ioctl(fd, CI_TS_DEACTIVATE) < 0 )
207 eDebug("CI_TS_DEACTIVATE failed (%m)");
213 void eDVBCI::mmi_begin()
215 unsigned char buffer
[10];
217 // eDebug("start mmi");
218 memcpy(buffer
,"\x90\x2\x0\x2\x9f\x80\x22\x0",8);
219 sendTPDU(0xA0,8,1,buffer
);
222 void eDVBCI::mmi_end()
224 unsigned char buffer
[10];
226 // eDebug("stop mmi");
227 memcpy(buffer
,"\x90\x2\x0\x4\x9f\x88\x00\x00",8);
228 sendTPDU(0xA0,8,1,buffer
);
231 void eDVBCI::mmi_enqansw(unsigned char *buf
)
233 // eDebug("got mmi_answer");
234 unsigned char buffer
[ buf
[0]+8 ];
235 memcpy(buffer
,"\x90\x2\x0\x4\x9f\x88\x08",7);
236 memcpy(buffer
+7, buf
, buf
[0]+1 );
239 for(;i
<MAX_SESSIONS
;++i
) // search mmi session .. hope it exist only one :)
240 if(sessions
[i
].state
&& sessions
[i
].service_class
==0x400041)
242 buffer
[3]=i
; // session
243 sendTPDU(0xA0,buf
[0]+8,1,buffer
);
245 for (int i
=0; i
< buf
[0]+8; ++i
)
246 eDebugNoNewLine("%02x ", buffer
[i
]);
251 if ( i
== MAX_SESSIONS
)
252 eDebug("[DVBCI] no mmi session found(enq) !");
255 void eDVBCI::mmi_menuansw(int val
)
257 // eDebug("got mmi_menu_answer %d",val);
258 unsigned char buffer
[9];
259 memcpy(buffer
,"\x90\x2\x0\x4\x9f\x88\x0B\x1",8);
262 for(;i
<MAX_SESSIONS
;++i
) // search mmi session .. hope it exist only one :)
263 if(sessions
[i
].state
&& sessions
[i
].service_class
==0x400041)
267 sendTPDU(0xA0,9,1,buffer
);
270 if ( i
== MAX_SESSIONS
)
271 eDebug("[DVBCI] no mmi session found!");
274 void eDVBCI::PMTsetVersion(int sid
, int version
)
276 for (CIServiceMap::iterator
it( services
.begin() );
277 it
!= services
.end(); ++it
)
279 if ( it
->first
== sid
)
281 for (std::list
<tempPMT_t
>::iterator
i( it
->second
.begin() );
282 i
!= it
->second
.end(); )
285 delete [] i
->descriptor
;
286 i
= it
->second
.erase(i
);
294 services
[sid
].push_back(tmp
);
297 void eDVBCI::PMTflush(int sid
)
299 for (CIServiceMap::iterator
it( services
.begin() );
300 it
!= services
.end(); )
302 if ( it
->first
== sid
|| sid
== -1 )
304 bool scrambled
=false;
305 std::map
<int,int>::iterator d
= versions
.find(it
->first
);
306 if ( d
!= versions
.end() )
308 for (std::list
<tempPMT_t
>::iterator
i( it
->second
.begin() );
309 i
!= it
->second
.end(); )
313 delete [] i
->descriptor
;
314 i
= it
->second
.erase(i
);
322 int oldvers
= d
->second
;
323 it
->second
.front().version
=((oldvers
&0xC1)|((oldvers
+2)&0x3E));
324 newService(); // i hope the ci give now this "slot" free
328 versions
.erase(it
->first
); // remove from last send version map
330 services
.erase(it
++); // remove from known service map
332 break; // the only one service is flushed.. break now
339 void eDVBCI::PMTaddPID(int sid
, int pid
, int streamtype
)
341 //eDebug("got new PID:%x",pid);
345 entry
.streamtype
= streamtype
;
347 services
[sid
].push_back(entry
);
350 void eDVBCI::PMTaddDescriptor(int sid
, unsigned char *data
)
352 //eDebug("got new CA-Descr. for CAID:%.2x%.2x",data[2],data[3]);
355 entry
.descriptor
= data
;
356 services
[sid
].push_back(entry
);
359 void eDVBCI::newService()
361 //eDebug("got new %d PMT entrys",tempPMTentrys);
362 ci_progress(appName
);
363 unsigned char capmt
[2048];
365 memcpy(capmt
,"\x90\x2\x0\x3\x9f\x80\x32",7); //session nr.3 & capmt-tag
368 for (std::map
<int, std::list
<tempPMT_t
> >::iterator it
= services
.begin();
369 it
!= services
.end(); ++it
)
374 if ( !versions
.size() )
375 capmt
[9] = 0x03; // only
378 std::map
<int,int>::iterator i
= versions
.find(it
->first
);
379 if ( i
!= versions
.end() )
381 if (it
->second
.front().version
!= i
->second
)
382 capmt
[9]=0x05; // update
384 continue; // this is the same pmt version.. don't send..
387 capmt
[9]=0x04; // new service.. add
390 // store new PMT version
391 versions
[it
->first
]=it
->second
.front().version
;
393 // eDebug("ca_pmt_list_management = %d", capmt[9]);
395 capmt
[10]=(unsigned char)((it
->first
>>8) & 0xff); //prg-nr
396 capmt
[11]=(unsigned char)(it
->first
& 0xff); //prg-nr
398 capmt
[12]=it
->second
.front().version
; //reserved - version - current/next
399 capmt
[13]=0x00; //reserved - prg-info len
400 capmt
[14]=0x00; //prg-info len
407 for( std::list
<tempPMT_t
>::iterator i
= it
->second
.begin();
408 i
!= it
->second
.end(); ++i
)
413 capmt
[lenpos
]=((len
& 0xf00)>>8);
414 capmt
[lenpos
+1]=(len
& 0xff);
418 capmt
[wp
++]=(i
->streamtype
& 0xffff);
419 capmt
[wp
++]=((i
->pid
>> 8) & 0xff);
420 capmt
[wp
++]=(i
->pid
& 0xff);
425 for(;x
<caidcount
;x
++)
427 if(caids
[x
] == ((i
->descriptor
[2]<<8)|(i
->descriptor
[3])))
436 capmt
[wp
++]=0x01; //ca_pmt_command_id
440 memcpy(capmt
+wp
,i
->descriptor
,i
->descriptor
[1]+2);
441 wp
+=i
->descriptor
[1]+2;
442 len
+=i
->descriptor
[1]+2;
448 capmt
[lenpos
]=((len
& 0xf00)>>8);
449 capmt
[lenpos
+1]=(len
& 0xff);
451 for(int i
=1;i
<MAX_SESSIONS
;++i
)
452 if(sessions
[i
].state
&& (sessions
[i
].service_class
==0x30041 || sessions
[i
].service_class
==0x34100))
454 // eDebug("[DVBCI] send capmt with session id %d", i);
455 capmt
[3]=i
; //session_id
456 create_sessionobject(capmt
+4,capmt
+9,wp
-9,i
);
458 eDebug("CAPMT-LEN:%d",wp
);
459 for(int i
=0;i
<wp
;++i
)
460 eDebugNoNewLine("%02x ",capmt
[i
]);
467 void eDVBCI::create_sessionobject(unsigned char *tag
,unsigned char *data
,unsigned int len
,int session
)
469 unsigned char buffer
[len
+3+5+4]; //data + tag_len + max_lengtfieldlen + spdu_header
472 memcpy(buffer
,"\x90\x2\x0\x3",4); //session nr.3 & capmt-tag
473 buffer
[3]=session
; //session_id
475 memcpy(buffer
+4,tag
,3);
480 memcpy(buffer
+8,data
,len
);
486 buffer
[8]=(len
&0xff00)>>8;
488 memcpy(buffer
+10,data
,len
);
495 memcpy(buffer
+9,data
,len
);
500 for(int i
=0;i
<newlen
;++i
)
501 printf("%02x ",buffer
[i
]);
504 sendTPDU(0xA0,newlen
,1,buffer
,true);
508 void eDVBCI::clearCAIDs()
510 eDVBServiceController
*sapi
=eDVB::getInstance()->getServiceAPI();
519 void eDVBCI::addCAID(int caid
)
521 caids
[caidcount
++]=caid
& 0xffff;
524 void eDVBCI::pushCAIDs()
526 eDVBServiceController
*sapi
=eDVB::getInstance()->getServiceAPI();
530 // eDebug("count for caids: %d",caidcount);
531 singleLock
s(eDVBServiceController::availCALock
);
532 for(unsigned int i
=0;i
<caidcount
;++i
)
533 sapi
->availableCASystems
.insert(caids
[i
]);
536 void eDVBCI::sendTPDU(unsigned char tpdu_tag
,unsigned int len
,unsigned char tc_id
,unsigned char *data
,bool dontQueue
)
538 unsigned char *buffer
= new unsigned char[len
+7];
547 buffer
[4]=((len
+1)>>8);
548 buffer
[5]=((len
+1) & 0xff);
550 memcpy(buffer
+7,data
,len
);
552 /* for ( int i=0; i < len+5; ++i )
553 eDebugNoNewLine("%02x ", buffer[i+2] );
556 if ( sendqueue
.empty() )
558 // eDebug("queue empty.. try to send data");
560 if ( !sendData(tc_id
,buffer
+2,len
+5) )
562 // eDebug("CI is busy... push to sendqueue..");
563 sendqueue
.push( queueData(tc_id
, buffer
, len
+5) );
568 else // already data in sendqueue.. push to end of queue
570 // eDebug("queuesize = %d.. append new data to queue", sendqueue.size());
571 sendqueue
.push( queueData(tc_id
, buffer
, len
+5) );
578 memcpy(buffer
+5,data
,len
);
579 /* for ( int i=0; i < len+3; ++i )
580 eDebugNoNewLine("%02x ", buffer[i+2] );
582 if ( sendqueue
.empty() )
584 // eDebug("queue empty.. try to send data");
585 if ( !sendData(tc_id
,buffer
+2,len
+3) )
587 // eDebug("CI is busy... push to sendqueue..");
588 sendqueue
.push( queueData(tc_id
, buffer
, len
+3) );
595 // eDebug("queusize = %d.. append new data to queue", sendqueue.size());
596 sendqueue
.push( queueData(tc_id
, buffer
, len
+3) );
601 bool eDVBCI::sendData(unsigned char tc_id
,unsigned char *data
,unsigned int len
)
605 if(write(fd
,data
,len
)<0)
609 eDebug("[DVBCI] write error");
617 void eDVBCI::help_manager(unsigned int session
)
619 switch(sessions
[session
].internal_state
)
623 unsigned char buffer
[12];
624 eDebug("[DVBCI] [HELP MANAGER] up to now nothing happens -> profile_enq");
626 memcpy(buffer
,"\x90\x2\x0\x1\x9f\x80\x10\x0",8);
627 sendTPDU(0xA0,8,sessions
[session
].tc_id
,buffer
);
629 sessions
[session
].internal_state
=1;
634 unsigned char buffer
[12];
636 eDebug("[DVBCI] [HELP MANAGER] profile_change");
638 memcpy(buffer
,"\x90\x2\x0\x1\x9f\x80\x12\x0",8);
639 sendTPDU(0xA0,8,sessions
[session
].tc_id
,buffer
);
641 sessions
[session
].internal_state
=2;
646 unsigned char buffer
[40];
648 eDebug("[DVBCI] [HELP MANAGER] profile_reply");
649 //was wir alles koennen :)
650 memcpy(buffer
,"\x90\x2\x0\x1\x9f\x80\x11",7);
653 buffer
[8]=0x00; //res. manager
656 buffer
[11]=0x41; //? :)
659 buffer
[13]=0x02; //02
661 buffer
[15]=0x41; //CA
665 buffer
[18]=0x00; //00 //date-time
669 buffer
[22]=0x00; //mmi
672 sendTPDU(0xA0,24,sessions
[session
].tc_id
,buffer
);
673 sessions
[session
].internal_state
=3;
677 //printf("[HELP MANAGER] undefined state\n"); //or ready ;)
682 void eDVBCI::app_manager(unsigned int session
)
684 switch(sessions
[session
].internal_state
)
688 unsigned char buffer
[12];
689 eDebug("[DVBCI] [APPLICATION MANAGER] up to now nothing happens -> app_info_enq");
690 memcpy(buffer
,"\x90\x2\x0\x2\x9f\x80\x20\x0",8);
691 sendTPDU(0xA0,8,sessions
[session
].tc_id
,buffer
);
692 sessions
[session
].internal_state
=1;
703 void eDVBCI::ca_manager(unsigned int session
)
705 // eDebug("[DVBCI] ca_manager session %d", session );
706 switch(sessions
[session
].internal_state
)
710 unsigned char buffer
[12];
711 sessions
[session
].internal_state
=1;
714 /* // disabled.. for more info see dvbservice.cpp
715 eServiceHandler *serviceHandler =
716 eServiceInterface::getInstance()->getService();
717 if ( serviceHandler && serviceHandler->getFlags() & eServiceHandler::flagIsScrambled )*/
719 if ( ::ioctl(fd
,CI_TS_ACTIVATE
)<0 )
720 eDebug("CI_TS_ACTIVATE failed (%m)");
724 eDebug("[DVBCI] [CA MANAGER] up to now nothing happens -> ca_info_enq");
726 memcpy(buffer
,"\x90\x2\x0\x3\x9f\x80\x30\x0",8);
728 if(!sessions
[session
].state
)
729 eDebug("CA-MANAGER SESSION %d not assigned !", session
);
733 if ( sessions
[session
].service_class
==0x30041 ||
734 sessions
[session
].service_class
==0x34100 )
735 sendTPDU(0xA0,8,sessions
[session
].tc_id
,buffer
);
737 eDebug("CA-MANAGER SESSION %d has invalid service_class %08x", sessions
[session
].service_class
);
743 eDebug("[DVBCI] [CA MANAGER] send ca_pmt");
746 newService(); // send with "only" service
747 sessions
[session
].internal_state
=2;
751 eDebug("unhandled session(%d) state %d", session
, sessions
[session
].internal_state
);
756 void eDVBCI::handle_session(unsigned char *data
,int len
)
759 eDebugNoNewLine("[DVBCI] dump handle session tag:");
760 for (int i
=0; i
< len
; ++i
)
761 eDebugNoNewLine("%02x ", data
[i
]);
765 if(data
[4]==0x9f && data
[5]==0x80 && data
[6]==0x11)
766 help_manager(data
[3]);
767 else if(data
[4]==0x9f && data
[5]==0x80 && data
[6]==0x10)
769 help_manager(data
[3]);
770 ci_progress("help-manager init");
772 else if(data
[4]==0x9f && data
[5]==0x80 && data
[6]==0x21)
774 eDebug("[DVBCI] APP-INFO");
775 memcpy(appName
,data
+14,data
[13]);
776 appName
[data
[13]]=0x0;
777 ci_progress("application manager-init");
779 else if(data
[4]==0x9f && data
[5]==0x80 && data
[6]==0x31)
782 eDebug("[DVBCI] CA-INFO");
785 eDebug("[DVBCI] [CA MANAGER] error in ca-info");
787 ci_progress("[DVBCI]ca-manager init");
789 for(i
=8;i
<data
[7]+8;i
+=2)
791 eDebug("[DVBCI] [CA MANAGER] add CAID: %04x",data
[i
]<<8|data
[i
+1]);
792 addCAID(data
[i
]<<8|data
[i
+1]);
796 if ( !sessions
[data
[3]].state
)
797 eDebug("[DVBCI] SESSION %d is not assigned !");
800 if ( sessions
[data
[3]].service_class
==0x30041 ||
801 sessions
[data
[3]].service_class
==0x34100)
804 eDebug("SESSION ID %d is no CA-MANAGER");
807 else if(data
[4]==0x9f && data
[5]==0x88 && data
[6]==0x01)
809 unsigned char buffer
[20];
810 eDebug("[DVBCI] [APPLICATION MANAGER] -> display-control");
811 memcpy(buffer
,"\x90\x2\x0\x4\x9f\x88\x2\x2\x1\x1",10);
812 buffer
[3]=data
[3]; // session id
813 sendTPDU(0xA0,10,1,buffer
);
815 else if(data
[4]==0x9f && data
[5]==0x84 && data
[6]==0x40)
817 unsigned char buffer
[20];
818 eDebug("[DVBCI] [DATE TIME ENQ]");
819 memcpy(buffer
,"\x90\x2\x0\x5\x9f\x88\x41\x5\xcd\x8A\x23\x13\x12",13);
820 buffer
[3]=data
[3]; // session id
821 sendTPDU(0xA0,13,1,buffer
);
823 else if(data
[4]==0x9f && data
[5]==0x88)
826 eDebug("[DVBCI] [APPLICATION MANAGER] -> mmi_menu");
828 eDebug("[DVBCI] mmi len:%d",len
);
829 for(int i
=0;i
<len
;++i
)
830 eDebugNoNewLine("%02x ",data
[i
]);
833 memcpy(buffer
,data
+4,len
-4);
834 ci_mmi_progress(buffer
,len
-4);
838 eDebug("[DVBCI] unhandled session:");
839 for(int i
=0;i
<len
;++i
)
840 eDebugNoNewLine("%02x ",data
[i
]);
845 int eDVBCI::service_available(unsigned long service_class
)
847 switch(service_class
)
853 case 0x034100: //WTF? find the bug ... endianess fool on integer-fields?
854 //if it is so...perhaps its better you switch the xa to 8bit mode *g*
859 eDebug("[DVBCI] service %08x not available", service_class
);
864 void eDVBCI::handle_spdu(unsigned int tpdu_tc_id
,unsigned char *data
,int len
)
866 unsigned char buffer
[40];
868 // eDebug("[DVBCI]handle_spdu(%02x)", data[0]);
873 handle_session(data
,len
);
876 if(service_available(*(unsigned long*)(data
+2)))
879 eDebugNoNewLine("[DVBCI] dump open session tag:");
880 for (int i
=0; i
< len
; ++i
)
881 eDebugNoNewLine("%02x ", data
[i
]);
885 for(;i
<MAX_SESSIONS
;++i
)
886 if(sessions
[i
].state
==STATE_FREE
)
890 eDebug("[DVBCI] no free sessions left");
891 memcpy(buffer
,"\x92\x7\xf0\x0\x0\x0\x0\x0\x0",9);
892 memcpy(buffer
+3,data
+2,4);
893 sendTPDU(0xA0,9,tpdu_tc_id
,buffer
);
897 sessions
[i
].state
=STATE_OPEN
;
898 sessions
[i
].service_class
=*(unsigned long*)(data
+2);
899 sessions
[i
].tc_id
=tpdu_tc_id
;
900 sessions
[i
].internal_state
=0;
902 memcpy(buffer
,"\x92\x7\x0",3);
903 memcpy(buffer
+3,data
+2,4);
906 sendTPDU(0xA0,9,tpdu_tc_id
,buffer
);
908 eDebug("[DVBCI] serviceclass (%x) request accepted on %d",*(unsigned long*)(data
+2),i
);
910 if(sessions
[i
].service_class
==0x10041)
912 if(sessions
[i
].service_class
==0x20041)
914 if(sessions
[i
].service_class
==0x30041)
916 if(sessions
[i
].service_class
==0x34100)
921 eDebug("[DVBCI] unknown serviceclass (%x) requested",*(unsigned long*)(data
+2));
922 memcpy(buffer
,"\x92\x7\xf0",3);
923 memcpy(buffer
+3,data
+2,4);
924 sendTPDU(0xA0,9,tpdu_tc_id
,buffer
);
927 case 0x95: //T_close_session
930 eDebugNoNewLine("[DVBCI] dump close session tag:");
931 for (int i
=0; i
< len
; ++i
)
932 eDebugNoNewLine("%02x ", data
[i
]);
935 memcpy(buffer
,"\x96\x3\xf0",3);
938 if( sessions
[data
[3]].state
!= STATE_FREE
)
940 buffer
[2]=0; // session freed
941 sessions
[data
[3]].state
=STATE_FREE
;
942 eDebug("[DVBCI] freeing session %d",data
[3]);
943 if(sessions
[data
[3]].service_class
== 0x400041)
945 eDebug("[DVBCI] close mmi after session free");
946 char *buf
="\x9f\x88\x00\x00";
947 ci_mmi_progress(buf
,4);
950 sendTPDU(0xA0,5,tpdu_tc_id
,buffer
);
954 eDebug("[DVBCI] unknown SPDU-TAG:%x",data
[0]);
958 void eDVBCI::receiveTPDU(unsigned char tpdu_tag
,unsigned int tpdu_len
,unsigned char tpdu_tc_id
,unsigned char *data
)
960 // eDebug("[DVBCI] receiveTPDU %02x", tpdu_tag);
965 // sendTPDU(0x81,0,tpdu_tc_id,0);
970 eDebug("[DVBCI] T_C_ID %d wurde erstellt",tpdu_tc_id
);
977 if(data
[0] >= 0x90 && data
[0] <= 0x96)
979 handle_spdu(tpdu_tc_id
,data
,tpdu_len
);
984 eDebug("[DVBCI] unknown spdu-tag:%x",data
[0]);
989 eDebug("[DVBCI] unknown tpdu-tag:%x, len = %d", tpdu_tag
, tpdu_len
);
994 void eDVBCI::incoming(unsigned char *buffer
,int len
)
1003 printf("incoming:");
1004 for(int i
=0;i
<len
;++i
)
1005 printf("%02x ",buffer
[i
]);
1015 if((buffer
[2] & 0xF0) != 0x80 && (buffer
[2] & 0xF0) != 0xA0)
1020 //the cheapest defrag on earth *g*
1021 if(m_l
&& ml_bufferlen
==0) //first fragment
1024 tpdu_tag
=buffer
[x
++];
1025 tpdu_len
=y
=buffer
[x
++];
1026 if(y
&0x80) //aua fix me
1028 //eDebug("y & 0x80 %x",tpdu_len);
1032 tpdu_len
=(buffer
[x
++]&0xff)<<(((y
*8)-8)-(i
*8));
1034 //tpdu_len=buffer[x++];
1035 //eDebug("len:%d\n",tpdu_len);
1038 tpdu_tc_id
=buffer
[x
++];
1040 memcpy(ml_buffer
,buffer
+x
,len
-7);
1042 ml_buffersize
=tpdu_len
;
1045 else if(!m_l
&& ml_bufferlen
) //last fragment
1047 memcpy(ml_buffer
+ml_bufferlen
,buffer
+2,len
-2);
1048 receiveTPDU(0xA0,ml_buffersize
,1,ml_buffer
);
1051 else //not fragmented
1056 tpdu_tag
=buffer
[x
++];
1057 tpdu_len
=y
=buffer
[x
++];
1058 if(y
&0x80) //aua fix me
1060 //eDebug("y & 0x80 %x",tpdu_len);
1064 tpdu_len
=(buffer
[x
++]&0xff)<<(((y
*8)-8)-(i
*8));
1065 //tpdu_len=buffer[x++];
1066 //eDebug("len:%d\n",tpdu_len);
1069 //if(tpdu_len>(len-6))
1071 tpdu_tc_id
=buffer
[x
++];
1073 printf("tpdu (%02x):",tpdu_tag
);
1074 for(int i
=0;i
<tpdu_len
;++i
)
1075 printf("%02x ",buffer
[(x
-tpdu_len
+1)+i
]);
1078 receiveTPDU(tpdu_tag
,tpdu_len
,tpdu_tc_id
,buffer
+x
);
1085 ptrlpduQueueElem
eDVBCI::AllocLpduQueueElem(unsigned char t_c_id
)
1087 ptrlpduQueueElem curElem
;
1089 curElem
= new lpduQueueElem
;
1091 curElem
->lpduLen
= 0;
1093 (curElem
->lpdu
)[0] = t_c_id
;
1095 curElem
->nextElem
= NULL
;
1100 int eDVBCI::lpduQueueElemIsMore(ptrlpduQueueElem curElem
)
1101 // Check header of contained LPDU for "more" flag
1104 if ((curElem
->lpdu
)[1] & 0x80)
1110 void eDVBCI::incoming(unsigned char *buffer
,int len
)
1112 ptrlpduQueueElem curElem
, lastElem
;
1114 unsigned char t_c_id
;
1116 unsigned char * payloadData
;
1119 unsigned char from_t_c_id
;
1125 // Allocate LPDU queue element
1126 curElem
= AllocLpduQueueElem(0);
1129 memcpy(curElem
->lpdu
,buffer
,len
);
1130 curElem
->lpduLen
=len
;
1133 t_c_id
= (curElem
->lpdu
)[0];
1135 // Append to the current receive queue for the transport ID
1136 lastElem
= lpduReceiveQueues
[t_c_id
].firstLPDU
;
1138 if (lastElem
== NULL
)
1140 lpduReceiveQueues
[t_c_id
].firstLPDU
= curElem
;
1144 while (lastElem
->nextElem
!= NULL
)
1145 lastElem
= lastElem
->nextElem
;
1147 lastElem
->nextElem
= curElem
;
1149 // Increment LPDU count
1150 lpduReceiveQueues
[t_c_id
].numLPDUS
++;
1152 if (!lpduQueueElemIsMore(curElem
))
1156 length
= lpduReceiveQueues
[t_c_id
].numLPDUS
* LPDUPAYLOADLEN
;
1157 from_t_c_id
= t_c_id
;
1159 payloadData
= new unsigned char[length
];
1162 curElem
= lpduReceiveQueues
[t_c_id
].firstLPDU
;
1164 while (curElem
!= NULL
)
1166 memcpy(payloadData
+ payloadIndex
, (curElem
->lpdu
) + LPDUHEADERLEN
, (curElem
->lpduLen
) - LPDUHEADERLEN
);
1168 payloadIndex
+= ((curElem
->lpduLen
) - LPDUHEADERLEN
);
1169 (length
) += ((curElem
->lpduLen
) - LPDUHEADERLEN
);
1172 curElem
= curElem
->nextElem
;
1174 // And remove element
1178 lpduReceiveQueues
[t_c_id
].numLPDUS
= 0;
1179 lpduReceiveQueues
[t_c_id
].firstLPDU
= NULL
;
1181 //printf("data assembled\n");
1182 //for(int i=0;i<length;++i)
1183 // printf("%02x ",payloadData[i]);
1186 //if(payloadData[length-4] != 0x80)
1187 // printf("Status-Field broken!!! (tag)\n");
1189 //if(payloadData[length-3] != 0x2)
1190 // printf("Status-Field broken!!! (len)\n");
1192 if(payloadData
[length
-1] == 0x80)
1194 // eDebug("[DVBCI] query data");
1195 sendTPDU(0x81,0,payloadData
[length
-2],0);
1200 int cl
=payloadData
[1] & 0x7f;
1202 if(payloadData
[1] & 0x80)
1204 lenfield
= payloadData
[1] & 0x7f;
1207 for(int i
=0;i
<lenfield
;++i
)
1208 cl
|= payloadData
[2+i
] << ((lenfield
-(i
+1))*8);
1211 //printf("lenfield:%d len:%d\n",lenfield,cl);
1215 //for(int i=0;i<length;++i)
1216 // printf("%02x ",payloadData[i]);
1220 receiveTPDU(payloadData
[0],cl
,t_c_id
,payloadData
+(2+lenfield
));
1222 delete [] payloadData
;
1229 void eDVBCI::startTimer()
1231 pollTimer
.start(80,true);
1234 void eDVBCI::stopTimer()
1239 void eDVBCI::dataAvailable(int what
)
1242 unsigned char buffer
[1024];
1249 if (::ioctl(fd
,CI_GET_STATUS
,&present
)<0)
1250 eDebug("[DVBCI] GET_STATUS failed (%m)");
1252 if(present
== 2 || present
!= 1)
1254 eDebug("[DVBCI] module removed");
1256 // clear receive lpdu queues
1257 ptrlpduQueueElem curElem
, lastElem
;
1258 for (int i
=0; i
< MAXTRANSPORTSESSIONS
; ++i
)
1260 if (lpduReceiveQueues
[i
].numLPDUS
)
1262 curElem
= lpduReceiveQueues
[i
].firstLPDU
;
1263 while (curElem
!= NULL
)
1266 curElem
= curElem
->nextElem
;
1267 // And remove element
1274 while(sendqueue
.size())
1276 delete [] sendqueue
.top().data
;
1280 strcpy(appName
,_("no module"));
1281 ci_progress(appName
);
1283 char *buf
="\x9f\x88\x00\x00";
1284 ci_mmi_progress(buf
,4);
1286 for(int i
=1;i
<MAX_SESSIONS
;++i
)
1287 sessions
[i
].state
=STATE_FREE
;
1289 ::read(fd
,&buffer
,0);
1297 if(ci_state
==0) //CI plugged
1300 eDebug("[DVBCI] module inserted");
1302 ci_progress("module found");
1304 // eZapMain::getInstance()->postMessage(eZapMessage(1,"Common Interface","CI inserted - initializing...",10),0);
1305 // SEND FAKE Message to eZapMain... now we can show ci plug message
1307 ci_mmi_progress(buf
,4);
1309 for(i
=1;i
<MAX_SESSIONS
;++i
)
1310 sessions
[i
].state
=STATE_FREE
;
1314 ::read(fd
,&buffer
,0);
1316 if (::ioctl(fd
,CI_RESET
)<0 ) // != 0
1318 eDebug("[DVBCI] RESET failed (%m)");
1325 while ( sendqueue
.size() )
1327 // eDebug("[DVBCI] clear queue");
1328 delete [] sendqueue
.top().data
;
1335 size
=::read(fd
,&buffer
,sizeof(buffer
));
1336 //eDebug("READ:%d",size);
1343 printf("%02x ",buffer
[i
]);
1346 incoming(buffer
,size
);
1348 if ( sendqueue
.size() )
1350 queueData d
= sendqueue
.top();
1352 if ( !sendData( d
.tc_id
, d
.data
+2, d
.len
) )
1354 // add this entry with higher priority to sendqueue..
1355 sendqueue
.push( queueData( d
.tc_id
, d
.data
, d
.len
, 1 ) );
1361 if (::ioctl(fd
,8,&i
)<0)
1362 eDebug("[DVBCI] GET failed (%m)");
1375 sendTPDU(0x82,0,1,0);
1387 eDebug("[DVBCI] TIMER");
1390 if (::ioctl(fd
,CI_GET_STATUS
,&present
)<0)
1391 eDebug("CI_GET_STATUS failed (%m)");
1393 if(present
) //CI removed
1394 sendTPDU(0xA0,0,1,0);