Device interface library for multiple platforms including Mbed.

Dependents:   DeepCover Embedded Security in IoT MaximInterface MAXREFDES155#

Maxim Interface is a library framework focused on providing flexible and expressive hardware interfaces. Both communication interfaces such as I2C and 1-Wire and device interfaces such as DS18B20 are supported. Modern C++ concepts are used extensively while keeping compatibility with C++98/C++03 and requiring no external dependencies. The embedded-friendly design does not depend on exceptions or RTTI.

The full version of the project is hosted on GitLab: https://gitlab.com/iabenz/MaximInterface

Committer:
IanBenzMaxim
Date:
Fri May 29 16:19:22 2020 -0500
Revision:
12:7eb41621ba22
Parent:
11:3f3bf6bf5e6c
Updated to version 2.2.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
IanBenzMaxim 7:9cd16581b578 1 /*******************************************************************************
IanBenzMaxim 8:5ea891c7d1a1 2 * Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
IanBenzMaxim 7:9cd16581b578 3 *
IanBenzMaxim 7:9cd16581b578 4 * Permission is hereby granted, free of charge, to any person obtaining a
IanBenzMaxim 7:9cd16581b578 5 * copy of this software and associated documentation files (the "Software"),
IanBenzMaxim 7:9cd16581b578 6 * to deal in the Software without restriction, including without limitation
IanBenzMaxim 7:9cd16581b578 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
IanBenzMaxim 7:9cd16581b578 8 * and/or sell copies of the Software, and to permit persons to whom the
IanBenzMaxim 7:9cd16581b578 9 * Software is furnished to do so, subject to the following conditions:
IanBenzMaxim 7:9cd16581b578 10 *
IanBenzMaxim 7:9cd16581b578 11 * The above copyright notice and this permission notice shall be included
IanBenzMaxim 7:9cd16581b578 12 * in all copies or substantial portions of the Software.
IanBenzMaxim 7:9cd16581b578 13 *
IanBenzMaxim 7:9cd16581b578 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
IanBenzMaxim 7:9cd16581b578 15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
IanBenzMaxim 7:9cd16581b578 16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IanBenzMaxim 7:9cd16581b578 17 * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
IanBenzMaxim 7:9cd16581b578 18 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
IanBenzMaxim 7:9cd16581b578 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
IanBenzMaxim 7:9cd16581b578 20 * OTHER DEALINGS IN THE SOFTWARE.
IanBenzMaxim 7:9cd16581b578 21 *
IanBenzMaxim 7:9cd16581b578 22 * Except as contained in this notice, the name of Maxim Integrated
IanBenzMaxim 7:9cd16581b578 23 * Products, Inc. shall not be used except as stated in the Maxim Integrated
IanBenzMaxim 7:9cd16581b578 24 * Products, Inc. Branding Policy.
IanBenzMaxim 7:9cd16581b578 25 *
IanBenzMaxim 7:9cd16581b578 26 * The mere transfer of this software does not imply any licenses
IanBenzMaxim 7:9cd16581b578 27 * of trade secrets, proprietary technology, copyrights, patents,
IanBenzMaxim 7:9cd16581b578 28 * trademarks, maskwork rights, or any other form of intellectual
IanBenzMaxim 7:9cd16581b578 29 * property whatsoever. Maxim Integrated Products, Inc. retains all
IanBenzMaxim 7:9cd16581b578 30 * ownership rights.
IanBenzMaxim 7:9cd16581b578 31 *******************************************************************************/
IanBenzMaxim 7:9cd16581b578 32
IanBenzMaxim 7:9cd16581b578 33 #include <MaximInterfaceCore/Error.hpp>
IanBenzMaxim 7:9cd16581b578 34 #include "DS2465.hpp"
IanBenzMaxim 7:9cd16581b578 35
IanBenzMaxim 8:5ea891c7d1a1 36 #define TRY MaximInterfaceCore_TRY
IanBenzMaxim 8:5ea891c7d1a1 37 #define TRY_VALUE MaximInterfaceCore_TRY_VALUE
IanBenzMaxim 8:5ea891c7d1a1 38
IanBenzMaxim 7:9cd16581b578 39 namespace MaximInterfaceDevices {
IanBenzMaxim 7:9cd16581b578 40
IanBenzMaxim 7:9cd16581b578 41 using namespace Core;
IanBenzMaxim 7:9cd16581b578 42
IanBenzMaxim 8:5ea891c7d1a1 43 // Delay required after writing an EEPROM segment.
IanBenzMaxim 7:9cd16581b578 44 static const int eepromSegmentWriteDelayMs = 10;
IanBenzMaxim 8:5ea891c7d1a1 45
IanBenzMaxim 8:5ea891c7d1a1 46 // Delay required after writing an EEPROM page such as the secret memory.
IanBenzMaxim 7:9cd16581b578 47 static const int eepromPageWriteDelayMs = 8 * eepromSegmentWriteDelayMs;
IanBenzMaxim 8:5ea891c7d1a1 48
IanBenzMaxim 8:5ea891c7d1a1 49 // Delay required for a SHA computation to complete.
IanBenzMaxim 7:9cd16581b578 50 static const int shaComputationDelayMs = 2;
IanBenzMaxim 7:9cd16581b578 51
IanBenzMaxim 7:9cd16581b578 52 static const uint_least8_t scratchpad = 0x00;
IanBenzMaxim 7:9cd16581b578 53 static const uint_least8_t commandReg = 0x60;
IanBenzMaxim 7:9cd16581b578 54
IanBenzMaxim 7:9cd16581b578 55 static const uint_least8_t owTransmitBlockCmd = 0x69;
IanBenzMaxim 7:9cd16581b578 56
IanBenzMaxim 8:5ea891c7d1a1 57 // DS2465 status bits.
IanBenzMaxim 8:5ea891c7d1a1 58 static const uint_least8_t status_1WB = 0x01;
IanBenzMaxim 8:5ea891c7d1a1 59 static const uint_least8_t status_PPD = 0x02;
IanBenzMaxim 8:5ea891c7d1a1 60 static const uint_least8_t status_SD = 0x04;
IanBenzMaxim 8:5ea891c7d1a1 61 static const uint_least8_t status_SBR = 0x20;
IanBenzMaxim 8:5ea891c7d1a1 62 static const uint_least8_t status_TSB = 0x40;
IanBenzMaxim 8:5ea891c7d1a1 63 static const uint_least8_t status_DIR = 0x80;
IanBenzMaxim 7:9cd16581b578 64
IanBenzMaxim 7:9cd16581b578 65 static const int maxBlockSize = 63;
IanBenzMaxim 7:9cd16581b578 66
IanBenzMaxim 7:9cd16581b578 67 const int DS2465::memoryPages;
IanBenzMaxim 7:9cd16581b578 68 const int DS2465::segmentsPerPage;
IanBenzMaxim 7:9cd16581b578 69
IanBenzMaxim 8:5ea891c7d1a1 70 Result<void> DS2465::initialize(Config config) {
IanBenzMaxim 7:9cd16581b578 71 // reset DS2465
IanBenzMaxim 8:5ea891c7d1a1 72 Result<void> result = resetDevice();
IanBenzMaxim 8:5ea891c7d1a1 73 if (result) {
IanBenzMaxim 7:9cd16581b578 74 // write the default configuration setup
IanBenzMaxim 7:9cd16581b578 75 result = writeConfig(config);
IanBenzMaxim 7:9cd16581b578 76 }
IanBenzMaxim 7:9cd16581b578 77 return result;
IanBenzMaxim 7:9cd16581b578 78 }
IanBenzMaxim 7:9cd16581b578 79
IanBenzMaxim 8:5ea891c7d1a1 80 Result<void> DS2465::computeNextMasterSecret(bool swap, int pageNum,
IanBenzMaxim 8:5ea891c7d1a1 81 PageRegion region) {
IanBenzMaxim 8:5ea891c7d1a1 82 Result<void> result = ArgumentOutOfRangeError;
IanBenzMaxim 7:9cd16581b578 83 if (pageNum >= 0) {
IanBenzMaxim 7:9cd16581b578 84 const uint_least8_t command[] = {
IanBenzMaxim 7:9cd16581b578 85 0x1E, static_cast<uint_least8_t>(swap ? (0xC8 | (pageNum << 4) | region)
IanBenzMaxim 7:9cd16581b578 86 : 0xBF)};
IanBenzMaxim 7:9cd16581b578 87 result = writeMemory(commandReg, command);
IanBenzMaxim 7:9cd16581b578 88 }
IanBenzMaxim 7:9cd16581b578 89 return result;
IanBenzMaxim 7:9cd16581b578 90 }
IanBenzMaxim 7:9cd16581b578 91
IanBenzMaxim 8:5ea891c7d1a1 92 Result<void> DS2465::computeWriteMac(bool regwrite, bool swap, int pageNum,
IanBenzMaxim 8:5ea891c7d1a1 93 int segmentNum) const {
IanBenzMaxim 8:5ea891c7d1a1 94 Result<void> result = ArgumentOutOfRangeError;
IanBenzMaxim 7:9cd16581b578 95 if (pageNum >= 0 && segmentNum >= 0) {
IanBenzMaxim 7:9cd16581b578 96 const uint_least8_t command[] = {
IanBenzMaxim 7:9cd16581b578 97 0x2D, static_cast<uint_least8_t>((regwrite << 7) | (swap << 6) |
IanBenzMaxim 7:9cd16581b578 98 (pageNum << 4) | segmentNum)};
IanBenzMaxim 7:9cd16581b578 99 result = writeMemory(commandReg, command);
IanBenzMaxim 8:5ea891c7d1a1 100 if (result) {
IanBenzMaxim 7:9cd16581b578 101 sleep->invoke(shaComputationDelayMs);
IanBenzMaxim 7:9cd16581b578 102 }
IanBenzMaxim 7:9cd16581b578 103 }
IanBenzMaxim 7:9cd16581b578 104 return result;
IanBenzMaxim 7:9cd16581b578 105 }
IanBenzMaxim 7:9cd16581b578 106
IanBenzMaxim 8:5ea891c7d1a1 107 Result<void> DS2465::computeAuthMac(bool swap, int pageNum,
IanBenzMaxim 8:5ea891c7d1a1 108 PageRegion region) const {
IanBenzMaxim 8:5ea891c7d1a1 109 Result<void> result = ArgumentOutOfRangeError;
IanBenzMaxim 7:9cd16581b578 110 if (pageNum >= 0) {
IanBenzMaxim 7:9cd16581b578 111 const uint_least8_t command[] = {
IanBenzMaxim 7:9cd16581b578 112 0x3C, static_cast<uint_least8_t>(swap ? (0xC8 | (pageNum << 4) | region)
IanBenzMaxim 7:9cd16581b578 113 : 0xBF)};
IanBenzMaxim 7:9cd16581b578 114 result = writeMemory(commandReg, command);
IanBenzMaxim 8:5ea891c7d1a1 115 if (result) {
IanBenzMaxim 7:9cd16581b578 116 sleep->invoke(shaComputationDelayMs * 2);
IanBenzMaxim 7:9cd16581b578 117 }
IanBenzMaxim 7:9cd16581b578 118 }
IanBenzMaxim 7:9cd16581b578 119 return result;
IanBenzMaxim 7:9cd16581b578 120 }
IanBenzMaxim 7:9cd16581b578 121
IanBenzMaxim 8:5ea891c7d1a1 122 Result<void> DS2465::computeSlaveSecret(bool swap, int pageNum,
IanBenzMaxim 8:5ea891c7d1a1 123 PageRegion region) {
IanBenzMaxim 8:5ea891c7d1a1 124 Result<void> result = ArgumentOutOfRangeError;
IanBenzMaxim 7:9cd16581b578 125 if (pageNum >= 0) {
IanBenzMaxim 7:9cd16581b578 126 const uint_least8_t command[] = {
IanBenzMaxim 7:9cd16581b578 127 0x4B, static_cast<uint_least8_t>(swap ? (0xC8 | (pageNum << 4) | region)
IanBenzMaxim 7:9cd16581b578 128 : 0xBF)};
IanBenzMaxim 7:9cd16581b578 129 result = writeMemory(commandReg, command);
IanBenzMaxim 8:5ea891c7d1a1 130 if (result) {
IanBenzMaxim 7:9cd16581b578 131 sleep->invoke(shaComputationDelayMs * 2);
IanBenzMaxim 7:9cd16581b578 132 }
IanBenzMaxim 7:9cd16581b578 133 }
IanBenzMaxim 7:9cd16581b578 134 return result;
IanBenzMaxim 7:9cd16581b578 135 }
IanBenzMaxim 7:9cd16581b578 136
IanBenzMaxim 8:5ea891c7d1a1 137 Result<DS2465::Page::array> DS2465::readPage(int pageNum) const {
IanBenzMaxim 7:9cd16581b578 138 uint_least8_t addr;
IanBenzMaxim 7:9cd16581b578 139 switch (pageNum) {
IanBenzMaxim 7:9cd16581b578 140 case 0:
IanBenzMaxim 7:9cd16581b578 141 addr = 0x80;
IanBenzMaxim 7:9cd16581b578 142 break;
IanBenzMaxim 7:9cd16581b578 143 case 1:
IanBenzMaxim 7:9cd16581b578 144 addr = 0xA0;
IanBenzMaxim 7:9cd16581b578 145 break;
IanBenzMaxim 7:9cd16581b578 146 default:
IanBenzMaxim 8:5ea891c7d1a1 147 return ArgumentOutOfRangeError;
IanBenzMaxim 7:9cd16581b578 148 }
IanBenzMaxim 8:5ea891c7d1a1 149 Page::array data;
IanBenzMaxim 8:5ea891c7d1a1 150 TRY(readMemory(addr, data));
IanBenzMaxim 8:5ea891c7d1a1 151 return data;
IanBenzMaxim 7:9cd16581b578 152 }
IanBenzMaxim 7:9cd16581b578 153
IanBenzMaxim 8:5ea891c7d1a1 154 Result<void> DS2465::writePage(int pageNum, Page::const_span data) {
IanBenzMaxim 8:5ea891c7d1a1 155 Result<void> result = writeMemory(scratchpad, data);
IanBenzMaxim 8:5ea891c7d1a1 156 if (result) {
IanBenzMaxim 7:9cd16581b578 157 result = copyScratchpad(false, pageNum, false, 0);
IanBenzMaxim 7:9cd16581b578 158 }
IanBenzMaxim 8:5ea891c7d1a1 159 if (result) {
IanBenzMaxim 7:9cd16581b578 160 sleep->invoke(eepromPageWriteDelayMs);
IanBenzMaxim 7:9cd16581b578 161 }
IanBenzMaxim 7:9cd16581b578 162 return result;
IanBenzMaxim 7:9cd16581b578 163 }
IanBenzMaxim 7:9cd16581b578 164
IanBenzMaxim 8:5ea891c7d1a1 165 Result<void> DS2465::writeSegment(int pageNum, int segmentNum,
IanBenzMaxim 8:5ea891c7d1a1 166 Segment::const_span data) {
IanBenzMaxim 8:5ea891c7d1a1 167 Result<void> result = writeMemory(scratchpad, data);
IanBenzMaxim 8:5ea891c7d1a1 168 if (result) {
IanBenzMaxim 7:9cd16581b578 169 result = copyScratchpad(false, pageNum, true, segmentNum);
IanBenzMaxim 7:9cd16581b578 170 }
IanBenzMaxim 8:5ea891c7d1a1 171 if (result) {
IanBenzMaxim 7:9cd16581b578 172 sleep->invoke(eepromSegmentWriteDelayMs);
IanBenzMaxim 7:9cd16581b578 173 }
IanBenzMaxim 7:9cd16581b578 174 return result;
IanBenzMaxim 7:9cd16581b578 175 }
IanBenzMaxim 7:9cd16581b578 176
IanBenzMaxim 8:5ea891c7d1a1 177 Result<void> DS2465::writeMasterSecret(Page::const_span masterSecret) {
IanBenzMaxim 8:5ea891c7d1a1 178 Result<void> result = writeMemory(scratchpad, masterSecret);
IanBenzMaxim 8:5ea891c7d1a1 179 if (result) {
IanBenzMaxim 7:9cd16581b578 180 result = copyScratchpad(true, 0, false, 0);
IanBenzMaxim 7:9cd16581b578 181 }
IanBenzMaxim 8:5ea891c7d1a1 182 if (result) {
IanBenzMaxim 7:9cd16581b578 183 sleep->invoke(eepromPageWriteDelayMs);
IanBenzMaxim 7:9cd16581b578 184 }
IanBenzMaxim 7:9cd16581b578 185 return result;
IanBenzMaxim 7:9cd16581b578 186 }
IanBenzMaxim 7:9cd16581b578 187
IanBenzMaxim 8:5ea891c7d1a1 188 Result<void> DS2465::copyScratchpad(bool destSecret, int pageNum, bool notFull,
IanBenzMaxim 8:5ea891c7d1a1 189 int segmentNum) {
IanBenzMaxim 8:5ea891c7d1a1 190 Result<void> result = ArgumentOutOfRangeError;
IanBenzMaxim 7:9cd16581b578 191 if (pageNum >= 0 && segmentNum >= 0) {
IanBenzMaxim 7:9cd16581b578 192 const uint_least8_t command[] = {
IanBenzMaxim 7:9cd16581b578 193 0x5A,
IanBenzMaxim 7:9cd16581b578 194 static_cast<uint_least8_t>(destSecret ? 0
IanBenzMaxim 7:9cd16581b578 195 : (0x80 | (pageNum << 4) |
IanBenzMaxim 7:9cd16581b578 196 (notFull << 3) | segmentNum))};
IanBenzMaxim 7:9cd16581b578 197 result = writeMemory(commandReg, command);
IanBenzMaxim 7:9cd16581b578 198 }
IanBenzMaxim 7:9cd16581b578 199 return result;
IanBenzMaxim 7:9cd16581b578 200 }
IanBenzMaxim 7:9cd16581b578 201
IanBenzMaxim 8:5ea891c7d1a1 202 Result<void> DS2465::configureLevel(Level level) {
IanBenzMaxim 7:9cd16581b578 203 // Check if supported level
IanBenzMaxim 7:9cd16581b578 204 if (!((level == NormalLevel) || (level == StrongLevel))) {
IanBenzMaxim 8:5ea891c7d1a1 205 return InvalidLevelError;
IanBenzMaxim 7:9cd16581b578 206 }
IanBenzMaxim 7:9cd16581b578 207 // Check if requested level already set
IanBenzMaxim 7:9cd16581b578 208 if (curConfig.getSPU() == (level == StrongLevel)) {
IanBenzMaxim 8:5ea891c7d1a1 209 return none;
IanBenzMaxim 7:9cd16581b578 210 }
IanBenzMaxim 7:9cd16581b578 211 // Set the level
IanBenzMaxim 7:9cd16581b578 212 return writeConfig(Config(curConfig).setSPU(level == StrongLevel));
IanBenzMaxim 7:9cd16581b578 213 }
IanBenzMaxim 7:9cd16581b578 214
IanBenzMaxim 8:5ea891c7d1a1 215 Result<void> DS2465::setLevel(Level newLevel) {
IanBenzMaxim 7:9cd16581b578 216 if (newLevel == StrongLevel) {
IanBenzMaxim 8:5ea891c7d1a1 217 return InvalidLevelError;
IanBenzMaxim 7:9cd16581b578 218 }
IanBenzMaxim 7:9cd16581b578 219
IanBenzMaxim 7:9cd16581b578 220 return configureLevel(newLevel);
IanBenzMaxim 7:9cd16581b578 221 }
IanBenzMaxim 7:9cd16581b578 222
IanBenzMaxim 8:5ea891c7d1a1 223 Result<void> DS2465::setSpeed(Speed newSpeed) {
IanBenzMaxim 7:9cd16581b578 224 // Check if supported speed
IanBenzMaxim 7:9cd16581b578 225 if (!((newSpeed == OverdriveSpeed) || (newSpeed == StandardSpeed))) {
IanBenzMaxim 8:5ea891c7d1a1 226 return InvalidSpeedError;
IanBenzMaxim 7:9cd16581b578 227 }
IanBenzMaxim 7:9cd16581b578 228 // Check if requested speed is already set
IanBenzMaxim 7:9cd16581b578 229 if (curConfig.get1WS() == (newSpeed == OverdriveSpeed)) {
IanBenzMaxim 8:5ea891c7d1a1 230 return none;
IanBenzMaxim 7:9cd16581b578 231 }
IanBenzMaxim 7:9cd16581b578 232 // Set the speed
IanBenzMaxim 7:9cd16581b578 233 return writeConfig(Config(curConfig).set1WS(newSpeed == OverdriveSpeed));
IanBenzMaxim 7:9cd16581b578 234 }
IanBenzMaxim 7:9cd16581b578 235
IanBenzMaxim 8:5ea891c7d1a1 236 Result<OneWireMaster::TripletData> DS2465::triplet(bool sendBit) {
IanBenzMaxim 7:9cd16581b578 237 // 1-Wire Triplet (Case B)
IanBenzMaxim 7:9cd16581b578 238 // S AD,0 [A] 1WT [A] SS [A] Sr AD,1 [A] [Status] A [Status] A\ P
IanBenzMaxim 7:9cd16581b578 239 // \--------/
IanBenzMaxim 7:9cd16581b578 240 // Repeat until 1WB bit has changed to 0
IanBenzMaxim 7:9cd16581b578 241 // [] indicates from slave
IanBenzMaxim 7:9cd16581b578 242 // SS indicates byte containing search direction bit value in msbit
IanBenzMaxim 7:9cd16581b578 243
IanBenzMaxim 7:9cd16581b578 244 const uint_least8_t command[] = {
IanBenzMaxim 8:5ea891c7d1a1 245 0x78, static_cast<uint_least8_t>(sendBit ? 0x80 : 0x00)};
IanBenzMaxim 8:5ea891c7d1a1 246 TRY(writeMemory(commandReg, command));
IanBenzMaxim 8:5ea891c7d1a1 247
IanBenzMaxim 8:5ea891c7d1a1 248 uint_least8_t status;
IanBenzMaxim 8:5ea891c7d1a1 249 TRY_VALUE(status, pollBusy());
IanBenzMaxim 8:5ea891c7d1a1 250
IanBenzMaxim 8:5ea891c7d1a1 251 TripletData data;
IanBenzMaxim 8:5ea891c7d1a1 252 data.readBit = ((status & status_SBR) == status_SBR);
IanBenzMaxim 8:5ea891c7d1a1 253 data.readBitComplement = ((status & status_TSB) == status_TSB);
IanBenzMaxim 8:5ea891c7d1a1 254 data.writeBit = ((status & status_DIR) == status_DIR);
IanBenzMaxim 8:5ea891c7d1a1 255 return data;
IanBenzMaxim 7:9cd16581b578 256 }
IanBenzMaxim 7:9cd16581b578 257
IanBenzMaxim 8:5ea891c7d1a1 258 Result<void> DS2465::readBlock(span<uint_least8_t> recvBuf) {
IanBenzMaxim 7:9cd16581b578 259 // 1-Wire Receive Block (Case A)
IanBenzMaxim 7:9cd16581b578 260 // S AD,0 [A] CommandReg [A] 1WRF [A] PR [A] P
IanBenzMaxim 7:9cd16581b578 261 // [] indicates from slave
IanBenzMaxim 7:9cd16581b578 262 // PR indicates byte containing parameter
IanBenzMaxim 7:9cd16581b578 263
IanBenzMaxim 7:9cd16581b578 264 span<uint_least8_t>::index_type recvIdx = 0;
IanBenzMaxim 8:5ea891c7d1a1 265 while (recvIdx < recvBuf.size()) {
IanBenzMaxim 7:9cd16581b578 266 const uint_least8_t command[] = {
IanBenzMaxim 7:9cd16581b578 267 0xE1,
IanBenzMaxim 7:9cd16581b578 268 static_cast<uint_least8_t>(std::min<span<uint_least8_t>::index_type>(
IanBenzMaxim 7:9cd16581b578 269 recvBuf.size() - recvIdx, maxBlockSize))};
IanBenzMaxim 8:5ea891c7d1a1 270 TRY(writeMemory(commandReg, command));
IanBenzMaxim 8:5ea891c7d1a1 271 TRY(pollBusy());
IanBenzMaxim 8:5ea891c7d1a1 272 TRY(readMemory(scratchpad, recvBuf.subspan(recvIdx, command[1])));
IanBenzMaxim 7:9cd16581b578 273 recvIdx += command[1];
IanBenzMaxim 7:9cd16581b578 274 }
IanBenzMaxim 8:5ea891c7d1a1 275 return none;
IanBenzMaxim 7:9cd16581b578 276 }
IanBenzMaxim 7:9cd16581b578 277
IanBenzMaxim 8:5ea891c7d1a1 278 Result<void> DS2465::writeBlock(span<const uint_least8_t> sendBuf) {
IanBenzMaxim 7:9cd16581b578 279 span<const uint_least8_t>::index_type sendIdx = 0;
IanBenzMaxim 8:5ea891c7d1a1 280 while (sendIdx < sendBuf.size()) {
IanBenzMaxim 7:9cd16581b578 281 const uint_least8_t command[] = {
IanBenzMaxim 7:9cd16581b578 282 owTransmitBlockCmd, static_cast<uint_least8_t>(
IanBenzMaxim 7:9cd16581b578 283 std::min<span<const uint_least8_t>::index_type>(
IanBenzMaxim 7:9cd16581b578 284 sendBuf.size() - sendIdx, maxBlockSize))};
IanBenzMaxim 7:9cd16581b578 285
IanBenzMaxim 7:9cd16581b578 286 // prefill scratchpad with required data
IanBenzMaxim 8:5ea891c7d1a1 287 TRY(writeMemory(scratchpad, sendBuf.subspan(sendIdx, command[1])));
IanBenzMaxim 7:9cd16581b578 288
IanBenzMaxim 7:9cd16581b578 289 // 1-Wire Transmit Block (Case A)
IanBenzMaxim 7:9cd16581b578 290 // S AD,0 [A] CommandReg [A] 1WTB [A] PR [A] P
IanBenzMaxim 7:9cd16581b578 291 // [] indicates from slave
IanBenzMaxim 7:9cd16581b578 292 // PR indicates byte containing parameter
IanBenzMaxim 8:5ea891c7d1a1 293 TRY(writeMemory(commandReg, command));
IanBenzMaxim 8:5ea891c7d1a1 294 TRY(pollBusy());
IanBenzMaxim 7:9cd16581b578 295 sendIdx += command[1];
IanBenzMaxim 7:9cd16581b578 296 }
IanBenzMaxim 8:5ea891c7d1a1 297 return none;
IanBenzMaxim 7:9cd16581b578 298 }
IanBenzMaxim 7:9cd16581b578 299
IanBenzMaxim 8:5ea891c7d1a1 300 Result<void> DS2465::writeMacBlock() {
IanBenzMaxim 7:9cd16581b578 301 // 1-Wire Transmit Block (Case A)
IanBenzMaxim 7:9cd16581b578 302 // S AD,0 [A] CommandReg [A] 1WTB [A] PR [A] P
IanBenzMaxim 7:9cd16581b578 303 // [] indicates from slave
IanBenzMaxim 7:9cd16581b578 304 // PR indicates byte containing parameter
IanBenzMaxim 7:9cd16581b578 305
IanBenzMaxim 7:9cd16581b578 306 const uint_least8_t command[] = {owTransmitBlockCmd, 0xFF};
IanBenzMaxim 8:5ea891c7d1a1 307 TRY(writeMemory(commandReg, command));
IanBenzMaxim 8:5ea891c7d1a1 308 TRY(pollBusy());
IanBenzMaxim 8:5ea891c7d1a1 309 return none;
IanBenzMaxim 7:9cd16581b578 310 }
IanBenzMaxim 7:9cd16581b578 311
IanBenzMaxim 8:5ea891c7d1a1 312 Result<uint_least8_t> DS2465::readByteSetLevel(Level afterLevel) {
IanBenzMaxim 7:9cd16581b578 313 // 1-Wire Read Bytes (Case C)
IanBenzMaxim 7:9cd16581b578 314 // S AD,0 [A] CommandReg [A] 1WRB [A] Sr AD,1 [A] [Status] A [Status] A
IanBenzMaxim 7:9cd16581b578 315 // \--------/
IanBenzMaxim 7:9cd16581b578 316 // Repeat until 1WB bit has changed to 0
IanBenzMaxim 7:9cd16581b578 317 // Sr AD,0 [A] SRP [A] E1 [A] Sr AD,1 [A] DD A\ P
IanBenzMaxim 7:9cd16581b578 318 //
IanBenzMaxim 7:9cd16581b578 319 // [] indicates from slave
IanBenzMaxim 7:9cd16581b578 320 // DD data read
IanBenzMaxim 7:9cd16581b578 321
IanBenzMaxim 8:5ea891c7d1a1 322 TRY(configureLevel(afterLevel));
IanBenzMaxim 7:9cd16581b578 323
IanBenzMaxim 8:5ea891c7d1a1 324 uint_least8_t buf = 0x96;
IanBenzMaxim 8:5ea891c7d1a1 325 TRY(writeMemory(commandReg, make_span(&buf, 1)));
IanBenzMaxim 8:5ea891c7d1a1 326 TRY(pollBusy());
IanBenzMaxim 8:5ea891c7d1a1 327 TRY(readMemory(0x62, make_span(&buf, 1)));
IanBenzMaxim 8:5ea891c7d1a1 328 return buf;
IanBenzMaxim 7:9cd16581b578 329 }
IanBenzMaxim 7:9cd16581b578 330
IanBenzMaxim 8:5ea891c7d1a1 331 Result<void> DS2465::writeByteSetLevel(uint_least8_t sendByte,
IanBenzMaxim 8:5ea891c7d1a1 332 Level afterLevel) {
IanBenzMaxim 7:9cd16581b578 333 // 1-Wire Write Byte (Case B)
IanBenzMaxim 7:9cd16581b578 334 // S AD,0 [A] CommandReg [A] 1WWB [A] DD [A] Sr AD,1 [A] [Status] A [Status]
IanBenzMaxim 7:9cd16581b578 335 // A\ P
IanBenzMaxim 7:9cd16581b578 336 // \--------/
IanBenzMaxim 7:9cd16581b578 337 // Repeat until 1WB bit has changed to 0
IanBenzMaxim 7:9cd16581b578 338 // [] indicates from slave
IanBenzMaxim 7:9cd16581b578 339 // DD data to write
IanBenzMaxim 7:9cd16581b578 340
IanBenzMaxim 8:5ea891c7d1a1 341 TRY(configureLevel(afterLevel));
IanBenzMaxim 7:9cd16581b578 342
IanBenzMaxim 7:9cd16581b578 343 const uint_least8_t command[] = {0xA5, sendByte};
IanBenzMaxim 8:5ea891c7d1a1 344 TRY(writeMemory(commandReg, command));
IanBenzMaxim 8:5ea891c7d1a1 345 TRY(pollBusy());
IanBenzMaxim 8:5ea891c7d1a1 346 return none;
IanBenzMaxim 7:9cd16581b578 347 }
IanBenzMaxim 7:9cd16581b578 348
IanBenzMaxim 8:5ea891c7d1a1 349 Result<bool> DS2465::touchBitSetLevel(bool sendBit, Level afterLevel) {
IanBenzMaxim 7:9cd16581b578 350 // 1-Wire bit (Case B)
IanBenzMaxim 7:9cd16581b578 351 // S AD,0 [A] CommandReg [A] 1WSB [A] BB [A] Sr AD,1 [A] [Status] A [Status]
IanBenzMaxim 7:9cd16581b578 352 // A\ P
IanBenzMaxim 7:9cd16581b578 353 // \--------/
IanBenzMaxim 7:9cd16581b578 354 // Repeat until 1WB bit has changed to 0
IanBenzMaxim 7:9cd16581b578 355 // [] indicates from slave
IanBenzMaxim 7:9cd16581b578 356 // BB indicates byte containing bit value in msbit
IanBenzMaxim 7:9cd16581b578 357
IanBenzMaxim 8:5ea891c7d1a1 358 TRY(configureLevel(afterLevel));
IanBenzMaxim 7:9cd16581b578 359
IanBenzMaxim 7:9cd16581b578 360 const uint_least8_t command[] = {
IanBenzMaxim 8:5ea891c7d1a1 361 0x87, static_cast<uint_least8_t>(sendBit ? 0x80 : 0x00)};
IanBenzMaxim 8:5ea891c7d1a1 362 TRY(writeMemory(commandReg, command));
IanBenzMaxim 7:9cd16581b578 363
IanBenzMaxim 7:9cd16581b578 364 uint_least8_t status;
IanBenzMaxim 8:5ea891c7d1a1 365 TRY_VALUE(status, pollBusy());
IanBenzMaxim 8:5ea891c7d1a1 366
IanBenzMaxim 8:5ea891c7d1a1 367 return (status & status_SBR) == status_SBR;
IanBenzMaxim 7:9cd16581b578 368 }
IanBenzMaxim 7:9cd16581b578 369
IanBenzMaxim 8:5ea891c7d1a1 370 Result<void> DS2465::writeMemory(uint_least8_t addr,
IanBenzMaxim 8:5ea891c7d1a1 371 span<const uint_least8_t> buf) const {
IanBenzMaxim 7:9cd16581b578 372 // Write SRAM (Case A)
IanBenzMaxim 7:9cd16581b578 373 // S AD,0 [A] VSA [A] DD [A] P
IanBenzMaxim 7:9cd16581b578 374 // \-----/
IanBenzMaxim 7:9cd16581b578 375 // Repeat for each data byte
IanBenzMaxim 7:9cd16581b578 376 // [] indicates from slave
IanBenzMaxim 7:9cd16581b578 377 // VSA valid SRAM memory address
IanBenzMaxim 7:9cd16581b578 378 // DD memory data to write
IanBenzMaxim 7:9cd16581b578 379
IanBenzMaxim 8:5ea891c7d1a1 380 Result<void> result = master->start(address_);
IanBenzMaxim 8:5ea891c7d1a1 381 if (!result) {
IanBenzMaxim 7:9cd16581b578 382 master->stop();
IanBenzMaxim 7:9cd16581b578 383 return result;
IanBenzMaxim 7:9cd16581b578 384 }
IanBenzMaxim 7:9cd16581b578 385 result = master->writeByte(addr);
IanBenzMaxim 8:5ea891c7d1a1 386 if (!result) {
IanBenzMaxim 7:9cd16581b578 387 master->stop();
IanBenzMaxim 7:9cd16581b578 388 return result;
IanBenzMaxim 7:9cd16581b578 389 }
IanBenzMaxim 7:9cd16581b578 390 result = master->writeBlock(buf);
IanBenzMaxim 8:5ea891c7d1a1 391 if (!result) {
IanBenzMaxim 7:9cd16581b578 392 master->stop();
IanBenzMaxim 7:9cd16581b578 393 return result;
IanBenzMaxim 7:9cd16581b578 394 }
IanBenzMaxim 7:9cd16581b578 395 result = master->stop();
IanBenzMaxim 7:9cd16581b578 396 return result;
IanBenzMaxim 7:9cd16581b578 397 }
IanBenzMaxim 7:9cd16581b578 398
IanBenzMaxim 8:5ea891c7d1a1 399 Result<void> DS2465::readMemory(uint_least8_t addr,
IanBenzMaxim 8:5ea891c7d1a1 400 span<uint_least8_t> buf) const {
IanBenzMaxim 7:9cd16581b578 401 // Read (Case A)
IanBenzMaxim 7:9cd16581b578 402 // S AD,0 [A] MA [A] Sr AD,1 [A] [DD] A [DD] A\ P
IanBenzMaxim 7:9cd16581b578 403 // \-----/
IanBenzMaxim 7:9cd16581b578 404 // Repeat for each data byte, NAK last byte
IanBenzMaxim 7:9cd16581b578 405 // [] indicates from slave
IanBenzMaxim 7:9cd16581b578 406 // MA memory address
IanBenzMaxim 7:9cd16581b578 407 // DD memory data read
IanBenzMaxim 7:9cd16581b578 408
IanBenzMaxim 8:5ea891c7d1a1 409 Result<void> result = master->start(address_);
IanBenzMaxim 8:5ea891c7d1a1 410 if (!result) {
IanBenzMaxim 7:9cd16581b578 411 master->stop();
IanBenzMaxim 7:9cd16581b578 412 return result;
IanBenzMaxim 7:9cd16581b578 413 }
IanBenzMaxim 7:9cd16581b578 414 result = master->writeByte(addr);
IanBenzMaxim 8:5ea891c7d1a1 415 if (!result) {
IanBenzMaxim 7:9cd16581b578 416 master->stop();
IanBenzMaxim 7:9cd16581b578 417 return result;
IanBenzMaxim 7:9cd16581b578 418 }
IanBenzMaxim 7:9cd16581b578 419 result = readMemory(buf);
IanBenzMaxim 7:9cd16581b578 420 return result;
IanBenzMaxim 7:9cd16581b578 421 }
IanBenzMaxim 7:9cd16581b578 422
IanBenzMaxim 8:5ea891c7d1a1 423 Result<void> DS2465::readMemory(span<uint_least8_t> buf) const {
IanBenzMaxim 8:5ea891c7d1a1 424 Result<void> result = master->start(address_ | 1);
IanBenzMaxim 8:5ea891c7d1a1 425 if (!result) {
IanBenzMaxim 7:9cd16581b578 426 master->stop();
IanBenzMaxim 7:9cd16581b578 427 return result;
IanBenzMaxim 7:9cd16581b578 428 }
IanBenzMaxim 8:5ea891c7d1a1 429 result = master->readBlock(buf, I2CMaster::Nack);
IanBenzMaxim 8:5ea891c7d1a1 430 if (!result) {
IanBenzMaxim 7:9cd16581b578 431 master->stop();
IanBenzMaxim 7:9cd16581b578 432 return result;
IanBenzMaxim 7:9cd16581b578 433 }
IanBenzMaxim 7:9cd16581b578 434 result = master->stop();
IanBenzMaxim 7:9cd16581b578 435 return result;
IanBenzMaxim 7:9cd16581b578 436 }
IanBenzMaxim 7:9cd16581b578 437
IanBenzMaxim 8:5ea891c7d1a1 438 Result<void> DS2465::writeConfig(Config config) {
IanBenzMaxim 7:9cd16581b578 439 const uint_least8_t configReg = 0x67;
IanBenzMaxim 7:9cd16581b578 440 uint_least8_t configBuf =
IanBenzMaxim 7:9cd16581b578 441 ((config.readByte() ^ 0xF) << 4) | config.readByte();
IanBenzMaxim 8:5ea891c7d1a1 442 Result<void> result = writeMemory(configReg, make_span(&configBuf, 1));
IanBenzMaxim 8:5ea891c7d1a1 443 if (result) {
IanBenzMaxim 7:9cd16581b578 444 result = readMemory(configReg, make_span(&configBuf, 1));
IanBenzMaxim 7:9cd16581b578 445 }
IanBenzMaxim 8:5ea891c7d1a1 446 if (result && configBuf != config.readByte()) {
IanBenzMaxim 8:5ea891c7d1a1 447 result = HardwareError;
IanBenzMaxim 7:9cd16581b578 448 }
IanBenzMaxim 8:5ea891c7d1a1 449 if (result) {
IanBenzMaxim 7:9cd16581b578 450 curConfig = config;
IanBenzMaxim 7:9cd16581b578 451 }
IanBenzMaxim 7:9cd16581b578 452 return result;
IanBenzMaxim 7:9cd16581b578 453 }
IanBenzMaxim 7:9cd16581b578 454
IanBenzMaxim 8:5ea891c7d1a1 455 Result<void> DS2465::writePortParameter(PortParameter param, int val) {
IanBenzMaxim 7:9cd16581b578 456 if (val < 0 || val > 15) {
IanBenzMaxim 8:5ea891c7d1a1 457 return ArgumentOutOfRangeError;
IanBenzMaxim 7:9cd16581b578 458 }
IanBenzMaxim 7:9cd16581b578 459
IanBenzMaxim 7:9cd16581b578 460 uint_least8_t addr = 0;
IanBenzMaxim 7:9cd16581b578 461 switch (param) {
IanBenzMaxim 7:9cd16581b578 462 case tRSTL_STD:
IanBenzMaxim 7:9cd16581b578 463 case tRSTL_OD:
IanBenzMaxim 7:9cd16581b578 464 addr = 0x68;
IanBenzMaxim 7:9cd16581b578 465 break;
IanBenzMaxim 7:9cd16581b578 466 case tMSP_STD:
IanBenzMaxim 7:9cd16581b578 467 case tMSP_OD:
IanBenzMaxim 7:9cd16581b578 468 addr = 0x69;
IanBenzMaxim 7:9cd16581b578 469 break;
IanBenzMaxim 7:9cd16581b578 470 case tW0L_STD:
IanBenzMaxim 7:9cd16581b578 471 case tW0L_OD:
IanBenzMaxim 7:9cd16581b578 472 addr = 0x6A;
IanBenzMaxim 7:9cd16581b578 473 break;
IanBenzMaxim 7:9cd16581b578 474 case tREC0:
IanBenzMaxim 7:9cd16581b578 475 addr = 0x6B;
IanBenzMaxim 7:9cd16581b578 476 break;
IanBenzMaxim 7:9cd16581b578 477 case RWPU:
IanBenzMaxim 7:9cd16581b578 478 addr = 0x6C;
IanBenzMaxim 7:9cd16581b578 479 break;
IanBenzMaxim 7:9cd16581b578 480 case tW1L_OD:
IanBenzMaxim 7:9cd16581b578 481 addr = 0x6D;
IanBenzMaxim 7:9cd16581b578 482 break;
IanBenzMaxim 7:9cd16581b578 483 }
IanBenzMaxim 7:9cd16581b578 484
IanBenzMaxim 7:9cd16581b578 485 uint_least8_t data;
IanBenzMaxim 8:5ea891c7d1a1 486 Result<void> result = readMemory(addr, make_span(&data, 1));
IanBenzMaxim 8:5ea891c7d1a1 487 if (!result) {
IanBenzMaxim 7:9cd16581b578 488 return result;
IanBenzMaxim 7:9cd16581b578 489 }
IanBenzMaxim 7:9cd16581b578 490
IanBenzMaxim 7:9cd16581b578 491 uint_least8_t newData;
IanBenzMaxim 7:9cd16581b578 492 if (param == tRSTL_OD || param == tMSP_OD || param == tW0L_OD) {
IanBenzMaxim 7:9cd16581b578 493 newData = (data & 0x0F) | (val << 4);
IanBenzMaxim 7:9cd16581b578 494 } else {
IanBenzMaxim 7:9cd16581b578 495 newData = (data & 0xF0) | val;
IanBenzMaxim 7:9cd16581b578 496 }
IanBenzMaxim 7:9cd16581b578 497
IanBenzMaxim 7:9cd16581b578 498 if (newData != data) {
IanBenzMaxim 7:9cd16581b578 499 result = writeMemory(addr, make_span(&newData, 1));
IanBenzMaxim 7:9cd16581b578 500 }
IanBenzMaxim 7:9cd16581b578 501 return result;
IanBenzMaxim 7:9cd16581b578 502 }
IanBenzMaxim 7:9cd16581b578 503
IanBenzMaxim 8:5ea891c7d1a1 504 Result<uint_least8_t> DS2465::pollBusy() const {
IanBenzMaxim 7:9cd16581b578 505 const int pollLimit = 200;
IanBenzMaxim 7:9cd16581b578 506
IanBenzMaxim 7:9cd16581b578 507 int pollCount = 0;
IanBenzMaxim 7:9cd16581b578 508 uint_least8_t status;
IanBenzMaxim 7:9cd16581b578 509 do {
IanBenzMaxim 8:5ea891c7d1a1 510 const Result<void> result = readMemory(make_span(&status, 1));
IanBenzMaxim 8:5ea891c7d1a1 511 if (!result) {
IanBenzMaxim 8:5ea891c7d1a1 512 return result.error();
IanBenzMaxim 7:9cd16581b578 513 }
IanBenzMaxim 7:9cd16581b578 514 if (pollCount++ >= pollLimit) {
IanBenzMaxim 8:5ea891c7d1a1 515 return HardwareError;
IanBenzMaxim 7:9cd16581b578 516 }
IanBenzMaxim 8:5ea891c7d1a1 517 } while ((status & status_1WB) == status_1WB);
IanBenzMaxim 8:5ea891c7d1a1 518 return status;
IanBenzMaxim 7:9cd16581b578 519 }
IanBenzMaxim 7:9cd16581b578 520
IanBenzMaxim 8:5ea891c7d1a1 521 Result<void> DS2465::reset() {
IanBenzMaxim 7:9cd16581b578 522 // 1-Wire reset (Case B)
IanBenzMaxim 7:9cd16581b578 523 // S AD,0 [A] CommandReg [A] 1WRS [A] Sr AD,1 [A] [Status] A [Status] A\ P
IanBenzMaxim 7:9cd16581b578 524 // \--------/
IanBenzMaxim 7:9cd16581b578 525 // Repeat until 1WB bit has changed to 0
IanBenzMaxim 7:9cd16581b578 526 // [] indicates from slave
IanBenzMaxim 7:9cd16581b578 527
IanBenzMaxim 7:9cd16581b578 528 uint_least8_t buf = 0xB4;
IanBenzMaxim 8:5ea891c7d1a1 529 TRY(writeMemory(commandReg, make_span(&buf, 1)));
IanBenzMaxim 8:5ea891c7d1a1 530
IanBenzMaxim 8:5ea891c7d1a1 531 TRY_VALUE(buf, pollBusy());
IanBenzMaxim 7:9cd16581b578 532
IanBenzMaxim 8:5ea891c7d1a1 533 if ((buf & status_SD) == status_SD) {
IanBenzMaxim 8:5ea891c7d1a1 534 return ShortDetectedError;
IanBenzMaxim 8:5ea891c7d1a1 535 }
IanBenzMaxim 8:5ea891c7d1a1 536 if ((buf & status_PPD) != status_PPD) {
IanBenzMaxim 8:5ea891c7d1a1 537 return NoSlaveError;
IanBenzMaxim 7:9cd16581b578 538 }
IanBenzMaxim 7:9cd16581b578 539
IanBenzMaxim 8:5ea891c7d1a1 540 return none;
IanBenzMaxim 7:9cd16581b578 541 }
IanBenzMaxim 7:9cd16581b578 542
IanBenzMaxim 8:5ea891c7d1a1 543 Result<void> DS2465::resetDevice() {
IanBenzMaxim 7:9cd16581b578 544 // Device Reset
IanBenzMaxim 7:9cd16581b578 545 // S AD,0 [A] CommandReg [A] 1WMR [A] Sr AD,1 [A] [SS] A\ P
IanBenzMaxim 7:9cd16581b578 546 // [] indicates from slave
IanBenzMaxim 7:9cd16581b578 547 // SS status byte to read to verify state
IanBenzMaxim 7:9cd16581b578 548
IanBenzMaxim 7:9cd16581b578 549 uint_least8_t buf = 0xF0;
IanBenzMaxim 8:5ea891c7d1a1 550 Result<void> result = writeMemory(commandReg, make_span(&buf, 1));
IanBenzMaxim 7:9cd16581b578 551
IanBenzMaxim 8:5ea891c7d1a1 552 if (result) {
IanBenzMaxim 7:9cd16581b578 553 result = readMemory(make_span(&buf, 1));
IanBenzMaxim 7:9cd16581b578 554 }
IanBenzMaxim 7:9cd16581b578 555
IanBenzMaxim 8:5ea891c7d1a1 556 if (result) {
IanBenzMaxim 7:9cd16581b578 557 if ((buf & 0xF7) != 0x10) {
IanBenzMaxim 8:5ea891c7d1a1 558 result = HardwareError;
IanBenzMaxim 7:9cd16581b578 559 }
IanBenzMaxim 7:9cd16581b578 560 }
IanBenzMaxim 7:9cd16581b578 561
IanBenzMaxim 8:5ea891c7d1a1 562 if (result) {
IanBenzMaxim 7:9cd16581b578 563 reset(); // do a command to get 1-Wire master reset out of holding state
IanBenzMaxim 7:9cd16581b578 564 }
IanBenzMaxim 7:9cd16581b578 565
IanBenzMaxim 7:9cd16581b578 566 return result;
IanBenzMaxim 7:9cd16581b578 567 }
IanBenzMaxim 7:9cd16581b578 568
IanBenzMaxim 8:5ea891c7d1a1 569 Result<void>
IanBenzMaxim 7:9cd16581b578 570 DS2465::computeNextMasterSecret(AuthenticationData::const_span data) {
IanBenzMaxim 8:5ea891c7d1a1 571 Result<void> result = writeMemory(scratchpad, data);
IanBenzMaxim 8:5ea891c7d1a1 572 if (result) {
IanBenzMaxim 7:9cd16581b578 573 result = computeNextMasterSecret(false, 0, FullPage);
IanBenzMaxim 7:9cd16581b578 574 }
IanBenzMaxim 7:9cd16581b578 575 return result;
IanBenzMaxim 7:9cd16581b578 576 }
IanBenzMaxim 7:9cd16581b578 577
IanBenzMaxim 8:5ea891c7d1a1 578 Result<void>
IanBenzMaxim 7:9cd16581b578 579 DS2465::computeNextMasterSecretWithSwap(AuthenticationData::const_span data,
IanBenzMaxim 7:9cd16581b578 580 int pageNum, PageRegion region) {
IanBenzMaxim 8:5ea891c7d1a1 581 Result<void> result = writeMemory(scratchpad, data);
IanBenzMaxim 8:5ea891c7d1a1 582 if (result) {
IanBenzMaxim 7:9cd16581b578 583 result = computeNextMasterSecret(true, pageNum, region);
IanBenzMaxim 7:9cd16581b578 584 }
IanBenzMaxim 7:9cd16581b578 585 return result;
IanBenzMaxim 7:9cd16581b578 586 }
IanBenzMaxim 7:9cd16581b578 587
IanBenzMaxim 8:5ea891c7d1a1 588 Result<void> DS2465::doComputeWriteMac(WriteMacData::const_span data) const {
IanBenzMaxim 8:5ea891c7d1a1 589 Result<void> result = writeMemory(scratchpad, data);
IanBenzMaxim 8:5ea891c7d1a1 590 if (result) {
IanBenzMaxim 7:9cd16581b578 591 result = computeWriteMac(false, false, 0, 0);
IanBenzMaxim 7:9cd16581b578 592 }
IanBenzMaxim 7:9cd16581b578 593 return result;
IanBenzMaxim 7:9cd16581b578 594 }
IanBenzMaxim 7:9cd16581b578 595
IanBenzMaxim 8:5ea891c7d1a1 596 Result<DS2465::Page::array>
IanBenzMaxim 8:5ea891c7d1a1 597 DS2465::computeWriteMac(WriteMacData::const_span data) const {
IanBenzMaxim 8:5ea891c7d1a1 598 Result<void> result = doComputeWriteMac(data);
IanBenzMaxim 7:9cd16581b578 599 if (!result) {
IanBenzMaxim 8:5ea891c7d1a1 600 return result.error();
IanBenzMaxim 7:9cd16581b578 601 }
IanBenzMaxim 8:5ea891c7d1a1 602 Page::array mac;
IanBenzMaxim 8:5ea891c7d1a1 603 result = readMemory(mac);
IanBenzMaxim 8:5ea891c7d1a1 604 if (!result) {
IanBenzMaxim 8:5ea891c7d1a1 605 return result.error();
IanBenzMaxim 8:5ea891c7d1a1 606 }
IanBenzMaxim 8:5ea891c7d1a1 607 return mac;
IanBenzMaxim 7:9cd16581b578 608 }
IanBenzMaxim 7:9cd16581b578 609
IanBenzMaxim 8:5ea891c7d1a1 610 Result<void> DS2465::computeAndTransmitWriteMac(WriteMacData::const_span data) {
IanBenzMaxim 8:5ea891c7d1a1 611 Result<void> result = doComputeWriteMac(data);
IanBenzMaxim 8:5ea891c7d1a1 612 if (result) {
IanBenzMaxim 7:9cd16581b578 613 result = writeMacBlock();
IanBenzMaxim 7:9cd16581b578 614 }
IanBenzMaxim 7:9cd16581b578 615 return result;
IanBenzMaxim 7:9cd16581b578 616 }
IanBenzMaxim 7:9cd16581b578 617
IanBenzMaxim 8:5ea891c7d1a1 618 Result<void> DS2465::doComputeWriteMacWithSwap(WriteMacData::const_span data,
IanBenzMaxim 8:5ea891c7d1a1 619 int pageNum,
IanBenzMaxim 8:5ea891c7d1a1 620 int segmentNum) const {
IanBenzMaxim 8:5ea891c7d1a1 621 Result<void> result = writeMemory(scratchpad, data);
IanBenzMaxim 8:5ea891c7d1a1 622 if (result) {
IanBenzMaxim 7:9cd16581b578 623 result = computeWriteMac(false, true, pageNum, segmentNum);
IanBenzMaxim 7:9cd16581b578 624 }
IanBenzMaxim 7:9cd16581b578 625 return result;
IanBenzMaxim 7:9cd16581b578 626 }
IanBenzMaxim 7:9cd16581b578 627
IanBenzMaxim 8:5ea891c7d1a1 628 Result<DS2465::Page::array>
IanBenzMaxim 8:5ea891c7d1a1 629 DS2465::computeWriteMacWithSwap(WriteMacData::const_span data, int pageNum,
IanBenzMaxim 8:5ea891c7d1a1 630 int segmentNum) const {
IanBenzMaxim 8:5ea891c7d1a1 631 Result<void> result = doComputeWriteMacWithSwap(data, pageNum, segmentNum);
IanBenzMaxim 7:9cd16581b578 632 if (!result) {
IanBenzMaxim 8:5ea891c7d1a1 633 return result.error();
IanBenzMaxim 7:9cd16581b578 634 }
IanBenzMaxim 8:5ea891c7d1a1 635 Page::array mac;
IanBenzMaxim 8:5ea891c7d1a1 636 result = readMemory(mac);
IanBenzMaxim 8:5ea891c7d1a1 637 if (!result) {
IanBenzMaxim 8:5ea891c7d1a1 638 return result.error();
IanBenzMaxim 8:5ea891c7d1a1 639 }
IanBenzMaxim 8:5ea891c7d1a1 640 return mac;
IanBenzMaxim 7:9cd16581b578 641 }
IanBenzMaxim 7:9cd16581b578 642
IanBenzMaxim 8:5ea891c7d1a1 643 Result<void>
IanBenzMaxim 7:9cd16581b578 644 DS2465::computeAndTransmitWriteMacWithSwap(WriteMacData::const_span data,
IanBenzMaxim 8:5ea891c7d1a1 645 int pageNum, int segmentNum) {
IanBenzMaxim 8:5ea891c7d1a1 646 Result<void> result = doComputeWriteMacWithSwap(data, pageNum, segmentNum);
IanBenzMaxim 8:5ea891c7d1a1 647 if (result) {
IanBenzMaxim 7:9cd16581b578 648 result = writeMacBlock();
IanBenzMaxim 7:9cd16581b578 649 }
IanBenzMaxim 7:9cd16581b578 650 return result;
IanBenzMaxim 7:9cd16581b578 651 }
IanBenzMaxim 7:9cd16581b578 652
IanBenzMaxim 8:5ea891c7d1a1 653 Result<void> DS2465::computeSlaveSecret(AuthenticationData::const_span data) {
IanBenzMaxim 8:5ea891c7d1a1 654 Result<void> result = writeMemory(scratchpad, data);
IanBenzMaxim 8:5ea891c7d1a1 655 if (result) {
IanBenzMaxim 7:9cd16581b578 656 result = computeSlaveSecret(false, 0, FullPage);
IanBenzMaxim 7:9cd16581b578 657 }
IanBenzMaxim 7:9cd16581b578 658 return result;
IanBenzMaxim 7:9cd16581b578 659 }
IanBenzMaxim 7:9cd16581b578 660
IanBenzMaxim 8:5ea891c7d1a1 661 Result<void>
IanBenzMaxim 7:9cd16581b578 662 DS2465::computeSlaveSecretWithSwap(AuthenticationData::const_span data,
IanBenzMaxim 7:9cd16581b578 663 int pageNum, PageRegion region) {
IanBenzMaxim 8:5ea891c7d1a1 664 Result<void> result = writeMemory(scratchpad, data);
IanBenzMaxim 8:5ea891c7d1a1 665 if (result) {
IanBenzMaxim 7:9cd16581b578 666 result = computeSlaveSecret(true, pageNum, region);
IanBenzMaxim 7:9cd16581b578 667 }
IanBenzMaxim 7:9cd16581b578 668 return result;
IanBenzMaxim 7:9cd16581b578 669 }
IanBenzMaxim 7:9cd16581b578 670
IanBenzMaxim 8:5ea891c7d1a1 671 Result<void>
IanBenzMaxim 8:5ea891c7d1a1 672 DS2465::doComputeAuthMac(AuthenticationData::const_span data) const {
IanBenzMaxim 8:5ea891c7d1a1 673 Result<void> result = writeMemory(scratchpad, data);
IanBenzMaxim 8:5ea891c7d1a1 674 if (result) {
IanBenzMaxim 7:9cd16581b578 675 result = computeAuthMac(false, 0, FullPage);
IanBenzMaxim 7:9cd16581b578 676 }
IanBenzMaxim 7:9cd16581b578 677 return result;
IanBenzMaxim 7:9cd16581b578 678 }
IanBenzMaxim 7:9cd16581b578 679
IanBenzMaxim 8:5ea891c7d1a1 680 Result<DS2465::Page::array>
IanBenzMaxim 8:5ea891c7d1a1 681 DS2465::computeAuthMac(AuthenticationData::const_span data) const {
IanBenzMaxim 8:5ea891c7d1a1 682 Result<void> result = doComputeAuthMac(data);
IanBenzMaxim 7:9cd16581b578 683 if (!result) {
IanBenzMaxim 8:5ea891c7d1a1 684 return result.error();
IanBenzMaxim 7:9cd16581b578 685 }
IanBenzMaxim 8:5ea891c7d1a1 686 Page::array mac;
IanBenzMaxim 8:5ea891c7d1a1 687 result = readMemory(mac);
IanBenzMaxim 8:5ea891c7d1a1 688 if (!result) {
IanBenzMaxim 8:5ea891c7d1a1 689 return result.error();
IanBenzMaxim 8:5ea891c7d1a1 690 }
IanBenzMaxim 8:5ea891c7d1a1 691 return mac;
IanBenzMaxim 7:9cd16581b578 692 }
IanBenzMaxim 7:9cd16581b578 693
IanBenzMaxim 8:5ea891c7d1a1 694 Result<void>
IanBenzMaxim 8:5ea891c7d1a1 695 DS2465::computeAndTransmitAuthMac(AuthenticationData::const_span data) {
IanBenzMaxim 8:5ea891c7d1a1 696 Result<void> result = doComputeAuthMac(data);
IanBenzMaxim 8:5ea891c7d1a1 697 if (result) {
IanBenzMaxim 7:9cd16581b578 698 result = writeMacBlock();
IanBenzMaxim 7:9cd16581b578 699 }
IanBenzMaxim 7:9cd16581b578 700 return result;
IanBenzMaxim 7:9cd16581b578 701 }
IanBenzMaxim 7:9cd16581b578 702
IanBenzMaxim 8:5ea891c7d1a1 703 Result<void>
IanBenzMaxim 8:5ea891c7d1a1 704 DS2465::doComputeAuthMacWithSwap(AuthenticationData::const_span data,
IanBenzMaxim 8:5ea891c7d1a1 705 int pageNum, PageRegion region) const {
IanBenzMaxim 8:5ea891c7d1a1 706 Result<void> result = writeMemory(scratchpad, data);
IanBenzMaxim 8:5ea891c7d1a1 707 if (result) {
IanBenzMaxim 7:9cd16581b578 708 result = computeAuthMac(true, pageNum, region);
IanBenzMaxim 7:9cd16581b578 709 }
IanBenzMaxim 7:9cd16581b578 710 return result;
IanBenzMaxim 7:9cd16581b578 711 }
IanBenzMaxim 7:9cd16581b578 712
IanBenzMaxim 8:5ea891c7d1a1 713 Result<DS2465::Page::array>
IanBenzMaxim 8:5ea891c7d1a1 714 DS2465::computeAuthMacWithSwap(AuthenticationData::const_span data, int pageNum,
IanBenzMaxim 8:5ea891c7d1a1 715 PageRegion region) const {
IanBenzMaxim 8:5ea891c7d1a1 716 Result<void> result = doComputeAuthMacWithSwap(data, pageNum, region);
IanBenzMaxim 7:9cd16581b578 717 if (!result) {
IanBenzMaxim 8:5ea891c7d1a1 718 return result.error();
IanBenzMaxim 7:9cd16581b578 719 }
IanBenzMaxim 8:5ea891c7d1a1 720 Page::array mac;
IanBenzMaxim 8:5ea891c7d1a1 721 result = readMemory(mac);
IanBenzMaxim 8:5ea891c7d1a1 722 if (!result) {
IanBenzMaxim 8:5ea891c7d1a1 723 return result.error();
IanBenzMaxim 8:5ea891c7d1a1 724 }
IanBenzMaxim 8:5ea891c7d1a1 725 return mac;
IanBenzMaxim 7:9cd16581b578 726 }
IanBenzMaxim 7:9cd16581b578 727
IanBenzMaxim 8:5ea891c7d1a1 728 Result<void>
IanBenzMaxim 8:5ea891c7d1a1 729 DS2465::computeAndTransmitAuthMacWithSwap(AuthenticationData::const_span data,
IanBenzMaxim 8:5ea891c7d1a1 730 int pageNum, PageRegion region) {
IanBenzMaxim 8:5ea891c7d1a1 731 Result<void> result = doComputeAuthMacWithSwap(data, pageNum, region);
IanBenzMaxim 8:5ea891c7d1a1 732 if (result) {
IanBenzMaxim 7:9cd16581b578 733 result = writeMacBlock();
IanBenzMaxim 7:9cd16581b578 734 }
IanBenzMaxim 7:9cd16581b578 735 return result;
IanBenzMaxim 7:9cd16581b578 736 }
IanBenzMaxim 7:9cd16581b578 737
IanBenzMaxim 7:9cd16581b578 738 const error_category & DS2465::errorCategory() {
IanBenzMaxim 7:9cd16581b578 739 static class : public error_category {
IanBenzMaxim 7:9cd16581b578 740 public:
IanBenzMaxim 11:3f3bf6bf5e6c 741 virtual const char * name() const { return "MaximInterfaceDevices.DS2465"; }
IanBenzMaxim 7:9cd16581b578 742
IanBenzMaxim 7:9cd16581b578 743 virtual std::string message(int condition) const {
IanBenzMaxim 7:9cd16581b578 744 switch (condition) {
IanBenzMaxim 7:9cd16581b578 745 case HardwareError:
IanBenzMaxim 7:9cd16581b578 746 return "Hardware Error";
IanBenzMaxim 7:9cd16581b578 747
IanBenzMaxim 7:9cd16581b578 748 case ArgumentOutOfRangeError:
IanBenzMaxim 7:9cd16581b578 749 return "Argument Out of Range Error";
IanBenzMaxim 7:9cd16581b578 750 }
IanBenzMaxim 8:5ea891c7d1a1 751 return defaultErrorMessage(condition);
IanBenzMaxim 7:9cd16581b578 752 }
IanBenzMaxim 7:9cd16581b578 753 } instance;
IanBenzMaxim 7:9cd16581b578 754 return instance;
IanBenzMaxim 7:9cd16581b578 755 }
IanBenzMaxim 7:9cd16581b578 756
IanBenzMaxim 7:9cd16581b578 757 } // namespace MaximInterfaceDevices