summaryrefslogtreecommitdiff
path: root/ci.c
diff options
context:
space:
mode:
authorKlaus Schmidinger <vdr@tvdr.de>2003-02-02 15:49:52 +0100
committerKlaus Schmidinger <vdr@tvdr.de>2003-02-02 15:49:52 +0100
commitb7777e230c82ddc9f7ce6bd309ac70cc9216e834 (patch)
treefa7e33ac7fd22779a192f4da5fb9b1ee25a5ec71 /ci.c
parent5693873b9b010124c33b8bc725fe178c3ca3a4f1 (diff)
downloadvdr-b7777e230c82ddc9f7ce6bd309ac70cc9216e834.tar.gz
vdr-b7777e230c82ddc9f7ce6bd309ac70cc9216e834.tar.bz2
Improved CAM handling1.1.23
Diffstat (limited to 'ci.c')
-rw-r--r--ci.c73
1 files changed, 53 insertions, 20 deletions
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!");