diff --git a/HISTORY b/HISTORY index db954d44..8e770ee7 100644 --- a/HISTORY +++ b/HISTORY @@ -1942,7 +1942,8 @@ Video Disk Recorder Revision History Kirchgatterer and Robert Schiele). - Fixed skipping unavailable channels in the EPG scanner. -2003-01-26: Version 1.1.23 +2003-02-02: Version 1.1.23 - Fixed a new/delete malloc/free mismatch in ringbuffer.c (thanks to Stefan Huelswitt for reporting this one). +- Improved CAM handling. diff --git a/ci.c b/ci.c index 61bc7482..97de9b01 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 1.2 2003/01/11 11:15:19 kls Exp $ + * $Id: ci.c 1.3 2003/02/02 15:49:52 kls Exp $ */ /* XXX TODO @@ -13,7 +13,6 @@ - update CA descriptors in case they change - dynamically react on CAM insert/remove - implement CAM reset (per slot) -- implement a CA enquiry menu with actual user input XXX*/ #include "ci.h" @@ -45,7 +44,7 @@ static int SysLogLevel = 3; static bool DumpTPDUDataTransfer = false; static bool DebugProtocol = false; -#define dbgprotocol(a...) if (DebugProtocol) printf(a) +#define dbgprotocol(a...) if (DebugProtocol) fprintf(stderr, a) #define OK 0 #define TIMEOUT -1 @@ -460,19 +459,32 @@ cCiTransportConnection *cCiTransportLayer::NewConnection(void) return NULL; } -#define CA_RESET_TIMEOUT 2 // seconds +#define CA_RESET_TIMEOUT 3 // seconds bool cCiTransportLayer::ResetSlot(int Slot) { + dbgprotocol("Resetting slot %d...", Slot); ca_slot_info_t sinfo; sinfo.num = Slot; - ioctl(fd, CA_RESET, Slot); - time_t t0 = time(NULL); - do { - ioctl(fd, CA_GET_SLOT_INFO, &sinfo); - if ((sinfo.flags & CA_CI_MODULE_READY) != 0) - return true; - } while (time(NULL) - t0 < CA_RESET_TIMEOUT); + 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); + } + else + esyslog("ERROR: can't reset CAM slot %d: %m", Slot); + dbgprotocol("failed!\n"); return false; } @@ -818,7 +830,27 @@ cCiConditionalAccessSupport::cCiConditionalAccessSupport(int SessionId, cCiTrans bool cCiConditionalAccessSupport::Process(int Length, const uint8_t *Data) { - if (state == 0) { + if (Data) { + int Tag = GetTag(Length, &Data); + switch (Tag) { + case AOT_CA_INFO: { + dbgprotocol("%d: <== Ca Info", SessionId()); + int l = 0; + const uint8_t *d = GetData(Data, l); + while (l > 1) { + dbgprotocol(" %04X", ((unsigned int)(*d) << 8) | *(d + 1)); + d += 2; + l -= 2; + } + dbgprotocol("\n"); + } + state = 2; + break; + default: esyslog("ERROR: CI conditional access support: unknown tag %06X", Tag); + return false; + } + } + else if (state == 0) { dbgprotocol("%d: ==> Ca Info Enq\n", SessionId()); SendData(AOT_CA_INFO_ENQ); state = 1; @@ -828,7 +860,7 @@ bool cCiConditionalAccessSupport::Process(int Length, const uint8_t *Data) bool cCiConditionalAccessSupport::SendPMT(cCiCaPmt &CaPmt) { - if (state == 1) { + if (state == 2) { SendData(AOT_CA_PMT, CaPmt.length, CaPmt.capmt); return true; } @@ -1186,27 +1218,27 @@ cCiCaPmt::cCiCaPmt(int ProgramNumber) capmt[length++] = (ProgramNumber >> 8) & 0xFF; capmt[length++] = ProgramNumber & 0xFF; capmt[length++] = 0x00; //XXX version_number, current_next_indicator - apparently may be 0x00 - capmt[length++] = 0x00; //XXX program_info_length H (at program level) - capmt[length++] = 0x00; //XXX program_info_length L - esInfoLengthPos = 0; + esInfoLengthPos = length; + capmt[length++] = 0x00; // program_info_length H (at program level) + capmt[length++] = 0x00; // program_info_length L } void cCiCaPmt::AddPid(int Pid) { + //XXX buffer overflow check??? capmt[length++] = 0x00; //XXX stream_type (apparently doesn't matter) capmt[length++] = (Pid >> 8) & 0xFF; capmt[length++] = Pid & 0xFF; esInfoLengthPos = length; + capmt[length++] = 0x00; // ES_info_length H (at ES level) + capmt[length++] = 0x00; // ES_info_length L } void cCiCaPmt::AddCaDescriptor(int Length, uint8_t *Data) { if (esInfoLengthPos) { - if (esInfoLengthPos == length) { - length += 2; - capmt[length++] = CPCI_OK_DESCRAMBLING; - } if (length + Length < int(sizeof(capmt))) { + capmt[length++] = CPCI_OK_DESCRAMBLING; memcpy(capmt + length, Data, Length); length += Length; int l = length - esInfoLengthPos - 2; @@ -1215,6 +1247,7 @@ void cCiCaPmt::AddCaDescriptor(int Length, uint8_t *Data) } else esyslog("ERROR: buffer overflow in CA descriptor"); + esInfoLengthPos = 0; } else esyslog("ERROR: adding CA descriptor without Pid!"); diff --git a/dvbdevice.c b/dvbdevice.c index 2e12f260..1ffe067a 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.41 2003/01/06 14:44:27 kls Exp $ + * $Id: dvbdevice.c 1.42 2003/02/02 15:31:31 kls Exp $ */ #include "dvbdevice.h" @@ -263,22 +263,15 @@ void cDvbTuner::Action(void) int length = cSIProcessor::GetCaDescriptors(channel.Source(), channel.Frequency(), channel.Sid(), sizeof(buffer), buffer); if (length > 0) { cCiCaPmt CaPmt(channel.Sid()); - if (channel.Vpid()) { + CaPmt.AddCaDescriptor(length, buffer); + if (channel.Vpid()) CaPmt.AddPid(channel.Vpid()); - CaPmt.AddCaDescriptor(length, buffer); - } - if (channel.Apid1()) { + if (channel.Apid1()) CaPmt.AddPid(channel.Apid1()); - CaPmt.AddCaDescriptor(length, buffer); - } - if (channel.Apid2()) { + if (channel.Apid2()) CaPmt.AddPid(channel.Apid2()); - CaPmt.AddCaDescriptor(length, buffer); - } - if (channel.Dpid1()) { + if (channel.Dpid1()) CaPmt.AddPid(channel.Dpid1()); - CaPmt.AddCaDescriptor(length, buffer); - } caSet = ciHandler->SetCaPmt(CaPmt); } } diff --git a/eit.c b/eit.c index 174ad6d4..eebe82c7 100644 --- a/eit.c +++ b/eit.c @@ -16,7 +16,7 @@ * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * - * $Id: eit.c 1.64 2003/01/26 12:21:15 kls Exp $ + * $Id: eit.c 1.65 2003/02/02 15:41:03 kls Exp $ ***************************************************************************/ #include "eit.h" @@ -1349,7 +1349,7 @@ void cSIProcessor::Action() /** Add a filter with packet identifier pid and table identifer tid */ -bool cSIProcessor::AddFilter(u_char pid, u_char tid) +bool cSIProcessor::AddFilter(unsigned short pid, u_char tid) { dmx_sct_filter_params sctFilterParams; memset(&sctFilterParams, 0, sizeof(sctFilterParams)); @@ -1390,7 +1390,7 @@ bool cSIProcessor::AddFilter(u_char pid, u_char tid) return false; } -bool cSIProcessor::DelFilter(u_char pid, u_char tid) +bool cSIProcessor::DelFilter(unsigned short pid, u_char tid) { for (int a = 0; a < MAX_FILTERS; a++) { diff --git a/eit.h b/eit.h index ec203eae..17fa9093 100644 --- a/eit.h +++ b/eit.h @@ -16,7 +16,7 @@ * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * - * $Id: eit.h 1.23 2003/01/04 10:12:54 kls Exp $ + * $Id: eit.h 1.24 2003/02/02 14:07:39 kls Exp $ ***************************************************************************/ #ifndef __EIT_H @@ -127,7 +127,7 @@ public: typedef struct sip_filter { - u_char pid; + unsigned short pid; u_char tid; int handle; bool inuse; @@ -155,8 +155,8 @@ private: char *fileName; bool active; void Action(void); - bool AddFilter(u_char pid, u_char tid); - bool DelFilter(u_char pid, u_char tid); + bool AddFilter(unsigned short pid, u_char tid); + bool DelFilter(unsigned short pid, u_char tid); bool ShutDownFilters(void); public: cSIProcessor(const char *FileName);