/// <summary>
        /// <P>Reads the account data off the SHAiButton using a standard READ
        /// command.  First, this function asserts that the account page number is
        /// known as well as the length of the account file.  The 32 byte account
        /// data page is copied into dataBuffer starting at the given offset.</P>
        /// </summary>
        /// <param name="dataBuffer"> the buffer to copy the account data into </param>
        /// <param name="offset"> the index into the buffer where copying should begin </param>
        /// <returns> whether or not the read was successful </returns>
        public override bool readAccountData(byte[] dataBuffer, int offset)
        {
            lock (this)
            {
                //init local vars
                OneWireContainer33 ibcL = this.ibc33;

                //make sure account info is properly setup
                if (!checkAccountPageInfo(ibcL))
                {
                    return(false);
                }

                //if the cache is empty
                if (this.accountData[0] == 0)
                {
                    //read directly into local cache
                    ibcL.readMemoryPage(this.accountPageNumber, this.accountData, 0);
                }

                //copy from cache into output buffer
                Array.Copy(this.accountData, 0, dataBuffer, offset, 32);

                //had to work, right?
                return(true);
            }
        }
        /// <summary>
        /// <P>Initialize a DS1961S as a fresh user iButton for a given SHA service.
        /// This constructor not only creates the service file for the user iButton
        /// using the TMEX file structure, but it also installs the master
        /// authentication secret and binds it to the iButton (making it unique for
        /// a particular button).  Optionally, the device can be formatted before
        /// the service file is installed.</P>
        ///
        /// <P>Note: With this constructor, the master secret is installed and bound
        /// to the iButton, so the final secret is none by the object.  For that
        /// reason, a hardware coprocessor is not necessary for generating the
        /// write-authorization MAC.</P>
        /// </summary>
        /// <param name="copr"> The SHAiButtonCopr to which the user object is tied.  This
        ///        Coprocessor contains the necessary binding code and service
        ///        filename, necessary for both locating a user and recreating his
        ///        unique secret. </param>
        /// <param name="owc"> The DS1963S iButton that this object will refer to. </param>
        /// <param name="formatDevice"> If <code>true</code>, the TMEX filesystem will be
        ///        formatted before the account service file is created. </param>
        /// <param name="authSecret"> The master authentication secret for the systm.
        /// </param>
        /// <exception cref="OneWireIOException"> on a 1-Wire communication error such as
        ///         reading an incorrect CRC from a 1-Wire device.  This could be
        ///         caused by a physical interruption in the 1-Wire Network due to
        ///         shorts or a newly arriving 1-Wire device issuing a 'presence pulse'. </exception>
        /// <exception cref="OneWireException"> on a communication or setup error with the 1-Wire
        ///         adapter
        /// </exception>
        /// <seealso cref= #SHAiButtonUser33(SHAiButtonCopr,SHAiButtonCopr,OneWireContainer33) </seealso>
        /// <seealso cref= #SHAiButtonUser33(SHAiButtonCopr,SHAiButtonCopr) </seealso>
        public SHAiButtonUser33(SHAiButtonCopr copr, OneWireContainer33 owc, bool formatDevice, byte[] authSecret) : this(copr, copr)
        {
            //setup service filename

            //hold container reference
            this.ibc33 = owc;

            //and address
            this.address = owc.Address;

            //clear out old secret first
            byte[] NullSecret = new byte[8];
            for (int i = 0; i < 8; i++)
            {
                NullSecret[i] = 0x00;
            }

            if (!this.ibc33.loadFirstSecret(NullSecret, 0))
            {
                throw new OneWireException("Failed to null out device secret.");
            }

            if (!owc.installMasterSecret(0, authSecret))
            {
                throw new OneWireException("Install Master Secret failed");
            }

            if (!createServiceFile(owc, strServiceFilename, formatDevice))
            {
                throw new OneWireException("Failed to create service file.");
            }

            //setup the fullBindCode with rest of info
            this.fullBindCode[4] = (byte)this.accountPageNumber;
            Array.Copy(this.address, 0, this.fullBindCode, 5, 7);

            if (!owc.bindSecretToiButton(this.accountPageNumber, copr.BindData))
            {
                throw new OneWireException("Bind Secret to iButton failed");
            }

            //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
            if (DEBUG)
            {
                IOHelper.writeLine("------------------------------------");
                IOHelper.writeLine("Initialized DS1961S User");
                IOHelper.writeLine("address");
                IOHelper.writeBytesHex(owc.Address);
                IOHelper.writeLine("serviceFilename: " + strServiceFilename);
                IOHelper.writeLine("accountPageNumber: " + accountPageNumber);
                IOHelper.writeLine("authSecret");
                IOHelper.writeBytesHex(authSecret);
                IOHelper.writeLine("bindData");
                IOHelper.writeBytesHex(copr.bindData);
                IOHelper.writeLine("bindCode");
                IOHelper.writeBytesHex(copr.bindCode);
                IOHelper.writeLine("------------------------------------");
            }
            //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
        }
        /// <summary>
        /// <P>Creates a valid SHAiButtonUser object.  If the service file,
        /// whose name is taken from the <code>SHAiButtonCopr</code>, is not
        /// found on the user iButton, a OneWireException is thrown with the
        /// message "Invalid SHA user".</P>
        ///
        /// <P>Note: The same coprocessor can be used for write-authorization as
        /// authentication if you're transaction system is using unsigned transaction
        /// data.</P>
        /// </summary>
        /// <param name="copr"> The SHAiButtonCopr to which the user object is tied.  This
        ///        Coprocessor contains the necessary binding code and service
        ///        filename, necessary for both locating a user and recreating his
        ///        unique secret. </param>
        /// <param name="authCopr"> The SHAiButtonCopr used to generate the write-authorization
        ///        MAC for the copy-scratchpad command of the DS1961S. </param>
        /// <param name="owc"> The DS1961S iButton that this object will refer to.
        /// </param>
        /// <exception cref="OneWireIOException"> on a 1-Wire communication error such as
        ///         reading an incorrect CRC from a 1-Wire device.  This could be
        ///         caused by a physical interruption in the 1-Wire Network due to
        ///         shorts or a newly arriving 1-Wire device issuing a 'presence pulse'. </exception>
        /// <exception cref="OneWireException"> on a communication or setup error with the 1-Wire
        ///         adapter
        /// </exception>
        /// <seealso cref= #SHAiButtonUser33(SHAiButtonCopr,OneWireContainer33,bool,byte[]) </seealso>
        /// <seealso cref= #SHAiButtonUser33(SHAiButtonCopr,SHAiButtonCopr) </seealso>
        public SHAiButtonUser33(SHAiButtonCopr copr, SHAiButtonCopr authCopr, OneWireContainer33 owc) : this(copr, authCopr)
        {
            //setup service filename

            //hold container reference and address
            if (!setiButton33(owc))
            {
                throw new OneWireException("Invalid SHA user");
            }
        }
 /// <summary>
 /// <P>Modifies this SHA iButton so that it refers to another 1963S.
 /// If this object already has an appropriate instance of OneWireContainer,
 /// that instance is updated with the new address.</P>
 /// </summary>
 /// <param name="adapter"> The adapter that the device can be found on. </param>
 /// <param name="address"> The address of the 1-Wire device
 /// </param>
 /// <returns> <code>true</code> if a valid account service file exists on
 ///         this <code>OneWireContainer18</code>.
 /// </returns>
 /// <exception cref="OneWireIOException"> on a 1-Wire communication error such as
 ///         reading an incorrect CRC from a 1-Wire device.  This could be
 ///         caused by a physical interruption in the 1-Wire Network due to
 ///         shorts or a newly arriving 1-Wire device issuing a 'presence pulse'. </exception>
 /// <exception cref="OneWireException"> on a communication or setup error with the 1-Wire
 ///         adapter </exception>
 public override bool setiButtonUser(DSPortAdapter adapter, byte[] address)
 {
     lock (this)
     {
         if (this.ibc33 == null)
         {
             this.ibc33 = new OneWireContainer33();
         }
         this.ibc33.setupContainer(adapter, address);
         return(setiButton33(this.ibc33));
     }
 }
Exemple #5
0
        /// <summary> Memory bank constructor.  Requires reference to the OneWireContainer
        /// this memory bank resides on.
        /// </summary>
        public MemoryBankSHAEE(OneWireContainer33 ibutton, MemoryBankScratchSHAEE scratch)
        {
            // keep reference to ibutton where memory bank is
            ib = ibutton;

            scratchpad = scratch;

            // keep reference to adapter that button is on
            adapter = ib.Adapter;

            // indicate speed has not been set
            doSetSpeed = true;
        }
        /// <summary>
        /// <P>Reads the account data off the SHAiButton using a READ_AUTHENTICATE
        /// command.  First, this function asserts that the account page number is
        /// known as well as the length of the account file.  Then it copies the
        /// 3 byte challenge to the scratchpad before sending the command for
        /// READ_AUTHENTICATE.  The 32 byte account data page is copied into
        /// dataBuffer starting at dataStart.</P>
        ///
        /// <P>In addition to the account data, this function also returns a
        /// calculated MAC.  The MAC requires 20 bytes after the start index.
        /// The return value is the write cycle counter value for the account
        /// data page<para>
        ///
        /// </para>
        /// </summary>
        /// <param name="chlg"> the buffer containing a 3-byte random challenge. </param>
        /// <param name="chlgStart"> the index into the buffer where the 3 byte
        ///        challenge begins. </param>
        /// <param name="dataBuffer"> the buffer to copy the account data into </param>
        /// <param name="dataStart"> the index into the buffer where copying should begin </param>
        /// <param name="mac"> the buffer to copy the resulting Message Authentication Code </param>
        /// <param name="macStart"> the index into the mac buffer to start copying
        /// </param>
        /// <returns> the value of the write cycle counter for the page </returns>
        public override int readAccountData(byte[] chlg, int chlgStart, byte[] dataBuffer, int dataStart, byte[] mac, int macStart)
        {
            lock (this)
            {
                //init local variables
                OneWireContainer33 ibcL = this.ibc33;

                //make sure account info is properly setup
                if (this.accountPageNumber < 0)
                {
                    //user not setup
                    throw new OneWireException("SHAiButtonUser Not Properly Initialized");
                }

                //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
                if (DEBUG)
                {
                    // for debug, lets use a constant challenge
                    chlg[0] = 0x00;
                    chlg[1] = 0x00;
                    chlg[2] = 0x00;
                }
                //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\

                //container keeps challenge as a member of the class
                ibcL.setChallenge(chlg, chlgStart);

                //performs the read authenticated page, to answer the challenge
                if (ibcL.readAuthenticatedPage(this.accountPageNumber, dataBuffer, dataStart, mac, macStart))
                {
                    //copy from outputbuffer into cache
                    Array.Copy(dataBuffer, dataStart, this.accountData, 0, 32);

                    //has no write cycle counter
                    return(-1);
                }
                else
                {
                    throw new OneWireException("SHAiButtonUser ReadAuthenticatedPage Failed");
                }
            }
        }
        /// <summary>
        /// <P>Modifies this SHA iButton so that it refers to another DS1961S
        /// container.  This function only copies the reference to the
        /// OneWireContainer, copes the reference to it's 1-Wire address, and
        /// then asserts that the iButton contains a valid acccount info file
        /// associated with the system.</P>
        /// </summary>
        /// <param name="owc"> The <code>OneWireContainer33</code> this object will refer to.
        /// </param>
        /// <returns> <code>true</code> if a valid account service file exists on
        ///         this <code>OneWireContainer33</code>.
        /// </returns>
        /// <exception cref="OneWireIOException"> on a 1-Wire communication error such as
        ///         reading an incorrect CRC from a 1-Wire device.  This could be
        ///         caused by a physical interruption in the 1-Wire Network due to
        ///         shorts or a newly arriving 1-Wire device issuing a 'presence pulse'. </exception>
        /// <exception cref="OneWireException"> on a communication or setup error with the 1-Wire
        ///         adapter </exception>
        public virtual bool setiButton33(OneWireContainer33 owc)
        {
            lock (this)
            {
                //hold container reference
                this.ibc33 = owc;

                //and address
                this.address = owc.Address;

                //clear account information
                this.accountPageNumber = -1;

                //make sure account info is properly setup
                if (!checkAccountPageInfo(owc))
                {
                    return(false);
                }

                //setup the fullBindCode with rest of info
                this.fullBindCode[4] = (byte)this.accountPageNumber;
                Array.Copy(this.address, 0, this.fullBindCode, 5, 7);

                //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
                if (DEBUG)
                {
                    IOHelper.writeLine("------------------------------------");
                    IOHelper.writeLine("Loaded DS1961S User");
                    IOHelper.writeLine("address");
                    IOHelper.writeBytesHex(owc.Address);
                    IOHelper.writeLine("accountPageNumber: " + accountPageNumber);
                    IOHelper.writeLine("serviceFilename: " + strServiceFilename);
                    IOHelper.writeLine("------------------------------------");
                }
                //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\

                return(true);
            }
        }
    /// <summary>
    /// Method main
    ///
    /// </summary>
    /// <param name="args">
    /// </param>
    /// <exception cref="OneWireException"> </exception>
    /// <exception cref="OneWireIOException">
    ///  </exception>
    public static void Main3(string[] args)
    {
        //coprocessor
        long coprID = 0;

        // attempt to open the sha.properties file
        sha_properties = new Properties();
        if (!sha_properties.loadLocalFile("sha.properties"))
        {
            Debug.WriteLine("loading default sha.properties!");
            Assembly asm = typeof(SHADebitDemo.MainPage).GetTypeInfo().Assembly;
            sha_properties.loadResourceFile(asm, "SHADebitDemo.sha.properties");
        }

        // ------------------------------------------------------------
        // Instantiate coprocessor containers
        // ------------------------------------------------------------
        SHAiButtonCopr     copr   = null;
        OneWireContainer18 copr18 = new OneWireContainer18();

        copr18.setSpeed(DSPortAdapter.SPEED_REGULAR, false);
        copr18.SpeedCheck = false;

        // ------------------------------------------------------------
        // Setup the adapter for the coprocessor
        // ------------------------------------------------------------
        DSPortAdapter coprAdapter = null;
        string        coprAdapterName = null, coprPort = null;

        try
        {
            coprAdapterName = sha_properties.getProperty("copr.adapter", "{DS9097U}");
            coprPort        = sha_properties.getProperty("copr.port", "COM1");

            if (string.ReferenceEquals(coprPort, null) || string.ReferenceEquals(coprAdapterName, null))
            {
                coprAdapter = OneWireAccessProvider.DefaultAdapter;
            }
            else
            {
                coprAdapter = OneWireAccessProvider.getAdapter(coprAdapterName, coprPort);
            }

            IOHelper.writeLine("Coprocessor adapter loaded, adapter: " + coprAdapter.AdapterName + " port: " + coprAdapter.PortName);

            coprAdapter.adapterDetected();
            coprAdapter.targetFamily(0x18);
            coprAdapter.beginExclusive(true);
            coprAdapter.setSearchAllDevices();
            coprAdapter.reset();
        }
        catch (Exception e)
        {
            IOHelper.writeLine("Error initializing coprocessor adapter");
            Debug.WriteLine(e.ToString());
            Debug.Write(e.StackTrace);
            return;
        }

        // ------------------------------------------------------------
        // Find the coprocessor
        // ------------------------------------------------------------
        if (sha_properties.getPropertyBoolean("copr.simulated.isSimulated", false))
        {
            string coprVMfilename = sha_properties.getProperty("copr.simulated.filename");
            // ---------------------------------------------------------
            // Load emulated coprocessor
            // ---------------------------------------------------------
            try
            {
                copr = new SHAiButtonCoprVM(coprVMfilename);
            }
            catch (Exception e)
            {
                IOHelper.writeLine("Invalid Coprocessor Data File");
                Debug.WriteLine(e.ToString());
                Debug.Write(e.StackTrace);
                return;
            }
        }
        else
        {
            // ---------------------------------------------------------
            // Get the name of the coprocessor service file
            // ---------------------------------------------------------
            string filename = sha_properties.getProperty("copr.filename", "COPR.0");

            // ---------------------------------------------------------
            // Check for hardcoded coprocessor address
            // ---------------------------------------------------------
            byte[] coprAddress = sha_properties.getPropertyBytes("copr.address", null);
            long   lookupID    = 0;
            if (coprAddress != null)
            {
                lookupID = Address.toLong(coprAddress);

                IOHelper.write("Looking for coprocessor: ");
                IOHelper.writeLineHex(lookupID);
            }

            // ---------------------------------------------------------
            // Find hardware coprocessor
            // ---------------------------------------------------------
            try
            {
                bool next = coprAdapter.findFirstDevice();
                while (copr == null && next)
                {
                    try
                    {
                        long tmpCoprID = coprAdapter.AddressAsLong;
                        if (coprAddress == null || tmpCoprID == lookupID)
                        {
                            IOHelper.write("Loading coprocessor file: " + filename + " from device: ");
                            IOHelper.writeLineHex(tmpCoprID);

                            copr18.setupContainer(coprAdapter, tmpCoprID);
                            copr = new SHAiButtonCopr(copr18, filename);

                            //save coprocessor ID
                            coprID = tmpCoprID;
                        }
                    }
                    catch (Exception e)
                    {
                        IOHelper.writeLine(e);
                    }

                    next = coprAdapter.findNextDevice();
                }
            }
            catch (Exception)
            {
                ;
            }
        }

        if (copr == null)
        {
            IOHelper.writeLine("No Coprocessor found!");
            return;
        }

        IOHelper.writeLine(copr);
        IOHelper.writeLine();


        // ------------------------------------------------------------
        // Create the SHADebit transaction types
        // ------------------------------------------------------------
        //stores DS1963S transaction data
        SHATransaction trans     = null;
        string         transType = sha_properties.getProperty("ds1961s.transaction.type", "Signed");

        if (transType.ToLower().IndexOf("unsigned", StringComparison.Ordinal) >= 0)
        {
            trans = new SHADebitUnsigned(copr, 10000, 50);
        }
        else
        {
            trans = new SHADebit(copr, 10000, 50);
        }

        // ------------------------------------------------------------
        // Create the User Buttons objects
        // ------------------------------------------------------------
        //holds DS1963S user buttons
        OneWireContainer33 owc33 = new OneWireContainer33();

        owc33.setSpeed(DSPortAdapter.SPEED_REGULAR, false);
        //owc33.setSpeedCheck(false);

        // ------------------------------------------------------------
        // Get the adapter for the user
        // ------------------------------------------------------------
        DSPortAdapter adapter = null;
        string        userAdapterName = null, userPort = null;

        try
        {
            userAdapterName = sha_properties.getProperty("user.adapter", "{DS9097U}");
            userPort        = sha_properties.getProperty("user.port", "COM9");

            if (string.ReferenceEquals(userPort, null) || string.ReferenceEquals(userAdapterName, null))
            {
                if (!string.ReferenceEquals(coprAdapterName, null) && !string.ReferenceEquals(coprPort, null))
                {
                    adapter = OneWireAccessProvider.DefaultAdapter;
                }
                else
                {
                    adapter = coprAdapter;
                }
            }
            else if (userAdapterName.Equals(coprAdapterName) && userPort.Equals(coprPort))
            {
                adapter = coprAdapter;
            }
            else
            {
                adapter = OneWireAccessProvider.getAdapter(userAdapterName, userPort);
            }

            IOHelper.writeLine("User adapter loaded, adapter: " + adapter.AdapterName + " port: " + adapter.PortName);

            byte[] families = new byte[] { 0x33, unchecked ((byte)0xB3) };

            adapter.adapterDetected();
            adapter.targetFamily(families);
            adapter.beginExclusive(false);
            adapter.setSearchAllDevices();
            adapter.reset();
        }
        catch (Exception e)
        {
            IOHelper.writeLine("Error initializing user adapter.");
            Debug.WriteLine(e.ToString());
            Debug.Write(e.StackTrace);
            return;
        }

        // ---------------------------------------------------------------
        // Search for the button
        // ---------------------------------------------------------------
        try
        {
            long tmpID = -1;
            bool next  = adapter.findFirstDevice();
            for (; tmpID == -1 && next; next = adapter.findNextDevice())
            {
                tmpID = adapter.AddressAsLong;
                if (tmpID == coprID)
                {
                    tmpID = -1;
                }
                else
                {
                    owc33.setupContainer(adapter, tmpID);
                }
            }

            if (tmpID == -1)
            {
                IOHelper.writeLine("No buttons found!");
                return;
            }
        }
        catch (Exception)
        {
            IOHelper.writeLine("Adapter error while searching.");
            return;
        }

        IOHelper.write("Setting up user button: ");
        IOHelper.writeBytesHex(owc33.Address);
        IOHelper.writeLine();

        IOHelper.writeLine("How would you like to enter the authentication secret (unlimited bytes)? ");
        byte[] auth_secret = getBytes(0);
        IOHelper.writeBytes(auth_secret);
        IOHelper.writeLine();

        auth_secret = SHAiButtonCopr.reformatFor1961S(auth_secret);
        IOHelper.writeLine("Reformatted for compatibility with 1961S buttons");
        IOHelper.writeBytes(auth_secret);
        IOHelper.writeLine("");

        IOHelper.writeLine("Initial Balance in Cents? ");
        int initialBalance = IOHelper.readInt(100);

        trans.setParameter(SHADebit.INITIAL_AMOUNT, initialBalance);

        SHAiButtonUser user = new SHAiButtonUser33(copr, owc33, true, auth_secret);

        if (trans.setupTransactionData(user))
        {
            IOHelper.writeLine("Transaction data installation succeeded");
        }
        else
        {
            IOHelper.writeLine("Failed to initialize transaction data");
        }

        IOHelper.writeLine(user);
    }
    /// <summary>
    /// Read a page from a memory bank and print in hex
    /// </summary>
    /// <param name="bank">  PagedMemoryBank to read a page from </param>
    /// <param name="pg">  page to read </param>
    public static void dumpBankPage(OneWireContainer33 owd, PagedMemoryBank bank, int pg)
    {
        byte[] read_buf  = new byte [bank.PageLength];
        byte[] extra_buf = new byte [bank.ExtraInfoLength];
        byte[] challenge = new byte [8];
        byte[] secret    = new byte [8];
        byte[] sernum    = new byte [8];
        bool   macvalid  = false;

        try
        {
            // read a page (use the most verbose and secure method)
            if (bank.hasPageAutoCRC())
            {
                Debug.WriteLine("Using device generated CRC");

                if (bank.hasExtraInfo())
                {
                    bank.readPageCRC(pg, false, read_buf, 0, extra_buf);

                    owd.getChallenge(challenge, 0);
                    owd.getContainerSecret(secret, 0);
                    sernum   = owd.Address;
                    macvalid = OneWireContainer33.isMACValid(bank.StartPhysicalAddress + pg * bank.PageLength, sernum, read_buf, extra_buf, challenge, secret);
                }
                else
                {
                    bank.readPageCRC(pg, false, read_buf, 0);
                }
            }
            else
            {
                if (bank.hasExtraInfo())
                {
                    bank.readPage(pg, false, read_buf, 0, extra_buf);
                }
                else
                {
                    bank.readPage(pg, false, read_buf, 0);
                }
            }

            Debug.Write("Page " + pg + ": ");
            hexPrint(read_buf, 0, read_buf.Length);
            Debug.WriteLine("");

            if (bank.hasExtraInfo())
            {
                Debug.Write("Extra: ");
                hexPrint(extra_buf, 0, bank.ExtraInfoLength);
                Debug.WriteLine("");

                if (macvalid)
                {
                    Debug.WriteLine("Data validated with correct MAC.");
                }
                else
                {
                    Debug.WriteLine("Data not validated because incorrect MAC.");
                }
            }
        }
        catch (Exception e)
        {
            Debug.WriteLine(e);
        }
    }
        /// <summary>
        /// <P>Writes the account data to the SHAiButton.  First, this function
        /// asserts that the account page number is known.  The account data is
        /// copied from dataBuffer starting at the offset.  If there are less
        /// than 32 bytes available to copy, this function only copies the bytes
        /// that are available.</P>
        ///
        /// <P>Note that for the DS1961S user button, an authorization MAC must
        /// be generated for the copy-scratchpad command.  Since the scratchpad
        /// is only 8 bytes long, this must be done 4 times to write a page of
        /// data.  So, this function only writes (in 8 byte blocks) the bytes
        /// that have changed.</P>
        /// </summary>
        /// <param name="dataBuffer"> the buffer to copy the account data from </param>
        /// <param name="offset"> the index into the buffer where copying should begin </param>
        /// <returns> whether or not the data write succeeded
        /// </returns>
        /// <exception cref="OneWireIOException"> on a 1-Wire communication error such as
        ///         reading an incorrect CRC from a 1-Wire device.  This could be
        ///         caused by a physical interruption in the 1-Wire Network due to
        ///         shorts or a newly arriving 1-Wire device issuing a 'presence pulse'. </exception>
        /// <exception cref="OneWireException"> on a communication or setup error with the 1-Wire
        ///         adapter </exception>
        public override bool writeAccountData(byte[] dataBuffer, int offset)
        {
            lock (this)
            {
                //local vars.
                OneWireContainer33 ibcL         = this.ibc33;
                byte[]             copyAuth     = this.writeAccountData_copyAuth;
                byte[]             scratchpad   = this.writeAccountData_scratchpad;
                byte[]             pageData     = this.writeAccountData_pageData;
                byte[]             fullBindCode = this.fullBindCode;
                SHAiButtonCopr     coprL        = this.copr;

                //make sure account info is properly setup
                if (!checkAccountPageInfo(ibcL))
                {
                    return(false);
                }

                //if the part is being initialized, the container class "knows"
                //the secret already.  no need for a coprocessor.
                if (ibcL.ContainerSecretSet)
                {
                    //use container to write the data page, since it knows the secret
                    ibcL.writeDataPage(this.accountPageNumber, dataBuffer);
                    //update the data cache
                    Array.Copy(dataBuffer, offset, this.accountData, 0, 32);
                }
                else
                {
                    //since the container's secret is not set, we have to use the
                    //coprocessor for generating the copy scratchpad authorization.
                    if (coprL == null)
                    {
                        throw new OneWireException("No Write Authorization Coprocessor Available!");
                    }

                    //copy the data cache into a working page;
                    Array.Copy(this.accountData, 0, pageData, 0, 32);

                    //takes four write/copies to actually write the data page.
                    for (int i = 24; i >= 0; i -= 8)
                    {
                        int index = offset + i;
                        //only perform any action if the data needs to be updated
                        if ((dataBuffer[index] != accountData[i]) || (dataBuffer[index + 1] != accountData[i + 1]) || (dataBuffer[index + 2] != accountData[i + 2]) || (dataBuffer[index + 3] != accountData[i + 3]) || (dataBuffer[index + 4] != accountData[i + 4]) || (dataBuffer[index + 5] != accountData[i + 5]) || (dataBuffer[index + 6] != accountData[i + 6]) || (dataBuffer[index + 7] != accountData[i + 7]))
                        {
                            //format the working page for generating the
                            //appropriate copy authorization mac
                            pageData[28] = dataBuffer[index];
                            pageData[29] = dataBuffer[index + 1];
                            pageData[30] = dataBuffer[index + 2];
                            pageData[31] = dataBuffer[index + 3];

                            //format the scratchpad for generating the
                            //appropriate copy authorization mac
                            scratchpad[8]  = dataBuffer[index + 4];
                            scratchpad[9]  = dataBuffer[index + 5];
                            scratchpad[10] = dataBuffer[index + 6];
                            scratchpad[11] = dataBuffer[index + 7];

                            //add in the page num and address
                            Array.Copy(this.fullBindCode, 4, scratchpad, 12, 11);

                            //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
                            if (DEBUG)
                            {
                                IOHelper.writeLine("------------------------------------------------------------");
                                IOHelper.writeLine("SHAiButtonUser33 - writeAccountData loop ");
                                IOHelper.writeLine("current account data state: ");
                                IOHelper.writeBytesHex(this.accountData);
                                IOHelper.writeLine("current byte block: " + i);
                                IOHelper.writeLine("New bytes for block: ");
                                IOHelper.writeBytesHex(dataBuffer, index, 8);
                                IOHelper.writeLine("------------------------------------------------------------");
                            }
                            //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\

                            //get the copy authorization mac
                            coprL.createDataSignatureAuth(pageData, scratchpad, copyAuth, 0, fullBindCode);

                            //only need to pass it to coprocessor once
                            fullBindCode = null;

                            //write 8 bytes of data to the DS1961S scratchpad
                            if (!ibcL.writeScratchpad(this.accountPageNumber, i, dataBuffer, index, 8))
                            {
                                //operation failed
                                return(false);
                            }

                            //copy scratchpad to page
                            if (!ibcL.copyScratchpad(this.accountPageNumber, i, copyAuth, 0))
                            {
                                //operation failed
                                return(false);
                            }

                            //update cache of account data
                            Array.Copy(dataBuffer, index, this.accountData, i, 8);

                            //update our working copy of the account data
                            Array.Copy(this.accountData, 0, pageData, 0, 32);
                        }
                    }
                }
                return(true);
            }
        }
        /// <summary>
        /// <P>Creates a valid SHAiButtonUser object.  If the service file,
        /// whose name is taken from the <code>SHAiButtonCopr</code>, is not
        /// found on the user iButton, a OneWireException is thrown with the
        /// message "Invalid SHA user".</P>
        ///
        /// <P>Note: The same coprocessor can be used for write-authorization as
        /// authentication if you're transaction system is using unsigned transaction
        /// data.</P>
        /// </summary>
        /// <param name="coprBindCode"> The Coprocessor Bind Code without the information. </param>
        /// <param name="fileName"> The file name from the Coprocessor. </param>
        /// <param name="fileNameExt"> The file extenstion from the Coprocessor </param>
        /// <param name="authCopr"> The SHAiButtonCopr used to generate the write-authorization
        ///        MAC for the copy-scratchpad command of the DS1961S. </param>
        /// <param name="owc"> The DS1961S iButton that this object will refer to.
        /// </param>
        /// <exception cref="OneWireIOException"> on a 1-Wire communication error such as
        ///         reading an incorrect CRC from a 1-Wire device.  This could be
        ///         caused by a physical interruption in the 1-Wire Network due to
        ///         shorts or a newly arriving 1-Wire device issuing a 'presence pulse'. </exception>
        /// <exception cref="OneWireException"> on a communication or setup error with the 1-Wire
        ///         adapter
        /// </exception>
        /// <seealso cref= #SHAiButtonUser33(SHAiButtonCopr,OneWireContainer33,bool,byte[]) </seealso>
        /// <seealso cref= #SHAiButtonUser33(SHAiButtonCopr,SHAiButtonCopr) </seealso>
        public SHAiButtonUser33(byte[] coprBindCode, byte[] fileName, int fileNameExt, OneWireContainer33 owc)
        {
            //make sure fullBindCode has appropriate ff padding
            Array.Copy(ffBlock, 0, this.fullBindCode, 0, 15);

            //create string representation of service filename
            copr.getFilename(this.serviceFile, 0);
            this.strServiceFilename = Encoding.Unicode.GetString(fileName) + "." + (int)fileNameExt;

            //hold container reference and address
            if (!setiButton33(owc))
            {
                throw new OneWireException("Invalid SHA user");
            }
        }
    public static void Main0(string[] args)
    {
        //coprocessor
        long coprID   = 0;
        long lookupID = 0;
        bool next;

        // ------------------------------------------------------------
        // Check for valid path to sha.properties file on the cmd line.
        // ------------------------------------------------------------
        for (int i = 0; i < args.Length; i++)
        {
            string arg = args[i].ToUpper();
            if (arg.IndexOf("-P", StringComparison.Ordinal) == 0)
            {
                string sha_props_path;
                if (arg.Length == 2)
                {
                    sha_props_path = args[++i];
                }
                else
                {
                    sha_props_path = arg.Substring(2);
                }

                // attempt to open the sha.properties file
                sha_properties = new Properties();
                if (!sha_properties.loadLocalFile("sha.properties"))
                {
                    Debug.WriteLine("loading default sha.properties!");
                    Assembly asm = typeof(SHADebitDemo.MainPage).GetTypeInfo().Assembly;
                    sha_properties.loadResourceFile(asm, "SHADebitDemo.sha.properties");
                }
            }
            else
            {
                printUsageString();
                return;
            }
        }


        // ------------------------------------------------------------
        // Instantiate coprocessor containers
        // ------------------------------------------------------------
        SHAiButtonCopr     copr   = null;
        OneWireContainer18 copr18 = new OneWireContainer18();

        copr18.setSpeed(DSPortAdapter.SPEED_OVERDRIVE, false);
        copr18.SpeedCheck = false;

        // ------------------------------------------------------------
        // Setup the adapter for the coprocessor
        // ------------------------------------------------------------
        DSPortAdapter coprAdapter = null;
        string        coprAdapterName = null, coprPort = null;

        try
        {
            coprAdapterName = sha_properties.getProperty("copr.adapter");
            coprPort        = sha_properties.getProperty("copr.port");

            if (string.ReferenceEquals(coprPort, null) || string.ReferenceEquals(coprAdapterName, null))
            {
                coprAdapter = OneWireAccessProvider.DefaultAdapter;
            }
            else
            {
                coprAdapter = OneWireAccessProvider.getAdapter(coprAdapterName, coprPort);
            }

            IOHelper.writeLine("Coprocessor adapter loaded, adapter: " + coprAdapter.AdapterName + " port: " + coprAdapter.PortName);

            coprAdapter.adapterDetected();
            coprAdapter.targetFamily(0x18);
            coprAdapter.beginExclusive(true);
            coprAdapter.reset();
            coprAdapter.setSearchAllDevices();
            coprAdapter.reset();
            coprAdapter.putByte(0x3c);
            coprAdapter.Speed = DSPortAdapter.SPEED_OVERDRIVE;
        }
        catch (Exception e)
        {
            IOHelper.writeLine("Error initializing coprocessor adapter");
            Debug.WriteLine(e.ToString());
            Debug.Write(e.StackTrace);
            return;
        }

        // ------------------------------------------------------------
        // Find the coprocessor
        // ------------------------------------------------------------
        if (sha_properties.getPropertyBoolean("copr.simulated.isSimulated", false))
        {
            string coprVMfilename = sha_properties.getProperty("copr.simulated.filename");
            // ---------------------------------------------------------
            // Load emulated coprocessor
            // ---------------------------------------------------------
            try
            {
                copr = new SHAiButtonCoprVM(coprVMfilename);
            }
            catch (Exception e)
            {
                IOHelper.writeLine("Invalid Coprocessor Data File");
                Debug.WriteLine(e.ToString());
                Debug.Write(e.StackTrace);
                return;
            }
        }
        else
        {
            // ---------------------------------------------------------
            // Get the name of the coprocessor service file
            // ---------------------------------------------------------
            string filename = sha_properties.getProperty("copr.filename", "COPR.0");

            // ---------------------------------------------------------
            // Check for hardcoded coprocessor address
            // ---------------------------------------------------------
            byte[] coprAddress = sha_properties.getPropertyBytes("copr.address", null);
            lookupID = 0;
            if (coprAddress != null)
            {
                lookupID = Address.toLong(coprAddress);

                IOHelper.write("Looking for coprocessor: ");
                IOHelper.writeLineHex(lookupID);
            }

            // ---------------------------------------------------------
            // Find hardware coprocessor
            // ---------------------------------------------------------
            try
            {
                next = coprAdapter.findFirstDevice();
                while (copr == null && next)
                {
                    try
                    {
                        long tmpCoprID = coprAdapter.AddressAsLong;
                        if (coprAddress == null || tmpCoprID == lookupID)
                        {
                            IOHelper.write("Loading coprocessor file: " + filename + " from device: ");
                            IOHelper.writeLineHex(tmpCoprID);

                            copr18.setupContainer(coprAdapter, tmpCoprID);
                            copr = new SHAiButtonCopr(copr18, filename);

                            //save coprocessor ID
                            coprID = tmpCoprID;
                        }
                    }
                    catch (Exception e)
                    {
                        IOHelper.writeLine(e);
                    }

                    next = coprAdapter.findNextDevice();
                }
            }
            catch (Exception)
            {
                ;
            }
        }

        if (copr == null)
        {
            IOHelper.writeLine("No Coprocessor found!");
            return;
        }

        IOHelper.writeLine(copr);
        IOHelper.writeLine();


        // ------------------------------------------------------------
        // Create the SHADebit transaction types
        // ------------------------------------------------------------
        //stores DS1963S transaction type
        SHATransaction debit18 = null;

        string transType18 = sha_properties.getProperty("transaction.type", "signed");

        transType18 = transType18.ToLower();
        if (transType18.Equals("signed"))
        {
            debit18 = new SHADebit(copr, 10000, 50);
        }
        else
        {
            debit18 = new SHADebitUnsigned(copr, 10000, 50);
        }

        //stores DS1961S transaction type
        SHATransaction debit33 = null;

        string transType33 = sha_properties.getProperty("ds1961s.transaction.type", "unsigned");

        transType33 = transType33.ToLower();
        if (transType33.Equals(transType18))
        {
            debit33 = debit18;
        }
        else if (transType33.IndexOf("unsigned", StringComparison.Ordinal) >= 0)
        {
            //everything is seemless if you use the authentication secret
            //as the button's secret.
            debit33 = new SHADebitUnsigned(copr, 10000, 50);
        }
        else
        {
            //if the 1961S uses the authentication secret,
            //you'll need another button for generating the
            //write authorization MAC, but you can share the
            //1963S debit code for signed data.
            debit33 = new SHADebit(copr, 10000, 50);
        }

        //Transaction super class, swap variable
        SHATransaction trans = null;

        // ------------------------------------------------------------
        // Get the write-authorization coprocessor for ds1961S
        // ------------------------------------------------------------
        //first get the write authorization adapter
        DSPortAdapter authAdapter = null;
        string        authAdapterName = null, authPort = null;

        try
        {
            authAdapterName = sha_properties.getProperty("ds1961s.copr.adapter");
            authPort        = sha_properties.getProperty("ds1961s.copr.port");

            if (string.ReferenceEquals(authAdapterName, null) || string.ReferenceEquals(authAdapterName, null))
            {
                if (!string.ReferenceEquals(coprAdapterName, null) && !string.ReferenceEquals(coprPort, null))
                {
                    authAdapter = OneWireAccessProvider.DefaultAdapter;
                }
                else
                {
                    authAdapter = coprAdapter;
                }
            }
            else if (coprAdapterName.Equals(authAdapterName) && coprPort.Equals(authPort))
            {
                authAdapter = coprAdapter;
            }
            else
            {
                authAdapter = OneWireAccessProvider.getAdapter(authAdapterName, authPort);
            }

            IOHelper.writeLine("Write-Authorization adapter loaded, adapter: " + authAdapter.AdapterName + " port: " + authAdapter.PortName);

            byte[] families = new byte[] { 0x18 };

            authAdapter.adapterDetected();
            authAdapter.targetFamily(families);
            authAdapter.beginExclusive(false);
            authAdapter.reset();
            authAdapter.setSearchAllDevices();
            authAdapter.reset();
            authAdapter.putByte(0x3c);
            authAdapter.Speed = DSPortAdapter.SPEED_OVERDRIVE;
        }
        catch (Exception e)
        {
            IOHelper.writeLine("Error initializing write-authorization adapter.");
            Debug.WriteLine(e.ToString());
            Debug.Write(e.StackTrace);
            return;
        }

        //now find the coprocessor
        SHAiButtonCopr authCopr = null;

        // -----------------------------------------------------------
        // Check for hardcoded write-authorizaton coprocessor address
        // -----------------------------------------------------------
        byte[] authCoprAddress = sha_properties.getPropertyBytes("ds1961s.copr.address", null);
        lookupID = 0;
        if (authCoprAddress != null)
        {
            lookupID = Address.toLong(authCoprAddress);

            IOHelper.write("Looking for coprocessor: ");
            IOHelper.writeLineHex(lookupID);
        }
        if (lookupID == coprID)
        {
            //it's the same as the standard coprocessor.
            //valid only if we're not signing the data
            authCopr = copr;
        }
        else
        {
            // ---------------------------------------------------------
            // Find write-authorization coprocessor
            // ---------------------------------------------------------
            try
            {
                string             filename = sha_properties.getProperty("ds1961s.copr.filename", "COPR.1");
                OneWireContainer18 auth18   = new OneWireContainer18();
                auth18.setSpeed(DSPortAdapter.SPEED_OVERDRIVE, false);
                auth18.SpeedCheck = false;

                next = authAdapter.findFirstDevice();
                while (authCopr == null && next)
                {
                    try
                    {
                        long tmpAuthID = authAdapter.AddressAsLong;
                        if (authCoprAddress == null || tmpAuthID == lookupID)
                        {
                            IOHelper.write("Loading coprocessor file: " + filename + " from device: ");
                            IOHelper.writeLineHex(tmpAuthID);

                            auth18.setupContainer(authAdapter, tmpAuthID);
                            authCopr = new SHAiButtonCopr(auth18, filename);
                        }
                    }
                    catch (Exception e)
                    {
                        IOHelper.writeLine(e);
                    }

                    next = authAdapter.findNextDevice();
                }
            }
            catch (Exception e)
            {
                IOHelper.writeLine(e);
            }
            if (authCopr == null)
            {
                IOHelper.writeLine("no write-authorization coprocessor found");
                if (copr is SHAiButtonCoprVM)
                {
                    authCopr = copr;
                    IOHelper.writeLine("Re-using SHAiButtonCoprVM");
                }
            }
        }

        IOHelper.writeLine(authCopr);
        IOHelper.writeLine();

        // ------------------------------------------------------------
        // Create the User Buttons objects
        // ------------------------------------------------------------
        //holds DS1963S user buttons
        SHAiButtonUser18   user18 = new SHAiButtonUser18(copr);
        OneWireContainer18 owc18  = new OneWireContainer18();

        owc18.setSpeed(DSPortAdapter.SPEED_OVERDRIVE, false);
        owc18.SpeedCheck = false;

        //holds DS1961S user buttons
        SHAiButtonUser33   user33 = new SHAiButtonUser33(copr, authCopr);
        OneWireContainer33 owc33  = new OneWireContainer33();

        owc33.setSpeed(DSPortAdapter.SPEED_OVERDRIVE, false);
        //owc33.setSpeedCheck(false);

        //Holds generic user type, swap variable
        SHAiButtonUser user = null;

        // ------------------------------------------------------------
        // Get the adapter for the user
        // ------------------------------------------------------------
        DSPortAdapter adapter = null;
        string        userAdapterName = null, userPort = null;

        try
        {
            userAdapterName = sha_properties.getProperty("user.adapter");
            userPort        = sha_properties.getProperty("user.port");

            if (string.ReferenceEquals(userPort, null) || string.ReferenceEquals(userAdapterName, null))
            {
                if (!string.ReferenceEquals(coprAdapterName, null) && !string.ReferenceEquals(coprPort, null))
                {
                    if (!string.ReferenceEquals(authAdapterName, null) && !string.ReferenceEquals(authPort, null))
                    {
                        adapter = OneWireAccessProvider.DefaultAdapter;
                    }
                    else
                    {
                        adapter = authAdapter;
                    }
                }
                else
                {
                    adapter = coprAdapter;
                }
            }
            else if (userAdapterName.Equals(authAdapterName) && userPort.Equals(authPort))
            {
                adapter = authAdapter;
            }
            else if (userAdapterName.Equals(coprAdapterName) && userPort.Equals(coprPort))
            {
                adapter = coprAdapter;
            }
            else
            {
                adapter = OneWireAccessProvider.getAdapter(userAdapterName, userPort);
            }

            IOHelper.writeLine("User adapter loaded, adapter: " + adapter.AdapterName + " port: " + adapter.PortName);

            byte[] families = new byte[] { 0x18, 0x33 };
            families = sha_properties.getPropertyBytes("transaction.familyCodes", families);
            IOHelper.write("Supporting the following family codes: ");
            IOHelper.writeBytesHex(" ", families, 0, families.Length);

            adapter.adapterDetected();
            adapter.targetFamily(families);
            adapter.beginExclusive(true);
            adapter.reset();
            adapter.setSearchAllDevices();
            adapter.reset();
            adapter.putByte(0x3c);
            adapter.Speed = DSPortAdapter.SPEED_OVERDRIVE;
        }
        catch (Exception e)
        {
            IOHelper.writeLine("Error initializing user adapter.");
            Debug.WriteLine(e.ToString());
            Debug.Write(e.StackTrace);
            return;
        }

        //timing variables
        long t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0, t5 = 0;

        //address of current device
        byte[] address = new byte[8];

        //result of findNextDevice/findFirstDevice
        next = false;

        //holds list of known buttons
        long[] buttons = new long[16];
        //count of how many buttons are in buttons array
        int index = 0;

        //temporary id representing current button
        long tmpID = -1;

        //array of buttons looked at during this search
        long[] temp = new long[16];
        //count of how many buttons in temp array
        int cIndex = 0;

        //flag indiciating whether or not temp array represents
        //the complete list of buttons on the network.
        bool wholeList = false;

        Debug.WriteLine("");
        Debug.WriteLine("");
        Debug.WriteLine("**********************************************************");
        Debug.WriteLine("   Beginning The Main Application Loop (Search & Debit)");
        Debug.WriteLine("           Press Enter to Exit Application");
        Debug.WriteLine("**********************************************************");
        Debug.WriteLine("");

        //application infinite loop
        for (bool applicationFinished = false; !applicationFinished;)
        {
            try
            {
                if (coprAdapter != adapter)
                {
                    //in case coprocessor communication got hosed, make sure
                    //the coprocessor adapter is in overdrive
                    coprAdapter.Speed = DSPortAdapter.SPEED_REGULAR;
                    coprAdapter.reset();
                    coprAdapter.putByte(0x3c);        //overdrive skip rom
                    coprAdapter.Speed = DSPortAdapter.SPEED_OVERDRIVE;
                }
                if (authAdapter != coprAdapter && authAdapter != adapter)
                {
                    //in case coprocessor communication with the write-
                    //authorization coprocessor got hosed, make sure
                    //the coprocessor adapter is in overdrive
                    authAdapter.Speed = DSPortAdapter.SPEED_REGULAR;
                    authAdapter.reset();
                    authAdapter.putByte(0x3c);        //overdrive skip rom
                    authAdapter.Speed = DSPortAdapter.SPEED_OVERDRIVE;
                }
            }
            catch (Exception)
            {
                ;
            }

            // ---------------------------------------------------------
            // Search for new buttons
            // ---------------------------------------------------------
            bool buttonSearch = true;

            //Button search loop, waits forever until new button appears.
            while (buttonSearch && !applicationFinished)
            {
                wholeList = false;
                t0        = Stopwatch.GetTimestamp() * TimeSpan.TicksPerMillisecond;
                try
                {
                    //Go into overdrive
                    adapter.Speed = DSPortAdapter.SPEED_REGULAR;
                    adapter.reset();
                    adapter.putByte(0x3c);        //overdrive skip rom
                    adapter.Speed = DSPortAdapter.SPEED_OVERDRIVE;

                    // Begin search for new buttons
                    if (!next)
                    {
                        wholeList = true;
                        next      = adapter.findFirstDevice();
                    }

                    for (tmpID = -1, cIndex = 0; next && (tmpID == -1); next = adapter.findNextDevice())
                    {
                        tmpID = adapter.AddressAsLong;
                        if (tmpID != coprID)
                        {
                            temp[cIndex++] = tmpID;
                            for (int i = 0; i < index; i++)
                            {
                                if (buttons[i] == tmpID)
                                {                 //been here all along
                                    tmpID = -1;
                                    i     = index;
                                }
                            }

                            if (tmpID != -1)
                            {
                                //populate address array
                                adapter.getAddress(address);
                            }
                        }
                        else
                        {
                            tmpID = -1;
                        }
                    }

                    //if we found a new button
                    if (tmpID != -1)
                    {
                        //add it to the main list
                        buttons[index++] = tmpID;

                        //quite searching, we got one!
                        buttonSearch = false;
                    }
                    else if (wholeList)
                    {
                        //went through whole list with nothing new
                        //update the main list of buttons
                        buttons = temp;
                        index   = cIndex;

                        //if user presses the enter key, we'll quit and clean up nicely
//TODO				  applicationFinished = (System.in.available() > 0);
                    }
                }
                catch (Exception e)
                {
                    if (DEBUG)
                    {
                        IOHelper.writeLine("adapter hiccup while searching");
                        Debug.WriteLine(e.ToString());
                        Debug.Write(e.StackTrace);
                    }
                }
            }

            if (applicationFinished)
            {
                continue;
            }

            // ---------------------------------------------------------
            // Perform the transaction
            // ---------------------------------------------------------
            try
            {
                t1 = Stopwatch.GetTimestamp() * TimeSpan.TicksPerMillisecond;

                //de-ref the user
                user = null;

                //check for button family code
                if ((tmpID & 0x18) == (byte)0x18)
                {
                    //get transactions for ds1963s
                    trans = debit18;
                    owc18.setupContainer(adapter, address);
                    if (user18.setiButton18(owc18))
                    {
                        user = user18;
                    }
                }
                else if ((tmpID & 0x33) == (byte)0x33)
                {
                    //get transactions for 1961S
                    trans = debit33;
                    owc33.setupContainer(adapter, address);
                    if (user33.setiButton33(owc33))
                    {
                        user = user33;
                    }
                }

                if (user != null)
                {
                    Debug.WriteLine("");
                    Debug.WriteLine(user.ToString());
                    t2 = Stopwatch.GetTimestamp() * TimeSpan.TicksPerMillisecond;
                    if (trans.verifyUser(user))
                    {
                        t3 = Stopwatch.GetTimestamp() * TimeSpan.TicksPerMillisecond;
                        if (trans.verifyTransactionData(user))
                        {
                            t4 = Stopwatch.GetTimestamp() * TimeSpan.TicksPerMillisecond;
                            if (!trans.executeTransaction(user, true))
                            {
                                Debug.WriteLine("Execute Transaction Failed");
                            }
                            t5 = Stopwatch.GetTimestamp() * TimeSpan.TicksPerMillisecond;

                            Debug.WriteLine("  Debit Amount: $00.50");
                            Debug.Write("User's balance: $");
                            int balance = trans.getParameter(SHADebit.USER_BALANCE);
                            Debug.WriteLine(com.dalsemi.onewire.utils.Convert.ToString(balance / 100d, 2));
                        }
                        else
                        {
                            Debug.WriteLine("Verify Transaction Data Failed");
                        }
                    }
                    else
                    {
                        Debug.WriteLine("Verify User Authentication Failed");
                    }
                }
                else
                {
                    Debug.WriteLine("Not a SHA user of this service");
                }

                Debug.Write("Total time: ");
                Debug.WriteLine(t5 - t0);
                Debug.Write("Executing transaction took: ");
                Debug.WriteLine(t5 - t4);
                Debug.Write("Verifying data took: ");
                Debug.WriteLine(t4 - t3);
                Debug.Write("Verifying user took: ");
                Debug.WriteLine(t3 - t2);
                Debug.Write("Loading user data took: ");
                Debug.WriteLine(t2 - t1);
                Debug.Write("Finding user took: ");
                Debug.WriteLine(t1 - t0);

                //report all errors
                if (trans.LastError != 0)
                {
                    IOHelper.writeLine("Last Error Code: ");
                    IOHelper.writeLine(trans.LastError);
                    if (trans.LastError == SHATransaction.COPROCESSOR_FAILURE)
                    {
                        IOHelper.writeLine("COPR Error Code: ");
                        IOHelper.writeLine(copr.LastError);
                    }
                }
            }
            catch (Exception e)
            {
                Debug.WriteLine("Transaction failed!");
                Debug.WriteLine(e.ToString());
                Debug.Write(e.StackTrace);
            }
        }

        // --------------------------------------------------------------
        // Some Friendly Cleanup
        // --------------------------------------------------------------
        adapter.endExclusive();
        coprAdapter.endExclusive();
        authAdapter.endExclusive();
    }
Exemple #13
0
        /// <summary>
        /// Method main
        ///
        /// </summary>
        /// <param name="args">
        /// </param>
        /// <exception cref="OneWireException"> </exception>
        /// <exception cref="OneWireIOException">
        ///  </exception>

        public void Main([ReadOnlyArray()] string[] args)
        {
            bool          usedefault   = false;
            DSPortAdapter access       = null;
            string        adapter_name = null;
            string        port_name    = null;

            if ((args == null) || (args.Length < 1))
            {
                try
                {
                    access = OneWireAccessProvider.DefaultAdapter;

                    if (access == null)
                    {
                        throw new Exception();
                    }
                }
                catch (Exception)
                {
                    Debug.WriteLine("Couldn't get default adapter!");
                    printUsageString();

                    return;
                }

                usedefault = true;
            }

            if (!usedefault)
            {
                //parse device instance

                //string[] st = args[0].Split(new char[] { '_' });

                if (args.Length != 2)
                {
                    printUsageString();

                    return;
                }

                adapter_name = args[0];
                port_name    = args[1];

                Debug.WriteLine("Adapter Name: " + adapter_name);
                Debug.WriteLine("Port Name: " + port_name);
            }

            if (access == null)
            {
                try
                {
                    access = OneWireAccessProvider.getAdapter(adapter_name, port_name);
                }
                catch (Exception)
                {
                    Debug.WriteLine("That is not a valid adapter/port combination.");

                    System.Collections.IEnumerator en = OneWireAccessProvider.enumerateAllAdapters();

                    while (en.MoveNext())
                    {
                        DSPortAdapter temp = (DSPortAdapter)en.Current;

                        Debug.WriteLine("Adapter: " + temp.AdapterName);

                        System.Collections.IEnumerator f = temp.PortNames;

                        while (f.MoveNext())
                        {
                            Debug.WriteLine("   Port name : " + ((DeviceInformation)f.Current).Id);
                        }
                    }

                    return;
                }
            }

            access.adapterDetected();
            access.targetAllFamilies();
            access.beginExclusive(true);
            access.reset();
            access.setSearchAllDevices();

            bool next = access.findFirstDevice();

            if (!next)
            {
                Debug.WriteLine("Could not find any iButtons!");

                return;
            }

            while (next)
            {
                OneWireContainer owc = access.DeviceContainer;

                Debug.WriteLine("====================================================");
                Debug.WriteLine("= Found One Wire Device: " + owc.AddressAsString + "          =");
                Debug.WriteLine("====================================================");
                Debug.WriteLine("=");

                bool isShaContainer   = false;
                OneWireContainer33 sc = null;

                try
                {
                    sc             = (OneWireContainer33)owc;
                    isShaContainer = true;
                }
                catch (System.InvalidCastException)
                {
                    sc             = null;
                    isShaContainer = false; //just to reiterate
                }

                if (isShaContainer)
                {
                    Debug.WriteLine("= This device is a " + owc.Name);
                    Debug.WriteLine("= Also known as a " + owc.AlternateNames);
                    Debug.WriteLine("=");
                    Debug.WriteLine("= It is a 1K-Bit protected 1-Wire EEPROM with SHA-1 Engine device.");

                    byte[] statusPage = null;
                    ReadMemoryBank(sc.StatusPageMemoryBank, out statusPage);

                    Debug.WriteLine("Status Page");
                    for (var i = 0; i < statusPage.Length; i++)
                    {
                        Debug.Write(statusPage[i].ToString("X") + " ");
                    }
                    Debug.WriteLine("");

                    byte[] mem = new byte[8];
                    Array.Copy(statusPage, 8, mem, 0, 8);

                    if ((mem[0] == 0xAA) || (mem[0] == 0x55))
                    {
                        Debug.WriteLine("SECRET IS WRITE PROTECTED - CANNOT LOAD FIRST SECRET");
                    }
                    else
                    {
                        Debug.WriteLine("SECRET IS NOT WRITE PROTECTED!");
                    }

                    if ((mem[1] == 0xAA) || (mem[1] == 0x55))
                    {
                        Debug.WriteLine("memoryPages[0].readOnly = true");
                        Debug.WriteLine("memoryPages[1].readOnly = true");
                        Debug.WriteLine("memoryPages[2].readOnly = true");
                    }
                    else
                    {
                        Debug.WriteLine("memoryPages[0].readWrite = true");
                        Debug.WriteLine("memoryPages[1].readWrite = true");
                        Debug.WriteLine("memoryPages[2].readWrite = true");
                    }

                    if ((mem[4] == 0xAA) || (mem[4] == 0x55))
                    {
                        Debug.WriteLine("memoryPages[1].writeOnce = true");
                    }
                    else
                    {
                        Debug.WriteLine("memoryPages[1].writeOnce = false");
                    }

                    if ((mem[5] == 0xAA) || (mem[5] == 0x55))
                    {
                        Debug.WriteLine("memoryPages[0].readOnly = true");
                    }
                    else
                    {
                        Debug.WriteLine("memoryPages[0].readWrite = true");
                    }

                    Debug.WriteLine("mem[0] " + mem[0].ToString("X"));
                    Debug.WriteLine("mem[1] " + mem[1].ToString("X"));
                    Debug.WriteLine("mem[3] " + mem[3].ToString("X"));

                    if (((mem[0] != 0xAA) && (mem[0] != 0x55)) &&
                        ((mem[3] != 0xAA) && (mem[3] != 0x55)))
                    {
                        Debug.WriteLine("Case 1");

                        //// Clear all memory to 0xFFh
                        //for (i = 0; i < 16; i++)
                        //{
                        //    if (!LoadFirSecret(portnum, (ushort)(i * 8), data, 8))
                        //        printf("MEMORY ADDRESS %d DIDN'T WRITE\n", i * 8);
                        //}

                        //printf("Current Bus Master Secret Is:\n");
                        //for (i = 0; i < 8; i++)
                        //    printf("%02X ", secret[i]);
                        //printf("\n");
                    }
                    else if ((mem[1] != 0xAA) || (mem[1] != 0x55))
                    {
                        Debug.WriteLine("Case 2");

                        //printf("Please Enter the Current Secret\n");
                        //printf("AA AA AA AA AA AA AA AA  <- Example\n");
                        //scanf("%s %s %s %s %s %s %s %s", &hexstr[0], &hexstr[2], &hexstr[4],
                        //       &hexstr[6], &hexstr[8], &hexstr[10], &hexstr[12], &hexstr[14]);

                        //if (!ParseData(hexstr, strlen(hexstr), data, 16))
                        //    printf("DIDN'T PARSE\n");
                        //else
                        //{
                        //    printf("The secret read was:\n");
                        //    for (i = 0; i < 8; i++)
                        //    {
                        //        secret[i] = data[i];
                        //        printf("%02X ", secret[i]);
                        //        data[i] = 0xFF;
                        //    }
                        //    printf("\n");
                        //}

                        //printf("\n");

                        //if ((indata[13] == 0xAA) || (indata[13] == 0x55))
                        //    skip = 4;
                        //else
                        //    skip = 0;

                        //for (i = (ushort)skip; i < 16; i++)
                        //{
                        //    ReadMem(portnum, (ushort)(((i * 8) / ((ushort)32)) * 32), memory);

                        //    if (WriteScratchSHAEE(portnum, (ushort)(i * 8), &data[0], 8))
                        //        CopyScratchSHAEE(portnum, (ushort)(i * 8), secret, sn, memory);
                        //}
                    }
                    else
                    {
                        Debug.WriteLine("Case 3");

                        //printf("Please Enter the Current Secret\n");
                        //printf("AA AA AA AA AA AA AA AA  <- Example\n");
                        //scanf("%s %s %s %s %s %s %s %s", &hexstr[0], &hexstr[2], &hexstr[4],
                        //       &hexstr[6], &hexstr[8], &hexstr[10], &hexstr[12], &hexstr[14]);
                        //if (!ParseData(hexstr, strlen(hexstr), secret, 16))
                        //    printf("DIDN'T PARSE\n");
                        //else
                        //{
                        //    printf("The secret that was read:\n");
                        //    for (i = 0; i < 8; i++)
                        //    {
                        //        printf("%02X ", secret[i]);
                        //    }
                        //    printf("\n");
                        //}
                    }
                }
                else
                {
                    Debug.WriteLine("= Not a SHA-1 Engine device.");
                    Debug.WriteLine("=");
                    Debug.WriteLine("=");
                }

                next = access.findNextDevice();
            }
        }