mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
Improved CAM support
This commit is contained in:
parent
b7777e230c
commit
777f330c77
@ -446,6 +446,7 @@ Oliver Endriss <o.endriss@gmx.de>
|
||||
Reinhard Walter Buchner <rw.buchner@freenet.de>
|
||||
for adding some satellites to 'sources.conf'
|
||||
for his help in testing tuning with "Motor-DiSEqC"
|
||||
for his help in debugging CAM support
|
||||
|
||||
Lauri Tischler <lauri.tischler@efore.fi>
|
||||
for helping to test and debug the new channel source and DiSEqC handling
|
||||
|
6
HISTORY
6
HISTORY
@ -1947,3 +1947,9 @@ Video Disk Recorder Revision History
|
||||
- Fixed a new/delete malloc/free mismatch in ringbuffer.c (thanks to Stefan
|
||||
Huelswitt for reporting this one).
|
||||
- Improved CAM handling.
|
||||
|
||||
2003-02-09: Version 1.1.24
|
||||
|
||||
- Improved CAM handling (thanks to Reinhard Walter Buchner for a great deal of help
|
||||
in debugging this). It is now possible to insert the CAM in any of the two slots,
|
||||
to insert and remove it while VDR is running and even to have two CAMs inserted.
|
||||
|
311
ci.c
311
ci.c
@ -4,15 +4,11 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: ci.c 1.3 2003/02/02 15:49:52 kls Exp $
|
||||
* $Id: ci.c 1.4 2003/02/09 11:54:22 kls Exp $
|
||||
*/
|
||||
|
||||
/* XXX TODO
|
||||
- handle slots separately
|
||||
- use return values
|
||||
- update CA descriptors in case they change
|
||||
- dynamically react on CAM insert/remove
|
||||
- implement CAM reset (per slot)
|
||||
XXX*/
|
||||
|
||||
#include "ci.h"
|
||||
@ -215,7 +211,7 @@ int cTPDU::Write(int fd)
|
||||
|
||||
int cTPDU::Read(int fd)
|
||||
{
|
||||
size = read(fd, data, sizeof(data));
|
||||
size = safe_read(fd, data, sizeof(data));
|
||||
if (size < 0) {
|
||||
esyslog("ERROR: %m");
|
||||
size = 0;
|
||||
@ -229,15 +225,15 @@ void cTPDU::Dump(bool Outgoing)
|
||||
{
|
||||
if (DumpTPDUDataTransfer) {
|
||||
#define MAX_DUMP 256
|
||||
printf("%s ", Outgoing ? "-->" : "<--");
|
||||
fprintf(stderr, "%s ", Outgoing ? "-->" : "<--");
|
||||
for (int i = 0; i < size && i < MAX_DUMP; i++)
|
||||
printf("%02X ", data[i]);
|
||||
printf("%s\n", size >= MAX_DUMP ? "..." : "");
|
||||
fprintf(stderr, "%02X ", data[i]);
|
||||
fprintf(stderr, "%s\n", size >= MAX_DUMP ? "..." : "");
|
||||
if (!Outgoing) {
|
||||
printf(" ");
|
||||
fprintf(stderr, " ");
|
||||
for (int i = 0; i < size && i < MAX_DUMP; i++)
|
||||
printf("%2c ", isprint(data[i]) ? data[i] : '.');
|
||||
printf("%s\n", size >= MAX_DUMP ? "..." : "");
|
||||
fprintf(stderr, "%2c ", isprint(data[i]) ? data[i] : '.');
|
||||
fprintf(stderr, "%s\n", size >= MAX_DUMP ? "..." : "");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -288,6 +284,7 @@ private:
|
||||
public:
|
||||
cCiTransportConnection(void);
|
||||
~cCiTransportConnection();
|
||||
int Slot(void) const { return slot; }
|
||||
int SendData(int Length, const uint8_t *Data);
|
||||
int RecvData(void);
|
||||
const uint8_t *Data(int &Length);
|
||||
@ -324,15 +321,15 @@ int cCiTransportConnection::SendTPDU(uint8_t Tag, int Length, const uint8_t *Dat
|
||||
return TPDU.Write(fd);
|
||||
}
|
||||
|
||||
#define CAM_READ_TIMEOUT 3500 // ms
|
||||
|
||||
int cCiTransportConnection::RecvTPDU(void)
|
||||
{
|
||||
//XXX poll, timeout???
|
||||
struct pollfd pfd[1];
|
||||
pfd[0].fd = fd;
|
||||
pfd[0].events = POLLIN;
|
||||
lastResponse = ERROR;
|
||||
if (poll(pfd, 1, 3500/*XXX*/) && (pfd[0].revents & POLLIN))//XXX
|
||||
if (tpdu->Read(fd) == OK && tpdu->Tcid() == tcid) {
|
||||
if (poll(pfd, 1, CAM_READ_TIMEOUT) && (pfd[0].revents & POLLIN) && tpdu->Read(fd) == OK && tpdu->Tcid() == tcid) {
|
||||
switch (state) {
|
||||
case stIDLE: break;
|
||||
case stCREATION: if (tpdu->Tag() == T_CTC_REPLY) {
|
||||
@ -363,6 +360,10 @@ int cCiTransportConnection::RecvTPDU(void)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
esyslog("ERROR: CAM: Read failed: slot %d, tcid %d\n", slot, tcid);
|
||||
Init(-1, slot, tcid);
|
||||
}
|
||||
return lastResponse;
|
||||
}
|
||||
|
||||
@ -385,11 +386,8 @@ int cCiTransportConnection::SendData(int Length, const uint8_t *Data)
|
||||
|
||||
int cCiTransportConnection::RecvData(void)
|
||||
{
|
||||
if (SendTPDU(T_RCV) == OK) {
|
||||
if (RecvTPDU() == OK) {
|
||||
//XXX
|
||||
}
|
||||
}
|
||||
if (SendTPDU(T_RCV) == OK)
|
||||
return RecvTPDU();
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
@ -403,7 +401,18 @@ int cCiTransportConnection::CreateConnection(void)
|
||||
if (state == stIDLE) {
|
||||
if (SendTPDU(T_CREATE_TC) == OK) {
|
||||
state = stCREATION;
|
||||
return OK;
|
||||
if (RecvTPDU() == T_CTC_REPLY)
|
||||
return OK;
|
||||
// the following is a workaround for CAMs that don't quite follow the specs...
|
||||
else {
|
||||
dbgprotocol("*** no reaction on T_CREATE_TC - retrying\n");
|
||||
if (RecvTPDU() == T_CTC_REPLY) {
|
||||
dbgprotocol("*** received T_CTC_REPLY\n");
|
||||
RecvTPDU();
|
||||
dbgprotocol("*** done dummy RecvTPDU()\n");
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ERROR;
|
||||
@ -412,9 +421,8 @@ int cCiTransportConnection::CreateConnection(void)
|
||||
int cCiTransportConnection::Poll(void)
|
||||
{
|
||||
if (state == stACTIVE) {
|
||||
if (SendTPDU(T_DATA_LAST) == OK) {
|
||||
if (SendTPDU(T_DATA_LAST) == OK)
|
||||
return RecvTPDU();
|
||||
}
|
||||
}
|
||||
return ERROR;
|
||||
}
|
||||
@ -428,11 +436,12 @@ private:
|
||||
int fd;
|
||||
int numSlots;
|
||||
cCiTransportConnection tc[MAX_CI_CONNECT];
|
||||
bool ResetSlot(int Slot);
|
||||
public:
|
||||
cCiTransportLayer(int Fd, int NumSlots);
|
||||
cCiTransportConnection *NewConnection(void);
|
||||
int Process(void);
|
||||
cCiTransportConnection *NewConnection(int Slot);
|
||||
bool ResetSlot(int Slot);
|
||||
bool ModuleReady(int Slot);
|
||||
cCiTransportConnection *Process(int Slot);
|
||||
};
|
||||
|
||||
cCiTransportLayer::cCiTransportLayer(int Fd, int NumSlots)
|
||||
@ -441,46 +450,28 @@ cCiTransportLayer::cCiTransportLayer(int Fd, int NumSlots)
|
||||
numSlots = NumSlots;
|
||||
for (int s = 0; s < numSlots; s++)
|
||||
ResetSlot(s);
|
||||
for (int i = 0; i < MAX_CI_CONNECT; i++)
|
||||
tc[i].Init(fd, 0/*XXX*/, i + 1);
|
||||
}
|
||||
|
||||
cCiTransportConnection *cCiTransportLayer::NewConnection(void)
|
||||
cCiTransportConnection *cCiTransportLayer::NewConnection(int Slot)
|
||||
{
|
||||
for (int i = 0; i < MAX_CI_CONNECT; i++) {
|
||||
if (tc[i].State() == stIDLE) {
|
||||
if (tc[i].CreateConnection() == OK) {
|
||||
if (tc[i].RecvTPDU() == T_CTC_REPLY)
|
||||
return &tc[i];
|
||||
}
|
||||
dbgprotocol("Creating connection: slot %d, tcid %d\n", Slot, i + 1);
|
||||
tc[i].Init(fd, Slot, i + 1);
|
||||
if (tc[i].CreateConnection() == OK)
|
||||
return &tc[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define CA_RESET_TIMEOUT 3 // seconds
|
||||
|
||||
bool cCiTransportLayer::ResetSlot(int Slot)
|
||||
{
|
||||
dbgprotocol("Resetting slot %d...", Slot);
|
||||
ca_slot_info_t sinfo;
|
||||
sinfo.num = Slot;
|
||||
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);
|
||||
dbgprotocol("ok.\n");
|
||||
return true;
|
||||
}
|
||||
else
|
||||
esyslog("ERROR: can't reset CAM slot %d: %m", Slot);
|
||||
@ -488,35 +479,55 @@ bool cCiTransportLayer::ResetSlot(int Slot)
|
||||
return false;
|
||||
}
|
||||
|
||||
int cCiTransportLayer::Process(void)
|
||||
bool cCiTransportLayer::ModuleReady(int Slot)
|
||||
{
|
||||
ca_slot_info_t sinfo;
|
||||
sinfo.num = Slot;
|
||||
if (ioctl(fd, CA_GET_SLOT_INFO, &sinfo) != -1)
|
||||
return sinfo.flags & CA_CI_MODULE_READY;
|
||||
else
|
||||
esyslog("ERROR: can't get info on CAM slot %d: %m", Slot);
|
||||
return false;
|
||||
}
|
||||
|
||||
cCiTransportConnection *cCiTransportLayer::Process(int Slot)
|
||||
{
|
||||
for (int i = 0; i < MAX_CI_CONNECT; i++) {
|
||||
cCiTransportConnection *Tc = &tc[i];
|
||||
if (Tc->State() == stACTIVE) {
|
||||
if (!Tc->DataAvailable()) {
|
||||
if (Tc->Poll() != OK)
|
||||
;//XXX continue;
|
||||
}
|
||||
switch (Tc->LastResponse()) {
|
||||
case T_REQUEST_TC:
|
||||
//XXX
|
||||
break;
|
||||
case T_DATA_MORE:
|
||||
case T_DATA_LAST:
|
||||
case T_CTC_REPLY:
|
||||
case T_SB:
|
||||
if (Tc->DataAvailable())
|
||||
Tc->RecvData();
|
||||
break;
|
||||
case TIMEOUT:
|
||||
case ERROR:
|
||||
default:
|
||||
//XXX Tc->state = stIDLE;//XXX Init()???
|
||||
if (Tc->Slot() == Slot) {
|
||||
switch (Tc->State()) {
|
||||
case stCREATION:
|
||||
case stACTIVE:
|
||||
if (!Tc->DataAvailable()) {
|
||||
if (Tc->Poll() != OK)
|
||||
;//XXX continue;
|
||||
}
|
||||
switch (Tc->LastResponse()) {
|
||||
case T_REQUEST_TC:
|
||||
//XXX
|
||||
break;
|
||||
case T_DATA_MORE:
|
||||
case T_DATA_LAST:
|
||||
case T_CTC_REPLY:
|
||||
case T_SB:
|
||||
if (Tc->DataAvailable())
|
||||
Tc->RecvData();
|
||||
break;
|
||||
case TIMEOUT:
|
||||
case ERROR:
|
||||
default:
|
||||
//XXX Tc->state = stIDLE;//XXX Init()???
|
||||
return NULL;
|
||||
break;
|
||||
}
|
||||
//XXX this will only work with _one_ transport connection per slot!
|
||||
return Tc;
|
||||
break;
|
||||
default: ;
|
||||
}
|
||||
}
|
||||
}
|
||||
return OK;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// -- cCiSession -------------------------------------------------------------
|
||||
@ -608,6 +619,7 @@ protected:
|
||||
public:
|
||||
cCiSession(int SessionId, int ResourceId, cCiTransportConnection *Tc);
|
||||
virtual ~cCiSession();
|
||||
const cCiTransportConnection *Tc(void) { return tc; }
|
||||
int SessionId(void) { return sessionId; }
|
||||
int ResourceId(void) { return resourceId; }
|
||||
virtual bool Process(int Length = 0, const uint8_t *Data = NULL);
|
||||
@ -1261,9 +1273,7 @@ cCiHandler::cCiHandler(int Fd, int NumSlots)
|
||||
for (int i = 0; i < MAX_CI_SESSION; i++)
|
||||
sessions[i] = NULL;
|
||||
tpl = new cCiTransportLayer(Fd, numSlots);
|
||||
tc = tpl->NewConnection();
|
||||
if (!tc)
|
||||
isyslog("CAM: no CAM detected");
|
||||
tc = NULL;
|
||||
}
|
||||
|
||||
cCiHandler::~cCiHandler()
|
||||
@ -1281,14 +1291,9 @@ cCiHandler *cCiHandler::CreateCiHandler(const char *FileName)
|
||||
if (ioctl(fd_ca, CA_GET_CAP, &Caps) == 0) {
|
||||
int NumSlots = Caps.slot_num;
|
||||
if (NumSlots > 0) {
|
||||
dsyslog("CAM: found %d CAM slots", NumSlots);
|
||||
if (Caps.slot_type == CA_CI_LINK) {
|
||||
cCiHandler *CiHandler = new cCiHandler(fd_ca, NumSlots);
|
||||
// drive the initial data exchange:
|
||||
for (int i = 0; i < 20; i++) //XXX make this dynamic???
|
||||
CiHandler->Process();
|
||||
return CiHandler;
|
||||
}
|
||||
//XXX dsyslog("CAM: found %d CAM slots", NumSlots); // TODO let's do this only once we can be sure that there _really_ is a CAM adapter!
|
||||
if (Caps.slot_type == CA_CI_LINK)
|
||||
return new cCiHandler(fd_ca, NumSlots);
|
||||
else
|
||||
esyslog("ERROR: CAM doesn't support link layer interface");
|
||||
}
|
||||
@ -1320,7 +1325,7 @@ bool cCiHandler::Send(uint8_t Tag, int SessionId, int ResourceId, int Status)
|
||||
*(short *)p = htons(SessionId);
|
||||
p += 2;
|
||||
buffer[1] = p - buffer - 2; // length
|
||||
return tc->SendData(p - buffer, buffer) == OK;
|
||||
return tc && tc->SendData(p - buffer, buffer) == OK;
|
||||
}
|
||||
|
||||
cCiSession *cCiHandler::GetSessionBySessionId(int SessionId)
|
||||
@ -1332,10 +1337,10 @@ cCiSession *cCiHandler::GetSessionBySessionId(int SessionId)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cCiSession *cCiHandler::GetSessionByResourceId(int ResourceId)
|
||||
cCiSession *cCiHandler::GetSessionByResourceId(int ResourceId, int Slot)
|
||||
{
|
||||
for (int i = 0; i < MAX_CI_SESSION; i++) {
|
||||
if (sessions[i] && sessions[i]->ResourceId() == ResourceId)
|
||||
if (sessions[i] && sessions[i]->Tc()->Slot() == Slot && sessions[i]->ResourceId() == ResourceId)
|
||||
return sessions[i];
|
||||
}
|
||||
return NULL;
|
||||
@ -1343,7 +1348,7 @@ cCiSession *cCiHandler::GetSessionByResourceId(int ResourceId)
|
||||
|
||||
cCiSession *cCiHandler::CreateSession(int ResourceId)
|
||||
{
|
||||
if (!GetSessionByResourceId(ResourceId)) {
|
||||
if (!GetSessionByResourceId(ResourceId, tc->Slot())) {
|
||||
for (int i = 0; i < MAX_CI_SESSION; i++) {
|
||||
if (!sessions[i]) {
|
||||
switch (ResourceId) {
|
||||
@ -1403,81 +1408,107 @@ bool cCiHandler::CloseSession(int SessionId)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cCiHandler::Process(void)
|
||||
int cCiHandler::CloseAllSessions(int Slot)
|
||||
{
|
||||
if (tc) {
|
||||
cMutexLock MutexLock(&mutex);
|
||||
if (tpl->Process() == OK) {
|
||||
int Length;
|
||||
const uint8_t *Data = tc->Data(Length);
|
||||
if (Data && Length > 1) {
|
||||
switch (*Data) {
|
||||
case ST_SESSION_NUMBER: if (Length > 4) {
|
||||
int SessionId = ntohs(*(short *)&Data[2]);
|
||||
cCiSession *Session = GetSessionBySessionId(SessionId);
|
||||
if (Session)
|
||||
return Session->Process(Length - 4, Data + 4);
|
||||
else {
|
||||
esyslog("ERROR: unknown session id: %d", SessionId);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ST_OPEN_SESSION_REQUEST: return OpenSession(Length, Data);
|
||||
case ST_CLOSE_SESSION_REQUEST: if (Length == 4)
|
||||
return CloseSession(ntohs(*(short *)&Data[2]));
|
||||
break;
|
||||
case ST_CREATE_SESSION_RESPONSE: //XXX fall through to default
|
||||
case ST_CLOSE_SESSION_RESPONSE: //XXX fall through to default
|
||||
default: esyslog("ERROR: unknown session tag: %02X", *Data);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
for (int i = 0; i < MAX_CI_SESSION; i++) {
|
||||
if (sessions[i])
|
||||
sessions[i]->Process();//XXX retval???
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
int result = 0;
|
||||
for (int i = 0; i < MAX_CI_SESSION; i++) {
|
||||
if (sessions[i] && sessions[i]->Tc()->Slot() == Slot) {
|
||||
CloseSession(sessions[i]->SessionId());
|
||||
result++;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool cCiHandler::EnterMenu(void)
|
||||
void cCiHandler::Process(void)
|
||||
{
|
||||
cMutexLock MutexLock(&mutex);
|
||||
//XXX slots???
|
||||
cCiApplicationInformation *api = (cCiApplicationInformation *)GetSessionByResourceId(RI_APPLICATION_INFORMATION);
|
||||
for (int Slot = 0; Slot < numSlots; Slot++) {
|
||||
tc = tpl->Process(Slot);
|
||||
if (tc) {
|
||||
int Length;
|
||||
const uint8_t *Data = tc->Data(Length);
|
||||
if (Data && Length > 1) {
|
||||
switch (*Data) {
|
||||
case ST_SESSION_NUMBER: if (Length > 4) {
|
||||
int SessionId = ntohs(*(short *)&Data[2]);
|
||||
cCiSession *Session = GetSessionBySessionId(SessionId);
|
||||
if (Session)
|
||||
Session->Process(Length - 4, Data + 4);
|
||||
else
|
||||
esyslog("ERROR: unknown session id: %d", SessionId);
|
||||
}
|
||||
break;
|
||||
case ST_OPEN_SESSION_REQUEST: OpenSession(Length, Data);
|
||||
break;
|
||||
case ST_CLOSE_SESSION_REQUEST: if (Length == 4)
|
||||
CloseSession(ntohs(*(short *)&Data[2]));
|
||||
break;
|
||||
case ST_CREATE_SESSION_RESPONSE: //XXX fall through to default
|
||||
case ST_CLOSE_SESSION_RESPONSE: //XXX fall through to default
|
||||
default: esyslog("ERROR: unknown session tag: %02X", *Data);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!CloseAllSessions(Slot)) {
|
||||
if (tpl->ModuleReady(Slot)) {
|
||||
dbgprotocol("Module ready in slot %d\n", Slot);
|
||||
tpl->NewConnection(Slot);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < MAX_CI_SESSION; i++) {
|
||||
if (sessions[i])
|
||||
sessions[i]->Process();
|
||||
}
|
||||
}
|
||||
|
||||
bool cCiHandler::EnterMenu(int Slot)
|
||||
{
|
||||
cMutexLock MutexLock(&mutex);
|
||||
cCiApplicationInformation *api = (cCiApplicationInformation *)GetSessionByResourceId(RI_APPLICATION_INFORMATION, Slot);
|
||||
return api ? api->EnterMenu() : false;
|
||||
}
|
||||
|
||||
cCiMenu *cCiHandler::GetMenu(void)
|
||||
{
|
||||
cMutexLock MutexLock(&mutex);
|
||||
//XXX slots???
|
||||
cCiMMI *mmi = (cCiMMI *)GetSessionByResourceId(RI_MMI);
|
||||
return mmi ? mmi->Menu() : NULL;
|
||||
for (int Slot = 0; Slot < numSlots; Slot++) {
|
||||
cCiMMI *mmi = (cCiMMI *)GetSessionByResourceId(RI_MMI, Slot);
|
||||
if (mmi)
|
||||
return mmi->Menu();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cCiEnquiry *cCiHandler::GetEnquiry(void)
|
||||
{
|
||||
cMutexLock MutexLock(&mutex);
|
||||
//XXX slots???
|
||||
cCiMMI *mmi = (cCiMMI *)GetSessionByResourceId(RI_MMI);
|
||||
return mmi ? mmi->Enquiry() : NULL;
|
||||
for (int Slot = 0; Slot < numSlots; Slot++) {
|
||||
cCiMMI *mmi = (cCiMMI *)GetSessionByResourceId(RI_MMI, Slot);
|
||||
if (mmi)
|
||||
return mmi->Enquiry();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool cCiHandler::SetCaPmt(cCiCaPmt &CaPmt)
|
||||
{
|
||||
cMutexLock MutexLock(&mutex);
|
||||
//XXX slots???
|
||||
cCiConditionalAccessSupport *cas = (cCiConditionalAccessSupport *)GetSessionByResourceId(RI_CONDITIONAL_ACCESS_SUPPORT);
|
||||
return cas ? cas->SendPMT(CaPmt) : false;
|
||||
bool result = false;
|
||||
for (int Slot = 0; Slot < numSlots; Slot++) {
|
||||
cCiConditionalAccessSupport *cas = (cCiConditionalAccessSupport *)GetSessionByResourceId(RI_CONDITIONAL_ACCESS_SUPPORT, Slot);
|
||||
if (cas)
|
||||
result |= cas->SendPMT(CaPmt);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool cCiHandler::Reset(void)
|
||||
bool cCiHandler::Reset(int Slot)
|
||||
{
|
||||
cMutexLock MutexLock(&mutex);
|
||||
//XXX slots???
|
||||
return false;//XXX not yet implemented
|
||||
CloseAllSessions(Slot);
|
||||
return tpl->ResetSlot(Slot);
|
||||
}
|
||||
|
11
ci.h
11
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 1.1 2003/01/06 12:31:09 kls Exp $
|
||||
* $Id: ci.h 1.2 2003/02/09 11:44:00 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __CI_H
|
||||
@ -86,20 +86,21 @@ private:
|
||||
int ResourceIdToInt(const uint8_t *Data);
|
||||
bool Send(uint8_t Tag, int SessionId, int ResourceId = 0, int Status = -1);
|
||||
cCiSession *GetSessionBySessionId(int SessionId);
|
||||
cCiSession *GetSessionByResourceId(int ResourceId);
|
||||
cCiSession *GetSessionByResourceId(int ResourceId, int Slot);
|
||||
cCiSession *CreateSession(int ResourceId);
|
||||
bool OpenSession(int Length, const uint8_t *Data);
|
||||
bool CloseSession(int SessionId);
|
||||
int CloseAllSessions(int Slot);
|
||||
cCiHandler(int Fd, int NumSlots);
|
||||
public:
|
||||
~cCiHandler();
|
||||
static cCiHandler *CreateCiHandler(const char *FileName);
|
||||
bool Process(void);
|
||||
bool EnterMenu(void);
|
||||
void Process(void);
|
||||
bool EnterMenu(int Slot);
|
||||
cCiMenu *GetMenu(void);
|
||||
cCiEnquiry *GetEnquiry(void);
|
||||
bool SetCaPmt(cCiCaPmt &CaPmt);
|
||||
bool Reset(void);
|
||||
bool Reset(int Slot);
|
||||
};
|
||||
|
||||
#endif //__CI_H
|
||||
|
4
config.h
4
config.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: config.h 1.147 2003/01/26 19:50:19 kls Exp $
|
||||
* $Id: config.h 1.148 2003/02/08 10:25:44 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __CONFIG_H
|
||||
@ -19,7 +19,7 @@
|
||||
#include "device.h"
|
||||
#include "tools.h"
|
||||
|
||||
#define VDRVERSION "1.1.23"
|
||||
#define VDRVERSION "1.1.24"
|
||||
|
||||
#define MAXPRIORITY 99
|
||||
#define MAXLIFETIME 99
|
||||
|
39
dvbdevice.c
39
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.42 2003/02/02 15:31:31 kls Exp $
|
||||
* $Id: dvbdevice.c 1.43 2003/02/09 11:47:02 kls Exp $
|
||||
*/
|
||||
|
||||
#include "dvbdevice.h"
|
||||
@ -238,6 +238,7 @@ bool cDvbTuner::SetFrontend(void)
|
||||
|
||||
void cDvbTuner::Action(void)
|
||||
{
|
||||
time_t StartTime = time(NULL);
|
||||
dsyslog("tuner thread started on device %d (pid=%d)", cardIndex + 1, getpid());
|
||||
active = true;
|
||||
while (active) {
|
||||
@ -258,24 +259,28 @@ void cDvbTuner::Action(void)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (ciHandler && !caSet) {//XXX TODO update in case the CA descriptors have changed
|
||||
uchar buffer[2048];
|
||||
int length = cSIProcessor::GetCaDescriptors(channel.Source(), channel.Frequency(), channel.Sid(), sizeof(buffer), buffer);
|
||||
if (length > 0) {
|
||||
cCiCaPmt CaPmt(channel.Sid());
|
||||
CaPmt.AddCaDescriptor(length, buffer);
|
||||
if (channel.Vpid())
|
||||
CaPmt.AddPid(channel.Vpid());
|
||||
if (channel.Apid1())
|
||||
CaPmt.AddPid(channel.Apid1());
|
||||
if (channel.Apid2())
|
||||
CaPmt.AddPid(channel.Apid2());
|
||||
if (channel.Dpid1())
|
||||
CaPmt.AddPid(channel.Dpid1());
|
||||
caSet = ciHandler->SetCaPmt(CaPmt);
|
||||
if (ciHandler) {
|
||||
ciHandler->Process();
|
||||
if (!caSet) {//XXX TODO update in case the CA descriptors have changed
|
||||
uchar buffer[2048];
|
||||
int length = cSIProcessor::GetCaDescriptors(channel.Source(), channel.Frequency(), channel.Sid(), sizeof(buffer), buffer);
|
||||
if (length > 0) {
|
||||
cCiCaPmt CaPmt(channel.Sid());
|
||||
CaPmt.AddCaDescriptor(length, buffer);
|
||||
if (channel.Vpid())
|
||||
CaPmt.AddPid(channel.Vpid());
|
||||
if (channel.Apid1())
|
||||
CaPmt.AddPid(channel.Apid1());
|
||||
if (channel.Apid2())
|
||||
CaPmt.AddPid(channel.Apid2());
|
||||
if (channel.Dpid1())
|
||||
CaPmt.AddPid(channel.Dpid1());
|
||||
caSet = ciHandler->SetCaPmt(CaPmt);
|
||||
}
|
||||
}
|
||||
}
|
||||
newSet.TimedWait(mutex, 1000);
|
||||
// in the beginning we loop more often to let the CAM connection start up fast
|
||||
newSet.TimedWait(mutex, (ciHandler && (time(NULL) - StartTime < 20)) ? 100 : 1000);
|
||||
}
|
||||
dsyslog("tuner thread ended on device %d (pid=%d)", cardIndex + 1, getpid());
|
||||
}
|
||||
|
22
menu.c
22
menu.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: menu.c 1.232 2003/01/19 14:59:46 kls Exp $
|
||||
* $Id: menu.c 1.233 2003/02/09 10:46:25 kls Exp $
|
||||
*/
|
||||
|
||||
#include "menu.h"
|
||||
@ -1537,6 +1537,7 @@ cMenuCam::cMenuCam(cCiMenu *CiMenu)
|
||||
Add(new cOsdItem(ciMenu->SubTitleText()));
|
||||
Add(new cOsdItem(ciMenu->BottomText()));
|
||||
Display();
|
||||
dsyslog("CAM: Menu - %s", ciMenu->TitleText());
|
||||
}
|
||||
|
||||
cMenuCam::~cMenuCam()
|
||||
@ -1622,7 +1623,6 @@ cOsdObject *CamControl(void)
|
||||
if (Device) {
|
||||
cCiHandler *CiHandler = Device->CiHandler();
|
||||
if (CiHandler) {
|
||||
CiHandler->Process();
|
||||
cCiMenu *CiMenu = CiHandler->GetMenu();
|
||||
if (CiMenu)
|
||||
return new cMenuCam(CiMenu);
|
||||
@ -2069,7 +2069,7 @@ class cMenuSetupCICAM : public cMenuSetupBase {
|
||||
private:
|
||||
int helpKeys;
|
||||
void SetHelpKeys(void);
|
||||
cCiHandler *GetCurrentCiHandler(void);
|
||||
cCiHandler *GetCurrentCiHandler(int *Slot = NULL);
|
||||
eOSState Menu(void);
|
||||
eOSState Reset(void);
|
||||
public:
|
||||
@ -2091,9 +2091,11 @@ cMenuSetupCICAM::cMenuSetupCICAM(void)
|
||||
SetHelpKeys();
|
||||
}
|
||||
|
||||
cCiHandler *cMenuSetupCICAM::GetCurrentCiHandler(void)
|
||||
cCiHandler *cMenuSetupCICAM::GetCurrentCiHandler(int *Slot)
|
||||
{
|
||||
cDevice *Device = cDevice::GetDevice(Current() / 2);
|
||||
if (Slot)
|
||||
*Slot = Current() % 2;
|
||||
return Device ? Device->CiHandler() : NULL;
|
||||
}
|
||||
|
||||
@ -2112,8 +2114,9 @@ void cMenuSetupCICAM::SetHelpKeys(void)
|
||||
|
||||
eOSState cMenuSetupCICAM::Menu(void)
|
||||
{
|
||||
cCiHandler *CiHandler = GetCurrentCiHandler();
|
||||
if (CiHandler && CiHandler->EnterMenu())
|
||||
int Slot = 0;
|
||||
cCiHandler *CiHandler = GetCurrentCiHandler(&Slot);
|
||||
if (CiHandler && CiHandler->EnterMenu(Slot))
|
||||
return osEnd; // the CAM menu will be executed explicitly from the main loop
|
||||
else
|
||||
Interface->Error(tr("Can't open CAM menu!"));
|
||||
@ -2122,9 +2125,12 @@ eOSState cMenuSetupCICAM::Menu(void)
|
||||
|
||||
eOSState cMenuSetupCICAM::Reset(void)
|
||||
{
|
||||
cCiHandler *CiHandler = GetCurrentCiHandler();
|
||||
if (CiHandler && CiHandler->Reset())
|
||||
int Slot = 0;
|
||||
cCiHandler *CiHandler = GetCurrentCiHandler(&Slot);
|
||||
if (CiHandler && CiHandler->Reset(Slot)) {
|
||||
Interface->Info(tr("CAM has been reset"));
|
||||
return osEnd;
|
||||
}
|
||||
else
|
||||
Interface->Error(tr("Can't reset CAM!"));
|
||||
return osContinue;
|
||||
|
4
vdr.c
4
vdr.c
@ -22,7 +22,7 @@
|
||||
*
|
||||
* The project's page is at http://www.cadsoft.de/people/kls/vdr
|
||||
*
|
||||
* $Id: vdr.c 1.141 2003/01/26 11:56:31 kls Exp $
|
||||
* $Id: vdr.c 1.142 2003/02/09 11:25:38 kls Exp $
|
||||
*/
|
||||
|
||||
#include <getopt.h>
|
||||
@ -469,7 +469,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
// CAM control:
|
||||
if (!Menu)
|
||||
if (!Interface->IsOpen())
|
||||
Menu = CamControl();
|
||||
// User Input:
|
||||
cOsdObject *Interact = Menu ? Menu : cControl::Control();
|
||||
|
Loading…
Reference in New Issue
Block a user