summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CONTRIBUTORS1
-rw-r--r--HISTORY6
-rw-r--r--ci.c311
-rw-r--r--ci.h11
-rw-r--r--config.h4
-rw-r--r--dvbdevice.c39
-rw-r--r--menu.c22
-rw-r--r--vdr.c4
8 files changed, 224 insertions, 174 deletions
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index ae550b81..a6663d9a 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -446,6 +446,7 @@ Oliver Endriss <o.endriss@gmx.de>
Reinhard Walter Buchner <rw.buchner@freenet.de>
for adding some satellites to 'sources.conf'
for his help in testing tuning with "Motor-DiSEqC"
+ for his help in debugging CAM support
Lauri Tischler <lauri.tischler@efore.fi>
for helping to test and debug the new channel source and DiSEqC handling
diff --git a/HISTORY b/HISTORY
index 8e770ee7..161f054e 100644
--- a/HISTORY
+++ b/HISTORY
@@ -1947,3 +1947,9 @@ Video Disk Recorder Revision History
- Fixed a new/delete malloc/free mismatch in ringbuffer.c (thanks to Stefan
Huelswitt for reporting this one).
- Improved CAM handling.
+
+2003-02-09: Version 1.1.24
+
+- Improved CAM handling (thanks to Reinhard Walter Buchner for a great deal of help
+ in debugging this). It is now possible to insert the CAM in any of the two slots,
+ to insert and remove it while VDR is running and even to have two CAMs inserted.
diff --git a/ci.c b/ci.c
index 97de9b01..f99be7d4 100644
--- a/ci.c
+++ b/ci.c
@@ -4,15 +4,11 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: ci.c 1.3 2003/02/02 15:49:52 kls Exp $
+ * $Id: ci.c 1.4 2003/02/09 11:54:22 kls Exp $
*/
/* XXX TODO
-- handle slots separately
-- use return values
- update CA descriptors in case they change
-- dynamically react on CAM insert/remove
-- implement CAM reset (per slot)
XXX*/
#include "ci.h"
@@ -215,7 +211,7 @@ int cTPDU::Write(int fd)
int cTPDU::Read(int fd)
{
- size = read(fd, data, sizeof(data));
+ size = safe_read(fd, data, sizeof(data));
if (size < 0) {
esyslog("ERROR: %m");
size = 0;
@@ -229,15 +225,15 @@ void cTPDU::Dump(bool Outgoing)
{
if (DumpTPDUDataTransfer) {
#define MAX_DUMP 256
- printf("%s ", Outgoing ? "-->" : "<--");
+ fprintf(stderr, "%s ", Outgoing ? "-->" : "<--");
for (int i = 0; i < size && i < MAX_DUMP; i++)
- printf("%02X ", data[i]);
- printf("%s\n", size >= MAX_DUMP ? "..." : "");
+ fprintf(stderr, "%02X ", data[i]);
+ fprintf(stderr, "%s\n", size >= MAX_DUMP ? "..." : "");
if (!Outgoing) {
- printf(" ");
+ fprintf(stderr, " ");
for (int i = 0; i < size && i < MAX_DUMP; i++)
- printf("%2c ", isprint(data[i]) ? data[i] : '.');
- printf("%s\n", size >= MAX_DUMP ? "..." : "");
+ fprintf(stderr, "%2c ", isprint(data[i]) ? data[i] : '.');
+ fprintf(stderr, "%s\n", size >= MAX_DUMP ? "..." : "");
}
}
}
@@ -288,6 +284,7 @@ private:
public:
cCiTransportConnection(void);
~cCiTransportConnection();
+ int Slot(void) const { return slot; }
int SendData(int Length, const uint8_t *Data);
int RecvData(void);
const uint8_t *Data(int &Length);
@@ -324,15 +321,15 @@ int cCiTransportConnection::SendTPDU(uint8_t Tag, int Length, const uint8_t *Dat
return TPDU.Write(fd);
}
+#define CAM_READ_TIMEOUT 3500 // ms
+
int cCiTransportConnection::RecvTPDU(void)
{
- //XXX poll, timeout???
struct pollfd pfd[1];
pfd[0].fd = fd;
pfd[0].events = POLLIN;
lastResponse = ERROR;
- if (poll(pfd, 1, 3500/*XXX*/) && (pfd[0].revents & POLLIN))//XXX
- if (tpdu->Read(fd) == OK && tpdu->Tcid() == tcid) {
+ if (poll(pfd, 1, CAM_READ_TIMEOUT) && (pfd[0].revents & POLLIN) && tpdu->Read(fd) == OK && tpdu->Tcid() == tcid) {
switch (state) {
case stIDLE: break;
case stCREATION: if (tpdu->Tag() == T_CTC_REPLY) {
@@ -363,6 +360,10 @@ int cCiTransportConnection::RecvTPDU(void)
break;
}
}
+ else {
+ esyslog("ERROR: CAM: Read failed: slot %d, tcid %d\n", slot, tcid);
+ Init(-1, slot, tcid);
+ }
return lastResponse;
}
@@ -385,11 +386,8 @@ int cCiTransportConnection::SendData(int Length, const uint8_t *Data)
int cCiTransportConnection::RecvData(void)
{
- if (SendTPDU(T_RCV) == OK) {
- if (RecvTPDU() == OK) {
- //XXX
- }
- }
+ if (SendTPDU(T_RCV) == OK)
+ return RecvTPDU();
return ERROR;
}
@@ -403,7 +401,18 @@ int cCiTransportConnection::CreateConnection(void)
if (state == stIDLE) {
if (SendTPDU(T_CREATE_TC) == OK) {
state = stCREATION;
- return OK;
+ if (RecvTPDU() == T_CTC_REPLY)
+ return OK;
+ // the following is a workaround for CAMs that don't quite follow the specs...
+ else {
+ dbgprotocol("*** no reaction on T_CREATE_TC - retrying\n");
+ if (RecvTPDU() == T_CTC_REPLY) {
+ dbgprotocol("*** received T_CTC_REPLY\n");
+ RecvTPDU();
+ dbgprotocol("*** done dummy RecvTPDU()\n");
+ }
+ return OK;
+ }
}
}
return ERROR;
@@ -412,9 +421,8 @@ int cCiTransportConnection::CreateConnection(void)
int cCiTransportConnection::Poll(void)
{
if (state == stACTIVE) {
- if (SendTPDU(T_DATA_LAST) == OK) {
+ if (SendTPDU(T_DATA_LAST) == OK)
return RecvTPDU();
- }
}
return ERROR;
}
@@ -428,11 +436,12 @@ private:
int fd;
int numSlots;
cCiTransportConnection tc[MAX_CI_CONNECT];
- bool ResetSlot(int Slot);
public:
cCiTransportLayer(int Fd, int NumSlots);
- cCiTransportConnection *NewConnection(void);
- int Process(void);
+ cCiTransportConnection *NewConnection(int Slot);
+ bool ResetSlot(int Slot);
+ bool ModuleReady(int Slot);
+ cCiTransportConnection *Process(int Slot);
};
cCiTransportLayer::cCiTransportLayer(int Fd, int NumSlots)
@@ -441,46 +450,28 @@ cCiTransportLayer::cCiTransportLayer(int Fd, int NumSlots)
numSlots = NumSlots;
for (int s = 0; s < numSlots; s++)
ResetSlot(s);
- for (int i = 0; i < MAX_CI_CONNECT; i++)
- tc[i].Init(fd, 0/*XXX*/, i + 1);
}
-cCiTransportConnection *cCiTransportLayer::NewConnection(void)
+cCiTransportConnection *cCiTransportLayer::NewConnection(int Slot)
{
for (int i = 0; i < MAX_CI_CONNECT; i++) {
if (tc[i].State() == stIDLE) {
- if (tc[i].CreateConnection() == OK) {
- if (tc[i].RecvTPDU() == T_CTC_REPLY)
- return &tc[i];
- }
+ dbgprotocol("Creating connection: slot %d, tcid %d\n", Slot, i + 1);
+ tc[i].Init(fd, Slot, i + 1);
+ if (tc[i].CreateConnection() == OK)
+ return &tc[i];
break;
}
}
return NULL;
}
-#define CA_RESET_TIMEOUT 3 // seconds
-
bool cCiTransportLayer::ResetSlot(int Slot)
{
dbgprotocol("Resetting slot %d...", Slot);
- ca_slot_info_t sinfo;
- sinfo.num = Slot;
if (ioctl(fd, CA_RESET, 1 << Slot) != -1) {
- time_t t0 = time(NULL);
- do {
- if (ioctl(fd, CA_GET_SLOT_INFO, &sinfo) != -1) {
- ioctl(fd, CA_GET_SLOT_INFO, &sinfo);
- if ((sinfo.flags & CA_CI_MODULE_READY) != 0) {
- dbgprotocol("ok.\n");
- return true;
- }
- }
- else {
- esyslog("ERROR: can't get info on CAM slot %d: %m", Slot);
- break;
- }
- } while (time(NULL) - t0 < CA_RESET_TIMEOUT);
+ dbgprotocol("ok.\n");
+ return true;
}
else
esyslog("ERROR: can't reset CAM slot %d: %m", Slot);
@@ -488,35 +479,55 @@ bool cCiTransportLayer::ResetSlot(int Slot)
return false;
}
-int cCiTransportLayer::Process(void)
+bool cCiTransportLayer::ModuleReady(int Slot)
+{
+ ca_slot_info_t sinfo;
+ sinfo.num = Slot;
+ if (ioctl(fd, CA_GET_SLOT_INFO, &sinfo) != -1)
+ return sinfo.flags & CA_CI_MODULE_READY;
+ else
+ esyslog("ERROR: can't get info on CAM slot %d: %m", Slot);
+ return false;
+}
+
+cCiTransportConnection *cCiTransportLayer::Process(int Slot)
{
for (int i = 0; i < MAX_CI_CONNECT; i++) {
cCiTransportConnection *Tc = &tc[i];
- if (Tc->State() == stACTIVE) {
- if (!Tc->DataAvailable()) {
- if (Tc->Poll() != OK)
- ;//XXX continue;
- }
- switch (Tc->LastResponse()) {
- case T_REQUEST_TC:
- //XXX
- break;
- case T_DATA_MORE:
- case T_DATA_LAST:
- case T_CTC_REPLY:
- case T_SB:
- if (Tc->DataAvailable())
- Tc->RecvData();
- break;
- case TIMEOUT:
- case ERROR:
- default:
- //XXX Tc->state = stIDLE;//XXX Init()???
+ if (Tc->Slot() == Slot) {
+ switch (Tc->State()) {
+ case stCREATION:
+ case stACTIVE:
+ if (!Tc->DataAvailable()) {
+ if (Tc->Poll() != OK)
+ ;//XXX continue;
+ }
+ switch (Tc->LastResponse()) {
+ case T_REQUEST_TC:
+ //XXX
+ break;
+ case T_DATA_MORE:
+ case T_DATA_LAST:
+ case T_CTC_REPLY:
+ case T_SB:
+ if (Tc->DataAvailable())
+ Tc->RecvData();
+ break;
+ case TIMEOUT:
+ case ERROR:
+ default:
+ //XXX Tc->state = stIDLE;//XXX Init()???
+ return NULL;
+ break;
+ }
+ //XXX this will only work with _one_ transport connection per slot!
+ return Tc;
break;
+ default: ;
}
}
}
- return OK;
+ return NULL;
}
// -- cCiSession -------------------------------------------------------------
@@ -608,6 +619,7 @@ protected:
public:
cCiSession(int SessionId, int ResourceId, cCiTransportConnection *Tc);
virtual ~cCiSession();
+ const cCiTransportConnection *Tc(void) { return tc; }
int SessionId(void) { return sessionId; }
int ResourceId(void) { return resourceId; }
virtual bool Process(int Length = 0, const uint8_t *Data = NULL);
@@ -1261,9 +1273,7 @@ cCiHandler::cCiHandler(int Fd, int NumSlots)
for (int i = 0; i < MAX_CI_SESSION; i++)
sessions[i] = NULL;
tpl = new cCiTransportLayer(Fd, numSlots);
- tc = tpl->NewConnection();
- if (!tc)
- isyslog("CAM: no CAM detected");
+ tc = NULL;
}
cCiHandler::~cCiHandler()
@@ -1281,14 +1291,9 @@ cCiHandler *cCiHandler::CreateCiHandler(const char *FileName)
if (ioctl(fd_ca, CA_GET_CAP, &Caps) == 0) {
int NumSlots = Caps.slot_num;
if (NumSlots > 0) {
- dsyslog("CAM: found %d CAM slots", NumSlots);
- if (Caps.slot_type == CA_CI_LINK) {
- cCiHandler *CiHandler = new cCiHandler(fd_ca, NumSlots);
- // drive the initial data exchange:
- for (int i = 0; i < 20; i++) //XXX make this dynamic???
- CiHandler->Process();
- return CiHandler;
- }
+ //XXX dsyslog("CAM: found %d CAM slots", NumSlots); // TODO let's do this only once we can be sure that there _really_ is a CAM adapter!
+ if (Caps.slot_type == CA_CI_LINK)
+ return new cCiHandler(fd_ca, NumSlots);
else
esyslog("ERROR: CAM doesn't support link layer interface");
}
@@ -1320,7 +1325,7 @@ bool cCiHandler::Send(uint8_t Tag, int SessionId, int ResourceId, int Status)
*(short *)p = htons(SessionId);
p += 2;
buffer[1] = p - buffer - 2; // length
- return tc->SendData(p - buffer, buffer) == OK;
+ return tc && tc->SendData(p - buffer, buffer) == OK;
}
cCiSession *cCiHandler::GetSessionBySessionId(int SessionId)
@@ -1332,10 +1337,10 @@ cCiSession *cCiHandler::GetSessionBySessionId(int SessionId)
return NULL;
}
-cCiSession *cCiHandler::GetSessionByResourceId(int ResourceId)
+cCiSession *cCiHandler::GetSessionByResourceId(int ResourceId, int Slot)
{
for (int i = 0; i < MAX_CI_SESSION; i++) {
- if (sessions[i] && sessions[i]->ResourceId() == ResourceId)
+ if (sessions[i] && sessions[i]->Tc()->Slot() == Slot && sessions[i]->ResourceId() == ResourceId)
return sessions[i];
}
return NULL;
@@ -1343,7 +1348,7 @@ cCiSession *cCiHandler::GetSessionByResourceId(int ResourceId)
cCiSession *cCiHandler::CreateSession(int ResourceId)
{
- if (!GetSessionByResourceId(ResourceId)) {
+ if (!GetSessionByResourceId(ResourceId, tc->Slot())) {
for (int i = 0; i < MAX_CI_SESSION; i++) {
if (!sessions[i]) {
switch (ResourceId) {
@@ -1403,81 +1408,107 @@ bool cCiHandler::CloseSession(int SessionId)
return false;
}
-bool cCiHandler::Process(void)
-{
- if (tc) {
- cMutexLock MutexLock(&mutex);
- if (tpl->Process() == OK) {
- int Length;
- const uint8_t *Data = tc->Data(Length);
- if (Data && Length > 1) {
- switch (*Data) {
- case ST_SESSION_NUMBER: if (Length > 4) {
- int SessionId = ntohs(*(short *)&Data[2]);
- cCiSession *Session = GetSessionBySessionId(SessionId);
- if (Session)
- return Session->Process(Length - 4, Data + 4);
- else {
- esyslog("ERROR: unknown session id: %d", SessionId);
- return false;
- }
- }
- break;
- case ST_OPEN_SESSION_REQUEST: return OpenSession(Length, Data);
- case ST_CLOSE_SESSION_REQUEST: if (Length == 4)
- return CloseSession(ntohs(*(short *)&Data[2]));
- break;
- case ST_CREATE_SESSION_RESPONSE: //XXX fall through to default
- case ST_CLOSE_SESSION_RESPONSE: //XXX fall through to default
- default: esyslog("ERROR: unknown session tag: %02X", *Data);
- return false;
- }
- return true;
- }
- for (int i = 0; i < MAX_CI_SESSION; i++) {
- if (sessions[i])
- sessions[i]->Process();//XXX retval???
+int cCiHandler::CloseAllSessions(int Slot)
+{
+ int result = 0;
+ for (int i = 0; i < MAX_CI_SESSION; i++) {
+ if (sessions[i] && sessions[i]->Tc()->Slot() == Slot) {
+ CloseSession(sessions[i]->SessionId());
+ result++;
+ }
+ }
+ return result;
+}
+
+void cCiHandler::Process(void)
+{
+ cMutexLock MutexLock(&mutex);
+ for (int Slot = 0; Slot < numSlots; Slot++) {
+ tc = tpl->Process(Slot);
+ if (tc) {
+ int Length;
+ const uint8_t *Data = tc->Data(Length);
+ if (Data && Length > 1) {
+ switch (*Data) {
+ case ST_SESSION_NUMBER: if (Length > 4) {
+ int SessionId = ntohs(*(short *)&Data[2]);
+ cCiSession *Session = GetSessionBySessionId(SessionId);
+ if (Session)
+ Session->Process(Length - 4, Data + 4);
+ else
+ esyslog("ERROR: unknown session id: %d", SessionId);
+ }
+ break;
+ case ST_OPEN_SESSION_REQUEST: OpenSession(Length, Data);
+ break;
+ case ST_CLOSE_SESSION_REQUEST: if (Length == 4)
+ CloseSession(ntohs(*(short *)&Data[2]));
+ break;
+ case ST_CREATE_SESSION_RESPONSE: //XXX fall through to default
+ case ST_CLOSE_SESSION_RESPONSE: //XXX fall through to default
+ default: esyslog("ERROR: unknown session tag: %02X", *Data);
+ }
}
- }
- }
- return false;
+ }
+ else {
+ if (!CloseAllSessions(Slot)) {
+ if (tpl->ModuleReady(Slot)) {
+ dbgprotocol("Module ready in slot %d\n", Slot);
+ tpl->NewConnection(Slot);
+ }
+ }
+ }
+ }
+ for (int i = 0; i < MAX_CI_SESSION; i++) {
+ if (sessions[i])
+ sessions[i]->Process();
+ }
}
-bool cCiHandler::EnterMenu(void)
+bool cCiHandler::EnterMenu(int Slot)
{
cMutexLock MutexLock(&mutex);
- //XXX slots???
- cCiApplicationInformation *api = (cCiApplicationInformation *)GetSessionByResourceId(RI_APPLICATION_INFORMATION);
+ cCiApplicationInformation *api = (cCiApplicationInformation *)GetSessionByResourceId(RI_APPLICATION_INFORMATION, Slot);
return api ? api->EnterMenu() : false;
}
cCiMenu *cCiHandler::GetMenu(void)
{
cMutexLock MutexLock(&mutex);
- //XXX slots???
- cCiMMI *mmi = (cCiMMI *)GetSessionByResourceId(RI_MMI);
- return mmi ? mmi->Menu() : NULL;
+ for (int Slot = 0; Slot < numSlots; Slot++) {
+ cCiMMI *mmi = (cCiMMI *)GetSessionByResourceId(RI_MMI, Slot);
+ if (mmi)
+ return mmi->Menu();
+ }
+ return NULL;
}
cCiEnquiry *cCiHandler::GetEnquiry(void)
{
cMutexLock MutexLock(&mutex);
- //XXX slots???
- cCiMMI *mmi = (cCiMMI *)GetSessionByResourceId(RI_MMI);
- return mmi ? mmi->Enquiry() : NULL;
+ for (int Slot = 0; Slot < numSlots; Slot++) {
+ cCiMMI *mmi = (cCiMMI *)GetSessionByResourceId(RI_MMI, Slot);
+ if (mmi)
+ return mmi->Enquiry();
+ }
+ return NULL;
}
bool cCiHandler::SetCaPmt(cCiCaPmt &CaPmt)
{
cMutexLock MutexLock(&mutex);
- //XXX slots???
- cCiConditionalAccessSupport *cas = (cCiConditionalAccessSupport *)GetSessionByResourceId(RI_CONDITIONAL_ACCESS_SUPPORT);
- return cas ? cas->SendPMT(CaPmt) : false;
+ bool result = false;
+ for (int Slot = 0; Slot < numSlots; Slot++) {
+ cCiConditionalAccessSupport *cas = (cCiConditionalAccessSupport *)GetSessionByResourceId(RI_CONDITIONAL_ACCESS_SUPPORT, Slot);
+ if (cas)
+ result |= cas->SendPMT(CaPmt);
+ }
+ return result;
}
-bool cCiHandler::Reset(void)
+bool cCiHandler::Reset(int Slot)
{
cMutexLock MutexLock(&mutex);
- //XXX slots???
- return false;//XXX not yet implemented
+ CloseAllSessions(Slot);
+ return tpl->ResetSlot(Slot);
}
diff --git a/ci.h b/ci.h
index c9cd6f54..5d33b611 100644
--- a/ci.h
+++ b/ci.h
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: ci.h 1.1 2003/01/06 12:31:09 kls Exp $
+ * $Id: ci.h 1.2 2003/02/09 11:44:00 kls Exp $
*/
#ifndef __CI_H
@@ -86,20 +86,21 @@ private:
int ResourceIdToInt(const uint8_t *Data);
bool Send(uint8_t Tag, int SessionId, int ResourceId = 0, int Status = -1);
cCiSession *GetSessionBySessionId(int SessionId);
- cCiSession *GetSessionByResourceId(int ResourceId);
+ cCiSession *GetSessionByResourceId(int ResourceId, int Slot);
cCiSession *CreateSession(int ResourceId);
bool OpenSession(int Length, const uint8_t *Data);
bool CloseSession(int SessionId);
+ int CloseAllSessions(int Slot);
cCiHandler(int Fd, int NumSlots);
public:
~cCiHandler();
static cCiHandler *CreateCiHandler(const char *FileName);
- bool Process(void);
- bool EnterMenu(void);
+ void Process(void);
+ bool EnterMenu(int Slot);
cCiMenu *GetMenu(void);
cCiEnquiry *GetEnquiry(void);
bool SetCaPmt(cCiCaPmt &CaPmt);
- bool Reset(void);
+ bool Reset(int Slot);
};
#endif //__CI_H
diff --git a/config.h b/config.h
index 8bf33f62..1760eed9 100644
--- a/config.h
+++ b/config.h
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: config.h 1.147 2003/01/26 19:50:19 kls Exp $
+ * $Id: config.h 1.148 2003/02/08 10:25:44 kls Exp $
*/
#ifndef __CONFIG_H
@@ -19,7 +19,7 @@
#include "device.h"
#include "tools.h"
-#define VDRVERSION "1.1.23"
+#define VDRVERSION "1.1.24"
#define MAXPRIORITY 99
#define MAXLIFETIME 99
diff --git a/dvbdevice.c b/dvbdevice.c
index 1ffe067a..01d828fa 100644
--- a/dvbdevice.c
+++ b/dvbdevice.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: dvbdevice.c 1.42 2003/02/02 15:31:31 kls Exp $
+ * $Id: dvbdevice.c 1.43 2003/02/09 11:47:02 kls Exp $
*/
#include "dvbdevice.h"
@@ -238,6 +238,7 @@ bool cDvbTuner::SetFrontend(void)
void cDvbTuner::Action(void)
{
+ time_t StartTime = time(NULL);
dsyslog("tuner thread started on device %d (pid=%d)", cardIndex + 1, getpid());
active = true;
while (active) {
@@ -258,24 +259,28 @@ void cDvbTuner::Action(void)
continue;
}
}
- if (ciHandler && !caSet) {//XXX TODO update in case the CA descriptors have changed
- uchar buffer[2048];
- int length = cSIProcessor::GetCaDescriptors(channel.Source(), channel.Frequency(), channel.Sid(), sizeof(buffer), buffer);
- if (length > 0) {
- cCiCaPmt CaPmt(channel.Sid());
- CaPmt.AddCaDescriptor(length, buffer);
- if (channel.Vpid())
- CaPmt.AddPid(channel.Vpid());
- if (channel.Apid1())
- CaPmt.AddPid(channel.Apid1());
- if (channel.Apid2())
- CaPmt.AddPid(channel.Apid2());
- if (channel.Dpid1())
- CaPmt.AddPid(channel.Dpid1());
- caSet = ciHandler->SetCaPmt(CaPmt);
+ if (ciHandler) {
+ ciHandler->Process();
+ if (!caSet) {//XXX TODO update in case the CA descriptors have changed
+ uchar buffer[2048];
+ int length = cSIProcessor::GetCaDescriptors(channel.Source(), channel.Frequency(), channel.Sid(), sizeof(buffer), buffer);
+ if (length > 0) {
+ cCiCaPmt CaPmt(channel.Sid());
+ CaPmt.AddCaDescriptor(length, buffer);
+ if (channel.Vpid())
+ CaPmt.AddPid(channel.Vpid());
+ if (channel.Apid1())
+ CaPmt.AddPid(channel.Apid1());
+ if (channel.Apid2())
+ CaPmt.AddPid(channel.Apid2());
+ if (channel.Dpid1())
+ CaPmt.AddPid(channel.Dpid1());
+ caSet = ciHandler->SetCaPmt(CaPmt);
+ }
}
}
- newSet.TimedWait(mutex, 1000);
+ // in the beginning we loop more often to let the CAM connection start up fast
+ newSet.TimedWait(mutex, (ciHandler && (time(NULL) - StartTime < 20)) ? 100 : 1000);
}
dsyslog("tuner thread ended on device %d (pid=%d)", cardIndex + 1, getpid());
}
diff --git a/menu.c b/menu.c
index 081a4ba1..495cb6a3 100644
--- a/menu.c
+++ b/menu.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: menu.c 1.232 2003/01/19 14:59:46 kls Exp $
+ * $Id: menu.c 1.233 2003/02/09 10:46:25 kls Exp $
*/
#include "menu.h"
@@ -1537,6 +1537,7 @@ cMenuCam::cMenuCam(cCiMenu *CiMenu)
Add(new cOsdItem(ciMenu->SubTitleText()));
Add(new cOsdItem(ciMenu->BottomText()));
Display();
+ dsyslog("CAM: Menu - %s", ciMenu->TitleText());
}
cMenuCam::~cMenuCam()
@@ -1622,7 +1623,6 @@ cOsdObject *CamControl(void)
if (Device) {
cCiHandler *CiHandler = Device->CiHandler();
if (CiHandler) {
- CiHandler->Process();
cCiMenu *CiMenu = CiHandler->GetMenu();
if (CiMenu)
return new cMenuCam(CiMenu);
@@ -2069,7 +2069,7 @@ class cMenuSetupCICAM : public cMenuSetupBase {
private:
int helpKeys;
void SetHelpKeys(void);
- cCiHandler *GetCurrentCiHandler(void);
+ cCiHandler *GetCurrentCiHandler(int *Slot = NULL);
eOSState Menu(void);
eOSState Reset(void);
public:
@@ -2091,9 +2091,11 @@ cMenuSetupCICAM::cMenuSetupCICAM(void)
SetHelpKeys();
}
-cCiHandler *cMenuSetupCICAM::GetCurrentCiHandler(void)
+cCiHandler *cMenuSetupCICAM::GetCurrentCiHandler(int *Slot)
{
cDevice *Device = cDevice::GetDevice(Current() / 2);
+ if (Slot)
+ *Slot = Current() % 2;
return Device ? Device->CiHandler() : NULL;
}
@@ -2112,8 +2114,9 @@ void cMenuSetupCICAM::SetHelpKeys(void)
eOSState cMenuSetupCICAM::Menu(void)
{
- cCiHandler *CiHandler = GetCurrentCiHandler();
- if (CiHandler && CiHandler->EnterMenu())
+ int Slot = 0;
+ cCiHandler *CiHandler = GetCurrentCiHandler(&Slot);
+ if (CiHandler && CiHandler->EnterMenu(Slot))
return osEnd; // the CAM menu will be executed explicitly from the main loop
else
Interface->Error(tr("Can't open CAM menu!"));
@@ -2122,9 +2125,12 @@ eOSState cMenuSetupCICAM::Menu(void)
eOSState cMenuSetupCICAM::Reset(void)
{
- cCiHandler *CiHandler = GetCurrentCiHandler();
- if (CiHandler && CiHandler->Reset())
+ int Slot = 0;
+ cCiHandler *CiHandler = GetCurrentCiHandler(&Slot);
+ if (CiHandler && CiHandler->Reset(Slot)) {
Interface->Info(tr("CAM has been reset"));
+ return osEnd;
+ }
else
Interface->Error(tr("Can't reset CAM!"));
return osContinue;
diff --git a/vdr.c b/vdr.c
index 87550ded..166afb04 100644
--- a/vdr.c
+++ b/vdr.c
@@ -22,7 +22,7 @@
*
* The project's page is at http://www.cadsoft.de/people/kls/vdr
*
- * $Id: vdr.c 1.141 2003/01/26 11:56:31 kls Exp $
+ * $Id: vdr.c 1.142 2003/02/09 11:25:38 kls Exp $
*/
#include <getopt.h>
@@ -469,7 +469,7 @@ int main(int argc, char *argv[])
}
}
// CAM control:
- if (!Menu)
+ if (!Interface->IsOpen())
Menu = CamControl();
// User Input:
cOsdObject *Interact = Menu ? Menu : cControl::Control();