/******************************************************************************
*                                                                             *
*              Copyright (C),  Philips Semiconductors SLH                     *
*                                                                             *
*  All rights are reserved. Reproduction in whole or in part is prohibited    *
*           without the written consent of the copyright owner.               *
*                                                                             *
*  Philips reserves the right to make changes without notice at any time.     *
* Philips makes no warranty, expressed, implied or statutory, including but   *
* not limited to any implied warranty of merchantibility or fitness for any   *
*   particular purpose, or that the use will not infringe any third party     *
* patent, copyright or trademark. Philips must not be liable for any loss or  *
*                      damage arising from its use.                           *
*                                                                             *
*******************************************************************************
*                                                                             *
*       Project: 336355/105 - Control SW Library for HTRC110/HTRC120/HITAG2   *
*                                                                             *
*       File: CO_BASE.C                                                       *
*       Author: F. Boeh                                                       *
*               S. de Zeeuw                                                   *
*                                                                             *
*******************************************************************************
*      DATE      *          CHANGES DONE                         *    BY      *
*******************************************************************************
*                *                                               *            *
*  Apr 27,1998   * Version 2.0, release                          *  DE ZEEUW  *
*                *                                               *            *
*******************************************************************************/

#include "HTRC120.H"
#include "portab.h"


#pragma regparms

unsigned char send_copro( unsigned char idata * addr, unsigned char length )
/******************************************************************************
*                                                                             *
* Description:                                                                *
* This procedure sends a bitstream from the microcontroller to the            *
* cryptocontroller.                                                           *
*                                                                             *
* Parameters:                                                                 *
*   addr:      address where the bitstream has been stored                    *
*   length:    number of bits to be send                                      *
* Return:                                                                     *
*   FALSE        in case that no error occured                                *
*   TRUE         in case of an error                                          *
*                                                                             *
******************************************************************************/
{
   unsigned char bit_mask;

   bit_mask=0x80;
   do
   {
      if (wait_copro()) return TRUE;              /* wait for /READY = LOW  */

      CDATA = (bit)( *addr & bit_mask ); 
                                 /* store data bit at the address of Mem_Addr */

      CCLK = 1;                  /* generate low-to-high transition at CCLK  */
                                 /* lets cryptocontroller set /Ready to High */
      delay_copro (5);           /* wait some time, see specification        */
      CCLK = 0;                  /* high-to-low transition at CCLK           */


      bit_mask>>=1;              /* advance to next bit in current byte      */ 
      if( !bit_mask )            /* switch to next byte if 8 bits have       */
      {                          /* already been stored                      */
         addr++;                 /* switch to next byte to store             */
         bit_mask=0x80;          /* and reset bit mask                       */
      }

   } while( --length );

   return FALSE;
}






unsigned char receive_copro( unsigned char idata * addr, unsigned char length )
/******************************************************************************
*                                                                             *
* Description:                                                                *
* This procedure receives a bitstream from the the cryptocontroller.          *
*                                                                             *
* Parameters:                                                                 *
*   addr:      memory address where the received data have to be stored       *
*   length:    number of bits to be read                                      *      
* Return:                                                                     *
*   FALSE         in case that no error occured                               *
*   TRUE          in case of an error                                         *
*                                                                             *
******************************************************************************/
{
   unsigned char bit_mask;

   CDATA = 1;                     /* switch I/O  port to input  */

   bit_mask=0x80;
   do
   {
      if (wait_copro()) return TRUE;          /* wait for /READY = LOW */

      if(bit_mask == 0x80) *addr = 0;  /* initialize next byte               */
      if (CDATA) *addr |= bit_mask;

      CCLK = 1;                   /* generate low-to-high transition at CCLK */
      delay_copro (5);            /* wait some time, see specification       */
      CCLK = 0;                  

      bit_mask>>=1;               /* advance to next bit in current byte     */ 
      if( !bit_mask )             /* switch to next byte if 8 bits have      */
      {                           /* already been stored                     */
         addr++;                  /* switch to next byte to store            */
         bit_mask=0x80;           /* and reset bit mask                      */
      }
   } while( --length );

   return FALSE;
}




void init_copro (void)
/******************************************************************************
*                                                                             *
* Description:                                                                *     
* This procedure is being called before sending a command to the HTRC120      *
* Afterwards the cryptoprocessor expects the next byte to be a valid command. *
*                                                                             *
* Parameters: none                                                            *
* Return:     none                                                            *
*                                                                             *                  
******************************************************************************/
{
   CRST = 0;                        

   CRST = 1;                      /* reset the cryptoprocessor               */
   delay_copro (10);                 

   SLEEP = 0;                     /* wake copro up                           */
   CCLK = 0;                      /* set CCLK to low (initial state)         */
                                  
   CRST = 0;                      /* end reset                               */
}


unsigned char wait_copro (void)
/******************************************************************************
*                                                                             *
* Description:                                                                *
* This procedure waits for /READY = LOW. It should not be called when \READY  *
* is already LOW. Minimum waiting time is 50 ms (16 MHz clock) and maximum    *
* 100 ms (8 MHz clock frequency)                                              *
*                                                                             *
* Parameters: none                                                            *
* Return:     none                                                            *
*                                                                             *
******************************************************************************/
{                                                
   unsigned short busy1 = 6666;  /* equivalent to 50ms at 16MHz */

   while (READY == 1)  /*check whether /READY is HIGH */
   {
      busy1--;
      if(!busy1)       /* 50..100 ms elapsed, generate error */
      {
        return TRUE;
      }
   }

   return FALSE;
}



void sleep_copro (void)
/******************************************************************************
*                                                                             *
* Description:                                                                *
* This procedure puts the cryptoprocessor into the SLEEP-modee                *
*                                                                             *
* Parameters: none                                                            *
* Return:     none                                                            *
*                                                                             *
******************************************************************************/
{                                                
   CCLK  = 1;
   CCLK  = 0;
   SLEEP = 1;                     /* put copro to SLEEP-state                */
}


void delay_copro (unsigned char cycles)
/******************************************************************************
*                                                                             *
* Description:                                                                *
* This function is intended to provide some delay time for the co-processor as*
* demanded in the specificatio. It was intended to avoid a                    *
* superfluous use of an extra timer.                                          *
*                                                                             *
* Parameters:                                                                 *
* cycles  : number of waiting loops (equivalent to a time interval)           *
*                                                                             *
* Return:    none                                                             *
*                                                                             *
******************************************************************************/
{
   while (cycles > 0) cycles --;
}
  





unsigned char Crypt_Set_Ident( unsigned char idata * addr )
/********************************************************************************
*                                                                               *
* Description:                                                                  *
* This procedure sends the transponder identifier the co-processor.             *
*                                                                               *
* Parameters:                                                                   *
*   addr:      memory address where the identifier is stored                    *
* Return:                                                                       *
*   FALSE         in case that no error occured                                 *
*   TRUE          in case of an error                                           *
*                                                                               *
********************************************************************************/
{
   unsigned char temp;

   init_copro();

#ifdef ENABLE_PWD_CHECK
   temp = CMD_START_AUTHENT_PWCHECK; /* command start_authent with passw.check */
#else
   temp = CMD_START_AUTHENT;         /* command start_authent without pw.check */
#endif

   if (send_copro( (unsigned char idata *) &temp, 8 ))       /* send command */
      return TRUE;

   if (send_copro( addr, 32 ))                 /* send identifier to HTRC120 */
      return TRUE;

   return FALSE;
}




unsigned char Crypt_Get_Rand_RWDPass( unsigned char idata * addr )
/********************************************************************************
*                                                                               *
* Description:                                                                  *     
* This routine reads  the random number and the encrypted RWD-password from     *
* the HTRC120.                                                                  *
*                                                                               *
* Parameters:                                                                   *
*   addr:      memory address where the data shall be stored                    *
* Return:                                                                       *
*   FALSE         in case that no error occured                                 *
*   TRUE          in case of an error                                           *
*                                                                               *                  
********************************************************************************/
{
   if (receive_copro ( addr, 64 )) return TRUE;

   return FALSE;
}


unsigned char Crypt_Decipher_HT2Pass( unsigned char idata * addr )
/********************************************************************************
*                                                                               *
* Description:                                                                  *
* This routine transmits the encrypted transponder password to the HTRC120.     *
* Depending on the definition of the pre-processor constant "ENABLE_PWD_CHECK"  *
* the decrypted configuration Byte/page 3 is received.                          *
*                                                                               *
* Parameters:                                                                   *
*   addr:      memory address where the enciphered transponder password is      *
*              stored and where the deciphered page3/coniguration Byte shall    *
*              be stored                                                        *
* Return:                                                                       *
*   FALSE         in case that no error occured                                 *
*   TRUE          in case of an error                                           *
*                                                                               *
********************************************************************************/
{
   if (send_copro ( addr, 32 ))          /* transmit enciphered HT2 password */
      return TRUE;

#ifdef ENABLE_PWD_CHECK
   if (receive_copro ( addr, 8 ))        /* receive response from HTRC120  */
      return TRUE;
#else
   if (receive_copro ( addr, 32 ))       /* receive deciphered HT2 password  */
      return TRUE;
#endif

   return FALSE;
}


   
unsigned char Crypt_Block( unsigned char idata * addr, unsigned char length )
/********************************************************************************
*                                                                               *
* Description:                                                                  *
* This procedure reads a bit stream from the co-processor and XORs it           *
* with the data bits, the values are overwritten                                *
*                                                                               *
* Parameters:                                                                   *
* Return:                                                                       *
*   FALSE         in case that no error occured                                 *
*   TRUE          in case of an error                                           *
*                                                                               *
********************************************************************************/
{
   unsigned char bit_mask;

   CDATA = 1;                     /* switch I/O  port to input  */

   bit_mask=0x80;
   do
   {
      if (wait_copro()) return TRUE;       /*  wait for /READY = LOW          */

      if( CDATA ^ (bit)(*addr & bit_mask ) )  /* read cypherbit   */
         *addr |=  bit_mask;      /* from the copro and XOR it       */
      else                        /* immediatly with the databit     */
         *addr &= ~bit_mask;      /* to be en- or decyphered         */


      CCLK = 1;                   /* generate low-to-high transition at CCLK  */
      delay_copro (5);            /* wait some time, see specification        */
      CCLK = 0;                  

      bit_mask>>=1;               /* advance to next bit in current byte      */ 
      if( !bit_mask )             /* switch to next byte if 8 bits have       */
      {                           /* already been stored                      */
         addr++;                  /* switch to next byte to store             */
         bit_mask=0x80;           /* and reset bit mask                       */
      }
   } while( --length );

   return FALSE;
}

