PageRenderTime 26ms CodeModel.GetById 12ms app.highlight 9ms RepoModel.GetById 2ms app.codeStats 0ms

/PCSCMicro/Teridian/PacketParser.cs

#
C# | 225 lines | 133 code | 9 blank | 83 comment | 18 complexity | 1e492c07adfd7f0e66adc86427a2630e MD5 | raw file
  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 ***************************************************************************/
 49using System;
 50using System.Text;
 51
 52namespace PCSCMicro
 53{
 54    class PacketParser
 55    {
 56        // Definition of acknowledge bytes
 57        const string ACK = "C0AAC0";
 58        const string NACK = "C055C0";
 59
 60        // Definition of statuses
 61        const string BAD_ATR_TCK = "F7";
 62        const string BAD_ATR_TS = "F8";
 63        const string KEYPAD_TIMEOUT = "F9";
 64        const string BAD_PASSCODE = "FA";
 65        const string HW_ERROR = "FB";
 66        const string ICC_OTHER_ERROR = "FC";
 67        const string SECMODE_NOT_SET = "FD";
 68        const string ICC_MUTE = "FE";
 69        const string CMD_ABORTED = "FF";
 70
 71        // Definitions of response locations
 72        const int statusWordLen = 2;
 73        const int statusWordStrLen = statusWordLen * 2;
 74
 75        // Potential error types
 76        internal enum ErrorType
 77        {
 78            None, NoResponse, Timeout, NACK, IllegalMessage, CRCCheck,
 79            CommandAborted, ICCMute, HWError, BadATRTS, BadATRTCK,
 80            KeypadTimeout, BadPasscode, IccOtherError, SecModeNotSet,
 81            Unknown
 82        }
 83
 84        // Definition of accessible variables
 85        string Message;
 86        internal string AckMsg;
 87        internal string ResMsg;
 88        internal string ErrorMessage;
 89        internal string statusWord;
 90        internal string resp;
 91        internal int respLen;
 92        internal ErrorType ErrorCode;
 93
 94        // Only one constructor to discourage bad uFW coding practices
 95        // (inherited code had another constructor with msg as parameter)
 96        internal PacketParser()
 97        {
 98            Message = "";
 99        }
100
101        // Encouraged to call this every time new message is received
102        // instead of creating new PacketParser each time
103        internal void GetPacket(string msg)
104        {
105            Message = msg;
106            ParseMe();
107        }
108
109        // Parse message data
110        // This function assumes the desired message is in Message
111        // At termination, resp holds the response which is of length
112        // respLen, ErrorCode contains the ErrorType associated with
113        // Message and ErrorMessage contains the corresponding string,
114        // AckMsg contains the acknowledgement string (either ACK or NACK)
115        // and ResMsg contains the rest of Message that is not a 
116        // part of AckMsg
117        internal void ParseMe()
118        {
119            // No response
120            if ((Message == "") || (Message == null))
121            {
122                AckMsg = "";
123                ResMsg = "";
124                ErrorMessage = "No response";
125                ErrorCode = ErrorType.NoResponse;
126            }
127            // ACK received, response falls into infinite loop
128            else if (Message == ACK)
129            {
130                AckMsg = ACK;
131                ResMsg = "";
132                ErrorMessage = "Timeout expired & no data received." + "\r\n" + "Increasing timeout may help. ";
133                ErrorCode = ErrorType.Timeout;
134            }
135            //NACK received
136            else if (Message == NACK)
137            {
138                AckMsg = NACK;
139                ResMsg = "";
140                ErrorMessage = "NACK limt reached";
141                ErrorCode = ErrorType.NACK;
142            }
143            // Illegal message
144            // Minimum length of a legal message is 15
145            // 
146            // C0AAC0 C0XXYYZZ CRC1 CRC2 C0
147            //   (6)     (8)   (1)  (1)  (1) = 15 bytes total
148            else if (Message.Length < 15)
149            {
150                AckMsg = "";
151                ResMsg = Message;
152                ErrorMessage = "Illegal message";
153                ErrorCode = ErrorType.IllegalMessage;
154            }
155            // Parse data to see if there's any error
156            else
157            {
158                AckMsg = Message.Substring(0, ACK.Length);                              // ACK string
159                ResMsg = Message.Substring(ACK.Length, Message.Length - ACK.Length);
160                // Example: C0AAC0C00041FB...,  Message.Substring(6, 2) = 'FB'
161                // Handle Error
162                // Get the error code, for example '41FB'
163                if ((Message.Substring(0, ACK.Length) == ACK) && (Message.Substring(8, 2) == "00"))
164                {
165                    ErrorMessage = ResMsg.Substring(4, 4);
166                    // Parse ResMsg to understand the error type
167                    // Message.Substring(6, 2)
168                    // Example: ResMsg.Substring(6, 2) = 'FB'
169                    //          ResMsg.Substring(4, 4) = '41FB'
170                    switch (ResMsg.Substring(6, 2))
171                    {
172                        case CMD_ABORTED:
173                            ErrorCode = ErrorType.CommandAborted;
174                            break;
175                        case ICC_MUTE:
176                            ErrorCode = ErrorType.ICCMute;
177                            break;
178                        case HW_ERROR:
179                            ErrorCode = ErrorType.HWError;
180                            break;
181                        case BAD_ATR_TS:
182                            ErrorCode = ErrorType.BadATRTS;
183                            break;
184                        case BAD_ATR_TCK:
185                            ErrorCode = ErrorType.BadATRTCK;
186                            break;
187                        case KEYPAD_TIMEOUT:
188                            ErrorCode = ErrorType.KeypadTimeout;
189                            break;
190                        case BAD_PASSCODE:
191                            ErrorCode = ErrorType.BadPasscode;
192                            break;
193                        case ICC_OTHER_ERROR:
194                            ErrorCode = ErrorType.IccOtherError;
195                            break;
196                        case SECMODE_NOT_SET:
197                            ErrorCode = ErrorType.SecModeNotSet;
198                            break;
199                        default:
200                            ErrorCode = ErrorType.Unknown;
201                            break;
202                    }
203                }
204                
205                else
206                {
207                    // If there is response, get it
208                    if (ResMsg.Length > AckMsg.Length + 2 + 6)
209                    {
210                        resp = ResMsg.Substring(ACK.Length + 2, ResMsg.Length - 6 - (ACK.Length + 2));
211                    }
212                    // Else get the status
213                    else
214                    {
215                        resp = ResMsg.Substring(ACK.Length + 2, statusWordStrLen);
216                    }
217                    respLen = resp.Length;
218                    statusWord = ResMsg.Substring(ACK.Length + 2 + respLen-4, statusWordStrLen);
219                    ErrorMessage = "";
220                    ErrorCode = ErrorType.None;
221                }
222            }
223        }
224    }
225}