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

// Include Files
#include <stdio.h>
#include "rawmem.h"
#include "mbnv.h"
#include "mbappreg.h"
#include "mbeprom.h"
#include "mbnvcrc.h"
#include "mbshaee.h"
#include "mbscrcrc.h"
#include "mbscrex.h"
#include "mbsha.h"
#include "mbscree.h"
#include "mbscr.h"
#include "mbee77.h"
#include "mbscrx77.h"
#include "mbee.h"
#include "pw77.h"

/**
 * Reads memory in this bank with no CRC checking (device or
 * data). The resulting data from this API may or may not be what is on
 * the 1-Wire device.  It is recommended that the data contain some kind
 * of checking (CRC) like in the owReadPagePacket method.
 * Some 1-Wire devices provide thier own CRC as in owReadPageCRC
 * The owReadPageCRC method is not supported on all memory types, see hasPageAutoCRC
 * in the same interface.  If neither is an option then this method could be called more
 * then once to at least verify that the same data is read consistently.  The
 * readContinue parameter is used to eliminate the overhead in re-accessing
 * a part already being read from. For example, if pages 0 - 4 are to
 * be read, readContinue would be set to false for page 0 and would be set
 * to true for the next four calls.
 *
 * Note: Using readContinue = true  can only be used if the new
 *       read continuous where the last one led off
 *       and it is inside a 'beginExclusive/endExclusive'
 *       block.
 *
 * bank          to tell what memory bank of the ibutton to use.
 * portnum       the port number of the port being used for the
 *               1-Wire Network.
 * SNum          the serial number for the part that the operation is
 *               to be done on.
 * str_add       starting address
 * rd_cont       true then device read is
 *               continued without re-selecting
 * buff          location for data read
 * len           length in bytes to read
 *
 * @return 'true' if the read was complete
 */
SMALLINT owRead(SMALLINT bank, int portnum, uchar *SNum, int str_add,
                SMALLINT rd_cont, uchar *buff, int len)
{
   SMALLINT ret = 0;
   uchar extra[5];

   switch(SNum[0] & 0x7F)
   {
      case 0x14:  //EE Memory Bank and AppReg Memory Bank
         if(bank > 0)
            ret = readEE(bank,portnum,SNum,str_add,rd_cont,buff,len);
         else if(bank == 0)
            ret = readAppReg(bank,portnum,SNum,str_add,rd_cont,buff,len);
         break;

      case 0x04: case 0x06: case 0x08: case 0x0A:
      case 0x0C: case 0x23: //NV Memory Bank and Scratch Memory Bank
         if(bank > 0)
            ret = readNV(bank,portnum,SNum,str_add,rd_cont,buff,len);
         else if(bank == 0)
            ret = readScratch(bank,portnum,SNum,str_add,rd_cont,buff,len);
         break;

      case (0x18):  //NV Memory Bank and Scratch SHA Memory Bank
         if(bank > 0)
            ret = readNV(bank,portnum,SNum,str_add,rd_cont,buff,len);
         else if(bank == 0)
            ret = readScratch(bank,portnum,SNum,str_add,rd_cont,buff,len);
         break;

      case 0x1A: case 0x1D:  //NVCRC Memory Bank and Scratch Ex Memory Bank
         if(bank > 0)
            ret = readNV(bank,portnum,SNum,str_add,rd_cont,buff,len);
         else if(bank == 0)
            ret = readScratch(bank,portnum,SNum,str_add,rd_cont,buff,len);
         break;

      case 0x21:  //NVCRC Memory Bank and Scratch CRC Memory Bank
         if(bank > 0)
            ret = readNV(bank,portnum,SNum,str_add,rd_cont,buff,len);
         else if(bank == 0)
            ret = readScratch(bank,portnum,SNum,str_add,rd_cont,buff,len);
         break;

      case 0x33: case 0xB3:  //SHAEE Memory Bank
         ret = readSHAEE(bank,portnum,SNum,str_add,rd_cont,buff,len);
         break;

      case 0x09: case 0x0B: case 0x0F: case 0x12: case 0x13:  //EPROM Memory Bank
         ret = readEPROM(bank,portnum,SNum,str_add,rd_cont,buff,len);
         break;

      case 0x37: case 0x77:
         if(bank > 0)
         {
            ret = readEEPsw77(bank,portnum,SNum,str_add,rd_cont,buff,len);
         }
         else if(bank == 0)
         {
            ret = readScratchPadCRC77(portnum,SNum,buff,len,&extra[0]);
         }
         break;

      default:
         break;
   }

   return ret;
}

/**
 * Writes memory in this bank. It is recommended that a structure with some
 * built in error checking is used to provide data integrity on read.
 * The method owWritePagePacket, which automatically wraps the data in a length
 * and CRC, could be used for this purpose.
 *
 * When using on Write-Once devices care must be taken to write into
 * into empty space.  If owWrite is used to write over an unlocked
 * page on a Write-Once device it will fail.
 *
 * bank        to tell what memory bank of the ibutton to use.
 * portnum     the port number of the port being used for the
 *             1-Wire Network.
 * SNum        the serial number for the part that the operation is
 *             to be done on.
 * str_add     starting address
 * buff        data to write
 * len         length in bytes to write
 *
 * @return 'true' if the write was complete
 */
SMALLINT owWrite(SMALLINT bank, int portnum, uchar *SNum, int str_add,
                 uchar *buff, int len)
{
   SMALLINT ret = 0;

   switch(SNum[0] & 0x7F)
   {
      case 0x14:  //EE Memory Bank and AppReg Memory Bank
         if(bank > 0)
            ret = writeEE(bank,portnum,SNum,str_add,buff,len);
         else if(bank == 0)
            ret = writeAppReg(bank,portnum,SNum,str_add,buff,len);
         break;

      case 0x04: case 0x06: case 0x08: case 0x0A:
      case 0x0C: case 0x23:  //NV Memory Bank and Scratch Memory Bank
         if(bank > 0)
            ret = writeNV(bank,portnum,SNum,str_add,buff,len);
         else if(bank == 0)
            ret = writeScratch(bank,portnum,SNum,str_add,buff,len);
         break;

      case 0x18:  //NV Memory Bank and Scratch SHA Memory Bank
         if(bank > 0)
            ret = writeNV(bank,portnum,SNum,str_add,buff,len);
         else if(bank == 0)
            ret = writeScratch(bank,portnum,SNum,str_add,buff,len);
         break;

      case 0x1A: case 0x1D:  //NVCRC Memory Bank and Scratch Ex Memory Bank
         if(bank > 0)
            ret = writeNV(bank,portnum,SNum,str_add,buff,len);
         else if(bank == 0)
            ret = writeScratch(bank,portnum,SNum,str_add,buff,len);
         break;

      case 0x21:  //NVCRC Memory Bank and Scratch CRC Memory Bank
         if(bank > 0)
            ret = writeNV(bank,portnum,SNum,str_add,buff,len);
         else if(bank == 0)
            ret = writeScratch(bank,portnum,SNum,str_add,buff,len);
         break;

      case 0x33: case 0xB3:  //SHAEE Memory Bank
         ret = writeSHAEE(bank,portnum,SNum,str_add,buff,len);
         break;

      case 0x09: case 0x0B: case 0x0F: case 0x12: case 0x13:  //EPROM Memory Bank
         ret = writeEPROM(bank,portnum,SNum,str_add,buff,len);
         break;

      case 0x37: case 0x77:
         if(bank > 0)
         {
            ret = writeEE77(bank,portnum,SNum,str_add,buff,len);
         }
         else if(bank == 0)
         {
            ret = writeScratchPadEx77(portnum,SNum,str_add,buff,len);
         }
         break;


      default:
         break;
   }

   return ret;
}

/**
 * Reads a page in this memory bank with no
 * CRC checking (device or data). The resulting data from this API
 * may or may not be what is on the 1-Wire device.  It is recommends
 * that the data contain some kind of checking (CRC) like in the
 * owReadPagePacket function or have the 1-Wire device provide the
 * CRC as in owReadPageCRC.
 * However device CRC generation is not
 * supported on all memory types, see owHasPageAutoCRC}.
 * If neither is an option then this method could be called more
 * then once to at least verify that the same data is read consistently.
 *
 * The readContinue parameter is used to eliminate the overhead in re-accessing
 * a part already being read from. For example, if pages 0 - 4 are to
 * be read, readContinue would be set to false for page 0 and would be set
 * to true for the next four calls.
 * Note: Using readContinue = true  can only be used if the new
 *       read continues where the last one left off
 *       and it is inside a 'beginExclusive/endExclusive'
 *       block.
 *
 * bank       to tell what memory bank of the ibutton to use.
 * portnum    the port number of the port being used for the
 *            1-Wire Network.
 * SNum       the serial number for the part that the operation is
 *            to be done on.
 * page       page number to read packet from
 * rd_cont    true, then device read
 *            is continued without re-selecting
 * buff       location for data read
 *
 * @return 'true' if the read was complete
 */
SMALLINT owReadPage(SMALLINT bank, int portnum, uchar *SNum, int page,
                    SMALLINT rd_cont, uchar *buff)
{
   SMALLINT ret = 0;

   switch(SNum[0] & 0x7F)
   {
      case 0x14:  //EE Memory Bank and AppReg Memory Bank
         if(bank > 0)
            ret = readPageEE(bank,portnum,SNum,page,rd_cont,buff);
         else if(bank == 0)
            ret = readPageAppReg(bank,portnum,SNum,page,rd_cont,buff);
         break;

      case 0x04: case 0x06: case 0x08: case 0x0A:
      case 0x0C: case 0x23:  //NV Memory Bank and Scratch Memory Bank
         if(bank > 0)
            ret = readPageNV(bank,portnum,SNum,page,rd_cont,buff);
         else if(bank == 0)
            ret = readPageScratch(bank,portnum,SNum,page,rd_cont,buff);
         break;

      case (0x18):  //NV Memory Bank and Scratch SHA Memory Bank
         if(bank == 3)
            ret = readPageNV(bank,portnum,SNum,page,rd_cont,buff);
         else if(bank > 0)
            ret = readPageNVCRC(bank,portnum,SNum,page,rd_cont,buff);
         else if(bank == 0)
            ret = readPageScratch(bank,portnum,SNum,page,rd_cont,buff);
         break;

      case 0x1A: case 0x1D:  //NVCRC Memory Bank and Scratch Ex Memory Bank
         if(bank > 0)
            ret = readPageNVCRC(bank,portnum,SNum,page,rd_cont,buff);
         else if(bank == 0)
            ret = readPageScratch(bank,portnum,SNum,page,rd_cont,buff);
         break;

      case 0x21:  //NVCRC Memory Bank and Scratch CRC Memory Bank
         if(bank > 0)
            ret = readPageNVCRC(bank,portnum,SNum,page,rd_cont,buff);
         else if(bank == 0)
            ret = readPageScratch(bank,portnum,SNum,page,rd_cont,buff);
         break;

      case 0x33: case 0xB3:  //SHAEE Memory Bank
         ret = readPageSHAEE(bank,portnum,SNum,page,rd_cont,buff);
         break;

      case 0x09: case 0x0B: case 0x0F: case 0x12: case 0x13:  //EPROM Memory Bank
         ret = readPageEPROM(bank,portnum,SNum,page,rd_cont,buff);
         break;

      case 0x37: case 0x77:
         if(bank > 0)
         {
            ret = readPageEE77(bank,portnum,SNum,page,rd_cont,buff);
         }
         else if(bank == 0)
         {
            ret = readPageScratchEx77(bank,portnum,SNum,page,rd_cont,buff);
         }
         break;

      default:
         break;
   }

   return ret;
}

/**
 * Reads a page in this memory bank with extra information with no
 * CRC checking (device or data). The resulting data from this API
 * may or may not be what is on the 1-Wire device.  It is recommends
 * that the data contain some kind of checking (CRC) like in the
 * owReadPagePacket function or have the 1-Wire device provide the
 * CRC as in owReadPageCRC}.
 * However device CRC generation is not
 * supported on all memory types, see owHasPageAutoCRC}.
 * If neither is an option then this method could be called more
 * then once to at least verify that the same data is read consistently.The
 * readContinue parameter is used to eliminate the overhead in re-accessing
 * a part already being read from. For example, if pages 0 - 4 are to
 * be read, readContinue would be set to false for page 0 and would be set
 * to true for the next four calls.
 *
 * Note: Using readContinue = true  can only be used if the new
 *       read continues where the last one left off
 *       and it is inside a 'beginExclusive/endExclusive'
 *       block.
 *
 * bank       to tell what memory bank of the ibutton to use.
 * portnum    the port number of the port being used for the
 *            1-Wire Network.
 * SNum       the serial number for the part that the operation is
 *            to be done on.
 * page       page number to read packet from
 * rd_cont    true  then device read
 *            is continued without re-selecting
 * buff       location for data read
 * extra      location for extra info read
 *
 * @return 'true' if the read was complete
 */
SMALLINT owReadPageExtra(SMALLINT bank, int portnum, uchar *SNum, int page,
                         SMALLINT rd_cont, uchar *buff, uchar *extra)
{
   SMALLINT ret = 0;

   switch(SNum[0] & 0x7F)
   {
      case 0x14:  //EE Memory Bank and AppReg Memory Bank
         if(bank > 0)
            ret = readPageExtraEE(bank,portnum,SNum,page,rd_cont,buff,extra);
         else if(bank == 0)
            ret = readPageExtraAppReg(bank,portnum,SNum,page,rd_cont,buff,extra);
         break;

      case 0x04: case 0x06: case 0x08: case 0x0A:
      case 0x0C: case 0x23:  //NV Memory Bank and Scratch Memory Bank
         if(bank > 0)
            ret = readPageExtraNV(bank,portnum,SNum,page,rd_cont,buff,extra);
         else if(bank == 0)
            ret = readPageExtraScratch(bank,portnum,SNum,page,rd_cont,buff,extra);
         break;

      case (0x18):  //NV Memory Bank and Scratch SHA Memory Bank
         if(bank == 3)
            ret = readPageExtraNV(bank,portnum,SNum,page,rd_cont,buff,extra);
         else if(bank > 0)
            ret = readPageExtraNVCRC(bank,portnum,SNum,page,rd_cont,buff,extra);
         else if(bank == 0)
            ret = readPageExtraScratch(bank,portnum,SNum,page,rd_cont,buff,extra);
         break;

      case 0x1A: case 0x1D:  //NVCRC Memory Bank and Scratch Ex Memory Bank
         if(bank > 0)
            ret = readPageExtraNVCRC(bank,portnum,SNum,page,rd_cont,buff,extra);
         else if(bank == 0)
            ret = readPageExtraScratch(bank,portnum,SNum,page,rd_cont,buff,extra);
         break;

      case 0x21:  //NVCRC Memory Bank and Scratch CRC Memory Bank
         if(bank > 0)
            ret = readPageExtraNVCRC(bank,portnum,SNum,page,rd_cont,buff,extra);
         else if(bank == 0)
            ret = readPageExtraScratch(bank,portnum,SNum,page,rd_cont,buff,extra);
         break;

      case 0x33: case 0xB3:  //SHAEE Memory Bank
         ret = readPageExtraSHAEE(bank,portnum,SNum,page,rd_cont,buff,extra);
         break;

      case 0x09: case 0x0B: case 0x0F: case 0x12: case 0x13:  //EPROM Memory Bank
         ret = readPageExtraEPROM(bank,portnum,SNum,page,rd_cont,buff,extra);
         break;

      case 0x37: case 0x77:
         if(bank > 0)
         {
            ret = readPageExtraEE77(bank,portnum,SNum,page,rd_cont,buff,extra);
         }
         else if(bank == 0)
         {
            ret = readPageExtraScratchEx77(bank,portnum,SNum,page,rd_cont,
                                           buff,extra);
         }
         break;

      default:
         break;
   }

   return ret;
}

/**
 * Reads a complete memory page with CRC verification provided by the
 * device with extra information.  Not supported by all devices. The
 * rd_Continue parameter is used to eliminate the overhead in re-accessing
 * a part already being read from. For example, if pages 0 - 4 are to
 * be read, readContinue would be set to false for page 0 and would be set
 * to true for the next four calls.
 *
 * bank       to tell what memory bank of the ibutton to use.
 * portnum    the port number of the port being used for the
 *            1-Wire Network.
 * SNum       the serial number for the part that the operation is
 *            to be done on.
 * page       page number to read
 * read_buff  location for data read
 * extra      location for extra info read
 *
 * @return 'true' if the read was complete
 */
SMALLINT owReadPageExtraCRC(SMALLINT bank, int portnum, uchar *SNum, int page,
                            uchar *read_buff, uchar *extra)
{
   SMALLINT ret = 0;

   switch(SNum[0] & 0x7F)
   {
      case 0x14:  //EE Memory Bank and AppReg Memory Bank
         if(bank > 0)
            ret = readPageExtraCRCEE(bank,portnum,SNum,page,read_buff,extra);
         else if(bank == 0)
            ret = readPageExtraCRCAppReg(bank,portnum,SNum,page,read_buff,extra);
         break;

      case 0x04: case 0x06: case 0x08: case 0x0A:
      case 0x0C: case 0x23:  //NV Memory Bank and Scratch Memory Bank
         if(bank > 0)
            ret = readPageExtraCRCNV(bank,portnum,SNum,page,read_buff,extra);
         else if(bank == 0)
            ret = readPageExtraCRCScratch(bank,portnum,SNum,page,read_buff,extra);
         break;

      case (0x18):  //NV Memory Bank and Scratch SHA Memory Bank
         if(bank == 3)
            ret = readPageExtraCRCNV(bank,portnum,SNum,page,read_buff,extra);
         else if(bank > 0)
            ret = readPageExtraCRCNVCRC(bank,portnum,SNum,page,read_buff,extra);
         else if(bank == 0)
            ret = readPageExtraCRCScratch(bank,portnum,SNum,page,read_buff,extra);
         break;

      case 0x1A: case 0x1D:  //NVCRC Memory Bank and Scratch Ex Memory Bank
         if(bank > 0)
            ret = readPageExtraCRCNVCRC(bank,portnum,SNum,page,read_buff,extra);
         else if(bank == 0)
            ret = readPageExtraCRCScratch(bank,portnum,SNum,page,read_buff,extra);
         break;

      case 0x21:  //NVCRC Memory Bank and Scratch CRC Memory Bank
         if(bank > 0)
            ret = readPageExtraCRCNVCRC(bank,portnum,SNum,page,read_buff,extra);
         else if(bank == 0)
            ret = readPageExtraCRCScratch(bank,portnum,SNum,page,read_buff,extra);
         break;

      case 0x33: case 0xB3:  //SHAEE Memory Bank
         ret = readPageExtraCRCSHAEE(bank,portnum,SNum,page,read_buff,extra);
         break;

      case 0x09: case 0x0B: case 0x0F: case 0x12: case 0x13:  //EPROM Memory Bank
         ret = readPageExtraCRCEPROM(bank,portnum,SNum,page,read_buff,extra);
         break;

      case 0x37: case 0x77:
         if(bank > 0)
         {
            ret = readPageExtraCRCEE77(bank,portnum,SNum,page,read_buff,extra);
         }
         else if(bank == 0)
         {
            ret = readPageExtraCRCScratchEx77(bank,portnum,SNum,page,read_buff,extra);
         }
         break;

      default:
         break;
   }

   return ret;
}


/**
 * Reads a complete memory page with CRC verification provided by the
 * device.  Not supported by all devices.  The
 * readContinue parameter is used to eliminate the overhead in re-accessing
 * a part already being read from. For example, if pages 0 - 4 are to
 * be read, readContinue would be set to false for page 0 and would be set
 * to true for the next four calls.
 *
 * bank       to tell what memory bank of the ibutton to use.
 * portnum    the port number of the port being used for the
 *            1-Wire Network.
 * SNum       the serial number for the part that the operation is
 *            to be done on.
 * page       page number to read
 * buff       location for data read
 *
 * @return 'true' if the read was complete
 */
SMALLINT owReadPageCRC(SMALLINT bank, int portnum, uchar *SNum, int page, uchar *buff)
{
   SMALLINT ret = 0;

   switch(SNum[0] & 0x7F)
   {
      case 0x14:  //EE Memory Bank and AppReg Memory Bank
         if(bank > 0)
            ret = readPageCRCEE(bank,portnum,SNum,page,buff);
         else if(bank == 0)
            ret = readPageCRCAppReg(bank,portnum,SNum,page,buff);
         break;

      case 0x04: case 0x06: case 0x08: case 0x0A:
      case 0x0C: case 0x23:  //NV Memory Bank and Scratch Memory Bank
         if(bank > 0)
            ret = readPageCRCNV(bank,portnum,SNum,page,buff);
         else if(bank == 0)
            ret = readPageCRCScratch(bank,portnum,SNum,page,buff);
         break;

      case (0x18):  //NV Memory Bank and Scratch SHA Memory Bank
         if(bank == 3)
            ret = readPageCRCNV(bank,portnum,SNum,page,buff);
         else if(bank > 0)
            ret = readPageCRCNVCRC(bank,portnum,SNum,page,buff);
         else if(bank == 0)
            ret = readPageCRCScratch(bank,portnum,SNum,page,buff);
         break;

      case 0x1A: case 0x1D:  //NVCRC Memory Bank and Scratch Ex Memory Bank
         if(bank > 0)
            ret = readPageCRCNVCRC(bank,portnum,SNum,page,buff);
         else if(bank == 0)
            ret = readPageCRCScratch(bank,portnum,SNum,page,buff);
         break;

      case 0x21:  //NVCRC Memory Bank and Scratch CRC Memory Bank
         if(bank > 0)
            ret = readPageCRCNVCRC(bank,portnum,SNum,page,buff);
         else if(bank == 0)
            ret = readPageCRCScratch(bank,portnum,SNum,page,buff);
         break;

      case 0x33: case 0xB3:  //SHAEE Memory Bank
         ret = readPageCRCSHAEE(bank,portnum,SNum,page,buff);
         break;

      case 0x09: case 0x0B: case 0x0F: case 0x12: case 0x13:  //EPROM Memory Bank
         ret = readPageCRCEPROM(bank,portnum,SNum,page,buff);
         break;

      case 0x37: case 0x77:
         if(bank > 0)
         {
            ret = readPageCRCEE77(bank,portnum,SNum,page,buff);
         }
         else
         {
            ret = readPageCRCScratchEx77(bank,portnum,SNum,page,buff);
         }
         break;

      default:
         break;
   }

   return ret;
}

/**
 * Reads a Universal Data Packet.
 *
 * The Universal Data Packet always starts on page boundaries but
 * can end anywhere in the page.  The structure specifies the length of
 * data bytes not including the length byte and the CRC16 bytes.
 * There is one length byte. The CRC16 is first initialized to
 * the page number.  This provides a check to verify the page that
 * was intended is being read.  The CRC16 is then calculated over
 * the length and data bytes.  The CRC16 is then inverted and stored
 * low byte first followed by the high byte.  The structure is
 * used by this method to verify the data but only
 * the data payload is returned. The
 * readContinue parameter is used to eliminate the overhead in re-accessing
 * a part already being read from. For example, if pages 0 - 4 are to
 * be read, readContinue would be set to false for page 0 and would be set
 * to true for the next four calls.
 *
 * See Dallas Semiconductor Application Note 114
 * for details: http://www.dalsemi.com/datasheets/pdfs/app114.pdf
 * http://www.dalsemi.com/datasheets/pdfs/app114.pdf
 *
 * <P> Note: Using rd_cont = true  can only be used if the new
 *           read continues where the last one left off
 *           and it is inside a 'beginExclusive/endExclusive'
 *           block.
 *
 * bank       to tell what memory bank of the ibutton to use.
 * portnum    the port number of the port being used for the
 *            1-Wire Network.
 * SNum       the serial number for the part that the operation is
 *            to be done on.
 * page       page number to read packet from
 * rd_cont    true then device read
 *            is continued without re-selecting
 * buff       location for data read
 * len        the length of the data
 *
 * @return 'true' if the read was complete
 */
SMALLINT owReadPagePacket(SMALLINT bank, int portnum, uchar *SNum, int page,
                          SMALLINT rd_cont, uchar *buff, int *len)
{
   SMALLINT ret = 0;

   switch(SNum[0] & 0x7F)
   {
      case 0x14:  //EE Memory Bank and AppReg Memory Bank
         if(bank > 0)
            ret = readPagePacketEE(bank,portnum,SNum,page,rd_cont,buff,len);
         else if(bank == 0)
            ret = readPagePacketAppReg(bank,portnum,SNum,page,rd_cont,buff,len);
         break;

      case 0x04: case 0x06: case 0x08: case 0x0A:
      case 0x0C: case 0x23:  //NV Memory Bank and Scratch Memory Bank
         if(bank > 0)
            ret = readPagePacketNV(bank,portnum,SNum,page,rd_cont,buff,len);
         else if(bank == 0)
            ret = readPagePacketScratch(bank,portnum,SNum,page,rd_cont,buff,len);
         break;

      case (0x18):  //NV Memory Bank and Scratch SHA Memory Bank
         if(bank > 0)
            ret = readPagePacketNV(bank,portnum,SNum,page,rd_cont,buff,len);
         else if(bank == 0)
            ret = readPagePacketScratch(bank,portnum,SNum,page,rd_cont,buff,len);
         break;

      case 0x1A: case 0x1D:  //NVCRC Memory Bank and Scratch Ex Memory Bank
         if(bank > 0)
            ret = readPagePacketNV(bank,portnum,SNum,page,rd_cont,buff,len);
         else if(bank == 0)
            ret = readPagePacketScratch(bank,portnum,SNum,page,rd_cont,buff,len);
         break;

      case 0x21:  //NVCRC Memory Bank and Scratch CRC Memory Bank
         if(bank > 0)
            ret = readPagePacketNV(bank,portnum,SNum,page,rd_cont,buff,len);
         else if(bank == 0)
            ret = readPagePacketScratch(bank,portnum,SNum,page,rd_cont,buff,len);
         break;

      case 0x33: case 0xB3:  //SHAEE Memory Bank
         ret = readPagePacketSHAEE(bank,portnum,SNum,page,rd_cont,buff,len);
         break;

      case 0x09: case 0x0B: case 0x0F: case 0x12: case 0x13:  //EPROM Memory Bank
         ret = readPagePacketEPROM(bank,portnum,SNum,page,rd_cont,buff,len);
         break;

      case 0x37: case 0x77:
         if(bank > 0)
         {
            ret = readPagePacketEE77(bank,portnum,SNum,page,rd_cont,buff,len);
         }
         else if(bank == 0)
         {
            ret = readPagePacketScratchEx77(bank,portnum,SNum,page,rd_cont,buff,len);
         }
         break;

      default:
         break;
   }

   return ret;
}

/**
 * Reads a Universal Data Packet and extra information.  See the
 * function owReadPagePacket}
 * for a description of the packet structure.  The
 * rd_cont parameter is used to eliminate the overhead in re-accessing
 * a part already being read from. For example, if pages 0 - 4 are to
 * be read, readContinue would be set to false for page 0 and would be set
 * to true for the next four calls.
 *
 * Note: Using readContinue = true  can only be used if the new
 *       read continues where the last one left off
 *       and it is inside a 'beginExclusive/endExclusive'
 *       block.
 *
 * bank       to tell what memory bank of the ibutton to use.
 * portnum    the port number of the port being used for the
 *            1-Wire Network.
 * SNum       the serial number for the part that the operation is
 *            to be done on.
 * page       page number to read packet from
 * rd_cont    true then device read
 *            is continued without re-selecting
 * buff       location for data read
 * len        the length of the data
 * extra      location for extra info read
 *
 * @return 'true' if the read was complete
 */
SMALLINT owReadPagePacketExtra(SMALLINT bank, int portnum, uchar *SNum, int page,
                               SMALLINT rd_cont, uchar *buff, int *len, uchar *extra)
{
   SMALLINT ret = 0;

   switch(SNum[0] & 0x7F)
   {
      case 0x14:  //EE Memory Bank and AppReg Memory Bank
         if(bank > 0)
            ret = readPagePacketExtraEE(bank,portnum,SNum,page,rd_cont,buff,len,extra);
         else if(bank == 0)
            ret = readPagePacketExtraAppReg(bank,portnum,SNum,page,rd_cont,buff,len,extra);
         break;

      case 0x04: case 0x06: case 0x08: case 0x0A:
      case 0x0C: case 0x23:  //NV Memory Bank and Scratch Memory Bank
         if(bank > 0)
            ret = readPagePacketExtraNV(bank,portnum,SNum,page,rd_cont,buff,len,extra);
         else if(bank == 0)
            ret = readPagePacketExtraScratch(bank,portnum,SNum,page,rd_cont,buff,len,extra);
         break;

      case (0x18):  //NV Memory Bank and Scratch SHA Memory Bank
         if(bank == 3)
            ret = readPagePacketExtraNV(bank,portnum,SNum,page,rd_cont,buff,len,extra);
         else if(bank > 0)
            ret = readPagePacketExtraNVCRC(bank,portnum,SNum,page,rd_cont,buff,len,extra);
         else if(bank == 0)
            ret = readPagePacketExtraScratch(bank,portnum,SNum,page,rd_cont,buff,len,extra);
         break;

      case 0x1A: case 0x1D:  //NVCRC Memory Bank and Scratch Ex Memory Bank
         if(bank > 0)
            ret = readPagePacketExtraNVCRC(bank,portnum,SNum,page,rd_cont,buff,len,extra);
         else if(bank == 0)
            ret = readPagePacketExtraScratch(bank,portnum,SNum,page,rd_cont,buff,len,extra);
         break;

      case 0x21:  //NVCRC Memory Bank and Scratch CRC Memory Bank
         if(bank > 0)
            ret = readPagePacketExtraNVCRC(bank,portnum,SNum,page,rd_cont,buff,len,extra);
         else if(bank == 0)
            ret = readPagePacketExtraScratch(bank,portnum,SNum,page,rd_cont,buff,len,extra);
         break;

      case 0x33: case 0xB3:  //SHAEE Memory Bank
         ret = readPagePacketExtraSHAEE(bank,portnum,SNum,page,rd_cont,buff,len,extra);
         break;

      case 0x09: case 0x0B: case 0x0F: case 0x12: case 0x13:  //EPROM Memory Bank
         ret = readPagePacketExtraEPROM(bank,portnum,SNum,page,rd_cont,buff,len,extra);
         break;

      case 0x37: case 0x77:
         if(bank > 0)
         {
            ret = readPagePacketExtraEE77(bank,portnum,SNum,page,rd_cont,buff,len,extra);
         }
         else if(bank == 0)
         {
            ret = readPagePacketExtraScratchEx77(bank,portnum,SNum,page,rd_cont,
                                                          buff,len,extra);
         }
         break;

      default:
         break;
   }

   return ret;
}

/**
 * Writes a Universal Data Packet.  See the funtion owReadPagePacket
 * for a description of the packet structure.
 *
 * bank       to tell what memory bank of the ibutton to use.
 * portnum    the port number of the port being used for the
 *            1-Wire Network.
 * SNum       the serial number for the part that the operation is
 *            to be done on.
 * page       page number to write packet to
 * buff       data to write
 * len        number of bytes to write with a max of owGetMaxPacketDataLength
 *            elements
 *
 * @return 'true' if the write was complete
 */
SMALLINT owWritePagePacket(SMALLINT bank, int portnum, uchar *SNum, int page,
                           uchar *buff, int len)
{
   SMALLINT ret = 0;

   switch(SNum[0] & 0x7F)
   {
      case 0x14:  //EE Memory Bank and AppReg Memory Bank
         if(bank > 0)
            ret = writePagePacketEE(bank,portnum,SNum,page,buff,len);
         else if(bank == 0)
            ret = writePagePacketAppReg(bank,portnum,SNum,page,buff,len);
         break;

      case 0x04: case 0x06: case 0x08: case 0x0A:
      case 0x0C: case 0x23:  //NV Memory Bank and Scratch Memory Bank
         if(bank > 0)
            ret = writePagePacketNV(bank,portnum,SNum,page,buff,len);
         else if(bank == 0)
            ret = writePagePacketScratch(bank,portnum,SNum,page,buff,len);
         break;

      case (0x18):  //NV Memory Bank and Scratch SHA Memory Bank
         if(bank > 0)
            ret = writePagePacketNV(bank,portnum,SNum,page,buff,len);
         else if(bank == 0)
            ret = writePagePacketScratch(bank,portnum,SNum,page,buff,len);
         break;

      case 0x1A: case 0x1D:  //NVCRC Memory Bank and Scratch Ex Memory Bank
         if(bank > 0)
            ret = writePagePacketNV(bank,portnum,SNum,page,buff,len);
         else if(bank == 0)
            ret = writePagePacketScratch(bank,portnum,SNum,page,buff,len);
         break;

      case 0x21:  //NVCRC Memory Bank and Scratch CRC Memory Bank
         if(bank > 0)
            ret = writePagePacketNV(bank,portnum,SNum,page,buff,len);
         else if(bank == 0)
            ret = writePagePacketScratch(bank,portnum,SNum,page,buff,len);
         break;

      case 0x33: case 0xB3:  //SHAEE Memory Bank
         ret = writePagePacketSHAEE(bank,portnum,SNum,page,buff,len);
         break;

      case 0x09: case 0x0B: case 0x0F: case 0x12: case 0x13:  //EPROM Memory Bank
         ret = writePagePacketEPROM(bank,portnum,SNum,page,buff,len);
         break;

      case 0x37: case 0x77:
         if(bank > 0)
         {
            ret = writePagePacketEE77(bank,portnum,SNum,page,buff,len);
         }
         else if(bank == 0)
         {
            ret = writePagePacketScratchEx77(bank,portnum,SNum,page,buff,len);
         }
         break;

      default:
         break;
   }

   return ret;
}

/**
 * Gets the number of banks for a certain button given it's family code.
 *
 * family     the family code
 *
 * @return the number of banks
 */
SMALLINT owGetNumberBanks(uchar family)
{
   SMALLINT ret = 0;

   switch(family & 0x7F)
   {
      case 0x14: case 0x04: case 0x06: case 0x08: case 0x0A:
      case 0x0C: case 0x09: case 0x12: case 0x23:
         ret = 2;
         break;

      case 0x1A:
         ret = 3;
         break;

      case 0x33: case 0xB3: case 0x18: case 0x1D:
         ret = 4;
         break;

      case 0x0B: case 0x0F: case 0x13:
         ret = 5;
         break;

      case 0x21:
         ret = 6;
         break;

      case 0x37: case 0x77:
         ret = 2;
         break;

      default:
         break;
   }

   return ret;
}

/**
 * Gets the number of pages in this memory bank.
 * The page numbers are then always 0 to (owGetNumberPages() - 1).
 *
 * bank       to tell what memory bank of the ibutton to use.
 * SNum       the serial number for the part that the operation is
 *            to be done on.
 *
 * @return  number of pages in this memory bank
 */
SMALLINT owGetNumberPages(SMALLINT bank, uchar *SNum)
{
   SMALLINT ret = 0;

   switch(SNum[0] & 0x7F)
   {
      case 0x14:  //EE Memory Bank and AppReg Memory Bank
         if(bank > 0)
            ret = getNumberPagesEE(bank,SNum);
         else if(bank == 0)
            ret = getNumberPagesAppReg(bank,SNum);
         break;

      case 0x04: case 0x06: case 0x08: case 0x0A:
      case 0x0C: case 0x23:  //NV Memory Bank and Scratch Memory Bank
         if(bank > 0)
            ret = getNumberPagesNV(bank,SNum);
         else if(bank == 0)
            ret = getNumberPagesScratch(bank,SNum);
         break;

      case 0x18:  //NV Memory Bank and Scratch SHA Memory Bank
         if(bank > 0)
            ret = getNumberPagesNV(bank,SNum);
         else if(bank == 0)
            ret = getNumberPagesScratch(bank,SNum);
         break;

      case 0x1A: case 0x1D:  //NVCRC Memory Bank and Scratch Ex Memory Bank
         if(bank > 0)
            ret = getNumberPagesNV(bank,SNum);
         else if(bank == 0)
            ret = getNumberPagesScratch(bank,SNum);
         break;

      case 0x21:  //NVCRC Memory Bank and Scratch CRC Memory Bank
         if(bank > 0)
            ret = getNumberPagesNV(bank,SNum);
         else if(bank == 0)
            ret = getNumberPagesScratch(bank,SNum);
         break;

      case 0x33: case 0xB3:  //SHAEE Memory Bank
         ret = getNumberPagesSHAEE(bank,SNum);
         break;

      case 0x09: case 0x0B: case 0x0F: case 0x12: case 0x13:  //EPROM Memory Bank
         ret = getNumberPagesEPROM(bank,SNum);
         break;

      case 0x37: case 0x77:
         if(bank > 0)
         {
            ret = getNumberPagesEE77(bank,SNum);
         }
         else if(bank == 0)
         {
            ret = getNumberPagesScratchEx77(bank,SNum);
         }
         break;

      default:
         break;
   }

   return ret;
}

/**
 * Gets the size of this memory bank in bytes.
 *
 * bank       to tell what memory bank of the ibutton to use.
 * SNum       the serial number for the part that the operation is
 *            to be done on.
 *
 * @return  number of bytes in current memory bank
 */
int owGetSize(SMALLINT bank, uchar *SNum)
{
   int ret = 0;

   switch(SNum[0] & 0x7F)
   {
      case 0x14:  //EE Memory Bank and AppReg Memory Bank
         if(bank > 0)
            ret = getSizeEE(bank,SNum);
         else if(bank == 0)
            ret = getSizeAppReg(bank,SNum);
         break;

      case 0x04: case 0x06: case 0x08: case 0x0A:
      case 0x0C: case 0x23:  //NV Memory Bank and Scratch Memory Bank
         if(bank > 0)
            ret = getSizeNV(bank,SNum);
         else if(bank == 0)
            ret = getSizeScratch(bank,SNum);
         break;

      case 0x18:  //NV Memory Bank and Scratch SHA Memory Bank
         if(bank > 0)
            ret = getSizeNV(bank,SNum);
         else if(bank == 0)
            ret = getSizeScratch(bank,SNum);
         break;

      case 0x1A: case 0x1D:  //NVCRC Memory Bank and Scratch Ex Memory Bank
         if(bank > 0)
            ret = getSizeNV(bank,SNum);
         else if(bank == 0)
            ret = getSizeScratch(bank,SNum);
         break;

      case 0x21:  //NVCRC Memory Bank and Scratch CRC Memory Bank
         if(bank > 0)
            ret = getSizeNV(bank,SNum);
         else if(bank == 0)
            ret = getSizeScratch(bank,SNum);
         break;

      case 0x33: case 0xB3:  //SHAEE Memory Bank
         ret = getSizeSHAEE(bank,SNum);
         break;

      case 0x09: case 0x0B: case 0x0F: case 0x12: case 0x13:  //EPROM Memory Bank
         ret = getSizeEPROM(bank,SNum);
         break;

      case 0x37: case 0x77:
         if(bank > 0)
            ret = getSizeEE77(bank,SNum);
         else if(bank == 0)
            ret = getSizeScratchEx77(bank,SNum);
         break;

      default:
         break;
   }

   return ret;
}

/**
 * Gets raw page length in bytes in this memory bank.
 *
 * bank       to tell what memory bank of the ibutton to use.
 * SNum       the serial number for the part that the operation is
 *            to be done on.
 *
 * @return   page length in bytes in this memory bank
 */
SMALLINT owGetPageLength(SMALLINT bank, uchar *SNum)
{
   SMALLINT ret = 0;

   switch(SNum[0] & 0x7F)
   {
      case 0x14:  // EE Memory Bank and AppReg Memory Bank
         if(bank > 0)
            ret = getPageLengthEE(bank,SNum);
         else if(bank == 0)
            ret = getPageLengthAppReg(bank,SNum);
         break;

      case 0x04: case 0x06: case 0x08: case 0x0A:
      case 0x0C: case 0x23:  //NV Memory Bank and Scratch Memory Bank
         if(bank > 0)
            ret = getPageLengthNV(bank,SNum);
         else if(bank == 0)
            ret = getPageLengthScratch(bank,SNum);
         break;

      case 0x18:  //NV Memory Bank and Scratch SHA Memory Bank
         if(bank > 0)
            ret = getPageLengthNV(bank,SNum);
         else if(bank == 0)
            ret = getPageLengthScratch(bank,SNum);
         break;

      case 0x1A: case 0x1D:  //NVCRC Memory Bank and Scratch Ex Memory Bank
         if(bank > 0)
            ret = getPageLengthNV(bank,SNum);
         else if(bank == 0)
            ret = getPageLengthScratch(bank,SNum);
         break;

      case 0x21:  //NVCRC Memory Bank and Scratch CRC Memory Bank
         if(bank > 0)
            ret = getPageLengthNV(bank,SNum);
         else if(bank == 0)
            ret = getPageLengthScratch(bank,SNum);
         break;

      case 0x33: case 0xB3:  //SHAEE Memory Bank
         ret = getPageLengthSHAEE(bank,SNum);
         break;

      case 0x09: case 0x0B: case 0x0F:
      case 0x12: case 0x13:
         ret = getPageLengthEPROM(bank,SNum);
         break;

      case 0x37: case 0x77:
         if(bank > 0)
            ret = getPageLengthEE77(bank,SNum);
         else if(bank == 0)
            ret = getPageLengthScratchEx77(bank,SNum);
         break;

      default:
         break;
   }

   return ret;
}

/**
 * Gets the starting physical address of this bank.  Physical
 * banks are sometimes sub-divided into logical banks due to changes
 * in attributes.  Note that this method is for information only.  The read
 * and write methods will automatically calculate the physical address
 * when writing to a logical memory bank.
 *
 * bank       to tell what memory bank of the ibutton to use.
 * SNum       the serial number for the part that the operation is
 *            to be done on.
 *
 * @return  physical starting address of this logical bank
 */
int owGetStartingAddress(SMALLINT bank, uchar *SNum)
{
   int ret = 0;

   switch(SNum[0] & 0x7F)
   {
      case 0x14:  //EE Memory Bank and AppReg Memory Bank
         if(bank > 0)
            ret = getStartingAddressEE(bank,SNum);
         else if(bank == 0)
            ret = getStartingAddressAppReg(bank,SNum);
         break;

      case 0x04: case 0x06: case 0x08: case 0x0A:
      case 0x0C: case 0x23:  //NV Memory Bank and Scratch Memory Bank
         if(bank > 0)
            ret = getStartingAddressNV(bank,SNum);
         else if(bank == 0)
            ret = getStartingAddressScratch(bank,SNum);
         break;

      case 0x18:  //NV Memory Bank and Scratch SHA Memory Bank
         if(bank > 0)
            ret = getStartingAddressNV(bank,SNum);
         else if(bank == 0)
            ret = getStartingAddressScratch(bank,SNum);
         break;

      case 0x1A: case 0x1D:  //NVCRC Memory Bank and Scratch Ex Memory Bank
         if(bank > 0)
            ret = getStartingAddressNV(bank,SNum);
         else if(bank == 0)
            ret = getStartingAddressScratch(bank,SNum);
         break;

      case 0x21:  //NVCRC Memory Bank and Scratch CRC Memory Bank
         if(bank > 0)
            ret = getStartingAddressNV(bank,SNum);
         else if(bank == 0)
            ret = getStartingAddressScratch(bank,SNum);
         break;

      case 0x33: case 0xB3:  //SHAEE Memory Bank
         ret = getStartingAddressSHAEE(bank,SNum);
         break;

      case 0x09: case 0x0B: case 0x0F: case 0x12: case 0x13:  //EPROM Memory Bank
         ret = getStartingAddressEPROM(bank,SNum);
         break;

      case 0x37: case 0x77:
         if(bank > 0)
            ret = getStartingAddressEE77(bank,SNum);
         else if(bank == 0)
            ret = getStartingAddressScratchEx77(bank,SNum);
         break;

      default:
         break;
   }

   return ret;
}

/**
 * Gets a string description of this memory bank.
 *
 * bank       to tell what memory bank of the ibutton to use.
 * SNum       the serial number for the part that the operation is
 *            to be done on.
 *
 * @return  the memory bank description
 */
char *owGetBankDescription(SMALLINT bank, uchar *SNum)
{
   switch(SNum[0] & 0x7F)
   {
      case 0x14:  //EE Memory Bank and AppReg Memory Bank
         if(bank > 0)
            return getBankDescriptionEE(bank,SNum);
         else if(bank == 0)
            return getBankDescriptionAppReg(bank,SNum);
         break;

      case 0x04: case 0x06: case 0x08: case 0x0A:
      case 0x0C: case 0x23:  //NV Memory Bank and Scratch Memory Bank
         if(bank > 0)
            return getBankDescriptionNV(bank,SNum);
         else if(bank == 0)
            return getBankDescriptionScratch(bank,SNum);
         break;

      case 0x18:  //NV Memory Bank and Scratch SHA Memory Bank
         if(bank > 0)
            return getBankDescriptionNV(bank,SNum);
         else if(bank == 0)
            return getBankDescriptionScratch(bank,SNum);
         break;

      case 0x1A: case 0x1D:  //NVCRC Memory Bank and Scratch Ex Memory Bank
         if(bank > 0)
            return getBankDescriptionNV(bank,SNum);
         else if(bank == 0)
            return getBankDescriptionScratch(bank,SNum);
         break;

      case 0x21:  //NVCRC Memory Bank and Scratch CRC Memory Bank
         if(bank > 0)
            return getBankDescriptionNV(bank,SNum);
         else if(bank == 0)
            return getBankDescriptionScratch(bank,SNum);
         break;

      case 0x33: case 0xB3:  //SHAEE Memory Bank
         return getBankDescriptionSHAEE(bank,SNum);
         break;

      case 0x09: case 0x0B: case 0x0F: case 0x12: case 0x13:  //EPROM Memory Bank
         return getBankDescriptionEPROM(bank,SNum);
         break;

      case 0x37: case 0x77:
         if(bank > 0)
            return getBankDescriptionEE77(bank,SNum);
         else if(bank == 0)
            return getBankDescriptionScratchEx77(bank,SNum);
         break;

      default:
         break;
   }

   return "";
}

/**
 * Retrieves the Dallas Semiconductor part number of the 1-Wire device
 * as a String.  For example 'Crypto iButton' or 'DS1992'.
 *
 * SNum       the serial number for the part that the operation is
 *            to be done on.
 *
 * @return 1-Wire device name
 */
char *owGetName(uchar *SNum)
{
   switch(SNum[0] & 0x7F)
   {
      case 0x14:
         return "DS1971";
         break;

      case 0x04:
         return "DS1994";
         break;

      case 0x06:
         return "DS1993";
         break;

      case 0x08:
         return "DS1992";
         break;

      case 0x09:
         return "DS1982";
         break;

      case 0x0A:
         return "DS1995";
         break;

      case 0x0B:
         return "DS1985";
         break;

      case 0x0C:
         return "DS1996";
         break;

      case 0x18:
         return "DS1963S";
         break;

      case 0x1A:
         return "DS1963L";
         break;

      case 0x1D:
         return "DS2423";
         break;

      case 0x23:
         return "DS1973";
         break;

      case 0x33: case 0xB3:
         return "DS1961S";
         break;

      case 0x37: case 0x77:
         return "DS1977";
         break;

      default:
         return "No Name";
   }
}

/**
 * Retrieves the alternate Dallas Semiconductor part numbers or names.
 * A 'family' of 1-Wire Network devices may have more than one part number
 * depending on packaging.  There can also be nicknames such as
 * 'Crypto iButton'.
 *
 * SNum       the serial number for the part that the operation is
 *            to be done on.
 *
 * @return 1-Wire device alternate names
 */
char *owGetAlternateName(uchar *SNum)
{
   switch(SNum[0] & 0x7F)
   {
      case 0x14:
         return "DS2430A";
         break;

      case 0x04:
         return "DS2404, Time-in-a-can, DS1427";
         break;

      case 0x09:
         return "DS2502";
         break;

      case 0x0B:
         return "DS2505";
         break;

      case 0x18:
         return "SHA-1 iButton";
         break;

      case 0x1A:
         return "Monetary iButton";
         break;

      case 0x23:
         return "DS2433";
         break;

      case 0x33: case 0xB3:
         return "DS2432";
         break;

      default:
         return "No Alternate Name";
   }
}

/**
 * Retrieves a short description of the function of the 1-Wire device type.
 *
 * SNum       the serial number for the part that the operation is
 *            to be done on.
 *
 * @return device functional description
 */
char *owGetDescription(uchar *SNum)
{
   switch(SNum[0] & 0x7F)
   {
      case 0x14:
         return "Electrically Erasable Programmable Read Only Memory\n"
                "*\t(EEPROM) organized as one page of 256 bits and 64 bit\n"
                "*\tone-time programmable application register.";
         break;

      case 0x04:
         return "4096 bit read/write nonvolatile memory partitioned\n"
                "*\tinto sixteen pages of 256 bits each and a real\n"
                "*\ttime clock/calendar in binary format.";
         break;

      case 0x06:
         return "4096 bit read/write nonvolatile memory partitioned\n"
                "*\tinto sixteen pages of 256 bits each.";
         break;

      case 0x08:
         return "1024 bit read/write nonvolatile memory partitioned\n"
                "*\tinto four pages of 256 bits each.";
         break;

      case 0x09:
         return "1024 bit Electrically Programmable Read Only Memory\n"
                "*\t(EPROM) partitioned into four 256 bit pages.\n"
                "*\tEach memory page can be permanently write-protected\n"
                "*\tto prevent tampering.  Architecture allows software\n"
                "*\tto patch data by supersending a used page in favor of\n"
                "*\ta newly programmed page.";
         break;

      case 0x0A:
         return "16384 bit read/write nonvolatile memory partitioned\n"
                "*\tinto sixty-four pages of 256 bits each.";
         break;

      case 0x0B:
         return "16384 bit Electrically Programmable Read Only Memory\n"
                "*\t(EPROM) partitioned into sixty-four 256 bit pages.\n"
                "*\tEach memory page can be permanently write-protected\n"
                "*\tto prevent tampering.  Architecture allows software\n"
                "*\tto patch data by supersending a used page in favor of\n"
                "*\ta newly programmed page.\n";
         break;

      case 0x0C:
         return "65536 bit read/write nonvolatile memory partitioned\n"
                "*\tinto two-hundred fifty-six pages of 256 bits each.";
         break;

      case 0x18:
         return "4096 bits of read/write nonvolatile memory. Memory\n"
                "*\tis partitioned into sixteen pages of 256 bits each.\n"
                "*\tHas overdrive mode.  One-chip 512-bit SHA-1 engine\n"
                "*\tand secret storage.\n";
         break;

      case 0x1A:
         return "4096 bit read/write nonvolatile memory with\n"
                "*\tfour 32-bit read-only non rolling-over page write\n"
                "*\tcycle counters and tamper-detect bits for small\n"
                "*\tmoney storage.\n";
         break;

      case 0x1D:
         return "1-Wire counter with 4096 bits of read/write, nonvolatile\n"
                "*\tmemory.  Memory is partitioned into sixteen pages of 256\n"
                "*\tbits each.  256 bit scratchpad ensures data transfer\n"
                "*\tintegrity.  Has overdrive mode.  Last four pages each have\n"
                "*\t32 bit read-only non rolling-over counter.  The first two\n"
                "*\tcounters increment on a page write cycle and the second two\n"
                "*\thave active-low external triggers.\n";
         break;

      case 0x23:
         return "4096 bit Electrically Erasable Programmable Read\n"
                "*\tOnly Memory (EEPROM) organized as sixteen pages of 256 bits.";
         break;

      case 0x33: case 0xB3:
         return "1K-Bit protected 1-Wire EEPROM with SHA-1 Engine.";
         break;

      case 0x37: case 0x77:
         return "32Kbyte EEPROM with read-only password and full\n"
                "*\taccess password.";
         break;

      default:
         return "No given description";
   }
}

/**
 * Checks to see if this memory bank is general purpose
 * user memory.  If it is NOT then it may be Memory-Mapped and writing
 * values to this memory may affect the behavior of the 1-Wire
 * device.
 *
 * bank       to tell what memory bank of the ibutton to use.
 * SNum       the serial number for the part that the operation is
 *            to be done on.
 *
 * @return  true if this memory bank is general purpose
 */
SMALLINT owIsGeneralPurposeMemory(SMALLINT bank, uchar *SNum)
{
   SMALLINT ret = 0;

   switch(SNum[0] & 0x7F)
   {
      case 0x14:  //EE Memory Bank and AppReg Memory Bank
         if(bank > 0)
            ret = isGeneralPurposeMemoryEE(bank,SNum);
         else if(bank == 0)
            ret = isGeneralPurposeMemoryAppReg(bank,SNum);
         break;

      case 0x04: case 0x06: case 0x08: case 0x0A:
      case 0x0C: case 0x23:  //NV Memory Bank and Scratch Memory Bank
         if(bank > 0)
            ret = isGeneralPurposeMemoryNV(bank,SNum);
         else if(bank == 0)
            ret = isGeneralPurposeMemoryScratch(bank,SNum);
         break;

      case 0x18:  //NV Memory Bank and Scratch SHA Memory Bank
         if(bank > 0)
            ret = isGeneralPurposeMemoryNV(bank,SNum);
         else if(bank == 0)
            ret = isGeneralPurposeMemoryScratch(bank,SNum);
         break;

      case 0x1A: case 0x1D:  //NVCRC Memory Bank and Scratch Ex Memory Bank
         if(bank > 0)
            ret = isGeneralPurposeMemoryNV(bank,SNum);
         else if(bank == 0)
            ret = isGeneralPurposeMemoryScratch(bank,SNum);
         break;

      case 0x21:  //NVCRC Memory Bank and Scratch CRC Memory Bank
         if(bank > 0)
            ret = isGeneralPurposeMemoryNV(bank,SNum);
         else if(bank == 0)
            ret = isGeneralPurposeMemoryScratch(bank,SNum);
         break;

      case 0x33: case 0xB3:  //SHAEE Memory Bank
         ret = isGeneralPurposeMemorySHAEE(bank,SNum);
         break;

      case 0x09: case 0x0B: case 0x0F: case 0x12: case 0x13:  //EPROM Memory Bank
         ret = isGeneralPurposeMemoryEPROM(bank,SNum);
         break;

      case 0x37: case 0x77:
         if(bank > 0)
            ret = isGeneralPurposeMemoryEE77(bank,SNum);
         else if(bank == 0)
            ret = isGeneralPurposeMemoryScratchEx77(bank,SNum);
         break;

      default:
         break;
   }

   return ret;
}

/**
 * Checks to see if this memory bank is read/write.
 *
 * bank       to tell what memory bank of the ibutton to use.
 * SNum       the serial number for the part that the operation is
 *            to be done on.
 *
 * @return    true if this memory bank is read/write
 */
SMALLINT owIsReadWrite(SMALLINT bank, int portnum, uchar *SNum)
{
   SMALLINT ret = 0;

   switch(SNum[0] & 0x7F)
   {
      case 0x14:  //EE Memory Bank and AppReg Memory Bank
         if(bank > 0)
            ret = isReadWriteEE(bank,portnum,SNum);
         else if(bank == 0)
            ret = isReadWriteAppReg(bank,portnum,SNum);
         break;

      case 0x04: case 0x06: case 0x08: case 0x0A:
      case 0x0C: case 0x23:  //NV Memory Bank and Scratch Memory Bank
         if(bank > 0)
            ret = isReadWriteNV(bank,portnum,SNum);
         else if(bank == 0)
            ret = isReadWriteScratch(bank,portnum,SNum);
         break;

      case 0x18:  //NV Memory Bank and Scratch SHA Memory Bank
         if(bank > 0)
            ret = isReadWriteNV(bank,portnum,SNum);
         else if(bank == 0)
            ret = isReadWriteScratch(bank,portnum,SNum);
         break;

      case 0x1A: case 0x1D:  //NVCRC Memory Bank and Scratch Ex Memory Bank
         if(bank > 0)
            ret = isReadWriteNV(bank,portnum,SNum);
         else if(bank == 0)
            ret = isReadWriteScratch(bank,portnum,SNum);
         break;

      case 0x21:  //NVCRC Memory Bank and Scratch CRC Memory Bank
         if(bank > 0)
            ret = isReadWriteNV(bank,portnum,SNum);
         else if(bank == 0)
            ret = isReadWriteScratch(bank,portnum,SNum);
         break;

      case 0x33: case 0xB3:  //SHAEE Memory Bank
         ret = isReadWriteSHAEE(bank,portnum,SNum);
         break;

      case 0x09: case 0x0B: case 0x0F: case 0x12: case 0x13:  //EPROM Memory Bank
         ret = isReadWriteEPROM(bank,portnum,SNum);
         break;

      case 0x37: case 0x77:
         if(bank > 0)
            ret = isReadWriteEE77(bank,portnum,SNum);
         else if(bank == 0)
            ret = isReadWriteScratchEx77(bank,portnum,SNum);
         break;

      default:
         break;
   }

   return ret;
}

/**
 * Checks to see if this memory bank is write once such
 * as with EPROM technology.
 *
 * bank       to tell what memory bank of the ibutton to use.
 * SNum       the serial number for the part that the operation is
 *            to be done on.
 *
 * @return    true if this memory bank can only be written once
 */
SMALLINT owIsWriteOnce(SMALLINT bank, int portnum, uchar *SNum)
{
   SMALLINT ret = 0;

   switch(SNum[0] & 0x7F)
   {
      case 0x14:  //EE Memory Bank and AppReg Memory Bank
         if(bank > 0)
            ret = isWriteOnceEE(bank,portnum,SNum);
         else if(bank == 0)
            ret = isWriteOnceAppReg(bank,portnum,SNum);
         break;

      case 0x04: case 0x06: case 0x08: case 0x0A:
      case 0x0C: case 0x23:  //NV Memory Bank and Scratch Memory Bank
         if(bank > 0)
            ret = isWriteOnceNV(bank,portnum,SNum);
         else if(bank == 0)
            ret = isWriteOnceScratch(bank,portnum,SNum);
         break;

      case 0x18:  //NV Memory Bank and Scratch SHA Memory Bank
         if(bank > 0)
            ret = isWriteOnceNV(bank,portnum,SNum);
         else if(bank == 0)
            ret = isWriteOnceScratch(bank,portnum,SNum);
         break;

      case 0x1A: case 0x1D:  //NVCRC Memory Bank and Scratch Ex Memory Bank
         if(bank > 0)
            ret = isWriteOnceNV(bank,portnum,SNum);
         else if(bank == 0)
            ret = isWriteOnceScratch(bank,portnum,SNum);
         break;

      case 0x21:  //NVCRC Memory Bank and Scratch CRC Memory Bank
         if(bank > 0)
            ret = isWriteOnceNV(bank,portnum,SNum);
         else if(bank == 0)
            ret = isWriteOnceScratch(bank,portnum,SNum);
         break;

      case 0x33: case 0xB3:  //SHAEE Memory Bank
         ret = isWriteOnceSHAEE(bank,portnum,SNum);
         break;

      case 0x09: case 0x0B: case 0x0F: case 0x12: case 0x13:  //EPROM Memory Bank
         ret = isWriteOnceEPROM(bank,portnum,SNum);
         break;

      case 0x37: case 0x77:
         if(bank > 0)
            ret = isWriteOnceEE77(bank,portnum,SNum);
         else if(bank == 0)
            ret = isWriteOnceScratchEx77(bank,portnum,SNum);
         break;

      default:
         break;
   }

   return ret;
}

/**
 * Query to see if current memory bank is read only.
 *
 * bank       to tell what memory bank of the ibutton to use.
 * SNum       the serial number for the part that the operation is
 *            to be done on.
 *
 * @return    true if current memory bank can only be read
 */
SMALLINT owIsReadOnly(SMALLINT bank, int portnum, uchar *SNum)
{
   SMALLINT ret = 0;

   switch(SNum[0] & 0x7F)
   {
      case 0x14:  //EE Memory Bank and AppReg Memory Bank
         if(bank > 0)
            ret = isReadOnlyEE(bank,portnum,SNum);
         else if(bank == 0)
            ret = isReadOnlyAppReg(bank,portnum,SNum);
         break;

      case 0x04: case 0x06: case 0x08: case 0x0A:
      case 0x0C: case 0x23:  //NV Memory Bank and Scratch Memory Bank
         if(bank > 0)
            ret = isReadOnlyNV(bank,portnum,SNum);
         else if(bank == 0)
            ret = isReadOnlyScratch(bank,portnum,SNum);
         break;

      case 0x1A: case 0x1D:  //NVCRC Memory Bank and Scratch Ex Memory Bank
         if(bank > 0)
            ret = isReadOnlyNV(bank,portnum,SNum);
         else if(bank == 0)
            ret = isReadOnlyScratch(bank,portnum,SNum);
         break;

      case 0x21:  //NVCRC Memory Bank and Scratch CRC Memory Bank
         if(bank > 0)
            ret = isReadOnlyNV(bank,portnum,SNum);
         else if(bank == 0)
            ret = isReadOnlyScratch(bank,portnum,SNum);
         break;

      case 0x33: case 0xB3:  //SHAEE Memory Bank
         ret = isReadOnlySHAEE(bank,portnum,SNum);
         break;

      case 0x09: case 0x0B: case 0x0F: case 0x12: case 0x13:  //EPROM Memory Bank
         ret = isReadOnlyEPROM(bank,portnum,SNum);
         break;

      case 0x37: case 0x77:
         if(bank > 0)
            ret = isReadOnlyEE77(bank,portnum,SNum);
         else if(bank == 0)
            ret = isReadOnlyScratchEx77(bank,portnum,SNum);
         break;

      default:
         break;
   }

   return ret;
}

/**
 * Query to see if current memory bank non-volatile.  Memory is
 * non-volatile if it retains its contents even when removed from
 * the 1-Wire network.
 *
 * bank       to tell what memory bank of the ibutton to use.
 * SNum       the serial number for the part that the operation is
 *            to be done on.
 *
 * @return    true if current memory bank non volatile.
 */
SMALLINT owIsNonVolatile(SMALLINT bank, uchar *SNum)
{
   SMALLINT ret = 0;

   switch(SNum[0] & 0x7F)
   {
      case 0x14:  //EE Memory Bank and AppReg Memory Bank
         if(bank > 0)
            ret = isNonVolatileEE(bank,SNum);
         else if(bank == 0)
            ret = isNonVolatileAppReg(bank,SNum);
         break;

      case 0x04: case 0x06: case 0x08: case 0x0A:
      case 0x0C: case 0x23:  //NV Memory Bank and Scratch Memory Bank
         if(bank > 0)
            ret = isNonVolatileNV(bank,SNum);
         else if(bank == 0)
            ret = isNonVolatileScratch(bank,SNum);
         break;

      case 0x18:  //NV Memory Bank and Scratch SHA Memory Bank
         if(bank > 0)
            ret = isNonVolatileNV(bank,SNum);
         else if(bank == 0)
            ret = isNonVolatileScratch(bank,SNum);
         break;

      case 0x1A: case 0x1D:  //NVCRC Memory Bank and Scratch Ex Memory Bank
         if(bank > 0)
            ret = isNonVolatileNV(bank,SNum);
         else if(bank == 0)
            ret = isNonVolatileScratch(bank,SNum);
         break;

      case 0x21:  //NVCRC Memory Bank and Scratch CRC Memory Bank
         if(bank > 0)
            ret = isNonVolatileNV(bank,SNum);
         else if(bank == 0)
            ret = isNonVolatileScratch(bank,SNum);
         break;

      case 0x33: case 0xB3: //SHAEE Memory Bank  //SHAEE Memory Bank
         ret = isNonVolatileSHAEE(bank,SNum);
         break;

      case 0x09: case 0x0B: case 0x0F: case 0x12: case 0x13:  //EPROM Memory Bank
         ret = isNonVolatileEPROM(bank,SNum);
         break;

      case 0x37: case 0x77:
         if(bank > 0)
            ret = isNonVolatileEE77(bank,SNum);
         else if(bank == 0)
            ret = isNonVolatileScratchEx77(bank,SNum);
         break;

      default:
         break;
   }

   return ret;
}

/**
 * Checks to see if this  memory bank requires a
 * 'ProgramPulse' in order to write.
 *
 * bank       to tell what memory bank of the ibutton to use.
 * SNum       the serial number for the part that the operation is
 *            to be done on.
 *
 * @return    true if writing to this memory bank
 *            requires a 'ProgramPulse' from the 1-Wire Adapter.
 */
SMALLINT owNeedsProgramPulse(SMALLINT bank, uchar *SNum)
{
   SMALLINT ret = 0;

   switch(SNum[0] & 0x7F)
   {
      case 0x14:  //EE Memory Bank and AppReg Memory Bank
         if(bank > 0)
            ret = needsProgramPulseEE(bank,SNum);
         else if(bank == 0)
            ret = needsProgramPulseAppReg(bank,SNum);
         break;

      case 0x04: case 0x06: case 0x08: case 0x0A:
      case 0x0C: case 0x23:  //NV Memory Bank and Scratch Memory Bank
         if(bank > 0)
            ret = needsProgramPulseNV(bank,SNum);
         else if(bank == 0)
            ret = needsProgramPulseScratch(bank,SNum);
         break;

      case 0x18:  //NV Memory Bank and Scratch SHA Memory Bank
         if(bank > 0)
            ret = needsProgramPulseNV(bank,SNum);
         else if(bank == 0)
            ret = needsProgramPulseScratch(bank,SNum);
         break;

      case 0x1A: case 0x1D:  //NVCRC Memory Bank and Scratch Ex Memory Bank
         if(bank > 0)
            ret = needsProgramPulseNV(bank,SNum);
         else if(bank == 0)
            ret = needsProgramPulseScratch(bank,SNum);
         break;

      case 0x21:  //NVCRC Memory Bank and Scratch CRC Memory Bank
         if(bank > 0)
            ret = needsProgramPulseNV(bank,SNum);
         else if(bank == 0)
            ret = needsProgramPulseScratch(bank,SNum);
         break;

      case 0x33: case 0xB3:  //SHAEE Memory Bank
         ret = needsProgramPulseSHAEE(bank,SNum);
         break;

      case 0x09: case 0x0B: case 0x0F: case 0x12: case 0x13:  //EPROM Memory Bank
         ret = needsProgramPulseEPROM(bank,SNum);
         break;

      case 0x37: case 0x77:
         if(bank > 0)
            ret = needsProgramPulseEE77(bank,SNum);
         else if(bank == 0)
            ret = needsProgramPulseScratchEx77(bank,SNum);
         break;

      default:
         break;
   }

   return ret;
}

/**
 * Checks to see if this memory bank requires 'PowerDelivery'
 * in order to write.
 *
 * bank       to tell what memory bank of the ibutton to use.
 * SNum       the serial number for the part that the operation is
 *            to be done on.
 *
 * @return    true if writing to this memory bank
 *            requires 'PowerDelivery' from the 1-Wire Adapter
 */
SMALLINT owNeedsPowerDelivery(SMALLINT bank, uchar *SNum)
{
   SMALLINT ret = 0;

   switch(SNum[0] & 0x7F)
   {
      case 0x14:  //EE Memory Bank and AppReg Memory Bank
         if(bank > 0)
            ret = needsPowerDeliveryEE(bank,SNum);
         else if(bank == 0)
            ret = needsPowerDeliveryAppReg(bank,SNum);
         break;

      case 0x04: case 0x06: case 0x08: case 0x0A:
      case 0x0C: case 0x23:  //NV Memory Bank and Scratch Memory Bank
         if(bank > 0)
            ret = needsPowerDeliveryNV(bank,SNum);
         else if(bank == 0)
            ret = needsPowerDeliveryScratch(bank,SNum);
         break;

      case 0x18:  //NV Memory Bank and Scratch SHA Memory Bank
         if(bank > 0)
            ret = needsPowerDeliveryNV(bank,SNum);
         else if(bank == 0)
            ret = needsPowerDeliveryScratch(bank,SNum);
         break;

      case 0x1A: case 0x1D:  //NVCRC Memory Bank and Scratch Ex Memory Bank
         if(bank > 0)
            ret = needsPowerDeliveryNV(bank,SNum);
         else if(bank == 0)
            ret = needsPowerDeliveryScratch(bank,SNum);
         break;

      case 0x21:  //NVCRC Memory Bank and Scratch CRC Memory Bank
         if(bank > 0)
            ret = needsPowerDeliveryNV(bank,SNum);
         else if(bank == 0)
            ret = needsPowerDeliveryScratch(bank,SNum);
         break;

      case 0x33: case 0xB3:  //SHAEE Memory Bank
         ret = needsPowerDeliverySHAEE(bank,SNum);
         break;

      case 0x09: case 0x0B: case 0x0F: case 0x12: case 0x13:  //EPROM Memory Bank
         ret = needsPowerDeliveryEPROM(bank,SNum);
         break;

      case 0x37: case 0x77:
         if(bank > 0)
            ret = needsPowerDeliveryEE77(bank,SNum);
         else if(bank == 0)
            ret = needsPowerDeliveryScratchEx77(bank,SNum);
         break;

      default:
         break;
   }

   return ret;
}

/**
 * Checks to see if this memory bank's pages deliver extra
 * information outside of the normal data space,  when read.  Examples
 * of this may be a redirection byte, counter, tamper protection
 * bytes, or SHA-1 result.  If this method returns true then the
 * methods with an 'extraInfo' parameter can be used:
 * owReadPageExtra,
 * owReadPageExtraCRC, and
 * owReadPagePacketExtra.
 *
 * bank       to tell what memory bank of the ibutton to use.
 * SNum       the serial number for the part that the operation is
 *            to be done on.
 *
 * @return  <CODE> true </CODE> if reading the this memory bank's
 *                 pages provides extra information
 */
SMALLINT owHasExtraInfo(SMALLINT bank, uchar *SNum)
{
   SMALLINT ret = 0;

   switch(SNum[0] & 0x7F)
   {
      case 0x14:  //EE Memory Bank and AppReg Memory Bank
         if(bank > 0)
            ret = hasExtraInfoEE(bank,SNum);
         else if(bank == 0)
            ret = hasExtraInfoAppReg(bank,SNum);
         break;

      case 0x04: case 0x06: case 0x08: case 0x0A:
      case 0x0C: case 0x23:  //NV Memory Bank and Scratch Memory Bank
         if(bank > 0)
            ret = hasExtraInfoNV(bank,SNum);
         else if(bank == 0)
            ret = hasExtraInfoScratch(bank,SNum);
         break;

      case 0x18:  //NV Memory Bank and Scratch SHA Memory Bank
         if(bank > 0)
            ret = hasExtraInfoNV(bank,SNum);
         else if(bank == 0)
            ret = hasExtraInfoScratch(bank,SNum);
         break;

      case 0x1A: case 0x1D:  //NVCRC Memory Bank and Scratch Ex Memory Bank
         if(bank > 0)
            ret = hasExtraInfoNV(bank,SNum);
         else if(bank == 0)
            ret = hasExtraInfoScratch(bank,SNum);
         break;

      case 0x21:  //NVCRC Memory Bank and Scratch CRC Memory Bank
         if(bank > 0)
            ret = hasExtraInfoNV(bank,SNum);
         else if(bank == 0)
            ret = hasExtraInfoScratch(bank,SNum);
         break;

      case 0x33: case 0xB3:  //SHAEE Memory Bank
         ret = hasExtraInfoSHAEE(bank,SNum);
         break;

      case 0x09: case 0x0B: case 0x0F: case 0x12: case 0x13:  //EPROM Memory Bank
         ret = hasExtraInfoEPROM(bank,SNum);
         break;

      case 0x37: case 0x77:
         if(bank > 0)
            ret = hasExtraInfoEE77(bank,SNum);
         else if(bank == 0)
            ret = hasExtraInfoScratchEx77(bank,SNum);
         break;

      default:
         break;
   }

   return ret;
}

/**
 * Gets the length in bytes of extra information that
 * is read when reading a page in this memory bank.
 *
 * bank       to tell what memory bank of the ibutton to use.
 * SNum       the serial number for the part that the operation is
 *            to be done on.
 *
 * @return  number of bytes in Extra Information read when reading
 *          pages from this memory bank
 */
SMALLINT owGetExtraInfoLength(SMALLINT bank, uchar *SNum)
{
   SMALLINT ret = 0;

   switch(SNum[0] & 0x7F)
   {
      case 0x14:  //EE Memory Bank and AppReg Memory Bank
         if(bank > 0)
            ret = getExtraInfoLengthEE(bank,SNum);
         else if(bank == 0)
            ret = getExtraInfoLengthAppReg(bank,SNum);
         break;

      case 0x04: case 0x06: case 0x08: case 0x0A:
      case 0x0C: case 0x23:  //NV Memory Bank and Scratch Memory Bank
         if(bank > 0)
            ret = getExtraInfoLengthNV(bank,SNum);
         else if(bank == 0)
            ret = getExtraInfoLengthScratch(bank,SNum);
         break;

      case 0x18:  //NV Memory Bank and Scratch SHA Memory Bank
         if(bank > 0)
            ret = getExtraInfoLengthNV(bank,SNum);
         else if(bank == 0)
            ret = getExtraInfoLengthScratch(bank,SNum);
         break;

      case 0x1A: case 0x1D:  //NVCRC Memory Bank and Scratch Ex Memory Bank
         if(bank > 0)
            ret = getExtraInfoLengthNV(bank,SNum);
         else if(bank == 0)
            ret = getExtraInfoLengthScratch(bank,SNum);
         break;

      case 0x21:  //NVCRC Memory Bank and Scratch CRC Memory Bank
         if(bank > 0)
            ret = getExtraInfoLengthNV(bank,SNum);
         else if(bank == 0)
            ret = getExtraInfoLengthScratch(bank,SNum);
         break;

      case 0x33: case 0xB3:  //SHAEE Memory Bank
         ret = getExtraInfoLengthSHAEE(bank,SNum);
         break;

      case 0x09: case 0x0B: case 0x0F: case 0x12: case 0x13:  //EPROM Memory Bank
         ret = getExtraInfoLengthEPROM(bank,SNum);
         break;

      case 0x37: case 0x77:
         if(bank > 0)
            ret = getExtraInfoLengthEE77(bank,SNum);
         else if(bank == 0)
            ret = getExtraInfoLengthScratchEx77(bank,SNum);
         break;

      default:
         break;
   }

   return ret;
}

/**
 * Gets a string description of what is contained in
 * the Extra Information returned when reading pages in this
 * memory bank.
 *
 * bank       to tell what memory bank of the ibutton to use.
 * SNum       the serial number for the part that the operation is
 *            to be done on.
 *
 * @return extra information description.
 */
char *owGetExtraInfoDesc(SMALLINT bank, uchar *SNum)
{
   switch(SNum[0] & 0x7F)
   {
      case 0x14:  //EE Memory Bank and AppReg Memory Bank
         if(bank > 0)
            return getExtraInfoDescEE(bank,SNum);
         else if(bank == 0)
            return getExtraInfoDescAppReg(bank,SNum);
         break;

      case 0x04: case 0x06: case 0x08: case 0x0A:
      case 0x0C: case 0x23:  //NV Memory Bank and Scratch Memory Bank
         if(bank > 0)
            return getExtraInfoDescNV(bank,SNum);
         else if(bank == 0)
            return getExtraInfoDescScratch(bank,SNum);
         break;

      case 0x18:  //NV Memory Bank and Scratch SHA Memory Bank
         if(bank > 0)
            return getExtraInfoDescNV(bank,SNum);
         else if(bank == 0)
            return getExtraInfoDescScratch(bank,SNum);
         break;

      case 0x1A: case 0x1D:  //NVCRC Memory Bank and Scratch Ex Memory Bank
         if(bank > 0)
            return getExtraInfoDescNV(bank,SNum);
         else if(bank == 0)
            return getExtraInfoDescScratch(bank,SNum);
         break;

      case 0x21:  //NVCRC Memory Bank and Scratch CRC Memory Bank
         if(bank > 0)
            return getExtraInfoDescNV(bank,SNum);
         else if(bank == 0)
            return getExtraInfoDescScratch(bank,SNum);
         break;

      case 0x33: case 0xB3:  //SHAEE Memory Bank
         return getExtraInfoDescSHAEE(bank,SNum);
         break;

      case 0x09: case 0x0B: case 0x0F: case 0x12: case 0x13:  //EPROM Memory Bank
         return getExtraInfoDescEPROM(bank,SNum);
         break;

      case 0x37: case 0x77:
         if(bank > 0)
            return getExtraInfoDescEE77(bank,SNum);
         else if(bank == 0)
            return getExtraInfoDescScratchEx77(bank,SNum);
         break;

      default:
         break;
   }

   return "";
}

/**
 * Gets Maximum data page length in bytes for a packet
 * read or written in this memory bank.  See the
 * owReadPagePacket and owWritePagePacket
 * function.  This function is only usefull
 * if this memory bank is general purpose memory.
 *
 * bank       to tell what memory bank of the ibutton to use.
 * SNum       the serial number for the part that the operation is
 *            to be done on.
 *
 * @return  max packet page length in bytes in this memory bank
 */
SMALLINT owGetMaxPacketDataLength(SMALLINT bank, uchar *SNum)
{
   SMALLINT ret = 0;

   switch(SNum[0] & 0x7F)
   {
      case 0x14:  //EE Memory Bank and AppReg Memory Bank
         if(bank > 0)
            ret = getMaxPacketDataLengthEE(bank,SNum);
         else if(bank == 0)
            ret = getMaxPacketDataLengthAppReg(bank,SNum);
         break;

      case 0x04: case 0x06: case 0x08: case 0x0A:
      case 0x0C: case 0x23:  //NV Memory Bank and Scratch Memory Bank
         if(bank > 0)
            ret = getMaxPacketDataLengthNV(bank,SNum);
         else if(bank == 0)
            ret = getMaxPacketDataLengthScratch(bank,SNum);
         break;

      case 0x1A: case 0x1D:  //NVCRC Memory Bank and Scratch Ex Memory Bank
         if(bank > 0)
            ret = getMaxPacketDataLengthNV(bank,SNum);
         else if(bank == 0)
            ret = getMaxPacketDataLengthScratch(bank,SNum);
         break;

      case 0x21:  //NVCRC Memory Bank and Scratch CRC Memory Bank
         if(bank > 0)
            ret = getMaxPacketDataLengthNV(bank,SNum);
         else if(bank == 0)
            ret = getMaxPacketDataLengthScratch(bank,SNum);
         break;

      case 0x33: case 0xB3:  //SHAEE Memory Bank
         ret = getMaxPacketDataLengthSHAEE(bank,SNum);
         break;

      case 0x09: case 0x0B: case 0x0F: case 0x12: case 0x13:  //EPROM Memory Bank
         ret = getMaxPacketDataLengthEPROM(bank,SNum);
         break;

      case 0x37: case 0x77:
         if(bank > 0)
            ret = getMaxPacketDataLengthEE77(bank,SNum);
         else if(bank == 0)
            ret = getMaxPacketDataLengthScratchEx77(bank,SNum);
         break;

      default:
         break;
   }

   return ret;
}

/**
 * Checks to see if this memory bank's pages can be read with
 * the contents being verified by a device generated CRC.
 * This is used to see if the owReadPageCRC function can be used.
 *
 * bank       to tell what memory bank of the ibutton to use.
 * SNum       the serial number for the part that the operation is
 *            to be done on.
 *
 * @return  true if this memory bank can be
 *          read with self generated CRC
 */
SMALLINT owHasPageAutoCRC(SMALLINT bank, uchar *SNum)
{
   SMALLINT ret = 0;

   switch(SNum[0] & 0x7F)
   {
      case 0x14:  //EE Memory Bank and AppReg Memory Bank
         if(bank > 0)
            ret = hasPageAutoCRCEE(bank,SNum);
         else if(bank == 0)
            ret = hasPageAutoCRCAppReg(bank,SNum);
         break;

      case 0x04: case 0x06: case 0x08: case 0x0A:
      case 0x0C: case 0x23:  //NV Memory Bank and Scratch Memory Bank
         if(bank > 0)
            ret = hasPageAutoCRCNV(bank,SNum);
         else if(bank == 0)
            ret = hasPageAutoCRCScratch(bank,SNum);
         break;

      case 0x18:  //NV Memory Bank and Scratch SHA Memory Bank
         if(bank > 0)
            ret = hasPageAutoCRCNV(bank,SNum);
         else if(bank == 0)
            ret = hasPageAutoCRCScratch(bank,SNum);
         break;

      case 0x1A: case 0x1D:  //NVCRC Memory Bank and Scratch Ex Memory Bank
         if(bank > 0)
            ret = hasPageAutoCRCNV(bank,SNum);
         else if(bank == 0)
            ret = hasPageAutoCRCScratch(bank,SNum);
         break;

      case 0x21:  //NVCRC Memory Bank and Scratch CRC Memory Bank
         if(bank > 0)
            ret = hasPageAutoCRCNV(bank,SNum);
         else if(bank == 0)
            ret = hasPageAutoCRCScratch(bank,SNum);
         break;

      case 0x33: case 0xB3:  //SHAEE Memory Bank
         ret = hasPageAutoCRCSHAEE(bank,SNum);
         break;

      case 0x09: case 0x0B: case 0x0F: case 0x12: case 0x13:  //EPROM Memory Bank
         ret = hasPageAutoCRCEPROM(bank,SNum);
         break;

      case 0x37: case 0x77:
         if(bank > 0)
            ret = hasPageAutoCRCEE77(bank,SNum);
         else if(bank == 0)
            ret = hasPageAutoCRCScratchEx77(bank,SNum);
         break;

      default:
         break;
   }

   return ret;
}

/**
 * Checks to see if this memory bank has pages that can be redirected
 * to a new page.  This is used in Write-Once memory
 * to provide a means to update.
 *
 * bank       to tell what memory bank of the ibutton to use.
 * SNum       the serial number for the part that the operation is
 *            to be done on.
 *
 * @return  true if this memory bank pages can be redirected
 *          to a new page
 */
SMALLINT owCanRedirectPage(SMALLINT bank, uchar *SNum)
{
   SMALLINT ret = 0;

   switch(SNum[0] & 0x7F)
   {
      case 0x14:  //EE Memory Bank and AppReg Memory Bank
         if(bank > 0)
            ret = canRedirectPageEE(bank,SNum);
         else if(bank == 0)
            ret = canRedirectPageAppReg(bank,SNum);
         break;

      case 0x04: case 0x06: case 0x08: case 0x0A:
      case 0x0C: case 0x23:  //NV Memory Bank and Scratch Memory Bank
         if(bank > 0)
            ret = canRedirectPageNV(bank,SNum);
         else if(bank == 0)
            ret = canRedirectPageScratch(bank,SNum);
         break;

      case 0x1A: case 0x1D:  //NVCRC Memory Bank and Scratch Ex Memory Bank
         if(bank > 0)
            ret = canRedirectPageNV(bank,SNum);
         else if(bank == 0)
            ret = canRedirectPageScratch(bank,SNum);
         break;

      case 0x21:  //NVCRC Memory Bank and Scratch CRC Memory Bank
         if(bank > 0)
            ret = canRedirectPageNV(bank,SNum);
         else if(bank == 0)
            ret = canRedirectPageScratch(bank,SNum);
         break;

      case 0x33: case 0xB3:  //SHAEE Memory Bank
         ret = canRedirectPageSHAEE(bank,SNum);
         break;

      case 0x09: case 0x0B: case 0x0F: case 0x12: case 0x13:
         ret = canRedirectPageEPROM(bank,SNum);
         break;

      case 0x37: case 0x77:
         if(bank > 0)
            ret = canRedirectPageEE77(bank,SNum);
         else if(bank == 0)
            ret = canRedirectPageScratchEx77(bank,SNum);
         break;

      default:
         break;
   }

   return ret;
}

/**
 * Checks to see if this memory bank has pages that can be locked.  A
 * locked page would prevent any changes to it's contents.
 *
 * bank       to tell what memory bank of the ibutton to use.
 * SNum       the serial number for the part that the operation is
 *            to be done on.
 *
 * @return  true if this memory bank has pages that can be
 *          locked
 */
SMALLINT owCanLockPage(SMALLINT bank, uchar *SNum)
{
   SMALLINT ret = 0;

   switch(SNum[0] & 0x7F)
   {
      case 0x14:  //EE Memory Bank and AppReg Memory Bank
         if(bank > 0)
            ret = canLockPageEE(bank,SNum);
         else if(bank == 0)
            ret = canLockPageAppReg(bank,SNum);
         break;

      case 0x04: case 0x06: case 0x08: case 0x0A:
      case 0x0C: case 0x23:  //NV Memory Bank and Scratch Memory Bank
         if(bank > 0)
            ret = canLockPageNV(bank,SNum);
         else if(bank == 0)
            ret = canLockPageScratch(bank,SNum);
         break;

      case 0x1A: case 0x1D:  //NVCRC Memory Bank and Scratch Ex Memory Bank
         if(bank > 0)
            ret = canLockPageNV(bank,SNum);
         else if(bank == 0)
            ret = canLockPageScratch(bank,SNum);
         break;

      case 0x21:  //NVCRC Memory Bank and Scratch CRC Memory Bank
         if(bank > 0)
            ret = canLockPageNV(bank,SNum);
         else if(bank == 0)
            ret = canLockPageScratch(bank,SNum);
         break;

      case 0x33: case 0xB3:  //SHAEE Memory Bank
         ret = canLockPageSHAEE(bank,SNum);
         break;

      case 0x09: case 0x0B: case 0x0F: case 0x12: case 0x13:
         ret = canLockPageEPROM(bank,SNum);
         break;

      case 0x37: case 0x77:
         if(bank > 0)
            ret = canLockPageEE77(bank,SNum);
         else if(bank == 0)
            ret = canLockPageScratchEx77(bank,SNum);
         break;

      default:
         break;
   }

   return ret;
}

/**
 * Checks to see if this memory bank has pages that can be locked from
 * being redirected.  This would prevent a Write-Once memory from
 * being updated.
 *
 * bank       to tell what memory bank of the ibutton to use.
 * SNum       the serial number for the part that the operation is
 *            to be done on.
 *
 * @return  true if this memory bank has pages that can
 *          be locked from being redirected to a new page
 */
SMALLINT owCanLockRedirectPage(SMALLINT bank, uchar *SNum)
{
   SMALLINT ret = 0;

   switch(SNum[0] & 0x7F)
   {
      case 0x14:  //EE Memory Bank and AppReg Memory Bank
         if(bank > 0)
            ret = canLockRedirectPageEE(bank,SNum);
         else if(bank == 0)
            ret = canLockRedirectPageAppReg(bank,SNum);
         break;

      case 0x04: case 0x06: case 0x08: case 0x0A:
      case 0x0C: case 0x23:  //NV Memory Bank and Scratch Memory Bank
         if(bank > 0)
            ret = canLockRedirectPageNV(bank,SNum);
         else if(bank == 0)
            ret = canLockRedirectPageScratch(bank,SNum);
         break;

      case 0x1A: case 0x1D:  //NVCRC Memory Bank and Scratch Ex Memory Bank
         if(bank > 0)
            ret = canLockRedirectPageNV(bank,SNum);
         else if(bank == 0)
            ret = canLockRedirectPageScratch(bank,SNum);
         break;

      case 0x21:  //NVCRC Memory Bank and Scratch CRC Memory Bank
         if(bank > 0)
            ret = canLockRedirectPageNV(bank,SNum);
         else if(bank == 0)
            ret = canLockRedirectPageScratch(bank,SNum);
         break;

      case 0x33: case 0xB3:  //SHAEE Memory Bank
         ret = canLockRedirectPageSHAEE(bank,SNum);
         break;

      case 0x09: case 0x0B: case 0x0F: case 0x12: case 0x13:
         ret = canLockRedirectPageEPROM(bank,SNum);
         break;

      case 0x37: case 0x77:
         if(bank > 0)
            ret = canLockRedirectPageEE77(bank,SNum);
         else if(bank == 0)
            ret = canLockRedirectPageScratchEx77(bank,SNum);
         break;

      default:
         break;
   }

   return ret;
}

/**
 * Tells whether a password is possibly needed.
 *
 * portnum    the port number of the port being used for the
 *            1-Wire Network.
 * SNum       the serial number for the part that the operation is
 *            to be done on.
 * pass       the password to set for read/write operations.
 *
 * @return    'true' if the password was set..
 */
SMALLINT owNeedPassword(uchar *SNum)
{
   SMALLINT ret = 0;

   switch(SNum[0] & 0x7F)
   {
      case 0x37: case 0x77:
         ret = TRUE;
         break;

      default:
         ret = FALSE;
         break;
   }

   return ret;
}

/**
 * Sets the password on the part for read-only operations.
 *
 * portnum    the port number of the port being used for the
 *            1-Wire Network.
 * SNum       the serial number for the part that the operation is
 *            to be done on.
 * pass       the password to set for read-only operations.
 *
 * @return    'true' if the password was set..
 */
SMALLINT owSetReadOnlyPassword(int portnum, uchar *SNum, uchar *pass)
{
   SMALLINT ret = 0;

   switch(SNum[0] & 0x7F)
   {
      case 0x37: case 0x77:
         if(setPassword(portnum,SNum,pass,READ_PSW))
         {
            ret = verifyPassword(portnum,SNum,pass,READ_PSW);

            if(ret)
               setBMPasswordRO(pass);
         }
         else
         {
            ret = FALSE;
         }
         break;

      default:
         OWERROR(OWERROR_NO_READ_ONLY_PASSWORD);
         ret = FALSE;
         break;
   }

   return ret;
}

/**
 * Sets the password on the part for read/write operations.
 *
 * portnum    the port number of the port being used for the
 *            1-Wire Network.
 * SNum       the serial number for the part that the operation is
 *            to be done on.
 * pass       the password to set for read/write operations.
 *
 * @return    'true' if the password was set..
 */
SMALLINT owSetReadWritePassword(int portnum, uchar *SNum, uchar *pass)
{
   SMALLINT ret = FALSE;

   switch(SNum[0] & 0x7F)
   {
      case 0x37: case 0x77:
         if(setPassword(portnum,SNum,pass,READ_WRITE_PSW))
         {
            ret = verifyPassword(portnum,SNum,pass,READ_WRITE_PSW);

            if(ret)
               setBMPasswordRW(pass);
         }
         else
         {
            ret = FALSE;
         }
         break;

      default:
         OWERROR(OWERROR_NO_READ_WRITE_PASSWORD);
         ret = FALSE;
         break;
   }

   return ret;
}

/**
 * Sets the password for read-only operations.
 *
 * portnum    the port number of the port being used for the
 *            1-Wire Network.
 * SNum       the serial number for the part that the operation is
 *            to be done on.
 * pass       the password for read-only operations.
 *
 * @return    'true' if the password was set..
 */
SMALLINT owSetBMReadOnlyPassword(int portnum, uchar *SNum, uchar *pass)
{
   SMALLINT ret = 0;

   switch(SNum[0] & 0x7F)
   {
      case 0x37: case 0x77:
         setBMPasswordRO(pass);
         ret = TRUE;
         break;

      default:
         OWERROR(OWERROR_NO_READ_ONLY_PASSWORD);
         ret = FALSE;
         break;
   }

   return ret;
}

/**
 * Sets the password for read/write operations.
 *
 * portnum    the port number of the port being used for the
 *            1-Wire Network.
 * SNum       the serial number for the part that the operation is
 *            to be done on.
 * pass       the password for read/write operations.
 *
 * @return    'true' if the password was set..
 */
SMALLINT owSetBMReadWritePassword(int portnum, uchar *SNum, uchar *pass)
{
   SMALLINT ret = FALSE;

   switch(SNum[0] & 0x7F)
   {
      case 0x37: case 0x77:
         setBMPasswordRW(pass);
         ret = TRUE;
         break;

      default:
         OWERROR(OWERROR_NO_READ_WRITE_PASSWORD);
         ret = FALSE;
         break;
   }

   return ret;
}

/**
 * Sets the password for read/write operations.
 *
 * portnum    the port number of the port being used for the
 *            1-Wire Network.
 * SNum       the serial number for the part that the operation is
 *            to be done on.
 * pass       the password for read/write operations.
 *
 * @return    'true' if the password was set..
 */
SMALLINT owSetPasswordMode(int portnum, uchar *SNum, int mode)
{
   SMALLINT ret = FALSE;

   switch(SNum[0] & 0x7F)
   {
      case 0x37: case 0x77:
         ret = setPasswordMode(portnum,SNum,mode);
         break;

      default:
         OWERROR(OWERROR_NO_READ_WRITE_PASSWORD);
         ret = FALSE;
         break;
   }

   return ret;
}

/**
 * Gets the memory bank given the page for the part.
 *
 * portnum    the port number of the port being used for the
 *            1-Wire Network.
 * SNum       the serial number for the part that the operation is
 *            to be done on.
 * page       the page number for the part not memory bank
 * flag       the flag to indicate status memory or regular memory
 *
 * @return    the bank number that the page is in.
 */
SMALLINT getBank(int portnum, uchar *SNum, PAGE_TYPE page, uchar flag)
{
   SMALLINT bank = 1;
   SMALLINT i,starting_bank=1;
   int      tmp_pg;
   int      num_pg;

   if(flag == STATUSMEM)
   {
      tmp_pg = page;

      for(i=starting_bank;i<owGetNumberBanks(SNum[0]);i++)
      {
         if((i+1) == owGetNumberBanks(SNum[0]))
            return i;
         else
         {
            if(owGetPageLength(bank,SNum) != 0)
               num_pg = owGetStartingAddress(i+1,SNum)/
                        owGetPageLength(bank,SNum);
            else
               return FALSE;
         }

         if(num_pg >= tmp_pg)
         {
            if(num_pg == tmp_pg)
               return i+1;
            else
               return i;
         }

      }
   }
   else
   {
      if(owIsWriteOnce(bank,portnum,SNum))
      {
         tmp_pg = page;

         for(i=0;i<owGetNumberBanks(SNum[0]);i++)
         {
            if(owIsNonVolatile(i,SNum) && owIsGeneralPurposeMemory(i,SNum))
            {
               num_pg = owGetNumberPages(i,SNum);

               if(num_pg >= tmp_pg)
                  return i;
               else
                  tmp_pg = tmp_pg - num_pg;
            }
         }
      }
      else
      {
         tmp_pg = page;

         for(i=0;i<owGetNumberBanks(SNum[0]);i++)
         {
            if(owIsNonVolatile(i,SNum) && owIsGeneralPurposeMemory(i,SNum) &&
               owIsReadWrite(i,portnum,SNum))
            {
               num_pg = owGetNumberPages(i,SNum);

               if(num_pg > tmp_pg)
                  return i;
               else
               tmp_pg = tmp_pg - num_pg;
            }
         }
      }
   }

   return FALSE;
}

/**
 * Gets the memory bank given the page for the part.
 *
 * portnum    the port number of the port being used for the
 *            1-Wire Network.
 * SNum       the serial number for the part that the operation is
 *            to be done on.
 * page       the page number for the part not memory bank
 * flag       the flag to indicate status memory or regular memory
 *
 * @return    the bank number that the page is in.
 */
SMALLINT getPage(int portnum, uchar *SNum, PAGE_TYPE page, uchar flag)
{
   SMALLINT bank = 1;
   SMALLINT i,starting_bank=1;
   int      tmp_pg;
   int      num_pg;

   if(flag == STATUSMEM)
   {
      tmp_pg = page;

      for(i=starting_bank;i<owGetNumberBanks(SNum[0]);i++)
      {
         if((i+1) == owGetNumberBanks(SNum[0]))
         {
            if(owGetPageLength(bank,SNum) != 0)
               return (tmp_pg - (owGetStartingAddress(i,SNum)/
                                 owGetPageLength(bank,SNum)));
            else
               return FALSE;
         }
         else
         {
            if(owGetPageLength(bank,SNum) != 0)
               num_pg = owGetStartingAddress(i+1,SNum)/owGetPageLength(bank,SNum);
            else
               return FALSE;
         }

         if(num_pg >= tmp_pg)
         {
            if(num_pg == tmp_pg)
               return 0;
            else if(owGetStartingAddress(i,SNum) == 0x00)
               return tmp_pg;
            else
            {
               if(owGetPageLength(bank,SNum) != 0)
                  return (tmp_pg - (owGetStartingAddress(i,SNum)/
                                    owGetPageLength(bank,SNum)));
               else
                  return FALSE;
            }
         }
      }
   }
   else
   {
      if(owIsWriteOnce(bank,portnum,SNum))
      {
         tmp_pg = page;

         for(i=0;i<owGetNumberBanks(SNum[0]);i++)
         {
            if(owIsNonVolatile(i,SNum) && owIsGeneralPurposeMemory(i,SNum))
            {
               num_pg = owGetNumberPages(i,SNum);

               if(num_pg >= tmp_pg)
                  return tmp_pg;
               else
                  tmp_pg = tmp_pg - num_pg;
            }
         }
      }
      else
      {
         tmp_pg = page;

         for(i=0;i<owGetNumberBanks(SNum[0]);i++)
         {
            if(owIsNonVolatile(i,SNum) && owIsGeneralPurposeMemory(i,SNum) &&
               owIsReadWrite(i,portnum,SNum))
            {
               num_pg = owGetNumberPages(i,SNum);

               if(num_pg > tmp_pg)
                  return tmp_pg;
               else
                  tmp_pg = tmp_pg - num_pg;
            }
         }
      }
   }

   return FALSE;
}