Device interface library for multiple platforms including Mbed.

Dependents:   DeepCover Embedded Security in IoT MaximInterface MAXREFDES155#

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers DS2465.cpp Source File

DS2465.cpp

00001 /*******************************************************************************
00002 * Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
00003 *
00004 * Permission is hereby granted, free of charge, to any person obtaining a
00005 * copy of this software and associated documentation files (the "Software"),
00006 * to deal in the Software without restriction, including without limitation
00007 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00008 * and/or sell copies of the Software, and to permit persons to whom the
00009 * Software is furnished to do so, subject to the following conditions:
00010 *
00011 * The above copyright notice and this permission notice shall be included
00012 * in all copies or substantial portions of the Software.
00013 *
00014 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00015 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00016 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
00017 * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
00018 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
00019 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
00020 * OTHER DEALINGS IN THE SOFTWARE.
00021 *
00022 * Except as contained in this notice, the name of Maxim Integrated
00023 * Products, Inc. shall not be used except as stated in the Maxim Integrated
00024 * Products, Inc. Branding Policy.
00025 *
00026 * The mere transfer of this software does not imply any licenses
00027 * of trade secrets, proprietary technology, copyrights, patents,
00028 * trademarks, maskwork rights, or any other form of intellectual
00029 * property whatsoever. Maxim Integrated Products, Inc. retains all
00030 * ownership rights.
00031 *******************************************************************************/
00032 
00033 #include <MaximInterfaceCore/Error.hpp>
00034 #include "DS2465.hpp"
00035 
00036 #define TRY MaximInterfaceCore_TRY
00037 #define TRY_VALUE MaximInterfaceCore_TRY_VALUE
00038 
00039 namespace MaximInterfaceDevices {
00040 
00041 using namespace Core;
00042 
00043 // Delay required after writing an EEPROM segment.
00044 static const int eepromSegmentWriteDelayMs = 10;
00045 
00046 // Delay required after writing an EEPROM page such as the secret memory.
00047 static const int eepromPageWriteDelayMs = 8 * eepromSegmentWriteDelayMs;
00048 
00049 // Delay required for a SHA computation to complete.
00050 static const int shaComputationDelayMs = 2;
00051 
00052 static const uint_least8_t scratchpad = 0x00;
00053 static const uint_least8_t commandReg = 0x60;
00054 
00055 static const uint_least8_t owTransmitBlockCmd = 0x69;
00056 
00057 // DS2465 status bits.
00058 static const uint_least8_t status_1WB = 0x01;
00059 static const uint_least8_t status_PPD = 0x02;
00060 static const uint_least8_t status_SD = 0x04;
00061 static const uint_least8_t status_SBR = 0x20;
00062 static const uint_least8_t status_TSB = 0x40;
00063 static const uint_least8_t status_DIR = 0x80;
00064 
00065 static const int maxBlockSize = 63;
00066 
00067 const int DS2465::memoryPages;
00068 const int DS2465::segmentsPerPage;
00069 
00070 Result<void> DS2465::initialize(Config config) {
00071   // reset DS2465
00072   Result<void> result = resetDevice();
00073   if (result) {
00074     // write the default configuration setup
00075     result = writeConfig(config);
00076   }
00077   return result;
00078 }
00079 
00080 Result<void> DS2465::computeNextMasterSecret(bool swap, int pageNum,
00081                                              PageRegion region) {
00082   Result<void> result = ArgumentOutOfRangeError;
00083   if (pageNum >= 0) {
00084     const uint_least8_t command[] = {
00085         0x1E, static_cast<uint_least8_t>(swap ? (0xC8 | (pageNum << 4) | region)
00086                                               : 0xBF)};
00087     result = writeMemory(commandReg, command);
00088   }
00089   return result;
00090 }
00091 
00092 Result<void> DS2465::computeWriteMac(bool regwrite, bool swap, int pageNum,
00093                                      int segmentNum) const {
00094   Result<void> result = ArgumentOutOfRangeError;
00095   if (pageNum >= 0 && segmentNum >= 0) {
00096     const uint_least8_t command[] = {
00097         0x2D, static_cast<uint_least8_t>((regwrite << 7) | (swap << 6) |
00098                                          (pageNum << 4) | segmentNum)};
00099     result = writeMemory(commandReg, command);
00100     if (result) {
00101       sleep->invoke(shaComputationDelayMs);
00102     }
00103   }
00104   return result;
00105 }
00106 
00107 Result<void> DS2465::computeAuthMac(bool swap, int pageNum,
00108                                     PageRegion region) const {
00109   Result<void> result = ArgumentOutOfRangeError;
00110   if (pageNum >= 0) {
00111     const uint_least8_t command[] = {
00112         0x3C, static_cast<uint_least8_t>(swap ? (0xC8 | (pageNum << 4) | region)
00113                                               : 0xBF)};
00114     result = writeMemory(commandReg, command);
00115     if (result) {
00116       sleep->invoke(shaComputationDelayMs * 2);
00117     }
00118   }
00119   return result;
00120 }
00121 
00122 Result<void> DS2465::computeSlaveSecret(bool swap, int pageNum,
00123                                         PageRegion region) {
00124   Result<void> result = ArgumentOutOfRangeError;
00125   if (pageNum >= 0) {
00126     const uint_least8_t command[] = {
00127         0x4B, static_cast<uint_least8_t>(swap ? (0xC8 | (pageNum << 4) | region)
00128                                               : 0xBF)};
00129     result = writeMemory(commandReg, command);
00130     if (result) {
00131       sleep->invoke(shaComputationDelayMs * 2);
00132     }
00133   }
00134   return result;
00135 }
00136 
00137 Result<DS2465::Page::array> DS2465::readPage(int pageNum) const {
00138   uint_least8_t addr;
00139   switch (pageNum) {
00140   case 0:
00141     addr = 0x80;
00142     break;
00143   case 1:
00144     addr = 0xA0;
00145     break;
00146   default:
00147     return ArgumentOutOfRangeError;
00148   }
00149   Page::array data;
00150   TRY(readMemory(addr, data));
00151   return data;
00152 }
00153 
00154 Result<void> DS2465::writePage(int pageNum, Page::const_span data) {
00155   Result<void> result = writeMemory(scratchpad, data);
00156   if (result) {
00157     result = copyScratchpad(false, pageNum, false, 0);
00158   }
00159   if (result) {
00160     sleep->invoke(eepromPageWriteDelayMs);
00161   }
00162   return result;
00163 }
00164 
00165 Result<void> DS2465::writeSegment(int pageNum, int segmentNum,
00166                                   Segment::const_span data) {
00167   Result<void> result = writeMemory(scratchpad, data);
00168   if (result) {
00169     result = copyScratchpad(false, pageNum, true, segmentNum);
00170   }
00171   if (result) {
00172     sleep->invoke(eepromSegmentWriteDelayMs);
00173   }
00174   return result;
00175 }
00176 
00177 Result<void> DS2465::writeMasterSecret(Page::const_span masterSecret) {
00178   Result<void> result = writeMemory(scratchpad, masterSecret);
00179   if (result) {
00180     result = copyScratchpad(true, 0, false, 0);
00181   }
00182   if (result) {
00183     sleep->invoke(eepromPageWriteDelayMs);
00184   }
00185   return result;
00186 }
00187 
00188 Result<void> DS2465::copyScratchpad(bool destSecret, int pageNum, bool notFull,
00189                                     int segmentNum) {
00190   Result<void> result = ArgumentOutOfRangeError;
00191   if (pageNum >= 0 && segmentNum >= 0) {
00192     const uint_least8_t command[] = {
00193         0x5A,
00194         static_cast<uint_least8_t>(destSecret ? 0
00195                                               : (0x80 | (pageNum << 4) |
00196                                                  (notFull << 3) | segmentNum))};
00197     result = writeMemory(commandReg, command);
00198   }
00199   return result;
00200 }
00201 
00202 Result<void> DS2465::configureLevel(Level level) {
00203   // Check if supported level
00204   if (!((level == NormalLevel) || (level == StrongLevel))) {
00205     return InvalidLevelError;
00206   }
00207   // Check if requested level already set
00208   if (curConfig.getSPU() == (level == StrongLevel)) {
00209     return none;
00210   }
00211   // Set the level
00212   return writeConfig(Config(curConfig).setSPU(level == StrongLevel));
00213 }
00214 
00215 Result<void> DS2465::setLevel (Level newLevel) {
00216   if (newLevel == StrongLevel) {
00217     return InvalidLevelError;
00218   }
00219 
00220   return configureLevel(newLevel);
00221 }
00222 
00223 Result<void> DS2465::setSpeed(Speed newSpeed) {
00224   // Check if supported speed
00225   if (!((newSpeed == OverdriveSpeed) || (newSpeed == StandardSpeed))) {
00226     return InvalidSpeedError;
00227   }
00228   // Check if requested speed is already set
00229   if (curConfig.get1WS() == (newSpeed == OverdriveSpeed)) {
00230     return none;
00231   }
00232   // Set the speed
00233   return writeConfig(Config(curConfig).set1WS(newSpeed == OverdriveSpeed));
00234 }
00235 
00236 Result<OneWireMaster::TripletData> DS2465::triplet(bool sendBit) {
00237   // 1-Wire Triplet (Case B)
00238   //   S AD,0 [A] 1WT [A] SS [A] Sr AD,1 [A] [Status] A [Status] A\ P
00239   //                                         \--------/
00240   //                           Repeat until 1WB bit has changed to 0
00241   //  [] indicates from slave
00242   //  SS indicates byte containing search direction bit value in msbit
00243 
00244   const uint_least8_t command[] = {
00245       0x78, static_cast<uint_least8_t>(sendBit ? 0x80 : 0x00)};
00246   TRY(writeMemory(commandReg, command));
00247 
00248   uint_least8_t status;
00249   TRY_VALUE(status, pollBusy());
00250 
00251   TripletData data;
00252   data.readBit = ((status & status_SBR) == status_SBR);
00253   data.readBitComplement = ((status & status_TSB) == status_TSB);
00254   data.writeBit = ((status & status_DIR) == status_DIR);
00255   return data;
00256 }
00257 
00258 Result<void> DS2465::readBlock(span<uint_least8_t> recvBuf) {
00259   // 1-Wire Receive Block (Case A)
00260   //   S AD,0 [A] CommandReg [A] 1WRF [A] PR [A] P
00261   //  [] indicates from slave
00262   //  PR indicates byte containing parameter
00263 
00264   span<uint_least8_t>::index_type recvIdx = 0;
00265   while (recvIdx < recvBuf.size()) {
00266     const uint_least8_t command[] = {
00267         0xE1,
00268         static_cast<uint_least8_t>(std::min<span<uint_least8_t>::index_type>(
00269             recvBuf.size() - recvIdx, maxBlockSize))};
00270     TRY(writeMemory(commandReg, command));
00271     TRY(pollBusy());
00272     TRY(readMemory(scratchpad, recvBuf.subspan(recvIdx, command[1])));
00273     recvIdx += command[1];
00274   }
00275   return none;
00276 }
00277 
00278 Result<void> DS2465::writeBlock(span<const uint_least8_t> sendBuf) {
00279   span<const uint_least8_t>::index_type sendIdx = 0;
00280   while (sendIdx < sendBuf.size()) {
00281     const uint_least8_t command[] = {
00282         owTransmitBlockCmd, static_cast<uint_least8_t>(
00283                                 std::min<span<const uint_least8_t>::index_type>(
00284                                     sendBuf.size() - sendIdx, maxBlockSize))};
00285 
00286     // prefill scratchpad with required data
00287     TRY(writeMemory(scratchpad, sendBuf.subspan(sendIdx, command[1])));
00288 
00289     // 1-Wire Transmit Block (Case A)
00290     //   S AD,0 [A] CommandReg [A] 1WTB [A] PR [A] P
00291     //  [] indicates from slave
00292     //  PR indicates byte containing parameter
00293     TRY(writeMemory(commandReg, command));
00294     TRY(pollBusy());
00295     sendIdx += command[1];
00296   }
00297   return none;
00298 }
00299 
00300 Result<void> DS2465::writeMacBlock() {
00301   // 1-Wire Transmit Block (Case A)
00302   //   S AD,0 [A] CommandReg [A] 1WTB [A] PR [A] P
00303   //  [] indicates from slave
00304   //  PR indicates byte containing parameter
00305 
00306   const uint_least8_t command[] = {owTransmitBlockCmd, 0xFF};
00307   TRY(writeMemory(commandReg, command));
00308   TRY(pollBusy());
00309   return none;
00310 }
00311 
00312 Result<uint_least8_t> DS2465::readByteSetLevel(Level afterLevel) {
00313   // 1-Wire Read Bytes (Case C)
00314   //   S AD,0 [A] CommandReg [A] 1WRB [A] Sr AD,1 [A] [Status] A [Status] A
00315   //                                                  \--------/
00316   //                     Repeat until 1WB bit has changed to 0
00317   //   Sr AD,0 [A] SRP [A] E1 [A] Sr AD,1 [A] DD A\ P
00318   //
00319   //  [] indicates from slave
00320   //  DD data read
00321 
00322   TRY(configureLevel(afterLevel));
00323 
00324   uint_least8_t buf = 0x96;
00325   TRY(writeMemory(commandReg, make_span(&buf, 1)));
00326   TRY(pollBusy());
00327   TRY(readMemory(0x62, make_span(&buf, 1)));
00328   return buf;
00329 }
00330 
00331 Result<void> DS2465::writeByteSetLevel(uint_least8_t sendByte,
00332                                        Level afterLevel) {
00333   // 1-Wire Write Byte (Case B)
00334   //   S AD,0 [A] CommandReg [A] 1WWB [A] DD [A] Sr AD,1 [A] [Status] A [Status]
00335   //   A\ P
00336   //                                                           \--------/
00337   //                             Repeat until 1WB bit has changed to 0
00338   //  [] indicates from slave
00339   //  DD data to write
00340 
00341   TRY(configureLevel(afterLevel));
00342 
00343   const uint_least8_t command[] = {0xA5, sendByte};
00344   TRY(writeMemory(commandReg, command));
00345   TRY(pollBusy());
00346   return none;
00347 }
00348 
00349 Result<bool> DS2465::touchBitSetLevel(bool sendBit, Level afterLevel) {
00350   // 1-Wire bit (Case B)
00351   //   S AD,0 [A] CommandReg [A] 1WSB [A] BB [A] Sr AD,1 [A] [Status] A [Status]
00352   //   A\ P
00353   //                                                          \--------/
00354   //                           Repeat until 1WB bit has changed to 0
00355   //  [] indicates from slave
00356   //  BB indicates byte containing bit value in msbit
00357 
00358   TRY(configureLevel(afterLevel));
00359 
00360   const uint_least8_t command[] = {
00361       0x87, static_cast<uint_least8_t>(sendBit ? 0x80 : 0x00)};
00362   TRY(writeMemory(commandReg, command));
00363 
00364   uint_least8_t status;
00365   TRY_VALUE(status, pollBusy());
00366 
00367   return (status & status_SBR) == status_SBR;
00368 }
00369 
00370 Result<void> DS2465::writeMemory(uint_least8_t addr,
00371                                  span<const uint_least8_t> buf) const {
00372   // Write SRAM (Case A)
00373   //   S AD,0 [A] VSA [A] DD [A]  P
00374   //                      \-----/
00375   //                        Repeat for each data byte
00376   //  [] indicates from slave
00377   //  VSA valid SRAM memory address
00378   //  DD memory data to write
00379 
00380   Result<void> result = master->start(address_);
00381   if (!result) {
00382     master->stop();
00383     return result;
00384   }
00385   result = master->writeByte(addr);
00386   if (!result) {
00387     master->stop();
00388     return result;
00389   }
00390   result = master->writeBlock(buf);
00391   if (!result) {
00392     master->stop();
00393     return result;
00394   }
00395   result = master->stop();
00396   return result;
00397 }
00398 
00399 Result<void> DS2465::readMemory(uint_least8_t addr,
00400                                 span<uint_least8_t> buf) const {
00401   // Read (Case A)
00402   //   S AD,0 [A] MA [A] Sr AD,1 [A] [DD] A [DD] A\ P
00403   //                                 \-----/
00404   //                                   Repeat for each data byte, NAK last byte
00405   //  [] indicates from slave
00406   //  MA memory address
00407   //  DD memory data read
00408 
00409   Result<void> result = master->start(address_);
00410   if (!result) {
00411     master->stop();
00412     return result;
00413   }
00414   result = master->writeByte(addr);
00415   if (!result) {
00416     master->stop();
00417     return result;
00418   }
00419   result = readMemory(buf);
00420   return result;
00421 }
00422 
00423 Result<void> DS2465::readMemory(span<uint_least8_t> buf) const {
00424   Result<void> result = master->start(address_ | 1);
00425   if (!result) {
00426     master->stop();
00427     return result;
00428   }
00429   result = master->readBlock(buf, I2CMaster::Nack);
00430   if (!result) {
00431     master->stop();
00432     return result;
00433   }
00434   result = master->stop();
00435   return result;
00436 }
00437 
00438 Result<void> DS2465::writeConfig(Config config) {
00439   const uint_least8_t configReg = 0x67;
00440   uint_least8_t configBuf =
00441       ((config.readByte() ^ 0xF) << 4) | config.readByte();
00442   Result<void> result = writeMemory(configReg, make_span(&configBuf, 1));
00443   if (result) {
00444     result = readMemory(configReg, make_span(&configBuf, 1));
00445   }
00446   if (result && configBuf != config.readByte()) {
00447     result = HardwareError;
00448   }
00449   if (result) {
00450     curConfig = config;
00451   }
00452   return result;
00453 }
00454 
00455 Result<void> DS2465::writePortParameter(PortParameter param, int val) {
00456   if (val < 0 || val > 15) {
00457     return ArgumentOutOfRangeError;
00458   }
00459 
00460   uint_least8_t addr = 0;
00461   switch (param) {
00462   case tRSTL_STD:
00463   case tRSTL_OD:
00464     addr = 0x68;
00465     break;
00466   case tMSP_STD:
00467   case tMSP_OD:
00468     addr = 0x69;
00469     break;
00470   case tW0L_STD:
00471   case tW0L_OD:
00472     addr = 0x6A;
00473     break;
00474   case tREC0:
00475     addr = 0x6B;
00476     break;
00477   case RWPU:
00478     addr = 0x6C;
00479     break;
00480   case tW1L_OD:
00481     addr = 0x6D;
00482     break;
00483   }
00484 
00485   uint_least8_t data;
00486   Result<void> result = readMemory(addr, make_span(&data, 1));
00487   if (!result) {
00488     return result;
00489   }
00490 
00491   uint_least8_t newData;
00492   if (param == tRSTL_OD || param == tMSP_OD || param == tW0L_OD) {
00493     newData = (data & 0x0F) | (val << 4);
00494   } else {
00495     newData = (data & 0xF0) | val;
00496   }
00497 
00498   if (newData != data) {
00499     result = writeMemory(addr, make_span(&newData, 1));
00500   }
00501   return result;
00502 }
00503 
00504 Result<uint_least8_t> DS2465::pollBusy() const {
00505   const int pollLimit = 200;
00506 
00507   int pollCount = 0;
00508   uint_least8_t status;
00509   do {
00510     const Result<void> result = readMemory(make_span(&status, 1));
00511     if (!result) {
00512       return result.error();
00513     }
00514     if (pollCount++ >= pollLimit) {
00515       return HardwareError;
00516     }
00517   } while ((status & status_1WB) == status_1WB);
00518   return status;
00519 }
00520 
00521 Result<void> DS2465::reset() {
00522   // 1-Wire reset (Case B)
00523   //   S AD,0 [A] CommandReg  [A] 1WRS [A] Sr AD,1 [A] [Status] A [Status] A\ P
00524   //                                                  \--------/
00525   //                       Repeat until 1WB bit has changed to 0
00526   //  [] indicates from slave
00527 
00528   uint_least8_t buf = 0xB4;
00529   TRY(writeMemory(commandReg, make_span(&buf, 1)));
00530 
00531   TRY_VALUE(buf, pollBusy());
00532 
00533   if ((buf & status_SD) == status_SD) {
00534     return ShortDetectedError;
00535   }
00536   if ((buf & status_PPD) != status_PPD) {
00537     return NoSlaveError;
00538   }
00539 
00540   return none;
00541 }
00542 
00543 Result<void> DS2465::resetDevice() {
00544   // Device Reset
00545   //   S AD,0 [A] CommandReg [A] 1WMR [A] Sr AD,1 [A] [SS] A\ P
00546   //  [] indicates from slave
00547   //  SS status byte to read to verify state
00548 
00549   uint_least8_t buf = 0xF0;
00550   Result<void> result = writeMemory(commandReg, make_span(&buf, 1));
00551 
00552   if (result) {
00553     result = readMemory(make_span(&buf, 1));
00554   }
00555 
00556   if (result) {
00557     if ((buf & 0xF7) != 0x10) {
00558       result = HardwareError;
00559     }
00560   }
00561 
00562   if (result) {
00563     reset(); // do a command to get 1-Wire master reset out of holding state
00564   }
00565 
00566   return result;
00567 }
00568 
00569 Result<void>
00570 DS2465::computeNextMasterSecret(AuthenticationData::const_span data) {
00571   Result<void> result = writeMemory(scratchpad, data);
00572   if (result) {
00573     result = computeNextMasterSecret(false, 0, FullPage);
00574   }
00575   return result;
00576 }
00577 
00578 Result<void>
00579 DS2465::computeNextMasterSecretWithSwap(AuthenticationData::const_span data,
00580                                         int pageNum, PageRegion region) {
00581   Result<void> result = writeMemory(scratchpad, data);
00582   if (result) {
00583     result = computeNextMasterSecret(true, pageNum, region);
00584   }
00585   return result;
00586 }
00587 
00588 Result<void> DS2465::doComputeWriteMac(WriteMacData::const_span data) const {
00589   Result<void> result = writeMemory(scratchpad, data);
00590   if (result) {
00591     result = computeWriteMac(false, false, 0, 0);
00592   }
00593   return result;
00594 }
00595 
00596 Result<DS2465::Page::array>
00597 DS2465::computeWriteMac(WriteMacData::const_span data) const {
00598   Result<void> result = doComputeWriteMac(data);
00599   if (!result) {
00600     return result.error();
00601   }
00602   Page::array mac;
00603   result = readMemory(mac);
00604   if (!result) {
00605     return result.error();
00606   }
00607   return mac;
00608 }
00609 
00610 Result<void> DS2465::computeAndTransmitWriteMac(WriteMacData::const_span data) {
00611   Result<void> result = doComputeWriteMac(data);
00612   if (result) {
00613     result = writeMacBlock();
00614   }
00615   return result;
00616 }
00617 
00618 Result<void> DS2465::doComputeWriteMacWithSwap(WriteMacData::const_span data,
00619                                                int pageNum,
00620                                                int segmentNum) const {
00621   Result<void> result = writeMemory(scratchpad, data);
00622   if (result) {
00623     result = computeWriteMac(false, true, pageNum, segmentNum);
00624   }
00625   return result;
00626 }
00627 
00628 Result<DS2465::Page::array>
00629 DS2465::computeWriteMacWithSwap(WriteMacData::const_span data, int pageNum,
00630                                 int segmentNum) const {
00631   Result<void> result = doComputeWriteMacWithSwap(data, pageNum, segmentNum);
00632   if (!result) {
00633     return result.error();
00634   }
00635   Page::array mac;
00636   result = readMemory(mac);
00637   if (!result) {
00638     return result.error();
00639   }
00640   return mac;
00641 }
00642 
00643 Result<void>
00644 DS2465::computeAndTransmitWriteMacWithSwap(WriteMacData::const_span data,
00645                                            int pageNum, int segmentNum) {
00646   Result<void> result = doComputeWriteMacWithSwap(data, pageNum, segmentNum);
00647   if (result) {
00648     result = writeMacBlock();
00649   }
00650   return result;
00651 }
00652 
00653 Result<void> DS2465::computeSlaveSecret(AuthenticationData::const_span data) {
00654   Result<void> result = writeMemory(scratchpad, data);
00655   if (result) {
00656     result = computeSlaveSecret(false, 0, FullPage);
00657   }
00658   return result;
00659 }
00660 
00661 Result<void>
00662 DS2465::computeSlaveSecretWithSwap(AuthenticationData::const_span data,
00663                                    int pageNum, PageRegion region) {
00664   Result<void> result = writeMemory(scratchpad, data);
00665   if (result) {
00666     result = computeSlaveSecret(true, pageNum, region);
00667   }
00668   return result;
00669 }
00670 
00671 Result<void>
00672 DS2465::doComputeAuthMac(AuthenticationData::const_span data) const {
00673   Result<void> result = writeMemory(scratchpad, data);
00674   if (result) {
00675     result = computeAuthMac(false, 0, FullPage);
00676   }
00677   return result;
00678 }
00679 
00680 Result<DS2465::Page::array>
00681 DS2465::computeAuthMac(AuthenticationData::const_span data) const {
00682   Result<void> result = doComputeAuthMac(data);
00683   if (!result) {
00684     return result.error();
00685   }
00686   Page::array mac;
00687   result = readMemory(mac);
00688   if (!result) {
00689     return result.error();
00690   }
00691   return mac;
00692 }
00693 
00694 Result<void>
00695 DS2465::computeAndTransmitAuthMac(AuthenticationData::const_span data) {
00696   Result<void> result = doComputeAuthMac(data);
00697   if (result) {
00698     result = writeMacBlock();
00699   }
00700   return result;
00701 }
00702 
00703 Result<void>
00704 DS2465::doComputeAuthMacWithSwap(AuthenticationData::const_span data,
00705                                  int pageNum, PageRegion region) const {
00706   Result<void> result = writeMemory(scratchpad, data);
00707   if (result) {
00708     result = computeAuthMac(true, pageNum, region);
00709   }
00710   return result;
00711 }
00712 
00713 Result<DS2465::Page::array>
00714 DS2465::computeAuthMacWithSwap(AuthenticationData::const_span data, int pageNum,
00715                                PageRegion region) const {
00716   Result<void> result = doComputeAuthMacWithSwap(data, pageNum, region);
00717   if (!result) {
00718     return result.error();
00719   }
00720   Page::array mac;
00721   result = readMemory(mac);
00722   if (!result) {
00723     return result.error();
00724   }
00725   return mac;
00726 }
00727 
00728 Result<void>
00729 DS2465::computeAndTransmitAuthMacWithSwap(AuthenticationData::const_span data,
00730                                           int pageNum, PageRegion region) {
00731   Result<void> result = doComputeAuthMacWithSwap(data, pageNum, region);
00732   if (result) {
00733     result = writeMacBlock();
00734   }
00735   return result;
00736 }
00737 
00738 const error_category & DS2465::errorCategory() {
00739   static class : public error_category {
00740   public:
00741     virtual const char * name() const { return "MaximInterfaceDevices.DS2465"; }
00742 
00743     virtual std::string message(int condition) const {
00744       switch (condition) {
00745       case HardwareError:
00746         return "Hardware Error";
00747 
00748       case ArgumentOutOfRangeError:
00749         return "Argument Out of Range Error";
00750       }
00751       return defaultErrorMessage(condition);
00752     }
00753   } instance;
00754   return instance;
00755 }
00756 
00757 } // namespace MaximInterfaceDevices