Problem: Conax not available after VDR startup
Commit Message
Rantanen Teemu wrote:
> Klaus Schmidinger wrote:
>
>>I really don't see why tuning to a particular channel should speed up
>>the initial setup of the CAM communication.
>
>
> I only know that EPG scan did help, and did help every time...
>
> But, in the meantime I've built a new vdr/file -server, and guess
> what... yep, the delay is gone. I have no idea what was the real fix as
> I've changed almost everything (except dvb-hardware):
>
> P2-350 -> Celeron-2.5G
> vdr-1.3.23 -> vdr-1.3.29
> linux-2.4 -> linux-2.6
> dvb-20041226 -> dvb in kernel
> etc...
>
> But I guess there are still some people who have the same problem. Why
> not add an option to VDR to allow EPG scan to start right away?
I strongly believe that the EPG scan thing was just a symptom, not the cause.
The attached patch makes VDR wait until all devices that have CAMs
are ready to decrypt. With this I can start VDR right away with
an encrypted channel, and it doesn't say "channel not available"
any more.
Please test whether this works for you, too.
Klaus
@@ -1354,6 +1354,8 @@
hasUserIO = false;
for (int i = 0; i < MAX_CI_SESSION; i++)
sessions[i] = NULL;
+ for (int i = 0; i < MAX_CI_SLOT; i++)
+ moduleReady[i] = false;
tpl = new cCiTransportLayer(Fd, numSlots);
tc = NULL;
}
@@ -1506,6 +1508,19 @@
return result;
}
+bool cCiHandler::Ready(void)
+{
+ cMutexLock MutexLock(&mutex);
+ for (int Slot = 0; Slot < numSlots; Slot++) {
+ if (moduleReady[Slot]) {
+ cCiConditionalAccessSupport *cas = (cCiConditionalAccessSupport *)GetSessionByResourceId(RI_CONDITIONAL_ACCESS_SUPPORT, Slot);
+ if (!cas || !*cas->GetCaSystemIds())
+ return false;
+ }
+ }
+ return true;
+}
+
bool cCiHandler::Process(void)
{
bool result = true;
@@ -1543,6 +1558,7 @@
}
else if (tpl->ModuleReady(Slot)) {
dbgprotocol("Module ready in slot %d\n", Slot);
+ moduleReady[Slot] = true;
tpl->NewConnection(Slot);
}
}
@@ -77,6 +77,7 @@
};
#define MAX_CI_SESSION 16 //XXX
+#define MAX_CI_SLOT 16
class cCiSession;
class cCiTransportLayer;
@@ -89,6 +90,7 @@
int numSlots;
bool newCaSupport;
bool hasUserIO;
+ bool moduleReady[MAX_CI_SLOT];
cCiSession *sessions[MAX_CI_SESSION];
cCiTransportLayer *tpl;
cCiTransportConnection *tc;
@@ -105,6 +107,7 @@
~cCiHandler();
static cCiHandler *CreateCiHandler(const char *FileName);
int NumSlots(void) { return numSlots; }
+ bool Ready(void);
bool Process(void);
bool HasUserIO(void) { return hasUserIO; }
bool EnterMenu(int Slot);
@@ -195,6 +195,19 @@
delete pesAssembler;
}
+void cDevice::WaitForAllDevicesReady(int Timeout)
+{
+ for (time_t t0 = time(NULL); time(NULL) - t0 < Timeout; ) {
+ bool ready = true;
+ for (int i = 0; i < numDevices; i++) {
+ if (device[i] && !device[i]->Ready())
+ ready = false;
+ }
+ if (ready)
+ break;
+ }
+}
+
void cDevice::SetUseDevice(int n)
{
if (n < MAXDEVICES)
@@ -1103,6 +1116,11 @@
XXX*/
}
+bool cDevice::Ready(void)
+{
+ return true;
+}
+
int cDevice::ProvidesCa(const cChannel *Channel) const
{
int Ca = Channel->Ca();
@@ -102,6 +102,9 @@
public:
static int NumDevices(void) { return numDevices; }
///< Returns the total number of devices.
+ static void WaitForAllDevicesReady(int Timeout = 0);
+ ///< Waits until all devices have become ready, or the given Timeout
+ ///< (seconds) has expired.
static void SetUseDevice(int n);
///< Sets the 'useDevice' flag of the given device.
///< If this function is not called before initializing, all devices
@@ -136,6 +139,9 @@
protected:
cDevice(void);
virtual ~cDevice();
+ virtual bool Ready(void);
+ ///< Returns true if this device is ready. Devices with conditional
+ ///< access hardware may need some time until they are up and running.
static int NextCardIndex(int n = 0);
///< Calculates the next card index.
///< Each device in a given machine must have a unique card index, which
@@ -478,6 +478,15 @@
return fd_video >= 0 && fd_audio >= 0;
}
+bool cDvbDevice::Ready(void)
+{
+ if (ciHandler) {
+ ciHandler->Process();
+ return ciHandler->Ready();
+ }
+ return true;
+}
+
int cDvbDevice::ProvidesCa(const cChannel *Channel) const
{
if (Channel->Ca() >= 0x0100 && ciHandler) {
@@ -42,6 +42,7 @@
public:
cDvbDevice(int n);
virtual ~cDvbDevice();
+ virtual bool Ready(void);
virtual int ProvidesCa(const cChannel *Channel) const;
virtual bool HasDecoder(void) const;
@@ -520,6 +520,7 @@
// Channel:
+ cDevice::WaitForAllDevicesReady(30);
Channels.SwitchTo(Setup.CurrentChannel);
if (MuteAudio)
cDevice::PrimaryDevice()->ToggleMute();