1-Wire® library for mbed. Complete 1-Wire library that supports our silicon masters along with a bit-bang master on the MAX32600MBED platform with one common interface for mbed. Slave support has also been included and more slaves will be added as time permits.

Dependents:   MAXREFDES131_Qt_Demo MAX32630FTHR_iButton_uSD_Logger MAX32630FTHR_DS18B20_uSD_Logger MAXREFDES130_131_Demo ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers DS28E15_22_25.cpp Source File

DS28E15_22_25.cpp

00001 /******************************************************************//**
00002 * Copyright (C) 2016 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 "DS28E15_22_25.h"
00034 #include "DS28E15.h"
00035 #include "DS28E22.h"
00036 #include "DS28E25.h"
00037 #include "Masters/OneWireMaster.h"
00038 #include "Utilities/crc.h"
00039 #include "Utilities/type_traits.h"
00040 #include "wait_api.h"
00041 
00042 using namespace OneWire;
00043 using namespace OneWire::crc;
00044 
00045 /// 1-Wire device commands.
00046 enum Command
00047 {
00048     WriteMemory = 0x55,
00049     ReadMemory = 0xF0,
00050     LoadAndLockSecret = 0x33,
00051     ComputeAndLockSecret = 0x3C,
00052     ReadWriteScratchpad = 0x0F,
00053     ComputePageMac = 0xA5,
00054     ReadStatus = 0xAA,
00055     WriteBlockProtection = 0xC3,
00056     AuthWriteMemory = 0x5A,
00057     AuthWriteBlockProtection = 0xCC,
00058 };
00059 
00060 DS28E15_22_25::Segment  DS28E15_22_25::segmentFromPage(unsigned int segmentNum, const Page & page)
00061 {
00062     if (segmentNum > (segmentsPerPage - 1))
00063     {
00064         segmentNum = (segmentsPerPage - 1);
00065     }
00066     Segment  segment;
00067     Page::const_iterator copyBegin = page.begin() + (segmentNum * Segment::size());
00068     std::copy(copyBegin, copyBegin + Segment::size(), segment.begin());
00069     return segment;
00070 }
00071 
00072 void DS28E15_22_25::segmentToPage(unsigned int segmentNum, const Segment  & segment, Page & page)
00073 {
00074     if (segmentNum > (segmentsPerPage - 1))
00075     {
00076         segmentNum = (segmentsPerPage - 1);
00077     }
00078     std::copy(segment.begin(), segment.end(), page.begin() + (segmentNum * segment.size()));
00079 }
00080 
00081 DS28E15_22_25::BlockProtection::BlockProtection(bool readProtection, bool writeProtection, bool eepromEmulation, bool authProtection, unsigned int blockNum)
00082 {
00083     setReadProtection(readProtection);
00084     setWriteProtection(writeProtection);
00085     setEepromEmulation(eepromEmulation);
00086     setAuthProtection(authProtection);
00087     setBlockNum(blockNum);
00088 }
00089 
00090 void DS28E15_22_25::BlockProtection::setBlockNum(unsigned int blockNum)
00091 {
00092     m_status &= ~blockNumMask;
00093     m_status |= (blockNum & blockNumMask);
00094 }
00095 
00096 bool DS28E15_22_25::BlockProtection::noProtection() const
00097 {
00098     return !readProtection() && !writeProtection() && !eepromEmulation() && !authProtection();
00099 }
00100 
00101 void DS28E15_22_25::BlockProtection::setReadProtection(bool readProtection)
00102 {
00103     if (readProtection)
00104     {
00105         m_status |= readProtectionMask;
00106     }
00107     else
00108     {
00109         m_status &= ~readProtectionMask;
00110     }
00111 }
00112 
00113 void DS28E15_22_25::BlockProtection::setWriteProtection(bool writeProtection)
00114 {
00115     if (writeProtection)
00116     {
00117         m_status |= writeProtectionMask;
00118     }
00119     else
00120     {
00121         m_status &= ~writeProtectionMask;
00122     }
00123 }
00124 
00125 void DS28E15_22_25::BlockProtection::setEepromEmulation(bool eepromEmulation)
00126 {
00127     if (eepromEmulation)
00128     {
00129         m_status |= eepromEmulationMask;
00130     }
00131     else
00132     {
00133         m_status &= ~eepromEmulationMask;
00134     }
00135 }
00136 
00137 void DS28E15_22_25::BlockProtection::setAuthProtection(bool authProtection)
00138 {
00139     if (authProtection)
00140     {
00141         m_status |= authProtectionMask;
00142     }
00143     else
00144     {
00145         m_status &= ~authProtectionMask;
00146     }
00147 }
00148 
00149 DS28E15_22_25::DS28E15_22_25 (RandomAccessRomIterator & selector, bool lowVoltage)
00150     : OneWireSlave(selector), m_manId(), m_lowVoltage(lowVoltage)
00151 {
00152 
00153 }
00154 
00155 OneWireSlave::CmdResult DS28E15_22_25::writeAuthBlockProtection(const ISha256MacCoproc & MacCoproc, const BlockProtection & newProtection, const BlockProtection & oldProtection)
00156 {
00157     uint8_t buf[256], cs;
00158     int cnt = 0;
00159     Mac mac;
00160     
00161     if (selectDevice() != OneWireMaster::Success)
00162     {
00163         return CommunicationError;
00164     }
00165 
00166     buf[cnt++] = AuthWriteBlockProtection;
00167     buf[cnt++] = newProtection.statusByte();
00168 
00169     // Send command
00170     master().OWWriteBlock(&buf[0], 2);
00171 
00172     // read first CRC byte
00173     master().OWReadByte(buf[cnt++]);
00174 
00175     // read the last CRC and enable
00176     master().OWReadBytePower(buf[cnt++]);
00177 
00178     // now wait for the MAC computation.
00179     wait_ms(shaComputationDelayMs);
00180 
00181     // disable strong pullup
00182     master().OWSetLevel(OneWireMaster::NormalLevel);
00183 
00184     // check CRC16
00185     if (calculateCrc16(buf, cnt) != 0xB001)
00186     {
00187         return CrcError;
00188     }
00189 
00190     ISha256MacCoproc::CmdResult result;
00191     result = computeProtectionWriteMac(MacCoproc, newProtection, oldProtection, romId (), manId (), mac);
00192     if (result != ISha256MacCoproc::Success)
00193     {
00194         return OperationFailure;
00195     }
00196     cnt = 0;
00197 
00198     // send the MAC
00199     master().OWWriteBlock(mac.data(), mac.size());
00200 
00201     // Read CRC and CS byte
00202     master().OWReadBlock(&buf[cnt], 3);
00203     cnt += 3;
00204 
00205     // check CRC16
00206     if (calculateCrc16(buf, cnt - 1, calculateCrc16(mac.data(), mac.size())) != 0xB001)
00207     {
00208         return CrcError;
00209     }
00210 
00211     // check CS
00212     if (buf[cnt - 1] != 0xAA)
00213     {
00214         return OperationFailure;
00215     }
00216 
00217     // send release and strong pull-up
00218     // DATASHEET_CORRECTION - last bit in release is a read-zero so don't check echo of write byte
00219     master().OWWriteBytePower(0xAA);
00220 
00221     // now wait for the programming.
00222     wait_ms(eepromWriteDelayMs);
00223 
00224     // disable strong pullup
00225     master().OWSetLevel(OneWireMaster::NormalLevel);
00226 
00227     // read the CS byte
00228     master().OWReadByte(cs);
00229 
00230     if (cs == 0xAA)
00231     {
00232         return Success;
00233     }
00234     // else
00235     return OperationFailure;
00236 }
00237 
00238 OneWireSlave::CmdResult DS28E15_22_25::writeBlockProtection(const BlockProtection & protection)
00239 {
00240     uint8_t buf[256], cs;
00241     int cnt = 0;
00242     
00243     if (selectDevice() != OneWireMaster::Success)
00244     {
00245         return CommunicationError;
00246     }
00247 
00248     buf[cnt++] = WriteBlockProtection;
00249 
00250     // compute parameter byte 
00251     buf[cnt++] = protection.statusByte();
00252 
00253     master().OWWriteBlock(&buf[0], cnt);
00254 
00255     // Read CRC
00256     master().OWReadBlock(&buf[cnt], 2);
00257     cnt += 2;
00258 
00259     // check CRC16
00260     if (calculateCrc16(buf, cnt) != 0xB001)
00261     {
00262         return CrcError;
00263     }
00264 
00265     // sent release
00266     master().OWWriteBytePower(0xAA);
00267 
00268     // now wait for the programming.
00269     wait_ms(eepromWriteDelayMs);
00270 
00271     // disable strong pullup
00272     master().OWSetLevel(OneWireMaster::NormalLevel);
00273 
00274     // read the CS byte
00275     master().OWReadByte(cs);
00276 
00277     if (cs == 0xAA)
00278     {
00279         return Success;
00280     }
00281     // else
00282     return OperationFailure;
00283 }
00284 
00285 template <class T>
00286 OneWireSlave::CmdResult DS28E15_22_25::doReadBlockProtection(unsigned int blockNum, BlockProtection & protection) const
00287 {
00288     uint8_t buf;
00289     CmdResult result;
00290     
00291     result = readStatus<T>(false, false, blockNum, &buf);
00292     if (result == Success)
00293     {
00294         protection.setStatusByte(buf);
00295     }
00296     return result;
00297 }
00298 
00299 template <class T>
00300 OneWireSlave::CmdResult DS28E15_22_25::doReadPersonality(Personality & personality) const
00301 {
00302     Personality::Buffer buffer;
00303     CmdResult result = readStatus<T>(true, false, 0, buffer.data());
00304     if (result == Success)
00305     {
00306         personality = Personality(buffer);
00307     }
00308     return result;
00309 }
00310 
00311 template <class T>
00312 OneWireSlave::CmdResult DS28E15_22_25::readStatus(bool personality, bool allpages, unsigned int blockNum, uint8_t * rdbuf) const
00313 {
00314     const size_t crcLen = 4, ds28e22_25_pagesPerBlock = 2;
00315 
00316     uint8_t buf[256];
00317     size_t cnt = 0, offset = 0;
00318     
00319     if (selectDevice() != OneWireMaster::Success)
00320     {
00321         return CommunicationError;
00322     }
00323 
00324     buf[cnt++] = ReadStatus;
00325     if (personality)
00326     {
00327         buf[cnt++] = 0xE0;
00328     }
00329     else if (allpages)
00330     {
00331         buf[cnt++] = 0;
00332     }
00333     else
00334     {
00335         // Convert to page number for DS28E22 and DS28E25
00336         buf[cnt] = blockNum;
00337         if (is_same<T, DS28E22>::value || is_same<T, DS28E25>::value)
00338         {
00339             buf[cnt] *= ds28e22_25_pagesPerBlock;
00340         }
00341         cnt++;
00342     }
00343 
00344     // send the command
00345     master().OWWriteBlock(&buf[0], 2);
00346 
00347     offset = cnt + 2;
00348 
00349     // Set data length
00350     size_t rdnum;
00351     if (personality)
00352     {
00353         rdnum = 4;
00354     }
00355     else if (!allpages)
00356     {
00357         rdnum = 1;
00358     }
00359     else if (is_same<T, DS28E22>::value || is_same<T, DS28E25>::value)
00360     {
00361         rdnum = DS28E25::memoryPages; // Need to read extra data on DS28E22 to get CRC16.
00362     }
00363     else // DS28E15
00364     {
00365         rdnum = DS28E15::protectionBlocks;
00366     }
00367     rdnum += crcLen; // Add in CRC length
00368 
00369     // Read the bytes 
00370     master().OWReadBlock(&buf[cnt], rdnum);
00371     cnt += rdnum;
00372 
00373     // check the first CRC16
00374     if (calculateCrc16(buf, offset) != 0xB001)
00375     {
00376         return CrcError;
00377     }
00378 
00379     if (personality || allpages)
00380     {
00381         // check the second CRC16
00382         if (calculateCrc16(buf + offset, cnt - offset) != 0xB001)
00383         {
00384             return CrcError;
00385         }
00386     }
00387 
00388     // copy the data to the read buffer
00389     rdnum -= crcLen;
00390     if (allpages && (is_same<T, DS28E22>::value || is_same<T, DS28E25>::value))
00391     {
00392         if (is_same<T, DS28E22>::value)
00393         {
00394             rdnum -= (DS28E25::memoryPages - DS28E22::memoryPages);
00395         }
00396 
00397         for (size_t i = 0; i < (rdnum / ds28e22_25_pagesPerBlock); i++)
00398         {
00399             rdbuf[i] = (buf[offset + (i * ds28e22_25_pagesPerBlock)] & 0xF0); // Upper nibble
00400             rdbuf[i] |= ((buf[offset + (i * ds28e22_25_pagesPerBlock)] & 0x0F) / ds28e22_25_pagesPerBlock); // Lower nibble
00401         }
00402     }
00403     else
00404     {
00405         std::memcpy(rdbuf, &buf[offset], rdnum);
00406     }
00407 
00408     return Success;
00409 }
00410 
00411 ISha256MacCoproc::CmdResult DS28E15_22_25::computeAuthMac(const ISha256MacCoproc & MacCoproc, const Page & pageData, unsigned int pageNum, const Scratchpad & challenge, const RomId & romId, const ManId  & manId, Mac & mac)
00412 {
00413     ISha256MacCoproc::AuthMacData authMacData;
00414 
00415     // insert ROM number or FF
00416     std::memcpy(authMacData.data(), romId.buffer.data(), romId.buffer.size());
00417 
00418     authMacData[10] = pageNum;
00419 
00420     authMacData[9] = manId[0];
00421     authMacData[8] = manId[1];
00422 
00423     authMacData[11] = 0x00;
00424 
00425     return MacCoproc.computeAuthMac(ISha256MacCoproc::DevicePage(pageData), challenge, authMacData, mac);
00426 }
00427 
00428 ISha256MacCoproc::CmdResult DS28E15_22_25::computeAuthMacAnon(const ISha256MacCoproc & MacCoproc, const Page & pageData, unsigned int pageNum, const Scratchpad & challenge, const ManId  & manId, Mac & mac)
00429 {
00430     RomId romId ;
00431     romId.buffer.fill(0xFF);
00432     return computeAuthMac(MacCoproc, pageData, pageNum, challenge, romId, manId, mac);
00433 }
00434 
00435 OneWireSlave::CmdResult DS28E15_22_25::computeReadPageMac(unsigned int page_num, bool anon, Mac & mac) const
00436 {
00437     uint8_t buf[256], cs;
00438     int cnt = 0;
00439     
00440     if (selectDevice() != OneWireMaster::Success)
00441     {
00442         return CommunicationError;
00443     }
00444 
00445     buf[cnt++] = ComputePageMac;
00446     buf[cnt++] = ((anon) ? 0xE0 : 0x00) | page_num;
00447 
00448     // Send command
00449     master().OWWriteBlock(&buf[0], 2);
00450 
00451     // read first CRC byte
00452     master().OWReadByte(buf[cnt++]);
00453 
00454     // read the last CRC and enable
00455     master().OWReadBytePower(buf[cnt++]);
00456 
00457     // now wait for the MAC computation.
00458     wait_ms(shaComputationDelayMs * 2);
00459 
00460     // disable strong pullup
00461     master().OWSetLevel(OneWireMaster::NormalLevel);
00462 
00463     // check CRC16
00464     if (calculateCrc16(buf, cnt) != 0xB001)
00465     {
00466         return CrcError;
00467     }
00468 
00469     // read the CS byte
00470     master().OWReadByte(cs);
00471     if (cs != 0xAA)
00472     {
00473         return OperationFailure;
00474     }
00475 
00476     // read the MAC and CRC
00477     master().OWReadBlock(&buf[0], (Mac::size() + 2));
00478 
00479     // check CRC16
00480     if (calculateCrc16(buf, Mac::size() + 2) != 0xB001)
00481     {
00482         return CrcError;
00483     }
00484 
00485     // copy MAC to return buffer
00486     std::memcpy(mac.data(), buf, mac.size());
00487 
00488     return Success;
00489 }
00490 
00491 OneWireSlave::CmdResult DS28E15_22_25::computeSecret(unsigned int page_num, bool lock)
00492 {
00493     uint8_t buf[256], cs;
00494     int cnt = 0;
00495     
00496     if (selectDevice() != OneWireMaster::Success)
00497     {
00498         return CommunicationError;
00499     }
00500 
00501     buf[cnt++] = ComputeAndLockSecret;
00502     buf[cnt++] = (lock) ? (0xE0 | page_num) : page_num;  // lock flag 
00503 
00504     // Send command
00505     master().OWWriteBlock(&buf[0], 2);
00506 
00507     // Read CRC
00508     master().OWReadBlock(&buf[cnt], 2);
00509     cnt += 2;
00510 
00511     // check CRC16
00512     if (calculateCrc16(buf, cnt) != 0xB001)
00513     {
00514         return CrcError;
00515     }
00516 
00517     // send release and strong pull-up
00518     master().OWWriteBytePower(0xAA);
00519 
00520     // now wait for the MAC computations and secret programming.
00521     wait_ms(shaComputationDelayMs * 2 + secretEepromWriteDelayMs());
00522 
00523     // disable strong pullup
00524     master().OWSetLevel(OneWireMaster::NormalLevel);
00525 
00526     // read the CS byte
00527     master().OWReadByte(cs);
00528 
00529     if (cs == 0xAA)
00530     {
00531         return Success;
00532     }
00533     // else
00534     return OperationFailure;
00535 }
00536 
00537 template <class T>
00538 OneWireSlave::CmdResult DS28E15_22_25::doWriteScratchpad(const Scratchpad & data) const
00539 {
00540     uint8_t buf[256];
00541     int cnt = 0, offset;
00542     
00543     if (selectDevice() != OneWireMaster::Success)
00544     {
00545         return CommunicationError;
00546     }
00547 
00548     buf[cnt++] = ReadWriteScratchpad;
00549     if (is_same<T, DS28E22>::value || is_same<T, DS28E25>::value)
00550     {
00551         buf[cnt++] = 0x20;
00552     }
00553     else
00554     {
00555         buf[cnt++] = 0x00;
00556     }
00557 
00558     // Send command
00559     master().OWWriteBlock(&buf[0], 2);
00560 
00561     // Read CRC
00562     master().OWReadBlock(&buf[cnt], 2);
00563     cnt += 2;
00564 
00565     offset = cnt;
00566 
00567     // add the data
00568     std::memcpy(&buf[cnt], data.data(), data.size());
00569     cnt += data.size();
00570 
00571     // Send the data
00572     master().OWWriteBlock(data.data(), data.size());
00573 
00574     // Read CRC
00575     master().OWReadBlock(&buf[cnt], 2);
00576     cnt += 2;
00577 
00578     // check first CRC16
00579     if (calculateCrc16(buf, offset) != 0xB001)
00580     {
00581         return CrcError;
00582     }
00583 
00584     // check the second CRC16
00585     if (calculateCrc16(buf + offset, cnt - offset) != 0xB001)
00586     {
00587         return CrcError;
00588     }
00589 
00590     return Success;
00591 }
00592 
00593 template <class T>
00594 OneWireSlave::CmdResult DS28E15_22_25::doReadScratchpad(Scratchpad & data) const
00595 {
00596     uint8_t buf[256];
00597     int cnt = 0, offset;
00598     
00599     if (selectDevice() != OneWireMaster::Success)
00600     {
00601         return CommunicationError;
00602     }
00603 
00604     buf[cnt++] = ReadWriteScratchpad;
00605     if (is_same<T, DS28E22>::value || is_same<T, DS28E25>::value)
00606     {
00607         buf[cnt++] = 0x2F;
00608     }
00609     else
00610     {
00611         buf[cnt++] = 0x0F;
00612     }
00613 
00614     // Send command
00615     master().OWWriteBlock(&buf[0], 2);
00616 
00617     // Read CRC
00618     master().OWReadBlock(&buf[cnt], 2);
00619     cnt += 2;
00620 
00621     offset = cnt;
00622 
00623     // Receive the data
00624     master().OWReadBlock(&buf[cnt], data.size());
00625     cnt += data.size();
00626 
00627     // Read CRC
00628     master().OWReadBlock(&buf[cnt], 2);
00629     cnt += 2;
00630 
00631     // check first CRC16
00632     if (calculateCrc16(buf, offset) != 0xB001)
00633     {
00634         return CrcError;
00635     }
00636 
00637     // check the second CRC16
00638     if (calculateCrc16(buf + offset, cnt - offset) != 0xB001)
00639     {
00640         return CrcError;
00641     }
00642 
00643     // Copy to output
00644     std::memcpy(data.data(), &buf[offset], data.size());
00645 
00646     return Success;
00647 }
00648 
00649 OneWireSlave::CmdResult DS28E15_22_25::loadSecret(bool lock)
00650 {
00651     uint8_t buf[256], cs;
00652     int cnt = 0;
00653     
00654     if (selectDevice() != OneWireMaster::Success)
00655     {
00656         return CommunicationError;
00657     }
00658 
00659     buf[cnt++] = LoadAndLockSecret;
00660     buf[cnt++] = (lock) ? 0xE0 : 0x00;  // lock flag 
00661 
00662     // Send command
00663     master().OWWriteBlock(&buf[0], 2);
00664 
00665     // Read CRC
00666     master().OWReadBlock(&buf[cnt], 2);
00667     cnt += 2;
00668 
00669     // check CRC16
00670     if (calculateCrc16(buf, cnt) != 0xB001)
00671     {
00672         return CrcError;
00673     }
00674 
00675     // send release and strong pull-up
00676     master().OWWriteBytePower(0xAA);
00677 
00678     // now wait for the secret programming.
00679     wait_ms(secretEepromWriteDelayMs());
00680 
00681     // disable strong pullup
00682     master().OWSetLevel(OneWireMaster::NormalLevel);
00683 
00684     // read the CS byte
00685     master().OWReadByte(cs);
00686 
00687     if (cs == 0xAA)
00688     {
00689         return Success;
00690     }
00691     // else
00692     return OperationFailure;
00693 }
00694 
00695 OneWireSlave::CmdResult DS28E15_22_25::readPage(unsigned int page, Page & rdbuf, bool continuing) const
00696 {
00697     uint8_t buf[256];
00698     int cnt = 0;
00699     int offset = 0;
00700 
00701     // check if not continuing a previous block write
00702     if (!continuing)
00703     {
00704         if (selectDevice() != OneWireMaster::Success)
00705         {
00706             return CommunicationError;
00707         }
00708         
00709         buf[cnt++] = ReadMemory;
00710         buf[cnt++] = page;   // address 
00711 
00712         // Send command
00713         master().OWWriteBlock(&buf[0], 2);
00714 
00715         // Read CRC
00716         master().OWReadBlock(&buf[cnt], 2);
00717         cnt += 2;
00718 
00719         offset = cnt;
00720     }
00721 
00722     // read data and CRC16
00723     master().OWReadBlock(&buf[cnt], (rdbuf.size() + 2));
00724     cnt += 34;
00725 
00726     // check the first CRC16
00727     if (!continuing)
00728     {
00729         if (calculateCrc16(buf, offset) != 0xB001)
00730         {
00731             return CrcError;
00732         }
00733     }
00734 
00735     // check the second CRC16
00736     if (calculateCrc16(buf + offset, cnt - offset) != 0xB001)
00737     {
00738         return CrcError;
00739     }
00740 
00741     // copy the data to the read buffer
00742     std::memcpy(rdbuf.data(), &buf[offset], rdbuf.size());
00743 
00744     return Success;
00745 }
00746 
00747 template <class T>
00748 OneWireSlave::CmdResult DS28E15_22_25::doWriteAuthSegmentMac(unsigned int pageNum, unsigned int segmentNum, const Segment & newData, const Mac & mac, bool continuing)
00749 {
00750     uint8_t buf[256], cs;
00751     int cnt, offset;
00752 
00753     cnt = 0;
00754     offset = 0;
00755 
00756     // check if not continuing a previous block write
00757     if (!continuing)
00758     {
00759         if (selectDevice() != OneWireMaster::Success)
00760         {
00761             return CommunicationError;
00762         }
00763         
00764         buf[cnt++] = AuthWriteMemory;
00765         buf[cnt++] = (segmentNum << 5) | pageNum;   // address 
00766 
00767         // Send command
00768         master().OWWriteBlock(&buf[0], 2);
00769 
00770         // Read CRC
00771         master().OWReadBlock(&buf[cnt], 2);
00772         cnt += 2;
00773 
00774         offset = cnt;
00775     }
00776 
00777     // add the data
00778     for (size_t i = 0; i < newData.size(); i++)
00779     {
00780         buf[cnt++] = newData[i];
00781     }
00782 
00783     // Send data
00784     master().OWWriteBlock(newData.data(), newData.size());
00785 
00786     // read first CRC byte
00787     master().OWReadByte(buf[cnt++]);
00788 
00789     // read the last CRC and enable power
00790     master().OWReadBytePower(buf[cnt++]);
00791 
00792     // now wait for the MAC computation.
00793     wait_ms(shaComputationDelayMs);
00794 
00795     // disable strong pullup
00796     master().OWSetLevel(OneWireMaster::NormalLevel);
00797 
00798     // check the first CRC16
00799     if (!continuing)
00800     {
00801         if (calculateCrc16(buf, offset) != 0xB001)
00802         {
00803             return CrcError;
00804         }
00805     }
00806 
00807     // check the second CRC16
00808     uint16_t CRC16 = 0;
00809 
00810     // DS28E25/DS28E22, crc gets calculagted with CS byte 
00811     if (is_same<T, DS28E22>::value || is_same<T, DS28E25>::value)
00812     {
00813         if (continuing)
00814         {
00815             CRC16 = calculateCrc16(CRC16, 0xAA);
00816         }
00817     }
00818 
00819     CRC16 = calculateCrc16(buf + offset, cnt - offset, CRC16);
00820 
00821     if (CRC16 != 0xB001)
00822     {
00823         return CrcError;
00824     }
00825 
00826     // transmit MAC as a block
00827     master().OWWriteBlock(mac.data(), mac.size());
00828 
00829     // calculate CRC on MAC
00830     CRC16 = calculateCrc16(mac.data(), mac.size());
00831 
00832     // append read of CRC16 and CS byte
00833     master().OWReadBlock(&buf[0], 3);
00834     cnt = 3;
00835 
00836     // ckeck CRC16
00837     CRC16 = calculateCrc16(buf, cnt - 1, CRC16);
00838 
00839     if (CRC16 != 0xB001)
00840     {
00841         return CrcError;
00842     }
00843 
00844     // check CS
00845     if (buf[cnt - 1] != 0xAA)
00846     {
00847         return OperationFailure;
00848     }
00849 
00850     // send release and strong pull-up
00851     master().OWWriteBytePower(0xAA);
00852 
00853     // now wait for the programming.
00854     wait_ms(eepromWriteDelayMs);
00855 
00856     // disable strong pullup
00857     master().OWSetLevel(OneWireMaster::NormalLevel);
00858 
00859     // read the CS byte
00860     master().OWReadByte(cs);
00861 
00862     if (cs == 0xAA)
00863     {
00864         return Success;
00865     }
00866     // else
00867     return OperationFailure;
00868 }
00869 
00870 ISha256MacCoproc::CmdResult DS28E15_22_25::computeSegmentWriteMac(const ISha256MacCoproc & MacCoproc, unsigned int pageNum, unsigned int segmentNum, const Segment  & newData, const Segment  & oldData, const RomId & romId, const ManId  & manId, Mac & mac)
00871 {
00872     ISha256MacCoproc::WriteMacData MT;
00873 
00874     // insert ROM number
00875     std::memcpy(&MT[0], romId.buffer.data(), romId.buffer.size());
00876 
00877     MT[11] = segmentNum;
00878     MT[10] = pageNum;
00879     MT[9] = manId[0];
00880     MT[8] = manId[1];
00881 
00882     // insert old data
00883     std::memcpy(&MT[12], oldData.data(), oldData.size());
00884 
00885     // insert new data
00886     std::memcpy(&MT[16], newData.data(), newData.size());
00887 
00888     return MacCoproc.computeWriteMac(MT, mac);
00889 }
00890 
00891 ISha256MacCoproc::CmdResult DS28E15_22_25::computeProtectionWriteMac(const ISha256MacCoproc & MacCoproc, const BlockProtection & newProtection, const BlockProtection & oldProtection, const RomId & romId, const ManId  & manId, Mac & mac)
00892 {
00893     ISha256MacCoproc::WriteMacData MT;
00894 
00895     // insert ROM number
00896     std::memcpy(MT.data(), romId.buffer.data(), romId.buffer.size());
00897 
00898     // instert block and page
00899     MT[11] = 0;
00900     MT[10] = newProtection.blockNum();
00901 
00902     MT[9] = manId[0];
00903     MT[8] = manId[1];
00904 
00905     // old data
00906     MT[12] = oldProtection.authProtection() ? 0x01 : 0x00;
00907     MT[13] = oldProtection.eepromEmulation() ? 0x01 : 0x00;
00908     MT[14] = oldProtection.writeProtection() ? 0x01 : 0x00;
00909     MT[15] = oldProtection.readProtection() ? 0x01 : 0x00;
00910     // new data
00911     MT[16] = newProtection.authProtection() ? 0x01 : 0x00;
00912     MT[17] = newProtection.eepromEmulation() ? 0x01 : 0x00;
00913     MT[18] = newProtection.writeProtection() ? 0x01 : 0x00;
00914     MT[19] = newProtection.readProtection() ? 0x01 : 0x00;
00915 
00916     // compute the mac
00917     return MacCoproc.computeWriteMac(MT, mac);
00918 }
00919 
00920 template <class T>
00921 OneWireSlave::CmdResult DS28E15_22_25::doWriteAuthSegment(const ISha256MacCoproc & MacCoproc, unsigned int pageNum, unsigned int segmentNum, const Segment & newData, const Segment & oldData, bool continuing)
00922 {
00923     uint8_t buf[256], cs;
00924     int cnt, offset;
00925 
00926     cnt = 0;
00927     offset = 0;
00928 
00929     // check if not continuing a previous block write
00930     if (!continuing)
00931     {
00932         if (selectDevice() != OneWireMaster::Success)
00933         {
00934             return CommunicationError;
00935         }
00936         
00937         buf[cnt++] = AuthWriteMemory;
00938         buf[cnt++] = (segmentNum << 5) | pageNum;   // address 
00939 
00940         // Send command
00941         master().OWWriteBlock(&buf[0], 2);
00942 
00943         // Read CRC
00944         master().OWReadBlock(&buf[cnt], 2);
00945         cnt += 2;
00946 
00947         offset = cnt;
00948     }
00949 
00950     // add the data
00951     for (size_t i = 0; i < newData.size(); i++)
00952     {
00953         buf[cnt++] = newData[i];
00954     }
00955 
00956     // Send data
00957     master().OWWriteBlock(newData.data(), newData.size());
00958 
00959     // read first CRC byte
00960     master().OWReadByte(buf[cnt++]);
00961 
00962     // read the last CRC and enable power
00963     master().OWReadBytePower(buf[cnt++]);
00964 
00965     // now wait for the MAC computation.
00966     wait_ms(shaComputationDelayMs);
00967 
00968     // disable strong pullup
00969     master().OWSetLevel(OneWireMaster::NormalLevel);
00970 
00971     // check the first CRC16
00972     if (!continuing)
00973     {
00974         if (calculateCrc16(buf, offset) != 0xB001)
00975         {
00976             return CrcError;
00977         }
00978     }
00979 
00980     // check the second CRC16
00981     uint16_t CRC16 = 0;
00982 
00983     // DS28E25/DS28E22, crc gets calculated with CS byte
00984     if (is_same<T, DS28E22>::value || is_same<T, DS28E25>::value)
00985     {
00986         if (continuing)
00987             CRC16 = calculateCrc16(CRC16, 0xAA);
00988     }
00989 
00990     CRC16 = calculateCrc16(buf + offset, cnt - offset, CRC16);
00991 
00992     if (CRC16 != 0xB001)
00993     {
00994         return CrcError;
00995     }
00996 
00997     // compute the mac
00998     ISha256MacCoproc::CmdResult result;
00999     Mac mac;
01000     result = computeSegmentWriteMac(MacCoproc, pageNum, segmentNum, newData, oldData, romId (), manId (), mac);
01001     if (result != ISha256MacCoproc::Success)
01002     {
01003         return OperationFailure;
01004     }
01005 
01006     // transmit MAC as a block
01007     master().OWWriteBlock(mac.data(), mac.size());
01008 
01009     // calculate CRC on MAC
01010     CRC16 = calculateCrc16(mac.data(), mac.size());
01011 
01012     // append read of CRC16 and CS byte
01013     master().OWReadBlock(&buf[0], 3);
01014     cnt = 3;
01015 
01016     // ckeck CRC16
01017     CRC16 = calculateCrc16(buf, cnt - 1, CRC16);
01018 
01019     if (CRC16 != 0xB001)
01020     {
01021         return CrcError;
01022     }
01023 
01024     // check CS
01025     if (buf[cnt - 1] != 0xAA)
01026     {
01027         return OperationFailure;
01028     }
01029 
01030     // send release and strong pull-up
01031     master().OWWriteBytePower(0xAA);
01032 
01033     // now wait for the programming.
01034     wait_ms(eepromWriteDelayMs);
01035 
01036     // disable strong pullup
01037     master().OWSetLevel(OneWireMaster::NormalLevel);
01038 
01039     // read the CS byte
01040     master().OWReadByte(cs);
01041 
01042     if (cs == 0xAA)
01043     {
01044         return Success;
01045     }
01046     // else
01047     return OperationFailure;
01048 }
01049 
01050 OneWireSlave::CmdResult DS28E15_22_25::readSegment(unsigned int page, unsigned int segment, Segment  & data, bool continuing) const
01051 {
01052     OneWireMaster::CmdResult result = OneWireMaster::OperationFailure;
01053     uint8_t buf[2];
01054 
01055     if (!continuing)
01056     {
01057         if (selectDevice() != OneWireMaster::Success)
01058         {
01059             return CommunicationError;
01060         }
01061         
01062         buf[0] = ReadMemory;
01063         buf[1] = (segment << 5) | page;
01064 
01065         // Transmit command
01066         master().OWWriteBlock(buf, 2);
01067 
01068         // Receive CRC
01069         result = master().OWReadBlock(buf, 2);
01070     }
01071     else if (segment == 0)
01072     {
01073         // Receive CRC from previous read
01074         result = master().OWReadBlock(buf, 2);
01075     }
01076 
01077     // Receive data
01078     if (result == OneWireMaster::Success)
01079     {
01080         result = master().OWReadBlock(data.data(), data.size());
01081     }
01082 
01083     return (result == OneWireMaster::Success ? OneWireSlave::Success : OneWireSlave::CommunicationError);
01084 }
01085 
01086 OneWireSlave::CmdResult DS28E15_22_25::writeSegment(unsigned int page, unsigned int block, const Segment  & data, bool continuing)
01087 {
01088     uint8_t buf[256], cs;
01089     int cnt = 0;
01090     int offset = 0;
01091 
01092     cnt = 0;
01093     offset = 0;
01094 
01095     // check if not continuing a previous block write
01096     if (!continuing)
01097     {
01098         if (selectDevice() != OneWireMaster::Success)
01099         {
01100             return CommunicationError;
01101         }
01102         
01103         buf[cnt++] = WriteMemory;
01104         buf[cnt++] = (block << 5) | page;   // address 
01105 
01106         // Send command 
01107         master().OWWriteBlock(&buf[0], 2);
01108 
01109         // Read CRC
01110         master().OWReadBlock(&buf[cnt], 2);
01111         cnt += 2;
01112 
01113         offset = cnt;
01114     }
01115 
01116     // add the data
01117     for (size_t i = 0; i < data.size(); i++)
01118     {
01119         buf[cnt++] = data[i];
01120     }
01121 
01122     // Send data
01123     master().OWWriteBlock(data.data(), data.size());
01124 
01125     // Read CRC
01126     master().OWReadBlock(&buf[cnt], 2);
01127     cnt += 2;
01128 
01129     // check the first CRC16
01130     if (!continuing)
01131     {
01132         if (calculateCrc16(buf, offset) != 0xB001)
01133         {
01134             return CrcError;
01135         }
01136     }
01137 
01138     // check the second CRC16
01139     if (calculateCrc16(buf + offset, cnt - offset) != 0xB001)
01140     {
01141         return CrcError;
01142     }
01143 
01144     // send release and strong pull-up
01145     master().OWWriteBytePower(0xAA);
01146 
01147     // now wait for the programming.
01148     wait_ms(eepromWriteDelayMs);
01149 
01150     // disable strong pullup
01151     master().OWSetLevel(OneWireMaster::NormalLevel);
01152 
01153     // read the CS byte
01154     master().OWReadByte(cs);
01155 
01156     if (cs == 0xAA)
01157     {
01158         return Success;
01159     }
01160     // else
01161     return OperationFailure;
01162 }
01163 
01164 ISha256MacCoproc::CmdResult DS28E15_22_25::computeNextSecret(ISha256MacCoproc & MacCoproc, const Page & bindingPage, unsigned int bindingPageNum, const Scratchpad & partialSecret, const RomId & romId, const ManId  & manId)
01165 {
01166     ISha256MacCoproc::SlaveSecretData slaveSecretData;
01167 
01168     // insert ROM number
01169     std::memcpy(slaveSecretData.data(), romId.buffer.data(), romId.buffer.size());
01170 
01171     slaveSecretData[11] = 0x00;
01172     slaveSecretData[10] = bindingPageNum;
01173     slaveSecretData[9] = manId[0];
01174     slaveSecretData[8] = manId[1];
01175 
01176     return MacCoproc.computeSlaveSecret(ISha256MacCoproc::DevicePage(bindingPage), partialSecret, slaveSecretData);
01177 }
01178 
01179 template <class T, size_t N>
01180 OneWireSlave::CmdResult DS28E15_22_25::doReadAllBlockProtection(array<BlockProtection, N> & protection) const
01181 {
01182     uint8_t buf[N];
01183     CmdResult result = readStatus<T>(false, true, 0, buf);
01184     if (result == Success)
01185     {
01186         for (size_t i = 0; i < N; i++)
01187         {
01188             protection[i].setStatusByte(buf[i]);
01189         }
01190     }
01191     return result;
01192 }
01193 
01194 OneWireSlave::CmdResult DS28E15::writeScratchpad(const Scratchpad & data) const
01195 {
01196     return doWriteScratchpad<DS28E15>(data);
01197 }
01198 
01199 OneWireSlave::CmdResult DS28E15::readScratchpad(Scratchpad & data) const
01200 {
01201     return doReadScratchpad<DS28E15>(data);
01202 }
01203 
01204 OneWireSlave::CmdResult DS28E15::readBlockProtection(unsigned int blockNum, BlockProtection & protection) const
01205 {
01206     return doReadBlockProtection<DS28E15>(blockNum, protection);
01207 }
01208 
01209 OneWireSlave::CmdResult DS28E15::readPersonality(Personality & personality) const
01210 {
01211     return doReadPersonality<DS28E15>(personality);
01212 }
01213 
01214 OneWireSlave::CmdResult DS28E15::writeAuthSegment(const ISha256MacCoproc & MacCoproc, unsigned int pageNum, unsigned int segmentNum, const Segment  & newData, const Segment  & oldData, bool continuing)
01215 {
01216     return doWriteAuthSegment<DS28E15>(MacCoproc, pageNum, segmentNum, newData, oldData, continuing);
01217 }
01218 
01219 OneWireSlave::CmdResult DS28E15::writeAuthSegmentMac(unsigned int pageNum, unsigned int segmentNum, const Segment  & newData, const Mac & mac, bool continuing)
01220 {
01221     return doWriteAuthSegmentMac<DS28E15>(pageNum, segmentNum, newData, mac, continuing);
01222 }
01223 
01224 OneWireSlave::CmdResult DS28E15::readAllBlockProtection(array<BlockProtection, protectionBlocks> & protection) const
01225 {
01226     return doReadAllBlockProtection<DS28E15>(protection);
01227 }
01228 
01229 OneWireSlave::CmdResult DS28E22::writeScratchpad(const Scratchpad & data) const
01230 {
01231     return doWriteScratchpad<DS28E22>(data);
01232 }
01233 
01234 OneWireSlave::CmdResult DS28E22::readScratchpad(Scratchpad & data) const
01235 {
01236     return doReadScratchpad<DS28E22>(data);
01237 }
01238 
01239 OneWireSlave::CmdResult DS28E22::readBlockProtection(unsigned int blockNum, BlockProtection & protection) const
01240 {
01241     return doReadBlockProtection<DS28E22>(blockNum, protection);
01242 }
01243 
01244 OneWireSlave::CmdResult DS28E22::readPersonality(Personality & personality) const
01245 {
01246     return doReadPersonality<DS28E22>(personality);
01247 }
01248 
01249 OneWireSlave::CmdResult DS28E22::writeAuthSegment(const ISha256MacCoproc & MacCoproc, unsigned int pageNum, unsigned int segmentNum, const Segment  & newData, const Segment  & oldData, bool continuing)
01250 {
01251     return doWriteAuthSegment<DS28E22>(MacCoproc, pageNum, segmentNum, newData, oldData, continuing);
01252 }
01253 
01254 OneWireSlave::CmdResult DS28E22::writeAuthSegmentMac(unsigned int pageNum, unsigned int segmentNum, const Segment  & newData, const Mac & mac, bool continuing)
01255 {
01256     return doWriteAuthSegmentMac<DS28E22>(pageNum, segmentNum, newData, mac, continuing);
01257 }
01258 
01259 OneWireSlave::CmdResult DS28E22::readAllBlockProtection(array<BlockProtection, protectionBlocks> & protection) const
01260 {
01261     return doReadAllBlockProtection<DS28E22>(protection);
01262 }
01263 
01264 OneWireSlave::CmdResult DS28E25::writeScratchpad(const Scratchpad & data) const
01265 {
01266     return doWriteScratchpad<DS28E25>(data);
01267 }
01268 
01269 OneWireSlave::CmdResult DS28E25::readScratchpad(Scratchpad & data) const
01270 {
01271     return doReadScratchpad<DS28E25>(data);
01272 }
01273 
01274 OneWireSlave::CmdResult DS28E25::readBlockProtection(unsigned int blockNum, BlockProtection & protection) const
01275 {
01276     return doReadBlockProtection<DS28E25>(blockNum, protection);
01277 }
01278 
01279 OneWireSlave::CmdResult DS28E25::readPersonality(Personality & personality) const
01280 {
01281     return doReadPersonality<DS28E25>(personality);
01282 }
01283 
01284 OneWireSlave::CmdResult DS28E25::writeAuthSegment(const ISha256MacCoproc & MacCoproc, unsigned int pageNum, unsigned int segmentNum, const Segment  & newData, const Segment  & oldData, bool continuing)
01285 {
01286     return doWriteAuthSegment<DS28E25>(MacCoproc, pageNum, segmentNum, newData, oldData, continuing);
01287 }
01288 
01289 OneWireSlave::CmdResult DS28E25::writeAuthSegmentMac(unsigned int pageNum, unsigned int segmentNum, const Segment  & newData, const Mac & mac, bool continuing)
01290 {
01291     return doWriteAuthSegmentMac<DS28E25>(pageNum, segmentNum, newData, mac, continuing);
01292 }
01293 
01294 OneWireSlave::CmdResult DS28E25::readAllBlockProtection(array<BlockProtection, protectionBlocks> & protection) const
01295 {
01296     return doReadAllBlockProtection<DS28E25>(protection);
01297 }