1-Wire® library for mbed. Complete 1-Wire library that supports our silicon masters along with a bit-bang master on the MAX32600MBED platform with one common interface for mbed. Slave support has also been included and more slaves will be added as time permits.
Dependents: MAXREFDES131_Qt_Demo MAX32630FTHR_iButton_uSD_Logger MAX32630FTHR_DS18B20_uSD_Logger MAXREFDES130_131_Demo ... more
Superseded by MaximInterface.
Diff: Slaves/Authenticators/DS28E15_22_25/DS28E15_22_25.cpp
- Revision:
- 86:2ce08ca58b9e
- Parent:
- 82:c11090a32471
- Child:
- 104:3f48daed532b
--- /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); +}