]> www.vanbest.org Git - sasc-ng.git/commitdiff
smartcards: introduce cardslot.conf
authorleslie <unknown>
Fri, 27 Feb 2009 00:01:28 +0000 (08:01 +0800)
committerleslie <unknown>
Fri, 27 Feb 2009 00:01:28 +0000 (08:01 +0800)
Makefile
README
examples/cardslot.conf.example [new file with mode: 0644]
sc.c
smartcard.c
smartcard.h

index 05fc2e92250d6ab88944a5c320ab9f115063e0c9..5a410f2fb9f4c0679de9289ae1058fd3758413db 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -110,14 +110,9 @@ endif
 # generic stuff
 #
 
-# smartcard default port
+# smartcard default port (dropped)
 ifdef DEFAULT_PORT
-  TEST := $(shell echo '$(DEFAULT_PORT)' | sed -ne '/".*",.*,.*,.*/p')
-  ifneq ($(strip $(TEST)),)
-    DEFINES += -DDEFAULT_PORT='$(DEFAULT_PORT)'
-  else
-    $(error DEFAULT_PORT has bad format)
-  endif 
+  $(error DEFAULT_PORT support was removed, use cardslot.conf)
 endif
 
 # max number of CAIDs per slot
diff --git a/README b/README
index 8eba99a15356134ce30277da875ec383a27c6bed..708eac8fd7961e3fceaa6528c15904fd326c3d1b 100644 (file)
--- a/README
+++ b/README
@@ -243,29 +243,11 @@ Smartcard support
 -----------------
 
 For most encrpytion systems this plugin supports original subscription
-smartcards on a Phoenix/Smartmouse ISO interface connected to a serial port.
-
-To enable smartcard support you have to copy one or more of the smartcard
-systems to the VDR plugin lib directory. To actually activate the smartcard
-interface, you should use the commandline option "-s" to specify one or more
-serial devices to which the Phoenix interface are connected e.g. use "-s
-/dev/ttyS0 -s /dev/ttyS1" to use two intefaces at COM1/COM2. If you want to add
-a default smartcard interface at compile time use the make option DEFAULT_PORT,
-e.g. DEFAULT_PORT='"/dev/ttyS0",0,0,0'. Note the quotes and double quotes. The
-three numeric values are identical to the -I and -R options (set to 1 to enable)
-and -C option (set to 0 for default clock) below.
-
-Appearently there are "broken" card readers which swap the meaning of the CD
-line (used for card detection). For these readers use the option "-I". This
-enables inverse CD detection for the next interface e.g. "-I -s /dev/ttyS0 -s
-/dev/ttyS1" will use inverse CD on COM1 and normal CD on COM2 while "-I -s
-/dev/ttyS0 -I -s /dev/ttyS1" will use inverse CD on both.
-Some other card readers have a reversed logic with the reset line (card won't
-reset with default settings). You can use the option "-R" for these readers.
-In some cases it's mandatory to know the exact clock frequency at which your
-cardreader runs (e.g. for baudrate calculations). With the option "-C" you can
-give a clock frequency (in Hz) which will be used instead of the default
-(3571200 Hz) for the next interface e.g. "-C 3579545 -s /dev/ttyS1".
+smartcards (e.g. from a Phoenix/Smartmouse ISO interface connected to a serial
+port).
+
+The configuartion of the smartcard slots if done in the "cardslot.conf" file
+(see example file for format).
 
 Some smartcards need additional information to establish communication with the
 card (e.g. certificate or box key for camcrypt). These information must be
diff --git a/examples/cardslot.conf.example b/examples/cardslot.conf.example
new file mode 100644 (file)
index 0000000..b5d471b
--- /dev/null
@@ -0,0 +1,13 @@
+;
+; Comment lines can start with # or ;
+;
+
+; cardslot with phoenix/smartmouse cardreader on serial port
+;
+; dev   - serial device e.g. /dev/ttyS0
+; CD    - card detect 0=normal 1=inverted
+; RST   - card reset  0=normal 1=inverted
+; clock - clock frequency in Hz. If missing or 0, default=3571200
+;
+serial:/dev/ttyS0:0:0
+serial:/dev/ttyS1:1:0:3579545
diff --git a/sc.c b/sc.c
index 6a7dcdda52261f7b90280b3b7d8fc2f747816f0e..c7c92c006e6f017eb0d7947ee8ab2a2301814ecf 100644 (file)
--- a/sc.c
+++ b/sc.c
@@ -229,9 +229,13 @@ eOSState cMenuEditHexItem::ProcessKey(eKeys Key)
 class cScInfoItem : public cOsdItem {
 private:
   void SetValue(const char *Name, const char *Value);
+  //
+  int ident;
 public:
   cScInfoItem(const char *Name, int Value, eOSState State=osUnknown);
   cScInfoItem(const char *Name, const char *Value=0, eOSState State=osUnknown);
+  void Ident(int id) { ident=id; }
+  int Ident(void) { return ident; }
   };
 
 cScInfoItem::cScInfoItem(const char *Name, int Value, eOSState State)
@@ -256,6 +260,7 @@ void cScInfoItem::SetValue(const char *Name, const char *Value)
   asprintf(&buff,Value ? "%s:\t%s":"%s",Name,Value);
   SetText(buff,false);
   cStatus::MsgOsdCurrentItem(buff);
+  ident=-1;
 }
 
 // --- cOpt --------------------------------------------------------------------
@@ -839,11 +844,6 @@ public:
   virtual eOSState ProcessKey(eKeys Key);
   };
 
-static eOSState portStates[] = { osUser1,osUser2,osUser3,osUser4 };
-#if MAX_PORTS!=4
-#error Update portStates[]
-#endif
-
 cMenuSetupSc::cMenuSetupSc(const char *CfgDir)
 {
   cfgdir=strdup(CfgDir);
@@ -860,8 +860,11 @@ cMenuSetupSc::cMenuSetupSc(const char *CfgDir)
     for(int i=0; smartcards.ListCard(i,id,sizeof(id)); i++) {
       char buff[32];
       snprintf(buff,sizeof(buff),"%s %d",tr("Smartcard interface"),i);
-      if(id[0]) Add(new cScInfoItem(buff,id,portStates[i]));
-      else      Add(new cScInfoItem(buff,tr("(empty)")));
+      cScInfoItem *ii;
+      if(id[0]) ii=new cScInfoItem(buff,id,osUser4);
+      else      ii=new cScInfoItem(buff,tr("(empty)"));
+      ii->Ident(i);
+      Add(ii);
       }
     }
   Add(new cOsdItem(tr("Status information..."),osUser8));
@@ -883,10 +886,10 @@ eOSState cMenuSetupSc::ProcessKey(eKeys Key)
 {
   eOSState state = cOsdMenu::ProcessKey(Key);
   switch(state) {
-    case osUser1...osUser4:
+    case osUser4:
       if(Feature.SmartCard()) {
-        for(unsigned int i=0; i<sizeof(portStates)/sizeof(eOSState); i++)
-          if(portStates[i]==state) return(AddSubMenu(new cMenuInfoCard(i)));
+        cScInfoItem *ii=dynamic_cast<cScInfoItem *>(Get(Current()));
+        if(ii) return(AddSubMenu(new cMenuInfoCard(ii->Ident())));
         }
       state=osContinue;
       break;
@@ -1008,12 +1011,17 @@ bool cScSetup::Ignore(unsigned short caid)
 bool cSoftCAM::Load(const char *cfgdir)
 {
   if(!Feature.KeyFile()) keys.Disable();
-  if(!Feature.SmartCard()) carddatas.Disable();
+  if(!Feature.SmartCard()) {
+    carddatas.Disable();
+    smartcards.Disable();
+    }
   cStructLoaders::Load(false);
   if(Feature.KeyFile() && keys.Count()<1)
     PRINTF(L_GEN_ERROR,"no keys loaded for softcam!");
   if(!cSystems::Init(cfgdir)) return false;
   srand(time(0));
+  if(Feature.SmartCard())
+    smartcards.LaunchWatcher();
   return true;
 }
 
@@ -1307,12 +1315,6 @@ bool cScPlugin::Start(void)
   cStructLoaders::SetCfgDir(cfgdir);
   ScSetup.Check();
   if(!cSoftCAM::Load(cfgdir)) return false;
-  if(Feature.SmartCard()) {
-#ifdef DEFAULT_PORT
-    smartcards.AddPort(DEFAULT_PORT);
-#endif
-    smartcards.LaunchWatcher();
-    }
   cScDvbDevice::Startup();
   keeper=new cScHousekeeper;
   return true;
@@ -1346,17 +1348,11 @@ const char *cScPlugin::CommandLineHelp(void)
   
   free(help_str);    //                                     for easier orientation, this is column 80|
   asprintf(&help_str,"  -B N      --budget=N     forces DVB device N to budget mode (using FFdecsa)\n"
-                     "  -I        --inverse-cd   use inverse CD detection for the next serial device\n"
-                     "  -R        --inverse-rst  use inverse RESET for the next serial device\n"
-                     "  -C FREQ   --clock=FREQ   use FREQ as clock for the card reader on the next\n"
-                     "                           serial device (rather than 3.5712 MHz\n"
-                     "  -s DEV    --serial=DEV   activate Phoenix ISO interface on serial device DEV\n"
-                     "                           (default: %s)\n"
                      "  -d CMD    --dialup=CMD   call CMD to start/stop dialup-network\n"
                      "                           (default: %s)\n"
                      "  -t SECS   --timeout=SECS shutdown timeout for dialup-network\n"
                      "                           (default: %d secs)\n",
-                     "none","none",netTimeout/1000
+                     "none",netTimeout/1000
                      );
   return help_str;
 }
@@ -1364,10 +1360,10 @@ const char *cScPlugin::CommandLineHelp(void)
 bool cScPlugin::ProcessArgs(int argc, char *argv[])
 {
   static struct option long_options[] = {
-      { "serial",      required_argument, NULL, 's' },
+      { "serial",      optional_argument, NULL, 's' },
       { "inverse-cd",  no_argument,       NULL, 'I' },
       { "inverse-rst", no_argument,       NULL, 'R' },
-      { "clock",       required_argument, NULL, 'C' },
+      { "clock",       optional_argument, NULL, 'C' },
       { "dialup",      required_argument, NULL, 'd' },
       { "external-au", required_argument, NULL, 'E' },
       { "budget",      required_argument, NULL, 'B' },
@@ -1375,14 +1371,12 @@ bool cScPlugin::ProcessArgs(int argc, char *argv[])
     };
 
   int c, option_index=0;
-  bool invCD=false, invRST=false;
-  int clock=0;
   while((c=getopt_long(argc,argv,"d:s:t:B:C:E:IR",long_options,&option_index))!=-1) {
     switch (c) {
-      case 'I': invCD=true; break;
-      case 'R': invRST=true; break;
-      case 'C': clock=atoi(optarg); break;
-      case 's': smartcards.AddPort(optarg,invCD,invRST,clock); invCD=false; invRST=false; clock=0; break;
+      case 'I':
+      case 'R':
+      case 'C':
+      case 's': fprintf(stderr,"smartcard commandline options were removed. use cardslot.conf\n"); return false;
       case 'd': netscript=optarg; break;
       case 't': netTimeout=atoi(optarg)*1000; break;
       case 'E': externalAU=optarg; break;
index fa7f73df897a3c4d988830bfef02b6f3d8938710..ef1bc51e86e73da51d87de946963ba46ed04bc39 100644 (file)
@@ -35,7 +35,6 @@
 #include "misc.h"
 #include "log-core.h"
 
-#define DATAFILE "smartcard.conf"
 #define ISO_FREQ 3571200 // Hz
 
 //#define SER_EMU   // use serial emulation (select one of the following)
@@ -748,6 +747,61 @@ void cInfoStr::Finish()
   current=Grab();
 }
 
+// -- cSmartCardData -----------------------------------------------------------
+
+cSmartCardData::cSmartCardData(int Ident)
+{
+  ident=Ident;
+}
+
+// -- cSmartCardDatas ----------------------------------------------------------
+
+cSmartCardDatas carddatas;
+
+cSmartCardDatas::cSmartCardDatas(void)
+:cStructList<cSmartCardData>("smartcard data","smartcard.conf",SL_MISSINGOK|SL_WATCH|SL_VERBOSE)
+{}
+
+cSmartCardData *cSmartCardDatas::Find(cSmartCardData *param)
+{
+  ListLock(false);
+  cSmartCardData *cd;
+  for(cd=First(); cd; cd=Next(cd))
+    if(cd->Ident()==param->Ident() && cd->Matches(param)) break;
+  ListUnlock();
+  return cd;
+}
+
+cStructItem *cSmartCardDatas::ParseLine(char *line)
+{
+  char *r=index(line,':');
+  if(r)
+    for(cSmartCardLink *scl=cSmartCards::first; scl; scl=scl->next)
+      if(!strncasecmp(scl->name,line,r-line)) {
+        cSmartCardData *scd=scl->CreateData();
+        if(scd && scd->Parse(r+1)) return scd;
+        delete scd;
+        break;
+        }
+  return 0;
+}
+
+// -- cSmartCardSlot -----------------------------------------------------------
+
+cSmartCardSlot::cSmartCardSlot(int num)
+{
+  Serial=0; Card=0;
+  CardId=0; UseCount=0; Dead=false;
+  SlotNum=num;
+  Clock=ISO_FREQ;
+}
+
+cSmartCardSlot::~cSmartCardSlot()
+{
+  delete Card;
+  delete Serial;
+}
+
 // -- cSmartCard ---------------------------------------------------------------
 
 static const int Ftable[16] = {
@@ -1086,45 +1140,6 @@ int cSmartCard::CheckSctLen(const unsigned char *data, int off)
   return l;
 }
 
-// -- cSmartCardData -----------------------------------------------------------
-
-cSmartCardData::cSmartCardData(int Ident)
-{
-  ident=Ident;
-}
-
-// -- cSmartCardDatas ----------------------------------------------------------
-
-cSmartCardDatas carddatas;
-
-cSmartCardDatas::cSmartCardDatas(void)
-:cStructList<cSmartCardData>("smartcard data",DATAFILE,SL_MISSINGOK|SL_WATCH|SL_VERBOSE)
-{}
-
-cSmartCardData *cSmartCardDatas::Find(cSmartCardData *param)
-{
-  ListLock(false);
-  cSmartCardData *cd;
-  for(cd=First(); cd; cd=Next(cd))
-    if(cd->Ident()==param->Ident() && cd->Matches(param)) break;
-  ListUnlock();
-  return cd;
-}
-
-cStructItem *cSmartCardDatas::ParseLine(char *line)
-{
-  char *r=index(line,':');
-  if(r)
-    for(cSmartCardLink *scl=cSmartCards::first; scl; scl=scl->next)
-      if(!strncasecmp(scl->name,line,r-line)) {
-        cSmartCardData *scd=scl->CreateData();
-        if(scd && scd->Parse(r+1)) return scd;
-        delete scd;
-        break;
-        }
-  return 0;
-}
-
 // -- cSmartCardLink -----------------------------------------------------------
 
 cSmartCardLink::cSmartCardLink(const char *Name, int Id)
@@ -1143,8 +1158,8 @@ static const char *serModes[] = { 0,"8e2","8o2","8n2" };
 
 cSmartCards::cSmartCards(void)
 :cThread("SmartcardWatcher")
+,cStructListPlain<cSmartCardSlot>("cardslot config","cardslot.conf",SL_MISSINGOK|SL_VERBOSE|SL_NOPURGE)
 {
-  for(int i=0 ; i<MAX_PORTS ; i++) ports[i].Serial=0;
   firstRun=true;
 }
 
@@ -1157,63 +1172,67 @@ void cSmartCards::Register(cSmartCardLink *scl)
 
 void cSmartCards::LaunchWatcher(void)
 {
-  for(int i=0 ; i<MAX_PORTS ; i++)
-    if(ports[i].Serial) { Start(); return; }
-  firstRun=false;
-  PRINTF(L_GEN_WARN,"no smartcard interface defined!");
+  firstRun=true;
+  if(Count()>0) Start();
+  else {
+    firstRun=false;
+    PRINTF(L_GEN_WARN,"no smartcard slot defined!");
+    }
 }
 
 void cSmartCards::Shutdown(void)
+{
+  PreLoad();
+}
+
+void cSmartCards::PreLoad(void)
 {
   Cancel(3);
   mutex.Lock();
-  for(int i=0 ; i<MAX_PORTS ; i++) {
-    if(ports[i].Serial) {
-      delete ports[i].Card;
-      delete ports[i].Serial;
-      ports[i].Serial=0;
-      }
-    }
+  Clear(); Modified(false);
   mutex.Unlock();
 }
 
-bool cSmartCards::AddPort(const char *devName, bool invCD, bool invRST, int clock)
+bool cSmartCards::ParseLinePlain(const char *line)
 {
-  cMutexLock lock(&mutex);
-  for(int i=0 ; i<MAX_PORTS ; i++) {
-    if(!ports[i].Serial) {
-      cSerial *ser=new cSerial(devName,invCD,invRST);
-      if(ser && ser->Open()) {
-        ports[i].Card=0;
-        ports[i].CardId=0;
-        ports[i].UseCount=0;
-        ports[i].Dead=false;
-        ports[i].PortNum=i;
-        ports[i].Serial=ser;
-        ports[i].Clock=clock ? clock : ISO_FREQ;
-        PRINTF(L_CORE_LOAD,"smartcards: added serial port %s as port %d (%s CD, %s RESET, CLOCK %d)",
-                  devName,i,invCD?"inverse":"normal",invRST?"inverse":"normal",ports[i].Clock);
-        return true;
+  char type[32];
+  int num;
+  if(sscanf(line,"%31[^:]:%n",type,&num)==1) {
+    if(!strcasecmp(type,"serial")) {
+      int invCD=0, invRST=0, clock=0;
+      char devName[64];
+      if(sscanf(&line[num],"%63[^:]:%d:%d:%d",devName,&invCD,&invRST,&clock)>=3) {
+        cSmartCardSlot *slot=new cSmartCardSlot(Count());
+        if(slot) {
+          cSerial *ser=new cSerial(devName,invCD,invRST);
+          if(ser && ser->Open()) {
+            slot->Serial=ser;
+            if(clock>0) slot->Clock=clock;
+            Add(slot);
+            PRINTF(L_CORE_LOAD,"smartcards: added serial port %s as port %d (%s CD, %s RESET, CLOCK %d)",
+                      devName,slot->SlotNum,invCD?"inverse":"normal",invRST?"inverse":"normal",slot->Clock);
+            return true;
+            }
+          else PRINTF(L_GEN_ERROR,"failed to open serial port %s",devName);
+          delete ser;
+          delete slot;
+          }
+        else PRINTF(L_GEN_ERROR,"failed to create cardslot");
         }
-      PRINTF(L_GEN_ERROR,"failed to open serial port %s",devName);
-      delete ser;
-      return false;
-      }
-    else if(!strcmp(ports[i].Serial->DeviceName(),devName)) {
-      PRINTF(L_GEN_ERROR,"duplicate serial port %s. Check your config!",devName);
-      return false;
+      else PRINTF(L_GEN_ERROR,"bad parameter for cardslot type '%s'",type);
       }
+    else PRINTF(L_GEN_ERROR,"unknown cardslot type '%s'",type);
     }
-  PRINTF(L_GEN_ERROR,"only %d serial ports supported",MAX_PORTS);
   return false;
 }
 
+
 bool cSmartCards::HaveCard(int id)
 {
   cMutexLock lock(&mutex);
   while(Running() && firstRun) cond.Wait(mutex);
-  for(int i=0 ; i<MAX_PORTS ; i++)
-    if(ports[i].Serial && ports[i].CardId==id) return true;
+  for(cSmartCardSlot *slot=First(); slot; slot=Next(slot))
+    if(slot->CardId==id) return true;
   return false;
 }
 
@@ -1221,18 +1240,18 @@ cSmartCard *cSmartCards::LockCard(int id)
 {
   mutex.Lock();
   while(Running() && firstRun) cond.Wait(mutex);
-  for(int i=0 ; i<MAX_PORTS ; i++) {
-    if(ports[i].Serial && ports[i].CardId==id) {
-      ports[i].UseCount++;
+  for(cSmartCardSlot *slot=First(); slot; slot=Next(slot)) {
+    if(slot->CardId==id) {
+      slot->UseCount++;
       mutex.Unlock();
-      cSmartCard *sc=ports[i].Card;
+      cSmartCard *sc=slot->Card;
       sc->Lock();
-      if(CardInserted(ports[i].Serial) && sc->CardUp() && !sc->NeedsReset())
+      if(CardInserted(slot->Serial) && sc->CardUp() && !sc->NeedsReset())
         return sc;
       // if failed, unlock the card and decrement UseCount
       sc->Unlock();
       mutex.Lock();
-      ports[i].UseCount--;
+      slot->UseCount--;
       cond.Broadcast();
       break;
       }
@@ -1245,9 +1264,9 @@ void cSmartCards::ReleaseCard(cSmartCard *sc)
 {
   sc->Unlock();
   mutex.Lock();
-  for(int i=0 ; i<MAX_PORTS ; i++) {
-    if(ports[i].Card==sc) {
-      ports[i].UseCount--;
+  for(cSmartCardSlot *slot=First(); slot; slot=Next(slot)) {
+    if(slot->Card==sc) {
+      slot->UseCount--;
       cond.Broadcast();
       mutex.Unlock();
       return;
@@ -1262,37 +1281,37 @@ bool cSmartCards::CardInserted(cSerial *ser)
   return ser->CheckCAR();
 }
 
-bool cSmartCards::CardReset(struct Port *port)
+bool cSmartCards::CardReset(cSmartCardSlot *port)
 {
-  if(Reset(port)<2 || !cSmartCard::ParseAtr(&port->Atr,port->PortNum,port->Clock))
+  if(Reset(port)<2 || !cSmartCard::ParseAtr(&port->Atr,port->SlotNum,port->Clock))
     return false;
   if(!DoPTS(port)) {
     // reset card again and continue without PTS
-    if(Reset(port)<2 || !cSmartCard::ParseAtr(&port->Atr,port->PortNum,port->Clock))
+    if(Reset(port)<2 || !cSmartCard::ParseAtr(&port->Atr,port->SlotNum,port->Clock))
       return false;
     }
   return true;
 }
 
-int cSmartCards::Reset(struct Port *port)
+int cSmartCards::Reset(cSmartCardSlot *port)
 {
   cSerial *ser=port->Serial;
-  PRINTF(L_CORE_SC,"%d: reseting card (sermode %s)",port->PortNum,serModes[ser->CurrentMode()]);
+  PRINTF(L_CORE_SC,"%d: reseting card (sermode %s)",port->SlotNum,serModes[ser->CurrentMode()]);
   ser->ToggleRTS();
   cCondWait::SleepMs(100);
   ser->ToggleRTS();
   int r=ser->Read(port->Atr.atr,-MAX_ATR_LEN,800,2000);
   port->Atr.atrLen=r;
-  if(r>0) LDUMP(L_CORE_SC,port->Atr.atr,r,"%d: <- ATR len=%d:",port->PortNum,r);
+  if(r>0) LDUMP(L_CORE_SC,port->Atr.atr,r,"%d: <- ATR len=%d:",port->SlotNum,r);
   return r;
 }
 
-bool cSmartCards::DoPTS(struct Port *port)
+bool cSmartCards::DoPTS(cSmartCardSlot *port)
 {
   const struct Atr *atr=&port->Atr;
   if(atr->F!=372 || atr->D!=1.0) { // PTS required
     cSerial *ser=port->Serial;
-    const int id=port->PortNum;
+    const int id=port->SlotNum;
     int baud=(int)((float)port->Clock*atr->D/atr->F);
     PRINTF(L_CORE_SC,"%d: PTS cycle: calculated baudrate %d",id,baud);
 
@@ -1341,7 +1360,7 @@ bool cSmartCards::DoPTS(struct Port *port)
  return true;
 }
 
-void cSmartCards::SetPort(struct Port *port, cSmartCard *sc, int id, bool dead)
+void cSmartCards::SetPort(cSmartCardSlot *port, cSmartCard *sc, int id, bool dead)
 {
   mutex.Lock();
   while(port->UseCount) cond.Wait(mutex);
@@ -1356,63 +1375,62 @@ void cSmartCards::SetPort(struct Port *port, cSmartCard *sc, int id, bool dead)
 void cSmartCards::Action(void)
 {
   while(Running()) {
-    for(int i=0 ; i<MAX_PORTS ;) {
-      struct Port *port=&ports[i];
-      cSerial *ser=port->Serial;
+  for(cSmartCardSlot *slot=First(); slot;) {
+      cSerial *ser=slot->Serial;
       if(ser) {
-        if(port->Card) {
-          cSmartCard *sc=port->Card;
+        if(slot->Card) {
+          cSmartCard *sc=slot->Card;
           sc->Lock();
           if(!CardInserted(ser)) {
             sc->Unlock(); sc=0;
-            PRINTF(L_CORE_SC,"%d: card removed (UseCount=%d)",port->PortNum,port->UseCount);
-            SetPort(port,0,0,false);
+            PRINTF(L_CORE_SC,"%d: card removed (UseCount=%d)",slot->SlotNum,slot->UseCount);
+            SetPort(slot,0,0,false);
             }
           else if(sc->NeedsReset()) {
-            PRINTF(L_CORE_SC,"%d: card reset requested",port->PortNum);
+            PRINTF(L_CORE_SC,"%d: card reset requested",slot->SlotNum);
             if(!ser->SetMode(ser->CurrentMode()&SM_MASK)
-                || !CardReset(port)
-                || !sc->Setup(ser,&port->Atr,port->PortNum)) {
+                || !CardReset(slot)
+                || !sc->Setup(ser,&slot->Atr,slot->SlotNum)) {
               sc->Unlock(); sc=0;
-              PRINTF(L_CORE_SC,"%d: card re-init failed",port->PortNum);
-              SetPort(port,0,0,true);
+              PRINTF(L_CORE_SC,"%d: card re-init failed",slot->SlotNum);
+              SetPort(slot,0,0,true);
               }
             }
           if(sc) sc->Unlock();
           }
         else if(CardInserted(ser)) {
-          if(!port->Dead) {
-            PRINTF(L_CORE_SC,"%d: new card inserted",port->PortNum);
+          if(!slot->Dead) {
+            PRINTF(L_CORE_SC,"%d: new card inserted",slot->SlotNum);
             for(int mode=SM_NONE+1 ; mode<SM_MAX ; mode++) {
               if(ser->SetMode(mode)) {
-                if(CardReset(port)) {
+                if(CardReset(slot)) {
                   cSmartCardLink *scl=first;
                   while(scl) {
-                    PRINTF(L_CORE_SC,"%d: checking for %s card",port->PortNum,scl->name);
+                    PRINTF(L_CORE_SC,"%d: checking for %s card",slot->SlotNum,scl->name);
                     cSmartCard *sc=scl->Create();
-                    if(sc && sc->Setup(ser,&port->Atr,port->PortNum)) {
-                      SetPort(port,sc,scl->id,false);
+                    if(sc && sc->Setup(ser,&slot->Atr,slot->SlotNum)) {
+                      SetPort(slot,sc,scl->id,false);
                       goto next; // ugly, any better solution?
                       }
                     delete sc;
                     scl=scl->next;
                     }
-                  PRINTF(L_CORE_SC,"%d: no card handler found",port->PortNum);
+                  PRINTF(L_CORE_SC,"%d: no card handler found",slot->SlotNum);
                   }
-                else PRINTF(L_CORE_SC,"%d: reset/atr error",port->PortNum);
+                else PRINTF(L_CORE_SC,"%d: reset/atr error",slot->SlotNum);
                 }
-              else PRINTF(L_CORE_SC,"%d: failed to set serial mode %s",port->PortNum,serModes[mode]);
+              else PRINTF(L_CORE_SC,"%d: failed to set serial mode %s",slot->SlotNum,serModes[mode]);
               }
-            port->Dead=true;
-            PRINTF(L_CORE_SC,"%d: can't initialise new card, ignoring port until card reinserted",port->PortNum);
+            slot->Dead=true;
+            PRINTF(L_CORE_SC,"%d: can't initialise new card, ignoring port until card reinserted",slot->SlotNum);
             }
           }
         else {
-          if(port->Dead) PRINTF(L_CORE_SC,"%d: card removed, port reactivated",port->PortNum);
-          port->Dead=false;
+          if(slot->Dead) PRINTF(L_CORE_SC,"%d: card removed, port reactivated",slot->SlotNum);
+          slot->Dead=false;
           }
         }
-next: i++;
+next: slot=Next(slot);
       }
     if(firstRun) {
       mutex.Lock();
@@ -1424,17 +1442,25 @@ next: i++;
     }  
 }
 
+cSmartCardSlot *cSmartCards::GetSlot(int num)
+{
+  for(cSmartCardSlot *slot=First(); slot; slot=Next(slot))
+    if(slot->SlotNum==num) return slot;
+  return 0;
+}
+
 bool cSmartCards::ListCard(int num, char *str, int len)
 {
-  if(num>=MAX_PORTS || !ports[num].Serial) return false;
+  cSmartCardSlot *slot=GetSlot(num);
+  if(!slot) return false;
   str[0]=0;
   mutex.Lock();
-  cSmartCard *sc=ports[num].Card;
+  cSmartCard *sc=slot->Card;
   if(sc) {
     if(!sc->GetCardIdStr(str,len)) {
       cSmartCardLink *scl=first;
       while(scl) {
-        if(scl->id==ports[num].CardId) {
+        if(scl->id==slot->CardId) {
           strn0cpy(str,scl->name,len);
           break;
           }
@@ -1449,10 +1475,11 @@ bool cSmartCards::ListCard(int num, char *str, int len)
 bool cSmartCards::CardInfo(int num, char *str, int len)
 {
   bool res=false;
-  if(num<MAX_PORTS && ports[num].Serial) {
+  cSmartCardSlot *slot=GetSlot(num);
+  if(slot) {
     str[0]=0;
     mutex.Lock();
-    cSmartCard *sc=ports[num].Card;
+    cSmartCard *sc=slot->Card;
     if(sc) res=sc->GetCardInfoStr(str,len);
     mutex.Unlock();
     }
@@ -1461,9 +1488,10 @@ bool cSmartCards::CardInfo(int num, char *str, int len)
 
 void cSmartCards::CardReset(int num)
 {
-  if(num<MAX_PORTS && ports[num].Serial) {
+  cSmartCardSlot *slot=GetSlot(num);
+  if(slot) {
     mutex.Lock();
-    cSmartCard *sc=ports[num].Card;
+    cSmartCard *sc=slot->Card;
     if(sc) sc->TriggerReset();
     mutex.Unlock();
     }
index e7a9ed0c25f0e5b5a2a884457b8f8dceec26cef9..63c1ed94eb7139789da9f9f4b01180b7bfcba8cd 100644 (file)
@@ -61,6 +61,31 @@ public:
 
 // ----------------------------------------------------------------
 
+class cSmartCardData : public cStructItem {
+protected:
+  int ident;
+public:
+  cSmartCardData(int Ident);
+  virtual ~cSmartCardData() {}
+  virtual bool Parse(const char *line)=0;
+  virtual bool Matches(cSmartCardData *cmp)=0;
+  int Ident(void) const { return ident; }
+  };
+
+// ----------------------------------------------------------------
+
+class cSmartCardDatas : public cStructList<cSmartCardData> {
+protected:
+  virtual cStructItem *ParseLine(char *line);
+public:
+  cSmartCardDatas(void);
+  cSmartCardData *Find(cSmartCardData *param);
+  };
+
+extern cSmartCardDatas carddatas;
+
+// ----------------------------------------------------------------
+
 #define SM_NONE 0
 #define SM_8E2  1
 #define SM_8O2  2
@@ -139,29 +164,18 @@ public:
 
 // ----------------------------------------------------------------
 
-class cSmartCardData : public cStructItem {
-protected:
-  int ident;
+class cSmartCardSlot : public cStructItem {
 public:
-  cSmartCardData(int Ident);
-  virtual ~cSmartCardData() {}
-  virtual bool Parse(const char *line)=0;
-  virtual bool Matches(cSmartCardData *cmp)=0;
-  int Ident(void) const { return ident; }
-  };
-
-// ----------------------------------------------------------------
-
-class cSmartCardDatas : public cStructList<cSmartCardData> {
-protected:
-  virtual cStructItem *ParseLine(char *line);
-public:
-  cSmartCardDatas(void);
-  cSmartCardData *Find(cSmartCardData *param);
+  cSmartCardSlot(int num);
+  ~cSmartCardSlot();
+  //
+  cSerial *Serial;
+  bool Dead;
+  cSmartCard *Card;
+  int CardId, UseCount, SlotNum, Clock;
+  struct Atr Atr;
   };
 
-extern cSmartCardDatas carddatas;
-
 // ----------------------------------------------------------------
 
 class cSmartCardLink {
@@ -178,34 +192,26 @@ public:
 
 // ----------------------------------------------------------------
 
-#define MAX_PORTS 4
-
-struct Port {
-  cSerial *Serial;
-  bool Dead;
-  cSmartCard *Card;
-  int CardId, UseCount, PortNum, Clock;
-  struct Atr Atr;
-  };
-
-class cSmartCards : private cThread {
+class cSmartCards : private cThread, public cStructListPlain<cSmartCardSlot> {
 friend class cSmartCardLink;
 friend class cSmartCardDatas;
 private:
   static cSmartCardLink *first;
   cMutex mutex;
   cCondVar cond;
-  struct Port ports[MAX_PORTS];
   bool firstRun;
   //
   static void Register(cSmartCardLink *scl);
   bool CardInserted(cSerial *ser);
-  bool CardReset(struct Port *port);
-  int Reset(struct Port *port);
-  bool DoPTS(struct Port *port);
-  void SetPort(struct Port *port, cSmartCard *sc, int id, bool dead);
+  bool CardReset(cSmartCardSlot *port);
+  int Reset(cSmartCardSlot *port);
+  bool DoPTS(cSmartCardSlot *port);
+  void SetPort(cSmartCardSlot *port, cSmartCard *sc, int id, bool dead);
+  cSmartCardSlot *GetSlot(int num);
 protected:
   virtual void Action(void);
+  virtual void PreLoad(void);
+  virtual bool ParseLinePlain(const char *line);
 public:
   cSmartCards(void);
   void Shutdown(void);
@@ -214,7 +220,6 @@ public:
   cSmartCard *LockCard(int id);
   void ReleaseCard(cSmartCard *sc);
   // to be called ONLY from frontend thread!
-  bool AddPort(const char *devName, bool invCD, bool invRST, int clock);
   void LaunchWatcher(void);
   bool ListCard(int num, char *str, int len);
   bool CardInfo(int num, char *str, int len);