Aleksandrs Gumenuks / MaximInterface_Extended

Dependents:   mbed_DS28EC20_GPIO

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers DS2465.cpp Source File

DS2465.cpp

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