#include <fcntl.h>
+#include <lib/base/init.h>
+#include <lib/base/init_num.h>
+
#include <lib/base/eerror.h>
#include <lib/dvb_ci/dvbci.h>
#include <lib/dvb_ci/dvbci_session.h>
int num_ci = 0;
eDebug("scanning for common interfaces..");
+
while (1)
{
struct stat s;
eDebug("done, found %d common interfaces");
}
-int eDVBCISlot::write(const unsigned char *data, size_t len)
+eDVBCIInterfaces::~eDVBCIInterfaces()
+{
+}
+
+int eDVBCISlot::send(const unsigned char *data, size_t len)
{
- return ::write(fd, data, len);
+ int res;
+ int i;
+
+ printf("< ");
+ for(i=0;i<len;i++)
+ printf("%02x ",data[i]);
+ printf("\n");
+
+ res = ::write(fd, data, len);
+
+ printf("write() %d\n",res);
+
+ notifier->setRequested(eSocketNotifier::Read|eSocketNotifier::Hungup|eSocketNotifier::Write);
+
+ return res;
}
-void eDVBCISlot::data(int)
+void eDVBCISlot::data(int what)
{
- eDebug("ci talks to us");
+ if(what == eSocketNotifier::Hungup) {
+ if(state != stateRemoved) {
+ state = stateRemoved;
+ printf("ci removed\n");
+ notifier->setRequested(eSocketNotifier::Read);
+ }
+ return;
+ }
+
__u8 data[4096];
int r;
r = ::read(fd, data, 4096);
- if(r < 0)
- eWarning("ERROR reading from CI - %m\n");
+ //if(r < 0)
+ // eWarning("ERROR reading from CI - %m\n");
if(state != stateInserted) {
state = stateInserted;
eDebug("ci inserted");
/* enable HUP to detect removal or errors */
- notifier_event->start();
+ //notifier_event->start();
+ notifier->setRequested(eSocketNotifier::Read|eSocketNotifier::Hungup|eSocketNotifier::Write);
}
- if(r > 0)
+ if(r > 0) {
+ int i;
+ printf("> ");
+ for(i=0;i<r;i++)
+ printf("%02x ",data[i]);
+ printf("\n");
+ //eDebug("ci talks to us");
eDVBCISession::receiveData(this, data, r);
-}
-
-void eDVBCISlot::event(int)
-{
- state = stateRemoved;
+ notifier->setRequested(eSocketNotifier::Read|eSocketNotifier::Hungup|eSocketNotifier::Write);
+ return;
+ }
- eDebug("CI removed");
-
- /* kill the TransportConnection */
-
- /* we know about and disable HUP */
- notifier_event->stop();
+ if(what == eSocketNotifier::Write) {
+ printf("pollall\n");
+ if(eDVBCISession::pollAll() == 0) {
+ printf("disable pollout\n");
+ notifier->setRequested(eSocketNotifier::Read | eSocketNotifier::Hungup);
+ }
+ return;
+ }
}
+DEFINE_REF(eDVBCISlot);
+
eDVBCISlot::eDVBCISlot(eMainloop *context, int nr)
{
char filename[128];
if (fd >= 0)
{
- //read callback
- notifier_data = new eSocketNotifier(context, fd, eSocketNotifier::Read);
- CONNECT(notifier_data->activated, eDVBCISlot::data);
- //remove callback
- notifier_event = new eSocketNotifier(context, fd, eSocketNotifier::Hungup);
- CONNECT(notifier_event->activated, eDVBCISlot::event);
+ notifier = new eSocketNotifier(context, fd, eSocketNotifier::Read | eSocketNotifier::Hungup);
+ CONNECT(notifier->activated, eDVBCISlot::data);
} else
{
perror(filename);
}
}
+eDVBCISlot::~eDVBCISlot()
+{
+}
+
+eAutoInitP0<eDVBCIInterfaces> init_eDVBCIInterfaces(eAutoInitNumbers::dvb, "CI Slots");
private:
int fd;
void data(int);
- eSocketNotifier *notifier_data;
- void event(int);
- eSocketNotifier *notifier_event;
+ eSocketNotifier *notifier;
int state;
enum {stateRemoved, stateInserted};
public:
eDVBCISlot(eMainloop *context, int nr);
- virtual ~eDVBCISlot();
+ ~eDVBCISlot();
- int eDVBCISlot::write(const unsigned char *data, size_t len);
+ int send(const unsigned char *data, size_t len);
eDVBCIApplicationManagerSession *application_manager;
eDVBCICAManagerSession *ca_manager;
class eDVBCIInterfaces
{
+DECLARE_REF(eDVBCIInterfaces);
private:
eSmartPtrList<eDVBCISlot> m_slots;
public:
eDVBCIInterfaces();
- virtual ~eDVBCIInterfaces();
+ ~eDVBCIInterfaces();
};
#endif
}
return 0;
}
+
+int eDVBCIApplicationManagerSession::doAction()
+{
+ switch (state)
+ {
+ case stateStarted:
+ {
+ const unsigned char tag[3]={0x9F, 0x80, 0x20}; // application manager info e sendAPDU(tag);
+ sendAPDU(tag);
+ state=stateFinal;
+ return 1;
+ }
+ case stateFinal:
+ printf("in final state.\n");
+ wantmenu = 0;
+ if (wantmenu)
+ {
+ printf("wantmenu: sending Tenter_menu\n");
+ const unsigned char tag[3]={0x9F, 0x80, 0x22}; // Tenter_menu
+ sendAPDU(tag);
+ wantmenu=0;
+ return 0;
+ } else
+ return 0;
+ default:
+ return 0;
+ }
+}
else
for (int i=0; i<len; i++)
printf("%02x ", ((const unsigned char*)data)[i]);
+
if (state == stateFirstProfileEnquiry)
{
// profile change
printf("unknown APDU tag 9F 80 %02x\n", tag[2]);
}
}
+
return 0;
}
{
const unsigned char tag[3]={0x9F, 0x80, 0x10}; // profile enquiry
sendAPDU(tag);
- state=stateFirstProfileEnquiry;
+ state = stateFirstProfileEnquiry;
return 0;
}
case stateFirstProfileEnquiry:
state=stateProfileChange;
return 0;
}
+ case stateProfileChange:
+ {
+ printf("bla kaputt\n");
+ break;
+ }
case stateProfileEnquiry:
{
const unsigned char tag[3]={0x9F, 0x80, 0x11};
#include <lib/dvb_ci/dvbci_datetimemgr.h>
#include <lib/dvb_ci/dvbci_mmi.h>
+eDVBCISession *eDVBCISession::sessions[SLMS];
+
int eDVBCISession::buildLengthField(unsigned char *pkt, int len)
{
if (len < 127)
memcpy(ptr, apdu, alen);
ptr+=alen;
- slot->write(pkt, ptr - pkt);
+ slot->send(pkt, ptr - pkt);
}
void eDVBCISession::sendOpenSessionResponse(eDVBCISlot *slot, unsigned char session_status, const unsigned char *resource_identifier, unsigned short session_nb)
eDVBCISession *session;
unsigned long tag;
unsigned short session_nb;
+
for (session_nb=1; session_nb < SLMS; ++session_nb)
if (!sessions[session_nb-1])
break;
case 0x00010041:
session=new eDVBCIResourceManagerSession;
printf("RESOURCE MANAGER\n");
+ printf("session: %p\n",session);
break;
case 0x00020041:
session=slot->application_manager = new eDVBCIApplicationManagerSession;
}
printf("new session_nb: %d\n", session_nb);
session->session_nb = session_nb;
+
if (session)
{
- printf("session ok, status %02x\n", session->status);
- status = session->getStatus();
- if (status)
- {
- delete session;
- session = 0;
- }
sessions[session_nb - 1] = session;
session->slot = slot;
+ status = 0;
}
session->state = stateInCreation;
+
return session;
}
+void eDVBCISession::handleClose()
+{
+ unsigned char data[1]={0x00};
+ sendSPDU(0x96, data, 1, 0, 0);
+}
+
+int eDVBCISession::pollAll()
+{
+ for (int session_nb=1; session_nb < SLMS; ++session_nb)
+ if (sessions[session_nb-1])
+ {
+ int r;
+
+ if (sessions[session_nb-1]->state == stateInDeletion)
+ {
+ sessions[session_nb-1]->handleClose();
+ delete sessions[session_nb-1];
+ sessions[session_nb-1]=0;
+ r=1;
+ } else
+ r=sessions[session_nb-1]->poll();
+
+ if (r)
+ return 1;
+ }
+ return 0;
+}
+
void eDVBCISession::receiveData(eDVBCISlot *slot, const unsigned char *ptr, size_t len)
{
const unsigned char *pkt = (const unsigned char*)ptr;
unsigned char tag = *pkt++;
int llen, hlen;
+
+ printf("slot: %p\n",slot);
+
+ int i;
+
+ for(i=0;i<len;i++)
+ printf("%02x ",ptr[i]);
+ printf("\n");
llen = parseLengthField(pkt, hlen);
pkt += llen;
unsigned char status;
session = createSession(slot, pkt, status);
sendOpenSessionResponse(slot, status, pkt, session?session->session_nb:0);
-
+
if (session)
{
session->state=stateStarted;
virtual int receivedAPDU(const unsigned char *tag, const void *data, int len) = 0;
void eDVBCISession::sendAPDU(const unsigned char *tag, const void *data=0,int len=0);
void eDVBCISession::sendSPDU(unsigned char tag, const void *data, int len,const void *apdu=0, int alen=0);
+ virtual doAction()=0;
+ void handleClose();
public:
+ int poll() { if (action) { action=doAction(); return 1; } return 0; }
enum { stateInCreation, stateBusy, stateInDeletion, stateStarted, statePrivate};
static int parseLengthField(const unsigned char *pkt, int &len);
int getState() { return state; }
int getStatus() { return status; }
+
+ static int pollAll();
};
#endif