summaryrefslogtreecommitdiff
path: root/dvbdevice.c
diff options
context:
space:
mode:
authorKlaus Schmidinger <kls (at) cadsoft (dot) de>2007-01-07 18:00:00 +0100
committerKlaus Schmidinger <kls (at) cadsoft (dot) de>2007-01-07 18:00:00 +0100
commit66ab78a40f5b57e20142a33484e32c785a0c4017 (patch)
tree2e351bb9df6cc1325d439729646f83b35e2c346d /dvbdevice.c
parenta2096f3beb9f7bf3ba600cf66555628fc899720e (diff)
downloadvdr-patch-lnbsharing-66ab78a40f5b57e20142a33484e32c785a0c4017.tar.gz
vdr-patch-lnbsharing-66ab78a40f5b57e20142a33484e32c785a0c4017.tar.bz2
Version 1.5.0vdr-1.5.0
- The CAM handling has been refactored. Instead of a cCiHandler per device there is now an abstract cCiAdapter and a cCamSlot. This allows each slot to be accessed individually. - The general 15 seconds workaround time before opening the CAM menu has been removed. If the CAM menu doesn't open within a timeout, the enter menu command is now sent again. - If a CAM is reset or pulled and reinserted, it now automatically starts decrypting the current channel again. - The Setup/CAM menu now dynamically refreshes its items and displays whether a CAM is present or ready. The 'Reset' function no longer leaves the menu. - The CAM menu will now be openend when pressing the Ok key on a slot entry. - The CAM menu now stays within the current menu context and doesn't close and reopen the menu every time an option is selected. - When an encrypted channel is switched to for the first time, VDR now checks explicitly whether a CAM can actually decrypt that channel. If there is more than one CAM in the system that claims to be able to decrypt the channel, they are all tried in turn. To make this possible, an encrypted channel needs to be received in Transfer Mode when it is switched to for the first time, so that VDR can determine whether the TS packets are actually decrypted. Once a channel is known to be decrypted by a particular CAM, the next time it is switched to it will be shown in normal live viewing mode. - A cDevice now automatically detaches all cReceiver objects that receive PIDs that can't be decrypted with the current CAM. A plugin that attaches a cReceiver to a device should therefore watch the receiver's IsAttached() function to see if it is still attached to the device. - The cReceiver constructor no longer takes an 'int Ca' as its first parameter, but rather a 'tChannelID ChannelID'. This is necessary for the device to be able to determine which CAM a particular channel can be decrypted with. If the channel is known to be unencrypted, or a plugin doesn't want to provide the channel id for other reasons, an invalid tChannelID() can be given. - The cThread::Start() function now waits until a previous incarnation of this thread has actually stopped. Before this it could happen that a thread's Cancel(-1) function was called and immediately after that it was started again, but the Start() function still found it to be 'active'. - The parameter NeedsDetachReceivers in cDevice::GetDevice(const cChannel *Channel, ...) has been removed. A call to this function will automatically detach all receivers from the device if it returns a non-NULL pointer. - The cTimeMs class now accepts an initial timeout value in its constructor. - A CAM is now explicitly instructed to stop decrypting when switching away from an encrypted channel. - If the CAM in use can decrypt several channels at the same time, VDR can now make use if this capability. Whether or not a CAM can decrypt more than one channel is determined by sending it an initial empty QUERY command and testing whether it replies to it. - Ca values in the range 0...F in channels.conf can still be used to assign a channel to a particular device, but this will no longer work with encrypted channels because without valid CA ids VDR can't decide which CAM slot to use. However, since VDR now automatically determines which CAM can decrypt which channel, setting fixed channel/device relations should no longer be necessary. IF AN ENCRYPTED CHANNEL CAN'T BE DECRYPTED AND YOU HAVE A CA VALUE IN THE RANGE 0...F FOR THAT CHANNEL, SET IT TO 0 (FTA) AND TUNE TO THE CHANNEL AGAIN.
Diffstat (limited to 'dvbdevice.c')
-rw-r--r--dvbdevice.c77
1 files changed, 31 insertions, 46 deletions
diff --git a/dvbdevice.c b/dvbdevice.c
index fb8ec93..487aec5 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.160 2006/08/14 09:38:32 kls Exp $
+ * $Id: dvbdevice.c 1.161 2007/01/05 11:09:51 kls Exp $
*/
#include "dvbdevice.h"
@@ -19,6 +19,7 @@
#include <sys/mman.h>
#include "channels.h"
#include "diseqc.h"
+#include "dvbci.h"
#include "dvbosd.h"
#include "eitscan.h"
#include "player.h"
@@ -28,7 +29,6 @@
#define DO_REC_AND_PLAY_ON_PRIMARY_DEVICE 1
#define DO_MULTIPLE_RECORDINGS 1
-//#define DO_MULTIPLE_CA_CHANNELS
#define DEV_VIDEO "/dev/video"
#define DEV_DVB_ADAPTER "/dev/dvb/adapter"
@@ -77,7 +77,6 @@ private:
int lockTimeout;
time_t lastTimeoutReport;
fe_type_t frontendType;
- cCiHandler *ciHandler;
cChannel channel;
const char *diseqcCommands;
eTunerStatus tunerStatus;
@@ -88,19 +87,18 @@ private:
bool SetFrontend(void);
virtual void Action(void);
public:
- cDvbTuner(int Fd_Frontend, int CardIndex, fe_type_t FrontendType, cCiHandler *CiHandler);
+ cDvbTuner(int Fd_Frontend, int CardIndex, fe_type_t FrontendType);
virtual ~cDvbTuner();
bool IsTunedTo(const cChannel *Channel) const;
void Set(const cChannel *Channel, bool Tune);
bool Locked(int TimeoutMs = 0);
};
-cDvbTuner::cDvbTuner(int Fd_Frontend, int CardIndex, fe_type_t FrontendType, cCiHandler *CiHandler)
+cDvbTuner::cDvbTuner(int Fd_Frontend, int CardIndex, fe_type_t FrontendType)
{
fd_frontend = Fd_Frontend;
cardIndex = CardIndex;
frontendType = FrontendType;
- ciHandler = CiHandler;
tuneTimeout = 0;
lockTimeout = 0;
lastTimeoutReport = 0;
@@ -346,8 +344,6 @@ void cDvbTuner::Action(void)
}
}
- if (ciHandler)
- ciHandler->Process();
if (tunerStatus != tsTuned)
newSet.TimedWait(mutex, 1000);
}
@@ -360,6 +356,7 @@ int cDvbDevice::setTransferModeForDolbyDigital = 1;
cDvbDevice::cDvbDevice(int n)
{
+ ciAdapter = NULL;
dvbTuner = NULL;
frontendType = fe_type_t(-1); // don't know how else to initialize this - there is no FE_UNKNOWN
spuDecoder = NULL;
@@ -377,6 +374,12 @@ cDvbDevice::cDvbDevice(int n)
fd_audio = DvbOpen(DEV_DVB_AUDIO, n, O_RDWR | O_NONBLOCK);
fd_stc = DvbOpen(DEV_DVB_DEMUX, n, O_RDWR);
+ // Common Interface:
+
+ fd_ca = DvbOpen(DEV_DVB_CA, n, O_RDWR);
+ if (fd_ca >= 0)
+ ciAdapter = cDvbCiAdapter::CreateCiAdapter(this, fd_ca);
+
// The DVR device (will be opened and closed as needed):
fd_dvr = -1;
@@ -420,8 +423,7 @@ cDvbDevice::cDvbDevice(int n)
dvb_frontend_info feinfo;
if (ioctl(fd_frontend, FE_GET_INFO, &feinfo) >= 0) {
frontendType = feinfo.type;
- ciHandler = cCiHandler::CreateCiHandler(*cDvbName(DEV_DVB_CA, n));
- dvbTuner = new cDvbTuner(fd_frontend, CardIndex(), frontendType, ciHandler);
+ dvbTuner = new cDvbTuner(fd_frontend, CardIndex(), frontendType);
}
else
LOG_ERROR;
@@ -436,6 +438,7 @@ cDvbDevice::~cDvbDevice()
{
delete spuDecoder;
delete dvbTuner;
+ delete ciAdapter;
// We're not explicitly closing any device files here, since this sometimes
// caused segfaults. Besides, the program is about to terminate anyway...
}
@@ -494,32 +497,11 @@ bool cDvbDevice::HasDecoder(void) const
bool cDvbDevice::Ready(void)
{
- if (ciHandler) {
- ciHandler->Process();
- return ciHandler->Ready();
- }
+ if (ciAdapter)
+ return ciAdapter->Ready();
return true;
}
-int cDvbDevice::ProvidesCa(const cChannel *Channel) const
-{
- int NumCams = 0;
- if (ciHandler) {
- NumCams = ciHandler->NumCams();
- if (Channel->Ca() >= CA_ENCRYPTED_MIN) {
- unsigned short ids[MAXCAIDS + 1];
- for (int i = 0; i <= MAXCAIDS; i++) // '<=' copies the terminating 0!
- ids[i] = Channel->Ca(i);
- if (ciHandler->ProvidesCa(ids))
- return NumCams + 1;
- }
- }
- int result = cDevice::ProvidesCa(Channel);
- if (result > 0)
- result += NumCams;
- return result;
-}
-
cSpuDecoder *cDvbDevice::GetSpuDecoder(void)
{
if (!spuDecoder && IsPrimaryDevice())
@@ -770,18 +752,19 @@ bool cDvbDevice::ProvidesChannel(const cChannel *Channel, int Priority, bool *Ne
bool hasPriority = Priority < 0 || Priority > this->Priority();
bool needsDetachReceivers = false;
- if (ProvidesSource(Channel->Source()) && ProvidesCa(Channel)) {
+ if (ProvidesSource(Channel->Source())) {
result = hasPriority;
if (Priority >= 0 && Receiving(true)) {
if (dvbTuner->IsTunedTo(Channel)) {
if (Channel->Vpid() && !HasPid(Channel->Vpid()) || Channel->Apid(0) && !HasPid(Channel->Apid(0))) {
#ifdef DO_MULTIPLE_RECORDINGS
-#ifndef DO_MULTIPLE_CA_CHANNELS
- if (Ca() >= CA_ENCRYPTED_MIN || Channel->Ca() >= CA_ENCRYPTED_MIN)
- needsDetachReceivers = Ca() != Channel->Ca();
- else
-#endif
- if (!IsPrimaryDevice())
+ if (CamSlot() && Channel->Ca() >= CA_ENCRYPTED_MIN) {
+ if (CamSlot()->CanDecrypt(Channel))
+ result = true;
+ else
+ needsDetachReceivers = true;
+ }
+ else if (!IsPrimaryDevice())
result = true;
#ifdef DO_REC_AND_PLAY_ON_PRIMARY_DEVICE
else
@@ -821,6 +804,8 @@ bool cDvbDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
&& (LiveView && HasPid(Channel->Vpid() ? Channel->Vpid() : Channel->Apid(0)) && (pidHandles[ptVideo].pid != Channel->Vpid() || (pidHandles[ptAudio].pid != Channel->Apid(0) && (Channel->Dpid(0) ? pidHandles[ptAudio].pid != Channel->Dpid(0) : true)))// the PID is already set as DMX_PES_OTHER
|| !LiveView && (pidHandles[ptVideo].pid == Channel->Vpid() || pidHandles[ptAudio].pid == Channel->Apid(0)) // a recording is going to shift the PIDs from DMX_PES_AUDIO/VIDEO to DMX_PES_OTHER
);
+ if (CamSlot() && !ChannelCamRelations.CamDecrypt(Channel->GetChannelID(), CamSlot()->SlotNumber()))
+ StartTransferMode |= LiveView && IsPrimaryDevice() && Channel->Ca() >= CA_ENCRYPTED_MIN;
bool TurnOnLivePIDs = HasDecoder() && !StartTransferMode && LiveView;
@@ -861,7 +846,7 @@ bool cDvbDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
CHECK(ioctl(fd_audio, AUDIO_SET_AV_SYNC, true));
}
else if (StartTransferMode)
- cControl::Launch(new cTransferControl(this, Channel->Vpid(), Channel->Apids(), Channel->Dpids(), Channel->Spids()));
+ cControl::Launch(new cTransferControl(this, Channel->GetChannelID(), Channel->Vpid(), Channel->Apids(), Channel->Dpids(), Channel->Spids()));
return true;
}
@@ -922,13 +907,13 @@ void cDvbDevice::SetAudioTrackDevice(eTrackType Type)
if (IS_AUDIO_TRACK(Type) || (IS_DOLBY_TRACK(Type) && SetAudioBypass(true))) {
if (pidHandles[ptAudio].pid && pidHandles[ptAudio].pid != TrackId->id) {
DetachAll(pidHandles[ptAudio].pid);
- if (ciHandler)
- ciHandler->SetPid(pidHandles[ptAudio].pid, false);
+ if (CamSlot())
+ CamSlot()->SetPid(pidHandles[ptAudio].pid, false);
pidHandles[ptAudio].pid = TrackId->id;
SetPid(&pidHandles[ptAudio], ptAudio, true);
- if (ciHandler) {
- ciHandler->SetPid(pidHandles[ptAudio].pid, true);
- ciHandler->StartDecrypting();
+ if (CamSlot()) {
+ CamSlot()->SetPid(pidHandles[ptAudio].pid, true);
+ CamSlot()->StartDecrypting();
}
}
}