Implementation of 1-Wire with added Alarm Search Functionality

Dependents:   Max32630_One_Wire_Interface

Revision:
86:2ce08ca58b9e
Parent:
82:c11090a32471
Child:
104:3f48daed532b
diff -r 708b7be59fb2 -r 2ce08ca58b9e Slaves/Authenticators/DS28E15_22_25/DS28E15_22_25.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Slaves/Authenticators/DS28E15_22_25/DS28E15_22_25.cpp	Wed Jun 15 15:00:06 2016 -0500
@@ -0,0 +1,1234 @@
+/******************************************************************//**
+* Copyright (C) 2016 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+**********************************************************************/
+
+#include "DS28E15_22_25.h"
+#include "Masters/OneWireMaster.h"
+#include "Utilities/crc.h"
+#include "wait_api.h"
+
+using namespace OneWire;
+using namespace OneWire::crc;
+
+/// 1-Wire device commands.
+enum Command
+{
+    WriteMemory = 0x55,
+    ReadMemory = 0xF0,
+    LoadAndLockSecret = 0x33,
+    ComputeAndLockSecret = 0x3C,
+    ReadWriteScratchpad = 0x0F,
+    ComputePageMac = 0xA5,
+    ReadStatus = 0xAA,
+    WriteBlockProtection = 0xC3,
+    AuthWriteMemory = 0x5A,
+    AuthWriteBlockProtection = 0xCC,
+};
+
+DS28E15_22_25::Segment DS28E15_22_25::Page::toSegment(unsigned int segmentNum) const
+{
+    if (segmentNum > (segmentsPerPage - 1))
+    {
+        segmentNum = (segmentsPerPage - 1);
+    }
+    return Segment(*reinterpret_cast<const Segment::Buffer *>(&m_data[segmentNum * sizeof(Segment::Buffer)]));
+}
+
+void DS28E15_22_25::Page::fromSegment(unsigned int segmentNum, const Segment & segment)
+{
+    if (segmentNum > (segmentsPerPage - 1))
+    {
+        segmentNum = (segmentsPerPage - 1);
+    }
+    std::memcpy(&m_data[segmentNum * sizeof(Segment::Buffer)], &static_cast<const Segment::Buffer &>(segment), Segment::length);
+}
+
+DS28E15_22_25::BlockProtection::BlockProtection(bool readProtection, bool writeProtection, bool eepromEmulation, bool authProtection, uint8_t blockNum)
+{
+    setReadProtection(readProtection);
+    setWriteProtection(writeProtection);
+    setEepromEmulation(eepromEmulation);
+    setAuthProtection(authProtection);
+    setBlockNum(blockNum);
+}
+
+void DS28E15_22_25::BlockProtection::setBlockNum(uint8_t blockNum)
+{
+    m_status &= ~blockNumMask;
+    m_status |= (blockNum & blockNumMask);
+}
+
+bool DS28E15_22_25::BlockProtection::noProtection() const
+{
+    return !readProtection() && !writeProtection() && !eepromEmulation() && !authProtection();
+}
+
+void DS28E15_22_25::BlockProtection::setReadProtection(bool readProtection)
+{
+    if (readProtection)
+    {
+        m_status |= readProtectionMask;
+    }
+    else
+    {
+        m_status &= ~readProtectionMask;
+    }
+}
+
+void DS28E15_22_25::BlockProtection::setWriteProtection(bool writeProtection)
+{
+    if (writeProtection)
+    {
+        m_status |= writeProtectionMask;
+    }
+    else
+    {
+        m_status &= ~writeProtectionMask;
+    }
+}
+
+void DS28E15_22_25::BlockProtection::setEepromEmulation(bool eepromEmulation)
+{
+    if (eepromEmulation)
+    {
+        m_status |= eepromEmulationMask;
+    }
+    else
+    {
+        m_status &= ~eepromEmulationMask;
+    }
+}
+
+void DS28E15_22_25::BlockProtection::setAuthProtection(bool authProtection)
+{
+    if (authProtection)
+    {
+        m_status |= authProtectionMask;
+    }
+    else
+    {
+        m_status &= ~authProtectionMask;
+    }
+}
+
+DS28E15_22_25::DS28E15_22_25(RandomAccessRomIterator & selector, bool lowVoltage)
+    : OneWireSlave(selector), m_lowVoltage(lowVoltage)
+{
+    std::memset(m_manId, 0x00, m_manId.length);
+}
+
+DS28E15_22_25::MemoryPages DS28E15_22_25::memoryPages()
+{
+    MemoryPages pages;
+
+    switch (romId().familyCode())
+    {
+    case DS28E25_Family:
+        pages = DS28E25_Pages;
+        break;
+
+    case DS28E22_Family:
+        pages = DS28E22_Pages;
+        break;
+
+    case DS28E15_Family:
+        pages = DS28E15_Pages;
+        break;
+
+    default:
+        pages = Unknown_Pages;
+        break;
+    }
+
+    return pages;
+}
+
+DS28E15_22_25::ProtectionBlocks DS28E15_22_25::protectionBlocks()
+{
+    ProtectionBlocks blocks;
+
+    switch (romId().familyCode())
+    {
+    case DS28E25_Family:
+        blocks = DS28E25_Blocks;
+        break;
+
+    case DS28E22_Family:
+        blocks = DS28E22_Blocks;
+        break;
+
+    case DS28E15_Family:
+        blocks = DS28E15_Blocks;
+        break;
+
+    default:
+        blocks = Unknown_Blocks;
+        break;
+    }
+
+    return blocks;
+}
+
+OneWireSlave::CmdResult DS28E15_22_25::writeAuthBlockProtection(const ISha256MacCoproc & MacCoproc, const BlockProtection & newProtection, const BlockProtection & oldProtection)
+{
+    uint8_t buf[256], cs;
+    int cnt = 0;
+    Mac mac;
+    
+    if (selectDevice() != OneWireMaster::Success)
+    {
+        return CommunicationError;
+    }
+
+    buf[cnt++] = AuthWriteBlockProtection;
+    buf[cnt++] = newProtection.statusByte();
+
+    // Send command
+    master().OWWriteBlock(&buf[0], 2);
+
+    // read first CRC byte
+    master().OWReadByte(buf[cnt++]);
+
+    // read the last CRC and enable
+    master().OWReadBytePower(buf[cnt++]);
+
+    // now wait for the MAC computation.
+    wait_ms(shaComputationDelayMs);
+
+    // disable strong pullup
+    master().OWSetLevel(OneWireMaster::NormalLevel);
+
+    // check CRC16
+    if (calculateCrc16(buf, 0, cnt) != 0xB001)
+    {
+        return CrcError;
+    }
+
+    ISha256MacCoproc::CmdResult result;
+    result = computeProtectionWriteMac(MacCoproc, newProtection, oldProtection, romId(), manId(), mac);
+    if (result != ISha256MacCoproc::Success)
+    {
+        return OperationFailure;
+    }
+    cnt = 0;
+
+    // send the MAC
+    master().OWWriteBlock(mac, mac.length);
+
+    // Read CRC and CS byte
+    master().OWReadBlock(&buf[cnt], 3);
+    cnt += 3;
+
+    // check CRC16
+    if (calculateCrc16(buf, 0, (cnt - 1), calculateCrc16(mac, 0, mac.length)) != 0xB001)
+    {
+        return CrcError;
+    }
+
+    // check CS
+    if (buf[cnt - 1] != 0xAA)
+    {
+        return OperationFailure;
+    }
+
+    // send release and strong pull-up
+    // DATASHEET_CORRECTION - last bit in release is a read-zero so don't check echo of write byte
+    master().OWWriteBytePower(0xAA);
+
+    // now wait for the programming.
+    wait_ms(eepromWriteDelayMs);
+
+    // disable strong pullup
+    master().OWSetLevel(OneWireMaster::NormalLevel);
+
+    // read the CS byte
+    master().OWReadByte(cs);
+
+    if (cs == 0xAA)
+    {
+        return Success;
+    }
+    // else
+    return OperationFailure;
+}
+
+OneWireSlave::CmdResult DS28E15_22_25::writeBlockProtection(const BlockProtection & protection)
+{
+    uint8_t buf[256], cs;
+    int cnt = 0;
+    
+    if (selectDevice() != OneWireMaster::Success)
+    {
+        return CommunicationError;
+    }
+
+    buf[cnt++] = WriteBlockProtection;
+
+    // compute parameter byte 
+    buf[cnt++] = protection.statusByte();
+
+    master().OWWriteBlock(&buf[0], cnt);
+
+    // Read CRC
+    master().OWReadBlock(&buf[cnt], 2);
+    cnt += 2;
+
+    // check CRC16
+    if (calculateCrc16(buf, 0, cnt) != 0xB001)
+    {
+        return CrcError;
+    }
+
+    // sent release
+    master().OWWriteBytePower(0xAA);
+
+    // now wait for the programming.
+    wait_ms(eepromWriteDelayMs);
+
+    // disable strong pullup
+    master().OWSetLevel(OneWireMaster::NormalLevel);
+
+    // read the CS byte
+    master().OWReadByte(cs);
+
+    if (cs == 0xAA)
+    {
+        return Success;
+    }
+    // else
+    return OperationFailure;
+}
+
+OneWireSlave::CmdResult DS28E15_22_25::readBlockProtection(unsigned int blockNum, BlockProtection & protection)
+{
+    uint8_t buf;
+    CmdResult result;
+    
+    result = readStatus(false, false, blockNum, &buf);
+    if (result == Success)
+    {
+        protection.setStatusByte(buf);
+    }
+    return result;
+}
+
+template <DS28E15_22_25::ProtectionBlocks blocks> OneWireSlave::CmdResult DS28E15_22_25::readAllBlockProtection(BlockProtection(&protection)[blocks]) const
+{
+    uint8_t buf[blocks];
+    CmdResult result = readStatus(false, true, 0, buf);
+    if (result == Success)
+    {
+        for (size_t i = 0; i < blocks; i++)
+        {
+            protection[i].setStatusByte(buf[i]);
+        }
+    }
+    return result;
+}
+
+OneWireSlave::CmdResult DS28E15_22_25::readAllBlockProtection(BlockProtection(&protection)[DS28E15_Blocks]) const
+{
+    return readAllBlockProtection<DS28E15_Blocks>(protection);
+}
+
+OneWireSlave::CmdResult DS28E15_22_25::readAllBlockProtection(BlockProtection(&protection)[DS28E25_Blocks]) const
+{
+    return readAllBlockProtection<DS28E25_Blocks>(protection);
+}
+
+OneWireSlave::CmdResult DS28E15_22_25::readPersonality(Personality & personality) const
+{
+    return readStatus(true, false, 0, personality.bytes);
+}
+
+OneWireSlave::CmdResult DS28E15_22_25::readStatus(bool personality, bool allpages, unsigned int blockNum, uint8_t * rdbuf) const
+{
+    const size_t crcLen = 4, ds28e22_25_pagesPerBlock = 2;
+
+    uint8_t buf[256];
+    size_t cnt = 0, offset = 0;
+    
+    if (selectDevice() != OneWireMaster::Success)
+    {
+        return CommunicationError;
+    }
+
+    buf[cnt++] = ReadStatus;
+    if (personality)
+    {
+        buf[cnt++] = 0xE0;
+    }
+    else if (allpages)
+    {
+        buf[cnt++] = 0;
+    }
+    else
+    {
+        // Convert to page number for DS28E22 and DS28E25
+        buf[cnt] = blockNum;
+        if ((romId().familyCode() == DS28E25_Family) || (romId().familyCode() == DS28E22_Family))
+        {
+            buf[cnt] *= ds28e22_25_pagesPerBlock;
+        }
+        cnt++;
+    }
+
+    // send the command
+    master().OWWriteBlock(&buf[0], 2);
+
+    offset = cnt + 2;
+
+    // Set data length
+    size_t rdnum;
+    if (personality)
+    {
+        rdnum = 4;
+    }
+    else if (!allpages)
+    {
+        rdnum = 1;
+    }
+    else if ((romId().familyCode() == DS28E22_Family) || (romId().familyCode() == DS28E25_Family))
+    {
+        rdnum = DS28E25_Pages; // Need to read extra data on DS28E22 to get CRC16.
+    }
+    else // DS28E15
+    {
+        rdnum = DS28E15_Blocks;
+    }
+    rdnum += crcLen; // Add in CRC length
+
+    // Read the bytes 
+    master().OWReadBlock(&buf[cnt], rdnum);
+    cnt += rdnum;
+
+    // check the first CRC16
+    if (calculateCrc16(buf, 0, offset) != 0xB001)
+    {
+        return CrcError;
+    }
+
+    if (personality || allpages)
+    {
+        // check the second CRC16
+        if (calculateCrc16(buf, offset, (cnt - offset)) != 0xB001)
+        {
+            return CrcError;
+        }
+    }
+
+    // copy the data to the read buffer
+    rdnum -= crcLen;
+    if (allpages && ((romId().familyCode() == DS28E25_Family) || (romId().familyCode() == DS28E22_Family)))
+    {
+        if (romId().familyCode() == DS28E22_Family)
+        {
+            rdnum -= (DS28E25_Pages - DS28E22_Pages);
+        }
+
+        for (size_t i = 0; i < (rdnum / ds28e22_25_pagesPerBlock); i++)
+        {
+            rdbuf[i] = (buf[offset + (i * ds28e22_25_pagesPerBlock)] & 0xF0); // Upper nibble
+            rdbuf[i] |= ((buf[offset + (i * ds28e22_25_pagesPerBlock)] & 0x0F) / ds28e22_25_pagesPerBlock); // Lower nibble
+        }
+    }
+    else
+    {
+        std::memcpy(rdbuf, &buf[offset], rdnum);
+    }
+
+    return Success;
+}
+
+ISha256MacCoproc::CmdResult DS28E15_22_25::computeAuthMac(const ISha256MacCoproc & MacCoproc, const Page & pageData, unsigned int pageNum, const Scratchpad & challenge, const RomId & romId, const ManId & manId, Mac & mac)
+{
+    ISha256MacCoproc::AuthMacData authMacData;
+
+    // insert ROM number or FF
+    std::memcpy(authMacData, romId, RomId::byteLen);
+
+    authMacData[10] = pageNum;
+
+    authMacData[9] = manId[0];
+    authMacData[8] = manId[1];
+
+    authMacData[11] = 0x00;
+
+    return MacCoproc.computeAuthMac(ISha256MacCoproc::DevicePage(pageData), challenge, authMacData, mac);
+}
+
+ISha256MacCoproc::CmdResult DS28E15_22_25::computeAuthMacAnon(const ISha256MacCoproc & MacCoproc, const Page & pageData, unsigned int pageNum, const Scratchpad & challenge, const ManId & manId, Mac & mac)
+{
+    RomId romId;
+    std::memset(romId, 0xFF, RomId::byteLen);
+    return computeAuthMac(MacCoproc, pageData, pageNum, challenge, romId, manId, mac);
+}
+
+OneWireSlave::CmdResult DS28E15_22_25::computeReadPageMac(unsigned int page_num, bool anon, Mac & mac) const
+{
+    uint8_t buf[256], cs;
+    int cnt = 0;
+    
+    if (selectDevice() != OneWireMaster::Success)
+    {
+        return CommunicationError;
+    }
+
+    buf[cnt++] = ComputePageMac;
+    buf[cnt++] = ((anon) ? 0xE0 : 0x00) | page_num;
+
+    // Send command
+    master().OWWriteBlock(&buf[0], 2);
+
+    // read first CRC byte
+    master().OWReadByte(buf[cnt++]);
+
+    // read the last CRC and enable
+    master().OWReadBytePower(buf[cnt++]);
+
+    // now wait for the MAC computation.
+    wait_ms(shaComputationDelayMs * 2);
+
+    // disable strong pullup
+    master().OWSetLevel(OneWireMaster::NormalLevel);
+
+    // check CRC16
+    if (calculateCrc16(buf, 0, cnt) != 0xB001)
+    {
+        return CrcError;
+    }
+
+    // read the CS byte
+    master().OWReadByte(cs);
+    if (cs != 0xAA)
+    {
+        return OperationFailure;
+    }
+
+    // read the MAC and CRC
+    master().OWReadBlock(&buf[0], (Mac::length + 2));
+
+    // check CRC16
+    if (calculateCrc16(buf, 0, (Mac::length + 2)) != 0xB001)
+    {
+        return CrcError;
+    }
+
+    // copy MAC to return buffer
+    std::memcpy(mac, buf, Mac::length);
+
+    return Success;
+}
+
+OneWireSlave::CmdResult DS28E15_22_25::computeSecret(unsigned int page_num, bool lock)
+{
+    uint8_t buf[256], cs;
+    int cnt = 0;
+    
+    if (selectDevice() != OneWireMaster::Success)
+    {
+        return CommunicationError;
+    }
+
+    buf[cnt++] = ComputeAndLockSecret;
+    buf[cnt++] = (lock) ? (0xE0 | page_num) : page_num;  // lock flag 
+
+    // Send command
+    master().OWWriteBlock(&buf[0], 2);
+
+    // Read CRC
+    master().OWReadBlock(&buf[cnt], 2);
+    cnt += 2;
+
+    // check CRC16
+    if (calculateCrc16(buf, 0, cnt) != 0xB001)
+    {
+        return CrcError;
+    }
+
+    // send release and strong pull-up
+    master().OWWriteBytePower(0xAA);
+
+    // now wait for the MAC computations and secret programming.
+    wait_ms(shaComputationDelayMs * 2 + secretEepromWriteDelayMs());
+
+    // disable strong pullup
+    master().OWSetLevel(OneWireMaster::NormalLevel);
+
+    // read the CS byte
+    master().OWReadByte(cs);
+
+    if (cs == 0xAA)
+    {
+        return Success;
+    }
+    // else
+    return OperationFailure;
+}
+
+OneWireSlave::CmdResult DS28E15_22_25::writeScratchpad(const Scratchpad & data) const
+{
+    uint8_t buf[256];
+    int cnt = 0, offset;
+    
+    if (selectDevice() != OneWireMaster::Success)
+    {
+        return CommunicationError;
+    }
+
+    buf[cnt++] = ReadWriteScratchpad;
+    if ((romId().familyCode() == DS28E25_Family) || (romId().familyCode() == DS28E22_Family))
+    {
+        buf[cnt++] = 0x20;
+    }
+    else
+    {
+        buf[cnt++] = 0x00;
+    }
+
+    // Send command
+    master().OWWriteBlock(&buf[0], 2);
+
+    // Read CRC
+    master().OWReadBlock(&buf[cnt], 2);
+    cnt += 2;
+
+    offset = cnt;
+
+    // add the data
+    std::memcpy(&buf[cnt], data, data.length);
+    cnt += data.length;
+
+    // Send the data
+    master().OWWriteBlock(data, data.length);
+
+    // Read CRC
+    master().OWReadBlock(&buf[cnt], 2);
+    cnt += 2;
+
+    // check first CRC16
+    if (calculateCrc16(buf, 0, offset) != 0xB001)
+    {
+        return CrcError;
+    }
+
+    // check the second CRC16
+    if (calculateCrc16(buf, offset, (cnt - offset)) != 0xB001)
+    {
+        return CrcError;
+    }
+
+    return Success;
+}
+
+OneWireSlave::CmdResult DS28E15_22_25::readScratchpad(Scratchpad & data) const
+{
+    uint8_t buf[256];
+    int cnt = 0, offset;
+    
+    if (selectDevice() != OneWireMaster::Success)
+    {
+        return CommunicationError;
+    }
+
+    buf[cnt++] = ReadWriteScratchpad;
+    if ((romId().familyCode() == DS28E25_Family) || (romId().familyCode() == DS28E22_Family))
+    {
+        buf[cnt++] = 0x2F;
+    }
+    else
+    {
+        buf[cnt++] = 0x0F;
+    }
+
+    // Send command
+    master().OWWriteBlock(&buf[0], 2);
+
+    // Read CRC
+    master().OWReadBlock(&buf[cnt], 2);
+    cnt += 2;
+
+    offset = cnt;
+
+    // Receive the data
+    master().OWReadBlock(&buf[cnt], data.length);
+    cnt += data.length;
+
+    // Read CRC
+    master().OWReadBlock(&buf[cnt], 2);
+    cnt += 2;
+
+    // check first CRC16
+    if (calculateCrc16(buf, 0, offset) != 0xB001)
+    {
+        return CrcError;
+    }
+
+    // check the second CRC16
+    if (calculateCrc16(buf, offset, (cnt - offset)) != 0xB001)
+    {
+        return CrcError;
+    }
+
+    // Copy to output
+    std::memcpy(data, &buf[offset], data.length);
+
+    return Success;
+}
+
+OneWireSlave::CmdResult DS28E15_22_25::loadSecret(bool lock)
+{
+    uint8_t buf[256], cs;
+    int cnt = 0;
+    
+    if (selectDevice() != OneWireMaster::Success)
+    {
+        return CommunicationError;
+    }
+
+    buf[cnt++] = LoadAndLockSecret;
+    buf[cnt++] = (lock) ? 0xE0 : 0x00;  // lock flag 
+
+    // Send command
+    master().OWWriteBlock(&buf[0], 2);
+
+    // Read CRC
+    master().OWReadBlock(&buf[cnt], 2);
+    cnt += 2;
+
+    // check CRC16
+    if (calculateCrc16(buf, 0, cnt) != 0xB001)
+    {
+        return CrcError;
+    }
+
+    // send release and strong pull-up
+    master().OWWriteBytePower(0xAA);
+
+    // now wait for the secret programming.
+    wait_ms(secretEepromWriteDelayMs());
+
+    // disable strong pullup
+    master().OWSetLevel(OneWireMaster::NormalLevel);
+
+    // read the CS byte
+    master().OWReadByte(cs);
+
+    if (cs == 0xAA)
+    {
+        return Success;
+    }
+    // else
+    return OperationFailure;
+}
+
+OneWireSlave::CmdResult DS28E15_22_25::readPage(unsigned int page, Page & rdbuf, bool continuing) const
+{
+    uint8_t buf[256];
+    int cnt, offset;
+
+    cnt = 0;
+    offset = 0;
+
+    // check if not continuing a previous block write
+    if (!continuing)
+    {
+        if (selectDevice() != OneWireMaster::Success)
+        {
+            return CommunicationError;
+        }
+        
+        buf[cnt++] = ReadMemory;
+        buf[cnt++] = page;   // address 
+
+        // Send command
+        master().OWWriteBlock(&buf[0], 2);
+
+        // Read CRC
+        master().OWReadBlock(&buf[cnt], 2);
+        cnt += 2;
+
+        offset = cnt;
+    }
+
+    // read data and CRC16
+    master().OWReadBlock(&buf[cnt], (rdbuf.length + 2));
+    cnt += 34;
+
+    // check the first CRC16
+    if (!continuing)
+    {
+        if (calculateCrc16(buf, 0, offset) != 0xB001)
+        {
+            return CrcError;
+        }
+    }
+
+    // check the second CRC16
+    if (calculateCrc16(buf, offset, (cnt - offset)) != 0xB001)
+    {
+        return CrcError;
+    }
+
+    // copy the data to the read buffer
+    std::memcpy(rdbuf, &buf[offset], rdbuf.length);
+
+    return Success;
+}
+
+OneWireSlave::CmdResult DS28E15_22_25::writeAuthSegmentMac(unsigned int pageNum, unsigned int segmentNum, const Segment & newData, const Mac & mac, bool continuing)
+{
+    uint8_t buf[256], cs;
+    int cnt, i, offset;
+
+    cnt = 0;
+    offset = 0;
+
+    // check if not continuing a previous block write
+    if (!continuing)
+    {
+        if (selectDevice() != OneWireMaster::Success)
+        {
+            return CommunicationError;
+        }
+        
+        buf[cnt++] = AuthWriteMemory;
+        buf[cnt++] = (segmentNum << 5) | pageNum;   // address 
+
+        // Send command
+        master().OWWriteBlock(&buf[0], 2);
+
+        // Read CRC
+        master().OWReadBlock(&buf[cnt], 2);
+        cnt += 2;
+
+        offset = cnt;
+    }
+
+    // add the data
+    for (i = 0; i < newData.length; i++)
+    {
+        buf[cnt++] = newData[i];
+    }
+
+    // Send data
+    master().OWWriteBlock(newData, newData.length);
+
+    // read first CRC byte
+    master().OWReadByte(buf[cnt++]);
+
+    // read the last CRC and enable power
+    master().OWReadBytePower(buf[cnt++]);
+
+    // now wait for the MAC computation.
+    wait_ms(shaComputationDelayMs);
+
+    // disable strong pullup
+    master().OWSetLevel(OneWireMaster::NormalLevel);
+
+    // check the first CRC16
+    if (!continuing)
+    {
+        if (calculateCrc16(buf, 0, offset) != 0xB001)
+        {
+            return CrcError;
+        }
+    }
+
+    // check the second CRC16
+    uint16_t CRC16 = 0;
+
+    // DS28E25/DS28E22, crc gets calculagted with CS byte 
+    if ((romId().familyCode() == DS28E25_Family) || (romId().familyCode() == DS28E22_Family))
+    {
+        if (continuing)
+        {
+            CRC16 = calculateCrc16(CRC16, 0xAA);
+        }
+    }
+
+    CRC16 = calculateCrc16(buf, offset, (cnt - offset), CRC16);
+
+    if (CRC16 != 0xB001)
+    {
+        return CrcError;
+    }
+
+    // transmit MAC as a block
+    master().OWWriteBlock(mac, mac.length);
+
+    // calculate CRC on MAC
+    CRC16 = calculateCrc16(mac, 0, mac.length);
+
+    // append read of CRC16 and CS byte
+    master().OWReadBlock(&buf[0], 3);
+    cnt = 3;
+
+    // ckeck CRC16
+    CRC16 = calculateCrc16(buf, 0, (cnt - 1), CRC16);
+
+    if (CRC16 != 0xB001)
+    {
+        return CrcError;
+    }
+
+    // check CS
+    if (buf[cnt - 1] != 0xAA)
+    {
+        return OperationFailure;
+    }
+
+    // send release and strong pull-up
+    master().OWWriteBytePower(0xAA);
+
+    // now wait for the programming.
+    wait_ms(eepromWriteDelayMs);
+
+    // disable strong pullup
+    master().OWSetLevel(OneWireMaster::NormalLevel);
+
+    // read the CS byte
+    master().OWReadByte(cs);
+
+    if (cs == 0xAA)
+    {
+        return Success;
+    }
+    // else
+    return OperationFailure;
+}
+
+ISha256MacCoproc::CmdResult DS28E15_22_25::computeSegmentWriteMac(const ISha256MacCoproc & MacCoproc, unsigned int pageNum, unsigned int segmentNum, const Segment & newData, const Segment & oldData, const RomId & romId, const ManId & manId, Mac & mac)
+{
+    ISha256MacCoproc::WriteMacData MT;
+
+    // insert ROM number
+    std::memcpy(&MT[0], romId, RomId::byteLen);
+
+    MT[11] = segmentNum;
+    MT[10] = pageNum;
+    MT[9] = manId[0];
+    MT[8] = manId[1];
+
+    // insert old data
+    std::memcpy(&MT[12], oldData, Segment::length);
+
+    // insert new data
+    std::memcpy(&MT[16], newData, Segment::length);
+
+    return MacCoproc.computeWriteMac(MT, mac);
+}
+
+ISha256MacCoproc::CmdResult DS28E15_22_25::computeProtectionWriteMac(const ISha256MacCoproc & MacCoproc, const BlockProtection & newProtection, const BlockProtection & oldProtection, const RomId & romId, const ManId & manId, Mac & mac)
+{
+    ISha256MacCoproc::WriteMacData MT;
+
+    // insert ROM number
+    std::memcpy(MT, romId, RomId::byteLen);
+
+    // instert block and page
+    MT[11] = 0;
+    MT[10] = newProtection.blockNum();
+
+    MT[9] = manId[0];
+    MT[8] = manId[1];
+
+    // old data
+    MT[12] = oldProtection.authProtection() ? 0x01 : 0x00;
+    MT[13] = oldProtection.eepromEmulation() ? 0x01 : 0x00;
+    MT[14] = oldProtection.writeProtection() ? 0x01 : 0x00;
+    MT[15] = oldProtection.readProtection() ? 0x01 : 0x00;
+    // new data
+    MT[16] = newProtection.authProtection() ? 0x01 : 0x00;
+    MT[17] = newProtection.eepromEmulation() ? 0x01 : 0x00;
+    MT[18] = newProtection.writeProtection() ? 0x01 : 0x00;
+    MT[19] = newProtection.readProtection() ? 0x01 : 0x00;
+
+    // compute the mac
+    return MacCoproc.computeWriteMac(MT, mac);
+}
+
+OneWireSlave::CmdResult DS28E15_22_25::writeAuthSegment(const ISha256MacCoproc & MacCoproc, unsigned int pageNum, unsigned int segmentNum, const Segment & newData, const Segment & oldData, bool continuing)
+{
+    uint8_t buf[256], cs;
+    int cnt, offset;
+
+    cnt = 0;
+    offset = 0;
+
+    // check if not continuing a previous block write
+    if (!continuing)
+    {
+        if (selectDevice() != OneWireMaster::Success)
+        {
+            return CommunicationError;
+        }
+        
+        buf[cnt++] = AuthWriteMemory;
+        buf[cnt++] = (segmentNum << 5) | pageNum;   // address 
+
+        // Send command
+        master().OWWriteBlock(&buf[0], 2);
+
+        // Read CRC
+        master().OWReadBlock(&buf[cnt], 2);
+        cnt += 2;
+
+        offset = cnt;
+    }
+
+    // add the data
+    for (size_t i = 0; i < newData.length; i++)
+    {
+        buf[cnt++] = newData[i];
+    }
+
+    // Send data
+    master().OWWriteBlock(newData, newData.length);
+
+    // read first CRC byte
+    master().OWReadByte(buf[cnt++]);
+
+    // read the last CRC and enable power
+    master().OWReadBytePower(buf[cnt++]);
+
+    // now wait for the MAC computation.
+    wait_ms(shaComputationDelayMs);
+
+    // disable strong pullup
+    master().OWSetLevel(OneWireMaster::NormalLevel);
+
+    // check the first CRC16
+    if (!continuing)
+    {
+        if (calculateCrc16(buf, 0, offset) != 0xB001)
+        {
+            return CrcError;
+        }
+    }
+
+    // check the second CRC16
+    uint16_t CRC16 = 0;
+
+    // DS28E25/DS28E22, crc gets calculagted with CS byte
+    if ((romId().familyCode() == DS28E25_Family) || (romId().familyCode() == DS28E22_Family))
+    {
+        if (continuing)
+            CRC16 = calculateCrc16(CRC16, 0xAA);
+    }
+
+    CRC16 = calculateCrc16(buf, offset, (cnt - offset), CRC16);
+
+    if (CRC16 != 0xB001)
+    {
+        return CrcError;
+    }
+
+    // compute the mac
+    ISha256MacCoproc::CmdResult result;
+    Mac mac;
+    result = computeSegmentWriteMac(MacCoproc, pageNum, segmentNum, newData, oldData, romId(), manId(), mac);
+    if (result != ISha256MacCoproc::Success)
+    {
+        return OperationFailure;
+    }
+
+    // transmit MAC as a block
+    master().OWWriteBlock(mac, mac.length);
+
+    // calculate CRC on MAC
+    CRC16 = calculateCrc16(mac, 0, mac.length);
+
+    // append read of CRC16 and CS byte
+    master().OWReadBlock(&buf[0], 3);
+    cnt = 3;
+
+    // ckeck CRC16
+    CRC16 = calculateCrc16(buf, 0, (cnt - 1), CRC16);
+
+    if (CRC16 != 0xB001)
+    {
+        return CrcError;
+    }
+
+    // check CS
+    if (buf[cnt - 1] != 0xAA)
+    {
+        return OperationFailure;
+    }
+
+    // send release and strong pull-up
+    master().OWWriteBytePower(0xAA);
+
+    // now wait for the programming.
+    wait_ms(eepromWriteDelayMs);
+
+    // disable strong pullup
+    master().OWSetLevel(OneWireMaster::NormalLevel);
+
+    // read the CS byte
+    master().OWReadByte(cs);
+
+    if (cs == 0xAA)
+    {
+        return Success;
+    }
+    // else
+    return OperationFailure;
+}
+
+OneWireSlave::CmdResult DS28E15_22_25::readSegment(unsigned int page, unsigned int segment, Segment & data, bool continuing) const
+{
+    OneWireMaster::CmdResult result;
+    uint8_t buf[2];
+
+    if (!continuing)
+    {
+        if (selectDevice() != OneWireMaster::Success)
+        {
+            return CommunicationError;
+        }
+        
+        buf[0] = ReadMemory;
+        buf[1] = (segment << 5) | page;
+
+        // Transmit command
+        master().OWWriteBlock(buf, 2);
+
+        // Receive CRC
+        result = master().OWReadBlock(buf, 2);
+    }
+    else if (segment == 0)
+    {
+        // Receive CRC from previous read
+        result = master().OWReadBlock(buf, 2);
+    }
+
+    // Receive data
+    if (result == OneWireMaster::Success)
+    {
+        result = master().OWReadBlock(data, data.length);
+    }
+
+    return (result == OneWireMaster::Success ? OneWireSlave::Success : OneWireSlave::CommunicationError);
+}
+
+OneWireSlave::CmdResult DS28E15_22_25::writeSegment(unsigned int page, unsigned int block, const Segment & data, bool continuing)
+{
+    uint8_t buf[256], cs;
+    int cnt, offset;
+
+    cnt = 0;
+    offset = 0;
+
+    // check if not continuing a previous block write
+    if (!continuing)
+    {
+        if (selectDevice() != OneWireMaster::Success)
+        {
+            return CommunicationError;
+        }
+        
+        buf[cnt++] = WriteMemory;
+        buf[cnt++] = (block << 5) | page;   // address 
+
+        // Send command 
+        master().OWWriteBlock(&buf[0], 2);
+
+        // Read CRC
+        master().OWReadBlock(&buf[cnt], 2);
+        cnt += 2;
+
+        offset = cnt;
+    }
+
+    // add the data
+    for (size_t i = 0; i < data.length; i++)
+    {
+        buf[cnt++] = data[i];
+    }
+
+    // Send data
+    master().OWWriteBlock(data, data.length);
+
+    // Read CRC
+    master().OWReadBlock(&buf[cnt], 2);
+    cnt += 2;
+
+    // check the first CRC16
+    if (!continuing)
+    {
+        if (calculateCrc16(buf, 0, offset) != 0xB001)
+        {
+            return CrcError;
+        }
+    }
+
+    // check the second CRC16
+    if (calculateCrc16(buf, offset, (cnt - offset)) != 0xB001)
+    {
+        return CrcError;
+    }
+
+    // send release and strong pull-up
+    master().OWWriteBytePower(0xAA);
+
+    // now wait for the programming.
+    wait_ms(eepromWriteDelayMs);
+
+    // disable strong pullup
+    master().OWSetLevel(OneWireMaster::NormalLevel);
+
+    // read the CS byte
+    master().OWReadByte(cs);
+
+    if (cs == 0xAA)
+    {
+        return Success;
+    }
+    // else
+    return OperationFailure;
+}
+
+ISha256MacCoproc::CmdResult DS28E15_22_25::computeNextSecret(ISha256MacCoproc & MacCoproc, const Page & bindingPage, unsigned int bindingPageNum, const Scratchpad & partialSecret, const RomId & romId, const ManId & manId)
+{
+    ISha256MacCoproc::SlaveSecretData slaveSecretData;
+
+    // insert ROM number
+    std::memcpy(slaveSecretData, romId, RomId::byteLen);
+
+    slaveSecretData[11] = 0x00;
+    slaveSecretData[10] = bindingPageNum;
+    slaveSecretData[9] = manId[0];
+    slaveSecretData[8] = manId[1];
+
+    return MacCoproc.computeSlaveSecret(ISha256MacCoproc::DevicePage(bindingPage), partialSecret, slaveSecretData);
+}