//---------------------------------------------------------------------------
// Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY,  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES
// OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
// Except as contained in this notice, the name of Dallas Semiconductor
// shall not be used except as stated in the Dallas Semiconductor
// Branding Policy.
//---------------------------------------------------------------------------
//
//  initcopr.c - This utility initializes the SHA iButton
//              (DS1963S) as a coprocessor.
//
//  Version:   2.00
//  History:
//

#include "ownet.h"
#include "ibsha18.h"

// external function prototypes
extern int PrintHeader(char *);
extern void output_status(int, char *);
extern int GetSeviceProviderSettings(int,char *,uchar *,int,uchar *);
extern int WriteFileSHA(uchar *,uchar *,int,uchar *,TransState *);
extern void ExitProg(char *, int);
extern int  owAcquire(int,char *);
extern void owRelease(int);
extern int CreateAuthSecret(uchar *, TransState *);
extern int CreateMoneySecret(uchar *, TransState *);
extern int SelectCoProcessor(TransState *);
extern int FindSHA(uchar *, TransState *);
extern int getkeystroke(void);

// verbose output mode
int VERBOSE=0;
// file for output
FILE *fp;

//----------------------------------------------------------------------
//  This is the Main routine for initcopr
//
int main(int argc, char **argv)
{
   int filenum;
   char msg[200];
   uchar auth_secret[65],money_secret[65];
   int cnt,exit_code,i;
   uchar buf[6],flname[6],page_map[1];
   TransState ts;

   // check arguments to see if request instruction with '?' or too many
   if ((argc > 4) || (argc < 2) || ((argc > 1) && (argv[1][0] == '?' || argv[1][1] == '?')))
       ExitProg("\nusage: initcopr 1wire_net_name <output_filename> </Verbose>\n"
              "  - initialize a coprocessor SHA iButton on specified\n"
              "    1-Wire Net port\n"
              "  - 1wire_net_port - required port name\n"
              "    example: \"COM1\" (Win32 DS2480),\"/dev/cua0\" \n"
              "    (Linux DS2480),\"1\" (Win32 TMEX)\n"
              "  - <output_filename> optional output filename\n"
              "  - </V> optional show verbose output (default not shown)\n"
              "  - version 2.00\n",EXIT_ERROR);

   // attempt to acquire the 1-Wire Net
   ts.portnum[IB_ROVING] = 0;
   if (!owAcquire(ts.portnum[IB_ROVING],argv[1]))
   {
      OWERROR_DUMP(stdout);
      exit(1);
   }

   // hard code CO_PROCESSOR port to be the same
   ts.portnum[IB_COPR] = ts.portnum[IB_ROVING];

   // print the header info
   if (!PrintHeader("InitCoPr Version 2.00"))
      ExitProg("No driver found\n",EXIT_ERROR);

   // check arguments
   VERBOSE = FALSE;
   filenum = 0;
   if (argc >= 3)
   {
      if (argv[2][0] != '/')
         filenum = 2;
      else if ((argv[2][1] == 'V') || (argv[2][1] == 'v'))
         VERBOSE = TRUE;

      if (argc == 4)
      {
         if (argv[3][0] != '/')
            filenum = 3;
         else if ((argv[3][1] == 'V') || (argv[3][1] == 'v'))
            VERBOSE = TRUE;
      }
   }

   // open the output file
   fp = NULL;
   if (filenum > 0)
   {
      fp = fopen(argv[filenum],"wb");
      if(fp == NULL)
      {
         printf("ERROR, Could not open output file!\n");
         exit(EXIT_ERROR);
      }
      else
         printf("File '%s' opened to write data.\n\n",
                 argv[filenum]);
   }

   // set the default pages used for secrets (will be written to copr)
   ts.c_mmaster_scrt = 0;  // co-processor money master secret
   ts.c_amaster_scrt = 1;  // co-processor auth master secret
   ts.c_udevice_scrt = 2;  // co-processor unique device secret(calculated)
   ts.r_udevice_scrt = 5;  // roving unique device secret
   ts.t_udevice_scrt = 4;  // till unique device secret
   sprintf((char *)(&ts.copr_file[0]),"COPR");

   // prompt for service provider settings
   output_status(LV_ALWAYS,"Enter information to create the co-processor SHA"
                " iButton for a service\n");
   if (!GetSeviceProviderSettings(TRUE,(char*)ts.provider,auth_secret,TRUE, money_secret))
      ExitProg("Aborted entering the provider settings, end program\n",EXIT_ERROR);

   // create the data for the TMEX file
   sprintf((char*)flname,"%s",ts.copr_file);  // first 4 letters, service name
   sprintf((char *)buf,"%s",ts.provider);
   buf[4] = 102;                       // extension of SHA money file
   buf[5] = ts.c_mmaster_scrt;         // money master secret number
   buf[6] = ts.c_amaster_scrt;         // auth master secret number
   buf[7] = ts.c_udevice_scrt;         // unique device secret(calculated)
   page_map[0] = 1;                    // page map for only 1 file page

   // get warning
   output_status(LV_ALWAYS,"\n** Warning SHA iButton on 1-Wire will be overwritten!!\n  (Press ENTER to continue)\n");
   getkeystroke();

   // select co-processor port
   if (SelectCoProcessor(&ts))
   {
      output_status(LV_ALWAYS,"** 1-Wire port for co-processor selected\n");

      // find the first available SHA iButton
      if (FindSHA(&ts.copr_rom[0], &ts))
      {
         // loop to print ROM of device found
         cnt = sprintf(msg,"** SHA iButton found: ");
         for (i = 7; i >= 0; i--)
            cnt += sprintf(msg + cnt,"%02X",ts.copr_rom[i]);
         sprintf(msg + cnt,"\n");
         output_status(LV_ALWAYS,msg);

         // create the authentication secret
         if (CreateAuthSecret(&auth_secret[0], &ts))
         {
            output_status(LV_ALWAYS,"** Authenticate secret created\n");

            // create the money secret
            if (CreateMoneySecret(&money_secret[0], &ts))
            {
               output_status(LV_ALWAYS,"** Money secret created\n");
               // coprocessor is already current device
               if (WriteFileSHA(flname, buf, 8, page_map, &ts))
               {
                  output_status(LV_ALWAYS,"** Co-processor info file created\n");
                  exit_code = EXIT_SUCCESS;
               }
               else
               {
                  output_status(LV_ALWAYS,"ERROR, Could not write Co-processor info file\n");
                  exit_code = EXIT_ERROR_WRITE;
               }
            }
            else
            {
               output_status(LV_ALWAYS,"ERROR, Could not create money secret\n");
               exit_code = EXIT_ERROR_MONEY_SCRT;
            }
         }
         else
         {
            output_status(LV_ALWAYS,"ERROR, Could not create authorization secret\n");
            exit_code = EXIT_ERROR_AUTH_SCRT;
         }
      }
      else
      {
         output_status(LV_ALWAYS,"ERROR, Could not find a SHA iButton\n");
         exit_code = EXIT_ERROR_NO_SHA;
      }
   }
   else
   {
      output_status(LV_ALWAYS,"ERROR, Could not select co-processor 1-Wire\n");
      exit_code = EXIT_ERROR;
   }

   // release the 1-Wire Net
   owRelease(ts.portnum[IB_ROVING]);
   sprintf(msg,"Closing port %s.\n", argv[1]);
   output_status(LV_ALWAYS,msg);

   // close opened file
   if ((fp != NULL) && (fp != stdout))
   {
      printf("File '%s' closed.\n",
              argv[filenum]);
      fclose(fp);
   }

   // check on result of operation
   if (exit_code)
   {
      OWERROR_DUMP(stdout);
      printf("ERROR reported (%d), end program\n",exit_code);
   }
   else
      printf("End program normally\n");

   // end the program
   exit(exit_code);

   return exit_code;
}


