diff --git a/HISTORY b/HISTORY index 45ba1c47..400ad11c 100644 --- a/HISTORY +++ b/HISTORY @@ -8132,8 +8132,11 @@ Video Disk Recorder Revision History and also to use the correct directory with --edit (the latter reported by Marko Mäkelä). -2014-01-07: Version 2.1.4 +2014-01-14: Version 2.1.4 - Updated 'sources.conf' (thanks to Antti Hartikainen). - cFont::CreateFont() now returns a dummy font in case there are no fonts installed. This prevents a crash with the LCARS skin on a system that has no fonts. +- Improved locking for CAM slots and made the pure functions of cCiAdapter have + default implementations, to fix a possible crash with CI adapters and CAM slots + that are implemented in a plugin. diff --git a/ci.c b/ci.c index e2881fed..56a4583e 100644 --- a/ci.c +++ b/ci.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: ci.c 3.4 2014/01/02 10:31:12 kls Exp $ + * $Id: ci.c 3.5 2014/01/14 12:03:37 kls Exp $ */ #include "ci.h" @@ -1584,6 +1584,8 @@ cCamSlot::cCamSlot(cCiAdapter *CiAdapter, bool ReceiveCaPids) cCamSlot::~cCamSlot() { + if (ciAdapter && ciAdapter->assignedDevice) + ciAdapter->assignedDevice->SetCamSlot(NULL); delete caPidReceiver; CamSlots.Del(this, false); DeleteAllConnections(); diff --git a/ci.h b/ci.h index 11237121..e3b85912 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 3.3 2014/01/02 10:14:39 kls Exp $ + * $Id: ci.h 3.4 2014/01/14 11:53:52 kls Exp $ */ #ifndef __CI_H @@ -88,19 +88,19 @@ protected: ///< Handles the attached CAM slots in a separate thread. ///< The derived class must call the Start() function to ///< actually start CAM handling. - virtual int Read(uint8_t *Buffer, int MaxLength) = 0; + virtual int Read(uint8_t *Buffer, int MaxLength) { return 0; } ///< Reads one chunk of data into the given Buffer, up to MaxLength bytes. ///< If no data is available immediately, wait for up to CAM_READ_TIMEOUT. ///< Returns the number of bytes read (in case of an error it will also ///< return 0). - virtual void Write(const uint8_t *Buffer, int Length) = 0; + virtual void Write(const uint8_t *Buffer, int Length) {} ///< Writes Length bytes of the given Buffer. - virtual bool Reset(int Slot) = 0; + virtual bool Reset(int Slot) { return false; } ///< Resets the CAM in the given Slot. ///< Returns true if the operation was successful. - virtual eModuleStatus ModuleStatus(int Slot) = 0; + virtual eModuleStatus ModuleStatus(int Slot) { return msNone; } ///< Returns the status of the CAM in the given Slot. - virtual bool Assign(cDevice *Device, bool Query = false) = 0; + virtual bool Assign(cDevice *Device, bool Query = false) { return false; } ///< Assigns this adapter to the given Device, if this is possible. ///< If Query is 'true', the adapter only checks whether it can be ///< assigned to the Device, but doesn't actually assign itself to it. diff --git a/device.c b/device.c index 84caf4e1..b84b5a26 100644 --- a/device.c +++ b/device.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: device.c 3.7 2014/01/02 10:31:58 kls Exp $ + * $Id: device.c 3.8 2014/01/14 11:58:49 kls Exp $ */ #include "device.h" @@ -358,6 +358,7 @@ bool cDevice::HasCi(void) void cDevice::SetCamSlot(cCamSlot *CamSlot) { + LOCK_THREAD; camSlot = CamSlot; } @@ -1575,6 +1576,7 @@ void cDevice::Action(void) while (Running()) { // Read data from the DVR device: uchar *b = NULL; + LOCK_THREAD; if (GetTSPacket(b)) { if (b) { int Pid = TsPid(b); @@ -1599,7 +1601,6 @@ void cDevice::Action(void) } } // Distribute the packet to all attached receivers: - Lock(); for (int i = 0; i < MAXRECEIVERS; i++) { if (receiver[i] && receiver[i]->WantsPid(Pid)) { if (DetachReceivers) { @@ -1612,7 +1613,6 @@ void cDevice::Action(void) ChannelCamRelations.SetDecrypt(receiver[i]->ChannelID(), CamSlotNumber); } } - Unlock(); } } else