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
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 }
Generated on Tue Jul 12 2022 15:46:21 by 1.7.2