PageRenderTime 26ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/PCSCMicro/Teridian/PacketParser.cs

#
C# | 225 lines | 133 code | 9 blank | 83 comment | 18 complexity | 1e492c07adfd7f0e66adc86427a2630e MD5 | raw file
Possible License(s): GPL-2.0
  1. /***************************************************************************
  2. * This code and information is provided "as is" without warranty of any *
  3. * kind, either expressed or implied, including but not limited to the *
  4. * implied warranties of merchantability and/or fitness for a particular *
  5. * purpose. *
  6. * *
  7. * Copyright (C) 2008 Teridian SemiConductor, Corp. All Rights Reserved. *
  8. * *
  9. ***************************************************************************/
  10. //**************************************************************************//
  11. // //
  12. // DESCRIPTION: TSCP-CCID //
  13. // PacketParser.cs //
  14. // PacketParser is an object that interprets the message received from //
  15. // serial port. The input for this object is a message string //
  16. // //
  17. // AUTHOR: SD //
  18. // //
  19. // HISTORY: 2007 SEPTEMBER 26; First Version Released 1.0 //
  20. // 2007 DECEMBER 14; Version 2.00 Release //
  21. // //
  22. //**************************************************************************//
  23. /***************************************************************************
  24. * This code was adapted from PacketParser.cs which was originally written *
  25. * by Teridian SemiConductor, Corp. It has been modified from its original *
  26. * version to allow for use of the Teridian board in the .NET Micro *
  27. * Framework. *
  28. * LAST MODIFIED: 2010 April 23 *
  29. * Copyright (C) 2009 Gemalto *
  30. ***************************************************************************/
  31. /***************************************************************************
  32. * PacketParser.cs is part of the PC/SC Micro API for the .NET Micro *
  33. * Framework. *
  34. * *
  35. * The PC/SC Micro API for the .NET Micro Framework is free software: *
  36. * you can redistribute it and/or modify it under the terms of the GNU *
  37. * General Public License as published by the Free Software Foundation, *
  38. * either version 2 of the License, or (at your option) any later version.*
  39. * *
  40. * The PC/SC Micro API for the .NET Micro Framework is distributed in *
  41. * the hope that it will be useful, but WITHOUT ANY WARRANTY; without even*
  42. * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR *
  43. * PURPOSE. See the GNU General Public License for more details. *
  44. * *
  45. * You should have received a copy of the GNU General Public License *
  46. * along with the PC/SC Micro API for the .NET Micro Framework. If not, *
  47. * see <http://www.gnu.org/licenses/>. *
  48. ***************************************************************************/
  49. using System;
  50. using System.Text;
  51. namespace PCSCMicro
  52. {
  53. class PacketParser
  54. {
  55. // Definition of acknowledge bytes
  56. const string ACK = "C0AAC0";
  57. const string NACK = "C055C0";
  58. // Definition of statuses
  59. const string BAD_ATR_TCK = "F7";
  60. const string BAD_ATR_TS = "F8";
  61. const string KEYPAD_TIMEOUT = "F9";
  62. const string BAD_PASSCODE = "FA";
  63. const string HW_ERROR = "FB";
  64. const string ICC_OTHER_ERROR = "FC";
  65. const string SECMODE_NOT_SET = "FD";
  66. const string ICC_MUTE = "FE";
  67. const string CMD_ABORTED = "FF";
  68. // Definitions of response locations
  69. const int statusWordLen = 2;
  70. const int statusWordStrLen = statusWordLen * 2;
  71. // Potential error types
  72. internal enum ErrorType
  73. {
  74. None, NoResponse, Timeout, NACK, IllegalMessage, CRCCheck,
  75. CommandAborted, ICCMute, HWError, BadATRTS, BadATRTCK,
  76. KeypadTimeout, BadPasscode, IccOtherError, SecModeNotSet,
  77. Unknown
  78. }
  79. // Definition of accessible variables
  80. string Message;
  81. internal string AckMsg;
  82. internal string ResMsg;
  83. internal string ErrorMessage;
  84. internal string statusWord;
  85. internal string resp;
  86. internal int respLen;
  87. internal ErrorType ErrorCode;
  88. // Only one constructor to discourage bad uFW coding practices
  89. // (inherited code had another constructor with msg as parameter)
  90. internal PacketParser()
  91. {
  92. Message = "";
  93. }
  94. // Encouraged to call this every time new message is received
  95. // instead of creating new PacketParser each time
  96. internal void GetPacket(string msg)
  97. {
  98. Message = msg;
  99. ParseMe();
  100. }
  101. // Parse message data
  102. // This function assumes the desired message is in Message
  103. // At termination, resp holds the response which is of length
  104. // respLen, ErrorCode contains the ErrorType associated with
  105. // Message and ErrorMessage contains the corresponding string,
  106. // AckMsg contains the acknowledgement string (either ACK or NACK)
  107. // and ResMsg contains the rest of Message that is not a
  108. // part of AckMsg
  109. internal void ParseMe()
  110. {
  111. // No response
  112. if ((Message == "") || (Message == null))
  113. {
  114. AckMsg = "";
  115. ResMsg = "";
  116. ErrorMessage = "No response";
  117. ErrorCode = ErrorType.NoResponse;
  118. }
  119. // ACK received, response falls into infinite loop
  120. else if (Message == ACK)
  121. {
  122. AckMsg = ACK;
  123. ResMsg = "";
  124. ErrorMessage = "Timeout expired & no data received." + "\r\n" + "Increasing timeout may help. ";
  125. ErrorCode = ErrorType.Timeout;
  126. }
  127. //NACK received
  128. else if (Message == NACK)
  129. {
  130. AckMsg = NACK;
  131. ResMsg = "";
  132. ErrorMessage = "NACK limt reached";
  133. ErrorCode = ErrorType.NACK;
  134. }
  135. // Illegal message
  136. // Minimum length of a legal message is 15
  137. //
  138. // C0AAC0 C0XXYYZZ CRC1 CRC2 C0
  139. // (6) (8) (1) (1) (1) = 15 bytes total
  140. else if (Message.Length < 15)
  141. {
  142. AckMsg = "";
  143. ResMsg = Message;
  144. ErrorMessage = "Illegal message";
  145. ErrorCode = ErrorType.IllegalMessage;
  146. }
  147. // Parse data to see if there's any error
  148. else
  149. {
  150. AckMsg = Message.Substring(0, ACK.Length); // ACK string
  151. ResMsg = Message.Substring(ACK.Length, Message.Length - ACK.Length);
  152. // Example: C0AAC0C00041FB..., Message.Substring(6, 2) = 'FB'
  153. // Handle Error
  154. // Get the error code, for example '41FB'
  155. if ((Message.Substring(0, ACK.Length) == ACK) && (Message.Substring(8, 2) == "00"))
  156. {
  157. ErrorMessage = ResMsg.Substring(4, 4);
  158. // Parse ResMsg to understand the error type
  159. // Message.Substring(6, 2)
  160. // Example: ResMsg.Substring(6, 2) = 'FB'
  161. // ResMsg.Substring(4, 4) = '41FB'
  162. switch (ResMsg.Substring(6, 2))
  163. {
  164. case CMD_ABORTED:
  165. ErrorCode = ErrorType.CommandAborted;
  166. break;
  167. case ICC_MUTE:
  168. ErrorCode = ErrorType.ICCMute;
  169. break;
  170. case HW_ERROR:
  171. ErrorCode = ErrorType.HWError;
  172. break;
  173. case BAD_ATR_TS:
  174. ErrorCode = ErrorType.BadATRTS;
  175. break;
  176. case BAD_ATR_TCK:
  177. ErrorCode = ErrorType.BadATRTCK;
  178. break;
  179. case KEYPAD_TIMEOUT:
  180. ErrorCode = ErrorType.KeypadTimeout;
  181. break;
  182. case BAD_PASSCODE:
  183. ErrorCode = ErrorType.BadPasscode;
  184. break;
  185. case ICC_OTHER_ERROR:
  186. ErrorCode = ErrorType.IccOtherError;
  187. break;
  188. case SECMODE_NOT_SET:
  189. ErrorCode = ErrorType.SecModeNotSet;
  190. break;
  191. default:
  192. ErrorCode = ErrorType.Unknown;
  193. break;
  194. }
  195. }
  196. else
  197. {
  198. // If there is response, get it
  199. if (ResMsg.Length > AckMsg.Length + 2 + 6)
  200. {
  201. resp = ResMsg.Substring(ACK.Length + 2, ResMsg.Length - 6 - (ACK.Length + 2));
  202. }
  203. // Else get the status
  204. else
  205. {
  206. resp = ResMsg.Substring(ACK.Length + 2, statusWordStrLen);
  207. }
  208. respLen = resp.Length;
  209. statusWord = ResMsg.Substring(ACK.Length + 2 + respLen-4, statusWordStrLen);
  210. ErrorMessage = "";
  211. ErrorCode = ErrorType.None;
  212. }
  213. }
  214. }
  215. }
  216. }