
/*---------------------------------------------------------------------------
 * Copyright (C) 1999,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.
 *---------------------------------------------------------------------------
 */

import com.dalsemi.onewire.adapter.*;
import com.dalsemi.onewire.container.*;
import com.dalsemi.onewire.*;
import java.util.*;
import java.io.*;


public class debit
{
   static char[] hex = "0123456789ABCDEF".toCharArray();

   /**
    * Method printUsageString
    *
    *
    */
   public static void printUsageString ()
   {
      System.out.println(
         "DS1963S SHA iButton Java Demo Transaction Program.\r\n");
      System.out.println("Usage: ");
      System.out.println("   java debit ADAPTER_PORT\r\n");
      System.out.println(
         "ADAPTER_PORT is a String that contains the name of the");
      System.out.println(
         "adapter you would like to use and the port you would like");
      System.out.println("to use, for example: ");
      System.out.println("   java debit {DS1410E}_LPT1");
      System.out.println(
         "You can leave ADAPTER_PORT blank to use the default one-wire adapter and port.");
   }

   /**
    * Method main
    *
    *
    * @param args
    *
    * @throws OneWireException
    * @throws OneWireIOException
    *
    */
   public static void main (String[] args)
      throws OneWireIOException, OneWireException
   {
      byte[]        ID         = new byte [8];
      byte[]        filebuffer = new byte [200];
      int           filelength;
      int           i;
      long[]        buttons      = new long [10];
      int           index        = 0;
      DSPortAdapter access       = null;
      long          coprocessor  = 0;
      SHAiButton    copr         = null;
      boolean       usedefault   = false;
      String        adapter_name = null;
      String        port_name    = null;

      if ((args == null) || (args.length < 1))
      {
         try
         {
            access = OneWireAccessProvider.getDefaultAdapter();

            if (access == null)
               throw new Exception();
         }
         catch (Exception e)
         {
            System.out.println("Couldn't get default adapter!");
            printUsageString();

            return;
         }

         usedefault = true;
      }

      if (!usedefault)
      {
         StringTokenizer st = new StringTokenizer(args [0], "_");

         if (st.countTokens() != 2)
         {
            printUsageString();

            return;
         }

         adapter_name = st.nextToken();
         port_name    = st.nextToken();

         System.out.println("Adapter Name: " + adapter_name);
         System.out.println("Port Name: " + port_name);
      }

      while (true)
      {
         try
         {
            if (access == null)
            {
               try
               {
                  access = OneWireAccessProvider.getAdapter(adapter_name,
                                                            port_name);
               }
               catch (Exception e)
               {
                  System.out.println(
                     "That is not a valid adapter/port combination.");

                  Enumeration en =
                     OneWireAccessProvider.enumerateAllAdapters();

                  while (en.hasMoreElements())
                  {
                     DSPortAdapter temp = ( DSPortAdapter ) en.nextElement();

                     System.out.println("Adapter: " + temp.getAdapterName());

                     Enumeration f = temp.getPortNames();

                     while (f.hasMoreElements())
                     {
                        System.out.println("   Port name : "
                                           + (( String ) f.nextElement()));
                     }
                  }

                  return;
               }
            }

            access.adapterDetected();
            access.targetFamily(0x18);
            access.beginExclusive(true);
            access.reset();
            access.setSearchAllDevices();

            boolean next = access.findFirstDevice();

            //first we need to find a coprocessor
            if (copr == null)
               while (next)
               {
                  access.getAddress(ID);

                  OneWireContainer18 ds1963S =
                     ( OneWireContainer18 ) access.getDeviceContainer(ID);

                  ds1963S.setupContainer(access, ID);
                  ds1963S.setSpeedCheck(false);

                  SHAiButton sha = new SHAiButton(ds1963S);

                  filelength = sha.readFile(0, filebuffer);

                  //look for file COPR.000
                  byte[] file     = "COPR".getBytes();
                  int    filepage = -1;

                  buttons [index] = access.getAddressAsLong();

                  index++;

                  for (i = 0; i < filelength; i++)
                  {
                     if (filebuffer [i] == file [0])
                        if (filebuffer [i + 1] == file [1])
                           if (filebuffer [i + 2] == file [2])
                              if (filebuffer [i + 3] == file [3])
                                 if (filebuffer [i + 4] == ( byte ) 0)   //000 is the extension
                                    filepage = filebuffer [i + 5];
                  }

                  if (filepage == -1)
                  {
                     System.out.println("Couldnt find the file page!!!");
                  }
                  else
                  {
                     filelength = sha.readFile(filepage, filebuffer);

                     try
                     {
                        sha.setFilename(filebuffer, 0);
                        sha.setSigningPageNumber(filebuffer [5]);
                        sha.setAuthenticationPageNumber(filebuffer [6]);
                        sha.setWorkspacePageNumber(filebuffer [7]);

                        if (filelength >= 45)
                           sha.setBindData(filebuffer, 13);

                        if (filelength >= 52)
                           sha.setBindCode(filebuffer, 45);
                     }
                     catch (Exception e)
                     {
                        System.out.println("Exception getting all that data");
                     }

                     if (sha.isCoprocessor())
                     {
                        coprocessor = ds1963S.getAddressAsLong();
                        copr        = sha;

                        System.out.println(
                           "Found a coprocessor for service \""
                           + sha.getUserFileName() + "\"");

                        index--;   //take the coprocessor out of the list
                     }
                  }

                  next = access.findNextDevice();
               }                   //end while next

            System.out.println("Adapter address: "
                               + access.getAdapterAddress());
            access.targetFamily(0x18);

            if (copr == null)
            {
               System.out.println("Coprocessor is NULL!");

               return;   //exit
            }

            int                currentindex = 0;
            long[]             temp         = new long [10];
            long[]             swap;
            OneWireContainer18 owc = new OneWireContainer18();

            owc.setSpeedCheck(false);

            byte[] file     = copr.getUserFileName().getBytes();
            byte   ext      = ( byte ) copr.getUserFileExtension();
            int    amount   = -50;
            byte[] pagedata = new byte [32];

            //index now holds how many buttons are in our 'vector'
            try
            {
               while (true)
               {
                  currentindex = 0;
                  next         = access.findFirstDevice();

                  while (next)
                  {

                     //poll and check for new buttons
                     long t = access.getAddressAsLong();

                     if (t != coprocessor)
                     {
                        temp [currentindex++] = t;

                        for (i = 0; i < index; i++)
                        {
                           if (buttons [i] == t)   //it has been here all along
                           {
                              t = -1;

                              index--;

                              buttons [i] = buttons [index];
                              i           = index;
                           }
                        }

                        if (t != -1)   //it is a new button
                        {

                           //new button so we need to do a transaction
                           System.out.println("New iButton Inserted: "
                                              + Long.toHexString(t));

                           boolean success = false;
                           long    t1      = System.currentTimeMillis();

                           access.reset();
                           access.putByte(0x3c);
                           access.setSpeed(access.SPEED_OVERDRIVE);

                           /*int x =*/
                           access.reset();

                           //System.out.println("X is "+x);
                           access.getAddress(ID);
                           owc.setupContainer(access, ID);

                           SHAiButton user = new SHAiButton(owc);

                           //now we need to find the file installed!
                           filelength = user.readFile(0, filebuffer);

                           int filepage = -1;

                           for (i = 0; i < filelength; i++)
                           {
                              if (filebuffer [i] == file [0])
                                 if (filebuffer [i + 1] == file [1])
                                    if (filebuffer [i + 2] == file [2])
                                       if (filebuffer [i + 3] == file [3])
                                          if (filebuffer [i + 4] == ext)
                                             filepage = filebuffer [i + 5];
                           }

                           if (filepage == -1)
                           {
                              System.out.println("No service installed!");
                           }
                           else
                           {
                              user.setUser(filepage);

                              int wcc = copr.verifyAuthentication(user,
                                                                  pagedata);

                              if (wcc > 0)
                              {
                                 if (copr.verifyUserMoney(pagedata, user,
                                                          wcc))
                                 {
                                    int cash = (pagedata [5] & 0x0ff)
                                               | ((pagedata [6] & 0x0ff) << 8)
                                               | ((pagedata [7] & 0x0ff)
                                                  << 16);

                                    if (cash + amount >= 0)
                                    {
                                       if (copr.signDataFile(user,
                                                             cash + amount,
                                                             wcc, pagedata))
                                       {
                                          long t2      =
                                             System.currentTimeMillis();
                                          int  newcash = cash + amount;

                                          System.out.println(
                                             "** Coprocessor SHA iButton: "
                                             + Long.toHexString(coprocessor));
                                          System.out.println(
                                             "** Provider file: "
                                             + copr.getUserFileName() + "."
                                             + copr.getUserFileExtension());
                                          System.out.println();
                                          System.out.println(
                                             "-----------------------");
                                          System.out.println(
                                             "| Device  : "
                                             + Long.toHexString(t));
                                          System.out.println("| Balance : $ "
                                                             + (newcash / 100)
                                                             + "."
                                                             + (newcash % 100)
                                                             + " US");
                                          System.out.println(
                                             "| Transaction time : "
                                             + (t2 - t1) + " ms");
                                          System.out.println(
                                             "-----------------------");
                                          System.out.println();

                                          success = true;
                                       }
                                    }
                                 }
                              }

                              if (!success)
                                 switch (copr.getLastError())
                                 {

                                    case SHAiButton.NO_ERROR :
                                       System.out.println("Transaction OK");
                                       break;
                                    case SHAiButton.AUTHENTICATION_FAILED_ERROR :
                                       System.out.println(
                                          "Authentication failed: You don't belong to the system");
                                       break;
                                    case SHAiButton.VERIFICATION_FAILED_ERROR :
                                       System.out.println(
                                          "Verification failed: Your money is no good");
                                       break;
                                    default :
                                       System.out.println(
                                          "Error occured "
                                          + copr.getLastError());
                                       System.out.println(
                                          "Transaction not completed, please try again");
                                       break;
                                 }
                           }

                           access.setSpeed(access.SPEED_REGULAR);
                           access.reset();
                        }
                     }

                     next = access.findNextDevice();
                  }

                  swap    = buttons;
                  buttons = temp;
                  temp    = swap;
                  index   = currentindex;
               }
            }
            catch (Exception e)
            {
               System.out.println("Outer loop exception: " + e.toString());
            }
            access.endExclusive();
         }
         catch (OneWireIOException owio)
         {
            System.out.println("OnewireIOException caught: " + owio);
         }
         catch (OneWireException ibe)
         {
            System.out.println("OneWireException caught: " + ibe);
         }
         catch (Exception e)
         {
            System.out.println("General exception caught!!!" + e.toString());
         }
      }   //end while true
   }

   static String printOutHash (byte[] A)
   {
      StringBuffer sb = new StringBuffer();

      for (int i = (A.length == 20 ? 0
                                   : 8); i < (A.length == 20 ? 20
                                                             : 28); i++)
      {
         sb.append(hex [(A [i] >> 4) & 0x0f]);
         sb.append(hex [(A [i]) & 0x0f]);
         sb.append('.');
      }

      return sb.toString();
   }

   static void printOutTheArray (byte[] A)
   {
      StringBuffer sb = new StringBuffer();

      for (int i = 0; i < A.length; i++)
      {
         if ((i & 31) == 0)
            sb.append("\r\n");

         sb.append(hex [(A [i] >> 4) & 0x0f]);
         sb.append(hex [(A [i]) & 0x0f]);
         sb.append('.');
      }

      System.out.println(sb);
   }
}
