PageRenderTime 44ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/PCSCMicro/GemCore/Device.cs

#
C# | 935 lines | 703 code | 50 blank | 182 comment | 149 complexity | 73dd2527d114430220270e5844741734 MD5 | raw file
Possible License(s): GPL-2.0
  1. /***************************************************************************
  2. * This code was adapted from TSPC_CCID.cs which was originally written by *
  3. * Teridian SemiConductor, Corp. It has been modified from its original *
  4. * version to allow for use in the .NET Micro Framework. It has also been *
  5. * adapted to allow for use with the GemCore Serial Lite Pro evaluation *
  6. * board. Additions have been made to the original version to allow for a *
  7. * broader use of the reader. *
  8. * LAST MODIFIED: 2010 April 23 *
  9. * Copyright (C) 2009 Gemalto *
  10. ***************************************************************************/
  11. /***************************************************************************
  12. * Device.cs is part of the PC/SC Micro API for the .NET Micro *
  13. * Framework. *
  14. * *
  15. * The PC/SC Micro API for the .NET Micro Framework is free software: *
  16. * you can redistribute it and/or modify it under the terms of the GNU *
  17. * General Public License as published by the Free Software Foundation, *
  18. * either version 2 of the License, or (at your option) any later version.*
  19. * *
  20. * The PC/SC Micro API for the .NET Micro Framework is distributed in *
  21. * the hope that it will be useful, but WITHOUT ANY WARRANTY; without even*
  22. * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR *
  23. * PURPOSE. See the GNU General Public License for more details. *
  24. * *
  25. * You should have received a copy of the GNU General Public License *
  26. * along with the PC/SC Micro API for the .NET Micro Framework. If not, *
  27. * see <http://www.gnu.org/licenses/>. *
  28. ***************************************************************************/
  29. using System;
  30. using Microsoft.SPOT;
  31. using Microsoft.SPOT.Hardware;
  32. namespace PCSCMicro
  33. {
  34. internal class Device : Reader
  35. {
  36. #region Definition of constants and global variables
  37. // Collecting Data TimeOut Design Setting
  38. int TestTimeOut = 15 * 60; // Timeout for APDU calculated to second
  39. int InitializationTimeOut = 10; // Apply to non-APDU and non-EMV testing command, in second
  40. int TimeOutUnitInMiliSec = 500; // This TimeOut is independent with the ones in Min and Sec
  41. // Hard-coded configuration constants
  42. const string ACK = "60";
  43. const string NACK = "E0";
  44. const string PowerOnSC = "0112FF";
  45. const string PowerOffSC = "0111FF";
  46. const string CheckStatus = "0117FF";
  47. const string SetParametersCommand = "0612";
  48. const string RestartReader = "040C000000FF";
  49. // Dynamic Strings used for commands
  50. string NAD = "42";
  51. string PCB = "00";
  52. string Config_Init;
  53. // Bit to keep track of sent parity
  54. bool pcb = false;
  55. const string onPCB = "40";
  56. const string offPCB = "00";
  57. // Keep track of slot status
  58. const int ACTIVATED = 0;
  59. const int PRESENT = 1;
  60. const int NOCARD = 2;
  61. const int ERROR = 3;
  62. int SlotStatus = NOCARD;
  63. // Maximum number of log lines
  64. const int MaxBytes = 4096;
  65. // Flags used for running processes
  66. bool IsSerialPortOn = false;
  67. bool APDUCommandComplete = true;
  68. bool ActivatingSmartCard = false;
  69. bool CardActivated = false;
  70. bool ResettingCard = false;
  71. // Retry counters for Serial Port Communication
  72. int NumberOfRetries;
  73. int NumberOfGemCoreRetries;
  74. // Serial Port
  75. int baudrate = 9600;
  76. System.IO.Ports.SerialPort ComPort = new System.IO.Ports.SerialPort(System.IO.Ports.Serial.COM1);
  77. // Packet parser
  78. PacketParser Packet = new PacketParser();
  79. // PPS Strings
  80. string Protocol = "00";//Protocol to be set by user later
  81. string FiDi = "11";//FiDi to be set by user later
  82. string PRT = "50"; // T = 0, EDC = LRC, I-Block Sent = 1, I-Block Received = 0
  83. string TC1 = "00";
  84. string TC2_TA3 = "10";
  85. string RFU_TB3 = "00";
  86. // Card characteristics
  87. ReaderError error = ReaderError.NONE;
  88. string atr = null;
  89. #endregion
  90. /*****************************************************************************/
  91. /* */
  92. /* Serial Port Communication: Initialize, Send and Receive Data */
  93. /* */
  94. /*****************************************************************************/
  95. #region Serial Port Interface
  96. // Initialize Serial Port
  97. void InitializeComPort(int baudrate, System.IO.Ports.Handshake handShake)
  98. {
  99. if (!ComPort.IsOpen)
  100. {
  101. // Set COM port properties
  102. ComPort.BaudRate = baudrate;
  103. ComPort.Parity = System.IO.Ports.Parity.None;
  104. ComPort.StopBits = System.IO.Ports.StopBits.One;
  105. ComPort.DataBits = 8;
  106. ComPort.Handshake = handShake;
  107. ComPort.ReadTimeout = 5000;
  108. ComPort.Open();
  109. }
  110. }
  111. // Compute the LRC of the sending string
  112. // LRC = result of XOR between ACK, length, and message characters
  113. byte ComputeLRC(byte[] bArr, int bytecount)
  114. {
  115. byte TRC = 0;
  116. int count = 0;
  117. while (count++ < bytecount)
  118. {
  119. TRC = (byte)(TRC ^ bArr[count - 1]);
  120. }
  121. return TRC;
  122. }
  123. // Check if the packet received is complete
  124. bool IsComplete(byte[] byteArray, int length)
  125. {
  126. if (length > 3)
  127. {
  128. byte len = byteArray[2];
  129. if (length == len + 4)
  130. {
  131. return true;
  132. }
  133. }
  134. return false;
  135. }
  136. // Send an array of bytes to the serial port
  137. void SendReceive(string Message, ref string Response, int InputTimeOutInSec)
  138. {
  139. int RetryNACK = NumberOfRetries;
  140. SendLabel: // Used when receiving a NACK response, comand sending must be resent
  141. /*-----------------------------------*/
  142. /* Send data to the Serial Port */
  143. /*-----------------------------------*/
  144. #region Send data to the Serial Port
  145. //Convert Hex String to Byte Array
  146. byte[] myBuffer = new byte[Message.Length / 2]; // reserve 2 byte for CRC
  147. myBuffer = HexStringDecoder.StringToByteArray(Message);
  148. if ((Message != ACK) && (Message != NACK))
  149. {
  150. // TRC Calculation
  151. byte TRC = ComputeLRC(myBuffer, myBuffer.Length - 1);
  152. myBuffer[myBuffer.Length - 1] = TRC;
  153. }
  154. // Update Message to include Error detection bits
  155. Message = HexStringDecoder.ByteArrayToString(myBuffer, myBuffer.Length);
  156. ComPort.DiscardInBuffer();
  157. ComPort.DiscardOutBuffer();
  158. // Send single byte in the byte array so it can be parsed
  159. for (int i = 0; i < myBuffer.Length; i++)
  160. {
  161. ComPort.Write(myBuffer, i, 1);
  162. }
  163. #endregion
  164. /*-----------------------------------*/
  165. /* Receive data from the Serial Port */
  166. /*-----------------------------------*/
  167. #region Receive data from the Serial Port
  168. // Initialize receive related variables
  169. int TimeOutCycleCountDown = (InputTimeOutInSec * 1000 / TimeOutUnitInMiliSec);
  170. bool TimeOut = false;
  171. int bytecount = 0;
  172. byte[] byteArrayBuffer = new byte[MaxBytes];
  173. byte[] byteArrayReturn = new byte[MaxBytes];
  174. // Reset the data string received and the byte received
  175. Response = "";
  176. // Unnecessary to collect data if it's an ACK or NACK
  177. if ((Message == ACK) || (Message == NACK))
  178. return;
  179. // Do the loop if there's no timeout or the timeout cycle still exists
  180. while ((!TimeOut) && (TimeOutCycleCountDown > 0) && (bytecount < MaxBytes))
  181. {
  182. // Attempt to read from COM port
  183. if (1 == ComPort.Read(byteArrayBuffer, bytecount, 1))
  184. {
  185. bytecount++;
  186. }
  187. else
  188. {
  189. // If restart command was sent, then timeout is expected
  190. if (Message.Length >= 4 + RestartReader.Length - 2
  191. && Message.Substring(4, RestartReader.Length - 2) == RestartReader.Substring(0, RestartReader.Length - 2))
  192. {
  193. break;
  194. }
  195. // Else set error and return
  196. error = ReaderError.NO_RESPONSE;
  197. return;
  198. }
  199. // Check if end of packet has been received
  200. if (IsComplete(byteArrayBuffer, bytecount))
  201. {
  202. TimeOut = true;
  203. }
  204. }
  205. // Copy data to Response
  206. byteArrayReturn = byteArrayBuffer;
  207. Response = HexStringDecoder.ByteArrayToString(byteArrayReturn, bytecount);
  208. #endregion
  209. /*-----------------------------------*
  210. * Handling NACK reponse *
  211. *-----------------------------------*/
  212. #region Handling NACK reponse
  213. // Prepare to resend the command
  214. if ((Response != null) && (Response.Length >= NACK.Length) &&
  215. (Response.Substring(0, NACK.Length) == NACK) && (RetryNACK-- > 0))
  216. {
  217. // Terminate all the running command after a number of retries when receiving NACK response
  218. if (RetryNACK == 0)
  219. {
  220. goto SendLabel;
  221. }
  222. }
  223. // Resend command because GemCore board has returned incorrect command form error
  224. // used when PCB is incorrect or for connect command
  225. else if ((Response != null) && (Response.Length >= 3)
  226. && (Response.Substring(0, 3).CompareTo("248") >= 0)
  227. && !Message.Substring(Message.Length - 2, 2).Equals("C0"))
  228. {
  229. Message = NAD + getPCB() + Message.Substring(4);
  230. NumberOfGemCoreRetries--;
  231. if (NumberOfGemCoreRetries > 0)
  232. {
  233. SendReceive(Message, ref Response, InputTimeOutInSec);
  234. }
  235. }
  236. else
  237. {
  238. NumberOfGemCoreRetries = 10;
  239. }
  240. #endregion
  241. }
  242. #endregion
  243. /*****************************************************************************/
  244. /* */
  245. /* Smart Card and Reader Communication */
  246. /* */
  247. /*****************************************************************************/
  248. #region Smart Card
  249. // Retrieves the correct PCB value
  250. string getPCB()
  251. {
  252. // Last one was "00", so now send "40"
  253. if (pcb)
  254. {
  255. PCB = onPCB;
  256. }
  257. // Last one was "40", so now send "00"
  258. else
  259. {
  260. PCB = offPCB;
  261. }
  262. pcb = !pcb;
  263. return PCB;
  264. }
  265. // Validate responses
  266. void ResponseValidation(PacketParser packet)
  267. {
  268. // Infinite Loop detection
  269. if ((packet.ErrorCode == PacketParser.ErrorType.Timeout)
  270. || (packet.ErrorCode == PacketParser.ErrorType.NoResponse)
  271. || (packet.ErrorCode == PacketParser.ErrorType.NACK))
  272. {
  273. error = ReaderError.NO_RESPONSE;
  274. }
  275. // Illegal response message detection
  276. else if (packet.ErrorCode == PacketParser.ErrorType.IllegalMessage)
  277. {
  278. error = ReaderError.BAD_MESSAGE;
  279. }
  280. // Illegal sent command detection
  281. else if (packet.ErrorCode == PacketParser.ErrorType.UnknownCommand
  282. || packet.ErrorCode == PacketParser.ErrorType.NumberArgs
  283. || packet.ErrorCode == PacketParser.ErrorType.BadCommandCode
  284. || packet.ErrorCode == PacketParser.ErrorType.NumberParams
  285. || packet.ErrorCode == PacketParser.ErrorType.CommandNotSupported)
  286. {
  287. error = ReaderError.BAD_COMMAND;
  288. }
  289. // Card malfunction detection
  290. else if (packet.ErrorCode == PacketParser.ErrorType.CardMissing
  291. || packet.ErrorCode == PacketParser.ErrorType.CardRemoved
  292. || packet.ErrorCode == PacketParser.ErrorType.CardMalfunction
  293. || packet.ErrorCode == PacketParser.ErrorType.PoweredDown
  294. || packet.ErrorCode == PacketParser.ErrorType.ShortCircuit)
  295. {
  296. error = ReaderError.NO_CARD_INSERTED;
  297. }
  298. // Other error detection
  299. else if (packet.ErrorCode != PacketParser.ErrorType.None)
  300. {
  301. error = ReaderError.UNKNOWN_ERROR;
  302. }
  303. // Correct data response
  304. else
  305. {
  306. error = ReaderError.NONE;
  307. }
  308. }
  309. // Connect reader
  310. internal override bool ConnectReader()
  311. {
  312. error = ReaderError.NONE;
  313. string Response = null;
  314. // Set port properties
  315. baudrate = 9600;
  316. // If reader is already on, no need to turn on again
  317. if (IsSerialPortOn)
  318. {
  319. error = ReaderError.ALREADY_CONNECTED;
  320. return true;
  321. }
  322. NumberOfGemCoreRetries = 10;
  323. try
  324. {
  325. // Open COM port
  326. InitializeComPort(baudrate, System.IO.Ports.Handshake.None);
  327. // Collect number of Retries if NACK receive
  328. NumberOfRetries = 5;
  329. // Send initialization command
  330. Config_Init = NAD + getPCB() + PowerOnSC;
  331. SendReceive(Config_Init, ref Response, InitializationTimeOut);
  332. Config_Init = NAD + getPCB() + PowerOffSC;
  333. SendReceive(Config_Init, ref Response, InitializationTimeOut);
  334. IsSerialPortOn = true;
  335. return true;
  336. }
  337. catch
  338. {
  339. if (ComPort.IsOpen)
  340. {
  341. ComPort.Close();
  342. }
  343. error = ReaderError.PORT_CONNECTION_FAILED;
  344. return false;
  345. }
  346. }
  347. // Disconnect reader
  348. internal override bool DisconnectReader()
  349. {
  350. error = ReaderError.NONE;
  351. // Cannot disconnect reader if sending APDU
  352. if ((!APDUCommandComplete))
  353. {
  354. error = ReaderError.TEST_RUNNING;
  355. return false;
  356. }
  357. // Reader is already off
  358. else if (!IsSerialPortOn)
  359. {
  360. error = ReaderError.READER_OFF;
  361. return true;
  362. }
  363. // Close Port, reset port and board flags
  364. ComPort.Close();
  365. IsSerialPortOn = false;
  366. return true;
  367. }
  368. // Reset reader
  369. internal override bool ResetReader()
  370. {
  371. error = ReaderError.NONE;
  372. // Send Restart Command and connect reader
  373. string Response = null;
  374. Config_Init = NAD + getPCB() + RestartReader;
  375. SendReceive(Config_Init, ref Response, InitializationTimeOut);
  376. IsSerialPortOn = false;
  377. return ConnectReader();
  378. }
  379. // Update status
  380. void UpdateStatus()
  381. {
  382. error = ReaderError.NONE;
  383. // Cannot update status of reader is off
  384. if (!IsSerialPortOn)
  385. {
  386. error = ReaderError.READER_OFF;
  387. return;
  388. }
  389. // Cannot update status if APDU is being sent
  390. if ((!APDUCommandComplete))
  391. {
  392. error = ReaderError.TEST_RUNNING;
  393. return;
  394. }
  395. // Cannot update status if activating smart card
  396. else if (ActivatingSmartCard)
  397. {
  398. error = ReaderError.ACTIVATING_CARD;
  399. return;
  400. }
  401. // Create status command string
  402. string StatusCmdStr = NAD + getPCB() + CheckStatus;
  403. try
  404. {
  405. // Reset activated flag in case card is no longer activated
  406. CardActivated = false;
  407. // Send command to reader
  408. string Response = null;
  409. SendReceive(StatusCmdStr, ref Response, InitializationTimeOut);
  410. // Parse Response
  411. Packet.GetPacket(Response);
  412. ResponseValidation(Packet);
  413. // If error, card is in error mode
  414. if (Packet.ErrorCode != PacketParser.ErrorType.None)
  415. {
  416. SlotStatus = ERROR;
  417. error = ReaderError.UNKNOWN_ERROR;
  418. }
  419. else
  420. {
  421. // Decode card's response
  422. switch (int.Parse(Response.Substring(9, 1)))
  423. {
  424. case 0:
  425. atr = null;
  426. SlotStatus = NOCARD;
  427. break;
  428. case 4:
  429. atr = null;
  430. SlotStatus = PRESENT;
  431. break;
  432. case 6:
  433. SlotStatus = ACTIVATED;
  434. CardActivated = true;
  435. break;
  436. default:
  437. atr = null;
  438. SlotStatus = ERROR;
  439. return;
  440. }
  441. }
  442. return;
  443. }
  444. catch
  445. {
  446. SlotStatus = ERROR;
  447. error = ReaderError.UNKNOWN_ERROR;
  448. return;
  449. }
  450. }
  451. // Send User SlotStatus if able to update
  452. internal override int GetStatus()
  453. {
  454. UpdateStatus();
  455. return SlotStatus;
  456. }
  457. // Activate card
  458. internal override bool ActivateCard()
  459. {
  460. error = ReaderError.NONE;
  461. // Cannot activate card if reader is off
  462. if (!IsSerialPortOn)
  463. {
  464. error = ReaderError.READER_OFF;
  465. return false;
  466. }
  467. // If resetting card, the following will have already been checked
  468. if (!ResettingCard)
  469. {
  470. // Cannot activate card if sending APDU
  471. if ((!APDUCommandComplete))
  472. {
  473. error = ReaderError.TEST_RUNNING;
  474. return false;
  475. }
  476. // Cannot activate if already (de)activating
  477. if ((ActivatingSmartCard))
  478. {
  479. error = ReaderError.ACTIVATING_CARD;
  480. return false;
  481. }
  482. UpdateStatus();
  483. // No need to activate already activated card
  484. if (SlotStatus == ACTIVATED)
  485. {
  486. error = ReaderError.NONE;
  487. return true;
  488. }
  489. // Cannot activate card if there is no card
  490. else if (SlotStatus != PRESENT)
  491. {
  492. error = ReaderError.NO_CARD_INSERTED;
  493. return false;
  494. }
  495. }
  496. // Set activation command string
  497. string Response = null;
  498. string ActivationCmdStr = NAD + getPCB() + PowerOnSC;
  499. try
  500. {
  501. // Set activation flag
  502. ActivatingSmartCard = true;
  503. // Send command to reader
  504. SendReceive(ActivationCmdStr, ref Response, InitializationTimeOut);
  505. // Parse response
  506. Packet.GetPacket(Response);
  507. ResponseValidation(Packet);
  508. // If no response, deactivate
  509. if (Packet.ErrorCode == PacketParser.ErrorType.NoResponse
  510. || Packet.ErrorCode == PacketParser.ErrorType.NACK)
  511. {
  512. string DeactivationCmdStr = NAD + getPCB() + PowerOffSC;
  513. SendReceive(DeactivationCmdStr, ref Response, InitializationTimeOut);
  514. Packet.GetPacket(Response);
  515. ResponseValidation(Packet);
  516. SlotStatus = ERROR;
  517. error = ReaderError.NO_RESPONSE;
  518. ActivatingSmartCard = false;
  519. return false;
  520. }
  521. // If card malfunction, set error type appropriately
  522. else if (Packet.ErrorCode == PacketParser.ErrorType.CardMalfunction)
  523. {
  524. SlotStatus = ERROR;
  525. error = ReaderError.CARD_MALFUNCTION;
  526. ActivatingSmartCard = false;
  527. return false;
  528. }
  529. // Any other error, set status as error
  530. else if (Packet.ErrorCode != PacketParser.ErrorType.None)
  531. {
  532. SlotStatus = ERROR;
  533. error = ReaderError.UNKNOWN_ERROR;
  534. ActivatingSmartCard = false;
  535. return false;
  536. }
  537. // No error means card is activated
  538. else
  539. {
  540. SlotStatus = ACTIVATED;
  541. atr = Response.Substring(8, Response.Length - 2 - 8);
  542. }
  543. // Update activation flags
  544. ActivatingSmartCard = false;
  545. CardActivated = true;
  546. return true;
  547. }
  548. catch
  549. {
  550. SlotStatus = ERROR;
  551. error = ReaderError.UNKNOWN_ERROR;
  552. return false;
  553. }
  554. }
  555. // Send PPS
  556. bool SendPPS()
  557. {
  558. error = ReaderError.NONE;
  559. // Cannot send PPS if reader is off
  560. if (!IsSerialPortOn)
  561. {
  562. error = ReaderError.READER_OFF;
  563. return false;
  564. }
  565. // Cannot send PPS if APDU is being sent
  566. if ((!APDUCommandComplete))
  567. {
  568. error = ReaderError.TEST_RUNNING;
  569. return false;
  570. }
  571. // Cannot send PPS if activating smart card
  572. else if (ActivatingSmartCard)
  573. {
  574. error = ReaderError.ACTIVATING_CARD;
  575. return false;
  576. }
  577. UpdateStatus();
  578. // Cannot send PPS if card is deactivated
  579. if (SlotStatus != ACTIVATED)
  580. {
  581. error = ReaderError.CARD_DEACTIVATED;
  582. return false;
  583. }
  584. // Error checking for protocol
  585. else if ((!Protocol.Equals("00")) && (!Protocol.Equals("01")))
  586. {
  587. error = ReaderError.BAD_PROTOCOL;
  588. return false;
  589. }
  590. // Set command string for PPS
  591. string SetParametersCmdStr = NAD + getPCB() + SetParametersCommand + PRT +
  592. FiDi + TC1 + TC2_TA3 + RFU_TB3 + "FF";
  593. try
  594. {
  595. // Send PPS to card
  596. string Response = null;
  597. SendReceive(SetParametersCmdStr, ref Response, InitializationTimeOut);
  598. // Parse Response
  599. Packet.GetPacket(Response);
  600. ResponseValidation(Packet);
  601. return true;
  602. }
  603. catch
  604. {
  605. error = ReaderError.UNKNOWN_ERROR;
  606. return false;
  607. }
  608. }
  609. // Send PPS with user defined parameters
  610. internal override bool SendPPS(byte protocol)
  611. {
  612. error = ReaderError.NONE;
  613. // Set data from protocol
  614. byte prt = (byte)HexStringDecoder.HexStringToInt(PRT);
  615. Protocol = HexStringDecoder.ByteToHex(protocol);
  616. if (protocol == 1)
  617. {
  618. prt |= 8; // Set protocol bit to 1
  619. TC2_TA3 = "20"; // Set TA3 = IFSC to 32
  620. RFU_TB3 = "00"; // Set TB3 = BWI/CWI to 0/0
  621. }
  622. else if (protocol == 0)
  623. {
  624. prt &= 0xF7; // Set protocol bit to 0
  625. TC2_TA3 = "10"; // Set TC2 = WI to 16
  626. RFU_TB3 = "00"; // Set RFU to 0
  627. }
  628. else
  629. {
  630. error = ReaderError.BAD_PROTOCOL;
  631. return false;
  632. }
  633. // Set PRT based on current PCB value
  634. if (pcb)
  635. {
  636. prt &= 0xFD; // Set next PCB to "00"
  637. }
  638. else
  639. {
  640. prt |= 2; // Set next PCB to "40"
  641. }
  642. PRT = HexStringDecoder.ByteToHex(prt);
  643. // Send PPS with updated PRT
  644. return SendPPS();
  645. }
  646. // Deactivate card
  647. internal override bool DeactivateCard()
  648. {
  649. error = ReaderError.NONE;
  650. // Cannot deactivate card if reader is off
  651. if (!IsSerialPortOn)
  652. {
  653. error = ReaderError.READER_OFF;
  654. return false;
  655. }
  656. // If resetting card, the following has already been done
  657. if (!ResettingCard)
  658. {
  659. // Cannot deactivate if currently activating
  660. if (ActivatingSmartCard)
  661. {
  662. error = ReaderError.ACTIVATING_CARD;
  663. return false;
  664. }
  665. // Cannot deactivate if APDU is being sent
  666. else if ((!APDUCommandComplete))
  667. {
  668. error = ReaderError.TEST_RUNNING;
  669. return false;
  670. }
  671. UpdateStatus();
  672. // No need to deactivate if card is already deactivated
  673. if (SlotStatus == PRESENT)
  674. {
  675. error = ReaderError.CARD_DEACTIVATED;
  676. return true;
  677. }
  678. // Cannot deactivate if there is no card
  679. else if (SlotStatus != ACTIVATED)
  680. {
  681. error = ReaderError.NO_CARD_INSERTED;
  682. return false;
  683. }
  684. }
  685. // Create deactivation command string
  686. string DeactivationCmdStr = NAD + getPCB() + PowerOffSC;
  687. try
  688. {
  689. // Set deactivating flag
  690. ActivatingSmartCard = true;
  691. // Send command to reader
  692. string Response = null;
  693. SendReceive(DeactivationCmdStr, ref Response, InitializationTimeOut);
  694. // Parse response
  695. Packet.GetPacket(Response);
  696. ResponseValidation(Packet);
  697. // If error, assume card was not deactivated
  698. if (Packet.ErrorCode != PacketParser.ErrorType.None)
  699. {
  700. SlotStatus = ERROR;
  701. atr = null;
  702. error = ReaderError.UNKNOWN_ERROR;
  703. CardActivated = false;
  704. ActivatingSmartCard = false;
  705. return false;
  706. }
  707. else
  708. {
  709. SlotStatus = PRESENT;
  710. atr = null;
  711. }
  712. // Reset flags
  713. ActivatingSmartCard = false;
  714. CardActivated = false;
  715. return true;
  716. }
  717. catch
  718. {
  719. ActivatingSmartCard = false;
  720. CardActivated = false;
  721. SlotStatus = ERROR;
  722. error = ReaderError.UNKNOWN_ERROR;
  723. return false;
  724. }
  725. }
  726. // Reset card
  727. internal override bool ResetCard()
  728. {
  729. error = ReaderError.NONE;
  730. // Reader must be on to reset card
  731. if (!IsSerialPortOn)
  732. {
  733. error = ReaderError.READER_OFF;
  734. return false;
  735. }
  736. // Cannot reset card while sending APDU
  737. else if ((!APDUCommandComplete))
  738. {
  739. error = ReaderError.TEST_RUNNING;
  740. return false;
  741. }
  742. // Cannot reset card if activiating card
  743. else if (ActivatingSmartCard)
  744. {
  745. error = ReaderError.ACTIVATING_CARD;
  746. return true;
  747. }
  748. UpdateStatus();
  749. // Cannot reset card if not there
  750. if (SlotStatus == NOCARD)
  751. {
  752. error = ReaderError.NO_CARD_INSERTED;
  753. return false;
  754. }
  755. // Set reset flag
  756. ResettingCard = true;
  757. // Deactivate card if necessary, then reactivate
  758. if (CardActivated)
  759. {
  760. DeactivateCard();
  761. }
  762. bool ret = ActivateCard();
  763. ResettingCard = false;
  764. return ret;
  765. }
  766. // Checks to see if reader is Connected or not
  767. internal override bool IsReaderActive()
  768. {
  769. error = ReaderError.NONE;
  770. return IsSerialPortOn;
  771. }
  772. // Executes a Command given as a parameter
  773. internal override string ExecuteCommand(string commandCode, string data)
  774. {
  775. error = ReaderError.NONE;
  776. // Cannot send command if reader is off
  777. if (!IsSerialPortOn)
  778. {
  779. error = ReaderError.READER_OFF;
  780. return null;
  781. }
  782. // Cannot send command if APDU is being sent
  783. if ((!APDUCommandComplete))
  784. {
  785. error = ReaderError.TEST_RUNNING;
  786. return null;
  787. }
  788. // Cannot send command if activiating card
  789. else if (ActivatingSmartCard)
  790. {
  791. error = ReaderError.ACTIVATING_CARD;
  792. return null;
  793. }
  794. // Create command string
  795. string CmdStr = NAD + getPCB()
  796. + HexStringDecoder.ByteToHex((byte)((commandCode.Length / 2) + (data.Length / 2)))
  797. + commandCode + data + "FF";
  798. try
  799. {
  800. // Send command to reader
  801. string Response = null;
  802. SendReceive(CmdStr, ref Response, InitializationTimeOut);
  803. // Parse response
  804. Packet.GetPacket(Response);
  805. ResponseValidation(Packet);
  806. return Response;
  807. }
  808. catch
  809. {
  810. error = ReaderError.UNKNOWN_ERROR;
  811. return null;
  812. }
  813. }
  814. // Get current error
  815. internal override ReaderError Error
  816. {
  817. get
  818. {
  819. return error;
  820. }
  821. }
  822. // Get ATR
  823. internal override string ATR
  824. {
  825. get
  826. {
  827. return atr;
  828. }
  829. }
  830. // Send APDU to smart card
  831. internal override string SendAPDU(string apduText)
  832. {
  833. error = ReaderError.NONE;
  834. // Cannot send APDU if serial port is off
  835. if (!IsSerialPortOn)
  836. {
  837. error = ReaderError.READER_OFF;
  838. return null;
  839. }
  840. // Cannot send APDU if another APDU is being sent
  841. else if ((!APDUCommandComplete))
  842. {
  843. error = ReaderError.TEST_RUNNING;
  844. return null;
  845. }
  846. // Cannot send APDU if activating smart card
  847. else if (ActivatingSmartCard)
  848. {
  849. error = ReaderError.ACTIVATING_CARD;
  850. return null;
  851. }
  852. UpdateStatus();
  853. // Cannot send APDU if card is deactivated
  854. if (SlotStatus != ACTIVATED)
  855. {
  856. error = ReaderError.CARD_DEACTIVATED;
  857. return null;
  858. }
  859. // Start Sending Procedure
  860. APDUCommandComplete = false;
  861. string Response = null;
  862. string APDUCmdStr = NAD + getPCB() +
  863. HexStringDecoder.ByteToHex((byte)(apduText.Length / 2 + 1)) // Length
  864. + "15" + apduText + "FF";
  865. // Send APDU string
  866. try
  867. {
  868. SendReceive(APDUCmdStr, ref Response, TestTimeOut);
  869. // Parse Response string
  870. Packet.GetPacket(Response);
  871. ResponseValidation(Packet);
  872. Response = Packet.resp;
  873. APDUCommandComplete = true;
  874. return Response;
  875. }
  876. catch
  877. {
  878. SlotStatus = ERROR;
  879. error = ReaderError.UNKNOWN_ERROR;
  880. return null;
  881. }
  882. }
  883. #endregion
  884. }
  885. }