summaryrefslogtreecommitdiffstats
path: root/kaffeine/src/input/dvb/dvbcam.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kaffeine/src/input/dvb/dvbcam.cpp')
-rw-r--r--kaffeine/src/input/dvb/dvbcam.cpp1252
1 files changed, 619 insertions, 633 deletions
diff --git a/kaffeine/src/input/dvb/dvbcam.cpp b/kaffeine/src/input/dvb/dvbcam.cpp
index 1cb5b86..e525f6d 100644
--- a/kaffeine/src/input/dvb/dvbcam.cpp
+++ b/kaffeine/src/input/dvb/dvbcam.cpp
@@ -1,6 +1,7 @@
/*
* dvbcam.cpp
*
+ * Copyright (C) 2008 Christophe Thommeret <hftom@free.fr>
* Copyright (C) 2006 Christoph Pfister <christophpfister@gmail.com>
*
* code based on ca_zap (LGPL)
@@ -29,173 +30,48 @@
#include <sys/poll.h>
#include <linux/dvb/ca.h>
-#include <libdvbapi/dvbca.h>
-#include <libdvbapi/dvbdemux.h>
-#include <libdvben50221/en50221_app_ai.h>
-#include <libdvben50221/en50221_app_ca.h>
-#include <libdvben50221/en50221_app_rm.h>
-#include <libdvben50221/en50221_app_tags.h>
-#include <libdvben50221/en50221_session.h>
-#include <libucsi/mpeg/section.h>
-
+#include <qapplication.h>
#include <qthread.h>
#include <qstring.h>
+#include <qspinbox.h>
+#include <qlabel.h>
+#include <qtextbrowser.h>
+#include <qlineedit.h>
+#include <qpushbutton.h>
#include "dvbcam.h"
-class DvbCamCamHandler
-{
-public:
- virtual ~DvbCamCamHandler();
-
- bool init();
-
- virtual void poll() = 0;
- virtual bool registerCam(int ca_fd, uint8_t slot) = 0;
-
- bool sendPmt(char *pmt_buffer, int size);
-
-protected:
- DvbCamCamHandler();
-
- static int infoCallback(void *arg, uint8_t slot_id, uint16_t session_number, uint32_t ca_id_count, uint16_t *ca_ids);
-
- virtual bool sub_init() = 0;
-
- void *AiResource;
- void *CaResource;
- en50221_app_send_functions SendFuncs;
-
- volatile int SessionNumber;
-};
-
-class DvbCamCamThread : protected QThread
-{
-public:
- DvbCamCamThread(int adapter, int ca_device, int ci_type);
- ~DvbCamCamThread();
-
- void start();
- void stop();
- void wait();
-
- bool processPmt(int demux_fd);
-
-private:
- void run();
-
- int Adapter;
- int CaDevice;
- int ciType;
-
- DvbCamCamHandler *CamHandler;
-
- char PmtBuffer[4096]; // we imply that processPmt is only once called
-
- volatile int PmtSize; // PmtSize <= 0 means PmtBuffer invalid
- volatile bool Stopped;
-};
-
-class DvbCamPmtThread : protected QThread
-{
-public:
- DvbCamPmtThread(DvbCamCamThread *cam_thread, int adapter, int demux_device, int service_id);
- ~DvbCamPmtThread();
-
- void start();
- void stop();
- void wait();
-
-private:
- int createSectionFilter(uint16_t pid, uint8_t table_id);
- int processPat(int demux_fd);
- void run();
+#define TIMER_EVENT_MMI_OPEN 500
+#define TIMER_EVENT_MMI_CLOSE 501
+#define TIMER_EVENT_CAM_READY 502
- DvbCamCamThread *CamThread;
- int Adapter;
- int DemuxDevice;
- int ServiceId;
- volatile bool Stopped;
-};
-class DvbCamCamHandlerLLCI : public DvbCamCamHandler
-{
-public:
- DvbCamCamHandlerLLCI();
- ~DvbCamCamHandlerLLCI();
-
-private:
- struct SlResource
- {
- en50221_app_public_resource_id resid;
- uint32_t binary_resource_id;
- en50221_sl_resource_callback callback;
- void *arg;
- };
-
- static int llci_rm_enq_callback(void *arg, uint8_t slot_id, uint16_t session_number);
- static int llci_rm_reply_callback(void *arg, uint8_t slot_id, uint16_t session_number, uint32_t resource_id_count, uint32_t *resource_ids);
- static int llci_rm_changed_callback(void *arg, uint8_t slot_id, uint16_t session_number);
- static int llci_lookup_callback(void *arg, uint8_t slot_id, uint32_t requested_resource_id, en50221_sl_resource_callback *callback_out, void **arg_out, uint32_t *connected_resource_id);
- static int llci_session_callback(void *arg, int reason, uint8_t slot_id, uint16_t session_number, uint32_t resource_id);
-
- void poll();
- bool registerCam(int ca_fd, uint8_t slot);
- bool sub_init();
-
- void *RmResource;
- void *SessionLayer;
- void *TransportLayer;
-
- SlResource Resources[3];
-};
-
-class DvbCamCamHandlerHLCI : public DvbCamCamHandler
-{
-public:
- DvbCamCamHandlerHLCI();
- ~DvbCamCamHandlerHLCI();
-
-private:
- static int hlci_send_data(void *arg, uint16_t session_number, uint8_t *data, uint16_t data_length);
- static int hlci_send_datav(void *arg, uint16_t session_number, iovec *vector, int iov_count);
-
- void poll();
- bool registerCam(int ca_fd, uint8_t slot);
- bool sub_init();
-};
-
-// class DvbCam
-
-DvbCam::DvbCam(int adapter, int ca_device, int demux_device, int ci_type)
+DvbCam::DvbCam(int adapter, int ca_device, int demux_device, int ci_type, int maxService)
{
Adapter = adapter;
CaDevice = ca_device;
DemuxDevice = demux_device;
ciType = ci_type;
+ CamMaxService = maxService;
+ fprintf(stderr, "DvbCam: CamMaxService = %d\n", CamMaxService);
- isRunning = false;
+ stdcam = NULL;
+ menuDialog = NULL;
- CamThread = NULL;
- PmtThread = NULL;
-
- // at that time, we do reset in cam_thread
- /*if ( ciType!=CA_CI ) { //do not reset HLCI
- int ca_fd = dvbca_open( Adapter, CaDevice );
- if(ca_fd < 0) // should not happen
- fprintf(stderr, "CamThread: [error] opening ca device failed\n");
- else {
- if(dvbca_reset(ca_fd, 0))
- fprintf(stderr, "CamThread: [error] resetting cam slot failed\n");
- close(ca_fd);
- }
- }*/
+ sidList.setAutoDelete( true );
+
+ isRunning = true;
+ start();
}
DvbCam::~DvbCam()
{
- stop();
+ isRunning = false;
+ wait();
+ sidMutex.lock();
+ sidList.clear();
+ sidMutex.unlock();
}
int DvbCam::probe( int adapter, int ca_device )
@@ -251,676 +127,786 @@ int DvbCam::probe( int adapter, int ca_device )
return -1;
}
-void DvbCam::restart(int service_id)
+bool DvbCam::canPlay( ChannelDesc *chan )
{
- stop();
-
- isRunning = true;
- sid = service_id;
-
- CamThread = new DvbCamCamThread(Adapter, CaDevice, ciType);
- CamThread->start();
+ int i, n=0;
- PmtThread = new DvbCamPmtThread(CamThread, Adapter, DemuxDevice, service_id);
- PmtThread->start();
-}
-
-void DvbCam::stop()
-{
- if(PmtThread != NULL) {
- PmtThread->stop();
- }
- if(CamThread != NULL) {
- CamThread->stop();
- }
- if(PmtThread != NULL) {
- PmtThread->wait();
- delete PmtThread;
- PmtThread = NULL;
- }
- if(CamThread != NULL) {
- CamThread->wait();
- delete CamThread; // be careful about deletion: PmtThread uses CamThread internally
- CamThread = NULL;
+ QMutexLocker locker( &sidMutex );
+ for ( i=0; i<sidList.count(); ++i ) {
+ if ( sidList.at(i)->getState()<CamService::Remove )
+ n++;
+ if ( sidList.at(i)->getChannel().name==chan->name )
+ return true;
}
- isRunning = false;
-}
-
-// class DvbCamCamThread
-
-DvbCamCamThread::DvbCamCamThread(int adapter, int ca_device, int ci_type)
-{
- Adapter = adapter;
- CaDevice = ca_device;
- ciType = ci_type;
-
- CamHandler = NULL;
-}
-
-DvbCamCamThread::~DvbCamCamThread()
-{
- wait(); // should never be necessary
+ return ( n<CamMaxService );
}
-void DvbCamCamThread::start()
+void DvbCam::startService( ChannelDesc *chan )
{
- PmtSize = 0;
- Stopped = false;
- QThread::start();
-}
-
-void DvbCamCamThread::stop()
-{
- Stopped = true;
+ int i;
+ QMutexLocker locker( &sidMutex );
+ for ( i=0; i<sidList.count(); ++i ) {
+ if ( sidList.at(i)->getChannel().name==chan->name ) {
+ sidList.at(i)->restart();
+ return;
+ }
+ }
+ sidList.append( new CamService( Adapter, DemuxDevice, chan, CamMaxService ) );
}
-void DvbCamCamThread::wait()
+void DvbCam::stopService( ChannelDesc *chan )
{
- QThread::wait();
+ int i;
+ QMutexLocker locker( &sidMutex );
+ for ( i=0; i<sidList.count(); ++i ) {
+ if ( sidList.at(i)->getChannel().name==chan->name ) {
+ sidList.at(i)->setState( CamService::Remove );
+ return;
+ }
+ }
}
-bool DvbCamCamThread::processPmt(int demux_fd)
+void DvbCam::resendPmts()
{
- // read section
- char si_buf[4096];
- int size = read(demux_fd, si_buf, sizeof(si_buf));
- if(size <= 0) {
- return false;
- }
-
- // parse section
- section *parsed_section = section_codec(reinterpret_cast<unsigned char *> (si_buf), size);
- if(parsed_section == NULL) {
- return false;
- }
-
- // parse section_ext
- section_ext *parsed_section_ext = section_ext_decode(parsed_section, 1); // crc check on
- if(parsed_section_ext == NULL) {
- return false;
- }
-
- // parse pmt
- mpeg_pmt_section *parsed_pmt = mpeg_pmt_section_codec(parsed_section_ext);
- if(parsed_pmt == NULL) {
- return false;
- }
-
- // translate it into a cam pmt
- PmtSize = en50221_ca_format_pmt(parsed_pmt, reinterpret_cast<unsigned char *> (PmtBuffer), sizeof(PmtBuffer), 0, CA_LIST_MANAGEMENT_ONLY, CA_PMT_CMD_ID_OK_DESCRAMBLING);
- if(PmtSize <= 0) {
- return false;
+ int i;
+ QMutexLocker locker( &sidMutex );
+ for ( i=0; i<sidList.count(); ++i ) {
+ if ( sidList.at(i)->getState()==CamService::Added ) {
+ sidList.at(i)->setState( CamService::Ready );
+ }
}
-
- // the DvbCamCamThread will send it to the cam
- return true;
}
-void DvbCamCamThread::run()
+void DvbCam::run()
{
+ int i, reset_loop, query_loop, state_loop;
+ bool cam_ready = false;
+
fprintf(stderr, "CamThread: started\n");
int ca_fd = dvbca_open(Adapter, CaDevice);
- if(ca_fd < 0) {
- fprintf(stderr, "CamThread: [error] opening ca device failed\n");
+ if ( ca_fd<0 ) {
+ fprintf( stderr, "CamThread: [error] opening ca device failed\n" );
return;
}
- fprintf(stderr, "CamThread: just using the first cam slot\n");
+ //fprintf(stderr, "CamThread: just using the first cam slot\n");
- if ( ciType!=CA_CI ) { // do not reset HLCI
- if(dvbca_reset(ca_fd, 0)) {
- fprintf(stderr, "CamThread: [error] resetting cam slot failed\n");
- close(ca_fd);
- return;
+ reset_loop=0;
+ while ( isRunning && reset_loop++<6 && !cam_ready ) {
+ if ( ciType!=CA_CI ) { // do not reset HLCI
+ if ( dvbca_reset(ca_fd, 0) ) {
+ fprintf( stderr, "CamThread: [error] resetting cam slot failed\n" );
+ //close( ca_fd );
+ //ca_fd = -1;
+ //return;
+ usleep(1000000);
+ continue;
+ }
+ fprintf( stderr, "CamThread: reset cam slot\n" );
}
- }
- while(!Stopped) {
- bool cam_ready = false;
- switch(dvbca_get_cam_state(ca_fd, 0)) {
- case DVBCA_CAMSTATE_MISSING: {
- /*fprintf(stderr, "CamThread: [error] no cam detected\n");
- close(ca_fd);
- return; */ // FIXME: find a more reliable solution
- break;
- }
- case DVBCA_CAMSTATE_READY: {
- fprintf(stderr, "CamThread: cam 0 is ready\n");
- cam_ready = true;
- break;
- }
- case DVBCA_CAMSTATE_INITIALISING: {
- if ( ciType==CA_CI ) { // workaround needed for hlci
- fprintf(stderr, "CamThread: cam 0 is ready [hlci workaround]\n");
+ state_loop=0;
+ query_loop=0;
+ while ( isRunning && state_loop++<30 ) {
+ switch( dvbca_get_cam_state(ca_fd, 0) ) {
+ case DVBCA_CAMSTATE_MISSING: {
+ //fprintf(stderr, "CamThread: [error] no cam detected\n");
+ //close(ca_fd);
+ //return; // FIXME: find a more reliable solution
+ break;
+ }
+ case DVBCA_CAMSTATE_READY: {
+ fprintf( stderr, "CamThread: cam 0 is ready\n" );
cam_ready = true;
+ break;
+ }
+ case DVBCA_CAMSTATE_INITIALISING: {
+ fprintf( stderr, "CamThread: cam is initialising\n" );
+ if ( ciType==CA_CI ) { // workaround needed for hlci
+ fprintf(stderr, "CamThread: cam 0 is ready [hlci workaround]\n");
+ cam_ready = true;
+ }
+ break;
+ }
+ default: {
+ if ( ++query_loop>3 ) {
+ fprintf(stderr, "CamThread: [error] querying the cam state failed\n");
+ close(ca_fd);
+ ca_fd = -1;
+ return;
+ }
}
- break;
}
- default: {
- fprintf(stderr, "CamThread: [error] querying the cam state failed\n");
- close(ca_fd);
- return;
+ if(cam_ready) {
+ break;
}
+ usleep(100000); // 100 ms
}
- if(cam_ready) {
- break;
- }
- usleep(100000); // 100 ms
}
- if(!Stopped) {
+ if ( isRunning ) {
switch(dvbca_get_interface_type(ca_fd, 0)) {
case DVBCA_INTERFACE_LINK: {
fprintf(stderr, "CamThread: LLCI cam slot detected\n");
- CamHandler = new DvbCamCamHandlerLLCI();
break;
}
case DVBCA_INTERFACE_HLCI: {
fprintf(stderr, "CamThread: HLCI cam slot detected\n");
- CamHandler = new DvbCamCamHandlerHLCI();
break;
}
default: {
fprintf(stderr, "CamThread: [error] unknown cam slot type\n");
close(ca_fd);
+ ca_fd = -1;
return;
}
}
}
- if(!Stopped) {
- if(!CamHandler->init()) {
- fprintf(stderr, "CamThread: [error] cam slot initialization failed\n");
- delete CamHandler;
- CamHandler = NULL;
- close(ca_fd);
- return;
- }
- }
+ close(ca_fd);
+ ca_fd = -1;
- if(!Stopped) {
- if(!CamHandler->registerCam(ca_fd, 0)) {
- fprintf(stderr, "CamThread: [error] registering cam 0 failed\n");
- delete CamHandler;
- CamHandler = NULL;
- close(ca_fd);
+ if ( isRunning ) {
+ if ( !init() ) {
+ fprintf(stderr, "CamThread: [error] cam slot initialisation failed\n");
return;
}
}
+ fprintf(stderr, "CamThread: cam slot initialised\n");
- while(!Stopped) {
- CamHandler->poll();
- if(PmtSize > 0) {
- if(CamHandler->sendPmt(PmtBuffer, PmtSize)) {
- fprintf(stderr, "CamThread: pmt sent to cam\n");
- PmtSize = 0;
+ CamService *cs;
+ while ( isRunning ) {
+ if ( stdcam->stdcam->poll( stdcam->stdcam )!=EN50221_STDCAM_CAM_OK ) {
+ usleep( 100000 );
+ continue;
+ }
+ sidMutex.lock();
+ for ( i=0; i<sidList.count(); ++i ) {
+ cs = sidList.at(i);
+ if ( cs->getState()==CamService::Remove ) {
+ if ( sendPmt( cs->caPmt, cs->caPmtSize ) ) {
+ fprintf( stderr, "CamThread: %s removed from camlist\n", cs->getChannel().name.ascii() );
+ sidList.remove( cs );
+ --i;
+ }
+ else
+ fprintf( stderr, "CamThread: %s failed removing from camlist\n", cs->getChannel().name.ascii() );
+ stdcam->stdcam->poll( stdcam->stdcam );
+ usleep(100000);
+ }
+ else if ( cs->getState()==CamService::Destroy ) {
+ fprintf( stderr, "CamThread: %s service deleted\n", cs->getChannel().name.ascii() );
+ sidList.remove( cs );
+ --i;
}
}
+ for ( i=0; i<sidList.count(); ++i ) {
+ cs = sidList.at(i);
+ if ( cs->getState()==CamService::Ready ) {
+ if ( sendPmt( cs->caPmt, cs->caPmtSize ) ) {
+ cs->setState( CamService::Added );
+ fprintf( stderr, "CamThread: %s pmt sent to cam\n", cs->getChannel().name.ascii() );
+ }
+ else
+ fprintf( stderr, "CamThread: %s pmt failed sending to cam\n", cs->getChannel().name.ascii() );
+ stdcam->stdcam->poll( stdcam->stdcam );
+ usleep(100000);
+ }
+ }
+ sidMutex.unlock();
+ usleep( 10000 ); //sleep a bit
}
fprintf(stderr, "CamThread: stopping requested\n");
- delete CamHandler;
- CamHandler = NULL;
- close(ca_fd);
+ if ( stdcam ) {
+ if (stdcam->stdcam->destroy)
+ stdcam->stdcam->destroy(stdcam->stdcam, 1);
+ en50221_sl_destroy( SessionLayer );
+ en50221_tl_destroy( TransportLayer );
+ delete stdcam;
+ }
fprintf(stderr, "CamThread: stopped\n");
return;
}
-// class DvbCamPmtThread
-
-DvbCamPmtThread::DvbCamPmtThread(DvbCamCamThread *cam_thread, int adapter, int demux_device, int service_id)
+bool DvbCam::init()
{
- CamThread = cam_thread;
- Adapter = adapter;
- DemuxDevice = demux_device;
- ServiceId = service_id;
+ TransportLayer = en50221_tl_create(1, 16);
+ if ( TransportLayer==NULL ) {
+ fprintf(stderr, "Failed to create transport layer\n");
+ return false;
+ }
+ SessionLayer = en50221_sl_create(TransportLayer, 16);
+ if ( SessionLayer==NULL ) {
+ fprintf(stderr, "Failed to create session layer\n");
+ en50221_tl_destroy( TransportLayer );
+ return false;
+ }
+ en50221_stdcam *sc = en50221_stdcam_create( Adapter, 0, TransportLayer, SessionLayer );
+ if ( sc==NULL ) {
+ en50221_sl_destroy( SessionLayer );
+ en50221_tl_destroy( TransportLayer );
+ fprintf(stderr, "Failed to create stdcam\n");
+ return false;
+ }
+
+ stdcam = new StandardCam( sc, this );
+
+ // hook up the AI callbacks
+ if ( stdcam->stdcam->ai_resource ) {
+ en50221_app_ai_register_callback( stdcam->stdcam->ai_resource, aiCallback, stdcam );
+ }
+
+ // hook up the CA callbacks
+ if ( stdcam->stdcam->ca_resource ) {
+ en50221_app_ca_register_info_callback( stdcam->stdcam->ca_resource, infoCallback, stdcam );
+ }
+
+ // hook up the MMI callbacks
+ if ( stdcam->stdcam->mmi_resource ) {
+ en50221_app_mmi_register_close_callback( stdcam->stdcam->mmi_resource, mmi_close_callback, stdcam );
+ en50221_app_mmi_register_display_control_callback( stdcam->stdcam->mmi_resource, mmi_display_control_callback, stdcam );
+ en50221_app_mmi_register_enq_callback( stdcam->stdcam->mmi_resource, mmi_enq_callback, stdcam );
+ en50221_app_mmi_register_menu_callback( stdcam->stdcam->mmi_resource, mmi_menu_callback, stdcam );
+ en50221_app_mmi_register_list_callback( stdcam->stdcam->mmi_resource, mmi_menu_callback, stdcam );
+ } else {
+ fprintf(stderr, "CAM Menus are not supported by this interface hardware\n");
+ }
+
+ return true;
}
-DvbCamPmtThread::~DvbCamPmtThread()
+bool DvbCam::sendPmt( unsigned char *pmt_buffer, int size )
{
- wait(); // should never be necessary
+ if ( !stdcam )
+ return false;
+ if ( en50221_app_ca_pmt( stdcam->stdcam->ca_resource, stdcam->stdcam->ca_session_number, pmt_buffer, size) )
+ return false;
+
+ return true;
}
-void DvbCamPmtThread::start()
+int DvbCam::infoCallback(void *arg, uint8_t slot_id, uint16_t session_number, uint32_t ca_id_count, uint16_t *ca_ids)
{
- Stopped = false;
- QThread::start();
+ StandardCam *std = (StandardCam*)arg;
+ (void)slot_id;
+ (void)session_number;
+
+ fprintf(stderr, "CAM supports the following ca system ids:\n");
+ uint32_t i;
+ for ( i=0; i<ca_id_count; i++ ) {
+ fprintf( stderr, " 0x%04x\n", ca_ids[i]);
+ }
+
+ QApplication::postEvent( std->dvbcam, new QTimerEvent(TIMER_EVENT_CAM_READY ) );
+
+ return 0;
}
-void DvbCamPmtThread::stop()
+int DvbCam::aiCallback(void *arg, uint8_t slot_id, uint16_t session_number, uint8_t application_type, uint16_t application_manufacturer, uint16_t manufacturer_code, uint8_t menu_string_length, uint8_t *menu_string)
{
- Stopped = true;
+ StandardCam *std = (StandardCam*)arg;
+ (void)slot_id;
+ (void)session_number;
+
+ fprintf(stderr, "CAM Application type: %02x\n", application_type);
+ std->dvbcam->setAppType( QString("0x%1").arg(application_type, 0, 16 ) );
+ fprintf(stderr, "CAM Application manufacturer: %04x\n", application_manufacturer);
+ std->dvbcam->setAppManu( QString("0x%1").arg(application_manufacturer, 0, 16 ) );
+ fprintf(stderr, "CAM Manufacturer code: %04x\n", manufacturer_code);
+ std->dvbcam->setManuCode( QString("0x%1").arg(manufacturer_code, 0, 16 ) );
+ fprintf(stderr, "CAM Menu string: %.*s\n", menu_string_length, menu_string);
+ QString s = (const char*)menu_string;
+ s.truncate( menu_string_length );
+ std->dvbcam->setMenuString( s );
+ return 0;
}
-void DvbCamPmtThread::wait()
+int DvbCam::mmi_close_callback(void *arg, uint8_t slot_id, uint16_t session_number, uint8_t cmd_id, uint8_t delay)
{
- QThread::wait();
+ fprintf( stderr,"mmi_close_callback, delay=%d\n",delay);
+ StandardCam *std = (StandardCam*)arg;
+ (void) slot_id;
+ (void) session_number;
+ (void) cmd_id;
+ (void) delay;
+
+ // note: not entirely correct as its supposed to delay if asked
+ std->mmi_state = MMI_STATE_CLOSED;
+ QApplication::postEvent( std->dvbcam, new QTimerEvent(TIMER_EVENT_MMI_CLOSE ) );
+ return 0;
}
-int DvbCamPmtThread::createSectionFilter(uint16_t pid, uint8_t table_id)
+int DvbCam::mmi_display_control_callback(void *arg, uint8_t slot_id, uint16_t session_number, uint8_t cmd_id, uint8_t mmi_mode)
{
- // open the demuxer
- int demux_fd = dvbdemux_open_demux(Adapter, DemuxDevice, 0);
- if(demux_fd < 0) {
- return -1;
+ fprintf( stderr,"mmi_display_control_callback\n");
+ struct en50221_app_mmi_display_reply_details reply;
+ StandardCam *std = (StandardCam*)arg;
+ (void) slot_id;
+
+ // don't support any commands but set mode
+ if ( cmd_id!=MMI_DISPLAY_CONTROL_CMD_ID_SET_MMI_MODE ) {
+ en50221_app_mmi_display_reply( std->stdcam->mmi_resource, session_number, MMI_DISPLAY_REPLY_ID_UNKNOWN_CMD_ID, &reply );
+ return 0;
}
- // create a section filter
- uint8_t filter[18] = {table_id};
- uint8_t mask[18] = {0xff};
- if(dvbdemux_set_section_filter(demux_fd, pid, filter, mask, 1, 1)) { // crc check on
- close(demux_fd);
- return -1;
+ // we only support high level mode
+ if ( mmi_mode!=MMI_MODE_HIGH_LEVEL ) {
+ en50221_app_mmi_display_reply( std->stdcam->mmi_resource, session_number, MMI_DISPLAY_REPLY_ID_UNKNOWN_MMI_MODE, &reply );
+ return 0;
}
- return demux_fd;
+ // ack the high level open
+ reply.u.mode_ack.mmi_mode = mmi_mode;
+ en50221_app_mmi_display_reply( std->stdcam->mmi_resource, session_number, MMI_DISPLAY_REPLY_ID_MMI_MODE_ACK, &reply );
+ std->mmi_state = MMI_STATE_OPEN;
+ return 0;
}
-int DvbCamPmtThread::processPat(int demux_fd)
+int DvbCam::mmi_enq_callback(void *arg, uint8_t slot_id, uint16_t session_number, uint8_t blind_answer, uint8_t expected_answer_length,
+ uint8_t *text, uint32_t text_size)
{
- // read section
- char si_buf[4096];
- int size = read(demux_fd, si_buf, sizeof(si_buf));
- if(size < 0) {
- return -1;
- }
+ fprintf( stderr,"mmi_enq_callback\n");
+ StandardCam *std = (StandardCam*)arg;
+ (void) slot_id;
+ (void) session_number;
- // parse section
- section *parsed_section = section_codec(reinterpret_cast<unsigned char *> (si_buf), size);
- if(parsed_section == NULL) {
- return -1;
- }
+ QString s;
- // parse section_ext
- section_ext *parsed_section_ext = section_ext_decode(parsed_section, 1); // crc check on
- if(parsed_section_ext == NULL) {
- return -1;
- }
+ QMutexLocker locker( &std->mutex );
- // parse pat
- mpeg_pat_section *parsed_pat = mpeg_pat_section_codec(parsed_section_ext);
- if(parsed_pat == NULL) {
- return -1;
- }
+ std->menuList.clear();
+ fprintf(stderr, "%.*s: ", text_size, text);
+ s = (const char*)text;
+ s.truncate( text_size );
+ std->menuList.append( s );
+ fflush(stdout);
- // try and find the requested program
- mpeg_pat_program *cur_program;
- mpeg_pat_section_programs_for_each(parsed_pat, cur_program) {
- if(cur_program->program_number == ServiceId) {
- return cur_program->pid;
- }
- }
+ std->mmi_enq_blind = blind_answer;
+ std->mmi_enq_length = expected_answer_length;
+ std->mmi_state = MMI_STATE_ENQ;
+ std->menuType = MMI_MENU;
- fprintf(stderr, "PmtThread: [warning] the requested service id couldn't be found\n");
-
- return -1;
+ return 0;
}
-void DvbCamPmtThread::run()
+int DvbCam::mmi_menu_callback(void *arg, uint8_t slot_id, uint16_t session_number, struct en50221_app_mmi_text *title,
+ struct en50221_app_mmi_text *sub_title, struct en50221_app_mmi_text *bottom, uint32_t item_count,
+ struct en50221_app_mmi_text *items, uint32_t item_raw_length, uint8_t *items_raw)
{
- fprintf(stderr, "PmtThread: started\n");
+ fprintf( stderr,"mmi_menu_callback, session=%d\n",session_number);
+ StandardCam *std = (StandardCam*)arg;
+ (void) slot_id;
+ (void) session_number;
+ (void) item_raw_length;
+ (void) items_raw;
- int demux_fd = createSectionFilter(TRANSPORT_PAT_PID, stag_mpeg_program_association);
- if(demux_fd < 0) {
- fprintf(stderr, "PmtThread: [error] opening demux device failed\n");
- return;
- }
+ QString s;
- pollfd poll_desc;
- poll_desc.fd = demux_fd;
- poll_desc.events = POLLIN | POLLPRI;
- while(!Stopped) {
- int ret = poll(&poll_desc, 1, 100); // 100 ms
- if(ret < 0) {
- fprintf(stderr, "PmtThread: [error] polling demux device failed\n");
- close(demux_fd);
- return;
- }
- if((ret > 0) && (poll_desc.revents != 0) && ((poll_desc.revents & ~(POLLIN | POLLPRI)) == 0)) {
- int processed_pat = processPat(demux_fd);
- if(processed_pat >= 0) {
- close(demux_fd);
- demux_fd = createSectionFilter(processed_pat, stag_mpeg_program_map);
- if(demux_fd < 0) {
- fprintf(stderr, "PmtThread: [error] opening demux device failed\n");
- return;
- }
- poll_desc.fd = demux_fd;
- break;
- }
- }
- }
+ QMutexLocker locker( &std->mutex );
+ std->menuList.clear();
- while(!Stopped) {
- int ret = poll(&poll_desc, 1, 100); // 100 ms
- if(ret < 0) {
- fprintf(stderr, "PmtThread: [error] polling demux device failed\n");
- close(demux_fd);
- return;
- }
- if((ret > 0) && (poll_desc.revents != 0) && ((poll_desc.revents & ~(POLLIN | POLLPRI)) == 0)) {
- if(CamThread->processPmt(demux_fd)) {
- fprintf(stderr, "PmtThread: new pmt received\n");
- close(demux_fd);
- fprintf(stderr, "PmtThread: stopped\n");
- return;
- }
- }
+ fprintf(stderr, "------------------------------\n");
+
+ if (title->text_length) {
+ fprintf(stderr, "%.*s\n", title->text_length, title->text);
+ s = (const char*)title->text;
+ s.truncate( title->text_length );
+ std->menuList.append( s );
+ }
+ if (sub_title->text_length) {
+ fprintf(stderr, "%.*s\n", sub_title->text_length, sub_title->text);
+ s = (const char*)sub_title->text;
+ s.truncate( sub_title->text_length );
+ std->menuList.append( s );
}
- fprintf(stderr, "PmtThread: stopping requested\n");
+ uint32_t i;
+ fprintf(stderr, "0. Quit menu\n");
+ std->menuList.append( "0. Quit menu" );
+ for(i=0; i< item_count; i++) {
+ fprintf(stderr, "%i. %.*s\n", i+1, items[i].text_length, items[i].text);
+ s = (const char*)items[i].text;
+ s.truncate( items[i].text_length );
+ std->menuList.append( QString("%1. %2").arg(i+1).arg(s) );
- close(demux_fd);
+ }
- fprintf(stderr, "PmtThread: stopped\n");
- return;
-}
+ if (bottom->text_length) {
+ fprintf(stderr, "%.*s\n", bottom->text_length, bottom->text);
+ s = (const char*)bottom->text;
+ s.truncate( bottom->text_length );
+ std->menuList.append( s );
+ }
+ fflush(stdout);
-// class DvbCamCamHandler
+ std->mmi_state = MMI_STATE_MENU;
+ std->menuType = MMI_MENU;
-DvbCamCamHandler::DvbCamCamHandler()
-{
- AiResource = NULL;
- CaResource = NULL;
+ QApplication::postEvent( std->dvbcam, new QTimerEvent(TIMER_EVENT_MMI_OPEN ) );
- SessionNumber = -1;
+ return 0;
}
-DvbCamCamHandler::~DvbCamCamHandler()
+void DvbCam::timerEvent( QTimerEvent *e )
{
- if(CaResource != NULL) {
- en50221_app_ca_destroy(CaResource);
- CaResource = NULL;
- }
- if(AiResource != NULL) {
- en50221_app_ai_destroy(AiResource);
- AiResource = NULL;
+ switch ( e->timerId() ) {
+ case TIMER_EVENT_MMI_OPEN:
+ showMMI();
+ break;
+ case TIMER_EVENT_MMI_CLOSE:
+ closeMMI();
+ break;
+ case TIMER_EVENT_CAM_READY:
+ resendPmts();
+ break;
}
}
-bool DvbCamCamHandler::init()
+void DvbCam::showMMI()
{
- AiResource = en50221_app_ai_create(&SendFuncs);
- CaResource = en50221_app_ca_create(&SendFuncs);
-
- if(CaResource != NULL) {
- en50221_app_ca_register_info_callback(CaResource, infoCallback, this);
+ if ( !menuDialog && stdcam ) {
+ menuDialog = new MCamMenuDialog( stdcam );
+ connect( menuDialog, SIGNAL(enteredResponse(QString)), this, SLOT(mmiResponse(QString)) );
+ menuDialog->exec();
+ closeMMI();
}
-
- return sub_init();
}
-bool DvbCamCamHandler::sendPmt(char *pmt_buffer, int size)
+void DvbCam::closeMMI()
{
- if((CaResource != NULL) && (SessionNumber >= 0)) {
- if(!en50221_app_ca_pmt(CaResource, SessionNumber, reinterpret_cast<unsigned char *> (pmt_buffer), size)) {
- return true;
+ if ( menuDialog ) {
+ delete menuDialog;
+ menuDialog = 0;
+ if ( stdcam && stdcam->stdcam->mmi_resource ) {
+ en50221_app_mmi_close( stdcam->stdcam->mmi_resource, stdcam->stdcam->mmi_session_number, MMI_CLOSE_MMI_CMD_ID_IMMEDIATE, 0 );
+ stdcam->mmi_state = MMI_STATE_CLOSED;
}
}
-
- return false;
}
-int DvbCamCamHandler::infoCallback(void *arg, uint8_t /*slot_id*/, uint16_t session_number, uint32_t /*ca_id_count*/, uint16_t */*ca_ids*/)
+int DvbCam::showCamDialog()
{
- (static_cast<DvbCamCamHandler *> (arg))->SessionNumber = session_number;
- return 0;
-}
-// class DvbCamCamHandlerLLCI
-
-#define MAX_CARDS 1
-#define MAX_TC 16
-#define MAX_SESSIONS 16
+ CamDialog dlg;
+ dlg.maxServiceSpin->setValue( getCamMaxService() );
+ dlg.appTypeLab->setText( getAppType() );
+ dlg.appManuLab->setText( getAppManu() );
+ dlg.manuCodeLab->setText( getManuCode() );
+ dlg.menuStringLab->setText( getMenuString() );
+ connect( dlg.camMenuBtn, SIGNAL(clicked()), this, SLOT(enterMenu()) );
+ dlg.exec();
+ CamMaxService = dlg.maxServiceSpin->value();
+ return CamMaxService;
+}
-DvbCamCamHandlerLLCI::DvbCamCamHandlerLLCI()
+void DvbCam::enterMenu()
{
- RmResource = NULL;
- SessionLayer = NULL;
- TransportLayer = NULL;
+ if ( stdcam && stdcam->stdcam->ai_resource )
+ en50221_app_ai_entermenu( stdcam->stdcam->ai_resource, stdcam->stdcam->ai_session_number );
}
-DvbCamCamHandlerLLCI::~DvbCamCamHandlerLLCI()
+void DvbCam::mmiResponse( QString s )
{
- if(SessionLayer != NULL) {
- en50221_sl_destroy(SessionLayer);
- SessionLayer = NULL;
- }
- if(TransportLayer != NULL) {
- en50221_tl_destroy(TransportLayer);
- TransportLayer = NULL;
- }
- if(RmResource != NULL) {
- en50221_app_rm_destroy(RmResource);
- RmResource = NULL;
+ QString res = s.stripWhiteSpace();
+
+ switch( stdcam->mmi_state ) {
+ case MMI_STATE_CLOSED:
+ case MMI_STATE_OPEN: {
+ en50221_app_ai_entermenu(stdcam->stdcam->ai_resource, stdcam->stdcam->ai_session_number);
+ fprintf(stderr,"en50221_app_ai_entermenu 2\n");
+ break;
+ }
+ case MMI_STATE_ENQ: {
+ if ( res.isEmpty() ) {
+ en50221_app_mmi_answ( stdcam->stdcam->mmi_resource, stdcam->stdcam->mmi_session_number, MMI_ANSW_ID_CANCEL, NULL, 0);
+ }
+ else {
+ en50221_app_mmi_answ( stdcam->stdcam->mmi_resource, stdcam->stdcam->mmi_session_number, MMI_ANSW_ID_ANSWER, (uint8_t*)res.ascii(), res.length() );
+ }
+ stdcam->mmi_state = MMI_STATE_OPEN;
+ break;
+ }
+ case MMI_STATE_MENU: {
+ en50221_app_mmi_menu_answ( stdcam->stdcam->mmi_resource, stdcam->stdcam->mmi_session_number, res.toInt() );
+ stdcam->mmi_state = MMI_STATE_OPEN;
+ break;
+ }
}
}
-int DvbCamCamHandlerLLCI::llci_rm_enq_callback(void *arg, uint8_t /*slot_id*/, uint16_t session_number)
+
+
+
+MCamMenuDialog::MCamMenuDialog( StandardCam *sc )
{
- uint32_t resource_ids[] = {EN50221_APP_RM_RESOURCEID, EN50221_APP_AI_RESOURCEID, EN50221_APP_CA_RESOURCEID};
- en50221_app_rm_reply(arg, session_number, sizeof(resource_ids) / 4, resource_ids);
- return 0;
+ stdcam = sc;
+ connect( inputLine, SIGNAL(returnPressed()), this, SLOT(validateClicked()) );
+ connect( &readTimer, SIGNAL(timeout()), this, SLOT(setMenu()) );
+ readTimer.start( 500 );
}
-int DvbCamCamHandlerLLCI::llci_rm_reply_callback(void *arg, uint8_t /*slot_id*/, uint16_t session_number, uint32_t /*resource_id_count*/, uint32_t */*resource_ids*/)
+void MCamMenuDialog::setMenu()
{
- en50221_app_rm_changed(arg, session_number);
- return 0;
+ if ( !stdcam )
+ return;
+ QMutexLocker locker( &stdcam->mutex );
+ if ( stdcam->menuType==MMI_MENU )
+ menuText->setText( stdcam->menuList.join("\n") );
}
-int DvbCamCamHandlerLLCI::llci_rm_changed_callback(void *arg, uint8_t /*slot_id*/, uint16_t session_number)
+void MCamMenuDialog::validateClicked()
{
- en50221_app_rm_enq(arg, session_number);
- return 0;
+ emit enteredResponse( inputLine->text() );
+ inputLine->clear();
}
-int DvbCamCamHandlerLLCI::llci_lookup_callback(void *arg, uint8_t /*slot_id*/, uint32_t requested_resource_id, en50221_sl_resource_callback *callback_out, void **arg_out, uint32_t *connected_resource_id)
+
+
+
+
+// class CamService
+CamService::CamService( int adapter, int demux_device, ChannelDesc *chan, int maxService )
{
- // decode the resource id
- en50221_app_public_resource_id resid;
- if(!en50221_app_decode_public_resource_id(&resid, requested_resource_id)) {
- return -1;
- }
+ Adapter = adapter;
+ DemuxDevice = demux_device;
+ CamMaxService = maxService;
+ channel = *chan;
+ parsedPmt = NULL;
+ state = NotReady;
+ isRunning = true;
+ start();
+}
- // try and find an instance of the resource
- const SlResource *Resources = (static_cast<DvbCamCamHandlerLLCI *> (arg))->Resources;
- int i;
- for(i = 0; i < 3; ++i) {
- if((resid.resource_class == Resources[i].resid.resource_class) && (resid.resource_type == Resources[i].resid.resource_type)) {
- *callback_out = Resources[i].callback;
- *arg_out = Resources[i].arg;
- *connected_resource_id = Resources[i].binary_resource_id;
- return 0;
- }
- }
- return -1;
+CamService::~CamService()
+{
+ stop();
}
-int DvbCamCamHandlerLLCI::llci_session_callback(void *arg, int reason, uint8_t /*slot_id*/, uint16_t session_number, uint32_t resource_id)
+void CamService::restart()
{
- if(reason == S_SCALLBACK_REASON_CAMCONNECTED) {
- if(resource_id == EN50221_APP_RM_RESOURCEID) {
- void *RmResource = (static_cast<DvbCamCamHandlerLLCI *> (arg))->Resources[0].arg;
- en50221_app_rm_enq(RmResource, session_number);
- }
- else if(resource_id == EN50221_APP_AI_RESOURCEID) {
- void *AiResource = (static_cast<DvbCamCamHandlerLLCI *> (arg))->Resources[1].arg;
- en50221_app_ai_enquiry(AiResource, session_number);
- }
- else if(resource_id == EN50221_APP_CA_RESOURCEID) {
- void *CaResource = (static_cast<DvbCamCamHandlerLLCI *> (arg))->Resources[2].arg;
- en50221_app_ca_info_enq(CaResource, session_number);
- }
- }
- return 0;
+ setState( NotReady );
}
-void DvbCamCamHandlerLLCI::poll()
+void CamService::stop()
{
- if(en50221_tl_poll(TransportLayer)) {
- fprintf(stderr, "CamThread: [warning] polling the stack failed\n");
- usleep(10000); // wait 10 ms to not block
- }
+ isRunning = false;
+ wait();
}
-bool DvbCamCamHandlerLLCI::registerCam(int ca_fd, uint8_t slot)
+int CamService::createSectionFilter(uint16_t pid, uint8_t table_id)
{
- // register the slot
- int slot_id = en50221_tl_register_slot(TransportLayer, ca_fd, slot, 1000, 100);
- if(slot_id < 0) {
- return false;
+ // open the demuxer
+ int demux_fd = dvbdemux_open_demux(Adapter, DemuxDevice, 0);
+ if(demux_fd < 0) {
+ return -1;
}
- // create a new connection on the slot
- if(en50221_tl_new_tc(TransportLayer, slot_id) < 0) {
- return false;
+ // create a section filter
+ uint8_t filter[18] = {table_id};
+ uint8_t mask[18] = {0xff};
+ if(dvbdemux_set_section_filter(demux_fd, pid, filter, mask, 1, 1)) { // crc check on
+ close(demux_fd);
+ return -1;
}
- return true;
+ return demux_fd;
}
-bool DvbCamCamHandlerLLCI::sub_init()
+int CamService::processPat(int demux_fd)
{
- // create transport layer
- TransportLayer = en50221_tl_create(MAX_CARDS, MAX_TC);
- if(TransportLayer == NULL) {
- return false;
- }
+ // read section
+ unsigned char si_buf[4096];
+ int size = read( demux_fd, si_buf, sizeof(si_buf) );
+ if ( size<0 )
+ return -1;
- // create session layer
- SessionLayer = en50221_sl_create(TransportLayer, MAX_SESSIONS);
- if(SessionLayer == NULL) {
- en50221_tl_destroy(TransportLayer);
- TransportLayer = NULL;
- return false;
- }
+ // parse section
+ section *parsed_section = section_codec( si_buf, size );
+ if ( parsed_section==NULL )
+ return -1;
- // create sendfuncs
- SendFuncs.arg = SessionLayer;
- SendFuncs.send_data = en50221_sl_send_data;
- SendFuncs.send_datav = en50221_sl_send_datav;
-
- // create the resource manager resource
- RmResource = en50221_app_rm_create(&SendFuncs);
- en50221_app_decode_public_resource_id(&Resources[0].resid, EN50221_APP_RM_RESOURCEID);
- Resources[0].binary_resource_id = EN50221_APP_RM_RESOURCEID;
- Resources[0].callback = en50221_app_rm_message;
- Resources[0].arg = RmResource;
- en50221_app_rm_register_enq_callback(RmResource, llci_rm_enq_callback, RmResource);
- en50221_app_rm_register_reply_callback(RmResource, llci_rm_reply_callback, RmResource);
- en50221_app_rm_register_changed_callback(RmResource, llci_rm_changed_callback, RmResource);
-
- // integrate the application information resource
- en50221_app_decode_public_resource_id(&Resources[1].resid, EN50221_APP_AI_RESOURCEID);
- Resources[1].binary_resource_id = EN50221_APP_AI_RESOURCEID;
- Resources[1].callback = en50221_app_ai_message;
- Resources[1].arg = AiResource;
-
- // integrate the ca resource
- en50221_app_decode_public_resource_id(&Resources[2].resid, EN50221_APP_CA_RESOURCEID);
- Resources[2].binary_resource_id = EN50221_APP_CA_RESOURCEID;
- Resources[2].callback = en50221_app_ca_message;
- Resources[2].arg = CaResource;
-
- // register session layer callbacks
- en50221_sl_register_lookup_callback(SessionLayer, llci_lookup_callback, this);
- en50221_sl_register_session_callback(SessionLayer, llci_session_callback, this);
+ // parse section_ext
+ section_ext *parsed_section_ext = section_ext_decode( parsed_section, 1 ); // crc check on
+ if ( parsed_section_ext==NULL )
+ return -1;
- return true;
-}
+ // parse pat
+ mpeg_pat_section *parsed_pat = mpeg_pat_section_codec( parsed_section_ext );
+ if ( parsed_pat==NULL )
+ return -1;
-// class DvbCamCamHandlerHLCI
+ // try and find the requested program
+ mpeg_pat_program *cur_program;
+ mpeg_pat_section_programs_for_each( parsed_pat, cur_program ) {
+ if ( cur_program->program_number==channel.sid )
+ return cur_program->pid;
+ }
-DvbCamCamHandlerHLCI::DvbCamCamHandlerHLCI()
-{
-}
+ fprintf( stderr, "CamService (%s): [warning] channel couldn't be found in PAT\n", channel.name.ascii() );
-DvbCamCamHandlerHLCI::~DvbCamCamHandlerHLCI()
-{
+ return -1;
}
-int DvbCamCamHandlerHLCI::hlci_send_data(void *arg, uint16_t /*session_number*/, uint8_t *data, uint16_t data_length)
+int CamService::processPmt( int demux_fd )
{
- return dvbca_hlci_write(static_cast<int> (reinterpret_cast<intptr_t> (arg)), data, data_length);
-}
+ // read section
+ memset( pmtBuffer, 0, sizeof(pmtBuffer) );
+ int size = read( demux_fd, pmtBuffer, sizeof(pmtBuffer) );
+ if ( size<=0 )
+ return -1;
-int DvbCamCamHandlerHLCI::hlci_send_datav(void *arg, uint16_t /*session_number*/, iovec *vector, int iov_count)
-{
- // calculate the total length of the data to send
- uint32_t data_size = 0;
- for(int i = 0; i < iov_count; ++i) {
- data_size += vector[i].iov_len;
- }
+ // parse section
+ section *parsed_section = section_codec( pmtBuffer, size );
+ if ( parsed_section==NULL )
+ return -1;
- // allocate memory for it
- uint8_t *buf = new uint8_t[data_size];
+ // parse section_ext
+ section_ext *parsed_section_ext = section_ext_decode( parsed_section, 1 ); // crc check on
+ if ( parsed_section_ext==NULL )
+ return -1;
- // merge the iovecs
- uint8_t *pos = buf;
- for(int i = 0; i < iov_count; ++i) {
- memcpy(pos, vector[i].iov_base, vector[i].iov_len);
- pos += vector[i].iov_len;
- }
+ // parse pmt
+ struct mpeg_pmt_section *pmt = mpeg_pmt_section_codec( parsed_section_ext );
+ if ( pmt==NULL )
+ return -1;
- // send it
- int status = dvbca_hlci_write(static_cast<int> (reinterpret_cast<intptr_t> (arg)), buf, data_size);
- delete buf;
- return status;
+ parsedPmt = pmt;
+ return parsedPmt->head.version_number;
}
-void DvbCamCamHandlerHLCI::poll()
+void CamService::setState( PmtState st )
{
- // we do nothing here for the moment
- usleep(100000); // 100 ms
+ QMutexLocker locker( &mutex );
+ switch ( st ) {
+ case Ready: {
+ int listmgnt;
+ if ( CamMaxService==1 )
+ listmgnt = CA_LIST_MANAGEMENT_ONLY;
+ else
+ listmgnt = CA_LIST_MANAGEMENT_ADD;
+ if ( state>Ready )
+ listmgnt = CA_LIST_MANAGEMENT_UPDATE;
+ if ( setCaPmt( listmgnt, CA_PMT_CMD_ID_OK_DESCRAMBLING ) )
+ state = st;
+ break;
+ }
+ case Remove: {
+ if ( state!=Added )
+ state = Destroy;
+ else if ( setCaPmt( CA_LIST_MANAGEMENT_UPDATE, CA_PMT_CMD_ID_NOT_SELECTED ) )
+ state = st;
+ break;
+ }
+ default: {
+ state = st;
+ }
+ }
}
-bool DvbCamCamHandlerHLCI::registerCam(int ca_fd, uint8_t /*slot*/)
+int CamService::getState()
{
- SendFuncs.arg = reinterpret_cast<void *> (ca_fd);
-
- // get application information
- if(en50221_app_ai_enquiry(AiResource, 0)) {
- fprintf(stderr, "CamThread: [DEBUG #1]\n");
- return false;
- }
-
- uint8_t buf[256];
- int size = dvbca_hlci_read(ca_fd, TAG_APP_INFO, buf, sizeof(buf));
- if(size <= 0) {
- fprintf(stderr, "CamThread: [DEBUG #2]\n");
- return false;
- }
+ QMutexLocker locker( &mutex );
+ return state;
+}
- if(en50221_app_ai_message(AiResource, 0, 0, EN50221_APP_AI_RESOURCEID, buf, size)) {
- fprintf(stderr, "CamThread: [DEBUG #3]\n");
+bool CamService::setCaPmt( int list_management, int cmd_id )
+{
+ if ( !parsedPmt )
return false;
- }
- // FIXME: try to change this soon
- buf[0] = TAG_CA_INFO >> 16;
- buf[1] = TAG_CA_INFO >> 8;
- buf[2] = TAG_CA_INFO;
- buf[3] = 0;
- if(en50221_app_ca_message(CaResource, 0, 0, EN50221_APP_CA_RESOURCEID, buf, 4)) {
- fprintf(stderr, "CamThread: [DEBUG #4]\n");
+ caPmtSize = en50221_ca_format_pmt( parsedPmt, caPmt, sizeof(caPmt), 0, list_management, cmd_id );
+ if ( caPmtSize<=0 )
return false;
- }
-
- fprintf(stderr, "CamThread: [DEBUG #5]\n");
return true;
}
-bool DvbCamCamHandlerHLCI::sub_init()
+void CamService::run()
{
- // create sendfuncs
- SendFuncs.arg = NULL;
- SendFuncs.send_data = hlci_send_data;
- SendFuncs.send_datav = hlci_send_datav;
+ int i, pmtVersion=-1;
+ int demux_fd=-1;
- return true;
+ fprintf( stderr, "CamService (%s): started\n", channel.name.ascii() );
+
+ while ( isRunning ) {
+loopLabel:
+ demux_fd = createSectionFilter( TRANSPORT_PAT_PID, stag_mpeg_program_association );
+ if ( demux_fd<0 ) {
+ fprintf( stderr, "CamService (%s): [error] opening demux device failed\n", channel.name.ascii() );
+ demux_fd = -1;
+ usleep( 100000 );
+ goto loopLabel;
+ }
+
+ pollfd poll_desc;
+ poll_desc.fd = demux_fd;
+ poll_desc.events = POLLIN | POLLPRI;
+ while ( isRunning ) {
+ int ret = poll( &poll_desc, 1, 1000 );
+ if ( ret<0 ) {
+ fprintf( stderr, "CamService (%s): [error] polling demux device failed\n", channel.name.ascii() );
+ close( demux_fd );
+ demux_fd = -1;
+ usleep( 100000 );
+ goto loopLabel;
+ }
+ if ( ret>0 ) {
+ int processed_pat = processPat( demux_fd );
+ if ( processed_pat>=0 ) {
+ close( demux_fd );
+ demux_fd = -1;
+ demux_fd = createSectionFilter( processed_pat, stag_mpeg_program_map );
+ if ( demux_fd<0 ) {
+ fprintf( stderr, "CamService (%s): [error] opening demux device failed\n", channel.name.ascii() );
+ demux_fd = -1;
+ usleep( 100000 );
+ goto loopLabel;
+ }
+ poll_desc.fd = demux_fd;
+ break;
+ }
+ else
+ usleep( 10000 );
+ }
+ else
+ usleep( 10000 );
+ }
+
+ while ( isRunning ) {
+ int ret = poll( &poll_desc, 1, 1000 );
+ if ( ret<0 ) {
+ fprintf( stderr, "CamService (%s): [error] polling demux device failed\n", channel.name.ascii() );
+ close( demux_fd );
+ demux_fd = -1;
+ usleep( 100000 );
+ goto loopLabel;
+ }
+ if ( ret>0 ) {
+ //fprintf( stderr, "CamService (%s): parsing pmt\n", channel.name.ascii() );
+ i = processPmt( demux_fd );
+ if ( i==-1 )
+ usleep( 10000 );
+ else {
+ if ( i!=pmtVersion || getState()<Ready ) {
+ fprintf( stderr, "CamService (%s): new pmt received\n", channel.name.ascii() );
+ setState( Ready );
+ pmtVersion = i;
+ }
+ i = 200;
+ while ( i-- && isRunning )
+ usleep( 10000 );
+ }
+ }
+ else
+ usleep( 10000 );
+ }
+ }
+
+ if ( demux_fd != -1 )
+ close( demux_fd );
+ fprintf( stderr, "CamService (%s): stopped\n", channel.name.ascii() );
}