[Pcsclite-cvs-commit] Drivers/ccid/src/protocol_t1 Makefile.am,NONE,1.1 README,NONE,1.1 atr.c,NONE,1.1 atr.h,NONE,1.1 defines.h,NONE,1.1 pps.c,NONE,1.1 pps.h,NONE,1.1 protocol_t1.c,NONE,1.1 protocol_t1.h,NONE,1.1 t1_block.c,NONE,1.1 t1_block.h,NONE,1.1

rousseau@quantz.debian.org rousseau@quantz.debian.org
Thu, 15 Jan 2004 15:34:23 +0100


Update of /cvsroot/pcsclite/Drivers/ccid/src/protocol_t1
In directory quantz:/tmp/cvs-serv24052/protocol_t1

Added Files:
	Makefile.am README atr.c atr.h defines.h pps.c pps.h 
	protocol_t1.c protocol_t1.h t1_block.c t1_block.h 
Log Message:
new files from Carlos Prados towitoko-2.0.7 driver (with a bit of hacking)


--- NEW FILE: Makefile.am ---
#
#   driver/Makefile.am 
#
#   This file is part of the Unix driver for Towitoko smartcard readers  
#   Copyright (C) 2000 Carlos Prados <cprados@yahoo.com>
#
#   This library is free software; you can redistribute it and/or
#   modify it under the terms of the GNU Lesser General Public
#   License as published by the Free Software Foundation; either
#   version 2 of the License, or (at your option) any later version.
#
#   This library 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
#   Lesser General Public License for more details.
#
#   You should have received a copy of the GNU Lesser General Public
#   License along with this library; if not, write to the Free Software
#   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#

INC = atr.h pps.h protocol_t1.h t1_block.h
SRC = atr.c pps.c protocol_t1.c t1_block.c

noinst_LIBRARIES = libt1.a
INCLUDES = -I$(top_srcdir)/src

libt1_a_SOURCES = $(SRC) $(INC)


--- NEW FILE: README ---
All the files in the src/protocol_t1/ directory comes from Carlos
Prados Towitoko smartcard readers driver.

I hacked the source files a bit to include them in my CCID driver. So
bugs are mine and not Carlos' fault.  As indicated in the source files
headers this code is protected by the GNU Lesser General Public License.

I used version 2.0.7 of Carlos driver available at
http://www.geocities.com/cprados/

$Id: README,v 1.1 2004/01/15 14:34:21 rousseau Exp $

--- NEW FILE: atr.c ---
/*
    atr.c
    ISO 7816 ICC's answer to reset abstract data type implementation

    This file is part of the Unix driver for Towitoko smartcard readers
    Copyright (C) 2000 Carlos Prados <cprados@yahoo.com>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library 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
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include "pcscdefines.h"
#include "atr.h"
#include <stdlib.h>
#include <string.h>

/* 
 * Not exported variables definition
 */

static unsigned long 
atr_fs_table[16] =
{ 
  0, 5000000L, 6000000L, 8000000L, 12000000L, 16000000L, 20000000L, 
  0, 0, 5000000L, 7500000L, 10000000L, 15000000L, 20000000L, 0, 0 
};

static unsigned
atr_num_ib_table[16] = 
{ 
  0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 
};

/*
 * Exported variables definition
 */

unsigned
atr_f_table[16] = 
{ 
  0, 372, 558, 744, 1116, 1488, 1860, 0, 0, 512, 768, 1024, 1536, 2048, 0, 0 
};

double 
atr_d_table[16] = 
{ 
  0, 1, 2, 4, 8, 16, 0, 0, 0, 0, 0.5, 0.25, 0.125, 0.0625, 0.03125, 0.015625 
};

unsigned 
atr_i_table[4] = 
{ 
  25, 50, 100, 0 
};

/* 
 * Exported funcions definition
 */

ATR *
ATR_New (void)
{
  ATR *atr;

  /* Allocate memory */
  atr = (ATR *) malloc (sizeof (ATR));

  return atr;
}

int
ATR_InitFromArray (ATR * atr, BYTE atr_buffer[ATR_MAX_SIZE], unsigned length)
{
  BYTE TDi;
  BYTE buffer[ATR_MAX_SIZE];
  unsigned pointer = 0, pn = 0;

  /* Check size of buffer */
  if (length < 2)
    return (ATR_MALFORMED);

  /* Check if ATR is from a inverse convention card */
  if (atr_buffer[0] == 0x03)
    {
      for (pointer = 0; pointer < length; pointer++)
	buffer[pointer] = ~(INVERT_BYTE (atr_buffer[pointer]));
    }
  else
    memcpy (buffer, atr_buffer, length);

  /* Store T0 and TS */
  atr->TS = buffer[0];

  atr->T0 = TDi = buffer[1];
  pointer = 1;

  /* Store number of historical bytes */
  atr->hbn = TDi & 0x0F;

  /* TCK is not present by default */
  (atr->TCK).present = FALSE;

  /* Extract interface bytes */
  while (pointer < length)
    {
      /* Check buffer is long enought */
      if (pointer + atr_num_ib_table[(0xF0 & TDi) >> 4] >= length)
	{
	  return (ATR_MALFORMED);
	}
      /* Check TAi is present */
      if ((TDi | 0xEF) == 0xFF)
	{
	  pointer++;
	  atr->ib[pn][ATR_INTERFACE_BYTE_TA].value = buffer[pointer];
	  atr->ib[pn][ATR_INTERFACE_BYTE_TA].present = TRUE;
	}
      else
	atr->ib[pn][ATR_INTERFACE_BYTE_TA].present = FALSE;
      /* Check TBi is present */
      if ((TDi | 0xDF) == 0xFF)
	{
	  pointer++;
	  atr->ib[pn][ATR_INTERFACE_BYTE_TB].value = buffer[pointer];
	  atr->ib[pn][ATR_INTERFACE_BYTE_TB].present = TRUE;
	}
      else
	atr->ib[pn][ATR_INTERFACE_BYTE_TB].present = FALSE;

      /* Check TCi is present */
      if ((TDi | 0xBF) == 0xFF)
	{
	  pointer++;
	  atr->ib[pn][ATR_INTERFACE_BYTE_TC].value = buffer[pointer];
	  atr->ib[pn][ATR_INTERFACE_BYTE_TC].present = TRUE;
	}
      else
	atr->ib[pn][ATR_INTERFACE_BYTE_TC].present = FALSE;

      /* Read TDi if present */
      if ((TDi | 0x7F) == 0xFF)
	{
	  pointer++;
	  TDi = atr->ib[pn][ATR_INTERFACE_BYTE_TD].value = buffer[pointer];
	  atr->ib[pn][ATR_INTERFACE_BYTE_TD].present = TRUE;
	  (atr->TCK).present = ((TDi & 0x0F) != ATR_PROTOCOL_TYPE_T0);
	  if (pn >= ATR_MAX_PROTOCOLS)
	    return (ATR_MALFORMED);
	  pn++;
	}
      else
	{
	  atr->ib[pn][ATR_INTERFACE_BYTE_TD].present = FALSE;
	  break;
	}
    }

  /* Store number of protocols */
  atr->pn = pn + 1;

  /* Store historical bytes */
  if (pointer + atr->hbn >= length)
    return (ATR_MALFORMED);

  memcpy (atr->hb, buffer + pointer + 1, atr->hbn);
  pointer += (atr->hbn);

  /* Store TCK  */
  if ((atr->TCK).present)
    {

      if (pointer + 1 >= length)
	return (ATR_MALFORMED);

      pointer++;

      (atr->TCK).value = buffer[pointer];
    }

  atr->length = pointer + 1;
  return (ATR_OK);
}


void
ATR_Delete (ATR * atr)
{
  free (atr);
}

int
ATR_GetConvention (ATR * atr, int *convention)
{
  if (atr->TS == 0x3B)
    (*convention) = ATR_CONVENTION_DIRECT;
  else if (atr->TS == 0x3F)
    (*convention) = ATR_CONVENTION_INVERSE;
  else
    return (ATR_MALFORMED);
  return (ATR_OK);
}

int
ATR_GetSize (ATR * atr, unsigned *size)
{
  (*size) = atr->length;
  return (ATR_OK);
}

int
ATR_GetNumberOfProtocols (ATR * atr, unsigned *number_protocols)
{
  (*number_protocols) = atr->pn;
  return (ATR_OK);
}

int
ATR_GetProtocolType (ATR * atr, unsigned number_protocol, BYTE *protocol_type)
{
  if ((number_protocol > atr->pn) || number_protocol < 2)
    return ATR_NOT_FOUND;

  if (atr->ib[number_protocol - 2][ATR_INTERFACE_BYTE_TD].present)
    (*protocol_type) =
      (atr->ib[number_protocol - 2][ATR_INTERFACE_BYTE_TD].value & 0x0F);
  else
    (*protocol_type) = ATR_PROTOCOL_TYPE_T0;

  return (ATR_OK);
}

int
ATR_GetInterfaceByte (ATR * atr, unsigned number, int character, BYTE * value)
{
  if (number > atr->pn || number < 1)
    return (ATR_NOT_FOUND);

  if (atr->ib[number - 1][character].present &&
      (character == ATR_INTERFACE_BYTE_TA ||
       character == ATR_INTERFACE_BYTE_TB ||
       character == ATR_INTERFACE_BYTE_TC ||
       character == ATR_INTERFACE_BYTE_TD))
    (*value) = atr->ib[number - 1][character].value;
  else
    return (ATR_NOT_FOUND);

  return (ATR_OK);
}

int
ATR_GetIntegerValue (ATR * atr, int name, BYTE * value)
{
  int ret;

  if (name == ATR_INTEGER_VALUE_FI)
    {
      if (atr->ib[0][ATR_INTERFACE_BYTE_TA].present)
	{
	  (*value) = (atr->ib[0][ATR_INTERFACE_BYTE_TA].value & 0xF0) >> 4;
	  ret = ATR_OK;
	}
      else
	ret = ATR_NOT_FOUND;
    }

  else if (name == ATR_INTEGER_VALUE_DI)
    {
      if (atr->ib[0][ATR_INTERFACE_BYTE_TA].present)
	{
	  (*value) = (atr->ib[0][ATR_INTERFACE_BYTE_TA].value & 0x0F);
	  ret = ATR_OK;
	}
      else
	ret = ATR_NOT_FOUND;
    }

  else if (name == ATR_INTEGER_VALUE_II)
    {
      if (atr->ib[0][ATR_INTERFACE_BYTE_TB].present)
	{
	  (*value) = (atr->ib[0][ATR_INTERFACE_BYTE_TB].value & 0x60) >> 5;
	  ret = ATR_OK;
	}
      else
	ret = ATR_NOT_FOUND;
    }

  else if (name == ATR_INTEGER_VALUE_PI1)
    {
      if (atr->ib[0][ATR_INTERFACE_BYTE_TB].present)
	{
	  (*value) = (atr->ib[0][ATR_INTERFACE_BYTE_TB].value & 0x1F);
	  ret = ATR_OK;
	}
      else
	ret = ATR_NOT_FOUND;
    }

  else if (name == ATR_INTEGER_VALUE_PI2)
    {
      if (atr->ib[1][ATR_INTERFACE_BYTE_TB].present)
	{
	  (*value) = atr->ib[1][ATR_INTERFACE_BYTE_TB].value;
	  ret = ATR_OK;
	}
      else
	ret = ATR_NOT_FOUND;
    }

  else if (name == ATR_INTEGER_VALUE_N)
    {
      if (atr->ib[0][ATR_INTERFACE_BYTE_TC].present)
	{
	  (*value) = atr->ib[0][ATR_INTERFACE_BYTE_TC].value;
	  ret = ATR_OK;
	}
      else
	ret = ATR_NOT_FOUND;
    }
  else
    ret = ATR_NOT_FOUND;

  return ret;
}

int
ATR_GetParameter (ATR * atr, int name, double *parameter)
{
  BYTE FI, DI, II, PI1, PI2, N;

  if (name == ATR_PARAMETER_F)
    {
      if (ATR_GetIntegerValue (atr, ATR_INTEGER_VALUE_FI, &FI) == ATR_OK)
	(*parameter) = (double) (atr_f_table[FI]);
      else
	(*parameter) = (double) ATR_DEFAULT_F;
      return (ATR_OK);
    }

  else if (name == ATR_PARAMETER_D)
    {
      if (ATR_GetIntegerValue (atr, ATR_INTEGER_VALUE_DI, &DI) == ATR_OK)
	(*parameter) = (double) (atr_d_table[DI]);
      else
	(*parameter) = (double) ATR_DEFAULT_D;
      return (ATR_OK);
    }

  else if (name == ATR_PARAMETER_I)
    {
      if (ATR_GetIntegerValue (atr, ATR_INTEGER_VALUE_II, &II) == ATR_OK)
	(*parameter) = (double) (atr_i_table[II]);
      else
	(*parameter) = ATR_DEFAULT_I;
      return (ATR_OK);
    }

  else if (name == ATR_PARAMETER_P)
    {
      if (ATR_GetIntegerValue (atr, ATR_INTEGER_VALUE_PI2, &PI2) == ATR_OK)
	(*parameter) = (double) PI2;
      else if (ATR_GetIntegerValue (atr, ATR_INTEGER_VALUE_PI1, &PI1) == ATR_OK)
	(*parameter) = (double) PI1;
      else
	(*parameter) = (double) ATR_DEFAULT_P;
      return (ATR_OK);
    }

  else if (name == ATR_PARAMETER_N)
    {
      if (ATR_GetIntegerValue (atr, ATR_INTEGER_VALUE_N, &N) == ATR_OK)
	(*parameter) = (double) N;
      else
	(*parameter) = (double) ATR_DEFAULT_N;
      return (ATR_OK);
    }

  return (ATR_NOT_FOUND);
}

int
ATR_GetHistoricalBytes (ATR * atr, BYTE hist[ATR_MAX_HISTORICAL], unsigned *length)
{
  if (atr->hbn == 0)
    return (ATR_NOT_FOUND);

  (*length) = atr->hbn;
  memcpy (hist, atr->hb, atr->hbn);
  return (ATR_OK);
}

int
ATR_GetRaw (ATR * atr, BYTE buffer[ATR_MAX_SIZE], unsigned *length)
{
  unsigned i, j;

  buffer[0] = atr->TS;
  buffer[1] = atr->T0;

  j = 2;

  for (i = 0; i < atr->pn; i++)
    {
      if (atr->ib[i][ATR_INTERFACE_BYTE_TA].present)
	buffer[j++] = atr->ib[i][ATR_INTERFACE_BYTE_TA].value;

      if (atr->ib[i][ATR_INTERFACE_BYTE_TB].present)
	buffer[j++] = atr->ib[i][ATR_INTERFACE_BYTE_TB].value;

      if (atr->ib[i][ATR_INTERFACE_BYTE_TC].present)
	buffer[j++] = atr->ib[i][ATR_INTERFACE_BYTE_TC].value;

      if (atr->ib[i][ATR_INTERFACE_BYTE_TD].present)
	buffer[j++] = atr->ib[i][ATR_INTERFACE_BYTE_TD].value;
    }

  if (atr->hbn > 0)
    {
      memcpy (&(buffer[j]), atr->hb, atr->hbn);
      j += atr->hbn;
    }

  if ((atr->TCK).present)
    buffer[j++] = (atr->TCK).value;

  (*length) = j;

  return ATR_OK;
}

int
ATR_GetCheckByte (ATR * atr, BYTE * check_byte)
{
  if (!((atr->TCK).present))
    return (ATR_NOT_FOUND);

  (*check_byte) = (atr->TCK).value;
  return (ATR_OK);
}

int
ATR_GetFsMax (ATR * atr, unsigned long *fsmax)
{
  BYTE FI;

  if (ATR_GetIntegerValue (atr, ATR_INTEGER_VALUE_FI, &FI) == ATR_OK)
    (*fsmax) = atr_fs_table[FI];
  else
    (*fsmax) = atr_fs_table[1];

  return (ATR_OK);
}


--- NEW FILE: atr.h ---
/*
    atr.h
    ISO 7816 ICC's answer to reset abstract data type definitions

    This file is part of the Unix driver for Towitoko smartcard readers
    Copyright (C) 2000 Carlos Prados <cprados@yahoo.com>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library 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
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#ifndef _ATR_
#define _ATR_

#include "defines.h"
//#include "io_serial.h"

/*
 * Exported constants definition
 */

/* Return values */
#define ATR_OK		0	/* ATR could be parsed and data returned */
#define ATR_NOT_FOUND	1	/* Data not present in ATR */
#define ATR_MALFORMED	2	/* ATR could not be parsed */
#define ATR_IO_ERROR	3	/* I/O stream error */

/* Paramenters */
#define ATR_MAX_SIZE 		33	/* Maximum size of ATR byte array */
#define ATR_MAX_HISTORICAL	15	/* Maximum number of historical bytes */
#define ATR_MAX_PROTOCOLS	7	/* Maximun number of protocols */
#define ATR_MAX_IB		4	/* Maximum number of interface bytes per protocol */
#define ATR_CONVENTION_DIRECT	0	/* Direct convention */
#define ATR_CONVENTION_INVERSE	1	/* Inverse convention */
#define ATR_PROTOCOL_TYPE_T0	0	/* Protocol type T=0 */
#define ATR_PROTOCOL_TYPE_T1	1	/* Protocol type T=1 */
#define ATR_PROTOCOL_TYPE_T2	2	/* Protocol type T=2 */
#define ATR_PROTOCOL_TYPE_T3	3	/* Protocol type T=3 */
#define ATR_PROTOCOL_TYPE_T14	14	/* Protocol type T=14 */
#define ATR_INTERFACE_BYTE_TA	0	/* Interface byte TAi */
#define ATR_INTERFACE_BYTE_TB	1	/* Interface byte TBi */
#define ATR_INTERFACE_BYTE_TC	2	/* Interface byte TCi */
#define ATR_INTERFACE_BYTE_TD	3	/* Interface byte TDi */
#define ATR_PARAMETER_F		0	/* Parameter F */
#define ATR_PARAMETER_D		1	/* Parameter D */
#define ATR_PARAMETER_I		2	/* Parameter I */
#define ATR_PARAMETER_P		3	/* Parameter P */
#define ATR_PARAMETER_N		4	/* Parameter N */
#define ATR_INTEGER_VALUE_FI	0	/* Integer value FI */
#define ATR_INTEGER_VALUE_DI	1	/* Integer value DI */
#define ATR_INTEGER_VALUE_II	2	/* Integer value II */
#define ATR_INTEGER_VALUE_PI1	3	/* Integer value PI1 */
#define ATR_INTEGER_VALUE_N	4	/* Integer value N */
#define ATR_INTEGER_VALUE_PI2	5	/* Integer value PI2 */

/* Default values for paramenters */
#define ATR_DEFAULT_F	372
#define ATR_DEFAULT_D	1
#define ATR_DEFAULT_I 	50
#define ATR_DEFAULT_N	0
#define ATR_DEFAULT_P	5

/*
 * Exported data types definition
 */

typedef struct
{
  unsigned length;
  BYTE TS;
  BYTE T0;
  struct
  {
    BYTE value;
    bool present;
  }
  ib[ATR_MAX_PROTOCOLS][ATR_MAX_IB], TCK;
  unsigned pn;
  BYTE hb[ATR_MAX_HISTORICAL];
  unsigned hbn;
}
ATR;

/*
 * Exported variables declaration
 */

extern unsigned atr_f_table[16];
extern double atr_d_table[16];
extern unsigned atr_i_table[4];

/*
 * Exported functions declaraton
 */

/* Creation and deletion */
extern ATR *ATR_New (void);
extern void ATR_Delete (ATR * atr);

/* Initialization */
extern int ATR_InitFromArray (ATR * atr, BYTE buffer[ATR_MAX_SIZE], unsigned length);

/* General smartcard characteristics */
extern int ATR_GetConvention (ATR * atr, int *convention);
extern int ATR_GetNumberOfProtocols (ATR * atr, unsigned *number_protocols);
extern int ATR_GetProtocolType (ATR * atr, unsigned number_protocol, BYTE *protocol_type);

/* ATR parameters and integer values */
extern int ATR_GetInterfaceByte (ATR * atr, unsigned number, int character, BYTE * ib);
extern int ATR_GetIntegerValue (ATR * atr, int name, BYTE * value);
extern int ATR_GetParameter (ATR * atr, int name, double *parameter);
extern int ATR_GetHistoricalBytes (ATR * atr, BYTE * hist, unsigned *length);
extern int ATR_GetCheckByte (ATR * atr, BYTE * check_byte);
extern int ATR_GetFsMax (ATR * atr, unsigned long *fsmax);

/* Raw ATR retrieving */
extern int ATR_GetRaw (ATR * atr, BYTE * buffer, unsigned *lenght);
extern int ATR_GetSize (ATR * atr, unsigned *size);

#endif /* _ATR_ */

--- NEW FILE: defines.h ---
/*
    defines.h

    This file is part of the Unix driver for Towitoko smartcard readers
    Copyright (C) 2000 Carlos Prados <cprados@yahoo.com>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library 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
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#ifndef DEFINES_H
#define DEFINES_H

/*
 * Get configuration information
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

/*
 * Boolean constants
 */

#ifndef TRUE
#define TRUE	1
#endif

#ifndef FALSE
#define FALSE	0
#endif

/*
 * Type definitions
 */

#include "pcscdefines.h"

typedef unsigned char      BYTE;
#ifndef __cplusplus
typedef int                bool;
#endif

/*
 * Utility macros
 */

#ifndef MAX
#define MAX(a,b)	((a)>(b)?(a):(b))
#endif

#ifndef MIN
#define MIN(a,b)	((a)<(b)?(a):(b))
#endif

/* Invert order of bits in a byte: b7->b0, b0->b7 */
#ifndef INVERT_BYTE
#define INVERT_BYTE(a)		((((a) << 7) & 0x80) | \
				(((a) << 5) & 0x40) | \
				(((a) << 3) & 0x20) | \
				(((a) << 1) & 0x10) | \
				(((a) >> 1) & 0x08) | \
				(((a) >> 3) & 0x04) | \
				(((a) >> 5) & 0x02) | \
				(((a) >> 7) & 0x01))
#endif

#endif /* DEFINES_H */


--- NEW FILE: pps.c ---
/*
    pps.c
    Protocol Parameters Selection
  
    This file is part of the Unix driver for Towitoko smartcard readers
    Copyright (C) 2000 2001 Carlos Prados <cprados@yahoo.com>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library 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
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
#    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include "protocol_t1.h"
#include "pps.h"
#include "atr.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "commands.h"
#include "defs.h"
#include "ifdhandler.h"

/*
 * Not exported constants definition
 */

#define PPS_DEFAULT_PROTOCOL	0x00

/*
 * Not exported macros definition
 */

#define PPS_HAS_PPS1(block)	((block[1] & 0x10) == 0x10)
#define PPS_HAS_PPS2(block)	((block[1] & 0x20) == 0x20)
#define PPS_HAS_PPS3(block)	((block[1] & 0x40) == 0x40)

/*
 * Not exported funtions declaration
 */

static bool PPS_Match (BYTE * request, unsigned len_request, BYTE * reply, unsigned len_reply);

static unsigned PPS_GetLength (BYTE * block);

static BYTE PPS_GetPCK (BYTE * block, unsigned length);

int
PPS_Exchange (Protocol_T1 * t1, BYTE * params, unsigned *length)
{
  BYTE confirm[PPS_MAX_LENGTH];
  unsigned len_request, len_confirm;
  int ret;
#ifdef DEBUG_PROTOCOL
  int i;
#endif

  len_request = PPS_GetLength (params);
  params[len_request - 1] = PPS_GetPCK(params, len_request - 1);

#ifdef DEBUG_PROTOCOL
  printf ("PPS: Sending request: ");
  for (i = 0; i < len_request; i++)
    printf ("%X ", params[i]);
  printf ("\n");
#endif

  /* Send PPS request */
  if (CCID_Transmit (t1->lun, len_request, params) != IFD_SUCCESS)
    return PPS_ICC_ERROR;

  /* Get PPS confirm */
  len_confirm = sizeof(confirm);
  if (CCID_Receive (t1->lun, &len_confirm, confirm) != IFD_SUCCESS)
    return PPS_ICC_ERROR;

  len_confirm = PPS_GetLength (confirm);

#ifdef DEBUG_PROTOCOL
  printf ("PPS: Receivig confirm: ");
  for (i = 0; i < len_confirm; i++)
    printf ("%X ", confirm[i]);
  printf ("\n");
#endif

  if (!PPS_Match (params, len_request, confirm, len_confirm))
    ret = PPS_HANDSAKE_ERROR;
  else
    ret = PPS_OK;

  /* Copy PPS handsake */
  memcpy (params, confirm, len_confirm);
  (*length) = len_confirm;

  return ret;
}

static bool
PPS_Match (BYTE * request, unsigned len_request, BYTE * confirm, unsigned len_confirm)
{
  /* See if the reply differs from request */
  if ((len_request != len_confirm) ||
      (!memcmp (request, confirm, len_request)))
    {
      /* See if the card specifies other than default FI and D */
      if ((PPS_HAS_PPS1 (confirm)) && (confirm[2] != request[2]))
	return FALSE;
    }

  return TRUE;
}

static unsigned
PPS_GetLength (BYTE * block)
{
  unsigned length = 3;

  if (PPS_HAS_PPS1 (block))
    length++;

  if (PPS_HAS_PPS2 (block))
    length++;

  if (PPS_HAS_PPS3 (block))
    length++;

  return length;
}

static BYTE
PPS_GetPCK (BYTE * block, unsigned length)
{
  BYTE pck;
  unsigned i;

  pck = block[0];
  for (i = 1; i < length; i++)
    pck ^= block[i];

  return pck;
}

--- NEW FILE: pps.h ---
/*
    pps.h
    Protocol Parameters Selection

    This file is part of the Unix driver for Towitoko smartcard readers
    Copyright (C) 2000 2001 Carlos Prados <cprados@yahoo.com>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library 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
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#ifndef _PPS_
#define _PPS_

#include "defines.h"

/*
 * Exported constants definition
 */

#define PPS_OK			0	/* Negotiation OK */
#define PPS_ICC_ERROR		1	/* Comunication error */
#define PPS_HANDSAKE_ERROR	2	/* Agreement not reached */
#define PPS_PROTOCOL_ERROR	3	/* Error starting protocol */
#define PPS_MAX_LENGTH		6
/*
 * Exported data types definition
 */

typedef struct
{
  double f;
  double d;
  double n;
  BYTE t;
}
PPS_ProtocolParameters;

typedef struct
{
  int icc;
  void *protocol;
  PPS_ProtocolParameters parameters;
}
PPS;

/*
 * Exported functions declaration
 */

int PPS_Exchange (Protocol_T1 * t1, BYTE * params, unsigned *length);

#endif /* _PPS_ */

--- NEW FILE: protocol_t1.c ---
/*
    protocol_t1.c
    Handling of ISO 7816 T=1 protocol
    
    This file is part of the Unix driver for Towitoko smartcard readers
    Copyright (C) 2000 Carlos Prados <cprados@yahoo.com>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library 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
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include "defines.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "protocol_t1.h"
#include "t1_block.h"
#include "atr.h"
#include "pps.h"

#include "defs.h"
#include "ccid.h"
#include "commands.h"
#include "ifdhandler.h"

/*
 * Not exported constants definition
 */
#define PROTOCOL_T1_DEFAULT_IFSC        32
#define PROTOCOL_T1_DEFAULT_IFSD        32
#define PROTOCOL_T1_MAX_IFSC            251  /* Cannot send > 255 buffer */
#define PROTOCOL_T1_DEFAULT_CWI         13
#define PROTOCOL_T1_DEFAULT_BWI         4
#define PROTOCOL_T1_EDC_LRC             0
#define PROTOCOL_T1_EDC_CRC             1

/* #define DEBUG_PROTOCOL */

/*
 * Not exported functions declaration
 */

static void 
Protocol_T1_Clear (Protocol_T1 * t1);

static int
Protocol_T1_SendBlock (Protocol_T1 * t1, T1_Block * block);

static int
Protocol_T1_ReceiveBlock (Protocol_T1 * t1, T1_Block ** block);

/*
 * Exproted funtions definition
 */

int
Protocol_T1_Init (Protocol_T1 * t1, int lun)
{
  BYTE ta, tc;
  ATR atr;

  /* Set ICC */
  t1->lun = lun;

  /* Get ATR of the card */
  ATR_InitFromArray(&atr, get_ccid_slot(lun) -> pcATRBuffer,
    get_ccid_slot(lun) -> nATRLength);

  /* Set IFSC */
  if (ATR_GetInterfaceByte (&atr, 3, ATR_INTERFACE_BYTE_TA, &ta) == ATR_NOT_FOUND)
    t1->ifsc = PROTOCOL_T1_DEFAULT_IFSC;
  else if ((ta != 0x00) && (ta != 0xFF))
    t1->ifsc = ta;
  else
    t1->ifsc = PROTOCOL_T1_DEFAULT_IFSC;

  /* Towitoko does not allow IFSC > 251 */
  t1->ifsc = MIN (t1->ifsc, PROTOCOL_T1_MAX_IFSC);

  /* Set IFSD */
  t1->ifsd = PROTOCOL_T1_DEFAULT_IFSD;

  /* Set the error detection code type */
  if (ATR_GetInterfaceByte (&atr, 3, ATR_INTERFACE_BYTE_TC, &tc) == ATR_NOT_FOUND)
    t1->edc = PROTOCOL_T1_EDC_LRC;
  else
    t1->edc = tc & 0x01;

  /* Set initial send sequence (NS) */
  t1->ns = 1;
  
  /* PPS */
  {
  	int len = 3;
	BYTE pps[] = {0xFF, 0x11, 0x94, 0};
	BYTE param[] = {0x94, 0x10, 0x00, 0x43, 0x00, 0x20, 0x00};

  	PPS_Exchange(t1, pps, &len);

	SetParameters(t1->lun, 1, 7, param);
  }

#ifdef DEBUG_PROTOCOL
  printf ("Protocol: T=1: IFSC=%d, IFSD=%d, EDC=%s\n",
     t1->ifsc, t1->ifsd, (t1->edc == PROTOCOL_T1_EDC_LRC) ? "LRC" : "CRC");
#endif

  return PROTOCOL_T1_OK;
}

int
Protocol_T1_Command (Protocol_T1 * t1, APDU_Cmd * cmd, APDU_Rsp * rsp)
{
  T1_Block *block;
  BYTE *buffer, rsp_type, bytes, nr, wtx;
  unsigned short counter;
  int ret;
  bool more;

  /* Calculate the number of bytes to send */
  counter = 0;
  bytes = MIN (cmd->length, t1->ifsc);

  /* See if chaining is needed */
  more = (cmd->length > t1->ifsc);

  /* Increment ns */
  t1->ns = (t1->ns + 1) %2;

  /* Create an I-Block */
  block = T1_Block_NewIBlock (bytes, cmd->command, t1->ns, more);

#ifdef DEBUG_PROTOCOL
  printf ("Sending block I(%d,%d)\n", t1->ns, more);
#endif

  /* Send a block */
  ret = Protocol_T1_SendBlock (t1, block);

  /* Delete I-block */
  T1_Block_Delete (block);

  while ((ret == PROTOCOL_T1_OK) && more)
    {
      /* Receive a block */
      ret = Protocol_T1_ReceiveBlock (t1, &block);

      if (ret == PROTOCOL_T1_OK)
        {
          rsp_type = T1_Block_GetType (block);

          /* Positive ACK R-Block received */
          if (rsp_type == T1_BLOCK_R_OK)
            {
#ifdef DEBUG_PROTOCOL
              printf ("Protocol: Received block R(%d)\n", T1_Block_GetNR (block));
#endif                   
              /* Delete block */
              T1_Block_Delete (block);
 
              /* Increment ns  */
              t1->ns = (t1->ns + 1) % 2;

              /* Calculate the number of bytes to send */
              counter += bytes;
              bytes = MIN (cmd->length - counter, t1->ifsc);

              /* See if chaining is needed */
              more = (cmd->length - counter > t1->ifsc);

              /* Create an I-Block */
              block =
                T1_Block_NewIBlock (bytes, cmd->command + counter,
                                    t1->ns, more);
#ifdef DEBUG_PROTOCOL
              printf ("Protocol: Sending block I(%d,%d)\n", t1->ns, more);
#endif
              /* Send a block */
              ret = Protocol_T1_SendBlock (t1, block);

              /* Delete I-block */
              T1_Block_Delete (block);
            }
                                   
          else
            {
              /* Delete block */
              T1_Block_Delete (block);

              ret = PROTOCOL_T1_NOT_IMPLEMENTED;
            }
        }

      else
        {
          ret = PROTOCOL_T1_NOT_IMPLEMENTED;
        }
    }

  /* Reset counter */
  buffer = NULL;
  counter = 0;      
  more = TRUE;
  wtx = 0;
      
  while ((ret == PROTOCOL_T1_OK) && more)
    {
      /* Receive a block */
      ret = Protocol_T1_ReceiveBlock (t1, &block);

      if (ret == PROTOCOL_T1_OK)
        {
          rsp_type = T1_Block_GetType (block);

          if (rsp_type == T1_BLOCK_I)
            {
#ifdef DEBUG_PROTOCOL
              printf ("Protocol: Received block I(%d,%d)\n", 
              T1_Block_GetNS(block), T1_Block_GetMore (block));
#endif
              /* Calculate nr */
              nr = (T1_Block_GetNS (block) + 1) % 2;
                               
              /* Save inf field */
              bytes = T1_Block_GetLen (block);
	      buffer = (BYTE *) realloc(buffer, counter + bytes);
              memcpy (buffer + counter, T1_Block_GetInf (block), bytes);
              counter += bytes;

              /* See if chaining is requested */
              more = T1_Block_GetMore (block);

              /* Delete block */
              T1_Block_Delete (block);

              if (more)
                {
                  /* Create an R-Block */
                  block = T1_Block_NewRBlock (T1_BLOCK_R_OK, nr);
#ifdef DEBUG_PROTOCOL
                  printf ("Protocol: Sending block R(%d)\n", nr);
#endif                    
                  /* Send R-Block */
                  ret = Protocol_T1_SendBlock (t1, block);

                  /* Delete I-block */
                  T1_Block_Delete (block);
                }
            }

          /* WTX Request S-Block received */ 
          else if (rsp_type == T1_BLOCK_S_WTX_REQ)
            {
              /* Get wtx multiplier */
              wtx = (*T1_Block_GetInf (block));
#ifdef DEBUG_PROTOCOL
              printf ("Protocol: Received block S(WTX request, %d)\n", wtx);
#endif                                  
              /* Delete block */
              T1_Block_Delete (block);
             
              /* Create an WTX response S-Block */
              block = T1_Block_NewSBlock (T1_BLOCK_S_WTX_RES, 1, &wtx);
#ifdef DEBUG_PROTOCOL
              printf ("Protocol: Sending block S(WTX response, %d)\n", wtx);
#endif                    
              /* Send WTX response */
              ret = Protocol_T1_SendBlock (t1, block);
                  
              /* Delete block */
              T1_Block_Delete (block);
            }

          else
            {
              ret = PROTOCOL_T1_NOT_IMPLEMENTED;
            }
        }
    }

  if (ret == PROTOCOL_T1_OK)
  {
    rsp -> response = buffer;
    rsp -> length = counter;
  }
  else
  {
    rsp -> response = NULL;
    rsp -> length = 0;
  }

  return ret;
}

int
Protocol_T1_Close (Protocol_T1 * t1)
{
  Protocol_T1_Clear (t1);

  return PROTOCOL_T1_OK;
}

/*
 * Not exported functions definition
 */

static int
Protocol_T1_SendBlock (Protocol_T1 * t1, T1_Block * block)
{
  /* Send T=1 block */
  if (CCID_Transmit(t1->lun, T1_Block_RawLen (block), T1_Block_Raw (block))
      != IFD_SUCCESS)
	  return PROTOCOL_T1_ICC_ERROR;

  return PROTOCOL_T1_OK;
}

static int
Protocol_T1_ReceiveBlock (Protocol_T1 * t1, T1_Block ** block)
{
  unsigned char cmd[T1_BLOCK_MAX_SIZE]; /* CCID + T1 block */
  int ret;
  int len = sizeof(cmd);

  /* Receive T=1 block */
  if (CCID_Receive(t1->lun, &len, cmd) != IFD_SUCCESS)
    {
      if (len >= ERROR_OFFSET)
        ccid_error(cmd[ERROR_OFFSET], __FILE__, __LINE__);	/* bError */
      ret = PROTOCOL_T1_ICC_ERROR;
      (*block) = NULL;
    }

  else
    {
      ret = PROTOCOL_T1_OK;
      (*block) = T1_Block_New (cmd, len);
    }

  return ret;
}

static void
Protocol_T1_Clear (Protocol_T1 * t1)
{
  t1->lun = 0;
  t1->ifsc = 0;
  t1->ifsd = 0;
  t1->edc = 0;
  t1->ns = 0;
}


--- NEW FILE: protocol_t1.h ---
/*
    protocol_t1.h
    ISO 7816 T=1 Transport Protocol definitions 

    This file is part of the Unix driver for Towitoko smartcard readers
    Copyright (C) 2000 Carlos Prados <cprados@yahoo.com>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library 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
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#ifndef _PROTOCOL_T1_
#define _PROTOCOL_T1_

#include "defines.h"
#include "apdu.h"

/*
 * Exported constants definition
 */

/* Return codes */
#define PROTOCOL_T1_OK                  0       /* Command OK */
#define PROTOCOL_T1_ICC_ERROR           2       /* ICC comunication error */
#define PROTOCOL_T1_ERROR               4       /* T=1 Protocol Error */
#define PROTOCOL_T1_NOT_IMPLEMENTED     7       /* Feture not implemented */

/*
 * Exported datatypes definition
 */

/* T=1 Protocol context */
typedef struct
{
  int lun;       /* Asynchronous integrated cirtuit card */
  unsigned short ifsc;  /* Information field size for the ICC */
  unsigned short ifsd;  /* Information field size for the IFD */
  int edc;              /* Type of error detection code */
  BYTE ns;              /* Send sequence number */
}
Protocol_T1;

/*
 * Exported functions declaration
 */

/* Create a new protocol handler */
extern Protocol_T1 * 
Protocol_T1_New (void);

/* Delete a protocol handler */
extern void 
Protocol_T1_Delete (Protocol_T1 * t1);

/* Initialise a protocol handler */
extern int 
Protocol_T1_Init (Protocol_T1 * t1, int icc);

/* Send a command and return a response */
extern int
Protocol_T1_Command (Protocol_T1 * t1, APDU_Cmd * cmd, APDU_Rsp * rsp);

/* Close a protocol handler */
extern int 
Protocol_T1_Close (Protocol_T1 * t1);

#endif /* _PROTOCOL_T1_ */

--- NEW FILE: t1_block.c ---
/*
    t1_block.h
    T=1 block abstract data type implementation

    This file is part of the Unix driver for Towitoko smartcard readers
    Copyright (C) 2000 Carlos Prados <cprados@yahoo.com>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library 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
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include "t1_block.h"
#include <stdlib.h>
#include <string.h>

/* #define DEBUG_PROTOCOL */

#ifdef DEBUG_PROTOCOL
#include <stdio.h>
#include "debug.h"
#endif

/*
 * Not exported constants definition
 */
 
#define T1_BLOCK_NAD        0x00

/*
 * Not exported functions declaration
 */
static BYTE
T1_Block_LRC (BYTE * data, unsigned length);
 
/*
 * Exported functions definition
 */

T1_Block *
T1_Block_New (BYTE * buffer, unsigned length)
{
  T1_Block * block;
  
  if (length < 4)
    return NULL;
  
  block = (T1_Block *) malloc (sizeof (T1_Block));
  
  if (block != NULL)
    {
      block->length = MIN(length, T1_BLOCK_MAX_SIZE);
      block->data = (BYTE *) calloc (block->length, sizeof (BYTE));
      
      if (block->data != NULL)
        {
          memcpy (block->data, buffer, block->length);
        }
      else
        {
          free (block);
          block = NULL;
        }
    }
  
  return block;
}

T1_Block *
T1_Block_NewIBlock (BYTE len, BYTE * inf, BYTE ns, bool more)
{
  T1_Block * block;
  
  block = (T1_Block *) malloc (sizeof (T1_Block));
  
  if (block != NULL)
    {
      block->length = len + 4;
      block->data = (BYTE *) calloc (block->length, sizeof (BYTE));
      
      if (block->data != NULL)
        {
          block->data[0] = T1_BLOCK_NAD;
          block->data[1] = T1_BLOCK_I | ((ns << 6) & 0x40);
          
          if (more)
            block->data[1] |= 0x20;
            
          block->data[2] = len;
          
          if (len != 0x00)
            memcpy (block->data + 3, inf, len);
          
          block->data[len+3] = T1_Block_LRC (block->data, len+3);
        }
      else
        {
          free (block);
          block = NULL;
        }
    }
  
  return block;
}

T1_Block *
T1_Block_NewRBlock (BYTE type, BYTE nr)
{
  T1_Block * block;
  
  block = (T1_Block *) malloc (sizeof (T1_Block));
  
  if (block != NULL)
    {
      block->length = 4;
      block->data = (BYTE *) calloc (block->length, sizeof (BYTE));
      
      if (block->data != NULL)
        {
          block->data[0] = T1_BLOCK_NAD;
          block->data[1] = type | ((nr << 4) & 0x10);
          block->data[2] = 0x00;
          block->data[3] = T1_Block_LRC (block->data, 3);
        }
      else
        {
          free (block);
          block = NULL;
        }
    }
  
  return block;
}

T1_Block *
T1_Block_NewSBlock (BYTE type, BYTE len, BYTE * inf)
{
  T1_Block * block;
  
  block = (T1_Block *) malloc (sizeof (T1_Block));
  
  if (block != NULL)
    {
      block->length = 4 + len;
      block->data = (BYTE *) calloc (block->length, sizeof (BYTE));
      
      if (block->data != NULL)
        {
          block->data[0] = T1_BLOCK_NAD;
          block->data[1] = type;
          block->data[2] = len;

          if (len != 0x00)
            memcpy (block->data + 3, inf, len);
          
          block->data[len+3] = T1_Block_LRC (block->data, len+3);
        }
      else
        {
          free (block);
          block = NULL;
        }
    }
  
  return block;
}

BYTE
T1_Block_GetType (T1_Block * block)
{
  if ((block->data[1] & 0x80) == T1_BLOCK_I)
    return T1_BLOCK_I;
    
  return (block->data[1] & 0xEF);
}

BYTE
T1_Block_GetNS (T1_Block * block)
{
  return ((block->data[1] >> 6)& 0x01);
}

bool
T1_Block_GetMore (T1_Block * block)
{
  return ((block->data[1] >> 5) & 0x01);
}

BYTE
T1_Block_GetNR (T1_Block * block)
{
  return ((block->data[1] >> 4) & 0x01);
}

BYTE
T1_Block_GetLen (T1_Block * block)
{
  return block->data[2];
}

BYTE *
T1_Block_GetInf (T1_Block * block)
{
  if (block->length < 5)
    return NULL;
    
  return block->data + 3;
}

BYTE *
T1_Block_Raw (T1_Block * block)
{
  return block->data;
}

unsigned
T1_Block_RawLen (T1_Block * block)
{
  return block->length;
}

void
T1_Block_Delete (T1_Block * block)
{
  free (block->data);
  free (block);
}

/*
 * Not exported functions definition
 */

static BYTE
T1_Block_LRC (BYTE * data, unsigned length)
{
  BYTE lrc;
  unsigned i;

  lrc = 0x00;
  for (i = 0; i < length; i++)
    {
      lrc ^= data[i];
    }
    
  return lrc;       
}


--- NEW FILE: t1_block.h ---
/*
    t1_block.h
    T=1 block abstract data type definitions

    This file is part of the Unix driver for Towitoko smartcard readers
    Copyright (C) 2000 Carlos Prados <cprados@yahoo.com>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library 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
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#ifndef _T1_BLOCK_
#define _T1_BLOCK_

#include "defines.h"

/*
 * Exported constants definition
 */

/* Buffer sizes */
#define T1_BLOCK_MAX_SIZE                259
#define T1_BLOCK_INF_MAX_SIZE            254

/* Types of block */
#define T1_BLOCK_I                0x00
#define T1_BLOCK_R_OK             0x80
#define T1_BLOCK_R_EDC_ERR        0x81
#define T1_BLOCK_R_OTHER_ERR      0x82
#define T1_BLOCK_S_RESYNCH_REQ    0xC0
#define T1_BLOCK_S_RESYNCH_RES    0xE0
#define T1_BLOCK_S_IFS_REQ        0xC1
#define T1_BLOCK_S_IFS_RES        0xE1
#define T1_BLOCK_S_ABORT_REQ      0xC2
#define T1_BLOCK_S_ABORT_RES      0xE2
#define T1_BLOCK_S_WTX_REQ        0xC3
#define T1_BLOCK_S_WTX_RES        0xE3
#define T1_BLOCK_S_VPP_ERR        0xE4

/*
 * Exported data types definition
 */

typedef struct
{
  BYTE * data;
  unsigned length;
}
T1_Block;
 
/*
 * Exported functions declaration
 */

extern T1_Block *
T1_Block_New (BYTE * buffer, unsigned length);

extern T1_Block *
T1_Block_NewIBlock (BYTE len, BYTE * inf, BYTE ns, bool more);

extern T1_Block *
T1_Block_NewRBlock (BYTE type, BYTE nr);

extern T1_Block *
T1_Block_NewSBlock (BYTE type, BYTE len, BYTE * inf);

extern BYTE
T1_Block_GetType (T1_Block * block);

extern BYTE
T1_Block_GetNS (T1_Block * block);

extern bool
T1_Block_GetMore (T1_Block * block);

extern BYTE
T1_Block_GetNR (T1_Block * block);

extern BYTE
T1_Block_GetLen (T1_Block * block);

extern BYTE *
T1_Block_GetInf (T1_Block * block);

extern BYTE *
T1_Block_Raw (T1_Block * block);

extern unsigned
T1_Block_RawLen (T1_Block * block);

extern void
T1_Block_Delete (T1_Block * block);

extern void
T1_Block_Dump(T1_Block * block);

#endif /* _T1_BLOCK_ */