diff options
| -rw-r--r-- | CONTRIBUTORS | 1 | ||||
| -rw-r--r-- | HISTORY | 6 | ||||
| -rw-r--r-- | ci.c | 311 | ||||
| -rw-r--r-- | ci.h | 11 | ||||
| -rw-r--r-- | config.h | 4 | ||||
| -rw-r--r-- | dvbdevice.c | 39 | ||||
| -rw-r--r-- | menu.c | 22 | ||||
| -rw-r--r-- | vdr.c | 4 | 
8 files changed, 224 insertions, 174 deletions
| diff --git a/CONTRIBUTORS b/CONTRIBUTORS index ae550b81..a6663d9a 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -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 @@ -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. @@ -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) -{ -  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??? +int cCiHandler::CloseAllSessions(int Slot) +{ +  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; +} + +void cCiHandler::Process(void) +{ +  cMutexLock MutexLock(&mutex); +  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); +              }              } -        } -     } -  return false; +         } +      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(void) +bool cCiHandler::EnterMenu(int Slot)  {    cMutexLock MutexLock(&mutex); -  //XXX slots??? -  cCiApplicationInformation *api = (cCiApplicationInformation *)GetSessionByResourceId(RI_APPLICATION_INFORMATION); +  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);  } @@ -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,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 diff --git a/dvbdevice.c b/dvbdevice.c index 1ffe067a..01d828fa 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.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());  } @@ -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; @@ -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(); | 
