📄 smartcard.c
字号:
LBSTARTF(L_CORE_SC); LBPUT("%d: <- PROC: ",id); do { do { if(Read(&buff,1,cfg->workTO)<=0) return -1; LBPUT("%02x ",buff); } while(buff==0x60); if((buff&0xF0)==0x60 || (buff&0xF0)==0x90) { // SW1/SW2 sb[0]=buff; if(Read(&buff,1)<=0) return -1; LBPUT("%02x",buff); sb[1]=buff; return 0; } else { if((buff&0xFE)==(ins&0xFE)) r=restLen; else if((~buff&0xFE)==(ins&0xFE)) r=1; else { LBPUT("cannot handle procedure %02x (ins=%02x)\n",buff,ins); return -1; } if(r>restLen) { LBPUT("data overrun r=%d restLen=%d\n",r,restLen); return -1; } } } while(r==0); LBEND(); return r;}bool cSmartCard::IsoRead(const unsigned char *cmd, unsigned char *data){ if(atr->T==0) { // only for ISO complaint cards LDUMP(L_CORE_SC,cmd,CMD_LEN,"%d: -> INS:",id); if(Write(cmd,CMD_LEN)<0) return Test(false); int tr=cmd[LEN_IDX] ? cmd[LEN_IDX] : 256; int len=0; while(1) { int r=Procedure(cmd[INS_IDX],tr-len); if(r<=0) return Test(r==0); if(Read(data+len,r)<0) return Test(false); LDUMP(L_CORE_SC,data+len,r,"%d: <- DATA:",id); len+=r; } } else PRINTF(L_CORE_SC,"%d: can't IsoRead() from incompatible card (T=%d)",id,atr->T); return false;}bool cSmartCard::IsoWrite(const unsigned char *cmd, const unsigned char *data){ if(atr->T==0) { // only for ISO complaint cards LDUMP(L_CORE_SC,cmd,CMD_LEN,"%d: -> INS:",id); if(Write(cmd,CMD_LEN)<0) return Test(false); int len=0; while(1) { int r=Procedure(cmd[INS_IDX],cmd[LEN_IDX]-len); if(r<=0) return Test(r==0); if(Write(data+len,r)<0) return Test(false); LDUMP(L_CORE_SC,data+len,r,"%d: -> DATA:",id); len+=r; } } else PRINTF(L_CORE_SC,"%d: can't IsoWrite() to incompatible card (T=%d)",id,atr->T); return false;}bool cSmartCard::Test(bool res){ if(!res) { TriggerReset(); PRINTF(L_CORE_SC,"%d: reset triggered",id); } return res;}bool cSmartCard::Status(void){ const struct StatusMsg *m=msg; while(m->sb[0]!=0xFF) { if(sb[0]==m->sb[0] && (m->sb[1]==0xFF || sb[1]==m->sb[1])) { if(!m->retval) PRINTF(L_CORE_SC,"%d: %s (status: %02x %02x)",id,m->message,sb[0],sb[1]); return m->retval; } m++; } PRINTF(L_CORE_SC,"%d: unknown (status: %02x %02x)",id,sb[0],sb[1]); return false;}int cSmartCard::CheckSctLen(const unsigned char *data, int off){ int l=SCT_LEN(data); if(l+off > MAX_LEN) { PRINTF(L_CORE_SC,"section too long %d > %d",l,MAX_LEN-off); l=-1; } return l;}// -- cSmartCardData -----------------------------------------------------------cSmartCardData::cSmartCardData(int Ident){ ident=Ident;}// -- cSmartCardLink -----------------------------------------------------------cSmartCardLink::cSmartCardLink(const char *Name, int Id){ name=Name; id=Id; cSmartCards::Register(this);}// -- cSmartCards --------------------------------------------------------------cSmartCardLink *cSmartCards::first=0;cSmartCards smartcards;static const char *serModes[] = { 0,"8e2","8o2","8n2" };cSmartCards::cSmartCards(void):cThread("SmartcardWatcher"){ for(int i=0 ; i<MAX_PORTS ; i++) ports[i].Serial=0; firstRun=true;}void cSmartCards::Register(cSmartCardLink *scl){ PRINTF(L_CORE_DYN,"registering %s smartcard (id %x)",scl->name,scl->id); scl->next=first; first=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!");}void cSmartCards::Shutdown(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; } } dataList.Clear(); mutex.Unlock();}bool cSmartCards::AddPort(const char *devName, bool invCD, bool invRST, int clock){ 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; } 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; } } PRINTF(L_GEN_ERROR,"only %d serial ports supported",MAX_PORTS); return false;}void cSmartCards::LoadData(const char *cfgdir){ mutex.Lock(); dataList.Clear(); ConfRead("smartcard data",AddDirectory(cfgdir,DATAFILE)); mutex.Unlock();}bool cSmartCards::ParseLine(const char *line, bool fromCache){ char *r=index(line,':'); if(!r) return false; for(cSmartCardLink *scl=first; scl; scl=scl->next) { if(!strncasecmp(scl->name,line,r-line)) { cSmartCardData *scd=scl->CreateData(); if(scd && scd->Parse(r+1)) { dataList.Add(scd); break; } else { delete scd; return false; } } } return true;}cSmartCardData *cSmartCards::FindCardData(cSmartCardData *param){ cMutexLock lock(&mutex); for(cSmartCardData *cd=dataList.First(); cd; cd=dataList.Next(cd)) if(cd->ident==param->ident && cd->Matches(param)) return cd; return 0;}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; return false;}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++; mutex.Unlock(); cSmartCard *sc=ports[i].Card; sc->Lock(); if(CardInserted(ports[i].Serial) && sc->CardUp() && !sc->NeedsReset()) return sc; // if failed, unlock the card and decrement UseCount sc->Unlock(); mutex.Lock(); ports[i].UseCount--; cond.Broadcast(); break; } } mutex.Unlock(); return 0;}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--; cond.Broadcast(); mutex.Unlock(); return; } } mutex.Unlock(); PRINTF(L_GEN_DEBUG,"internal: can't find port in cSmartCards::ReleaseCard()");}bool cSmartCards::CardInserted(cSerial *ser){ return ser->CheckCAR();}bool cSmartCards::CardReset(struct Port *port){ if(Reset(port)<2 || !cSmartCard::ParseAtr(&port->Atr,port->PortNum,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)) return false; } return true;}int cSmartCards::Reset(struct Port *port){ cSerial *ser=port->Serial; PRINTF(L_CORE_SC,"%d: reseting card (sermode %s)",port->PortNum,serModes[ser->CurrentMode()]); ser->ToggleRTS(); cCondWait::SleepMs(20); 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); return r;}bool cSmartCards::DoPTS(struct Port *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; int baud=(int)((float)port->Clock*atr->D/atr->F); PRINTF(L_CORE_SC,"%d: PTS cycle: calculated baudrate %d",id,baud); if(atr->Tspec<0) { PRINTF(L_CORE_SC,"%d: negotiable mode",id);#ifdef NO_PTS_PROTO PRINTF(L_CORE_SC,"%d: PTS disabled at compile time!!!",id); return true;#else unsigned char req[4], conf[16]; req[0]=0xFF; req[1]=0x10 | atr->T; req[2]=atr->TA1; req[3]=XorSum(req,3); LDUMP(L_CORE_SC,req,4,"%d: PTS request:",id); if(ser->Write(req,4)!=4) { PRINTF(L_CORE_SC,"%d: PTS request, write failed",id); return false; } if(ser->Read(conf,4,100,100)!=4) { PRINTF(L_CORE_SC,"%d: PTS request, echo readback failed",id); return false; } int n=ser->Read(conf,-16,200,1000); if(n>0) LDUMP(L_CORE_SC,conf,n,"%d: PTS confirm:",id); if(n<1 || conf[0]!=0xFF || XorSum(conf,n)!=0) { PRINTF(L_CORE_SC,"%d: PTS confirm, bad format",id); return false; } if(n<4 || conf[1]!=req[1] || conf[2]!=req[2]) { PRINTF(L_CORE_SC,"%d: PTS not confirmed",id); return false; }#endif // NO_PTS_PROTO } else PRINTF(L_CORE_SC,"%d: specific mode Tspec=%d",id,atr->Tspec); int mode=ser->CurrentMode(); if(atr->N==255) mode|=SM_1SB; if(!ser->SetMode(mode,baud)) { PRINTF(L_CORE_SC,"%d: setting baudrate %d failed",id,baud); return false; } } return true;}void cSmartCards::SetPort(struct Port *port, cSmartCard *sc, int id, bool dead){ mutex.Lock(); while(port->UseCount) cond.Wait(mutex); delete port->Card; port->Card=sc; port->CardId=id; port->Dead=dead; port->UseCount=0; mutex.Unlock();}void cSmartCards::Action(void){ while(Running()) { for(int i=0 ; i<MAX_PORTS ;) { struct Port *port=&ports[i]; cSerial *ser=port->Serial; if(ser) { if(port->Card) { cSmartCard *sc=port->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); } else if(sc->NeedsReset()) { PRINTF(L_CORE_SC,"%d: card reset requested",port->PortNum); if(!ser->SetMode(ser->CurrentMode()&SM_MASK) || !CardReset(port) || !sc->Setup(ser,&port->Atr,port->PortNum)) { sc->Unlock(); sc=0; PRINTF(L_CORE_SC,"%d: card re-init failed",port->PortNum); SetPort(port,0,0,true); } } if(sc) sc->Unlock(); } else if(CardInserted(ser)) { if(!port->Dead) { PRINTF(L_CORE_SC,"%d: new card inserted",port->PortNum); for(int mode=SM_NONE+1 ; mode<SM_MAX ; mode++) { if(ser->SetMode(mode)) { if(CardReset(port)) { cSmartCardLink *scl=first; while(scl) { PRINTF(L_CORE_SC,"%d: checking for %s card",port->PortNum,scl->name); cSmartCard *sc=scl->Create(); if(sc && sc->Setup(ser,&port->Atr,port->PortNum)) { SetPort(port,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); } else PRINTF(L_CORE_SC,"%d: reset/atr error",port->PortNum); } else PRINTF(L_CORE_SC,"%d: failed to set serial mode %s",port->PortNum,serModes[mode]); } port->Dead=true; PRINTF(L_CORE_SC,"%d: can't initialise new card, ignoring port until card reinserted",port->PortNum); } } else { if(port->Dead) PRINTF(L_CORE_SC,"%d: card removed, port reactivated",port->PortNum); port->Dead=false; } }next: i++; } if(firstRun) { mutex.Lock(); cond.Broadcast(); firstRun=false; mutex.Unlock(); } cCondWait::SleepMs(300); } }bool cSmartCards::ListCard(int num, char *str, int len){ if(num>=MAX_PORTS || !ports[num].Serial) return false; str[0]=0; mutex.Lock(); cSmartCard *sc=ports[num].Card; if(sc) { if(!sc->GetCardIdStr(str,len)) { cSmartCardLink *scl=first; while(scl) { if(scl->id==ports[num].CardId) { strn0cpy(str,scl->name,len); break; } scl=scl->next; } } } mutex.Unlock(); return true;}bool cSmartCards::CardInfo(int num, char *str, int len){ bool res=false; if(num<MAX_PORTS && ports[num].Serial) { str[0]=0; mutex.Lock(); cSmartCard *sc=ports[num].Card; if(sc) res=sc->GetCardInfoStr(str,len); mutex.Unlock(); } return res;}void cSmartCards::CardReset(int num){ if(num<MAX_PORTS && ports[num].Serial) { mutex.Lock(); cSmartCard *sc=ports[num].Card; if(sc) sc->TriggerReset(); mutex.Unlock(); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -