|
SASC
DVBSoftCAM
|
00001 /* 00002 * Softcam plugin to VDR (C++) 00003 * 00004 * This code is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This code is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software 00016 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00017 * Or, point your browser to http://www.gnu.org/copyleft/gpl.html 00018 */ 00019 00020 #include <stdlib.h> 00021 #include <string.h> 00022 #include <errno.h> 00023 #include <fcntl.h> 00024 #include <sys/ioctl.h> 00025 #include <sys/poll.h> 00026 #include <unistd.h> 00027 #include <termios.h> 00028 #include <linux/serial.h> 00029 #include <ctype.h> 00030 00031 #include <vdr/tools.h> 00032 #include <vdr/thread.h> 00033 00034 #include "smartcard.h" 00035 #include "global.h" 00036 #include "misc.h" 00037 #include "log-core.h" 00038 00039 #define ISO_FREQ 3571200 // Hz 00040 #define ISO_BAUD 9600 00041 00042 //#define CARD_EMU // include smartcard emulation code 00043 //#define NO_PTS_PROTO // disable PTS protocol (baudrate changes) 00044 00045 // -- cSmartCardSlot ----------------------------------------------------------- 00046 00047 class cSmartCardSlot : private cThread, public cStructItem { 00048 private: 00049 cSmartCard *card; 00050 int usecount, cardid; 00051 bool firstRun, needsReset, dead; 00052 cMutex mutex; 00053 cCondVar cond; 00054 // 00055 void SetCard(cSmartCard *c, int cid=0); 00056 bool CardReset(void); 00057 protected: 00058 virtual bool DeviceOpen(const char *cfg)=0; 00059 virtual void DeviceClose(void) {} 00060 virtual bool DeviceSetMode(int mode, int baud)=0; 00061 virtual int DeviceRead(unsigned char *mem, int len, int timeout, int initialTimeout=0)=0; 00062 virtual int DeviceWrite(const unsigned char *mem, int len, int delay=0)=0; 00063 virtual void DeviceToggleReset(void)=0; 00064 virtual bool DevicePTS(void)=0; 00065 virtual bool DeviceIsInserted(void)=0; 00066 virtual int DeviceCurrentMode(void) { return currMode; } 00067 // 00068 virtual void Action(void); 00069 // 00070 int Procedure(unsigned char ins, int restLen); 00071 int Read(unsigned char *data, int len, int to=0); 00072 int Write(const unsigned char *data, int len); 00073 bool Test(bool res); 00074 void Invert(unsigned char *data, int n); 00075 virtual bool Reset(void); 00076 bool ParseAtr(void); 00077 // 00078 int slotnum, clock; 00079 const struct CardConfig *cfg; 00080 unsigned char sb[SB_LEN]; 00081 struct Atr atr; 00082 bool localecho, singlereset; 00083 // 00084 char devName[256]; 00085 int currMode; 00086 public: 00087 cSmartCardSlot(void); 00088 virtual ~cSmartCardSlot(); 00089 bool Setup(int num, const char *cfg); 00090 void SetCardConfig(const struct CardConfig *Cfg) { cfg=Cfg; } 00091 void TriggerReset(void) { needsReset=true; } 00092 bool HaveCard(int id); 00093 cSmartCard *LockCard(int id); 00094 void ReleaseCard(cSmartCard *sc); 00095 void GetCardIdStr(char *str, int len); 00096 bool GetCardInfoStr(char *str, int len); 00097 int SlotNum(void) { return slotnum; } 00098 // 00099 virtual bool IsoRead(const unsigned char *cmd, unsigned char *data); 00100 virtual bool IsoWrite(const unsigned char *cmd, const unsigned char *data); 00101 virtual int RawRead(unsigned char *data, int len, int to=0); 00102 virtual int RawWrite(const unsigned char *data, int len); 00103 }; 00104 00105 static const char *serModes[] = { 0,"8e2","8o2","8n2" }; 00106 00107 cSmartCardSlot::cSmartCardSlot(void) 00108 { 00109 card=0; cfg=0; usecount=0; slotnum=-1; currMode=SM_NONE; clock=ISO_FREQ; 00110 firstRun=true; needsReset=false; dead=false; 00111 localecho=true; singlereset=false; 00112 } 00113 00114 cSmartCardSlot::~cSmartCardSlot() 00115 { 00116 Cancel(3); 00117 SetCard(0); 00118 DeviceClose(); 00119 } 00120 00121 bool cSmartCardSlot::Setup(int num, const char *cfg) 00122 { 00123 slotnum=num; 00124 SetDescription("CardSlot %d watcher",slotnum); 00125 if(DeviceOpen(cfg)) { 00126 firstRun=true; 00127 Start(); 00128 return true; 00129 } 00130 return false; 00131 } 00132 00133 bool cSmartCardSlot::HaveCard(int id) 00134 { 00135 cMutexLock lock(&mutex); 00136 while(Running() && firstRun) cond.Wait(mutex); 00137 return card && cardid==id; 00138 } 00139 00140 cSmartCard *cSmartCardSlot::LockCard(int id) 00141 { 00142 mutex.Lock(); 00143 while(Running() && firstRun) cond.Wait(mutex); 00144 if(card && cardid==id) { 00145 usecount++; 00146 mutex.Unlock(); 00147 card->Lock(); 00148 if(DeviceIsInserted() && card->CardUp() && !needsReset) return card; 00149 // if failed, unlock the card and decrement UseCount 00150 card->Unlock(); 00151 mutex.Lock(); 00152 usecount--; 00153 cond.Broadcast(); 00154 } 00155 mutex.Unlock(); 00156 return 0; 00157 } 00158 00159 void cSmartCardSlot::ReleaseCard(cSmartCard *sc) 00160 { 00161 if(card==sc) { 00162 card->Unlock(); 00163 mutex.Lock(); 00164 usecount--; 00165 cond.Broadcast(); 00166 mutex.Unlock(); 00167 } 00168 } 00169 00170 void cSmartCardSlot::GetCardIdStr(char *str, int len) 00171 { 00172 mutex.Lock(); 00173 if(card && !card->GetCardIdStr(str,len)) { 00174 for(cSmartCardLink *scl=smartcards.First(); scl; smartcards.Next(scl)) { 00175 if(scl->Id()==cardid) { 00176 strn0cpy(str,scl->Name(),len); 00177 break; 00178 } 00179 } 00180 } 00181 mutex.Unlock(); 00182 } 00183 00184 bool cSmartCardSlot::GetCardInfoStr(char *str, int len) 00185 { 00186 mutex.Lock(); 00187 bool res=false; 00188 if(card) res=card->GetCardInfoStr(str,len); 00189 mutex.Unlock(); 00190 return res; 00191 } 00192 00193 void cSmartCardSlot::SetCard(cSmartCard *c, int cid) 00194 { 00195 mutex.Lock(); 00196 while(usecount) cond.Wait(mutex); 00197 delete card; 00198 card=c; cardid=cid; needsReset=dead=false; 00199 mutex.Unlock(); 00200 } 00201 00202 void cSmartCardSlot::Action(void) 00203 { 00204 while(Running()) { 00205 if(card) { 00206 card->Lock(); 00207 if(!DeviceIsInserted()) { 00208 card->Unlock(); 00209 PRINTF(L_CORE_SC,"%d: card removed (usecount=%d)",slotnum,usecount); 00210 SetCard(0); 00211 } 00212 else if(needsReset) { 00213 PRINTF(L_CORE_SC,"%d: card reset requested",slotnum); 00214 int mode=DeviceCurrentMode()&SM_MASK; 00215 if(!DeviceSetMode(mode,ISO_BAUD) 00216 || !CardReset() 00217 || !card->Setup(this,mode,&atr,sb)) { 00218 card->Unlock(); 00219 PRINTF(L_CORE_SC,"%d: card re-init failed",slotnum); 00220 SetCard(0); dead=true; 00221 } 00222 } 00223 if(card) card->Unlock(); 00224 } 00225 else if(DeviceIsInserted()) { 00226 if(!dead) { 00227 PRINTF(L_CORE_SC,"%d: new card inserted",slotnum); 00228 bool resetdone=false; 00229 for(int mode=SM_NONE+1 ; mode<SM_MAX ; mode++) { 00230 if(DeviceSetMode(mode,ISO_BAUD)) { 00231 if((singlereset && resetdone) || (resetdone=CardReset())) { 00232 for(cSmartCardLink *scl=smartcards.First(); scl; scl=smartcards.Next(scl)) { 00233 if(!Running()) goto done; 00234 PRINTF(L_CORE_SC,"%d: checking for %s card",slotnum,scl->Name()); 00235 cSmartCard *sc=scl->Create(); 00236 if(sc && sc->Setup(this,mode,&atr,sb)) { 00237 SetCard(sc,scl->Id()); 00238 goto done; // ugly, any better solution? 00239 } 00240 delete sc; 00241 } 00242 PRINTF(L_CORE_SC,"%d: no card handler found",slotnum); 00243 } 00244 else PRINTF(L_CORE_SC,"%d: reset/atr error",slotnum); 00245 } 00246 else PRINTF(L_CORE_SC,"%d: failed to set serial mode %s",slotnum,serModes[mode]); 00247 } 00248 dead=true; 00249 PRINTF(L_CORE_SC,"%d: can't initialise new card, ignoring port until card reinserted",slotnum); 00250 } 00251 } 00252 else { 00253 if(dead) PRINTF(L_CORE_SC,"%d: card removed, port reactivated",slotnum); 00254 dead=false; 00255 } 00256 done: 00257 if(firstRun) { 00258 mutex.Lock(); 00259 cond.Broadcast(); 00260 firstRun=false; 00261 mutex.Unlock(); 00262 } 00263 cCondWait::SleepMs(300); 00264 } 00265 } 00266 00267 bool cSmartCardSlot::Reset(void) 00268 { 00269 PRINTF(L_CORE_SC,"%d: reseting card (sermode %s)",slotnum,serModes[DeviceCurrentMode()]); 00270 DeviceToggleReset(); 00271 cCondWait::SleepMs(100); 00272 DeviceToggleReset(); 00273 int r=DeviceRead(atr.atr,-MAX_ATR_LEN,800,2000); 00274 atr.atrLen=r; 00275 if(r>0) LDUMP(L_CORE_SC,atr.atr,r,"%d: <- ATR len=%d:",slotnum,r); 00276 return r>=2; 00277 } 00278 00279 bool cSmartCardSlot::CardReset(void) 00280 { 00281 if(!Reset() || !ParseAtr()) return false; 00282 if((atr.F!=372 || atr.D!=1.0) && !DevicePTS()) { 00283 // reset card again and continue without PTS 00284 if(!Reset() || !ParseAtr()) return false; 00285 } 00286 return true; 00287 } 00288 00289 void cSmartCardSlot::Invert(unsigned char *data, int n) 00290 { 00291 static const unsigned char swaptab[] = { 15,7,11,3,13,5,9,1,14,6,10,2,12,4,8,0 }; 00292 for(int i=n-1; i>=0; i--) 00293 data[i]=(swaptab[data[i]&0x0f]<<4) | swaptab[data[i]>>4]; 00294 } 00295 00296 int cSmartCardSlot::Read(unsigned char *data, int len, int to) 00297 { 00298 int r=DeviceRead(data,len,cfg->serTO,to); 00299 if(atr.convention==SM_INDIRECT && r>0) Invert(data,r); 00300 return r; 00301 } 00302 00303 int cSmartCardSlot::Write(const unsigned char *data, int len) 00304 { 00305 unsigned char *tmp=AUTOMEM(len); 00306 if(atr.convention==SM_INDIRECT) { 00307 memcpy(tmp,data,len); 00308 Invert(tmp,len); 00309 data=tmp; 00310 } 00311 int r=DeviceWrite(data,len,cfg->serDL); 00312 if(r>0 && localecho) { 00313 unsigned char *buff=AUTOMEM(r); 00314 int rr=DeviceRead(buff,r,cfg->serTO); 00315 if(rr<0) r=rr; 00316 } 00317 return r; 00318 } 00319 00320 int cSmartCardSlot::Procedure(unsigned char ins, int restLen) 00321 { 00322 int r; 00323 unsigned char buff; 00324 LBSTARTF(L_CORE_SC); 00325 LBPUT("%d: <- PROC: ",slotnum); 00326 do { 00327 do { 00328 if(Read(&buff,1,cfg->workTO)<=0) return -1; 00329 LBPUT("%02x ",buff); 00330 } while(buff==0x60); 00331 00332 if((buff&0xF0)==0x60 || (buff&0xF0)==0x90) { // SW1/SW2 00333 sb[0]=buff; 00334 if(Read(&buff,1)<=0) return -1; 00335 LBPUT("%02x",buff); 00336 sb[1]=buff; 00337 return 0; 00338 } 00339 else { 00340 if((buff&0xFE)==(ins&0xFE)) r=restLen; 00341 else if((~buff&0xFE)==(ins&0xFE)) r=1; 00342 else { 00343 LBPUT("cannot handle procedure %02x (ins=%02x)",buff,ins); 00344 return -1; 00345 } 00346 if(r>restLen) { 00347 LBPUT("data overrun r=%d restLen=%d",r,restLen); 00348 return -1; 00349 } 00350 } 00351 } while(r==0); 00352 LBEND(); 00353 return r; 00354 } 00355 00356 bool cSmartCardSlot::Test(bool res) 00357 { 00358 if(!res) { 00359 TriggerReset(); 00360 PRINTF(L_CORE_SC,"%d: reset triggered",slotnum); 00361 } 00362 return res; 00363 } 00364 00365 bool cSmartCardSlot::IsoRead(const unsigned char *cmd, unsigned char *data) 00366 { 00367 LDUMP(L_CORE_SC,cmd,CMD_LEN,"%d: -> INS:",slotnum); 00368 if(Write(cmd,CMD_LEN)<0) return Test(false); 00369 int tr=cmd[LEN_IDX] ? cmd[LEN_IDX] : 256; 00370 int len=0; 00371 while(1) { 00372 int r=Procedure(cmd[INS_IDX],tr-len); 00373 if(r<=0) return Test(r==0); 00374 if(Read(data+len,r)<0) return Test(false); 00375 LDUMP(L_CORE_SC,data+len,r,"%d: <- DATA:",slotnum); 00376 len+=r; 00377 } 00378 } 00379 00380 bool cSmartCardSlot::IsoWrite(const unsigned char *cmd, const unsigned char *data) 00381 { 00382 LDUMP(L_CORE_SC,cmd,CMD_LEN,"%d: -> INS:",slotnum); 00383 if(Write(cmd,CMD_LEN)<0) return Test(false); 00384 int len=0; 00385 while(1) { 00386 int r=Procedure(cmd[INS_IDX],cmd[LEN_IDX]-len); 00387 if(r<=0) return Test(r==0); 00388 if(Write(data+len,r)<0) return Test(false); 00389 LDUMP(L_CORE_SC,data+len,r,"%d: -> DATA:",slotnum); 00390 len+=r; 00391 } 00392 } 00393 00394 int cSmartCardSlot::RawRead(unsigned char *data, int len, int to) 00395 { 00396 int r=Read(data,len,to); 00397 if(r<0) Test(false); 00398 return r; 00399 } 00400 00401 int cSmartCardSlot::RawWrite(const unsigned char *data, int len) 00402 { 00403 int r=Write(data,len); 00404 if(r<0) Test(false); 00405 return r; 00406 } 00407 00408 #define NEED(x) { if(len+(x)>atr.atrLen) { LBPUT("SHORT ATR"); return false; } } 00409 00410 bool cSmartCardSlot::ParseAtr(void) 00411 { 00412 // default values 00413 atr.histLen=0; atr.T=0; atr.F=372; atr.fs=clock; atr.D=1.0; atr.N=0; atr.WI=10; 00414 atr.BWI=4; atr.CWI=0; atr.Tspec=-1; 00415 00416 static const int Ftable[16] = { 00417 372,372,558,744,1116,1488,1860,0,0,512,768,1024,1536,2048,0,0 00418 }; 00419 static const int fstable[16] = { 00420 3571200,5000000,6000000, 8000000,12000000,16000000,20000000,0, 00421 0,5000000,7500000,10000000,15000000,20000000, 0,0 00422 }; 00423 static const float Dtable[16] = { 00424 0.0,1.0,2.0,4.0,8.0,16.0,0.0,0.0, 00425 0.0,0.0,0.5,0.25,0.125,0.0625,0.03125,0.015625 00426 }; 00427 00428 const unsigned char *rawatr=atr.atr; 00429 if(rawatr[0]==0x03) { 00430 PRINTF(L_CORE_SC,"%d: indirect convention detected",slotnum); 00431 Invert(atr.atr,atr.atrLen); 00432 atr.convention=SM_INDIRECT; 00433 } 00434 else if(rawatr[0]==0x3B) { 00435 PRINTF(L_CORE_SC,"%d: direct convention detected",slotnum); 00436 atr.convention=SM_DIRECT; 00437 } 00438 else if(rawatr[0]==0x3F) { 00439 PRINTF(L_CORE_SC,"%d: inverted indirect convention detected",slotnum); 00440 atr.convention=SM_INDIRECT_INV; 00441 } 00442 else { 00443 PRINTF(L_CORE_SC,"%d: byte mode not supported 0x%02x",slotnum,rawatr[0]); 00444 return false; 00445 } 00446 00447 // TS TO 00448 atr.histLen=rawatr[1]&0x0F; 00449 int Y=rawatr[1]&0xF0, i=1, len=2; 00450 LBSTARTF(L_CORE_SC); 00451 LBPUT("%d: atr decoding TS=%02x hist=%d Y%d=%02x ",slotnum,rawatr[0],atr.histLen,i,Y); 00452 do { 00453 if(Y&0x10) { // TAi 00454 NEED(1); 00455 LBPUT("TA%d=%02x ",i,rawatr[len]); 00456 if(i==1) { 00457 atr.TA1=rawatr[len]; 00458 int i=(rawatr[len]>>4)&0x0F; 00459 atr.F=Ftable[i]; atr.fs=fstable[i]; 00460 atr.D=Dtable[rawatr[len]&0x0F]; 00461 LBPUT("F=%d fs=%.4f D=%f ",atr.F,atr.fs/1000000.0,atr.D); 00462 } 00463 else if(i==2) { 00464 atr.Tspec=rawatr[len]&0x0F; 00465 LBPUT("Tspec=%d ",atr.Tspec); 00466 } 00467 else if(i==3) { 00468 LBPUT("IFSC=%d ",rawatr[len]); 00469 } 00470 len++; 00471 } 00472 if(Y&0x20) { // TBi 00473 NEED(1); 00474 LBPUT("TB%d=%02x ",i,rawatr[len]); 00475 if(i==3) { 00476 atr.BWI=(rawatr[len]>>4)&0x0F; 00477 atr.CWI=rawatr[len]&0x0F; 00478 LBPUT("BWI=%d CWI=%d ",atr.BWI,atr.CWI); 00479 } 00480 len++; 00481 } 00482 if(Y&0x40) { // TCi 00483 NEED(1); 00484 LBPUT("TC%d=%02x ",i,rawatr[len]); 00485 if(i==1) { 00486 atr.N=rawatr[len]; 00487 LBPUT("N=%d ",atr.N); 00488 } 00489 else if(i==2) { 00490 atr.WI=rawatr[len]; 00491 LBPUT("WI=%d ",atr.WI); 00492 } 00493 else if(i==3) { 00494 LBPUT("CHK=%s ",rawatr[len]&1 ? "CRC16":"LRC"); 00495 } 00496 len++; 00497 } 00498 if(Y&0x80) { // TDi 00499 NEED(1); 00500 LBPUT("TD%d=%02x ",i,rawatr[len]); 00501 if(i==1) { 00502 atr.T=rawatr[len]&0x0F; 00503 LBPUT("T=%d ",atr.T); 00504 } 00505 else { 00506 LBPUT("Tn=%d ",rawatr[len]&0x0F); 00507 } 00508 Y=rawatr[len]&0xF0; 00509 len++; 00510 } 00511 else Y=0; 00512 i++; 00513 LBPUT("Y%d=%02x ",i,Y); 00514 } while(Y); 00515 NEED(atr.histLen); 00516 LBEND(); 00517 00518 LBSTART(L_CORE_SC); 00519 LBPUT("%d: historical:",slotnum); 00520 for(int i=0; i<atr.histLen; i++) LBPUT(" %02x",rawatr[len+i]); 00521 LBFLUSH(); 00522 LBPUT("%d: historical: '",slotnum); 00523 for(int i=0; i<atr.histLen; i++) LBPUT("%c",isprint(rawatr[len+i]) ? rawatr[len+i] : '.'); 00524 LBEND(); 00525 00526 memcpy(atr.hist,&rawatr[len],atr.histLen); 00527 len+=atr.histLen; 00528 00529 // TCK 00530 if(atr.T!=0 && len+1<=atr.atrLen) { 00531 len++; 00532 unsigned char cs=XorSum(rawatr+1,len-1); 00533 // according to the ISO the initial TS byte isn't checksumed, but 00534 // some cards do so. In this case the checksum is equal TS. 00535 if(cs==0) PRINTF(L_CORE_SC,"%d: atr checksum ok",slotnum); 00536 else if(cs==rawatr[0]) PRINTF(L_CORE_SC,"iso: %d: atr checksum is TS (not ISO compliant)",slotnum); 00537 else { 00538 PRINTF(L_CORE_SC,"%d: atr checksum FAILED (cs:%02x)",slotnum,cs); 00539 return false; 00540 } 00541 } 00542 else PRINTF(L_CORE_SC,"%d: atr checksum not given/not required",slotnum); 00543 00544 if(atr.atrLen>len) PRINTF(L_CORE_SC,"%d: long atr read=%d len=%d",slotnum,atr.atrLen,len); 00545 atr.wwt=960*atr.WI*atr.F/(clock/1000); 00546 atr.bwt=(int)(960*(float)(1<<atr.BWI)*372/(clock/1000)); 00547 PRINTF(L_CORE_SC,"%d: indicated wwt(T0)=%d ms, bwt(T1)=%d ms (at %.4f MHz)",slotnum,atr.wwt,atr.bwt,(float)clock/1000000); 00548 return true; 00549 } 00550 00551 #undef NEED 00552 00553 // -- cSmartCardSlots / cSmartCardSlotLink ------------------------------------- 00554 00555 class cSmartCardSlotLink { 00556 public: 00557 cSmartCardSlotLink *next; 00558 const char *name; 00559 public: 00560 cSmartCardSlotLink(const char *Name); 00561 virtual ~cSmartCardSlotLink() {} 00562 virtual cSmartCardSlot *Create(void)=0; 00563 }; 00564 00565 template<class LL> class cSmartCardSlotLinkReg : public cSmartCardSlotLink { 00566 public: 00567 cSmartCardSlotLinkReg(const char *Name):cSmartCardSlotLink(Name) {} 00568 virtual cSmartCardSlot *Create(void) { return new LL; } 00569 }; 00570 00571 class cSmartCardSlots : public cStructListPlain<cSmartCardSlot> { 00572 friend class cSmartCardSlotLink; 00573 private: 00574 static cSmartCardSlotLink *first; 00575 // 00576 static void Register(cSmartCardSlotLink *scl); 00577 protected: 00578 virtual bool ParseLinePlain(const char *line); 00579 public: 00580 cSmartCardSlots(void); 00581 cSmartCardSlot *GetSlot(int num); 00582 cSmartCardSlot *FirstSlot(void); 00583 void Release(void); 00584 }; 00585 00586 cSmartCardSlotLink *cSmartCardSlots::first=0; 00587 00588 static cSmartCardSlots cardslots; 00589 00590 cSmartCardSlotLink::cSmartCardSlotLink(const char *Name) 00591 { 00592 name=Name; 00593 cSmartCardSlots::Register(this); 00594 } 00595 00596 cSmartCardSlots::cSmartCardSlots(void) 00597 :cStructListPlain<cSmartCardSlot>("cardslot config","cardslot.conf",SL_MISSINGOK|SL_VERBOSE|SL_NOPURGE) 00598 {} 00599 00600 void cSmartCardSlots::Register(cSmartCardSlotLink *scl) 00601 { 00602 PRINTF(L_CORE_DYN,"registering cardslot type %s",scl->name); 00603 scl->next=first; 00604 first=scl; 00605 } 00606 00607 cSmartCardSlot *cSmartCardSlots::GetSlot(int num) 00608 { 00609 ListLock(false); 00610 for(cSmartCardSlot *slot=First(); slot; slot=Next(slot)) 00611 if(slot->SlotNum()==num) return slot; 00612 return 0; 00613 } 00614 00615 cSmartCardSlot *cSmartCardSlots::FirstSlot(void) 00616 { 00617 ListLock(false); 00618 return First(); 00619 } 00620 00621 void cSmartCardSlots::Release(void) 00622 { 00623 ListUnlock(); 00624 } 00625 00626 bool cSmartCardSlots::ParseLinePlain(const char *line) 00627 { 00628 char type[32]; 00629 int num; 00630 if(sscanf(line,"%31[^:]:%n",type,&num)==1) { 00631 for(cSmartCardSlotLink *scs=first; scs; scs=scs->next) { 00632 if(!strcasecmp(type,scs->name)) { 00633 cSmartCardSlot *slot=scs->Create(); 00634 if(slot) { 00635 if(slot->Setup(Count(),&line[num])) { 00636 Add(slot); 00637 return true; 00638 } 00639 delete slot; 00640 } 00641 else PRINTF(L_GEN_ERROR,"failed to create cardslot"); 00642 return false; 00643 } 00644 } 00645 PRINTF(L_GEN_ERROR,"unknown cardslot type '%s'",type); 00646 } 00647 return false; 00648 } 00649 00650 // -- cSmartCardSlotSerial ----------------------------------------------------- 00651 00652 class cSmartCardSlotSerial : public cSmartCardSlot { 00653 private: 00654 int statInv, invRST; 00655 bool custombaud; 00656 // 00657 speed_t FindBaud(int baud); 00658 protected: 00659 int fd; 00660 // 00661 void Flush(void); 00662 void SetDtrRts(void); 00663 // 00664 virtual bool DeviceOpen(const char *cfg); 00665 virtual void DeviceClose(void); 00666 virtual bool DeviceSetMode(int mode, int baud); 00667 virtual int DeviceRead(unsigned char *mem, int len, int timeout, int initialTimeout=0); 00668 virtual int DeviceWrite(const unsigned char *mem, int len, int delay=0); 00669 virtual void DeviceToggleReset(void); 00670 virtual bool DevicePTS(void); 00671 virtual bool DeviceIsInserted(void); 00672 public: 00673 cSmartCardSlotSerial(void); 00674 }; 00675 00676 static cSmartCardSlotLinkReg<cSmartCardSlotSerial> __scs_serial("serial"); 00677 00678 cSmartCardSlotSerial::cSmartCardSlotSerial(void) 00679 { 00680 fd=-1; statInv=0; invRST=false; custombaud=false; 00681 } 00682 00683 bool cSmartCardSlotSerial::DeviceOpen(const char *cfg) 00684 { 00685 int invCD=0; 00686 if(sscanf(cfg,"%255[^:]:%d:%d:%d",devName,&invCD,&invRST,&clock)>=3) { 00687 if(clock<=0) clock=ISO_FREQ; 00688 statInv=invCD ? TIOCM_CAR:0; 00689 PRINTF(L_CORE_SERIAL,"%s: open serial port",devName); 00690 fd=open(devName,O_RDWR|O_NONBLOCK|O_NOCTTY); 00691 if(fd>=0) { 00692 SetDtrRts(); 00693 PRINTF(L_CORE_SERIAL,"%s: init done",devName); 00694 PRINTF(L_CORE_LOAD,"cardslot: added serial port %s as port %d (%s CD, %s RESET, CLOCK %d)", 00695 devName,slotnum,invCD?"inverse":"normal",invRST?"inverse":"normal",clock); 00696 return true; 00697 } 00698 else PRINTF(L_GEN_ERROR,"%s: open failed: %s",devName,strerror(errno)); 00699 } 00700 else PRINTF(L_GEN_ERROR,"bad parameter for cardslot type 'serial'"); 00701 return false; 00702 } 00703 00704 void cSmartCardSlotSerial::SetDtrRts(void) 00705 { 00706 PRINTF(L_CORE_SERIAL,"%s: set DTR/RTS",devName); 00707 unsigned int modembits; 00708 modembits=TIOCM_DTR; CHECK(ioctl(fd, TIOCMBIS, &modembits)); 00709 modembits=TIOCM_RTS; CHECK(ioctl(fd, invRST?TIOCMBIS:TIOCMBIC, &modembits)); 00710 } 00711 00712 void cSmartCardSlotSerial::DeviceClose(void) 00713 { 00714 if(fd>=0) { 00715 PRINTF(L_CORE_SERIAL,"%s: shutting down",devName); 00716 Flush(); 00717 unsigned int modembits=0; 00718 CHECK(ioctl(fd,TIOCMSET,&modembits)); 00719 close(fd); fd=-1; 00720 PRINTF(L_CORE_SERIAL,"%s: shutdown done",devName); 00721 } 00722 } 00723 00724 void cSmartCardSlotSerial::Flush(void) 00725 { 00726 if(fd>=0) CHECK(tcflush(fd,TCIOFLUSH)); 00727 } 00728 00729 speed_t cSmartCardSlotSerial::FindBaud(int baud) 00730 { 00731 static const struct BaudRates { int real; speed_t apival; } BaudRateTab[] = { 00732 { 9600, B9600 }, { 19200, B19200 }, { 38400, B38400 }, 00733 { 57600, B57600 }, { 115200, B115200 }, { 230400, B230400 } 00734 }; 00735 00736 for(int i=0; i<(int)(sizeof(BaudRateTab)/sizeof(struct BaudRates)); i++) { 00737 int b=BaudRateTab[i].real; 00738 int d=((b-baud)*10000)/b; 00739 if(abs(d)<=300) { 00740 PRINTF(L_CORE_SERIAL,"%s: requested baudrate %d -> %d (%+.2f%%)",devName,baud,b,(float)d/100.0); 00741 return BaudRateTab[i].apival; 00742 } 00743 } 00744 PRINTF(L_CORE_SERIAL,"%s: requested baudrate %d -> custom",devName,baud); 00745 return B0; 00746 } 00747 00748 bool cSmartCardSlotSerial::DeviceSetMode(int mode, int baud) 00749 { 00750 if(fd>=0) { 00751 speed_t bconst=FindBaud(baud); 00752 bool custom=false; 00753 if(bconst==B0) { custom=true; bconst=B38400; } 00754 00755 struct termios tio; 00756 memset(&tio,0,sizeof(tio)); 00757 LBSTARTF(L_CORE_SERIAL); 00758 LBPUT("%s: set serial options: %d,",devName,baud); 00759 tio.c_cflag = (CS8 | CREAD | HUPCL | CLOCAL); 00760 if(!(mode&SM_1SB)) tio.c_cflag |= CSTOPB; 00761 tio.c_iflag = (INPCK | IGNBRK); 00762 tio.c_cc[VMIN] = 1; 00763 cfsetispeed(&tio,bconst); 00764 cfsetospeed(&tio,bconst); 00765 switch(mode&SM_MASK) { 00766 case SM_8E2: 00767 LBPUT("8e%d",(mode&SM_1SB)?1:2); 00768 tio.c_cflag |= PARENB; break; 00769 case SM_8N2: 00770 LBPUT("8n%d",(mode&SM_1SB)?1:2); 00771 break; 00772 case SM_8O2: 00773 LBPUT("8o%d",(mode&SM_1SB)?1:2); 00774 tio.c_cflag |= (PARENB | PARODD); break; 00775 default: 00776 LBPUT("BAD MODE"); 00777 return false; 00778 } 00779 LBEND(); 00780 00781 struct serial_struct s; 00782 if(ioctl(fd,TIOCGSERIAL,&s)<0) { 00783 if(custom || custombaud) { 00784 PRINTF(L_GEN_ERROR,"%s: get serial failed: %s",devName,strerror(errno)); 00785 return false; 00786 } 00787 PRINTF(L_CORE_SERIAL,"%s: get serial failed: %s",devName,strerror(errno)); 00788 PRINTF(L_CORE_SERIAL,"%s: custombaud not used, try to continue...",devName); 00789 } 00790 else if(!custom && ((s.flags&ASYNC_SPD_MASK)==ASYNC_SPD_CUST || s.custom_divisor!=0)) { 00791 s.custom_divisor=0; 00792 s.flags &= ~ASYNC_SPD_MASK; 00793 if(ioctl(fd,TIOCSSERIAL,&s)<0) { 00794 PRINTF(L_GEN_ERROR,"%s: set serial failed: %s",devName,strerror(errno)); 00795 return false; 00796 } 00797 custombaud=false; 00798 } 00799 if(!tcsetattr(fd,TCSANOW,&tio)) { 00800 if(custom) { 00801 s.custom_divisor=(s.baud_base+(baud/2))/baud; 00802 s.flags=(s.flags&~ASYNC_SPD_MASK) | ASYNC_SPD_CUST; 00803 PRINTF(L_CORE_SERIAL,"%s: custom: baud_base=%d baud=%d devisor=%d -> effective baudrate %d (%+.2f%% off)",devName,s.baud_base,baud,s.custom_divisor,s.baud_base/s.custom_divisor,(float)(s.baud_base/s.custom_divisor-baud)/(float)baud); 00804 if(ioctl(fd,TIOCSSERIAL,&s)<0) { 00805 PRINTF(L_GEN_ERROR,"%s: set serial failed: %s",devName,strerror(errno)); 00806 return false; 00807 } 00808 custombaud=true; 00809 } 00810 currMode=mode; Flush(); 00811 return true; 00812 } 00813 else PRINTF(L_GEN_ERROR,"%s: tcsetattr failed: %s",devName,strerror(errno)); 00814 } 00815 return false; 00816 } 00817 00818 int cSmartCardSlotSerial::DeviceRead(unsigned char *mem, int len, int timeout, int initialTimeout) 00819 { 00820 PRINTF(L_CORE_SERIAL,"%s: read len=%d timeout=%d:%d",devName,len,timeout,initialTimeout); 00821 bool incomplete=false; 00822 if(len<0) { len=-len; incomplete=true; } 00823 int to=initialTimeout>0 ? initialTimeout : timeout; 00824 int n=0; 00825 while(n<len) { 00826 int r=read(fd,mem+n,len-n); 00827 if(r<=0) { 00828 if(r==0) PRINTF(L_CORE_SERIAL,"%s: read bogus eof",devName); 00829 if(errno==EAGAIN) { 00830 struct pollfd u; 00831 u.fd=fd; u.events=POLLIN; 00832 r=poll(&u,1,to); 00833 if(r<0) { 00834 PRINTF(L_GEN_ERROR,"%s: read poll failed: %s",devName,strerror(errno)); 00835 return -1; 00836 } 00837 else if(r==0) { // timeout 00838 PRINTF(L_CORE_SERIAL,"%s: read timeout (%d ms)",devName,to); 00839 if(n>0 && incomplete) break; // return bytes read so far 00840 return -2; 00841 } 00842 continue; 00843 } 00844 else { 00845 PRINTF(L_GEN_ERROR,"%s: read failed: %s",devName,strerror(errno)); 00846 return -1; 00847 } 00848 } 00849 n+=r; to=timeout; 00850 } 00851 HEXDUMP(L_CORE_SERIAL,mem,n,"%s: read data",devName); 00852 return n; 00853 } 00854 00855 int cSmartCardSlotSerial::DeviceWrite(const unsigned char *mem, int len, int delay) 00856 { 00857 PRINTF(L_CORE_SERIAL,"%s: write len=%d delay=%d",devName,len,delay); 00858 HEXDUMP(L_CORE_SERIAL,mem,len,"%s: write data",devName); 00859 Flush(); 00860 int n=0; 00861 while(n<len) { 00862 struct pollfd u; 00863 u.fd=fd; u.events=POLLOUT; 00864 int r; 00865 do { 00866 r=poll(&u,1,500); 00867 if(r<0) { 00868 PRINTF(L_GEN_ERROR,"%s: write poll failed: %s",devName,strerror(errno)); 00869 return -1; 00870 } 00871 else if(r==0) { // timeout 00872 PRINTF(L_CORE_SERIAL,"%s: write timeout",devName); 00873 return -2; 00874 } 00875 } while(r<1); 00876 r=write(fd,mem+n,delay>0?1:len-n); 00877 if(r<0 && errno!=EAGAIN) { 00878 PRINTF(L_GEN_ERROR,"%s: write failed: %s",devName,strerror(errno)); 00879 return -1; 00880 } 00881 if(r>0) n+=r; 00882 if(delay>0) cCondWait::SleepMs(delay); 00883 } 00884 return n; 00885 } 00886 00887 void cSmartCardSlotSerial::DeviceToggleReset(void) 00888 { 00889 int mask=0; 00890 if(ioctl(fd,TIOCMGET,&mask)<0) { LOG_ERROR; return; } 00891 if(mask&TIOCM_RTS) { mask&=~TIOCM_RTS; PRINTF(L_CORE_SERIAL,"%s: toggle RTS, now off",devName); } 00892 else { mask|= TIOCM_RTS; PRINTF(L_CORE_SERIAL,"%s: toggle RTS, now on",devName); } 00893 CHECK(ioctl(fd,TIOCMSET,&mask)); 00894 Flush(); 00895 } 00896 00897 bool cSmartCardSlotSerial::DevicePTS(void) 00898 { 00899 int baud=(int)((float)clock*atr.D/atr.F); 00900 PRINTF(L_CORE_SC,"%d: PTS cycle: calculated baudrate %d",slotnum,baud); 00901 00902 if(atr.Tspec<0) { 00903 PRINTF(L_CORE_SC,"%d: negotiable mode",slotnum); 00904 #ifdef NO_PTS_PROTO 00905 PRINTF(L_CORE_SC,"%d: PTS disabled at compile time!!!",slotnum); 00906 return true; 00907 #else 00908 unsigned char req[4], conf[16]; 00909 req[0]=0xFF; 00910 req[1]=0x10 | atr.T; 00911 req[2]=atr.TA1; 00912 req[3]=XorSum(req,3); 00913 LDUMP(L_CORE_SC,req,4,"%d: PTS request:",slotnum); 00914 if(DeviceWrite(req,4)!=4) { 00915 PRINTF(L_CORE_SC,"%d: PTS request, write failed",slotnum); 00916 return false; 00917 } 00918 if(DeviceRead(conf,4,100,100)!=4) { 00919 PRINTF(L_CORE_SC,"%d: PTS request, echo readback failed",slotnum); 00920 return false; 00921 } 00922 int n=DeviceRead(conf,-16,200,1000); 00923 if(n>0) LDUMP(L_CORE_SC,conf,n,"%d: PTS confirm:",slotnum); 00924 if(n<1 || conf[0]!=0xFF || XorSum(conf,n)!=0) { 00925 PRINTF(L_CORE_SC,"%d: PTS confirm, bad format",slotnum); 00926 return false; 00927 } 00928 if(n<4 || conf[1]!=req[1] || conf[2]!=req[2]) { 00929 PRINTF(L_CORE_SC,"%d: PTS not confirmed",slotnum); 00930 return false; 00931 } 00932 #endif // NO_PTS_PROTO 00933 } 00934 else 00935 PRINTF(L_CORE_SC,"%d: specific mode Tspec=%d",slotnum,atr.Tspec); 00936 00937 int mode=DeviceCurrentMode(); 00938 if(atr.N==255) mode|=SM_1SB; 00939 if(!DeviceSetMode(mode,baud)) { 00940 PRINTF(L_CORE_SC,"%d: setting baudrate %d failed",slotnum,baud); 00941 return false; 00942 } 00943 return true; 00944 } 00945 00946 bool cSmartCardSlotSerial::DeviceIsInserted(void) 00947 { 00948 int status=0; 00949 if(ioctl(fd,TIOCMGET,&status)<0) { LOG_ERROR; return false; } 00950 PRINTF(L_CORE_SERIAL,"%s: CAR is %sactive (lines:%s%s%s%s%s%s%s%s%s)", 00951 devName,(status&TIOCM_CAR)?"in":"", 00952 (status&TIOCM_LE)?" LE":"", (status&TIOCM_DTR)?" DTR":"", 00953 (status&TIOCM_RTS)?" RTS":"",(status&TIOCM_ST)?" ST":"", 00954 (status&TIOCM_SR)?" SR":"", (status&TIOCM_CTS)?" CTS":"", 00955 (status&TIOCM_CAR)?" CAR":"",(status&TIOCM_RNG)?" RNG":"", 00956 (status&TIOCM_DSR)?" DSR":"" ); 00957 status^=statInv; // invert status for broken cardreaders 00958 return !(status & TIOCM_CAR); 00959 } 00960 00961 // -- cSmartCardSlotSRPlus ----------------------------------------------------- 00962 00963 class cSmartCardSlotSRPlus : public cSmartCardSlotSerial { 00964 private: 00965 bool SRConfig(int F, float D, int fs, int N, int T, int inv); 00966 protected: 00967 virtual bool DeviceOpen(const char *cfg); 00968 virtual bool DeviceSetMode(int mode, int baud); 00969 virtual bool DevicePTS(void); 00970 public: 00971 cSmartCardSlotSRPlus(void); 00972 }; 00973 00974 static cSmartCardSlotLinkReg<cSmartCardSlotSRPlus> __scs_srplus("srplus"); 00975 00976 cSmartCardSlotSRPlus::cSmartCardSlotSRPlus(void) 00977 { 00978 localecho=false; 00979 } 00980 00981 bool cSmartCardSlotSRPlus::DeviceOpen(const char *cfg) 00982 { 00983 if(sscanf(cfg,"%255[^:]:%d",devName,&clock)>=1) { 00984 if(clock<=0) clock=ISO_FREQ; 00985 PRINTF(L_CORE_SERIAL,"%s: open serial port",devName); 00986 fd=open(devName,O_RDWR|O_NONBLOCK|O_NOCTTY); 00987 if(fd>=0) { 00988 SetDtrRts(); 00989 PRINTF(L_CORE_SERIAL,"%s: init done",devName); 00990 PRINTF(L_CORE_LOAD,"cardslot: added smartreader+ port %s as port %d (CLOCK %d)", 00991 devName,slotnum,clock); 00992 return true; 00993 } 00994 else PRINTF(L_GEN_ERROR,"%s: open failed: %s",devName,strerror(errno)); 00995 } 00996 else PRINTF(L_GEN_ERROR,"bad parameter for cardslot type 'srplus'"); 00997 return false; 00998 } 00999 01000 bool cSmartCardSlotSRPlus::DeviceSetMode(int mode, int baud) 01001 { 01002 // Configure SmartReader+ with initial settings, ref ISO 7816 3.1. 01003 return baud==ISO_BAUD && 01004 cSmartCardSlotSerial::DeviceSetMode(mode,ISO_BAUD) && 01005 SRConfig(372,1.0,clock,0,0,0); 01006 } 01007 01008 bool cSmartCardSlotSRPlus::DevicePTS(void) 01009 { 01010 // Configure SmartReader+ with work settings, ref ISO 7816 3.1. 01011 int inv=0; 01012 if(atr.convention==SM_INDIRECT) atr.convention=SM_INDIRECT_INV; 01013 if(atr.convention==SM_INDIRECT_INV) inv=1; 01014 // Use ISO work clock frequency unless a fixed frequency is specified. 01015 int cl=(clock==ISO_FREQ) ? atr.fs:clock; 01016 if(!SRConfig(atr.F,atr.D,cl,atr.N,atr.T,inv)) return false; 01017 PRINTF(L_CORE_SERIAL,"%s: SmartReader+ mode %.4f MHz",devName,cl/1000000.0); 01018 return true; 01019 } 01020 01021 bool cSmartCardSlotSRPlus::SRConfig(int F, float D, int fs, int N, int T, int inv) 01022 { 01023 fs/=1000; // convert to kHz. 01024 PRINTF(L_CORE_SERIAL,"%s: SR+ options F=%d D=%f fs=%d N=%d T=%d inv=%d",devName,F,D,fs,N,T,inv); 01025 // Set SmartReader+ in CMD mode. 01026 struct termios term; 01027 if(tcgetattr(fd,&term)==-1) { 01028 PRINTF(L_GEN_ERROR,"%s: tcgetattr failed: %s",devName,strerror(errno)); 01029 return false; 01030 } 01031 term.c_cflag&=~CSIZE; 01032 term.c_cflag|=CS5; 01033 if(tcsetattr(fd,TCSADRAIN,&term)==-1) { 01034 PRINTF(L_GEN_ERROR,"%s: tcsetattr failed: %s",devName,strerror(errno)); 01035 return false; 01036 } 01037 // Write SmartReader+ configuration commands. 01038 unsigned char cmd[16]; 01039 //XXX how is (int)D supposed to work for fractional values e.g. 0.125 ?? 01040 cmd[0]=1; cmd[1]=F>>8; cmd[2]=F; cmd[3]=(int)D; 01041 if(DeviceWrite(cmd,4)!=4) return false; 01042 cmd[0]=2; cmd[1]=fs>>8; cmd[2]=fs; 01043 if(DeviceWrite(cmd,3)!=3) return false; 01044 cmd[0]=3; cmd[1]=N; 01045 if(DeviceWrite(cmd,2)!=2) return false; 01046 cmd[0]=4; cmd[1]=T; 01047 if(DeviceWrite(cmd,2)!=2) return false; 01048 cmd[0]=5; cmd[1]=inv; 01049 if(DeviceWrite(cmd,2)!=2) return false; 01050 // Send zero bits for 0.25 - 0.5 seconds. 01051 if(tcsendbreak(fd,0)==-1) { 01052 PRINTF(L_GEN_ERROR,"%s: tcsendbreak failed: %s",devName,strerror(errno)); 01053 return false; 01054 } 01055 // We're entering SmartReader+ mode; speed up serial communication. 01056 // B3000000 is the highest setting that sticks. 01057 cfsetispeed(&term,B3000000); 01058 cfsetospeed(&term,B3000000); 01059 // Set SmartReader+ in DATA mode. 01060 term.c_cflag&=~CSIZE; 01061 term.c_cflag|=CS8; 01062 if(tcsetattr(fd,TCSADRAIN,&term)==-1) { 01063 PRINTF(L_GEN_ERROR,"%s: tcsetattr failed: %s",devName,strerror(errno)); 01064 return false; 01065 } 01066 return true; 01067 } 01068 01069 // -- cSmartCardSlotCCID ------------------------------------------------------- 01070 01071 #ifdef WITH_PCSC 01072 #include <winscard.h> 01073 01074 class cSmartCardSlotCCID : public cSmartCardSlot { 01075 private: 01076 SCARDCONTEXT hContext; 01077 SCARDHANDLE hCard; 01078 DWORD dwProtocol; 01079 bool needsReOpen; 01080 // 01081 int Transmit(const unsigned char *request, int requestlen, unsigned char *answer, int answerlen); 01082 protected: 01083 virtual bool DeviceOpen(const char *cfg); 01084 virtual void DeviceClose(void); 01085 virtual bool DeviceSetMode(int mode, int baud); 01086 virtual int DeviceRead(unsigned char *mem, int len, int timeout, int initialTimeout=0) { return -1; } 01087 virtual int DeviceWrite(const unsigned char *mem, int len, int delay=0) { return -1; } 01088 virtual void DeviceToggleReset(void) {} 01089 virtual bool DevicePTS(void) { return true; } 01090 virtual bool DeviceIsInserted(void); 01091 // 01092 virtual bool Reset(void); 01093 public: 01094 cSmartCardSlotCCID(void); 01095 virtual bool IsoRead(const unsigned char *cmd, unsigned char *data); 01096 virtual bool IsoWrite(const unsigned char *cmd, const unsigned char *data); 01097 virtual int RawRead(unsigned char *data, int len, int to=0) { return -1; } 01098 virtual int RawWrite(const unsigned char *data, int len) { return -1; } 01099 }; 01100 01101 static cSmartCardSlotLinkReg<cSmartCardSlotCCID> __scs_ccid("ccid"); 01102 01103 cSmartCardSlotCCID::cSmartCardSlotCCID(void) 01104 { 01105 singlereset=true; 01106 } 01107 01108 bool cSmartCardSlotCCID::DeviceOpen(const char *cfg) 01109 { 01110 if(!cfg || sscanf(cfg,"%255[^:]",devName)==1) { 01111 LONG rv=SCardEstablishContext(SCARD_SCOPE_SYSTEM,NULL,NULL,&hContext); 01112 PRINTF(L_CORE_SC,"%d: establish context: %lx:%s",slotnum,rv,pcsc_stringify_error(rv)); 01113 if(rv==SCARD_S_SUCCESS) { 01114 DWORD protocol=SCARD_PROTOCOL_T0|SCARD_PROTOCOL_T1; 01115 rv=SCardConnect(hContext,devName,SCARD_SHARE_SHARED,protocol,&hCard,&dwProtocol); 01116 PRINTF(L_CORE_SC,"%d: connect '%s': %lx:%s",slotnum,devName,rv,pcsc_stringify_error(rv)); 01117 if(rv==SCARD_S_SUCCESS) { 01118 needsReOpen=false; 01119 return true; 01120 } 01121 } 01122 } 01123 else PRINTF(L_GEN_ERROR,"bad parameter for cardslot type 'ccid'"); 01124 return false; 01125 } 01126 01127 void cSmartCardSlotCCID::DeviceClose(void) 01128 { 01129 SCardDisconnect(hCard,SCARD_RESET_CARD); 01130 SCardReleaseContext(hContext); 01131 } 01132 01133 bool cSmartCardSlotCCID::DeviceSetMode(int mode, int baud) 01134 { 01135 currMode=mode; 01136 return true; 01137 } 01138 01139 bool cSmartCardSlotCCID::DeviceIsInserted(void) 01140 { 01141 BYTE pbAtr[MAX_ATR_SIZE]; 01142 DWORD dwState, dwReaderLen=0, dwAtrLen=sizeof(pbAtr); 01143 LONG rv=SCardStatus(hCard,NULL,&dwReaderLen,&dwState,&dwProtocol,pbAtr,&dwAtrLen); 01144 if(rv==SCARD_S_SUCCESS && (dwState&SCARD_NEGOTIABLE)) return true; 01145 needsReOpen=true; 01146 return false; 01147 } 01148 01149 bool cSmartCardSlotCCID::Reset(void) 01150 { 01151 PRINTF(L_CORE_SC,"%d: reseting card (sermode %s)",slotnum,serModes[DeviceCurrentMode()]); 01152 if(needsReOpen) { DeviceClose(); DeviceOpen(0); } 01153 DWORD protocol=dwProtocol; 01154 LONG rv=SCardReconnect(hCard,SCARD_SHARE_EXCLUSIVE,protocol,SCARD_RESET_CARD,&dwProtocol); 01155 if(rv!=SCARD_S_SUCCESS) { 01156 PRINTF(L_CORE_SC,"%d: reset failed: %lx:%sn",slotnum,rv,pcsc_stringify_error(rv)); 01157 return false; 01158 } 01159 DWORD dwState, dwReaderLen=0, dwAtrLen=sizeof(atr.atr); 01160 rv=SCardStatus(hCard,NULL,&dwReaderLen,&dwState,&dwProtocol,atr.atr,&dwAtrLen); 01161 if(rv==SCARD_S_SUCCESS) { 01162 atr.atrLen=dwAtrLen; 01163 LDUMP(L_CORE_SC,atr.atr,dwAtrLen,"%d: <- ATR len=%ld:",slotnum,dwAtrLen); 01164 return true; 01165 } 01166 return false; 01167 } 01168 01169 int cSmartCardSlotCCID::Transmit(const unsigned char *request, int requestlen, unsigned char *answer, int answerlen) 01170 { 01171 SCARD_IO_REQUEST pioRecvPci, pioSendPci; 01172 switch(dwProtocol) { 01173 case SCARD_PROTOCOL_T0: 01174 case SCARD_PROTOCOL_T1: 01175 pioSendPci.dwProtocol=dwProtocol; 01176 pioSendPci.cbPciLength=sizeof(pioSendPci); 01177 pioRecvPci.dwProtocol=dwProtocol; 01178 pioRecvPci.cbPciLength=sizeof(pioRecvPci); 01179 break; 01180 default: 01181 PRINTF(L_CORE_SC,"%d: protocol failure: %ld",slotnum,dwProtocol); 01182 return 0; 01183 } 01184 DWORD answlen=answerlen; 01185 DWORD rv=SCardTransmit(hCard,&pioSendPci,(LPCBYTE)request,(DWORD)requestlen,&pioRecvPci,(LPBYTE)answer,&answlen); 01186 if(rv!=SCARD_S_SUCCESS) { 01187 PRINTF(L_CORE_SC, "%d: transmit failed: %lx:%s\n",slotnum,rv,pcsc_stringify_error(rv)); 01188 return -1; 01189 } 01190 return answlen; 01191 } 01192 01193 bool cSmartCardSlotCCID::IsoRead(const unsigned char *cmd, unsigned char *data) 01194 { 01195 LDUMP(L_CORE_SC,cmd,CMD_LEN,"%d: -> INS:",slotnum); 01196 int restlen=Transmit(cmd,CMD_LEN,data,MAX_LEN); 01197 if(restlen<2) return Test(false); 01198 sb[0]=data[restlen-2]; 01199 sb[1]=data[restlen-1]; 01200 LDUMP(L_CORE_SC,sb,2,"%d: <- SB: ",slotnum); 01201 LDUMP(L_CORE_SC,data,restlen-2,"%d: <- DATA:",slotnum); 01202 return true; 01203 } 01204 01205 bool cSmartCardSlotCCID::IsoWrite(const unsigned char *cmd, const unsigned char *data) 01206 { 01207 LDUMP(L_CORE_SC,cmd,CMD_LEN,"%d: -> INS:",slotnum); 01208 LDUMP(L_CORE_SC,data,cmd[LEN_IDX],"%d: -> DATA:",slotnum); 01209 unsigned char sendbuf[MAX_LEN+CMD_LEN], recvbuf[MAX_LEN]; 01210 memcpy(sendbuf,cmd,CMD_LEN); 01211 memcpy(sendbuf+CMD_LEN,data,sendbuf[LEN_IDX]); 01212 int restlen=Transmit(sendbuf,CMD_LEN+sendbuf[LEN_IDX],recvbuf,MAX_LEN); 01213 if(restlen<2) return Test(false); 01214 sb[0]=recvbuf[restlen-2]; 01215 sb[1]=recvbuf[restlen-1]; 01216 LDUMP(L_CORE_SC,sb,2,"%d: <- SB: ",slotnum); 01217 return true; 01218 } 01219 01220 #endif //WITH_PCSC 01221 01222 // -- cSmartCardSlotEmuGeneric ------------------------------------------------- 01223 01224 #ifdef CARD_EMU 01225 01226 #define PUSH(mem,len) { memcpy(devBuff+buffCount,(mem),(len)); buffCount+=(len); } 01227 #define PUSHB(b) { devBuff[buffCount++]=(b); } 01228 01229 class cSmartCardSlotEmuGeneric : public cSmartCardSlot { 01230 protected: 01231 unsigned char devBuff[1024], nextSW[SB_LEN]; 01232 int buffCount, dataLen, record; 01233 bool cmdStart, rts, dsr, flag; 01234 time_t remTime; 01235 // 01236 virtual bool DeviceOpen(const char *cfg); 01237 virtual void DeviceClose(void); 01238 virtual bool DeviceSetMode(int mode, int baud); 01239 virtual int DeviceRead(unsigned char *mem, int len, int timeout, int initialTimeout=0); 01240 virtual void DeviceToggleReset(void); 01241 virtual bool DevicePTS(void); 01242 virtual bool DeviceIsInserted(void); 01243 // 01244 virtual void EmuPushAtr(void)=0; 01245 void Flush(void); 01246 }; 01247 01248 bool cSmartCardSlotEmuGeneric::DeviceOpen(const char *cfg) 01249 { 01250 PRINTF(L_CORE_SERIAL,"%s: open serial port (emulator)",devName); 01251 PRINTF(L_CORE_SERIAL,"%s: init done",devName); 01252 buffCount=0; cmdStart=true; rts=false; flag=false; 01253 remTime=time(0); dsr=true; 01254 PRINTF(L_CORE_LOAD,"cardslot: added emulated port %s as port %d",devName,slotnum); 01255 return true; 01256 } 01257 01258 void cSmartCardSlotEmuGeneric::DeviceClose(void) 01259 { 01260 PRINTF(L_CORE_SERIAL,"%s: shutting down",devName); 01261 } 01262 01263 void cSmartCardSlotEmuGeneric::Flush(void) 01264 { 01265 buffCount=0; 01266 } 01267 01268 bool cSmartCardSlotEmuGeneric::DeviceSetMode(int mode, int baud) 01269 { 01270 currMode=mode; 01271 Flush(); 01272 return true; 01273 } 01274 01275 int cSmartCardSlotEmuGeneric::DeviceRead(unsigned char *mem, int len, int timeout, int initialTimeout) 01276 { 01277 PRINTF(L_CORE_SERIAL,"%s: read len=%d timeout=%d",devName,len,timeout); 01278 if(len<0) { 01279 len=-len; 01280 if(buffCount<len) len=buffCount; 01281 } 01282 if(buffCount<len) return -2; // timeout 01283 memcpy(mem,devBuff,len); 01284 memmove(devBuff,devBuff+len,buffCount-len); 01285 buffCount-=len; 01286 return len; 01287 } 01288 01289 void cSmartCardSlotEmuGeneric::DeviceToggleReset(void) 01290 { 01291 rts=!rts; 01292 if(!rts) { 01293 EmuPushAtr(); 01294 PRINTF(L_CORE_SERIAL,"%s: toggle RTS, now off",devName); 01295 } 01296 else { PRINTF(L_CORE_SERIAL,"%s: toggle RTS, now on",devName); } 01297 } 01298 01299 bool cSmartCardSlotEmuGeneric::DevicePTS(void) 01300 { 01301 return true; 01302 } 01303 01304 bool cSmartCardSlotEmuGeneric::DeviceIsInserted(void) 01305 { 01306 #if 0 01307 if(time(0)>=remTime+30) { 01308 dsr=!dsr; 01309 remTime=time(0); 01310 } 01311 #endif 01312 return dsr; 01313 } 01314 01315 // -- cSmartCardSlotEmuSeca ---------------------------------------------------- 01316 01317 class cSmartCardSlotEmuSeca : public cSmartCardSlotEmuGeneric { 01318 protected: 01319 virtual int DeviceWrite(const unsigned char *mem, int len, int delay=0); 01320 virtual void EmuPushAtr(void); 01321 public: 01322 cSmartCardSlotEmuSeca(void); 01323 }; 01324 01325 static cSmartCardSlotLinkReg<cSmartCardSlotEmuSeca> __scs_emuseca("emuseca"); 01326 01327 cSmartCardSlotEmuSeca::cSmartCardSlotEmuSeca(void) 01328 { 01329 strcpy(devName,"emuseca"); 01330 } 01331 01332 int cSmartCardSlotEmuSeca::DeviceWrite(const unsigned char *mem, int len, int delay) 01333 { 01334 PRINTF(L_CORE_SERIAL,"%s: write len=%d delay=%d",devName,len,delay); 01335 Flush(); 01336 cCondWait::SleepMs(300); 01337 PUSH(mem,len); // echo back 01338 //--- 01339 if(cmdStart && len==CMD_LEN) { // new INS 01340 PUSHB(mem[INS_IDX]); // ACK byte 01341 cmdStart=false; 01342 dataLen=mem[LEN_IDX]; 01343 unsigned char data[256]; 01344 memset(data,0,sizeof(data)); 01345 nextSW[0]=0x90; nextSW[1]=0x00; 01346 bool readcmd=false; 01347 switch(mem[0]*256+mem[1]) { 01348 case 0xc13a: 01349 case 0xc10e: 01350 readcmd=true; 01351 break; 01352 case 0xc116: 01353 data[3]=0x04; 01354 readcmd=true; 01355 break; 01356 case 0xc112: 01357 data[1]=0x64; 01358 data[22]=0x1d; data[23]=0x84; 01359 readcmd=true; 01360 break; 01361 case 0xc132: 01362 data[1]=0xFF; data[2]=0xFF; data[3]=0xFF; data[4]=0xFF; 01363 data[5]=0xFF; data[6]=0xFF; data[7]=0xFF; data[8]=0xFF; 01364 readcmd=true; 01365 break; 01366 } 01367 if(readcmd) { 01368 PUSH(data,dataLen); 01369 PUSH(nextSW,2); 01370 cmdStart=true; 01371 } 01372 } 01373 else { 01374 dataLen-=len; 01375 if(dataLen<=0 && !cmdStart) { 01376 PUSH(nextSW,2); 01377 cmdStart=true; 01378 } 01379 } 01380 //--- 01381 return len; 01382 } 01383 01384 void cSmartCardSlotEmuSeca::EmuPushAtr(void) 01385 { 01386 static const unsigned char atr[] = { 0x3b,0x77,0x12,0x00,0x00, 01387 0x60,0x60,0x03,0x0E,0x6C,0xB6,0xD6 }; 01388 PUSH(atr,sizeof(atr)); 01389 } 01390 01391 // -- cSmartCardSlotEmuCrypto -------------------------------------------------- 01392 01393 class cSmartCardSlotEmuCrypto : public cSmartCardSlotEmuGeneric { 01394 protected: 01395 virtual int DeviceWrite(const unsigned char *mem, int len, int delay=0); 01396 virtual void EmuPushAtr(void); 01397 public: 01398 cSmartCardSlotEmuCrypto(void); 01399 }; 01400 01401 static cSmartCardSlotLinkReg<cSmartCardSlotEmuCrypto> __scs_emucrypto("emucrypto"); 01402 01403 cSmartCardSlotEmuCrypto::cSmartCardSlotEmuCrypto(void) 01404 { 01405 strcpy(devName,"emucrypto"); 01406 } 01407 01408 int cSmartCardSlotEmuCrypto::DeviceWrite(const unsigned char *mem, int len, int delay) 01409 { 01410 PRINTF(L_CORE_SERIAL,"%s: write len=%d delay=%d",devName,len,delay); 01411 Flush(); 01412 cCondWait::SleepMs(300); 01413 PUSH(mem,len); // echo back 01414 //--- 01415 if(cmdStart && len==CMD_LEN) { // new INS 01416 cmdStart=false; 01417 dataLen=mem[LEN_IDX]; 01418 unsigned char data[256]; 01419 memset(data,0,sizeof(data)); 01420 nextSW[0]=0x90; nextSW[1]=0x00; 01421 bool readcmd=false; 01422 switch(mem[0]*256+mem[1]) { 01423 case 0xa4a4: 01424 switch(mem[5]*256+mem[6]) { 01425 case 0x2f01: 01426 case 0x0f00: 01427 case 0x0f20: 01428 //case 0x0f40: 01429 case 0x0f60: 01430 case 0x0e11: 01431 case 0x1f88: 01432 case 0x1f8c: nextSW[0]=0x9f; nextSW[1]=0x11; break; 01433 default: nextSW[0]=0x94; nextSW[1]=0x04; break; 01434 } 01435 break; 01436 case 0xa4a2: 01437 if(mem[2]==1) { 01438 if(mem[4]==3) { 01439 record=0x01; 01440 nextSW[0]=0x9f; nextSW[1]=0x26; 01441 } 01442 else { 01443 record=0x02; 01444 nextSW[0]=0x9f; nextSW[1]=0x42; 01445 } 01446 } 01447 else { 01448 record=mem[5]; 01449 switch(record) { 01450 case 0x80: nextSW[0]=0x9f; nextSW[1]=0x07; break; 01451 case 0xD1: nextSW[0]=0x9f; nextSW[1]=0x04; break; 01452 case 0x9F: nextSW[0]=0x9f; nextSW[1]=0x03; break; 01453 case 0x9E: nextSW[0]=0x9f; nextSW[1]=0x42; break; 01454 case 0xD6: 01455 case 0xC0: nextSW[0]=0x9f; nextSW[1]=0x12; break; 01456 default: nextSW[0]=0x94; nextSW[1]=0x02; break; 01457 } 01458 } 01459 break; 01460 case 0xa4b2: 01461 readcmd=true; 01462 switch(record) { 01463 case 0x01: 01464 if(mem[3]==1) { 01465 nextSW[0]=0x94; nextSW[1]=0x02; 01466 dataLen=0; 01467 } 01468 else { 01469 dataLen=0x26; 01470 static const unsigned char resp[0x26] = { 01471 0x83,0x01,0x88, 01472 0x8c,0x03,0x40,0x30,0x40, 01473 0x8d,0x04,0x16,0xac,0x16,0xba, 01474 0xd5,0x10,'D','u','m','m','y',0,0,0,0,0,0,0,0x12,0x34,0x56,0x67, 01475 0x8f,0x01,0x55, 01476 0x91,0x01,0x40 01477 }; 01478 memcpy(data,resp,sizeof(resp)); 01479 } 01480 break; 01481 case 0x02: 01482 if(mem[3]==1) { 01483 nextSW[0]=0x94; nextSW[1]=0x02; 01484 dataLen=0; 01485 } 01486 else { 01487 dataLen=0x42; 01488 static const unsigned char resp[0x42] = { 01489 0x83,0x01,0x88, 01490 0x8c,0x03,0xA0,0x30,0x40, 01491 0x8d,0x04,0x16,0xac,0x16,0xba, 01492 0xd5,0x10,'D','u','m','m','y',0,0,0,0,0,0,0,0x12,0x34,0x56,0x67, 01493 0x92,0x20,0x00 // ... 01494 }; 01495 memcpy(data,resp,sizeof(resp)); 01496 } 01497 break; 01498 case 0x80: 01499 dataLen=0x07; 01500 data[0]=0x80; data[1]=0x05; data[2]=0x5c; data[3]=0x0c; 01501 data[4]=0x00; data[5]=0xec; data[6]=0x0a; 01502 break; 01503 case 0xD1: 01504 dataLen=0x04; 01505 data[0]=0xd1; data[1]=0x02; data[2]=0x0d; data[3]=0x22; 01506 break; 01507 case 0x9F: 01508 dataLen=0x03; 01509 data[0]=0x9f; data[1]=0x01; data[2]=0x88; 01510 break; 01511 case 0x9E: 01512 { 01513 dataLen=0x42; 01514 static const unsigned char resp[0x42] = { 01515 0x9E,0x40, 01516 0x28,0xFE, 01517 }; 01518 memcpy(data,resp,sizeof(resp)); 01519 flag=true; 01520 break; 01521 } 01522 case 0xC0: 01523 case 0xD6: 01524 dataLen=0x12; 01525 data[0]=record; 01526 data[1]=0x10; 01527 memset(data+2,0,16); 01528 strcpy((char *)data+2,"Dum Issuer"); 01529 break; 01530 } 01531 break; 01532 case 0xa4b8: 01533 readcmd=true; 01534 if(mem[2]==0) { 01535 dataLen=0x0C; 01536 memset(data,0,0x0c); 01537 data[0]=0xDF; data[1]=0x0A; data[4]=0xDF; data[5]=0x88; 01538 } 01539 else { 01540 dataLen=0; 01541 nextSW[0]=0x94; nextSW[1]=0x02; 01542 } 01543 break; 01544 case 0xa44c: 01545 nextSW[0]=0x9f; nextSW[1]=flag ? 0x42 : 0x1c; 01546 break; 01547 case 0xa4c0: 01548 readcmd=true; 01549 if(mem[4]==0x1c) { 01550 data[0]=0xdb; data[1]=0x10; 01551 memset(&data[2],0x45,16); 01552 data[18]=0xdf; data[19]=0x08; data[20]=0x50; data[23]=0x80; 01553 } 01554 else if(mem[4]==0x11) { 01555 memset(data,0,0x11); 01556 data[0]=0xdf; data[1]=0x0f; data[6]=0x3f; data[7]=0x6a; 01557 } 01558 else if(mem[4]==0x42) { 01559 static const unsigned char resp[0x42] = { 01560 0xdf,0x40, 01561 0x6d,0xbb,0x81, // ... 01562 }; 01563 memcpy(data,resp,sizeof(resp)); 01564 } 01565 break; 01566 } 01567 if(readcmd) { 01568 if(dataLen>0) { 01569 PUSHB(mem[INS_IDX]); // ACK byte 01570 PUSH(data,dataLen); 01571 } 01572 PUSH(nextSW,2); 01573 cmdStart=true; 01574 } 01575 else { 01576 PUSHB(mem[INS_IDX]); // ACK byte 01577 } 01578 } 01579 else { 01580 dataLen-=len; 01581 if(dataLen<=0 && !cmdStart) { 01582 PUSH(nextSW,2); 01583 cmdStart=true; 01584 } 01585 } 01586 //--- 01587 return len; 01588 } 01589 01590 void cSmartCardSlotEmuCrypto::EmuPushAtr(void) 01591 { 01592 static const unsigned char atr[] = { 0x3B,0x78,0x12,0x00,0x00, 01593 0x65,0xC4,0x05,0x05,0x8F,0xF1,0x90,0x00 }; 01594 PUSH(atr,sizeof(atr)); 01595 } 01596 01597 // -- cSmartCardSlotEmuIrdeto -------------------------------------------------- 01598 01599 class cSmartCardSlotEmuIrdeto : public cSmartCardSlotEmuGeneric { 01600 private: 01601 bool acs384; 01602 protected: 01603 virtual bool DeviceOpen(const char *cfg); 01604 virtual int DeviceWrite(const unsigned char *mem, int len, int delay=0); 01605 virtual void EmuPushAtr(void); 01606 public: 01607 cSmartCardSlotEmuIrdeto(void); 01608 }; 01609 01610 static cSmartCardSlotLinkReg<cSmartCardSlotEmuIrdeto> __scs_emuirdeto("emuirdeto"); 01611 01612 cSmartCardSlotEmuIrdeto::cSmartCardSlotEmuIrdeto(void) 01613 { 01614 strcpy(devName,"emuirdeto"); 01615 acs384=false; 01616 } 01617 01618 bool cSmartCardSlotEmuIrdeto::DeviceOpen(const char *cfg) 01619 { 01620 char acs[32]; 01621 if(sscanf(cfg,"%31[^:]",acs)>=0) { 01622 if(!strcasecmp(acs,"acs384")) acs384=true; 01623 else if(!strcasecmp(acs,"acs383")) acs384=false; 01624 else { 01625 PRINTF(L_GEN_ERROR,"unknown ACS type"); 01626 return false; 01627 } 01628 return cSmartCardSlotEmuGeneric::DeviceOpen(0); 01629 } 01630 else PRINTF(L_GEN_ERROR,"bad parameter for cardslot type '%s'",devName); 01631 return false; 01632 } 01633 01634 int cSmartCardSlotEmuIrdeto::DeviceWrite(const unsigned char *mem, int len, int delay) 01635 { 01636 PRINTF(L_CORE_SERIAL,"%s: write len=%d delay=%d",devName,len,delay); 01637 Flush(); 01638 cCondWait::SleepMs(300); 01639 PUSH(mem,len); // echo back 01640 //--- 01641 static const struct Resp { 01642 unsigned int cmd; 01643 int acs; 01644 unsigned char data[MAX_LEN]; 01645 } resp[] = { 01646 { 0x01020203,0x384, 01647 {0x01,0x02,0x00,0x00,0x02,0x00,0x00,0x10,0x03,0x84,0x00,0x00,0x00,0x17,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x47,0x45,0x52} }, 01648 { 0x01020E02,0x384, 01649 {0x01,0x02,0x00,0x00,0x0e,0x02,0x00,0x40,0xa9,0x6d,0x73,0x97,0x9e,0xfc,0x9b,0x8e,0x5b,0x8c,0xfa,0xb2,0x0c,0xb2,0x57,0x0f,0xb2,0xf7,0x29,0x4e,0xa2,0xcb,0xbd,0x5b,0x52,0x74,0xb1,0x2a,0xb7,0xc5,0xd9,0x62,0x6d,0x37,0x6d,0x9d,0xa3,0xe9,0x61,0xbb,0x1b,0x2b,0x56,0xb7,0x86,0x0c,0xe6,0xb1,0x07,0x6f,0xe0,0xf8,0x8a,0xd3,0x05,0x83,0xf6,0x53,0x0e,0xd2,0x72,0xd5,0xc1,0x50} }, 01650 { 0x01020E03,0x384, 01651 {0x01,0x02,0x00,0x00,0x0e,0x03,0x00,0x40,0xb6,0xde,0xa8,0xce,0x86,0x1c,0x42,0x72,0xa8,0x16,0x4b,0xf9,0xce,0x33,0xb5,0x43,0xd0,0x50,0xe6,0xa7,0xf1,0xcb,0x55,0x25,0x97,0x13,0xee,0x62,0x98,0xe7,0x17,0x50,0xeb,0x3b,0x59,0x10,0x0a,0xb6,0x2e,0x93,0x61,0x71,0x3c,0xe6,0xe2,0x2c,0x1e,0x7d,0xbd,0x6a,0x49,0xbb,0x04,0x5b,0xdf,0x2f,0xb7,0xa7,0x93,0xe0,0x3d,0x40,0x4e,0xd1} }, 01652 // 01653 { 0x01020203,0x383, 01654 {0x01,0x02,0x00,0x00,0x02,0x00,0x00,0x10,0x03,0x83,0x00,0x00,0x00,0x17,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x47,0x45,0x52} }, 01655 { 0x01020E02,0x383, 01656 {0x01,0x02,0x00,0x00,0x0E,0x02,0x00,0x40,0x65,0xEF,0xD0,0xA7,0xF3,0x80,0x48,0x0E,0xC1,0x4B,0x41,0x6C,0xDB,0x68,0x47,0xE4,0x23,0xAD,0x96,0x12,0x07,0x58,0x58,0x29,0xE9,0x14,0x27,0x7F,0x7D,0xF8,0xC2,0x65,0x76,0x4D,0x75,0x04,0x7C,0x9B,0xAA,0x99,0x58,0xEA,0xE2,0x43,0xB5,0x03,0x05,0xD6,0x62,0x99,0xF5,0x18,0x16,0x4E,0xCF,0x49,0x11,0xBD,0xF3,0xEE,0xC3,0xCD,0x90,0x3B} }, 01657 { 0x01020E03,0x383, 01658 {0x01,0x02,0x00,0x00,0x0E,0x03,0x00,0x40,0x9B,0x06,0xB5,0x0A,0x98,0xC6,0x2E,0x1D,0x71,0xA1,0xE8,0x84,0xAE,0x98,0x57,0xE9,0xE6,0xC2,0x97,0x46,0x25,0x7A,0x2B,0xA1,0xD5,0x33,0x18,0xDE,0x16,0xC1,0xAB,0x22,0x2C,0xC2,0x11,0x24,0x81,0x11,0xA8,0x39,0xE3,0xB1,0xDB,0x33,0x1A,0x93,0x31,0xB0,0x61,0xD8,0xDE,0x92,0x1F,0x29,0x20,0xD0,0x9E,0x0F,0x6A,0xF0,0x7C,0xBA,0xCD,0xCC} }, 01659 // 01660 { 0x01020003,0x0, 01661 {0x01,0x02,0x00,0x00,0x00,0x03,0x00,0x14,0x37,0x30,0x31,0x32,0x30,0x36,0x39,0x33,0x34,0x37,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} }, 01662 { 0x01020103,0x0, 01663 {0x01,0x02,0x00,0x00,0x01,0x00,0x00,0x10,0x00,0x17,0x00,0x00,0x01,0x00,0x17,0x00,0x00,0x01,0x04,0x00,0xF3,0x86,0x01,0x1A} }, 01664 { 0x01021100,0x0, 01665 {0x01,0x02,0x58,0x00,0x11,0x00,0x00,0x00} }, 01666 { 0x01020903,0x0, 01667 {0x01,0x02,0x55,0x00,0x09,0x03,0x00,0x00} }, 01668 { 0x01020303,0x0, 01669 {0x01,0x02,0x00,0x00,0x03,0x03,0x02,0x18,0x0F,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} }, 01670 { 0x01020400,0x0, 01671 {0x01,0x02,0x54,0x00,0x04,0x00,0x00,0x00} }, 01672 { 0x01050000,0x0, 01673 {0x01,0x05,0x9D,0x00,0x38,0x00,0x02,0x16,0x00,0x01,0x00,0x13,0xFF,0xFF,0x22,0x88,0xBF,0x02,0x70,0xFA,0x5F,0x80,0xFD,0x1E,0xD4,0xD6,0xF0,0xF1,0x81,0xB3} }, 01674 { 0x01010000,0x0, 01675 {0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0xFF} }, 01676 { 0x00000000,0x0, // don't delete this one 01677 {} } 01678 }; 01679 const unsigned int cmd=(mem[0]<<24) + (mem[1]<<16) + (mem[2]<<8) + mem[3]; 01680 const struct Resp *r=&resp[0]; 01681 int acs=acs384 ? 0x384:0x383; 01682 while(1) { 01683 if(!r->cmd) { 01684 static const unsigned char fail[] = { 0x01,0x99,0x6f }; 01685 PUSH(fail,sizeof(fail)); 01686 break; 01687 } 01688 if(cmd==r->cmd && (!r->acs || r->acs==acs)) { 01689 const int len=r->data[7]+9-1; 01690 int cs=0x3f; 01691 for(int i=0 ; i<len ; i++) cs ^= r->data[i]; 01692 PUSH(r->data,len); 01693 PUSHB(cs); 01694 break; 01695 } 01696 r++; 01697 } 01698 //--- 01699 return len; 01700 } 01701 01702 void cSmartCardSlotEmuIrdeto::EmuPushAtr(void) 01703 { 01704 static const unsigned char atr384[] = { 0x3B,0x9F,0x21,0x0E, 01705 0x49,0x52,0x44,0x45,0x54,0x4f,0x20,0x41,0x43,0x53,0x03,0x84,0x55,0xff,0x80,0x6d }; 01706 static const unsigned char atr383[] = { 0x3B,0x9F,0x21,0x0E, 01707 0x49,0x52,0x44,0x45,0x54,0x4F,0x20,0x41,0x43,0x53,0x03,0x83,0x95,0x00,0x80,0x55 }; 01708 if(acs384) PUSH(atr384,sizeof(atr384)) 01709 else PUSH(atr383,sizeof(atr383)) 01710 } 01711 01712 // -- cSmartCardSlotEmuNagra -------------------------------------------------- 01713 01714 class cSmartCardSlotEmuNagra : public cSmartCardSlotEmuGeneric { 01715 private: 01716 int toggle; 01717 int dt_count[16]; 01718 protected: 01719 virtual void DeviceToggleReset(void); 01720 virtual int DeviceWrite(const unsigned char *mem, int len, int delay=0); 01721 virtual void EmuPushAtr(void); 01722 public: 01723 cSmartCardSlotEmuNagra(void); 01724 }; 01725 01726 static cSmartCardSlotLinkReg<cSmartCardSlotEmuNagra> __scs_emunagra("emunagra"); 01727 01728 cSmartCardSlotEmuNagra::cSmartCardSlotEmuNagra(void) 01729 { 01730 strcpy(devName,"emunagra"); 01731 toggle=0; 01732 memset(dt_count,0,sizeof(dt_count)); 01733 } 01734 01735 void cSmartCardSlotEmuNagra::DeviceToggleReset(void) 01736 { 01737 toggle=0; 01738 memset(dt_count,0,sizeof(dt_count)); 01739 cSmartCardSlotEmuGeneric::DeviceToggleReset(); 01740 } 01741 01742 int cSmartCardSlotEmuNagra::DeviceWrite(const unsigned char *mem, int len, int delay) 01743 { 01744 PRINTF(L_CORE_SERIAL,"%s: write len=%d delay=%d",devName,len,delay); 01745 Flush(); 01746 cCondWait::SleepMs(100); 01747 PUSH(mem,len); // echo back 01748 01749 // for this sample data: 01750 // BOXKEY: BB99FF99BB997788 01751 // CARDMOD: 9A2AE686F360A8F63B679E05443FE32969DE606A8521A48003A9C904F53FCE34D6D62B3DA6A9EF090556559068B4B127213A6EC310E629AEA7286D6B46AB6519 01752 // -> SESSKEY: 9d2cd4cbc4b22bdf65c5c2d8506a2927 01753 static const struct Resp { 01754 int cmd, cc; 01755 unsigned int idata; 01756 unsigned char data[MAX_LEN]; 01757 } resp[] = { 01758 /* status */ { 0xC0, 0,0x00000000, { 0x08,0xb0,0x04,0x00,0x13,0x00,0x20,0x90,0x00 } }, 01759 /* datetim */ { 0xC8, 0,0x00000000, { 0x08,0xb8,0x04,0x00,0x00,0x00,0x00,0x90,0x00 } }, 01760 /* card ID*/ { 0x12, 0,0x00000000, { 0x08,0x92,0x04,0x71,0x2A,0x3B,0x4C,0x90,0x00 } }, 01761 /* IRDINFO */ { 0x22, 0,0x00000000, { 0x3b,0xA2,0x37,0x2A,0xFF,0x90,0x00,0x00,0x00,0x01,0x01,0xE9,0x01,0x01,0x01,0x12,0x3B,0x4F,0x5C,0x00,0x00,0x00,0x01,0x60,0x62,0x18,0x7A,0xA8,0xBE,0x10,0x5C,0x4F,0x3B,0x12,0x31,0x37,0x42,0x42,0x44,0x41,0x4C,0x44,0x50,0x34,0x35,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x00 } }, 01762 /* */ { 0x22,-1,0x00000080, { 0x3b,0xa2,0x37,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x00 } }, 01763 /* DT01 */ { 0x22, 0,0x00000001, { 0x10,0xa2,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x00 } }, 01764 /* DT04 */ { 0x22, 0,0x00000004, { 0x46,0xa2,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x00 } }, 01765 /* */ { 0x22,-1,0x00000084, { 0x46,0xa2,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x00 } }, 01766 /* TIERS */ { 0x22, 0,0x00000005, { 0x59,0xa2,0x55,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x00 } }, 01767 /* */ { 0x22,-1,0x00000085, { 0x59,0xa2,0x55,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x00 } }, 01768 /* DT06 */ { 0x22, 0,0x00000006, { 0x18,0xa2,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x00 } }, 01769 /* CAMDATA */ { 0x22, 0,0x00000008, { 0x57,0xa2,0x53,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x00 } }, 01770 /* */ { 0x22,-1,0x00000088, { 0x57,0xa2,0x53,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x00 } }, 01771 /* CMD 26 */ { 0x26, 0,0x123b4f5c, { 0x44,0xa6,0x40,0xa1,0x36,0x96,0xdc,0x3d,0x43,0x98,0xc9,0xd3,0xda,0x73,0xca,0x67,0x37,0x75,0xf0,0x29,0x33,0x6c,0xf9,0x2c,0xb4,0xdd,0x0e,0x18,0xaf,0x9e,0x24,0xb8,0x56,0xa2,0x04,0xd9,0xbf,0x7b,0xf5,0xc2,0x64,0xc4,0x61,0xd0,0xce,0x33,0xa7,0x13,0x56,0x68,0xcd,0xb2,0xa5,0x54,0x04,0xce,0x79,0x72,0x1a,0xde,0x9a,0xc4,0x92,0x2c,0x49,0x4f,0x85,0x90,0x00 } }, 01772 /* CMD 27 */ { 0x27, 0,0xfecd819a, { 0x04,0xa7,0x00,0x90,0x00 } }, 01773 // don't remove this one 01774 /* END */ { 0xFF, 0,0x00000000, { 0x0 }} }; 01775 01776 unsigned char *rmem=AUTOMEM(len); 01777 memcpy(rmem,mem,len); 01778 Invert(rmem,len); 01779 01780 unsigned char buff[MAX_LEN+16]; 01781 int c=0; 01782 if(rmem[0]==0x21 && rmem[1]==0xc1) { // IFS 01783 buff[c++]=0x12; 01784 buff[c++]=0x00; 01785 buff[c++]=0x00; 01786 buff[c++]=0x00; 01787 } 01788 else { 01789 int cmd=rmem[8], ilen=rmem[9]; 01790 unsigned int idata=0; 01791 if(ilen>0) { 01792 if(ilen>4) ilen=4; 01793 for(int i=0; i<ilen; i++) idata=(idata<<8) | rmem[10+i]; 01794 } 01795 bool isdt = (cmd==0x22); 01796 for(const struct Resp *r=&resp[0]; 1 ;r++) { 01797 if(r->cmd==0xFF) { 01798 static const unsigned char fail[] = { 0x12,0x82,0x00,0x90 }; 01799 c=sizeof(fail); 01800 memcpy(buff,fail,c); 01801 break; 01802 } 01803 if(cmd==r->cmd && idata==r->idata && (!isdt || dt_count[idata&0xF]==r->cc || r->cc<0)) { 01804 buff[c++]=0x12; 01805 buff[c++]=toggle; toggle^=0x40; 01806 unsigned int l=r->data[0]+1; 01807 memcpy(&buff[c],r->data,l); 01808 c+=l; 01809 if(isdt) { 01810 dt_count[idata&0xF]++; 01811 PRINTF(L_CORE_SERIAL,"%s: dt%02x count now %d",devName,idata&0xf,dt_count[idata&0xF]); 01812 } 01813 break; 01814 } 01815 } 01816 } 01817 if(c>0) { 01818 buff[c]=XorSum(buff,c); c++; 01819 Invert(buff,c); 01820 PUSH(buff,c); 01821 } 01822 return len; 01823 } 01824 01825 void cSmartCardSlotEmuNagra::EmuPushAtr(void) 01826 { 01827 static const unsigned char atr[] = { 0x03,0x00,0x56,0xff,0x00,0x76,0x7e,0x71,0x80,0x1d,0xff,0xdd,0x8d,0x7d,0x35,0xf5,0xb3,0xd3,0x73,0xfb,0xdd,0x31,0xe9,0xed,0xf3,0x33,0x9f }; 01828 PUSH(atr,sizeof(atr)) 01829 } 01830 01831 #endif // CARD_EMU 01832 01833 // -- cInfoStr ----------------------------------------------------------------- 01834 01835 cInfoStr::cInfoStr(void) 01836 :cLineBuff(256) 01837 { 01838 current=0; 01839 } 01840 01841 cInfoStr::~cInfoStr() 01842 { 01843 free(current); 01844 } 01845 01846 bool cInfoStr::Get(char *buff, int len) 01847 { 01848 cMutexLock lock(&mutex); 01849 if(current && current[0]) { 01850 strn0cpy(buff,current,len); 01851 return true; 01852 } 01853 return false; 01854 } 01855 01856 void cInfoStr::Begin(void) 01857 { 01858 Flush(); 01859 } 01860 01861 void cInfoStr::Finish() 01862 { 01863 cMutexLock lock(&mutex); 01864 free(current); 01865 current=Grab(); 01866 } 01867 01868 // -- cSmartCardData ----------------------------------------------------------- 01869 01870 cSmartCardData::cSmartCardData(int Ident) 01871 { 01872 ident=Ident; 01873 } 01874 01875 // -- cSmartCardDatas ---------------------------------------------------------- 01876 01877 class cSmartCardDatas : public cStructList<cSmartCardData> { 01878 protected: 01879 virtual cStructItem *ParseLine(char *line); 01880 public: 01881 cSmartCardDatas(void); 01882 cSmartCardData *Find(cSmartCardData *param); 01883 }; 01884 01885 static cSmartCardDatas carddatas; 01886 01887 cSmartCardDatas::cSmartCardDatas(void) 01888 :cStructList<cSmartCardData>("smartcard data","smartcard.conf",SL_MISSINGOK|SL_WATCH|SL_VERBOSE) 01889 {} 01890 01891 cSmartCardData *cSmartCardDatas::Find(cSmartCardData *param) 01892 { 01893 ListLock(false); 01894 cSmartCardData *cd; 01895 for(cd=First(); cd; cd=Next(cd)) 01896 if(cd->Ident()==param->Ident() && cd->Matches(param)) break; 01897 ListUnlock(); 01898 return cd; 01899 } 01900 01901 cStructItem *cSmartCardDatas::ParseLine(char *line) 01902 { 01903 char *r=index(line,':'); 01904 if(r) 01905 for(cSmartCardLink *scl=smartcards.First(); scl; scl=smartcards.Next(scl)) 01906 if(!strncasecmp(scl->Name(),line,r-line)) { 01907 cSmartCardData *scd=scl->CreateData(); 01908 if(scd && scd->Parse(r+1)) return scd; 01909 delete scd; 01910 break; 01911 } 01912 return 0; 01913 } 01914 01915 // -- cSmartCard --------------------------------------------------------------- 01916 01917 cSmartCard::cSmartCard(const struct CardConfig *Cfg, const struct StatusMsg *Msg) 01918 { 01919 msg=Msg; 01920 slot=0; sb=0; atr=0; idStr[0]=0; cardUp=false; 01921 NewCardConfig(Cfg); 01922 } 01923 01924 void cSmartCard::NewCardConfig(const struct CardConfig *Cfg) 01925 { 01926 cfg=Cfg; 01927 if(slot) slot->SetCardConfig(cfg); 01928 } 01929 01930 bool cSmartCard::GetCardIdStr(char *str, int len) 01931 { 01932 strn0cpy(str,idStr,len); 01933 return (str[0]!=0); 01934 } 01935 01936 bool cSmartCard::GetCardInfoStr(char *str, int len) 01937 { 01938 return infoStr.Get(str,len); 01939 } 01940 01941 bool cSmartCard::Setup(cSmartCardSlot *Slot, int sermode, const struct Atr *Atr, unsigned char *Sb) 01942 { 01943 slot=Slot; atr=Atr; sb=Sb; 01944 slotnum=slot->SlotNum(); slot->SetCardConfig(cfg); 01945 cardUp=false; 01946 if(cfg->SerMode==sermode && Init()) cardUp=true; 01947 return cardUp; 01948 } 01949 01950 int cSmartCard::SerRead(unsigned char *data, int len, int to) 01951 { 01952 if(atr->T==1 || atr->T==14) return slot->RawRead(data,len,to); 01953 PRINTF(L_CORE_SC,"%d: SerRead() not allowed for ISO compliant cards (T=%d)",slotnum,atr->T); 01954 return -1; 01955 } 01956 01957 int cSmartCard::SerWrite(const unsigned char *data, int len) 01958 { 01959 if(atr->T==1 || atr->T==14) return slot->RawWrite(data,len); 01960 PRINTF(L_CORE_SC,"%d: SerWrite() not allowed for ISO compliant cards (T=%d)",slotnum,atr->T); 01961 return -1; 01962 } 01963 01964 bool cSmartCard::IsoRead(const unsigned char *cmd, unsigned char *data) 01965 { 01966 if(atr->T==0) return slot->IsoRead(cmd,data); 01967 PRINTF(L_CORE_SC,"%d: can't IsoRead() from incompatible card (T=%d)",slotnum,atr->T); 01968 return false; 01969 } 01970 01971 bool cSmartCard::IsoWrite(const unsigned char *cmd, const unsigned char *data) 01972 { 01973 if(atr->T==0) return slot->IsoWrite(cmd,data); 01974 PRINTF(L_CORE_SC,"%d: can't IsoWrite() to incompatible card (T=%d)",slotnum,atr->T); 01975 return false; 01976 } 01977 01978 bool cSmartCard::Status(void) 01979 { 01980 const struct StatusMsg *m=msg; 01981 while(m->sb[0]!=0xFF) { 01982 if(sb[0]==m->sb[0] && (m->sb[1]==0xFF || sb[1]==m->sb[1])) { 01983 if(!m->retval) PRINTF(L_CORE_SC,"%d: %s (status: %02x %02x)",slotnum,m->message,sb[0],sb[1]); 01984 return m->retval; 01985 } 01986 m++; 01987 } 01988 PRINTF(L_CORE_SC,"%d: unknown (status: %02x %02x)",slotnum,sb[0],sb[1]); 01989 return false; 01990 } 01991 01992 int cSmartCard::CheckSctLen(const unsigned char *data, int off) 01993 { 01994 int l=SCT_LEN(data); 01995 if(l+off > MAX_LEN) { 01996 PRINTF(L_CORE_SC,"section too long %d > %d",l,MAX_LEN-off); 01997 l=-1; 01998 } 01999 return l; 02000 } 02001 02002 void cSmartCard::CaidsChanged(void) 02003 { 02004 cGlobal::CaidsChanged(); 02005 } 02006 02007 // -- cSmartCardLink ----------------------------------------------------------- 02008 02009 cSmartCardLink::cSmartCardLink(const char *Name, int Id) 02010 { 02011 name=Name; id=Id; 02012 cSmartCards::Register(this); 02013 } 02014 02015 // -- cSmartCards -------------------------------------------------------------- 02016 02017 cSmartCardLink *cSmartCards::first=0; 02018 02019 cSmartCards smartcards; 02020 02021 void cSmartCards::Register(cSmartCardLink *scl) 02022 { 02023 PRINTF(L_CORE_DYN,"registering %s smartcard (id %x)",scl->name,scl->id); 02024 scl->next=first; 02025 first=scl; 02026 } 02027 02028 void cSmartCards::Shutdown(void) 02029 { 02030 carddatas.SafeClear(); 02031 cardslots.SafeClear(); 02032 } 02033 02034 void cSmartCards::Disable(void) 02035 { 02036 carddatas.Disable(); 02037 cardslots.Disable(); 02038 } 02039 02040 cSmartCardData *cSmartCards::FindCardData(cSmartCardData *param) 02041 { 02042 return carddatas.Find(param); 02043 } 02044 02045 bool cSmartCards::HaveCard(int id) 02046 { 02047 bool res=false; 02048 for(cSmartCardSlot *slot=cardslots.FirstSlot(); slot; slot=cardslots.Next(slot)) 02049 if(slot->HaveCard(id)) { res=true; break; } 02050 cardslots.Release(); 02051 return res; 02052 } 02053 02054 cSmartCard *cSmartCards::LockCard(int id) 02055 { 02056 cSmartCard *sc=0; 02057 for(cSmartCardSlot *slot=cardslots.FirstSlot(); slot; slot=cardslots.Next(slot)) 02058 if((sc=slot->LockCard(id))) break; 02059 cardslots.Release(); 02060 return sc; 02061 } 02062 02063 void cSmartCards::ReleaseCard(cSmartCard *sc) 02064 { 02065 for(cSmartCardSlot *slot=cardslots.FirstSlot(); slot; slot=cardslots.Next(slot)) 02066 slot->ReleaseCard(sc); 02067 cardslots.Release(); 02068 } 02069 02070 bool cSmartCards::ListCard(int num, char *str, int len) 02071 { 02072 cSmartCardSlot *slot=cardslots.GetSlot(num); 02073 str[0]=0; 02074 bool res=false; 02075 if(slot) { slot->GetCardIdStr(str,len); res=true; } 02076 cardslots.Release(); 02077 return res; 02078 } 02079 02080 bool cSmartCards::CardInfo(int num, char *str, int len) 02081 { 02082 cSmartCardSlot *slot=cardslots.GetSlot(num); 02083 str[0]=0; 02084 bool res=false; 02085 if(slot) res=slot->GetCardInfoStr(str,len); 02086 cardslots.Release(); 02087 return res; 02088 } 02089 02090 void cSmartCards::CardReset(int num) 02091 { 02092 cSmartCardSlot *slot=cardslots.GetSlot(num); 02093 if(slot) slot->TriggerReset(); 02094 cardslots.Release(); 02095 }