/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
- /***************************************************************************
- * This code and information is provided "as is" without warranty of any *
- * kind, either expressed or implied, including but not limited to the *
- * implied warranties of merchantability and/or fitness for a particular *
- * purpose. *
- * *
- * Copyright (C) 2008 Teridian SemiConductor, Corp. All Rights Reserved. *
- * *
- ***************************************************************************/
- //**************************************************************************//
- // //
- // DESCRIPTION: TSCP-CCID //
- // PacketParser.cs //
- // PacketParser is an object that interprets the message received from //
- // serial port. The input for this object is a message string //
- // //
- // AUTHOR: SD //
- // //
- // HISTORY: 2007 SEPTEMBER 26; First Version Released 1.0 //
- // 2007 DECEMBER 14; Version 2.00 Release //
- // //
- //**************************************************************************//
- /***************************************************************************
- * This code was adapted from PacketParser.cs which was originally written *
- * by Teridian SemiConductor, Corp. It has been modified from its original *
- * version to allow for use of the Teridian board in the .NET Micro *
- * Framework. *
- * LAST MODIFIED: 2010 April 23 *
- * Copyright (C) 2009 Gemalto *
- ***************************************************************************/
- /***************************************************************************
- * PacketParser.cs is part of the PC/SC Micro API for the .NET Micro *
- * Framework. *
- * *
- * The PC/SC Micro API for the .NET Micro Framework is free software: *
- * you can redistribute it and/or modify it under the terms of the GNU *
- * General Public License as published by the Free Software Foundation, *
- * either version 2 of the License, or (at your option) any later version.*
- * *
- * The PC/SC Micro API for the .NET Micro Framework is distributed in *
- * the hope that it will be useful, but WITHOUT ANY WARRANTY; without even*
- * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR *
- * PURPOSE. See the GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with the PC/SC Micro API for the .NET Micro Framework. If not, *
- * see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
- using System;
- using System.Text;
-
- namespace PCSCMicro
- {
- class PacketParser
- {
- // Definition of acknowledge bytes
- const string ACK = "C0AAC0";
- const string NACK = "C055C0";
-
- // Definition of statuses
- const string BAD_ATR_TCK = "F7";
- const string BAD_ATR_TS = "F8";
- const string KEYPAD_TIMEOUT = "F9";
- const string BAD_PASSCODE = "FA";
- const string HW_ERROR = "FB";
- const string ICC_OTHER_ERROR = "FC";
- const string SECMODE_NOT_SET = "FD";
- const string ICC_MUTE = "FE";
- const string CMD_ABORTED = "FF";
-
- // Definitions of response locations
- const int statusWordLen = 2;
- const int statusWordStrLen = statusWordLen * 2;
-
- // Potential error types
- internal enum ErrorType
- {
- None, NoResponse, Timeout, NACK, IllegalMessage, CRCCheck,
- CommandAborted, ICCMute, HWError, BadATRTS, BadATRTCK,
- KeypadTimeout, BadPasscode, IccOtherError, SecModeNotSet,
- Unknown
- }
-
- // Definition of accessible variables
- string Message;
- internal string AckMsg;
- internal string ResMsg;
- internal string ErrorMessage;
- internal string statusWord;
- internal string resp;
- internal int respLen;
- internal ErrorType ErrorCode;
-
- // Only one constructor to discourage bad uFW coding practices
- // (inherited code had another constructor with msg as parameter)
- internal PacketParser()
- {
- Message = "";
- }
-
- // Encouraged to call this every time new message is received
- // instead of creating new PacketParser each time
- internal void GetPacket(string msg)
- {
- Message = msg;
- ParseMe();
- }
-
- // Parse message data
- // This function assumes the desired message is in Message
- // At termination, resp holds the response which is of length
- // respLen, ErrorCode contains the ErrorType associated with
- // Message and ErrorMessage contains the corresponding string,
- // AckMsg contains the acknowledgement string (either ACK or NACK)
- // and ResMsg contains the rest of Message that is not a
- // part of AckMsg
- internal void ParseMe()
- {
- // No response
- if ((Message == "") || (Message == null))
- {
- AckMsg = "";
- ResMsg = "";
- ErrorMessage = "No response";
- ErrorCode = ErrorType.NoResponse;
- }
- // ACK received, response falls into infinite loop
- else if (Message == ACK)
- {
- AckMsg = ACK;
- ResMsg = "";
- ErrorMessage = "Timeout expired & no data received." + "\r\n" + "Increasing timeout may help. ";
- ErrorCode = ErrorType.Timeout;
- }
- //NACK received
- else if (Message == NACK)
- {
- AckMsg = NACK;
- ResMsg = "";
- ErrorMessage = "NACK limt reached";
- ErrorCode = ErrorType.NACK;
- }
- // Illegal message
- // Minimum length of a legal message is 15
- //
- // C0AAC0 C0XXYYZZ CRC1 CRC2 C0
- // (6) (8) (1) (1) (1) = 15 bytes total
- else if (Message.Length < 15)
- {
- AckMsg = "";
- ResMsg = Message;
- ErrorMessage = "Illegal message";
- ErrorCode = ErrorType.IllegalMessage;
- }
- // Parse data to see if there's any error
- else
- {
- AckMsg = Message.Substring(0, ACK.Length); // ACK string
- ResMsg = Message.Substring(ACK.Length, Message.Length - ACK.Length);
- // Example: C0AAC0C00041FB..., Message.Substring(6, 2) = 'FB'
- // Handle Error
- // Get the error code, for example '41FB'
- if ((Message.Substring(0, ACK.Length) == ACK) && (Message.Substring(8, 2) == "00"))
- {
- ErrorMessage = ResMsg.Substring(4, 4);
- // Parse ResMsg to understand the error type
- // Message.Substring(6, 2)
- // Example: ResMsg.Substring(6, 2) = 'FB'
- // ResMsg.Substring(4, 4) = '41FB'
- switch (ResMsg.Substring(6, 2))
- {
- case CMD_ABORTED:
- ErrorCode = ErrorType.CommandAborted;
- break;
- case ICC_MUTE:
- ErrorCode = ErrorType.ICCMute;
- break;
- case HW_ERROR:
- ErrorCode = ErrorType.HWError;
- break;
- case BAD_ATR_TS:
- ErrorCode = ErrorType.BadATRTS;
- break;
- case BAD_ATR_TCK:
- ErrorCode = ErrorType.BadATRTCK;
- break;
- case KEYPAD_TIMEOUT:
- ErrorCode = ErrorType.KeypadTimeout;
- break;
- case BAD_PASSCODE:
- ErrorCode = ErrorType.BadPasscode;
- break;
- case ICC_OTHER_ERROR:
- ErrorCode = ErrorType.IccOtherError;
- break;
- case SECMODE_NOT_SET:
- ErrorCode = ErrorType.SecModeNotSet;
- break;
- default:
- ErrorCode = ErrorType.Unknown;
- break;
- }
- }
-
- else
- {
- // If there is response, get it
- if (ResMsg.Length > AckMsg.Length + 2 + 6)
- {
- resp = ResMsg.Substring(ACK.Length + 2, ResMsg.Length - 6 - (ACK.Length + 2));
- }
- // Else get the status
- else
- {
- resp = ResMsg.Substring(ACK.Length + 2, statusWordStrLen);
- }
- respLen = resp.Length;
- statusWord = ResMsg.Substring(ACK.Length + 2 + respLen-4, statusWordStrLen);
- ErrorMessage = "";
- ErrorCode = ErrorType.None;
- }
- }
- }
- }
- }